📄 53c7,8xx.scr
字号:
CLEAR ACK#endif WAIT DISCONNECT#ifdef EVENTS INT int_EVENT_DISCONNECT;#endif#if 0 INT int_debug_disconnected#endif JUMP schedule#endif ;; select;; PURPOSE : establish a nexus for the SCSI command referenced by DSA.; On success, the current DSA structure is removed from the issue ; queue. Usually, this is entered as a fall-through from schedule,; although the contingent allegiance handling code will write; the select entry address to the DSP to restart a command as a ; REQUEST SENSE. A message is sent (usually IDENTIFY, although; additional SDTR or WDTR messages may be sent). COMMAND OUT; is handled.;; INPUTS : DSA - SCSI command, issue_dsa_head;; CALLS : NOT OK;; MODIFIES : SCRATCH, issue_dsa_head;; EXITS : on reselection or selection, go to select_failed; otherwise, RETURN so control is passed back to ; dsa_begin.;ENTRY selectselect:#if 0#ifdef EVENTS INT int_EVENT_BEFORE_SELECT#endif#endif#if 0#ifdef DEBUG INT int_debug_scheduled#endif#endif CLEAR TARGET; XXX;; In effect, SELECTION operations are backgrounded, with execution; continuing until code which waits for REQ or a fatal interrupt is ; encountered.;; So, for more performance, we could overlap the code which removes ; the command from the NCRs issue queue with the selection, but ; at this point I don't want to deal with the error recovery.;#if (CHIP != 700) && (CHIP != 70066) SELECT ATN FROM dsa_select, select_failed JUMP select_msgout, WHEN MSG_OUTENTRY select_msgoutselect_msgout: MOVE FROM dsa_msgout, WHEN MSG_OUT#elseENTRY select_msgout SELECT ATN 0, select_failedselect_msgout: MOVE 0, 0, WHEN MSGOUT#endif#ifdef EVENTS INT int_EVENT_SELECT#endif RETURN; ; select_done; ; PURPOSE: continue on to normal data transfer; called as the exit ; point from dsa_begin.;; INPUTS: dsa;; CALLS: OK;;select_done:#ifdef DEBUGENTRY select_check_dsaselect_check_dsa: INT int_debug_check_dsa#endif; After a successful selection, we should get either a CMD phase or ; some transfer request negotiation message. JUMP cmdout, WHEN CMD INT int_err_unexpected_phase, WHEN NOT MSG_IN select_msg_in: CALL msg_in, WHEN MSG_IN JUMP select_msg_in, WHEN MSG_INcmdout: INT int_err_unexpected_phase, WHEN NOT CMD#if (CHIP == 700) INT int_norm_selected#endifENTRY cmdout_cmdoutcmdout_cmdout:#if (CHIP != 700) && (CHIP != 70066) MOVE FROM dsa_cmdout, WHEN CMD#else MOVE 0, 0, WHEN CMD#endif /* (CHIP != 700) && (CHIP != 70066) */;; data_transfer ; other_out; other_in; other_transfer;; PURPOSE : handle the main data transfer for a SCSI command in ; several parts. In the first part, data_transfer, DATA_IN; and DATA_OUT phases are allowed, with the user provided; code (usually dynamically generated based on the scatter/gather; list associated with a SCSI command) called to handle these ; phases.;; After control has passed to one of the user provided ; DATA_IN or DATA_OUT routines, back calls are made to ; other_transfer_in or other_transfer_out to handle non-DATA IN; and DATA OUT phases respectively, with the state of the active; data pointer being preserved in TEMP.;; On completion, the user code passes control to other_transfer; which causes DATA_IN and DATA_OUT to result in unexpected_phase; interrupts so that data overruns may be trapped.;; INPUTS : DSA - SCSI command;; CALLS : OK in data_transfer_start, not ok in other_out and other_in, ok in; other_transfer;; MODIFIES : SCRATCH;; EXITS : if STATUS IN is detected, signifying command completion,; the NCR jumps to command_complete. If MSG IN occurs, a ; CALL is made to msg_in. Otherwise, other_transfer runs in ; an infinite loop.; ENTRY data_transferdata_transfer: JUMP cmdout_cmdout, WHEN CMD CALL msg_in, WHEN MSG_IN INT int_err_unexpected_phase, WHEN MSG_OUT JUMP do_dataout, WHEN DATA_OUT JUMP do_datain, WHEN DATA_IN JUMP command_complete, WHEN STATUS JUMP data_transferENTRY end_data_transferend_data_transfer:;; FIXME: On NCR53c700 and NCR53c700-66 chips, do_dataout/do_datain ; should be fixed up whenever the nexus changes so it can point to the ; correct routine for that command.;#if (CHIP != 700) && (CHIP != 70066); Nasty jump to dsa->dataoutdo_dataout: CALL dsa_to_scratch MOVE SCRATCH0 + dsa_dataout TO SCRATCH0 MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY MOVE dmode_ncr_to_memory TO DMODE MOVE MEMORY 4, addr_scratch, dataout_to_jump + 4 MOVE dmode_memory_to_memory TO DMODEdataout_to_jump: MOVE MEMORY 4, 0, dataout_jump + 4 dataout_jump: JUMP 0; Nasty jump to dsa->dsaindo_datain: CALL dsa_to_scratch MOVE SCRATCH0 + dsa_datain TO SCRATCH0 MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY MOVE dmode_ncr_to_memory TO DMODE MOVE MEMORY 4, addr_scratch, datain_to_jump + 4 MOVE dmode_memory_to_memory TO DMODE ENTRY datain_to_jumpdatain_to_jump: MOVE MEMORY 4, 0, datain_jump + 4#if 0 INT int_debug_datain#endifdatain_jump: JUMP 0#endif /* (CHIP != 700) && (CHIP != 70066) */; Note that other_out and other_in loop until a non-data phase; is discovered, so we only execute return statements when we; can go on to the next data phase block move statement.ENTRY other_outother_out:#if 0 INT 0x03ffdead#endif INT int_err_unexpected_phase, WHEN CMD JUMP msg_in_restart, WHEN MSG_IN INT int_err_unexpected_phase, WHEN MSG_OUT INT int_err_unexpected_phase, WHEN DATA_IN JUMP command_complete, WHEN STATUS JUMP other_out, WHEN NOT DATA_OUT RETURNENTRY other_inother_in:#if 0 INT 0x03ffdead#endif INT int_err_unexpected_phase, WHEN CMD JUMP msg_in_restart, WHEN MSG_IN INT int_err_unexpected_phase, WHEN MSG_OUT INT int_err_unexpected_phase, WHEN DATA_OUT JUMP command_complete, WHEN STATUS JUMP other_in, WHEN NOT DATA_IN RETURNENTRY other_transferother_transfer: INT int_err_unexpected_phase, WHEN CMD CALL msg_in, WHEN MSG_IN INT int_err_unexpected_phase, WHEN MSG_OUT INT int_err_unexpected_phase, WHEN DATA_OUT INT int_err_unexpected_phase, WHEN DATA_IN JUMP command_complete, WHEN STATUS JUMP other_transfer;; msg_in_restart; msg_in; munge_msg;; PURPOSE : process messages from a target. msg_in is called when the ; caller hasn't read the first byte of the message. munge_message; is called when the caller has read the first byte of the message,; and left it in SFBR. msg_in_restart is called when the caller ; hasn't read the first byte of the message, and wishes RETURN; to transfer control back to the address of the conditional; CALL instruction rather than to the instruction after it.;; Various int_* interrupts are generated when the host system; needs to intervene, as is the case with SDTR, WDTR, and; INITIATE RECOVERY messages.;; When the host system handles one of these interrupts,; it can respond by reentering at reject_message, ; which rejects the message and returns control to; the caller of msg_in or munge_msg, accept_message; which clears ACK and returns control, or reply_message; which sends the message pointed to by the DSA ; msgout_other table indirect field.;; DISCONNECT messages are handled by moving the command; to the reconnect_dsa_queue.;; INPUTS : DSA - SCSI COMMAND, SFBR - first byte of message (munge_msg; only);; CALLS : NO. The TEMP register isn't backed up to allow nested calls.;; MODIFIES : SCRATCH, DSA on DISCONNECT;; EXITS : On receipt of SAVE DATA POINTER, RESTORE POINTERS,; and normal return from message handlers running under; Linux, control is returned to the caller. Receipt; of DISCONNECT messages pass control to dsa_schedule.;ENTRY msg_in_restartmsg_in_restart:; XXX - hackish;; Since it's easier to debug changes to the statically ; compiled code, rather than the dynamically generated ; stuff, such as;; MOVE x, y, WHEN data_phase; CALL other_z, WHEN NOT data_phase; MOVE x, y, WHEN data_phase;; I'd like to have certain routines (notably the message handler); restart on the conditional call rather than the next instruction.;; So, subtract 8 from the return address MOVE TEMP0 + 0xf8 TO TEMP0 MOVE TEMP1 + 0xff TO TEMP1 WITH CARRY MOVE TEMP2 + 0xff TO TEMP2 WITH CARRY MOVE TEMP3 + 0xff TO TEMP3 WITH CARRYENTRY msg_inmsg_in: MOVE 1, msg_buf, WHEN MSG_INmunge_msg: JUMP munge_extended, IF 0x01 ; EXTENDED MESSAGE JUMP munge_2, IF 0x20, AND MASK 0xdf ; two byte message;; XXX - I've seen a handful of broken SCSI devices which fail to issue; a SAVE POINTERS message before disconnecting in the middle of ; a transfer, assuming that the DATA POINTER will be implicitly ; restored. ;; Historically, I've often done an implicit save when the DISCONNECT; message is processed. We may want to consider having the option of ; doing that here. ; JUMP munge_save_data_pointer, IF 0x02 ; SAVE DATA POINTER JUMP munge_restore_pointers, IF 0x03 ; RESTORE POINTERS JUMP munge_disconnect, IF 0x04 ; DISCONNECT INT int_msg_1, IF 0x07 ; MESSAGE REJECT INT int_msg_1, IF 0x0f ; INITIATE RECOVERY#ifdef EVENTS INT int_EVENT_SELECT_FAILED #endif JUMP reject_messagemunge_2: JUMP reject_message;; The SCSI standard allows targets to recover from transient ; error conditions by backing up the data pointer with a ; RESTORE POINTERS message. ; ; So, we must save and restore the _residual_ code as well as ; the current instruction pointer. Because of this messiness,; it is simpler to put dynamic code in the dsa for this and to; just do a simple jump down there. ;munge_save_data_pointer: MOVE DSA0 + dsa_save_data_pointer TO SFBR MOVE SFBR TO SCRATCH0 MOVE DSA1 + 0xff TO SFBR WITH CARRY MOVE SFBR TO SCRATCH1 MOVE DSA2 + 0xff TO SFBR WITH CARRY MOVE SFBR TO SCRATCH2 MOVE DSA3 + 0xff TO SFBR WITH CARRY MOVE SFBR TO SCRATCH3 MOVE dmode_ncr_to_memory TO DMODE MOVE MEMORY 4, addr_scratch, jump_dsa_save + 4 MOVE dmode_memory_to_memory TO DMODEjump_dsa_save: JUMP 0munge_restore_pointers: MOVE DSA0 + dsa_restore_pointers TO SFBR MOVE SFBR TO SCRATCH0 MOVE DSA1 + 0xff TO SFBR WITH CARRY MOVE SFBR TO SCRATCH1 MOVE DSA2 + 0xff TO SFBR WITH CARRY MOVE SFBR TO SCRATCH2 MOVE DSA3 + 0xff TO SFBR WITH CARRY MOVE SFBR TO SCRATCH3 MOVE dmode_ncr_to_memory TO DMODE MOVE MEMORY 4, addr_scratch, jump_dsa_restore + 4 MOVE dmode_memory_to_memory TO DMODEjump_dsa_restore: JUMP 0munge_disconnect:#if 0 INT int_debug_disconnect_msg#endif/* * Before, we overlapped processing with waiting for disconnect, but * debugging was beginning to appear messy. Temporarily move things * to just before the WAIT DISCONNECT. */ #ifdef ORIGINAL MOVE SCNTL2 & 0x7f TO SCNTL2 CLEAR ACK#endif#if (CHIP != 700) && (CHIP != 70066) JUMP dsa_schedule#else WAIT DISCONNECT INT int_norm_disconnected#endifmunge_extended: CLEAR ACK INT int_err_unexpected_phase, WHEN NOT MSG_IN MOVE 1, msg_buf + 1, WHEN MSG_IN JUMP munge_extended_2, IF 0x02 JUMP munge_extended_3, IF 0x03 JUMP reject_messagemunge_extended_2: CLEAR ACK MOVE 1, msg_buf + 2, WHEN MSG_IN JUMP reject_message, IF NOT 0x02 ; Must be WDTR CLEAR ACK MOVE 1, msg_buf + 3, WHEN MSG_IN INT int_msg_wdtrmunge_extended_3: CLEAR ACK MOVE 1, msg_buf + 2, WHEN MSG_IN JUMP reject_message, IF NOT 0x01 ; Must be SDTR CLEAR ACK MOVE 2, msg_buf + 3, WHEN MSG_IN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -