diff options
Diffstat (limited to 'sys/dev/aic7xxx/aic7xxx.seq')
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.seq | 404 |
1 files changed, 185 insertions, 219 deletions
diff --git a/sys/dev/aic7xxx/aic7xxx.seq b/sys/dev/aic7xxx/aic7xxx.seq index 3377449cd302b..c1ab64df4193e 100644 --- a/sys/dev/aic7xxx/aic7xxx.seq +++ b/sys/dev/aic7xxx/aic7xxx.seq @@ -1,7 +1,7 @@ /* * Adaptec 274x/284x/294x device driver firmware for Linux and FreeBSD. * - * Copyright (c) 1994-1999 Justin Gibbs. + * Copyright (c) 1994-1998 Justin Gibbs. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,7 +32,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: aic7xxx.seq,v 1.83 1998/12/17 00:06:52 gibbs Exp $ + * $Id: aic7xxx.seq,v 1.78 1998/09/15 07:24:16 gibbs Exp $ */ #include <dev/aic7xxx/aic7xxx.reg> @@ -58,9 +58,12 @@ reset: clr SCSISIGO; /* De-assert BSY */ - and SXFRCTL1, ~BITBUCKET; /* Always allow reselection */ - and SCSISEQ, ENSELI|ENRSELI|ENAUTOATNP, SCSISEQ_TEMPLATE; + if ((ahc->flags & AHC_TARGETMODE) != 0) { + mvi SCSISEQ, ENSELI|ENRSELI|ENAUTOATNP; + } else { + mvi SCSISEQ, ENRSELI|ENAUTOATNP; + } if ((ahc->features & AHC_CMD_CHAN) != 0) { /* Ensure that no DMA operations are in progress */ @@ -178,12 +181,13 @@ initialize_scsiid: and SCSIID, OID; /* Clear old target */ or SCSIID, A; } - mov SINDEX, SCSISEQ_TEMPLATE; if ((ahc->flags & AHC_TARGETMODE) != 0) { - test SCB_CONTROL, TARGET_SCB jz . + 2; - or SINDEX, TEMODE; + and SINDEX, TARGET_SCB, SCB_CONTROL; + or SCSISEQ, ENSELO|ENAUTOATNO|ENSELI + |ENRSELI|ENAUTOATNP, SINDEX ret ; + } else { + mvi SCSISEQ, ENSELO|ENAUTOATNO|ENRSELI|ENAUTOATNP ret; } - mov SCSISEQ, SINDEX ret; /* * Initialize transfer settings and clear the SCSI channel. @@ -212,26 +216,29 @@ selection: mvi CLRSINT0, CLRSELDI; select_in: if ((ahc->flags & AHC_TARGETMODE) != 0) { - if ((ahc->flags & AHC_INITIATORMODE) != 0) { - test SSTAT0, TARGET jz initiator_reselect; - } - + test SSTAT0, TARGET jz initiator_reselect; /* * We've just been selected. Assert BSY and * setup the phase for receiving messages * from the target. */ mvi SCSISIGO, P_MESGOUT|BSYO; - mvi CLRSINT1, CLRBUSFREE; + + /* + * LAST_MSG gives an indication to the host of what + * went wrong should we need to terminate this selection + * before doing real work. Initialize it to SCB_LIST_NULL to + * indicate an improper initiator selection. + */ + mvi LAST_MSG, SCB_LIST_NULL; /* * Setup the DMA for sending the identify and - * command information. + * command information. We keep a count of the + * number of bytes to send to the host in ARG_2. */ or SEQ_FLAGS, CMDPHASE_PENDING; - - /* XXX If ring buffer is full, return busy or queue full */ - mov A, TQINPOS; + mov A, TMODE_CMDADDR_NEXT; if ((ahc->features & AHC_CMD_CHAN) != 0) { mvi DINDEX, CCHADDR; mvi TMODE_CMDADDR call set_32byte_addr; @@ -265,9 +272,6 @@ select_in: } } - /* No tag yet */ - mvi INITIATOR_TAG, SCB_LIST_NULL; - /* * If ATN isn't asserted, the target isn't interested * in talking to us. Go directly to bus free. @@ -279,20 +283,20 @@ select_in: * initiator. We follow the guidlines from section 6.5 * of the SCSI-2 spec for what messages are allowed when. */ - call target_inb; + call targ_inb; /* * Our first message must be one of IDENTIFY, ABORT, or * BUS_DEVICE_RESET. */ - /* XXX May need to be more lax here for older initiators... */ - test DINDEX, MSG_IDENTIFYFLAG jz host_target_message_loop; + test DINDEX, MSG_IDENTIFYFLAG jz more_first_messages; /* Store for host */ if ((ahc->features & AHC_CMD_CHAN) != 0) { mov CCSCBRAM, DINDEX; } else { mov DFDAT, DINDEX; } + mvi ARG_2, 3; /* Remember for disconnection decision */ test DINDEX, MSG_IDENTIFY_DISCFLAG jnz . + 2; @@ -300,7 +304,7 @@ select_in: or SEQ_FLAGS, NO_DISCONNECT; test SCSISIGI, ATNI jz ident_messages_done; - call target_inb; + call targ_inb; /* * If this is a tagged request, the tagged message must * immediately follow the identify. We test for a valid @@ -324,39 +328,39 @@ select_in: * free. */ test SCSISIGI, ATNI jz target_busfree; - /* * Store the tag for the host. */ - call target_inb; + call targ_inb; if ((ahc->features & AHC_CMD_CHAN) != 0) { mov CCSCBRAM, DINDEX; } else { mov DFDAT, DINDEX; } - mov INITIATOR_TAG, DINDEX; + add ARG_2, 2; jmp ident_messages_done; +more_first_messages: /* - * Pushed message loop to allow the kernel to - * run it's own target mode message state engine. + * Hmm. Now we're down to only accepting + * either an ABORT or BDR. */ -host_target_message_loop: - mvi INTSTAT, HOST_MSG_LOOP; - nop; - cmp RETURN_1, EXIT_MSG_LOOP je target_ITloop; - test SSTAT0, SPIORDY jz .; - jmp host_target_message_loop; + cmp DINDEX, MSG_ABORT je . + 2; + cmp DINDEX, MSG_BUS_DEV_RESET jne target_busfree; + + /* Record the event and notify the host */ + mov LAST_MSG, DINDEX; + jmp target_busfree; ident_messages_done: + mvi LAST_MSG, MSG_NOOP; /* We are so far successful */ /* Terminate the ident list */ if ((ahc->features & AHC_CMD_CHAN) != 0) { mvi CCSCBRAM, SCB_LIST_NULL; } else { mvi DFDAT, SCB_LIST_NULL; } - or SEQ_FLAGS, TARG_CMD_PENDING|IDENTIFY_SEEN; - test SCSISIGI, ATNI jnz target_mesgout_pending_msg; + or SEQ_FLAGS, TARG_CMD_PENDING; jmp target_ITloop; /* @@ -364,20 +368,16 @@ ident_messages_done: * message byte we receive so it can be checked prior to * driving REQ on the bus for the next byte. */ -target_inb: - /* - * Drive REQ on the bus by enabling SCSI PIO. - */ +targ_inb: + /* Drive REQ on the bus by enabling SCSI PIO */ or SXFRCTL0, SPIOEN; /* Wait for the byte */ test SSTAT0, SPIORDY jz .; /* Prevent our read from triggering another REQ */ and SXFRCTL0, ~SPIOEN; - /* Save latched contents */ mov DINDEX, SCSIDATL ret; } -if ((ahc->flags & AHC_INITIATORMODE) != 0) { /* * Reselection has been initiated by a target. Make a note that we've been * reselected, but haven't seen an IDENTIFY message from the target yet. @@ -389,7 +389,7 @@ initiator_reselect: test SBLKCTL, SELBUSB jz . + 2; or SAVED_TCL, SELBUSB; } - or SXFRCTL0, SPIOEN|CLRSTCNT|CLRCHN; + or SXFRCTL0, SPIOEN|CLRCHN; mvi CLRSINT1,CLRBUSFREE; or SIMODE1, ENBUSFREE; /* * We aren't expecting a @@ -399,7 +399,6 @@ initiator_reselect: */ mvi MSG_OUT, MSG_NOOP; /* No message to send */ jmp ITloop; -} /* * After the selection, remove this SCB from the "waiting SCB" @@ -409,7 +408,11 @@ initiator_reselect: */ select_out: /* Turn off the selection hardware */ - and SCSISEQ, ENSELI|ENRSELI|ENAUTOATNP, SCSISEQ_TEMPLATE; + if ((ahc->flags & AHC_TARGETMODE) != 0) { + mvi SCSISEQ, ENSELI|ENRSELI|ENAUTOATNP; + } else { + mvi SCSISEQ, ENRSELI|ENAUTOATNP; + } mvi CLRSINT0, CLRSELDO; mov SCBPTR, WAITING_SCBH; mov WAITING_SCBH,SCB_NEXT; @@ -422,8 +425,7 @@ select_out: * Assert BSY and setup the phase for * sending our identify messages. */ - mvi P_MESGIN|BSYO call change_phase; - mvi CLRSINT1,CLRBUSFREE; + mvi SCSISIGO, P_MESGIN|BSYO; /* * Start out with a simple identify message. @@ -437,22 +439,19 @@ select_out: */ test SCB_CONTROL, TAG_ENB jz . + 3; mvi MSG_SIMPLE_Q_TAG call target_outb; - mov SCB_INITIATOR_TAG call target_outb; - mov INITIATOR_TAG, SCB_INITIATOR_TAG; + mov SCB_TAG call target_outb; target_synccmd: /* * Now determine what phases the host wants us * to go through. */ mov SEQ_FLAGS, SCB_TARGET_PHASES; - target_ITloop: /* - * Start honoring ATN signals now that - * we properly identified ourself. + * XXX Start honoring ATN signals now that + * we properly identified ourself. */ - test SCSISIGI, ATNI jnz target_mesgout; test SEQ_FLAGS, CMDPHASE_PENDING jnz target_cmdphase; test SEQ_FLAGS, DPHASE_PENDING jnz target_dphase; test SEQ_FLAGS, SPHASE_PENDING jnz target_sphase; @@ -465,35 +464,38 @@ target_ITloop: if ((ahc->flags & AHC_PAGESCBS) != 0) { mov ALLZEROS call get_free_or_disc_scb; } - mov RETURN_1, ALLZEROS; call complete_target_cmd; - cmp RETURN_1, CONT_MSG_LOOP jne .; mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET; mov SCB_TAG call dma_scb; jmp target_synccmd; -target_mesgout: - mvi SCSISIGO, P_MESGOUT|BSYO; - call target_inb; - /* Local Processing goes here... */ -target_mesgout_pending_msg: - jmp host_target_message_loop; - target_disconnect: - mvi P_MESGIN|BSYO call change_phase; - test SEQ_FLAGS, DPHASE jz . + 2; - mvi MSG_SAVEDATAPOINTER call target_outb; + mvi SCSISIGO, P_MESGIN|BSYO; mvi MSG_DISCONNECT call target_outb; target_busfree: + and SXFRCTL0, ~SPIOEN; clr SCSISIGO; call complete_target_cmd; + cmp LAST_MSG, MSG_NOOP je . + 2; + mvi INTSTAT, TARGET_MSG_HELP; call clear_target_state; jmp poll_for_work; target_cmdphase: - mvi P_COMMAND|BSYO call change_phase; - call target_inb; + /* + * Add one for the terminating byte + * and one for the command code. + */ + if ((ahc->features & AHC_CMD_CHAN) != 0) { + add CCHCNT, 2, ARG_2; + } else { + add HCNT[0], 2, ARG_2; + clr HCNT[1]; + clr HCNT[2]; + } + mvi SCSISIGO, P_COMMAND|BSYO; + call targ_inb; mov A, DINDEX; /* Store for host */ if ((ahc->features & AHC_CMD_CHAN) != 0) { @@ -504,16 +506,20 @@ target_cmdphase: /* * Determine the number of bytes to read - * based on the command group code via table lookup. - * We reuse the first 8 bytes of the TARG_SCSIRATE - * BIOS array for this table. Count is one less than - * the total for the command since we've already fetched - * the first byte. + * based on the command group code using an adding + * jump table. Count is one less than the total + * since we've already fetched the first byte. */ shr A, CMD_GROUP_CODE_SHIFT; add SINDEX, TARG_SCSIRATE, A; mov A, SINDIR; + if ((ahc->features & AHC_CMD_CHAN) != 0) { + add CCHCNT, A; + } else { + add HCNT[0], A; + } + test A, 0xFF jz command_phase_done; command_loop: or SXFRCTL0, SPIOEN; @@ -537,20 +543,20 @@ target_dphase: * Data direction flags are from the * perspective of the initiator. */ + and SXFRCTL0, ~SPIOEN; + or SXFRCTL0, CLRCHN; test SCB_TARGET_PHASES[1], TARGET_DATA_IN jz . + 4; + mvi SCSISIGO, P_DATAIN|BSYO; mvi LASTPHASE, P_DATAOUT; - mvi P_DATAIN|BSYO call change_phase; - jmp . + 3; + jmp p_data; + mvi SCSISIGO, P_DATAOUT|BSYO; mvi LASTPHASE, P_DATAIN; - mvi P_DATAOUT|BSYO call change_phase; - mov ALLZEROS call initialize_channel; jmp p_data; target_sphase: - mvi P_STATUS|BSYO call change_phase; - mvi LASTPHASE, P_STATUS; + mvi SCSISIGO, P_STATUS|BSYO; mov SCB_TARGET_STATUS call target_outb; - /* XXX Watch for ATN or parity errors??? */ + /* XXX Watch for ATN for parity errors??? */ mvi SCSISIGO, P_MESGIN|BSYO; /* MSG_CMDCMPLT is 0, but we can't do an immediate of 0 */ mov ALLZEROS call target_outb; @@ -560,52 +566,37 @@ complete_target_cmd: test SEQ_FLAGS, TARG_CMD_PENDING jnz . + 2; mov SCB_TAG jmp complete_post; if ((ahc->features & AHC_CMD_CHAN) != 0) { - /* Set the valid byte */ - mvi CCSCBADDR, 24; - mov CCSCBRAM, ALLONES; - mvi CCHCNT, 28; or CCSCBCTL, CCSCBEN|CCSCBRESET; test CCSCBCTL, CCSCBDONE jz .; clr CCSCBCTL; } else { - /* Set the valid byte */ - or DFCNTRL, FIFORESET; - mvi DFWADDR, 3; /* Third 64bit word or byte 24 */ - mov DFDAT, ALLONES; - mvi HCNT[0], 28; - clr HCNT[1]; - clr HCNT[2]; or DFCNTRL, HDMAEN|FIFOFLUSH; call dma_finish; } - inc TQINPOS; - mvi INTSTAT,CMDCMPLT ret; + inc TMODE_CMDADDR_NEXT; + cmp TMODE_CMDADDR_NEXT, TMODE_NUMCMDS jne . + 2; + clr TMODE_CMDADDR_NEXT; + mvi TARGET_CMD_CMPLT jmp complete_post; } - -if ((ahc->flags & AHC_INITIATORMODE) != 0) { initiator_select: mvi SPIOEN call initialize_channel; - - /* - * We aren't expecting a bus free, so interrupt - * the kernel driver if it happens. - */ +/* + * We aren't expecting a bus free, so interrupt + * the kernel driver if it happens. + */ mvi CLRSINT1,CLRBUSFREE; or SIMODE1, ENBUSFREE; - - /* - * As soon as we get a successful selection, the target - * should go into the message out phase since we have ATN - * asserted. - */ +/* + * As soon as we get a successful selection, the target should go + * into the message out phase since we have ATN asserted. + */ mvi MSG_OUT, MSG_IDENTIFYFLAG; or SEQ_FLAGS, IDENTIFY_SEEN; - /* - * Main loop for information transfer phases. Wait for the - * target to assert REQ before checking MSG, C/D and I/O for - * the bus phase. - */ +/* + * Main loop for information transfer phases. Wait for the target + * to assert REQ before checking MSG, C/D and I/O for the bus phase. + */ ITloop: call phase_lock; @@ -617,7 +608,7 @@ ITloop: cmp A,P_STATUS je p_status; cmp A,P_MESGIN je p_mesgin; - mvi INTSTAT,BAD_PHASE; + mvi INTSTAT,BAD_PHASE; /* unknown phase - signal driver */ jmp ITloop; /* Try reading the bus again. */ await_busfree: @@ -628,27 +619,20 @@ await_busfree: test SSTAT1,REQINIT|BUSFREE jz .; test SSTAT1, BUSFREE jnz poll_for_work; mvi INTSTAT, BAD_PHASE; -} clear_target_state: - /* - * We assume that the kernel driver may reset us - * at any time, even in the middle of a DMA, so - * clear DFCNTRL too. - */ - clr DFCNTRL; - - /* - * We don't know the target we will connect to, - * so default to narrow transfers to avoid - * parity problems. - */ - if ((ahc->features & AHC_ULTRA2) != 0) { - bmov SCSIRATE, ALLZEROS, 2; - } else { - clr SCSIRATE; - and SXFRCTL0, ~(FAST20); - } + clr DFCNTRL; /* + * We assume that the kernel driver + * may reset us at any time, even + * in the middle of a DMA, so clear + * DFCNTRL too. + */ + clr SCSIRATE; /* + * We don't know the target we will + * connect to, so default to narrow + * transfers to avoid parity problems. + */ + and SXFRCTL0, ~(FAST20); mvi LASTPHASE, P_BUSFREE; /* clear target specific flags */ clr SEQ_FLAGS ret; @@ -664,7 +648,6 @@ data_phase_reinit: mvi DINDEX, STCNT; mvi SCB_RESID_DCNT call bcopy_3; } - and DATA_COUNT_ODD, 0x1, SCB_RESID_DCNT[0]; jmp data_phase_loop; p_data: @@ -699,7 +682,6 @@ p_data: mvi DINDEX, HADDR; mvi SCB_DATAPTR call bcopy_7; } - and DATA_COUNT_ODD, 0x1, SCB_DATACNT[0]; if ((ahc->features & AHC_ULTRA2) == 0) { if ((ahc->features & AHC_CMD_CHAN) != 0) { @@ -826,10 +808,6 @@ prefetched_segs_avail: mvi HADDR call dfdat_in_7; } - /* Track odd'ness */ - test HCNT[0], 0x1 jz . + 2; - xor DATA_COUNT_ODD, 0x1; - if ((ahc->features & AHC_ULTRA2) == 0) { /* Load STCNT as well. It is a mirror of HCNT */ if ((ahc->features & AHC_CMD_CHAN) != 0) { @@ -844,12 +822,7 @@ prefetched_segs_avail: add SG_NEXT[0],SG_SIZEOF; adc SG_NEXT[1],A; - if ((ahc->flags & AHC_TARGETMODE) != 0) { - test SSTAT0, TARGET jnz data_phase_loop; - } - test SSTAT1, REQINIT jz .; test SSTAT1,PHASEMIS jz data_phase_loop; - /* Ensure the last seg is visable at the shaddow layer */ if ((ahc->features & AHC_ULTRA2) != 0) { or DFCNTRL, PRELOADEN; @@ -878,14 +851,8 @@ data_phase_finish: } if ((ahc->flags & AHC_TARGETMODE) != 0) { - test SEQ_FLAGS, DPHASE_PENDING jz ITloop; + test SEQ_FLAGS, DPHASE_PENDING jz . + 3; and SEQ_FLAGS, ~DPHASE_PENDING; - /* - * For data-in phases, wait for any pending acks from the - * initiator before changing phase. - */ - test DFCNTRL, DIRECTION jz target_ITloop; - test SSTAT1, REQINIT jnz .; jmp target_ITloop; } jmp ITloop; @@ -915,7 +882,6 @@ ultra2_dmahalt: ret; } -if ((ahc->flags & AHC_INITIATORMODE) != 0) { /* * Command phase. Set up the DMA registers and let 'er rip. */ @@ -972,22 +938,17 @@ p_status: jmp ITloop; /* - * Message out phase. If MSG_OUT is MSG_IDENTIFYFLAG, build a full - * indentify message sequence and send it to the target. The host may - * override this behavior by setting the MK_MESSAGE bit in the SCB - * control byte. This will cause us to interrupt the host and allow - * it to handle the message phase completely on its own. If the bit - * associated with this target is set, we will also interrupt the host, - * thereby allowing it to send a message on the next selection regardless - * of the transaction being sent. + * Message out phase. If MSG_OUT is 0x80, build I full indentify message + * sequence and send it to the target. In addition, if the MK_MESSAGE bit + * is set in the SCB_CONTROL byte, interrupt the host and allow it to send + * it's own message. * * If MSG_OUT is == HOST_MSG, also interrupt the host and take a message. - * This is done to allow the host to send messages outside of an identify + * This is done to allow the hsot to send messages outside of an identify * sequence while protecting the seqencer from testing the MK_MESSAGE bit * on an SCB that might not be for the current nexus. (For example, a * BDR message in responce to a bad reselection would leave us pointed to * an SCB that doesn't have anything to do with the current target). - * * Otherwise, treat MSG_OUT as a 1 byte message to send (abort, abort tag, * bus device reset). * @@ -995,29 +956,22 @@ p_status: * in case the target decides to put us in this phase for some strange * reason. */ -p_mesgout_retry: - or SCSISIGO,ATNO,LASTPHASE;/* turn on ATN for the retry */ p_mesgout: mov SINDEX, MSG_OUT; cmp SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host; - test SCB_CONTROL,MK_MESSAGE jnz host_message_loop; - mov FUNCTION1, SCB_TCL; - mov A, FUNCTION1; - mov SINDEX, TARGET_MSG_REQUEST[0]; - if ((ahc->features & AHC_TWIN) != 0) { - /* Second Channel uses high byte bits */ - test SCB_TCL, SELBUSB jz . + 2; - mov SINDEX, TARGET_MSG_REQUEST[1]; - } else if ((ahc->features & AHC_WIDE) != 0) { - test SCB_TCL, 0x80 jz . + 2; /* target > 7 */ - mov SINDEX, TARGET_MSG_REQUEST[1]; - } - test SINDEX, A jnz host_message_loop; p_mesgout_identify: - and SINDEX,LID,SCB_TCL; /* lun */ + if ((ahc->features & AHC_WIDE) != 0) { + and SINDEX,0xf,SCB_TCL; /* lun */ + } else { + and SINDEX,0x7,SCB_TCL; /* lun */ + } and A,DISCENB,SCB_CONTROL; /* mask off disconnect privledge */ or SINDEX,A; /* or in disconnect privledge */ or SINDEX,MSG_IDENTIFYFLAG; +p_mesgout_mk_message: + test SCB_CONTROL,MK_MESSAGE jz p_mesgout_tag; + mov SCSIDATL, SINDEX; /* Send the last byte */ + jmp p_mesgout_from_host + 1;/* Skip HOST_MSG test */ /* * Send a tag message if TAG_ENB is set in the SCB control block. * Use SCB_TAG (the position in the kernel's SCB array) as the tag value. @@ -1032,27 +986,36 @@ p_mesgout_tag: cmp LASTPHASE, P_MESGOUT jne p_mesgout_done; mov SCB_TAG jmp p_mesgout_onebyte; /* - * Interrupt the driver, and allow it to handle this message - * phase and any required retries. + * Interrupt the driver, and allow it to send a message + * if it asks. */ p_mesgout_from_host: cmp SINDEX, HOST_MSG jne p_mesgout_onebyte; - jmp host_message_loop; + mvi INTSTAT,AWAITING_MSG; + nop; + /* + * Did the host detect a phase change? + */ + cmp RETURN_1, MSGOUT_PHASEMIS je p_mesgout_done; p_mesgout_onebyte: mvi CLRSINT1, CLRATNO; mov SCSIDATL, SINDEX; /* - * If the next bus phase after ATN drops is message out, it means + * If the next bus phase after ATN drops is a message out, it means * that the target is requesting that the last message(s) be resent. */ call phase_lock; - cmp LASTPHASE, P_MESGOUT je p_mesgout_retry; + cmp LASTPHASE, P_MESGOUT jne p_mesgout_done; + or SCSISIGO,ATNO,LASTPHASE;/* turn on ATN for the retry */ + jmp p_mesgout; p_mesgout_done: mvi CLRSINT1,CLRATNO; /* Be sure to turn ATNO off */ mov LAST_MSG, MSG_OUT; + cmp MSG_OUT, MSG_IDENTIFYFLAG jne . + 2; + and SCB_CONTROL, ~MK_MESSAGE; mvi MSG_OUT, MSG_NOOP; /* No message left */ jmp ITloop; @@ -1067,22 +1030,19 @@ p_mesgin: cmp A,MSG_SAVEDATAPOINTER je mesgin_sdptrs; cmp ALLZEROS,A je mesgin_complete; cmp A,MSG_RESTOREPOINTERS je mesgin_rdptrs; + cmp A,MSG_EXTENDED je mesgin_extended; + cmp A,MSG_MESSAGE_REJECT je mesgin_reject; cmp A,MSG_NOOP je mesgin_done; +rej_mesgin: /* - * Pushed message loop to allow the kernel to - * RUN IT's own message state engine. To avoid an - * extra nop instruction after signaling the kernel, - * we perform the phase_lock before checking to see - * if we should exit the loop and skip the phase_lock - * in the ITloop. Performing back to back phase_locks - * shouldn't hurt, but why do it twice... + * We have no idea what this message in is, so we issue a message reject + * and hope for the best. In any case, rejection should be a rare + * occurrence - signal the driver when it happens. */ -host_message_loop: - mvi INTSTAT, HOST_MSG_LOOP; - call phase_lock; - cmp RETURN_1, EXIT_MSG_LOOP je ITloop + 1; - jmp host_message_loop; + mvi INTSTAT,SEND_REJECT; /* let driver know */ + + mvi MSG_MESSAGE_REJECT call mk_mesg; mesgin_done: mov NONE,SCSIDATL; /*dummy read from latch to ACK*/ @@ -1147,7 +1107,6 @@ complete_queue: add_to_free_list: call add_scb_to_free_list; jmp await_busfree; -} complete_post: /* Post the SCBID in SINDEX and issue an interrupt */ @@ -1162,9 +1121,23 @@ complete_post: if ((ahc->features & AHC_QUEUE_REGS) == 0) { inc QOUTPOS; } + if ((ahc->flags & AHC_TARGETMODE) != 0) { + test SEQ_FLAGS, NO_DISCONNECT jz . + 3; + mvi INTSTAT,TARGET_SYNC_CMD|CMDCMPLT; + ret; + } mvi INTSTAT,CMDCMPLT ret; -if ((ahc->flags & AHC_INITIATORMODE) != 0) { +/* + * Is it an extended message? Copy the message to our message buffer and + * notify the host. The host will tell us whether to reject this message, + * respond to it with the message that the host placed in our message buffer, + * or simply to do nothing. + */ +mesgin_extended: + mvi INTSTAT,EXTENDED_MSG; /* let driver know */ + jmp ITloop; + /* * Is it a disconnect message? Set a flag in the SCB to remind us * and await the bus going free. @@ -1293,6 +1266,16 @@ not_found: jmp mesgin_done; /* + * Message reject? Let the kernel driver handle this. If we have an + * outstanding WDTR or SDTR negotiation, assume that it's a response from + * the target selecting 8bit or asynchronous transfer, otherwise just ignore + * it since we have no clue what it pertains to. + */ +mesgin_reject: + mvi INTSTAT, REJECT_MSG; + jmp mesgin_done; + +/* * [ ADD MORE MESSAGE HANDLING HERE ] */ @@ -1337,35 +1320,18 @@ inb_first: mov DINDIR,SCSIBUSL ret; /*read byte directly from bus*/ inb_last: mov NONE,SCSIDATL ret; /*dummy read from latch to ACK*/ -} if ((ahc->flags & AHC_TARGETMODE) != 0) { -/* - * Change to a new phase. If we are changing the state of the I/O signal, - * from out to in, wait an additional data release delay before continuing. - */ -change_phase: - and DINDEX, IOI, SCSISIGI; - mov SCSISIGO, SINDEX; - and A, IOI, SINDEX; - cmp DINDEX, A je change_phase_wait; - test SINDEX, IOI jz change_phase_wait; - call change_phase_wait; -change_phase_wait: - nop; - nop; - nop; - nop ret; - -/* - * Send a byte to an initiator in Automatic PIO mode. - */ + /* + * Send a byte to an initiator in Automatic PIO mode. + * SPIOEN must be on prior to calling this routine. + */ target_outb: or SXFRCTL0, SPIOEN; test SSTAT0, SPIORDY jz .; mov SCSIDATL, SINDEX; test SSTAT0, SPIORDY jz .; - and SXFRCTL0, ~SPIOEN ret; + ret; } mesgin_phasemis: @@ -1584,8 +1550,8 @@ get_SCBID_from_host: phase_lock: test SSTAT1, REQINIT jz phase_lock; test SSTAT1, SCSIPERR jnz phase_lock; - and SCSISIGO, PHASE_MASK, SCSISIGI; - and LASTPHASE, PHASE_MASK, SCSISIGI ret; + and LASTPHASE, PHASE_MASK, SCSISIGI; + mov SCSISIGO, LASTPHASE ret; if ((ahc->features & AHC_CMD_CHAN) == 0) { set_stcnt_from_hcnt: |