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