source: bootcd/isolinux/syslinux-6.03/gpxe/src/drivers/bus/eisa.c

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

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