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 48#include <sys/cdefs.h> 49__FBSDID("$FreeBSD$"); 50 51#include <sys/param.h> 52#include <sys/systm.h> 53#include <sys/kernel.h> 54#include <sys/module.h> 55#include <sys/lock.h> 56#include <sys/mutex.h> 57 58#include <machine/bus.h> 59#include <machine/resource.h> 60#include <sys/bus.h> 61#include <sys/rman.h> 62 63#include <isa/isavar.h> 64 65#include <dev/advansys/advansys.h> 66 67#include <cam/scsi/scsi_all.h> 68 69#define ADV_ISA_MAX_DMA_ADDR (0x00FFFFFFL) 70#define ADV_ISA_MAX_DMA_COUNT (0x00FFFFFFL) 71 72#define ADV_VL_MAX_DMA_ADDR (0x07FFFFFFL) 73#define ADV_VL_MAX_DMA_COUNT (0x07FFFFFFL) 74 75/* 76 * The overrun buffer shared amongst all ISA/VL adapters. 77 */ 78static u_int8_t* overrun_buf; 79static bus_dma_tag_t overrun_dmat; 80static bus_dmamap_t overrun_dmamap; 81static bus_addr_t overrun_physbase; 82 83/* Possible port addresses an ISA or VL adapter can live at */ 84static u_int16_t adv_isa_ioports[] = 85{ 86 0x100, 87 0x110, /* First selection in BIOS setup */ 88 0x120, 89 0x130, /* Second selection in BIOS setup */ 90 0x140, 91 0x150, /* Third selection in BIOS setup */ 92 0x190, /* Fourth selection in BIOS setup */ 93 0x210, /* Fifth selection in BIOS setup */ 94 0x230, /* Sixth selection in BIOS setup */ 95 0x250, /* Seventh selection in BIOS setup */ 96 0x330 /* Eighth and default selection in BIOS setup */ 97}; 98 99#define MAX_ISA_IOPORT_INDEX (sizeof(adv_isa_ioports)/sizeof(u_int16_t) - 1) 100 101static int adv_isa_probe(device_t dev); 102static int adv_isa_attach(device_t dev); 103static void adv_set_isapnp_wait_for_key(void); 104static int adv_get_isa_dma_channel(struct adv_softc *adv); 105static int adv_set_isa_dma_settings(struct adv_softc *adv); 106 107static int 108adv_isa_probe(device_t dev) 109{ 110 int port_index; 111 int max_port_index; 112 u_long iobase, iocount, irq; 113 int user_iobase = 0; 114 int rid = 0; 115 void *ih; 116 struct resource *iores, *irqres; 117 118 /* 119 * We don't know of any PnP ID's for these cards. 120 */ 121 if (isa_get_logicalid(dev) != 0) 122 return (ENXIO); 123 124 /* 125 * Default to scanning all possible device locations. 126 */ 127 port_index = 0; 128 max_port_index = MAX_ISA_IOPORT_INDEX; 129 130 if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, &iocount) == 0) { 131 user_iobase = 1; 132 for (;port_index <= max_port_index; port_index++) 133 if (iobase <= adv_isa_ioports[port_index]) 134 break; 135 if ((port_index > max_port_index) 136 || (iobase != adv_isa_ioports[port_index])) { 137 if (bootverbose) 138 device_printf(dev, 139 "Invalid baseport of 0x%lx specified. " 140 "Nearest valid baseport is 0x%x. Failing " 141 "probe.\n", iobase, 142 (port_index <= max_port_index) ? 143 adv_isa_ioports[port_index] : 144 adv_isa_ioports[max_port_index]); 145 return ENXIO; 146 } 147 max_port_index = port_index; 148 } 149 150 /* Perform the actual probing */ 151 adv_set_isapnp_wait_for_key(); 152 for (;port_index <= max_port_index; port_index++) { 153 u_int16_t port_addr = adv_isa_ioports[port_index]; 154 bus_size_t maxsegsz; 155 bus_size_t maxsize; 156 bus_addr_t lowaddr; 157 int error; 158 struct adv_softc *adv; 159 160 if (port_addr == 0) 161 /* Already been attached */ 162 continue; 163 164 if (bus_set_resource(dev, SYS_RES_IOPORT, 0, port_addr, 1)) 165 continue; 166 167 /* XXX what is the real portsize? */ 168 iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, 169 RF_ACTIVE); 170 if (iores == NULL) 171 continue; 172 173 if (adv_find_signature(iores) == 0) { 174 bus_release_resource(dev, SYS_RES_IOPORT, 0, iores); 175 continue; 176 } 177 178 /* 179 * Got one. Now allocate our softc 180 * and see if we can initialize the card. 181 */ 182 adv = adv_alloc(dev, iores, 0); 183 if (adv == NULL) { 184 bus_release_resource(dev, SYS_RES_IOPORT, 0, iores); 185 break; 186 } 187 188 /* 189 * Stop the chip. 190 */ 191 ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT); 192 ADV_OUTW(adv, ADV_CHIP_STATUS, 0); 193 /* 194 * Determine the chip version. 195 */ 196 adv->chip_version = ADV_INB(adv, ADV_NONEISA_CHIP_REVISION); 197 if ((adv->chip_version >= ADV_CHIP_MIN_VER_VL) 198 && (adv->chip_version <= ADV_CHIP_MAX_VER_VL)) { 199 adv->type = ADV_VL; 200 maxsegsz = ADV_VL_MAX_DMA_COUNT; 201 maxsize = BUS_SPACE_MAXSIZE_32BIT; 202 lowaddr = ADV_VL_MAX_DMA_ADDR; 203 bus_delete_resource(dev, SYS_RES_DRQ, 0); 204 } else if ((adv->chip_version >= ADV_CHIP_MIN_VER_ISA) 205 && (adv->chip_version <= ADV_CHIP_MAX_VER_ISA)) { 206 if (adv->chip_version >= ADV_CHIP_MIN_VER_ISA_PNP) { 207 adv->type = ADV_ISAPNP; 208 ADV_OUTB(adv, ADV_REG_IFC, 209 ADV_IFC_INIT_DEFAULT); 210 } else { 211 adv->type = ADV_ISA; 212 } 213 maxsegsz = ADV_ISA_MAX_DMA_COUNT; 214 maxsize = BUS_SPACE_MAXSIZE_24BIT; 215 lowaddr = ADV_ISA_MAX_DMA_ADDR; 216 adv->isa_dma_speed = ADV_DEF_ISA_DMA_SPEED; 217 adv->isa_dma_channel = adv_get_isa_dma_channel(adv); 218 bus_set_resource(dev, SYS_RES_DRQ, 0, 219 adv->isa_dma_channel, 1); 220 } else { 221 panic("advisaprobe: Unknown card revision\n"); 222 } 223 224 /* 225 * Allocate a parent dmatag for all tags created 226 * by the MI portions of the advansys driver 227 */ 228 error = bus_dma_tag_create( 229 /* parent */ bus_get_dma_tag(dev), 230 /* alignemnt */ 1, 231 /* boundary */ 0, 232 /* lowaddr */ lowaddr, 233 /* highaddr */ BUS_SPACE_MAXADDR, 234 /* filter */ NULL, 235 /* filterarg */ NULL, 236 /* maxsize */ maxsize, 237 /* nsegments */ ~0, 238 /* maxsegsz */ maxsegsz, 239 /* flags */ 0, 240 /* lockfunc */ NULL, 241 /* lockarg */ NULL, 242 &adv->parent_dmat); 243 244 if (error != 0) { 245 device_printf(dev, 246 "Could not allocate DMA tag - error %d\n", error); 247 adv_free(adv); 248 bus_release_resource(dev, SYS_RES_IOPORT, 0, iores); 249 break; 250 } 251 252 adv->init_level += 2; 253 254 if (overrun_buf == NULL) { 255 /* Need to allocate our overrun buffer */ 256 if (bus_dma_tag_create( 257 /* parent */ adv->parent_dmat, 258 /* alignment */ 8, 259 /* boundary */ 0, 260 /* lowaddr */ ADV_ISA_MAX_DMA_ADDR, 261 /* highaddr */ BUS_SPACE_MAXADDR, 262 /* filter */ NULL, 263 /* filterarg */ NULL, 264 /* maxsize */ ADV_OVERRUN_BSIZE, 265 /* nsegments */ 1, 266 /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 267 /* flags */ 0, 268 /* lockfunc */ NULL, 269 /* lockarg */ NULL, 270 &overrun_dmat) != 0) { 271 adv_free(adv); 272 bus_release_resource(dev, SYS_RES_IOPORT, 0, 273 iores); 274 break; 275 } 276 if (bus_dmamem_alloc(overrun_dmat, 277 (void **)&overrun_buf, 278 BUS_DMA_NOWAIT, 279 &overrun_dmamap) != 0) { 280 bus_dma_tag_destroy(overrun_dmat); 281 adv_free(adv); 282 bus_release_resource(dev, SYS_RES_IOPORT, 0, 283 iores); 284 break; 285 } 286 /* And permanently map it in */ 287 bus_dmamap_load(overrun_dmat, overrun_dmamap, 288 overrun_buf, ADV_OVERRUN_BSIZE, 289 adv_map, &overrun_physbase, 290 /*flags*/0); 291 } 292 293 adv->overrun_physbase = overrun_physbase; 294 295 if (adv_init(adv) != 0) { 296 bus_dmamap_unload(overrun_dmat, overrun_dmamap); 297 bus_dmamem_free(overrun_dmat, overrun_buf, 298 overrun_dmamap); 299 bus_dma_tag_destroy(overrun_dmat); 300 adv_free(adv); 301 bus_release_resource(dev, SYS_RES_IOPORT, 0, iores); 302 break; 303 } 304 305 switch (adv->type) { 306 case ADV_ISAPNP: 307 if (adv->chip_version == ADV_CHIP_VER_ASYN_BUG) { 308 adv->bug_fix_control 309 |= ADV_BUG_FIX_ASYN_USE_SYN; 310 adv->fix_asyn_xfer = ~0; 311 } 312 /* Fall Through */ 313 case ADV_ISA: 314 adv->max_dma_count = ADV_ISA_MAX_DMA_COUNT; 315 adv->max_dma_addr = ADV_ISA_MAX_DMA_ADDR; 316 adv_set_isa_dma_settings(adv); 317 break; 318 319 case ADV_VL: 320 adv->max_dma_count = ADV_VL_MAX_DMA_COUNT; 321 adv->max_dma_addr = ADV_VL_MAX_DMA_ADDR; 322 break; 323 default: 324 panic("advisaprobe: Invalid card type\n"); 325 } 326 327 /* Determine our IRQ */ 328 if (bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL)) 329 bus_set_resource(dev, SYS_RES_IRQ, 0, 330 adv_get_chip_irq(adv), 1); 331 else 332 adv_set_chip_irq(adv, irq); 333 334 irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 335 RF_ACTIVE); 336 if (irqres == NULL || 337 bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY| 338 INTR_MPSAFE, NULL, adv_intr, adv, &ih) != 0) { 339 if (irqres != NULL) 340 bus_release_resource(dev, SYS_RES_IRQ, rid, 341 irqres); 342 bus_dmamap_unload(overrun_dmat, overrun_dmamap); 343 bus_dmamem_free(overrun_dmat, overrun_buf, 344 overrun_dmamap); 345 bus_dma_tag_destroy(overrun_dmat); 346 adv_free(adv); 347 bus_release_resource(dev, SYS_RES_IOPORT, 0, iores); 348 break; 349 } 350 351 /* Mark as probed */ 352 adv_isa_ioports[port_index] = 0; 353 return 0; 354 } 355 356 if (user_iobase) 357 bus_set_resource(dev, SYS_RES_IOPORT, 0, iobase, iocount); 358 else 359 bus_delete_resource(dev, SYS_RES_IOPORT, 0); 360 361 return ENXIO; 362} 363 364static int 365adv_isa_attach(device_t dev) 366{ 367 struct adv_softc *adv = device_get_softc(dev); 368 369 return (adv_attach(adv)); 370} 371 372static int 373adv_get_isa_dma_channel(struct adv_softc *adv) 374{ 375 int channel; 376 377 channel = ADV_INW(adv, ADV_CONFIG_LSW) & ADV_CFG_LSW_ISA_DMA_CHANNEL; 378 if (channel == 0x03) 379 return (0); 380 else if (channel == 0x00) 381 return (7); 382 return (channel + 4); 383} 384 385static int 386adv_set_isa_dma_settings(struct adv_softc *adv) 387{ 388 u_int16_t cfg_lsw; 389 u_int8_t value; 390 391 if ((adv->isa_dma_channel >= 5) && (adv->isa_dma_channel <= 7)) { 392 if (adv->isa_dma_channel == 7) 393 value = 0x00; 394 else 395 value = adv->isa_dma_channel - 4; 396 cfg_lsw = ADV_INW(adv, ADV_CONFIG_LSW) 397 & ~ADV_CFG_LSW_ISA_DMA_CHANNEL; 398 cfg_lsw |= value; 399 ADV_OUTW(adv, ADV_CONFIG_LSW, cfg_lsw); 400 401 adv->isa_dma_speed &= 0x07; 402 adv_set_bank(adv, 1); 403 ADV_OUTB(adv, ADV_DMA_SPEED, adv->isa_dma_speed); 404 adv_set_bank(adv, 0); 405 isa_dmacascade(adv->isa_dma_channel); 406 } 407 return (0); 408} 409 410static void 411adv_set_isapnp_wait_for_key(void) 412{ 413 static int isapnp_wait_set = 0; 414 if (isapnp_wait_set == 0) { 415 outb(ADV_ISA_PNP_PORT_ADDR, 0x02); 416 outb(ADV_ISA_PNP_PORT_WRITE, 0x02); 417 isapnp_wait_set++; 418 } 419} 420 421static device_method_t adv_isa_methods[] = { 422 /* Device interface */ 423 DEVMETHOD(device_probe, adv_isa_probe), 424 DEVMETHOD(device_attach, adv_isa_attach), 425 { 0, 0 } 426}; 427 428static driver_t adv_isa_driver = { 429 "adv", adv_isa_methods, sizeof(struct adv_softc) 430}; 431 432static devclass_t adv_isa_devclass; 433DRIVER_MODULE(adv, isa, adv_isa_driver, adv_isa_devclass, 0, 0); 434MODULE_DEPEND(adv, isa, 1, 1, 1); 435