diff options
author | Michael Brown | 2005-04-21 20:18:29 +0200 |
---|---|---|
committer | Michael Brown | 2005-04-21 20:18:29 +0200 |
commit | 98ff29345ec0819498f131496db0d96262e3c05f (patch) | |
tree | 4b31c4d59e3293d7fc0b35587145a30d1b074f2e /src/include | |
parent | Force a standard format upon debug messages. (diff) | |
download | ipxe-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.h | 161 | ||||
-rw-r--r-- | src/include/dev.h | 307 | ||||
-rw-r--r-- | src/include/dhcp.h | 12 | ||||
-rw-r--r-- | src/include/isa_ids.h | 2 | ||||
-rw-r--r-- | src/include/mca.h | 2 | ||||
-rw-r--r-- | src/include/nic.h | 52 | ||||
-rw-r--r-- | src/include/pci.h | 93 |
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 */ |