diff options
author | Michael Brown | 2007-03-10 19:08:33 +0100 |
---|---|---|
committer | Michael Brown | 2007-03-10 19:08:33 +0100 |
commit | 520d9c36af2f9e4f207dd7275a47ea97c668f749 (patch) | |
tree | fc665c3d4c250d3c9411219f580f5affbbf03873 /src/drivers | |
parent | Start a new release notes file (RELNOTES) in preparation for release (diff) | |
download | ipxe-520d9c36af2f9e4f207dd7275a47ea97c668f749.tar.gz ipxe-520d9c36af2f9e4f207dd7275a47ea97c668f749.tar.xz ipxe-520d9c36af2f9e4f207dd7275a47ea97c668f749.zip |
Updated ISAPnP, EISA, MCA and ISA buses to current device model.
ISA 3c509 is currently non-functional, although the EISA (3c509-eisa) and
MCA (3c529) variants should build OK.
None of this code is yet tested.
Diffstat (limited to 'src/drivers')
-rw-r--r-- | src/drivers/bus/eisa.c | 300 | ||||
-rw-r--r-- | src/drivers/bus/isa.c | 240 | ||||
-rw-r--r-- | src/drivers/bus/isa_ids.c | 14 | ||||
-rw-r--r-- | src/drivers/bus/isapnp.c | 604 | ||||
-rw-r--r-- | src/drivers/bus/mca.c | 276 | ||||
-rw-r--r-- | src/drivers/bus/pci.c | 6 | ||||
-rw-r--r-- | src/drivers/net/3c509-eisa.c | 6 | ||||
-rw-r--r-- | src/drivers/net/3c509.c | 6 | ||||
-rw-r--r-- | src/drivers/net/3c509.h | 2 | ||||
-rw-r--r-- | src/drivers/net/3c515.c | 6 | ||||
-rw-r--r-- | src/drivers/net/3c529.c | 6 | ||||
-rw-r--r-- | src/drivers/net/3c5x9.c | 2 | ||||
-rw-r--r-- | src/drivers/net/cs89x0.c | 2 | ||||
-rw-r--r-- | src/drivers/net/depca.c | 2 | ||||
-rw-r--r-- | src/drivers/net/eepro.c | 13 | ||||
-rw-r--r-- | src/drivers/net/legacy.c | 34 | ||||
-rw-r--r-- | src/drivers/net/mlx_ipoib/mt23108.c | 2 | ||||
-rw-r--r-- | src/drivers/net/mlx_ipoib/mt25218.c | 2 | ||||
-rw-r--r-- | src/drivers/net/ns8390.c | 2 | ||||
-rw-r--r-- | src/drivers/net/skel.c | 419 | ||||
-rw-r--r-- | src/drivers/net/smc9000.c | 2 | ||||
-rw-r--r-- | src/drivers/net/tg3.c | 7 | ||||
-rw-r--r-- | src/drivers/net/via-velocity.h | 4 |
23 files changed, 742 insertions, 1215 deletions
diff --git a/src/drivers/bus/eisa.c b/src/drivers/bus/eisa.c index 31c248f0..d9d02d72 100644 --- a/src/drivers/bus/eisa.c +++ b/src/drivers/bus/eisa.c @@ -1,179 +1,185 @@ -#include "string.h" -#include "io.h" -#include "timer.h" -#include "console.h" -#include "dev.h" -#include "eisa.h" - -/* - * 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. +#include <stdint.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <io.h> +#include <timer.h> +#include <gpxe/eisa.h> + +static struct eisa_driver eisa_drivers[0] + __table_start ( struct eisa_driver, eisa_drivers ); +static struct eisa_driver eisa_drivers_end[0] + __table_end ( struct eisa_driver, eisa_drivers ); + +static void eisabus_remove ( struct root_device *rootdev ); + +/** + * Reset and enable/disable an EISA device * + * @v eisa EISA device + * @v enabled 1=enable, 0=disable */ -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. - * +void eisa_device_enabled ( struct eisa_device *eisa, int enabled ) { + /* Set reset line high for 1000 µs. Spec says 500 µs, but + * this doesn't work for all cards, so we are conservative. */ - BUS_LOC_CHECK ( struct eisa_loc ); - BUS_DEV_CHECK ( struct eisa_device ); - - return ( eisa_loc->slot = ( ++eisa_loc->slot & EISA_MAX_SLOT ) ); -} - -/* - * Fill in parameters for an EISA device based on slot number - * - * Return 1 if device present, 0 otherwise - * - */ -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 ); - - /* Test for board present */ - outb ( 0xff, eisa->ioaddr + EISA_MFG_ID_HI ); - present = inb ( eisa->ioaddr + EISA_MFG_ID_HI ); - if ( present & 0x80 ) { - /* No board present */ - return 0; - } + outb ( EISA_CMD_RESET, eisa->ioaddr + EISA_GLOBAL_CONFIG ); + udelay ( 1000 ); /* Must wait 800 */ - /* Read mfg and product IDs. Yes, the resulting uint16_ts - * will be upside-down. This appears to be by design. + /* Set reset low and write a 1 to ENABLE. Delay again, in + * case the card takes a while to wake up. */ - eisa->mfg_id = ( inb ( eisa->ioaddr + EISA_MFG_ID_LO ) << 8 ) - + present; - eisa->prod_id = ( inb ( eisa->ioaddr + EISA_PROD_ID_LO ) << 8 ) - + inb ( eisa->ioaddr + EISA_PROD_ID_HI ); - - 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 ) ); + outb ( enabled ? EISA_CMD_ENABLE : 0, + eisa->ioaddr + EISA_GLOBAL_CONFIG ); + udelay ( 1000 ); /* Must wait 800 */ - return 1; + DBG ( "EISA %s device %02x\n", ( enabled ? "enabled" : "disabled" ), + eisa->slot ); } -/* - * Test whether or not a driver is capable of driving the device. +/** + * Probe an EISA device + * + * @v eisa EISA device + * @ret rc Return status code * + * Searches for a driver for the EISA device. If a driver is found, + * its probe() routine is called. */ -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; +static int eisa_probe ( struct eisa_device *eisa ) { + struct eisa_driver *driver; + struct eisa_device_id *id; unsigned int i; - - /* 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; + int rc; + + DBG ( "Adding EISA device %02x (%04x:%04x (\"%s\") io %x)\n", + eisa->slot, eisa->vendor_id, eisa->prod_id, + isa_id_string ( eisa->vendor_id, eisa->prod_id ), eisa->ioaddr ); + + for ( driver = eisa_drivers; driver < eisa_drivers_end; driver++ ) { + for ( i = 0 ; i < driver->id_count ; i++ ) { + id = &driver->ids[i]; + if ( id->vendor_id != eisa->vendor_id ) + continue; + if ( ISA_PROD_ID ( id->prod_id ) != + ISA_PROD_ID ( eisa->prod_id ) ) + continue; + eisa->driver = driver; + eisa->driver_name = id->name; + DBG ( "...using driver %s\n", eisa->driver_name ); + if ( ( rc = driver->probe ( eisa, id ) ) != 0 ) { + DBG ( "......probe failed\n" ); + continue; + } + return 0; } } - /* No device found */ - return 0; + DBG ( "...no driver found\n" ); + return -ENOTTY; } -/* - * Describe an EISA device +/** + * Remove an EISA device * + * @v eisa EISA device */ -static char * eisa_describe_device ( struct bus_dev *bus_dev ) { - struct eisa_device *eisa = ( struct eisa_device * ) bus_dev; - static char eisa_description[] = "EISA 00"; - - sprintf ( eisa_description + 5, "%hhx", eisa->slot ); - return eisa_description; +static void eisa_remove ( struct eisa_device *eisa ) { + eisa->driver->remove ( eisa ); + DBG ( "Removed EISA device %02x\n", eisa->slot ); } -/* - * Name an EISA device +/** + * Probe EISA root bus * - */ -static const char * eisa_name_device ( struct bus_dev *bus_dev ) { - struct eisa_device *eisa = ( struct eisa_device * ) bus_dev; - - return eisa->name; -} - -/* - * EISA bus operations table + * @v rootdev EISA bus root device * + * Scans the EISA bus for devices and registers all devices it can + * find. */ -struct bus_driver eisa_driver __bus_driver = { - .name = "EISA", - .next_location = eisa_next_location, - .fill_device = eisa_fill_device, - .check_driver = eisa_check_driver, - .describe_device = eisa_describe_device, - .name_device = eisa_name_device, -}; +static int eisabus_probe ( struct root_device *rootdev ) { + struct eisa_device *eisa = NULL; + unsigned int slot; + int rc; + + for ( slot = EISA_MIN_SLOT ; slot <= EISA_MAX_SLOT ; slot++ ) { + /* Allocate struct eisa_device */ + if ( ! eisa ) + eisa = malloc ( sizeof ( *eisa ) ); + if ( ! eisa ) { + rc = -ENOMEM; + goto err; + } + memset ( eisa, 0, sizeof ( *eisa ) ); + eisa->slot = slot; + eisa->ioaddr = EISA_SLOT_BASE ( eisa->slot ); + + /* Test for board present */ + outb ( 0xff, eisa->ioaddr + EISA_VENDOR_ID ); + eisa->vendor_id = + le16_to_cpu ( inw ( eisa->ioaddr + EISA_VENDOR_ID ) ); + eisa->prod_id = + le16_to_cpu ( inw ( eisa->ioaddr + EISA_PROD_ID ) ); + if ( eisa->vendor_id & 0x80 ) { + /* No board present */ + continue; + } -/* - * Fill in a nic structure - * - */ -void eisa_fill_nic ( struct nic *nic, struct eisa_device *eisa ) { + /* Add to device hierarchy */ + snprintf ( eisa->dev.name, sizeof ( eisa->dev.name ), + "EISA%02x", slot ); + eisa->dev.desc.bus_type = BUS_TYPE_EISA; + eisa->dev.desc.vendor = eisa->vendor_id; + eisa->dev.desc.device = eisa->prod_id; + eisa->dev.parent = &rootdev->dev; + list_add ( &eisa->dev.siblings, &rootdev->dev.children ); + INIT_LIST_HEAD ( &eisa->dev.children ); + + /* Look for a driver */ + if ( eisa_probe ( eisa ) == 0 ) { + /* eisadev registered, we can drop our ref */ + eisa = NULL; + } else { + /* Not registered; re-use struct */ + list_del ( &eisa->dev.siblings ); + } + } - /* Fill in ioaddr and irqno */ - nic->ioaddr = eisa->ioaddr; - nic->irqno = 0; + free ( eisa ); + return 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 ); + err: + free ( eisa ); + eisabus_remove ( rootdev ); + return rc; } -/* - * Reset and enable/disable an EISA device +/** + * Remove EISA root bus * + * @v rootdev EISA bus root device */ -void eisa_device_enabled ( struct eisa_device *eisa, int enabled ) { - /* Set reset line high for 1000 µs. Spec says 500 µs, but - * this doesn't work for all cards, so we are conservative. - */ - outb ( EISA_CMD_RESET, eisa->ioaddr + EISA_GLOBAL_CONFIG ); - udelay ( 1000 ); /* Must wait 800 */ +static void eisabus_remove ( struct root_device *rootdev ) { + struct eisa_device *eisa; + struct eisa_device *tmp; + + list_for_each_entry_safe ( eisa, tmp, &rootdev->dev.children, + dev.siblings ) { + eisa_remove ( eisa ); + list_del ( &eisa->dev.siblings ); + free ( eisa ); + } +} - /* Set reset low and write a 1 to ENABLE. Delay again, in - * case the card takes a while to wake up. - */ - outb ( enabled ? EISA_CMD_ENABLE : 0, - eisa->ioaddr + EISA_GLOBAL_CONFIG ); - udelay ( 1000 ); /* Must wait 800 */ +/** EISA bus root device driver */ +static struct root_driver eisa_root_driver = { + .probe = eisabus_probe, + .remove = eisabus_remove, +}; - DBG ( "EISA %s device %hhx\n", ( enabled ? "enabled" : "disabled" ), - eisa->slot ); -} +/** EISA bus root device */ +struct root_device eisa_root_device __root_device = { + .dev = { .name = "EISA" }, + .driver = &eisa_root_driver, +}; diff --git a/src/drivers/bus/isa.c b/src/drivers/bus/isa.c index d8b88fdb..a4105fd0 100644 --- a/src/drivers/bus/isa.c +++ b/src/drivers/bus/isa.c @@ -1,8 +1,10 @@ -#include "string.h" -#include "console.h" -#include "config/isa.h" -#include "dev.h" -#include "isa.h" +#include <stdint.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <io.h> +#include <gpxe/isa.h> /* * isa.c implements a "classical" port-scanning method of ISA device @@ -31,161 +33,143 @@ static isa_probe_addr_t isa_extra_probe_addrs[] = { ISA_PROBE_ADDRS #endif }; -#define isa_extra_probe_addr_count \ +#define ISA_EXTRA_PROBE_ADDR_COUNT \ ( sizeof ( isa_extra_probe_addrs ) / sizeof ( isa_extra_probe_addrs[0] ) ) +#define ISA_IOIDX_MIN( driver ) ( -ISA_EXTRA_PROBE_ADDR_COUNT ) #ifdef ISA_PROBE_ONLY -#define ISA_PROBE_ADDR_COUNT(driver) ( isa_extra_probe_addr_count ) +#define ISA_IOIDX_MAX( driver ) ( -1 ) #else -#define ISA_PROBE_ADDR_COUNT(driver) \ - ( isa_extra_probe_addr_count + (driver)->addr_count ) +#define ISA_IOIDX_MAX( driver ) ( (int) (driver)->addr_count - 1 ) #endif -/* - * Symbols defined by linker - * - */ +#define ISA_IOADDR( driver, ioidx ) \ + ( ( (ioidx) < 0 ) ? \ + isa_extra_probe_addrs[ (ioidx) + ISA_EXTRA_PROBE_ADDR_COUNT ] : \ + (driver)->probe_addrs[(ioidx)] ) + static struct isa_driver isa_drivers[0] __table_start ( struct isa_driver, isa_driver ); static struct isa_driver isa_drivers_end[0] __table_end ( struct isa_driver, isa_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. - * - * There is no sensible concept of a device location on an ISA bus, so - * we use the probe address list for each ISA driver to define the - * list of ISA locations. - * - */ -static int isa_next_location ( struct bus_loc *bus_loc ) { - struct isa_loc *isa_loc = ( struct isa_loc * ) bus_loc; - struct isa_driver *driver; - - /* - * 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 isa_loc ); - BUS_DEV_CHECK ( struct isa_device ); - - /* Move to next probe address within this driver */ - driver = &isa_drivers[isa_loc->driver]; - if ( ++isa_loc->probe_idx < ISA_PROBE_ADDR_COUNT ( driver ) ) - return 1; - - /* Move to next driver */ - isa_loc->probe_idx = 0; - if ( ( ++isa_loc->driver, ++driver ) < isa_drivers_end ) - return 1; - - isa_loc->driver = 0; - return 0; -} +static void isabus_remove ( struct root_device *rootdev ); -/* - * 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. +/** + * Probe an ISA device * + * @v isa ISA device + * @ret rc Return status code */ -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; - - /* Fill in struct isa from struct isa_loc */ - isa->driver = &isa_drivers[isa_loc->driver]; - 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 = isa->driver->probe_addrs[driver_probe_idx]; - } +static int isa_probe ( struct isa_device *isa ) { + int rc; + + DBG ( "Trying ISA driver %s at I/O %04x\n", + isa->driver->name, isa->ioaddr ); - /* Call driver's probe_addr method to determine if a device is - * physically present - */ - if ( isa->driver->probe_addr ( isa->ioaddr ) ) { - isa->name = isa->driver->name; - isa->mfg_id = isa->driver->mfg_id; - isa->prod_id = isa->driver->prod_id; - DBG ( "ISA found %s device at address %hx\n", - isa->name, isa->ioaddr ); - return 1; + if ( ( rc = isa->driver->probe ( isa ) ) != 0 ) { + DBG ( "...probe failed\n" ); + return rc; } + DBG ( "...device found\n" ); return 0; } -/* - * Test whether or not a driver is capable of driving the specified - * device. +/** + * Remove an ISA device * + * @v isa ISA 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; - - return ( driver == isa->driver ); +static void isa_remove ( struct isa_device *isa ) { + isa->driver->remove ( isa ); + DBG ( "Removed ISA%04x\n", isa->ioaddr ); } -/* - * Describe a ISA device +/** + * Probe ISA root bus + * + * @v rootdev ISA bus root device * + * Scans the ISA bus for devices and registers all devices it can + * find. */ -static char * isa_describe_device ( struct bus_dev *bus_dev ) { - struct isa_device *isa = ( struct isa_device * ) bus_dev; - static char isa_description[] = "ISA 0000 (00)"; +static int isabus_probe ( struct root_device *rootdev ) { + struct isa_device *isa = NULL; + struct isa_driver *driver; + int ioidx; + int rc; + + for ( driver = isa_drivers ; driver < isa_drivers_end ; driver++ ) { + for ( ioidx = ISA_IOIDX_MIN ( driver ) ; + ioidx <= ISA_IOIDX_MAX ( driver ) ; ioidx++ ) { + /* Allocate struct isa_device */ + if ( ! isa ) + isa = malloc ( sizeof ( *isa ) ); + if ( ! isa ) { + rc = -ENOMEM; + goto err; + } + memset ( isa, 0, sizeof ( *isa ) ); + isa->driver = driver; + isa->ioaddr = ISA_IOADDR ( driver, ioidx ); + + /* Add to device hierarchy */ + snprintf ( isa->dev.name, sizeof ( isa->dev.name ), + "ISA%04x", isa->ioaddr ); + isa->dev.desc.bus_type = BUS_TYPE_ISA; + isa->dev.desc.vendor = driver->vendor_id; + isa->dev.desc.device = driver->prod_id; + isa->dev.parent = &rootdev->dev; + list_add ( &isa->dev.siblings, + &rootdev->dev.children ); + INIT_LIST_HEAD ( &isa->dev.children ); + + /* Try probing at this I/O address */ + if ( isa_probe ( isa ) == 0 ) { + /* isadev registered, we can drop our ref */ + isa = NULL; + } else { + /* Not registered; re-use struct */ + list_del ( &isa->dev.siblings ); + } + } + } - sprintf ( isa_description + 4, "%hx (%hhx)", isa->ioaddr, - isa->driver - isa_drivers ); - return isa_description; + free ( isa ); + return 0; + + err: + free ( isa ); + isabus_remove ( rootdev ); + return rc; } -/* - * Name a ISA device +/** + * Remove ISA root bus * + * @v rootdev ISA bus root device */ -static const char * isa_name_device ( struct bus_dev *bus_dev ) { - struct isa_device *isa = ( struct isa_device * ) bus_dev; - - return isa->name; +static void isabus_remove ( struct root_device *rootdev ) { + struct isa_device *isa; + struct isa_device *tmp; + + list_for_each_entry_safe ( isa, tmp, &rootdev->dev.children, + dev.siblings ) { + isa_remove ( isa ); + list_del ( &isa->dev.siblings ); + free ( isa ); + } } -/* - * ISA bus operations table - * - */ -struct bus_driver isa_driver __bus_driver = { - .name = "ISA", - .next_location = isa_next_location, - .fill_device = isa_fill_device, - .check_driver = isa_check_driver, - .describe_device = isa_describe_device, - .name_device = isa_name_device, +/** ISA bus root device driver */ +static struct root_driver isa_root_driver = { + .probe = isabus_probe, + .remove = isabus_remove, }; -/* - * 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 ); -} +/** ISA bus root device */ +struct root_device isa_root_device __root_device = { + .dev = { .name = "ISA" }, + .driver = &isa_root_driver, +}; diff --git a/src/drivers/bus/isa_ids.c b/src/drivers/bus/isa_ids.c index a175ed45..73101584 100644 --- a/src/drivers/bus/isa_ids.c +++ b/src/drivers/bus/isa_ids.c @@ -1,15 +1,15 @@ -#include "stdint.h" -#include "byteswap.h" -#include "console.h" -#include "isa_ids.h" +#include <stdint.h> +#include <stdio.h> +#include <byteswap.h> +#include <gpxe/isa_ids.h> /* * EISA and ISAPnP IDs are actually mildly human readable, though in a * somewhat brain-damaged way. * */ -char * isa_id_string ( uint16_t vendor, uint16_t product ) { - static unsigned char buf[7]; +char * isa_id_string ( unsigned int vendor, unsigned int product ) { + static char buf[7]; int i; /* Vendor ID is a compressed ASCII string */ @@ -20,7 +20,7 @@ char * isa_id_string ( uint16_t vendor, uint16_t product ) { } /* Product ID is a 4-digit hex string */ - sprintf ( &buf[3], "%hx", bswap_16 ( product ) ); + sprintf ( &buf[3], "%04x", bswap_16 ( product ) ); return buf; } diff --git a/src/drivers/bus/isapnp.c b/src/drivers/bus/isapnp.c index 41c9cb28..96bc60ec 100644 --- a/src/drivers/bus/isapnp.c +++ b/src/drivers/bus/isapnp.c @@ -60,80 +60,77 @@ * */ -#include "string.h" -#include "timer.h" -#include "io.h" -#include "console.h" -#include "dev.h" -#include "isapnp.h" +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include <io.h> +#include <timer.h> +#include <gpxe/isapnp.h> /** * ISAPnP Read Port address. * + * ROM prefix may be able to set this address, which is why this is + * non-static. */ uint16_t isapnp_read_port; -/** - * Highest assigned CSN. - * - * Note that @b we do not necessarily assign CSNs; it could be done by - * the PnP BIOS instead. We therefore set this only when we first try - * to Wake[CSN] a device and find that there's nothing there. Page 16 - * (PDF page 22) of the ISAPnP spec states that "Valid Card Select - * Numbers for identified ISA cards range from 1 to 255 and must be - * assigned sequentially starting from 1", so we are (theoretically, - * at least) safe to assume that there are no ISAPnP cards at CSNs - * higher than the first unused CSN. - * - */ -static uint8_t isapnp_max_csn = 0xff; +static struct isapnp_driver isapnp_drivers[0] + __table_start ( struct isapnp_driver, isapnp_drivers ); +static struct isapnp_driver isapnp_drivers_end[0] + __table_end ( struct isapnp_driver, isapnp_drivers ); + +static void isapnpbus_remove ( struct root_device *rootdev ); /* * ISAPnP utility functions * */ -#define ISAPNP_CARD_ID_FMT "ID %hx:%hx (\"%s\") serial %x" +#define ISAPNP_CARD_ID_FMT "ID %04x:%04x (\"%s\") serial %lx" #define ISAPNP_CARD_ID_DATA(identifier) \ (identifier)->vendor_id, (identifier)->prod_id, \ isa_id_string ( (identifier)->vendor_id, (identifier)->prod_id ), \ (identifier)->serial -#define ISAPNP_DEV_ID_FMT "ID %hx:%hx (\"%s\")" +#define ISAPNP_DEV_ID_FMT "ID %04x:%04x (\"%s\")" #define ISAPNP_DEV_ID_DATA(isapnp) \ (isapnp)->vendor_id, (isapnp)->prod_id, \ isa_id_string ( (isapnp)->vendor_id, (isapnp)->prod_id ) -static inline void isapnp_write_address ( uint8_t address ) { +static inline void isapnp_write_address ( unsigned int address ) { outb ( address, ISAPNP_ADDRESS ); } -static inline void isapnp_write_data ( uint8_t data ) { +static inline void isapnp_write_data ( unsigned int data ) { outb ( data, ISAPNP_WRITE_DATA ); } -static inline uint8_t isapnp_read_data ( void ) { +static inline unsigned int isapnp_read_data ( void ) { return inb ( isapnp_read_port ); } -static inline void isapnp_write_byte ( uint8_t address, uint8_t value ) { +static inline void isapnp_write_byte ( unsigned int address, + unsigned int value ) { isapnp_write_address ( address ); isapnp_write_data ( value ); } -static inline uint8_t isapnp_read_byte ( uint8_t address ) { +static inline unsigned int isapnp_read_byte ( unsigned int address ) { isapnp_write_address ( address ); return isapnp_read_data (); } -static inline uint16_t isapnp_read_word ( uint8_t address ) { +static inline unsigned int isapnp_read_word ( unsigned int address ) { /* Yes, they're in big-endian order */ return ( ( isapnp_read_byte ( address ) << 8 ) - + isapnp_read_byte ( address + 1 ) ); + | isapnp_read_byte ( address + 1 ) ); } /** Inform cards of a new read port address */ static inline void isapnp_set_read_port ( void ) { - isapnp_write_byte ( ISAPNP_READPORT, isapnp_read_port >> 2 ); + isapnp_write_byte ( ISAPNP_READPORT, ( isapnp_read_port >> 2 ) ); } /** @@ -141,7 +138,6 @@ static inline void isapnp_set_read_port ( void ) { * * Only cards currently in the Sleep state will respond to this * command. - * */ static inline void isapnp_serialisolation ( void ) { isapnp_write_address ( ISAPNP_SERIALISOLATION ); @@ -152,7 +148,6 @@ static inline void isapnp_serialisolation ( void ) { * * All cards will respond to this command, regardless of their current * state. - * */ static inline void isapnp_wait_for_key ( void ) { isapnp_write_byte ( ISAPNP_CONFIGCONTROL, ISAPNP_CONFIG_WAIT_FOR_KEY ); @@ -163,7 +158,6 @@ static inline void isapnp_wait_for_key ( void ) { * * Only cards currently in the Sleep state will respond to this * command. - * */ static inline void isapnp_reset_csn ( void ) { isapnp_write_byte ( ISAPNP_CONFIGCONTROL, ISAPNP_CONFIG_RESET_CSN ); @@ -179,17 +173,16 @@ static inline void isapnp_reset_csn ( void ) { * Only cards currently in the Sleep, Isolation, or Config states will * respond to this command. The card that has the specified CSN will * enter the Config state, all other cards will enter the Sleep state. - * */ static inline void isapnp_wake ( uint8_t csn ) { isapnp_write_byte ( ISAPNP_WAKE, csn ); } -static inline uint8_t isapnp_read_resourcedata ( void ) { +static inline unsigned int isapnp_read_resourcedata ( void ) { return isapnp_read_byte ( ISAPNP_RESOURCEDATA ); } -static inline uint8_t isapnp_read_status ( void ) { +static inline unsigned int isapnp_read_status ( void ) { return isapnp_read_byte ( ISAPNP_STATUS ); } @@ -197,38 +190,35 @@ static inline uint8_t isapnp_read_status ( void ) { * Assign a Card Select Number to a card, and enter the Config state. * * @v csn Card Select Number - * @ret None - - * @err None - * * Only cards in the Isolation state will respond to this command. * The isolation protocol is designed so that only one card will * remain in the Isolation state by the time the isolation protocol * completes. - * */ -static inline void isapnp_write_csn ( uint8_t csn ) { +static inline void isapnp_write_csn ( unsigned int csn ) { isapnp_write_byte ( ISAPNP_CARDSELECTNUMBER, csn ); } -static inline void isapnp_logicaldevice ( uint8_t logdev ) { +static inline void isapnp_logicaldevice ( unsigned int logdev ) { isapnp_write_byte ( ISAPNP_LOGICALDEVICENUMBER, logdev ); } -static inline void isapnp_activate ( uint8_t logdev ) { +static inline void isapnp_activate ( unsigned int logdev ) { isapnp_logicaldevice ( logdev ); isapnp_write_byte ( ISAPNP_ACTIVATE, 1 ); } -static inline void isapnp_deactivate ( uint8_t logdev ) { +static inline void isapnp_deactivate ( unsigned int logdev ) { isapnp_logicaldevice ( logdev ); isapnp_write_byte ( ISAPNP_ACTIVATE, 0 ); } -static inline uint16_t isapnp_read_iobase ( unsigned int index ) { +static inline unsigned int isapnp_read_iobase ( unsigned int index ) { return isapnp_read_word ( ISAPNP_IOBASE ( index ) ); } -static inline uint8_t isapnp_read_irqno ( unsigned int index ) { +static inline unsigned int isapnp_read_irqno ( unsigned int index ) { return isapnp_read_byte ( ISAPNP_IRQNO ( index ) ); } @@ -242,7 +232,6 @@ static void isapnp_delay ( void ) { * @v lfsr Current value of the LFSR * @v input_bit Current input bit to the LFSR * @ret lfsr Next value of the LFSR - * @err None - * * This routine implements the linear feedback shift register as * described in Appendix B of the PnP ISA spec. The hardware @@ -250,9 +239,9 @@ static void isapnp_delay ( void ) { * think this is probably the smallest possible implementation in * software. Six instructions when input_bit is a constant 0 (for * isapnp_send_key). :) - * */ -static inline uint8_t isapnp_lfsr_next ( uint8_t lfsr, int input_bit ) { +static inline unsigned int isapnp_lfsr_next ( unsigned int lfsr, + unsigned int input_bit ) { register uint8_t lfsr_next; lfsr_next = lfsr >> 1; @@ -265,11 +254,10 @@ static inline uint8_t isapnp_lfsr_next ( uint8_t lfsr, int input_bit ) { * * Sending the key causes all ISAPnP cards that are currently in the * Wait for Key state to transition into the Sleep state. - * */ static void isapnp_send_key ( void ) { unsigned int i; - uint8_t lfsr; + unsigned int lfsr; isapnp_delay(); isapnp_write_address ( 0x00 ); @@ -285,19 +273,17 @@ static void isapnp_send_key ( void ) { /** * Compute ISAPnP identifier checksum * - * @v identifier ISAPnP identifier - * @ret checksum Expected checksum value - * @err None - - * + * @v identifier ISAPnP identifier + * @ret checksum Expected checksum value */ -static uint8_t isapnp_checksum ( struct isapnp_identifier *identifier ) { - int i, j; - uint8_t lfsr; - uint8_t byte; +static unsigned int isapnp_checksum ( struct isapnp_identifier *identifier ) { + unsigned int i, j; + unsigned int lfsr; + unsigned int byte; lfsr = ISAPNP_LFSR_SEED; for ( i = 0 ; i < 8 ; i++ ) { - byte = ( (char *) identifier )[i]; + byte = * ( ( ( uint8_t * ) identifier ) + i ); for ( j = 0 ; j < 8 ; j++ ) { lfsr = isapnp_lfsr_next ( lfsr, byte ); byte >>= 1; @@ -309,17 +295,18 @@ static uint8_t isapnp_checksum ( struct isapnp_identifier *identifier ) { /* * Read a byte of resource data from the current location * + * @ret byte Byte of resource data */ -static inline uint8_t isapnp_peek_byte ( void ) { - int i; +static inline unsigned int isapnp_peek_byte ( void ) { + unsigned int i; /* Wait for data to be ready */ - for ( i = 0 ; i < 20 ; i ++ ) { + for ( i = 0 ; i < 20 ; i++ ) { if ( isapnp_read_status() & 0x01 ) { /* Byte ready - read it */ return isapnp_read_resourcedata(); } - isapnp_delay (); + isapnp_delay(); } /* Data never became ready - return 0xff */ return 0xff; @@ -330,22 +317,18 @@ static inline uint8_t isapnp_peek_byte ( void ) { * * @v buf Buffer in which to store data, or NULL * @v bytes Number of bytes to read - * @ret None - - * @err None - * * Resource data is read from the current location. If #buf is NULL, * the data is discarded. - * */ -static void isapnp_peek ( uint8_t *buf, size_t bytes ) { +static void isapnp_peek ( void *buf, size_t len ) { unsigned int i; - uint8_t byte; + unsigned int byte; - for ( i = 0 ; i < bytes ; i++) { + for ( i = 0 ; i < len ; i++) { byte = isapnp_peek_byte(); - if ( buf ) { - buf[i] = byte; - } + if ( buf ) + * ( ( uint8_t * ) buf + i ) = byte; } } @@ -354,40 +337,59 @@ static void isapnp_peek ( uint8_t *buf, size_t bytes ) { * * @v wanted_tag The tag that we're looking for * @v buf Buffer in which to store the tag's contents - * @ret True Tag was found - * @ret False Tag was not found - * @err None - + * @v len Length of buffer + * @ret rc Return status code * * Scan through the resource data until we find a particular tag, and - * read its contents into a buffer. It is the caller's responsibility - * to ensure that #buf is large enough to contain a tag of the - * requested size. - * + * read its contents into a buffer. */ -static int isapnp_find_tag ( uint8_t wanted_tag, uint8_t *buf ) { - uint8_t tag; - uint16_t len; +static int isapnp_find_tag ( unsigned int wanted_tag, void *buf, size_t len ) { + unsigned int tag; + unsigned int tag_len; DBG2 ( "ISAPnP read tag" ); do { tag = isapnp_peek_byte(); if ( ISAPNP_IS_SMALL_TAG ( tag ) ) { - len = ISAPNP_SMALL_TAG_LEN ( tag ); + tag_len = ISAPNP_SMALL_TAG_LEN ( tag ); tag = ISAPNP_SMALL_TAG_NAME ( tag ); } else { - len = isapnp_peek_byte() + ( isapnp_peek_byte() << 8 ); + tag_len = ( isapnp_peek_byte() + + ( isapnp_peek_byte() << 8 ) ); tag = ISAPNP_LARGE_TAG_NAME ( tag ); } - DBG2 ( " %hhx (%hhx)", tag, len ); + DBG2 ( " %02x (%02x)", tag, tag_len ); if ( tag == wanted_tag ) { + if ( len > tag_len ) + len = tag_len; isapnp_peek ( buf, len ); DBG2 ( "\n" ); - return 1; + return 0; } else { - isapnp_peek ( NULL, len ); + isapnp_peek ( NULL, tag_len ); } } while ( tag != ISAPNP_TAG_END ); DBG2 ( "\n" ); + return -ENOENT; +} + +/** + * Find specified Logical Device ID tag + * + * @v logdev Logical device ID + * @v logdevid Logical device ID structure to fill in + * @ret rc Return status code + */ +static int isapnp_find_logdevid ( unsigned int logdev, + struct isapnp_logdevid *logdevid ) { + unsigned int i; + int rc; + + for ( i = 0 ; i <= logdev ; i++ ) { + if ( ( rc = isapnp_find_tag ( ISAPNP_TAG_LOGDEVID, logdevid, + sizeof ( *logdevid ) ) ) != 0 ) + return rc; + } return 0; } @@ -401,37 +403,36 @@ static int isapnp_find_tag ( uint8_t wanted_tag, uint8_t *buf ) { * * The state diagram on page 18 (PDF page 24) of the PnP ISA spec * gives the best overview of what happens here. - * */ static int isapnp_try_isolate ( void ) { struct isapnp_identifier identifier; unsigned int i, j; unsigned int seen_55aa, seen_life; unsigned int csn = 0; - uint16_t data; - uint8_t byte; + unsigned int data; + unsigned int byte; - DBG ( "ISAPnP attempting isolation at read port %hx\n", + DBG ( "ISAPnP attempting isolation at read port %04x\n", isapnp_read_port ); /* Place all cards into the Sleep state, whatever state * they're currently in. */ - isapnp_wait_for_key (); - isapnp_send_key (); + isapnp_wait_for_key(); + isapnp_send_key(); /* Reset all assigned CSNs */ - isapnp_reset_csn (); + isapnp_reset_csn(); isapnp_delay(); isapnp_delay(); /* Place all cards into the Isolation state */ isapnp_wait_for_key (); - isapnp_send_key (); + isapnp_send_key(); isapnp_wake ( 0x00 ); /* Set the read port */ - isapnp_set_read_port (); + isapnp_set_read_port(); isapnp_delay(); while ( 1 ) { @@ -442,7 +443,7 @@ static int isapnp_try_isolate ( void ) { */ /* Initiate serial isolation */ - isapnp_serialisolation (); + isapnp_serialisolation(); isapnp_delay(); /* Read identifier serially via the ISAPnP read port. */ @@ -451,9 +452,9 @@ static int isapnp_try_isolate ( void ) { for ( i = 0 ; i < 9 ; i++ ) { byte = 0; for ( j = 0 ; j < 8 ; j++ ) { - data = isapnp_read_data (); + data = isapnp_read_data(); isapnp_delay(); - data = ( data << 8 ) | isapnp_read_data (); + data = ( ( data << 8 ) | isapnp_read_data() ); isapnp_delay(); byte >>= 1; if ( data != 0xffff ) { @@ -464,7 +465,7 @@ static int isapnp_try_isolate ( void ) { } } } - ( (char *) &identifier )[i] = byte; + *( ( ( uint8_t * ) &identifier ) + i ) = byte; } /* If we didn't see any 55aa patterns, stop here */ @@ -487,8 +488,8 @@ static int isapnp_try_isolate ( void ) { /* If the checksum was invalid stop here */ if ( identifier.checksum != isapnp_checksum ( &identifier) ) { DBG ( "ISAPnP found malformed card " - ISAPNP_CARD_ID_FMT "\n with checksum %hhx " - "(should be %hhx), trying new read port\n", + ISAPNP_CARD_ID_FMT "\n with checksum %02x " + "(should be %02x), trying new read port\n", ISAPNP_CARD_ID_DATA ( &identifier ), identifier.checksum, isapnp_checksum ( &identifier) ); @@ -499,7 +500,7 @@ static int isapnp_try_isolate ( void ) { /* Give the device a CSN */ csn++; DBG ( "ISAPnP found card " ISAPNP_CARD_ID_FMT - ", assigning CSN %hhx\n", + ", assigning CSN %02x\n", ISAPNP_CARD_ID_DATA ( &identifier ), csn ); isapnp_write_csn ( csn ); @@ -513,11 +514,11 @@ static int isapnp_try_isolate ( void ) { } /* Place all cards in Wait for Key state */ - isapnp_wait_for_key (); + isapnp_wait_for_key(); /* Return number of cards found */ if ( csn > 0 ) { - DBG ( "ISAPnP found %d cards at read port %hx\n", + DBG ( "ISAPnP found %d cards at read port %04x\n", csn, isapnp_read_port ); } return csn; @@ -539,281 +540,222 @@ static void isapnp_isolate ( void ) { continue; /* If we detect any ISAPnP cards at this location, stop */ - if ( isapnp_try_isolate () >= 0 ) + if ( isapnp_try_isolate() >= 0 ) return; } } /** - * Increment a #bus_loc structure to the next possible ISAPnP - * location. + * Activate or deactivate an ISAPnP device. * - * @v bus_loc Bus location - * @ret True #bus_loc contains a valid ISAPnP location - * @ret False There are no more valid ISAPnP locations + * @v isapnp ISAPnP device + * @v activation True to enable, False to disable the device + * @ret None - * @err None - * - * If there are no more valid locations, the #bus_loc structure will - * be zeroed. - * - */ -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. - * - * @v bus_dev Bus device to be filled in - * @v bus_loc Bus location as filled in by isapnp_next_location() - * @ret True A device is present at this location - * @ret False No device is present at this location - * @err None - + * This routine simply activates the device in its current + * configuration, or deactivates the device. It does not attempt any + * kind of resource arbitration. * */ -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 to see if we are already past the maximum CSN */ - if ( isapnp->csn > isapnp_max_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 */ +void isapnp_device_activation ( struct isapnp_device *isapnp, + int activation ) { + /* Wake the card and select the logical device */ isapnp_wait_for_key (); isapnp_send_key (); isapnp_wake ( isapnp->csn ); - - /* 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 ) { - isapnp_max_csn = isapnp->csn - 1; - 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, - ( char * ) &logdevid ) ) { - /* No tag for this device */ - if ( isapnp->logdev == 0 ) { - DBG ( "ISAPnP found no device %hhx.0 on card " - ISAPNP_CARD_ID_FMT "\n", isapnp->csn, - ISAPNP_CARD_ID_DATA ( &identifier ) ); - } - cache.csn = isapnp->csn; - cache.first_nonexistent_logdev = isapnp->logdev; - return 0; - } - } - - /* Read information from logdevid structure */ - isapnp->vendor_id = logdevid.vendor_id; - isapnp->prod_id = logdevid.prod_id; - - /* Select the logical device */ isapnp_logicaldevice ( isapnp->logdev ); - /* Read the current ioaddr and irqno */ - isapnp->ioaddr = isapnp_read_iobase ( 0 ); - isapnp->irqno = isapnp_read_irqno ( 0 ); + /* Activate/deactivate the logical device */ + isapnp_activate ( activation ); + isapnp_delay(); /* Return all cards to Wait for Key state */ isapnp_wait_for_key (); - DBG ( "ISAPnP found device %hhx.%hhx " ISAPNP_DEV_ID_FMT - ", base %hx irq %d\n", isapnp->csn, isapnp->logdev, - ISAPNP_DEV_ID_DATA ( isapnp ), isapnp->ioaddr, isapnp->irqno ); - DBG ( " on card " ISAPNP_CARD_ID_FMT "\n", - ISAPNP_CARD_ID_DATA ( &identifier ) ); - - return 1; + DBG ( "ISAPnP %s device %02x:%02x\n", + ( activation ? "activated" : "deactivated" ), + isapnp->csn, isapnp->logdev ); } /** - * Test whether or not a driver is capable of driving the device. + * Probe an ISAPnP device * - * @v bus_dev Bus device as filled in by isapnp_fill_device() - * @v device_driver Device driver - * @ret True Driver is capable of driving this device - * @ret False Driver is not capable of driving this device - * @err None - + * @v isapnp ISAPnP device + * @ret rc Return status code * + * Searches for a driver for the ISAPnP device. If a driver is found, + * its probe() routine is called. */ -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; +static int isapnp_probe ( struct isapnp_device *isapnp ) { + struct isapnp_driver *driver; + struct isapnp_device_id *id; unsigned int i; - - /* 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, device_driver->name ); - isapnp->name = id->name; - return 1; + int rc; + + DBG ( "Adding ISAPnP device %02x:%02x (%04x:%04x (\"%s\") " + "io %x irq %d)\n", isapnp->csn, isapnp->logdev, + isapnp->vendor_id, isapnp->prod_id, + isa_id_string ( isapnp->vendor_id, isapnp->prod_id ), + isapnp->ioaddr, isapnp->irqno ); + + for ( driver = isapnp_drivers; driver < isapnp_drivers_end; driver++ ){ + for ( i = 0 ; i < driver->id_count ; i++ ) { + id = &driver->ids[i]; + if ( id->vendor_id != isapnp->vendor_id ) + continue; + if ( ISA_PROD_ID ( id->prod_id ) != + ISA_PROD_ID ( isapnp->prod_id ) ) + continue; + isapnp->driver = driver; + isapnp->driver_name = id->name; + DBG ( "...using driver %s\n", isapnp->driver_name ); + if ( ( rc = driver->probe ( isapnp, id ) ) != 0 ) { + DBG ( "......probe failed\n" ); + continue; + } + return 0; } } - return 0; + DBG ( "...no driver found\n" ); + return -ENOTTY; } /** - * Describe an ISAPnP device. - * - * @v bus_dev Bus device as filled in by isapnp_fill_device() - * @ret string Printable string describing the device - * @err None - - * - * The string returned by isapnp_describe_device() is valid only until - * the next call to isapnp_describe_device(). + * Remove an ISAPnP device * + * @v isapnp ISAPnP device */ -static char * isapnp_describe_device ( struct bus_dev *bus_dev ) { - struct isapnp_device *isapnp = ( struct isapnp_device * ) bus_dev; - static char isapnp_description[] = "ISAPnP 00:00"; - - sprintf ( isapnp_description + 7, "%hhx:%hhx", - isapnp->csn, isapnp->logdev ); - return isapnp_description; +static void isapnp_remove ( struct isapnp_device *isapnp ) { + isapnp->driver->remove ( isapnp ); + DBG ( "Removed ISAPnP device %02x:%02x\n", + isapnp->csn, isapnp->logdev ); } /** - * Name an ISAPnP device. + * Probe ISAPnP root bus * - * @v bus_dev Bus device as filled in by isapnp_fill_device() - * @ret string Printable string naming the device - * @err None - - * - * The string returned by isapnp_name_device() is valid only until the - * next call to isapnp_name_device(). + * @v rootdev ISAPnP bus root device * + * Scans the ISAPnP bus for devices and registers all devices it can + * find. */ -static const char * isapnp_name_device ( struct bus_dev *bus_dev ) { - struct isapnp_device *isapnp = ( struct isapnp_device * ) bus_dev; - - return isapnp->name; -} +static int isapnpbus_probe ( struct root_device *rootdev ) { + struct isapnp_device *isapnp = NULL; + struct isapnp_identifier identifier; + struct isapnp_logdevid logdevid; + unsigned int csn; + unsigned int logdev; + int rc; -/* - * ISAPnP bus operations table - * - */ -struct bus_driver isapnp_driver __bus_driver = { - .name = "ISAPnP", - .next_location = isapnp_next_location, - .fill_device = isapnp_fill_device, - .check_driver = isapnp_check_driver, - .describe_device = isapnp_describe_device, - .name_device = isapnp_name_device, -}; + /* Perform isolation if it hasn't yet been done */ + if ( ! isapnp_read_port ) + isapnp_isolate(); -/** - * Activate or deactivate an ISAPnP device. - * - * @v isapnp ISAPnP device - * @v activation True to enable, False to disable the device - * @ret None - - * @err None - - * - * This routine simply activates the device in its current - * configuration, or deactivates the device. It does not attempt any - * kind of resource arbitration. - * - */ -void isapnp_device_activation ( struct isapnp_device *isapnp, - int activation ) { - /* Wake the card and select the logical device */ - isapnp_wait_for_key (); - isapnp_send_key (); - isapnp_wake ( isapnp->csn ); - isapnp_logicaldevice ( isapnp->logdev ); + for ( csn = 1 ; csn <= 0xff ; csn++ ) { + for ( logdev = 0 ; logdev <= 0xff ; logdev++ ) { - /* Activate/deactivate the logical device */ - isapnp_activate ( activation ); - isapnp_delay(); + /* Allocate struct isapnp_device */ + if ( ! isapnp ) + isapnp = malloc ( sizeof ( *isapnp ) ); + if ( ! isapnp ) { + rc = -ENOMEM; + goto err; + } + memset ( isapnp, 0, sizeof ( *isapnp ) ); + isapnp->csn = csn; + isapnp->logdev = logdev; + + /* Wake the card */ + isapnp_wait_for_key(); + isapnp_send_key(); + isapnp_wake ( csn ); + + /* Read the card identifier */ + isapnp_peek ( &identifier, sizeof ( identifier ) ); + + /* No card with this CSN; stop here */ + if ( identifier.vendor_id & 0x80 ) + goto done; + + /* Find the Logical Device ID tag */ + if ( ( rc = isapnp_find_logdevid ( logdev, + &logdevid ) ) != 0){ + /* No more logical devices; go to next CSN */ + break; + } + + /* Select the logical device */ + isapnp_logicaldevice ( logdev ); + + /* Populate struct isapnp_device */ + isapnp->vendor_id = logdevid.vendor_id; + isapnp->prod_id = logdevid.prod_id; + isapnp->ioaddr = isapnp_read_iobase ( 0 ); + isapnp->irqno = isapnp_read_irqno ( 0 ); + + /* Return all cards to Wait for Key state */ + isapnp_wait_for_key(); + + /* Add to device hierarchy */ + snprintf ( isapnp->dev.name, + sizeof ( isapnp->dev.name ), + "ISAPnP%02x:%02x", csn, logdev ); + isapnp->dev.desc.bus_type = BUS_TYPE_ISAPNP; + isapnp->dev.desc.vendor = isapnp->vendor_id; + isapnp->dev.desc.device = isapnp->prod_id; + isapnp->dev.parent = &rootdev->dev; + list_add ( &isapnp->dev.siblings, + &rootdev->dev.children ); + INIT_LIST_HEAD ( &isapnp->dev.children ); + + /* Look for a driver */ + if ( isapnp_probe ( isapnp ) == 0 ) { + /* isapnpdev registered, we can drop our ref */ + isapnp = NULL; + } else { + /* Not registered; re-use struct */ + list_del ( &isapnp->dev.siblings ); + } + } + } - /* Return all cards to Wait for Key state */ - isapnp_wait_for_key (); + done: + free ( isapnp ); + return 0; - DBG ( "ISAPnP %s device %hhx.%hhx\n", - ( activation ? "activated" : "deactivated" ), - isapnp->csn, isapnp->logdev ); + err: + free ( isapnp ); + isapnpbus_remove ( rootdev ); + return rc; } /** - * Fill in a nic structure. - * - * @v nic NIC structure to be filled in - * @v isapnp ISAPnP device - * @ret None - - * @err None - - * - * This fills in generic NIC parameters (e.g. I/O address and IRQ - * number) that can be determined directly from the ISAPnP device, - * without any driver-specific knowledge. + * Remove ISAPnP root bus * + * @v rootdev ISAPnP bus root device */ -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 ); +static void isapnpbus_remove ( struct root_device *rootdev ) { + struct isapnp_device *isapnp; + struct isapnp_device *tmp; + + list_for_each_entry_safe ( isapnp, tmp, &rootdev->dev.children, + dev.siblings ) { + isapnp_remove ( isapnp ); + list_del ( &isapnp->dev.siblings ); + free ( isapnp ); + } } +/** ISAPnP bus root device driver */ +static struct root_driver isapnp_root_driver = { + .probe = isapnpbus_probe, + .remove = isapnpbus_remove, +}; + +/** ISAPnP bus root device */ +struct root_device isapnp_root_device __root_device = { + .dev = { .name = "ISAPnP" }, + .driver = &isapnp_root_driver, +}; diff --git a/src/drivers/bus/mca.c b/src/drivers/bus/mca.c index 63044295..375a6834 100644 --- a/src/drivers/bus/mca.c +++ b/src/drivers/bus/mca.c @@ -5,157 +5,177 @@ * */ -#include "string.h" -#include "io.h" -#include "console.h" -#include "dev.h" -#include "mca.h" - -/* - * 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. +#include <stdint.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <io.h> +#include <timer.h> +#include <gpxe/mca.h> + +static struct mca_driver mca_drivers[0] + __table_start ( struct mca_driver, mca_drivers ); +static struct mca_driver mca_drivers_end[0] + __table_end ( struct mca_driver, mca_drivers ); + +static void mcabus_remove ( struct root_device *rootdev ); + +/** + * Probe an MCA device * - */ -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_loc->slot & MCA_MAX_SLOT_NR ) ); -} - -/* - * Fill in parameters for an MCA device based on slot number + * @v mca MCA device + * @ret rc Return status code * + * Searches for a driver for the MCA device. If a driver is found, + * its probe() routine is called. */ -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 ); - - /* Select the slot */ - outb_p ( 0x8 | ( mca->slot & 0xf ), MCA_ADAPTER_SETUP_REG ); - - /* Read the POS registers */ - seen_non_ff = 0; - for ( i = 0 ; i < ( sizeof ( mca->pos ) / sizeof ( mca->pos[0] ) ) ; - i++ ) { - mca->pos[i] = inb_p ( MCA_POS_REG ( i ) ); - if ( mca->pos[i] != 0xff ) - seen_non_ff = 1; - } - - /* If all POS registers are 0xff, this means there's no device - * present - */ - if ( ! seen_non_ff ) - return 0; - - /* Kill all setup modes */ - outb_p ( 0, MCA_ADAPTER_SETUP_REG ); +static int mca_probe ( struct mca_device *mca ) { + struct mca_driver *driver; + struct mca_device_id *id; + unsigned int i; + int rc; - DBG ( "MCA found slot %d id %hx " - "(POS %hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx)\n", + DBG ( "Adding MCA slot %02x (ID %04x POS " + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x)\n", mca->slot, MCA_ID ( mca ), mca->pos[0], mca->pos[1], mca->pos[2], mca->pos[3], mca->pos[4], mca->pos[5], mca->pos[6], mca->pos[7] ); - return 1; -} - -/* - * Test whether or not a driver is capable of driving the device. - * - */ -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; - - /* 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, device_driver->name ); - mca->name = id->name; - return 1; + for ( driver = mca_drivers; driver < mca_drivers_end; driver++ ){ + for ( i = 0 ; i < driver->id_count ; i++ ) { + id = &driver->ids[i]; + if ( id->id != MCA_ID ( mca ) ) + continue; + mca->driver = driver; + mca->driver_name = id->name; + DBG ( "...using driver %s\n", mca->driver_name ); + if ( ( rc = driver->probe ( mca, id ) ) != 0 ) { + DBG ( "......probe failed\n" ); + continue; + } + return 0; } } - /* No device found */ - return 0; + DBG ( "...no driver found\n" ); + return -ENOTTY; } -/* - * Describe an MCA device +/** + * Remove an MCA device * + * @v mca MCA device */ -static char * mca_describe_device ( struct bus_dev *bus_dev ) { - struct mca_device *mca = ( struct mca_device * ) bus_dev; - static char mca_description[] = "MCA 00"; - - sprintf ( mca_description + 4, "%hhx", mca->slot ); - return mca_description; +static void mca_remove ( struct mca_device *mca ) { + mca->driver->remove ( mca ); + DBG ( "Removed MCA device %02x\n", mca->slot ); } -/* - * Name an MCA device +/** + * Probe MCA root bus + * + * @v rootdev MCA bus root device * + * Scans the MCA bus for devices and registers all devices it can + * find. */ -static const char * mca_name_device ( struct bus_dev *bus_dev ) { - struct mca_device *mca = ( struct mca_device * ) bus_dev; +static int mcabus_probe ( struct root_device *rootdev ) { + struct mca_device *mca = NULL; + unsigned int slot; + int seen_non_ff; + unsigned int i; + int rc; + + for ( slot = 0 ; slot <= MCA_MAX_SLOT_NR ; slot++ ) { + /* Allocate struct mca_device */ + if ( ! mca ) + mca = malloc ( sizeof ( *mca ) ); + if ( ! mca ) { + rc = -ENOMEM; + goto err; + } + memset ( mca, 0, sizeof ( *mca ) ); + mca->slot = slot; + + /* Make sure motherboard setup is off */ + outb_p ( 0xff, MCA_MOTHERBOARD_SETUP_REG ); + + /* Select the slot */ + outb_p ( 0x8 | ( mca->slot & 0xf ), MCA_ADAPTER_SETUP_REG ); + + /* Read the POS registers */ + seen_non_ff = 0; + for ( i = 0 ; i < ( sizeof ( mca->pos ) / + sizeof ( mca->pos[0] ) ) ; i++ ) { + mca->pos[i] = inb_p ( MCA_POS_REG ( i ) ); + if ( mca->pos[i] != 0xff ) + seen_non_ff = 1; + } - return mca->name; + /* Kill all setup modes */ + outb_p ( 0, MCA_ADAPTER_SETUP_REG ); + + /* If all POS registers are 0xff, this means there's no device + * present + */ + if ( ! seen_non_ff ) + continue; + + /* Add to device hierarchy */ + snprintf ( mca->dev.name, sizeof ( mca->dev.name ), + "MCA%02x", slot ); + mca->dev.desc.bus_type = BUS_TYPE_MCA; + mca->dev.desc.vendor = GENERIC_MCA_VENDOR; + mca->dev.desc.device = MCA_ID ( mca ); + mca->dev.parent = &rootdev->dev; + list_add ( &mca->dev.siblings, &rootdev->dev.children ); + INIT_LIST_HEAD ( &mca->dev.children ); + + /* Look for a driver */ + if ( mca_probe ( mca ) == 0 ) { + /* mcadev registered, we can drop our ref */ + mca = NULL; + } else { + /* Not registered; re-use struct */ + list_del ( &mca->dev.siblings ); + } + } + + free ( mca ); + return 0; + + err: + free ( mca ); + mcabus_remove ( rootdev ); + return rc; } -/* - * MCA bus operations table +/** + * Remove MCA root bus * + * @v rootdev MCA bus root device */ -struct bus_driver mca_driver __bus_driver = { - .name = "MCA", - .next_location = mca_next_location, - .fill_device = mca_fill_device, - .check_driver = mca_check_driver, - .describe_device = mca_describe_device, - .name_device = mca_name_device, +static void mcabus_remove ( struct root_device *rootdev ) { + struct mca_device *mca; + struct mca_device *tmp; + + list_for_each_entry_safe ( mca, tmp, &rootdev->dev.children, + dev.siblings ) { + mca_remove ( mca ); + list_del ( &mca->dev.siblings ); + free ( mca ); + } +} + +/** MCA bus root device driver */ +static struct root_driver mca_root_driver = { + .probe = mcabus_probe, + .remove = mcabus_remove, }; -/* - * 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 ) ); -} +/** MCA bus root device */ +struct root_device mca_root_device __root_device = { + .dev = { .name = "MCA" }, + .driver = &mca_root_driver, +}; diff --git a/src/drivers/bus/pci.c b/src/drivers/bus/pci.c index e8f34fba..577691f5 100644 --- a/src/drivers/bus/pci.c +++ b/src/drivers/bus/pci.c @@ -283,9 +283,9 @@ static int pcibus_probe ( struct root_device *rootdev ) { "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.desc.location = PCI_BUSDEVFN (bus, devfn); + pci->dev.desc.vendor = pci->vendor; + pci->dev.desc.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/drivers/net/3c509-eisa.c b/src/drivers/net/3c509-eisa.c index a82fd942..f0ffdaf6 100644 --- a/src/drivers/net/3c509-eisa.c +++ b/src/drivers/net/3c509-eisa.c @@ -4,8 +4,8 @@ * */ -#include "eisa.h" -#include "isa.h" +#include <gpxe/eisa.h> +#include <gpxe/isa.h> #include "console.h" #include "3c509.h" @@ -27,7 +27,7 @@ static void el3_eisa_disable ( struct nic *nic, struct eisa_device *eisa ) { disable_eisa_device ( eisa ); } -static struct eisa_id el3_eisa_adapters[] = { +static struct eisa_device_id el3_eisa_adapters[] = { { "3Com 3c509 EtherLink III (EISA)", MFG_ID, PROD_ID }, }; diff --git a/src/drivers/net/3c509.c b/src/drivers/net/3c509.c index 29701713..1ae6a06b 100644 --- a/src/drivers/net/3c509.c +++ b/src/drivers/net/3c509.c @@ -4,7 +4,9 @@ * */ -#include "isa.h" +#if 0 + +#include <gpxe/isa.h> #include "io.h" #include "timer.h" #include "string.h" @@ -399,3 +401,5 @@ DRIVER ( "3c509", nic_driver, t509_driver, el3_t509_driver, el3_t509_probe, el3_t509_disable ); ISA_ROM ( "3c509", "3c509" ); + +#endif diff --git a/src/drivers/net/3c509.h b/src/drivers/net/3c509.h index b443b1ea..a06d91ea 100644 --- a/src/drivers/net/3c509.h +++ b/src/drivers/net/3c509.h @@ -31,6 +31,8 @@ */ +#include "nic.h" + /* * Ethernet software status per interface. */ diff --git a/src/drivers/net/3c515.c b/src/drivers/net/3c515.c index e839b358..d82accdc 100644 --- a/src/drivers/net/3c515.c +++ b/src/drivers/net/3c515.c @@ -48,8 +48,8 @@ #include "etherboot.h" /* to get the interface to the body of the program */ #include "nic.h" -#include "isapnp.h" -#include "isa.h" /* for ISA_ROM */ +#include <gpxe/isapnp.h> +#include <gpxe/isa.h> /* for ISA_ROM */ #include "timer.h" #include <gpxe/ethernet.h> @@ -753,7 +753,7 @@ corkscrew_probe1(int ioaddr, int irq, int product_index __unused, return 0; } -static struct isapnp_id t515_adapters[] = { +static struct isapnp_device_id t515_adapters[] = { { "3c515 (ISAPnP)", ISAPNP_VENDOR('T','C','M'), 0x5051 }, }; diff --git a/src/drivers/net/3c529.c b/src/drivers/net/3c529.c index 8cf795ac..bcdd765e 100644 --- a/src/drivers/net/3c529.c +++ b/src/drivers/net/3c529.c @@ -4,8 +4,8 @@ */ #include "etherboot.h" -#include "mca.h" -#include "isa.h" /* for ISA_ROM */ +#include <gpxe/mca.h> +#include <gpxe/isa.h> /* for ISA_ROM */ #include "nic.h" #include "3c509.h" @@ -37,7 +37,7 @@ static void t529_disable ( struct nic *nic, struct mca_device *mca __unused ) { t5x9_disable ( nic ); } -static struct mca_id el3_mca_adapters[] = { +static struct mca_device_id el3_mca_adapters[] = { { "3Com 3c529 EtherLink III (10base2)", 0x627c }, { "3Com 3c529 EtherLink III (10baseT)", 0x627d }, { "3Com 3c529 EtherLink III (test mode)", 0x62db }, diff --git a/src/drivers/net/3c5x9.c b/src/drivers/net/3c5x9.c index dc0c3f7b..1ade6f47 100644 --- a/src/drivers/net/3c5x9.c +++ b/src/drivers/net/3c5x9.c @@ -27,7 +27,7 @@ $Id$ #include <gpxe/ethernet.h> #include "etherboot.h" #include "nic.h" -#include "isa.h" +#include <gpxe/isa.h> #include "timer.h" #include "3c509.h" diff --git a/src/drivers/net/cs89x0.c b/src/drivers/net/cs89x0.c index 282e8990..ecb632f9 100644 --- a/src/drivers/net/cs89x0.c +++ b/src/drivers/net/cs89x0.c @@ -69,7 +69,7 @@ #include <gpxe/ethernet.h> #include "etherboot.h" #include "nic.h" -#include "isa.h" +#include <gpxe/isa.h> #include "console.h" #include "cs89x0.h" diff --git a/src/drivers/net/depca.c b/src/drivers/net/depca.c index feb12764..47e94f0d 100644 --- a/src/drivers/net/depca.c +++ b/src/drivers/net/depca.c @@ -236,7 +236,7 @@ #include "etherboot.h" #include "nic.h" -#include "isa.h" +#include <gpxe/isa.h> #include "console.h" #include <gpxe/ethernet.h> diff --git a/src/drivers/net/eepro.c b/src/drivers/net/eepro.c index 5de3fa07..521c720d 100644 --- a/src/drivers/net/eepro.c +++ b/src/drivers/net/eepro.c @@ -33,7 +33,7 @@ has 34 pins, the top row of 2 are not used. #include "etherboot.h" #include "nic.h" -#include "isa.h" +#include <gpxe/isa.h> #include "timer.h" #include <gpxe/ethernet.h> @@ -557,6 +557,7 @@ static int eepro_probe ( struct nic *nic, struct isa_device *isa ) { unsigned char caddr[ETH_ALEN]; unsigned short saddr[ETH_ALEN/2]; } station_addr; + const char *name; nic->irqno = 0; isa_fill_nic ( nic, isa ); @@ -576,16 +577,16 @@ static int eepro_probe ( struct nic *nic, struct isa_device *isa ) { station_addr.saddr[1] = read_eeprom(nic->ioaddr,3); station_addr.saddr[0] = read_eeprom(nic->ioaddr,4); if (l_eepro) - isa->name = "Intel EtherExpress 10 ISA"; + name = "Intel EtherExpress 10 ISA"; else if (read_eeprom(nic->ioaddr,7) == ee_FX_INT2IRQ) { - isa->name = "Intel EtherExpress Pro/10+ ISA"; + name = "Intel EtherExpress Pro/10+ ISA"; l_eepro = 2; } else if (station_addr.saddr[0] == SA_ADDR1) { - isa->name = "Intel EtherExpress Pro/10 ISA"; + name = "Intel EtherExpress Pro/10 ISA"; l_eepro = 1; } else { l_eepro = 0; - isa->name = "Intel 82595-based LAN card"; + name = "Intel 82595-based LAN card"; } station_addr.saddr[0] = swap16(station_addr.saddr[0]); station_addr.saddr[1] = swap16(station_addr.saddr[1]); @@ -594,7 +595,7 @@ static int eepro_probe ( struct nic *nic, struct isa_device *isa ) { nic->node_addr[i] = station_addr.caddr[i]; } - DBG ( "%s ioaddr %#hX, addr %s", isa->name, nic->ioaddr, eth_ntoa ( nic->node_addr ) ); + DBG ( "%s ioaddr %#hX, addr %s", name, nic->ioaddr, eth_ntoa ( nic->node_addr ) ); mem_start = RCV_LOWER_LIMIT << 8; if ((mem_end & 0x3F) < 3 || (mem_end & 0x3F) > 29) diff --git a/src/drivers/net/legacy.c b/src/drivers/net/legacy.c index aca83eaf..d9bae1d7 100644 --- a/src/drivers/net/legacy.c +++ b/src/drivers/net/legacy.c @@ -64,11 +64,11 @@ static void legacy_close ( struct net_device *netdev __unused ) { /* Nothing to do */ } -int legacy_probe ( struct pci_device *pci, - const struct pci_device_id *id __unused, - int ( * probe ) ( struct nic *nic, - struct pci_device *pci ), - void ( * disable ) ( struct nic *nic ) ) { +int legacy_probe ( void *hwdev, + void ( * set_drvdata ) ( void *hwdev, void *priv ), + struct device *dev, + int ( * probe ) ( struct nic *nic, void *hwdev ), + void ( * disable ) ( struct nic *nic, void *hwdev ) ) { struct net_device *netdev; int rc; @@ -80,8 +80,8 @@ int legacy_probe ( struct pci_device *pci, return -ENOMEM; netdev->priv = &nic; memset ( &nic, 0, sizeof ( nic ) ); - pci_set_drvdata ( pci, netdev ); - netdev->dev = &pci->dev; + set_drvdata ( hwdev, netdev ); + netdev->dev = dev; netdev->open = legacy_open; netdev->close = legacy_close; @@ -89,13 +89,13 @@ int legacy_probe ( struct pci_device *pci, netdev->poll = legacy_poll; nic.node_addr = netdev->ll_addr; - if ( ! probe ( &nic, pci ) ) { + if ( ! probe ( &nic, hwdev ) ) { free_netdev ( netdev ); return -ENODEV; } if ( ( rc = register_netdev ( netdev ) ) != 0 ) { - disable ( &nic ); + disable ( &nic, hwdev ); free_netdev ( netdev ); return rc; } @@ -108,22 +108,18 @@ int legacy_probe ( struct pci_device *pci, return 0; } -void legacy_remove ( struct pci_device *pci, - void ( * disable ) ( struct nic *nic ) ) { - struct net_device *netdev = pci_get_drvdata ( pci ); +void legacy_remove ( void *hwdev, + void * ( * get_drvdata ) ( void *hwdev ), + void ( * disable ) ( struct nic *nic, void *hwdev ) ) { + struct net_device *netdev = get_drvdata ( hwdev ); struct nic *nic = netdev->priv; unregister_netdev ( netdev ); - disable ( nic ); + disable ( nic, hwdev ); free_netdev ( netdev ); legacy_registered = 0; } -void pci_fill_nic ( struct nic *nic, struct pci_device *pci ) { - nic->ioaddr = pci->ioaddr; - nic->irqno = pci->irq; -} - int dummy_connect ( struct nic *nic __unused ) { return 1; } @@ -131,5 +127,3 @@ int dummy_connect ( struct nic *nic __unused ) { void dummy_irq ( struct nic *nic __unused, irq_action_t irq_action __unused ) { return; } - -REQUIRE_OBJECT ( pci ); diff --git a/src/drivers/net/mlx_ipoib/mt23108.c b/src/drivers/net/mlx_ipoib/mt23108.c index d07d8384..492bc901 100644 --- a/src/drivers/net/mlx_ipoib/mt23108.c +++ b/src/drivers/net/mlx_ipoib/mt23108.c @@ -17,7 +17,7 @@ Skeleton NIC driver for Etherboot /* to get the PCI support functions, if this is a PCI NIC */ #include <gpxe/pci.h> /* to get the ISA support functions, if this is an ISA NIC */ -#include "isa.h" +#include <gpxe/isa.h> #include "mt_version.c" #include "mt23108_imp.c" diff --git a/src/drivers/net/mlx_ipoib/mt25218.c b/src/drivers/net/mlx_ipoib/mt25218.c index 22c8480f..a603cdeb 100644 --- a/src/drivers/net/mlx_ipoib/mt25218.c +++ b/src/drivers/net/mlx_ipoib/mt25218.c @@ -17,7 +17,7 @@ Skeleton NIC driver for Etherboot /* to get the PCI support functions, if this is a PCI NIC */ #include <gpxe/pci.h> /* to get the ISA support functions, if this is an ISA NIC */ -#include "isa.h" +#include <gpxe/isa.h> #include "mt_version.c" #include "mt25218_imp.c" diff --git a/src/drivers/net/ns8390.c b/src/drivers/net/ns8390.c index 03cc7f4e..d37af436 100644 --- a/src/drivers/net/ns8390.c +++ b/src/drivers/net/ns8390.c @@ -36,7 +36,7 @@ SMC8416 PIO support added by Andrew Bettison (andrewb@zip.com.au) on 4/3/02 #ifdef INCLUDE_NS8390 #include <gpxe/pci.h> #else -#include "isa.h" +#include <gpxe/isa.h> #endif static unsigned char eth_vendor, eth_flags; diff --git a/src/drivers/net/skel.c b/src/drivers/net/skel.c deleted file mode 100644 index d784f7c2..00000000 --- a/src/drivers/net/skel.c +++ /dev/null @@ -1,419 +0,0 @@ -/************************************************************************** -Etherboot - BOOTP/TFTP Bootstrap Program -Skeleton NIC driver for Etherboot -***************************************************************************/ - -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2, or (at - * your option) any later version. - */ - -#include "etherboot.h" -#include "nic.h" -#include <gpxe/pci.h> -#include <gpxe/ethernet.h> -#include "isa.h" -#include "eisa.h" -#include "isapnp.h" -#include "mca.h" - -/* - * NIC specific static variables go here. Try to avoid using static - * variables wherever possible. In particular, the I/O address can - * always be accessed via nic->ioaddr. - */ - -/* - * If you have large static variables (e.g. transmit and receive - * buffers), you should place them together in a single structure and - * mark the structure as "shared". This enables this space to be - * shared between drivers in multi-driver images, which can easily - * reduce the runtime size by 50%. - * - */ -#define SKEL_RX_BUFS 1 -#define SKEL_TX_BUFS 1 -#define SKEL_RX_BUFSIZE 0 -#define SKEL_TX_BUFSIZE 0 -struct skel_rx_desc {}; -struct skel_tx_desc {}; -struct { - struct skel_rx_desc rxd[SKEL_RX_BUFS]; - unsigned char rxb[SKEL_RX_BUFS][SKEL_RX_BUFSIZE]; - struct skel_tx_desc txd[SKEL_TX_BUFS]; - unsigned char txb[SKEL_TX_BUFS][SKEL_TX_BUFSIZE]; -} skel_bufs __shared; - -/* - * Don't forget to remove "__unused" from all the function parameters! - * - */ - -/************************************************************************** - * CONNECT - Connect to the network - ************************************************************************** -*/ -static int skel_connect ( struct nic *nic __unused ) { - /* - * Connect to the network. For most NICs, this will probably - * be a no-op. For wireless NICs, this should be the point at - * which you attempt to join to an access point. - * - * Return 0 if the connection failed (e.g. no cable plugged - * in), 1 for success. - * - */ - return 1; -} - -/************************************************************************** - * TRANSMIT - Transmit a frame - ************************************************************************** -*/ -static void skel_transmit ( struct nic *nic __unused, - const char *dest __unused, - unsigned int type __unused, - unsigned int size __unused, - const char *packet __unused ) { - /* Transmit packet to dest MAC address. You will need to - * construct the link-layer header (dest MAC, source MAC, - * type). - */ - /* - unsigned int nstype = htons ( type ); - memcpy ( <tx_buffer>, dest, ETH_ALEN ); - memcpy ( <tx_buffer> + ETH_ALEN, nic->node_addr, ETH_ALEN ); - memcpy ( <tx_buffer> + 2 * ETH_ALEN, &nstype, 2 ); - memcpy ( <tx_buffer> + ETH_HLEN, data, size ); - <transmit_data> ( <tx_buffer>, size + ETH_HLEN ); - */ -} - -/************************************************************************** - * POLL - Wait for a frame - ************************************************************************** -*/ -static int skel_poll ( struct nic *nic __unused, int retrieve __unused ) { - /* Work out whether or not there's an ethernet packet ready to - * read. Return 0 if not. - */ - /* - if ( ! <packet_ready> ) return 0; - */ - - /* retrieve==0 indicates that we are just checking for the - * presence of a packet but don't want to read it just yet. - */ - /* - if ( ! retrieve ) return 1; - */ - - /* Copy data to nic->packet. Data should include the - * link-layer header (dest MAC, source MAC, type). - * Store length of data in nic->packetlen. - * Return true to indicate a packet has been read. - */ - /* - nic->packetlen = <packet_length>; - memcpy ( nic->packet, <packet_data>, <packet_length> ); - return 1; - */ - - return 0; /* Remove this line once this method is implemented */ -} - -/************************************************************************** - * IRQ - handle interrupts - ************************************************************************** -*/ -static void skel_irq ( struct nic *nic __unused, irq_action_t action ) { - /* This routine is somewhat optional. Etherboot itself - * doesn't use interrupts, but they are required under some - * circumstances when we're acting as a PXE stack. - * - * If you don't implement this routine, the only effect will - * be that your driver cannot be used via Etherboot's UNDI - * API. This won't affect programs that use only the UDP - * portion of the PXE API, such as pxelinux. - */ - - switch ( action ) { - case DISABLE : - case ENABLE : - /* Set receive interrupt enabled/disabled state */ - /* - outb ( action == ENABLE ? IntrMaskEnabled : IntrMaskDisabled, - nic->ioaddr + IntrMaskRegister ); - */ - break; - case FORCE : - /* Force NIC to generate a receive interrupt */ - /* - outb ( ForceInterrupt, nic->ioaddr + IntrForceRegister ); - */ - break; - } -} - -/************************************************************************** - * OPERATIONS TABLE - Pointers to all the above methods - ************************************************************************** - */ -static struct nic_operations skel_operations = { - .connect = skel_connect, - .transmit = skel_transmit, - .poll = skel_poll, - .irq = skel_irq, -}; - -/************************************************************************** - * PROBE - Look for an adapter - * - * You need to define a probe routine and a disable routine for each - * bus type that your driver supports, together with tables that - * enable Etherboot to identify that your driver should be used for a - * particular device. - * - * Delete whichever of the following sections you don't need. For - * example, most PCI devices will only need the PCI probing section; - * ISAPnP, EISA, etc. can all be deleted. - * - * Some devices will need custom bus logic. The ISA 3c509 is a good - * example of this; it has a contention-resolution mechanism that is - * similar to ISAPnP, but not close enough to use the generic ISAPnP - * code. Look at 3c509.c to see how it works. - * - ************************************************************************** - */ - -/************************************************************************** - * PCI PROBE and DISABLE - ************************************************************************** - */ -static int skel_pci_probe ( struct nic *nic, struct pci_device *pci ) { - - pci_fill_nic ( nic, pci ); - - /* Test for physical presence of NIC */ - /* - if ( ! my_tests ) { - DBG ( "Could not find NIC: my explanation\n" ); - return 0; - } - */ - - /* point to NIC specific routines */ - nic->nic_op = &skel_operations; - return 1; -} - -static void skel_pci_disable ( struct nic *nic __unused ) { - /* Reset the card to its initial state, disable DMA and - * interrupts - */ -} - -static struct pci_device_id skel_pci_nics[] = { -PCI_ROM ( 0x0000, 0x0000, "skel-pci", "Skeleton PCI Adapter" ), -}; - -PCI_DRIVER ( skel_pci_driver, skel_pci_nics, PCI_NO_CLASS ); - -DRIVER ( "SKEL/PCI", nic_driver, pci_driver, skel_pci_driver, - skel_pci_probe, skel_pci_disable ); - -/************************************************************************** - * EISA PROBE and DISABLE - ************************************************************************** - */ -static int skel_eisa_probe ( struct nic *nic, struct eisa_device *eisa ) { - - eisa_fill_nic ( nic, eisa ); - enable_eisa_device ( eisa ); - nic->irqno = 0; /* No standard way to get irq from EISA cards */ - - /* Test for physical presence of NIC */ - /* - if ( ! my_tests ) { - DBG ( "Could not find NIC: my explanation\n" ); - return 0; - } - */ - - /* point to NIC specific routines */ - nic->nic_op = &skel_operations; - return 1; -} - -static void skel_eisa_disable ( struct nic *nic __unused, - struct eisa_device *eisa ) { - /* Reset the card to its initial state, disable DMA and - * interrupts - */ - disable_eisa_device ( eisa ); -} - -static struct eisa_id skel_eisa_nics[] = { - { "Skeleton EISA Adapter", EISA_VENDOR('S','K','L'), 0x0000 }, -}; - -EISA_DRIVER ( skel_eisa_driver, skel_eisa_nics ); - -DRIVER ( "SKEL/EISA", nic_driver, eisa_driver, skel_eisa_driver, - skel_eisa_probe, skel_eisa_disable ); - -ISA_ROM ( "skel-eisa", "Skeleton EISA Adapter" ); - -/************************************************************************** - * ISAPnP PROBE and DISABLE - ************************************************************************** - */ -static int skel_isapnp_probe ( struct nic *nic, - struct isapnp_device *isapnp ) { - - isapnp_fill_nic ( nic, isapnp ); - activate_isapnp_device ( isapnp ); - - /* Test for physical presence of NIC */ - /* - if ( ! my_tests ) { - DBG ( "Could not find NIC: my explanation\n" ); - return 0; - } - */ - - /* point to NIC specific routines */ - nic->nic_op = &skel_operations; - return 1; -} - -static void skel_isapnp_disable ( struct nic *nic __unused, - struct isapnp_device *isapnp ) { - /* Reset the card to its initial state, disable DMA and - * interrupts - */ - deactivate_isapnp_device ( isapnp ); -} - -static struct isapnp_id skel_isapnp_nics[] = { - { "Skeleton ISAPnP Adapter", ISAPNP_VENDOR('S','K','L'), 0x0000 }, -}; - -ISAPNP_DRIVER ( skel_isapnp_driver, skel_isapnp_nics ); - -DRIVER ( "SKEL/ISAPnP", nic_driver, isapnp_driver, skel_isapnp_driver, - skel_isapnp_probe, skel_isapnp_disable ); - -ISA_ROM ( "skel-isapnp", "Skeleton ISAPnP Adapter" ); - -/************************************************************************** - * MCA PROBE and DISABLE - ************************************************************************** - */ -static int skel_mca_probe ( struct nic *nic, - struct mca_device *mca ) { - - mca_fill_nic ( nic, mca ); - - /* MCA parameters are available in the mca->pos[] array */ - /* - nic->ioaddr = ( mca->pos[xxx] << 8 ) + mca->pos[yyy]; - nic->irqno = mca->pos[zzz] & 0x0f; - */ - - /* Test for physical presence of NIC */ - /* - if ( ! my_tests ) { - DBG ( "Could not find NIC: my explanation\n" ); - return 0; - } - */ - - /* point to NIC specific routines */ - nic->nic_op = &skel_operations; - return 1; -} - -static void skel_mca_disable ( struct nic *nic __unused, - struct mca_device *mca __unused ) { - /* Reset the card to its initial state, disable DMA and - * interrupts - */ -} - -static struct mca_id skel_mca_nics[] = { - { "Skeleton MCA Adapter", 0x0000 }, -}; - -MCA_DRIVER ( skel_mca_driver, skel_mca_nics ); - -DRIVER ( "SKEL/MCA", nic_driver, mca_driver, skel_mca_driver, - skel_mca_probe, skel_mca_disable ); - -ISA_ROM ( "skel-mca", "Skeleton MCA Adapter" ); - -/************************************************************************** - * ISA PROBE and DISABLE - * - * The "classical" ISA probe is split into two stages: trying a list - * of I/O addresses to see if there's anything listening, and then - * using that I/O address to fill in the information in the nic - * structure. - * - * The list of probe addresses defined in skel_isa_probe_addrs[] will - * be passed to skel_isa_probe_addr(). If skel_isa_probe_addr() - * returns true, a struct isa_device will be created with isa->ioaddr - * set to the working I/O address, and skel_isa_probe() will be - * called. - * - * There is a standard mechanism for overriding the probe address list - * using ISA_PROBE_ADDRS. Do not implement any custom code to - * override the probe address list. - * - ************************************************************************** - */ -static int skel_isa_probe_addr ( isa_probe_addr_t ioaddr __unused ) { - return 0; -} - -static int skel_isa_probe ( struct nic *nic, struct isa_device *isa ) { - - isa_fill_nic ( nic, isa ); - nic->irqno = 0; /* No standard way to get IRQ for ISA */ - - /* Test for physical presence of NIC */ - /* - if ( ! my_tests ) { - DBG ( "Could not find NIC: my explanation\n" ); - return 0; - } - */ - - /* point to NIC specific routines */ - nic->nic_op = &skel_operations; - return 1; -} - -static void skel_isa_disable ( struct nic *nic __unused, - struct isa_device *isa __unused ) { - /* Reset the card to its initial state, disable DMA and - * interrupts - */ -} - -static isa_probe_addr_t skel_isa_probe_addrs[] = { - /* - 0x200, 0x240, - */ -}; - -ISA_DRIVER ( skel_isa_driver, skel_isa_probe_addrs, skel_isa_probe_addr, - ISA_VENDOR('S','K','L'), 0x0000 ); - -DRIVER ( "SKEL/ISA", nic_driver, isa_driver, skel_isa_driver, - skel_isa_probe, skel_isa_disable ); - -ISA_ROM ( "skel-isa", "Skeleton ISA Adapter" ); - diff --git a/src/drivers/net/smc9000.c b/src/drivers/net/smc9000.c index 34e9753d..c7893e6f 100644 --- a/src/drivers/net/smc9000.c +++ b/src/drivers/net/smc9000.c @@ -38,7 +38,7 @@ #include <gpxe/ethernet.h> #include "etherboot.h" #include "nic.h" -#include "isa.h" +#include <gpxe/isa.h> #include "timer.h" #include "smc9000.h" diff --git a/src/drivers/net/tg3.c b/src/drivers/net/tg3.c index 973573de..389442ad 100644 --- a/src/drivers/net/tg3.c +++ b/src/drivers/net/tg3.c @@ -28,13 +28,6 @@ static struct tg3 tg3; -/* Dummy defines for error handling */ -#define EBUSY 1 -#define ENODEV 2 -#define EINVAL 3 -#define ENOMEM 4 - - /* These numbers seem to be hard coded in the NIC firmware somehow. * You can't change the ring sizes, but you can change where you place * them in the NIC onboard memory. diff --git a/src/drivers/net/via-velocity.h b/src/drivers/net/via-velocity.h index a6c132dc..6e1195d6 100644 --- a/src/drivers/net/via-velocity.h +++ b/src/drivers/net/via-velocity.h @@ -1768,11 +1768,11 @@ struct velocity_opt { #define RX_DESC_MIN 4 #define RX_DESC_MAX 255 -#define RX_DESC_DEF 64 +#define RX_DESC_DEF RX_DESC_MIN #define TX_DESC_MIN 1 #define TX_DESC_MAX 256 -#define TX_DESC_DEF 4 +#define TX_DESC_DEF TX_DESC_MIN struct velocity_info { // struct list_head list; |