99784cc0fe00601518b65853665735a1df957a15
[people/lynusvaz/gpxe.git] / src / drivers / bus / isa.c
1 #include "string.h"
2 #include "config/isa.h"
3 #include "isa.h"
4
5 /*
6  * isa.c implements a "classical" port-scanning method of ISA device
7  * detection.  The driver must provide a list of probe addresses
8  * (probe_addrs), together with a function (probe_addr) that can be
9  * used to test for the physical presence of a device at any given
10  * address.
11  *
12  * Note that this should probably be considered the "last resort" for
13  * device probing.  If the card supports ISAPnP or EISA, use that
14  * instead.  Some cards (e.g. the 3c509) implement a proprietary
15  * ISAPnP-like mechanism.
16  *
17  * The ISA probe address list can be overridden by config.c; if the
18  * user specifies ISA_PROBE_ADDRS then that list will be used first.
19  * (If ISA_PROBE_ADDRS ends with a zero, the driver's own list will
20  * never be used).
21  */
22
23 /*
24  * Ensure that there is sufficient space in the shared dev_bus
25  * structure for a struct isa_device.
26  *
27  */
28 DEV_BUS( struct isa_device, isa_dev );
29 static char isa_magic[0]; /* guaranteed unique symbol */
30
31 /*
32  * User-supplied probe address list
33  *
34  */
35 static isa_probe_addr_t isa_extra_probe_addrs[] = {
36         ISA_PROBE_ADDRS
37 #if ISA_PROBE_ONLY
38         , 0
39 #endif
40 };
41 #define isa_extra_probe_addr_count \
42      ( sizeof ( isa_extra_probe_addrs ) / sizeof ( isa_extra_probe_addrs[0] ) )
43
44 /*
45  * Find an ISA device matching the specified driver
46  *
47  */
48 int find_isa_device ( struct isa_device *isa, struct isa_driver *driver ) {
49         unsigned int i;
50         uint16_t ioaddr;
51
52         /* Initialise struct isa if it's the first time it's been used. */
53         if ( isa->magic != isa_magic ) {
54                 memset ( isa, 0, sizeof ( *isa ) );
55                 isa->magic = isa_magic;
56         }
57
58         /* Iterate through any ISA probe addresses specified by the
59          * user, starting where we left off.
60          */
61         DBG ( "ISA searching for device matching driver %s\n", driver->name );
62         for ( i = isa->probe_idx ; i < isa_extra_probe_addr_count ; i++ ) {
63                 /* If we've already used this device, skip it */
64                 if ( isa->already_tried ) {
65                         isa->already_tried = 0;
66                         continue;
67                 }
68                 
69                 /* Set I/O address */
70                 ioaddr = isa_extra_probe_addrs[i];
71
72                 /* An I/O address of 0 in extra_probe_addrs list means
73                  * stop probing (i.e. don't continue to the
74                  * driver-provided list)
75                  */
76                 if ( ! ioaddr )
77                         goto notfound;
78
79                 /* Use probe_addr method to see if there's a device
80                  * present at this address.
81                  */
82                 if ( driver->probe_addr ( ioaddr ) ) {
83                         isa->probe_idx = i;
84                         goto found;
85                 }
86         }
87
88         /* Iterate through all ISA probe addresses provided by the
89          * driver, starting where we left off.
90          */
91         for ( i = isa->probe_idx - isa_extra_probe_addr_count ;
92               i < driver->addr_count ; i++ ) {
93
94                 /* If we've already used this device, skip it */
95                 if ( isa->already_tried ) {
96                         isa->already_tried = 0;
97                         continue;
98                 }
99
100                 /* Set I/O address */
101                 ioaddr = driver->probe_addrs[i];
102
103                 /* Use probe_addr method to see if there's a device
104                  * present at this address.
105                  */
106                 if ( driver->probe_addr ( ioaddr ) ) {
107                         isa->probe_idx = i + isa_extra_probe_addr_count;
108                         goto found;
109                 }
110         }
111
112  notfound:
113         /* No device found */
114         DBG ( "ISA found no device matching driver %s\n", driver->name );
115         isa->probe_idx = 0;
116         return 0;
117
118  found:
119         DBG ( "ISA found %s device at address %hx\n", driver->name, ioaddr );
120         isa->ioaddr = ioaddr;
121         isa->already_tried = 1;
122         return 1;
123 }
124
125 /*
126  * Find the next ISA device that can be used to boot using the
127  * specified driver.
128  *
129  */
130 int find_isa_boot_device ( struct dev *dev, struct isa_driver *driver ) {
131         struct isa_device *isa = ( struct isa_device * )dev->bus;
132
133         if ( ! find_isa_device ( isa, driver ) )
134                 return 0;
135
136         dev->name = driver->name;
137         dev->devid.bus_type = ISA_BUS_TYPE;
138         dev->devid.vendor_id = driver->mfg_id;
139         dev->devid.device_id = driver->prod_id;
140
141         return 1;
142 }