2
0
mirror of https://github.com/xcat2/xNBA.git synced 2024-12-14 23:31:39 +00:00

If preloaded device matches, use that rather than going via the UNDI

loader.
This commit is contained in:
Michael Brown 2007-01-09 02:32:06 +00:00
parent 2436dac281
commit f2f492a536

View File

@ -24,6 +24,7 @@
#include <undirom.h>
#include <undiload.h>
#include <undinet.h>
#include <undipreload.h>
/** @file
*
@ -31,35 +32,44 @@
*
*/
/**
* 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;