{ *************************************************************************** } MODULE mod_handle_zrl ; { Created 15-JUN-1994 Philippe Laurens - MSU L1 Trigger } { *************************************************************************** } INCLUDE mod_sys_service, mod_handle_console, mod_handle_tracing, mod_common_hard_io, {from the TRICS hardware IO library } mod_tcs_io_drv11j_handling, {from the TRICS hardware IO library } mod_tcs_io_comint_handling, {from the TRICS hardware IO library } $PHYSICAL_ADDRESS, $KERNELMSG, { from ELN$:RTLOBJECT.OLB } $KERNEL ; { *************************************************************************** } EXPORT addr_pQBA, {Pointer to a RECORD for access to pQBA CSR registers } addr_pVBA, {Pointer to a RECORD for access to pVBA CSR registers } Hydra_A_Page_DPM, {CONST mapped page allocated to Hydra A -- Dual Port } Hydra_A_Page_Ctrl, {CONST mapped page allocated to Hydra A -- Ctrl Reg } Hydra_B_Page_DPM, {CONST mapped page allocated to Hydra B -- Dual Port } Hydra_B_Page_Ctrl, {CONST mapped page allocated to Hydra B -- Ctrl Reg } Hydra_C_Page_DPM, {CONST mapped page allocated to Hydra C -- Dual Port } Hydra_C_Page_Ctrl, {CONST mapped page allocated to Hydra C -- Ctrl Reg } CPU_68k_page_DPM, {CONST mapped page allocated to MVME 135 - Dual Port } CPU_68k_page_Ctrl, {CONST mapped page allocated to MVME 135 - Ctrl Reg } Ironics_page {CONST mapped page allocated to Ironics IO Cards } Scratch_A24_page, {CONST mapped page to MVME 214, A24 from VertX to 214 } longwords_of_A24_Scratch, {CONST size of A24 scratch memory region } scratch_A24_long_offset,{CONST offset of A24 scratch from beg of mapped page} Scratch_A16_page, {CONST mapped page to MVME 214, A16 from VertX to 214 } bytes_of_A16_Scratch, {CONST size of A16 scratch memory region } scratch_A16_byte_offset,{CONST offset of A16 scratch from beg of mapped page} VME_mapped_region, {ARRAY of pages of mapped VME addresses } pVBA_Mapped_page, {TYPE Page of VME memory mapped to VAX address space } VME_Mapping_reg, {ARRAY of pVBA Mapping Control Registers } reset_ZRL_and_DRV11Js, {PROCEDURE reset and reload ZRL and attached devices } init_ZRL_devices_and_DRV11Js ; {PROCEDURE create master pVBA device } { *************************************************************************** } IMPORT find_dev_addr_and_map_mem, {from module MOD_SYS_SERVICE } write_dev_addr_in_int_disp_blk, {from module MOD_SYS_SERVICE } replace_REI_with_RSB_in_IDB, {from module MOD_SYS_SERVICE } map_memory, {from module MOD_SYS_SERVICE } idb, {from module MOD_SYS_SERVICE } lock_console, {from module MOD_HANDLE_CONSOLE } unlock_console, {from module MOD_HANDLE_CONSOLE } handle_trc_inf, {from module MOD_HANDLE_TRACING } handle_trc_sys, {from module MOD_HANDLE_TRACING } handle_trc_sta, {from module MOD_HANDLE_TRACING } handle_trc_err, {from module MOD_HANDLE_TRACING } reg_drv11j_pilot, {from module MOD_COMMON_HARD_IO } reg_drv11j_assist, {from module MOD_COMMON_HARD_IO } proced_tcs_reset_comint, {from module MOD_TCS_IO_COMINT_HANDLING } proced_tcs_define_drv11j, {from module MOD_TCS_IO_DRV11J_HANDLING } proced_tcs_initialize_drv11j, {from module MOD_TCS_IO_DRV11J_HANDLING } p_isr_vect_pilot, {from module MOD_TCS_IO_DRV11J_HANDLING } p_isr_vect_assist, {from module MOD_TCS_IO_DRV11J_HANDLING } KER$_SUCCESS, {from module $KERNELMSG } KER$_DEBUG_SIGNAL, {from module $KERNELMSG } PHYSICAL_ADDRESS, {from module $PHYSICAL_ADDRESS } ELN$PHYSICAL_ADDRESS, {from module $PHYSICAL_ADDRESS } KER$NAME_OBJECT ; {from module $KERNEL } { *************************************************************************** } { *************************************************************************** } { *** the following declarations match PQBA4000.H *** } { *************************************************************************** } TYPE pQBA_regs = {pQBA registers} PACKED RECORD pad1 : INTEGER ; pad2 : INTEGER ; dmaear : INTEGER ; (* DMA Error Address Register *) qear : INTEGER ; (* Q-Bus Error Address Register *) int0 : INTEGER ; (* Q-Bus interrupt register *) int1 : INTEGER ; (* Error interrupt register *) reset : INTEGER ; (* Reset register *) dmaen : INTEGER ; (* DMA Enable Register *) END ; CONST (* INT1 Flag bit definitions *) pQBA_DMANXM = %X00000001; (* DMA Q-Bus to VAX Cycle Timeout *) pQBA_BAT = %X00000004; (* VAX to Q-Bus Bus Access Timeout *) pQBA_LOST = %X00000008; (* Lost QAR Info due to multiple errors *) pQBA_DMAPERR = %X00000010; (* Parity Error on DMA read of pQBA *) pQBA_PERR = %X00000020; (* Parity Error on Q-Bus read *) pQBA_NXM = %X00000080; (* Non Exixtent Memory *) pQBA_GRTMO = %X10000000; (* External device did not acknowldge bus grant within timeout period *) pQBA_IACKTMO = %X08000000; (* No device responded to Interrupt ACK cycle *) pQBA_PWRFL = %X40000000; (* AC Power Fail *) (* INT0 Error bit definitions *) pQBA_UNEXP_VECTOR = 1 ; (* Interrupt from unmapped device *) pQBA_BAD_VECTOR = 2 ; (* Vector out of range *) pQBA_INT_OVERFLOW = 4 ; (* Interrupt not getting cleared *) pQBA_VEC_ERR = 8 ; (* Error reading interrupt vector *) { *************************************************************************** } { *** the following declarations match pVBA4000.H *** } { *************************************************************************** } TYPE byte = [BYTE] 0..255 ; pVBA_regs = {pVBA registers} PACKED RECORD VMEreq : byte ; (* VME Bus req register *) vsbreq : byte ; (* VSB Bus req register *) VMEirq : byte ; (* VME Interrupt req register *) vsbirq : byte ; (* VSB Int req register (not currently implemented) *) esr : INTEGER ; (* Error status register *) fifo : INTEGER ; (* Mailbox FIFO *) resv1 : INTEGER ; (* Currently Mailbox FIFO Duplicate *) int0 : INTEGER ; (* VME interrupt register *) int1 : INTEGER ; (* Local/VSB interrupt register *) reset : INTEGER ; (* Reset register *) resv2 : INTEGER ; (* Unused *) END ; CONST (* INT0 Error bit definitions *) pVBA_UNEXP_VECTOR = %X00000001; (* Interrupt from unmapped device *) pVBA_BAD_VECTOR = %X00000002; (* Vector out of range *) pVBA_INT_OVERFLOW = %X00000004; (* Interrupt not getting cleared *) pVBA_VEC_ERR = %X00000008; (* Error reading interrupt vector *) (* INT0 Interrupt enable bits, 0 = enabled, 1 = disabled *) pVBA_INT0 = %X00000080; (* Enables INT0 assertion to VAX *) (* INT1 Interrupt enable bits, 0 = enabled, 1 = disabled *) pVBA_MBX_WR = %X00000001; (* Mailbox FIFO data available *) pVBA_VSB_INT = %X00000002; (* VSB Interrupt *) pVBA_BUS_RDY = %X00000004; (* VME/VSB Bus ready *) pVBA_BUS_ERR = %X00000008; (* VME/VSB Bus error *) pVBA_CNT_OVF = %X00000010; (* VME/VSB Bus request count over/underflow *) pVBA_CYC_ABO = %X00000020; (* VME/VSB Cycle abort *) pVBA_SCAN = %X00000040; (* Display scan enable, 1 = scan, 0 = hold *) pVBA_INT1 = %X00000080; (* Enables INT1 assertion to VAX *) (* INT1 Local Interrupt vector values *) pVBA_MBX_WRV = %X7; (* Mailbox FIFO data available *) pVBA_VME_RDYV = %X8; (* VME Bus ready *) pVBA_VSB_RDYV = %X9; (* VSB Bus ready *) pVBA_VME_ERRV = %XA; (* VME Bus error *) pVBA_VSB_ERRV = %XB; (* VSB Bus error *) pVBA_VME_OVFV = %XC; (* VME Bus request count over/under flow *) pVBA_VSB_OVFV = %XD; (* VSB Bus request count over/under flow *) pVBA_VME_ABOV = %XE; (* VME Cycle abort *) pVBA_VSB_ABOV = %XF; (* VSB Cycle abort *) TYPE {Automatic byte swapping control values} swap_ctrl = ( swap_not, {0} (* No swapping *) swap_byte, {1} (* Byte Swapping *) swap_word, {2} (* Word Swapping *) swap_full ) ; {3} (* Full Swapping *) { *************************************************************************** } { *** the following declarations match DUAL_INTERRUPTS.H *** } { *** but most importantly match the declarations in DUAL_ISR10A.MAC *** } { *************************************************************************** } TYPE DUAL_isr_comm_region = PACKED RECORD int0_error : INTEGER ; (* Error mask for INT0 *) int1_error : INTEGER ; (* Error mask for INT1 *) bogus_cnt : INTEGER ; (* Count of bogus interrupts *) int0_val : INTEGER ; (* Last value read from INT0 *) int1_val : INTEGER ; (* Last value read from INT1 *) qear_val : INTEGER ; (* Last value read from Q-Bus error addr reg *) dmaear_val : INTEGER ; (* Last value read from DMA error addr reg *) overflow_cnt : INTEGER ; (* Maximum number of passes through ISR. *) addr_pVBA :^pVBA_regs ; (* Pointer to pVBA registers *) reserved : ARRAY [1..54] OF INTEGER ; (* Reserved, size = 63 - # of ints preceeding *) devcnt : INTEGER ; (* Number of devices on Q-Bus, offset %XFC *) dispatch_ptr : ARRAY [1..64] OF ^ANYTYPE ; (* List of dispatch addresses, offset %X100, first entry for %x100, second for %x104, last for %x1FC *) END ; { *************************************************************************** } { *** the following are additional to ZRL code *** } { *************************************************************************** } CONST one_second = -10000000 ; forever = FALSE ; shift_9bits = %X200 ;{multiply by this power of 2 to shift 9 bits to the left} {code selecting VME or VSB buss mapping} select_VME_bus = 0 ; {Address Modifier selecting Addressing Modes} A32_addr_mode = %X09 ; A24_addr_mode = %X39 ; A16_addr_mode = %X29 ; VAX_addr_pVBA_mapping_reg = %X37001000 ; VAX_addr_pVBA_mapped_region = %X3C000000 ; Bytes_per_mapped_page = 65536 ; {64k bytes per mapped page} Longwords_per_mapped_page = 16384 ; {16k longword = 64k bytes per mapped page} {mapped page allocation} Hydra_A_Page_DPM = 1 ; Hydra_A_Page_Ctrl = 2 ; Hydra_B_Page_DPM = 3 ; Hydra_B_Page_Ctrl = 4 ; Hydra_C_Page_DPM = 5 ; Hydra_C_Page_Ctrl = 6 ; CPU_68k_Page_DPM = 7 ; CPU_68k_Page_Ctrl = 8 ; Ironics_page = 9 ; Scratch_A24_page = 10 ; Scratch_A16_page = 11 ; {make this one last (e.g. short IO MVME214)} number_of_mapped_pages = Scratch_A16_page ; {VME addresses (thru Vertical Interconnect)} VME_addr_Hydra_A_DPM = %X10A00000 ; {VME Adrres of Hydra A -- Dual Port Mem } VME_addr_Hydra_A_Ctrl = %X10A10000 ; {VME Adrres of Hydra A -- Control Reg } VME_addr_Hydra_B_DPM = %X10B00000 ; {VME Adrres of Hydra B -- Dual Port Mem } VME_addr_Hydra_B_Ctrl = %X10B10000 ; {VME Adrres of Hydra B -- Control Reg } VME_addr_Hydra_C_DPM = %X10C00000 ; {VME Adrres of Hydra C -- Dual Port Mem } VME_addr_Hydra_C_Ctrl = %X10C10000 ; {VME Adrres of Hydra C -- Control Reg } VME_addr_CPU_68k_DPM = %X10060000 ; {VME Addr of MVME135 -- Dual Port Mem } VME_addr_CPU_68k_Ctrl = %X10FF0000 ; {VME Addr of MVME135 -- Control Reg } {(Short IO) registers at offset 8000} VME_addr_Ironics = %X10FF0000 ; {VME Addr of all Ironics modules} {(Short IO) first module at offset F010} VME_addr_A24_Scratch = %X10300000 ; {VME Adrres of fancy MVME214} VME_addr_A16_Scratch = %X10FF0000 ; {VME Adrres of short IO MVME214} {first address at offset 9000} longwords_of_A24_Scratch = 4096 ; {4k longwords = 1/2 of 32 kbytes,} {other half for 68k tests} bytes_of_A16_Scratch = 2048 ; {2 kbytes,} scratch_A24_long_offset = %X0000 DIV 4 ; {no offset to start of page} {i.e. aligned on 64k boundary} scratch_A16_byte_offset = %X9000 ; {short IO 214 starts at FFFF9000 } TYPE pVBA_mapping_reg = [LONG] PACKED RECORD swap_ctrl : [POS(0)] swap_ctrl ; reserved_1 : [POS(2)] 0..3 ; bus_select : [POS(4)] 0..1 ; reserved_2 : [POS(5)] 0..7 ; addr_mode : [POS(8)] 0..63 ; reserved_3 : [POS(14)] 0..3 ; VME_page : [POS(16)] 0..65535 ; END ; pVBA_mapping_registers = ARRAY [1..number_of_mapped_pages] OF pVBA_mapping_reg ; pVBA_mapped_page = PACKED RECORD CASE INTEGER OF 0 : ( LongWord : ARRAY [0..(Longwords_per_mapped_page-1)] OF INTEGER ) ; 1 : ( Byte : ARRAY [0..(Bytes_per_mapped_page-1)] OF byte ) ; END ; pVBA_mapped_region = ARRAY [1..number_of_mapped_pages] OF pVBA_mapped_page ; ZRL_device = ( pQBA, pVBA ) ; VAR dev_DUAL : ARRAY [pQBA..pVBA] OF DEVICE ; (* device object *) isr_comm_region :^DUAL_isr_comm_region ; (* interrupt region *) addr_pQBA :^pQBA_regs ; (* Pointer to pVBA registers *) addr_pVBA :^pVBA_regs ; (* Pointer to pVBA registers *) addr_DUAL :^ANYTYPE ; {Pointer to DUAL, i.e. pQBA} vect_DUAL :^INTEGER ; prio_DUAL : INTEGER ; tag : VARYING_STRING(8) := 'ZRL/DEV%' ; proc_DUAL_device_control : PROCESS ; name_DUAL_device_control : NAME ; VME_mapping_reg : ^pVBA_mapping_registers ; VME_mapped_region : ^pVBA_mapped_region ; {to run with the pVBA disconnected } {change the Ignore_pVBA variable and recompile, or use the debugger } {$ EDEBUG D0HTCC } { } {Edebug CTRL/C> halt 8,3 } {Edebug CTRL/C> set session 8,3 } {Edebug 8,3> deposit mod_handle_zrl\Ignore_pVBA=TRUE } {Edebug 8,3> Go } { } Ignore_pVBA : BOOLEAN := FALSE ; { *************************************************************************** } INTERRUPT_SERVICE DUAL_isr ( p_DUAL : ^pQBA_regs ; p_isr_comm_region : ^ANYTYPE ) ; EXTERNAL ; {The code is in the Macro DUAL_ISR10A.MAC} { *************************************************************************** } PROCEDURE init_ZRL_devices_and_DRV11Js ; VAR status : INTEGER ; BEGIN CREATE_PROCESS ( proc_DUAL_device_control, block_DUAL_device_control, STATUS := status ) ; handle_trc_sta ( TAG := 'CRE/PRC%DUAL_ctrl%', STATUS := status ) ; KER$NAME_OBJECT( name_DUAL_device_control, 'ZRL CTRL', proc_DUAL_device_control, STATUS := status ) ; handle_trc_sta ( TAG := 'NAM/PRC%DUAL_ctrl%', STATUS := status ) ; { *** raise the priority of the process to service the pQBA/pVBA ASAP *** } SET_PROCESS_PRIORITY ( proc_DUAL_device_control, 6, STATUS := status ); handle_trc_sta ( TAG := 'SET/PIO%DUAL_ctrl%', STATUS := status ) ; END ; { *************************************************************************** } PROCESS_BLOCK block_DUAL_device_control ; VAR status : INTEGER ; result : INTEGER ; p_idb :^idb ; QBus_vector : INTEGER ; BEGIN lock_console ; DISABLE_SWITCH ; unlock_console ; handle_trc_sys ( TAG := tag, MESSAGE := ' Creating Dual pQBA/pVBA Device ' ) ; (* Create the Master DUAL device *) { *** On the QBus version of the Kernel, the CREATE_DEVICE routine *** } { *** would return the virtual address of the pVBA device CSR register *** } { *** in the argument REGISTERS for CREATE_DEVICE, and would also *** } { *** pass this address to the ISR when a device interrupt occurs. *** } { *** But the VAXstatsion 4000 version of the Kernel returns zero *** } { *** for the device address, and passes zero to the ISR. *** } { *** I haven't seen any reference to this in the ELN documentation, *** } { *** maybe it is a bug. I noticed that the Epascal drivers for the 4000 *** } { *** (e.g. DZSDRIVER.PAS) get a system pointer to the CSR registers using *** } { *** ker$allocate_system_region and pass it to the ISR in the *** } { *** communication region. *** } CREATE_DEVICE ( 'DUAL', dev_DUAL, SERVICE_ROUTINE := DUAL_isr, REGION := isr_comm_region, VECTOR := vect_DUAL, PRIORITY := prio_DUAL, STATUS := status ) ; (* Exit if create fails, printing status value to console *) IF ( status <> KER$_SUCCESS ) THEN BEGIN handle_trc_err ( TAG := tag, MESSAGE := ' Unable to create Dual pQBA/pVBA Device' ) ; handle_trc_sta ( TAG := tag, STATUS := status ) ; raise_exception ( KER$_DEBUG_SIGNAL ) ; {get debugger to investigate } END ; { *** CREATE_DEVICE does not return the register base address for the 4000 *** } { *** So we have to retrieve the EBUILD device descritpion by hand *** } find_dev_addr_and_map_mem ( DEV_NAME := 'PQBA', REG_ADDR := addr_pQBA, REG_SIZE := SIZE(pQBA_regs) ) ; find_dev_addr_and_map_mem ( DEV_NAME := 'PVBA', REG_ADDR := addr_pVBA, REG_SIZE := SIZE(pVBA_regs) ) ; { *** clear the Interrupt Service Routine Communication Region *** } isr_comm_region^ := ZERO ; isr_comm_region^.overflow_cnt := 5 ; (* Maximum passes through pVBA_ISR. *) isr_comm_region^.addr_PVBA := addr_pVBA ; { *** CREATE_DEVICE does not prepare the ISR argument for CSR address. *** } { *** Copy by hand the System pointer to pVBA in kernel's Int Disp Block *** } addr_DUAL := addr_pQBA ; {the DUAL_isr wants the address of the pQBA to start} write_dev_addr_in_int_disp_blk ( DEV_NAME := 'Dual pQBA/pVBA', DEV_VECT := vect_DUAL, REG_ADDR := addr_DUAL ) ; { *** display collected information *** } handle_trc_inf ( TAG := 'INI/pQB%', MESSAGE := ' pQBA Register Base Address = %X' + HEX(PHYSICAL_ADDRESS(addr_pQBA)) ) ; handle_trc_inf ( TAG := 'INI/pQB%', MESSAGE := ' pVBA Register Base Address = %X' + HEX(PHYSICAL_ADDRESS(addr_pVBA)) ) ; handle_trc_inf ( TAG := 'INI/pQB%', MESSAGE := ' Dual pQBA/pVBA Interrupt Prior Level = %D ' + CONVERT(STRING,prio_DUAL) ) ; handle_trc_inf ( TAG := 'INI/pQB%', MESSAGE := ' Dual pQBA/pVBA Card Interrupt Vector = %X' + HEX(PHYSICAL_ADDRESS(vect_DUAL)) ) ; (******************************************************************************) { *** create DRV11j Devices, pilot and assistant *** } proced_tcs_define_drv11j ; {*** Enter the Int Service Routine for the pilot and assistant DRV11J *** } {*** into the dispatch table that the ISR macro PQBA_ISR10D will use *** } {*** to redirect the QBus interrupts *** } {*** More precisely, use the pointer to the Interrupt Dispatcher code *** } {*** of the Interrupt dispatch Block for the DRV11J *** } {*** Also copy system pointer to DRV CSR registers into kernel's IDB *** } {*** Also replace return opcode from REI to RSB, to only use REI once *** } write_dev_addr_in_int_disp_blk ( DEV_NAME := 'DRV11J_PILOT', DEV_VECT := p_isr_vect_pilot, REG_ADDR := reg_drv11j_pilot, INT_DISP_BLOCK := p_idb ) ; handle_trc_sys ( TAG := tag, MESSAGE := ' Inserting DRV11J_PILOT' + ' in ZRL Interrupt Redirection Table ' ) ; {evaluate interrupt vector number (longword rank in interrupt vector page)} QBus_vector := (p_isr_vect_pilot::INTEGER MOD 512) DIV 4 ; {copy pointer to DRV dispatcher code into pQBA dispatcher array} isr_comm_region^.dispatch_ptr[QBus_vector-63] := ADDRESS(p_idb^.IDB$B_DISPATCHER) ; isr_comm_region^.devcnt := isr_comm_region^.devcnt + 1 ; {look for the last instruction in interrupt dispatch block, } {start at the end of the dispatcher code and look for a REI opcode} replace_REI_with_RSB_in_IDB ( DEV_NAME := 'DRV11J_PILOT', INT_DISP_BLOCK := p_idb ) ; { *** same thing for Assistant DRV11J *** } write_dev_addr_in_int_disp_blk ( DEV_NAME := 'DRV11J_ASSIST', DEV_VECT := p_isr_vect_assist, REG_ADDR := reg_drv11j_assist, INT_DISP_BLOCK := p_idb ) ; handle_trc_sys ( TAG := tag, MESSAGE := ' Inserting DRV11J_ASSIST' + ' in ZRL Interrupt Redirection Table ' ) ; {evaluate interrupt vector number (longword rank in interrupt vector page)} QBus_vector := (p_isr_vect_assist::INTEGER MOD 512) DIV 4 ; isr_comm_region^.dispatch_ptr[QBus_vector-63] := ADDRESS(p_idb^.IDB$B_DISPATCHER) ; isr_comm_region^.devcnt := isr_comm_region^.devcnt + 1 ; {look for the last instruction in interrupt dispatch block, } {start at the end of the dispatcher code and look for a REI opcode} replace_REI_with_RSB_in_IDB ( DEV_NAME := 'DRV11J_ASSIST', INT_DISP_BLOCK := p_idb ) ; (******************************************************************************) { "connect" to pVBA mapping registers } map_memory ( PHYS_ADDR := VAX_addr_pVBA_mapping_reg, VIRT_ADDR := VME_mapping_reg, SIZE := SIZE(pVBA_mapping_registers) ) ; { "connect" to pVBA mapped region } map_memory ( PHYS_ADDR := VAX_addr_pVBA_mapped_region, VIRT_ADDR := VME_mapped_region, SIZE := SIZE(pVBA_mapped_region) ) ; { reset pQBA and PVBA devices, re-program DRV11Js, reload VME mapping params } reset_ZRL_and_DRV11Js ; (******************************************************************************) (* Initialization done, reenable other processes, and wait for interrupt *) (******************************************************************************) ENABLE_SWITCH ; (******************************************************************************) (* Infinite Loop, print out any errors that occur, and reset card when needed *) (******************************************************************************) REPEAT (* Wait for a signal that an error occurred *) WAIT_ANY( dev_DUAL[pQBA], dev_DUAL[pVBA], RESULT := result ) ; lock_console ; DISABLE_SWITCH ; unlock_console ; (******************************************************************************) (*** pQBA Interrupt ***) (******************************************************************************) IF ( result = 1 ) {the pQBA is being signaled by the ISR Macro} THEN BEGIN handle_trc_err ( TAG := tag, MESSAGE := ' ZRL DUAL Int Serv Routine has signaled the pQBA' + ' Master device...' ) ; (* Check for reset error *) IF ( isr_comm_region^.int1_error = %XFFFFFFFF ) THEN BEGIN handle_trc_err ( TAG := tag, MESSAGE := '...pQBA Accessed while reset or powered down ' ) ; reset_pQBA ; END ELSE BEGIN IF ( isr_comm_region^.int1_error <> 0 ) (* Report any INT1 errors *) THEN BEGIN IF ( bitwise_and ( isr_comm_region^.int1_error, pQBA_NXM ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := '...Timeout while accessing Q-Bus addr %X' + HEX(isr_comm_region^.qear_val * shift_9bits) ) ; IF ( bitwise_and ( isr_comm_region^.int1_error, pQBA_BAT ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := '...Bus Access Timeout' ) ; IF ( bitwise_and ( isr_comm_region^.int1_error, pQBA_LOST ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := '...Lost error address info' + ' due to multiple errors' ) ; IF ( bitwise_and ( isr_comm_region^.int1_error, pQBA_PERR ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := '...Parity Error on Q-Bus read at addr %X' + HEX(isr_comm_region^.qear_val * shift_9bits) ) ; IF ( bitwise_and ( isr_comm_region^.int1_error, pQBA_PWRFL ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := '...AC Power Fail' ) ; IF ( bitwise_and ( isr_comm_region^.int1_error, pQBA_IACKTMO ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := '...Interrupt Acknowledge Timeout' ) ; IF ( bitwise_and ( isr_comm_region^.int1_error, pQBA_GRTMO ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := '...External Q-Bus Device' + ' Bus Grant Timeout' ) ; IF ( bitwise_and ( isr_comm_region^.int1_error, pQBA_DMANXM ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := '...DMA Timeout' + ' while accessing Q-Bus Addr %X' + HEX(isr_comm_region^.dmaear_val * shift_9bits) ); IF ( bitwise_and ( isr_comm_region^.int1_error, pQBA_DMAPERR ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := '...DMA Parity Error at Q-Bus Addr %X' + HEX(isr_comm_region^.dmaear_val * shift_9bits) ); (* Re-enable INT1 interrupts *) WRITE_REGISTER( addr_pQBA^.int1, %X00800000 ); END ; IF ( isr_comm_region^.int0_error <> 0 ) (* Report any INT0 errors *) THEN BEGIN IF ( bitwise_and ( isr_comm_region^.int0_error, pQBA_BAD_VECTOR ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := '...Q-Bus interrupt vector out of range: %X' + HEX(isr_comm_region^.int0_val) ) ; IF ( bitwise_and ( isr_comm_region^.int0_error, pQBA_UNEXP_VECTOR ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := '...Interrupt from unmapped Q-Bus vector: %X' + HEX(isr_comm_region^.int0_val) ) ; IF ( bitwise_and ( isr_comm_region^.int0_error, pQBA_INT_OVERFLOW ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := '...Q-Bus interrupt count overflow' ) ; IF ( bitwise_and ( isr_comm_region^.int0_error, pQBA_VEC_ERR ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := '...Interrupt vector read error: %X' + HEX(isr_comm_region^.int0_val) ) ; (* Re-enable INT0 interrupts *) WRITE_REGISTER( addr_pQBA^.int0, %X00800000 ) ; END ; END ; { *** re-Initialize DRV11j Devices, pilot and assistant *** } { *** and the COMINT card *** } proced_tcs_initialize_drv11j ; proced_tcs_reset_comint ; END (******************************************************************************) (*** pVBA Interrupt ***) (******************************************************************************) ELSE BEGIN {the pVBA is being signaled by the ISR Macro} handle_trc_err ( TAG := tag, MESSAGE := ' ZRL DUAL Int Serv Routine has signaled the pVBA' + ' Master device...' ) ; IF ( Ignore_pVBA = TRUE ) THEN GOTO skip_service_pVBA ; (* Check for reset error *) IF ( isr_comm_region^.int1_error = %XFFFFFFFF ) THEN BEGIN handle_trc_err ( TAG := tag, MESSAGE := '...pVBA Accessed while reset or powered down ' ) ; reset_pVBA ; END ELSE BEGIN IF ( isr_comm_region^.int1_error <> 0 ) (* Report any INT1 errors *) THEN BEGIN CASE isr_comm_region^.int1_error OF pVBA_MBX_WRV : (* Mailbox FIFO data available *) handle_trc_err ( TAG := tag, MESSAGE := '...Unexpected Mailbox Interrupt' ) ; pVBA_VME_RDYV : (* VME Bus ready *) handle_trc_err ( TAG := tag, MESSAGE := '...Unexpected VME Bus Ready Interrupt' ) ; pVBA_VSB_RDYV : (* VSB Bus ready *) handle_trc_err ( TAG := tag, MESSAGE := '...Unexpected VSB Bus Ready Interrupt' ) ; pVBA_VME_ERRV : (* VME Bus error *) handle_trc_err ( TAG := tag, MESSAGE := '...Bus Error while accessing VME Bus' ) ; pVBA_VSB_ERRV : (* VSB Bus error *) handle_trc_err ( TAG := tag, MESSAGE := '...Bus Error while accessing VSB Bus' ) ; pVBA_VME_OVFV : (* VME Bus request count over/under flow *) handle_trc_err ( TAG := tag, MESSAGE := '...VME Bus Request Count Overflow' ) ; pVBA_VSB_OVFV : (* VSB Bus request count over/under flow *) handle_trc_err ( TAG := tag, MESSAGE := '...VSB Bus Request Count Overflow' ) ; pVBA_VME_ABOV : (* VME Cycle abort *) handle_trc_err ( TAG := tag, MESSAGE := '...VME Cycle Abort, timeout accessing bus' ) ; pVBA_VSB_ABOV : (* VSB Cycle abort *) handle_trc_err ( TAG := tag, MESSAGE := '...VSB Cycle Abort, timeout accessing bus' ) ; END ; (* Re-enable INT1 interrupts *) WRITE_REGISTER( addr_pVBA^.int1, 0 ); END ; IF ( isr_comm_region^.int0_error <> 0 ) (* Report any INT0 errors *) THEN BEGIN IF ( bitwise_and ( isr_comm_region^.int0_error, pVBA_BAD_VECTOR ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := '...VME interrupt vector out of range: %X' + HEX(isr_comm_region^.int0_val) ) ; IF ( bitwise_and ( isr_comm_region^.int0_error, pVBA_UNEXP_VECTOR ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := '...Interrupt from unmapped VNE vector: %X' + HEX(isr_comm_region^.int0_val) ) ; IF ( bitwise_and ( isr_comm_region^.int0_error, pVBA_INT_OVERFLOW ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := '...VME interrupt count overflow' ) ; IF ( bitwise_and ( isr_comm_region^.int0_error, pVBA_VEC_ERR ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := '...Interrupt vector read error: %X' + HEX(isr_comm_region^.int0_val) ) ; (* Re-enable INT0 interrupts *) WRITE_REGISTER( addr_pVBA^.int0, 0 ) ; END ; { *** reload the VME mapping register *** } handle_trc_err ( TAG := tag, MESSAGE := ' Re-Programming pVBA Mapping Registers ' ) ; Load_pVBA_Mapping_Registers ; END ; skip_service_pVBA: END ; ENABLE_SWITCH ; UNTIL ( forever ) ; END ; { *************************************************************************** } { *************************************************************************** } PROCEDURE reset_ZRL_and_DRV11Js ; BEGIN (******************************************************************************) (* Reset the pQBA *) (******************************************************************************) reset_pQBA ; { *** Initialize DRV11j Devices, pilot and assistant *** } proced_tcs_initialize_drv11j ; { *** initialize the COMINT card *** } proced_tcs_reset_comint ; (******************************************************************************) (* Reset the pVBA *) (******************************************************************************) reset_pVBA ; { *** load the mapping register describing address translation to VME *** } handle_trc_sys ( TAG := tag, MESSAGE := ' Programming pVBA Mapping Registers ' ) ; Load_pVBA_Mapping_Registers ; END ; { *************************************************************************** } { *************************************************************************** } PROCEDURE reset_pQBA ; BEGIN handle_trc_sys ( TAG := tag, MESSAGE := ' Resetting the pQBA ' ) ; WRITE_REGISTER( addr_pQBA^.reset, 1 ) ; REPEAT handle_trc_sys ( TAG := tag, MESSAGE := ' Waiting for pQBA Ready after Reset' ) ; WAIT_ANY ( TIME := one_second ) ; UNTIL ( READ_REGISTER( addr_pQBA^.reset ) <> %XFFFFFFFF ) ; (* Enable reset error interrupts *) WRITE_REGISTER( addr_pQBA^.int0, %X00800000 ); (* Enable INT1 interrupts *) WRITE_REGISTER( addr_pQBA^.int1, %X00800000 ); (* Re-enable pQBA Interrupts and DMA, since disabled by reset *) {18-NOV-1993 Philippe: problem writing to DMA control } {after writing to int0 and int1. This wipes out int0/1} {We could probably do DMA first, then write int0 ant1} {But we can simply skip it, as we don't use DMA} { WRITE_REGISTER( addr_pQBA^.dmaen, 1 ) ; } END ; { *************************************************************************** } { *************************************************************************** } PROCEDURE reset_pVBA ; BEGIN IF ( Ignore_pVBA = TRUE ) THEN GOTO skip_pVBA_Init ; handle_trc_sys ( TAG := tag, MESSAGE := ' Resetting the pVBA ' ) ; WRITE_REGISTER( addr_pVBA^.reset, 1 ) ; REPEAT handle_trc_sys ( TAG := tag, MESSAGE := ' Waiting for pVBA Ready after Reset' ) ; WAIT_ANY ( TIME := one_second ) ; UNTIL ( ( bitwise_and( addr_pVBA^.reset, 1) = 0 ) OR ( Ignore_pVBA = TRUE ) ) ; (* Enable reset error interrupts *) WRITE_REGISTER( addr_pVBA^.reset, 0 ) ; (* Re-enable pVBA Interrupts, since disabled by reset *) (* Enable INT0 interrupts *) WRITE_REGISTER( addr_pVBA^.int0, 0 ); (* Enable INT1 interrupts *) WRITE_REGISTER( addr_pVBA^.int1, 0 ); skip_pVBA_Init: END ; { *************************************************************************** } { *************************************************************************** } PROCEDURE Load_pVBA_Mapping_Registers ; BEGIN { setup the page mapped for the Hydra A } VME_mapping_reg^[Hydra_A_Page_DPM] := ZERO ; VME_mapping_reg^[Hydra_A_Page_DPM].swap_ctrl := swap_not ; VME_mapping_reg^[Hydra_A_Page_DPM].bus_select := select_VME_bus ; VME_mapping_reg^[Hydra_A_Page_DPM].addr_mode := A32_addr_mode ; VME_mapping_reg^[Hydra_A_Page_DPM].VME_page := VME_addr_Hydra_A_DPM DIV Longwords_per_mapped_page DIV 4 ; VME_mapping_reg^[Hydra_A_Page_Ctrl] := ZERO ; VME_mapping_reg^[Hydra_A_Page_Ctrl].swap_ctrl := swap_not ; VME_mapping_reg^[Hydra_A_Page_Ctrl].bus_select := select_VME_bus ; VME_mapping_reg^[Hydra_A_Page_Ctrl].addr_mode := A32_addr_mode ; VME_mapping_reg^[Hydra_A_Page_Ctrl].VME_page := VME_addr_Hydra_A_Ctrl DIV Longwords_per_mapped_page DIV 4 ; { setup the page mapped for the Hydra B } VME_mapping_reg^[Hydra_B_Page_DPM] := ZERO ; VME_mapping_reg^[Hydra_B_Page_DPM].swap_ctrl := swap_not ; VME_mapping_reg^[Hydra_B_Page_DPM].bus_select := select_VME_bus ; VME_mapping_reg^[Hydra_B_Page_DPM].addr_mode := A32_addr_mode ; VME_mapping_reg^[Hydra_B_Page_DPM].VME_page := VME_addr_Hydra_B_DPM DIV Longwords_per_mapped_page DIV 4 ; VME_mapping_reg^[Hydra_B_Page_Ctrl] := ZERO ; VME_mapping_reg^[Hydra_B_Page_Ctrl].swap_ctrl := swap_not ; VME_mapping_reg^[Hydra_B_Page_Ctrl].bus_select := select_VME_bus ; VME_mapping_reg^[Hydra_B_Page_Ctrl].addr_mode := A32_addr_mode ; VME_mapping_reg^[Hydra_B_Page_Ctrl].VME_page := VME_addr_Hydra_B_Ctrl DIV Longwords_per_mapped_page DIV 4 ; { setup the page mapped for the Hydra C } VME_mapping_reg^[Hydra_C_Page_DPM] := ZERO ; VME_mapping_reg^[Hydra_C_Page_DPM].swap_ctrl := swap_not ; VME_mapping_reg^[Hydra_C_Page_DPM].bus_select := select_VME_bus ; VME_mapping_reg^[Hydra_C_Page_DPM].addr_mode := A32_addr_mode ; VME_mapping_reg^[Hydra_C_Page_DPM].VME_page := VME_addr_Hydra_C_DPM DIV Longwords_per_mapped_page DIV 4 ; VME_mapping_reg^[Hydra_C_Page_Ctrl] := ZERO ; VME_mapping_reg^[Hydra_C_Page_Ctrl].swap_ctrl := swap_not ; VME_mapping_reg^[Hydra_C_Page_Ctrl].bus_select := select_VME_bus ; VME_mapping_reg^[Hydra_C_Page_Ctrl].addr_mode := A32_addr_mode ; VME_mapping_reg^[Hydra_C_Page_Ctrl].VME_page := VME_addr_Hydra_C_Ctrl DIV Longwords_per_mapped_page DIV 4 ; { setup the pages mapped for the CPU 68k } VME_mapping_reg^[CPU_68k_Page_DPM] := ZERO ; VME_mapping_reg^[CPU_68k_Page_DPM].swap_ctrl := swap_not ; VME_mapping_reg^[CPU_68k_Page_DPM].bus_select := select_VME_bus ; VME_mapping_reg^[CPU_68k_Page_DPM].addr_mode := A32_addr_mode ; VME_mapping_reg^[CPU_68k_Page_DPM].VME_page := VME_addr_CPU_68k_DPM DIV Longwords_per_mapped_page DIV 4 ; { *** NOTICE THAT BELOW THE PVBA IS ASKED TO PERFORM "BYTE SWAPPING". } { *** *************************************************************** } { *** IN VME SPACE, WE WANT TO ADDRESS THIS SPACE ONE BYTE AT A TIME, { *** WHILE SKIPPING ALL EVEN BYTES. } { *** WE DO NOT WANT TO RETRIEVE BYTES ACCORDING TO THEIR SIGNIFICANCE } { *** IN THEIR LONGWORD BOUNDARIES. } { *** INSTEAD, WE NEED A ONE-TO-ONE TRANSFER OF THE VAX ADDRESS TO VME SPACE} { *** IN OTHER WORDS, WE WANT TO INHIBIT THE PVBA FROM PERFORMING } { *** ANY ADDRESS TRANSLATION ON THE A0-A1 ADDRESS LINES} { *** *************************************************************** } VME_mapping_reg^[CPU_68k_Page_Ctrl] := ZERO ; VME_mapping_reg^[CPU_68k_Page_Ctrl].swap_ctrl := swap_full ; VME_mapping_reg^[CPU_68k_Page_Ctrl].bus_select := select_VME_bus ; VME_mapping_reg^[CPU_68k_Page_Ctrl].addr_mode := A32_addr_mode ; VME_mapping_reg^[CPU_68k_Page_Ctrl].VME_page := VME_addr_CPU_68k_Ctrl DIV Longwords_per_mapped_page DIV 4 ; { setup the page mapped for the Ironics IO cards} { *** NOTICE THAT BELOW THE PVBA IS ASKED TO PERFORM "BYTE SWAPPING". } { *** *************************************************************** } VME_mapping_reg^[Ironics_page] := ZERO ; VME_mapping_reg^[Ironics_page].swap_ctrl := swap_full ; VME_mapping_reg^[Ironics_page].bus_select := select_VME_bus ; VME_mapping_reg^[Ironics_page].addr_mode := A32_addr_mode ; VME_mapping_reg^[Ironics_page].VME_page := VME_addr_Ironics DIV Longwords_per_mapped_page DIV 4 ; { setup the page mapped for the scratch memory region} VME_mapping_reg^[Scratch_A24_page] := ZERO ; VME_mapping_reg^[Scratch_A24_page].swap_ctrl := swap_not ; VME_mapping_reg^[Scratch_A24_page].bus_select := select_VME_bus ; VME_mapping_reg^[Scratch_A24_page].addr_mode := A32_addr_mode ; VME_mapping_reg^[Scratch_A24_page].VME_page := VME_addr_A24_Scratch DIV Longwords_per_mapped_page DIV 4 ; { setup the page mapped for the scratch short IO memory region} VME_mapping_reg^[Scratch_A16_page] := ZERO ; VME_mapping_reg^[Scratch_A16_page].swap_ctrl := swap_not ; VME_mapping_reg^[Scratch_A16_page].bus_select := select_VME_bus ; VME_mapping_reg^[Scratch_A16_page].addr_mode := A32_addr_mode ; VME_mapping_reg^[Scratch_A16_page].VME_page := VME_addr_A16_Scratch DIV Longwords_per_mapped_page DIV 4 ; END ; { *************************************************************************** } FUNCTION bitwise_and ( op1 , op2 : INTEGER ) : INTEGER ; VAR set1, set2, set3 : [LONG] PACKED SET OF 0..31 ; BEGIN set1::BYTE_DATA := op1::BYTE_DATA ; set2::BYTE_DATA := op2::BYTE_DATA ; set3 := set1 * set2 ; bitwise_and::BYTE_DATA := set3::BYTE_DATA ; END ; { *************************************************************************** } [INLINE] FUNCTION time_stamp : STRING(23) ; VAR status : INTEGER ; bin_time : LARGE_INTEGER ; ascii_time : STRING(23) ; BEGIN GET_TIME ( bin_time, STATUS := status ) ; ascii_time := TIME_STRING(bin_time) ; time_stamp := SUBSTR(ascii_time,13) ; END ; { *************************************************************************** } { *************************************************************************** } END.