{ *************************************************************************** } MODULE mod_handle_pVBA ; { Created 27-APR-1994 Philippe Laurens - MSU L1 Trigger } { *************************************************************************** } INCLUDE mod_sys_service, mod_handle_console, mod_handle_tracing, $PHYSICAL_ADDRESS, $KERNELMSG, { from ELN$:RTLOBJECT.OLB } $KERNEL ; { *************************************************************************** } EXPORT 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 } init_pVBA_device ; {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 } map_memory, {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 } 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 } { *************************************************************************** } CONST one_second = -10000000 ; forever = FALSE ; { *** the following decalrations match pVBA4000.H and pVBA_INTERRUPTS.H, *** } { *** but most importantly match the declarations in pVBA_ISR10D.MAC *** } (* 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 *) { base addresses } pVBA_CSR_BASE = %X34000000; (* Base of pVBA_REGS *) pVBA_CMEM_BASE = %X36000000; (* Base of Control Memory *) pVBA_MBX_BASE = %X36007c00; (* Base of Mailbox registers *) pVBA_MEM_BASE = %X38000000; (* Base of mapped region *) (* 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 *) byte = [BYTE] 0..255 ; pVBA_isr_comm_region = PACKED RECORD int0_error : INTEGER ; (* Vector for INT0 *) int1_error : INTEGER ; (* Vector 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 *) overflow_cnt : INTEGER ; (* Maximum number of passes through ISR. reg *) reserved : ARRAY [1..57] OF INTEGER ; (* Reserved, size = 63 - # of ints preceeding *) devcnt : INTEGER ; (* Number of devices on VME, offset %XFC *) dispatch_ptr : ARRAY [1..192] OF ^ANYTYPE ; (* List of dispatch addresses, offset %X100, first entry for VME vector %x40, second for second for %x41, last for %xFF *) END ; 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 {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 = %X36000000 ; VAX_addr_pVBA_mapped_region = %X38000000 ; 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 ; VAR tag : VARYING_STRING(8) := 'pVB/CTL%' ; proc_pVBA_device_control : PROCESS ; name_pVBA_device_control : NAME ; VME_mapping_reg : ^pVBA_mapping_registers ; VME_mapped_region : ^pVBA_mapped_region ; { *************************************************************************** } PROCEDURE init_pVBA_device ; VAR status : INTEGER ; BEGIN CREATE_PROCESS ( proc_pVBA_device_control, block_pVBA_device_control, STATUS := status ) ; handle_trc_sta ( TAG := 'CRE/PRC%pVBA_ctrl%', STATUS := status ) ; KER$NAME_OBJECT( name_pVBA_device_control, 'pVBA CTRL', proc_pVBA_device_control, STATUS := status ) ; handle_trc_sta ( TAG := 'NAM/PRC%pVBA_ctrl%', STATUS := status ) ; { *** raise the priority of the process to service the pVBA ASAP *** } SET_PROCESS_PRIORITY ( proc_pVBA_device_control, 6, STATUS := status ); handle_trc_sta ( TAG := 'SET/PIO%pVBA_ctrl%', STATUS := status ) ; END ; { *************************************************************************** } INTERRUPT_SERVICE pVBA_isr ( p_pVBA : ^pVBA_regs ; p_isr_comm_region : ^ANYTYPE ) ; EXTERNAL ; { *************************************************************************** } PROCESS_BLOCK block_pVBA_device_control ; VAR dev_pVBA : DEVICE ; (* pVBA device object *) isr_comm_region :^pVBA_isr_comm_region ; (* pVBA interrupt region *) addr_pVBA :^pVBA_regs ; (* Pointer to pVBA registers *) vect_pVBA :^INTEGER ; prio_pVBA : INTEGER ; status : INTEGER ; BEGIN lock_console ; DISABLE_SWITCH ; unlock_console ; handle_trc_sys ( TAG := tag, MESSAGE := ' Creating pVBA Device ' ) ; (* Create the Master pVBA 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 ( 'PVBA', dev_pVBA, SERVICE_ROUTINE := pVBA_isr, REGION := isr_comm_region, VECTOR := vect_pVBA, PRIORITY := prio_pVBA, 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 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 := '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. *) { *** 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 *** } write_dev_addr_in_int_disp_blk ( DEV_NAME := 'PVBA', DEV_VECT := vect_pVBA, REG_ADDR := addr_pVBA ) ; { *** display collected information *** } handle_trc_inf ( TAG := 'INI/pQB%', MESSAGE := ' pVBA Register Base Address = %X' + HEX(PHYSICAL_ADDRESS(addr_pVBA)) ) ; handle_trc_inf ( TAG := 'INI/pQB%', MESSAGE := ' pVBA Interrupt Prior Level = %D ' + CONVERT(STRING,prio_pVBA) ) ; handle_trc_inf ( TAG := 'INI/pQB%', MESSAGE := ' pVBA Card Interrupt Vector = %X' + HEX(PHYSICAL_ADDRESS(vect_pVBA)) ) ; ENABLE_SWITCH ; (* Reset the pVBA *) handle_trc_sys ( TAG := tag, MESSAGE := ' Resetting pVBA ' ) ; WRITE_REGISTER( addr_pVBA^.reset, 1 ) ; REPEAT WAIT_ANY ( TIME := one_second ) ; UNTIL ( bitwise_and ( addr_pVBA^.reset, 1 ) = 0 ) ; (* 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 ); { connect to mapping registers } map_memory ( PHYS_ADDR := VAX_addr_pVBA_mapping_reg, VIRT_ADDR := VME_mapping_reg, SIZE := SIZE(pVBA_mapping_registers) ) ; { connect to mapped region } map_memory ( PHYS_ADDR := VAX_addr_pVBA_mapped_region, VIRT_ADDR := VME_mapped_region, SIZE := SIZE(pVBA_mapped_region) ) ; (* Loop forever, printing out any errors that occur *) REPEAT Load_pVBA_Mapping_Registers ; (* Wait for a signal that an error occurred *) WAIT_ANY( dev_pVBA ) ; lock_console ; DISABLE_SWITCH ; unlock_console ; handle_trc_err ( TAG := 'pQB/JOB%', MESSAGE := ' pVBA Int Serv Routine has signaled the pVBA ' + ' Master device...' ) ; (* Check for reset error *) IF ( isr_comm_region^.int1_error = -1) THEN BEGIN handle_trc_err ( TAG := tag, MESSAGE := ' pVBA Accessed while reset or powered down ' ) ; handle_trc_err ( TAG := tag, MESSAGE := ' Resetting pVBA ' ) ; WRITE_REGISTER( addr_pVBA^.reset, 1 ) ; { Weird..? already done by the ISR} REPEAT WAIT_ANY ( TIME := one_second ) ; UNTIL ( bitwise_and ( addr_pVBA^.reset, 1 ) = 0 ) ; (* 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 ); END ELSE BEGIN IF ( isr_comm_region^.int1_error <> 0 ) (* Report any INT1 errors *) THEN BEGIN (* Mailbox FIFO data available *) IF ( bitwise_and ( isr_comm_region^.int1_error, pVBA_MBX_WRV ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := 'Unexpected Mailbox Interrupt' ) ; (* VME Bus ready *) IF ( bitwise_and ( isr_comm_region^.int1_error, pVBA_VME_RDYV ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := 'Unexpected VME Bus Ready Interrupt' ) ; (* VSB Bus ready *) IF ( bitwise_and ( isr_comm_region^.int1_error, pVBA_VSB_RDYV ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := 'Unexpected VSB Bus Ready Interrupt' ) ; (* VME Bus error *) IF ( bitwise_and ( isr_comm_region^.int1_error, pVBA_VME_ERRV ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := 'Bus Error while accessing VME Bus' ) ; (* VSB Bus error *) IF ( bitwise_and ( isr_comm_region^.int1_error, pVBA_VSB_ERRV ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := 'Bus Error while accessing VSB Bus' ) ; (* VME Bus request count over/under flow *) IF ( bitwise_and ( isr_comm_region^.int1_error, pVBA_VME_OVFV ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := 'VME Bus Request Count Overflow' ) ; (* VSB Bus request count over/under flow *) IF ( bitwise_and ( isr_comm_region^.int1_error, pVBA_VSB_OVFV ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := 'VSB Bus Request Count Overflow' ) ; (* VME Cycle abort *) IF ( bitwise_and ( isr_comm_region^.int1_error, pVBA_VME_ABOV ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := 'VME Cycle Abort, timeout accessing bus' ) ; (* VSB Cycle abort *) IF ( bitwise_and ( isr_comm_region^.int1_error, pVBA_VSB_ABOV ) <> 0 ) THEN handle_trc_err ( TAG := tag, MESSAGE := 'VSB Cycle Abort, timeout accessing bus' ) ; (* 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 := ' VNE 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 ; END ; ENABLE_SWITCH ; UNTIL ( forever ) ; 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.