diff options
| author | Michael Brown | 2007-01-09 03:32:06 +0100 |
|---|---|---|
| committer | Michael Brown | 2007-01-09 03:32:06 +0100 |
| commit | f2f492a536f8efd3301414ac769534ecdd834725 (patch) | |
| tree | 455aff01285d214c9ddae57c0c7021de812782de /src/arch/i386/drivers/net | |
| parent | Populate preloaded_undi device when applicable. (diff) | |
| download | ipxe-f2f492a536f8efd3301414ac769534ecdd834725.tar.gz ipxe-f2f492a536f8efd3301414ac769534ecdd834725.tar.xz ipxe-f2f492a536f8efd3301414ac769534ecdd834725.zip | |
If preloaded device matches, use that rather than going via the UNDI
loader.
Diffstat (limited to 'src/arch/i386/drivers/net')
| -rw-r--r-- | src/arch/i386/drivers/net/undi.c | 67 |
1 files changed, 46 insertions, 21 deletions
diff --git a/src/arch/i386/drivers/net/undi.c b/src/arch/i386/drivers/net/undi.c index 354a07f7c..a6f1267bc 100644 --- a/src/arch/i386/drivers/net/undi.c +++ b/src/arch/i386/drivers/net/undi.c @@ -24,6 +24,7 @@ #include <undirom.h> #include <undiload.h> #include <undinet.h> +#include <undipreload.h> /** @file * @@ -32,34 +33,43 @@ */ /** + * Find UNDI ROM for PCI device + * + * @v pci PCI device + * @ret undirom UNDI ROM, or NULL + * + * Try to find a driver for this device. Try an exact match on the + * ROM address first, then fall back to a vendor/device ID match only + */ +static struct undi_rom * undipci_find_rom ( struct pci_device *pci ) { + struct undi_rom *undirom; + unsigned long rombase; + + rombase = pci_bar_start ( pci, PCI_ROM_ADDRESS ); + undirom = undirom_find_pci ( pci->vendor, pci->device, rombase ); + if ( ! undirom ) + undirom = undirom_find_pci ( pci->vendor, pci->device, 0 ); + return undirom; +} + +/** * Probe PCI device * - * @v pci PCI device - * @v id PCI ID - * @ret rc Return status code + * @v pci PCI device + * @v id PCI ID + * @ret rc Return status code */ static int undipci_probe ( struct pci_device *pci, const struct pci_device_id *id __unused ) { struct undi_device *undi; struct undi_rom *undirom; - unsigned long rombase; + unsigned int busdevfn = ( ( pci->bus << 8 ) | pci->devfn ); int rc; /* Ignore non-network devices */ if ( PCI_BASE_CLASS ( pci->class ) != PCI_BASE_CLASS_NETWORK ) return -ENOTTY; - /* Try to find a driver for this device. Try an exact match - * on the ROM address first, then fall back to a vendor/device - * ID match only - */ - rombase = pci_bar_start ( pci, PCI_ROM_ADDRESS ); - undirom = undirom_find_pci ( pci->vendor, pci->device, rombase ); - if ( ! undirom ) - undirom = undirom_find_pci ( pci->vendor, pci->device, 0 ); - if ( ! undirom ) - return -ENODEV; - /* Allocate UNDI device structure */ undi = malloc ( sizeof ( *undi ) ); if ( ! undi ) @@ -67,16 +77,30 @@ static int undipci_probe ( struct pci_device *pci, memset ( undi, 0, sizeof ( *undi ) ); pci_set_drvdata ( pci, undi ); + /* Find/create our pixie */ + if ( preloaded_undi.pci_busdevfn == busdevfn ) { + /* Claim preloaded UNDI device */ + DBGC ( undi, "UNDI %p using preloaded UNDI device\n", undi ); + memcpy ( undi, &preloaded_undi, sizeof ( *undi ) ); + memset ( &preloaded_undi, 0, sizeof ( preloaded_undi ) ); + } else { + /* Find UNDI ROM for PCI device */ + if ( ! ( undirom = undipci_find_rom ( pci ) ) ) { + rc = -ENODEV; + goto err_find_rom; + } + + /* Call UNDI ROM loader to create pixie */ + if ( ( rc = undi_load_pci ( undi, undirom, pci->bus, + pci->devfn ) ) != 0 ) + goto err_load_pci; + } + /* Add to device hierarchy */ undi->dev.parent = &pci->dev; INIT_LIST_HEAD ( &undi->dev.children ); list_add ( &undi->dev.siblings, &pci->dev.children ); - /* Call UNDI ROM loader to create pixie */ - if ( ( rc = undi_load_pci ( undi, undirom, pci->bus, - pci->devfn ) ) != 0 ) - goto err_load_pci; - /* Create network device */ if ( ( rc = undinet_probe ( undi ) ) != 0 ) goto err_undinet_probe; @@ -85,8 +109,9 @@ static int undipci_probe ( struct pci_device *pci, err_undinet_probe: undi_unload ( undi ); - err_load_pci: list_del ( &undi->dev.siblings ); + err_find_rom: + err_load_pci: free ( undi ); pci_set_drvdata ( pci, NULL ); return rc; |
