2 * Adaptec 274x/284x/294x device driver firmware for Linux and FreeBSD.
4 * Copyright (c) 1994-1999 Justin Gibbs.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
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
35 * $Id: aic7xxx.seq,v 1.77 1998/06/28 02:58:57 gibbs Exp $
38 #include "aic7xxx.reg"
39 #include "scsi_message.h"
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.
60 clr SCSISIGO; /* De-assert BSY */
61 and SXFRCTL1, ~BITBUCKET;
62 /* Always allow reselection */
63 if ((p->flags & AHC_TARGETMODE) != 0) {
64 mvi SCSISEQ, ENSELI|ENRSELI|ENAUTOATNP;
66 mvi SCSISEQ, ENRSELI|ENAUTOATNP;
69 if ((p->features & AHC_CMD_CHAN) != 0) {
70 /* Ensure that no DMA operations are in progress */
75 call clear_target_state;
77 and SXFRCTL0, ~SPIOEN;
78 if ((p->features & AHC_QUEUE_REGS) == 0) {
82 if ((p->features & AHC_QUEUE_REGS) == 0) {
83 and SEQCTL, ~PAUSEDIS;
85 test SSTAT0, SELDO|SELDI jnz selection;
86 test SCSISEQ, ENSELO jnz poll_for_work;
87 if ((p->features & AHC_TWIN) != 0) {
89 * Twin channel devices cannot handle things like SELTO
90 * interrupts on the "background" channel. So, if we
91 * are selecting, keep polling the current channel util
92 * either a selection or reselection occurs.
94 xor SBLKCTL,SELBUSB; /* Toggle to the other bus */
95 test SSTAT0, SELDO|SELDI jnz selection;
96 test SCSISEQ, ENSELO jnz poll_for_work;
97 xor SBLKCTL,SELBUSB; /* Toggle back */
99 cmp WAITING_SCBH,SCB_LIST_NULL jne start_waiting;
101 /* Has the driver posted any work for us? */
102 if ((p->features & AHC_QUEUE_REGS) != 0) {
103 test QOFF_CTLSTA, SCB_AVAIL jz poll_for_work_loop;
104 mov NONE, SNSCB_QOFF;
108 cmp KERNEL_QINPOS, A je poll_for_work_loop;
110 and SEQCTL, ~PAUSEDIS;
114 * We have at least one queued SCB now and we don't have any
115 * SCBs in the list of SCBs awaiting selection. If we have
116 * any SCBs available for use, pull the tag from the QINFIFO
117 * and get to work on it.
119 if ((p->flags & AHC_PAGESCBS) != 0) {
120 mov ALLZEROS call get_free_or_disc_scb;
125 mvi QINFIFO_OFFSET call fetch_byte;
127 if ((p->flags & AHC_PAGESCBS) == 0) {
128 /* In the non-paging case, the SCBID == hardware SCB index */
129 mov SCBPTR, RETURN_2;
133 * DMA the SCB from host ram into the current SCB location.
135 mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
136 mov RETURN_2 call dma_scb;
139 * Preset the residual fields in case we never go through a data phase.
140 * This isn't done by the host so we can avoid a DMA to clear these
141 * fields for the normal case of I/O that completes without underrun
142 * or overrun conditions.
144 if ((p->features & AHC_CMD_CHAN) != 0) {
145 bmov SCB_RESID_DCNT, SCB_DATACNT, 3;
147 mov SCB_RESID_DCNT[0],SCB_DATACNT[0];
148 mov SCB_RESID_DCNT[1],SCB_DATACNT[1];
149 mov SCB_RESID_DCNT[2],SCB_DATACNT[2];
151 mov SCB_RESID_SGCNT, SCB_SGCOUNT;
155 * Place us on the waiting list in case our selection
156 * doesn't win during bus arbitration.
158 mov SCB_NEXT,WAITING_SCBH;
159 mov WAITING_SCBH, SCBPTR;
162 * Pull the first entry off of the waiting SCB list.
164 mov SCBPTR, WAITING_SCBH;
165 call start_selection;
169 if ((p->features & AHC_TWIN) != 0) {
170 and SINDEX,~SELBUSB,SBLKCTL;/* Clear channel select bit */
171 and A,SELBUSB,SCB_TCL; /* Get new channel bit */
173 mov SBLKCTL,SINDEX; /* select channel */
176 if ((p->features & AHC_ULTRA2) != 0) {
177 and A, TID, SCB_TCL; /* Get target ID */
178 and SCSIID_ULTRA2, OID; /* Clear old target */
181 and A, TID, SCB_TCL; /* Get target ID */
182 and SCSIID, OID; /* Clear old target */
185 mvi SCSISEQ, ENSELO|ENAUTOATNO|ENRSELI|ENAUTOATNP ret;
188 * Initialize Ultra mode setting and clear the SCSI channel.
189 * SINDEX should contain any additional bit's the client wants
193 or SXFRCTL0, CLRSTCNT|CLRCHN, SINDEX;
194 if ((p->features & AHC_ULTRA) != 0) {
196 mvi SINDEX, ULTRA_ENB+1;
197 test SAVED_TCL, 0x80 jnz ultra_2; /* Target ID > 7 */
200 mov FUNCTION1,SAVED_TCL;
202 test SINDIR, A jz ndx_dtr;
206 * Initialize SCSIRATE with the appropriate value for this target.
207 * The SCSIRATE settings for each target are stored in an array
208 * based at TARG_SCSIRATE.
212 if ((p->features & AHC_TWIN) != 0) {
213 test SBLKCTL,SELBUSB jz ndx_dtr_2;
214 or SAVED_TCL, SELBUSB;
215 or A,0x08; /* Channel B entries add 8 */
219 if ((p->features & AHC_ULTRA2) != 0) {
220 add SINDEX, TARG_OFFSET, A;
221 mov SCSIOFFSET, SINDIR;
224 add SINDEX,TARG_SCSIRATE,A;
225 mov SCSIRATE,SINDIR ret;
229 test SSTAT0,SELDO jnz select_out;
231 if ((p->flags & AHC_TARGETMODE) != 0) {
232 test SSTAT0, TARGET jz initiator_reselect;
234 * We've just been selected. Assert BSY and
235 * setup the phase for receiving the messages
238 mvi SCSISIGO, P_MESGOUT|BSYO;
239 mvi CLRSINT0, CLRSELDO;
242 * If ATN isn't asserted, go directly to bus free.
244 test SCSISIGI, ATNI jz target_busfree;
247 * Setup the DMA for sending the identify and
248 * command information.
250 mov A, TMODE_CMDADDR_NEXT;
252 mvi TMODE_CMDADDR call set_32byte_addr;
253 mvi DFCNTRL, FIFORESET;
256 /* Watch ATN closely now */
259 test SSTAT0, SPIORDY jz .;
260 and SXFRCTL0, ~SPIOEN;
261 mov DINDEX, SCSIDATL;
265 /* Message Testing... */
266 test DINDEX, MSG_IDENTIFYFLAG jz . + 2;
269 test SCSISIGI, ATNI jnz message_loop;
272 mvi DFDAT, SCB_LIST_NULL; /* Terminate the message list */
278 mvi SCSISIGO, P_COMMAND|BSYO;
280 test SSTAT0, SPIORDY jz .;
282 mov DFDAT, A; /* Store for host */
285 * Determine the number of bytes to read
286 * based on the command group code. Count is
287 * one less than the total since we've already
288 * fetched the first byte.
291 shr A, CMD_GROUP_CODE_SHIFT;
294 add SINDEX, CMD_GROUP0_BYTE_DELTA;
295 nop; /* Group 1 and 2 are the same */
296 add SINDEX, CMD_GROUP2_BYTE_DELTA;
297 nop; /* Group 3 is reserved */
298 add SINDEX, CMD_GROUP4_BYTE_DELTA;
299 add SINDEX, CMD_GROUP5_BYTE_DELTA;
300 /* Group 6 and 7 are not handled yet */
306 test SSTAT0, SPIORDY jz .;
307 cmp SINDEX, 1 jne . + 2;
308 and SXFRCTL0, ~SPIOEN; /* Last Byte */
311 test SINDEX, 0xFF jnz command_loop;
313 or DFCNTRL, HDMAEN|FIFOFLUSH;
317 test ARG_1, MSG_IDENTIFY_DISCFLAG jz selectin_post;
319 mvi SCSISIGO, P_MESGIN|BSYO;
323 mvi MSG_DISCONNECT call target_outb;
326 inc TMODE_CMDADDR_NEXT;
327 cmp TMODE_CMDADDR_NEXT, TMODE_NUMCMDS jne . + 2;
328 clr TMODE_CMDADDR_NEXT;
329 mvi QOUTFIFO, SCB_LIST_NULL;
330 mvi INTSTAT,CMDCMPLT;
332 test ARG_1, MSG_IDENTIFY_DISCFLAG jnz target_busfree;
334 /* Busy loop on something then go to data or status phase */
343 * Reselection has been initiated by a target. Make a note that we've been
344 * reselected, but haven't seen an IDENTIFY message from the target yet.
347 mvi CLRSINT0, CLRSELDI;
348 /* XXX test for and handle ONE BIT condition */
349 and SAVED_TCL, SELID_MASK, SELID;
350 mvi CLRSINT1,CLRBUSFREE;
351 or SIMODE1, ENBUSFREE; /*
352 * We aren't expecting a
353 * bus free, so interrupt
354 * the kernel driver if it
357 mvi SPIOEN call initialize_channel;
358 mvi MSG_OUT, MSG_NOOP; /* No message to send */
362 * After the selection, remove this SCB from the "waiting SCB"
363 * list. This is achieved by simply moving our "next" pointer into
364 * WAITING_SCBH. Our next pointer will be set to null the next time this
365 * SCB is used, so don't bother with it now.
368 /* Turn off the selection hardware */
369 mvi SCSISEQ, ENRSELI|ENAUTOATNP; /*
370 * ATN on parity errors
373 mvi CLRSINT0, CLRSELDO;
374 mov SCBPTR, WAITING_SCBH;
375 mov WAITING_SCBH,SCB_NEXT;
376 mov SAVED_TCL, SCB_TCL;
377 mvi CLRSINT1,CLRBUSFREE;
378 or SIMODE1, ENBUSFREE; /*
379 * We aren't expecting a
380 * bus free, so interrupt
381 * the kernel driver if it
384 mvi SPIOEN call initialize_channel;
386 * As soon as we get a successful selection, the target should go
387 * into the message out phase since we have ATN asserted.
389 mvi MSG_OUT, MSG_IDENTIFYFLAG;
390 or SEQ_FLAGS, IDENTIFY_SEEN;
393 * Main loop for information transfer phases. Wait for the target
394 * to assert REQ before checking MSG, C/D and I/O for the bus phase.
401 test A, ~P_DATAIN jz p_data;
402 cmp A,P_COMMAND je p_command;
403 cmp A,P_MESGOUT je p_mesgout;
404 cmp A,P_STATUS je p_status;
405 cmp A,P_MESGIN je p_mesgin;
407 mvi INTSTAT,BAD_PHASE; /* unknown phase - signal driver */
408 jmp ITloop; /* Try reading the bus again. */
411 and SIMODE1, ~ENBUSFREE;
412 call clear_target_state;
413 mov NONE, SCSIDATL; /* Ack the last byte */
414 and SXFRCTL0, ~SPIOEN;
415 test SSTAT1,REQINIT|BUSFREE jz .;
416 test SSTAT1, BUSFREE jnz poll_for_work;
417 mvi INTSTAT, BAD_PHASE;
421 * We assume that the kernel driver may reset us
422 * at any time, even in the middle of a DMA, so
428 * We don't know the target we will connect to,
429 * so default to narrow transfers to avoid
432 if ((p->features & AHC_ULTRA2) != 0) {
433 bmov SCSIRATE, ALLZEROS, 2;
436 and SXFRCTL0, ~(FAST20);
438 mvi LASTPHASE, P_BUSFREE;
439 /* clear target specific flags */
443 * If we re-enter the data phase after going through another phase, the
444 * STCNT may have been cleared, so restore it from the residual field.
447 if ((p->features & AHC_CMD_CHAN) != 0) {
448 if ((p->features & AHC_ULTRA2) != 0) {
449 bmov HCNT, SCB_RESID_DCNT, 3;
451 bmov STCNT, SCB_RESID_DCNT, 3;
454 mvi SCB_RESID_DCNT call bcopy_3;
459 if ((p->features & AHC_ULTRA2) != 0) {
460 mvi DMAPARAMS, PRELOADEN|SCSIEN|HDMAEN;
462 mvi DMAPARAMS, WIDEODD|SCSIEN|SDMAEN|HDMAEN|FIFORESET;
464 test LASTPHASE, IOI jnz . + 2;
465 or DMAPARAMS, DIRECTION;
467 * Ensure entering a data
468 * phase is okay - seen identify, etc.
470 if ((p->features & AHC_CMD_CHAN) != 0) {
471 mvi CCSGADDR, CCSGADDR_MAX;
473 test SEQ_FLAGS, DPHASE jnz data_phase_reinit;
475 /* We have seen a data phase */
476 or SEQ_FLAGS, DPHASE;
479 * Initialize the DMA address and counter from the SCB.
480 * Also set SG_COUNT and SG_NEXT in memory since we cannot
481 * modify the values in the SCB itself until we see a
482 * save data pointers message.
484 if ((p->features & AHC_CMD_CHAN) != 0) {
485 bmov HADDR, SCB_DATAPTR, 7;
487 bmov SG_COUNT, SCB_SGCOUNT, 5;
490 mvi SCB_DATAPTR call bcopy_7;
491 call set_stcnt_from_hcnt;
492 mvi DINDEX, SG_COUNT;
493 mvi SCB_SGCOUNT call bcopy_5;
497 /* Guard against overruns */
498 test SG_COUNT, 0xff jnz data_phase_inbounds;
500 * Turn on 'Bit Bucket' mode, set the transfer count to
501 * 16meg and let the target run until it changes phase.
502 * When the transfer completes, notify the host that we
505 or SXFRCTL1,BITBUCKET;
506 and DMAPARAMS, ~(HDMAEN|SDMAEN);
507 if ((p->features & AHC_CMD_CHAN) != 0) {
508 if ((p->features & AHC_ULTRA2) != 0) {
509 bmov HCNT, ALLONES, 3;
511 bmov STCNT, ALLONES, 3;
518 /* If we are the last SG block, tell the hardware. */
519 if ((p->features & AHC_ULTRA2) == 0) {
520 cmp SG_COUNT,0x01 jne data_phase_wideodd;
521 and DMAPARAMS, ~WIDEODD;
524 if ((p->features & AHC_ULTRA2) != 0) {
526 mov DFCNTRL, DMAPARAMS;
527 test SSTAT0, SDONE jnz .;
529 test SSTAT0, SDONE jnz data_phase_dma_done;
530 test SSTAT1,PHASEMIS jz data_phase_dma_loop; /* ie. underrun */
531 data_phase_dma_phasemis:
532 test SSTAT0,SDONE jnz . + 2;
533 clr SINDEX; /* Remember the phasemiss */
535 mov DMAPARAMS call dma;
539 /* Go tell the host about any overruns */
540 test SXFRCTL1,BITBUCKET jnz data_phase_overrun;
542 /* Exit if we had an underrun. dma clears SINDEX in this case. */
543 test SINDEX,0xff jz data_phase_finish;
546 * Advance the scatter-gather pointers if needed
549 dec SG_COUNT; /* one less segment to go */
551 test SG_COUNT, 0xff jz data_phase_finish; /* Are we done? */
553 * Load a struct scatter and set up the data address and length.
554 * If the working value of the SG count is nonzero, then
555 * we need to load a new set of values.
557 * This, like all DMA's, assumes little-endian host data storage.
560 if ((p->features & AHC_CMD_CHAN) != 0) {
562 * Do we have any prefetch left???
564 cmp CCSGADDR, CCSGADDR_MAX jne prefetched_segs_avail;
567 * Fetch MIN(CCSGADDR_MAX, (SG_COUNT * 8)) bytes.
569 add A, -(CCSGRAM_MAXSEGS + 1), SG_COUNT;
574 bmov CCHADDR, SG_NEXT, 4;
575 mvi CCSGCTL, CCSGEN|CCSGRESET;
576 test CCSGCTL, CCSGDONE jz .;
577 and CCSGCTL, ~CCSGEN;
578 test CCSGCTL, CCSGEN jnz .;
579 mvi CCSGCTL, CCSGRESET;
580 prefetched_segs_avail:
581 bmov HADDR, CCSGRAM, 8;
582 if ((p->features & AHC_ULTRA2) == 0) {
587 mvi SG_NEXT call bcopy_4;
589 mvi HCNT[0],SG_SIZEOF;
593 or DFCNTRL, HDMAEN|DIRECTION|FIFORESET;
598 * Copy data from FIFO into SCB data pointer and data count.
599 * This assumes that the SG segments are of the form:
600 * struct ahc_dma_seg {
601 * u_int32_t addr; four bytes, little-endian order
602 * u_int32_t len; four bytes, little endian order
605 mvi HADDR call dfdat_in_7;
606 call set_stcnt_from_hcnt;
609 /* Advance the SG pointer */
610 clr A; /* add sizeof(struct scatter) */
611 add SG_NEXT[0],SG_SIZEOF;
614 test SSTAT1, REQINIT jz .;
615 test SSTAT1,PHASEMIS jz data_phase_loop;
617 if ((p->features & AHC_ULTRA2) != 0) {
618 mov DFCNTRL, DMAPARAMS;
619 test SSTAT0, SDONE jnz .;
624 * After a DMA finishes, save the SG and STCNT residuals back into the SCB
625 * We use STCNT instead of HCNT, since it's a reflection of how many bytes
626 * were transferred on the SCSI (as opposed to the host) bus.
628 if ((p->features & AHC_ULTRA2) != 0) {
629 call ultra2_dmafinish;
631 if ((p->features & AHC_ULTRA2) == 0) {
632 if ((p->features & AHC_CMD_CHAN) != 0) {
633 bmov SCB_RESID_DCNT, STCNT, 3;
634 mov SCB_RESID_SGCNT, SG_COUNT;
636 mov SCB_RESID_DCNT[0],STCNT[0];
637 mov SCB_RESID_DCNT[1],STCNT[1];
638 mov SCB_RESID_DCNT[2],STCNT[2];
639 mov SCB_RESID_SGCNT, SG_COUNT;
646 if ((p->features & AHC_ULTRA2) != 0) {
647 call ultra2_dmafinish;
650 * Turn off BITBUCKET mode and notify the host
652 and SXFRCTL1, ~BITBUCKET;
653 mvi INTSTAT,DATA_OVERRUN;
657 if ((p->features & AHC_ULTRA2) != 0) {
658 test DFCNTRL, DIRECTION jnz ultra2_dmahalt;
659 and DFCNTRL, ~SCSIEN;
660 test DFCNTRL, SCSIEN jnz .;
661 or DFCNTRL, FIFOFLUSH;
662 test DFSTATUS, FIFOEMP jz . - 1;
664 and DFCNTRL, ~(SCSIEN|HDMAEN);
665 test DFCNTRL, HDMAEN jnz .;
666 bmov SCB_RESID_DCNT, STCNT, 3;
667 mov SCB_RESID_SGCNT, SG_COUNT;
668 or SXFRCTL0, CLRSTCNT|CLRCHN;
673 * Command phase. Set up the DMA registers and let 'er rip.
679 * Load HADDR and HCNT.
681 if ((p->features & AHC_CMD_CHAN) != 0) {
682 bmov HADDR, SCB_CMDPTR, 5;
683 bmov HCNT[1], ALLZEROS, 2;
684 if ((p->features & AHC_ULTRA2) == 0) {
689 mvi SCB_CMDPTR call bcopy_5;
692 call set_stcnt_from_hcnt;
695 if ((p->features & AHC_ULTRA2) == 0) {
696 mvi (SCSIEN|SDMAEN|HDMAEN|DIRECTION|FIFORESET) call dma;
698 mvi DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN|DIRECTION);
699 test SSTAT0, SDONE jnz .;
701 test SSTAT0, DMADONE jnz p_command_ultra2_dma_done;
702 test SSTAT1,PHASEMIS jz p_command_dma_loop; /* ie. underrun */
703 p_command_ultra2_dma_done:
704 and DFCNTRL, ~(SCSIEN|HDMAEN);
705 test DFCNTRL, HDMAEN jnz .;
706 or SXFRCTL0, CLRSTCNT|CLRCHN;
711 * Status phase. Wait for the data byte to appear, then read it
712 * and store it into the SCB.
717 mov SCB_TARGET_STATUS, SCSIDATL;
721 * Message out phase. If MSG_OUT is 0x80, build I full indentify message
722 * sequence and send it to the target. In addition, if the MK_MESSAGE bit
723 * is set in the SCB_CONTROL byte, interrupt the host and allow it to send
726 * If MSG_OUT is == HOST_MSG, also interrupt the host and take a message.
727 * This is done to allow the hsot to send messages outside of an identify
728 * sequence while protecting the seqencer from testing the MK_MESSAGE bit
729 * on an SCB that might not be for the current nexus. (For example, a
730 * BDR message in responce to a bad reselection would leave us pointed to
731 * an SCB that doesn't have anything to do with the current target).
732 * Otherwise, treat MSG_OUT as a 1 byte message to send (abort, abort tag,
735 * When there are no messages to send, MSG_OUT should be set to MSG_NOOP,
736 * in case the target decides to put us in this phase for some strange
740 or SCSISIGO,ATNO,LASTPHASE;/* turn on ATN for the retry */
743 cmp SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host;
745 if ((p->features & AHC_WIDE) != 0) {
746 and SINDEX,0xf,SCB_TCL; /* lun */
748 and SINDEX,0x7,SCB_TCL; /* lun */
750 and A,DISCENB,SCB_CONTROL; /* mask off disconnect privledge */
751 or SINDEX,A; /* or in disconnect privledge */
752 or SINDEX,MSG_IDENTIFYFLAG;
753 p_mesgout_mk_message:
754 test SCB_CONTROL,MK_MESSAGE jz p_mesgout_tag;
755 mov SCSIDATL, SINDEX; /* Send the last byte */
756 jmp p_mesgout_from_host + 1;/* Skip HOST_MSG test */
758 * Send a tag message if TAG_ENB is set in the SCB control block.
759 * Use SCB_TAG (the position in the kernel's SCB array) as the tag value.
762 test SCB_CONTROL,TAG_ENB jz p_mesgout_onebyte;
763 mov SCSIDATL, SINDEX; /* Send the identify message */
765 cmp LASTPHASE, P_MESGOUT jne p_mesgout_done;
766 and SCSIDATL,TAG_ENB|SCB_TAG_TYPE,SCB_CONTROL;
768 cmp LASTPHASE, P_MESGOUT jne p_mesgout_done;
769 mov SCB_TAG jmp p_mesgout_onebyte;
771 * Interrupt the driver, and allow it to send a message
775 cmp SINDEX, HOST_MSG jne p_mesgout_onebyte;
776 mvi INTSTAT,AWAITING_MSG;
779 * Did the host detect a phase change?
781 cmp RETURN_1, MSGOUT_PHASEMIS je p_mesgout_done;
784 mvi CLRSINT1, CLRATNO;
785 mov SCSIDATL, SINDEX;
788 * If the next bus phase after ATN drops is a message out, it means
789 * that the target is requesting that the last message(s) be resent.
792 cmp LASTPHASE, P_MESGOUT je p_mesgout_retry;
795 mvi CLRSINT1,CLRATNO; /* Be sure to turn ATNO off */
796 mov LAST_MSG, MSG_OUT;
797 cmp MSG_OUT, MSG_IDENTIFYFLAG jne . + 2;
798 and SCB_CONTROL, ~MK_MESSAGE;
799 mvi MSG_OUT, MSG_NOOP; /* No message left */
803 * Message in phase. Bytes are read using Automatic PIO mode.
806 mvi ACCUM call inb_first; /* read the 1st message byte */
808 test A,MSG_IDENTIFYFLAG jnz mesgin_identify;
809 cmp A,MSG_DISCONNECT je mesgin_disconnect;
810 cmp A,MSG_SAVEDATAPOINTER je mesgin_sdptrs;
811 cmp ALLZEROS,A je mesgin_complete;
812 cmp A,MSG_RESTOREPOINTERS je mesgin_rdptrs;
813 cmp A,MSG_EXTENDED je mesgin_extended;
814 cmp A,MSG_MESSAGE_REJECT je mesgin_reject;
815 cmp A,MSG_NOOP je mesgin_done;
819 * We have no idea what this message in is, so we issue a message reject
820 * and hope for the best. In any case, rejection should be a rare
821 * occurrence - signal the driver when it happens.
823 mvi INTSTAT,SEND_REJECT; /* let driver know */
825 mvi MSG_MESSAGE_REJECT call mk_mesg;
828 mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
834 * We got a "command complete" message, so put the SCB_TAG into the QOUTFIFO,
835 * and trigger a completion interrupt. Before doing so, check to see if there
836 * is a residual or the status byte is something other than STATUS_GOOD (0).
837 * In either of these conditions, we upload the SCB back to the host so it can
838 * process this information. In the case of a non zero status byte, we
839 * additionally interrupt the kernel driver synchronously, allowing it to
840 * decide if sense should be retrieved. If the kernel driver wishes to request
841 * sense, it will fill the kernel SCB with a request sense command and set
842 * RETURN_1 to SEND_SENSE. If RETURN_1 is set to SEND_SENSE we redownload
843 * the SCB, and process it as the next command by adding it to the waiting list.
844 * If the kernel driver does not wish to request sense, it need only clear
845 * RETURN_1, and the command is allowed to complete normally. We don't bother
846 * to post to the QOUTFIFO in the error cases since it would require extra
847 * work in the kernel driver to ensure that the entry was removed before the
848 * command complete code tried processing it.
852 * First check for residuals
854 test SCB_RESID_SGCNT,0xff jnz upload_scb;
855 test SCB_TARGET_STATUS,0xff jz complete; /* Good Status? */
857 mvi DMAPARAMS, FIFORESET;
858 mov SCB_TAG call dma_scb;
860 test SCB_TARGET_STATUS,0xff jz complete; /* Just a residual? */
861 mvi INTSTAT,BAD_STATUS; /* let driver know */
863 cmp RETURN_1, SEND_SENSE jne complete;
864 /* This SCB becomes the next to execute as it will retrieve sense */
865 mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
866 mov SCB_TAG call dma_scb;
868 mov SCB_NEXT,WAITING_SCBH;
869 mov WAITING_SCBH, SCBPTR;
871 * Prepare our selection hardware before the busfree so we have a
872 * high probability of winning arbitration.
874 call start_selection;
878 /* If we are untagged, clear our address up in host ram */
879 test SCB_CONTROL, TAG_ENB jnz complete_post;
881 mvi UNTAGGEDSCB_OFFSET call post_byte_setup;
882 mvi SCB_LIST_NULL call post_byte;
885 /* Post the SCB and issue an interrupt */
886 if ((p->features & AHC_QUEUE_REGS) != 0) {
891 mvi QOUTFIFO_OFFSET call post_byte_setup;
892 mov SCB_TAG call post_byte;
893 if ((p->features & AHC_QUEUE_REGS) == 0) {
896 mvi INTSTAT,CMDCMPLT;
899 call add_scb_to_free_list;
903 * Is it an extended message? Copy the message to our message buffer and
904 * notify the host. The host will tell us whether to reject this message,
905 * respond to it with the message that the host placed in our message buffer,
906 * or simply to do nothing.
909 mvi INTSTAT,EXTENDED_MSG; /* let driver know */
913 * Is it a disconnect message? Set a flag in the SCB to remind us
914 * and await the bus going free.
917 or SCB_CONTROL,DISCONNECTED;
918 call add_scb_to_disc_list;
922 * Save data pointers message:
923 * Copying RAM values back to SCB, for Save Data Pointers message, but
924 * only if we've actually been into a data phase to change them. This
925 * protects against bogus data in scratch ram and the residual counts
926 * since they are only initialized when we go into data_in or data_out.
929 test SEQ_FLAGS, DPHASE jz mesgin_done;
931 * The SCB SGPTR becomes the next one we'll download,
932 * and the SCB DATAPTR becomes the current SHADDR.
933 * Use the residual number since STCNT is corrupted by
934 * any message transfer.
936 if ((p->features & AHC_CMD_CHAN) != 0) {
937 bmov SCB_SGCOUNT, SG_COUNT, 5;
938 bmov SCB_DATAPTR, SHADDR, 4;
939 bmov SCB_DATACNT, SCB_RESID_DCNT, 3;
941 mvi DINDEX, SCB_SGCOUNT;
942 mvi SG_COUNT call bcopy_5;
943 mvi DINDEX, SCB_DATAPTR;
944 mvi SHADDR call bcopy_4;
945 mvi SCB_RESID_DCNT call bcopy_3;
950 * Restore pointers message? Data pointers are recopied from the
951 * SCB anytime we enter a data phase for the first time, so all
952 * we need to do is clear the DPHASE flag and let the data phase
956 and SEQ_FLAGS, ~DPHASE; /*
958 * the next time through
964 * Identify message? For a reconnecting target, this tells us the lun
965 * that the reconnection is for - find the correct SCB and switch to it,
966 * clearing the "disconnected" bit so we don't "find" it by accident later.
970 if ((p->features & AHC_WIDE) != 0) {
971 and A,0x0f; /* lun in lower four bits */
973 and A,0x07; /* lun in lower three bits */
975 or SAVED_TCL,A; /* SAVED_TCL should be complete now */
977 mvi ARG_2, SCB_LIST_NULL; /* SCBID of prev SCB in disc List */
978 call get_untagged_SCBID;
979 cmp ARG_1, SCB_LIST_NULL je snoop_tag;
980 if ((p->flags & AHC_PAGESCBS) != 0) {
981 test SEQ_FLAGS, SCBPTR_VALID jz use_retrieveSCB;
984 * If the SCB was found in the disconnected list (as is
985 * always the case in non-paging scenarios), SCBPTR is already
986 * set to the correct SCB. So, simply setup the SCB and get
989 mov SCBPTR call rem_scb_from_disc_list;
992 * Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message.
993 * If we get one, we use the tag returned to find the proper
994 * SCB. With SCB paging, this requires using search for both tagged
995 * and non-tagged transactions since the SCB may exist in any slot.
996 * If we're not using SCB paging, we can use the tag as the direct
1000 mov NONE,SCSIDATL; /* ACK Identify MSG */
1003 cmp LASTPHASE, P_MESGIN jne not_found;
1004 cmp SCSIBUSL,MSG_SIMPLE_Q_TAG jne not_found;
1006 mvi ARG_1 call inb_next; /* tag value */
1012 cmp SCB_TCL, A jne not_found_cleanup_scb;
1013 test SCB_CONTROL,DISCONNECTED jz not_found_cleanup_scb;
1014 and SCB_CONTROL,~DISCONNECTED;
1015 or SEQ_FLAGS,IDENTIFY_SEEN; /* make note of IDENTIFY */
1016 /* See if the host wants to send a message upon reconnection */
1017 test SCB_CONTROL, MK_MESSAGE jz mesgin_done;
1018 and SCB_CONTROL, ~MK_MESSAGE;
1019 mvi HOST_MSG call mk_mesg;
1022 not_found_cleanup_scb:
1023 test SCB_CONTROL, DISCONNECTED jz . + 3;
1024 call add_scb_to_disc_list;
1026 call add_scb_to_free_list;
1028 mvi INTSTAT, NO_MATCH;
1029 mvi MSG_BUS_DEV_RESET call mk_mesg;
1033 * Message reject? Let the kernel driver handle this. If we have an
1034 * outstanding WDTR or SDTR negotiation, assume that it's a response from
1035 * the target selecting 8bit or asynchronous transfer, otherwise just ignore
1036 * it since we have no clue what it pertains to.
1039 mvi INTSTAT, REJECT_MSG;
1043 * [ ADD MORE MESSAGE HANDLING HERE ]
1047 * Locking the driver out, build a one-byte message passed in SINDEX
1048 * if there is no active message already. SINDEX is returned intact.
1051 or SCSISIGO,ATNO,LASTPHASE;/* turn on ATNO */
1052 mov MSG_OUT,SINDEX ret;
1055 * Functions to read data in Automatic PIO mode.
1057 * According to Adaptec's documentation, an ACK is not sent on input from
1058 * the target until SCSIDATL is read from. So we wait until SCSIDATL is
1059 * latched (the usual way), then read the data byte directly off the bus
1060 * using SCSIBUSL. When we have pulled the ATN line, or we just want to
1061 * acknowledge the byte, then we do a dummy read from SCISDATL. The SCSI
1062 * spec guarantees that the target will hold the data byte on the bus until
1065 * The assumption here is that these are called in a particular sequence,
1066 * and that REQ is already set when inb_first is called. inb_{first,next}
1067 * use the same calling convention as inb.
1071 mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
1074 * If there is a parity error, wait for the kernel to
1075 * see the interrupt and prepare our message response
1076 * before continuing.
1078 test SSTAT1, REQINIT jz inb_next_wait;
1079 test SSTAT1, SCSIPERR jnz inb_next_wait;
1080 and LASTPHASE, PHASE_MASK, SCSISIGI;
1081 cmp LASTPHASE, P_MESGIN jne mesgin_phasemis;
1084 mov DINDIR,SCSIBUSL ret; /*read byte directly from bus*/
1086 mov NONE,SCSIDATL ret; /*dummy read from latch to ACK*/
1088 if ((p->flags & AHC_TARGETMODE) != 0) {
1090 * Send a byte to an initiator in Automatic PIO mode.
1091 * SPIOEN must be on prior to calling this routine.
1094 mov SCSIDATL, SINDEX;
1095 test SSTAT0, SPIORDY jz .;
1101 * We expected to receive another byte, but the target changed phase
1103 mvi INTSTAT, MSGIN_PHASEMIS;
1107 * DMA data transfer. HADDR and HCNT must be loaded first, and
1108 * SINDEX should contain the value to load DFCNTRL with - 0x3d for
1109 * host->scsi, or 0x39 for scsi->host. The SCSI channel is cleared
1110 * during initialization.
1112 if ((p->features & AHC_ULTRA2) == 0) {
1116 test SSTAT0,DMADONE jnz dma_dmadone;
1117 test SSTAT1,PHASEMIS jz dma_loop; /* ie. underrun */
1119 test SSTAT0,SDONE jnz dma_checkfifo;
1120 mov SINDEX,ALLZEROS; /* Notify caller of phasemiss */
1123 * We will be "done" DMAing when the transfer count goes to zero, or
1124 * the target changes the phase (in light of this, it makes sense that
1125 * the DMA circuitry doesn't ACK when PHASEMIS is active). If we are
1126 * doing a SCSI->Host transfer, the data FIFO should be flushed auto-
1127 * magically on STCNT=0 or a phase change, so just wait for FIFO empty
1131 test DFCNTRL,DIRECTION jnz dma_fifoempty;
1133 test DFSTATUS,FIFOEMP jz dma_fifoflush;
1136 /* Don't clobber an inprogress host data transfer */
1137 test DFSTATUS, MREQPEND jnz dma_fifoempty;
1139 * Now shut the DMA enables off and make sure that the DMA enables are
1140 * actually off first lest we get an ILLSADDR.
1143 and DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN);
1146 * Some revisions of the aic7880 have a problem where, if the
1147 * data fifo is full, but the PCI input latch is not empty,
1148 * HDMAEN cannot be cleared. The fix used here is to attempt
1149 * to drain the data fifo until there is space for the input
1150 * latch to drain and HDMAEN de-asserts.
1153 test DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz dma_halt;
1159 * Assert that if we've been reselected, then we've seen an IDENTIFY
1163 test SEQ_FLAGS,IDENTIFY_SEEN jnz return; /* seen IDENTIFY? */
1165 mvi INTSTAT,NO_IDENT ret; /* no - tell the kernel */
1168 * Locate a disconnected SCB either by SAVED_TCL (ARG_1 is SCB_LIST_NULL)
1169 * or by the SCBID ARG_1. The search begins at the SCB index passed in
1170 * via SINDEX which is an SCB that must be on the disconnected list. If
1171 * the SCB cannot be found, SINDEX will be SCB_LIST_NULL, otherwise, SCBPTR
1172 * is set to the proper SCB.
1175 mov SCBPTR,SINDEX; /* Initialize SCBPTR */
1176 cmp ARG_1, SCB_LIST_NULL jne findSCB_by_SCBID;
1178 mvi SCB_TCL jmp findSCB_loop; /* &SCB_TCL -> SINDEX */
1180 mov A, ARG_1; /* Tag passed in ARG_1 */
1181 mvi SCB_TAG jmp findSCB_loop; /* &SCB_TAG -> SINDEX */
1184 cmp SCB_NEXT, SCB_LIST_NULL je notFound;
1185 mov SCBPTR,SCB_NEXT;
1186 dec SINDEX; /* Last comparison moved us too far */
1188 cmp SINDIR, A jne findSCB_next;
1189 mov SINDEX, SCBPTR ret;
1191 mvi SINDEX, SCB_LIST_NULL ret;
1194 * Retrieve an SCB by SCBID first searching the disconnected list falling
1195 * back to DMA'ing the SCB down from the host. This routine assumes that
1196 * ARG_1 is the SCBID of interrest and that SINDEX is the position in the
1197 * disconnected list to start the search from. If SINDEX is SCB_LIST_NULL,
1198 * we go directly to the host for the SCB.
1201 test SEQ_FLAGS, SCBPTR_VALID jz retrieve_from_host;
1202 mov SCBPTR call findSCB; /* Continue the search */
1203 cmp SINDEX, SCB_LIST_NULL je retrieve_from_host;
1206 * This routine expects SINDEX to contain the index of the SCB to be
1207 * removed, SCBPTR to be pointing to that SCB, and ARG_2 to be the
1208 * SCBID of the SCB just previous to this one in the list or SCB_LIST_NULL
1209 * if it is at the head.
1211 rem_scb_from_disc_list:
1212 /* Remove this SCB from the disconnection list */
1213 cmp ARG_2, SCB_LIST_NULL je rHead;
1214 mov DINDEX, SCB_NEXT;
1216 mov SCB_NEXT, DINDEX;
1217 mov SCBPTR, SINDEX ret;
1219 mov DISCONNECTED_SCBH,SCB_NEXT ret;
1223 * We didn't find it. Pull an SCB and DMA down the one we want.
1224 * We should never get here in the non-paging case.
1226 mov ALLZEROS call get_free_or_disc_scb;
1227 mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
1228 /* Jump instead of call as we want to return anyway */
1229 mov ARG_1 jmp dma_scb;
1232 * Determine whether a target is using tagged or non-tagged transactions
1233 * by first looking for a matching transaction based on the TCL and if
1234 * that fails, looking up this device in the host's untagged SCB array.
1235 * The TCL to search for is assumed to be in SAVED_TCL. The value is
1236 * returned in ARG_1 (SCB_LIST_NULL for tagged, SCBID for non-tagged).
1237 * The SCBPTR_VALID bit is set in SEQ_FLAGS if we found the information
1238 * in an SCB instead of having to go to the host.
1241 cmp DISCONNECTED_SCBH, SCB_LIST_NULL je get_SCBID_from_host;
1242 mvi ARG_1, SCB_LIST_NULL;
1243 mov DISCONNECTED_SCBH call findSCB;
1244 cmp SINDEX, SCB_LIST_NULL je get_SCBID_from_host;
1245 or SEQ_FLAGS, SCBPTR_VALID;/* Was in disconnected list */
1246 test SCB_CONTROL, TAG_ENB jnz . + 2;
1247 mov ARG_1, SCB_TAG ret;
1248 mvi ARG_1, SCB_LIST_NULL ret;
1251 * Fetch a byte from host memory given an index of (A + (256 * SINDEX))
1252 * and a base address of SCBID_ADDR. The byte is returned in RETURN_2.
1256 if ((p->features & AHC_CMD_CHAN) != 0) {
1257 mvi DINDEX, CCHADDR;
1258 mvi SCBID_ADDR call set_1byte_addr;
1260 mvi CCSGCTL, CCSGEN|CCSGRESET;
1261 test CCSGCTL, CCSGDONE jz .;
1262 mvi CCSGCTL, CCSGRESET;
1263 bmov RETURN_2, CCSGRAM, 1 ret;
1266 mvi SCBID_ADDR call set_1byte_addr;
1270 mvi DFCNTRL, HDMAEN|DIRECTION|FIFORESET;
1272 mov RETURN_2, DFDAT ret;
1276 * Prepare the hardware to post a byte to host memory given an
1277 * index of (A + (256 * SINDEX)) and a base address of SCBID_ADDR.
1281 if ((p->features & AHC_CMD_CHAN) != 0) {
1282 mvi DINDEX, CCHADDR;
1283 mvi SCBID_ADDR call set_1byte_addr;
1285 mvi CCSCBCTL, CCSCBRESET ret;
1288 mvi SCBID_ADDR call set_1byte_addr;
1292 mvi DFCNTRL, FIFORESET ret;
1296 if ((p->features & AHC_CMD_CHAN) != 0) {
1297 bmov CCSCBRAM, SINDEX, 1;
1298 or CCSCBCTL, CCSCBEN|CCSCBRESET;
1299 test CCSCBCTL, CCSCBDONE jz .;
1303 or DFCNTRL, HDMAEN|FIFOFLUSH;
1307 get_SCBID_from_host:
1309 mvi UNTAGGEDSCB_OFFSET call fetch_byte;
1310 mov RETURN_1, RETURN_2 ret;
1313 test SSTAT1, REQINIT jz phase_lock;
1314 test SSTAT1, SCSIPERR jnz phase_lock;
1315 and SCSISIGO, PHASE_MASK, SCSISIGI;
1316 and LASTPHASE, PHASE_MASK, SCSISIGI ret;
1318 if ((p->features & AHC_CMD_CHAN) == 0) {
1319 set_stcnt_from_hcnt:
1320 mov STCNT[0], HCNT[0];
1321 mov STCNT[1], HCNT[1];
1322 mov STCNT[2], HCNT[2] ret;
1334 mov DINDIR, SINDIR ret;
1338 * Setup addr assuming that A is an index into
1339 * an array of 32byte objects, SINDEX contains
1340 * the base address of that array, and DINDEX
1341 * contains the base address of the location
1342 * to store the indexed address.
1348 * Setup addr assuming that A + (ARG_1 * 256) is an
1349 * index into an array of 1byte objects, SINDEX contains
1350 * the base address of that array, and DINDEX contains
1351 * the base address of the location to store the computed
1355 add DINDIR, A, SINDIR;
1357 adc DINDIR, A, SINDIR;
1359 adc DINDIR, A, SINDIR;
1360 adc DINDIR, A, SINDIR ret;
1363 * Either post or fetch and SCB from host memory based on the
1364 * DIRECTION bit in DMAPARAMS. The host SCB index is in SINDEX.
1368 if ((p->features & AHC_CMD_CHAN) != 0) {
1369 mvi DINDEX, CCHADDR;
1370 mvi HSCB_ADDR call set_32byte_addr;
1371 mov CCSCBPTR, SCBPTR;
1373 test DMAPARAMS, DIRECTION jz dma_scb_tohost;
1374 mvi CCSCBCTL, CCARREN|CCSCBEN|CCSCBDIR|CCSCBRESET;
1375 cmp CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN|CCSCBDIR jne .;
1378 if ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
1379 mvi CCSCBCTL, CCSCBRESET;
1380 bmov CCSCBRAM, SCB_CONTROL, 32;
1381 or CCSCBCTL, CCSCBEN|CCSCBRESET;
1382 test CCSCBCTL, CCSCBDONE jz .;
1384 mvi CCSCBCTL, CCARREN|CCSCBEN|CCSCBRESET;
1385 cmp CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN jne .;
1389 test CCSCBCTL, CCARREN|CCSCBEN jnz .;
1393 mvi HSCB_ADDR call set_32byte_addr;
1397 mov DFCNTRL, DMAPARAMS;
1398 test DMAPARAMS, DIRECTION jnz dma_scb_fromhost;
1399 /* Fill it with the SCB data */
1401 mvi SINDEX, SCB_CONTROL;
1403 copy_scb_tofifo_loop:
1412 cmp SINDEX, A jne copy_scb_tofifo_loop;
1413 or DFCNTRL, HDMAEN|FIFOFLUSH;
1416 /* If we were putting the SCB, we are done */
1417 test DMAPARAMS, DIRECTION jz return;
1418 mvi SCB_CONTROL call dfdat_in_7;
1419 call dfdat_in_7_continued;
1420 call dfdat_in_7_continued;
1421 jmp dfdat_in_7_continued;
1424 dfdat_in_7_continued:
1431 mov DINDIR,DFDAT ret;
1436 * Wait for DMA from host memory to data FIFO to complete, then disable
1437 * DMA and wait for it to acknowledge that it's off.
1439 if ((p->features & AHC_CMD_CHAN) == 0) {
1441 test DFSTATUS,HDONE jz dma_finish;
1443 and DFCNTRL, ~HDMAEN;
1444 test DFCNTRL, HDMAEN jnz .;
1448 add_scb_to_free_list:
1449 if ((p->flags & AHC_PAGESCBS) != 0) {
1450 mov SCB_NEXT, FREE_SCBH;
1451 mov FREE_SCBH, SCBPTR;
1453 mvi SCB_TAG, SCB_LIST_NULL ret;
1455 if ((p->flags & AHC_PAGESCBS) != 0) {
1456 get_free_or_disc_scb:
1457 cmp FREE_SCBH, SCB_LIST_NULL jne dequeue_free_scb;
1458 cmp DISCONNECTED_SCBH, SCB_LIST_NULL jne dequeue_disc_scb;
1460 mvi SINDEX, SCB_LIST_NULL ret;
1462 mov SCBPTR, DISCONNECTED_SCBH;
1464 mvi DMAPARAMS, FIFORESET;
1465 mov SCB_TAG call dma_scb;
1467 mov DISCONNECTED_SCBH, SCB_NEXT ret;
1469 mov SCBPTR, FREE_SCBH;
1470 mov FREE_SCBH, SCB_NEXT ret;
1473 add_scb_to_disc_list:
1475 * Link this SCB into the DISCONNECTED list. This list holds the
1476 * candidates for paging out an SCB if one is needed for a new command.
1477 * Modifying the disconnected list is a critical(pause dissabled) section.
1479 mov SCB_NEXT, DISCONNECTED_SCBH;
1480 mov DISCONNECTED_SCBH, SCBPTR ret;