diff options
Diffstat (limited to 'sys/pci')
-rw-r--r-- | sys/pci/dpt_pci.c | 531 | ||||
-rw-r--r-- | sys/pci/dpt_pci.h | 207 |
2 files changed, 738 insertions, 0 deletions
diff --git a/sys/pci/dpt_pci.c b/sys/pci/dpt_pci.c new file mode 100644 index 0000000..e6f966e --- /dev/null +++ b/sys/pci/dpt_pci.c @@ -0,0 +1,531 @@ +/* + * Copyright (c) 1997 by Simon Shapiro + * All Rights Reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * dptpci.c: Pseudo device drivers for DPT on PCI on FreeBSD + * + * caveats: We may need an eisa and an isa files too + */ + +#ident "$Id: dpt_pci.c,v 1.10 1998/01/21 04:38:47 ShimonR Exp $" + +#include "opt_dpt.h" +#include <pci.h> + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/malloc.h> +#include <sys/buf.h> +#include <sys/proc.h> +#include <sys/kernel.h> + +#include <scsi/scsi_all.h> +#include <scsi/scsi_message.h> +#include <scsi/scsiconf.h> + +#include <pci/pcireg.h> +#include <sys/queue.h> +#include <pci/pcivar.h> + +#include <sys/dpt.h> +#include <pci/dpt_pci.h> + +#include <machine/clock.h> + +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/pmap.h> + +#define PCI_BASEADR0 PCI_MAP_REG_START /* I/O Address */ +#define PCI_BASEADR1 PCI_MAP_REG_START + 4 /* Mem I/O Address */ + +#define ISA_PRIMARY_WD_ADDRESS 0x1f8 + +/* Global variables */ + +int dpt_controllers_present = 0; + +/* Function Prototypes */ + +char *dpt_pci_probe(pcici_t tag, pcidi_t type); +void dpt_pci_attach(pcici_t config_id, int unit); +int dpt_pci_shutdown(int foo, int bar); + +extern struct cdevsw dpt_cdevsw; + +static struct pci_device dpt_pci_driver = +{ + "dpt", + dpt_pci_probe, + dpt_pci_attach, + &dpt_unit, + dpt_pci_shutdown +}; + +DATA_SET(pcidevice_set, dpt_pci_driver); + +/* + * Probe the PCI device. + * Some of this work will have to be duplicated in _attach + * because we do not know for sure how the two relate. + */ + +char * +dpt_pci_probe(pcici_t tag, pcidi_t type) +{ + static char silly_message[64]; + static int already_announced = 0; + + u_int32_t dpt_id; + u_int32_t command; + u_int32_t class; + +#define pci_device tag.cfg2.port +#define pci_bus tag.cfg2.forward +#define pci_index tag.cfg2.enable + +#ifndef PCI_COMMAND_MASTER_ENABLE +#define PCI_COMMAND_MASTER_ENABLE 0x00000004 +#endif + +#ifndef PCI_SUBCLASS_MASS_STORAGE_SCSI +#define PCI_SUBCLASS_MASS_STORAGE_SCSI 0x00000000 +#endif + + if ( !already_announced ) { + printf("DPT: PCI SCSI HBA Driver, version %d.%d.%d\n", + DPT_RELEASE, DPT_VERSION, DPT_PATCH); + ++already_announced; + } + + if ((dpt_id = (type & 0xffff0000) >> 16) == DPT_DEVICE_ID) { + /* This one appears to belong to us, but what is it? */ + class = pci_conf_read(tag, PCI_CLASS_REG); + if (((class & PCI_CLASS_MASK) == PCI_CLASS_MASS_STORAGE) && + ((class & PCI_SUBCLASS_MASK) == PCI_SUBCLASS_MASS_STORAGE_SCSI) ) { + /* It is a SCSI storage device. How do talk to it? */ + command = pci_conf_read(tag, PCI_COMMAND_STATUS_REG); +#ifdef DPT_ALLOW_MEMIO + if ( ((command & PCI_COMMAND_IO_ENABLE) == 0) + && ((command & PCI_COMMAND_MEM_ENABLE) == 0) ) +#else + if ( ((command & PCI_COMMAND_IO_ENABLE) == 0) ) +#endif /* DPT_ALLOW_MEMIO */ + { + printf("DPT: Cannot map the controller registers :-(\n"); + return(NULL); + } + } else { + printf("DPT: Device is not Mass Storage, nor SCSI controller\n"); + return(NULL); + } + + command = pci_conf_read(tag, PCI_COMMAND_STATUS_REG); + if ( (command & PCI_COMMAND_MASTER_ENABLE) == 0 ) { + printf("DPT: Cannot be functional without BUSMASTER. :-(\n"); + return (NULL); + } + +#ifdef DPT_DEBUG_PCI + printf("DPT: Controller is %s mapable\n", + (command & PCI_COMMAND_MEM_ENABLE) + ? "MEMORY" + : ((command & PCI_COMMAND_IO_ENABLE) + ? "I/O" + : "NOT")); +#endif + return ("DPT Caching SCSI RAID Controller"); + } + +#if defined(DPT_DEBUG_PCI) && defined(DPT_DEBUG_WARN) + printf("DPT: Unknown Controller Type %x Found\n", dpt_id); + printf(" (class = %x, command = %x\n", class, command); +#endif + return (NULL); +} + +void +dpt_pci_attach(pcici_t config_id, int unit) +{ + int ospl; + int result; + int ndx; + + vm_offset_t vaddr; + vm_offset_t paddr; + u_int16_t io_base; + u_int32_t command; + u_int32_t data; + dpt_conf_t *config; + dpt_softc_t *dpt; + + if (dpt_controllers_present >= DPT_MAX_ADAPTERS) { + printf("dpt%d: More than %d Adapters found! Adapter rejected\n", + unit, DPT_MAX_ADAPTERS); + return; + } + + if ((dpt = (dpt_softc_t *) malloc(sizeof(dpt_softc_t), M_DEVBUF, M_NOWAIT)) + == NULL) { + printf("dpt%d: Failed to allocate %d bytes for a DPT softc\n", + unit, sizeof(dpt_softc_t)); + return; + } + + /* + * Initialize the queues. See dpt.h for details. We do this here, + * as we may get hit with interrupts at any moment and we want to + * have a minimal structure in place to handle them. We also want to + * register interrupts correctly. To do so, we need a valid dpt + * structure. To have that, we need this minimal setup here. + */ + bzero(dpt, sizeof(dpt_softc_t)); + + TAILQ_INIT(&dpt->free_ccbs); + TAILQ_INIT(&dpt->waiting_ccbs); + TAILQ_INIT(&dpt->submitted_ccbs); + TAILQ_INIT(&dpt->completed_ccbs); + + if (TAILQ_EMPTY(&dpt_softc_list)) { + TAILQ_INIT(&dpt_softc_list); + } + + TAILQ_INSERT_TAIL(&dpt_softc_list, dpt, links); + dpt->queue_status = DPT_QUEUES_NONE_ACTIVE; + dpt->commands_processed = 0; + +#ifdef DPT_MEASURE_PERFORMANCE + /* Zero out all command counters */ + bzero((void *)&dpt->performance, sizeof(dpt_perf_t)); + for ( ndx = 0; ndx < 256; ndx ++ ) + dpt->performance.min_command_time[ndx] = BIG_ENOUGH; + + dpt->performance.min_intr_time = BIG_ENOUGH; + dpt->performance.min_waiting_time = BIG_ENOUGH; + dpt->performance.min_submit_time = BIG_ENOUGH; + dpt->performance.min_complete_time = BIG_ENOUGH; + dpt->performance.min_eata_tries = BIG_ENOUGH; + + for (ndx = 0; ndx < 10; ndx++ ) { + dpt->performance.read_by_size_min_time[ndx] = BIG_ENOUGH; + dpt->performance.write_by_size_min_time[ndx] = BIG_ENOUGH; + } +#endif /* DPT_MEASURE_PERFORMANCE */ + + dpt->unit = unit; + dpt->handle_interrupts = 0; /* + * Do not set to 1 until all + * initialization is done + */ + dpt->v_membase = NULL; + dpt->p_membase = NULL; + io_base = 0; + vaddr = 0; + paddr = 0; + command = pci_conf_read(config_id, PCI_COMMAND_STATUS_REG); + +#ifdef DPT_ALLOW_MEMIO + if ( (command & PCI_COMMAND_MEM_ENABLE) == 0 ) { +#ifdef DPT_DEBUG_PCI + printf("dpt%d: Cannot be memory mapped\n", unit); +#endif + force_io: + if ((command & PCI_COMMAND_IO_ENABLE) == 0 ) { + printf("dpt%d: Cannot be I/O mapped either :-(\n", unit); + free(dpt, M_DEVBUF); + return; + } else { + data = pci_conf_read(config_id, PCI_MAP_REG_START); + if ( pci_map_port(config_id, PCI_MAP_REG_START, &io_base) == 0 ) { +#ifdef DPT_DEBUG_ERROR + printf("dpt%d: Failed to map as I/O :-(\n", unit); +#endif + free(dpt, M_DEVBUF); + return; + } else { + dpt->io_base = io_base + 0x10; +#ifdef DPT_DEBUG_PCI + printf("dpt%d: Mapped registers to I/O space, " + "starting at %x\n", + dpt->unit, dpt->io_base); +#endif + } + } + } else { + if ( pci_map_mem(config_id, PCI_MAP_REG_START + 4, &vaddr, + &paddr) == 0 ) { +#ifdef DPT_DEBUG_ERROR + printf("dpt%d: Failed to map as MEMORY.\n" + " Attemting to force I/O mapping\n", unit); +#endif + goto force_io; + } else { + dpt->v_membase = (volatile u_int8_t *)(vaddr + 0x10); + dpt->p_membase = (volatile u_int8_t *)(paddr + 0x10); +#ifdef DPT_DEBUG_PCI + printf("dpt%d: Mapped registers to MEMORY space, " + "starting at %x/%x\n", + dpt->unit, dpt->v_membase, dpt->p_membase); +#endif + } + } + +#else /* !DPT_ALLOW_MEMIO */ + data = pci_conf_read(config_id, PCI_MAP_REG_START); + if ((command & PCI_COMMAND_IO_ENABLE) == 0 ) { + printf("dpt%d: Registers cannot be I/O mapped :-(\n", unit); + free(dpt, M_DEVBUF); + return; + } else { + if ( pci_map_port(config_id, PCI_MAP_REG_START, &io_base) == 0 ) { +#ifdef DPT_DEBUG_ERROR + printf("dpt%d: Failed to map registers as I/O :-(\n", unit); +#endif + free(dpt, M_DEVBUF); + return; + } else { + dpt->io_base = io_base + 0x10; +#ifdef DPT_DEBUG_PCI + printf("dpt%d: Mapped registers to I/O space, starting at %x\n", + dpt->unit, dpt->io_base); +#endif + } + } +#endif /* !DPT_ALLOW_MEMIO */ + + if (pci_map_int(config_id, dpt_intr, (void *)dpt, &cam_imask) == 0) { +#ifdef DPT_DEBUG_WARN + printf("dpt%d: Failed to map interrupt :-(\n", unit); +#endif + free(dpt, M_DEVBUF); + return; + } + + /* If the DPT is mapped as an IDE controller, let it be IDE controller */ + if (io_base == (ISA_PRIMARY_WD_ADDRESS)) { +#ifdef DPT_DEBUG_WARN + printf("dpt%d: Mapped as an IDE controller. " + "Disabling SCSI setup\n", unit); +#endif + free(dpt, M_DEVBUF); + return; + } else { + if ((config = dpt_get_conf(dpt, 0xc1, 7, + sizeof(dpt_conf_t), 1)) == NULL) { +#ifdef DPT_DEBUG_ERROR + printf("dpt%d: Failed to get board configuration (%x)\n", + unit, BaseRegister(dpt)); +#endif + free(dpt, M_DEVBUF); + return; + } + } + + dpt->max_id = config->MAX_ID; + dpt->max_lun = config->MAX_LUN; + dpt->irq = config->IRQ; + dpt->channels = config->MAX_CHAN; + dpt->dma_channel = (8 - config->DMA_channel) & 7; + +#ifdef DPT_DEBUG_SETUP + printf("dpt%d: max_id = %d, max_chan = %d, max_lun = %d\n", + dpt->unit, dpt->max_id, dpt->channels, dpt->max_lun); +#endif + + if (result = dpt_setup(dpt, config)) { + free(config, M_TEMP); + free(dpt, M_DEVBUF); + printf("dpt%d: dpt_setup failed (%d). Driver Disabled :-(\n", + dpt->unit, result); + } else { + /* clean up the informational data, and display */ + char clean_vendor[9]; + char clean_model[17]; + char clean_firmware[5]; + char clean_protocol[5]; + char clean_other[7]; + + int ndx; + + strncpy(clean_other, dpt->board_data.otherData, 8); + clean_other[6] = '\0'; + for (ndx = 5; ndx >= 0; ndx--) { + if (clean_other[ndx] == ' ') + clean_other[ndx] = '\0'; + else + break; + } + strncpy(dpt->board_data.otherData, clean_other, 6); + + strncpy(clean_vendor, dpt->board_data.vendor, 8); + clean_vendor[8] = '\0'; + for (ndx = 7; ndx >= 0; ndx--) { + if (clean_vendor[ndx] == ' ') + clean_vendor[ndx] = '\0'; + else + break; + } + strncpy(dpt->board_data.vendor, clean_vendor, 8); + + strncpy(clean_model, dpt->board_data.modelNum, 16); + clean_model[16] = '\0'; + for (ndx = 15; ndx >= 0; ndx--) { + if (clean_model[ndx] == ' ') + clean_model[ndx] = '\0'; + else + break; + } + strncpy(dpt->board_data.modelNum, clean_model, 16); + + strncpy(clean_firmware, dpt->board_data.firmware, 4); + clean_firmware[4] = '\0'; + for (ndx = 3; ndx >= 0; ndx--) { + if (clean_firmware[ndx] == ' ') + clean_firmware[ndx] = '\0'; + else + break; + } + strncpy(dpt->board_data.firmware, clean_firmware, 4); + + strncpy(clean_protocol, dpt->board_data.protocol, 4); + clean_protocol[4] = '\0'; + for (ndx = 3; ndx >= 0; ndx--) { + if (clean_protocol[ndx] == ' ') + clean_protocol[ndx] = '\0'; + else + break; + } + strncpy(dpt->board_data.protocol, clean_protocol, 4); + + dpt_detect_cache(dpt); + + printf("dpt%d: %s type %x, model %s firmware %s, Protocol %s \n" + " on port %x with %s cache. LED = %s\n", + dpt->unit, clean_vendor, dpt->board_data.deviceType, + clean_model, clean_firmware, clean_protocol, dpt->io_base, + (dpt->cache_type == DPT_NO_CACHE) + ? "Disabled" + : (dpt->cache_type == DPT_CACHE_WRITETHROUGH) + ? "Write-Through" + : "Write-Back", + i2bin(dpt_blinking_led(dpt), 8)); + printf("dpt%d: Enabled Options:\n", dpt->unit); +#ifdef DPT_LOST_IRQ + printf(" Recover Lost Interrupts\n"); +#endif +#ifdef DPT_VERIFY_HINTR + printf(" Verify Lost Transactions\n"); +#endif +#ifdef DPT_RESTRICTED_FREELIST + printf(" Restrict the Freelist Size\n"); +#endif +#ifdef DPT_MEASURE_PERFORMANCE + printf(" Collect Metrics\n"); +#endif +#ifdef DPT_FREELIST_IS_STACK + printf(" Optimize CPU Cache\n"); +#endif +#ifdef DPT_HANDLE_TIMEOUTS + printf(" Handle Timeouts\n"); +#endif +#ifdef DPT_ALLOW_MEMIO + printf(" Allow I/O to be Memeory Mapped\n"); +#endif +#ifdef DPT_HINTR_CHECK_SOFTC + printf(" Validate SoftC at Interrupt\n"); +#endif + + /* register shutdown handlers */ + result = at_shutdown((bootlist_fn)dpt_shutdown, (void *)dpt, + SHUTDOWN_POST_SYNC); + switch ( result ) { + case 0: +#ifdef DPT_DEBUG_SHUTDOWN + printf("dpt%d: Shutdown handler registered\n", dpt->unit); +#endif + break; + default: +#ifdef DPT_DEBUG_WARN + printf("dpt%d: Failed to register shutdown handler (%d)\n", + dpt->unit, result); +#endif + break; + } + + /* Attach SCSI devices */ + dpt_attach(dpt); + ++dpt_controllers_present; + + /* + * Now we create the DEVFS entry. + * This would be normally done from dpt_control.c, + * But since it appears to be called before we do here, + * We never get the entries made. + */ +#ifdef DEVFS + dpt->devfs_data_token = devfs_add_devswf(&dpt_cdevsw, dpt->unit, DV_CHR, + UID_ROOT, GID_WHEEL, 0600, + "dpt%d", dpt->unit); + dpt->devfs_ctl_token = devfs_add_devswf(&dpt_cdevsw, + dpt->unit | SCSI_CONTROL_MASK, + DV_CHR, + UID_ROOT, GID_WHEEL, 0600, + "dpt%d.ctl", dpt->unit); +#endif + } +} + +int +dpt_pci_shutdown(int foo, int bar) +{ +#ifdef DPT_DEBUG_WARN + printf("dpt_pci_shutdown(%x, %x)\n", foo, bar); +#endif + return (0); +} + +/* End of the DPT PCI part of the driver */ + +/* + * Hello emacs, these are the + * Local Variables: + * c-indent-level: 8 + * c-continued-statement-offset: 8 + * c-continued-brace-offset: 0 + * c-brace-offset: -8 + * c-brace-imaginary-offset: 0 + * c-argdecl-indent: 8 + * c-label-offset: -8 + * c++-hanging-braces: 1 + * c++-access-specifier-offset: -8 + * c++-empty-arglist-indent: 8 + * c++-friend-offset: 0 + * End: + */ diff --git a/sys/pci/dpt_pci.h b/sys/pci/dpt_pci.h new file mode 100644 index 0000000..4db7bf9 --- /dev/null +++ b/sys/pci/dpt_pci.h @@ -0,0 +1,207 @@ +/* + * Copyright (c) 1997 by Simon Shapiro + * All Rights Reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ident "$Id: dpt_pci.h,v 1.3 1997/10/02 04:25:30 ShimonR Exp $" + +#define DPT_VENDOR_ID 0x00001044 +#define DPT_DEVICE_ID 0x0000a400 + +/* The following are taken, shamelessly from Linux include/linux/pci.h */ + +/* + * Under PCI, each device has 256 bytes of configuration address space, + * of which the first 64 bytes are standardized as follows: + */ +#define PCI_VENDOR_ID 0x00 /* 16 bits */ +#define PCI_DEVICE_ID 0x02 /* 16 bits */ +#define PCI_COMMAND 0x04 /* 16 bits */ +#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */ +#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */ +#define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */ +#define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */ +#define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */ +#define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */ +#define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */ +#define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */ +#define PCI_COMMAND_SERR 0x100 /* Enable SERR */ +#define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */ + +#define PCI_STATUS 0x06 /* 16 bits */ +#define PCI_STATUS_66MHZ 0x20 /* Support 66 Mhz PCI 2.1 bus */ +#define PCI_STATUS_UDF 0x40 /* Support User Definable Features */ + +#define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */ +#define PCI_STATUS_PARITY 0x100 /* Detected parity error */ +#ifndef PCI_STATUS_DEVSEL_MASK +#define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */ +#define PCI_STATUS_DEVSEL_FAST 0x000 +#define PCI_STATUS_DEVSEL_MEDIUM 0x200 +#define PCI_STATUS_DEVSEL_SLOW 0x400 +#endif +#define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */ +#define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */ +#define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */ +#define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */ +#define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */ + +#define PCI_CLASS_REVISION 0x08 /* High 24 bits are class, low 8 + * revision */ +#define PCI_REVISION_ID 0x08 /* Revision ID */ +#define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */ +#define PCI_CLASS_DEVICE 0x0a /* Device class */ + +#define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */ +#define PCI_LATENCY_TIMER 0x0d /* 8 bits */ +#define PCI_HEADER_TYPE 0x0e /* 8 bits */ +#define PCI_BIST 0x0f /* 8 bits */ +#define PCI_BIST_CODE_MASK 0x0f /* Return result */ +#define PCI_BIST_START 0x40 /* 1 to start BIST, 2 secs or less */ +#define PCI_BIST_CAPABLE 0x80 /* 1 if BIST capable */ + +/* + * Base addresses specify locations in memory or I/O space. + * Decoded size can be determined by writing a value of + * 0xffffffff to the register, and reading it back. Only + * 1 bits are decoded. + */ +#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */ +#define PCI_BASE_ADDRESS_1 0x14 /* 32 bits */ +#define PCI_BASE_ADDRESS_2 0x18 /* 32 bits */ +#define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */ +#define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */ +#define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */ +#define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */ +#define PCI_BASE_ADDRESS_SPACE_IO 0x01 +#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00 +#define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06 +#define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */ +#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M */ +#define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */ +#define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */ +#define PCI_BASE_ADDRESS_MEM_MASK (~0x0f) +#define PCI_BASE_ADDRESS_IO_MASK (~0x03) +/* bit 1 is reserved if address_space = 1 */ + +#define PCI_CARDBUS_CIS 0x28 +#define PCI_SUBSYSTEM_ID 0x2c +#define PCI_SUBSYSTEM_VENDOR_ID 0x2e +#define PCI_ROM_ADDRESS 0x30 /* 32 bits */ +#define PCI_ROM_ADDRESS_ENABLE 0x01 /* Write 1 to enable ROM, bits 31..11 + * are address, 10..2 are reserved */ + +/* 0x34-0x3b are reserved */ +#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */ +#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */ +#define PCI_MIN_GNT 0x3e /* 8 bits */ +#define PCI_MAX_LAT 0x3f /* 8 bits */ + +#define PCI_CLASS_NOT_DEFINED 0x0000 +#define PCI_CLASS_NOT_DEFINED_VGA 0x0001 + +#define PCI_BASE_CLASS_STORAGE 0x01 +#define PCI_CLASS_STORAGE_SCSI 0x0100 +#define PCI_CLASS_STORAGE_IDE 0x0101 +#define PCI_CLASS_STORAGE_FLOPPY 0x0102 +#define PCI_CLASS_STORAGE_IPI 0x0103 +#define PCI_CLASS_STORAGE_RAID 0x0104 +#define PCI_CLASS_STORAGE_OTHER 0x0180 + +#define PCI_BASE_CLASS_NETWORK 0x02 +#define PCI_CLASS_NETWORK_ETHERNET 0x0200 +#define PCI_CLASS_NETWORK_TOKEN_RING 0x0201 +#define PCI_CLASS_NETWORK_FDDI 0x0202 +#define PCI_CLASS_NETWORK_ATM 0x0203 +#define PCI_CLASS_NETWORK_OTHER 0x0280 + +#define PCI_BASE_CLASS_DISPLAY 0x03 +#define PCI_CLASS_DISPLAY_VGA 0x0300 +#define PCI_CLASS_DISPLAY_XGA 0x0301 +#define PCI_CLASS_DISPLAY_OTHER 0x0380 + +#define PCI_BASE_CLASS_MULTIMEDIA 0x04 +#define PCI_CLASS_MULTIMEDIA_VIDEO 0x0400 +#define PCI_CLASS_MULTIMEDIA_AUDIO 0x0401 +#define PCI_CLASS_MULTIMEDIA_OTHER 0x0480 + +#define PCI_BASE_CLASS_MEMORY 0x05 +#define PCI_CLASS_MEMORY_RAM 0x0500 +#define PCI_CLASS_MEMORY_FLASH 0x0501 +#define PCI_CLASS_MEMORY_OTHER 0x0580 + +#define PCI_BASE_CLASS_BRIDGE 0x06 +#define PCI_CLASS_BRIDGE_HOST 0x0600 +#define PCI_CLASS_BRIDGE_ISA 0x0601 +#define PCI_CLASS_BRIDGE_EISA 0x0602 +#define PCI_CLASS_BRIDGE_MC 0x0603 +#define PCI_CLASS_BRIDGE_PCI 0x0604 +#define PCI_CLASS_BRIDGE_PCMCIA 0x0605 +#define PCI_CLASS_BRIDGE_NUBUS 0x0606 +#define PCI_CLASS_BRIDGE_CARDBUS 0x0607 +#define PCI_CLASS_BRIDGE_OTHER 0x0680 + + +#define PCI_BASE_CLASS_COMMUNICATION 0x07 +#define PCI_CLASS_COMMUNICATION_SERIAL 0x0700 +#define PCI_CLASS_COMMUNICATION_PARALLEL 0x0701 +#define PCI_CLASS_COMMUNICATION_OTHER 0x0780 + +#define PCI_BASE_CLASS_SYSTEM 0x08 +#define PCI_CLASS_SYSTEM_PIC 0x0800 +#define PCI_CLASS_SYSTEM_DMA 0x0801 +#define PCI_CLASS_SYSTEM_TIMER 0x0802 +#define PCI_CLASS_SYSTEM_RTC 0x0803 +#define PCI_CLASS_SYSTEM_OTHER 0x0880 + +#define PCI_BASE_CLASS_INPUT 0x09 +#define PCI_CLASS_INPUT_KEYBOARD 0x0900 +#define PCI_CLASS_INPUT_PEN 0x0901 +#define PCI_CLASS_INPUT_MOUSE 0x0902 +#define PCI_CLASS_INPUT_OTHER 0x0980 + +#define PCI_BASE_CLASS_DOCKING 0x0a +#define PCI_CLASS_DOCKING_GENERIC 0x0a00 +#define PCI_CLASS_DOCKING_OTHER 0x0a01 + +#define PCI_BASE_CLASS_PROCESSOR 0x0b +#define PCI_CLASS_PROCESSOR_386 0x0b00 +#define PCI_CLASS_PROCESSOR_486 0x0b01 +#define PCI_CLASS_PROCESSOR_PENTIUM 0x0b02 +#define PCI_CLASS_PROCESSOR_ALPHA 0x0b10 +#define PCI_CLASS_PROCESSOR_POWERPC 0x0b20 +#define PCI_CLASS_PROCESSOR_CO 0x0b40 + +#define PCI_BASE_CLASS_SERIAL 0x0c +#define PCI_CLASS_SERIAL_FIREWIRE 0x0c00 +#define PCI_CLASS_SERIAL_ACCESS 0x0c01 +#define PCI_CLASS_SERIAL_SSA 0x0c02 +#define PCI_CLASS_SERIAL_USB 0x0c03 +#define PCI_CLASS_SERIAL_FIBER 0x0c04 + +#define PCI_CLASS_OTHERS 0xff |