root/drivers/scsi/sym53c8xx_2/sym_fw.c

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

DEFINITIONS

This source file includes following definitions.
  1. sym_fw1_patch
  2. sym_fw2_patch
  3. sym_fw_fill_data
  4. sym_fw_setup_bus_addresses
  5. sym_fw1_setup
  6. sym_fw2_setup
  7. sym_find_firmware
  8. sym_fw_bind_script

   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 
  29 /*
  30  *  Macros used for all firmwares.
  31  */
  32 #define SYM_GEN_A(s, label)     ((short) offsetof(s, label)),
  33 #define SYM_GEN_B(s, label)     ((short) offsetof(s, label)),
  34 #define SYM_GEN_Z(s, label)     ((short) offsetof(s, label)),
  35 #define PADDR_A(label)          SYM_GEN_PADDR_A(struct SYM_FWA_SCR, label)
  36 #define PADDR_B(label)          SYM_GEN_PADDR_B(struct SYM_FWB_SCR, label)
  37 
  38 
  39 #if     SYM_CONF_GENERIC_SUPPORT
  40 /*
  41  *  Allocate firmware #1 script area.
  42  */
  43 #define SYM_FWA_SCR             sym_fw1a_scr
  44 #define SYM_FWB_SCR             sym_fw1b_scr
  45 #define SYM_FWZ_SCR             sym_fw1z_scr
  46 #include "sym_fw1.h"
  47 static struct sym_fwa_ofs sym_fw1a_ofs = {
  48         SYM_GEN_FW_A(struct SYM_FWA_SCR)
  49 };
  50 static struct sym_fwb_ofs sym_fw1b_ofs = {
  51         SYM_GEN_FW_B(struct SYM_FWB_SCR)
  52 };
  53 static struct sym_fwz_ofs sym_fw1z_ofs = {
  54         SYM_GEN_FW_Z(struct SYM_FWZ_SCR)
  55 };
  56 #undef  SYM_FWA_SCR
  57 #undef  SYM_FWB_SCR
  58 #undef  SYM_FWZ_SCR
  59 #endif  /* SYM_CONF_GENERIC_SUPPORT */
  60 
  61 /*
  62  *  Allocate firmware #2 script area.
  63  */
  64 #define SYM_FWA_SCR             sym_fw2a_scr
  65 #define SYM_FWB_SCR             sym_fw2b_scr
  66 #define SYM_FWZ_SCR             sym_fw2z_scr
  67 #include "sym_fw2.h"
  68 static struct sym_fwa_ofs sym_fw2a_ofs = {
  69         SYM_GEN_FW_A(struct SYM_FWA_SCR)
  70 };
  71 static struct sym_fwb_ofs sym_fw2b_ofs = {
  72         SYM_GEN_FW_B(struct SYM_FWB_SCR)
  73         SYM_GEN_B(struct SYM_FWB_SCR, start64)
  74         SYM_GEN_B(struct SYM_FWB_SCR, pm_handle)
  75 };
  76 static struct sym_fwz_ofs sym_fw2z_ofs = {
  77         SYM_GEN_FW_Z(struct SYM_FWZ_SCR)
  78 };
  79 #undef  SYM_FWA_SCR
  80 #undef  SYM_FWB_SCR
  81 #undef  SYM_FWZ_SCR
  82 
  83 #undef  SYM_GEN_A
  84 #undef  SYM_GEN_B
  85 #undef  SYM_GEN_Z
  86 #undef  PADDR_A
  87 #undef  PADDR_B
  88 
  89 #if     SYM_CONF_GENERIC_SUPPORT
  90 /*
  91  *  Patch routine for firmware #1.
  92  */
  93 static void
  94 sym_fw1_patch(struct Scsi_Host *shost)
  95 {
  96         struct sym_hcb *np = sym_get_hcb(shost);
  97         struct sym_fw1a_scr *scripta0;
  98         struct sym_fw1b_scr *scriptb0;
  99 
 100         scripta0 = (struct sym_fw1a_scr *) np->scripta0;
 101         scriptb0 = (struct sym_fw1b_scr *) np->scriptb0;
 102 
 103         /*
 104          *  Remove LED support if not needed.
 105          */
 106         if (!(np->features & FE_LED0)) {
 107                 scripta0->idle[0]       = cpu_to_scr(SCR_NO_OP);
 108                 scripta0->reselected[0] = cpu_to_scr(SCR_NO_OP);
 109                 scripta0->start[0]      = cpu_to_scr(SCR_NO_OP);
 110         }
 111 
 112 #ifdef SYM_CONF_IARB_SUPPORT
 113         /*
 114          *    If user does not want to use IMMEDIATE ARBITRATION
 115          *    when we are reselected while attempting to arbitrate,
 116          *    patch the SCRIPTS accordingly with a SCRIPT NO_OP.
 117          */
 118         if (!SYM_CONF_SET_IARB_ON_ARB_LOST)
 119                 scripta0->ungetjob[0] = cpu_to_scr(SCR_NO_OP);
 120 #endif
 121         /*
 122          *  Patch some data in SCRIPTS.
 123          *  - start and done queue initial bus address.
 124          *  - target bus address table bus address.
 125          */
 126         scriptb0->startpos[0]   = cpu_to_scr(np->squeue_ba);
 127         scriptb0->done_pos[0]   = cpu_to_scr(np->dqueue_ba);
 128         scriptb0->targtbl[0]    = cpu_to_scr(np->targtbl_ba);
 129 }
 130 #endif  /* SYM_CONF_GENERIC_SUPPORT */
 131 
 132 /*
 133  *  Patch routine for firmware #2.
 134  */
 135 static void
 136 sym_fw2_patch(struct Scsi_Host *shost)
 137 {
 138         struct sym_data *sym_data = shost_priv(shost);
 139         struct pci_dev *pdev = sym_data->pdev;
 140         struct sym_hcb *np = sym_data->ncb;
 141         struct sym_fw2a_scr *scripta0;
 142         struct sym_fw2b_scr *scriptb0;
 143 
 144         scripta0 = (struct sym_fw2a_scr *) np->scripta0;
 145         scriptb0 = (struct sym_fw2b_scr *) np->scriptb0;
 146 
 147         /*
 148          *  Remove LED support if not needed.
 149          */
 150         if (!(np->features & FE_LED0)) {
 151                 scripta0->idle[0]       = cpu_to_scr(SCR_NO_OP);
 152                 scripta0->reselected[0] = cpu_to_scr(SCR_NO_OP);
 153                 scripta0->start[0]      = cpu_to_scr(SCR_NO_OP);
 154         }
 155 
 156 #if   SYM_CONF_DMA_ADDRESSING_MODE == 2
 157         /*
 158          *  Remove useless 64 bit DMA specific SCRIPTS, 
 159          *  when this feature is not available.
 160          */
 161         if (!use_dac(np)) {
 162                 scripta0->is_dmap_dirty[0] = cpu_to_scr(SCR_NO_OP);
 163                 scripta0->is_dmap_dirty[1] = 0;
 164                 scripta0->is_dmap_dirty[2] = cpu_to_scr(SCR_NO_OP);
 165                 scripta0->is_dmap_dirty[3] = 0;
 166         }
 167 #endif
 168 
 169 #ifdef SYM_CONF_IARB_SUPPORT
 170         /*
 171          *    If user does not want to use IMMEDIATE ARBITRATION
 172          *    when we are reselected while attempting to arbitrate,
 173          *    patch the SCRIPTS accordingly with a SCRIPT NO_OP.
 174          */
 175         if (!SYM_CONF_SET_IARB_ON_ARB_LOST)
 176                 scripta0->ungetjob[0] = cpu_to_scr(SCR_NO_OP);
 177 #endif
 178         /*
 179          *  Patch some variable in SCRIPTS.
 180          *  - start and done queue initial bus address.
 181          *  - target bus address table bus address.
 182          */
 183         scriptb0->startpos[0]   = cpu_to_scr(np->squeue_ba);
 184         scriptb0->done_pos[0]   = cpu_to_scr(np->dqueue_ba);
 185         scriptb0->targtbl[0]    = cpu_to_scr(np->targtbl_ba);
 186 
 187         /*
 188          *  Remove the load of SCNTL4 on reselection if not a C10.
 189          */
 190         if (!(np->features & FE_C10)) {
 191                 scripta0->resel_scntl4[0] = cpu_to_scr(SCR_NO_OP);
 192                 scripta0->resel_scntl4[1] = cpu_to_scr(0);
 193         }
 194 
 195         /*
 196          *  Remove a couple of work-arounds specific to C1010 if 
 197          *  they are not desirable. See `sym_fw2.h' for more details.
 198          */
 199         if (!(pdev->device == PCI_DEVICE_ID_LSI_53C1010_66 &&
 200               pdev->revision < 0x1 &&
 201               np->pciclk_khz < 60000)) {
 202                 scripta0->datao_phase[0] = cpu_to_scr(SCR_NO_OP);
 203                 scripta0->datao_phase[1] = cpu_to_scr(0);
 204         }
 205         if (!(pdev->device == PCI_DEVICE_ID_LSI_53C1010_33 /* &&
 206               pdev->revision < 0xff */)) {
 207                 scripta0->sel_done[0] = cpu_to_scr(SCR_NO_OP);
 208                 scripta0->sel_done[1] = cpu_to_scr(0);
 209         }
 210 
 211         /*
 212          *  Patch some other variables in SCRIPTS.
 213          *  These ones are loaded by the SCRIPTS processor.
 214          */
 215         scriptb0->pm0_data_addr[0] =
 216                 cpu_to_scr(np->scripta_ba + 
 217                            offsetof(struct sym_fw2a_scr, pm0_data));
 218         scriptb0->pm1_data_addr[0] =
 219                 cpu_to_scr(np->scripta_ba + 
 220                            offsetof(struct sym_fw2a_scr, pm1_data));
 221 }
 222 
 223 /*
 224  *  Fill the data area in scripts.
 225  *  To be done for all firmwares.
 226  */
 227 static void
 228 sym_fw_fill_data (u32 *in, u32 *out)
 229 {
 230         int     i;
 231 
 232         for (i = 0; i < SYM_CONF_MAX_SG; i++) {
 233                 *in++  = SCR_CHMOV_TBL ^ SCR_DATA_IN;
 234                 *in++  = offsetof (struct sym_dsb, data[i]);
 235                 *out++ = SCR_CHMOV_TBL ^ SCR_DATA_OUT;
 236                 *out++ = offsetof (struct sym_dsb, data[i]);
 237         }
 238 }
 239 
 240 /*
 241  *  Setup useful script bus addresses.
 242  *  To be done for all firmwares.
 243  */
 244 static void 
 245 sym_fw_setup_bus_addresses(struct sym_hcb *np, struct sym_fw *fw)
 246 {
 247         u32 *pa;
 248         u_short *po;
 249         int i;
 250 
 251         /*
 252          *  Build the bus address table for script A 
 253          *  from the script A offset table.
 254          */
 255         po = (u_short *) fw->a_ofs;
 256         pa = (u32 *) &np->fwa_bas;
 257         for (i = 0 ; i < sizeof(np->fwa_bas)/sizeof(u32) ; i++)
 258                 pa[i] = np->scripta_ba + po[i];
 259 
 260         /*
 261          *  Same for script B.
 262          */
 263         po = (u_short *) fw->b_ofs;
 264         pa = (u32 *) &np->fwb_bas;
 265         for (i = 0 ; i < sizeof(np->fwb_bas)/sizeof(u32) ; i++)
 266                 pa[i] = np->scriptb_ba + po[i];
 267 
 268         /*
 269          *  Same for script Z.
 270          */
 271         po = (u_short *) fw->z_ofs;
 272         pa = (u32 *) &np->fwz_bas;
 273         for (i = 0 ; i < sizeof(np->fwz_bas)/sizeof(u32) ; i++)
 274                 pa[i] = np->scriptz_ba + po[i];
 275 }
 276 
 277 #if     SYM_CONF_GENERIC_SUPPORT
 278 /*
 279  *  Setup routine for firmware #1.
 280  */
 281 static void 
 282 sym_fw1_setup(struct sym_hcb *np, struct sym_fw *fw)
 283 {
 284         struct sym_fw1a_scr *scripta0;
 285 
 286         scripta0 = (struct sym_fw1a_scr *) np->scripta0;
 287 
 288         /*
 289          *  Fill variable parts in scripts.
 290          */
 291         sym_fw_fill_data(scripta0->data_in, scripta0->data_out);
 292 
 293         /*
 294          *  Setup bus addresses used from the C code..
 295          */
 296         sym_fw_setup_bus_addresses(np, fw);
 297 }
 298 #endif  /* SYM_CONF_GENERIC_SUPPORT */
 299 
 300 /*
 301  *  Setup routine for firmware #2.
 302  */
 303 static void 
 304 sym_fw2_setup(struct sym_hcb *np, struct sym_fw *fw)
 305 {
 306         struct sym_fw2a_scr *scripta0;
 307 
 308         scripta0 = (struct sym_fw2a_scr *) np->scripta0;
 309 
 310         /*
 311          *  Fill variable parts in scripts.
 312          */
 313         sym_fw_fill_data(scripta0->data_in, scripta0->data_out);
 314 
 315         /*
 316          *  Setup bus addresses used from the C code..
 317          */
 318         sym_fw_setup_bus_addresses(np, fw);
 319 }
 320 
 321 /*
 322  *  Allocate firmware descriptors.
 323  */
 324 #if     SYM_CONF_GENERIC_SUPPORT
 325 static struct sym_fw sym_fw1 = SYM_FW_ENTRY(sym_fw1, "NCR-generic");
 326 #endif  /* SYM_CONF_GENERIC_SUPPORT */
 327 static struct sym_fw sym_fw2 = SYM_FW_ENTRY(sym_fw2, "LOAD/STORE-based");
 328 
 329 /*
 330  *  Find the most appropriate firmware for a chip.
 331  */
 332 struct sym_fw * 
 333 sym_find_firmware(struct sym_chip *chip)
 334 {
 335         if (chip->features & FE_LDSTR)
 336                 return &sym_fw2;
 337 #if     SYM_CONF_GENERIC_SUPPORT
 338         else if (!(chip->features & (FE_PFEN|FE_NOPM|FE_DAC)))
 339                 return &sym_fw1;
 340 #endif
 341         else
 342                 return NULL;
 343 }
 344 
 345 /*
 346  *  Bind a script to physical addresses.
 347  */
 348 void sym_fw_bind_script(struct sym_hcb *np, u32 *start, int len)
 349 {
 350         u32 opcode, new, old, tmp1, tmp2;
 351         u32 *end, *cur;
 352         int relocs;
 353 
 354         cur = start;
 355         end = start + len/4;
 356 
 357         while (cur < end) {
 358 
 359                 opcode = *cur;
 360 
 361                 /*
 362                  *  If we forget to change the length
 363                  *  in scripts, a field will be
 364                  *  padded with 0. This is an illegal
 365                  *  command.
 366                  */
 367                 if (opcode == 0) {
 368                         printf ("%s: ERROR0 IN SCRIPT at %d.\n",
 369                                 sym_name(np), (int) (cur-start));
 370                         ++cur;
 371                         continue;
 372                 };
 373 
 374                 /*
 375                  *  We use the bogus value 0xf00ff00f ;-)
 376                  *  to reserve data area in SCRIPTS.
 377                  */
 378                 if (opcode == SCR_DATA_ZERO) {
 379                         *cur++ = 0;
 380                         continue;
 381                 }
 382 
 383                 if (DEBUG_FLAGS & DEBUG_SCRIPT)
 384                         printf ("%d:  <%x>\n", (int) (cur-start),
 385                                 (unsigned)opcode);
 386 
 387                 /*
 388                  *  We don't have to decode ALL commands
 389                  */
 390                 switch (opcode >> 28) {
 391                 case 0xf:
 392                         /*
 393                          *  LOAD / STORE DSA relative, don't relocate.
 394                          */
 395                         relocs = 0;
 396                         break;
 397                 case 0xe:
 398                         /*
 399                          *  LOAD / STORE absolute.
 400                          */
 401                         relocs = 1;
 402                         break;
 403                 case 0xc:
 404                         /*
 405                          *  COPY has TWO arguments.
 406                          */
 407                         relocs = 2;
 408                         tmp1 = cur[1];
 409                         tmp2 = cur[2];
 410                         if ((tmp1 ^ tmp2) & 3) {
 411                                 printf ("%s: ERROR1 IN SCRIPT at %d.\n",
 412                                         sym_name(np), (int) (cur-start));
 413                         }
 414                         /*
 415                          *  If PREFETCH feature not enabled, remove 
 416                          *  the NO FLUSH bit if present.
 417                          */
 418                         if ((opcode & SCR_NO_FLUSH) &&
 419                             !(np->features & FE_PFEN)) {
 420                                 opcode = (opcode & ~SCR_NO_FLUSH);
 421                         }
 422                         break;
 423                 case 0x0:
 424                         /*
 425                          *  MOVE/CHMOV (absolute address)
 426                          */
 427                         if (!(np->features & FE_WIDE))
 428                                 opcode = (opcode | OPC_MOVE);
 429                         relocs = 1;
 430                         break;
 431                 case 0x1:
 432                         /*
 433                          *  MOVE/CHMOV (table indirect)
 434                          */
 435                         if (!(np->features & FE_WIDE))
 436                                 opcode = (opcode | OPC_MOVE);
 437                         relocs = 0;
 438                         break;
 439 #ifdef SYM_CONF_TARGET_ROLE_SUPPORT
 440                 case 0x2:
 441                         /*
 442                          *  MOVE/CHMOV in target role (absolute address)
 443                          */
 444                         opcode &= ~0x20000000;
 445                         if (!(np->features & FE_WIDE))
 446                                 opcode = (opcode & ~OPC_TCHMOVE);
 447                         relocs = 1;
 448                         break;
 449                 case 0x3:
 450                         /*
 451                          *  MOVE/CHMOV in target role (table indirect)
 452                          */
 453                         opcode &= ~0x20000000;
 454                         if (!(np->features & FE_WIDE))
 455                                 opcode = (opcode & ~OPC_TCHMOVE);
 456                         relocs = 0;
 457                         break;
 458 #endif
 459                 case 0x8:
 460                         /*
 461                          *  JUMP / CALL
 462                          *  don't relocate if relative :-)
 463                          */
 464                         if (opcode & 0x00800000)
 465                                 relocs = 0;
 466                         else if ((opcode & 0xf8400000) == 0x80400000)/*JUMP64*/
 467                                 relocs = 2;
 468                         else
 469                                 relocs = 1;
 470                         break;
 471                 case 0x4:
 472                 case 0x5:
 473                 case 0x6:
 474                 case 0x7:
 475                         relocs = 1;
 476                         break;
 477                 default:
 478                         relocs = 0;
 479                         break;
 480                 };
 481 
 482                 /*
 483                  *  Scriptify:) the opcode.
 484                  */
 485                 *cur++ = cpu_to_scr(opcode);
 486 
 487                 /*
 488                  *  If no relocation, assume 1 argument 
 489                  *  and just scriptize:) it.
 490                  */
 491                 if (!relocs) {
 492                         *cur = cpu_to_scr(*cur);
 493                         ++cur;
 494                         continue;
 495                 }
 496 
 497                 /*
 498                  *  Otherwise performs all needed relocations.
 499                  */
 500                 while (relocs--) {
 501                         old = *cur;
 502 
 503                         switch (old & RELOC_MASK) {
 504                         case RELOC_REGISTER:
 505                                 new = (old & ~RELOC_MASK) + np->mmio_ba;
 506                                 break;
 507                         case RELOC_LABEL_A:
 508                                 new = (old & ~RELOC_MASK) + np->scripta_ba;
 509                                 break;
 510                         case RELOC_LABEL_B:
 511                                 new = (old & ~RELOC_MASK) + np->scriptb_ba;
 512                                 break;
 513                         case RELOC_SOFTC:
 514                                 new = (old & ~RELOC_MASK) + np->hcb_ba;
 515                                 break;
 516                         case 0:
 517                                 /*
 518                                  *  Don't relocate a 0 address.
 519                                  *  They are mostly used for patched or 
 520                                  *  script self-modified areas.
 521                                  */
 522                                 if (old == 0) {
 523                                         new = old;
 524                                         break;
 525                                 }
 526                                 /* fall through */
 527                         default:
 528                                 new = 0;
 529                                 panic("sym_fw_bind_script: "
 530                                       "weird relocation %x\n", old);
 531                                 break;
 532                         }
 533 
 534                         *cur++ = cpu_to_scr(new);
 535                 }
 536         };
 537 }

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