Home | History | Annotate | Line # | Download | only in aic7xxx
aic7xxx.seq revision 1.13
      1  1.13       wiz /*	$NetBSD: aic7xxx.seq,v 1.13 2001/08/20 12:00:52 wiz 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.13       wiz 		/* Wait for preceding 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.12       wiz  * 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