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