• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/scsi/sym53c8xx_2/
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 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 */
148static void
149sym_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 */
240static void
241sym_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 */
257static void
258sym_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 */
294static void
295sym_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 */
318static void
319sym_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
342static struct sym_fw sym_fw1 = SYM_FW_ENTRY(sym_fw1, "NCR-generic");
343#endif	/* SYM_CONF_GENERIC_SUPPORT */
344static 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 */
349struct sym_fw *
350sym_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 */
365void 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}
555