Fix BUILD_SERIAL.
[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 #ifdef ISA_PROBE_ADDRS
36 #  ifdef ISA_PROBE_ONLY
37 #    define                     HAVE_ISA_PROBE_ADDRS    1
38 #    define                     ISA_PROBE_ADDR_LIST     ISA_PROBE_ADDRS, 0
39 #  else
40 #    define                     HAVE_ISA_PROBE_ADDRS    1
41 #    define                     ISA_PROBE_ADDR_LIST     ISA_PROBE_ADDRS
42 #  endif
43 #else
44 #  define                       HAVE_ISA_PROBE_ADDRS    0
45 #  define                       ISA_PROBE_ADDR_LIST     
46 #endif
47
48 static isa_probe_addr_t isa_extra_probe_addrs[] = {
49         ISA_PROBE_ADDR_LIST
50 };
51 #define isa_extra_probe_addr_count \
52      ( sizeof ( isa_extra_probe_addrs ) / sizeof ( isa_extra_probe_addrs[0] ) )
53
54 /*
55  * Find an ISA device matching the specified driver
56  *
57  */
58 int find_isa_device ( struct isa_device *isa, struct isa_driver *driver ) {
59         unsigned int i;
60         uint16_t ioaddr;
61
62         /* Initialise struct isa if it's the first time it's been used. */
63         if ( isa->magic != isa_magic ) {
64                 memset ( isa, 0, sizeof ( *isa ) );
65                 isa->magic = isa_magic;
66         }
67
68         /* Iterate through any ISA probe addresses specified by the
69          * user, starting where we left off.
70          */
71         DBG ( "ISA searching for device matching driver %s\n", driver->name );
72         for ( i = isa->probe_idx ; i < isa_extra_probe_addr_count ; i++ ) {
73                 /* If we've already used this device, skip it */
74                 if ( isa->already_tried ) {
75                         isa->already_tried = 0;
76                         continue;
77                 }
78                 
79                 /* Set I/O address */
80                 ioaddr = isa_extra_probe_addrs[i];
81
82                 /* An I/O address of 0 in extra_probe_addrs list means
83                  * stop probing (i.e. don't continue to the
84                  * driver-provided list)
85                  */
86                 if ( ! ioaddr )
87                         goto notfound;
88
89                 /* Use probe_addr method to see if there's a device
90                  * present at this address.
91                  */
92                 if ( driver->probe_addr ( ioaddr ) ) {
93                         isa->probe_idx = i;
94                         goto found;
95                 }
96         }
97
98         /* Iterate through all ISA probe addresses provided by the
99          * driver, starting where we left off.
100          */
101         for ( i = isa->probe_idx - isa_extra_probe_addr_count ;
102               i < driver->addr_count ; i++ ) {
103
104                 /* If we've already used this device, skip it */
105                 if ( isa->already_tried ) {
106                         isa->already_tried = 0;
107                         continue;
108                 }
109
110                 /* Set I/O address */
111                 ioaddr = driver->probe_addrs[i];
112
113                 /* Use probe_addr method to see if there's a device
114                  * present at this address.
115                  */
116                 if ( driver->probe_addr ( ioaddr ) ) {
117                         isa->probe_idx = i + isa_extra_probe_addr_count;
118                         goto found;
119                 }
120         }
121
122  notfound:
123         /* No device found */
124         DBG ( "ISA found no device matching driver %s\n", driver->name );
125         isa->probe_idx = 0;
126         return 0;
127
128  found:
129         DBG ( "ISA found %s device at address %hx\n", driver->name, ioaddr );
130         isa->ioaddr = ioaddr;
131         isa->already_tried = 1;
132         return 1;
133 }
134
135 /*
136  * Find the next ISA device that can be used to boot using the
137  * specified driver.
138  *
139  */
140 int find_isa_boot_device ( struct dev *dev, struct isa_driver *driver ) {
141         struct isa_device *isa = ( struct isa_device * )dev->bus;
142
143         if ( ! find_isa_device ( isa, driver ) )
144                 return 0;
145
146         dev->name = driver->name;
147         dev->devid.bus_type = ISA_BUS_TYPE;
148         dev->devid.vendor_id = driver->mfg_id;
149         dev->devid.device_id = driver->prod_id;
150
151         return 1;
152 }