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 udelay(5); 274 } 275 276 /* 277 * Send START condition to NVRAM to wake it up. 278 */ 279 static void S24C16_start(struct sym_device *np, u_char *gpreg) 280 { 281 S24C16_set_bit(np, 1, gpreg, SET_BIT); 282 S24C16_set_bit(np, 0, gpreg, SET_CLK); 283 S24C16_set_bit(np, 0, gpreg, CLR_BIT); 284 S24C16_set_bit(np, 0, gpreg, CLR_CLK); 285 } 286 287 /* 288 * Send STOP condition to NVRAM - puts NVRAM to sleep... ZZzzzz!! 289 */ 290 static void S24C16_stop(struct sym_device *np, u_char *gpreg) 291 { 292 S24C16_set_bit(np, 0, gpreg, SET_CLK); 293 S24C16_set_bit(np, 1, gpreg, SET_BIT); 294 } 295 296 /* 297 * Read or write a bit to the NVRAM, 298 * read if GPIO0 input else write if GPIO0 output 299 */ 300 static void S24C16_do_bit(struct sym_device *np, u_char *read_bit, u_char write_bit, 301 u_char *gpreg) 302 { 303 S24C16_set_bit(np, write_bit, gpreg, SET_BIT); 304 S24C16_set_bit(np, 0, gpreg, SET_CLK); 305 if (read_bit) 306 *read_bit = INB(np, nc_gpreg); 307 S24C16_set_bit(np, 0, gpreg, CLR_CLK); 308 S24C16_set_bit(np, 0, gpreg, CLR_BIT); 309 } 310 311 /* 312 * Output an ACK to the NVRAM after reading, 313 * change GPIO0 to output and when done back to an input 314 */ 315 static void S24C16_write_ack(struct sym_device *np, u_char write_bit, u_char *gpreg, 316 u_char *gpcntl) 317 { 318 OUTB(np, nc_gpcntl, *gpcntl & 0xfe); 319 S24C16_do_bit(np, NULL, write_bit, gpreg); 320 OUTB(np, nc_gpcntl, *gpcntl); 321 } 322 323 /* 324 * Input an ACK from NVRAM after writing, 325 * change GPIO0 to input and when done back to an output 326 */ 327 static void S24C16_read_ack(struct sym_device *np, u_char *read_bit, u_char *gpreg, 328 u_char *gpcntl) 329 { 330 OUTB(np, nc_gpcntl, *gpcntl | 0x01); 331 S24C16_do_bit(np, read_bit, 1, gpreg); 332 OUTB(np, nc_gpcntl, *gpcntl); 333 } 334 335 /* 336 * WRITE a byte to the NVRAM and then get an ACK to see it was accepted OK, 337 * GPIO0 must already be set as an output 338 */ 339 static void S24C16_write_byte(struct sym_device *np, u_char *ack_data, u_char write_data, 340 u_char *gpreg, u_char *gpcntl) 341 { 342 int x; 343 344 for (x = 0; x < 8; x++) 345 S24C16_do_bit(np, NULL, (write_data >> (7 - x)) & 0x01, gpreg); 346 347 S24C16_read_ack(np, ack_data, gpreg, gpcntl); 348 } 349 350 /* 351 * READ a byte from the NVRAM and then send an ACK to say we have got it, 352 * GPIO0 must already be set as an input 353 */ 354 static void S24C16_read_byte(struct sym_device *np, u_char *read_data, u_char ack_data, 355 u_char *gpreg, u_char *gpcntl) 356 { 357 int x; 358 u_char read_bit; 359 360 *read_data = 0; 361 for (x = 0; x < 8; x++) { 362 S24C16_do_bit(np, &read_bit, 1, gpreg); 363 *read_data |= ((read_bit & 0x01) << (7 - x)); 364 } 365 366 S24C16_write_ack(np, ack_data, gpreg, gpcntl); 367 } 368 369 #if SYM_CONF_NVRAM_WRITE_SUPPORT 370 /* 371 * Write 'len' bytes starting at 'offset'. 372 */ 373 static int sym_write_S24C16_nvram(struct sym_device *np, int offset, 374 u_char *data, int len) 375 { 376 u_char gpcntl, gpreg; 377 u_char old_gpcntl, old_gpreg; 378 u_char ack_data; 379 int x; 380 381 /* save current state of GPCNTL and GPREG */ 382 old_gpreg = INB(np, nc_gpreg); 383 old_gpcntl = INB(np, nc_gpcntl); 384 gpcntl = old_gpcntl & 0x1c; 385 386 /* set up GPREG & GPCNTL to set GPIO0 and GPIO1 in to known state */ 387 OUTB(np, nc_gpreg, old_gpreg); 388 OUTB(np, nc_gpcntl, gpcntl); 389 390 /* this is to set NVRAM into a known state with GPIO0/1 both low */ 391 gpreg = old_gpreg; 392 S24C16_set_bit(np, 0, &gpreg, CLR_CLK); 393 S24C16_set_bit(np, 0, &gpreg, CLR_BIT); 394 395 /* now set NVRAM inactive with GPIO0/1 both high */ 396 S24C16_stop(np, &gpreg); 397 398 /* NVRAM has to be written in segments of 16 bytes */ 399 for (x = 0; x < len ; x += 16) { 400 do { 401 S24C16_start(np, &gpreg); 402 S24C16_write_byte(np, &ack_data, 403 0xa0 | (((offset+x) >> 7) & 0x0e), 404 &gpreg, &gpcntl); 405 } while (ack_data & 0x01); 406 407 S24C16_write_byte(np, &ack_data, (offset+x) & 0xff, 408 &gpreg, &gpcntl); 409 410 for (y = 0; y < 16; y++) 411 S24C16_write_byte(np, &ack_data, data[x+y], 412 &gpreg, &gpcntl); 413 S24C16_stop(np, &gpreg); 414 } 415 416 /* return GPIO0/1 to original states after having accessed NVRAM */ 417 OUTB(np, nc_gpcntl, old_gpcntl); 418 OUTB(np, nc_gpreg, old_gpreg); 419 420 return 0; 421 } 422 #endif /* SYM_CONF_NVRAM_WRITE_SUPPORT */ 423 424 /* 425 * Read 'len' bytes starting at 'offset'. 426 */ 427 static int sym_read_S24C16_nvram(struct sym_device *np, int offset, u_char *data, int len) 428 { 429 u_char gpcntl, gpreg; 430 u_char old_gpcntl, old_gpreg; 431 u_char ack_data; 432 int retv = 1; 433 int x; 434 435 /* save current state of GPCNTL and GPREG */ 436 old_gpreg = INB(np, nc_gpreg); 437 old_gpcntl = INB(np, nc_gpcntl); 438 gpcntl = old_gpcntl & 0x1c; 439 440 /* set up GPREG & GPCNTL to set GPIO0 and GPIO1 in to known state */ 441 OUTB(np, nc_gpreg, old_gpreg); 442 OUTB(np, nc_gpcntl, gpcntl); 443 444 /* this is to set NVRAM into a known state with GPIO0/1 both low */ 445 gpreg = old_gpreg; 446 S24C16_set_bit(np, 0, &gpreg, CLR_CLK); 447 S24C16_set_bit(np, 0, &gpreg, CLR_BIT); 448 449 /* now set NVRAM inactive with GPIO0/1 both high */ 450 S24C16_stop(np, &gpreg); 451 452 /* activate NVRAM */ 453 S24C16_start(np, &gpreg); 454 455 /* write device code and random address MSB */ 456 S24C16_write_byte(np, &ack_data, 457 0xa0 | ((offset >> 7) & 0x0e), &gpreg, &gpcntl); 458 if (ack_data & 0x01) 459 goto out; 460 461 /* write random address LSB */ 462 S24C16_write_byte(np, &ack_data, 463 offset & 0xff, &gpreg, &gpcntl); 464 if (ack_data & 0x01) 465 goto out; 466 467 /* regenerate START state to set up for reading */ 468 S24C16_start(np, &gpreg); 469 470 /* rewrite device code and address MSB with read bit set (lsb = 0x01) */ 471 S24C16_write_byte(np, &ack_data, 472 0xa1 | ((offset >> 7) & 0x0e), &gpreg, &gpcntl); 473 if (ack_data & 0x01) 474 goto out; 475 476 /* now set up GPIO0 for inputting data */ 477 gpcntl |= 0x01; 478 OUTB(np, nc_gpcntl, gpcntl); 479 480 /* input all requested data - only part of total NVRAM */ 481 for (x = 0; x < len; x++) 482 S24C16_read_byte(np, &data[x], (x == (len-1)), &gpreg, &gpcntl); 483 484 /* finally put NVRAM back in inactive mode */ 485 gpcntl &= 0xfe; 486 OUTB(np, nc_gpcntl, gpcntl); 487 S24C16_stop(np, &gpreg); 488 retv = 0; 489 out: 490 /* return GPIO0/1 to original states after having accessed NVRAM */ 491 OUTB(np, nc_gpcntl, old_gpcntl); 492 OUTB(np, nc_gpreg, old_gpreg); 493 494 return retv; 495 } 496 497 #undef SET_BIT 498 #undef CLR_BIT 499 #undef SET_CLK 500 #undef CLR_CLK 501 502 /* 503 * Try reading Symbios NVRAM. 504 * Return 0 if OK. 505 */ 506 static int sym_read_Symbios_nvram(struct sym_device *np, Symbios_nvram *nvram) 507 { 508 static u_char Symbios_trailer[6] = {0xfe, 0xfe, 0, 0, 0, 0}; 509 u_char *data = (u_char *) nvram; 510 int len = sizeof(*nvram); 511 u_short csum; 512 int x; 513 514 /* probe the 24c16 and read the SYMBIOS 24c16 area */ 515 if (sym_read_S24C16_nvram (np, SYMBIOS_NVRAM_ADDRESS, data, len)) 516 return 1; 517 518 /* check valid NVRAM signature, verify byte count and checksum */ 519 if (nvram->type != 0 || 520 memcmp(nvram->trailer, Symbios_trailer, 6) || 521 nvram->byte_count != len - 12) 522 return 1; 523 524 /* verify checksum */ 525 for (x = 6, csum = 0; x < len - 6; x++) 526 csum += data[x]; 527 if (csum != nvram->checksum) 528 return 1; 529 530 return 0; 531 } 532 533 /* 534 * 93C46 EEPROM reading. 535 * 536 * GPOI0 - data in 537 * GPIO1 - data out 538 * GPIO2 - clock 539 * GPIO4 - chip select 540 * 541 * Used by Tekram. 542 */ 543 544 /* 545 * Pulse clock bit in GPIO0 546 */ 547 static void T93C46_Clk(struct sym_device *np, u_char *gpreg) 548 { 549 OUTB(np, nc_gpreg, *gpreg | 0x04); 550 udelay(2); 551 OUTB(np, nc_gpreg, *gpreg); 552 } 553 554 /* 555 * Read bit from NVRAM 556 */ 557 static void T93C46_Read_Bit(struct sym_device *np, u_char *read_bit, u_char *gpreg) 558 { 559 udelay(2); 560 T93C46_Clk(np, gpreg); 561 *read_bit = INB(np, nc_gpreg); 562 } 563 564 /* 565 * Write bit to GPIO0 566 */ 567 static void T93C46_Write_Bit(struct sym_device *np, u_char write_bit, u_char *gpreg) 568 { 569 if (write_bit & 0x01) 570 *gpreg |= 0x02; 571 else 572 *gpreg &= 0xfd; 573 574 *gpreg |= 0x10; 575 576 OUTB(np, nc_gpreg, *gpreg); 577 udelay(2); 578 579 T93C46_Clk(np, gpreg); 580 } 581 582 /* 583 * Send STOP condition to NVRAM - puts NVRAM to sleep... ZZZzzz!! 584 */ 585 static void T93C46_Stop(struct sym_device *np, u_char *gpreg) 586 { 587 *gpreg &= 0xef; 588 OUTB(np, nc_gpreg, *gpreg); 589 udelay(2); 590 591 T93C46_Clk(np, gpreg); 592 } 593 594 /* 595 * Send read command and address to NVRAM 596 */ 597 static void T93C46_Send_Command(struct sym_device *np, u_short write_data, 598 u_char *read_bit, u_char *gpreg) 599 { 600 int x; 601 602 /* send 9 bits, start bit (1), command (2), address (6) */ 603 for (x = 0; x < 9; x++) 604 T93C46_Write_Bit(np, (u_char) (write_data >> (8 - x)), gpreg); 605 606 *read_bit = INB(np, nc_gpreg); 607 } 608 609 /* 610 * READ 2 bytes from the NVRAM 611 */ 612 static void T93C46_Read_Word(struct sym_device *np, 613 unsigned short *nvram_data, unsigned char *gpreg) 614 { 615 int x; 616 u_char read_bit; 617 618 *nvram_data = 0; 619 for (x = 0; x < 16; x++) { 620 T93C46_Read_Bit(np, &read_bit, gpreg); 621 622 if (read_bit & 0x01) 623 *nvram_data |= (0x01 << (15 - x)); 624 else 625 *nvram_data &= ~(0x01 << (15 - x)); 626 } 627 } 628 629 /* 630 * Read Tekram NvRAM data. 631 */ 632 static int T93C46_Read_Data(struct sym_device *np, unsigned short *data, 633 int len, unsigned char *gpreg) 634 { 635 int x; 636 637 for (x = 0; x < len; x++) { 638 unsigned char read_bit; 639 /* output read command and address */ 640 T93C46_Send_Command(np, 0x180 | x, &read_bit, gpreg); 641 if (read_bit & 0x01) 642 return 1; /* Bad */ 643 T93C46_Read_Word(np, &data[x], gpreg); 644 T93C46_Stop(np, gpreg); 645 } 646 647 return 0; 648 } 649 650 /* 651 * Try reading 93C46 Tekram NVRAM. 652 */ 653 static int sym_read_T93C46_nvram(struct sym_device *np, Tekram_nvram *nvram) 654 { 655 u_char gpcntl, gpreg; 656 u_char old_gpcntl, old_gpreg; 657 int retv = 1; 658 659 /* save current state of GPCNTL and GPREG */ 660 old_gpreg = INB(np, nc_gpreg); 661 old_gpcntl = INB(np, nc_gpcntl); 662 663 /* set up GPREG & GPCNTL to set GPIO0/1/2/4 in to known state, 0 in, 664 1/2/4 out */ 665 gpreg = old_gpreg & 0xe9; 666 OUTB(np, nc_gpreg, gpreg); 667 gpcntl = (old_gpcntl & 0xe9) | 0x09; 668 OUTB(np, nc_gpcntl, gpcntl); 669 670 /* input all of NVRAM, 64 words */ 671 retv = T93C46_Read_Data(np, (u_short *) nvram, 672 sizeof(*nvram) / sizeof(short), &gpreg); 673 674 /* return GPIO0/1/2/4 to original states after having accessed NVRAM */ 675 OUTB(np, nc_gpcntl, old_gpcntl); 676 OUTB(np, nc_gpreg, old_gpreg); 677 678 return retv; 679 } 680 681 /* 682 * Try reading Tekram NVRAM. 683 * Return 0 if OK. 684 */ 685 static int sym_read_Tekram_nvram (struct sym_device *np, Tekram_nvram *nvram) 686 { 687 u_char *data = (u_char *) nvram; 688 int len = sizeof(*nvram); 689 u_short csum; 690 int x; 691 692 switch (np->device_id) { 693 case PCI_DEVICE_ID_NCR_53C885: 694 case PCI_DEVICE_ID_NCR_53C895: 695 case PCI_DEVICE_ID_NCR_53C896: 696 x = sym_read_S24C16_nvram(np, TEKRAM_24C16_NVRAM_ADDRESS, 697 data, len); 698 break; 699 case PCI_DEVICE_ID_NCR_53C875: 700 x = sym_read_S24C16_nvram(np, TEKRAM_24C16_NVRAM_ADDRESS, 701 data, len); 702 if (!x) 703 break; 704 default: 705 x = sym_read_T93C46_nvram(np, nvram); 706 break; 707 } 708 if (x) 709 return 1; 710 711 /* verify checksum */ 712 for (x = 0, csum = 0; x < len - 1; x += 2) 713 csum += data[x] + (data[x+1] << 8); 714 if (csum != 0x1234) 715 return 1; 716 717 return 0; 718 } 719 720 #ifdef CONFIG_PARISC 721 /* 722 * Host firmware (PDC) keeps a table for altering SCSI capabilities. 723 * Many newer machines export one channel of 53c896 chip as SE, 50-pin HD. 724 * Also used for Multi-initiator SCSI clusters to set the SCSI Initiator ID. 725 */ 726 static int sym_read_parisc_pdc(struct sym_device *np, struct pdc_initiator *pdc) 727 { 728 struct hardware_path hwpath; 729 get_pci_node_path(np->pdev, &hwpath); 730 if (!pdc_get_initiator(&hwpath, pdc)) 731 return 0; 732 733 return SYM_PARISC_PDC; 734 } 735 #else 736 static int sym_read_parisc_pdc(struct sym_device *np, struct pdc_initiator *x) 737 { 738 return 0; 739 } 740 #endif 741 742 /* 743 * Try reading Symbios or Tekram NVRAM 744 */ 745 int sym_read_nvram(struct sym_device *np, struct sym_nvram *nvp) 746 { 747 if (!sym_read_Symbios_nvram(np, &nvp->data.Symbios)) { 748 nvp->type = SYM_SYMBIOS_NVRAM; 749 sym_display_Symbios_nvram(np, &nvp->data.Symbios); 750 } else if (!sym_read_Tekram_nvram(np, &nvp->data.Tekram)) { 751 nvp->type = SYM_TEKRAM_NVRAM; 752 sym_display_Tekram_nvram(np, &nvp->data.Tekram); 753 } else { 754 nvp->type = sym_read_parisc_pdc(np, &nvp->data.parisc); 755 } 756 return nvp->type; 757 } 758 759 char *sym_nvram_type(struct sym_nvram *nvp) 760 { 761 switch (nvp->type) { 762 case SYM_SYMBIOS_NVRAM: 763 return "Symbios NVRAM"; 764 case SYM_TEKRAM_NVRAM: 765 return "Tekram NVRAM"; 766 case SYM_PARISC_PDC: 767 return "PA-RISC Firmware"; 768 default: 769 return "No NVRAM"; 770 } 771 } 772