10 * isa.c implements a "classical" port-scanning method of ISA device
11 * detection. The driver must provide a list of probe addresses
12 * (probe_addrs), together with a function (probe_addr) that can be
13 * used to test for the physical presence of a device at any given
16 * Note that this should probably be considered the "last resort" for
17 * device probing. If the card supports ISAPnP or EISA, use that
18 * instead. Some cards (e.g. the 3c509) implement a proprietary
19 * ISAPnP-like mechanism.
21 * The ISA probe address list can be overridden by config.h; if the
22 * user specifies ISA_PROBE_ADDRS then that list will be used first.
23 * (If ISA_PROBE_ONLY is defined, the driver's own list will never be
28 * User-supplied probe address list
31 static isa_probe_addr_t isa_extra_probe_addrs[] = {
32 #ifdef ISA_PROBE_ADDRS
36 #define ISA_EXTRA_PROBE_ADDR_COUNT \
37 ( sizeof ( isa_extra_probe_addrs ) / sizeof ( isa_extra_probe_addrs[0] ) )
39 #define ISA_IOIDX_MIN( driver ) ( -ISA_EXTRA_PROBE_ADDR_COUNT )
41 #define ISA_IOIDX_MAX( driver ) ( -1 )
43 #define ISA_IOIDX_MAX( driver ) ( (int) (driver)->addr_count - 1 )
46 #define ISA_IOADDR( driver, ioidx ) \
48 isa_extra_probe_addrs[ (ioidx) + ISA_EXTRA_PROBE_ADDR_COUNT ] : \
49 (driver)->probe_addrs[(ioidx)] )
51 static struct isa_driver isa_drivers[0]
52 __table_start ( struct isa_driver, isa_driver );
53 static struct isa_driver isa_drivers_end[0]
54 __table_end ( struct isa_driver, isa_driver );
56 static void isabus_remove ( struct root_device *rootdev );
62 * @ret rc Return status code
64 static int isa_probe ( struct isa_device *isa ) {
67 DBG ( "Trying ISA driver %s at I/O %04x\n",
68 isa->driver->name, isa->ioaddr );
70 if ( ( rc = isa->driver->probe ( isa ) ) != 0 ) {
71 DBG ( "...probe failed\n" );
75 DBG ( "...device found\n" );
80 * Remove an ISA device
84 static void isa_remove ( struct isa_device *isa ) {
85 isa->driver->remove ( isa );
86 DBG ( "Removed ISA%04x\n", isa->ioaddr );
92 * @v rootdev ISA bus root device
94 * Scans the ISA bus for devices and registers all devices it can
97 static int isabus_probe ( struct root_device *rootdev ) {
98 struct isa_device *isa = NULL;
99 struct isa_driver *driver;
103 for ( driver = isa_drivers ; driver < isa_drivers_end ; driver++ ) {
104 for ( ioidx = ISA_IOIDX_MIN ( driver ) ;
105 ioidx <= ISA_IOIDX_MAX ( driver ) ; ioidx++ ) {
106 /* Allocate struct isa_device */
108 isa = malloc ( sizeof ( *isa ) );
113 memset ( isa, 0, sizeof ( *isa ) );
114 isa->driver = driver;
115 isa->ioaddr = ISA_IOADDR ( driver, ioidx );
117 /* Add to device hierarchy */
118 snprintf ( isa->dev.name, sizeof ( isa->dev.name ),
119 "ISA%04x", isa->ioaddr );
120 isa->dev.desc.bus_type = BUS_TYPE_ISA;
121 isa->dev.desc.vendor = driver->vendor_id;
122 isa->dev.desc.device = driver->prod_id;
123 isa->dev.parent = &rootdev->dev;
124 list_add ( &isa->dev.siblings,
125 &rootdev->dev.children );
126 INIT_LIST_HEAD ( &isa->dev.children );
128 /* Try probing at this I/O address */
129 if ( isa_probe ( isa ) == 0 ) {
130 /* isadev registered, we can drop our ref */
133 /* Not registered; re-use struct */
134 list_del ( &isa->dev.siblings );
144 isabus_remove ( rootdev );
149 * Remove ISA root bus
151 * @v rootdev ISA bus root device
153 static void isabus_remove ( struct root_device *rootdev ) {
154 struct isa_device *isa;
155 struct isa_device *tmp;
157 list_for_each_entry_safe ( isa, tmp, &rootdev->dev.children,
160 list_del ( &isa->dev.siblings );
165 /** ISA bus root device driver */
166 static struct root_driver isa_root_driver = {
167 .probe = isabus_probe,
168 .remove = isabus_remove,
171 /** ISA bus root device */
172 struct root_device isa_root_device __root_device = {
173 .dev = { .name = "ISA" },
174 .driver = &isa_root_driver,