1139749Simp/*-
226997Sgibbs * Adaptec 274x/284x/294x device driver firmware for Linux and FreeBSD.
313177Sgibbs *
495378Sgibbs * Copyright (c) 1994-2001 Justin T. Gibbs.
595378Sgibbs * Copyright (c) 2000-2001 Adaptec Inc.
626997Sgibbs * All rights reserved.
713177Sgibbs *
826997Sgibbs * Redistribution and use in source and binary forms, with or without
926997Sgibbs * modification, are permitted provided that the following conditions
1026997Sgibbs * are met:
1126997Sgibbs * 1. Redistributions of source code must retain the above copyright
1226997Sgibbs *    notice, this list of conditions, and the following disclaimer,
1354211Sgibbs *    without modification.
1495378Sgibbs * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1595378Sgibbs *    substantially similar to the "NO WARRANTY" disclaimer below
1695378Sgibbs *    ("Disclaimer") and any redistribution must be conditioned upon
1795378Sgibbs *    including a substantially similar Disclaimer requirement for further
1895378Sgibbs *    binary redistribution.
1995378Sgibbs * 3. Neither the names of the above-listed copyright holders nor the names
2095378Sgibbs *    of any contributors may be used to endorse or promote products derived
2195378Sgibbs *    from this software without specific prior written permission.
2213177Sgibbs *
2354211Sgibbs * Alternatively, this software may be distributed under the terms of the
2495378Sgibbs * GNU General Public License ("GPL") version 2 as published by the Free
2595378Sgibbs * Software Foundation.
2613177Sgibbs *
2795378Sgibbs * NO WARRANTY
2895378Sgibbs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2995378Sgibbs * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3095378Sgibbs * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3195378Sgibbs * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3295378Sgibbs * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3326997Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3426997Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3595378Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3695378Sgibbs * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
3795378Sgibbs * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3895378Sgibbs * POSSIBILITY OF SUCH DAMAGES.
3913177Sgibbs *
4050477Speter * $FreeBSD: releng/10.2/sys/dev/aic7xxx/aic7xxx.seq 165628 2006-12-29 13:08:46Z yar $
4126997Sgibbs */
424568Sgibbs
43123579SgibbsVERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $"
4495378SgibbsPATCH_ARG_LIST = "struct ahc_softc *ahc"
45102673SgibbsPREFIX = "ahc_"
4679874Sgibbs
4766268Sgibbs#include "aic7xxx.reg"
4866268Sgibbs#include "scsi_message.h"
495647Sgibbs
5013177Sgibbs/*
5119164Sgibbs * A few words on the waiting SCB list:
5219164Sgibbs * After starting the selection hardware, we check for reconnecting targets
5313690Sgibbs * as well as for our selection to complete just in case the reselection wins
5413690Sgibbs * bus arbitration.  The problem with this is that we must keep track of the
5513690Sgibbs * SCB that we've already pulled from the QINFIFO and started the selection
5613690Sgibbs * on just in case the reselection wins so that we can retry the selection at
5713690Sgibbs * a later time.  This problem cannot be resolved by holding a single entry
5813690Sgibbs * in scratch ram since a reconnecting target can request sense and this will
5913690Sgibbs * create yet another SCB waiting for selection.  The solution used here is to 
6013690Sgibbs * use byte 27 of the SCB as a psuedo-next pointer and to thread a list
6119164Sgibbs * of SCBs that are awaiting selection.  Since 0-0xfe are valid SCB indexes, 
6219164Sgibbs * SCB_LIST_NULL is 0xff which is out of range.  An entry is also added to
6319164Sgibbs * this list everytime a request sense occurs or after completing a non-tagged
6419164Sgibbs * command for which a second SCB has been queued.  The sequencer will
6519164Sgibbs * automatically consume the entries.
6613177Sgibbs */
674568Sgibbs
6871390Sgibbsbus_free_sel:
6971390Sgibbs	/*
7071390Sgibbs	 * Turn off the selection hardware.  We need to reset the
7171390Sgibbs	 * selection request in order to perform a new selection.
7271390Sgibbs	 */
73109590Sgibbs	and	SCSISEQ, TEMODE|ENSELI|ENRSELI|ENAUTOATNP;
7471390Sgibbs	and	SIMODE1, ~ENBUSFREE;
7544507Sgibbspoll_for_work:
7623925Sgibbs	call	clear_target_state;
7739220Sgibbs	and	SXFRCTL0, ~SPIOEN;
7868623Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0) {
7968623Sgibbs		clr	SCSIBUSL;
8068623Sgibbs	}
8172811Sgibbs	test	SCSISEQ, ENSELO	jnz poll_for_selection;
8272811Sgibbs	if ((ahc->features & AHC_TWIN) != 0) {
8372811Sgibbs		xor	SBLKCTL,SELBUSB;	/* Toggle to the other bus */
8472811Sgibbs		test	SCSISEQ, ENSELO		jnz poll_for_selection;
8572811Sgibbs	}
86133670SgibbsBEGIN_CRITICAL;
8772811Sgibbs	cmp	WAITING_SCBH,SCB_LIST_NULL jne start_waiting;
88133670SgibbsEND_CRITICAL;
8939220Sgibbspoll_for_work_loop:
9039220Sgibbs	if ((ahc->features & AHC_TWIN) != 0) {
9139220Sgibbs		xor	SBLKCTL,SELBUSB;	/* Toggle to the other bus */
9239220Sgibbs	}
9372811Sgibbs	test	SSTAT0, SELDO|SELDI	jnz selection;
9419164Sgibbstest_queue:
9519164Sgibbs	/* Has the driver posted any work for us? */
9695378SgibbsBEGIN_CRITICAL;
9739220Sgibbs	if ((ahc->features & AHC_QUEUE_REGS) != 0) {
9839220Sgibbs		test	QOFF_CTLSTA, SCB_AVAIL jz poll_for_work_loop;
9939220Sgibbs	} else {
10068087Sgibbs		mov	A, QINPOS;
10139220Sgibbs		cmp	KERNEL_QINPOS, A je poll_for_work_loop;
10239220Sgibbs	}
10366647Sgibbs	mov	ARG_1, NEXT_QUEUED_SCB;
1044568Sgibbs
10563457Sgibbs	/*
10663457Sgibbs	 * We have at least one queued SCB now and we don't have any 
10766647Sgibbs	 * SCBs in the list of SCBs awaiting selection.  Allocate a
10866647Sgibbs	 * card SCB for the host's SCB and get to work on it.
10963457Sgibbs	 */
11039220Sgibbs	if ((ahc->flags & AHC_PAGESCBS) != 0) {
11139220Sgibbs		mov	ALLZEROS	call	get_free_or_disc_scb;
11266647Sgibbs	} else {
11339220Sgibbs		/* In the non-paging case, the SCBID == hardware SCB index */
11466647Sgibbs		mov	SCBPTR, ARG_1;
11539220Sgibbs	}
11674094Sgibbs	or	SEQ_FLAGS2, SCB_DMA;
11795378SgibbsEND_CRITICAL;
11819164Sgibbsdma_queued_scb:
11963457Sgibbs	/*
12063457Sgibbs	 * DMA the SCB from host ram into the current SCB location.
12163457Sgibbs	 */
12223925Sgibbs	mvi	DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
12366647Sgibbs	mov	ARG_1	call dma_scb;
12419164Sgibbs	/*
12566647Sgibbs	 * Check one last time to see if this SCB was canceled
12666647Sgibbs	 * before we completed the DMA operation.  If it was,
12766647Sgibbs	 * the QINFIFO next pointer will not match our saved
12866647Sgibbs	 * value.
12919164Sgibbs	 */
13066647Sgibbs	mov	A, ARG_1;
13195378SgibbsBEGIN_CRITICAL;
13266647Sgibbs	cmp	NEXT_QUEUED_SCB, A jne abort_qinscb;
13368087Sgibbs	if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
13468087Sgibbs		cmp	SCB_TAG, A je . + 2;
13568402Sgibbs		mvi	SCB_MISMATCH call set_seqint;
13668087Sgibbs	}
13766647Sgibbs	mov	NEXT_QUEUED_SCB, SCB_NEXT;
13823925Sgibbs	mov	SCB_NEXT,WAITING_SCBH;
13923925Sgibbs	mov	WAITING_SCBH, SCBPTR;
14068402Sgibbs	if ((ahc->features & AHC_QUEUE_REGS) != 0) {
14168402Sgibbs		mov	NONE, SNSCB_QOFF;
14268402Sgibbs	} else {
14368402Sgibbs		inc	QINPOS;
14468402Sgibbs	}
14574094Sgibbs	and	SEQ_FLAGS2, ~SCB_DMA;
14623925Sgibbsstart_waiting:
14723925Sgibbs	/*
14863457Sgibbs	 * Start the first entry on the waiting SCB list.
14923925Sgibbs	 */
15023925Sgibbs	mov	SCBPTR, WAITING_SCBH;
15123925Sgibbs	call	start_selection;
152133670SgibbsEND_CRITICAL;
1538104Sgibbs
15472811Sgibbspoll_for_selection:
15568579Sgibbs	/*
15672811Sgibbs	 * Twin channel devices cannot handle things like SELTO
15772811Sgibbs	 * interrupts on the "background" channel.  So, while
15872811Sgibbs	 * selecting, keep polling the current channel until
15972811Sgibbs	 * either a selection or reselection occurs.
16068579Sgibbs	 */
16172811Sgibbs	test	SSTAT0, SELDO|SELDI	jz poll_for_selection;
16239220Sgibbs
16339220Sgibbsselection:
16463457Sgibbs	/*
16563457Sgibbs	 * We aren't expecting a bus free, so interrupt
16663457Sgibbs	 * the kernel driver if it happens.
16763457Sgibbs	 */
16863457Sgibbs	mvi	CLRSINT1,CLRBUSFREE;
16976634Sgibbs	if ((ahc->features & AHC_DT) == 0) {
17076634Sgibbs		or	SIMODE1, ENBUSFREE;
17176634Sgibbs	}
17263457Sgibbs
17368579Sgibbs	/*
17468579Sgibbs	 * Guard against a bus free after (re)selection
17568579Sgibbs	 * but prior to enabling the busfree interrupt.  SELDI
17668579Sgibbs	 * and SELDO will be cleared in that case.
17768579Sgibbs	 */
17871390Sgibbs	test	SSTAT0, SELDI|SELDO	jz bus_free_sel;
17939220Sgibbs	test	SSTAT0,SELDO	jnz select_out;
18039220Sgibbsselect_in:
18168087Sgibbs	if ((ahc->flags & AHC_TARGETROLE) != 0) {
18268087Sgibbs		if ((ahc->flags & AHC_INITIATORROLE) != 0) {
18341646Sgibbs			test	SSTAT0, TARGET	jz initiator_reselect;
18441646Sgibbs		}
18571390Sgibbs		mvi	CLRSINT0, CLRSELDI;
18642652Sgibbs
18739220Sgibbs		/*
18839220Sgibbs		 * We've just been selected.  Assert BSY and
18939220Sgibbs		 * setup the phase for receiving messages
19039220Sgibbs		 * from the target.
19139220Sgibbs		 */
19239220Sgibbs		mvi	SCSISIGO, P_MESGOUT|BSYO;
19339220Sgibbs
19439220Sgibbs		/*
19539220Sgibbs		 * Setup the DMA for sending the identify and
19641299Sgibbs		 * command information.
19739220Sgibbs		 */
198109590Sgibbs		mvi	SEQ_FLAGS, CMDPHASE_PENDING;
19941299Sgibbs
20041299Sgibbs		mov     A, TQINPOS;
20139220Sgibbs		if ((ahc->features & AHC_CMD_CHAN) != 0) {
20239220Sgibbs			mvi	DINDEX, CCHADDR;
20363457Sgibbs			mvi	SHARED_DATA_ADDR call set_32byte_addr;
20439220Sgibbs			mvi	CCSCBCTL, CCSCBRESET;
20539220Sgibbs		} else {
20639220Sgibbs			mvi	DINDEX, HADDR;
20763457Sgibbs			mvi	SHARED_DATA_ADDR call set_32byte_addr;
20839220Sgibbs			mvi	DFCNTRL, FIFORESET;
20939220Sgibbs		}
21039220Sgibbs
21139220Sgibbs		/* Initiator that selected us */
21263457Sgibbs		and	SAVED_SCSIID, SELID_MASK, SELID;
21363457Sgibbs		/* The Target ID we were selected at */
21463457Sgibbs		if ((ahc->features & AHC_MULTI_TID) != 0) {
21563457Sgibbs			and	A, OID, TARGIDIN;
21663457Sgibbs		} else if ((ahc->features & AHC_ULTRA2) != 0) {
21763457Sgibbs			and	A, OID, SCSIID_ULTRA2;
21839220Sgibbs		} else {
21963457Sgibbs			and	A, OID, SCSIID;
22039220Sgibbs		}
22163457Sgibbs		or	SAVED_SCSIID, A;
22263457Sgibbs		if ((ahc->features & AHC_TWIN) != 0) {
22363457Sgibbs			test 	SBLKCTL, SELBUSB jz . + 2;
22463457Sgibbs			or	SAVED_SCSIID, TWIN_CHNLB;
22563457Sgibbs		}
22644507Sgibbs		if ((ahc->features & AHC_CMD_CHAN) != 0) {
22763457Sgibbs			mov	CCSCBRAM, SAVED_SCSIID;
22839220Sgibbs		} else {
22963457Sgibbs			mov	DFDAT, SAVED_SCSIID;
23039220Sgibbs		}
23139220Sgibbs
23239220Sgibbs		/*
23339220Sgibbs		 * If ATN isn't asserted, the target isn't interested
23439220Sgibbs		 * in talking to us.  Go directly to bus free.
23563457Sgibbs		 * XXX SCSI-1 may require us to assume lun 0 if
23663457Sgibbs		 * ATN is false.
23739220Sgibbs		 */
23839220Sgibbs		test	SCSISIGI, ATNI	jz	target_busfree;
23939220Sgibbs
24039220Sgibbs		/*
24139220Sgibbs		 * Watch ATN closely now as we pull in messages from the
24239220Sgibbs		 * initiator.  We follow the guidlines from section 6.5
24339220Sgibbs		 * of the SCSI-2 spec for what messages are allowed when.
24439220Sgibbs		 */
24541646Sgibbs		call	target_inb;
24639220Sgibbs
24739220Sgibbs		/*
24839220Sgibbs		 * Our first message must be one of IDENTIFY, ABORT, or
24939220Sgibbs		 * BUS_DEVICE_RESET.
25039220Sgibbs		 */
25142652Sgibbs		test	DINDEX, MSG_IDENTIFYFLAG jz host_target_message_loop;
25239220Sgibbs		/* Store for host */
25339220Sgibbs		if ((ahc->features & AHC_CMD_CHAN) != 0) {
25439220Sgibbs			mov	CCSCBRAM, DINDEX;
25539220Sgibbs		} else {
25639220Sgibbs			mov	DFDAT, DINDEX;
25739220Sgibbs		}
25895378Sgibbs		and	SAVED_LUN, MSG_IDENTIFY_LUNMASK, DINDEX;
25939220Sgibbs
26039220Sgibbs		/* Remember for disconnection decision */
26139220Sgibbs		test	DINDEX, MSG_IDENTIFY_DISCFLAG jnz . + 2;
26239220Sgibbs		/* XXX Honor per target settings too */
26339220Sgibbs		or	SEQ_FLAGS, NO_DISCONNECT;
26439220Sgibbs
26539220Sgibbs		test	SCSISIGI, ATNI	jz	ident_messages_done;
26641646Sgibbs		call	target_inb;
26739220Sgibbs		/*
26839220Sgibbs		 * If this is a tagged request, the tagged message must
26939220Sgibbs		 * immediately follow the identify.  We test for a valid
27039220Sgibbs		 * tag message by seeing if it is >= MSG_SIMPLE_Q_TAG and
27139220Sgibbs		 * < MSG_IGN_WIDE_RESIDUE.
27239220Sgibbs		 */
27339220Sgibbs		add	A, -MSG_SIMPLE_Q_TAG, DINDEX;
27495378Sgibbs		jnc	ident_messages_done_msg_pending;
27539220Sgibbs		add	A, -MSG_IGN_WIDE_RESIDUE, DINDEX;
27695378Sgibbs		jc	ident_messages_done_msg_pending;
27795378Sgibbs
27839220Sgibbs		/* Store for host */
27939220Sgibbs		if ((ahc->features & AHC_CMD_CHAN) != 0) {
28039220Sgibbs			mov	CCSCBRAM, DINDEX;
28139220Sgibbs		} else {
28239220Sgibbs			mov	DFDAT, DINDEX;
28339220Sgibbs		}
28439220Sgibbs		
28539220Sgibbs		/*
28639220Sgibbs		 * If the initiator doesn't feel like providing a tag number,
28739220Sgibbs		 * we've got a failed selection and must transition to bus
28839220Sgibbs		 * free.
28939220Sgibbs		 */
29039220Sgibbs		test	SCSISIGI, ATNI	jz	target_busfree;
29142652Sgibbs
29239220Sgibbs		/*
29339220Sgibbs		 * Store the tag for the host.
29439220Sgibbs		 */
29541646Sgibbs		call	target_inb;
29639220Sgibbs		if ((ahc->features & AHC_CMD_CHAN) != 0) {
29739220Sgibbs			mov	CCSCBRAM, DINDEX;
29839220Sgibbs		} else {
29939220Sgibbs			mov	DFDAT, DINDEX;
30039220Sgibbs		}
30142652Sgibbs		mov	INITIATOR_TAG, DINDEX;
30263457Sgibbs		or	SEQ_FLAGS, TARGET_CMD_IS_TAGGED;
30395378Sgibbs
30495378Sgibbsident_messages_done:
30595378Sgibbs		/* Terminate the ident list */
30695378Sgibbs		if ((ahc->features & AHC_CMD_CHAN) != 0) {
30795378Sgibbs			mvi	CCSCBRAM, SCB_LIST_NULL;
30895378Sgibbs		} else {
30995378Sgibbs			mvi	DFDAT, SCB_LIST_NULL;
31095378Sgibbs		}
311109590Sgibbs		or	SEQ_FLAGS, TARG_CMD_PENDING;
31295378Sgibbs		test	SEQ_FLAGS2, TARGET_MSG_PENDING
31395378Sgibbs			jnz target_mesgout_pending;
31495378Sgibbs		test	SCSISIGI, ATNI jnz target_mesgout_continue;
31595378Sgibbs		jmp	target_ITloop;
31695378Sgibbs
31795378Sgibbs
31895378Sgibbsident_messages_done_msg_pending:
31995378Sgibbs		or	SEQ_FLAGS2, TARGET_MSG_PENDING;
32039220Sgibbs		jmp	ident_messages_done;
32139220Sgibbs
32241646Sgibbs		/*
32341646Sgibbs		 * Pushed message loop to allow the kernel to
32442652Sgibbs		 * run it's own target mode message state engine.
32541646Sgibbs		 */
32641646Sgibbshost_target_message_loop:
32768402Sgibbs		mvi	HOST_MSG_LOOP call set_seqint;
32841646Sgibbs		cmp	RETURN_1, EXIT_MSG_LOOP	je target_ITloop;
32941646Sgibbs		test	SSTAT0, SPIORDY jz .;
33041646Sgibbs		jmp	host_target_message_loop;
33139220Sgibbs	}
33239220Sgibbs
33368087Sgibbsif ((ahc->flags & AHC_INITIATORROLE) != 0) {
33439220Sgibbs/*
33523925Sgibbs * Reselection has been initiated by a target. Make a note that we've been
33623925Sgibbs * reselected, but haven't seen an IDENTIFY message from the target yet.
33713177Sgibbs */
33839220Sgibbsinitiator_reselect:
33923925Sgibbs	/* XXX test for and handle ONE BIT condition */
34071390Sgibbs	or	SXFRCTL0, SPIOEN|CLRSTCNT|CLRCHN;
34163457Sgibbs	and	SAVED_SCSIID, SELID_MASK, SELID;
34263457Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0) {
34363457Sgibbs		and	A, OID, SCSIID_ULTRA2;
34463457Sgibbs	} else {
34563457Sgibbs		and	A, OID, SCSIID;
34663457Sgibbs	}
34763457Sgibbs	or	SAVED_SCSIID, A;
34839545Sgibbs	if ((ahc->features & AHC_TWIN) != 0) {
34939545Sgibbs		test	SBLKCTL, SELBUSB	jz . + 2;
35063457Sgibbs		or	SAVED_SCSIID, TWIN_CHNLB;
35139545Sgibbs	}
35271390Sgibbs	mvi	CLRSINT0, CLRSELDI;
35339220Sgibbs	jmp	ITloop;
35441646Sgibbs}
3554568Sgibbs
35672811Sgibbsabort_qinscb:
35772811Sgibbs	call	add_scb_to_free_list;
35872811Sgibbs	jmp	poll_for_work_loop;
35972811Sgibbs
360133670SgibbsBEGIN_CRITICAL;
36172811Sgibbsstart_selection:
36272811Sgibbs	/*
36372811Sgibbs	 * If bus reset interrupts have been disabled (from a previous
36472811Sgibbs	 * reset), re-enable them now.  Resets are only of interest
36572811Sgibbs	 * when we have outstanding transactions, so we can safely
36672811Sgibbs	 * defer re-enabling the interrupt until, as an initiator,
36772811Sgibbs	 * we start sending out transactions again.
36872811Sgibbs	 */
36972811Sgibbs	test	SIMODE1, ENSCSIRST	jnz . + 3;
37072811Sgibbs	mvi	CLRSINT1, CLRSCSIRSTI;
37172811Sgibbs	or	SIMODE1, ENSCSIRST;
37272811Sgibbs	if ((ahc->features & AHC_TWIN) != 0) {
37372811Sgibbs		and	SINDEX,~SELBUSB,SBLKCTL;/* Clear channel select bit */
37472811Sgibbs		test	SCB_SCSIID, TWIN_CHNLB jz . + 2;
37572811Sgibbs		or	SINDEX, SELBUSB;
37672811Sgibbs		mov	SBLKCTL,SINDEX;		/* select channel */
37772811Sgibbs	}
37872811Sgibbsinitialize_scsiid:
37972811Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0) {
38072811Sgibbs		mov	SCSIID_ULTRA2, SCB_SCSIID;
38172811Sgibbs	} else if ((ahc->features & AHC_TWIN) != 0) {
38272811Sgibbs		and	SCSIID, TWIN_TID|OID, SCB_SCSIID;
38372811Sgibbs	} else {
38472811Sgibbs		mov	SCSIID, SCB_SCSIID;
38572811Sgibbs	}
38672811Sgibbs	if ((ahc->flags & AHC_TARGETROLE) != 0) {
38772811Sgibbs		mov	SINDEX, SCSISEQ_TEMPLATE;
38872811Sgibbs		test	SCB_CONTROL, TARGET_SCB jz . + 2;
38972811Sgibbs		or	SINDEX, TEMODE;
39072811Sgibbs		mov	SCSISEQ, SINDEX ret;
39172811Sgibbs	} else {
39272811Sgibbs		mov	SCSISEQ, SCSISEQ_TEMPLATE ret;
39372811Sgibbs	}
394133670SgibbsEND_CRITICAL;
39572811Sgibbs
39613177Sgibbs/*
397102673Sgibbs * Initialize transfer settings with SCB provided settings.
39872811Sgibbs */
39972811Sgibbsset_transfer_settings:
40072811Sgibbs	if ((ahc->features & AHC_ULTRA) != 0) {
40172811Sgibbs		test	SCB_CONTROL, ULTRAENB jz . + 2;
40272811Sgibbs		or	SXFRCTL0, FAST20;
40372811Sgibbs	} 
40472811Sgibbs	/*
40572811Sgibbs	 * Initialize SCSIRATE with the appropriate value for this target.
40672811Sgibbs	 */
40772811Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0) {
40872811Sgibbs		bmov	SCSIRATE, SCB_SCSIRATE, 2 ret;
40972811Sgibbs	} else {
41072811Sgibbs		mov	SCSIRATE, SCB_SCSIRATE ret;
41172811Sgibbs	}
41272811Sgibbs
41372811Sgibbsif ((ahc->flags & AHC_TARGETROLE) != 0) {
41472811Sgibbs/*
41572811Sgibbs * We carefully toggle SPIOEN to allow us to return the 
41672811Sgibbs * message byte we receive so it can be checked prior to
41772811Sgibbs * driving REQ on the bus for the next byte.
41872811Sgibbs */
41972811Sgibbstarget_inb:
42072811Sgibbs	/*
42172811Sgibbs	 * Drive REQ on the bus by enabling SCSI PIO.
42272811Sgibbs	 */
42372811Sgibbs	or	SXFRCTL0, SPIOEN;
42472811Sgibbs	/* Wait for the byte */
42572811Sgibbs	test	SSTAT0, SPIORDY jz .;
42672811Sgibbs	/* Prevent our read from triggering another REQ */
42772811Sgibbs	and	SXFRCTL0, ~SPIOEN;
42872811Sgibbs	/* Save latched contents */
42972811Sgibbs	mov	DINDEX, SCSIDATL ret;
43072811Sgibbs}
43172811Sgibbs
43272811Sgibbs/*
43323925Sgibbs * After the selection, remove this SCB from the "waiting SCB"
43423925Sgibbs * list.  This is achieved by simply moving our "next" pointer into
43523925Sgibbs * WAITING_SCBH.  Our next pointer will be set to null the next time this
43623925Sgibbs * SCB is used, so don't bother with it now.
43723925Sgibbs */
43839220Sgibbsselect_out:
43925005Sgibbs	/* Turn off the selection hardware */
44058258Sgibbs	and	SCSISEQ, TEMODE|ENSELI|ENRSELI|ENAUTOATNP, SCSISEQ;
44125005Sgibbs	mov	SCBPTR, WAITING_SCBH;
44224914Sgibbs	mov	WAITING_SCBH,SCB_NEXT;
44363457Sgibbs	mov	SAVED_SCSIID, SCB_SCSIID;
444115333Sgibbs	and	SAVED_LUN, LID, SCB_LUN;
445102673Sgibbs	call	set_transfer_settings;
44668087Sgibbs	if ((ahc->flags & AHC_TARGETROLE) != 0) {
44739220Sgibbs		test	SSTAT0, TARGET	jz initiator_select;
4488567Sdg
449102673Sgibbs		or	SXFRCTL0, CLRSTCNT|CLRCHN;
450102673Sgibbs
45139220Sgibbs		/*
452102673Sgibbs		 * Put tag in connonical location since not
453102673Sgibbs		 * all connections have an SCB.
454102673Sgibbs		 */
455102673Sgibbs		mov	INITIATOR_TAG, SCB_TARGET_ITAG;
456102673Sgibbs
457102673Sgibbs		/*
45839220Sgibbs		 * We've just re-selected an initiator.
45939220Sgibbs		 * Assert BSY and setup the phase for
46039220Sgibbs		 * sending our identify messages.
46139220Sgibbs		 */
46241646Sgibbs		mvi	P_MESGIN|BSYO call change_phase;
463102673Sgibbs		mvi	CLRSINT0, CLRSELDO;
4644568Sgibbs
46539220Sgibbs		/*
46639220Sgibbs		 * Start out with a simple identify message.
46739220Sgibbs		 */
468115333Sgibbs		or	SAVED_LUN, MSG_IDENTIFYFLAG call target_outb;
4696608Sgibbs
47039220Sgibbs		/*
47139220Sgibbs		 * If we are the result of a tagged command, send
47239220Sgibbs		 * a simple Q tag and the tag id.
47339220Sgibbs		 */
47439220Sgibbs		test	SCB_CONTROL, TAG_ENB	jz . + 3;
47539220Sgibbs		mvi	MSG_SIMPLE_Q_TAG call target_outb;
47695378Sgibbs		mov	SCB_TARGET_ITAG call target_outb;
47739220Sgibbstarget_synccmd:
47839220Sgibbs		/*
47939220Sgibbs		 * Now determine what phases the host wants us
48039220Sgibbs		 * to go through.
48139220Sgibbs		 */
48295378Sgibbs		mov	SEQ_FLAGS, SCB_TARGET_PHASES;
48342652Sgibbs		
48474972Sgibbs		test	SCB_CONTROL, MK_MESSAGE	jz target_ITloop;
48574972Sgibbs		mvi	P_MESGIN|BSYO call change_phase;
48674972Sgibbs		jmp	host_target_message_loop;
48739220Sgibbstarget_ITloop:
48839220Sgibbs		/*
48941646Sgibbs		 * Start honoring ATN signals now that
49044507Sgibbs		 * we properly identified ourselves.
49139220Sgibbs		 */
49241646Sgibbs		test	SCSISIGI, ATNI			jnz target_mesgout;
49339220Sgibbs		test	SEQ_FLAGS, CMDPHASE_PENDING	jnz target_cmdphase;
49439220Sgibbs		test	SEQ_FLAGS, DPHASE_PENDING	jnz target_dphase;
49539220Sgibbs		test	SEQ_FLAGS, SPHASE_PENDING	jnz target_sphase;
49639220Sgibbs
49739220Sgibbs		/*
49839220Sgibbs		 * No more work to do.  Either disconnect or not depending
49939220Sgibbs		 * on the state of NO_DISCONNECT.
50039220Sgibbs		 */
50139220Sgibbs		test	SEQ_FLAGS, NO_DISCONNECT jz target_disconnect; 
502102673Sgibbs		mvi	TARG_IMMEDIATE_SCB, SCB_LIST_NULL;
50374972Sgibbs		call	complete_target_cmd;
50439220Sgibbs		if ((ahc->flags & AHC_PAGESCBS) != 0) {
50539220Sgibbs			mov	ALLZEROS	call	get_free_or_disc_scb;
50639220Sgibbs		}
507102673Sgibbs		cmp	TARG_IMMEDIATE_SCB, SCB_LIST_NULL je .;
50839220Sgibbs		mvi	DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
509102673Sgibbs		mov	TARG_IMMEDIATE_SCB call dma_scb;
51095378Sgibbs		call	set_transfer_settings;
511102673Sgibbs		or	SXFRCTL0, CLRSTCNT|CLRCHN;
51239220Sgibbs		jmp	target_synccmd;
51339220Sgibbs
51441646Sgibbstarget_mesgout:
51541646Sgibbs		mvi	SCSISIGO, P_MESGOUT|BSYO;
51663457Sgibbstarget_mesgout_continue:
51741646Sgibbs		call	target_inb;
51863457Sgibbstarget_mesgout_pending:
519109590Sgibbs		and	SEQ_FLAGS2, ~TARGET_MSG_PENDING;
52041646Sgibbs		/* Local Processing goes here... */
52141646Sgibbs		jmp	host_target_message_loop;
52241646Sgibbs		
52339220Sgibbstarget_disconnect:
52441646Sgibbs		mvi	P_MESGIN|BSYO call change_phase;
52541816Sgibbs		test	SEQ_FLAGS, DPHASE	jz . + 2;
52641816Sgibbs		mvi	MSG_SAVEDATAPOINTER call target_outb;
52739220Sgibbs		mvi	MSG_DISCONNECT call target_outb;
52839220Sgibbs
52943880Sgibbstarget_busfree_wait:
53072640Sasmodai		/* Wait for preceding I/O session to complete. */
53143880Sgibbs		test	SCSISIGI, ACKI jnz .;
53239220Sgibbstarget_busfree:
53363457Sgibbs		and	SIMODE1, ~ENBUSFREE;
53468623Sgibbs		if ((ahc->features & AHC_ULTRA2) != 0) {
53568623Sgibbs			clr	SCSIBUSL;
53668623Sgibbs		}
53739220Sgibbs		clr	SCSISIGO;
53857099Sgibbs		mvi	LASTPHASE, P_BUSFREE;
53939220Sgibbs		call	complete_target_cmd;
54039220Sgibbs		jmp	poll_for_work;
54139220Sgibbs
54239220Sgibbstarget_cmdphase:
54395378Sgibbs		/*
54495378Sgibbs		 * The target has dropped ATN (doesn't want to abort or BDR)
54595378Sgibbs		 * and we believe this selection to be valid.  If the ring
54695378Sgibbs		 * buffer for new commands is full, return busy or queue full.
54795378Sgibbs		 */
54895378Sgibbs		if ((ahc->features & AHC_HS_MAILBOX) != 0) {
54995378Sgibbs			and	A, HOST_TQINPOS, HS_MAILBOX;
55095378Sgibbs		} else {
55195378Sgibbs			mov	A, KERNEL_TQINPOS;
55295378Sgibbs		}
55395378Sgibbs		cmp	TQINPOS, A jne tqinfifo_has_space;
55495378Sgibbs		mvi	P_STATUS|BSYO call change_phase;
55595378Sgibbs		test	SEQ_FLAGS, TARGET_CMD_IS_TAGGED jz . + 3;
55695378Sgibbs		mvi	STATUS_QUEUE_FULL call target_outb;
55795378Sgibbs		jmp	target_busfree_wait;
55895378Sgibbs		mvi	STATUS_BUSY call target_outb;
55995378Sgibbs		jmp	target_busfree_wait;
56095378Sgibbstqinfifo_has_space:	
56141646Sgibbs		mvi	P_COMMAND|BSYO call change_phase;
56241646Sgibbs		call	target_inb;
56339220Sgibbs		mov	A, DINDEX;
56439220Sgibbs		/* Store for host */
56539220Sgibbs		if ((ahc->features & AHC_CMD_CHAN) != 0) {
56639220Sgibbs			mov	CCSCBRAM, A;
56739220Sgibbs		} else {
56839220Sgibbs			mov	DFDAT, A;
56939220Sgibbs		}
57039220Sgibbs
57139220Sgibbs		/*
57239220Sgibbs		 * Determine the number of bytes to read
57341299Sgibbs		 * based on the command group code via table lookup.
57441299Sgibbs		 * We reuse the first 8 bytes of the TARG_SCSIRATE
57541299Sgibbs		 * BIOS array for this table. Count is one less than
57641299Sgibbs		 * the total for the command since we've already fetched
57741299Sgibbs		 * the first byte.
57839220Sgibbs		 */
57939220Sgibbs		shr	A, CMD_GROUP_CODE_SHIFT;
58068087Sgibbs		add	SINDEX, CMDSIZE_TABLE, A;
58139220Sgibbs		mov	A, SINDIR;
58239220Sgibbs
58339220Sgibbs		test	A, 0xFF jz command_phase_done;
58471390Sgibbs		or	SXFRCTL0, SPIOEN;
58539220Sgibbscommand_loop:
58639220Sgibbs		test	SSTAT0, SPIORDY jz .;
58739220Sgibbs		cmp	A, 1 jne . + 2;
58839220Sgibbs		and	SXFRCTL0, ~SPIOEN;	/* Last Byte */
58939220Sgibbs		if ((ahc->features & AHC_CMD_CHAN) != 0) {
59039220Sgibbs			mov	CCSCBRAM, SCSIDATL;
59139220Sgibbs		} else {
59239220Sgibbs			mov	DFDAT, SCSIDATL;
59339220Sgibbs		}
59439220Sgibbs		dec	A;
59539220Sgibbs		test	A, 0xFF jnz command_loop;
59639220Sgibbs
59739220Sgibbscommand_phase_done:
59839220Sgibbs		and	SEQ_FLAGS, ~CMDPHASE_PENDING;
59939220Sgibbs		jmp	target_ITloop;
60039220Sgibbs
60139220Sgibbstarget_dphase:
60239220Sgibbs		/*
60363457Sgibbs		 * Data phases on the bus are from the
60463457Sgibbs		 * perspective of the initiator.  The dma
60563457Sgibbs		 * code looks at LASTPHASE to determine the
60663457Sgibbs		 * data direction of the DMA.  Toggle it for
60763457Sgibbs		 * target transfers.
60839220Sgibbs		 */
60995378Sgibbs		xor	LASTPHASE, IOI, SCB_TARGET_DATA_DIR;
61095378Sgibbs		or	SCB_TARGET_DATA_DIR, BSYO call change_phase;
61139220Sgibbs		jmp	p_data;
61239220Sgibbs
61339220Sgibbstarget_sphase:
61441646Sgibbs		mvi	P_STATUS|BSYO call change_phase;
61541646Sgibbs		mvi	LASTPHASE, P_STATUS;
61695378Sgibbs		mov	SCB_SCSI_STATUS call target_outb;
61741646Sgibbs		/* XXX Watch for ATN or parity errors??? */
61839220Sgibbs		mvi	SCSISIGO, P_MESGIN|BSYO;
61939220Sgibbs		/* MSG_CMDCMPLT is 0, but we can't do an immediate of 0 */
62039220Sgibbs		mov	ALLZEROS call target_outb;
62143880Sgibbs		jmp	target_busfree_wait;
62239220Sgibbs	
62339220Sgibbscomplete_target_cmd:
62439220Sgibbs		test	SEQ_FLAGS, TARG_CMD_PENDING	jnz . + 2;
62539220Sgibbs		mov	SCB_TAG jmp complete_post;
62639220Sgibbs		if ((ahc->features & AHC_CMD_CHAN) != 0) {
62741299Sgibbs			/* Set the valid byte */
62841299Sgibbs			mvi	CCSCBADDR, 24;
62941299Sgibbs			mov	CCSCBRAM, ALLONES;
63041299Sgibbs			mvi	CCHCNT, 28;
63139220Sgibbs			or	CCSCBCTL, CCSCBEN|CCSCBRESET;
63239220Sgibbs			test	CCSCBCTL, CCSCBDONE jz .;
63339220Sgibbs			clr	CCSCBCTL;
63439220Sgibbs		} else {
63541299Sgibbs			/* Set the valid byte */
63641299Sgibbs			or	DFCNTRL, FIFORESET;
63741299Sgibbs			mvi	DFWADDR, 3; /* Third 64bit word or byte 24 */
63841299Sgibbs			mov	DFDAT, ALLONES;
63963457Sgibbs			mvi	28	call set_hcnt;
64039220Sgibbs			or	DFCNTRL, HDMAEN|FIFOFLUSH;
64139220Sgibbs			call	dma_finish;
64239220Sgibbs		}
64341299Sgibbs		inc	TQINPOS;
64441299Sgibbs		mvi	INTSTAT,CMDCMPLT ret;
64539220Sgibbs	}
64641646Sgibbs
64768087Sgibbsif ((ahc->flags & AHC_INITIATORROLE) != 0) {
64839220Sgibbsinitiator_select:
649102673Sgibbs	or	SXFRCTL0, SPIOEN|CLRSTCNT|CLRCHN;
65041646Sgibbs	/*
65141646Sgibbs	 * As soon as we get a successful selection, the target
65241646Sgibbs	 * should go into the message out phase since we have ATN
65341646Sgibbs	 * asserted.
65441646Sgibbs	 */
65539220Sgibbs	mvi	MSG_OUT, MSG_IDENTIFYFLAG;
656107420Sscottl	mvi	SEQ_FLAGS, NO_CDB_SENT;
657102673Sgibbs	mvi	CLRSINT0, CLRSELDO;
65813177Sgibbs
65941646Sgibbs	/*
66041646Sgibbs	 * Main loop for information transfer phases.  Wait for the
66141646Sgibbs	 * target to assert REQ before checking MSG, C/D and I/O for
66241646Sgibbs	 * the bus phase.
66341646Sgibbs	 */
66463457Sgibbsmesgin_phasemis:
6654568SgibbsITloop:
66639220Sgibbs	call	phase_lock;
6674568Sgibbs
66839220Sgibbs	mov	A, LASTPHASE;
6694568Sgibbs
67039220Sgibbs	test	A, ~P_DATAIN	jz p_data;
67123925Sgibbs	cmp	A,P_COMMAND	je p_command;
67223925Sgibbs	cmp	A,P_MESGOUT	je p_mesgout;
67323925Sgibbs	cmp	A,P_STATUS	je p_status;
67423925Sgibbs	cmp	A,P_MESGIN	je p_mesgin;
6754568Sgibbs
67668402Sgibbs	mvi	BAD_PHASE call set_seqint;
67723925Sgibbs	jmp	ITloop;			/* Try reading the bus again. */
6784568Sgibbs
67923925Sgibbsawait_busfree:
68023925Sgibbs	and	SIMODE1, ~ENBUSFREE;
68123925Sgibbs	mov	NONE, SCSIDATL;		/* Ack the last byte */
68268623Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0) {
68368623Sgibbs		clr	SCSIBUSL;	/* Prevent bit leakage durint SELTO */
68468623Sgibbs	}
68539220Sgibbs	and	SXFRCTL0, ~SPIOEN;
686123579Sgibbs	mvi	SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT;
68723925Sgibbs	test	SSTAT1,REQINIT|BUSFREE	jz .;
68823925Sgibbs	test	SSTAT1, BUSFREE jnz poll_for_work;
68968579Sgibbs	mvi	MISSED_BUSFREE call set_seqint;
69041646Sgibbs}
69123925Sgibbs	
69223925Sgibbsclear_target_state:
69341646Sgibbs	/*
69441646Sgibbs	 * We assume that the kernel driver may reset us
69541646Sgibbs	 * at any time, even in the middle of a DMA, so
69641646Sgibbs	 * clear DFCNTRL too.
69741646Sgibbs	 */
69841646Sgibbs	clr	DFCNTRL;
69968087Sgibbs	or	SXFRCTL0, CLRSTCNT|CLRCHN;
70041646Sgibbs
70141646Sgibbs	/*
70241646Sgibbs	 * We don't know the target we will connect to,
70341646Sgibbs	 * so default to narrow transfers to avoid
70441646Sgibbs	 * parity problems.
70541646Sgibbs	 */
70641646Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0) {
70741646Sgibbs		bmov	SCSIRATE, ALLZEROS, 2;
70841646Sgibbs	} else {
70941646Sgibbs		clr	SCSIRATE;
71063457Sgibbs		if ((ahc->features & AHC_ULTRA) != 0) {
71163457Sgibbs			and	SXFRCTL0, ~(FAST20);
71263457Sgibbs		}
71341646Sgibbs	}
71423925Sgibbs	mvi	LASTPHASE, P_BUSFREE;
71523925Sgibbs	/* clear target specific flags */
716107420Sscottl	mvi	SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT ret;
71723925Sgibbs
71863457Sgibbssg_advance:
71963457Sgibbs	clr	A;			/* add sizeof(struct scatter) */
72063457Sgibbs	add	SCB_RESIDUAL_SGPTR[0],SG_SIZEOF;
72163457Sgibbs	adc	SCB_RESIDUAL_SGPTR[1],A;
72263457Sgibbs	adc	SCB_RESIDUAL_SGPTR[2],A;
72363457Sgibbs	adc	SCB_RESIDUAL_SGPTR[3],A ret;
72463457Sgibbs
72574094Sgibbsif ((ahc->features & AHC_CMD_CHAN) != 0) {
72674094Sgibbsdisable_ccsgen:
72774094Sgibbs	test	CCSGCTL, CCSGEN jz return;
72874094Sgibbs	test	CCSGCTL, CCSGDONE jz .;
72974094Sgibbsdisable_ccsgen_fetch_done:
73074094Sgibbs	clr	CCSGCTL;
73174094Sgibbs	test	CCSGCTL, CCSGEN jnz .;
73274094Sgibbs	ret;
73363457Sgibbsidle_loop:
73476634Sgibbs	/*
73576634Sgibbs	 * Do we need any more segments for this transfer?
73676634Sgibbs	 */
73776634Sgibbs	test	SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jnz return;
73876634Sgibbs
73974094Sgibbs	/* Did we just finish fetching segs? */
74074094Sgibbs	cmp	CCSGCTL, CCSGEN|CCSGDONE je idle_sgfetch_complete;
74163457Sgibbs
74274094Sgibbs	/* Are we actively fetching segments? */
74374094Sgibbs	test	CCSGCTL, CCSGEN jnz return;
74463457Sgibbs
74574094Sgibbs	/*
74674094Sgibbs	 * Do we have any prefetch left???
74774094Sgibbs	 */
74874094Sgibbs	cmp	CCSGADDR, SG_PREFETCH_CNT jne idle_sg_avail;
74963457Sgibbs
75074094Sgibbs	/*
75174094Sgibbs	 * Need to fetch segments, but we can only do that
75274094Sgibbs	 * if the command channel is completely idle.  Make
75374094Sgibbs	 * sure we don't have an SCB prefetch going on.
75474094Sgibbs	 */
75574094Sgibbs	test	CCSCBCTL, CCSCBEN jnz return;
75663457Sgibbs
75774094Sgibbs	/*
75874094Sgibbs	 * We fetch a "cacheline aligned" and sized amount of data
75974094Sgibbs	 * so we don't end up referencing a non-existant page.
76074094Sgibbs	 * Cacheline aligned is in quotes because the kernel will
76174094Sgibbs	 * set the prefetch amount to a reasonable level if the
76274094Sgibbs	 * cacheline size is unknown.
76374094Sgibbs	 */
76474094Sgibbs	mvi	CCHCNT, SG_PREFETCH_CNT;
76574094Sgibbs	and	CCHADDR[0], SG_PREFETCH_ALIGN_MASK, SCB_RESIDUAL_SGPTR;
76674094Sgibbs	bmov	CCHADDR[1], SCB_RESIDUAL_SGPTR[1], 3;
76774094Sgibbs	mvi	CCSGCTL, CCSGEN|CCSGRESET ret;
76863457Sgibbsidle_sgfetch_complete:
76974094Sgibbs	call	disable_ccsgen_fetch_done;
77074094Sgibbs	and	CCSGADDR, SG_PREFETCH_ADDR_MASK, SCB_RESIDUAL_SGPTR;
77163457Sgibbsidle_sg_avail:
77274094Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0) {
77374094Sgibbs		/* Does the hardware have space for another SG entry? */
77474094Sgibbs		test	DFSTATUS, PRELOAD_AVAIL jz return;
77579874Sgibbs		bmov 	HADDR, CCSGRAM, 7;
77674094Sgibbs		bmov	SCB_RESIDUAL_DATACNT[3], CCSGRAM, 1;
77779874Sgibbs		if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
77879874Sgibbs			mov	SCB_RESIDUAL_DATACNT[3] call set_hhaddr;
77979874Sgibbs		}
78074094Sgibbs		call	sg_advance;
78174094Sgibbs		mov	SINDEX, SCB_RESIDUAL_SGPTR[0];
78274094Sgibbs		test	SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz . + 2;
78374094Sgibbs		or	SINDEX, LAST_SEG;
78474094Sgibbs		mov	SG_CACHE_PRE, SINDEX;
78574507Sgibbs		/* Load the segment */
78674507Sgibbs		or	DFCNTRL, PRELOADEN;
78763457Sgibbs	}
78874094Sgibbs	ret;
78974094Sgibbs}
79063457Sgibbs
79165942Sgibbsif ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 && ahc->pci_cachesize != 0) {
79213177Sgibbs/*
79365942Sgibbs * Calculate the trailing portion of this S/G segment that cannot
79465942Sgibbs * be transferred using memory write and invalidate PCI transactions.  
79565942Sgibbs * XXX Can we optimize this for PCI writes only???
79665942Sgibbs */
79765942Sgibbscalc_mwi_residual:
79865942Sgibbs	/*
79965942Sgibbs	 * If the ending address is on a cacheline boundary,
80065942Sgibbs	 * there is no need for an extra segment.
80165942Sgibbs	 */
80265942Sgibbs	mov	A, HCNT[0];
80365942Sgibbs	add	A, A, HADDR[0];
80465942Sgibbs	and	A, CACHESIZE_MASK;
80565942Sgibbs	test	A, 0xFF jz return;
80665942Sgibbs
80765942Sgibbs	/*
80865942Sgibbs	 * If the transfer is less than a cachline,
80965942Sgibbs	 * there is no need for an extra segment.
81065942Sgibbs	 */
81165942Sgibbs	test	HCNT[1], 0xFF	jnz calc_mwi_residual_final;
81265942Sgibbs	test	HCNT[2], 0xFF	jnz calc_mwi_residual_final;
81365942Sgibbs	add	NONE, INVERTED_CACHESIZE_MASK, HCNT[0];
81465942Sgibbs	jnc	return;
81565942Sgibbs
81665942Sgibbscalc_mwi_residual_final:
81765942Sgibbs	mov	MWI_RESIDUAL, A;
81865942Sgibbs	not	A;
81965942Sgibbs	inc	A;
82065942Sgibbs	add	HCNT[0], A;
82165942Sgibbs	adc	HCNT[1], -1;
82265942Sgibbs	adc	HCNT[2], -1 ret;
82365942Sgibbs}
82465942Sgibbs
82539220Sgibbsp_data:
826107420Sscottl	test	SEQ_FLAGS,NOT_IDENTIFIED|NO_CDB_SENT jz p_data_allowed;
827107420Sscottl	mvi	PROTO_VIOLATION call set_seqint;
828107420Sscottlp_data_allowed:
82939220Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0) {
83039220Sgibbs		mvi	DMAPARAMS, PRELOADEN|SCSIEN|HDMAEN;
83139220Sgibbs	} else {
83239220Sgibbs		mvi	DMAPARAMS, WIDEODD|SCSIEN|SDMAEN|HDMAEN|FIFORESET;
83339220Sgibbs	}
83439220Sgibbs	test	LASTPHASE, IOI jnz . + 2;
83539220Sgibbs	or	DMAPARAMS, DIRECTION;
83639220Sgibbs	if ((ahc->features & AHC_CMD_CHAN) != 0) {
83763457Sgibbs		/* We don't have any valid S/G elements */
83866647Sgibbs		mvi	CCSGADDR, SG_PREFETCH_CNT;
83939220Sgibbs	}
84079874Sgibbs	test	SEQ_FLAGS, DPHASE	jz data_phase_initialize;
8414568Sgibbs
84279874Sgibbs	/*
84379874Sgibbs	 * If we re-enter the data phase after going through another
84479874Sgibbs	 * phase, our transfer location has almost certainly been
84579874Sgibbs	 * corrupted by the interveining, non-data, transfers.  Ask
84679874Sgibbs	 * the host driver to fix us up based on the transfer residual.
84779874Sgibbs	 */
84879874Sgibbs	mvi	PDATA_REINIT	call set_seqint;
84979874Sgibbs	jmp	data_phase_loop;
85079874Sgibbs
85179874Sgibbsdata_phase_initialize:
85279874Sgibbs	/* We have seen a data phase for the first time */
85339220Sgibbs	or	SEQ_FLAGS, DPHASE;
85439220Sgibbs
85519164Sgibbs	/*
85619164Sgibbs	 * Initialize the DMA address and counter from the SCB.
85763457Sgibbs	 * Also set SCB_RESIDUAL_SGPTR, including the LAST_SEG
85863457Sgibbs	 * flag in the highest byte of the data count.  We cannot
85963457Sgibbs	 * modify the saved values in the SCB until we see a save
86063457Sgibbs	 * data pointers message.
86119164Sgibbs	 */
86279874Sgibbs	if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
86379874Sgibbs		/* The lowest address byte must be loaded last. */
86479874Sgibbs		mov	SCB_DATACNT[3] call set_hhaddr;
86579874Sgibbs	}
86639220Sgibbs	if ((ahc->features & AHC_CMD_CHAN) != 0) {
86739220Sgibbs		bmov	HADDR, SCB_DATAPTR, 7;
86863457Sgibbs		bmov	SCB_RESIDUAL_DATACNT[3], SCB_DATACNT[3], 5;
86939220Sgibbs	} else {
87039220Sgibbs		mvi	DINDEX, HADDR;
87139220Sgibbs		mvi	SCB_DATAPTR	call bcopy_7;
87263457Sgibbs		mvi	DINDEX, SCB_RESIDUAL_DATACNT + 3;
87363457Sgibbs		mvi	SCB_DATACNT + 3 call bcopy_5;
87439220Sgibbs	}
87565942Sgibbs	if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 && ahc->pci_cachesize != 0) {
87665942Sgibbs		call	calc_mwi_residual;
87765942Sgibbs	}
87863457Sgibbs	and	SCB_RESIDUAL_SGPTR[0], ~SG_FULL_RESID;
87919164Sgibbs
88039220Sgibbs	if ((ahc->features & AHC_ULTRA2) == 0) {
88139220Sgibbs		if ((ahc->features & AHC_CMD_CHAN) != 0) {
88239220Sgibbs			bmov	STCNT, HCNT, 3;
88339220Sgibbs		} else {
88439220Sgibbs			call	set_stcnt_from_hcnt;
88539220Sgibbs		}
88639220Sgibbs	}
88719164Sgibbs
88863457Sgibbsdata_phase_loop:
88963457Sgibbs	/* Guard against overruns */
89063457Sgibbs	test	SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz data_phase_inbounds;
89119164Sgibbs
89263457Sgibbs	/*
89368087Sgibbs	 * Turn on `Bit Bucket' mode, wait until the target takes
89468087Sgibbs	 * us to another phase, and then notify the host.
89563457Sgibbs	 */
89668087Sgibbs	and	DMAPARAMS, DIRECTION;
89768087Sgibbs	mov	DFCNTRL, DMAPARAMS;
89823925Sgibbs	or	SXFRCTL1,BITBUCKET;
89976634Sgibbs	if ((ahc->features & AHC_DT) == 0) {
90076634Sgibbs		test	SSTAT1,PHASEMIS	jz .;
90176634Sgibbs	} else {
90276634Sgibbs		test	SCSIPHASE, DATA_PHASE_MASK jnz .;
90376634Sgibbs	}
90468087Sgibbs	and	SXFRCTL1, ~BITBUCKET;
90568402Sgibbs	mvi	DATA_OVERRUN call set_seqint;
90668087Sgibbs	jmp	ITloop;
90768087Sgibbs
90816260Sgibbsdata_phase_inbounds:
90939220Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0) {
91063457Sgibbs		mov	SINDEX, SCB_RESIDUAL_SGPTR[0];
91163457Sgibbs		test	SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz . + 2;
91263457Sgibbs		or	SINDEX, LAST_SEG;
91363457Sgibbs		mov	SG_CACHE_PRE, SINDEX;
91463457Sgibbs		mov	DFCNTRL, DMAPARAMS;
91563457Sgibbsultra2_dma_loop:
91663457Sgibbs		call	idle_loop;
91763457Sgibbs		/*
91863457Sgibbs		 * The transfer is complete if either the last segment
91963457Sgibbs		 * completes or the target changes phase.
92063457Sgibbs		 */
92163457Sgibbs		test	SG_CACHE_SHADOW, LAST_SEG_DONE jnz ultra2_dmafinish;
92276634Sgibbs		if ((ahc->features & AHC_DT) == 0) {
92376634Sgibbs			if ((ahc->flags & AHC_TARGETROLE) != 0) {
92476634Sgibbs				 /*
92576634Sgibbs				  * As a target, we control the phases,
92676634Sgibbs				  * so ignore PHASEMIS.
92776634Sgibbs				  */
92876634Sgibbs				test	SSTAT0, TARGET jnz ultra2_dma_loop;
92976634Sgibbs			}
93076634Sgibbs			if ((ahc->flags & AHC_INITIATORROLE) != 0) {
93176634Sgibbs				test	SSTAT1,PHASEMIS	jz ultra2_dma_loop;
93276634Sgibbs			}
93376634Sgibbs		} else {
93476634Sgibbs			test	DFCNTRL, SCSIEN jnz ultra2_dma_loop;
93570204Sgibbs		}
93663457Sgibbs
93763457Sgibbsultra2_dmafinish:
93876634Sgibbs		/*
93976634Sgibbs		 * The transfer has terminated either due to a phase
94076634Sgibbs		 * change, and/or the completion of the last segment.
94176634Sgibbs		 * We have two goals here.  Do as much other work
94276634Sgibbs		 * as possible while the data fifo drains on a read
94376634Sgibbs		 * and respond as quickly as possible to the standard
94476634Sgibbs		 * messages (save data pointers/disconnect and command
94576634Sgibbs		 * complete) that usually follow a data phase.
94676634Sgibbs		 */
94763457Sgibbs		if ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0) {
94863457Sgibbs			/*
94976634Sgibbs			 * On chips with broken auto-flush, start
95076634Sgibbs			 * the flushing process now.  We'll poke
95176634Sgibbs			 * the chip from time to time to keep the
95276634Sgibbs			 * flush process going as we complete the
95376634Sgibbs			 * data phase.
95463457Sgibbs			 */
95563457Sgibbs			or	DFCNTRL, FIFOFLUSH;
95663457Sgibbs		}
95763457Sgibbs		/*
95876634Sgibbs		 * We assume that, even though data may still be
95976634Sgibbs		 * transferring to the host, that the SCSI side of
96076634Sgibbs		 * the DMA engine is now in a static state.  This
96176634Sgibbs		 * allows us to update our notion of where we are
96276634Sgibbs		 * in this transfer.
96376634Sgibbs		 *
96463944Sgibbs		 * If, by chance, we stopped before being able
96563944Sgibbs		 * to fetch additional segments for this transfer,
96663944Sgibbs		 * yet the last S/G was completely exhausted,
96763944Sgibbs		 * call our idle loop until it is able to load
96863944Sgibbs		 * another segment.  This will allow us to immediately
96963944Sgibbs		 * pickup on the next segment on the next data phase.
97063944Sgibbs		 *
97163944Sgibbs		 * If we happened to stop on the last segment, then
97263944Sgibbs		 * our residual information is still correct from
97363944Sgibbs		 * the idle loop and there is no need to perform
97476634Sgibbs		 * any fixups.
97563944Sgibbs		 */
97663944Sgibbsultra2_ensure_sg:
97763944Sgibbs		test	SG_CACHE_SHADOW, LAST_SEG jz ultra2_shvalid;
97863944Sgibbs		/* Record if we've consumed all S/G entries */
97995378Sgibbs		test	SSTAT2, SHVALID	jnz residuals_correct;
98063944Sgibbs		or	SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL;
98176634Sgibbs		jmp	residuals_correct;
98263944Sgibbs
98363944Sgibbsultra2_shvalid:
98495378Sgibbs		test	SSTAT2, SHVALID	jnz sgptr_fixup;
98563944Sgibbs		call	idle_loop;
98663944Sgibbs		jmp	ultra2_ensure_sg;
98763944Sgibbs
98863944Sgibbssgptr_fixup:
98963944Sgibbs		/*
99063457Sgibbs		 * Fixup the residual next S/G pointer.  The S/G preload
99163457Sgibbs		 * feature of the chip allows us to load two elements
99263457Sgibbs		 * in addition to the currently active element.  We
99363457Sgibbs		 * store the bottom byte of the next S/G pointer in
99463457Sgibbs		 * the SG_CACEPTR register so we can restore the
99563457Sgibbs		 * correct value when the DMA completes.  If the next
99663457Sgibbs		 * sg ptr value has advanced to the point where higher
99763457Sgibbs		 * bytes in the address have been affected, fix them
99863457Sgibbs		 * too.
99963457Sgibbs		 */
100063457Sgibbs		test	SG_CACHE_SHADOW, 0x80 jz sgptr_fixup_done;
100163457Sgibbs		test	SCB_RESIDUAL_SGPTR[0], 0x80 jnz sgptr_fixup_done;
100263457Sgibbs		add	SCB_RESIDUAL_SGPTR[1], -1;
100363457Sgibbs		adc	SCB_RESIDUAL_SGPTR[2], -1; 
100463457Sgibbs		adc	SCB_RESIDUAL_SGPTR[3], -1;
100563457Sgibbssgptr_fixup_done:
100663457Sgibbs		and	SCB_RESIDUAL_SGPTR[0], SG_ADDR_MASK, SG_CACHE_SHADOW;
1007115333Sgibbs		/* We are not the last seg */
1008115333Sgibbs		and	SCB_RESIDUAL_DATACNT[3], ~SG_LAST_SEG;
100976634Sgibbsresiduals_correct:
101076634Sgibbs		/*
101176634Sgibbs		 * Go ahead and shut down the DMA engine now.
101276634Sgibbs		 * In the future, we'll want to handle end of
101376634Sgibbs		 * transfer messages prior to doing this, but this
101476634Sgibbs		 * requires similar restructuring for pre-ULTRA2
101576634Sgibbs		 * controllers.
101676634Sgibbs		 */
101776634Sgibbs		test	DMAPARAMS, DIRECTION jnz ultra2_fifoempty;
101876634Sgibbsultra2_fifoflush:
101976634Sgibbs		if ((ahc->features & AHC_DT) == 0) {
102076634Sgibbs			if ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0) {
102176634Sgibbs				/*
102276634Sgibbs				 * On Rev A of the aic7890, the autoflush
102376634Sgibbs				 * feature doesn't function correctly.
102476634Sgibbs				 * Perform an explicit manual flush.  During
102576634Sgibbs				 * a manual flush, the FIFOEMP bit becomes
102676634Sgibbs				 * true every time the PCI FIFO empties
102776634Sgibbs				 * regardless of the state of the SCSI FIFO.
102876634Sgibbs				 * It can take up to 4 clock cycles for the
102976634Sgibbs				 * SCSI FIFO to get data into the PCI FIFO
103076634Sgibbs				 * and for FIFOEMP to de-assert.  Here we
103176634Sgibbs				 * guard against this condition by making
103276634Sgibbs				 * sure the FIFOEMP bit stays on for 5 full
103376634Sgibbs				 * clock cycles.
103476634Sgibbs				 */
103576634Sgibbs				or	DFCNTRL, FIFOFLUSH;
103676634Sgibbs				test	DFSTATUS, FIFOEMP jz ultra2_fifoflush;
103776634Sgibbs				test	DFSTATUS, FIFOEMP jz ultra2_fifoflush;
103876634Sgibbs				test	DFSTATUS, FIFOEMP jz ultra2_fifoflush;
103976634Sgibbs				test	DFSTATUS, FIFOEMP jz ultra2_fifoflush;
104076634Sgibbs			}
104176634Sgibbs			test	DFSTATUS, FIFOEMP jz ultra2_fifoflush;
104276634Sgibbs		} else {
104376634Sgibbs			/*
104476634Sgibbs			 * We enable the auto-ack feature on DT capable
104576634Sgibbs			 * controllers.  This means that the controller may
104676634Sgibbs			 * have already transferred some overrun bytes into
104776634Sgibbs			 * the data FIFO and acked them on the bus.  The only
104876634Sgibbs			 * way to detect this situation is to wait for
104976634Sgibbs			 * LAST_SEG_DONE to come true on a completed transfer
105076634Sgibbs			 * and then test to see if the data FIFO is non-empty.
105176634Sgibbs			 */
1052115334Sgibbs			test	SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL
1053115334Sgibbs				jz ultra2_wait_fifoemp;
105476634Sgibbs			test	SG_CACHE_SHADOW, LAST_SEG_DONE jz .;
1055115334Sgibbs			/*
1056115334Sgibbs			 * FIFOEMP can lag LAST_SEG_DONE.  Wait a few
1057115334Sgibbs			 * clocks before calling this an overrun.
1058115334Sgibbs			 */
105976634Sgibbs			test	DFSTATUS, FIFOEMP jnz ultra2_fifoempty;
1060115334Sgibbs			test	DFSTATUS, FIFOEMP jnz ultra2_fifoempty;
1061115334Sgibbs			test	DFSTATUS, FIFOEMP jnz ultra2_fifoempty;
106276634Sgibbs			/* Overrun */
106376634Sgibbs			jmp	data_phase_loop;
1064115334Sgibbsultra2_wait_fifoemp:
106576634Sgibbs			test	DFSTATUS, FIFOEMP jz .;
106676634Sgibbs		}
106776634Sgibbsultra2_fifoempty:
106876634Sgibbs		/* Don't clobber an inprogress host data transfer */
106976634Sgibbs		test	DFSTATUS, MREQPEND	jnz ultra2_fifoempty;
107076634Sgibbsultra2_dmahalt:
107176634Sgibbs		and     DFCNTRL, ~(SCSIEN|HDMAEN);
107276634Sgibbs		test	DFCNTRL, SCSIEN|HDMAEN jnz .;
107379874Sgibbs		if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
107479874Sgibbs			/*
107579874Sgibbs			 * Keep HHADDR cleared for future, 32bit addressed
107679874Sgibbs			 * only, DMA operations.
107779874Sgibbs			 *
107879874Sgibbs			 * Due to bayonette style S/G handling, our residual
107979874Sgibbs			 * data must be "fixed up" once the transfer is halted.
108079874Sgibbs			 * Here we fixup the HSHADDR stored in the high byte
108179874Sgibbs			 * of the residual data cnt.  By postponing the fixup,
108279874Sgibbs			 * we can batch the clearing of HADDR with the fixup.
108379874Sgibbs			 * If we halted on the last segment, the residual is
108479874Sgibbs			 * already correct.   If we are not on the last
108579874Sgibbs			 * segment, copy the high address directly from HSHADDR.
108679874Sgibbs			 * We don't need to worry about maintaining the
108779874Sgibbs			 * SG_LAST_SEG flag as it will always be false in the
108879874Sgibbs			 * case where an update is required.
108979874Sgibbs			 */
109079874Sgibbs			or	DSCOMMAND1, HADDLDSEL0;
109179874Sgibbs			test	SG_CACHE_SHADOW, LAST_SEG jnz . + 2;
109279874Sgibbs			mov	SCB_RESIDUAL_DATACNT[3], SHADDR;
109379874Sgibbs			clr	HADDR;
109479874Sgibbs			and	DSCOMMAND1, ~HADDLDSEL0;
109579874Sgibbs		}
109639220Sgibbs	} else {
109763457Sgibbs		/* If we are the last SG block, tell the hardware. */
109865942Sgibbs		if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0
109965942Sgibbs		  && ahc->pci_cachesize != 0) {
110065942Sgibbs			test	MWI_RESIDUAL, 0xFF jnz dma_mid_sg;
110165942Sgibbs		}
110263457Sgibbs		test	SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz dma_mid_sg;
110368087Sgibbs		if ((ahc->flags & AHC_TARGETROLE) != 0) {
110463944Sgibbs			test	SSTAT0, TARGET jz dma_last_sg;
1105123579Sgibbs			if ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0) {
110663944Sgibbs				test	DMAPARAMS, DIRECTION jz dma_mid_sg;
110763944Sgibbs			}
110857099Sgibbs		}
110963944Sgibbsdma_last_sg:
111039220Sgibbs		and	DMAPARAMS, ~WIDEODD;
111163457Sgibbsdma_mid_sg:
111263457Sgibbs		/* Start DMA data transfer. */
111339220Sgibbs		mov	DFCNTRL, DMAPARAMS;
111463457Sgibbsdma_loop:
111563457Sgibbs		if ((ahc->features & AHC_CMD_CHAN) != 0) {
111663457Sgibbs			call	idle_loop;
111763457Sgibbs		}
111863457Sgibbs		test	SSTAT0,DMADONE	jnz dma_dmadone;
111963457Sgibbs		test	SSTAT1,PHASEMIS	jz dma_loop;	/* ie. underrun */
112063457Sgibbsdma_phasemis:
112139220Sgibbs		/*
112263457Sgibbs		 * We will be "done" DMAing when the transfer count goes to
112363457Sgibbs		 * zero, or the target changes the phase (in light of this,
112463457Sgibbs		 * it makes sense that the DMA circuitry doesn't ACK when
112563457Sgibbs		 * PHASEMIS is active).  If we are doing a SCSI->Host transfer,
112663457Sgibbs		 * the data FIFO should be flushed auto-magically on STCNT=0
112763457Sgibbs		 * or a phase change, so just wait for FIFO empty status.
112839220Sgibbs		 */
112963457Sgibbsdma_checkfifo:
113063457Sgibbs		test	DFCNTRL,DIRECTION	jnz dma_fifoempty;
113163457Sgibbsdma_fifoflush:
113263457Sgibbs		test	DFSTATUS,FIFOEMP	jz dma_fifoflush;
113363457Sgibbsdma_fifoempty:
113463457Sgibbs		/* Don't clobber an inprogress host data transfer */
113563457Sgibbs		test	DFSTATUS, MREQPEND	jnz dma_fifoempty;
11364568Sgibbs
113739220Sgibbs		/*
113863457Sgibbs		 * Now shut off the DMA and make sure that the DMA
113963457Sgibbs		 * hardware has actually stopped.  Touching the DMA
114063457Sgibbs		 * counters, etc. while a DMA is active will result
114163457Sgibbs		 * in an ILLSADDR exception.
114239220Sgibbs		 */
114363457Sgibbsdma_dmadone:
114463457Sgibbs		and	DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN);
114563457Sgibbsdma_halt:
114663457Sgibbs		/*
114765942Sgibbs		 * Some revisions of the aic78XX have a problem where, if the
114863457Sgibbs		 * data fifo is full, but the PCI input latch is not empty, 
114963457Sgibbs		 * HDMAEN cannot be cleared.  The fix used here is to drain
115063457Sgibbs		 * the prefetched but unused data from the data fifo until
115163457Sgibbs		 * there is space for the input latch to drain.
115263457Sgibbs		 */
115365942Sgibbs		if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0) {
115465942Sgibbs			mov	NONE, DFDAT;
115565942Sgibbs		}
115663457Sgibbs		test	DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz dma_halt;
115722568Sgibbs
115863457Sgibbs		/* See if we have completed this last segment */
115963457Sgibbs		test	STCNT[0], 0xff	jnz data_phase_finish;
116063457Sgibbs		test	STCNT[1], 0xff	jnz data_phase_finish;
116163457Sgibbs		test	STCNT[2], 0xff	jnz data_phase_finish;
11629928Sgibbs
116339220Sgibbs		/*
116463457Sgibbs		 * Advance the scatter-gather pointers if needed 
116539220Sgibbs		 */
116665942Sgibbs		if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0
116765942Sgibbs		  && ahc->pci_cachesize != 0) {
116865942Sgibbs			test	MWI_RESIDUAL, 0xFF jz no_mwi_resid;
116965942Sgibbs			/*
117065942Sgibbs			 * Reload HADDR from SHADDR and setup the
117165942Sgibbs			 * count to be the size of our residual.
117265942Sgibbs			 */
117365942Sgibbs			if ((ahc->features & AHC_CMD_CHAN) != 0) {
117465942Sgibbs				bmov	HADDR, SHADDR, 4;
117565942Sgibbs				mov	HCNT, MWI_RESIDUAL;
117665942Sgibbs				bmov	HCNT[1], ALLZEROS, 2;
117765942Sgibbs			} else {
117865942Sgibbs				mvi	DINDEX, HADDR;
117965942Sgibbs				mvi	SHADDR call bcopy_4;
118065942Sgibbs				mov	MWI_RESIDUAL call set_hcnt;
118165942Sgibbs			}
118265942Sgibbs			clr	MWI_RESIDUAL;
118365942Sgibbs			jmp	sg_load_done;
118465942Sgibbsno_mwi_resid:
118565942Sgibbs		}
118663457Sgibbs		test	SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz sg_load;
118763457Sgibbs		or	SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL;
118863457Sgibbs		jmp	data_phase_finish;
118963457Sgibbssg_load:
119063457Sgibbs		/*
119163457Sgibbs		 * Load the next SG element's data address and length
119263457Sgibbs		 * into the DMA engine.  If we don't have hardware
119363457Sgibbs		 * to perform a prefetch, we'll have to fetch the
119463457Sgibbs		 * segment from host memory first.
119563457Sgibbs		 */
119639220Sgibbs		if ((ahc->features & AHC_CMD_CHAN) != 0) {
119763457Sgibbs			/* Wait for the idle loop to complete */
119863457Sgibbs			test	CCSGCTL, CCSGEN jz . + 3;
119963457Sgibbs			call	idle_loop;
120063457Sgibbs			test	CCSGCTL, CCSGEN jnz . - 1;
120163457Sgibbs			bmov 	HADDR, CCSGRAM, 7;
120279874Sgibbs			/*
120379874Sgibbs			 * Workaround for flaky external SCB RAM
120479874Sgibbs			 * on certain aic7895 setups.  It seems
120579874Sgibbs			 * unable to handle direct transfers from
120679874Sgibbs			 * S/G ram to certain SCB locations.
120779874Sgibbs			 */
120879874Sgibbs			mov	SINDEX, CCSGRAM;
120979874Sgibbs			mov	SCB_RESIDUAL_DATACNT[3], SINDEX;
121039220Sgibbs		} else {
121179874Sgibbs			if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
121279874Sgibbs				mov	ALLZEROS call set_hhaddr;
121379874Sgibbs			}
121463457Sgibbs			mvi	DINDEX, HADDR;
121563457Sgibbs			mvi	SCB_RESIDUAL_SGPTR	call bcopy_4;
121663457Sgibbs
121763457Sgibbs			mvi	SG_SIZEOF	call set_hcnt;
121863457Sgibbs
121963457Sgibbs			or	DFCNTRL, HDMAEN|DIRECTION|FIFORESET;
122063457Sgibbs
122163457Sgibbs			call	dma_finish;
122263457Sgibbs
122365942Sgibbs			mvi	DINDEX, HADDR;
122465942Sgibbs			call	dfdat_in_7;
122563457Sgibbs			mov	SCB_RESIDUAL_DATACNT[3], DFDAT;
122665942Sgibbs		}
122765942Sgibbs
122879874Sgibbs		if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
122979874Sgibbs			mov	SCB_RESIDUAL_DATACNT[3] call set_hhaddr;
123079874Sgibbs
123179874Sgibbs			/*
123279874Sgibbs			 * The lowest address byte must be loaded
123379874Sgibbs			 * last as it triggers the computation of
123479874Sgibbs			 * some items in the PCI block.  The ULTRA2
123579874Sgibbs			 * chips do this on PRELOAD.
123679874Sgibbs			 */
123779874Sgibbs			mov	HADDR, HADDR;
123879874Sgibbs		}
123965942Sgibbs		if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0
124065942Sgibbs		  && ahc->pci_cachesize != 0) {
124165942Sgibbs			call calc_mwi_residual;
124265942Sgibbs		}
124365942Sgibbs
124465942Sgibbs		/* Point to the new next sg in memory */
124565942Sgibbs		call	sg_advance;
124665942Sgibbs
124765942Sgibbssg_load_done:
124865942Sgibbs		if ((ahc->features & AHC_CMD_CHAN) != 0) {
124965942Sgibbs			bmov	STCNT, HCNT, 3;
125065942Sgibbs		} else {
125139220Sgibbs			call	set_stcnt_from_hcnt;
125239220Sgibbs		}
125339220Sgibbs
125468087Sgibbs		if ((ahc->flags & AHC_TARGETROLE) != 0) {
125563457Sgibbs			test	SSTAT0, TARGET jnz data_phase_loop;
125663457Sgibbs		}
125763457Sgibbs	}
125863457Sgibbsdata_phase_finish:
125963457Sgibbs	/*
126063457Sgibbs	 * If the target has left us in data phase, loop through
126163457Sgibbs	 * the dma code again.  In the case of ULTRA2 adapters,
126263457Sgibbs	 * we should only loop if there is a data overrun.  For
126363457Sgibbs	 * all other adapters, we'll loop after each S/G element
126463457Sgibbs	 * is loaded as well as if there is an overrun.
126563457Sgibbs	 */
126668087Sgibbs	if ((ahc->flags & AHC_TARGETROLE) != 0) {
126763457Sgibbs		test	SSTAT0, TARGET jnz data_phase_done;
126841646Sgibbs	}
126968087Sgibbs	if ((ahc->flags & AHC_INITIATORROLE) != 0) {
127063457Sgibbs		test	SSTAT1, REQINIT jz .;
127176634Sgibbs		if ((ahc->features & AHC_DT) == 0) {
127276634Sgibbs			test	SSTAT1,PHASEMIS	jz data_phase_loop;
127376634Sgibbs		} else {
127476634Sgibbs			test	SCSIPHASE, DATA_PHASE_MASK jnz data_phase_loop;
127576634Sgibbs		}
127639220Sgibbs	}
12774568Sgibbs
127863457Sgibbsdata_phase_done:
127963457Sgibbs	/*
128063457Sgibbs	 * After a DMA finishes, save the SG and STCNT residuals back into
128163457Sgibbs	 * the SCB.  We use STCNT instead of HCNT, since it's a reflection
128263457Sgibbs	 * of how many bytes were transferred on the SCSI (as opposed to the
128363457Sgibbs	 * host) bus.
128463457Sgibbs	 */
128539220Sgibbs	if ((ahc->features & AHC_CMD_CHAN) != 0) {
128663457Sgibbs		/* Kill off any pending prefetch */
128774094Sgibbs		call	disable_ccsgen;
128865942Sgibbs	}
128963457Sgibbs
129079874Sgibbs	if ((ahc->features & AHC_ULTRA2) == 0) {
129179874Sgibbs		/*
129279874Sgibbs		 * Clear the high address byte so that all other DMA
129379874Sgibbs		 * operations, which use 32bit addressing, can assume
129479874Sgibbs		 * HHADDR is 0.
129579874Sgibbs		 */
129679874Sgibbs		if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
129779874Sgibbs			mov	ALLZEROS call set_hhaddr;
129879874Sgibbs		}
129979874Sgibbs	}
130079874Sgibbs
130179874Sgibbs	/*
130279874Sgibbs	 * Update our residual information before the information is
130379874Sgibbs	 * lost by some other type of SCSI I/O (e.g. PIO).  If we have
130479874Sgibbs	 * transferred all data, no update is needed.
130579874Sgibbs	 *
130679874Sgibbs	 */
130779874Sgibbs	test	SCB_RESIDUAL_SGPTR, SG_LIST_NULL jnz residual_update_done;
130865942Sgibbs	if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0
130965942Sgibbs	  && ahc->pci_cachesize != 0) {
131065942Sgibbs		if ((ahc->features & AHC_CMD_CHAN) != 0) {
131165942Sgibbs			test	MWI_RESIDUAL, 0xFF jz bmov_resid;
131265942Sgibbs		}
131365942Sgibbs		mov	A, MWI_RESIDUAL;
131465942Sgibbs		add	SCB_RESIDUAL_DATACNT[0], A, STCNT[0];
131565942Sgibbs		clr	A;
131665942Sgibbs		adc	SCB_RESIDUAL_DATACNT[1], A, STCNT[1];
131765942Sgibbs		adc	SCB_RESIDUAL_DATACNT[2], A, STCNT[2];
131865942Sgibbs		clr	MWI_RESIDUAL;
131965942Sgibbs		if ((ahc->features & AHC_CMD_CHAN) != 0) {
132065942Sgibbs			jmp	. + 2;
132165942Sgibbsbmov_resid:
132265942Sgibbs			bmov	SCB_RESIDUAL_DATACNT, STCNT, 3;
132365942Sgibbs		}
132465942Sgibbs	} else if ((ahc->features & AHC_CMD_CHAN) != 0) {
132563457Sgibbs		bmov	SCB_RESIDUAL_DATACNT, STCNT, 3;
132639220Sgibbs	} else {
132765942Sgibbs		mov	SCB_RESIDUAL_DATACNT[0], STCNT[0];
132865942Sgibbs		mov	SCB_RESIDUAL_DATACNT[1], STCNT[1];
132965942Sgibbs		mov	SCB_RESIDUAL_DATACNT[2], STCNT[2];
133039220Sgibbs	}
133179874Sgibbsresidual_update_done:
133263457Sgibbs	/*
133363457Sgibbs	 * Since we've been through a data phase, the SCB_RESID* fields
133463457Sgibbs	 * are now initialized.  Clear the full residual flag.
133563457Sgibbs	 */
133663457Sgibbs	and	SCB_SGPTR[0], ~SG_FULL_RESID;
133763457Sgibbs
133839220Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0) {
133963457Sgibbs		/* Clear the channel in case we return to data phase later */
134039220Sgibbs		or	SXFRCTL0, CLRSTCNT|CLRCHN;
134168402Sgibbs		or	SXFRCTL0, CLRSTCNT|CLRCHN;
134239220Sgibbs	}
134322568Sgibbs
134468087Sgibbs	if ((ahc->flags & AHC_TARGETROLE) != 0) {
134541646Sgibbs		test	SEQ_FLAGS, DPHASE_PENDING jz ITloop;
134639220Sgibbs		and	SEQ_FLAGS, ~DPHASE_PENDING;
134742652Sgibbs		/*
134842652Sgibbs		 * For data-in phases, wait for any pending acks from the
134995378Sgibbs		 * initiator before changing phase.  We only need to
135095378Sgibbs		 * send Ignore Wide Residue messages for data-in phases.
135142652Sgibbs		 */
135242652Sgibbs		test	DFCNTRL, DIRECTION jz target_ITloop;
135342652Sgibbs		test	SSTAT1, REQINIT	jnz .;
1354115333Sgibbs		test	SCB_LUN, SCB_XFERLEN_ODD jz target_ITloop;
135595378Sgibbs		test	SCSIRATE, WIDEXFER jz target_ITloop;
135695378Sgibbs		/*
135795378Sgibbs		 * Issue an Ignore Wide Residue Message.
135895378Sgibbs		 */
135995378Sgibbs		mvi	P_MESGIN|BSYO call change_phase;
136095378Sgibbs		mvi	MSG_IGN_WIDE_RESIDUE call target_outb;
136195378Sgibbs		mvi	1 call target_outb;
136239220Sgibbs		jmp	target_ITloop;
136363457Sgibbs	} else {
136463457Sgibbs		jmp	ITloop;
136539220Sgibbs	}
13664568Sgibbs
136768087Sgibbsif ((ahc->flags & AHC_INITIATORROLE) != 0) {
136816260Sgibbs/*
136915328Sgibbs * Command phase.  Set up the DMA registers and let 'er rip.
137013177Sgibbs */
13714568Sgibbsp_command:
1372107420Sscottl	test	SEQ_FLAGS, NOT_IDENTIFIED jz p_command_okay;
1373107420Sscottl	mvi	PROTO_VIOLATION call set_seqint;
137479874Sgibbsp_command_okay:
13754568Sgibbs
137663457Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0) {
137763457Sgibbs		bmov	HCNT[0], SCB_CDB_LEN,  1;
137839220Sgibbs		bmov	HCNT[1], ALLZEROS, 2;
137963944Sgibbs		mvi	SG_CACHE_PRE, LAST_SEG;
138063457Sgibbs	} else if ((ahc->features & AHC_CMD_CHAN) != 0) {
138163457Sgibbs		bmov	STCNT[0], SCB_CDB_LEN, 1;
138263457Sgibbs		bmov	STCNT[1], ALLZEROS, 2;
138339220Sgibbs	} else {
138463457Sgibbs		mov	STCNT[0], SCB_CDB_LEN;
138563457Sgibbs		clr	STCNT[1];
138663457Sgibbs		clr	STCNT[2];
138739220Sgibbs	}
138863457Sgibbs	add	NONE, -13, SCB_CDB_LEN;
138965942Sgibbs	mvi	SCB_CDB_STORE jnc p_command_embedded;
139063457Sgibbsp_command_from_host:
139163457Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0) {
139263457Sgibbs		bmov	HADDR[0], SCB_CDB_PTR, 4;
139363457Sgibbs		mvi	DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN|DIRECTION);
139463457Sgibbs	} else {
139563457Sgibbs		if ((ahc->features & AHC_CMD_CHAN) != 0) {
139663457Sgibbs			bmov	HADDR[0], SCB_CDB_PTR, 4;
139765942Sgibbs			bmov	HCNT, STCNT, 3;
139863457Sgibbs		} else {
139963457Sgibbs			mvi	DINDEX, HADDR;
140068087Sgibbs			mvi	SCB_CDB_PTR call bcopy_4;
140168087Sgibbs			mov	SCB_CDB_LEN call set_hcnt;
140239220Sgibbs		}
140339220Sgibbs		mvi	DFCNTRL, (SCSIEN|SDMAEN|HDMAEN|DIRECTION|FIFORESET);
140463457Sgibbs	}
1405107420Sscottl	jmp	p_command_xfer;
140663457Sgibbsp_command_embedded:
140763457Sgibbs	/*
140876634Sgibbs	 * The data fifo seems to require 4 byte aligned
140963457Sgibbs	 * transfers from the sequencer.  Force this to
141063457Sgibbs	 * be the case by clearing HADDR[0] even though
141195378Sgibbs	 * we aren't going to touch host memory.
141263457Sgibbs	 */
141363457Sgibbs	clr	HADDR[0];
141463457Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0) {
141563457Sgibbs		mvi	DFCNTRL, (PRELOADEN|SCSIEN|DIRECTION);
141663457Sgibbs		bmov	DFDAT, SCB_CDB_STORE, 12; 
141765942Sgibbs	} else if ((ahc->features & AHC_CMD_CHAN) != 0) {
141871390Sgibbs		if ((ahc->flags & AHC_SCB_BTT) != 0) {
141965942Sgibbs			/*
142065942Sgibbs			 * On the 7895 the data FIFO will
142165942Sgibbs			 * get corrupted if you try to dump
142265942Sgibbs			 * data from external SCB memory into
142365942Sgibbs			 * the FIFO while it is enabled.  So,
142465942Sgibbs			 * fill the fifo and then enable SCSI
142565942Sgibbs			 * transfers.
142665942Sgibbs			 */
142765942Sgibbs			mvi	DFCNTRL, (DIRECTION|FIFORESET);
142865942Sgibbs		} else {
142965942Sgibbs			mvi	DFCNTRL, (SCSIEN|SDMAEN|DIRECTION|FIFORESET);
143065942Sgibbs		}
143165942Sgibbs		bmov	DFDAT, SCB_CDB_STORE, 12; 
143271390Sgibbs		if ((ahc->flags & AHC_SCB_BTT) != 0) {
143365942Sgibbs			mvi	DFCNTRL, (SCSIEN|SDMAEN|DIRECTION|FIFOFLUSH);
143465942Sgibbs		} else {
143563821Sgibbs			or	DFCNTRL, FIFOFLUSH;
143663821Sgibbs		}
143763457Sgibbs	} else {
143865942Sgibbs		mvi	DFCNTRL, (SCSIEN|SDMAEN|DIRECTION|FIFORESET);
143963821Sgibbs		call	copy_to_fifo_6;
144063821Sgibbs		call	copy_to_fifo_6;
144163821Sgibbs		or	DFCNTRL, FIFOFLUSH;
144263457Sgibbs	}
1443107420Sscottlp_command_xfer:
1444107420Sscottl	and	SEQ_FLAGS, ~NO_CDB_SENT;
144576634Sgibbs	if ((ahc->features & AHC_DT) == 0) {
144676634Sgibbs		test	SSTAT0, SDONE jnz . + 2;
1447107420Sscottl		test    SSTAT1, PHASEMIS jz . - 1;
144876634Sgibbs		/*
144976634Sgibbs		 * Wait for our ACK to go-away on it's own
145076634Sgibbs		 * instead of being killed by SCSIEN getting cleared.
145176634Sgibbs		 */
145276634Sgibbs		test	SCSISIGI, ACKI jnz .;
145376634Sgibbs	} else {
1454107420Sscottl		test	DFCNTRL, SCSIEN jnz .;
145576634Sgibbs	}
1456107420Sscottl	test	SSTAT0, SDONE jnz p_command_successful;
1457107420Sscottl	/*
1458107420Sscottl	 * Don't allow a data phase if the command
1459107420Sscottl	 * was not fully transferred.
1460107420Sscottl	 */
1461107420Sscottl	or	SEQ_FLAGS, NO_CDB_SENT;
1462107420Sscottlp_command_successful:
146355581Sgibbs	and	DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN);
146439220Sgibbs	test	DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz .;
146523925Sgibbs	jmp	ITloop;
14664568Sgibbs
146713177Sgibbs/*
146813177Sgibbs * Status phase.  Wait for the data byte to appear, then read it
146913177Sgibbs * and store it into the SCB.
147013177Sgibbs */
14714568Sgibbsp_status:
1472107420Sscottl	test	SEQ_FLAGS, NOT_IDENTIFIED jnz mesgin_proto_violation;
147379874Sgibbsp_status_okay:
147463457Sgibbs	mov	SCB_SCSI_STATUS, SCSIDATL;
1475107420Sscottl	or	SCB_CONTROL, STATUS_RCVD;
147623925Sgibbs	jmp	ITloop;
14774568Sgibbs
147813177Sgibbs/*
147941646Sgibbs * Message out phase.  If MSG_OUT is MSG_IDENTIFYFLAG, build a full
148041646Sgibbs * indentify message sequence and send it to the target.  The host may
148141646Sgibbs * override this behavior by setting the MK_MESSAGE bit in the SCB
148241646Sgibbs * control byte.  This will cause us to interrupt the host and allow
148341646Sgibbs * it to handle the message phase completely on its own.  If the bit
148441646Sgibbs * associated with this target is set, we will also interrupt the host,
148541646Sgibbs * thereby allowing it to send a message on the next selection regardless
148641646Sgibbs * of the transaction being sent.
148739220Sgibbs * 
148839220Sgibbs * If MSG_OUT is == HOST_MSG, also interrupt the host and take a message.
148941646Sgibbs * This is done to allow the host to send messages outside of an identify
149039220Sgibbs * sequence while protecting the seqencer from testing the MK_MESSAGE bit
149139220Sgibbs * on an SCB that might not be for the current nexus. (For example, a
149239220Sgibbs * BDR message in responce to a bad reselection would leave us pointed to
149339220Sgibbs * an SCB that doesn't have anything to do with the current target).
149441646Sgibbs *
149539220Sgibbs * Otherwise, treat MSG_OUT as a 1 byte message to send (abort, abort tag,
149639220Sgibbs * bus device reset).
149739220Sgibbs *
149839220Sgibbs * When there are no messages to send, MSG_OUT should be set to MSG_NOOP,
149939220Sgibbs * in case the target decides to put us in this phase for some strange
150039220Sgibbs * reason.
150113177Sgibbs */
150241646Sgibbsp_mesgout_retry:
150376634Sgibbs	/* Turn on ATN for the retry */
150476634Sgibbs	if ((ahc->features & AHC_DT) == 0) {
150576634Sgibbs		or	SCSISIGO, ATNO, LASTPHASE;
150676634Sgibbs	} else {
150776634Sgibbs		mvi	SCSISIGO, ATNO;
150876634Sgibbs	}
15094568Sgibbsp_mesgout:
151039220Sgibbs	mov	SINDEX, MSG_OUT;
151139220Sgibbs	cmp	SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host;
151241646Sgibbs	test	SCB_CONTROL,MK_MESSAGE	jnz host_message_loop;
151339220Sgibbsp_mesgout_identify:
1514115333Sgibbs	or	SINDEX, MSG_IDENTIFYFLAG|DISCENB, SAVED_LUN;
151563457Sgibbs	test	SCB_CONTROL, DISCENB jnz . + 2;
151663457Sgibbs	and	SINDEX, ~DISCENB;
151713177Sgibbs/*
151839220Sgibbs * Send a tag message if TAG_ENB is set in the SCB control block.
151939220Sgibbs * Use SCB_TAG (the position in the kernel's SCB array) as the tag value.
152013177Sgibbs */
152139220Sgibbsp_mesgout_tag:
152239220Sgibbs	test	SCB_CONTROL,TAG_ENB jz  p_mesgout_onebyte;
152339220Sgibbs	mov	SCSIDATL, SINDEX;	/* Send the identify message */
152439220Sgibbs	call	phase_lock;
152539220Sgibbs	cmp	LASTPHASE, P_MESGOUT	jne p_mesgout_done;
152639220Sgibbs	and	SCSIDATL,TAG_ENB|SCB_TAG_TYPE,SCB_CONTROL;
152739220Sgibbs	call	phase_lock;
152839220Sgibbs	cmp	LASTPHASE, P_MESGOUT	jne p_mesgout_done;
152939220Sgibbs	mov	SCB_TAG	jmp p_mesgout_onebyte;
153013177Sgibbs/*
153141646Sgibbs * Interrupt the driver, and allow it to handle this message
153241646Sgibbs * phase and any required retries.
153313177Sgibbs */
153439220Sgibbsp_mesgout_from_host:
153539220Sgibbs	cmp	SINDEX, HOST_MSG	jne p_mesgout_onebyte;
153641646Sgibbs	jmp	host_message_loop;
153739220Sgibbs
153839220Sgibbsp_mesgout_onebyte:
153939220Sgibbs	mvi	CLRSINT1, CLRATNO;
154039220Sgibbs	mov	SCSIDATL, SINDEX;
154139220Sgibbs
154213177Sgibbs/*
154341646Sgibbs * If the next bus phase after ATN drops is message out, it means
154413177Sgibbs * that the target is requesting that the last message(s) be resent.
154513177Sgibbs */
154639220Sgibbs	call	phase_lock;
154741646Sgibbs	cmp	LASTPHASE, P_MESGOUT	je p_mesgout_retry;
15484568Sgibbs
154919906Sgibbsp_mesgout_done:
155023925Sgibbs	mvi	CLRSINT1,CLRATNO;	/* Be sure to turn ATNO off */
155139220Sgibbs	mov	LAST_MSG, MSG_OUT;
155239220Sgibbs	mvi	MSG_OUT, MSG_NOOP;	/* No message left */
155323925Sgibbs	jmp	ITloop;
15544568Sgibbs
155513177Sgibbs/*
155613177Sgibbs * Message in phase.  Bytes are read using Automatic PIO mode.
155713177Sgibbs */
15584568Sgibbsp_mesgin:
155923925Sgibbs	mvi	ACCUM		call inb_first;	/* read the 1st message byte */
15604568Sgibbs
156123925Sgibbs	test	A,MSG_IDENTIFYFLAG	jnz mesgin_identify;
156223925Sgibbs	cmp	A,MSG_DISCONNECT	je mesgin_disconnect;
156323925Sgibbs	cmp	A,MSG_SAVEDATAPOINTER	je mesgin_sdptrs;
156423925Sgibbs	cmp	ALLZEROS,A		je mesgin_complete;
156523925Sgibbs	cmp	A,MSG_RESTOREPOINTERS	je mesgin_rdptrs;
156663457Sgibbs	cmp	A,MSG_IGN_WIDE_RESIDUE	je mesgin_ign_wide_residue;
156723925Sgibbs	cmp	A,MSG_NOOP		je mesgin_done;
15684568Sgibbs
156913177Sgibbs/*
157041887Sgibbs * Pushed message loop to allow the kernel to
157157099Sgibbs * run it's own message state engine.  To avoid an
157241887Sgibbs * extra nop instruction after signaling the kernel,
157341887Sgibbs * we perform the phase_lock before checking to see
157441887Sgibbs * if we should exit the loop and skip the phase_lock
157541887Sgibbs * in the ITloop.  Performing back to back phase_locks
157641887Sgibbs * shouldn't hurt, but why do it twice...
157713177Sgibbs */
157841887Sgibbshost_message_loop:
157968402Sgibbs	mvi	HOST_MSG_LOOP call set_seqint;
158041887Sgibbs	call	phase_lock;
158141887Sgibbs	cmp	RETURN_1, EXIT_MSG_LOOP	je ITloop + 1;
158241887Sgibbs	jmp	host_message_loop;
15839954Sgibbs
158463457Sgibbsmesgin_ign_wide_residue:
158563457Sgibbsif ((ahc->features & AHC_WIDE) != 0) {
158663457Sgibbs	test	SCSIRATE, WIDEXFER jz mesgin_reject;
158763457Sgibbs	/* Pull the residue byte */
158863457Sgibbs	mvi	ARG_1	call inb_next;
158963457Sgibbs	cmp	ARG_1, 0x01 jne mesgin_reject;
159063457Sgibbs	test	SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz . + 2;
1591115333Sgibbs	test	SCB_LUN, SCB_XFERLEN_ODD jnz mesgin_done;
159268402Sgibbs	mvi	IGN_WIDE_RES call set_seqint;
159363457Sgibbs	jmp	mesgin_done;
159463457Sgibbs}
159563457Sgibbs
1596107420Sscottlmesgin_proto_violation:
1597107420Sscottl	mvi	PROTO_VIOLATION call set_seqint;
1598107420Sscottl	jmp	mesgin_done;
159963457Sgibbsmesgin_reject:
160063457Sgibbs	mvi	MSG_MESSAGE_REJECT	call mk_mesg;
16019954Sgibbsmesgin_done:
160223925Sgibbs	mov	NONE,SCSIDATL;		/*dummy read from latch to ACK*/
160323925Sgibbs	jmp	ITloop;
16049954Sgibbs
160513177Sgibbs/*
160663457Sgibbs * We received a "command complete" message.  Put the SCB_TAG into the QOUTFIFO,
160719164Sgibbs * and trigger a completion interrupt.  Before doing so, check to see if there
160839220Sgibbs * is a residual or the status byte is something other than STATUS_GOOD (0).
160939220Sgibbs * In either of these conditions, we upload the SCB back to the host so it can
161019164Sgibbs * process this information.  In the case of a non zero status byte, we 
161119164Sgibbs * additionally interrupt the kernel driver synchronously, allowing it to
161219164Sgibbs * decide if sense should be retrieved.  If the kernel driver wishes to request
161368087Sgibbs * sense, it will fill the kernel SCB with a request sense command, requeue
161468087Sgibbs * it to the QINFIFO and tell us not to post to the QOUTFIFO by setting 
161568087Sgibbs * RETURN_1 to SEND_SENSE.
161613177Sgibbs */
1617107420Sscottlmesgin_complete:
161819164Sgibbs
1619107420Sscottl	/*
1620107420Sscottl	 * If ATN is raised, we still want to give the target a message.
1621107420Sscottl	 * Perhaps there was a parity error on this last message byte.
1622107420Sscottl	 * Either way, the target should take us to message out phase
1623107420Sscottl	 * and then attempt to complete the command again.  We should use a
1624107420Sscottl	 * critical section here to guard against a timeout triggering
1625107420Sscottl	 * for this command and setting ATN while we are still processing
1626107420Sscottl	 * the completion.
162768579Sgibbs	test	SCSISIGI, ATNI jnz mesgin_done;
1628107420Sscottl	 */
162968579Sgibbs
1630107420Sscottl	/*
1631107420Sscottl	 * If we are identified and have successfully sent the CDB,
1632107420Sscottl	 * any status will do.  Optimize this fast path.
1633107420Sscottl	 */
1634107420Sscottl	test	SCB_CONTROL, STATUS_RCVD jz mesgin_proto_violation;
1635107420Sscottl	test	SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT jz complete_accepted; 
1636107420Sscottl
1637107420Sscottl	/*
1638107420Sscottl	 * If the target never sent an identify message but instead went
1639107420Sscottl	 * to mesgin to give an invalid message, let the host abort us.
1640107420Sscottl	 */
1641107420Sscottl	test	SEQ_FLAGS, NOT_IDENTIFIED jnz mesgin_proto_violation;
1642107420Sscottl
1643107420Sscottl	/*
1644107420Sscottl	 * If we recevied good status but never successfully sent the
1645107420Sscottl	 * cdb, abort the command.
1646107420Sscottl	 */
1647107420Sscottl	test	SCB_SCSI_STATUS,0xff	jnz complete_accepted;
1648107420Sscottl	test	SEQ_FLAGS, NO_CDB_SENT jnz mesgin_proto_violation;
1649107420Sscottl
1650107420Sscottlcomplete_accepted:
1651107420Sscottl	/*
1652107420Sscottl	 * See if we attempted to deliver a message but the target ingnored us.
1653107420Sscottl	 */
165468402Sgibbs	test	SCB_CONTROL, MK_MESSAGE jz . + 2;
165568402Sgibbs	mvi	MKMSG_FAILED call set_seqint;
165668402Sgibbs
1657107420Sscottl	/*
1658107420Sscottl	 * Check for residuals
1659107420Sscottl	 */
166063457Sgibbs	test	SCB_SGPTR, SG_LIST_NULL jnz check_status;/* No xfer */
166163457Sgibbs	test	SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */
166263457Sgibbs	test	SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb;
166363457Sgibbscheck_status:
166463457Sgibbs	test	SCB_SCSI_STATUS,0xff	jz complete;	/* Good Status? */
166519164Sgibbsupload_scb:
166663457Sgibbs	or	SCB_SGPTR, SG_RESID_VALID;
166723925Sgibbs	mvi	DMAPARAMS, FIFORESET;
166823925Sgibbs	mov	SCB_TAG		call dma_scb;
166963457Sgibbs	test	SCB_SCSI_STATUS, 0xff	jz complete;	/* Just a residual? */
167068402Sgibbs	mvi	BAD_STATUS call set_seqint;		/* let driver know */
167139220Sgibbs	cmp	RETURN_1, SEND_SENSE	jne complete;
167268087Sgibbs	call	add_scb_to_free_list;
167323925Sgibbs	jmp	await_busfree;
167439220Sgibbscomplete:
167539220Sgibbs	mov	SCB_TAG call complete_post;
167623925Sgibbs	jmp	await_busfree;
167741646Sgibbs}
16784568Sgibbs
167939220Sgibbscomplete_post:
168039220Sgibbs	/* Post the SCBID in SINDEX and issue an interrupt */
168144507Sgibbs	call	add_scb_to_free_list;
168239220Sgibbs	mov	ARG_1, SINDEX;
168339220Sgibbs	if ((ahc->features & AHC_QUEUE_REGS) != 0) {
168439220Sgibbs		mov	A, SDSCB_QOFF;
168539220Sgibbs	} else {
168639220Sgibbs		mov	A, QOUTPOS;
168739220Sgibbs	}
168839220Sgibbs	mvi	QOUTFIFO_OFFSET call post_byte_setup;
168939220Sgibbs	mov	ARG_1 call post_byte;
169039220Sgibbs	if ((ahc->features & AHC_QUEUE_REGS) == 0) {
169139220Sgibbs		inc 	QOUTPOS;
169239220Sgibbs	}
169339220Sgibbs	mvi	INTSTAT,CMDCMPLT ret;
169439220Sgibbs
169568087Sgibbsif ((ahc->flags & AHC_INITIATORROLE) != 0) {
169613177Sgibbs/*
169713177Sgibbs * Is it a disconnect message?  Set a flag in the SCB to remind us
169863457Sgibbs * and await the bus going free.  If this is an untagged transaction
169963457Sgibbs * store the SCB id for it in our untagged target table for lookup on
170063457Sgibbs * a reselction.
170113177Sgibbs */
17029954Sgibbsmesgin_disconnect:
170368579Sgibbs	/*
170468579Sgibbs	 * If ATN is raised, we still want to give the target a message.
170568579Sgibbs	 * Perhaps there was a parity error on this last message byte
170668579Sgibbs	 * or we want to abort this command.  Either way, the target
170768579Sgibbs	 * should take us to message out phase and then attempt to
170868579Sgibbs	 * disconnect again.
170968579Sgibbs	 * XXX - Wait for more testing.
171068579Sgibbs	test	SCSISIGI, ATNI jnz mesgin_done;
171168579Sgibbs	 */
1712107420Sscottl	test	SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT
1713107420Sscottl		jnz mesgin_proto_violation;
171423925Sgibbs	or	SCB_CONTROL,DISCONNECTED;
171563457Sgibbs	if ((ahc->flags & AHC_PAGESCBS) != 0) {
171663457Sgibbs		call	add_scb_to_disc_list;
171763457Sgibbs	}
171863457Sgibbs	test	SCB_CONTROL, TAG_ENB jnz await_busfree;
171963457Sgibbs	mov	ARG_1, SCB_TAG;
1720115333Sgibbs	and	SAVED_LUN, LID, SCB_LUN;
172168087Sgibbs	mov	SCB_SCSIID	call set_busy_target;
172223925Sgibbs	jmp	await_busfree;
172319164Sgibbs
172415328Sgibbs/*
172519164Sgibbs * Save data pointers message:
172619164Sgibbs * Copying RAM values back to SCB, for Save Data Pointers message, but
172719164Sgibbs * only if we've actually been into a data phase to change them.  This
172819164Sgibbs * protects against bogus data in scratch ram and the residual counts
172919164Sgibbs * since they are only initialized when we go into data_in or data_out.
173076634Sgibbs * Ack the message as soon as possible.  For chips without S/G pipelining,
173176634Sgibbs * we can only ack the message after SHADDR has been saved.  On these
173276634Sgibbs * chips, SHADDR increments with every bus transaction, even PIO.
173315328Sgibbs */
173419164Sgibbsmesgin_sdptrs:
173576634Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0) {
173676634Sgibbs		mov	NONE,SCSIDATL;		/*dummy read from latch to ACK*/
173776634Sgibbs		test	SEQ_FLAGS, DPHASE	jz ITloop;
173876634Sgibbs	} else {
173976634Sgibbs		test	SEQ_FLAGS, DPHASE	jz mesgin_done;
174076634Sgibbs	}
174179874Sgibbs
174239220Sgibbs	/*
174379874Sgibbs	 * If we are asked to save our position at the end of the
174479874Sgibbs	 * transfer, just mark us at the end rather than perform a
174579874Sgibbs	 * full save.
174679874Sgibbs	 */
174779874Sgibbs	test	SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz mesgin_sdptrs_full;
174879874Sgibbs	or	SCB_SGPTR, SG_LIST_NULL;
174981170Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0) {
175081170Sgibbs		jmp	ITloop;
175181170Sgibbs	} else {
175281170Sgibbs		jmp	mesgin_done;
175381170Sgibbs	}
175479874Sgibbs
175579874Sgibbsmesgin_sdptrs_full:
175679874Sgibbs
175779874Sgibbs	/*
175863457Sgibbs	 * The SCB_SGPTR becomes the next one we'll download,
175963457Sgibbs	 * and the SCB_DATAPTR becomes the current SHADDR.
176039220Sgibbs	 * Use the residual number since STCNT is corrupted by
176139220Sgibbs	 * any message transfer.
176239220Sgibbs	 */
176339220Sgibbs	if ((ahc->features & AHC_CMD_CHAN) != 0) {
176439220Sgibbs		bmov	SCB_DATAPTR, SHADDR, 4;
176576634Sgibbs		if ((ahc->features & AHC_ULTRA2) == 0) {
176676634Sgibbs			mov	NONE,SCSIDATL;	/*dummy read from latch to ACK*/
176776634Sgibbs		}
176863457Sgibbs		bmov	SCB_DATACNT, SCB_RESIDUAL_DATACNT, 8;
176939220Sgibbs	} else {
177039220Sgibbs		mvi	DINDEX, SCB_DATAPTR;
177163457Sgibbs		mvi	SHADDR call bcopy_4;
177276634Sgibbs		mov	NONE,SCSIDATL;	/*dummy read from latch to ACK*/
177363457Sgibbs		mvi	SCB_RESIDUAL_DATACNT call bcopy_8;
177439220Sgibbs	}
177576634Sgibbs	jmp	ITloop;
17764568Sgibbs
177713177Sgibbs/*
177813177Sgibbs * Restore pointers message?  Data pointers are recopied from the
177913177Sgibbs * SCB anytime we enter a data phase for the first time, so all
178013177Sgibbs * we need to do is clear the DPHASE flag and let the data phase
1781107420Sscottl * code do the rest.  We also reset/reallocate the FIFO to make
1782107420Sscottl * sure we have a clean start for the next data or command phase.
178313177Sgibbs */
17849954Sgibbsmesgin_rdptrs:
178523925Sgibbs	and	SEQ_FLAGS, ~DPHASE;		/*
178623925Sgibbs						 * We'll reload them
178713177Sgibbs						 * the next time through
178823925Sgibbs						 * the dataphase.
178913177Sgibbs						 */
1790107420Sscottl	or	SXFRCTL0, CLRSTCNT|CLRCHN;
179123925Sgibbs	jmp	mesgin_done;
17924568Sgibbs
179313177Sgibbs/*
179463457Sgibbs * Index into our Busy Target table.  SINDEX and DINDEX are modified
179563457Sgibbs * upon return.  SCBPTR may be modified by this action.
179663457Sgibbs */
179768087Sgibbsset_busy_target:
179868087Sgibbs	shr	DINDEX, 4, SINDEX;
179971390Sgibbs	if ((ahc->flags & AHC_SCB_BTT) != 0) {
180063457Sgibbs		mov	SCBPTR, SAVED_LUN;
180168087Sgibbs		add	DINDEX, SCB_64_BTT;
180263457Sgibbs	} else {
180368087Sgibbs		add	DINDEX, BUSY_TARGETS;
180463457Sgibbs	}
180568087Sgibbs	mov	DINDIR, ARG_1 ret;
180663457Sgibbs
180763457Sgibbs/*
180813177Sgibbs * Identify message?  For a reconnecting target, this tells us the lun
180913177Sgibbs * that the reconnection is for - find the correct SCB and switch to it,
181013177Sgibbs * clearing the "disconnected" bit so we don't "find" it by accident later.
181113177Sgibbs */
18129954Sgibbsmesgin_identify:
181363457Sgibbs	/*
181463457Sgibbs	 * Determine whether a target is using tagged or non-tagged
181563457Sgibbs	 * transactions by first looking at the transaction stored in
181663457Sgibbs	 * the busy target array.  If there is no untagged transaction
181763457Sgibbs	 * for this target or the transaction is for a different lun, then
1818102673Sgibbs	 * this must be a tagged transaction.
181963457Sgibbs	 */
182072325Sgibbs	shr	SINDEX, 4, SAVED_SCSIID;
182171390Sgibbs	and	SAVED_LUN, MSG_IDENTIFY_LUNMASK, A;
182271390Sgibbs	if ((ahc->flags & AHC_SCB_BTT) != 0) {
182371390Sgibbs		add	SINDEX, SCB_64_BTT;
182468087Sgibbs		mov	SCBPTR, SAVED_LUN;
182571390Sgibbs		if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
182671390Sgibbs			add	NONE, -SCB_64_BTT, SINDEX;
182771390Sgibbs			jc	. + 2;
182871390Sgibbs			mvi	INTSTAT, OUT_OF_RANGE;
182971390Sgibbs			nop;
183071390Sgibbs			add	NONE, -(SCB_64_BTT + 16), SINDEX;
183171390Sgibbs			jnc	. + 2;
183271390Sgibbs			mvi	INTSTAT, OUT_OF_RANGE;
183371390Sgibbs			nop;
183471390Sgibbs		}
183568087Sgibbs	} else {
183671390Sgibbs		add	SINDEX, BUSY_TARGETS;
183768087Sgibbs		if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
183871390Sgibbs			add	NONE, -BUSY_TARGETS, SINDEX;
183968087Sgibbs			jc	. + 2;
184068087Sgibbs			mvi	INTSTAT, OUT_OF_RANGE;
184168402Sgibbs			nop;
184271390Sgibbs			add	NONE, -(BUSY_TARGETS + 16), SINDEX;
184368087Sgibbs			jnc	. + 2;
184468087Sgibbs			mvi	INTSTAT, OUT_OF_RANGE;
184568402Sgibbs			nop;
184668087Sgibbs		}
184768087Sgibbs	}
184868087Sgibbs	mov	ARG_1, SINDIR;
184968087Sgibbs	cmp	ARG_1, SCB_LIST_NULL	je snoop_tag;
185063457Sgibbs	if ((ahc->flags & AHC_PAGESCBS) != 0) {
185168579Sgibbs		mov	ARG_1 call findSCB;
185239220Sgibbs	} else {
185374094Sgibbs		mov	SCBPTR, ARG_1;
185439220Sgibbs	}
185571390Sgibbs	if ((ahc->flags & AHC_SCB_BTT) != 0) {
185663457Sgibbs		jmp setup_SCB_id_lun_okay;
185763457Sgibbs	} else {
185874094Sgibbs		/*
185974094Sgibbs		 * We only allow one untagged command per-target
186074094Sgibbs		 * at a time.  So, if the lun doesn't match, look
186174094Sgibbs		 * for a tag message.
186274094Sgibbs		 */
1863115333Sgibbs		and	A, LID, SCB_LUN;
186474094Sgibbs		cmp	SAVED_LUN, A	je setup_SCB_id_lun_okay;
186574094Sgibbs		if ((ahc->flags & AHC_PAGESCBS) != 0) {
186674094Sgibbs			/*
186774094Sgibbs			 * findSCB removes the SCB from the
186874094Sgibbs			 * disconnected list, so we must replace
186974094Sgibbs			 * it there should this SCB be for another
187074094Sgibbs			 * lun.
187174094Sgibbs			 */
187274094Sgibbs			call	cleanup_scb;
187374094Sgibbs		}
187463457Sgibbs	}
187539220Sgibbs
187613177Sgibbs/*
187713177Sgibbs * Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message.
187823168Sgibbs * If we get one, we use the tag returned to find the proper
187963457Sgibbs * SCB.  With SCB paging, we must search for non-tagged
188063457Sgibbs * transactions since the SCB may exist in any slot.  If we're not
188163457Sgibbs * using SCB paging, we can use the tag as the direct index to the
188263457Sgibbs * SCB.
188313177Sgibbs */
188424608Sgibbssnoop_tag:
188571390Sgibbs	if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
188671390Sgibbs		or	SEQ_FLAGS, 0x80;
188771390Sgibbs	}
188823925Sgibbs	mov	NONE,SCSIDATL;		/* ACK Identify MSG */
188939220Sgibbs	call	phase_lock;
189068087Sgibbs	if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
189168087Sgibbs		or	SEQ_FLAGS, 0x1;
189268087Sgibbs	}
189323925Sgibbs	cmp	LASTPHASE, P_MESGIN	jne not_found;
189468087Sgibbs	if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
189568087Sgibbs		or	SEQ_FLAGS, 0x2;
189668087Sgibbs	}
189723925Sgibbs	cmp	SCSIBUSL,MSG_SIMPLE_Q_TAG jne not_found;
18986608Sgibbsget_tag:
189963457Sgibbs	if ((ahc->flags & AHC_PAGESCBS) != 0) {
190063457Sgibbs		mvi	ARG_1	call inb_next;	/* tag value */
190163457Sgibbs		mov	ARG_1	call findSCB;
190263457Sgibbs	} else {
190368087Sgibbs		mvi	ARG_1	call inb_next;	/* tag value */
190468087Sgibbs		mov	SCBPTR, ARG_1;
190563457Sgibbs	}
190613177Sgibbs
190763457Sgibbs/*
190863457Sgibbs * Ensure that the SCB the tag points to is for
190963457Sgibbs * an SCB transaction to the reconnecting target.
191063457Sgibbs */
191139220Sgibbssetup_SCB:
191268087Sgibbs	if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
191368087Sgibbs		or	SEQ_FLAGS, 0x4;
191468087Sgibbs	}
191571390Sgibbs	mov	A, SCB_SCSIID;
191671390Sgibbs	cmp	SAVED_SCSIID, A	jne not_found_cleanup_scb;
191768087Sgibbs	if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
191868087Sgibbs		or	SEQ_FLAGS, 0x8;
191968087Sgibbs	}
192071390Sgibbssetup_SCB_id_okay:
1921115333Sgibbs	and	A, LID, SCB_LUN;
192271390Sgibbs	cmp	SAVED_LUN, A	jne not_found_cleanup_scb;
192363457Sgibbssetup_SCB_id_lun_okay:
192468087Sgibbs	if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
192568087Sgibbs		or	SEQ_FLAGS, 0x10;
192663457Sgibbs	}
192768087Sgibbs	test	SCB_CONTROL,DISCONNECTED jz not_found_cleanup_scb;
192823925Sgibbs	and	SCB_CONTROL,~DISCONNECTED;
192963457Sgibbs	test	SCB_CONTROL, TAG_ENB	jnz setup_SCB_tagged;
193074094Sgibbs	if ((ahc->flags & AHC_SCB_BTT) != 0) {
193174094Sgibbs		mov	A, SCBPTR;
193274094Sgibbs	}
193368087Sgibbs	mvi	ARG_1, SCB_LIST_NULL;
193468087Sgibbs	mov	SAVED_SCSIID	call	set_busy_target;
193574094Sgibbs	if ((ahc->flags & AHC_SCB_BTT) != 0) {
193674094Sgibbs		mov	SCBPTR, A;
193774094Sgibbs	}
193863457Sgibbssetup_SCB_tagged:
1939107420Sscottl	clr	SEQ_FLAGS;	/* make note of IDENTIFY */
194039220Sgibbs	call	set_transfer_settings;
194139220Sgibbs	/* See if the host wants to send a message upon reconnection */
194239220Sgibbs	test	SCB_CONTROL, MK_MESSAGE jz mesgin_done;
194339220Sgibbs	mvi	HOST_MSG	call mk_mesg;
194423925Sgibbs	jmp	mesgin_done;
194515328Sgibbs
194668087Sgibbsnot_found_cleanup_scb:
194768087Sgibbs	if ((ahc->flags & AHC_PAGESCBS) != 0) {
194874094Sgibbs		call	cleanup_scb;
194968087Sgibbs	}
195019218Sgibbsnot_found:
195168402Sgibbs	mvi	NO_MATCH call set_seqint;
195223925Sgibbs	jmp	mesgin_done;
19536608Sgibbs
19544568Sgibbsmk_mesg:
195576634Sgibbs	if ((ahc->features & AHC_DT) == 0) {
195676634Sgibbs		or	SCSISIGO, ATNO, LASTPHASE;
195776634Sgibbs	} else {
195876634Sgibbs		mvi	SCSISIGO, ATNO;
195976634Sgibbs	}
196039220Sgibbs	mov	MSG_OUT,SINDEX ret;
19614568Sgibbs
196213177Sgibbs/*
196313177Sgibbs * Functions to read data in Automatic PIO mode.
196413177Sgibbs *
196513177Sgibbs * According to Adaptec's documentation, an ACK is not sent on input from
196613177Sgibbs * the target until SCSIDATL is read from.  So we wait until SCSIDATL is
196713177Sgibbs * latched (the usual way), then read the data byte directly off the bus
196813177Sgibbs * using SCSIBUSL.  When we have pulled the ATN line, or we just want to
196913177Sgibbs * acknowledge the byte, then we do a dummy read from SCISDATL.  The SCSI
197013177Sgibbs * spec guarantees that the target will hold the data byte on the bus until
197113177Sgibbs * we send our ACK.
197213177Sgibbs *
197313177Sgibbs * The assumption here is that these are called in a particular sequence,
197413177Sgibbs * and that REQ is already set when inb_first is called.  inb_{first,next}
197513177Sgibbs * use the same calling convention as inb.
197613177Sgibbs */
197757099Sgibbsinb_next_wait_perr:
197868402Sgibbs	mvi	PERR_DETECTED call set_seqint;
197957099Sgibbs	jmp	inb_next_wait;
198013177Sgibbsinb_next:
198123925Sgibbs	mov	NONE,SCSIDATL;		/*dummy read from latch to ACK*/
198213360Sgibbsinb_next_wait:
198321947Sgibbs	/*
198421947Sgibbs	 * If there is a parity error, wait for the kernel to
198521947Sgibbs	 * see the interrupt and prepare our message response
198621947Sgibbs	 * before continuing.
198721947Sgibbs	 */
198823925Sgibbs	test	SSTAT1, REQINIT	jz inb_next_wait;
198957099Sgibbs	test	SSTAT1, SCSIPERR jnz inb_next_wait_perr;
199057099Sgibbsinb_next_check_phase:
199123925Sgibbs	and	LASTPHASE, PHASE_MASK, SCSISIGI;
199223925Sgibbs	cmp	LASTPHASE, P_MESGIN jne mesgin_phasemis;
199319623Sgibbsinb_first:
199423925Sgibbs	mov	DINDEX,SINDEX;
199523925Sgibbs	mov	DINDIR,SCSIBUSL	ret;		/*read byte directly from bus*/
199613177Sgibbsinb_last:
199723925Sgibbs	mov	NONE,SCSIDATL ret;		/*dummy read from latch to ACK*/
199841646Sgibbs}
19994568Sgibbs
200068087Sgibbsif ((ahc->flags & AHC_TARGETROLE) != 0) {
200141646Sgibbs/*
200241646Sgibbs * Change to a new phase.  If we are changing the state of the I/O signal,
200341646Sgibbs * from out to in, wait an additional data release delay before continuing.
200441646Sgibbs */
200541646Sgibbschange_phase:
2006165628Syar	/* Wait for preceding I/O session to complete. */
200743880Sgibbs	test	SCSISIGI, ACKI jnz .;
200843880Sgibbs
200943880Sgibbs	/* Change the phase */
201041646Sgibbs	and	DINDEX, IOI, SCSISIGI;
201141646Sgibbs	mov	SCSISIGO, SINDEX;
201241646Sgibbs	and	A, IOI, SINDEX;
201343880Sgibbs
201443880Sgibbs	/*
201543880Sgibbs	 * If the data direction has changed, from
201643880Sgibbs	 * out (initiator driving) to in (target driving),
201763457Sgibbs	 * we must wait at least a data release delay plus
201843880Sgibbs	 * the normal bus settle delay. [SCSI III SPI 10.11.0]
201943880Sgibbs	 */
202041646Sgibbs	cmp 	DINDEX, A je change_phase_wait;
202141646Sgibbs	test	SINDEX, IOI jz change_phase_wait;
202241646Sgibbs	call	change_phase_wait;
202341646Sgibbschange_phase_wait:
202441646Sgibbs	nop;
202541646Sgibbs	nop;
202641646Sgibbs	nop;
202741646Sgibbs	nop ret;
202841646Sgibbs
202941646Sgibbs/*
203041646Sgibbs * Send a byte to an initiator in Automatic PIO mode.
203141646Sgibbs */
203239220Sgibbstarget_outb:
203339220Sgibbs	or	SXFRCTL0, SPIOEN;
203439220Sgibbs	test	SSTAT0, SPIORDY	jz .;
203539220Sgibbs	mov	SCSIDATL, SINDEX;
203639220Sgibbs	test	SSTAT0, SPIORDY	jz .;
203741646Sgibbs	and	SXFRCTL0, ~SPIOEN ret;
203839220Sgibbs}
203939220Sgibbs	
204013177Sgibbs/*
204163457Sgibbs * Locate a disconnected SCB by SCBID.  Upon return, SCBPTR and SINDEX will
204263457Sgibbs * be set to the position of the SCB.  If the SCB cannot be found locally,
204363457Sgibbs * it will be paged in from host memory.  RETURN_2 stores the address of the
204463457Sgibbs * preceding SCB in the disconnected list which can be used to speed up
204563457Sgibbs * removal of the found SCB from the disconnected list.
204613177Sgibbs */
204765942Sgibbsif ((ahc->flags & AHC_PAGESCBS) != 0) {
204895378SgibbsBEGIN_CRITICAL;
20494568SgibbsfindSCB:
205068087Sgibbs	mov	A, SINDEX;			/* Tag passed in SINDEX */
205168087Sgibbs	cmp	DISCONNECTED_SCBH, SCB_LIST_NULL je findSCB_notFound;
205263457Sgibbs	mov	SCBPTR, DISCONNECTED_SCBH;	/* Initialize SCBPTR */
205368087Sgibbs	mvi	ARG_2, SCB_LIST_NULL;		/* Head of list */
205463457Sgibbs	jmp	findSCB_loop;
205539220SgibbsfindSCB_next:
205663457Sgibbs	cmp	SCB_NEXT, SCB_LIST_NULL je findSCB_notFound;
205768087Sgibbs	mov	ARG_2, SCBPTR;
205839220Sgibbs	mov	SCBPTR,SCB_NEXT;
205923168SgibbsfindSCB_loop:
206063457Sgibbs	cmp	SCB_TAG, A	jne findSCB_next;
206119164Sgibbsrem_scb_from_disc_list:
206239220Sgibbs	cmp	ARG_2, SCB_LIST_NULL	je rHead;
206339220Sgibbs	mov	DINDEX, SCB_NEXT;
206468087Sgibbs	mov	SINDEX, SCBPTR;
206539220Sgibbs	mov	SCBPTR, ARG_2;
206639220Sgibbs	mov	SCB_NEXT, DINDEX;
206723925Sgibbs	mov	SCBPTR, SINDEX ret;
206815328SgibbsrHead:
206923925Sgibbs	mov	DISCONNECTED_SCBH,SCB_NEXT ret;
207095378SgibbsEND_CRITICAL;
207168087SgibbsfindSCB_notFound:
207268087Sgibbs	/*
207368087Sgibbs	 * We didn't find it.  Page in the SCB.
207468087Sgibbs	 */
207568087Sgibbs	mov	ARG_1, A; /* Save tag */
207668087Sgibbs	mov	ALLZEROS call get_free_or_disc_scb;
207768087Sgibbs	mvi	DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
207868087Sgibbs	mov	ARG_1	jmp dma_scb;
207968087Sgibbs}
20804568Sgibbs
208139220Sgibbs/*
208239220Sgibbs * Prepare the hardware to post a byte to host memory given an
208363457Sgibbs * index of (A + (256 * SINDEX)) and a base address of SHARED_DATA_ADDR.
208439220Sgibbs */
208539220Sgibbspost_byte_setup:
208639220Sgibbs	mov	ARG_2, SINDEX;
208739220Sgibbs	if ((ahc->features & AHC_CMD_CHAN) != 0) {
208839220Sgibbs		mvi	DINDEX, CCHADDR;
208963457Sgibbs		mvi	SHARED_DATA_ADDR call	set_1byte_addr;
209039220Sgibbs		mvi	CCHCNT, 1;
209139220Sgibbs		mvi	CCSCBCTL, CCSCBRESET ret;
209239220Sgibbs	} else {
209339220Sgibbs		mvi	DINDEX, HADDR;
209463457Sgibbs		mvi	SHARED_DATA_ADDR call	set_1byte_addr;
209563457Sgibbs		mvi	1	call set_hcnt;
209639220Sgibbs		mvi	DFCNTRL, FIFORESET ret;
209739220Sgibbs	}
209839220Sgibbs
209939220Sgibbspost_byte:
210039220Sgibbs	if ((ahc->features & AHC_CMD_CHAN) != 0) {
210139220Sgibbs		bmov	CCSCBRAM, SINDEX, 1;
210239220Sgibbs		or	CCSCBCTL, CCSCBEN|CCSCBRESET;
210339220Sgibbs		test	CCSCBCTL, CCSCBDONE jz .;
210439220Sgibbs		clr	CCSCBCTL ret;
210539220Sgibbs	} else {
210639220Sgibbs		mov	DFDAT, SINDEX;
210739220Sgibbs		or	DFCNTRL, HDMAEN|FIFOFLUSH;
210839220Sgibbs		jmp	dma_finish;
210939220Sgibbs	}
211039220Sgibbs
211157099Sgibbsphase_lock_perr:
211268402Sgibbs	mvi	PERR_DETECTED call set_seqint;
211339220Sgibbsphase_lock:     
211457099Sgibbs	/*
211557099Sgibbs	 * If there is a parity error, wait for the kernel to
211657099Sgibbs	 * see the interrupt and prepare our message response
211757099Sgibbs	 * before continuing.
211857099Sgibbs	 */
211939220Sgibbs	test	SSTAT1, REQINIT jz phase_lock;
212057099Sgibbs	test	SSTAT1, SCSIPERR jnz phase_lock_perr;
212157099Sgibbsphase_lock_latch_phase:
212276634Sgibbs	if ((ahc->features & AHC_DT) == 0) {
212376634Sgibbs		and	SCSISIGO, PHASE_MASK, SCSISIGI;
212476634Sgibbs	}
212541646Sgibbs	and	LASTPHASE, PHASE_MASK, SCSISIGI ret;
212639220Sgibbs
212739220Sgibbsif ((ahc->features & AHC_CMD_CHAN) == 0) {
212863457Sgibbsset_hcnt:
212963457Sgibbs	mov	HCNT[0], SINDEX;
213063457Sgibbsclear_hcnt:
213163457Sgibbs	clr	HCNT[1];
213263457Sgibbs	clr	HCNT[2] ret;
213363457Sgibbs
213419164Sgibbsset_stcnt_from_hcnt:
213523925Sgibbs	mov	STCNT[0], HCNT[0];
213623925Sgibbs	mov	STCNT[1], HCNT[1];
213723925Sgibbs	mov	STCNT[2], HCNT[2] ret;
21384568Sgibbs
213963457Sgibbsbcopy_8:
214063457Sgibbs	mov	DINDIR, SINDIR;
214119164Sgibbsbcopy_7:
214223925Sgibbs	mov	DINDIR, SINDIR;
214323925Sgibbs	mov	DINDIR, SINDIR;
214419164Sgibbsbcopy_5:
214523925Sgibbs	mov	DINDIR, SINDIR;
214619164Sgibbsbcopy_4:
214723925Sgibbs	mov	DINDIR, SINDIR;
214819164Sgibbsbcopy_3:
214923925Sgibbs	mov	DINDIR, SINDIR;
215023925Sgibbs	mov	DINDIR, SINDIR;
215123925Sgibbs	mov	DINDIR, SINDIR ret;
215239220Sgibbs}
21534568Sgibbs
215468087Sgibbsif ((ahc->flags & AHC_TARGETROLE) != 0) {
215539220Sgibbs/*
215639220Sgibbs * Setup addr assuming that A is an index into
215739220Sgibbs * an array of 32byte objects, SINDEX contains
215839220Sgibbs * the base address of that array, and DINDEX
215939220Sgibbs * contains the base address of the location
216039220Sgibbs * to store the indexed address.
216139220Sgibbs */
216239220Sgibbsset_32byte_addr:
216339220Sgibbs	shr	ARG_2, 3, A;
216439220Sgibbs	shl	A, 5;
216539220Sgibbs	jmp	set_1byte_addr;
216639220Sgibbs}
216739220Sgibbs
216839220Sgibbs/*
216939220Sgibbs * Setup addr assuming that A is an index into
217039220Sgibbs * an array of 64byte objects, SINDEX contains
217139220Sgibbs * the base address of that array, and DINDEX
217239220Sgibbs * contains the base address of the location
217339220Sgibbs * to store the indexed address.
217439220Sgibbs */
217539220Sgibbsset_64byte_addr:
217639220Sgibbs	shr	ARG_2, 2, A;
217739220Sgibbs	shl	A, 6;
217839220Sgibbs
217939220Sgibbs/*
218063457Sgibbs * Setup addr assuming that A + (ARG_2 * 256) is an
218139220Sgibbs * index into an array of 1byte objects, SINDEX contains
218239220Sgibbs * the base address of that array, and DINDEX contains
218339220Sgibbs * the base address of the location to store the computed
218439220Sgibbs * address.
218539220Sgibbs */
218639220Sgibbsset_1byte_addr:
218739220Sgibbs	add     DINDIR, A, SINDIR;
218839220Sgibbs	mov     A, ARG_2;
218939220Sgibbs	adc	DINDIR, A, SINDIR;
219039220Sgibbs	clr	A;
219139220Sgibbs	adc	DINDIR, A, SINDIR;
219239220Sgibbs	adc	DINDIR, A, SINDIR ret;
219339220Sgibbs
219439220Sgibbs/*
219595378Sgibbs * Either post or fetch an SCB from host memory based on the
219639220Sgibbs * DIRECTION bit in DMAPARAMS. The host SCB index is in SINDEX.
219739220Sgibbs */
219819164Sgibbsdma_scb:
219939220Sgibbs	mov	A, SINDEX;
220039220Sgibbs	if ((ahc->features & AHC_CMD_CHAN) != 0) {
220139220Sgibbs		mvi	DINDEX, CCHADDR;
220239220Sgibbs		mvi	HSCB_ADDR call set_64byte_addr;
220339220Sgibbs		mov	CCSCBPTR, SCBPTR;
220439220Sgibbs		test	DMAPARAMS, DIRECTION jz dma_scb_tohost;
220571390Sgibbs		if ((ahc->flags & AHC_SCB_BTT) != 0) {
220665942Sgibbs			mvi	CCHCNT, SCB_DOWNLOAD_SIZE_64;
220765942Sgibbs		} else {
220865942Sgibbs			mvi	CCHCNT, SCB_DOWNLOAD_SIZE;
220965942Sgibbs		}
221039220Sgibbs		mvi	CCSCBCTL, CCARREN|CCSCBEN|CCSCBDIR|CCSCBRESET;
221139220Sgibbs		cmp	CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN|CCSCBDIR jne .;
221239220Sgibbs		jmp	dma_scb_finish;
221339220Sgibbsdma_scb_tohost:
221465942Sgibbs		mvi	CCHCNT, SCB_UPLOAD_SIZE;
221565942Sgibbs		if ((ahc->features & AHC_ULTRA2) == 0) {
221639220Sgibbs			mvi	CCSCBCTL, CCSCBRESET;
221765942Sgibbs			bmov	CCSCBRAM, SCB_BASE, SCB_UPLOAD_SIZE;
221839220Sgibbs			or	CCSCBCTL, CCSCBEN|CCSCBRESET;
221968579Sgibbs			test	CCSCBCTL, CCSCBDONE jz .;
222065942Sgibbs		} else if ((ahc->bugs & AHC_SCBCHAN_UPLOAD_BUG) != 0) {
222165942Sgibbs			mvi	CCSCBCTL, CCARREN|CCSCBRESET;
222265942Sgibbs			cmp	CCSCBCTL, ARRDONE|CCARREN jne .;
222365942Sgibbs			mvi	CCHCNT, SCB_UPLOAD_SIZE;
222465942Sgibbs			mvi	CCSCBCTL, CCSCBEN|CCSCBRESET;
222565942Sgibbs			cmp	CCSCBCTL, CCSCBDONE|CCSCBEN jne .;
222639220Sgibbs		} else {
222739220Sgibbs			mvi	CCSCBCTL, CCARREN|CCSCBEN|CCSCBRESET;
222839220Sgibbs			cmp	CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN jne .;
222939220Sgibbs		}
223039220Sgibbsdma_scb_finish:
223139220Sgibbs		clr	CCSCBCTL;
223239220Sgibbs		test	CCSCBCTL, CCARREN|CCSCBEN jnz .;
223339220Sgibbs		ret;
223439220Sgibbs	} else {
223539220Sgibbs		mvi	DINDEX, HADDR;
223639220Sgibbs		mvi	HSCB_ADDR call set_64byte_addr;
223765942Sgibbs		mvi	SCB_DOWNLOAD_SIZE call set_hcnt;
223839220Sgibbs		mov	DFCNTRL, DMAPARAMS;
223939220Sgibbs		test	DMAPARAMS, DIRECTION	jnz dma_scb_fromhost;
224039220Sgibbs		/* Fill it with the SCB data */
224124175Sgibbscopy_scb_tofifo:
224265942Sgibbs		mvi	SINDEX, SCB_BASE;
224365942Sgibbs		add	A, SCB_DOWNLOAD_SIZE, SINDEX;
224424175Sgibbscopy_scb_tofifo_loop:
224565942Sgibbs		call	copy_to_fifo_8;
224639220Sgibbs		cmp	SINDEX, A jne copy_scb_tofifo_loop;
224739220Sgibbs		or	DFCNTRL, HDMAEN|FIFOFLUSH;
224865942Sgibbs		jmp	dma_finish;
224919164Sgibbsdma_scb_fromhost:
225065942Sgibbs		mvi	DINDEX, SCB_BASE;
225165942Sgibbs		if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0) {
225265942Sgibbs			/*
225365942Sgibbs			 * The PCI module will only issue a PCI
225465942Sgibbs			 * retry if the data FIFO is empty.  If the
225565942Sgibbs			 * host disconnects in the middle of a
225665942Sgibbs			 * transfer, we must empty the fifo of all
225765942Sgibbs			 * available data to force the chip to
225865942Sgibbs			 * continue the transfer.  This does not
225965942Sgibbs			 * happen for SCSI transfers as the SCSI module
2260102673Sgibbs			 * will drain the FIFO as data are made available.
226172325Sgibbs			 * When the hang occurs, we know that a multiple
2262102673Sgibbs			 * of 8 bytes is in the FIFO because the PCI
226365942Sgibbs			 * module has an 8 byte input latch that only
226465942Sgibbs			 * dumps to the FIFO when HCNT == 0 or the
226565942Sgibbs			 * latch is full.
226665942Sgibbs			 */
226772325Sgibbs			clr	A;
226874507Sgibbs			/* Wait for at least 8 bytes of data to arrive. */
226965942Sgibbsdma_scb_hang_fifo:
227074434Sgibbs			test	DFSTATUS, FIFOQWDEMP jnz dma_scb_hang_fifo;
227165942Sgibbsdma_scb_hang_wait:
227265942Sgibbs			test	DFSTATUS, MREQPEND jnz dma_scb_hang_wait;
227365942Sgibbs			test	DFSTATUS, HDONE	jnz dma_scb_hang_dma_done;
227465942Sgibbs			test	DFSTATUS, HDONE	jnz dma_scb_hang_dma_done;
227565942Sgibbs			test	DFSTATUS, HDONE	jnz dma_scb_hang_dma_done;
227665942Sgibbs			/*
227772325Sgibbs			 * The PCI module no longer intends to perform
227874507Sgibbs			 * a PCI transaction.  Drain the fifo.
227965942Sgibbs			 */
228081170Sgibbsdma_scb_hang_dma_drain_fifo:
228181170Sgibbs			not	A, HCNT;
228281170Sgibbs			add	A, SCB_DOWNLOAD_SIZE+SCB_BASE+1;
228381170Sgibbs			and	A, ~0x7;
228481170Sgibbs			mov	DINDIR,DFDAT;
228581170Sgibbs			cmp	DINDEX, A jne . - 1;
228681170Sgibbs			cmp	DINDEX, SCB_DOWNLOAD_SIZE+SCB_BASE
228781170Sgibbs				je	dma_finish_nowait;
228881170Sgibbs			/* Restore A as the lines left to transfer. */
228981170Sgibbs			add	A, -SCB_BASE, DINDEX;
229081170Sgibbs			shr	A, 3;
229165942Sgibbs			jmp	dma_scb_hang_fifo;
229265942Sgibbsdma_scb_hang_dma_done:
229365942Sgibbs			and	DFCNTRL, ~HDMAEN;
229465942Sgibbs			test	DFCNTRL, HDMAEN jnz .;
229572325Sgibbs			add	SEQADDR0, A;
229665942Sgibbs		} else {
229765942Sgibbs			call	dma_finish;
229865942Sgibbs		}
229972325Sgibbs		call	dfdat_in_8;
230072325Sgibbs		call	dfdat_in_8;
230172325Sgibbs		call	dfdat_in_8;
230265942Sgibbsdfdat_in_8:
230365942Sgibbs		mov	DINDIR,DFDAT;
230419164Sgibbsdfdat_in_7:
230539220Sgibbs		mov	DINDIR,DFDAT;
230639220Sgibbs		mov	DINDIR,DFDAT;
230739220Sgibbs		mov	DINDIR,DFDAT;
230839220Sgibbs		mov	DINDIR,DFDAT;
230939220Sgibbs		mov	DINDIR,DFDAT;
231065942Sgibbsdfdat_in_2:
231139220Sgibbs		mov	DINDIR,DFDAT;
231239220Sgibbs		mov	DINDIR,DFDAT ret;
231339220Sgibbs	}
231419164Sgibbs
231565942Sgibbscopy_to_fifo_8:
231665942Sgibbs	mov	DFDAT,SINDIR;
231765942Sgibbs	mov	DFDAT,SINDIR;
231863457Sgibbscopy_to_fifo_6:
231963457Sgibbs	mov	DFDAT,SINDIR;
232063457Sgibbscopy_to_fifo_5:
232163457Sgibbs	mov	DFDAT,SINDIR;
232263457Sgibbscopy_to_fifo_4:
232363457Sgibbs	mov	DFDAT,SINDIR;
232463457Sgibbs	mov	DFDAT,SINDIR;
232563457Sgibbs	mov	DFDAT,SINDIR;
232663457Sgibbs	mov	DFDAT,SINDIR ret;
232739220Sgibbs
232813177Sgibbs/*
232919164Sgibbs * Wait for DMA from host memory to data FIFO to complete, then disable
233019164Sgibbs * DMA and wait for it to acknowledge that it's off.
233113177Sgibbs */
233219164Sgibbsdma_finish:
233323925Sgibbs	test	DFSTATUS,HDONE	jz dma_finish;
233474434Sgibbsdma_finish_nowait:
233522234Sgibbs	/* Turn off DMA */
233623925Sgibbs	and	DFCNTRL, ~HDMAEN;
233723925Sgibbs	test	DFCNTRL, HDMAEN jnz .;
233823925Sgibbs	ret;
23399928Sgibbs
234074094Sgibbs/*
234174094Sgibbs * Restore an SCB that failed to match an incoming reselection
234274094Sgibbs * to the correct/safe state.  If the SCB is for a disconnected
234374094Sgibbs * transaction, it must be returned to the disconnected list.
234474094Sgibbs * If it is not in the disconnected state, it must be free.
234574094Sgibbs */
234674094Sgibbscleanup_scb:
234774094Sgibbs	if ((ahc->flags & AHC_PAGESCBS) != 0) {
234874094Sgibbs		test	SCB_CONTROL,DISCONNECTED jnz add_scb_to_disc_list;
234974094Sgibbs	}
235023925Sgibbsadd_scb_to_free_list:
235139220Sgibbs	if ((ahc->flags & AHC_PAGESCBS) != 0) {
235295378SgibbsBEGIN_CRITICAL;
235339220Sgibbs		mov	SCB_NEXT, FREE_SCBH;
235457099Sgibbs		mvi	SCB_TAG, SCB_LIST_NULL;
235557099Sgibbs		mov	FREE_SCBH, SCBPTR ret;
235695378SgibbsEND_CRITICAL;
235757099Sgibbs	} else {
235857099Sgibbs		mvi	SCB_TAG, SCB_LIST_NULL ret;
235939220Sgibbs	}
23604568Sgibbs
236179874Sgibbsif ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
236279874Sgibbsset_hhaddr:
236379874Sgibbs	or	DSCOMMAND1, HADDLDSEL0;
236479874Sgibbs	and	HADDR, SG_HIGH_ADDR_BITS, SINDEX;
236579874Sgibbs	and	DSCOMMAND1, ~HADDLDSEL0 ret;
236679874Sgibbs}
236779874Sgibbs
236839220Sgibbsif ((ahc->flags & AHC_PAGESCBS) != 0) {
236919164Sgibbsget_free_or_disc_scb:
237095378SgibbsBEGIN_CRITICAL;
237123925Sgibbs	cmp	FREE_SCBH, SCB_LIST_NULL jne dequeue_free_scb;
237223925Sgibbs	cmp	DISCONNECTED_SCBH, SCB_LIST_NULL jne dequeue_disc_scb;
237319623Sgibbsreturn_error:
237468402Sgibbs	mvi	NO_FREE_SCB call set_seqint;
237523925Sgibbs	mvi	SINDEX, SCB_LIST_NULL	ret;
237619623Sgibbsdequeue_disc_scb:
237723925Sgibbs	mov	SCBPTR, DISCONNECTED_SCBH;
237868579Sgibbs	mov	DISCONNECTED_SCBH, SCB_NEXT;
237995378SgibbsEND_CRITICAL;
238023925Sgibbs	mvi	DMAPARAMS, FIFORESET;
238168579Sgibbs	mov	SCB_TAG	jmp dma_scb;
238295378SgibbsBEGIN_CRITICAL;
238319164Sgibbsdequeue_free_scb:
238423925Sgibbs	mov	SCBPTR, FREE_SCBH;
238523925Sgibbs	mov	FREE_SCBH, SCB_NEXT ret;
238695378SgibbsEND_CRITICAL;
23874568Sgibbs
238819164Sgibbsadd_scb_to_disc_list:
238913177Sgibbs/*
239019164Sgibbs * Link this SCB into the DISCONNECTED list.  This list holds the
239119164Sgibbs * candidates for paging out an SCB if one is needed for a new command.
239219164Sgibbs * Modifying the disconnected list is a critical(pause dissabled) section.
239313177Sgibbs */
239495378SgibbsBEGIN_CRITICAL;
239523925Sgibbs	mov	SCB_NEXT, DISCONNECTED_SCBH;
239639220Sgibbs	mov	DISCONNECTED_SCBH, SCBPTR ret;
239795378SgibbsEND_CRITICAL;
239865942Sgibbs}
239968402Sgibbsset_seqint:
240068402Sgibbs	mov	INTSTAT, SINDEX;
240168402Sgibbs	nop;
240263457Sgibbsreturn:
240363457Sgibbs	ret;
2404