drivers/comedi/drivers/dt2811.c

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

File Facts

System
Linux kernel
Corpus path
drivers/comedi/drivers/dt2811.c
Extension
.c
Size
17812 bytes
Lines
646
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 dt2811_board {
	const char *name;
	unsigned int is_pgh:1;
};

static const struct dt2811_board dt2811_boards[] = {
	{
		.name		= "dt2811-pgh",
		.is_pgh		= 1,
	}, {
		.name		= "dt2811-pgl",
	},
};

struct dt2811_private {
	unsigned int ai_divisor;
};

static unsigned int dt2811_ai_read_sample(struct comedi_device *dev,
					  struct comedi_subdevice *s)
{
	unsigned int val;

	val = inb(dev->iobase + DT2811_ADDATA_LO_REG) |
	      (inb(dev->iobase + DT2811_ADDATA_HI_REG) << 8);

	return val & s->maxdata;
}

static irqreturn_t dt2811_interrupt(int irq, void *d)
{
	struct comedi_device *dev = d;
	struct comedi_subdevice *s = dev->read_subdev;
	struct comedi_async *async = s->async;
	struct comedi_cmd *cmd = &async->cmd;
	unsigned int status;

	if (!dev->attached)
		return IRQ_NONE;

	status = inb(dev->iobase + DT2811_ADCSR_REG);

	if (status & DT2811_ADCSR_ADERROR) {
		async->events |= COMEDI_CB_OVERFLOW;

		outb(status | DT2811_ADCSR_CLRERROR,
		     dev->iobase + DT2811_ADCSR_REG);
	}

	if (status & DT2811_ADCSR_ADDONE) {
		unsigned short val;

		val = dt2811_ai_read_sample(dev, s);
		comedi_buf_write_samples(s, &val, 1);
	}

	if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg)
		async->events |= COMEDI_CB_EOA;

	comedi_handle_events(dev, s);

	return IRQ_HANDLED;
}

static int dt2811_ai_cancel(struct comedi_device *dev,
			    struct comedi_subdevice *s)
{
	/*
	 * Mode 0
	 * Single conversion
	 *
	 * Loading a chanspec will trigger a conversion.
	 */
	outb(DT2811_ADCSR_ADMODE(0), dev->iobase + DT2811_ADCSR_REG);

	return 0;
}

static void dt2811_ai_set_chanspec(struct comedi_device *dev,
				   unsigned int chanspec)
{
	unsigned int chan = CR_CHAN(chanspec);
	unsigned int range = CR_RANGE(chanspec);

	outb(DT2811_ADGCR_CHAN(chan) | DT2811_ADGCR_GAIN(range),
	     dev->iobase + DT2811_ADGCR_REG);
}

static int dt2811_ai_cmd(struct comedi_device *dev,
			 struct comedi_subdevice *s)

Annotation

Implementation Notes