	Notes on DL: drivers, RMD and Idle Terminal Monitors

			Edward J. Cetron
			Center for Biomedical Design
			3168 MEB, Univ. of Utah
			Salt Lake City, Utah  84112

			This article was first submitted
		sometime in Jan. of 1983.... It was lost
		in the shuffle of newsletter editors and
		that dry period of Multi-taskers.  I
		finally found it and have resubmitted
		it.  I will apologize in advance for the
		few instances where the material has
		become somewhat dated. - EJC

	I've been meaning to write this article for quite some time now,
but, as usual, I just never got the time to type up and organize some
of the interesting modifications I've made to me system.  Having 
just returned from the Fall '82 symposium, with all the comments I 
received about these modifications, I decided now was the time to finally
write the article.  (Does anyone know a good chiropractor -- my arm still
hurts.)
	



		DL: drivers and assorted features

	In an previous issue, some discussion was made about rumors of 
dual RL02 controllers not working under 11M V4.0.  Not having that problem, I
simply ignored it.  Unfortunately, we had to modify an 11/23 Q-bus system 
into an 11/23 Q-22 (yes, we know it voids the warranty -- but it is only
four wires, or so we thought).  Well, the modifications were made, the baseline
system was booted and sysgen completed.  The newly generated system would not 
boot - in fact it would run all over memory, and we could not even generate a
crash dump.
	
	We knew that the hardware worked since the baseline system ran
perfectly.  And the new system would boot and function properly on our 11/44
system.  After a great deal of anguish and frustration, we decided, like
all good systems people, to read the driver code.  It seems the baseline system
is, for compatibility reasons, an 18-bit system.  Therefore, the extra 4 bits 
(for Q-22 or 22-bit Unibus) are ignored and our system would work just fine.
But what happens when the new system, configured to be a 22-bit system tries 
to boot?

	We learned quite hastily that our RL02's were DMA devices.  That is to
say the when they wanted to transfer information to memory, they would 
'disable' the CPU and, ASSERTING ALL 22-BITS, write directly into memory.  But
our controllers only used a 16-bit address register -- where were the other 
bits?  It turns out that 2 additional bits are stored in the CSR of the drives.
The last four bits are stored by a hardware extension on Unibus machines called
the Unibus Map or Unibus Mapping Registers.  Since Q-22 systems don't have
a Unibus, Digital decided not to give them a Unibus Map (logical, for once).

	Instead, they designed a new RL02 controller with 5 device registers 
instead of the standard 4 and dedicated the fifth register for holding
those extra 4 bits.  Obviously, we didn't have the 5 register controller. 
And with the new transportablity over all CPU's of 11M V4.0, 11M expected
5 registers -- sort of.

	After reading the code, we realized how, in general terms, the drivers
decide which DMA technique to use:

	1.  22-bit system?
			no --- use old 18-bit DMA (and our baseline worked)
			yes -- continue

	2.  Q-22 or Unibus?
			try to access the fifth register; did it work?
				yes -- Q-22 so use fifth register for DMA
				no --- Unibus so ignore the high 4 bits and
					let the Unibus Map handle it.

	We now realized that this explained three related problems. First, in
our 11/23 system, the driver tried to find the fifth register, failed and then
tried to do Unibus DMA.  With no Unibus Map, the most significant 4 bits were
never set and our DMA transfers went, well... all over the place. Solution: we
obtained the RLV12, 5-register controller and all is well.
	
	The second problem that it explains is why our 11/44 system's error
logger keeps telling me that my controller has 5 registers -- it thinks its
on a Q-22 system.  Oh well.... I do understand however, that the patch is on
its way.  It also explains why 2 controllers on a Unibus system might not work.

	When the addresses of multiple controllers are selected, common
practice is to put the CSR's of the second controller immediately after those
of the first controller.  Well, remember how the driver checks to see if
it is on a Q-22 system?  Yes, it goes out to the first controller, counts out
where the fifth register would be, and lo and behold there is something there.
It matters not that this is the first register of the SECOND controller, the
driver know thinks it is running on a Q-22 system and things really get messed
up.  Solution: leave a blank address or four between multiple controllers.




		RMD on large memory systems (11M V4.0, V4.1,  11M+ V2.1)



	In the last issue of the Multi-Tasker, it was suggested to use $SYSIZ 
to modify the size of an RMD display.  This is an extremely dangerous procedure
and since some tasks and executive routines use this value your system will tend
to spontaneously crash quite often (and sometimes quite spectacularly).  Our
11/44 has 3.25 Megabytes of memory and the RMD display is quite crowded; if not
completely written over itself.  At the Center for Biomedical Design, I made 
a few patches to improve the readability of the RMD display:

		1. Treat VT102's, VT105's, and VT125's as 132 columm devices.
		2. Move the IN:, OUT: fields up to the SECPOOL area to prevent
			their being overwritten; this patch will have to be
			removed for M-plus compatibility.
			( I move them past SECPOOL for M-plus )
		3. Provide a command to allow dynamic sizing of the memory page.
		4. Include the patches provided in the last issue to use the
			I/O page when using 11M.

	The following SLP file will change all the appropriate routines.  It is
designed to be used with the command file which follows.  The general idea is 
to rename all the appropriate files from .MAC to .OLD (thus preserving the 
distribution kit for the inevitable DEC patches).  The .OLD files are then
modified into .MAC form by SLP, assembled and placed in the library (RMD.OLB) 
out of which RMD.TSK is produced.  These files are only templates and some
modification of device assignments and UIC's will be necessary depending on
your distribution kit.

	While I did attempt to comment the SLP files, more comments mean more 
typing in the .SLP files that can be mistyped and ruin the checksum checking.
Therefore, it is strongly recommended that you read the newly generated source
code -- it is well documented already. If you have any problems please let me 
know.  For those of you wondering, the following .SLP file can be entered as
one file or as multiple files.

(	NOTE:  With a tape drive on order, I will finally have in-house access
		to a tape drive.  I have removed the .SLP files from this 
		article and will instead submit all the .SLP files and a .TSK
		image for 11MV4.1, and 11M+ V2.1B on the SIG tape in Cincinnati.
		For those who can't wait, send me a blank tape and a return 
		mailer, postage if you can afford it would be appreciated.)



		Notes on the Idle Terminal Monitor

	In our location, the console terminal is always in use.  Even though its
use is restricted (only myself), we would still like to have it come under the 
purview of the Idle Terminal Monitor.  Somehow, BIGBRO (short for BIG BROTHER,
our name for the Monitor) must be able to selectively identify certain tasks as
what I call 'ghost' tasks.  This will enable BIGBRO to skip those tasks that
are normally running from TT0: as the console and allow logging off TT0:.
This feature is also needed since MCR... remains 'assigned' to the last terminal
that used it.  This could prevent the logoff of an idle terminal on an idle
system.
	In addition, I have added some code to set all non-logged in terminals
to a site-specific CLI (which may someday appear in these pages) which accepts
input from logged out terminals for WHO, RMD, HEL(LO), HELP, and a password
controlled ABO(RT).  Additional code has been added to reduce to non-privileged
any privileged terminal at the issuance of the first warning.  I don't have the
source for BIGBRO as originally written by Bruce Mitchell so I can't generate
a .SLP file.  Instead, I've included just my modifications with enough of the
existing code so that it can inserted at the correct place (sort of a 
CMP TI:=SY:USER.MAC, MULTI-TASKER HARDCOPY).

 	First, the changed sections of USER.MAC, each changed section is 
delimited by asterisks:




	.title	USERMN	User Terminal Monitor
	.IDENT	/X01.03/
; USERMN - User Terminal Activity Monitor for RSX-11M/M+
;
;
; Author:
;	Bruce R. Mitchell
;
;	Patterned after the POOL monitor task supplied by Digital
;		Equipment Corporation on RSX-11M-PLUS V1.0 Autopatch E.
;
;
; Source Site:
;	Engineering Systems and Technology Laboratory
;	3M Company, 3M Center, St. Paul, Minnesota  55144
;
; Revision History:
;
;	31-dec-81	First version written
;	3-jan-82	Command file generates Ascii strings for time
;	5-jan-82	In-house version released
;	9-jan-82	Decnet HT: support conditionally added
;	11-jan-82	Decus version released
;	20-jan-82	VT100 support conditionalized
;	27-feb-82	Warning messages cleared for active terminals
;	15-mar-82	Correct conditionlization for HT's
; ***************************************************************************
;	21-Jun-82	Modified to fit CBD's 11/44 system
;			First warning sets terminal no-priv 
;			Added software to log off TT0:
;				by using 'ghost' tasks
;			Added loop counter
;	25-aug-82	resets non-logged in terminals to the
;				non-logged in CLI (lgocli)
;

; ***************************************************************************
	.mcall	wtse$		; wait for single event flag
	.mcall	scli$		; set cli
;
; ***************************************************************************
	.page
	.sbttl Local Variables
;
;
;	Local variables
;
lopcnt:	.word	0		; loop counter
;
;
datbuf:	.blkw	8.		; Buffer area for date and time
; ***************************************************************************
;	spawn MCR to log out the terminal at address MCRTRM, setting
;		event flag SPNEFN on exit or status emmission
mcrspn:	spwn$	MCR...,,,,,spnefn,,,mcrbye,byelth,,TT
mcrbye:	.ascii	/bye/		; MCR command to logout terminal
byelth	= . - mcrbye		; length of command
	.even

setspn:	spwn$	MCR...,,,,,spnefn,,,mcrset,setlth,,TT
mcrset:	.ascii	\set /nopriv=ti:\	; MCR command to de-privilege terminal
setlth	= . - mcrset		; length of command
	.even

lgoset:	scli$	LGOCLI,TT,0
sleep:	stse$	efn2		; goto sleep and wait until next check time
spnwai:	wtse$	spnefn		; wait for spawn or timeout event flag
;
;
;
ghosts = 3			; number of tasks the are NOT considered active
ghstnm:	.rad50	/COT.../	; name of the first task to ignore 
	.rad50	/BIGBRO/	; ignore us
	.rad50	/MCR.../	; and let us forget this too!
;
;
; ***************************************************************************
;
warn1:	.ascii	<cr><lf><lf><lf>
	.ascii	/From BIG BROTHER:  First idle terminal warning!/<cr><lf><07>
	.ascii	/                    /
.if df v$t100			; if vt100 support
	.ascii	<esc><133><65><73><61><155>	; esc[5;1m (bold and blink)
.endc
	.even
	.word	time1		; remaining time
	.ascii	/ minutes/
.if df v$t100
	.ascii	<esc><133><60><155>	;esc[0m
.endc
	.ascii	/ before forced logout./
	.ascii	<cr><lf>
wrn1ln	= . - warn1;
;
;
	.even
warnp:	.ascii	/                   Terminal now non-privileged/<cr><lf><07>
	.ascii	<cr><lf><lf>
wrnpln	= . - warnp
	.even
; ***************************************************************************
;
	.even
banzai:	.ascii	<cr><lf><lf><lf>
.if df v$t100	
;		make a terrible looking display on the screen
	.ascii	<esc><133><61><73><61><110>	; esc[1;1H
	.ascii	<esc>/#9/			; esc#9
	.ascii	<esc>/[>3;11;0;14;132J/	; clear lines 11-14 inclusive
	.ascii	<esc><133><65><155>		; esc[5m
	.ascii	<esc>/[12;26H/			; move to row 12, col 26
.endc
	.ascii	/From BIG BROTHER:  BYE, BYE/<cr><lf>
.if df v$t100
	.ascii	<esc>/[13;26H/
.endc
	.ascii	/      -- Idle terminal logout/<cr><lf>
.if df v$t100
	.ascii	<esc><133><60><155>		; esc[0m
.endc
	.ascii	<cr><lf><lf><lf>
banzln	= . - banzai
;
; ***************************************************************************
;
;
;	switch to system state and check active task list
;
	call	$SWSTK,compar		; switch to system state
					;  and return at compar
	mov	$acthd,r0		;; r0 points to active task listhead
23$:	mov	#ghstnm,r3		;; get basis of ghost names
	mov	#ghosts,r1		;; get number of ghosts
	beq	30$			;; ignore if no ghosts
25$:	cmp	(r3)+,t.nam(r0)		;; is this task a ghost?
	beq	26$			;;  maybe, first three letters match
	inc	r3			;;  no, skip second word (three letters)
	inc	r3			;;  ( by two bytes)
	br	27$			;;  and then go to the next ghost
26$:	cmp	(r3)+,t.nam+2(r0)	;; do the second three letters match?
	beq	70$			;;  yes, so ignore it
27$:	sob	r1,25$			;; no, so try again...	
30$:	mov	t.ucb(r0),r3		;; r3 points to UCB for this task
	mov	u.dcb(r3),r1		;; r1 points to DCB for the UCB
; ***************************************************************************

;	set up pointers for next active task and check for list end

70$:	mov	t.actl(r0),r0		;; point to next active task
	tst	r0			;; is this the last task?
	bne	23$			;; no, so get more
; ***************************************************************************
	
.if ndf rs.nsl
45$:	bis	#tm.log,trmdat(r2)	;; set logged-in flag

.iff
45$:	tst	r4			;; TT: or HT:
	bne	50$			;; if an HT:, go to it
	bis	#tm.log,trmdat(r2)	;; set flag for logged-in TT:
	br	55$			;; go for next unit
50$:	bis	#tm.log,netdat(r2)	;; set flag for logged-in HT:
.endc

55$:	bit	#u2.prv,u.cw2(r1)	;; is this unit priv'ed
	beq	60$			;; no, look at next unit

.if ndf rs.nsl
	bis	#tm.prv,trmdat(r2)	;; set priv'ed flag
.iff
	tst	r4			;; TT: or HT:
	bne	555$			;; if an HT:, go to it
	bis	#tm.prv,trmdat(r2)	;; set flag for priv'ed TT:
	br	60$			;; go for next unit
555$:	bis	#tm.prv,netdat(r2)	;; set flag for priv'ed HT:
.endc

60$:	add	#4,r2			;; r2 points at next terminal flag word
	inc	r5
	add	d.ucbl(r0),r1		;; r1 points at next UCB on DCB
	sob	r3,40$			;; loop for each UCB on DCB
; ***************************************************************************
compar:	mov	#<itt*4>,r0		; r0 counts down terminal data blocks
	mov	#itt,r5			; r5 counts down terminal number
10$:	bit	#tm.log,trmdat(r0)	; is this terminal logged-in?
	bne	20$			; if so, skip and process it
	mov	#"TT,lgoset+s.cidv	; set SCLI$ DPB to TT's
	mov	r5,lgoset+s.ciun	; set SCLI$ DPB unit
	dir$	#lgoset			; set not logged in terminal to lgocli
	clr	trmdat+2(r0)		; not logged-in, clear idle counter
	br	40$			; and set up for next data block

;	terminal logged in; check for active task

; ***************************************************************************
	mov	#iht,r5
50$:	bit	#tm.log,netdat(r2)	; is this HT logged-in?
	bne	60$			; if so, skip and process it
	mov	#"HT,lgoset+s.cidv	; set SCLI$ DPB to HT's
	mov	r5,lgoset+s.ciun	; set SCLI$ DPB unit
	dir$	#lgoset			; set not logged in terminal to lgocli
	clr	netdat+2(r0)		; not logged-in, clear idle counter
	br	80$			; and set up for next data block

;	HT logged in; check for active task

; ***************************************************************************
.if df rs.nsl
 	clr	r3			; assume terminal type is TT:
.endc

	mov	#"TT,asslun+a.luna	; set device to TT for alun$
	mov	#"TT,mcrspn+s.pwdn	; set device to TT for spwn$
	mov	#"TT,lgodev		; set device to TT for console message
10$:	tst	trmdat+2(r2)		; is this an idle terminal?
	beq	60$			; yes, set up for next terminal

; ***************************************************************************
70$:	clr	r1			; r1 is HT: number
	clr	r2			; r2 is offset in HT: data block
 	mov	#1,r3			; assume HT: type is HT:
	mov	#"HT,asslun+a.luna	; set device to HT for alun$
	mov	#"HT,mcrspn+s.pwdn	; set device to HT for spwn$
	mov	#"HT,lgodev		; set device to HT for console message
80$:	tst	netdat+2(r2)		; is this an idle HT: terminal?
	beq	130$			; yes, set up for next HT:

; ***************************************************************************

;	all terminals processed, back to sleep

140$:	dir$	#timdpb			; set wake-up call
	inc	lopcnt			; say we finished another iteration
	mov	lopcnt,r0		;
	dir$	#sleep			; and go to sleep
	jmp	tsks			; rise and shine and do it all again
; ***************************************************************************

	.sbttl	warone issue first warning
;
;	warone - issue first warning and de-privilege the terminal
;
;	inputs:	r1 - target terminal number
;		r2 - data block offset
;		r3 - 0 -> TT:,   1 -> HT:
;
;	outputs: terminal flag word is updated
;
;	registers are not save or restored
;
.if df rs.nsl
warone:	tst	r3			; is this an HT:?
	beq	5$			; a TT:
	bit	#tm.1st,netdat(r2)	; an HT:, has first message been sent?
	beq	10$			; no, so send it 
	return				; yes, so don't bother
5$:	bit	#tm.1st,trmdat(r2)	; a TT:, has first message been sent?
.iff
warone:	bit	#tm.1st,trmdat(r2)	; has the first message been sent?
.endc

	beq	10$			; no, so issue it
	return				; yes, don't do it again
10$:	mov	r1,asslun+a.lunu	; load terminal number in alun$ DPB
	dir$	#asslun			; assign lun 2 to target terminal
	bcc	20$			; if it succeeded, issue message
	return				; if failed, punt
20$:	mov	#warn1,brodpb+q.iopl	; load message address into qio DPB
	mov	#wrn1ln,brodpb+q.iopl+2	; load message length into qio DPB
	dir$	#brodpb			; send out message

.if df rs.nsl
	tst	r3			; is this a TT:, or an HT:
	beq	25$			; TT:, so go to TT: code
	bis	#tm.1st,netdat(r2)	; HT:, set first message sent flag
	bit	#tm.prv,netdat(r2)	; was HT: priv'ed
	beq	40$			; no, so leave
	br	30$			; yes, rejoin common code
.endc

25$:	bis	#tm.1st,trmdat(r2)	; TT:, set first message sent flag
	bit	#tm.prv,trmdat(r2)	; TT:, was TT: priv'ed
	beq	40$			; no, so go home	
30$:	mov	r1,setspn+s.pwvt	; load terminal number into spwn$ DPB
	dir$	#setspn			; de-privilege terminal
	bcc	35$			; if ok, good
	return				; if not, punt
35$:	dir$	#spnwai			; wait for spawn to complete
	mov	#warnp,brodpb+q.iopl	; load message address into qio DPB
	mov	#wrnpln,brodpb+q.iopl+2	; load message length into qio DPB
	dir$	#brodpb			; send out message
40$:	return				; and go home
; ***************************************************************************
	


	And now the sections from USERPRE0.MAC (in the same format):



;
; USERPRE - User Terminal Activity Monitor prefix file
;
;	Companion source file to USER.MAC
;
; Author:
;	Bruce R. Mitchell
;
;	Patterned after the POOL monitor task supplied by Digital
;		Equipment Corporation on RSX-11M-PLUS V1.0 Autopatch E.
;
;
; Source Site:
;	Engineering Systems and Technology Laboratory
;	3M Company, 3M Center, St. Paul, Minnesota  55144
;
; Revision History:
;
;	1-Jan-82	Source ripped out of SLPRE.MAC
;	2-Jan-82	Warning message bit definitions added
;	21-Jun-82	Modified to fit CBD's 11/44 system
;			Added software to log off TT0:
; ************************************************************************
;	Bit masks for terminal and task characteristics
;
tm.log	=	1		; terminal logged in
tm.tsk	=	2		; task active on terminal
tm.mcr	=	4		; terminal CLI is MCR (not used)
tm.1st	=	10		; first warning message sent 
tm.2nd	=	20		; second warning message sent and demoted to
				;  non-privileged status
tm.3rd	=	40		; final warning message sent
tm.prv	=	100		; terminal is privileged
; ************************************************************************




	These corrections should work.  For those who don't like to type (like
me) these changes will be on the next SIG symposia tape as I mentioned above.
If time permits, I will document up our logged-out terminal monitor and include 
it also. Maybe even a CLI that enables non-privileged users to RUN programs as
a privileged user...... 


