{ *************************************************************************** } MODULE mod_tcs_io_spy_handling ; { *************************************************************************** } INCLUDE mod_common_hard_io, mod_common_global_flags, mod_inline_hard_io, mod_tcs_io_drv11j_handling, mod_tcs_io_comint_handling, mod_handle_tracing ; { *************************************************************************** } EXPORT proced_tcs_request_spy, {PROCEDURE requests a copy of the next dblock } proced_tcs_read_db_spy ; {PROCEDURE read the full data block spy } { *************************************************************************** } IMPORT PortA, PortB, PortC, PortD, {from module MOD_COMMON_HARD_IO } dev_drv11j_pilot, {from module MOD_COMMON_HARD_IO } dev_drv11j_assist, {from module MOD_COMMON_HARD_IO } drv11j_registers, {from module MOD_COMMON_HARD_IO } reg_drv11j, {from module MOD_COMMON_HARD_IO } reg_drv11j_pilot, {from module MOD_COMMON_HARD_IO } reg_drv11j_assist, {from module MOD_COMMON_HARD_IO } outdbra,{outdbrb,}outdbrc, {from module MOD_COMMON_HARD_IO } indbrd, {from module MOD_COMMON_HARD_IO } array_data_block_spy, {from module MOD_COMMON_HARD_IO } p_dblock_low, p_dblock_high, {from module MOD_COMMON_HARD_IO } trg_alloc, {from module MOD_COMMON_HARD_IO } array_two_flags, {from module MOD_COMMON_HARD_IO } two_comint_types, {from module MOD_COMMON_HARD_IO } pilot, assist, {from module MOD_COMMON_HARD_IO } inline_init_io_cycle, {from module MOD_INLINE_HARD_IO } inline_end_io_cycle, {from module MOD_INLINE_HARD_IO } proced_tcs_enb_int, {from module MOD_TCS_IO_DRV11J_HANDLING } proced_tcs_pause, {from module MOD_TCS_IO_COMINT_HANDLING } proced_tcs_resume, {from module MOD_TCS_IO_COMINT_HANDLING } status_type, ok, {already_done,} io_failure, not_found, {from module MOD_COMMON_GLOBAL_FLAGS } framework_state, running, {from module MOD_COMMON_GLOBAL_FLAGS } inline_tracing, {from module MOD_HANDLE_TRACING } trace_warn, trace_error, {from module MOD_HANDLE_TRACING } handle_trc_wrn, {from module MOD_HANDLE_TRACING } handle_trc_sta, {from module MOD_HANDLE_TRACING } handle_trc_err ; {from module MOD_HANDLE_TRACING } { *************************************************************************** } %INCLUDE 'SITE_DEPENDENT.CST/LIST' TYPE byte = [BYTE] 0..255 ; word = [WORD] 0..65535 ; { *************************************************************************** } { *************************************************************************** } PROCEDURE proced_tcs_request_spy ( VAR status : [OPTIONAL] status_type ) ; VAR spy_was_full : ARRAY [Pilot..Assist] OF BOOLEAN ; dev_was_sig : ARRAY [Pilot..Assist] OF BOOLEAN ; fail_reset : ARRAY [Pilot..Assist] OF BOOLEAN ; pause_status : status_type ; fail_pause : BOOLEAN ; result : INTEGER ; dummy_flag : array_two_flags ; BEGIN IF PRESENT(status) THEN status := ok ; spy_was_full := ZERO ; dev_was_sig := ZERO ; fail_reset := ZERO ; fail_pause := ZERO ; { **** Pause the Framework first so the 2 COMINTs can catch the same dblock } { **** It would be sufficient to pause the framework at the last second, } { **** right before sending the request pulse, but we call the pause } { **** outside the DISABLE/ENABLE_SWITCH code block so that an error message } { **** can be displayed without causing a screen semaphore lock-up. } { **** Another method would be to call lock_console before entering the } { **** disable_switch section; unlock_console may be called immediately after } proced_tcs_pause ; inline_init_io_cycle ( dummy_flag ) ; { **** check the data block spy full line first **** } indbrd.comstat::BYTE := READ_REGISTER (reg_drv11j_pilot^[PortD].buffer.highbyte ) ; IF ( indbrd.comstat.dbspyfull = 1 ) THEN BEGIN spy_was_full[pilot] := TRUE ; { **** reset data block spy **** } outdbrc.comctrl.readspy := 1 ; WRITE_REGISTER ( reg_drv11j_pilot^[PortC].buffer::WORD, outdbrc::WORD ) ; outdbrc.comctrl.readspy := 0 ; WRITE_REGISTER ( reg_drv11j_pilot^[PortC].buffer::WORD, outdbrc::WORD ) ; { **** check the data block spy full line (again) **** } indbrd.comstat::BYTE := READ_REGISTER (reg_drv11j_pilot^[PortD].buffer.highbyte ) ; IF ( indbrd.comstat.dbspyfull = 1 ) THEN BEGIN fail_reset[pilot] := TRUE ; IF PRESENT(status) THEN status := io_failure ; END ; END ; indbrd.comstat::BYTE := READ_REGISTER (reg_drv11j_assist^[PortD].buffer.highbyte ) ; IF ( indbrd.comstat.dbspyfull = 1 ) THEN BEGIN spy_was_full[assist] := TRUE ; { **** reset data block spy **** } outdbrc.comctrl.readspy := 1 ; WRITE_REGISTER ( reg_drv11j_assist^[PortC].buffer::WORD, outdbrc::WORD ) ; outdbrc.comctrl.readspy := 0 ; WRITE_REGISTER ( reg_drv11j_assist^[PortC].buffer::WORD, outdbrc::WORD ) ; { **** check the data block spy full line (again) **** } indbrd.comstat::BYTE := READ_REGISTER (reg_drv11j_assist^[PortD].buffer.highbyte ) ; IF ( indbrd.comstat.dbspyfull = 1 ) THEN BEGIN fail_reset[assist] := TRUE ; IF PRESENT(status) THEN status := io_failure ; END ; END ; { *** flush old satisfied interrupt requests **** } WAIT_ANY ( dev_drv11j_pilot[PortB], TIME := 0, RESULT := result ) ; IF ( result = 1 ) { wait was satisfied by outstanding interrupt } THEN dev_was_sig[pilot] := TRUE ; WAIT_ANY ( dev_drv11j_assist[PortB], TIME := 0, RESULT := result ) ; IF ( result = 1 ) { wait was satisfied by outstanding interrupt } THEN dev_was_sig[assist] := TRUE ; { **** enable USER RPLY interrupt on Port B **** } proced_tcs_enb_int ( reg_drv11j_pilot, PortB ) ; proced_tcs_enb_int ( reg_drv11j_assist, PortB ) ; { **** send rising edge to request a copy of the next data block **** } outdbrc.comctrl.spynextdb := 1 ; WRITE_REGISTER ( reg_drv11j_pilot^[PortC].buffer::WORD, outdbrc::WORD ) ; WRITE_REGISTER ( reg_drv11j_assist^[PortC].buffer::WORD, outdbrc::WORD ) ; outdbrc.comctrl.spynextdb := 0 ; WRITE_REGISTER ( reg_drv11j_pilot^[PortC].buffer::WORD, outdbrc::WORD ) ; WRITE_REGISTER ( reg_drv11j_assist^[PortC].buffer::WORD, outdbrc::WORD ) ; {resume the framework, if COOR had it resumed} IF ( Framework_state = Running ) THEN proced_tcs_resume ; inline_end_io_cycle ( dummy_flag ) ; IF ( spy_was_full[pilot] = TRUE ) THEN IF ( inline_tracing(trace_warn) <> 0 ) THEN handle_trc_wrn ( TAG := 'CMI/SPY%', MESSAGE := ' Pilot Spy was full,' + ' requesting new Data Block ' ) ; IF ( spy_was_full[assist] = TRUE ) THEN IF ( inline_tracing(trace_warn) <> 0 ) THEN handle_trc_wrn ( TAG := 'CMI/SPY%', MESSAGE := ' Assistant Spy was full,' + ' requesting new Data Block ' ) ; IF ( dev_was_sig[Pilot] = TRUE ) THEN IF ( inline_tracing(trace_warn) <> 0 ) THEN handle_trc_wrn ( TAG := 'CMI/SPY%', MESSAGE := ' Pilot Spy full was already Signaled ' ) ; IF ( dev_was_sig[Assist] = TRUE ) THEN IF ( inline_tracing(trace_warn) <> 0 ) THEN handle_trc_wrn ( TAG := 'CMI/SPY%', MESSAGE := ' Assistant Spy full was already Signaled ' ) ; IF ( fail_reset[Pilot] = TRUE ) THEN IF ( inline_tracing(trace_error) <> 0 ) THEN handle_trc_err ( TAG := 'CMI/SPY%', MESSAGE := ' Failure Resetting the Pilot DBlock Spy ' ) ; IF ( fail_reset[Assist] = TRUE ) THEN IF ( inline_tracing(trace_error) <> 0 ) THEN handle_trc_err ( TAG := 'CMI/SPY%', MESSAGE := ' Failure Resetting the Assistant DBlock Spy ' ) ; END; { *************************************************************************** } { *************************************************************************** } PROCEDURE proced_tcs_read_db_spy ( dbspy : ^array_data_block_spy ; comint : two_comint_types ; report : BOOLEAN := TRUE ; max_wait : LARGE_INTEGER := -1 ; VAR snap_time :[OPTIONAL] LARGE_INTEGER ; VAR status :[OPTIONAL] status_type ) ; VAR word_count : INTEGER ; wait_spy : INTEGER ; time_int : INTEGER ; stawai : INTEGER ; result : INTEGER ; line_low_before, line_low_while : BOOLEAN ; line_high_after, line_still_high : BOOLEAN ; dummy_flag : array_two_flags ; spy_type : VARYING_STRING(6) ; reg_drv11j :^drv11j_registers ; { force the use of a private copy of pointer } { instead of the general purpose one, } { because it would be hard to prevent } { other processes to modify it } BEGIN IF PRESENT(status) THEN status := ok ; line_low_before := ZERO ; line_low_while := ZERO ; line_high_after := ZERO ; line_still_high := ZERO ; { see SITE_DEPENDENT.CST for timeout value } IF ( max_wait = -1 ) THEN max_wait := p_spy_timeout ; {default value } IF ( COMINT = Pilot ) THEN BEGIN spy_type := 'Pilot' ; reg_drv11j := reg_drv11j_pilot ; WAIT_ANY ( dev_drv11j_pilot[PortB], TIME := max_wait, RESULT := result, STATUS := stawai ) ; END ELSE BEGIN spy_type := 'Assist' ; reg_drv11j := reg_drv11j_assist ; WAIT_ANY ( dev_drv11j_assist[PortB], TIME := max_wait, RESULT := result, STATUS := stawai ) ; END ; IF PRESENT(snap_time) THEN GET_TIME (snap_time) ; IF ( stawai <> 1 ) THEN BEGIN handle_trc_sta ( TAG := 'WAI/SPY%drv_'+spy_type+'%', STATUS := stawai ) ; IF PRESENT(status) THEN status := io_failure ; END ; IF ( result = 0 ) { wait was satisfied by timeout } THEN BEGIN IF ( report = TRUE ) THEN IF ( inline_tracing(trace_warn) <> 0 ) THEN handle_trc_wrn ( TAG := 'CMI/SPY%', MESSAGE := ' ' + Spy_type + ' Data Block Spy Timeout ' ) ; IF PRESENT(status) THEN status := not_found ; indbrd.comstat::BYTE := READ_REGISTER (reg_drv11j^[PORTD].buffer.highbyte ) ; IF ( indbrd.comstat.dbspyfull = 1 ) THEN BEGIN handle_trc_err ( TAG := 'CMI/SPY%', MESSAGE := ' Wait for ' + Spy_type + ' Spy Interrupt Timeout, ' + ' but Spy Full Line asserted ' ) ; IF PRESENT(status) THEN status := io_failure ; END ; GOTO quit_read_spy ; END ; { {weird behavior of the code/hardware where the data block spy full line} { {remains low for some time} {27-SEP-1989 understood: proced_enb_int was only unmasking the interrupt { without clearing an older interrupt request, { the drv11j could thus be requesting an interrupt { immediately (and remain ahead by one interrupt). { status_before::BYTE := READ_REGISTER ( drv11j^[PORTD].buffer.highbyte ) ; { WAIT_ANY ( TIME := -5000000 ) ; {.5s} { status_after::BYTE := READ_REGISTER ( drv11j^[PORTD].buffer.highbyte ) ; } inline_init_io_cycle ( dummy_flag ) ; { **** set port B for Read Direction **** } WRITE_REGISTER ( reg_drv11j^[PORTB].csreg, dir := 0 ) ; { **** switch the data block spy to read mode **** } outdbrc.comctrl.readspy := 1 ; WRITE_REGISTER ( reg_drv11j^[PORTC].buffer::WORD, outdbrc::WORD ) ; { the datablock spy full line should still be high **** } indbrd.comstat::BYTE := READ_REGISTER ( reg_drv11j^[PORTD].buffer.highbyte ) ; IF ( indbrd.comstat.dbspyfull = 0 ) THEN BEGIN IF PRESENT(status) THEN status := io_failure ; line_low_before := TRUE ; END ; { **** now read the 8 KBytes 16 bit word at a time **** } {27-FEB-1991 add two dummy read to align spy with comint prom addresses } {It is only when the PROM clock says 1 that the content of the COMINT PROM } {address 0 is displayed. The spy RAM clock is separate but in phase with } {the PROM clock while spying. It is only when the clocks say 2 that the } {result of PROM address 0 is latched on the data lines, and written into } {the spy RAM. } dbspy^[p_dblock_low] := READ_REGISTER (reg_drv11j^[PORTB].buffer::WORD ) ; dbspy^[p_dblock_low] := READ_REGISTER (reg_drv11j^[PORTB].buffer::WORD ) ; { read all the data block words but the last one **** } FOR word_count := p_dblock_low TO p_dblock_high - 3 DO dbspy^[word_count] := READ_REGISTER (reg_drv11j^[PORTB].buffer::WORD ) ; { now comes a test of the proper completion of the readout of the spy **** } { cf. COMINT card schematic page 18 **** } { the datablock spy full line should stay high while the spy is read **** } indbrd.comstat::BYTE := READ_REGISTER (reg_drv11j^[PORTD].buffer.highbyte ) ; IF ( indbrd.comstat.dbspyfull = 0 ) THEN BEGIN IF PRESENT(status) THEN status := io_failure ; line_low_while := TRUE ; END ; { read the last word (27-FEB-1991 and it is one before last dblock word) **** } dbspy^[p_dblock_high-2] := READ_REGISTER (reg_drv11j^[PORTB].buffer::WORD ) ; { the datablock spy full line should go low when the last word is read **** } indbrd.comstat::BYTE := READ_REGISTER (reg_drv11j^[PORTD].buffer.highbyte ) ; IF ( indbrd.comstat.dbspyfull = 1 ) THEN BEGIN line_high_after := TRUE ; IF PRESENT(status) THEN status := io_failure ; END ; { **** signal end of data_block spy read mode **** } outdbrc.comctrl.readspy := 0 ; WRITE_REGISTER ( reg_drv11j^[PORTC].buffer::WORD, outdbrc::WORD ) ; { the datablock spy full line should have been forced low after end read **** } indbrd.comstat::BYTE := READ_REGISTER (reg_drv11j^[PORTD].buffer.highbyte ) ; IF ( indbrd.comstat.dbspyfull = 1 ) THEN BEGIN IF PRESENT(status) THEN status := io_failure ; line_still_high := TRUE ; END ; { **** replace port B in Write Direction **** } WRITE_REGISTER ( reg_drv11j^[PORTB].csreg, dir := 1 ) ; inline_end_io_cycle ( dummy_flag ) ; IF ( ( report = TRUE ) AND ( inline_tracing(trace_error) <> 0 ) ) THEN BEGIN IF ( line_low_before = TRUE ) THEN handle_trc_err ( TAG := 'CMI/SPY%', MESSAGE := ' Error reading ' + Spy_type + ' Spy, Spy Full Line' + ' already LOW before reading 1st word' ) ; IF ( line_low_while = TRUE ) THEN handle_trc_err ( TAG := 'CMI/SPY%', MESSAGE := ' Error reading ' + Spy_type + ' Spy, Spy Full Line' + ' already LOW before reading last word' ) ; IF ( line_high_after = TRUE ) THEN handle_trc_err ( TAG := 'CMI/SPY%', MESSAGE := ' Error reading ' + Spy_type + ' Spy, Spy Full Line' + ' stil HIGH after reading last word' ) ; IF ( line_still_high = TRUE ) THEN handle_trc_err ( TAG := 'CMI/SPY%', MESSAGE := ' Error reading ' + Spy_type + ' Spy, Spy Full Line' + ' stil HIGH after negating Reading Spy Line'); END ; quit_read_spy : END; { *************************************************************************** } { *************************************************************************** } END .