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