1 /* $NetBSD: ahc_isa.c,v 1.5 1996/10/21 22:27:39 thorpej Exp $ */ 2 3 /* 4 * Product specific probe and attach routines for: 5 * 284X VLbus SCSI controllers 6 * 7 * Copyright (c) 1996 Jason R. Thorpe. 8 * All rights reserved. 9 * 10 * Copyright (c) 1995, 1996 Christopher G. Demetriou. 11 * All rights reserved. 12 * 13 * Copyright (c) 1994, 1995, 1996 Justin T. Gibbs. 14 * All rights reserved. 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 1. Redistributions of source code must retain the above copyright 20 * notice immediately at the beginning of the file, without modification, 21 * this list of conditions, and the following disclaimer. 22 * 2. Redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution. 25 * 3. All advertising materials mentioning features or use of this software 26 * must display the following acknowledgement: 27 * This product includes software developed by Christopher G. Demetriou 28 * for the NetBSD Project. 29 * 4. The name of the author may not be used to endorse or promote products 30 * derived from this software without specific prior written permission. 31 * 32 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 36 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 42 * SUCH DAMAGE. 43 */ 44 45 /* 46 * This front-end driver is really sort of a hack. The AHA-284X likes 47 * to masquerade as an EISA device. However, on VLbus machines with 48 * no EISA signature in the BIOS, the EISA bus will never be scanned. 49 * This is intended to catch the 284X controllers on those systems 50 * by looking in "EISA i/o space" for 284X controllers. 51 * 52 * This relies heavily on i/o port accounting. We also just use the 53 * EISA macros for everything ... it's a real waste to redefine them. 54 * 55 * Note: there isn't any #ifdef for FreeBSD in this file, since the 56 * FreeBSD EISA driver handles all cases of the 284X. 57 * 58 * -- Jason R. Thorpe <thorpej@NetBSD.ORG> 59 * July 12, 1996 60 * 61 * TODO: some code could be shared with ahc_eisa.c, but it would probably 62 * be a logistical mightmare to even try. 63 */ 64 65 #include <sys/param.h> 66 #include <sys/systm.h> 67 #include <sys/kernel.h> 68 #include <sys/device.h> 69 #include <sys/queue.h> 70 #include <sys/malloc.h> 71 72 #include <machine/bus.h> 73 #include <machine/intr.h> 74 75 #include <scsi/scsi_all.h> 76 #include <scsi/scsiconf.h> 77 78 #include <dev/isa/isavar.h> 79 80 #include <dev/eisa/eisareg.h> 81 #include <dev/eisa/eisavar.h> 82 #include <dev/eisa/eisadevs.h> 83 84 #include <dev/ic/aic7xxxreg.h> 85 #include <dev/ic/aic7xxxvar.h> 86 87 /* IO port address setting range as EISA slot number */ 88 #define AHC_ISA_MIN_SLOT 0x1 /* from iobase = 0x1c00 */ 89 #define AHC_ISA_MAX_SLOT 0xe /* to iobase = 0xec00 */ 90 91 #define AHC_ISA_SLOT_OFFSET 0xc00 /* offset from EISA IO space */ 92 #define AHC_ISA_IOSIZE 0x100 93 94 /* 95 * I/O port offsets 96 */ 97 #define INTDEF 0x5cul /* Interrupt Definition Register */ 98 #define AHC_ISA_VID (EISA_SLOTOFF_VID - AHC_ISA_SLOT_OFFSET) 99 #define AHC_ISA_PID (EISA_SLOTOFF_PID - AHC_ISA_SLOT_OFFSET) 100 #define AHC_ISA_PRIMING AHC_ISA_VID /* enable vendor/product ID */ 101 102 /* 103 * AHC_ISA_PRIMING register values (write) 104 */ 105 #define AHC_ISA_PRIMING_VID(index) (AHC_ISA_VID + (index)) 106 #define AHC_ISA_PRIMING_PID(index) (AHC_ISA_PID + (index)) 107 108 int ahc_isa_irq __P((bus_space_tag_t, bus_space_handle_t)); 109 int ahc_isa_idstring __P((bus_space_tag_t, bus_space_handle_t, char *)); 110 int ahc_isa_match __P((struct isa_attach_args *, bus_addr_t)); 111 112 int ahc_isa_probe __P((struct device *, void *, void *)); 113 void ahc_isa_attach __P((struct device *, struct device *, void *)); 114 115 struct cfattach ahc_isa_ca = { 116 sizeof(struct ahc_data), ahc_isa_probe, ahc_isa_attach 117 }; 118 119 /* 120 * This keeps track of which slots are to be checked next if the 121 * iobase locator is a wildcard. A simple static variable isn't enough, 122 * since it's conceivable that a system might have more than one ISA 123 * bus. 124 * 125 * The "bus" member is the unit number of the parent ISA bus, e.g. "0" 126 * for "isa0". 127 */ 128 struct ahc_isa_slot { 129 LIST_ENTRY(ahc_isa_slot) link; 130 int bus; 131 int slot; 132 }; 133 static LIST_HEAD(, ahc_isa_slot) ahc_isa_all_slots; 134 static int ahc_isa_slot_initialized; 135 136 /* 137 * Return irq setting of the board, otherwise -1. 138 */ 139 int 140 ahc_isa_irq(iot, ioh) 141 bus_space_tag_t iot; 142 bus_space_handle_t ioh; 143 { 144 int irq; 145 u_char intdef; 146 147 ahc_reset("ahc_isa", iot, ioh); 148 intdef = bus_space_read_1(iot, ioh, INTDEF); 149 switch (irq = (intdef & 0xf)) { 150 case 9: 151 case 10: 152 case 11: 153 case 12: 154 case 14: 155 case 15: 156 break; 157 default: 158 printf("ahc_isa_irq: illegal irq setting %d\n", intdef); 159 return -1; 160 } 161 162 /* Note that we are going and return (to probe) */ 163 return irq; 164 } 165 166 int 167 ahc_isa_idstring(iot, ioh, idstring) 168 bus_space_tag_t iot; 169 bus_space_handle_t ioh; 170 char *idstring; 171 { 172 u_int8_t vid[EISA_NVIDREGS], pid[EISA_NPIDREGS]; 173 int i; 174 175 /* Get the vendor ID bytes */ 176 for (i = 0; i < EISA_NVIDREGS; i++) { 177 bus_space_write_1(iot, ioh, AHC_ISA_PRIMING, 178 AHC_ISA_PRIMING_VID(i)); 179 vid[i] = bus_space_read_1(iot, ioh, AHC_ISA_VID + i); 180 } 181 182 /* Check for device existence */ 183 if (EISA_VENDID_NODEV(vid)) { 184 #if 0 185 printf("ahc_isa_idstring: no device at 0x%lx\n", 186 ioh); /* XXX knows about ioh guts */ 187 printf("\t(0x%x, 0x%x)\n", vid[0], vid[1]); 188 #endif 189 return (0); 190 } 191 192 /* And check that the firmware didn't biff something badly */ 193 if (EISA_VENDID_IDDELAY(vid)) { 194 printf("ahc_isa_idstring: BIOS biffed it at 0x%lx\n", 195 ioh); /* XXX knows about ioh guts */ 196 return (0); 197 } 198 199 /* Get the product ID bytes */ 200 for (i = 0; i < EISA_NPIDREGS; i++) { 201 bus_space_write_1(iot, ioh, AHC_ISA_PRIMING, 202 AHC_ISA_PRIMING_PID(i)); 203 pid[i] = bus_space_read_1(iot, ioh, AHC_ISA_PID + i); 204 } 205 206 /* Create the ID string from the vendor and product IDs */ 207 idstring[0] = EISA_VENDID_0(vid); 208 idstring[1] = EISA_VENDID_1(vid); 209 idstring[2] = EISA_VENDID_2(vid); 210 idstring[3] = EISA_PRODID_0(pid); 211 idstring[4] = EISA_PRODID_1(pid); 212 idstring[5] = EISA_PRODID_2(pid); 213 idstring[6] = EISA_PRODID_3(pid); 214 idstring[7] = '\0'; /* sanity */ 215 216 return (1); 217 } 218 219 int 220 ahc_isa_match(ia, iobase) 221 struct isa_attach_args *ia; 222 bus_addr_t iobase; 223 { 224 bus_space_tag_t iot = ia->ia_iot; 225 bus_space_handle_t ioh; 226 int irq; 227 char idstring[EISA_IDSTRINGLEN]; 228 229 /* 230 * Get a mapping for the while slot-specific address 231 * space. If we can't, assume nothing's there, but 232 * warn about it. 233 */ 234 if (bus_space_map(iot, iobase, AHC_ISA_IOSIZE, 0, &ioh)) { 235 #if 0 236 /* 237 * Don't print anything out here, since this could 238 * be common on machines configured to look for 239 * ahc_eisa and ahc_isa. 240 */ 241 printf("ahc_isa_match: can't map I/O space for 0x%x\n", 242 iobase); 243 #endif 244 return (0); 245 } 246 247 if (!ahc_isa_idstring(iot, ioh, idstring)) 248 irq = -1; /* cannot get the ID string */ 249 else if (strcmp(idstring, "ADP7756") && 250 strcmp(idstring, "ADP7757")) 251 irq = -1; /* unknown ID strings */ 252 else 253 irq = ahc_isa_irq(iot, ioh); 254 255 bus_space_unmap(iot, ioh, AHC_ISA_IOSIZE); 256 257 if (irq < 0) 258 return (0); 259 260 if (ia->ia_irq != IRQUNK && 261 ia->ia_irq != irq) { 262 printf("ahc_isa_match: irq mismatch (kernel %d, card %d)\n", 263 ia->ia_irq, irq); 264 return (0); 265 } 266 267 /* We have a match */ 268 ia->ia_iobase = iobase; 269 ia->ia_irq = irq; 270 ia->ia_iosize = AHC_ISA_IOSIZE; 271 ia->ia_msize = 0; 272 return (1); 273 } 274 275 /* 276 * Check the slots looking for a board we recognise 277 * If we find one, note it's address (slot) and call 278 * the actual probe routine to check it out. 279 */ 280 int 281 ahc_isa_probe(parent, match, aux) 282 struct device *parent; 283 void *match, *aux; 284 { 285 struct isa_attach_args *ia = aux; 286 struct ahc_isa_slot *as; 287 288 if (ahc_isa_slot_initialized == 0) { 289 LIST_INIT(&ahc_isa_all_slots); 290 ahc_isa_slot_initialized = 1; 291 } 292 293 if (ia->ia_iobase != IOBASEUNK) 294 return (ahc_isa_match(ia, ia->ia_iobase)); 295 296 /* 297 * Find this bus's state. If we don't yet have a slot 298 * marker, allocate and initialize one. 299 */ 300 for (as = ahc_isa_all_slots.lh_first; as != NULL; 301 as = as->link.le_next) 302 if (as->bus == parent->dv_unit) 303 goto found_slot_marker; 304 305 /* 306 * Don't have one, so make one. 307 */ 308 as = (struct ahc_isa_slot *) 309 malloc(sizeof(struct ahc_isa_slot), M_DEVBUF, M_NOWAIT); 310 if (as == NULL) 311 panic("ahc_isa_probe: can't allocate slot marker"); 312 313 as->bus = parent->dv_unit; 314 as->slot = AHC_ISA_MIN_SLOT; 315 LIST_INSERT_HEAD(&ahc_isa_all_slots, as, link); 316 317 found_slot_marker: 318 319 for (; as->slot <= AHC_ISA_MAX_SLOT; as->slot++) { 320 if (ahc_isa_match(ia, EISA_SLOT_ADDR(as->slot) + 321 AHC_ISA_SLOT_OFFSET)) { 322 as->slot++; /* next slot to search */ 323 return (1); 324 } 325 } 326 327 /* No matching cards were found. */ 328 return (0); 329 } 330 331 void 332 ahc_isa_attach(parent, self, aux) 333 struct device *parent, *self; 334 void *aux; 335 { 336 ahc_type type; 337 struct ahc_data *ahc = (void *)self; 338 struct isa_attach_args *ia = aux; 339 bus_space_tag_t iot = ia->ia_iot; 340 bus_space_handle_t ioh; 341 int irq; 342 char idstring[EISA_IDSTRINGLEN]; 343 const char *model; 344 345 if (bus_space_map(iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh)) 346 panic("ahc_isa_attach: could not map slot I/O addresses"); 347 if (!ahc_isa_idstring(iot, ioh, idstring)) 348 panic("ahc_isa_attach: could not read ID string"); 349 if ((irq = ahc_isa_irq(iot, ioh)) < 0) 350 panic("ahc_isa_attach: ahc_isa_irq failed!"); 351 352 if (strcmp(idstring, "ADP7756") == 0) { 353 model = EISA_PRODUCT_ADP7756; 354 type = AHC_284; 355 } else if (strcmp(idstring, "ADP7757") == 0) { 356 model = EISA_PRODUCT_ADP7757; 357 type = AHC_284; 358 } else { 359 panic("ahc_isa_attach: Unknown device type %s\n", idstring); 360 } 361 printf(": %s\n", model); 362 363 ahc_construct(ahc, iot, ioh, type, AHC_FNONE); 364 365 #ifdef DEBUG 366 /* 367 * Tell the user what type of interrupts we're using. 368 * usefull for debugging irq problems 369 */ 370 printf( "%s: Using %s Interrupts\n", ahc_name(ahc), 371 ahc->pause & IRQMS ? "Level Sensitive" : "Edge Triggered"); 372 #endif 373 374 /* 375 * Now that we know we own the resources we need, do the 376 * card initialization. 377 * 378 * First, the aic7770 card specific setup. 379 */ 380 381 /* XXX 382 * On AHA-284x, 383 * all values are automagically intialized at 384 * POST for these cards, so we can always rely 385 * on the Scratch Ram values. However, we should 386 * read the SEEPROM here (Dan has the code to do 387 * it) so we can say what kind of translation the 388 * BIOS is using. Printing out the geometry could 389 * save a lot of users the grief of failed installs. 390 */ 391 392 /* 393 * See if we have a Rev E or higher aic7770. Anything below a 394 * Rev E will have a R/O autoflush disable configuration bit. 395 * It's still not clear exactly what is differenent about the Rev E. 396 * We think it allows 8 bit entries in the QOUTFIFO to support 397 * "paging" SCBs so you can have more than 4 commands active at 398 * once. 399 */ 400 { 401 char *id_string; 402 u_char sblkctl; 403 u_char sblkctl_orig; 404 405 sblkctl_orig = AHC_INB(ahc, SBLKCTL); 406 sblkctl = sblkctl_orig ^ AUTOFLUSHDIS; 407 AHC_OUTB(ahc, SBLKCTL, sblkctl); 408 sblkctl = AHC_INB(ahc, SBLKCTL); 409 if(sblkctl != sblkctl_orig) 410 { 411 id_string = "aic7770 >= Rev E, "; 412 /* 413 * Ensure autoflush is enabled 414 */ 415 sblkctl &= ~AUTOFLUSHDIS; 416 AHC_OUTB(ahc, SBLKCTL, sblkctl); 417 418 /* Allow paging on this adapter */ 419 ahc->flags |= AHC_PAGESCBS; 420 } 421 else 422 id_string = "aic7770 <= Rev C, "; 423 424 printf("%s: %s", ahc_name(ahc), id_string); 425 } 426 427 /* Setup the FIFO threshold and the bus off time */ 428 { 429 u_char hostconf = AHC_INB(ahc, HOSTCONF); 430 AHC_OUTB(ahc, BUSSPD, hostconf & DFTHRSH); 431 AHC_OUTB(ahc, BUSTIME, (hostconf << 2) & BOFF); 432 } 433 434 /* 435 * Generic aic7xxx initialization. 436 */ 437 if(ahc_init(ahc)){ 438 ahc_free(ahc); 439 return; 440 } 441 442 /* 443 * Enable the board's BUS drivers 444 */ 445 AHC_OUTB(ahc, BCTL, ENABLE); 446 447 /* 448 * The IRQMS bit enables level sensitive interrupts only allow 449 * IRQ sharing if its set. 450 */ 451 ahc->sc_ih = isa_intr_establish(ia->ia_ic, irq, 452 ahc->pause & IRQMS ? IST_LEVEL : IST_EDGE, IPL_BIO, ahc_intr, ahc); 453 if (ahc->sc_ih == NULL) { 454 printf("%s: couldn't establish interrupt\n", 455 ahc->sc_dev.dv_xname); 456 ahc_free(ahc); 457 return; 458 } 459 460 /* Attach sub-devices - always succeeds */ 461 ahc_attach(ahc); 462 } 463