📄 aic79xx.seq
字号:
test LQOSTAT2, LQOPHACHGOUTPKT jnz use_lastscb; /* * If the hardware has traversed the whole list, NEXTSCB * will be NULL, CURRSCB and LASTSCB cannot be trusted, * but MAXCMDCNT is accurate. If we stop part way through * the list or only had one command to issue, NEXTSCB[1] is * not NULL and LASTSCB is the last command to go out. */ cmp NEXTSCB[1], SCB_LIST_NULL jne use_lastscb; /* * Brute force walk. */ bmov SCBPTR, WAITING_TID_HEAD, 2; mvi SEQINTCTL, INTVEC1DSL; mvi MODE_PTR, MK_MODE(M_CFG, M_CFG); mov A, MAXCMDCNT; mvi MODE_PTR, MK_MODE(M_SCSI, M_SCSI); clr SEQINTCTL;find_lastscb_loop: dec A; test A, 0xFF jz found_last_sent_scb; bmov SCBPTR, SCB_NEXT, 2; jmp find_lastscb_loop;use_lastscb: bmov SCBPTR, LASTSCB, 2;found_last_sent_scb: bmov CURRSCB, SCBPTR, 2;curscb_ww_done: } else { /* * Untested - Verify with Rev B. */ bmov SCBPTR, CURRSCB, 2; } /* * Requeue any SCBs not sent, to the tail of the waiting Q. */ cmp SCB_NEXT[1], SCB_LIST_NULL je select_out_list_done; /* * We know that neither the per-TID list nor the list of * TIDs is empty. Use this knowledge to our advantage. */ bmov REG0, SCB_NEXT, 2; bmov SCBPTR, WAITING_TID_TAIL, 2; bmov SCB_NEXT2, REG0, 2; bmov WAITING_TID_TAIL, REG0, 2; jmp select_out_inc_tid_q;select_out_list_done: /* * The whole list made it. Just clear our TID's tail pointer * unless we were queued independently due to our need to * send a message. */ test SCB_CONTROL, MK_MESSAGE jnz select_out_inc_tid_q; shr DINDEX, 3, SCB_SCSIID;/* XXX When we switch to SCB_SELOID, put +1 in addition below. */ or DINDEX, 1; /* Want only the second byte */ mvi DINDEX[1], ((WAITING_SCB_TAILS) >> 8); mvi DINDIR, SCB_LIST_NULL;select_out_inc_tid_q: bmov SCBPTR, WAITING_TID_HEAD, 2; bmov WAITING_TID_HEAD, SCB_NEXT2, 2; cmp WAITING_TID_HEAD[1], SCB_LIST_NULL jne . + 2; mvi WAITING_TID_TAIL[1], SCB_LIST_NULL; bmov SCBPTR, CURRSCB, 2;END_CRITICAL; mvi CLRSINT0, CLRSELDO; test LQOSTAT2, LQOPHACHGOUTPKT jnz unexpected_nonpkt_phase; test LQOSTAT1, LQOPHACHGINPKT jnz unexpected_nonpkt_phase; /* * If this is a packetized connection, return to our * idle_loop and let our interrupt handler deal with * any connection setup/teardown issues. The only * exception is the case of MK_MESSAGE SCBs. In the * A, the LQO manager transitions to LQOSTOP0 even if * we have selected out with ATN asserted and the target * REQs in a non-packet phase. */ if ((ahd->bugs & AHD_LQO_ATNO_BUG) != 0) { test SCB_CONTROL, MK_MESSAGE jz select_out_no_message; test SCSISIGO, ATNO jnz select_out_non_packetized;select_out_no_message: } test LQOSTAT2, LQOSTOP0 jnz idle_loop;select_out_non_packetized: /* Non packetized request. */ and SCSISEQ0, ~ENSELO; mov SAVED_SCSIID, SCB_SCSIID; mov SAVED_LUN, SCB_LUN; or SXFRCTL0, SPIOEN; /* * 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; mvi SEQ_FLAGS, NO_CDB_SENT; /* * 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. */mesgin_phasemis:ITloop: call phase_lock; mov A, LASTPHASE; test A, ~P_DATAIN_DT jz p_data; cmp A,P_COMMAND je p_command; cmp A,P_MESGOUT je p_mesgout; cmp A,P_STATUS je p_status; cmp A,P_MESGIN je p_mesgin; mvi SEQINTCODE, BAD_PHASE; jmp ITloop; /* Try reading the bus again. *//* * Command phase. Set up the DMA registers and let 'er rip. */p_command:SET_SRC_MODE M_DFF1;SET_DST_MODE M_DFF1; test MODE_PTR, ~(MK_MODE(M_DFF1, M_DFF1)) jnz p_command_allocate_fifo; /* * Command retry. Free our current FIFO and * re-allocate a FIFO so transfer state is * reset. */ mvi DFFSXFRCTL, RSTCHN|CLRSHCNT;p_command_allocate_fifo: call allocate_fifo; add NONE, -17, SCB_CDB_LEN; jnc p_command_embedded;p_command_from_host: bmov HADDR[0], SCB_CDB_PTR, 11; mvi SG_CACHE_PRE, LAST_SEG; mvi DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN); jmp p_command_loop;p_command_embedded: bmov SHCNT[0], SCB_CDB_LEN, 1; bmov SHCNT[1], ALLZEROS, 2; bmov DFDAT, SCB_CDB_STORE, 16; mvi DFCNTRL, SCSIEN;p_command_loop: test DFCNTRL, SCSIEN jnz p_command_loop; /* * DMA Channel automatically disabled. * Don't allow a data phase if the command * was not fully transferred. Make sure that * we clear the IDENTIFY SEEN flag if a retry * falls short too. */ and SEQ_FLAGS, ~NO_CDB_SENT; test SSTAT2, SDONE jnz ITloop; or SEQ_FLAGS, NO_CDB_SENT; jmp ITloop;/* * Status phase. Wait for the data byte to appear, then read it * and store it into the SCB. */SET_SRC_MODE M_SCSI;SET_DST_MODE M_SCSI;p_status: test SEQ_FLAGS,NOT_IDENTIFIED jz p_status_okay; mvi SEQINTCODE, PROTO_VIOLATION; jmp mesgin_done;p_status_okay: mov SCB_SCSI_STATUS, SCSIDAT; or SCB_CONTROL, STATUS_RCVD; 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. * * 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 * 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). * * When there are no messages to send, MSG_OUT should be set to MSG_NOOP, * in case the target decides to put us in this phase for some strange * reason. */p_mesgout_retry: /* Turn on ATN for the retry */ mvi SCSISIGO, ATNO;p_mesgout: mov SINDEX, MSG_OUT; cmp SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host; test SCB_CONTROL,MK_MESSAGE jnz host_message_loop;p_mesgout_identify: or SINDEX, MSG_IDENTIFYFLAG|DISCENB, SCB_LUN; test SCB_CONTROL, DISCENB jnz . + 2; and SINDEX, ~DISCENB;/* * Send a tag message if TAG_ENB is set in the SCB control block. * Use SCB_NONPACKET_TAG as the tag value. */p_mesgout_tag: test SCB_CONTROL,TAG_ENB jz p_mesgout_onebyte; mov SCSIDAT, SINDEX; /* Send the identify message */ call phase_lock; cmp LASTPHASE, P_MESGOUT jne p_mesgout_done; and SCSIDAT,TAG_ENB|SCB_TAG_TYPE,SCB_CONTROL; call phase_lock; cmp LASTPHASE, P_MESGOUT jne p_mesgout_done; mov SCB_NONPACKET_TAG jmp p_mesgout_onebyte;/* * Interrupt the driver, and allow it to handle this message * phase and any required retries. */p_mesgout_from_host: cmp SINDEX, HOST_MSG jne p_mesgout_onebyte; jmp host_message_loop;p_mesgout_onebyte: mvi CLRSINT1, CLRATNO; mov SCSIDAT, SINDEX;/* * If the next bus phase after ATN drops is 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;p_mesgout_done: mvi CLRSINT1,CLRATNO; /* Be sure to turn ATNO off */ mov LAST_MSG, MSG_OUT; mvi MSG_OUT, MSG_NOOP; /* No message left */ jmp ITloop;/* * Message in phase. Bytes are read using Automatic PIO mode. */p_mesgin: /* read the 1st message byte */ mvi ACCUM call inb_first; test A,MSG_IDENTIFYFLAG jnz mesgin_identify; cmp A,MSG_DISCONNECT je mesgin_disconnect; cmp A,MSG_SAVEDATAPOINTER je mesgin_sdptrs; cmp ALLZEROS,A je mesgin_complete; cmp A,MSG_RESTOREPOINTERS je mesgin_rdptrs; cmp A,MSG_IGN_WIDE_RESIDUE je mesgin_ign_wide_residue; cmp A,MSG_NOOP je mesgin_done;/* * 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... */host_message_loop: call phase_lock; /* Benign the first time through. */ mvi SEQINTCODE, HOST_MSG_LOOP; cmp RETURN_1, EXIT_MSG_LOOP je ITloop; cmp RETURN_1, CONT_MSG_LOOP_WRITE jne . + 3; mov SCSIDAT, RETURN_2; jmp host_message_loop; /* Must be CONT_MSG_LOOP_READ */ mov NONE, SCSIDAT; /* ACK Byte */ jmp host_message_loop;mesgin_ign_wide_residue: shr NEGOADDR, 4, SAVED_SCSIID; test NEGCONOPTS, WIDEXFER jz mesgin_reject; /* Pull the residue byte */ mvi REG0 call inb_next; cmp REG0, 0x01 jne mesgin_reject; test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz . + 2; test DATA_COUNT_ODD, 0x1 jz mesgin_done; mvi SEQINTCODE, IGN_WIDE_RES; jmp mesgin_done;mesgin_reject: mvi MSG_MESSAGE_REJECT call mk_mesg;mesgin_done: mov NONE,SCSIDAT; /*dummy read from latch to ACK*/ jmp ITloop;#define INDEX_DISC_LIST_SCB(target, lun) \ mov SCBPTR, lun; \ shr SCBPTR[1], 3, target #define INDEX_DISC_LIST(target, lun) \ INDEX_DISC_LIST_SCB(target, lun); \ and SINDEX, 0x7, target; \ shl SINDEX, 1; \ add SINDEX, (SCB_DISCONNECTED_LISTS & 0xFF); \ mvi SINDEX[1], ((SCB_DISCONNECTED_LISTS >> 8) & 0xFF)mesgin_identify: /* * Determine whether a target is using tagged or non-tagged * transactions by first looking at the transaction stored in * the per-device, disconnected array. If there is no untagged * transaction for this target this must be an untagged transaction. */ shr SINDEX, 4, SAVED_SCSIID; and SAVED_LUN, MSG_IDENTIFY_LUNMASK, A; INDEX_DISC_LIST(SINDEX, SAVED_LUN); bmov DINDEX, SINDEX, 2; bmov SCBPTR, SINDIR, 2; cmp SCBPTR[1], SCB_LIST_NULL je snoop_tag; test SCB_CONTROL, TAG_ENB jnz snoop_tag; /* Untagged. Setup the SCB. */ bmov REG1, SCB_TAG, 4; /* Save SCB_TAG and SCB_NEXT */ jmp dequeue_first_scb;/* * Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message. * If we get one, we use the tag returned to find the proper * SCB. The disconnected list contains any outstanding tagged transactions * where SCB_TAG != SCB_NONPACKET_TAG or SCB_NONPACKET_TAG + 256. * After receiving the tag, look for the SCB at SCB locations tag and * tag + 256. If those SCBs do not match, traverse the disconnected * list until we find the correct SCB. */snoop_tag: if ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0) { or SEQ_FLAGS, 0x80; } mov NONE, SCSIDAT; /* ACK Identify MSG */ call phase_lock; if ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0) { or SEQ_FLAGS, 0x1; } cmp LASTPHASE, P_MESGIN jne not_found_ITloop; if ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0) { or SEQ_FLAGS, 0x2; } cmp SCSIBUS, MSG_SIMPLE_Q_TAG jne not_found;get_tag: /* Save diconnected list head. */ bmov REG0, SCBPTR, 2; clr SCBPTR[1]; mvi SCBPTR call inb_next; /* tag value */ mov REG1, SCBPTR;verify_scb: mov A, REG1; cmp SCB_NONPACKET_TAG, A jne verify_other_scb; mov A, SAVED_SCSIID; cmp SCB_SCSIID, A jne verify_other_scb; mov A, SAVED_LUN; cmp SCB_LUN, A je setup_SCB;verify_other_scb: xor SCBPTR[1], 1; test SCBPTR[1], 0xFF jnz verify_scb;search_disc_list: /* Restore disconnected list head. */ bmov SCBPTR, REG0, 2; mvi REG0[1], SCB_LIST_NULL; mov A, REG1;search_disc_list_loop: cmp SCB_NONPACKET_TAG, A je dequeue_scb; bmov REG0, SCBPTR, 2; bmov SCBPTR, SCB_NEXT, 2; cmp SCBPTR[1], SCB_LIST_NULL jne search_disc_list_loop; jmp not_found;dequeue_scb: bmov REG1, SCB_TAG, 4; /* Save SCB_TAG and SCB_NEXT */ cmp REG0[1], SCB_LIST_NULL jne dequeue_intermediate_SCB;dequeue_first_scb: shr SINDEX, 4, SAVED_SCSIID; INDEX_DISC_LIST_SCB(SINDEX, SAVED_LUN); /* Update list head. */ bmov DINDIR, REG2, 2; jmp dequeue_restore;dequeue_intermediate_SCB: bmov SCBPTR, REG0, 2; bmov SCB_NEXT, REG2, 2;dequeue_restore: bmov SCBPTR, REG1, 2;/* * Ensure that the SCB the tag points to is for * an SCB transaction to the reconnecting target. */setup_SCB: if ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0) { or SEQ_FLAGS, 0x10; } test SCB_CONTROL,DISCONNECTED jz not_found; and SCB_CONTROL,~DISCONNECTED; clr SEQ_FLAGS; /* make note of IDENTIFY */ test SCB_SGPTR, SG_LIST_NULL jnz . + 2; call allocate_fifo;/* mvi SEQINTCODE, PRINT_RESIDUALS; */ /* See if the host wants to send a message upon reconnection */ test SCB_CONTROL, MK_MESSAGE jz mesgin_done; mvi HOST_MSG call mk_mesg; jmp mesgin_done;not_found: mvi SEQINTCODE, NO_MATCH; jmp mesgin_done;not_found_ITloop: mvi SEQINTCODE, NO_MATCH;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -