Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sym_fw.c
Go to the documentation of this file.
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 <[email protected]>
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 <[email protected]>
15  * Stefan Esser <[email protected]>
16  * Copyright (C) 1994 Wolfgang Stanglmeier
17  *
18  * Other major contributions:
19  *
20  * NVRAM detection and reading.
21  * Copyright (C) 1997 Richard Waltham <[email protected]>
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 = {
62 };
63 static struct sym_fwb_ofs sym_fw1b_ofs = {
65 };
66 static struct sym_fwz_ofs sym_fw1z_ofs = {
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 = {
83 };
84 static struct sym_fwb_ofs sym_fw2b_ofs = {
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 = {
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  */
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  */
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 *
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 
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 }