summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/arch/i386/core/pcibios.c4
-rw-r--r--src/arch/i386/drivers/net/undi.c3
-rw-r--r--src/arch/i386/drivers/net/undiload.c4
-rw-r--r--src/arch/i386/drivers/net/undionly.c34
-rw-r--r--src/arch/i386/include/undi.h25
-rw-r--r--src/arch/i386/include/undiload.h4
-rw-r--r--src/arch/i386/prefix/pxeprefix.S7
-rw-r--r--src/drivers/bus/pci.c4
-rw-r--r--src/include/gpxe/device.h48
-rw-r--r--src/include/gpxe/pci.h7
10 files changed, 116 insertions, 24 deletions
diff --git a/src/arch/i386/core/pcibios.c b/src/arch/i386/core/pcibios.c
index a4f61b71..1c93e4be 100644
--- a/src/arch/i386/core/pcibios.c
+++ b/src/arch/i386/core/pcibios.c
@@ -72,7 +72,7 @@ int pcibios_read ( struct pci_device *pci, uint32_t command, uint32_t *value ){
: "=a" ( status ), "=b" ( discard_b ),
"=c" ( *value ), "=D" ( discard_D )
: "a" ( command >> 16 ), "D" ( command ),
- "b" ( ( pci->bus << 8 ) | pci->devfn )
+ "b" ( PCI_BUSDEVFN ( pci->bus, pci->devfn ) )
: "edx" );
return ( ( status >> 8 ) & 0xff );
@@ -98,7 +98,7 @@ int pcibios_write ( struct pci_device *pci, uint32_t command, uint32_t value ){
: "=a" ( status ), "=b" ( discard_b ),
"=c" ( discard_c ), "=D" ( discard_D )
: "a" ( command >> 16 ), "D" ( command ),
- "b" ( ( pci->bus << 8 ) | pci->devfn ),
+ "b" ( PCI_BUSDEVFN ( pci->bus, pci->devfn ) ),
"c" ( value )
: "edx" );
diff --git a/src/arch/i386/drivers/net/undi.c b/src/arch/i386/drivers/net/undi.c
index 492e8fa0..c93ad247 100644
--- a/src/arch/i386/drivers/net/undi.c
+++ b/src/arch/i386/drivers/net/undi.c
@@ -64,7 +64,7 @@ static int undipci_probe ( struct pci_device *pci,
const struct pci_device_id *id __unused ) {
struct undi_device *undi;
struct undi_rom *undirom;
- unsigned int busdevfn = ( ( pci->bus << 8 ) | pci->devfn );
+ unsigned int busdevfn = PCI_BUSDEVFN ( pci->bus, pci->devfn );
int rc;
/* Ignore non-network devices */
@@ -99,6 +99,7 @@ static int undipci_probe ( struct pci_device *pci,
/* Add to device hierarchy */
snprintf ( undi->dev.name, sizeof ( undi->dev.name ),
"UNDI-%s", pci->dev.name );
+ memcpy ( &undi->dev.desc, &pci->dev.desc, sizeof ( undi->dev.desc ) );
undi->dev.parent = &pci->dev;
INIT_LIST_HEAD ( &undi->dev.children );
list_add ( &undi->dev.siblings, &pci->dev.children );
diff --git a/src/arch/i386/drivers/net/undiload.c b/src/arch/i386/drivers/net/undiload.c
index 27f26526..70008a49 100644
--- a/src/arch/i386/drivers/net/undiload.c
+++ b/src/arch/i386/drivers/net/undiload.c
@@ -76,13 +76,13 @@ int undi_load ( struct undi_device *undi, struct undi_rom *undirom ) {
/* Debug info */
DBGC ( undi, "UNDI %p loading UNDI ROM %p to CS %04x DS %04x for ",
undi, undirom, undi_loader.UNDI_CS, undi_loader.UNDI_DS );
- if ( undi->pci_busdevfn != 0xffff ) {
+ if ( undi->pci_busdevfn != UNDI_NO_PCI_BUSDEVFN ) {
unsigned int bus = ( undi->pci_busdevfn >> 8 );
unsigned int devfn = ( undi->pci_busdevfn & 0xff );
DBGC ( undi, "PCI %02x:%02x.%x\n",
bus, PCI_SLOT ( devfn ), PCI_FUNC ( devfn ) );
}
- if ( undi->isapnp_csn != 0xffff ) {
+ if ( undi->isapnp_csn != UNDI_NO_ISAPNP_CSN ) {
DBGC ( undi, "ISAPnP(%04x) CSN %04x\n",
undi->isapnp_read_port, undi->isapnp_csn );
}
diff --git a/src/arch/i386/drivers/net/undionly.c b/src/arch/i386/drivers/net/undionly.c
index bd53e1d3..d9558417 100644
--- a/src/arch/i386/drivers/net/undionly.c
+++ b/src/arch/i386/drivers/net/undionly.c
@@ -49,29 +49,41 @@
* find.
*/
static int undibus_probe ( struct root_device *rootdev ) {
+ struct undi_device *undi = &preloaded_undi;
int rc;
/* Check for a valie preloaded UNDI device */
- if ( ! preloaded_undi.entry.segment ) {
+ if ( ! undi->entry.segment ) {
DBG ( "No preloaded UNDI device found!\n" );
return -ENODEV;
}
/* Add to device hierarchy */
- strncpy ( preloaded_undi.dev.name, "UNDI",
- ( sizeof ( preloaded_undi.dev.name ) - 1 ) );
- preloaded_undi.dev.parent = &rootdev->dev;
- list_add ( &preloaded_undi.dev.siblings, &rootdev->dev.children);
- INIT_LIST_HEAD ( &preloaded_undi.dev.children );
+ strncpy ( undi->dev.name, "UNDI",
+ ( sizeof ( undi->dev.name ) - 1 ) );
+ if ( undi->pci_busdevfn != UNDI_NO_PCI_BUSDEVFN ) {
+ struct pci_device_description *pcidesc = &undi->dev.desc.pci;
+ pcidesc->bus_type = BUS_TYPE_PCI;
+ pcidesc->busdevfn = undi->pci_busdevfn;
+ pcidesc->vendor = undi->pci_vendor;
+ pcidesc->device = undi->pci_device;
+ } else if ( undi->isapnp_csn != UNDI_NO_ISAPNP_CSN ) {
+ struct isapnp_device_description *isapnpdesc
+ = &undi->dev.desc.isapnp;
+ isapnpdesc->bus_type = BUS_TYPE_ISAPNP;
+ }
+ undi->dev.parent = &rootdev->dev;
+ list_add ( &undi->dev.siblings, &rootdev->dev.children);
+ INIT_LIST_HEAD ( &undi->dev.children );
/* Create network device */
- if ( ( rc = undinet_probe ( &preloaded_undi ) ) != 0 )
+ if ( ( rc = undinet_probe ( undi ) ) != 0 )
goto err;
return 0;
err:
- list_del ( &preloaded_undi.dev.siblings );
+ list_del ( &undi->dev.siblings );
return rc;
}
@@ -81,8 +93,10 @@ static int undibus_probe ( struct root_device *rootdev ) {
* @v rootdev UNDI bus root device
*/
static void undibus_remove ( struct root_device *rootdev __unused ) {
- undinet_remove ( &preloaded_undi );
- list_del ( &preloaded_undi.dev.siblings );
+ struct undi_device *undi = &preloaded_undi;
+
+ undinet_remove ( undi );
+ list_del ( &undi->dev.siblings );
}
/** UNDI bus root device driver */
diff --git a/src/arch/i386/include/undi.h b/src/arch/i386/include/undi.h
index e2e3c1d5..f6e22e70 100644
--- a/src/arch/i386/include/undi.h
+++ b/src/arch/i386/include/undi.h
@@ -26,12 +26,22 @@ struct undi_device {
UINT16_t fbms;
/** Free base memory prior to load */
UINT16_t restore_fbms;
- /** PCI bus:dev.fn, or 0xffff */
+ /** PCI bus:dev.fn, or @c UNDI_NO_PCI_BUSDEVFN */
UINT16_t pci_busdevfn;
- /** ISAPnP card select number, or 0xffff */
+ /** ISAPnP card select number, or @c UNDI_NO_ISAPNP_CSN */
UINT16_t isapnp_csn;
- /** ISAPnP read port, or 0xffff */
+ /** ISAPnP read port, or @c UNDI_NO_ISAPNP_READ_PORT */
UINT16_t isapnp_read_port;
+ /** PCI vendor ID
+ *
+ * Filled in only for the preloaded UNDI device by pxeprefix.S
+ */
+ UINT16_t pci_vendor;
+ /** PCI device ID
+ *
+ * Filled in only for the preloaded UNDI device by pxeprefix.S
+ */
+ UINT16_t pci_device;
/** Padding */
UINT16_t pad;
@@ -45,6 +55,15 @@ struct undi_device {
void *priv;
} __attribute__ (( packed ));
+/** PCI bus:dev.fn field is invalid */
+#define UNDI_NO_PCI_BUSDEVFN 0xffff
+
+/** ISAPnP card select number field is invalid */
+#define UNDI_NO_ISAPNP_CSN 0xffff
+
+/** ISAPnP read port field is invalid */
+#define UNDI_NO_ISAPNP_READ_PORT 0xffff
+
/**
* Set UNDI driver-private data
*
diff --git a/src/arch/i386/include/undiload.h b/src/arch/i386/include/undiload.h
index e42563b4..bfc11874 100644
--- a/src/arch/i386/include/undiload.h
+++ b/src/arch/i386/include/undiload.h
@@ -25,8 +25,8 @@ static inline int undi_load_pci ( struct undi_device *undi,
struct undi_rom *undirom,
unsigned int pci_busdevfn ) {
undi->pci_busdevfn = pci_busdevfn;
- undi->isapnp_csn = 0xffff;
- undi->isapnp_read_port = 0xffff;
+ undi->isapnp_csn = UNDI_NO_ISAPNP_CSN;
+ undi->isapnp_read_port = UNDI_NO_ISAPNP_READ_PORT;
return undi_load ( undi, undirom );
}
diff --git a/src/arch/i386/prefix/pxeprefix.S b/src/arch/i386/prefix/pxeprefix.S
index 55a228ff..8c091df6 100644
--- a/src/arch/i386/prefix/pxeprefix.S
+++ b/src/arch/i386/prefix/pxeprefix.S
@@ -220,7 +220,9 @@ get_physical_device:
jmp no_physical_device
pci_physical_device:
- /* Record PCI bus:dev.fn */
+ /* Record PCI bus:dev.fn and vendor/device IDs */
+ movl ( pxe_parameter_structure + 0x03 ), %eax
+ movl %eax, pci_vendor
movw ( pxe_parameter_structure + 0x0b ), %ax
movw %ax, pci_busdevfn
movw $10f, %si
@@ -680,6 +682,9 @@ pci_busdevfn: .word 0xffff
isapnp_csn: .word 0xffff
isapnp_read_port: .word 0xffff
+pci_vendor: .word 0
+pci_device: .word 0
+
.equ undi_device_size, ( . - undi_device )
/*****************************************************************************
diff --git a/src/drivers/bus/pci.c b/src/drivers/bus/pci.c
index 11a8e0a0..56436b7d 100644
--- a/src/drivers/bus/pci.c
+++ b/src/drivers/bus/pci.c
@@ -282,6 +282,10 @@ static int pcibus_probe ( struct root_device *rootdev ) {
snprintf ( pci->dev.name, sizeof ( pci->dev.name ),
"PCI%02x:%02x.%x", bus,
PCI_SLOT ( devfn ), PCI_FUNC ( devfn ) );
+ pci->dev.desc.bus_type = BUS_TYPE_PCI;
+ pci->dev.desc.pci.busdevfn = PCI_BUSDEVFN (bus, devfn);
+ pci->dev.desc.pci.vendor = pci->vendor;
+ pci->dev.desc.pci.device = pci->device;
pci->dev.parent = &rootdev->dev;
list_add ( &pci->dev.siblings, &rootdev->dev.children);
INIT_LIST_HEAD ( &pci->dev.children );
diff --git a/src/include/gpxe/device.h b/src/include/gpxe/device.h
index 9f670cfd..139fb78b 100644
--- a/src/include/gpxe/device.h
+++ b/src/include/gpxe/device.h
@@ -11,10 +11,58 @@
#include <gpxe/list.h>
#include <gpxe/tables.h>
+/** A PCI device description */
+struct pci_device_description {
+ /** Bus type
+ *
+ * Must be @c BUS_TYPE_PCI.
+ */
+ unsigned int bus_type;
+ /** Bus:dev.fn address
+ *
+ * As constructed by PCI_BUSDEVFN().
+ */
+ unsigned int busdevfn;
+ /** Vendor ID */
+ unsigned int vendor;
+ /** Device ID */
+ unsigned int device;
+};
+
+/** PCI bus type */
+#define BUS_TYPE_PCI 1
+
+/** An ISAPnP device description */
+struct isapnp_device_description {
+ /** Bus type
+ *
+ * Must be @c BUS_TYPE_ISAPNP.
+ */
+ unsigned int bus_type;
+};
+
+/** PCI bus type */
+#define BUS_TYPE_ISAPNP 2
+
+/** A hardware device description */
+union device_description {
+ /** Bus type
+ *
+ * This must be a BUS_TYPE_XXX constant.
+ */
+ unsigned int bus_type;
+ /** PCI device description */
+ struct pci_device_description pci;
+ /** ISAPnP device description */
+ struct isapnp_device_description isapnp;
+};
+
/** A hardware device */
struct device {
/** Name */
char name[16];
+ /** Device description */
+ union device_description desc;
/** Devices on the same bus */
struct list_head siblings;
/** Devices attached to this device */
diff --git a/src/include/gpxe/pci.h b/src/include/gpxe/pci.h
index 8269dfaa..eaa1560b 100644
--- a/src/include/gpxe/pci.h
+++ b/src/include/gpxe/pci.h
@@ -307,9 +307,10 @@ struct pci_driver {
/** Declare a PCI driver */
#define __pci_driver __table ( struct pci_driver, pci_drivers, 01 )
-#define PCI_DEVFN( slot, func ) ( ( (slot) << 3 ) | (func) )
-#define PCI_SLOT( devfn ) ( ( (devfn) >> 3 ) & 0x1f )
-#define PCI_FUNC( devfn ) ( (devfn) & 0x07 )
+#define PCI_DEVFN( slot, func ) ( ( (slot) << 3 ) | (func) )
+#define PCI_SLOT( devfn ) ( ( (devfn) >> 3 ) & 0x1f )
+#define PCI_FUNC( devfn ) ( (devfn) & 0x07 )
+#define PCI_BUSDEVFN( bus, devfn ) ( ( (bus) << 8 ) | (devfn) )
#define PCI_BASE_CLASS( class ) ( (class) >> 16 )