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		[ 11];
7759743Sgroudier	u32 getjob_begin	[  4];
7859743Sgroudier	u32 _sms_a10		[  5];
7959743Sgroudier	u32 getjob_end		[  4];
8059743Sgroudier	u32 _sms_a20		[  4];
8159743Sgroudier	u32 select		[  8];
8259743Sgroudier	u32 _sms_a30		[  8];
8359743Sgroudier	u32 wf_sel_done		[  2];
8459743Sgroudier	u32 send_ident		[  2];
8559743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT
8659743Sgroudier	u32 select2		[  8];
8759743Sgroudier#else
8859743Sgroudier	u32 select2		[  2];
8959743Sgroudier#endif
9059743Sgroudier	u32 command		[  2];
9159743Sgroudier	u32 dispatch		[ 28];
9259743Sgroudier	u32 sel_no_cmd		[ 10];
9359743Sgroudier	u32 init		[  6];
9459743Sgroudier	u32 clrack		[  4];
9559743Sgroudier	u32 disp_status		[  4];
9659743Sgroudier	u32 datai_done		[ 26];
9759743Sgroudier	u32 datao_done		[ 12];
9859743Sgroudier	u32 datai_phase		[  2];
9959743Sgroudier	u32 datao_phase		[  2];
10059743Sgroudier	u32 msg_in		[  2];
10159743Sgroudier	u32 msg_in2		[ 10];
10259743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT
10359743Sgroudier	u32 status		[ 14];
10459743Sgroudier#else
10559743Sgroudier	u32 status		[ 10];
10659743Sgroudier#endif
10759743Sgroudier	u32 complete		[  9];
10859743Sgroudier	u32 complete2		[  8];
10959743Sgroudier	u32 _sms_a40		[ 12];
11059743Sgroudier	u32 complete_error	[  5];
11159743Sgroudier	u32 done		[  5];
11259743Sgroudier	u32 _sms_a50		[  5];
11359743Sgroudier	u32 _sms_a60		[  2];
11459743Sgroudier	u32 done_end		[  4];
11559743Sgroudier	u32 save_dp		[  9];
11659743Sgroudier	u32 restore_dp		[  5];
11759743Sgroudier	u32 disconnect		[ 20];
11859743Sgroudier	u32 disconnect2		[  5];
11959743Sgroudier	u32 _sms_a65		[  3];
12059743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT
12159743Sgroudier	u32 idle		[  4];
12259743Sgroudier#else
12359743Sgroudier	u32 idle		[  2];
12459743Sgroudier#endif
12559743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT
12659743Sgroudier	u32 ungetjob		[  7];
12759743Sgroudier#else
12859743Sgroudier	u32 ungetjob		[  5];
12959743Sgroudier#endif
13059743Sgroudier	u32 reselect		[  4];
13159743Sgroudier	u32 reselected		[ 19];
13259743Sgroudier	u32 _sms_a70		[  6];
13359743Sgroudier	u32 _sms_a80		[  4];
13459743Sgroudier	u32 reselected1		[ 25];
13559743Sgroudier	u32 _sms_a90		[  4];
13659743Sgroudier	u32 resel_lun0		[  7];
13759743Sgroudier	u32 _sms_a100		[  4];
13859743Sgroudier	u32 resel_tag		[  8];
13959743Sgroudier#if   SYM_CONF_MAX_TASK*4 > 512
14059743Sgroudier	u32 _sms_a110		[ 23];
14159743Sgroudier#elif SYM_CONF_MAX_TASK*4 > 256
14259743Sgroudier	u32 _sms_a110		[ 17];
14359743Sgroudier#else
14459743Sgroudier	u32 _sms_a110		[ 13];
14559743Sgroudier#endif
14659743Sgroudier	u32 _sms_a120		[  2];
14759743Sgroudier	u32 resel_go		[  4];
14859743Sgroudier	u32 _sms_a130		[  7];
14959743Sgroudier	u32 resel_dsa		[  2];
15059743Sgroudier	u32 resel_dsa1		[  4];
15159743Sgroudier	u32 _sms_a140		[ 10];
15259743Sgroudier	u32 resel_no_tag	[  4];
15359743Sgroudier	u32 _sms_a145		[  7];
15459743Sgroudier	u32 data_in		[SYM_CONF_MAX_SG * 2];
15559743Sgroudier	u32 data_in2		[  4];
15659743Sgroudier	u32 data_out		[SYM_CONF_MAX_SG * 2];
15759743Sgroudier	u32 data_out2		[  4];
15859743Sgroudier	u32 pm0_data		[ 12];
15959743Sgroudier	u32 pm0_data_out	[  6];
16059743Sgroudier	u32 pm0_data_end	[  7];
16159743Sgroudier	u32 pm_data_end		[  4];
16259743Sgroudier	u32 _sms_a150		[  4];
16359743Sgroudier	u32 pm1_data		[ 12];
16459743Sgroudier	u32 pm1_data_out	[  6];
16559743Sgroudier	u32 pm1_data_end	[  9];
16659743Sgroudier};
16759743Sgroudier
16859743Sgroudier/*
16959743Sgroudier *  Script fragments which stay in main memory for all chips
17059743Sgroudier *  except for chips that support 8K on-chip RAM.
17159743Sgroudier */
17259743Sgroudierstruct SYM_FWB_SCR {
17359743Sgroudier	u32 no_data		[  2];
17459743Sgroudier	u32 sel_for_abort	[ 18];
17559743Sgroudier	u32 sel_for_abort_1	[  2];
17659743Sgroudier	u32 msg_in_etc		[ 12];
17759743Sgroudier	u32 msg_received	[  5];
17859743Sgroudier	u32 msg_weird_seen	[  5];
17959743Sgroudier	u32 msg_extended	[ 17];
18059743Sgroudier	u32 _sms_b10		[  4];
18159743Sgroudier	u32 msg_bad		[  6];
18259743Sgroudier	u32 msg_weird		[  4];
18359743Sgroudier	u32 msg_weird1		[  8];
18459743Sgroudier	u32 wdtr_resp		[  6];
18559743Sgroudier	u32 send_wdtr		[  4];
18659743Sgroudier	u32 sdtr_resp		[  6];
18759743Sgroudier	u32 send_sdtr		[  4];
18859743Sgroudier	u32 ppr_resp		[  6];
18959743Sgroudier	u32 send_ppr		[  4];
19059743Sgroudier	u32 nego_bad_phase	[  4];
19159743Sgroudier	u32 msg_out		[  4];
19259743Sgroudier	u32 msg_out_done	[  4];
19359743Sgroudier	u32 data_ovrun		[  3];
19459743Sgroudier	u32 data_ovrun1		[ 22];
19559743Sgroudier	u32 data_ovrun2		[  8];
19659743Sgroudier	u32 abort_resel		[ 16];
19759743Sgroudier	u32 resend_ident	[  4];
19859743Sgroudier	u32 ident_break		[  4];
19959743Sgroudier	u32 ident_break_atn	[  4];
20059743Sgroudier	u32 sdata_in		[  6];
20159743Sgroudier	u32 resel_bad_lun	[  4];
20259743Sgroudier	u32 bad_i_t_l		[  4];
20359743Sgroudier	u32 bad_i_t_l_q		[  4];
20459743Sgroudier	u32 bad_status		[  7];
20559743Sgroudier	u32 wsr_ma_helper	[  4];
20659743Sgroudier
20759743Sgroudier	/* Data area */
20859743Sgroudier	u32 zero		[  1];
20959743Sgroudier	u32 scratch		[  1];
21059743Sgroudier	u32 scratch1		[  1];
21159743Sgroudier	u32 prev_done		[  1];
21259743Sgroudier	u32 done_pos		[  1];
21359743Sgroudier	u32 nextjob		[  1];
21459743Sgroudier	u32 startpos		[  1];
21559743Sgroudier	u32 targtbl		[  1];
21659743Sgroudier	/* End of data area */
21759743Sgroudier
21859743Sgroudier	u32 snooptest		[  9];
21959743Sgroudier	u32 snoopend		[  2];
22059743Sgroudier};
22159743Sgroudier
222179029Smariusstatic const struct SYM_FWA_SCR SYM_FWA_SCR = {
22359743Sgroudier/*--------------------------< START >----------------------------*/ {
22459743Sgroudier	/*
22559743Sgroudier	 *  Switch the LED on.
22659743Sgroudier	 *  Will be patched with a NO_OP if LED
22759743Sgroudier	 *  not needed or not desired.
22859743Sgroudier	 */
22959743Sgroudier	SCR_REG_REG (gpreg, SCR_AND, 0xfe),
23059743Sgroudier		0,
23159743Sgroudier	/*
23259743Sgroudier	 *      Clear SIGP.
23359743Sgroudier	 */
23459743Sgroudier	SCR_FROM_REG (ctest2),
23559743Sgroudier		0,
23659743Sgroudier	/*
23759743Sgroudier	 *  Stop here if the C code wants to perform
23859743Sgroudier	 *  some error recovery procedure manually.
23959743Sgroudier	 *  (Indicate this by setting SEM in ISTAT)
24059743Sgroudier	 */
24159743Sgroudier	SCR_FROM_REG (istat),
24259743Sgroudier		0,
24359743Sgroudier	/*
24459743Sgroudier	 *  Report to the C code the next position in
24559743Sgroudier	 *  the start queue the SCRIPTS will schedule.
24659743Sgroudier	 *  The C code must not change SCRATCHA.
24759743Sgroudier	 */
24859743Sgroudier	SCR_COPY (4),
24959743Sgroudier		PADDR_B (startpos),
25059743Sgroudier		RADDR_1 (scratcha),
25159743Sgroudier	SCR_INT ^ IFTRUE (MASK (SEM, SEM)),
25259743Sgroudier		SIR_SCRIPT_STOPPED,
25359743Sgroudier	/*
25459743Sgroudier	 *  Start the next job.
25559743Sgroudier	 *
25659743Sgroudier	 *  @DSA     = start point for this job.
25759743Sgroudier	 *  SCRATCHA = address of this job in the start queue.
25859743Sgroudier	 *
25959743Sgroudier	 *  We will restore startpos with SCRATCHA if we fails the
26059743Sgroudier	 *  arbitration or if it is the idle job.
26159743Sgroudier	 *
26259743Sgroudier	 *  The below GETJOB_BEGIN to GETJOB_END section of SCRIPTS
26359743Sgroudier	 *  is a critical path. If it is partially executed, it then
26459743Sgroudier	 *  may happen that the job address is not yet in the DSA
265218909Sbrucec	 *  and the next queue position points to the next JOB.
26659743Sgroudier	 */
26759743Sgroudier}/*-------------------------< GETJOB_BEGIN >---------------------*/,{
26859743Sgroudier	/*
26959743Sgroudier	 *  Copy to a fixed location both the next STARTPOS
27059743Sgroudier	 *  and the current JOB address, using self modifying
27159743Sgroudier	 *  SCRIPTS.
27259743Sgroudier	 */
27359743Sgroudier	SCR_COPY (4),
27459743Sgroudier		RADDR_1 (scratcha),
27559743Sgroudier		PADDR_A (_sms_a10),
27659743Sgroudier	SCR_COPY (8),
27759743Sgroudier}/*-------------------------< _SMS_A10 >-------------------------*/,{
27859743Sgroudier		0,
27959743Sgroudier		PADDR_B (nextjob),
28059743Sgroudier	/*
28159743Sgroudier	 *  Move the start address to TEMP using self-
28259743Sgroudier	 *  modifying SCRIPTS and jump indirectly to
28359743Sgroudier	 *  that address.
28459743Sgroudier	 */
28559743Sgroudier	SCR_COPY (4),
28659743Sgroudier		PADDR_B (nextjob),
28759743Sgroudier		RADDR_1 (dsa),
28859743Sgroudier}/*-------------------------< GETJOB_END >-----------------------*/,{
28959743Sgroudier	SCR_COPY (4),
29059743Sgroudier		RADDR_1 (dsa),
29159743Sgroudier		PADDR_A (_sms_a20),
29259743Sgroudier	SCR_COPY (4),
29359743Sgroudier}/*-------------------------< _SMS_A20 >-------------------------*/,{
29459743Sgroudier		0,
29559743Sgroudier		RADDR_1 (temp),
29659743Sgroudier	SCR_RETURN,
29759743Sgroudier		0,
29859743Sgroudier}/*-------------------------< SELECT >---------------------------*/,{
29959743Sgroudier	/*
30059743Sgroudier	 *  DSA	contains the address of a scheduled
30159743Sgroudier	 *  	data structure.
30259743Sgroudier	 *
30359743Sgroudier	 *  SCRATCHA contains the address of the start queue
30459743Sgroudier	 *  	entry which points to the next job.
30559743Sgroudier	 *
30659743Sgroudier	 *  Set Initiator mode.
30759743Sgroudier	 *
30859743Sgroudier	 *  (Target mode is left as an exercise for the reader)
30959743Sgroudier	 */
31059743Sgroudier	SCR_CLR (SCR_TRG),
31159743Sgroudier		0,
31259743Sgroudier	/*
31359743Sgroudier	 *      And try to select this target.
31459743Sgroudier	 */
31559743Sgroudier	SCR_SEL_TBL_ATN ^ offsetof (struct sym_dsb, select),
31659743Sgroudier		PADDR_A (ungetjob),
31759743Sgroudier	/*
31859743Sgroudier	 *  Now there are 4 possibilities:
31959743Sgroudier	 *
320160964Syar	 *  (1) The chip loses arbitration.
32159743Sgroudier	 *  This is ok, because it will try again,
32259743Sgroudier	 *  when the bus becomes idle.
32359743Sgroudier	 *  (But beware of the timeout function!)
32459743Sgroudier	 *
32559743Sgroudier	 *  (2) The chip is reselected.
32659743Sgroudier	 *  Then the script processor takes the jump
32759743Sgroudier	 *  to the RESELECT label.
32859743Sgroudier	 *
32959743Sgroudier	 *  (3) The chip wins arbitration.
33059743Sgroudier	 *  Then it will execute SCRIPTS instruction until
33159743Sgroudier	 *  the next instruction that checks SCSI phase.
33259743Sgroudier	 *  Then will stop and wait for selection to be
33359743Sgroudier	 *  complete or selection time-out to occur.
33459743Sgroudier	 *
33559743Sgroudier	 *  After having won arbitration, the SCRIPTS
33659743Sgroudier	 *  processor is able to execute instructions while
33759743Sgroudier	 *  the SCSI core is performing SCSI selection.
33859743Sgroudier	 */
33959743Sgroudier
34059743Sgroudier	/*
34159743Sgroudier	 *  Copy the CCB header to a fixed location
34259743Sgroudier	 *  in the HCB using self-modifying SCRIPTS.
34359743Sgroudier	 */
34459743Sgroudier	SCR_COPY (4),
34559743Sgroudier		RADDR_1 (dsa),
34659743Sgroudier		PADDR_A (_sms_a30),
34759743Sgroudier	SCR_COPY (sizeof(struct sym_ccbh)),
34859743Sgroudier}/*-------------------------< _SMS_A30 >-------------------------*/,{
34959743Sgroudier		0,
35059743Sgroudier		HADDR_1 (ccb_head),
35159743Sgroudier	/*
35259743Sgroudier	 *  Load the savep (saved data pointer) into
35359743Sgroudier	 *  the actual data pointer.
35459743Sgroudier	 */
35559743Sgroudier	SCR_COPY (4),
35659743Sgroudier		HADDR_1 (ccb_head.savep),
35759743Sgroudier		RADDR_1 (temp),
35859743Sgroudier	/*
35959743Sgroudier	 *  Initialize the status register
36059743Sgroudier	 */
36159743Sgroudier	SCR_COPY (4),
36259743Sgroudier		HADDR_1 (ccb_head.status),
36359743Sgroudier		RADDR_1 (scr0),
36459743Sgroudier}/*-------------------------< WF_SEL_DONE >----------------------*/,{
36559743Sgroudier	SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)),
36659743Sgroudier		SIR_SEL_ATN_NO_MSG_OUT,
36759743Sgroudier}/*-------------------------< SEND_IDENT >-----------------------*/,{
36859743Sgroudier	/*
36959743Sgroudier	 *  Selection complete.
37059743Sgroudier	 *  Send the IDENTIFY and possibly the TAG message
37159743Sgroudier	 *  and negotiation message if present.
37259743Sgroudier	 */
37359743Sgroudier	SCR_MOVE_TBL ^ SCR_MSG_OUT,
37459743Sgroudier		offsetof (struct sym_dsb, smsg),
37559743Sgroudier}/*-------------------------< SELECT2 >--------------------------*/,{
37659743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT
37759743Sgroudier	/*
37859743Sgroudier	 *  Set IMMEDIATE ARBITRATION if we have been given
37959743Sgroudier	 *  a hint to do so. (Some job to do after this one).
38059743Sgroudier	 */
38159743Sgroudier	SCR_FROM_REG (HF_REG),
38259743Sgroudier		0,
38359743Sgroudier	SCR_JUMPR ^ IFFALSE (MASK (HF_HINT_IARB, HF_HINT_IARB)),
38459743Sgroudier		8,
38559743Sgroudier	SCR_REG_REG (scntl1, SCR_OR, IARB),
38659743Sgroudier		0,
38759743Sgroudier#endif
38859743Sgroudier	/*
38959743Sgroudier	 *  Anticipate the COMMAND phase.
39059743Sgroudier	 *  This is the PHASE we expect at this point.
39159743Sgroudier	 */
39259743Sgroudier	SCR_JUMP ^ IFFALSE (WHEN (SCR_COMMAND)),
39359743Sgroudier		PADDR_A (sel_no_cmd),
39459743Sgroudier}/*-------------------------< COMMAND >--------------------------*/,{
39559743Sgroudier	/*
39659743Sgroudier	 *  ... and send the command
39759743Sgroudier	 */
39859743Sgroudier	SCR_MOVE_TBL ^ SCR_COMMAND,
39959743Sgroudier		offsetof (struct sym_dsb, cmd),
40059743Sgroudier}/*-------------------------< DISPATCH >-------------------------*/,{
40159743Sgroudier	/*
40259743Sgroudier	 *  MSG_IN is the only phase that shall be
40359743Sgroudier	 *  entered at least once for each (re)selection.
40459743Sgroudier	 *  So we test it first.
40559743Sgroudier	 */
40659743Sgroudier	SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)),
40759743Sgroudier		PADDR_A (msg_in),
40859743Sgroudier	SCR_JUMP ^ IFTRUE (IF (SCR_DATA_OUT)),
40959743Sgroudier		PADDR_A (datao_phase),
41059743Sgroudier	SCR_JUMP ^ IFTRUE (IF (SCR_DATA_IN)),
41159743Sgroudier		PADDR_A (datai_phase),
41259743Sgroudier	SCR_JUMP ^ IFTRUE (IF (SCR_STATUS)),
41359743Sgroudier		PADDR_A (status),
41459743Sgroudier	SCR_JUMP ^ IFTRUE (IF (SCR_COMMAND)),
41559743Sgroudier		PADDR_A (command),
41659743Sgroudier	SCR_JUMP ^ IFTRUE (IF (SCR_MSG_OUT)),
41759743Sgroudier		PADDR_B (msg_out),
41859743Sgroudier	/*
41959743Sgroudier	 *  Discard as many illegal phases as
42059743Sgroudier	 *  required and tell the C code about.
42159743Sgroudier	 */
42259743Sgroudier	SCR_JUMPR ^ IFFALSE (WHEN (SCR_ILG_OUT)),
42359743Sgroudier		16,
42459743Sgroudier	SCR_MOVE_ABS (1) ^ SCR_ILG_OUT,
42559743Sgroudier		HADDR_1 (scratch),
42659743Sgroudier	SCR_JUMPR ^ IFTRUE (WHEN (SCR_ILG_OUT)),
42759743Sgroudier		-16,
42859743Sgroudier	SCR_JUMPR ^ IFFALSE (WHEN (SCR_ILG_IN)),
42959743Sgroudier		16,
43059743Sgroudier	SCR_MOVE_ABS (1) ^ SCR_ILG_IN,
43159743Sgroudier		HADDR_1 (scratch),
43259743Sgroudier	SCR_JUMPR ^ IFTRUE (WHEN (SCR_ILG_IN)),
43359743Sgroudier		-16,
43459743Sgroudier	SCR_INT,
43559743Sgroudier		SIR_BAD_PHASE,
43659743Sgroudier	SCR_JUMP,
43759743Sgroudier		PADDR_A (dispatch),
43859743Sgroudier}/*-------------------------< SEL_NO_CMD >-----------------------*/,{
43959743Sgroudier	/*
44059743Sgroudier	 *  The target does not switch to command
44159743Sgroudier	 *  phase after IDENTIFY has been sent.
44259743Sgroudier	 *
44359743Sgroudier	 *  If it stays in MSG OUT phase send it
44459743Sgroudier	 *  the IDENTIFY again.
44559743Sgroudier	 */
44659743Sgroudier	SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_OUT)),
44759743Sgroudier		PADDR_B (resend_ident),
44859743Sgroudier	/*
44959743Sgroudier	 *  If target does not switch to MSG IN phase
45059743Sgroudier	 *  and we sent a negotiation, assert the
45159743Sgroudier	 *  failure immediately.
45259743Sgroudier	 */
45359743Sgroudier	SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)),
45459743Sgroudier		PADDR_A (dispatch),
45559743Sgroudier	SCR_FROM_REG (HS_REG),
45659743Sgroudier		0,
45759743Sgroudier	SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)),
45859743Sgroudier		SIR_NEGO_FAILED,
45959743Sgroudier	/*
46059743Sgroudier	 *  Jump to dispatcher.
46159743Sgroudier	 */
46259743Sgroudier	SCR_JUMP,
46359743Sgroudier		PADDR_A (dispatch),
46459743Sgroudier}/*-------------------------< INIT >-----------------------------*/,{
46559743Sgroudier	/*
46659743Sgroudier	 *  Wait for the SCSI RESET signal to be
46759743Sgroudier	 *  inactive before restarting operations,
46859743Sgroudier	 *  since the chip may hang on SEL_ATN
46959743Sgroudier	 *  if SCSI RESET is active.
47059743Sgroudier	 */
47159743Sgroudier	SCR_FROM_REG (sstat0),
47259743Sgroudier		0,
47359743Sgroudier	SCR_JUMPR ^ IFTRUE (MASK (IRST, IRST)),
47459743Sgroudier		-16,
47559743Sgroudier	SCR_JUMP,
47659743Sgroudier		PADDR_A (start),
47759743Sgroudier}/*-------------------------< CLRACK >---------------------------*/,{
47859743Sgroudier	/*
47959743Sgroudier	 *  Terminate possible pending message phase.
48059743Sgroudier	 */
48159743Sgroudier	SCR_CLR (SCR_ACK),
48259743Sgroudier		0,
48359743Sgroudier	SCR_JUMP,
48459743Sgroudier		PADDR_A (dispatch),
48559743Sgroudier}/*-------------------------< DISP_STATUS >----------------------*/,{
48659743Sgroudier	/*
48759743Sgroudier	 *  Anticipate STATUS phase.
48859743Sgroudier	 *
48959743Sgroudier	 *  Does spare 3 SCRIPTS instructions when we have
49059743Sgroudier	 *  completed the INPUT of the data.
49159743Sgroudier	 */
49259743Sgroudier	SCR_JUMP ^ IFTRUE (WHEN (SCR_STATUS)),
49359743Sgroudier		PADDR_A (status),
49459743Sgroudier	SCR_JUMP,
49559743Sgroudier		PADDR_A (dispatch),
49659743Sgroudier}/*-------------------------< DATAI_DONE >-----------------------*/,{
49759743Sgroudier	/*
49859743Sgroudier	 *  If the device still wants to send us data,
49959743Sgroudier	 *  we must count the extra bytes.
50059743Sgroudier	 */
50159743Sgroudier	SCR_JUMP ^ IFTRUE (WHEN (SCR_DATA_IN)),
50259743Sgroudier		PADDR_B (data_ovrun),
50359743Sgroudier	/*
50459743Sgroudier	 *  If the SWIDE is not full, jump to dispatcher.
50559743Sgroudier	 *  We anticipate a STATUS phase.
50659743Sgroudier	 */
50759743Sgroudier	SCR_FROM_REG (scntl2),
50859743Sgroudier		0,
50959743Sgroudier	SCR_JUMP ^ IFFALSE (MASK (WSR, WSR)),
51059743Sgroudier		PADDR_A (disp_status),
51159743Sgroudier	/*
51259743Sgroudier	 *  The SWIDE is full.
51359743Sgroudier	 *  Clear this condition.
51459743Sgroudier	 */
51559743Sgroudier	SCR_REG_REG (scntl2, SCR_OR, WSR),
51659743Sgroudier		0,
51759743Sgroudier	/*
51859743Sgroudier	 *  We are expecting an IGNORE RESIDUE message
51959743Sgroudier	 *  from the device, otherwise we are in data
52059743Sgroudier	 *  overrun condition. Check against MSG_IN phase.
52159743Sgroudier	 */
52259743Sgroudier	SCR_INT ^ IFFALSE (WHEN (SCR_MSG_IN)),
52359743Sgroudier		SIR_SWIDE_OVERRUN,
52459743Sgroudier	SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)),
52559743Sgroudier		PADDR_A (disp_status),
52659743Sgroudier	/*
52759743Sgroudier	 *  We are in MSG_IN phase,
52859743Sgroudier	 *  Read the first byte of the message.
52959743Sgroudier	 *  If it is not an IGNORE RESIDUE message,
53059743Sgroudier	 *  signal overrun and jump to message
53159743Sgroudier	 *  processing.
53259743Sgroudier	 */
53359743Sgroudier	SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
53459743Sgroudier		HADDR_1 (msgin[0]),
53559743Sgroudier	SCR_INT ^ IFFALSE (DATA (M_IGN_RESIDUE)),
53659743Sgroudier		SIR_SWIDE_OVERRUN,
53759743Sgroudier	SCR_JUMP ^ IFFALSE (DATA (M_IGN_RESIDUE)),
53859743Sgroudier		PADDR_A (msg_in2),
53959743Sgroudier	/*
54059743Sgroudier	 *  We got the message we expected.
54159743Sgroudier	 *  Read the 2nd byte, and jump to dispatcher.
54259743Sgroudier	 */
54359743Sgroudier	SCR_CLR (SCR_ACK),
54459743Sgroudier		0,
54559743Sgroudier	SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
54659743Sgroudier		HADDR_1 (msgin[1]),
54759743Sgroudier	SCR_CLR (SCR_ACK),
54859743Sgroudier		0,
54959743Sgroudier	SCR_JUMP,
55059743Sgroudier		PADDR_A (disp_status),
55159743Sgroudier}/*-------------------------< DATAO_DONE >-----------------------*/,{
55259743Sgroudier	/*
55359743Sgroudier	 *  If the device wants us to send more data,
55459743Sgroudier	 *  we must count the extra bytes.
55559743Sgroudier	 */
55659743Sgroudier	SCR_JUMP ^ IFTRUE (WHEN (SCR_DATA_OUT)),
55759743Sgroudier		PADDR_B (data_ovrun),
55859743Sgroudier	/*
55959743Sgroudier	 *  If the SODL is not full jump to dispatcher.
56059743Sgroudier	 *  We anticipate a STATUS phase.
56159743Sgroudier	 */
56259743Sgroudier	SCR_FROM_REG (scntl2),
56359743Sgroudier		0,
56459743Sgroudier	SCR_JUMP ^ IFFALSE (MASK (WSS, WSS)),
56559743Sgroudier		PADDR_A (disp_status),
56659743Sgroudier	/*
56759743Sgroudier	 *  The SODL is full, clear this condition.
56859743Sgroudier	 */
56959743Sgroudier	SCR_REG_REG (scntl2, SCR_OR, WSS),
57059743Sgroudier		0,
57159743Sgroudier	/*
57259743Sgroudier	 *  And signal a DATA UNDERRUN condition
57359743Sgroudier	 *  to the C code.
57459743Sgroudier	 */
57559743Sgroudier	SCR_INT,
57659743Sgroudier		SIR_SODL_UNDERRUN,
57759743Sgroudier	SCR_JUMP,
57859743Sgroudier		PADDR_A (dispatch),
57959743Sgroudier}/*-------------------------< DATAI_PHASE >----------------------*/,{
58059743Sgroudier	SCR_RETURN,
58159743Sgroudier		0,
58259743Sgroudier}/*-------------------------< DATAO_PHASE >----------------------*/,{
58359743Sgroudier	SCR_RETURN,
58459743Sgroudier		0,
58559743Sgroudier}/*-------------------------< MSG_IN >---------------------------*/,{
58659743Sgroudier	/*
58759743Sgroudier	 *  Get the first byte of the message.
58859743Sgroudier	 *
58959743Sgroudier	 *  The script processor doesn't negate the
59059743Sgroudier	 *  ACK signal after this transfer.
59159743Sgroudier	 */
59259743Sgroudier	SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
59359743Sgroudier		HADDR_1 (msgin[0]),
59459743Sgroudier}/*-------------------------< MSG_IN2 >--------------------------*/,{
59559743Sgroudier	/*
59659743Sgroudier	 *  Check first against 1 byte messages
59759743Sgroudier	 *  that we handle from SCRIPTS.
59859743Sgroudier	 */
59959743Sgroudier	SCR_JUMP ^ IFTRUE (DATA (M_COMPLETE)),
60059743Sgroudier		PADDR_A (complete),
60159743Sgroudier	SCR_JUMP ^ IFTRUE (DATA (M_DISCONNECT)),
60259743Sgroudier		PADDR_A (disconnect),
60359743Sgroudier	SCR_JUMP ^ IFTRUE (DATA (M_SAVE_DP)),
60459743Sgroudier		PADDR_A (save_dp),
60559743Sgroudier	SCR_JUMP ^ IFTRUE (DATA (M_RESTORE_DP)),
60659743Sgroudier		PADDR_A (restore_dp),
60759743Sgroudier	/*
60859743Sgroudier	 *  We handle all other messages from the
60959743Sgroudier	 *  C code, so no need to waste on-chip RAM
61059743Sgroudier	 *  for those ones.
61159743Sgroudier	 */
61259743Sgroudier	SCR_JUMP,
61359743Sgroudier		PADDR_B (msg_in_etc),
61459743Sgroudier}/*-------------------------< STATUS >---------------------------*/,{
61559743Sgroudier	/*
61659743Sgroudier	 *  get the status
61759743Sgroudier	 */
61859743Sgroudier	SCR_MOVE_ABS (1) ^ SCR_STATUS,
61959743Sgroudier		HADDR_1 (scratch),
62059743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT
62159743Sgroudier	/*
62259743Sgroudier	 *  If STATUS is not GOOD, clear IMMEDIATE ARBITRATION,
62359743Sgroudier	 *  since we may have to tamper the start queue from
62459743Sgroudier	 *  the C code.
62559743Sgroudier	 */
62659743Sgroudier	SCR_JUMPR ^ IFTRUE (DATA (S_GOOD)),
62759743Sgroudier		8,
62859743Sgroudier	SCR_REG_REG (scntl1, SCR_AND, ~IARB),
62959743Sgroudier		0,
63059743Sgroudier#endif
63159743Sgroudier	/*
63259743Sgroudier	 *  save status to scsi_status.
63359743Sgroudier	 *  mark as complete.
63459743Sgroudier	 */
63559743Sgroudier	SCR_TO_REG (SS_REG),
63659743Sgroudier		0,
63759743Sgroudier	SCR_LOAD_REG (HS_REG, HS_COMPLETE),
63859743Sgroudier		0,
63959743Sgroudier	/*
64059743Sgroudier	 *  Anticipate the MESSAGE PHASE for
64159743Sgroudier	 *  the TASK COMPLETE message.
64259743Sgroudier	 */
64359743Sgroudier	SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)),
64459743Sgroudier		PADDR_A (msg_in),
64559743Sgroudier	SCR_JUMP,
64659743Sgroudier		PADDR_A (dispatch),
64759743Sgroudier}/*-------------------------< COMPLETE >-------------------------*/,{
64859743Sgroudier	/*
64959743Sgroudier	 *  Complete message.
65059743Sgroudier	 *
65159743Sgroudier	 *  Copy the data pointer to LASTP.
65259743Sgroudier	 */
65359743Sgroudier	SCR_COPY (4),
65459743Sgroudier		RADDR_1 (temp),
65559743Sgroudier		HADDR_1 (ccb_head.lastp),
65659743Sgroudier	/*
65759743Sgroudier	 *  When we terminate the cycle by clearing ACK,
65859743Sgroudier	 *  the target may disconnect immediately.
65959743Sgroudier	 *
66059743Sgroudier	 *  We don't want to be told of an "unexpected disconnect",
66159743Sgroudier	 *  so we disable this feature.
66259743Sgroudier	 */
66359743Sgroudier	SCR_REG_REG (scntl2, SCR_AND, 0x7f),
66459743Sgroudier		0,
66559743Sgroudier	/*
66659743Sgroudier	 *  Terminate cycle ...
66759743Sgroudier	 */
66859743Sgroudier	SCR_CLR (SCR_ACK|SCR_ATN),
66959743Sgroudier		0,
67059743Sgroudier	/*
67159743Sgroudier	 *  ... and wait for the disconnect.
67259743Sgroudier	 */
67359743Sgroudier	SCR_WAIT_DISC,
67459743Sgroudier		0,
67559743Sgroudier}/*-------------------------< COMPLETE2 >------------------------*/,{
67659743Sgroudier	/*
67759743Sgroudier	 *  Save host status.
67859743Sgroudier	 */
67959743Sgroudier	SCR_COPY (4),
68059743Sgroudier		RADDR_1 (scr0),
68159743Sgroudier		HADDR_1 (ccb_head.status),
68259743Sgroudier	/*
68359743Sgroudier	 *  Move back the CCB header using self-modifying
68459743Sgroudier	 *  SCRIPTS.
68559743Sgroudier	 */
68659743Sgroudier	SCR_COPY (4),
68759743Sgroudier		RADDR_1 (dsa),
68859743Sgroudier		PADDR_A (_sms_a40),
68959743Sgroudier	SCR_COPY (sizeof(struct sym_ccbh)),
69059743Sgroudier		HADDR_1 (ccb_head),
69159743Sgroudier}/*-------------------------< _SMS_A40 >-------------------------*/,{
69259743Sgroudier		0,
69359743Sgroudier	/*
69459743Sgroudier	 *  Some bridges may reorder DMA writes to memory.
69559743Sgroudier	 *  We donnot want the CPU to deal with completions
69659743Sgroudier	 *  without all the posted write having been flushed
69759743Sgroudier	 *  to memory. This DUMMY READ should flush posted
69859743Sgroudier	 *  buffers prior to the CPU having to deal with
69959743Sgroudier	 *  completions.
70059743Sgroudier	 */
70159743Sgroudier	SCR_COPY (4),			/* DUMMY READ */
70259743Sgroudier		HADDR_1 (ccb_head.status),
70359743Sgroudier		RADDR_1 (scr0),
70459743Sgroudier	/*
70559743Sgroudier	 *  If command resulted in not GOOD status,
70659743Sgroudier	 *  call the C code if needed.
70759743Sgroudier	 */
70859743Sgroudier	SCR_FROM_REG (SS_REG),
70959743Sgroudier		0,
71059743Sgroudier	SCR_CALL ^ IFFALSE (DATA (S_GOOD)),
71159743Sgroudier		PADDR_B (bad_status),
71259743Sgroudier	/*
71359743Sgroudier	 *  If we performed an auto-sense, call
71459743Sgroudier	 *  the C code to synchronyze task aborts
71559743Sgroudier	 *  with UNIT ATTENTION conditions.
71659743Sgroudier	 */
71759743Sgroudier	SCR_FROM_REG (HF_REG),
71859743Sgroudier		0,
71959743Sgroudier	SCR_JUMP ^ IFTRUE (MASK (0 ,(HF_SENSE|HF_EXT_ERR))),
72059743Sgroudier		PADDR_A (done),
72159743Sgroudier}/*-------------------------< COMPLETE_ERROR >-------------------*/,{
72259743Sgroudier	SCR_COPY (4),
72359743Sgroudier		PADDR_B (startpos),
72459743Sgroudier		RADDR_1 (scratcha),
72559743Sgroudier	SCR_INT,
72659743Sgroudier		SIR_COMPLETE_ERROR,
72759743Sgroudier}/*-------------------------< DONE >-----------------------------*/,{
72859743Sgroudier	/*
72959743Sgroudier	 *  Copy the DSA to the DONE QUEUE and
73059743Sgroudier	 *  signal completion to the host.
73159743Sgroudier	 *  If we are interrupted between DONE
73259743Sgroudier	 *  and DONE_END, we must reset, otherwise
73359743Sgroudier	 *  the completed CCB may be lost.
73459743Sgroudier	 */
73559743Sgroudier	SCR_COPY (4),
73659743Sgroudier		PADDR_B (done_pos),
73759743Sgroudier		PADDR_A (_sms_a50),
73859743Sgroudier	SCR_COPY (4),
73959743Sgroudier		RADDR_1 (dsa),
74059743Sgroudier}/*-------------------------< _SMS_A50 >-------------------------*/,{
74159743Sgroudier		0,
74259743Sgroudier	SCR_COPY (4),
74359743Sgroudier		PADDR_B (done_pos),
74459743Sgroudier		PADDR_A (_sms_a60),
74559743Sgroudier	/*
74659743Sgroudier	 *  The instruction below reads the DONE QUEUE next
74759743Sgroudier	 *  free position from memory.
74859743Sgroudier	 *  In addition it ensures that all PCI posted writes
74959743Sgroudier	 *  are flushed and so the DSA value of the done
75059743Sgroudier	 *  CCB is visible by the CPU before INTFLY is raised.
75159743Sgroudier	 */
75259743Sgroudier	SCR_COPY (8),
75359743Sgroudier}/*-------------------------< _SMS_A60 >-------------------------*/,{
75459743Sgroudier		0,
75559743Sgroudier		PADDR_B (prev_done),
75659743Sgroudier}/*-------------------------< DONE_END >-------------------------*/,{
75759743Sgroudier	SCR_INT_FLY,
75859743Sgroudier		0,
75959743Sgroudier	SCR_JUMP,
76059743Sgroudier		PADDR_A (start),
76159743Sgroudier}/*-------------------------< SAVE_DP >--------------------------*/,{
76259743Sgroudier	/*
76359743Sgroudier	 *  Clear ACK immediately.
76459743Sgroudier	 *  No need to delay it.
76559743Sgroudier	 */
76659743Sgroudier	SCR_CLR (SCR_ACK),
76759743Sgroudier		0,
76859743Sgroudier	/*
76959743Sgroudier	 *  Keep track we received a SAVE DP, so
77059743Sgroudier	 *  we will switch to the other PM context
77159743Sgroudier	 *  on the next PM since the DP may point
77259743Sgroudier	 *  to the current PM context.
77359743Sgroudier	 */
77459743Sgroudier	SCR_REG_REG (HF_REG, SCR_OR, HF_DP_SAVED),
77559743Sgroudier		0,
77659743Sgroudier	/*
77759743Sgroudier	 *  SAVE_DP message:
77859743Sgroudier	 *  Copy the data pointer to SAVEP.
77959743Sgroudier	 */
78059743Sgroudier	SCR_COPY (4),
78159743Sgroudier		RADDR_1 (temp),
78259743Sgroudier		HADDR_1 (ccb_head.savep),
78359743Sgroudier	SCR_JUMP,
78459743Sgroudier		PADDR_A (dispatch),
78559743Sgroudier}/*-------------------------< RESTORE_DP >-----------------------*/,{
78659743Sgroudier	/*
78759743Sgroudier	 *  RESTORE_DP message:
78859743Sgroudier	 *  Copy SAVEP to actual data pointer.
78959743Sgroudier	 */
79059743Sgroudier	SCR_COPY (4),
79159743Sgroudier		HADDR_1 (ccb_head.savep),
79259743Sgroudier		RADDR_1 (temp),
79359743Sgroudier	SCR_JUMP,
79459743Sgroudier		PADDR_A (clrack),
79559743Sgroudier}/*-------------------------< DISCONNECT >-----------------------*/,{
79659743Sgroudier	/*
79759743Sgroudier	 *  DISCONNECTing  ...
79859743Sgroudier	 *
79959743Sgroudier	 *  disable the "unexpected disconnect" feature,
80059743Sgroudier	 *  and remove the ACK signal.
80159743Sgroudier	 */
80259743Sgroudier	SCR_REG_REG (scntl2, SCR_AND, 0x7f),
80359743Sgroudier		0,
80459743Sgroudier	SCR_CLR (SCR_ACK|SCR_ATN),
80559743Sgroudier		0,
80659743Sgroudier	/*
80759743Sgroudier	 *  Wait for the disconnect.
80859743Sgroudier	 */
80959743Sgroudier	SCR_WAIT_DISC,
81059743Sgroudier		0,
81159743Sgroudier	/*
81259743Sgroudier	 *  Status is: DISCONNECTED.
81359743Sgroudier	 */
81459743Sgroudier	SCR_LOAD_REG (HS_REG, HS_DISCONNECT),
81559743Sgroudier		0,
81659743Sgroudier	/*
81759743Sgroudier	 *  Save host status.
81859743Sgroudier	 */
81959743Sgroudier	SCR_COPY (4),
82059743Sgroudier		RADDR_1 (scr0),
82159743Sgroudier		HADDR_1 (ccb_head.status),
82259743Sgroudier	/*
82359743Sgroudier	 *  If QUIRK_AUTOSAVE is set,
824108470Sschweikh	 *  do a "save pointer" operation.
82559743Sgroudier	 */
82659743Sgroudier	SCR_FROM_REG (QU_REG),
82759743Sgroudier		0,
82859743Sgroudier	SCR_JUMP ^ IFFALSE (MASK (SYM_QUIRK_AUTOSAVE, SYM_QUIRK_AUTOSAVE)),
82959743Sgroudier		PADDR_A (disconnect2),
83059743Sgroudier	/*
83159743Sgroudier	 *  like SAVE_DP message:
83259743Sgroudier	 *  Remember we saved the data pointer.
83359743Sgroudier	 *  Copy data pointer to SAVEP.
83459743Sgroudier	 */
83559743Sgroudier	SCR_REG_REG (HF_REG, SCR_OR, HF_DP_SAVED),
83659743Sgroudier		0,
83759743Sgroudier	SCR_COPY (4),
83859743Sgroudier		RADDR_1 (temp),
83959743Sgroudier		HADDR_1 (ccb_head.savep),
84059743Sgroudier}/*-------------------------< DISCONNECT2 >----------------------*/,{
84159743Sgroudier	/*
84259743Sgroudier	 *  Move back the CCB header using self-modifying
84359743Sgroudier	 *  SCRIPTS.
84459743Sgroudier	 */
84559743Sgroudier	SCR_COPY (4),
84659743Sgroudier		RADDR_1 (dsa),
84759743Sgroudier		PADDR_A (_sms_a65),
84859743Sgroudier	SCR_COPY (sizeof(struct sym_ccbh)),
84959743Sgroudier		HADDR_1 (ccb_head),
85059743Sgroudier}/*-------------------------< _SMS_A65 >-------------------------*/,{
85159743Sgroudier		0,
85259743Sgroudier	SCR_JUMP,
85359743Sgroudier		PADDR_A (start),
85459743Sgroudier}/*-------------------------< IDLE >-----------------------------*/,{
85559743Sgroudier	/*
85659743Sgroudier	 *  Nothing to do?
85759743Sgroudier	 *  Switch the LED off and wait for reselect.
85859743Sgroudier	 *  Will be patched with a NO_OP if LED
85959743Sgroudier	 *  not needed or not desired.
86059743Sgroudier	 */
86159743Sgroudier	SCR_REG_REG (gpreg, SCR_OR, 0x01),
86259743Sgroudier		0,
86359743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT
86459743Sgroudier	SCR_JUMPR,
86559743Sgroudier		8,
86659743Sgroudier#endif
86759743Sgroudier}/*-------------------------< UNGETJOB >-------------------------*/,{
86859743Sgroudier#ifdef SYM_CONF_IARB_SUPPORT
86959743Sgroudier	/*
87059743Sgroudier	 *  Set IMMEDIATE ARBITRATION, for the next time.
87159743Sgroudier	 *  This will give us better chance to win arbitration
87259743Sgroudier	 *  for the job we just wanted to do.
87359743Sgroudier	 */
87459743Sgroudier	SCR_REG_REG (scntl1, SCR_OR, IARB),
87559743Sgroudier		0,
87659743Sgroudier#endif
87759743Sgroudier	/*
87859743Sgroudier	 *  We are not able to restart the SCRIPTS if we are
87959743Sgroudier	 *  interrupted and these instruction haven't been
88059743Sgroudier	 *  all executed. BTW, this is very unlikely to
88159743Sgroudier	 *  happen, but we check that from the C code.
88259743Sgroudier	 */
88359743Sgroudier	SCR_LOAD_REG (dsa, 0xff),
88459743Sgroudier		0,
88559743Sgroudier	SCR_COPY (4),
88659743Sgroudier		RADDR_1 (scratcha),
88759743Sgroudier		PADDR_B (startpos),
88859743Sgroudier}/*-------------------------< RESELECT >-------------------------*/,{
88959743Sgroudier	/*
89059743Sgroudier	 *  Make sure we are in initiator mode.
89159743Sgroudier	 */
89259743Sgroudier	SCR_CLR (SCR_TRG),
89359743Sgroudier		0,
89459743Sgroudier	/*
89559743Sgroudier	 *  Sleep waiting for a reselection.
89659743Sgroudier	 */
89759743Sgroudier	SCR_WAIT_RESEL,
89859743Sgroudier		PADDR_A(start),
89959743Sgroudier}/*-------------------------< RESELECTED >-----------------------*/,{
90059743Sgroudier	/*
90159743Sgroudier	 *  Switch the LED on.
90259743Sgroudier	 *  Will be patched with a NO_OP if LED
90359743Sgroudier	 *  not needed or not desired.
90459743Sgroudier	 */
90559743Sgroudier	SCR_REG_REG (gpreg, SCR_AND, 0xfe),
90659743Sgroudier		0,
90759743Sgroudier	/*
90859743Sgroudier	 *  load the target id into the sdid
90959743Sgroudier	 */
91059743Sgroudier	SCR_REG_SFBR (ssid, SCR_AND, 0x8F),
91159743Sgroudier		0,
91259743Sgroudier	SCR_TO_REG (sdid),
91359743Sgroudier		0,
91459743Sgroudier	/*
91559743Sgroudier	 *  Load the target control block address
91659743Sgroudier	 */
91759743Sgroudier	SCR_COPY (4),
91859743Sgroudier		PADDR_B (targtbl),
91959743Sgroudier		RADDR_1 (dsa),
92059743Sgroudier	SCR_SFBR_REG (dsa, SCR_SHL, 0),
92159743Sgroudier		0,
92259743Sgroudier	SCR_REG_REG (dsa, SCR_SHL, 0),
92359743Sgroudier		0,
92459743Sgroudier	SCR_REG_REG (dsa, SCR_AND, 0x3c),
92559743Sgroudier		0,
92659743Sgroudier	SCR_COPY (4),
92759743Sgroudier		RADDR_1 (dsa),
92859743Sgroudier		PADDR_A (_sms_a70),
92959743Sgroudier	SCR_COPY (4),
93059743Sgroudier}/*-------------------------< _SMS_A70 >-------------------------*/,{
93159743Sgroudier		0,
93259743Sgroudier		RADDR_1 (dsa),
93359743Sgroudier	/*
93459743Sgroudier	 *  Copy the TCB header to a fixed place in
93559743Sgroudier	 *  the HCB.
93659743Sgroudier	 */
93759743Sgroudier	SCR_COPY (4),
93859743Sgroudier		RADDR_1 (dsa),
93959743Sgroudier		PADDR_A (_sms_a80),
94059743Sgroudier	SCR_COPY (sizeof(struct sym_tcbh)),
94159743Sgroudier}/*-------------------------< _SMS_A80 >-------------------------*/,{
94259743Sgroudier		0,
94359743Sgroudier		HADDR_1 (tcb_head),
94459743Sgroudier	/*
94559743Sgroudier	 *  We expect MESSAGE IN phase.
94659743Sgroudier	 *  If not, get help from the C code.
94759743Sgroudier	 */
94859743Sgroudier	SCR_INT ^ IFFALSE (WHEN (SCR_MSG_IN)),
94959743Sgroudier		SIR_RESEL_NO_MSG_IN,
95059743Sgroudier}/*-------------------------< RESELECTED1 >----------------------*/,{
95159743Sgroudier	/*
95259743Sgroudier	 *  Load the synchronous transfer registers.
95359743Sgroudier	 */
95459743Sgroudier	SCR_COPY (1),
95559743Sgroudier		HADDR_1 (tcb_head.wval),
95659743Sgroudier		RADDR_1 (scntl3),
95759743Sgroudier	SCR_COPY (1),
95859743Sgroudier		HADDR_1 (tcb_head.sval),
95959743Sgroudier		RADDR_1 (sxfer),
96059743Sgroudier	/*
96159743Sgroudier	 *  Get the IDENTIFY message.
96259743Sgroudier	 */
96359743Sgroudier	SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
96459743Sgroudier		HADDR_1 (msgin),
96559743Sgroudier	/*
96659743Sgroudier	 *  If IDENTIFY LUN #0, use a faster path
96759743Sgroudier	 *  to find the LCB structure.
96859743Sgroudier	 */
96959743Sgroudier	SCR_JUMP ^ IFTRUE (MASK (0x80, 0xbf)),
97059743Sgroudier		PADDR_A (resel_lun0),
97159743Sgroudier	/*
97259743Sgroudier	 *  If message isn't an IDENTIFY,
97359743Sgroudier	 *  tell the C code about.
97459743Sgroudier	 */
97559743Sgroudier	SCR_INT ^ IFFALSE (MASK (0x80, 0x80)),
97659743Sgroudier		SIR_RESEL_NO_IDENTIFY,
97759743Sgroudier	/*
97859743Sgroudier	 *  It is an IDENTIFY message,
97959743Sgroudier	 *  Load the LUN control block address.
98059743Sgroudier	 */
98159743Sgroudier	SCR_COPY (4),
98259743Sgroudier		HADDR_1 (tcb_head.luntbl_sa),
98359743Sgroudier		RADDR_1 (dsa),
98459743Sgroudier	SCR_SFBR_REG (dsa, SCR_SHL, 0),
98559743Sgroudier		0,
98659743Sgroudier	SCR_REG_REG (dsa, SCR_SHL, 0),
98759743Sgroudier		0,
98859743Sgroudier	SCR_REG_REG (dsa, SCR_AND, 0xfc),
98959743Sgroudier		0,
99059743Sgroudier	SCR_COPY (4),
99159743Sgroudier		RADDR_1 (dsa),
99259743Sgroudier		PADDR_A (_sms_a90),
99359743Sgroudier	SCR_COPY (4),
99459743Sgroudier}/*-------------------------< _SMS_A90 >-------------------------*/,{
99559743Sgroudier		0,
99659743Sgroudier		RADDR_1 (dsa),
99759743Sgroudier	SCR_JUMPR,
99859743Sgroudier		12,
99959743Sgroudier}/*-------------------------< RESEL_LUN0 >-----------------------*/,{
100059743Sgroudier	/*
100159743Sgroudier	 *  LUN 0 special case (but usual one :))
100259743Sgroudier	 */
100359743Sgroudier	SCR_COPY (4),
100459743Sgroudier		HADDR_1 (tcb_head.lun0_sa),
100559743Sgroudier		RADDR_1 (dsa),
100659743Sgroudier	/*
100759743Sgroudier	 *  Jump indirectly to the reselect action for this LUN.
100859743Sgroudier	 *  (lcb.head.resel_sa assumed at offset zero of lcb).
100959743Sgroudier	 */
101059743Sgroudier	SCR_COPY (4),
101159743Sgroudier		RADDR_1 (dsa),
101259743Sgroudier		PADDR_A (_sms_a100),
101359743Sgroudier	SCR_COPY (4),
101459743Sgroudier}/*-------------------------< _SMS_A100 >------------------------*/,{
101559743Sgroudier		0,
101659743Sgroudier		RADDR_1 (temp),
101759743Sgroudier	SCR_RETURN,
101859743Sgroudier		0,
101959743Sgroudier	/* In normal situations, we jump to RESEL_TAG or RESEL_NO_TAG */
102059743Sgroudier}/*-------------------------< RESEL_TAG >------------------------*/,{
102159743Sgroudier	/*
102260134Sgroudier	 *  ACK the IDENTIFY previously received.
102359743Sgroudier	 */
102459743Sgroudier	SCR_CLR (SCR_ACK),
102559743Sgroudier		0,
102659743Sgroudier	/*
102759743Sgroudier	 *  It shall be a tagged command.
102859743Sgroudier	 *  Read SIMPLE+TAG.
102959743Sgroudier	 *  The C code will deal with errors.
1030220950Smarius	 *  Aggressive optimization, isn't it? :)
103159743Sgroudier	 */
103259743Sgroudier	SCR_MOVE_ABS (2) ^ SCR_MSG_IN,
103359743Sgroudier		HADDR_1 (msgin),
103459743Sgroudier	/*
103559743Sgroudier	 *  Copy the LCB header to a fixed place in
103659743Sgroudier	 *  the HCB using self-modifying SCRIPTS.
103759743Sgroudier	 */
103859743Sgroudier	SCR_COPY (4),
103959743Sgroudier		RADDR_1 (dsa),
104059743Sgroudier		PADDR_A (_sms_a110),
104159743Sgroudier	SCR_COPY (sizeof(struct sym_lcbh)),
104259743Sgroudier}/*-------------------------< _SMS_A110 >------------------------*/,{
104359743Sgroudier		0,
104459743Sgroudier		HADDR_1 (lcb_head),
104559743Sgroudier	/*
104659743Sgroudier	 *  Load the pointer to the tagged task
104759743Sgroudier	 *  table for this LUN.
104859743Sgroudier	 */
104959743Sgroudier	SCR_COPY (4),
105059743Sgroudier		HADDR_1 (lcb_head.itlq_tbl_sa),
105159743Sgroudier		RADDR_1 (dsa),
105259743Sgroudier	/*
105359743Sgroudier	 *  The SIDL still contains the TAG value.
1054220944Smarius	 *  Aggressive optimization, isn't it? :):)
105559743Sgroudier	 */
105659743Sgroudier	SCR_REG_SFBR (sidl, SCR_SHL, 0),
105759743Sgroudier		0,
105859743Sgroudier#if SYM_CONF_MAX_TASK*4 > 512
105959743Sgroudier	SCR_JUMPR ^ IFFALSE (CARRYSET),
106059743Sgroudier		8,
106159743Sgroudier	SCR_REG_REG (dsa1, SCR_OR, 2),
106259743Sgroudier		0,
106359743Sgroudier	SCR_REG_REG (sfbr, SCR_SHL, 0),
106459743Sgroudier		0,
106559743Sgroudier	SCR_JUMPR ^ IFFALSE (CARRYSET),
106659743Sgroudier		8,
106759743Sgroudier	SCR_REG_REG (dsa1, SCR_OR, 1),
106859743Sgroudier		0,
106959743Sgroudier#elif SYM_CONF_MAX_TASK*4 > 256
107059743Sgroudier	SCR_JUMPR ^ IFFALSE (CARRYSET),
107159743Sgroudier		8,
107259743Sgroudier	SCR_REG_REG (dsa1, SCR_OR, 1),
107359743Sgroudier		0,
107459743Sgroudier#endif
107559743Sgroudier	/*
107659743Sgroudier	 *  Retrieve the DSA of this task.
107759743Sgroudier	 *  JUMP indirectly to the restart point of the CCB.
107859743Sgroudier	 */
107959743Sgroudier	SCR_SFBR_REG (dsa, SCR_AND, 0xfc),
108059743Sgroudier		0,
108159743Sgroudier	SCR_COPY (4),
108259743Sgroudier		RADDR_1 (dsa),
108359743Sgroudier		PADDR_A (_sms_a120),
108459743Sgroudier	SCR_COPY (4),
108559743Sgroudier}/*-------------------------< _SMS_A120 >------------------------*/,{
108659743Sgroudier		0,
108759743Sgroudier		RADDR_1 (dsa),
108859743Sgroudier}/*-------------------------< RESEL_GO >-------------------------*/,{
108959743Sgroudier	SCR_COPY (4),
109059743Sgroudier		RADDR_1 (dsa),
109159743Sgroudier		PADDR_A (_sms_a130),
109259743Sgroudier	/*
109359743Sgroudier	 *  Move 'ccb.phys.head.go' action to
109459743Sgroudier	 *  scratch/scratch1. So scratch1 will
109559743Sgroudier	 *  contain the 'restart' field of the
109659743Sgroudier	 *  'go' structure.
109759743Sgroudier	 */
109859743Sgroudier	SCR_COPY (8),
109959743Sgroudier}/*-------------------------< _SMS_A130 >------------------------*/,{
110059743Sgroudier		0,
110159743Sgroudier		PADDR_B (scratch),
110259743Sgroudier	SCR_COPY (4),
110359743Sgroudier		PADDR_B (scratch1), /* phys.head.go.restart */
110459743Sgroudier		RADDR_1 (temp),
110559743Sgroudier	SCR_RETURN,
110659743Sgroudier		0,
110759743Sgroudier	/* In normal situations we branch to RESEL_DSA */
110859743Sgroudier}/*-------------------------< RESEL_DSA >------------------------*/,{
110959743Sgroudier	/*
111059743Sgroudier	 *  ACK the IDENTIFY or TAG previously received.
111159743Sgroudier	 */
111259743Sgroudier	SCR_CLR (SCR_ACK),
111359743Sgroudier		0,
111459743Sgroudier}/*-------------------------< RESEL_DSA1 >-----------------------*/,{
111559743Sgroudier	/*
111659743Sgroudier	 *  Copy the CCB header to a fixed location
111759743Sgroudier	 *  in the HCB using self-modifying SCRIPTS.
111859743Sgroudier	 */
111959743Sgroudier	SCR_COPY (4),
112059743Sgroudier		RADDR_1 (dsa),
112159743Sgroudier		PADDR_A (_sms_a140),
112259743Sgroudier	SCR_COPY (sizeof(struct sym_ccbh)),
112359743Sgroudier}/*-------------------------< _SMS_A140 >------------------------*/,{
112459743Sgroudier		0,
112559743Sgroudier		HADDR_1 (ccb_head),
112659743Sgroudier	/*
112759743Sgroudier	 *  Load the savep (saved data pointer) into
112859743Sgroudier	 *  the actual data pointer.
112959743Sgroudier	 */
113059743Sgroudier	SCR_COPY (4),
113159743Sgroudier		HADDR_1 (ccb_head.savep),
113259743Sgroudier		RADDR_1 (temp),
113359743Sgroudier	/*
113459743Sgroudier	 *  Initialize the status register
113559743Sgroudier	 */
113659743Sgroudier	SCR_COPY (4),
113759743Sgroudier		HADDR_1 (ccb_head.status),
113859743Sgroudier		RADDR_1 (scr0),
113959743Sgroudier	/*
114059743Sgroudier	 *  Jump to dispatcher.
114159743Sgroudier	 */
114259743Sgroudier	SCR_JUMP,
114359743Sgroudier		PADDR_A (dispatch),
114459743Sgroudier}/*-------------------------< RESEL_NO_TAG >---------------------*/,{
114559743Sgroudier	/*
114659743Sgroudier	 *  Copy the LCB header to a fixed place in
114759743Sgroudier	 *  the HCB using self-modifying SCRIPTS.
114859743Sgroudier	 */
114959743Sgroudier	SCR_COPY (4),
115059743Sgroudier		RADDR_1 (dsa),
115159743Sgroudier		PADDR_A (_sms_a145),
115259743Sgroudier	SCR_COPY (sizeof(struct sym_lcbh)),
115359743Sgroudier}/*-------------------------< _SMS_A145 >------------------------*/,{
115459743Sgroudier		0,
115559743Sgroudier		HADDR_1 (lcb_head),
115659743Sgroudier	/*
115759743Sgroudier	 *  Load the DSA with the unique ITL task.
115859743Sgroudier	 */
115959743Sgroudier	SCR_COPY (4),
116059743Sgroudier		HADDR_1 (lcb_head.itl_task_sa),
116159743Sgroudier		RADDR_1 (dsa),
116259743Sgroudier	SCR_JUMP,
116359743Sgroudier		PADDR_A (resel_go),
116459743Sgroudier}/*-------------------------< DATA_IN >--------------------------*/,{
116559743Sgroudier/*
116659743Sgroudier *  Because the size depends on the
116759743Sgroudier *  #define SYM_CONF_MAX_SG parameter,
116859743Sgroudier *  it is filled in at runtime.
116959743Sgroudier *
117059743Sgroudier *  ##===========< i=0; i<SYM_CONF_MAX_SG >=========
117159743Sgroudier *  ||	SCR_CHMOV_TBL ^ SCR_DATA_IN,
117259743Sgroudier *  ||		offsetof (struct sym_dsb, data[ i]),
117359743Sgroudier *  ##==========================================
117459743Sgroudier */
117559743Sgroudier0
117659743Sgroudier}/*-------------------------< DATA_IN2 >-------------------------*/,{
117759743Sgroudier	SCR_CALL,
117859743Sgroudier		PADDR_A (datai_done),
117959743Sgroudier	SCR_JUMP,
118059743Sgroudier		PADDR_B (data_ovrun),
118159743Sgroudier}/*-------------------------< DATA_OUT >-------------------------*/,{
118259743Sgroudier/*
118359743Sgroudier *  Because the size depends on the
118459743Sgroudier *  #define SYM_CONF_MAX_SG parameter,
118559743Sgroudier *  it is filled in at runtime.
118659743Sgroudier *
118759743Sgroudier *  ##===========< i=0; i<SYM_CONF_MAX_SG >=========
118859743Sgroudier *  ||	SCR_CHMOV_TBL ^ SCR_DATA_OUT,
118959743Sgroudier *  ||		offsetof (struct sym_dsb, data[ i]),
119059743Sgroudier *  ##==========================================
119159743Sgroudier */
119259743Sgroudier0
119359743Sgroudier}/*-------------------------< DATA_OUT2 >------------------------*/,{
119459743Sgroudier	SCR_CALL,
119559743Sgroudier		PADDR_A (datao_done),
119659743Sgroudier	SCR_JUMP,
119759743Sgroudier		PADDR_B (data_ovrun),
119859743Sgroudier}/*-------------------------< PM0_DATA >-------------------------*/,{
119959743Sgroudier	/*
120059743Sgroudier	 *  Read our host flags to SFBR, so we will be able
120159743Sgroudier	 *  to check against the data direction we expect.
120259743Sgroudier	 */
120359743Sgroudier	SCR_FROM_REG (HF_REG),
120459743Sgroudier		0,
120559743Sgroudier	/*
120659743Sgroudier	 *  Check against actual DATA PHASE.
120759743Sgroudier	 */
120859743Sgroudier	SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)),
120959743Sgroudier		PADDR_A (pm0_data_out),
121059743Sgroudier	/*
121159743Sgroudier	 *  Actual phase is DATA IN.
121259743Sgroudier	 *  Check against expected direction.
121359743Sgroudier	 */
121459743Sgroudier	SCR_JUMP ^ IFFALSE (MASK (HF_DATA_IN, HF_DATA_IN)),
121559743Sgroudier		PADDR_B (data_ovrun),
121659743Sgroudier	/*
121759743Sgroudier	 *  Keep track we are moving data from the
121859743Sgroudier	 *  PM0 DATA mini-script.
121959743Sgroudier	 */
122059743Sgroudier	SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM0),
122159743Sgroudier		0,
122259743Sgroudier	/*
122359743Sgroudier	 *  Move the data to memory.
122459743Sgroudier	 */
122559743Sgroudier	SCR_CHMOV_TBL ^ SCR_DATA_IN,
122659743Sgroudier		offsetof (struct sym_ccb, phys.pm0.sg),
122759743Sgroudier	SCR_JUMP,
122859743Sgroudier		PADDR_A (pm0_data_end),
122959743Sgroudier}/*-------------------------< PM0_DATA_OUT >---------------------*/,{
123059743Sgroudier	/*
123159743Sgroudier	 *  Actual phase is DATA OUT.
123259743Sgroudier	 *  Check against expected direction.
123359743Sgroudier	 */
123459743Sgroudier	SCR_JUMP ^ IFTRUE (MASK (HF_DATA_IN, HF_DATA_IN)),
123559743Sgroudier		PADDR_B (data_ovrun),
123659743Sgroudier	/*
123759743Sgroudier	 *  Keep track we are moving data from the
123859743Sgroudier	 *  PM0 DATA mini-script.
123959743Sgroudier	 */
124059743Sgroudier	SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM0),
124159743Sgroudier		0,
124259743Sgroudier	/*
124359743Sgroudier	 *  Move the data from memory.
124459743Sgroudier	 */
124559743Sgroudier	SCR_CHMOV_TBL ^ SCR_DATA_OUT,
124659743Sgroudier		offsetof (struct sym_ccb, phys.pm0.sg),
124759743Sgroudier}/*-------------------------< PM0_DATA_END >---------------------*/,{
124859743Sgroudier	/*
124959743Sgroudier	 *  Clear the flag that told we were moving
125059743Sgroudier	 *  data from the PM0 DATA mini-script.
125159743Sgroudier	 */
125259743Sgroudier	SCR_REG_REG (HF_REG, SCR_AND, (~HF_IN_PM0)),
125359743Sgroudier		0,
125459743Sgroudier	/*
125559743Sgroudier	 *  Return to the previous DATA script which
125659743Sgroudier	 *  is guaranteed by design (if no bug) to be
125759743Sgroudier	 *  the main DATA script for this transfer.
125859743Sgroudier	 */
125959743Sgroudier	SCR_COPY (4),
126059743Sgroudier		RADDR_1 (dsa),
126159743Sgroudier		RADDR_1 (scratcha),
126259743Sgroudier	SCR_REG_REG (scratcha, SCR_ADD, offsetof (struct sym_ccb,phys.pm0.ret)),
126359743Sgroudier		0,
126459743Sgroudier}/*-------------------------< PM_DATA_END >----------------------*/,{
126559743Sgroudier	SCR_COPY (4),
126659743Sgroudier		RADDR_1 (scratcha),
126759743Sgroudier		PADDR_A (_sms_a150),
126859743Sgroudier	SCR_COPY (4),
126959743Sgroudier}/*-------------------------< _SMS_A150 >------------------------*/,{
127059743Sgroudier		0,
127159743Sgroudier		RADDR_1 (temp),
127259743Sgroudier	SCR_RETURN,
127359743Sgroudier		0,
127459743Sgroudier}/*-------------------------< PM1_DATA >-------------------------*/,{
127559743Sgroudier	/*
127659743Sgroudier	 *  Read our host flags to SFBR, so we will be able
127759743Sgroudier	 *  to check against the data direction we expect.
127859743Sgroudier	 */
127959743Sgroudier	SCR_FROM_REG (HF_REG),
128059743Sgroudier		0,
128159743Sgroudier	/*
128259743Sgroudier	 *  Check against actual DATA PHASE.
128359743Sgroudier	 */
128459743Sgroudier	SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)),
128559743Sgroudier		PADDR_A (pm1_data_out),
128659743Sgroudier	/*
128759743Sgroudier	 *  Actual phase is DATA IN.
128859743Sgroudier	 *  Check against expected direction.
128959743Sgroudier	 */
129059743Sgroudier	SCR_JUMP ^ IFFALSE (MASK (HF_DATA_IN, HF_DATA_IN)),
129159743Sgroudier		PADDR_B (data_ovrun),
129259743Sgroudier	/*
129359743Sgroudier	 *  Keep track we are moving data from the
129459743Sgroudier	 *  PM1 DATA mini-script.
129559743Sgroudier	 */
129659743Sgroudier	SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM1),
129759743Sgroudier		0,
129859743Sgroudier	/*
129959743Sgroudier	 *  Move the data to memory.
130059743Sgroudier	 */
130159743Sgroudier	SCR_CHMOV_TBL ^ SCR_DATA_IN,
130259743Sgroudier		offsetof (struct sym_ccb, phys.pm1.sg),
130359743Sgroudier	SCR_JUMP,
130459743Sgroudier		PADDR_A (pm1_data_end),
130559743Sgroudier}/*-------------------------< PM1_DATA_OUT >---------------------*/,{
130659743Sgroudier	/*
130759743Sgroudier	 *  Actual phase is DATA OUT.
130859743Sgroudier	 *  Check against expected direction.
130959743Sgroudier	 */
131059743Sgroudier	SCR_JUMP ^ IFTRUE (MASK (HF_DATA_IN, HF_DATA_IN)),
131159743Sgroudier		PADDR_B (data_ovrun),
131259743Sgroudier	/*
131359743Sgroudier	 *  Keep track we are moving data from the
131459743Sgroudier	 *  PM1 DATA mini-script.
131559743Sgroudier	 */
131659743Sgroudier	SCR_REG_REG (HF_REG, SCR_OR, HF_IN_PM1),
131759743Sgroudier		0,
131859743Sgroudier	/*
131959743Sgroudier	 *  Move the data from memory.
132059743Sgroudier	 */
132159743Sgroudier	SCR_CHMOV_TBL ^ SCR_DATA_OUT,
132259743Sgroudier		offsetof (struct sym_ccb, phys.pm1.sg),
132359743Sgroudier}/*-------------------------< PM1_DATA_END >---------------------*/,{
132459743Sgroudier	/*
132559743Sgroudier	 *  Clear the flag that told we were moving
132659743Sgroudier	 *  data from the PM1 DATA mini-script.
132759743Sgroudier	 */
132859743Sgroudier	SCR_REG_REG (HF_REG, SCR_AND, (~HF_IN_PM1)),
132959743Sgroudier		0,
133059743Sgroudier	/*
133159743Sgroudier	 *  Return to the previous DATA script which
133259743Sgroudier	 *  is guaranteed by design (if no bug) to be
133359743Sgroudier	 *  the main DATA script for this transfer.
133459743Sgroudier	 */
133559743Sgroudier	SCR_COPY (4),
133659743Sgroudier		RADDR_1 (dsa),
133759743Sgroudier		RADDR_1 (scratcha),
133859743Sgroudier	SCR_REG_REG (scratcha, SCR_ADD, offsetof (struct sym_ccb,phys.pm1.ret)),
133959743Sgroudier		0,
134059743Sgroudier	SCR_JUMP,
134159743Sgroudier		PADDR_A (pm_data_end),
134259743Sgroudier}/*--------------------------<>----------------------------------*/
134359743Sgroudier};
134459743Sgroudier
1345179029Smariusstatic const struct SYM_FWB_SCR SYM_FWB_SCR = {
134659743Sgroudier/*-------------------------< NO_DATA >--------------------------*/ {
134759743Sgroudier	SCR_JUMP,
134859743Sgroudier		PADDR_B (data_ovrun),
134959743Sgroudier}/*-------------------------< SEL_FOR_ABORT >--------------------*/,{
135059743Sgroudier	/*
135159743Sgroudier	 *  We are jumped here by the C code, if we have
135259743Sgroudier	 *  some target to reset or some disconnected
135359743Sgroudier	 *  job to abort. Since error recovery is a serious
135459743Sgroudier	 *  busyness, we will really reset the SCSI BUS, if
1355220944Smarius	 *  case of a SCSI interrupt occurring in this path.
135659743Sgroudier	 */
135759743Sgroudier
135859743Sgroudier	/*
135959743Sgroudier	 *  Set initiator mode.
136059743Sgroudier	 */
136159743Sgroudier	SCR_CLR (SCR_TRG),
136259743Sgroudier		0,
136359743Sgroudier	/*
136459743Sgroudier	 *      And try to select this target.
136559743Sgroudier	 */
136659743Sgroudier	SCR_SEL_TBL_ATN ^ offsetof (struct sym_hcb, abrt_sel),
136759743Sgroudier		PADDR_A (reselect),
136859743Sgroudier	/*
136959743Sgroudier	 *  Wait for the selection to complete or
137059743Sgroudier	 *  the selection to time out.
137159743Sgroudier	 */
137259743Sgroudier	SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_OUT)),
137359743Sgroudier		-8,
137459743Sgroudier	/*
137559743Sgroudier	 *  Call the C code.
137659743Sgroudier	 */
137759743Sgroudier	SCR_INT,
137859743Sgroudier		SIR_TARGET_SELECTED,
137959743Sgroudier	/*
138059743Sgroudier	 *  The C code should let us continue here.
138159743Sgroudier	 *  Send the 'kiss of death' message.
138259743Sgroudier	 *  We expect an immediate disconnect once
138359743Sgroudier	 *  the target has eaten the message.
138459743Sgroudier	 */
138559743Sgroudier	SCR_REG_REG (scntl2, SCR_AND, 0x7f),
138659743Sgroudier		0,
138759743Sgroudier	SCR_MOVE_TBL ^ SCR_MSG_OUT,
138859743Sgroudier		offsetof (struct sym_hcb, abrt_tbl),
138959743Sgroudier	SCR_CLR (SCR_ACK|SCR_ATN),
139059743Sgroudier		0,
139159743Sgroudier	SCR_WAIT_DISC,
139259743Sgroudier		0,
139359743Sgroudier	/*
139459743Sgroudier	 *  Tell the C code that we are done.
139559743Sgroudier	 */
139659743Sgroudier	SCR_INT,
139759743Sgroudier		SIR_ABORT_SENT,
139859743Sgroudier}/*-------------------------< SEL_FOR_ABORT_1 >------------------*/,{
139959743Sgroudier	/*
140059743Sgroudier	 *  Jump at scheduler.
140159743Sgroudier	 */
140259743Sgroudier	SCR_JUMP,
140359743Sgroudier		PADDR_A (start),
140459743Sgroudier}/*-------------------------< MSG_IN_ETC >-----------------------*/,{
140559743Sgroudier	/*
140659743Sgroudier	 *  If it is an EXTENDED (variable size message)
140759743Sgroudier	 *  Handle it.
140859743Sgroudier	 */
140959743Sgroudier	SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED)),
141059743Sgroudier		PADDR_B (msg_extended),
141159743Sgroudier	/*
141259743Sgroudier	 *  Let the C code handle any other
141359743Sgroudier	 *  1 byte message.
141459743Sgroudier	 */
141559743Sgroudier	SCR_JUMP ^ IFTRUE (MASK (0x00, 0xf0)),
141659743Sgroudier		PADDR_B (msg_received),
141759743Sgroudier	SCR_JUMP ^ IFTRUE (MASK (0x10, 0xf0)),
141859743Sgroudier		PADDR_B (msg_received),
141959743Sgroudier	/*
142059743Sgroudier	 *  We donnot handle 2 bytes messages from SCRIPTS.
142159743Sgroudier	 *  So, let the C code deal with these ones too.
142259743Sgroudier	 */
142362134Sgroudier	SCR_JUMP ^ IFFALSE (MASK (0x20, 0xf0)),
142462134Sgroudier		PADDR_B (msg_weird_seen),
142559743Sgroudier	SCR_CLR (SCR_ACK),
142659743Sgroudier		0,
142759743Sgroudier	SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
142859743Sgroudier		HADDR_1 (msgin[1]),
142959743Sgroudier}/*-------------------------< MSG_RECEIVED >---------------------*/,{
143059743Sgroudier	SCR_COPY (4),			/* DUMMY READ */
143159743Sgroudier		HADDR_1 (cache),
143259743Sgroudier		RADDR_1 (scratcha),
143359743Sgroudier	SCR_INT,
143459743Sgroudier		SIR_MSG_RECEIVED,
143559743Sgroudier}/*-------------------------< MSG_WEIRD_SEEN >-------------------*/,{
143659743Sgroudier	SCR_COPY (4),			/* DUMMY READ */
143759743Sgroudier		HADDR_1 (cache),
143859743Sgroudier		RADDR_1 (scratcha),
143959743Sgroudier	SCR_INT,
144059743Sgroudier		SIR_MSG_WEIRD,
144159743Sgroudier}/*-------------------------< MSG_EXTENDED >---------------------*/,{
144259743Sgroudier	/*
144359743Sgroudier	 *  Clear ACK and get the next byte
144459743Sgroudier	 *  assumed to be the message length.
144559743Sgroudier	 */
144659743Sgroudier	SCR_CLR (SCR_ACK),
144759743Sgroudier		0,
144859743Sgroudier	SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
144959743Sgroudier		HADDR_1 (msgin[1]),
145059743Sgroudier	/*
145159743Sgroudier	 *  Try to catch some unlikely situations as 0 length
145259743Sgroudier	 *  or too large the length.
145359743Sgroudier	 */
145459743Sgroudier	SCR_JUMP ^ IFTRUE (DATA (0)),
145559743Sgroudier		PADDR_B (msg_weird_seen),
145659743Sgroudier	SCR_TO_REG (scratcha),
145759743Sgroudier		0,
145859743Sgroudier	SCR_REG_REG (sfbr, SCR_ADD, (256-8)),
145959743Sgroudier		0,
146059743Sgroudier	SCR_JUMP ^ IFTRUE (CARRYSET),
146159743Sgroudier		PADDR_B (msg_weird_seen),
146259743Sgroudier	/*
146359743Sgroudier	 *  We donnot handle extended messages from SCRIPTS.
1464220944Smarius	 *  Read the amount of data corresponding to the
146559743Sgroudier	 *  message length and call the C code.
146659743Sgroudier	 */
146759743Sgroudier	SCR_COPY (1),
146859743Sgroudier		RADDR_1 (scratcha),
146959743Sgroudier		PADDR_B (_sms_b10),
147059743Sgroudier	SCR_CLR (SCR_ACK),
147159743Sgroudier		0,
147259743Sgroudier}/*-------------------------< _SMS_B10 >-------------------------*/,{
147359743Sgroudier	SCR_MOVE_ABS (0) ^ SCR_MSG_IN,
147459743Sgroudier		HADDR_1 (msgin[2]),
147559743Sgroudier	SCR_JUMP,
147659743Sgroudier		PADDR_B (msg_received),
147759743Sgroudier}/*-------------------------< MSG_BAD >--------------------------*/,{
147859743Sgroudier	/*
147959743Sgroudier	 *  unimplemented message - reject it.
148059743Sgroudier	 */
148159743Sgroudier	SCR_INT,
148259743Sgroudier		SIR_REJECT_TO_SEND,
148359743Sgroudier	SCR_SET (SCR_ATN),
148459743Sgroudier		0,
148559743Sgroudier	SCR_JUMP,
148659743Sgroudier		PADDR_A (clrack),
148759743Sgroudier}/*-------------------------< MSG_WEIRD >------------------------*/,{
148859743Sgroudier	/*
148959743Sgroudier	 *  weird message received
149059743Sgroudier	 *  ignore all MSG IN phases and reject it.
149159743Sgroudier	 */
149259743Sgroudier	SCR_INT,
149359743Sgroudier		SIR_REJECT_TO_SEND,
149459743Sgroudier	SCR_SET (SCR_ATN),
149559743Sgroudier		0,
149659743Sgroudier}/*-------------------------< MSG_WEIRD1 >-----------------------*/,{
149759743Sgroudier	SCR_CLR (SCR_ACK),
149859743Sgroudier		0,
149959743Sgroudier	SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)),
150059743Sgroudier		PADDR_A (dispatch),
150159743Sgroudier	SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
150259743Sgroudier		HADDR_1 (scratch),
150359743Sgroudier	SCR_JUMP,
150459743Sgroudier		PADDR_B (msg_weird1),
150559743Sgroudier}/*-------------------------< WDTR_RESP >------------------------*/,{
150659743Sgroudier	/*
150759743Sgroudier	 *  let the target fetch our answer.
150859743Sgroudier	 */
150959743Sgroudier	SCR_SET (SCR_ATN),
151059743Sgroudier		0,
151159743Sgroudier	SCR_CLR (SCR_ACK),
151259743Sgroudier		0,
151359743Sgroudier	SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)),
151459743Sgroudier		PADDR_B (nego_bad_phase),
151559743Sgroudier}/*-------------------------< SEND_WDTR >------------------------*/,{
151659743Sgroudier	/*
151759743Sgroudier	 *  Send the M_X_WIDE_REQ
151859743Sgroudier	 */
151959743Sgroudier	SCR_MOVE_ABS (4) ^ SCR_MSG_OUT,
152059743Sgroudier		HADDR_1 (msgout),
152159743Sgroudier	SCR_JUMP,
152259743Sgroudier		PADDR_B (msg_out_done),
152359743Sgroudier}/*-------------------------< SDTR_RESP >------------------------*/,{
152459743Sgroudier	/*
152559743Sgroudier	 *  let the target fetch our answer.
152659743Sgroudier	 */
152759743Sgroudier	SCR_SET (SCR_ATN),
152859743Sgroudier		0,
152959743Sgroudier	SCR_CLR (SCR_ACK),
153059743Sgroudier		0,
153159743Sgroudier	SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)),
153259743Sgroudier		PADDR_B (nego_bad_phase),
153359743Sgroudier}/*-------------------------< SEND_SDTR >------------------------*/,{
153459743Sgroudier	/*
153559743Sgroudier	 *  Send the M_X_SYNC_REQ
153659743Sgroudier	 */
153759743Sgroudier	SCR_MOVE_ABS (5) ^ SCR_MSG_OUT,
153859743Sgroudier		HADDR_1 (msgout),
153959743Sgroudier	SCR_JUMP,
154059743Sgroudier		PADDR_B (msg_out_done),
154159743Sgroudier}/*-------------------------< PPR_RESP >-------------------------*/,{
154259743Sgroudier	/*
154359743Sgroudier	 *  let the target fetch our answer.
154459743Sgroudier	 */
154559743Sgroudier	SCR_SET (SCR_ATN),
154659743Sgroudier		0,
154759743Sgroudier	SCR_CLR (SCR_ACK),
154859743Sgroudier		0,
154959743Sgroudier	SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)),
155059743Sgroudier		PADDR_B (nego_bad_phase),
155159743Sgroudier}/*-------------------------< SEND_PPR >-------------------------*/,{
155259743Sgroudier	/*
155359743Sgroudier	 *  Send the M_X_PPR_REQ
155459743Sgroudier	 */
155559743Sgroudier	SCR_MOVE_ABS (8) ^ SCR_MSG_OUT,
155659743Sgroudier		HADDR_1 (msgout),
155759743Sgroudier	SCR_JUMP,
155859743Sgroudier		PADDR_B (msg_out_done),
155959743Sgroudier}/*-------------------------< NEGO_BAD_PHASE >-------------------*/,{
156059743Sgroudier	SCR_INT,
156159743Sgroudier		SIR_NEGO_PROTO,
156259743Sgroudier	SCR_JUMP,
156359743Sgroudier		PADDR_A (dispatch),
156459743Sgroudier}/*-------------------------< MSG_OUT >--------------------------*/,{
156559743Sgroudier	/*
156659743Sgroudier	 *  The target requests a message.
156759743Sgroudier	 *  We donnot send messages that may
156859743Sgroudier	 *  require the device to go to bus free.
156959743Sgroudier	 */
157059743Sgroudier	SCR_MOVE_ABS (1) ^ SCR_MSG_OUT,
157159743Sgroudier		HADDR_1 (msgout),
157259743Sgroudier	/*
157359743Sgroudier	 *  ... wait for the next phase
157459743Sgroudier	 *  if it's a message out, send it again, ...
157559743Sgroudier	 */
157659743Sgroudier	SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_OUT)),
157759743Sgroudier		PADDR_B (msg_out),
157859743Sgroudier}/*-------------------------< MSG_OUT_DONE >---------------------*/,{
157959743Sgroudier	/*
158059743Sgroudier	 *  Let the C code be aware of the
158159743Sgroudier	 *  sent message and clear the message.
158259743Sgroudier	 */
158359743Sgroudier	SCR_INT,
158459743Sgroudier		SIR_MSG_OUT_DONE,
158559743Sgroudier	/*
158659743Sgroudier	 *  ... and process the next phase
158759743Sgroudier	 */
158859743Sgroudier	SCR_JUMP,
158959743Sgroudier		PADDR_A (dispatch),
159059743Sgroudier}/*-------------------------< DATA_OVRUN >-----------------------*/,{
159159743Sgroudier	/*
159259743Sgroudier	 *  Zero scratcha that will count the
159359743Sgroudier	 *  extras bytes.
159459743Sgroudier	 */
159559743Sgroudier	SCR_COPY (4),
159659743Sgroudier		PADDR_B (zero),
159759743Sgroudier		RADDR_1 (scratcha),
159859743Sgroudier}/*-------------------------< DATA_OVRUN1 >----------------------*/,{
159959743Sgroudier	/*
160059743Sgroudier	 *  The target may want to transfer too much data.
160159743Sgroudier	 *
160259743Sgroudier	 *  If phase is DATA OUT write 1 byte and count it.
160359743Sgroudier	 */
160459743Sgroudier	SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_OUT)),
160559743Sgroudier		16,
160659743Sgroudier	SCR_CHMOV_ABS (1) ^ SCR_DATA_OUT,
160759743Sgroudier		HADDR_1 (scratch),
160859743Sgroudier	SCR_JUMP,
160959743Sgroudier		PADDR_B (data_ovrun2),
161059743Sgroudier	/*
161159743Sgroudier	 *  If WSR is set, clear this condition, and
161259743Sgroudier	 *  count this byte.
161359743Sgroudier	 */
161459743Sgroudier	SCR_FROM_REG (scntl2),
161559743Sgroudier		0,
161659743Sgroudier	SCR_JUMPR ^ IFFALSE (MASK (WSR, WSR)),
161759743Sgroudier		16,
161859743Sgroudier	SCR_REG_REG (scntl2, SCR_OR, WSR),
161959743Sgroudier		0,
162059743Sgroudier	SCR_JUMP,
162159743Sgroudier		PADDR_B (data_ovrun2),
162259743Sgroudier	/*
162359743Sgroudier	 *  Finally check against DATA IN phase.
162459743Sgroudier	 *  Signal data overrun to the C code
162559743Sgroudier	 *  and jump to dispatcher if not so.
162659743Sgroudier	 *  Read 1 byte otherwise and count it.
162759743Sgroudier	 */
162859743Sgroudier	SCR_JUMPR ^ IFTRUE (WHEN (SCR_DATA_IN)),
162959743Sgroudier		16,
163059743Sgroudier	SCR_INT,
163159743Sgroudier		SIR_DATA_OVERRUN,
163259743Sgroudier	SCR_JUMP,
163359743Sgroudier		PADDR_A (dispatch),
163459743Sgroudier	SCR_CHMOV_ABS (1) ^ SCR_DATA_IN,
163559743Sgroudier		HADDR_1 (scratch),
163659743Sgroudier}/*-------------------------< DATA_OVRUN2 >----------------------*/,{
163759743Sgroudier	/*
163859743Sgroudier	 *  Count this byte.
163959743Sgroudier	 *  This will allow to return a negative
164059743Sgroudier	 *  residual to user.
164159743Sgroudier	 */
164259743Sgroudier	SCR_REG_REG (scratcha,  SCR_ADD,  0x01),
164359743Sgroudier		0,
164459743Sgroudier	SCR_REG_REG (scratcha1, SCR_ADDC, 0),
164559743Sgroudier		0,
164659743Sgroudier	SCR_REG_REG (scratcha2, SCR_ADDC, 0),
164759743Sgroudier		0,
164859743Sgroudier	/*
164959743Sgroudier	 *  .. and repeat as required.
165059743Sgroudier	 */
165159743Sgroudier	SCR_JUMP,
165259743Sgroudier		PADDR_B (data_ovrun1),
165359743Sgroudier}/*-------------------------< ABORT_RESEL >----------------------*/,{
165459743Sgroudier	SCR_SET (SCR_ATN),
165559743Sgroudier		0,
165659743Sgroudier	SCR_CLR (SCR_ACK),
165759743Sgroudier		0,
165859743Sgroudier	/*
165959743Sgroudier	 *  send the abort/abortag/reset message
166059743Sgroudier	 *  we expect an immediate disconnect
166159743Sgroudier	 */
166259743Sgroudier	SCR_REG_REG (scntl2, SCR_AND, 0x7f),
166359743Sgroudier		0,
166459743Sgroudier	SCR_MOVE_ABS (1) ^ SCR_MSG_OUT,
166559743Sgroudier		HADDR_1 (msgout),
166659743Sgroudier	SCR_CLR (SCR_ACK|SCR_ATN),
166759743Sgroudier		0,
166859743Sgroudier	SCR_WAIT_DISC,
166959743Sgroudier		0,
167059743Sgroudier	SCR_INT,
167159743Sgroudier		SIR_RESEL_ABORTED,
167259743Sgroudier	SCR_JUMP,
167359743Sgroudier		PADDR_A (start),
167459743Sgroudier}/*-------------------------< RESEND_IDENT >---------------------*/,{
167559743Sgroudier	/*
167659743Sgroudier	 *  The target stays in MSG OUT phase after having acked
167759743Sgroudier	 *  Identify [+ Tag [+ Extended message ]]. Targets shall
167859743Sgroudier	 *  behave this way on parity error.
167959743Sgroudier	 *  We must send it again all the messages.
168059743Sgroudier	 */
168159743Sgroudier	SCR_SET (SCR_ATN), /* Shall be asserted 2 deskew delays before the  */
168259743Sgroudier		0,         /* 1rst ACK = 90 ns. Hope the chip isn't too fast */
168359743Sgroudier	SCR_JUMP,
168459743Sgroudier		PADDR_A (send_ident),
168559743Sgroudier}/*-------------------------< IDENT_BREAK >----------------------*/,{
168659743Sgroudier	SCR_CLR (SCR_ATN),
168759743Sgroudier		0,
168859743Sgroudier	SCR_JUMP,
168959743Sgroudier		PADDR_A (select2),
169059743Sgroudier}/*-------------------------< IDENT_BREAK_ATN >------------------*/,{
169159743Sgroudier	SCR_SET (SCR_ATN),
169259743Sgroudier		0,
169359743Sgroudier	SCR_JUMP,
169459743Sgroudier		PADDR_A (select2),
169559743Sgroudier}/*-------------------------< SDATA_IN >-------------------------*/,{
169659743Sgroudier	SCR_CHMOV_TBL ^ SCR_DATA_IN,
169759743Sgroudier		offsetof (struct sym_dsb, sense),
169859743Sgroudier	SCR_CALL,
169959743Sgroudier		PADDR_A (datai_done),
170059743Sgroudier	SCR_JUMP,
170159743Sgroudier		PADDR_B (data_ovrun),
170259743Sgroudier}/*-------------------------< RESEL_BAD_LUN >--------------------*/,{
170359743Sgroudier	/*
170459743Sgroudier	 *  Message is an IDENTIFY, but lun is unknown.
170559743Sgroudier	 *  Signal problem to C code for logging the event.
170659743Sgroudier	 *  Send a M_ABORT to clear all pending tasks.
170759743Sgroudier	 */
170859743Sgroudier	SCR_INT,
170959743Sgroudier		SIR_RESEL_BAD_LUN,
171059743Sgroudier	SCR_JUMP,
171159743Sgroudier		PADDR_B (abort_resel),
171259743Sgroudier}/*-------------------------< BAD_I_T_L >------------------------*/,{
171359743Sgroudier	/*
171459743Sgroudier	 *  We donnot have a task for that I_T_L.
171559743Sgroudier	 *  Signal problem to C code for logging the event.
171659743Sgroudier	 *  Send a M_ABORT message.
171759743Sgroudier	 */
171859743Sgroudier	SCR_INT,
171959743Sgroudier		SIR_RESEL_BAD_I_T_L,
172059743Sgroudier	SCR_JUMP,
172159743Sgroudier		PADDR_B (abort_resel),
172259743Sgroudier}/*-------------------------< BAD_I_T_L_Q >----------------------*/,{
172359743Sgroudier	/*
172459743Sgroudier	 *  We donnot have a task that matches the tag.
172559743Sgroudier	 *  Signal problem to C code for logging the event.
172659743Sgroudier	 *  Send a M_ABORTTAG message.
172759743Sgroudier	 */
172859743Sgroudier	SCR_INT,
172959743Sgroudier		SIR_RESEL_BAD_I_T_L_Q,
173059743Sgroudier	SCR_JUMP,
173159743Sgroudier		PADDR_B (abort_resel),
173259743Sgroudier}/*-------------------------< BAD_STATUS >-----------------------*/,{
173359743Sgroudier	/*
173459743Sgroudier	 *  Anything different from INTERMEDIATE
173559743Sgroudier	 *  CONDITION MET should be a bad SCSI status,
173659743Sgroudier	 *  given that GOOD status has already been tested.
173759743Sgroudier	 *  Call the C code.
173859743Sgroudier	 */
173959743Sgroudier	SCR_COPY (4),
174059743Sgroudier		PADDR_B (startpos),
174159743Sgroudier		RADDR_1 (scratcha),
174259743Sgroudier	SCR_INT ^ IFFALSE (DATA (S_COND_MET)),
174359743Sgroudier		SIR_BAD_SCSI_STATUS,
174459743Sgroudier	SCR_RETURN,
174559743Sgroudier		0,
174659743Sgroudier}/*-------------------------< WSR_MA_HELPER >--------------------*/,{
174759743Sgroudier	/*
174859743Sgroudier	 *  Helper for the C code when WSR bit is set.
174959743Sgroudier	 *  Perform the move of the residual byte.
175059743Sgroudier	 */
175159743Sgroudier	SCR_CHMOV_TBL ^ SCR_DATA_IN,
175259743Sgroudier		offsetof (struct sym_ccb, phys.wresid),
175359743Sgroudier	SCR_JUMP,
175459743Sgroudier		PADDR_A (dispatch),
175559743Sgroudier}/*-------------------------< ZERO >-----------------------------*/,{
175659743Sgroudier	SCR_DATA_ZERO,
175759743Sgroudier}/*-------------------------< SCRATCH >--------------------------*/,{
175859743Sgroudier	SCR_DATA_ZERO, /* MUST BE BEFORE SCRATCH1 */
175959743Sgroudier}/*-------------------------< SCRATCH1 >-------------------------*/,{
176059743Sgroudier	SCR_DATA_ZERO,
176159743Sgroudier}/*-------------------------< PREV_DONE >------------------------*/,{
176259743Sgroudier	SCR_DATA_ZERO, /* MUST BE BEFORE DONE_POS ! */
176359743Sgroudier}/*-------------------------< DONE_POS >-------------------------*/,{
176459743Sgroudier	SCR_DATA_ZERO,
176559743Sgroudier}/*-------------------------< NEXTJOB >--------------------------*/,{
176659743Sgroudier	SCR_DATA_ZERO, /* MUST BE BEFORE STARTPOS ! */
176759743Sgroudier}/*-------------------------< STARTPOS >-------------------------*/,{
176859743Sgroudier	SCR_DATA_ZERO,
176959743Sgroudier}/*-------------------------< TARGTBL >--------------------------*/,{
177059743Sgroudier	SCR_DATA_ZERO,
177159743Sgroudier
177259743Sgroudier}/*-------------------------< SNOOPTEST >------------------------*/,{
177359743Sgroudier	/*
177459743Sgroudier	 *  Read the variable.
177559743Sgroudier	 */
177659743Sgroudier	SCR_COPY (4),
177759743Sgroudier		HADDR_1 (cache),
177859743Sgroudier		RADDR_1 (scratcha),
177959743Sgroudier	/*
178059743Sgroudier	 *  Write the variable.
178159743Sgroudier	 */
178259743Sgroudier	SCR_COPY (4),
178359743Sgroudier		RADDR_1 (temp),
178459743Sgroudier		HADDR_1 (cache),
178559743Sgroudier	/*
178659743Sgroudier	 *  Read back the variable.
178759743Sgroudier	 */
178859743Sgroudier	SCR_COPY (4),
178959743Sgroudier		HADDR_1 (cache),
179059743Sgroudier		RADDR_1 (temp),
179159743Sgroudier}/*-------------------------< SNOOPEND >-------------------------*/,{
179259743Sgroudier	/*
179359743Sgroudier	 *  And stop.
179459743Sgroudier	 */
179559743Sgroudier	SCR_INT,
179659743Sgroudier		99,
179759743Sgroudier}/*--------------------------<>----------------------------------*/
179859743Sgroudier};
1799