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