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