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