	.Title	Install-Idle-Monitor
;
;	This loads code into system space and patches into the
;	terminal port/class interface to update UCB$L_ABSTIM whenever
;	a character is sent or received. This allows us to keep
;	track of 'idletime' on non-TIMED devices.
;

	.library /SYS$LIBRARY:LIB/
	$CXBDEF
	$DDTDEF
	$DPTDEF
	$DYNDEF
	$TTYUCBDEF
	$TTYVECDEF
	$UCBDEF

	.Entry	Install_Idle_Monitor,^m<>
	$CMKRNL_S   $$Install_Idle_Monitor
	Ret


	.Entry	$$Install_Idle_Monitor,^m<r2,r3,r4,r5,r6,r7>

	;
	;   See if we have an RTA0 device installed.
	;

	Clrl	R7			; Assume no RTDRIVER DDT to patch
	Jsb	G^Sch$IOLockR		; Lock the I/O database

	MovAQ	RT_DEVICE,R1
	Jsb	G^IOC$SearchDev		; Search for RTA0
	Blbc	R0,1$
	Movl	UCB$L_DDT(R1),R7
1$:

;
;	Allocate a buffer to hold the code the be loaded into
;	nonpaged pool
;

	MovL	#CodeLen+12,R1		; Skip 12 bytes for pool header
	TstL	R7
	BEql	2$
	AddW2	DDT$W_FDTSIZE(R7),R1	; Room for old FDT
	AddW2	#3*4,R1			; Room for the new FDT entry
2$:

	Jsb	G^Exe$AllocBuf
	Blbs	R0,10$
	Pushl	R0
	Brb	Done
10$:

;
;	Copy the code into the pool
;

	MovAB	12(R2),R6		    ; Address of start of code
	MovC3	#CodeLen,W^Code,(R6)	    ; Copy code into pool

;
;	Link the code into the class interface to TTDRIVER.
;

	MovL	G^TTY$GL_DPT,R1		    ; Get TTDRIVER DPT
	MovZWL	DPT$W_VECTOR(R1),R0	    ; Offset to CLASS VECTOR
	AddL2	R0,R1			    ; Address of CLASS VECTOR

	MovL	CLASS_GETNXT(R1),B^V1_Jump-Code(R6)
	MovL	CLASS_PUTNXT(R1),B^V2_Jump-Code(R6)
	MovAB	B^V1-Code(R6),CLASS_GETNXT(R1)
	MovAB	B^V2-Code(R6),CLASS_PUTNXT(R1)

;
;	Build a new FDT routine for RTTDRIVER.
;
	Tstl	R7
	Beql	20$
	Addl3	S^#Patched_RT_FDT-Code,R6,R0; Pointer to start of new FDT
	Movl	DDT$L_FDT(R7),R1	    ; Pointer to start of old FDT
	MovQ	(R1)+,(R0)+		    ; Copy the supported I/O mask
	MovQ	(R1)+,(R0)+		    ; Copy the buffered I/O mask
	MovQ	-16(R1),(R0)+		    ; Copy the supported into the new entry
	MovAB	B^RTT_Fix-Code(R6),(R0)+    ; New FDT code address
	MovZWL	DDT$W_FDTSIZE(R7),R2
	SubL2	#16,R2			    ; Calculate size of remaining FDT
	MovC3	R2,(R1),(R0)		    ; Move it
	MovAL	B^Patched_RT_FDT-Code(R6),DDT$L_FDT(R7)
	AddW2	#12,DDT$W_FDTSIZE(R7)	    ; Update the pointers to the new FDT
20$:
;
;	Exit
;
	Pushl	#SS$_NORMAL
Done:	Movl	G^CTL$GL_PCB,R4
	Jsb	G^SCH$IoUnLock
	PopL	R0
	Ret


RT_DEVICE:
	.Ascid	/_RTA0:/

;
;   This code sits in between the port/class interface for each
;   terminal and updates the "DUETIM" field when each I/O occurs
;   It *Must* be PIC.
;
Code:
V1:	BBC	#TTY$V_PC_NOTIME,UCB$W_TT_PRTCTL(R5),10$
	MovL	@#EXE$GL_ABSTIM,UCB$L_DUETIM(R5)
10$:	Jmp	@I^#00000000
V1_Jump = .-4


V2:	BBC	#TTY$V_PC_NOTIME,UCB$W_TT_PRTCTL(R5),10$
	MovL	@#EXE$GL_ABSTIM,UCB$L_DUETIM(R5)
10$:	Jmp	@I^#00000000
V2_Jump = .-4

Rtt_Fix:MovL	@#EXE$GL_ABSTIM,UCB$L_DUETIM(R5)
	Rsb

CodeLen = .-Code

Patched_RT_FDT:

	.End	Install_Idle_Monitor
