adv_pci.c revision 76307
139217Sgibbs/* 239217Sgibbs * Device probe and attach routines for the following 339217Sgibbs * Advanced Systems Inc. SCSI controllers: 439217Sgibbs * 539217Sgibbs * Connectivity Products: 655945Sgibbs * ABP902/3902 - Bus-Master PCI (16 CDB) 755945Sgibbs * ABP3905 - Bus-Master PCI (16 CDB) 855945Sgibbs * ABP915 - Bus-Master PCI (16 CDB) 955945Sgibbs * ABP920 - Bus-Master PCI (16 CDB) 1055945Sgibbs * ABP3922 - Bus-Master PCI (16 CDB) 1155945Sgibbs * ABP3925 - Bus-Master PCI (16 CDB) 1255945Sgibbs * ABP930 - Bus-Master PCI (16 CDB) * 1355945Sgibbs * ABP930U - Bus-Master PCI Ultra (16 CDB) 1455945Sgibbs * ABP930UA - Bus-Master PCI Ultra (16 CDB) 1555945Sgibbs * ABP960 - Bus-Master PCI MAC/PC (16 CDB) ** 1657679Sgibbs * ABP960U - Bus-Master PCI MAC/PC (16 CDB) ** 1739217Sgibbs * 1839217Sgibbs * Single Channel Products: 1957679Sgibbs * ABP940 - Bus-Master PCI (240 CDB) 2057679Sgibbs * ABP940U - Bus-Master PCI Ultra (240 CDB) 2157679Sgibbs * ABP940UA/3940UA - Bus-Master PCI Ultra (240 CDB) 2257679Sgibbs * ABP3960UA - Bus-Master PCI MAC/PC (240 CDB) 2357679Sgibbs * ABP970 - Bus-Master PCI MAC/PC (240 CDB) 2457679Sgibbs * ABP970U - Bus-Master PCI MAC/PC Ultra (240 CDB) 2539217Sgibbs * 2639217Sgibbs * Dual Channel Products: 2739217Sgibbs * ABP950 - Dual Channel Bus-Master PCI (240 CDB Per Channel) 2857679Sgibbs * ABP980 - Four Channel Bus-Master PCI (240 CDB Per Channel) 2957679Sgibbs * ABP980U - Four Channel Bus-Master PCI Ultra (240 CDB Per Channel) 3055945Sgibbs * ABP980UA/3980UA - Four Channel Bus-Master PCI Ultra (16 CDB Per Chan.) 3139217Sgibbs * 3239217Sgibbs * Footnotes: 3339217Sgibbs * * This board has been sold by SIIG as the Fast SCSI Pro PCI. 3439217Sgibbs * ** This board has been sold by Iomega as a Jaz Jet PCI adapter. 3539217Sgibbs * 3639217Sgibbs * Copyright (c) 1997 Justin Gibbs. 3739217Sgibbs * All rights reserved. 3839217Sgibbs * 3939217Sgibbs * Redistribution and use in source and binary forms, with or without 4039217Sgibbs * modification, are permitted provided that the following conditions 4139217Sgibbs * are met: 4239217Sgibbs * 1. Redistributions of source code must retain the above copyright 4339217Sgibbs * notice, this list of conditions, and the following disclaimer, 4455945Sgibbs * without modification. 4539217Sgibbs * 2. The name of the author may not be used to endorse or promote products 4639217Sgibbs * derived from this software without specific prior written permission. 4739217Sgibbs * 4839217Sgibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 4939217Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 5039217Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 5139217Sgibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 5239217Sgibbs * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 5339217Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 5439217Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 5539217Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 5639217Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5739217Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5839217Sgibbs * SUCH DAMAGE. 5939217Sgibbs * 6050477Speter * $FreeBSD: head/sys/dev/advansys/adv_pci.c 76307 2001-05-06 08:33:29Z nyan $ 6139217Sgibbs */ 6239217Sgibbs 6339217Sgibbs#include <sys/param.h> 6439217Sgibbs#include <sys/systm.h> 6539217Sgibbs#include <sys/kernel.h> 6639217Sgibbs 6739217Sgibbs#include <machine/bus_pio.h> 6839217Sgibbs#include <machine/bus.h> 6959082Snyan#include <machine/resource.h> 7059082Snyan#include <sys/bus.h> 7159082Snyan#include <sys/rman.h> 7239217Sgibbs 7339217Sgibbs#include <pci/pcireg.h> 7439217Sgibbs#include <pci/pcivar.h> 7539217Sgibbs 7639217Sgibbs#include <dev/advansys/advansys.h> 7739217Sgibbs 7861034Speter#define PCI_BASEADR0 PCIR_MAPS /* I/O Address */ 7961034Speter#define PCI_BASEADR1 PCIR_MAPS + 4 /* Mem I/O Address */ 8039217Sgibbs 8139217Sgibbs#define PCI_DEVICE_ID_ADVANSYS_1200A 0x110010CD 8239217Sgibbs#define PCI_DEVICE_ID_ADVANSYS_1200B 0x120010CD 8355945Sgibbs#define PCI_DEVICE_ID_ADVANSYS_3000 0x130010CD 8439217Sgibbs#define PCI_DEVICE_REV_ADVANSYS_3150 0x02 8539217Sgibbs#define PCI_DEVICE_REV_ADVANSYS_3050 0x03 8639217Sgibbs 8739217Sgibbs#define ADV_PCI_MAX_DMA_ADDR (0xFFFFFFFFL) 8839217Sgibbs#define ADV_PCI_MAX_DMA_COUNT (0xFFFFFFFFL) 8939217Sgibbs 9059082Snyanstatic int adv_pci_probe(device_t); 9159082Snyanstatic int adv_pci_attach(device_t); 9239217Sgibbs 9339217Sgibbs/* 9439217Sgibbs * The overrun buffer shared amongst all PCI adapters. 9539217Sgibbs */ 9639217Sgibbsstatic u_int8_t* overrun_buf; 9742012Sgibbsstatic bus_dma_tag_t overrun_dmat; 9842012Sgibbsstatic bus_dmamap_t overrun_dmamap; 9942012Sgibbsstatic bus_addr_t overrun_physbase; 10039217Sgibbs 10159082Snyanstatic int 10259082Snyanadv_pci_probe(device_t dev) 10339217Sgibbs{ 10459082Snyan int rev = pci_get_revid(dev); 10555945Sgibbs 10659082Snyan switch (pci_get_devid(dev)) { 10739217Sgibbs case PCI_DEVICE_ID_ADVANSYS_1200A: 10859082Snyan device_set_desc(dev, "AdvanSys ASC1200A SCSI controller"); 10959082Snyan return 0; 11039217Sgibbs case PCI_DEVICE_ID_ADVANSYS_1200B: 11159082Snyan device_set_desc(dev, "AdvanSys ASC1200B SCSI controller"); 11259082Snyan return 0; 11355945Sgibbs case PCI_DEVICE_ID_ADVANSYS_3000: 11459082Snyan if (rev == PCI_DEVICE_REV_ADVANSYS_3150) { 11559082Snyan device_set_desc(dev, 11659082Snyan "AdvanSys ASC3150 SCSI controller"); 11759082Snyan return 0; 11859082Snyan } else if (rev == PCI_DEVICE_REV_ADVANSYS_3050) { 11959082Snyan device_set_desc(dev, 12059082Snyan "AdvanSys ASC3030/50 SCSI controller"); 12159082Snyan return 0; 12259082Snyan } else if (rev >= PCI_DEVICE_REV_ADVANSYS_3150) { 12359082Snyan device_set_desc(dev, "Unknown AdvanSys controller"); 12459082Snyan return 0; 12559082Snyan } 12639217Sgibbs break; 12739217Sgibbs default: 12839217Sgibbs break; 12939217Sgibbs } 13059082Snyan return ENXIO; 13139217Sgibbs} 13239217Sgibbs 13359082Snyanstatic int 13459082Snyanadv_pci_attach(device_t dev) 13539217Sgibbs{ 13639217Sgibbs struct adv_softc *adv; 13739217Sgibbs u_int32_t id; 13839217Sgibbs u_int32_t command; 13976307Snyan int error, rid, irqrid; 14059082Snyan void *ih; 14159082Snyan struct resource *iores, *irqres; 14259082Snyan 14339217Sgibbs /* 14439217Sgibbs * Determine the chip version. 14539217Sgibbs */ 14661034Speter id = pci_read_config(dev, PCIR_DEVVENDOR, /*bytes*/4); 14759082Snyan command = pci_read_config(dev, PCIR_COMMAND, /*bytes*/1); 14839217Sgibbs 14939217Sgibbs /* 15039217Sgibbs * These cards do not allow memory mapped accesses, so we must 15139217Sgibbs * ensure that I/O accesses are available or we won't be able 15239217Sgibbs * to talk to them. 15339217Sgibbs */ 15439217Sgibbs if ((command & (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN)) 15539217Sgibbs != (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN)) { 15639217Sgibbs command |= PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN; 15759082Snyan pci_write_config(dev, PCIR_COMMAND, command, /*bytes*/1); 15839217Sgibbs } 15939217Sgibbs 16039217Sgibbs /* 16139217Sgibbs * Early chips can't handle non-zero latency timer settings. 16239217Sgibbs */ 16339217Sgibbs if (id == PCI_DEVICE_ID_ADVANSYS_1200A 16439217Sgibbs || id == PCI_DEVICE_ID_ADVANSYS_1200B) { 16559082Snyan pci_write_config(dev, PCIR_LATTIMER, /*value*/0, /*bytes*/1); 16639217Sgibbs } 16739217Sgibbs 16859171Snyan rid = PCI_BASEADR0; 16959082Snyan iores = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, 17059082Snyan RF_ACTIVE); 17159082Snyan if (iores == NULL) 17259082Snyan return ENXIO; 17339217Sgibbs 17459082Snyan if (adv_find_signature(rman_get_bustag(iores), 17559171Snyan rman_get_bushandle(iores)) == 0) { 17676307Snyan bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); 17759082Snyan return ENXIO; 17859171Snyan } 17939217Sgibbs 18059082Snyan adv = adv_alloc(dev, rman_get_bustag(iores), rman_get_bushandle(iores)); 18159171Snyan if (adv == NULL) { 18276307Snyan bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); 18359082Snyan return ENXIO; 18459171Snyan } 18539217Sgibbs 18639217Sgibbs /* Allocate a dmatag for our transfer DMA maps */ 18739217Sgibbs /* XXX Should be a child of the PCI bus dma tag */ 18849860Sgibbs error = bus_dma_tag_create(/*parent*/NULL, /*alignment*/1, 18939217Sgibbs /*boundary*/0, 19039217Sgibbs /*lowaddr*/ADV_PCI_MAX_DMA_ADDR, 19139217Sgibbs /*highaddr*/BUS_SPACE_MAXADDR, 19239217Sgibbs /*filter*/NULL, /*filterarg*/NULL, 19339217Sgibbs /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, 19439217Sgibbs /*nsegments*/BUS_SPACE_UNRESTRICTED, 19539217Sgibbs /*maxsegsz*/ADV_PCI_MAX_DMA_COUNT, 19639217Sgibbs /*flags*/0, 19739217Sgibbs &adv->parent_dmat); 19839217Sgibbs 19939217Sgibbs if (error != 0) { 20039217Sgibbs printf("%s: Could not allocate DMA tag - error %d\n", 20139217Sgibbs adv_name(adv), error); 20239217Sgibbs adv_free(adv); 20376307Snyan bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); 20459082Snyan return ENXIO; 20539217Sgibbs } 20639217Sgibbs 20739217Sgibbs adv->init_level++; 20839217Sgibbs 20939217Sgibbs if (overrun_buf == NULL) { 21039217Sgibbs /* Need to allocate our overrun buffer */ 21139217Sgibbs if (bus_dma_tag_create(adv->parent_dmat, 21239217Sgibbs /*alignment*/8, /*boundary*/0, 21339217Sgibbs ADV_PCI_MAX_DMA_ADDR, BUS_SPACE_MAXADDR, 21439217Sgibbs /*filter*/NULL, /*filterarg*/NULL, 21539217Sgibbs ADV_OVERRUN_BSIZE, /*nsegments*/1, 21639217Sgibbs BUS_SPACE_MAXSIZE_32BIT, /*flags*/0, 21739217Sgibbs &overrun_dmat) != 0) { 21839217Sgibbs bus_dma_tag_destroy(adv->parent_dmat); 21939217Sgibbs adv_free(adv); 22076307Snyan bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); 22159082Snyan return ENXIO; 22239217Sgibbs } 22339217Sgibbs if (bus_dmamem_alloc(overrun_dmat, 22439217Sgibbs (void **)&overrun_buf, 22539217Sgibbs BUS_DMA_NOWAIT, 22639217Sgibbs &overrun_dmamap) != 0) { 22739217Sgibbs bus_dma_tag_destroy(overrun_dmat); 22839217Sgibbs bus_dma_tag_destroy(adv->parent_dmat); 22939217Sgibbs adv_free(adv); 23076307Snyan bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); 23159082Snyan return ENXIO; 23239217Sgibbs } 23339217Sgibbs /* And permanently map it in */ 23439217Sgibbs bus_dmamap_load(overrun_dmat, overrun_dmamap, 23539217Sgibbs overrun_buf, ADV_OVERRUN_BSIZE, 23639217Sgibbs adv_map, &overrun_physbase, 23739217Sgibbs /*flags*/0); 23839217Sgibbs } 23939217Sgibbs 24039217Sgibbs adv->overrun_physbase = overrun_physbase; 24139217Sgibbs 24239217Sgibbs /* 24339217Sgibbs * Stop the chip. 24439217Sgibbs */ 24539217Sgibbs ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT); 24639217Sgibbs ADV_OUTW(adv, ADV_CHIP_STATUS, 0); 24739217Sgibbs 24839217Sgibbs adv->chip_version = ADV_INB(adv, ADV_NONEISA_CHIP_REVISION); 24939217Sgibbs adv->type = ADV_PCI; 25039217Sgibbs 25139217Sgibbs /* 25239217Sgibbs * Setup active negation and signal filtering. 25339217Sgibbs */ 25439217Sgibbs { 25539217Sgibbs u_int8_t extra_cfg; 25639217Sgibbs 25739217Sgibbs if (adv->chip_version >= ADV_CHIP_VER_PCI_ULTRA_3150) 25839217Sgibbs adv->type |= ADV_ULTRA; 25955945Sgibbs if (adv->chip_version == ADV_CHIP_VER_PCI_ULTRA_3050) 26039217Sgibbs extra_cfg = ADV_IFC_ACT_NEG | ADV_IFC_WR_EN_FILTER; 26139217Sgibbs else 26239217Sgibbs extra_cfg = ADV_IFC_ACT_NEG | ADV_IFC_SLEW_RATE; 26339217Sgibbs ADV_OUTB(adv, ADV_REG_IFC, extra_cfg); 26439217Sgibbs } 26539217Sgibbs 26639217Sgibbs if (adv_init(adv) != 0) { 26739217Sgibbs adv_free(adv); 26876307Snyan bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); 26959082Snyan return ENXIO; 27039217Sgibbs } 27139217Sgibbs 27239217Sgibbs adv->max_dma_count = ADV_PCI_MAX_DMA_COUNT; 27339217Sgibbs adv->max_dma_addr = ADV_PCI_MAX_DMA_ADDR; 27439217Sgibbs 27539217Sgibbs#if CC_DISABLE_PCI_PARITY_INT 27641591Sarchie { 27741591Sarchie u_int16_t config_msw; 27841591Sarchie 27941591Sarchie config_msw = ADV_INW(adv, ADV_CONFIG_MSW); 28041591Sarchie config_msw &= 0xFFC0; 28141591Sarchie ADV_OUTW(adv, ADV_CONFIG_MSW, config_msw); 28241591Sarchie } 28339217Sgibbs#endif 28439217Sgibbs 28539217Sgibbs if (id == PCI_DEVICE_ID_ADVANSYS_1200A 28639217Sgibbs || id == PCI_DEVICE_ID_ADVANSYS_1200B) { 28739217Sgibbs adv->bug_fix_control |= ADV_BUG_FIX_IF_NOT_DWB; 28839217Sgibbs adv->bug_fix_control |= ADV_BUG_FIX_ASYN_USE_SYN; 28939217Sgibbs adv->fix_asyn_xfer = ~0; 29039217Sgibbs } 29139217Sgibbs 29276307Snyan irqrid = 0; 29376307Snyan irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &irqrid, 0, ~0, 1, 29459082Snyan RF_SHAREABLE | RF_ACTIVE); 29559082Snyan if (irqres == NULL || 29673280Smarkm bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY, adv_intr, adv, &ih)) { 29739217Sgibbs adv_free(adv); 29876307Snyan bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); 29959082Snyan return ENXIO; 30039217Sgibbs } 30159082Snyan 30239217Sgibbs adv_attach(adv); 30359082Snyan return 0; 30439217Sgibbs} 30559082Snyan 30659082Snyanstatic device_method_t adv_pci_methods[] = { 30759082Snyan /* Device interface */ 30859082Snyan DEVMETHOD(device_probe, adv_pci_probe), 30959082Snyan DEVMETHOD(device_attach, adv_pci_attach), 31059082Snyan { 0, 0 } 31159082Snyan}; 31259082Snyan 31359082Snyanstatic driver_t adv_pci_driver = { 31459082Snyan "adv", adv_pci_methods, sizeof(struct adv_softc) 31559082Snyan}; 31659082Snyan 31759082Snyanstatic devclass_t adv_pci_devclass; 31859082SnyanDRIVER_MODULE(adv, pci, adv_pci_driver, adv_pci_devclass, 0, 0); 319