diff --git a/src/drivers/bus/eisa.c b/src/drivers/bus/eisa.c index d1902dd4..2ec86a2e 100644 --- a/src/drivers/bus/eisa.c +++ b/src/drivers/bus/eisa.c @@ -1,15 +1,29 @@ #include "string.h" #include "io.h" #include "timer.h" +#include "console.h" #include "eisa.h" /* - * Ensure that there is sufficient space in the shared dev_bus - * structure for a struct pci_device. + * Increment a bus_loc structure to the next possible EISA location. + * Leave the structure zeroed and return 0 if there are no more valid + * locations. * */ -DEV_BUS( struct eisa_device, eisa_dev ); -static char eisa_magic[0]; /* guaranteed unique symbol */ +static int eisa_next_location ( struct bus_loc *bus_loc ) { + struct eisa_loc *eisa_loc = ( struct eisa_loc * ) bus_loc; + + /* + * Ensure that there is sufficient space in the shared bus + * structures for a struct isa_loc and a struct + * isa_dev, as mandated by bus.h. + * + */ + BUS_LOC_CHECK ( struct eisa_loc ); + BUS_DEV_CHECK ( struct eisa_device ); + + return ( ++eisa_loc->slot & EISA_MAX_SLOT ); +} /* * Fill in parameters for an EISA device based on slot number @@ -17,9 +31,20 @@ static char eisa_magic[0]; /* guaranteed unique symbol */ * Return 1 if device present, 0 otherwise * */ -static int fill_eisa_device ( struct eisa_device *eisa ) { +static int eisa_fill_device ( struct bus_dev *bus_dev, + struct bus_loc *bus_loc ) { + struct eisa_loc *eisa_loc = ( struct eisa_loc * ) bus_loc; + struct eisa_device *eisa = ( struct eisa_device * ) bus_dev; uint8_t present; + /* Copy slot number to struct eisa, set default values */ + eisa->slot = eisa_loc->slot; + eisa->name = "?"; + + /* Slot 0 is never valid */ + if ( ! eisa->slot ) + return 0; + /* Set ioaddr */ eisa->ioaddr = EISA_SLOT_BASE ( eisa->slot ); @@ -39,7 +64,7 @@ static int fill_eisa_device ( struct eisa_device *eisa ) { eisa->prod_id = ( inb ( eisa->ioaddr + EISA_PROD_ID_LO ) << 8 ) + inb ( eisa->ioaddr + EISA_PROD_ID_HI ); - DBG ( "EISA found slot %d (base %#hx) ID %hx:%hx (\"%s\")\n", + DBG ( "EISA found slot %hhx (base %#hx) ID %hx:%hx (\"%s\")\n", eisa->slot, eisa->ioaddr, eisa->mfg_id, eisa->prod_id, isa_id_string ( eisa->mfg_id, eisa->prod_id ) ); @@ -47,78 +72,86 @@ static int fill_eisa_device ( struct eisa_device *eisa ) { } /* - * Find an EISA device matching the specified driver + * Test whether or not a driver is capable of driving the device. * */ -int find_eisa_device ( struct eisa_device *eisa, struct eisa_driver *driver ) { +static int eisa_check_driver ( struct bus_dev *bus_dev, + struct device_driver *device_driver ) { + struct eisa_device *eisa = ( struct eisa_device * ) bus_dev; + struct eisa_driver *driver + = ( struct eisa_driver * ) device_driver->bus_driver_info; unsigned int i; - /* Initialise struct eisa if it's the first time it's been used. */ - if ( eisa->magic != eisa_magic ) { - memset ( eisa, 0, sizeof ( *eisa ) ); - eisa->magic = eisa_magic; - eisa->slot = EISA_MIN_SLOT; - } - - /* Iterate through all possible EISA slots, starting where we - * left off. - */ - DBG ( "EISA searching for device matching driver %s\n", driver->name ); - for ( ; eisa->slot <= EISA_MAX_SLOT ; eisa->slot++ ) { - /* If we've already used this device, skip it */ - if ( eisa->already_tried ) { - eisa->already_tried = 0; - continue; - } - - /* Fill in device parameters */ - if ( ! fill_eisa_device ( eisa ) ) { - continue; - } - - /* Compare against driver's ID list */ - for ( i = 0 ; i < driver->id_count ; i++ ) { - struct eisa_id *id = &driver->ids[i]; - - if ( ( eisa->mfg_id == id->mfg_id ) && - ( ISA_PROD_ID ( eisa->prod_id ) == - ISA_PROD_ID ( id->prod_id ) ) ) { - DBG ( "EISA found ID %hx:%hx (\"%s\") " - "(device %s) matching driver %s\n", - eisa->mfg_id, eisa->prod_id, - isa_id_string ( eisa->mfg_id, - eisa->prod_id ), - id->name, driver->name ); - eisa->name = id->name; - eisa->already_tried = 1; - return 1; - } + /* Compare against driver's ID list */ + for ( i = 0 ; i < driver->id_count ; i++ ) { + struct eisa_id *id = &driver->ids[i]; + + if ( ( eisa->mfg_id == id->mfg_id ) && + ( ISA_PROD_ID ( eisa->prod_id ) == + ISA_PROD_ID ( id->prod_id ) ) ) { + DBG ( "EISA found ID %hx:%hx (\"%s\") " + "(device %s) matching driver %s\n", + eisa->mfg_id, eisa->prod_id, + isa_id_string ( eisa->mfg_id, + eisa->prod_id ), + id->name, driver->name ); + eisa->name = id->name; + return 1; } } /* No device found */ - DBG ( "EISA found no device matching driver %s\n", driver->name ); - eisa->slot = EISA_MIN_SLOT; return 0; } /* - * Find the next EISA device that can be used to boot using the - * specified driver. + * Describe an EISA device * */ -int find_eisa_boot_device ( struct dev *dev, struct eisa_driver *driver ) { - struct eisa_device *eisa = ( struct eisa_device * )dev->bus; +static char * eisa_describe ( struct bus_dev *bus_dev ) { + struct eisa_device *eisa = ( struct eisa_device * ) bus_dev; + static char eisa_description[] = "EISA 00"; - if ( ! find_eisa_device ( eisa, driver ) ) - return 0; + sprintf ( eisa_description + 5, "%hhx", eisa->slot ); + return eisa_description; +} - dev->name = eisa->name; - dev->devid.bus_type = ISA_BUS_TYPE; - dev->devid.vendor_id = eisa->mfg_id; - dev->devid.device_id = eisa->prod_id; +/* + * Name an EISA device + * + */ +static const char * eisa_name ( struct bus_dev *bus_dev ) { + struct eisa_device *eisa = ( struct eisa_device * ) bus_dev; + + return eisa->name; +} - return 1; +/* + * EISA bus operations table + * + */ +struct bus_driver eisa_driver __bus_driver = { + .next_location = eisa_next_location, + .fill_device = eisa_fill_device, + .check_driver = eisa_check_driver, + .describe = eisa_describe, + .name = eisa_name, +}; + +/* + * Fill in a nic structure + * + */ +void eisa_fill_nic ( struct nic *nic, struct eisa_device *eisa ) { + + /* Fill in ioaddr and irqno */ + nic->ioaddr = eisa->ioaddr; + nic->irqno = 0; + + /* Fill in DHCP device ID structure */ + nic->dhcp_dev_id.bus_type = ISA_BUS_TYPE; + nic->dhcp_dev_id.vendor_id = htons ( eisa->mfg_id ); + nic->dhcp_dev_id.device_id = htons ( eisa->prod_id ); } /* diff --git a/src/drivers/bus/isa.c b/src/drivers/bus/isa.c index 1afb1aa1..9c5b4efd 100644 --- a/src/drivers/bus/isa.c +++ b/src/drivers/bus/isa.c @@ -1,4 +1,5 @@ #include "string.h" +#include "console.h" #include "config/isa.h" #include "isa.h" @@ -14,139 +15,156 @@ * instead. Some cards (e.g. the 3c509) implement a proprietary * ISAPnP-like mechanism. * - * The ISA probe address list can be overridden by config.c; if the + * The ISA probe address list can be overridden by config.h; if the * user specifies ISA_PROBE_ADDRS then that list will be used first. * (If ISA_PROBE_ADDRS ends with a zero, the driver's own list will * never be used). */ -/* - * Ensure that there is sufficient space in the shared dev_bus - * structure for a struct isa_device. - * - */ -DEV_BUS( struct isa_device, isa_dev ); -static char isa_magic[0]; /* guaranteed unique symbol */ - /* * User-supplied probe address list * */ -#ifdef ISA_PROBE_ADDRS -# ifdef ISA_PROBE_ONLY -# define HAVE_ISA_PROBE_ADDRS 1 -# define ISA_PROBE_ADDR_LIST ISA_PROBE_ADDRS, 0 -# else -# define HAVE_ISA_PROBE_ADDRS 1 -# define ISA_PROBE_ADDR_LIST ISA_PROBE_ADDRS -# endif -#else -# define HAVE_ISA_PROBE_ADDRS 0 -# define ISA_PROBE_ADDR_LIST -#endif - static isa_probe_addr_t isa_extra_probe_addrs[] = { - ISA_PROBE_ADDR_LIST +#ifdef ISA_PROBE_ADDRS + ISA_PROBE_ADDRS +#endif }; #define isa_extra_probe_addr_count \ ( sizeof ( isa_extra_probe_addrs ) / sizeof ( isa_extra_probe_addrs[0] ) ) +#ifdef ISA_PROBE_ONLY +# define ISA_PROBE_IDX_LIMIT isa_extra_probe_addr_count +#else +# define ISA_PROBE_IDX_LIMIT ( ISA_MAX_PROBE_IDX + 1 ) +#endif + /* - * Find an ISA device matching the specified driver + * Increment a bus_loc structure to the next possible ISA location. + * Leave the structure zeroed and return 0 if there are no more valid + * locations. * */ -int find_isa_device ( struct isa_device *isa, struct isa_driver *driver ) { - unsigned int i; - uint16_t ioaddr; - - /* Initialise struct isa if it's the first time it's been used. */ - if ( isa->magic != isa_magic ) { - memset ( isa, 0, sizeof ( *isa ) ); - isa->magic = isa_magic; - } - - /* Iterate through any ISA probe addresses specified by the - * user, starting where we left off. +static int isa_next_location ( struct bus_loc *bus_loc ) { + struct isa_loc *isa_loc = ( struct isa_loc * ) bus_loc; + + /* + * Ensure that there is sufficient space in the shared bus + * structures for a struct isa_loc and a struct + * isa_dev, as mandated by bus.h. + * */ - DBG ( "ISA searching for device matching driver %s\n", driver->name ); - for ( i = isa->probe_idx ; i < isa_extra_probe_addr_count ; i++ ) { - /* If we've already used this device, skip it */ - if ( isa->already_tried ) { - isa->already_tried = 0; - continue; - } - - /* Set I/O address */ - ioaddr = isa_extra_probe_addrs[i]; + BUS_LOC_CHECK ( struct isa_loc ); + BUS_DEV_CHECK ( struct isa_device ); - /* An I/O address of 0 in extra_probe_addrs list means - * stop probing (i.e. don't continue to the - * driver-provided list) - */ - if ( ! ioaddr ) - goto notfound; + return ( ( ++isa_loc->probe_idx < ISA_PROBE_IDX_LIMIT ) ? + 1 : ( isa_loc->probe_idx = 0 ) ); +} - /* Use probe_addr method to see if there's a device - * present at this address. - */ - if ( driver->probe_addr ( ioaddr ) ) { - isa->probe_idx = i; - goto found; - } +/* + * Fill in parameters (vendor & device ids, class, membase etc.) for + * an ISA device based on bus_loc. + * + * Returns 1 if a device was found, 0 for no device present. + * + */ +static int isa_fill_device ( struct bus_dev *bus_dev, + struct bus_loc *bus_loc ) { + struct isa_loc *isa_loc = ( struct isa_loc * ) bus_loc; + struct isa_device *isa = ( struct isa_device * ) bus_dev; + signed int driver_probe_idx; + + driver_probe_idx = isa_loc->probe_idx - isa_extra_probe_addr_count; + if ( driver_probe_idx < 0 ) { + isa->ioaddr = isa_extra_probe_addrs[isa_loc->probe_idx]; + } else { + isa->ioaddr = 0; + isa->driver_probe_idx = driver_probe_idx; } + isa->mfg_id = isa->prod_id = 0; + isa->name = "?"; + return 1; +} - /* Iterate through all ISA probe addresses provided by the - * driver, starting where we left off. +/* + * Test whether or not a driver is capable of driving the specified + * device. + * + */ +int isa_check_driver ( struct bus_dev *bus_dev, + struct device_driver *device_driver ) { + struct isa_device *isa = ( struct isa_device * ) bus_dev; + struct isa_driver *driver + = ( struct isa_driver * ) device_driver->bus_driver_info; + + /* If ioaddr is zero, it means we're using a driver-specified + * ioaddr */ - for ( i = isa->probe_idx - isa_extra_probe_addr_count ; - i < driver->addr_count ; i++ ) { + if ( ! isa->ioaddr ) + isa->ioaddr = driver->probe_addrs[isa->driver_probe_idx]; - /* If we've already used this device, skip it */ - if ( isa->already_tried ) { - isa->already_tried = 0; - continue; - } - - /* Set I/O address */ - ioaddr = driver->probe_addrs[i]; - - /* Use probe_addr method to see if there's a device - * present at this address. - */ - if ( driver->probe_addr ( ioaddr ) ) { - isa->probe_idx = i + isa_extra_probe_addr_count; - goto found; - } + /* Use probe_addr method to see if there's a device + * present at this address. + */ + if ( driver->probe_addr ( isa->ioaddr ) ) { + DBG ( "ISA found %s device at address %hx\n", + driver->name, isa->ioaddr ); + isa->name = driver->name; + isa->mfg_id = driver->mfg_id; + isa->prod_id = driver->prod_id; + return 1; } - notfound: /* No device found */ - DBG ( "ISA found no device matching driver %s\n", driver->name ); - isa->probe_idx = 0; return 0; - - found: - DBG ( "ISA found %s device at address %hx\n", driver->name, ioaddr ); - isa->ioaddr = ioaddr; - isa->already_tried = 1; - return 1; } /* - * Find the next ISA device that can be used to boot using the - * specified driver. + * Describe a ISA device * */ -int find_isa_boot_device ( struct dev *dev, struct isa_driver *driver ) { - struct isa_device *isa = ( struct isa_device * )dev->bus; +static char * isa_describe ( struct bus_dev *bus_dev ) { + struct isa_device *isa = ( struct isa_device * ) bus_dev; + static char isa_description[] = "ISA 0000"; - if ( ! find_isa_device ( isa, driver ) ) - return 0; - - dev->name = driver->name; - dev->devid.bus_type = ISA_BUS_TYPE; - dev->devid.vendor_id = driver->mfg_id; - dev->devid.device_id = driver->prod_id; - - return 1; + sprintf ( isa_description + 4, "%hx", isa->ioaddr ); + return isa_description; +} + +/* + * Name a ISA device + * + */ +static const char * isa_name ( struct bus_dev *bus_dev ) { + struct isa_device *isa = ( struct isa_device * ) bus_dev; + + return isa->name; +} + +/* + * ISA bus operations table + * + */ +struct bus_driver isa_driver __bus_driver = { + .next_location = isa_next_location, + .fill_device = isa_fill_device, + .check_driver = isa_check_driver, + .describe = isa_describe, + .name = isa_name, +}; + +/* + * Fill in a nic structure + * + */ +void isa_fill_nic ( struct nic *nic, struct isa_device *isa ) { + + /* Fill in ioaddr and irqno */ + nic->ioaddr = isa->ioaddr; + nic->irqno = 0; + + /* Fill in DHCP device ID structure */ + nic->dhcp_dev_id.bus_type = ISA_BUS_TYPE; + nic->dhcp_dev_id.vendor_id = htons ( isa->mfg_id ); + nic->dhcp_dev_id.device_id = htons ( isa->prod_id ); } diff --git a/src/drivers/bus/isapnp.c b/src/drivers/bus/isapnp.c index 3cf65b9e..9157f0be 100644 --- a/src/drivers/bus/isapnp.c +++ b/src/drivers/bus/isapnp.c @@ -36,16 +36,9 @@ #include "string.h" #include "timer.h" #include "io.h" +#include "console.h" #include "isapnp.h" -/* - * Ensure that there is sufficient space in the shared dev_bus - * structure for a struct isapnp_device. - * - */ -DEV_BUS( struct isapnp_device, isapnp_dev ); -static char isapnp_magic[0]; /* guaranteed unique symbol */ - /* * We can have only one ISAPnP bus in a system. Once the read port is * known and all cards have been allocated CSNs, there's nothing to be @@ -56,9 +49,14 @@ static char isapnp_magic[0]; /* guaranteed unique symbol */ * ISA bus. We therefore probe only when we are first asked to find * an ISAPnP device. * + * External code (e.g. the ISAPnP ROM prefix) may already know the + * read port address, in which case it can initialise this value. + * Note that setting the read port address will prevent further + * isolation from taking place; you should set the read port address + * only if you know that devices have already been allocated CSNs. + * */ -static uint16_t isapnp_read_port; -static uint16_t isapnp_max_csn; +uint16_t isapnp_read_port; /* * ISAPnP utility functions @@ -297,7 +295,8 @@ static int isapnp_find_tag ( uint8_t wanted_tag, uint8_t *buf ) { */ static int isapnp_try_isolate ( void ) { struct isapnp_identifier identifier; - int i, j, seen55aa; + unsigned int i, j, seen55aa; + unsigned int csn = 0; uint16_t data; uint8_t byte; @@ -312,7 +311,6 @@ static int isapnp_try_isolate ( void ) { /* Reset all assigned CSNs */ isapnp_reset_csn (); - isapnp_max_csn = 0; isapnp_delay(); isapnp_delay(); @@ -358,7 +356,7 @@ static int isapnp_try_isolate ( void ) { /* If we didn't see any 55aa patterns, stop here */ if ( ! seen55aa ) { DBG ( "ISAPnP saw %s signs of life\n", - isapnp_max_csn ? "no futher" : "no" ); + csn ? "no futher" : "no" ); break; } @@ -374,12 +372,12 @@ static int isapnp_try_isolate ( void ) { } /* Give the device a CSN */ - isapnp_max_csn++; + csn++; DBG ( "ISAPnP found card " ISAPNP_CARD_ID_FMT ", assigning CSN %hhx\n", - ISAPNP_CARD_ID_DATA ( &identifier ), isapnp_max_csn ); + ISAPNP_CARD_ID_DATA ( &identifier ), csn ); - isapnp_write_csn ( isapnp_max_csn ); + isapnp_write_csn ( csn ); isapnp_delay(); /* Send this card back to Sleep and force all cards @@ -394,8 +392,8 @@ static int isapnp_try_isolate ( void ) { /* Return number of cards found */ DBG ( "ISAPnP found %d cards at read port %hx\n", - isapnp_max_csn, isapnp_read_port ); - return isapnp_max_csn; + csn, isapnp_read_port ); + return csn; } /* @@ -419,17 +417,65 @@ static void isapnp_isolate ( void ) { } } +/* + * Increment a bus_loc structure to the next possible ISAPnP location. + * Leave the structure zeroed and return 0 if there are no more valid + * locations. + * + */ +static int isapnp_next_location ( struct bus_loc *bus_loc ) { + struct isapnp_loc *isapnp_loc = ( struct isapnp_loc * ) bus_loc; + + /* + * Ensure that there is sufficient space in the shared bus + * structures for a struct isapnp_loc and a struct isapnp_dev, + * as mandated by bus.h. + * + */ + BUS_LOC_CHECK ( struct isapnp_loc ); + BUS_DEV_CHECK ( struct isapnp_device ); + + return ( ++isapnp_loc->logdev ? 1 : ++isapnp_loc->csn ); +} + /* * Fill in parameters for an ISAPnP device based on CSN * * Return 1 if device present, 0 otherwise * */ -static int fill_isapnp_device ( struct isapnp_device *isapnp ) { +static int isapnp_fill_device ( struct bus_dev *bus_dev, + struct bus_loc *bus_loc ) { + struct isapnp_device *isapnp = ( struct isapnp_device * ) bus_dev; + struct isapnp_loc *isapnp_loc = ( struct isapnp_loc * ) bus_loc; unsigned int i; struct isapnp_identifier identifier; struct isapnp_logdevid logdevid; - + static struct { + uint8_t csn; + uint8_t first_nonexistent_logdev; + } cache = { 0, 0 }; + + /* Copy CSN and logdev to isapnp_device, set default values */ + isapnp->csn = isapnp_loc->csn; + isapnp->logdev = isapnp_loc->logdev; + isapnp->name = "?"; + + /* CSN 0 is never valid, but may be passed in */ + if ( ! isapnp->csn ) + return 0; + + /* Check cache to see if we are already past the highest + * logical device of this CSN + */ + if ( ( isapnp->csn == cache.csn ) && + ( isapnp->logdev >= cache.first_nonexistent_logdev ) ) + return 0; + + /* Perform isolation if it hasn't yet been done */ + if ( ! isapnp_read_port ) + isapnp_isolate(); + /* Wake the card */ isapnp_wait_for_key (); isapnp_send_key (); @@ -438,6 +484,14 @@ static int fill_isapnp_device ( struct isapnp_device *isapnp ) { /* Read the card identifier */ isapnp_peek ( ( char * ) &identifier, sizeof ( identifier ) ); + /* Need to return 0 if no device exists at this CSN */ + if ( identifier.vendor_id & 0x80 ) { + DBG ( "ISAPnP found no card %hhx\n", isapnp->csn ); + cache.csn = isapnp->csn; + cache.first_nonexistent_logdev = 0; + return 0; + } + /* Find the Logical Device ID tag corresponding to this device */ for ( i = 0 ; i <= isapnp->logdev ; i++ ) { if ( ! isapnp_find_tag ( ISAPNP_TAG_LOGDEVID, @@ -447,6 +501,8 @@ static int fill_isapnp_device ( struct isapnp_device *isapnp ) { "card " ISAPNP_CARD_ID_FMT "\n", isapnp->csn, isapnp->logdev, ISAPNP_CARD_ID_DATA ( &identifier ) ); + cache.csn = isapnp->csn; + cache.first_nonexistent_logdev = isapnp->logdev; return 0; } } @@ -475,99 +531,74 @@ static int fill_isapnp_device ( struct isapnp_device *isapnp ) { } /* - * Find an ISAPnP device matching the specified driver + * Test whether or not a driver is capable of driving the device. * */ -int find_isapnp_device ( struct isapnp_device *isapnp, - struct isapnp_driver *driver ) { +static int isapnp_check_driver ( struct bus_dev *bus_dev, + struct device_driver *device_driver ) { + struct isapnp_device *isapnp = ( struct isapnp_device * ) bus_dev; + struct isapnp_driver *driver + = ( struct isapnp_driver * ) device_driver->bus_driver_info; unsigned int i; - /* Initialise struct isapnp if it's the first time it's been used. */ - if ( isapnp->magic != isapnp_magic ) { - memset ( isapnp, 0, sizeof ( *isapnp ) ); - isapnp->magic = isapnp_magic; - isapnp->csn = 1; - } - - /* Ensure that all ISAPnP cards have CSNs allocated to them, - * if we haven't already done so. - */ - if ( ! isapnp_read_port ) { - isapnp_isolate(); - } - - /* Iterate through all possible ISAPNP CSNs, starting where we - * left off. - */ - DBG ( "ISAPnP searching for device matching driver %s\n", - driver->name ); - for ( ; isapnp->csn <= isapnp_max_csn ; isapnp->csn++ ) { - for ( ; isapnp->logdev <= 0xff ; isapnp->logdev++ ) { - /* If we've already used this device, skip it */ - if ( isapnp->already_tried ) { - isapnp->already_tried = 0; - continue; - } - - /* Fill in device parameters */ - if ( ! fill_isapnp_device ( isapnp ) ) { - /* If fill_isapnp_device fails, assume - * that we've reached the last logical - * device on this card, and proceed to - * the next card. - */ - isapnp->logdev = 0; - break; - } - - /* Compare against driver's ID list */ - for ( i = 0 ; i < driver->id_count ; i++ ) { - struct isapnp_id *id = &driver->ids[i]; - - if ( ( isapnp->vendor_id == id->vendor_id ) && - ( ISA_PROD_ID ( isapnp->prod_id ) == - ISA_PROD_ID ( id->prod_id ) ) ) { - DBG ( "ISAPnP found ID %hx:%hx " - "(\"%s\") (device %s) " - "matching driver %s\n", - isapnp->vendor_id, - isapnp->prod_id, - isa_id_string( isapnp->vendor_id, - isapnp->prod_id ), - id->name, driver->name ); - isapnp->name = id->name; - isapnp->already_tried = 1; - return 1; - } - } + /* Compare against driver's ID list */ + for ( i = 0 ; i < driver->id_count ; i++ ) { + struct isapnp_id *id = &driver->ids[i]; + + if ( ( isapnp->vendor_id == id->vendor_id ) && + ( ISA_PROD_ID ( isapnp->prod_id ) == + ISA_PROD_ID ( id->prod_id ) ) ) { + DBG ( "ISAPnP found ID %hx:%hx " + "(\"%s\") (device %s) " + "matching driver %s\n", + isapnp->vendor_id, + isapnp->prod_id, + isa_id_string( isapnp->vendor_id, + isapnp->prod_id ), + id->name, driver->name ); + isapnp->name = id->name; + return 1; } } - /* No device found */ - DBG ( "ISAPnP found no device matching driver %s\n", driver->name ); - isapnp->csn = 1; return 0; } /* - * Find the next ISAPNP device that can be used to boot using the - * specified driver. + * Describe an ISAPnP device * */ -int find_isapnp_boot_device ( struct dev *dev, struct isapnp_driver *driver ) { - struct isapnp_device *isapnp = ( struct isapnp_device * ) dev->bus; +static char * isapnp_describe ( struct bus_dev *bus_dev ) { + struct isapnp_device *isapnp = ( struct isapnp_device * ) bus_dev; + static char isapnp_description[] = "ISAPnP 00:00"; - if ( ! find_isapnp_device ( isapnp, driver ) ) - return 0; - - dev->name = isapnp->name; - dev->devid.bus_type = ISA_BUS_TYPE; - dev->devid.vendor_id = isapnp->vendor_id; - dev->devid.device_id = isapnp->prod_id; - - return 1; + sprintf ( isapnp_description + 7, "%hhx:%hhx", + isapnp->csn, isapnp->logdev ); + return isapnp_description; } +/* + * Name an ISAPnP device + * + */ +static const char * isapnp_name ( struct bus_dev *bus_dev ) { + struct isapnp_device *isapnp = ( struct isapnp_device * ) bus_dev; + + return isapnp->name; +} + +/* + * ISAPnP bus operations table + * + */ +struct bus_driver isapnp_driver __bus_driver = { + .next_location = isapnp_next_location, + .fill_device = isapnp_fill_device, + .check_driver = isapnp_check_driver, + .describe = isapnp_describe, + .name = isapnp_name, +}; + /* * Activate or deactivate an ISAPnP device * @@ -594,3 +625,20 @@ void activate_isapnp_device ( struct isapnp_device *isapnp, DBG ( "ISAPnP activated device %hhx.%hhx\n", isapnp->csn, isapnp->logdev ); } + +/* + * Fill in a nic structure + * + */ +void isapnp_fill_nic ( struct nic *nic, struct isapnp_device *isapnp ) { + + /* Fill in ioaddr and irqno */ + nic->ioaddr = isapnp->ioaddr; + nic->irqno = isapnp->irqno; + + /* Fill in DHCP device ID structure */ + nic->dhcp_dev_id.bus_type = ISA_BUS_TYPE; + nic->dhcp_dev_id.vendor_id = htons ( isapnp->vendor_id ); + nic->dhcp_dev_id.device_id = htons ( isapnp->prod_id ); +} + diff --git a/src/drivers/bus/mca.c b/src/drivers/bus/mca.c index f3795023..51f81d8d 100644 --- a/src/drivers/bus/mca.c +++ b/src/drivers/bus/mca.c @@ -7,23 +7,45 @@ #include "string.h" #include "io.h" +#include "console.h" +#include "nic.h" #include "mca.h" /* - * Ensure that there is sufficient space in the shared dev_bus - * structure for a struct pci_device. + * Increment a bus_loc structure to the next possible MCA location. + * Leave the structure zeroed and return 0 if there are no more valid + * locations. * */ -DEV_BUS( struct mca_device, mca_dev ); -static char mca_magic[0]; /* guaranteed unique symbol */ +static int mca_next_location ( struct bus_loc *bus_loc ) { + struct mca_loc *mca_loc = ( struct mca_loc * ) bus_loc; + + /* + * Ensure that there is sufficient space in the shared bus + * structures for a struct mca_loc and a struct + * mca_dev, as mandated by bus.h. + * + */ + BUS_LOC_CHECK ( struct mca_loc ); + BUS_DEV_CHECK ( struct mca_device ); + + return ( ++mca_loc->slot & MCA_MAX_SLOT_NR ); +} /* * Fill in parameters for an MCA device based on slot number * */ -static int fill_mca_device ( struct mca_device *mca ) { +static int mca_fill_device ( struct bus_dev *bus_dev, + struct bus_loc *bus_loc ) { + struct mca_loc *mca_loc = ( struct mca_loc * ) bus_loc; + struct mca_device *mca = ( struct mca_device * ) bus_dev; unsigned int i, seen_non_ff; + /* Store slot in struct mca, set default values */ + mca->slot = mca_loc->slot; + mca->name = "?"; + /* Make sure motherboard setup is off */ outb_p ( 0xff, MCA_MOTHERBOARD_SETUP_REG ); @@ -58,70 +80,81 @@ static int fill_mca_device ( struct mca_device *mca ) { } /* - * Find an MCA device matching the specified driver + * Test whether or not a driver is capable of driving the device. * */ -int find_mca_device ( struct mca_device *mca, struct mca_driver *driver ) { +static int mca_check_driver ( struct bus_dev *bus_dev, + struct device_driver *device_driver ) { + struct mca_device *mca = ( struct mca_device * ) bus_dev; + struct mca_driver *driver + = ( struct mca_driver * ) device_driver->bus_driver_info; unsigned int i; - /* Initialise struct mca if it's the first time it's been used. */ - if ( mca->magic != mca_magic ) { - memset ( mca, 0, sizeof ( *mca ) ); - mca->magic = mca_magic; - } - - /* Iterate through all possible MCA slots, starting where we - * left off - */ - DBG ( "MCA searching for device matching driver %s\n", driver->name ); - for ( ; mca->slot < MCA_MAX_SLOT_NR ; mca->slot++ ) { - /* If we've already used this device, skip it */ - if ( mca->already_tried ) { - mca->already_tried = 0; - continue; - } - - /* Fill in device parameters */ - if ( ! fill_mca_device ( mca ) ) { - continue; - } - - /* Compare against driver's ID list */ - for ( i = 0 ; i < driver->id_count ; i++ ) { - struct mca_id *id = &driver->ids[i]; - - if ( MCA_ID ( mca ) == id->id ) { - DBG ( "MCA found ID %hx (device %s) " - "matching driver %s\n", - id->name, id->id, driver->name ); - mca->name = id->name; - mca->already_tried = 1; - return 1; - } + /* Compare against driver's ID list */ + for ( i = 0 ; i < driver->id_count ; i++ ) { + struct mca_id *id = &driver->ids[i]; + + if ( MCA_ID ( mca ) == id->id ) { + DBG ( "MCA found ID %hx (device %s) " + "matching driver %s\n", + id->name, id->id, driver->name ); + mca->name = id->name; + return 1; } } /* No device found */ - DBG ( "MCA found no device matching driver %s\n", driver->name ); - mca->slot = 0; return 0; } /* - * Find the next MCA device that can be used to boot using the - * specified driver. + * Describe an MCA device * */ -int find_mca_boot_device ( struct dev *dev, struct mca_driver *driver ) { - struct mca_device *mca = ( struct mca_device * )dev->bus; +static char * mca_describe ( struct bus_dev *bus_dev ) { + struct mca_device *mca = ( struct mca_device * ) bus_dev; + static char mca_description[] = "MCA 00"; - if ( ! find_mca_device ( mca, driver ) ) - return 0; - - dev->name = mca->name; - dev->devid.bus_type = MCA_BUS_TYPE; - dev->devid.vendor_id = GENERIC_MCA_VENDOR; - dev->devid.device_id = MCA_ID ( mca ); - - return 1; + sprintf ( mca_description + 4, "%hhx", mca->slot ); + return mca_description; +} + +/* + * Name an MCA device + * + */ +static const char * mca_name ( struct bus_dev *bus_dev ) { + struct mca_device *mca = ( struct mca_device * ) bus_dev; + + return mca->name; +} + +/* + * MCA bus operations table + * + */ +struct bus_driver mca_driver __bus_driver = { + .next_location = mca_next_location, + .fill_device = mca_fill_device, + .check_driver = mca_check_driver, + .describe = mca_describe, + .name = mca_name, +}; + +/* + * Fill in a nic structure + * + */ +void mca_fill_nic ( struct nic *nic, struct mca_device *mca ) { + + /* ioaddr and irqno must be read in a device-dependent way + * from the POS registers + */ + nic->ioaddr = 0; + nic->irqno = 0; + + /* Fill in DHCP device ID structure */ + nic->dhcp_dev_id.bus_type = MCA_BUS_TYPE; + nic->dhcp_dev_id.vendor_id = htons ( GENERIC_MCA_VENDOR ); + nic->dhcp_dev_id.device_id = htons ( MCA_ID ( mca ) ); } diff --git a/src/drivers/bus/pci.c b/src/drivers/bus/pci.c index c58a186b..6653b4d3 100644 --- a/src/drivers/bus/pci.c +++ b/src/drivers/bus/pci.c @@ -45,7 +45,7 @@ static int pci_fill_device ( struct bus_dev *bus_dev, struct pci_device *pci = ( struct pci_device * ) bus_dev; uint16_t busdevfn = pci_loc->busdevfn; static struct { - uint16_t devfn0; + uint16_t busdevfn0; int is_present; } cache = { 0, 1 }; uint32_t l; @@ -65,7 +65,7 @@ static int pci_fill_device ( struct bus_dev *bus_dev, * increase scan speed by a factor of 8. */ if ( ( PCI_FUNC ( busdevfn ) != 0 ) && - ( PCI_FN0 ( busdevfn ) == cache.devfn0 ) && + ( PCI_FN0 ( busdevfn ) == cache.busdevfn0 ) && ( ! cache.is_present ) ) { return 0; } @@ -79,7 +79,7 @@ static int pci_fill_device ( struct bus_dev *bus_dev, /* Don't look for subsequent functions if the * card itself is not present. */ - cache.devfn0 = busdevfn; + cache.busdevfn0 = busdevfn; cache.is_present = 0; } return 0; @@ -130,7 +130,7 @@ static int pci_fill_device ( struct bus_dev *bus_dev, pci_read_config_byte ( pci, PCI_INTERRUPT_LINE, &pci->irq ); } - DBG ( "found device %hhx:%hhx.%d Class %hx: %hx:%hx (rev %hhx)\n", + DBG ( "PCI found device %hhx:%hhx.%d Class %hx: %hx:%hx (rev %hhx)\n", PCI_BUS ( pci->busdevfn ), PCI_DEV ( pci->busdevfn ), PCI_FUNC ( pci->busdevfn ), pci->class, pci->vendor_id, pci->device_id, pci->revision ); @@ -152,7 +152,7 @@ static int pci_check_driver ( struct bus_dev *bus_dev, /* If driver has a class, and class matches, use it */ if ( pci_driver->class && ( pci_driver->class == pci->class ) ) { - DBG ( "driver %s matches class %hx\n", + DBG ( "PCI driver %s matches class %hx\n", device_driver->name, pci_driver->class ); pci->name = device_driver->name; return 1; @@ -164,7 +164,7 @@ static int pci_check_driver ( struct bus_dev *bus_dev, if ( ( pci->vendor_id == id->vendor_id ) && ( pci->device_id == id->device_id ) ) { - DBG ( "driver %s device %s matches ID %hx:%hx\n", + DBG ( "PCI driver %s device %s matches ID %hx:%hx\n", device_driver->name, id->name, id->vendor_id, id->device_id ); pci->name = id->name; @@ -222,7 +222,7 @@ void adjust_pci_device ( struct pci_device *pci ) { pci_read_config_word ( pci, PCI_COMMAND, &pci_command ); new_command = pci_command | PCI_COMMAND_MASTER | PCI_COMMAND_IO; if ( pci_command != new_command ) { - DBG ( "BIOS has not enabled device %hhx:%hhx.%d! " + DBG ( "PCI BIOS has not enabled device %hhx:%hhx.%d! " "Updating PCI command %hX->%hX\n", PCI_BUS ( pci->busdevfn ), PCI_DEV ( pci->busdevfn ), PCI_FUNC ( pci->busdevfn ), pci_command, new_command ); @@ -230,7 +230,7 @@ void adjust_pci_device ( struct pci_device *pci ) { } pci_read_config_byte ( pci, PCI_LATENCY_TIMER, &pci_latency); if ( pci_latency < 32 ) { - DBG ( "device %hhx:%hhx.%d latency timer is " + DBG ( "PCI device %hhx:%hhx.%d latency timer is " "unreasonably low at %d. Setting to 32.\n", PCI_BUS ( pci->busdevfn ), PCI_DEV ( pci->busdevfn ), PCI_FUNC ( pci->busdevfn ), pci_latency ); @@ -338,7 +338,7 @@ int pci_find_capability ( struct pci_device *pci, int cap ) { while ( ttl-- && pos >= 0x40 ) { pos &= ~3; pci_read_config_byte ( pci, pos + PCI_CAP_LIST_ID, &id ); - DBG ( "Capability: %d\n", id ); + DBG ( "PCI Capability: %d\n", id ); if ( id == 0xff ) break; if ( id == cap ) @@ -349,7 +349,7 @@ int pci_find_capability ( struct pci_device *pci, int cap ) { } /* - * Fill in a DHCP device ID structure + * Fill in a nic structure * */ void pci_fill_nic ( struct nic *nic, struct pci_device *pci ) { diff --git a/src/include/eisa.h b/src/include/eisa.h index df03fe84..42999e7d 100644 --- a/src/include/eisa.h +++ b/src/include/eisa.h @@ -1,8 +1,9 @@ #ifndef EISA_H #define EISA_H +#include "stdint.h" #include "isa_ids.h" -#include "dev.h" +#include "nic.h" /* * EISA constants @@ -10,7 +11,7 @@ */ #define EISA_MIN_SLOT (0x1) -#define EISA_MAX_SLOT (0xf) +#define EISA_MAX_SLOT (0xf) /* Must be 2^n - 1 */ #define EISA_SLOT_BASE( n ) ( 0x1000 * (n) ) #define EISA_MFG_ID_HI ( 0xc80 ) @@ -22,18 +23,24 @@ #define EISA_CMD_RESET ( 1 << 2 ) #define EISA_CMD_ENABLE ( 1 << 0 ) +/* + * A location on an EISA bus + * + */ +struct eisa_loc { + unsigned int slot; +}; + /* * A physical EISA device * */ struct eisa_device { - char *magic; /* must be first */ const char *name; unsigned int slot; uint16_t ioaddr; uint16_t mfg_id; uint16_t prod_id; - int already_tried; }; /* @@ -59,20 +66,22 @@ struct eisa_driver { * Define an EISA driver * */ -#define EISA_DRIVER( driver_name, eisa_ids ) { \ - .name = driver_name, \ - .ids = eisa_ids, \ - .id_count = sizeof ( eisa_ids ) / sizeof ( eisa_ids[0] ), \ +#define EISA_DRIVER( _ids ) { \ + .ids = _ids, \ + .id_count = sizeof ( _ids ) / sizeof ( _ids[0] ), \ } /* * Functions in eisa.c * */ -extern int find_eisa_device ( struct eisa_device *eisa, - struct eisa_driver *driver ); -extern int find_eisa_boot_device ( struct dev *dev, - struct eisa_driver *driver ); extern void enable_eisa_device ( struct eisa_device *eisa ); +extern void fill_eisa_nic ( struct nic *nic, struct eisa_device *eisa ); + +/* + * EISA bus global definition + * + */ +extern struct bus_driver eisa_driver; #endif /* EISA_H */ diff --git a/src/include/isa.h b/src/include/isa.h index 7d67502f..0082eab8 100644 --- a/src/include/isa.h +++ b/src/include/isa.h @@ -1,18 +1,29 @@ #ifndef ISA_H #define ISA_H +#include "stdint.h" #include "isa_ids.h" -#include "dev.h" +#include "nic.h" + +/* + * A location on an ISA bus + * + */ +struct isa_loc { + unsigned int probe_idx; +}; +#define ISA_MAX_PROBE_IDX 255 /* Unlikely to ever be more than ~20 */ /* * A physical ISA device * */ struct isa_device { - char *magic; /* must be first */ - unsigned int probe_idx; + const char *name; + unsigned int driver_probe_idx; uint16_t ioaddr; - int already_tried; + uint16_t mfg_id; + uint16_t prod_id; }; /* @@ -41,8 +52,7 @@ struct isa_driver { * Define an ISA driver * */ -#define ISA_DRIVER( _name, _probe_addrs, _probe_addr, _mfg_id, _prod_id ) { \ - .name = _name, \ +#define ISA_DRIVER( _probe_addrs, _probe_addr, _mfg_id, _prod_id ) { \ .probe_addrs = _probe_addrs, \ .addr_count = sizeof ( _probe_addrs ) / sizeof ( _probe_addrs[0] ), \ .probe_addr = _probe_addr, \ @@ -61,10 +71,13 @@ struct isa_driver { * Functions in isa.c * */ -extern int find_isa_device ( struct isa_device *eisa, - struct isa_driver *driver ); -extern int find_isa_boot_device ( struct dev *dev, - struct isa_driver *driver ); +extern void fill_isa_nic ( struct nic *nic, struct isa_device *isa ); + +/* + * ISA bus global definition + * + */ +extern struct bus_driver isa_driver; #endif /* ISA_H */ diff --git a/src/include/isapnp.h b/src/include/isapnp.h index 4d7bc395..58bb71e0 100644 --- a/src/include/isapnp.h +++ b/src/include/isapnp.h @@ -36,8 +36,9 @@ #ifndef ISAPNP_H #define ISAPNP_H +#include "stdint.h" +#include "nic.h" #include "isa_ids.h" -#include "dev.h" /* * ISAPnP constants @@ -154,12 +155,20 @@ struct isapnp_logdevid { uint16_t flags; } __attribute__ (( packed )); +/* + * A location on an ISAPnP bus + * + */ +struct isapnp_loc { + uint8_t csn; + uint8_t logdev; +}; + /* * A physical ISAPnP device * */ struct isapnp_device { - char *magic; /* must be first */ const char *name; uint8_t csn; uint8_t logdev; @@ -167,7 +176,6 @@ struct isapnp_device { uint16_t prod_id; uint16_t ioaddr; uint8_t irqno; - int already_tried; }; /* @@ -184,7 +192,6 @@ struct isapnp_id { * */ struct isapnp_driver { - const char *name; struct isapnp_id *ids; unsigned int id_count; }; @@ -193,21 +200,29 @@ struct isapnp_driver { * Define an ISAPnP driver * */ -#define ISAPNP_DRIVER( driver_name, isapnp_ids ) { \ - .name = driver_name, \ - .ids = isapnp_ids, \ - .id_count = sizeof ( isapnp_ids ) / sizeof ( isapnp_ids[0] ), \ +#define ISAPNP_DRIVER( _ids ) { \ + .ids = _ids, \ + .id_count = sizeof ( _ids ) / sizeof ( _ids[0] ), \ } /* * Functions in isapnp.c * */ -extern int find_isapnp_device ( struct isapnp_device *isapnp, - struct isapnp_driver *driver ); -extern int find_isapnp_boot_device ( struct dev *dev, - struct isapnp_driver *driver ); extern void activate_isapnp_device ( struct isapnp_device *isapnp, int active ); +extern void isapnp_fill_nic ( struct nic *nic, struct isapnp_device *isapnp ); + +/* + * ISAPnP bus global definition + * + */ +extern struct bus_driver isapnp_driver; + +/* + * ISAPnP read port. ROM prefix may be able to set this address. + * + */ +extern uint16_t isapnp_read_port; #endif /* ISAPNP_H */ diff --git a/src/include/mca.h b/src/include/mca.h index 3b4de21f..236c9002 100644 --- a/src/include/mca.h +++ b/src/include/mca.h @@ -20,22 +20,28 @@ #define MCA_MOTHERBOARD_SETUP_REG 0x94 #define MCA_ADAPTER_SETUP_REG 0x96 -#define MCA_MAX_SLOT_NR 8 +#define MCA_MAX_SLOT_NR 0x07 /* Must be 2^n - 1 */ #define MCA_POS_REG(n) (0x100+(n)) /* Is there a standard that would define this? */ #define GENERIC_MCA_VENDOR ISA_VENDOR ( 'M', 'C', 'A' ) +/* + * A location on an MCA bus + * + */ +struct mca_loc { + unsigned int slot; +}; + /* * A physical MCA device * */ struct mca_device { - char *magic; /* must be first */ const char *name; unsigned int slot; unsigned char pos[8]; - int already_tried; }; #define MCA_ID(mca) ( ( (mca)->pos[1] << 8 ) + (mca)->pos[0] ) @@ -53,7 +59,6 @@ struct mca_id { * */ struct mca_driver { - const char *name; struct mca_id *ids; unsigned int id_count; }; @@ -62,18 +67,15 @@ struct mca_driver { * Define an MCA driver * */ -#define MCA_DRIVER( driver_name, mca_ids ) { \ - .name = driver_name, \ - .ids = mca_ids, \ - .id_count = sizeof ( mca_ids ) / sizeof ( mca_ids[0] ), \ +#define MCA_DRIVER( _ids ) { \ + .ids = _ids, \ + .id_count = sizeof ( _ids ) / sizeof ( _ids[0] ), \ } /* - * Functions in mca.c + * MCA bus global definition * */ -extern int find_mca_device ( struct mca_device *mca, - struct mca_driver *driver ); -extern int find_mca_boot_device ( struct dev *dev, struct mca_driver *driver ); +extern struct bus_driver mca_driver; #endif