drivers/parport/daisy.c

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

File Facts

System
Linux kernel
Corpus path
drivers/parport/daisy.c
Extension
.c
Size
13213 bytes
Lines
507
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

struct device_driver *drv = par_dev->dev.driver;

	if (strcmp(drv->name, "daisy_drv"))
		return -ENODEV;
	if (strcmp(par_dev->name, daisy_dev_name))
		return -ENODEV;

	return 0;
}

static struct parport_driver daisy_driver = {
	.name = "daisy_drv",
	.probe = daisy_drv_probe,
};

/* Discover the IEEE1284.3 topology on a port -- muxes and daisy chains.
 * Return value is number of devices actually detected. */
int parport_daisy_init(struct parport *port)
{
	int detected = 0;
	char *deviceid;
	static const char *th[] = { /*0*/"th", "st", "nd", "rd", "th" };
	int num_ports;
	int i;
	int last_try = 0;

	if (!daisy_init_done) {
		/*
		 * flag should be marked true first as
		 * parport_register_driver() might try to load the low
		 * level driver which will lead to announcing new ports
		 * and which will again come back here at
		 * parport_daisy_init()
		 */
		daisy_init_done = true;
		i = parport_register_driver(&daisy_driver);
		if (i) {
			pr_err("daisy registration failed\n");
			daisy_init_done = false;
			return i;
		}
	}

again:
	/* Because this is called before any other devices exist,
	 * we don't have to claim exclusive access.  */

	/* If mux present on normal port, need to create new
	 * parports for each extra port. */
	if (port->muxport < 0 && mux_present(port) &&
	    /* don't be fooled: a mux must have 2 or 4 ports. */
	    ((num_ports = num_mux_ports(port)) == 2 || num_ports == 4)) {
		/* Leave original as port zero. */
		port->muxport = 0;
		pr_info("%s: 1st (default) port of %d-way multiplexor\n",
			port->name, num_ports);
		for (i = 1; i < num_ports; i++) {
			/* Clone the port. */
			struct parport *extra = clone_parport(port, i);
			if (!extra) {
				if (signal_pending(current))
					break;

				schedule();
				continue;
			}

			pr_info("%s: %d%s port of %d-way multiplexor on %s\n",
				extra->name, i + 1, th[i + 1], num_ports,
				port->name);

			/* Analyse that port too.  We won't recurse
			   forever because of the 'port->muxport < 0'
			   test above. */
			parport_daisy_init(extra);
		}
	}

	if (port->muxport >= 0)
		select_port(port);

	parport_daisy_deselect_all(port);
	detected += assign_addrs(port);

	/* Count the potential legacy device at the end. */
	add_dev(numdevs++, port, -1);

	/* Find out the legacy device's IEEE 1284 device ID. */
	deviceid = kmalloc(1024, GFP_KERNEL);
	if (deviceid) {

Annotation

Implementation Notes