adv_pci.c revision 165102
1139749Simp/*- 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 */ 6039217Sgibbs 61119418Sobrien#include <sys/cdefs.h> 62119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/advansys/adv_pci.c 165102 2006-12-11 18:28:31Z mjacob $"); 63119418Sobrien 6439217Sgibbs#include <sys/param.h> 6539217Sgibbs#include <sys/systm.h> 6639217Sgibbs#include <sys/kernel.h> 67117126Sscottl#include <sys/lock.h> 68129879Sphk#include <sys/module.h> 69117126Sscottl#include <sys/mutex.h> 7039217Sgibbs 7139217Sgibbs#include <machine/bus.h> 7259082Snyan#include <machine/resource.h> 7359082Snyan#include <sys/bus.h> 7459082Snyan#include <sys/rman.h> 7539217Sgibbs 76119277Simp#include <dev/pci/pcireg.h> 77119277Simp#include <dev/pci/pcivar.h> 7839217Sgibbs 7939217Sgibbs#include <dev/advansys/advansys.h> 8039217Sgibbs 81119690Sjhb#define PCI_BASEADR0 PCIR_BAR(0) /* I/O Address */ 82119690Sjhb#define PCI_BASEADR1 PCIR_BAR(1) /* Mem I/O Address */ 8339217Sgibbs 8439217Sgibbs#define PCI_DEVICE_ID_ADVANSYS_1200A 0x110010CD 8539217Sgibbs#define PCI_DEVICE_ID_ADVANSYS_1200B 0x120010CD 8655945Sgibbs#define PCI_DEVICE_ID_ADVANSYS_3000 0x130010CD 8739217Sgibbs#define PCI_DEVICE_REV_ADVANSYS_3150 0x02 8839217Sgibbs#define PCI_DEVICE_REV_ADVANSYS_3050 0x03 8939217Sgibbs 9039217Sgibbs#define ADV_PCI_MAX_DMA_ADDR (0xFFFFFFFFL) 9139217Sgibbs#define ADV_PCI_MAX_DMA_COUNT (0xFFFFFFFFL) 9239217Sgibbs 9359082Snyanstatic int adv_pci_probe(device_t); 9459082Snyanstatic int adv_pci_attach(device_t); 9539217Sgibbs 9639217Sgibbs/* 9739217Sgibbs * The overrun buffer shared amongst all PCI adapters. 9839217Sgibbs */ 99155319Simpstatic void* overrun_buf; 10042012Sgibbsstatic bus_dma_tag_t overrun_dmat; 10142012Sgibbsstatic bus_dmamap_t overrun_dmamap; 10242012Sgibbsstatic bus_addr_t overrun_physbase; 10339217Sgibbs 10459082Snyanstatic int 10559082Snyanadv_pci_probe(device_t dev) 10639217Sgibbs{ 10759082Snyan int rev = pci_get_revid(dev); 10855945Sgibbs 10959082Snyan switch (pci_get_devid(dev)) { 11039217Sgibbs case PCI_DEVICE_ID_ADVANSYS_1200A: 11159082Snyan device_set_desc(dev, "AdvanSys ASC1200A SCSI controller"); 112143164Simp return BUS_PROBE_DEFAULT; 11339217Sgibbs case PCI_DEVICE_ID_ADVANSYS_1200B: 11459082Snyan device_set_desc(dev, "AdvanSys ASC1200B SCSI controller"); 115143164Simp return BUS_PROBE_DEFAULT; 11655945Sgibbs case PCI_DEVICE_ID_ADVANSYS_3000: 11759082Snyan if (rev == PCI_DEVICE_REV_ADVANSYS_3150) { 11859082Snyan device_set_desc(dev, 11959082Snyan "AdvanSys ASC3150 SCSI controller"); 120143164Simp return BUS_PROBE_DEFAULT; 12159082Snyan } else if (rev == PCI_DEVICE_REV_ADVANSYS_3050) { 12259082Snyan device_set_desc(dev, 12359082Snyan "AdvanSys ASC3030/50 SCSI controller"); 124143164Simp return BUS_PROBE_DEFAULT; 12559082Snyan } else if (rev >= PCI_DEVICE_REV_ADVANSYS_3150) { 12659082Snyan device_set_desc(dev, "Unknown AdvanSys controller"); 127143164Simp return BUS_PROBE_DEFAULT; 12859082Snyan } 12939217Sgibbs break; 13039217Sgibbs default: 13139217Sgibbs break; 13239217Sgibbs } 13359082Snyan return ENXIO; 13439217Sgibbs} 13539217Sgibbs 13659082Snyanstatic int 13759082Snyanadv_pci_attach(device_t dev) 13839217Sgibbs{ 13939217Sgibbs struct adv_softc *adv; 14039217Sgibbs u_int32_t id; 14139217Sgibbs u_int32_t command; 14276307Snyan int error, rid, irqrid; 14359082Snyan void *ih; 14459082Snyan struct resource *iores, *irqres; 14559082Snyan 14639217Sgibbs /* 14739217Sgibbs * Determine the chip version. 14839217Sgibbs */ 14961034Speter id = pci_read_config(dev, PCIR_DEVVENDOR, /*bytes*/4); 15059082Snyan command = pci_read_config(dev, PCIR_COMMAND, /*bytes*/1); 15139217Sgibbs 15239217Sgibbs /* 15339217Sgibbs * These cards do not allow memory mapped accesses, so we must 15439217Sgibbs * ensure that I/O accesses are available or we won't be able 15539217Sgibbs * to talk to them. 15639217Sgibbs */ 15739217Sgibbs if ((command & (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN)) 15839217Sgibbs != (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN)) { 15939217Sgibbs command |= PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN; 16059082Snyan pci_write_config(dev, PCIR_COMMAND, command, /*bytes*/1); 16139217Sgibbs } 16239217Sgibbs 16339217Sgibbs /* 16439217Sgibbs * Early chips can't handle non-zero latency timer settings. 16539217Sgibbs */ 16639217Sgibbs if (id == PCI_DEVICE_ID_ADVANSYS_1200A 16739217Sgibbs || id == PCI_DEVICE_ID_ADVANSYS_1200B) { 16859082Snyan pci_write_config(dev, PCIR_LATTIMER, /*value*/0, /*bytes*/1); 16939217Sgibbs } 17039217Sgibbs 17159171Snyan rid = PCI_BASEADR0; 172127135Snjl iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, 173127135Snjl RF_ACTIVE); 17459082Snyan if (iores == NULL) 17559082Snyan return ENXIO; 17639217Sgibbs 17759082Snyan if (adv_find_signature(rman_get_bustag(iores), 17859171Snyan rman_get_bushandle(iores)) == 0) { 17976307Snyan bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); 18059082Snyan return ENXIO; 18159171Snyan } 18239217Sgibbs 18359082Snyan adv = adv_alloc(dev, rman_get_bustag(iores), rman_get_bushandle(iores)); 18459171Snyan if (adv == NULL) { 18576307Snyan bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); 18659082Snyan return ENXIO; 18759171Snyan } 18839217Sgibbs 18939217Sgibbs /* Allocate a dmatag for our transfer DMA maps */ 19039217Sgibbs /* XXX Should be a child of the PCI bus dma tag */ 191112782Smdodd error = bus_dma_tag_create( 192112782Smdodd /* parent */ NULL, 193112782Smdodd /* alignment */ 1, 194112782Smdodd /* boundary */ 0, 195112782Smdodd /* lowaddr */ ADV_PCI_MAX_DMA_ADDR, 196112782Smdodd /* highaddr */ BUS_SPACE_MAXADDR, 197112782Smdodd /* filter */ NULL, 198112782Smdodd /* filterarg */ NULL, 199112782Smdodd /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, 200112782Smdodd /* nsegments */ ~0, 201112782Smdodd /* maxsegsz */ ADV_PCI_MAX_DMA_COUNT, 202112782Smdodd /* flags */ 0, 203117126Sscottl /* lockfunc */ busdma_lock_mutex, 204117126Sscottl /* lockarg */ &Giant, 205112782Smdodd &adv->parent_dmat); 20639217Sgibbs 20739217Sgibbs if (error != 0) { 20839217Sgibbs printf("%s: Could not allocate DMA tag - error %d\n", 20939217Sgibbs adv_name(adv), error); 21039217Sgibbs adv_free(adv); 21176307Snyan bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); 21259082Snyan return ENXIO; 21339217Sgibbs } 21439217Sgibbs 21539217Sgibbs adv->init_level++; 21639217Sgibbs 21739217Sgibbs if (overrun_buf == NULL) { 21839217Sgibbs /* Need to allocate our overrun buffer */ 219112782Smdodd if (bus_dma_tag_create( 220112782Smdodd /* parent */ adv->parent_dmat, 221112782Smdodd /* alignment */ 8, 222112782Smdodd /* boundary */ 0, 223112782Smdodd /* lowaddr */ ADV_PCI_MAX_DMA_ADDR, 224112782Smdodd /* highaddr */ BUS_SPACE_MAXADDR, 225112782Smdodd /* filter */ NULL, 226112782Smdodd /* filterarg */ NULL, 227112782Smdodd /* maxsize */ ADV_OVERRUN_BSIZE, 228112782Smdodd /* nsegments */ 1, 229112782Smdodd /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 230112782Smdodd /* flags */ 0, 231117126Sscottl /* lockfunc */ busdma_lock_mutex, 232117126Sscottl /* lockarg */ &Giant, 233112782Smdodd &overrun_dmat) != 0) { 23439217Sgibbs bus_dma_tag_destroy(adv->parent_dmat); 23539217Sgibbs adv_free(adv); 23676307Snyan bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); 23759082Snyan return ENXIO; 23839217Sgibbs } 23939217Sgibbs if (bus_dmamem_alloc(overrun_dmat, 240155319Simp &overrun_buf, 24139217Sgibbs BUS_DMA_NOWAIT, 24239217Sgibbs &overrun_dmamap) != 0) { 24339217Sgibbs bus_dma_tag_destroy(overrun_dmat); 24439217Sgibbs bus_dma_tag_destroy(adv->parent_dmat); 24539217Sgibbs adv_free(adv); 24676307Snyan bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); 24759082Snyan return ENXIO; 24839217Sgibbs } 24939217Sgibbs /* And permanently map it in */ 25039217Sgibbs bus_dmamap_load(overrun_dmat, overrun_dmamap, 25139217Sgibbs overrun_buf, ADV_OVERRUN_BSIZE, 25239217Sgibbs adv_map, &overrun_physbase, 25339217Sgibbs /*flags*/0); 25439217Sgibbs } 25539217Sgibbs 25639217Sgibbs adv->overrun_physbase = overrun_physbase; 25739217Sgibbs 25839217Sgibbs /* 25939217Sgibbs * Stop the chip. 26039217Sgibbs */ 26139217Sgibbs ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT); 26239217Sgibbs ADV_OUTW(adv, ADV_CHIP_STATUS, 0); 26339217Sgibbs 26439217Sgibbs adv->chip_version = ADV_INB(adv, ADV_NONEISA_CHIP_REVISION); 26539217Sgibbs adv->type = ADV_PCI; 26639217Sgibbs 26739217Sgibbs /* 26839217Sgibbs * Setup active negation and signal filtering. 26939217Sgibbs */ 27039217Sgibbs { 27139217Sgibbs u_int8_t extra_cfg; 27239217Sgibbs 27339217Sgibbs if (adv->chip_version >= ADV_CHIP_VER_PCI_ULTRA_3150) 27439217Sgibbs adv->type |= ADV_ULTRA; 27555945Sgibbs if (adv->chip_version == ADV_CHIP_VER_PCI_ULTRA_3050) 27639217Sgibbs extra_cfg = ADV_IFC_ACT_NEG | ADV_IFC_WR_EN_FILTER; 27739217Sgibbs else 27839217Sgibbs extra_cfg = ADV_IFC_ACT_NEG | ADV_IFC_SLEW_RATE; 27939217Sgibbs ADV_OUTB(adv, ADV_REG_IFC, extra_cfg); 28039217Sgibbs } 28139217Sgibbs 28239217Sgibbs if (adv_init(adv) != 0) { 28339217Sgibbs adv_free(adv); 28476307Snyan bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); 28559082Snyan return ENXIO; 28639217Sgibbs } 28739217Sgibbs 28839217Sgibbs adv->max_dma_count = ADV_PCI_MAX_DMA_COUNT; 28939217Sgibbs adv->max_dma_addr = ADV_PCI_MAX_DMA_ADDR; 29039217Sgibbs 291153072Sru#if defined(CC_DISABLE_PCI_PARITY_INT) && CC_DISABLE_PCI_PARITY_INT 29241591Sarchie { 29341591Sarchie u_int16_t config_msw; 29441591Sarchie 29541591Sarchie config_msw = ADV_INW(adv, ADV_CONFIG_MSW); 29641591Sarchie config_msw &= 0xFFC0; 29741591Sarchie ADV_OUTW(adv, ADV_CONFIG_MSW, config_msw); 29841591Sarchie } 29939217Sgibbs#endif 30039217Sgibbs 30139217Sgibbs if (id == PCI_DEVICE_ID_ADVANSYS_1200A 30239217Sgibbs || id == PCI_DEVICE_ID_ADVANSYS_1200B) { 30339217Sgibbs adv->bug_fix_control |= ADV_BUG_FIX_IF_NOT_DWB; 30439217Sgibbs adv->bug_fix_control |= ADV_BUG_FIX_ASYN_USE_SYN; 30539217Sgibbs adv->fix_asyn_xfer = ~0; 30639217Sgibbs } 30739217Sgibbs 30876307Snyan irqrid = 0; 309127135Snjl irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irqrid, 310127135Snjl RF_SHAREABLE | RF_ACTIVE); 31159082Snyan if (irqres == NULL || 31273280Smarkm bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY, adv_intr, adv, &ih)) { 31339217Sgibbs adv_free(adv); 31476307Snyan bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); 31559082Snyan return ENXIO; 31639217Sgibbs } 31759082Snyan 31839217Sgibbs adv_attach(adv); 31959082Snyan return 0; 32039217Sgibbs} 32159082Snyan 32259082Snyanstatic device_method_t adv_pci_methods[] = { 32359082Snyan /* Device interface */ 32459082Snyan DEVMETHOD(device_probe, adv_pci_probe), 32559082Snyan DEVMETHOD(device_attach, adv_pci_attach), 32659082Snyan { 0, 0 } 32759082Snyan}; 32859082Snyan 32959082Snyanstatic driver_t adv_pci_driver = { 33059082Snyan "adv", adv_pci_methods, sizeof(struct adv_softc) 33159082Snyan}; 33259082Snyan 33359082Snyanstatic devclass_t adv_pci_devclass; 33459082SnyanDRIVER_MODULE(adv, pci, adv_pci_driver, adv_pci_devclass, 0, 0); 335165102SmjacobMODULE_DEPEND(adv, pci, 1, 1, 1); 336