drivers/comedi/drivers/aio_aio12_8.c

Source file repositories/reference/linux-study-clean/drivers/comedi/drivers/aio_aio12_8.c

File Facts

System
Linux kernel
Corpus path
drivers/comedi/drivers/aio_aio12_8.c
Extension
.c
Size
7222 bytes
Lines
278
Domain
Driver Families
Bucket
drivers/comedi
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct aio12_8_boardtype {
	const char *name;
	unsigned int has_ai:1;
	unsigned int has_ao:1;
};

static const struct aio12_8_boardtype board_types[] = {
	{
		.name		= "aio_aio12_8",
		.has_ai		= 1,
		.has_ao		= 1,
	}, {
		.name		= "aio_ai12_8",
		.has_ai		= 1,
	}, {
		.name		= "aio_ao12_4",
		.has_ao		= 1,
	},
};

static int aio_aio12_8_ai_eoc(struct comedi_device *dev,
			      struct comedi_subdevice *s,
			      struct comedi_insn *insn,
			      unsigned long context)
{
	unsigned int status;

	status = inb(dev->iobase + AIO12_8_STATUS_REG);
	if (status & AIO12_8_STATUS_ADC_EOC)
		return 0;
	return -EBUSY;
}

static int aio_aio12_8_ai_read(struct comedi_device *dev,
			       struct comedi_subdevice *s,
			       struct comedi_insn *insn,
			       unsigned int *data)
{
	unsigned int chan = CR_CHAN(insn->chanspec);
	unsigned int range = CR_RANGE(insn->chanspec);
	unsigned int val;
	unsigned char control;
	int ret;
	int i;

	/*
	 * Setup the control byte for internal 2MHz clock, 3uS conversion,
	 * at the desired range of the requested channel.
	 */
	control = AIO12_8_ADC_MODE_NORMAL | AIO12_8_ADC_ACQ_3USEC |
		  AIO12_8_ADC_RANGE(range) | AIO12_8_ADC_CHAN(chan);

	/* Read status to clear EOC latch */
	inb(dev->iobase + AIO12_8_STATUS_REG);

	for (i = 0; i < insn->n; i++) {
		/*  Setup and start conversion */
		outb(control, dev->iobase + AIO12_8_ADC_REG);

		/*  Wait for conversion to complete */
		ret = comedi_timeout(dev, s, insn, aio_aio12_8_ai_eoc, 0);
		if (ret)
			return ret;

		val = inw(dev->iobase + AIO12_8_ADC_REG) & s->maxdata;

		/* munge bipolar 2's complement data to offset binary */
		if (comedi_range_is_bipolar(s, range))
			val = comedi_offset_munge(s, val);

		data[i] = val;
	}

	return insn->n;
}

static int aio_aio12_8_ao_insn_write(struct comedi_device *dev,
				     struct comedi_subdevice *s,
				     struct comedi_insn *insn,
				     unsigned int *data)
{
	unsigned int chan = CR_CHAN(insn->chanspec);
	unsigned int val = s->readback[chan];
	int i;

	/* enable DACs */
	outb(AIO12_8_DAC_ENABLE_REF_ENA, dev->iobase + AIO12_8_DAC_ENABLE_REG);

	for (i = 0; i < insn->n; i++) {
		val = data[i];

Annotation

Implementation Notes