1139749Simp/*-
259743Sgroudier *  Device driver optimized for the Symbios/LSI 53C896/53C895A/53C1010
359743Sgroudier *  PCI-SCSI controllers.
459743Sgroudier *
586266Sgroudier *  Copyright (C) 1999-2001  Gerard Roudier <groudier@free.fr>
659743Sgroudier *
759743Sgroudier *  This driver also supports the following Symbios/LSI PCI-SCSI chips:
859743Sgroudier *	53C810A, 53C825A, 53C860, 53C875, 53C876, 53C885, 53C895,
959743Sgroudier *	53C810,  53C815,  53C825 and the 53C1510D is 53C8XX mode.
1059743Sgroudier *
1159743Sgroudier *
1259743Sgroudier *  This driver for FreeBSD-CAM is derived from the Linux sym53c8xx driver.
1359743Sgroudier *  Copyright (C) 1998-1999  Gerard Roudier
1459743Sgroudier *
1559743Sgroudier *  The sym53c8xx driver is derived from the ncr53c8xx driver that had been
1659743Sgroudier *  a port of the FreeBSD ncr driver to Linux-1.2.13.
1759743Sgroudier *
1859743Sgroudier *  The original ncr driver has been written for 386bsd and FreeBSD by
1959743Sgroudier *          Wolfgang Stanglmeier        <wolf@cologne.de>
2059743Sgroudier *          Stefan Esser                <se@mi.Uni-Koeln.de>
2159743Sgroudier *  Copyright (C) 1994  Wolfgang Stanglmeier
2259743Sgroudier *
2359743Sgroudier *  The initialisation code, and part of the code that addresses
2459743Sgroudier *  FreeBSD-CAM services is based on the aic7xxx driver for FreeBSD-CAM
2559743Sgroudier *  written by Justin T. Gibbs.
2659743Sgroudier *
2759743Sgroudier *  Other major contributions:
2859743Sgroudier *
2959743Sgroudier *  NVRAM detection and reading.
3059743Sgroudier *  Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk>
3159743Sgroudier *
3259743Sgroudier *-----------------------------------------------------------------------------
3359743Sgroudier *
3459743Sgroudier * Redistribution and use in source and binary forms, with or without
3559743Sgroudier * modification, are permitted provided that the following conditions
3659743Sgroudier * are met:
3759743Sgroudier * 1. Redistributions of source code must retain the above copyright
3859743Sgroudier *    notice, this list of conditions and the following disclaimer.
3959743Sgroudier * 2. Redistributions in binary form must reproduce the above copyright
4059743Sgroudier *    notice, this list of conditions and the following disclaimer in the
4159743Sgroudier *    documentation and/or other materials provided with the distribution.
4259743Sgroudier * 3. The name of the author may not be used to endorse or promote products
4359743Sgroudier *    derived from this software without specific prior written permission.
4459743Sgroudier *
4559743Sgroudier * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
4659743Sgroudier * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4759743Sgroudier * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4859743Sgroudier * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
4959743Sgroudier * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5059743Sgroudier * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5159743Sgroudier * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5259743Sgroudier * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5359743Sgroudier * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5459743Sgroudier * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5559743Sgroudier * SUCH DAMAGE.
5659743Sgroudier */
5759743Sgroudier
5859743Sgroudier/* $FreeBSD$ */
5959743Sgroudier
6059743Sgroudier/*
6159743Sgroudier *  Scripts for SYMBIOS-Processor
6259743Sgroudier *
6359743Sgroudier *  We have to know the offsets of all labels before we reach
6459743Sgroudier *  them (for forward jumps). Therefore we declare a struct
6559743Sgroudier *  here. If you make changes inside the script,
6659743Sgroudier *
6759743Sgroudier *  DONT FORGET TO CHANGE THE LENGTHS HERE!
6859743Sgroudier */
6959743Sgroudier
7059743Sgroudier/*
7159743Sgroudier *  Script fragments which are loaded into the on-chip RAM
7259743Sgroudier *  of 825A, 875, 876, 895, 895A, 896 and 1010 chips.
7359743Sgroudier *  Must not exceed 4K bytes.
7459743Sgroudier */
7559743Sgroudierstruct SYM_FWA_SCR {
7659743Sgroudier	u32 start		[ 14];
7759743Sgroudier	u32 getjob_begin	[  4];
7859743Sgroudier	u32 getjob_end		[  4];
7959743Sgroudier	u32 select		[  8];
8059743Sgroudier	u32 wf_sel_done		[  2];
8160134Sgroudier	u32 sel_done		[  2];
8259743Sgroudier	u32 send_ident		[  2];
8359743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT
8459743Sgroudier	u32 select2		[  8];
8559743Sgroudier#else
8659743Sgroudier	u32 select2		[  2];
8759743Sgroudier#endif
8859743Sgroudier	u32 command		[  2];
8959743Sgroudier	u32 dispatch		[ 28];
9059743Sgroudier	u32 sel_no_cmd		[ 10];
9159743Sgroudier	u32 init		[  6];
9259743Sgroudier	u32 clrack		[  4];
9359743Sgroudier	u32 disp_status		[  4];
9459743Sgroudier	u32 datai_done		[ 26];
9559743Sgroudier	u32 datao_done		[ 12];
9659743Sgroudier	u32 datai_phase		[  2];
9760134Sgroudier	u32 datao_phase		[  4];
9859743Sgroudier	u32 msg_in		[  2];
9959743Sgroudier	u32 msg_in2		[ 10];
10059743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT
10159743Sgroudier	u32 status		[ 14];
10259743Sgroudier#else
10359743Sgroudier	u32 status		[ 10];
10459743Sgroudier#endif
10559743Sgroudier	u32 complete		[  8];
10659743Sgroudier	u32 complete2		[ 12];
10759743Sgroudier	u32 complete_error	[  4];
10859743Sgroudier	u32 done		[ 14];
10959743Sgroudier	u32 done_end		[  2];
11059743Sgroudier	u32 save_dp		[  8];
11159743Sgroudier	u32 restore_dp		[  4];
11259743Sgroudier	u32 disconnect		[ 20];
11359743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT
11459743Sgroudier	u32 idle		[  4];
11559743Sgroudier#else
11659743Sgroudier	u32 idle		[  2];
11759743Sgroudier#endif
11859743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT
11959743Sgroudier	u32 ungetjob		[  6];
12059743Sgroudier#else
12159743Sgroudier	u32 ungetjob		[  4];
12259743Sgroudier#endif
12359743Sgroudier	u32 reselect		[  4];
12459743Sgroudier	u32 reselected		[ 22];
12559743Sgroudier	u32 resel_scntl4	[ 20];
12659743Sgroudier	u32 resel_lun0		[  6];
12759743Sgroudier#if   SYM_CONF_MAX_TASK*4 > 512
12859743Sgroudier	u32 resel_tag		[ 26];
12959743Sgroudier#elif SYM_CONF_MAX_TASK*4 > 256
13059743Sgroudier	u32 resel_tag		[ 20];
13159743Sgroudier#else
13259743Sgroudier	u32 resel_tag		[ 16];
13359743Sgroudier#endif
13459743Sgroudier	u32 resel_dsa		[  2];
13559743Sgroudier	u32 resel_dsa1		[  6];
13659743Sgroudier	u32 resel_no_tag	[  6];
13759743Sgroudier	u32 data_in		[SYM_CONF_MAX_SG * 2];
13859743Sgroudier	u32 data_in2		[  4];
13959743Sgroudier	u32 data_out		[SYM_CONF_MAX_SG * 2];
14059743Sgroudier	u32 data_out2		[  4];
14159743Sgroudier	u32 pm0_data		[ 12];
14259743Sgroudier	u32 pm0_data_out	[  6];
14359743Sgroudier	u32 pm0_data_end	[  6];
14459743Sgroudier	u32 pm1_data		[ 12];
14559743Sgroudier	u32 pm1_data_out	[  6];
14659743Sgroudier	u32 pm1_data_end	[  6];
14759743Sgroudier};
14859743Sgroudier
14959743Sgroudier/*
15059743Sgroudier *  Script fragments which stay in main memory for all chips
15159743Sgroudier *  except for chips that support 8K on-chip RAM.
15259743Sgroudier */
15359743Sgroudierstruct SYM_FWB_SCR {
15459743Sgroudier	u32 start64		[  2];
15559743Sgroudier	u32 no_data		[  2];
15659743Sgroudier	u32 sel_for_abort	[ 18];
15759743Sgroudier	u32 sel_for_abort_1	[  2];
15859743Sgroudier	u32 msg_in_etc		[ 12];
15959743Sgroudier	u32 msg_received	[  4];
16059743Sgroudier	u32 msg_weird_seen	[  4];
16159743Sgroudier	u32 msg_extended	[ 20];
16259743Sgroudier	u32 msg_bad		[  6];
16359743Sgroudier	u32 msg_weird		[  4];
16459743Sgroudier	u32 msg_weird1		[  8];
16559743Sgroudier
16659743Sgroudier	u32 wdtr_resp		[  6];
16759743Sgroudier	u32 send_wdtr		[  4];
16859743Sgroudier	u32 sdtr_resp		[  6];
16959743Sgroudier	u32 send_sdtr		[  4];
17059743Sgroudier	u32 ppr_resp		[  6];
17159743Sgroudier	u32 send_ppr		[  4];
17259743Sgroudier	u32 nego_bad_phase	[  4];
17359743Sgroudier	u32 msg_out		[  4];
17459743Sgroudier	u32 msg_out_done	[  4];
17559743Sgroudier	u32 data_ovrun		[  2];
17659743Sgroudier	u32 data_ovrun1		[ 22];
17759743Sgroudier	u32 data_ovrun2		[  8];
17859743Sgroudier	u32 abort_resel		[ 16];
17959743Sgroudier	u32 resend_ident	[  4];
18059743Sgroudier	u32 ident_break		[  4];
18159743Sgroudier	u32 ident_break_atn	[  4];
18259743Sgroudier	u32 sdata_in		[  6];
18359743Sgroudier	u32 resel_bad_lun	[  4];
18459743Sgroudier	u32 bad_i_t_l		[  4];
18559743Sgroudier	u32 bad_i_t_l_q		[  4];
18659743Sgroudier	u32 bad_status		[  6];
18759743Sgroudier	u32 pm_handle		[ 20];
18859743Sgroudier	u32 pm_handle1		[  4];
18959743Sgroudier	u32 pm_save		[  4];
19059743Sgroudier	u32 pm0_save		[ 14];
19159743Sgroudier	u32 pm1_save		[ 14];
19259743Sgroudier
19359743Sgroudier	/* WSR handling */
19459743Sgroudier	u32 pm_wsr_handle	[ 42];
19559743Sgroudier	u32 wsr_ma_helper	[  4];
19659743Sgroudier
19759743Sgroudier	/* Data area */
19859743Sgroudier	u32 zero		[  1];
19959743Sgroudier	u32 scratch		[  1];
20059743Sgroudier	u32 pm0_data_addr	[  1];
20159743Sgroudier	u32 pm1_data_addr	[  1];
20259743Sgroudier	u32 saved_dsa		[  1];
20359743Sgroudier	u32 saved_drs		[  1];
20459743Sgroudier	u32 done_pos		[  1];
20559743Sgroudier	u32 startpos		[  1];
20659743Sgroudier	u32 targtbl		[  1];
20759743Sgroudier	/* End of data area */
20859743Sgroudier
20959743Sgroudier	u32 snooptest		[  6];
21059743Sgroudier	u32 snoopend		[  2];
21159743Sgroudier};
21259743Sgroudier
213179029Smariusstatic const struct SYM_FWA_SCR SYM_FWA_SCR = {
21459743Sgroudier/*--------------------------< START >----------------------------*/ {
21559743Sgroudier	/*
21659743Sgroudier	 *  Switch the LED on.
21759743Sgroudier	 *  Will be patched with a NO_OP if LED
21859743Sgroudier	 *  not needed or not desired.
21959743Sgroudier	 */
22059743Sgroudier	SCR_REG_REG (gpreg, SCR_AND, 0xfe),
22159743Sgroudier		0,
22259743Sgroudier	/*
22359743Sgroudier	 *      Clear SIGP.
22459743Sgroudier	 */
22559743Sgroudier	SCR_FROM_REG (ctest2),
22659743Sgroudier		0,
22759743Sgroudier	/*
22859743Sgroudier	 *  Stop here if the C code wants to perform
22959743Sgroudier	 *  some error recovery procedure manually.
23059743Sgroudier	 *  (Indicate this by setting SEM in ISTAT)
23159743Sgroudier	 */
23259743Sgroudier	SCR_FROM_REG (istat),
23359743Sgroudier		0,
23459743Sgroudier	/*
23559743Sgroudier	 *  Report to the C code the next position in
23659743Sgroudier	 *  the start queue the SCRIPTS will schedule.
23759743Sgroudier	 *  The C code must not change SCRATCHA.
23859743Sgroudier	 */
23959743Sgroudier	SCR_LOAD_ABS (scratcha, 4),
24059743Sgroudier		PADDR_B (startpos),
24159743Sgroudier	SCR_INT ^ IFTRUE (MASK (SEM, SEM)),
24259743Sgroudier		SIR_SCRIPT_STOPPED,
24359743Sgroudier	/*
24459743Sgroudier	 *  Start the next job.
24559743Sgroudier	 *
24659743Sgroudier	 *  @DSA     = start point for this job.
24759743Sgroudier	 *  SCRATCHA = address of this job in the start queue.
24859743Sgroudier	 *
24959743Sgroudier	 *  We will restore startpos with SCRATCHA if we fails the
25059743Sgroudier	 *  arbitration or if it is the idle job.
25159743Sgroudier	 *
25259743Sgroudier	 *  The below GETJOB_BEGIN to GETJOB_END section of SCRIPTS
25359743Sgroudier	 *  is a critical path. If it is partially executed, it then
25459743Sgroudier	 *  may happen that the job address is not yet in the DSA
255218909Sbrucec	 *  and the next queue position points to the next JOB.
25659743Sgroudier	 */
25759743Sgroudier	SCR_LOAD_ABS (dsa, 4),
25859743Sgroudier		PADDR_B (startpos),
25959743Sgroudier	SCR_LOAD_REL (temp, 4),
26059743Sgroudier		4,
26159743Sgroudier}/*-------------------------< GETJOB_BEGIN >---------------------*/,{
26259743Sgroudier	SCR_STORE_ABS (temp, 4),
26359743Sgroudier		PADDR_B (startpos),
26459743Sgroudier	SCR_LOAD_REL (dsa, 4),
26559743Sgroudier		0,
26659743Sgroudier}/*-------------------------< GETJOB_END >-----------------------*/,{
26759743Sgroudier	SCR_LOAD_REL (temp, 4),
26859743Sgroudier		0,
26959743Sgroudier	SCR_RETURN,
27059743Sgroudier		0,
27159743Sgroudier}/*-------------------------< SELECT >---------------------------*/,{
27259743Sgroudier	/*
27359743Sgroudier	 *  DSA	contains the address of a scheduled
27459743Sgroudier	 *  	data structure.
27559743Sgroudier	 *
27659743Sgroudier	 *  SCRATCHA contains the address of the start queue
27759743Sgroudier	 *  	entry which points to the next job.
27859743Sgroudier	 *
27959743Sgroudier	 *  Set Initiator mode.
28059743Sgroudier	 *
28159743Sgroudier	 *  (Target mode is left as an exercise for the reader)
28259743Sgroudier	 */
28359743Sgroudier	SCR_CLR (SCR_TRG),
28459743Sgroudier		0,
28559743Sgroudier	/*
28659743Sgroudier	 *      And try to select this target.
28759743Sgroudier	 */
28859743Sgroudier	SCR_SEL_TBL_ATN ^ offsetof (struct sym_dsb, select),
28959743Sgroudier		PADDR_A (ungetjob),
29059743Sgroudier	/*
29159743Sgroudier	 *  Now there are 4 possibilities:
29259743Sgroudier	 *
293160964Syar	 *  (1) The chip loses arbitration.
29459743Sgroudier	 *  This is ok, because it will try again,
29559743Sgroudier	 *  when the bus becomes idle.
29659743Sgroudier	 *  (But beware of the timeout function!)
29759743Sgroudier	 *
29859743Sgroudier	 *  (2) The chip is reselected.
29959743Sgroudier	 *  Then the script processor takes the jump
30059743Sgroudier	 *  to the RESELECT label.
30159743Sgroudier	 *
30259743Sgroudier	 *  (3) The chip wins arbitration.
30359743Sgroudier	 *  Then it will execute SCRIPTS instruction until
30459743Sgroudier	 *  the next instruction that checks SCSI phase.
30559743Sgroudier	 *  Then will stop and wait for selection to be
30659743Sgroudier	 *  complete or selection time-out to occur.
30759743Sgroudier	 *
30859743Sgroudier	 *  After having won arbitration, the SCRIPTS
30959743Sgroudier	 *  processor is able to execute instructions while
31059743Sgroudier	 *  the SCSI core is performing SCSI selection.
31159743Sgroudier	 */
31259743Sgroudier	/*
31359743Sgroudier	 *      load the savep (saved data pointer) into
31459743Sgroudier	 *      the actual data pointer.
31559743Sgroudier	 */
31659743Sgroudier	SCR_LOAD_REL (temp, 4),
31759743Sgroudier		offsetof (struct sym_ccb, phys.head.savep),
31859743Sgroudier	/*
31959743Sgroudier	 *      Initialize the status registers
32059743Sgroudier	 */
32159743Sgroudier	SCR_LOAD_REL (scr0, 4),
32259743Sgroudier		offsetof (struct sym_ccb, phys.head.status),
32359743Sgroudier}/*-------------------------< WF_SEL_DONE >----------------------*/,{
32459743Sgroudier	SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)),
32559743Sgroudier		SIR_SEL_ATN_NO_MSG_OUT,
32660134Sgroudier}/*-------------------------< SEL_DONE >-------------------------*/,{
32760134Sgroudier	/*
32860134Sgroudier	 *  C1010-33 errata work-around.
32960134Sgroudier	 *  Due to a race, the SCSI core may not have
33060134Sgroudier	 *  loaded SCNTL3 on SEL_TBL instruction.
33160134Sgroudier	 *  We reload it once phase is stable.
33260134Sgroudier	 *  Patched with a NOOP for other chips.
33360134Sgroudier	 */
33460134Sgroudier	SCR_LOAD_REL (scntl3, 1),
33560134Sgroudier		offsetof(struct sym_dsb, select.sel_scntl3),
33659743Sgroudier}/*-------------------------< SEND_IDENT >-----------------------*/,{
33759743Sgroudier	/*
33859743Sgroudier	 *  Selection complete.
33959743Sgroudier	 *  Send the IDENTIFY and possibly the TAG message
34059743Sgroudier	 *  and negotiation message if present.
34159743Sgroudier	 */
34259743Sgroudier	SCR_MOVE_TBL ^ SCR_MSG_OUT,
34359743Sgroudier		offsetof (struct sym_dsb, smsg),
34459743Sgroudier}/*-------------------------< SELECT2 >--------------------------*/,{
34559743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT
34659743Sgroudier	/*
34759743Sgroudier	 *  Set IMMEDIATE ARBITRATION if we have been given
34859743Sgroudier	 *  a hint to do so. (Some job to do after this one).
34959743Sgroudier	 */
35059743Sgroudier	SCR_FROM_REG (HF_REG),
35159743Sgroudier		0,
35259743Sgroudier	SCR_JUMPR ^ IFFALSE (MASK (HF_HINT_IARB, HF_HINT_IARB)),
35359743Sgroudier		8,
35459743Sgroudier	SCR_REG_REG (scntl1, SCR_OR, IARB),
35559743Sgroudier		0,
35659743Sgroudier#endif
35759743Sgroudier	/*
35859743Sgroudier	 *  Anticipate the COMMAND phase.
35959743Sgroudier	 *  This is the PHASE we expect at this point.
36059743Sgroudier	 */
36159743Sgroudier	SCR_JUMP ^ IFFALSE (WHEN (SCR_COMMAND)),
36259743Sgroudier		PADDR_A (sel_no_cmd),
36359743Sgroudier}/*-------------------------< COMMAND >--------------------------*/,{
36459743Sgroudier	/*
36559743Sgroudier	 *  ... and send the command
36659743Sgroudier	 */
36759743Sgroudier	SCR_MOVE_TBL ^ SCR_COMMAND,
36859743Sgroudier		offsetof (struct sym_dsb, cmd),
36959743Sgroudier}/*-------------------------< DISPATCH >-------------------------*/,{
37059743Sgroudier	/*
37159743Sgroudier	 *  MSG_IN is the only phase that shall be
37259743Sgroudier	 *  entered at least once for each (re)selection.
37359743Sgroudier	 *  So we test it first.
37459743Sgroudier	 */
37559743Sgroudier	SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)),
37659743Sgroudier		PADDR_A (msg_in),
37759743Sgroudier	SCR_JUMP ^ IFTRUE (IF (SCR_DATA_OUT)),
37859743Sgroudier		PADDR_A (datao_phase),
37959743Sgroudier	SCR_JUMP ^ IFTRUE (IF (SCR_DATA_IN)),
38059743Sgroudier		PADDR_A (datai_phase),
38159743Sgroudier	SCR_JUMP ^ IFTRUE (IF (SCR_STATUS)),
38259743Sgroudier		PADDR_A (status),
38359743Sgroudier	SCR_JUMP ^ IFTRUE (IF (SCR_COMMAND)),
38459743Sgroudier		PADDR_A (command),
38559743Sgroudier	SCR_JUMP ^ IFTRUE (IF (SCR_MSG_OUT)),
38659743Sgroudier		PADDR_B (msg_out),
38759743Sgroudier	/*
38859743Sgroudier	 *  Discard as many illegal phases as
38959743Sgroudier	 *  required and tell the C code about.
39059743Sgroudier	 */
39159743Sgroudier	SCR_JUMPR ^ IFFALSE (WHEN (SCR_ILG_OUT)),
39259743Sgroudier		16,
39359743Sgroudier	SCR_MOVE_ABS (1) ^ SCR_ILG_OUT,
39459743Sgroudier		HADDR_1 (scratch),
39559743Sgroudier	SCR_JUMPR ^ IFTRUE (WHEN (SCR_ILG_OUT)),
39659743Sgroudier		-16,
39759743Sgroudier	SCR_JUMPR ^ IFFALSE (WHEN (SCR_ILG_IN)),
39859743Sgroudier		16,
39959743Sgroudier	SCR_MOVE_ABS (1) ^ SCR_ILG_IN,
40059743Sgroudier		HADDR_1 (scratch),
40159743Sgroudier	SCR_JUMPR ^ IFTRUE (WHEN (SCR_ILG_IN)),
40259743Sgroudier		-16,
40359743Sgroudier	SCR_INT,
40459743Sgroudier		SIR_BAD_PHASE,
40559743Sgroudier	SCR_JUMP,
40659743Sgroudier		PADDR_A (dispatch),
40759743Sgroudier}/*-------------------------< SEL_NO_CMD >-----------------------*/,{
40859743Sgroudier	/*
40959743Sgroudier	 *  The target does not switch to command
41059743Sgroudier	 *  phase after IDENTIFY has been sent.
41159743Sgroudier	 *
41259743Sgroudier	 *  If it stays in MSG OUT phase send it
41359743Sgroudier	 *  the IDENTIFY again.
41459743Sgroudier	 */
41559743Sgroudier	SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_OUT)),
41659743Sgroudier		PADDR_B (resend_ident),
41759743Sgroudier	/*
41859743Sgroudier	 *  If target does not switch to MSG IN phase
41959743Sgroudier	 *  and we sent a negotiation, assert the
42059743Sgroudier	 *  failure immediately.
42159743Sgroudier	 */
42259743Sgroudier	SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)),
42359743Sgroudier		PADDR_A (dispatch),
42459743Sgroudier	SCR_FROM_REG (HS_REG),
42559743Sgroudier		0,
42659743Sgroudier	SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)),
42759743Sgroudier		SIR_NEGO_FAILED,
42859743Sgroudier	/*
42959743Sgroudier	 *  Jump to dispatcher.
43059743Sgroudier	 */
43159743Sgroudier	SCR_JUMP,
43259743Sgroudier		PADDR_A (dispatch),
43359743Sgroudier}/*-------------------------< INIT >-----------------------------*/,{
43459743Sgroudier	/*
43559743Sgroudier	 *  Wait for the SCSI RESET signal to be
43659743Sgroudier	 *  inactive before restarting operations,
43759743Sgroudier	 *  since the chip may hang on SEL_ATN
43859743Sgroudier	 *  if SCSI RESET is active.
43959743Sgroudier	 */
44059743Sgroudier	SCR_FROM_REG (sstat0),
44159743Sgroudier		0,
44259743Sgroudier	SCR_JUMPR ^ IFTRUE (MASK (IRST, IRST)),
44359743Sgroudier		-16,
44459743Sgroudier	SCR_JUMP,
44559743Sgroudier		PADDR_A (start),
44659743Sgroudier}/*-------------------------< CLRACK >---------------------------*/,{
44759743Sgroudier	/*
44859743Sgroudier	 *  Terminate possible pending message phase.
44959743Sgroudier	 */
45059743Sgroudier	SCR_CLR (SCR_ACK),
45159743Sgroudier		0,
45259743Sgroudier	SCR_JUMP,
45359743Sgroudier		PADDR_A (dispatch),
45459743Sgroudier}/*-------------------------< DISP_STATUS >----------------------*/,{
45559743Sgroudier	/*
45659743Sgroudier	 *  Anticipate STATUS phase.
45759743Sgroudier	 *
45859743Sgroudier	 *  Does spare 3 SCRIPTS instructions when we have
45959743Sgroudier	 *  completed the INPUT of the data.
46059743Sgroudier	 */
46159743Sgroudier	SCR_JUMP ^ IFTRUE (WHEN (SCR_STATUS)),
46259743Sgroudier		PADDR_A (status),
46359743Sgroudier	SCR_JUMP,
46459743Sgroudier		PADDR_A (dispatch),
46559743Sgroudier}/*-------------------------< DATAI_DONE >-----------------------*/,{
46659743Sgroudier	/*
46759743Sgroudier	 *  If the device still wants to send us data,
46859743Sgroudier	 *  we must count the extra bytes.
46959743Sgroudier	 */
47059743Sgroudier	SCR_JUMP ^ IFTRUE (WHEN (SCR_DATA_IN)),
47159743Sgroudier		PADDR_B (data_ovrun),
47259743Sgroudier	/*
47359743Sgroudier	 *  If the SWIDE is not full, jump to dispatcher.
47459743Sgroudier	 *  We anticipate a STATUS phase.
47559743Sgroudier	 */
47659743Sgroudier	SCR_FROM_REG (scntl2),
47759743Sgroudier		0,
47859743Sgroudier	SCR_JUMP ^ IFFALSE (MASK (WSR, WSR)),
47959743Sgroudier		PADDR_A (disp_status),
48059743Sgroudier	/*
48159743Sgroudier	 *  The SWIDE is full.
48259743Sgroudier	 *  Clear this condition.
48359743Sgroudier	 */
48459743Sgroudier	SCR_REG_REG (scntl2, SCR_OR, WSR),
48559743Sgroudier		0,
48659743Sgroudier	/*
48759743Sgroudier	 *  We are expecting an IGNORE RESIDUE message
48859743Sgroudier	 *  from the device, otherwise we are in data
48959743Sgroudier	 *  overrun condition. Check against MSG_IN phase.
49059743Sgroudier	 */
49159743Sgroudier	SCR_INT ^ IFFALSE (WHEN (SCR_MSG_IN)),
49259743Sgroudier		SIR_SWIDE_OVERRUN,
49359743Sgroudier	SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)),
49459743Sgroudier		PADDR_A (disp_status),
49559743Sgroudier	/*
49659743Sgroudier	 *  We are in MSG_IN phase,
49759743Sgroudier	 *  Read the first byte of the message.
49859743Sgroudier	 *  If it is not an IGNORE RESIDUE message,
49959743Sgroudier	 *  signal overrun and jump to message
50059743Sgroudier	 *  processing.
50159743Sgroudier	 */
50259743Sgroudier	SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
50359743Sgroudier		HADDR_1 (msgin[0]),
50459743Sgroudier	SCR_INT ^ IFFALSE (DATA (M_IGN_RESIDUE)),
50559743Sgroudier		SIR_SWIDE_OVERRUN,
50659743Sgroudier	SCR_JUMP ^ IFFALSE (DATA (M_IGN_RESIDUE)),
50759743Sgroudier		PADDR_A (msg_in2),
50859743Sgroudier	/*
50959743Sgroudier	 *  We got the message we expected.
51059743Sgroudier	 *  Read the 2nd byte, and jump to dispatcher.
51159743Sgroudier	 */
51259743Sgroudier	SCR_CLR (SCR_ACK),
51359743Sgroudier		0,
51459743Sgroudier	SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
51559743Sgroudier		HADDR_1 (msgin[1]),
51659743Sgroudier	SCR_CLR (SCR_ACK),
51759743Sgroudier		0,
51859743Sgroudier	SCR_JUMP,
51959743Sgroudier		PADDR_A (disp_status),
52059743Sgroudier}/*-------------------------< DATAO_DONE >-----------------------*/,{
52159743Sgroudier	/*
52259743Sgroudier	 *  If the device wants us to send more data,
52359743Sgroudier	 *  we must count the extra bytes.
52459743Sgroudier	 */
52559743Sgroudier	SCR_JUMP ^ IFTRUE (WHEN (SCR_DATA_OUT)),
52659743Sgroudier		PADDR_B (data_ovrun),
52759743Sgroudier	/*
52859743Sgroudier	 *  If the SODL is not full jump to dispatcher.
52959743Sgroudier	 *  We anticipate a STATUS phase.
53059743Sgroudier	 */
53159743Sgroudier	SCR_FROM_REG (scntl2),
53259743Sgroudier		0,
53359743Sgroudier	SCR_JUMP ^ IFFALSE (MASK (WSS, WSS)),
53459743Sgroudier		PADDR_A (disp_status),
53559743Sgroudier	/*
53659743Sgroudier	 *  The SODL is full, clear this condition.
53759743Sgroudier	 */
53859743Sgroudier	SCR_REG_REG (scntl2, SCR_OR, WSS),
53959743Sgroudier		0,
54059743Sgroudier	/*
54159743Sgroudier	 *  And signal a DATA UNDERRUN condition
54259743Sgroudier	 *  to the C code.
54359743Sgroudier	 */
54459743Sgroudier	SCR_INT,
54559743Sgroudier		SIR_SODL_UNDERRUN,
54659743Sgroudier	SCR_JUMP,
54759743Sgroudier		PADDR_A (dispatch),
54859743Sgroudier}/*-------------------------< DATAI_PHASE >----------------------*/,{
54959743Sgroudier	SCR_RETURN,
55059743Sgroudier		0,
55159743Sgroudier}/*-------------------------< DATAO_PHASE >----------------------*/,{
55260134Sgroudier	/*
55360134Sgroudier	 *  C1010-66 errata work-around.
55461051Sgroudier	 *  Extra clocks of data hold must be inserted
55561051Sgroudier	 *  in DATA OUT phase on 33 MHz PCI BUS.
55660134Sgroudier	 *  Patched with a NOOP for other chips.
55760134Sgroudier	 */
55861051Sgroudier	SCR_REG_REG (scntl4, SCR_OR, (XCLKH_DT|XCLKH_ST)),
55961051Sgroudier		0,
56059743Sgroudier	SCR_RETURN,
56159743Sgroudier		0,
56259743Sgroudier}/*-------------------------< MSG_IN >---------------------------*/,{
56359743Sgroudier	/*
56459743Sgroudier	 *  Get the first byte of the message.
56559743Sgroudier	 *
56659743Sgroudier	 *  The script processor doesn't negate the
56759743Sgroudier	 *  ACK signal after this transfer.
56859743Sgroudier	 */
56959743Sgroudier	SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
57059743Sgroudier		HADDR_1 (msgin[0]),
57159743Sgroudier}/*-------------------------< MSG_IN2 >--------------------------*/,{
57259743Sgroudier	/*
57359743Sgroudier	 *  Check first against 1 byte messages
57459743Sgroudier	 *  that we handle from SCRIPTS.
57559743Sgroudier	 */
57659743Sgroudier	SCR_JUMP ^ IFTRUE (DATA (M_COMPLETE)),
57759743Sgroudier		PADDR_A (complete),
57859743Sgroudier	SCR_JUMP ^ IFTRUE (DATA (M_DISCONNECT)),
57959743Sgroudier		PADDR_A (disconnect),
58059743Sgroudier	SCR_JUMP ^ IFTRUE (DATA (M_SAVE_DP)),
58159743Sgroudier		PADDR_A (save_dp),
58259743Sgroudier	SCR_JUMP ^ IFTRUE (DATA (M_RESTORE_DP)),
58359743Sgroudier		PADDR_A (restore_dp),
58459743Sgroudier	/*
58559743Sgroudier	 *  We handle all other messages from the
58659743Sgroudier	 *  C code, so no need to waste on-chip RAM
58759743Sgroudier	 *  for those ones.
58859743Sgroudier	 */
58959743Sgroudier	SCR_JUMP,
59059743Sgroudier		PADDR_B (msg_in_etc),
59159743Sgroudier}/*-------------------------< STATUS >---------------------------*/,{
59259743Sgroudier	/*
59359743Sgroudier	 *  get the status
59459743Sgroudier	 */
59559743Sgroudier	SCR_MOVE_ABS (1) ^ SCR_STATUS,
59659743Sgroudier		HADDR_1 (scratch),
59759743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT
59859743Sgroudier	/*
59959743Sgroudier	 *  If STATUS is not GOOD, clear IMMEDIATE ARBITRATION,
60059743Sgroudier	 *  since we may have to tamper the start queue from
60159743Sgroudier	 *  the C code.
60259743Sgroudier	 */
60359743Sgroudier	SCR_JUMPR ^ IFTRUE (DATA (S_GOOD)),
60459743Sgroudier		8,
60559743Sgroudier	SCR_REG_REG (scntl1, SCR_AND, ~IARB),
60659743Sgroudier		0,
60759743Sgroudier#endif
60859743Sgroudier	/*
60959743Sgroudier	 *  save status to scsi_status.
61059743Sgroudier	 *  mark as complete.
61159743Sgroudier	 */
61259743Sgroudier	SCR_TO_REG (SS_REG),
61359743Sgroudier		0,
61459743Sgroudier	SCR_LOAD_REG (HS_REG, HS_COMPLETE),
61559743Sgroudier		0,
61659743Sgroudier	/*
61759743Sgroudier	 *  Anticipate the MESSAGE PHASE for
61859743Sgroudier	 *  the TASK COMPLETE message.
61959743Sgroudier	 */
62059743Sgroudier	SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)),
62159743Sgroudier		PADDR_A (msg_in),
62259743Sgroudier	SCR_JUMP,
62359743Sgroudier		PADDR_A (dispatch),
62459743Sgroudier}/*-------------------------< COMPLETE >-------------------------*/,{
62559743Sgroudier	/*
62659743Sgroudier	 *  Complete message.
62759743Sgroudier	 *
62859743Sgroudier	 *  Copy the data pointer to LASTP.
62959743Sgroudier	 */
63059743Sgroudier	SCR_STORE_REL (temp, 4),
63159743Sgroudier		offsetof (struct sym_ccb, phys.head.lastp),
63259743Sgroudier	/*
63359743Sgroudier	 *  When we terminate the cycle by clearing ACK,
63459743Sgroudier	 *  the target may disconnect immediately.
63559743Sgroudier	 *
63659743Sgroudier	 *  We don't want to be told of an "unexpected disconnect",
63759743Sgroudier	 *  so we disable this feature.
63859743Sgroudier	 */
63959743Sgroudier	SCR_REG_REG (scntl2, SCR_AND, 0x7f),
64059743Sgroudier		0,
64159743Sgroudier	/*
64259743Sgroudier	 *  Terminate cycle ...
64359743Sgroudier	 */
64459743Sgroudier	SCR_CLR (SCR_ACK|SCR_ATN),
64559743Sgroudier		0,
64659743Sgroudier	/*
64759743Sgroudier	 *  ... and wait for the disconnect.
64859743Sgroudier	 */
64959743Sgroudier	SCR_WAIT_DISC,
65059743Sgroudier		0,
65159743Sgroudier}/*-------------------------< COMPLETE2 >------------------------*/,{
65259743Sgroudier	/*
65359743Sgroudier	 *  Save host status.
65459743Sgroudier	 */
65559743Sgroudier	SCR_STORE_REL (scr0, 4),
65659743Sgroudier		offsetof (struct sym_ccb, phys.head.status),
65759743Sgroudier	/*
65859743Sgroudier	 *  Some bridges may reorder DMA writes to memory.
65959743Sgroudier	 *  We donnot want the CPU to deal with completions
66059743Sgroudier	 *  without all the posted write having been flushed
66159743Sgroudier	 *  to memory. This DUMMY READ should flush posted
66259743Sgroudier	 *  buffers prior to the CPU having to deal with
66359743Sgroudier	 *  completions.
66459743Sgroudier	 */
66559743Sgroudier	SCR_LOAD_REL (scr0, 4),	/* DUMMY READ */
66659743Sgroudier		offsetof (struct sym_ccb, phys.head.status),
66759743Sgroudier
66859743Sgroudier	/*
66959743Sgroudier	 *  If command resulted in not GOOD status,
67059743Sgroudier	 *  call the C code if needed.
67159743Sgroudier	 */
67259743Sgroudier	SCR_FROM_REG (SS_REG),
67359743Sgroudier		0,
67459743Sgroudier	SCR_CALL ^ IFFALSE (DATA (S_GOOD)),
67559743Sgroudier		PADDR_B (bad_status),
67659743Sgroudier	/*
67759743Sgroudier	 *  If we performed an auto-sense, call
67859743Sgroudier	 *  the C code to synchronyze task aborts
67959743Sgroudier	 *  with UNIT ATTENTION conditions.
68059743Sgroudier	 */
68159743Sgroudier	SCR_FROM_REG (HF_REG),
68259743Sgroudier		0,
68359743Sgroudier	SCR_JUMPR ^ IFTRUE (MASK (0 ,(HF_SENSE|HF_EXT_ERR))),
68459743Sgroudier		16,
68559743Sgroudier}/*-------------------------< COMPLETE_ERROR >-------------------*/,{
68659743Sgroudier	SCR_LOAD_ABS (scratcha, 4),
68759743Sgroudier		PADDR_B (startpos),
68859743Sgroudier	SCR_INT,
68959743Sgroudier		SIR_COMPLETE_ERROR,
69059743Sgroudier}/*-------------------------< DONE >-----------------------------*/,{
69159743Sgroudier	/*
69259743Sgroudier	 *  Copy the DSA to the DONE QUEUE and
69359743Sgroudier	 *  signal completion to the host.
69459743Sgroudier	 *  If we are interrupted between DONE
69559743Sgroudier	 *  and DONE_END, we must reset, otherwise
69659743Sgroudier	 *  the completed CCB may be lost.
69759743Sgroudier	 */
69859743Sgroudier	SCR_STORE_ABS (dsa, 4),
69959743Sgroudier		PADDR_B (saved_dsa),
70059743Sgroudier	SCR_LOAD_ABS (dsa, 4),
70159743Sgroudier		PADDR_B (done_pos),
70259743Sgroudier	SCR_LOAD_ABS (scratcha, 4),
70359743Sgroudier		PADDR_B (saved_dsa),
70459743Sgroudier	SCR_STORE_REL (scratcha, 4),
70559743Sgroudier		0,
70659743Sgroudier	/*
70759743Sgroudier	 *  The instruction below reads the DONE QUEUE next
70859743Sgroudier	 *  free position from memory.
70959743Sgroudier	 *  In addition it ensures that all PCI posted writes
71059743Sgroudier	 *  are flushed and so the DSA value of the done
71159743Sgroudier	 *  CCB is visible by the CPU before INTFLY is raised.
71259743Sgroudier	 */
71359743Sgroudier	SCR_LOAD_REL (temp, 4),
71459743Sgroudier		4,
71559743Sgroudier	SCR_INT_FLY,
71659743Sgroudier		0,
71759743Sgroudier	SCR_STORE_ABS (temp, 4),
71859743Sgroudier		PADDR_B (done_pos),
71959743Sgroudier}/*-------------------------< DONE_END >-------------------------*/,{
72059743Sgroudier	SCR_JUMP,
72159743Sgroudier		PADDR_A (start),
72259743Sgroudier}/*-------------------------< SAVE_DP >--------------------------*/,{
72359743Sgroudier	/*
72459743Sgroudier	 *  Clear ACK immediately.
72559743Sgroudier	 *  No need to delay it.
72659743Sgroudier	 */
72759743Sgroudier	SCR_CLR (SCR_ACK),
72859743Sgroudier		0,
72959743Sgroudier	/*
73059743Sgroudier	 *  Keep track we received a SAVE DP, so
73159743Sgroudier	 *  we will switch to the other PM context
73259743Sgroudier	 *  on the next PM since the DP may point
73359743Sgroudier	 *  to the current PM context.
73459743Sgroudier	 */
73559743Sgroudier	SCR_REG_REG (HF_REG, SCR_OR, HF_DP_SAVED),
73659743Sgroudier		0,
73759743Sgroudier	/*
73859743Sgroudier	 *  SAVE_DP message:
73959743Sgroudier	 *  Copy the data pointer to SAVEP.
74059743Sgroudier	 */
74159743Sgroudier	SCR_STORE_REL (temp, 4),
74259743Sgroudier		offsetof (struct sym_ccb, phys.head.savep),
74359743Sgroudier	SCR_JUMP,
74459743Sgroudier		PADDR_A (dispatch),
74559743Sgroudier}/*-------------------------< RESTORE_DP >-----------------------*/,{
74659743Sgroudier	/*
74759743Sgroudier	 *  RESTORE_DP message:
74859743Sgroudier	 *  Copy SAVEP to actual data pointer.
74959743Sgroudier	 */
75059743Sgroudier	SCR_LOAD_REL  (temp, 4),
75159743Sgroudier		offsetof (struct sym_ccb, phys.head.savep),
75259743Sgroudier	SCR_JUMP,
75359743Sgroudier		PADDR_A (clrack),
75459743Sgroudier}/*-------------------------< DISCONNECT >-----------------------*/,{
75559743Sgroudier	/*
75659743Sgroudier	 *  DISCONNECTing  ...
75759743Sgroudier	 *
75859743Sgroudier	 *  disable the "unexpected disconnect" feature,
75959743Sgroudier	 *  and remove the ACK signal.
76059743Sgroudier	 */
76159743Sgroudier	SCR_REG_REG (scntl2, SCR_AND, 0x7f),
76259743Sgroudier		0,
76359743Sgroudier	SCR_CLR (SCR_ACK|SCR_ATN),
76459743Sgroudier		0,
76559743Sgroudier	/*
76659743Sgroudier	 *  Wait for the disconnect.
76759743Sgroudier	 */
76859743Sgroudier	SCR_WAIT_DISC,
76959743Sgroudier		0,
77059743Sgroudier	/*
77159743Sgroudier	 *  Status is: DISCONNECTED.
77259743Sgroudier	 */
77359743Sgroudier	SCR_LOAD_REG (HS_REG, HS_DISCONNECT),
77459743Sgroudier		0,
77559743Sgroudier	/*
77659743Sgroudier	 *  Save host status.
77759743Sgroudier	 */
77859743Sgroudier	SCR_STORE_REL (scr0, 4),
77959743Sgroudier		offsetof (struct sym_ccb, phys.head.status),
78059743Sgroudier	/*
78159743Sgroudier	 *  If QUIRK_AUTOSAVE is set,
782108470Sschweikh	 *  do a "save pointer" operation.
78359743Sgroudier	 */
78459743Sgroudier	SCR_FROM_REG (QU_REG),
78559743Sgroudier		0,
78659743Sgroudier	SCR_JUMP ^ IFFALSE (MASK (SYM_QUIRK_AUTOSAVE, SYM_QUIRK_AUTOSAVE)),
78759743Sgroudier		PADDR_A (start),
78859743Sgroudier	/*
78959743Sgroudier	 *  like SAVE_DP message:
79059743Sgroudier	 *  Remember we saved the data pointer.
79159743Sgroudier	 *  Copy data pointer to SAVEP.
79259743Sgroudier	 */
79359743Sgroudier	SCR_REG_REG (HF_REG, SCR_OR, HF_DP_SAVED),
79459743Sgroudier		0,
79559743Sgroudier	SCR_STORE_REL (temp, 4),
79659743Sgroudier		offsetof (struct sym_ccb, phys.head.savep),
79759743Sgroudier	SCR_JUMP,
79859743Sgroudier		PADDR_A (start),
79959743Sgroudier}/*-------------------------< IDLE >-----------------------------*/,{
80059743Sgroudier	/*
80159743Sgroudier	 *  Nothing to do?
80259743Sgroudier	 *  Switch the LED off and wait for reselect.
80359743Sgroudier	 *  Will be patched with a NO_OP if LED
80459743Sgroudier	 *  not needed or not desired.
80559743Sgroudier	 */
80659743Sgroudier	SCR_REG_REG (gpreg, SCR_OR, 0x01),
80759743Sgroudier		0,
80859743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT
80959743Sgroudier	SCR_JUMPR,
81059743Sgroudier		8,
81159743Sgroudier#endif
81259743Sgroudier}/*-------------------------< UNGETJOB >-------------------------*/,{
81359743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT
81459743Sgroudier	/*
81559743Sgroudier	 *  Set IMMEDIATE ARBITRATION, for the next time.
81659743Sgroudier	 *  This will give us better chance to win arbitration
81759743Sgroudier	 *  for the job we just wanted to do.
81859743Sgroudier	 */
81959743Sgroudier	SCR_REG_REG (scntl1, SCR_OR, IARB),
82059743Sgroudier		0,
82159743Sgroudier#endif
82259743Sgroudier	/*
82359743Sgroudier	 *  We are not able to restart the SCRIPTS if we are
82459743Sgroudier	 *  interrupted and these instruction haven't been
82559743Sgroudier	 *  all executed. BTW, this is very unlikely to
82659743Sgroudier	 *  happen, but we check that from the C code.
82759743Sgroudier	 */
82859743Sgroudier	SCR_LOAD_REG (dsa, 0xff),
82959743Sgroudier		0,
83059743Sgroudier	SCR_STORE_ABS (scratcha, 4),
83159743Sgroudier		PADDR_B (startpos),
83259743Sgroudier}/*-------------------------< RESELECT >-------------------------*/,{
83359743Sgroudier	/*
83459743Sgroudier	 *  Make sure we are in initiator mode.
83559743Sgroudier	 */
83659743Sgroudier	SCR_CLR (SCR_TRG),
83759743Sgroudier		0,
83859743Sgroudier	/*
83959743Sgroudier	 *  Sleep waiting for a reselection.
84059743Sgroudier	 */
84159743Sgroudier	SCR_WAIT_RESEL,
84259743Sgroudier		PADDR_A(start),
84359743Sgroudier}/*-------------------------< RESELECTED >-----------------------*/,{
84459743Sgroudier	/*
84559743Sgroudier	 *  Switch the LED on.
84659743Sgroudier	 *  Will be patched with a NO_OP if LED
84759743Sgroudier	 *  not needed or not desired.
84859743Sgroudier	 */
84959743Sgroudier	SCR_REG_REG (gpreg, SCR_AND, 0xfe),
85059743Sgroudier		0,
85159743Sgroudier	/*
85259743Sgroudier	 *  load the target id into the sdid
85359743Sgroudier	 */
85459743Sgroudier	SCR_REG_SFBR (ssid, SCR_AND, 0x8F),
85559743Sgroudier		0,
85659743Sgroudier	SCR_TO_REG (sdid),
85759743Sgroudier		0,
85859743Sgroudier	/*
85959743Sgroudier	 *  Load the target control block address
86059743Sgroudier	 */
86159743Sgroudier	SCR_LOAD_ABS (dsa, 4),
86259743Sgroudier		PADDR_B (targtbl),
86359743Sgroudier	SCR_SFBR_REG (dsa, SCR_SHL, 0),
86459743Sgroudier		0,
86559743Sgroudier	SCR_REG_REG (dsa, SCR_SHL, 0),
86659743Sgroudier		0,
86759743Sgroudier	SCR_REG_REG (dsa, SCR_AND, 0x3c),
86859743Sgroudier		0,
86959743Sgroudier	SCR_LOAD_REL (dsa, 4),
87059743Sgroudier		0,
87159743Sgroudier	/*
87259743Sgroudier	 *  We expect MESSAGE IN phase.
87359743Sgroudier	 *  If not, get help from the C code.
87459743Sgroudier	 */
87559743Sgroudier	SCR_INT ^ IFFALSE (WHEN (SCR_MSG_IN)),
87659743Sgroudier		SIR_RESEL_NO_MSG_IN,
87759743Sgroudier	/*
87859743Sgroudier	 *  Load the legacy synchronous transfer registers.
87959743Sgroudier	 */
88059743Sgroudier	SCR_LOAD_REL (scntl3, 1),
88159743Sgroudier		offsetof(struct sym_tcb, head.wval),
88259743Sgroudier	SCR_LOAD_REL (sxfer, 1),
88359743Sgroudier		offsetof(struct sym_tcb, head.sval),
88459743Sgroudier}/*-------------------------< RESEL_SCNTL4 >---------------------*/,{
88559743Sgroudier	/*
88659743Sgroudier	 *  The C1010 uses a new synchronous timing scheme.
88759743Sgroudier	 *  Will be patched with a NO_OP if not a C1010.
88859743Sgroudier	 */
88959743Sgroudier	SCR_LOAD_REL (scntl4, 1),
89059743Sgroudier		offsetof(struct sym_tcb, head.uval),
89159743Sgroudier	/*
89259743Sgroudier	 *  Get the IDENTIFY message.
89359743Sgroudier	 */
89459743Sgroudier	SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
89559743Sgroudier		HADDR_1 (msgin),
89659743Sgroudier	/*
89759743Sgroudier	 *  If IDENTIFY LUN #0, use a faster path
89859743Sgroudier	 *  to find the LCB structure.
89959743Sgroudier	 */
90059743Sgroudier	SCR_JUMP ^ IFTRUE (MASK (0x80, 0xbf)),
90159743Sgroudier		PADDR_A (resel_lun0),
90259743Sgroudier	/*
90359743Sgroudier	 *  If message isn't an IDENTIFY,
90459743Sgroudier	 *  tell the C code about.
90559743Sgroudier	 */
90659743Sgroudier	SCR_INT ^ IFFALSE (MASK (0x80, 0x80)),
90759743Sgroudier		SIR_RESEL_NO_IDENTIFY,
90859743Sgroudier	/*
90959743Sgroudier	 *  It is an IDENTIFY message,
91059743Sgroudier	 *  Load the LUN control block address.
91159743Sgroudier	 */
91259743Sgroudier	SCR_LOAD_REL (dsa, 4),
91359743Sgroudier		offsetof(struct sym_tcb, head.luntbl_sa),
91459743Sgroudier	SCR_SFBR_REG (dsa, SCR_SHL, 0),
91559743Sgroudier		0,
91659743Sgroudier	SCR_REG_REG (dsa, SCR_SHL, 0),
91759743Sgroudier		0,
91859743Sgroudier	SCR_REG_REG (dsa, SCR_AND, 0xfc),
91959743Sgroudier		0,
92059743Sgroudier	SCR_LOAD_REL (dsa, 4),
92159743Sgroudier		0,
92259743Sgroudier	SCR_JUMPR,
92359743Sgroudier		8,
92459743Sgroudier}/*-------------------------< RESEL_LUN0 >-----------------------*/,{
92559743Sgroudier	/*
92659743Sgroudier	 *  LUN 0 special case (but usual one :))
92759743Sgroudier	 */
92859743Sgroudier	SCR_LOAD_REL (dsa, 4),
92959743Sgroudier		offsetof(struct sym_tcb, head.lun0_sa),
93059743Sgroudier	/*
93159743Sgroudier	 *  Jump indirectly to the reselect action for this LUN.
93259743Sgroudier	 */
93359743Sgroudier	SCR_LOAD_REL (temp, 4),
93459743Sgroudier		offsetof(struct sym_lcb, head.resel_sa),
93559743Sgroudier	SCR_RETURN,
93659743Sgroudier		0,
93759743Sgroudier	/* In normal situations, we jump to RESEL_TAG or RESEL_NO_TAG */
93859743Sgroudier}/*-------------------------< RESEL_TAG >------------------------*/,{
93959743Sgroudier	/*
94060134Sgroudier	 *  ACK the IDENTIFY previously received.
94159743Sgroudier	 */
94259743Sgroudier	SCR_CLR (SCR_ACK),
94359743Sgroudier		0,
94459743Sgroudier	/*
94559743Sgroudier	 *  It shall be a tagged command.
94659743Sgroudier	 *  Read SIMPLE+TAG.
94759743Sgroudier	 *  The C code will deal with errors.
948220950Smarius	 *  Aggressive optimization, isn't it? :)
94959743Sgroudier	 */
95059743Sgroudier	SCR_MOVE_ABS (2) ^ SCR_MSG_IN,
95159743Sgroudier		HADDR_1 (msgin),
95259743Sgroudier	/*
95359743Sgroudier	 *  Load the pointer to the tagged task
95459743Sgroudier	 *  table for this LUN.
95559743Sgroudier	 */
95659743Sgroudier	SCR_LOAD_REL (dsa, 4),
95759743Sgroudier		offsetof(struct sym_lcb, head.itlq_tbl_sa),
95859743Sgroudier	/*
95959743Sgroudier	 *  The SIDL still contains the TAG value.
960220944Smarius	 *  Aggressive optimization, isn't it? :):)
96159743Sgroudier	 */
96259743Sgroudier	SCR_REG_SFBR (sidl, SCR_SHL, 0),
96359743Sgroudier		0,
96459743Sgroudier#if SYM_CONF_MAX_TASK*4 > 512
96559743Sgroudier	SCR_JUMPR ^ IFFALSE (CARRYSET),
96659743Sgroudier		8,
96759743Sgroudier	SCR_REG_REG (dsa1, SCR_OR, 2),
96859743Sgroudier		0,
96959743Sgroudier	SCR_REG_REG (sfbr, SCR_SHL, 0),
97059743Sgroudier		0,
97159743Sgroudier	SCR_JUMPR ^ IFFALSE (CARRYSET),
97259743Sgroudier		8,
97359743Sgroudier	SCR_REG_REG (dsa1, SCR_OR, 1),
97459743Sgroudier		0,
97559743Sgroudier#elif SYM_CONF_MAX_TASK*4 > 256
97659743Sgroudier	SCR_JUMPR ^ IFFALSE (CARRYSET),
97759743Sgroudier		8,
97859743Sgroudier	SCR_REG_REG (dsa1, SCR_OR, 1),
97959743Sgroudier		0,
98059743Sgroudier#endif
98159743Sgroudier	/*
98259743Sgroudier	 *  Retrieve the DSA of this task.
98359743Sgroudier	 *  JUMP indirectly to the restart point of the CCB.
98459743Sgroudier	 */
98559743Sgroudier	SCR_SFBR_REG (dsa, SCR_AND, 0xfc),
98659743Sgroudier		0,
98759743Sgroudier	SCR_LOAD_REL (dsa, 4),
98859743Sgroudier		0,
98959743Sgroudier	SCR_LOAD_REL (temp, 4),
99059743Sgroudier		offsetof(struct sym_ccb, phys.head.go.restart),
99159743Sgroudier	SCR_RETURN,
99259743Sgroudier		0,
99359743Sgroudier	/* In normal situations we branch to RESEL_DSA */
99459743Sgroudier}/*-------------------------< RESEL_DSA >------------------------*/,{
99559743Sgroudier	/*
99659743Sgroudier	 *  ACK the IDENTIFY or TAG previously received.
99759743Sgroudier	 */
99859743Sgroudier	SCR_CLR (SCR_ACK),
99959743Sgroudier		0,
100059743Sgroudier}/*-------------------------< RESEL_DSA1 >-----------------------*/,{
100159743Sgroudier	/*
100259743Sgroudier	 *      load the savep (saved pointer) into
100359743Sgroudier	 *      the actual data pointer.
100459743Sgroudier	 */
100559743Sgroudier	SCR_LOAD_REL (temp, 4),
100659743Sgroudier		offsetof (struct sym_ccb, phys.head.savep),
100759743Sgroudier	/*
100859743Sgroudier	 *      Initialize the status registers
100959743Sgroudier	 */
101059743Sgroudier	SCR_LOAD_REL (scr0, 4),
101159743Sgroudier		offsetof (struct sym_ccb, phys.head.status),
101259743Sgroudier	/*
101359743Sgroudier	 *  Jump to dispatcher.
101459743Sgroudier	 */
101559743Sgroudier	SCR_JUMP,
101659743Sgroudier		PADDR_A (dispatch),
101759743Sgroudier}/*-------------------------< RESEL_NO_TAG >---------------------*/,{
101859743Sgroudier	/*
101959743Sgroudier	 *  Load the DSA with the unique ITL task.
102059743Sgroudier	 */
102159743Sgroudier	SCR_LOAD_REL (dsa, 4),
102259743Sgroudier		offsetof(struct sym_lcb, head.itl_task_sa),
102359743Sgroudier	/*
102459743Sgroudier	 *  JUMP indirectly to the restart point of the CCB.
102559743Sgroudier	 */
102659743Sgroudier	SCR_LOAD_REL (temp, 4),
102759743Sgroudier		offsetof(struct sym_ccb, phys.head.go.restart),
102859743Sgroudier	SCR_RETURN,
102959743Sgroudier		0,
103059743Sgroudier	/* In normal situations we branch to RESEL_DSA */
103159743Sgroudier}/*-------------------------< DATA_IN >--------------------------*/,{
103259743Sgroudier/*
103359743Sgroudier *  Because the size depends on the
103459743Sgroudier *  #define SYM_CONF_MAX_SG parameter,
103559743Sgroudier *  it is filled in at runtime.
103659743Sgroudier *
103759743Sgroudier *  ##===========< i=0; i<SYM_CONF_MAX_SG >=========
103859743Sgroudier *  ||	SCR_CHMOV_TBL ^ SCR_DATA_IN,
103959743Sgroudier *  ||		offsetof (struct sym_dsb, data[ i]),
104059743Sgroudier *  ##==========================================
104159743Sgroudier */
104259743Sgroudier0
104359743Sgroudier}/*-------------------------< DATA_IN2 >-------------------------*/,{
104459743Sgroudier	SCR_CALL,
104559743Sgroudier		PADDR_A (datai_done),
104659743Sgroudier	SCR_JUMP,
104759743Sgroudier		PADDR_B (data_ovrun),
104859743Sgroudier}/*-------------------------< DATA_OUT >-------------------------*/,{
104959743Sgroudier/*
105059743Sgroudier *  Because the size depends on the
105159743Sgroudier *  #define SYM_CONF_MAX_SG parameter,
105259743Sgroudier *  it is filled in at runtime.
105359743Sgroudier *
105459743Sgroudier *  ##===========< i=0; i<SYM_CONF_MAX_SG >=========
105559743Sgroudier *  ||	SCR_CHMOV_TBL ^ SCR_DATA_OUT,
105659743Sgroudier *  ||		offsetof (struct sym_dsb, data[ i]),
105759743Sgroudier *  ##==========================================
105859743Sgroudier */
105959743Sgroudier0
106059743Sgroudier}/*-------------------------< DATA_OUT2 >------------------------*/,{
106159743Sgroudier	SCR_CALL,
106259743Sgroudier		PADDR_A (datao_done),
106359743Sgroudier	SCR_JUMP,
106459743Sgroudier		PADDR_B (data_ovrun),
106559743Sgroudier}/*-------------------------< PM0_DATA >-------------------------*/,{
106659743Sgroudier	/*
106759743Sgroudier	 *  Read our host flags to SFBR, so we will be able
106859743Sgroudier	 *  to check against the data direction we expect.
106959743Sgroudier	 */
107059743Sgroudier	SCR_FROM_REG (HF_REG),
107159743Sgroudier		0,
107259743Sgroudier	/*
107359743Sgroudier	 *  Check against actual DATA PHASE.
107459743Sgroudier	 */
107559743Sgroudier	SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)),
107659743Sgroudier		PADDR_A (pm0_data_out),
107759743Sgroudier	/*
107859743Sgroudier	 *  Actual phase is DATA IN.
107959743Sgroudier	 *  Check against expected direction.
108059743Sgroudier	 */
108159743Sgroudier	SCR_JUMP ^ IFFALSE (MASK (HF_DATA_IN, HF_DATA_IN)),
108259743Sgroudier		PADDR_B (data_ovrun),
108359743Sgroudier	/*
108459743Sgroudier	 *  Keep track we are moving data from the
108559743Sgroudier	 *  PM0 DATA mini-script.
108659743Sgroudier	 */
108759743Sgroudier	SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM0),
108859743Sgroudier		0,
108959743Sgroudier	/*
109059743Sgroudier	 *  Move the data to memory.
109159743Sgroudier	 */
109259743Sgroudier	SCR_CHMOV_TBL ^ SCR_DATA_IN,
109359743Sgroudier		offsetof (struct sym_ccb, phys.pm0.sg),
109459743Sgroudier	SCR_JUMP,
109559743Sgroudier		PADDR_A (pm0_data_end),
109659743Sgroudier}/*-------------------------< PM0_DATA_OUT >---------------------*/,{
109759743Sgroudier	/*
109859743Sgroudier	 *  Actual phase is DATA OUT.
109959743Sgroudier	 *  Check against expected direction.
110059743Sgroudier	 */
110159743Sgroudier	SCR_JUMP ^ IFTRUE (MASK (HF_DATA_IN, HF_DATA_IN)),
110259743Sgroudier		PADDR_B (data_ovrun),
110359743Sgroudier	/*
110459743Sgroudier	 *  Keep track we are moving data from the
110559743Sgroudier	 *  PM0 DATA mini-script.
110659743Sgroudier	 */
110759743Sgroudier	SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM0),
110859743Sgroudier		0,
110959743Sgroudier	/*
111059743Sgroudier	 *  Move the data from memory.
111159743Sgroudier	 */
111259743Sgroudier	SCR_CHMOV_TBL ^ SCR_DATA_OUT,
111359743Sgroudier		offsetof (struct sym_ccb, phys.pm0.sg),
111459743Sgroudier}/*-------------------------< PM0_DATA_END >---------------------*/,{
111559743Sgroudier	/*
111659743Sgroudier	 *  Clear the flag that told we were moving
111759743Sgroudier	 *  data from the PM0 DATA mini-script.
111859743Sgroudier	 */
111959743Sgroudier	SCR_REG_REG (HF_REG, SCR_AND, (~HF_IN_PM0)),
112059743Sgroudier		0,
112159743Sgroudier	/*
112259743Sgroudier	 *  Return to the previous DATA script which
112359743Sgroudier	 *  is guaranteed by design (if no bug) to be
112459743Sgroudier	 *  the main DATA script for this transfer.
112559743Sgroudier	 */
112659743Sgroudier	SCR_LOAD_REL (temp, 4),
112759743Sgroudier		offsetof (struct sym_ccb, phys.pm0.ret),
112859743Sgroudier	SCR_RETURN,
112959743Sgroudier		0,
113059743Sgroudier}/*-------------------------< PM1_DATA >-------------------------*/,{
113159743Sgroudier	/*
113259743Sgroudier	 *  Read our host flags to SFBR, so we will be able
113359743Sgroudier	 *  to check against the data direction we expect.
113459743Sgroudier	 */
113559743Sgroudier	SCR_FROM_REG (HF_REG),
113659743Sgroudier		0,
113759743Sgroudier	/*
113859743Sgroudier	 *  Check against actual DATA PHASE.
113959743Sgroudier	 */
114059743Sgroudier	SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)),
114159743Sgroudier		PADDR_A (pm1_data_out),
114259743Sgroudier	/*
114359743Sgroudier	 *  Actual phase is DATA IN.
114459743Sgroudier	 *  Check against expected direction.
114559743Sgroudier	 */
114659743Sgroudier	SCR_JUMP ^ IFFALSE (MASK (HF_DATA_IN, HF_DATA_IN)),
114759743Sgroudier		PADDR_B (data_ovrun),
114859743Sgroudier	/*
114959743Sgroudier	 *  Keep track we are moving data from the
115059743Sgroudier	 *  PM1 DATA mini-script.
115159743Sgroudier	 */
115259743Sgroudier	SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM1),
115359743Sgroudier		0,
115459743Sgroudier	/*
115559743Sgroudier	 *  Move the data to memory.
115659743Sgroudier	 */
115759743Sgroudier	SCR_CHMOV_TBL ^ SCR_DATA_IN,
115859743Sgroudier		offsetof (struct sym_ccb, phys.pm1.sg),
115959743Sgroudier	SCR_JUMP,
116059743Sgroudier		PADDR_A (pm1_data_end),
116159743Sgroudier}/*-------------------------< PM1_DATA_OUT >---------------------*/,{
116259743Sgroudier	/*
116359743Sgroudier	 *  Actual phase is DATA OUT.
116459743Sgroudier	 *  Check against expected direction.
116559743Sgroudier	 */
116659743Sgroudier	SCR_JUMP ^ IFTRUE (MASK (HF_DATA_IN, HF_DATA_IN)),
116759743Sgroudier		PADDR_B (data_ovrun),
116859743Sgroudier	/*
116959743Sgroudier	 *  Keep track we are moving data from the
117059743Sgroudier	 *  PM1 DATA mini-script.
117159743Sgroudier	 */
117259743Sgroudier	SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM1),
117359743Sgroudier		0,
117459743Sgroudier	/*
117559743Sgroudier	 *  Move the data from memory.
117659743Sgroudier	 */
117759743Sgroudier	SCR_CHMOV_TBL ^ SCR_DATA_OUT,
117859743Sgroudier		offsetof (struct sym_ccb, phys.pm1.sg),
117959743Sgroudier}/*-------------------------< PM1_DATA_END >---------------------*/,{
118059743Sgroudier	/*
118159743Sgroudier	 *  Clear the flag that told we were moving
118259743Sgroudier	 *  data from the PM1 DATA mini-script.
118359743Sgroudier	 */
118459743Sgroudier	SCR_REG_REG (HF_REG, SCR_AND, (~HF_IN_PM1)),
118559743Sgroudier		0,
118659743Sgroudier	/*
118759743Sgroudier	 *  Return to the previous DATA script which
118859743Sgroudier	 *  is guaranteed by design (if no bug) to be
118959743Sgroudier	 *  the main DATA script for this transfer.
119059743Sgroudier	 */
119159743Sgroudier	SCR_LOAD_REL (temp, 4),
119259743Sgroudier		offsetof (struct sym_ccb, phys.pm1.ret),
119359743Sgroudier	SCR_RETURN,
119459743Sgroudier		0,
119559743Sgroudier}/*-------------------------<>-----------------------------------*/
119659743Sgroudier};
119759743Sgroudier
1198179029Smariusstatic const struct SYM_FWB_SCR SYM_FWB_SCR = {
119959743Sgroudier/*--------------------------< START64 >--------------------------*/ {
120059743Sgroudier	/*
120159743Sgroudier	 *  SCRIPT entry point for the 895A, 896 and 1010.
120259743Sgroudier	 *  For now, there is no specific stuff for those
120359743Sgroudier	 *  chips at this point, but this may come.
120459743Sgroudier	 */
120559743Sgroudier	SCR_JUMP,
120659743Sgroudier		PADDR_A (init),
120759743Sgroudier}/*-------------------------< NO_DATA >--------------------------*/,{
120859743Sgroudier	SCR_JUMP,
120959743Sgroudier		PADDR_B (data_ovrun),
121059743Sgroudier}/*-------------------------< SEL_FOR_ABORT >--------------------*/,{
121159743Sgroudier	/*
121259743Sgroudier	 *  We are jumped here by the C code, if we have
121359743Sgroudier	 *  some target to reset or some disconnected
121459743Sgroudier	 *  job to abort. Since error recovery is a serious
121559743Sgroudier	 *  busyness, we will really reset the SCSI BUS, if
1216220944Smarius	 *  case of a SCSI interrupt occurring in this path.
121759743Sgroudier	 */
121859743Sgroudier
121959743Sgroudier	/*
122059743Sgroudier	 *  Set initiator mode.
122159743Sgroudier	 */
122259743Sgroudier	SCR_CLR (SCR_TRG),
122359743Sgroudier		0,
122459743Sgroudier	/*
122559743Sgroudier	 *      And try to select this target.
122659743Sgroudier	 */
122759743Sgroudier	SCR_SEL_TBL_ATN ^ offsetof (struct sym_hcb, abrt_sel),
122859743Sgroudier		PADDR_A (reselect),
122959743Sgroudier	/*
123059743Sgroudier	 *  Wait for the selection to complete or
123159743Sgroudier	 *  the selection to time out.
123259743Sgroudier	 */
123359743Sgroudier	SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_OUT)),
123459743Sgroudier		-8,
123559743Sgroudier	/*
123659743Sgroudier	 *  Call the C code.
123759743Sgroudier	 */
123859743Sgroudier	SCR_INT,
123959743Sgroudier		SIR_TARGET_SELECTED,
124059743Sgroudier	/*
124159743Sgroudier	 *  The C code should let us continue here.
124259743Sgroudier	 *  Send the 'kiss of death' message.
124359743Sgroudier	 *  We expect an immediate disconnect once
124459743Sgroudier	 *  the target has eaten the message.
124559743Sgroudier	 */
124659743Sgroudier	SCR_REG_REG (scntl2, SCR_AND, 0x7f),
124759743Sgroudier		0,
124859743Sgroudier	SCR_MOVE_TBL ^ SCR_MSG_OUT,
124959743Sgroudier		offsetof (struct sym_hcb, abrt_tbl),
125059743Sgroudier	SCR_CLR (SCR_ACK|SCR_ATN),
125159743Sgroudier		0,
125259743Sgroudier	SCR_WAIT_DISC,
125359743Sgroudier		0,
125459743Sgroudier	/*
125559743Sgroudier	 *  Tell the C code that we are done.
125659743Sgroudier	 */
125759743Sgroudier	SCR_INT,
125859743Sgroudier		SIR_ABORT_SENT,
125959743Sgroudier}/*-------------------------< SEL_FOR_ABORT_1 >------------------*/,{
126059743Sgroudier	/*
126159743Sgroudier	 *  Jump at scheduler.
126259743Sgroudier	 */
126359743Sgroudier	SCR_JUMP,
126459743Sgroudier		PADDR_A (start),
126559743Sgroudier}/*-------------------------< MSG_IN_ETC >-----------------------*/,{
126659743Sgroudier	/*
126759743Sgroudier	 *  If it is an EXTENDED (variable size message)
126859743Sgroudier	 *  Handle it.
126959743Sgroudier	 */
127059743Sgroudier	SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED)),
127159743Sgroudier		PADDR_B (msg_extended),
127259743Sgroudier	/*
127359743Sgroudier	 *  Let the C code handle any other
127459743Sgroudier	 *  1 byte message.
127559743Sgroudier	 */
127659743Sgroudier	SCR_JUMP ^ IFTRUE (MASK (0x00, 0xf0)),
127759743Sgroudier		PADDR_B (msg_received),
127859743Sgroudier	SCR_JUMP ^ IFTRUE (MASK (0x10, 0xf0)),
127959743Sgroudier		PADDR_B (msg_received),
128059743Sgroudier	/*
128159743Sgroudier	 *  We donnot handle 2 bytes messages from SCRIPTS.
128259743Sgroudier	 *  So, let the C code deal with these ones too.
128359743Sgroudier	 */
128462134Sgroudier	SCR_JUMP ^ IFFALSE (MASK (0x20, 0xf0)),
128562134Sgroudier		PADDR_B (msg_weird_seen),
128659743Sgroudier	SCR_CLR (SCR_ACK),
128759743Sgroudier		0,
128859743Sgroudier	SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
128959743Sgroudier		HADDR_1 (msgin[1]),
129059743Sgroudier}/*-------------------------< MSG_RECEIVED >---------------------*/,{
129159743Sgroudier	SCR_LOAD_REL (scratcha, 4),	/* DUMMY READ */
129259743Sgroudier		0,
129359743Sgroudier	SCR_INT,
129459743Sgroudier		SIR_MSG_RECEIVED,
129559743Sgroudier}/*-------------------------< MSG_WEIRD_SEEN >-------------------*/,{
129659743Sgroudier	SCR_LOAD_REL (scratcha, 4),	/* DUMMY READ */
129759743Sgroudier		0,
129859743Sgroudier	SCR_INT,
129959743Sgroudier		SIR_MSG_WEIRD,
130059743Sgroudier}/*-------------------------< MSG_EXTENDED >---------------------*/,{
130159743Sgroudier	/*
130259743Sgroudier	 *  Clear ACK and get the next byte
130359743Sgroudier	 *  assumed to be the message length.
130459743Sgroudier	 */
130559743Sgroudier	SCR_CLR (SCR_ACK),
130659743Sgroudier		0,
130759743Sgroudier	SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
130859743Sgroudier		HADDR_1 (msgin[1]),
130959743Sgroudier	/*
131059743Sgroudier	 *  Try to catch some unlikely situations as 0 length
131159743Sgroudier	 *  or too large the length.
131259743Sgroudier	 */
131359743Sgroudier	SCR_JUMP ^ IFTRUE (DATA (0)),
131459743Sgroudier		PADDR_B (msg_weird_seen),
131559743Sgroudier	SCR_TO_REG (scratcha),
131659743Sgroudier		0,
131759743Sgroudier	SCR_REG_REG (sfbr, SCR_ADD, (256-8)),
131859743Sgroudier		0,
131959743Sgroudier	SCR_JUMP ^ IFTRUE (CARRYSET),
132059743Sgroudier		PADDR_B (msg_weird_seen),
132159743Sgroudier	/*
132259743Sgroudier	 *  We donnot handle extended messages from SCRIPTS.
1323220944Smarius	 *  Read the amount of data corresponding to the
132459743Sgroudier	 *  message length and call the C code.
132559743Sgroudier	 */
132659743Sgroudier	SCR_STORE_REL (scratcha, 1),
132759743Sgroudier		offsetof (struct sym_dsb, smsg_ext.size),
132859743Sgroudier	SCR_CLR (SCR_ACK),
132959743Sgroudier		0,
133059743Sgroudier	SCR_MOVE_TBL ^ SCR_MSG_IN,
133159743Sgroudier		offsetof (struct sym_dsb, smsg_ext),
133259743Sgroudier	SCR_JUMP,
133359743Sgroudier		PADDR_B (msg_received),
133459743Sgroudier}/*-------------------------< MSG_BAD >--------------------------*/,{
133559743Sgroudier	/*
133659743Sgroudier	 *  unimplemented message - reject it.
133759743Sgroudier	 */
133859743Sgroudier	SCR_INT,
133959743Sgroudier		SIR_REJECT_TO_SEND,
134059743Sgroudier	SCR_SET (SCR_ATN),
134159743Sgroudier		0,
134259743Sgroudier	SCR_JUMP,
134359743Sgroudier		PADDR_A (clrack),
134459743Sgroudier}/*-------------------------< MSG_WEIRD >------------------------*/,{
134559743Sgroudier	/*
134659743Sgroudier	 *  weird message received
134759743Sgroudier	 *  ignore all MSG IN phases and reject it.
134859743Sgroudier	 */
134959743Sgroudier	SCR_INT,
135059743Sgroudier		SIR_REJECT_TO_SEND,
135159743Sgroudier	SCR_SET (SCR_ATN),
135259743Sgroudier		0,
135359743Sgroudier}/*-------------------------< MSG_WEIRD1 >-----------------------*/,{
135459743Sgroudier	SCR_CLR (SCR_ACK),
135559743Sgroudier		0,
135659743Sgroudier	SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)),
135759743Sgroudier		PADDR_A (dispatch),
135859743Sgroudier	SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
135959743Sgroudier		HADDR_1 (scratch),
136059743Sgroudier	SCR_JUMP,
136159743Sgroudier		PADDR_B (msg_weird1),
136259743Sgroudier}/*-------------------------< WDTR_RESP >------------------------*/,{
136359743Sgroudier	/*
136459743Sgroudier	 *  let the target fetch our answer.
136559743Sgroudier	 */
136659743Sgroudier	SCR_SET (SCR_ATN),
136759743Sgroudier		0,
136859743Sgroudier	SCR_CLR (SCR_ACK),
136959743Sgroudier		0,
137059743Sgroudier	SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)),
137159743Sgroudier		PADDR_B (nego_bad_phase),
137259743Sgroudier}/*-------------------------< SEND_WDTR >------------------------*/,{
137359743Sgroudier	/*
137459743Sgroudier	 *  Send the M_X_WIDE_REQ
137559743Sgroudier	 */
137659743Sgroudier	SCR_MOVE_ABS (4) ^ SCR_MSG_OUT,
137759743Sgroudier		HADDR_1 (msgout),
137859743Sgroudier	SCR_JUMP,
137959743Sgroudier		PADDR_B (msg_out_done),
138059743Sgroudier}/*-------------------------< SDTR_RESP >------------------------*/,{
138159743Sgroudier	/*
138259743Sgroudier	 *  let the target fetch our answer.
138359743Sgroudier	 */
138459743Sgroudier	SCR_SET (SCR_ATN),
138559743Sgroudier		0,
138659743Sgroudier	SCR_CLR (SCR_ACK),
138759743Sgroudier		0,
138859743Sgroudier	SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)),
138959743Sgroudier		PADDR_B (nego_bad_phase),
139059743Sgroudier}/*-------------------------< SEND_SDTR >------------------------*/,{
139159743Sgroudier	/*
139259743Sgroudier	 *  Send the M_X_SYNC_REQ
139359743Sgroudier	 */
139459743Sgroudier	SCR_MOVE_ABS (5) ^ SCR_MSG_OUT,
139559743Sgroudier		HADDR_1 (msgout),
139659743Sgroudier	SCR_JUMP,
139759743Sgroudier		PADDR_B (msg_out_done),
139859743Sgroudier}/*-------------------------< PPR_RESP >-------------------------*/,{
139959743Sgroudier	/*
140059743Sgroudier	 *  let the target fetch our answer.
140159743Sgroudier	 */
140259743Sgroudier	SCR_SET (SCR_ATN),
140359743Sgroudier		0,
140459743Sgroudier	SCR_CLR (SCR_ACK),
140559743Sgroudier		0,
140659743Sgroudier	SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)),
140759743Sgroudier		PADDR_B (nego_bad_phase),
140859743Sgroudier}/*-------------------------< SEND_PPR >-------------------------*/,{
140959743Sgroudier	/*
141059743Sgroudier	 *  Send the M_X_PPR_REQ
141159743Sgroudier	 */
141259743Sgroudier	SCR_MOVE_ABS (8) ^ SCR_MSG_OUT,
141359743Sgroudier		HADDR_1 (msgout),
141459743Sgroudier	SCR_JUMP,
141559743Sgroudier		PADDR_B (msg_out_done),
141659743Sgroudier}/*-------------------------< NEGO_BAD_PHASE >-------------------*/,{
141759743Sgroudier	SCR_INT,
141859743Sgroudier		SIR_NEGO_PROTO,
141959743Sgroudier	SCR_JUMP,
142059743Sgroudier		PADDR_A (dispatch),
142159743Sgroudier}/*-------------------------< MSG_OUT >--------------------------*/,{
142259743Sgroudier	/*
142359743Sgroudier	 *  The target requests a message.
142459743Sgroudier	 *  We donnot send messages that may
142559743Sgroudier	 *  require the device to go to bus free.
142659743Sgroudier	 */
142759743Sgroudier	SCR_MOVE_ABS (1) ^ SCR_MSG_OUT,
142859743Sgroudier		HADDR_1 (msgout),
142959743Sgroudier	/*
143059743Sgroudier	 *  ... wait for the next phase
143159743Sgroudier	 *  if it's a message out, send it again, ...
143259743Sgroudier	 */
143359743Sgroudier	SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_OUT)),
143459743Sgroudier		PADDR_B (msg_out),
143559743Sgroudier}/*-------------------------< MSG_OUT_DONE >---------------------*/,{
143659743Sgroudier	/*
143759743Sgroudier	 *  Let the C code be aware of the
143859743Sgroudier	 *  sent message and clear the message.
143959743Sgroudier	 */
144059743Sgroudier	SCR_INT,
144159743Sgroudier		SIR_MSG_OUT_DONE,
144259743Sgroudier	/*
144359743Sgroudier	 *  ... and process the next phase
144459743Sgroudier	 */
144559743Sgroudier	SCR_JUMP,
144659743Sgroudier		PADDR_A (dispatch),
144759743Sgroudier}/*-------------------------< DATA_OVRUN >-----------------------*/,{
144859743Sgroudier	/*
144959743Sgroudier	 *  Use scratcha to count the extra bytes.
145059743Sgroudier	 */
145159743Sgroudier	SCR_LOAD_ABS (scratcha, 4),
145259743Sgroudier		PADDR_B (zero),
145359743Sgroudier}/*-------------------------< DATA_OVRUN1 >----------------------*/,{
145459743Sgroudier	/*
145559743Sgroudier	 *  The target may want to transfer too much data.
145659743Sgroudier	 *
145759743Sgroudier	 *  If phase is DATA OUT write 1 byte and count it.
145859743Sgroudier	 */
145959743Sgroudier	SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_OUT)),
146059743Sgroudier		16,
146159743Sgroudier	SCR_CHMOV_ABS (1) ^ SCR_DATA_OUT,
146259743Sgroudier		HADDR_1 (scratch),
146359743Sgroudier	SCR_JUMP,
146459743Sgroudier		PADDR_B (data_ovrun2),
146559743Sgroudier	/*
146659743Sgroudier	 *  If WSR is set, clear this condition, and
146759743Sgroudier	 *  count this byte.
146859743Sgroudier	 */
146959743Sgroudier	SCR_FROM_REG (scntl2),
147059743Sgroudier		0,
147159743Sgroudier	SCR_JUMPR ^ IFFALSE (MASK (WSR, WSR)),
147259743Sgroudier		16,
147359743Sgroudier	SCR_REG_REG (scntl2, SCR_OR, WSR),
147459743Sgroudier		0,
147559743Sgroudier	SCR_JUMP,
147659743Sgroudier		PADDR_B (data_ovrun2),
147759743Sgroudier	/*
147859743Sgroudier	 *  Finally check against DATA IN phase.
147959743Sgroudier	 *  Signal data overrun to the C code
148059743Sgroudier	 *  and jump to dispatcher if not so.
148159743Sgroudier	 *  Read 1 byte otherwise and count it.
148259743Sgroudier	 */
148359743Sgroudier	SCR_JUMPR ^ IFTRUE (WHEN (SCR_DATA_IN)),
148459743Sgroudier		16,
148559743Sgroudier	SCR_INT,
148659743Sgroudier		SIR_DATA_OVERRUN,
148759743Sgroudier	SCR_JUMP,
148859743Sgroudier		PADDR_A (dispatch),
148959743Sgroudier	SCR_CHMOV_ABS (1) ^ SCR_DATA_IN,
149059743Sgroudier		HADDR_1 (scratch),
149159743Sgroudier}/*-------------------------< DATA_OVRUN2 >----------------------*/,{
149259743Sgroudier	/*
149359743Sgroudier	 *  Count this byte.
149459743Sgroudier	 *  This will allow to return a negative
149559743Sgroudier	 *  residual to user.
149659743Sgroudier	 */
149759743Sgroudier	SCR_REG_REG (scratcha,  SCR_ADD,  0x01),
149859743Sgroudier		0,
149959743Sgroudier	SCR_REG_REG (scratcha1, SCR_ADDC, 0),
150059743Sgroudier		0,
150159743Sgroudier	SCR_REG_REG (scratcha2, SCR_ADDC, 0),
150259743Sgroudier		0,
150359743Sgroudier	/*
150459743Sgroudier	 *  .. and repeat as required.
150559743Sgroudier	 */
150659743Sgroudier	SCR_JUMP,
150759743Sgroudier		PADDR_B (data_ovrun1),
150859743Sgroudier}/*-------------------------< ABORT_RESEL >----------------------*/,{
150959743Sgroudier	SCR_SET (SCR_ATN),
151059743Sgroudier		0,
151159743Sgroudier	SCR_CLR (SCR_ACK),
151259743Sgroudier		0,
151359743Sgroudier	/*
151459743Sgroudier	 *  send the abort/abortag/reset message
151559743Sgroudier	 *  we expect an immediate disconnect
151659743Sgroudier	 */
151759743Sgroudier	SCR_REG_REG (scntl2, SCR_AND, 0x7f),
151859743Sgroudier		0,
151959743Sgroudier	SCR_MOVE_ABS (1) ^ SCR_MSG_OUT,
152059743Sgroudier		HADDR_1 (msgout),
152159743Sgroudier	SCR_CLR (SCR_ACK|SCR_ATN),
152259743Sgroudier		0,
152359743Sgroudier	SCR_WAIT_DISC,
152459743Sgroudier		0,
152559743Sgroudier	SCR_INT,
152659743Sgroudier		SIR_RESEL_ABORTED,
152759743Sgroudier	SCR_JUMP,
152859743Sgroudier		PADDR_A (start),
152959743Sgroudier}/*-------------------------< RESEND_IDENT >---------------------*/,{
153059743Sgroudier	/*
153159743Sgroudier	 *  The target stays in MSG OUT phase after having acked
153259743Sgroudier	 *  Identify [+ Tag [+ Extended message ]]. Targets shall
153359743Sgroudier	 *  behave this way on parity error.
153459743Sgroudier	 *  We must send it again all the messages.
153559743Sgroudier	 */
153659743Sgroudier	SCR_SET (SCR_ATN), /* Shall be asserted 2 deskew delays before the  */
153759743Sgroudier		0,         /* 1rst ACK = 90 ns. Hope the chip isn't too fast */
153859743Sgroudier	SCR_JUMP,
153959743Sgroudier		PADDR_A (send_ident),
154059743Sgroudier}/*-------------------------< IDENT_BREAK >----------------------*/,{
154159743Sgroudier	SCR_CLR (SCR_ATN),
154259743Sgroudier		0,
154359743Sgroudier	SCR_JUMP,
154459743Sgroudier		PADDR_A (select2),
154559743Sgroudier}/*-------------------------< IDENT_BREAK_ATN >------------------*/,{
154659743Sgroudier	SCR_SET (SCR_ATN),
154759743Sgroudier		0,
154859743Sgroudier	SCR_JUMP,
154959743Sgroudier		PADDR_A (select2),
155059743Sgroudier}/*-------------------------< SDATA_IN >-------------------------*/,{
155159743Sgroudier	SCR_CHMOV_TBL ^ SCR_DATA_IN,
155259743Sgroudier		offsetof (struct sym_dsb, sense),
155359743Sgroudier	SCR_CALL,
155459743Sgroudier		PADDR_A (datai_done),
155559743Sgroudier	SCR_JUMP,
155659743Sgroudier		PADDR_B (data_ovrun),
155759743Sgroudier}/*-------------------------< RESEL_BAD_LUN >--------------------*/,{
155859743Sgroudier	/*
155959743Sgroudier	 *  Message is an IDENTIFY, but lun is unknown.
156059743Sgroudier	 *  Signal problem to C code for logging the event.
156159743Sgroudier	 *  Send a M_ABORT to clear all pending tasks.
156259743Sgroudier	 */
156359743Sgroudier	SCR_INT,
156459743Sgroudier		SIR_RESEL_BAD_LUN,
156559743Sgroudier	SCR_JUMP,
156659743Sgroudier		PADDR_B (abort_resel),
156759743Sgroudier}/*-------------------------< BAD_I_T_L >------------------------*/,{
156859743Sgroudier	/*
156959743Sgroudier	 *  We donnot have a task for that I_T_L.
157059743Sgroudier	 *  Signal problem to C code for logging the event.
157159743Sgroudier	 *  Send a M_ABORT message.
157259743Sgroudier	 */
157359743Sgroudier	SCR_INT,
157459743Sgroudier		SIR_RESEL_BAD_I_T_L,
157559743Sgroudier	SCR_JUMP,
157659743Sgroudier		PADDR_B (abort_resel),
157759743Sgroudier}/*-------------------------< BAD_I_T_L_Q >----------------------*/,{
157859743Sgroudier	/*
157959743Sgroudier	 *  We donnot have a task that matches the tag.
158059743Sgroudier	 *  Signal problem to C code for logging the event.
158159743Sgroudier	 *  Send a M_ABORTTAG message.
158259743Sgroudier	 */
158359743Sgroudier	SCR_INT,
158459743Sgroudier		SIR_RESEL_BAD_I_T_L_Q,
158559743Sgroudier	SCR_JUMP,
158659743Sgroudier		PADDR_B (abort_resel),
158759743Sgroudier}/*-------------------------< BAD_STATUS >-----------------------*/,{
158859743Sgroudier	/*
158959743Sgroudier	 *  Anything different from INTERMEDIATE
159059743Sgroudier	 *  CONDITION MET should be a bad SCSI status,
159159743Sgroudier	 *  given that GOOD status has already been tested.
159259743Sgroudier	 *  Call the C code.
159359743Sgroudier	 */
159459743Sgroudier	SCR_LOAD_ABS (scratcha, 4),
159559743Sgroudier		PADDR_B (startpos),
159659743Sgroudier	SCR_INT ^ IFFALSE (DATA (S_COND_MET)),
159759743Sgroudier		SIR_BAD_SCSI_STATUS,
159859743Sgroudier	SCR_RETURN,
159959743Sgroudier		0,
160059743Sgroudier}/*-------------------------< PM_HANDLE >------------------------*/,{
160159743Sgroudier	/*
160259743Sgroudier	 *  Phase mismatch handling.
160359743Sgroudier	 *
160459743Sgroudier	 *  Since we have to deal with 2 SCSI data pointers
160559743Sgroudier	 *  (current and saved), we need at least 2 contexts.
160659743Sgroudier	 *  Each context (pm0 and pm1) has a saved area, a
160759743Sgroudier	 *  SAVE mini-script and a DATA phase mini-script.
160859743Sgroudier	 */
160959743Sgroudier	/*
161059743Sgroudier	 *  Get the PM handling flags.
161159743Sgroudier	 */
161259743Sgroudier	SCR_FROM_REG (HF_REG),
161359743Sgroudier		0,
161459743Sgroudier	/*
161559743Sgroudier	 *  If no flags (1rst PM for example), avoid
161659743Sgroudier	 *  all the below heavy flags testing.
161759743Sgroudier	 *  This makes the normal case a bit faster.
161859743Sgroudier	 */
161959743Sgroudier	SCR_JUMP ^ IFTRUE (MASK (0, (HF_IN_PM0 | HF_IN_PM1 | HF_DP_SAVED))),
162059743Sgroudier		PADDR_B (pm_handle1),
162159743Sgroudier	/*
162259743Sgroudier	 *  If we received a SAVE DP, switch to the
162359743Sgroudier	 *  other PM context since the savep may point
162459743Sgroudier	 *  to the current PM context.
162559743Sgroudier	 */
162659743Sgroudier	SCR_JUMPR ^ IFFALSE (MASK (HF_DP_SAVED, HF_DP_SAVED)),
162759743Sgroudier		8,
162859743Sgroudier	SCR_REG_REG (sfbr, SCR_XOR, HF_ACT_PM),
162959743Sgroudier		0,
163059743Sgroudier	/*
163159743Sgroudier	 *  If we have been interrupt in a PM DATA mini-script,
163259743Sgroudier	 *  we take the return address from the corresponding
163359743Sgroudier	 *  saved area.
163459743Sgroudier	 *  This ensure the return address always points to the
163559743Sgroudier	 *  main DATA script for this transfer.
163659743Sgroudier	 */
163759743Sgroudier	SCR_JUMP ^ IFTRUE (MASK (0, (HF_IN_PM0 | HF_IN_PM1))),
163859743Sgroudier		PADDR_B (pm_handle1),
163959743Sgroudier	SCR_JUMPR ^ IFFALSE (MASK (HF_IN_PM0, HF_IN_PM0)),
164059743Sgroudier		16,
164159743Sgroudier	SCR_LOAD_REL (ia, 4),
164259743Sgroudier		offsetof(struct sym_ccb, phys.pm0.ret),
164359743Sgroudier	SCR_JUMP,
164459743Sgroudier		PADDR_B (pm_save),
164559743Sgroudier	SCR_LOAD_REL (ia, 4),
164659743Sgroudier		offsetof(struct sym_ccb, phys.pm1.ret),
164759743Sgroudier	SCR_JUMP,
164859743Sgroudier		PADDR_B (pm_save),
164959743Sgroudier}/*-------------------------< PM_HANDLE1 >-----------------------*/,{
165059743Sgroudier	/*
165159743Sgroudier	 *  Normal case.
165259743Sgroudier	 *  Update the return address so that it
165359743Sgroudier	 *  will point after the interrupted MOVE.
165459743Sgroudier	 */
165559743Sgroudier	SCR_REG_REG (ia, SCR_ADD, 8),
165659743Sgroudier		0,
165759743Sgroudier	SCR_REG_REG (ia1, SCR_ADDC, 0),
165859743Sgroudier		0,
165959743Sgroudier}/*-------------------------< PM_SAVE >--------------------------*/,{
166059743Sgroudier	/*
166159743Sgroudier	 *  Clear all the flags that told us if we were
166259743Sgroudier	 *  interrupted in a PM DATA mini-script and/or
166359743Sgroudier	 *  we received a SAVE DP.
166459743Sgroudier	 */
166559743Sgroudier	SCR_SFBR_REG (HF_REG, SCR_AND, (~(HF_IN_PM0|HF_IN_PM1|HF_DP_SAVED))),
166659743Sgroudier		0,
166759743Sgroudier	/*
166859743Sgroudier	 *  Choose the current PM context.
166959743Sgroudier	 */
167059743Sgroudier	SCR_JUMP ^ IFTRUE (MASK (HF_ACT_PM, HF_ACT_PM)),
167159743Sgroudier		PADDR_B (pm1_save),
167259743Sgroudier}/*-------------------------< PM0_SAVE >-------------------------*/,{
167359743Sgroudier	SCR_STORE_REL (ia, 4),
167459743Sgroudier		offsetof(struct sym_ccb, phys.pm0.ret),
167559743Sgroudier	/*
167659743Sgroudier	 *  If WSR bit is set, either UA and RBC may
167759743Sgroudier	 *  have to be changed whether the device wants
167859743Sgroudier	 *  to ignore this residue or not.
167959743Sgroudier	 */
168059743Sgroudier	SCR_FROM_REG (scntl2),
168159743Sgroudier		0,
168259743Sgroudier	SCR_CALL ^ IFTRUE (MASK (WSR, WSR)),
168359743Sgroudier		PADDR_B (pm_wsr_handle),
168459743Sgroudier	/*
168559743Sgroudier	 *  Save the remaining byte count, the updated
168659743Sgroudier	 *  address and the return address.
168759743Sgroudier	 */
168859743Sgroudier	SCR_STORE_REL (rbc, 4),
168959743Sgroudier		offsetof(struct sym_ccb, phys.pm0.sg.size),
169059743Sgroudier	SCR_STORE_REL (ua, 4),
169159743Sgroudier		offsetof(struct sym_ccb, phys.pm0.sg.addr),
169259743Sgroudier	/*
169359743Sgroudier	 *  Set the current pointer at the PM0 DATA mini-script.
169459743Sgroudier	 */
169559743Sgroudier	SCR_LOAD_ABS (temp, 4),
169659743Sgroudier		PADDR_B (pm0_data_addr),
169759743Sgroudier	SCR_JUMP,
169859743Sgroudier		PADDR_A (dispatch),
169959743Sgroudier}/*-------------------------< PM1_SAVE >-------------------------*/,{
170059743Sgroudier	SCR_STORE_REL (ia, 4),
170159743Sgroudier		offsetof(struct sym_ccb, phys.pm1.ret),
170259743Sgroudier	/*
170359743Sgroudier	 *  If WSR bit is set, either UA and RBC may
170459743Sgroudier	 *  have to be changed whether the device wants
170559743Sgroudier	 *  to ignore this residue or not.
170659743Sgroudier	 */
170759743Sgroudier	SCR_FROM_REG (scntl2),
170859743Sgroudier		0,
170959743Sgroudier	SCR_CALL ^ IFTRUE (MASK (WSR, WSR)),
171059743Sgroudier		PADDR_B (pm_wsr_handle),
171159743Sgroudier	/*
171259743Sgroudier	 *  Save the remaining byte count, the updated
171359743Sgroudier	 *  address and the return address.
171459743Sgroudier	 */
171559743Sgroudier	SCR_STORE_REL (rbc, 4),
171659743Sgroudier		offsetof(struct sym_ccb, phys.pm1.sg.size),
171759743Sgroudier	SCR_STORE_REL (ua, 4),
171859743Sgroudier		offsetof(struct sym_ccb, phys.pm1.sg.addr),
171959743Sgroudier	/*
172059743Sgroudier	 *  Set the current pointer at the PM1 DATA mini-script.
172159743Sgroudier	 */
172259743Sgroudier	SCR_LOAD_ABS (temp, 4),
172359743Sgroudier		PADDR_B (pm1_data_addr),
172459743Sgroudier	SCR_JUMP,
172559743Sgroudier		PADDR_A (dispatch),
172659743Sgroudier}/*-------------------------< PM_WSR_HANDLE >--------------------*/,{
172759743Sgroudier	/*
172859743Sgroudier	 *  Phase mismatch handling from SCRIPT with WSR set.
172959743Sgroudier	 *  Such a condition can occur if the chip wants to
173059743Sgroudier	 *  execute a CHMOV(size > 1) when the WSR bit is
173159743Sgroudier	 *  set and the target changes PHASE.
173259743Sgroudier	 *
173359743Sgroudier	 *  We must move the residual byte to memory.
173459743Sgroudier	 *
173559743Sgroudier	 *  UA contains bit 0..31 of the address to
173659743Sgroudier	 *  move the residual byte.
173759743Sgroudier	 *  Move it to the table indirect.
173859743Sgroudier	 */
173959743Sgroudier	SCR_STORE_REL (ua, 4),
174059743Sgroudier		offsetof (struct sym_ccb, phys.wresid.addr),
174159743Sgroudier	/*
174259743Sgroudier	 *  Increment UA (move address to next position).
174359743Sgroudier	 */
174459743Sgroudier	SCR_REG_REG (ua, SCR_ADD, 1),
174559743Sgroudier		0,
174659743Sgroudier	SCR_REG_REG (ua1, SCR_ADDC, 0),
174759743Sgroudier		0,
174859743Sgroudier	SCR_REG_REG (ua2, SCR_ADDC, 0),
174959743Sgroudier		0,
175059743Sgroudier	SCR_REG_REG (ua3, SCR_ADDC, 0),
175159743Sgroudier		0,
175259743Sgroudier	/*
175359743Sgroudier	 *  Compute SCRATCHA as:
175459743Sgroudier	 *  - size to transfer = 1 byte.
175559743Sgroudier	 *  - bit 24..31 = high address bit [32...39].
175659743Sgroudier	 */
175759743Sgroudier	SCR_LOAD_ABS (scratcha, 4),
175859743Sgroudier		PADDR_B (zero),
175959743Sgroudier	SCR_REG_REG (scratcha, SCR_OR, 1),
176059743Sgroudier		0,
176159743Sgroudier	SCR_FROM_REG (rbc3),
176259743Sgroudier		0,
176359743Sgroudier	SCR_TO_REG (scratcha3),
176459743Sgroudier		0,
176559743Sgroudier	/*
176659743Sgroudier	 *  Move this value to the table indirect.
176759743Sgroudier	 */
176859743Sgroudier	SCR_STORE_REL (scratcha, 4),
176959743Sgroudier		offsetof (struct sym_ccb, phys.wresid.size),
177059743Sgroudier	/*
177159743Sgroudier	 *  Wait for a valid phase.
177259743Sgroudier	 *  While testing with bogus QUANTUM drives, the C1010
177359743Sgroudier	 *  sometimes raised a spurious phase mismatch with
177459743Sgroudier	 *  WSR and the CHMOV(1) triggered another PM.
177559743Sgroudier	 *  Waiting explicitely for the PHASE seemed to avoid
177659743Sgroudier	 *  the nested phase mismatch. Btw, this didn't happen
177759743Sgroudier	 *  using my IBM drives.
177859743Sgroudier	 */
177959743Sgroudier	SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_IN)),
178059743Sgroudier		0,
178159743Sgroudier	/*
178259743Sgroudier	 *  Perform the move of the residual byte.
178359743Sgroudier	 */
178459743Sgroudier	SCR_CHMOV_TBL ^ SCR_DATA_IN,
178559743Sgroudier		offsetof (struct sym_ccb, phys.wresid),
178659743Sgroudier	/*
178759743Sgroudier	 *  We can now handle the phase mismatch with UA fixed.
178859743Sgroudier	 *  RBC[0..23]=0 is a special case that does not require
178959743Sgroudier	 *  a PM context. The C code also checks against this.
179059743Sgroudier	 */
179159743Sgroudier	SCR_FROM_REG (rbc),
179259743Sgroudier		0,
179359743Sgroudier	SCR_RETURN ^ IFFALSE (DATA (0)),
179459743Sgroudier		0,
179559743Sgroudier	SCR_FROM_REG (rbc1),
179659743Sgroudier		0,
179759743Sgroudier	SCR_RETURN ^ IFFALSE (DATA (0)),
179859743Sgroudier		0,
179959743Sgroudier	SCR_FROM_REG (rbc2),
180059743Sgroudier		0,
180159743Sgroudier	SCR_RETURN ^ IFFALSE (DATA (0)),
180259743Sgroudier		0,
180359743Sgroudier	/*
180459743Sgroudier	 *  RBC[0..23]=0.
180559743Sgroudier	 *  Not only we donnot need a PM context, but this would
180659743Sgroudier	 *  lead to a bogus CHMOV(0). This condition means that
180759743Sgroudier	 *  the residual was the last byte to move from this CHMOV.
180859743Sgroudier	 *  So, we just have to move the current data script pointer
180959743Sgroudier	 *  (i.e. TEMP) to the SCRIPTS address following the
181059743Sgroudier	 *  interrupted CHMOV and jump to dispatcher.
181159743Sgroudier	 */
181259743Sgroudier	SCR_STORE_ABS (ia, 4),
181359743Sgroudier		PADDR_B (scratch),
181459743Sgroudier	SCR_LOAD_ABS (temp, 4),
181559743Sgroudier		PADDR_B (scratch),
181659743Sgroudier	SCR_JUMP,
181759743Sgroudier		PADDR_A (dispatch),
181859743Sgroudier}/*-------------------------< WSR_MA_HELPER >--------------------*/,{
181959743Sgroudier	/*
182059743Sgroudier	 *  Helper for the C code when WSR bit is set.
182159743Sgroudier	 *  Perform the move of the residual byte.
182259743Sgroudier	 */
182359743Sgroudier	SCR_CHMOV_TBL ^ SCR_DATA_IN,
182459743Sgroudier		offsetof (struct sym_ccb, phys.wresid),
182559743Sgroudier	SCR_JUMP,
182659743Sgroudier		PADDR_A (dispatch),
182759743Sgroudier}/*-------------------------< ZERO >-----------------------------*/,{
182859743Sgroudier	SCR_DATA_ZERO,
182959743Sgroudier}/*-------------------------< SCRATCH >--------------------------*/,{
183059743Sgroudier	SCR_DATA_ZERO,
183159743Sgroudier}/*-------------------------< PM0_DATA_ADDR >--------------------*/,{
183259743Sgroudier	SCR_DATA_ZERO,
183359743Sgroudier}/*-------------------------< PM1_DATA_ADDR >--------------------*/,{
183459743Sgroudier	SCR_DATA_ZERO,
183559743Sgroudier}/*-------------------------< SAVED_DSA >------------------------*/,{
183659743Sgroudier	SCR_DATA_ZERO,
183759743Sgroudier}/*-------------------------< SAVED_DRS >------------------------*/,{
183859743Sgroudier	SCR_DATA_ZERO,
183959743Sgroudier}/*-------------------------< DONE_POS >-------------------------*/,{
184059743Sgroudier	SCR_DATA_ZERO,
184159743Sgroudier}/*-------------------------< STARTPOS >-------------------------*/,{
184259743Sgroudier	SCR_DATA_ZERO,
184359743Sgroudier}/*-------------------------< TARGTBL >--------------------------*/,{
184459743Sgroudier	SCR_DATA_ZERO,
184559743Sgroudier
184659743Sgroudier}/*-------------------------< SNOOPTEST >------------------------*/,{
184759743Sgroudier	/*
184859743Sgroudier	 *  Read the variable from memory.
184959743Sgroudier	 */
185059743Sgroudier	SCR_LOAD_REL (scratcha, 4),
185159743Sgroudier		offsetof(struct sym_hcb, cache),
185259743Sgroudier	/*
185359743Sgroudier	 *  Write the variable to memory.
185459743Sgroudier	 */
185559743Sgroudier	SCR_STORE_REL (temp, 4),
185659743Sgroudier		offsetof(struct sym_hcb, cache),
185759743Sgroudier	/*
185859743Sgroudier	 *  Read back the variable from memory.
185959743Sgroudier	 */
186059743Sgroudier	SCR_LOAD_REL (temp, 4),
186159743Sgroudier		offsetof(struct sym_hcb, cache),
186259743Sgroudier}/*-------------------------< SNOOPEND >-------------------------*/,{
186359743Sgroudier	/*
186459743Sgroudier	 *  And stop.
186559743Sgroudier	 */
186659743Sgroudier	SCR_INT,
186759743Sgroudier		99,
186859743Sgroudier}/*-------------------------<>-----------------------------------*/
186959743Sgroudier};
1870