c80974a8a0d9479a5d5f012aba9e70a04f501643
[people/xl0/gpxe.git] / src / drivers / bus / eisa.c
1 #include "etherboot.h"
2 #include "dev.h"
3 #include "io.h"
4 #include "timer.h"
5 #include "eisa.h"
6
7 #define DEBUG_EISA
8
9 #undef DBG
10 #ifdef DEBUG_EISA
11 #define DBG(...) printf ( __VA_ARGS__ )
12 #else
13 #define DBG(...)
14 #endif
15
16 /*
17  * Ensure that there is sufficient space in the shared dev_bus
18  * structure for a struct pci_device.
19  *
20  */
21 DEV_BUS( struct eisa_device, eisa_dev );
22 static char eisa_magic[0]; /* guaranteed unique symbol */
23
24 /*
25  * Fill in parameters for an EISA device based on slot number
26  *
27  * Return 1 if device present, 0 otherwise
28  *
29  */
30 static int fill_eisa_device ( struct eisa_device *eisa ) {
31         uint8_t present;
32
33         /* Set ioaddr */
34         eisa->ioaddr = EISA_SLOT_BASE ( eisa->slot );
35
36         /* Test for board present */
37         outb ( 0xff, eisa->ioaddr + EISA_MFG_ID_HI );
38         present = inb ( eisa->ioaddr + EISA_MFG_ID_HI );
39         if ( present & 0x80 ) {
40                 /* No board present */
41                 return 0;
42         }
43
44         /* Read mfg and product IDs.  Yes, the resulting uint16_ts
45          * will be upside-down.  This appears to be by design.
46          */
47         eisa->mfg_id = ( inb ( eisa->ioaddr + EISA_MFG_ID_LO ) << 8 )
48                 + present;
49         eisa->prod_id = ( inb ( eisa->ioaddr + EISA_PROD_ID_LO ) << 8 )
50                 + inb ( eisa->ioaddr + EISA_PROD_ID_HI );
51
52         DBG ( "EISA slot %d (base %#hx) ID %hx:%hx (\"%s\")\n",
53               eisa->slot, eisa->ioaddr, eisa->mfg_id, eisa->prod_id,
54               isa_id_string ( eisa->mfg_id, eisa->prod_id ) );
55
56         return 1;
57 }
58
59 /*
60  * Obtain a struct eisa * from a struct dev *
61  *
62  * If dev has not previously been used for an EISA device scan, blank
63  * out struct eisa
64  */
65 struct eisa_device * eisa_device ( struct dev *dev ) {
66         struct eisa_device *eisa = dev->bus;;
67
68         if ( eisa->magic != eisa_magic ) {
69                 memset ( eisa, 0, sizeof ( *eisa ) );
70                 eisa->magic = eisa_magic;
71         }
72         eisa->dev = dev;
73         return eisa;
74 }
75
76 /*
77  * Find an EISA device matching the specified driver
78  *
79  */
80 int find_eisa_device ( struct eisa_device *eisa, struct eisa_driver *driver ) {
81         unsigned int i;
82
83         /* Iterate through all possible EISA slots, starting where we
84          * left off.  If eisa->slot is zero (which it will be if we
85          * have a zeroed structure), start from slot EISA_MIN_SLOT,
86          * since slot 0 doesn't exist.
87          */
88         if ( ! eisa->slot ) {
89                 eisa->slot = EISA_MIN_SLOT;
90         }
91         for ( ; eisa->slot <= EISA_MAX_SLOT ; eisa->slot++ ) {
92                 /* If we've already used this device, skip it */
93                 if ( eisa->already_tried ) {
94                         eisa->already_tried = 0;
95                         continue;
96                 }
97
98                 /* Fill in device parameters */
99                 if ( ! fill_eisa_device ( eisa ) ) {
100                         continue;
101                 }
102
103                 /* Compare against driver's ID list */
104                 for ( i = 0 ; i < driver->id_count ; i++ ) {
105                         struct eisa_id *id = &driver->ids[i];
106                         
107                         if ( ( eisa->mfg_id == id->mfg_id ) &&
108                              ( ISA_PROD_ID ( eisa->prod_id ) ==
109                                ISA_PROD_ID ( id->prod_id ) ) ) {
110                                 DBG ( "Device %s (driver %s) matches ID %s\n",
111                                       id->name, driver->name,
112                                       isa_id_string ( eisa->mfg_id,
113                                                       eisa->prod_id ) );
114                                 if ( eisa->dev ) {
115                                         eisa->dev->name = driver->name;
116                                         eisa->dev->devid.bus_type
117                                                 = ISA_BUS_TYPE;
118                                         eisa->dev->devid.vendor_id
119                                                 = eisa->mfg_id;
120                                         eisa->dev->devid.device_id
121                                                 = eisa->prod_id;
122                                 }
123                                 eisa->already_tried = 1;
124                                 return 1;
125                         }
126                 }
127         }
128
129         /* No device found */
130         eisa->slot = EISA_MIN_SLOT;
131         return 0;
132 }
133
134 /*
135  * Reset and enable an EISA device
136  *
137  */
138 void enable_eisa_device ( struct eisa_device *eisa ) {
139         /* Set reset line high for 1000 µs.  Spec says 500 µs, but
140          * this doesn't work for all cards, so we are conservative.
141          */
142         outb ( EISA_CMD_RESET, eisa->ioaddr + EISA_GLOBAL_CONFIG );
143         udelay ( 1000 ); /* Must wait 800 */
144
145         /* Set reset low and write a 1 to ENABLE.  Delay again, in
146          * case the card takes a while to wake up.
147          */
148         outb ( EISA_CMD_ENABLE, eisa->ioaddr + EISA_GLOBAL_CONFIG );
149         udelay ( 1000 ); /* Must wait 800 */
150 }