drivers/comedi/drivers/ni_atmio.c

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

File Facts

System
Linux kernel
Corpus path
drivers/comedi/drivers/ni_atmio.c
Extension
.c
Size
9387 bytes
Lines
370
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

if (pnp_activate_dev(isapnp_dev) < 0) {
			pnp_device_detach(isapnp_dev);
			return -EAGAIN;
		}

		if (!pnp_port_valid(isapnp_dev, 0) ||
		    !pnp_irq_valid(isapnp_dev, 0)) {
			pnp_device_detach(isapnp_dev);
			return -ENOMEM;
		}
		break;
	}
	if (i == ARRAY_SIZE(ni_boards))
		return -ENODEV;
	*dev = isapnp_dev;
	return 0;
}

static const struct ni_board_struct *ni_atmio_probe(struct comedi_device *dev)
{
	int device_id = ni_read_eeprom(dev, 511);
	int i;

	for (i = 0; i < ARRAY_SIZE(ni_boards); i++) {
		const struct ni_board_struct *board = &ni_boards[i];

		if (board->device_id == device_id)
			return board;
	}
	if (device_id == 255)
		dev_err(dev->class_dev, "can't find board\n");
	else if (device_id == 0)
		dev_err(dev->class_dev,
			"EEPROM read error (?) or device not found\n");
	else
		dev_err(dev->class_dev,
			"unknown device ID %d -- contact author\n", device_id);

	return NULL;
}

static int ni_atmio_attach(struct comedi_device *dev,
			   struct comedi_devconfig *it)
{
	const struct ni_board_struct *board;
	struct pnp_dev *isapnp_dev;
	int ret;
	unsigned long iobase;
	unsigned int irq;

	ret = ni_alloc_private(dev);
	if (ret)
		return ret;

	iobase = it->options[0];
	irq = it->options[1];
	isapnp_dev = NULL;
	if (iobase == 0) {
		ret = ni_isapnp_find_board(&isapnp_dev);
		if (ret < 0)
			return ret;

		iobase = pnp_port_start(isapnp_dev, 0);
		irq = pnp_irq(isapnp_dev, 0);
		comedi_set_hw_dev(dev, &isapnp_dev->dev);
	}

	ret = comedi_check_request_region(dev, iobase, 0x20,
					  0x20, 0xffff, 32);
	if (ret)
		return ret;

	board = ni_atmio_probe(dev);
	if (!board)
		return -ENODEV;
	dev->board_ptr = board;
	dev->board_name = board->name;

	/* irq stuff */

	if (irq != 0) {
		if (irq > 15 || ni_irqpin[irq] == -1)
			return -EINVAL;
		ret = request_irq(irq, ni_E_interrupt, 0,
				  dev->board_name, dev);
		if (ret < 0)
			return -EINVAL;
		dev->irq = irq;
	}

Annotation

Implementation Notes