1 /* 2 * Device driver for the SYMBIOS/LSILOGIC 53C8XX and 53C1010 family 3 * of PCI-SCSI IO processors. 4 * 5 * Copyright (C) 1999-2001 Gerard Roudier <groudier@free.fr> 6 * 7 * This driver is derived from the Linux sym53c8xx driver. 8 * Copyright (C) 1998-2000 Gerard Roudier 9 * 10 * The sym53c8xx driver is derived from the ncr53c8xx driver that had been 11 * a port of the FreeBSD ncr driver to Linux-1.2.13. 12 * 13 * The original ncr driver has been written for 386bsd and FreeBSD by 14 * Wolfgang Stanglmeier <wolf@cologne.de> 15 * Stefan Esser <se@mi.Uni-Koeln.de> 16 * Copyright (C) 1994 Wolfgang Stanglmeier 17 * 18 * Other major contributions: 19 * 20 * NVRAM detection and reading. 21 * Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk> 22 * 23 *----------------------------------------------------------------------------- 24 * 25 * This program is free software; you can redistribute it and/or modify 26 * it under the terms of the GNU General Public License as published by 27 * the Free Software Foundation; either version 2 of the License, or 28 * (at your option) any later version. 29 * 30 * This program is distributed in the hope that it will be useful, 31 * but WITHOUT ANY WARRANTY; without even the implied warranty of 32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 33 * GNU General Public License for more details. 34 * 35 * You should have received a copy of the GNU General Public License 36 * along with this program; if not, write to the Free Software 37 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 38 */ 39 40 #include "sym_glue.h" 41 #include "sym_nvram.h" 42 43 #ifdef SYM_CONF_DEBUG_NVRAM 44 static u_char Tekram_boot_delay[7] = {3, 5, 10, 20, 30, 60, 120}; 45 #endif 46 47 /* 48 * Get host setup from NVRAM. 49 */ 50 void sym_nvram_setup_host(struct Scsi_Host *shost, struct sym_hcb *np, struct sym_nvram *nvram) 51 { 52 /* 53 * Get parity checking, host ID, verbose mode 54 * and miscellaneous host flags from NVRAM. 55 */ 56 switch (nvram->type) { 57 case SYM_SYMBIOS_NVRAM: 58 if (!(nvram->data.Symbios.flags & SYMBIOS_PARITY_ENABLE)) 59 np->rv_scntl0 &= ~0x0a; 60 np->myaddr = nvram->data.Symbios.host_id & 0x0f; 61 if (nvram->data.Symbios.flags & SYMBIOS_VERBOSE_MSGS) 62 np->verbose += 1; 63 if (nvram->data.Symbios.flags1 & SYMBIOS_SCAN_HI_LO) 64 shost->reverse_ordering = 1; 65 if (nvram->data.Symbios.flags2 & SYMBIOS_AVOID_BUS_RESET) 66 np->usrflags |= SYM_AVOID_BUS_RESET; 67 break; 68 case SYM_TEKRAM_NVRAM: 69 np->myaddr = nvram->data.Tekram.host_id & 0x0f; 70 break; 71 #ifdef CONFIG_PARISC 72 case SYM_PARISC_PDC: 73 if (nvram->data.parisc.host_id != -1) 74 np->myaddr = nvram->data.parisc.host_id; 75 if (nvram->data.parisc.factor != -1) 76 np->minsync = nvram->data.parisc.factor; 77 if (nvram->data.parisc.width != -1) 78 np->maxwide = nvram->data.parisc.width; 79 switch (nvram->data.parisc.mode) { 80 case 0: np->scsi_mode = SMODE_SE; break; 81 case 1: np->scsi_mode = SMODE_HVD; break; 82 case 2: np->scsi_mode = SMODE_LVD; break; 83 default: break; 84 } 85 #endif 86 default: 87 break; 88 } 89 } 90 91 /* 92 * Get target set-up from Symbios format NVRAM. 93 */ 94 static void 95 sym_Symbios_setup_target(struct sym_hcb *np, int target, Symbios_nvram *nvram) 96 { 97 struct sym_tcb *tp = &np->target[target]; 98 Symbios_target *tn = &nvram->target[target]; 99 100 tp->usrtags = 101 (tn->flags & SYMBIOS_QUEUE_TAGS_ENABLED)? SYM_SETUP_MAX_TAG : 0; 102 103 if (!(tn->flags & SYMBIOS_DISCONNECT_ENABLE)) 104 tp->usrflags &= ~SYM_DISC_ENABLED; 105 if (!(tn->flags & SYMBIOS_SCAN_AT_BOOT_TIME)) 106 tp->usrflags |= SYM_SCAN_BOOT_DISABLED; 107 if (!(tn->flags & SYMBIOS_SCAN_LUNS)) 108 tp->usrflags |= SYM_SCAN_LUNS_DISABLED; 109 } 110 111 /* 112 * Get target set-up from Tekram format NVRAM. 113 */ 114 static void 115 sym_Tekram_setup_target(struct sym_hcb *np, int target, Tekram_nvram *nvram) 116 { 117 struct sym_tcb *tp = &np->target[target]; 118 struct Tekram_target *tn = &nvram->target[target]; 119 120 if (tn->flags & TEKRAM_TAGGED_COMMANDS) { 121 tp->usrtags = 2 << nvram->max_tags_index; 122 } 123 124 if (tn->flags & TEKRAM_DISCONNECT_ENABLE) 125 tp->usrflags |= SYM_DISC_ENABLED; 126 127 /* If any device does not support parity, we will not use this option */ 128 if (!(tn->flags & TEKRAM_PARITY_CHECK)) 129 np->rv_scntl0 &= ~0x0a; /* SCSI parity checking disabled */ 130 } 131 132 /* 133 * Get target setup from NVRAM. 134 */ 135 void sym_nvram_setup_target(struct sym_hcb *np, int target, struct sym_nvram *nvp) 136 { 137 switch (nvp->type) { 138 case SYM_SYMBIOS_NVRAM: 139 sym_Symbios_setup_target(np, target, &nvp->data.Symbios); 140 break; 141 case SYM_TEKRAM_NVRAM: 142 sym_Tekram_setup_target(np, target, &nvp->data.Tekram); 143 break; 144 default: 145 break; 146 } 147 } 148 149 #ifdef SYM_CONF_DEBUG_NVRAM 150 /* 151 * Dump Symbios format NVRAM for debugging purpose. 152 */ 153 static void sym_display_Symbios_nvram(struct sym_device *np, Symbios_nvram *nvram) 154 { 155 int i; 156 157 /* display Symbios nvram host data */ 158 printf("%s: HOST ID=%d%s%s%s%s%s%s\n", 159 sym_name(np), nvram->host_id & 0x0f, 160 (nvram->flags & SYMBIOS_SCAM_ENABLE) ? " SCAM" :"", 161 (nvram->flags & SYMBIOS_PARITY_ENABLE) ? " PARITY" :"", 162 (nvram->flags & SYMBIOS_VERBOSE_MSGS) ? " VERBOSE" :"", 163 (nvram->flags & SYMBIOS_CHS_MAPPING) ? " CHS_ALT" :"", 164 (nvram->flags2 & SYMBIOS_AVOID_BUS_RESET)?" NO_RESET" :"", 165 (nvram->flags1 & SYMBIOS_SCAN_HI_LO) ? " HI_LO" :""); 166 167 /* display Symbios nvram drive data */ 168 for (i = 0 ; i < 15 ; i++) { 169 struct Symbios_target *tn = &nvram->target[i]; 170 printf("%s-%d:%s%s%s%s WIDTH=%d SYNC=%d TMO=%d\n", 171 sym_name(np), i, 172 (tn->flags & SYMBIOS_DISCONNECT_ENABLE) ? " DISC" : "", 173 (tn->flags & SYMBIOS_SCAN_AT_BOOT_TIME) ? " SCAN_BOOT" : "", 174 (tn->flags & SYMBIOS_SCAN_LUNS) ? " SCAN_LUNS" : "", 175 (tn->flags & SYMBIOS_QUEUE_TAGS_ENABLED)? " TCQ" : "", 176 tn->bus_width, 177 tn->sync_period / 4, 178 tn->timeout); 179 } 180 } 181 182 /* 183 * Dump TEKRAM format NVRAM for debugging purpose. 184 */ 185 static void sym_display_Tekram_nvram(struct sym_device *np, Tekram_nvram *nvram) 186 { 187 int i, tags, boot_delay; 188 char *rem; 189 190 /* display Tekram nvram host data */ 191 tags = 2 << nvram->max_tags_index; 192 boot_delay = 0; 193 if (nvram->boot_delay_index < 6) 194 boot_delay = Tekram_boot_delay[nvram->boot_delay_index]; 195 switch ((nvram->flags & TEKRAM_REMOVABLE_FLAGS) >> 6) { 196 default: 197 case 0: rem = ""; break; 198 case 1: rem = " REMOVABLE=boot device"; break; 199 case 2: rem = " REMOVABLE=all"; break; 200 } 201 202 printf("%s: HOST ID=%d%s%s%s%s%s%s%s%s%s BOOT DELAY=%d tags=%d\n", 203 sym_name(np), nvram->host_id & 0x0f, 204 (nvram->flags1 & SYMBIOS_SCAM_ENABLE) ? " SCAM" :"", 205 (nvram->flags & TEKRAM_MORE_THAN_2_DRIVES) ? " >2DRIVES":"", 206 (nvram->flags & TEKRAM_DRIVES_SUP_1GB) ? " >1GB" :"", 207 (nvram->flags & TEKRAM_RESET_ON_POWER_ON) ? " RESET" :"", 208 (nvram->flags & TEKRAM_ACTIVE_NEGATION) ? " ACT_NEG" :"", 209 (nvram->flags & TEKRAM_IMMEDIATE_SEEK) ? " IMM_SEEK" :"", 210 (nvram->flags & TEKRAM_SCAN_LUNS) ? " SCAN_LUNS" :"", 211 (nvram->flags1 & TEKRAM_F2_F6_ENABLED) ? " F2_F6" :"", 212 rem, boot_delay, tags); 213 214 /* display Tekram nvram drive data */ 215 for (i = 0; i <= 15; i++) { 216 int sync, j; 217 struct Tekram_target *tn = &nvram->target[i]; 218 j = tn->sync_index & 0xf; 219 sync = Tekram_sync[j]; 220 printf("%s-%d:%s%s%s%s%s%s PERIOD=%d\n", 221 sym_name(np), i, 222 (tn->flags & TEKRAM_PARITY_CHECK) ? " PARITY" : "", 223 (tn->flags & TEKRAM_SYNC_NEGO) ? " SYNC" : "", 224 (tn->flags & TEKRAM_DISCONNECT_ENABLE) ? " DISC" : "", 225 (tn->flags & TEKRAM_START_CMD) ? " START" : "", 226 (tn->flags & TEKRAM_TAGGED_COMMANDS) ? " TCQ" : "", 227 (tn->flags & TEKRAM_WIDE_NEGO) ? " WIDE" : "", 228 sync); 229 } 230 } 231 #else 232 static void sym_display_Symbios_nvram(struct sym_device *np, Symbios_nvram *nvram) { (void)np; (void)nvram; } 233 static void sym_display_Tekram_nvram(struct sym_device *np, Tekram_nvram *nvram) { (void)np; (void)nvram; } 234 #endif /* SYM_CONF_DEBUG_NVRAM */ 235 236 237 /* 238 * 24C16 EEPROM reading. 239 * 240 * GPOI0 - data in/data out 241 * GPIO1 - clock 242 * Symbios NVRAM wiring now also used by Tekram. 243 */ 244 245 #define SET_BIT 0 246 #define CLR_BIT 1 247 #define SET_CLK 2 248 #define CLR_CLK 3 249 250 /* 251 * Set/clear data/clock bit in GPIO0 252 */ 253 static void S24C16_set_bit(struct sym_device *np, u_char write_bit, u_char *gpreg, 254 int bit_mode) 255 { 256 udelay(5); 257 switch (bit_mode) { 258 case SET_BIT: 259 *gpreg |= write_bit; 260 break; 261 case CLR_BIT: 262 *gpreg &= 0xfe; 263 break; 264 case SET_CLK: 265 *gpreg |= 0x02; 266 break; 267 case CLR_CLK: 268 *gpreg &= 0xfd; 269 break; 270 271 } 272 OUTB(np, nc_gpreg, *gpreg); 273 INB(np, nc_mbox1); 274 udelay(5); 275 } 276 277 /* 278 * Send START condition to NVRAM to wake it up. 279 */ 280 static void S24C16_start(struct sym_device *np, u_char *gpreg) 281 { 282 S24C16_set_bit(np, 1, gpreg, SET_BIT); 283 S24C16_set_bit(np, 0, gpreg, SET_CLK); 284 S24C16_set_bit(np, 0, gpreg, CLR_BIT); 285 S24C16_set_bit(np, 0, gpreg, CLR_CLK); 286 } 287 288 /* 289 * Send STOP condition to NVRAM - puts NVRAM to sleep... ZZzzzz!! 290 */ 291 static void S24C16_stop(struct sym_device *np, u_char *gpreg) 292 { 293 S24C16_set_bit(np, 0, gpreg, SET_CLK); 294 S24C16_set_bit(np, 1, gpreg, SET_BIT); 295 } 296 297 /* 298 * Read or write a bit to the NVRAM, 299 * read if GPIO0 input else write if GPIO0 output 300 */ 301 static void S24C16_do_bit(struct sym_device *np, u_char *read_bit, u_char write_bit, 302 u_char *gpreg) 303 { 304 S24C16_set_bit(np, write_bit, gpreg, SET_BIT); 305 S24C16_set_bit(np, 0, gpreg, SET_CLK); 306 if (read_bit) 307 *read_bit = INB(np, nc_gpreg); 308 S24C16_set_bit(np, 0, gpreg, CLR_CLK); 309 S24C16_set_bit(np, 0, gpreg, CLR_BIT); 310 } 311 312 /* 313 * Output an ACK to the NVRAM after reading, 314 * change GPIO0 to output and when done back to an input 315 */ 316 static void S24C16_write_ack(struct sym_device *np, u_char write_bit, u_char *gpreg, 317 u_char *gpcntl) 318 { 319 OUTB(np, nc_gpcntl, *gpcntl & 0xfe); 320 S24C16_do_bit(np, NULL, write_bit, gpreg); 321 OUTB(np, nc_gpcntl, *gpcntl); 322 } 323 324 /* 325 * Input an ACK from NVRAM after writing, 326 * change GPIO0 to input and when done back to an output 327 */ 328 static void S24C16_read_ack(struct sym_device *np, u_char *read_bit, u_char *gpreg, 329 u_char *gpcntl) 330 { 331 OUTB(np, nc_gpcntl, *gpcntl | 0x01); 332 S24C16_do_bit(np, read_bit, 1, gpreg); 333 OUTB(np, nc_gpcntl, *gpcntl); 334 } 335 336 /* 337 * WRITE a byte to the NVRAM and then get an ACK to see it was accepted OK, 338 * GPIO0 must already be set as an output 339 */ 340 static void S24C16_write_byte(struct sym_device *np, u_char *ack_data, u_char write_data, 341 u_char *gpreg, u_char *gpcntl) 342 { 343 int x; 344 345 for (x = 0; x < 8; x++) 346 S24C16_do_bit(np, NULL, (write_data >> (7 - x)) & 0x01, gpreg); 347 348 S24C16_read_ack(np, ack_data, gpreg, gpcntl); 349 } 350 351 /* 352 * READ a byte from the NVRAM and then send an ACK to say we have got it, 353 * GPIO0 must already be set as an input 354 */ 355 static void S24C16_read_byte(struct sym_device *np, u_char *read_data, u_char ack_data, 356 u_char *gpreg, u_char *gpcntl) 357 { 358 int x; 359 u_char read_bit; 360 361 *read_data = 0; 362 for (x = 0; x < 8; x++) { 363 S24C16_do_bit(np, &read_bit, 1, gpreg); 364 *read_data |= ((read_bit & 0x01) << (7 - x)); 365 } 366 367 S24C16_write_ack(np, ack_data, gpreg, gpcntl); 368 } 369 370 #if SYM_CONF_NVRAM_WRITE_SUPPORT 371 /* 372 * Write 'len' bytes starting at 'offset'. 373 */ 374 static int sym_write_S24C16_nvram(struct sym_device *np, int offset, 375 u_char *data, int len) 376 { 377 u_char gpcntl, gpreg; 378 u_char old_gpcntl, old_gpreg; 379 u_char ack_data; 380 int x; 381 382 /* save current state of GPCNTL and GPREG */ 383 old_gpreg = INB(np, nc_gpreg); 384 old_gpcntl = INB(np, nc_gpcntl); 385 gpcntl = old_gpcntl & 0x1c; 386 387 /* set up GPREG & GPCNTL to set GPIO0 and GPIO1 in to known state */ 388 OUTB(np, nc_gpreg, old_gpreg); 389 OUTB(np, nc_gpcntl, gpcntl); 390 391 /* this is to set NVRAM into a known state with GPIO0/1 both low */ 392 gpreg = old_gpreg; 393 S24C16_set_bit(np, 0, &gpreg, CLR_CLK); 394 S24C16_set_bit(np, 0, &gpreg, CLR_BIT); 395 396 /* now set NVRAM inactive with GPIO0/1 both high */ 397 S24C16_stop(np, &gpreg); 398 399 /* NVRAM has to be written in segments of 16 bytes */ 400 for (x = 0; x < len ; x += 16) { 401 do { 402 S24C16_start(np, &gpreg); 403 S24C16_write_byte(np, &ack_data, 404 0xa0 | (((offset+x) >> 7) & 0x0e), 405 &gpreg, &gpcntl); 406 } while (ack_data & 0x01); 407 408 S24C16_write_byte(np, &ack_data, (offset+x) & 0xff, 409 &gpreg, &gpcntl); 410 411 for (y = 0; y < 16; y++) 412 S24C16_write_byte(np, &ack_data, data[x+y], 413 &gpreg, &gpcntl); 414 S24C16_stop(np, &gpreg); 415 } 416 417 /* return GPIO0/1 to original states after having accessed NVRAM */ 418 OUTB(np, nc_gpcntl, old_gpcntl); 419 OUTB(np, nc_gpreg, old_gpreg); 420 421 return 0; 422 } 423 #endif /* SYM_CONF_NVRAM_WRITE_SUPPORT */ 424 425 /* 426 * Read 'len' bytes starting at 'offset'. 427 */ 428 static int sym_read_S24C16_nvram(struct sym_device *np, int offset, u_char *data, int len) 429 { 430 u_char gpcntl, gpreg; 431 u_char old_gpcntl, old_gpreg; 432 u_char ack_data; 433 int retv = 1; 434 int x; 435 436 /* save current state of GPCNTL and GPREG */ 437 old_gpreg = INB(np, nc_gpreg); 438 old_gpcntl = INB(np, nc_gpcntl); 439 gpcntl = old_gpcntl & 0x1c; 440 441 /* set up GPREG & GPCNTL to set GPIO0 and GPIO1 in to known state */ 442 OUTB(np, nc_gpreg, old_gpreg); 443 OUTB(np, nc_gpcntl, gpcntl); 444 445 /* this is to set NVRAM into a known state with GPIO0/1 both low */ 446 gpreg = old_gpreg; 447 S24C16_set_bit(np, 0, &gpreg, CLR_CLK); 448 S24C16_set_bit(np, 0, &gpreg, CLR_BIT); 449 450 /* now set NVRAM inactive with GPIO0/1 both high */ 451 S24C16_stop(np, &gpreg); 452 453 /* activate NVRAM */ 454 S24C16_start(np, &gpreg); 455 456 /* write device code and random address MSB */ 457 S24C16_write_byte(np, &ack_data, 458 0xa0 | ((offset >> 7) & 0x0e), &gpreg, &gpcntl); 459 if (ack_data & 0x01) 460 goto out; 461 462 /* write random address LSB */ 463 S24C16_write_byte(np, &ack_data, 464 offset & 0xff, &gpreg, &gpcntl); 465 if (ack_data & 0x01) 466 goto out; 467 468 /* regenerate START state to set up for reading */ 469 S24C16_start(np, &gpreg); 470 471 /* rewrite device code and address MSB with read bit set (lsb = 0x01) */ 472 S24C16_write_byte(np, &ack_data, 473 0xa1 | ((offset >> 7) & 0x0e), &gpreg, &gpcntl); 474 if (ack_data & 0x01) 475 goto out; 476 477 /* now set up GPIO0 for inputting data */ 478 gpcntl |= 0x01; 479 OUTB(np, nc_gpcntl, gpcntl); 480 481 /* input all requested data - only part of total NVRAM */ 482 for (x = 0; x < len; x++) 483 S24C16_read_byte(np, &data[x], (x == (len-1)), &gpreg, &gpcntl); 484 485 /* finally put NVRAM back in inactive mode */ 486 gpcntl &= 0xfe; 487 OUTB(np, nc_gpcntl, gpcntl); 488 S24C16_stop(np, &gpreg); 489 retv = 0; 490 out: 491 /* return GPIO0/1 to original states after having accessed NVRAM */ 492 OUTB(np, nc_gpcntl, old_gpcntl); 493 OUTB(np, nc_gpreg, old_gpreg); 494 495 return retv; 496 } 497 498 #undef SET_BIT 499 #undef CLR_BIT 500 #undef SET_CLK 501 #undef CLR_CLK 502 503 /* 504 * Try reading Symbios NVRAM. 505 * Return 0 if OK. 506 */ 507 static int sym_read_Symbios_nvram(struct sym_device *np, Symbios_nvram *nvram) 508 { 509 static u_char Symbios_trailer[6] = {0xfe, 0xfe, 0, 0, 0, 0}; 510 u_char *data = (u_char *) nvram; 511 int len = sizeof(*nvram); 512 u_short csum; 513 int x; 514 515 /* probe the 24c16 and read the SYMBIOS 24c16 area */ 516 if (sym_read_S24C16_nvram (np, SYMBIOS_NVRAM_ADDRESS, data, len)) 517 return 1; 518 519 /* check valid NVRAM signature, verify byte count and checksum */ 520 if (nvram->type != 0 || 521 memcmp(nvram->trailer, Symbios_trailer, 6) || 522 nvram->byte_count != len - 12) 523 return 1; 524 525 /* verify checksum */ 526 for (x = 6, csum = 0; x < len - 6; x++) 527 csum += data[x]; 528 if (csum != nvram->checksum) 529 return 1; 530 531 return 0; 532 } 533 534 /* 535 * 93C46 EEPROM reading. 536 * 537 * GPOI0 - data in 538 * GPIO1 - data out 539 * GPIO2 - clock 540 * GPIO4 - chip select 541 * 542 * Used by Tekram. 543 */ 544 545 /* 546 * Pulse clock bit in GPIO0 547 */ 548 static void T93C46_Clk(struct sym_device *np, u_char *gpreg) 549 { 550 OUTB(np, nc_gpreg, *gpreg | 0x04); 551 INB(np, nc_mbox1); 552 udelay(2); 553 OUTB(np, nc_gpreg, *gpreg); 554 } 555 556 /* 557 * Read bit from NVRAM 558 */ 559 static void T93C46_Read_Bit(struct sym_device *np, u_char *read_bit, u_char *gpreg) 560 { 561 udelay(2); 562 T93C46_Clk(np, gpreg); 563 *read_bit = INB(np, nc_gpreg); 564 } 565 566 /* 567 * Write bit to GPIO0 568 */ 569 static void T93C46_Write_Bit(struct sym_device *np, u_char write_bit, u_char *gpreg) 570 { 571 if (write_bit & 0x01) 572 *gpreg |= 0x02; 573 else 574 *gpreg &= 0xfd; 575 576 *gpreg |= 0x10; 577 578 OUTB(np, nc_gpreg, *gpreg); 579 INB(np, nc_mbox1); 580 udelay(2); 581 582 T93C46_Clk(np, gpreg); 583 } 584 585 /* 586 * Send STOP condition to NVRAM - puts NVRAM to sleep... ZZZzzz!! 587 */ 588 static void T93C46_Stop(struct sym_device *np, u_char *gpreg) 589 { 590 *gpreg &= 0xef; 591 OUTB(np, nc_gpreg, *gpreg); 592 INB(np, nc_mbox1); 593 udelay(2); 594 595 T93C46_Clk(np, gpreg); 596 } 597 598 /* 599 * Send read command and address to NVRAM 600 */ 601 static void T93C46_Send_Command(struct sym_device *np, u_short write_data, 602 u_char *read_bit, u_char *gpreg) 603 { 604 int x; 605 606 /* send 9 bits, start bit (1), command (2), address (6) */ 607 for (x = 0; x < 9; x++) 608 T93C46_Write_Bit(np, (u_char) (write_data >> (8 - x)), gpreg); 609 610 *read_bit = INB(np, nc_gpreg); 611 } 612 613 /* 614 * READ 2 bytes from the NVRAM 615 */ 616 static void T93C46_Read_Word(struct sym_device *np, 617 unsigned short *nvram_data, unsigned char *gpreg) 618 { 619 int x; 620 u_char read_bit; 621 622 *nvram_data = 0; 623 for (x = 0; x < 16; x++) { 624 T93C46_Read_Bit(np, &read_bit, gpreg); 625 626 if (read_bit & 0x01) 627 *nvram_data |= (0x01 << (15 - x)); 628 else 629 *nvram_data &= ~(0x01 << (15 - x)); 630 } 631 } 632 633 /* 634 * Read Tekram NvRAM data. 635 */ 636 static int T93C46_Read_Data(struct sym_device *np, unsigned short *data, 637 int len, unsigned char *gpreg) 638 { 639 int x; 640 641 for (x = 0; x < len; x++) { 642 unsigned char read_bit; 643 /* output read command and address */ 644 T93C46_Send_Command(np, 0x180 | x, &read_bit, gpreg); 645 if (read_bit & 0x01) 646 return 1; /* Bad */ 647 T93C46_Read_Word(np, &data[x], gpreg); 648 T93C46_Stop(np, gpreg); 649 } 650 651 return 0; 652 } 653 654 /* 655 * Try reading 93C46 Tekram NVRAM. 656 */ 657 static int sym_read_T93C46_nvram(struct sym_device *np, Tekram_nvram *nvram) 658 { 659 u_char gpcntl, gpreg; 660 u_char old_gpcntl, old_gpreg; 661 int retv = 1; 662 663 /* save current state of GPCNTL and GPREG */ 664 old_gpreg = INB(np, nc_gpreg); 665 old_gpcntl = INB(np, nc_gpcntl); 666 667 /* set up GPREG & GPCNTL to set GPIO0/1/2/4 in to known state, 0 in, 668 1/2/4 out */ 669 gpreg = old_gpreg & 0xe9; 670 OUTB(np, nc_gpreg, gpreg); 671 gpcntl = (old_gpcntl & 0xe9) | 0x09; 672 OUTB(np, nc_gpcntl, gpcntl); 673 674 /* input all of NVRAM, 64 words */ 675 retv = T93C46_Read_Data(np, (u_short *) nvram, 676 sizeof(*nvram) / sizeof(short), &gpreg); 677 678 /* return GPIO0/1/2/4 to original states after having accessed NVRAM */ 679 OUTB(np, nc_gpcntl, old_gpcntl); 680 OUTB(np, nc_gpreg, old_gpreg); 681 682 return retv; 683 } 684 685 /* 686 * Try reading Tekram NVRAM. 687 * Return 0 if OK. 688 */ 689 static int sym_read_Tekram_nvram (struct sym_device *np, Tekram_nvram *nvram) 690 { 691 u_char *data = (u_char *) nvram; 692 int len = sizeof(*nvram); 693 u_short csum; 694 int x; 695 696 switch (np->device_id) { 697 case PCI_DEVICE_ID_NCR_53C885: 698 case PCI_DEVICE_ID_NCR_53C895: 699 case PCI_DEVICE_ID_NCR_53C896: 700 x = sym_read_S24C16_nvram(np, TEKRAM_24C16_NVRAM_ADDRESS, 701 data, len); 702 break; 703 case PCI_DEVICE_ID_NCR_53C875: 704 x = sym_read_S24C16_nvram(np, TEKRAM_24C16_NVRAM_ADDRESS, 705 data, len); 706 if (!x) 707 break; 708 default: 709 x = sym_read_T93C46_nvram(np, nvram); 710 break; 711 } 712 if (x) 713 return 1; 714 715 /* verify checksum */ 716 for (x = 0, csum = 0; x < len - 1; x += 2) 717 csum += data[x] + (data[x+1] << 8); 718 if (csum != 0x1234) 719 return 1; 720 721 return 0; 722 } 723 724 #ifdef CONFIG_PARISC 725 /* 726 * Host firmware (PDC) keeps a table for altering SCSI capabilities. 727 * Many newer machines export one channel of 53c896 chip as SE, 50-pin HD. 728 * Also used for Multi-initiator SCSI clusters to set the SCSI Initiator ID. 729 */ 730 static int sym_read_parisc_pdc(struct sym_device *np, struct pdc_initiator *pdc) 731 { 732 struct hardware_path hwpath; 733 get_pci_node_path(np->pdev, &hwpath); 734 if (!pdc_get_initiator(&hwpath, pdc)) 735 return 0; 736 737 return SYM_PARISC_PDC; 738 } 739 #else 740 static inline int sym_read_parisc_pdc(struct sym_device *np, 741 struct pdc_initiator *x) 742 { 743 return 0; 744 } 745 #endif 746 747 /* 748 * Try reading Symbios or Tekram NVRAM 749 */ 750 int sym_read_nvram(struct sym_device *np, struct sym_nvram *nvp) 751 { 752 if (!sym_read_Symbios_nvram(np, &nvp->data.Symbios)) { 753 nvp->type = SYM_SYMBIOS_NVRAM; 754 sym_display_Symbios_nvram(np, &nvp->data.Symbios); 755 } else if (!sym_read_Tekram_nvram(np, &nvp->data.Tekram)) { 756 nvp->type = SYM_TEKRAM_NVRAM; 757 sym_display_Tekram_nvram(np, &nvp->data.Tekram); 758 } else { 759 nvp->type = sym_read_parisc_pdc(np, &nvp->data.parisc); 760 } 761 return nvp->type; 762 } 763 764 char *sym_nvram_type(struct sym_nvram *nvp) 765 { 766 switch (nvp->type) { 767 case SYM_SYMBIOS_NVRAM: 768 return "Symbios NVRAM"; 769 case SYM_TEKRAM_NVRAM: 770 return "Tekram NVRAM"; 771 case SYM_PARISC_PDC: 772 return "PA-RISC Firmware"; 773 default: 774 return "No NVRAM"; 775 } 776 } 777