Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / drivers / bus / isa.c
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           (driver)->probe_addrs[(ioidx)] :                                \
51           *( isa_extra_probe_addrs + (ioidx) + ISA_EXTRA_PROBE_ADDR_COUNT ) )
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 };