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