diff options
Diffstat (limited to 'gpxe/src/drivers/bus')
-rw-r--r-- | gpxe/src/drivers/bus/eisa.c | 182 | ||||
-rw-r--r-- | gpxe/src/drivers/bus/isa.c | 172 | ||||
-rw-r--r-- | gpxe/src/drivers/bus/isa_ids.c | 26 | ||||
-rw-r--r-- | gpxe/src/drivers/bus/isapnp.c | 755 | ||||
-rw-r--r-- | gpxe/src/drivers/bus/mca.c | 177 | ||||
-rw-r--r-- | gpxe/src/drivers/bus/pci.c | 341 | ||||
-rw-r--r-- | gpxe/src/drivers/bus/pcibackup.c | 90 | ||||
-rw-r--r-- | gpxe/src/drivers/bus/pciextra.c | 86 | ||||
-rw-r--r-- | gpxe/src/drivers/bus/virtio-pci.c | 64 | ||||
-rw-r--r-- | gpxe/src/drivers/bus/virtio-ring.c | 134 |
10 files changed, 0 insertions, 2027 deletions
diff --git a/gpxe/src/drivers/bus/eisa.c b/gpxe/src/drivers/bus/eisa.c deleted file mode 100644 index b533364b..00000000 --- a/gpxe/src/drivers/bus/eisa.c +++ /dev/null @@ -1,182 +0,0 @@ -#include <stdint.h> -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <errno.h> -#include <gpxe/io.h> -#include <unistd.h> -#include <gpxe/eisa.h> - -FILE_LICENCE ( GPL2_OR_LATER ); - -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 - */ -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 */ - - /* 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 */ - - DBG ( "EISA %s device %02x\n", ( enabled ? "enabled" : "disabled" ), - eisa->slot ); -} - -/** - * 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_probe ( struct eisa_device *eisa ) { - struct eisa_driver *driver; - struct eisa_device_id *id; - unsigned int i; - 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_each_table_entry ( driver, EISA_DRIVERS ) { - 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; - } - } - - DBG ( "...no driver found\n" ); - return -ENOTTY; -} - -/** - * Remove an EISA device - * - * @v eisa EISA device - */ -static void eisa_remove ( struct eisa_device *eisa ) { - eisa->driver->remove ( eisa ); - DBG ( "Removed EISA device %02x\n", eisa->slot ); -} - -/** - * Probe EISA root bus - * - * @v rootdev EISA bus root device - * - * Scans the EISA bus for devices and registers all devices it can - * find. - */ -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; - } - - /* 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 ); - } - } - - free ( eisa ); - return 0; - - err: - free ( eisa ); - eisabus_remove ( rootdev ); - return rc; -} - -/** - * Remove EISA root bus - * - * @v rootdev EISA bus root device - */ -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 ); - } -} - -/** EISA bus root device driver */ -static struct root_driver eisa_root_driver = { - .probe = eisabus_probe, - .remove = eisabus_remove, -}; - -/** EISA bus root device */ -struct root_device eisa_root_device __root_device = { - .dev = { .name = "EISA" }, - .driver = &eisa_root_driver, -}; diff --git a/gpxe/src/drivers/bus/isa.c b/gpxe/src/drivers/bus/isa.c deleted file mode 100644 index f458826d..00000000 --- a/gpxe/src/drivers/bus/isa.c +++ /dev/null @@ -1,172 +0,0 @@ -#include <stdint.h> -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <errno.h> -#include <gpxe/io.h> -#include <gpxe/isa.h> - -FILE_LICENCE ( GPL2_OR_LATER ); - -/* - * isa.c implements a "classical" port-scanning method of ISA device - * detection. The driver must provide a list of probe addresses - * (probe_addrs), together with a function (probe_addr) that can be - * used to test for the physical presence of a device at any given - * address. - * - * Note that this should probably be considered the "last resort" for - * device probing. If the card supports ISAPnP or EISA, use that - * instead. Some cards (e.g. the 3c509) implement a proprietary - * ISAPnP-like mechanism. - * - * 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_ONLY is defined, the driver's own list will never be - * used). - */ - -/* - * User-supplied probe address list - * - */ -static isa_probe_addr_t isa_extra_probe_addrs[] = { -#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] ) ) - -#define ISA_IOIDX_MIN( driver ) ( -ISA_EXTRA_PROBE_ADDR_COUNT ) -#ifdef ISA_PROBE_ONLY -#define ISA_IOIDX_MAX( driver ) ( -1 ) -#else -#define ISA_IOIDX_MAX( driver ) ( (int) (driver)->addr_count - 1 ) -#endif - -#define ISA_IOADDR( driver, ioidx ) \ - ( ( (ioidx) < 0 ) ? \ - isa_extra_probe_addrs[ (ioidx) + ISA_EXTRA_PROBE_ADDR_COUNT ] : \ - (driver)->probe_addrs[(ioidx)] ) - -static void isabus_remove ( struct root_device *rootdev ); - -/** - * Probe an ISA device - * - * @v isa ISA device - * @ret rc Return status code - */ -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 ); - - if ( ( rc = isa->driver->probe ( isa ) ) != 0 ) { - DBG ( "...probe failed\n" ); - return rc; - } - - DBG ( "...device found\n" ); - return 0; -} - -/** - * Remove an ISA device - * - * @v isa ISA device - */ -static void isa_remove ( struct isa_device *isa ) { - isa->driver->remove ( isa ); - DBG ( "Removed ISA%04x\n", isa->ioaddr ); -} - -/** - * Probe ISA root bus - * - * @v rootdev ISA bus root device - * - * Scans the ISA bus for devices and registers all devices it can - * find. - */ -static int isabus_probe ( struct root_device *rootdev ) { - struct isa_device *isa = NULL; - struct isa_driver *driver; - int ioidx; - int rc; - - for_each_table_entry ( driver, ISA_DRIVERS ) { - 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 ); - } - } - } - - free ( isa ); - return 0; - - err: - free ( isa ); - isabus_remove ( rootdev ); - return rc; -} - -/** - * Remove ISA root bus - * - * @v rootdev ISA bus root device - */ -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 root device driver */ -static struct root_driver isa_root_driver = { - .probe = isabus_probe, - .remove = isabus_remove, -}; - -/** ISA bus root device */ -struct root_device isa_root_device __root_device = { - .dev = { .name = "ISA" }, - .driver = &isa_root_driver, -}; diff --git a/gpxe/src/drivers/bus/isa_ids.c b/gpxe/src/drivers/bus/isa_ids.c deleted file mode 100644 index 73101584..00000000 --- a/gpxe/src/drivers/bus/isa_ids.c +++ /dev/null @@ -1,26 +0,0 @@ -#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 ( unsigned int vendor, unsigned int product ) { - static char buf[7]; - int i; - - /* Vendor ID is a compressed ASCII string */ - vendor = bswap_16 ( vendor ); - for ( i = 2 ; i >= 0 ; i-- ) { - buf[i] = ( 'A' - 1 + ( vendor & 0x1f ) ); - vendor >>= 5; - } - - /* Product ID is a 4-digit hex string */ - sprintf ( &buf[3], "%04x", bswap_16 ( product ) ); - - return buf; -} diff --git a/gpxe/src/drivers/bus/isapnp.c b/gpxe/src/drivers/bus/isapnp.c deleted file mode 100644 index ccf6209f..00000000 --- a/gpxe/src/drivers/bus/isapnp.c +++ /dev/null @@ -1,755 +0,0 @@ -/************************************************************************** -* -* isapnp.c -- Etherboot isapnp support for the 3Com 3c515 -* Written 2002-2003 by Timothy Legge <tlegge@rogers.com> -* -* 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 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -* -* Portions of this code: -* Copyright (C) 2001 P.J.H.Fox (fox@roestock.demon.co.uk) -* -* -* REVISION HISTORY: -* ================ -* Version 0.1 April 26, 2002 TJL -* Version 0.2 01/08/2003 TJL Moved outside the 3c515.c driver file -* Version 0.3 Sept 23, 2003 timlegge Change delay to currticks -* -* -* Generalised into an ISAPnP bus that can be used by more than just -* the 3c515 by Michael Brown <mbrown@fensystems.co.uk> -* -***************************************************************************/ - -/** @file - * - * ISAPnP bus support - * - * Etherboot orignally gained ISAPnP support in a very limited way for - * the 3c515 NIC. The current implementation is almost a complete - * rewrite based on the ISAPnP specification, with passing reference - * to the Linux ISAPnP code. - * - * There can be 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 gained by re-scanning for cards. - * - * External code (e.g. the ISAPnP ROM prefix) may already know the - * read port address, in which case it can store it in - * #isapnp_read_port. Note that setting the read port address in this - * way 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. - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <errno.h> -#include <gpxe/io.h> -#include <unistd.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; - -static void isapnpbus_remove ( struct root_device *rootdev ); - -/* - * ISAPnP utility functions - * - */ - -#define ISAPNP_CARD_ID_FMT "ID %04x:%04x (\"%s\") serial %x" -#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 %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 ( unsigned int address ) { - outb ( address, ISAPNP_ADDRESS ); -} - -static inline void isapnp_write_data ( unsigned int data ) { - outb ( data, ISAPNP_WRITE_DATA ); -} - -static inline unsigned int isapnp_read_data ( void ) { - return inb ( isapnp_read_port ); -} - -static inline void isapnp_write_byte ( unsigned int address, - unsigned int value ) { - isapnp_write_address ( address ); - isapnp_write_data ( value ); -} - -static inline unsigned int isapnp_read_byte ( unsigned int address ) { - isapnp_write_address ( address ); - return isapnp_read_data (); -} - -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 ) ); -} - -/** 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 ) ); -} - -/** - * Enter the Isolation state. - * - * Only cards currently in the Sleep state will respond to this - * command. - */ -static inline void isapnp_serialisolation ( void ) { - isapnp_write_address ( ISAPNP_SERIALISOLATION ); -} - -/** - * Enter the Wait for Key state. - * - * 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 ); -} - -/** - * Reset (i.e. remove) Card Select Number. - * - * 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 ); -} - -/** - * Place a specified card into the Config state. - * - * @v csn Card Select Number - * @ret None - - * @err None - - * - * 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 unsigned int isapnp_read_resourcedata ( void ) { - return isapnp_read_byte ( ISAPNP_RESOURCEDATA ); -} - -static inline unsigned int isapnp_read_status ( void ) { - return isapnp_read_byte ( ISAPNP_STATUS ); -} - -/** - * Assign a Card Select Number to a card, and enter the Config state. - * - * @v csn Card Select Number - * - * 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 ( unsigned int csn ) { - isapnp_write_byte ( ISAPNP_CARDSELECTNUMBER, csn ); -} - -static inline void isapnp_logicaldevice ( unsigned int logdev ) { - isapnp_write_byte ( ISAPNP_LOGICALDEVICENUMBER, logdev ); -} - -static inline void isapnp_activate ( unsigned int logdev ) { - isapnp_logicaldevice ( logdev ); - isapnp_write_byte ( ISAPNP_ACTIVATE, 1 ); -} - -static inline void isapnp_deactivate ( unsigned int logdev ) { - isapnp_logicaldevice ( logdev ); - isapnp_write_byte ( ISAPNP_ACTIVATE, 0 ); -} - -static inline unsigned int isapnp_read_iobase ( unsigned int index ) { - return isapnp_read_word ( ISAPNP_IOBASE ( index ) ); -} - -static inline unsigned int isapnp_read_irqno ( unsigned int index ) { - return isapnp_read_byte ( ISAPNP_IRQNO ( index ) ); -} - -static void isapnp_delay ( void ) { - udelay ( 1000 ); -} - -/** - * Linear feedback shift register. - * - * @v lfsr Current value of the LFSR - * @v input_bit Current input bit to the LFSR - * @ret lfsr Next value of the LFSR - * - * This routine implements the linear feedback shift register as - * described in Appendix B of the PnP ISA spec. The hardware - * implementation uses eight D-type latches and two XOR gates. I - * 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 unsigned int isapnp_lfsr_next ( unsigned int lfsr, - unsigned int input_bit ) { - register uint8_t lfsr_next; - - lfsr_next = lfsr >> 1; - lfsr_next |= ( ( ( lfsr ^ lfsr_next ) ^ input_bit ) ) << 7; - return lfsr_next; -} - -/** - * Send the ISAPnP initiation key. - * - * 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; - unsigned int lfsr; - - isapnp_delay(); - isapnp_write_address ( 0x00 ); - isapnp_write_address ( 0x00 ); - - lfsr = ISAPNP_LFSR_SEED; - for ( i = 0 ; i < 32 ; i++ ) { - isapnp_write_address ( lfsr ); - lfsr = isapnp_lfsr_next ( lfsr, 0 ); - } -} - -/** - * Compute ISAPnP identifier checksum - * - * @v identifier ISAPnP identifier - * @ret checksum Expected checksum value - */ -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 = * ( ( ( uint8_t * ) identifier ) + i ); - for ( j = 0 ; j < 8 ; j++ ) { - lfsr = isapnp_lfsr_next ( lfsr, byte ); - byte >>= 1; - } - } - return lfsr; -} - -/* - * Read a byte of resource data from the current location - * - * @ret byte Byte of resource data - */ -static inline unsigned int isapnp_peek_byte ( void ) { - unsigned int i; - - /* Wait for data to be ready */ - for ( i = 0 ; i < 20 ; i++ ) { - if ( isapnp_read_status() & 0x01 ) { - /* Byte ready - read it */ - return isapnp_read_resourcedata(); - } - isapnp_delay(); - } - /* Data never became ready - return 0xff */ - return 0xff; -} - -/** - * Read resource data. - * - * @v buf Buffer in which to store data, or NULL - * @v bytes Number of bytes to read - * - * Resource data is read from the current location. If #buf is NULL, - * the data is discarded. - */ -static void isapnp_peek ( void *buf, size_t len ) { - unsigned int i; - unsigned int byte; - - for ( i = 0 ; i < len ; i++) { - byte = isapnp_peek_byte(); - if ( buf ) - * ( ( uint8_t * ) buf + i ) = byte; - } -} - -/** - * Find a tag within the resource data. - * - * @v wanted_tag The tag that we're looking for - * @v buf Buffer in which to store the tag's contents - * @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. - */ -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 ) ) { - tag_len = ISAPNP_SMALL_TAG_LEN ( tag ); - tag = ISAPNP_SMALL_TAG_NAME ( tag ); - } else { - tag_len = ( isapnp_peek_byte() + - ( isapnp_peek_byte() << 8 ) ); - tag = ISAPNP_LARGE_TAG_NAME ( tag ); - } - DBG2 ( " %02x (%02x)", tag, tag_len ); - if ( tag == wanted_tag ) { - if ( len > tag_len ) - len = tag_len; - isapnp_peek ( buf, len ); - DBG2 ( "\n" ); - return 0; - } else { - 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; -} - -/** - * Try isolating ISAPnP cards at the current read port. - * - * @ret \>0 Number of ISAPnP cards found - * @ret 0 There are no ISAPnP cards in the system - * @ret \<0 A conflict was detected; try a new read port - * @err None - - * - * 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; - unsigned int data; - unsigned int byte; - - 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(); - - /* Reset all assigned CSNs */ - isapnp_reset_csn(); - isapnp_delay(); - isapnp_delay(); - - /* Place all cards into the Isolation state */ - isapnp_wait_for_key (); - isapnp_send_key(); - isapnp_wake ( 0x00 ); - - /* Set the read port */ - isapnp_set_read_port(); - isapnp_delay(); - - while ( 1 ) { - - /* All cards that do not have assigned CSNs are - * currently in the Isolation state, each time we go - * through this loop. - */ - - /* Initiate serial isolation */ - isapnp_serialisolation(); - isapnp_delay(); - - /* Read identifier serially via the ISAPnP read port. */ - memset ( &identifier, 0, sizeof ( identifier ) ); - seen_55aa = seen_life = 0; - for ( i = 0 ; i < 9 ; i++ ) { - byte = 0; - for ( j = 0 ; j < 8 ; j++ ) { - data = isapnp_read_data(); - isapnp_delay(); - data = ( ( data << 8 ) | isapnp_read_data() ); - isapnp_delay(); - byte >>= 1; - if ( data != 0xffff ) { - seen_life++; - if ( data == 0x55aa ) { - byte |= 0x80; - seen_55aa++; - } - } - } - *( ( ( uint8_t * ) &identifier ) + i ) = byte; - } - - /* If we didn't see any 55aa patterns, stop here */ - if ( ! seen_55aa ) { - if ( csn ) { - DBG ( "ISAPnP found no more cards\n" ); - } else { - if ( seen_life ) { - DBG ( "ISAPnP saw life but no cards, " - "trying new read port\n" ); - csn = -1; - } else { - DBG ( "ISAPnP saw no signs of life, " - "abandoning isolation\n" ); - } - } - break; - } - - /* 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 %02x " - "(should be %02x), trying new read port\n", - ISAPNP_CARD_ID_DATA ( &identifier ), - identifier.checksum, - isapnp_checksum ( &identifier) ); - csn = -1; - break; - } - - /* Give the device a CSN */ - csn++; - DBG ( "ISAPnP found card " ISAPNP_CARD_ID_FMT - ", assigning CSN %02x\n", - ISAPNP_CARD_ID_DATA ( &identifier ), csn ); - - isapnp_write_csn ( csn ); - isapnp_delay(); - - /* Send this card back to Sleep and force all cards - * without a CSN into Isolation state - */ - isapnp_wake ( 0x00 ); - isapnp_delay(); - } - - /* Place all cards in Wait for Key state */ - isapnp_wait_for_key(); - - /* Return number of cards found */ - if ( csn > 0 ) { - DBG ( "ISAPnP found %d cards at read port %04x\n", - csn, isapnp_read_port ); - } - return csn; -} - -/** - * Find a valid read port and isolate all ISAPnP cards. - * - */ -static void isapnp_isolate ( void ) { - for ( isapnp_read_port = ISAPNP_READ_PORT_START ; - isapnp_read_port <= ISAPNP_READ_PORT_MAX ; - isapnp_read_port += ISAPNP_READ_PORT_STEP ) { - /* Avoid problematic locations such as the NE2000 - * probe space - */ - if ( ( isapnp_read_port >= 0x280 ) && - ( isapnp_read_port <= 0x380 ) ) - continue; - - /* If we detect any ISAPnP cards at this location, stop */ - if ( isapnp_try_isolate() >= 0 ) - return; - } -} - -/** - * 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 ); - - /* Activate/deactivate the logical device */ - isapnp_activate ( activation ); - isapnp_delay(); - - /* Return all cards to Wait for Key state */ - isapnp_wait_for_key (); - - DBG ( "ISAPnP %s device %02x:%02x\n", - ( activation ? "activated" : "deactivated" ), - isapnp->csn, isapnp->logdev ); -} - -/** - * Probe an ISAPnP device - * - * @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_probe ( struct isapnp_device *isapnp ) { - struct isapnp_driver *driver; - struct isapnp_device_id *id; - unsigned int i; - 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_each_table_entry ( driver, ISAPNP_DRIVERS ) { - 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; - } - } - - DBG ( "...no driver found\n" ); - return -ENOTTY; -} - -/** - * Remove an ISAPnP device - * - * @v isapnp ISAPnP device - */ -static void isapnp_remove ( struct isapnp_device *isapnp ) { - isapnp->driver->remove ( isapnp ); - DBG ( "Removed ISAPnP device %02x:%02x\n", - isapnp->csn, isapnp->logdev ); -} - -/** - * Probe ISAPnP root bus - * - * @v rootdev ISAPnP bus root device - * - * Scans the ISAPnP bus for devices and registers all devices it can - * find. - */ -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; - - /* Perform isolation if it hasn't yet been done */ - if ( ! isapnp_read_port ) - isapnp_isolate(); - - for ( csn = 1 ; csn <= 0xff ; csn++ ) { - for ( logdev = 0 ; logdev <= 0xff ; logdev++ ) { - - /* 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.desc.ioaddr = isapnp->ioaddr; - isapnp->dev.desc.irq = isapnp->irqno; - 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 ); - } - } - } - - done: - free ( isapnp ); - return 0; - - err: - free ( isapnp ); - isapnpbus_remove ( rootdev ); - return rc; -} - -/** - * Remove ISAPnP root bus - * - * @v rootdev ISAPnP bus root device - */ -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/gpxe/src/drivers/bus/mca.c b/gpxe/src/drivers/bus/mca.c deleted file mode 100644 index 2815603e..00000000 --- a/gpxe/src/drivers/bus/mca.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * MCA bus driver code - * - * Abstracted from 3c509.c. - * - */ - -FILE_LICENCE ( BSD2 ); - -#include <stdint.h> -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <errno.h> -#include <gpxe/io.h> -#include <gpxe/mca.h> - -static void mcabus_remove ( struct root_device *rootdev ); - -/** - * Probe an MCA device - * - * @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_probe ( struct mca_device *mca ) { - struct mca_driver *driver; - struct mca_device_id *id; - unsigned int i; - int rc; - - 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] ); - - for_each_table_entry ( driver, MCA_DRIVERS ) { - 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; - } - } - - DBG ( "...no driver found\n" ); - return -ENOTTY; -} - -/** - * Remove an MCA device - * - * @v mca MCA device - */ -static void mca_remove ( struct mca_device *mca ) { - mca->driver->remove ( mca ); - DBG ( "Removed MCA device %02x\n", mca->slot ); -} - -/** - * Probe MCA root bus - * - * @v rootdev MCA bus root device - * - * Scans the MCA bus for devices and registers all devices it can - * find. - */ -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; - } - - /* 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; -} - -/** - * Remove MCA root bus - * - * @v rootdev MCA bus root 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, -}; - -/** MCA bus root device */ -struct root_device mca_root_device __root_device = { - .dev = { .name = "MCA" }, - .driver = &mca_root_driver, -}; diff --git a/gpxe/src/drivers/bus/pci.c b/gpxe/src/drivers/bus/pci.c deleted file mode 100644 index 8899e6e1..00000000 --- a/gpxe/src/drivers/bus/pci.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>. - * - * Based in part on pci.c from Etherboot 5.4, by Ken Yap and David - * Munro, in turn based on the Linux kernel's PCI implementation. - * - * 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 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <gpxe/tables.h> -#include <gpxe/device.h> -#include <gpxe/pci.h> - -/** @file - * - * PCI bus - * - */ - -static void pcibus_remove ( struct root_device *rootdev ); - -/** - * Read PCI BAR - * - * @v pci PCI device - * @v reg PCI register number - * @ret bar Base address register - * - * Reads the specified PCI base address register, including the flags - * portion. 64-bit BARs will be handled automatically. If the value - * of the 64-bit BAR exceeds the size of an unsigned long (i.e. if the - * high dword is non-zero on a 32-bit platform), then the value - * returned will be zero plus the flags for a 64-bit BAR. Unreachable - * 64-bit BARs are therefore returned as uninitialised 64-bit BARs. - */ -static unsigned long pci_bar ( struct pci_device *pci, unsigned int reg ) { - uint32_t low; - uint32_t high; - - pci_read_config_dword ( pci, reg, &low ); - if ( ( low & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK) ) - == (PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64) ){ - pci_read_config_dword ( pci, reg + 4, &high ); - if ( high ) { - if ( sizeof ( unsigned long ) > sizeof ( uint32_t ) ) { - return ( ( ( uint64_t ) high << 32 ) | low ); - } else { - DBG ( "Unhandled 64-bit BAR %08x%08x\n", - high, low ); - return PCI_BASE_ADDRESS_MEM_TYPE_64; - } - } - } - return low; -} - -/** - * Find the start of a PCI BAR - * - * @v pci PCI device - * @v reg PCI register number - * @ret start BAR start address - * - * Reads the specified PCI base address register, and returns the - * address portion of the BAR (i.e. without the flags). - * - * If the address exceeds the size of an unsigned long (i.e. if a - * 64-bit BAR has a non-zero high dword on a 32-bit machine), the - * return value will be zero. - */ -unsigned long pci_bar_start ( struct pci_device *pci, unsigned int reg ) { - unsigned long bar; - - bar = pci_bar ( pci, reg ); - if ( (bar & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY ){ - return ( bar & PCI_BASE_ADDRESS_MEM_MASK ); - } else { - return ( bar & PCI_BASE_ADDRESS_IO_MASK ); - } -} - -/** - * Read membase and ioaddr for a PCI device - * - * @v pci PCI device - * - * This scans through all PCI BARs on the specified device. The first - * valid memory BAR is recorded as pci_device::membase, and the first - * valid IO BAR is recorded as pci_device::ioaddr. - * - * 64-bit BARs are handled automatically. On a 32-bit platform, if a - * 64-bit BAR has a non-zero high dword, it will be regarded as - * invalid. - */ -static void pci_read_bases ( struct pci_device *pci ) { - unsigned long bar; - int reg; - - for ( reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4 ) { - bar = pci_bar ( pci, reg ); - if ( bar & PCI_BASE_ADDRESS_SPACE_IO ) { - if ( ! pci->ioaddr ) - pci->ioaddr = - ( bar & PCI_BASE_ADDRESS_IO_MASK ); - } else { - if ( ! pci->membase ) - pci->membase = - ( bar & PCI_BASE_ADDRESS_MEM_MASK ); - /* Skip next BAR if 64-bit */ - if ( bar & PCI_BASE_ADDRESS_MEM_TYPE_64 ) - reg += 4; - } - } -} - -/** - * Enable PCI device - * - * @v pci PCI device - * - * Set device to be a busmaster in case BIOS neglected to do so. Also - * adjust PCI latency timer to a reasonable value, 32. - */ -void adjust_pci_device ( struct pci_device *pci ) { - unsigned short new_command, pci_command; - unsigned char pci_latency; - - pci_read_config_word ( pci, PCI_COMMAND, &pci_command ); - new_command = ( pci_command | PCI_COMMAND_MASTER | - PCI_COMMAND_MEM | PCI_COMMAND_IO ); - if ( pci_command != new_command ) { - DBG ( "PCI BIOS has not enabled device %02x:%02x.%x! " - "Updating PCI command %04x->%04x\n", pci->bus, - PCI_SLOT ( pci->devfn ), PCI_FUNC ( pci->devfn ), - pci_command, new_command ); - pci_write_config_word ( pci, PCI_COMMAND, new_command ); - } - - pci_read_config_byte ( pci, PCI_LATENCY_TIMER, &pci_latency); - if ( pci_latency < 32 ) { - DBG ( "PCI device %02x:%02x.%x latency timer is unreasonably " - "low at %d. Setting to 32.\n", pci->bus, - PCI_SLOT ( pci->devfn ), PCI_FUNC ( pci->devfn ), - pci_latency ); - pci_write_config_byte ( pci, PCI_LATENCY_TIMER, 32); - } -} - -/** - * Probe a PCI device - * - * @v pci PCI device - * @ret rc Return status code - * - * Searches for a driver for the PCI device. If a driver is found, - * its probe() routine is called. - */ -static int pci_probe ( struct pci_device *pci ) { - struct pci_driver *driver; - struct pci_device_id *id; - unsigned int i; - int rc; - - DBG ( "Adding PCI device %02x:%02x.%x (%04x:%04x mem %lx io %lx " - "irq %d)\n", pci->bus, PCI_SLOT ( pci->devfn ), - PCI_FUNC ( pci->devfn ), pci->vendor, pci->device, - pci->membase, pci->ioaddr, pci->irq ); - - for_each_table_entry ( driver, PCI_DRIVERS ) { - for ( i = 0 ; i < driver->id_count ; i++ ) { - id = &driver->ids[i]; - if ( ( id->vendor != PCI_ANY_ID ) && - ( id->vendor != pci->vendor ) ) - continue; - if ( ( id->device != PCI_ANY_ID ) && - ( id->device != pci->device ) ) - continue; - pci->driver = driver; - pci->driver_name = id->name; - DBG ( "...using driver %s\n", pci->driver_name ); - if ( ( rc = driver->probe ( pci, id ) ) != 0 ) { - DBG ( "......probe failed\n" ); - continue; - } - return 0; - } - } - - DBG ( "...no driver found\n" ); - return -ENOTTY; -} - -/** - * Remove a PCI device - * - * @v pci PCI device - */ -static void pci_remove ( struct pci_device *pci ) { - pci->driver->remove ( pci ); - DBG ( "Removed PCI device %02x:%02x.%x\n", pci->bus, - PCI_SLOT ( pci->devfn ), PCI_FUNC ( pci->devfn ) ); -} - -/** - * Probe PCI root bus - * - * @v rootdev PCI bus root device - * - * Scans the PCI bus for devices and registers all devices it can - * find. - */ -static int pcibus_probe ( struct root_device *rootdev ) { - struct pci_device *pci = NULL; - unsigned int max_bus; - unsigned int bus; - unsigned int devfn; - uint8_t hdrtype = 0; - uint32_t tmp; - int rc; - - max_bus = pci_max_bus(); - for ( bus = 0 ; bus <= max_bus ; bus++ ) { - for ( devfn = 0 ; devfn <= 0xff ; devfn++ ) { - - /* Allocate struct pci_device */ - if ( ! pci ) - pci = malloc ( sizeof ( *pci ) ); - if ( ! pci ) { - rc = -ENOMEM; - goto err; - } - memset ( pci, 0, sizeof ( *pci ) ); - pci->bus = bus; - pci->devfn = devfn; - - /* Skip all but the first function on - * non-multifunction cards - */ - if ( PCI_FUNC ( devfn ) == 0 ) { - pci_read_config_byte ( pci, PCI_HEADER_TYPE, - &hdrtype ); - } else if ( ! ( hdrtype & 0x80 ) ) { - continue; - } - - /* Check for physical device presence */ - pci_read_config_dword ( pci, PCI_VENDOR_ID, &tmp ); - if ( ( tmp == 0xffffffff ) || ( tmp == 0 ) ) - continue; - - /* Populate struct pci_device */ - pci->vendor = ( tmp & 0xffff ); - pci->device = ( tmp >> 16 ); - pci_read_config_dword ( pci, PCI_REVISION, &tmp ); - pci->class = ( tmp >> 8 ); - pci_read_config_byte ( pci, PCI_INTERRUPT_LINE, - &pci->irq ); - pci_read_bases ( pci ); - - /* Add to device hierarchy */ - snprintf ( pci->dev.name, sizeof ( pci->dev.name ), - "PCI%02x:%02x.%x", bus, - PCI_SLOT ( devfn ), PCI_FUNC ( devfn ) ); - pci->dev.desc.bus_type = BUS_TYPE_PCI; - pci->dev.desc.location = PCI_BUSDEVFN (bus, devfn); - pci->dev.desc.vendor = pci->vendor; - pci->dev.desc.device = pci->device; - pci->dev.desc.class = pci->class; - pci->dev.desc.ioaddr = pci->ioaddr; - pci->dev.desc.irq = pci->irq; - pci->dev.parent = &rootdev->dev; - list_add ( &pci->dev.siblings, &rootdev->dev.children); - INIT_LIST_HEAD ( &pci->dev.children ); - - /* Look for a driver */ - if ( pci_probe ( pci ) == 0 ) { - /* pcidev registered, we can drop our ref */ - pci = NULL; - } else { - /* Not registered; re-use struct pci_device */ - list_del ( &pci->dev.siblings ); - } - } - } - - free ( pci ); - return 0; - - err: - free ( pci ); - pcibus_remove ( rootdev ); - return rc; -} - -/** - * Remove PCI root bus - * - * @v rootdev PCI bus root device - */ -static void pcibus_remove ( struct root_device *rootdev ) { - struct pci_device *pci; - struct pci_device *tmp; - - list_for_each_entry_safe ( pci, tmp, &rootdev->dev.children, - dev.siblings ) { - pci_remove ( pci ); - list_del ( &pci->dev.siblings ); - free ( pci ); - } -} - -/** PCI bus root device driver */ -static struct root_driver pci_root_driver = { - .probe = pcibus_probe, - .remove = pcibus_remove, -}; - -/** PCI bus root device */ -struct root_device pci_root_device __root_device = { - .dev = { .name = "PCI" }, - .driver = &pci_root_driver, -}; diff --git a/gpxe/src/drivers/bus/pcibackup.c b/gpxe/src/drivers/bus/pcibackup.c deleted file mode 100644 index 8f9994ec..00000000 --- a/gpxe/src/drivers/bus/pcibackup.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>. - * - * 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 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <gpxe/pci.h> -#include <gpxe/pcibackup.h> - -/** @file - * - * PCI configuration space backup and restoration - * - */ - -/** - * Check PCI configuration space offset against exclusion list - * - * @v pci PCI device - * @v offset Offset within PCI configuration space - * @v exclude PCI configuration space backup exclusion list, or NULL - */ -static int -pci_backup_excluded ( struct pci_device *pci, unsigned int offset, - const uint8_t *exclude ) { - - if ( ! exclude ) - return 0; - for ( ; *exclude != PCI_CONFIG_BACKUP_EXCLUDE_END ; exclude++ ) { - if ( offset == *exclude ) { - DBGC ( pci, "PCI %p skipping configuration offset " - "%02x\n", pci, offset ); - return 1; - } - } - return 0; -} - -/** - * Back up PCI configuration space - * - * @v pci PCI device - * @v backup PCI configuration space backup - * @v exclude PCI configuration space backup exclusion list, or NULL - */ -void pci_backup ( struct pci_device *pci, struct pci_config_backup *backup, - const uint8_t *exclude ) { - unsigned int offset; - uint32_t *dword; - - for ( offset = 0, dword = backup->dwords ; offset < 0x100 ; - offset += sizeof ( *dword ) , dword++ ) { - if ( ! pci_backup_excluded ( pci, offset, exclude ) ) - pci_read_config_dword ( pci, offset, dword ); - } -} - -/** - * Restore PCI configuration space - * - * @v pci PCI device - * @v backup PCI configuration space backup - * @v exclude PCI configuration space backup exclusion list, or NULL - */ -void pci_restore ( struct pci_device *pci, struct pci_config_backup *backup, - const uint8_t *exclude ) { - unsigned int offset; - uint32_t *dword; - - for ( offset = 0, dword = backup->dwords ; offset < 0x100 ; - offset += sizeof ( *dword ) , dword++ ) { - if ( ! pci_backup_excluded ( pci, offset, exclude ) ) - pci_write_config_dword ( pci, offset, *dword ); - } -} diff --git a/gpxe/src/drivers/bus/pciextra.c b/gpxe/src/drivers/bus/pciextra.c deleted file mode 100644 index 74c40990..00000000 --- a/gpxe/src/drivers/bus/pciextra.c +++ /dev/null @@ -1,86 +0,0 @@ -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <gpxe/pci.h> - -/** - * Look for a PCI capability - * - * @v pci PCI device to query - * @v cap Capability code - * @ret address Address of capability, or 0 if not found - * - * Determine whether or not a device supports a given PCI capability. - * Returns the address of the requested capability structure within - * the device's PCI configuration space, or 0 if the device does not - * support it. - */ -int pci_find_capability ( struct pci_device *pci, int cap ) { - uint16_t status; - uint8_t pos, id; - uint8_t hdr_type; - int ttl = 48; - - pci_read_config_word ( pci, PCI_STATUS, &status ); - if ( ! ( status & PCI_STATUS_CAP_LIST ) ) - return 0; - - pci_read_config_byte ( pci, PCI_HEADER_TYPE, &hdr_type ); - switch ( hdr_type & 0x7F ) { - case PCI_HEADER_TYPE_NORMAL: - case PCI_HEADER_TYPE_BRIDGE: - default: - pci_read_config_byte ( pci, PCI_CAPABILITY_LIST, &pos ); - break; - case PCI_HEADER_TYPE_CARDBUS: - pci_read_config_byte ( pci, PCI_CB_CAPABILITY_LIST, &pos ); - break; - } - while ( ttl-- && pos >= 0x40 ) { - pos &= ~3; - pci_read_config_byte ( pci, pos + PCI_CAP_LIST_ID, &id ); - DBG ( "PCI Capability: %d\n", id ); - if ( id == 0xff ) - break; - if ( id == cap ) - return pos; - pci_read_config_byte ( pci, pos + PCI_CAP_LIST_NEXT, &pos ); - } - return 0; -} - -/** - * Find the size of a PCI BAR - * - * @v pci PCI device - * @v reg PCI register number - * @ret size BAR size - * - * It should not be necessary for any Etherboot code to call this - * function. - */ -unsigned long pci_bar_size ( struct pci_device *pci, unsigned int reg ) { - uint16_t cmd; - uint32_t start, size; - - /* Save the original command register */ - pci_read_config_word ( pci, PCI_COMMAND, &cmd ); - /* Save the original bar */ - pci_read_config_dword ( pci, reg, &start ); - /* Compute which bits can be set */ - pci_write_config_dword ( pci, reg, ~0 ); - pci_read_config_dword ( pci, reg, &size ); - /* Restore the original size */ - pci_write_config_dword ( pci, reg, start ); - /* Find the significant bits */ - /* Restore the original command register. This reenables decoding. */ - pci_write_config_word ( pci, PCI_COMMAND, cmd ); - if ( start & PCI_BASE_ADDRESS_SPACE_IO ) { - size &= PCI_BASE_ADDRESS_IO_MASK; - } else { - size &= PCI_BASE_ADDRESS_MEM_MASK; - } - /* Find the lowest bit set */ - size = size & ~( size - 1 ); - return size; -} diff --git a/gpxe/src/drivers/bus/virtio-pci.c b/gpxe/src/drivers/bus/virtio-pci.c deleted file mode 100644 index 34acce2d..00000000 --- a/gpxe/src/drivers/bus/virtio-pci.c +++ /dev/null @@ -1,64 +0,0 @@ -/* virtio-pci.c - pci interface for virtio interface - * - * (c) Copyright 2008 Bull S.A.S. - * - * Author: Laurent Vivier <Laurent.Vivier@bull.net> - * - * some parts from Linux Virtio PCI driver - * - * Copyright IBM Corp. 2007 - * Authors: Anthony Liguori <aliguori@us.ibm.com> - * - */ - -#include "etherboot.h" -#include "gpxe/io.h" -#include "gpxe/virtio-ring.h" -#include "gpxe/virtio-pci.h" - -int vp_find_vq(unsigned int ioaddr, int queue_index, - struct vring_virtqueue *vq) -{ - struct vring * vr = &vq->vring; - u16 num; - - /* select the queue */ - - outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_SEL); - - /* check if the queue is available */ - - num = inw(ioaddr + VIRTIO_PCI_QUEUE_NUM); - if (!num) { - printf("ERROR: queue size is 0\n"); - return -1; - } - - if (num > MAX_QUEUE_NUM) { - printf("ERROR: queue size %d > %d\n", num, MAX_QUEUE_NUM); - return -1; - } - - /* check if the queue is already active */ - - if (inl(ioaddr + VIRTIO_PCI_QUEUE_PFN)) { - printf("ERROR: queue already active\n"); - return -1; - } - - vq->queue_index = queue_index; - - /* initialize the queue */ - - vring_init(vr, num, (unsigned char*)&vq->queue); - - /* activate the queue - * - * NOTE: vr->desc is initialized by vring_init() - */ - - outl((unsigned long)virt_to_phys(vr->desc) >> PAGE_SHIFT, - ioaddr + VIRTIO_PCI_QUEUE_PFN); - - return num; -} diff --git a/gpxe/src/drivers/bus/virtio-ring.c b/gpxe/src/drivers/bus/virtio-ring.c deleted file mode 100644 index 6415f626..00000000 --- a/gpxe/src/drivers/bus/virtio-ring.c +++ /dev/null @@ -1,134 +0,0 @@ -/* virtio-pci.c - virtio ring management - * - * (c) Copyright 2008 Bull S.A.S. - * - * Author: Laurent Vivier <Laurent.Vivier@bull.net> - * - * some parts from Linux Virtio Ring - * - * Copyright Rusty Russell IBM Corporation 2007 - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - * - * - */ - -#include "etherboot.h" -#include "gpxe/io.h" -#include "gpxe/virtio-ring.h" -#include "gpxe/virtio-pci.h" - -#define BUG() do { \ - printf("BUG: failure at %s:%d/%s()!\n", \ - __FILE__, __LINE__, __FUNCTION__); \ - while(1); \ -} while (0) -#define BUG_ON(condition) do { if (condition) BUG(); } while (0) - -/* - * vring_free - * - * put at the begin of the free list the current desc[head] - */ - -void vring_detach(struct vring_virtqueue *vq, unsigned int head) -{ - struct vring *vr = &vq->vring; - unsigned int i; - - /* find end of given descriptor */ - - i = head; - while (vr->desc[i].flags & VRING_DESC_F_NEXT) - i = vr->desc[i].next; - - /* link it with free list and point to it */ - - vr->desc[i].next = vq->free_head; - wmb(); - vq->free_head = head; -} - -/* - * vring_get_buf - * - * get a buffer from the used list - * - */ - -int vring_get_buf(struct vring_virtqueue *vq, unsigned int *len) -{ - struct vring *vr = &vq->vring; - struct vring_used_elem *elem; - u32 id; - int ret; - - BUG_ON(!vring_more_used(vq)); - - elem = &vr->used->ring[vq->last_used_idx % vr->num]; - wmb(); - id = elem->id; - if (len != NULL) - *len = elem->len; - - ret = vq->vdata[id]; - - vring_detach(vq, id); - - vq->last_used_idx++; - - return ret; -} - -void vring_add_buf(struct vring_virtqueue *vq, - struct vring_list list[], - unsigned int out, unsigned int in, - int index, int num_added) -{ - struct vring *vr = &vq->vring; - int i, avail, head, prev; - - BUG_ON(out + in == 0); - - prev = 0; - head = vq->free_head; - for (i = head; out; i = vr->desc[i].next, out--) { - - vr->desc[i].flags = VRING_DESC_F_NEXT; - vr->desc[i].addr = (u64)virt_to_phys(list->addr); - vr->desc[i].len = list->length; - prev = i; - list++; - } - for ( ; in; i = vr->desc[i].next, in--) { - - vr->desc[i].flags = VRING_DESC_F_NEXT|VRING_DESC_F_WRITE; - vr->desc[i].addr = (u64)virt_to_phys(list->addr); - vr->desc[i].len = list->length; - prev = i; - list++; - } - vr->desc[prev].flags &= ~VRING_DESC_F_NEXT; - - vq->free_head = i; - - vq->vdata[head] = index; - - avail = (vr->avail->idx + num_added) % vr->num; - vr->avail->ring[avail] = head; - wmb(); -} - -void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added) -{ - struct vring *vr = &vq->vring; - - wmb(); - vr->avail->idx += num_added; - - mb(); - if (!(vr->used->flags & VRING_USED_F_NO_NOTIFY)) - vp_notify(ioaddr, vq->queue_index); -} - |