Annotation of sys/dev/microcode/aic7xxx/aic7xxx.seq, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: aic7xxx.seq,v 1.21 2007/05/26 00:36:03 krw Exp $ */
2: /*-
3: * Adaptec 274x/284x/294x device driver firmware for Linux and FreeBSD.
4: *
5: * Copyright (c) 1994-2001 Justin T. Gibbs.
6: * Copyright (c) 2000-2001 Adaptec Inc.
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions, and the following disclaimer,
14: * without modification.
15: * 2. Redistributions in binary form must reproduce at minimum a disclaimer
16: * substantially similar to the "NO WARRANTY" disclaimer below
17: * ("Disclaimer") and any redistribution must be conditioned upon
18: * including a substantially similar Disclaimer requirement for further
19: * binary redistribution.
20: * 3. Neither the names of the above-listed copyright holders nor the names
21: * of any contributors may be used to endorse or promote products derived
22: * from this software without specific prior written permission.
23: *
24: * Alternatively, this software may be distributed under the terms of the
25: * GNU General Public License ("GPL") version 2 as published by the Free
26: * Software Foundation.
27: *
28: * NO WARRANTY
29: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
32: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33: * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
38: * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39: * POSSIBILITY OF SUCH DAMAGES.
40: *
41: * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.seq,v 1.128 2005/01/06 01:42:26 imp Exp $
42: */
43:
44: VERSION = "$Id: aic7xxx.seq,v 1.21 2007/05/26 00:36:03 krw Exp $"
45: PATCH_ARG_LIST = "struct ahc_softc *ahc"
46: PREFIX = "ahc_"
47:
48: #include <dev/microcode/aic7xxx/aic7xxx.reg>
49: #include <scsi/scsi_message.h>
50:
51: /*
52: * A few words on the waiting SCB list:
53: * After starting the selection hardware, we check for reconnecting targets
54: * as well as for our selection to complete just in case the reselection wins
55: * bus arbitration. The problem with this is that we must keep track of the
56: * SCB that we've already pulled from the QINFIFO and started the selection
57: * on just in case the reselection wins so that we can retry the selection at
58: * a later time. This problem cannot be resolved by holding a single entry
59: * in scratch ram since a reconnecting target can request sense and this will
60: * create yet another SCB waiting for selection. The solution used here is to
61: * use byte 27 of the SCB as a psuedo-next pointer and to thread a list
62: * of SCBs that are awaiting selection. Since 0-0xfe are valid SCB indexes,
63: * SCB_LIST_NULL is 0xff which is out of range. An entry is also added to
64: * this list everytime a request sense occurs or after completing a non-tagged
65: * command for which a second SCB has been queued. The sequencer will
66: * automatically consume the entries.
67: */
68:
69: bus_free_sel:
70: /*
71: * Turn off the selection hardware. We need to reset the
72: * selection request in order to perform a new selection.
73: */
74: and SCSISEQ, TEMODE|ENSELI|ENRSELI|ENAUTOATNP;
75: and SIMODE1, ~ENBUSFREE;
76: poll_for_work:
77: call clear_target_state;
78: and SXFRCTL0, ~SPIOEN;
79: if ((ahc->features & AHC_ULTRA2) != 0) {
80: clr SCSIBUSL;
81: }
82: test SCSISEQ, ENSELO jnz poll_for_selection;
83: if ((ahc->features & AHC_TWIN) != 0) {
84: xor SBLKCTL,SELBUSB; /* Toggle to the other bus */
85: test SCSISEQ, ENSELO jnz poll_for_selection;
86: }
87: BEGIN_CRITICAL;
88: cmp WAITING_SCBH,SCB_LIST_NULL jne start_waiting;
89: END_CRITICAL;
90: poll_for_work_loop:
91: if ((ahc->features & AHC_TWIN) != 0) {
92: xor SBLKCTL,SELBUSB; /* Toggle to the other bus */
93: }
94: test SSTAT0, SELDO|SELDI jnz selection;
95: test_queue:
96: /* Has the driver posted any work for us? */
97: BEGIN_CRITICAL;
98: if ((ahc->features & AHC_QUEUE_REGS) != 0) {
99: test QOFF_CTLSTA, SCB_AVAIL jz poll_for_work_loop;
100: } else {
101: mov A, QINPOS;
102: cmp KERNEL_QINPOS, A je poll_for_work_loop;
103: }
104: mov ARG_1, NEXT_QUEUED_SCB;
105:
106: /*
107: * We have at least one queued SCB now and we don't have any
108: * SCBs in the list of SCBs awaiting selection. Allocate a
109: * card SCB for the host's SCB and get to work on it.
110: */
111: if ((ahc->flags & AHC_PAGESCBS) != 0) {
112: mov ALLZEROS call get_free_or_disc_scb;
113: } else {
114: /* In the non-paging case, the SCBID == hardware SCB index */
115: mov SCBPTR, ARG_1;
116: }
117: or SEQ_FLAGS2, SCB_DMA;
118: END_CRITICAL;
119: dma_queued_scb:
120: /*
121: * DMA the SCB from host ram into the current SCB location.
122: */
123: mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
124: mov ARG_1 call dma_scb;
125: /*
126: * Check one last time to see if this SCB was canceled
127: * before we completed the DMA operation. If it was,
128: * the QINFIFO next pointer will not match our saved
129: * value.
130: */
131: mov A, ARG_1;
132: BEGIN_CRITICAL;
133: cmp NEXT_QUEUED_SCB, A jne abort_qinscb;
134: if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
135: cmp SCB_TAG, A je . + 2;
136: mvi SCB_MISMATCH call set_seqint;
137: }
138: mov NEXT_QUEUED_SCB, SCB_NEXT;
139: mov SCB_NEXT,WAITING_SCBH;
140: mov WAITING_SCBH, SCBPTR;
141: if ((ahc->features & AHC_QUEUE_REGS) != 0) {
142: mov NONE, SNSCB_QOFF;
143: } else {
144: inc QINPOS;
145: }
146: and SEQ_FLAGS2, ~SCB_DMA;
147: start_waiting:
148: /*
149: * Start the first entry on the waiting SCB list.
150: */
151: mov SCBPTR, WAITING_SCBH;
152: call start_selection;
153: END_CRITICAL;
154:
155: poll_for_selection:
156: /*
157: * Twin channel devices cannot handle things like SELTO
158: * interrupts on the "background" channel. So, while
159: * selecting, keep polling the current channel until
160: * either a selection or reselection occurs.
161: */
162: test SSTAT0, SELDO|SELDI jz poll_for_selection;
163:
164: selection:
165: /*
166: * We aren't expecting a bus free, so interrupt
167: * the kernel driver if it happens.
168: */
169: mvi CLRSINT1,CLRBUSFREE;
170: if ((ahc->features & AHC_DT) == 0) {
171: or SIMODE1, ENBUSFREE;
172: }
173:
174: /*
175: * Guard against a bus free after (re)selection
176: * but prior to enabling the busfree interrupt. SELDI
177: * and SELDO will be cleared in that case.
178: */
179: test SSTAT0, SELDI|SELDO jz bus_free_sel;
180: test SSTAT0,SELDO jnz select_out;
181: select_in:
182: if ((ahc->flags & AHC_TARGETROLE) != 0) {
183: if ((ahc->flags & AHC_INITIATORROLE) != 0) {
184: test SSTAT0, TARGET jz initiator_reselect;
185: }
186: mvi CLRSINT0, CLRSELDI;
187:
188: /*
189: * We've just been selected. Assert BSY and
190: * setup the phase for receiving messages
191: * from the target.
192: */
193: mvi SCSISIGO, P_MESGOUT|BSYO;
194:
195: /*
196: * Setup the DMA for sending the identify and
197: * command information.
198: */
199: mvi SEQ_FLAGS, CMDPHASE_PENDING;
200:
201: mov A, TQINPOS;
202: if ((ahc->features & AHC_CMD_CHAN) != 0) {
203: mvi DINDEX, CCHADDR;
204: mvi SHARED_DATA_ADDR call set_32byte_addr;
205: mvi CCSCBCTL, CCSCBRESET;
206: } else {
207: mvi DINDEX, HADDR;
208: mvi SHARED_DATA_ADDR call set_32byte_addr;
209: mvi DFCNTRL, FIFORESET;
210: }
211:
212: /* Initiator that selected us */
213: and SAVED_SCSIID, SELID_MASK, SELID;
214: /* The Target ID we were selected at */
215: if ((ahc->features & AHC_MULTI_TID) != 0) {
216: and A, OID, TARGIDIN;
217: } else if ((ahc->features & AHC_ULTRA2) != 0) {
218: and A, OID, SCSIID_ULTRA2;
219: } else {
220: and A, OID, SCSIID;
221: }
222: or SAVED_SCSIID, A;
223: if ((ahc->features & AHC_TWIN) != 0) {
224: test SBLKCTL, SELBUSB jz . + 2;
225: or SAVED_SCSIID, TWIN_CHNLB;
226: }
227: if ((ahc->features & AHC_CMD_CHAN) != 0) {
228: mov CCSCBRAM, SAVED_SCSIID;
229: } else {
230: mov DFDAT, SAVED_SCSIID;
231: }
232:
233: /*
234: * If ATN isn't asserted, the target isn't interested
235: * in talking to us. Go directly to bus free.
236: * XXX SCSI-1 may require us to assume lun 0 if
237: * ATN is false.
238: */
239: test SCSISIGI, ATNI jz target_busfree;
240:
241: /*
242: * Watch ATN closely now as we pull in messages from the
243: * initiator. We follow the guidlines from section 6.5
244: * of the SCSI-2 spec for what messages are allowed when.
245: */
246: call target_inb;
247:
248: /*
249: * Our first message must be one of IDENTIFY, ABORT, or
250: * BUS_DEVICE_RESET.
251: */
252: test DINDEX, MSG_IDENTIFYFLAG jz host_target_message_loop;
253: /* Store for host */
254: if ((ahc->features & AHC_CMD_CHAN) != 0) {
255: mov CCSCBRAM, DINDEX;
256: } else {
257: mov DFDAT, DINDEX;
258: }
259: and SAVED_LUN, MSG_IDENTIFY_LUNMASK, DINDEX;
260:
261: /* Remember for disconnection decision */
262: test DINDEX, MSG_IDENTIFY_DISCFLAG jnz . + 2;
263: /* XXX Honor per target settings too */
264: or SEQ_FLAGS, NO_DISCONNECT;
265:
266: test SCSISIGI, ATNI jz ident_messages_done;
267: call target_inb;
268: /*
269: * If this is a tagged request, the tagged message must
270: * immediately follow the identify. We test for a valid
271: * tag message by seeing if it is >= MSG_SIMPLE_Q_TAG and
272: * < MSG_IGN_WIDE_RESIDUE.
273: */
274: add A, -MSG_SIMPLE_Q_TAG, DINDEX;
275: jnc ident_messages_done_msg_pending;
276: add A, -MSG_IGN_WIDE_RESIDUE, DINDEX;
277: jc ident_messages_done_msg_pending;
278:
279: /* Store for host */
280: if ((ahc->features & AHC_CMD_CHAN) != 0) {
281: mov CCSCBRAM, DINDEX;
282: } else {
283: mov DFDAT, DINDEX;
284: }
285:
286: /*
287: * If the initiator doesn't feel like providing a tag number,
288: * we've got a failed selection and must transition to bus
289: * free.
290: */
291: test SCSISIGI, ATNI jz target_busfree;
292:
293: /*
294: * Store the tag for the host.
295: */
296: call target_inb;
297: if ((ahc->features & AHC_CMD_CHAN) != 0) {
298: mov CCSCBRAM, DINDEX;
299: } else {
300: mov DFDAT, DINDEX;
301: }
302: mov INITIATOR_TAG, DINDEX;
303: or SEQ_FLAGS, TARGET_CMD_IS_TAGGED;
304:
305: ident_messages_done:
306: /* Terminate the ident list */
307: if ((ahc->features & AHC_CMD_CHAN) != 0) {
308: mvi CCSCBRAM, SCB_LIST_NULL;
309: } else {
310: mvi DFDAT, SCB_LIST_NULL;
311: }
312: or SEQ_FLAGS, TARG_CMD_PENDING;
313: test SEQ_FLAGS2, TARGET_MSG_PENDING
314: jnz target_mesgout_pending;
315: test SCSISIGI, ATNI jnz target_mesgout_continue;
316: jmp target_ITloop;
317:
318:
319: ident_messages_done_msg_pending:
320: or SEQ_FLAGS2, TARGET_MSG_PENDING;
321: jmp ident_messages_done;
322:
323: /*
324: * Pushed message loop to allow the kernel to
325: * run its own target mode message state engine.
326: */
327: host_target_message_loop:
328: mvi HOST_MSG_LOOP call set_seqint;
329: cmp RETURN_1, EXIT_MSG_LOOP je target_ITloop;
330: test SSTAT0, SPIORDY jz .;
331: jmp host_target_message_loop;
332: }
333:
334: if ((ahc->flags & AHC_INITIATORROLE) != 0) {
335: /*
336: * Reselection has been initiated by a target. Make a note that we've been
337: * reselected, but haven't seen an IDENTIFY message from the target yet.
338: */
339: initiator_reselect:
340: /* XXX test for and handle ONE BIT condition */
341: or SXFRCTL0, SPIOEN|CLRSTCNT|CLRCHN;
342: and SAVED_SCSIID, SELID_MASK, SELID;
343: if ((ahc->features & AHC_ULTRA2) != 0) {
344: and A, OID, SCSIID_ULTRA2;
345: } else {
346: and A, OID, SCSIID;
347: }
348: or SAVED_SCSIID, A;
349: if ((ahc->features & AHC_TWIN) != 0) {
350: test SBLKCTL, SELBUSB jz . + 2;
351: or SAVED_SCSIID, TWIN_CHNLB;
352: }
353: mvi CLRSINT0, CLRSELDI;
354: jmp ITloop;
355: }
356:
357: abort_qinscb:
358: call add_scb_to_free_list;
359: jmp poll_for_work_loop;
360:
361: BEGIN_CRITICAL;
362: start_selection:
363: /*
364: * If bus reset interrupts have been disabled (from a previous
365: * reset), re-enable them now. Resets are only of interest
366: * when we have outstanding transactions, so we can safely
367: * defer re-enabling the interrupt until, as an initiator,
368: * we start sending out transactions again.
369: */
370: test SIMODE1, ENSCSIRST jnz . + 3;
371: mvi CLRSINT1, CLRSCSIRSTI;
372: or SIMODE1, ENSCSIRST;
373: if ((ahc->features & AHC_TWIN) != 0) {
374: and SINDEX,~SELBUSB,SBLKCTL;/* Clear channel select bit */
375: test SCB_SCSIID, TWIN_CHNLB jz . + 2;
376: or SINDEX, SELBUSB;
377: mov SBLKCTL,SINDEX; /* select channel */
378: }
379: initialize_scsiid:
380: if ((ahc->features & AHC_ULTRA2) != 0) {
381: mov SCSIID_ULTRA2, SCB_SCSIID;
382: } else if ((ahc->features & AHC_TWIN) != 0) {
383: and SCSIID, TWIN_TID|OID, SCB_SCSIID;
384: } else {
385: mov SCSIID, SCB_SCSIID;
386: }
387: if ((ahc->flags & AHC_TARGETROLE) != 0) {
388: mov SINDEX, SCSISEQ_TEMPLATE;
389: test SCB_CONTROL, TARGET_SCB jz . + 2;
390: or SINDEX, TEMODE;
391: mov SCSISEQ, SINDEX ret;
392: } else {
393: mov SCSISEQ, SCSISEQ_TEMPLATE ret;
394: }
395: END_CRITICAL;
396:
397: /*
398: * Initialize transfer settings with SCB provided settings.
399: */
400: set_transfer_settings:
401: if ((ahc->features & AHC_ULTRA) != 0) {
402: test SCB_CONTROL, ULTRAENB jz . + 2;
403: or SXFRCTL0, FAST20;
404: }
405: /*
406: * Initialize SCSIRATE with the appropriate value for this target.
407: */
408: if ((ahc->features & AHC_ULTRA2) != 0) {
409: bmov SCSIRATE, SCB_SCSIRATE, 2 ret;
410: } else {
411: mov SCSIRATE, SCB_SCSIRATE ret;
412: }
413:
414: if ((ahc->flags & AHC_TARGETROLE) != 0) {
415: /*
416: * We carefully toggle SPIOEN to allow us to return the
417: * message byte we receive so it can be checked prior to
418: * driving REQ on the bus for the next byte.
419: */
420: target_inb:
421: /*
422: * Drive REQ on the bus by enabling SCSI PIO.
423: */
424: or SXFRCTL0, SPIOEN;
425: /* Wait for the byte */
426: test SSTAT0, SPIORDY jz .;
427: /* Prevent our read from triggering another REQ */
428: and SXFRCTL0, ~SPIOEN;
429: /* Save latched contents */
430: mov DINDEX, SCSIDATL ret;
431: }
432:
433: /*
434: * After the selection, remove this SCB from the "waiting SCB"
435: * list. This is achieved by simply moving our "next" pointer into
436: * WAITING_SCBH. Our next pointer will be set to null the next time this
437: * SCB is used, so don't bother with it now.
438: */
439: select_out:
440: /* Turn off the selection hardware */
441: and SCSISEQ, TEMODE|ENSELI|ENRSELI|ENAUTOATNP, SCSISEQ;
442: mov SCBPTR, WAITING_SCBH;
443: mov WAITING_SCBH,SCB_NEXT;
444: mov SAVED_SCSIID, SCB_SCSIID;
445: and SAVED_LUN, LID, SCB_LUN;
446: call set_transfer_settings;
447: if ((ahc->flags & AHC_TARGETROLE) != 0) {
448: test SSTAT0, TARGET jz initiator_select;
449:
450: or SXFRCTL0, CLRSTCNT|CLRCHN;
451:
452: /*
453: * Put tag in connonical location since not
454: * all connections have an SCB.
455: */
456: mov INITIATOR_TAG, SCB_TARGET_ITAG;
457:
458: /*
459: * We've just re-selected an initiator.
460: * Assert BSY and setup the phase for
461: * sending our identify messages.
462: */
463: mvi P_MESGIN|BSYO call change_phase;
464: mvi CLRSINT0, CLRSELDO;
465:
466: /*
467: * Start out with a simple identify message.
468: */
469: or SAVED_LUN, MSG_IDENTIFYFLAG call target_outb;
470:
471: /*
472: * If we are the result of a tagged command, send
473: * a simple Q tag and the tag id.
474: */
475: test SCB_CONTROL, TAG_ENB jz . + 3;
476: mvi MSG_SIMPLE_Q_TAG call target_outb;
477: mov SCB_TARGET_ITAG call target_outb;
478: target_synccmd:
479: /*
480: * Now determine what phases the host wants us
481: * to go through.
482: */
483: mov SEQ_FLAGS, SCB_TARGET_PHASES;
484:
485: test SCB_CONTROL, MK_MESSAGE jz target_ITloop;
486: mvi P_MESGIN|BSYO call change_phase;
487: jmp host_target_message_loop;
488: target_ITloop:
489: /*
490: * Start honoring ATN signals now that
491: * we properly identified ourselves.
492: */
493: test SCSISIGI, ATNI jnz target_mesgout;
494: test SEQ_FLAGS, CMDPHASE_PENDING jnz target_cmdphase;
495: test SEQ_FLAGS, DPHASE_PENDING jnz target_dphase;
496: test SEQ_FLAGS, SPHASE_PENDING jnz target_sphase;
497:
498: /*
499: * No more work to do. Either disconnect or not depending
500: * on the state of NO_DISCONNECT.
501: */
502: test SEQ_FLAGS, NO_DISCONNECT jz target_disconnect;
503: mvi TARG_IMMEDIATE_SCB, SCB_LIST_NULL;
504: call complete_target_cmd;
505: if ((ahc->flags & AHC_PAGESCBS) != 0) {
506: mov ALLZEROS call get_free_or_disc_scb;
507: }
508: cmp TARG_IMMEDIATE_SCB, SCB_LIST_NULL je .;
509: mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
510: mov TARG_IMMEDIATE_SCB call dma_scb;
511: call set_transfer_settings;
512: or SXFRCTL0, CLRSTCNT|CLRCHN;
513: jmp target_synccmd;
514:
515: target_mesgout:
516: mvi SCSISIGO, P_MESGOUT|BSYO;
517: target_mesgout_continue:
518: call target_inb;
519: target_mesgout_pending:
520: and SEQ_FLAGS2, ~TARGET_MSG_PENDING;
521: /* Local Processing goes here... */
522: jmp host_target_message_loop;
523:
524: target_disconnect:
525: mvi P_MESGIN|BSYO call change_phase;
526: test SEQ_FLAGS, DPHASE jz . + 2;
527: mvi MSG_SAVEDATAPOINTER call target_outb;
528: mvi MSG_DISCONNECT call target_outb;
529:
530: target_busfree_wait:
531: /* Wait for preceding I/O session to complete. */
532: test SCSISIGI, ACKI jnz .;
533: target_busfree:
534: and SIMODE1, ~ENBUSFREE;
535: if ((ahc->features & AHC_ULTRA2) != 0) {
536: clr SCSIBUSL;
537: }
538: clr SCSISIGO;
539: mvi LASTPHASE, P_BUSFREE;
540: call complete_target_cmd;
541: jmp poll_for_work;
542:
543: target_cmdphase:
544: /*
545: * The target has dropped ATN (doesn't want to abort or BDR)
546: * and we believe this selection to be valid. If the ring
547: * buffer for new commands is full, return busy or queue full.
548: */
549: if ((ahc->features & AHC_HS_MAILBOX) != 0) {
550: and A, HOST_TQINPOS, HS_MAILBOX;
551: } else {
552: mov A, KERNEL_TQINPOS;
553: }
554: cmp TQINPOS, A jne tqinfifo_has_space;
555: mvi P_STATUS|BSYO call change_phase;
556: test SEQ_FLAGS, TARGET_CMD_IS_TAGGED jz . + 3;
557: mvi STATUS_QUEUE_FULL call target_outb;
558: jmp target_busfree_wait;
559: mvi STATUS_BUSY call target_outb;
560: jmp target_busfree_wait;
561: tqinfifo_has_space:
562: mvi P_COMMAND|BSYO call change_phase;
563: call target_inb;
564: mov A, DINDEX;
565: /* Store for host */
566: if ((ahc->features & AHC_CMD_CHAN) != 0) {
567: mov CCSCBRAM, A;
568: } else {
569: mov DFDAT, A;
570: }
571:
572: /*
573: * Determine the number of bytes to read
574: * based on the command group code via table lookup.
575: * We reuse the first 8 bytes of the TARG_SCSIRATE
576: * BIOS array for this table. Count is one less than
577: * the total for the command since we've already fetched
578: * the first byte.
579: */
580: shr A, CMD_GROUP_CODE_SHIFT;
581: add SINDEX, CMDSIZE_TABLE, A;
582: mov A, SINDIR;
583:
584: test A, 0xFF jz command_phase_done;
585: or SXFRCTL0, SPIOEN;
586: command_loop:
587: test SSTAT0, SPIORDY jz .;
588: cmp A, 1 jne . + 2;
589: and SXFRCTL0, ~SPIOEN; /* Last Byte */
590: if ((ahc->features & AHC_CMD_CHAN) != 0) {
591: mov CCSCBRAM, SCSIDATL;
592: } else {
593: mov DFDAT, SCSIDATL;
594: }
595: dec A;
596: test A, 0xFF jnz command_loop;
597:
598: command_phase_done:
599: and SEQ_FLAGS, ~CMDPHASE_PENDING;
600: jmp target_ITloop;
601:
602: target_dphase:
603: /*
604: * Data phases on the bus are from the
605: * perspective of the initiator. The DMA
606: * code looks at LASTPHASE to determine the
607: * data direction of the DMA. Toggle it for
608: * target transfers.
609: */
610: xor LASTPHASE, IOI, SCB_TARGET_DATA_DIR;
611: or SCB_TARGET_DATA_DIR, BSYO call change_phase;
612: jmp p_data;
613:
614: target_sphase:
615: mvi P_STATUS|BSYO call change_phase;
616: mvi LASTPHASE, P_STATUS;
617: mov SCB_SCSI_STATUS call target_outb;
618: /* XXX Watch for ATN or parity errors??? */
619: mvi SCSISIGO, P_MESGIN|BSYO;
620: /* MSG_CMDCMPLT is 0, but we can't do an immediate of 0 */
621: mov ALLZEROS call target_outb;
622: jmp target_busfree_wait;
623:
624: complete_target_cmd:
625: test SEQ_FLAGS, TARG_CMD_PENDING jnz . + 2;
626: mov SCB_TAG jmp complete_post;
627: if ((ahc->features & AHC_CMD_CHAN) != 0) {
628: /* Set the valid byte */
629: mvi CCSCBADDR, 24;
630: mov CCSCBRAM, ALLONES;
631: mvi CCHCNT, 28;
632: or CCSCBCTL, CCSCBEN|CCSCBRESET;
633: test CCSCBCTL, CCSCBDONE jz .;
634: clr CCSCBCTL;
635: } else {
636: /* Set the valid byte */
637: or DFCNTRL, FIFORESET;
638: mvi DFWADDR, 3; /* Third 64bit word or byte 24 */
639: mov DFDAT, ALLONES;
640: mvi 28 call set_hcnt;
641: or DFCNTRL, HDMAEN|FIFOFLUSH;
642: call dma_finish;
643: }
644: inc TQINPOS;
645: mvi INTSTAT,CMDCMPLT ret;
646: }
647:
648: if ((ahc->flags & AHC_INITIATORROLE) != 0) {
649: initiator_select:
650: or SXFRCTL0, SPIOEN|CLRSTCNT|CLRCHN;
651: /*
652: * As soon as we get a successful selection, the target
653: * should go into the message out phase since we have ATN
654: * asserted.
655: */
656: mvi MSG_OUT, MSG_IDENTIFYFLAG;
657: mvi SEQ_FLAGS, NO_CDB_SENT;
658: mvi CLRSINT0, CLRSELDO;
659:
660: /*
661: * Main loop for information transfer phases. Wait for the
662: * target to assert REQ before checking MSG, C/D and I/O for
663: * the bus phase.
664: */
665: mesgin_phasemis:
666: ITloop:
667: call phase_lock;
668:
669: mov A, LASTPHASE;
670:
671: test A, ~P_DATAIN jz p_data;
672: cmp A,P_COMMAND je p_command;
673: cmp A,P_MESGOUT je p_mesgout;
674: cmp A,P_STATUS je p_status;
675: cmp A,P_MESGIN je p_mesgin;
676:
677: mvi BAD_PHASE call set_seqint;
678: jmp ITloop; /* Try reading the bus again. */
679:
680: await_busfree:
681: and SIMODE1, ~ENBUSFREE;
682: mov NONE, SCSIDATL; /* Ack the last byte */
683: if ((ahc->features & AHC_ULTRA2) != 0) {
684: clr SCSIBUSL; /* Prevent bit leakage durint SELTO */
685: }
686: and SXFRCTL0, ~SPIOEN;
687: mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT;
688: test SSTAT1,REQINIT|BUSFREE jz .;
689: test SSTAT1, BUSFREE jnz poll_for_work;
690: mvi MISSED_BUSFREE call set_seqint;
691: }
692:
693: clear_target_state:
694: /*
695: * We assume that the kernel driver may reset us
696: * at any time, even in the middle of a DMA, so
697: * clear DFCNTRL too.
698: */
699: clr DFCNTRL;
700: or SXFRCTL0, CLRSTCNT|CLRCHN;
701:
702: /*
703: * We don't know the target we will connect to,
704: * so default to narrow transfers to avoid
705: * parity problems.
706: */
707: if ((ahc->features & AHC_ULTRA2) != 0) {
708: bmov SCSIRATE, ALLZEROS, 2;
709: } else {
710: clr SCSIRATE;
711: if ((ahc->features & AHC_ULTRA) != 0) {
712: and SXFRCTL0, ~(FAST20);
713: }
714: }
715: mvi LASTPHASE, P_BUSFREE;
716: /* clear target specific flags */
717: mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT ret;
718:
719: sg_advance:
720: clr A; /* add sizeof(struct scatter) */
721: add SCB_RESIDUAL_SGPTR[0],SG_SIZEOF;
722: adc SCB_RESIDUAL_SGPTR[1],A;
723: adc SCB_RESIDUAL_SGPTR[2],A;
724: adc SCB_RESIDUAL_SGPTR[3],A ret;
725:
726: if ((ahc->features & AHC_CMD_CHAN) != 0) {
727: disable_ccsgen:
728: test CCSGCTL, CCSGEN jz return;
729: test CCSGCTL, CCSGDONE jz .;
730: disable_ccsgen_fetch_done:
731: clr CCSGCTL;
732: test CCSGCTL, CCSGEN jnz .;
733: ret;
734: idle_loop:
735: /*
736: * Do we need any more segments for this transfer?
737: */
738: test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jnz return;
739:
740: /* Did we just finish fetching segs? */
741: cmp CCSGCTL, CCSGEN|CCSGDONE je idle_sgfetch_complete;
742:
743: /* Are we actively fetching segments? */
744: test CCSGCTL, CCSGEN jnz return;
745:
746: /*
747: * Do we have any prefetch left???
748: */
749: cmp CCSGADDR, SG_PREFETCH_CNT jne idle_sg_avail;
750:
751: /*
752: * Need to fetch segments, but we can only do that
753: * if the command channel is completely idle. Make
754: * sure we don't have an SCB prefetch going on.
755: */
756: test CCSCBCTL, CCSCBEN jnz return;
757:
758: /*
759: * We fetch a "cacheline aligned" and sized amount of data
760: * so we don't end up referencing a non-existant page.
761: * Cacheline aligned is in quotes because the kernel will
762: * set the prefetch amount to a reasonable level if the
763: * cacheline size is unknown.
764: */
765: mvi CCHCNT, SG_PREFETCH_CNT;
766: and CCHADDR[0], SG_PREFETCH_ALIGN_MASK, SCB_RESIDUAL_SGPTR;
767: bmov CCHADDR[1], SCB_RESIDUAL_SGPTR[1], 3;
768: mvi CCSGCTL, CCSGEN|CCSGRESET ret;
769: idle_sgfetch_complete:
770: call disable_ccsgen_fetch_done;
771: and CCSGADDR, SG_PREFETCH_ADDR_MASK, SCB_RESIDUAL_SGPTR;
772: idle_sg_avail:
773: if ((ahc->features & AHC_ULTRA2) != 0) {
774: /* Does the hardware have space for another SG entry? */
775: test DFSTATUS, PRELOAD_AVAIL jz return;
776: bmov HADDR, CCSGRAM, 7;
777: bmov SCB_RESIDUAL_DATACNT[3], CCSGRAM, 1;
778: if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
779: mov SCB_RESIDUAL_DATACNT[3] call set_hhaddr;
780: }
781: call sg_advance;
782: mov SINDEX, SCB_RESIDUAL_SGPTR[0];
783: test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz . + 2;
784: or SINDEX, LAST_SEG;
785: mov SG_CACHE_PRE, SINDEX;
786: /* Load the segment */
787: or DFCNTRL, PRELOADEN;
788: }
789: ret;
790: }
791:
792: if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 && ahc->pci_cachesize != 0) {
793: /*
794: * Calculate the trailing portion of this S/G segment that cannot
795: * be transferred using memory write and invalidate PCI transactions.
796: * XXX Can we optimize this for PCI writes only???
797: */
798: calc_mwi_residual:
799: /*
800: * If the ending address is on a cacheline boundary,
801: * there is no need for an extra segment.
802: */
803: mov A, HCNT[0];
804: add A, A, HADDR[0];
805: and A, CACHESIZE_MASK;
806: test A, 0xFF jz return;
807:
808: /*
809: * If the transfer is less than a cachline,
810: * there is no need for an extra segment.
811: */
812: test HCNT[1], 0xFF jnz calc_mwi_residual_final;
813: test HCNT[2], 0xFF jnz calc_mwi_residual_final;
814: add NONE, INVERTED_CACHESIZE_MASK, HCNT[0];
815: jnc return;
816:
817: calc_mwi_residual_final:
818: mov MWI_RESIDUAL, A;
819: not A;
820: inc A;
821: add HCNT[0], A;
822: adc HCNT[1], -1;
823: adc HCNT[2], -1 ret;
824: }
825:
826: p_data:
827: test SEQ_FLAGS,NOT_IDENTIFIED|NO_CDB_SENT jz p_data_allowed;
828: mvi PROTO_VIOLATION call set_seqint;
829: p_data_allowed:
830: if ((ahc->features & AHC_ULTRA2) != 0) {
831: mvi DMAPARAMS, PRELOADEN|SCSIEN|HDMAEN;
832: } else {
833: mvi DMAPARAMS, WIDEODD|SCSIEN|SDMAEN|HDMAEN|FIFORESET;
834: }
835: test LASTPHASE, IOI jnz . + 2;
836: or DMAPARAMS, DIRECTION;
837: if ((ahc->features & AHC_CMD_CHAN) != 0) {
838: /* We don't have any valid S/G elements */
839: mvi CCSGADDR, SG_PREFETCH_CNT;
840: }
841: test SEQ_FLAGS, DPHASE jz data_phase_initialize;
842:
843: /*
844: * If we re-enter the data phase after going through another
845: * phase, our transfer location has almost certainly been
846: * corrupted by the interveining, non-data, transfers. Ask
847: * the host driver to fix us up based on the transfer residual.
848: */
849: mvi PDATA_REINIT call set_seqint;
850: jmp data_phase_loop;
851:
852: data_phase_initialize:
853: /* We have seen a data phase for the first time */
854: or SEQ_FLAGS, DPHASE;
855:
856: /*
857: * Initialize the DMA address and counter from the SCB.
858: * Also set SCB_RESIDUAL_SGPTR, including the LAST_SEG
859: * flag in the highest byte of the data count. We cannot
860: * modify the saved values in the SCB until we see a save
861: * data pointers message.
862: */
863: if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
864: /* The lowest address byte must be loaded last. */
865: mov SCB_DATACNT[3] call set_hhaddr;
866: }
867: if ((ahc->features & AHC_CMD_CHAN) != 0) {
868: bmov HADDR, SCB_DATAPTR, 7;
869: bmov SCB_RESIDUAL_DATACNT[3], SCB_DATACNT[3], 5;
870: } else {
871: mvi DINDEX, HADDR;
872: mvi SCB_DATAPTR call bcopy_7;
873: mvi DINDEX, SCB_RESIDUAL_DATACNT + 3;
874: mvi SCB_DATACNT + 3 call bcopy_5;
875: }
876: if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 && ahc->pci_cachesize != 0) {
877: call calc_mwi_residual;
878: }
879: and SCB_RESIDUAL_SGPTR[0], ~SG_FULL_RESID;
880:
881: if ((ahc->features & AHC_ULTRA2) == 0) {
882: if ((ahc->features & AHC_CMD_CHAN) != 0) {
883: bmov STCNT, HCNT, 3;
884: } else {
885: call set_stcnt_from_hcnt;
886: }
887: }
888:
889: data_phase_loop:
890: /* Guard against overruns */
891: test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz data_phase_inbounds;
892:
893: /*
894: * Turn on `Bit Bucket' mode, wait until the target takes
895: * us to another phase, and then notify the host.
896: */
897: and DMAPARAMS, DIRECTION;
898: mov DFCNTRL, DMAPARAMS;
899: or SXFRCTL1,BITBUCKET;
900: if ((ahc->features & AHC_DT) == 0) {
901: test SSTAT1,PHASEMIS jz .;
902: } else {
903: test SCSIPHASE, DATA_PHASE_MASK jnz .;
904: }
905: and SXFRCTL1, ~BITBUCKET;
906: mvi DATA_OVERRUN call set_seqint;
907: jmp ITloop;
908:
909: data_phase_inbounds:
910: if ((ahc->features & AHC_ULTRA2) != 0) {
911: mov SINDEX, SCB_RESIDUAL_SGPTR[0];
912: test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz . + 2;
913: or SINDEX, LAST_SEG;
914: mov SG_CACHE_PRE, SINDEX;
915: mov DFCNTRL, DMAPARAMS;
916: ultra2_dma_loop:
917: call idle_loop;
918: /*
919: * The transfer is complete if either the last segment
920: * completes or the target changes phase.
921: */
922: test SG_CACHE_SHADOW, LAST_SEG_DONE jnz ultra2_dmafinish;
923: if ((ahc->features & AHC_DT) == 0) {
924: if ((ahc->flags & AHC_TARGETROLE) != 0) {
925: /*
926: * As a target, we control the phases,
927: * so ignore PHASEMIS.
928: */
929: test SSTAT0, TARGET jnz ultra2_dma_loop;
930: }
931: if ((ahc->flags & AHC_INITIATORROLE) != 0) {
932: test SSTAT1,PHASEMIS jz ultra2_dma_loop;
933: }
934: } else {
935: test DFCNTRL, SCSIEN jnz ultra2_dma_loop;
936: }
937:
938: ultra2_dmafinish:
939: /*
940: * The transfer has terminated either due to a phase
941: * change, and/or the completion of the last segment.
942: * We have two goals here. Do as much other work
943: * as possible while the data fifo drains on a read
944: * and respond as quickly as possible to the standard
945: * messages (save data pointers/disconnect and command
946: * complete) that usually follow a data phase.
947: */
948: if ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0) {
949: /*
950: * On chips with broken auto-flush, start
951: * the flushing process now. We'll poke
952: * the chip from time to time to keep the
953: * flush process going as we complete the
954: * data phase.
955: */
956: or DFCNTRL, FIFOFLUSH;
957: }
958: /*
959: * We assume that, even though data may still be
960: * transferring to the host, that the SCSI side of
961: * the DMA engine is now in a static state. This
962: * allows us to update our notion of where we are
963: * in this transfer.
964: *
965: * If, by chance, we stopped before being able
966: * to fetch additional segments for this transfer,
967: * yet the last S/G was completely exhausted,
968: * call our idle loop until it is able to load
969: * another segment. This will allow us to immediately
970: * pickup on the next segment on the next data phase.
971: *
972: * If we happened to stop on the last segment, then
973: * our residual information is still correct from
974: * the idle loop and there is no need to perform
975: * any fixups.
976: */
977: ultra2_ensure_sg:
978: test SG_CACHE_SHADOW, LAST_SEG jz ultra2_shvalid;
979: /* Record if we've consumed all S/G entries */
980: test SSTAT2, SHVALID jnz residuals_correct;
981: or SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL;
982: jmp residuals_correct;
983:
984: ultra2_shvalid:
985: test SSTAT2, SHVALID jnz sgptr_fixup;
986: call idle_loop;
987: jmp ultra2_ensure_sg;
988:
989: sgptr_fixup:
990: /*
991: * Fixup the residual next S/G pointer. The S/G preload
992: * feature of the chip allows us to load two elements
993: * in addition to the currently active element. We
994: * store the bottom byte of the next S/G pointer in
995: * the SG_CACEPTR register so we can restore the
996: * correct value when the DMA completes. If the next
997: * sg ptr value has advanced to the point where higher
998: * bytes in the address have been affected, fix them
999: * too.
1000: */
1001: test SG_CACHE_SHADOW, 0x80 jz sgptr_fixup_done;
1002: test SCB_RESIDUAL_SGPTR[0], 0x80 jnz sgptr_fixup_done;
1003: add SCB_RESIDUAL_SGPTR[1], -1;
1004: adc SCB_RESIDUAL_SGPTR[2], -1;
1005: adc SCB_RESIDUAL_SGPTR[3], -1;
1006: sgptr_fixup_done:
1007: and SCB_RESIDUAL_SGPTR[0], SG_ADDR_MASK, SG_CACHE_SHADOW;
1008: /* We are not the last seg */
1009: and SCB_RESIDUAL_DATACNT[3], ~SG_LAST_SEG;
1010: residuals_correct:
1011: /*
1012: * Go ahead and shut down the DMA engine now.
1013: * In the future, we'll want to handle end of
1014: * transfer messages prior to doing this, but this
1015: * requires similar restructuring for pre-ULTRA2
1016: * controllers.
1017: */
1018: test DMAPARAMS, DIRECTION jnz ultra2_fifoempty;
1019: ultra2_fifoflush:
1020: if ((ahc->features & AHC_DT) == 0) {
1021: if ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0) {
1022: /*
1023: * On Rev A of the aic7890, the autoflush
1024: * feature doesn't function correctly.
1025: * Perform an explicit manual flush. During
1026: * a manual flush, the FIFOEMP bit becomes
1027: * true every time the PCI FIFO empties
1028: * regardless of the state of the SCSI FIFO.
1029: * It can take up to 4 clock cycles for the
1030: * SCSI FIFO to get data into the PCI FIFO
1031: * and for FIFOEMP to de-assert. Here we
1032: * guard against this condition by making
1033: * sure the FIFOEMP bit stays on for 5 full
1034: * clock cycles.
1035: */
1036: or DFCNTRL, FIFOFLUSH;
1037: test DFSTATUS, FIFOEMP jz ultra2_fifoflush;
1038: test DFSTATUS, FIFOEMP jz ultra2_fifoflush;
1039: test DFSTATUS, FIFOEMP jz ultra2_fifoflush;
1040: test DFSTATUS, FIFOEMP jz ultra2_fifoflush;
1041: }
1042: test DFSTATUS, FIFOEMP jz ultra2_fifoflush;
1043: } else {
1044: /*
1045: * We enable the auto-ack feature on DT capable
1046: * controllers. This means that the controller may
1047: * have already transferred some overrun bytes into
1048: * the data FIFO and acked them on the bus. The only
1049: * way to detect this situation is to wait for
1050: * LAST_SEG_DONE to come true on a completed transfer
1051: * and then test to see if the data FIFO is non-empty.
1052: */
1053: test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL
1054: jz ultra2_wait_fifoemp;
1055: test SG_CACHE_SHADOW, LAST_SEG_DONE jz .;
1056: /*
1057: * FIFOEMP can lag LAST_SEG_DONE. Wait a few
1058: * clocks before calling this an overrun.
1059: */
1060: test DFSTATUS, FIFOEMP jnz ultra2_fifoempty;
1061: test DFSTATUS, FIFOEMP jnz ultra2_fifoempty;
1062: test DFSTATUS, FIFOEMP jnz ultra2_fifoempty;
1063: /* Overrun */
1064: jmp data_phase_loop;
1065: ultra2_wait_fifoemp:
1066: test DFSTATUS, FIFOEMP jz .;
1067: }
1068: ultra2_fifoempty:
1069: /* Don't clobber an inprogress host data transfer */
1070: test DFSTATUS, MREQPEND jnz ultra2_fifoempty;
1071: ultra2_dmahalt:
1072: and DFCNTRL, ~(SCSIEN|HDMAEN);
1073: test DFCNTRL, SCSIEN|HDMAEN jnz .;
1074: if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
1075: /*
1076: * Keep HHADDR cleared for future, 32bit addressed
1077: * only, DMA operations.
1078: *
1079: * Due to bayonette style S/G handling, our residual
1080: * data must be "fixed up" once the transfer is halted.
1081: * Here we fixup the HSHADDR stored in the high byte
1082: * of the residual data cnt. By postponing the fixup,
1083: * we can batch the clearing of HADDR with the fixup.
1084: * If we halted on the last segment, the residual is
1085: * already correct. If we are not on the last
1086: * segment, copy the high address directly from HSHADDR.
1087: * We don't need to worry about maintaining the
1088: * SG_LAST_SEG flag as it will always be false in the
1089: * case where an update is required.
1090: */
1091: or DSCOMMAND1, HADDLDSEL0;
1092: test SG_CACHE_SHADOW, LAST_SEG jnz . + 2;
1093: mov SCB_RESIDUAL_DATACNT[3], SHADDR;
1094: clr HADDR;
1095: and DSCOMMAND1, ~HADDLDSEL0;
1096: }
1097: } else {
1098: /* If we are the last SG block, tell the hardware. */
1099: if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0
1100: && ahc->pci_cachesize != 0) {
1101: test MWI_RESIDUAL, 0xFF jnz dma_mid_sg;
1102: }
1103: test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz dma_mid_sg;
1104: if ((ahc->flags & AHC_TARGETROLE) != 0) {
1105: test SSTAT0, TARGET jz dma_last_sg;
1106: if ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0) {
1107: test DMAPARAMS, DIRECTION jz dma_mid_sg;
1108: }
1109: }
1110: dma_last_sg:
1111: and DMAPARAMS, ~WIDEODD;
1112: dma_mid_sg:
1113: /* Start DMA data transfer. */
1114: mov DFCNTRL, DMAPARAMS;
1115: dma_loop:
1116: if ((ahc->features & AHC_CMD_CHAN) != 0) {
1117: call idle_loop;
1118: }
1119: test SSTAT0,DMADONE jnz dma_dmadone;
1120: test SSTAT1,PHASEMIS jz dma_loop; /* ie. underrun */
1121: dma_phasemis:
1122: /*
1123: * We will be "done" DMAing when the transfer count goes to
1124: * zero, or the target changes the phase (in light of this,
1125: * it makes sense that the DMA circuitry doesn't ACK when
1126: * PHASEMIS is active). If we are doing a SCSI->Host transfer,
1127: * the data FIFO should be flushed auto-magically on STCNT=0
1128: * or a phase change, so just wait for FIFO empty status.
1129: */
1130: dma_checkfifo:
1131: test DFCNTRL,DIRECTION jnz dma_fifoempty;
1132: dma_fifoflush:
1133: test DFSTATUS,FIFOEMP jz dma_fifoflush;
1134: dma_fifoempty:
1135: /* Don't clobber an inprogress host data transfer */
1136: test DFSTATUS, MREQPEND jnz dma_fifoempty;
1137:
1138: /*
1139: * Now shut off the DMA and make sure that the DMA
1140: * hardware has actually stopped. Touching the DMA
1141: * counters, etc. while a DMA is active will result
1142: * in an ILLSADDR exception.
1143: */
1144: dma_dmadone:
1145: and DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN);
1146: dma_halt:
1147: /*
1148: * Some revisions of the aic78XX have a problem where, if the
1149: * data fifo is full, but the PCI input latch is not empty,
1150: * HDMAEN cannot be cleared. The fix used here is to drain
1151: * the prefetched but unused data from the data fifo until
1152: * there is space for the input latch to drain.
1153: */
1154: if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0) {
1155: mov NONE, DFDAT;
1156: }
1157: test DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz dma_halt;
1158:
1159: /* See if we have completed this last segment */
1160: test STCNT[0], 0xff jnz data_phase_finish;
1161: test STCNT[1], 0xff jnz data_phase_finish;
1162: test STCNT[2], 0xff jnz data_phase_finish;
1163:
1164: /*
1165: * Advance the scatter-gather pointers if needed
1166: */
1167: if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0
1168: && ahc->pci_cachesize != 0) {
1169: test MWI_RESIDUAL, 0xFF jz no_mwi_resid;
1170: /*
1171: * Reload HADDR from SHADDR and setup the
1172: * count to be the size of our residual.
1173: */
1174: if ((ahc->features & AHC_CMD_CHAN) != 0) {
1175: bmov HADDR, SHADDR, 4;
1176: mov HCNT, MWI_RESIDUAL;
1177: bmov HCNT[1], ALLZEROS, 2;
1178: } else {
1179: mvi DINDEX, HADDR;
1180: mvi SHADDR call bcopy_4;
1181: mov MWI_RESIDUAL call set_hcnt;
1182: }
1183: clr MWI_RESIDUAL;
1184: jmp sg_load_done;
1185: no_mwi_resid:
1186: }
1187: test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz sg_load;
1188: or SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL;
1189: jmp data_phase_finish;
1190: sg_load:
1191: /*
1192: * Load the next SG element's data address and length
1193: * into the DMA engine. If we don't have hardware
1194: * to perform a prefetch, we'll have to fetch the
1195: * segment from host memory first.
1196: */
1197: if ((ahc->features & AHC_CMD_CHAN) != 0) {
1198: /* Wait for the idle loop to complete */
1199: test CCSGCTL, CCSGEN jz . + 3;
1200: call idle_loop;
1201: test CCSGCTL, CCSGEN jnz . - 1;
1202: bmov HADDR, CCSGRAM, 7;
1203: /*
1204: * Workaround for flaky external SCB RAM
1205: * on certain aic7895 setups. It seems
1206: * unable to handle direct transfers from
1207: * S/G ram to certain SCB locations.
1208: */
1209: mov SINDEX, CCSGRAM;
1210: mov SCB_RESIDUAL_DATACNT[3], SINDEX;
1211: } else {
1212: if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
1213: mov ALLZEROS call set_hhaddr;
1214: }
1215: mvi DINDEX, HADDR;
1216: mvi SCB_RESIDUAL_SGPTR call bcopy_4;
1217:
1218: mvi SG_SIZEOF call set_hcnt;
1219:
1220: or DFCNTRL, HDMAEN|DIRECTION|FIFORESET;
1221:
1222: call dma_finish;
1223:
1224: mvi DINDEX, HADDR;
1225: call dfdat_in_7;
1226: mov SCB_RESIDUAL_DATACNT[3], DFDAT;
1227: }
1228:
1229: if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
1230: mov SCB_RESIDUAL_DATACNT[3] call set_hhaddr;
1231:
1232: /*
1233: * The lowest address byte must be loaded
1234: * last as it triggers the computation of
1235: * some items in the PCI block. The ULTRA2
1236: * chips do this on PRELOAD.
1237: */
1238: mov HADDR, HADDR;
1239: }
1240: if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0
1241: && ahc->pci_cachesize != 0) {
1242: call calc_mwi_residual;
1243: }
1244:
1245: /* Point to the new next sg in memory */
1246: call sg_advance;
1247:
1248: sg_load_done:
1249: if ((ahc->features & AHC_CMD_CHAN) != 0) {
1250: bmov STCNT, HCNT, 3;
1251: } else {
1252: call set_stcnt_from_hcnt;
1253: }
1254:
1255: if ((ahc->flags & AHC_TARGETROLE) != 0) {
1256: test SSTAT0, TARGET jnz data_phase_loop;
1257: }
1258: }
1259: data_phase_finish:
1260: /*
1261: * If the target has left us in data phase, loop through
1262: * the DMA code again. In the case of ULTRA2 adapters,
1263: * we should only loop if there is a data overrun. For
1264: * all other adapters, we'll loop after each S/G element
1265: * is loaded as well as if there is an overrun.
1266: */
1267: if ((ahc->flags & AHC_TARGETROLE) != 0) {
1268: test SSTAT0, TARGET jnz data_phase_done;
1269: }
1270: if ((ahc->flags & AHC_INITIATORROLE) != 0) {
1271: test SSTAT1, REQINIT jz .;
1272: if ((ahc->features & AHC_DT) == 0) {
1273: test SSTAT1,PHASEMIS jz data_phase_loop;
1274: } else {
1275: test SCSIPHASE, DATA_PHASE_MASK jnz data_phase_loop;
1276: }
1277: }
1278:
1279: data_phase_done:
1280: /*
1281: * After a DMA finishes, save the SG and STCNT residuals back into
1282: * the SCB. We use STCNT instead of HCNT, since it's a reflection
1283: * of how many bytes were transferred on the SCSI (as opposed to the
1284: * host) bus.
1285: */
1286: if ((ahc->features & AHC_CMD_CHAN) != 0) {
1287: /* Kill off any pending prefetch */
1288: call disable_ccsgen;
1289: }
1290:
1291: if ((ahc->features & AHC_ULTRA2) == 0) {
1292: /*
1293: * Clear the high address byte so that all other DMA
1294: * operations, which use 32bit addressing, can assume
1295: * HHADDR is 0.
1296: */
1297: if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
1298: mov ALLZEROS call set_hhaddr;
1299: }
1300: }
1301:
1302: /*
1303: * Update our residual information before the information is
1304: * lost by some other type of SCSI I/O (e.g. PIO). If we have
1305: * transferred all data, no update is needed.
1306: *
1307: */
1308: test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jnz residual_update_done;
1309: if ((ahc->bugs & AHC_PCI_MWI_BUG) != 0
1310: && ahc->pci_cachesize != 0) {
1311: if ((ahc->features & AHC_CMD_CHAN) != 0) {
1312: test MWI_RESIDUAL, 0xFF jz bmov_resid;
1313: }
1314: mov A, MWI_RESIDUAL;
1315: add SCB_RESIDUAL_DATACNT[0], A, STCNT[0];
1316: clr A;
1317: adc SCB_RESIDUAL_DATACNT[1], A, STCNT[1];
1318: adc SCB_RESIDUAL_DATACNT[2], A, STCNT[2];
1319: clr MWI_RESIDUAL;
1320: if ((ahc->features & AHC_CMD_CHAN) != 0) {
1321: jmp . + 2;
1322: bmov_resid:
1323: bmov SCB_RESIDUAL_DATACNT, STCNT, 3;
1324: }
1325: } else if ((ahc->features & AHC_CMD_CHAN) != 0) {
1326: bmov SCB_RESIDUAL_DATACNT, STCNT, 3;
1327: } else {
1328: mov SCB_RESIDUAL_DATACNT[0], STCNT[0];
1329: mov SCB_RESIDUAL_DATACNT[1], STCNT[1];
1330: mov SCB_RESIDUAL_DATACNT[2], STCNT[2];
1331: }
1332: residual_update_done:
1333: /*
1334: * Since we've been through a data phase, the SCB_RESID* fields
1335: * are now initialized. Clear the full residual flag.
1336: */
1337: and SCB_SGPTR[0], ~SG_FULL_RESID;
1338:
1339: if ((ahc->features & AHC_ULTRA2) != 0) {
1340: /* Clear the channel in case we return to data phase later */
1341: or SXFRCTL0, CLRSTCNT|CLRCHN;
1342: or SXFRCTL0, CLRSTCNT|CLRCHN;
1343: }
1344:
1345: if ((ahc->flags & AHC_TARGETROLE) != 0) {
1346: test SEQ_FLAGS, DPHASE_PENDING jz ITloop;
1347: and SEQ_FLAGS, ~DPHASE_PENDING;
1348: /*
1349: * For data-in phases, wait for any pending acks from the
1350: * initiator before changing phase. We only need to
1351: * send Ignore Wide Residue messages for data-in phases.
1352: */
1353: test DFCNTRL, DIRECTION jz target_ITloop;
1354: test SSTAT1, REQINIT jnz .;
1355: test SCB_LUN, SCB_XFERLEN_ODD jz target_ITloop;
1356: test SCSIRATE, WIDEXFER jz target_ITloop;
1357: /*
1358: * Issue an Ignore Wide Residue Message.
1359: */
1360: mvi P_MESGIN|BSYO call change_phase;
1361: mvi MSG_IGN_WIDE_RESIDUE call target_outb;
1362: mvi 1 call target_outb;
1363: jmp target_ITloop;
1364: } else {
1365: jmp ITloop;
1366: }
1367:
1368: if ((ahc->flags & AHC_INITIATORROLE) != 0) {
1369: /*
1370: * Command phase. Set up the DMA registers and let 'er rip.
1371: */
1372: p_command:
1373: test SEQ_FLAGS, NOT_IDENTIFIED jz p_command_okay;
1374: mvi PROTO_VIOLATION call set_seqint;
1375: p_command_okay:
1376:
1377: if ((ahc->features & AHC_ULTRA2) != 0) {
1378: bmov HCNT[0], SCB_CDB_LEN, 1;
1379: bmov HCNT[1], ALLZEROS, 2;
1380: mvi SG_CACHE_PRE, LAST_SEG;
1381: } else if ((ahc->features & AHC_CMD_CHAN) != 0) {
1382: bmov STCNT[0], SCB_CDB_LEN, 1;
1383: bmov STCNT[1], ALLZEROS, 2;
1384: } else {
1385: mov STCNT[0], SCB_CDB_LEN;
1386: clr STCNT[1];
1387: clr STCNT[2];
1388: }
1389: add NONE, -13, SCB_CDB_LEN;
1390: mvi SCB_CDB_STORE jnc p_command_embedded;
1391: p_command_from_host:
1392: if ((ahc->features & AHC_ULTRA2) != 0) {
1393: bmov HADDR[0], SCB_CDB_PTR, 4;
1394: mvi DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN|DIRECTION);
1395: } else {
1396: if ((ahc->features & AHC_CMD_CHAN) != 0) {
1397: bmov HADDR[0], SCB_CDB_PTR, 4;
1398: bmov HCNT, STCNT, 3;
1399: } else {
1400: mvi DINDEX, HADDR;
1401: mvi SCB_CDB_PTR call bcopy_4;
1402: mov SCB_CDB_LEN call set_hcnt;
1403: }
1404: mvi DFCNTRL, (SCSIEN|SDMAEN|HDMAEN|DIRECTION|FIFORESET);
1405: }
1406: jmp p_command_xfer;
1407: p_command_embedded:
1408: /*
1409: * The data fifo seems to require 4 byte aligned
1410: * transfers from the sequencer. Force this to
1411: * be the case by clearing HADDR[0] even though
1412: * we aren't going to touch host memory.
1413: */
1414: clr HADDR[0];
1415: if ((ahc->features & AHC_ULTRA2) != 0) {
1416: mvi DFCNTRL, (PRELOADEN|SCSIEN|DIRECTION);
1417: bmov DFDAT, SCB_CDB_STORE, 12;
1418: } else if ((ahc->features & AHC_CMD_CHAN) != 0) {
1419: if ((ahc->flags & AHC_SCB_BTT) != 0) {
1420: /*
1421: * On the 7895 the data FIFO will
1422: * get corrupted if you try to dump
1423: * data from external SCB memory into
1424: * the FIFO while it is enabled. So,
1425: * fill the fifo and then enable SCSI
1426: * transfers.
1427: */
1428: mvi DFCNTRL, (DIRECTION|FIFORESET);
1429: } else {
1430: mvi DFCNTRL, (SCSIEN|SDMAEN|DIRECTION|FIFORESET);
1431: }
1432: bmov DFDAT, SCB_CDB_STORE, 12;
1433: if ((ahc->flags & AHC_SCB_BTT) != 0) {
1434: mvi DFCNTRL, (SCSIEN|SDMAEN|DIRECTION|FIFOFLUSH);
1435: } else {
1436: or DFCNTRL, FIFOFLUSH;
1437: }
1438: } else {
1439: mvi DFCNTRL, (SCSIEN|SDMAEN|DIRECTION|FIFORESET);
1440: call copy_to_fifo_6;
1441: call copy_to_fifo_6;
1442: or DFCNTRL, FIFOFLUSH;
1443: }
1444: p_command_xfer:
1445: and SEQ_FLAGS, ~NO_CDB_SENT;
1446: if ((ahc->features & AHC_DT) == 0) {
1447: test SSTAT0, SDONE jnz . + 2;
1448: test SSTAT1, PHASEMIS jz . - 1;
1449: /*
1450: * Wait for our ACK to go-away on its own
1451: * instead of being killed by SCSIEN getting cleared.
1452: */
1453: test SCSISIGI, ACKI jnz .;
1454: } else {
1455: test DFCNTRL, SCSIEN jnz .;
1456: }
1457: test SSTAT0, SDONE jnz p_command_successful;
1458: /*
1459: * Don't allow a data phase if the command
1460: * was not fully transferred.
1461: */
1462: or SEQ_FLAGS, NO_CDB_SENT;
1463: p_command_successful:
1464: and DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN);
1465: test DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz .;
1466: jmp ITloop;
1467:
1468: /*
1469: * Status phase. Wait for the data byte to appear, then read it
1470: * and store it into the SCB.
1471: */
1472: p_status:
1473: test SEQ_FLAGS, NOT_IDENTIFIED jnz mesgin_proto_violation;
1474: p_status_okay:
1475: mov SCB_SCSI_STATUS, SCSIDATL;
1476: or SCB_CONTROL, STATUS_RCVD;
1477: jmp ITloop;
1478:
1479: /*
1480: * Message out phase. If MSG_OUT is MSG_IDENTIFYFLAG, build a full
1481: * identify message sequence and send it to the target. The host may
1482: * override this behavior by setting the MK_MESSAGE bit in the SCB
1483: * control byte. This will cause us to interrupt the host and allow
1484: * it to handle the message phase completely on its own. If the bit
1485: * associated with this target is set, we will also interrupt the host,
1486: * thereby allowing it to send a message on the next selection regardless
1487: * of the transaction being sent.
1488: *
1489: * If MSG_OUT is == HOST_MSG, also interrupt the host and take a message.
1490: * This is done to allow the host to send messages outside of an identify
1491: * sequence while protecting the sequencer from testing the MK_MESSAGE bit
1492: * on an SCB that might not be for the current nexus. (For example, a
1493: * BDR message in response to a bad reselection would leave us pointed to
1494: * an SCB that doesn't have anything to do with the current target).
1495: *
1496: * Otherwise, treat MSG_OUT as a 1 byte message to send (abort, abort tag,
1497: * bus device reset).
1498: *
1499: * When there are no messages to send, MSG_OUT should be set to MSG_NOOP,
1500: * in case the target decides to put us in this phase for some strange
1501: * reason.
1502: */
1503: p_mesgout_retry:
1504: /* Turn on ATN for the retry */
1505: if ((ahc->features & AHC_DT) == 0) {
1506: or SCSISIGO, ATNO, LASTPHASE;
1507: } else {
1508: mvi SCSISIGO, ATNO;
1509: }
1510: p_mesgout:
1511: mov SINDEX, MSG_OUT;
1512: cmp SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host;
1513: test SCB_CONTROL,MK_MESSAGE jnz host_message_loop;
1514: p_mesgout_identify:
1515: or SINDEX, MSG_IDENTIFYFLAG|DISCENB, SAVED_LUN;
1516: test SCB_CONTROL, DISCENB jnz . + 2;
1517: and SINDEX, ~DISCENB;
1518: /*
1519: * Send a tag message if TAG_ENB is set in the SCB control block.
1520: * Use SCB_TAG (the position in the kernel's SCB array) as the tag value.
1521: */
1522: p_mesgout_tag:
1523: test SCB_CONTROL,TAG_ENB jz p_mesgout_onebyte;
1524: mov SCSIDATL, SINDEX; /* Send the identify message */
1525: call phase_lock;
1526: cmp LASTPHASE, P_MESGOUT jne p_mesgout_done;
1527: and SCSIDATL,TAG_ENB|SCB_TAG_TYPE,SCB_CONTROL;
1528: call phase_lock;
1529: cmp LASTPHASE, P_MESGOUT jne p_mesgout_done;
1530: mov SCB_TAG jmp p_mesgout_onebyte;
1531: /*
1532: * Interrupt the driver, and allow it to handle this message
1533: * phase and any required retries.
1534: */
1535: p_mesgout_from_host:
1536: cmp SINDEX, HOST_MSG jne p_mesgout_onebyte;
1537: jmp host_message_loop;
1538:
1539: p_mesgout_onebyte:
1540: mvi CLRSINT1, CLRATNO;
1541: mov SCSIDATL, SINDEX;
1542:
1543: /*
1544: * If the next bus phase after ATN drops is message out, it means
1545: * that the target is requesting that the last message(s) be resent.
1546: */
1547: call phase_lock;
1548: cmp LASTPHASE, P_MESGOUT je p_mesgout_retry;
1549:
1550: p_mesgout_done:
1551: mvi CLRSINT1,CLRATNO; /* Be sure to turn ATNO off */
1552: mov LAST_MSG, MSG_OUT;
1553: mvi MSG_OUT, MSG_NOOP; /* No message left */
1554: jmp ITloop;
1555:
1556: /*
1557: * Message in phase. Bytes are read using Automatic PIO mode.
1558: */
1559: p_mesgin:
1560: mvi ACCUM call inb_first; /* read the 1st message byte */
1561:
1562: test A,MSG_IDENTIFYFLAG jnz mesgin_identify;
1563: cmp A,MSG_DISCONNECT je mesgin_disconnect;
1564: cmp A,MSG_SAVEDATAPOINTER je mesgin_sdptrs;
1565: cmp ALLZEROS,A je mesgin_complete;
1566: cmp A,MSG_RESTOREPOINTERS je mesgin_rdptrs;
1567: cmp A,MSG_IGN_WIDE_RESIDUE je mesgin_ign_wide_residue;
1568: cmp A,MSG_NOOP je mesgin_done;
1569:
1570: /*
1571: * Pushed message loop to allow the kernel to
1572: * run its own message state engine. To avoid an
1573: * extra nop instruction after signaling the kernel,
1574: * we perform the phase_lock before checking to see
1575: * if we should exit the loop and skip the phase_lock
1576: * in the ITloop. Performing back to back phase_locks
1577: * shouldn't hurt, but why do it twice...
1578: */
1579: host_message_loop:
1580: mvi HOST_MSG_LOOP call set_seqint;
1581: call phase_lock;
1582: cmp RETURN_1, EXIT_MSG_LOOP je ITloop + 1;
1583: jmp host_message_loop;
1584:
1585: mesgin_ign_wide_residue:
1586: if ((ahc->features & AHC_WIDE) != 0) {
1587: test SCSIRATE, WIDEXFER jz mesgin_reject;
1588: /* Pull the residue byte */
1589: mvi ARG_1 call inb_next;
1590: cmp ARG_1, 0x01 jne mesgin_reject;
1591: test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz . + 2;
1592: test SCB_LUN, SCB_XFERLEN_ODD jnz mesgin_done;
1593: mvi IGN_WIDE_RES call set_seqint;
1594: jmp mesgin_done;
1595: }
1596:
1597: mesgin_proto_violation:
1598: mvi PROTO_VIOLATION call set_seqint;
1599: jmp mesgin_done;
1600: mesgin_reject:
1601: mvi MSG_MESSAGE_REJECT call mk_mesg;
1602: mesgin_done:
1603: mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
1604: jmp ITloop;
1605:
1606: /*
1607: * We received a "command complete" message. Put the SCB_TAG into the QOUTFIFO,
1608: * and trigger a completion interrupt. Before doing so, check to see if there
1609: * is a residual or the status byte is something other than STATUS_GOOD (0).
1610: * In either of these conditions, we upload the SCB back to the host so it can
1611: * process this information. In the case of a non zero status byte, we
1612: * additionally interrupt the kernel driver synchronously, allowing it to
1613: * decide if sense should be retrieved. If the kernel driver wishes to request
1614: * sense, it will fill the kernel SCB with a request sense command, requeue
1615: * it to the QINFIFO and tell us not to post to the QOUTFIFO by setting
1616: * RETURN_1 to SEND_SENSE.
1617: */
1618: mesgin_complete:
1619:
1620: /*
1621: * If ATN is raised, we still want to give the target a message.
1622: * Perhaps there was a parity error on this last message byte.
1623: * Either way, the target should take us to message out phase
1624: * and then attempt to complete the command again. We should use a
1625: * critical section here to guard against a timeout triggering
1626: * for this command and setting ATN while we are still processing
1627: * the completion.
1628: test SCSISIGI, ATNI jnz mesgin_done;
1629: */
1630:
1631: /*
1632: * If we are identified and have successfully sent the CDB,
1633: * any status will do. Optimize this fast path.
1634: */
1635: test SCB_CONTROL, STATUS_RCVD jz mesgin_proto_violation;
1636: test SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT jz complete_accepted;
1637:
1638: /*
1639: * If the target never sent an identify message but instead went
1640: * to mesgin to give an invalid message, let the host abort us.
1641: */
1642: test SEQ_FLAGS, NOT_IDENTIFIED jnz mesgin_proto_violation;
1643:
1644: /*
1645: * If we received good status but never successfully sent the
1646: * cdb, abort the command.
1647: */
1648: test SCB_SCSI_STATUS,0xff jnz complete_accepted;
1649: test SEQ_FLAGS, NO_CDB_SENT jnz mesgin_proto_violation;
1650:
1651: complete_accepted:
1652: /*
1653: * See if we attempted to deliver a message but the target ingnored us.
1654: */
1655: test SCB_CONTROL, MK_MESSAGE jz . + 2;
1656: mvi MKMSG_FAILED call set_seqint;
1657:
1658: /*
1659: * Check for residuals
1660: */
1661: test SCB_SGPTR, SG_LIST_NULL jnz check_status;/* No xfer */
1662: test SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */
1663: test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb;
1664: check_status:
1665: test SCB_SCSI_STATUS,0xff jz complete; /* Good Status? */
1666: upload_scb:
1667: or SCB_SGPTR, SG_RESID_VALID;
1668: mvi DMAPARAMS, FIFORESET;
1669: mov SCB_TAG call dma_scb;
1670: test SCB_SCSI_STATUS, 0xff jz complete; /* Just a residual? */
1671: mvi BAD_STATUS call set_seqint; /* let driver know */
1672: cmp RETURN_1, SEND_SENSE jne complete;
1673: call add_scb_to_free_list;
1674: jmp await_busfree;
1675: complete:
1676: mov SCB_TAG call complete_post;
1677: jmp await_busfree;
1678: }
1679:
1680: complete_post:
1681: /* Post the SCBID in SINDEX and issue an interrupt */
1682: call add_scb_to_free_list;
1683: mov ARG_1, SINDEX;
1684: if ((ahc->features & AHC_QUEUE_REGS) != 0) {
1685: mov A, SDSCB_QOFF;
1686: } else {
1687: mov A, QOUTPOS;
1688: }
1689: mvi QOUTFIFO_OFFSET call post_byte_setup;
1690: mov ARG_1 call post_byte;
1691: if ((ahc->features & AHC_QUEUE_REGS) == 0) {
1692: inc QOUTPOS;
1693: }
1694: mvi INTSTAT,CMDCMPLT ret;
1695:
1696: if ((ahc->flags & AHC_INITIATORROLE) != 0) {
1697: /*
1698: * Is it a disconnect message? Set a flag in the SCB to remind us
1699: * and await the bus going free. If this is an untagged transaction
1700: * store the SCB id for it in our untagged target table for lookup on
1701: * a reselection.
1702: */
1703: mesgin_disconnect:
1704: /*
1705: * If ATN is raised, we still want to give the target a message.
1706: * Perhaps there was a parity error on this last message byte
1707: * or we want to abort this command. Either way, the target
1708: * should take us to message out phase and then attempt to
1709: * disconnect again.
1710: * XXX - Wait for more testing.
1711: test SCSISIGI, ATNI jnz mesgin_done;
1712: */
1713: test SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT
1714: jnz mesgin_proto_violation;
1715: or SCB_CONTROL,DISCONNECTED;
1716: if ((ahc->flags & AHC_PAGESCBS) != 0) {
1717: call add_scb_to_disc_list;
1718: }
1719: test SCB_CONTROL, TAG_ENB jnz await_busfree;
1720: mov ARG_1, SCB_TAG;
1721: and SAVED_LUN, LID, SCB_LUN;
1722: mov SCB_SCSIID call set_busy_target;
1723: jmp await_busfree;
1724:
1725: /*
1726: * Save data pointers message:
1727: * Copying RAM values back to SCB, for Save Data Pointers message, but
1728: * only if we've actually been into a data phase to change them. This
1729: * protects against bogus data in scratch ram and the residual counts
1730: * since they are only initialized when we go into data_in or data_out.
1731: * Ack the message as soon as possible. For chips without S/G pipelining,
1732: * we can only ack the message after SHADDR has been saved. On these
1733: * chips, SHADDR increments with every bus transaction, even PIO.
1734: */
1735: mesgin_sdptrs:
1736: if ((ahc->features & AHC_ULTRA2) != 0) {
1737: mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
1738: test SEQ_FLAGS, DPHASE jz ITloop;
1739: } else {
1740: test SEQ_FLAGS, DPHASE jz mesgin_done;
1741: }
1742:
1743: /*
1744: * If we are asked to save our position at the end of the
1745: * transfer, just mark us at the end rather than perform a
1746: * full save.
1747: */
1748: test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz mesgin_sdptrs_full;
1749: or SCB_SGPTR, SG_LIST_NULL;
1750: if ((ahc->features & AHC_ULTRA2) != 0) {
1751: jmp ITloop;
1752: } else {
1753: jmp mesgin_done;
1754: }
1755:
1756: mesgin_sdptrs_full:
1757:
1758: /*
1759: * The SCB_SGPTR becomes the next one we'll download,
1760: * and the SCB_DATAPTR becomes the current SHADDR.
1761: * Use the residual number since STCNT is corrupted by
1762: * any message transfer.
1763: */
1764: if ((ahc->features & AHC_CMD_CHAN) != 0) {
1765: bmov SCB_DATAPTR, SHADDR, 4;
1766: if ((ahc->features & AHC_ULTRA2) == 0) {
1767: mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
1768: }
1769: bmov SCB_DATACNT, SCB_RESIDUAL_DATACNT, 8;
1770: } else {
1771: mvi DINDEX, SCB_DATAPTR;
1772: mvi SHADDR call bcopy_4;
1773: mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
1774: mvi SCB_RESIDUAL_DATACNT call bcopy_8;
1775: }
1776: jmp ITloop;
1777:
1778: /*
1779: * Restore pointers message? Data pointers are recopied from the
1780: * SCB anytime we enter a data phase for the first time, so all
1781: * we need to do is clear the DPHASE flag and let the data phase
1782: * code do the rest. We also reset/reallocate the FIFO to make
1783: * sure we have a clean start for the next data or command phase.
1784: */
1785: mesgin_rdptrs:
1786: and SEQ_FLAGS, ~DPHASE; /*
1787: * We'll reload them
1788: * the next time through
1789: * the dataphase.
1790: */
1791: or SXFRCTL0, CLRSTCNT|CLRCHN;
1792: jmp mesgin_done;
1793:
1794: /*
1795: * Index into our Busy Target table. SINDEX and DINDEX are modified
1796: * upon return. SCBPTR may be modified by this action.
1797: */
1798: set_busy_target:
1799: shr DINDEX, 4, SINDEX;
1800: if ((ahc->flags & AHC_SCB_BTT) != 0) {
1801: mov SCBPTR, SAVED_LUN;
1802: add DINDEX, SCB_64_BTT;
1803: } else {
1804: add DINDEX, BUSY_TARGETS;
1805: }
1806: mov DINDIR, ARG_1 ret;
1807:
1808: /*
1809: * Identify message? For a reconnecting target, this tells us the lun
1810: * that the reconnection is for - find the correct SCB and switch to it,
1811: * clearing the "disconnected" bit so we don't "find" it by accident later.
1812: */
1813: mesgin_identify:
1814: /*
1815: * Determine whether a target is using tagged or non-tagged
1816: * transactions by first looking at the transaction stored in
1817: * the busy target array. If there is no untagged transaction
1818: * for this target or the transaction is for a different lun, then
1819: * this must be a tagged transaction.
1820: */
1821: shr SINDEX, 4, SAVED_SCSIID;
1822: and SAVED_LUN, MSG_IDENTIFY_LUNMASK, A;
1823: if ((ahc->flags & AHC_SCB_BTT) != 0) {
1824: add SINDEX, SCB_64_BTT;
1825: mov SCBPTR, SAVED_LUN;
1826: if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
1827: add NONE, -SCB_64_BTT, SINDEX;
1828: jc . + 2;
1829: mvi INTSTAT, OUT_OF_RANGE;
1830: nop;
1831: add NONE, -(SCB_64_BTT + 16), SINDEX;
1832: jnc . + 2;
1833: mvi INTSTAT, OUT_OF_RANGE;
1834: nop;
1835: }
1836: } else {
1837: add SINDEX, BUSY_TARGETS;
1838: if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
1839: add NONE, -BUSY_TARGETS, SINDEX;
1840: jc . + 2;
1841: mvi INTSTAT, OUT_OF_RANGE;
1842: nop;
1843: add NONE, -(BUSY_TARGETS + 16), SINDEX;
1844: jnc . + 2;
1845: mvi INTSTAT, OUT_OF_RANGE;
1846: nop;
1847: }
1848: }
1849: mov ARG_1, SINDIR;
1850: cmp ARG_1, SCB_LIST_NULL je snoop_tag;
1851: if ((ahc->flags & AHC_PAGESCBS) != 0) {
1852: mov ARG_1 call findSCB;
1853: } else {
1854: mov SCBPTR, ARG_1;
1855: }
1856: if ((ahc->flags & AHC_SCB_BTT) != 0) {
1857: jmp setup_SCB_id_lun_okay;
1858: } else {
1859: /*
1860: * We only allow one untagged command per-target
1861: * at a time. So, if the lun doesn't match, look
1862: * for a tag message.
1863: */
1864: and A, LID, SCB_LUN;
1865: cmp SAVED_LUN, A je setup_SCB_id_lun_okay;
1866: if ((ahc->flags & AHC_PAGESCBS) != 0) {
1867: /*
1868: * findSCB removes the SCB from the
1869: * disconnected list, so we must replace
1870: * it there should this SCB be for another
1871: * lun.
1872: */
1873: call cleanup_scb;
1874: }
1875: }
1876:
1877: /*
1878: * Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message.
1879: * If we get one, we use the tag returned to find the proper
1880: * SCB. With SCB paging, we must search for non-tagged
1881: * transactions since the SCB may exist in any slot. If we're not
1882: * using SCB paging, we can use the tag as the direct index to the
1883: * SCB.
1884: */
1885: snoop_tag:
1886: if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
1887: or SEQ_FLAGS, 0x80;
1888: }
1889: mov NONE,SCSIDATL; /* ACK Identify MSG */
1890: call phase_lock;
1891: if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
1892: or SEQ_FLAGS, 0x1;
1893: }
1894: cmp LASTPHASE, P_MESGIN jne not_found;
1895: if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
1896: or SEQ_FLAGS, 0x2;
1897: }
1898: cmp SCSIBUSL,MSG_SIMPLE_Q_TAG jne not_found;
1899: get_tag:
1900: if ((ahc->flags & AHC_PAGESCBS) != 0) {
1901: mvi ARG_1 call inb_next; /* tag value */
1902: mov ARG_1 call findSCB;
1903: } else {
1904: mvi ARG_1 call inb_next; /* tag value */
1905: mov SCBPTR, ARG_1;
1906: }
1907:
1908: /*
1909: * Ensure that the SCB the tag points to is for
1910: * an SCB transaction to the reconnecting target.
1911: */
1912: setup_SCB:
1913: if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
1914: or SEQ_FLAGS, 0x4;
1915: }
1916: mov A, SCB_SCSIID;
1917: cmp SAVED_SCSIID, A jne not_found_cleanup_scb;
1918: if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
1919: or SEQ_FLAGS, 0x8;
1920: }
1921: setup_SCB_id_okay:
1922: and A, LID, SCB_LUN;
1923: cmp SAVED_LUN, A jne not_found_cleanup_scb;
1924: setup_SCB_id_lun_okay:
1925: if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
1926: or SEQ_FLAGS, 0x10;
1927: }
1928: test SCB_CONTROL,DISCONNECTED jz not_found_cleanup_scb;
1929: and SCB_CONTROL,~DISCONNECTED;
1930: test SCB_CONTROL, TAG_ENB jnz setup_SCB_tagged;
1931: if ((ahc->flags & AHC_SCB_BTT) != 0) {
1932: mov A, SCBPTR;
1933: }
1934: mvi ARG_1, SCB_LIST_NULL;
1935: mov SAVED_SCSIID call set_busy_target;
1936: if ((ahc->flags & AHC_SCB_BTT) != 0) {
1937: mov SCBPTR, A;
1938: }
1939: setup_SCB_tagged:
1940: clr SEQ_FLAGS; /* make note of IDENTIFY */
1941: call set_transfer_settings;
1942: /* See if the host wants to send a message upon reconnection */
1943: test SCB_CONTROL, MK_MESSAGE jz mesgin_done;
1944: mvi HOST_MSG call mk_mesg;
1945: jmp mesgin_done;
1946:
1947: not_found_cleanup_scb:
1948: if ((ahc->flags & AHC_PAGESCBS) != 0) {
1949: call cleanup_scb;
1950: }
1951: not_found:
1952: mvi NO_MATCH call set_seqint;
1953: jmp mesgin_done;
1954:
1955: mk_mesg:
1956: if ((ahc->features & AHC_DT) == 0) {
1957: or SCSISIGO, ATNO, LASTPHASE;
1958: } else {
1959: mvi SCSISIGO, ATNO;
1960: }
1961: mov MSG_OUT,SINDEX ret;
1962:
1963: /*
1964: * Functions to read data in Automatic PIO mode.
1965: *
1966: * According to Adaptec's documentation, an ACK is not sent on input from
1967: * the target until SCSIDATL is read from. So we wait until SCSIDATL is
1968: * latched (the usual way), then read the data byte directly off the bus
1969: * using SCSIBUSL. When we have pulled the ATN line, or we just want to
1970: * acknowledge the byte, then we do a dummy read from SCISDATL. The SCSI
1971: * spec guarantees that the target will hold the data byte on the bus until
1972: * we send our ACK.
1973: *
1974: * The assumption here is that these are called in a particular sequence,
1975: * and that REQ is already set when inb_first is called. inb_{first,next}
1976: * use the same calling convention as inb.
1977: */
1978: inb_next_wait_perr:
1979: mvi PERR_DETECTED call set_seqint;
1980: jmp inb_next_wait;
1981: inb_next:
1982: mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
1983: inb_next_wait:
1984: /*
1985: * If there is a parity error, wait for the kernel to
1986: * see the interrupt and prepare our message response
1987: * before continuing.
1988: */
1989: test SSTAT1, REQINIT jz inb_next_wait;
1990: test SSTAT1, SCSIPERR jnz inb_next_wait_perr;
1991: inb_next_check_phase:
1992: and LASTPHASE, PHASE_MASK, SCSISIGI;
1993: cmp LASTPHASE, P_MESGIN jne mesgin_phasemis;
1994: inb_first:
1995: mov DINDEX,SINDEX;
1996: mov DINDIR,SCSIBUSL ret; /*read byte directly from bus*/
1997: inb_last:
1998: mov NONE,SCSIDATL ret; /*dummy read from latch to ACK*/
1999: }
2000:
2001: if ((ahc->flags & AHC_TARGETROLE) != 0) {
2002: /*
2003: * Change to a new phase. If we are changing the state of the I/O signal,
2004: * from out to in, wait an additional data release delay before continuing.
2005: */
2006: change_phase:
2007: /* Wait for preceding I/O session to complete. */
2008: test SCSISIGI, ACKI jnz .;
2009:
2010: /* Change the phase */
2011: and DINDEX, IOI, SCSISIGI;
2012: mov SCSISIGO, SINDEX;
2013: and A, IOI, SINDEX;
2014:
2015: /*
2016: * If the data direction has changed, from
2017: * out (initiator driving) to in (target driving),
2018: * we must wait at least a data release delay plus
2019: * the normal bus settle delay. [SCSI III SPI 10.11.0]
2020: */
2021: cmp DINDEX, A je change_phase_wait;
2022: test SINDEX, IOI jz change_phase_wait;
2023: call change_phase_wait;
2024: change_phase_wait:
2025: nop;
2026: nop;
2027: nop;
2028: nop ret;
2029:
2030: /*
2031: * Send a byte to an initiator in Automatic PIO mode.
2032: */
2033: target_outb:
2034: or SXFRCTL0, SPIOEN;
2035: test SSTAT0, SPIORDY jz .;
2036: mov SCSIDATL, SINDEX;
2037: test SSTAT0, SPIORDY jz .;
2038: and SXFRCTL0, ~SPIOEN ret;
2039: }
2040:
2041: /*
2042: * Locate a disconnected SCB by SCBID. Upon return, SCBPTR and SINDEX will
2043: * be set to the position of the SCB. If the SCB cannot be found locally,
2044: * it will be paged in from host memory. RETURN_2 stores the address of the
2045: * preceding SCB in the disconnected list which can be used to speed up
2046: * removal of the found SCB from the disconnected list.
2047: */
2048: if ((ahc->flags & AHC_PAGESCBS) != 0) {
2049: BEGIN_CRITICAL;
2050: findSCB:
2051: mov A, SINDEX; /* Tag passed in SINDEX */
2052: cmp DISCONNECTED_SCBH, SCB_LIST_NULL je findSCB_notFound;
2053: mov SCBPTR, DISCONNECTED_SCBH; /* Initialize SCBPTR */
2054: mvi ARG_2, SCB_LIST_NULL; /* Head of list */
2055: jmp findSCB_loop;
2056: findSCB_next:
2057: cmp SCB_NEXT, SCB_LIST_NULL je findSCB_notFound;
2058: mov ARG_2, SCBPTR;
2059: mov SCBPTR,SCB_NEXT;
2060: findSCB_loop:
2061: cmp SCB_TAG, A jne findSCB_next;
2062: rem_scb_from_disc_list:
2063: cmp ARG_2, SCB_LIST_NULL je rHead;
2064: mov DINDEX, SCB_NEXT;
2065: mov SINDEX, SCBPTR;
2066: mov SCBPTR, ARG_2;
2067: mov SCB_NEXT, DINDEX;
2068: mov SCBPTR, SINDEX ret;
2069: rHead:
2070: mov DISCONNECTED_SCBH,SCB_NEXT ret;
2071: END_CRITICAL;
2072: findSCB_notFound:
2073: /*
2074: * We didn't find it. Page in the SCB.
2075: */
2076: mov ARG_1, A; /* Save tag */
2077: mov ALLZEROS call get_free_or_disc_scb;
2078: mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
2079: mov ARG_1 jmp dma_scb;
2080: }
2081:
2082: /*
2083: * Prepare the hardware to post a byte to host memory given an
2084: * index of (A + (256 * SINDEX)) and a base address of SHARED_DATA_ADDR.
2085: */
2086: post_byte_setup:
2087: mov ARG_2, SINDEX;
2088: if ((ahc->features & AHC_CMD_CHAN) != 0) {
2089: mvi DINDEX, CCHADDR;
2090: mvi SHARED_DATA_ADDR call set_1byte_addr;
2091: mvi CCHCNT, 1;
2092: mvi CCSCBCTL, CCSCBRESET ret;
2093: } else {
2094: mvi DINDEX, HADDR;
2095: mvi SHARED_DATA_ADDR call set_1byte_addr;
2096: mvi 1 call set_hcnt;
2097: mvi DFCNTRL, FIFORESET ret;
2098: }
2099:
2100: post_byte:
2101: if ((ahc->features & AHC_CMD_CHAN) != 0) {
2102: bmov CCSCBRAM, SINDEX, 1;
2103: or CCSCBCTL, CCSCBEN|CCSCBRESET;
2104: test CCSCBCTL, CCSCBDONE jz .;
2105: clr CCSCBCTL ret;
2106: } else {
2107: mov DFDAT, SINDEX;
2108: or DFCNTRL, HDMAEN|FIFOFLUSH;
2109: jmp dma_finish;
2110: }
2111:
2112: phase_lock_perr:
2113: mvi PERR_DETECTED call set_seqint;
2114: phase_lock:
2115: /*
2116: * If there is a parity error, wait for the kernel to
2117: * see the interrupt and prepare our message response
2118: * before continuing.
2119: */
2120: test SSTAT1, REQINIT jz phase_lock;
2121: test SSTAT1, SCSIPERR jnz phase_lock_perr;
2122: phase_lock_latch_phase:
2123: if ((ahc->features & AHC_DT) == 0) {
2124: and SCSISIGO, PHASE_MASK, SCSISIGI;
2125: }
2126: and LASTPHASE, PHASE_MASK, SCSISIGI ret;
2127:
2128: if ((ahc->features & AHC_CMD_CHAN) == 0) {
2129: set_hcnt:
2130: mov HCNT[0], SINDEX;
2131: clear_hcnt:
2132: clr HCNT[1];
2133: clr HCNT[2] ret;
2134:
2135: set_stcnt_from_hcnt:
2136: mov STCNT[0], HCNT[0];
2137: mov STCNT[1], HCNT[1];
2138: mov STCNT[2], HCNT[2] ret;
2139:
2140: bcopy_8:
2141: mov DINDIR, SINDIR;
2142: bcopy_7:
2143: mov DINDIR, SINDIR;
2144: mov DINDIR, SINDIR;
2145: bcopy_5:
2146: mov DINDIR, SINDIR;
2147: bcopy_4:
2148: mov DINDIR, SINDIR;
2149: bcopy_3:
2150: mov DINDIR, SINDIR;
2151: mov DINDIR, SINDIR;
2152: mov DINDIR, SINDIR ret;
2153: }
2154:
2155: if ((ahc->flags & AHC_TARGETROLE) != 0) {
2156: /*
2157: * Setup addr assuming that A is an index into
2158: * an array of 32byte objects, SINDEX contains
2159: * the base address of that array, and DINDEX
2160: * contains the base address of the location
2161: * to store the indexed address.
2162: */
2163: set_32byte_addr:
2164: shr ARG_2, 3, A;
2165: shl A, 5;
2166: jmp set_1byte_addr;
2167: }
2168:
2169: /*
2170: * Setup addr assuming that A is an index into
2171: * an array of 64byte objects, SINDEX contains
2172: * the base address of that array, and DINDEX
2173: * contains the base address of the location
2174: * to store the indexed address.
2175: */
2176: set_64byte_addr:
2177: shr ARG_2, 2, A;
2178: shl A, 6;
2179:
2180: /*
2181: * Setup addr assuming that A + (ARG_2 * 256) is an
2182: * index into an array of 1byte objects, SINDEX contains
2183: * the base address of that array, and DINDEX contains
2184: * the base address of the location to store the computed
2185: * address.
2186: */
2187: set_1byte_addr:
2188: add DINDIR, A, SINDIR;
2189: mov A, ARG_2;
2190: adc DINDIR, A, SINDIR;
2191: clr A;
2192: adc DINDIR, A, SINDIR;
2193: adc DINDIR, A, SINDIR ret;
2194:
2195: /*
2196: * Either post or fetch an SCB from host memory based on the
2197: * DIRECTION bit in DMAPARAMS. The host SCB index is in SINDEX.
2198: */
2199: dma_scb:
2200: mov A, SINDEX;
2201: if ((ahc->features & AHC_CMD_CHAN) != 0) {
2202: mvi DINDEX, CCHADDR;
2203: mvi HSCB_ADDR call set_64byte_addr;
2204: mov CCSCBPTR, SCBPTR;
2205: test DMAPARAMS, DIRECTION jz dma_scb_tohost;
2206: if ((ahc->flags & AHC_SCB_BTT) != 0) {
2207: mvi CCHCNT, SCB_DOWNLOAD_SIZE_64;
2208: } else {
2209: mvi CCHCNT, SCB_DOWNLOAD_SIZE;
2210: }
2211: mvi CCSCBCTL, CCARREN|CCSCBEN|CCSCBDIR|CCSCBRESET;
2212: cmp CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN|CCSCBDIR jne .;
2213: jmp dma_scb_finish;
2214: dma_scb_tohost:
2215: mvi CCHCNT, SCB_UPLOAD_SIZE;
2216: if ((ahc->features & AHC_ULTRA2) == 0) {
2217: mvi CCSCBCTL, CCSCBRESET;
2218: bmov CCSCBRAM, SCB_BASE, SCB_UPLOAD_SIZE;
2219: or CCSCBCTL, CCSCBEN|CCSCBRESET;
2220: test CCSCBCTL, CCSCBDONE jz .;
2221: } else if ((ahc->bugs & AHC_SCBCHAN_UPLOAD_BUG) != 0) {
2222: mvi CCSCBCTL, CCARREN|CCSCBRESET;
2223: cmp CCSCBCTL, ARRDONE|CCARREN jne .;
2224: mvi CCHCNT, SCB_UPLOAD_SIZE;
2225: mvi CCSCBCTL, CCSCBEN|CCSCBRESET;
2226: cmp CCSCBCTL, CCSCBDONE|CCSCBEN jne .;
2227: } else {
2228: mvi CCSCBCTL, CCARREN|CCSCBEN|CCSCBRESET;
2229: cmp CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN jne .;
2230: }
2231: dma_scb_finish:
2232: clr CCSCBCTL;
2233: test CCSCBCTL, CCARREN|CCSCBEN jnz .;
2234: ret;
2235: } else {
2236: mvi DINDEX, HADDR;
2237: mvi HSCB_ADDR call set_64byte_addr;
2238: mvi SCB_DOWNLOAD_SIZE call set_hcnt;
2239: mov DFCNTRL, DMAPARAMS;
2240: test DMAPARAMS, DIRECTION jnz dma_scb_fromhost;
2241: /* Fill it with the SCB data */
2242: copy_scb_tofifo:
2243: mvi SINDEX, SCB_BASE;
2244: add A, SCB_DOWNLOAD_SIZE, SINDEX;
2245: copy_scb_tofifo_loop:
2246: call copy_to_fifo_8;
2247: cmp SINDEX, A jne copy_scb_tofifo_loop;
2248: or DFCNTRL, HDMAEN|FIFOFLUSH;
2249: jmp dma_finish;
2250: dma_scb_fromhost:
2251: mvi DINDEX, SCB_BASE;
2252: if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0) {
2253: /*
2254: * The PCI module will only issue a PCI
2255: * retry if the data FIFO is empty. If the
2256: * host disconnects in the middle of a
2257: * transfer, we must empty the fifo of all
2258: * available data to force the chip to
2259: * continue the transfer. This does not
2260: * happen for SCSI transfers as the SCSI module
2261: * will drain the FIFO as data are made available.
2262: * When the hang occurs, we know that a multiple
2263: * of 8 bytes is in the FIFO because the PCI
2264: * module has an 8 byte input latch that only
2265: * dumps to the FIFO when HCNT == 0 or the
2266: * latch is full.
2267: */
2268: clr A;
2269: /* Wait for at least 8 bytes of data to arrive. */
2270: dma_scb_hang_fifo:
2271: test DFSTATUS, FIFOQWDEMP jnz dma_scb_hang_fifo;
2272: dma_scb_hang_wait:
2273: test DFSTATUS, MREQPEND jnz dma_scb_hang_wait;
2274: test DFSTATUS, HDONE jnz dma_scb_hang_dma_done;
2275: test DFSTATUS, HDONE jnz dma_scb_hang_dma_done;
2276: test DFSTATUS, HDONE jnz dma_scb_hang_dma_done;
2277: /*
2278: * The PCI module no longer intends to perform
2279: * a PCI transaction. Drain the fifo.
2280: */
2281: dma_scb_hang_dma_drain_fifo:
2282: not A, HCNT;
2283: add A, SCB_DOWNLOAD_SIZE+SCB_BASE+1;
2284: and A, ~0x7;
2285: mov DINDIR,DFDAT;
2286: cmp DINDEX, A jne . - 1;
2287: cmp DINDEX, SCB_DOWNLOAD_SIZE+SCB_BASE
2288: je dma_finish_nowait;
2289: /* Restore A as the lines left to transfer. */
2290: add A, -SCB_BASE, DINDEX;
2291: shr A, 3;
2292: jmp dma_scb_hang_fifo;
2293: dma_scb_hang_dma_done:
2294: and DFCNTRL, ~HDMAEN;
2295: test DFCNTRL, HDMAEN jnz .;
2296: add SEQADDR0, A;
2297: } else {
2298: call dma_finish;
2299: }
2300: call dfdat_in_8;
2301: call dfdat_in_8;
2302: call dfdat_in_8;
2303: dfdat_in_8:
2304: mov DINDIR,DFDAT;
2305: dfdat_in_7:
2306: mov DINDIR,DFDAT;
2307: mov DINDIR,DFDAT;
2308: mov DINDIR,DFDAT;
2309: mov DINDIR,DFDAT;
2310: mov DINDIR,DFDAT;
2311: dfdat_in_2:
2312: mov DINDIR,DFDAT;
2313: mov DINDIR,DFDAT ret;
2314: }
2315:
2316: copy_to_fifo_8:
2317: mov DFDAT,SINDIR;
2318: mov DFDAT,SINDIR;
2319: copy_to_fifo_6:
2320: mov DFDAT,SINDIR;
2321: copy_to_fifo_5:
2322: mov DFDAT,SINDIR;
2323: copy_to_fifo_4:
2324: mov DFDAT,SINDIR;
2325: mov DFDAT,SINDIR;
2326: mov DFDAT,SINDIR;
2327: mov DFDAT,SINDIR ret;
2328:
2329: /*
2330: * Wait for DMA from host memory to data FIFO to complete, then disable
2331: * DMA and wait for it to acknowledge that it's off.
2332: */
2333: dma_finish:
2334: test DFSTATUS,HDONE jz dma_finish;
2335: dma_finish_nowait:
2336: /* Turn off DMA */
2337: and DFCNTRL, ~HDMAEN;
2338: test DFCNTRL, HDMAEN jnz .;
2339: ret;
2340:
2341: /*
2342: * Restore an SCB that failed to match an incoming reselection
2343: * to the correct/safe state. If the SCB is for a disconnected
2344: * transaction, it must be returned to the disconnected list.
2345: * If it is not in the disconnected state, it must be free.
2346: */
2347: cleanup_scb:
2348: if ((ahc->flags & AHC_PAGESCBS) != 0) {
2349: test SCB_CONTROL,DISCONNECTED jnz add_scb_to_disc_list;
2350: }
2351: add_scb_to_free_list:
2352: if ((ahc->flags & AHC_PAGESCBS) != 0) {
2353: BEGIN_CRITICAL;
2354: mov SCB_NEXT, FREE_SCBH;
2355: mvi SCB_TAG, SCB_LIST_NULL;
2356: mov FREE_SCBH, SCBPTR ret;
2357: END_CRITICAL;
2358: } else {
2359: mvi SCB_TAG, SCB_LIST_NULL ret;
2360: }
2361:
2362: if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
2363: set_hhaddr:
2364: or DSCOMMAND1, HADDLDSEL0;
2365: and HADDR, SG_HIGH_ADDR_BITS, SINDEX;
2366: and DSCOMMAND1, ~HADDLDSEL0 ret;
2367: }
2368:
2369: if ((ahc->flags & AHC_PAGESCBS) != 0) {
2370: get_free_or_disc_scb:
2371: BEGIN_CRITICAL;
2372: cmp FREE_SCBH, SCB_LIST_NULL jne dequeue_free_scb;
2373: cmp DISCONNECTED_SCBH, SCB_LIST_NULL jne dequeue_disc_scb;
2374: return_error:
2375: mvi NO_FREE_SCB call set_seqint;
2376: mvi SINDEX, SCB_LIST_NULL ret;
2377: dequeue_disc_scb:
2378: mov SCBPTR, DISCONNECTED_SCBH;
2379: mov DISCONNECTED_SCBH, SCB_NEXT;
2380: END_CRITICAL;
2381: mvi DMAPARAMS, FIFORESET;
2382: mov SCB_TAG jmp dma_scb;
2383: BEGIN_CRITICAL;
2384: dequeue_free_scb:
2385: mov SCBPTR, FREE_SCBH;
2386: mov FREE_SCBH, SCB_NEXT ret;
2387: END_CRITICAL;
2388:
2389: add_scb_to_disc_list:
2390: /*
2391: * Link this SCB into the DISCONNECTED list. This list holds the
2392: * candidates for paging out an SCB if one is needed for a new command.
2393: * Modifying the disconnected list is a critical(pause dissabled) section.
2394: */
2395: BEGIN_CRITICAL;
2396: mov SCB_NEXT, DISCONNECTED_SCBH;
2397: mov DISCONNECTED_SCBH, SCBPTR ret;
2398: END_CRITICAL;
2399: }
2400: set_seqint:
2401: mov INTSTAT, SINDEX;
2402: nop;
2403: return:
2404: ret;
CVSweb