11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Device driver for the SYMBIOS/LSILOGIC 53C8XX and 53C1010 family
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of PCI-SCSI IO processors.
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1999-2001  Gerard Roudier <groudier@free.fr>
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This driver is derived from the Linux sym53c8xx driver.
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1998-2000  Gerard Roudier
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The sym53c8xx driver is derived from the ncr53c8xx driver that had been
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * a port of the FreeBSD ncr driver to Linux-1.2.13.
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The original ncr driver has been written for 386bsd and FreeBSD by
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *         Wolfgang Stanglmeier        <wolf@cologne.de>
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *         Stefan Esser                <se@mi.Uni-Koeln.de>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1994  Wolfgang Stanglmeier
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Other major contributions:
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NVRAM detection and reading.
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *-----------------------------------------------------------------------------
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (at your option) any later version.
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful,
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GNU General Public License for more details.
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; if not, write to the Free Software
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sym_glue.h"
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Macros used for all firmwares.
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SYM_GEN_A(s, label)	((short) offsetof(s, label)),
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SYM_GEN_B(s, label)	((short) offsetof(s, label)),
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SYM_GEN_Z(s, label)	((short) offsetof(s, label)),
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	PADDR_A(label)		SYM_GEN_PADDR_A(struct SYM_FWA_SCR, label)
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	PADDR_B(label)		SYM_GEN_PADDR_B(struct SYM_FWB_SCR, label)
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if	SYM_CONF_GENERIC_SUPPORT
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Allocate firmware #1 script area.
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SYM_FWA_SCR		sym_fw1a_scr
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SYM_FWB_SCR		sym_fw1b_scr
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SYM_FWZ_SCR		sym_fw1z_scr
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sym_fw1.h"
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sym_fwa_ofs sym_fw1a_ofs = {
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SYM_GEN_FW_A(struct SYM_FWA_SCR)
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sym_fwb_ofs sym_fw1b_ofs = {
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SYM_GEN_FW_B(struct SYM_FWB_SCR)
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sym_fwz_ofs sym_fw1z_ofs = {
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SYM_GEN_FW_Z(struct SYM_FWZ_SCR)
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef	SYM_FWA_SCR
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef	SYM_FWB_SCR
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef	SYM_FWZ_SCR
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif	/* SYM_CONF_GENERIC_SUPPORT */
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Allocate firmware #2 script area.
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SYM_FWA_SCR		sym_fw2a_scr
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SYM_FWB_SCR		sym_fw2b_scr
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SYM_FWZ_SCR		sym_fw2z_scr
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sym_fw2.h"
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sym_fwa_ofs sym_fw2a_ofs = {
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SYM_GEN_FW_A(struct SYM_FWA_SCR)
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sym_fwb_ofs sym_fw2b_ofs = {
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SYM_GEN_FW_B(struct SYM_FWB_SCR)
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SYM_GEN_B(struct SYM_FWB_SCR, start64)
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SYM_GEN_B(struct SYM_FWB_SCR, pm_handle)
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sym_fwz_ofs sym_fw2z_ofs = {
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	SYM_GEN_FW_Z(struct SYM_FWZ_SCR)
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef	SYM_FWA_SCR
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef	SYM_FWB_SCR
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef	SYM_FWZ_SCR
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef	SYM_GEN_A
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef	SYM_GEN_B
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef	SYM_GEN_Z
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef	PADDR_A
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef	PADDR_B
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if	SYM_CONF_GENERIC_SUPPORT
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Patch routine for firmware #1.
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
1075111eefa17615bdf17ca00ec2cdca16302c7697eMatthew Wilcoxsym_fw1_patch(struct Scsi_Host *shost)
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1095111eefa17615bdf17ca00ec2cdca16302c7697eMatthew Wilcox	struct sym_hcb *np = sym_get_hcb(shost);
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sym_fw1a_scr *scripta0;
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sym_fw1b_scr *scriptb0;
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scripta0 = (struct sym_fw1a_scr *) np->scripta0;
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scriptb0 = (struct sym_fw1b_scr *) np->scriptb0;
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  Remove LED support if not needed.
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(np->features & FE_LED0)) {
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scripta0->idle[0]	= cpu_to_scr(SCR_NO_OP);
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scripta0->reselected[0]	= cpu_to_scr(SCR_NO_OP);
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scripta0->start[0]	= cpu_to_scr(SCR_NO_OP);
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef SYM_CONF_IARB_SUPPORT
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *    If user does not want to use IMMEDIATE ARBITRATION
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *    when we are reselected while attempting to arbitrate,
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *    patch the SCRIPTS accordingly with a SCRIPT NO_OP.
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!SYM_CONF_SET_IARB_ON_ARB_LOST)
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scripta0->ungetjob[0] = cpu_to_scr(SCR_NO_OP);
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  Patch some data in SCRIPTS.
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  - start and done queue initial bus address.
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  - target bus address table bus address.
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scriptb0->startpos[0]	= cpu_to_scr(np->squeue_ba);
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scriptb0->done_pos[0]	= cpu_to_scr(np->dqueue_ba);
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scriptb0->targtbl[0]	= cpu_to_scr(np->targtbl_ba);
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif	/* SYM_CONF_GENERIC_SUPPORT */
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Patch routine for firmware #2.
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
1495111eefa17615bdf17ca00ec2cdca16302c7697eMatthew Wilcoxsym_fw2_patch(struct Scsi_Host *shost)
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1515111eefa17615bdf17ca00ec2cdca16302c7697eMatthew Wilcox	struct sym_data *sym_data = shost_priv(shost);
1525111eefa17615bdf17ca00ec2cdca16302c7697eMatthew Wilcox	struct pci_dev *pdev = sym_data->pdev;
1535111eefa17615bdf17ca00ec2cdca16302c7697eMatthew Wilcox	struct sym_hcb *np = sym_data->ncb;
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sym_fw2a_scr *scripta0;
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sym_fw2b_scr *scriptb0;
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scripta0 = (struct sym_fw2a_scr *) np->scripta0;
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scriptb0 = (struct sym_fw2b_scr *) np->scriptb0;
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  Remove LED support if not needed.
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(np->features & FE_LED0)) {
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scripta0->idle[0]	= cpu_to_scr(SCR_NO_OP);
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scripta0->reselected[0]	= cpu_to_scr(SCR_NO_OP);
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scripta0->start[0]	= cpu_to_scr(SCR_NO_OP);
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if   SYM_CONF_DMA_ADDRESSING_MODE == 2
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  Remove useless 64 bit DMA specific SCRIPTS,
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  when this feature is not available.
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1744d85b471593d03e141f9160a58574b9204363267Matthew Wilcox	if (!use_dac(np)) {
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scripta0->is_dmap_dirty[0] = cpu_to_scr(SCR_NO_OP);
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scripta0->is_dmap_dirty[1] = 0;
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scripta0->is_dmap_dirty[2] = cpu_to_scr(SCR_NO_OP);
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scripta0->is_dmap_dirty[3] = 0;
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef SYM_CONF_IARB_SUPPORT
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *    If user does not want to use IMMEDIATE ARBITRATION
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *    when we are reselected while attempting to arbitrate,
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *    patch the SCRIPTS accordingly with a SCRIPT NO_OP.
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!SYM_CONF_SET_IARB_ON_ARB_LOST)
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scripta0->ungetjob[0] = cpu_to_scr(SCR_NO_OP);
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  Patch some variable in SCRIPTS.
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  - start and done queue initial bus address.
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  - target bus address table bus address.
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scriptb0->startpos[0]	= cpu_to_scr(np->squeue_ba);
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scriptb0->done_pos[0]	= cpu_to_scr(np->dqueue_ba);
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scriptb0->targtbl[0]	= cpu_to_scr(np->targtbl_ba);
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  Remove the load of SCNTL4 on reselection if not a C10.
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(np->features & FE_C10)) {
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scripta0->resel_scntl4[0] = cpu_to_scr(SCR_NO_OP);
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scripta0->resel_scntl4[1] = cpu_to_scr(0);
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  Remove a couple of work-arounds specific to C1010 if
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  they are not desirable. See `sym_fw2.h' for more details.
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2125111eefa17615bdf17ca00ec2cdca16302c7697eMatthew Wilcox	if (!(pdev->device == PCI_DEVICE_ID_LSI_53C1010_66 &&
2135111eefa17615bdf17ca00ec2cdca16302c7697eMatthew Wilcox	      pdev->revision < 0x1 &&
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	      np->pciclk_khz < 60000)) {
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scripta0->datao_phase[0] = cpu_to_scr(SCR_NO_OP);
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scripta0->datao_phase[1] = cpu_to_scr(0);
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2185111eefa17615bdf17ca00ec2cdca16302c7697eMatthew Wilcox	if (!(pdev->device == PCI_DEVICE_ID_LSI_53C1010_33 /* &&
2195111eefa17615bdf17ca00ec2cdca16302c7697eMatthew Wilcox	      pdev->revision < 0xff */)) {
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scripta0->sel_done[0] = cpu_to_scr(SCR_NO_OP);
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		scripta0->sel_done[1] = cpu_to_scr(0);
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  Patch some other variables in SCRIPTS.
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  These ones are loaded by the SCRIPTS processor.
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scriptb0->pm0_data_addr[0] =
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cpu_to_scr(np->scripta_ba +
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   offsetof(struct sym_fw2a_scr, pm0_data));
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scriptb0->pm1_data_addr[0] =
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cpu_to_scr(np->scripta_ba +
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   offsetof(struct sym_fw2a_scr, pm1_data));
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Fill the data area in scripts.
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  To be done for all firmwares.
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssym_fw_fill_data (u32 *in, u32 *out)
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int	i;
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < SYM_CONF_MAX_SG; i++) {
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*in++  = SCR_CHMOV_TBL ^ SCR_DATA_IN;
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*in++  = offsetof (struct sym_dsb, data[i]);
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*out++ = SCR_CHMOV_TBL ^ SCR_DATA_OUT;
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*out++ = offsetof (struct sym_dsb, data[i]);
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Setup useful script bus addresses.
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  To be done for all firmwares.
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssym_fw_setup_bus_addresses(struct sym_hcb *np, struct sym_fw *fw)
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 *pa;
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_short *po;
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  Build the bus address table for script A
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  from the script A offset table.
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	po = (u_short *) fw->a_ofs;
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pa = (u32 *) &np->fwa_bas;
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0 ; i < sizeof(np->fwa_bas)/sizeof(u32) ; i++)
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pa[i] = np->scripta_ba + po[i];
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  Same for script B.
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	po = (u_short *) fw->b_ofs;
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pa = (u32 *) &np->fwb_bas;
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0 ; i < sizeof(np->fwb_bas)/sizeof(u32) ; i++)
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pa[i] = np->scriptb_ba + po[i];
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  Same for script Z.
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	po = (u_short *) fw->z_ofs;
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pa = (u32 *) &np->fwz_bas;
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0 ; i < sizeof(np->fwz_bas)/sizeof(u32) ; i++)
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pa[i] = np->scriptz_ba + po[i];
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if	SYM_CONF_GENERIC_SUPPORT
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Setup routine for firmware #1.
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssym_fw1_setup(struct sym_hcb *np, struct sym_fw *fw)
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sym_fw1a_scr *scripta0;
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sym_fw1b_scr *scriptb0;
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scripta0 = (struct sym_fw1a_scr *) np->scripta0;
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scriptb0 = (struct sym_fw1b_scr *) np->scriptb0;
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  Fill variable parts in scripts.
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sym_fw_fill_data(scripta0->data_in, scripta0->data_out);
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  Setup bus addresses used from the C code..
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sym_fw_setup_bus_addresses(np, fw);
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif	/* SYM_CONF_GENERIC_SUPPORT */
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Setup routine for firmware #2.
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssym_fw2_setup(struct sym_hcb *np, struct sym_fw *fw)
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sym_fw2a_scr *scripta0;
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sym_fw2b_scr *scriptb0;
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scripta0 = (struct sym_fw2a_scr *) np->scripta0;
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scriptb0 = (struct sym_fw2b_scr *) np->scriptb0;
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  Fill variable parts in scripts.
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sym_fw_fill_data(scripta0->data_in, scripta0->data_out);
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  Setup bus addresses used from the C code..
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sym_fw_setup_bus_addresses(np, fw);
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Allocate firmware descriptors.
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if	SYM_CONF_GENERIC_SUPPORT
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sym_fw sym_fw1 = SYM_FW_ENTRY(sym_fw1, "NCR-generic");
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif	/* SYM_CONF_GENERIC_SUPPORT */
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sym_fw sym_fw2 = SYM_FW_ENTRY(sym_fw2, "LOAD/STORE-based");
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Find the most appropriate firmware for a chip.
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct sym_fw *
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssym_find_firmware(struct sym_chip *chip)
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (chip->features & FE_LDSTR)
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return &sym_fw2;
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if	SYM_CONF_GENERIC_SUPPORT
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else if (!(chip->features & (FE_PFEN|FE_NOPM|FE_DAC)))
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return &sym_fw1;
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return NULL;
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Bind a script to physical addresses.
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid sym_fw_bind_script(struct sym_hcb *np, u32 *start, int len)
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 opcode, new, old, tmp1, tmp2;
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 *end, *cur;
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int relocs;
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cur = start;
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	end = start + len/4;
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (cur < end) {
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		opcode = *cur;
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *  If we forget to change the length
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *  in scripts, a field will be
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *  padded with 0. This is an illegal
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *  command.
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (opcode == 0) {
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printf ("%s: ERROR0 IN SCRIPT at %d.\n",
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				sym_name(np), (int) (cur-start));
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			++cur;
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		};
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *  We use the bogus value 0xf00ff00f ;-)
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *  to reserve data area in SCRIPTS.
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (opcode == SCR_DATA_ZERO) {
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*cur++ = 0;
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (DEBUG_FLAGS & DEBUG_SCRIPT)
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printf ("%d:  <%x>\n", (int) (cur-start),
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(unsigned)opcode);
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *  We don't have to decode ALL commands
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (opcode >> 28) {
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0xf:
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *  LOAD / STORE DSA relative, don't relocate.
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			relocs = 0;
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0xe:
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *  LOAD / STORE absolute.
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			relocs = 1;
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0xc:
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *  COPY has TWO arguments.
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			relocs = 2;
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tmp1 = cur[1];
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tmp2 = cur[2];
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((tmp1 ^ tmp2) & 3) {
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				printf ("%s: ERROR1 IN SCRIPT at %d.\n",
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					sym_name(np), (int) (cur-start));
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *  If PREFETCH feature not enabled, remove
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *  the NO FLUSH bit if present.
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((opcode & SCR_NO_FLUSH) &&
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    !(np->features & FE_PFEN)) {
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				opcode = (opcode & ~SCR_NO_FLUSH);
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x0:
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *  MOVE/CHMOV (absolute address)
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(np->features & FE_WIDE))
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				opcode = (opcode | OPC_MOVE);
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			relocs = 1;
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x1:
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *  MOVE/CHMOV (table indirect)
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(np->features & FE_WIDE))
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				opcode = (opcode | OPC_MOVE);
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			relocs = 0;
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef SYM_CONF_TARGET_ROLE_SUPPORT
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x2:
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *  MOVE/CHMOV in target role (absolute address)
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			opcode &= ~0x20000000;
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(np->features & FE_WIDE))
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				opcode = (opcode & ~OPC_TCHMOVE);
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			relocs = 1;
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x3:
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *  MOVE/CHMOV in target role (table indirect)
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			opcode &= ~0x20000000;
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(np->features & FE_WIDE))
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				opcode = (opcode & ~OPC_TCHMOVE);
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			relocs = 0;
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x8:
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *  JUMP / CALL
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 *  don't relocate if relative :-)
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (opcode & 0x00800000)
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				relocs = 0;
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else if ((opcode & 0xf8400000) == 0x80400000)/*JUMP64*/
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				relocs = 2;
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				relocs = 1;
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x4:
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x5:
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x6:
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x7:
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			relocs = 1;
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			relocs = 0;
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		};
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *  Scriptify:) the opcode.
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*cur++ = cpu_to_scr(opcode);
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *  If no relocation, assume 1 argument
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *  and just scriptize:) it.
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!relocs) {
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*cur = cpu_to_scr(*cur);
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			++cur;
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *  Otherwise performs all needed relocations.
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while (relocs--) {
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			old = *cur;
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			switch (old & RELOC_MASK) {
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case RELOC_REGISTER:
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				new = (old & ~RELOC_MASK) + np->mmio_ba;
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case RELOC_LABEL_A:
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				new = (old & ~RELOC_MASK) + np->scripta_ba;
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case RELOC_LABEL_B:
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				new = (old & ~RELOC_MASK) + np->scriptb_ba;
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case RELOC_SOFTC:
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				new = (old & ~RELOC_MASK) + np->hcb_ba;
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case 0:
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/*
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 *  Don't relocate a 0 address.
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 *  They are mostly used for patched or
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 *  script self-modified areas.
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 */
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (old == 0) {
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					new = old;
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					break;
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* fall through */
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			default:
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				new = 0;
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				panic("sym_fw_bind_script: "
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				      "weird relocation %x\n", old);
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*cur++ = cpu_to_scr(new);
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	};
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
555