9 FILE_LICENCE ( GPL2_OR_LATER
);
12 * isa.c implements a "classical" port-scanning method of ISA device
13 * detection. The driver must provide a list of probe addresses
14 * (probe_addrs), together with a function (probe_addr) that can be
15 * used to test for the physical presence of a device at any given
18 * Note that this should probably be considered the "last resort" for
19 * device probing. If the card supports ISAPnP or EISA, use that
20 * instead. Some cards (e.g. the 3c509) implement a proprietary
21 * ISAPnP-like mechanism.
23 * The ISA probe address list can be overridden by config.h; if the
24 * user specifies ISA_PROBE_ADDRS then that list will be used first.
25 * (If ISA_PROBE_ONLY is defined, the driver's own list will never be
30 * User-supplied probe address list
33 static isa_probe_addr_t isa_extra_probe_addrs
[] = {
34 #ifdef ISA_PROBE_ADDRS
38 #define ISA_EXTRA_PROBE_ADDR_COUNT \
39 ( sizeof ( isa_extra_probe_addrs ) / sizeof ( isa_extra_probe_addrs[0] ) )
41 #define ISA_IOIDX_MIN( driver ) ( -ISA_EXTRA_PROBE_ADDR_COUNT )
43 #define ISA_IOIDX_MAX( driver ) ( -1 )
45 #define ISA_IOIDX_MAX( driver ) ( (int) (driver)->addr_count - 1 )
48 #define ISA_IOADDR( driver, ioidx ) \
50 isa_extra_probe_addrs[ (ioidx) + ISA_EXTRA_PROBE_ADDR_COUNT ] : \
51 (driver)->probe_addrs[(ioidx)] )
53 static void isabus_remove ( struct root_device
*rootdev
);
59 * @ret rc Return status code
61 static int isa_probe ( struct isa_device
*isa
) {
64 DBG ( "Trying ISA driver %s at I/O %04x\n",
65 isa
->driver
->name
, isa
->ioaddr
);
67 if ( ( rc
= isa
->driver
->probe ( isa
) ) != 0 ) {
68 DBG ( "...probe failed\n" );
72 DBG ( "...device found\n" );
77 * Remove an ISA device
81 static void isa_remove ( struct isa_device
*isa
) {
82 isa
->driver
->remove ( isa
);
83 DBG ( "Removed ISA%04x\n", isa
->ioaddr
);
89 * @v rootdev ISA bus root device
91 * Scans the ISA bus for devices and registers all devices it can
94 static int isabus_probe ( struct root_device
*rootdev
) {
95 struct isa_device
*isa
= NULL
;
96 struct isa_driver
*driver
;
100 for_each_table_entry ( driver
, ISA_DRIVERS
) {
101 for ( ioidx
= ISA_IOIDX_MIN ( driver
) ;
102 ioidx
<= ISA_IOIDX_MAX ( driver
) ; ioidx
++ ) {
103 /* Allocate struct isa_device */
105 isa
= malloc ( sizeof ( *isa
) );
110 memset ( isa
, 0, sizeof ( *isa
) );
111 isa
->driver
= driver
;
112 isa
->ioaddr
= ISA_IOADDR ( driver
, ioidx
);
114 /* Add to device hierarchy */
115 snprintf ( isa
->dev
.name
, sizeof ( isa
->dev
.name
),
116 "ISA%04x", isa
->ioaddr
);
117 isa
->dev
.desc
.bus_type
= BUS_TYPE_ISA
;
118 isa
->dev
.desc
.vendor
= driver
->vendor_id
;
119 isa
->dev
.desc
.device
= driver
->prod_id
;
120 isa
->dev
.parent
= &rootdev
->dev
;
121 list_add ( &isa
->dev
.siblings
,
122 &rootdev
->dev
.children
);
123 INIT_LIST_HEAD ( &isa
->dev
.children
);
125 /* Try probing at this I/O address */
126 if ( isa_probe ( isa
) == 0 ) {
127 /* isadev registered, we can drop our ref */
130 /* Not registered; re-use struct */
131 list_del ( &isa
->dev
.siblings
);
141 isabus_remove ( rootdev
);
146 * Remove ISA root bus
148 * @v rootdev ISA bus root device
150 static void isabus_remove ( struct root_device
*rootdev
) {
151 struct isa_device
*isa
;
152 struct isa_device
*tmp
;
154 list_for_each_entry_safe ( isa
, tmp
, &rootdev
->dev
.children
,
157 list_del ( &isa
->dev
.siblings
);
162 /** ISA bus root device driver */
163 static struct root_driver isa_root_driver
= {
164 .probe
= isabus_probe
,
165 .remove
= isabus_remove
,
168 /** ISA bus root device */
169 struct root_device isa_root_device __root_device
= {
170 .dev
= { .name
= "ISA" },
171 .driver
= &isa_root_driver
,