iPXE
mca.c
Go to the documentation of this file.
1 /*
2  * MCA bus driver code
3  *
4  * Abstracted from 3c509.c.
5  *
6  */
7 
8 FILE_LICENCE ( BSD2 );
9 
10 #include <stdint.h>
11 #include <string.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <errno.h>
15 #include <ipxe/io.h>
16 #include <ipxe/mca.h>
17 
18 static void mcabus_remove ( struct root_device *rootdev );
19 
20 /**
21  * Probe an MCA device
22  *
23  * @v mca MCA device
24  * @ret rc Return status code
25  *
26  * Searches for a driver for the MCA device. If a driver is found,
27  * its probe() routine is called.
28  */
29 static int mca_probe ( struct mca_device *mca ) {
30  struct mca_driver *driver;
31  struct mca_device_id *id;
32  unsigned int i;
33  int rc;
34 
35  DBG ( "Adding MCA slot %02x (ID %04x POS "
36  "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x)\n",
37  mca->slot, MCA_ID ( mca ),
38  mca->pos[0], mca->pos[1], mca->pos[2], mca->pos[3],
39  mca->pos[4], mca->pos[5], mca->pos[6], mca->pos[7] );
40 
41  for_each_table_entry ( driver, MCA_DRIVERS ) {
42  for ( i = 0 ; i < driver->id_count ; i++ ) {
43  id = &driver->ids[i];
44  if ( id->id != MCA_ID ( mca ) )
45  continue;
46  mca->driver = driver;
47  mca->dev.driver_name = id->name;
48  DBG ( "...using driver %s\n", mca->dev.driver_name );
49  if ( ( rc = driver->probe ( mca, id ) ) != 0 ) {
50  DBG ( "......probe failed\n" );
51  continue;
52  }
53  return 0;
54  }
55  }
56 
57  DBG ( "...no driver found\n" );
58  return -ENOTTY;
59 }
60 
61 /**
62  * Remove an MCA device
63  *
64  * @v mca MCA device
65  */
66 static void mca_remove ( struct mca_device *mca ) {
67  mca->driver->remove ( mca );
68  DBG ( "Removed MCA device %02x\n", mca->slot );
69 }
70 
71 /**
72  * Probe MCA root bus
73  *
74  * @v rootdev MCA bus root device
75  *
76  * Scans the MCA bus for devices and registers all devices it can
77  * find.
78  */
79 static int mcabus_probe ( struct root_device *rootdev ) {
80  struct mca_device *mca = NULL;
81  unsigned int slot;
82  int seen_non_ff;
83  unsigned int i;
84  int rc;
85 
86  for ( slot = 0 ; slot <= MCA_MAX_SLOT_NR ; slot++ ) {
87  /* Allocate struct mca_device */
88  if ( ! mca )
89  mca = malloc ( sizeof ( *mca ) );
90  if ( ! mca ) {
91  rc = -ENOMEM;
92  goto err;
93  }
94  memset ( mca, 0, sizeof ( *mca ) );
95  mca->slot = slot;
96 
97  /* Make sure motherboard setup is off */
99 
100  /* Select the slot */
101  outb_p ( 0x8 | ( mca->slot & 0xf ), MCA_ADAPTER_SETUP_REG );
102 
103  /* Read the POS registers */
104  seen_non_ff = 0;
105  for ( i = 0 ; i < ( sizeof ( mca->pos ) /
106  sizeof ( mca->pos[0] ) ) ; i++ ) {
107  mca->pos[i] = inb_p ( MCA_POS_REG ( i ) );
108  if ( mca->pos[i] != 0xff )
109  seen_non_ff = 1;
110  }
111 
112  /* Kill all setup modes */
114 
115  /* If all POS registers are 0xff, this means there's no device
116  * present
117  */
118  if ( ! seen_non_ff )
119  continue;
120 
121  /* Add to device hierarchy */
122  snprintf ( mca->dev.name, sizeof ( mca->dev.name ),
123  "MCA%02x", slot );
124  mca->dev.desc.bus_type = BUS_TYPE_MCA;
126  mca->dev.desc.device = MCA_ID ( mca );
127  mca->dev.parent = &rootdev->dev;
128  list_add ( &mca->dev.siblings, &rootdev->dev.children );
129  INIT_LIST_HEAD ( &mca->dev.children );
130 
131  /* Look for a driver */
132  if ( mca_probe ( mca ) == 0 ) {
133  /* mcadev registered, we can drop our ref */
134  mca = NULL;
135  } else {
136  /* Not registered; re-use struct */
137  list_del ( &mca->dev.siblings );
138  }
139  }
140 
141  free ( mca );
142  return 0;
143 
144  err:
145  free ( mca );
146  mcabus_remove ( rootdev );
147  return rc;
148 }
149 
150 /**
151  * Remove MCA root bus
152  *
153  * @v rootdev MCA bus root device
154  */
155 static void mcabus_remove ( struct root_device *rootdev ) {
156  struct mca_device *mca;
157  struct mca_device *tmp;
158 
159  list_for_each_entry_safe ( mca, tmp, &rootdev->dev.children,
160  dev.siblings ) {
161  mca_remove ( mca );
162  list_del ( &mca->dev.siblings );
163  free ( mca );
164  }
165 }
166 
167 /** MCA bus root device driver */
168 static struct root_driver mca_root_driver = {
169  .probe = mcabus_probe,
170  .remove = mcabus_remove,
171 };
172 
173 /** MCA bus root device */
174 struct root_device mca_root_device __root_device = {
175  .dev = { .name = "MCA" },
176  .driver = &mca_root_driver,
177 };
iPXE I/O API
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
static void mca_remove(struct mca_device *mca)
Remove an MCA device.
Definition: mca.c:66
#define MCA_DRIVERS
MCA driver table.
Definition: mca.h:81
#define outb_p(data, io_addr)
Write byte to I/O-mapped device, slowly.
Definition: io.h:461
struct device dev
Generic device.
Definition: mca.h:40
#define list_add(new, head)
Add a new entry to the head of a list.
Definition: list.h:69
static void mcabus_remove(struct root_device *rootdev)
Remove MCA root bus.
Definition: mca.c:155
Error codes.
#define GENERIC_MCA_VENDOR
Definition: mca.h:27
struct mca_driver * driver
Driver for this device.
Definition: mca.h:46
FILE_LICENCE(BSD2)
char name[40]
Name.
Definition: device.h:75
A root device.
Definition: device.h:94
An MCA driver.
Definition: mca.h:58
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
#define BUS_TYPE_MCA
MCA bus type.
Definition: device.h:52
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
#define inb_p(io_addr)
Read byte from I/O-mapped device.
Definition: io.h:425
#define ENOMEM
Not enough space.
Definition: errno.h:534
int(* probe)(struct mca_device *mca, const struct mca_device_id *id)
Probe device.
Definition: mca.h:70
static int mca_probe(struct mca_device *mca)
Probe an MCA device.
Definition: mca.c:29
static int mcabus_probe(struct root_device *rootdev)
Probe MCA root bus.
Definition: mca.c:79
An MCA device.
Definition: mca.h:38
#define MCA_MOTHERBOARD_SETUP_REG
Definition: mca.h:21
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
uint8_t id
Request identifier.
Definition: ena.h:12
unsigned char pos[8]
POS register values.
Definition: mca.h:44
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:358
#define MCA_ADAPTER_SETUP_REG
Definition: mca.h:22
A root device driver.
Definition: device.h:107
#define MCA_MAX_SLOT_NR
Definition: mca.h:23
unsigned int id_count
Number of entries in MCA ID table.
Definition: mca.h:62
#define MCA_ID(mca)
Definition: mca.h:55
uint8_t slot
Slot.
Definition: edd.h:16
int(* probe)(struct root_device *rootdev)
Add root device.
Definition: device.h:116
void * malloc(size_t size)
Allocate memory.
Definition: malloc.c:583
struct mca_device_id * ids
MCA ID table.
Definition: mca.h:60
static struct root_driver mca_root_driver
MCA bus root device driver.
Definition: mca.c:168
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition: list.h:45
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
struct list_head children
Devices attached to this device.
Definition: device.h:83
unsigned int slot
Slot number.
Definition: mca.h:42
struct root_device mca_root_device __root_device
MCA bus root device.
Definition: mca.c:174
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
An MCA device ID list entry.
Definition: mca.h:30
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
#define MCA_POS_REG(n)
Definition: mca.h:24
String functions.
void * memset(void *dest, int character, size_t len) __nonnull
void(* remove)(struct mca_device *mca)
Remove device.
Definition: mca.h:77