source: bootcd/isolinux/syslinux-6.03/gpxe/src/drivers/bus/isa.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.1 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 <gpxe/isa.h>
8
9FILE_LICENCE ( GPL2_OR_LATER );
10
11/*
12 * isa.c implements a "classical" port-scanning method of ISA device
13 * detection.  The driver must provide a list of probe addresses
14 * (probe_addrs), together with a function (probe_addr) that can be
15 * used to test for the physical presence of a device at any given
16 * address.
17 *
18 * Note that this should probably be considered the "last resort" for
19 * device probing.  If the card supports ISAPnP or EISA, use that
20 * instead.  Some cards (e.g. the 3c509) implement a proprietary
21 * ISAPnP-like mechanism.
22 *
23 * The ISA probe address list can be overridden by config.h; if the
24 * user specifies ISA_PROBE_ADDRS then that list will be used first.
25 * (If ISA_PROBE_ONLY is defined, the driver's own list will never be
26 * used).
27 */
28
29/*
30 * User-supplied probe address list
31 *
32 */
33static isa_probe_addr_t isa_extra_probe_addrs[] = {
34#ifdef ISA_PROBE_ADDRS
35        ISA_PROBE_ADDRS
36#endif
37};
38#define ISA_EXTRA_PROBE_ADDR_COUNT \
39     ( sizeof ( isa_extra_probe_addrs ) / sizeof ( isa_extra_probe_addrs[0] ) )
40
41#define ISA_IOIDX_MIN( driver ) ( -ISA_EXTRA_PROBE_ADDR_COUNT )
42#ifdef ISA_PROBE_ONLY
43#define ISA_IOIDX_MAX( driver ) ( -1 )
44#else
45#define ISA_IOIDX_MAX( driver ) ( (int) (driver)->addr_count - 1 )
46#endif
47
48#define ISA_IOADDR( driver, ioidx )                                       \
49        ( ( (ioidx) < 0 ) ?                                               \
50          isa_extra_probe_addrs[ (ioidx) + ISA_EXTRA_PROBE_ADDR_COUNT ] : \
51          (driver)->probe_addrs[(ioidx)] )
52
53static void isabus_remove ( struct root_device *rootdev );
54
55/**
56 * Probe an ISA device
57 *
58 * @v isa               ISA device
59 * @ret rc              Return status code
60 */
61static int isa_probe ( struct isa_device *isa ) {
62        int rc;
63
64        DBG ( "Trying ISA driver %s at I/O %04x\n",
65              isa->driver->name, isa->ioaddr );
66
67        if ( ( rc = isa->driver->probe ( isa ) ) != 0 ) {
68                DBG ( "...probe failed\n" );
69                return rc;
70        }
71
72        DBG ( "...device found\n" );
73        return 0;
74}
75
76/**
77 * Remove an ISA device
78 *
79 * @v isa               ISA device
80 */
81static void isa_remove ( struct isa_device *isa ) {
82        isa->driver->remove ( isa );
83        DBG ( "Removed ISA%04x\n", isa->ioaddr );
84}
85
86/**
87 * Probe ISA root bus
88 *
89 * @v rootdev           ISA bus root device
90 *
91 * Scans the ISA bus for devices and registers all devices it can
92 * find.
93 */
94static int isabus_probe ( struct root_device *rootdev ) {
95        struct isa_device *isa = NULL;
96        struct isa_driver *driver;
97        int ioidx;
98        int rc;
99
100        for_each_table_entry ( driver, ISA_DRIVERS ) {
101                for ( ioidx = ISA_IOIDX_MIN ( driver ) ;
102                      ioidx <= ISA_IOIDX_MAX ( driver ) ; ioidx++ ) {
103                        /* Allocate struct isa_device */
104                        if ( ! isa )
105                                isa = malloc ( sizeof ( *isa ) );
106                        if ( ! isa ) {
107                                rc = -ENOMEM;
108                                goto err;
109                        }
110                        memset ( isa, 0, sizeof ( *isa ) );
111                        isa->driver = driver;
112                        isa->ioaddr = ISA_IOADDR ( driver, ioidx );
113
114                        /* Add to device hierarchy */
115                        snprintf ( isa->dev.name, sizeof ( isa->dev.name ),
116                                   "ISA%04x", isa->ioaddr );
117                        isa->dev.desc.bus_type = BUS_TYPE_ISA;
118                        isa->dev.desc.vendor = driver->vendor_id;
119                        isa->dev.desc.device = driver->prod_id;
120                        isa->dev.parent = &rootdev->dev;
121                        list_add ( &isa->dev.siblings,
122                                   &rootdev->dev.children );
123                        INIT_LIST_HEAD ( &isa->dev.children );
124
125                        /* Try probing at this I/O address */
126                        if ( isa_probe ( isa ) == 0 ) {
127                                /* isadev registered, we can drop our ref */
128                                isa = NULL;
129                        } else {
130                                /* Not registered; re-use struct */
131                                list_del ( &isa->dev.siblings );
132                        }
133                }
134        }
135
136        free ( isa );
137        return 0;
138
139 err:
140        free ( isa );
141        isabus_remove ( rootdev );
142        return rc;
143}
144
145/**
146 * Remove ISA root bus
147 *
148 * @v rootdev           ISA bus root device
149 */
150static void isabus_remove ( struct root_device *rootdev ) {
151        struct isa_device *isa;
152        struct isa_device *tmp;
153
154        list_for_each_entry_safe ( isa, tmp, &rootdev->dev.children,
155                                   dev.siblings ) {
156                isa_remove ( isa );
157                list_del ( &isa->dev.siblings );
158                free ( isa );
159        }
160}
161
162/** ISA bus root device driver */
163static struct root_driver isa_root_driver = {
164        .probe = isabus_probe,
165        .remove = isabus_remove,
166};
167
168/** ISA bus root device */
169struct root_device isa_root_device __root_device = {
170        .dev = { .name = "ISA" },
171        .driver = &isa_root_driver,
172};
Note: See TracBrowser for help on using the repository browser.