1 /* $NetBSD: ahc_pci.c,v 1.9 1996/10/21 22:56:24 thorpej Exp $ */ 2 3 /* 4 * Product specific probe and attach routines for: 5 * 3940, 2940, aic7880, aic7870, aic7860 and aic7850 SCSI controllers 6 * 7 * Copyright (c) 1995, 1996 Justin T. Gibbs. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice immediately at the beginning of the file, without modification, 15 * this list of conditions, and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 26 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * from Id: aic7870.c,v 1.37 1996/06/08 06:55:55 gibbs Exp 35 */ 36 37 #if defined(__FreeBSD__) 38 #include <pci.h> 39 #endif 40 #if NPCI > 0 || defined(__NetBSD__) 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/malloc.h> 44 #include <sys/kernel.h> 45 #include <sys/queue.h> 46 #if defined(__NetBSD__) 47 #include <sys/device.h> 48 #include <machine/bus.h> 49 #include <machine/intr.h> 50 #endif /* defined(__NetBSD__) */ 51 52 #include <scsi/scsi_all.h> 53 #include <scsi/scsiconf.h> 54 55 #if defined(__FreeBSD__) 56 57 #include <pci/pcireg.h> 58 #include <pci/pcivar.h> 59 60 #include <machine/clock.h> 61 62 #include <i386/scsi/aic7xxx.h> 63 #include <i386/scsi/93cx6.h> 64 65 #include <dev/aic7xxx/aic7xxx_reg.h> 66 67 #define PCI_BASEADR0 PCI_MAP_REG_START 68 69 #elif defined(__NetBSD__) 70 71 #include <dev/pci/pcireg.h> 72 #include <dev/pci/pcivar.h> 73 74 #include <dev/ic/aic7xxxreg.h> 75 #include <dev/ic/aic7xxxvar.h> 76 #include <dev/ic/smc93cx6var.h> 77 78 /* 79 * Under normal circumstances, these messages are unnecessary 80 * and not terribly cosmetic. 81 */ 82 #ifdef DEBUG 83 #define bootverbose 1 84 #else 85 #define bootverbose 0 86 #endif 87 88 #define PCI_BASEADR0 PCI_MAPREG_START 89 90 #endif /* defined(__NetBSD__) */ 91 92 #define PCI_DEVICE_ID_ADAPTEC_3940U 0x82789004ul 93 #define PCI_DEVICE_ID_ADAPTEC_2944U 0x84789004ul 94 #define PCI_DEVICE_ID_ADAPTEC_2940U 0x81789004ul 95 #define PCI_DEVICE_ID_ADAPTEC_2940AU 0x61789004ul 96 #define PCI_DEVICE_ID_ADAPTEC_3940 0x72789004ul 97 #define PCI_DEVICE_ID_ADAPTEC_2944 0x74789004ul 98 #define PCI_DEVICE_ID_ADAPTEC_2940 0x71789004ul 99 #define PCI_DEVICE_ID_ADAPTEC_AIC7880 0x80789004ul 100 #define PCI_DEVICE_ID_ADAPTEC_AIC7870 0x70789004ul 101 #define PCI_DEVICE_ID_ADAPTEC_AIC7860 0x60789004ul 102 #define PCI_DEVICE_ID_ADAPTEC_AIC7855 0x55789004ul 103 #define PCI_DEVICE_ID_ADAPTEC_AIC7850 0x50789004ul 104 105 #define DEVCONFIG 0x40 106 #define MPORTMODE 0x00000400ul /* aic7870 only */ 107 #define RAMPSM 0x00000200ul /* aic7870 only */ 108 #define VOLSENSE 0x00000100ul 109 #define SCBRAMSEL 0x00000080ul 110 #define MRDCEN 0x00000040ul 111 #define EXTSCBTIME 0x00000020ul /* aic7870 only */ 112 #define EXTSCBPEN 0x00000010ul /* aic7870 only */ 113 #define BERREN 0x00000008ul 114 #define DACEN 0x00000004ul 115 #define STPWLEVEL 0x00000002ul 116 #define DIFACTNEGEN 0x00000001ul /* aic7870 only */ 117 118 #define CSIZE_LATTIME 0x0c 119 #define CACHESIZE 0x0000003ful /* only 5 bits */ 120 #define LATTIME 0x0000ff00ul 121 122 /* 123 * Define the format of the aic78X0 SEEPROM registers (16 bits). 124 * 125 */ 126 127 struct seeprom_config { 128 129 /* 130 * SCSI ID Configuration Flags 131 */ 132 #define CFXFER 0x0007 /* synchronous transfer rate */ 133 #define CFSYNCH 0x0008 /* enable synchronous transfer */ 134 #define CFDISC 0x0010 /* enable disconnection */ 135 #define CFWIDEB 0x0020 /* wide bus device */ 136 /* UNUSED 0x00C0 */ 137 #define CFSTART 0x0100 /* send start unit SCSI command */ 138 #define CFINCBIOS 0x0200 /* include in BIOS scan */ 139 #define CFRNFOUND 0x0400 /* report even if not found */ 140 /* UNUSED 0xf800 */ 141 u_int16_t device_flags[16]; /* words 0-15 */ 142 143 /* 144 * BIOS Control Bits 145 */ 146 #define CFSUPREM 0x0001 /* support all removeable drives */ 147 #define CFSUPREMB 0x0002 /* support removeable drives for boot only */ 148 #define CFBIOSEN 0x0004 /* BIOS enabled */ 149 /* UNUSED 0x0008 */ 150 #define CFSM2DRV 0x0010 /* support more than two drives */ 151 /* UNUSED 0x0060 */ 152 #define CFEXTEND 0x0080 /* extended translation enabled */ 153 /* UNUSED 0xff00 */ 154 u_int16_t bios_control; /* word 16 */ 155 156 /* 157 * Host Adapter Control Bits 158 */ 159 /* UNUSED 0x0001 */ 160 #define CFULTRAEN 0x0002 /* Ultra SCSI speed enable (Ultra cards) */ 161 #define CFSTERM 0x0004 /* SCSI low byte termination (non-wide cards) */ 162 #define CFWSTERM 0x0008 /* SCSI high byte termination (wide card) */ 163 #define CFSPARITY 0x0010 /* SCSI parity */ 164 /* UNUSED 0x0020 */ 165 #define CFRESETB 0x0040 /* reset SCSI bus at IC initialization */ 166 /* UNUSED 0xff80 */ 167 u_int16_t adapter_control; /* word 17 */ 168 169 /* 170 * Bus Release, Host Adapter ID 171 */ 172 #define CFSCSIID 0x000f /* host adapter SCSI ID */ 173 /* UNUSED 0x00f0 */ 174 #define CFBRTIME 0xff00 /* bus release time */ 175 u_int16_t brtime_id; /* word 18 */ 176 177 /* 178 * Maximum targets 179 */ 180 #define CFMAXTARG 0x00ff /* maximum targets */ 181 /* UNUSED 0xff00 */ 182 u_int16_t max_targets; /* word 19 */ 183 184 u_int16_t res_1[11]; /* words 20-30 */ 185 u_int16_t checksum; /* word 31 */ 186 }; 187 188 static void load_seeprom __P((struct ahc_data *ahc)); 189 static int acquire_seeprom __P((struct seeprom_descriptor *sd)); 190 static void release_seeprom __P((struct seeprom_descriptor *sd)); 191 192 static u_char aic3940_count; 193 194 #if defined(__FreeBSD__) 195 196 static char* aic7870_probe __P((pcici_t tag, pcidi_t type)); 197 static void aic7870_attach __P((pcici_t config_id, int unit)); 198 199 static struct pci_device ahc_pci_driver = { 200 "ahc", 201 aic7870_probe, 202 aic7870_attach, 203 &ahc_unit, 204 NULL 205 }; 206 207 DATA_SET (pcidevice_set, ahc_pci_driver); 208 209 static char* 210 aic7870_probe (pcici_t tag, pcidi_t type) 211 { 212 switch(type) { 213 case PCI_DEVICE_ID_ADAPTEC_3940U: 214 return ("Adaptec 3940 Ultra SCSI host adapter"); 215 break; 216 case PCI_DEVICE_ID_ADAPTEC_3940: 217 return ("Adaptec 3940 SCSI host adapter"); 218 break; 219 case PCI_DEVICE_ID_ADAPTEC_2944U: 220 return ("Adaptec 2944 Ultra SCSI host adapter"); 221 break; 222 case PCI_DEVICE_ID_ADAPTEC_2940U: 223 return ("Adaptec 2940 Ultra SCSI host adapter"); 224 break; 225 case PCI_DEVICE_ID_ADAPTEC_2944: 226 return ("Adaptec 2944 SCSI host adapter"); 227 break; 228 case PCI_DEVICE_ID_ADAPTEC_2940: 229 return ("Adaptec 2940 SCSI host adapter"); 230 break; 231 case PCI_DEVICE_ID_ADAPTEC_2940AU: 232 return ("Adaptec 2940A Ultra SCSI host adapter"); 233 break; 234 case PCI_DEVICE_ID_ADAPTEC_AIC7880: 235 return ("Adaptec aic7880 Ultra SCSI host adapter"); 236 break; 237 case PCI_DEVICE_ID_ADAPTEC_AIC7870: 238 return ("Adaptec aic7870 SCSI host adapter"); 239 break; 240 case PCI_DEVICE_ID_ADAPTEC_AIC7860: 241 return ("Adaptec aic7860 SCSI host adapter"); 242 break; 243 case PCI_DEVICE_ID_ADAPTEC_AIC7855: 244 return ("Adaptec aic7855 SCSI host adapter"); 245 break; 246 case PCI_DEVICE_ID_ADAPTEC_AIC7850: 247 return ("Adaptec aic7850 SCSI host adapter"); 248 break; 249 default: 250 break; 251 } 252 return (0); 253 254 } 255 256 #elif defined(__NetBSD__) 257 258 int ahc_pci_probe __P((struct device *, void *, void *)); 259 void ahc_pci_attach __P((struct device *, struct device *, void *)); 260 261 struct cfattach ahc_pci_ca = { 262 sizeof(struct ahc_data), ahc_pci_probe, ahc_pci_attach 263 }; 264 265 int 266 ahc_pci_probe(parent, match, aux) 267 struct device *parent; 268 void *match, *aux; 269 { 270 struct pci_attach_args *pa = aux; 271 272 switch (pa->pa_id) { 273 case PCI_DEVICE_ID_ADAPTEC_3940U: 274 case PCI_DEVICE_ID_ADAPTEC_2944U: 275 case PCI_DEVICE_ID_ADAPTEC_2940U: 276 case PCI_DEVICE_ID_ADAPTEC_2940AU: 277 case PCI_DEVICE_ID_ADAPTEC_3940: 278 case PCI_DEVICE_ID_ADAPTEC_2944: 279 case PCI_DEVICE_ID_ADAPTEC_2940: 280 case PCI_DEVICE_ID_ADAPTEC_AIC7880: 281 case PCI_DEVICE_ID_ADAPTEC_AIC7870: 282 case PCI_DEVICE_ID_ADAPTEC_AIC7860: 283 case PCI_DEVICE_ID_ADAPTEC_AIC7855: 284 case PCI_DEVICE_ID_ADAPTEC_AIC7850: 285 return 1; 286 } 287 return 0; 288 } 289 #endif /* defined(__NetBSD__) */ 290 291 #if defined(__FreeBSD__) 292 static void 293 aic7870_attach(config_id, unit) 294 pcici_t config_id; 295 int unit; 296 #elif defined(__NetBSD__) 297 void 298 ahc_pci_attach(parent, self, aux) 299 struct device *parent, *self; 300 void *aux; 301 #endif 302 { 303 #if defined(__FreeBSD__) 304 u_long io_port; 305 int unit = ahc->sc_dev.dv_unit; 306 #elif defined(__NetBSD__) 307 struct pci_attach_args *pa = aux; 308 struct ahc_data *ahc = (void *)self; 309 bus_addr_t iobase; 310 bus_size_t iosize; 311 bus_space_handle_t ioh; 312 pci_intr_handle_t ih; 313 const char *intrstr; 314 #endif 315 u_long id; 316 unsigned opri = 0; 317 ahc_type ahc_t = AHC_NONE; 318 ahc_flag ahc_f = AHC_FNONE; 319 #if defined(__FreeBSD__) 320 struct ahc_data *ahc; 321 #endif 322 u_char ultra_enb = 0; 323 u_char our_id = 0; 324 325 #if defined(__FreeBSD__) 326 if(!(io_port = pci_conf_read(config_id, PCI_BASEADR0))) 327 return; 328 /* 329 * The first bit of PCI_BASEADR0 is always 330 * set hence we mask it off. 331 */ 332 io_port &= 0xfffffffe; 333 #elif defined(__NetBSD__) 334 if (pci_io_find(pa->pa_pc, pa->pa_tag, PCI_BASEADR0, &iobase, &iosize)) 335 return; 336 if (bus_space_map(pa->pa_iot, iobase, iosize, 0, &ioh)) 337 return; 338 #endif 339 340 #if defined(__FreeBSD__) 341 switch ((id = pci_conf_read(config_id, PCI_ID_REG))) { 342 #elif defined(__NetBSD__) 343 switch (id = pa->pa_id) { 344 #endif 345 case PCI_DEVICE_ID_ADAPTEC_3940U: 346 case PCI_DEVICE_ID_ADAPTEC_3940: 347 if (id == PCI_DEVICE_ID_ADAPTEC_3940U) 348 ahc_t = AHC_394U; 349 else 350 ahc_t = AHC_394; 351 aic3940_count++; 352 if(!(aic3940_count & 0x01)) 353 /* Even count implies second channel */ 354 ahc_f |= AHC_CHNLB; 355 break; 356 case PCI_DEVICE_ID_ADAPTEC_2944U: 357 case PCI_DEVICE_ID_ADAPTEC_2940U: 358 ahc_t = AHC_294U; 359 break; 360 case PCI_DEVICE_ID_ADAPTEC_2944: 361 case PCI_DEVICE_ID_ADAPTEC_2940: 362 ahc_t = AHC_294; 363 break; 364 case PCI_DEVICE_ID_ADAPTEC_2940AU: 365 ahc_t = AHC_294AU; 366 break; 367 case PCI_DEVICE_ID_ADAPTEC_AIC7880: 368 ahc_t = AHC_AIC7880; 369 break; 370 case PCI_DEVICE_ID_ADAPTEC_AIC7870: 371 ahc_t = AHC_AIC7870; 372 break; 373 case PCI_DEVICE_ID_ADAPTEC_AIC7860: 374 ahc_t = AHC_AIC7860; 375 break; 376 case PCI_DEVICE_ID_ADAPTEC_AIC7855: 377 case PCI_DEVICE_ID_ADAPTEC_AIC7850: 378 ahc_t = AHC_AIC7850; 379 break; 380 default: 381 break; 382 } 383 384 /* On all PCI adapters, we allow SCB paging */ 385 ahc_f |= AHC_PAGESCBS; 386 387 /* Remeber how the card was setup in case there is no SEEPROM */ 388 #if defined(__FreeBSD__) 389 our_id = inb(SCSIID + io_port) & OID; 390 if(ahc_t & AHC_ULTRA) 391 ultra_enb = inb(SXFRCTL0 + io_port) & ULTRAEN; 392 #else 393 our_id = bus_space_read_1(pa->pa_iot, ioh, SCSIID) & OID; 394 if(ahc_t & AHC_ULTRA) 395 ultra_enb = bus_space_read_1(pa->pa_iot, ioh, 396 SXFRCTL0) & ULTRAEN; 397 #endif 398 399 #if defined(__FreeBSD__) 400 ahc_reset(io_port); 401 #elif defined(__NetBSD__) 402 printf("\n"); 403 ahc_reset(ahc->sc_dev.dv_xname, pa->pa_iot, ioh); 404 #endif 405 406 if(ahc_t & AHC_AIC7870){ 407 #if defined(__FreeBSD__) 408 u_long devconfig = pci_conf_read(config_id, DEVCONFIG); 409 #elif defined(__NetBSD__) 410 u_long devconfig = 411 pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG); 412 #endif 413 414 if(devconfig & (RAMPSM)) { 415 /* 416 * External SRAM present. Have the probe walk 417 * the SCBs to see how much SRAM we have and set 418 * the number of SCBs accordingly. We have to 419 * turn off SCBRAMSEL to access the external 420 * SCB SRAM. 421 * 422 * It seems that early versions of the aic7870 423 * didn't use these bits, hence the hack for the 424 * 3940 above. I would guess that recent 3940s 425 * using later aic7870 or aic7880 chips do 426 * actually set RAMPSM. 427 * 428 * The documentation isn't clear, but it sounds 429 * like the value written to devconfig must not 430 * have RAMPSM set. The second sixteen bits of 431 * the register are R/O anyway, so it shouldn't 432 * affect RAMPSM either way. 433 */ 434 devconfig &= ~(RAMPSM|SCBRAMSEL); 435 #if defined(__FreeBSD__) 436 pci_conf_write(config_id, DEVCONFIG, devconfig); 437 #elif defined(__NetBSD__) 438 pci_conf_write(pa->pa_pc, pa->pa_tag, 439 DEVCONFIG, devconfig); 440 #endif 441 } 442 } 443 444 #if defined(__FreeBSD__) 445 if(!(ahc = ahc_alloc(unit, io_port, ahc_t, ahc_f))) 446 return; /* XXX PCI code should take return status */ 447 448 if(!(pci_map_int(config_id, ahc_intr, (void *)ahc, &bio_imask))) { 449 ahc_free(ahc); 450 return; 451 } 452 #elif defined(__NetBSD__) 453 ahc_construct(ahc, pa->pa_iot, ioh, ahc_t, ahc_f); 454 455 if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 456 pa->pa_intrline, &ih)) { 457 printf("%s: couldn't map interrupt\n", ahc->sc_dev.dv_xname); 458 ahc_free(ahc); 459 return; 460 } 461 intrstr = pci_intr_string(pa->pa_pc, ih); 462 #if defined(__OpenBSD__) 463 ahc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, ahc_intr, ahc, 464 ahc->sc_dev.dv_xname); 465 #else 466 ahc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, ahc_intr, ahc); 467 #endif 468 if (ahc->sc_ih == NULL) { 469 printf("%s: couldn't establish interrupt", 470 ahc->sc_dev.dv_xname); 471 if (intrstr != NULL) 472 printf(" at %s", intrstr); 473 printf("\n"); 474 ahc_free(ahc); 475 return; 476 } 477 if (intrstr != NULL) 478 printf("%s: interrupting at %s\n", ahc->sc_dev.dv_xname, 479 intrstr); 480 #endif 481 /* 482 * Protect ourself from spurrious interrupts during 483 * intialization. 484 */ 485 opri = splbio(); 486 487 /* 488 * Do aic7870/aic7880/aic7850 specific initialization 489 */ 490 { 491 u_char sblkctl; 492 char *id_string; 493 494 switch(ahc->type) { 495 case AHC_394U: 496 case AHC_294U: 497 case AHC_AIC7880: 498 { 499 id_string = "aic7880 "; 500 load_seeprom(ahc); 501 break; 502 } 503 case AHC_394: 504 case AHC_294: 505 case AHC_AIC7870: 506 { 507 id_string = "aic7870 "; 508 load_seeprom(ahc); 509 break; 510 } 511 case AHC_294AU: 512 case AHC_AIC7860: 513 { 514 id_string = "aic7860 "; 515 load_seeprom(ahc); 516 break; 517 } 518 case AHC_AIC7850: 519 { 520 id_string = "aic7850 "; 521 /* 522 * Use defaults, if the chip wasn't initialized by 523 * a BIOS. 524 */ 525 ahc->flags |= AHC_USEDEFAULTS; 526 break; 527 } 528 default: 529 { 530 printf("ahc: Unknown controller type. Ignoring.\n"); 531 ahc_free(ahc); 532 splx(opri); 533 return; 534 } 535 } 536 537 /* 538 * Take the LED out of diagnostic mode 539 */ 540 sblkctl = AHC_INB(ahc, SBLKCTL); 541 AHC_OUTB(ahc, SBLKCTL, (sblkctl & ~(DIAGLEDEN|DIAGLEDON))); 542 543 /* 544 * I don't know where this is set in the SEEPROM or by the 545 * BIOS, so we default to 100%. 546 */ 547 AHC_OUTB(ahc, DSPCISTATUS, DFTHRSH_100); 548 549 if(ahc->flags & AHC_USEDEFAULTS) { 550 /* 551 * PCI Adapter default setup 552 * Should only be used if the adapter does not have 553 * an SEEPROM. 554 */ 555 /* See if someone else set us up already */ 556 u_long i; 557 for(i = TARG_SCRATCH; i < 0x60; i++) { 558 if(AHC_INB(ahc, i) != 0x00) 559 break; 560 } 561 if(i == TARG_SCRATCH) { 562 /* 563 * Try looking for all ones. You can get 564 * either. 565 */ 566 for (i = TARG_SCRATCH; i < 0x60; i++) { 567 if(AHC_INB(ahc, i) != 0xff) 568 break; 569 } 570 } 571 if((i != 0x60) && (our_id != 0)) { 572 printf("%s: Using left over BIOS settings\n", 573 ahc_name(ahc)); 574 ahc->flags &= ~AHC_USEDEFAULTS; 575 } 576 else 577 our_id = 0x07; 578 AHC_OUTB(ahc, SCSICONF, 579 (our_id & 0x07)|ENSPCHK|RESET_SCSI); 580 /* In case we are a wide card */ 581 AHC_OUTB(ahc, SCSICONF + 1, our_id); 582 583 if(!ultra_enb || (ahc->flags & AHC_USEDEFAULTS)) { 584 /* 585 * If there wasn't a BIOS or the board 586 * wasn't in this mode to begin with, 587 * turn off ultra. 588 */ 589 ahc->type &= ~AHC_ULTRA; 590 } 591 } 592 593 printf("%s: %s", ahc_name(ahc), id_string); 594 } 595 596 if(ahc_init(ahc)){ 597 ahc_free(ahc); 598 splx(opri); 599 return; /* XXX PCI code should take return status */ 600 } 601 splx(opri); 602 603 ahc_attach(ahc); 604 } 605 606 /* 607 * Read the SEEPROM. Return 0 on failure 608 */ 609 void 610 load_seeprom(ahc) 611 struct ahc_data *ahc; 612 { 613 struct seeprom_descriptor sd; 614 struct seeprom_config sc; 615 u_short *scarray = (u_short *)≻ 616 u_short checksum = 0; 617 u_char scsi_conf; 618 u_char host_id; 619 int have_seeprom; 620 621 #if defined(__FreeBSD__) 622 sd.sd_iobase = ahc->baseport + SEECTL; 623 #elif defined(__NetBSD__) 624 sd.sd_iot = ahc->sc_iot; 625 sd.sd_ioh = ahc->sc_ioh; 626 sd.sd_offset = SEECTL; 627 #endif 628 sd.sd_MS = SEEMS; 629 sd.sd_RDY = SEERDY; 630 sd.sd_CS = SEECS; 631 sd.sd_CK = SEECK; 632 sd.sd_DO = SEEDO; 633 sd.sd_DI = SEEDI; 634 635 if(bootverbose) 636 printf("%s: Reading SEEPROM...", ahc_name(ahc)); 637 have_seeprom = acquire_seeprom(&sd); 638 if (have_seeprom) { 639 have_seeprom = read_seeprom(&sd, 640 (u_int16_t *)&sc, 641 ahc->flags & AHC_CHNLB, 642 sizeof(sc)/2); 643 release_seeprom(&sd); 644 if (have_seeprom) { 645 /* Check checksum */ 646 int i; 647 648 for (i = 0;i < (sizeof(sc)/2 - 1);i = i + 1) 649 checksum = checksum + scarray[i]; 650 if (checksum != sc.checksum) { 651 if(bootverbose) 652 printf ("checksum error"); 653 have_seeprom = 0; 654 } 655 else if(bootverbose) 656 printf("done.\n"); 657 } 658 } 659 if (!have_seeprom) { 660 if(bootverbose) 661 printf("\n%s: No SEEPROM availible\n", ahc_name(ahc)); 662 ahc->flags |= AHC_USEDEFAULTS; 663 } 664 else { 665 /* 666 * Put the data we've collected down into SRAM 667 * where ahc_init will find it. 668 */ 669 int i; 670 int max_targ = sc.max_targets & CFMAXTARG; 671 672 for(i = 0; i < max_targ; i++){ 673 u_char target_settings; 674 target_settings = (sc.device_flags[i] & CFXFER) << 4; 675 if (sc.device_flags[i] & CFSYNCH) 676 target_settings |= SOFS; 677 if (sc.device_flags[i] & CFWIDEB) 678 target_settings |= WIDEXFER; 679 if (sc.device_flags[i] & CFDISC) 680 ahc->discenable |= (0x01 << i); 681 AHC_OUTB(ahc, TARG_SCRATCH+i, target_settings); 682 } 683 AHC_OUTB(ahc, DISC_DSB, ~(ahc->discenable & 0xff)); 684 AHC_OUTB(ahc, DISC_DSB + 1, ~((ahc->discenable >> 8) & 0xff)); 685 686 host_id = sc.brtime_id & CFSCSIID; 687 688 scsi_conf = (host_id & 0x7); 689 if(sc.adapter_control & CFSPARITY) 690 scsi_conf |= ENSPCHK; 691 if(sc.adapter_control & CFRESETB) 692 scsi_conf |= RESET_SCSI; 693 694 if(ahc->type & AHC_ULTRA) { 695 /* Should we enable Ultra mode? */ 696 if(!(sc.adapter_control & CFULTRAEN)) 697 /* Treat us as a non-ultra card */ 698 ahc->type &= ~AHC_ULTRA; 699 } 700 /* Set the host ID */ 701 AHC_OUTB(ahc, SCSICONF, scsi_conf); 702 /* In case we are a wide card */ 703 AHC_OUTB(ahc, SCSICONF + 1, host_id); 704 } 705 } 706 707 static int 708 acquire_seeprom(sd) 709 struct seeprom_descriptor *sd; 710 { 711 int wait; 712 713 /* 714 * Request access of the memory port. When access is 715 * granted, SEERDY will go high. We use a 1 second 716 * timeout which should be near 1 second more than 717 * is needed. Reason: after the chip reset, there 718 * should be no contention. 719 */ 720 SEEPROM_OUTB(sd, sd->sd_MS); 721 wait = 1000; /* 1 second timeout in msec */ 722 while (--wait && ((SEEPROM_INB(sd) & sd->sd_RDY) == 0)) { 723 DELAY (1000); /* delay 1 msec */ 724 } 725 if ((SEEPROM_INB(sd) & sd->sd_RDY) == 0) { 726 SEEPROM_OUTB(sd, 0); 727 return (0); 728 } 729 return(1); 730 } 731 732 static void 733 release_seeprom(sd) 734 struct seeprom_descriptor *sd; 735 { 736 /* Release access to the memory port and the serial EEPROM. */ 737 SEEPROM_OUTB(sd, 0); 738 } 739 740 #endif /* NPCI > 0 */ 741