sym_fw.c 13 KB

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