diff options
author | gibbs <gibbs@FreeBSD.org> | 1998-09-15 08:33:38 +0000 |
---|---|---|
committer | gibbs <gibbs@FreeBSD.org> | 1998-09-15 08:33:38 +0000 |
commit | 589d4a338b39b4f9e27060b9b9c717ae520f8905 (patch) | |
tree | c4a36ecfbf82749363f81dbb7ccb7eed321da23b /sys/dev/dpt/dpt_pci.c | |
parent | 766d4620976e348ecb44cd6fc16aeceee88fe1ca (diff) | |
download | FreeBSD-src-589d4a338b39b4f9e27060b9b9c717ae520f8905.zip FreeBSD-src-589d4a338b39b4f9e27060b9b9c717ae520f8905.tar.gz |
Conver the DPT driver to CAM. The dpt_control interface is not yet
functional, but will be in another day or so.
Diffstat (limited to 'sys/dev/dpt/dpt_pci.c')
-rw-r--r-- | sys/dev/dpt/dpt_pci.c | 495 |
1 files changed, 88 insertions, 407 deletions
diff --git a/sys/dev/dpt/dpt_pci.c b/sys/dev/dpt/dpt_pci.c index f171c8a..2e2e16b 100644 --- a/sys/dev/dpt/dpt_pci.c +++ b/sys/dev/dpt/dpt_pci.c @@ -29,12 +29,10 @@ */ /* - * dptpci.c: Pseudo device drivers for DPT on PCI on FreeBSD - * - * caveats: We may need an eisa and an isa files too + * dptpci.c: PCI Bus Attachment for DPT SCSI HBAs */ -#ident "$Id: dpt_pci.c,v 1.6 1998/06/02 00:32:38 eivind Exp $" +#ident "$Id: dpt_pci.c,v 1.7 1998/08/05 00:54:37 eivind Exp $" #include "opt_devfs.h" #include "opt_dpt.h" @@ -45,18 +43,19 @@ #include <sys/buf.h> #include <sys/kernel.h> -#include <scsi/scsiconf.h> - #include <pci/pcireg.h> #include <pci/pcivar.h> -#include <sys/dpt.h> -#include <pci/dpt_pci.h> +#include <machine/bus_memio.h> +#include <machine/bus_pio.h> +#include <machine/bus.h> -#include <vm/vm.h> -#include <vm/pmap.h> +#include <cam/scsi/scsi_all.h> + +#include <dev/dpt/dpt.h> +#include <pci/dpt_pci.h> -#define PCI_BASEADR0 PCI_MAP_REG_START /* I/O Address */ +#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 @@ -67,17 +66,16 @@ static char *dpt_pci_probe(pcici_t tag, pcidi_t type); static void dpt_pci_attach(pcici_t config_id, int unit); -static 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 + "dpt", + dpt_pci_probe, + dpt_pci_attach, + &dpt_unit, + NULL }; DATA_SET(pcidevice_set, dpt_pci_driver); @@ -91,16 +89,7 @@ DATA_SET(pcidevice_set, dpt_pci_driver); static 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 + u_int32_t class; #ifndef PCI_COMMAND_MASTER_ENABLE #define PCI_COMMAND_MASTER_ENABLE 0x00000004 @@ -110,398 +99,90 @@ dpt_pci_probe(pcici_t tag, pcidi_t type) #define PCI_SUBCLASS_MASS_STORAGE_SCSI 0x00000000 #endif - if ( bootverbose && !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); + if (((type & 0xffff0000) >> 16) == DPT_DEVICE_ID + && (class & PCI_CLASS_MASK) == PCI_CLASS_MASS_STORAGE + && (class & PCI_SUBCLASS_MASK) == PCI_SUBCLASS_MASS_STORAGE_SCSI) + return ("DPT Caching SCSI RAID Controller"); + return (NULL); } static 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 - dpt_reset_performance(dpt); -#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); - + dpt_softc_t *dpt; + vm_offset_t vaddr; + vm_offset_t paddr; + u_int16_t io_base; + bus_space_tag_t tag; + bus_space_handle_t bsh; + u_int32_t command; + u_int32_t data; + int result; + int ndx; + int s; + + vaddr = NULL; + 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) { + if ((command & PCI_COMMAND_MEM_ENABLE) == 0 + || (pci_map_mem(config_id, PCI_BASEADR1, &vaddr, &paddr)) == 0) { +#endif + if ((command & PCI_COMMAND_IO_ENABLE) == 0 + || (pci_map_port(config_id, PCI_BASEADR0, &io_base)) == 0) + return; + + /* + * If the DPT is mapped as an IDE controller, + * let it be IDE controller + */ + if (io_base == ISA_PRIMARY_WD_ADDRESS - 0x10) { #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)); + printf("dpt%d: Mapped as an IDE controller. " + "Disabling SCSI setup\n", unit); #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); + return; + } - 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 + /* XXX Should be passed in by parent bus */ + /* XXX Why isn't the 0x10 offset incorporated into the reg defs? */ + if (vaddr != 0) { + tag = I386_BUS_SPACE_MEM; + bsh = vaddr + 0x10; + } else { + tag = I386_BUS_SPACE_IO; + bsh = io_base + 0x10; + } - /* 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; - } + if ((dpt = dpt_alloc(unit, tag, bsh)) == NULL) + return; /* XXX PCI code should take return status */ + + /* Allocate a dmatag representing the capabilities of this attachment */ + /* XXX Should be a child of the PCI bus dma tag */ + if (bus_dma_tag_create(/*parent*/NULL, /*alignemnt*/0, /*boundary*/0, + /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, + /*highaddr*/BUS_SPACE_MAXADDR, + /*filter*/NULL, /*filterarg*/NULL, + /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, + /*nsegments*/BUS_SPACE_UNRESTRICTED, + /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, + /*flags*/0, &dpt->parent_dmat) != 0) { + dpt_free(dpt); + return; + } - /* Attach SCSI devices */ - dpt_attach(dpt); - ++dpt_controllers_present; + if (pci_map_int(config_id, dpt_intr, (void *)dpt, &cam_imask) == 0) { + dpt_free(dpt); + return; + } - /* - * 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 - (void) devfs_add_devswf(&dpt_cdevsw, dpt->unit, DV_CHR, - UID_ROOT, GID_WHEEL, 0600, - "dpt%d", dpt->unit); - (void) devfs_add_devswf(&dpt_cdevsw, dpt->unit | SCSI_CONTROL_MASK, - DV_CHR, - UID_ROOT, GID_WHEEL, 0600, - "dpt%d.ctl", dpt->unit); -#endif - } -} + s = splcam(); + if (dpt_init(dpt) != 0) { + dpt_free(dpt); + return; + } -static int -dpt_pci_shutdown(int foo, int bar) -{ -#ifdef DPT_DEBUG_WARN - printf("dpt_pci_shutdown(%x, %x)\n", foo, bar); -#endif - return (0); + /* Register with the XPT */ + dpt_attach(dpt); + splx(s); } - -/* 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: - */ |