Revert "convert to zalloc"
[people/xl0/gpxe-arm.git] / src / drivers / bus / eisa.c
1 #include <stdint.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <errno.h>
6 #include <io.h>
7 #include <timer.h>
8 #include <gpxe/eisa.h>
9
10 static struct eisa_driver eisa_drivers[0]
11         __table_start ( struct eisa_driver, eisa_drivers );
12 static struct eisa_driver eisa_drivers_end[0]
13         __table_end ( struct eisa_driver, eisa_drivers );
14
15 static void eisabus_remove ( struct root_device *rootdev );
16
17 /**
18  * Reset and enable/disable an EISA device
19  *
20  * @v eisa              EISA device
21  * @v enabled           1=enable, 0=disable
22  */
23 void eisa_device_enabled ( struct eisa_device *eisa, int enabled ) {
24         /* Set reset line high for 1000 µs.  Spec says 500 µs, but
25          * this doesn't work for all cards, so we are conservative.
26          */
27         outb ( EISA_CMD_RESET, eisa->ioaddr + EISA_GLOBAL_CONFIG );
28         udelay ( 1000 ); /* Must wait 800 */
29
30         /* Set reset low and write a 1 to ENABLE.  Delay again, in
31          * case the card takes a while to wake up.
32          */
33         outb ( enabled ? EISA_CMD_ENABLE : 0,
34                eisa->ioaddr + EISA_GLOBAL_CONFIG );
35         udelay ( 1000 ); /* Must wait 800 */
36
37         DBG ( "EISA %s device %02x\n", ( enabled ? "enabled" : "disabled" ),
38               eisa->slot );
39 }
40
41 /**
42  * Probe an EISA device
43  *
44  * @v eisa              EISA device
45  * @ret rc              Return status code
46  *
47  * Searches for a driver for the EISA device.  If a driver is found,
48  * its probe() routine is called.
49  */
50 static int eisa_probe ( struct eisa_device *eisa ) {
51         struct eisa_driver *driver;
52         struct eisa_device_id *id;
53         unsigned int i;
54         int rc;
55
56         DBG ( "Adding EISA device %02x (%04x:%04x (\"%s\") io %x)\n",
57               eisa->slot, eisa->vendor_id, eisa->prod_id,
58               isa_id_string ( eisa->vendor_id, eisa->prod_id ), eisa->ioaddr );
59
60         for ( driver = eisa_drivers; driver < eisa_drivers_end; driver++ ) {
61                 for ( i = 0 ; i < driver->id_count ; i++ ) {
62                         id = &driver->ids[i];
63                         if ( id->vendor_id != eisa->vendor_id )
64                                 continue;
65                         if ( ISA_PROD_ID ( id->prod_id ) !=
66                              ISA_PROD_ID ( eisa->prod_id ) )
67                                 continue;
68                         eisa->driver = driver;
69                         eisa->driver_name = id->name;
70                         DBG ( "...using driver %s\n", eisa->driver_name );
71                         if ( ( rc = driver->probe ( eisa, id ) ) != 0 ) {
72                                 DBG ( "......probe failed\n" );
73                                 continue;
74                         }
75                         return 0;
76                 }
77         }
78
79         DBG ( "...no driver found\n" );
80         return -ENOTTY;
81 }
82
83 /**
84  * Remove an EISA device
85  *
86  * @v eisa              EISA device
87  */
88 static void eisa_remove ( struct eisa_device *eisa ) {
89         eisa->driver->remove ( eisa );
90         DBG ( "Removed EISA device %02x\n", eisa->slot );
91 }
92
93 /**
94  * Probe EISA root bus
95  *
96  * @v rootdev           EISA bus root device
97  *
98  * Scans the EISA bus for devices and registers all devices it can
99  * find.
100  */
101 static int eisabus_probe ( struct root_device *rootdev ) {
102         struct eisa_device *eisa = NULL;
103         unsigned int slot;
104         int rc;
105
106         for ( slot = EISA_MIN_SLOT ; slot <= EISA_MAX_SLOT ; slot++ ) {
107                 /* Allocate struct eisa_device */
108                 if ( ! eisa )
109                         eisa = malloc ( sizeof ( *eisa ) );
110                 if ( ! eisa ) {
111                         rc = -ENOMEM;
112                         goto err;
113                 }
114                 memset ( eisa, 0, sizeof ( *eisa ) );
115                 eisa->slot = slot;
116                 eisa->ioaddr = EISA_SLOT_BASE ( eisa->slot );
117
118                 /* Test for board present */
119                 outb ( 0xff, eisa->ioaddr + EISA_VENDOR_ID );
120                 eisa->vendor_id =
121                         le16_to_cpu ( inw ( eisa->ioaddr + EISA_VENDOR_ID ) );
122                 eisa->prod_id =
123                         le16_to_cpu ( inw ( eisa->ioaddr + EISA_PROD_ID ) );
124                 if ( eisa->vendor_id & 0x80 ) {
125                         /* No board present */
126                         continue;
127                 }
128
129                 /* Add to device hierarchy */
130                 snprintf ( eisa->dev.name, sizeof ( eisa->dev.name ),
131                            "EISA%02x", slot );
132                 eisa->dev.desc.bus_type = BUS_TYPE_EISA;
133                 eisa->dev.desc.vendor = eisa->vendor_id;
134                 eisa->dev.desc.device = eisa->prod_id;
135                 eisa->dev.parent = &rootdev->dev;
136                 list_add ( &eisa->dev.siblings, &rootdev->dev.children );
137                 INIT_LIST_HEAD ( &eisa->dev.children );
138
139                 /* Look for a driver */
140                 if ( eisa_probe ( eisa ) == 0 ) {
141                         /* eisadev registered, we can drop our ref */
142                         eisa = NULL;
143                 } else {
144                         /* Not registered; re-use struct */
145                         list_del ( &eisa->dev.siblings );
146                 }
147         }
148
149         free ( eisa );
150         return 0;
151
152  err:
153         free ( eisa );
154         eisabus_remove ( rootdev );
155         return rc;
156 }
157
158 /**
159  * Remove EISA root bus
160  *
161  * @v rootdev           EISA bus root device
162  */
163 static void eisabus_remove ( struct root_device *rootdev ) {
164         struct eisa_device *eisa;
165         struct eisa_device *tmp;
166
167         list_for_each_entry_safe ( eisa, tmp, &rootdev->dev.children,
168                                    dev.siblings ) {
169                 eisa_remove ( eisa );
170                 list_del ( &eisa->dev.siblings );
171                 free ( eisa );
172         }
173 }
174
175 /** EISA bus root device driver */
176 static struct root_driver eisa_root_driver = {
177         .probe = eisabus_probe,
178         .remove = eisabus_remove,
179 };
180
181 /** EISA bus root device */
182 struct root_device eisa_root_device __root_device = {
183         .dev = { .name = "EISA" },
184         .driver = &eisa_root_driver,
185 };