drivers/comedi/drivers/quatech_daqp_cs.c

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

File Facts

System
Linux kernel
Corpus path
drivers/comedi/drivers/quatech_daqp_cs.c
Extension
.c
Size
24763 bytes
Lines
842
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 daqp_private {
	unsigned int pacer_div;
	int stop;
};

static const struct comedi_lrange range_daqp_ai = {
	4, {
		BIP_RANGE(10),
		BIP_RANGE(5),
		BIP_RANGE(2.5),
		BIP_RANGE(1.25)
	}
};

static int daqp_clear_events(struct comedi_device *dev, int loops)
{
	unsigned int status;

	/*
	 * Reset any pending interrupts (my card has a tendency to require
	 * multiple reads on the status register to achieve this).
	 */
	while (--loops) {
		status = inb(dev->iobase + DAQP_STATUS_REG);
		if ((status & DAQP_STATUS_EVENTS) == 0)
			return 0;
	}
	dev_err(dev->class_dev, "couldn't clear events in status register\n");
	return -EBUSY;
}

static int daqp_ai_cancel(struct comedi_device *dev,
			  struct comedi_subdevice *s)
{
	struct daqp_private *devpriv = dev->private;

	if (devpriv->stop)
		return -EIO;

	/*
	 * Stop any conversions, disable interrupts, and clear
	 * the status event flags.
	 */
	outb(DAQP_CMD_STOP, dev->iobase + DAQP_CMD_REG);
	outb(0, dev->iobase + DAQP_CTRL_REG);
	inb(dev->iobase + DAQP_STATUS_REG);

	return 0;
}

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

	/*
	 * Get a two's complement sample from the FIFO and
	 * return the munged offset binary value.
	 */
	val = inb(dev->iobase + DAQP_AI_FIFO_REG);
	val |= inb(dev->iobase + DAQP_AI_FIFO_REG) << 8;
	return comedi_offset_munge(s, val);
}

static irqreturn_t daqp_interrupt(int irq, void *dev_id)
{
	struct comedi_device *dev = dev_id;
	struct comedi_subdevice *s = dev->read_subdev;
	struct comedi_cmd *cmd = &s->async->cmd;
	int loop_limit = 10000;
	int status;

	if (!dev->attached)
		return IRQ_NONE;

	status = inb(dev->iobase + DAQP_STATUS_REG);
	if (!(status & DAQP_STATUS_EVENTS))
		return IRQ_NONE;

	while (!(status & DAQP_STATUS_FIFO_EMPTY)) {
		unsigned short data;

		if (status & DAQP_STATUS_DATA_LOST) {
			s->async->events |= COMEDI_CB_OVERFLOW;
			dev_warn(dev->class_dev, "data lost\n");
			break;
		}

		data = daqp_ai_get_sample(dev, s);
		comedi_buf_write_samples(s, &data, 1);

Annotation

Implementation Notes