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