From fdc97499bf83ef958db8a50985fdd321835dccf3 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 10 Jan 2007 15:27:48 +0000 Subject: [PATCH] Add device description fields to struct device. --- src/arch/i386/core/pcibios.c | 4 +-- src/arch/i386/drivers/net/undi.c | 3 +- src/arch/i386/drivers/net/undiload.c | 4 +-- src/arch/i386/drivers/net/undionly.c | 34 ++++++++++++++------ src/arch/i386/include/undi.h | 25 +++++++++++++-- src/arch/i386/include/undiload.h | 4 +-- src/arch/i386/prefix/pxeprefix.S | 7 +++- src/drivers/bus/pci.c | 4 +++ src/include/gpxe/device.h | 48 ++++++++++++++++++++++++++++ src/include/gpxe/pci.h | 7 ++-- 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 #include +/** 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 )