Debug message fixes.
[people/xl0/gpxe.git] / src / drivers / bus / eisa.c
1 #include "string.h"
2 #include "io.h"
3 #include "timer.h"
4 #include "console.h"
5 #include "eisa.h"
6
7 /*
8  * Increment a bus_loc structure to the next possible EISA location.
9  * Leave the structure zeroed and return 0 if there are no more valid
10  * locations.
11  *
12  */
13 static int eisa_next_location ( struct bus_loc *bus_loc ) {
14         struct eisa_loc *eisa_loc = ( struct eisa_loc * ) bus_loc;
15         
16         /*
17          * Ensure that there is sufficient space in the shared bus
18          * structures for a struct isa_loc and a struct
19          * isa_dev, as mandated by bus.h.
20          *
21          */
22         BUS_LOC_CHECK ( struct eisa_loc );
23         BUS_DEV_CHECK ( struct eisa_device );
24
25         return ( eisa_loc->slot = ( ++eisa_loc->slot & EISA_MAX_SLOT ) );
26 }
27
28 /*
29  * Fill in parameters for an EISA device based on slot number
30  *
31  * Return 1 if device present, 0 otherwise
32  *
33  */
34 static int eisa_fill_device  ( struct bus_dev *bus_dev,
35                                struct bus_loc *bus_loc ) {
36         struct eisa_loc *eisa_loc = ( struct eisa_loc * ) bus_loc;
37         struct eisa_device *eisa = ( struct eisa_device * ) bus_dev;
38         uint8_t present;
39
40         /* Copy slot number to struct eisa, set default values */
41         eisa->slot = eisa_loc->slot;
42         eisa->name = "?";
43
44         /* Slot 0 is never valid */
45         if ( ! eisa->slot )
46                 return 0;
47
48         /* Set ioaddr */
49         eisa->ioaddr = EISA_SLOT_BASE ( eisa->slot );
50
51         /* Test for board present */
52         outb ( 0xff, eisa->ioaddr + EISA_MFG_ID_HI );
53         present = inb ( eisa->ioaddr + EISA_MFG_ID_HI );
54         if ( present & 0x80 ) {
55                 /* No board present */
56                 return 0;
57         }
58
59         /* Read mfg and product IDs.  Yes, the resulting uint16_ts
60          * will be upside-down.  This appears to be by design.
61          */
62         eisa->mfg_id = ( inb ( eisa->ioaddr + EISA_MFG_ID_LO ) << 8 )
63                 + present;
64         eisa->prod_id = ( inb ( eisa->ioaddr + EISA_PROD_ID_LO ) << 8 )
65                 + inb ( eisa->ioaddr + EISA_PROD_ID_HI );
66
67         DBG ( "EISA found slot %hhx (base %#hx) ID %hx:%hx (\"%s\")\n",
68               eisa->slot, eisa->ioaddr, eisa->mfg_id, eisa->prod_id,
69               isa_id_string ( eisa->mfg_id, eisa->prod_id ) );
70
71         return 1;
72 }
73
74 /*
75  * Test whether or not a driver is capable of driving the device.
76  *
77  */
78 static int eisa_check_driver ( struct bus_dev *bus_dev,
79                                  struct device_driver *device_driver ) {
80         struct eisa_device *eisa = ( struct eisa_device * ) bus_dev;
81         struct eisa_driver *driver
82                 = ( struct eisa_driver * ) device_driver->bus_driver_info;
83         unsigned int i;
84
85         /* Compare against driver's ID list */
86         for ( i = 0 ; i < driver->id_count ; i++ ) {
87                 struct eisa_id *id = &driver->ids[i];
88                 
89                 if ( ( eisa->mfg_id == id->mfg_id ) &&
90                      ( ISA_PROD_ID ( eisa->prod_id ) ==
91                        ISA_PROD_ID ( id->prod_id ) ) ) {
92                         DBG ( "EISA found ID %hx:%hx (\"%s\") "
93                               "(device %s) matching driver %s\n",
94                               eisa->mfg_id, eisa->prod_id,
95                               isa_id_string ( eisa->mfg_id,
96                                               eisa->prod_id ),
97                               id->name, driver->name );
98                         eisa->name = id->name;
99                         return 1;
100                 }
101         }
102
103         /* No device found */
104         return 0;
105 }
106
107 /*
108  * Describe an EISA device
109  *
110  */
111 static char * eisa_describe ( struct bus_dev *bus_dev ) {
112         struct eisa_device *eisa = ( struct eisa_device * ) bus_dev;
113         static char eisa_description[] = "EISA 00";
114
115         sprintf ( eisa_description + 5, "%hhx", eisa->slot );
116         return eisa_description;
117 }
118
119 /*
120  * Name an EISA device
121  *
122  */
123 static const char * eisa_name ( struct bus_dev *bus_dev ) {
124         struct eisa_device *eisa = ( struct eisa_device * ) bus_dev;
125         
126         return eisa->name;
127 }
128
129 /*
130  * EISA bus operations table
131  *
132  */
133 struct bus_driver eisa_driver __bus_driver = {
134         .next_location  = eisa_next_location,
135         .fill_device    = eisa_fill_device,
136         .check_driver   = eisa_check_driver,
137         .describe       = eisa_describe,
138         .name           = eisa_name,
139 };
140
141 /*
142  * Fill in a nic structure
143  *
144  */
145 void eisa_fill_nic ( struct nic *nic, struct eisa_device *eisa ) {
146
147         /* Fill in ioaddr and irqno */
148         nic->ioaddr = eisa->ioaddr;
149         nic->irqno = 0;
150
151         /* Fill in DHCP device ID structure */
152         nic->dhcp_dev_id.bus_type = ISA_BUS_TYPE;
153         nic->dhcp_dev_id.vendor_id = htons ( eisa->mfg_id );
154         nic->dhcp_dev_id.device_id = htons ( eisa->prod_id );
155 }
156
157 /*
158  * Reset and enable/disable an EISA device
159  *
160  */
161 void eisa_device_enabled ( struct eisa_device *eisa, int enabled ) {
162         /* Set reset line high for 1000 µs.  Spec says 500 µs, but
163          * this doesn't work for all cards, so we are conservative.
164          */
165         outb ( EISA_CMD_RESET, eisa->ioaddr + EISA_GLOBAL_CONFIG );
166         udelay ( 1000 ); /* Must wait 800 */
167
168         /* Set reset low and write a 1 to ENABLE.  Delay again, in
169          * case the card takes a while to wake up.
170          */
171         outb ( enabled ? EISA_CMD_ENABLE : 0,
172                eisa->ioaddr + EISA_GLOBAL_CONFIG );
173         udelay ( 1000 ); /* Must wait 800 */
174
175         DBG ( "EISA %s device %hhx\n", ( enabled ? "enabled" : "disabled" ),
176               eisa->slot );
177 }