summaryrefslogtreecommitdiffstats
path: root/src/include
diff options
context:
space:
mode:
authorMichael Brown2005-04-21 20:18:29 +0200
committerMichael Brown2005-04-21 20:18:29 +0200
commit98ff29345ec0819498f131496db0d96262e3c05f (patch)
tree4b31c4d59e3293d7fc0b35587145a30d1b074f2e /src/include
parentForce a standard format upon debug messages. (diff)
downloadipxe-98ff29345ec0819498f131496db0d96262e3c05f.tar.gz
ipxe-98ff29345ec0819498f131496db0d96262e3c05f.tar.xz
ipxe-98ff29345ec0819498f131496db0d96262e3c05f.zip
Created a bus/device API that allows for the ROM prefix to specify an
initial device, and will also allow for e.g. a device menu to be presented to the user.
Diffstat (limited to 'src/include')
-rw-r--r--src/include/bus.h161
-rw-r--r--src/include/dev.h307
-rw-r--r--src/include/dhcp.h12
-rw-r--r--src/include/isa_ids.h2
-rw-r--r--src/include/mca.h2
-rw-r--r--src/include/nic.h52
-rw-r--r--src/include/pci.h93
7 files changed, 341 insertions, 288 deletions
diff --git a/src/include/bus.h b/src/include/bus.h
deleted file mode 100644
index 80faa0e8..00000000
--- a/src/include/bus.h
+++ /dev/null
@@ -1,161 +0,0 @@
-#ifndef BUS_H
-#define BUS_H
-
-#include "stdint.h"
-
-/*
- * When looking at the following data structures, mentally substitute
- * "<bus>_" in place of "bus_" and everything will become clear.
- * "struct bus_location" becomes "struct <bus>_location", which means
- * "the location of a device on a <bus> bus", where <bus> is a
- * particular type of bus such as "pci" or "isapnp".
- *
- */
-
-/*
- * A physical device location.
- *
- */
-#define BUS_LOCATION_SIZE 4
-struct bus_location {
- char bytes[BUS_LOCATION_SIZE];
-};
-
-/*
- * A structure fully describing a physical device.
- *
- */
-#define BUS_DEVICE_SIZE 32
-struct bus_device {
- char bytes[BUS_DEVICE_SIZE];
-};
-
-/*
- * Individual buses will have different sizes for their <bus>_location
- * and <bus>_device structures. We need to be able to allocate static
- * storage that's large enough to contain these structures for any
- * bus type that's being used in the current binary.
- *
- * We can't just create a union of all the various types, because some
- * may be architecture-dependent (and some are even embedded in
- * specific drivers, e.g. 3c509), so this would quickly get messy.
- *
- * We could use the magic of common symbols. Each bus could declare a
- * common symbol with the name "_bus_device" of the correct size; this
- * is easily done using code like
- * struct pci_device _bus_device;
- * The linker would then use the largest size of the "_bus_device"
- * symbol in any included object, thus giving us a single _bus_device
- * symbol of *exactly* the required size. However, there's no way to
- * extract the size of this symbol, either directly as a linker symbol
- * ("_bus_device_size = SIZEOF(_bus_device)"; the linker language just
- * doesn't provide this construct) or via any linker trickery I can
- * think of (such as creating a special common symbol section just for
- * this symbol then using SIZE(section) to read the size of the
- * section; ld recognises only a single common symbol section called
- * "COMMON").
- *
- * Since there's no way to get the size of the symbol, this
- * effectively limits us to just one instance of the symbol. This is
- * all very well for the simple case of "just boot from any single
- * device you can", but becomes limiting when you want to do things
- * like introducing PCMCIA buses (which must instantiate other devices
- * such as PCMCIA controllers).
- *
- * So, we declare the maximum sizes of these constructions to be
- * compile-time constants. Each individual bus driver should define
- * its own struct <bus>_location and struct <bus>_device however it
- * likes, and can freely cast pointers from struct bus_location to
- * struct <bus>_location (and similarly for bus_device). To guard
- * against bounding errors, each bus driver *MUST* use the macros
- * BUS_LOCATION_CHECK() and BUS_DEVICE_CHECK(), as in:
- *
- * BUS_LOCATION_CHECK ( struct pci_location );
- * BUS_DEVICE_CHECK ( struct pci_device );
- *
- * These macros will generate a link-time error if the size of the
- * <bus> structure exceeds the declared maximum size.
- *
- * The macros will generate no binary object code, but must be placed
- * inside a function (in order to generate syntactically valid C).
- * The easiest wy to do this is to place them in the
- * <bus>_next_location() function.
- *
- * If anyone can think of a better way of doing this that avoids *ALL*
- * of the problems described above, please implement it!
- *
- */
-
-#define LINKER_ASSERT(test,error_symbol) \
- if ( ! (test) ) { \
- extern void error_symbol ( void ); \
- error_symbol(); \
- }
-
-#define BUS_LOCATION_CHECK(datatype) \
- LINKER_ASSERT( ( sizeof (datatype) < sizeof (struct bus_location) ),
- __BUS_LOCATION_SIZE_is_too_small__see_dev_h )
-#define BUS_DEVICE_CHECK(datatype) \
- LINKER_ASSERT( ( sizeof (datatype) < sizeof (struct bus_device) ),
- __BUS_DEVICE_SIZE_is_too_small__see_dev_h )
-
-/*
- * A description of a device. This is used to send information about
- * the device to a DHCP server, and to provide a text string to
- * describe the device to the user.
- *
- * Note that "text" is allowed to be NULL, in which case the
- * describe_device() method will print the information directly to the
- * console rather than writing it into a buffer. (This happens
- * transparently because sprintf(NULL,...) is exactly equivalent to
- * printf(...) in our vsprintf.c).
- *
- */
-struct bus_description {
- char *text;
- uint16_t vendor_id;
- uint16_t device_id;
- uint8_t bus_type;
-};
-
-/*
- * A driver definition
- *
- */
-struct bus_driver;
-
-/*
- * Bus-level operations.
- *
- * int next_location ( struct bus_location * bus_location )
- *
- * Increment bus_location to point to the next possible device on
- * the bus (e.g. the next PCI busdevfn, or the next ISAPnP CSN).
- * If there are no more valid locations, return 0 and leave
- * struct bus_location zeroed, otherwise return true.
- *
- * int fill_device ( struct bus_location *bus_location,
- * struct bus_device *bus_device )
- *
- * Fill out a bus_device structure with the parameters for the
- * device at bus_location. (For example, fill in the PCI vendor
- * and device IDs). Return true if there is a device physically
- * present at this location, otherwise 0.
- *
- * int check_driver ( )
- *
- */
-struct bus_operations {
- int ( *next_location ) ( struct bus_location * bus_location );
- int ( *fill_device ) ( struct bus_location * bus_location,
- struct bus_device * bus_device );
- int ( *check_driver ) ( struct bus_device * bus_device,
- struct bus_driver * bus_driver );
- void ( *describe_device ) ( struct bus_device * bus_device,
- struct bus_driver * bus_driver,
- struct bus_description * bus_description );
-};
-
-
-
-#endif /* BUS_H */
diff --git a/src/include/dev.h b/src/include/dev.h
index 555712aa..327a2714 100644
--- a/src/include/dev.h
+++ b/src/include/dev.h
@@ -2,91 +2,276 @@
#define DEV_H
#include "stdint.h"
+#include "string.h"
+#include "dhcp.h" /* for dhcp_dev_id */
-/* Device types */
-#include "nic.h"
+/*
+ * Forward declarations
+ *
+ */
+struct type_dev;
+struct type_driver;
+struct bus_driver;
+struct bus_dev;
+struct device_driver;
-/* Need to check the packing of this struct if Etherboot is ported */
-struct dev_id {
- uint16_t vendor_id;
- uint16_t device_id;
- uint8_t bus_type;
-#define PCI_BUS_TYPE 1
-#define ISA_BUS_TYPE 2
-#define MCA_BUS_TYPE 3
-} __attribute__ ((packed));
+/*
+ * When looking at the following data structures, mentally substitute
+ * "<bus>_" in place of "bus_" and everything will become clear.
+ * "struct bus_location" becomes "struct <bus>_location", which means
+ * "the location of a device on a <bus> bus", where <bus> is a
+ * particular type of bus such as "pci" or "isapnp".
+ *
+ */
-/* Dont use sizeof, that will include the padding */
-#define DEV_ID_SIZE 8
+/*
+ * A physical device location on a bus.
+ *
+ */
+#define BUS_LOC_SIZE 4
+struct bus_loc {
+ char bytes[BUS_LOC_SIZE];
+};
-struct dev {
- struct dev_operations *dev_op;
- const char *name;
- struct dev_id devid; /* device ID string (sent to DHCP server) */
- struct boot_driver *driver; /* driver being used for boot */
- /* Pointer to bus information for device. Whatever sets up
- * the struct dev must make sure that this points to a buffer
- * large enough for the required struct <bus>_device.
- */
- struct bus_device *bus;
- /* All possible device types */
- union {
- struct nic nic;
- };
+/*
+ * A structure fully describing a physical device on a bus.
+ *
+ */
+#define BUS_DEV_SIZE 32
+struct bus_dev {
+ char bytes[BUS_DEV_SIZE];
};
/*
- * Macro to help create a common symbol with enough space for any
- * struct <bus>_device.
+ * Individual buses will have different sizes for their <bus>_location
+ * and <bus>_device structures. We need to be able to allocate static
+ * storage that's large enough to contain these structures for any
+ * bus type that's being used in the current binary.
+ *
+ * We can't just create a union of all the various types, because some
+ * may be architecture-dependent (and some are even embedded in
+ * specific drivers, e.g. 3c509), so this would quickly get messy.
+ *
+ * We could use the magic of common symbols. Each bus could declare a
+ * common symbol with the name "_bus_dev" of the correct size; this
+ * is easily done using code like
+ * struct pci_device _bus_dev;
+ * The linker would then use the largest size of the "_bus_dev" symbol
+ * in any included object, thus giving us a single _bus_dev symbol of
+ * *exactly* the required size. However, there's no way to extract
+ * the size of this symbol, either directly as a linker symbol
+ * ("_bus_dev_size = SIZEOF(_bus_dev)"; the linker language just
+ * doesn't provide this construct) or via any linker trickery I can
+ * think of (such as creating a special common symbol section just for
+ * this symbol then using SIZE(section) to read the size of the
+ * section; ld recognises only a single common symbol section called
+ * "COMMON").
+ *
+ * Since there's no way to get the size of the symbol, this
+ * effectively limits us to just one instance of the symbol. This is
+ * all very well for the simple case of "just boot from any single
+ * device you can", but becomes limiting when you want to do things
+ * like introducing PCMCIA buses (which must instantiate other devices
+ * such as PCMCIA controllers).
+ *
+ * So, we declare the maximum sizes of these constructions to be
+ * compile-time constants. Each individual bus driver should define
+ * its own struct <bus>_location and struct <bus>_device however it
+ * likes, and can freely cast pointers from struct bus_loc to
+ * struct <bus>_location (and similarly for bus_dev). To guard
+ * against bounding errors, each bus driver *MUST* use the macros
+ * BUS_LOC_CHECK() and BUS_DEV_CHECK(), as in:
+ *
+ * BUS_LOC_CHECK ( struct pci_location );
+ * BUS_DEV_CHECK ( struct pci_device );
+ *
+ * These macros will generate a link-time error if the size of the
+ * <bus> structure exceeds the declared maximum size.
+ *
+ * The macros will generate no binary object code, but must be placed
+ * inside a function (in order to generate syntactically valid C).
+ * The easiest wy to do this is to place them in the
+ * <bus>_next_location() function.
+ *
+ * If anyone can think of a better way of doing this that avoids *ALL*
+ * of the problems described above, please implement it!
*
- * Use as e.g. DEV_BUS(struct pci_device);
*/
-#define DEV_BUS(datatype,symbol) datatype symbol __asm__ ( "_dev_bus" );
-struct dev_operations {
- void ( *disable ) ( struct dev * );
- void ( *print_info ) ( struct dev * );
- int ( *load_configuration ) ( struct dev * );
- int ( *load ) ( struct dev * );
+#define LINKER_ASSERT(test,error_symbol) \
+ if ( ! (test) ) { \
+ extern void error_symbol ( void ); \
+ error_symbol(); \
+ }
+
+#define BUS_LOC_CHECK(datatype) \
+ LINKER_ASSERT( ( sizeof (datatype) < sizeof (struct bus_loc) ), \
+ __BUS_LOC_SIZE_is_too_small__see_dev_h )
+#define BUS_DEV_CHECK(datatype) \
+ LINKER_ASSERT( ( sizeof (datatype) < sizeof (struct bus_dev) ), \
+ __BUS_DEV_SIZE_is_too_small__see_dev_h )
+
+/*
+ * Bus-level operations.
+ *
+ * int next_location ( struct bus_loc * bus_loc )
+ *
+ * Increment bus_loc to point to the next possible device on
+ * the bus (e.g. the next PCI busdevfn, or the next ISAPnP CSN).
+ * If there are no more valid locations, return 0 and leave
+ * struct bus_loc zeroed, otherwise return true.
+ *
+ * int fill_device ( struct bus_dev *bus_dev,
+ * struct bus_loc *bus_loc )
+ *
+ * Fill out a bus_dev structure with the parameters for the
+ * device at bus_loc. (For example, fill in the PCI vendor
+ * and device IDs). Return true if there is a device physically
+ * present at this location, otherwise 0.
+ *
+ * int check_driver ( struct bus_dev *bus_dev,
+ * struct device_driver *device_driver )
+ *
+ * Test whether or not the specified driver is capable of driving
+ * the specified device by, for example, comparing the device's
+ * PCI IDs against the list of PCI IDs claimed by the driver.
+ *
+ * char * describe ( struct bus_dev *bus_dev )
+ *
+ * Return a text string describing the bus device bus_dev
+ * (e.g. "PCI 00:01.2")
+ *
+ * char * name ( struct bus_dev *bus_dev )
+ *
+ * Return a text string describing the bus device bus_dev
+ * (e.g. "dfe538")
+ *
+ */
+struct bus_driver {
+ int ( *next_location ) ( struct bus_loc *bus_loc );
+ int ( *fill_device ) ( struct bus_dev *bus_dev,
+ struct bus_loc *bus_loc );
+ int ( *check_driver ) ( struct bus_dev *bus_dev,
+ struct device_driver *device_driver );
+ char * ( *describe ) ( struct bus_dev *bus_dev );
+ char * ( *name ) ( struct bus_dev *bus_dev );
};
+#define __bus_driver __attribute__ (( used, __section__ ( ".drivers.bus" ) ))
+
/*
- * Table to describe a bootable device driver. See comments in dev.c
- * for an explanation.
+ * A structure fully describing the bus-independent parts of a
+ * particular type (e.g. nic or disk) of device.
+ *
+ * Unlike struct bus_dev, e can limit ourselves to having no more than
+ * one instance of this data structure. We therefore place an
+ * instance in each type driver file (e.g. nic.c), and simply use a
+ * pointer to the struct type_dev in the struct dev.
*
*/
-struct bus_device {};
-struct bus_driver {};
-struct boot_driver {
+struct type_dev;
+
+/*
+ * A type driver (e.g. nic, disk)
+ *
+ */
+struct type_driver {
char *name;
- struct bus_device * ( *find_bus_boot_device ) ( struct dev *dev,
- struct bus_driver *driver );
+ struct type_dev *type_dev; /* single instance */
+ char * ( * describe ) ( struct type_dev *type_dev );
+};
+
+#define __type_driver __attribute__ (( used, __section__ ( ".drivers.type" ) ))
+
+/*
+ * A driver for a device.
+ *
+ */
+struct device_driver {
+ const char *name;
+ struct type_driver *type_driver;
struct bus_driver *bus_driver;
- int ( *probe ) ( struct dev *dev, struct bus_device *bus_device );
+ struct bus_driver_info *bus_driver_info;
+ int ( * probe ) ( struct type_dev *type_dev,
+ struct bus_dev *bus_dev );
+ void ( * disable ) ( struct type_dev *type_dev,
+ struct bus_dev *bus_dev );
};
-#define BOOT_DRIVER( _name, _find_bus_boot_device, _bus_driver, _probe ) \
- static struct boot_driver boot_ ## _bus_driver \
- __attribute__ ((used,__section__(".boot_drivers"))) = { \
- .name = _name, \
- .find_bus_boot_device = ( void * ) _find_bus_boot_device, \
- .bus_driver = ( void * ) &_bus_driver, \
- .probe = ( void * ) _probe, \
+#define __device_driver \
+ __attribute__ (( used, __section__ ( ".drivers.device" ) ))
+
+#define DRIVER(_name,_name_string,_type_driver,_bus_driver,_bus_info, \
+ _probe,_disable) \
+ static struct device_driver _name __device_driver = { \
+ .name = _name_string, \
+ .type_driver = &_type_driver, \
+ .bus_driver = &_bus_driver, \
+ .bus_driver_info = ( struct bus_driver_info * ) &_bus_info, \
+ .probe = ( int (*) () ) _probe, \
+ .disable = ( void (*) () ) _disable, \
};
-/* Functions in dev.c */
+/*
+ * A bootable device, comprising a physical device on a bus, a driver
+ * for that device, and a type device
+ *
+ */
+struct dev {
+ struct bus_driver *bus_driver;
+ struct bus_loc bus_loc;
+ struct bus_dev bus_dev;
+ struct device_driver *device_driver;
+ struct type_driver *type_driver;
+ struct type_dev *type_dev;
+};
+
+/* The current boot device */
+extern struct dev dev;
+
+/*
+ * Functions in dev.c
+ *
+ */
extern void print_drivers ( void );
-extern int find_boot_device ( struct dev *dev );
-extern int probe ( struct dev *dev );
-extern void disable ( struct dev *dev );
-static inline void print_info ( struct dev *dev ) {
- dev->dev_op->print_info ( dev );
+extern int find_any ( struct bus_driver **bus_driver, struct bus_loc *bus_loc,
+ struct bus_dev *bus_dev, signed int skip );
+extern int find_by_device ( struct device_driver **device_driver,
+ struct bus_driver *bus_driver,
+ struct bus_dev *bus_dev,
+ signed int skip );
+extern int find_by_driver ( struct bus_loc *bus_loc, struct bus_dev *bus_dev,
+ struct device_driver *device_driver,
+ signed int skip );
+extern int find_any_with_driver ( struct dev *dev, signed int skip );
+
+/*
+ * Functions inlined to save space
+ *
+ */
+
+/* Probe a device */
+static inline int probe ( struct dev *dev ) {
+ return dev->device_driver->probe ( dev->type_dev, &dev->bus_dev );
}
-static inline int load_configuration ( struct dev *dev ) {
- return dev->dev_op->load_configuration ( dev );
+/* Disable a device */
+static inline void disable ( struct dev *dev ) {
+ dev->device_driver->disable ( dev->type_dev, &dev->bus_dev );
}
-static inline int load ( struct dev *dev ) {
- return dev->dev_op->load ( dev );
+/* Set the default boot device */
+static inline void select_device ( struct dev *dev,
+ struct bus_driver *bus_driver,
+ struct bus_loc *bus_loc ) {
+ dev->bus_driver = bus_driver;
+ memcpy ( &dev->bus_loc, bus_loc, sizeof ( dev->bus_loc ) );
}
+/* Linker symbols for the various tables */
+extern struct bus_driver bus_drivers[];
+extern struct bus_driver bus_drivers_end[];
+extern struct type_driver type_drivers[];
+extern struct type_driver type_drivers_end[];
+extern struct device_driver device_drivers[];
+extern struct device_driver device_drivers_end[];
+
#endif /* DEV_H */
diff --git a/src/include/dhcp.h b/src/include/dhcp.h
new file mode 100644
index 00000000..deba219b
--- /dev/null
+++ b/src/include/dhcp.h
@@ -0,0 +1,12 @@
+#ifndef DHCP_H
+#define DHCP_H
+
+#include "stdint.h"
+
+struct dhcp_dev_id {
+ uint8_t bus_type;
+ uint16_t vendor_id;
+ uint16_t device_id;
+} __attribute__ (( packed ));
+
+#endif /* DHCP_H */
diff --git a/src/include/isa_ids.h b/src/include/isa_ids.h
index f21a093b..7d77f0d8 100644
--- a/src/include/isa_ids.h
+++ b/src/include/isa_ids.h
@@ -19,6 +19,8 @@
#include "stdint.h"
+#define ISA_BUS_TYPE 2
+
/*
* Construct a vendor ID from three ASCII characters
*
diff --git a/src/include/mca.h b/src/include/mca.h
index e5daf715..3b4de21f 100644
--- a/src/include/mca.h
+++ b/src/include/mca.h
@@ -11,6 +11,8 @@
#include "isa_ids.h"
#include "dev.h"
+#define MCA_BUS_TYPE 3
+
/*
* MCA constants
*
diff --git a/src/include/nic.h b/src/include/nic.h
index 02fcafc1..7b12c5be 100644
--- a/src/include/nic.h
+++ b/src/include/nic.h
@@ -8,6 +8,10 @@
#ifndef NIC_H
#define NIC_H
+#include "dev.h"
+#include "byteswap.h"
+#include "dhcp.h"
+
typedef enum {
DISABLE = 0,
ENABLE,
@@ -24,16 +28,17 @@ typedef enum duplex {
* functions.
*/
struct nic {
- struct nic_operations *nic_op;
- int flags; /* driver specific flags */
- unsigned char *node_addr;
- unsigned char *packet;
- unsigned int packetlen;
- unsigned int ioaddr;
- unsigned char irqno;
- unsigned int mbps;
- duplex_t duplex;
- void *priv_data; /* driver can hang private data here */
+ struct nic_operations *nic_op;
+ int flags; /* driver specific flags */
+ unsigned char *node_addr;
+ unsigned char *packet;
+ unsigned int packetlen;
+ unsigned int ioaddr;
+ unsigned char irqno;
+ unsigned int mbps;
+ duplex_t duplex;
+ struct dhcp_dev_id dhcp_dev_id;
+ void *priv_data; /* driver private data */
};
struct nic_operations {
@@ -42,52 +47,43 @@ struct nic_operations {
void ( *transmit ) ( struct nic *, const char *,
unsigned int, unsigned int, const char * );
void ( *irq ) ( struct nic *, irq_action_t );
- void ( *disable ) ( struct nic * );
};
+extern struct type_driver nic_driver;
+
/*
* Function prototypes
*
*/
-struct dev;
-extern struct nic * nic_device ( struct dev * dev );
extern int dummy_connect ( struct nic *nic );
extern void dummy_irq ( struct nic *nic, irq_action_t irq_action );
+extern void nic_disable ( struct nic *nic );
/*
* Functions that implicitly operate on the current boot device
*
- * "nic" always points to &dev.nic
*/
-extern struct nic *nic;
+extern struct nic nic;
static inline int eth_connect ( void ) {
- return nic->nic_op->connect ( nic );
+ return nic.nic_op->connect ( &nic );
}
static inline int eth_poll ( int retrieve ) {
- return nic->nic_op->poll ( nic, retrieve );
+ return nic.nic_op->poll ( &nic, retrieve );
}
static inline void eth_transmit ( const char *dest, unsigned int type,
unsigned int size, const void *packet ) {
- nic->nic_op->transmit ( nic, dest, type, size, packet );
+ nic.nic_op->transmit ( &nic, dest, type, size, packet );
}
static inline void eth_irq ( irq_action_t action ) {
- nic->nic_op->irq ( nic, action );
+ nic.nic_op->irq ( &nic, action );
}
/* Should be using disable() rather than eth_disable() */
-static inline void eth_disable ( void ) __attribute__ (( deprecated ));
-static inline void eth_disable ( void ) {
- nic->nic_op->disable ( nic );
-}
-
-/* dev.h needs declarations from nic.h */
-#include "dev.h"
-/* to get global "dev" */
-#include "main.h"
+extern void eth_disable ( void ) __attribute__ (( deprecated ));
#endif /* NIC_H */
diff --git a/src/include/pci.h b/src/include/pci.h
index fd6ac9ba..f904504f 100644
--- a/src/include/pci.h
+++ b/src/include/pci.h
@@ -22,8 +22,10 @@
*/
#include "stdint.h"
+#include "nic.h"
#include "pci_ids.h"
-#include "dev.h"
+
+#define PCI_BUS_TYPE 1
/*
* PCI constants
@@ -234,32 +236,44 @@
#define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */
#define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */
/*
- * A physical PCI device
+ * A location on a PCI bus
*
*/
-struct pci_device {
- char * magic; /* must be first */
- const char * name;
- uint32_t membase; /* BAR 1 */
- uint32_t ioaddr; /* first IO BAR */
- uint16_t vendor, dev_id;
- uint16_t class;
+struct pci_loc {
uint16_t busdevfn;
- uint8_t revision;
- uint8_t irq;
- uint8_t already_tried;
};
+
+/*
+ * A physical PCI device
+ *
+ */
+struct pci_device {
+ const char * name;
+ uint32_t membase; /* BAR 1 */
+ uint32_t ioaddr; /* first IO BAR */
+ uint16_t vendor_id, device_id;
+ uint16_t class;
+ uint16_t busdevfn;
+ uint8_t revision;
+ uint8_t irq;
+} __attribute__ (( packed ));
+
+/*
+ * Useful busdevfn calculations
+ *
+ */
#define PCI_BUS(busdevfn) ( ( uint8_t ) ( ( (busdevfn) >> 8 ) & 0xff ) )
#define PCI_DEV(busdevfn) ( ( uint8_t ) ( ( (busdevfn) >> 3 ) & 0x1f ) )
#define PCI_FUNC(busdevfn) ( ( uint8_t ) ( (busdevfn) & 0x07 ) )
#define PCI_FN0(busdevfn) ( ( uint16_t ) ( (busdevfn) & 0xfff8 ) )
+#define PCI_MAX_BUSDEVFN 0xffff
/*
* An individual PCI device identified by vendor and device IDs
*
*/
struct pci_id {
- unsigned short vendor, dev_id;
+ unsigned short vendor_id, device_id;
const char *name;
};
@@ -268,24 +282,23 @@ struct pci_id {
* is also parsed by parserom.pl to generate Makefile rules and files
* for rom-o-matic.
*/
-#define PCI_ROM( rom_vendor, rom_dev_id, rom_name, rom_description ) { \
- .vendor = rom_vendor, \
- .dev_id = rom_dev_id, \
- .name = rom_name, \
+#define PCI_ROM( _vendor_id, _device_id, _name, _description ) { \
+ .vendor_id = _vendor_id, \
+ .device_id = _device_id, \
+ .name = _name, \
}
/*
- * A PCI driver, with a device ID (struct pci_id) table and an
- * optional class.
+ * A PCI driver information table, with a device ID (struct pci_id)
+ * table and an optional class.
*
* Set the class to something other than PCI_NO_CLASS if the driver
* can handle an entire class of devices.
*
*/
-struct pci_driver {
- const char *name;
+struct pci_driver_info {
struct pci_id *ids;
- int id_count;
+ unsigned int id_count;
uint16_t class;
};
#define PCI_NO_CLASS 0
@@ -294,30 +307,30 @@ struct pci_driver {
* Define a PCI driver.
*
*/
-#define PCI_DRIVER( driver_name, pci_ids, pci_class ) { \
- .name = driver_name, \
- .ids = pci_ids, \
- .id_count = sizeof ( pci_ids ) / sizeof ( pci_ids[0] ), \
- .class = pci_class, \
-}
+#define PCI_DRIVER( _info_name, _ids, _class ) \
+ static struct pci_driver_info _info_name = { \
+ .ids = _ids, \
+ .id_count = sizeof ( _ids ) / sizeof ( _ids[0] ), \
+ .class = _class, \
+ };
/*
* These are the functions we expect pci_io.c to provide.
*
*/
-extern int pci_read_config_byte ( struct pci_device *dev, unsigned int where,
+extern int pci_read_config_byte ( struct pci_device *pci, unsigned int where,
uint8_t *value );
-extern int pci_write_config_byte ( struct pci_device *dev, unsigned int where,
+extern int pci_write_config_byte ( struct pci_device *pci, unsigned int where,
uint8_t value );
-extern int pci_read_config_word ( struct pci_device *dev, unsigned int where,
+extern int pci_read_config_word ( struct pci_device *pci, unsigned int where,
uint16_t *value );
-extern int pci_write_config_word ( struct pci_device *dev, unsigned int where,
+extern int pci_write_config_word ( struct pci_device *pci, unsigned int where,
uint16_t value );
-extern int pci_read_config_dword ( struct pci_device *dev, unsigned int where,
+extern int pci_read_config_dword ( struct pci_device *pci, unsigned int where,
uint32_t *value );
-extern int pci_write_config_dword ( struct pci_device *dev, unsigned int where,
+extern int pci_write_config_dword ( struct pci_device *pci, unsigned int where,
uint32_t value );
-extern unsigned long pci_bus_base ( struct pci_device *dev );
+extern unsigned long pci_bus_base ( struct pci_device *pci );
/*
* pci_io.c is allowed to overwrite pci_max_bus if it knows what the
@@ -330,13 +343,17 @@ extern unsigned int pci_max_bus;
* Functions in pci.c
*
*/
-extern int find_pci_device ( struct pci_device *pci,
- struct pci_driver *driver );
-extern int find_pci_boot_device ( struct dev *dev, struct pci_driver *driver );
extern void adjust_pci_device ( struct pci_device *pci );
extern unsigned long pci_bar_start ( struct pci_device *pci,
unsigned int bar );
extern unsigned long pci_bar_size ( struct pci_device *pci, unsigned int bar );
extern int pci_find_capability ( struct pci_device *pci, int capability );
+extern void pci_fill_nic ( struct nic *nic, struct pci_device *pci );
+
+/*
+ * PCI bus global definition
+ *
+ */
+extern struct bus_driver pci_driver;
#endif /* PCI_H */