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.
- 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.
- Defines an operation table; this is where Linux turns generic core objects into subsystem-specific behavior.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/module.hlinux/parport.hlinux/delay.hlinux/slab.hlinux/sched/signal.hasm/current.hlinux/uaccess.h
Detected Declarations
function add_devfunction daisy_drv_probefunction parport_daisy_initfunction parport_daisy_finifunction parport_register_devicefunction parport_openfunction cpp_daisyfunction cpp_muxfunction parport_daisy_deselect_allfunction parport_daisy_selectfunction mux_presentfunction num_mux_portsfunction select_portfunction assign_addrs
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
- Immediate include surface: `linux/module.h`, `linux/parport.h`, `linux/delay.h`, `linux/slab.h`, `linux/sched/signal.h`, `asm/current.h`, `linux/uaccess.h`.
- Detected declarations: `function add_dev`, `function daisy_drv_probe`, `function parport_daisy_init`, `function parport_daisy_fini`, `function parport_register_device`, `function parport_open`, `function cpp_daisy`, `function cpp_mux`, `function parport_daisy_deselect_all`, `function parport_daisy_select`.
- Atlas domain: Driver Families / drivers/parport.
- Implementation status: pattern implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.