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