Google
 

Trailing-Edge - PDP-10 Archives - decuslib10-01 - 43,50035/uuocon.mun
There are no other files named uuocon.mun in the archive.
TITLE	UUOCON - UUO HANDLER AND UUO+IO ROUTINES - V434
SUBTTL /RCC TS 03 JUN 69
XP VUUOCN,434	;THIS MACRO PUTS VERSION NO. IN STORAGE MAP AND GLOB

	IFNDEF FTPDP8,<FTPDP8==1>

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

;THIS ROUTINE COMBINES THE OLD SYSCON,SYSCSS, AND IOCONT ROUTINES
;IT CONSISTS OF THE UUO TRAP HANDLER
;THE CALL UUO ROUTINES AND THE IO UUO ROUTINES
;SOME UUO DO DISPATCH TO OTHER ROUTINES OUTSIDE OF UUOCON
,   ALL UUOS DROP THEMSELVES IN REAL LOCATION 40, AND TRAP
, TO 41.  THE UUO HANDLER SHUFFLES THE UUO OFF TO THE USER'S
, 40,41, IF IT IS NOT A SYSTEM UUO.
;SYSTEM UUOS(40-77) FIRST SAVE THE USERS ACS IN RELATIVE LOC 0-17
;THEN THE FOLLOWING ACS ARE LOADED UP BEFORE DISPATCHING:
;	PDP	;PUSHDOWN LIST IN CURRENT JOB DATA AREA
;	PROG	;CURRENT JOB RELOCATION IN RH,PROTECTION IN LH
;	JDAT	;ADDRESS OF CURRENT JOB DATA AREA
;	UUO	;THE CONTENTS OF LOC 40 WITH PROG IN INDEX FIELD
;		;SO THAT RELOCATION CAN BE DONE FOR PICKING UP ARGUMENTS
		; EXCEPT THAT ON A CALL OR CALLI UUO, THE ADDRESS IS
		; MODIFIED TO BE THE AC OF THE UUO,FOR
		; PICKING UP ARGUMENTS.
;	DEVDAT	;ADR. OF DEVICE DATA BLOCK
;	IOS	;DEVICE IO STATUS WORD
;	DSER	;ADR. OF DEVICE SERVICE ROUT. DISPATCH TABLE
;	UCHN	;THE USER IO CHANNEL(AC FIELD) OF UUO

;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 PDP,
;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 PDP,
, 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.
;HERE ON UUO FROM USER
;USER AC 17 ALREADY SAVED IN LOC USRSAV(SEE COMMON)
;AC 17 CONTAINS ADR OF JOB(JOBADR)
;SAVE HIS ACS ON REL. LOC 0-17

;TO UUOSY1 IF UUO FROM EXEC MODE (AC 17 GUARRANTEED NOT TO BE EQUAL TO AC PROG)

INTERNAL UUOUSR,UUOSY1,USRXIT
EXTERN FORTY,SIXTY
EXTERN ADRERR,CORUUO,DEVHNG,GETWRD,HOLD,ILLINS
EXTERN ILLMOD,IOIERR,JOBKL,JOBSAV,PHOLD,REASSI,SETAPR
EXTERN STWAIT,UGTSEG,URUN,USCHED,UUOERR
EXTERN WAIT1,WSYNC
EXTERNAL USRSAV,JOBPDL,MJOBPD,PUUOAC,USRJDA
EXTERNAL USRHCU,JOB,JBTSTS,TIMEF
EXTERNAL JOBDAT,JOBAC,UUO0,FORTY

UUOUSR:	MOVEM 16,16(17)		;STORE AC16 IN USER 16
	MOVEI 16,(17)		;SET UP BLT POINTER
	BLT 16,15(17)		;MOVE REAL AC'S TO USER AREA
	MOVE TAC,USRSAV		;MOVE USER 17 TO USER'S AREA
	MOVEM TAC,17(17)
	MOVE PROG,17		;LOAD UP POINTER TO USER PROGRAM AREA
IFN JDAT-PROG,<
	MOVE JDAT,JOBDAT	;ADDRESS OF JOB DATA AREA
>
	MOVSI PDP,MJOBPD	;LOAD UP PUSH DOWN AC AND
	HRRI PDP,JOBPDL(JDAT)	;MAKE ABSOLUTE RATHER THAN RELATIVE
UUOSY1:	PUSH PDP,UUO0		;SAVE RETURN ON PUSH DOWN LIST
	MOVE UUO,FORTY		;GET THE UUO INTO AC(UUO)
	TLNN UUO,740000		;SYSTEM UUO?
ILEGAL:	JRST UUOERR		;NO, 0-37 ARE ILLEGAL,PRINT ERROR
	TLO UUO,PROG		;SET FOR RELOCATION
	LDB TAC1,[POINT 9,UUO,8];PICK UP UUO OP CODE
	CAIL TAC1,100		;ILLEGAL INSTRUCTION?
	JRST ILLINS		;YES, STOP JOB AND PRINT ERROR
	LDB UCHN,PUUOAC		;SETUP USER DEVICE CHANNEL NUMBER
	SKIPE DEVDAT,USRJDA(UCHN)	;GET ADRESS OF DEVICE DATA BLOCK
	CAMLE UCHN,USRHCU	;IS IT LESS THAN OR EQUAL TO HIGHEST
				; USER IO CHANNEL IN USE FOR CURRENT JOB?
	JRST NOCHAN		;CHANNEL NOT ASSIGNED
	MOVE IOS,DEVIOS(DEVDAT)	;GET DATA BLOCK STATUS WORD
	MOVE DSER,DEVSER(DEVDAT);SETUP IO SERVICE DISPATCH
				; TABLE ADDRESS
	CAIL TAC1,LNGUUO	;LONG DISPATCH TABLE UUO?
	JRST DISP1		;YES
DISP0:	ROT TAC1,-1		;DIVIDE UUO OPCODE BY 2, SAVE REMAINDER
	MOVE DAT,UUOTAB-20(TAC1);GET DISPATCH TABLE ENTRY
DISP2:	TLNN TAC1,400000	;WAS UUO ODD?
	MOVS DAT,DAT		;NO, USE LH OF DISPATCH ENTRY
	CAME PROG,17		;UUO FROM SYSTEM?
	JRST (DAT)		;YES, RETURN ADDRESS ALREADY ON PD 
				; LIST. AVOID RESTORING USER
				; ACS ON RETURN TO SYSTEM.
;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 PDP,(DAT)		;NO, FROM USER. ALL
				; UUO ROUTINES RETURN WITH POPJ
	JRST USRXIT		;NO SKIP RETURN TO USER
USRXT1:	IFN FTPDP8,<		;IF PDP-8'S IN THE SYSTEM
	MOVE TAC,(PDP)		;GET USER'S PC
	TLNE TAC,200		;IS BIT 10 SET ?
	JRST USRXT3		;YES, MUST NOT INCREMENT IT
>	AOS (PDP)		;SKIP RETURN TO USER
USRXIT:	MOVE ITEM,JOB		;CURRENT JOB NUMBER
	MOVE TAC,JBTSTS(ITEM)
	JUMPG TAC,USRXT2	;HAS A CONTROL C BEEN EXECUTED?
IFN FTPDP8,< EXTERN UUOTRA
	SKIPE UUOTRA		;IS RAPID RESCHEDULING REQUIRED ?
	JRST USRXT2		;YES, GO DO SO
>
	TLNN TAC,STOPIO		;TRYING TO STOP IO?
	SKIPE TIMEF		;NO. HAS CLOCK TICKED WHILE IN MONITOR?
USRXT2:	PUSHJ PDP,USCHED	;YES, GO CALL SCHEDULER
	POP PDP,UUO0		;USER RETURN ADDRESS
	MOVSI 17,JOBAC(PROG)	;RESTORE ALL USER ACS
	BLT 17,17
	JEN @UUO0		;RESTORE FLAGS AND RETURN TO USER
				; DISMISS INTERRUPT ONLY ON TRPJEN UUO
				; IN ALL OTHER CASES NO INTERRUPTS
				; IN PROGRESS

IFN FTPDP8,<  EXTERN AOSPC
USRXT3:	MOVE ITEM,JOB		;GET CURRENT JOB NUMBER
	MOVSI TAC,AOSPC		;SET SKIP RETURN STATUS BIT
	IORM TAC,JBTSTS(ITEM)	;IN JOB STATUS WORD
	JRST USRXIT+1		;ALREADY HAVE JOB NUMBER
>

NOCHAN:NOCHAN:	CAMN PROG,17		;UUO FROM USER?
				;IF FROM EXEC, PROBABLY SAVEGET WHICH SETS USRCHN NEG. IN LH
	CAIGE TAC1,IOUUO	;YES, IS THIS AN IO UUO?
	JRST DISP0		;NO, GO DISPATCH
	CAIE TAC1,70		;YES,IS IT CLOSE OR RELEASE?
	CAIN TAC1,71		;CLOSE AND RELEASE ALWAYS LEGAL EVEN THOUGH NO DEVICE ASSIGNED
	JRST USRXIT
	JRST IOIERR		;NO, PRINT IO TO UNASSIGNED CHANNEL
				; AND STOP JOB

DISP1:	MOVE TAC,DEVMOD(DEVDAT)	;LONG DISPATCH TABLE UUO
	TLNE TAC,DVLNG		;DOES THIS DEVICE HAVE A LONG
				; DISPATCH TABLE?
	JRST DISP0		;YES, DISPATCH
	CAIGE TAC1,76		;NO, IS UUO LOOKUP OR ENTER?
	JRST USRXIT		;NO, RETURN TO USER
	JRST USRXT1		;YES, SKIP RETURN TO USER
;TABLE OF UUO DISPATCH ADDRESSES
;IN FORMAT:
;	XWD 40,41
;	XWD 42,43
;	.
;	XWD 76,77



UUOTAB:	XWD UCALL,UINIT		;(40,41)CALL,INIT
	XWD UUOERR,UUOERR	;(42,43)FIVE UUOS FOR EACH INSTALLATION
	XWD UUOERR,UUOERR	;(44,45)TO DEFINE AS THEY SEE FIT
	XWD UUOERR,UCALLI	;(46,47),CALLI
IFN FTTTYSER,<
EXTERN TTYUUO
	XWD UOPEN,TTYUUO	;(50,51)OPEN, TTCALL
>
IFE FTTTYSER,<
	XWD	UOPEN,CPOPJ	;(50,51)OPEN, NO-OP FOR TTCALL
>
	XWD ILEGAL,ILEGAL	;(52,53)
	XWD ILEGAL,URENAM	;(54,55),RENAME
XP IOUUO,55			;LOWEST IO UUO(RENAME)
	XWD TIN,TOUT		;(56,57)IN,OUT
	XWD SETIOS,USTATO	;(60,61)SETSTS,STATO
	XWD USTATS,USTATZ	;(62,63)GETSTS,STATZ
	XWD UINBF,UOUTBF	;(64,65)INBUF,OUTBUF
	XWD IN,UOUT		;(66,67)INPUT,OUTPUT
	XWD CLOSE1,RELEA1	;(70,71)CLOSE,RELEASE
XP LNGUUO,72			;LOWEST LING DISPATCH TABLE UUO
	XWD UMTAPE,UDGF		;(72,73)MTAPE,GETF
	XWD UDSI,UDSO		;(74,75)SETI,SETO
	XWD 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 51,52,53 AND 54 ARE RESERVED FOR EXPANSION BY DIGITAL
, 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 TAC,UUO SET TO POINT
;TO USER AC, PROG IN LH.
;ITEM SET TO JOB NUMBER

EXTERNAL JOB

UCALL:	PUSHJ PDP,GETWDU	;SET TAC FROM CONTENTS OF EFFECTIVE ADDRESS OF
				; UUO FROM EITHER HIGH OR LOW SEG
				; DO NOT RETURN IF ERROR
				; SET ITEM TO CURRENT JOB NO.
	MOVSI TAC1,-UCLLEN-CCLLEN-1	;-SUM OF LENGTHS OF SIXBIT TABLES,
				; -1 FOR THE CARRY TO LH IN AOBJN
	HRRI TAC1,-CCLLEN	;- LENGTH OF CUSTOMER TABLE
	CAME TAC,UCLTAB(TAC1)	;SEARCH SYSTEM ROUTINE NAME TABLE
	AOBJN TAC1,.-1
	HRRM TAC1,UUO		;STORE INDEX IN UUO, JUST AS IF USER HAD DONE CALLI UUO


;CALLI UUO	-	CALL IMMEDIATE
;CALLI D,E
;WHERE E IS RELATIVE INDEX IN CALL TABLE

INTERNAL UCALLI

UCALLI:	HRRE TAC1,UUO		;GET CALLI NUMBER (POS. = DIGITAL, NEG. = CUSTOMER DEFINED)
	CAML TAC1,[-CCLLEN]	;MORE NEGATIVE THAN MOST NEGATIVE CUSTOMER DEFINED UUO?
	CAIL TAC1,UCLLEN	;MORE POSITIVE THAT DIGITAL DEFINED UUO?
	POPJ PDP,		;YES, RETURN TO USER TREAT AS NO-OP SO
				; PROGRAMS AHEAD OF MONITOR WILL STILL
				; RUN WITHOUT ERROR MESSAGE
	CAMN PROG,17		;NO, WAS UUO FROM MONITOR?
	POP PDP,TAC		;REMOVE RETURN
	HRR UUO,UCHN		;UUO AC FIELD
	MOVE TAC,@UUO		;PICK UP CONTENTS OF USER AC
	ROT TAC1,-1		;DEVIDE BY 2 AND SAVE REMAINDER
	MOVE DAT,UCLJMP(TAC1)	;GET DISPACTH TABLE ENTRY
	MOVE ITEM,JOB		;SETUP CURRENT JOB NUMBER(IN CASE THIS IS CALLI)
	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)

;ALSO EXTERNALS MUST BE IN RH(IE ODD CALLI INDECIES)

EXTERNAL DDTIN,DDTOUT,CPOPJ

DEFINE CNAMES <
	X CPOPJ,CPOPJ		;(-3) PLACE FOR CUSTOMERS TO PATCH UUOS
	X CPOPJ,CPOPJ		;(-2) 
	X LIGHTS,LIGHTS		;(-1) SET LIGHTS (EXAMPLE OF CUSTOMER DEFINED UUO)
>

DEFINE NAMES,<
	X RESET,RESET		;(0)RESET IO
	X DDTIN,DDTIN		;(1)EXT-GET DDT CHAR.
	X SETDDT,SETDDT		;(2)SETDDT LOC IN PROTECTED JOB DATA
	X DDTOUT,DDTOUT		;(3)EXT:SEND DDT CHAR.
	X DEVCHR,DVCHR		;(4)DEVICE CHARACTISTICS
	X DDTGT,CPOPJ		;(5)GET DDT MODE
	X GETCHR,DVCHR		;(6)DEVICE CHAR.(DIFF. NAME)
	X DDTRL,CPOPJ		;(7)RELEASE DDT MODE
	X WAIT,WAIT		;(10)WAIT TILL DEVICE INACTIVE
	X CORE,CORUUO		;(11)CORE UUO
	X EXIT,EXIT		;(12)EXIT
	X UTPCLR,UTPCLR		;(13)CLEAR DEC TAPE DIRECTORY 
	X DATE,DATE		;(14)GET DATE
	X LOGIN,LOGIN		;(15)LOGIN
	X APRENB,APRENB		;(16)ENABLE APR FOR TRAPPING
	X LOGOUT,LOGOUT		;(17)LOGOUT
	X SWITCH,SWITCH		;(20)RETURN DATA SWITCHES
	X REASSIGN,REASSIGN	;(21)REASSIGN DEVICE TO ANOTHER JOB
	X TIMER,TIMER		;(22)RETURN JIFFY CLOCK TIME
	X MSTIME,MSTIME		;(23)RETURN TIME OF DAY IN MS
	X GETPPN,GETPPN		;(24)RETURN PROJECT-PROGRAMMER NUMBER
	X TRPSET,TRPSET		;(25)SET PI TRAP LOC, AND USER IO
	X TRPJEN,UUOERR		;(26)DISMISS INTERRUPT TO EXEC MODE(SUPERCEDED BY UJEN)
	X RUNTIM,JOBTIM		;(27)RETURN TOTAL JOB RUNNING TIME
	X PJOB,JOBNO		;(30)RETURN JOB NUMBER
	X SLEEP,SLEEP		;(31)SLEEP FOR N SECONDS, THEN RETURN TO USER
	X SETPOV,SETPOV		;(32)SET PUSH DOWN OVERFLOW TRAP
				; (FOR COMPATIBILITY ONLY)
	X PEEK,UPEEK		;(33)TO PEEK AT CERTAIN MONITOR PARAMETERS
	X GETLIN,GETLN		;(34) GET TTY UNE NUMBER
	X RUN,URUN		;(35) RUN DEV:FILE
	X SETUWP,SETUWP		;(36) SET OR CLEAR USER MODE WRITE PROTECT
	X REMAP, REMAP		;(37) REMAP TOP OF LOW SEGMENT INTO HIGH SEG
	X GETSEG,UGTSEG		;(40) GET SHARABLE HIGH SEG
	X GETTAB,GETTAB		;(41) GET EXEC ADDRESS OF A JOB TABLE
	X SPY,USPY		;(42) SET HIGH SEG TO BE PHYSICAL CORE
	X SETNAM,SETNAM		;(43) SETNAME OF THIS PROGRAM
	X CPOPJ,CPOPJ		;2 SPARE UUO'S FOR PATCHING - DIGITAL ONLY
	X CPOPJ,CPOPJ		;ALWAYS ADD NEW UUO'S ABOVE THESE
				;CUSTOMERS SHOULD ADD UUO'S ABOVE
				;IN CNAMES MACRO RATHER THAN NAMES MACRO
				; SO THAT THEIR CALLI INDECES WILL
				; BE NEGATIVE
>
;GENERATE SIXBIT TABLE OF UUO NAMES

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

;GENERATE CUSTOMER CALL/CALLI UUO'S

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

;GENERATE DIGITAL UUO'S

UCLTAB:	NAMES
UCLLEN=.-UCLTAB		;DEFINE LENGTH OF DIGITAL UUO TABLE(MAX. CALLI NO. TOO)
DEFINE X (A,B)
<	ZZ=ZZ+1
	DEFINE XX (C)		;DEFINE XX IN CASE JOB NUMBER OF CUSTOMER UUO'S
<	XWD UUOERR,C
>>
ZZ=0
;COUNT NUMBER OF CUSTOMER DEFINED UUO'S
	CNAMES

;GENERATE HALF WORD UUO DISPATCH TABLE

DEFINE X (A,B)
<	IFE ZZ&1,
<	DEFINE XX (C)
<
	XWD B,C
>>
	IFN ZZ&1,
<
	XX B
>
ZZ=ZZ+1
>

;GENERATE CUSTOMER TABLE

CUSTAB:	CNAMES


ZZ=0

;GENERATE DIGITAL TABLE

UCLJMP:	NAMES

	IFN ZZ&1,<XX 0>	;GEN. LAST WORD IF ODD NUMBER OF UUOS

;FIX UP SYMBOLS NOT IN UUOCON

IFN FT2REL,<EXTERN USPY>
IFE FT2REL,<USPY=LCPOPJ>
;EXIT UUO ROUTINE
;CALL:	CALL FIELD, [SIXBIT/EXIT/]
;IF FIELD - 0, PRINT EXIT ^C.  CONT WILL NOT WORK
;IF FIELD NON-ZERO, JUST PRINT.  DO NOT RELEASE DEVICES

EXTERNAL TTYFUW

EXIT:	JUMPN UCHN,MONRET	;AC FIELD NON-ZERO?
	PUSHJ PDP,IORELS	;NO, RELEASE ALL DEVICES
	PUSHJ PDP,TTYFUW	;FIND TTY FOR CURRENT JOB
				; SET ITEM TO JOB NO.,DAT TO OUTPUT BYTE POINTER
				; DEVDAT TO TTY DDB
	JSP TAC,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

	EXTERN PRPER,STOP1,CRLF,TTYSTC

MONRET:	PUSHJ PDP,TTYFUW	;FIND TTY FOR CURRENT JOB
	PUSHJ PDP,CRLF		;PRINT CR LF
	PUSHJ PDP,PRPER		;PRINT .
	PUSHJ PDP,TTYSTC	;PUT TTY INTO COMMAND MODE
	JRST STOP1		;START TTY IN MONITOR MODE AND STOP JOB
				;BUT ALLOW CONTINUE TO WORK (RETURN CONTROL AFTER EXIT UUO)

;SETPOV - SET PUSH DOWN OVERFLOW TRAP
;CALL	MOVE AC,ADR. OF TRAP ON PD OVF
;	CALL AC,[SIXBIT /SETPOV/]

EXTERNAL JOBAPR

SETPOV:	MOVEM TAC,JOBAPR(JDAT)
	MOVEI TAC,1B19
	JRST APRENB		;SET TRAP LOC.

;RESET UUO ROUTINE

INTERNAL RESET,FTTRPSET
EXTERNAL JOBPD1

RESET:
IFN FTTRPSET,<
	EXTERN STOPTS
	CAIN	TAC,1		;IS THIS JOB 1 DOING THE RESET?
	SETZM	STOPTS		;YES. MAKE SURE SCHEDULING ALLOWED
				; IN CASE THIS FOLLOWS A TRPSET UUO
>
IFN FT2REL,<
	EXTERN HRESET
	PUSHJ PDP,HRESET	;FLAG USER AS HAVING UWP ON FOR HIGH SEG
				; AND DO DATAO TO SET UWP ON
>
	PUSHJ PDP,IOKILL	;RELEASE ALL DEVICES
	MOVSI TAC,777777-USRMOD	;CLEAR ALL UUO PC FLAGS IN LH, EXCEPT USER MODE
	ANDCAM TAC,JOBPD1(JDAT)	;LEAVE USER MODE OFF TOO, IF EXEC DOING CALL RESET
				; FALL INTO APRENB WITH RH TAC=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

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

INTERNAL APRENB

APRENB:	HRRM TAC,JOBENB(JDAT)	;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
;RETURN JOB NUMBER FOR THIS JOB

JOBNO:	SKIPA TAC,ITEM		;JOB NUMBER
				; SKIP AND STORE TAC IS USER AC

;RETURN THE DATE TO THE USER

EXTERNAL THSDAT

DATE:	MOVE TAC,THSDAT
	JRST STOTAC

;RETURN JOB RUNNING TIME IN MILLISECONDS

INTERNAL FTTIME

JOBTIM:
IFN FTTIME,<EXTERNAL JOBN
	SKIPL TAC
	CAILE TAC,JOBN
	JRST	RTZER
	SKIPN TAC
	MOVE TAC,ITEM
	SKIPA TAC,TTIME(TAC)	;TOTAL JOB RUNNING TIME
	EXTERNAL TTIME
>
IFE FTTIME,<
		TDZA TAC,TAC	;RETURN ZERO IF NO TIMMING COM.
>

;RETURN TIME OF DAY IN MILLISECONDS

EXTERNAL TIME,JIFSEC

MSTIME:	MOVE TAC,TIME		;TIME OF DAY IN JIFFIES
	IMULI TAC,^D1000
	IDIVI TAC,JIFSEC	;DIVIDE BY NO. OF JIFFIES PER SECOND
	JRST STOTAC
;PUT JOB TO SLEEP FOR NSECONDS
;CALL	CALL AC,[SIXBIT /SLEEP/]

INTERNAL FTSLEEP,SLEEP

SLEEP:
IFN FTSLEEP,<
EXTERNAL JIFSEC,JBTSTS,PION,PIOFF,SETSLP,WAKE,CLOCK
	MOVSI TAC1,CLKR
	TDNE TAC1,JBTSTS(ITEM)	;DOES THIS JOB HAVE A CLOCK QUEUE
				; REQUEST IN CLOCK QUEUE?
	JRST SLEEP1		;YES, DO NOT PUT ANOTHER ONE IN
	IMULI TAC,JIFSEC	;MULTIPLY BY NO. OF JIFFIES PER SECOND
	TRNN TAC,7777		;0 TIME?(CHECK ONLY 12 BITS)
	MOVEI TAC,1		;YES. SLEEP 1 JIFFY
	DPB ITEM,[POINT 6,TAC,23]
	HRLI TAC,WAKE		;ADR. IN RUNCSS WHEN JOB WAKES UP
	CONO PI,PIOFF
	IDPB TAC,CLOCK
	CONO PI,PION
SLEEP1:	JRST SETSLP		;SET JOB STATUS WORD SO JOB WILL NOT RUN
>
IFE FTSLEEP,<	POPJ PDP,	;RETURN IMMEDIATELY IF NOT A FEATURE>

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

	EXTERN SYSSIZ

UPEEK:
IFN FTLOGIN,<
	HLRZ	TAC1,PRJPRG(ITEM)	;GET USER'S PROJECT NR
	CAIE	TAC1,1			;ADMIN NR?
	JFCL		;SHOULD BE PATCHED TO "JRST UUOERR" IF
			; IF CUSTOMER WANTS PEEK UUO NOT ALLOWED FOR ALL USERS
>
	CAMLE TAC,SYSSIZ	;ONLY UP TO SIZE OF SYSTEM
	JRST RTZER		;RETURN 0 IF USER ASKING TOO BIG
	MOVE	TAC,(TAC)
	JRST	STOTAC
;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)

IFN FT2REL,<
	EXTERN USTUWP
SETUWP:	JRST 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

IFN FT2REL,<
	EXTERN UREMAP
REMAP:	JRST UREMAP		;CORE1 MODULE IN SEGCON
>
IFE FT2REL,<
REMAP=CPOPJ			;ERROR RETURN TO USER(CPOPJ IS AN EXTERN)
>

;ROUTINE TO GET WORD FROM USER AREA AT UUO LEVEL - EITHER SEGMENT
;CALL:	MOVE PROG,XWD PROTECTION,RELOCATION FOR LOW SEG
;	HRR UUO,USER ADR.
;	HRLI UUO,PROG	;FOR RELOCATION
;	PUSHJ PDP,GETWDU
;	RETURN ONLY IF ADDRESS OK, WORD IN TAC, ABS. ADR IN TAC1

;	IF OUT OF BOUNDS, PRINT ILL UUO AND STOP JOB

	INTERN GETWDU,GETWD1
	EXTERN JOB

GETWD1:	HRRI UUO,1(UUO)		;INCREMENT UUO BEFORE PICKING UP WORD
GETWDU:	MOVE ITEM,JOB		;SETUP CURRENT JOB NUMBER
	PUSHJ PDP,GETWRD	;GET THE WORD AND CHECK IF LEGAL
	JRST UUOERR		;ADR. NOT IN LOW OR HIGH SEG, PRINT ERROR
LCPOPJ:
RMPERR:	POPJ PDP,		;OK RETURN, TAC=WORD, TAC1=ABS. ADR.
;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:	DATAO PI,TAC		;SENT USER'S AC TO CONSOLE LIGHTS
	POPJ PDP,		;RETURN TO HIM

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

EXTERNAL TIME

TIMER:	SKIPA TAC,TIME		;FALL INTO STOTAC

;RETURN DATA SWITCHES


SWITCH:	DATAI TAC

;ROUTINE TO STORE TAC IN USER AREA AS SPECIFIED BY UUO
;MUST BE CALLED FROM UUO LEVEL WITH PROG SETUP
;ALSO PROG IN INDEX FIELD OF UUO

INTERNAL STOTAC

STOTAC:	HRRZ AC1,UUO
	PUSHJ PDP,UADCK1	;IS ADDRESS IN BOUNDS(OR IN ACS)?
	MOVEM TAC,@UUO		;YES, STORE
	POPJ PDP,

;RETURN DEVICE CHARACTERISTICS

EXTERNAL JOB,PJOBN

DVCHR:	PUSHJ PDP,DEVSRC	;SERACH FOR DEVICE
	TDZA TAC,TAC		;NOT A DEVICE, RETURN ZERO
	SKIPA TAC,DEVMOD(DEVDAT);DEVICE FOUND,RETURN DEVMOD
	JRST STOTAC		;RETURN ZERO, DEVICE NOT FOUND
	LDB TAC1,PJOBN		;GET JOB NO.  USING DEVICE
	CAME TAC1,JOB		;DOES CURRENT USER ALREADY HAVE IT?
	TRNN TAC,ASSCON+ASSPRG	;NO, IS IT ASSIGNED?
	TLO TAC,DVAVAL		;NO, BUT HE CAN GET IT.
	JRST STOTAC

;RETURN PROJECT-PROGRAMMER NUMBER IN AC

GETPPN:
INTERNAL FTLOGIN
IFN FTLOGIN,<
	EXTERNAL PRJPRG
	MOVSI TAC,JACCT
	TDNE TAC,JBTSTS(ITEM)	;LOGIN OR LOGOUT CUSP RUNNING ?
	JRST GETPPL		;YES, SPECIAL PROJ,PROG NUMBER CHANGE.
	SKIPA TAC,PRJPRG(ITEM)	;NO, RETURN PROJECT-PROGRAMMER NO. OF THIS JOB.
>

INTERN RTZER

IFE FT2REL, <
SETUWP:				;SETUWP RETURNS 0
>

RTZER:	MOVEI TAC,0		;RETURN 0. TO USER AC
	JRST STOTAC		;AS SPECIFIED IN AC FIELD OF HIS UUO
EXTERNAL USRDDT

SETDDT:	MOVEM TAC,USRDDT
	POPJ PDP,		;RETURN TO USER

;WAIT FOR IO TO BECOME INACTIVE ON CHANNEL AC


WAIT:	JUMPE DEVDAT,CPOPJ	;CHANNEL ASSIGNED?
	JRST WAIT1		;WAIT TILL INACTIVE BEFORE
				; RETURNING TO USER.


IFN	FTLOGIN, <
EXTERNAL	DUMPPP,MJOBN
GETPPL:	MOVE	TAC,DUMPPP	;CHANGE USER'S NUMBERS TO [1,2]
	EXCH	TAC,PRJPRG(ITEM)	; AND GET OLD NUMBERS.
	MOVSI	TAC1,MJOBN	;CHECK FOR OTHER USERS UNDER SAME PP NUMBER.
	CAMN	TAC,PRJPRG(TAC1)	;ANOTHER USER UNDER SAME PROJ,PROG NUMBER ?
	AOSA	(PDP)		;YES, SKIP RETURN TO USER (LOGIN OR LOGOUT)
	AOBJN	TAC1,.-2	;NO, KEEP LOOKING
	JRST	STOTAC
>

GETLN:	PUSHJ	PDP,TTYFND	;FIND USER'S TTY DATA BLOCK.
	MOVE	TAC,DEVNAM(DEVDAT)	;GET DEVICE NAME IN SIXBIT
	JRST	STOTAC		;RETURN IT TO USER.
;LOGIN UUO USED ONLY BY LOGIN CUSP
;CALL:	CALL AC,[SIXBIT /LOGIN/]
;WHERE AC CONTAINS XWD -NO. OF ENTRIES,LOCATION
;WHICH IS A LIST OF JOB STATISTICS TO BE STORED IN MONITOR

INTERNAL FTLOGIN

IFN FTLOGIN,<
EXTERNAL JOB,JBTSTS,TTYFUW

LOGIN:	MOVSI TAC1,JLOG		;IS USER ALREADY LOGGED IN?
	TDNE TAC1,JBTSTS(ITEM)
	JRST UUOERR		;YES, PRINT ILLEGAL UUO
	HLRE AC1,TAC		;NO, -NO. OF WORDS
	HRR UUO,TAC		;FIRST REL. LOC.
	MOVE AC2,[XWD -LOGTOP,LOGTAB]	;SET FOR LOOP
LOGIN1:	AOSG AC1		;FINISHED HIS COUNT?
	SKIPA AC3,@UUO		;NO, GET NEXT WORD FROM USER AREA
	MOVEI AC3,0		;YES, STORE 0
	MOVEM AC3,@(AC2)	;NO, STORE ITEM
	ADDI UUO,1		;GET NEXT ITEM
	AOBJN AC2,LOGIN1	;FINISHED NO. OF MONITOR TABLES?
	IORM TAC1,JBTSTS(ITEM)	;YES, FINALLY SET LOGIN BIT
	MOVSI	TAC1,JACCT	;RESET THIS BIT TO INDICATE LOG-IN IS
	ANDCAM	TAC1,JBTSTS(ITEM)	; NOW COMPLETE AND ^C IS AGAIN PERMITTED.
LOGIN2:	PUSHJ PDP,IORELS	;RELEASE ALL DEVICES
	PUSHJ PDP,TTYFUW	;FIND TTY AND PRINT ^C
	JRST HOLD

;TABLE OF POINTERS TO TABLES(STORED WITH JOB NUMBER AS INDEX)
;TO MAKE LOGIN SET MORE TABLES IN MONITOR, JUST ADD TABLE NAMES AT END

EXTERNAL PRJPRG


LOGTAB:	XWD ITEM,PRJPRG		;PROJECT-PROGRAMMER NUMBER
IFN FTPRV,<
	EXTERN JBTPRV
	XWD ITEM,JBTPRV		;JOB PRIVILEGE BITS
>
IFE FTPRV,<
	EXP IOS			;STORE IN AC IOS, SINCE PRIVILEGE TABLE DOES NOT EXIST
>

LOGTOP=.-LOGTAB	;NO. OF TABLES TO BE SET
>
;LOGOUT UUO

INTERNAL FTLOGIN
EXTERNAL TTYTCM

IFN FTLOGIN,<
LOGOUT:	PUSHJ	PDP,TTYFUW
	MOVSI	TAC,JLOG
	TDNN	TAC,JBTSTS(ITEM)	;IS JOB ALREADY LOGGED OUT ?
	JRST	JOBKL		;NO, GO COMPLETE WORK OF LOGOUT CUSP.
	JRST	EXIT	;YES, TREAT AS "EXIT"
>

IFE FTLOGIN,<

LOGIN=UUOERR	;CANT DO A LOGIN UUO
LOGOUT=EXIT	;TREAT A KJOB UUO AS AN EXIT IN 10/40
>
;GETTAB UUO
;UUO TO RETURN CONTENTS OF A MONITOR JOB TABLE ENTRY
;CALL:	HRROI AC, MONITOR JOB TABLE NUMBER
;	HRLI AC, JOB NUMBER (OPTIONAL) LH .LT. 0 MEANS CURRENT JOB
;	CALL AC, [SIXBIT /GETTAB/] OR CALLI AC,41
;	ERROR RETURN AC PRESERVED IF LH OR RH TOO BIG OR
				; AC=-1 IF NOT PRIVILIGED TO GET INFO
;	NORMAL RETURN - AC=0 IF TABLE IS UNDEFINED
IFN FTGETTAB,<
	EXTERN JOB,JOBMAX,TTYTAB,TTPMXL,JOBMXL,JBTMXL

GETTAB:	HLRZ ITEM,TAC		;GET USER SUPPLIED JOB NUMBER
	SKIPGE TAC		;DID HE SUPPLY ONE?
	MOVE ITEM, JOB		;NO, USE CURRENT JOB NUMBER
	HRRZS TAC		;GET TABLE NUMBER IN TAC
	CAIL TAC,GTTBLN		;IS TABLE NUMBER LEGAL?
	POPJ PDP,		;YES. ERROR RETURN, AC UNCHANGED
	LDB TAC1,[POINT 9,NUMTAB(TAC),8]	;MAX LEGAL ARG.
	CAMLE ITEM,TAC1		;DOES HIS ARG EXCEED LEGAL ONE?
	POPJ PDP,0		;YES. ERROR RETURN
	MOVE TAC,@NUMTAB(TAC)	;GET CONTENTS OF MONITOR TABLE
	AOS (PDP)		;OK (SKIP) RETURN TO USER
	JRST STOTAC		;RETURN TAC IN HIS AC

;THE MONITOR JOB TABLE NUMBERS:
	EXTERN JBTSTS,JBTADR,JBTPRG,NSWTBL,CNFTBL,NSWMXL,CNFMXL
NUMTAB:	XWD ITEM+JBTMXL,JBTSTS	;0 - JOB STATUS BITS
	XWD ITEM+JBTMXL,JBTADR	;1 - JOB SIZE -1 AND ABS.LOC
IFN FTLOGIN,<
	EXTERN PRJPRG
	XWD ITEM+JBTMXL,PRJPRG	;2 - PROJECT,PROGRAMMER NUMBER
>
IFE FTLOGIN,<
	XWD JBTMXL,[0]	;2 - NOT DEFINED
>
	XWD ITEM+JBTMXL,JBTPRG	;3 - PROGRAM BEING RUN
IFN FTTIME,<

	EXTERN TTIME

	XWD ITEM+JOBMXL,TTIME	;4 - TOTAL RUN TIME IN JIFFIES
>
IFE FTTIME,<
	XWD JOBMXL,[0]	;4 - NOT DEFINED TABLE - RETURN 0
>
IFN FTKCT,<
	EXTERN JBTKCT
	XWD ITEM+JOBMXL,JBTKCT	;5 - KILO-CORE TICKS(JIFFIES*SIZE IN K)
>
IFE FTKCT,<
	XWD JOBMXL,[0]	;5  NOT DEFINED TABLE - RETURN 0
>
IFN FTPRV,<
	EXTERN JBTPRV
	XWD ITEM+JOBMXL,JBTPRV	;6 - PRIVILEGE BITS SET BY LOGIN
>
IFE FTPRV,<
	XWD JOBMXL,[0]		;6 - NOT DEFINED TABLE - RETURN 0
>
IFN FTSWAP,<
	EXTERN JBTSWP,SWPTBL,SWPMXL
	XWD ITEM+JBTMXL,JBTSWP	;7 - LOC ON DISK, SIZE ON DISK, IN CORE PROTECT TIME
>
IFE FTSWAP,<
	XWD JOBMXL,[0]		;7 - NOT DEFINED TABLE - RETURN 0
>
	XWD ITEM+TTPMXL,TTYTAB	;10 - TTY TRANSLATOR TABLE
	XWD ITEM+CNFMXL,CNFTBL	;11 - CONFIGURATION DATA
	XWD ITEM+NSWMXL,NSWTBL	;12 - NON-SWAPPING DATA
IFN FTSWAP,<
	XWD ITEM+SWPMXL,SWPTBL	;13 - SWAPPER DATA
>
IFE FTSWAP,<
	EXP [0]		;13 - UNDEFINED
				;ALL CALL ARE ERROR RETURNS SINCE TABLE
				; HAS NO ENTRIES
>
IFN FT2REL,<

EXTERN JBTSGN,ITMSGN

	XWD ITMSGN,JBTSGN	;14 - HIGH SEG NO. THIS JOB IS USING
				;LH=ITEM+JOBMXL IF REENTRANT SOFTWARE
				;LH=0+JOBMXL, SO ALL ENTRIES RETURN 0
				; IF NON-REENTRANT SOFTWARE
>
IFE FT2REL,<
	XWD JOBMXL,[0]		;14 - UNDEFINED
>
IFN FTDISK,<
	EXTERN ODPMXL,ODPTBL
	XWD ITEM+ODPMXL,ODPTBL	;15 - ONCE ONLY DISK PARAMETERS
>
IFE FTDISK,<
	EXP [0]			;50 - UNDEFINED
>
GTTBLN=.-NUMTAB			;LENGTH OF TABLE
>

IFE FTGETTAB,<GETTAB=UUOERR>

;UUO TO SET CURRENT PROGRAM NAME
;	MOVE AC,[SIXBIT /NAME/]
;	ALWAYS RETURN

	EXTERN JBTPRG

SETNAM:	MOVEM TAC,JBTPRG(ITEM)	;STORE PROGRAM NAME FOR SYSTAT AND SYSDPY
	POPJ PDP,

;UUO TO SET JOB TO USE IO IN USER MODE
;AND TO SET PI INTERRUPT LOCATION IN LOWER CORE(WORKS ONLY ON PDP-10'S -SEE NEXT PAGE)
;CALL:	CALL AC,[SIXBIT /TRPSET/]
;	ERROR RETURN, USER NOT ALLOWED TO DO IO IN USER MODE
;	OK RETURN

;WHERE RH(AC)=REL ADR. OF 1 INSTRUCTION TO BE MOVED INTO
;THE MONITOR PI TRAP LOCATION(40-57) AS SPECIFIED BY LH(AC)
;RELOCATION OF JOB IS ADDED TO RH OF INSTRUCTION AS IT IS MOVED.
;ALSO THE RELOCATION IS ADDED TO THE RH OF WORD IN USER AREA SPECIFIED BY
;RH OF USER INSTRUCTION IN CASE IT IS A BLKO/BLKI POINTER
;THE USER MUST RESET EVERY TRPSET CALL IF BLKI/BLKO POINTER 
;AND SHOULD SET RH TO 0 IF JSR PC WORD
;THE APR IS ALSO SET SO USER MAY DO IO IN USER MODE
;TO SET USER MODE IO WITHOUT SETTING LOWER CORE, C(AC)=0
;STOP TIME SHARING ONLY IF AC IS NON-ZERO(IE RUN ONLY JOB 1)

INTERNAL FTTRPSET

TRPSET:
IFN FTTRPSET,<
EXTERNAL JOBPD1,STOPTS

	CAIE ITEM,1		;IS THIS JOB 1?
	POPJ PDP,		;NO, ERROR RETURN
	SETZM STOPTS		;CLEAR THE STOP TIME SHARING FLAG
	JUMPE TAC,TRPST1	;IS AC 0?(DO NOT SET PI LOC IF YES)
	HLRZ TAC1,TAC		;NO, SET LOWER CORE
	CAIL TAC1,40		;IS IT LEGAL LOWER CORE ADR.?
	CAIL TAC1,60
	POPJ PDP,		;NO, ERROR RETURN
	SETOM STOPTS		;SET STOP TIME SHARING FLAG, SO NO OTHER JOBS
				; JOBS WILL RUN AND NO CORE SHUFFLING
	HRLI TAC,PROG		;YES, SET TO RELOCATE
	MOVE TAC,@TAC		;GET THE INSTR.
	ADDI TAC,(PROG)		;ADD RELOCATION SO WILL POINTER TO USER AREA
	HRRZ	DAT,PROG	;USER RELOCATION
	ADDM	DAT,(TAC)		;ALSO ADD RELOCATION TO WORD POINTED TO BY INSTR
				; IN CASE IT IS A BLKI/BLKO POINTER WORD
				; USER SHOULD RESET RH OF POINTER IF BLKI/BLKO INSTR
				; OR CLEAR PC LOC IF JSR INSTR
	EXCH TAC,(TAC1)		;AND STORE IN MONITOR TRAP LOC.
TRPST1:	AOS (PDP)		;OK RETURN
	MOVSI TAC1,4000		;SET USER IO PC FLAG
	IORM TAC1,JOBPD1(JDAT)	;IN UUO RETURN PC
>
	JRST STOTAC		;RETURN PREVIOUS CONTENTS OF PI LOC.
;ROUTINE TO DISMISS INTERRUPT  FOR JOB DOING USER IO
;WHEN PC IS IN EXEC MODE
;NOTE  THE TRPJEN UUO HAS BEEN ELIMINATED
;BECAUSE UUO HANDLER CANNOT BE INTERRUPTED AND REENTERED
;INSTEAD INTERRUPTS IN USER MODE ARE DISMISSED
;BY USING OP CODE 100 (UJEN) WHICH
;TRAPS TO EXEC 61 INSTEAD OF 41 ON PDP-10'S
;UJEN IS A NO-OP ON PDP-6'S AND SO THIS FACILTY IS GOOD ON PDP-10'S ONLY
;CALL:	RESTORE ALL EXEC ACS
;		UJEN ADR	;UJEN=100
;		WHERE ADR CONTAINS PC STORED BY INTERRUPT JSR
;		SEE UUO HANDLER (UUO2) FOR CODE
;FOR PURPOSES OF COMMENTING THIS SUBROUTINE THE
;TERM 'BUFFER HEADER' SHALL REFER TO THE 3 WORD HEADER
;WHICH IS USED BY THE USER PROGRAM AND THIS EXEC FOR
;REFERING TO THE RING BUFFERS.

;THE CONTENTS OF THE 3 WORD HEADER (AS SET BY THE MONITOR
;		ON EACH INPUT AND OUTPUT UUO).
;		BIT 18-35=ADDRESS OF SECOND WORD OF THE
;		CURRENT BUFFER IN RING WHICH USER IS REFERENCING
;	WORD 2:	BYTE POINTER TO CURRENT ITEM.
;	WORD 3:	POSITIVE ITEM COUNT (NO. OF ITEMS LEFT ON
;		INPUT, NO. OF FREE ITEMS TO GO ON OUTPUT).

;EACH BUFFER IN THE RING HAS FOLLOWING FORMAT (AS THE USER SEES IT)

;	WORD 1:	RESERVED FOR BLOCK NUMBER FOR FIXED ADDRESS DEVICES
;	WORD 2:	BIT 0=USE BIT FOR THIS BUFFER
;		BIT 1-17=NO. OF WORDS WHICH FOLLOW (LENGTH OF BUFFER)/
;		BIT 18-35=ADDRESS OF SECOND WORD OF NEXT BUFFER IN RING
;	WORD 3:	LH=LINK TO NEXT BLOCK (SET BY MONITOR FOR DECTAPE)
;		RH=NO. OF WORDS OF DATA WHICH FOLLOW (USUALLY
;		SET BY EXEC EXCEPT IF THE USER HAS SPECIFIED
;		THAT HE WANTS TO COMPUTE WORD COUNT
;		HIMSELF INSTEAD OF HAVING THE MONITOR DO IT
;		USING THE BYTE POINTER IN THE 3 WORD HEADER).





,CALLING SEQUENCE
,	CLOSE D,
,	EXIT		ALWAYS RETURNS HERE
, THIS ROUTINES PROCESSES THE CLOSE UUO AND DETERMINES WHETHER THE
,OUTPUT ROUTINE SHOULD BE CALLED IF OUTPUT WERE ACTIVE, CLEARS
,THE INPUT BUFFER AREA IF INPUT WERE ACTIVE, AND CLEARS THE 
,ITEM COUNTS OF BOTH INPUT AND OUTPUT HEADERS SERVING TO BOTH
,TERMINATE THE USE OF THE DEVICE AND SET THE I/O ROUTINES TO
,ACCEPT ANOTHER INPUT OR OUTPUT COMMAND IN A CLEAR STATE.
,IN THE CASE OF OUTPUT DEVICES, THE CLOSE ROUTINE OF THE DEVICE HANDL-
,ING ROUTINE IS CALLED IN CASE ANY SPECIAL HANDLING IS REQUIRED.
INTERNAL CLOSE1
EXTERNAL PIOMOD

CLOSE1:	PUSHJ PDP,WAIT1		;WAIT UNTIL DEVICE IS INACTIVE
	TRNN UUO,CLSIN		;SUPPRESS INPUT CLOSE?
	TLOE DEVDAT,ICLOSB	;NO. INPUT ALREADY BEEN CLOSED?
	JRST UCLS2		;YES
	LDB TAC,PIOMOD		;NO
	CAIGE TAC,SD		;DUMP MODE?
	JRST UCLSBI		;NO. CLOSE BUFFERED INPUT.
UCLS5:	PUSHJ PDP,DCLI(DSER)	;YES. DISPATCH TO DEVICE DEP. ROUTINE
	JRST UCLS2		;MUST NOT DESTROY UUO,DEVDAT,DSER,UCHN
UCLSBI:	MOVE	TAC,DEVMOD(DEVDAT)
	TLNE DEVDAT,INBFB+INPB	;WAS AN INPUT BUFFER SETUP?
	JRST UCLS4		;YES
	TLNE	TAC,DVDSK	;CLOSING A DISK FILE ?
	JRST	UCLS5		;YES, DO DEVICE DEPENDENT CLOSE ANYWAY.
	JRST	UCLS2		;NO, CLOSE NOT NECESSARY.
UCLS4:	TLNE TAC,DVLNG		;IS THIS A LONG DISPATCH TABLE?
	PUSHJ PDP,DCLI(DSER)	;YES, CLOSE INPUT
	HRRZ TAC1,DEVBUF(DEVDAT)
	HRLI TAC1,PROG
	HRRZ DAT,@TAC1		;FIRST WORD OF 3 WORD BUFFER HEADER
	HRR TAC1,@TAC1		;REMEMBER CURRENT BUFFER IN TAC1
	HRLZI TAC,IOUSE		;USED BOTH FOR HEADER AND EACH BUFFER
	JUMPE DAT,UCLS1		;HAS A RING BEEN SETUP?(NO IF 0)
	HRLI DAT,PROG		;YES
	MOVEI AC1,(DAT)		;IS ADDRESS SPECIFIED BY CONTENTS OF
	PUSHJ PDP,UADRCK	;FIRST WORD OF 3 WORD BUFFER HEADER IN BOUNDS?
	SETZM AC1
UCLS0:	HRR DAT,@DAT		;ADVANCE CURRENT INPUT BUFFER ADDRESS
	CAIN AC1,(DAT)		;IS THIS THE SAME BUFFER AS LAST ONE?
	JRST UCLS1		;YES. BAD RING. LOOPING ON ITSELF.
	MOVEI AC1,(DAT)		;IS ADDRESS OK?
	PUSHJ PDP,UADRCK
	ANDCAM TAC,@DAT		;YES, CLEAR USE BIT.
	CAME TAC1,DAT		;DONE?
	JRST UCLS0
EXTERNAL USRJDA

UCLS1:	HRLI DAT,PROG
	HRR DAT,DEVBUF(DEVDAT)
	IORM TAC,@DAT		;FLAG AS VIRGIN BUFFER IN 3 WORD HEADER
	ADDI DAT,2		;JBFCTR:=0
	SETZM @DAT		;CLEAR INPUT ITEM COUNT.
	MOVE IOS,[XWD IOEND,IODEND]
	ANDCAB IOS,DEVIOS(DEVDAT)
UCLS2:	TRNN UUO,CLSOUT		;SUPPRESS OUTPUT CLOSE?
	TLOE DEVDAT,OCLOSB	;NO. OUTPUT ALREADY CLOSED?
	JRST UCLS3		;YES
	IFN FT2REL,<
	EXTERN RELSEG
	PUSH PDP,UCHN
	PUSHJ PDP,RELSEG	;CLEAR SHARED SEG NAME IF FILE JUST CLOSED HAS
				; EXTENSION .SHR AND SEG HAS SAME DIRECTORY AND NAME
	POP PDP,UCHN
>
	LDB TAC,PIOMOD		;NO.
	CAIGE TAC,SD		;DUMP MODE?
	JRST UCLSBO		;NO. CLOSE BUFFERED OUTPUT
UCLS7:	PUSHJ PDP,DCL(DSER)	;YES. DISPATCH TO DEVICE DEP. ROUTINE
	JRST UCLS3
UCLSBO:	TLNN DEVDAT,OUTBFB+OUTPB	;WAS AN OUTPUT BUFFER SET UP?
	JRST UCLS6		;NO
	HLR DAT, DEVBUF(DEVDAT)	;VIRGIN OUBPUT BUFFER?
	HRLI DAT, PROG
	SKIPG @DAT
	JRST UCLS6		;YES, DO NOT CLOSE UNLESS IT IS A DISK FILE
UCLS2A:	MOVE	DSER,DEVSER(DEVDAT)
	SKIPL @DEVOAD(DEVDAT)	;NO, HAS SERVICE ROUTINE WRITTEN
				; ITS NEXT BUFFER YET?
	JRST UCLS2B		;YES
	TRZ	IOS,760000	;NO,CLEAR ERROR BITS AND START OUTPUT DEVICE
	PUSH PDP,UUO
	PUSHJ	PDP,DOU(DSER)	;CALL SERVICE ROUTINE TO DO OUTPUT
	POP PDP,UUO
	PUSHJ	PDP,WAIT1	;WAIT TILL MOST BUFFERS FILLED
	TRNN	IOS,760000	;ERROR?
	JRST UCLS2A		;NO,RETURN WHEN ALL EMPTIED
				; OR SHUFFLING REQUIRED STOPS DEVICE
UCLS2B:	MOVE DSER,DEVSER(DEVDAT)
	PUSHJ PDP,DCL(DSER)	;CLOSE OUTPUT BUFFER
	HLR DAT,DEVBUF(DEVDAT)
	HRLI DAT,PROG
	HRLZI TAC,IOUSE
	IORM TAC,@DAT
	ADDI DAT,2
	SETZM @DAT		;JBFCTR:=0
	PUSHJ PDP,WAIT1
	TLO DEVDAT,OCLOSB	;SET OCLOSB AFTER OUTPUT IS COMPLETE
UCLS3:	HLLM DEVDAT,USRJDA(UCHN)
	POPJ PDP,		;EXIT THIS UUO

UCLS6:	MOVSI	TAC,DVDSK
	TDNE	TAC,DEVMOD(DEVDAT)	;CLOSING A DISK FILE ?
	JRST	UCLS7		;YES, DO DISK CLOSE ROUTINE IN ANY EVENT
	JRST	UCLS3
,CALLING SEQUENCE
,	INBUF D,N
,	EXIT		RETURNS HERE IF MEMORY NOT EXCEEDED
,CALLING SEQUENCE
,	OUTBUF D,N
,	EXIT		RETURNS HERE IF MEMORY NOT EXCEEDED
, SETS UP AN N BUFFER RING FOLLOWING THE USER'S PROGRAM FOR DEVICE
, D AND INITIALIZES THE JOB BUFFER AREA HEADER:
,	JBFADR0:=1,	JBFADR 1-17:=0
,	JBFADR 18-35:=ADDRESS OF FIRST BUFFER IN RING
,INPUT SETS DEVIAD:=ADDRESS OF FIRST BUFFER IN RING
,OUTPUT SET DEVOAD:=ADDRESS OF FIRST BUFFER IN RING
,BUFPNT IS RESTORED.
	INTERNAL UINBF, UOUTBF
	EXTERNAL PUUOAC,USRJDA


UOUTBF:	TLO DEVDAT,OUTBFB	;FLAG OUTBUF UUO DONE
	PUSH PDP,BUFPNT		;SAVE BUFPNT ON STACK
	PUSHJ PDP,BUFCLC	;SET UP BUFFER RING
	HLR TAC,DEVBUF(DEVDAT)	;TAC:=OUTPUT BUFFER AREA HEADER ADDRESS
	HRRM BUFPNT,DEVOAD(DEVDAT)	;DEVOAD:=ADDRESS OF FIRST BUFFER
				; IN RING
UOBF1:	HRLI TAC,PROG		;RELOCATE BUFFER AREA HEADER ADDRESS
	MOVEM BUFPNT,@TAC	;JBFADR:=IOUSE,ADDRESS OF FIRST BUFFER
				; IN RING
	LDB TAC,PUUOAC
	MOVEM DEVDAT,USRJDA(TAC)
	POP PDP,BUFPNT		;RESTORE BUFPNT FROM STACK
	POPJ PDP,		;EXIT THIS UUO
UINBF:	TLO DEVDAT,INBFB	;FLAG INBUF UUO DONE
	PUSH PDP,BUFPNT		;SAVE BUFPNT ON STACK
	PUSHJ PDP,BUFCLC	;SET UP BUFFER RING
	HRRM BUFPNT,DEVIAD(DEVDAT)	;DEVIAD:=ADDRESS OF FIRST BUFFER
				; IN RING
	HRR TAC,DEVBUF(DEVDAT)	;TAC:=INPUT BUFFER AREA HEADER ADDRESS
	JRST UOBF1
;OPEN UUO - PERFORMS SAME OPERATION AS INIT
;MAY BE USED EASILY BY REENTRANT PROGRAMS
;CALLING SEQUENCE FROM USER AREA
;	OPEN D,ADR
;	ERROR RETURN
;	DEVICE INITED

;LH(ADR)=0,RH(ADR)=DATA MODE THIS INIT
;LH(ADR+1)=OUTPUT BUFFER HEADER ADDRESS
;RH(ADR+1)=INPUT BUFFER HEADER ADDRESS
;C(ADR+2,...,ADR+5)=SAME AS LOOKUP OR ENTER

INTERNAL UOPEN

UOPEN:	PUSHJ PDP,GETWDU	;SET TAC TO CONTENTS OF FIRST ARG(IO STATUS BITS)
	AOJA UUO,UINIT0		;MAKE UUO POINT TO ARG+1(WITH PROG STILL
				; IN INDEX FIELD)


,CALLING SEQUENCE
,	INIT D,MODUS	D=JOB DEVICE CHANNEL
,			MODUS=IORDEL,IOCON,IOWC,MODE.
,	SIXBIT/NAME/	DEVICE NAME
,	XWD OBUF,IBUF	BUFFER AREA HEADER ADDRESSES
,	EXIT1		DEVICE NOT AVAILABLE
,	EXIT2		DEVICE PROPERLY ASSIGNED
,THE LEFT HALF OF NAME CONTAINS THE THREE LETTER DEVICE MNEMONIC,
,   THE RIGHT HALF IS EITHER ZERO (SYSTEM WILL ASSIGN AN ARBITRARY
,   UNIT) OR NON-ZERO TO REQUEST A SPECIFIC UNIT (LEFT JUSTIFIED).
,IF THE SELECTED DEVICE IS NOT AVAILABLE, CONTROL RETURNS TO EXIT1.
,OTHERWISE, THE DEVICE IS ASSIGNED TO THE USER AND ATTACHED TO HIS
,CHANNEL D.  THE DEVICE IS INITIALIZED IN THE FOLLOWING MANNER AFTER
,IOACT IS ZERO:
,	IOBEG:=1
,	DATA MODE:=BITS 32-35 OF AC UUO
,	IOCON:=BIT 31 OF AC UUO
,	IOWC:=BIT 30 OF AC UUO
,	IORDEL:=BIT 29 OF AC UUO
,	IOACT:=IODEND:=IOBKTL:=IODTER:=IODERR:=IOIMPM:=0
,	JBFADR:=JBFCTR:=0 FOR THE SPECIFIED BUFFERS.
,	DEVBUF:=OBUF,IBUF
INTERNAL UINIT
EXTERNAL STREQ,STUSER
EXTERNAL USRJDA,USRHCU,SYSTAP,TPOPJ,TPOPJ1,IADPTR

UINIT:	MOVE TAC,UUO		;SAVE FIRST ARG(IO STATUS BITS) IN TAC
	HRR UUO,-1(PDP)		;SET UUO TO ADR+1 OF USER ARGS
	AOS -1(PDP)		;SET RETURN SKIP THE 2 ARGUMENTS
	AOS -1(PDP)
UINIT0:	PUSH PDP,UUO		;HERE ON OPEN UUO, SAVE ADR+1 OF USER ARGS
	PUSH PDP,TAC		;SAVE IO STATUS BITS(FIRST ARG)
	SKIPE DEVDAT,USRJDA(UCHN)	;IS A DEVICE ALREADY ASSIGNED TO THIS CHAN?
	CAMLE UCHN,USRHCU	;YES, IS THIS CHAN. LESS OR EQUAL TO HIGHEST
				; CHAN. FOR THIS USER?
	JRST UINITA		;NO, NO PREVIOUS DEVICE TO RELEASE
	PUSHJ PDP,RELEA0	;RELEASE PREVIOUS DEVICE ON THIS CHAN.
UINITA:	MOVE UUO,-1(PDP)	;RESTORE UUO (ADR+1 OF 3 ARGS)
	PUSHJ PDP,GETWDU	;C(TAC)=DEVICE NAME IF IN BOUNDS
				; DO NOT RETURN IF OUT OF BOUNDS(PRINT ERR AND STOP)
				; SET ITEM TO CURRENT JOB NUMBER
	PUSHJ PDP,DEVSRC	;SEARCH FOR DEVICE NAME
				; (SET SYSDEV BIT IN LH OF
				; DEVDAT IF THIS IS SYSTEM TAPE)
	JRST UINITE		;NO SUCH DEVICE
	MOVE UUO,(PDP)		;RESTORE USER'S MODE SETTING
	PUSHJ	PDP,CHKMOD	;CHECK FOR LEGAL MODE, IF NOT RIGHT DONT RETURN
	MOVE TAC,DEVNAM(DEVDAT)	;PHYSICAL DEVICE NAME
	CAME TAC,[SIXBIT /DSK/]	;NOT DISK?
	CAME TAC,SYSTAP		;SYSTEM TAPE DEVICE?
	JRST UINIT1		;NO, DISK OR NOT SYSTEM TAPE
	AOSE STREQ		;SYSTEM TAPE, INCREMENT REQUEST COUNT
	PUSHJ PDP,STWAIT	;SYSTEM TAPE BUSY, PUT JOB IN WAIT
	MOVEM ITEM,STUSER	;SET THIS JOB AS ONLY USER OF SYSTEM TAPE
				; CONTROL C DOES NOT STOP JOB WHILE USING S. T.
UINIT1:	MOVE TEM,DEVMOD(DEVDAT)	;DEVICE CHARACTERISTICS
	TLNN TEM,DVDTA		;IS THIS DEVICE A DECTAPE?
	JRST UINITB		;NO
	LDB TAC1,IADPTR		;YES, GE NO OF USER CHANS DEV INITED ON
	HRR TEM,TAC1		;SAVE OLD NUMBER
	AOS TAC1		;INCREASE CHANNEL COUNT
	CAIL TAC1,3		;ANY MORE THAN JUST 2 CHANNELS?
	JRST UINITE		;YES, GIVE ERROR RETURN(POP TAC)
	DPB TAC1,IADPTR		;YES, STORE UPDATED CHANNEL COUNT FOR THIS DEVICE(DTA)
UINITB:	MOVEI TAC1,ASSPRG	;TRY TO ASSIGN IT BY PROGRAM
	PUSHJ PDP,ASSASG
	JRST UINIT6		;NOT AVAILABLE, GIVE ERROR RETURN(POP TAC)
	POP PDP,UUO		;RESTORE USER'S MODE SETTING
	PUSHJ PDP,SETIOS	;SET DDB IOS STATUS WORD
				; FROM RT. HALF OF AC UUO
				; WAIT FOR DEVICES TO BECOME INACTIVE IN CASE IT IS
				; INITED ON A DIFFERENT CHANNEL(OR MONITOR COMMAND
				; RESPONSE ON TTY)
	MOVSI IOS,IOBEG
	IORB IOS,DEVIOS(DEVDAT)
UINITL:	CAMG UCHN,USRHCU	;IS THIS CHAN. .GT. HIGHEST CHAN. IN USE?
	JRST UINITC		;NO
	AOS TAC,USRHCU		;YES, BUMP HIGHEST SO FAR BY ONE
	SETZM USRJDA(TAC)	;AND CLEAR IT OUT
	JRST UINITL		;AND KEEP LOOKING

UINITC:	TLO DEVDAT,INITB+ICLOSB+OCLOSB;SET INIT UUO BIT
				;PREVENT SUPERFLUOUS CALLS TO CLOSE (SEE LOOKUP,ENTER)
	AOS UUO,(PDP)		;ADVANCE TO 3RD ARG(BUFFER HEADER)
	PUSHJ PDP,GETWDU	;C(TAC)=BUFFER HEADER ARG
	HLRZ TAC1,TAC		;OUTPUT BUFFER HEADER FROM USER
	JUMPE TAC1,UINIT4	;WAS ONE SPECIFIED?
	HRLM TAC1,DEVBUF(DEVDAT);YES, SET DEVICE DATA BLOCK
	TLO DEVDAT,OBUFB	;SET OUTPUT BUFFER SPECIFIED BIT
	PUSHJ PDP,UINITZ	;INITIALIZE OUTPUT BUFFER HEADER
UINIT4:	PUSHJ PDP,GETWDU	;C(TAC)=BUFFER HEADER ARG FROM USER
	HRRZ TAC1,TAC		;INPUT BUFFER HEADER
	JUMPE TAC1,UINIT5	;WAS ONE SPECIFIED?
	HRRM TAC1,DEVBUF(DEVDAT)	;YES, SET DEVICE DATA BLOCK
	TLO DEVDAT,IBUFB	;SET INPUT BUFFER SPECIFIED BIT
	MOVSI IOS,IOEND		;CLEAR END OF FILE FLAG
	ANDCAB IOS,DEVIOS(DEVDAT)	;AND RETAIN IOS
	PUSHJ PDP,UINITZ	;INITIALIZE INPUT BUFFER HEADER
UINIT5:	MOVEM DEVDAT,USRJDA(UCHN)	;STORE UUO BITS AND  DEVICE
				; DATA BLOCK ADDRESS
	JRST TPOPJ1		;SUCCESSFUL RETURN(POP TAC)

UINIT6:	TLNE TEM,DVDTA		;WAS DEVICE A DECTAPE?
	DPB TEM,IADPTR		;YES, RESTORE NO. OF USER CHAN INITED ON
UINITE:	POP PDP,TAC		;REMOVE IO STATUS ARG
	JRST TPOPJ		;AND GIVE ERROR RETURN AND POP TAC
,CALLING SEQUENCE
,	PUSHJ PDP,UINITZ
,	EXIT		RETURNS HERE IF MEMORY NOT EXCEEDED.
,SETS JBFADR:=JBFCTR:=0 FOR THE BUFFER AREA HEADER WHOSE ADDRESS
,IS IN AC TAC1.  ALSO,JBFPTR 0-5:=JBFPTR 12-17:=0,JBFPTR 6-11:=BYTE SIZE


UINITZ:	HRLI TAC1,PROG		;SET FOR RELOCATION
	MOVEI AC1,2(TAC1)	;CHECK 3RD WORD OF BUFFER HEADER
	PUSHJ PDP,UADRCK
	SETZM @TAC1		;CLEAR FIRST WORD (CURRENT BUFFER) OF 3 WORD HEADER
	AOS TAC1		;POINT TO SECOND WORD (BYTE POINTER)
	PUSH PDP,TAC1
	AOS TAC1		;POINT TO THIRD WORD (ITEM COUNT)
	SETZM @TAC1		;SET ITEM COUNT TO ZERO
	PUSHJ PDP,SETBYT	;SET BYTE SIZE ACCORDING TO MODE AS SET IN AC IOS
	TLZ TAC,770077
	POP PDP,TAC1
	HLLM TAC,@TAC1		;AND STORE IN SECOND WORD
	POPJ PDP,		;RETURN
;LONG DISPATCH TABLE UUOS - GET HERE ONLY IF DEVICE HAS LONG
;DISPACTH TABLE
;DISPACTH TO DEVICE DEPENDENT SERVICE ROUTINE
;ENTER UUO - ENTER FILE NAME IN DIRECTORY

EXTERNAL USRJDA

UDEN:	MOVEI TAC,CLSIN
	TLNN DEVDAT,OCLOSB	;FILE OPEN?
	PUSHJ PDP,UDLKC		;YES. CLOSE IT[OCLOSB_1]
	TLO IOS,IOBEG
	TRZ IOS,776000
	MOVEM IOS,DEVIOS(DEVDAT)
	HLLM DEVDAT,USRJDA(UCHN)	;STORE UUO BITS
	PUSHJ PDP,DEN(DSER)	;ATTEMPT AN ENTER
	POPJ PDP,		;FAILURE
	TLZ DEVDAT,OCLOSB
	TLO DEVDAT,ENTRB		;NOTE SUCCESSFUL ENTER
	JRST DLKDEN		;STORE THE PROGRESS BITS

;LOOKUP UUO - LOOKUP FILE NAME IN DIRECTORY

EXTERNAL USRJDA

UDLK:	MOVEI TAC,CLSOUT	;IN HIBIT OUTPUT CLOSE BIT
	TLNN DEVDAT,ICLOSB	;FILE OPEN?
	PUSHJ PDP,UDLKC		;YES. CLOSE IT[ICLOSB_1]
	TDZ IOS,[XWD IOEND,776000]
	MOVEM IOS,DEVIOS(DEVDAT)
	HLLM DEVDAT,USRJDA(UCHN)	;STORE UUO BITS
	PUSHJ PDP,DLK(DSER)	;ATTEMPT A LOOKUP
	POPJ PDP,		;FAILURE
	TLZ DEVDAT,ICLOSB
	TLO DEVDAT,LOOKB	;NOTE SUCCESSFUL LOOKUP
DLKDEN:	LDB TAC,PUUOAC		;GET CHANNEL #
	HLLM DEVDAT,USRJDA(TAC) ;STORE UUO PROGRESS BITS
	JRST CPOPJ1		;SUCCESS RETURN TO USER (CALL+2)

INTERNAL UDLKC

UDLKC:	PUSH PDP,UUO
	HRRI	UUO,(TAC)
	PUSHJ PDP,CLOSE1
	POP PDP,UUO
	JRST	WAIT1
;RENAME UUO - HERE ON SHORT DISPATCH TABLE DEVICES TOO
INTERNAL FT2REL

EXTERNAL CPOPJ1

URENAM:	MOVE TAC,DEVMOD(DEVDAT)	;IS THIS DEVICE A LONG DISPATCH TABLE?
	TLNN TAC,DVLNG
	JRST CPOPJ1		;NO, GIVE SKIP RETURN TO USER
IFE FT2REL,<
	JRST DRN(DSER)		;YES, DISPATCH TO SERVICE ROUTINE
>
IFN FT2REL,<
	EXTERN RELSG1
	PUSHJ PDP,DRN(DSER)	;TRY TO RENAME (SERVICE ROUTINE)
	POPJ PDP,		;ERROR,ERROR RETURN TO USER
	JRST RELSG1		;SUCCESSFUL RENAME, GO ZERO SHARABLE SEG NAME
				; IF NEW FILE EXT IS .SHR AND FILE NAME
				; FIND DIRECTORY (DEVICE) ARE SAME AS SHARABLE SEG
				; ALWAYS SKIP RETURN
>

;SETO UUO - SET NEXT OUTPUT BLOCK NUMBER(DECTAPE)

UDSO:	JRST DSO(DSER)

;SETI UUO - SET NEXT INPUT BLOCK NUMBER

UDSI:	JRST DSI(DSER)

;GETF UUO - GET NEXT FREE BLOCK

UDGF:	JRST DGF(DSER)

;MTAPE UUO - MAGTAPE OPERATIONS

UMTAPE:	JRST DMT(DSER)

;UTPCLR - CLEAR DECTAPE DIRECT.

UTPCLR:	MOVE TAC,DEVMOD(DEVDAT)	;IS THIS A LONG DISPATCH TABLE?
	TLNN TAC,DVLNG
	POPJ PDP,		;NO,RETURN
	JRST DCLR(DSER)		;YES, DISPATCH
;INPUT UUO

;1)  IF OUTPUT ACTIVE ON THIS CHANNEL, WAIT FOR IT TO COMPLETE.
;2)  IF DUMP MODE, WAIT FOR DEVICE INACTIVE, CALL SERVICE
;	ROUTINE TO START INPUT, WAIT TILL COMPLETE, THEN RETURN TO USER.
;3)  IF NO BUFFER RING SETUP, SET UP 2 RING BUFFER.
;4)  IF FIRST REFERENCE, START SERVICE ROUTINE, GO TO
;5)  FLAG CURRENT BUFFER AS FREE TO RECEIVE MORE INPUT
;	(USE BIT SET TO 0).
;	START SERVICE ROUTINE FILLING FIRST BUFFER WITH USE BIT 0
;	(NEXT BUFFER OR ONE AHEAD OF IT)
;	(SERVICE ROUTINE WILL SET USE BIT WHEN IT FINISHES FILLING
;	BUFFER).
;7)  IF NEXT INPUT BUFFER IS FULL OF DATA, GO TO 10).
;8)  PUT JOB IN IO WAIT TILL NEXT BUFFER FILLED.
;9)  IF NEXT INPUT BUFFER STILL NOT FILLED, CHECK FOR END
;	OF FILE OR ERROR BITS SET BY SERVICE ROUTINE.
;10) CONVERT WORD COUNT AS STORED BY SERVICE ROUTINE IN THIRD
;	WORD OF BUFFER TO ITEM COUNT AND STORE IN THIRD WORD
;	OF HEADER (ITEM COUNT) ALSO SET BYTE POINTER (SECOND
;	WORD OF HEADER) AND RETURN TO USER.
INTERNAL IN
EXTERNAL USRJDA,PIOMOD

IN:	TLNE IOS,IO		;IS THIS DEVICE ALREADY DOING OUTPUT?
	PUSHJ PDP,WAIT1		;YES, WAIT TILL IT IS FINISHED.
	TLO DEVDAT,INPB		;FOR THIS DEVICE.
	TLZ DEVDAT,ICLOSB
	HLLM DEVDAT,USRJDA(UCHN)	;IN LH OF CURRENT JOB DEVICE CHANNEL
	LDB TAC,PIOMOD		;IO MODE
	CAIL TAC,SD		;IT THE IO MODE DUMP(SD,D,DR)?
	JRST INDMP		;YES
IN1:	HRR JBUF,DEVBUF(DEVDAT)	;NO, GET ADDRESS OF BUFFER HEADER
	HRLZI TAC,IOUSE		;BUFFER INUSE BIT
	HRLI JBUF,PROG		;SET INDEX FIELD FOR RELOCATION USING AC PROG
	MOVEI AC1,2(JBUF)	;CHECK BUFFER HEADER
	PUSHJ PDP,UADRCK
	MOVE IOS,DEVIOS(DEVDAT)	;SETUP IO STATUS AGAIN FORM FROM MEMORY
				; AC IOS IS CLOBBERED BY AUTOMATIC CORE EXPANSION
				; ON AN IMPLICIT INBUF ON FIRST INPUT
	MOVE TAC1,@JBUF		;GET WORD 1 OF 3 WORD BUFFER HEADER.
	HRLI TAC1,PROG		;SET INDEX FIELD COR RELOCATION USING AC PROG
	SKIPG @JBUF		;HAS A BUFFER RING BEEN SET UP (RH NON-ZERO)
				; WHICH HAS BEEN REFERENCED BY PREVIOUS INPUT (BIT0=0)
	JRST INPUTF		;NO. GO SET UP BUFFER IF NECESSARY AND DO FIRST IO
	HRRZ AC1,TAC1		;YES, CHECK ADR. TO SEE IF OK
	PUSHJ PDP,UADRCK
	MOVE	IOS,DEVIOS(DEVDAT)
	TDNN	TAC,@TAC1
	JRST	INPT1
	ANDCAB TAC,@TAC1	;FLAG CURRENT BUFFER AS FREE TO
				; RECEIVE MORE INPUT, CLEAR USE BIT
				; AND GET POINTER TO NEXT BUFFER
	HRRM TAC,@JBUF		;SET WORD 1 IN 3 WORD HEADER TO NEXT BUFFER
	HRRZ AC1,TAC		;AND CHECK ITS ADDRESS TO SEE IF IN BOUNDS
	PUSHJ PDP,UADRCK
	TRNE IOS,IOACT		;IS THE DEVICE ALREADY ACTIVE
	JRST INPT0C		;YES
	MOVE AC1,DEVMOD(DEVDAT)	;GET DEVICE CHARACTERISTIC WORD
	HRLI TAC,PROG		;SET FOR RELOCATION
	TLNN AC1,DVTTY		;IS IT A TTY?
	HRR TAC,@TAC		;GET POINTER 1 BUFFER AHEAD OF NEXT BUFFER
				; IF NOT TTY.
	HRRZ AC1,TAC		;SEE IF USER HAS CLOBBERED POINTER
	PUSHJ PDP,UADRCK
	SKIPL @TAC		;IS THE USE BIT SET?
	PUSHJ PDP,CALIN		;NO, START SERVICE ROUTINE FILLING EMPTY BUFFER
INPT0C:	HRR TAC1,@TAC1		;GET USE BIT FOR NEXT BUFFER
INPT0A:	SKIPGE @TAC1		;IS USE BIT SET YET?(BUFFER FILLED YET?)
	JRST INPUT2		;YES, RETURN IMMEDIATELY TO USER
INPT2:	PUSHJ PDP,WSYNC		;NO, PUT JOB IN IO WAIT TILL BUFFER FILLED.
	SKIPL @TAC1		;RETURN WHEN BUFFER FILLED. CHECK TO MAKE SURE.
	JRST INEOF		;NO, MUST BE EOF OR ERROR
INPUT2:	ADDI TAC1,1		;YES, GET WORD COUNT AS SET BY IO SERVICE
	HRRZ ITEM,@TAC1		;RH OF 3RD WORD(FIRST SO-CALLED DATA WORD)
	SOJA TAC1,IOSETC	;SET ITEM COUNT AND BYTE POINTER
				; IN 3 WORD HEADER AND RETURN TO USER

INPT1:	TRNN	IOS,IOACT
	PUSHJ	PDP,CALIN
	JRST	INPT2


INEOF:	TDNN IOS,[XWD IOEND,IODERR+IOBKTL+IODTER+IOIMPM]
				; EOF OR ERROR BIT SET BY SERVICE ROUTINE
	JSP	DAT,UUOERR	;NO,MONITOR ERROR AT UUO LEVEL
	TLNE IOS,IOEND		;IS THIS EOF?
	TRO IOS,IODEND		;YES, SET USER EOF BIT.
	IORM IOS,DEVIOS(DEVDAT)
	POPJ PDP,		;RETURN TO USER'S PROGRAM



;HERE ON FIRST INPUT AFTER INIT, INIT & LOOKUP, OR INIT & LOOKUP & INPUT
INPUTF:	ANDCAB TAC,@JBUF	;MARK THAT BUFFERS HAVE BEEN REFER
				; BY CLEARING SIGN BIT OF 1ST WORD IN 3 WORD
				; IN 3 WORD BUFFER HEADER
	JUMPE TAC,INPUT3	;HAS A RING BEEN SET UP YET?
	HRRZ AC1,TAC1		;YES ADDRESS CHECK FIRST USER BUFFER
	PUSHJ PDP,UADRCK	;
	SKIPG @TAC1		;IS USE BIT SET IN FIRST USER INPUT BUFFER?
				; CAN HAPPEN IF TTY AND USER HAS TYPED
				; IN LINE AFTER INBUF BUT BEFORE FIRST INPUT UUO
	JRST INPUT2		;YES, DO NOT CALL SERVICE ROUTINE(SCNSER)
				; SINCE USER BUFFER ALREADY HAS DATA
	HRRM TAC,DEVIAD(DEVDAT)	;YES, STORE ADR. OF 2ND WORD OF
				; A BUFFER FOR SERVICE ROUTINE
	PUSHJ PDP,CALIN		;YES. GO START IO SERVICE ROUTINE
				; FILLING BUFFER
	JRST INPT0A
INPUT3:	HRRI UUO,2		;BUFFERS NOT SETUP YET.
				; SET UP 2
	PUSHJ PDP, UINBF
	HLLZS UUO		;CLEAR RIGHT HALF
	JRST IN1


INDMP:	PUSHJ PDP,WSYNC		;INPUT DUMP
	PUSHJ PDP,DDI(DSER)	;CALL SERVICE ROUTINE
	JRST WAIT1		;THEN WAIT TILL IO  FINISHED BEFORE
				; RETURNING TO USER.
EXTERNAL JOBPFI,USRREL

CALIN:	TLNE IOS,IOEND
	POPJ PDP,
	PUSH PDP,TAC1
	PUSH PDP,JBUF
	HRRZ AC1,DEVIAD(DEVDAT)	;IS FIRST ADR. ABOVE JOB DATA AREA?
	CAIG AC1,JOBPFI
	JRST ADRERR		;NO, PRINT ERROR AND STOP JOB
	HLRZ AC2,@DEVIAD(DEVDAT)	;GET LENGTH OF BUFFER
	TRZ AC2,IOUSE		;CLEAR USE BIT IN CASE IT IS ON(TTY)
	ADD AC1,AC2
	CAMLE AC1,USRREL	;IS LAST ADDRESS IN BOUNDS?
	JRST ADRERR		;NO, STOP JOB AND PRINT ERROR
	PUSHJ PDP,DIN(DSER)	;DISPATCH TO IO SERVICE ROUTINE
	POP PDP,JBUF
	POP PDP,TAC1
	POPJ PDP,
,CALLING SEQUENCE
,     OUTPUT D,
,     EXIT
,OR
,     OUTPUT D, ADR
,     EXIT

,IF INPUT IS ACTIVE, WAIT FOR IT TO COMPLETE.
,IF DUMP MODE WAS SELECTED BY THE LAST INIT UUO OR SETSTS UUO
,   THE PROGRAM WAITS UNTIL THE DEVICE IN INACTIVE AND THEN
,   WRITES THE DUMPFILE AND RETURNS CONTROL TO THE USER'S PROGRAM
,   WHEN IO HAS COMPLETED.
,IF THE MODE IS NOT DUMP, THEN
,1) IF ADR IS NOT ZERO, WAIT FOR DEVICE TO BECOME INACTIVE THEN SET THE
,   CURRENT BUFFER ADDRESS EQUAL TO ADR AND AN INDICATOR (JBFADR0)
,   SPECIFYING THAT THIS BUFFER RING HAS NEVER BEEN REFERENCED FROM THE
,   USER'S PROGRAM BY AN INPUT OR AN OUTPUT UUO.  OTHERWISE, GO TO
,   2) DIRECTLY.

,2) IF THE BUFFER RING HAS NEVER BEEN REFERENCED (JBFADR0=1), THE
,   BUFFER IS CLEARED, IOUSE SET TO ZERO AND
,      IF THE CURRENT BUFFER ADDRESS IS ZERO, A TWO BUFFER RING IS SET UP.
,      THEN GO TO 8
,
,3) IF THE BUFFER RING HAS BEEN REFERENCED (JBFADR0=0	,THEN A CHECK IS
,   MADE TO DETERMINE IF THE WORD COUNT IS TO BE COMPUTED.
,      IF THE WORD COUNT IS TO BE COMPUTED (IOWC=0), IT IS SET EQUAL
,      TO THE ADDRESS FOR THE LAST DATA WORD MINUS THE ADDRESS OF THE
,      BUFFER MINUS ONE.

,4) IOUSE IS SET TO ONE, INDICATING THAT THE BUFFER IS FULL OR BEING
,   EMPTIED, AND THE CURRENT BUFFER ADDRESS IS ADVANCED.

,5) IF THE DEVICE IS NOT ACTIVE (IOACT=0), OUTPUT IS STARTED.
,6) IF THE CURRENT BUFFER IS FULL OR BEING EMPTIED (IOUSE=1),
,   THE PROGRAM WAITS UNTIL THE DEVICE FINISHES THE BUFFER
,   (THE OUTPUT SERVICE ROUTINE CLEARS THE USE BIT WHEN
,   IT FINISHES OUTPUTTING A BUFFER).
,7) THE CURRENT BUFFER IS CLEARED.
,8) THE ITEM POINTER IS INITIATED TO THE CURRENT BUFFER ADDRESS+1
,   AND THE ITEM COUNT IS SET TO THE PRODUCT OF THE BUFFER SIZE
,   MINUS ONE AND THE INTEGER PART OF 36/BYTE SIZE.
,9) RETURN TO THE USER'S PROGRAM
;HERE ON OUTPUT UUO
EXTERNAL USRJDA,PIOMOD

UOUT:	TLO DEVDAT,OUTPB	;SET OUTPUT UUO BIT
	TLZ DEVDAT,OCLOSB	;CLEAR CLOSE OUTPUT BIT

;HERE FROM DEVICE SERVICE ROUTINES ON CLOSE UUO

INTERNAL OUT

OUT:	TLNN IOS,IO		;IS THIS DEVICE ALREADY DOING INPUT?
	PUSHJ PDP,WAIT1		;YES, WAIT TILL IT BECOMES INACTIVE
	HLLM DEVDAT,USRJDA(UCHN);SAVE NEW BIT SETTINGS.
	LDB TAC,PIOMOD		;GET DATA MODE SET BY INIT OR SETSTS.
	CAIL TAC,SD		;IS IT DUMP MODE(SD,DR,D)?
	JRST OUTDMP		;YES.
	PUSHJ PDP,OUTA		;NO, CHECK FOR NON-ZERO ADDRESS(USER
				; CHANGING RING)
	HLR JBUF,DEVBUF(DEVDAT)	;REL. ADDR. OF OUTPUT BUFFER HEADER
	MOVEI AC1,2(JBUF)	;CHECK END OF 3 WORD HEADER
	PUSHJ PDP,UADRCK
	HRLI JBUF,PROG		;SET INDEX FIELD FOR RELOCATION.
	SKIPG TAC1,@JBUF	; CHECK FIRST WORD OF BUFFER HEADER
	JRST OUTF		;RING NOT SET UP OR FIRST REFERENCE TO RING
	AOS JBUF		;COMPUTE WORD COUNT FROM BYTE POINTER
	HRRZ TAC,@JBUF		;GET RH OF BYTE POINTER.
	ADDI TAC1,1		;REL. ADDR. OF 3RD WORD IN BUFFER.
	SKIPE	TAC
	SUB TAC,TAC1		;DISTANCE FILLED BY USER.
	HRLI TAC1,PROG
	TRNE IOS,IOWC		;DOES USER WANT SYSTEM TO COMPUTE WORD
				; COUNT FROM BYTE POINTER?
	JRST OUT2		;NO.
	HRRZ AC1,TAC1		;PROCEED ONLY IF ADDR. OF WORD COUNT IN BOUNDS
	ADDI	AC1,(TAC)	;FORM REL. ADR OF LAST WORD TO OUTPUT
	PUSHJ PDP,UADRCK
	HRRM TAC,@TAC1		;YES, STORE WORD COUNT IN 3RD WORD OF BUFFER.
OUT2:	SUBI JBUF,1		;REL. ADDR. OF 1ST WORD IN HEADER
				; (POINTER TO CURRENT BUFFER).
	SUBI TAC1,1			;REL. ADDR. OF 2ND WORD IN BUFFER
					; (LINK TO NEXT BUFFER).
	HRLZI TAC,IOUSE		;FLAG CURRENT BUFFER CONTAINS ACTIVE DATA.
	IORB TAC,@TAC1
	HRRM TAC,@JBUF		;ADVANCE CURRENT BUFFER ADDRESS
	MOVE IOS,DEVIOS(DEVDAT)	;IS DEVICE ACTIVE?
	TRNN IOS,IOACT
	PUSHJ PDP,DOU(DSER)	;NO,START OUTPUT.
	HLR JBUF,DEVBUF(DEVDAT)	;JBUF TO REL. ADDR. OF BUFFER HEADER
	HRLI JBUF,PROG		;SET TO RELOCATE
	MOVE TAC1,@JBUF		;TAC1 TO REL. ADDR. OF 2ND WORD OF BUFFER.
	HRRZ AC1,TAC1
	PUSHJ PDP,UADRCK
	HRLI TAC1,PROG
	MOVEI	TAC,@JBUF
	HLLZS	1(TAC)
	SKIPG @TAC1		;HAS SERVICE ROUTINE EMPTIED NEXT BUFFER
				; YET (USE BIT = 0)?
	PUSHJ PDP,WSYNC		;NO, WAIT.
	JRST OUTS		;RETURN TO USER.


OUTF:	SKIPE TAC1,@JBUF
	JRST OUTF1
	HRRI UUO,2
	PUSHJ PDP,UOUTBF
	HLR JBUF,DEVBUF(DEVDAT)
	HRLI JBUF,PROG
OUTF1:	HRLZI TAC, IOUSE
	ANDCAB TAC, @JBUF	;IOUSE:=0
	HRRM TAC,DEVOAD(DEVDAT)
OUTS:	HRRZ TAC,@JBUF		;CLEAR NEXT OUTPUT BUFFER.
	PUSHJ PDP,BUFCLR	;BEING CLEARED.
	JRST ADRERR		;ADDRESS CHECK
	HRR TAC1,@JBUF
	HRLI TAC1,PROG
	LDB ITEM,[POINT 17,@TAC1,17]
	SOJA ITEM,IOSETC
				; ADDRESS+1
				; JBFCTR:=(BUFFER SIZE-1)*[36/BYTE
				; SIZE]
				; RETURN TO USER'S PROGRAM

OUTDMP:	PUSHJ PDP,WSYNC
	PUSHJ PDP,DDO(DSER)
	JRST WAIT1		;WAIT BEFORE RETURNING TO USER
,CALLING SEQUENCE:
,	PUSHJ PDP,OUTA
,	EXIT		ALWAYS RETURNS HERE
,IF THE ADDRESS FIELD OF AC UUO IS ZERO,EXIT. OTHERWISE,CHECK IOACT.
,IF IOACT=1, WAIT FOR IOACT=0.
,SET JBFADR18-35:=ADDRESS FIELD OF AC UUO. JBFADR0:=1 AND EXIT.

	INTERN OUTA
OUTA:	TRNN UUO,777774		;IS BUFFER ADDRESS SPECIFIED?
	POPJ PDP,		;NO
	PUSHJ PDP,WAIT1
	HLR JBUF,DEVBUF(DEVDAT)
	HRLI JBUF,PROG
	HRRM UUO,@JBUF
	HRRM UUO,DEVOAD(DEVDAT)
	HRLZI TAC,IOUSE
	ANDCAM TAC,@JBUF
	POPJ PDP,		;RETURN
,RELEASE A DEVICE

INTERNAL RELEA1,RELEA2,RELEA3,RELEA5,RELEA6,RELEA9
EXTERNAL USRJDA,USRHCU,CPOPJ,SYSTAP,STUSER,STREQ,STAVAL,PJOBN,IADPTR

RELEA0:
RELEA2:RELEA3:
RELEA1:	TRZ UUO,-1		;CLOSE BOTH INPUT AND OUTPUT
	PUSHJ PDP,CLOSE1
	PUSHJ PDP,WAIT1		;WAIT FOR DEVICE TO BECOME INACTIVE
RELEA5:	PUSHJ PDP,DRL(DSER)	;DISPATCH TO DEVICE SERVICE ROUTINE
	MOVEI IOS,IOACT		;CLEAR IO ACTIVE BIT
	ANDCAB IOS,DEVIOS(DEVDAT)	;AND RETURN WITH IOS SET
	LDB TAC1,IADPTR		;GET COUNT OF NO OF CHANS DEVICE ON(IF DTA)
	SOS TAC1		;COUNT DOWN BY ONE
	MOVE TAC,DEVMOD(DEVDAT)
	TLNE TAC,DVDTA		;DEVICE A DTA?
	DPB TAC1,IADPTR		;YES, STORE UPDATED COUNT
	SETZB DAT,USRJDA(UCHN)	;CLEAR DEVICE ASSIGNMENT
	MOVE TAC,USRHCU		;HIGHEST IO CHANNEL IN USE
RELEA4:	HRRZ TAC1,USRJDA(TAC)
	JUMPN DAT,RELE4A	;NON-ZERO CHAN. ALREADY?
	MOVE DAT,TAC1		;NO, SET DAT WHEN FIRST(HIGHEST) FOUND
	MOVEM TAC,USRHCU	;STORE HIGHEST IN USE CHANNEL
RELE4A:	CAIE TAC1,(DEVDAT)	;IS THIS DEVICE SAME AS ONE BEING RELEASED?
	SOJGE TAC,RELEA4
	JUMPGE TAC,CPOPJ	;EXIT IF ON ANOTHER CHANNEL
	HLLZS DEVIAD(DEVDAT)	;CLEAR INPUT BUFFER ADDRESS
	HLLZS DEVOAD(DEVDAT)	;AND OUTPUT BUFFER ADDRESS.
;CALLED FROM ERROR STOP ROUTINE(ESTOP)
RELEA9:	MOVE TAC,DEVNAM(DEVDAT)	;IS THIS SYSTEM TAPE?
	CAME TAC,[SIXBIT /DSK/]	;DSK IS NEVER QUEUED
	CAME TAC,SYSTAP
	JRST RELEA7		;IS DISK OR NOT SYSTEM TAPE
	SKIPN STUSER		;HAS COUNT ALREADY BEEN REDUCED AT ESTOP?
	JRST RELEA7		;YES
	SETZM STUSER		;YES, CLEAR SYSTEM USER NO.
	SOSL STREQ		;YES, REDUCE COUNT
	SETOM STAVAL		;SOMEONE IS WAITING, SET AVAILABLE FLAG/
RELEA7:	MOVEI TAC1,ASSPRG	;CLEAR ASSIGNED BY PROGRAM BIT
RELEA6:	ANDCAB TAC1,DEVMOD(DEVDAT)	;CALLED FROM DEASSIGN
	TRZ TAC1,777		;CLEAR JOB NO. FIELD
INTERNAL FTDISK
IFE FTDISK,<
		TDNN TAC1,[XWD TTYATC,ASSCON+ASSPRG]
		DPB TAC1,PJOBN	;CLEAR JOB NUMBER IF ALL 3 BITS OFF
		POPJ PDP,	;IE ASSIGNED BY CONSOLE,PROGRAM, OR
>
IFN FTDISK,<EXTERNAL CLRDDB,IPOPJ
	TDNE TAC1,[XWD TTYATC,ASSCON+ASSPRG]
	POPJ PDP,		;DEVICE ASSIGNED BY OTHER MEANS TOO
	DPB TAC1,PJOBN		;CLEAR JOB NUMBER
	PUSH PDP,ITEM		;SAVE JOB NO.
	TLNE TAC1,DVDSK		;IS DEVICE A DSK
	PUSHJ PDP,CLRDDB	;YES-RETURN DDB TO STORAGE
	JRST IPOPJ		;RESTORE JOB NO. & RETURN.
>
,CALLING SEQUENCE
,	STATO D,MASK
,	EXIT1		ALL SELECTED BITS ARE 0
,	EXIT2		SOME SELECTED BITS ARE 1
,TESTS BITS OF I/O STATUS WORD OF DEVICE ON USER'S CHANNEL D WHICH
,ARE SELECTED BY MASK.


	INTERN USTATO
USTATO:	TRNE IOS,(UUO)		;SKIP IF ANY INDICATED BITS ARE ONE
	AOS (PDP)
	POPJ PDP,		;RETURN TO USER


,CALLING SEQUENCE
,	STATUS D,ADR
,	EXIT		ALWAYS RETURNS HERE
,STORES I/O STATUS WORD OF DEVICE ON CHANNEL D IN LOCATION ADR.


INTERN USTATS


USTATS:	HRRZ TAC,IOS		;GET USER HALF OF IOS.
	JRST STOTAC		;ADDRESS CHECK AND STORE IN USER AREA


,CALLING SEQUENCE
,	STATZ D,MASK
,	EXIT1		SOME SELECTED BITS ARE 1
,	EXIT2		ALL SELECTED BITS ARE 0

,TESTS BITS OF I/O STATUS WORD OF DEVICE ON USER'S
,CHANNEL D WHICH ARE SELECTED BY MASK.

	INTERN USTATZ

USTATZ:	TRNN IOS,(UUO)		;SKIP IF ALL INDICATED BITS ARE ZERO
	AOS (PDP)
	POPJ PDP,		;RETURN TO USER
;IN UUO - LIKE INPUT	SKIPS IF  EOF OR ERRORS

INTERNAL TIN

TIN:	PUSHJ PDP,IN		;DO INPUT UUO
	TRNE IOS,IOBKTL+IODTER+IODERR+IOIMPM+IODEND
	AOS (PDP)
	POPJ PDP,


;OUT UUO - LIKE OUTPUT  -  SKIPS IF ERRORS

INTERNAL TOUT

TOUT:	PUSHJ PDP,UOUT		;DO OUTPUT UUO
	TRNE IOS,IOBKTL+IODTER+IODERR+IOIMPM
	AOS (PDP)
	POPJ PDP,


;5 UUOS FOR EACH INSTALLATION TO DEFINE
;OPCODES 42-46


SUBTTL	IOCSS - COMMON IO SUBROUTINES

;ROUTINE TO ADVANCE OUTPUT BUFFER AT INTERRUPT LEVEL

;CALL:	PUSHJ PDP,ADVBFE
,	EXIT1		RETURN IF NEXT BUFFER IS EMPTY
,	EXIT2		RETURN IF NEXT BUFFER IS FULL
,CLEARS THE USE BIT (IOUSE:=0) OF THE BUFFER POINTED TO BY THE
,OUTPUT BUFFER ADDRESS (DEVOAD) OF THE CURRENT DEVICE DATA BLOCK
,AND ADVANCES THE BUFFER ADDRESS TO THE NEXT BUFFER IN THE RING.
,UPON RETURN, SKIPS IF THE NEXT BUFFER IS FULL.
;SECOND WORD OF NEXT BUFFER IS ADDRESS CHECKED TO
;MAKE SURE IT IS NOT IN JOB DATA AREA OR ABOVE USER AREA
;THE SECOND WORD OF CURRENT BUFFER WAS CHECKED AT UUO LEVEL
;OR PREVIOUS CALL TO ADVBFE

INTERNAL ADVBE1,ADVBFE
EXTERNAL XJBPFI,CPOPJ

ADVBFE:	MOVEI TAC1,@DEVOAD(DEVDAT)	;ABS. ADR. OF 2ND WORD OF LAST BUF.
	JUMPE TAC1,CPOPJ	;HAS DEVOAD BEEN CLEARED BY RELEASE?
	MOVEM IOS,-1(TAC1)	;NO. STORE IO STATUS WORD(ERROR BITS)
				; IN FIRST WORD OF BUFFER
	MOVSI TAC,IOUSE		;IOUSE:=0
	ANDCAB TAC,(TAC1)	;CLEAR USE BIT IN 2ND WORD
				; ADRESS CHECKED WHEN STORED IN DEVOAD
				; DEVICE ACTIVE SINCE THEN
	HRLZ TAC,TAC		;NEXT BUFFER ADR. TO LH
	CAMLE TAC,XJBPFI	;IS IT IN IO PROTECTED PART OF JOB DATA AREA?
	CAML TAC,PROG		;NO, IS IT GREATER OR EQUAL TO LAST WORD IN USER AREA?
	POPJ PDP,		;YES, DO NOT STORE NEXT ADDRESS
				; CATCH ERROR LATER AT UUO LEVEL
	HLRM TAC,DEVOAD(DEVDAT)	;NOW SAFELY STORE NEXT BUFFER ADRESS

;ENTER HERE FROM SCNSER TO CHECK IF NEXT BUFFER FULL OF DATA YET

ADVBE1:	SKIPL @DEVOAD(DEVDAT)	;IS IOUSE=0?
	POPJ PDP,		;EXIT1. BUFFER IS EMPTY
	JRST ADVBF1	;GO SEE IF USER TYPED CONTROL C
				; OR EXEC IS WAITING TO SHUFFLE JOB
;ROUTINE TO ADVANCE INPUT BUFFER AT INTERRUPT LEVEL

;CALL:	PUSHJ PDP,DEVBFF
,	EXIT1		RETURN IF NEXT BUFFER IS FULL
,	EXIT2		RETURN IF NEXT BUFFER IS EMPTY
,SETS THE USE BIT (IOUSE:=1) OF THE BUFFER POINTED TO BY THE
,INPUT BUFFER ADDRESS (DEVIAD) OF THE CURRENT DEVICE DATA BLOCK
,AND ADVANCES THE BUFFER ADDRESS TO THE NEXT BUFFER IN THE RING.
,UPON RETURN, SKIPS IF THE NEXT BUFFER IS EMPTY.
;SECOND WORD OF NEXT BUFFER IS ADDRESS CHECKED TO MAKE SURE
;IT IS NOT IN IO PROTECTED PART OF JOB DATA AREA OR ABOVE
;USER AREA
;ALSO END OF BUFFER IS CHECKED TO MAKE SURE NOT ABOVE JOB AREA

INTERNAL ADVBFF
EXTERNAL XJBPFI,PJOBN,JBTSTS,CPOPJ

ADVBFF:	MOVEI TAC1,@DEVIAD(DEVDAT)	; ABS. ADR. OF LAST INPUT BUFFER
	JUMPE TAC1,CPOPJ	;HAS DEVIAD BEEN CLEARED BY RELEASE?
	MOVEM IOS,-1(TAC1)	;NO. STORE IOS WORD IN FIRST WORD OF BUF.
	MOVSI TAC,IOUSE		;IOUSE:=1
	IORB TAC,(TAC1)		;FLAG THAT DATA HAS BEEN INPUT
	HRLZ TAC,TAC		;NEXT BUFFER TO LEFT HALF
	CAMLE TAC,XJBPFI	;IS ADR. IN PROT. PART OF JOB DATA AREA?
	CAML TAC,PROG		;NO, WILL SECOND AND THIRD WORD FIT?
	POPJ PDP,		;NO, GIVE ERROR RETURN SO DEVICE WILL STOP
	HLRM TAC,DEVIAD(DEVDAT)	;YES, SAFELY STORE ADDRESS OF NEXT BUFFER
	SKIPGE TAC1,@DEVIAD(DEVDAT)	;IS NEXT INPUT BUFFER STILL FULL?
	POPJ PDP,		;YES, GIVE STOP RETURN
	TRZ TAC1,-1		;XWD LENGTH OF BUFFER,0
	ADD TAC,TAC1		;ADD LENGTH TO REL. ADR. OF SECOND WORD
				; LENGTH=NO. WORDS WHICH FOLLOW SECOND
	CAMLE TAC,PROG		;IS LAST WORD IN BOUNDS?
	POPJ PDP,		;NO, GIVE STOP RETURN
ADVBF1:	LDB TAC,PJOBN		;GET JOB NO. FROM DEVICE DATA BLOCK
	SKIPGE TAC,JBTSTS(TAC)	;IS RUN BIT ON IN JOB STATUS WORD
	TLNE TAC,SHF+CMWB	;YES, SYSTEM WAITING TO SHUFFLE,
				; EXECUTE A COMMAND, OR TO SWAP JOB OUT?
				; SHF SET BY SWAPPER TO STOP IO IF IT WANTS TO SWAP JOB OUT
				; 2 RELOC REG SOFTWARE DOES NOT SET SHF IN LOW SEG
				; IF JOB HAS 2 SEG, SINCE HIGH SEG CAN BE
				; SWAPPED EVEN THOUGH ACTIVE IO IN LOW SEG.
				; THUS A LIMITED FORM OF MONITOR BUFFERING IS ACHIEVED
	POPJ PDP,		;YES,PRETEND NEXT BUFFER NOT AVAILABLE
	TRNN IOS,IOCON		;NEXT BUFFER AVAILABLE. DISCONTINUOUS MODE?
	AOS (PDP)		;NO
	POPJ PDP,		;YES
;ROUTINE TO ADDRESS CHECK AT UUO LEVEL ONLY
;CALL	HRRZ AC1,REL ADR.
;	PUSHJ PDP,UADCK1
;	NEVER RETURNS IF ERROR,STOPS JOB AND PRINTS ERROR
;BAD ADR. IF IN LOC 20-JOBPFI IN JOB DATA AREA
;OR IF ABOVE PROTECTION(USRREL) FOR CURRENT JOB

INTERNAL UADCK1
EXTERNAL USRREL,JOBPFI

UADCK1:	TRNN AC1,777760		;IN USER ACS?
	POPJ PDP,		;YES, ADDRESS IS OK

;ROUTINE TO ADDRESS CHECK AT UUO LEVEL ONLY
;USER ACS ARE ALSO ILLEGAL(ADR IS FOR IO USE LATER AT
;INTERRUPT LEVEL)
;CALL:	HRRZ AC1,REL.ADR.
;	PUSHJ PDP,UADRCK
;	NEVER RETURN IF ERROR

INTERNAL UADRCK
EXTERNAL USRREL,JOBPFI

UADRCK:	CAILE AC1,JOBPFI	;IS ADR. IN IO PROT. PART OF JOB DATA AREA?
	CAMLE AC1,USRREL	;NO, IS IT ABOVE PROTECT.?
	JRST ADRERR		;YES, STOP JOB AND PRINT ERROR
	POPJ PDP,		;NO

;ROUTINE TO ADDRESS CHECK AT ANY LEVEL
;CALL:	MOVE PROG,[XWD PROT.,RELOC,]
;	HRRZ TAC,REL. ADR.
;	PUSHJ PDP,IADRCK
;	ERROR RETURN(ERROR MESSAGE NOT PRINTED,JOB NOT STOPPED)
;	OK RETURN

INTERNAL IADRCK
EXTERNAL JOBPFI,CPOPJ1

IADRCK:	MOVS TAC1,PROG		;GET PROTECTION(TO RH)
	CAILE TAC,JOBPFI	;ADR. ABOVE PROT. PART OF JOB DATA AREA?
	CAILE TAC,(TAC1)	;YES, BELOW OR EQUAL TO PROTECT.?
	POPJ PDP,		;NO
	JRST CPOPJ1		;YES, SKIP RETURN
;ROUTINE TO CHECK VALIDITY OF A DUMP MODE COMMAND LIST
;WHICH IS:
;A LIST OF 0 OR MORE IOWD FORMAT WORDS
; TERMINATED BY A GOTO WORD(LH=0)
; WHICH POINTS TO ANOTHER LIST OF 0 OR MORE IOWD FORMAT WORDS ETC.
; UNTIL A GOTO WORD IS ENTIRELY ZERO
;
;SINCE MONITOR DOES NOT RESCHEDULE WHEN IN EXEC MODE
;A MAXIMUM LIST OF 100 IS IMPOSED

;CALL:	MOVE UUO,[XWD PROG,REL. ADR. OF FIRST COMMAND]
;	PUSHJ PDP,COMCHK
;	ADDRESS CHECK RETURN(ERROR ROUTINE IS NOT CALLED)
;	OK RETURN, SUM OF LH OF IOWDS IN DAT
;	USER ADDRESS OF FIRST IOWD LH PROG IN INDEX FIELD IN UUO
;

INTERNAL COMCHK
EXTERNAL JOBPFI,USRREL,TPOPJ1,USRHCU

COMCHK:	PUSH PDP,UUO		;SAVE POINTER TO LIST
	PUSH PDP,AC2
	MOVEI AC1,JOBPFI	;HIGHEST IO PROTECTED LOC. IN JOB DATA AREA
	SKIPGE USRHCU		;IS A SAVE OR GET IN PROGRESS(MAYBE RUN UUO)
	MOVEI AC1,JOBSAV	;YES, HIGHEST LOC. NOT WRITTEN BY SAVE
	SETZB DAT,AC2		;CLEAR WORD COUNT AND ADDRESS OF FIRST IOWD
	MOVEI ITEM,100		;ONLY 100 LISTS
	SKIPA TAC1,UUO		;CHECK THE START OF LIST.
COMCK0:	HRR UUO,TAC1		;CHANGE COMMAND LIST POINTER ON GO TO WORD
	HRRZ TAC,TAC1		;SET UP TAC FOR IADRCK
	TRNN TAC,777760		;IS LIST IN THE ACS?
	JRST COMCK1		;YES. THAT'S OK.
	PUSHJ	PDP,IADRCK
	JRST	COMCKE		;BAD ADDR.
COMCK1:	SOJLE ITEM,COMCKE	;EXCEEDED 100 YET?
	SKIPN TAC1,@UUO		;NO. GET NEXT IOWD. END OF LIST?
	JRST COMCK2		;YES
	JUMPG TAC1,COMCK0	;NO. IS IT A GO TO WORD?
	HLRE TAC,TAC1		;NO. SAVE NEGATIVE WORD COUNT
	HRRZS TAC1		;GET LOWEST ADDRESS-1
	CAMGE TAC1,AC1		;IS IT GREATER THAN LOC. PROTECTED
				; FROM IO IN JOB DATA AREA?
	JRST COMCKE		;NO. ERROR RETURN
	SUB TAC1,TAC		;YES. COMPUTE LAST LOC.
	CAMLE TAC1,USRREL	;IS LAST LOC. IN BOUNDS?
	JRST COMCKE		;NO. ERROR RETURN
	SUB DAT,TAC		;YES. ACCUMULATE NEG. WORD COUNT
	SKIPN AC2		;IS THIS THE FIRST IOWD?
	MOVE AC2,UUO		;YES. SAVE ADDRESS IN AC2
	AOJA UUO,COMCK1		;GO GET NEXT IOWD
COMCK2:	SKIPE AC2		;ARE THERE ANY IOWDS WITH LH NOT 0?
	MOVE UUO,AC2		;YES, POINT UUO TO FIRST SUCH IOWD.
	POP PDP,AC2
	JRST TPOPJ1		;REMOVE SAVED UUO AND SKIP RETURN


COMCKE:	POP PDP,AC2
	POP PDP,UUO		;RESTORE ORIGINAL UUO
	POPJ PDP,		;ERROR RETURN
INTERNAL ASSASG,FTDISK
EXTERNAL SCNON,SCNOFF,PJOBN

;ASSIGN DEVICE IF UNASSIGNED
;CALL:	MOVE ITEM, JOB NUMBER
;	MOVE DEVDAT, ADDR. OF DDB
;	MOVEI TAC1, EITHER ASSPRG OR ASSCON
;	PUSHJ PDP, ASSASG
;	CAN'T ASSIGN RETURN
;	ASSIGNED RETURN


ASSASG:	IFN FTDISK,<EXTERNAL SETDDB
		MOVE TAC,DEVMOD(DEVDAT)	;IS IT A DISK?
	TLNE TAC,DVDSK
	PUSHJ PDP,SETDDB	;YES, BUILD DEVICE DATA BLOCK
>
	NOSCHEDULE		;DISABLE SCHEDULING
	LDB TAC,PJOBN		;GET JOB NUMBER IN DEV DATA BLOCK
	CAMN TAC,ITEM		;IS IT ALREADY ASSIGNED TO THIS JOB
	JRST ASSAS1		;YES
	MOVEI TAC, ASSPRG+ASSCON	;NO, IS IT ASSIGNED TO ANOTHER JOB?
	CONO PI,SCNOFF		;TURN SCANNER OFF
	TDNE TAC, DEVMOD(DEVDAT)	;ARE EITHER ASSIGNED BITS SET?
	JRST ASSAS2		;YES
	DPB ITEM,PJOBN		;NO, STORE JOB NUMBER
ASSAS1:	IORM TAC1,DEVMOD(DEVDAT)	;SET ONE OF ASSIGN BITS
	AOS (PDP)
ASSAS2:	CONO PI,SCNON		;TURN SCANNER CHAN. BACK ON
	SCHEDULE		;SCHEDULING
	POPJ PDP,
;ROUTINE TO SEARCH FOR A DEVICE
;CALL:	HRR ITEM,JOB NUMBER
;	MOVE TAC,[SIXBIT .DEVICE NAME.]
;	PUSHJ PDP, DEVSRC
;	NOT FOUND
;	FOUND

	INTERNAL DEVLG,DEVSRC,DEVPHY
	EXTERNAL SYSTAP,DEVOPR,TTYFND,CPOPJ1,DEVLST,PJOBN,GETDDB

DEVSRC:
IFN FTLOGIN,<
	MOVSI	DEVDAT,JLOG	;DO NOT ALLOW LOGICAL NAMES IF THE JOB IS NOT
				; NOT LOGGED IN OR IS IN THE PROCESS OF BEING LOGGED OUT
	TDNE DEVDAT,JBTSTS(ITEM)	;OTHERWISE USER CAN RUN OWN LOGOUT PROGRAM
				; JLOG SET TO 0 IN COMMAND DECODER ON KJOB
>
	PUSHJ PDP, DEVLG	;SEARCH LOGICAL NAMES FIRST
	JRST DEVPHY		;NOT FOUND, SEARCH PHYSICAL NAMES
	JRST CPOPJ1		;FOUND

;SEARCH LOGICAL NAMES

DEVLG:	HLRZ DEVDAT,DEVLST	;BEGINNING OF DDB CHAIN
DEVLP0:	CAME TAC,DEVLOG(DEVDAT)	;COMAPRE WITH LOGICAL NAME
	JRST DEV0		;NO MATCH
	LDB TAC1,PJOBN		;DOES THE LOGICAL NAME BELONG TO THIS JOB?
	CAMN TAC1,ITEM
	JUMPN TAC,CPOPJ1	;YES, GIVE SUCCESSFUL RET. IF NAME NOT 0
DEV0:	HLRZ DEVDAT,DEVSER(DEVDAT)	;NO, KEEP LOOKING
	JUMPN DEVDAT,DEVLP0
	POPJ PDP,		;FINISHED AND NOT FOUND
;SEARCH PHYSICAL NAMES

DEVPHY:	CAMN TAC,[SIXBIT /OPR/]	;IS IT "OPR"?
	MOVE TAC,DEVOPR		;YES, CHANGE TO OPERATOR'S TTY
	CAMN TAC,[SIXBIT /SYS/]	;IS IT "SYS"?
	SKIPA TAC,SYSTAP	;YES, CHANGE TO SYSTEM TAPE DEVICE NAME
	TDZA TAC1,TAC1		;NO, CLEAR SYSTEM TAPE FLAG
	MOVEI TAC1,SYSDEV	;YES, SET SYSTEM TAPE FLAG
	HLRZ DEVDAT,DEVLST	;SEARCH DEVICE DATA BLOCKS
DEVLP1:
	TLO DEVDAT,(TAC1)	;SET SYSTEM TAPE BIT IF SEARCHING FOR SYS
	CAMN TAC,DEVNAM(DEVDAT)	;MATCH OF PHYSICAL NAME?
	JUMPN TAC,CPOPJ1	;YES, GIVE OK RET. IF NAME IS NOT 0
	HLRZ DEVDAT,DEVSER(DEVDAT)
	JUMPN DEVDAT,DEVLP1
	CAME TAC,[SIXBIT /TTY/]	;IS THIS PUBLIC LOGICAL NAME TTY?
	JRST	GETDDB		;SEE IF IT'S A TTY.
	PUSH PDP,DAT		;SAVE OUTPUT BYTE POINTER(TTY) OR INIT. ARG. ADR.
	PUSHJ PDP,TTYFND	;YES, FIND TTY JOB IS ATTACHED TO
	POP PDP,DAT		;RESTORE
	JRST CPOPJ1		;AND GIVE SUCCESSFUL RETURN
;ROUTINE TO SETUP N-RING IO BUFFER IN USER AREA

;CALL:	PUSHJ PDP,BUFCLC
,	EXIT		RETURNS HERE IF MEMORY NOT EXCEEDED
, SETS UP AN N BUFFER RING FOLLOWING THE USER'S PROGRAM, WHERE N
, IS IN THE ADDRESS FIELD OF AC UUO.
, THE BUFFER RING FORMAT IS AS FOLLOWS:
,	LOCATION		LH   CONTENTS   RH
, C(JOBFF) + 1              BUFFER         C(JOBFF) +1
,    + 0(BUFFER SIZE+2)      SIZE               + 1(BUFFER SIZE+2)
, C(JOBFF) +1               BUFFER         C(JOBFF) +1
,     +1(BUFFER SIZE+2)      SIZE                + 2(BUFFER SIZE+2)
,         .		.		     .
,	.		.		     .
,	.		.		     .
, C(JOBFF) + 1	        BUFFER	   C(JOBFF) + 1
,    + (N-2)(BUFFER SIZE+2)  SIZE               +(N-1)(BUFFER SIZE+2)
, C(JOBFF) + 1	        BUFFER	   C(JOBFF) + 1
,    + (N-1)(BUFFER SIZE+2)  SIZE		   
,THEN SET 	BUFPNT:=IOUSE,C(JOBFF) + 1
, AND		JOBFF:=C(JOBFF) + N(BUFFER SIZE + 2)
, BUFWRD IS RESTORED.
	INTERNAL BUFCLC
	EXTERNAL JOBFF

BUFCLC:	PUSH PDP,BUFWRD		;SAVE BUFWRD ON STACK
	LDB TAC,[POINT 12,DEVCHR(DEVDAT),35];TAC:=BUFFER SIZE
	HRRZ BUFPNT,JOBFF(PROG)	;BUFPNT:=FIRST FREE LOCATION + 1
	ADDI BUFPNT,1
	HRRZ BUFWRD,BUFPNT
	HRLI BUFPNT,PROG
	HRL BUFWRD,TAC		;BUFWRD:=BUFFER SIZE,FIRST FREE LOC + 1
	ADDI TAC,2		;TAC:=BUFFER SIZE + 2
	HRRZ TAC1,UUO		;TAC1:=N=ADDRESS FIELD OF AC UUO
	HRRZ AC1,TAC		;BUFFER SIZE+2
	IMUL AC1,TAC1		;TIME NO. OF BUFFERS
	ADD AC1,BUFWRD		;LOC. OF FIRST BUFFER
	HRRZ AC1,AC1		;MAKE SURE POSITIVE
	CAMG AC1,USRREL		;WILL THIS SPACE FIR IN USER CORE?
	JRST BUFC1		;YES, FO DO INBUF CODE
				; NO, AUTOMATICALLY EXPAND SIZE OF USER CORE
	PUSH PDP,TAC		;SAVE A BUNCH OF ACS USED IN CORE AND IO WAIT
	PUSH PDP,UUO
	PUSH PDP,TAC1
	PUSH PDP,BUFPNT
	PUSH PDP,BUFWRD
	PUSH PDP,DEVDAT
	PUSH PDP,DSER
	MOVE ITEM,JOB		;CURRENT JOB NUMBER
	MOVE TAC,AC1		;HIGHEST USER ADR. TO TRY FOR
	MOVEI UUO,UUO		;SET INDEX FIELD TO 0, SO STOTAC WILL STORE
				; NO. OF K CORE AVAILABLE IN EXEC AC UUO INSTEAD
				; OF USER'S AC UUO
	PUSHJ PDP,CORUUO	;TRY TO ASSIGN CORE
	JFCL			;ERROR RETURN-LET ADR CHECK HAPPEN AND STOP JOB
	POP PDP,DSER
	POP PDP,DEVDAT
	POP PDP,BUFWRD
	POP PDP,BUFPNT
	POP PDP,TAC1
	POP PDP,UUO
	POP PDP,TAC
BUFC1:	ADD BUFWRD,TAC		;BUFWRD:=C(BUFWRD) + C(TAC)
	HRRZ AC1,BUFPNT		;IS LAST ADDR IN BOUNDS?
	PUSHJ PDP,UADRCK
	MOVEM BUFWRD,@BUFPNT	;BUFFER HEADER+1:=C(BUFWRD)
	HRR BUFPNT,BUFWRD	;BUFPNT 18-35:=C(BUFWRD 18-35)
	SOJG TAC1,BUFC1		;N:=N-1.  IS N GR 0?
	HRR BUFWRD,JOBFF(PROG)
	ADDI BUFWRD,1
	MOVEI AC1,-2(BUFPNT)	;CHECK LAST ADR. OF HEADER
	PUSHJ PDP,UADRCK
	SUB BUFPNT,TAC
	MOVEM BUFWRD,@BUFPNT	;LINK LAST BUFFER TO FIRST BUFFER
	ADDI BUFPNT,-1(TAC)
	HRRM BUFPNT,JOBFF(PROG)	;JOBFF:=C(JOBFF)+1+N(BUFFER SIZE+2)
	HRR BUFPNT,BUFWRD	;BUFPNT:=IOUSE,ADDRESS OF FIRST BUFFER
				; IN RING.
	HRLI BUFPNT,IOUSE
	POP PDP,BUFWRD		;RESTORE BUFWRD FROM STACK.
	POPJ PDP,		;RETURN
;ROUTINE TO CLEAR IO BUFFER IN USER AREA
;CALLED AT INTERRUPT AND UUO LEVEL

;CALL:	HRRZ TAC,REL. ADR. OF 2ND WORD OF USER BUFFER
;	PUSHJ PDP,BUFCLR
;	ERROR RETURN MEMORY EXCEEDED
,	EXIT		RETURNS HERE IF MEMORY NOT EXCEEDED
, CLEARS THE WORD COUNT AND DATA AREA OF THE BUFFER WHOSE ADDRESS
, IS IN TAC 18-35.

	INTERNAL BUFCLR
	EXTERNAL TPOPJ,CPOPJ1

BUFCLR:	PUSHJ PDP,IADRCK	;IN BOUNDS?
	POPJ PDP,		;NO. ERROR RETURN
	HRLI TAC,PROG
	PUSH PDP,TAC		;SAVE FIRST BUFFER ADR.
	HLRZ TAC1,@TAC		;TAC1 18-35=SIZE
	TRZ TAC1,400000
	ADD TAC,TAC1		;LAST ADR=2ND ADR+SIZE
	TLZ TAC,-1		;CLEAR LEFT HALF
	PUSHJ PDP,IADRCK	;LAST ADDRESS IN BOUNDS?
	JRST TPOPJ		;NO. ERROR RETURN
	HRLI TAC,PROG		;SET LAST ADR. FOR RELOC.
	POP PDP,TAC1		;RESTORE FIRST ADR.
	NOSHUFF			;NO SHUFFLING
	MOVEI TAC1,@TAC1	;ABS. ADR. OF 2ND WORD OF BUFFER
	HRL TAC1,TAC1
	AOBJN TAC1,.+1		;THIRD WORD IN BUFFER
	SETZM (TAC1)		;CLEAR THIRD WORD
	AOS TAC1		;SET DEST. ADR. TO 4TH WORD
	BLT TAC1,@TAC		;CLEAR BUFFER
	SHUFFLE			;SHUFFLING
	JRST CPOPJ1		;SUCESSFUL RETURN
;ROUTINE TO COMPUTE 12 BIT FOLDED CHECKSUM

;CALL:	PUSHJ PDP,CKS12
,	EXIT		ALWAYS RETURNS HERE
,CALCULATES FOLDED 12 BIT CHECKSUMS OF THE DATA WORDS IN THE
,BUFFER WHOSE ADDRESS IS IN AC TAC1.  TWO ALGORITHMS ARE USED.
,ON RETURN, THE LEFT HALF OF AC TAC CONTAINS A CHECKSUM OBTAINED
,BY ACCUMULATING, IN ONE'S COMPLEMENT, THE DATA WORDS AND FOLDING IT.
,THE LEFT HALF OF AC DAT CONTAINS A CHECKSUM OBTAINED BY ACCUMULATING,
,IN TWO'S COMPLEMENT, THE DATA WORDS AND FOLDING IT.  AC TAC1
,CONTAINS A 1.

	INTERN CKS12

CKS12:	ADD TAC1,PROG		;TAC1:=-WORD COUNT,ADDRESS OF FIRST DATA WORD
	AOS TAC1
	HRRZ TAC,0(TAC1)
	MOVNS TAC
	AOS TAC1
	HRL TAC1,TAC
	CLEARM TAC		;INITIALIZE TWO'S COMPLEMENT SUM
CKS12A:	ADD TAC,0(TAC1)		;TWO'S COMPLEMENT ADD
	AOBJN TAC1,CKS12A	;DONE?
	LSHC TAC,-30
	LSH TAC1,-14
	ADD TAC,TAC1
	LSHC TAC,-14
	LSH TAC1,-30
	ADD TAC,TAC1
	TRZE TAC,770000
	AOS TAC
	HRLZS TAC
	MOVEI TAC1,1		;TAC1:=1
	POPJ PDP,
;ROUTINE TO CLEAR RESIDUE OF WORD POINTED TO BY A BYTE POINTER

;CALL:	PUSHJ PDP,CLRBYT
,	EXIT		ALWAYS RETURNS HERE
,CALLED WITH A BYTE POINTER IN AC TAC, IT CLEARS THE REST OF THE
,WORD POINTED TO BY THE BYTE POINTER.

	INTERNAL CLRBYT

CLRBYT:	LDB TAC1,[POINT 6,TAC,5]	;TAC1:=P
	DPB TAC1,[POINT 12,TAC,11]	;TAC 0-5:=0,TAC 6-12:=P
	SETZM TAC1
	DPB TAC1,TAC		;CLEAR BITS 36-P THROUGH 35
	POPJ PDP,		;RETURN

;ROUTINE TO PUT EVEN PARITY IN ( OR TAKE IT OUT OF ) BIT 28 OF
;AC TEM. ASSUMING CHARACTER IS IN BITS 28-35 OF TEM, REST CLEAR.
;TAC IS DESTROYED. CALLED FROM PTP AND TTY SERVICE ROUTINES

;CALL:	PUSHJ	PDP,PEVEN8
;	EXIT HERE WITH TEM SET TO EVEN PARITY

	INTERNAL PEVEN8

PEVEN8:	MOVE	TAC,TEM		;COPY ORIGINAL CHARACTER
	IMULI	TAC,200401	;MAKE THREE COPIES OF THE CHAR
	AND	TAC,[OCT 11111111]	;GET THE BITS INDIVIDUALLY
	IMUL	TAC,[OCT 11111111]	;ADD UP THE BITS
	TLNE	TAC,10		;TEST THE PARITY OF THE SUM
	TRC	TEM,200		;IT WAS ODD. MAKE IT EVEN.
	POPJ	PDP,0		;RETURN
;ROUTINE TO RELEASE ALL DEVICES ASSIGNED TO JOB

INTERNAL IORELS
EXTERNAL PUUOAC


IORELS:	MOVEI TAC,RELEA3	;RELEASE ALL IO DEVICES(DON'T CLOSE)

;ROUTINE TO DO IO FOR ALL DEVICES ASSIGNED TO JOB
;CALL	MOVEI TAC,ADR. OF IO SUB.
;	PUSHJ PDP,IOALL
;	RETURNS WITH ITEM=CURRENT JOB # ,UUO PRESERVED

INTERNAL IOALL
EXTERNAL TPOPJ,USRHCU,USRJDA

IOALL:	PUSH PDP,TAC		;SAVE ADR. OF SUB.
	PUSH PDP,UUO		;SAVE UUO
	SETZB UCHN,UUO		;START WITH USER CHANNEL 0
IOALL1:	CAMLE UCHN,USRHCU	;IS IT GREATER THAN HIGHEST CHAN. USED?
	JUMPN UCHN,IOALL2	;YES - RETURN
				; IF USRCHU IS NEG - ASSUME SAVGET
				; WHICH USES CHANNEL 0
	SKIPN DEVDAT,USRJDA(UCHN)	;GET NEXT DDB ADR., IS IT IN USE?
	AOJA UCHN,IOALL1	;NO, KEEP GOING
	MOVE IOS,DEVIOS(DEVDAT)
	DPB UCHN,PUUOAC
	MOVE DSER,DEVSER(DEVDAT)	;SETUP ADR. OF DEV. DISP. TABLE
	LDB TAC,PJOBN		;GET JOB NUMBER WHICH JOB IS ASSIGNED TO
	CAMN TAC,JOB		;IS IT SAME AS CURRENT JOB(SHOULD BE EXCEPT FOR 140
				; RESTART WHILE THIS JOB WAS SWAPPED OUT)
				; DEVICE DATA BLOCKS JOB NUMBERS ARE SET TO 0 ON
				; 140 RESTART,BUT THE JOB DATA AREA DEVICE ASSIGNMENTS
				; FOR SWAPPED OUT JOBS HAVE NOT
	PUSHJ PDP,@-1(PDP)	;YES,CALL THE SUB.
	AOJA UCHN,IOALL1	;INCREMENT USER CHAN. NO.
IOALL2:	POP PDP,UUO		;RESTORE UUO & RETURN RESTORING TAC TOO
	MOVE ITEM,JOB		;GET JOB NO.
	JRST TPOPJ


;WAIT TILL ALL DEVICES ARE INACTIVE

INTERNAL IOWAIT

IOWAIT:	MOVEI TAC,WAIT1
	JRST IOALL
;KILL ALL DEVICES(RELEASE WITHOUT WAITING FOR DEVICE INACTIVE)

INTERNAL IOKILL

IOKILL:	MOVEI TAC,RELEA5
	PUSHJ PDP,IOALL		;RELEASE ALL DEVICES WITHOUT WAITING

;ROUTINE TO CLEAR PROTECTED JOB DATA AREA IN MONITOR
;AND RECLAIM FREE AREA ABOVE USER PROGRAM FOR IO BUFFERS
;CALL:	MOVE JDAT,ADR. OF CURRENT JOB DATA AREA
;	PUSHJ PDP,SETUSR

INTERNAL SETUSR,CLRUSR
EXTERNAL USRLO1,USRLO,USRHI,JOBSA,JOBFF
EXTERNAL JOBENB,USRHCU

SETUSR:	HLRZ TAC,JOBSA(JDAT)	;RESET FIRST FREE LOC. FOR THIS JOB
	MOVEM TAC,JOBFF(JDAT)
CLRUSR:	SETZM JOBENB(JDAT)	;INITIALIZE APR TRAPPING (I.E., NONE)
	MOVEI TAC,USRLO1	;FIRST LOC+1 TO CLEAR
	HRLI TAC,USRLO		;FIRST LOC.
	SETZM USRLO
	BLT TAC,USRHI
	SETZM USRHCU		;CLEAR HIGHEST USER IO CHAN. IN USE
	POPJ PDP,
;ROUTINE TO FLAG DEVICE ACTIVE
;CALL	MOVE IOS,IO STATUS BITS
;	MOVE DEVDAT,ADDRESS OF DEVICE DATA BLOCK
;	PUSHJ PDP,SETACT
;CALLED BY ALL IO SERVICE ROUTINES AT UUO AND INTERRUPT LEVELS

INTERNAL SETACT,CLRACT,STOIOS,ORACT
EXTERNAL PDVTIM,PDVCNT

ORACT:	TRO IOS,IOACT
	IORB IOS,DEVIOS(DEVDAT)
	JRST ORACT1
SETACT:	TRO IOS,IOACT
	TLZA	IOS,IOW
CLRACT:	TRZ IOS,IOACT
STOIOS:	MOVEM IOS,DEVIOS(DEVDAT)
ORACT1:	LDB TAC,PDVTIM		;GET NO. OF SECONDS
	DPB TAC,PDVCNT		;TO WAIT BEFORE
	POPJ PDP,		;DEVICE IS CONSIDERED HUNG

INTERNAL DEVCHK
EXTERNAL HNGTIM,HNGSEC,DEVLST

DEVCHK:	MOVEI TAC,HNGSEC	;RESET HUNG DEVICE CHECK TIME
	MOVEM TAC,HNGTIM	;TO CHECK ONCE A SECOND
	HLRZ DEVDAT,DEVLST
DEVCK0:	MOVE IOS,DEVIOS(DEVDAT)	;IS DEVICE ACTIVE?
	TRNN IOS,IOACT
	JRST DEVCK1		;NO
	LDB TAC,PDVCNT		;YES,DECREMENT
	SOJL TAC,DEVCK1		;0 MEANS IGNORE DEVICE
	DPB TAC,PDVCNT
	JUMPN TAC,DEVCK1	;HAS COUNT GONE TO 0?
	MOVE DSER,DEVSER(DEVDAT);YES, GET DISPATCH TABLE ENTRY
	PUSH PDP,DEVDAT
	PUSHJ PDP,DHNG(DSER)	;DISPATCH TO SERVICE ROUTINES TO 
				; UNHANG DEVICE
	PUSHJ PDP,DEVHNG	;PRINT ERROR MESSAGE AND STOP JOB
	POP PDP,DEVDAT		;DO NOT PRINT MESS. AND STOP JOB RETURN
DEVCK1:	HLRZ DEVDAT,DEVSER(DEVDAT)
	JUMPN DEVDAT,DEVCK0
	POPJ PDP,
;ROUTINE TO SETUP PROG AND ITEM FOR INTERRUPT SERVICE ROUTINE

;CALL	PUSHJ PDP,IOSET
,	EXIT	ALWAYS RETURNS HERE
,THIS PROGRAM IS CALLED FROM AN INTERRUPT SERVICE ROUTINE.
,IT PUTS THE ADDRESS OF THE DATA AREA OF THE JOB (C(JBTADR18-35))
,CONNECTED TO THE DEVICE SPECIFIED BY AC DEVDAT IN AC PROG AND
,PUTS THE ITEM POINTER (C(DEVCTR)) IN AC ITEM.

	INTERNAL IOSET
	EXTERNAL PJOBN,JBTADR

IOSET:	LDB PROG,PJOBN
	MOVE ITEM,DEVCTR(DEVDAT)	;ITEM:=ITEM POINTER=C(DEVCTR)
	MOVE PROG,JBTADR(PROG)	;PROG:=C(JBTADR 18-35)
	MOVE IOS,DEVIOS(DEVDAT)	;GET IO STATUS FROM THE DDB
	POPJ PDP,		;RETURN

,CALLING SEQUENCE
,	PUSHJ PDP,IOSETC
,	EXIT		ALWAYS RETURNS HERE

,SETS JBFPTR18-35:=C(TAC1 18-35)
,	JBFCTR:=C(ITEM)*[WORD LENGTH/BYTE SIZE]
,WHERE	WORD LENGTH:=36 DECIMAL
,	BYTE SIZE:=C(JBFPTR6-11)
,	[X]:= INTEGER PART OF X


	INTERN IOSETC


IOSETC:	ADDI JBUF,1		;JBFPTR12-18:=0
	HRLZI TAC,7777		;JBFPTR18-35:=C(TAC1 18-35)+1
	ANDM TAC,@JBUF
	HRRM TAC1,@JBUF
	AOS @JBUF
	LDB TAC1,[POINT 6,@JBUF,11]	;TAC1:=BYTE SIZE
	PUSHJ PDP,ITMCT1	;JBFCTR:=C(ITEM)*[36/BYTE SIZE]
	ADDI JBUF,1
	MOVEM ITEM,@JBUF
	POPJ PDP,		;EXIT
;ROUTINE TO RETURN NO. OF ITEMS IN BUFFER

;CALL:	PUSHJ PDP,ITMSET
,	EXIT		ALWAYS RETURNS HERE
,SETS AC ITEM:=(BUFFER SIZE-1)*[WORD LENGTH/BYTE SIZE]
,WHERE BUFFER SIZE:=BITS 1-17 OF THE BUFFER HEADER WORD POINTED TO
,		BY C(DEVADR)
,	WORD LENGTH:=36 DECIMAL
,	BYTE SIZE:=INTEGER PART OF X.

,CALLING SEQUENCE
,	PUSHJ PDP,ITMCNT
,	EXIT		ALWAYS RETURNS HERE
,SETS AC ITEM:=C(ITEM)*[WORD LENGHT/BYTE SIZE]

,CALLING SEQUENCE
,	PUSHJ PDP,ITMCT1
,	EXIT		ALWAYS RETURNS HERE
,SETS AC ITEM:=C(ITEM)*[WORD LENGHT/C(TAC1)]

	INTERN ITMSET,ITMCNT,ITMCT1
ITMSET:	LDB ITEM,[POINT 17,@DEVADR(DEVDAT),17];ITEM:=BUFFER SIZE-1
	SUBI ITEM,1
ITMCNT:	LDB TAC1,[POINT 6,DEVPTR(DEVDAT),11];TAC1:=BYTE SIZE
ITMCT1:	MOVEI TAC,44		;ITEM:=C(ITEM)*[WORD LENGTH/C(TAC1)]
	IDIV TAC,TAC1
	IMUL ITEM,TAC
	POPJ PDP,
;ROUTINE TO SET DEVICE STATUS WORD FROM UUO
;AND SETUP IOS

INTERNAL SETIOS

SETIOS:	PUSHJ	PDP,WAIT1	;WAIT FOR DEVICE (INCLUDING TTY
				; MONITOR COMMAND RESPONSE WHEN
				; USER INITS TTY)

	PUSHJ	PDP,CHKMOD	;CHECK FOR LEGAL MODE, IF NOT RIGHT DONT RETURN
	TRZ UUO,IOACT		;LET USER SET ALL BITS EXCEPT IOACT
	HRRM UUO,DEVIOS(DEVDAT)
	POPJ PDP,



;CHECK FOR A LEGAL MODE FOR DEVICE
CHKMOD:		LDB TAC1,[POINT 4,UUO,35]	;GET DEVICE DATA MODE
	MOVEI TAC,1		;AND CHECK FOR LEGALITY
	LSH TAC,(TAC1)
	TDNN TAC,DEVMOD(DEVDAT)
	JRST ILLMOD		;ILLEGAL MODE
	POPJ	PDP,		;OK


;SETUP BYTE POINTER AND ITEM COUNT
;CALL	PUSHJ PDP,NEWBUF
;	ADDRESS CHECK WHEN SETTING UP BUFFER
;	OK RETURN



EXTERNAL CPOPJ1
INTERNAL NEWBUF,NEWBF1

NEWBF1:
NEWBUF:	HRRZ TAC,DEVADR(DEVDAT)	;TAC:=INPUT BUFFER HEADER ADDRESS
	PUSHJ PDP,BUFCLR	;CLEAR INPUT BUFFER.
	POPJ PDP,		;ADDRESS CHECK
	HRLZI TAC,7737
	AND TAC,DEVPTR(DEVDAT)	;DEVPTR 0-5:=0, DEVPTR 12:=0
	HRR TAC,DEVADR(DEVDAT)	;DEVPTR 18-35:=C(DEVADR 18-35) + 1
	AOS TAC
	MOVEM TAC,DEVPTR(DEVDAT)
	PUSHJ PDP,ITMSET	;ITEM:=(BUFFER SIZE-1)*[36/BYTE SIZE]
	MOVEM ITEM,DEVCTR(DEVDAT)	;DEVCTR:=ITEM COUNT
	JRST CPOPJ1		;RETURN
;ROUTINE TO SETUP BYTE POINTER ACCORDING TO DATA MODE

;CALL:	PUSHJ PDP,SETBYT
,	EXIT		ALWAYS RETURNS HERE
,SETS	TAC 0-5:=0
,	TAC 6-11:=S
,	TAC 12-13:=0
,	TAC 14-17:=PROG
,WHERE S=36 IF DATA MODE (IOS 32-25) IS BINARY (B)
,	IMAGE (I), IMAGE BINARY (IB), OR DUMP (SD,D,DR)
,      S=7  IF DATA MODE IS 	ASCII PACKED (A)
,			ASCII LINE (AL)
,			ASCII SEQUENCED (AS)
,			ASCII SEQUENCED LINE (ASL)
,		OR	ALTERNATE MODE BREAK (AM)

	INTERN SETBYT

SETBYT:	TRNN IOS,14		;IS MODE LESS THAN 10?
	HRLI TAC,700+PROG	;YES,ASCII OR ASCII LINE
	TRNE IOS,14		;10 OR GREATER?
	HRLI TAC,4400+PROG	;YES, IMAGE,IMAGE BIN. OR BIN.
	POPJ PDP,
;ROUTINE TO STORE DATA IN IOBUFFER FOR INPUT CHAR. AT A TIME DEVICES

;CALL:	PUSHJ PDP,STODAT
,	EXIT1		CHECKSUM ERROR
,	EXIT2		BLOCK FULL OR BLOCK COMPLETE
,	EXIT3		DATA STORED CORRECTLY
,CALLED FROM AN INPUT SERVICE ROUTINE WITH A DATA ITEM IN AC DAT.
,STORES THE DATA ITEM IN THE BUFFER, CHECKING TO SEE IF IT WERE
,THE FIRST ITEM ON THE BUFFER AND SETTING UP THE POINTER AND
,WORD COUNT APPROPRIATELY CHECKING THE MODE TO SEE IF ANY SPECIAL
,PROCESSING NEED BE DONE. FOR EXAMPLE, THE TERMINATION
,OF A BUFFER ON CERTAIN CHARACTERS IN OTHER MODES, OR IF THE BUFFER
,IS FULL.  THERE ARE THREE RETURNS FROM THIS ROUTINE: THE FIRST
,RETURN OCCURS ON AN ERROR CONDITION, THE SECOND RETURN OCCURS
,ON A BLOCK FULL CONDITION OR BLOCK COMPLETE CONDITION, THE THIRD
,RETURN OCCURS ON THE DATA STORED CORRECTLY CONDITION.  THIS
,ROUTINE ALSO DOES SOME CHECKING ON INPUT OF BINARY RECORD,
,PAPER TAPE OR CARDS.
,CALLING SEQUENCE
,	PUSHJ PDP,STOSQD
,	XXXX		ALWAYS SKIPS 
,	EXIT		ALWAYS RETURNS HERE
,STORES THE WORD COUNT:=C(DEVPTR 18-35) -C(DEVIAD 18-35) - 1
,IN THE BUFFER.
	INTERN STODAT, STOSQD
	EXTERNAL PIOMOD,CPOPJ,CPOPJ1,CPOPJ2

STODAT:	TLNN IOS,IOFST		;IS THIS FIRST ITEM OF BUFFER?
	JRST STO0		;NO
	PUSHJ PDP,NEWBUF	;SET UP A NEW BUFFER. ITEM:=(BUFFER 
				; SIZE - 1)*[36/BYTE SIZE]
	POPJ PDP,
STO0:	LDB TAC1,PIOMOD		;DATA MODE
	CAIN TAC1,B		;MODE=BINARY?
	JRST STOBIN
	TLZ IOS,IOFST
STO1:	IDPB DAT,DEVPTR(DEVDAT)	;STORE DATA IN BUFFER.
	CAIE TAC1,A		;MODE=ASCII, IMAGE, OR BINARY?
	CAIN TAC1,I
	JRST STOAIB
	CAIE TAC1,IB		;IMAGE BINARY?
	CAIN TAC1,B		;CHECKSUM BINARY?
	JRST STOAIB		;YES
	ANDI	DAT,177		;NO, MUST BE ASCII LINE MODE.
	CAIG	 DAT,14		;LINE FEED,FORM FEED, OR VERTICAL TAB?
	CAIGE	DAT,12
	JRST .+2		;NO
	JRST STOSQF		;YES
	SOJGE ITEM,CPOPJ2	;ITEM:=C(ITEM)-1. IS C(ITEM) GR OR=0?
STOE1:	TRO IOS,IOBKTL	;IOBKTL:=1
	POPJ	PDP,
STOAIB:	SOJG ITEM,CPOPJ2;	ITEM:=C(ITEM)-1. IS C(ITEM) GR 0?
	CAIN TAC1,A		;MODE=ASCII?
	JRST STOSQF		;YES
	CAIN TAC1,B		;MODE=BINARY?
	JRST STOBND		;YES, COMPUTE CHECKSUM AND CHECK.
	PUSHJ PDP,ITMSET	;ITEM:=(BUFFER SIZE-1)*[36/BYTE SIZE]
				; - C(DEVCTR)
	SUB ITEM,DEVCTR(DEVDAT)
	MOVE TAC1,DEVIAD(DEVDAT)	;STORE ITEM COUNT
	ADDI ITEM,1		;IN FIRST WORD OF BUFFER
	AOJA TAC1,STOSQE
STOSQD:	TLZN IOS,IOFST		;FIRST CALL?
	JRST STOSQF		;NO
	PUSHJ PDP,NEWBUF	;YES, CLEAR BUFFER,SET ITEM COUNT
	POPJ PDP,		;ADDRESS CHECK
STOSQF:	MOVE TAC1,DEVIAD(DEVDAT)	;REL. ADR. OF BUFFER
	AOS TAC1
	HRRZ ITEM,DEVPTR(DEVDAT)	;ITEM:=C(DEVPTR 18-35) -
				; C(DEVIAD 18-35) -1
	SUBI ITEM,(TAC1)
STOSQE:	HRRM ITEM,@TAC1		;WORD COUNT TO FIRST WORD IN BUFFER
	JRST CPOPJ1		;EXIT2. BLOCK COMPLETE


STOBIN:	TLZN IOS,IOFST		;WILL THE NEXT ITEM BE THE FIRST ITEM
	JRST STO1		;OF A BUFFER?  IOFST:=0
	HRRZ TAC,DAT		;YES.
	CAMLE TAC,ITEM		;IS WORD COUNT LE (BUFFER SIZE-1)*
	JRST STOE1		; [36/BYTE SIZE]?
	MOVE ITEM,TAC		;ITEM:=WORD COUNT
	MOVEM DAT,@DEVPTR(DEVDAT)	;STORE WORD COUNT IN BUFFER
	JRST CPOPJ2		;EXIT3.  DATA STORED CORRECTLY.

STOBND:	HRRZ TAC1,DEVIAD(DEVDAT)
	PUSHJ PDP,CKS12		;COMPUTE CHECKSUM
	ADD TAC1, DEVIAD(DEVDAT)
	HLLZ TAC1,@TAC1		;DATA CHECKSUM=COMPUTED CHECKSUM?
	CAMN TAC,TAC1
	JRST CPOPJ1		;EXIT2. BLOCK COMPLETE
	TRO IOS,IODTER		;IODTER:=1
	POPJ PDP,		;EXIT1. CHECKSUM ERROR


	LIT
IFN FTCHECK,<INTERNAL CHKEND
	CHKEND=.
>

UUOEND:	END