aic7xxx.seq revision 15843
1/*+M***********************************************************************
2 *Adaptec 274x/284x/294x device driver for Linux and FreeBSD.
3 *
4 *Copyright (c) 1994 John Aycock
5 *  The University of Calgary Department of Computer Science.
6 *  All rights reserved.
7 *
8 *FreeBSD, Twin, Wide, 2 command per target support, tagged queuing,
9 *SCB paging and other optimizations:
10 *Copyright (c) 1994, 1995, 1996 Justin Gibbs. All rights reserved.
11 *
12 *Redistribution and use in source and binary forms, with or without
13 *modification, are permitted provided that the following conditions
14 *are met:
15 *1. Redistributions of source code must retain the above copyright
16 *   notice, this list of conditions, and the following disclaimer.
17 *2. Redistributions in binary form must reproduce the above copyright
18 *   notice, this list of conditions and the following disclaimer in the
19 *   documentation and/or other materials provided with the distribution.
20 *3. All advertising materials mentioning features or use of this software
21 *   must display the following acknowledgement:
22 *     This product includes software developed by the University of Calgary
23 *     Department of Computer Science and its contributors.
24 *4. Neither the name of the University nor the names of its contributors
25 *   may be used to endorse or promote products derived from this software
26 *   without specific prior written permission.
27 *
28 *THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
29 *ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 *IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 *ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
32 *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 *DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 *OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 *HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 *OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 *SUCH DAMAGE.
39 *
40 *-M************************************************************************/
41
42VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 1.34 1996/05/10 16:11:01 gibbs Exp $"
43
44#include "../../dev/aic7xxx/aic7xxx_reg.h"
45
46/*
47 * We can't just use ACCUM in the sequencer code because it
48 * must be treated specially by the assembler, and it currently
49 * looks for the symbol 'A'.  This is the only register defined in
50 * the assembler's symbol space.
51 */
52A = ACCUM
53
54/* After starting the selection hardware, we check for reconnecting targets
55 * as well as for our selection to complete just in case the reselection wins
56 * bus arbitration.  The problem with this is that we must keep track of the
57 * SCB that we've already pulled from the QINFIFO and started the selection
58 * on just in case the reselection wins so that we can retry the selection at
59 * a later time.  This problem cannot be resolved by holding a single entry
60 * in scratch ram since a reconnecting target can request sense and this will
61 * create yet another SCB waiting for selection.  The solution used here is to 
62 * use byte 27 of the SCB as a psuedo-next pointer and to thread a list
63 * of SCBs that are awaiting selection.  Since 0-0xfe are valid SCB offsets, 
64 * SCB_LIST_NULL is 0xff which is out of range.  The kernel driver must
65 * add an entry to this list everytime a request sense occurs.  The sequencer
66 * will automatically consume the entries.
67 */
68
69/*
70 * We assume that the kernel driver may reset us at any time, even in the
71 * middle of a DMA, so clear DFCNTRL too.
72 */
73reset:
74	clr	DFCNTRL
75	clr	SCSISIGO		/* De-assert BSY */
76/*
77 * We jump to start after every bus free.
78 */
79start:
80	and	FLAGS,0x0f		/* clear target specific flags */
81	mvi	SCSISEQ,ENRSELI		/* Always allow reselection */
82poll_for_work:
83	/*
84	 * Are we a twin channel device?
85	 * For fairness, we check the other bus first,
86	 * since we just finished a transaction on the
87	 * current channel.
88	 */
89	test	FLAGS,TWIN_BUS	jz start2
90	xor	SBLKCTL,SELBUSB			/* Toggle to the other bus */
91	test	SSTAT0,SELDI	jnz reselect
92	xor	SBLKCTL,SELBUSB			/* Toggle to the original bus */
93start2:
94	test	SSTAT0,SELDI	jnz reselect
95	cmp	WAITING_SCBH,SCB_LIST_NULL jne start_waiting
96	mov	A, QCNTMASK
97	test	QINCNT,A	jz poll_for_work
98
99/*
100 * We have at least one queued SCB now and we don't have any 
101 * SCBs in the list of SCBs awaiting selection.  Set the SCB
102 * pointer from the FIFO so we see the right bank of SCB 
103 * registers.
104 */
105	mov	SCBPTR,QINFIFO
106
107/*
108 * See if there is not already an active SCB for this target.  This code
109 * locks out on a per target basis instead of target/lun.  Although this
110 * is not ideal for devices that have multiple luns active at the same
111 * time, it is faster than looping through all SCB's looking for active
112 * commands.  It may be benificial to make findscb a more general procedure
113 * to see if the added cost of the search is negligible.  This code also 
114 * assumes that the kernel driver will clear the active flags on board 
115 * initialization, board reset, and a target SELTO.  Tagged commands
116 * don't set the active bits since you can queue more than one command
117 * at a time.  We do, however, look to see if there are any non-tagged
118 * I/Os in progress, and requeue the command if there are.  Tagged and
119 * non-tagged commands cannot be mixed to a single target.
120 */
121
122test_busy:
123	mov	FUNCTION1,SCB_TCL
124	mov	A,FUNCTION1
125	test	SCB_TCL,0x88	jz test_a	/* Id < 8 && A channel */
126
127	test	ACTIVE_B,A	jnz requeue
128	test	SCB_CONTROL,TAG_ENB	jnz start_scb
129	/* Mark the current target as busy */
130	or	ACTIVE_B,A
131	jmp	start_scb
132
133/* Place the currently active SCB back on the queue for later processing */
134requeue:
135	mov	QINFIFO, SCBPTR
136	jmp	poll_for_work
137
138/*
139 * Pull the first entry off of the waiting for selection list
140 * We don't have to "test_busy" because only transactions that
141 * have passed that test can be in the waiting_scb list.
142 */
143start_waiting:
144	mov	SCBPTR,WAITING_SCBH
145	jmp	start_scb2
146
147test_a:
148	test	ACTIVE_A,A jnz requeue
149	test	SCB_CONTROL,TAG_ENB jnz start_scb
150	/* Mark the current target as busy */
151	or	ACTIVE_A,A
152
153start_scb:
154	mov	SCB_NEXT,WAITING_SCBH
155	mov	WAITING_SCBH, SCBPTR
156start_scb2:
157	and	SINDEX,0xf7,SBLKCTL	/* Clear the channel select bit */
158	and	A,0x08,SCB_TCL		/* Get new channel bit */
159	or	SINDEX,A
160	mov	SBLKCTL,SINDEX		/* select channel */
161	mov	SCB_TCL	call initialize_scsiid
162
163/*
164 * Enable selection phase as an initiator, and do automatic ATN
165 * after the selection.  We do this now so that we can overlap the
166 * rest of our work to set up this target with the arbitration and
167 * selection bus phases.
168 */
169start_selection:
170	mvi	SCSISEQ,0x58		/* ENSELO|ENAUTOATNO|ENRSELI */
171
172/*
173 * As soon as we get a successful selection, the target should go
174 * into the message out phase since we have ATN asserted.  Prepare
175 * the message to send.
176 *
177 * Messages are stored in scratch RAM starting with a length byte
178 * followed by the message itself.
179 */
180	test	SCB_CMDLEN,0xff jnz mk_identify	/* 0 Length Command? */
181
182/*
183 * The kernel has sent us an SCB with no command attached.  This implies
184 * that the kernel wants to send a message of some sort to this target,
185 * so we interrupt the driver, allow it to fill the message buffer, and
186 * then go back into the arbitration loop
187 */
188	mvi     INTSTAT,AWAITING_MSG
189	jmp     wait_for_selection
190
191mk_identify:
192	and	A,DISCENB,SCB_CONTROL	/* mask off disconnect privledge */
193
194	and	MSG0,0x7,SCB_TCL	/* lun */
195	or	MSG0,A			/* or in disconnect privledge */
196	or	MSG0,MSG_IDENTIFY
197	mvi	MSG_LEN, 1
198
199	test	SCB_CONTROL,0xb0 jz  !message	/* WDTR, SDTR or TAG?? */
200/*
201 * Send a tag message if TAG_ENB is set in the SCB control block.
202 * Use SCB_TAG (the position in the kernel's SCB array) as the tag value.
203 */
204
205mk_tag:
206	mvi	DINDEX, MSG1
207	test	SCB_CONTROL,TAG_ENB jz mk_tag_done
208	and	DINDIR,0x23,SCB_CONTROL
209	mov	DINDIR,SCB_TAG
210
211	add	MSG_LEN,COMP_MSG0,DINDEX	/* update message length */
212
213mk_tag_done:
214
215	test	SCB_CONTROL,0x90 jz !message	/* NEEDWDTR|NEEDSDTR */
216	mov	DINDEX	call mk_dtr	/* build DTR message if needed */
217
218!message:
219wait_for_selection:
220	test	SSTAT0,SELDO	jnz select 
221	test	SSTAT0,SELDI	jz wait_for_selection
222
223/*
224 * Reselection has been initiated by a target. Make a note that we've been
225 * reselected, but haven't seen an IDENTIFY message from the target
226 * yet.
227 */
228reselect:
229	clr	MSG_LEN		/* Don't have anything in the mesg buffer */
230	mov	SELID		call initialize_scsiid
231	or	FLAGS,RESELECTED
232	jmp	select2
233
234/*
235 * After the selection, remove this SCB from the "waiting for selection"
236 * list.  This is achieved by simply moving our "next" pointer into
237 * WAITING_SCBH.  Our next pointer will be set to null the next time this
238 * SCB is used, so don't bother with it now.
239 */
240select:
241	mov	WAITING_SCBH,SCB_NEXT
242	or	FLAGS,SELECTED
243select2:
244/*
245 * Set CLRCHN here before the target has entered a data transfer mode -
246 * with synchronous SCSI, if you do it later, you blow away some
247 * data in the SCSI FIFO that the target has already sent to you.
248 */
249	or	SXFRCTL0,CLRCHN
250/*
251 * Initialize SCSIRATE with the appropriate value for this target.
252 */
253	call	ndx_dtr
254	mov	SCSIRATE,SINDIR
255
256/*
257 * Initialize Ultra mode setting.  ndx_dtr has left our target mask
258 * in A.
259 */
260	and	SINDEX,0xdf,SXFRCTL0		/* default to Ultra disabled */
261	test	SCSIID, 0x80	 jnz ultra_b	/* Target ID > 7 */
262	test	SBLKCTL, SELBUSB jnz ultra_b	/* Second channel device */
263	test	ULTRA_ENB,A	 jz  set_sxfrctl0
264	or	SINDEX, ULTRAEN  jmp set_sxfrctl0
265ultra_b:
266	test	ULTRA_ENB_B,A	 jz  set_sxfrctl0
267	or	SINDEX, ULTRAEN
268
269set_sxfrctl0:
270	mov	SXFRCTL0,SINDEX
271
272	mvi	SCSISEQ,ENAUTOATNP		/*
273						 * ATN on parity errors
274						 * for "in" phases
275						 */
276	mvi	CLRSINT1,CLRBUSFREE
277	mvi	CLRSINT0,0x60			/* CLRSELDI|CLRSELDO */
278/*
279 * Main loop for information transfer phases.  If BSY is false, then
280 * we have a bus free condition, expected or not.  Otherwise, wait
281 * for the target to assert REQ before checking MSG, C/D and I/O
282 * for the bus phase.
283 *
284 */
285ITloop:
286	test	SSTAT1,BUSFREE	jnz p_busfree
287	test	SSTAT1,REQINIT	jz ITloop
288
289	and	A,PHASE_MASK,SCSISIGI
290	mov	LASTPHASE,A
291	mov	SCSISIGO,A
292
293	cmp	ALLZEROS,A	je p_dataout
294	cmp	A,P_DATAIN	je p_datain
295	cmp	A,P_COMMAND	je p_command
296	cmp	A,P_MESGOUT	je p_mesgout
297	cmp	A,P_STATUS	je p_status
298	cmp	A,P_MESGIN	je p_mesgin
299
300	mvi	INTSTAT,BAD_PHASE	/* unknown phase - signal driver */
301	jmp	ITloop			/* Try reading the bus again. */
302
303p_dataout:
304	mvi	DMAPARAMS,0x7d			/*
305						 * WIDEODD|SCSIEN|SDMAEN|HDMAEN|
306						 * DIRECTION|FIFORESET
307						 */
308	jmp	data_phase_init
309
310/*
311 * If we re-enter the data phase after going through another phase, the
312 * STCNT may have been cleared, so restore it from the residual field.
313 */
314data_phase_reinit:
315	mov	STCNT0,SCB_RESID_DCNT0
316	mov	STCNT1,SCB_RESID_DCNT1
317	mov	STCNT2,SCB_RESID_DCNT2
318	jmp	data_phase_loop
319
320p_datain:
321	mvi	DMAPARAMS,0x79		/*
322					 * WIDEODD|SCSIEN|SDMAEN|HDMAEN|
323					 * !DIRECTION|FIFORESET
324					 */
325data_phase_init:
326	call	assert
327
328	test	FLAGS, DPHASE	jnz data_phase_reinit
329	call	sg_scb2ram
330	or	FLAGS, DPHASE		/* We have seen a data phase */
331
332data_phase_loop:
333/* If we are the last SG block, don't set wideodd. */
334	cmp	SG_COUNT,0x01 jne data_phase_wideodd
335	and	DMAPARAMS, 0xbf		/* Turn off WIDEODD */
336data_phase_wideodd:
337	mov	DMAPARAMS  call dma
338
339/* Exit if we had an underrun */
340	test	SSTAT0,SDONE	jz data_phase_finish /* underrun STCNT != 0 */
341
342/*
343 * Advance the scatter-gather pointers if needed 
344 */
345sg_advance:
346	dec	SG_COUNT	/* one less segment to go */
347
348	test	SG_COUNT, 0xff	jz data_phase_finish /* Are we done? */
349
350	clr	A			/* add sizeof(struct scatter) */
351	add	SG_NEXT0,SG_SIZEOF,SG_NEXT0
352	adc	SG_NEXT1,A,SG_NEXT1
353
354/*
355 * Load a struct scatter and set up the data address and length.
356 * If the working value of the SG count is nonzero, then
357 * we need to load a new set of values.
358 *
359 * This, like all DMA's, assumes little-endian host data storage.
360 */
361sg_load:
362	clr	HCNT2
363	clr	HCNT1
364	mvi	HCNT0,SG_SIZEOF
365
366	mov	HADDR0,SG_NEXT0
367	mov	HADDR1,SG_NEXT1
368	mov	HADDR2,SG_NEXT2
369	mov	HADDR3,SG_NEXT3
370
371	or	DFCNTRL,0xd			/* HDMAEN|DIRECTION|FIFORESET */
372
373/*
374 * Wait for DMA from host memory to data FIFO to complete, then disable
375 * DMA and wait for it to acknowledge that it's off.
376 */
377dma_finish:
378	test	DFSTATUS,HDONE	jz dma_finish
379	/* Turn off DMA preserving WIDEODD */
380	and	DFCNTRL,WIDEODD
381dma_finish2:
382	test	DFCNTRL,HDMAENACK jnz dma_finish2
383
384/*
385 * Copy data from FIFO into SCB data pointer and data count.  This assumes
386 * that the struct scatterlist has this structure (this and sizeof(struct
387 * scatterlist) == 12 are asserted in aic7xxx.c for the Linux driver):
388 *
389 *	struct scatterlist {
390 *		char *address;		four bytes, little-endian order
391 *		...			four bytes, ignored
392 *		unsigned short length;	two bytes, little-endian order
393 *	}
394 *
395 *
396 * In FreeBSD, the scatter list entry is only 8 bytes.
397 * 
398 * struct ahc_dma_seg {
399 *       physaddr addr;                  four bytes, little-endian order
400 *       long    len;                    four bytes, little endian order
401 * };
402 */
403
404	mov	HADDR0,DFDAT
405	mov	HADDR1,DFDAT
406	mov	HADDR2,DFDAT
407	mov	HADDR3,DFDAT
408/*
409 * For Linux, we must throw away four bytes since there is a 32bit gap
410 * in the middle of a struct scatterlist.
411 */
412#ifdef __linux__
413	mov	NONE,DFDAT
414	mov	NONE,DFDAT
415	mov	NONE,DFDAT
416	mov	NONE,DFDAT
417#endif
418	mov	HCNT0,DFDAT
419	mov	HCNT1,DFDAT
420	mov	HCNT2,DFDAT
421
422/* Load STCNT as well.  It is a mirror of HCNT */
423	mov	STCNT0,HCNT0
424	mov	STCNT1,HCNT1
425	mov	STCNT2,HCNT2
426        test    SSTAT1,PHASEMIS  jz data_phase_loop
427
428data_phase_finish:
429/*
430 * After a DMA finishes, save the SG and STCNT residuals back into the SCB
431 * We use STCNT instead of HCNT, since it's a reflection of how many bytes 
432 * were transferred on the SCSI (as opposed to the host) bus.
433 */
434	mov	SCB_RESID_DCNT0,STCNT0
435	mov	SCB_RESID_DCNT1,STCNT1
436	mov	SCB_RESID_DCNT2,STCNT2
437	mov	SCB_RESID_SGCNT, SG_COUNT
438	jmp	ITloop
439
440/*
441 * Command phase.  Set up the DMA registers and let 'er rip.
442 */
443p_command:
444	call	assert
445
446/*
447 * Load HADDR and HCNT.
448 */
449	mov	HADDR0, SCB_CMDPTR0
450	mov	HADDR1, SCB_CMDPTR1
451	mov	HADDR2, SCB_CMDPTR2
452	mov	HADDR3, SCB_CMDPTR3
453	mov	HCNT0, SCB_CMDLEN
454	clr	HCNT1
455	clr	HCNT2
456
457	mov	STCNT0, HCNT0
458	mov	STCNT1, HCNT1
459	mov	STCNT2, HCNT2
460
461	mvi	0x3d		call dma	# SCSIEN|SDMAEN|HDMAEN|
462						#   DIRECTION|FIFORESET
463	jmp	ITloop
464
465/*
466 * Status phase.  Wait for the data byte to appear, then read it
467 * and store it into the SCB.
468 */
469p_status:
470	mvi	SCB_TARGET_STATUS	call inb_first
471	jmp	mesgin_done
472
473/*
474 * Message out phase.  If there is not an active message, but the target
475 * took us into this phase anyway, build a no-op message and send it.
476 */
477p_mesgout:
478	test	MSG_LEN, 0xff	jnz  p_mesgout_start
479	mvi	MSG_NOP		call mk_mesg	/* build NOP message */
480
481p_mesgout_start:
482/*
483 * Set up automatic PIO transfer from MSG0.  Bit 3 in
484 * SXFRCTL0 (SPIOEN) is already on.
485 */
486	mvi	SINDEX,MSG0
487	mov	DINDEX,MSG_LEN
488
489/*
490 * When target asks for a byte, drop ATN if it's the last one in
491 * the message.  Otherwise, keep going until the message is exhausted.
492 *
493 * Keep an eye out for a phase change, in case the target issues
494 * a MESSAGE REJECT.
495 */
496p_mesgout_loop:
497	test	SSTAT1,PHASEMIS	jnz p_mesgout_phasemis
498	test	SSTAT0,SPIORDY	jz p_mesgout_loop
499	cmp	DINDEX,1	jne p_mesgout_outb	/* last byte? */
500	mvi	CLRSINT1,CLRATNO			/* drop ATN */
501p_mesgout_outb:
502	dec	DINDEX
503	or	CLRSINT0, CLRSPIORDY
504	mov	SCSIDATL,SINDIR
505	
506p_mesgout4:
507	test	DINDEX,0xff	jnz p_mesgout_loop
508
509/*
510 * If the next bus phase after ATN drops is a message out, it means
511 * that the target is requesting that the last message(s) be resent.
512 */
513p_mesgout_snoop:
514	test	SSTAT1,BUSFREE	jnz p_mesgout_done
515	test	SSTAT1,REQINIT	jz p_mesgout_snoop
516
517	test	SSTAT1,PHASEMIS	jnz p_mesgout_done
518
519	or	SCSISIGO,ATNO			/* turn on ATNO */
520
521	jmp	ITloop
522
523p_mesgout_phasemis:
524	mvi	CLRSINT1,CLRATNO	/* Be sure to turn ATNO off */
525p_mesgout_done:
526	clr	MSG_LEN			/* no active msg */
527	jmp	ITloop
528
529/*
530 * Message in phase.  Bytes are read using Automatic PIO mode.
531 */
532p_mesgin:
533	mvi	A		call inb_first	/* read the 1st message byte */
534	mov	REJBYTE,A			/* save it for the driver */
535
536	test	A,MSG_IDENTIFY		jnz mesgin_identify
537	cmp	A,MSG_DISCONNECT	je mesgin_disconnect
538	cmp	A,MSG_SDPTRS		je mesgin_sdptrs
539	cmp	ALLZEROS,A		je mesgin_complete
540	cmp	A,MSG_RDPTRS		je mesgin_rdptrs
541	cmp	A,MSG_EXTENDED		je mesgin_extended
542	cmp	A,MSG_REJECT		je mesgin_reject
543
544rej_mesgin:
545/*
546 * We have no idea what this message in is, and there's no way
547 * to pass it up to the kernel, so we issue a message reject and
548 * hope for the best.  Since we're now using manual PIO mode to
549 * read in the message, there should no longer be a race condition
550 * present when we assert ATN.  In any case, rejection should be a
551 * rare occurrence - signal the driver when it happens.
552 */
553	or	SCSISIGO,ATNO			/* turn on ATNO */
554	mvi	INTSTAT,SEND_REJECT		/* let driver know */
555
556	mvi	MSG_REJECT	call mk_mesg
557
558mesgin_done:
559	call	inb_last			/*ack & turn auto PIO back on*/
560	jmp	ITloop
561
562
563mesgin_complete:
564/*
565 * We got a "command complete" message, so put the SCB_TAG into QUEUEOUT,
566 * and trigger a completion interrupt.  Check status for non zero return
567 * and interrupt driver if needed.  This allows the driver to interpret
568 * errors only when they occur instead of always uploading the scb.  If
569 * the status is SCSI_CHECK, the driver will download a new scb requesting
570 * sense to replace the old one, modify the "waiting for selection" SCB list
571 * and set RETURN_1 to SEND_SENSE.  If RETURN_1 is set to SEND_SENSE the
572 * sequencer imediately jumps to main loop where it will run down the waiting
573 * SCB list and process the sense request.  If the kernel driver does not
574 * wish to request sense, it need only clear RETURN_1, and the command is
575 * allowed to complete.  We don't bother to post to the QOUTFIFO in the
576 * error case since it would require extra work in the kernel driver to
577 * ensure that the entry was removed before the command complete code tried
578 * processing it.
579 *
580 * First check for residuals
581 */
582	test	SCB_RESID_SGCNT,0xff	jz check_status
583/*
584 * If we have a residual count, interrupt and tell the host.  Other
585 * alternatives are to pause the sequencer on all command completes (yuck),
586 * dma the resid directly to the host (slick, we may have space to do it now)
587 * or have the sequencer pause itself when it encounters a non-zero resid 
588 * (unecessary pause just to flag the command -yuck-, but takes one instruction
589 * and since it shouldn't happen that often is good enough for our purposes).  
590 */
591resid:
592	mvi	INTSTAT,RESIDUAL
593
594check_status:
595	test	SCB_TARGET_STATUS,0xff	jz status_ok	/* Good Status? */
596	mvi	INTSTAT,BAD_STATUS			/* let driver know */
597	cmp	RETURN_1, SEND_SENSE	jne status_ok
598	jmp	mesgin_done
599
600status_ok:
601/* First, mark this target as free. */
602	test	SCB_CONTROL,TAG_ENB jnz test_immediate	/*
603							 * Tagged commands
604							 * don't busy the
605							 * target.
606							 */
607	mov	FUNCTION1,SCB_TCL
608	mov	A,FUNCTION1
609	test	SCB_TCL,0x88 jz clear_a
610	xor	ACTIVE_B,A
611	jmp	test_immediate
612
613clear_a:
614	xor	ACTIVE_A,A
615
616test_immediate:
617	test    SCB_CMDLEN,0xff jnz complete  /* Immediate message complete */
618/*
619 * Pause the sequencer until the driver gets around to handling the command
620 * complete.  This is so that any action that might require carefull timing
621 * with the completion of this command can occur.
622 */
623	mvi	INTSTAT,IMMEDDONE
624	jmp	start
625complete:
626	mov	QOUTFIFO,SCB_TAG
627	mvi	INTSTAT,CMDCMPLT
628	jmp	mesgin_done
629
630
631/*
632 * Is it an extended message?  We only support the synchronous and wide data
633 * transfer request messages, which will probably be in response to
634 * WDTR or SDTR message outs from us.  If it's not SDTR or WDTR, reject it -
635 * apparently this can be done after any message in byte, according
636 * to the SCSI-2 spec.
637 */
638mesgin_extended:
639	mvi	ARG_1		call inb_next	/* extended message length */
640	mvi	REJBYTE_EXT	call inb_next	/* extended message code */
641
642	cmp	REJBYTE_EXT,MSG_SDTR	je p_mesginSDTR
643	cmp	REJBYTE_EXT,MSG_WDTR	je p_mesginWDTR
644	jmp	rej_mesgin
645
646p_mesginWDTR:
647	cmp	ARG_1,2		jne rej_mesgin	/* extended mesg length=2 */
648	mvi	ARG_1		call inb_next	/* Width of bus */
649	mvi	INTSTAT,WDTR_MSG		/* let driver know */
650	test	RETURN_1,0xff jz mesgin_done	/* Do we need to send WDTR? */
651	cmp	RETURN_1,SEND_REJ je rej_mesgin /*
652						 * Bus width was too large 
653						 * Reject it.
654						 */
655
656/* We didn't initiate the wide negotiation, so we must respond to the request */
657	and	RETURN_1,0x7f			/* Clear the SEND_WDTR Flag */
658	mvi	DINDEX,MSG0
659	mvi	MSG0	call mk_wdtr		/* build WDTR message */
660	or	SCSISIGO,ATNO			/* turn on ATNO */
661	jmp	mesgin_done
662
663p_mesginSDTR:
664	cmp	ARG_1,3		jne rej_mesgin	/* extended mesg length=3 */
665	mvi	ARG_1		call inb_next	/* xfer period */
666	mvi	A		call inb_next	/* REQ/ACK offset */
667	mvi	INTSTAT,SDTR_MSG		/* call driver to convert */
668
669	test	RETURN_1,0xff	jz mesgin_done  /* Do we need to mk_sdtr/rej */
670	cmp	RETURN_1,SEND_REJ je rej_mesgin /*
671						 * Requested SDTR too small
672						 * Reject it.
673						 */
674	clr	ARG_1				/* Use the scratch ram rate */
675	mvi	DINDEX, MSG0
676	mvi     MSG0     call mk_sdtr
677	or	SCSISIGO,ATNO			/* turn on ATNO */
678	jmp	mesgin_done
679
680/*
681 * Is it a disconnect message?  Set a flag in the SCB to remind us
682 * and await the bus going free.
683 */
684mesgin_disconnect:
685	or	SCB_CONTROL,DISCONNECTED
686	test	FLAGS, PAGESCBS jz mesgin_done
687/*
688 * Link this SCB into the DISCONNECTED list.  This list holds the
689 * candidates for paging out an SCB if one is needed for a new command.
690 * Modifying the disconnected list is a critical(pause dissabled) section.
691 */
692	mvi	SCB_PREV, SCB_LIST_NULL
693	mvi	SEQCTL,0x50			/* PAUSEDIS|FASTMODE */
694	mov	SCB_NEXT, DISCONNECTED_SCBH
695	mov	DISCONNECTED_SCBH, SCBPTR
696	cmp	SCB_NEXT,SCB_LIST_NULL je linkdone
697	mov	SCBPTR,SCB_NEXT
698	mov	SCB_PREV,DISCONNECTED_SCBH
699	mov	SCBPTR,DISCONNECTED_SCBH
700linkdone:
701	mvi	SEQCTL,0x10			/* !PAUSEDIS|FASTMODE */
702	jmp	mesgin_done
703
704/*
705 * Save data pointers message?  Copy working values into the SCB,
706 * usually in preparation for a disconnect.
707 */
708mesgin_sdptrs:
709	call	sg_ram2scb
710	jmp	mesgin_done
711
712/*
713 * Restore pointers message?  Data pointers are recopied from the
714 * SCB anytime we enter a data phase for the first time, so all
715 * we need to do is clear the DPHASE flag and let the data phase
716 * code do the rest.
717 */
718mesgin_rdptrs:
719	and	FLAGS,0xef			/*
720						 * !DPHASE we'll reload them
721						 * the next time through
722						 */
723	jmp	mesgin_done
724
725/*
726 * Identify message?  For a reconnecting target, this tells us the lun
727 * that the reconnection is for - find the correct SCB and switch to it,
728 * clearing the "disconnected" bit so we don't "find" it by accident later.
729 */
730mesgin_identify:
731	test	A,0x78	jnz rej_mesgin	/*!DiscPriv|!LUNTAR|!Reserved*/
732
733	and	A,0x07			/* lun in lower three bits */
734	or      SAVED_TCL,A,SELID          
735	and     SAVED_TCL,0xf7
736	and     A,SELBUSB,SBLKCTL	/* B Channel?? */
737	or      SAVED_TCL,A
738	call	inb_last		/* ACK */
739
740/*
741 * Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message.
742 * If we get one, we use the tag returned to switch to find the proper
743 * SCB.  With SCB paging, this requires using findSCB for both tagged
744 * and non-tagged transactions since the SCB may exist in any slot.
745 * If we're not using SCB paging, we can use the tag as the direct
746 * index to the SCB.
747 */
748	mvi	ARG_1,SCB_LIST_NULL	/* Default to no-tag */
749snoop_tag_loop:
750	test	SSTAT1,BUSFREE	jnz use_findSCB
751	test	SSTAT1,REQINIT	jz snoop_tag_loop
752	test	SSTAT1,PHASEMIS	jnz use_findSCB
753	mvi	A		call inb_first
754	cmp	A,MSG_SIMPLE_TAG jne use_findSCB
755get_tag:
756	mvi	ARG_1	call inb_next	/* tag value */
757/*
758 * See if the tag is in range.  The tag is < SCBCOUNT if we add
759 * the complement of SCBCOUNT to the incomming tag and there is
760 * no carry.
761 */
762	mov	A,COMP_SCBCOUNT	
763	add	SINDEX,A,ARG_1
764	jc	abort_tag
765
766/*
767 * Ensure that the SCB the tag points to is for an SCB transaction
768 * to the reconnecting target.
769 */
770	test	FLAGS, PAGESCBS	jz index_by_tag
771	call	inb_last			/* Ack Tag */
772use_findSCB:
773	mov	ALLZEROS	call findSCB	  /* Have to search */
774setup_SCB:
775	and	SCB_CONTROL,0xfb	  /* clear disconnect bit in SCB */
776	or	FLAGS,IDENTIFY_SEEN	  /* make note of IDENTIFY */
777	jmp	ITloop
778index_by_tag:
779	mov	SCBPTR,ARG_1
780	mov	A,SAVED_TCL
781	cmp	SCB_TCL,A		jne abort_tag
782	test	SCB_CONTROL,TAG_ENB	jz  abort_tag
783	call	inb_last			/* Ack Successful tag */
784	jmp	setup_SCB
785
786abort_tag:
787	or	SCSISIGO,ATNO			/* turn on ATNO */
788	mvi	INTSTAT,ABORT_TAG 		/* let driver know */
789	mvi	MSG_ABORT_TAG	call mk_mesg	/* ABORT TAG message */
790	jmp	mesgin_done
791
792/*
793 * Message reject?  Let the kernel driver handle this.  If we have an 
794 * outstanding WDTR or SDTR negotiation, assume that it's a response from 
795 * the target selecting 8bit or asynchronous transfer, otherwise just ignore 
796 * it since we have no clue what it pertains to.
797 */
798mesgin_reject:
799	mvi	INTSTAT, REJECT_MSG
800	jmp	mesgin_done
801
802/*
803 * [ ADD MORE MESSAGE HANDLING HERE ]
804 */
805
806/*
807 * Bus free phase.  It might be useful to interrupt the device
808 * driver if we aren't expecting this.  For now, make sure that
809 * ATN isn't being asserted and look for a new command.
810 */
811p_busfree:
812	mvi	CLRSINT1,CLRATNO
813	clr	LASTPHASE
814
815/*
816 * if this is an immediate command, perform a psuedo command complete to
817 * notify the driver.
818 */
819	test	SCB_CMDLEN,0xff	jz status_ok
820	jmp	start
821
822/*
823 * Locking the driver out, build a one-byte message passed in SINDEX
824 * if there is no active message already.  SINDEX is returned intact.
825 */
826mk_mesg:
827	mvi	SEQCTL,0x50			/* PAUSEDIS|FASTMODE */
828	test	MSG_LEN,0xff	jz mk_mesg1	/* Should always succeed */
829	
830	/*
831	 * Hmmm.  For some reason the mesg buffer is in use.
832	 * Tell the driver.  It should look at SINDEX to find
833	 * out what we wanted to use the buffer for and resolve
834	 * the conflict.
835	 */
836	mvi	SEQCTL,0x10			/* !PAUSEDIS|FASTMODE */
837	mvi	INTSTAT,MSG_BUFFER_BUSY
838
839mk_mesg1:
840	mvi	MSG_LEN,1		/* length = 1 */
841	mov	MSG0,SINDEX		/* 1-byte message */
842	mvi	SEQCTL,0x10	ret	/* !PAUSEDIS|FASTMODE */
843
844/*
845 * Functions to read data in Automatic PIO mode.
846 *
847 * According to Adaptec's documentation, an ACK is not sent on input from
848 * the target until SCSIDATL is read from.  So we wait until SCSIDATL is
849 * latched (the usual way), then read the data byte directly off the bus
850 * using SCSIBUSL.  When we have pulled the ATN line, or we just want to
851 * acknowledge the byte, then we do a dummy read from SCISDATL.  The SCSI
852 * spec guarantees that the target will hold the data byte on the bus until
853 * we send our ACK.
854 *
855 * The assumption here is that these are called in a particular sequence,
856 * and that REQ is already set when inb_first is called.  inb_{first,next}
857 * use the same calling convention as inb.
858 */
859
860inb_next:
861	or	CLRSINT0, CLRSPIORDY
862	mov	NONE,SCSIDATL			/*dummy read from latch to ACK*/
863inb_next_wait:
864	test	SSTAT1,PHASEMIS	jnz mesgin_phasemis
865	test	SSTAT0,SPIORDY	jz inb_next_wait /* wait for next byte */
866inb_first:
867	mov	DINDEX,SINDEX
868	mov	DINDIR,SCSIBUSL	ret		/*read byte directly from bus*/
869inb_last:
870	mov	NONE,SCSIDATL ret		/*dummy read from latch to ACK*/
871
872mesgin_phasemis:
873/*
874 * We expected to receive another byte, but the target changed phase
875 */
876	mvi	INTSTAT, MSGIN_PHASEMIS
877	jmp	ITloop
878
879/*
880 * DMA data transfer.  HADDR and HCNT must be loaded first, and
881 * SINDEX should contain the value to load DFCNTRL with - 0x3d for
882 * host->scsi, or 0x39 for scsi->host.  The SCSI channel is cleared
883 * during initialization.
884 */
885dma:
886	mov	DFCNTRL,SINDEX
887dma1:
888	test	SSTAT0,DMADONE	jnz dma3
889	test	SSTAT1,PHASEMIS	jz dma1		/* ie. underrun */
890
891/*
892 * We will be "done" DMAing when the transfer count goes to zero, or
893 * the target changes the phase (in light of this, it makes sense that
894 * the DMA circuitry doesn't ACK when PHASEMIS is active).  If we are
895 * doing a SCSI->Host transfer, the data FIFO should be flushed auto-
896 * magically on STCNT=0 or a phase change, so just wait for FIFO empty
897 * status.
898 */
899dma3:
900	test	SINDEX,DIRECTION	jnz dma5
901dma4:
902	test	DFSTATUS,FIFOEMP	jz dma4
903
904/*
905 * Now shut the DMA enables off and make sure that the DMA enables are 
906 * actually off first lest we get an ILLSADDR.
907 */
908dma5:
909	/* disable DMA, but maintain WIDEODD */
910	and	DFCNTRL,WIDEODD
911dma6:
912	test	DFCNTRL,0x38	jnz dma6  /* SCSIENACK|SDMAENACK|HDMAENACK */
913
914	ret
915
916/*
917 * Common SCSI initialization for selection and reselection.  Expects
918 * the target SCSI ID to be in the upper four bits of SINDEX, and A's
919 * contents are stomped on return.
920 */
921initialize_scsiid:
922	and	SINDEX,0xf0		/* Get target ID */
923	and	A,0x0f,SCSIID
924	or	SINDEX,A
925	mov	SCSIID,SINDEX ret
926
927/*
928 * Assert that if we've been reselected, then we've seen an IDENTIFY
929 * message.
930 */
931assert:
932	test	FLAGS,RESELECTED	jz return	/* reselected? */
933	test	FLAGS,IDENTIFY_SEEN	jnz return	/* seen IDENTIFY? */
934
935	mvi	INTSTAT,NO_IDENT 	ret	/* no - cause a kernel panic */
936
937/*
938 * Locate the SCB matching the target ID/channel/lun in SAVED_TCL, and the tag
939 * value in ARG_1.  If ARG_1 == SCB_LIST_NULL, we're looking for a non-tagged
940 * SCB.  Have the kernel print a warning message if it can't be found, and
941 * generate an ABORT/ABORT_TAG message to the target.  SINDEX should be
942 * cleared on call.
943 */
944findSCB:
945	mov	A,SAVED_TCL
946	mov	SCBPTR,SINDEX			/* switch to next SCB */
947	mvi	SEQCTL,0x50			/* PAUSEDIS|FASTMODE */
948	cmp	SCB_TCL,A	jne findSCB1 /* target ID/channel/lun match? */
949	test	SCB_CONTROL,DISCONNECTED jz findSCB1 /*should be disconnected*/
950	test	SCB_CONTROL,TAG_ENB jnz findTaggedSCB
951	cmp	ARG_1,SCB_LIST_NULL je foundSCB
952	jmp	findSCB1
953findTaggedSCB:
954	mov	A, ARG_1			/* Tag passed in ARG_1 */
955	cmp	SCB_TAG,A	jne findSCB1	/* Found it? */
956foundSCB:
957	test	FLAGS,PAGESCBS	jz foundSCB_ret
958/* Remove this SCB from the disconnection list */
959	cmp	SCB_NEXT,SCB_LIST_NULL je unlink_prev
960	mov	SAVED_LINKPTR, SCB_PREV
961	mov	SCBPTR, SCB_NEXT
962	mov	SCB_PREV, SAVED_LINKPTR
963	mov	SCBPTR, SINDEX
964unlink_prev:
965	cmp	SCB_PREV,SCB_LIST_NULL	je rHead/* At the head of the list */
966	mov	SAVED_LINKPTR, SCB_NEXT
967	mov	SCBPTR, SCB_PREV
968	mov	SCB_NEXT, SAVED_LINKPTR
969	mov	SCBPTR, SINDEX
970	mvi	SEQCTL,0x10	ret		/* !PAUSEDIS|FASTMODE */
971rHead:
972	mov	DISCONNECTED_SCBH,SCB_NEXT
973foundSCB_ret:
974	mvi	SEQCTL,0x10	ret		/* !PAUSEDIS|FASTMODE */
975
976findSCB1:
977	mvi	SEQCTL,0x10			/* !PAUSEDIS|FASTMODE */
978	inc	SINDEX
979	mov	A,SCBCOUNT
980	cmp	SINDEX,A	jne findSCB
981
982	mvi	INTSTAT,NO_MATCH		/* not found - signal kernel */
983	cmp	RETURN_1,SCB_PAGEDIN je return
984	or	SCSISIGO,ATNO			/* assert ATNO */
985	cmp	ARG_1,SCB_LIST_NULL jne find_abort_tag
986	mvi	MSG_ABORT	call mk_mesg
987	jmp	ITloop
988find_abort_tag:
989	mvi	MSG_ABORT_TAG	call mk_mesg
990	jmp	ITloop
991
992/*
993 * Make a working copy of the scatter-gather parameters from the SCB.
994 */
995sg_scb2ram:
996	mov	HADDR0, SCB_DATAPTR0
997	mov	HADDR1, SCB_DATAPTR1
998	mov	HADDR2, SCB_DATAPTR2
999	mov	HADDR3, SCB_DATAPTR3
1000	mov	HCNT0, SCB_DATACNT0
1001	mov	HCNT1, SCB_DATACNT1
1002	mov	HCNT2, SCB_DATACNT2
1003
1004	mov	STCNT0, HCNT0
1005	mov	STCNT1, HCNT1
1006	mov	STCNT2, HCNT2
1007
1008	mov	SG_COUNT,SCB_SGCOUNT
1009
1010	mov	SG_NEXT0, SCB_SGPTR0
1011	mov	SG_NEXT1, SCB_SGPTR1
1012	mov	SG_NEXT2, SCB_SGPTR2
1013	mov	SG_NEXT3, SCB_SGPTR3 ret
1014
1015/*
1016 * Copying RAM values back to SCB, for Save Data Pointers message, but
1017 * only if we've actually been into a data phase to change them.  This
1018 * protects against bogus data in scratch ram and the residual counts
1019 * since they are only initialized when we go into data_in or data_out.
1020 */
1021sg_ram2scb:
1022	test	FLAGS, DPHASE	jz return
1023	mov	SCB_SGCOUNT,SG_COUNT
1024
1025	mov	SCB_SGPTR0,SG_NEXT0
1026	mov	SCB_SGPTR1,SG_NEXT1
1027	mov	SCB_SGPTR2,SG_NEXT2
1028	mov	SCB_SGPTR3,SG_NEXT3
1029	
1030	mov	SCB_DATAPTR0,SHADDR0
1031	mov	SCB_DATAPTR1,SHADDR1
1032	mov	SCB_DATAPTR2,SHADDR2
1033	mov	SCB_DATAPTR3,SHADDR3
1034
1035/*
1036 * Use the residual number since STCNT is corrupted by any message transfer
1037 */
1038	mov	SCB_DATACNT0,SCB_RESID_DCNT0
1039	mov	SCB_DATACNT1,SCB_RESID_DCNT1
1040	mov	SCB_DATACNT2,SCB_RESID_DCNT2 ret
1041
1042/*
1043 * Add the array base TARG_SCRATCH to the target offset (the target address
1044 * is in SCSIID), and return the result in SINDEX.  The accumulator
1045 * contains the 3->8 decoding of the target ID on return.
1046 */
1047ndx_dtr:
1048	shr	A,SCSIID,4
1049	test	SBLKCTL,SELBUSB	jz ndx_dtr_2
1050	or	A,0x08		/* Channel B entries add 8 */
1051ndx_dtr_2:
1052	add	SINDEX,TARG_SCRATCH,A ret
1053
1054/*
1055 * If we need to negotiate transfer parameters, build the WDTR or SDTR message
1056 * starting at the address passed in SINDEX.  DINDEX is modified on return.
1057 * The SCSI-II spec requires that Wide negotiation occur first and you can
1058 * only negotiat one or the other at a time otherwise in the event of a message
1059 * reject, you wouldn't be able to tell which message was the culpret.
1060 */
1061mk_dtr:
1062	test	SCB_CONTROL,NEEDWDTR jnz  mk_wdtr_16bit
1063	mvi	ARG_1, MAXOFFSET	/* Force an offset of 15 or 8 if WIDE */
1064
1065mk_sdtr:
1066	mvi	DINDIR,1		/* extended message */
1067	mvi	DINDIR,3		/* extended message length = 3 */
1068	mvi	DINDIR,1		/* SDTR code */
1069	call	sdtr_to_rate
1070	mov	DINDIR,RETURN_1		/* REQ/ACK transfer period */
1071	cmp	ARG_1, MAXOFFSET je mk_sdtr_max_offset
1072	and	DINDIR,0x0f,SINDIR	/* Sync Offset */
1073
1074mk_sdtr_done:
1075	add	MSG_LEN,COMP_MSG0,DINDEX ret	/* update message length */
1076
1077mk_sdtr_max_offset:
1078/*
1079 * We're initiating sync negotiation, so request the max offset we can (15 or 8)
1080 */
1081	/* Talking to a WIDE device? */
1082	test	SCSIRATE, WIDEXFER	jnz wmax_offset	
1083	mvi	DINDIR, MAX_OFFSET_8BIT
1084	jmp	mk_sdtr_done
1085
1086wmax_offset:
1087	mvi	DINDIR, MAX_OFFSET_16BIT
1088	jmp	mk_sdtr_done
1089
1090mk_wdtr_16bit:
1091	mvi	ARG_1,BUS_16_BIT
1092mk_wdtr:
1093	mvi	DINDIR,1		/* extended message */
1094	mvi	DINDIR,2		/* extended message length = 2 */
1095	mvi	DINDIR,3		/* WDTR code */
1096	mov	DINDIR,ARG_1		/* bus width */
1097
1098	add	MSG_LEN,COMP_MSG0,DINDEX ret	/* update message length */
1099	
1100sdtr_to_rate:
1101	call	ndx_dtr			/* index scratch space for target */
1102	shr	A,SINDIR,0x4
1103	dec	SINDEX			/* Preserve SINDEX */
1104	and	A,0x7
1105	clr	RETURN_1
1106sdtr_to_rate_loop:
1107	test	A,0x0f	jz sdtr_to_rate_done
1108	add	RETURN_1,0x19
1109	dec	A	
1110	jmp	sdtr_to_rate_loop
1111sdtr_to_rate_done:
1112	shr	RETURN_1,0x2
1113	add	RETURN_1,0x19
1114	test	SXFRCTL0,ULTRAEN jz return
1115	shr	RETURN_1,0x1
1116return:
1117	ret
1118