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 				/* fall through */
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 }
538