1/* 2 * Device probe and attach routines for the following 3 * Advanced Systems Inc. SCSI controllers: 4 * 5 * Connectivity Products: 6 * ABP510/5150 - Bus-Master ISA (240 CDB) * 7 * ABP5140 - Bus-Master ISA PnP (16 CDB) * ** 8 * ABP5142 - Bus-Master ISA PnP with floppy (16 CDB) *** 9 * 10 * Single Channel Products: 11 * ABP542 - Bus-Master ISA with floppy (240 CDB) 12 * ABP842 - Bus-Master VL (240 CDB) 13 * 14 * Dual Channel Products: 15 * ABP852 - Dual Channel Bus-Master VL (240 CDB Per Channel) 16 * 17 * * This board has been shipped by HP with the 4020i CD-R drive. 18 * The board has no BIOS so it cannot control a boot device, but 19 * it can control any secondary SCSI device. 20 * ** This board has been sold by SIIG as the i540 SpeedMaster. 21 * *** This board has been sold by SIIG as the i542 SpeedMaster. 22 * 23 * Copyright (c) 1996, 1997 Justin T. Gibbs. 24 * All rights reserved. 25 * 26 * Redistribution and use in source and binary forms, with or without 27 * modification, are permitted provided that the following conditions 28 * are met: 29 * 1. Redistributions of source code must retain the above copyright 30 * notice, this list of conditions, and the following disclaimer, 31 * without modification, immediately at the beginning of the file. 32 * 2. The name of the author may not be used to endorse or promote products 33 * derived from this software without specific prior written permission. 34 * 35 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 36 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 38 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 39 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 40 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 41 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 45 * SUCH DAMAGE. 46 *
|
47 * $Id: adv_isa.c,v 1.3 1997/02/22 09:35:51 peter Exp $
|
47 * $Id: adv_isa.c,v 1.4 1998/09/15 07:03:39 gibbs Exp $ |
48 */ 49 50#include <sys/param.h> 51#include <sys/systm.h> 52#include <sys/malloc.h> 53 54#include <machine/bus_pio.h> 55#include <machine/bus.h> 56 57#include <i386/isa/isa.h> 58#include <i386/isa/isa_device.h> 59 60#include <dev/advansys/advansys.h> 61 62#include <cam/scsi/scsi_all.h> 63 64#define ADV_ISA_MAX_DMA_ADDR (0x00FFFFFFL) 65#define ADV_ISA_MAX_DMA_COUNT (0x00FFFFFFL) 66 67#define ADV_VL_MAX_DMA_ADDR (0x07FFFFFFL) 68#define ADV_VL_MAX_DMA_COUNT (0x07FFFFFFL) 69 70/* 71 * The overrun buffer shared amongst all ISA/VL adapters. 72 */ 73static u_int8_t* overrun_buf; 74bus_dma_tag_t overrun_dmat; 75bus_dmamap_t overrun_dmamap; 76bus_addr_t overrun_physbase; 77 78/* Possible port addresses an ISA or VL adapter can live at */ 79u_int16_t adv_isa_ioports[] = 80{ 81 0x100, 82 0x110, /* First selection in BIOS setup */ 83 0x120, 84 0x130, /* Second selection in BIOS setup */ 85 0x140, 86 0x150, /* Third selection in BIOS setup */ 87 0x190, /* Fourth selection in BIOS setup */ 88 0x210, /* Fifth selection in BIOS setup */ 89 0x230, /* Sixth selection in BIOS setup */ 90 0x250, /* Seventh selection in BIOS setup */ 91 0x330 /* Eighth and default selection in BIOS setup */ 92}; 93 94#define MAX_ISA_IOPORT_INDEX (sizeof(adv_isa_ioports)/sizeof(u_int16_t) - 1) 95 96static int advisaprobe(struct isa_device *id); 97static int advisaattach(struct isa_device *id); 98static void adv_set_isapnp_wait_for_key(void); 99static int adv_get_isa_dma_channel(struct adv_softc *adv); 100static int adv_set_isa_dma_settings(struct adv_softc *adv); 101 102void adv_isa_intr(void *unit); 103 104struct isa_driver advdriver = 105{ 106 advisaprobe, 107 advisaattach, 108 "adv" 109}; 110 111static int 112advisaprobe(struct isa_device *id) 113{ 114 int port_index; 115 int max_port_index; 116 117 /* 118 * Default to scanning all possible device locations. 119 */ 120 port_index = 0; 121 max_port_index = MAX_ISA_IOPORT_INDEX; 122 123 if (id->id_iobase > 0) { 124 for (;port_index <= max_port_index; port_index++) 125 if (id->id_iobase >= adv_isa_ioports[port_index]) 126 break; 127 if ((port_index > max_port_index) 128 || (id->id_iobase != adv_isa_ioports[port_index])) { 129 printf("adv%d: Invalid baseport of 0x%x specified. " 130 "Neerest valid baseport is 0x%x. Failing " 131 "probe.\n", id->id_unit, id->id_iobase, 132 (port_index <= max_port_index) ? 133 adv_isa_ioports[port_index] : 134 adv_isa_ioports[max_port_index]); 135 return 0; 136 } 137 max_port_index = port_index; 138 } 139 140 /* Perform the actual probing */ 141 adv_set_isapnp_wait_for_key(); 142 for (;port_index <= max_port_index; port_index++) { 143 u_int16_t port_addr = adv_isa_ioports[port_index]; 144 bus_size_t maxsegsz; 145 bus_size_t maxsize; 146 bus_addr_t lowaddr; 147 int error; 148 149 if (port_addr == 0) 150 /* Already been attached */ 151 continue;
|
152 /* 153 * Make sure that we do not conflict with another device's 154 * I/O address. 155 */ 156 if (haveseen_isadev(id, CC_IOADDR)) 157 continue; 158 |
159 if (adv_find_signature(I386_BUS_SPACE_IO, port_addr)) { 160 /* 161 * Got one. Now allocate our softc 162 * and see if we can initialize the card. 163 */ 164 struct adv_softc *adv; 165 adv = adv_alloc(id->id_unit, I386_BUS_SPACE_IO, 166 port_addr); 167 if (adv == NULL) 168 return (0); 169 170 adv_unit++; 171 172 id->id_iobase = adv->bsh; 173 174 /* 175 * Stop the chip. 176 */ 177 ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT); 178 ADV_OUTW(adv, ADV_CHIP_STATUS, 0); 179 /* 180 * Determine the chip version. 181 */ 182 adv->chip_version = ADV_INB(adv, 183 ADV_NONEISA_CHIP_REVISION); 184 if ((adv->chip_version >= ADV_CHIP_MIN_VER_VL) 185 && (adv->chip_version <= ADV_CHIP_MAX_VER_VL)) { 186 adv->type = ADV_VL; 187 maxsegsz = ADV_VL_MAX_DMA_COUNT; 188 maxsize = BUS_SPACE_MAXSIZE_32BIT; 189 lowaddr = ADV_VL_MAX_DMA_ADDR; 190 id->id_drq = -1; 191 } else if ((adv->chip_version >= ADV_CHIP_MIN_VER_ISA) 192 && (adv->chip_version <= ADV_CHIP_MAX_VER_ISA)) { 193 if (adv->chip_version >= ADV_CHIP_MIN_VER_ISA_PNP) { 194 adv->type = ADV_ISAPNP; 195 ADV_OUTB(adv, ADV_REG_IFC, 196 ADV_IFC_INIT_DEFAULT); 197 } else { 198 adv->type = ADV_ISA; 199 } 200 maxsegsz = ADV_ISA_MAX_DMA_COUNT; 201 maxsize = BUS_SPACE_MAXSIZE_24BIT; 202 lowaddr = ADV_ISA_MAX_DMA_ADDR; 203 adv->isa_dma_speed = ADV_DEF_ISA_DMA_SPEED; 204 adv->isa_dma_channel = 205 adv_get_isa_dma_channel(adv); 206 id->id_drq = adv->isa_dma_channel; 207 } else { 208 panic("advisaprobe: Unknown card revision\n"); 209 } 210 211 /* 212 * Allocate a parent dmatag for all tags created 213 * by the MI portions of the advansys driver 214 */ 215 /* XXX Should be a child of the ISA bus dma tag */ 216 error = 217 bus_dma_tag_create(/*parent*/NULL, 218 /*alignemnt*/0, 219 /*boundary*/0, 220 lowaddr, 221 /*highaddr*/BUS_SPACE_MAXADDR, 222 /*filter*/NULL, 223 /*filterarg*/NULL, 224 maxsize, 225 /*nsegs*/BUS_SPACE_UNRESTRICTED, 226 maxsegsz, 227 /*flags*/0, 228 &adv->parent_dmat); 229 230 if (error != 0) { 231 printf("%s: Could not allocate DMA tag - error %d\n", 232 adv_name(adv), error); 233 adv_free(adv); 234 return (0); 235 } 236 237 adv->init_level++; 238 239 if (overrun_buf == NULL) { 240 /* Need to allocate our overrun buffer */ 241 if (bus_dma_tag_create(adv->parent_dmat, 242 /*alignment*/8, 243 /*boundary*/0, 244 ADV_ISA_MAX_DMA_ADDR, 245 BUS_SPACE_MAXADDR, 246 /*filter*/NULL, 247 /*filterarg*/NULL, 248 ADV_OVERRUN_BSIZE, 249 /*nsegments*/1, 250 BUS_SPACE_MAXSIZE_32BIT, 251 /*flags*/0, 252 &overrun_dmat) != 0) { 253 adv_free(adv); 254 return (0); 255 } 256 if (bus_dmamem_alloc(overrun_dmat, 257 (void **)&overrun_buf, 258 BUS_DMA_NOWAIT, 259 &overrun_dmamap) != 0) { 260 bus_dma_tag_destroy(overrun_dmat); 261 adv_free(adv); 262 return (0); 263 } 264 /* And permanently map it in */ 265 bus_dmamap_load(overrun_dmat, overrun_dmamap, 266 overrun_buf, ADV_OVERRUN_BSIZE, 267 adv_map, &overrun_physbase, 268 /*flags*/0); 269 } 270 271 adv->overrun_physbase = overrun_physbase; 272
|
273 /* 274 * OK, check to make sure that we're not stepping on 275 * someone else's IRQ or DRQ 276 */ 277 if (haveseen_isadev(id, CC_DRQ)) { 278 printf("advisaprobe: Aha card at I/O 0x%x's " 279 "drq %d conflicts, ignoring card.\n", 280 id->id_iobase, id->id_drq); 281 adv_free(adv); 282 return 0; 283 } 284 |
285 if (adv_init(adv) != 0) { 286 adv_free(adv); 287 return (0); 288 } 289 290 switch (adv->type) { 291 case ADV_ISAPNP: 292 if (adv->chip_version == ADV_CHIP_VER_ASYN_BUG){ 293 adv->bug_fix_control 294 |= ADV_BUG_FIX_ASYN_USE_SYN; 295 adv->fix_asyn_xfer = ~0; 296 } 297 /* Fall Through */ 298 case ADV_ISA: 299 adv->max_dma_count = ADV_ISA_MAX_DMA_COUNT; 300 adv->max_dma_addr = ADV_ISA_MAX_DMA_ADDR; 301 adv_set_isa_dma_settings(adv); 302 break; 303 304 case ADV_VL: 305 adv->max_dma_count = ADV_VL_MAX_DMA_COUNT; 306 adv->max_dma_addr = ADV_VL_MAX_DMA_ADDR; 307 break; 308 default: 309 panic("advisaprobe: Invalid card type\n"); 310 } 311 312 /* Determine our IRQ */ 313 if (id->id_irq == 0 /* irq ? */) 314 id->id_irq = 1 << adv_get_chip_irq(adv); 315 else 316 adv_set_chip_irq(adv, ffs(id->id_irq) - 1);
|
317 |
318 id->id_intr = adv_isa_intr; 319 320 /* Mark as probed */ 321 adv_isa_ioports[port_index] = 0; 322 return 1; 323 } 324 } 325 326 return 0; 327} 328 329static int 330advisaattach(struct isa_device *id) 331{ 332 struct adv_softc *adv; 333 334 adv = advsoftcs[id->id_unit]; 335 return (adv_attach(adv)); 336} 337 338static int 339adv_get_isa_dma_channel(struct adv_softc *adv) 340{ 341 int channel; 342 343 channel = ADV_INW(adv, ADV_CONFIG_LSW) & ADV_CFG_LSW_ISA_DMA_CHANNEL; 344 if (channel == 0x03) 345 return (0); 346 else if (channel == 0x00) 347 return (7); 348 return (channel + 4); 349} 350 351static int 352adv_set_isa_dma_settings(struct adv_softc *adv) 353{ 354 u_int16_t cfg_lsw; 355 u_int8_t value; 356 357 if ((adv->isa_dma_channel >= 5) && (adv->isa_dma_channel <= 7)) { 358 if (adv->isa_dma_channel == 7) 359 value = 0x00; 360 else 361 value = adv->isa_dma_channel - 4; 362 cfg_lsw = ADV_INW(adv, ADV_CONFIG_LSW) 363 & ~ADV_CFG_LSW_ISA_DMA_CHANNEL; 364 cfg_lsw |= value; 365 ADV_OUTW(adv, ADV_CONFIG_LSW, cfg_lsw); 366 367 adv->isa_dma_speed &= 0x07; 368 adv_set_bank(adv, 1); 369 ADV_OUTB(adv, ADV_DMA_SPEED, adv->isa_dma_speed); 370 adv_set_bank(adv, 0); 371 isa_dmacascade(adv->isa_dma_channel); 372 } 373 return (0); 374} 375 376static void 377adv_set_isapnp_wait_for_key(void) 378{ 379 static int isapnp_wait_set = 0; 380 if (isapnp_wait_set == 0) { 381 outb(ADV_ISA_PNP_PORT_ADDR, 0x02); 382 outb(ADV_ISA_PNP_PORT_WRITE, 0x02); 383 isapnp_wait_set++; 384 } 385 return; 386} 387 388/* 389 * Handle an ISA interrupt. 390 * XXX should go away as soon as ISA interrupt handlers 391 * take a (void *) arg. 392 */ 393void 394adv_isa_intr(void *unit) 395{ 396 struct adv_softc *arg = advsoftcs[(int)unit]; 397 adv_intr((void *)arg); 398}
|