1 /* $OpenBSD: ahc_isa.c,v 1.18 2009/03/29 21:53:52 sthen Exp $ */ 2 /* $NetBSD: ahc_isa.c,v 1.5 1996/10/21 22:27:39 thorpej Exp $ */ 3 4 /* 5 * Product specific probe and attach routines for: 6 * 284X VLbus SCSI controllers 7 * 8 * Copyright (c) 1996 Jason R. Thorpe. 9 * All rights reserved. 10 * 11 * Copyright (c) 1995, 1996 Christopher G. Demetriou. 12 * All rights reserved. 13 * 14 * Copyright (c) 1994, 1995, 1996 Justin T. Gibbs. 15 * All rights reserved. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions 19 * are met: 20 * 1. Redistributions of source code must retain the above copyright 21 * notice immediately at the beginning of the file, without modification, 22 * this list of conditions, and the following disclaimer. 23 * 2. Redistributions in binary form must reproduce the above copyright 24 * notice, this list of conditions and the following disclaimer in the 25 * documentation and/or other materials provided with the distribution. 26 * 3. All advertising materials mentioning features or use of this software 27 * must display the following acknowledgement: 28 * This product includes software developed by Christopher G. Demetriou 29 * for the NetBSD Project. 30 * 4. The name of the author may not be used to endorse or promote products 31 * derived from this software without specific prior written permission. 32 * 33 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 34 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 35 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 36 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 37 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 38 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 39 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 40 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 41 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 42 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 43 * SUCH DAMAGE. 44 */ 45 46 /* 47 * This front-end driver is really sort of a hack. The AHA-284X likes 48 * to masquerade as an EISA device. However, on VLbus machines with 49 * no EISA signature in the BIOS, the EISA bus will never be scanned. 50 * This is intended to catch the 284X controllers on those systems 51 * by looking in "EISA i/o space" for 284X controllers. 52 * 53 * This relies heavily on i/o port accounting. We also just use the 54 * EISA macros for everything ... it's a real waste to redefine them. 55 * 56 * Note: there isn't any #ifdef for FreeBSD in this file, since the 57 * FreeBSD EISA driver handles all cases of the 284X. 58 * 59 * -- Jason R. Thorpe <thorpej@NetBSD.ORG> 60 * July 12, 1996 61 * 62 * TODO: some code could be shared with ahc_eisa.c, but it would probably 63 * be a logistical mightmare to even try. 64 */ 65 66 #include <sys/param.h> 67 #include <sys/systm.h> 68 #include <sys/kernel.h> 69 #include <sys/device.h> 70 #include <sys/queue.h> 71 #include <sys/malloc.h> 72 73 #include <machine/bus.h> 74 #include <machine/intr.h> 75 76 #include <scsi/scsi_all.h> 77 #include <scsi/scsiconf.h> 78 79 #include <dev/isa/isavar.h> 80 81 #include <dev/eisa/eisareg.h> 82 #include <dev/eisa/eisavar.h> 83 #include <dev/eisa/eisadevs.h> 84 85 #include <dev/ic/aic7xxx_openbsd.h> 86 #include <dev/ic/aic7xxx_inline.h> 87 #include <dev/ic/smc93cx6var.h> 88 89 #ifdef DEBUG 90 #define bootverbose 1 91 #else 92 #define bootverbose 0 93 #endif 94 95 /* IO port address setting range as EISA slot number */ 96 #define AHC_ISA_MIN_SLOT 0x1 /* from iobase = 0x1c00 */ 97 #define AHC_ISA_MAX_SLOT 0xe /* to iobase = 0xec00 */ 98 99 #define AHC_ISA_SLOT_OFFSET 0xc00 /* offset from EISA IO space */ 100 #define AHC_ISA_IOSIZE 0x100 101 102 /* 103 * I/O port offsets 104 */ 105 #define AHC_ISA_VID (EISA_SLOTOFF_VID - AHC_ISA_SLOT_OFFSET) 106 #define AHC_ISA_PID (EISA_SLOTOFF_PID - AHC_ISA_SLOT_OFFSET) 107 #define AHC_ISA_PRIMING AHC_ISA_VID /* enable vendor/product ID */ 108 109 /* 110 * AHC_ISA_PRIMING register values (write) 111 */ 112 #define AHC_ISA_PRIMING_VID(index) (AHC_ISA_VID + (index)) 113 #define AHC_ISA_PRIMING_PID(index) (AHC_ISA_PID + (index)) 114 115 int ahc_isa_irq(bus_space_tag_t, bus_space_handle_t); 116 int ahc_isa_idstring(bus_space_tag_t, bus_space_handle_t, char *); 117 int ahc_isa_match(struct isa_attach_args *, bus_addr_t); 118 119 int ahc_isa_probe(struct device *, void *, void *); 120 void ahc_isa_attach(struct device *, struct device *, void *); 121 void aha2840_load_seeprom(struct ahc_softc *ahc); 122 123 struct cfattach ahc_isa_ca = { 124 sizeof(struct ahc_softc), ahc_isa_probe, ahc_isa_attach 125 }; 126 127 /* 128 * This keeps track of which slots are to be checked next if the 129 * iobase locator is a wildcard. A simple static variable isn't enough, 130 * since it's conceivable that a system might have more than one ISA 131 * bus. 132 * 133 * The "bus" member is the unit number of the parent ISA bus, e.g. "0" 134 * for "isa0". 135 */ 136 struct ahc_isa_slot { 137 LIST_ENTRY(ahc_isa_slot) link; 138 int bus; 139 int slot; 140 }; 141 static LIST_HEAD(, ahc_isa_slot) ahc_isa_all_slots; 142 static int ahc_isa_slot_initialized; 143 144 /* 145 * Return irq setting of the board, otherwise -1. 146 */ 147 int 148 ahc_isa_irq(bus_space_tag_t iot, bus_space_handle_t ioh) 149 { 150 int irq; 151 u_char intdef; 152 u_char hcntrl; 153 154 /* Pause the card preseving the IRQ type */ 155 hcntrl = bus_space_read_1(iot, ioh, HCNTRL) & IRQMS; 156 bus_space_write_1(iot, ioh, HCNTRL, hcntrl | PAUSE); 157 158 intdef = bus_space_read_1(iot, ioh, INTDEF); 159 switch (irq = (intdef & VECTOR)) { 160 case 9: 161 case 10: 162 case 11: 163 case 12: 164 case 14: 165 case 15: 166 break; 167 default: 168 printf("ahc_isa_irq: illegal irq setting %d\n", intdef); 169 return -1; 170 } 171 172 /* Note that we are going and return (to probe) */ 173 return irq; 174 } 175 176 int 177 ahc_isa_idstring(bus_space_tag_t iot, bus_space_handle_t ioh, char *idstring) 178 { 179 u_int8_t vid[EISA_NVIDREGS], pid[EISA_NPIDREGS]; 180 int i; 181 182 /* Get the vendor ID bytes */ 183 for (i = 0; i < EISA_NVIDREGS; i++) { 184 bus_space_write_1(iot, ioh, AHC_ISA_PRIMING, 185 AHC_ISA_PRIMING_VID(i)); 186 vid[i] = bus_space_read_1(iot, ioh, AHC_ISA_VID + i); 187 } 188 189 /* Check for device existence */ 190 if (EISA_VENDID_NODEV(vid)) { 191 #if 0 192 printf("ahc_isa_idstring: no device at 0x%lx\n", 193 ioh); /* XXX knows about ioh guts */ 194 printf("\t(0x%x, 0x%x)\n", vid[0], vid[1]); 195 #endif 196 return (0); 197 } 198 199 /* And check that the firmware didn't biff something badly */ 200 if (EISA_VENDID_IDDELAY(vid)) { 201 printf("ahc_isa_idstring: BIOS biffed it at 0x%lx\n", 202 ioh); /* XXX knows about ioh guts */ 203 return (0); 204 } 205 206 /* Get the product ID bytes */ 207 for (i = 0; i < EISA_NPIDREGS; i++) { 208 bus_space_write_1(iot, ioh, AHC_ISA_PRIMING, 209 AHC_ISA_PRIMING_PID(i)); 210 pid[i] = bus_space_read_1(iot, ioh, AHC_ISA_PID + i); 211 } 212 213 /* Create the ID string from the vendor and product IDs */ 214 idstring[0] = EISA_VENDID_0(vid); 215 idstring[1] = EISA_VENDID_1(vid); 216 idstring[2] = EISA_VENDID_2(vid); 217 idstring[3] = EISA_PRODID_0(pid); 218 idstring[4] = EISA_PRODID_1(pid); 219 idstring[5] = EISA_PRODID_2(pid); 220 idstring[6] = EISA_PRODID_3(pid); 221 idstring[7] = '\0'; /* sanity */ 222 223 return (1); 224 } 225 226 int 227 ahc_isa_match(struct isa_attach_args *ia, bus_addr_t iobase) 228 { 229 bus_space_tag_t iot = ia->ia_iot; 230 bus_space_handle_t ioh; 231 int irq; 232 char idstring[EISA_IDSTRINGLEN]; 233 234 /* 235 * Get a mapping for the while slot-specific address 236 * space. If we can't, assume nothing's there, but 237 * warn about it. 238 */ 239 if (bus_space_map(iot, iobase, AHC_ISA_IOSIZE, 0, &ioh)) { 240 #if 0 241 /* 242 * Don't print anything out here, since this could 243 * be common on machines configured to look for 244 * ahc_eisa and ahc_isa. 245 */ 246 printf("ahc_isa_match: can't map i/o space for 0x%x\n", 247 iobase); 248 #endif 249 return (0); 250 } 251 252 if (!ahc_isa_idstring(iot, ioh, idstring)) 253 irq = -1; /* cannot get the ID string */ 254 else if (strcmp(idstring, "ADP7756") && 255 strcmp(idstring, "ADP7757")) 256 irq = -1; /* unknown ID strings */ 257 else 258 irq = ahc_isa_irq(iot, ioh); 259 260 bus_space_unmap(iot, ioh, AHC_ISA_IOSIZE); 261 262 if (irq < 0) 263 return (0); 264 265 if (ia->ia_irq != IRQUNK && 266 ia->ia_irq != irq) { 267 printf("ahc_isa_match: irq mismatch (kernel %d, card %d)\n", 268 ia->ia_irq, irq); 269 return (0); 270 } 271 272 /* We have a match */ 273 ia->ia_iobase = iobase; 274 ia->ia_irq = irq; 275 ia->ia_iosize = AHC_ISA_IOSIZE; 276 ia->ia_msize = 0; 277 return (1); 278 } 279 280 /* 281 * Check the slots looking for a board we recognise 282 * If we find one, note its address (slot) and call 283 * the actual probe routine to check it out. 284 */ 285 int 286 ahc_isa_probe(struct device *parent, void *match, void *aux) 287 { 288 struct isa_attach_args *ia = aux; 289 struct ahc_isa_slot *as; 290 291 if (ahc_isa_slot_initialized == 0) { 292 LIST_INIT(&ahc_isa_all_slots); 293 ahc_isa_slot_initialized = 1; 294 } 295 296 if (ia->ia_iobase != IOBASEUNK) 297 return (ahc_isa_match(ia, ia->ia_iobase)); 298 299 /* 300 * Find this bus's state. If we don't yet have a slot 301 * marker, allocate and initialize one. 302 */ 303 LIST_FOREACH(as, &ahc_isa_all_slots, link) 304 if (as->bus == parent->dv_unit) 305 goto found_slot_marker; 306 307 /* 308 * Don't have one, so make one. 309 */ 310 as = (struct ahc_isa_slot *) 311 malloc(sizeof(struct ahc_isa_slot), M_DEVBUF, M_NOWAIT); 312 if (as == NULL) 313 panic("ahc_isa_probe: can't allocate slot marker"); 314 315 as->bus = parent->dv_unit; 316 as->slot = AHC_ISA_MIN_SLOT; 317 LIST_INSERT_HEAD(&ahc_isa_all_slots, as, link); 318 319 found_slot_marker: 320 321 for (; as->slot <= AHC_ISA_MAX_SLOT; as->slot++) { 322 if (ahc_isa_match(ia, EISA_SLOT_ADDR(as->slot) + 323 AHC_ISA_SLOT_OFFSET)) { 324 as->slot++; /* next slot to search */ 325 return (1); 326 } 327 } 328 329 /* No matching cards were found. */ 330 return (0); 331 } 332 333 void 334 ahc_isa_attach(struct device *parent, struct device *self, void *aux) 335 { 336 struct ahc_softc *ahc = (void *)self; 337 struct isa_attach_args *ia = aux; 338 bus_space_tag_t iot = ia->ia_iot; 339 bus_space_handle_t ioh; 340 int irq; 341 char idstring[EISA_IDSTRINGLEN]; 342 const char *model; 343 u_int intdef; 344 345 ahc_set_name(ahc, ahc->sc_dev.dv_xname); 346 ahc_set_unit(ahc, ahc->sc_dev.dv_unit); 347 348 /* set dma tags */ 349 ahc->parent_dmat = ia->ia_dmat; 350 351 ahc->chip = AHC_VL; /* We are a VL Bus Controller */ 352 353 if (bus_space_map(iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh)) 354 panic("ahc_isa_attach: can't map slot i/o addresses"); 355 if (!ahc_isa_idstring(iot, ioh, idstring)) 356 panic("ahc_isa_attach: could not read ID string"); 357 if ((irq = ahc_isa_irq(iot, ioh)) < 0) 358 panic("ahc_isa_attach: ahc_isa_irq failed!"); 359 360 if (strcmp(idstring, "ADP7756") == 0) { 361 model = EISA_PRODUCT_ADP7756; 362 } else if (strcmp(idstring, "ADP7757") == 0) { 363 model = EISA_PRODUCT_ADP7757; 364 } else { 365 panic("ahc_isa_attach: Unknown device type %s", idstring); 366 } 367 printf(": %s\n", model); 368 369 ahc->channel = 'A'; 370 ahc->chip = AHC_AIC7770; 371 ahc->features = AHC_AIC7770_FE; 372 ahc->bugs |= AHC_TMODE_WIDEODD_BUG; 373 ahc->flags |= AHC_PAGESCBS; 374 375 /* set tag and handle */ 376 ahc->tag = iot; 377 ahc->bsh = ioh; 378 379 #ifdef DEBUG 380 /* 381 * Tell the user what type of interrupts we're using. 382 * useful for debugging irq problems 383 */ 384 printf( "%s: Using %s Interrupts\n", ahc_name(ahc), 385 ahc->pause & IRQMS ? "Level Sensitive" : "Edge Triggered"); 386 #endif 387 388 if (ahc_reset(ahc, /*reinit*/FALSE) != 0) 389 return; 390 391 /* See if we are edge triggered */ 392 intdef = ahc_inb(ahc, INTDEF); 393 if ((intdef & EDGE_TRIG) != 0) 394 ahc->flags |= AHC_EDGE_INTERRUPT; 395 396 /* 397 * Now that we know we own the resources we need, do the 398 * card initialization. 399 */ 400 aha2840_load_seeprom(ahc); 401 402 /* 403 * See if we have a Rev E or higher aic7770. Anything below a 404 * Rev E will have a R/O autoflush disable configuration bit. 405 * It's still not clear exactly what is differenent about the Rev E. 406 * We think it allows 8 bit entries in the QOUTFIFO to support 407 * "paging" SCBs so you can have more than 4 commands active at 408 * once. 409 */ 410 { 411 char *id_string; 412 u_char sblkctl; 413 u_char sblkctl_orig; 414 415 sblkctl_orig = ahc_inb(ahc, SBLKCTL); 416 sblkctl = sblkctl_orig ^ AUTOFLUSHDIS; 417 ahc_outb(ahc, SBLKCTL, sblkctl); 418 sblkctl = ahc_inb(ahc, SBLKCTL); 419 if(sblkctl != sblkctl_orig) 420 { 421 id_string = "aic7770 >= Rev E, "; 422 /* 423 * Ensure autoflush is enabled 424 */ 425 sblkctl &= ~AUTOFLUSHDIS; 426 ahc_outb(ahc, SBLKCTL, sblkctl); 427 428 /* Allow paging on this adapter */ 429 ahc->flags |= AHC_PAGESCBS; 430 } 431 else 432 id_string = "aic7770 <= Rev C, "; 433 434 printf("%s: %s", ahc_name(ahc), id_string); 435 } 436 437 /* Setup the FIFO threshold and the bus off time */ 438 { 439 u_char hostconf = ahc_inb(ahc, HOSTCONF); 440 ahc_outb(ahc, BUSSPD, hostconf & DFTHRSH); 441 ahc_outb(ahc, BUSTIME, (hostconf << 2) & BOFF); 442 } 443 444 /* 445 * Generic aic7xxx initialization. 446 */ 447 if(ahc_init(ahc)){ 448 ahc_free(ahc); 449 return; 450 } 451 452 /* 453 * Link this softc in with all other ahc instances. 454 */ 455 ahc_softc_insert(ahc); 456 457 /* 458 * Enable the board's BUS drivers 459 */ 460 ahc_outb(ahc, BCTL, ENABLE); 461 462 /* 463 * The IRQMS bit enables level sensitive interrupts only allow 464 * IRQ sharing if its set. 465 */ 466 ahc->ih = isa_intr_establish(ia->ia_ic, irq, 467 ahc->pause & IRQMS ? IST_LEVEL : IST_EDGE, IPL_BIO, ahc_platform_intr, 468 ahc, ahc->sc_dev.dv_xname); 469 if (ahc->ih == NULL) { 470 printf("%s: couldn't establish interrupt\n", 471 ahc->sc_dev.dv_xname); 472 ahc_free(ahc); 473 return; 474 } 475 476 ahc_intr_enable(ahc, TRUE); 477 478 /* Attach sub-devices - always succeeds */ 479 ahc_attach(ahc); 480 } 481 482 /* 483 * Read the 284x SEEPROM. 484 */ 485 void 486 aha2840_load_seeprom(struct ahc_softc *ahc) 487 { 488 struct seeprom_descriptor sd; 489 struct seeprom_config sc; 490 u_int16_t checksum = 0; 491 u_int8_t scsi_conf; 492 int have_seeprom; 493 494 sd.sd_tag = ahc->tag; 495 sd.sd_bsh = ahc->bsh; 496 sd.sd_regsize = 1; 497 sd.sd_control_offset = SEECTL_2840; 498 sd.sd_status_offset = STATUS_2840; 499 sd.sd_dataout_offset = STATUS_2840; 500 sd.sd_chip = C46; 501 sd.sd_MS = 0; 502 sd.sd_RDY = EEPROM_TF; 503 sd.sd_CS = CS_2840; 504 sd.sd_CK = CK_2840; 505 sd.sd_DO = DO_2840; 506 sd.sd_DI = DI_2840; 507 508 if (bootverbose) 509 printf("%s: Reading SEEPROM...", ahc_name(ahc)); 510 have_seeprom = read_seeprom(&sd, 511 (u_int16_t *)&sc, 512 /*start_addr*/0, 513 sizeof(sc)/2); 514 515 if (have_seeprom) { 516 /* Check checksum */ 517 int i; 518 int maxaddr = (sizeof(sc)/2) - 1; 519 u_int16_t *scarray = (u_int16_t *)≻ 520 521 for (i = 0; i < maxaddr; i++) 522 checksum = checksum + scarray[i]; 523 if (checksum != sc.checksum) { 524 if(bootverbose) 525 printf ("checksum error\n"); 526 have_seeprom = 0; 527 } else if (bootverbose) { 528 printf("done.\n"); 529 } 530 } 531 532 if (!have_seeprom) { 533 if (bootverbose) 534 printf("%s: No SEEPROM available\n", ahc_name(ahc)); 535 ahc->flags |= AHC_USEDEFAULTS; 536 } else { 537 /* 538 * Put the data we've collected down into SRAM 539 * where ahc_init will find it. 540 */ 541 int i; 542 int max_targ = (ahc->features & AHC_WIDE) != 0 ? 16 : 8; 543 u_int16_t discenable; 544 545 discenable = 0; 546 for (i = 0; i < max_targ; i++){ 547 u_int8_t target_settings; 548 target_settings = (sc.device_flags[i] & CFXFER) << 4; 549 if (sc.device_flags[i] & CFSYNCH) 550 target_settings |= SOFS; 551 if (sc.device_flags[i] & CFWIDEB) 552 target_settings |= WIDEXFER; 553 if (sc.device_flags[i] & CFDISC) 554 discenable |= (0x01 << i); 555 ahc_outb(ahc, TARG_SCSIRATE + i, target_settings); 556 } 557 ahc_outb(ahc, DISC_DSB, ~(discenable & 0xff)); 558 ahc_outb(ahc, DISC_DSB + 1, ~((discenable >> 8) & 0xff)); 559 560 ahc->our_id = sc.brtime_id & CFSCSIID; 561 562 scsi_conf = (ahc->our_id & 0x7); 563 if (sc.adapter_control & CFSPARITY) 564 scsi_conf |= ENSPCHK; 565 if (sc.adapter_control & CFRESETB) 566 scsi_conf |= RESET_SCSI; 567 568 if (sc.bios_control & CF284XEXTEND) 569 ahc->flags |= AHC_EXTENDED_TRANS_A; 570 /* Set SCSICONF info */ 571 ahc_outb(ahc, SCSICONF, scsi_conf); 572 573 if (sc.adapter_control & CF284XSTERM) 574 ahc->flags |= AHC_TERM_ENB_A; 575 } 576 } 577