📄 53c7xx.scr
字号:
; EXITS : On successful reselection, control is returned to the ; DSA which called reselected_ok. If the WAIT RESELECT; was interrupted by a new commands arrival signaled by ; SIG_P, control is passed to schedule. If the NCR is ; selected, the host system is interrupted with an ; int_err_selected which is usually responded to by; setting DSP to the target_abort address.ENTRY wait_reselectwait_reselect:#ifdef EVENTS int int_EVENT_IDLE#endif#ifdef DEBUG int int_debug_idle#endif WAIT RESELECT wait_reselect_failedreselected:#ifdef EVENTS int int_EVENT_RESELECT#endif CLEAR TARGET DMODE_MEMORY_TO_MEMORY ; Read all data needed to reestablish the nexus - MOVE 1, reselected_identify, WHEN MSG_IN ; We used to CLEAR ACK here.#if (CHIP != 700) && (CHIP != 70066)#ifdef DEBUG int int_debug_reselected#endif ; Point DSA at the current head of the disconnected queue. DMODE_MEMORY_TO_NCR MOVE MEMORY 4, reconnect_dsa_head, addr_scratch DMODE_MEMORY_TO_MEMORY#if (CHIP == 710) MOVE MEMORY 4, addr_scratch, saved_dsa#else CALL scratch_to_dsa#endif ; Fix the update-next pointer so that the reconnect_dsa_head ; pointer is the one that will be updated if this DSA is a hit ; and we remove it from the queue. MOVE MEMORY 4, addr_reconnect_dsa_head, reselected_ok_patch + 8#if (CHIP == 710) ; Time to correct DSA following memory move MOVE MEMORY 4, saved_dsa, addr_dsa#endifENTRY reselected_check_nextreselected_check_next:#ifdef DEBUG INT int_debug_reselect_check#endif ; Check for a NULL pointer. MOVE DSA0 TO SFBR JUMP reselected_not_end, IF NOT 0 MOVE DSA1 TO SFBR JUMP reselected_not_end, IF NOT 0 MOVE DSA2 TO SFBR JUMP reselected_not_end, IF NOT 0 MOVE DSA3 TO SFBR JUMP reselected_not_end, IF NOT 0 INT int_err_unexpected_reselectreselected_not_end: ; ; XXX the ALU is only eight bits wide, and the assembler ; wont do the dirt work for us. As long as dsa_check_reselect ; is negative, we need to sign extend with 1 bits to the full ; 32 bit width of the address. ; ; A potential work around would be to have a known alignment ; of the DSA structure such that the base address plus ; dsa_check_reselect doesn't require carrying from bytes ; higher than the LSB. ; MOVE DSA0 TO SFBR MOVE SFBR + dsa_check_reselect TO SCRATCH0 MOVE DSA1 TO SFBR MOVE SFBR + 0xff TO SCRATCH1 WITH CARRY MOVE DSA2 TO SFBR MOVE SFBR + 0xff TO SCRATCH2 WITH CARRY MOVE DSA3 TO SFBR MOVE SFBR + 0xff TO SCRATCH3 WITH CARRY DMODE_NCR_TO_MEMORY MOVE MEMORY 4, addr_scratch, reselected_check + 4 DMODE_MEMORY_TO_MEMORY#if (CHIP == 710) ; Time to correct DSA following memory move MOVE MEMORY 4, saved_dsa, addr_dsa#endifreselected_check: JUMP 0;;#if (CHIP == 710); We have problems here - the memory move corrupts TEMP and DSA. This; routine is called from DSA code, and patched from many places. Scratch; is probably free when it is called.; We have to:; copy temp to scratch, one byte at a time; write scratch to patch a jump in place of the return; do the move memory; jump to the patched in return address; DSA is corrupt when we get here, and can be left corruptENTRY reselected_okreselected_ok: MOVE TEMP0 TO SFBR MOVE SFBR TO SCRATCH0 MOVE TEMP1 TO SFBR MOVE SFBR TO SCRATCH1 MOVE TEMP2 TO SFBR MOVE SFBR TO SCRATCH2 MOVE TEMP3 TO SFBR MOVE SFBR TO SCRATCH3 MOVE MEMORY 4, addr_scratch, reselected_ok_jump + 4reselected_ok_patch: MOVE MEMORY 4, 0, 0reselected_ok_jump: JUMP 0#elseENTRY reselected_okreselected_ok:reselected_ok_patch: MOVE MEMORY 4, 0, 0 ; Patched : first word ; is address of ; successful dsa_next ; Second word is last ; unsuccessful dsa_next, ; starting with ; dsa_reconnect_head ; We used to CLEAR ACK here.#ifdef DEBUG INT int_debug_reselected_ok#endif#ifdef DEBUG INT int_debug_check_dsa#endif RETURN ; Return control to where#endif#else INT int_norm_reselected#endif /* (CHIP != 700) && (CHIP != 70066) */selected: INT int_err_selected;;; A select or reselect failure can be caused by one of two conditions : ; 1. SIG_P was set. This will be the case if the user has written; a new value to a previously NULL head of the issue queue.;; 2. The NCR53c810 was selected or reselected by another device.;; 3. The bus was already busy since we were selected or reselected; before starting the command.wait_reselect_failed:#ifdef EVENTS INT int_EVENT_RESELECT_FAILED#endif; Check selected bit. #if (CHIP == 710) ; Must work out how to tell if we are selected....#else MOVE SIST0 & 0x20 TO SFBR JUMP selected, IF 0x20#endif; Reading CTEST2 clears the SIG_P bit in the ISTAT register. MOVE CTEST2 & 0x40 TO SFBR JUMP schedule, IF 0x40; Check connected bit. ; FIXME: this needs to change if we support target mode MOVE ISTAT & 0x08 TO SFBR JUMP reselected, IF 0x08; FIXME : Something bogus happened, and we shouldn't fail silently.#if 0 JUMP schedule#else INT int_debug_panic#endifselect_failed:#if (CHIP == 710) ; Disable selection timer MOVE CTEST7 | 0x10 TO CTEST7#endif#ifdef EVENTS int int_EVENT_SELECT_FAILED#endif; Otherwise, mask the selected and reselected bits off SIST0#if (CHIP ==710) ; Let's assume we don't get selected for now MOVE SSTAT0 & 0x10 TO SFBR#else MOVE SIST0 & 0x30 TO SFBR JUMP selected, IF 0x20#endif JUMP reselected, IF 0x10 ; If SIGP is set, the user just gave us another command, and; we should restart or return to the scheduler.; Reading CTEST2 clears the SIG_P bit in the ISTAT register. MOVE CTEST2 & 0x40 TO SFBR JUMP select, IF 0x40; Check connected bit. ; FIXME: this needs to change if we support target mode; FIXME: is this really necessary? MOVE ISTAT & 0x08 TO SFBR JUMP reselected, IF 0x08; FIXME : Something bogus happened, and we shouldn't fail silently.#if 0 JUMP schedule#else INT int_debug_panic#endif;; test_1; test_2;; PURPOSE : run some verification tests on the NCR. test_1; copies test_src to test_dest and interrupts the host; processor, testing for cache coherency and interrupt; problems in the processes.;; test_2 runs a command with offsets relative to the ; DSA on entry, and is useful for miscellaneous experimentation.;; Verify that interrupts are working correctly and that we don't ; have a cache invalidation problem.ABSOLUTE test_src = 0, test_dest = 0ENTRY test_1test_1: MOVE MEMORY 4, test_src, test_dest INT int_test_1;; Run arbitrary commands, with test code establishing a DSA; ENTRY test_2test_2: CLEAR TARGET#if (CHIP == 710) ; Enable selection timer#ifdef NO_SELECTION_TIMEOUT MOVE CTEST7 & 0xff TO CTEST7#else MOVE CTEST7 & 0xef TO CTEST7#endif#endif SELECT ATN FROM 0, test_2_fail JUMP test_2_msgout, WHEN MSG_OUTENTRY test_2_msgouttest_2_msgout:#if (CHIP == 710) ; Disable selection timer MOVE CTEST7 | 0x10 TO CTEST7#endif MOVE FROM 8, WHEN MSG_OUT MOVE FROM 16, WHEN CMD MOVE FROM 24, WHEN DATA_IN MOVE FROM 32, WHEN STATUS MOVE FROM 40, WHEN MSG_IN#if (CHIP != 710) MOVE SCNTL2 & 0x7f TO SCNTL2#endif CLEAR ACK WAIT DISCONNECTtest_2_fail:#if (CHIP == 710) ; Disable selection timer MOVE CTEST7 | 0x10 TO CTEST7#endif INT int_test_2ENTRY debug_breakdebug_break: INT int_debug_break;; initiator_abort; target_abort;; PURPOSE : Abort the currently established nexus from with initiator; or target mode.;; ENTRY target_aborttarget_abort: SET TARGET DISCONNECT CLEAR TARGET JUMP schedule ENTRY initiator_abortinitiator_abort: SET ATN;; The SCSI-I specification says that targets may go into MSG out at ; their leisure upon receipt of the ATN single. On all versions of the ; specification, we can't change phases until REQ transitions true->false, ; so we need to sink/source one byte of data to allow the transition.;; For the sake of safety, we'll only source one byte of data in all ; cases, but to accommodate the SCSI-I dain bramage, we'll sink an ; arbitrary number of bytes. JUMP spew_cmd, WHEN CMD JUMP eat_msgin, WHEN MSG_IN JUMP eat_datain, WHEN DATA_IN JUMP eat_status, WHEN STATUS JUMP spew_dataout, WHEN DATA_OUT JUMP satedspew_cmd: MOVE 1, NCR53c7xx_zero, WHEN CMD JUMP satedeat_msgin: MOVE 1, NCR53c7xx_sink, WHEN MSG_IN JUMP eat_msgin, WHEN MSG_IN JUMP satedeat_status: MOVE 1, NCR53c7xx_sink, WHEN STATUS JUMP eat_status, WHEN STATUS JUMP satedeat_datain: MOVE 1, NCR53c7xx_sink, WHEN DATA_IN JUMP eat_datain, WHEN DATA_IN JUMP satedspew_dataout: MOVE 1, NCR53c7xx_zero, WHEN DATA_OUTsated:#if (CHIP != 710) MOVE SCNTL2 & 0x7f TO SCNTL2#endif MOVE 1, NCR53c7xx_msg_abort, WHEN MSG_OUT WAIT DISCONNECT INT int_norm_aborted#if (CHIP != 710);; dsa_to_scratch; scratch_to_dsa;; PURPOSE :; The NCR chips cannot do a move memory instruction with the DSA register ; as the source or destination. So, we provide a couple of subroutines; that let us switch between the DSA register and scratch register.;; Memory moves to/from the DSPS register also don't work, but we ; don't use them.;; dsa_to_scratch: MOVE DSA0 TO SFBR MOVE SFBR TO SCRATCH0 MOVE DSA1 TO SFBR MOVE SFBR TO SCRATCH1 MOVE DSA2 TO SFBR MOVE SFBR TO SCRATCH2 MOVE DSA3 TO SFBR MOVE SFBR TO SCRATCH3 RETURNscratch_to_dsa: MOVE SCRATCH0 TO SFBR MOVE SFBR TO DSA0 MOVE SCRATCH1 TO SFBR MOVE SFBR TO DSA1 MOVE SCRATCH2 TO SFBR MOVE SFBR TO DSA2 MOVE SCRATCH3 TO SFBR MOVE SFBR TO DSA3 RETURN#endif #if (CHIP == 710); Little patched jump, used to overcome problems with TEMP getting; corrupted on memory moves.jump_temp: JUMP 0#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -