iPXE
isa.c
Go to the documentation of this file.
1#include <stdint.h>
2#include <string.h>
3#include <stdlib.h>
4#include <stdio.h>
5#include <errno.h>
6#include <ipxe/io.h>
7#include <ipxe/isa.h>
8#include <config/isa.h>
9
10FILE_LICENCE ( GPL2_OR_LATER );
11
12/*
13 * isa.c implements a "classical" port-scanning method of ISA device
14 * detection. The driver must provide a list of probe addresses
15 * (probe_addrs), together with a function (probe_addr) that can be
16 * used to test for the physical presence of a device at any given
17 * address.
18 *
19 * Note that this should probably be considered the "last resort" for
20 * device probing. If the card supports ISAPnP or EISA, use that
21 * instead. Some cards (e.g. the 3c509) implement a proprietary
22 * ISAPnP-like mechanism.
23 *
24 * The ISA probe address list can be overridden by config.h; if the
25 * user specifies ISA_PROBE_ADDRS then that list will be used first.
26 * (If ISA_PROBE_ONLY is defined, the driver's own list will never be
27 * used).
28 */
29
30/*
31 * User-supplied probe address list
32 *
33 */
35#ifdef ISA_PROBE_ADDRS
36 ISA_PROBE_ADDRS
37#endif
38};
39#define ISA_EXTRA_PROBE_ADDR_COUNT \
40 ( sizeof ( isa_extra_probe_addrs ) / sizeof ( isa_extra_probe_addrs[0] ) )
41
42#define ISA_IOIDX_MIN( driver ) ( -ISA_EXTRA_PROBE_ADDR_COUNT )
43#ifdef ISA_PROBE_ONLY
44#define ISA_IOIDX_MAX( driver ) ( -1 )
45#else
46#define ISA_IOIDX_MAX( driver ) ( (int) (driver)->addr_count - 1 )
47#endif
48
49#define ISA_IOADDR( driver, ioidx ) \
50 ( ( (ioidx) >= 0 ) ? \
51 (driver)->probe_addrs[(ioidx)] : \
52 *( isa_extra_probe_addrs + (ioidx) + ISA_EXTRA_PROBE_ADDR_COUNT ) )
53
54static void isabus_remove ( struct root_device *rootdev );
55
56/**
57 * Probe an ISA device
58 *
59 * @v isa ISA device
60 * @ret rc Return status code
61 */
62static int isa_probe ( struct isa_device *isa ) {
63 int rc;
64
65 DBG ( "Trying ISA driver %s at I/O %04x\n",
66 isa->driver->name, isa->ioaddr );
67
68 if ( ( rc = isa->driver->probe ( isa ) ) != 0 ) {
69 DBG ( "...probe failed\n" );
70 return rc;
71 }
72
73 DBG ( "...device found\n" );
74 return 0;
75}
76
77/**
78 * Remove an ISA device
79 *
80 * @v isa ISA device
81 */
82static void isa_remove ( struct isa_device *isa ) {
83 isa->driver->remove ( isa );
84 DBG ( "Removed ISA%04x\n", isa->ioaddr );
85}
86
87/**
88 * Probe ISA root bus
89 *
90 * @v rootdev ISA bus root device
91 *
92 * Scans the ISA bus for devices and registers all devices it can
93 * find.
94 */
95static int isabus_probe ( struct root_device *rootdev ) {
96 struct isa_device *isa = NULL;
97 struct isa_driver *driver;
98 long ioidx;
99 int rc;
100
102 for ( ioidx = ISA_IOIDX_MIN ( driver ) ;
103 ioidx <= ISA_IOIDX_MAX ( driver ) ; ioidx++ ) {
104 /* Allocate struct isa_device */
105 if ( ! isa )
106 isa = malloc ( sizeof ( *isa ) );
107 if ( ! isa ) {
108 rc = -ENOMEM;
109 goto err;
110 }
111 memset ( isa, 0, sizeof ( *isa ) );
112 isa->driver = driver;
113 isa->ioaddr = ISA_IOADDR ( driver, ioidx );
114
115 /* Add to device hierarchy */
116 snprintf ( isa->dev.name, sizeof ( isa->dev.name ),
117 "ISA%04x", isa->ioaddr );
118 isa->dev.driver_name = driver->name;
120 isa->dev.desc.vendor = driver->vendor_id;
121 isa->dev.desc.device = driver->prod_id;
122 isa->dev.parent = &rootdev->dev;
123 list_add ( &isa->dev.siblings,
124 &rootdev->dev.children );
125 INIT_LIST_HEAD ( &isa->dev.children );
126
127 /* Try probing at this I/O address */
128 if ( isa_probe ( isa ) == 0 ) {
129 /* isadev registered, we can drop our ref */
130 isa = NULL;
131 } else {
132 /* Not registered; re-use struct */
133 list_del ( &isa->dev.siblings );
134 }
135 }
136 }
137
138 free ( isa );
139 return 0;
140
141 err:
142 free ( isa );
143 isabus_remove ( rootdev );
144 return rc;
145}
146
147/**
148 * Remove ISA root bus
149 *
150 * @v rootdev ISA bus root device
151 */
152static void isabus_remove ( struct root_device *rootdev ) {
153 struct isa_device *isa;
154 struct isa_device *tmp;
155
156 list_for_each_entry_safe ( isa, tmp, &rootdev->dev.children,
157 dev.siblings ) {
158 isa_remove ( isa );
159 list_del ( &isa->dev.siblings );
160 free ( isa );
161 }
162}
163
164/** ISA bus root device driver */
166 .probe = isabus_probe,
167 .remove = isabus_remove,
168};
169
170/** ISA bus root device */
171struct root_device isa_root_device __root_device = {
172 .dev = { .name = "ISA" },
173 .driver = &isa_root_driver,
174};
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
ISA probe address configuration.
#define __root_device
Declare a root device.
Definition device.h:136
#define BUS_TYPE_ISA
ISA bus type.
Definition device.h:56
Error codes.
#define DBG(...)
Print a debugging message.
Definition compiler.h:498
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ENOMEM
Not enough space.
Definition errno.h:535
iPXE I/O API
#define ISA_DRIVERS
ISA driver table.
Definition isa.h:62
uint16_t isa_probe_addr_t
Definition isa.h:31
String functions.
void * memset(void *dest, int character, size_t len) __nonnull
static int isa_probe(struct isa_device *isa)
Probe an ISA device.
Definition isa.c:62
#define ISA_IOIDX_MAX(driver)
Definition isa.c:44
static struct root_driver isa_root_driver
ISA bus root device driver.
Definition isa.c:165
#define ISA_IOADDR(driver, ioidx)
Definition isa.c:49
static void isabus_remove(struct root_device *rootdev)
Remove ISA root bus.
Definition isa.c:152
static isa_probe_addr_t isa_extra_probe_addrs[]
Definition isa.c:34
static void isa_remove(struct isa_device *isa)
Remove an ISA device.
Definition isa.c:82
static int isabus_probe(struct root_device *rootdev)
Probe ISA root bus.
Definition isa.c:95
#define ISA_IOIDX_MIN(driver)
Definition isa.c:42
unsigned long tmp
Definition linux_pci.h:65
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition list.h:459
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition list.h:46
#define list_add(new, head)
Add a new entry to the head of a list.
Definition list.h:70
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:621
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
unsigned int bus_type
Bus type.
Definition device.h:25
unsigned int device
Device ID.
Definition device.h:34
unsigned int vendor
Vendor ID.
Definition device.h:32
struct device_description desc
Device description.
Definition device.h:83
struct device * parent
Bus device.
Definition device.h:89
struct list_head children
Devices attached to this device.
Definition device.h:87
struct list_head siblings
Devices on the same bus.
Definition device.h:85
const char * driver_name
Driver name.
Definition device.h:81
char name[40]
Name.
Definition device.h:79
An ISA device.
Definition isa.h:12
struct isa_driver * driver
Driver for this device.
Definition isa.h:18
struct device dev
Generic device.
Definition isa.h:14
uint16_t ioaddr
I/O address.
Definition isa.h:16
An ISA driver.
Definition isa.h:34
uint16_t vendor_id
Manufacturer ID to be assumed for this device.
Definition isa.h:42
const char * name
Name.
Definition isa.h:36
void(* remove)(struct isa_device *isa)
Remove device.
Definition isa.h:58
int(* probe)(struct isa_device *isa)
Probe device.
Definition isa.h:52
uint16_t prod_id
Product ID to be assumed for this device.
Definition isa.h:44
A root device.
Definition device.h:98
struct device dev
Device chain.
Definition device.h:103
A root device driver.
Definition device.h:111
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition tables.h:386
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition vsprintf.c:383