Home | History | Annotate | Line # | Download | only in aic7xxx
aic7xxx.seq revision 1.11.6.1
      1  1.11.6.1   nathanw /*	$NetBSD: aic7xxx.seq,v 1.11.6.1 2001/06/21 20:04:10 nathanw Exp $	*/
      2       1.3   thorpej 
      3      1.11      fvdl /*
      4      1.11      fvdl  * Adaptec 274x/284x/294x device driver firmware for Linux and FreeBSD.
      5       1.2   mycroft  *
      6      1.11      fvdl  * Copyright (c) 1994-2000 Justin Gibbs.
      7      1.11      fvdl  * All rights reserved.
      8       1.2   mycroft  *
      9      1.11      fvdl  * Redistribution and use in source and binary forms, with or without
     10      1.11      fvdl  * modification, are permitted provided that the following conditions
     11      1.11      fvdl  * are met:
     12      1.11      fvdl  * 1. Redistributions of source code must retain the above copyright
     13      1.11      fvdl  *    notice, this list of conditions, and the following disclaimer,
     14      1.11      fvdl  *    without modification.
     15      1.11      fvdl  * 2. The name of the author may not be used to endorse or promote products
     16      1.11      fvdl  *    derived from this software without specific prior written permission.
     17       1.2   mycroft  *
     18      1.11      fvdl  * Alternatively, this software may be distributed under the terms of the
     19      1.11      fvdl  * the GNU Public License ("GPL").
     20       1.2   mycroft  *
     21      1.11      fvdl  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     22      1.11      fvdl  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23      1.11      fvdl  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24      1.11      fvdl  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
     25      1.11      fvdl  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26      1.11      fvdl  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27      1.11      fvdl  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28      1.11      fvdl  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29      1.11      fvdl  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30      1.11      fvdl  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31      1.11      fvdl  * SUCH DAMAGE.
     32       1.2   mycroft  *
     33      1.11      fvdl  * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.seq,v 1.94 2000/02/09 21:25:00 gibbs Exp $
     34      1.11      fvdl  */
     35       1.2   mycroft 
     36       1.2   mycroft /*
     37      1.11      fvdl  * #ifdef __NetBSD__
     38       1.2   mycroft  */
     39      1.11      fvdl #include <dev/microcode/aic7xxx/aic7xxx.reg>
     40      1.11      fvdl #include <dev/scsipi/scsi_message.h>
     41      1.11      fvdl /*
     42      1.11      fvdl  * Assembler can't handle ifdef.
     43      1.11      fvdl  *
     44      1.11      fvdl  * #else
     45      1.11      fvdl  * #include <dev/aic7xxx/aic7xxx.reg>
     46      1.11      fvdl  * #include <cam/scsi/scsi_message.h>
     47      1.11      fvdl  * #endif
     48      1.11      fvdl */
     49       1.2   mycroft 
     50      1.11      fvdl /*
     51      1.11      fvdl  * A few words on the waiting SCB list:
     52      1.11      fvdl  * After starting the selection hardware, we check for reconnecting targets
     53       1.2   mycroft  * as well as for our selection to complete just in case the reselection wins
     54       1.2   mycroft  * bus arbitration.  The problem with this is that we must keep track of the
     55       1.2   mycroft  * SCB that we've already pulled from the QINFIFO and started the selection
     56       1.2   mycroft  * on just in case the reselection wins so that we can retry the selection at
     57       1.2   mycroft  * a later time.  This problem cannot be resolved by holding a single entry
     58       1.2   mycroft  * in scratch ram since a reconnecting target can request sense and this will
     59       1.2   mycroft  * create yet another SCB waiting for selection.  The solution used here is to
     60       1.2   mycroft  * use byte 27 of the SCB as a psuedo-next pointer and to thread a list
     61      1.11      fvdl  * of SCBs that are awaiting selection.  Since 0-0xfe are valid SCB indexes,
     62      1.11      fvdl  * SCB_LIST_NULL is 0xff which is out of range.  An entry is also added to
     63      1.11      fvdl  * this list everytime a request sense occurs or after completing a non-tagged
     64      1.11      fvdl  * command for which a second SCB has been queued.  The sequencer will
     65      1.11      fvdl  * automatically consume the entries.
     66       1.2   mycroft  */
     67       1.2   mycroft 
     68       1.2   mycroft reset:
     69      1.11      fvdl 	clr	SCSISIGO;		/* De-assert BSY */
     70      1.11      fvdl 	mvi	MSG_OUT, MSG_NOOP;	/* No message to send */
     71      1.11      fvdl 	and	SXFRCTL1, ~BITBUCKET;
     72      1.11      fvdl 	/* Always allow reselection */
     73      1.11      fvdl 	and	SCSISEQ, ENSELI|ENRSELI|ENAUTOATNP, SCSISEQ_TEMPLATE;
     74      1.11      fvdl 	if ((ahc->features & AHC_CMD_CHAN) != 0) {
     75      1.11      fvdl 		/* Ensure that no DMA operations are in progress */
     76      1.11      fvdl 		clr	CCSGCTL;
     77      1.11      fvdl 		clr	CCSCBCTL;
     78      1.11      fvdl 	}
     79      1.11      fvdl 
     80       1.1   mycroft poll_for_work:
     81      1.11      fvdl 	call	clear_target_state;
     82      1.11      fvdl 	and	SXFRCTL0, ~SPIOEN;
     83      1.11      fvdl 	if ((ahc->features & AHC_QUEUE_REGS) == 0) {
     84      1.11      fvdl 		mov	A, QINPOS;
     85      1.11      fvdl 	}
     86      1.11      fvdl poll_for_work_loop:
     87      1.11      fvdl 	if ((ahc->features & AHC_QUEUE_REGS) == 0) {
     88      1.11      fvdl 		and	SEQCTL, ~PAUSEDIS;
     89      1.11      fvdl 	}
     90      1.11      fvdl 	test	SSTAT0, SELDO|SELDI	jnz selection;
     91      1.11      fvdl 	test	SCSISEQ, ENSELO	jnz poll_for_work;
     92      1.11      fvdl 	if ((ahc->features & AHC_TWIN) != 0) {
     93      1.11      fvdl 		/*
     94      1.11      fvdl 		 * Twin channel devices cannot handle things like SELTO
     95      1.11      fvdl 		 * interrupts on the "background" channel.  So, if we
     96      1.11      fvdl 		 * are selecting, keep polling the current channel util
     97      1.11      fvdl 		 * either a selection or reselection occurs.
     98      1.11      fvdl 		 */
     99      1.11      fvdl 		xor	SBLKCTL,SELBUSB;	/* Toggle to the other bus */
    100      1.11      fvdl 		test	SSTAT0, SELDO|SELDI	jnz selection;
    101      1.11      fvdl 		test	SCSISEQ, ENSELO	jnz poll_for_work;
    102      1.11      fvdl 		xor	SBLKCTL,SELBUSB;	/* Toggle back */
    103      1.11      fvdl 	}
    104      1.11      fvdl 	cmp	WAITING_SCBH,SCB_LIST_NULL jne start_waiting;
    105      1.11      fvdl test_queue:
    106      1.11      fvdl 	/* Has the driver posted any work for us? */
    107      1.11      fvdl 	if ((ahc->features & AHC_QUEUE_REGS) != 0) {
    108      1.11      fvdl 		test	QOFF_CTLSTA, SCB_AVAIL jz poll_for_work_loop;
    109      1.11      fvdl 		mov	NONE, SNSCB_QOFF;
    110      1.11      fvdl 		inc	QINPOS;
    111      1.11      fvdl 	} else {
    112      1.11      fvdl 		or	SEQCTL, PAUSEDIS;
    113      1.11      fvdl 		cmp	KERNEL_QINPOS, A je poll_for_work_loop;
    114      1.11      fvdl 		inc	QINPOS;
    115      1.11      fvdl 		and	SEQCTL, ~PAUSEDIS;
    116      1.11      fvdl 	}
    117       1.2   mycroft 
    118       1.2   mycroft /*
    119       1.2   mycroft  * We have at least one queued SCB now and we don't have any
    120      1.11      fvdl  * SCBs in the list of SCBs awaiting selection.  If we have
    121      1.11      fvdl  * any SCBs available for use, pull the tag from the QINFIFO
    122      1.11      fvdl  * and get to work on it.
    123      1.11      fvdl  */
    124      1.11      fvdl 	if ((ahc->flags & AHC_PAGESCBS) != 0) {
    125      1.11      fvdl 		mov	ALLZEROS	call	get_free_or_disc_scb;
    126      1.11      fvdl 	}
    127      1.11      fvdl 
    128      1.11      fvdl dequeue_scb:
    129      1.11      fvdl 	add	A, -1, QINPOS;
    130      1.11      fvdl 	mvi	QINFIFO_OFFSET call fetch_byte;
    131      1.11      fvdl 
    132      1.11      fvdl 	if ((ahc->flags & AHC_PAGESCBS) == 0) {
    133      1.11      fvdl 		/* In the non-paging case, the SCBID == hardware SCB index */
    134      1.11      fvdl 		mov	SCBPTR, RETURN_2;
    135      1.11      fvdl 	}
    136      1.11      fvdl dma_queued_scb:
    137      1.11      fvdl /*
    138      1.11      fvdl  * DMA the SCB from host ram into the current SCB location.
    139      1.11      fvdl  */
    140      1.11      fvdl 	mvi	DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
    141      1.11      fvdl 	mov	RETURN_2	 call dma_scb;
    142      1.11      fvdl 
    143      1.11      fvdl /*
    144      1.11      fvdl  * Preset the residual fields in case we never go through a data phase.
    145      1.11      fvdl  * This isn't done by the host so we can avoid a DMA to clear these
    146      1.11      fvdl  * fields for the normal case of I/O that completes without underrun
    147      1.11      fvdl  * or overrun conditions.
    148      1.11      fvdl  */
    149      1.11      fvdl 	if ((ahc->features & AHC_CMD_CHAN) != 0) {
    150      1.11      fvdl 		bmov	SCB_RESID_DCNT, SCB_DATACNT, 3;
    151      1.11      fvdl 	} else {
    152      1.11      fvdl 		mov	SCB_RESID_DCNT[0],SCB_DATACNT[0];
    153      1.11      fvdl 		mov	SCB_RESID_DCNT[1],SCB_DATACNT[1];
    154      1.11      fvdl 		mov	SCB_RESID_DCNT[2],SCB_DATACNT[2];
    155      1.11      fvdl 	}
    156      1.11      fvdl 	mov	SCB_RESID_SGCNT, SCB_SGCOUNT;
    157       1.1   mycroft 
    158       1.1   mycroft start_scb:
    159      1.11      fvdl 	/*
    160      1.11      fvdl 	 * Place us on the waiting list in case our selection
    161      1.11      fvdl 	 * doesn't win during bus arbitration.
    162      1.11      fvdl 	 */
    163      1.11      fvdl 	mov	SCB_NEXT,WAITING_SCBH;
    164      1.11      fvdl 	mov	WAITING_SCBH, SCBPTR;
    165      1.11      fvdl start_waiting:
    166      1.11      fvdl 	/*
    167      1.11      fvdl 	 * Pull the first entry off of the waiting SCB list.
    168      1.11      fvdl 	 */
    169      1.11      fvdl 	mov	SCBPTR, WAITING_SCBH;
    170      1.11      fvdl 	call	start_selection;
    171      1.11      fvdl 	jmp	poll_for_work;
    172       1.1   mycroft 
    173       1.2   mycroft start_selection:
    174      1.11      fvdl 	if ((ahc->features & AHC_TWIN) != 0) {
    175      1.11      fvdl 		and	SINDEX,~SELBUSB,SBLKCTL;/* Clear channel select bit */
    176      1.11      fvdl 		and	A,SELBUSB,SCB_TCL;	/* Get new channel bit */
    177      1.11      fvdl 		or	SINDEX,A;
    178      1.11      fvdl 		mov	SBLKCTL,SINDEX;		/* select channel */
    179      1.11      fvdl 	}
    180      1.11      fvdl initialize_scsiid:
    181      1.11      fvdl 	mov	SINDEX, SCSISEQ_TEMPLATE;
    182      1.11      fvdl 	if ((ahc->flags & AHC_TARGETMODE) != 0) {
    183      1.11      fvdl 		test	SCB_CONTROL, TARGET_SCB jz . + 4;
    184      1.11      fvdl 		if ((ahc->features & AHC_ULTRA2) != 0) {
    185      1.11      fvdl 			mov	SCSIID_ULTRA2, SCB_CMDPTR[2];
    186      1.11      fvdl 		} else {
    187      1.11      fvdl 			mov	SCSIID, SCB_CMDPTR[2];
    188      1.11      fvdl 		}
    189      1.11      fvdl 		or	SINDEX, TEMODE;
    190      1.11      fvdl 		jmp	initialize_scsiid_fini;
    191      1.11      fvdl 	}
    192      1.11      fvdl 	if ((ahc->features & AHC_ULTRA2) != 0) {
    193      1.11      fvdl 		and	A, TID, SCB_TCL;	/* Get target ID */
    194      1.11      fvdl 		and	SCSIID_ULTRA2, OID;	/* Clear old target */
    195      1.11      fvdl 		or	SCSIID_ULTRA2, A;
    196      1.11      fvdl 	} else {
    197      1.11      fvdl 		and	A, TID, SCB_TCL;	/* Get target ID */
    198      1.11      fvdl 		and	SCSIID, OID;		/* Clear old target */
    199      1.11      fvdl 		or	SCSIID, A;
    200      1.11      fvdl 	}
    201      1.11      fvdl initialize_scsiid_fini:
    202      1.11      fvdl 	mov	SCSISEQ, SINDEX ret;
    203      1.11      fvdl 
    204      1.11      fvdl /*
    205      1.11      fvdl  * Initialize transfer settings and clear the SCSI channel.
    206      1.11      fvdl  * SINDEX should contain any additional bit's the client wants
    207      1.11      fvdl  * set in SXFRCTL0.  We also assume that the current SCB is
    208      1.11      fvdl  * a valid SCB for the target we wish to talk to.
    209      1.11      fvdl  */
    210      1.11      fvdl initialize_channel:
    211      1.11      fvdl 	or	SXFRCTL0, CLRSTCNT|CLRCHN, SINDEX;
    212      1.11      fvdl set_transfer_settings:
    213      1.11      fvdl 	if ((ahc->features & AHC_ULTRA) != 0) {
    214      1.11      fvdl 		test	SCB_CONTROL, ULTRAENB jz . + 2;
    215      1.11      fvdl 		or	SXFRCTL0, FAST20;
    216      1.11      fvdl 	}
    217       1.2   mycroft /*
    218      1.11      fvdl  * Initialize SCSIRATE with the appropriate value for this target.
    219       1.2   mycroft  */
    220      1.11      fvdl 	if ((ahc->features & AHC_ULTRA2) != 0) {
    221      1.11      fvdl 		bmov	SCSIRATE, SCB_SCSIRATE, 2 ret;
    222      1.11      fvdl 	} else {
    223      1.11      fvdl 		mov	SCSIRATE, SCB_SCSIRATE ret;
    224      1.11      fvdl 	}
    225      1.11      fvdl 
    226      1.11      fvdl selection:
    227      1.11      fvdl 	test	SSTAT0,SELDO	jnz select_out;
    228      1.11      fvdl 	mvi	CLRSINT0, CLRSELDI;
    229      1.11      fvdl select_in:
    230      1.11      fvdl 	if ((ahc->flags & AHC_TARGETMODE) != 0) {
    231      1.11      fvdl 		if ((ahc->flags & AHC_INITIATORMODE) != 0) {
    232      1.11      fvdl 			test	SSTAT0, TARGET	jz initiator_reselect;
    233      1.11      fvdl 		}
    234      1.11      fvdl 
    235      1.11      fvdl 		/*
    236      1.11      fvdl 		 * We've just been selected.  Assert BSY and
    237      1.11      fvdl 		 * setup the phase for receiving messages
    238      1.11      fvdl 		 * from the target.
    239      1.11      fvdl 		 */
    240      1.11      fvdl 		mvi	SCSISIGO, P_MESGOUT|BSYO;
    241      1.11      fvdl 		mvi	CLRSINT1, CLRBUSFREE;
    242      1.11      fvdl 
    243      1.11      fvdl 		/*
    244      1.11      fvdl 		 * Setup the DMA for sending the identify and
    245      1.11      fvdl 		 * command information.
    246      1.11      fvdl 		 */
    247      1.11      fvdl 		or	SEQ_FLAGS, CMDPHASE_PENDING;
    248      1.11      fvdl 
    249      1.11      fvdl 		mov     A, TQINPOS;
    250      1.11      fvdl 		if ((ahc->features & AHC_CMD_CHAN) != 0) {
    251      1.11      fvdl 			mvi	DINDEX, CCHADDR;
    252      1.11      fvdl 			mvi	TMODE_CMDADDR call set_32byte_addr;
    253      1.11      fvdl 			mvi	CCSCBCTL, CCSCBRESET;
    254      1.11      fvdl 		} else {
    255      1.11      fvdl 			mvi	DINDEX, HADDR;
    256      1.11      fvdl 			mvi	TMODE_CMDADDR call set_32byte_addr;
    257      1.11      fvdl 			mvi	DFCNTRL, FIFORESET;
    258      1.11      fvdl 		}
    259      1.11      fvdl 
    260      1.11      fvdl 		/* Initiator that selected us */
    261      1.11      fvdl 		and	SAVED_TCL, SELID_MASK, SELID;
    262      1.11      fvdl 		if ((ahc->features & AHC_CMD_CHAN) != 0) {
    263      1.11      fvdl 			mov	CCSCBRAM, SAVED_TCL;
    264      1.11      fvdl 		} else {
    265      1.11      fvdl 			mov	DFDAT, SAVED_TCL;
    266      1.11      fvdl 		}
    267      1.11      fvdl 
    268      1.11      fvdl 		/* The Target ID we were selected at */
    269      1.11      fvdl 		if ((ahc->features & AHC_CMD_CHAN) != 0) {
    270      1.11      fvdl 			if ((ahc->features & AHC_MULTI_TID) != 0) {
    271      1.11      fvdl 				and	CCSCBRAM, OID, TARGIDIN;
    272      1.11      fvdl 			} else if ((ahc->features & AHC_ULTRA2) != 0) {
    273      1.11      fvdl 				and	CCSCBRAM, OID, SCSIID_ULTRA2;
    274      1.11      fvdl 			} else {
    275      1.11      fvdl 				and	CCSCBRAM, OID, SCSIID;
    276      1.11      fvdl 			}
    277      1.11      fvdl 		} else {
    278      1.11      fvdl 			if ((ahc->features & AHC_MULTI_TID) != 0) {
    279      1.11      fvdl 				and	DFDAT, OID, TARGIDIN;
    280      1.11      fvdl 			} else if ((ahc->features & AHC_ULTRA2) != 0) {
    281      1.11      fvdl 				and	DFDAT, OID, SCSIID_ULTRA2;
    282      1.11      fvdl 			} else {
    283      1.11      fvdl 				and	DFDAT, OID, SCSIID;
    284      1.11      fvdl 			}
    285      1.11      fvdl 		}
    286      1.11      fvdl 
    287      1.11      fvdl 		/* No tag yet */
    288      1.11      fvdl 		mvi	INITIATOR_TAG, SCB_LIST_NULL;
    289      1.11      fvdl 
    290      1.11      fvdl 		/*
    291      1.11      fvdl 		 * If ATN isn't asserted, the target isn't interested
    292      1.11      fvdl 		 * in talking to us.  Go directly to bus free.
    293      1.11      fvdl 		 */
    294      1.11      fvdl 		test	SCSISIGI, ATNI	jz	target_busfree;
    295      1.11      fvdl 
    296      1.11      fvdl 		/*
    297      1.11      fvdl 		 * Watch ATN closely now as we pull in messages from the
    298      1.11      fvdl 		 * initiator.  We follow the guidlines from section 6.5
    299      1.11      fvdl 		 * of the SCSI-2 spec for what messages are allowed when.
    300      1.11      fvdl 		 */
    301      1.11      fvdl 		call	target_inb;
    302      1.11      fvdl 
    303      1.11      fvdl 		/*
    304      1.11      fvdl 		 * Our first message must be one of IDENTIFY, ABORT, or
    305      1.11      fvdl 		 * BUS_DEVICE_RESET.
    306      1.11      fvdl 		 */
    307      1.11      fvdl 		/* XXX May need to be more lax here for older initiators... */
    308      1.11      fvdl 		test	DINDEX, MSG_IDENTIFYFLAG jz host_target_message_loop;
    309      1.11      fvdl 		/* Store for host */
    310      1.11      fvdl 		if ((ahc->features & AHC_CMD_CHAN) != 0) {
    311      1.11      fvdl 			mov	CCSCBRAM, DINDEX;
    312      1.11      fvdl 		} else {
    313      1.11      fvdl 			mov	DFDAT, DINDEX;
    314      1.11      fvdl 		}
    315      1.11      fvdl 
    316      1.11      fvdl 		/* Remember for disconnection decision */
    317      1.11      fvdl 		test	DINDEX, MSG_IDENTIFY_DISCFLAG jnz . + 2;
    318      1.11      fvdl 		/* XXX Honor per target settings too */
    319      1.11      fvdl 		or	SEQ_FLAGS, NO_DISCONNECT;
    320      1.11      fvdl 
    321      1.11      fvdl 		test	SCSISIGI, ATNI	jz	ident_messages_done;
    322      1.11      fvdl 		call	target_inb;
    323      1.11      fvdl 		/*
    324      1.11      fvdl 		 * If this is a tagged request, the tagged message must
    325      1.11      fvdl 		 * immediately follow the identify.  We test for a valid
    326      1.11      fvdl 		 * tag message by seeing if it is >= MSG_SIMPLE_Q_TAG and
    327      1.11      fvdl 		 * < MSG_IGN_WIDE_RESIDUE.
    328      1.11      fvdl 		 */
    329      1.11      fvdl 		add	A, -MSG_SIMPLE_Q_TAG, DINDEX;
    330      1.11      fvdl 		jnc	ident_messages_done;
    331      1.11      fvdl 		add	A, -MSG_IGN_WIDE_RESIDUE, DINDEX;
    332      1.11      fvdl 		jc	ident_messages_done;
    333      1.11      fvdl 		/* Store for host */
    334      1.11      fvdl 		if ((ahc->features & AHC_CMD_CHAN) != 0) {
    335      1.11      fvdl 			mov	CCSCBRAM, DINDEX;
    336      1.11      fvdl 		} else {
    337      1.11      fvdl 			mov	DFDAT, DINDEX;
    338      1.11      fvdl 		}
    339      1.11      fvdl 
    340      1.11      fvdl 		/*
    341      1.11      fvdl 		 * If the initiator doesn't feel like providing a tag number,
    342      1.11      fvdl 		 * we've got a failed selection and must transition to bus
    343      1.11      fvdl 		 * free.
    344      1.11      fvdl 		 */
    345      1.11      fvdl 		test	SCSISIGI, ATNI	jz	target_busfree;
    346      1.11      fvdl 
    347      1.11      fvdl 		/*
    348      1.11      fvdl 		 * Store the tag for the host.
    349      1.11      fvdl 		 */
    350      1.11      fvdl 		call	target_inb;
    351      1.11      fvdl 		if ((ahc->features & AHC_CMD_CHAN) != 0) {
    352      1.11      fvdl 			mov	CCSCBRAM, DINDEX;
    353      1.11      fvdl 		} else {
    354      1.11      fvdl 			mov	DFDAT, DINDEX;
    355      1.11      fvdl 		}
    356      1.11      fvdl 		mov	INITIATOR_TAG, DINDEX;
    357      1.11      fvdl 		jmp	ident_messages_done;
    358      1.11      fvdl 
    359      1.11      fvdl 		/*
    360      1.11      fvdl 		 * Pushed message loop to allow the kernel to
    361      1.11      fvdl 		 * run it's own target mode message state engine.
    362      1.11      fvdl 		 */
    363      1.11      fvdl host_target_message_loop:
    364      1.11      fvdl 		mvi	INTSTAT, HOST_MSG_LOOP;
    365      1.11      fvdl 		nop;
    366      1.11      fvdl 		cmp	RETURN_1, EXIT_MSG_LOOP	je target_ITloop;
    367      1.11      fvdl 		test	SSTAT0, SPIORDY jz .;
    368      1.11      fvdl 		jmp	host_target_message_loop;
    369      1.11      fvdl 
    370      1.11      fvdl ident_messages_done:
    371      1.11      fvdl 		/* If ring buffer is full, return busy or queue full */
    372      1.11      fvdl 		mov	A, KERNEL_TQINPOS;
    373      1.11      fvdl 		cmp	TQINPOS, A jne tqinfifo_has_space;
    374      1.11      fvdl 		mvi	P_STATUS|BSYO call change_phase;
    375      1.11      fvdl 		cmp	INITIATOR_TAG, SCB_LIST_NULL je . + 3;
    376      1.11      fvdl 		mvi	STATUS_QUEUE_FULL call target_outb;
    377      1.11      fvdl 		jmp	target_busfree_wait;
    378      1.11      fvdl 		mvi	STATUS_BUSY call target_outb;
    379      1.11      fvdl 		jmp	target_busfree_wait;
    380      1.11      fvdl tqinfifo_has_space:
    381      1.11      fvdl 		/* Terminate the ident list */
    382      1.11      fvdl 		if ((ahc->features & AHC_CMD_CHAN) != 0) {
    383      1.11      fvdl 			mvi	CCSCBRAM, SCB_LIST_NULL;
    384      1.11      fvdl 		} else {
    385      1.11      fvdl 			mvi	DFDAT, SCB_LIST_NULL;
    386      1.11      fvdl 		}
    387      1.11      fvdl 		or	SEQ_FLAGS, TARG_CMD_PENDING|IDENTIFY_SEEN;
    388      1.11      fvdl 		test	SCSISIGI, ATNI	jnz target_mesgout_pending_msg;
    389      1.11      fvdl 		jmp	target_ITloop;
    390      1.11      fvdl 
    391      1.11      fvdl /*
    392      1.11      fvdl  * We carefully toggle SPIOEN to allow us to return the
    393      1.11      fvdl  * message byte we receive so it can be checked prior to
    394      1.11      fvdl  * driving REQ on the bus for the next byte.
    395      1.11      fvdl  */
    396      1.11      fvdl target_inb:
    397      1.11      fvdl 		/*
    398      1.11      fvdl 		 * Drive REQ on the bus by enabling SCSI PIO.
    399      1.11      fvdl 		 */
    400      1.11      fvdl 		or	SXFRCTL0, SPIOEN;
    401      1.11      fvdl 		/* Wait for the byte */
    402      1.11      fvdl 		test	SSTAT0, SPIORDY jz .;
    403      1.11      fvdl 		/* Prevent our read from triggering another REQ */
    404      1.11      fvdl 		and	SXFRCTL0, ~SPIOEN;
    405      1.11      fvdl 		/* Save latched contents */
    406      1.11      fvdl 		mov	DINDEX, SCSIDATL ret;
    407      1.11      fvdl 	}
    408       1.2   mycroft 
    409      1.11      fvdl if ((ahc->flags & AHC_INITIATORMODE) != 0) {
    410       1.2   mycroft /*
    411       1.2   mycroft  * Reselection has been initiated by a target. Make a note that we've been
    412      1.11      fvdl  * reselected, but haven't seen an IDENTIFY message from the target yet.
    413       1.2   mycroft  */
    414      1.11      fvdl initiator_reselect:
    415      1.11      fvdl 	/* XXX test for and handle ONE BIT condition */
    416      1.11      fvdl 	and	SAVED_TCL, SELID_MASK, SELID;
    417      1.11      fvdl 	if ((ahc->features & AHC_TWIN) != 0) {
    418      1.11      fvdl 		test	SBLKCTL, SELBUSB	jz . + 2;
    419      1.11      fvdl 		or	SAVED_TCL, SELBUSB;
    420      1.11      fvdl 	}
    421      1.11      fvdl 	or	SXFRCTL0, SPIOEN|CLRSTCNT|CLRCHN;
    422      1.11      fvdl 	mvi	CLRSINT1,CLRBUSFREE;
    423      1.11      fvdl 	or	SIMODE1, ENBUSFREE;		/*
    424      1.11      fvdl 						 * We aren't expecting a
    425      1.11      fvdl 						 * bus free, so interrupt
    426      1.11      fvdl 						 * the kernel driver if it
    427      1.11      fvdl 						 * happens.
    428      1.11      fvdl 						 */
    429      1.11      fvdl 	jmp	ITloop;
    430      1.11      fvdl }
    431       1.1   mycroft 
    432       1.2   mycroft /*
    433      1.11      fvdl  * After the selection, remove this SCB from the "waiting SCB"
    434       1.2   mycroft  * list.  This is achieved by simply moving our "next" pointer into
    435       1.2   mycroft  * WAITING_SCBH.  Our next pointer will be set to null the next time this
    436       1.2   mycroft  * SCB is used, so don't bother with it now.
    437       1.2   mycroft  */
    438      1.11      fvdl select_out:
    439      1.11      fvdl 	/* Turn off the selection hardware */
    440      1.11      fvdl 	and	SCSISEQ, ENSELI|ENRSELI|ENAUTOATNP, SCSISEQ_TEMPLATE;
    441      1.11      fvdl 	mvi	CLRSINT0, CLRSELDO;
    442      1.11      fvdl 	mov	SCBPTR, WAITING_SCBH;
    443      1.11      fvdl 	mov	WAITING_SCBH,SCB_NEXT;
    444      1.11      fvdl 	mov	SAVED_TCL, SCB_TCL;
    445      1.11      fvdl 	if ((ahc->flags & AHC_TARGETMODE) != 0) {
    446      1.11      fvdl 		test	SSTAT0, TARGET	jz initiator_select;
    447      1.11      fvdl 
    448      1.11      fvdl 		/*
    449      1.11      fvdl 		 * We've just re-selected an initiator.
    450      1.11      fvdl 		 * Assert BSY and setup the phase for
    451      1.11      fvdl 		 * sending our identify messages.
    452      1.11      fvdl 		 */
    453      1.11      fvdl 		mvi	P_MESGIN|BSYO call change_phase;
    454      1.11      fvdl 		mvi	CLRSINT1,CLRBUSFREE;
    455      1.11      fvdl 
    456      1.11      fvdl 		/*
    457      1.11      fvdl 		 * Start out with a simple identify message.
    458      1.11      fvdl 		 */
    459      1.11      fvdl 		and	A, LID, SCB_TCL;
    460      1.11      fvdl 		or	A, MSG_IDENTIFYFLAG call target_outb;
    461      1.11      fvdl 
    462      1.11      fvdl 		/*
    463      1.11      fvdl 		 * If we are the result of a tagged command, send
    464      1.11      fvdl 		 * a simple Q tag and the tag id.
    465      1.11      fvdl 		 */
    466      1.11      fvdl 		test	SCB_CONTROL, TAG_ENB	jz . + 3;
    467      1.11      fvdl 		mvi	MSG_SIMPLE_Q_TAG call target_outb;
    468      1.11      fvdl 		mov	SCB_INITIATOR_TAG call target_outb;
    469      1.11      fvdl 		mov	INITIATOR_TAG, SCB_INITIATOR_TAG;
    470      1.11      fvdl target_synccmd:
    471      1.11      fvdl 		/*
    472      1.11      fvdl 		 * Now determine what phases the host wants us
    473      1.11      fvdl 		 * to go through.
    474      1.11      fvdl 		 */
    475      1.11      fvdl 		mov	SEQ_FLAGS, SCB_TARGET_PHASES;
    476      1.11      fvdl 
    477      1.11      fvdl 
    478      1.11      fvdl target_ITloop:
    479      1.11      fvdl 		/*
    480      1.11      fvdl 		 * Start honoring ATN signals now that
    481      1.11      fvdl 		 * we properly identified ourselves.
    482      1.11      fvdl 		 */
    483      1.11      fvdl 		test	SCSISIGI, ATNI			jnz target_mesgout;
    484      1.11      fvdl 		test	SEQ_FLAGS, CMDPHASE_PENDING	jnz target_cmdphase;
    485      1.11      fvdl 		test	SEQ_FLAGS, DPHASE_PENDING	jnz target_dphase;
    486      1.11      fvdl 		test	SEQ_FLAGS, SPHASE_PENDING	jnz target_sphase;
    487      1.11      fvdl 
    488      1.11      fvdl 		/*
    489      1.11      fvdl 		 * No more work to do.  Either disconnect or not depending
    490      1.11      fvdl 		 * on the state of NO_DISCONNECT.
    491      1.11      fvdl 		 */
    492      1.11      fvdl 		test	SEQ_FLAGS, NO_DISCONNECT jz target_disconnect;
    493      1.11      fvdl 		if ((ahc->flags & AHC_PAGESCBS) != 0) {
    494      1.11      fvdl 			mov	ALLZEROS	call	get_free_or_disc_scb;
    495      1.11      fvdl 		}
    496      1.11      fvdl 		mov	RETURN_1, ALLZEROS;
    497      1.11      fvdl 		call	complete_target_cmd;
    498      1.11      fvdl 		cmp	RETURN_1, CONT_MSG_LOOP jne .;
    499      1.11      fvdl 		mvi	DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
    500      1.11      fvdl 		mov	SCB_TAG	 call dma_scb;
    501      1.11      fvdl 		jmp	target_synccmd;
    502      1.11      fvdl 
    503      1.11      fvdl target_mesgout:
    504      1.11      fvdl 		mvi	SCSISIGO, P_MESGOUT|BSYO;
    505      1.11      fvdl 		call	target_inb;
    506      1.11      fvdl 		/* Local Processing goes here... */
    507      1.11      fvdl target_mesgout_pending_msg:
    508      1.11      fvdl 		jmp	host_target_message_loop;
    509      1.11      fvdl 
    510      1.11      fvdl target_disconnect:
    511      1.11      fvdl 		mvi	P_MESGIN|BSYO call change_phase;
    512      1.11      fvdl 		test	SEQ_FLAGS, DPHASE	jz . + 2;
    513      1.11      fvdl 		mvi	MSG_SAVEDATAPOINTER call target_outb;
    514      1.11      fvdl 		mvi	MSG_DISCONNECT call target_outb;
    515      1.11      fvdl 
    516      1.11      fvdl target_busfree_wait:
    517      1.11      fvdl 		/* Wait for preceeding I/O session to complete. */
    518      1.11      fvdl 		test	SCSISIGI, ACKI jnz .;
    519      1.11      fvdl target_busfree:
    520      1.11      fvdl 		clr	SCSISIGO;
    521      1.11      fvdl 		mvi	LASTPHASE, P_BUSFREE;
    522      1.11      fvdl 		call	complete_target_cmd;
    523      1.11      fvdl 		jmp	poll_for_work;
    524      1.11      fvdl 
    525      1.11      fvdl target_cmdphase:
    526      1.11      fvdl 		mvi	P_COMMAND|BSYO call change_phase;
    527      1.11      fvdl 		call	target_inb;
    528      1.11      fvdl 		mov	A, DINDEX;
    529      1.11      fvdl 		/* Store for host */
    530      1.11      fvdl 		if ((ahc->features & AHC_CMD_CHAN) != 0) {
    531      1.11      fvdl 			mov	CCSCBRAM, A;
    532      1.11      fvdl 		} else {
    533      1.11      fvdl 			mov	DFDAT, A;
    534      1.11      fvdl 		}
    535      1.11      fvdl 
    536      1.11      fvdl 		/*
    537      1.11      fvdl 		 * Determine the number of bytes to read
    538      1.11      fvdl 		 * based on the command group code via table lookup.
    539      1.11      fvdl 		 * We reuse the first 8 bytes of the TARG_SCSIRATE
    540      1.11      fvdl 		 * BIOS array for this table. Count is one less than
    541      1.11      fvdl 		 * the total for the command since we've already fetched
    542      1.11      fvdl 		 * the first byte.
    543      1.11      fvdl 		 */
    544      1.11      fvdl 		shr	A, CMD_GROUP_CODE_SHIFT;
    545      1.11      fvdl 		add	SINDEX, TARG_SCSIRATE, A;
    546      1.11      fvdl 		mov	A, SINDIR;
    547      1.11      fvdl 
    548      1.11      fvdl 		test	A, 0xFF jz command_phase_done;
    549      1.11      fvdl command_loop:
    550      1.11      fvdl 		or	SXFRCTL0, SPIOEN;
    551      1.11      fvdl 		test	SSTAT0, SPIORDY jz .;
    552      1.11      fvdl 		cmp	A, 1 jne . + 2;
    553      1.11      fvdl 		and	SXFRCTL0, ~SPIOEN;	/* Last Byte */
    554      1.11      fvdl 		if ((ahc->features & AHC_CMD_CHAN) != 0) {
    555      1.11      fvdl 			mov	CCSCBRAM, SCSIDATL;
    556      1.11      fvdl 		} else {
    557      1.11      fvdl 			mov	DFDAT, SCSIDATL;
    558      1.11      fvdl 		}
    559      1.11      fvdl 		dec	A;
    560      1.11      fvdl 		test	A, 0xFF jnz command_loop;
    561      1.11      fvdl 
    562      1.11      fvdl command_phase_done:
    563      1.11      fvdl 		and	SEQ_FLAGS, ~CMDPHASE_PENDING;
    564      1.11      fvdl 		jmp	target_ITloop;
    565      1.11      fvdl 
    566      1.11      fvdl target_dphase:
    567      1.11      fvdl 		/*
    568      1.11      fvdl 		 * Data direction flags are from the
    569      1.11      fvdl 		 * perspective of the initiator.
    570      1.11      fvdl 		 */
    571      1.11      fvdl 		test	SCB_TARGET_PHASES[1], TARGET_DATA_IN jz . + 4;
    572      1.11      fvdl 		mvi	LASTPHASE, P_DATAOUT;
    573      1.11      fvdl 		mvi	P_DATAIN|BSYO call change_phase;
    574      1.11      fvdl 		jmp	. + 3;
    575      1.11      fvdl 		mvi	LASTPHASE, P_DATAIN;
    576      1.11      fvdl 		mvi	P_DATAOUT|BSYO call change_phase;
    577      1.11      fvdl 		mov	ALLZEROS call initialize_channel;
    578      1.11      fvdl 		jmp	p_data;
    579      1.11      fvdl 
    580      1.11      fvdl target_sphase:
    581      1.11      fvdl 		mvi	P_STATUS|BSYO call change_phase;
    582      1.11      fvdl 		mvi	LASTPHASE, P_STATUS;
    583      1.11      fvdl 		mov	SCB_TARGET_STATUS call target_outb;
    584      1.11      fvdl 		/* XXX Watch for ATN or parity errors??? */
    585      1.11      fvdl 		mvi	SCSISIGO, P_MESGIN|BSYO;
    586      1.11      fvdl 		/* MSG_CMDCMPLT is 0, but we can't do an immediate of 0 */
    587      1.11      fvdl 		mov	ALLZEROS call target_outb;
    588      1.11      fvdl 		jmp	target_busfree_wait;
    589      1.11      fvdl 
    590      1.11      fvdl complete_target_cmd:
    591      1.11      fvdl 		test	SEQ_FLAGS, TARG_CMD_PENDING	jnz . + 2;
    592      1.11      fvdl 		mov	SCB_TAG jmp complete_post;
    593      1.11      fvdl 		if ((ahc->features & AHC_CMD_CHAN) != 0) {
    594      1.11      fvdl 			/* Set the valid byte */
    595      1.11      fvdl 			mvi	CCSCBADDR, 24;
    596      1.11      fvdl 			mov	CCSCBRAM, ALLONES;
    597      1.11      fvdl 			mvi	CCHCNT, 28;
    598      1.11      fvdl 			or	CCSCBCTL, CCSCBEN|CCSCBRESET;
    599      1.11      fvdl 			test	CCSCBCTL, CCSCBDONE jz .;
    600      1.11      fvdl 			clr	CCSCBCTL;
    601      1.11      fvdl 		} else {
    602      1.11      fvdl 			/* Set the valid byte */
    603      1.11      fvdl 			or	DFCNTRL, FIFORESET;
    604      1.11      fvdl 			mvi	DFWADDR, 3; /* Third 64bit word or byte 24 */
    605      1.11      fvdl 			mov	DFDAT, ALLONES;
    606      1.11      fvdl 			mvi	HCNT[0], 28;
    607      1.11      fvdl 			clr	HCNT[1];
    608      1.11      fvdl 			clr	HCNT[2];
    609      1.11      fvdl 			or	DFCNTRL, HDMAEN|FIFOFLUSH;
    610      1.11      fvdl 			call	dma_finish;
    611      1.11      fvdl 		}
    612      1.11      fvdl 		inc	TQINPOS;
    613      1.11      fvdl 		mvi	INTSTAT,CMDCMPLT ret;
    614      1.11      fvdl 	}
    615      1.11      fvdl 
    616      1.11      fvdl if ((ahc->flags & AHC_INITIATORMODE) != 0) {
    617      1.11      fvdl initiator_select:
    618      1.11      fvdl 	mvi	SPIOEN call	initialize_channel;
    619      1.11      fvdl 
    620      1.11      fvdl 	/*
    621      1.11      fvdl 	 * We aren't expecting a bus free, so interrupt
    622      1.11      fvdl 	 * the kernel driver if it happens.
    623      1.11      fvdl 	 */
    624      1.11      fvdl 	mvi	CLRSINT1,CLRBUSFREE;
    625      1.11      fvdl 	or	SIMODE1, ENBUSFREE;
    626      1.11      fvdl 
    627      1.11      fvdl 	/*
    628      1.11      fvdl 	 * As soon as we get a successful selection, the target
    629      1.11      fvdl 	 * should go into the message out phase since we have ATN
    630      1.11      fvdl 	 * asserted.
    631      1.11      fvdl 	 */
    632      1.11      fvdl 	mvi	MSG_OUT, MSG_IDENTIFYFLAG;
    633      1.11      fvdl 	or	SEQ_FLAGS, IDENTIFY_SEEN;
    634       1.2   mycroft 
    635      1.11      fvdl 	/*
    636      1.11      fvdl 	 * Main loop for information transfer phases.  Wait for the
    637      1.11      fvdl 	 * target to assert REQ before checking MSG, C/D and I/O for
    638      1.11      fvdl 	 * the bus phase.
    639      1.11      fvdl 	 */
    640       1.1   mycroft ITloop:
    641      1.11      fvdl 	call	phase_lock;
    642      1.11      fvdl 
    643      1.11      fvdl 	mov	A, LASTPHASE;
    644      1.11      fvdl 
    645      1.11      fvdl 	test	A, ~P_DATAIN	jz p_data;
    646      1.11      fvdl 	cmp	A,P_COMMAND	je p_command;
    647      1.11      fvdl 	cmp	A,P_MESGOUT	je p_mesgout;
    648      1.11      fvdl 	cmp	A,P_STATUS	je p_status;
    649      1.11      fvdl 	cmp	A,P_MESGIN	je p_mesgin;
    650      1.11      fvdl 
    651      1.11      fvdl 	mvi	INTSTAT,BAD_PHASE;
    652      1.11      fvdl 	jmp	ITloop;			/* Try reading the bus again. */
    653      1.11      fvdl 
    654      1.11      fvdl await_busfree:
    655      1.11      fvdl 	and	SIMODE1, ~ENBUSFREE;
    656      1.11      fvdl 	mov	NONE, SCSIDATL;		/* Ack the last byte */
    657      1.11      fvdl 	and	SXFRCTL0, ~SPIOEN;
    658      1.11      fvdl 	test	SSTAT1,REQINIT|BUSFREE	jz .;
    659      1.11      fvdl 	test	SSTAT1, BUSFREE jnz poll_for_work;
    660      1.11      fvdl 	mvi	INTSTAT, BAD_PHASE;
    661      1.11      fvdl }
    662      1.11      fvdl 
    663      1.11      fvdl clear_target_state:
    664      1.11      fvdl 	/*
    665      1.11      fvdl 	 * We assume that the kernel driver may reset us
    666      1.11      fvdl 	 * at any time, even in the middle of a DMA, so
    667      1.11      fvdl 	 * clear DFCNTRL too.
    668      1.11      fvdl 	 */
    669      1.11      fvdl 	clr	DFCNTRL;
    670       1.1   mycroft 
    671      1.11      fvdl 	/*
    672      1.11      fvdl 	 * We don't know the target we will connect to,
    673      1.11      fvdl 	 * so default to narrow transfers to avoid
    674      1.11      fvdl 	 * parity problems.
    675      1.11      fvdl 	 */
    676      1.11      fvdl 	if ((ahc->features & AHC_ULTRA2) != 0) {
    677      1.11      fvdl 		bmov	SCSIRATE, ALLZEROS, 2;
    678      1.11      fvdl 	} else {
    679      1.11      fvdl 		clr	SCSIRATE;
    680      1.11      fvdl 		and	SXFRCTL0, ~(FAST20);
    681      1.11      fvdl 	}
    682      1.11      fvdl 	mvi	LASTPHASE, P_BUSFREE;
    683      1.11      fvdl 	/* clear target specific flags */
    684      1.11      fvdl 	clr	SEQ_FLAGS ret;
    685       1.2   mycroft 
    686       1.2   mycroft /*
    687       1.2   mycroft  * If we re-enter the data phase after going through another phase, the
    688       1.2   mycroft  * STCNT may have been cleared, so restore it from the residual field.
    689       1.2   mycroft  */
    690       1.2   mycroft data_phase_reinit:
    691      1.11      fvdl 	if ((ahc->features & AHC_ULTRA2) != 0) {
    692      1.11      fvdl 		/*
    693      1.11      fvdl 		 * The preload circuitry requires us to
    694      1.11      fvdl 		 * reload the address too, so pull it from
    695      1.11      fvdl 		 * the shaddow address.
    696      1.11      fvdl 		 */
    697      1.11      fvdl 		bmov	HADDR, SHADDR, 4;
    698      1.11      fvdl 		bmov	HCNT, SCB_RESID_DCNT, 3;
    699      1.11      fvdl 	} else if ((ahc->features & AHC_CMD_CHAN) != 0) {
    700      1.11      fvdl 		bmov	STCNT, SCB_RESID_DCNT, 3;
    701      1.11      fvdl 	} else {
    702      1.11      fvdl 		mvi	DINDEX, STCNT;
    703      1.11      fvdl 		mvi	SCB_RESID_DCNT	call bcopy_3;
    704      1.11      fvdl 	}
    705      1.11      fvdl 	and	DATA_COUNT_ODD, 0x1, SCB_RESID_DCNT[0];
    706      1.11      fvdl 	jmp	data_phase_loop;
    707      1.11      fvdl 
    708      1.11      fvdl p_data:
    709      1.11      fvdl 	if ((ahc->features & AHC_ULTRA2) != 0) {
    710      1.11      fvdl 		mvi	DMAPARAMS, PRELOADEN|SCSIEN|HDMAEN;
    711      1.11      fvdl 	} else {
    712      1.11      fvdl 		mvi	DMAPARAMS, WIDEODD|SCSIEN|SDMAEN|HDMAEN|FIFORESET;
    713      1.11      fvdl 	}
    714      1.11      fvdl 	test	LASTPHASE, IOI jnz . + 2;
    715      1.11      fvdl 	or	DMAPARAMS, DIRECTION;
    716      1.11      fvdl 	call	assert;			/*
    717      1.11      fvdl 					 * Ensure entering a data
    718      1.11      fvdl 					 * phase is okay - seen identify, etc.
    719       1.2   mycroft 					 */
    720      1.11      fvdl 	if ((ahc->features & AHC_CMD_CHAN) != 0) {
    721      1.11      fvdl 		mvi	CCSGADDR, CCSGADDR_MAX;
    722      1.11      fvdl 	}
    723      1.11      fvdl 	test	SEQ_FLAGS, DPHASE	jnz data_phase_reinit;
    724       1.1   mycroft 
    725      1.11      fvdl 	/* We have seen a data phase */
    726      1.11      fvdl 	or	SEQ_FLAGS, DPHASE;
    727      1.11      fvdl 
    728      1.11      fvdl 	/*
    729      1.11      fvdl 	 * Initialize the DMA address and counter from the SCB.
    730      1.11      fvdl 	 * Also set SG_COUNT and SG_NEXT in memory since we cannot
    731      1.11      fvdl 	 * modify the values in the SCB itself until we see a
    732      1.11      fvdl 	 * save data pointers message.
    733      1.11      fvdl 	 */
    734      1.11      fvdl 	if ((ahc->features & AHC_CMD_CHAN) != 0) {
    735      1.11      fvdl 		bmov	HADDR, SCB_DATAPTR, 7;
    736      1.11      fvdl 	} else {
    737      1.11      fvdl 		mvi	DINDEX, HADDR;
    738      1.11      fvdl 		mvi	SCB_DATAPTR	call bcopy_7;
    739      1.11      fvdl 	}
    740      1.11      fvdl 	and	DATA_COUNT_ODD, 0x1, SCB_DATACNT[0];
    741      1.11      fvdl 
    742      1.11      fvdl 	if ((ahc->features & AHC_ULTRA2) == 0) {
    743      1.11      fvdl 		if ((ahc->features & AHC_CMD_CHAN) != 0) {
    744      1.11      fvdl 			bmov	STCNT, HCNT, 3;
    745      1.11      fvdl 		} else {
    746      1.11      fvdl 			call	set_stcnt_from_hcnt;
    747      1.11      fvdl 		}
    748      1.11      fvdl 	}
    749      1.11      fvdl 
    750      1.11      fvdl 	if ((ahc->features & AHC_CMD_CHAN) != 0) {
    751      1.11      fvdl 		bmov	SG_COUNT, SCB_SGCOUNT, 5;
    752      1.11      fvdl 	} else {
    753      1.11      fvdl 		mvi	DINDEX, SG_COUNT;
    754      1.11      fvdl 		mvi	SCB_SGCOUNT	call bcopy_5;
    755      1.11      fvdl 	}
    756       1.1   mycroft 
    757       1.2   mycroft data_phase_loop:
    758       1.4  explorer /* Guard against overruns */
    759      1.11      fvdl 	test	SG_COUNT, 0xff jnz data_phase_inbounds;
    760       1.4  explorer /*
    761       1.4  explorer  * Turn on 'Bit Bucket' mode, set the transfer count to
    762       1.4  explorer  * 16meg and let the target run until it changes phase.
    763       1.4  explorer  * When the transfer completes, notify the host that we
    764       1.4  explorer  * had an overrun.
    765       1.4  explorer  */
    766      1.11      fvdl 	or	SXFRCTL1,BITBUCKET;
    767      1.11      fvdl 	and	DMAPARAMS, ~(HDMAEN|SDMAEN);
    768      1.11      fvdl 	if ((ahc->features & AHC_ULTRA2) != 0) {
    769      1.11      fvdl 		bmov	HCNT, ALLONES, 3;
    770      1.11      fvdl 	} else if ((ahc->features & AHC_CMD_CHAN) != 0) {
    771      1.11      fvdl 		bmov	STCNT, ALLONES, 3;
    772      1.11      fvdl 	} else {
    773      1.11      fvdl 		mvi	STCNT[0], 0xFF;
    774      1.11      fvdl 		mvi	STCNT[1], 0xFF;
    775      1.11      fvdl 		mvi	STCNT[2], 0xFF;
    776      1.11      fvdl 	}
    777       1.4  explorer data_phase_inbounds:
    778      1.11      fvdl /* If we are the last SG block, tell the hardware. */
    779      1.11      fvdl 	cmp	SG_COUNT,0x01 jne data_phase_wideodd;
    780      1.11      fvdl 	if ((ahc->features & AHC_ULTRA2) != 0) {
    781      1.11      fvdl 		or	SG_CACHEPTR, LAST_SEG;
    782      1.11      fvdl 	} else {
    783      1.11      fvdl 		if ((ahc->flags & AHC_TARGETMODE) != 0) {
    784      1.11      fvdl 			test	SSTAT0, TARGET jz . + 2;
    785      1.11      fvdl 			test	DMAPARAMS, DIRECTION jz data_phase_wideodd;
    786      1.11      fvdl 		}
    787      1.11      fvdl 		and	DMAPARAMS, ~WIDEODD;
    788      1.11      fvdl 	}
    789       1.2   mycroft data_phase_wideodd:
    790      1.11      fvdl 	if ((ahc->features & AHC_ULTRA2) != 0) {
    791      1.11      fvdl 		mov	SINDEX, ALLONES;
    792      1.11      fvdl 		mov	DFCNTRL, DMAPARAMS;
    793      1.11      fvdl 		test	SSTAT0, SDONE jnz .;/* Wait for preload to complete */
    794      1.11      fvdl data_phase_dma_loop:
    795      1.11      fvdl 		test	SSTAT0,	SDONE jnz data_phase_dma_done;
    796      1.11      fvdl 		test	SSTAT1,PHASEMIS	jz data_phase_dma_loop;	/* ie. underrun */
    797      1.11      fvdl 	} else {
    798      1.11      fvdl 		mov	DMAPARAMS  call dma;
    799      1.11      fvdl 	}
    800       1.2   mycroft 
    801      1.11      fvdl data_phase_dma_done:
    802       1.4  explorer /* Go tell the host about any overruns */
    803      1.11      fvdl 	test	SXFRCTL1,BITBUCKET jnz data_phase_overrun;
    804       1.4  explorer 
    805      1.11      fvdl /* See if we completed this segment */
    806      1.11      fvdl 	test	STCNT[0], 0xff	jnz data_phase_finish;
    807      1.11      fvdl 	test	STCNT[1], 0xff	jnz data_phase_finish;
    808      1.11      fvdl 	test	STCNT[2], 0xff	jnz data_phase_finish;
    809       1.2   mycroft 
    810       1.2   mycroft /*
    811       1.2   mycroft  * Advance the scatter-gather pointers if needed
    812       1.2   mycroft  */
    813       1.2   mycroft sg_advance:
    814      1.11      fvdl 	dec	SG_COUNT;	/* one less segment to go */
    815       1.2   mycroft 
    816      1.11      fvdl 	test	SG_COUNT, 0xff	jz data_phase_finish; /* Are we done? */
    817       1.2   mycroft /*
    818       1.2   mycroft  * Load a struct scatter and set up the data address and length.
    819       1.2   mycroft  * If the working value of the SG count is nonzero, then
    820       1.2   mycroft  * we need to load a new set of values.
    821       1.2   mycroft  *
    822       1.2   mycroft  * This, like all DMA's, assumes little-endian host data storage.
    823       1.2   mycroft  */
    824       1.2   mycroft sg_load:
    825      1.11      fvdl 	if ((ahc->features & AHC_CMD_CHAN) != 0) {
    826      1.11      fvdl 		/*
    827      1.11      fvdl 		 * Do we have any prefetch left???
    828      1.11      fvdl 		 */
    829      1.11      fvdl 		cmp	CCSGADDR, CCSGADDR_MAX jne prefetched_segs_avail;
    830      1.11      fvdl 
    831      1.11      fvdl 		/*
    832      1.11      fvdl 		 * Fetch MIN(CCSGADDR_MAX, (SG_COUNT * 8)) bytes.
    833      1.11      fvdl 		 */
    834      1.11      fvdl 		add	A, -(CCSGRAM_MAXSEGS + 1), SG_COUNT;
    835      1.11      fvdl 		mvi	A, CCSGADDR_MAX;
    836      1.11      fvdl 		jc	. + 2;
    837      1.11      fvdl 		shl	A, 3, SG_COUNT;
    838      1.11      fvdl 		mov	CCHCNT, A;
    839      1.11      fvdl 		bmov	CCHADDR, SG_NEXT, 4;
    840      1.11      fvdl 		mvi	CCSGCTL, CCSGEN|CCSGRESET;
    841      1.11      fvdl 		test	CCSGCTL, CCSGDONE jz .;
    842      1.11      fvdl 		and	CCSGCTL, ~CCSGEN;
    843      1.11      fvdl 		test	CCSGCTL, CCSGEN jnz .;
    844      1.11      fvdl 		mvi	CCSGCTL, CCSGRESET;
    845      1.11      fvdl prefetched_segs_avail:
    846      1.11      fvdl 		bmov 	HADDR, CCSGRAM, 8;
    847      1.11      fvdl 	} else {
    848      1.11      fvdl 		mvi	DINDEX, HADDR;
    849      1.11      fvdl 		mvi	SG_NEXT	call bcopy_4;
    850      1.11      fvdl 
    851      1.11      fvdl 		mvi	HCNT[0],SG_SIZEOF;
    852      1.11      fvdl 		clr	HCNT[1];
    853      1.11      fvdl 		clr	HCNT[2];
    854      1.11      fvdl 
    855      1.11      fvdl 		or	DFCNTRL, HDMAEN|DIRECTION|FIFORESET;
    856      1.11      fvdl 
    857      1.11      fvdl 		call	dma_finish;
    858      1.11      fvdl 
    859      1.11      fvdl 		/*
    860      1.11      fvdl 		 * Copy data from FIFO into SCB data pointer and data count.
    861      1.11      fvdl 		 * This assumes that the SG segments are of the form:
    862      1.11      fvdl 		 * struct ahc_dma_seg {
    863      1.11      fvdl 		 *	u_int32_t	addr;	four bytes, little-endian order
    864      1.11      fvdl 		 *	u_int32_t	len;	four bytes, little endian order
    865      1.11      fvdl 		 * };
    866      1.11      fvdl 		 */
    867      1.11      fvdl 		mvi	HADDR	call dfdat_in_7;
    868      1.11      fvdl 	}
    869      1.11      fvdl 
    870      1.11      fvdl 	/* Track odd'ness */
    871      1.11      fvdl 	test	HCNT[0], 0x1 jz . + 2;
    872      1.11      fvdl 	xor	DATA_COUNT_ODD, 0x1;
    873      1.11      fvdl 
    874      1.11      fvdl 	if ((ahc->features & AHC_ULTRA2) == 0) {
    875      1.11      fvdl 		/* Load STCNT as well.  It is a mirror of HCNT */
    876      1.11      fvdl 		if ((ahc->features & AHC_CMD_CHAN) != 0) {
    877      1.11      fvdl 			bmov	STCNT, HCNT, 3;
    878      1.11      fvdl 		} else {
    879      1.11      fvdl 			call	set_stcnt_from_hcnt;
    880      1.11      fvdl 		}
    881      1.11      fvdl 	}
    882      1.11      fvdl 
    883      1.11      fvdl /* Advance the SG pointer */
    884      1.11      fvdl 	clr	A;			/* add sizeof(struct scatter) */
    885      1.11      fvdl 	add	SG_NEXT[0],SG_SIZEOF;
    886      1.11      fvdl 	adc	SG_NEXT[1],A;
    887      1.11      fvdl 
    888      1.11      fvdl 	if ((ahc->flags & AHC_TARGETMODE) != 0) {
    889      1.11      fvdl 		test	SSTAT0, TARGET jnz data_phase_loop;
    890      1.11      fvdl 	}
    891      1.11      fvdl 	test	SSTAT1, REQINIT jz .;
    892      1.11      fvdl 	test	SSTAT1,PHASEMIS	jz data_phase_loop;
    893      1.11      fvdl 
    894      1.11      fvdl 	/* Ensure the last seg is visable at the shaddow layer */
    895      1.11      fvdl 	if ((ahc->features & AHC_ULTRA2) != 0) {
    896      1.11      fvdl 		mov	DFCNTRL, DMAPARAMS;
    897      1.11      fvdl 		test	SSTAT0, SDONE jnz .;/* Wait for preload to complete */
    898      1.11      fvdl 	}
    899       1.2   mycroft 
    900       1.2   mycroft data_phase_finish:
    901      1.11      fvdl 	if ((ahc->features & AHC_ULTRA2) != 0) {
    902      1.11      fvdl 		call	ultra2_dmafinish;
    903      1.11      fvdl 	}
    904       1.2   mycroft /*
    905       1.2   mycroft  * After a DMA finishes, save the SG and STCNT residuals back into the SCB
    906       1.2   mycroft  * We use STCNT instead of HCNT, since it's a reflection of how many bytes
    907       1.2   mycroft  * were transferred on the SCSI (as opposed to the host) bus.
    908       1.2   mycroft  */
    909      1.11      fvdl 	if ((ahc->features & AHC_CMD_CHAN) != 0) {
    910      1.11      fvdl 		bmov	SCB_RESID_DCNT, STCNT, 3;
    911      1.11      fvdl 	} else {
    912      1.11      fvdl 		mov	SCB_RESID_DCNT[0],STCNT[0];
    913      1.11      fvdl 		mov	SCB_RESID_DCNT[1],STCNT[1];
    914      1.11      fvdl 		mov	SCB_RESID_DCNT[2],STCNT[2];
    915      1.11      fvdl 	}
    916      1.11      fvdl 	mov	SCB_RESID_SGCNT, SG_COUNT;
    917      1.11      fvdl 
    918      1.11      fvdl 	if ((ahc->features & AHC_ULTRA2) != 0) {
    919      1.11      fvdl 		or	SXFRCTL0, CLRSTCNT|CLRCHN;
    920      1.11      fvdl 	}
    921      1.11      fvdl 
    922      1.11      fvdl 	if ((ahc->flags & AHC_TARGETMODE) != 0) {
    923      1.11      fvdl 		test	SEQ_FLAGS, DPHASE_PENDING jz ITloop;
    924      1.11      fvdl 		and	SEQ_FLAGS, ~DPHASE_PENDING;
    925      1.11      fvdl 		/*
    926      1.11      fvdl 		 * For data-in phases, wait for any pending acks from the
    927      1.11      fvdl 		 * initiator before changing phase.
    928      1.11      fvdl 		 */
    929      1.11      fvdl 		test	DFCNTRL, DIRECTION jz target_ITloop;
    930      1.11      fvdl 		test	SSTAT1, REQINIT	jnz .;
    931      1.11      fvdl 		jmp	target_ITloop;
    932      1.11      fvdl 	}
    933      1.11      fvdl 	jmp	ITloop;
    934       1.1   mycroft 
    935       1.4  explorer data_phase_overrun:
    936      1.11      fvdl 	if ((ahc->features & AHC_ULTRA2) != 0) {
    937      1.11      fvdl 		call	ultra2_dmafinish;
    938      1.11      fvdl 		or	SXFRCTL0, CLRSTCNT|CLRCHN;
    939      1.11      fvdl 	}
    940       1.4  explorer /*
    941       1.4  explorer  * Turn off BITBUCKET mode and notify the host
    942       1.4  explorer  */
    943      1.11      fvdl 	and	SXFRCTL1, ~BITBUCKET;
    944      1.11      fvdl 	mvi	INTSTAT,DATA_OVERRUN;
    945      1.11      fvdl 	jmp	ITloop;
    946      1.11      fvdl 
    947      1.11      fvdl ultra2_dmafinish:
    948      1.11      fvdl 	if ((ahc->features & AHC_ULTRA2) != 0) {
    949      1.11      fvdl 		test	DFCNTRL, DIRECTION jnz ultra2_dmafifoempty;
    950      1.11      fvdl 		and	DFCNTRL, ~SCSIEN;
    951      1.11      fvdl 		test	DFCNTRL, SCSIEN jnz .;
    952      1.11      fvdl ultra2_dmafifoflush:
    953      1.11      fvdl 		or	DFCNTRL, FIFOFLUSH;
    954      1.11      fvdl 		/*
    955      1.11      fvdl 		 * The FIFOEMP status bit on the Ultra2 class
    956      1.11      fvdl 		 * of controllers seems to be a bit flaky.
    957      1.11      fvdl 		 * It appears that if the FIFO is full and the
    958      1.11      fvdl 		 * transfer ends with some data in the REQ/ACK
    959      1.11      fvdl 		 * FIFO, FIFOEMP will fall temporarily
    960      1.11      fvdl 		 * as the data is transferred to the PCI bus.
    961      1.11      fvdl 		 * This glitch lasts for fewer than 5 clock cycles,
    962      1.11      fvdl 		 * so we work around the problem by ensuring the
    963      1.11      fvdl 		 * status bit stays false through a full glitch
    964      1.11      fvdl 		 * window.
    965      1.11      fvdl 		 */
    966      1.11      fvdl 		test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
    967      1.11      fvdl 		test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
    968      1.11      fvdl 		test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
    969      1.11      fvdl 		test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
    970      1.11      fvdl 		test	DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
    971      1.11      fvdl 
    972      1.11      fvdl ultra2_dmafifoempty:
    973      1.11      fvdl 		/* Don't clobber an inprogress host data transfer */
    974      1.11      fvdl 		test	DFSTATUS, MREQPEND	jnz ultra2_dmafifoempty;
    975      1.11      fvdl 
    976      1.11      fvdl ultra2_dmahalt:
    977      1.11      fvdl 		and     DFCNTRL, ~(SCSIEN|HDMAEN);
    978      1.11      fvdl 		test	DFCNTRL, HDMAEN jnz .;
    979      1.11      fvdl 		ret;
    980      1.11      fvdl 	}
    981       1.4  explorer 
    982      1.11      fvdl if ((ahc->flags & AHC_INITIATORMODE) != 0) {
    983       1.2   mycroft /*
    984       1.2   mycroft  * Command phase.  Set up the DMA registers and let 'er rip.
    985       1.2   mycroft  */
    986       1.1   mycroft p_command:
    987      1.11      fvdl 	call	assert;
    988       1.1   mycroft 
    989      1.11      fvdl 	if ((ahc->features & AHC_CMD_CHAN) != 0) {
    990      1.11      fvdl 		mov	HCNT[0], SCB_CMDLEN;
    991      1.11      fvdl 		bmov	HCNT[1], ALLZEROS, 2;
    992      1.11      fvdl 		if ((ahc->features & AHC_ULTRA2) == 0) {
    993      1.11      fvdl 			bmov	STCNT, HCNT, 3;
    994      1.11      fvdl 		}
    995      1.11      fvdl 		add	NONE, -17, SCB_CMDLEN;
    996      1.11      fvdl 		jc	dma_cmd_data;
    997      1.11      fvdl 		/*
    998      1.11      fvdl 		 * The data fifo seems to require 4 byte alligned
    999      1.11      fvdl 		 * transfers from the sequencer.  Force this to
   1000      1.11      fvdl 		 * be the case by clearing HADDR[0] even though
   1001      1.11      fvdl 		 * we aren't going to touch host memeory.
   1002      1.11      fvdl 		 */
   1003      1.11      fvdl 		bmov	HADDR[0], ALLZEROS, 1;
   1004      1.11      fvdl 		if ((ahc->features & AHC_ULTRA2) != 0) {
   1005      1.11      fvdl 			mvi	DFCNTRL, (PRELOADEN|SCSIEN|DIRECTION);
   1006      1.11      fvdl 		} else {
   1007      1.11      fvdl 			mvi	DFCNTRL, (SCSIEN|SDMAEN|DIRECTION|FIFORESET);
   1008      1.11      fvdl 		}
   1009      1.11      fvdl 		bmov   DFDAT, SCB_CMDSTORE, 16;
   1010      1.11      fvdl 		jmp	cmd_loop;
   1011      1.11      fvdl dma_cmd_data:
   1012      1.11      fvdl 		bmov	HADDR, SCB_CMDPTR, 4;
   1013      1.11      fvdl 	} else {
   1014      1.11      fvdl 		mvi	DINDEX, HADDR;
   1015      1.11      fvdl 		mvi	SCB_CMDPTR	call bcopy_5;
   1016      1.11      fvdl 		clr	HCNT[1];
   1017      1.11      fvdl 		clr	HCNT[2];
   1018      1.11      fvdl 	}
   1019      1.11      fvdl 
   1020      1.11      fvdl 	if ((ahc->features & AHC_ULTRA2) == 0) {
   1021      1.11      fvdl 		if ((ahc->features & AHC_CMD_CHAN) == 0) {
   1022      1.11      fvdl 			call	set_stcnt_from_hcnt;
   1023      1.11      fvdl 		}
   1024      1.11      fvdl 		mvi	DFCNTRL, (SCSIEN|SDMAEN|HDMAEN|DIRECTION|FIFORESET);
   1025      1.11      fvdl 	} else {
   1026      1.11      fvdl 		mvi	DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN|DIRECTION);
   1027      1.11      fvdl 	}
   1028      1.11      fvdl cmd_loop:
   1029      1.11      fvdl 	test	SSTAT0, SDONE jnz . + 2;
   1030      1.11      fvdl 	test    SSTAT1, PHASEMIS jz cmd_loop;
   1031      1.11      fvdl 	/*
   1032      1.11      fvdl 	 * Wait for our ACK to go-away on it's own
   1033      1.11      fvdl 	 * instead of being killed by SCSIEN getting cleared.
   1034      1.11      fvdl 	 */
   1035      1.11      fvdl 	test	SCSISIGI, ACKI jnz .;
   1036      1.11      fvdl 	and	DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN);
   1037      1.11      fvdl 	test	DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz .;
   1038      1.11      fvdl 	jmp	ITloop;
   1039       1.1   mycroft 
   1040       1.2   mycroft /*
   1041       1.2   mycroft  * Status phase.  Wait for the data byte to appear, then read it
   1042       1.2   mycroft  * and store it into the SCB.
   1043       1.2   mycroft  */
   1044       1.1   mycroft p_status:
   1045      1.11      fvdl 	call	assert;
   1046      1.11      fvdl 
   1047      1.11      fvdl 	mov	SCB_TARGET_STATUS, SCSIDATL;
   1048      1.11      fvdl 	jmp	ITloop;
   1049       1.1   mycroft 
   1050       1.2   mycroft /*
   1051      1.11      fvdl  * Message out phase.  If MSG_OUT is MSG_IDENTIFYFLAG, build a full
   1052      1.11      fvdl  * indentify message sequence and send it to the target.  The host may
   1053      1.11      fvdl  * override this behavior by setting the MK_MESSAGE bit in the SCB
   1054      1.11      fvdl  * control byte.  This will cause us to interrupt the host and allow
   1055      1.11      fvdl  * it to handle the message phase completely on its own.  If the bit
   1056      1.11      fvdl  * associated with this target is set, we will also interrupt the host,
   1057      1.11      fvdl  * thereby allowing it to send a message on the next selection regardless
   1058      1.11      fvdl  * of the transaction being sent.
   1059      1.11      fvdl  *
   1060      1.11      fvdl  * If MSG_OUT is == HOST_MSG, also interrupt the host and take a message.
   1061      1.11      fvdl  * This is done to allow the host to send messages outside of an identify
   1062      1.11      fvdl  * sequence while protecting the seqencer from testing the MK_MESSAGE bit
   1063      1.11      fvdl  * on an SCB that might not be for the current nexus. (For example, a
   1064  1.11.6.1   nathanw  * BDR message in response to a bad reselection would leave us pointed to
   1065      1.11      fvdl  * an SCB that doesn't have anything to do with the current target).
   1066      1.11      fvdl  *
   1067      1.11      fvdl  * Otherwise, treat MSG_OUT as a 1 byte message to send (abort, abort tag,
   1068      1.11      fvdl  * bus device reset).
   1069      1.11      fvdl  *
   1070      1.11      fvdl  * When there are no messages to send, MSG_OUT should be set to MSG_NOOP,
   1071      1.11      fvdl  * in case the target decides to put us in this phase for some strange
   1072      1.11      fvdl  * reason.
   1073       1.2   mycroft  */
   1074      1.11      fvdl p_mesgout_retry:
   1075      1.11      fvdl 	or	SCSISIGO,ATNO,LASTPHASE;/* turn on ATN for the retry */
   1076       1.1   mycroft p_mesgout:
   1077      1.11      fvdl 	mov	SINDEX, MSG_OUT;
   1078      1.11      fvdl 	cmp	SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host;
   1079      1.11      fvdl 	test	SCB_CONTROL,MK_MESSAGE	jnz host_message_loop;
   1080      1.11      fvdl 	mov	FUNCTION1, SCB_TCL;
   1081      1.11      fvdl 	mov	A, FUNCTION1;
   1082      1.11      fvdl 	if ((ahc->features & AHC_HS_MAILBOX) != 0) {
   1083      1.11      fvdl 		/*
   1084      1.11      fvdl 		 * Work around a pausing bug in at least the aic7890.
   1085      1.11      fvdl 		 * If the host needs to update the TARGET_MSG_REQUEST
   1086      1.11      fvdl 		 * bit field, it will set the HS_MAILBOX to 1.  In
   1087      1.11      fvdl 		 * response, we pause with a specific interrupt code
   1088      1.11      fvdl 		 * asking for the mask to be updated before we continue.
   1089      1.11      fvdl 		 * Ugh.
   1090      1.11      fvdl 		 */
   1091      1.11      fvdl 		test	HS_MAILBOX, 0xF0	jz . + 2;
   1092      1.11      fvdl 		mvi	INTSTAT, UPDATE_TMSG_REQ;
   1093      1.11      fvdl 		nop;
   1094      1.11      fvdl 	}
   1095      1.11      fvdl 	mov	SINDEX, TARGET_MSG_REQUEST[0];
   1096      1.11      fvdl 	if ((ahc->features & AHC_TWIN) != 0) {
   1097      1.11      fvdl 		/* Second Channel uses high byte bits */
   1098      1.11      fvdl 		test	SCB_TCL, SELBUSB	jz . + 2;
   1099      1.11      fvdl 		mov	SINDEX, TARGET_MSG_REQUEST[1];
   1100      1.11      fvdl 	} else if ((ahc->features & AHC_WIDE) != 0) {
   1101      1.11      fvdl 		test	SCB_TCL, 0x80		jz . + 2; /* target > 7 */
   1102      1.11      fvdl 		mov	SINDEX, TARGET_MSG_REQUEST[1];
   1103      1.11      fvdl 	}
   1104      1.11      fvdl 	test	SINDEX, A	jnz host_message_loop;
   1105      1.11      fvdl p_mesgout_identify:
   1106      1.11      fvdl 	and	SINDEX,LID,SCB_TCL;	/* lun */
   1107      1.11      fvdl 	and	A,DISCENB,SCB_CONTROL;	/* mask off disconnect privledge */
   1108      1.11      fvdl 	or	SINDEX,A;		/* or in disconnect privledge */
   1109      1.11      fvdl 	or	SINDEX,MSG_IDENTIFYFLAG;
   1110       1.2   mycroft /*
   1111      1.11      fvdl  * Send a tag message if TAG_ENB is set in the SCB control block.
   1112      1.11      fvdl  * Use SCB_TAG (the position in the kernel's SCB array) as the tag value.
   1113       1.2   mycroft  */
   1114      1.11      fvdl p_mesgout_tag:
   1115      1.11      fvdl 	test	SCB_CONTROL,TAG_ENB jz  p_mesgout_onebyte;
   1116      1.11      fvdl 	mov	SCSIDATL, SINDEX;	/* Send the identify message */
   1117      1.11      fvdl 	call	phase_lock;
   1118      1.11      fvdl 	cmp	LASTPHASE, P_MESGOUT	jne p_mesgout_done;
   1119      1.11      fvdl 	and	SCSIDATL,TAG_ENB|SCB_TAG_TYPE,SCB_CONTROL;
   1120      1.11      fvdl 	call	phase_lock;
   1121      1.11      fvdl 	cmp	LASTPHASE, P_MESGOUT	jne p_mesgout_done;
   1122      1.11      fvdl 	mov	SCB_TAG	jmp p_mesgout_onebyte;
   1123      1.11      fvdl /*
   1124      1.11      fvdl  * Interrupt the driver, and allow it to handle this message
   1125      1.11      fvdl  * phase and any required retries.
   1126      1.11      fvdl  */
   1127      1.11      fvdl p_mesgout_from_host:
   1128      1.11      fvdl 	cmp	SINDEX, HOST_MSG	jne p_mesgout_onebyte;
   1129      1.11      fvdl 	jmp	host_message_loop;
   1130      1.11      fvdl 
   1131      1.11      fvdl p_mesgout_onebyte:
   1132      1.11      fvdl 	mvi	CLRSINT1, CLRATNO;
   1133      1.11      fvdl 	mov	SCSIDATL, SINDEX;
   1134       1.2   mycroft 
   1135       1.2   mycroft /*
   1136      1.11      fvdl  * If the next bus phase after ATN drops is message out, it means
   1137       1.2   mycroft  * that the target is requesting that the last message(s) be resent.
   1138       1.2   mycroft  */
   1139      1.11      fvdl 	call	phase_lock;
   1140      1.11      fvdl 	cmp	LASTPHASE, P_MESGOUT	je p_mesgout_retry;
   1141       1.1   mycroft 
   1142       1.2   mycroft p_mesgout_done:
   1143      1.11      fvdl 	mvi	CLRSINT1,CLRATNO;	/* Be sure to turn ATNO off */
   1144      1.11      fvdl 	mov	LAST_MSG, MSG_OUT;
   1145      1.11      fvdl 	mvi	MSG_OUT, MSG_NOOP;	/* No message left */
   1146      1.11      fvdl 	jmp	ITloop;
   1147       1.1   mycroft 
   1148       1.2   mycroft /*
   1149       1.2   mycroft  * Message in phase.  Bytes are read using Automatic PIO mode.
   1150       1.2   mycroft  */
   1151       1.1   mycroft p_mesgin:
   1152      1.11      fvdl 	mvi	ACCUM		call inb_first;	/* read the 1st message byte */
   1153       1.2   mycroft 
   1154      1.11      fvdl 	test	A,MSG_IDENTIFYFLAG	jnz mesgin_identify;
   1155      1.11      fvdl 	cmp	A,MSG_DISCONNECT	je mesgin_disconnect;
   1156      1.11      fvdl 	cmp	A,MSG_SAVEDATAPOINTER	je mesgin_sdptrs;
   1157      1.11      fvdl 	cmp	ALLZEROS,A		je mesgin_complete;
   1158      1.11      fvdl 	cmp	A,MSG_RESTOREPOINTERS	je mesgin_rdptrs;
   1159      1.11      fvdl 	cmp	A,MSG_NOOP		je mesgin_done;
   1160      1.11      fvdl 
   1161      1.11      fvdl /*
   1162      1.11      fvdl  * Pushed message loop to allow the kernel to
   1163      1.11      fvdl  * run it's own message state engine.  To avoid an
   1164      1.11      fvdl  * extra nop instruction after signaling the kernel,
   1165      1.11      fvdl  * we perform the phase_lock before checking to see
   1166      1.11      fvdl  * if we should exit the loop and skip the phase_lock
   1167      1.11      fvdl  * in the ITloop.  Performing back to back phase_locks
   1168      1.11      fvdl  * shouldn't hurt, but why do it twice...
   1169      1.11      fvdl  */
   1170      1.11      fvdl host_message_loop:
   1171      1.11      fvdl 	mvi	INTSTAT, HOST_MSG_LOOP;
   1172      1.11      fvdl 	call	phase_lock;
   1173      1.11      fvdl 	cmp	RETURN_1, EXIT_MSG_LOOP	je ITloop + 1;
   1174      1.11      fvdl 	jmp	host_message_loop;
   1175       1.2   mycroft 
   1176       1.2   mycroft mesgin_done:
   1177      1.11      fvdl 	mov	NONE,SCSIDATL;		/*dummy read from latch to ACK*/
   1178      1.11      fvdl 	jmp	ITloop;
   1179       1.2   mycroft 
   1180       1.2   mycroft 
   1181       1.2   mycroft mesgin_complete:
   1182       1.2   mycroft /*
   1183      1.11      fvdl  * We got a "command complete" message, so put the SCB_TAG into the QOUTFIFO,
   1184      1.11      fvdl  * and trigger a completion interrupt.  Before doing so, check to see if there
   1185      1.11      fvdl  * is a residual or the status byte is something other than STATUS_GOOD (0).
   1186      1.11      fvdl  * In either of these conditions, we upload the SCB back to the host so it can
   1187      1.11      fvdl  * process this information.  In the case of a non zero status byte, we
   1188      1.11      fvdl  * additionally interrupt the kernel driver synchronously, allowing it to
   1189      1.11      fvdl  * decide if sense should be retrieved.  If the kernel driver wishes to request
   1190      1.11      fvdl  * sense, it will fill the kernel SCB with a request sense command and set
   1191      1.11      fvdl  * RETURN_1 to SEND_SENSE.  If RETURN_1 is set to SEND_SENSE we redownload
   1192      1.11      fvdl  * the SCB, and process it as the next command by adding it to the waiting list.
   1193      1.11      fvdl  * If the kernel driver does not wish to request sense, it need only clear
   1194      1.11      fvdl  * RETURN_1, and the command is allowed to complete normally.  We don't bother
   1195      1.11      fvdl  * to post to the QOUTFIFO in the error cases since it would require extra
   1196      1.11      fvdl  * work in the kernel driver to ensure that the entry was removed before the
   1197      1.11      fvdl  * command complete code tried processing it.
   1198       1.2   mycroft  */
   1199      1.11      fvdl 
   1200       1.2   mycroft /*
   1201      1.11      fvdl  * First check for residuals
   1202       1.2   mycroft  */
   1203      1.11      fvdl 	test	SCB_RESID_SGCNT,0xff	jnz upload_scb;
   1204      1.11      fvdl 	test	SCB_TARGET_STATUS,0xff	jz complete;	/* Good Status? */
   1205      1.11      fvdl upload_scb:
   1206      1.11      fvdl 	mvi	DMAPARAMS, FIFORESET;
   1207      1.11      fvdl 	mov	SCB_TAG		call dma_scb;
   1208      1.11      fvdl check_status:
   1209      1.11      fvdl 	test	SCB_TARGET_STATUS,0xff	jz complete;	/* Just a residual? */
   1210      1.11      fvdl 	mvi	INTSTAT,BAD_STATUS;			/* let driver know */
   1211      1.11      fvdl 	nop;
   1212      1.11      fvdl 	cmp	RETURN_1, SEND_SENSE	jne complete;
   1213      1.11      fvdl 	/* This SCB becomes the next to execute as it will retrieve sense */
   1214      1.11      fvdl 	mvi	DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
   1215      1.11      fvdl 	mov	SCB_TAG		call dma_scb;
   1216      1.11      fvdl add_to_waiting_list:
   1217      1.11      fvdl 	mov	SCB_NEXT,WAITING_SCBH;
   1218      1.11      fvdl 	mov	WAITING_SCBH, SCBPTR;
   1219      1.11      fvdl 	/*
   1220      1.11      fvdl 	 * Prepare our selection hardware before the busfree so we have a
   1221      1.11      fvdl 	 * high probability of winning arbitration.
   1222      1.11      fvdl 	 */
   1223      1.11      fvdl 	call	start_selection;
   1224      1.11      fvdl 	jmp	await_busfree;
   1225       1.1   mycroft 
   1226       1.1   mycroft complete:
   1227      1.11      fvdl 	/* If we are untagged, clear our address up in host ram */
   1228      1.11      fvdl 	test	SCB_CONTROL, TAG_ENB jnz complete_queue;
   1229      1.11      fvdl 	mov	A, SAVED_TCL;
   1230      1.11      fvdl 	/* fvdl - let ahc_intr clear this to avoid race conditions */
   1231      1.11      fvdl 	/* mvi	UNTAGGEDSCB_OFFSET call post_byte_setup; */
   1232      1.11      fvdl 	/* mvi	SCB_LIST_NULL call post_byte; */
   1233      1.11      fvdl 
   1234      1.11      fvdl complete_queue:
   1235      1.11      fvdl 	mov	SCB_TAG call complete_post;
   1236      1.11      fvdl 	jmp	await_busfree;
   1237      1.11      fvdl }
   1238      1.11      fvdl 
   1239      1.11      fvdl complete_post:
   1240      1.11      fvdl 	/* Post the SCBID in SINDEX and issue an interrupt */
   1241      1.11      fvdl 	call	add_scb_to_free_list;
   1242      1.11      fvdl 	mov	ARG_1, SINDEX;
   1243      1.11      fvdl 	if ((ahc->features & AHC_QUEUE_REGS) != 0) {
   1244      1.11      fvdl 		mov	A, SDSCB_QOFF;
   1245      1.11      fvdl 	} else {
   1246      1.11      fvdl 		mov	A, QOUTPOS;
   1247      1.11      fvdl 	}
   1248      1.11      fvdl 	mvi	QOUTFIFO_OFFSET call post_byte_setup;
   1249      1.11      fvdl 	mov	ARG_1 call post_byte;
   1250      1.11      fvdl 	if ((ahc->features & AHC_QUEUE_REGS) == 0) {
   1251      1.11      fvdl 		inc 	QOUTPOS;
   1252      1.11      fvdl 	}
   1253      1.11      fvdl 	mvi	INTSTAT,CMDCMPLT ret;
   1254       1.2   mycroft 
   1255      1.11      fvdl if ((ahc->flags & AHC_INITIATORMODE) != 0) {
   1256       1.2   mycroft /*
   1257       1.2   mycroft  * Is it a disconnect message?  Set a flag in the SCB to remind us
   1258       1.2   mycroft  * and await the bus going free.
   1259       1.2   mycroft  */
   1260       1.2   mycroft mesgin_disconnect:
   1261      1.11      fvdl 	or	SCB_CONTROL,DISCONNECTED;
   1262      1.11      fvdl 	call	add_scb_to_disc_list;
   1263      1.11      fvdl 	jmp	await_busfree;
   1264       1.2   mycroft 
   1265       1.2   mycroft /*
   1266      1.11      fvdl  * Save data pointers message:
   1267      1.11      fvdl  * Copying RAM values back to SCB, for Save Data Pointers message, but
   1268      1.11      fvdl  * only if we've actually been into a data phase to change them.  This
   1269      1.11      fvdl  * protects against bogus data in scratch ram and the residual counts
   1270      1.11      fvdl  * since they are only initialized when we go into data_in or data_out.
   1271       1.2   mycroft  */
   1272       1.2   mycroft mesgin_sdptrs:
   1273      1.11      fvdl 	test	SEQ_FLAGS, DPHASE	jz mesgin_done;
   1274      1.11      fvdl 
   1275      1.11      fvdl 	/*
   1276      1.11      fvdl 	 * The SCB SGPTR becomes the next one we'll download,
   1277      1.11      fvdl 	 * and the SCB DATAPTR becomes the current SHADDR.
   1278      1.11      fvdl 	 * Use the residual number since STCNT is corrupted by
   1279      1.11      fvdl 	 * any message transfer.
   1280      1.11      fvdl 	 */
   1281      1.11      fvdl 	if ((ahc->features & AHC_CMD_CHAN) != 0) {
   1282      1.11      fvdl 		bmov	SCB_SGCOUNT, SG_COUNT, 5;
   1283      1.11      fvdl 		bmov	SCB_DATAPTR, SHADDR, 4;
   1284      1.11      fvdl 		bmov	SCB_DATACNT, SCB_RESID_DCNT, 3;
   1285      1.11      fvdl 	} else {
   1286      1.11      fvdl 		mvi	DINDEX, SCB_SGCOUNT;
   1287      1.11      fvdl 		mvi	SG_COUNT call bcopy_5;
   1288      1.11      fvdl 
   1289      1.11      fvdl 		mvi	DINDEX, SCB_DATAPTR;
   1290      1.11      fvdl 		mvi	SHADDR		call bcopy_4;
   1291      1.11      fvdl 		mvi	SCB_RESID_DCNT	call bcopy_3;
   1292      1.11      fvdl 	}
   1293      1.11      fvdl 	jmp	mesgin_done;
   1294       1.1   mycroft 
   1295       1.2   mycroft /*
   1296       1.2   mycroft  * Restore pointers message?  Data pointers are recopied from the
   1297       1.2   mycroft  * SCB anytime we enter a data phase for the first time, so all
   1298       1.2   mycroft  * we need to do is clear the DPHASE flag and let the data phase
   1299       1.2   mycroft  * code do the rest.
   1300       1.2   mycroft  */
   1301       1.2   mycroft mesgin_rdptrs:
   1302      1.11      fvdl 	and	SEQ_FLAGS, ~DPHASE;		/*
   1303      1.11      fvdl 						 * We'll reload them
   1304       1.2   mycroft 						 * the next time through
   1305      1.11      fvdl 						 * the dataphase.
   1306       1.2   mycroft 						 */
   1307      1.11      fvdl 	jmp	mesgin_done;
   1308       1.2   mycroft 
   1309       1.2   mycroft /*
   1310       1.2   mycroft  * Identify message?  For a reconnecting target, this tells us the lun
   1311       1.2   mycroft  * that the reconnection is for - find the correct SCB and switch to it,
   1312       1.2   mycroft  * clearing the "disconnected" bit so we don't "find" it by accident later.
   1313       1.2   mycroft  */
   1314       1.2   mycroft mesgin_identify:
   1315      1.11      fvdl 	if ((ahc->features & AHC_WIDE) != 0) {
   1316      1.11      fvdl 		and	A,0x0f;		/* lun in lower four bits */
   1317      1.11      fvdl 	} else {
   1318      1.11      fvdl 		and	A,0x07;		/* lun in lower three bits */
   1319      1.11      fvdl 	}
   1320      1.11      fvdl 	or      SAVED_TCL,A;		/* SAVED_TCL should be complete now */
   1321      1.11      fvdl 
   1322      1.11      fvdl 	mvi	ARG_2, SCB_LIST_NULL;	/* SCBID of prev SCB in disc List */
   1323      1.11      fvdl 	call	get_untagged_SCBID;
   1324      1.11      fvdl 	cmp	ARG_1, SCB_LIST_NULL	je snoop_tag;
   1325      1.11      fvdl 	if ((ahc->flags & AHC_PAGESCBS) != 0) {
   1326      1.11      fvdl 		test	SEQ_FLAGS, SCBPTR_VALID	jz use_retrieveSCB;
   1327      1.11      fvdl 	}
   1328      1.11      fvdl 	/*
   1329      1.11      fvdl 	 * If the SCB was found in the disconnected list (as is
   1330      1.11      fvdl 	 * always the case in non-paging scenarios), SCBPTR is already
   1331      1.11      fvdl 	 * set to the correct SCB.  So, simply setup the SCB and get
   1332      1.11      fvdl 	 * on with things.
   1333      1.11      fvdl 	 */
   1334      1.11      fvdl 	call	rem_scb_from_disc_list;
   1335      1.11      fvdl 	jmp	setup_SCB;
   1336       1.2   mycroft /*
   1337       1.2   mycroft  * Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message.
   1338      1.11      fvdl  * If we get one, we use the tag returned to find the proper
   1339      1.11      fvdl  * SCB.  With SCB paging, this requires using search for both tagged
   1340       1.2   mycroft  * and non-tagged transactions since the SCB may exist in any slot.
   1341       1.2   mycroft  * If we're not using SCB paging, we can use the tag as the direct
   1342       1.2   mycroft  * index to the SCB.
   1343       1.2   mycroft  */
   1344      1.11      fvdl snoop_tag:
   1345      1.11      fvdl 	mov	NONE,SCSIDATL;		/* ACK Identify MSG */
   1346       1.2   mycroft snoop_tag_loop:
   1347      1.11      fvdl 	call	phase_lock;
   1348      1.11      fvdl 	cmp	LASTPHASE, P_MESGIN	jne not_found;
   1349      1.11      fvdl 	cmp	SCSIBUSL,MSG_SIMPLE_Q_TAG jne not_found;
   1350       1.2   mycroft get_tag:
   1351      1.11      fvdl 	mvi	ARG_1	call inb_next;	/* tag value */
   1352       1.2   mycroft 
   1353      1.11      fvdl 	/*
   1354      1.11      fvdl 	 * Ensure that the SCB the tag points to is for
   1355      1.11      fvdl 	 * an SCB transaction to the reconnecting target.
   1356      1.11      fvdl 	 */
   1357      1.11      fvdl use_retrieveSCB:
   1358      1.11      fvdl 	call	retrieveSCB;
   1359       1.1   mycroft setup_SCB:
   1360      1.11      fvdl 	mov	A, SAVED_TCL;
   1361      1.11      fvdl 	cmp	SCB_TCL, A	jne not_found_cleanup_scb;
   1362      1.11      fvdl 	test	SCB_CONTROL,DISCONNECTED jz not_found_cleanup_scb;
   1363      1.11      fvdl 	and	SCB_CONTROL,~DISCONNECTED;
   1364      1.11      fvdl 	or	SEQ_FLAGS,IDENTIFY_SEEN;	/* make note of IDENTIFY */
   1365      1.11      fvdl 	call	set_transfer_settings;
   1366      1.11      fvdl 	/* See if the host wants to send a message upon reconnection */
   1367      1.11      fvdl 	test	SCB_CONTROL, MK_MESSAGE jz mesgin_done;
   1368      1.11      fvdl 	and	SCB_CONTROL, ~MK_MESSAGE;
   1369      1.11      fvdl 	mvi	HOST_MSG	call mk_mesg;
   1370      1.11      fvdl 	jmp	mesgin_done;
   1371      1.11      fvdl 
   1372      1.11      fvdl not_found_cleanup_scb:
   1373      1.11      fvdl 	test	SCB_CONTROL, DISCONNECTED jz . + 3;
   1374      1.11      fvdl 	call	add_scb_to_disc_list;
   1375      1.11      fvdl 	jmp	not_found;
   1376      1.11      fvdl 	call	add_scb_to_free_list;
   1377      1.11      fvdl not_found:
   1378      1.11      fvdl 	mvi	INTSTAT, NO_MATCH;
   1379      1.11      fvdl 	jmp	mesgin_done;
   1380       1.2   mycroft 
   1381       1.2   mycroft /*
   1382       1.2   mycroft  * [ ADD MORE MESSAGE HANDLING HERE ]
   1383       1.2   mycroft  */
   1384       1.2   mycroft 
   1385       1.2   mycroft /*
   1386       1.2   mycroft  * Locking the driver out, build a one-byte message passed in SINDEX
   1387       1.2   mycroft  * if there is no active message already.  SINDEX is returned intact.
   1388       1.2   mycroft  */
   1389       1.2   mycroft mk_mesg:
   1390      1.11      fvdl 	or	SCSISIGO,ATNO,LASTPHASE;/* turn on ATNO */
   1391      1.11      fvdl 	mov	MSG_OUT,SINDEX ret;
   1392       1.2   mycroft 
   1393       1.2   mycroft /*
   1394       1.2   mycroft  * Functions to read data in Automatic PIO mode.
   1395       1.2   mycroft  *
   1396       1.2   mycroft  * According to Adaptec's documentation, an ACK is not sent on input from
   1397       1.2   mycroft  * the target until SCSIDATL is read from.  So we wait until SCSIDATL is
   1398       1.2   mycroft  * latched (the usual way), then read the data byte directly off the bus
   1399       1.2   mycroft  * using SCSIBUSL.  When we have pulled the ATN line, or we just want to
   1400       1.2   mycroft  * acknowledge the byte, then we do a dummy read from SCISDATL.  The SCSI
   1401       1.2   mycroft  * spec guarantees that the target will hold the data byte on the bus until
   1402       1.2   mycroft  * we send our ACK.
   1403       1.2   mycroft  *
   1404       1.2   mycroft  * The assumption here is that these are called in a particular sequence,
   1405       1.2   mycroft  * and that REQ is already set when inb_first is called.  inb_{first,next}
   1406       1.2   mycroft  * use the same calling convention as inb.
   1407       1.2   mycroft  */
   1408      1.11      fvdl inb_next_wait_perr:
   1409      1.11      fvdl 	mvi	INTSTAT, PERR_DETECTED;
   1410      1.11      fvdl 	jmp	inb_next_wait;
   1411       1.2   mycroft inb_next:
   1412      1.11      fvdl 	mov	NONE,SCSIDATL;		/*dummy read from latch to ACK*/
   1413       1.2   mycroft inb_next_wait:
   1414      1.11      fvdl 	/*
   1415      1.11      fvdl 	 * If there is a parity error, wait for the kernel to
   1416      1.11      fvdl 	 * see the interrupt and prepare our message response
   1417      1.11      fvdl 	 * before continuing.
   1418      1.11      fvdl 	 */
   1419      1.11      fvdl 	test	SSTAT1, REQINIT	jz inb_next_wait;
   1420      1.11      fvdl 	test	SSTAT1, SCSIPERR jnz inb_next_wait_perr;
   1421      1.11      fvdl inb_next_check_phase:
   1422      1.11      fvdl 	and	LASTPHASE, PHASE_MASK, SCSISIGI;
   1423      1.11      fvdl 	cmp	LASTPHASE, P_MESGIN jne mesgin_phasemis;
   1424       1.1   mycroft inb_first:
   1425      1.11      fvdl 	mov	DINDEX,SINDEX;
   1426      1.11      fvdl 	mov	DINDIR,SCSIBUSL	ret;		/*read byte directly from bus*/
   1427       1.2   mycroft inb_last:
   1428      1.11      fvdl 	mov	NONE,SCSIDATL ret;		/*dummy read from latch to ACK*/
   1429      1.11      fvdl }
   1430       1.1   mycroft 
   1431      1.11      fvdl if ((ahc->flags & AHC_TARGETMODE) != 0) {
   1432      1.11      fvdl /*
   1433      1.11      fvdl  * Change to a new phase.  If we are changing the state of the I/O signal,
   1434      1.11      fvdl  * from out to in, wait an additional data release delay before continuing.
   1435      1.11      fvdl  */
   1436      1.11      fvdl change_phase:
   1437      1.11      fvdl 	/* Wait for preceeding I/O session to complete. */
   1438      1.11      fvdl 	test	SCSISIGI, ACKI jnz .;
   1439      1.11      fvdl 
   1440      1.11      fvdl 	/* Change the phase */
   1441      1.11      fvdl 	and	DINDEX, IOI, SCSISIGI;
   1442      1.11      fvdl 	mov	SCSISIGO, SINDEX;
   1443      1.11      fvdl 	and	A, IOI, SINDEX;
   1444      1.11      fvdl 
   1445      1.11      fvdl 	/*
   1446      1.11      fvdl 	 * If the data direction has changed, from
   1447      1.11      fvdl 	 * out (initiator driving) to in (target driving),
   1448      1.11      fvdl 	 * we must waitat least a data release delay plus
   1449      1.11      fvdl 	 * the normal bus settle delay. [SCSI III SPI 10.11.0]
   1450      1.11      fvdl 	 */
   1451      1.11      fvdl 	cmp 	DINDEX, A je change_phase_wait;
   1452      1.11      fvdl 	test	SINDEX, IOI jz change_phase_wait;
   1453      1.11      fvdl 	call	change_phase_wait;
   1454      1.11      fvdl change_phase_wait:
   1455      1.11      fvdl 	nop;
   1456      1.11      fvdl 	nop;
   1457      1.11      fvdl 	nop;
   1458      1.11      fvdl 	nop ret;
   1459      1.11      fvdl 
   1460      1.11      fvdl /*
   1461      1.11      fvdl  * Send a byte to an initiator in Automatic PIO mode.
   1462      1.11      fvdl  */
   1463      1.11      fvdl target_outb:
   1464      1.11      fvdl 	or	SXFRCTL0, SPIOEN;
   1465      1.11      fvdl 	test	SSTAT0, SPIORDY	jz .;
   1466      1.11      fvdl 	mov	SCSIDATL, SINDEX;
   1467      1.11      fvdl 	test	SSTAT0, SPIORDY	jz .;
   1468      1.11      fvdl 	and	SXFRCTL0, ~SPIOEN ret;
   1469      1.11      fvdl }
   1470      1.11      fvdl 
   1471       1.2   mycroft mesgin_phasemis:
   1472       1.2   mycroft /*
   1473       1.2   mycroft  * We expected to receive another byte, but the target changed phase
   1474       1.2   mycroft  */
   1475      1.11      fvdl 	mvi	INTSTAT, MSGIN_PHASEMIS;
   1476      1.11      fvdl 	jmp	ITloop;
   1477       1.1   mycroft 
   1478       1.2   mycroft /*
   1479       1.2   mycroft  * DMA data transfer.  HADDR and HCNT must be loaded first, and
   1480       1.2   mycroft  * SINDEX should contain the value to load DFCNTRL with - 0x3d for
   1481       1.2   mycroft  * host->scsi, or 0x39 for scsi->host.  The SCSI channel is cleared
   1482       1.2   mycroft  * during initialization.
   1483       1.2   mycroft  */
   1484       1.1   mycroft dma:
   1485      1.11      fvdl 	mov	DFCNTRL,SINDEX;
   1486      1.11      fvdl dma_loop:
   1487      1.11      fvdl 	test	SSTAT0,DMADONE	jnz dma_dmadone;
   1488      1.11      fvdl 	test	SSTAT1,PHASEMIS	jz dma_loop;	/* ie. underrun */
   1489      1.11      fvdl dma_phasemis:
   1490       1.2   mycroft 
   1491       1.2   mycroft /*
   1492       1.2   mycroft  * We will be "done" DMAing when the transfer count goes to zero, or
   1493       1.2   mycroft  * the target changes the phase (in light of this, it makes sense that
   1494       1.2   mycroft  * the DMA circuitry doesn't ACK when PHASEMIS is active).  If we are
   1495       1.2   mycroft  * doing a SCSI->Host transfer, the data FIFO should be flushed auto-
   1496       1.2   mycroft  * magically on STCNT=0 or a phase change, so just wait for FIFO empty
   1497       1.2   mycroft  * status.
   1498       1.2   mycroft  */
   1499      1.11      fvdl dma_checkfifo:
   1500      1.11      fvdl 	test	DFCNTRL,DIRECTION	jnz dma_fifoempty;
   1501      1.11      fvdl dma_fifoflush:
   1502      1.11      fvdl 	test	DFSTATUS,FIFOEMP	jz dma_fifoflush;
   1503      1.11      fvdl 
   1504      1.11      fvdl dma_fifoempty:
   1505      1.11      fvdl 	/* Don't clobber an inprogress host data transfer */
   1506      1.11      fvdl 	test	DFSTATUS, MREQPEND	jnz dma_fifoempty;
   1507       1.2   mycroft /*
   1508      1.10    mjacob  * Now shut the DMA enables off and make sure that the DMA enables are
   1509       1.2   mycroft  * actually off first lest we get an ILLSADDR.
   1510       1.2   mycroft  */
   1511      1.11      fvdl dma_dmadone:
   1512      1.11      fvdl 	and	DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN);
   1513      1.11      fvdl dma_halt:
   1514      1.11      fvdl 	/*
   1515      1.11      fvdl 	 * Some revisions of the aic7880 have a problem where, if the
   1516      1.11      fvdl 	 * data fifo is full, but the PCI input latch is not empty,
   1517      1.11      fvdl 	 * HDMAEN cannot be cleared.  The fix used here is to attempt
   1518      1.11      fvdl 	 * to drain the data fifo until there is space for the input
   1519      1.11      fvdl 	 * latch to drain and HDMAEN de-asserts.
   1520      1.11      fvdl 	 */
   1521      1.11      fvdl 	if ((ahc->features & AHC_ULTRA2) == 0) {
   1522      1.11      fvdl 		mov	NONE, DFDAT;
   1523      1.11      fvdl 	}
   1524      1.11      fvdl 	test	DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz dma_halt;
   1525       1.6     gibbs return:
   1526      1.11      fvdl 	ret;
   1527       1.1   mycroft 
   1528       1.2   mycroft /*
   1529       1.2   mycroft  * Assert that if we've been reselected, then we've seen an IDENTIFY
   1530       1.2   mycroft  * message.
   1531       1.2   mycroft  */
   1532       1.1   mycroft assert:
   1533      1.11      fvdl 	test	SEQ_FLAGS,IDENTIFY_SEEN	jnz return;	/* seen IDENTIFY? */
   1534       1.1   mycroft 
   1535      1.11      fvdl 	mvi	INTSTAT,NO_IDENT 	ret;	/* no - tell the kernel */
   1536       1.1   mycroft 
   1537       1.2   mycroft /*
   1538      1.11      fvdl  * Locate a disconnected SCB either by SAVED_TCL (ARG_1 is SCB_LIST_NULL)
   1539      1.11      fvdl  * or by the SCBID ARG_1.  The search begins at the SCB index passed in
   1540      1.11      fvdl  * via SINDEX which is an SCB that must be on the disconnected list.  If
   1541      1.11      fvdl  * the SCB cannot be found, SINDEX will be SCB_LIST_NULL, otherwise, SCBPTR
   1542      1.11      fvdl  * is set to the proper SCB.
   1543       1.2   mycroft  */
   1544       1.1   mycroft findSCB:
   1545      1.11      fvdl 	mov	SCBPTR,SINDEX;			/* Initialize SCBPTR */
   1546      1.11      fvdl 	cmp	ARG_1, SCB_LIST_NULL	jne findSCB_by_SCBID;
   1547      1.11      fvdl 	mov	A, SAVED_TCL;
   1548      1.11      fvdl 	mvi	SCB_TCL	jmp findSCB_loop;	/* &SCB_TCL -> SINDEX */
   1549      1.11      fvdl findSCB_by_SCBID:
   1550      1.11      fvdl 	mov	A, ARG_1;			/* Tag passed in ARG_1 */
   1551      1.11      fvdl 	mvi	SCB_TAG	jmp findSCB_loop;	/* &SCB_TAG -> SINDEX */
   1552      1.11      fvdl findSCB_next:
   1553      1.11      fvdl 	mov	ARG_2, SCBPTR;
   1554      1.11      fvdl 	cmp	SCB_NEXT, SCB_LIST_NULL je notFound;
   1555      1.11      fvdl 	mov	SCBPTR,SCB_NEXT;
   1556      1.11      fvdl 	dec	SINDEX;		/* Last comparison moved us too far */
   1557      1.11      fvdl findSCB_loop:
   1558      1.11      fvdl 	cmp	SINDIR, A	jne findSCB_next;
   1559      1.11      fvdl 	mov	SINDEX, SCBPTR 	ret;
   1560      1.11      fvdl notFound:
   1561      1.11      fvdl 	mvi	SINDEX, SCB_LIST_NULL	ret;
   1562      1.11      fvdl 
   1563      1.11      fvdl /*
   1564      1.11      fvdl  * Retrieve an SCB by SCBID first searching the disconnected list falling
   1565      1.11      fvdl  * back to DMA'ing the SCB down from the host.  This routine assumes that
   1566      1.11      fvdl  * ARG_1 is the SCBID of interrest and that SINDEX is the position in the
   1567      1.11      fvdl  * disconnected list to start the search from.  If SINDEX is SCB_LIST_NULL,
   1568      1.11      fvdl  * we go directly to the host for the SCB.
   1569      1.11      fvdl  */
   1570      1.11      fvdl retrieveSCB:
   1571      1.11      fvdl 	test	SEQ_FLAGS, SCBPTR_VALID	jz retrieve_from_host;
   1572      1.11      fvdl 	mov	SCBPTR	call findSCB;	/* Continue the search */
   1573      1.11      fvdl 	cmp	SINDEX, SCB_LIST_NULL	je retrieve_from_host;
   1574      1.11      fvdl 
   1575      1.11      fvdl /*
   1576      1.11      fvdl  * This routine expects SINDEX to contain the index of the SCB to be
   1577      1.11      fvdl  * removed, SCBPTR to be pointing to that SCB, and ARG_2 to be the
   1578      1.11      fvdl  * SCBID of the SCB just previous to this one in the list or SCB_LIST_NULL
   1579      1.11      fvdl  * if it is at the head.
   1580      1.11      fvdl  */
   1581      1.11      fvdl rem_scb_from_disc_list:
   1582       1.2   mycroft /* Remove this SCB from the disconnection list */
   1583      1.11      fvdl 	cmp	ARG_2, SCB_LIST_NULL	je rHead;
   1584      1.11      fvdl 	mov	DINDEX, SCB_NEXT;
   1585      1.11      fvdl 	mov	SCBPTR, ARG_2;
   1586      1.11      fvdl 	mov	SCB_NEXT, DINDEX;
   1587      1.11      fvdl 	mov	SCBPTR, SINDEX ret;
   1588       1.2   mycroft rHead:
   1589      1.11      fvdl 	mov	DISCONNECTED_SCBH,SCB_NEXT ret;
   1590       1.2   mycroft 
   1591      1.11      fvdl retrieve_from_host:
   1592       1.2   mycroft /*
   1593      1.11      fvdl  * We didn't find it.  Pull an SCB and DMA down the one we want.
   1594      1.11      fvdl  * We should never get here in the non-paging case.
   1595       1.2   mycroft  */
   1596      1.11      fvdl 	mov	ALLZEROS	call	get_free_or_disc_scb;
   1597      1.11      fvdl 	mvi	DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
   1598      1.11      fvdl 	/* Jump instead of call as we want to return anyway */
   1599      1.11      fvdl 	mov	ARG_1	jmp dma_scb;
   1600      1.11      fvdl 
   1601      1.11      fvdl /*
   1602      1.11      fvdl  * Determine whether a target is using tagged or non-tagged transactions
   1603      1.11      fvdl  * by first looking for a matching transaction based on the TCL and if
   1604      1.11      fvdl  * that fails, looking up this device in the host's untagged SCB array.
   1605      1.11      fvdl  * The TCL to search for is assumed to be in SAVED_TCL.  The value is
   1606      1.11      fvdl  * returned in ARG_1 (SCB_LIST_NULL for tagged, SCBID for non-tagged).
   1607      1.11      fvdl  * The SCBPTR_VALID bit is set in SEQ_FLAGS if we found the information
   1608      1.11      fvdl  * in an SCB instead of having to go to the host.
   1609      1.11      fvdl  */
   1610      1.11      fvdl get_untagged_SCBID:
   1611      1.11      fvdl 	cmp	DISCONNECTED_SCBH, SCB_LIST_NULL je get_SCBID_from_host;
   1612      1.11      fvdl 	mvi	ARG_1, SCB_LIST_NULL;
   1613      1.11      fvdl 	mov	DISCONNECTED_SCBH call findSCB;
   1614      1.11      fvdl 	cmp	SINDEX, SCB_LIST_NULL	je get_SCBID_from_host;
   1615      1.11      fvdl 	or	SEQ_FLAGS, SCBPTR_VALID;/* Was in disconnected list */
   1616      1.11      fvdl 	test	SCB_CONTROL, TAG_ENB	jnz . + 2;
   1617      1.11      fvdl 	mov	ARG_1, SCB_TAG	ret;
   1618      1.11      fvdl 	mvi	ARG_1, SCB_LIST_NULL ret;
   1619      1.11      fvdl 
   1620      1.11      fvdl /*
   1621      1.11      fvdl  * Fetch a byte from host memory given an index of (A + (256 * SINDEX))
   1622      1.11      fvdl  * and a base address of SCBID_ADDR.  The byte is returned in RETURN_2.
   1623      1.11      fvdl  */
   1624      1.11      fvdl fetch_byte:
   1625      1.11      fvdl 	mov	ARG_2, SINDEX;
   1626      1.11      fvdl 	if ((ahc->features & AHC_CMD_CHAN) != 0) {
   1627      1.11      fvdl 		mvi	DINDEX, CCHADDR;
   1628      1.11      fvdl 		mvi	SCBID_ADDR call set_1byte_addr;
   1629      1.11      fvdl 		mvi	CCHCNT, 1;
   1630      1.11      fvdl 		mvi	CCSGCTL, CCSGEN|CCSGRESET;
   1631      1.11      fvdl 		test	CCSGCTL, CCSGDONE jz .;
   1632      1.11      fvdl 		mvi	CCSGCTL, CCSGRESET;
   1633      1.11      fvdl 		bmov	RETURN_2, CCSGRAM, 1 ret;
   1634      1.11      fvdl 	} else {
   1635      1.11      fvdl 		mvi	DINDEX, HADDR;
   1636      1.11      fvdl 		mvi	SCBID_ADDR call set_1byte_addr;
   1637      1.11      fvdl 		mvi	HCNT[0], 1;
   1638      1.11      fvdl 		clr	HCNT[1];
   1639      1.11      fvdl 		clr	HCNT[2];
   1640      1.11      fvdl 		mvi	DFCNTRL, HDMAEN|DIRECTION|FIFORESET;
   1641      1.11      fvdl 		call	dma_finish;
   1642      1.11      fvdl 		mov	RETURN_2, DFDAT ret;
   1643      1.11      fvdl 	}
   1644      1.11      fvdl 
   1645      1.11      fvdl /*
   1646      1.11      fvdl  * Prepare the hardware to post a byte to host memory given an
   1647      1.11      fvdl  * index of (A + (256 * SINDEX)) and a base address of SCBID_ADDR.
   1648      1.11      fvdl  */
   1649      1.11      fvdl post_byte_setup:
   1650      1.11      fvdl 	mov	ARG_2, SINDEX;
   1651      1.11      fvdl 	if ((ahc->features & AHC_CMD_CHAN) != 0) {
   1652      1.11      fvdl 		mvi	DINDEX, CCHADDR;
   1653      1.11      fvdl 		mvi	SCBID_ADDR call	set_1byte_addr;
   1654      1.11      fvdl 		mvi	CCHCNT, 1;
   1655      1.11      fvdl 		mvi	CCSCBCTL, CCSCBRESET ret;
   1656      1.11      fvdl 	} else {
   1657      1.11      fvdl 		mvi	DINDEX, HADDR;
   1658      1.11      fvdl 		mvi	SCBID_ADDR call	set_1byte_addr;
   1659      1.11      fvdl 		mvi	HCNT[0], 1;
   1660      1.11      fvdl 		clr	HCNT[1];
   1661      1.11      fvdl 		clr	HCNT[2];
   1662      1.11      fvdl 		mvi	DFCNTRL, FIFORESET ret;
   1663      1.11      fvdl 	}
   1664      1.11      fvdl 
   1665      1.11      fvdl post_byte:
   1666      1.11      fvdl 	if ((ahc->features & AHC_CMD_CHAN) != 0) {
   1667      1.11      fvdl 		bmov	CCSCBRAM, SINDEX, 1;
   1668      1.11      fvdl 		or	CCSCBCTL, CCSCBEN|CCSCBRESET;
   1669      1.11      fvdl 		test	CCSCBCTL, CCSCBDONE jz .;
   1670      1.11      fvdl 		clr	CCSCBCTL ret;
   1671      1.11      fvdl 	} else {
   1672      1.11      fvdl 		mov	DFDAT, SINDEX;
   1673      1.11      fvdl 		or	DFCNTRL, HDMAEN|FIFOFLUSH;
   1674      1.11      fvdl 		jmp	dma_finish;
   1675      1.11      fvdl 	}
   1676      1.11      fvdl 
   1677      1.11      fvdl get_SCBID_from_host:
   1678      1.11      fvdl 	mov	A, SAVED_TCL;
   1679      1.11      fvdl 	mvi	UNTAGGEDSCB_OFFSET call fetch_byte;
   1680      1.11      fvdl 	mov	RETURN_1,  RETURN_2 ret;
   1681      1.11      fvdl 
   1682      1.11      fvdl phase_lock_perr:
   1683      1.11      fvdl 	mvi	INTSTAT, PERR_DETECTED;
   1684      1.11      fvdl phase_lock:
   1685      1.11      fvdl 	/*
   1686      1.11      fvdl 	 * If there is a parity error, wait for the kernel to
   1687      1.11      fvdl 	 * see the interrupt and prepare our message response
   1688      1.11      fvdl 	 * before continuing.
   1689      1.11      fvdl 	 */
   1690      1.11      fvdl 	test	SSTAT1, REQINIT jz phase_lock;
   1691      1.11      fvdl 	test	SSTAT1, SCSIPERR jnz phase_lock_perr;
   1692      1.11      fvdl phase_lock_latch_phase:
   1693      1.11      fvdl 	and	SCSISIGO, PHASE_MASK, SCSISIGI;
   1694      1.11      fvdl 	and	LASTPHASE, PHASE_MASK, SCSISIGI ret;
   1695      1.11      fvdl 
   1696      1.11      fvdl if ((ahc->features & AHC_CMD_CHAN) == 0) {
   1697      1.11      fvdl set_stcnt_from_hcnt:
   1698      1.11      fvdl 	mov	STCNT[0], HCNT[0];
   1699      1.11      fvdl 	mov	STCNT[1], HCNT[1];
   1700      1.11      fvdl 	mov	STCNT[2], HCNT[2] ret;
   1701      1.11      fvdl 
   1702      1.11      fvdl bcopy_7:
   1703      1.11      fvdl 	mov	DINDIR, SINDIR;
   1704      1.11      fvdl 	mov	DINDIR, SINDIR;
   1705      1.11      fvdl bcopy_5:
   1706      1.11      fvdl 	mov	DINDIR, SINDIR;
   1707      1.11      fvdl bcopy_4:
   1708      1.11      fvdl 	mov	DINDIR, SINDIR;
   1709      1.11      fvdl bcopy_3:
   1710      1.11      fvdl 	mov	DINDIR, SINDIR;
   1711      1.11      fvdl 	mov	DINDIR, SINDIR;
   1712      1.11      fvdl 	mov	DINDIR, SINDIR ret;
   1713      1.11      fvdl }
   1714      1.11      fvdl 
   1715      1.11      fvdl if ((ahc->flags & AHC_TARGETMODE) != 0) {
   1716      1.11      fvdl /*
   1717      1.11      fvdl  * Setup addr assuming that A is an index into
   1718      1.11      fvdl  * an array of 32byte objects, SINDEX contains
   1719      1.11      fvdl  * the base address of that array, and DINDEX
   1720      1.11      fvdl  * contains the base address of the location
   1721      1.11      fvdl  * to store the indexed address.
   1722      1.11      fvdl  */
   1723      1.11      fvdl set_32byte_addr:
   1724      1.11      fvdl 	shr	ARG_2, 3, A;
   1725      1.11      fvdl 	shl	A, 5;
   1726      1.11      fvdl 	jmp	set_1byte_addr;
   1727      1.11      fvdl }
   1728      1.11      fvdl 
   1729      1.11      fvdl /*
   1730      1.11      fvdl  * Setup addr assuming that A is an index into
   1731      1.11      fvdl  * an array of 64byte objects, SINDEX contains
   1732      1.11      fvdl  * the base address of that array, and DINDEX
   1733      1.11      fvdl  * contains the base address of the location
   1734      1.11      fvdl  * to store the indexed address.
   1735      1.11      fvdl  */
   1736      1.11      fvdl set_64byte_addr:
   1737      1.11      fvdl 	shr	ARG_2, 2, A;
   1738      1.11      fvdl 	shl	A, 6;
   1739      1.11      fvdl 
   1740      1.11      fvdl /*
   1741      1.11      fvdl  * Setup addr assuming that A + (ARG_1 * 256) is an
   1742      1.11      fvdl  * index into an array of 1byte objects, SINDEX contains
   1743      1.11      fvdl  * the base address of that array, and DINDEX contains
   1744      1.11      fvdl  * the base address of the location to store the computed
   1745      1.11      fvdl  * address.
   1746      1.11      fvdl  */
   1747      1.11      fvdl set_1byte_addr:
   1748      1.11      fvdl 	add     DINDIR, A, SINDIR;
   1749      1.11      fvdl 	mov     A, ARG_2;
   1750      1.11      fvdl 	adc	DINDIR, A, SINDIR;
   1751      1.11      fvdl 	clr	A;
   1752      1.11      fvdl 	adc	DINDIR, A, SINDIR;
   1753      1.11      fvdl 	adc	DINDIR, A, SINDIR ret;
   1754      1.11      fvdl 
   1755      1.11      fvdl /*
   1756      1.11      fvdl  * Either post or fetch and SCB from host memory based on the
   1757      1.11      fvdl  * DIRECTION bit in DMAPARAMS. The host SCB index is in SINDEX.
   1758      1.11      fvdl  */
   1759      1.11      fvdl dma_scb:
   1760      1.11      fvdl 	mov	A, SINDEX;
   1761      1.11      fvdl 	if ((ahc->features & AHC_CMD_CHAN) != 0) {
   1762      1.11      fvdl 		mvi	DINDEX, CCHADDR;
   1763      1.11      fvdl 		mvi	HSCB_ADDR call set_64byte_addr;
   1764      1.11      fvdl 		mov	CCSCBPTR, SCBPTR;
   1765      1.11      fvdl 		test	DMAPARAMS, DIRECTION jz dma_scb_tohost;
   1766      1.11      fvdl 		mvi	CCHCNT, SCB_64BYTE_SIZE;
   1767      1.11      fvdl 		mvi	CCSCBCTL, CCARREN|CCSCBEN|CCSCBDIR|CCSCBRESET;
   1768      1.11      fvdl 		cmp	CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN|CCSCBDIR jne .;
   1769      1.11      fvdl 		jmp	dma_scb_finish;
   1770      1.11      fvdl dma_scb_tohost:
   1771      1.11      fvdl 		mvi	CCHCNT, SCB_32BYTE_SIZE;
   1772      1.11      fvdl 		if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
   1773      1.11      fvdl 			mvi	CCSCBCTL, CCSCBRESET;
   1774      1.11      fvdl 			bmov	CCSCBRAM, SCB_CONTROL, SCB_32BYTE_SIZE;
   1775      1.11      fvdl 			or	CCSCBCTL, CCSCBEN|CCSCBRESET;
   1776      1.11      fvdl 			test	CCSCBCTL, CCSCBDONE jz .;
   1777      1.11      fvdl 		} else {
   1778      1.11      fvdl 			mvi	CCSCBCTL, CCARREN|CCSCBEN|CCSCBRESET;
   1779      1.11      fvdl 			cmp	CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN jne .;
   1780      1.11      fvdl 		}
   1781      1.11      fvdl dma_scb_finish:
   1782      1.11      fvdl 		clr	CCSCBCTL;
   1783      1.11      fvdl 		test	CCSCBCTL, CCARREN|CCSCBEN jnz .;
   1784      1.11      fvdl 		ret;
   1785      1.11      fvdl 	} else {
   1786      1.11      fvdl 		mvi	DINDEX, HADDR;
   1787      1.11      fvdl 		mvi	HSCB_ADDR call set_64byte_addr;
   1788      1.11      fvdl 		mvi	HCNT[0], SCB_32BYTE_SIZE;
   1789      1.11      fvdl 		clr	HCNT[1];
   1790      1.11      fvdl 		clr	HCNT[2];
   1791      1.11      fvdl 		mov	DFCNTRL, DMAPARAMS;
   1792      1.11      fvdl 		test	DMAPARAMS, DIRECTION	jnz dma_scb_fromhost;
   1793      1.11      fvdl 		/* Fill it with the SCB data */
   1794      1.11      fvdl copy_scb_tofifo:
   1795      1.11      fvdl 		mvi	SINDEX, SCB_CONTROL;
   1796      1.11      fvdl 		add	A, SCB_32BYTE_SIZE, SINDEX;
   1797      1.11      fvdl copy_scb_tofifo_loop:
   1798      1.11      fvdl 		mov	DFDAT,SINDIR;
   1799      1.11      fvdl 		mov	DFDAT,SINDIR;
   1800      1.11      fvdl 		mov	DFDAT,SINDIR;
   1801      1.11      fvdl 		mov	DFDAT,SINDIR;
   1802      1.11      fvdl 		mov	DFDAT,SINDIR;
   1803      1.11      fvdl 		mov	DFDAT,SINDIR;
   1804      1.11      fvdl 		mov	DFDAT,SINDIR;
   1805      1.11      fvdl 		cmp	SINDEX, A jne copy_scb_tofifo_loop;
   1806      1.11      fvdl 		or	DFCNTRL, HDMAEN|FIFOFLUSH;
   1807      1.11      fvdl dma_scb_fromhost:
   1808      1.11      fvdl 		call	dma_finish;
   1809      1.11      fvdl 		/* If we were putting the SCB, we are done */
   1810      1.11      fvdl 		test	DMAPARAMS, DIRECTION	jz	return;
   1811      1.11      fvdl 		mvi	SCB_CONTROL  call dfdat_in_7;
   1812      1.11      fvdl 		call	dfdat_in_7_continued;
   1813      1.11      fvdl 		call	dfdat_in_7_continued;
   1814      1.11      fvdl 		jmp	dfdat_in_7_continued;
   1815      1.11      fvdl dfdat_in_7:
   1816      1.11      fvdl 		mov     DINDEX,SINDEX;
   1817      1.11      fvdl dfdat_in_7_continued:
   1818      1.11      fvdl 		mov	DINDIR,DFDAT;
   1819      1.11      fvdl 		mov	DINDIR,DFDAT;
   1820      1.11      fvdl 		mov	DINDIR,DFDAT;
   1821      1.11      fvdl 		mov	DINDIR,DFDAT;
   1822      1.11      fvdl 		mov	DINDIR,DFDAT;
   1823      1.11      fvdl 		mov	DINDIR,DFDAT;
   1824      1.11      fvdl 		mov	DINDIR,DFDAT ret;
   1825      1.11      fvdl 	}
   1826      1.11      fvdl 
   1827       1.2   mycroft 
   1828       1.2   mycroft /*
   1829      1.11      fvdl  * Wait for DMA from host memory to data FIFO to complete, then disable
   1830      1.11      fvdl  * DMA and wait for it to acknowledge that it's off.
   1831       1.2   mycroft  */
   1832      1.11      fvdl dma_finish:
   1833      1.11      fvdl 	test	DFSTATUS,HDONE	jz dma_finish;
   1834      1.11      fvdl 	/* Turn off DMA */
   1835      1.11      fvdl 	and	DFCNTRL, ~HDMAEN;
   1836      1.11      fvdl 	test	DFCNTRL, HDMAEN jnz .;
   1837      1.11      fvdl 	ret;
   1838      1.11      fvdl 
   1839      1.11      fvdl add_scb_to_free_list:
   1840      1.11      fvdl 	if ((ahc->flags & AHC_PAGESCBS) != 0) {
   1841      1.11      fvdl 		mov	SCB_NEXT, FREE_SCBH;
   1842      1.11      fvdl 		mvi	SCB_TAG, SCB_LIST_NULL;
   1843      1.11      fvdl 		mov	FREE_SCBH, SCBPTR ret;
   1844      1.11      fvdl 	} else {
   1845      1.11      fvdl 		mvi	SCB_TAG, SCB_LIST_NULL ret;
   1846      1.11      fvdl 	}
   1847      1.11      fvdl 
   1848      1.11      fvdl if ((ahc->flags & AHC_PAGESCBS) != 0) {
   1849      1.11      fvdl get_free_or_disc_scb:
   1850      1.11      fvdl 	cmp	FREE_SCBH, SCB_LIST_NULL jne dequeue_free_scb;
   1851      1.11      fvdl 	cmp	DISCONNECTED_SCBH, SCB_LIST_NULL jne dequeue_disc_scb;
   1852      1.11      fvdl return_error:
   1853      1.11      fvdl 	mvi	SINDEX, SCB_LIST_NULL	ret;
   1854      1.11      fvdl dequeue_disc_scb:
   1855      1.11      fvdl 	mov	SCBPTR, DISCONNECTED_SCBH;
   1856      1.11      fvdl dma_up_scb:
   1857      1.11      fvdl 	mvi	DMAPARAMS, FIFORESET;
   1858      1.11      fvdl 	mov	SCB_TAG		call dma_scb;
   1859      1.11      fvdl unlink_disc_scb:
   1860      1.11      fvdl 	mov	DISCONNECTED_SCBH, SCB_NEXT ret;
   1861      1.11      fvdl dequeue_free_scb:
   1862      1.11      fvdl 	mov	SCBPTR, FREE_SCBH;
   1863      1.11      fvdl 	mov	FREE_SCBH, SCB_NEXT ret;
   1864      1.11      fvdl }
   1865       1.2   mycroft 
   1866      1.11      fvdl add_scb_to_disc_list:
   1867       1.2   mycroft /*
   1868      1.11      fvdl  * Link this SCB into the DISCONNECTED list.  This list holds the
   1869      1.11      fvdl  * candidates for paging out an SCB if one is needed for a new command.
   1870      1.11      fvdl  * Modifying the disconnected list is a critical(pause dissabled) section.
   1871       1.2   mycroft  */
   1872      1.11      fvdl 	mov	SCB_NEXT, DISCONNECTED_SCBH;
   1873      1.11      fvdl 	mov	DISCONNECTED_SCBH, SCBPTR ret;
   1874