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 
10 FILE_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 
54 static 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  */
62 static 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  */
82 static 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  */
95 static 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 
101  for_each_table_entry ( driver, ISA_DRIVERS ) {
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;
119  isa->dev.desc.bus_type = BUS_TYPE_ISA;
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  */
152 static 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 */
165 static struct root_driver isa_root_driver = {
166  .probe = isabus_probe,
167  .remove = isabus_remove,
168 };
169 
170 /** ISA bus root device */
171 struct root_device isa_root_device __root_device = {
172  .dev = { .name = "ISA" },
173  .driver = &isa_root_driver,
174 };
iPXE I/O API
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
uint16_t ioaddr
I/O address.
Definition: isa.h:16
const char * name
Name.
Definition: isa.h:36
An ISA device.
Definition: isa.h:12
struct device dev
Generic device.
Definition: isa.h:14
#define list_add(new, head)
Add a new entry to the head of a list.
Definition: list.h:69
Error codes.
char name[40]
Name.
Definition: device.h:75
uint16_t prod_id
Product ID to be assumed for this device.
Definition: isa.h:44
A root device.
Definition: device.h:94
int(* probe)(struct isa_device *isa)
Probe device.
Definition: isa.h:52
#define ISA_IOADDR(driver, ioidx)
Definition: isa.c:49
struct device dev
Device chain.
Definition: device.h:99
unsigned int vendor
Vendor ID.
Definition: device.h:31
struct device * parent
Bus device.
Definition: device.h:85
ISA probe address configuration.
uint16_t vendor_id
Manufacturer ID to be assumed for this device.
Definition: isa.h:42
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
#define ENOMEM
Not enough space.
Definition: errno.h:534
#define BUS_TYPE_ISA
ISA bus type.
Definition: device.h:55
uint16_t isa_probe_addr_t
Definition: isa.h:31
static void isabus_remove(struct root_device *rootdev)
Remove ISA root bus.
Definition: isa.c:152
const char * driver_name
Driver name.
Definition: device.h:77
#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:447
static int isa_probe(struct isa_device *isa)
Probe an ISA device.
Definition: isa.c:62
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
struct list_head siblings
Devices on the same bus.
Definition: device.h:81
uint8_t * tmp
Definition: entropy.h:156
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition: tables.h:385
A root device driver.
Definition: device.h:107
#define ISA_DRIVERS
ISA driver table.
Definition: isa.h:62
int(* probe)(struct root_device *rootdev)
Add root device.
Definition: device.h:116
void * malloc(size_t size)
Allocate memory.
Definition: malloc.c:583
void(* remove)(struct isa_device *isa)
Remove device.
Definition: isa.h:58
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition: list.h:45
unsigned int bus_type
Bus type.
Definition: device.h:24
unsigned int device
Device ID.
Definition: device.h:33
struct list_head children
Devices attached to this device.
Definition: device.h:83
static void isa_remove(struct isa_device *isa)
Remove an ISA device.
Definition: isa.c:82
struct device_description desc
Device description.
Definition: device.h:79
An ISA driver.
Definition: isa.h:34
static isa_probe_addr_t isa_extra_probe_addrs[]
Definition: isa.c:34
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition: vsprintf.c:382
#define ISA_IOIDX_MAX(driver)
Definition: isa.c:46
static int isabus_probe(struct root_device *rootdev)
Probe ISA root bus.
Definition: isa.c:95
struct isa_driver * driver
Driver for this device.
Definition: isa.h:18
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
static struct root_driver isa_root_driver
ISA bus root device driver.
Definition: isa.c:165
#define ISA_IOIDX_MIN(driver)
Definition: isa.c:42
struct root_device isa_root_device __root_device
ISA bus root device.
Definition: isa.c:171
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
FILE_LICENCE(GPL2_OR_LATER)
String functions.
void * memset(void *dest, int character, size_t len) __nonnull