Google
 

Trailing-Edge - PDP-10 Archives - BB-F493Z-DD_1986 - 10,7/703mon/uuocon.mac
Click 10,7/703mon/uuocon.mac to see without markup as text/plain
There are 16 other files named uuocon.mac in the archive. Click here to see a list.
TITLE 	UUOCON - UUO HANDLER AND UUO+IO ROUTINES - V1736
SUBTTL /CHW/TL/RCC/CMF/PH/GDR/DAL/EVS/TW/JMF/DRT/JBS/RCB	 21 JAN 86
	SEARCH	F,S
IFN FTKL10,<
	SEARCH	ICHPRM		;FOR DIAG. UUO
>; END IFN FTKL10
	$RELOC
	$HIGH

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
.CPYRT<1973,1986>
;COPYRIGHT (C) 1973,1974,1975,1976,1977,1978,1979,1980,1982,1984,1986
;BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
;ALL RIGHTS RESERVED.


;

XP VUUOCN,1736
		;THIS MACRO PUTS VERSION NO. IN STORAGE MAP AND GLOB

UUOCON::ENTRY	UUOCON		;ALWAYS LOAD UUOCON(IF LIB SEARCH)

IFNDEF MAXCAL,<XP MAXCAL,56>
			;DEFINE HIGHEST CALLI UUO WHICH HAS
			; CORRESPONDING CALL UUO
;               TABLE OF CONTENTS FOR UUOCON
;
;
;                        SECTION                                   PAGE
;    1. UUO DISPATCH ROUTINE......................................   2
;    2. CALL & CALLI UUO'S........................................   7
;    3. EXIT & SETPOV UUO'S.......................................  19
;    4. RESET & APRENB UUO'S......................................  20
;    5. MISC. ACCOUNTING UUOS (JOBNO,JOBTIM,DATE & MSTIME)........  24
;    6. SLEEP SERVICE FOR SLEEP UUO, DTA, MTA AND SCNSER..........  26
;    7. PEEK UUO..................................................  27
;    8. POKE. UUO.................................................  28
;    9. PERF. MUUO................................................  31
;   10. CALLS TO SEGCON FOR SETUWP AND REMAP......................  35
;   11. TRIVIAL UUOS (LIGHTS, TIMER AND SWITCH)...................  36
;   12. DVPHY. UUO................................................  37
;   13. DEVCHR AND DEVSIZ UUO'S...................................  39
;   14. GETPPN AND DEVPPN UUO'S (ALSO RTZER)......................  45
;   15. IONDX.  UUO...............................................  46
;   16. SUBROUTINE TO FIND A DDB GIVEN ITS IO INDEX...............  48
;   17. GTNTN./GTXTN. UUO'S FOR TTY NAMES.........................  50
;   18. MVBFH. UUO
;        18.1   MOVE BUFFER HEADERS...............................  52
;   19. DEVSTS, DEVLNM, DEVRST, AND DEVURS UUO'S..................  53
;   20. SETDDT, WAIT AND GETLIN CALLI'S ; WAIT2 AND GETPPL........  56
;   21. ACCT. UUO - ACCOUNTING UUO................................  59
;   22. LOGIN, LOGOUT AND ATTACH UUO'S............................  61
;   23. GETTAB UUO................................................  67
;   24. SETNAM & CNGPPN UUO'S.....................................  73
;   25. DEVNAM UUO................................................  74
;   26. REAL-TIME AND HIBWAKE FEATURE.............................  75
;   27. DAEMON UUO'S AND ROUTINES.................................  84
;   28. ALLOC. UUO................................................  91
;   29. DEVOP. UUO................................................  95
;   30. FILOP. UUO................................................  97
;   31. PERF. UUO................................................. 109
;   32. CLOSE UUO................................................. 110
;   33. INBUF & OUTBUF UUO'S...................................... 114
;   34. OPEN & INIT UUO'S......................................... 115
;   35. COMMON PART OF LOOKUP AND ENTER........................... 121
;   36. COMMON PART OF RENAME, USETI/O, UGETF AND UTPCLR.......... 123
;   37. COMMON PART OF INPUT AND OUTPUT UUO'S..................... 124
;   38. RELEASE UUO............................................... 140
;   39. STATUS SETTING AND GETTING UUO'S.......................... 142
;   40. ROUTINES TO ADVANCE BUFFERS............................... 144
;   41. DUMP MODE COMMAND LIST PROCESSING ROUTINES................ 152
;   42. DDB SCAN LOGIC............................................ 156
;   43. BUFFER RING BUILDER & CLEARER............................. 178
;   44. RANDOM SUBROUTINES FOR I/O................................ 182
;THE CALL UUO ROUTINES AND THE IO UUO ROUTINES
;SOME UUO DO DISPATCH TO OTHER ROUTINES OUTSIDE OF UUOCON
;SYSTEM UUOS(40-77) FIRST SAVE THE USERS ACS IN RELATIVE LOC 0-17
;THEN THE FOLLOWING ACS ARE LOADED UP BEFORE DISPATCHING:
;	P	;PUSHDOWN LIST IN CURRENT JOB DATA AREA
;	M	;THE CONTENTS OF LOC 40
		; EXCEPT THAT ON A CALL OR CALLI UUO, THE ADDRESS IS
		; MODIFIED TO BE THE AC OF THE UUO,FOR
		; PICKING UP ARGUMENTS.
;	F	;ADR. OF DEVICE DATA BLOCK
;	S	;DEVICE IO STATUS WORD
;	T1	;(CALLI) CONTENTS OF AC
;	T4	;ADR. OF DEVICE SERVICE ROUT. DISPATCH TABLE
;	P1	;THE USER IO CHANNEL(AC FIELD) OF UUO
		;LH BIT 0=1 (PHONLY) IF ONLY PHYSICAL DEVICE WANTED
		; IE NO LOGICAL NAME SEARCH

;RETURN IS PUSHED ON END OF PD LIST
;THEN IF CALL WAS FROM USER MODE, THE UUO ROUTINE IS CALLED
;WITH A PUSHJ, SO THAT ALL UUO ROUTINE RETURN WITH A POPJ P,
;WHICH WILL RETURN CONTROL TO UUOCON WHICH WILL RESTORE USERS
;ACS AND RETURN TO HIM
;IF THE CALL IS FROM EXEC MODE, THE UUO ROUTINE IS CALLED
;BY DOING JUST A JRST,  WHEN THE UUO ROUTINE RETURNS WITH
;A POPJ, IT WILL RETURN TO THE EXEC WITHOUT RESTORING
;ANY ACS
; CONTROL MAY ALWAYS BE RETURNED BY EXECUTING A
;	POPJ P,
; WHICH WILL RESTORE THE ACS, APR BITS, AND RETURN.
; THE UUO HANDLER IS PURE IF THE FOLLOWING RESTRICTIONS ARE OBSERVED.
; RESTRICTIONS: UUOS CANNOT BE CALLED BY INTERRUPT SERVICE ROUTINES.

;ALL UUO'S SHOULD PRESERVE THE PRESERVED AC'S P1-P4
	SUBTTL	UUO DISPATCH ROUTINE

;HERE FROM COMMON
UUOSY1::HRLZ	M,.USMUO	;UUO OP CODE
	IOR	M,.USMUE	;RESULTS OF THE EFFECTIVE ADDRESS CALCULATION
	MOVE	J,.CPJOB##	;SET UP J IN CASE UUOERR
				; (GIVRES EXPECTS J SET UP)
	TLNN	M,740000	;SYSTEM UUO?
	JRST	UUOERR##	;NO, 0-37 ARE ILLEGAL, PRINT ERROR
	MOVE	T1,.USMUO	;MUUO FLAGS
	TLNE	T1,(XC.USR)	;DON'T PUSH FLAGS IF EXEC MODE UUO
	PUSH	P,.USMUO	;PUSH FLAGS
	PUSH	P,.USMUP	;SAVE RETURN ON PUSH DOWN LIST
	PUSHJ	P,FNDPDS##	;FIND JOB'S PDB
	AOS	.PDUUC##(W)	;COUNT THE UUO
	LDB	T2,[POINT 9,M,8];PICK UP UUO OP CODE
	CAIL	T2,100		;ILLEGAL INSTRUCTION?
	JRST	ILLINS##	;YES, STOP JOB AND PRINT ERROR
	LDB	P1,PUUOAC##	;SETUP USER DEVICE CHANNEL NUMBER
	HRRZ	T3,USRHCU##
	SKIPE	F,USRJDA##(P1)	;GET ADDRESS OF DEVICE DATA BLOCK
	CAMLE	P1,T3
	JRST	NOCHAN		;CHANNEL NOT ASSIGNED
	HRLM	P1,.USCTA	;STORE CHANNEL NUMBER
DISP3:	MOVE	S,DEVIOS(F)
	MOVE	T4,DEVSER(F)	;SETUP IO SERVICE DISPATCH
				; TABLE ADDRESS
	CAIL	T2,LNGUUO	;LONG DISPATCH TABLE UUO?
	JRST	DISP1		;YES
DISP0:	ROT	T2,-1		;DIVIDE UUO OPCODE BY 2, SAVE REMAINDER
	MOVE	U,UUOTAB-20(T2)	;GET DISPATCH TABLE ENTRY
	MOVE	T1,M		;ADR INTO T1 FOR UUOCHK
	MOVE	T3,CHKTAB-20(T2);GET CHECK-BITS FOR THE UUO
DISP2:	JUMPL	T2,DISP2A	;WAS UUO ODD?
	MOVS	U,U		;NO, USE LH OF DISPATCH ENTRY
	MOVSS	T3
DISP2A:
IFN FTMP,<
	TRNN	T3,UU.CP1	;CAN UUO BE EXECUTED ON ANY CPU
	PUSHJ	P,ONCPU0##	;NO, GET ONTO BOOTSTRAP CPU
>
IFN FTXMON,<
	TRNE	M,^-17		;ONLY IF A REAL EFFECTIVE ADDRESS
	TRNN	T3,UU.PCS	;DOES UUO DO ITS OWN SECTION ADJUSTMENTS?
	JRST	DISP4		;YES, DON'T CHEAT IT
	PUSH	P,T1		;NO, SAVE T1
	LDB	T1,[POINT SECWID,M,SECPOS] ;GET SECTION TO BE USED
	PUSHJ	P,STPCS##	;SET IT UP AS PCS
	DPB	T1,[POINT SECWID,.USUPF,SECPOS] ;SAVE AS UUO PCS (FOR CONTEXT SWITCHING)
	POP	P,T1		;RESTORE AC CONTENTS
DISP4:
> ;END OF IFN FTXMON
	TRNE	T3,UU.MSK	;CHECK ARGUMENTS FOR VALIDITY?
	PUSHJ	P,UUOCHK##	;YES (DONT ALLOW PAGE FAULT IN UUO PROCESSING)
IFN FTXMON,<
	HRLI	U,(MCSEC1)	;ASSUME UUO CAN BE EXECUTED IN SECTION 1
	TRNE	T3,UU.SE1	;CAN UUO BE EXECUTED IN SECTION 1?
	XJRST	[MCSEC1+.+1]	;YES, GET INTO SECTION 1
> ;END IFN FTXMON
	MOVE	T2,.USMUO	;UUO FROM SYSTEM?
	TLNN	T2,(XC.USR)
	JRST	(U)		;YES
IFN FTPI,<
	PUSHJ	P,ANYUUO##	;CALL PSISER SINCE THIS IS A FUNNY
				; CONDITION
;***NOTE: THIS ROUTINE SKIPS TO ABORT THE UUO. IT MUST BE PRIOR TO THE
; PUSHJ P,(U) SO IT WILL SKIP INTO UUOXIT
>

;DISPATCH TO UUO ROUTINE
;THE FOLLOWING CODE IS EXECUTED ON ALL RETURN TO USER PROGRAMS
;BUT IS NEVER EXECUTED ON RETURNS FROM EXEC UUOS(SAVGET)

	PUSHJ	P,(U)		;NO, FROM USER. ALL
				; UUO ROUTINES RETURN WITH POPJ
	  JRST	USRXIT		;NO SKIP RETURN TO USER
USRXT1:	PUSHJ	P,INCPD1##
USRXIT::XJRST	[0+.+1]		;DO THE REST OF THIS IN SECTION 0

IFN FTNET,<NTDBUG NO,EITHER>	;MUST NOT HAVE THE INTERLOCK.  ANY LEVEL OK.
	JUMPE	F,UUOND1	;NO DDB
	HRRZ	T1,DEVSER(F)	;GET DISPATCH TABLE ADDRESS
IFN FTNET,<
	CAIN	T1,NETDSP##	;IS IT A NETWORK DEVICE?
	JRST	[PUSHJ	P,ZAPNET##	;YES, DISCONNECT IF NO LONGER NEEDED
		JRST	UUOND1]		;RETURN TO USER IN EITHER CASE
> ;END IFN FTNET
	CAIN	T1,SCNDSP##	;IS IT A TTY DDB?
	PUSHJ	P,TTYKLQ##	;YES, GIVE IT UP IF NOT IN USE
UUOND1:	MOVSI	T1,37		;GET MASK OF IR+IND FIELDS
	IORM	T1,.USMUO	;OR INTO 40 SO UUO WATCHERS SEE IT
IFN FTMPFH,<
	SETZM	.USPFU		;CLEAR COUNT OF PAGE FAULTS IN THIS UUO
>
	MOVE	J,.CPJOB##	;CURRENT JOB NUMBER
IFN FTMP,<
	PUSHJ	P,UXITMP##	;CHECK IF JOB IS RUNNABLE ON THIS CPU
	  JRST	[MOVE T1,JBTSTS##(J) ;NO, GO DO A RESCHEDULE
		 JRST USRXT2]
>
	MOVE	T1,JBTSTS##(J)	;JOB STATUS WORD
	TDNN	T1,[XWD STOPIO!CNTRLC,JS.DEP!JS.MPE]	;IS MONITOR TRYING TO STOP THIS
				; USERS IO OR IS HE TRYING TO STOP HIS JOB
				; (BY TYPING ^C WHILE HE WAS IN MONITOR)?
				; OR HAD ERROR AND IS IN DAEMON ERROR PAUSE?
				; OR MEM PAR ERR (WHILE IN MONITOR BUT BAD ADR
				; PROVED TO BE IN USER MODE)
	SKIPE	.CPTMF##	;NO. HAS CLOCK TICKED WHILE IN MONITOR?
	JRST	USRXT2		;YES, GO CALL SCHEDULER
	CAME	J,FORCEF##	;TRYING TO SWAP THIS JOB
	SKIPE	SCDRTF##	;NO, SHOULD WE DO A HIGH PRIORITY RESCHEDULE
;------ NOTE - 'UUODON' MUST LABEL THE PC STORED BY THIS PUSHJ
;USED FOR CONTROL C INTERCEPT TO DETECT USER STOPPED ON THIS CALL TO SCHED
USRXT2:	PUSHJ	P,USCHD1##	;YES, GO CALL SCHEDULER
UUODON::			; SAVE CURRENT JOB NO (J)
;----------------		; NOTE: USCHD1 POPS PUSHJ PC INTO JOBPC
				; WHEN RESCHEDULING JOB
;HERE TO RETURN TO USER - CHECK IF USER TRAP PENDING

USRRET::
IFN FTKL10,<
	MOVEI	T1,JS.ABP	;EXEC MODE ADDRESS BREAK BIT
	TDNE	T1,JBTST2##(J)	;DID ONE OCCUR DURING THIS UUO?
	PUSHJ	P,EXCABK##	;YES, GO PROCESS IT
>
IFN FTPI,<
	XCT	PINOJN##	;SKIP IF CANNOT GRANT INTERRUPTS
	PUSHJ	P,PSIGEN##	;CAN, GIVE ANY TO THE USER
> ;END FTPI
	MOVE	T1,JBTSTS##(J)	;STATUS WORD FOR CURRENT USER
				; ON THIS CPU
	TRNN	T1,UTRP		;SEE IF TRAP PENDING
	JRST	USRXNT		;NO--PROCEED BELOW
;HERE WHEN TRAP SET UP WHILE JOB WAS DOING A UUO.
;TYPE OF TRAP IS IN .JBFDV:
;	-1 IF .JBINT TRAP (E.G., ^C)
;	0,,ADDR	IF START AT ADDR (E.G., .DDT)

	MOVE	T2,(P)		;GET RETURN PC
	SKIPGE	T4,.JDAT+JOBFDV##	;GET NEW PC
	JRST	USRXJI		;NO--GO DO .JBINT

	MOVEM	T2,.JDAT+JOBOPC##	;STORE INTERRUPTED PC
	HRRM	T4,(P)		;STORE NEW PC
	JRST	USRXCT		;AND GO FINISH INTERRUPT
USRXJI:	MOVEI	T4,0		;CLEAR BITS
	PUSHJ	P,CHKINT##	;SEE IF INT BLOCK OK
	  JRST	USRXCT		;NO--JUST CLEAR TRAP
	PUSHJ	P,DOINT##	;YES--SWITCH PC


USRXCT:	MOVEI	T1,UTRP		;CLEAR
	ANDCAB	T1,JBTSTS##(J)	;  TRAP FLAG
;HERE TO RESTORE USER HARDWARE STATE AND JUMP TO USER
USRXNT:	PUSHJ	P,ZAPEPL##	;RESET EXTENDED PDL IF ANY USED
	JRST	UMPRET##	;RETURN TO COMMON FOR UUO EXIT
NOCHAN:	SKIPL	USRHCU##	;SAVE/SET IN PROGRESS?
	CAMG	P1,USRHCU##	;NO, MAKE SURE LEGAL CHANNEL
	SKIPA			;DON'T ZERO F - IT POINTS TO A DDB
	MOVEI	F,0		;INDICATE NO DDB
	MOVSI	T3,(XC.USR)
	CAIE	T2,70		;YES,IS IT CLOSE OR RELEASE?
	CAIN	T2,71		;CLOSE AND RELEASE ALWAYS LEGAL
				; EVEN THOUGH NO DEVICE ASSIGNED
	JRST	NOOP		;YES, DO NO-OP FOR EXEC OR USER
	TDNE	T3,.USMUO	;UUO FROM USER?
				;IF FROM EXEC, PROBABLY SAVGET
				; WHICH SETS USRCHN NEG. IN LH
	CAIGE	T2,IOUUO	;YES, IS THIS AN IO UUO?
	JRST	DISP3		;NO, GO DISPATCH
	JRST	IOIERR##	;NO, PRINT IO TO UNASSIGNED CHANNEL
				; AND STOP JOB

NOOP:	TDNE	T3,.USMUO	;YES,IS UUO FROM USER?
	JRST	USRXIT		;YES, RETURN TO HIM (RESTORE ACS)
	POPJ	P,		;NO, RETURN TO EXEC (DO NOT RESTORE ACS)
DISP1:	MOVE	T1,DEVMOD(F)	;LONG DISPATCH TABLE UUO
IFN FTSPL,<
	SKIPL	DEVSPL(F)	;LONG DISPATCH TABLE IF SPOOLED
>
	TLNE	T1,DVLNG	;DOES THIS DEVICE HAVE A LONG
				; DISPATCH TABLE?
	JRST	DISP0		;YES, DISPATCH
	CAIGE	T2,76		;NO, IS UUO LOOKUP OR ENTER?
	JRST	USRXIT		;NO, RETURN TO USER
	HRRI	T1,DVIN		;YES, TEST IF DEVICE LEGAL
	CAIN	T2,77		;LOOKUP?
	HRRI	T1,DVOUT	;NO, TEST FOR OUTPUT DEVICE (ENTER)
	TLNE	T1,(T1)		;IF LOOKUP, TEST FOR INPUT DEVICE (DVIN)
	JRST	USRXT1		;DEVICE AND FUNCTION AGREE, SKIP RETURN
	PUSHJ	P,GETWD1##	;NOT AGREE, GET E+1
	HRRI	T1,0		;ERROR CODE 0, FILE-NOT-FOUND SHOULD NOT MESS UP UPDATES
	PUSHJ	P,PUTWDU##	;PUT BACK IN E+1
	JRST	USRXIT		;AN NON SKIP RETURN TO USER
;TABLE OF UUO DISPATCH ADDRESSES
;IN FORMAT:
;	XWD 40,41
;	XWD 42,43
;	.
;	XWD 76,77



UUOTAB:	UCALL,,UINIT		;(40,41)CALL,INIT
	UUOERR##,,UUOERR##	;(42,43)FIVE UUOS FOR EACH INSTALLATION
	UUOERR##,,UUOERR##	;(44,45)TO DEFINE AS THEY SEE FIT
	UUOERR##,,UCALLI	;(46,47),CALLI
	UOPEN,,TTYUUO##		;(50,51)OPEN, TTCALL
	UUOERR##,,UUOERR##	;(52,53)
	UUOERR##,,URENAM	;(54,55),RENAME
XP IOUUO,55			;LOWEST IO UUO(RENAME)
	TIN,,TOUT		;(56,57)IN,OUT
	SETIOS,,USTATO		;(60,61)SETSTS,STATO
	USTATS,,USTATZ		;(62,63)GETSTS,STATZ
	UINBF,,UOUTBF		;(64,65)INBUF,OUTBUF
	UIN,,UOUT		;(66,67)INPUT,OUTPUT
	CLOSE1,,URELEA		;(70,71)CLOSE,RELEASE
XP LNGUUO,72			;LOWEST LONG DISPATCH TABLE UUO
	UMTAPE,,UDGF		;(72,73)MTAPE,GETF
	UDSI,,UDSO		;(74,75)USETI,USETO
	UDLK,,UDEN		;(76,77)LOOKUP,ENTER

;UUOS 42, 43, 44, 45, AND 46 ARE FOR CUSTOMERS TO DEFINE AS THEY PLEASE
;UUOS 40, 41 AND 47 THROUGH 77 ARE DEFINED BY DIGITAL
;UUOS 52,53 AND 54 ARE RESERVED FOR EXPANSION BY DIGITAL

;TABLE OF CHECK-BITS FOR UUOS
CHKTAB::UU.PCS+UU.EA+UU.CP1,,UU.CP1+3	;CALL,INIT
	0,,0			;42,43
	0,,0			;44,45
	0,,UU.CP1		;46,CALLI
	UU.PCS+UU.CP1+UU.EA+3,,UU.PCS+UU.CP1+UU.SE1+UU.EA	;OPEN,TTCALL
	0,,0			;52,53
	0,,UU.PCS+UU.CP1+UU.LER	;54,RENAME
	UU.PCS+UU.CP1,,UU.PCS+UU.CP1		;IN,OUT
	UU.CP1,,UU.CP1		;SETSTS,STATO
	UU.PCS+UU.CP1,,UU.CP1	;GETSTS,STATZ
	UU.CP1,,UU.CP1		;INBUF,OUTBUF
	UU.PCS+UU.CP1,,UU.PCS+UU.CP1		;INPUT,,OUTPUT
	UU.CP1,,UU.CP1		;CLOSE,,RELEASE
	UU.CP1,,UU.PCS+UU.CP1	;MTAPE,UGETF
	UU.PCS+UU.CP1,,UU.PCS+UU.CP1		;USETI,USETO
	UU.PCS+UU.CP1+UU.LER,,UU.PCS+UU.CP1+UU.LER	;LOOKUP,ENTER
	SUBTTL	CALL & CALLI UUO'S

; CALLING SEQUENCE
;	CALL D,[SIXBIT/NAME/]
; WHERE NAME IS THE NAME OF A SYSTEM ROUTINE.
; IF NO SYSTEM ROUTINE WITH THE SPECIFIED NAME IF FOUND, THIS ROUTINE
; EXITS TO UUOERR.
;CONTENTS OF USER AC PLACED IN AC T1, M SET TO POINT TO USER AC
;J SET TO JOB NUMBER
UCALL:	PUSHJ	P,UCALLX	;CALCULATE CALLI INDEX
	  POPJ	P,		;BAD ARGUMENT
	JRST	UCALLI		;LIKE CALLI
UCALLX::PUSHJ	P,GETWDU##	;SET T1 FROM CONTENTS OF EFFECTIVE ADDRESS OF
				; UUO FROM EITHER HIGH OR LOW SEG
				; DO NOT RETURN IF ERROR
				; SET J TO CURRENT JOB NO.
	MOVNI	T2,UCLLEN+CCLLEN	;LENGTH OF TABLE
	CAME	T1,CCLTAB+UCLLEN+CCLLEN(T2)	;SEARCH SYSTEM ROUTINE NAME TABLE
	AOJL	T2,.-1
	HRRI	T2,UCLLEN(T2)
	JUMPGE	T2,CPOPJ##	;IF NOT FOUND, NO. OF UUO
	HRRM	T2,M		;STORE INDEX IN UUO, JUST AS IF USER HAD DONE CALLI UUO
	JRST	CPOPJ1##	;GOOD RETURN
;CALL UUO FALLS IN HERE
;CALLI UUO	-	CALL IMMEDIATE
;CALLI D,E
;WHERE E IS RELATIVE INDEX IN CALL TABLE
UCALLI::MOVE	T1,T2		;SAVE USER/EXEC BIT
	HRRE	T2,M		;GET CALLI NUMBER(POS.=DIGITAL,NEG.=CUSTOMER DEFINED)
	JUMPL	T2,UCALL1	;IF ARGUMENT IS POSITIVE,
	TRZE	T2,UPHNLY	;IS BIT 19=1?
	HRLI	P1,PHONLY	;YES, PHYSICAL DEVICES ONLY
	JRST	UCALL2
UCALL1:	TRON	T2,UPHNLY	;ARGUMENT NEG, IS BIT 19=0?
	HRLI	P1,PHONLY	;YES, PHYSICAL ONLY
UCALL2:	CAML	T2,MCCLEN	;MORE NEGATIVE THAN MOST NEGATIVE CUSTOMER DEFINED UUO?
	CAIL	T2,UCILEN	;MORE POSITIVE THAN HIGHEST DIGITAL DEFINED CALLI?
	POPJ	P,		;YES, RETURN TO USER TREAT AS NO-OP SO
				; PROGRAMS AHEAD OF MONITOR WILL STILL
				; RUN WITHOUT ERROR MESSAGE
	TLNE	T1,(XC.USR)	;NO, UUO WAS FROM MONITOR?
	POP	P,(P)		;NO, REMOVE RETURN
	HRR	M,P1		;UUO AC FIELD
	PUSHJ	P,GTWST2##	;PICK UP CONTENTS OF USER AC
	ROT	T2,-1		;DIVIDE BY 2 AND SAVE REMAINDER
	MOVE	U,UCLJMP(T2)	;GET DISPATCH TABLE ENTRY
	MOVE	T3,CHKTBC(T2)	;GET CHECK-BITS

	JRST	DISP2		;AND GO DISPATCH
;CALL UUO DISPATCH TABLE
;NEW UUO'S MUST BE ADDED AT END SINCE CALLI DEPENDS ON
;POSITION IN TABLE, CUSTOMERS SHOULD ADD UUO'S IN CNAMES MACRO SO CALLI ADDRESS
;WILL BE NEGATIVE.  IN THIS WAY BOTH DIGITAL AND ITS CUSTOMERS CAN ADD UUO'S
;WITHOUT CONFLICT, DIGITAL GOING POSITIVE, CUSTOMERS GOING NEGATIVE.
; (ALSO, TOWARD TOP OF PAGE)



DEFINE CNAMES <
	XLIST
IFN FTPATT,<
X	CPOPJ,CPOPJ##,UU.CP1            ;(-3) PLACE FOR CUSTOMERS
                                        ;    TO PATCH UUOS
X	CPOPJ,CPOPJ##,UU.CP1            ;(-2)
>
X	LIGHTS,LIGHTS,UU.CP1            ;(-1) SET LIGHTS (EXAMPLE
                                        ;    OF CUSTOMER DEFINED
                                        ;    UUO)
>

DEFINE NAMES,<
X	RESET,RESET,UU.CP1		;(0)RESET IO
X	DDTIN,DDTIN##,UU.CP1+UU.SE1+UU.EA+25   ;(1)EXT-GET DDT CHAR.
X	SETDDT,SETDDT,UU.CP1            ;(2)SETDDT LOC IN PROTECTED
                                        ;    JOB DATA
X	DDTOUT,DDTOUT##,UU.CP1+UU.SE1+UU.EA+25  ;(3)EXT:SEND DDT CHAR.
X	DEVCHR,UDVCHR,UU.CP1             ;(4)DEVICE CHARACTISTICS
X	DDTGT,CPOPJ##,UU.CP1            ;(5)GET DDT MODE
X	GETCHR,UDVCHR,UU.CP1             ;(6)DEVICE CHAR.(DIFF. NAME)
X	DDTRL,CPOPJ##,UU.CP1            ;(7)RELEASE DDT MODE
X	WAIT,WAIT,UU.CP1                ;(10)WAIT TILL DEVICE INACTIVE
X	CORE,CORUUO##,UU.CP1		;(11)CORE UUO
X	EXIT,EXIT,UU.CP1		;(12)EXIT
X	UTPCLR,UTPCLR,UU.CP1            ;(13)CLEAR DEC TAPE DIRECTORY
                                        ;
X	DATE,DATE,UU.CP1                ;(14)GET DATE
X	LOGIN,LOGIN,UU.MEA+UU.CP1 	;(15)LOGIN
X	APRENB,APRENB,UU.CP1            ;(16)ENABLE APR FOR TRAPPING
X	LOGOUT,LOGOUT,UU.CP1 		;(17)LOGOUT
X	SWITCH,SWITCH,UU.CP1            ;(20)RETURN DATA SWITCHES
X	REASSI,REASSI##,UU.CP1          ;(21)REASSIGN DEVICE TO ANOTHER
                                        ;    JOB
X	TIMER,TIMER,UU.CP1              ;(22)RETURN JIFFY CLOCK TIME
X	MSTIME,MSTIME,UU.CP1            ;(23)RETURN TIME OF DAY IN
                                        ;    MS


;CONTINUED ON NEXT PAGE
X	GETPPN,GETPPN,UU.CP1            ;(24)RETURN PROJECT-PROGRAMMER
                                        ;    NUMBER
X	TRPSET,TRPSET,UU.LEA+UU.CP1     ;(25)SET PI TRAP LOC, AND
                                        ;    USER IO
X	TRPJEN,UUOERR##,UU.CP1          ;(26)DISMISS INTERRUPT TO
                                        ;    EXEC MODE(SUPERCEDED
                                        ;    BY UJEN)
X	RUNTIM,JOBTIM,UU.CP1            ;(27)RETURN TOTAL JOB RUNNING
                                        ;    TIME
X	PJOB,JOBNO,UU.CP1               ;(30)RETURN JOB NUMBER
X	SLEEP,SLEEP,UU.CP1              ;(31)SLEEP FOR N SECONDS,
                                        ;    THEN RETURN TO USER
X	SETPOV,SETPOV,UU.CP1            ;(32)SET PUSH DOWN OVERFLOW
                                        ;    TRAP
X	PEEK,UPEEK,UU.CP1               ;(33)TO PEEK AT CERTAIN MONITOR
                                        ;    PARAMETERS
X	GETLIN,GETLN,UU.CP1             ;(34) GET TTY LINE NUMBER
X	RUN,URUN##,UU.EA+6+UU.CP1 	;(35) RUN DEV:FILE
X	SETUWP,SETUWP,UU.CP1            ;(36) SET OR CLEAR USER MODE
                                        ;    WRITE PROTECT
X	REMAP,REMAP,UU.CP1              ;(37) REMAP TOP OF LOW SEGMENT
                                        ;    INTO HIGH SEG
X	GETSEG,UGTSEG##,UU.EA+6+UU.CP1 	;(40) GET SHARABLE HIGH SEG
X	GETTAB,GETTAB,UU.CP1            ;(41) GET EXEC ADDRESS OF
                                        ;    A JOB TABLE
X	SPY,USPY##,UU.CP1	        ;(42) SET HIGH SEG TO BE
                                        ;    PHYSICAL CORE
X	SETNAM,SETNAM,UU.CP1            ;(43) SETNAME OF THIS PROGRAM
                                        ;LAST CALLI IN 4.50
X	TMPCOR,TMPUUO##,UU.EA+UU.CP1+2 	;(44) TEMPORARY FILE STORAGE
                                        ;    UUO (CCL)
X	DSKCHR,DSKCHR##,UU.CP1+UU.LEA   ;(45) DISK CHARACTERISTICS
                                        ;LAST CALLI IN 4.72
X	SYSSTR,SYSTUU##,UU.CP1          ;(46) RETURN NEXT STR IN
                                        ;    SYSTEM
X	JOBSTR,JOBSTR##,UU.LEA+UU.CP1 	;(47) RETURN NEXT STR IN
                                        ;    JOB
X	STRUUO,STRUUO##,UU.CP1+UU.LEA   ;(50) VARIOUS FUNCTION FOR
                                        ;    STRS
X	SYSPHY,SYSPHY##,UU.CP1          ;(51) RETURN ALL PHYSICAL
                                        ;    DEVS AND UNITS IN SYSTEM
X	FRECHN,CPOPJ##,UU.CP1           ;(52) RETURN 1ST FREE USER
                                        ;    CHAN IN AC, STARTING
                                        ;    FROM C(AC)
X	DEVTYP,UDVTYP,UU.CP1             ;(53) EXTENDED DEVICE CHARACTERISTICS
                                        ;    AND BUFFER SIZE


;CONTINUED ON NEXT PAGE
X	DEVSTS,DEVST,UU.CP1             ;(54) DEVSTS
X	DEVPPN,DEVPPU,UU.CP1            ;(55) RETURN PPN FOR DEVICE
X	SEEK,CPOPJ##,UU.CP1             ;(56) SEEK
                                        ;LAST CALLI IN 5.01
X	RTTRP,RTTRP##,UU.CP1+UU.EA+4    ;(57) REAL TIME TRAP
X	LOCK,LOKJOB##			;(60) LOCK JOB IN CORE
X	JOBSTS,UJBSTS##,UU.CP1+UU.SE1   ;(61) RETURN STATUS OF JOB
                                        ;    AND ITS PTY
X	LOCATE,LOCATE##,UU.CP1          ;(62) FOR REMOTE COMM
X	WHERE,WHERE##,UU.CP1            ;(63) FOR REMOTE COMM
X	DEVNAM,UDEVNM,UU.CP1            ;(64) GET PHYSICAL DEVICE
                                        ;    NAME
X	CTLJOB,CTLJOB##,UU.CP1          ;(65) FIND CONTROLLER OF
                                        ;    THIS JOB (IF BY PTY)
X	GOBSTR,GOBSTR##,UU.CP1+UU.LEA   ;(66) GENERALIZED JOBSTR
                                        ;    (ANY JOB'S SEARCH LIST)
                                        ;LAST CALLI IN 5.02
X	FOO,CPOPJ##,UU.CP1              ;(67) FOO
X	FOO,CPOPJ##,UU.CP1              ;(70) FOO
X	HPQ,HPQ##,UU.CP1                ;(71) HIGH PRIORITY QUEUE
                                        ;    UUO
X	HIBER,HIBUUO,UU.CP1             ;(72) HIBERNATE UUO

X	WAKE,WAKUUO,UU.CP1              ;(73) WAKE UUO
X	CHGPPN,CHGPPN,UU.CP1            ;(74) CHANGE PPN
X	SETUUO,SETUUO##,UU.CP1          ;(75) SET
X	DEVGEN,DEVGEN,UU.CP1            ;(76) DEVICE GENERIC NUMBER
                                        ;    UUO
X	OTHUSR,GETPPL,UU.CP1            ;(77) SEE IF OTHER USER'S
                                        ;    WITH SAME PPN AS CALLING
                                        ;    JOB
X	CHKACC,ACCCHK##,UU.CP1+UU.EA+3  ;(100) ACCESS-ALLOWED UUO
X	DEVSIZ,DVSIZ,UU.CP1             ;(101) RETURN BUFFER SIZE
X	DAEMON,CALDAE,UU.CP1+UU.LEA     ;(102) CALL DAEMON
X	JOBPEK,JOBPEK,UU.CP1+UU.EA+2    ;(103) READ/WRITE ANOTHER
                                        ;    JOB'S CORE
X	ATTACH,UATTAC,UU.CP1+UU.SE1	;(104) ATTACH OR DETACH JOBS.
X	DAEFIN,DAEFIN,UU.LEA+UU.CP1 	;(105) DAEMON FINISHED -
                                        ;    RESTART USER JOB
X	FRCUUO,FRCUUO,UU.LEA+UU.CP1	;(106) FORCE COMMAND FOR
                                        ;    JOB
X	DEVLNM,DEVLNM,UU.CP1            ;(107) SET DEVICE LOGICAL
                                        ;    NAME
                                        ;LAST CALLI IN 5.03


;CONTINUED ON NEXT PAGE
X	PATH.,PTHUUO##,UU.CP1+UU.LEA    ;(110) TEST/SET FULL PATHS
                                        ;    TO FILES
X	METER.,CPOPJ##		        ;(111)PERFORMANCE METERING (OBSOLETE)
X	MTCHR.,MTACHR##,UU.CP1		;(112)GET MAGTAPE CHARACTERISTICS
X	JBSET.,JBSET.##,UU.EA+2+UU.CP1	;(113)JOB SETUUO
X	POKE.,POKE,UU.CP1+UU.EA+3       ;(114)CHANGE MONITOR
X	TRMNO.,TRMNO##,UU.CP1+UU.SE1    ;(115)TERMINAL NUMBER FOR
                                        ;    JOB
X	TRMOP.,TRMOP##,UU.LEA+UU.CP1+UU.SE1    ;(116)TERMINAL OPERATIONS
                                        ;    UUO
X	RESDV.,RESDV,UU.CP1             ;(117)RESET DEVICE OR CHANNEL
X	UNLOK.,UNLOK.##,UU.CP1          ;(120)UNLOCK A LOCKED JOB
                                        ;LAST CALLI IN 5.04
X	DISK.,DSKUUO##,UU.CP1+UU.EA     ;(121)RANDOM DISK FUNCTIONS
X	DVRST.,DEVRST,UU.CP1            ;(122)RESTRICT DEVICE TO
                                        ;    OPER ONLY
X	DVURS.,DEVURS,UU.CP1            ;(123)UNRESTRICT DEVICE
                                        ;LAST CALLI IN 5.05 & 5.06
X	XTTSK.,XTUUO##,UU.LEA+UU.CP1    ;(124)DA28C DEPENDENT FUNCTIONS
X	CAL11.,CALL11##,UU.LEA+UU.CP1   ;(125)MULTI-FUNCTION CALLI
                                        ;    FOR THE PDP-11
X	MTAID.,MTARID##,UU.CP1          ;(126)FOR MTA ERROR REPORTING
X	IONDX.,UIONDX,UU.CP1            ;(127)RETURN IO INDEX

X	CNECT.,CONECT##,UU.CP1+UU.EA+1	;(130)CONNECT A DEVICE TO
                                        ;    AN MPX CHAN
X	MVHDR.,MOVHDR,UU.CP1		;(131)MOVE BUFFER HEADER
X	ERLST.,ERLST##,UU.CP1+UU.EA+2	;(132)ERROR LIST
X	SENSE.,SENSE##,UU.CP1+UU.LEA	;(133)SENSE
X	CLRST.,CLRST##,UU.CP1+UU.LEA	;(134)CLEAR STATUS


;CONTINUED ON NEXT PAGE
X	PIINI.,PIINI##,UU.CP1+UU.EA     ;(135)INITIALIZE SOFTWARE
                                        ;    INTERRUPT SYSTEM
X	PISYS.,PISYS##,UU.CP1           ;(136)MANIPULATE SOFT. INTERRUPT
                                        ;    SYSTEM
X	DEBRK.,DEBRK##,UU.CP1           ;(137)DISMISS A SOFTWARE
                                        ;    INTERRUPT
X	PISAV.,PISAVE##,UU.CP1+UU.LEA   ;(140)SAVE THE PI SYSTEM
X	PIRST.,PIRST##,UU.CP1+UU.EA+UU.CEA ;(141)RESTORE THE PI SYSTEM
X	IPCFR.,UIPCFR##,UU.CP1+UU.SE1   ;(142) IPCF READ
X	IPCFS.,UIPCFS##,UU.CP1+UU.SE1 	;(143) IPCF SEND
X	IPCFQ.,UIPCFQ##,UU.CP1+UU.SE1 	;(144) IPCF QUERY
X	PAGE.,UPAGE.##,UU.CP1           ;(145) PAGING UUOS

X	SUSET.,USUSET##,UU.CP1          ;(146) SUPER USETI/O
X	COMPT.,CPOPJ##,UU.CP1           ;(147) CALL TO COMPATABILITY
                                        ;    PACKAGES
                                        ;LAST CALLI IN 5.07/6.01
X	SCHED.,SCHED.##,UU.CP1		;(150) SCHEDULING UUO
X	ENQ.,ENQ##,UU.CP1		;(151) ENQUEUE
X	DEQ.,DEQ##,UU.CP1		;(152) DEQUEUE
X	ENQC.,ENQC##,UU.CP1		;(153) ENQ CONTROLLER


;CONTINUED ON NEXT PAGE
X	TAPOP.,UTAPOP##,UU.LEA+UU.CP1	;(154) TAPOP. UUO (SEE TAPSER)
X	FILOP.,FILOP,UU.CP1+UU.LEA      ;(155) FILOP. UUO

X	CAL78.,CALL78##,UU.CP1		;(156) FOR DAS78
X	NODE.,NODE.U##,UU.CP1+UU.SE1	;(157) RESERVED FOR NETWORKS
X	ERRPT.,ERRPT.##,UU.CP1		;(160) ERROR REPORTING UUO FOR DAEMON
X	ALLOC.,CPOPJ##,UU.CP1		;(161) OBSOLETE, ALLOC.UUO
X	PERF.,UPERF.,UU.CP1		;(162) PERFORMANCE ANALYSIS UUO
					;LAST UUO IN 6.02
X	DIAG.,DIAUUO,UU.CP1		;(163) DIAGNOSTIC UUO
X	DVPHY.,DVPHY.,UU.CP1		;(164) DVPHY.UUO

X	GTNTN.,GTNTN,UU.CP1+UU.SE1	;(165) GET THE NETWORK TTY NUMBER
X	GTXTN.,GTXTN,UU.CP1+UU.SE1	;(166) GET THE -10 TTY NAME

X	ACCT.,ACCT,UU.CP1		;(167) ACCOUNTING UUO
X	DTE.,DTE.##,UU.CP1		;(170) DTE. UUO
X	DEVOP.,DEVOP,UU.CP1+UU.LEA	;(171) DEVOP. UUO

X	SPPRM.,SPPRM,UU.CP1+UU.LEA	;(172) SPPRM. UUO
					;LAST UUO IN 6.03
X	MERGE.,UMERGE##,UU.CP1+UU.EA+6	;(173) MERGE. UUO
X	UTRP.,UUTRP,UU.CP1+UU.LER	;(174) UTRP. UUO
X	PIJBI.,PIJOB##,UU.CP1		;(175) PIJBI. UUO
X	SNOOP.,SNOOP,UU.CP1		;(176) SNOOP. UUO
X	TSK.,TSK.##,UU.CP1		;(177) TSK. UUO
X	KDP.,KDP.##,UU.CP1		;(200) KDP. UUO
					;LAST UUO IN 7.00
X	QUEUE.,GLXINF##,UU.CP1+UU.SE1	;(201) QUEUE. UUO
X	RECON.,RECON,UU.CP1		;(202) RECON. UUO
					;LAST UUO IN 7.01
X	PITMR.,PITMR##,UU.CP1		;(203) PITMR. UUO
X	ACCLG.,ACCLOG,UU.CP1		;(204) ACCLG. UUO
X	NSP.,SCUUUO##,UU.CP1+UU.SE1	;(205) DECNET-10'S NSP.
X	NTMAN.,NTMAN##,UU.CP1+UU.SE1	;(206) DECNET NETWORK MANAGEMENT.
X	DNET.,DNET##,UU.CP1+UU.SE1	;(207) DECNET INFORMATION
X	SAVE.,USAVE##,UU.CP1+UU.EA+6	;(210) SAVE CORE-IMAGE ON DISK
X	CMAND.,CMAND,UU.CP1		;(211) USER DEFINABLE COMMANDS
X	PIBLK.,PIBLK##,UU.CP1		;(212) PIBLK UUO
IFE FTSCA,<
X	SCS.,CPOPJ##,UU.CP1		;(213) NOOP
>; END IFE FTSCA
IFN FTSCA,<
X	SCS.,SCS##,UU.CP1+UU.SE1	;(213) SCS. UUO
>; END IFN FTSCA
X	SEBLK.,SEBLK.##,UU.CP1		;(214) SEBLK. UUO
X	CTX.,CTXUUO##,UU.CP1!UU.SE1	;(215) CONTEXT UUO
X	PIFLG.,PIFLG##,UU.CP1		;(216) PIFLG UUO
X	IPCFM.,UIPCFM##,UU.SE1		;(217) IPCFM UUO
X	LLMOP.,.LLMOP##,UU.CP1		;(220) LLMOP. UUO
X	LATOP.,.LATOP##,UU.SE1		;(221) LATOP. UUO
X	KNIBT.,KNIBT.##,UU.CP1!UU.SE1	;(222) KNIBT. UUO
X	CHTRN.,UCHTRN##,UU.CP1		;(223) CHTRN. UUO
X	ETHNT.,ETHNT.##,UU.CP1!UU.SE1	;(224) ETHNT. UUO
X	ENTVC.,ENTVC,UU.CP1!UU.SE1	;(225) ENTVC. UUO
X	NETOP.,NETOP,UU.CP1!UU.SE1	;(226) NETOP. UUO

;***ADD NEW CALLI'S ABOVE THIS LINE *****
IFN FTPATT,<
X	CPOPJ,CPOPJ##,UU.CP1   ;2 SPARE UUO'S FOR PATCHING - DIGITAL ONLY
X	CPOPJ,CPOPJ##,UU.CP1   ;ALWAYS ADD NEW UUO'S ABOVE THESE
>
                                ;CUSTOMERS SHOULD ADD UUO'S ABOVE
                                ;IN CNAMES MACRO RATHER THAN NAMES MACRO
                                ; SO THAT THEIR CALLI INDICES WILL
                                ; BE NEGATIVE
	LIST
	SALL
>
;GENERATE SIXBIT TABLE OF UUO NAMES

DEFINE X (A,B,C) <
	<EXP SIXBIT /A/>
>

;GENERATE CUSTOMER CALL/CALLI UUO'S

MCCLEN::EXP	-CCLLEN
CCLTAB:	CNAMES
CCLLEN==.-CCLTAB	;LENGTH OF CUSTOMER DEFINED CALL/CALLI UUO'S
			;(MINIMUM CALLI NUMBER, TOO)

;GENERATE DIGITAL UUO'S

DEFINE X (A,B,C)  <
	IFL	.-UCLTAB-MAXCAL,<EXP SIXBIT /A/>
>

UCLTAB:	NAMES
XP	UCLLEN,.-UCLTAB		;DEFINE LENGTH OF DIGITAL UUO TABLE
DEFINE X (A,B,C)
<	ZZ==ZZ+1
	DEFINE	XX (D)		;DEFINE XX IN CASE ODD NUMBER OF CUSTOMER UUO'S
<	XWD CPOPJ##,D
>>
ZZ==0
;COUNT NUMBER OF CUSTOMER DEFINED UUO'S
	CNAMES

;GENERATE HALF WORD UUO DISPATCH TABLE

DEFINE X (A,B,C)
<	IFE ZZ&1,
<	DEFINE XX (D)
<
	XWD	B,D
>>
	IFN	ZZ&1,
<
	XX	B
>
ZZ==ZZ+1
>
;GENERATE CUSTOMER TABLE

CUSTAB:	CNAMES

ZZ==0

;GENERATE DIGITAL TABLE

UCLJMP:	NAMES

	IFN	ZZ&1,<XX CPOPJ##>	;GEN. LAST WORD IF ODD NUMBER OF UUOS
UCILEN==:<.-UCLJMP>*2		;MAX DIGITAL CALLI INDEX
	DEFINE	X(A,B,C)
<	ZZ==ZZ+1
>
	DEFINE	XX(D)		;DEFINE XX IN CASE ODD NO. OF CUST. CALLI'S
<	XWD	0,D
>
ZZ==0
;COUNT NUMBER OF CUSTOMER CALLI'S
	CNAMES
DEFINE X (A,B,C)
<IFE ZZ&1,
<DEFINE XX (D)
<
	XWD	C,D
>>
	IFN	ZZ&1,
<
	XX	C
>
ZZ==ZZ+1
>
	CNAMES
ZZ==0
CHKTBC::NAMES

IFN ZZ&1,< XX 0>
	SUBTTL	EXIT & SETPOV UUO'S

;EXIT UUO ROUTINE
;CALL:	CALL FIELD, [SIXBIT/EXIT/]
;IF FIELD - 0, PRINT EXIT ^C.  CONT WILL NOT WORK

EXIT:	MOVSI	T1,JLOG
	TDNN	T1,JBTSTS##(J)	;IS THIS JOB LOGGED IN?
	JRST	LOGOUT		;NO, GO DESTROY JOB

	JUMPN	P1,MONRET	;AC FIELD NON-ZERO?
	PUSHJ	P,IORELS	;NO, RELEASE ALL DEVICES
	PUSHJ	P,RESET		;AFTER CLOSING OUT FILES, RELEASE RT DEV
				;UNLOCK JOB, RESET APR
	MOVSI	T1,(JS.SAC)	;BIT TO TEST
	TDNE	T1,JBTST2##(J)	;DOING AN AUTO-RESTORE ON PROGRAM EXIT?
	JRST	MONRET		;YES, DON'T TYPE EXTRA JUNK
	PUSHJ	P,TTYFUW##	;FIND TTY FOR CURRENT JOB
				; SET J TO JOB NO.,U TO LDB ADDRESS
				; F TO TTY DDB
	JSP	T1,PHOLD##	;MOVE "EXIT" TO OUTPUT BUFFER
				; AND STOP JOB, AND START TTY, CONT WILL NOT WORK
	ASCIZ	/
EXIT/

;	CALL 1,[SIXBIT/EXIT/] - RETURN TTY TO MONITOR MODE,
;	STOP JOB, BUT DO NOT RELEASE DEVICES
;TYPE . WITH NO CRLF, ALLOW CONT COMMAND TO RETURN AFTER UUO


MONRET::MOVSI	T1,(JS.SAC)	;BIT TO TEST
	TDNE	T1,JBTST2##(J)	;DOING AN AUTO-RESTORE ON PROGRAM EXIT?
	JRST	[PUSHJ	P,TTYFNU##	;FIND TTY
		 MOVSI	T1,(UP.DST)	;GET HNGSTP BIT
		 IORM	T1,.USBTS	;LIGHT IT FOR STOP1C PROCESSING
		 JUMPE	U,MONRE1	;DON'T TOUCH LDB IF DETACHED
		 MOVSI	T1,LDLCOM##	;COMMAND MODE BIT
		 SE1XCT <ANDCAM T1,LDBDCH##(U)> ;CLEAR IT (STOP COMCON)
		 JRST	MONRE1]		;DON'T TYPE OUT OR ALLOW COMMANDS
	PUSHJ	P,TTYFUW##	;WAIT FOR A TTY TO TYPE ON
	PUSHJ	P,PRRSP3##	;NO--PRINT [XXX], CRLF, DOT
	PUSHJ	P,TTYSTC##	;PUT TTY INTO COMMAND MODE
MONRE1:	PUSHJ	P,STOP1C##	;START TTY IN MONITOR MODE AND STOP JOB, BUT ALLOW
				; CONTINUE TO WORK (RETURN CONTROL AFTER EXIT UUO)
	JRST	USCHED##	;CALL SCHEDULER WHICH WILL SET CURRENT JOB
				; WITH RUN BIT OFF AND WILL STOP JOB
;SETPOV - SET PUSH DOWN OVERFLOW TRAP
;CALL	MOVE AC,ADR. OF TRAP ON PD OVF
;	CALL AC,[SIXBIT /SETPOV/]


SETPOV:	MOVEM	T1,.JDAT+JOBAPR##
	MOVEI	T1,AP.POV
	JRST	APRENB		;SET TRAP LOC.
	SUBTTL	RESET & APRENB UUO'S

RESET::
IFN FTKL10,<
	PUSHJ	P,GIVPMR##
	PUSHJ	P,FEDRST##	;RELEASE FRONT END DEVICE
>;END IFN FTKL10
	PUSHJ	P,SNPRST	;REMOVE BREAK POINTS
IFN FTHPQ,<			;HIGH PRIORITY QUEUE FEATURE?
	LDB	T2,HPQSPT##	;CONSOLE COMMAND HPQ SETTING
>
	HRLOI	T1,HPQMSK##	;MASK OUT LH BITS LEAVE RH SAME
				; (REAL TIME DEVICE COUNT)
	ANDM	T1,JBTRTD##(J)	;CLEAR ALL BUT CONSOLE COMMAND HPQ
IFN FTHPQ,<			;HIGH PRIORITY QUEUE
	DPB	T2,HPQPNT##	;RESTORE CONSOLE COMMAND AS OPERATING QUEUE
>				;END FTHPQ
IFN FTNET,<
				;THIS CALL MUST PRECEED THE CALL TO UNLOCK BELOW
	PUSHJ	P,NETCTC##	;ALSO CALL NETSER ON CONTROL ^C
>;END FTNET
IFN FTSCA,<
	PUSHJ	P,SCSRST##	;CALL SCSUUO ON RESET
>; END IFN FTSCA
IFN FTENET,<
	PUSHJ	P,ENTRST##	;CALL ETHUUO ABOUT RESET
IFN FTKL10,<
	PUSHJ	P,KNIRST##	;CALL KNISER ABOUT RESET
>; END IFN FTKL10
>; END IFN FTENET
IFN FTDECNET,<
	SNCALL	(SCURST##,MS.HGH) ;RESET DECNET-10
>
IFN FTLOCK,<
	PUSHJ	P,UNLOCK##	;TURN OFF NSHF AND NSWP AND RETURN CORE
>
IFN FTTRPSET,<
	MOVEI	T1,[CAMN J,.CPSTS##-.CPCDB##(P1) ;MAKE SURE SCHEDULING ALLOWED
		    SETZM .CPSTS##-.CPCDB##(P1)
		    POPJ P,]
				; IN CASE THIS FOLLOWS A TRPSET UUO
				;(IF STOPTS IS NON-ZERO, THIS MUST BE
				; THE JOB THAT STOPPED TIME SHARING)
	PUSHJ	P,CPUAPP##	;ZERO .CPSTS FOR ALL CPU'S
>
IFN FTMP,<
	PUSHJ	P,CRESET##	;RESET UUO SET CPU SPECIFICATION
>
	PUSHJ	P,HRESET##	;FLAG USER AS HAVING UWP ON FOR HIGH SEG
				; AND DO DATAO TO SET UWP ON

	PUSHJ	P,FNDPDS##	;FIND THE JOB PDB
	HRRZ	T2,.PDSCX##(W)	;ADDRESS OF JOB'S SAVED CONTEXT
	MOVEI	T1,NWSCTX	;NUMBER OF WORDS OF SAVED CONTEXT
	SKIPE	T2		;HAS THE JOB'S CONTEXT BEEN SAVED?
	PUSHJ	P,GIVWDS##	;YES, RETURN SPACE TO MONITOR FREE CORE
	HLLZS	.PDSCX##(W)	;INDICATE NO SAVED CONTEXT
	HRRZS	.PDLBS##(W)	;CLEAR LARGE DISK BUFFERS IF SET BY UUO
	PUSHJ	P,CLRBRK##	;CLEAR ADDRESS BREAK IF SET BY UUO
IFN FTPI,<
	PUSHJ	P,CLRPSI##	;RESET SOFTWARE INTERRUPT STATUS
>
IFN FTEQDQ,<
	PUSHJ	P,ENQRST##	;CLEAR ALL LOCKS
>
IFN FTIPCF,<
	PUSHJ	P,IPCFRC##	;SIGNAL RESET TO SYS:INFO
>
	MOVEI	T1,RELEA1	;RELEASE ALL DEVICES
	PUSHJ	P,IOALL		; WITHOUT WAITING
	PUSHJ	P,TTYRES##	;NORMALIZE CONTROLLING TTY, IF ANY
	MOVEI	T1,HIGHXC##-20	;NUMBER OF EXTENDED CHANNELS
	HRRZ	T2,.USCTA
	SKIPE	T2		;STILL HAVE FUNNY SPACE?
	PUSHJ	P,GVFWDS##	;GIVE IT BACK
	HLLZS	.USCTA
	HLLZS	JBTDDB##(J)	;NOT IN IOWAIT NOW (FOR ^T'ERS)

	PUSHJ	P,SETUSR	;CLEAR USERS JOB DATA AREA

IFN FTMDA,<
	PUSHJ	P,MDARST	;CHECK ANY STRUCTURE LOCKS
> ;END FTMDA
	MOVSI	T1,777777-USRMOD ;CLEAR ALL UUO PC FLAGS IN LH, EXCEPT USER MODE
	ANDCAM	T1,.JDAT+JOBPD1## ;LEAVE USER MODE OFF TOO, IF EXEC DOING CALL RESET
				; FALL INTO APRENB WITH RH T1=0
				; SO THAT ALL APR INTERRUPTS WILL BE DISABLED
;ROUTINE TO SET UP APR FOR USER TRAPPING
;CALL:	CALL AC,[SIXBIT /APRENB/]
;WITH FOLLOWING APR CONSO FLAG BITS
;TO INDICATE WHICH APR CONDITIONS SHOULD
;TRAP TO USER WHEN TRAP OCCURS FROM USER MODE
;1B18	;DO NOT DISABLE SELECTED CONDITIONS (EXCEPT CLOCK) SEE APRINT

;1B19	;PUSHDOWN OVERFLOW
;1B22	;ILLEGAL MEMORY
;1B23	;NON-EXISTENT MEMORY
;1B26	;CLOCK
;1B29	;FLOATING POINT OVERFLOW
;1B32	;ARITH. OVERFLOW


APRENB::HRRM	T1,.JDAT+JOBENB##  ;SET RH TO CONSO BITS IN JOB DATA AREA
				; USED EVERY TIME IS STARTED UP
;	JRST	SETAPR##	;GO ENABLE/DISABLE APR FOR FOV AND HR OV
				; ALSO SET APR CONSO INSTR. FOR PROPER FLAGS
				; AND RETURN TO USER

;ROUTINE TO ENABLE/DISABLE APR FOR TRAPPING TO USER AND EXEC
;CALL:	MOVEI T1, APR CONSO FLAGS FOR USER TRAPPING
;	PUSHJ P,SETAPR
;	RETURN WITH APR RESET AND INTERRUPT LOCATION CONSO'S SET

SETAPR::
SETAP1::PUSHJ	P,SETRP		;SETUP THE TRAP LOCATIONS (PAGE FAULT,
				; ARITHMETIC, PDL OVF)
;	PJRST	SETCNA		;SET USER ENABLES FOR NXM AND CLOCK AND
				; SET THE APR PIA AND EXIT

;SUBROUTINE TO SETUP USER'S APR CONSO MASK AND THE APR PIA
;CALLING SEQUENCE:
;	MOVE	T1,USER'S APR ENABLE BITS
;	PUSHJ	P,SETCNA
;	ALWAYS RETURN HERE

SETCNA::HRL	T1,T1		;COPY ENABLE BITS TO LEFT HALF
	TLZ	T1,-1-XP.CLK-UE.PEF-UE.NXM ;CLEAR ALL BUT CLOCK, NXM, AND PARITY
	HRR	T1,.CPEEB##	;SET MONITOR ENABLE BITS
	MOVEI	T2,IP.ECI	;ENABLE CLOCK INTERRUPT
	ADDI	T2,@.CPAPI##	;ADD IN APR PIA
	CONO	PI,PI.OFF	;DISALLOW INTERRUPTS WHILE CHANGING APR BITS
	HLRM	T1,.CPCN1##	;USER'S ENABLE BITS
	HRRM	T1,.CPCON##	;MONITOR'S ENABLE BITS
	CONO	APR,(T2)	;SET CLOCK ENABLE AND APR PIA
	CONO	PI,PI.ON	;RESTORE PI
	POPJ	P,		;RETURN
;ROUTINE TO SETUP USER TRAP LOCATIONS AS SPECIFIED BY USER ENABLE BITS
; PAGE FAULT (ILL. MEM. REF.), ARITHMETIC (INTEGER OVERFLOW, FLOATING
; POINT OVERFLOW OR UNDERFLOW, AND DIVIDE CHECK), PUSH DOWN LIST OVERFLOW
; TRAP 3 IS ALWAYS IGNORED IN USER MODE.
;CALLING SEQUENCE:
;	MOVE	T1,USER ENABLE BITS
;	PUSHJ	P,SETRP
;	ALWAYS RETURN HERE
;T1 IS PRESERVED.

SETRP:	TRNE	T1,AP.AOV+AP.FOV;IS HE?
	TDZA	T2,T2		;YES, SET TO FIELD TRAPS
	MOVSI	T2,(JFCL)	;IGNORE ARITHMETIC TRAPS IF USER NOT ENABLED
	HRRI	T2,UE.AOT	;SET DISPATCH ADDRESS
	MOVEM	T2,.USAOT	;STORE IN UPT
	MOVEI	T2,UP.PDT	;IF USER NOT ENABLED FOR POV HANDLE LIKE EXEC POV
	TRNE	T1,AP.POV	;IS HE ENABLED?
	MOVEI	T2,UE.PDT	;YES, HANDLE DIFFERENTLY
	MOVEM	T2,.USPDT	;YES, SET FOR SEPDLO OR SUPDLO TO HANDLE PDL OV
IFE FTPI,<
	POPJ	P,		;RETURN
>
IFN FTPI,<
	PJRST	APPSI##		;SETUP TRAP LOCATIONS FOR ANY INTERRUPTS THE
				; USER IS ENABLED FOR
>
;HERE WHENEVER ANY JOB DOES A RESET
;CALL WITH J=JOB

IFN FTMDA,<
MDARST:	PUSHJ	P,FNDPDS##
	MOVE	T1,UDATEX##	;GET NOW
	MOVEM	T1,.PDSTM##(W)	;MARK LAST RESET TIME
	MOVSI	T1,(JS.OLS)	;GET OWNS LOCKED STR BIT
	TDNN	T1,JBTST2##(J)	;OWN ANY AT ALL?
	POPJ	P,		;NO, ALL DONE
	ANDCAM	T1,JBTST2##(J)	;YES, NOTED
				;SAVE PDB
	PUSHJ	P,SNDMDR##	;INFORM MDA
	  POPJ	P,		;IGNORE ERROR
	POPJ	P,
> ;END FTMDA
	SUBTTL	UTRP. UUO - SET TRAP LOCATIONS

;UUO ALLOWS A PROGRAM TO PLACE AN INSTRUCTION (ADDRESS OF LUUO BLOCK) IN TRAP
; LOCATIONS. MAKES OVERFLOW, UNDERFLOW TRAPPING FAST, LUUOS IN NON-ZERO SECTIONS
; POSSIBLE.
;CALLING SEQUENCE:
;	MOVE	AC,[FUNCTION,,ADDRESS]
;	UTRP.	AC,
;	  ERROR RETURN
;	NORMAL RETURN


UTADC%==1			;ADDRESS CHECK
UTUNF%==2			;UNKNOWN FUNCTION
UTBTN%==3			;BAD TRAP NUMBER
UTIUT%==4			;ILLEGAL USER TRAP INSTR

ERCODE	UTEADC,UTADC%
ERCODE	UTEUNF,UTUNF%
ERCODE	UTEBTN,UTBTN%
ERCODE	UTEIUT,UTIUT%

UUTRP:	HLRZ	U,T1		;GET FUNCTION
	CAILE	U,NUTRPF	;LEGAL FUNCTION?
	JRST	UTEUNF		;NO
	HRR	M,T1		;ADDRESS OF ARGUMENT LIST
	PUSHJ	P,GETWRD##	;GET ARGUMENT COUNT
	  JRST	UTEADC		;ADDRESS CHECK
	PUSHJ	P,SAVE1##	;SAVE AN AC
	MOVE	P1,T1		;ARGUMENT COUNT TO P1
	JRST	@UTPTBL(U)	;DISPATCH TO SET OR READ TRAP LOCATIONS

UTPTBL:	UTPRED
	UTPSET
NUTRPF==.-UTPTBL-1

;HERE TO READ CONTENTS OF TRAP LOCATIONS
UTPRED:	PUSHJ	P,GETTRN	;GET TRAP NUMBER
	  POPJ	P,		;ADDRESS CHECK OR BAD TRAP NUMBER
	MOVE	T1,.USTVC(U)	;GET CONTENTS OF TRAP LOCATION
	PUSHJ	P,PUTWR1##	;STORE IT FOR THE USER
	  JRST	UTEADC		;ADDRESS CHECK
	SOJG	P1,UTPRED	;EXHAUSED COUNT?
	JRST	CPOPJ1##	;YES, GIVE GOOD RETURN

;HERE TO SET CONTENTS OF TRAP LOCATION
UTPSET:	PUSHJ	P,GETTRN	;GET TRAP NUMBER
	  POPJ	P,		;ADDRESS CHECK OR BAD TRAP NUMBER
	PUSHJ	P,GETWR1##	;GET INSTRUCTION/ADDRESS TO STORE IN TRAP LOCATION
	  JRST	UTEADC		;ADDRESS CHECK
	JUMPE	U,UTPSE2	;ANY VALUE IS FINE FOR LUUO BLOCK
	TLNE	T1,777000	;OPCODE ZERO?
	  JRST	UTPSE2		;NO, JUST GO STUFF
	JUMPN	T1,UTEIUT	;ILLEGAL UNLESS DEFAULTING
	PUSH	P,.USTVC	;SAVE CURRENT CONTENTS OF ALL TRAP LOCATIONS
	PUSH	P,.USTVC+1
	PUSH	P,.USTVC+2
	PUSH	P,.USTVC+3
	MOVE	T1,.JDAT+JOBENB##
	PUSHJ	P,SETRP		;SETUP TRAP LOCATIONS TO MONITOR DEFAULTS
	MOVE	T1,(U)		;GET MONITOR DEFAULT FOR CURRENT TRAP NUMBER
	POP	P,.USTVC+3	;RESTORE ALL OTHER TRAP LOCATIONS
	POP	P,.USTVC+2
	POP	P,.USTVC+1
	POP	P,.USTVC
UTPSE2:	MOVEM	T1,.USTVC(U)	;STORE USER SUPPLIED INTRUCTION/ADDRESS, OR DEFAULT
	SOJG	P1,UTPSET	;LOOP OVEN ENTIRE ARGUMENT LIST
	JRST	CPOPJ1##	;AND GIVE DONE GOOD RETURN

;SUBROUTINE TO FETCH AND VALIDATE A TRAP NUMBER, RETURNS CPOPJ IF BAD, CPOPJ1
; IF OKAY, TRAP NUMBER IN U
GETTRN:	PUSHJ	P,GETWR1##	;GET NEXT TRAP NUMBER
	  JRST	UTEADC		;ADDRESS CHECK
	SKIPL	T1		;NEGATIVE TRAP NUMBERS ARE ILLEGAL
	CAILE	T1,2		;SO ARE TRAP NUMBERS GREATER THAN 2
	JRST	UTEBTN		;BAD TRAP NUMBER
	MOVEI	U,(T1)		;RETURN TRAP NUMBER IN U
	SOJA	P1,CPOPJ1##	;DECREMENT ARGUMENT COUNT AND GOOD RETURN
	SUBTTL	MISC. ACCOUNTING UUOS (JOBNO,JOBTIM,DATE & MSTIME)

;RETURN JOB NUMBER FOR THIS JOB

JOBNO:	SKIPA	T1,J		;JOB NUMBER
				; SKIP AND STORE T1 IS USER AC

;RETURN THE DATE TO THE USER


DATE:	MOVE	T1,THSDAT##
	JRST	STOTAC##

;RETURN JOB RUNNING TIME IN MILLISECONDS
JOBTIM:	PUSHJ	P,JOBTMM	;GET JOBS RUN TIME
	PJRST	STOTAC##	; AND STORE IT

;THIS CODE DEPENDS UPON RTUPS BEING AN INTEGRAL MULTIPLE OF ^D100000

JOBTMM::MOVEI	T3,RTUPS3##	;ASSUME MILLISECOND RESOLUTION
	TLZE	T1,(1B0)	;IF SIGN BIT = 1
	MOVEI	T3,RTUPS5##	; RETURN 10 USEC. RESOLUTION
	IMUL	T3,TICSEC##
	PUSH	P,T3		;SAVE FOR LATER DIV
	PUSHJ	P,LGLPR1##	;SKIP IF LEGAL JOB NUMBER (0 IS OK)
	  JRST	JOBTM3
	SKIPN	T1
	SKIPA	T1,J
	MOVE	J,T1		;J PROCESS # IN QUESTION
	PUSHJ	P,FNDPDB##	;FIND THE PDB
	  JRST	JOBTM3		;IF NONE RETURN ZERO
	MOVE	J,.CPJOB##	;SETUP J FROM JOB
IFN FTEMRT,<
	MOVEI	T1,ST%EMR	;EBOX MBOX ROUTINE?
	TDNN	T1,CNFST2##	;?
	JRST	JOBTM1		;NO, COMPUTE RUNTIME NORMAL WAY
				;YES,
	.MOVE	T1,.PDMB2##(W)	;GET REMAINDER FROM MBOX JIFFY CALCULATION
	MULI	T1,RTUPS##	;COMPUTE LEFTOVER*RTUPS/MBOX TICKS PER JIFFY
	DIV	T1,.CPMBJ##	;LEAVE IN T1
	.MOVE	T3,.PDEB2##(W)	;SAME FOR EBOX TICKS
	MULI	T3,RTUPS##
	DIV	T3,.CPEBJ##
	ADD	T3,T1		;RESULT CANNOT BE GREATER THAN 2*RTUPS,
				; WHICH FITS IN 36 BITS
	.MOVE	T1,.PDEBT##(W)	;GET EBOX TICKS
	.ADD	T1,.PDMBT##(W)	;COMPUTE EBOX/MBOX HIGH ORDER RUNTIME
	MULI	T1,RTUPS##	;CONVERT TO HIGH PRECISION UNITS
	ADD	T2,T3		;ADD LOW ORDER PART FROM T3
	JRST	JOBTM2		;GO JOIN COMMON CODE AGAIN
JOBTM1:>;END FTEMRT
	.MOVE	T1,.PDTTM##(W)	;TOTAL JOB RUNNING TIME
	MULI	T1,RTUPS##	;EXPAND TO FULL PRECISION
	.ADD	T2,.PDTT2##(W)	;ADD JIFFY FRACTION
JOBTM2:	TLZE	T2,(1B0)	; DOUBLE PRECISION
	AOS	T1
	POP	P,T3
	DIV	T1,T3
	POPJ	P,
JOBTM3:	SETZM	(P)		;RETURN ZERO
	JRST	TPOPJ##


;RETURN TIME OF DAY IN MILLISECONDS


MSTIME:	MOVE	T1,TIME##	;USE APR CLOCK BECAUSE IT HAS BETTER LONG
				; TERM ACCURACY
	IMULI	T1,^D1000	;CONVERT TO MILLISECONDS
	IDIV	T1,TICSEC##
	JRST	STOTAC##
SLEEPF::
	PUSH	P,F		;PRESERVE F
	PUSHJ	P,SLEEP		;ZZZZZ
	JRST	FPOPJ##		;RESTORE F AND RETURN
	SUBTTL	SLEEP SERVICE FOR SLEEP UUO, DTA, MTA AND SCNSER.

;PUT JOB TO SLEEP FOR NSECONDS
;CALL	CALL AC,[SIXBIT /SLEEP/]
;AC=XWD LOC,N   N=NUMBER OF SECONDS TO SLEEP
;IF LH(AC)NON-0, SLEEP ONLY IF LOC THROUGH LOG+17
; MATCHES THE CURRENT JOBSTS ON THAT CHAN, OR IS 0

SLEEP::
	IMUL	T1,TICSEC##	;CONVERT TO TICKS
	ANDI	T1,7777
	TDZA	F,F		;LET WORLD KNOW THIS ISN'T AN I/O UUO
HSLEEP:	TLO	T1,(1B0)	;FLAG IT'S FROM HIBER
MSLEEP:	TRNN	T1,7776		;0 TIME?(CHECK ONLY 12 BITS)
	HRRI	T1,2		;YES. SLEEP 1 JIFFY
	PUSH	P,T1		;SAVE SLEEP TIME
	PUSH	P,W		;SAVE W FOR DTASRN WHERE IT POINTS
				; TO CONTROLER DATA BLOCK
	PUSHJ	P,FNPDBS##	;FIND THE PDB OR STOP
	.LDB	T2,PDYIPT##	;GET PROTECT TIME
	CAIGE	T2,(T1)		;SLEEPING LONGER THAN PROTECT TIME?
	PUSHJ	P,CLRIPT##	;YES. CLEAR PROTECT TIME
	POP	P,W

	HRLI	T1,CTXWKJ##	;ADR. IN RUNCSS WHEN JOB WAKES UP
	MOVEI	T2,CLKR
	TDNE	T2,JBTSTS##(J)	;DOES THIS JOB HAVE A CLOCK QUEUE
				; REQUEST IN CLOCK QUEUE?
	JRST	XSLEEP		;YES, DO NOT PUT ANOTHER ONE IN
SSLEEP:	MOVE	T2,.CPJCH##	;NO, GET JCH TO AWAKEN
	SYSPIF
	IDPB	T1,CLOCK##
	IDPB	T2,CLOCK##
	SYSPIN
	SETOM	CLKNEW##	;NEW ENTRY HAS BEEN MADE
	JRST	SLPNAP		;SET JOB STATUS WORD SO JOB WILL NOT RUN
XSLEEP:	MOVE	T2,T1		;TIME TO SLEEP
	MOVE	T1,.CPJCH##	;JCH TO AWAKEN
	PUSHJ	P,CLKCHG##	;FIX UP THE CLOCK REQUEST
	  JRST	SSLEEP		;NO ENTRY FOUND IN THE CLOCK QUEUE
				; SO MAKE ONE NOW

SLPNAP:	POP	P,T1		;RESTORE SLEEP TIME
	DMOVEM	16,.JDAT+JOBDAC##+16 ;[~~] SETSTT RESTORES 16&17 FROM HERE.
	MOVEI	T2,JIFSEC##	;GET SECONDS WORTH OF JIFFIES
	JUMPL	T1,SETHBR##	;DON'T RESTORE SLPQ/NAPQ IF HIBER (HSLEEP)
	CAILE	T2,(T1)		;SLEEPING LONGER THAN A SECOND?
	JRST	SETNAP##	;NO, JUST GIVE THIS JOB A NAP
	JRST	SETSLP##	;YES, PUT THIS JOB TO SLEEP
	SUBTTL	PEEK UUO

;PEEK INTO MONITOR UUO
;CALL	MOVEI	AC,<MONITOR ADDRESS>
;	CALL	AC,[SIXBIT .PEEK.]


IFN FTPEEKSPY,<			;PEEK AND SPY
UPEEK:	JUMPL	T1,RTZER	;RETURN 0 IF NEGATIVE ARGUMENT
	MOVE	T2,T1		;SAVE ARG
	MOVSI	T1,PVSPYA	;SEE IF USER MAY SPY ON ALL CORE
	PUSHJ	P,PRVBIT##	;..
	  JRST	GOPEEK		;YES OK
	JUMPL	P1,RTZER	;PHYSICAL ONLY REQUIRES PEEK ON ALL
				; OF CORE PRIVILEGES
	MOVSI	T1,PVSPYM	;NO.  MAY HE SPY ON MONITOR?
	PUSHJ	P,PRVBIT##	;..
	  JRST	PEEK1		;YES
	JRST	RTZER		;NO.  ERROR, RETURN 0.

PEEK1:	MOVE	T3,T2		;COPY ADDRESS
IFE FTXMON,<
	HLRZ	T1,T3		;GET SECTION #
	CAILE	T1,.E0DMP##-.E0STB##	;REASONABLE NUMBER?
	 JRST	RTZER		;NO, RETURN ERROR
	TLZ	T3,-1		;IGNORE SECTION NUMBER FOR NOW
>
	CAMGE	T3,SYSSIZ##	;IS HE ASKING FOR LEGAL VALUE?
	  JRST	GOPEK1		;YES
	CAIL	T3,MONORG##	;IS THIS IN THE
	CAML	T3,MONVFF##	; HISEG
	  JRST	RTZER		; NO
GOPEEK:	JUMPGE	P1,GOPEK1	;VIRTUAL
	CAMGE	T2,MEMSIZ##	;IF PHYSICAL, IS IT LEGAL?
GOPEK1:	PUSHJ	P,PPPADR	;IF PHYSICAL ONLY, GET VIRTUAL ADR
	  JRST	RTZER
	MOVE	T1,0(T2)	;YES.  GET WORD
	JRST	STOTAC##	;RETURN IT TO USER IN AC.

>	;END IFN FTPEEKSPY
	SUBTTL	POKE. UUO
;POKE. -- PRIVILEGED UUO TO ALTER THE MONITOR
;CALL:	MOVE	AC,[3,,BLOCK]
;	POKE.	AC,
;	ERROR
;	OK
;ERROR RETURN WITH AC UNCHANGED IF NOT IMPLEMENTED
;	AC=0 IF NOT PRIVILEGED
;	AC=1 IF BAD MATCH
;	AC=2 IF BAD ADDRESS
;
;BLOCK:	LOCATION
;   +1	OLD VALUE
;   +2	NEW VALUE
IFN	FTPOKE,<
POKE:	PUSHJ	P,SAVE2##	;SAVE P1-P2
	MOVE	P2,T1		;SAVE ARGUMENT
	MOVSI	T1,JP.POK	;CHECK FOR POKE
	PUSHJ	P,PRVBIT##	;  PRIVILEGES
	  CAIA
	JRST	RTZER		;NO--BOMB USER
	HRR	M,P2		;POINT TO BLOCK
	PUSHJ	P,GETWDU##	;GET LOCATION
	CAIL	T1,MONORG##	;BELOW THE BOTTOM OF THE MONITOR VIRTUAL ADDRESS SPACE?
	CAML	T1,MONVFF##	;BELOW THE TOP OF THE MONITOR VIRTUAL ADDRESS SPACE?
	CAIA
	JRST	POKE0
	JUMPGE	P1,POKE0	;ALLOW IF VIRTUAL ADDRESS
	CAILE	T1,17		;CHECK ADDRESS
	CAML	T1,MEMSIZ##	;  SEE IF LEGAL
	PJRST	ECOD2##		;NO--BOMB USER WITH ERROR 2
POKE0:	MOVE	T2,T1
	MOVE	P2,T2
	PUSHJ	P,PPPADR	;GET VIRTUAL ADR IF ARG IS PHYSICAL ADR
	  JRST	ECOD2##
	MOVE	P1,T2		;SAVE ADDRESS
	PUSHJ	P,GETWD1##	;GET USER'S IDEA OF OLD CONTENTS
	MOVE	T4,T1		;SAVE IT
	PUSHJ	P,GETWD1##	;GET NEW VALUE
	PUSHJ	P,POKADR	;COMPUTE ADDRESS
POKE1:	SYSPIF			;TO BE SAFE
	CAME	T4,(P1)		;COMPARE OLD VALUE
	JRST	POKE.1		;FAIL--BOMB USER
	MOVEM	T1,(P1)		;WIN--STORE
	SYSPIN			;TURN ON SYSTEM
	AOS	LASPUC##	;INCREMENT COUNT OF NO. OF POKE UUOS
	HRLM	J,LASPUC##	;ALSO STORE JOB NO WHICH POKED LAST
	MOVEM	P2,LASPOK##	;SAVE LOCATION CHANGED TOO (LEAVE ROOM FOR 22 BIT ADR)
				; USEFUL IN CASE OF CRASH CAUSED BY POKE
	MOVE	T1,[.SWEPK,,.ERSWE] ;EVENT,,ERROR CODES FOR DAEMON
	HRRZ	U,P2		;SECOND WORD OF ERPTBK
	HLRZ	F,P2		;IS ADDRESS POKED
	PUSHJ	P,DAERPT##	;TELL DAEMON TO LOG IT

	SETZ	F,		;NOT AN I/O UUO
	JRST	CPOPJ1##	;SKIP RETURN

POKE.1:	SYSPIN			;TURN ON SYSTEM
	PJRST	ECOD1##		;RETURN CODE 1
>
IFE FTPOKE,<POKE==CPOPJ##>

;SUBROUTINE TO COMPUTE ADDRESS FOR POKE OR SNOOP

POKADR:	CAIL	P1,MONORG##	;BELOW THE HIGH SEGMENT?
	CAML	P1,MONVFF##	;OR ABOVE THE HIGH SEGMENT?
	POPJ	P,		;YES, MUST BE MAPPED ONE-TO-ONE
	MOVE	T2,P1		;MONITOR VIRTUAL ADDRESS
	LSH	T2,W2PLSH##
	HRLI	T2,(POINT 36,0,35)

	ADD	T2,.CPMAP##	;RELOCATE FOR THIS CPU
	LDB	T3,T2		;GET CONTENTS OF EXEC MAP SLOT CORRESPONDING TO THE PAGE
IFN FTKL10&FTMP,<
	TDZE	T3,[PM.CSH]	;CACHED?
	PUSHJ	P,UNCACH##	;UNCACHE THE PAGE FOR ALL CPUS
>
	TDO	T3,[PM.WRT]	;ALLOW WRITING
	MOVEM	T3,.UPMP+.UMTMP

	MOVEI	T2,.TEMP/PAGSIZ##;VIRTUAL PAGE NUMBER TO USE IN PER-PROCESS MAPPED ADDRESS
	DPB	T2,[POINT 9,P1,26] ;MONITOR VIRTUAL ADDRESS FOR POKE/SNOOP
	CLRPGT	(0)		;CLEAR PAGING MEMORY SO NEW MAPPING IS USED
	POPJ	P,		;AND RETURN
;SUBROUTINE TO MAKE A PHYSICAL ADDRESS ADDRESSABLE IF PHYSICAL ONLY
; UUO OR UUO ARGUMENT IS .GT. 256K.
;
;CALL WITH (T2) = PHYSICAL ADDRESS
;RETURNS WITH (T2) = VIRTUAL ADDRESS WHICH MAPS TO PHYSICAL ADDRESS
IFN FTPEEKSPY!FTPOKE,<
PPPADR:	MOVE	T1,T2
	SKIPGE	P1		;PHYSICAL ONLY UUO?
	JRST	PPPAD1		;NO
	PUSHJ	P,PPPV2P
	  POPJ	P,
	TLNN	T2,-1
	JRST	CPOPJ1##

PPPAD1:	LSH	T1,W2PLSH##	;PAGE NUMBER
	HRLI	T1,(<PM.DCD>B2+PM.WRT+PM.PUB)
	MOVEM	T1,.UPMP+.UMTMP

	ANDI	T2,PG.BDY##	;COMPUTE VIRTUAL ADDRESS OF LOC
	IORI	T2,.TEMP
	CLRPGT	(0,.TEMP)
	JRST	CPOPJ1##
PPPV2P::SE1ENT
IFE FTXMON,<
	HLRZ	T1,T2		;GET "SECTION" NUMBER
	CAIN	T1,.E0DMP##-.E0STB##	;IS THIS "DECNET" CONTEXT?
	 JRST	[DNCALL	PPPVP1	;YES, MUST DO THE MAP IN DECNET CONTEXT
		 POPJ	P,	;RETURN ERROR
		 JRST	CPOPJ1##]	;RETURN PHYSICAL ADDRESS
PPPVP1:>;FTXMON
	MAP	T1,(T2)
	PUSHJ	P,FLTCHK##
 	  POPJ	P,
	TLZ	T1,777760
	JRST	CPOPJ1##
>
	SUBTTL	SNOOP. UUO - INSERT BREAK POINTS IN THE MONITOR

;UUO ALLOWS A PROGRAM TO INSERT BREAK POINTS IN THE MONITOR
; USEFUL FOR PERFORMANCE ANALYSIS, FAULT INSERTION, TRACE FUNCTIONS, ETC.
;CALLING SEQUENCE:
;	MOVE	AC,[FUNCTION,,ADDRESS]
;	SNOOP.	AC,
;	  ERROR RETURN
;	NORMAL RETURN

SNOOP:	HLRZ	U,T1		;FUNCTION
	CAILE	U,NLSNOP	;IS IT LEGAL?
	JRST	SNPIAL		;NO, ILLEGAL ARGUMENT LIST
	PUSHJ	P,PRUSET	;T1 = LENGTH OF THE ARGUMENT LIST
	  JRST	SNPNPV		;NOT PRIVILEGED
	JRST	@SNPDSP(U)	;DISPATCH

SNPDSP:	SNPDBP			;(0) DEFINE BREAK POINTS
	SNPIBP			;(1) INSERT BREAK POINTS
	SNPRBP			;(2) REMOVE BREAK POINTS
	SNPUBP			;(3) UNDEFINE BREAK POINTS
	SNPNUL			;(4) NULL FUNCTION. FOR BREAKPOINTS.
NLSNOP==.-SNPDSP-1
Comment	@
Usefull labels for Breakpoints:
BP$000	Gets called by the .SONUL breakpoint function. Usefull for being
	able to execute code at UUO level.
BP$001	Gets called right before the breakpoints are removed. Usefull for
	installing cleanup code which gets called on a reset.
	@

;ERROR RETURNS FROM THE SNOOP UUO
SOIAL%==1
SONPV%==2
SOSAS%==3
SOMBX%==4
SOIBI%==5
SONFS%==6
SOADC%==7
SOINL%==10
SOWMS%==11

	ERCODE	SNPIAL,SOIAL%	;ILLEGAL ARGUMENT LIST
	ERCODE	SNPNPV,SONPV%	;NOT PRIVILEGED
	ERCODE	SNPSAS,SOSAS%	;SOMEONE IS ALREADY SNOOP.'ING
	ERCODE	SNPMBX,SOMBX%	;MAXIMUM NUMBER OF BREAKPOINTS EXCEEDED
	ERCODE	SNPIBI,SOIBI%	;FUNCTION ILLEGAL BECAUSE BREAKPOINTS ALREADY INSERTED
	ERCODE	SNPNFS,SONFS%	;NO MONITOR FREE CORE
	ERCODE	SNPADC,SOADC%	;ADDRESS CHECK
	ERCODE	SNPINL,SOINL%	;ILLEGAL FUNCTION IF NOT LOCKED
	ERCODE	SNPWMS,SOWMS%	;WRONG MONITOR CHECKSUM

;OFFSETS IN BREAKPOINT CODE BLOCK
SNPAOS==0			;AOS .+SNPCNT
SNPUSI==1			;USER SUPPLIED INSTRUCTION
SNPSER==2			;SOSA AT ERROR RETURN OF USER INSTRUCTION
SNPSNR==3			;SOSA AT NORMAL RETURN OF USER INSTRUCTION
SNPRMI==4			;REPLACED MONITOR INSTRUCTION
SNPJER==5			;JRST AT ERROR RETURN OF MONITOR INSTRUCTION
SNPJNR==6			;JRST AT NORMAAL RETURN OF MONITOR INSTRUCTION
SNPCNT==7			;CURRENT USE COUNT FOR THIS BREAKPOINT
SNPBCB==^D8			;SIZE OF BREAKPOINT CODE BLOCK
;HERE TO DEFINE BREAK POINTS (FUNCTION 0)

SNPDBP:	SYSPIF			;INTERLOCK SYSTEM
	SKIPE	SYSBPJ##	;SNOOP FACILITY ALREADY IN USE?
	CAMN	J,SYSBPJ##	;YES, IN USE BY THIS JOB?
	CAIA			;FREE OR IN USE BY THIS JOB, ALL IS WELL
	JRST	[SYSPIN		;UNLOCK
		JRST SNPSAS]	;SOMEONE ALREADY SNOOPING
	MOVEM	J,SYSBPJ##	;RESERVE THE SNOOP FACILITY FOR THIS JOB
	SYSPIN			;UNLOCK THE SYSTEM AND PROCEDE
	JUMPLE	T1,[PUSHJ P,RTNBPS ;NEGATIVE OR ZERO ARGUMENT LIST LENGTH IS ILLEGAL
		JRST SNPIAL]	;RETURN BREAK POINTS AND GIVE ERROR RETURN
	TRNE	T1,1		;MUST BE ODD
	CAIGE	T1,3		;AND GE 3
	JRST	[PUSHJ P,RTNBPS	;RETURN BREAK POINTS
		JRST SNPIAL]	;AND GIVE ILLEGAL ARGUMENT LIST ERROR RETURN
	HRRZ	T2,SYSBPP##	;NUMBER OF BREAK POINTS DEFINED SO FAR
	LSH	T2,1		;TIMES 2 WORDS PER ARGUMENT
	MOVNS	T2		;MINUS TWO TIMES THE NUMBER OF B.P.S ALREADY DEFINED
	CAILE	T1,2*MAXNBP##+1(T2)
	JRST	SNPMBX		;MAXIMUM NUMBER OF BREAK POINTS EXCEEDED
	PUSHJ	P,CKBINS	;SEE IF BREAK POINTS HAVE BEEN INSERTED
	  JRST	SNPIBI		;THEY HAVE, ILLEGAL FUNCTION IF BREAK POINTS ARE INSERTED
	PUSHJ	P,SAVE2##	;SAVE P1-P2
	SOS	P1,T1		;CHECKSUM WORD
	LSH	P1,-1		;TWO WORDS PER BREAK POINT
	PUSHJ	P,GETWR1##	;GET THE MONITOR CHECKSUM
	  JRST	[PUSHJ P,RTNBPS	;ADDRESS CHECK, RETURN BREAK POINTS
		JRST SNPADC]	;AND GIVE AN ERROR RETURN
	CAME	T1,MSTCKS##	;USER SUPPLIED CHECKSUM AGREE WITH  MONITOR COMPUTED ONE?
	JRST	[PUSHJ P,RTNBPS	;NO, RETURN BREAK POINTS
		JRST SNPWMS]	;AND GIVE WRONG MONITOR CHECKSUM RETURN
	HRRZ	T1,SYSBPP##	;CURRENT NUMBER OF BREAK POINTS DEFINED
	JUMPN	T1,[HLRZ P2,SYSBPP##  ;POINTER TO THE BREAK POINT TABLE
		ADDI P2,(T1)	;NEXT FREE SLOT IN BREAK POINT TABLE
		JRST SNPDB1]	;GO DEFINE NEXT BREAK POINT
	MOVEI	T2,MAXNBP##	;NO BREAK POINTS DEFINED YET, ALLOCATE A BREAK POINT TABLE
	PUSHJ	P,GTFWDC##	;GET SPACE
	  JRST	SNPNFS		;NO FUNNY SPACE AVAILABLE
	HRLZM	T1,SYSBPP##	;STORE THE ADDRESS OF THE TABLE, NO B.P.S DEFINED YET
	MOVE	P2,T1		;WORKING INDEX INTO THE TABLE
;HERE WITH P2 = POINTER TO THE BREAK POINT TABLE
;A BREAK POINT CODE BLOCK (BPCB) LOOKS LIKE THIS
;BPCB+SNPAOS	AOS	BPCB+SNPCNT	;EXECUTING BREAK POINT
;BPCB+SNPUSI	USER SUPPLIED BREAK POINT INSTRUCTION
;BPCB+SNPSER	SOSA	BPCB+SNPCNT	;DONE EXECUTION OF BP, NON-SKIP
;BPCB+SNPSNR	SOSA	BPCB+SNPCNT	;DONE EXECUTION OF BP, SKIP
;BPCB+SNPRMI	REPLACED MONITOR INSTRUCTION, 0 IF BPS NOT INSERTED
;BPCB+SNPJER	JRST	BP+1
;BPCB+SNPJNR	JRST	BP+2
;BPCB+SNPCNT	NON-ZERO IF THE BREAK POINT IS CURRENTLY BEING EXECUTED

SNPDB1:	PUSHJ	P,GETWR1##	;MONITOR ADDRESS WHERE BREAK POINT IS TO BE INSERTED
	  JRST	[PUSHJ P,RTNBPS	;;ADDRESS CHECK, RETURN BREAK POINTS
		JRST SNPADC]	;AND GIVE ADDRESS CHECK ERROR RETURN
	TLZ	T1,-1		;CLEAR LH JUNK
	CAIG	T1,17		;TRYING TO INSERT IT IN AN AC?
	JRST	[PUSHJ P,RTNBPS ;YES, RETURN BREAKPOINTS
		 JRST SNPIAL]	;AND GIVE ILL ARG LIST RETURN
	HRLM	T1,(P2)		;STORE MONITOR ADDRESS OF THE BREAK POINT
	MOVEI	T2,SNPBCB	;EIGHT WORDS ARE REQUIRED FOR THE BREAK POINT CODE
	PUSHJ	P,GETWDS##	;GET THE SPACE
	  JRST	[PUSHJ P,RTNBPS	;NOT AVAILABLE, RETURN BREAK POINTS
		JRST SNPNFS]	;AND GIVE NO FREE SPACE ERROR RETURN
	HRRM	T1,(P2)		;STORE ADDRESS OF THE CODE BLOCK ASSOCIATED WITH THIS B.P.
	AOS	SYSBPP##	;ONE MORE BREAK POINT DEFINED
	PUSHJ	P,GETWR1##	;BREAK POINT INSTRUCTION
	  JRST	[PUSHJ P,RTNBPS	;ADDRESS CHECK, RETURN BREAK POINTS
		JRST SNPADC]	;AND GIVE ADDRESS CHECK ERROR RETURN
	HRRZ	T2,(P2)		;RESTORE ADDRESS OF THE CODE BLOCK
	MOVSI	T3,(AOS)	;AOS
	HRRI	T3,SNPCNT(T2)	; BP CODE + SNPCNT
	MOVEM	T3,SNPAOS(T2)	;STORE THAT TO BE EXECUTED BEFORE BP INSTRUCTION
	SETZM	(T3)		;BREAK POINT ISN'T IN EXECUTION
	MOVEM	T1,SNPUSI(T2)	;STORE THE USER SUPPLIED BREAK POINT INSTRUCTION
	SETZM	SNPRMI(T2)		;INDICATE THAT BREAK POINT HAS NOT BEEN INSERTED YET
	HRLI	T3,(SOSA)	;SOSA BP CODE + SNPCNT
	MOVEM	T3,SNPSER(T2)	;BREAK POINT INSTRUCTION DIDN'T SKIP
	MOVEM	T3,SNPSNR(T2)	;BREAK POINT INSTRUCTION SKIPPED
	MOVSI	T1,(JRST)	;UNCONDITIONAL JUMP
	HLRZ	T3,(P2)		;MONITOR ADDRESS OF THE BREAK POINT
	ADDI	T1,1(T3)	;BREAK POINT ADDRESS + 1
	MOVEM	T1,SNPJER(T2)	;JRST BP+1
	ADDI	T1,1		;BREAK POINT ADDRESS + 2
	MOVEM	T1,SNPJNR(T2)	;JRST BP+2
IFN FTKL10&FTMP,<
	PUSH	P,P1		;SAVE COUNT
	HLRZ	P1,(P2)		;EXEC VIRTUAL ADDRESS OF THE B.P.
	PUSHJ	P,POKADR	;MAKE SURE THAT THE PAGE IS UNCACHED IN ALL MAPS
	POP	P,P1		;RESTORE COUNT
>
	AOS	P2		;NEXT SLOT IN THE BREAK POINT TABLE
	SOJG	P1,SNPDB1	;LOOP OVER THE USER'S ENTIRE ARGUMENT LIST
	JRST	CPOPJ1##	;AND GIVE GOOD RETURN
;HERE TO INSERT BREAK POINTS (FUNCTION 1)

SNPIBP:	PUSHJ	P,LOKEVC##	;JOB MUST BE LOCKED CONTIGUOUSLY IN EVM
	  JRST	SNPINL		;ITS NOT, ILLEGAL IF NOT LOCKED ERROR RETURN
	CAME	J,SYSBPJ##	;IS THIS JOB THE CURRENT OWNER OF THE SNOOP FACILITY?
	JRST	SNPSAS		;NO, SOMEONE ELSE IS ALREADY  SNOOPING
	PUSHJ	P,CKBINS	;HAVE BREAK POINTS ALREADY BEEN INSERTED?
	  JRST	SNPIBI		;YES, ILLEGAL FUNCTION IF BREAK POINTS ARE INSERTED
	SETZ	F,		;F=0, U=FUNCTION
	MOVE	T1,[.SWESN,,.ERSWE] ;EVENT,, SOFTWARE EVENT REPORT
	PUSHJ	P,DAERPT##	;GET IT RECORDED IN THE ERROR FILE

	PUSHJ	P,SAVE4##	;SAVE WORKING ACS
	HRRZ	P2,SYSBPP##	;NUMBER OF BREAK POINTS WHICH HAVE BEEN DEFINED
	HLRZ	P3,SYSBPP##	;ADDRESS OF THE BREAK POINT TABLE
	MOVSI	P4,(JRST)	;BREAK POINT INSTRUCTION IS A JRST TO THE BREAK POINT CODE
	SYSPIF			;LOCK SYSTEM
SNPIB1:	MOVS	P1,(P3)		;ADDRESS OF THE BREAK POINT
	MOVE	T1,(P1)		;MONITOR INSTRUCTION
	MOVSS	P1		;ADDRESS OF THE BREAK POINT CODE
	HRRI	P4,(P1)		;JRST TO THE BREAK POINT CODE
	MOVEM	T1,SNPRMI(P1)	;STORE MONITOR INSTRUCTION IN BREAK POINT CODE
	HLRZS	P1		;VIRTUAL ADDRESS OF THE BREAK POINT
	PUSHJ	P,POKADR	;MAKE IT WRITABLE
	MOVEM	P4,(P1)		;STORE JRST TO BREAK POINT CODE AT THE BREAK POINT
	AOS	P3		;NEXT ENTRY IN THE BREAK POINT TABLE
	SOJG	P2,SNPIB1	;INSERT ALL OF THE BREAK POINTS
	SYSPIN			;NOW, UNLOCK THE SYSTEM
	JRST	CPOPJ1##	;AND GIVE THE USER THE GOOD RETURN
;HERE TO REMOVE BREAK POINTS (FUNCTION 2)

SNPRBP:	CAME	J,SYSBPJ##	;THIS JOB OWN THE BREAK POINT FACILITY
	JRST	SNPSAS		;NO, SOMEONE ELSE IS SNOOPING
REMBPS:	PUSHJ	P,SAVE4##	;SAVE WORKING ACS
	HRRZ	P2,SYSBPP##	;NUMBER OF BREAK POINTS DEFINED
	HLRZ	P3,SYSBPP##	;ADDRESS OF THE BREAK POINT TABLE
	SYSPIF			;NO INTERRUPTIONS
REMBP1:	MOVE	P1,(P3)		;ADDRESS OF BREAK POINT CODE BLOCK
	MOVE	P4,SNPRMI(P1)	;ORIGINAL MONITOR INSTRUCTION
	HLRZS	P1		;MONITOR ADDRESS OF THE BREAK POINT
	PUSHJ	P,POKADR	;MAKE BREAK POINT LOCATION WRITABLE
	MOVEM	P4,(P1)		;STORE ORGINAL MONITOR INSTRUCTION BACK AT B.P. ADDRESS
	MOVE	P1,(P3)		;ADDRESS OF THE BREAK POINT CODE BLOCK
IFE FTMP,<
	SETZM	SNPRMI(P1)	;INDICATE THAT THE BREAK POINT IS NO LONGER INSERTED
>
	AOS	P3		;NEXT ENTRY IN THE BREAK POINT TABLE
	SOJG	P2,REMBP1	;REMOVE ALL OF THE BREAK POINTS
	SYSPIN			;ALLOW INTERRUPTS

;NOW LOOP OVER ALL BREAK POINTS MAKING SURE THEY AREN'T
; CURRENTLY IN EXECUTION ON SOME OTHER CPU BEFORE
; ACTUALLY INDICATING BREAK POINT HAS BEEN REMOVED
; IF SOME CPU IS EXECUTING THE BREAK POINT, WAIT UNTIL IT'S DONE

IFN FTMP,<
	HRRZ	P2,SYSBPP##	;NUMBER OF BREAK POINTS DEFINED
	HLRZ	P3,SYSBPP##	;ADDRESS OF BREAK POINT TABLE
REMBP2:	HRRZ	P1,(P3)		;ADDRESS OF BREAK POINT CODE BLOCK
REMBP3:	SKIPN	SNPCNT(P1)	;BREAK POINT CURRENTLY BEING EXECUTED?
	JRST	REMBP4		;NO, REMOVE IT
	MOVEI	T1,0		;YES, SLEEP FOR A TIC
	PUSHJ	P,SLEEPF	;ZZZZZZ
	JRST	REMBP3		;CHECK AGAIN
REMBP4:	SETZM	SNPRMI(P1)	;REMOVE THE BREAK POINT
	AOS	P3		;NEXT ENTRY IN BREAK POINT TABLE
	SOJG	P2,REMBP2	;LOOP OVER ALL BREAK POINTS
>
	JRST	CPOPJ1##	;AND GIVE THE USER THE OK RETURN
;HERE TO UNDEFINE BREAK POINTS (FUNCTION 3)

SNPUBP:	CAME	J,SYSBPJ##	;CURRENT JOB OWN THE SNOOP FACILITY?
	JRST	SNPSAS		;NO, SOMEONE ELSE IS ALREADY SNOOPING
	PUSHJ	P,CKBINS	;ARE BREAK POINTS INSERTED?
	  JRST	SNPIBI		;YES, ILLEGAL IF BREAK POINTS ARE INSERTED
	AOS	(P)		;SET FOR SKIP RETURN
	PJRST	RTNBPS

;THE NULL FUNCTION
SNPNUL:	CAME	J,SYSBPJ##	;THIS BEING EXECUTED BY SNOOP OWNER?
	JRST	SNPSAS		; NOPE. SOMEONE ELSE.
BP$000:	POPJ	P,		;FINISHED
	JRST	CPOPJ1##	;IN CASE SNOOPED INSTRUCTION SKIPS.

;MISC. SUBROUTINES

RTNBPS:	PUSHJ	P,SAVE2##	;SAVE P1-P2
BP$001:!HRRZ	P1,SYSBPP##	;NUMBER OF DEFINED BREAK POINTS
	HLRZ	P2,SYSBPP##	;ADDRESS OF THE BREAK POINT TABLE
	JUMPE	P1,RTNBP2	;JUMP IF NO BREAK POINTS CURRENTLY DEFINED
RTNBP1:	MOVEI	T1,SNPBCB	;EIGHT WORDS PER BREAK POINT CODE BLOCK
	HRRZ	T2,(P2)		;ADDRESS OF THIS BREAK POINT CODE BLOCK
	PUSHJ	P,GIVWDS##	;RETURN THE MONITOR FREE CORE
	AOS	P2		;NEXT ENTRY IN THE BREAK POINT TABLE
	SOJG	P1,RTNBP1	;LOOP OVER THE ENTIRE BREAK POINT TABLE
RTNBP2:	MOVEI	T1,MAXNBP##	;LENGTH OF THE BREAK POINT TABLE
	HLRZ	T2,SYSBPP##	;ADDRESS OF THE BREAK POINT TABLE
	SKIPE	T2		;IF A TABLE HAS BEEN ALLOCATED,
	PUSHJ	P,GVFWDS##	; RETURN THE SPACE
	SETZM	SYSBPJ##	;NO LONGER ANYONE SNOOPING
	SETZM	SYSBPP##	;AND NO BREAK POINT TABLE IS ALLOCATED
	POPJ	P,		;RETURN

CKBINS:	HRRZ	T2,SYSBPP##	;NUMBER OF BREAK POINTS
	JUMPE	T2,CPOPJ1##	;BREAK POINTS AREN'T INSERTED IF NONE ARE DEFINED
	HLRZ	T2,SYSBPP##	;ADDRESS OF THE BREAK POINT TABLE
	HRRZ	T2,(T2)		;ADDRESS OF BREAK POINT CODE BLOCK FOR FIRST BREAK POINT
	SKIPN	SNPRMI(T2)	;IF NON-ZERO, BREAK POINTS HAVE BEEN INSERTED
	AOS	(P)		;ZERO, BREAK POINT IS DEFINED BUT NOT INSERTED
	POPJ	P,		;GIVE INSERTED OR NOT INSERTED RETURN

SNPRST:	CAME	J,SYSBPJ##	;DOES JOB DOING THE RESET OWN THE SNOOP FACILITY?
	POPJ	P,		;NO, NOTHING TO DO
	PUSHJ	P,CKBINS	;YES, ARE THE BREAK POINTS INSERTED?
	  PUSHJ	P,REMBPS	;YES, REMOVE THEN
	  JFCL			;FOR SKIPS
	PJRST	RTNBPS		;BREAK POINTS ARE REMOVED, NOW UNDEFINE THEM
SUBTTL PERF. MUUO

;THE PERF. MUUO IS INTENDED TO BE A GENERAL PURPOSE CALL
; TO EXECUTE SYSTEM PERFORMANCE MEASURING FUNCTIONS.  THESE FUNCTIONS
; INCLUDE HANDLING OF THE KL10 PERFORMANCE METER.  THE METER IS
; CONSIDERED A RESOURCE WHICH CAN BE USED ONLY BY ONE PROCESS AT A TIME.
;
;CALL TO THE PERF. MUUO:
;
;	MOVE	AC,[XWD N,ADDR]		;COUNT OF FUNCTIONS, ADDRESS
;	PERF.	AC,			;OR CALLI AC,***
;	  <ERROR RETURN>		;ERROR CODE RETURNED IN AC
;	<SUCCESSFUL RETURN>
;
;ADDR:	XWD	FUNCTION,BLOCK
;	XWD	FUNCTION,BLOCK
;		.
;		.
;		.			;N FUNCTIONS
;
;THE LOCATION BLOCK ALWAYS CONTAINS COUNT OF THE NUMBER OF
; WORDS FOLLOWING IN THE BLOCK.  THE REST OF THE
; BLOCK IS FUNCTION SPECIFIC.
;
;THE MAIN LOOP OF THE PERF. UUO IS RESPONSIBLE FOR SETTING UP
; P2 FROM THE ITEM COUNT AT LOCATION BLOCK, CHECKING AND DISPATCHING
; FROM THE FUNCTION NUMBERS PROVIDED, AND SETTING UP THE RIGHT HALF
; OF AC M TO POINT TO BLOCK OF THE CURRENT FUNCTION IT IS EXECUTING.
; IT EXPECTS P1 TO BE PRESERVED BY THE FUNCTION EXECUTION ROUTINES, SINCE
; P1 IS USED AS AN AOBJN POINTER TO THE LIST OF FUNCTIONS TO BE EXECUTED.
;
;THE FUNCTION EXECUTION ROUTINES USE ACS T1-T4, AND A SPECIAL ARGUMENT
; GETTER THAT THEY CALL USES P2 TO DETERMINE IF THE ARGUMENTS IN BLOCK
; ARE EXHAUSTED OR NOT.  THE ROUTINES THAT HANDLE THE KL10 PERFORMANCE
; METER TAKE ADVANTAGE OF THE FACT THAT ZERO IS ALWAYS DONT CARE BY
; SIMPLY RETURNING ZERO IF THE ARGUMENT IS NOT PRESENT.

;INTERN THE ERROR RETURNS SO THE MODULES CAN CALL THEM


	INTERN	PREICT,PRENXC,PREIPM,PREMNS,PREMIU,PREMAS,PREBJN
	INTERN	PREMNR,PREFNI,PREBFN,PREMBP

UPERF.::PUSHJ	P,SAVE2##	;P1 AND P2 WILL BE USED
	MOVE	P1,T1		;SAVE C(AC)
	PUSHJ	P,PRVJ##	;PRIVS?
	  CAIA			;YES
	JRST	PREMBP		;**MUST BE PRIVILEGED**
	HLRE	T1,P1		;GET POSITIVE COUNT IN T1
	JUMPLE	T1,CPOPJ1##	;FINISHED IF .LE. ZERO
	MOVNS	T1		;MAKE AOBJN POINTER
	HRL	P1,T1		;PUT -COUNT IN LH OF P1, AOBJN POINTER
UPERF1:	HRR	M,P1		;GET NEXT FUNCTION
	PUSHJ	P,GETWDU##	;GET FUNCTION,,BLOCK
	HRR	M,T1		;PUT ADDRESS OF BLOCK IN M
	HLRZ	T4,T1		;SAVE FUNCTION NUMBER IN T4
	CAILE	T4,PRFMAX	;IS THE FUNCTION DEFINED?
	  JRST	PREFNI		; NO, GIVE HIM UNIMPLEMENTED ERROR
	PUSHJ	P,GETWDU##	;GET COUNT OF ITEMS IN BLOCK
				;M NOW POINTS TO BLOCK FOR FUNCTION ROUTINE
	MOVE	P2,T1		;SAVE COUNT IN P2 WHERE IT BELONGS
	ROT	T4,-1		;TAKE INTO ACCOUNT DISPATCH TABLE IS 1/2 WORDS
	MOVE	T3,UPRFDS(T4)	;GET ENTRY
	SKIPL	T4		;SKIP IF ITS THE ODD ENTRY
	MOVSS	T3		;NOT, ITS THE EVEN
	PUSHJ	P,(T3)		;DISPATCH TO PROPER ROUTINE
	  POPJ	P,		;ROUTINE GAVE ERROR RETURN, STOP UUO
	AOBJN	P1,UPERF1	;OK SO FAR, DO MORE FUNCTIONS IF ANY LEFT
	JRST	CPOPJ1##	;EVERYTHING IS BEAUTIFUL (IN ITS OWN WAY)
;DISPATCH TABLE
; HERE WE MUST EITHER EXTERN THE ADDRESS OF THE FUNCTION ROUTINE,
; OR DEFINE THE FUNCTION TO JUMP TO THE ERROR ROUTINE
; THAT INDICATES UNIMPLEMENTED FUNCTION.

IFN FTKL10,<
	EXTERN PMRSET,PMRSTR,PMRRED,PMRSTP,PMRREL
IFN FTRSP,<
	EXTERN PMRBPF,PMRBPN
>;END IFN FTRSP
IFE FTRSP,<
	PMRBPF==PREFNI
	PMRBPN==PREFNI
>;END IFE FTRSP
>;END IFN FTKL10

IFE FTKL10,<
	PMRSET==PREFNI
	PMRSTR==PREFNI
	PMRRED==PREFNI
	PMRSTP==PREFNI
	PMRREL==PREFNI
	PMRBPF==PREFNI
	PMRBPN==PREFNI
>;END IFN FTKL10


UPRFDS:	XWD	CPOPJ##,PMRSET		;(0,1)
	XWD	PMRSTR,PMRRED		;(2,3)
	XWD	PMRSTP,PMRREL		;(4,5)
	XWD	PMRBPF,PMRBPN		;(6,7)

	PRFMAX==<.-UPRFDS>*2-1	;MAXIMUM FUNCTION NUMBER
				;NOTE THAT IF LAST WORD IN DISPATCH
				;TABLE HAS ONLY ONE FUNCTION,
				;THE OTHER SLOT MUST HAVE PREFNI IN IT.
;ERROR RETURNS - USE SYSTEM ERCODE MACRO

	PRFBC%==1
	PRFNC%==2
	PRFIM%==3
	PRFNS%==4
	PRFMB%==5
	PRFAS%==6
	PRFBJ%==7
	PRFMS%==10
	PRFUF%==11
	PRFBF%==12
	PRFNP%==13

	ERCODE	PREICT,PRFBC%	;IMPROPER CPU TYPE
	ERCODE	PRENXC,PRFNC%	;NON-EXISTANT CPU
	ERCODE	PREIPM,PRFIM%	;IMPROPER MODE
	ERCODE	PREMNS,PRFNS%	;METER NOT SETUP
	ERCODE	PREMIU,PRFMB%	;METER BUSY
	ERCODE	PREMAS,PRFAS%	;METER ALREADY STARTED
	ERCODE	PREBJN,PRFBJ%	;BAD JOB NUMBER
	ERCODE	PREMNR,PRFMS%	;METER NOT RUNNING
	ERCODE	PREFNI,PRFUF%	;UNIMPLEMENTED FUNCTION
	ERCODE	PREBFN,PRFBF%	;BAD FUNCTION NUMBER
	ERCODE	PREMBP,PRFNP%	;NO PRIVILEGES
	SUBTTL	DIAG. UUO

IFN FTKS10,<
DIACLR==:CPOPJ##
DIAUUO==CPOPJ##			;NO DIAG. UUO ON THE KS10
>
IFE FTKS10,<
REPEAT 0,<
;FUNCTIONS DEFINED IN FILIO AND TAPUUO:
1	ASSIGN SINGLE UNIT
2	ASSIGN ALL UNITS ON A CHAN/KONTROLLER
3	RELEASE CHANNEL/KONTROLLER AND ALL UNITS
4	SPECIFY CHANNEL PROGRAM
5	RELEASE CHANNEL PROGRAM
6	GET CHANNEL STATUS
7	GET KONTROLLER AND UNIT NUMBERS
12	SPECIFY CHANNEL PROGRAM FOR READ IN REVERSE
15	SHUTDOWN I/O ON TAPE CHANNEL
16	START I/O ON TAPE CHANNEL

FUNCTIONS DEFINED IN UUOCON
10	READ CSB
11	READ DSB
13	ENABLE/DISABLE AUTO LOAD OF DX20'S
14	OBTAIN USER IOT
FUNCTIONS DEFINED IN MOSSER
100	GET MEMORY
101	GIVE MEMORY
FUNCTIONS DEFINED IN KLPSER AND KNISER
22	SET MAINTENANCE MODE
23	CLEAR MAINTENANCE MODE
FUNCTIONS DEFINED IN KLPSER
105	RESET REMOTE SYSTEM
106	START REMOTE SYSTEM
107	PORT COUNTER FUNCTIONS
112	WRITE CI MAINTENANCE DATA
113	READ CI MAINTENANCE DATA
>
DIAUUO:	PUSHJ	P,SAVE4##	;DO THIS NOW
	PUSH	P,T1
	HRR	M,T1		;ADR OF BLOCK
	PUSHJ	P,GETWDU##	;GET ARG
	MOVSI	P4,-DIDSLN	;AOBJN POINTER TO DIAG TABLE
DIAUO1:	LDB	T3,[POINT 9,DIADST(P4),17]	;GET FUNCTION
	CAIE	T3,(T1)		;THIS FUNCTION?
	AOBJN	P4,DIAUO1	;NO
	JUMPGE	P4,[POP  P,T1
		    JRST BADFNC]
	MOVE	P4,DIADST(P4)	;GET DISPATCH WORD
	MOVE	P2,T1		;MOVE FUNCTION TO T1

;IF GOING TO DO IO HE'D BETTER BE ALL IN CORE

	TLNE	P4,(DI.NVR)	;NOT ALLOWED TO BE VIRTUAL?
	SKIPN	.USVRT		;NO, IS HE?
	JRST	DIAUO2		;NOT VIRTUAL OR DON'T CARE
	POP	P,(P)		;FIX STACK
	JRST	DIAVRT		;LOSE
DIAUO2:	TLNN	P4,(DI.UIO)	;GIVE USER I/O ON THIS FUNCTION?
	JRST	DIAUO3		;NO
	SETZ	T1,		;SAY WE WANT USER-IOT
	PUSHJ	P,STOTAC##	;TRPSET CALLS GETTAC
	PUSHJ	P,TRPSTU	;CHECK PRIVS, SET USRIOT
	  JRST	[POP P,(P)	;NO PRIVS, LOSE
		JRST DIANPV]
DIAUO3:	POP	P,T1		;OK, RESTORE ARGUMENT
	TLNE	P4,(DI.UIO)	;DIDN'T CALL TRPSET
	PUSHJ	P,STOTAC##	;TRPSET STORES 0 IN THE AC
	TLNE	P4,(DI.NON)	;CHECK N?
	JRST	DIAUO4		;NO
	HLRE	T2,T1		;NUMBER OF ARGUMENTS
	JUMPGE	T2,WRONGN	;ILLEGAL N
	MOVN	P1,T2		;P1=NUMBER OF ARGS
	CAIGE	P1,2		;LEGAL?
	JRST	WRONGN		;ILLEGAL N
DIAUO4:	HLRZ	T1,P2		;GET POSSIBLE CPU NUMBER
	TLZ	P2,-1		;AND CLEAR THE ARGUMENT
IFE FTMP,<
	TLNE	P4,(DI.CPU)	;WOULD FUNCTION ACCEPT CPU NUMBER?
	JUMPN	T1,DIABAL	;YES, GIVE AN ERROR IF ONE SPECIFIED
>; END IFE FTMP
IFN FTMP,<
	TLNN	P4,(DI.CPU)	;CPU NUMBER SUPPLIED IN FUNCTION WORD?
	JRST	DIAUO5		;NO
	PUSHJ	P,ONCPUS##	;GET ON THAT CPU
	  JRST	DIACNR		;NOT RUNNING
DIAUO5:
>; END IFN FTMP
	TLNN	P4,(DI.KDB!DI.UDB)	;NEED ONE OF THESE?
	JRST	(P4)			;NO
	PUSHJ	P,GETWD1##	;GET KON/UNIT WORD
	LDB	T2,[POINT 7,T1,6] ;CONTROLLER NUMBER
	HLRZ	P3,SYSKON##	;GET FIRST DISK KDB

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

DIADRS:
IFN FTMP,<
	MOVE	T3,KONCAM##(P3)	;RIGHT CPU?
	TDNN	T3,.CPBIT##
	JRST	DIADR1		;NO, KEEP LOOKING
>
IFN FTCIDSK,<
	LDB	T3,KOZKTP##	;GET KONTROLLER TYPE
	CAIN	T3,TYPRA##	;CI DISK?
	JRST	DIADR1		;YES, KEEP LOOKING
>; END IFN FTCIDSK
	HRRZ	T3,P3		;GET KDB ADDRESS
	ADD	T3,KONIIO##(P3)	;POINT AT FIRST IO WORD IN KDB
	LDB	T3,[POINT 7,(T3),9]	;KON NUM FROM KDB
	CAIN	T3,(T2)		;MATCH?
	JRST	DIAUNI		;YES, WE HAVE KON
DIADR1:	HLRZ	P3,KONNXT##(P3)	;NO, STEP TO NEXT
	JUMPN	P3,DIADRS	;AND TEST IT
	SKIPN	W,CNFMTK##	;NOT A DISK, TRY MAGTAPES
	JRST	DIADR5		;NO MAGTAPES, YOU LOSE UNLESS KLIPA
DIADR2:	LDB	T4,[POINT 7,TKBCSO##(W),9]
IFN FTMP,<
	LDB	T3,TKYCPU##	;CPU CONTROLLER LIVES ON
	CAMN	T3,.CPCPN##	;IS IT US?
>
	CAIE	T4,(T2)		;YES, RIGHT CONTROLLER?
	JRST	DIADR4		;NO, TRY NEXT KDB
	SKIPG	TKBUNI##(W)	;MULTI-UNIT CONTROLLER?
	JRST	DIADR3		;NO, USE UNIT NUMBER
	HLRZ	T3,TKBUNI##(W)	;YES. GET THIS KDB'S UNIT NUMBER
	LDB	T4,[POINT 3,T1,29]
	CAIE	T3,(T4)		;RIGHT UNIT (KDB)?
	JRST	DIADR4		;NO. TRY NEXT KDB
	LDB	P3,[POINT 3,T1,35] ;YES. GET SLAVE NUMBER
	CAIA
DIADR3:	LDB	P3,[POINT 3,T1,29] ;GET UNIT NUMBER
	ADDI	P3,TKBUDB##(W)	;POINT TO RIGHT UDB
	SKIPN	U,(P3)		;IS THERE SUCH A UNIT?
	JRST	ILLUNI		;NO, YOU LOSE
	HRROS	U		;YES, INDICATE IT'S A TAPE
	PUSHJ	P,FNDPDS##	;RESET W
	JRST	DIADSP		;AND CALL TAPUUO
DIADR4:	HRRZ	W,TKBKDB##(W)	;STEP TO NEXT TAPE KDB
	JUMPN	W,DIADR2	;TEST IT
				;FALL INTO DIADR5

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;HERE TO TEST IF A KLNI OR KLIPA WAS REQUESTED

DIADR5:	MOVEI	T4,-FSTICD/4(T2) ;GET INTERNAL CHANNEL NUMBER
	SKIPN	P1,.CPCHN##(T4)	;IS THERE A CHANNEL DATA BLOCK?
	JRST	ILLKON		;NO, YOU LOSE
IFN FTENET,<
	CAIN	T4,KNIICH	;KLNI CHANNEL?
	PJRST	KNIDIA##	;DISPATCH TO KNISER
>; END IFN FTENET
IFN FTSCA,<
	CAIN	T4,KLPICH	;KLIPA CHANNEL?
	PJRST	PPDDIA##	;DISPATCH TO KLPSER
>; END IFN FTSCA
	JRST	ILLKON		;NOT KLNI OR KLIPA CHANNEL

DIAUNI:	LDB	T1,[POINT 3,T1,29] ;UNIT
	MOVE	T3,KONTBP##(P3)	;AOBJN POINTER TO UNITS
DIAUN1:	HRRZ	U,(T3)
	LDB	T2,UNYPUN##	;UNIT FROM UDB
	CAMN	T1,T2		;RIGHT ONE?
	JRST	DIAUN2		;YES, SEE IF SAME KON
	AOBJN	T3,DIAUN1	;NO, TRY NEXT
	JRST	ILLUNI		;NO MATCH, YOU LOSE
DIAUN2:	HRRZ	T1,UNIKON##(U)	;ON SAME KONTROLLER?
	CAIE	T1,(P3)
	JRST	ILLUNI		;ILLEGAL UNIT
	JRST	(P4)		;YES, DO IT
;HERE TO GET KONTROLLER/UNIT
DIAKUN:	PUSHJ	P,GETWD1##	;GET DEVICE NAME
	PUSHJ	P,DEVSRG	;FIND IT
IFE FTDUAL,<JRST ILLUNI>	;NO SUCH UNIT
IFN FTDUAL,<JRST DIAALT##>
	MOVEI	P2,7		;SET UP FUNCTION
	MOVE	T2,DEVMOD(F)
	TLNE	T2,DVMTA	;IS IT A MAG TAPE?
	JRST	DSPMTA		;YES
	JRST	DSPDSK		;NO, DISK


;HERE FROM STOP1A ON ^C OR EXIT, HALT,...  ;OR FROM HNGDSK
DIACLR::
IFN FTSCA,<PUSHJ P,PPDCLR##>	;CLEAR STALE STUFF IN PCBS
	PUSH	P,M		;SAVE M
	HRROS	M		;SO DON'T STORE IN USER'S ACS
	PUSHJ	P,TPDSIA##	;START UP TAPE SCHEDULING
	  JFCL
	POP	P,M		;RESTORE M
	PUSHJ	P,FNDPDB##	;FIND FDB
	  POPJ	P,		;THERE ISN'T ONE
	SKIPN	F,.PDDIA##(W)	;DIAG GOING?
	POPJ	P,		;NO
	PUSHJ	P,SAVE3##	;YES, SAVE SOME ACS
	HLL	U,F		;GET DISK/TAPE FLAG
	TDZA	P2,P2		;ENTRY 0 = ^C POINT

DIADSP:	HRRZ	F,.PDDIA##(W)	;SET UP F
	SKIPL	U		;DISK?
DSPDSK:	SKIPA	T2,[DSKDIA##]	;YES
DSPMTA:	MOVEI	T2,MTADIA##	;NO
	PUSHJ	P,(T2)		;DISPATCH TO FILUUO OR TAPUUO
DIANUI::  SKIPA	T1,[XC.UIO]	;LOST - CLEAR USRIOT
	JRST	CPOPJ1##	;;WON - SKIP RETURN
	ANDCAM	T1,.JDAT+JOBPD1##
	MOVSI	T1,NSWP!NSHF	;JOB IS NOW MOVABLE
	LDB	T2,PJOBN##
	ANDCAM	T1,JBTSTS##(T2)
	POPJ	P,

;FINISH UP GET CHANNEL STATS
;ENTER WITH P1=NO OF ARGS, P2=LOC OF ICWA
DIAGCS::MOVEI	T2,-4(P1)	;SAVE NO OF ARGS -4
	HRRZ	T3,(P2)		;SAVE ADDR OF 1ST IOWD
	CAILE	P1,4		;ASKING FOR TOO MUCH?
	MOVEI	P1,4		;YES, MAX HE CAN GET
DIAGC1:	MOVE	T1,(P2)		;GET A WORD FROM LOW CORE
	PUSHJ	P,PUTWD1##	;TELL USER
	SOJLE	P1,DIAGC2	;DONE IF 0
	AOJA	P2,DIAGC1	;GET NEXT WORD
DIAGC2:	JUMPLE	T2,CPOPJ1##	;RETURN IF HE DOESN'T WANT CCWS STORED
DIAGC3:	MOVE	T1,(T3)		;GET A CCW
	PUSHJ	P,PUTWD1##	;GIVE IT TO THE USER
	JUMPE	T1,CPOPJ1##	;RETURN AFTER STORING TERMINATING ZERO
	SOJLE	T2,CPOPJ1##	;RETURN IF COUNT EXHAUSTED
	TLNN	T1,577777	;REAL IOWD?
	SOS	T3,T1		;CHAN JUMP - GET NEW ADDRESS
	AOJA	T3,DIAGC3	;GO GET NEXT IOWD
;HERE FOR THE CODE COMMON TO BOTH READ CPU STATUS BLOCK AND READ
;DEVICE STATUS BLOCK
DIAXSB:	PUSHJ	P,SAVE1##	;SAVE P1
	MOVEI	P1,(T1)		;SAVE FUNCTION
	MOVSI	T1,JP.POK	;MUST HAVE POKE PRIVS OR
	PUSHJ	P,PRVBIT##	;BE [1,2] OR JACCT
	  SKIPA			;HE'S OK
	JRST	DIANPV		;NOT ENOUGH PRIVS
	PUSHJ	P,GETWD1##	;GET CPU NUMBER
	SKIPL	T1		;IF NEGATIVE
	CAIL	T1,CPUN##	;OR GREATER THAN THE NUMBER OF CPUS
	JRST	DIANSC		;IT'S ILLEGAL
IFN FTMP,<
	PUSHJ	P,ONCPUS##	;GET TO THAT CPU
	  JRST	DIACNR		;CPU NOT RUNNING
>
	PJRST	@.+1-10(P1)	;DO THE FUNCTION SPECIFIC STUFF IN COMMON
	EXP	DIACSB##	;(10) READ CPU STATUS BLOCK
	EXP	DIADSB##	;(11) READ DEVICE STATUS BLOCK
;DISPATCH TABLE FOR DIAG

	DEFINE	DIAGDS	(FLAGS,CODE,ADDR)<

		%%FLG==0
	IRP	FLAGS,<
			%%FLG=%%FLG!DI.'FLAGS
		>
	EXP	%%FLG!<<CODE>B17+ADDR>

>
;FLAG BITS:
	DI.KDB==1B0			;NEEDS KONTROLLER
	DI.UDB==1B1			;NEEDS UNIT
	DI.UIO==1B2			;GIVE USER USER I/O
	DI.NVR==1B3			;USER CAN'T BE VIRTUAL
	DI.NON==1B4			;DON'T BOTHER TO CHECK N
	DI.CPU==1B5			;CPU NUMBER SPECIFIED IN LH OF FNC WORD

;NOTE THAT THE DISPATCH ENTRY IS NOT GIVEN FOR DEVICE SPECIFIC FUNCTIONS

DIADST:	DIAGDS	(<KDB,UDB,UIO,NVR>,1,DIADSP)	;ASSIGN UNIT
	DIAGDS	(<KDB,UDB,UIO,NVR>,2,DIADSP)	;ASSIGN ALL UNITS
	DIAGDS	(<KDB,UDB,UIO,NVR>,3,DIADSP)	;RELEASE CHANNEL/KON ALL UNITS
	DIAGDS	(<KDB,UDB,UIO,NVR>,4,DIADSP)	;SPECIFY CHANNEL PROG
	DIAGDS	(<KDB,UDB,UIO,NVR>,5,DIADSP)	;RELEASE CHANNEL PROG
	DIAGDS	(<KDB,UDB,UIO,NVR>,6,DIADSP)	;GET CHANNEL STATUS
	DIAGDS	(<NON>,7,DIAKUN)		;GET KONTROLLER AND UNIT #S
	DIAGDS	(<NON>,10,DIAXSB)		;READ CSB
	DIAGDS	(<NON>,11,DIAXSB)		;READ DSB
	DIAGDS	(<KDB,UDB,UIO,NVR>,12,DIADSP)	;CHANNEL PROGRAM FOR READ REVERSE
	DIAGDS	(,13,DIANLD)			;ENAB/DISAB AUTO DX20 RELOAD
	DIAGDS	(<UIO,NON>,14,CPOPJ1##)		;GET USER I/O
	DIAGDS	(,15,TPDKIO##)			;STOP TAPE CHANNEL ACTIVITY
	DIAGDS	(,16,TPDSIO##)			;START TAPE ACTIVITY
	DIAGDS	(<KDB,UDB,NON,CPU>,17,DIADSP)	;ENABLE MICROCODE LOADING
	DIAGDS	(<KDB,UDB,NON,CPU>,20,DIADSP)	;DISABLE MICROCODE LOADING
	DIAGDS	(<KDB,UDB,NON,CPU>,21,DIADSP)	;LOAD MICROCODE
	DIAGDS	(<KDB,CPU>,22,DIADSP)		;SET IPA CHANNEL MAINT MODE
	DIAGDS	(<KDB,CPU>,23,DIADSP)		;CLEAR IPA CHANNEL MAINT MODE
IFN FTKL10&FTMOS,<
	DIAGDS	(<UIO>,100,DIAGTM##)		;GET MEMORY
	DIAGDS	(<UIO,NON>,101,DIAGVM##)	;GIVE MEMORY
>
IFE FTKL10!FTMOS,<
	DIAGDS	(,100,BADFNC)
	DIAGDS	(,101,BADFNC)
>
IFN FTSCA,<
	DIAGDS	(,105,DIARRS##)			;RESET REMOTE SYSTEM
	DIAGDS	(,106,DIASRS##)			;START REMOTE SYSTEM
	DIAGDS	(<CPU>,107,DIACTR##)		;PORT COUNTER FUNCTIONS
	DIAGDS	(,112,DIAWMD##)			;WRITE CI MAINTENANCE DATA
	DIAGDS	(,113,DIARMD##)			;READ CI MAINTENANCE DATA
>; END IFN FTSCA

	DIDSLN==.-DIADST			;LENGTH OF TABLE


;HERE TO ENABLE/DISABLE THE LOAD OF DX20 MICROCODE
IFN FTKL10,<
DIANLD:	PUSH	P,T1		;SAVE T1
	MOVSI	T1,JP.POK	;CHECK FOR PRIVILEGED JOB
	PUSHJ	P,PRVBIT##	;  (OR ONE WITH POKE)
	  SKIPA			;HAS THE REQUIRED PRIVS
	JRST	DIANPV		;INSUFFICIENT PRIVS
	PUSHJ	P,GETWD1##	;GET THE ARGUMENT
	MOVEM	T1,0(P)		;OVERWRITE ORIGINAL ARG ON STACK
	HRRES	T1		;KEEP ONLY CPU NUMBER
	JUMPL	T1,DIANL1	;IF NEGATIVE, DO ALL OF THEM
	CAIL	T1,CPUN##	;IS IT REASONABLE?
	JRST	DIANSC		;NO, GIVE ERROR
	LSH	T1,.CPSOF##	;COMPUTE OFFSET OF THE CORRECT CDB
	ADDI	T1,.C0CDB##	;OFFSET BY START OF CPU0 CDB
	POP	P,T2		;GET THE ARGUMENT BACK
	HLRZM	T2,.CPNLD##-.CPCDB##(T1) ;SET THE FLAG INTO THE CDB
	JRST	CPOPJ1##	;GIVE SUCCESS RETURN

;HERE IF ALL CPU'S WERE SPECIFIED
DIANL1:	EXCH	P2,0(P)		;SAVE P2, GET ARGUMENT BACK
	MOVEI	T1,[HLRZM P2,.CPNLD##-.CPCDB(P1) ;SUBROUTINE TO CALL
		    POPJ  P,]	;  FOR EVERY CPU
	PUSHJ	P,CPUAPP	;SET THE FLAG IN ALL CDB'S
	POP	P,P2		;RESTORE P2
	JRST	CPOPJ1##	;GIVE SUCCESS RETURN
>
IFE FTKL10,<
DIANLD==CPOPJ1##
>
INTERN	WRONGN,DINEFC,DIABAL,DIAMNA,DIAPNR
IFN FTSCA,<
INTERN	UNNDMD,UNAAJB,DIANPC,DIATMO,DIAMRF,DIANPV,ILLKON,IOWCPB
>; END IFN FTSCA

ERCODE	DIANPV,1		;NOT ENOUGH PRIVS
ERCODE	WRONGN,2		;ILLEGAL NUMBER OF ARGS
ERCODE	ILLKON,3		;ILLEGAL CONTROLLER NUMBER
ERCODE	ILLUNI,4		;ILLEGAL UNIT NUMBER
ERCODE	DIUNAA,5		;SOME UNITS ALREADY ASSIGNED
ERCODE	UNNDMD,6		;UNIT NOT IN DIAG MODE
ERCODE	UNAAJB,7		;UNIT ASS'D TO ANOTHER JOB
ERCODE	DINEFC,10		;NOT ENOUGH FREE CORE
ERCODE	NOASUN,11		;NO ASSIGNED UNITS
ERCODE	IOWCPB,12		;IOWD CROSSES PAGE BOUNDARY
ERCODE	BADFNC,13
ERCODE	DIAVRT,14
ERCODE	DIANSC,15		;NO SUCH CPU
ERCODE	DIACNR,16		;CPU NOT RUNNING
ERCODE	DIABAL,17		;SOME ARGUMENT IS ILLEGAL
ERCODE	DIANPC,20		;NO CI PORT ON CPU
ERCODE	DIATMO,21		;READ COUNTERS FUNCTION TIMED OUT
ERCODE	DIANKC,22		;NO NI PORT ON CPU
ERCODE	DIAMRF,23		;MICROCODE RELOAD FAILED
ERCODE	DIAMNA,24		;MICROCODE NOT AVAILABLE
ERCODE	DIAPNR,25		;CI/NI PORT NOT RUNNING
>;END IFE FTKS10
	SUBTTL	RECON. UUO - SYSTEM LOGICAL RECONFIGURATION UUO

;THIS UUO PROVIDES THE SUPPORT NECESSARY FOR A USER PROGRAM TO LOGICALLY
; RECONFIGURE THE SYSTEM AND SUPPEND ITS OPERATION TEMPORARLY SO THAT
; OPERATIONS CAN PHYSICALLY RECONFIGURE AND THEN RESUME
;CALLING SEQUENCE:
;	MOVE	AC,[FUNCTION,,ADDRESS]
;	RECON.	AC,
;	  ERROR RETURN
;	NORMAL RETURN

RECON:	HLRE	U,T1		;FUNCTION
	CAML	U,[NLRECC]	;IS IT A LEGAL CUSTOMER FUNCTION?
	CAILE	U,NLRECN	;IS IT LEGAL?
	JRST	RCNIAL		;ILLEGAL ARGUMENT LIST
	PUSHJ	P,PRUSET	;GET LENGTH OF ARGUMENT LIST AND CHECK PRIVILEGES
	  JRST	RCNNPV		;NOT PRIVILEGED
	JRST	@RCNDSP(U)	;DISPATCH

RCNCST:				;CUSTOMER FUNCTIONS GO HERE
RCNDSP:	RCNROM			;(0) RUN ONLY ME
	RCNSPN			;(1) SUSPEND SYSTEM
	RCNCI7			;(2) TAKE CI7 CONTINUABLE DUMP
	RCNNAR			;(3) SET/CLEAR DF.NAR
	RCNBTX			;(4) SUPPLY NEW VALUE OF BOOTXT
	RCNRLD			;(5) RELOAD THE SYSTEM
IFN FTAUTC,<
	RCNATC			;(6) FORCE AUTCON TO RUN
>
IFE FTAUTC,<
	CPOPJ1##		;IF NO AUTCON
>
	RCNDET			;(7) DETACH (CPU OR DEVICE)
	RCNATT			;(10) ATTACH (CPU OR DEVICE)
	RCNMOL			;(11) SET MEMORY ON-LINE
	RCNMOF			;(12) SET MEMORY OFF-LINE
	RCNCPU			;(13) FIND CPU MASK FOR A DEVICE
	RCNIOW			;(14) WAIT FOR ALL ACTIVE I/O TO STOP
	RCNSDF			;(15) SET DUMP/RELOAD FLAGS IN DEBUGF
	RCNCDF			;(16) CLEAR DUMP/RELOAD FLAGS IN DEBUGF
NLRECN==.-RCNDSP-1
NLRECC==RCNCST-RCNDSP

;ERROR RETURNS
RCIAL%==1
RCNPV%==2
RCNTS%==3
RCNIJ%==4
RCNCD%==5
RCNAC%==6
RCNIS%==7
RCNIC%==10
RCNCR%==11
RCNCA%==12
RCNDS%==13
RCNAA%==14
RCNID%==15
RCNDU%==16
RCNND%==17
RCNNL%==20
RCNMM%==21
RCNTB%==22
RCNLJ%==23

	ERCODE	RCNIAL,RCIAL%	;ILLEGAL ARGUMENT LIST
	ERCODE	RCNNPV,RCNPV%	;NOT PRIVILEGED
	ERCODE	RCNTAS,RCNTS%	;TIME-SHARING ALREADY STOPPED ON SOME CPU
	ERCODE	RCNIJN,RCNIJ%	;ILLEGAL JOB NUMBER
	ERCODE	RCNCND,RCNCD%	;SYSTEM CANNOT BE SNAP SHOTTED
	ERCODE	RCNADC,RCNAC%	;ADDRESS CHECK
	ERCODE	RCNIST,RCNIS%	;ILLEGAL STRING
	ERCODE	RCNICN,RCNIC%	;ILLEGAL CPU NUMBER
	ERCODE	RCNCIR,RCNCR%	;CPU STILL RUNNING
	ERCODE	RCNCAD,RCNCA%	;CAN'T ATTACH DISK
	ERCODE	RCNDIS,RCNDS%	;DEVICE IS SPOOLED
	ERCODE	RCNDAA,RCNAA%	;DEVICE IS ALREADY ATTACHED
	ERCODE	RCNILD,RCNID%	;ILLEGAL DEVICE
	ERCODE	RCNDIU,RCNDU%	;DEVICE IN USE
	ERCODE	RCNCDD,RCNND%	;CAN NOT DETACH DISK
	ERCODE	RCNLNL,RCNNL%	;LOKCON NOT LOADED
	ERCODE	RCNRMM,RCNMM%	;REMOVING MONITOR MEMORY
	ERCODE	RCNJTB,RCNTB%	;JOB(S) TOO BIG
	ERCODE	RCNMLJ,RCNLJ%	;MOVING LOCKED JOB(S)
;HERE TO MAKE ONLY ONE JOB RUNNABLE ON THE SYSTEM (FUNCTION 0)

RCNROM:	CAIE	T1,2		;MUST BE EXACTLY ONE ARGUMENT
	JRST	RCNIAL		;ILLEGAL ARGUMENT LIST
	PUSHJ	P,GETWR1##	;GET JOB NUMBER
	  JRST	RCNADC		;ADDRESS CHECK
	CAME	T1,[-1]		;DEFAULT TO THE CURRENT JOB?
	MOVE	J,T1		;NO, USE USER SUPPLIED JOB NUMBER
	PUSHJ	P,FNDPDB##	;VALIDATE JOB NUMBER
	  JRST	RCNIJN		;ILLEGAL JOB NUMBER
IFN FTMP,<
	PUSHJ	P,SBSCD##	;GET SCHEDULAR INTERLOCK (RESTORE ON POPJ)
>; END IFN FTMP
	MOVEI	T1,[CAME T2,.CPSTS##-.CPCDB##(P1)
		    SKIPN .CPSTS##-.CPCDB##(P1)
		    CAIA
		    SETO T2,
		    POPJ P,]
	MOVE	T2,.CPJOB##	;JOB NUMBER OF REQUESTOR
	PUSHJ	P,CPUAPP##	;HAS TIME-SHARING BEEN STOPPED ON ANY CPU?
	JUMPL	T2,RCNTAS	;TIME-SHARING HAS ALREADY BEEN STOPPED ON SOME CPU
	MOVEI	T1,[MOVEM J,.CPSTS##-.CPCDB##(P1)
		    POPJ P,]
	PUSHJ	P,CPUAPP##	;MAKE THIS JOB BE THE ONLY RUNNABLE JOB ON THE SYSTEM
	JRST	CPOPJ1##	;TELL THE USER THAT HE DID GOOD

;HERE TO SUSPEND THE SYSTEM (FUNCTION 1)

RCNSPN:	PUSH	P,T1		;SAVE MONBTS ADDRESS
	MOVEI	T1,[ASCIZ /SEND ALL Suspending system operation
/]
	PUSHJ	P,[PUSHJ P,FRCSET## ;SETUP TO SEND FROM [SYSTEM]
		   PJRST CONMES##]  ;TELL THE WORLD
RCNSP1:	MOVEI	T1,^D10		;WAIT UNTIL EVERYONE SEES IT
	PUSHJ	P,SLEEP
	SKIPE	SNDCTR##
	JRST	RCNSP1
	POP	P,T1		;GET BACK USER AC, WHICH CONTAINS MONBTS ADDR
	HRRZM	T1,MBTCOM##	;STORE IT INTO THE MONBTS COMMUNICATION AREA
	MOVEI	T1,SYSRST##	;RESTART ADDRESS
	HRRM	T1,.JBSA##	;STORE THAT FOR REBOOT
	MOVSI	T1,(CR.SPD!CR.TSS)	;SUSPEND THIS CPU AND SNAP SHOT BITS
	IORM	T1,.CPRUN##	;MAKE US GO AWAY AS SOON AS THE NULL JOB RUNS
	MOVEI	T1,^D10		;LET THINGS SETTLE DOWN
	PUSHJ	P,SLEEP		;ZZZZZZ
	MOVSI	T1,(CR.TSS)	;DUMP FAILED BIT
	TDNN	T1,.CPRUN##	;DID IT FAIL?
	JRST	RCNSP2		;SYSTEM WAS RESUMED, GIVE GOOD RETURN TO USER
	ANDCAM	T1,.CPRUN##	;YES, CANNOT SUSPEND THE SYSTEM
	JRST	RCNCND		;GIVE THE USER AN ERROR RETURN
RCNSP2:	PUSHJ	P,FRCSET##
	PUSHJ	P,INLMES##
	ASCIZ	/SEND ALL System resumed
/
	JRST	CPOPJ1##
;HERE TO TAKE A CI7 CONTINUABLE DUMP (FUNCTION 2)

RCNCI7: SE1ENT			;ENTER SECTION ONE
	MOVE	T1,JBTPPN##(J)	;GET PPN OF JOB
	CAME	T1,FFAPPN##	;MUST BE 1,2 TO DO THIS
	JRST	RCNNPV		;NO, NOT PRIVILEGED
	MOVSI	T1,(DF.RDC!DF.DDC) ;DON'T DO THIS IF WE WILL RELOAD
	TDNN	T1,DEBUGF##	;  ON IT OR IF WE WON'T TAKE THE DUMP
	PUSHJ	P,BTAVAL##	;IS THE BOOTSTRAP AVAILABLE?
	JRST	RCNCND		;NO, CAN'T DO IT
	STOPCD	.+1,DEBUG,CI7, ;++CI7 CONTINUABLE SNAPSHOT DUMP
	JRST	CPOPJ1##	;GIVE SUCCESS RETURN


;HERE TO SET/CLEAR DF.NAR IN DEBUGF TO ENABLE/DISABLE AUTO RELOADS.
;  (FUNCTION 3)

RCNNAR:	CAIE	T1,2		;MUST HAVE EXACTLY ONE ARGUMENT
	JRST	RCNIAL		;ELSE ILLEGAL
	PUSHJ	P,GETWD1##	;GET THE ARGUMENT
	MOVSI	T2,(DF.NAR)	;GET THE RELEVANT BIT
	SKIPE	T1		;WANT TO SET THE BIT?
	IORM	T2,DEBUGF##	;YES, DO SO
	SKIPN	T1		;WANT TO CLEAR THE BIT?
	ANDCAM	T2,DEBUGF##	;YES, DO SO
	JRST	CPOPJ1##	;GIVE SUCCESS RETURN
;HERE TO SPECIFY A NEW BOOTXT STRING (FUNCTION 4)

RCNBTX:	SOJLE	T1,RCNIAL	;DISCOUNT THIS WORD, CHECK FOR LENGTH ERROR
	CAILE	T1,BTXLEN##	;IS IT TOO LONG?
	JRST	RCNIAL		;YES, GIVE ERROR RETURN
	PUSHJ	P,SAVE3##	;SAVE P1-P3
	MOVE	P1,T1		;SAVE +LENGTH FOR FIRST LOOP
	MOVN	P2,T1		;  AND -LENGTH FOR SECOND LOOP
	MOVE	P3,M		;SAVE M ALSO
RCNBT1:	PUSHJ	P,GETWR1##	;GET NEXT WORD IN STRING
	  JRST	RCNADC		;ADDRESS CHECK
	MOVE	T2,[POINT 7,T1]	;GET BYTE POINTER TO STRING
RCNBT2:	ILDB	T3,T2		;GET NEXT BYTE
	JUMPE	T3,RCNBT3	;GO IF FOUND THE END
	CAIN	T3,12		;ANY LINE FEEDS IN THE STRING?
	JRST	RCNIST		;YES, CR+LF WILL SCREW UP BOOT (RESTRICT TO CR)
	TLNE	T2,(76B5)	;DONE WITH THIS WORD YET?
	JRST	RCNBT2		;NO, CONTINUE
	SOJG	P1,RCNBT1	;YES, GET NEXT WORD
	JRST	RCNIAL		;SIZE OF STRING WAS WRONG
RCNBT3:	SOJN	P1,RCNIAL	;SIZE OF STRING WAS WRONG
	HRLZ	P1,P2		;MAKE AOBJN POINTER TO STRING WORDS
	MOVE	M,P3		;RESTORE M
RCNBT4:	PUSHJ	P,GETWD1##	;GET NEXT WORD IN STRING
	MOVEM	T1,BOOTXT##(P1) ;STORE IN MEMORY
	AOBJN	P1,RCNBT4	;LOOP FOR ALL WORDS
	JRST	CPOPJ1##	;GIVE SKIP RETURN


;HERE TO RELOAD THE SYSTEM.  (FUNCTION 5)

RCNRLD:	MOVE	T1,JBTPPN##(J)	;GET PPN OF JOB
	CAME	T1,FFAPPN##	;MUST BE 1,2 TO DO THIS
	JRST	RCNNPV		;NO, NOT PRIVILEGED
	MOVSI	T1,(DF.RIP)	;RELOAD IN PROGRESS
	IORM	T1,DEBUGF##	;TELL DIE AND REBOOT ABOUT IT
	STOPCD	.,STOP,RLD,	;++RELOAD MONITOR
;HERE TO FORCE AUTCON TO RUN AND POSSIBLY ADD DEVICES. (FUNCTION 6)

IFN FTAUTC,<
RCNATC:	CAIE	T1,2		;MUST BE EXACTLY 1 ARGUMENT
	JRST	RCNIAL		;ILLEGAL ARGUMENT LIST
	PUSHJ	P,GETWR1##	;GET CPU NUMBER
	  JRST	RCNADC		;ADDRESS CHECK
	CAME	T1,[-1]		;ALL CPUS?
	CAIG	T1,CPUN##	;NO, A LEGAL CPU?
	CAIA			;ALL OR LEGAL
	JRST	RCNICN		;ILLEGAL CPU SPECIFIED
	JUMPL	T1,RCNAC1	;GO IF ALL CPUS SPECIFIED
	PUSHJ	P,SAVE1##	;SAVE AN AC
	LSH	T1,.CPSOF##	;OFFSET INTO CDBS FOR THIS CPU
	MOVE	P1,.C0SLF##(T1)	;CDB FOR SPECIFIED CPU
	PUSHJ	P,RCNDOA	;AUTOCONFIGURE DEVIECS ON THAT CPU
	JRST	CPOPJ1##	;AND SAY WE DID GOOD
RCNAC1:	MOVEI	T1,RCNDOA	;SUBROUTINE TO EXECUTE ACROSS CPUS
	PUSHJ	P,CPUAPP##	;DO THE AUTOCONFIGURATION ON ALL CPUS
	JRST	CPOPJ1##	;GOOD RETURN

;SUBROUTINE TO CAUSE AUTCON TO BE RUN ON A SPECIFIED CPU
;CALL WITH P1 = THE CDB ADDRESS FOR THE CPU
RCNDOA:
IFN FTMP,<
	MOVE	T1,.CPCPN##-.CPCDB##(P1) ;CPU NUMBER
	PUSHJ	P,ONCPUS##	;GET ONTO THE CORRECT CPU
	  POPJ	P,		;NOOP IF NOT RUNNING
>
	PJRST	CPUATC##	;DO IT
>
;HERE TO DETACH A CPU OR DEVICE (FUNCTION 7)

RCNDET:	CAIGE	T1,2		;MUST HAVE AT LEAST ANOTHER WORD
	JRST	RCNIAL		;ILLEGAL ARGUMENT LIST
	PUSHJ	P,GETWR1##	;GET OBJECT TO DETACH
	  JRST	RCNADC		;ADDRESS CHECK
IFN FTMP,<
	MOVE	T2,T1		;COPY FOR NAME MATCHERS
	PUSHJ	P,CPUFND##	;LOOK UP AS A CPU
	  JRST	RCNDE1		;NOT A CPU
	CAIL	T1,M.CPU##	;LEGAL CPU NUMBER?
	JRST	RCNICN		;NO, ERROR
	MOVE	T2,T1		;COPY CPU NUMBER
	LSH	T2,.CPSOF##	;SIZE OFFSET FOR CDB
	SKIPG	.C0OK##(T2)	;IS CPU DOWN?
	JRST	RCNCIR		;ERROR IF CPU IS RUNNING
	PUSHJ	P,CPUDTU##	;HAVE CPNSER FINISH UP
	JRST	CPOPJ1##	;RETURN SUCCESS
RCNDE1:	MOVE T1,T2		;RESTORE T1
> ;IFN FTMP
	PUSHJ	P,SAVE2##	;SAVE A FEW
	PUSHJ	P,DEVPHY	;SEARCH FOR DEVICE
IFE FTDUAL,<
	  JRST	RCNILD		;ILLEGAL DEVICE
>
IFN FTDUAL,<
	  JRST	RCNDE3		;CHECK FOR DISK UNIT ANYWAY
>
	MOVE	T2,DEVMOD(F)	;CHECK TO SEE IF THIS IS DSK
	TRNE	T2,ASSPRG	;ASSIGNED BY PROGRAM?
	JRST	RCNDIU		;YES, DEVICE IN USE
	TLNE	T2,DVDSK	;TRYING TO TAKE DOWN A DISK?
	JRST	RCNDE3		;YES, DO IT DIFFERENTLY
	TLNE	T2,DVTTY	;IS IT THE DSK OR A TTY?
	JRST	RCNILD		;YES, ILLEGAL DEVICE
	MOVEI	T2,ASSCON	;FOUND-SET UP ASSIGNED BY CONSOLE
	PUSHJ	P,ASSASG	;TRY TO ASSIGN
	JRST	RCNDIU		;CAN'T ASSIGN
	SKIPGE	DEVSPL(F)	;SPOOLED?
	JRST	RCNDE2		;YES
	TLNE	F,SYSDEV	;IS THIS SYSTEM DEVICE?
	JRST	RCNDE4		;YES, ILLEGAL DEVICE
	MOVEI	T1,0		;NO. SET JOB NUMBER TO ZERO
	DPB	T1,PJOBN##	; ..
	JRST	CPOPJ1##	;RETURN SUCCESSFUL

RCNDE2:	PUSHJ	P,CLRDDB##	;DEASSIGN THE DEVICE
	JRST	RCNDIS		;ERROR WHEN DEVICE IS SPOOLED

;HERE TO DETACH A DSK
RCNDE3:	PUSHJ	P,DETDSK##	;TRY TO DETACH
	  JRST	RCNILD		;ILLEGAL DEVICE
	  JRST	RCNCDD		;CANNOT DETACH
	JRST	CPOPJ1##	;WIN

RCNDE4:	MOVEI	T2,ASSCON	;BIT TO CLEAR
	PUSHJ	P,RELEA6	;DEASSIGN THE DEVICE
	JRST	RCNILD		;ILLEGAL DEVICE ERROR
;HERE TO ATTACH A CPU OR DEVICE (FUNCTION 10)

RCNATT:	CAIGE	T1,2		;MUST HAVE ANOTHER ARGUMENT
	JRST	RCNIAL		;ILLEGAL ARGUMENT LIST
	PUSHJ	P,GETWR1##	;GET OBJECT TO ATTACH
	  JRST	RCNADC		;ADDRESS CHECK
	PUSHJ	P,SAVE2##	;SAVE A FEW FROM MANGLING
IFN FTMP,<
	MOVE	T2,T1		;COPY FOR NAME MATCHER
	PUSHJ	P,CPUFND##	;CHECK IF CPU ARGUMENT
	  JRST	RCNAT1		;NOT A CPU
	CAIL	T1,M.CPU##	;IN RANGE?
	JRST	RCNICN		;ILLEGAL CPU NUMBER
	PUSHJ	P,CPUATU##	;LET CPNSER DO THE ATTACH
	  JRST	RCNCIR		;CPU IS RUNNING ERROR
	JRST	CPOPJ1##	;RETURN SUCCESS
RCNAT1:	MOVE	T1,T2		;RESTORE DEVICE NAME
> ;IFN FTMP
	PUSHJ	P,DEVSRG	;SEARCH FOR DEVICE
IFE FTDUAL,<
	  JRST	RCNILD		;ILLEGAL DEVICE
>
IFN FTDUAL,<
	  JRST	RCNAT2		;SEE IF DUAL-PORTED DISK
>
	MOVE	T2,DEVMOD(F)
	TLNE	T2,DVDSK	;DISK?
	JRST	RCNAT2		;YES, DO IT DIFFERENTLY
	SKIPN	DEVCHR(F)	;IS IT A "FAKE" DDB?
	PJRST	RCNDIS		;YES, CAN'T ATTACH SPOOLED DEVICE
	TRNN	T2,ASSCON	;WAS DEVICE DETACHED?
	PJRST	RCNDAA		;NO, ERROR
	LDB	T1,PJOBN##	;GET JOB NUMBER
	JUMPN	T1,RCNDAA	;IS IT = 0?
	SETZM	DEVLOG(F)
	DPB	J,PJOBN##	;SET JOB NUMBER
	HRRI	T1,MTSIZ##+1	;GET DEFAULT MAGTAPE BLOCK SIZE
	HLL	T1,DEVMOD(F)
	TLNN	T1,DVMTA	;MAGTAPE?
	JRST	CPOPJ1##	;NO, IGNORE
	DPB	T1,PBUFSZ##	;RESTORE DEFAULT BLOCK SIZE
	SETZ	T1,
	DPB	T1,TDYDN1##	;CLEAR USER SET DEFAULT DENSITY
	DPB	T1,TDYMD1##	;CLEAR DEFAULT MODE
	DPB	T1,PBUFRM##	;CLEAR MAX FRAME-COUNT
IFN FTDX10,<
	DPB	T1,PMTRTY##	;ENABLE AUTO ERROR-RETRY
>
	JRST	CPOPJ1##	;RETURN SUCCESS

;HERE TO ATTACH A DISK UNIT
RCNAT2:	PUSHJ	P,ATTDSK##	;TRY TO PUT IT ON-LINE
	  JRST	RCNAT3		;NOT DOWN OR NO SUCH UNIT
	  JFCL			;DOESN'T RETURN HERE WHEN CALLED AT UUO LEVEL
	JRST	CPOPJ1##	;UNIT IS NOW UP

RCNAT3:	TLZE	U,400000	;IS IT A DSK?
	JRST	RCNILD		;NO, "NOT A DEVICE"
	JRST	RCNCAD		;YES, "ATTACH DEV?"
;HERE TO SET MEMORY ON LINE (FUNCTION 11)

RCNMOL:	PUSHJ	P,RCNMEM	;DO ARGUMENT CHECKING
	  POPJ	P,		;PROPAGATE FAILURE
	PUSHJ	P,SAVE2##	;SO COMCON WON'T CLOBBER THEM
	AOS	(P)		;WE WILL SUCCEED
	PJRST	MEMONU##	;HAVE COMCON PUT THE PAGES ON-LINE

RCNMEM:	CAIGE	T1,3		;HAVE ENOUGH ARGUMENTS?
	JRST	RCNIAL		;NO, ILLEGAL ARGUMENT LIST
	PUSHJ	P,GETWR1##	;GET FIRST PAGE TO SET ONLINE
	  JRST	RCNADC		;ADDRESS CHECK
	MOVE	T2,T1		;SAVE IT
	PUSHJ	P,GETWR1##	;GET FIRST PAGE TO LEAVE ALONE (LAST PAGE+1)
	  JRST	RCNADC		;ADDRESS CHECK
	EXCH	T1,T2		;GET IN RIGHT ORDER
	TLNN	T1,-1		;IF EITHER IS RIDICULOUS
	TLNE	T2,-1		; ...
	JRST	RCNIAL		;ILLEGAL ARGUMENT LIST
	CAML	T1,T2		;MUST BE IN RIGHT ORDER
	JRST	RCNIAL		;OR ILLEGAL ARG LIST
	JRST	CPOPJ1##	;GIVE OK RETURN
;HERE TO SET MEMORY OFF LINE (FUNCTION 12)

RCNMOF:	SKIPN	[LOKINC##]	;IS LOKCON LOADED?
	JRST	RCNLNL		;ERROR IF NOT
IFN FTMP,<
	PUSHJ	P,ONCPU0##	;AVOID POSSIBLE RACE WITH COMCON
>
	PUSHJ	P,RCNMEM	;CHECK OUR ARG LIST
	  POPJ	P,		;PROPAGATE FAILURE
	PUSHJ	P,CKMOL##	;CHECK THAT RANGE DOESN'T OVERLAP THE MONITOR
	  JRST	RCNRMM		;IT DOES SO WE CAN'T DO IT
	LDB	T3,[POINT 14,NWCORE##,26] ;GET TOTAL SIZE (ON OR OFF)
	CAIL	T1,(T3)		;LOWER BOUND BEYOND END?
	JRST	CPOPJ1##	;YES, IT'S ALREADY OFF
	CAIL	T2,(T3)		;UPPER BOUND BEYOND END?
	MOVE	T2,T3		;YES,CHANGE UPPER BOUND
	PUSH	P,T1		;SAVE LOWER BOUND
	PUSH	P,T2		;AND UPPER BOUND
	PUSHJ	P,NEWCMX##	;SEE IF ALL JOBS CAN CONTINUE TO RUN
	JUMPLE	T1,[ADJSP P,-2	;IF .LE. 0, REMOVING MONITOR MEMORY
		    JRST RCNRMM];GO EXPLAIN THE PROBLEM
	PUSH	P,J		;SAVE J
	MOVEI	J,0		;STARTING WITH JOB 0,
	PUSHJ	P,JBSTBG##	;MAKE SURE ALL JOBS CAN STILL RUN (I.E., NONE IS TOO BIG)
	  JRST	RCNMF2		;NONE ARE
	POP	P,J		;RESTORE J
	ADJSP	P,-2		;BALANCE STACK
	JRST	RCNJTB		;JOB(S) TOO BIG
RCNMF2:	MOVEI	J,0		;STARTING WITH JOB 0,
	MOVE	T1,-2(P)	;LOWER BOUND,
	MOVE	T2,-1(P)	;UPPER BOUND,
	PUSHJ	P,CKLJB##	;SEE IF RANGE OVERLAPS SOME LOCKED JOB
	  JRST	RCNMF3		;IT DOESN'T SO ALL IS WELL
	POP	P,J		;RESTORE J
	ADJSP	P,-2		;BALANCE STACK
	JRST	RCNMLJ		;ERROR IF NEED TO MOVE LOCKED JOB(S)
RCNMF3:	POP	P,J		;RESTORE J
	POP	P,T2		;RESTORE UPPER BOUND
	POP	P,T1		;AND LOWER BOUND
	AOS	(P)		;WILL SUCCEED NOW
	PJRST	MEMOFU##	;GO SET THE MEMORY OFF-LINE
;HERE TO FIND THE CPU ACCESSABILITY MASK FOR A DEVICE (FUNCTION 13)

RCNCPU:	CAIGE	T1,2		;MUST HAVE AT LEAST ANOTHER WORD
	JRST	RCNIAL		;ILLEGAL ARGUMENT LIST
	PUSHJ	P,GETWR1##	;GET DEVICE TO DETACH
	  JRST	RCNADC		;ADDRESS CHECK
	CAME	T1,[SIXBIT /CPU/] ;IS IT GENERIC CPU?
	JRST	RCNCP1		;NO, TRY FOR SPECIFIC CPU
IFN FTMP,<
	SETZ	T2,		;YES, ZERO BIT ACCUMULATION
	MOVEI	T1,[MOVE T1,.CPRUN##-.CPCDB##(P1) ;GET RUN BITS
		    TLNN T1,(CR.NRN!CR.RMV!CR.DET!CR.SPD) ;IS IT AVAILABLE?
		    TDO	 T2,.CPBIT##-.CPCDB##(P1) ;YES, ADD IN ITS BIT
		    POPJ P,]	;END OF ROUTINE
	PUSHJ	P,CPUAPP##	;COLLECT THE BITS FOR ALL RUNNING CPUS
	MOVE	T1,T2		;COPY BIT MASK TO RETURN AC
>
IFE FTMP,<
	MOVE	T1,.CPBIT##	;GET OUR BIT
>
	JRST	STOTC1##	;RETURN BIT MASK TO USER
RCNCP1:	MOVE	T2,T1		;COPY FOR FINDERS
IFN FTMP,<
	PUSHJ	P,CPUFND##	;IS IT A CPU?
	  JRST	RCNCP2		;NO, TRY DEVICES
	CAIL	T1,M.CPU##	;YES, IS IT IN RANGE?
	JRST	RCNICN		;NO, GIVE ERROR
	MOVE	T1,T3		;COPY MASK
	ANDI	T1,77		;KEEP ONLY LOW PORTION
>
IFE FTMP,<
	MOVE	T1,.CPBIT##	;GET OUR BIT (IN CASE IT'S US)
	CAME	T2,.CPPHY##	;IS IT OUR PHYSICAL NAME?
	CAMN	T2,.CPLOG##	;OR OUR LOGICAL NAME?
>
	JRST	STOTC1##	;YES, RETURN ITS BIT TO THE USER
RCNCP2:	MOVE	T1,T2		;RESTORE DEVICE NAME
	PUSHJ	P,DEVPSN	;SEARCH FOR DEVICE
	  JRST	RCNCP4		;CHECK FOR DISK UNIT ANYWAY
	SKIPGE	DEVSPL(F)	;SPOOLED?
	JRST	RCNDIS		;YES, ERROR
	MOVE	T2,DEVMOD(F)	;CHECK TO SEE IF THIS IS DSK
	TLNE	T2,DVDSK	;TRYING TO FIND A DISK?
	JRST	RCNCP4		;YES, DO IT DIFFERENTLY
;WORRY ABOUT MAGTAPES HERE SOMEDAY
IFN FTMP,<
	LDB	T2,DEYCPF##	;GET OWNING CPU NUMBER
	CAIN	T2,CPFBIT##	;NEED A BIT MASK?
	STOPCD	.+1,DEBUG,NMCPUM,	;++NEED MISSING CPU MASK
	MOVEI	T1,1		;GET A BIT
	LSH	T1,(T2)		;CONVERT TO A MASK
	CAIN	T2,CPFBOO##	;GENERIC BOOT CPU?
	MOVEI	T1,77		;YES, ALL CPUS CAN REACH IT
>
IFE FTMP,<
RCNCP3:	MOVEI	T1,1		;BOTTOM BIT ONLY IF NO MP
>
	JRST	STOTC1##	;RETURN IT TO USER AND WIN

;HERE TO FIND A DSK
RCNCP4:	PUSHJ	P,SRSTR##	;LOOK FOR A STRUCTURE
	  JRST	RCNCP6		;NO, TRY FOR A UNIT
IFE FTMP,<
	JRST	RCNCP3		;GO WITH CPU0 IF VALID STR
>
IFN FTMP,<
	MOVEI	T3,77		;START BY ASSUMING AVAILABLE ON ALL CPUS
RCNCP5:	PUSHJ	P,GETCAM##	;GET BITS FOR THIS SPINDLE
	AND	T3,T1		;STRUCTURES ARE RESTRICTIVELY ACCUMULATED
	HLRZ	U,UNISTR##(U)	;GET NEXT UNIT IN STRUCTURE
	JUMPN	U,RCNCP5	;LOOP OVER ALL UNITS IN STR
	MOVE	T1,T3		;PUT BITS IN RIGHT AC
	JRST	STOTC1##	;RETURN BITS WITH WINNITUDE
> ;END OF IFN FTMP

;HERE TO FIND A DISK UNIT
RCNCP6:	SETO	T2,		;ALLOW ONLY FULL MATCHES, NOT ABBREVIATIONS
	PUSHJ	P,SRUNA##	;LOOK FOR A MATCHING UNIT
	  JRST	RCNILD		;NOT A DISK, SO IT'S ILLEGAL
	  JFCL			;LOGICAL MATCH IS OK
IFE FTMP,<
	JRST	RCNCP3		;RETURN ONLY CPU IF NO SMP FEATURE
>
IFN FTMP,<
	PUSHJ	P,GETCAM##	;GET BITS FOR THE SPINDLE (BOTH PORTS)
	JRST	STOTC1##	;RETURN IT WINNINGLY TO THE USER
>
;HERE TO WAIT FOR ALL I/O ON THE SYSTEM TO CEASE (FUNCTION 14)

RCNIOW:	MOVEI	F,HNGLST##-DEVSER ;START AT FIRST SERIOUS DDB
RCNIO1:	HLRZ	F,DEVSER(F)	;STEP TO NEXT DDB
	JUMPE	F,RCNIO3	;DONE WITH LOW CORE DDBS
	MOVEI	T1,IOACT	;I/O ACTIVE BIT
	TDNN	T1,DEVIOS(F)	;IS IT ON HERE?
	JRST	RCNIO1		;NO, KEEP LOOKING
RCNIO2:	SETZ	T1,		;YES, SET ARGUMENT FOR A TICK
	PUSHJ	P,SLEEPF	;SNOOZE A BIT
	JRST	RCNIOW		;AND START LOOKING AGAIN

;HERE WHEN NO LOW CORE DDB HAS IOACT LIT
RCNIO3:	HLRZ	T1,SYSCHN##	;POINT TO FIRST CHANNEL DB ON SYSTEM
RCNIO4:	SKIPL	.CHBSY(T1)	;IS THIS CHANNEL ACTIVE?
	JRST	RCNIO2		;YES, SNOOZE A WHILE
	HLRZ	T1,.CHSYS(T1)	;NO, POINT TO NEXT DB
	JUMPN	T1,RCNIO4	;CHECK ALL CHANNEL DATA BLOCKS FOR BUSY
	JRST	CPOPJ1##	;LOOKS GOOD TO ME
;HERE TO SET/CLEAR DUMP/RELOAD BITS IN DEBUGF (FUNCTIONS 15 AND 16)

DFFLGS==DF.RDC!DF.RJE!DF.NAR!DF.CP1!DF.DDC!DF.DJE!DF.DCP ;LEGAL FLAGS TO DIDDLE

RCNSDF:	SKIPA	P1,[IORB T1,DEBUGF##] ;GET INSTRUCTION TO EXECUTE FOR SET
RCNCDF:	MOVE	P1,[ANDCAB T1,DEBUGF##] ;GET INSTRUCTION TO EXECUTE FOR CLEAR
	CAIE	T1,2		;MUST BE EXACTLY ONE ARGUMENT
	JRST	RCNIAL		;ILLEGAL ARGUMENT LIST
	PUSHJ	P,GETWR1##	;GET FLAGS
	  JRST	RCNADC		;ADDRESS CHECK
	AND	T1,[DFFLGS]	;KEEP JUST LEGAL FLAGS
	XCT	P1		;SET/CLEAR THE FLAGS
	PJRST	STOTC1##	;STORE NEW FLAGS IN AC AND SKIP RETURN
;HERE FROM CLOCK1 WHEN SNAPSHOT HAS BEEN TAKEN TO STICK OUR HEAD IN THE SAND
RMVCPU::
IFN FTKL10,<
IFN FTENET,<
	PUSHJ	P,KNIRMV##	;ZAP THE KLNI
>; END IFN FTENET
IFN FTSCA,<
	PUSHJ	P,PPDRMV##	;ZAP THE KLIPA
>; END IFN FTSCA
	MOVEI	T1,LG.CSL!LG.CSW ;TURN OFF CACHE BITS
	ANDCAM	T1,.CPEBR##	;FOR 400 RE-START
	MOVE	F,.CPCPN##	;CPU NUMBER
	MOVE	F,DTEMAS##(F)	;THE MASTER DTE
	PUSHJ	P,TTDRLD##	;CLEAR F.E. TTY STATUS
	PUSHJ	P,SVPPC##	;TURN OFF "KEEP ALIVE"
>
IFN	FTKS10,<
	PUSHJ	P,DISKAL##	;DISABLE KEEP ALIVE
>
	PUSHJ	P,CSDMP##	;EMPTY CACHE
	AOS	.CPCSN##	;INSURE SWEEP GETS RECORDED

	CONO	PI,CLRPIS##	;DON'T MAINTAIN OK WORDS
	CONO	APR,APRRST##	;BLAST THE PROCESSOR
	MOVE	1,.+1		;GET AN INFINITE LOOP
	JRST	1		;AND DISAPPEAR
	SUBTTL	CMAND. UUO PLAY WITH USER-DEFINABLE COMMANDS.

CMAND:	HLRZ	U,T1		;GET FUNCTION CODE
	CAIL	U,NLCMDN	;RANGE CHECK
	 JRST	CMDIAL		;BAD FUNCTION CODE
	HRR	M,T1		;POINT TO OUR ARGUMENT LIST NOW.
	JRST	@CMDDSP(U)	;AND DISPATCH

CMDDSP:	IFIW	CMDINT		;INITIALIZE AND INSERT COMMANDS
	IFIW	CMDADD		;ADD COMMANDS TO TABLE
	IFIW	CMDDEL		;DELETE A COMMAND FROM TABLE.
	IFIW	CMDLST		;LIST COMMAND NAMES
	IFIW	CMDRET		;RETURN INFORMATION ABOUT A COMMAND
	IFIW	CMDDMP		;DUMP COMMAND DATA BASE
NLCMDN==.-CMDDSP

;ERROR CODES RETURNED
CMIAL%==1			;ILLEGAL ARGUMENT LIST
CMADC%==2			;ADDRESS CHECK
CMNER%==3			;NOT ENOUGH ROOM IN FUNNY SPACE
CMDNF%==4			;DID NOT FINISH (NO ROOM IN USER BUFFER)
CMNSN%==5			;NO SUCH NAME (FOR .CMRET FUNCTION)

	ERCODE	CMDIAL,CMIAL%	;DEFINE ERROR RETURNS
	ERCODE	CMDADC,CMADC%
	ERCODE	CMDNER,CMNER%
	ERCODE	CMDDNF,CMDNF%
	ERCODE	CMDNSN,CMNSN%

;BYTE SIZE VALUES FOR .PDUNQ
CM.BSZ==6			;BYTE SIZE IN BITS
CM.BPW==^D36/CM.BSZ		;NUMBER OF BYTES PER WORD
CM.BP1==CM.BPW-1		;ROUND-UP VALUE FOR WORDS TO STORE BYTES
CM.BPE==2*CM.BPW+1		;NUMBER OF BYTES PER COMMAND ENTRY IN TABLE

;SACFLG VALUE FOR COMCON
XP CM.SAC,40			;AUTO-PUSH COMMAND
;XP CM.???,20			;FREE BIT
;XP CM.UNQ,17			;UNIQUENESS BITS
;FUNCTION .CMINI
;DEFINE A NEW COMMAND LIST

CMDINT:	PUSHJ	P,SAVE1##	;IN CASE RECURSIVE UUO (HA!)
	PUSHJ	P,RMVCMD	;REMOVE ANY CURRENTLY DEFINED USER COMMANDS
	PUSHJ	P,CMDCNT	;COUNT NUMBER OF COMMANDS TO DEFINE
	 POPJ	P,		;PROPAGATE ERROR
CMDIN1:	JUMPE	P1,CPOPJ1	;IF NO COMMANDS TO DEFINE, RETURN SUCCESS.
	PUSHJ	P,CMDCOR	;GET CORE FOR OUR FREECORE DIRECTORY.
	 POPJ	P,
	PUSHJ	P,CMDINS	;AND ADD COMMANDS SUPPLIED IN THIS UUO
	 POPJ	P,		;PROPAGATE ERROR.
	RETSKP			;RETURN SUCCESS.
;FUNCTION .CMADD
;UUO FUNCTION TO ADD COMMANDS TO OUR LIST.
CMDADD:
	PUSHJ	P,SAVE1##	;AVOID TRASHING A MONITOR UUO.
	PUSHJ	P,CMDCNT	;COUNT NUMBER OF COMMANDS TO ADD
	 POPJ	P,		;HMM. MUST HAVE HAD A BUM ADDRESS
	SETZ	T1,		;START COUNTING FROM 0
	SKIPN	T2,.PDCMN##(W)	;GET POINTER TO COMMAND NAMES
	 JRST	CMDIN1		;NONE DEFINED. CALL THE DEFINE CODE.
CMDAD1:	SKIPN	(T2)		;IS THIS COMMAND DEFINED?
	 AOJ	T1,		;NO, BUMP COUNT OF AVAILABLE COMMANDS.
	AOBJN	T2,CMDAD1	;AND CONTINUE FOR ALL COMMANDS IN DIRECTORY.
	CAMG	P1,T1		;DO WE HAVE ENOUGH ROOM TO DEFINE COMMANDS?
	 JRST	CMDAD4		;YES, JUST ADD THEM.
	HLRO	T2,.PDCMN##(W)	;GET NEGATIVE SIZE OF CURRENT COMMAND DIRECTORY
	ADD	T2,T1		;CONVERT TO NEGATIVE NUMBER OF COMMANDS TAKEN
	SUB	P1,T2		;TOTAL NUMBER OF COMMANDS WE WILL NEED.
	PUSHJ	P,CMDXPN	;NOT ENOUGH ROOM, EXPAND OUR DIRECTORY.
	 POPJ	P,		;PROPAGATE ERROR.
CMDAD4:
	PJRST	CMDINS		;AND INSERT OUR COMMANDS
;FUNCTION .CMDEL
;DELETE COMMANDS
CMDDEL:	PUSHJ	P,SAVE4##
	PUSHJ	P,GETWRD##	;GET NUMBER OF COMMANDS TO DELETE
	 JRST	CMDADC		;BLOW UP
	MOVE	P1,T1		;COPY NUMBER OF COMMANDS TO DO
CMDDE1:	SOJLE	P1,CPOPJ1##	;RETURN SUCCESS.
	PUSHJ	P,GETWR1##	;GET NEXT COMMAND NAME TO DELETE
	 JRST	CMDADC		;BAD ADDRESS
	PUSHJ	P,CMDINI	;INITIALIZE POINTERS
	JUMPE	P2,CMDDE1	;IF NO COMMANDS, DON'T TRY SEARCHING
	JUMPE	T1,CMDDE1	;IF NULL COMMAND, PUNT
CMDDE2:	CAME	T1,(P2)		;IS THIS THE COMMAND WE WANT?
	 JRST	CMDDE3		;NOPE, TRY FOR NEXT ONE
	PUSHJ	P,CMDREM	;REMOVE IT.
CMDDE3:	PUSHJ	P,CMDADV	;ADVANCE POINTERS
	 JRST	CMDDE2		;AND TRY NEXT LOCATION IN COMMAND DIRECTORY
	JRST	CMDDE1		;AND DO THE NEXT COMMAND HE SUPPLIED US WITH
;FUNCTION .CMLST
;LIST THE COMMAND NAMES WE HAVE DEFINED. SUITABLE FOR USE BY "HELP" IN
;INFORMING THE USER SIMPLY THE NAMES AND NUMBER OF COMMANDS HE HAS DEFINED.

CMDLST:	PUSHJ	P,SAVE4##	;SINCE CMDINI TRASHES ALL 4 P REGISTERS
	SETZ	P1,		;START WITH ZERO COMMANDS
	PUSHJ	P,CMDINI	;INITIALIZE POINTERS TO COMMAND LISTS
	JUMPE	P2,CMDLS4	;IF NO COMMANDS, DON'T COUNT EM
CMDLS1:	SKIPE	(P2)		;DO WE HAVE A COMMAND NAME DEFINED?
	SKIPN	(P3)		;AND DO WE HAVE A POINTER TO A COMMAND BLOCK?
	SKIPA			;NO, DON'T COUNT THIS COMMAND
	AOJ	P1,		;INCREMENT NUMBER OF COMMANDS WE HAVE FOUND
	PUSHJ	P,CMDADV	;ADVANCE TO NEXT COMMAND POINTER
	 JRST	CMDLS1		;AND GO TRY TO COUNT ANOTHER COMMAND
CMDLS4:	PUSHJ	P,GETWRD##	;FIND OUT HOW MANY WORDS HE HAS ALLOCATED FOR US
	 JRST	CMDADC		;ADDRESS CHECK.
	EXCH	T1,P1		;SAVE NUMBER OF WORDS WE ARE ALLOWED
	PUSHJ	P,PUTWRD##	;TELL THE USER HOW MANY COMMANDS WE HAVE
	 JRST	CMDADC		;ADDRESS CHECK, TELL HIM NOT TO USE HISEG
	PUSHJ	P,CMDINI	;RE-INITIALIZE POINTERS TO COMMANDS
	JUMPE	P2,CPOPJ1##	;IF NO COMMANDS, RETURN
CMDLS2:	SKIPE	T1,(P2)		;DO WE HAVE A COMMAND NAME DEFINED?
	SKIPN	(P3)		;AND DOES IT HAVE A POINTER TO A COMMAND BLOCK
	JRST	CMDLS3		;NO, SKIP IT
	PUSHJ	P,CMDPUT	;PUT THIS COMMAND NAME IN HIS BLOCK
	 POPJ	P,		;PROPAGATE ERROR
CMDLS3:	PUSHJ	P,CMDADV	;ADVANCE TO NEXT COMMAND
	 JRST	CMDLS2		;AND GO GET THE NEXT NAME TO STORE
	RETSKP			;RETURN SUCCESS, WE HAVE GIVEN HIM ALL NAMES
;FUNCTION .CMRET
;RETURN INFORMATION ON A SINGLE COMMAND

CMDRET:	PUSHJ	P,SAVE4##	;SINCE CMDINI DESTROYS ALL P ACS
	PUSHJ	P,GETWRD##	;GET NUMBER OF WORDS WE ARE ALLOWED TO RETURN
	 JRST	CMDADC		;BOGUS ADDRESS
	MOVE	P1,T1		;SAVE NUMBER OR WORDS WE ARE ALLOWED
	HRRZ	T1,M		;FIRST ADDRESS WE ARE GOING TO RETURN TO
	HRLI	T1,(IFIW)	;MAKE SECTION RELATIVE
	MOVE	T2,P1		;GET WORD COUNT
	PUSHJ	P,ARNGE##	;RANGE CHECK ARGUMENTS
	  JRST	CMDADC		;ADDRESS CHECK
	  JFCL			;ADDRESS OK BUT ILLEGAL FOR I/O (IGNORED HERE)
	PUSHJ	P,GETWR1##	;GET NEXT WORD (NAME TO SEARCH FOR)
	 JRST	CMDADC		;ADDRESS CHECK
	SUBI	M,2		;SO THAT WE CAN OVERWRITE THESE ARGUMENTS
	PUSHJ	P,CMDINI	;INITIALIZE COMMAND TABLE POINTERS
	JUMPE	P2,CMDNSN	;IF NO COMMANDS, WE AREN'T GOING TO FIND IT
CMDRE2:	CAMN	T1,(P2)		;IS THIS THE COMMAND WE ARE LOOKING FOR?
	JRST	[SKIPN U,(P3)	;DOES IT HAVE A BLOCK POINTER?
		JRST .+1	;NOPE, IGNORE IT
		JRST CMDCRT]	;AND LIST THE COMMAND INTO HIS BUFFER
	PUSHJ	P,CMDADV	;NO, ADVANCE TO NEXT COMMAND
	 JRST	CMDRE2		;AND LOOK FOR NEXT COMMAND
	JRST	CMDNSN		;NO SUCH COMMAND NAME
;FUNCTION .CMDMP
;DUMP THE COMMAND DATA BASE. SUITABLE FOR READING/RESTORING AN ENTIRE
;COMMAND DATA BASE ACROSS LOGINS.

CMDDMP:	PUSHJ	P,SAVE4##	;AVOID TRASHING A MONITOR UUO
	PUSHJ	P,GETWRD##	;GET NUMBER OF WORDS WE ARE ALLOWED TO RETURN
	  JRST	CMDADC		;HE GAVE US A TURKEY ADDRESS.
	MOVE	P1,T1		;SAVE NUMBER OF WORDS WE ARE ALLOWED TO RETURN
	HRRZ	T1,M		;FIRST ADDRESS WE ARE GOING TO RETURN STUFF TO.
	HRLI	T1,(IFIW)	;MAKE SECTION RELATIVE
	MOVE	T2,P1		;GET WORD COUNT
	PUSHJ	P,ARNGE##	;RANGE CHECK ARGUMENTS
	  JRST	CMDADC		;ADDRESS CHECK
	  JFCL			;ADDRESS OK BUT ILLEGAL FOR I/O (IGNORED HERE)
	SUBI	M,1		;SINCE WE DO PUTWD1'S LATER
	PUSHJ	P,CMDINI	;INITIALIZE POINTERS
	JUMPE	P2,CMDDM9	;IF NO COMMANDS, TELL HIM THAT.

CMDDM1:	SKIPE	(P2)		;DO WE HAVE A COMMAND DEFINED?
	SKIPN	U,(P3)		;GET POINTER TO THIS COMMAND'S BLOCK
	JRST	CMDDM8		;NO COMMAND, TRY FOR NEXT COMMAND
	PUSHJ	P,CMDCRT	;RETURN THIS COMMAND TO USER'S BUFFER
	 POPJ	P,		;HMM. MUSTA RUN OUTA BUFFER SPACE
CMDDM8:	PUSHJ	P,CMDADV	;ADVANCE POINTERS
	 JRST	CMDDM1		;AND RETURN NEXT COMMAND
CMDDM9:	SETZ	T1,		;A ZERO WORD TERMINATOR
	PUSHJ	P,CMDPUT	;TERMINATE LIST OF COMMANDS
	 POPJ	P,		;WHAT TERRIBLE LUCK!
	RETSKP
;UTILITY ROUTINES, CALLED BY ABOVE FUNCTIONS

;RETURN A COMMAND TO USER'S BUFFER.
;ARGS
;P1/ NUMBER OF WORDS LEFT IN USERS BUFFER
;P2-P4/ AS SET UP BY CMDINI AND CMDADV

CMDCRT:	MOVE	T4,(U)		;GET NUMBER OF WORDS IN OUR BLOCK
	MOVEI	T1,1(T4)	;MAKE IT NUMBER OF WORDS USER UNDERSTANDS
	LDB	T2,P4		;GET UNIQUENESS BITS
	HRL	T1,T2		;MAKE IT THE FLAGS IN LEFT HALF
	PUSHJ	P,CMDPUT	;PUT THIS WORD IN USER'S BUFFER
	 POPJ	P,		;HMM. WE JUST RAN OUT OF ROOM.
	MOVE	T1,(P2)		;GET COMMAND NAME
	PUSHJ	P,CMDPUT	;PUT IT IN THE USER'S BUFFER
	 POPJ	P,		;RAN OUT OF ROOM.
	SUBI	T4,1		;DECREMENT NUMBER OF WORDS LEFT TO GO
CMDCR3:	ADDI	U,1		;POINT TO NEXT WORD IN COMMAND BLOCK
	MOVE	T1,(U)		;GET WORD FROM COMMAND BLOCK
	PUSHJ	P,CMDPUT	;AND PUT IT IN USER'S BLOCK
	 POPJ	P,
	SOJG	T4,CMDCR3	;DO UNTIL FINISHED THIS BLOCK
	RETSKP			;RETURN INDICATING THAT IT FIT.


;PUT WORDS INTO USER'S BUFFER, CHECKING TO MAKE SURE THEY FIT.
;PRESERVES THE T ACS, MODIFIES M AND P1
CMDPUT:	PUSHJ	P,SAVT##	;AVOID TRASHING T ACS
	SOJLE	P1,CMDDNF	;MAKE SURE WE CAN FIT THIS IN USER'S BUFFER
	PUSHJ	P,PUTWD1##	;PUT THIS IN NEXT WORD OF USER'S BUFFER
	RETSKP			;RETURN SUCCESS


;REMOVE A COMMAND FROM TABLES.
;CALL WITH (P2)NAME, (P3)DISPATCH, P4/BPT TO UNIQNESS
CMDREM:	SETZB	T2,(P2)		;YUP, WIPE COMMAND NAME
	EXCH	T2,(P3)		;WIPE DISPATCH POINTER
	HRRZ	T1,(T2)		;GET NUMBER OF WORDS IN ENTRY
	PUSHJ	P,GVFWDS##	;RETURN THE FUNNY SPACE
	SETZ	T2,		;CLEAR AGAIN.
	DPB	T2,P4		;AND WIPE UNIQUENESS BITS (JUST FOR GRINS)
	POPJ	P,		;AND RETURN.

;ADVANCE POINTERS TO NEXT COMMAND. MADE INTO ROUTINE TO GUARANTEE EVERYONE
;USES SAME PROCEDURE.
CMDADV:	AOJ	P3,		;INCREMENT POINTER TO DISPATCH
	IBP	P4		;INCREMENT UNIQUENESS POINTER
	AOBJN	P2,CPOPJ	;RETURN NON SKIP IF STILL THINGS TO LOOK AT
	RETSKP			;NOTHING MORE TO LOOK AT. SKIP RETURN.

;INITIALIZE POINTERS FOR ABOVE. SETS UP P2,P3,P4
;CHECK FOR P2=0 TO INDICATE NO COMMAND DATA BASE
CMDINI:	MOVE	P2,.PDCMN##(W)	;GET POINTER TO COMMAND NAMES
	HRRZ	P3,.PDUNQ##(W)	;GET POINTER TO COMMAND DISPATCHES
	HRLI	P4,(POINT CM.BSZ,,CM.BSZ-1) ;BYTE POINTER FOR UNIQUENESS BITS
	HLR	P4,.PDUNQ##(W)	;GET POINTER TO OUR TABLE OF UNIQUENESS
	POPJ	P,

;EXPAND COMMAND DIRECTORY. NEW NUMBER OF COMMANDS IN P1.
CMDXPN:
	PUSHJ	P,SAVE2##	;AVOID TRASHING OUR TOP LEVEL
	MOVE	P2,.PDCMN##(W)	;SAVE A POINTER TO CURRENT COMMAND LIST
	PUSHJ	P,CMDCOR	;AND ALLOCATE MORE CORE.
	 POPJ	P,		;PROPAGATE THIS ERROR.
	HLRO	T3,P2		;MINUS NUMBER OF COMMAND SLOTS WE USED TO HAVE
	MOVNS	T3		;NUMBER OF COMMAND SLOTS
	HRL	T1,P2		;POINTER TO OLD COMMAND DIRECTORY
	HRR	T1,.PDCMN##(W)	;POINTER TO NEW COMMAND DIRECTORY
	MOVE	T2,T3		;COPY NUMBER OF COMMANDS TO COPY
	ADDI	T2,(T1)		;POINTER TO FIRST WORD BEYOND THESE COMMANDS.
	BLT	T1,-1(T2)	;COPY OLD COMMANDS TO NEW TABLE.
	HRR	T1,.PDUNQ##(W)	;POINTER TO NEW DISPATCHES TABLE
	HRRZ	T2,T1		;DESTINATION FOR BLT
	ADD	T2,T3		;POINT TO FIRST WORD BEYOND DISPATCHES.
	BLT	T1,-1(T2)	;COPY NEW DISPATCHES.
	IDIVI	T3,CM.BPW	;NUMBER OF WORDS IN UNQTAB
	HLR	T1,.PDUNQ##(W)	;NEW POINTER TO UNQTAB
	HRRZ	T2,T1		;DESTINATION FOR BLT
	ADD	T2,T3		;POINT TO FIRST WORD BEYOND UNQTAB
	BLT	T1,-1(T2)	;AND COPY THE UNQTAB DATA
	IMULI	T3,CM.BPE	;NUMBER OF WORDS FOR USED FOR ENTIRE TABLE
	MOVE	T1,T3		;COPY NUMBER OF WORDS TO RETURN
	HRRZ	T2,P2		;WHERE OUR TABLE IS
	PUSHJ	P,GVFWDS##	;AND RETURN FUNNY FOR OLD COMMAND DIRECTORY
	RETSKP			;RETURN SUCCESS

;ALLOCATE CORE FOR COMMANDS DIRECTORY. RETURNS WITH .PDCMN AND .PDUNQ SET UP
;AND ALL COMMAND NAMES SET TO ZERO.

CMDCOR:	PUSHJ	P,SAVE2##	;PRESERVE P ACS
	MOVEI	T2,CM.BP1(P1)	;NUMBER OF COMMANDS TO DEFINE (ROUNDING UP)
	IDIVI	T2,CM.BPW	;NUMBER OF WORDS IN UNQTAB
	MOVE	P2,T2
	IMULI	T2,CM.BPW	;NUMBER OF WORDS FOR OUR TABLES (MULTIPLE OF 6)
	MOVE	P1,T2
	ASH	T2,1		;NUMBER OF WORDS FOR NAMES+DISPATCH
	ADD	T2,P2		;ADD IN NUMBER OF WORDS FOR UNQTAB
	PUSHJ	P,GTFWDC##	;GET CACHED FUNNY SPACE.
	 JRST	CMDNER		;NOT ENOUGH ROOM.
	MOVE	T2,T1		;POINTER TO COMMAND NAMES
	ADD	T2,P1		;POINTER TO COMMAND DISPATCHES
	MOVEI	T3,1(T1)	;MAKE A BLT POINTER TOWARDS NAMES
	HRL	T3,T1		;LEFT HALF OF BLT POINTER
	SETZM	(T1)		;CLEAR FIRST WORD OF COMMAND NAMES
	BLT	T3,-1(T2)	;AND ALL THE REST OF THE WORDS TOO.
	MOVN	T3,P1		;NEGATIVE NUMBER OF COMMANDS ALLOWED IN LIST
	HRL	T1,T3		;MAKE AN AOBJN POINTER TO COMMANDS
	MOVE	T3,T2		;POINTER TO COMMAND DISPATCHES
	ADD	T3,P1		;POINTER TO COMMAND UNQTAB
	HRL	T2,T3
	MOVEM	T2,.PDUNQ##(W)	;SAVE POINTERS (NOTE ORDER: .PDCMN CAN'T BE
	MOVEM	T1,.PDCMN##(W)	;	SAVED UNTIL .PDUNQ IS SET UP)
	RETSKP

;INSERT COMMANDS SUPPLIED BY UUO TO OUR LIST OF USER DEFINED COMMANDS. IT IS
;THE RESPONSOBILITY OF THE CALLER TO INSURE THAT THERE ARE ENOUGH AVAILABLE
;COMMAND SLOTS IN THE COMMAND DIRECTORY (.PDCMN).
CMDINS:	PUSHJ	P,SAVE4##	;AVOID TRASHING ACS.
	PUSHJ	P,CMDINI	;INITIALIZE POINTERS
CMDIN2:	UMOVE	U,(M)		;GET LENGTH OF COMMAND ENTRY
	JUMPE	U,CPOPJ1	;AT END, EXIT.
	UMOVE	P1,1(M)		;GET COMMAND NAME
	JUMPE	P1,CMDIN6	;IF NO COMMAND NAME, PITCH IT.
CMDI25:	CAMN	P1,(P2)		;IS THIS THE SAME COMMAND AS OURS?
	 JRST	CMDIN4		;YES, USE IT.
	PUSHJ	P,CMDADV	;ADVANCE POINTERS
	 JRST	CMDI25		;AND TRY FOR ANOTHER COMMAND
	PUSHJ	P,CMDINI	;INITIALIZE POINTERS AGAIN
CMDIN3:	SKIPN	(P2)		;IS THIS COMMAND NAME TAKEN?
	 JRST	CMDIN5		;NO, CONTINUE
	PUSHJ	P,CMDADV	;ADVANCE POINTERS
	 JRST	CMDIN3		;AND TRY FOR ANOTHER SLOT
	STOPCD	RMVCMD,DEBUG,NCE ;++NO COMMAND SLOT AVAILABLE.

CMDIN4:	PUSHJ	P,CMDREM	;REMOVE THIS COMMAND
CMDIN5:	HLRZ	T1,U		;GET UNIQNESS BITS
	DPB	T1,P4		;STORE FOR THIS COMMAND
	HRRZS	U		;CLEAR FLAGS
	CAIGE	U,3		;MUST CONTAIN AT LEAST UP TO .CMFIL
	 JRST	CMDIAL		;ILLEGAL ARGUMENT LIST.
	SOS	T2,U		;OUR TABLE IS ONE WORD SHORTER THAN USER'S
	PUSHJ	P,GTFWDC##	;GET SOME CACHED FREESPACE
	 JRST	CMDNER		;NO MORE ROOM
	MOVEM	T1,(P3)		;SAVE POINTER TO THIS BLOCK
	HRRZM	U,(T1)		;SAVE LENGTH IN BLOCK
	MOVEI	T2,1(T1)	;DESTINATION OF THIS BLOCK
	HRLI	T2,2(M)		;SOURCE FROM USER
	ADDI	T1,-1(U)	;POINT TO LAST WORD IN OUR BLOCK
	EXCTUX	<BLT T2,(T1)>	;AND COPY OUR DATA
	MOVEM	P1,(P2)		;AND NOW SAVE THE COMMAND NAME
CMDIN6:	ADDI	M,1(U)		;POINT PAST THIS COMMAND
	JRST	CMDIN2		;AND ADD THE NEXT COMMAND


;COUNT COMMANDS SUPPLIED IN UUO. RETURNS NUMBER OF COMMANDS TO DEFINE IN P1

CMDCNT:	SETZ	P1,		;START WITH 0 COMMANDS COUNTED.
	PUSHJ	P,SAVUM##	;SAVE M (U AND W GO ALONG FOR THE RIDE)
CMDCN1:	PUSHJ	P,GETWRD##	;GET FIRST WORD OF ARGUMENT (LENGTH)
	  JRST	CMDADC		;ADDRESS CHECK.
	JUMPE	T1,CPOPJ1##	;END OF LIST, GET CORE TO STORE THESE IN.
	HRRZS	T1		;CLEAR FLAGS AWAY THIS TIME.
	CAIL	T1,4		;MUST CONTAIN UP TO THE FILENAME
	CAILE	T1,MAXLVL##+6	;SFDS+PPN+EXT+NAME+DEV+COMMAND+FLAGS
	JRST	CMDIAL		;ILLEGAL ADDRESS LIST
	MOVE	T2,T1		;SAVE LENGTH
	ADDI	M,2		;POINT TO NAME OF COMMAND
	PUSHJ	P,GETWRD##	;GET COMMAND NAME
	  JRST	CMDADC		;ADDR CHECK
	JUMPE	T1,CMDIAL	;MUST HAVE A NAME
	ADDI	M,-2(T2)	;POINT TO NEXT COMAND BLOCK
	AOJA	P1,CMDCN1	;AND FIND ANOTHER COMMAND

;REMOVE ALL COMMANDS.
RMVCMD:
	PUSHJ	P,SAVE4##	;WE USE P1 AND P2
	PUSHJ	P,CMDINI	;INITIALIZE POINTERS
	JUMPE	P2,CPOPJ##	;IF NO POINTER TO NAMES, SUCCESS
RMVCM1:	SKIPE	(P2)		;ZERO OUT THE COMMAND NAME FIRST
	SKIPN	T2,(P3)		;AND GET POINTER TO THE FILESPEC BLOCK
	JRST	RMVCM2		;NO NAME OR POINTER, IGNORE THIS COMMAND
	PUSHJ	P,CMDREM	;REMOVE THIS COMMAND
RMVCM2:	PUSHJ	P,CMDADV	;ADVANCE POINTERS
	 JRST	RMVCM1		;AND DO ANOTHER COMMAND

	HLRO	T1,.PDCMN##(W)	;GET NUMBER OF ENTRIES
	IMUL	T1,[-CM.BPE]	;CONVERT TO POSITIVE NUMBER OF 6 BIT BYTES
	ADDI	T1,CM.BP1	;ROUND UP TO NEAREST WORD
	IDIVI	T1,CM.BPW	;AND CONVERT BACK DOWN TO NUMBER OF WORDS
	HRRZ	T2,.PDCMN##(W)	;GET POINTER TO TABLE
	PUSHJ	P,GVFWDS##	;AND RETURN THE TABLES THEMSELVES.
	SETZM	.PDCMN##(W)	;WIPE POINTER TO COMMAND NAMES
	SETZM	.PDUNQ##(W)	;AND POINTER TO UNQTAB AND DISPATCHES
	POPJ	P,
	SUBTTL	CALLS TO SEGCON FOR SETUWP AND REMAP

;SET OR CLEAR USER MODE WRITE PROTECT BIT IN HIGH SEG FOR THIS USER ONLY
;CALL:	MOVEI AC,0 OR 1
;	CALL AC,[SIXBIT /SETUWP/] OR CALLI AC,34
;	ERROR - MACHINE OR MONITOR CANNOT HANDLE TWO REG, OR TRYING TO CLEAR
;			;UWP OF A SHARABLE SEG(AC=1 ON RETURN)
;	OK RETURN - AC CONTAINS PREVIOUS SETTING( OR JOB HAS NO HIGH SEG)

SETUWP=USTUWP##			;GO TO ROUTINE IN SEGCON
				;IF FT2REL=0, SETUWP DOES RTZER



;UUO TO REMAP TOP PART OF LOW SEGMENT INTO HIGH SEGMENT
;PREVIOUS HIGH SEG(IF ANY) IS KILLED AND A NEW SEGMENT NUMBER IS ASSIGNED
;TO THIS JOB. REMAP IS USED BY LOADER AND GET
;CALL:	MOVEI AC,NEW HIGHEST USER ADR IN LOW SEG(EXEC ORS IN 1777)
;	CALL AC,[SIXBIT /REMAP/] OR CALLI AC,35
;	ERROR RETURN, MACHINE OR EXEC CANNOT HANDLE 2 REG OR DESIRED ADR
;			;GREATER THAN OLD LOW SEG
;	OK RETURN, LOW SEG ABOVE ARG NOW THE HIGH SEG

REMAP=UREMAP##			;CORE1 MODULE IN SEGCON
	SUBTTL	TRIVIAL UUOS (LIGHTS, TIMER AND SWITCH)

;SET LIGHTS ON CONSOLE FROM USER PROGRAM

;CALL AC,[SIXBIT /DATAO/] OR CALLI AC,-1

;THIS IS AN EXAMPLE OF A USER DEFINED UUO WITH A NEGATIVE CALLI ARG.

LIGHTS:
	POPJ	P,		;RETURN TO HIM

;RETURN TIME OF DAY IN JIFFIES (60THS,50THS OR MS)


TIMER:	SKIPA	T1,TIME##	;FALL INTO STOTAC

;RETURN DATA SWITCHES


SWITCH:	SETZ	T1,		;RETURN ZERO
	JRST	STOTAC##	;GO STORE VALUE
	SUBTTL	ENTVC. UUO

;THE ENTVC. UUO SETS OR RETURNS THE PROGRAMS CURRENT ENTRY VECTOR
;CALLING SEQUENCE:
;	XMOVEI	AC,ADDR
;	ENTVC.	AC,
;	<ERROR RETURN>
;	<NORMAL RETURN>
;	...
;ADDR/	FUNCTION		;READ OR SET (SIGN BIT ON MEANS SET)
;ADDR+1/LENGTH			;(JRST) OR 0-N (WHERE N IS .LE.37)
;ADDR+2/EXEC-ADDR		;30 BIT ADDRESS OF ENTRY VECTOR OR START ADDRESS
;				; IF LENGTH = 0 OR (JRST)
;

ENTVC:	PUSHJ	P,SAVE4##	;SAVE SOME ACS
	MOVEI	T2,3		;WANT THREE WORDS OF ARG LIST
	PUSHJ	P,ARNGE##	;SEE IF THE LIST IS WELL-FORMED
	  JRST	ENVADC		;NO
	  JFCL			;IGNORE I/O ILLEGAL HERE
	PUSHJ	P,SXPCS##	;MAKE SURE THE REFERENCES WILL WORK
	  JRST	ENVADC		;ADDRESS CHECK
	SKIPL	T1		;IF GLOBAL,
	SOSA	T1		;PRE-DECREMENT GLOBALLY
	HRRI	T1,-1(T1)	;ELSE LOCALLY
	MOVE	M,T1		;POINT AT ARGUMENT LIST (PREDECREMENTED)
	MOVSI	P4,-3		;FETCH 3 ARGS INTO P1-P3
ENTVC1:	PUSHJ	P,GETEW1##	;GET NEXT ARG
	  JRST	ENVADC		;ADDRESS CHECK
	MOVEM	T1,P1(P4)	;STORE ARGUMENT IN AN AC
	AOBJN	P4,ENTVC1	;FETCH ALL 3 ARGUMENTS
	SKIPN	P2		;LENGTH = 0?
	MOVEI	P2,(JRST)	;YES, SUBSTITUTE (JRST)
	HRRZ	T1,P1		;FUNCTION CODE
	JUMPN	T1,ENVIFC	;ONLY FUNCTION 0 IS DEFINED FOR NOW
	TLNE	P1,377777	;ANY UNKNOWN BITS?
	JRST	ENVIAL		;ILLEGAL ARG LIST
	JUMPL	P1,ENTVC4	;GO IF SET FUNCTION
;HERE TO READ THE ENTRY VECTOR
	SKIPE	P3,.USUSA	;ENTRY VECTOR SETUP?
	JRST	ENTVC2		;YES
	MOVEI	P2,(JRST)	;NO, JUST RETURN STARTING ADDRESS
	SKIPE	P3,.USUSN	;INCLUDING SECTION IF APPLICABLE
	LSH	P3,P2WLSH##	; ..
	HRR	P3,.JDAT+.JBSA##; ..
	TRNN	P3,-1		;EXCEPT IF NO START ADDRESS,
	SETZB	P2,P3		;THEN THERE'S NOTHING AT ALL
	JRST	ENTVC3		;STORE THE ANSWERS AND RETURN
ENTVC2:	LDB	P2,[POINT 5,P3,5] ;LENGTH
	TLZ	P3,(77B5)	;VIRTUAL ADDRESS OF THE ENTRY VECTOR
	SKIPN	P2		;HAVE A LENGTH?
	MOVEI	P2,(JRST)	;NO, ADMIT TO START ADDRESS FORMAT
ENTVC3:	SUBI	M,1		;BACK UP FOR STORING ANSWERS
	MOVE	T1,P2		;LENGTH TO T1
	PUSHJ	P,PUTEWD##	;STORE THAT
	  JRST	ENVADC		;ADDRESS CHECK
	MOVE	T1,P3		;ADDRESS TO T1
	PUSHJ	P,PUTEW1##	;STORE THAT
	  JRST	ENVADC		;ADDRESS CHECK
	JRST	CPOPJ1##	;AND GIVE SKIP RETURN TO THE USER
;HERE TO SET THE ENTRY VECTOR
ENTVC4:	CAIN	P2,(JRST)	;JUST SETTING THE START ADDRESS?
	JRST	ENTVC5		;YES, JUST STORE THE ADDRESS AND RETURN
	SKIPL	P2		;MUST HAVE POSITIVE LENGTH
	CAILE	P2,37		;LENGTH LESS THAN 32 WORDS?
	JRST	ENVIAL		;DON'T HAVE ROOM FOR ANY MORE SO SAY ILL ARG
	TRO	P2,40		;TO MAKE IT EASY TO TEST FOR "REAL" ENTRY VECTOR
	DPB	P2,[POINT 6,P3,5] ;FOR .USUSA
	CAIGE	P2,42		;EXCLUDING A REENTER ADDRESS?
	SETZM	.JDAT+.JBREN##	;YES, DON'T CONFUSE HUMANS
	SETZM	.JDAT+.JBVER##	;ALWAYS CLEAR THIS IN CASE OMITTED FROM VECTOR
	CAIGE	P2,43		;SPECIFYING A VERSION NUMBER?
	JRST	ENTVC5		;NO, JUST STORE NUMBERS AND RETURN
	MOVE	M,P3		;ARG LIST POINTER
	ADDI	M,2		;WHERE THE VERSION NUMBER IS
	TLZ	M,770000	;ISOLATE THE ADDRESS
	PUSHJ	P,GETXWD##	;GET THE VERSION NUMBER
	  JRST	ENTVC5		;IGNORE ADDRESS CHECK
	MOVEM	T1,.JDAT+.JBVER## ;STORE IT WHERE HUMANS LOOK
ENTVC5:	MOVEM	P3,.USUSA	;STORE ADDRESS OF ENTRY VECTOR
	JRST	CPOPJ1##	;AND TELL HIM HE DID GOOD

;ERROR CODES
EVIAL%==1			;ILLEGAL ARGUMENT LIST
EVIFC%==2			;ILLEGAL FUNCTION CODE
EVADC%==3			;ADDRESS CHECK

	ERCODX	ENVIAL,EVIAL%
	ERCODX	ENVIFC,EVIFC%
	ERCODX	ENVADC,EVADC%
SUBTTL DVPHY. UUO
;THE DVPHY. UUO RETURNS THE PHYSICAL NAMES OF ALL THE DEVICES OF A
; CERTAIN TYPE OR OPTIONALLY, THE PHYSICAL NAMES OF ALL THE DEVICES
; ON THE SYSTEM (EXCLUDING PTYS, TTYS, MPXS, AND DSK).
;CALLING SEQUENCE:
;	MOVE	AC,[N,,ADDR]	;COUNT,,ARGUMENT
;	DVPHY. 	AC,		;OR CALLI AC,164
;	<ERROR RETURN>
;	<NORMAL RETURN>
;WHERE
;ADDR:	DEVICE TYPE OR -1 IF ALL DEVICES
;+1	0 FOR FIRST CALL, PREVIOUS DEVICE NAME ON SUBSEQUENT CALLS
;NEXT PHYSICAL DEVICE NAME IS RETURNED IN ADDR+1 OR 0 IF LAST
; DEVICE IN THE SYSTEM OF THAT TYPE.

DVPHY.:	PUSHJ	P,SAVE1##	;SAVE P1
	HRR	M,T1		;ADR OF ARG BLOCK
	HLRE	T1,T1		;LENGTH OF BLOCK
	MOVMS	T1		;MAKE SURE IT'S POSITIVE
	CAIGE	T1,2		;ENOUGH ARGS?
	JRST	DPEIAL		;INVALID ARG LIST
	PUSHJ	P,GETWDU##	;GET DEVICE TYPE
	CAILE	T1,TYPMAX	;LEGAL?
	JRST	DPENDT		;NO SUCH DEVICE TYPE
	CAME	T1,[-1]		;WANT EVERYTHING?
	JUMPL	T1,DPENDT	;NO, NO DEVICE IF NEGATIVE
	MOVE	P1,T1		;SAVE ARGUMENT
	PUSHJ	P,GETWD1##	;GET NEXT ARG
	JUMPGE	P1,DVPHY2	;GO IF DONT WANT EVERYTHING
	HLRZ	F,DEVLST##	;ALL, START AT START OF DEVS
	JUMPE	T1,DVPHY1	;GO IF FIRST CALL
	PUSHJ	P,DEVPHY	;NOT FIRST, FIND THIS DEVICE
	  JRST	DPENPD		;NOT THERE
	PUSHJ	P,NXDDB		;POINT AT NEXT DEVICE ON CHAIN
	  JUMPE	F,DVPHY4
DVPHY1:	PUSHJ	P,NOTPTD	;FIND NEXT DEVICE
	  JRST	DVPHY4		;NO MORE, RETURN A ZERO
	JRST	DVPHY6		;WON, STORE T1 AND SKIP RETURN
DVPHY2:	JUMPN	T1,DVPHY3	;GO IF NOT 1ST CALL
	MOVE	T1,P1		;AND HERE I GOT CONFUSED
	PUSHJ	P,DVSDVT
	  JRST	DPENDT
	JRST	DVPHY5
DVPHY3:	PUSHJ	P,DEVPHY
	  JRST	DPENPD
DVPHY7:	PUSHJ	P,NXDDB		;POINT AT NEXT DEVICE ON CHAIN
	  JUMPE	F,DVPHY4
	LDB	T1,PDVTYP##
	CAIE	T1,.TYDSK/.TYEST
	CAME	T1,P1
DVPHY4:	TDZA	T1,T1
DVPHY5:	MOVE	T1,DEVNAM(F)
	JUMPE	T1,DVPHY6	;IF NO DEVICE, JUST STORE
	CAIE	P1,.TYTTY/.TYEST ;IS IT A TTY?
	 JRST	DVPHY6		;NO, JUST STORE
	MOVE	T2,DDBLDB##(F)	;YES, GET ASSOCIATED LDB
	JUMPE	T2,DVPHY7	;SKIP THIS ONE IF NOT ATTACHED
DVPHY6:	AOS	(P)
	PJRST	PUTWDU##
;SUBROUTINE TO SEARCH FOR A DEVICE TYPE
;CALLING SEQUENCE:
;	MOVEI	T1,DEVICE TYPE
;	PUSHJ	P,DVSDVT
;RETURNS CPOPJ IF NOT FOUND. CPOPJ1 IF FOUND, F POINTS AT THE FIRST
; DDB IN THE DEVICE CHAIN WHICH IS THAT DEVICE TYPE,

DVSDVT:	HLRZ	F,DEVLST##
DVSDV1:	LDB	T2,PDVTYP##
	CAMN	T1,T2
	JRST	CPOPJ1##
	PUSHJ	P,NXDDB
	  JUMPE	F,CPOPJ##
	JRST	DVSDV1

;SUBROUTINE TO SEARCH FOR THE NEXT DEVICE WHICH IS NOT A PTY, TTY,
; OR DSK.
;CALLING SEQUENCE:
;	MOVE	F,PLACE TO START ON THE DDB CHAIN
;	PUSHJ	P,NOTPTD
;RETURNS CPOPJ IF NO MORE DEVICES, CPOPJ1 WITH F POINTING AT THE
; DDB IF A DEVICE WHICH IS NOT A PTY, TTY, OR DSK IS FOUND, T1= DEVICE
; NAME.

NOTPTD:	JUMPE	F,CPOPJ##
	MOVEI	T1,NOTTTL
	LDB	T2,PDVTYP##
NOTPT1:	CAIE	T2,@NOTTBL-1(T1)
	SOJG	T1,NOTPT1
	JUMPLE	T1,NOTPT3
NOTPT2:	PUSHJ	P,NXDDB		;POINT AT NEXT DEVICE ON CHAIN
	  JFCL
	JRST	NOTPTD
NOTPT3:	SKIPE	T1,DEVNAM(F)
	JRST	CPOPJ1##
	JRST	NOTPT2

NOTTBL:	XWD	ZERO5,.TYPTY/.TYEST
	XWD	ZERO5,.TYTTY/.TYEST
	XWD	ZERO5,.TYDSK/.TYEST
	XWD	ZERO5,.TYMPX/.TYEST
	XWD	ZERO5,.TYTSK/.TYEST
	XWD	ZERO5,TYPMAX+1
NOTTTL==.-NOTTBL
;DVPHY. ERROR CODES
DVPIA%==1	;INVALID ARGUMENT LIST
DVPIT%==2	;INVALID DEVICE TYPE
DVPNP%==3	;NO SUCH PHYSICAL DEVICE
DVPNT%==4	;NO SUCH DEVICE TYPE

ERCODE DPEIAL,DVPIA%	;INVALID ARGUMENT LIST
ERCODE DPEIDT,DVPIT%	;INVALID DEVICE TYPE
ERCODE DPENPD,DVPNP%	;NO SUCH PHYSICAL DEVICE
ERCODE DPENDT,DVPNT%	;NO SUCH DEVICE TYPE
	SUBTTL	DEVCHR AND DEVSIZ UUO'S

;RETURN DEVICE CHARACTERISTICS

UDVCHR:	PUSHJ	P,DVCHR		;CALL INTERNAL ROUTINE TO DO THE WORK
	PJRST	STOTAC##	;AND RETURN THE ANSWER TO THE USER

IFN FTSPL, <
DVCH0:
	TLOE	P1,PHONLY	;ALREADY HAVE REAL DEVICE ?
	JRST	DVCH1		;YES, GET DEVMOD

	MOVE	T1,DEVNAM(F)	;NO, GET NAME USER SUPPLIED
	HRRZ	P2,DEVMOD(F)	;DEVMOD FOR SPOOLED DEVICE
	TRZ	P2,-1-<ASSCON!ASSPRG>	;SAVE ASSCON AND ASSPRG
	JRST	DVCH3		;SKIP OVER SAVE AND CLEARING P2
DVCHR:	PUSHJ	P,SAVE2##	;SAVE P1-P2
	SETZ	P2,		;FIRST CALL - ZERO P2
DVCH3:
>
IFE FTSPL, <
DVCHR:
>
	PUSHJ	P,DVCNSG	;SEARCH FOR DEVICE
	  JRST	ZPOPJ##		;NOT A DEVICE, GIVE ERROR
	SETZ	T3,
	CAMN	T1,[SIXBIT /NUL/]	;NUL DEVICE?
	MOVEI	T3,-1-TTYATC	;YES, LH WILL BE CHANGED

IFN FTSPL, <
	SKIPE	DEVCHR(F)	;IF NOT A FAKE DDB,
	SKIPL	DEVSPL(F)	;IF A SPOOLED DEVICE,
DVCH1:	SKIPA	T1,DEVMOD(F)
	JRST	DVCH0		; GO GET DEVMOD FOR REAL DEVICE
>
IFE FTSPL,<
DVCH1:	MOVE	T1,DEVMOD(F)	;REAL DEVICE FOUND, RETURN DEVMOD
>
IFN FTSPL,<
	PUSHJ	P,CHKSPL	;DEVICE SPOOLED?
	  TRZA	T1,ASSCON!ASSPRG  ;YES, IGNORE WHAT REAL DEV IS DOING
	JRST	DVCH2		;NO
	IOR	T1,P2		; AND SET ASSCON, ASSPRG FROM SPOOLED DDB
	TLO	T1,DVAVAL	;YES, SET AVAILABLE-BIT
DVCH2:
>
	LDB	T2,PJOBN##	;GET JOB NO.  USING DEVICE
	CAME	T2,.CPJOB##	;DOES CURRENT USER ALREADY HAVE IT?
	TRNN	T1,ASSCON+ASSPRG	;NO, IS IT ASSIGNED?
	TLO	T1,DVAVAL	;NO, BUT HE CAN GET IT.
IFN FTNET,<
	TLNN	T1,DVTTY	;IS THIS A TTY?
	JRST	DVCH4		;NO, SKIP VTM TEST
	MOVE	T2,DDBLDB(F)	;YES, GET LDB
	JUMPE	T2,DVCH4	;OK IF NONE
	SE1XCT	<SKIPGE LDBREM##(T2)>	;VTM + SET HOST?
	TLZ	T1,DVAVAL	;YES, IT'S NOT AVAILABLE AFTER ALL
DVCH4:
>
	TLO	T1,(T3)		;SET LH = -1 IF NUL:

	POPJ	P,		;RETURN

;SUBROUTINE TO DETERMINE IF CHARACTERISTICS OF DDB IN F SHOULD BE
; REPLACED BY THOSE OF THE SPOOLED DEVICE.
;CALL IS
;	MOVE	F,DDB-ADR
;	PUSHJ	P,CHKSPL
;	SPOOLED RETURN
;	NOT SPOOLED RETURN
;SPOOLED BIT FOR DEVICE (DEYSPL) RETURNED IN T2; OTHER ACS PRESERVED
IFN FTSPL,<	;IF SPOOLING
CHKSPL:	LDB	T2,DEYSPL##	;GET SPOOL BIT FOR DEVICE
	SKIPN	DEVCHR(F)	; "FAKE" (TABLE) DDB?
	POPJ	P,		;YES
	TDNN	T2,JBTSPL##(J)	;NO. JOB SPOOLING DEVICE?
	  JRST	CPOPJ1##	;NO
	PUSH	P,T1		;MAYBE. SAVE T1
	PUSH	P,T2		; AND T2
	MOVE	T1,DEVMOD(F)	;GET DEVMOD
	LDB	T2,PJOBN##	;AND JOB OWNING DEVICE
	TRNE	T1,ASSCON!ASSPRG	;DEVICE ASSIGNED OR INITED?
	CAME	T2,.CPJOB##	;YES, TO US?
	  SOS	-2(P)		;NO, SPOOLED RETURN
	POP	P,T2		;RESTORE T2
	JRST	TPOPJ1##	;RESTORE T1 AND EXIT SKIP/NO-SKIP
>	;END FTSPL
;RETURN DEVICE TYPE (AND OTHER PROPERTIES)
UDVTYP:	AOS	(P)		;SKIP-RETURN SINCE UUO IS IMPLIEMENTED
	PUSHJ	P,DVTYP
	PJRST	STOTAC##	;AND STORE THE ANSWER

DVTYP:	PUSH	P,T1		;SAVE DEVICE NAME
	PUSHJ	P,DVCHR		;GET DEVICE CHARACTERISTICS
	JUMPE	T1,T2POPJ##	;NO SUCH DEV - RETURN 0
DVTY1:
IFN FTSPL,<
	PUSHJ	P,CHKSPL	;SEE IF DEVICE IS SPOOLED
	  TLOA	T2,.TYSPL!DVAVAL	;YES, SPOOL+AVAILABLE
>	;END CONDITIONAL ON FTSPL

	SETZ	T2,		;NO
	MOVE	T3,T2		;SAVE DEVCHR WORD
	TLZ	T1,-1-DVIN-DVOUT-DVTTY-DVAVAL;SAVE CERTAIN BITS
	OR	T1,T2		;+SPOOL+AVAILABLE
	POP	P,T2		;PUT DEVICE NAME IN T2
	PUSHJ	P,GNRCDV	;IS IT A GENERIC DEVICE?
	  TLO	T1,TY.GEN	;YES
	LDB	T2,DEYTYP##	;GET TYPE+VAR BUFFER SIZE
IFN FTSPL,<
	SKIPN	DEVCHR(F)	;FROM TABLE?
	HLRZ	T2,SPLBIT##(F)	;YES, GET TYPE-NUMBER
>
	TRZE	T2,DERLEN	;VARIABLE BUFFER SIZE?
	TLNE	T1,.TYSPL	;YES, BEING SPOOLED?
	JRST	.+2		;YES
	TLO	T1,.TYVAR	;UNSPOOLED, VARIABLE DEV
	HRR	T1,T2		;GET TYPE INTO T1
	SKIPN	T2		;IF A DISK,
	JUMPL	T3,DVTY2	; IF "DVDIRIN" IS ON ITS NUL:

IFN FTTSK!FTRDX,<
	CAIE	T2,.TYRDA/.TYEST	;IS IT A RDA
	CAIN	T2,.TYTSK/.TYEST	;IS IT A TASK
	TLOA	T1,.TYINT	;YES, SET INTERACTIVE MODE
>
	CAIG	T2,.TYDTA/.TYEST	;DSK OR DTA?
	TLO	T1,.TYMAN	;YES - LOOKUP/ENTER MANDATORY
DVTY2:	LDB	T2,PJOBN##	;OWNER OF DEVICE
IFN FTSPL,<
	SKIPE	DEVCHR(F)	;NO OWNER IF SPOOLED
>
	DPB	T2,[POINT 9,T1,26]	;IN BITS 18-26
IFN FTMSGSER,<
	TLO	T1,TY.MPX	;ASSUME OK
	PUSHJ	P,LGLMPX##	;IS IT OK?
	  TLZ	T1,TY.MPX	;NO--CLEAR BIT
>
	SKIPGE	DEVCHR(F)	;IS THIS A LOWER CASE LPT?
	TLO	T1,TY.LL	;YES
	MOVSI	T2,DVCMDA	;IS THIS AN
	TDNE	T2,DEVCHR(F)	;MDA DEVICE?
	TLO	T1,TY.MDA	;YES
	POPJ	P,
	SUBTTL	NETOP. UUO

;CALL:	XMOVEI	AC,ARGLIS
;	NETOP.	AC,
;	  ERROR CODE IN AC
;	SUCCESS, AC UNCHANGED
;
;
NETOP:	PUSHJ	P,SXPCS##	;VALIDATE THE ARG BLOCK POINTER
	  JRST	NOPADC		;ADDRESS ERROR
	MOVE	M,T1		;COPY FOR FETCHING
	PUSHJ	P,GETEWD##	;GET LENGTH,,FCN
	  JRST	NOPADC		;ADDRESS ERROR
	MOVE	T4,T1		;SAVE IT
	HLRZ	T2,T1		;GET LENGTH OF ARG BLOCK
	HRRZS	T1		;ISOLATE FUNCTION CODE
	SKIPE	T1		;FUNCTION 0 IS ILLEGAL
	CAILE	T1,NETFMX	;LEGAL FUNCTION CODE?
	  JRST	NOPILF		;NOPE
	CAMGE	T2,NETFNL(T1)	;ARG LIST LONG ENOUGH?
	  JRST	NOPLTS		;NOPE
	MOVE	T1,M		;GET ADDRESS OF ARG LIST
	PUSHJ	P,ARNGE##	;ADDRESS CHECK THE ARG BLOCK ITSELF
	  JRST	NOPADC		;NOT ALL ADDRESSABLE
	  JRST	NOPADC		;CAN'T STORE RESULTS
	HRRZ	T1,T4		;GET FCN CODE AGAIN
	PJRST	@NETFND(T1)	;AND GO FOR IT

	DEFINE	NETFNS,<
NETFUN	(0,NOPILF)	;; 0 - ILLEGAL FUNCTION
NETFUN	(7,NET.DI)	;; 1 - DEVICE INFO
>

	DEFINE	NETFUN(LENGTH,DISPATCH),<EXP	LENGTH>
NETFNL:	NETFNS			;TABLE OF ARG LIST LENGTHS
NETFMX==.-NETFNL-1		;MAXIMUM NET. FUNCTION CODE

	DEFINE	NETFUN(LENGTH,DISPATCH),<IFIW	DISPATCH>
NETFND:	NETFNS			;TABEL OF DISPATCH ADDRESSES
	
	NOADC%==1	;ADDRESS CHECK
	NOILF%==2	;ILLEGAL FUNCTION
	NOLTS%==3	;ARG LIST TOO SHORT
	NONSD%==4	;NO SUCH DEVICE
	NODNC%==5	;DEVICE NOT CONNECTED
	NONTY%==6	;DEVICE IS NOT A TTY

	ERCODX	NOPADC,NOADC%
	ERCODX	NOPILF,NOILF%
	ERCODX	NOPLTS,NOLTS%
	ERCODX	NOPNSD,NONSD%
	ERCODX	NOPDNC,NODNC%
	ERCODX	NOPNTY,NONTY%

	INTERN	NOPADC,NOPDNC		;ERRORS NEEDED BY NRTSER & LATSER
	SUBTTL	NETOP. UUO
;FUNCTION CODE 1 - .NOGDI - Device info
; User must fill in words 0 and 2 of arg block
;
;ARGLIS+0/	LENGTH,,FUNCTION
;	+1/	Flags indicating how device is connected
;	+2/	SIXBIT DEVICE NAME, UDX, OR OPEN CHANNEL NUMBER
;	+3/	Output, same results as DEVCHR UUO
;	+4/	Output, same results as DEVTYP UUO
;	+5/	ADDRESS OF STRING BLOCK FOR OUTPUT NODE NAME STRING
;	+6/	ADDRESS OF STRING BLOCK FOR OUTPUT PORT NAME STRING
;
NET.DI:	PUSHJ	P,SAVE2##	;GET A COUPLE OF ACS TO USE
	UMOVE	T1,2(M)		;GET DEVICE/UDX/CHANNEL
	MOVE	P1,T1		;SAVE IT
	S0PSHJ	DVCHR		;FIND DDB AND GET DEVCHR UUO STUFF
	  JUMPE	T1,NOPNSD	;NO SUCH DEVICE
	UMOVEM	T1,3(M)		;STORE DEVCHR UUO INFO
	S0PSHJ	[PUSH	P,P1	;;PUSH DEVICE NAME AND
		   PJRST DVTY1]	;CALL DEVTYP ROUTINE
	UMOVEM	T1,4(M)		;SAVE DEVTYP INFO FOR USER
	ANDI	T1,77		;CLEAR ALL BUT DEVICE TYPE
	CAIE	T1,.TYTTY/.TYEST ;IS IT A TTY?
	  JRST	NOPNTY		;NOPE, PUNT.
	SKIPN	U,DDBLDB##(F)	;GET LDB ADDRESS FOR TTY
	  JRST	NOPDNC		;NOT CONNECTED
	HLLZ	T1,LDBTTW##(U)	;GET WORD WITH NET TYPE BITS
	TLNN	T1,LTLUSE##	;IS IT IN USE?
	  JRST	NOPDNC		;NOT CONNECTED
	TLZ	T1,^-<LTLANF##!LTLNRT##!LTLLAT##>
	UMOVEM	T1,1(M)		;TELL USER THE NETWORK TYPE
	JFFO	T1,.+2		;ENCODE THE FIRST NET TYPE WE FIND
	  JRST	NETDIS		;NO BITS, TREAT LOCAL LIKE ANF
	PJRST	@[IFIW NETDIA##		;ANF
		 IFIW NETDID##		;DECNET (CTERM OR NRT)
		 IFIW NETDIL##](T2)	;LAT
	SUBTTL	NETOP. UUO

;NETDIS - NETOP. function to return node and port ID for a local TTY
;
;Call: (in section 1 already)
;
;	F/ DDB of terminal
;	U/ LDB of terminal
;	M/ Address of user's NETOP. arg list
;Return:
;	ECDX?	depending on error
;	RETSKP	node name stored in string block pointed to by user's arg list
;
;Uses P1,P2 (already saved by higher routine), T1-T4, M

NETDIS:	MOVE	P1,M		;SAVE ARG LIST POINTER
IFN FTNET,<
	PUSHJ	P,GTNTS1	;GET NODE#,,LINE# IN T1
	  JRST	NOPDNC		;NOT CONNECTED
>
	EXCTUX	<SKIPN	M,5(P1)>	;DOES HE WANT NODE NAME?
	  JRST	NTDIS1		;NO
IFE FTNET,<SETZ T1,>		;NULL NODE NAME IF NO NETWORKS
IFN FTNET,<MOVE T1,STANAM##>	;GET OUR NODE NAME
	PUSHJ	P,PU6STB	;PUT SIXBIT INTO STRING BLOCK
	  JRST	NOPADC		;CAN'T
NTDIS1:	EXCTUX	<SKIPN	M,6(P1)>;DOES THE GUY WANT PORT NAME?
	  JRST	CPOPJ1##	;NO, DONE
	MOVE	T1,DEVNAM(F)	;YES, GET DEVICE NAME
	PUSHJ	P,PU6STB	;STORE SIXBIT NAME INTO STRING BLOCK
	  JRST	NOPADC		;NO LUCK
	JRST	CPOPJ1##	;DONE
;
;PU6STB - STORE A SIXBIT WORD INTO USER'S 8 BIT STRING BLOCK
;
;CALL: M/ADDRESS OF STRING BLOCK
;    	T1/SIXBIT WORD
;
;RETURN:	+1 ADDRESS CHECK
;		+2 SUCCESS
;
PU6STB::PUSHJ	P,SAVE2##	;GET A COUPLE OF SPARE REGS
	MOVE	P1,T1		;SAVE THE SIXBIT
	MOVE	T1,M		;COPY BLOCK POINTER
IFN FTXMON,<PUSHJ P,SSPCS##>	;PRESERVE PCS IN CASE WE NEED TO CHANGE IT
	PUSHJ	P,SXPCS##	;VALIDATE ITS FORM
	  POPJ	P,		;NO GO
	MOVEI	T4,2		;STRING BLOCK MIGHT ONLY NEED TO BE 2 LONG
	TRNE	P1,7777		;UNLESS WE HAVE 5 OR 6 CHARS
	MOVEI	T4,3		;THEN IT NEEDS TO BE 3 WORDS LONG
	PUSHJ	P,GETEWD##	;SEE HOW LONG IT IS
	  POPJ	P,		;NOT ADDRESSABLE AT ALL!
	HRRZ	T3,T1		;GET LENGTH IN WORDS
	CAIGE	T3,(T4)		;IF IT'S NOT LONG ENOUGH
	  POPJ	P,		;THEN PUNT
	PUSH	P,M		;SAVE START ADDRESS OF STRING BLOCK
	SETZ	T4,		;NO CHARS DONE YET
PU6ST1:	HRLI	T4,-4		;4 CHARS PER WORD
	SETZ	T1,		;ZAP THE TARGET WORD
	MOVE	T2,[POINT 8,T1]	;SET UP BYTE POINTER
PU6ST2:	JUMPE	P1,PU6ST3	;IF NO MORE CHARS, QUIT
	SETZ	P2,		;ZAP THE FREE AC
	ROTC	P1,6		;GET NEXT CHAR IN P2
	ADDI	P2," "		;MAKE IT ASCII
	IDPB	P2,T2		;STORE IT
	AOBJN	T4,PU6ST2	;KEEP STUFFING
PU6ST3:	JUMPE	T1,PU6ST4
	PUSHJ	P,PUTEW1##	;STORE A WORD OF RESULT
	  JRST	MPOPJ##		;CAN'T
	JRST	PU6ST1		;KEEP DOING IT
PU6ST4:	POP	P,M		;GET BACK ORIGINAL ADDRESS
	HRL	T3,T4		;RECORD HOW MANY CHARS DONE
	MOVE	T1,T3
	PJRST	PUTEWD##	;INFORM THE USER (MAYBE TAKE FAIL RETURN)
;RETURN BUFFER SIZE, STANDARD NO OF BUFFERS
;CALL:	MOVE AC,LOC OF (2 WORRD) OPEN BLOCK
;CALLI AC,DVSIZ
;NOT IMPLEMENTED RETURN
;AC=XWD NO OF BUFS,BUF SIZE

DVSIZ:	PUSHJ	P,SAVE1##	;SAVE P1
	PUSH	P,M		;SAVE M
	HRR	M,T1		;GET LOC OF OPEN-BLOCK
	PUSHJ	P,GETWDU##	;GET MODE
	MOVE	P1,T1		;SAVE IT
	PUSHJ	P,GETWD1##	;GET DEVICE
	PUSHJ	P,DVCNSG	;FIND ITS DDB
	  TDZA	T1,T1		;NOT A DEVICE
	SKIPA	M,P1		;FOUND - SET M=MODE
	SOJA	T1,SIZRET	;NOT A DEV - RETURN AC=-1
	MOVEI	T2,1		;SET FOR MODE TEST
	ANDI	P1,17		;GET MODE ALONE
	LSH	T2,(P1)		;POSITION THE BIT
	SETZI	T1,		;IF MODE IS ILLEGAL,
	CAIL	P1,SD		;TEST FOR DUMP MODE
	JRST	SIZRT1		;IT IS, RETURN AC=0
	MOVNI	T1,2
	TDNN	T2,DEVMOD(F)	; RETURN AC=-2
	PJRST	SIZRET
IFN FTSPL,<
	PUSHJ	P,CHKSPL	;SPOOLED DEVICE?
	  MOVEI	F,DSKDDB##	;YES, SET FOR A DISK
>	;END CONDITIONAL ON FTSPL

	MOVE	T4,DEVSER(F)	;LOC OF DISPATCH TABLE
	PUSHJ	P,DSZ(T4)	;GET BUFFER SIZE
	PUSHJ	P,DFTNB		;FIND DEFAULT NUMBER OF BUFS
	HRL	T1,T2		;RETURN IN LH(T1)
	ADDI	T1,2		;BUM