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