/* 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; staticconstchar *th[] = { /*0*/"th", "st", "nd", "rd", "th" }; int num_ports; int i; int last_try = 0;
if (!daisy_init_done) { /* *flagshouldbemarkedtruefirstas *parport_register_driver()mighttrytoloadthelow *leveldriverwhichwillleadtoannouncingnewports *andwhichwillagaincomebackhereat *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 foreverbecauseofthe'port->muxport<0'
test above. */
parport_daisy_init(extra);
}
}
/* 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) { if (parport_device_id(numdevs - 1, deviceid, 1024) > 2)
detected++;
kfree(deviceid);
}
if (!detected && !last_try) { /* No devices were detected. Perhaps they are in some funnystate;let'strytoresetthemandseeif
they wake up. */
parport_daisy_fini(port);
parport_write_control(port, PARPORT_CONTROL_SELECT);
udelay(50);
parport_write_control(port,
PARPORT_CONTROL_SELECT |
PARPORT_CONTROL_INIT);
udelay(50);
last_try = 1; goto again;
}
return detected;
}
/* Forget about devices on a physical port. */ void parport_daisy_fini(struct parport *port)
{ struct daisydev **p;
spin_lock(&topology_lock);
p = &topology; while (*p) { struct daisydev *dev = *p; if (dev->port != port) {
p = &dev->next; continue;
}
*p = dev->next;
kfree(dev);
}
/* Gaps in the numbering could be handled better. How should someoneenumeratethroughallIEEE1284.3devicesinthe
topology?. */ if (!topology) numdevs = 0;
spin_unlock(&topology_lock); return;
}
memset(&par_cb, 0, sizeof(par_cb));
spin_lock(&topology_lock); while (p && p->devnum != devnum)
p = p->next;
if (!p) {
spin_unlock(&topology_lock); return NULL;
}
daisy = p->daisy;
port = parport_get_port(p->port);
spin_unlock(&topology_lock);
dev = parport_register_dev_model(port, name, &par_cb, devnum);
parport_put_port(port); if (!dev) return NULL;
dev->daisy = daisy;
/* Check that there really is a device to select. */ if (daisy >= 0) { int selected;
parport_claim_or_block(dev);
selected = port->daisy;
parport_release(dev);
if (selected != daisy) { /* No corresponding device. */
parport_unregister_device(dev); return NULL;
}
}
int parport_daisy_select(struct parport *port, int daisy, int mode)
{ switch (mode)
{ // For these modes we should switch to EPP mode: case IEEE1284_MODE_EPP: case IEEE1284_MODE_EPPSL: case IEEE1284_MODE_EPPSWE: return !(cpp_daisy(port, 0x20 + daisy) &
PARPORT_STATUS_ERROR);
// For these modes we should switch to ECP mode: case IEEE1284_MODE_ECP: case IEEE1284_MODE_ECPRLE: case IEEE1284_MODE_ECPSWE: return !(cpp_daisy(port, 0xd0 + daisy) &
PARPORT_STATUS_ERROR);
// Nothing was told for BECP in Daisy chain specification. // May be it's wise to use ECP? case IEEE1284_MODE_BECP: // Others use compat mode case IEEE1284_MODE_NIBBLE: case IEEE1284_MODE_BYTE: case IEEE1284_MODE_COMPAT: default: return !(cpp_daisy(port, 0xe0 + daisy) &
PARPORT_STATUS_ERROR);
}
}
/* See if this device thought it was the last in the
* chain. */ if (!(s & PARPORT_STATUS_BUSY)) break;
/* We are seeing pass through status now. We see last_devfromnextdeviceoriflast_devdoesnot workstatuslinesfromsomenon-daisychain
device. */
s = parport_read_status(port);
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.15Bemerkung:
(vorverarbeitet am 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.