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