Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[linux-2.6] / 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 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 }