root/drivers/scsi/sym53c8xx_2/sym_nvram.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sym_nvram_setup_host
  2. sym_Symbios_setup_target
  3. sym_Tekram_setup_target
  4. sym_nvram_setup_target
  5. sym_display_Symbios_nvram
  6. sym_display_Tekram_nvram
  7. sym_display_Symbios_nvram
  8. sym_display_Tekram_nvram
  9. S24C16_set_bit
  10. S24C16_start
  11. S24C16_stop
  12. S24C16_do_bit
  13. S24C16_write_ack
  14. S24C16_read_ack
  15. S24C16_write_byte
  16. S24C16_read_byte
  17. sym_write_S24C16_nvram
  18. sym_read_S24C16_nvram
  19. sym_read_Symbios_nvram
  20. T93C46_Clk
  21. T93C46_Read_Bit
  22. T93C46_Write_Bit
  23. T93C46_Stop
  24. T93C46_Send_Command
  25. T93C46_Read_Word
  26. T93C46_Read_Data
  27. sym_read_T93C46_nvram
  28. sym_read_Tekram_nvram
  29. sym_read_parisc_pdc
  30. sym_read_parisc_pdc
  31. sym_read_nvram
  32. sym_nvram_type

   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
  31 static u_char Tekram_boot_delay[7] = {3, 5, 10, 20, 30, 60, 120};
  32 #endif
  33 
  34 /*
  35  *  Get host setup from NVRAM.
  36  */
  37 void 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  */
  81 static void
  82 sym_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 
  98 static 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  */
 105 static void
 106 sym_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  */
 125 void 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  */
 143 static 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  */
 175 static 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
 222 static void sym_display_Symbios_nvram(struct sym_device *np, Symbios_nvram *nvram) { (void)np; (void)nvram; }
 223 static 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  *  GPOI0 - 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  */
 243 static 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  */
 270 static 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  */
 281 static 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  */
 291 static 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  */
 306 static 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  */
 318 static 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  */
 330 static 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  */
 345 static 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  */
 364 static 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  */
 418 static 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;
 480 out:
 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  */
 497 static 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  *  GPOI0 - 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  */
 538 static 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  */
 549 static 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  */
 559 static 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  */
 578 static 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  */
 591 static 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  */
 606 static 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  */
 626 static 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  */
 647 static 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  */
 679 static 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                 /* fall through */
 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  */
 721 static 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
 731 static 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  */
 741 int 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 
 755 char *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 }

/* [<][>][^][v][top][bottom][index][help] */