adv_pci.c revision 42012
1/* 2 * Device probe and attach routines for the following 3 * Advanced Systems Inc. SCSI controllers: 4 * 5 * Connectivity Products: 6 * ABP920 - Bus-Master PCI (16 CDB) 7 * ABP930 - Bus-Master PCI (16 CDB) * 8 * ABP930U - Bus-Master PCI Ultra (16 CDB) 9 * ABP930UA - Bus-Master PCI Ultra (16 CDB) 10 * ABP960 - Bus-Master PCI MAC/PC (16 CDB) ** 11 * ABP960U - Bus-Master PCI MAC/PC Ultra (16 CDB) 12 * 13 * Single Channel Products: 14 * ABP940 - Bus-Master PCI (240 CDB) 15 * ABP940U - Bus-Master PCI Ultra (240 CDB) 16 * ABP970 - Bus-Master PCI MAC/PC (240 CDB) 17 * ABP970U - Bus-Master PCI MAC/PC Ultra (240 CDB) 18 * 19 * Dual Channel Products: 20 * ABP950 - Dual Channel Bus-Master PCI (240 CDB Per Channel) 21 * 22 * Footnotes: 23 * * This board has been sold by SIIG as the Fast SCSI Pro PCI. 24 * ** This board has been sold by Iomega as a Jaz Jet PCI adapter. 25 * 26 * Copyright (c) 1997 Justin Gibbs. 27 * All rights reserved. 28 * 29 * Redistribution and use in source and binary forms, with or without 30 * modification, are permitted provided that the following conditions 31 * are met: 32 * 1. Redistributions of source code must retain the above copyright 33 * notice, this list of conditions, and the following disclaimer, 34 * without modification, immediately at the beginning of the file. 35 * 2. The name of the author may not be used to endorse or promote products 36 * derived from this software without specific prior written permission. 37 * 38 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 39 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 41 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 42 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 43 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 44 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 46 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 47 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 48 * SUCH DAMAGE. 49 * 50 * $Id: adv_pci.c,v 1.3 1998/12/14 06:32:54 dillon Exp $ 51 */ 52 53#include <pci.h> 54#if NPCI > 0 55#include <sys/param.h> 56#include <sys/systm.h> 57#include <sys/kernel.h> 58 59#include <machine/bus_pio.h> 60#include <machine/bus.h> 61 62#include <pci/pcireg.h> 63#include <pci/pcivar.h> 64 65#include <dev/advansys/advansys.h> 66 67#define PCI_BASEADR0 PCI_MAP_REG_START /* I/O Address */ 68#define PCI_BASEADR1 PCI_MAP_REG_START + 4 /* Mem I/O Address */ 69 70#define PCI_DEVICE_ID_ADVANSYS_1200A 0x110010CD 71#define PCI_DEVICE_ID_ADVANSYS_1200B 0x120010CD 72#define PCI_DEVICE_ID_ADVANSYS_ULTRA 0x130010CD 73#define PCI_DEVICE_REV_ADVANSYS_3150 0x02 74#define PCI_DEVICE_REV_ADVANSYS_3050 0x03 75 76#define ADV_PCI_MAX_DMA_ADDR (0xFFFFFFFFL) 77#define ADV_PCI_MAX_DMA_COUNT (0xFFFFFFFFL) 78 79static const char* advpciprobe(pcici_t tag, pcidi_t type); 80static void advpciattach(pcici_t config_id, int unit); 81 82/* 83 * The overrun buffer shared amongst all PCI adapters. 84 */ 85static u_int8_t* overrun_buf; 86static bus_dma_tag_t overrun_dmat; 87static bus_dmamap_t overrun_dmamap; 88static bus_addr_t overrun_physbase; 89 90static struct pci_device adv_pci_driver = { 91 "adv", 92 advpciprobe, 93 advpciattach, 94 &adv_unit, 95 NULL 96}; 97 98DATA_SET (pcidevice_set, adv_pci_driver); 99 100static const char* 101advpciprobe(pcici_t tag, pcidi_t type) 102{ 103 int rev = pci_conf_read(tag, PCI_CLASS_REG) & 0xff; 104 switch (type) { 105 case PCI_DEVICE_ID_ADVANSYS_1200A: 106 return ("AdvanSys ASC1200A SCSI controller"); 107 case PCI_DEVICE_ID_ADVANSYS_1200B: 108 return ("AdvanSys ASC1200B SCSI controller"); 109 case PCI_DEVICE_ID_ADVANSYS_ULTRA: 110 if (rev == PCI_DEVICE_REV_ADVANSYS_3150) 111 return ("AdvanSys ASC3150 Ultra SCSI controller"); 112 else 113 return ("AdvanSys ASC3050 Ultra SCSI controller"); 114 break; 115 default: 116 break; 117 } 118 return (NULL); 119} 120 121static void 122advpciattach(pcici_t config_id, int unit) 123{ 124 u_int16_t io_port; 125 struct adv_softc *adv; 126 u_int32_t id; 127 u_int32_t command; 128 int error; 129 130 /* 131 * Determine the chip version. 132 */ 133 id = pci_cfgread(config_id, PCI_ID_REG, /*bytes*/4); 134 command = pci_cfgread(config_id, PCIR_COMMAND, /*bytes*/1); 135 136 /* 137 * These cards do not allow memory mapped accesses, so we must 138 * ensure that I/O accesses are available or we won't be able 139 * to talk to them. 140 */ 141 if ((command & (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN)) 142 != (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN)) { 143 command |= PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN; 144 pci_cfgwrite(config_id, PCIR_COMMAND, command, /*bytes*/1); 145 } 146 147 /* 148 * Early chips can't handle non-zero latency timer settings. 149 */ 150 if (id == PCI_DEVICE_ID_ADVANSYS_1200A 151 || id == PCI_DEVICE_ID_ADVANSYS_1200B) { 152 pci_cfgwrite(config_id, PCIR_LATTIMER, /*value*/0, /*bytes*/1); 153 } 154 155 156 if (pci_map_port(config_id, PCI_BASEADR0, &io_port) == 0) 157 return; 158 159 if (adv_find_signature(I386_BUS_SPACE_IO, io_port) == 0) 160 return; 161 162 adv = adv_alloc(unit, I386_BUS_SPACE_IO, io_port); 163 if (adv == NULL) 164 return; 165 166 /* Allocate a dmatag for our transfer DMA maps */ 167 /* XXX Should be a child of the PCI bus dma tag */ 168 error = bus_dma_tag_create(/*parent*/NULL, /*alignment*/0, 169 /*boundary*/0, 170 /*lowaddr*/ADV_PCI_MAX_DMA_ADDR, 171 /*highaddr*/BUS_SPACE_MAXADDR, 172 /*filter*/NULL, /*filterarg*/NULL, 173 /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, 174 /*nsegments*/BUS_SPACE_UNRESTRICTED, 175 /*maxsegsz*/ADV_PCI_MAX_DMA_COUNT, 176 /*flags*/0, 177 &adv->parent_dmat); 178 179 if (error != 0) { 180 printf("%s: Could not allocate DMA tag - error %d\n", 181 adv_name(adv), error); 182 adv_free(adv); 183 return; 184 } 185 186 adv->init_level++; 187 188 if (overrun_buf == NULL) { 189 /* Need to allocate our overrun buffer */ 190 if (bus_dma_tag_create(adv->parent_dmat, 191 /*alignment*/8, /*boundary*/0, 192 ADV_PCI_MAX_DMA_ADDR, BUS_SPACE_MAXADDR, 193 /*filter*/NULL, /*filterarg*/NULL, 194 ADV_OVERRUN_BSIZE, /*nsegments*/1, 195 BUS_SPACE_MAXSIZE_32BIT, /*flags*/0, 196 &overrun_dmat) != 0) { 197 bus_dma_tag_destroy(adv->parent_dmat); 198 adv_free(adv); 199 return; 200 } 201 if (bus_dmamem_alloc(overrun_dmat, 202 (void **)&overrun_buf, 203 BUS_DMA_NOWAIT, 204 &overrun_dmamap) != 0) { 205 bus_dma_tag_destroy(overrun_dmat); 206 bus_dma_tag_destroy(adv->parent_dmat); 207 adv_free(adv); 208 return; 209 } 210 /* And permanently map it in */ 211 bus_dmamap_load(overrun_dmat, overrun_dmamap, 212 overrun_buf, ADV_OVERRUN_BSIZE, 213 adv_map, &overrun_physbase, 214 /*flags*/0); 215 } 216 217 adv->overrun_physbase = overrun_physbase; 218 219 /* 220 * Stop the chip. 221 */ 222 ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT); 223 ADV_OUTW(adv, ADV_CHIP_STATUS, 0); 224 225 adv->chip_version = ADV_INB(adv, ADV_NONEISA_CHIP_REVISION); 226 adv->type = ADV_PCI; 227 228 /* 229 * Setup active negation and signal filtering. 230 */ 231 { 232 u_int8_t extra_cfg; 233 234 if (adv->chip_version >= ADV_CHIP_VER_PCI_ULTRA_3150) 235 adv->type |= ADV_ULTRA; 236 if (adv->chip_version == ADV_CHIP_VER_PCI_ULTRA_3150) 237 extra_cfg = ADV_IFC_ACT_NEG | ADV_IFC_SLEW_RATE; 238 else if (adv->chip_version == ADV_CHIP_VER_PCI_ULTRA_3050) 239 extra_cfg = ADV_IFC_ACT_NEG | ADV_IFC_WR_EN_FILTER; 240 else 241 extra_cfg = ADV_IFC_ACT_NEG | ADV_IFC_SLEW_RATE; 242 ADV_OUTB(adv, ADV_REG_IFC, extra_cfg); 243 } 244 245 if (adv_init(adv) != 0) { 246 adv_free(adv); 247 return; 248 } 249 250 adv->max_dma_count = ADV_PCI_MAX_DMA_COUNT; 251 adv->max_dma_addr = ADV_PCI_MAX_DMA_ADDR; 252 253#if CC_DISABLE_PCI_PARITY_INT 254 { 255 u_int16_t config_msw; 256 257 config_msw = ADV_INW(adv, ADV_CONFIG_MSW); 258 config_msw &= 0xFFC0; 259 ADV_OUTW(adv, ADV_CONFIG_MSW, config_msw); 260 } 261#endif 262 263 if (id == PCI_DEVICE_ID_ADVANSYS_1200A 264 || id == PCI_DEVICE_ID_ADVANSYS_1200B) { 265 adv->bug_fix_control |= ADV_BUG_FIX_IF_NOT_DWB; 266 adv->bug_fix_control |= ADV_BUG_FIX_ASYN_USE_SYN; 267 adv->fix_asyn_xfer = ~0; 268 } 269 270 if ((pci_map_int(config_id, adv_intr, (void *)adv, &cam_imask)) == 0) { 271 adv_free(adv); 272 return; 273 } 274 275 adv_attach(adv); 276} 277 278#endif /* NPCI > 0 */ 279