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