iPXE
eisa.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 <unistd.h>
8 #include <ipxe/eisa.h>
9 
10 FILE_LICENCE ( GPL2_OR_LATER );
11 
12 static 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  */
20 void 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  */
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  */
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  */
47 static 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 
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->dev.driver_name = id->name;
67  DBG ( "...using driver %s\n", eisa->dev.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  */
85 static 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  */
98 static int eisabus_probe ( struct root_device *rootdev ) {
99  struct eisa_device *eisa = NULL;
100  unsigned int slot;
101  uint8_t system;
102  int rc;
103 
104  /* Check for EISA system board */
105  system = inb ( EISA_VENDOR_ID );
106  if ( system & 0x80 ) {
107  DBG ( "No EISA system board (read %02x)\n", system );
108  return -ENODEV;
109  }
110 
111  for ( slot = EISA_MIN_SLOT ; slot <= EISA_MAX_SLOT ; slot++ ) {
112  /* Allocate struct eisa_device */
113  if ( ! eisa )
114  eisa = malloc ( sizeof ( *eisa ) );
115  if ( ! eisa ) {
116  rc = -ENOMEM;
117  goto err;
118  }
119  memset ( eisa, 0, sizeof ( *eisa ) );
120  eisa->slot = slot;
121  eisa->ioaddr = EISA_SLOT_BASE ( eisa->slot );
122 
123  /* Test for board present */
124  outb ( 0xff, eisa->ioaddr + EISA_VENDOR_ID );
125  eisa->vendor_id =
126  le16_to_cpu ( inw ( eisa->ioaddr + EISA_VENDOR_ID ) );
127  eisa->prod_id =
128  le16_to_cpu ( inw ( eisa->ioaddr + EISA_PROD_ID ) );
129  if ( eisa->vendor_id & 0x80 ) {
130  /* No board present */
131  continue;
132  }
133 
134  /* Add to device hierarchy */
135  snprintf ( eisa->dev.name, sizeof ( eisa->dev.name ),
136  "EISA%02x", slot );
137  eisa->dev.desc.bus_type = BUS_TYPE_EISA;
138  eisa->dev.desc.vendor = eisa->vendor_id;
139  eisa->dev.desc.device = eisa->prod_id;
140  eisa->dev.parent = &rootdev->dev;
141  list_add ( &eisa->dev.siblings, &rootdev->dev.children );
142  INIT_LIST_HEAD ( &eisa->dev.children );
143 
144  /* Look for a driver */
145  if ( eisa_probe ( eisa ) == 0 ) {
146  /* eisadev registered, we can drop our ref */
147  eisa = NULL;
148  } else {
149  /* Not registered; re-use struct */
150  list_del ( &eisa->dev.siblings );
151  }
152  }
153 
154  free ( eisa );
155  return 0;
156 
157  err:
158  free ( eisa );
159  eisabus_remove ( rootdev );
160  return rc;
161 }
162 
163 /**
164  * Remove EISA root bus
165  *
166  * @v rootdev EISA bus root device
167  */
168 static void eisabus_remove ( struct root_device *rootdev ) {
169  struct eisa_device *eisa;
170  struct eisa_device *tmp;
171 
172  list_for_each_entry_safe ( eisa, tmp, &rootdev->dev.children,
173  dev.siblings ) {
174  eisa_remove ( eisa );
175  list_del ( &eisa->dev.siblings );
176  free ( eisa );
177  }
178 }
179 
180 /** EISA bus root device driver */
181 static struct root_driver eisa_root_driver = {
182  .probe = eisabus_probe,
183  .remove = eisabus_remove,
184 };
185 
186 /** EISA bus root device */
187 struct root_device eisa_root_device __root_device = {
188  .dev = { .name = "EISA" },
189  .driver = &eisa_root_driver,
190 };
static int eisa_probe(struct eisa_device *eisa)
Probe an EISA device.
Definition: eisa.c:47
iPXE I/O API
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
uint16_t inw(volatile uint16_t *io_addr)
Read 16-bit word from I/O-mapped device.
#define list_add(new, head)
Add a new entry to the head of a list.
Definition: list.h:69
#define EISA_PROD_ID
Definition: eisa.h:21
Error codes.
uint16_t vendor_id
Manufacturer ID.
Definition: eisa.h:46
FILE_LICENCE(GPL2_OR_LATER)
char name[40]
Name.
Definition: device.h:75
A root device.
Definition: device.h:94
void eisa_device_enabled(struct eisa_device *eisa, int enabled)
Reset and enable/disable an EISA device.
Definition: eisa.c:20
#define EISA_MIN_SLOT
Definition: eisa.h:16
An EISA device.
Definition: eisa.h:38
struct device dev
Device chain.
Definition: device.h:99
char * isa_id_string(unsigned int vendor, unsigned int product)
Definition: isa_ids.c:11
unsigned int vendor
Vendor ID.
Definition: device.h:31
struct device * parent
Bus device.
Definition: device.h:85
uint32_t enabled
Bitmask of enabled AENQ groups (host -> device)
Definition: ena.h:14
int(* probe)(struct eisa_device *eisa, const struct eisa_device_id *id)
Probe device.
Definition: eisa.h:72
unsigned long tmp
Definition: linux_pci.h:53
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
static void eisabus_remove(struct root_device *rootdev)
Remove EISA root bus.
Definition: eisa.c:168
#define ENOMEM
Not enough space.
Definition: errno.h:534
static int eisabus_probe(struct root_device *rootdev)
Probe EISA root bus.
Definition: eisa.c:98
struct eisa_driver * driver
Driver for this device.
Definition: eisa.h:50
void udelay(unsigned long usecs)
Delay for a fixed number of microseconds.
Definition: timer.c:60
static struct root_driver eisa_root_driver
EISA bus root device driver.
Definition: eisa.c:181
An EISA device ID list entry.
Definition: eisa.h:28
unsigned int slot
Slot number.
Definition: eisa.h:42
struct root_device eisa_root_device __root_device
EISA bus root device.
Definition: eisa.c:187
const char * driver_name
Driver name.
Definition: device.h:77
void(* remove)(struct eisa_device *eisa)
Remove device.
Definition: eisa.h:79
#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:458
unsigned int id_count
Number of entries in EISA ID table.
Definition: eisa.h:64
#define BUS_TYPE_EISA
EISA bus type.
Definition: device.h:49
uint8_t id
Request identifier.
Definition: ena.h:12
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
#define EISA_VENDOR_ID
Definition: eisa.h:20
struct list_head siblings
Devices on the same bus.
Definition: device.h:81
An EISA driver.
Definition: eisa.h:60
#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 ENODEV
No such device.
Definition: errno.h:509
unsigned char uint8_t
Definition: stdint.h:10
uint8_t slot
Slot.
Definition: edd.h:16
uint8_t inb(volatile uint8_t *io_addr)
Read byte from I/O-mapped device.
#define le16_to_cpu(value)
Definition: byteswap.h:112
int(* probe)(struct root_device *rootdev)
Add root device.
Definition: device.h:116
void * malloc(size_t size)
Allocate memory.
Definition: malloc.c:583
#define EISA_CMD_RESET
Definition: eisa.h:24
uint16_t ioaddr
I/O address.
Definition: eisa.h:44
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition: list.h:45
#define ISA_PROD_ID(product)
Definition: isa_ids.h:45
#define outb(data, io_addr)
Definition: io.h:309
unsigned int bus_type
Bus type.
Definition: device.h:24
#define ENOTTY
Inappropriate I/O control operation.
Definition: errno.h:594
unsigned int device
Device ID.
Definition: device.h:33
#define EISA_MAX_SLOT
Definition: eisa.h:17
struct list_head children
Devices attached to this device.
Definition: device.h:83
#define EISA_DRIVERS
EISA driver table.
Definition: eisa.h:83
struct eisa_device_id * ids
EISA ID table.
Definition: eisa.h:62
struct device_description desc
Device description.
Definition: device.h:79
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition: vsprintf.c:382
#define EISA_CMD_ENABLE
Definition: eisa.h:25
#define EISA_GLOBAL_CONFIG
Definition: eisa.h:22
struct device dev
Generic device.
Definition: eisa.h:40
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
uint16_t prod_id
Product ID.
Definition: eisa.h:48
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
String functions.
static void eisa_remove(struct eisa_device *eisa)
Remove an EISA device.
Definition: eisa.c:85
uint8_t system[ETH_ALEN]
System identifier.
Definition: eth_slow.h:24
void * memset(void *dest, int character, size_t len) __nonnull
#define EISA_SLOT_BASE(n)
Definition: eisa.h:18