.TITLE TT-idle-mon ; Install hook for idle terminal timing .IDENT /V1.0 <97.351>/ ;++ ; Copyright © 1997 by Brian Schenkenberger and TMESIS. ; ALL RIGHTS RESERVED. ; Notice of Disclaimer ; ------------------------- ; ; This Software is provided "AS IS" and is supplied for informational purpose ; only. No warranty is expressed or implied and no liability can be accepted ; for any direct, indirect or consequential damages or for any damage whatso- ; ever resulting in the loss of systems, data or profit from the use of this ; software or from any of the information contained herein. The author makes ; no claims as to the suitablility or fitness of this Software or information ; contain herein for any particular purpose. ; ; Redistribution or Copying ; ------------------------- ; Permission is hereby granted *ONLY* for the "not-for-profit" redistribution ; of this software provided that ALL SOURCE and/or OBJECT CODE remains intact ; and ALL COPYRIGHT NOTICES and NOTICES OF DISCLAIMER remain intact from its ; original distribution. ; ; A fee may be levied for the media upon which the software is redistributed ; provided that the fee charged is for the media and the production costs of ; the media and that the cost associated is clearly stated. ; ; Execution of the Software ; ------------------------- ; Any proper copy of this Software obtained within the guidelines expressed ; in the section above entitiled, "Redistribution or Copying" may be used on ; any CPU so desired by the proper recipient of the copy. ; ; Title and Ownership ; ------------------------- ; NO TITLE TO AND/OR OWNERSHIP OF THIS SOFTWARE IS HEREBY TRANSFERRED. ANY ; MODIFICATION WITHOUT THE PRIOR WRITTEN CONSENT OF THE COPYRIGHT HOLDER IS ; PROHIBITED. ANY USE, IN WHOLE OR PART, OF THIS SOFTWARE FOR A COMMERCIAL ; PRODUCT WITHOUT THE PRIOR WRITTEN CONSENT OF THE COPYRIGHT HOLDER IS ALSO ; PROHIBITED. THE TECHNIQUES EMPLOYED IN THE SOFTWARE ARE THE INTELLECTUAL ; PROPERTY OF THE COPYRIGHT HOLDER. ;-- ;++ ; Program Author: Brian Schenkenberger, VAXman- ; Author's e-Mail: VAXman@TMESIS.COM ; Program Genesis: 17-DEC-1997 ;-- ;++ ; This program is a loadable executive image, execlet or LEI. Its intended ; purpose is to install an intercept into the OpenVMS terminal class driver ; (TTDRIVER) which causes the terminal UCB field UCB$L_DUETIM to be updated ; with the value of the system cell EXE$GL_ABSTIM whenever an I/O operation ; is performed. ; ; This execlet is intended to be loaded during the system bootstrap. This ; will insure that the TTDRIVER intercept is in place prior to any terminal ; port driver being loaded. The DECnet RTDRIVER, however, does not use the ; TTDRIVER class driver. Thus, a special intercept is used for RTDRIVER. ; ; To facilitate the aforementioned two drivers, the execlet initialization ; routine is designed to be invoked multiple instances. During the system ; bootstrap, this execlet will be loaded and the initialization routine is ; invoked. At this time, there is no RTDRIVER present and therefore, the ; initialization code can only install the TTDRIVER intercept. Normally, ; the initializaiton routine would be discarded once it is invoked. This ; execlet postpones the deallocation and discarding of the initialization ; routine in hopes that it will be reinvoked after the RTDRIVER is loaded ; when DECnet is started. It is reinvoked by a routine which invokes the ; system routine LDR$INIT_ALL at kernel mode. If RTDRIVER is present when ; the initialization routine is reinvoked, the intercept is installed into ; the RTDRIVER and then, the initialization routine is marked for discard. ;-- ;++ ; To build: { } - optional qualifiers ; ; On VAX: ; $ MACRO TT_IDLE_MONITOR {/LIST} ; $ LINK/NOTRACEBACK/SHAREABLE/NOSYSSHR - ; TT_IDLE_MONITOR.OBJ,TT_IDLE_MONITOR.OPT/OPTIONS,- ; SYS$SYSTEM:SYS.STB/SELECTIVE {/MAP/FULL/SYMBOL_TABLE} ; ; On Alpha: ; $ MACRO TT_IDLE_MONITOR {/LIST} ; $ LINK/NOTRACEBACK/SHAREABLE/NOSYSSHR/NATIVE_ONLY/SYSEXE - ; TT_IDLE_MONITOR.OBJ,TT_IDLE_MONITOR.OPT/OPTIONS ; {MAP/FULL/SYMBOL_TABLE} ;-- ;++ ; The resulting loadable execlet, TT_IDLE_MONITOR.EXE, must be placed into ; the directory: SYS$COMMON:[SYS$LDR]. ; ; To instruct the system to load the execlet, issue the following commands: ; ; $ MCR SYSMAN SYS_LOADABLE ADD IDLE TT_IDLE_MONITOR ; $ @SYS$UPDATE:VMS$SYSTEM_IMAGES ; ; In case of trouble, conversationally boot the system and at the SYSBOOT> ; prompt, enter: SYSBOOT> SET LOAD_SYS_IMAGES 0 and then SYSBOOT> CONTINUE ; When the system has been booted, you can remove the TT_IDLE_MONITOR from ; the system bootstrap load by issueing the following commands: ; ; $ MCR SYSMAN SYS_LOADABLE REMOVE IDLE TT_IDLE_MONITOR ; $ @SYS$UPDATE:VMS$SYSTEM_IMAGES ; ; Shutdown the system and conversationally reboot it and set the parameter ; LOAD_SYS_IMAGES back to its original value (typically the default value). ;-- ;++ .SBTTL Determine the target architecture ;-- .NTYPE ...ON_ALPHA...,R31 .IIF EQ,<...ON_ALPHA...@-4&^XF>-5, ALPHA=0 .IIF DF,ALPHA, .DISABLE FLAGGING ;++ .SBTTL Primitive program datum definitions ;-- ZERO = 0 ; |_ BYTE = 1@0 ; |_|_ WORD = 1@1 ; |___|___ LONG = 1@2 ; |_______|_______ QUAD = 1@3 ; |_______________|_______________ OCTA = 1@4 ; |_______________|_______________| PAGE = 1@9 ; VAX page ; Alpha Pagelet BLOCK= 1@9 ; Standard disk block size ;++ .SBTTL Macro declarations for architectural conditional compilation ;-- .MACRO .ON_AXP OPERATION ; conditional compilation macro .IIF DF,ALPHA, OPERATION ; for code specific to Alpha .ENDM .ON_AXP;OPERATION .MACRO .ON_VAX OPERATION ; conditional compilation macro .IIF NDF,ALPHA, OPERATION ; for code specific to VAX .ENDM .ON_VAX;OPERATION ;++ .SBTTL Macro declarations for 64 bit address conditional compilation ;-- .MACRO .IF_32 OPERATION .IIF NDF,ALPHA, OPERATION .IIF NDF,ALPHA, .MEXIT .IIF NDF,SS$_NORMAL,$SSDEF .IIF NDF,SS$_ARG_GTR_32_BITS, OPERATION .ENDM .IF_32;OPERATION .MACRO .IF_64 OPERATION .IIF NDF,ALPHA, .MEXIT .IIF NDF,SS$_NORMAL,$SSDEF .IIF DF,SS$_ARG_GTR_32_BITS, OPERATION .ENDM .IF_64;OPERATION ;++ .SBTTL Macros to manipulate 64 bit register stack saves and restores ;-- .MACRO $PUSHR64,REGLST .MACRO ...REV,A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15 .IRP REG, .IIF NB,REG, EVAX_STQ REG,-(SP) .ENDR .ENDM ...REV ...REV REGLST .MDELETE ...REV .ENDM $PUSHR64 .MACRO $POPR64,REGLST .IRP REG, .IIF NB,REG, EVAX_LDQ REG,(SP)+ .ENDR .ENDM $POPR64 ;++ ; The following macro is used to check the return status of system calls. ; It can take up to three arguments: ; STS ...... register or memory containing the status value ; ERROR .... instruction to execute if an error is detected ; NORMAL ... change status to a success before taking ERROR ;-- .MACRO CHKSTS,STS=,NORMAL=,ERROR=,?LBL .IIF DIF,,, MOVZWL STS,R0 .IIF IDN,,, BLBS R0,LBL .IIF DIF,,, BBSS #0,R0,LBL .IRP ERR, .SHOW MEB ERR .NOSHOW MEB .ENDR LBL: .ENDM CHKSTS ;++ ; The following macro is used to call routine which do not have a Digital ; supplied invocation macro. It takes two arguments: ; ROUTIN ...... routine to be invoked ; ARGUMENTS ... list of arguments and their stack access mechanism. ;-- .MACRO CALL,ROUTIN,ARGUMENTS .SHOW MEB .MACRO ...REV,FUNC,A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF ... = 0 .IRP ARG,<,,,,,,,> .IIF NB,, PUSH ARG .ENDR .IRP ARG,<,,,,,,,> .IIF NB,, FUNC ARG .ENDR .ENDM ...REV;FUNC,A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,AA,AB,AC,AD,AE,AF .MACRO .PUSH,ARG,XX PUSH'XX ARG ...=...+1 .ENDM .PUSH .MACRO .CALL,CNT,RTN .IF EQ %LOCATE(<@>,RTN) .IF_TRUE CALLS #CNT,RTN .IF_FALSE CALLS #CNT,G^RTN .ENDC .ENDM .CALL;CNT,RTN ...REV <.PUSH>,ARGUMENTS .MDELETE .PUSH .MDELETE ...REV .CALL \...,ROUTIN .NOSHOW MEB .MDELETE .CALL .ENDM CALL ;++ .SBTTL Macros to output information to the system console. ;-- .MACRO OUTPUT,MSGTEXT,?LBL .SAVE_PSECT LOCAL_BLOCK .PSECT EXEC$INIT_DATA_CONTRIB,5,PIC,CON,REL,LCL,NOSHR,EXE,RD,WRT .ALIGN LONG MSG'LBL:.ASCIC <13><10>"%TT_idle-mon, MSGTEXT"<7><13> .ALIGN LONG .RESTORE_PSECT .IF_32 > .IF_64 <$PUSHR64 > MOVL G^OPA$AR_UCB0,R5 .ON_AXP <.PRESERVE ATOMICITY> BICL2 #TT$M_NOBRDCST,- UCB$L_DEVDEPEND(R5) .ON_AXP <.NOPRESERVE ATOMICITY> MOVAB MSG'LBL,R2 MOVZBL (R2)+,R1 JSB G^IOC$BROADCAST .IF_32 > .IF_64 <$POPR64 > .ENDM OUTPUT .LIBRARY "SYS$LIBRARY:STARLET.MLB" ; look here for: $DSCDEF ; OpenVMS descriptor definitions $IODEF ; I/O function code definitions $SSDEF ; system status code definitions .LIBRARY "SYS$LIBRARY:LIB.MLB" ; look here for: $BOOSTATEDEF ; system bootstrap state definitions $DDTDEF ; driver dispatch table definitions $DPTDEF ; driver prologue table definitions $INIRTNDEF ; execlet initialization definitions $TTYUCBDEF ; terminal UCB extension definitions $TTYVECDEF ; terminal port/class vector definitions $UCBDEF ; unit control block definitions DECLARE_PSECT EXEC$INIT_CODE INITIALIZATION_ROUTINE INIT_ROUTINE INIT_ROUTINE: .ON_AXP <.CALL_ENTRY> .ON_AXP ; fetch LDRIMG block .ON_AXP ; fetch INIRTN flags BICL2 #INIRTN$M_NO_RECALL,(R5); recall initialization routine SAVIPL -(SP) ; preserve the current IPL PUSHL R4 ; preserve LDRIMG block address MOVL G^CTL$GL_PCB,R4 ; get the process's PCB address JSB G^SCH$IOLOCKR ; lock I/O database for read POPL R4 ; restore LDRIMG block address MOVAQ RT_TEMPLATE_DEV,R1 ; get descriptor address of RTA0 MOVAB DSC$S_DSCDEF1(R1),- ; fixup device name descriptor DSC$A_POINTER(R1) ; pointer to loaded address JSB G^IOC$SEARCHDEV ; Search for RTA0 BLBC R0,10$ MOVL UCB$L_DDT(R1),RT_TEMPLATE_DDT 10$: MOVL G^TTY$GL_DPT,R1 ; Get TTDRIVER DPT TSTL TTDRIVER_HOOKED ; was the TTDRIVER hooked? BNEQ 20$ ; yes! then skip over hook MOVL R1,TTDRIVER_HOOKED ; denote that we're hooking it OUTPUT .ON_VAX ; Offset to CLASS VECTOR .ON_VAX ; Address of CLASS VECTOR .ON_AXP ; Address of CLASS VECTOR MOVL CLASS_GETNXT(R1),ORIGINAL_GETNXT MOVL CLASS_PUTNXT(R1),ORIGINAL_PUTNXT MOVAB INTERCEPT_GETNXT,CLASS_GETNXT(R1) MOVAB INTERCEPT_PUTNXT,CLASS_PUTNXT(R1) OUTPUT ;++ ; Build a new FDT routine for RTTDRIVER. ;-- 20$: MOVL RT_TEMPLATE_DDT,R3 ; recover the RT DDT address BEQL 30$ ; didn't have one? skip this BISL2 #INIRTN$M_NO_RECALL,(R5); initialization routine done .IF NDF ALPHA .IF_TRUE ; on VAX ; _______________________ ; |____ valid I/O mask ___| RTFM: VAX/VMS Internals and Data ; |_______________________| Structures Version V5.0 ; |__ buffered I/O mask __| ; |_______________________| Layout of a Function Deci- ; |__ I/O function mask __| sion Table (FDT) ; |_______________________| Page: 583 Figure: 20.3 ; |___ Routine Address ___| ; |__ I/O function mask __| ; |_______________________| ; |___ Routine Address ___| ; |__ I/O function mask __| ; |_______________________| ; |___ Routine Address ___| ; = = ; |__ I/O function mask __| ; |_______________________| ; |___ Routine Address ___| MOVAB PATCHED_RT_FDT,R2 ; pointer to start of new FDT MOVL DDT$L_FDT(R3),R1 ; pointer to start of old FDT MOVQ (R1)+,(R2)+ ; copy the supported I/O mask MOVQ (R1)+,(R2)+ ; copy the buffered I/O mask MOVQ -<2*QUAD>(R1),(R2)+ ; copy supported mask into entry MOVAB RT_FDT_INTERCEPT,(R2)+ ; new FDT code address MOVZWL DDT$W_FDTSIZE(R3),R0 SUBL2 #<2*QUAD>,R0 ; calculate size of remaining FDT PUSHR #^m ; preserve regs munged by MOVC3 MOVC3 R0,(R1),(R2) ; copy remainder of FDT vector POPR #^m ; restore regs munged by MOVC3 MOVAL PATCHED_RT_FDT,DDT$L_FDT(R3) ; set new FDT vector adr ADDW2 #,DDT$W_FDTSIZE(R3) ; set new FDT vector size .IF_FALSE ; on Alpha ; _______________________ ; |__ buffered I/O mask __| ; |_______________________| ; |___ Routine Address ___|\ ; |___ Routine Address ___| \ 64 entries: one for each possible ; |___ Routine Address ___| I/O function code. Functions not ; = = / supported invoke: EXE$ILLIOFUNC. ; |___ Routine Address ___|/ ADDL3 #8,DDT$PS_FDT_2(R3),R1 ; get address of starting point MOVL <4*IO$_READVBLK>(R1),ORIGINAL_FDT_READ MOVAB INTERCEPT_FDT_READ,<4*IO$_READVBLK>(R1) MOVAB INTERCEPT_FDT_READ,<4*IO$_READLBLK>(R1) MOVAB INTERCEPT_FDT_READ,<4*IO$_READPBLK>(R1) MOVAB INTERCEPT_FDT_READ,<4*IO$_READPROMPT>(R1) MOVAB INTERCEPT_FDT_READ,<4*IO$_TTYREADALL>(R1) MOVAB INTERCEPT_FDT_READ,<4*IO$_TTYREADPALL>(R1) MOVL <4*IO$_WRITEVBLK>(R1),ORIGINAL_FDT_WRITE MOVAB INTERCEPT_FDT_WRITE,<4*IO$_WRITEVBLK>(R1) MOVAB INTERCEPT_FDT_WRITE,<4*IO$_WRITELBLK>(R1) MOVAB INTERCEPT_FDT_WRITE,<4*IO$_WRITEPBLK>(R1) MOVL <4*IO$_SETCHAR>(R1),ORIGINAL_FDT_SETMODE MOVAB INTERCEPT_FDT_SETMODE,<4*IO$_SETCHAR>(R1) MOVAB INTERCEPT_FDT_SETMODE,<4*IO$_SETMODE>(R1) MOVL <4*IO$_SENSECHAR>(R1),ORIGINAL_FDT_GETMODE MOVAB INTERCEPT_FDT_GETMODE,<4*IO$_SENSECHAR>(R1) MOVAB INTERCEPT_FDT_GETMODE,<4*IO$_SENSEMODE>(R1) .ENDC; NDF ALPHA OUTPUT 30$: PUSHL R4 ; preserve LDRIMG block address MOVL G^CTL$GL_PCB,R4 ; get the process's PCB address JSB G^SCH$IOUNLOCK ; unlock the I/O database POPL R4 ; restore LDRIMG block address SETIPL (SP)+,- ; restore the previous IPL ENVIRON=UNIPROCESSOR MOVL #SS$_NORMAL,R0 .ON_AXP RET .ON_VAX RSB DECLARE_PSECT EXEC$NONPAGED_CODE INTERCEPT_GETNXT: .ON_AXP <.JSB_ENTRY> BBC #TTY$V_PC_NOTIME,UCB$W_TT_PRTCTL(R5),10$ MOVL @#EXE$GL_ABSTIM,UCB$L_DUETIM(R5) 10$: JSB @ORIGINAL_GETNXT RSB INTERCEPT_PUTNXT: .ON_AXP <.JSB_ENTRY> BBC #TTY$V_PC_NOTIME,UCB$W_TT_PRTCTL(R5),10$ MOVL @#EXE$GL_ABSTIM,UCB$L_DUETIM(R5) 10$: JSB @ORIGINAL_PUTNXT RSB RT_FDT_INTERCEPT: .ON_AXP <.JSB_ENTRY> MOVL @#EXE$GL_ABSTIM,UCB$L_DUETIM(R5) RSB .IF DF ALPHA INTERCEPT_FDT_READ: $DRIVER_FDT_ENTRY FETCH=YES ; RT Read ULAR JSB RT_FDT_INTERCEPT CALL @ORIGINAL_FDT_READ,<,,,> RET INTERCEPT_FDT_WRITE: $DRIVER_FDT_ENTRY FETCH=YES ; RT Write ULAR JSB RT_FDT_INTERCEPT CALL @ORIGINAL_FDT_WRITE,<,,,> RET INTERCEPT_FDT_SETMODE: $DRIVER_FDT_ENTRY FETCH=YES ; RT Setmode ULAR JSB RT_FDT_INTERCEPT CALL @ORIGINAL_FDT_SETMODE,<,,,> RET INTERCEPT_FDT_GETMODE: $DRIVER_FDT_ENTRY FETCH=YES ; RT Setmode ULAR JSB RT_FDT_INTERCEPT CALL @ORIGINAL_FDT_GETMODE,<,,,> RET .ENDC; DF ALPHA DECLARE_PSECT EXEC$NONPAGED_DATA ORIGINAL_GETNXT: .LONG 0 ; original TTDRIVER GETNXT routine ORIGINAL_PUTNXT: .LONG 0 ; original TTDRIVER PUTNXT routine TTDRIVER_HOOKED: .LONG 0 ; state of the TTDRIVER intercept RT_TEMPLATE_DDT: .LONG 0 ; DDT address of TEMPLATE RT device .IF DF ALPHA ORIGINAL_FDT_READ: .LONG 0 ; original RT device read URAL ORIGINAL_FDT_WRITE: .LONG 0 ; original RT device write URAL ORIGINAL_FDT_SETMODE: .LONG 0 ; original RT device setmode URAL ORIGINAL_FDT_GETMODE: .LONG 0 ; original RT device sensemode URAL .ENDC; DF ALPHA RT_TEMPLATE_DEV: .ASCID /_RTA0:/; RT TEMPLATE device name string .ALIGN QUAD PATCHED_RT_FDT: .LONG 0[100] ; storage for patched RT FDT vector .END