|
|
1.1 root 1: #include <stdint.h>
2: #include <string.h>
3: #include <stdlib.h>
4: #include <stdio.h>
5: #include <errno.h>
6: #include <ipxe/io.h>
7: #include <ipxe/isa.h>
8:
9: FILE_LICENCE ( GPL2_OR_LATER );
10:
11: /*
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
16: * address.
17: *
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.
22: *
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
26: * used).
27: */
28:
29: /*
30: * User-supplied probe address list
31: *
32: */
33: static isa_probe_addr_t isa_extra_probe_addrs[] = {
34: #ifdef ISA_PROBE_ADDRS
35: ISA_PROBE_ADDRS
36: #endif
37: };
38: #define ISA_EXTRA_PROBE_ADDR_COUNT \
39: ( sizeof ( isa_extra_probe_addrs ) / sizeof ( isa_extra_probe_addrs[0] ) )
40:
41: #define ISA_IOIDX_MIN( driver ) ( -ISA_EXTRA_PROBE_ADDR_COUNT )
42: #ifdef ISA_PROBE_ONLY
43: #define ISA_IOIDX_MAX( driver ) ( -1 )
44: #else
45: #define ISA_IOIDX_MAX( driver ) ( (int) (driver)->addr_count - 1 )
46: #endif
47:
48: #define ISA_IOADDR( driver, ioidx ) \
49: ( ( (ioidx) < 0 ) ? \
50: isa_extra_probe_addrs[ (ioidx) + ISA_EXTRA_PROBE_ADDR_COUNT ] : \
51: (driver)->probe_addrs[(ioidx)] )
52:
53: static void isabus_remove ( struct root_device *rootdev );
54:
55: /**
56: * Probe an ISA device
57: *
58: * @v isa ISA device
59: * @ret rc Return status code
60: */
61: static int isa_probe ( struct isa_device *isa ) {
62: int rc;
63:
64: DBG ( "Trying ISA driver %s at I/O %04x\n",
65: isa->driver->name, isa->ioaddr );
66:
67: if ( ( rc = isa->driver->probe ( isa ) ) != 0 ) {
68: DBG ( "...probe failed\n" );
69: return rc;
70: }
71:
72: DBG ( "...device found\n" );
73: return 0;
74: }
75:
76: /**
77: * Remove an ISA device
78: *
79: * @v isa ISA device
80: */
81: static void isa_remove ( struct isa_device *isa ) {
82: isa->driver->remove ( isa );
83: DBG ( "Removed ISA%04x\n", isa->ioaddr );
84: }
85:
86: /**
87: * Probe ISA root bus
88: *
89: * @v rootdev ISA bus root device
90: *
91: * Scans the ISA bus for devices and registers all devices it can
92: * find.
93: */
94: static int isabus_probe ( struct root_device *rootdev ) {
95: struct isa_device *isa = NULL;
96: struct isa_driver *driver;
97: int ioidx;
98: int rc;
99:
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 */
104: if ( ! isa )
105: isa = malloc ( sizeof ( *isa ) );
106: if ( ! isa ) {
107: rc = -ENOMEM;
108: goto err;
109: }
110: memset ( isa, 0, sizeof ( *isa ) );
111: isa->driver = driver;
112: isa->ioaddr = ISA_IOADDR ( driver, ioidx );
113:
114: /* Add to device hierarchy */
115: snprintf ( isa->dev.name, sizeof ( isa->dev.name ),
116: "ISA%04x", isa->ioaddr );
117: isa->dev.driver_name = driver->name;
118: isa->dev.desc.bus_type = BUS_TYPE_ISA;
119: isa->dev.desc.vendor = driver->vendor_id;
120: isa->dev.desc.device = driver->prod_id;
121: isa->dev.parent = &rootdev->dev;
122: list_add ( &isa->dev.siblings,
123: &rootdev->dev.children );
124: INIT_LIST_HEAD ( &isa->dev.children );
125:
126: /* Try probing at this I/O address */
127: if ( isa_probe ( isa ) == 0 ) {
128: /* isadev registered, we can drop our ref */
129: isa = NULL;
130: } else {
131: /* Not registered; re-use struct */
132: list_del ( &isa->dev.siblings );
133: }
134: }
135: }
136:
137: free ( isa );
138: return 0;
139:
140: err:
141: free ( isa );
142: isabus_remove ( rootdev );
143: return rc;
144: }
145:
146: /**
147: * Remove ISA root bus
148: *
149: * @v rootdev ISA bus root device
150: */
151: static void isabus_remove ( struct root_device *rootdev ) {
152: struct isa_device *isa;
153: struct isa_device *tmp;
154:
155: list_for_each_entry_safe ( isa, tmp, &rootdev->dev.children,
156: dev.siblings ) {
157: isa_remove ( isa );
158: list_del ( &isa->dev.siblings );
159: free ( isa );
160: }
161: }
162:
163: /** ISA bus root device driver */
164: static struct root_driver isa_root_driver = {
165: .probe = isabus_probe,
166: .remove = isabus_remove,
167: };
168:
169: /** ISA bus root device */
170: struct root_device isa_root_device __root_device = {
171: .dev = { .name = "ISA" },
172: .driver = &isa_root_driver,
173: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.