diff --git a/src/core/main.c b/src/core/main.c index ab3ea42f..19802d9d 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -176,7 +176,7 @@ int main ( void ) { * */ for ( ; ; disable ( &dev ), call_reset_fns() ) { - + /* Get next boot device */ if ( ! probe ( &dev ) ) { /* Reached end of device list */ @@ -210,6 +210,24 @@ void exit(int status) } +/* + * Set PCI device to use. + * + * This routine can be called by e.g. the ROM prefix to specify that + * the first device to be tried should be the device on which the ROM + * was physically located. + * + * Note that this is deliberately in main.c rather than pci.c, because + * this function should generalise to other bus types (e.g. ISAPnP), + * and we don't want to end up dragging in pci.o unnecessarily. + */ +void set_pci_device ( uint16_t busdevfn ) { + dev.devid.bus_type = PCI_BUS_TYPE; + dev.pci.busdevfn = busdevfn; + dev.pci.already_tried = 0; +} + + #if 0 static int main_loop(int state) diff --git a/src/drivers/bus/pci.c b/src/drivers/bus/pci.c index 2a8055a6..892eb0b7 100644 --- a/src/drivers/bus/pci.c +++ b/src/drivers/bus/pci.c @@ -11,9 +11,6 @@ #define DBG(...) #endif -static struct pci_device current; -static char used_current; - /* * Fill in parameters (vendor & device ids, class, membase etc.) for a * PCI device based on bus & devfn. @@ -114,77 +111,76 @@ static void adjust_pci_device ( struct pci_device *pci ) { } /* - * Set PCI device to use. - * - * This routine can be called by e.g. the ROM prefix to specify that - * the first device to be tried should be the device on which the ROM - * was physically located. + * Obtain a struct pci * from a struct dev * * + * If dev has not previously been used for a PCI device scan, blank + * out dev.pci */ -void set_pci_device ( uint16_t busdevfn ) { - current.busdevfn = busdevfn; - used_current = 0; +struct pci_device * pci_device ( struct dev *dev ) { + struct pci_device *pci = &dev->pci; + + if ( dev->devid.bus_type != PCI_BUS_TYPE ) { + memset ( pci, 0, sizeof ( *pci ) ); + } + pci->dev = dev; + return pci; } /* * Find a PCI device matching the specified driver * - * If "dev" is non-NULL, the struct dev will be filled in with any - * relevant information. - * */ -struct pci_device * find_pci_device ( struct pci_driver *driver, - struct dev *dev ) { +int find_pci_device ( struct pci_device *pci, + struct pci_driver *driver ) { int i; /* Iterate through all possible PCI bus:dev.fn combinations, * starting where we left off. */ - for ( ; current.busdevfn <= 0xffff ; current.busdevfn++ ) { + for ( ; pci->busdevfn <= 0xffff ; pci->busdevfn++ ) { /* If we've already used this device, skip it */ - if ( used_current ) { - used_current = 0; + if ( pci->already_tried ) { + pci->already_tried = 0; continue; } /* Fill in device parameters, if device present */ - if ( ! fill_pci_device ( ¤t ) ) { + if ( ! fill_pci_device ( pci ) ) { continue; } /* Fix up PCI device */ - adjust_pci_device ( ¤t ); + adjust_pci_device ( pci ); /* Fill in dev structure, if present */ - if ( dev ) { - dev->name = driver->name; - dev->devid.vendor_id = current.vendor; - dev->devid.device_id = current.dev_id; - dev->devid.bus_type = PCI_BUS_TYPE; + if ( pci->dev ) { + pci->dev->name = driver->name; + pci->dev->devid.vendor_id = pci->vendor; + pci->dev->devid.device_id = pci->dev_id; } /* If driver has a class, and class matches, use it */ if ( driver->class && - ( driver->class == current.class ) ) { + ( driver->class == pci->class ) ) { DBG ( "Driver %s matches class %hx\n", driver->name, driver->class ); - used_current = 1; - return ¤t; + pci->already_tried = 1; + return 1; } /* If any of driver's IDs match, use it */ for ( i = 0 ; i < driver->id_count; i++ ) { struct pci_id *id = &driver->ids[i]; - if ( ( current.vendor == id->vendor ) && - ( current.dev_id == id->dev_id ) ) { + if ( ( pci->vendor == id->vendor ) && + ( pci->dev_id == id->dev_id ) ) { DBG ( "Device %s (driver %s) matches " "ID %hx:%hx\n", id->name, driver->name, id->vendor, id->dev_id ); - if ( dev ) - dev->name = id->name; - used_current = 1; - return ¤t; + if ( pci->dev ) + pci->dev->name = id->name; + pci->already_tried = 1; + return 1; } } @@ -192,8 +188,7 @@ struct pci_device * find_pci_device ( struct pci_driver *driver, } /* No device found */ - memset ( ¤t, 0, sizeof ( current ) ); - return NULL; + return 0; } /* diff --git a/src/include/dev.h b/src/include/dev.h index aa9ccac3..3c029b91 100644 --- a/src/include/dev.h +++ b/src/include/dev.h @@ -3,6 +3,7 @@ #include "stdint.h" #include "nic.h" +#include "pci.h" /* Need to check the packing of this struct if Etherboot is ported */ struct dev_id { @@ -17,9 +18,13 @@ struct dev_id { #define DEV_ID_SIZE 8 struct dev { + struct dev_operations *dev_op; const char *name; struct dev_id devid; /* device ID string (sent to DHCP server) */ - struct dev_operations *dev_op; + /* All possible bus types */ + union { + struct pci_device pci; + }; /* All possible device types */ union { struct nic nic; diff --git a/src/include/main.h b/src/include/main.h index da9624e4..1841abb7 100644 --- a/src/include/main.h +++ b/src/include/main.h @@ -3,8 +3,9 @@ #include "dev.h" -extern int main ( void ); - extern struct dev dev; +extern int main ( void ); +extern void set_pci_device ( uint16_t busdevfn ); + #endif /* MAIN_H */ diff --git a/src/include/pci.h b/src/include/pci.h index 51393871..f2ba6c98 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -237,7 +237,9 @@ * A physical PCI device * */ +struct dev; struct pci_device { + struct dev * dev; uint32_t membase; /* BAR 1 */ uint32_t ioaddr; /* first IO BAR */ uint16_t vendor, dev_id; @@ -245,6 +247,7 @@ struct pci_device { uint16_t busdevfn; uint8_t revision; uint8_t irq; + uint8_t already_tried; }; #define PCI_BUS(busdevfn) ( ( (busdevfn) >> 8 ) & 0xff ) #define PCI_DEV(busdevfn) ( ( (busdevfn) >> 3 ) & 0x1f ) @@ -319,9 +322,9 @@ extern unsigned long pci_bus_base ( struct pci_device *dev ); * Functions in pci.c * */ -extern void set_pci_device ( uint16_t busdevfn ); -extern struct pci_device * find_pci_device ( struct pci_driver *driver, - struct dev *dev ); +extern struct pci_device * pci_device ( struct dev *dev ); +extern int find_pci_device ( struct pci_device *pci, + struct pci_driver *driver ); 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 );