drivers/parport/parport_pc.c

Source file repositories/reference/linux-study-clean/drivers/parport/parport_pc.c

File Facts

System
Linux kernel
Corpus path
drivers/parport/parport_pc.c
Extension
.c
Size
90063 bytes
Lines
3409
Domain
Driver Families
Bucket
drivers/parport
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static struct pci_driver parport_pc_pci_driver = {
	.name		= "parport_pc",
	.id_table	= parport_pc_pci_tbl,
	.probe		= parport_pc_pci_probe,
	.remove		= parport_pc_pci_remove,
};

static int __init parport_pc_init_superio(int autoirq, int autodma)
{
	const struct pci_device_id *id;
	struct pci_dev *pdev = NULL;
	int ret = 0;

	for_each_pci_dev(pdev) {
		id = pci_match_id(parport_pc_pci_tbl, pdev);
		if (id == NULL || id->driver_data >= last_sio)
			continue;

		if (parport_pc_superio_info[id->driver_data].probe(
			pdev, autoirq, autodma,
			parport_pc_superio_info[id->driver_data].via)) {
			ret++;
		}
	}

	return ret; /* number of devices found */
}
#else
static struct pci_driver parport_pc_pci_driver;
static int __init parport_pc_init_superio(int autoirq, int autodma)
{
	return 0;
}
#endif /* CONFIG_PCI */

#ifdef CONFIG_PNP

static const struct pnp_device_id parport_pc_pnp_tbl[] = {
	/* Standard LPT Printer Port */
	{.id = "PNP0400", .driver_data = 0},
	/* ECP Printer Port */
	{.id = "PNP0401", .driver_data = 0},
	{ }
};

MODULE_DEVICE_TABLE(pnp, parport_pc_pnp_tbl);

static int parport_pc_pnp_probe(struct pnp_dev *dev,
						const struct pnp_device_id *id)
{
	struct parport *pdata;
	unsigned long io_lo, io_hi;
	int dma, irq;

	if (pnp_port_valid(dev, 0) &&
		!(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) {
		io_lo = pnp_port_start(dev, 0);
	} else
		return -EINVAL;

	if (pnp_port_valid(dev, 1) &&
		!(pnp_port_flags(dev, 1) & IORESOURCE_DISABLED)) {
		io_hi = pnp_port_start(dev, 1);
	} else
		io_hi = 0;

	if (pnp_irq_valid(dev, 0) &&
		!(pnp_irq_flags(dev, 0) & IORESOURCE_DISABLED)) {
		irq = pnp_irq(dev, 0);
	} else
		irq = PARPORT_IRQ_NONE;

	if (pnp_dma_valid(dev, 0) &&
		!(pnp_dma_flags(dev, 0) & IORESOURCE_DISABLED)) {
		dma = pnp_dma(dev, 0);
	} else
		dma = PARPORT_DMA_NONE;

	dev_info(&dev->dev, "reported by %s\n", dev->protocol->name);
	pdata = parport_pc_probe_port(io_lo, io_hi, irq, dma, &dev->dev, 0);
	if (pdata == NULL)
		return -ENODEV;

	pnp_set_drvdata(dev, pdata);
	return 0;
}

static void parport_pc_pnp_remove(struct pnp_dev *dev)
{
	struct parport *pdata = (struct parport *)pnp_get_drvdata(dev);

Annotation

Implementation Notes