1 /* $OpenBSD: aic7xxx_seeprom.c,v 1.4 2008/05/13 02:24:08 brad Exp $ */ 2 /* $NetBSD: aic7xxx_seeprom.c,v 1.8 2003/05/02 19:12:19 dyoung Exp $ */ 3 4 /* 5 * Product specific probe and attach routines for: 6 * 3940, 2940, aic7895, aic7890, aic7880, 7 * aic7870, aic7860 and aic7850 SCSI controllers 8 * 9 * Copyright (c) 1994-2001 Justin T. Gibbs. 10 * Copyright (c) 2000-2001 Adaptec Inc. 11 * All rights reserved. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions, and the following disclaimer, 18 * without modification. 19 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 20 * substantially similar to the "NO WARRANTY" disclaimer below 21 * ("Disclaimer") and any redistribution must be conditioned upon 22 * including a substantially similar Disclaimer requirement for further 23 * binary redistribution. 24 * 3. Neither the names of the above-listed copyright holders nor the names 25 * of any contributors may be used to endorse or promote products derived 26 * from this software without specific prior written permission. 27 * 28 * Alternatively, this software may be distributed under the terms of the 29 * GNU General Public License ("GPL") version 2 as published by the Free 30 * Software Foundation. 31 * 32 * NO WARRANTY 33 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 34 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 35 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 36 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 37 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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, 41 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 42 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 43 * POSSIBILITY OF SUCH DAMAGES. 44 * 45 * This file was originally split off from the PCI code by 46 * Jason Thorpe <thorpej@netbsd.org>. This version was split off 47 * from the FreeBSD source file aic7xxx_pci.c by Frank van der Linden 48 * <fvdl@netbsd.org> 49 * 50 * $Id: aic7xxx_seeprom.c,v 1.4 2008/05/13 02:24:08 brad Exp $ 51 * 52 * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx_pci.c,v 1.22 2003/01/20 20:44:55 gibbs Exp $ 53 */ 54 55 #include <sys/param.h> 56 #include <sys/systm.h> 57 #include <sys/malloc.h> 58 #include <sys/kernel.h> 59 #include <sys/queue.h> 60 #include <sys/device.h> 61 #include <sys/reboot.h> /* for AB_* needed by bootverbose */ 62 63 #include <machine/bus.h> 64 #include <machine/intr.h> 65 66 #include <scsi/scsi_all.h> 67 #include <scsi/scsiconf.h> 68 69 #include <dev/ic/aic7xxx_openbsd.h> 70 #include <dev/ic/aic7xxx_inline.h> 71 72 #include <dev/ic/smc93cx6var.h> 73 74 #define DEVCONFIG 0x40 75 #define STPWLEVEL 0x00000002 76 77 static void configure_termination(struct ahc_softc *, 78 struct seeprom_descriptor *, u_int, u_int *); 79 static int verify_seeprom_cksum(struct seeprom_config *sc); 80 81 static void ahc_new_term_detect(struct ahc_softc *, int *, int *, int *, 82 int *, int *); 83 static void aic787X_cable_detect(struct ahc_softc *, int *, int *, int *, 84 int *); 85 static void aic785X_cable_detect(struct ahc_softc *, int *, int *, int *); 86 static void write_brdctl(struct ahc_softc *, u_int8_t); 87 static u_int8_t read_brdctl(struct ahc_softc *); 88 static void ahc_parse_pci_eeprom(struct ahc_softc *, struct seeprom_config *); 89 90 /* 91 * Check the external port logic for a serial eeprom 92 * and termination/cable detection contrls. 93 */ 94 void 95 ahc_check_extport(struct ahc_softc *ahc, u_int *sxfrctl1) 96 { 97 struct seeprom_descriptor sd; 98 struct seeprom_config *sc; 99 int have_seeprom; 100 int have_autoterm; 101 102 sd.sd_tag = ahc->tag; 103 sd.sd_bsh = ahc->bsh; 104 sd.sd_regsize = 1; 105 sd.sd_control_offset = SEECTL; 106 sd.sd_status_offset = SEECTL; 107 sd.sd_dataout_offset = SEECTL; 108 sc = ahc->seep_config; 109 110 /* 111 * For some multi-channel devices, the c46 is simply too 112 * small to work. For the other controller types, we can 113 * get our information from either SEEPROM type. Set the 114 * type to start our probe with accordingly. 115 */ 116 if (ahc->flags & AHC_LARGE_SEEPROM) 117 sd.sd_chip = C56_66; 118 else 119 sd.sd_chip = C46; 120 121 sd.sd_MS = SEEMS; 122 sd.sd_RDY = SEERDY; 123 sd.sd_CS = SEECS; 124 sd.sd_CK = SEECK; 125 sd.sd_DO = SEEDO; 126 sd.sd_DI = SEEDI; 127 128 have_seeprom = ahc_acquire_seeprom(ahc, &sd); 129 if (have_seeprom) { 130 131 if (bootverbose) 132 printf("%s: Reading SEEPROM...", ahc_name(ahc)); 133 134 for (;;) { 135 u_int start_addr; 136 137 start_addr = 32 * (ahc->channel - 'A'); 138 have_seeprom = read_seeprom(&sd, (uint16_t *)sc, 139 start_addr, 140 sizeof(*sc)/2); 141 142 if (have_seeprom) 143 have_seeprom = verify_seeprom_cksum(sc); 144 145 if (have_seeprom != 0 || sd.sd_chip == C56_66) { 146 if (bootverbose) { 147 if (have_seeprom == 0) 148 printf ("checksum error\n"); 149 else 150 printf ("done.\n"); 151 } 152 break; 153 } 154 sd.sd_chip = C56_66; 155 } 156 ahc_release_seeprom(&sd); 157 } 158 159 if (!have_seeprom) { 160 /* 161 * Pull scratch ram settings and treat them as 162 * if they are the contents of an seeprom if 163 * the 'ADPT' signature is found in SCB2. 164 * We manually compose the data as 16bit values 165 * to avoid endian issues. 166 */ 167 ahc_outb(ahc, SCBPTR, 2); 168 if (ahc_inb(ahc, SCB_BASE) == 'A' 169 && ahc_inb(ahc, SCB_BASE + 1) == 'D' 170 && ahc_inb(ahc, SCB_BASE + 2) == 'P' 171 && ahc_inb(ahc, SCB_BASE + 3) == 'T') { 172 uint16_t *sc_data; 173 int i; 174 175 sc_data = (uint16_t *)sc; 176 for (i = 0; i < 32; i++, sc_data++) { 177 int j; 178 179 j = i * 2; 180 *sc_data = ahc_inb(ahc, SRAM_BASE + j) 181 | ahc_inb(ahc, SRAM_BASE + j + 1) << 8; 182 } 183 have_seeprom = verify_seeprom_cksum(sc); 184 if (have_seeprom) 185 ahc->flags |= AHC_SCB_CONFIG_USED; 186 } 187 /* 188 * Clear any SCB parity errors in case this data and 189 * its associated parity was not initialized by the BIOS 190 */ 191 ahc_outb(ahc, CLRINT, CLRPARERR); 192 ahc_outb(ahc, CLRINT, CLRBRKADRINT); 193 } 194 195 if (!have_seeprom) { 196 if (bootverbose) 197 printf("%s: No SEEPROM available.\n", ahc_name(ahc)); 198 ahc->flags |= AHC_USEDEFAULTS | AHC_NO_BIOS_INIT; 199 free(ahc->seep_config, M_DEVBUF); 200 ahc->seep_config = NULL; 201 sc = NULL; 202 } else { 203 ahc_parse_pci_eeprom(ahc, sc); 204 } 205 206 /* 207 * Cards that have the external logic necessary to talk to 208 * a SEEPROM, are almost certain to have the remaining logic 209 * necessary for auto-termination control. This assumption 210 * hasn't failed yet... 211 */ 212 have_autoterm = have_seeprom; 213 214 /* 215 * Some low-cost chips have SEEPROM and auto-term control built 216 * in, instead of using a GAL. They can tell us directly 217 * if the termination logic is enabled. 218 */ 219 if ((ahc->features & AHC_SPIOCAP) != 0) { 220 if ((ahc_inb(ahc, SPIOCAP) & SSPIOCPS) == 0) 221 have_autoterm = FALSE; 222 } 223 224 if (have_autoterm) { 225 ahc_acquire_seeprom(ahc, &sd); 226 configure_termination(ahc, &sd, sc->adapter_control, sxfrctl1); 227 ahc_release_seeprom(&sd); 228 } else if (have_seeprom) { 229 *sxfrctl1 &= ~STPWEN; 230 if ((sc->adapter_control & CFSTERM) != 0) 231 *sxfrctl1 |= STPWEN; 232 if (bootverbose) 233 printf("%s: Low byte termination %sabled\n", 234 ahc_name(ahc), 235 (*sxfrctl1 & STPWEN) ? "en" : "dis"); 236 } 237 } 238 239 static void 240 ahc_parse_pci_eeprom(struct ahc_softc *ahc, struct seeprom_config *sc) 241 { 242 /* 243 * Put the data we've collected down into SRAM 244 * where ahc_init will find it. 245 */ 246 int i; 247 int max_targ = sc->max_targets & CFMAXTARG; 248 u_int scsi_conf; 249 uint16_t discenable; 250 uint16_t ultraenb; 251 252 discenable = 0; 253 ultraenb = 0; 254 if ((sc->adapter_control & CFULTRAEN) != 0) { 255 /* 256 * Determine if this adapter has a "newstyle" 257 * SEEPROM format. 258 */ 259 for (i = 0; i < max_targ; i++) { 260 if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0) { 261 ahc->flags |= AHC_NEWEEPROM_FMT; 262 break; 263 } 264 } 265 } 266 267 for (i = 0; i < max_targ; i++) { 268 u_int scsirate; 269 uint16_t target_mask; 270 271 target_mask = 0x01 << i; 272 if (sc->device_flags[i] & CFDISC) 273 discenable |= target_mask; 274 if ((ahc->flags & AHC_NEWEEPROM_FMT) != 0) { 275 if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0) 276 ultraenb |= target_mask; 277 } else if ((sc->adapter_control & CFULTRAEN) != 0) { 278 ultraenb |= target_mask; 279 } 280 if ((sc->device_flags[i] & CFXFER) == 0x04 281 && (ultraenb & target_mask) != 0) { 282 /* Treat 10MHz as a non-ultra speed */ 283 sc->device_flags[i] &= ~CFXFER; 284 ultraenb &= ~target_mask; 285 } 286 if ((ahc->features & AHC_ULTRA2) != 0) { 287 u_int offset; 288 289 if (sc->device_flags[i] & CFSYNCH) 290 offset = MAX_OFFSET_ULTRA2; 291 else 292 offset = 0; 293 ahc_outb(ahc, TARG_OFFSET + i, offset); 294 295 /* 296 * The ultra enable bits contain the 297 * high bit of the ultra2 sync rate 298 * field. 299 */ 300 scsirate = (sc->device_flags[i] & CFXFER) 301 | ((ultraenb & target_mask) ? 0x8 : 0x0); 302 if (sc->device_flags[i] & CFWIDEB) 303 scsirate |= WIDEXFER; 304 } else { 305 scsirate = (sc->device_flags[i] & CFXFER) << 4; 306 if (sc->device_flags[i] & CFSYNCH) 307 scsirate |= SOFS; 308 if (sc->device_flags[i] & CFWIDEB) 309 scsirate |= WIDEXFER; 310 } 311 ahc_outb(ahc, TARG_SCSIRATE + i, scsirate); 312 } 313 ahc->our_id = sc->brtime_id & CFSCSIID; 314 315 scsi_conf = (ahc->our_id & 0x7); 316 if (sc->adapter_control & CFSPARITY) 317 scsi_conf |= ENSPCHK; 318 if (sc->adapter_control & CFRESETB) 319 scsi_conf |= RESET_SCSI; 320 321 ahc->flags |= (sc->adapter_control & CFBOOTCHAN) >> CFBOOTCHANSHIFT; 322 323 if (sc->bios_control & CFEXTEND) 324 ahc->flags |= AHC_EXTENDED_TRANS_A; 325 326 if (sc->bios_control & CFBIOSEN) 327 ahc->flags |= AHC_BIOS_ENABLED; 328 if (ahc->features & AHC_ULTRA 329 && (ahc->flags & AHC_NEWEEPROM_FMT) == 0) { 330 /* Should we enable Ultra mode? */ 331 if (!(sc->adapter_control & CFULTRAEN)) 332 /* Treat us as a non-ultra card */ 333 ultraenb = 0; 334 } 335 336 if (sc->signature == CFSIGNATURE 337 || sc->signature == CFSIGNATURE2) { 338 uint32_t devconfig; 339 340 /* Honor the STPWLEVEL settings */ 341 devconfig = pci_conf_read(ahc->bd->pc, ahc->bd->tag, DEVCONFIG); 342 devconfig &= ~STPWLEVEL; 343 if ((sc->bios_control & CFSTPWLEVEL) != 0) 344 devconfig |= STPWLEVEL; 345 pci_conf_write(ahc->bd->pc, ahc->bd->tag, DEVCONFIG, devconfig); 346 } 347 /* Set SCSICONF info */ 348 ahc_outb(ahc, SCSICONF, scsi_conf); 349 ahc_outb(ahc, DISC_DSB, ~(discenable & 0xff)); 350 ahc_outb(ahc, DISC_DSB + 1, ~((discenable >> 8) & 0xff)); 351 ahc_outb(ahc, ULTRA_ENB, ultraenb & 0xff); 352 ahc_outb(ahc, ULTRA_ENB + 1, (ultraenb >> 8) & 0xff); 353 } 354 355 static void 356 configure_termination(struct ahc_softc *ahc, 357 struct seeprom_descriptor *sd, 358 u_int adapter_control, 359 u_int *sxfrctl1) 360 { 361 uint8_t brddat; 362 363 brddat = 0; 364 365 /* 366 * Update the settings in sxfrctl1 to match the 367 * termination settings 368 */ 369 *sxfrctl1 = 0; 370 371 /* 372 * SEECS must be on for the GALS to latch 373 * the data properly. Be sure to leave MS 374 * on or we will release the seeprom. 375 */ 376 SEEPROM_OUTB(sd, sd->sd_MS | sd->sd_CS); 377 if ((adapter_control & CFAUTOTERM) != 0 378 || (ahc->features & AHC_NEW_TERMCTL) != 0) { 379 int internal50_present; 380 int internal68_present; 381 int externalcable_present; 382 int eeprom_present; 383 int enableSEC_low; 384 int enableSEC_high; 385 int enablePRI_low; 386 int enablePRI_high; 387 int sum; 388 389 enableSEC_low = 0; 390 enableSEC_high = 0; 391 enablePRI_low = 0; 392 enablePRI_high = 0; 393 if ((ahc->features & AHC_NEW_TERMCTL) != 0) { 394 ahc_new_term_detect(ahc, &enableSEC_low, 395 &enableSEC_high, 396 &enablePRI_low, 397 &enablePRI_high, 398 &eeprom_present); 399 if ((adapter_control & CFSEAUTOTERM) == 0) { 400 if (bootverbose) 401 printf("%s: Manual SE Termination\n", 402 ahc_name(ahc)); 403 enableSEC_low = (adapter_control & CFSELOWTERM); 404 enableSEC_high = 405 (adapter_control & CFSEHIGHTERM); 406 } 407 if ((adapter_control & CFAUTOTERM) == 0) { 408 if (bootverbose) 409 printf("%s: Manual LVD Termination\n", 410 ahc_name(ahc)); 411 enablePRI_low = (adapter_control & CFSTERM); 412 enablePRI_high = (adapter_control & CFWSTERM); 413 } 414 /* Make the table calculations below happy */ 415 internal50_present = 0; 416 internal68_present = 1; 417 externalcable_present = 1; 418 } else if ((ahc->features & AHC_SPIOCAP) != 0) { 419 aic785X_cable_detect(ahc, &internal50_present, 420 &externalcable_present, 421 &eeprom_present); 422 /* Can never support a wide connector. */ 423 internal68_present = 0; 424 } else { 425 aic787X_cable_detect(ahc, &internal50_present, 426 &internal68_present, 427 &externalcable_present, 428 &eeprom_present); 429 } 430 431 if ((ahc->features & AHC_WIDE) == 0) 432 internal68_present = 0; 433 434 if (bootverbose 435 && (ahc->features & AHC_ULTRA2) == 0) { 436 printf("%s: internal 50 cable %s present", 437 ahc_name(ahc), 438 internal50_present ? "is":"not"); 439 440 if ((ahc->features & AHC_WIDE) != 0) 441 printf(", internal 68 cable %s present", 442 internal68_present ? "is":"not"); 443 printf("\n%s: external cable %s present\n", 444 ahc_name(ahc), 445 externalcable_present ? "is":"not"); 446 } 447 if (bootverbose) 448 printf("%s: BIOS eeprom %s present\n", 449 ahc_name(ahc), eeprom_present ? "is" : "not"); 450 451 if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) { 452 /* 453 * The 50 pin connector is a separate bus, 454 * so force it to always be terminated. 455 * In the future, perform current sensing 456 * to determine if we are in the middle of 457 * a properly terminated bus. 458 */ 459 internal50_present = 0; 460 } 461 462 /* 463 * Now set the termination based on what 464 * we found. 465 * Flash Enable = BRDDAT7 466 * Secondary High Term Enable = BRDDAT6 467 * Secondary Low Term Enable = BRDDAT5 (7890) 468 * Primary High Term Enable = BRDDAT4 (7890) 469 */ 470 if ((ahc->features & AHC_ULTRA2) == 0 471 && (internal50_present != 0) 472 && (internal68_present != 0) 473 && (externalcable_present != 0)) { 474 printf("%s: Illegal cable configuration!!. " 475 "Only two connectors on the " 476 "adapter may be used at a " 477 "time!\n", ahc_name(ahc)); 478 479 /* 480 * Pretend there are no cables in the hope 481 * that having all of the termination on 482 * gives us a more stable bus. 483 */ 484 internal50_present = 0; 485 internal68_present = 0; 486 externalcable_present = 0; 487 } 488 489 if ((ahc->features & AHC_WIDE) != 0 490 && ((externalcable_present == 0) 491 || (internal68_present == 0) 492 || (enableSEC_high != 0))) { 493 brddat |= BRDDAT6; 494 if (bootverbose) { 495 if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) 496 printf("%s: 68 pin termination " 497 "Enabled\n", ahc_name(ahc)); 498 else 499 printf("%s: %sHigh byte termination " 500 "Enabled\n", ahc_name(ahc), 501 enableSEC_high ? "Secondary " 502 : ""); 503 } 504 } 505 506 sum = internal50_present + internal68_present 507 + externalcable_present; 508 if (sum < 2 || (enableSEC_low != 0)) { 509 if ((ahc->features & AHC_ULTRA2) != 0) 510 brddat |= BRDDAT5; 511 else 512 *sxfrctl1 |= STPWEN; 513 if (bootverbose) { 514 if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) 515 printf("%s: 50 pin termination " 516 "Enabled\n", ahc_name(ahc)); 517 else 518 printf("%s: %sLow byte termination " 519 "Enabled\n", ahc_name(ahc), 520 enableSEC_low ? "Secondary " 521 : ""); 522 } 523 } 524 525 if (enablePRI_low != 0) { 526 *sxfrctl1 |= STPWEN; 527 if (bootverbose) 528 printf("%s: Primary Low Byte termination " 529 "Enabled\n", ahc_name(ahc)); 530 } 531 532 /* 533 * Setup STPWEN before setting up the rest of 534 * the termination per the tech note on the U160 cards. 535 */ 536 ahc_outb(ahc, SXFRCTL1, *sxfrctl1); 537 538 if (enablePRI_high != 0) { 539 brddat |= BRDDAT4; 540 if (bootverbose) 541 printf("%s: Primary High Byte " 542 "termination Enabled\n", 543 ahc_name(ahc)); 544 } 545 546 write_brdctl(ahc, brddat); 547 548 } else { 549 if ((adapter_control & CFSTERM) != 0) { 550 *sxfrctl1 |= STPWEN; 551 552 if (bootverbose) 553 printf("%s: %sLow byte termination Enabled\n", 554 ahc_name(ahc), 555 (ahc->features & AHC_ULTRA2) ? "Primary " 556 : ""); 557 } 558 559 if ((adapter_control & CFWSTERM) != 0 560 && (ahc->features & AHC_WIDE) != 0) { 561 brddat |= BRDDAT6; 562 if (bootverbose) 563 printf("%s: %sHigh byte termination Enabled\n", 564 ahc_name(ahc), 565 (ahc->features & AHC_ULTRA2) 566 ? "Secondary " : ""); 567 } 568 569 /* 570 * Setup STPWEN before setting up the rest of 571 * the termination per the tech note on the U160 cards. 572 */ 573 ahc_outb(ahc, SXFRCTL1, *sxfrctl1); 574 575 if ((ahc->features & AHC_WIDE) != 0) 576 write_brdctl(ahc, brddat); 577 } 578 SEEPROM_OUTB(sd, sd->sd_MS); /* Clear CS */ 579 } 580 581 static void 582 ahc_new_term_detect(struct ahc_softc *ahc, int *enableSEC_low, 583 int *enableSEC_high, int *enablePRI_low, 584 int *enablePRI_high, int *eeprom_present) 585 { 586 uint8_t brdctl; 587 588 /* 589 * BRDDAT7 = Eeprom 590 * BRDDAT6 = Enable Secondary High Byte termination 591 * BRDDAT5 = Enable Secondary Low Byte termination 592 * BRDDAT4 = Enable Primary high byte termination 593 * BRDDAT3 = Enable Primary low byte termination 594 */ 595 brdctl = read_brdctl(ahc); 596 *eeprom_present = brdctl & BRDDAT7; 597 *enableSEC_high = (brdctl & BRDDAT6); 598 *enableSEC_low = (brdctl & BRDDAT5); 599 *enablePRI_high = (brdctl & BRDDAT4); 600 *enablePRI_low = (brdctl & BRDDAT3); 601 } 602 603 static void 604 aic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present, 605 int *internal68_present, int *externalcable_present, 606 int *eeprom_present) 607 { 608 uint8_t brdctl; 609 610 /* 611 * First read the status of our cables. 612 * Set the rom bank to 0 since the 613 * bank setting serves as a multiplexor 614 * for the cable detection logic. 615 * BRDDAT5 controls the bank switch. 616 */ 617 write_brdctl(ahc, 0); 618 619 /* 620 * Now read the state of the internal 621 * connectors. BRDDAT6 is INT50 and 622 * BRDDAT7 is INT68. 623 */ 624 brdctl = read_brdctl(ahc); 625 *internal50_present = (brdctl & BRDDAT6) ? 0 : 1; 626 *internal68_present = (brdctl & BRDDAT7) ? 0 : 1; 627 628 /* 629 * Set the rom bank to 1 and determine 630 * the other signals. 631 */ 632 write_brdctl(ahc, BRDDAT5); 633 634 /* 635 * Now read the state of the external 636 * connectors. BRDDAT6 is EXT68 and 637 * BRDDAT7 is EPROMPS. 638 */ 639 brdctl = read_brdctl(ahc); 640 *externalcable_present = (brdctl & BRDDAT6) ? 0 : 1; 641 *eeprom_present = (brdctl & BRDDAT7) ? 1 : 0; 642 } 643 644 static void 645 aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present, 646 int *externalcable_present, int *eeprom_present) 647 { 648 uint8_t brdctl; 649 uint8_t spiocap; 650 651 spiocap = ahc_inb(ahc, SPIOCAP); 652 spiocap &= ~SOFTCMDEN; 653 spiocap |= EXT_BRDCTL; 654 ahc_outb(ahc, SPIOCAP, spiocap); 655 ahc_outb(ahc, BRDCTL, BRDRW|BRDCS); 656 ahc_outb(ahc, BRDCTL, 0); 657 brdctl = ahc_inb(ahc, BRDCTL); 658 *internal50_present = (brdctl & BRDDAT5) ? 0 : 1; 659 *externalcable_present = (brdctl & BRDDAT6) ? 0 : 1; 660 661 *eeprom_present = (ahc_inb(ahc, SPIOCAP) & EEPROM) ? 1 : 0; 662 } 663 664 int 665 ahc_acquire_seeprom(struct ahc_softc *ahc, struct seeprom_descriptor *sd) 666 { 667 int wait; 668 669 if ((ahc->features & AHC_SPIOCAP) != 0 670 && (ahc_inb(ahc, SPIOCAP) & SEEPROM) == 0) 671 return (0); 672 673 /* 674 * Request access of the memory port. When access is 675 * granted, SEERDY will go high. We use a 1 second 676 * timeout which should be near 1 second more than 677 * is needed. Reason: after the chip reset, there 678 * should be no contention. 679 */ 680 SEEPROM_OUTB(sd, sd->sd_MS); 681 wait = 1000; /* 1 second timeout in msec */ 682 while (--wait && ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0)) { 683 aic_delay(1000); /* delay 1 msec */ 684 } 685 if ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0) { 686 SEEPROM_OUTB(sd, 0); 687 return (0); 688 } 689 return(1); 690 } 691 692 void 693 ahc_release_seeprom(struct seeprom_descriptor *sd) 694 { 695 /* Release access to the memory port and the serial EEPROM. */ 696 SEEPROM_OUTB(sd, 0); 697 } 698 699 static void 700 write_brdctl(struct ahc_softc *ahc, uint8_t value) 701 { 702 uint8_t brdctl; 703 704 if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) { 705 brdctl = BRDSTB; 706 if (ahc->channel == 'B') 707 brdctl |= BRDCS; 708 } else if ((ahc->features & AHC_ULTRA2) != 0) { 709 brdctl = 0; 710 } else { 711 brdctl = BRDSTB|BRDCS; 712 } 713 ahc_outb(ahc, BRDCTL, brdctl); 714 ahc_flush_device_writes(ahc); 715 brdctl |= value; 716 ahc_outb(ahc, BRDCTL, brdctl); 717 ahc_flush_device_writes(ahc); 718 if ((ahc->features & AHC_ULTRA2) != 0) 719 brdctl |= BRDSTB_ULTRA2; 720 else 721 brdctl &= ~BRDSTB; 722 ahc_outb(ahc, BRDCTL, brdctl); 723 ahc_flush_device_writes(ahc); 724 if ((ahc->features & AHC_ULTRA2) != 0) 725 brdctl = 0; 726 else 727 brdctl &= ~BRDCS; 728 ahc_outb(ahc, BRDCTL, brdctl); 729 } 730 731 static uint8_t 732 read_brdctl(ahc) 733 struct ahc_softc *ahc; 734 { 735 uint8_t brdctl; 736 uint8_t value; 737 738 if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) { 739 brdctl = BRDRW; 740 if (ahc->channel == 'B') 741 brdctl |= BRDCS; 742 } else if ((ahc->features & AHC_ULTRA2) != 0) { 743 brdctl = BRDRW_ULTRA2; 744 } else { 745 brdctl = BRDRW|BRDCS; 746 } 747 ahc_outb(ahc, BRDCTL, brdctl); 748 ahc_flush_device_writes(ahc); 749 value = ahc_inb(ahc, BRDCTL); 750 ahc_outb(ahc, BRDCTL, 0); 751 return (value); 752 } 753 754 static int 755 verify_seeprom_cksum(struct seeprom_config *sc) 756 { 757 int i; 758 int maxaddr; 759 uint32_t checksum; 760 uint16_t *scarray; 761 762 maxaddr = (sizeof(*sc)/2) - 1; 763 checksum = 0; 764 scarray = (uint16_t *)sc; 765 766 for (i = 0; i < maxaddr; i++) 767 checksum = checksum + scarray[i]; 768 if (checksum == 0 769 || (checksum & 0xFFFF) != sc->checksum) { 770 return (0); 771 } else { 772 return(1); 773 } 774 } 775