Trailing-Edge
-
PDP-10 Archives
-
PCL_FOR_701
-
uuocon.mac
There are 20 other files named uuocon.mac in the archive. Click here to see a list.
TITLE UUOCON - UUO HANDLER AND UUO+IO ROUTINES - V1335
SUBTTL /CHW/TL/RCC/CMF/PH/GDR/DAL/EVS/TW/JMF/DRT/JBS 22 JUL 80
SEARCH F,S
$RELOC
$HIGH
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1973,1974,1975,1976,1977,1978,1979,1980 BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
XP VUUOCN,1335
;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::MOVE M,.UPMP+.UPMUO ;GET THE UUO INTO AC(M)
; (CHECK THIS BEFORE PUSHING ON STACK WHICH WOULD
; DESTROY VALUABLE INFO IN CRASH IF FROM EXEC MODE)
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
PUSH P,.UPMP+.UPMUP ;SAVE RETURN ON PUSH DOWN LIST
PUSHJ P,FNDPDS## ;FIND JOB'S PDB
IFN FTACCT,<
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,.UPMP+.UPCTA ;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
>
TRNE T3,UU.MSK ;CHECK ARGUMENTS FOR VALIDITY?
PUSHJ P,UUOCHK## ;YES (DONT ALLOW PAGE FAULT IN UUO PROCESSING)
MOVE T2,(P) ;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::
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,<
CAIE T1,NETDSP## ;IS IT A NETWORK DEVICE?
JRST UUONET ;NO, IGNORE
MOVEI T1,ASSCON!ASSPRG ;IS THE DDB ASSIGNED OR INITED
TDNN T1,DEVMOD(F) ;CHECK
PUSHJ P,ZAPNET## ;NO, REMOVE THE DDB
UUONET:
> ;END 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,.UPMP+.UPMUO ;OR INTO 40 SO UUO WATCHERS SEE IT
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 <FTKI10!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
IFN FTCCIN,<
SKIPGE T4,.JDAT+JOBFDV## ;GET NEW PC
JRST USRXJI ;NO--GO DO .JBINT
>
IFE FTCCIN,<
MOVE T4,.JDAT+JOBFDV## ;GET NEW PC
>
MOVEM T2,.JDAT+JOBOPC## ;STORE INTERRUPTED PC
HRRM T4,(P) ;STORE NEW PC
IFN FTCCIN,<
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
ANDCAM T1,JBTSTS##(J) ; TRAP FLAG
;HERE TO RESTORE USER HARDWARE STATE AND JUMP TO USER
USRXNT: 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,(P) ;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,(P) ;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,,RELEA1 ;(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.EA+UU.CP1,,UU.CP1+3 ;CALL,INIT
0,,0 ;42,43
0,,0 ;44,45
0,,UU.CP1 ;46,CALLI
UU.CP1+UU.EA+3,,UU.CP1+UU.EA ;OPEN,TTCALL
0,,0 ;52,53
0,,UU.CP1+UU.LER ;54,RENAME
UU.CP1,,UU.CP1 ;IN,OUT
UU.CP1,,UU.CP1 ;SETSTS,STATO
UU.CP1,,UU.CP1 ;GETSTS,STATZ
UU.CP1,,UU.CP1 ;INBUF,OUTBUF
UU.CP1,,UU.CP1 ;INPUT,,OUTPUT
UU.CP1,,UU.CP1 ;CLOSE,,RELEASE
UU.CP1,,UU.CP1 ;MTAPE,UGETF
UU.CP1,,UU.CP1 ;USETI,USETO
UU.CP1+UU.LER,,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.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.EA+25 ;(3)EXT:SEND DDT CHAR.
X DEVCHR,DVCHR,UU.CP1 ;(4)DEVICE CHARACTISTICS
X DDTGT,CPOPJ##,UU.CP1 ;(5)GET DDT MODE
X GETCHR,DVCHR,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 ;(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,DVTYP,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,UUOSEK##,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 ;(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 ;(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.,METER##,UU.LEA ;(111)PERFORMANCE METERING
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 ;(115)TERMINAL NUMBER FOR
; JOB
X TRMOP.,TRMOP##,UU.LEA+UU.CP1 ;(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 ;(142) IPCF READ
X IPCFS.,UIPCFS##,UU.CP1 ;(143) IPCF SEND
X IPCFQ.,UIPCFQ##,UU.CP1 ;(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.,CPOPJ##,UU.CP1 ;(156) FOR DAS78 (NOW OBSOLETE)
X NODE.,NODE.U##,UU.CP1 ;(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 ;(165) GET THE NETWORK TTY NUMBER
X GTXTN.,GTXTN,UU.CP1 ;(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 ;(201) QUEUE. UUO
X RECON.,RECON,UU.CP1 ;(202) RECON. 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
PUSHJ P,TTYFUW## ;FIND TTY FOR CURRENT JOB
; SET J TO JOB NO.,U TO OUTPUT BYTE POINTER
; 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: PUSHJ P,TTYFUW## ;FIND TTY FOR CURRENT JOB
PUSHJ P,PRRSP3## ;PRINT [XXX], CRLF, DOT
PUSHJ P,TTYSTC## ;PUT TTY INTO COMMAND MODE
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 FTLOCK,<
PUSHJ P,UNLOCK## ;TURN OFF NSHF AND NSWP AND RETURN CORE
>
IFN FTTRPSET,<
MOVEI T1,[CAME 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
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,RELEA5 ;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,.UPMP+.UPCTA
SKIPE T2 ;STILL HAVE FUNNY SPACE?
PUSHJ P,GVFWDS## ;GIVE IT BACK
HLLZS .UPMP+.UPCTA
IFN FTWATCH,<
HRRZS JBTPC##(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
;HERE WHENEVER ANYJOB 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
UTADC%==1 ;ADDRESS CHECK
UTUNF%==2 ;UNKNOWN FUNCTION
UTBTN%==3 ;BAD TRAP NUMBER
ERCODE UTEADC,UTADC%
ERCODE UTEUNF,UTUNF%
ERCODE UTEBTN,UTBTN%
UUTRP: HLRZ U,T1
CAILE U,NUTRPF
JRST UTEUNF
HRR M,T1
PUSHJ P,GETWRD##
JRST UTEADC
PUSHJ P,SAVE1##
MOVE P1,T1
JRST @UTPTBL(U)
UTPTBL: UTPRED
UTPSET
NUTRPF==.-UTPTBL-1
UTPRED: PUSHJ P,GETTRN
POPJ P,
MOVE T1,(U)
PUSHJ P,PUTWR1##
JRST UTEADC
SOJG P1,UTPRED
JRST CPOPJ1##
UTPSET: PUSHJ P,GETTRN
POPJ P,
PUSHJ P,GETWR1##
JRST UTEADC
MOVEM T1,(U)
SOJG P1,UTPSET
JRST CPOPJ1##
GETTRN: PUSHJ P,GETWR1##
JRST UTEADC
SKIPLE T1
CAILE T1,2
JRST UTEBTN
MOVEI U,.UPMP+.UPTVC(T1)
SOJA P1,CPOPJ1##
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:IFN FTTIME,<
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##
>
IFE FTTIME,<
JRST RTZER ;RETURN ZERO IF NO TIMMING COM.
>
;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::
SETZ F, ;LET WORLD KNOW THIS ISN'T AN I/O UUO
IMUL T1,TICSEC## ;CONVERT TO TICKS
ANDI T1,7777
MSLEEP: TRNN T1,7776 ;0 TIME?(CHECK ONLY 12 BITS)
MOVEI T1,2 ;YES. SLEEP 1 JIFFY
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
PUSH P,T1 ;SAVE SLEEP TIME
HRLI T1,WAKEJ## ;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: SYSPIF
IDPB T1,CLOCK##
IDPB J,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,J ;JOB NUMBER
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
PUSHJ P,SAVE4## ;SETSLP USES 16,17
MOVEI T2,JIFSEC## ;GET SECONDS WORTH OF JIFFIES
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 PEEKOK ;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: CAMGE T2,SYSSIZ## ;IS HE ASKING FOR LEGAL VALUE?
PEEKOK: CAML T2,MEMSIZ## ;..
JRST PEEKHI ;NO. FAILURE. RETURN 0
GOPEEK: 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.
PEEKHI: CAIL T2,400000 ;IS THIS IN THE
CAML T2,MONVFF## ; HISEG
JRST RTZER ; NO
JRST GOPEEK ; YES
> ;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
CAILE T1,17 ;CHECK ADDRESS
CAML T1,MEMSIZ## ; SEE IF LEGAL
PJRST ECOD2## ;NO--BOMB USER WITH ERROR 2
POKE0: MOVE T2,T1
PUSHJ P,PPPADR ;GET VIRTUAL ADR IF ARG IS PHYSICAL ADR
JRST ECOD2##
MOVE P1,T2 ;SAVE ADDRESS
MOVE P2,T2
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
IFN FTDAEM,<
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
>
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
LSHC T2,W2PLSH##-1 ;PAGE NUMBER DIVIDED BY TWO
TLNN T3,400000 ;EVEN OR ODD PAGE?
TDOA T2,[POINT 18,.EPPM##-.EPMP##,17] ;EVEN PAGE NUMBER
TDO T2,[POINT 18,.EPPM##-.EPMP##,35] ;ODD PAGE NUMBER
ADD T2,.CPTOS## ;RELOCATE FOR THIS CPU
LDB T3,T2 ;GET CONTENTS OF EXEC MAP SLOT CORRESPONDING TO THE PAGE
IFN FTKL10&FTMP,<
TRZE T3,PM.CSH ;CACHED?
PUSHJ P,UNCACH## ;UNCACHE THE PAGE FOR ALL CPUS
>
TRO T3,PM.WRT ;ALLOW WRITING
HRRM T3,.UPMP+.MTEMP ;STORE IN A PER-PROCESS TEMPORARY SLOT
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: TLNN T2,17 ;22 BIT ADDRESS?
SKIPGE P1 ; OR PHYSICAL ONLY UUO?
SKIPA T1,T2 ;YES
JRST PPPAD1 ;NO, T2 = VIRTUAL ADDRESS USER WANTS
LSH T1,W2PLSH## ;PAGE NUMBER
TRO T1,PM.ACC+PM.WRT ;ACCESS ALLOWED + WRITABLE (POKE)
HRRM T1,.UPMP+.MTEMP ;ADDRESSABLE VIA TEMP
ANDI T2,PG.BDY## ;COMPUTE VIRTUAL ADDRESS OF LOC
IORI T2,.TEMP
CLRPGT (0,.TEMP)
JRST CPOPJ1##
PPPAD1: MAP T1,(T2)
PJRST FLTCHK##
>
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
NLSNOP==.-SNPDSP-1
;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
IFN FTDAEM,<
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
;MISC. SUBROUTINES
RTNBPS: PUSHJ P,SAVE2## ;SAVE P1-P2
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,<
IFE FTDHIA,<
DIAUUO==CPOPJ## ;NO DIAG. UUO
>
IFN FTDHIA,<
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
FUNCTIONS DEFINED IN UUOCON
10 READ CSB
11 READ DSB
FUNCTIONS DEFINED IN MOSSER
100 GET MEMORY
101 GIVE MEMORY
>
DIAUUO: PUSH P,T1
HRR M,T1 ;ADR OF BLOCK
PUSHJ P,GETWDU## ;GET ARG
CAIN T1,7 ;WANT KON/UNIT NUMBER?
JRST DIAKUN ;YES, TELL HIM
CAIE T1,10 ;WANT TO READ CSB
CAIN T1,11 ; OR DSB ?
JRST DIAXSB ;YES, DO SO
;STILL IN FTDHIA CONDITIONAL
;IF GOING TO DO IO HE'D BETTER BE ALL IN CORE
SKIPE .UPMP+.UPVRT
JRST [POP P,(P)
JRST DIAVRT]
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]
POP P,T1 ;OK, RESTORE ARGUMENT
PUSHJ P,STOTAC## ;TRPSET STORES 0 IN THE AC
HLRE T2,T1 ;NUMBER OF ARGUMENTS
JUMPGE T2,WRONGN ;ILLEGAL N
PUSHJ P,SAVE4##
MOVN P1,T2 ;P1=NUMBER OF ARGS
HRR M,T1 ;LOC OF ARG BLOCK
PUSHJ P,GETWDU## ;GET FUNCTION
CAILE T1,MXDIAG## ;LEGAL?
IFE FTKL10,<
JRST BADFNC ;ILLEGAL FNCTION
>
IFN FTKL10,<
IFE FTMOS,<
JRST BADFNC ;ILLEGAL FNCN
>
IFN FTMOS,<
JRST [CAIN T1,100 ;GET MEMORY?
JRST DIAGTM## ;YES
CAIN T1,101 ;GIVE MEMORY?
JRST DIAGVM## ;YES
JRST BADFNC] ;ILLEGAL FUNCTION
>>
CAIGE P1,2 ;LEGAL?
JRST WRONGN ;ILLEGAL N
MOVE P2,T1 ;P2=FUNCTION CODE
PUSHJ P,GETWD1## ;GET KON/UNIT WORD
LDB T2,[POINT 7,T1,6] ;CONTROLLER NUMBER
HLRZ P3,SYSKON## ;GET FIRST DISK KDB
;STILL IN FTDHIA CONDITIONAL
DIADRS:
IFN FTMP,<
MOVE T3,P3
LDB T3,KOZCPU## ;RIGHT CPU?
CAME T3,.CPCPN##
JRST DIADR1 ;NO, KEEP LOOKING
>
MOVE T3,KONREG##(P3)
ADDI T3,KONEBK##(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
MOVEI W,MT0KDB## ;NOT A DISK, TRY MAGTAPES
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 DIADR3 ;NO, TRY NEXT KDB
LDB P3,[POINT 3,T1,29] ;YES, 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
DIADR3: HRRZ W,TKBKDB##(W) ;STEP TO NEXT TAPE KDB
JUMPN W,DIADR2 ;TEST IT
JRST ILLKON ;ILLEGAL CONTROLLER NUMBER
DIAUNI: LDB T1,[POINT 3,T1,29] ;UNIT
MOVE T3,P3
HRLI T3,-10 ;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 DIADSP ;YES, DO IT
;STILL IN FTDHIA CONDITIONAL
;HERE TO GET KONTROLLER/UNIT
DIAKUN: POP P,(P) ;REMOVE SAVED T1
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::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: MOVE 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::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,CPOPJ1## ;DONE IF 0
AOJA P2,DIAGC1 ;GET NEXT WORD
;STILL IN FTDHIA CONDITIONAL
;HERE FOR THE CODE COMMON TO BOTH READ CPU STATUS BLOCK AND READ
;DEVICE STATUS BLOCK
DIAXSB: POP P,(P) ;FLUSH SAVED T1
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
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
INTERN WRONGN,DINEFC,DIABAL
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
> ;END FTDHIA
>;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: HLRZ U,T1 ;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
RCNDSP: RCNROM ;(0) RUN ONLY ME
RCNSPN ;(1) SUPPEND SYSTEM
NLRECN==.-RCNDSP-1
;ERROR RETURNS
RCIAL%==1
RCNPV%==2
RCNTS%==3
RCNIJ%==4
RCNCD%==5
RCNAC%==6
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
;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
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: 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
MOVEI T1,SYSRST## ;RESTART ADDRESS
HRRM T1,.JBSA## ;STORE THAT FOR REBOOT
MOVSI T1,60000 ;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,20000 ;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##
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:
IFN FTKI10,<
DATAO PI,T1 ;SENT USER'S AC TO CONSOLE LIGHTS
>;END IFN FTKI10
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:
IFN FTKI10,<
DATAI APR,T1 ;GET 36 BIT SWITCHES
>
IFN FTKL10!FTKS10,<
SETZ T1, ;RETURN ZERO ON KL10
>
JRST STOTAC## ;GO STORE VALUE
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
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)
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
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 RTZER ;NOT A DEVICE, RETURN ZERO
IFN FTNUL,<
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 FTNUL,<
TLO T1,(T3) ;SET LH = -1 IF NUL:
>
PUSHJ P,TTYKLQ## ;DISCARD TTY DDB IF NOT IN USE
JRST STOTAC##
;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)
DVTYP: AOS (P) ;SKIP-RETURN SINCE UUO IS IMPLIEMENTED
PUSH P,T1 ;SAVE DEVICE NAME
PUSHJ P,DVCHR ;GET DEVICE CHARACTERISTICS
JUMPE T1,T2POPJ## ;NO SUCH DEV - RETURN 0
IFN FTSPL,<
PUSHJ P,CHKSPL ;SEE IF DEVICE IS SPOOLED
TLOA T2,.TYSPL!DVAVAL ;YES, SPOOL+AVAILABLE
> ;END CONDITIONAL ON FTSPL
DVTY1: 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
IFN FTNUL,<
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
PJRST STOTAC## ;RETURN TO USER
;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 ;BUMP SIZE BY 2 HOUSEKEEPING WORDS
SIZRT1: AOS -1(P) ;GIVE SKIP RETURN
SIZRET: POP P,M ;RESTORE LOC OF AC
PJRST STOTAC## ;STOTAC, THEN RETURN
;SUBROUTINE TO SET T1=LENGTH OF A NON-VARIABLE BUFFER
REGSIZ::LDB T1,PBUFSZ## ;NORMAL SIZE
POPJ P, ;RETURN
;DEVGEN -- RETURN RANGE AND STATION OF GENERIC DEVICES
;CALL: MOVE AC,SIXBIT NAME OF DEVICE
; CALLI AC,DEVGEN
;RETURNS CPOPJ IF UNIMPLEMENTED OR IF NO SUCH DEVICE (AC UNCHANGED)
;RETURNS CPOPJ1 IF DEVICE FOUND WITH AC AS FOLLOWS:
; BITS 0-8: LOWEST DEVICE NUMBER MATCHING GENERIC NAME
; 9-17: HIGHEST DEVICE NUMBER MATCHING
; 18-35: STATION NUMBER OF DEVICE
;IN PARTICULAR, DEPENDING ON THE TYPE OF NAME SPECIFIED, THE
;FOLLOWING RESULTS:
; (1) SPECIFIC (E.G. LPT153)
; LOW=HIGH=UNIT NUMBER (153)
; (2) STATION GENERIC (E.G. LPTS3)
; LOW=LOWEST DEVICE AT STATION OF THAT TYPE
; HIGH=HIGHEST
; (3) GLOBAL GENERIC (E.G. LPT)
; IF DEVICE AT JOB'S STATION, SAME AS STATION GENERIC
; IF NO DEVICE AT JOB'S STATION, SAME AS STATION GENERIC
; AT THE CENTRAL STATION
DEVGEN==CPOPJ## ;THIS UUO NOT SUPPORTED NOW
REPEAT 0,<
DEVGEN: PUSHJ P,DEVSRC ;SEE IF SPECIFIC NAME
JRST DEVGN1 ;NO--TRY GENERIC
IFN FTSPL,<
SKIPL DEVSPL(F) ;SPOOLED DISK?
JRST DEVGN0 ;NO
MOVE T1,DEVNAM(F) ;YES. NAME USER INITED
JRST DEVGEN ;DO THE UUO ON REAL DEVICE
DEVGN0:>
LDB T1,PDVSTA## ;GET STATION NUMBER
LDB T2,PUNIT## ;GET UNIT NUMBER
MOVE T3,T2 ;SET OTHER UNIT THE SAME
DEVGNX: HRL T1,T3 ;STORE HIGH UNIT
DPB T2,[POINT 9,T1,8] ;STORE LOW UNIT
PJRST STOTC1## ;SKIP RETURN WITH T1 AS ANSWER
;HERE WHEN NOT A SPECIFIC UNIT
DEVGN1: MOVEI T3,0 ;TAKE ANY DEVICE
PUSHJ P,DVASRC ;TRY GENERIC SEARCH
POPJ P, ;FAILED--RETURN TO USER
LDB T2,PUNIT## ;SAVE LOWEST UNIT
LDB T1,PDVSTA## ;GET STATION NUMBER
;LOOP OVER DDB CHAIN GETTING REST OF UNITS
PUSHJ P,SAVE1## ;SAVE P1
DEVGNL: HLLZ T4,DEVNAM(F) ;GET GENERIC NAME
LDB T3,PUNIT## ;SAVE HIGH UNIT IN CASE LAST ONE
PUSHJ P,NXDDB ;POINT AT NEXT DEVICE ON CHAIN
JUMPE F,DEVGNX ;RETURN RESULT IF END OF CHAIN
LDB P1,PDVSTA## ;GET THIS DEVICE'S LOCATION
CAME P1,T1 ;IS IT THE SAME AS WE WANT?
JRST DEVGNX ;NO--RETURN RESULT TO USER
HLLZ P1,DEVNAM(F) ;YES--GET IT'S GENERIC NAME
CAMN P1,T4 ;SEE IF IT MATCHES OUR REQUEST
JRST DEVGNL ;YES--LOOP ONWARDS
JRST DEVGNX ;NO--ALL DONE, RETURN RESULT
>;END OF REPEAT ZERO
SUBTTL GETPPN AND DEVPPN UUO'S (ALSO RTZER)
;RETURN PROJECT-PROGRAMMER NUMBER IN AC
GETPPN: MOVSI T1,JACCT
TDNE T1,JBTSTS##(J) ;LOGIN OR LOGOUT CUSP RUNNING ?
JRST GETPPL ;YES, SPECIAL PROJ,PROG NUMBER CHANGE.
MOVE T1,JBTPPN##(J) ;NO, RETURN PROJECT-PROGRAMMER NO. OF THIS JOB.
JRST STOTAC##
RTZER1::AOSA (P) ;RETURN 0 AND SKIP RETURN
RTZERP: POP P,T1 ;POP STACK & RETURN 0
IFE FTPEEKSPY,<
UPEEK:
>
RTZER:: TDZA T1,T1 ;RETURN 0. TO USER AC
RTM1:: SETOM T1 ;RETURN -1
JRST STOTAC## ;AS SPECIFIED IN AC FIELD OF HIS UUO
DEVPPU: PUSHJ P,DVCNSG ;FIND DDB
JRST RTZER ;NOT A DEVICE - RETURN 0
PUSHJ P,CURPPX##
MOVSI T2,DVDSK
TDNN T2,DEVMOD(F) ;IS DEVICE A DISK?
JRST STOTAC## ;NO, ERROR RETURN
JRST STOTC1## ;STORE ANSWER AND RETURN
SUBTTL IONDX. UUO
;CALLI TO CONVERT CHANNEL # OR DEVICE NAME TO I/O INDEX
;CALL WITH:
; MOVE AC,DEVICE NAME OR CHANNEL #
; IONDX. AC, OR CALLI 127
; ERROR RETURN
; GOOD RETURN UNIVERSAL I/O INDEX IN AC
UIONDX::PUSHJ P,SAVE1## ;SAVE P1
PUSHJ P,IONDX ;FIND THE IO INDEX
JRST STOTAC## ;STORE ERROR CODE
JRST STOTC1## ;STORE IO INDEX
;SUBROUTINE TO FIND IO INDEX. SAME AS UIONDX EXCEPT USER'S AC IS LEFT
; ALONE
;DESTROYS P1
IONDX:: PUSHJ P,DVCNSG ;FIND A DDB
PJRST ZPOPJ## ;RETURN 0 IF NO SUCH DEVICE
IONDF:: FRAME <NDXARG,NDXNAM>
MOVEM T1,NDXARG
MOVE T1,DEVNAM(F)
MOVEM T1,NDXNAM
PUSHJ P,TTYKLQ## ;KILL OFF DDB IF DDB
; NOT NEEDED
MOVE T1,NDXNAM ;GET DEVICE NAME IN T1
PUSHJ P,TTYALL## ;SET UP U VIA SIXBIT NAME
JRST DEVUDX ;TRY HARDER IF NOT A TTY
LDB T1,LDPLNO## ;GET LINE NUMBER
ADDI T1,.UXTRM ;CONVERT TO I/O INDEX
PJRST CPOPJ1## ;STORE IN AC AND SKIP
DEVUDX: LDB T1,PDVTYP## ;GET THE DEVICE TYPE
MOVE T3,T1
LSH T1,9 ;ALLOW FOR UNIT NUMBER
LDB T2,PUNIT## ;PICK UP UNIT NUMBER
IFN FTRDX,<
CAIN T3,.TYRDA/.TYEST ;RDX DEVICE
ANDI T2,7 ;YES, ONLY LOW ORDER 3 BITS
>;END FTRDX
IOR T1,T2 ;SQUISH TOGETHER
JUMPE T1,DSKUDX ;IF RESULT=0 WE HAVE A DISK AND WANT TO DO
; SOME SPECIAL THINGS.
LDB T2,PDVSTA##
LSH T2,3
CAIE T3,.TYTTY/.TYEST
CAIN T3,.TYPTY/.TYEST
SKIPA
IOR T1,T2
IFN FTRDX,<
CAIN T3,.TYRDA/.TYEST ;RDX DEVICE
JRST DEVUD1 ;YES
>;END FTRDX
CAIE T3,.TYMTA/.TYEST;IS THIS A MAG TAPE
CAIN T3,.TYDTA/.TYEST; OR A DEC TAPE?
SKIPA ;YES--SEE IF THIS IS 2ND CONTROL
PJRST CPOPJ1## ;GOOD RETURN
DEVUD1: LDB T2,[POINT 6,DEVNAM(F),17] ;GET THIRD LETTER
SUBI T2,' A'
LSH T2,^D15
ADD T1,T2
JRST CPOPJ1## ;GOOD RETURN
DSKUDX: MOVEI P1,0 ;START AT CHANNEL ZERO
DSKUD1: PUSHJ P,NXTCH ;NEXT CHANNEL
JRST ZPOPJ## ;NOT FOUND
MOVE T2,DEVNAM(T1) ;DEVICE NAME
CAIE T1,(F) ;DVCNSG FIND THIS DDB?
CAMN T2,NDXARG ;FIND A CHANNEL FOR THIS DDB?
SOSA T1,P1 ;YES
JRST DSKUD1 ;NO, KEEP LOOKING
JRST CPOPJ1## ;FOUND RETURN
SUBTTL SUBROUTINE TO FIND A DDB GIVEN ITS IO INDEX
;SUBROUTINE TO FIND A DDB GIVEN ITS UNIVERSAL IO INDEX
;CALL WITH:
; MOVE T1,IO-INDEX
; PUSHJ P,UDXDDB
; BAD UDX OR NO SUCH DEVICE
; HERE WITH F POINTING TO THE DDB
;
;NOTE: THIS ROUTINE IS NOT VERY FAST. DO NOT CALL IT UNLESS
; THERE IS NO OTHER WAY TO SETUP F. IN PARTICULAR, DO NOT
; CALL UDXDDB ON IN OR OUT UUOS.
;
UDXDDB::TLNE T1,-1 ;IS LH=0
POPJ P,0 ;NO--INSTANT LOOSER
CAIGE T1,HIGHXC## ;0 TO 20 ARE I/O CHANNELS
PJRST DVCNSG ;GO SEE IF OPEN -- SKIP RETURN IF YES
CAIGE T1,1000 ;20 THRU 777 ARE RESERVED
POPJ P,0 ; SO THEY ALL FAIL
LDB T2,[POINT 3,T1,20] ;GET CONTROLLER NUMBER
PUSH P,T2
CAIN T2,2 ;MATCH SPECIAL CODE FOR TTY?
JRST [TRNE T1,577000 ;IS THIS A POSSIBLE TTY
JRST UDXDB1 ;NO, CONTINUE
TRZN T1,.UXTRM ; CHECK FOR A TTY
JRST T2POPJ## ;NO EXIT
SETZM (P) ;YES
PUSH P,[SIXBIT .TTY.] ;ELSE ASSUME TTY #
MOVEI T2,.TYPTY/.TYEST ;SET T2 IN CASE VIRTUAL TTY
JRST UDXDB2] ;AND GO LOOK FOR IT
UDXDB1: LDB T2,[POINT 6,T1,26] ;PICK UP DEVICE TYPE
CAILE T2,TYPMAX ;SKIP IF NOT TOO BIG
JRST T2POPJ## ;TOO BIG--BOMB OUT
PUSH P,TYPTAB(T2) ;ELSE SAVE GENERIC NAME
UDXDB2: ANDI T1,777 ;JUST UNIT NUMBER
CAIN T1,777 ;GENERIC ONLY?
JRST UDXDB4 ;YES--GO DO GENERIC THING
MOVE T3,-1(P) ;GET BACK CONTROLLER NUMBER
JUMPE T3,UDXDB3
ADDI T3,'A' ;CONVERT TO LETTER
DPB T3,[POINT 6,(P),17] ;STORE IN DEVICE NAME
UDXDB3: PUSH P,T2
PUSHJ P,CVTSBT ;CONVERT UNIT NUMBER TO SIXBIT
POP P,T2
CAIN T2,.TYPTY/.TYEST ;NO LEADING O'S FOR PTY
JRST UDXDB4
TLNN T1,77 ;3 DIGITS?
JRST [LSH T1,-6 ;NO, SHIFT ONE DIGIT
TLO T1,(20B5) ;INSERT A LEADING SIXBIT 0
JRST .-1]
UDXDB4: HLRM T1,(P) ;STORE NUMBER
POP P,T1 ;PUT INTO T1 FOR DEVSRG
POP P,T2
PJRST DEVSRG ;GO LOOK FOR THE DDB
DEFINE TYPES(X),<
IRP X,<
<SIXBIT \X\>
>>
TYPTAB: TYPES <DSK,DTA,MTA,TTY,PTR,PTP,DIS,LPT,CDR>
TYPES <CDP,PTY,PLT,EPA,MPX,PAR,PCR,PAP,LPC,PCP,WTY,TSK>
TYPES <XXI,RDA,MCR>
SUBTTL GTNTN./GTXTN. UUO'S FOR TTY NAMES
;CALLI 165 (GTNTN) RETURN THE PHYSICAL NODE NUMBER AND TTY NUMBER
;CALL WITH:
; MOVE AC,[SIXBIT /TTYNNN/]
; GTNTN. AC,
;RETURN CPOPJ ;TTY DOES NOT EXIST / NOT CONNECTED
;AC=XWD NODE NUMBER,LINE NUMBER
;ERRORS:
; 0: NO SUCH DEVICE
; 1: NOT A TTY
; 2: TTY NOT CONNECTED
GTNTN: PUSHJ P,DVCNSG ;GET THE DDB
PJRST ECOD0## ;NO SUCH DEVICE
MOVSI T2,DVTTY ;GET THE TTY BIT
TDNN T2,DEVMOD(F) ;IS IT?
PJRST ECOD1## ;NOPE
HRRZ U,DDBLDB##(F) ;GET THE LDB
IFN FTNET,<
MOVEI T1,LDRREM## ;GET THE REMOTE BIT
TDNN T1,LDBDCH##(U) ;NETWORK TTY?
JRST GTNTN1 ;NO, LOCAL TTY
MOVE T2,LDBREM##(U) ;GET THE WORD WITH "CONNECTED" BIT
TLNN T2,LRLCON## ;IS THIS TERMINAL CONNECTED
JRST ECOD2## ;TERMINAL NOT CONNECTED. TELL THE USER
LDB T2,LDPRNN## ;GET THE NUMBER OF TERMINAL'S NODE
LDB T1,LDPRLN## ;GET THE REMOTE LINE NUMBER
HRLI T1,(T2) ;INSERT THE NODE NUMBER
PJRST STOTC1## ;EXIT
GTNTN1:
> ;END IFN FTNET
LDB T1,LDPLNO## ;GET THE LINE NUMBER
IFN FTNET,<
HRL T1,JBTLOC## ;GET THE LOCAL NODE NUMBER
>
PJRST STOTC1## ;RETURN THE NODE,,LINE
;CALLI 166 (GTXTN) RETURN THE -10'S TTY NUMBER GIVEN NODE AND LINE
;CALL WITH:
; MOVE AC,[XWD NODE,LINE]
; GTXTN AC,
;RETURN CPOPJ ;TTY/NODE DO NOT EXITS/NOT CONNECTED
; CPOPJ1 ;AC=SIXBIT /TTYNNN/
;ERRORS:
; 0: UNKNOWN NETWORK TTY
; 1: NO SUCH LOCAL TTY
GTXTN:: HLRZ T2,T1 ;GET THE NODE NUMBER
IFN FTNET,<
CAME T2,JBTLOC## ;LOCAL NODE?
>
SKIPN T2 ;ZERO IS ALSO THE LOCAL NODE
JRST GTXTN4 ;LOCAL NODE
IFE FTNET,<
PJRST ECOD0## ;NOT LOCAL RETURN ZERO
>
IFN FTNET,<
SKIPN T4,NETRTY## ;GET THE REMOTE PORTION OF THE SYSTEM'S TTYS
JRST ECOD0## ;NO REMOTE TTYS, RETURN ZERO
GTXTN1: MOVE U,LINTAB##(T4) ;GET THE LDB POINTER
MOVE T3,LDBREM##(U) ;GET THE REMOTE STATUS BITS
TLNN T3,LRLCON## ;IS THIS TERMINAL "CONNECTED"
JRST GTXTN2 ;TERMINAL IS NOT CONNECTED.
LDB T3,LDPRNN## ;GET THE NUMBER OF THE NODE THAT OWNS THE TTY
CAIE T3,(T2) ;ON THIS NODE?
JRST GTXTN2 ;NO
LDB T3,LDPRLN## ;GET THE REMOTE LINE NUMBER
CAIE T3,(T1) ;IS THIS THE LINE?
GTXTN2: AOBJN T4,GTXTN1 ;NO, CONTINUE THRU LINTAB
JUMPGE T4,ECOD0## ;NOT CONNECTED OR ILLEGAL
GTXTN3: LDB T1,LDPLNO## ;GET THE -10 LINE NUMBER
;RESTORE U
JRST GTXTN5 ;CONVERT AND EXIT
> ;END IFN FTNET
GTXTN4: ANDI T1,-1 ;MAX NUMBER
CAILE T1,TCONLN## ;IN RANGE?
JRST ECOD1## ;NO, NOT A LEGAL TTY
IFN FTNET,<
MOVE T2,LINTAB##(T1) ;GET THE LDB POINTER
MOVEI T3,LDRREM## ;GET NETWORK LINE BIT
TDNE T3,LDBDCH##(T2) ;IS IT A NETWORK TTY?
JRST ECOD1## ;YES, ILLEGAL DEVICE
> ;END IFN FTNET
GTXTN5: PUSHJ P,CVTSBT ;NO, CONVERT TO SIXBIT
HLRZ T1,T1 ;RIGHT HALF
HRLI T1,'TTY' ;INSERT TTY NAME
JUMPGE M,STOTC1## ;EXIT THE UUO
PJRST CPOPJ1 ;IF INTERNAL CALL, EXIT SKIP RETURN
SUBTTL MVBFH. UUO -- MOVE BUFFER HEADERS
;SUBROUTINE TO MOVE BUFFER HEADERS
;CALL WITH:
; MOVE AC,CHANNEL-NUMBER
; MOVE AC+1,[NEW-OUTPUT,,NEW-INPUT]
; MVBFH. AC,
; ERROR RETURN
; GOOD RETURN
MOVHDR: PUSHJ P,SAVE1## ;SAVE UCHAN
HRRZ P1,T1 ;COPY CHANNEL NUMBER
PUSHJ P,SETUF
JRST ECOD1## ;ERROR -- BAD CHANNEL NUMBER
HRLM P1,.UPMP+.UPCTA ;SAVE CHAN
LDB T1,PUUOAC## ;GET AC #
HRRI M,1(T1) ;PLUS 1
PUSHJ P,GETWDU## ;PICK UP THE WORD
MOVE P1,T1
HLRZ T2,T1 ;GET OUTPUT BUFFER ADDRESS
JUMPE T2,MVBFH1 ;JUMPE IF NO CHANGE
HRLM T2,DEVBUF(F) ;STORE NEW ADDRESS
TLON F,OBUFB ;TEST AND SET "OUTPUT BUFFER EXISTS" FLAG
PUSHJ P,UINITZ ;NEW BUFFER
MVBFH1: HRRZ T2,P1 ;GET INPUT POINTER
JUMPE T2,MVBFH2 ;JUMP IF NO CHANGE
HRRM T2,DEVBUF(F) ;SAVE NEW ADDRESS
TLON F,IBUFB ;FLAG WE HAVE INPUT BUFFER
PUSHJ P,UINITZ ;NEW BUFFER
MVBFH2: PUSHJ P,JDAADR
MOVEM F,(T1) ;SAVE UPDATED FLAGS
JRST CPOPJ1## ;GOOD RETURN
SUBTTL DEVSTS, DEVLNM, DEVRST, AND DEVURS UUO'S
;DEVICE STATUS CONI RETRIEVAL CALLI UUO
; CALL AC,[SIXBIT/DEVSTS/]
; OR
; CALLI AC,54
; WHERE AC CONTAINS THE CHANNEL NUMBER OF THE
; INIT'ED DEVICE....
; OR DEVICE NAME
; THE CONI STATUS WORD IN THE DDB (DEVSTS)
; IS RETURNED IN AC
DEVST: PUSHJ P,DVCNSG ;SEARCH FOR DEVICE OR CHANNEL
JRST RTZER ;RETURN 0 IF NOT THERE
IFN FTSPL,<
SKIPE T1,DEVCHR(F) ;ZERO IF SPOOLED DDB
>
MOVE T1,DEVSTS(F) ;GET DEVICE STATUS WORD
JRST STOTC1## ;USER, RETURNING T1 IN AC
;CALLI TO SET LOGICAL NAME
; MOVE AC,SIXBIT/DEVICE NAME/OR CHAN. NO.
; MOVE AC+1,SIXBIT/LOGICAL NAME/
; DEVLNM AC,
; ERROR RETURN ;AC=-1 IF NON-EX DEV. OR CHAN;-2 IF LOGICAL NAME IN USE
; NORMAL RETURN
DEVLNM: PUSHJ P,DVCNSG ;FIND DDB FOR THIS DEVICE
PJRST RTM1 ;CAN'T--ERROR RET. WITH AC=-1
LDB T2,PJOBN##
MOVE T1,DEVMOD(F) ;DEVICE INITED OR ASSIGNED?
CAMN T2,J ;MY DEVICE
TRNN T1,ASSCON!ASSPRG
IFN FTMDA,<
JRST [SKIPN T2 ;DEVICE OWNED BY ANYONE AT ALL?
CAME J,MDAJOB ;NO, IS THIS MDA?
JRST DEVLN3 ;OWNED, OR NOT MDA, ERROR
JRST DEVLN0] ;LET MDA GET UNOWNED DEVICE
DEVLN0:
>;END IFN FTMDA
IFE FTMDA,<
JRST DEVLN3 ;NO, RETURN -3
>;END IFE FTMDA
PUSHJ P,SAVE1## ;SAVE P1
PUSHJ P,GETWD1## ;GET LOGICAL NAME
MOVE P1,F ;SAVE DDB ADDR.
PUSHJ P,DEVLG ;IS ALREADY USED?
JRST DEVLN1 ;NO--
CAME F,P1 ;YES--SAME DEVICE?
SOJA M,DEVLN2 ;NO--ERROR RET -2
DEVLN1: CAIN P1,DSKDDB## ;DON'T CHANGE PROTYPE DSK DDB
JRST CPOPJ1##
MOVEM T1,DEVLOG(P1) ;YES--SET LOGICAL NAME
MOVE F,P1 ;RESTORE F FOR ASSCHK AND SETDVL
MOVE T1,DEVMOD(F) ;IF NOT ASSIGNED ...
TRNE T1,ASSCON!ASSPRG ;DON'T FIX LOGICAL NAME TABLE
PUSHJ P,SETDVL ;BE SURE LOG. NAME TABLE IS OK.
SKIPN DEVLOG(F) ;CLEARING LOGICAL NAME?
PUSHJ P,ASSCK1## ;YES, SEE IF WE CAN RECLAIM SPACE
JRST CPOPJ1## ; AND GIVE GOOD RETURN
DEVLN3: SKIPA T1,[-3]
DEVLN2: MOVNI T1,2 ;RETURN -2 IN USER AC
PJRST STOTAC##
;CALLI'S TO SET AND CLEAR THE RESTRICTED
;ASSIGNMENT BIT (DEPRAS) IN DEVSTA. LIMITED
;TO [1,2] OR JACCT SET.
; MOVE AC,[SIXBIT /DEVICE NAME/] OR CHANEL NO.
; DEVRST. AC, ;TO RESTRICT DEVICE
; DEVURS. AC, ;TO UNRESTRICT DEVICE
; ERROR RETURN ;NOT PRIVILEDGED, OR NON-EXISTANT DEVICE
; NORMAL RETURN
DEVRST: PUSHJ P,PRVJ## ;SKIP IF NOT PRIVILEDGED
PUSHJ P,DVCNSG ;SEARCH FOR DDB AND SKIP IF FOUND
POPJ P, ;ERROR (NON-SKIP) RETURN
MOVSI T1,DVDSK
IFN FTSPL,<
SKIPE DEVCHR(F)
>
TDNE T1,DEVMOD(F) ;IS IT A DISK?
POPJ P, ;YES, DON'T RESTRICT DISKS
MOVSI T1,DEPRAS ;GET RESTRICTED ASSIGNMENT BIT
IORM T1,DEVSTA(F) ;SET BIT IN DDB
PJRST CPOPJ1## ;AND SKIP RETURN
DEVURS: PUSHJ P,PRVJ## ;SKIP IF NOTPRIVILEDGED
PUSHJ P,DVCNSG ;SEARCH FOR DDB AND SKIP IF FOUND
POPJ P, ;ERROR (NON-SKIP) RETURN
MOVSI T2,DVDSK
MOVSI T1,DEPRAS ;GET RESTRICTED ASSIGNMENT BIT
IFN FTSPL,<
SKIPE DEVCHR(F) ;DON'T DO IT TO SPLTAB
>
TDNE T2,DEVMOD(F) ;DON'T UNRESTRICT DISKS
POPJ P, ;IF SPLTAB, GIVE ERROR RETURN
ANDCAM T1,DEVSTA(F) ;CLEAR THE BIT IN DDB
PJRST CPOPJ1## ;AND SKIP RETURN
SUBTTL SETDDT, WAIT AND GETLIN CALLI'S ; WAIT2 AND GETPPL
SETDDT: MOVEM T1,.JDAT+JOBDDT## ;SET BOTH USRDDT & JOBDDT IN JOB DATA AREA IN CASE
MOVEM T1,USRDDT## ; USER LOOKS AT JOBDDT BEFORE RESCHEDULING OCCURS
POPJ P, ;RETURN TO USER
GETPPL: MOVE T1,JBTPPN##(J) ; AND GET OLD NUMBERS.
MOVE T2,HIGHJB## ;CHECK FOR OTHER USERS UNDER SAME PP NUMBER.
PPNLUP: CAIN T2,(J) ;IS NEXT JOB TO BE LOOKED AT CURRENT JOB ?
SOJLE T2,STOTAC## ;YES, FINISHED SCANNING ALL JOBS ?
CAMN T1,JBTPPN##(T2) ;NO, ANOTHER USER UNDER SAME PROJ,PROG NUMBER ?
JRST STOTC1## ;YES, SKIP RETURN TO USER (LOGIN OR LOGOUT)
SOJG T2,PPNLUP ;NO, KEEP LOOKING
JRST STOTAC## ;NO OTHER JOBS, GIVE NORMAL RETURN
GETLN: PUSHJ P,TTYFND## ;FIND USER'S TTY DATA BLOCK.
MOVE T1,DEVNAM(F) ;GET DEVICE NAME IN SIXBIT
JRST STOTAC## ;RETURN IT TO USER.
;WAIT FOR IO TO BECOME INACTIVE ON CHANNEL AC
WAIT:: JUMPE F,CPOPJ## ;CHANNEL ASSIGNED?
; JRST WAIT2 ;WAIT TILL INACTIVE BEFORE
; RETURNING TO USER.
;ROUTINE TO ENSURE THAT ALL OUTPUT BUFFERS HAVE BEEN WRITTEN
WAIT2:
WAIT2X: PUSHJ P,WAIT1## ;NO, WAIT TILL INACTIVE
HLRZ U,DEVBUF(F) ;L(BUF)
JUMPE U,CPOPJ## ;NONE-RETURN
LDB T1,PIOMOD##
CAIGE T1,SD ;BUF MODE?
TLNN F,OUTBFB+OUTPB ;YES, ANY BUFFERS?
POPJ P, ;NO
IFN FTMSGSER,<
LDB T1,PDVTYP## ;DEVICE TYPE
CAIN T1,.TYMPX/.TYEST;MPX?
PJRST MPXWAT## ;YES, WAIT MPX STYLE
>
HRRZ T1,U
PUSHJ P,UADRCK ;ADDRESS CHECK THE HEADER
TLNE S,IO ;RETURN IF OUTPUT WASN'T LAST
EXCTUX <SKIPG @U> ;YES, VIRGIN RING?
POPJ P, ;YES, RETURN
PUSH P,DEVAIO(F)
MOVEI T1,DEPAIO!DEPOND;NON-BLOCKING BIT AND OUTPUT NOT DONE BIT
ANDCAM T1,DEVAIO(F) ;MAKE SURE THAT THIS WAITS UNTIL BUFFERS ARE OUT
;FALL INTO WAIT2A
WAIT2A: HRRZ U,DEVOAD(F)
HRRZ T1,U
JUMPE T1,WAIT2B ;RETURN IF REALLY NO OUTPUTS
PUSHJ P,UADRCK ;ADDRESS CHECK THE BUFFER ITSELF
EXCTUX <SKIPL @U> ;BUFFER HAVE DATA?
JRST WAIT2B ;NO, DONE
PUSHJ P,BRNGE## ;MAKE SURE ENTIRE DEVOAD BUFFER IS IN CORE
TRZ S,760000 ;YES, CLEAR ERROR BITS
IFN FTMP,<
PUSHJ P,SETCPF## ;GET ON RIGHT CPU
>
PUSH P,M
PUSHJ P,CALOUT ;CRANK UP THE DEVICE
POP P,M
PUSHJ P,WAIT1##
TRNE S,760000 ;ERRORS ENCOUNTERED?
JRST WAIT2B ;YES, GIVE UP
MOVSI T1,DEPSIE ;STOP ON ERROR BIT
TDNE T1,DEVJOB(F) ;IS IT ON?
TRNN S,IOTEND ;AND END OF TAPE?
JRST WAIT2A ;NO, RESTART IO IF NOT ALL BUFS DONE
WAIT2B: HRRZ T4,DEVSER(F) ;YES, RESTORE T4 = DISPATCH ADR
POP P,T1
ANDI T1,DEPAIO+DEPOND
IORM T1,DEVAIO(F)
POPJ P, ;AND RETURN
IFN FTACCT,<
SUBTTL ACCT. UUO - ACCOUNTING UUO
;UUO TO PERFORM ACCOUNTING FUNCTIONS
;CALLING SEQUENCE:
; MOVE AC,[FUNCTION,,ADDRESS]
; ACCT. AC,
; ERROR RETURN
; NORMAL RETURN
ACCT: HLRZ U,T1 ;FUNCTION
CAILE U,NLACCT ;DEFINED?
JRST ACTIAL ;NO, ILLEGAL
HRR M,T1 ;ADDRESS OF ARGUMENT BLOCK
PUSHJ P,GETWRD## ;GET LENGTH OF ARGUMENT BLOCK
JRST ACTADC ;ADDRESS CHECK
JRST @ACTTBL(U) ;DISPATCH
ACTTBL: ACTCAS
ACTRAS
NLACCT==.-ACTTBL-1
;HERE TO CHANGE THE ACCOUNT STRING
ACTCAS: MOVEI T2,ACTSTL## ;LENGTH OF ACCOUNT STRING
JUMPE T2,CPOPJ## ;NOT IMPLEMENTED IF LENGTH EQUALS ZERO
MOVSI T2,JACCT ;IS HE?
TDNN T2,JBTSTS##(J) ;NO, ERROR
JRST ACTNPV ;NO, ERROR
CAIE T1,1 ;ARGUMENT LIST MUST CONTAIN EXACTLY ONE WORD
JRST ACTIAL ;ILLEGAL ARGUMENT LIST
PUSHJ P,GETWR1## ;GET BYTE POINTER TO ACCOUNT STRING
JRST ACTADC ;ADDRESS CHECK
PUSHJ P,CKSTR ;MAKE SURE THE STRING IS LEGAL AND IN CORE
JRST ACTADC ;ADDRESS CHECK
PUSHJ P,SAVE1## ;SAVE P1
MOVSI P1,MACTSL## ;MINUS THE MAXIMUM LENGTH OF AN ACCOUNTING STRING
HRRI P1,.PDACS##(W) ;WHERE TO STORE ACCOUNT STRING
HRRI M,-1(T1) ;ADDRESS OF NEW ACCOUNT STRING
ACTCA1: PUSHJ P,GETWD1## ;GET NEXT WORD
MOVEM T1,(P1) ; AND STORE IT IN THE PDB
AOBJN P1,ACTCA1 ;LOOP OVER ENTIRE STRING
LDB T1,LSTBAS## ;LAST BYTE IN THE ACCOUNT STRING
MOVEI T2,0 ;LAST BYTE MUST BE ZERO
DPB T2,LSTBAS## ;ZAP
JUMPN T1,ACTTLS ;ERROR IF LAST BYTE ISN'T ZERO
JRST CPOPJ1## ;GOOD RETURN
;HERE TO READ THE ACCOUNT STRING
ACTRAS: MOVEI T2,ACTSTL## ;LENGTH OF THE ACCOUNT STRING
JUMPE T2,CPOPJ## ;NOT IMPLEMENTED IF ZERO
CAIE T1,2 ;ARGUMENT LIST MUST BE EXACTLY TWO WORDS LONG
JRST ACTIAL ;ILLEGAL ARGUMENT LIST
PUSHJ P,GETWR1## ;GET JOB NUMBER
JRST ACTADC ;ADDRESS CHECK
CAME T1,[-1] ;MINUS ONE MEANS CURRENT JOB
MOVE J,T1 ;TARGET JOB NUMBER
PUSHJ P,FNDPDB## ;FIND JOB'S PDB
JRST ACTNSJ ;NO SUCH JOB
MOVE J,.CPJOB## ;RESTORE REQUESTING JOB'S JOB NUMBER
PUSHJ P,GETWR1## ;GET ADDRESS WHERE A.S. SHOULD BE STORED
JRST ACTADC ;ADDRESS CHECK
HRRI M,ACTSTL##(T1) ;LAST ADDRESS WHERE A.S. TO BE STORED
PUSHJ P,GETWRD## ;CHECK LEGALITY
JRST ACTADC ;BAD ADDRESS
HRRI M,MACTSL##-1(M) ;SET TO STORE ACCOUNT STRING
MOVSI T2,MACTSL## ;NEGATIVE LENGTH
HRRI T2,.PDACS##(W) ;ADDRESS OF THE ACCOUNT STRING
ACTRA1: MOVE T1,(T2) ;WORD FROM ACCOUNT STRING
PUSHJ P,PUTWD1## ;STORE IT FOR THE PROGRAM
AOBJN T2,ACTRA1 ;LOOP OVER THE ENTIRE ACCOUNT STRING
JRST CPOPJ1## ;GOOD RETURN
;ACCT. ERROR CODES
ERCODE ACTTLS,1 ;STRING TOO LONG
ERCODE ACTADC,2 ;ADDRESS CHECK
ERCODE ACTIAL,3 ;ILLEGAL ARGUMENT LIST
ERCODE ACTNSJ,4 ;NO SUCH JOB
ERCODE ACTNPV,5 ;NOT PRIVILEGED
>;END IFN FTACCT
IFE FTACCT,<
ACCT==CPOPJ## ;NO ACCT UUO
>
SUBTTL LOGIN, LOGOUT AND ATTACH UUO'S
;LOGIN UUO USED ONLY BY LOGIN AND LOGOUT CUSPS
;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
;RETURNS TO UUO +1 IF SUCCESSFUL AND THAT LOC DOES NOT CONTAIN A HALT
LOGIN: MOVSI T2,JLOG ;IS USER ALREADY LOGGED IN?
TDNE T2,JBTSTS##(J)
POPJ P, ;YES, NO-OP
PUSHJ P,SAVE2## ;SAVE P1-P2
HLRE P1,T1 ;NO, -NO. OF WORDS
HRR M,T1 ;FIRST REL. LOC.
MOVE P2,[XWD -LOGTOP,LOGTAB] ;SET FOR LOOP
LOGIN1: MOVEI T1,0 ;ASSUME 0
AOSG P1 ;FINISHED HIS COUNT?
PUSHJ P,GTWST2## ;NO, GET NEXT WORD FROM USER AREA
MOVEM T1,@(P2) ;STORE WORD OR 0
ADDI M,1 ;GET NEXT ITEM
AOBJN P2,LOGIN1 ;FINISHED NO. OF MONITOR TABLES?
MOVE T1,JBTPRV##(J) ;GET MY PRIVILEGE WORD
MOVEM T1,.PDCAP##(W) ; AND SAVE AS CAPABILITY WORD
PUSHJ P,SETLOG## ;SET JLOG, INCREMEN LOGNUM, BATNUM
PUSHJ P,QSRLGI##
MOVSI T2,JACCT ;RESET THIS BIT TO INDICATE LOG-IN IS
HRRI T2,JS.XO ; AND CLEAR EXECUTE ONLY
ANDCAM T2,JBTSTS##(J) ; NOW COMPLETE AND ^C IS AGAIN PERMITTED.
HRRZ M,.JDAT+JOBPD1## ;LOCATION OF UUO IN USER AREA
PUSHJ P,GETWDU## ;GET NEXT INSTR FROM USER AREA
LSH T1,-30 ;LOOK AT TOP 12 BITS
CAIE T1,<HALT>B<35+24> ;HALT?
POPJ P,0 ;NO. RETURN TO USER.
LOGIN2: PUSHJ P,IORELS ;RELEASE ALL DEVICES
PUSHJ P,TTYFUW## ;FIND TTY AND PRINT ^C
JRST HOLD##
;STILL IN FTLOGIN CONDITIONAL
;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
LOGTAB: XWD J,JBTPPN## ;PROJECT-PROGRAMMER NUMBER
XWD J,JBTPRV## ;JOB PRIVILEGE BITS
XWD W,.PDNM1## ;1ST HALF OF USER'S NAME
XWD W,.PDNM2## ;2ND HALF OF USER'S NAME
IFN FTCNO,<
XWD W,.PDCNO## ;CHARGE NUMBER THIS JOB
>
IFE FTCNO,<
REPEAT 0,<
;KEEP THESE IF ANY ENTRIES FOLLOW
EXP S
>>
LOGTOP==.-LOGTAB ;NO. OF TABLES TO BE SET
;LOGOUT UUO
LOGOUT: PUSHJ P,TTYFNU##
MOVE T1,JBTSTS##(J) ;JOB STATUS
TLNN T1,JLOG ;LOGGED IN?
JRST JOBKL## ;NO
TLNN T1,JACCT ;ONLY A REAL, LIVE
;JACCTED LOGOUT
JRST EXIT ;IS ALLOWED TO DO THIS
MOVE T1,JBTPRG##(J) ;FOR EVERYBODY WLSE,
CAME T1,[SIXBIT .LOGOUT.] ;TREAT JUST LIKE EXIT
JRST EXIT
JRST JOBKL##
;ATTACH UUO - PRIVILEGED, FOR DAEMON, ATTACH COMMAND.
IFE FTATTACH,<UATTAC==CPOPJ##>
IFN FTATTACH,<
UATTAC: PUSHJ P,SAVE1## ;SAVE P1
HLLZ P1,T1 ;P1=FLAGS
PUSH P,T1 ;SAVE ARG XWD LINE, JOB
PUSHJ P,PRVJ## ;IS THIS A PRIVILEGED JOB?
SKIPA T1,0(P) ;YES. RESTORE ARGUMENT.
JRST UATAC5 ;NO. GO
TRNE T1,400000 ;NEGATIVE JOB ARGUMENT?
JRST UATC1A ;YES, MIGHT BE LINE CHANGE
TRNE T1,-1 ;ZERO ARGUMENT?
JRST UATAC1 ;NO. WANTS ATTACH.
HLRZ T1,0(P) ;YES. WANTS DETACH DONE
TRZ T1,600000 ;CLEAR FLAGS
CAIE T1,177777 ;DETATCH SELF?
JRST UATAC2 ;NO.
PUSHJ P,TTYSRC## ;FIND DDB VIA J
JRST TPOPJ## ;SHOULDN'T FAIL, NO DDB THIS JOB?
UATAC3: PUSHJ P,TTYDTC## ;DETACH VIA F
SKIPE LDBBKC##(U) ;ANY BREAK CHARACTERS INPUT?
PUSHJ P,COMSET## ;YES, ASSUME COMMAND TYPED
JRST TPOPJ1## ;GIVE USER OK RETURN
UATAC2: CAIL T1,TTPLEN## ;LEGAL LINE NUMBER?
JRST TPOPJ## ;NO. GIVE FAIL RETURN.
HRRZ U, LINTAB##(T1) ;YES. GET THE LDB ADDRESS
HRRZ F,LDBDDB##(U) ;GET LINKED DDB, IF ANY
JUMPE F,TPOPJ1## ;ALREADY DETACHED. GIVE OK RETURN
JRST UATAC3 ;GO DETACH JOB.
UATAC1: HRRZS T1 ;JOB NUMBER OF JOB BEING ATTACHED TO
PUSHJ P,LGLPRC## ;IS IT A LEGAL JOB NUMBER?
JRST TPOPJ## ;NO, FAIL RETURN
SKIPA T1,(P) ;YES, RESTORE JOB NUMBER
UATC1A: HRR T1,J ;NEGATIVE JOB ARGUMENT MEANS SELF
HRRZ F,TTYTAB##(T1) ;DDB OF JOB DESIRED
JUMPE F,TPOPJ## ;IF NONE, FAIL RETURN
HRRZ U,DDBLDB##(F) ;GET LDB ADDRESS FROM DDB LINK
MOVSI T1,600000 ;FLAG BITS TO CLEAR
ANDCAM T1,0(P) ;ZAP!
HLRZ T1,0(P) ;GET LINE NUMBER REQUESTED
CAIL T1,TTPLEN## ;IS IT LEGAL?
JRST TPOPJ## ;NO. FAIL RETURN.
MOVEI T3,LDRDSR##
MOVE T2,LINTAB##(T1) ;"TO" TTY
CAIG T1,TCONLN##
TDNE T3,LDBDCH##(T2) ;ATTACHING TO LOCAL TTY?
JRST UATC1C ;NO, OK
MOVE T1,JBTPPN##(J) ;GET MY PPN
CAME T1,HELPPP##
CAMN T1,FSFPPN## ;OR A PRIV'D JOB?
JRST UATC1C ;OK
JUMPE U,TPOPJ## ;IF "FROM" TTY UNKNOWN PLAY IT SAFE
MOVE T3,LDBDCH##(U)
TRNN T3,LDRPTY##
TRNE T3,LDRDSR##
JRST TPOPJ ;CAN'T DO IT
UATC1C: PUSHJ P,PTYDTC## ;DETACH VIA F
HLRZ U,0(P) ;GET LINE NUMBER
HRRZ U,LINTAB##(U) ;GET LDB ADDRESS
LDB J,PJOBN## ;GET JOB NUMBER
MOVE T1,(P) ;RESTORE ARGUMENT
TRNN T1,400000 ;JOB ATTACH ?
JRST UATC1B ;YES
HRRM J,(P) ;NO. USE J.
UATC1B: PUSHJ P,TTYATT## ;DO THE ATTACH.
JRST TPOPJ## ;FAIL RETURN (SHOULDN'T HAPPEN)
JUMPGE P1,UATAC4 ;JUMP IF SET TO MONITOR LEVEL FLAG NOT SET
PUSHJ P,CNCMOD## ;SET TO MONITOR LEVEL
JRST TPOPJ1##
UATAC4: MOVSI T1,LDLCOM##
TLNE P1,200000 ;SKIP IF TO SET USER LEVEL
ANDCAM T1,LDBDCH##(U) ;CLEAR MONITOR LEVEL BIT
TDNE T1,LDBDCH##(U) ;SKIP IF AT USER LEVEL
JRST TPOPJ1## ;NO, OK RETURN NOW
LDB T1,PJBSTS##
CAIE T1,TIOWQ##
JRST TPOPJ1##
MOVE T1,DEVIOS(F)
TLNE T1,IOW
PUSHJ P,TTWAKE##
JRST TPOPJ1## ;OK RETURN.
UATAC5: MOVE T1,(P) ;DET STILL ALOWED (SOMETIMES)
TRNE T1,-1 ;DOES HE WANT A DET?
PJRST TPOPJ## ;NO, RETURN
PUSHJ P,TTYSRC## ;YES, SET UP 4
PJRST TPOPJ## ;SHOULD NEVER FAIL
HLRZ T1,(P) ;GET TTY NUMBER HE WANTED DET'D
CAIN T1,-1 ;IS IT -1? (DEFAULT FOR SELF)
JRST UATAC6 ;YES, CHECK USER MODE
TRZ T1,600000 ;GET RID OF FLAGS
LDB P1,LDPLNO## ;GET REAL TTY NUMBER
CAME T1,P1 ;SAME?
PJRST TPOPJ## ;NO, RETURN
UATAC6: MOVSI T1,LDLCOM## ;MONITOR COMMAND LEVEL BIT
MOVSI P1,(JB.LBT) ;GET BATCH BIT
TDNN P1,JBTLIM##(J) ;IS THIS A BATCH JOB?
TDNE T1,LDBDCH##(U) ;IS HIS TTY AT USER LEVEL?
PJRST TPOPJ## ;NO, RETURN
JRST UATAC3 ;YES, NOW DET HIM.
> ;END FTATTACH CONDITIONAL
SUBTTL GETTAB UUO
;UUO TO RETURN CONTENTS OF A MONITOR JOB TABLE ENTRY
;CALL: HRROI AC, MONITOR JOB TABLE NUMBER (NEG. TABLES FOR CUSTOMER)
; HRLI AC, JOB NUMBER (OPTIONAL) LH .EQ. -1 MEANS CURRENT JOB
; LH .EQ. -2 MEANS JOB'S HIGH-SEGMENT
; 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
GETTAB: HLRZ T2,T1 ;GET USER SUPPLIED JOB NUMBER
HRRE T3,T1 ;GET TABLE NUMBER IN T3
CAIN T3,.GTRNG
HLRE T3,T1
CAIGE T3,GTTBLN ;IS TABLE NUMBER LEGAL?
CAMGE T3,MINTBB ; (NEGATIVE NUMBERS LEGAL FOR CUSTOMER'S TABLES)
POPJ P, ;NO. ERROR RETURN, AC UNCHANGED
HRRE T4,T1
CAIN T3,GTSELF ;IS THIS A GETTAB IMMEDIATELY?
MOVEI T3,.GTSLF ;YES--GO HANDLE SPECIALLY
LDB T1,[POINT 3,NUMTAB(T3),11] ;GET CODE
JUMPE T1,CPOPJ## ;JUMP IF UNDEFINED
HRRE J,T2
CAIE T4,.GTRNG ;GO IF USER WANTS RANGE
CAIE T1,GT.RNG ;TABLE WITH A RANGE ?
JRST GETTB0 ;NO
LDB T2,[POINT 9,NUMTAB(T3),8] ;GET INDEX INTO RANGE TABLE
HLRE T1,RNGTAB(T2) ;LOWER BOUND
HRRE T2,RNGTAB(T2) ;UPPER BOUND
CAMG J,T2 ;TOO LARGE ?
CAMGE J,T1 ;OR TOO SMALL ?
POPJ P, ;YES, ERROR RETURN
JRST GETTBX ;NO, GO GET THE ANSWER
GETTB0: CAIE T1,GT.RNG
CAIN T1,GT.ITM
JRST GETTB1
CAIL T2,-2
MOVE J,.CPJOB##
CAIE T2,-2 ;YES--SEE IF REQUESTING HI-SEG
JRST GETTB1 ;NO--SKIP AHEAD
SKIPG J,JBTSGN##(J) ;YES--SEE IF HE HAS A HI-SEG
POPJ P, ;ERROR IF NO HI-SEG
TLZ J,-1
;AT THIS POINT T3=TABLE NUMBER AND J=INDEX
GETTB1: MOVEI T2,0 ;ASSUME 0 MAX
CAIE T1,GT.JOB ;JOB TABLE?
CAIN T1,GT.PDB ; OR PDB POINTER?
MOVEI T2,JOBMAX## ;YES--SETUP MAXIMUM
CAIN T1,GT.SEG ;JOBN+SEGN LONG?
MOVEI T2,JBTMAX## ;YES--SETUP MAXIMUM
CAIE T1,GT.RNG
CAIN T1,GT.ITM ;SPECIAL TABLE
LDB T2,[POINT 9,NUMTAB(T3),8] ;GET MAXIMUM
JUMPE T2,RTZER1 ;IF T2=0 NUMTAB IS WRONG
CAIE T4,.GTRNG
JRST GETTB2
CAIE T1,GT.RNG
SKIPA T1,T2
MOVE T1,RNGTAB(T2)
JRST STOTC1##
GETTB2: SKIPL J ;SKIP IF TOO SMALL
CAMLE J,T2 ;SKIP IF VALID INDEX
POPJ P,0 ;INDEX IS TOO BIG
CAIE T1,GT.PDB ;IS DATA IN PDB?
JRST GETTBX ;NO--GET FROM TABLE
MOVE T2,J ;COPY INDEX INTO RIGHT AC
HRRZ T3,NUMTAB(T3) ;INDEX INTO PDB
PUSHJ P,PDBWRD## ;GET WORD FROM PDB
JRST STOTC1## ;STORE AS ANSWER
GETTBX: MOVE T1,@NUMTAB(T3) ;GET WORD
JRST STOTC1## ;SKIP RETURN T1 IN HIS AC
;THE MONITOR JOB TABLE NUMBERS:
$LOW ;MUST BE IN LOW SEG FOR GETTAB IMMEDIATE
;MACRO TO DEFINE A GETTAB TABLE
;THIS MACRO HAS 3 ARGUMENTS:
; FT - FEATURE TESTS FOR WHICH TABLE EXISTS
; TYPE - ONE OF:
; "J" - JOB TABLE
; "S"- JOB TABLE WITH JOBN + SEGN ENTRIES
; "I" - RANDOM TABLE
; "P" - DATA IN PDB
; "R" - DATA WITHIN A RANGE TABLE
; TBL - ADDRESS OF TABLE (OR INDEX INTO PDB)
; MAX - MAXIMUM FOR RANDOM TABLES SHIFTED LEFT 9 BITS
; OFS - ADDRESS OF ENTRY IN RANGE CHECKING TABLE
DEFINE GT(FT,TYPE,TBL,MAX,OFS),<
IFIDN <TYPE>,<J>,<
IFE FT,< JOBMXL##+<GT.JOB>B29,,ZERO>
IFN FT,< JOBMXL##+<GT.JOB>B29+J,,TBL>
>
IFIDN <TYPE>,<S>,<
IFE FT,< JBTMXL##+<GT.SEG>B29,,ZERO>
IFN FT,< JBTMXL##+<GT.SEG>B29+J,,TBL>
>
IFIDN <TYPE>,<P>,<
IFE FT,< JOBMXL##+<GT.JOB>B29,,ZERO>
IFN FT,< JOBMXL##+<GT.PDB>B29+W,,TBL>
>
IFIDN <TYPE>,<I>,<
IFE FT,< ZERO>
IFN FT,< MAX+<GT.ITM>B29+J,,TBL>
>
IFIDN <TYPE>,<R>,<
IFE FT,< ZERO>
IFN FT,< EXP <OFS>B8+<GT.RNG>B11+<J>B17+TBL>
>
>
DEFINE RANGE(FT,FIRST,LAST,RNG,NAME),<
IFN FT,<
RNG'OFS==.-RNGTAB
IFNB <NAME>,<
NAME:: FIRST,,LAST
>
IFB <NAME>,<
FIRST,,LAST
>
>>
ZERO:
RNGTAB: 0 ;ENTRY 0 NOT USED
RANGE 1,<GTBSTT-NUMTAB>,<GTTBLN-1>,NUM
RANGE 1,<CTTWDT##-TTTWDT##>,<TTTWDN##-1-<TTTWDT##-CTTWDT##>>,TTT
RANGE FTIPCF,<.GTCSD##-.GTSID##>,SDTBLN##,SID
RNGTBL==.-RNGTAB
SALL
GTBSTT: ;CUSTOMER TABLES GO HERE
NUMTAB::GT 1,S,JBTSTS## ;(000) JOB STATUS TABLE
MINTAB==GTBSTT-NUMTAB
GT 1,S,JBTADR## ;(001) SIZE,,ADDRESS
GT 1,S,JBTPPN## ;(002) PPN
GT 1,S,JBTPRG## ;(003) PROGRAM NAME
GT FTTIME,P,.PDTTM## ;(004) RUNTIME IN JIFFIES
GT FTKCT,P,.PDKCT## ;(005) KCT COUNT
GT 1,J,JBTPRV## ;(006) PRIVILEGE BITS
GT 1,S,JBTSWP## ;(007) LOCATION ON DISK
GT 1,J,TTYTAB## ;(010) TTY DDB POINTERS
GT 1,I,CNFTBL##,CNFMXL## ;(011) CONFIGURATION DATA
GT 1,I,NSWTBL##,NSWMXL## ;(012) NON-SWAPPING DATA
GT 1,I,SWPTBL##,SWPMXL## ;(013) SWAPPING DATA
GT 1,J,JBTSGN## ;(014) HIGH SEG #
GT 1,I,ODPTBL##,ODPMXL## ;(015) ONCE ONLY DISK PARAMETERS
GT 1,I,LVDTBL##,LVDMXL## ;(016) LEVEL-D TABLE
GT FTDSTT,J,JBTRCT## ;(017) DISK READS
GT FTDSTT,J,JBTWCT## ;(020) DISK WRITES
EXP ZERO ;(021) UNUSED
EXP ZERO ;(022) UNUSED
GTSELF==.-NUMTAB ;TABLE # OF NUMTAB
GT 1,I,NUMTAB,<<GTTBLN-1>B26> ;(023) THIS TABLE
GT 1,S,JBTDEV## ;(024) DEVICE OR FSN
GT 1,I,STSTBL##,STSMXL## ;(025) STATE CODES
GT FTNET,J,JBTLOC## ;(026) JOB LOCATION
GT 1,I,CORTAB##,CTBMXL## ;(027) KA10 CORE TABLE
GT 1,I,COMTAB##,COMMXL## ;(030) MONITOR COMMANDS*
GT 1,P,.PDNM1## ;(031) USER NAME (0FIRST)
GT 1,P,.PDNM2## ;(032) USER NAME (0LAST)
GT FTCNO,P,.PDCNO## ;(033) CHARGE NUMBER
EXP ZERO ;(034) UNUSED
GT FTWATC,J,JBTWCH## ;(035) WATCH BITS
GT FTSPL,J,JBTSPL## ;(036) SPOOL TABLE
GT FTRTTR!FTHPQ,J,JBTRTD##,ITMRTD## ;(037) REAL TIME
GT FTTLIM,J,JBTLIM## ;(040) CORE AND TIME LIMITS
EXP ZERO ;(041) UNUSED
EXP ZERO ;(042) UNUSED
GT 1,I,COMTB2##,COMMX2## ;(043) SET COMMANDS
GT 1,I,APRSTS##,LENSTS## ;(044) CRASH TABLE
GT 1,I,ISCAN##,ISTMXL## ;(045) SWAP-IN LIST
GT 1,I,OSCAN##,OSTMXL## ;(046) SWAP-OUT LIST
GT 1,I,SSCAN##,SSTMXL## ;(047) SCHEDULER LIST
GT FTRSP,J,JBTRSP## ;(050) TIME USER BEGAN TO WAIT
GT 1,I,SYSTBL##,SYSMXL## ;(051) SYSTEM WIDE DATA
GT FTWHY,I,CRSHAC##,17000 ;(052) WHY RELOAD COMMENT
GT FTRSP,J,JBTRQT## ;(053) TIME IN RUN QUEUES
GT FTMP,J,JBTSPS##,ITMSPS## ;(054) SECOND CPU STATUS
;CONTINUED ON NEXT PAGE
GT 1,I,.C0CDB##,ITMC0C## ;(055) CPU0 CDB CONSTANTS
GT 1,I,.C0VBG##,ITMC0V## ;(056) CPU0 CDB VARIABLES
GT 1,I,.C1CDB##,ITMC1C## ;(057)
GT 1,I,.C1VBG##,ITMC1V## ;(060)
GT 1,I,.C2CDB##,ITMC2C## ;(061)
GT 1,I,.C2VBG##,ITMC2V## ;(062)
GT 1,I,.C3CDB##,ITMC3C## ;(063)
GT 1,I,.C3VBG##,ITMC3V## ;(064)
GT 1,I,.C4CDB##,ITMC4C## ;(065)
GT 1,I,.C4VBG##,ITMC4V## ;(066)
GT 1,I,.C5CDB##,ITMC5C## ;(067)
GT 1,I,.C5VBG##,ITMC5V## ;(070)
GT 1,I,FETTBL,FETMXL ;(071) FEATURE TABLE
GT 1,I,SDVTBL##,SDVMXL## ;(072) ERSATZ DEVICE NAMES
GT FTRSP,I,.GTSCN##,SCNMXL## ;(073) SCNSER DATA
GT 1,I,SNDTMP##,SNDMXL## ;(074) LAST SEND ALL
GT 1,I,TTCWDT##,TTCMXL## ;(075) SET TTY NAMES*
GT FTIPCF,I,PIDTAB##,MIDMXL## ;(076) PROCESS ID TABLE
GT FTIPCF,I,IPCTAB##,IPCMXL## ;(077) IPCF MISC. DATA
GT 1,S,JBTUPM## ;(100)POINTER TO USER PAGE MAP
GT FTWATCH,I,WATTAB##,WTCMXL## ;(101) WATCH COMMANDS*
GT 1,P,.PDCVL## ;(102) CURRENT VM LIMITS
GT 1,P,.PDMVL## ;(103) MAX VM LIMITS
GT FTIPCF,P,.PDIPA## ;(104) IPCF STATISTICS
GT FTIPCF,P,.PDIPC## ;(105) IPCF POINTERS
GT FTIPCF,P,.PDIPI## ;(106) THIS JOB'S [SYSTEM]INFO
GT FTIPCF,P,.PDIPQ## ;(107) FLAGS AND QUOTAS
GT 1,P,.PDDVL## ;(110) POINTER TO DEVICE LOG NAME TABLE
GT 1,P,.PDABS## ;(111) ADDRESS BREAK SETTING
EXP ZERO ;(112) RESERVED
GT 1,I,.GTVM##,GTVMXL## ;(113) VM DATA
GT 1,J,JBTVRT## ;(114) PAGING RATES
GT 1,I,.GTSST##,SSDMXL## ;(115) SCHEDULER STATISTICS
GT FTNSCH,I,.GTDCF##,DCFMXL## ;(116) DESIRED CHAN USE FRACTION
GT 1,J,JBTST2## ;(117)SECOND JOB STATUS WORD
GT FTNSCH,J,JBTSCD## ;(120) TYPES AND CLASS WORD
GT FTNSCH,I,CLSSTS##,CLSMXL## ;(121) QUOTAS BY CLASS
GT FTNSCH,I,CLSQTA##,CLSMXL## ;(122) QUOTAS BY CLASS IN JIFFIES
GT FTNSCH,I,CLSRTM##,CLSMXL## ;(123) RUNTIME BY CLASS SINCE STARTUP
EXP ZERO ;(124) UNUSED
EXP ZERO ;(125) UNUSED
;CONTINUED ON NEXT PAGE
GT FTIPCF,R,.GTSID##,,SIDOFS ;(126) SPECIAL PIDS
GT FTEQDQ,I,.EQTAB##,ENQMXL## ;(127) ENQ/DEQ STATISTICS
GT 1,J,JBTJLT## ;(130) JOB LOGIN TIME
GT FTKL10&FTEMRT,P,.PDEBT## ;(131) # JIFFIES OF EBOX TIME FOR JOB
GT FTKL10&FTEMRT,P,.PDEB2## ;(132) REMAINDER MOD RTUPS OF JIFFIES OF EBOX TIME FOR JOB
GT FTKL10&FTEMRT,P,.PDMBT## ;(133) # JIFFIES SPENT DOING MEMORY REFERENCES FOR JOB
GT FTKL10&FTEMRT,P,.PDMB2## ;(134) REMAINDER MOD RTUPS OF A MBOX JIFFIES FOR JOB
GT 1,P,.PDSTR## ;(135) DEVICE PROGRAM WAS RUN FROM
GT 1,P,.PDDIR## ;(136) DIRECTORY PROGRAM WAS RUN FROM
GT 1,P,.PDNAM## ;(137) PROGRAM NAME
GT 1,P,.PDDFL## ;(140) USER'S DEFAULTS
GT FTNET&FTCMSR,I,NETGTT##,.NTMXL## ;(141) NETSER PERFORMANCE MEASUREMENTS
GT FTPSCD,I,SCDPER##,%PERLN## ;(142) PERFORMANCE TABLE
GT FTACCT&FTKCT,P,.PDVKC## ;(143)JOB'S VIRTUAL KCT
GT FTACCT,P,.PDUUC## ;(144)JOB'S UUO COUNT
GT 1,P,.PDSFD## ;(145) FIRST SFD IN PATH PROGRAM WAS RUN FROM
GT 1,P,.PDSFD##+1 ;(146) SECOND
GT 1,P,.PDSFD##+2 ;(147) THIRD
GT 1,P,.PDSFD##+3 ;(150) FOURTH
GT 1,P,.PDSFD##+4 ;(151) FIFTH
GT FTWATCH,J,JBTPC## ;(152) JOB'S PC
GT 1,P,.PDCAP## ;(153) CAPABILITY WORD (MAX PRIVILEGES)
.GTRNG==.-NUMTAB
GT 1,I,RNGTAB,<<RNGTBL-1>B26> ;(154) RANGE TABLE FOR GETTABS
.GTSLF==.-NUMTAB
GT 1,R,NUMTAB,,NUMOFS ;(155) .GTSLF REVISITED
GT 1,R,TTTWDT##,,TTTOFS ;(156) SIXBIT TERMINAL NAMES
GT 1,P,.PDOBI## ;(157) OPERATOR AND BATCH INFORMATION
GT 1,I,DVCSTS##,LENDVS## ;(160) CONI/DATAI DEVICE STATUS
GT FTNET,I,NDBTBL##,NDBMXL## ;(161) NDB BYTE POINTERS
GT 1,J,JBTPDB## ;(162) JOB PDB ADDRESS
GT FTEQDQ,P,.PDEQJ## ;(163) ENQ Q-HEADER
GT 1,I,DFLTTB##,DFLMXL## ;(164) SET DEFAULT COMMAND ARGUMENTS
;INSERT NEW TABLES ABOVE HERE
GTTBLN=.-NUMTAB ;LENGTH OF TABLE
IFN FTPATT,<
Z ;FOR PATCHING
Z
>
$HIGH ;BACK TO THE HIGH SEGMENT
MINTBB: MINTAB
DEFINE FTBITS(FET),<
.X==0
.Y==0
.Z==0
IRP FET<
IFGE .Y-21,<PRINTX ? FET CANT BE INSERTED>
IFN FT'FET,<.X==.X!1_.Y>
.Z==.Z!1_.Y
F.'FET==1_.Y
.Y==.Y+1>
XWD .Z,.X>
FT1==-1 ;FORCE ON (NAME=1)
FT0==0 ;FORCE OFF (NAME=0)
;TABLE OF BITS FOR MONITOR FEATURES
;ALWAYS ADD NEW FEATURES AT END OF LIST
;AND ATTEMPT TO INCLUDE IN MOST APPROPRIATE LIST
$LOW
FETTBL:
;(0) LIST OF MONITOR NON-I/O FEATURES WHICH DIRECTLY IMPACT CUSPS (THIS WORD IS FULL)
FTBITS<0,1,DAEMON,1,SPL,JCON,POKE,PEEK,1,CCIN,IPCF,PI,1,EQDQ,MIC,MLOG,MDA>
;(1) REAL-TIME AND SCHEDULING FEATURES
FTBITS<HPQ,1,1,RTTRAP,TRPSET,LOCK,RTC,0,1,1,NSCHED,PSCD,CMSR>
;(2) COMMAND FEATURES (THIS WORD IS FULL)
FTBITS<ATTACH,1,1,1,1,WATCH,1,1,VERS,1,1,1,1,MONL,MOFF,EXE,PJOB>
;(3) ACCOUNTING FEATURES
FTBITS<TIME,KCT,1,CNO,TLIM,FDAE,EMRT,ACCT>
;(4) NON I/O FEATURES NOT RELATED TO DEBUGGING
FTBITS<1,MP,EL,2SWP,1,1,1,METR,KI10,0,22BI,0,KL10,1,KS10>
;(5) NON I/O DEBUGGING FEATURES
FTBITS<0,0,1,1,TRAC,PATT,WHY,RSP,1>
;(6) DISK UUO FEATURES (THIS WORD IS FULL)
FTBITS<1,SFD,1,1,STR,DQTA,DSUP,DSEK,DRDR,GSRC,AIR,APLB,DPRI,LIB,NUL,DSIM,DHIA>
;(7) DISK "INVISIBLE" FEATURES (THIS WORD IS FULL)
FTBITS<DOPT,DBAD,DHNG,DSTT,DALC,1,DMRB,DETS,DUFC,DBBK,SWPE,0,1,1,CBDB,0,SLCK>
;(10) SCANNER, RP04 FEATURES
FTBITS<HDPX,GPO2,630H,MODM,SCNR,SCLC,DIAL,TPAG,TBLK,CAFE,2741,0,TVP,D10H,RDX,1>
;(11) OTHER PERIPHERALS (THIS WORD IS FULL)
FTBITS<1,MTSE,CDRS,1,LPTR,NET,1,CRTR,CPTR,1,MSGS,XTC,DN60,TSK,TLAB,1,1>
;(12) OTHER PERIPERALS (SECOND WORD)
FTBITS<DX10>
;(13) DISK "INVISIBLE" FEATURES (SECOND WORD)
FTBITS<DUAL>
;(14) DISK UUO FEATURES (SECOND WORD)
FTBITS<PSTR>
;(15) LIST OF MONITOR NON-I/O FEATURES WHICH DIRECTLY IMPACT CUSPS (SECOND WORD)
FTBITS <MPB>
FETMXL=<.-FETTBL-1>B26
$HIGH
SUBTTL SETNAM & CNGPPN UUO'S
;UUO TO SET CURRENT PROGRAM NAME
; MOVE AC,[SIXBIT /NAME/]
; ALWAYS RETURN
SETNAM: MOVEM T1,JBTPRG##(J) ;STORE PROGRAM NAME FOR SYSTAT AND SYSDPY
IFN FTTLIM, < MOVSI T2,(JB.LSY) ;CLEAR "GOT FROM SYS:" FLAG
ANDCAM T2,JBTLIM##(J) ; INDICATES LOADER IS DONE
>
MOVSI T2,JACCT ;ALWAYS CLEAR JACCT
ANDCAM T2,JBTSTS##(J)
MOVEI T2,JS.RUU!JS.XO!JS.XOR ;CLEAR EXECUTE ONLY SO CAN SAVE
MOVE T3,JBTSGN##(J) ;HI SEG CHARACTERISTICS FOR THIS JOB
MOVE T4,.JDAT+JOBPD1## ;UUO PC
TLNE T3,GTSSEG ;HE SEG CONCEALED?
TLNN T4,(IC.LIP) ;UUO DONE FROM A PUBLIC PAGE?
ANDCAM T2,JBTSTS##(J) ; A PROGRAM LOADED BY XO LOADER
; ALWAYS CLEAR JACCT WITH JS.XO
MOVSI T2,(UP.GET) ;CLEAR GET IN PROGRESS FLAG
ANDCAM T2,.UPMP+.UPBTS
PUSHJ P,MAPHGH## ;REDO THE MAP IN CASE CONCEALED
MOVE T1,JBTPRG##(J) ;RESTORE NAME
IFN FTWATCH&FTVERSION,<
JUMPE T1,CPOPJ## ;IF TO 0, DONT TYPE OUT
PUSHJ P,VERWAT## ;SEE IF WATCHING (IF SO, ONLY ON CPU0)
POPJ P, ;NO--JUST RETURN
PUSHJ P,INLMES## ;TYPE:
ASCIZ /:/
PUSHJ P,VERBTH## ;TYPE NAME AND VERSION
PJRST PRRBKC## ;TYPE RIGHT BRACKET <CRLF>
>
IFE FTWATCH&FTVERSION,<
POPJ P,
>
;UUO TO CHANGE PROJECT, PROGRAMMER NUMBER, FOR LOGIN ONLY
; MOVE AC,NEW PPN
; CALLI AC,CHGPPN
; NOT IMPLEMENTED
; OK
CHGPPN: TRNE T1,777777 ;PROG. # = 0?
TLNN T1,777777 ;NO, PROG. = 0?
POPJ P, ;NO ZER0'S ALLOWED
MOVSI T2,JLOG ;LOGGED IN BIT
TDNE T2,JBTSTS##(J) ;SKIP IF JOB NOT LOGGED IN
POPJ P, ;NO GOOD IF IT IS
MOVEM T1,JBTPPN##(J) ;OK, CHANGE PPN
JRST CPOPJ1## ;AND GIVE OK RETURN
SUBTTL DEVNAM UUO
;DEVNAM UUO (CALLI 64)
;OPERATES IN TWO MODES:
;MODE 1:C(AC) HAVE AN INIT'ED CHANNEL NUMBER
;DEVNAM RETURNS SIXBIT DEVICE NAME IN DEVNAM IN AC
;MODE 2: C(AC) ASSUMED TO HAVE SIXBIT LOGICAL DEVICE NAME
;IF ARE GREATER THAN 17. PHYSICAL NAME RETURNED IN AC.
UDEVNM: PUSHJ P,DVCNSG ;SEARCH FOR CHANNEL OR DEVICE
JRST RTZER ;NONE--RETURN ERROR AS 0
TLZ F,-1
CAIE F,DSKDDB## ;T1 IS MORE SPECIFIC THAN 'DSK'
MOVE T1,DEVNAM(F) ;GET PHYSICAL NAME
JRST STOTC1## ;PUT IN AC AND RETURN
SUBTTL REAL-TIME AND HIBWAKE FEATURE
;UUO TO SET JOB TO USE IO IN USER MODE
;AND TO SET PI INTERRUPT LOCATION IN LOWER CORE(WORKS ONLY ON P-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)
IFN FTTRPSET,<
TRPSET::TDZA T3,T3 ;FORCE CALL TO DAERPT
TRPSTU::SETOM T3 ;DON'T CALL DAERPT (DIAG. UUO)
MOVE T2,JBTPRV##(J) ;IS JOB PRIVILEGED TO DO TRPSET UUO?
TLNN T2,PVTRPS ;PVTRPS IS SPECIFIED IN ACCT.SYS AND SETUP BY LOGIN
POPJ P, ;NO, ERROR RETURN
SETZM .CPSTS## ;CLEAR THE STOP TIME SHARING FLAG
IFN FTDAEM,<
JUMPN T3,TRPST0 ;AVOID DAEMON CALL IF NOT TRPSET UUO
HRRZ U,T1 ;SECOND WORD OF ERPTBK IS CONTENTS
HLRZ F,T1 ; OF AC AT TRPSET CALL
MOVE T1,[.SWETP,,.ERSWE] ;EVENT,,ERROR CODES FOR DAEMON
PUSHJ P,DAEDSJ## ;TELL DAEMON TO LOG IT
PUSHJ P,GETTAC## ;RESTORE ARGUMENT
TRPST0:
>
JUMPE T1,TRPST1 ;IS AC 0?(DO NOT SET PI LOC IF YES)
IFN FTMP,<
PUSHJ P,CHKCPU## ;LOCKED? OR GET LOCKED
POPJ P, ;CAN'T RUN ON 0
PUSHJ P,ONCPUN## ;GET ON THE RIGHT CPU
PUSHJ P,GETTAC## ;RESTORE ARGUMENT
>
HLRZ T2,T1 ;NO, SET LOWER CORE
CAIL T2,40 ;IS IT LEGAL LOWER CORE ADR.?
CAIL T2,60
POPJ P, ;NO, ERROR RETURN
IFN FTLOCK,<
PUSHJ P,LOKEVC## ;IF KI10, JOB MUST BE LOCKED IN EVM
; IS IT?
>
POPJ P, ;NO, ERROR RETURN
PUSHJ P,GETTAC## ;RESTORE USER'S AC ARGUMENT TO T1
MOVEM J,.CPSTS## ;SET STOP TIME SHARING FLAG, SO NO OTHER JOBS
; JOBS WILL RUN AND NO CORE SHUFFLING
PUSHJ P,SAVE2## ;SAVE TEMPS
MOVE P1,T2 ;SAVE INTERRUPT LOCATION
HRR M,T1 ;LOCATION OF THE INTERRUPT INSTR
PUSHJ P,GETWDU## ;GET THE INSTRUCTION
MOVE P2,T1 ;SAVE IT
HRR M,T1 ;ADDRESS POINTED TO BY IRP INSTR
PUSHJ P,GETWDU## ;GET THAT
HRRZ U,JBTADR##(J) ;EVA OF THE JOB
ADD P2,U ;RELOCATE THE IRP INSTR
ADD T1,U ;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
PUSHJ P,PUTWDU## ;STORE IT FOR THE USER
ADD P1,.CPTOS## ;ADD IN DRAP OFFSET FOR THIS CPU
EXCH P2,(P1) ;AND STORE IN MONITOR TRAP LOC.
MOVE T1,P2 ;RETURN PREVIOUS CONTENTS TO THE USERS
TRPST1: AOS (P) ;OK RETURN
MOVSI T2,(XC.UIO) ;SET USER IO PC FLAG
IORM T2,.JDAT+JOBPD1## ;IN UUO RETURN PC
JRST STOTAC## ;RETURN PREVIOUS CONTENTS OF PI LOC.
> ;END CONDITIONAL ON FTTRPSET
IFE FTTRPSET,<
TRPSET==:CPOPJ##
>
;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 P-10'S
;UJEN IS A NO-OP ON P-6'S AND SO THIS FACILTY IS GOOD ON P-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
;RTTRP UUO
;LOCK UUO
;HPQ UUO
; HIBERNATE/WAKE UUOS
;SIGN BIT OF UUO AC ARG=1 IF JOB
; WANT TO BE SWAPPED OUT IMMEDIATELY
HIBUUO: PUSHJ P,INCPD1##
IFN FTPI,<
XCT PINOJN ;SKIP IF USER NOT ENABLED FOR TRAPS
SKIPN @JBTPIA##(J) ;ARE THERE ANY PENDING INTERRUPTS
JRST HIBER ; NOT ENABLED OR NONE PENDING
POPJ P, ;EXIT NOW TO GRANT INTERRUPT
>
HIBER:: MOVSI T2,(JS.HIB) ;SET HIBER BIT
IORM T2,JBTST2##(J)
PUSHJ P,HIBER4 ;DO THE UUO
JFCL
MOVSI T2,(JS.HIB) ;CLEAR HIBER BIT
ANDCAM T2,JBTST2##(J)
POPJ P,
HIBER4: PUSHJ P,SAVE1## ;SAVE P1
HLRZ T2,T1 ;GET THE PROTECTION BITS
DPB T2,HIBPRT## ;STORE PROTECTION CODE IN LEFT HALF OF JBTRTD(J)
IFN FTIPCF,<
MOVSI T3,IPCACE## ;CLEAR IPC ACTIVITY ENABLE
ANDCAM T3,JBTRTD##(J)
TRNE T2,IPCUUB## ;USER WANT IPC ACTIVITY?
IORM T3,JBTRTD##(J) ;YES, DO SO
>
MOVSI P1,TTILCE## ;TTY CHARACTER OR LINE MODE BIT
TDNE P1,JBTRTD##(J) ;IS JOB GOING INTO CHARACTER MODE?
PUSHJ P,HIBTTY## ;YES, GO SET UP LINE CHARACTERISTICS
MOVSI T2,WAKEB## ;CHECK IF JOB HAS BEEN AWAKENED
MOVEI P1,SLPQ## ;PREPARE TO PUT JOB IN SLEEP QUEUE
SYSPIF ;GUARD AGAINST WAKEUP AT INTERRUPT LEVEL
TDNN T2,JBTRTD##(J) ;HAS THIS JOB BEEN WOKEN
JRST HIBER1 ;NO, THEN PUT IT TO SLEEP
ANDCAM T2,JBTRTD##(J) ;CLEAR THE WAKE BIT
SYSPIN ;RESTORE THE PI STATUS
JRST CPOPJ1## ;GIVE A SKIP RETURN TO THE USER
HIBER1: DPB P1,PJBSTS## ;STORE THE SLEEP CODE IN JBTSTS WORD
SYSPIN ;RESTORE PI SYSTEM
JUMPGE T1,HIBER2 ;DOES JOB WANT TO BE SWAPPED OUT IMMEDIATELY?
; (HBRSWP SET)
PUSHJ P,ZERIPT## ;YES, MARK HIM AS SWAPPABLE.
PUSHJ P,GETWDU## ;PICKUP. ARGUMENT OF UUO AGAIN
;MORE
HIBER2: AOS (P) ;GIVE SKIP RETURN WHEN JOB WAKES UP
HRRZS T1 ;GET THE SLEEP TIME IN MILLISEC
JUMPE T1,HIBER3 ;IF NO SLEEP TIME, DONT ENTER CLOCK REQUEST
IMUL T1,TICSEC## ;CONVERT TO JIFFIES
IDIVI T1,^D1000 ; FROM MILLISECONDS
SKIPE T2 ;IS THIS AN EVEN NUMBER OF JIFFIES
AOS T1 ;NO, ALWAYS ROUND UP TO NEXT JIFFY
CAILE T1,7777 ;WAS THIS A VERY LARGE NUMBER
MOVEI T1,7777 ;YES, THEN SLEEP THE MAXIMUM TIME
JRST MSLEEP ;GO ENTER SLEEP TIME IN CLOCK REQUEST QUEUE
HIBER3: PUSHJ P,FNPDBS## ;GET THE PDB ADDRESS
PUSHJ P,CLRIPT## ;CLEAR IN-CORE PROTECT TIME
PJRST WSCHED## ;GO RESCHEDULE
;HERE ON A WAKE UUO
WAKUUO::
;HERE FROM RTTRP AT INTERRUPT LEVEL
WAKEUP::JUMPLE T1,WAKEME ;WAKE UP CURRENT JOB ON NEG ARGUMENT
PUSHJ P,LGLPR1## ;IS THIS AN UNREASONABLE REQUEST?
POPJ P, ;YES, GIVE AN ERROR RETURN
PUSHJ P,PRVJ## ;DOES THIS JOB HAVE SPECIAL PRIVELEGES?
JRST WAKOK1 ;YES, WAKE THE JOB UP ALWAYS
EXCH T1,J ;SET UP TO TAKE THE JOB OUT OF SLPQ
LDB T2,HIBPRT## ;GET PROTECTION CODE
TRNE T2,4 ;ONLY-ME PROTECTION?
JRST ONLYME ;YES, MAKE SURE THIS IS RIGHT JOB
TRNE T2,1 ;ALL PROJECTS OK?
JSP T3,CHPRJ ;NO, CHECK THIS PROJECT NUMBER
TRNE T2,2 ;ALL PROGRAMMERS OK?
JSP T3,CHPRG ;NO, CHECK THIS PROGRAMMER NUMBER
JRST WAKEOK ;GO WAKE THE JOB UP
WAKEME: SKIPA T1,J
WAKOK1: EXCH J,T1 ;SET UP J PROPERLY
WAKEOK: MOVSI T2,(JS.HIB) ;JOB DID SLEEP UUO BIT
TDNN T2,JBTST2##(J) ;SLEEP OR HIBER?
JRST SETWAK ;SLEEP, JUST SET WAKE BIT
IFN FTPI,<
MOVE T2,T1 ;GET JOB NUMBER OF WAKER
SIGNAL C$WAKE ;SIGNAL WAKEUP
JRST WAKEIT ;WAKE UP JOB SINCE PSISER DIDN'T
JRST CPOPJ1## ;GIVE SKIP RETURN
>
WAKEIT: MOVEI T1,RNQ## ;PREPARE TO PUT JOB IN THE RUN QUEUE
SYSPIF ;GUARD AGAINST HIGHER PI ACTIVITY
LDB T2,PJBSTS## ;GET CURRENT QUEUE CODE
CAIE T2,SLPQ## ;IS THE JOB IN THE SLEEP QUEUE
JRST NOTSLP ;NO, THEN DONT WAKE THE JOB UP
IFN FTPSCD,<
AOS REQWK## ;COUNT A WAKE
>
WAKOKE::DPB T1,PJBSTS## ;PUT THE JOB IN THE RUN QUEUE
SYSPIN ;TURN THE PI BACK ON
PUSHJ P,SETR2## ;SET A SCHEDULER REQUEST
WAKOKA:
IFN FTHPQ,<
LDB T1,HPQPNT## ;GET CURRENT RUNQUE
JUMPE T1,CPOPJ1## ;IF IT IS TS QUEUE THEN DONT SCHEDULE
MOVSI T2,SWP ;PREPARE TO CHECK IF JOB IS ON DISK
SYSPIF ;GUARD AGAINST HIGH PI WAKE UP
SETOM .CPCKF## ;FLAG THE SCHEDULER FOR CPU
SKIPN .CPRTF## ;IS THERE A FORCED SCHEDULE TO BE DONE
SETOM .CPRTF## ;NO, MARK ONE IS IN PROGRESS FOR CPU
TDNN T2,JBTSTS##(J) ;IS THIS JOB SWAPPED OUT
JRST WAKOK3 ;NO. PROCEED.
SKIPG T2,.CPRTF## ;ANYONE IN .CPRTF?
JRST WAKOK2 ;NO. PUT OUR NUMBER IN IT.
LDB T3,HPQPT2## ;YES. GET HIS HPQ NUMBER
CAMLE T1,T3 ;IS HE AHEAD OF US?
WAKOK2: HRRZM J,.CPRTF## ;NO. PUT OUR NUMBER IN.
WAKOK3: SYSPIN (CLKBIT##+PI.IIO) ;CAUSE AN INTERRUPT ON PI 7
>
JRST CPOPJ1## ;GIVE SKIP RETURN
;WAKJOB IS A ROUTINE WHICH CAN BE CALLED FROM ANY INTERRUPT LEVEL
;TO WAKE UP A HIBERNATING JOB. THE CALLING SEQUENCE IS:
; MOVE T1,JOBNUM ;T1 = # OF JOB TO BE WOKEN
; PUSHJ P,WAKJOB ;WAKE UP JOB
; RETURN ALWAYS
;WAKJOB SAVES ALL ACS EXCEPT T1, T2
WAKJOB::PUSH P,J ;SAVE J
MOVE J,T1
PUSHJ P,WAKEIT ;GO WAKE JOB
PJRST JPOPJ## ;ALWAYS SKIP RETURNS
PJRST JPOPJ## ;RESTORE J AND RETURN
;WAKEJB SAME AS WAKJOB EXCEPT J=JOB#
WAKEJB::PUSHJ P,WAKEIT
POPJ P,
POPJ P,
;WAKPST IS A ROUTINE TO EITHER WAKE UP A HIBERNATING
; JOB OR POST THE WAKE UP IF SLEEPING/RUNNING
; T1=JOB NUMBER
;CLOBBERS T2
WAKPST::MOVSI T2,(JS.HIB) ;IS JOB HIBERNATING
TDNE T2,JBTST2##(T1) ;OR SLEEPING
PJRST WAKJOB ;HIBERNATING, GO WAKE IT NOW
PUSH P,J ;SAVE J
MOVE J,T1 ;COPY JOB NUMBER
PUSHJ P,SETWAK ;POST THE WAKE UP
PJRST JPOPJ## ;ALWAYS NON-SKIP RETURN
PJRST JPOPJ## ;RESTORE J AND RETURN
NOTSLP: CAIE T2,NAPQ## ;NOT SLEEP, IS IT A NAP?
JRST NOTNAP ;NO, SET WAKE BIT
DPB T1,PJBSTS## ;ITS A NAP, CLEAR WAIT STATE
SYSPIN ;TURN ON PIS AGAIN
JRST WAKOKA ;AND RETURN AFTER CHECKING FOR HPQ STUFF
SETWAK: SYSPIF ;GUARD AGAINST PI LEVEL ACTIVITY
NOTNAP: MOVSI T2,WAKEB## ;SET WAKEUP BIT INSTEAD
IORM T2,JBTRTD##(J) ;SET WAKE UP BIT
SYSPIN ;DONT RESCHEDULE
JRST CPOPJ1## ;SKIP RETURN TO CALLER
ONLYME: CAME T1,J ;IS THIS JOB ME
POPJ P, ;NO, GIVE ERROR RETURN
JRST WAKEOK ;YES, GO WAKE THE JOB UP
CHPRJ: HLLZ T4,JBTPPN##(T1) ;GET OBJECT JOB'S PROJECT NUMBER
XOR T4,JBTPPN##(J) ;COMPARE WITH THIS JOB'S PROJECT
MOVSS T4 ;RESULT TO RH
JRST CHPRG1 ;TEST
CHPRG: HRRZ T4,JBTPPN##(T1) ;GET OBJECT JOB'S PROGRAMMER NUMBER
XOR T4,JBTPPN##(J) ;COMPARE WITH THIS JOB'S PROGRAMMER
CHPRG1: TRNE T4,-1 ;SKIP IF EXACT MATCH
POPJ P, ;NO, GIVE ERROR RETURN
JRST (T3) ;OK, KEEP GOING
SUBTTL DAEMON UUO'S AND ROUTINES
IFN FTDAEM,<
;UUO TO REQUEST SERVICE BY DAEMON
;CALL MOVE AC,[XWD +LENGTH,ADDR OF ARG LIST]
; (FIRST ARG = FUNCTION CODE--SEE DAEMON FOR LEGAL FUNCTIONS)
; CALLI AC,102
; ERROR RETURN
; OKAY RETURN
CALDAE: PUSH P,T1 ;SAVE USER ARG AC
PUSHJ P,STDAEM## ;IS DAEMON RUNNING?
JRST TPOPJ## ;NO, ERROR RETURN TO USER-HIS AC UNCHANGED
POP P,T2 ;T2=USER'S AC
HRR M,T2 ;ADR. OF FIRST ARG IN USER AREA
PUSHJ P,GETWDU## ;GET FIRST WORD = FUNCTION
; LEAVE IN T1 FOR DAEMON TO FINE IN DUMP ACS.
MOVEI T3,JDCQ## ;MAKE JOB UNRUNABLE
DPB T3,PJBSTS## ;BY PUTTING IT IN DAEMON WAIT STATE
PUSHJ P,WSCHED## ;CALL SCHEDULER
;DAEMON WILL FIND T1 IN DUMP ACS FOR FUNCTION
; IT WILL RETURN ERROR CODE IN FUMP T1 AND 0/NON-0
; FLAG IN T1+1 IF SKIP/NON-SKIP RETURN
JUMPE T2,STOTC1## ;SKIP RETURN IF OK
JRST STOTAC## ;ERROR RETURN - STORE RETURN IN AC IN ANY CASE
;STILL IN FTDAEM CONDITIONAL
;UUO TO READ OR WRITE ANOTHER JOB'S CORE
;CALL MOVEI AC,ADDR OF 2 WORD ARGUMENT LIST
; JOBPEK AC,
; ERROR RETURN
; NORMAL RETURN
;ADDR: XWD FLAGS+JOB NUMBER,NUMBER OF WORDS TO TRANSFER
; XWD SOURCE ADDRESS,DESTINATION ADDRESS
;FLAGS ARE:
; 1B0 - 0=READ, 1=WRITE
; 1B1 - READ UPMP OF SPECIFIED JOB
; 1B2 - READ EXEC VIRTUAL ADDRESS BETWEEN 340000 AND 377777
; AS IF MAPPED THROUGH SPECIFIED JOB'S MAP
JOBPEK: PUSHJ P,SAVE4## ;SAVE P1-P4
PUSHJ P,PRUSET ;REQUIRES PRIVILEGES
JRST JPKNPV ;NOT PRIVILEGED
TLNE T1,(JK.EVA) ;IF EVM FLAG IS SET, INSURE THAT WRITE
TLZ T1,(JK.WRT!JK.UPM) ; AND UPMP FLAGS ARE CLEARED
HLRZ P1,T1 ;RH P1=OTHER JOB NUMBER
TRZ P1,(JK.ALL) ;CLEAR FLAGS
HLL P1,T1 ;LH P1=FLAGS
HRREI P2,-1(T1) ;P2=LENGTH-1 OF TRANSFER
HRRZ T1,P1 ;T1=OTHER JOB NUMBER
PUSHJ P,LGLPRC## ;SKIP IF LEGAL JOB NUMBER
JRST JPKIJN ;NO, REFUSE TO DO IT
MOVSI T2,SWP ;JOB ON ITS WAY OUT OR IN?
TDNE T2,JBTSTS##(T1) ;LOSE IF SO
JRST JPKSWP ;RETURN IF SWP=1
MOVSI T2,(JS.SIP) ;T2 = JOB IN TRANSIT
SKIPE JBTADR##(P1) ;SKIP IF JOB SWAPPED
TDNE T2,JBTST2##(P1) ;SKIP IF ALL IN CORE
JRST JPKSWP ;NOT IN CORE
CAILE P2,1000-1 ;SKIP IF UNDER MAX
MOVEI P2,1000-1
PUSHJ P,GETWD1## ;GET XWD SOURCE, DESTINATION
PUSH P,T1 ;SAVE T1
TLNE P1,(JK.WRT) ;SKIP IF READ
HLRZS T1 ;ADDR IN OUR JOB
HRRZS T2,T1 ;. .
ADD T2,P2 ;HIGHEST ADDRESS IN OUR JOB
PUSHJ P,TRNGE## ;SEE IF PROCEEDING WILL CAUSE A PAGE FAULT
TLNN P1,(JK.EVA!JK.UPM) ;DON'T CHECK HERE IF FUNNY SPACE
CAIE J,(P1) ;JOBPEK ON SELF?
JRST JOBPK1 ;NO, PROCEED
MOVE T1,(P) ;GET XWD BACK
TLNN P1,(JK.WRT) ;SKIP IF WRITE
HLRZS T1 ;OTHER ADDR IN OUR JOB
HRRZS T2,T1 ; ...
ADD T2,P2 ;HIGHEST ADDR IN JOB
PUSHJ P,TRNGE## ;CHECK IT
JOBPK1: POP P,T1 ;RESTORE XWD
;STILL IN FTDAEM CONDITIONAL
;HERE TO CHECK IF SOURCE ADDR IS FROM HIGH SEGMENT
MOVE P3,JBTADR##(J) ;P3=JBTADR FOR OUR JOB
MOVE T4,JBTADR##(P1) ;T4=JBTADR FOR SPECIFIED JOB
TLNE P1,(JK.WRT) ;SKIP IF READ, NOT IF WRITE
EXCH T4,P3 ;T4=SOURCE JBTADR, P3=DESTINATION JBTADR
HLRZ T3,T4 ;T3=SIZE OF SOURCE LOW SEGMENT
HLRZ T2,T1 ;T2=SOURCE ADDRESS
TLNN P1,(JK.EVA) ;SOURCE IN EVM MAPPED THROUGH USER?
JRST JOBPK2 ;NO
CAIL T2,340000 ;INSURE THAT THE ADDRESS IS IN
CAILE T2,377777 ; THE PER-PROCESS AREA
JRST JPKIAD ;ILLEGAL IF NOT
JRST JOBPK5 ;CHECK DESTINATION ADDRESS
JOBPK2: CAMGE T2,T3 ;SKIP IF SOURCE ADDR GT LOW SEGMENT SIZE
JRST JOBPK4 ;SOURCE ADDRESS IS IN LOW SEGMENT
MOVE T4,JBTSGN##(P1) ;HIGH SEGMENT NUMBER FOR SPECIFIED JOB
TLNE P1,(JK.WRT) ;SKIP IF READ, NOT IF WRITE
MOVE T4,JBTSGN##(J) ;HIGH SEGMENT NUMBER FOR THIS JOB
JUMPE T4,JPKIAD ;EXIT IF SOURCE JOB HAS NO HIGH SEGMENT
CAIGE T3,400000 ;SKIP IF LOW SEGMENT GT 400000 LOCATIONS
MOVEI T3,400000 ;NO, T3=OFFSET FOR HIGH SEGMENT
JUMPL T4,JOBPK3 ;GO IF A SPY SEG.
LDB T3,[POINT 9,JBTUPM##(T4),8] ;HIGH SEG ORIGIN PAGE #
LSH T3,P2WLSH## ;VIRTUAL ADDRESS OF HIGH SEG.
JOBPK3: SUB T2,T3 ;T2=ADDRESS IN SEGMENT FOR TRANSFER
JUMPL T2,JPKIAD ;ILLEGAL ADR IF NEGATIVE
HRL T1,T2 ;ADDRESS IN SEGMENT BACK TO ACTUAL ADDRESS
SKIPL T4 ;SKIP IF SPY SEG
SKIPA T4,JBTADR##(T4) ;T4=JBTADR FOR SOURCE SEGMENT
HRLZS T4 ;T4=XWD LENGTH, START ADDR OF SPYSEG
HLRZ T3,T4 ;T3=SIZE OF SOURCE SEGMENT
;FALL INTO JOBPK4
;HERE TO CHECK IF SOURCE ADDRESS FITS IN SOURCE SEGMENT
JOBPK4: ADD T2,P2 ;SOURCE ADDR+LENGTH OF SEG=LAST ADDR OF SOURCE
CAMLE T2,T3 ;SKIP IF LE LAST ADDR OF SOURCE SEG
JRST JPKIAD ;DOESN'T FIT IN SOURCE SEGMENT
;HERE TO CHECK IF DESTINATION FITS IN DESTINATION SEGMENT
;NOTE THAT DESTINATION MUST BE A LOW SEGMENT - IF A HIGH SEGMENT IS
; SPECIFIED IT WILL BE OUT OF BOUNDS AND HENCE ILLEGAL. THIS IS IN LIEU
; OF DETERMINING APPROPRIATE PRIVILEGES TO WRITE IN HIGH SEGMENT
JOBPK5: HRRZ T2,T1 ;T2=DESTINATION ADDRESS
ADD T2,P2 ;LAST ADDR OF DESTINATION
HLRZ T3,P3 ;T3=SIZE OF DESTINATION SEGMENT
CAMLE T2,T3 ;SKIP IF FITS IN DESTINATION SEGMENT
JRST JPKIAD
;HERE WHEN ADDRESSES ARE VERIFIED TO BE LEGAL
AOJE P2,CPOPJ1## ;EXIT NOW IF 0 WORDS TO TRANSFER
PJRST JOBPKD## ;DO THE BLT AND GIVE SKIP/NON-SKIP
;RETURN
;ERROR CODES RETURNED BY JOBPEK (MORE IN KXSER)
ERCODE JPKNPV,JKNPV% ;NOT PRIVILEGED
ERCODE JPKIJN,JKIJN% ;ILLEGAL JOB NUMBER
ERCODE JPKSWP,JKSWP% ;JOB SWAPPED
ERCODE JPKIAD,JKIAD% ;ILLEGAL ADDRESS
;STILL IN FTDAEM CONDITIONAL
;UUO TO TAKE JOB OUT OF DAEMON QUEUE
;CALL MOVE AC,XWD +LENGTH, ADDR OF ARGUMENT LIST
; CALLI AC,DAEFIN
; ERROR RETURN
; OK RETURN
;FIRST ARG=JOB NUMBER
;REST OF ARGUMENTS=ACCOUNTING INFORMATION
DAEFIN: PUSHJ P,PRUSET ;SEE IF JOB IS PRIVILEGED
POPJ P,
PUSHJ P,LGLPRC## ;SEE IF JOB NUMBER LEGAL
POPJ P, ;NO, ERROR RETURN
EXCH J,T1 ;J=JOB DAEMON HAS FINISHED
PUSHJ P,DAEDON## ;START USER NOW THAT DAEMON IS DONE
JRST CPOPJ1## ;SKIP RETURN
> ;END CONDITIONAL ON FTDAEM
IFE FTDAEM,<
JOBPEK=CPOPJ##
CALDAE=CPOPJ##
DAEFIN=CPOPJ##
>
;UUO TO FORCE A COMMAND FOR A JOB OR A TTY
;CALL MOVE AC,XWD +LENGTH OR 0, ADDR OF ARG LIST
; CALLI AC,FRCUUO
; ERROR RETURN
; OK RETURN
; FIRST ARG=SIXBIT COMMAND TO FORCE
; SECOND ARG=JOB NUMBER OR TTY IOINDEX
FRCUUO: PUSHJ P,PRUSET ;REQUIRES PRIVILEGES
POPJ P, ;NO GOOD
MOVSI T4,MTTFCM## ;MINUS LENGTH OF COMMAND TABLE
CAME T1,TTFCOM##(T4) ;SKIP IF FOUND COMMAND
AOBJN T4,.-1
JUMPGE T4,CPOPJ## ;NO GOOD IF NOT LEGAL COMMAND
CAIN T3,1 ;SUPPLIED A SECOND ARG?
TDZA T1,T1 ;NO, DEFAULT TO ZERO
PUSHJ P,GETWD1## ;YES, GET IT
CAIGE T1,.UXTRM ;LOOK LIKE A TERMINAL?
JRST FRCUU1 ;NO, MUST BE JOB NUMBER
SUBI T1,.UXTRM ;YES, REMOVE OFFSET
CAIL T1,TTPLEN## ;LEGAL TERMINAL?
POPJ P, ;NO, ERROR RETURN
HRRZ U,LINTAB##(T1) ;YES, GET LDB ADDRESS
JRST FRCUU2 ; AND FORCE THE COMMAND ON IT
FRCUU1: SKIPN T1 ;SUBMITTED ZERO SECOND ARGUMENT?
MOVE T1,J ;YES, USE THIS JOB #
PUSHJ P,LGLPRC## ;SKIP IF LEGAL JOB NUMBER
POPJ P,
MOVSI T3,JNA ;DON'T ALLOW FORCED COMMAND IF NOT A JOB
TDNN T3,JBTSTS##(T1) ;JOB NUMBER ASSIGNED?
POPJ P, ;NO, LOSE
HRRZ F,TTYTAB##(T1) ;ADDRESS OF TTY DDB
HRRZ U,DDBLDB##(F) ;GET POINTER TO LDB
JUMPE U,CPOPJ## ;FAIL ON DETACHED JOB
FRCUU2: HRRZ T2,T4 ;T2=INDEX OF COMMAND
PUSHJ P,COMFRL## ;FORCE COMMAND
JRST CPOPJ1## ;OK
POPJ P, ;CAN'T
;SUBROUTINE TO CHECK FOR PRIVILEGES AND RETURN FIRST ARGUMENT
;CALL T1=CONTENTS OF USER'S AC=+LENGTH, ADDR
;RETURN T1=CONTENTS OF USER LOCATION ADDR
; T3=+LENGTH OF ARGUMENT LIST
PRUSET::HRR M,T1 ;SOME CALLERS (EG CAL78.)
HLRZ T3,T1 ;USE LENGTH EVEN IF NOT PRIVILEGED.
PUSHJ P,GETWDU## ;GET FIRST ARGUMENT
PUSH P,T1 ;USER'S AC
PUSH P,T3 ;ARG LIST LENGTH
MOVSI T1,JP.POK ;NOW CHECK PRIVS
PUSHJ P,PRVBIT## ;SKIP RETURN IF NOT
AOS -2(P) ;FUDGE SKIP RETURN TO CALLER FOR PRIV OK
POP P,T3 ;BUT GIVE HIM THIS IN ANY CASE
PJRST TPOPJ##
;UUO TO SET PARAMETERS ON SPOOLED FILES
;CALL: MOVE AC,[N,,E]
; SPPRM. AC,
; ERROR RETURN
; NORMAL RETURN
;
;E: FUNCTION CODE
; CHANNEL # OR DEVICE NAME
; A SPOOLING PARAMETER BLOCK
;
;ERRORS: -1 = ADDRESS CHECK
; 0 = ARG BLOCK TOO SHORT
; 1 = NO SUCH DEVICE
; 2 = DEVICE NOT ASSIGNED OR INITED
; 3 = DEVICE NOT SPOOLED
; 4 = NO FREE CORE FOR SPB
; 5 = ILLEGAL FUNCTION
SPPRM: PUSHJ P,SAVE2## ;SAVE AN AC
HRR M,T1 ;POINT AT ARGUMENT ADDRESS
HLRE P1,T1 ;GET LENGTH IN P1
CAIGE P1,2 ;ENOUGH THERE?
PJRST ECOD0## ;NO, ERROR
PUSHJ P,GETWRD## ;GET FUNCTION
PJRST RTM1
CAIG T1,2 ;CORRECT CODE?
SOSGE P2,T1
PJRST ECOD5## ;NO, LOSE
PUSHJ P,GETWR1## ;GET DEVICE SPEC
PJRST RTM1
PUSHJ P,DVCNSG ;FIND THE DDB
PJRST ECOD1## ;NO SUCH DEVICE
MOVEI T1,ASSCON!ASSPRG ;GET ASSIGNED + INITED BITS
SKIPE P2
MOVEI T1,ASSPRG
TDNN T1,DEVMOD(F) ;IS DDB EITHER
PJRST ECOD2## ;NOPE
SKIPL DEVSPL(F) ;SPOOLED?
JUMPE P2,ECOD3## ;NO, LOSE IF FUNCTION 1
HRRZ T1,DEVSPM##(F) ;IS THERE A SPOOL PARAM BLOCK?
JUMPN T1,SPPRM1 ;YES, USE IT
MOVEI T2,SPBMAX## ;HOW MUCH CORE WE NEED
PUSHJ P,GTFWDC## ;GET THAT CORE
PJRST ECOD4## ;NO FREE CORE
HRRZM T1,DEVSPM##(F) ;REMEMBER WHERE IT IS
HRLZ T2,T1 ;SET ADR,,0
HRRI T2,1(T1) ;ADR,,ADR+1
SETZM 0(T1) ;CLEAR FIRST WORD
BLT T2,SPBMAX##-1(T1) ;CLEAR THE REST
;FALL INTO SPPRM1
SPPRM1: SUBI P1,1 ;ADJUST FOR DEVICE NAME
CAILE P1,SPBMAX## ;BIGGER THAN MAX
MOVEI P1,SPBMAX## ;YES, USE MAX
MOVNS P1 ;MAKE P1 NEGATIVE
HRLS P1 ;MAKE IT A
HRR P1,T1 ;POINTER
SPPRM2: PUSHJ P,GETWR1## ;GET NEXT WORD
PJRST RTM1 ;ADDR CHECK
MOVEM T1,(P1) ;SAVE USERS ARG
AOBJN P1,SPPRM2 ;LOOP FOR ALL ARGS
JUMPE P2,CPOPJ1## ;GOOD RETURN IF FUNCTION 1
PJRST SPLREN## ;FUNCTION 2 LET FILSER RENAME
SUBTTL DEVOP. UUO
;UUO TO PERFORM MISCELLANEOUS DEVICE FUNCTIONS
;
;CALL: MOVE AC,[+N,,ADR]
; DEVOP. AC,0 ;OR CALLI AC,171
; ERROR RETURN
;DEVOP FUNCTIONS ARE EITHER DEVICE INDEPENDENT OR DEVICE DEPENDENT.
; DEVICE INDEPENDENT OPERATIONS ARE HANDLED BELOW, AND DEVICE DEPENDENT
; OPERATIONS ARE HANDLED BY CALLING THE DEVICE SERVICE ROUTINE VIA
; THE DDVO (-4) DISPATCH WITH T1 CONTAINING THE FUNCTION CODE AND F
; POINTING TO THE DDB.
;DEVOP DISPATCH TABLE
; XWD CODE,ADR
DVPDIS: XWD 1,DVPCAL ;(01) LOAD STD VFU (DEP)
XWD 2,DVPCAL ;(02) ENABLE NON-STD VFU LOAD (DEP)
XWD 3,DVPCAL ;(03) DISABLE VFU LOAD
XWD 11,DVPCAL ;(11) LOAD RSX-20F LP RAM
XWD 12,DVPCAL ;(12) LOAD RSX-20F LP VFU
IFN FTMDA,<
XWD 13,DVPMDC ;CLEAR MDA RESTRICTION
XWD 14,DVPMDS ;SET MDA RESTRICTION
>;END IFN FTMDA
XWD 1000,DVPCAL ;READ/SET PAGE CTR (DEP)
XWD 1002,DVPRHC ;READ/SET DEVICE CHAR (IND)
XWD 1003,DVPRES ;READ ERROR STATUS
XWD 1004,DVPCAL ;READ DEVICE STATUS
DVPDSL==.-DVPDIS ;LENGTH OF DISPATCH
;DEVOP ERRORS
DFACS%==-1 ;ADDRESS CHECK
DFIFC%==0 ;ILLEGAL FUNCTION CODE
DFPRV%==1 ;NO PRIVILEGES
DFDIF%==2 ;FUNCTION NOT VALID FOR SPECIFIED DEVICE
DFNLR%==3 ;VALUE OUT OF RANGE
DFNXD%==4 ;NON-EX DEVICE
DFNDV%==5 ;NO DAVFU
DFNIA%==6 ;DEVICE NOT INITED
DFDOL%==7 ;DEVICE IS OFFLINE
DFCNS%==10 ;PAGE COUNTER NOT SET
DFNPC%==11 ;NO PAGE COUNTER
DFENI%==12 ;EXT ERROR RECOVERY NOT IMP
DFNVC%==13 ;NON VARIABLE CHAR SET
DEVOP:: PUSHJ P,SAVE4## ;SAVE AC'S
MOVE P4,T1 ;RELOCATE USER ARG
HRR M,T1 ;LOAD ADDRESS
HLRE T2,T1 ;GET LENGTH
CAIGE T2,2 ;VALID?
PJRST ECOD3## ;NO
PUSHJ P,GETWRD## ;GET FUNCTION CODE
PJRST RTM1 ;OOPS...BAD GUY
JUMPLE T1,RTZER ;BAD FUNCTION
MOVE P1,T1 ;SAVE FUNCTION
PUSHJ P,GETWR1## ;GET NEXT ARG (DEVICE)
PJRST RTM1 ;LOSE
PUSHJ P,DVCNSG ;SEARCH FOR IT
PJRST ECOD4## ;NONE SUCH
IFN FTSPL,<
SKIPN DEVCHR(F) ;IF SPOOLED
PJRST ECOD4## ; LOSE
>
MOVE S,DEVIOS(F) ; AND S
MOVE T1,P1 ;GET FUNCTION
MOVE T2,T1 ;COPY INTO T2
TRNE T2,2000 ;CHANGE SET INTO
TRON T2,1000 ;+ READ FOR COMPARE
TRZ T2,2000 ;BUFFER NET CUSTOMER ARG.
HRLZI T3,-DVPDSL ;LOAD AOBJN POINTER
DEVOP1: HLRZ T4,DVPDIS(T3) ;GET CODE
HRRZ P1,DVPDIS(T3) ;GET DISPATCH
CAMN T2,T4 ;MATCH?
JRST (P1) ;YES, DISPATCH T1=FUNCTION
AOBJN T3,DEVOP1 ;NO, LOOP
PJRST ECOD0## ;ILLEGAL FUNCTION CODE
;HERE TO CALL DEVICE SERVICE ROUTINE
DVPCAL:
IFN FTMP,<
PUSHJ P,SETCPF## ;GET ON CPU WHICH OWNS DEVICE
>
HRRZ T2,DEVSER(F)
PJRST DDVO(T2) ;CALL THE SERVICE ROUTINE
;HERE TO RETURN ERROR STATUS
DVPRES: TRNE T1,2000 ;SET?
PJRST ECOD0## ;YES, ILLEGAL
LDB T1,PDVESE##
PJRST STOTC1##
;HERE TO READ/SET HARDWARE CHARACTERISTICS
DVPRHC: MOVE T2,T1
MOVE T1,DEVHCW(F) ;GET HCW WORD
TRNE T2,1000 ;READ?
PJRST STOTC1## ;YUP, RETURN
PUSHJ P,PRVJ## ;IS JOB PRIVILEGED?
SKIPA ;YES, SKIP
PJRST ECOD1## ;NO.
PUSHJ P,GETWR1## ;GET THE CHARS
PJRST RTM1 ;ADDRESS CHECK
MOVEM T1,DEVHCW(F) ;STORE
PJRST CPOPJ1## ;AND RETURN
IFN FTMDA,<
;HERE TO CLEAR 'CONTROLLED BY MDA BIT
DVPMDC: SKIPA T3,[ANDCAM T2,DEVCHR(F)]
;HERE TO MAKE A DEVICE CONTROLLED BY MDA
DVPMDS: MOVE T3,[IORM T2,DEVCHR(F)]
CAME J,MDAJOB## ;IS THIS MDA?
PJRST ECOD1## ;NO, TOO BAD
MOVE T2,DEVMOD(F) ;IF A DISK
TLNE T2,DVDSK
PJRST ECOD2## ; FORGET IT
MOVSI T2,DVCMDA ;YES, GET THE BIT
XCT T3 ;SET/CLEAR THE BIT
PJRST CPOPJ1## ;WIN
>;END IFN FTMDA
SUBTTL FILOP. UUO
;UUO TO PERFORM FILE OPERATIONS
;CALL WITH:
; MOVE AC,[N,,E]
; FILOP. AC,
; ERROR RETURN
; NORMAL RETURN
;
;BITS IN THE LH OF FOPFLG
FOP.SA==(1B0) ;THIS FILOP. DOES BOTH A LOOKUP AND
; AN ENTER. WE MUST SAVE ARGUMENTS TILL
; THE ENTER
FOP.LK==(1B1) ;DO A LOOKUP
FOP.EN==(1B2) ;DO AN ENTER
FOP.MA==(1B3) ;MULTI-ACCESS UPDATE
FOP.AP==(1B4) ;APPEND
FOP.PV==(1B5) ;REQUESTING PRIVS.
FOP.NS==(1B6) ;DO NOT SUPERSEDE
FOP.UR==(1B7) ;JUST UPDATE RIB
FOP.NF==(1B8) ;LIT IF INPUT FILE NOT FOUND ON APPEND OR UPDATE
FOP.AL==(1B9) ;PRE-ALLOCATE
FOP.RN==(1B10) ;THIS FILOP. DOES A RENAME
FOP.DL==(1B11) ;THIS FILOP. DELETES THE FILE
FOP.SO==(1B12) ;SUPER I/O
FOP.XC==(1B13) ;EXTENDED CHANNEL
FOPTAB: ;DISPATCH TABLE FOR FILOP.
EXP FOPILU ;(00) ILLEGAL
XWD FOP.LK,FOPEN ;(01) READ
XWD FOP.NS+FOP.EN,FOPEN ;(02) CREATE
XWD FOP.EN,FOPEN ;(03) CREATE OR SUPERSEDE
XWD FOP.SA+FOP.LK+FOP.EN,FOPEN ;(04) UPDATE
XWD FOP.SA+FOP.LK+FOP.EN+FOP.MA,FOPEN ;(05) MULTI-ACCESS UPDATE
XWD FOP.SA+FOP.LK+FOP.EN+FOP.AP,FOPEN ;(06) APPEND
EXP FCLOS ;(07) CLOSE
XWD FOP.UR,FCLOS ;(10) UPDATE RIB
EXP FUSTI ;(11) USETI
EXP FUSTO ;(12) USETO
XWD FOP.RN+FOP.LK,FOPEN ;(13) RENAME
XWD FOP.RN+FOP.DL+FOP.LK,FOPEN ;(14) DELETE
XWD FOP.EN+FOP.AL,FOPEN ;(15) PREALLOCATE
XWD FOP.SO,FOPEN ;(16) OPEN FOR SUPER I/O
EXP FOPIN ;(17) INPUT
EXP FOPOUT ;(20) OUTPUT
EXP FOPSST ;(21) SETSTS
EXP FOPGST ;(22) GETSTS
EXP FOPREL ;(23) RELEASE
EXP FOPWAT ;(24) WAIT FOR I/O TO STOP
EXP FOPSEK ;(25) SEEK
EXP FOPRRC ;(26) REWRITE RIB IF CHANGED
FOPMAX==.-FOPTAB-1 ;MAXIMUM FUNCTION
SALL
FILOP: FRAME <FOPFLG,FOPAP,FOPTMP,FOPBLK,FOPEXT>
HRRZM T1,FOPAP ;ADDRESS OF ARG LIST
HLLM M,FOPAP ;AC #
HLRE T2,T1 ;GET ARGUMENT COUNT
JUMPLE T2,FCLOSI ;ILLEGAL IF NEGATIVE OR ZERO
HRR M,T1 ;POINT TO FIRST ARGUMENT
PUSHJ P,GETWDU## ;GET FIRST ARGUMENT
TLZE T1,(1B0) ;DOES HE WANT TO BE PRIV'D?
TLO T2,FOP.PV ;YES--REMEMBER THAT
TLZE T1,(1B1) ;ASSIGN A FREE CHANNEL?
TLO T2,FOP.XC ;YES, REMEMBER THAT
PUSHJ P,PRVJO## ;IS HE PRIV'ED
TLZ T2,FOP.PV ;NO, CLEAR THE BIT
HLRZ P1,T1 ;REMEMBER CHANNEL #
TLZ T1,177777 ;CLEAR OUT CHAN #
CAIGE P1,HIGHXC## ;OUT OF RANGE?
CAILE T1,FOPMAX ;FUNCTION TOO BIG?
JRST FOPILU ;YES--ERROR
TLNE T2,FOP.XC ;ASSIGN AN EXTENDED CHANNEL?
JUMPN P1,FOPILU ;YES, NUMBER FIELD MBZ
HLLZ T3,FOPTAB(T1) ;GET FLAGS
IORB T2,T3 ;MAKE FLAGS,,LEN
MOVEM T2,FOPFLG ;SAVE THE FLAGS
HRRZ T2,FOPTAB(T1) ;FUNCTION
PUSHJ P,SETUF ;NO, SETUP F
JRST [CAIE T2,FOPEN ;OPEN?
JRST FCLOSI ;NO, IOIMPM
JRST .+1] ;YES, PROCEED
HRLM P1,.UPMP+.UPCTA ;STORE UDX FOR THIS UUO
CAIE T2,FOPEN ;OPEN?
JRST (T2) ;NO, JUST DISPATCH
CAILE P1,17 ;YES, TRADITIONAL CHANNEL?
TLNE T3,FOP.XC ;NO, ASSIGN AN EXTENDED CHANNEL?
JRST (T2) ;DISPATCH BY FUNCTION
JUMPE F,FOPILU ;EXTENDED CHANNEL, ILLEGAL IF NOT ALREADY OPEN
JRST (T2) ;DISPATCH
;ROUTINE TO GET NEXT INITED CHAN. DDB.
;CALL - P1 CHANNEL TO START FROM
;RETURNS - CPOPJ - NO MORE INITED CHANS
; - CPOPJ1 - T1 POINTS TO DDB
; P1 HAS CHAN # +1
NXTCH:: CAIGE P1,HIGHXC##
SKIPGE USRHCU##
POPJ P,
HRRZ T1,.UPMP+.UPCTA
CAILE P1,17
JUMPE T1,CPOPJ##
PUSH P,F
NXTCH1: PUSHJ P,SETUF
JRST [CAIE P1,HIGHXC##
AOJA P1,NXTCH1
JRST FPOPJ##]
HRRZ T1,F
AOJA P1,FPOPJ1##
;SUBROUTINE TO SETUP F TO POINT TO THE DDB ASSOCIATED WITH THE USERS CHANNEL
; PRESERVES T2,T3
SETUF:: PUSHJ P,SAVE1## ;SAVE P1
SETZ F, ;ASSUME NO DDB
HRRZS P1 ;ZERO LEFT HALF - PHYSICAL ONLY BIT?
HRRZ T1,.UPMP+.UPCTA ;ADDRESS OF EXTENDED CHANNEL TABLE
CAIG P1,17 ;TRADITIONAL CHANNEL?
JRST SETUF1 ;YES
JUMPE T1,CPOPJ## ;NO, ERROR IF NO EXTENDED CHANNEL TABLE
ADD T1,P1 ;ADDRESS OF THE DDB
CAIGE P1,HIGHXC## ;HIGHER THAN HIGHEST ALLOWED?
SKIPN F,-20(T1) ;AND IS THERE A DDB?
POPJ P, ;ERROR
JRST SETUF2 ;GOOD RETURN, F SETUP
SETUF1: CAMG P1,USRHCU## ;A LEGAL CHANNEL?
SKIPN F,USRJDA##(P1) ;AND HAS IT BEEN OPENED?
POPJ P, ;NO, ERROR
SETUF2: MOVE S,DEVIOS(F) ;SETUP I/O STATUS
JRST CPOPJ1## ;YES, GOOD RETURN, F SETUP
;HERE FOR FUNCTIONS WHICH OPEN A FILE
FOPEN: HRRZ T4,FOPFLG ;GET ARG COUNT
CAIGE T4,4 ;MUST BE AT LEAST 4
JRST FOPILU ;ELSE ILL UUO ERROR
CAIGE T4,6 ;LOOKUP / ENTER GIVEN?
JRST FOPVMX ;NO--ALL VALID
HRRI M,5(M) ;POINTER TO LOOKUP/ENTER BLOCK
PUSHJ P,GETWDU## ;GET POINTER
HRR M,T1 ;PUT IN GOOD AC
HLRZ P2,T1 ;ADDRESS OF THE RENAME BLOCK
PUSHJ P,FCLERB ;CHECK LOOKUP/ENTER/RENAME BLOCK
JUMPE P2,FOPEN0 ;JUMP IF NO RENAME BLOCK
HRR M,P2 ;ADDRESS OF THE RENAME BLOCK
PUSHJ P,FCLERB ;MAKE SURE THATS IN CORE
FOPEN0: CAIGE T4,7 ;PATH POINTER
JRST FOPVMX ;NO--ALL IS WELL
HRR M,FOPAP ;GET ARG POINTER
HRRI M,6(M) ;PATH PTR
PUSHJ P,GETWDU## ;GET ARGUMENT
JUMPE T1,FOPVMX ;JUMP IF PATH ISN'T REQUIRED
HLRZ T2,T1 ;COPY LENGTH
ADDI T2,(T1) ;END ADDRESS
TLZ T1,-1 ;START ADDRESS
PUSHJ P,TRNGE## ;TEST RANGE
FOPVMX: MOVSI T1,FOP.XC ;EXTENDED CHANNEL REQUESTED BIT
TDNN T1,FOPFLG ;WAS AN EXTENDED CHANNEL REQUESTED?
JRST FOPVM4 ;NO, PROCEED TRADITIONALLY
HRRZ T1,.UPMP+.UPCTA ;AN EXTENDED CHANNEL TABLE ALREADY SETUP?
JUMPN T1,FOPVM1 ;YES, FIND A FREE CHANNEL
MOVEI T2,HIGHXC##-20 ;NO, ALLOCATE AN EXTENDED CHANNEL TABLE
PUSHJ P,GTFWDC## ;GET FUNNY WORDS CACHED
JRST FOPOER ;NONE AVAILABLE
HRRM T1,.UPMP+.UPCTA ;STORE THE ADDRESS OF THE XCT
MOVSI T2,(T1) ;FORM A BLT POINTER
HRRI T2,1(T1) ; ..
SETZM (T1) ;ZERO FIRST WORD OF THE TABLE
BLT T2,HIGHXC##-21(T1) ;ZAP, THE TABLE IS INITIALIZED
;HERE WITH T1 = ADDRESS OF THE EXTENDED CHANNEL TABLE
FOPVM1: MOVEI P1,0 ;START AT THE BEGINNING OF THE TABLE
FOPVM2: MOVE T2,T1 ;ADDRESS OF THE TABLE
ADD T2,P1 ;PLUS CURRENT CHANNEL NUMBER
SKIPN (T2) ;CHANNEL IN USE?
JRST FOPVM3 ;NO, AVAILABLE
CAIGE P1,HIGHXC##-20 ;YES, LOOKED AT THE ENTIRE TABLE?
AOJA P1,FOPVM2 ;NO, LOOP OVER ENTIRE TABLE
JRST FOPOER ;ERROR
;HERE WHEN AN AVAILABLE CHANNEL WAS FOUND
FOPVM3: ADDI P1,20 ;EXTENDED CHANNEL NUMBER
;STORE CHANNEL NUMBER FOR THE USER
FOPVM4: HRLM P1,.UPMP+.UPCTA ;CHANNEL NUMBER
HRR M,FOPAP ;GET ARGUMENT POINTER
PUSHJ P,GETWDU## ;GET CHANNEL NUMBER
DPB P1,[POINT 9,T1,17] ;STORE POSSIBLE EXTENDED CHANNEL NUMBER
TLZ T1,(1B1) ; AND CLEAR THE ASSIGN EXT CHAN BIT
PUSHJ P,PUTWDU## ;STORE THAT FOR THE USER
HRRI M,1(M) ;POINT TO OPEN BLOCK
MOVE T1,.UPMP+.UPFOP
MOVEM T1,FOPEXT
MOVE P2,FOPFLG ;FLAGS
TLNE P2,FOP.RN+FOP.DL ;RENAMES OR DELETES
JUMPN F,[TLNE F,LOOKB!ENTRB ;YES -- ACTIVE LOOKUP OR ENTER
JRST FOPEN2 ;YES -- SKIP THE OPEN
JRST .+1] ;NO -- DO THE OPEN
TLO M,400000 ;INDICATE FROM FILOP
PUSHJ P,UOPEN ;TRY TO OPEN
JRST FOPOER ;CAN NOT OPEN
TLZ M,400000
HRRZ T1,FOPFLG ;GET ARG COUNT
CAIN T1,4 ;ONLY DOING AN OPEN?
JRST FOPWIN ;YES--GIVE THE GOOD RETURN
HRR M,FOPAP ;GET ARGUMENT POINTER
HRRI M,4(M) ;POINT TO BUFFER WORD
PUSHJ P,GETWDU## ;GET THE WORD
MOVEM T1,FOPTMP ;SAVE FOR A BIT
HLRE T2,T1 ;GET THE NUMBER OF OUTPUT
; BUFFERS REQUESTED
JUMPE T2,FOPEN1 ;NONE--SKIP OUTBUF
SKIPN T1,FOPEXT
MOVE T1,.JDAT+JOBFF##
MOVEM T1,.JDAT+JOBFF##
MOVEM T1,.UPMP+.UPFOP
SKIPG T2 ;SKIP IF NUMBER GIVEN
MOVEI T2,0 ;ELSE USE DEFAULT
HRR M,T2 ;PUT IN M
PUSHJ P,UOUTBF ;DO THE OUTBUF
FOPEN1: HRRE T1,FOPTMP ;GET THE NUMBER OF INPUT
; BUFFERS REQUESTED
JUMPE T1,FOPEN2 ;JUMP IF NONE REQUESTED
SKIPG T1 ;TURN -1 INTO
MOVEI T1,0 ; ZERO
HRR M,T1
PUSHJ P,UINBF ;BUILD BUFFERS
;HERE TO DO LOOKUP AND/OR ENTER
FOPEN2: HRRZ T1,FOPFLG ;GET # OF ARGUMENTS
CAIN T1,5 ;DONE YET?
JRST FOPWIN ;YES--GIVE SKIP RETURN
HRR M,FOPAP ;GET ARG POINTER
HRRI M,5(M) ;GET POINTER TO LOOKUP BLK
PUSHJ P,GETWDU## ;GET THE POINTER
HRR M,T1 ;SAVE ADDRESS OF BLOCK
HRRM M,FOPBLK ;SAVE ADDRESS FOR LATER
PUSHJ P,GETWDU## ;GET FIRST WORD
MOVE T2,DEVMOD(F) ;GET DEVCHR BITS
TLNE T2,DVDSK ;SKIP IF THIS IS NOT A DISK
TLNE T1,-1 ;SKIP IF EXTENDED UUO
JRST FOPEN3 ;NO DISK OR NOT EXTENDED
TLO P1,400000 ;EXTENDED - INDICATE THAT
HRRI M,UUXNAM(M) ;POINT TO FILE NAME
SKIPA T2,T1 ;YES--COPY COUNT TO T2
FOPEN3: MOVEI T2,4 ;NO--4 WORD BLOCK
TRZ T2,400000 ;IN CASE OF OLD FORMAT
HRLM T2,FOPBLK ;SAVE COUNT
MOVEI T3,UUNEXT-UUNNAM(M) ;WHERE TO FIND EXTENSION
HRLZM T3,FOPEXT ;REMEMBER FOR LATER
MOVE P2,FOPFLG ;GET FLAGS
MOVSI T1,DEPFOP ;WANT TO SET "FILOP. IN PROGRESS BIT"
TLNN P2,FOP.PV ;DOES HE WANT FULL FILE ACCESS
TLO T1,DEPFFA ;NO--MAKE SURE HE DOES NOT GET IT
IORM T1,DEVJOB(F) ;TURN ON BITS IN DDB
TLNE T1,DEPFFA ;PRIVILEGED INVOKING PRIVILEGES?
TDZA T1,T1 ;NO
MOVSI T1,(UP.PFO) ;YES
IORM T1,.UPMP+.UPBTS ;FOR ACCESSOR'S IPCF CAPABILITIES
MOVEI T1,DEPECS ;NON-SUPERSEDING ENTER
ANDCAM T1,DEVSTA(F) ;CLEAR TO START WITH
TLNE P2,FOP.NS ;WANT TO SUPERSEDE?
IORM T1,DEVSTA(F) ;NO--TELL FNDFIL SUPERSEDE IS ILLEGAL
HRRZ T1,FOPFLG ;# OF ARGUMENTS
MOVE T2,DEVMOD(F) ;DEVICE CHARACTERISTICS
CAIL T1,10 ;8TH ARGUMENT SPECIFIED?
TLNN T2,DVDSK ;ONLY IF A DSK
JRST FOPN3A ;NO
HRR M,FOPAP ;GET ARGUMENT POINTER
HRRI M,7(M) ;POINT TO "IN YOUR BEHALF" PPN
PUSHJ P,GETWDU## ;GET IT
TLNE P2,FOP.PV ;DON'T STORE IF NOT A PRIV'ED PROGRAM INVOKING PRIVS
MOVEM T1,DEVUPP##(F) ;STORE IT FOR FNDFIL
FOPN3A: JUMPGE P2,FOPEN4 ;JUMP IF NOT BOTH LOOKUP AND ENTER
;HERE IF BOTH LOOKUP AND ENTER MUST BE DONE. WE CHANGE THE LENGTH OF
; THE BLOCK (IF REQUIRED) SO THAT WORDS LIKE .RBALC, .RBPOS ETC. ARE
; NOT STORED BUT ARE INSTEAD ARGUMENTS TO THE ENTER.
HLRZ T1,FOPBLK ;REMEMBER SIZE
IFN FTDSIM,<
TLNN P2,FOP.MA ;SIMULTANEOUS UPDATE?
>
CAIGE T1,UUXSIZ+1 ;5 OR MORE WORDS?
JRST FOPEN5 ;NO--DO NOT SAVE ANYTHING
HRR M,FOPBLK ;ADDRESS OF BLOCK
MOVEI T1,UUXPRV+1 ;ONLY NEED PPN/FILE/EXT
PUSHJ P,PUTWDU## ;DON'T LOOK BEYOND
FOPEN4: TLNN P2,FOP.LK ;LOOKUP NEEDED?
JRST FOPEN7 ;NO--SKIP TO ENTER
FOPEN5: HLR M,FOPEXT ;GET EXTENSION ADDRESS
PUSHJ P,GETWDU## ;GET THE EXTENSION
HRRM T1,FOPEXT ;SAVE DATE BITS
SKIPL P1 ;POINT AT PPN WORD -1
AOSA M
SUBI M,UUXEXT-UUXPPN+1
PUSHJ P,GETWD1## ;GET USERS PPN
MOVEM T1,FOPTMP ;AND SAVE IT FOR ENTER
HRR M,FOPBLK ;GET POINTER
MOVE T4,DEVSER(F) ;SETUP FOR DISPATCH
MOVSI T1,DVIN ;ATTEMPTING INPUT
HLRZ T2,FOPEXT ;ADDRESS OF EXT WORD
TLNN F,LOOKB+ENTRB ;RENAME, FILE ALREADY OPEN?
PUSHJ P,FOPTS ;CHECK DEVICE CHARACTERISTICS
JRST FOPFNF ;SHORT DISPATCH VECTOR
PUSHJ P,UDLK ;DO THE LOOKUP
JRST FOPLER ;LOOKUP ERROR
FOPFNF: ;HERE ON UPDATE OR APPEND FILE NOT FOUND
HRR M,FOPBLK ;POINT TO BLOCK
HLRZ T1,FOPBLK ;GET LENGTH
CAIL T1,UUXPRV+1 ;LONG BLOCK?
PUSHJ P,PUTWDU## ;YES--STORE COUNT BACK
FOPEN7: TLNN P2,FOP.EN ;NEED AN ENTER?
JRST FOPEN8 ;NO--CHARGE AHEAD
HRR M,FOPBLK ;GET BLOCK ADR
SKIPGE P1 ;IF EXTENDED UUO
AOSA M ;POINT M AT THE PPN WORD
HRRI M,UUNPPN-UUNNAM(M) ;POINT TO PPN WORD
MOVE T1,FOPTMP ;INDICATE ENTER IN SAME DIRECTORY AS LOOKUP
TLNE P2,FOP.LK ;DON'T RESTORE PPN WORD IF LOOKUP
; WASN'T DONE.
PUSHJ P,PUTWDU## ;..
IFN FTDSIM,<
MOVE T1,FOPFLG
MOVSI T2,DEPSIM ;IF SIMULTANEOUS ACCESS,
TLNE T1,FOP.MA ;...
IORM T2,DEVJOB(F) ;LIGHT A BIT IN THE DDB
>
MOVEI T1,DEPPAL## ;IF PREALLOCATE,
TLNE P2,FOP.AL
IORM T1,DEVPAL##(F) ;TELL FILUUO
HRR M,FOPBLK ;GET BLOCK POINTER
MOVE T4,DEVSER(F) ;SETUP T4 FOR UDEN
MOVSI T1,DVOUT ;ATTEMPTING OUTPUT
HLRZ T2,FOPEXT ;ADDRESS OF EXT WORD
PUSHJ P,FOPTS ;CHECK DEVICE CHARACTERISTICS
JRST FOPEN8 ;SHORT DISPATCH VECTOR
PUSHJ P,UDEN ;DO THE ENTER
JRST FOPEER ;ENTER ERROR
FOPEN8: TLNN P2,FOP.RN ;RENAME FUNCTION?
JRST FOPN8A ;NO, PROCEED
HRR M,FOPAP ;ARGUMENT POINTER
HRRI M,5(M) ;POINT TO RENAME/DELETE BLOCK
PUSHJ P,GETWDU## ;GET ADDRESS OF RENAME/DELETE BLOCK
HLR M,T1 ;ADDRESS OF BLOCK TO M
HRRM M,FOPBLK ;SAVE ADDRESS OF THE BLOCK
PUSHJ P,GETWDU## ;FIRST WORD OF THE BLOCK
TLNN T1,-1 ;EXTENDED BLOCK
HRRI M,UUXNAM(M) ;YES, POINT AT THE FILE NAME
MOVEI T1,0 ;ASSUME DELETE
TLNE P2,FOP.DL ;IS IT THE DELETE FUNCTION?
PUSHJ P,PUTWDU## ;YES, STORE A ZERO IN THE RENAME BLOCK
MOVEI T1,UUNEXT-UUNNAM(M) ;WHERE THE EXTENSION IS STORED
HRLZM T1,FOPEXT ;SAVE THAT IN CASE OF AN ERROR
MOVE T1,DEVMOD(F) ;DEVICE CHARACTERISTICS
TLNN T1,DVLNG ;LONG DISPATCH VECTOR?
JRST FOPN8A ;NO, DON'T ATTEMPT A RENAME
HRR M,FOPBLK ;RESTORE ADDRESS OF THE RENAME BLOCK
MOVSI T1,DEPFFA ;SO THE CLOSE WILL HAPPEN
ANDCAM T1,DEVJOB(F) ; IN FILUUO (CLRSTS)
MOVE T4,DEVSER(F) ;ADDRESS OF DEVICE DISPATCH VECTOR
PUSHJ P,URENAM ;DO THE RENAME
JRST FOPLER ;RENAME ERROR
FOPN8A: HRRZ T1,FOPFLG ;GET # OF ARGUMENTS
CAIGE T1,7 ;PATH BLOCK GIVEN
JRST FOPEN9 ;NO--ALL IS WELL
HRR M,FOPAP ;GET ARG POINTER
HRRI M,6(M) ;POINT TO PATH WORD
PUSHJ P,GETWDU## ;FETCH POINTER
MOVEM T1,FOPTMP ;SAVE IN PDL
HRR M,T1 ;PATH BLOCK
HLRZ T1,T1 ;GET SIZE
CAIGE T1,3 ;INTERESTING CASE
JRST FOPEN9 ;NO--RETURN
HRRZ T1,P1 ;CHANNEL #
PUSHJ P,PUTWDU## ;STORE FOR PATH. UUO
MOVE T1,FOPTMP ;PRESET AC
TLO M,400000 ;SO FTUUUO DOESN'T CLOBBER USER'S AC
PUSHJ P,PTHUUO## ;DO THE PATH UUO
JFCL ;SHOULD NEVER FAIL
TLZ M,400000
HRLM P1,.UPMP+.UPCTA ;RESET IO CHAN
PUSHJ P,SETUF ;F GOT WIPED
JRST FOPXI1 ;CAN'T HAPPEN
FOPEN9: MOVE P2,FOPFLG ;GET FLAGS
TLNN P2,FOP.NF ;CREATING INSTEAD OF UPDATING
JRST FOPN9A ;NO--CONTINUE
MOVSI T1,DEPFFA ;YES--FORCE FILE INTO
IORM T1,DEVJOB(F) ; UPDATE MODE
HRRI M,0 ;NO SPECIAL STUFF
PUSHJ P,CLOSE1 ; ..
PUSHJ P,WAIT1## ; ..
FOPN9A: SKIPE P2,FOPFLG ;GET FLAGS
TLNN P2,FOP.AP ;WANT TO APPEND?
JRST FOPWIN ;NO--ALL DONE
MOVE T1,DEVMOD(F) ;IS THIS A DISK
TLNE T1,DVTTY ;NUL:?
JRST FOPWIN ;YES, DONE
TLNN T1,DVDSK ; ..
JRST FOPN11 ;NO, ALL DONE UNLESS AN MTA
;HERE TO APPEND TO A DISK FILE
FOPN9B: MOVE S,DEVIOS(F) ;GET STATUS BITS
HRRZ T3,DEVACC##(F) ;ADDRESS OF A.T.
MOVE T1,ACCWRT##(T3) ;SIZE OF FILE IN BLOCKS
LDB T2,PIOMOD## ;GET THE MODE
CAIL T2,SD ;DUMP MODE?
JRST FOPN10 ;YES--CAN NOT MERGE DATA
LDB T2,ACZLBS## ;WORD IN LAST BLOCK
TRNN T2,BLKSIZ##-1 ;IF FULL THERE IS NO NEED
JRST FOPN10 ; TO READ IT
;AT THIS POINT WE READ C(T2) WORDS FROM BLOCK C(T1) INTO BUFFER AT C(T3)
MOVEM T2,FOPBLK ;SAVE WORD COUNT
MOVEM T1,FOPTMP ;SAVE BLK #
HLRZ U,DEVBUF(F) ;GET RING ADR
PUSHJ P,OUTF ;ZERO BUFFER
HRRZ T3,DEVOAD(F) ;READ TO HERE
MOVN T2,FOPBLK ;NEG. WORD COUNT
HRLZ T2,T2 ; ..
HRRI T2,1(T3) ; ..
HRLM T2,DEVUVA##(F) ;SAVE IN CASE CHECKSUM NEEDED
MOVEM T2,DEVDMP##(F) ;SAVE IN DDB
MOVE W,FOPTMP ;BLOCK #
PUSHJ P,FUSETO## ;SETUP POINTERS
MOVEM S,FOPTMP ;SAVE STATUS
TRO S,D ;SET DUMP MODE
TLZ S,IO ;READING
PUSHJ P,UUOSET## ;MAKE EVERYTHING OK
JFCL ;CAN NOT MISS
PUSHJ P,UUOPWQ## ;DO THE I/O
PUSHJ P,PWAIT1## ;WAIT FOR IT
ANDI S,740000 ;PRESERVE ERROR BITS
IORB S,FOPTMP ;RESTORE OLD MODE
MOVEM S,DEVIOS(F) ;SAVE IN DDB
MOVEI J,BLKSIZ## ;WORDS IN BUFFER
SUB J,FOPBLK ;MINUS WORDS WE READ
HLRZ U,DEVBUF(F) ;RING HEADER
HRRZ T2,DEVOAD(F) ;FOR BYTE POINTER
ADD T2,FOPBLK
PUSHJ P,IOSETC ;STORE CORRECT DATA IN HEADER
MOVE J,.CPJOB## ;RESET J
MOVE T1,DEVREL##(F) ;LAST BLOCK WRITTEN
SUBI T1,2 ;REWRITE IT
FOPN10: AOS W,T1 ;BLOCK TO WRITE
PUSHJ P,FUSETO## ;SET POINTERS
JRST FOPWIN ;ALL DONE
FOPN11: TLNN T1,DVMTA ;MAGTAPE?
JRST FOPWIN ;NO, ALL DONE
HRRI M,16
PUSHJ P,DOMTAP ;YES, SKIP TO EOF
JRST FOPXIT ;IO ERROR, LOSE
HRRI M,7
PUSHJ P,DOMTAP ;BACKSPACE OVER EOF
JRST FOPXIT
LDB T1,PIOMOD##
CAIL T1,SD ;IF DUMP MODE,
JRST FOPWIN ; WE ARE DONE
PUSHJ P,DOMTAP ;BACKSPACE OVER LAST DATA RECORD
JRST FOPXIT ;IO ERROR
HLRZS U,DEVBUF(F) ;TURN OUTPUT HDR INTO INPUT HDR
PUSHJ P,OUTF ;ZERO BUFFER
HRRZ T1,DEVOAD(F)
HRRM T1,DEVIAD(F) ;READ INTO OUTPUT BUFFER
EXCTUX <MOVE T2,@T1> ;PICK UP PNTR TO NEXT BUF
EXCTUU <HRRM T1,@T1> ;TURN IT INTO A 1-BUFFER INPUT RING
MOVEM T2,FOPTMP ;SAVE NEXT BUFFER LOC
PUSHJ P,TPMIN## ;READ IN THE LAST RECORD
TLO F,OUTPB ;IN CASE CLOSE WITH NO OUTPUTS -
PUSHJ P,JDAADR
MOVEM F,(T1) ; TAPUUO WILL IGNORE IF OUTPB=0
PUSHJ P,WAIT1## ;WAIT FOR IT
MOVE U,DEVBUF(F) ;TURN IT BACK INTO AN OUTPUT HDR
HRLZM U,DEVBUF(F) ;CANT DO INPUT AFTER WRITING A TAPE
HRRZ T1,DEVOAD(F) ;WHERE WE READ
MOVE T3,FOPTMP
EXCTUU <MOVEM T3,@T1> ;RESTORE BUFFER RING
EXCTUX <MOVE T2,1(T1)> ;PICK UP WORDCOUNT
HLRZ J,T3 ;MAX WORDCOUNT(+1) OF BUFFER
SUBI J,1(T2) ;AMOUNT LEFT
JUMPE J,FOPN12 ;INIT NEW BUFFER IF NO ROOM IN THIS ONE
ADDI T2,(T1) ;POINT T2 TO LAST DATA IN BUFFER FOR IOSETC
PUSHJ P,IOSETC ;SET UP RING HEADER
PUSHJ P,DOMTAP ;BACKSP OVER RECORD SO WILL REWRITE IT
JRST FOPXIT ;LOST!
JRST FOPWIN ;AND TELL USER HE WON
FOPN12: PUSHJ P,BUFCLR ;ZERO THE BUFFER
JFCL ;SHOULD NEVER HAPPEN
JRST FOPWIN ;AND WE WON
DOMTAP: PUSHJ P,MTAPE0## ;TEL TAPUUO WHAT TO DO
TRNN S,IODERR!IODTER!IOIMPM
AOSA (P) ;WON
MOVEI T1,1 ;LOST, ERROR CODE=1
POPJ P, ;RETURN TO CALLER
;HERE TO DO A USETI AND RETURN STATUS
FUSTI: SKIPA W,[FUSETI##] ;DISPATCH TO USETI
;HERE TO DO A USETO AND RETURN STATUS
FUSTO: MOVEI W,FUSETO## ;DISPATCH TO USETO
HRRZ T4,FOPFLG ;NUMBER OF ARGS
CAIE T4,2 ;MUST BE EXACTLY TWO
JRST FOPILU ;IF NOT, LOSE
PUSHJ P,GETWD1## ;GET THE BLOCK NUMBER
EXCH T1,W ;BLOCK NUMBER IN W
PUSHJ P,(T1) ;CALL USET CODE IN FILSER
HRRZ T1,DEVIOS(F) ;I/O STATUS
TRNN T1,760000 ;ERRORS OR END OF FILE?
AOS (P) ;NO, SKIP RETURN TO THE USER
JRST FOPXIT ;DONE
;HERE TO CLOSE A FILE AND RETURN STATUS
FCLOS: MOVE T1,P1 ;COPY CHANNEL
PUSHJ P,DVCNSG ;REAL DEVICE
JRST FCLOSI ;NO--RETURN IOIMPM
HRRZ T2,FOPFLG ;GET LENGTH
SOSE T1,T2 ;ONLY 1 WORD?
PUSHJ P,GETWD1## ;NO--GET FLAGS
HRR M,T1 ;COPY TO CORRECT PLACE
MOVSI T1,DEPFFA ;SET TO JUST UPDATE RIB
MOVSI T2,FOP.UR ;WANT REAL CLOSE?
TDNN T2,FOPFLG ; ..
JRST FCLOS1 ;YES
TLNE F,ENTRB ;NO, FILE ENTERED
TLNE F,OCLOSB ;AND STILL OPEN?
JRST FCLOSI ;NO, LIGHT IOIMPM
IORM T1,DEVJOB(F) ;YES--SET DEPFFA
HLLZS M ;TURN OFF CLOSE-BITS
FCLOS1: PUSHJ P,CLOSEF ;CLOSE THE FILE
PUSHJ P,WAIT1## ;WAIT FOR I/O
HRRZ T1,DEVIOS(F) ;GET STATUS
TRNE T1,740000 ;ERROR BITS?
JRST FOPXIT ;DONE
MOVSI T2,FOP.UR
TDNN T2,FOPFLG
AOSA (P)
SKIPA T1,DEVMOD(F)
JRST FOPXIT
IFN FTNUL,<
TLNN T1,DVTTY ;GOOD RETURN IF NUL
>
TLNN T1,DVDSK ;DISK?
JRST FOPWIN ;NO, GOOD RETURN
MOVE T2,DEVACC##(F)
SOS T1,DEVREL##(F)
CAMGE T1,ACCWRT##(T2) ;AT EOF?
JRST FOPN10 ;NO, JUST POSITION TO THAT BLOCK
JRST FOPN9B ;YES, POSITION TO LAST BLOCK.
FCLOSI: MOVEI T1,IOIMPM ;SET IOIMPM
PJRST FOPXIT ;DONE
FOPWAT: MOVEI W,WAIT ;WAIT
JRST FOPOU1
FOPIN: SKIPA W,[TIN] ;INPUT
FOPOUT: MOVEI W,TOUT ;OUTPUT
HRRZ T1,FOPFLG
CAIG T1,1 ;MORE THAN 1 ARGUMENT?
TRZA T1,-1 ;NO, NO CLOSE BITS
PUSHJ P,GETWD1## ;YES, GET THE CLOSE BITS
HRR M,T1
HRRZ T4,DEVSER(F)
FOPOU1: PUSHJ P,(W) ;DO THE IN, OUT, OR WAIT
AOS (P) ;GOOD RETURN
HRRZ T1,S ;DEVICE STATUS
PJRST STOTAC## ;RETURN THAT FOR THE USER
FOPSST: HRRZ T1,FOPFLG
CAIGE T1,2
JRST FOPILU
PUSHJ P,GETWD1##
HRR M,T1
AOS (P) ;GOOD RETURN
PJRST SETIOS ;SET STATUS
FOPGST: AOS (P) ;GOOD RETURN
LDB T1,PUUOAC##
HRR M,T1
PJRST USTATS ;GET STATUS
FOPREL: AOS (P) ;GOOD RETURN
PJRST RELEA1 ;DO THE RELEASE
FOPSEK: AOS (P) ;GOOD RETURN
PJRST UUOSKF## ;DO THE SEEK
FOPRRC: MOVE T1,DEVMOD(F)
TLNN T1,DVDSK ;DISK?
JRST CPOPJ1## ;NO
AOS (P)
PJRST FWRBIC## ;YES, REWRITE RIB IF CHANGED
;SUBROUTINE TO RETURN THE ADDRESS OF A CHANNEL IN USRJDA OR THE EXTENDED
; CHANNEL TABLE IN T1
;RETURNS WITH T1 EQUAL TO THE ADDRESS OF THE CHANNEL TABLE ENTRY
JDAADP::HRRZ T2,P1
CAIA
JDAADR::HLRZ T2,.UPMP+.UPCTA ;CHANNEL NUMBER
CAILE T2,HIGHXC## ;LEGAL CHANNEL NUMBER?
STOPCD CPOPJ,JOB,ICL, ;++ILLEGAL CHANNEL NUMBER
MOVEI T1,USRJDA##(T2) ;ASSUME A TRADITIONAL CHANNEL
CAIG T2,17 ;A TRADITIONAL CHANNEL?
POPJ P, ;YES
HRRZ T1,.UPMP+.UPCTA ;NO
ADDI T1,-20(T2) ;ADDRESS OF EXTENDED CHANNEL
POPJ P, ;RETURN
;FILOP. EXIT ROUTINES
FOPWIN: MOVNI T1,1 ;INDICATE SUCCESS
JRST FOPXIT ;STANDARD EXIT
;RIB ERROR
FOPRER: SKIPA T1,[TRNERR]
;ILLEGAL UUO
FOPILU: MOVEI T1,ILUERR ;ERROR CODE
JRST FOPXI1 ;EXIT UUO
;OPEN ERROR
FOPOER: TLZ M,400000
HRR M,FOPAP ;ARG POINTER
HRRI M,2(M) ;POINT TO DEVICE
PUSHJ P,GETWDU## ;FETCH ARGUMENT
PUSHJ P,DEVSRG ;REAL DEVICE?
JRST FOPNSD ;NO SUCH DEVICE
SKIPA T1,[DNAERR] ;DEVICE NOT AVAIL.
FOPNSD: MOVEI T1,NSDERR ;NO SUCH DEVICE
JRST FOPXI1 ;DONE
;LOOKUP AND ENTER ERRORS
FOPLER: TDZA T4,T4 ;FLAG LOOKUP FAILURE
FOPEER: MOVNI T4,1 ;ENTER FAILURE
HLR M,FOPEXT ;ADDRESS OF EXTENSION
PUSHJ P,GETWDU## ;GET THE WORD
IORI T4,(T1) ;COMBINE WITH FLAG
JUMPN T4,FOPXI0 ;JUMP IF NOT FNFERR ON LOOKUP
MOVSI P2,FOP.NF ;SET FILE-NOT-FOUND FLAG
IORB P2,FOPFLG ; ..
TLNN P2,FOP.EN ;ENTER NEEDED
JRST FOPXI0 ;NO--FATAL ERROR ON READ
HRR T1,FOPEXT ;RESTORE DATE BITS
PUSHJ P,PUTWDU## ;STORE FOR ENTER
JRST FOPFNF ;TRY ENTER
FOPXI0: TLZ T1,-1 ;JUST ERROR NUMBER IN T1
MOVEI T2,DEPPAL## ;IF THIS IS A DSK,
MOVE T3,DEVMOD(F)
TLNE T3,DVDSK
ANDCAM T2,DEVPAL##(F) ; CLEAR PRE-ALLOCATE
FOPXIT: MOVSI T2,DEPFOP!DEPFFA ;MUST CLEAR THESE OR DDB
; CAUSE PROBLEMS ON NEXT UUO
ANDCAM T2,DEVJOB(F) ;ZAP!
SETZM .UPMP+.UPFOP ;FILOP. IS DONE
MOVSI T2,(UP.PFO) ;PRIV'ED FILOP
ANDCAM T2,.UPMP+.UPBTS ;CLEAR THAT
MOVE T2,DEVMOD(F)
TLNE T2,DVDSK ;IF A DSK
SETZM DEVUPP##(F) ;ZERO "IN YOUR BEHALF" PPN
JUMPL T1,CPOPJ1## ;ALL DONE IF NO ERRORS
FOPXI1: LDB M,[POINT 4,FOPAP,12] ;GET AC NUMBER
PJRST PUTWDU## ;STORE CODE AND NON-SKIP RETURN
;SUBROUTINE TO ENSURE A LOOKUP/ENTER/RENAME BLOCK IS IN CORE
;CALLING SEQUENCE:
; HRRI M,ADDRESS OF THE BLOCK
; PUSHJ P,FCLERB
FCLERB: PUSHJ P,GETWDU## ;GET FIRST WORD OF BLOCK
TLNN T1,-1 ;EXTENDED UUO?
TRZA T1,400000 ;YES--CLEAR OLD STYLE BIT
MOVEI T1,3 ;NO--4 WORDS
HRRZ T2,M ;START ADDRESS
ADDM T1,T2 ;PLUS LENGTH GIVES END
MOVEI T1,(M) ;RESTORE START
PJRST TRNGE## ;MAKE SURE ALL OK
;SUBROUTINE TO TEST WHETHER A DEVICE CAN DO THE TYPE OF I/O
; INDICATED AND WHETHER IT HAS A LONG DISPATCH VECTOR OR NOT
;CALLING SEQUENCE:
; MOVSI T1,DVIN OR DVOUT
; MOVE T2,ADDRESS OF THE EXTENSION WORD
; PUSHJ P,FOPTS
;RETURNS CPOPJ IF I/O DIRECTION IS LEGAL BUT DEVICE HAS A
; SHORT DISPATCH VECTOR, CPOPJ1 IF I/O DIRECTION IS LEGAL AND
; DEVICE HAS A LONG DISPATCH VECTOR, CPOPJ2 IF THE I/O DIRECTION
; IS ILLEGAL (FNFERR STORED IN THE EXTENSION WORD OF THE
; LOOKUP/ENTER BLOCK)
;PRESERVES T4
FOPTS: TDNE T1,DEVMOD(F) ;LEGAL I/O DIRECTION?
JRST FOPTS1 ;YES
HRR M,T2 ;NO, ADDRESS OF EXTENSION WORD
PUSHJ P,GETWDU## ;GET THE EXTENSION WORD
HRRI T1,FNFERR ;FILE NOT FOUND ERROR
PUSHJ P,PUTWDU## ;STORE THAT FOR THE USER
JRST CPOPJ2## ;ILLEGAL I/O DIRECTION RETURN
FOPTS1: MOVSI T1,DVLNG ;DEVICE HAS A LONG DISPATCH VECTOR BIT
TDNE T1,DEVMOD(F) ;DOES THE DEVICE HAVE A LONG DISPATCH VECTOR?
AOS (P) ;YES
POPJ P, ;NO
SUBTTL CLOSE UUO
;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.
;HERE FROM FILOP
CLOSEF: TDNE T1,DEVJOB(F) ;IF UPDATE RIB
JRST CLOSE2 ; CAN KEEP ENQ LOCKS
;NOT CHECKPOINT, FALL INTO CLOSE1
CLOSE1::
IFN FTEQDQ,<
PUSHJ P,ENQCLS## ;CHECK FOR LOCKS STILL OUT
SKIPA ;THERE WERE SOME
JRST ENQOK ;THERE WERE NO LOCKS
NQABRT: MOVEI T4,IOBKTL ;SET ERROR BIT...
IORM T4,DEVIOS(F) ;... IN DEVIOS
POPJ P, ;ABORT UUO
ENQOK: >;END OF IFN FTEQDQ
CLOSE2:
IFN FTMP,<
PUSHJ P,SETCPF## ;GET JOB ON THE RIGHT CPU TO DO FILE OPERATION
>
SETZM .UPMP+.UPFOP
HRRZ T4,DEVSER(F) ;RESTORE T4
PUSHJ P,WAIT1## ;WAIT UNTIL DEVICE IS INACTIVE
TRNN M,CLSIN ;SUPPRESS INPUT CLOSE?
TLOE F,ICLOSB ;NO. INPUT ALREADY BEEN CLOSED?
JRST UCLS2 ;YES
LDB T1,PIOMOD## ;NO
CAIGE T1,SD ;DUMP MODE?
JRST UCLSBI ;NO. CLOSE BUFFERED INPUT.
UCLS5: PUSHJ P,DCLI(T4) ;YES. DISPATCH TO DEVICE DEP. ROUTINE
JRST UCLS2 ;MUST NOT DESTROY M,F,T4,W, OR P1-P4
UCLSBI: MOVE T1,DEVMOD(F)
TLNN T1,DVDTA ;IS IT A DTA, OR
TLNE F,INBFB+INPB ;WAS AN INPUT BUFFER SETUP?
JRST UCLS4 ;YES
TLNE T1,DVDSK ;CLOSING A DISK FILE ?
JRST UCLS5 ;YES, DO DEVICE DEPENDENT CLOSE ANYWAY.
JRST UCLS2 ;NO, CLOSE NOT NECESSARY.
UCLS4: TLNE T1,DVLNG ;IS THIS A LONG DISPATCH TABLE?
PUSHJ P,DCLI(T4) ;YES, CLOSE INPUT
HRRZ T2,DEVBUF(F)
JUMPE T2,UCLS2 ;IF NO BUFFER, LOOK FOR OUTPUT SIDE
HRRZ T1,T2 ;ADDRESS OF THE FIRST WORD OF THE BUFFER HEADER
PUSHJ P,UADRCK ;MAKE SURE ITS IN CORE
EXCTUX <HRRZ U,@T2> ;FIRST WORD OF 3 WORD BUFFER HEADER
EXCTUX <HRR T2,@T2> ;REMEMBER CURRENT BUFFER IN T2
HRLZI T1,IOUSE ;USED BOTH FOR HEADER AND EACH BUFFER
JUMPE U,UCLS1 ;HAS A RING BEEN SETUP?(NO IF 0)
MOVEI T1,(U) ;IS ADDRESS SPECIFIED BY CONTENTS OF
PUSHJ P,UADRCK ;FIRST WORD OF 3 WORD BUFFER HEADER IN BOUNDS?
MOVEI T3,10000 ;ONLY ALLOW 10000 BUFFERS IN A RING
; SETUP COUNT IN CASE USER HAS MESSED
; BUFFER RING INTO A FIGURE SIX
UCLS0: EXCTUX <HRR U,@U> ;ADVANCE CURRENT INPUT BUFFER ADDRESS
MOVEI T1,(U) ;IS ADDRESS OK?
PUSHJ P,UADRCK
HRLZI T1,IOUSE ;USE BIT FOR BOTH HEADER AND BUFFERS
EXCTUU <ANDCAM T1,@U> ;YES, CLEAR USE BIT.
CAME T2,U ;DONE?
SOJG T3,UCLS0 ;NO, HAVE WE SCANNED 10000 BUFFERS?
; (WHICH MAY BE THE SAME)
; YES
UCLS1: HRR U,DEVBUF(F)
EXCTUU <IORM T1,@U> ;FLAG AS VIRGIN BUFFER IN 3 WORD HEADER
ADDI U,2 ;JBFCTR:=0
HRRZ T1,U
PUSHJ P,UADRCK ;MAKE SURE ITS IN CORE
EXCTXU <SETZM @U> ;CLEAR INPUT ITEM COUNT.
MOVE S,[XWD IOEND,IODEND]
MOVE T1,DEVMOD(F)
TLNE T1,DVTTY ;IS THIS A TTY?
TLO S,FRCEND## ;YES, CLEAR OTHER EOF FLAG
ANDCAB S,DEVIOS(F)
UCLS2: PUSHJ P,UCLS3 ;STORE UPDATED F
TRNN M,CLSOUT ;SUPPRESS OUTPUT CLOSE?
TLOE F,OCLOSB ;NO. OUTPUT ALREADY CLOSED?
JRST UCLS3 ;YES
PUSHJ P,RELSEG## ;CLEAR SHARED SEG NAME IF FILE JUST CLOSED HAS
; EXTENSION .SHR AND SEG HAS SAME DIRECTORY AND NAME
LDB T1,PIOMOD## ;NO.
CAIGE T1,SD ;DUMP MODE?
JRST UCLSBO ;NO. CLOSE BUFFERED OUTPUT
UCLS7: HRRZ T4,DEVSER(F) ;RESTORE T4
PUSHJ P,DCL(T4) ;YES. DISPATCH TO DEVICE DEP. ROUTINE
JRST UCLS3
UCLSBO: TLNN F,OUTBFB+OUTPB ;WAS AN OUTPUT BUFFER SET UP?
JRST UCLS6 ;NO
HLRZ U,DEVBUF(F) ;VIRGIN OUTPUT BUFFER?
JUMPE U,UCLS6 ;IF NO BUFFER, DON'T CLOSE UNLESS DISK
PUSHJ P,CLSCHK
EXCTUX <SKIPG @U>
JRST UCLS6 ;YES, DO NOT CLOSE UNLESS IT IS A DISK FILE
PUSHJ P,WAIT2X ;ENSURE ALL BUFFERS WRITTEN
UCLS2B: MOVE T4,DEVSER(F)
MOVEI T1,DEPAIO!DEPOND
ANDCAM T1,DEVAIO(F) ;DON'T ALLOW NON-BLOCKING I/O DURING CLOSE
PUSHJ P,DCL(T4) ;CLOSE OUTPUT BUFFER
HLRZ U,DEVBUF(F)
HRLZI T1,IOUSE
EXCTUU <IORM T1,@U>
EXCTXU <SETZM 2(U)> ;JBFCTR:=0
PUSHJ P,WAIT1##
MOVSI T1,DEPFFA ;IF FILOP UPDATE-RIB
TDNN T1,DEVJOB(F) ; DON'T LIGHT OCLOSB CAUSE FILE STAYS OPEN
TLO F,OCLOSB ;SET OCLOSB AFTER OUTPUT IS COMPLETE
UCLS3: PUSHJ P,JDAADR
HLLM F,(T1)
POPJ P, ;EXIT THIS UUO
UCLS6: MOVSI T1,DVDSK!DVDTA
TDNN T1,DEVMOD(F) ;CLOSING A DISK OR DTA FILE ?
JRST UCLS3 ;NO
PUSHJ P,CLSCHK
JRST UCLS7 ;YES, CALL DSK CLOSE ANYWAY
;SUBROUTINE TO CHECK LEGALITY OF BUF HEADER FOR CLOSE
CLSCHK: HLRZ T1,DEVBUF(F) ;START OF BUFFER HEADER
JUMPE T1,CPOPJ##
MOVEI T2,2(T1) ;END
PJRST TRNGE## ;MAKE SURE ITS IN CORE
SUBTTL INBUF & OUTBUF UUO'S
;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
;W IS RESTORED.
UINBF:: TLO F,INBFB ;FLAG INBUF UUO DONE
HRRZ T2,DEVBUF(F) ;GET BUFFER HEADER ADDRESS
JUMPE T2,ADRERR## ;ADDRESS CHECK IF NO HEADER
PUSHJ P,BUFCLC ;SET UP BUFFER RING
HRRM T3,DEVIAD(F) ;DEVIAD:=ADDRESS OF FIRST BUFFER
; IN RING
MOVSI T1,DVDSK+DVMTA ;IF A DSK,
TDNE T1,DEVMOD(F) ; SAVE THE NUMBER OF BUFFERS
DPB M,PINBFN## ; IN THE DDB
HRRZ T2,DEVBUF(F) ;T2:=INPUT BUFFER AREA HEADER ADDRESS
JRST UOBF1
UOUTBF::TLO F,OUTBFB ;FLAG OUTBUF UUO DONE
HLRZ T2,DEVBUF(F) ;GET BUFFER HEADER ADDRESS
JUMPE T2,ADRERR## ;ADDRESS CHECK IF NO HEADER
PUSHJ P,BUFCLC ;SET UP BUFFER RING
HLRZ T2,DEVBUF(F) ;T2:=OUTPUT BUFFER AREA HEADER ADDRESS
HRRM T3,DEVOAD(F) ;DEVOAD:=ADDRESS OF FIRST BUFFER
; IN RING
IFN FTMSGSER,<
LDB T1,PDVTYP## ;GET DEVICE TYPE BYTE
CAIN T1,<.TYMPX/.TYEST> ;MPX DEVICE
EXCTUU <HLLZS @T4> ;LIST NOT RING
>
UOBF1: HRRZ T1,T2 ;CHECK ADR OF BUF HEADER
PUSHJ P,UADRCK
EXCTXU <MOVEM T3,@T2> ;JBFADR:=IOUSE,ADDRESS OF FIRST BUFFER
; IN RING
PUSHJ P,JDAADR
MOVEM F,(T1)
POPJ P, ;EXIT THIS UUO
SUBTTL OPEN & INIT UUO'S
;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
;C(ADR+1) = SIXBIT /NAME/
;LH(ADR+2)=OUTPUT BUFFER HEADER ADDRESS
;RH(ADR+2)=INPUT BUFFER HEADER ADDRESS
UOPEN:: PUSHJ P,GETWDU## ;SET T1 TO CONTENTS OF FIRST ARG(IO STATUS BITS)
AOJA M,UINIT0 ;MAKE UUO POINT TO ARG+1
;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
UINIT:: HRRZ T1,M ;SAVE FIRST ARG(IO STATUS BITS) IN T1
HRR M,-1(P) ;SET UUO TO ADR+1 OF USER ARGS
PUSHJ P,UINIT0 ;TRY TO INIT THE DEVICE
TDZA T1,T1 ;FAIL
MOVEI T1,1 ;WIN, GIVE SKIP RETURN
ADDI T1,2 ;ACCOUNT FOR THE ARGUMENTS
ADDM T1,-1(P) ;BUMP RETURN PAST THE ARGUMENTS
POPJ P, ;RETURN
UINIT0:
IFN FTEQDQ,<
PUSHJ P,ENQCLS## ;ANY LOCKS OUT?
JRST NQABRT ;YES, ABORT UUO
>
PUSHJ P,SAVE3## ;SAVE P1
PUSH P,M ;HERE ON OPEN UUO, SAVE ADR+1 OF USER ARGS
PUSH P,T1 ;SAVE IO STATUS BITS(FIRST ARG)
PUSHJ P,SETUF ;IS A DEVICE ALREADY ASSIGNED TO THIS CHAN?
;YES, IS THIS CHAN. LESS OR EQUAL TO HIGHEST
; CHAN. FOR THIS USER?
JRST UINITA ;NO, NO PREVIOUS DEVICE TO RELEASE
PUSHJ P,RELEA0 ;RELEASE PREVIOUS DEVICE ON THIS CHAN.
UINITA: MOVE M,-1(P) ;RESTORE M (ADR+1 OF 3 ARGS)
PUSHJ P,GETWDU## ;C(T1)=DEVICE NAME IF IN BOUNDS
; DO NOT RETURN IF OUT OF BOUNDS(PRINT ERR AND STOP)
; SET J TO CURRENT JOB NUMBER
SKIPGE (P) ;SIGN BIT OF MODE-WORD=1?
HRLI P1,PHONLY ;YES, SET FOR PHYSICAL DEVICES ONLY
PUSHJ P,DEVSRC ;SEARCH FOR DEVICE NAME
; (SET SYSDEV BIT IN LH OF
; F IF THIS IS SYSTEM TAPE)
TDZA T3,T3 ;NO SUCH DEVICE - TRY GENERIC
JRST UINIT2 ;FOUND PHY DEV (OR LOGICAL)
IFE FTGSRC!FTNET,<
PUSHJ P,DEVSRC ;SEARCH FOR DEVICE
>
IFN FTGSRC!FTNET,<
PUSHJ P,DVSRSP ;DOES ANY DEV OF THIS TYPE EXIST?
>
JRST UINITE ;NO - ERROR
IFN FTSPL,<
SKIPN DEVCHR(F) ;IS IT A "FAKE" DDB
SKIPA T2,SPLBIT##(F) ;YES, GET BIT FROM TABLE
LDB T2,DEYSPL## ;YES. GET SPOOLING BIT
HRRZS T2 ;CLEAR TYPE BIT
TDNE T2,JBTSPL##(J) ;JOB SPOOLING THIS DEV?
JRST UINIT2 ;YES. OK
> ;END CONDITIONAL ON FTSPL
MOVEI T3,ASSPRG ;FLAG THAT INIT'ED DEV UNACCEPTABLE
PUSH P,F ;SAVE DDB LOC
IFE FTGSRC,<
PUSHJ P,DEVSRC ;SEARCH FOR DEVICE
>
IFN FTGSRC,<
PUSHJ P,DVASRC ;TRY TO FIND GENERICALLY
>
SKIPA F,(P) ;RESTORE POSSIBLE DDB
JRST UINIT1 ;WON - CONTINUE
TRNE T1,770000 ;IS IT DEVX?
TRNE T1,7700
JRST UINITD ;NO - LOSE
UINIT1: POP P,(P) ;YES - WIN
UINIT2: MOVE T2,JBTSTS##(J) ;IS THIS JOB
TLNE T2,JLOG ; LOGGIN IN?
JRST UINI2A ;YES, CONTINUE
MOVE T2,DEVMOD(F) ;NO, MAKE SURE JOB
TLNN T2,DVDSK!DVTTY ; IS TRYING FOR VALID DEVICE
JRST UINITE ;NO, ERROR
UINI2A: MOVE M,(P) ;RESTORE USER'S MODE SETTING
TLNE M,^-.OPALL&777770 ;ANY UNDEFINED OPEN BITS SET?
JRST ILLMOD## ;YES--BOMB THE USER
PUSH P,T1 ;SAVE NAME USER SUPPLIED
IFN FTNUL,<
CAME T1,[SIXBIT /NUL/] ;ALL MODES ARE LEGAL FOR NUL:
>
PUSHJ P,CHKMOD ;CHECK FOR LEGAL MODE, IF NOT RIGHT DONT RETURN
POP P,T1 ;RESTORE NAME
MOVE T3,DEVMOD(F) ;DEVICE CHARACTERISTICS
TLNN T3,DVDTA ;IS THIS DEVICE A DECTAPE?
JRST UINITB ;NO
LDB T2,IADPTR## ;YES, GE NO OF USER CHANS DEV INITED ON
HRR T3,T2 ;SAVE OLD NUMBER
AOS T2 ;INCREASE CHANNEL COUNT
DPB T2,IADPTR## ;YES, STORE UPDATED CHANNEL COUNT FOR THIS DEV(DTA)
UINITB: MOVEI T2,ASSPRG ;TRY TO ASSIGN IT BY PROGRAM
SETZM M
PUSHJ P,ASSASG
JRST UINIT6 ;NOT AVAILABLE, GIVE ERROR RETURN(POP T1)
POP P,M ;RESTORE USER'S MODE SETTING
MOVE T2,[XWD DEPIBC,DEPDEL!DEPDER!DEPAIO]
;DISABLE ERROR LOGGING AND ERROR RECOVERY
ANDCAM T2,DEVSTA(F) ;MAKE SURE NOT DISABLED
MOVSI T3,DEPSIE
ANDCAM T3,DEVJOB(F) ;DISABLE SYNCH ON ERROR
TLNN M,.OPDEL!.OPFSP ;IS USER TRYING TO DISABLE ERROR LOGGING?
JRST UINIT3 ;NO, LEAVE ERROR LOGGING ENABLED
MOVE J,.CPJOB## ;YES, CURRENT JOB NUMBER
MOVEI T3,DEPDEL ;SETUP TO STORE DISABLE BIT IN DDB
LDB T2,PDVTYP##
CAIN T2,.TYPTY/.TYEST
JRST UINITX
MOVE T2,JBTPPN##(J) ;PROJ PROG NUMBER FOR CURRENT JOB
CAME T2,FSFPPN## ;IS THIS USER FAILSAFE PPN [1,2]?
CAMN T2,UMDPPN## ;NO, IS THS USER MODE DIAG [6,6]?
UINITX: IORM T3,DEVSTA(F) ;YES, USER PRIVILEGED TO DISABLE ERROR LOGGING
UINIT3: LDB T3,PDVTYP## ;SET DEVTYP WORD
CAIE T3,.TYPTY/.TYEST ;IS IT A PTY?
JRST UINIB0 ;NO, SEE IF IT'S A TASK
MOVSI T3,DVDIBP ;YES, GET BATCH PTY BIT
ANDCAM T3,DEVCHR(F) ;START WITH IT OFF
PUSHJ P,PRVJ## ;IS JOB PRIV'ED?
TLNN M,.OPBJP ;YES, DID USER REQUEST IT?
JRST UINIB2 ;NO, IGNORE THE BIT
MOVSI T3,DVDIBP ;LOAD BATCH PTY BIT AGAIN
IORM T3,DEVCHR(F) ;TURN IT ON
JRST UINIB2 ;AND CONTINUE ON
UINIB0: CAIE T3,.TYTSK/.TYEST ;IS THIS A TASK DEVICE
JRST UINIB1 ;IF NOT, DON'T CHECK .OPDMR
MOVSI S,IOSDMR ;IF IT IS A TASK, FIRST
ANDCAB S,DEVIOS(F) ; MAKE SURE THAT IOSDMR IS CLEAR
TLNE M,.OPDMR ;BUT IF THE USER ASKED FOR "DISABLE
MOVSI S,IOSDMR ; MESSAGE RE-ASSEMBLY" THEN
IORB S,DEVIOS(F) ; GIVE IT TO HIM
JRST UINIB2 ;DON'T CHECK FOR ANY OTHER MEANINGS
UINIB1: MOVEI T2,DEPDER ;SETUP FOR POSSIBLE DISABLE ERROR RETRY
TLNE M,.OPDER ;USER WANT ERROR RETRY DISABLED?
IORM T2,DEVSTA(F) ;YES, SET DISABLE IN DDB
UINIB2: MOVEI T2,DEPAIO ;NON-BLOCKING I/O ON THIS FILE?
TLNE M,.OPAIO ;SKIP IF NO
IORM T2,DEVAIO(F) ;YES, FLAG ASYNCHRONOUS I/O
MOVSI T2,DEPIBC ;INHIBIT BUFFER CLEAR BIT
TLNE M,.OPIBC ;DOES THE USER WANT TO INHIBIT CLEARING OUTPUT BUFFER?
IORM T2,DEVTYP(F) ;YES, REMEMBER THAT
MOVSI T2,DEPSIE ;BIT FOR SYNCH ON I/O ERROR
TLNE M,.OPSIE ;TEST IF USER WANTS IT
IORM T2,DEVJOB(F) ;YES - SET FLG IN DDB
CAIE T3,.TYDSK/.TYEST
JRST UINIB3
MOVE T2,DEVRRC##(F)
TLZ T2,DEPRRC##!DEPRHC##!DEPPHO##
TLNE M,.OPRRC ;REWRITE RIB ON CHANGE?
TLO T2,DEPRRC## ;YES
SKIPGE P1 ;PHYSICAL ONLY?
TLO T2,DEPPHO## ;YES, REMEMBER THAT.
HLLM T2,DEVRRC##(F)
UINIB3: HRRZ T2,DEVSER(F) ;GET DISPATCH ADDRESS
;DSZ CALL NEVER RETURNS FOR DC44 DEVICES WHICH ARE DOWN
;THIS EXITS VIA DWNP11 IN ERRCON
PUSHJ P,DSZ(T2) ;LET ROUTINE PUT IN BUF SIZE
DPB T1,PBUFSZ## ;STORE THE BUFFER SIZE IN DEVCHR WORD
PUSHJ P,SETIOS ;SET DDB S 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 S,IOBEG
IORB S,DEVIOS(F)
HRRZS P1 ;CLEAR LH(P1) FOR UINITL LOOP
HRLM P1,.UPMP+.UPCTA
CAILE P1,17
JRST UINITC
UINITL: SKIPL USRHCU## ;SAVGET (CHAN 0)?
CAMG P1,USRHCU## ;NO, IS THIS CHAN. .GT. HIGHEST CHAN. IN USE?
JRST UINITC ;NO
AOS T1,USRHCU## ;YES, BUMP HIGHEST SO FAR BY ONE
SETZM USRJDA##(T1) ;AND CLEAR IT OUT
JRST UINITL ;AND KEEP LOOKING
UINITC: PUSHJ P,JDAADR ;CHANNEL ADDRESS
MOVEM F,(T1)
TLO F,INITB+ICLOSB+OCLOSB;SET INIT UUO BIT
;PREVENT SUPERFLUOUS CALLS TO CLOSE (SEE LOOKUP,ENTER)
AOS M,(P) ;ADVANCE TO 3RD ARG(BUFFER HEADER)
PUSHJ P,GETWDU## ;C(T1)=BUFFER HEADER ARG
HLRZ T2,T1 ;OUTPUT BUFFER HEADER FROM USER
JUMPE T2,UINIT4 ;WAS ONE SPECIFIED?
HRLM T2,DEVBUF(F) ;SAVE BUFFER HDR LOC
TLO F,OBUFB ;SET OUTPUT BUFFER SPECIFIED BIT
PUSHJ P,UINITZ ;INITIALIZE OUTPUT BUFFER HEADER
UINIT4: PUSHJ P,GETWDU## ;USER'S ARG AGAIN
HRRZ T2,T1 ;INPUT BUFFER HDR
JUMPE T2,UINIT5 ;WAS ONE SPECIFIED?
HRRM T2,DEVBUF(F)
TLO F,IBUFB ;SET INPUT BUFFER SPECIFIED BIT
MOVSI S,IOEND ;CLEAR END OF FILE FLAG
ANDCAB S,DEVIOS(F) ;AND RETAIN S
PUSHJ P,UINITZ ;INITIALIZE INPUT BUFFER HEADER
UINIT5: PUSHJ P,JDAADR ;CHANNEL ADDRESS
MOVEM F,(T1) ;STORE UUO BITS AND DEVICE
; DATA BLOCK ADDRESS
MOVE T1,DEVMOD(F) ;GET THE GOOD WORD
TLNN T1,DVTTY ;IS THIS A TTY?
JRST TPOPJ1## ;SUCCESSFUL RETURN(POP T1)
JRST TTYOPN## ;YES, GO SET UP LDB
UINIT6: PUSHJ P,TTYKLQ## ;IF IT WAS A FREE TTY, DISCARD DDB
TLNE T3,DVDTA ;WAS DEVICE A DECTAPE?
DPB T3,IADPTR## ;YES, RESTORE NO. OF USER CHAN INITED ON
CAIA
UINITD: POP P,(P)
UINITE: POP P,T1 ;REMOVE IO STATUS ARG
SETZ F, ;CLEAR F TO CIRCUMVENT UUONET.
JRST TPOPJ## ;AND GIVE ERROR RETURN AND POP T1
;CALLING SEQUENCE
; PUSHJ P,UINITZ
; EXIT RETURNS HERE IF MEMORY NOT EXCEEDED.
;SETS JBFADR:=JBFCTR:=0 FOR THE BUFFER AREA HEADER WHOSE ADDRESS
;IS IN AC T2. ALSO,JBFPTR 0-5:=JBFPTR 12-17:=0,JBFPTR 6-11:=BYTE SIZE
UINITZ::MOVEI T1,(T2) ;START ADR OF HEADER
MOVEI T2,2(T1) ;TOP ADR
PUSHJ P,LRNGE## ;MAKE SURE WHOLE HEADER IS IN CORE
MOVEI T2,-2(T2) ;RESET T2
SKIPL M ;IF NOT FROM FILOP,
EXCTXU <SETZM @T2> ; CLEAR FIRST WORD (CURRENT BUFFER) OF 3 WORD HEADER
PUSH P,T2
EXCTXU <SETZM 2(T2)> ;SET ITEM COUNT TO ZERO
PUSHJ P,SETBYT ;SET BYTE SIZE ACCORDING TO MODE AS SET IN AC S
POP P,T2 ;GET T2 BACK
TLZ T1,770077
EXCTUU <HLLM T1,1(T2)> ;AND STORE IN SECOND WORD
POPJ P, ;RETURN
SUBTTL COMMON PART OF LOOKUP AND ENTER
;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
UDEN: PUSHJ P,SAVE4##
IFN FTEQDQ,<
PUSHJ P,ENQCLS## ;LOCKS STILL OUT?
JRST LKNQER ;YES
>
IFN FTMP,<
PUSHJ P,SETCPF##
>
MOVEI T1,CLSIN
TLNN F,OCLOSB ;FILE OPEN?
PUSHJ P,UDLKC ;YES. CLOSE IT[OCLOSB_1]
MOVSI S,IOBEG ;RESET BITS IN S
IORM S,DEVIOS(F) ; (CAN'T DO A MOVEM DUE TO
MOVEI S,IOIMPM!IODERR!IODTER!IOBKTL!IODEND!IOBOT!IOTEND
ANDCAB S,DEVIOS(F) ; POSSIBLE RACE WITH SERVICE ROUTINE)
PUSHJ P,ARGCHK ;ADDRESS CHECK ARG.
PUSHJ P,DEN(T4) ;ATTEMPT AN ENTER
IFE FTWATCH,<
POPJ P, ;FAILURE
>
IFN FTWATCH,<
CAIA ;FAILURE
TRZ M,-1 ;SUCCESS
PUSHJ P,WCHFIL ;TELL THE WORLD
CAI "E"
TRNE M,-1
POPJ P, ;EXIT IF ERROR
>
TLZ F,OCLOSB
TLO F,ENTRB ;NOTE SUCCESSFUL ENTER
JRST DLKDEN ;STORE THE PROGRESS BITS
;LOOKUP UUO - LOOKUP FILE NAME IN DIRECTORY
UDLK: PUSHJ P,SAVE4##
IFN FTEQDQ,<
PUSHJ P,ENQCLS## ;LOCKS STILL OUT?
JRST LKNQER ;YES
>
IFN FTMP,<
PUSHJ P,SETCPF##
>
MOVEI T1,CLSOUT ;INHIBIT OUTPUT CLOSE BIT
TLNN F,ICLOSB ;FILE OPEN?
PUSHJ P,UDLKC ;YES. CLOSE IT[ICLOSB_1]
MOVE S,[XWD IOEND,IOIMPM!IODERR!IODTER!IOBKTL!IODEND!IOBOT!IOTEND]
ANDCAB S,DEVIOS(F)
PUSHJ P,ARGCHK ;ADDRESS CHECK ARG.
MOVE T4,DEVSER(F)
PUSHJ P,DLK(T4) ;ATTEMPT A LOOKUP
IFE FTWATCH,<
POPJ P, ;FAILURE
>
IFN FTWATCH,<
CAIA ;FAILURE
TRZ M,-1 ;SUCCESS
PUSHJ P,WCHFIL ;TELL THE WORLD
CAI "L"
TRNE M,-1
POPJ P, ;EXIT IF ERROR
>
TLZ F,ICLOSB
TLO F,LOOKB ;NOTE SUCCESSFUL LOOKUP
DLKDEN: PUSHJ P,JDAADR ;STORE UUO PROGRESS BITS
HLLM F,(T1)
JRST CPOPJ1## ;SUCCESS RETURN TO USER (CALL+2)
IFN FTEQDQ,<
LKNQER: PUSHJ P,GETWDU## ;GET ADDRESS OF LOOKUP BLOCK
TLNN T1,-1 ;IS IT AN EXTENDED ONE?
ADDI M,2 ;YES
PUSHJ P,GETWD1## ;GET CONTENTS OF WORD
HRRI T1,ENQERR ;SET ERROR CODE
PJRST PUTWDU## ;RETURN IT TO USER
>
;SUBROUTINE TO DO THE CLOSE FOR LOOKUP/ENTER
UDLKC:: PUSH P,M ;SAVE ACS
PUSH P,T4
HRRI M,(T1)
PUSHJ P,CLOSE1 ;DO THE CLOSE
POP P,T4
POP P,M ;RESTORE ACS
JRST WAIT1## ;WAIT TILL IO DONE AND RETURN
ARGCHK: MOVEI T1,0(M)
PUSHJ P,UADCK1 ;CHECK FIRST WORF OF TABLE
MOVEI T1,3(M) ;LOAD UP LAST WORD OF TABLE
PJRST UADCK1 ;ADDRESS CHECK IT
IFN FTWATCH,<
;ROUTINE TO PRINT WATCH-FILE DATA
;CALL: HRR M,UVA OF ERROR CODE (HRRI M,0 IF SUCCESS)
; PUSHJ P,WCHFIL
; CAI 'X'
WCHFIL: MOVE J,.CPJOB##
MOVE T1,JBTWCH##(J)
HRR T1,JBTSTS##(J)
MOVS T2,.UPMP+.UPMUO
TRNE T1,JS.ASA
CAIN T2,(ENTER)
CAIA ;SAVE - WATCH IT
POPJ P, ;RUN/GET - DON'T WATCH
TRNN T1,JS.XO
TLNN T1,JW.WFL
POPJ P,
PUSH P,U
PUSH P,F
PUSHJ P,TTYFND##
POP P,F
JUMPE U,UPOPJ##
PUSHJ P,PRLBK##
MOVE T1,DEVJOB(F)
TLNN T1,DEPFOP
JRST WCHFI1
PUSHJ P,INLMES##
ASCIZ /F/
WCHFI1: HRRZ T3,@-1(P)
PUSHJ P,COMTYO##
HLRZ T1,.UPMP+.UPCTA
PUSHJ P,PRTDI8##
PUSHJ P,INLMES##
ASCIZ /: /
PUSHJ P,PRTDDB##
TRNN M,-1
JRST WCHFI2
PUSHJ P,INLMES##
ASCIZ /, error /
PUSHJ P,GETWDU##
HRRZS T1
PUSHJ P,PRTDI8##
WCHFI2: PUSHJ P,PRRBK##
PUSHJ P,PCRLF##
JRST UPOPJ##
>
SUBTTL COMMON PART OF RENAME, USETI/O, UGETF AND UTPCLR
;RENAME UUO - HERE ON SHORT DISPATCH TABLE DEVICES TOO
URENAM: MOVE T1,DEVMOD(F) ;IS THIS DEVICE A LONG DISPATCH TABLE?
TLNN T1,DVLNG
JRST CPOPJ1## ;NO, GIVE SKIP RETURN TO USER
PUSHJ P,ARGCHK ;ADDRESS CHECK END OF BLOCK
IFN FTMP,<
PUSHJ P,SETCPF## ;SET CPU FOR FILE OPERATION
>
JRST RNMSEG## ;OLD FILE IS .SHR AND RENAME SUCCESSFUL.
;HERE FROM SEGCON
UDREN::
IFE FTWATCH,<
PJRST DRN(T4) ;DO THE RENAME
>
IFN FTWATCH,<
PUSHJ P,DRN(T4) ;DO THE RENAME
SOSA (P) ;FAILURE
TRZ M,-1 ;SUCCESS
PUSHJ P,WCHFIL ;TELL THE WATCHER
CAI "R"
PJRST CPOPJ1##
>
;SETO UUO - SET NEXT OUTPUT BLOCK NUMBER(DECTAPE)
UDSO:
IFN FTMP,<
PUSHJ P,SETCPF## ;SET CPU FOR FILE OPERATION
>
PUSHJ P,WAIT2 ;WAIT FOR IO, FIX OUTPUT BUFFERS
JRST DSO(T4)
;SETI UUO - SET NEXT INPUT BLOCK NUMBER
UDSI:
IFN FTMP,<
PUSHJ P,SETCPF## ;SET CPU FOR FILE OPERATION
>
PUSHJ P,WAIT2 ;WAIT FOR IO, FIX OUTPUT BUFFERS
JRST DSI(T4)
;GETF UUO - GET NEXT FREE BLOCK
UDGF:
IFN FTMP,<
PUSHJ P,SETCPF## ;SET CPU FOR FILE OPERATION
>
JRST DGF(T4)
;MTAPE UUO - MAGTAPE OPERATIONS
UMTAPE:
IFN FTMP,<
PUSHJ P,SETCPF## ;SET CPU FOR FILE OPERATION
>
JRST DMT(T4)
;UTPCLR - CLEAR DECTAPE DIRECT.
UTPCLR: MOVE T1,DEVMOD(F) ;IS THIS A LONG DISPATCH TABLE?
TLNN T1,DVLNG
POPJ P, ;NO,RETURN
IFN FTMP,<
PUSHJ P,SETCPF## ;SET CPU FOR FILE OPERATION
>
JRST DCLR(T4) ;YES, DISPATCH
SUBTTL COMMON PART OF INPUT AND OUTPUT UUO'S
;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.
CNGIN: TRNN M,-1 ;IS USER CHANGING RINGS
POPJ P, ;NO - RETURN IMMEDIATELY
PUSHJ P,WAIT1## ;WAIT FOR I/O TO COMPLETE
TRNN T2,-1 ;DID HE HAVE A PREVIOUS BUFFER?
JRST SETNEW ;NO - SKIP NEXT
HRRZ T1,T2 ;MAKE SURE THAT BUFFER WAS
PUSHJ P,UADRCK ;IN HIS ADDRESS SPACE
HRLZI T1,IOUSE ;BUFFER IN USE BIT
EXCTUU <ANDCAM T1,@T2> ;AND THEN MAKE IT AVAILABLE
SETNEW: EXCTUU <HRRM M,@U> ;POINT HEADER TO NEW RING
HRR T2,M ;AND RESET PTR TO CURRENT BUFFER
HRLZI T1,IOUSE ;BUFFER IN USE BIT
EXCTUU <IORM T1,@U> ;VIRGIN BIT FOR NEW RING
MOVE S,DEVIOS(F) ;LOAD S JUST IN CASE
POPJ P,0 ;RETURN WITH TRANSPARENT CHANGES
UIN:IFN FTPI,< ;IF WE SUPPORT PSISER
XCT OKSGNL## ;IS AN INTERRUPT REMOTELY POSSIBLE?
JRST UIN00 ;NO--BE FAST
PUSHJ P,UIN00 ;YES--DO THE INPUT
PJRST PSIIDN## ;CALL PSISER TO SEE IF ANYTHING HAPPENED
> ;END FTPI
UIN00: TLNN S,IO ;IS THIS DEVICE ALREADY DOING OUTPUT?
JRST UIN01 ;NO
MOVE T1,DEVCHR(F) ;IS THIS A FULL DUPLEX DEVICE
TLNN T1,DVC2IO ; IF IT IS, DON'T WAIT FOR OUTPUT
PUSHJ P,WAIT2 ;YES, WAIT TILL IT IS FINISHED.
IFN FTKL10&FTMP,<
PUSHJ P,OTHNBF ;RESET DEVNBF
>
UIN01: TLO F,INPB ;FOR THIS DEVICE.
TLZ F,ICLOSB
PUSHJ P,JDAADR ;IN LH OF CURRENT JOB DEVICE CHANNEL
HLLM F,(T1)
LDB T1,PIOMOD## ;IO MODE
CAIL T1,SD ;IT THE IO MODE DUMP(SD,D,DR)?
JRST INDMP ;YES
IN1:
IFN FTMP,<
PUSHJ P,SETCPF## ;GET JOB ON RIGHT CPU TO DO IO
; IF NON-QUEUED PROTOCOL
>
HRRZ U,DEVBUF(F) ;NO, GET ADDRESS OF BUFFER HEADER
HRRZ T1,U ;START OF HEADER
MOVEI T2,2(T1) ;TOP OF HEADER
PUSHJ P,LRNGE## ;MAKE SURE ITS ALL THERE
MOVE S,DEVIOS(F) ;SETUP IO STATUS AGAIN FROM MEMORY
; AC S IS CLOBBERED BY AUTOMATIC CORE EXPANSION
; ON AN IMPLICIT INBUF ON FIRST INPUT
EXCTUX <HRRZ T2,@U> ;GET WORD 1 OF 3 WORD BUFFER HEADER.
PUSHJ P,CNGIN ;GO SEE IF USER CHANGING RINGS
HRRZ T1,T2 ;CHECK ADR. TO SEE IF OK
PUSHJ P,UADCK1
EXCTUX <SKIPG @U> ;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
MOVE S,DEVIOS(F)
HRRZ T1,DEVIAD(F) ;BUFFER ADR DEVICE WILL USE
TDNN S,[XWD IOEND,IOACT] ;BUFFER HAS BEEN ADR CHECKED IF I/O IS ACTIVE
PUSHJ P,UADRCK ;MAKE SURE IT'S LEGAL
MOVSI T1,IOUSE ;BUFFER IN USE BIT
EXCTUX <TDNN T1,@T2>
JRST INPT1
EXCTUX <HRRZ T1,@T2> ;MAKE SURE A FAULT WONT HAPPEN
PUSHJ P,FLTST## ; BEFORE WE ADVANCE THE BUFFER HEADER
JRST UUOFLT## ;OOPS - GET THE PAGE IN CORE
EXCTUX <SKIPGE T2,@T1>
MOVSI T2,1 ;WRD 1 MUST BE IN CORE
HLRZS T2
ADDI T2,(T1)
PUSHJ P,LRNGE##
EXCTUX <HRRZ T2,@U>
MOVEI T3,DEPIND ;DID WE RETURN EARLY BEFORE?
TDNE T3,DEVAIO(F) ; (ASYNC. IO, BUFFER NOT FULL)
JRST INPT3 ;YES, DON'T ADVANCE BUFFERS NOW
IFN FTMSGSER,<
LDB T1,PDVTYP## ;GET DEVICE TYPE
CAIE T1,<.TYMPX/.TYEST>
JRST INPT0E ;NO--CHARGE AHEAD
HRR T1,DEVBUF(F) ;GET ADDRESS OF INPUT BUFFER HEADER
MOVEI T2,3(T1) ;TOP OF 4-WORD HEADER
PUSHJ P,TRNGE## ;MAKE SURE IT'S IN CORE
INPT0E:> ;END FTMSGSER
MOVSI T3,IOUSE
EXCTUX <HRRZ T2,@U> ;RESTORE T2
EXCTUU <ANDCAB T3,@T2> ;FLAG CURRENT BUFFER AS FREE TO
; RECEIVE MORE INPUT, CLEAR USE BIT
; AND GET POINTER TO NEXT BUFFER
IFN FTMP & FTKL10,<
HRRZ T1,T2 ;WE JUST TOUCHED THE CURRENT BUFFER
PUSHJ P,OUCHE## ; SO GET IT OUT OF THE CACHE
HRRZ T1,T3 ;IN CASE USER DRAGGED IN NEXT USE BIT
PUSHJ P,OUCHE## ;MAKE SURE SERVICE ROUTINE KNOWS WHERE TO STOP
>
HRRZ T1,T3 ;AND CHECK ITS ADDRESS TO SEE IF IN BOUNDS
PUSHJ P,UADRCK
EXCTUU <HRRM T1,@U> ;SET WORD 1 IN 3 WORD HEADER TO NEXT BUFFER
TRNE S,IOACT ;IS THE DEVICE ALREADY ACTIVE
JRST INPT0C ;YES
MOVE T3,DEVMOD(F) ;GET DEVICE CHARACTERISTIC WORD
TLNN T3,DVTTY ;IS IT A TTY?
TRNE S,IOCON ;DISCONTINUOUS MODE?
JRST INPT0B ;YES, LOOK AT FIRST BUFFER (NOT NEXT)
SKIPN .UPMP+.UPREL
SKIPE .UPMP+.UPVRT ;IF JOB IS VIRTUAL
JRST INPT0F ; DONT TRY N-BUF LOOKAHEAD
TLNN T3,DVDSK+DVMTA ;IF A DISK,
TDZA T3,T3
LDB T3,PINBFN## ;TRY N/2 - BUFFER LOOKAHEAD (N-BUF RING)
LSH T3,-1 ;TRY 1-BUFFER LOOKAHEAD IF NOT A DISK
INPT0T: EXCTUX <HRRZ T1,@T1> ;GET LOC OF NEXT BUFFER
PUSHJ P,UADRCK ;MAKE SURE ITS OK
SOJLE T3,INPT0B ;LAST BUFFER TO CHECK IF T3 = 0
EXCTUX <SKIPGE @T1> ;IS IT FULL?
JRST INPT0T ;YES, CHECK NEXT
JRST INPT0G ;NO, START IO INTO THIS BUFFER
INPT0F: PUSHJ P,FLTST## ;IS THIS BUFFER IN CORE?
JRST INPT0D ;NO. GO BACK TO FIRST
EXCTUX <HLRZ T3,@T1>
ANDI T3,IOSIZ ;YES, IS THE WHOLE BUFFER IN CORE?
ADDI T1,(T3)
PUSHJ P,FLTST##
INPT0D: EXCTUX <SKIPA T1,@U> ;NO, GO BACK TO FIRST BUFFER
SUBI T1,(T3) ;YES, START IO FOR THIS BUFFER IF EMPTY
HRRZS T1 ;PREPARE FOR CT1
PUSHJ P,UADRCK
INPT0B: EXCTUX <SKIPL @T1> ;IS THE USE BIT SET?
INPT0G: PUSHJ P,CALIN ;NO, START SERVICE ROUTINE FILLING EMPTY BUFFER
INPT0C: EXCTUX <HRR T2,@U> ;GET USE BIT FOR NEXT BUFFER
INPT0A: EXCTUX <SKIPGE @T2> ;IS USE BIT SET YET?(BUFFER FILLED YET?)
JRST INPUT2 ;YES, RETURN IMMEDIATELY TO USER
INPT2: MOVEI T1,DEPAIO ;ASYNCHRONOUS IO?
TDNN T1,DEVAIO(F) ;YES, DON'T BLOCK THE JOB
PUSHJ P,WSYNC## ;NO, PUT JOB IN IO WAIT TILL BUFFER FILLED.
INPT3:
IFN FTKL10&FTMP,<
HRRZ T1,T2 ;ADDRESS OF BUFFER WE JUST TOUCHED
PUSHJ P,OUCHE## ;GET IT OUT OF CACHE
>
IFN FTMSGSER,<
PUSHJ P,CHKMPX## ;AN MPX DDB OR A DDB CONNECTED TO AN MPX?
JRST INPT3A ;YES, LET MSGSER WORRY ABOUT TROUBLE
>
TLZE S,IOSTBL ;RECOVERABLE ERROR?
JRST INPT1 ;YES, TRY AGAIN
INPT3A: EXCTUX <SKIPL @T2> ;RETURN WHEN BUFFER FILLED. CHECK TO MAKE SURE.
JRST INEOF ;NO, MUST BE EOF OR ERROR
INPUT2: ADDI T2,1 ;YES, GET WORD COUNT AS SET BY IO SERVICE
IFN FTKL10&FTMP,<
PUSHJ P,ISITQ ;NON-TTY AND QUEUED PROTOCOL?
JRST INPT0X ;NO
INPT0Z: PUSHJ P,CKNBF## ;SET LH(DEVNBF) FOR ALL THE BUFFERS WE CAN GET
MOVSI T1,-1 ;IF THERE ARE NO BUFFERS FOR US TO USE
TDNN T1,DEVNBF(F)
JRST [SKIPN DEVNBF(F);ANY FILLED BUFFERS AT ALL?
JRST INPT0X ;NO. (SYSTEM ERROR?)
PUSHJ P,CSDMP##;YES, SWEEP FOR THEM
JRST INPT0Z] ;GO UPDATE LH(DEVNBF) AND TRY AGAIN
ADDM T1,DEVNBF(F) ;ACCOUNT FOR THE BUFFER WE'RE ABOUT TO USE
INPT0X: MOVEI T1,-1(T2) ;IN CASE USER LOOKED AT USE-BITS
PUSHJ P,KLBUFB ;OUCHE BOTH ENDS OF BUFFER FORM HIM
>
IFN FTMSGSER,<
LDB J,PDVTYP## ;GET THE DEVICE TYPE
CAIE J,<.TYMPX/.TYEST> ;MPX: ?
JRST INPT2A ;NO--IGNORE 4-TH WORD
EXCTUX <HLRZ J,@T2> ;PICK UP THE UDX
MOVE T1,U ;ADDRESS OF RING HEADER
EXCTUU <MOVEM J,3(T1)> ;STORE FOR USER TO SEE
INPT2A:>
EXCTUX <HRRZ J,@T2> ;RH OF 3RD WORD(FIRST SO-CALLED DATA WORD)
MOVEI T1,DEPIND
ANDCAM T1,DEVAIO(F) ;DON'T WANT TO USE BUFFER AGAIN
SOJA T2,IOSETC ;SET ITEM COUNT AND BYTE POINTER
; IN 3 WORD HEADER AND RETURN TO USER
INPT1: TRNN S,IOACT ;IF DEVICE ISNT ALREADY GOING
PUSHJ P,CALIN ; START IT NOW
JRST INPT2 ;BLOCK UNTIL BUFFER FILLED
INEOF: TDNN S,[XWD IOEND,IODERR+IOBKTL+IODTER+IOIMPM]
; EOF OR ERROR BIT SET BY SERVICE ROUTINE
JRST INEOF1 ;MONITOR ERROR
TLNE S,IOEND ;IS THIS EOF?
TRO S,IODEND ;YES, SET USER EOF BIT.
IORB S,DEVIOS(F)
TRNN S,IOACT ;DEVICE ACTIVE?
PUSHJ P,RTEVMI## ;RETURNS EXEC VIRTUAL MEMORY IF ANY
POPJ P, ;RETURN TO USER'S PROGRAM
INEOF1: MOVE T1,DEVAIO(F) ;ASYNC?
TRNN T1,DEPAIO
JRST UUOER1## ;NO-MONITOR ERROR
MOVEI T1,DEPIND
IORM T1,DEVAIO(F) ;YES, INDICATE WE RETURNED EARLY
POPJ P,
;HERE ON FIRST INPUT AFTER INIT, INIT & LOOKUP, OR INIT & LOOKUP & INPUT
INPUTF: JUMPE T1,INPTF1 ;IF A BUFFER ADR IS SPECIFIED,
PUSHJ P,BRNGE## ;MAKE SURE WHOLE BUFFER IS IN CORE
EXCTUX <HRRZ T2,@U> ;RESET T2
INPTF1:
IFN FTKL10&FTMP,<
PUSHJ P,ISITQ ;QUEUED PROTOCOL?
JRST INPTF2 ;NO
SETZM DEVNBF(F) ;YES, NO BUFFERS TO START
SETZM DEVSBF(F)
>
INPTF2: HRLZI T3,IOUSE ;BUFFER IN USE BIT
EXCTUU <ANDCAB T3,@U> ;MARK THAT BUFFERS HAVE BEEN REFERENCED
; BY CLEARING SIGN BIT OF 1ST WORD
; IN 3 WORD BUFFER HEADER
JUMPE T3,INPUT3 ;HAS A RING BEEN SET UP YET?
HRRZ T1,T2 ;YES ADDRESS CHECK FIRST USER BUFFER
PUSHJ P,UADRCK ;
EXCTUX <SKIPG @T2> ;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
PUSHJ P,WAIT1## ;WAIT FOR I/O TO STOP
HRRM T3,DEVIAD(F) ;YES, STORE ADR. OF 2ND WORD OF
; A BUFFER FOR SERVICE ROUTINE
PUSHJ P,CALIN ;YES. GO START IO SERVICE ROUTINE
; FILLING BUFFER
JRST INPT0A
INPUT3: HLLZS M ;USE DEFAULT NO OF BUFFERS
PUSHJ P,UINBF
HLLZS M ;CLEAR RIGHT HALF
JRST IN1
IFN FTMP,<
;SUBROUTINE TO SEE IF A DDB IS QUEUED PROTOCOL
;RETURNS CPOPJ IF NO, CPOPJ1 IF YES
;RETURNS DEYPCL BYTE IN T1
;RESPECTS T2
ISITQ: LDB T1,DEYPCL##
JUMPE T1,CPOPJ## ;NOT QUEUED PROTOCAL IF 0
LDB T3,DEYCPF## ;MAYBE
CAIE T3,7 ;IS IT TTY/PTY?
AOS (P) ;NO, REALLY IS QUEUED
POPJ P,
IFN FTKL10,<
;SUBROUTINE TO SAVE DEVNBF, RESTORE SAVED VALUE
OTHNBF: PUSHJ P,ISITQ ;QUEUED PROTOCAL?
POPJ P, ;NO
MOVE T1,DEVNBF(F) ;YES
EXCH T1,DEVSBF(F) ;SAVE CURRENT DEVNBF, RESTORE SAVED VALUE
MOVEM T1,DEVNBF(F) ; (SWITCHING FROM INPUT TO OUTPUT OR VICE VERSA)
POPJ P,
>>
CALIN:: MOVSI S,IOSTBL ;RESET ERROR FLAG
IFN FTMSGSER,<
PUSHJ P,CHKMPX## ;AN MPX DDB OR A DDB CONNECTED TO AN MPX?
MOVEI S,0 ;YES, DON'T CHANGE THE STATE OF TROUBLE
>
ANDCAB S,DEVIOS(F) ; IN DDB AND S
TLNE S,IOEND ;DEVICE SEEN EOF?
POPJ P, ;YES, DON'T START IT
PUSH P,T2 ;NO, START IO ON THE DEVICE
PUSH P,U
HRRZ T1,DEVIAD(F) ;IS FIRST ADR. ABOVE JOB DATA AREA?
EXCTUX <HLRZ T2,@T1> ;GET LENGTH OF BUFFER
MOVE T3,DEVMOD(F)
TLNE T3,DVTTY
ANDI T2,IOSIZ ;CLEAR BOOKKEEPING BITS
ADDI T2,(T1) ;TOP ADR
SUBI T1,1 ;1ST ADR-1 (WHERE ADVBFE STORES)
PUSHJ P,LRNGE## ;MAKE SURE WHOLE BUFFER IS IS CORE & LEGAL
PUSHJ P,GTIEVM## ;GET EVM FOR THIS INPUT OPERATION IF THE
; DEVICE REQUIRES IT
MOVE T4,DEVSER(F)
PUSHJ P,DIN(T4) ;DISPATCH TO IO SERVICE ROUTINE
MOVE J,.CPJOB## ;RESTORE J
POP P,U
PJRST T2POPJ## ;RESTORE T2 AND RETURN
;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 J 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
UOUT:
IFN FTPI,< ;IF WE SUPPORT PSISER
XCT OKSGNL## ;DID USER DO A PIINI UUO?
JRST UOUT00 ;NO--CHARGE AHEAD
PUSHJ P,UOUT00 ;YES--DO OUTPUT
PJRST PSIODN## ;CALL PSISER TO LOOK FOR INTERRUPTS
>
UOUT00: TLO F,OUTPB ;SET OUTPUT UUO BIT
TLZ F,OCLOSB ;CLEAR CLOSE OUTPUT BIT
PUSHJ P,JDAADR ;SAVE NEW BIT SETTINGS.
HLLM F,(T1)
IFN FTMSGSER,<
LDB T1,PDVTYP## ;GET THE DEVICE TYPE
CAIN T1,<.TYMPX/.TYEST> ;IS THIS MPX?
PJRST MSGOUT## ;YES--CALL MSGSER
> ;END FTMSGSER
;HERE FROM DEVICE SERVICE ROUTINES ON CLOSE UUO
OUT:: HRRZ T4,DEVSER(F) ;RESTORE T4
TLNE S,IO ;IS THIS DEVICE ALREADY DOING INPUT?
JRST UOUT01 ;NO
MOVE T1,DEVCHR(F) ;SEE IF THIS IS A FULL DUPLEX DEVICE
TLNN T1,DVC2IO ; IF SO, DON'T WAIT FOR INPUT
PUSHJ P,WAIT1## ;YES, WAIT TILL IT BECOMES INACTIVE
IFN FTKL10&FTMP,<
PUSHJ P,OTHNBF
>
UOUT01: LDB T1,PIOMOD## ;GET DATA MODE SET BY INIT OR SETSTS.
CAIL T1,SD ;IS IT DUMP MODE(SD,DR,D)?
JRST OUTDMP ;YES.
IFN FTMP,<
PUSHJ P,SETCPF## ;SET JOB ON CPU OWNING DEVICE
; IF NON-QUEUED PROTOCOL
>
PUSHJ P,OUTA ;NO, CHECK FOR NON-ZERO ADDRESS(USER
; CHANGING RING)
HLRZ U,DEVBUF(F) ;REL. ADDR. OF OUTPUT BUFFER HEADER
MOVEI T1,(U) ;START OF BUFFER HEADER
MOVEI T2,2(T1) ;TOP OF HEADER
PUSHJ P,LRNGE## ;MAKE SURE HEADER IS COMPLETELY IN CORE
EXCTUX <SKIPG T2,@U> ; CHECK FIRST WORD OF BUFFER RING HEADER
JRST OUTF ;RING NOT SET UP OR FIRST REFERENCE TO RING
MOVEI T1,-1(T2) ;BUF LOC-1 IS STORED THERE
PUSHJ P,UADRCK ;ENSURE ADVBFF WONT FAULT
HRRZS T1,T2
MOVEI T3,DEPOND ;ASYNCHRONOUS OUTPUT?
TLNN S,IOSTBL ;IF TROUBLE, BLUNDER ON TO RECOVERY REGARDLESS
TDNN T3,DEVAIO(F)
JRST OUT0 ;NO, PROCEED
PUSHJ P,UADRCK ;ADR CHECK POINTER TO CURRENT BUF
IFN FTMP&FTKL10,<
PUSHJ P,OUCHE## ;CHASE OUT ANY OLD COPY
>
EXCTUX <SKIPL @T2> ;IS THE CURRENT BUFFER EMPTY
JRST OUTS ;YES, ADVANCE THE BUFFER HEADER
MOVE T3,DEVCHR(F) ;IF THIS ISN'T ONE OF NETSER'S
TLNN T3,DVCNET ; DEVICES, THEN WE'RE
POPJ P, ; DONE, OTHERWISE CALL THE DRIVER
OUT0: TRNE S,IOACT ;ADR CHECK CURRENT BUFFER ONLY IF NOT I/O ACTIVE
JRST OUT1 ;BUFFER ALREADY ADDRESS CHECKED
HRRZ T1,DEVOAD(F) ;CURRENT BUFFER LOC DEVICE IS USING
PUSHJ P,UADRCK ;MAKE SURE IT'S LEGAL
PUSHJ P,BRNGE## ;MAKE SURE WHOLE BUFFER IS IN
EXCTUX <HRRZ T2,@U> ;OK - RESTORE T2
HRRZI T1,1(T2) ;PROCEED ONLY IF ADDR. OF WORD COUNT IN BOUNDS
CAIG T1,JOBPFI## ;IS 1ST ADR ABOVE JOB DATA AREA?
JRST ADRERR## ;NO, PRINT ERROR MESSAGE
OUT1: MOVE T1,DEVADV(F) ;IF BUFFERS SHOULDN'T BE DEADVANCED
TDNN T1,[DEPADV,,DEPOND] ; ON ERROR INTERCEPT OR DUE TO TROUBLE
AOSA U
JRST OUT3 ;THEN JUST START THE DEVICE
MOVE T4,DEVMOD(F) ;GET CHARACTERISTICS
EXCTUX <HRRZ T1,@U> ;GET RH OF BYTE POINTER.
ADDI T2,1 ;REL. ADDR. OF 3RD WORD IN BUFFER.
JUMPE T1,OUT2 ;WRDCNT ALREADY STORED IF INTERCEPT RETRY
SUBI T1,(T2) ;DISTANCE FILLED BY USER.
TRNE S,IOWC
OUT2: EXCTUX <HRRZ T1,@T2>
SKIPGE T3,T1 ;PRESERVE USER'S WORDCOUNT
PJRST ADRERR## ;NEGATIVE WORDCOUNTS ARE ILLEGAL
TLNE T4,DVDSK!DVDTA ;IF DISK OR DTA,
MOVEI T1,200 ; MAKE SURE WHOLE BUFFER IS THERE
OUT2B: PUSH P,T2 ;SAVE L(WRDCNT WORD)
EXCH T1,T2 ;FST ADR INTO T1
ADDI T2,(T1) ;TOP ADR IN T2
PUSHJ P,LRNGE## ;MAKE SURE WHOLE BUFFER IS OK
LDB T1,PIOMOD## ;I/O MODE
CAIE T1,BYTMOD ;BYTE MODE?
JRST OUT2A ;NO
EXCTUX <LDB T1,[POINT 6,@U,5]> ;POSITION FIELD OUT OF THE USER'S BYTE POINTER
MOVNS T1
ADDI T1,^D36 ;T1=36 - POSITION FIELD
MOVE T4,DEVMOD(F) ;GET CHARACTERISTICS
TLNE T4,DVDSK ;IF DSK AND NOT LAST BUFFER
TLNE F,OCLOSB ; THEN NO PARTIAL WORDS
SKIPGE T1 ;IF.LE.0, NO BYTES ARE STORED IN THIS WORD
MOVEI T1,0 ;0 BYTES IN THE LAST WORD
EXCTUX <LDB T4,[POINT 6,@U,11]> ;BYTE SIZE FROM USER'S BYTE POINTER
IDIVI T1,(T4) ;NUMBER OF BYTES IN THE LAST WORD
SOS T2,T3 ;OUT2 ROUNDED UP
MOVEI T3,^D36
IDIVI T3,(T4) ;NUMBER OF BYTES PER WORD
IMULI T3,(T2) ;NUMBER OF BYTES IN THE RECORD NOT COUNTING
; THE LAST WORD
ADDI T3,(T1) ;NUMBER OF BYTES IN THE RECORD
OUT2A: POP P,T2 ;GOOD-RESTORE T2
TRNN S,IOWC ;COMPUTE WORD COUNT FOR USER?
EXCTUU <HRRM T3,@T2> ;YES, STORE WORD COUNT IN 3RD WORD OF BUFFER.
SUBI U,1 ;REL. ADDR. OF 1ST WORD IN HEADER
; (POINTER TO CURRENT BUFFER).
SUBI T2,1 ;REL. ADDR. OF 2ND WORD IN BUFFER
EXCTUX <HRRZ T1,@T2> ;START OF NEXT BUF
PUSH P,T2
PUSHJ P,UADRCK ;MAKE SURE IT'S IN CORE
PUSHJ P,BRNGE##
POP P,T2
HRLZI T1,IOUSE ;FLAG CURRENT BUFFER CONTAINS ACTIVE DATA.
HRL W,S ;SAVE CURRENT STATE OF IOACT
EXCTUU <IORB T1,@T2>
EXCTUU <HRRM T1,@U> ;ADVANCE CURRENT BUFFER ADDRESS
IFN FTKL10&FTMP,<
PUSHJ P,ISITQ ;NON-TTY, QUEUED PROTOCOL
JRST OUT3 ;NO
PUSHJ P,CKNBF## ;SET LH(DEVNBF) FOR ALL THE BUFFERS WE CAN DO
PUSHJ P,STONBF## ;SAVE SWEEP NUMBER, CPU
AOS DEVNBF(F) ;UPDATE RH(DEVNBF)
PUSHJ P,CKNBF## ;ADD IT TO LH IF ON RIGHT CPU
>
OUT3: MOVSI T1,DEPADV ;DON'T DEADVANCE BUFFERS BIT
ANDCAM T1,DEVADV(F) ;CLEAR BEFORE RETRY. REPEAT OF ERRORS
; WILL SET IT AGAIN.
MOVSI S,IOSTBL ;CLEAR TROUBLE FLAG
ANDCAB S,DEVIOS(F)
PUSHJ P,CALOUI
HLRZ U,DEVBUF(F) ;U TO REL. ADDR. OF BUFFER HEADER
EXCTUX <HRRZ T2,@U> ;T2 TO REL. ADDR. OF 2ND WORD OF BUFFER.
HRRZ T1,T2
PUSHJ P,UADRCK
MOVEI T1,@U ;IN CASE WE REDO THE UUO
EXCTUU <HLLZS 1(T1)> ; AFTER AN OFF-LINE INTERCEPT
EXCTUX <SKIPL @T2> ;HAS SERVICE ROUTINE EMPTIED NEXT BUFFER
; YET (USE BIT = 0)?
JRST OUTS ;YES RETURN TO USER
MOVEI T1,DEPAIO ;ASYNC IO?
TDNE T1,DEVAIO(F)
JRST OUT4 ;YES, DON'T BLOCK
PUSHJ P,WSYNC## ;NO - WAIT
TLZN S,IOSTBL ;ERROR OCCURED?
JRST OUTS ;RETURN TO USER.
HRL W,S ;YES. RESET LH(W)
JRST OUT3 ;AND TRY AGAIN
OUT4: MOVEI T1,DEPOND ;INDICATE BUFFER HEADER NOT
IORM T1,DEVAIO(F) ;YES,, YET SET UP FOR NEXT OUTPUT
POPJ P, ;RETURN WITHOUT CLEARING ANYTHING
OUTF: TLO S,IO ;INDICATE OUTPUT FOR IOSETC
EXCTUX <SKIPE T2,@U>
JRST OUTF1
PUSHJ P,DFTNB ;GET DEFAULT NO OF BUFS
HRR M,T2
MOVEM S,DEVIOS(F) ;IN CASE UOUTBF CALLS CORE1
PUSHJ P,UOUTBF
HLRZ U,DEVBUF(F)
OUTF1: EXCTUX <HRRZ T1,@U> ;CALL BUFCLR EARLY
PUSHJ P,BUFCLR ; TO ENSURE THAT A FAULT WONT HAPPEN
JRST ADRERR## ; AFTER THE VIRGIN-RING BIT IS CLEARED
HRLZI T1,IOUSE
EXCTUU <ANDCAB T1,@U> ;IOUSE:=0
HRRM T1,DEVOAD(F)
OUTS: EXCTUX <HRRZ T1,@U> ;CLEAR NEXT OUTPUT BUFFER.
MOVSI T2,DEPIBC ;USER DID AN OPEN WITH INHIBIT BUFFER CLEAR BIT
MOVSI T3,IOIBC ;INHIBIT CLEARING THIS BUFFER BIT
TDNE T2,DEVTYP(F) ;DID THE USER ENABLE FOR INHIBITING CLEARING BUFFER?
EXCTUX <TDNN T3,@U> ;YES, DOES HE WANT THIS BUFFER NOT TO BE CLEARED
CAIA ;NO, CLEAR R FROM THE LEFT HALF WORD IF ITS ON
JRST OUTS1 ;YES, SKIP CLEARING THE NEXT BUFFER
PUSHJ P,BUFCLR ;BEING CLEARED.
JRST ADRERR## ;ADDRESS CHECK
OUTS1: EXCTUX <HRRZ T2,@U>
EXCTUX <LDB J,[POINT 17,@T2,17]>
MOVEI T1,DEPOND ;CLEAR OUTPUT NOT YET DONE FLAG
ANDCAM T1,DEVAIO(F)
SOJA J,IOSETC
; ADDRESS+1
; JBFCTR:=(BUFFER SIZE-1)*[36/BYTE SIZE]
; RETURN TO USER'S PROGRAM
CALOUI: TLNE W,IOACT
POPJ P,
CALOUT::MOVSI T1,DEPSIE ;BIT TO TEST
TDNN T1,DEVJOB(F) ;WANT TO LOOK FOR ERROR
JRST CALOU1 ;NO-PROCEED
MOVE T1,DEVIOS(F) ;YES - CHECK I/O STATUS
TRNE T1,742000 ;ANY ERRORS? (INCLUDE IOTEND)
POPJ P, ;RETURN (NO OUTPUT DONE)
CALOU1: PUSHJ P,GTOEVM## ;GET EVM FOR THIS OUTPUT OPERATION
; IF THE DEVICE REQUIRES IT
MOVE T4,DEVSER(F) ;SETUP DISPATCH ADR. FOR SERVICE ROUTINE
PUSHJ P,DOU(T4) ;START DEVICE DOING OUTPUT
MOVE J,.CPJOB## ;RESTORE J
MOVE S,DEVIOS(F) ;GET DEVICE STATUS
TRNN S,IOACT ;IS THE DEVICE I/O ACTIVE NOW?
PJRST RTEVMO## ;NO, RETURN ANY EXEC VIRTUAL MEMORY THE
; DEVICE MAY HAVE ASSIGNED
POPJ P, ;I/O ACTIVE, JUST RETURN
;HERE ON DUMP MODE INPUT
INDMP: MOVEI T1,DDI(T4) ;DISPATCH TO DO DUMP MODE INPUT
PJRST DMPIO ;JOIN COMMON INPUT/OUTPUT CODE
;HERE ON DUMP MODE OUTPUT
OUTDMP: MOVEI T1,DDO(T4) ;DISPATCH TO DO DUMP MODE OUTPUT
; AND FALL INTO COMMON INPUT/OUTPUT CODE
;ROUTINE TO SETUP FOR DUMP MODE I/O. IF THIS IS A
;CHANNEL DEVICE (DSK OR MTA) CALL THE SERVICE
;ROUTINE DIRECTLY AND MAPIO WILL FIXUP THE IOWDS AS NECESSARY. OTHERWISE,
;FIND THE LARGEST IOWD IN THE LIST, ALLOCATE ENOUGH EXEC VIRTUAL MEMORY
;TO COVER THAT IOWD, MAP THE FIRST IOWD, AND THEN CALL THE SERVICE ROUTINE
;TO START THE I/O
;CALLING SEQUENCE:
; MOVEI T1,DUMP I/O DISPATCH ADDRESS
; PUSHJ P,DMPIO
;NEVER RETURN IF ADDRESS CHECK
DMPIO: PUSHJ P,WSYNC## ;WAIT UNTIL THE DEVICE IS INACTIVE
IFN FTMP,<
PUSHJ P,SETCPF## ;GET RUNNING ON RIGHT CPU
; IF NON-QUEUE PROTOCOL
>
PUSHJ P,DMPEV## ;GET EVM FOR THE I/O IF NEEDED
PUSHJ P,(T1) ;CALL THE DEVICE ROUTINE TO START THE I/O
PUSHJ P,WAIT1## ;WAIT UNTIL ITS DONE
PJRST RTNEVM## ;RETURN ANY EVM JOB HAS FOR DOING I/O
;CALLING SEQUENCE:
; PUSHJ P,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.
OUTA:: TRNE M,-1 ;IS BUFFER ADDRESS SPECIFIED?
TLNE F,OCLOSB ;THIS OPTION DOESN'T APPLY DURING CLOSE UUO
POPJ P, ;NO
PUSHJ P,WAIT2 ;YES, FORCE OUT ALL CURRENT BUFFERS
HLRZ U,DEVBUF(F) ;CURRENT OUTPUT BUFFER
EXCTUU <HRRM M,@U> ;SAVE IN RING HEADER
HRRM M,DEVOAD(F) ;SAVE AS NEXT BUF TO WRITE
HRLZI T1,IOUSE
EXCTUU <ANDCAM T1,@U> ;CLEAR THE USE-BIT
POPJ P, ;RETURN
;RESDV.-- UUO TO RESET CHANNEL
;CALL: MOVE AC,CHANNEL
; RESDV. AC,
;ERROR IF NOT IMPLEMENTED, OR CHANNEL NOT OPEN(AC=-1)
;OK IF DONE
RESDV: JUMPL T1,RTM1 ;ERROR IF ILLEGAL CHANNEL
HRRZ P1,T1 ;SETUP CHANNEL NUMBER
PUSHJ P,SETUF ;SETUP DDB
JRST RTM1 ;IF NONE--RETURN ERROR
HRLM P1,.UPMP+.UPCTA ;PUT CHANNEL #
; (IN CASE OF TROUBLE AND CALL HNGSTP)
PUSHJ P,RELEAC ;RESET IT
JRST CPOPJ1## ;SKIP RETURN
SUBTTL RELEASE UUO
;RELEASE A DEVICE
RELEA1::
RELEA0:
RELEA2::RELEA3::
TRZ M,-1 ;CLOSE BOTH INPUT AND OUTPUT
PUSHJ P,CLOSE1
PUSHJ P,WAIT1## ;WAIT FOR DEVICE TO BECOME INACTIVE
RELEAC::HRRZ T4,DEVSER(F) ;RESTORE T4
RELEA5::
IFN FTMP,<
PUSHJ P,SETCPF##
>
PUSHJ P,DRL(T4) ;DISPATCH TO DEVICE SERVICE ROUTINE
MOVEI S,IOACT ;CLEAR IO ACTIVE BIT
ANDCAB S,DEVIOS(F) ;AND RETURN WITH S SET
LDB T2,IADPTR## ;GET COUNT OF NO OF CHANS DEVICE ON(IF DTA)
SOS T2 ;COUNT DOWN BY ONE
MOVE T1,DEVMOD(F)
TLNE T1,DVDTA ;DEVICE A DTA?
DPB T2,IADPTR## ;YES, STORE UPDATED COUNT
PUSHJ P,JDAADR ;CLEAR DEVICE ASSIGNMENT
SETZM (T1) ;U=0 IF NO EXTENDED CHANS OPEN
PUSH P,P1 ;SAVE CHANNEL
MOVEI P1,0 ;START AT CHANNEL 0
RELE5A: PUSHJ P,NXTCH ;GET NEXT CHANNEL
JRST RELEA4 ;FINISHED
CAIN T1,(F) ;SAME DEVICE ON ANOTHER CHANNEL?
JRST P1POPJ## ;YES, EXIT
JRST RELE5A ;LOOP FOR THE NEXT OPEN CHANNEL
RELEA4: POP P,P1 ;RESTORE P1
;HERE FROM ERROR STOP ROUTINES (SWAP READ ERROR, PARITY ERROR, ETC.)
RELEA9::JUMPE F,CPOPJ##
MOVEI T3,0
PUSHJ P,RTIEVM##
MOVEI T3,0
PUSHJ P,RTOEVM##
MOVEI T1,DEPAIO
ANDCAM T1,DEVAIO(F) ;CLEAR NON-BLOCKING I/O FLAG
RELEA7::MOVEI T2,ASSPRG ;CLEAR ASSIGNED BY PROGRAM BIT
RELEA6::ANDCAB T2,DEVMOD(F) ;CALLED FROM DEASSIGN
TRZ T2,777 ;CLEAR JOB NO. FIELD
TLNE T2,DVDSK+DVMTA ;DSK?
DPB T2,PINBFN## ;YES, CLEAR NO OF BUFS
TDNE T2,[XWD TTYATC,ASSCON+ASSPRG]
POPJ P, ;DEVICE ASSIGNED BY OTHER MEANS TOO
SETZM DEVBUF(F) ;NO BUFFER HEADERS
IFN FTPI,<
SKIPE DEVPSI(F) ;SOMEONE PSI'ING ON THIS DEVICE
PUSHJ P,PSIRMV## ;YES, REMOVE FROM PSI CHAIN
>; END FTPI
PUSHJ P,CLRDVL ;DISCONNECT JOB FROM DDB
MOVE T2,DEVMOD(F) ;PUT DEVMOD IN T2
IFN FTMTSET,<
TLNN T2,DVTTY ;DON'T BE FOOLED BY NULL
TLNN T2,DVMTA
JRST RELE6A
HRRI T2,MTSIZ##+1 ;GET DEFAULT MTA BLOCK SIZE
DPB T2,PBUFSZ## ; SET SYSTEM DEFAULT IN BUFFER
TRZ T2,-1 ;CLEAR FOR DENSITY
DPB T2,TDYDN1## ; SET TO FORCE INSTALLATION DENSITY
DPB T2,PBUFRM## ;CLEAR FRAME-COUNT
RELE6A:> ;END CONDITIONAL ON FTMTSET
IFN FTMDA,<
MOVSI T1,DVCMDA ;SEE IF MDA CONTROLS THIS DEVICE
TDNE T1,DEVCHR(F) ;DOES IT?
PUSHJ P,RELMDA ;YES, TELL'EM
>;END FTMDA
IFN FTNET,<
MOVSI T1,DVCNET ;CHECK FOR A NETWORK DEVICE
TDNE T1,DEVCHR(F) ;IS IT
PJRST ZAPNET## ;YES, CLEAR THE DDB
>;END FTNET
IFN FTSPL,<
SKIPL DEVSPL(F) ;IS DEVICE A SPOOLED DISK
>
TLNE T2,DVDSK ;IS DEVICE A DSK
PJRST CLRDDB## ;YES-RETURN DDB TO STORAGE
IFN FTMSGSER,<
LDB T2,PDVTYP## ;GET THE DEVICE TYPE
CAIN T2,.TYMPX/.TYEST;IS THIS AN MPX DDB?
PUSHJ P,ZAPMPX## ;YES--KILL IT OFF
> ;END FTMSGSER
PJRST XTKLDB## ;GO KILL XTC DDB IF NECESSARY
IFN FTMDA,<
RELMDA: PUSH P,T2 ;SAVE DEVMOD
MOVE T1,DEVNAM(F) ;GET DEVICE NAME
LDB T2,PDVTYP## ;GET DEVICE TYPE
MOVE T3,J ;GET OWNER'S JOB
PUSH P,W ;IPCSER WIPES W
PUSHJ P,SNDFIN## ;TELL MDA
JFCL ;IGNORE ERROR (SLEEP MAY BE BETTER)
POP P,W ;GET BACK PDB
JRST T2POPJ## ;RESTORE DEVMOD, AND RETURN
>;END IFN FTMDA
SUBTTL STATUS SETTING AND GETTING UUO'S
;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.
USTATO::
IFN FTXTC,<
PUSHJ P,XTCIOS## ;GET S
>
TRNE S,(M) ;SKIP IF ANY INDICATED BITS ARE ONE
AOS (P)
POPJ P, ;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.
USTATS::
IFN FTXTC,<
PUSHJ P,XTCIOS## ;GET S
>
HRRZ T1,S ;GET USER HALF OF IOS.
PJRST PUTWDU## ;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.
USTATZ::
IFN FTXTC,<
PUSHJ P,XTCIOS## ;GET S
>
TRNN S,(M) ;SKIP IF ALL INDICATED BITS ARE ZERO
AOS (P)
POPJ P, ;RETURN TO USER
;IN UUO - LIKE INPUT SKIPS IF EOF OR ERRORS OR BUFFER NOT FULL IF NON-BLOCKING I/O
TIN:: PUSHJ P,UIN00 ;DO INPUT UUO
LDB T1,PIOMOD## ;I/O MODE
TRNN S,IODEND ;EOF
CAIL T1,SD ;OR DUMP MODE?
JRST TIN1 ;YES
HRRZ T1,DEVBUF(F) ;BUFFER HEADER ADDRESS
PUSHJ P,UADRCK ;LEGAL?
EXCTUX <HRRZ T2,(T1)> ;CURRENT USER BUFFER
MOVEI T1,-1(T2) ;DEVIOS WORD
PUSHJ P,LRNGE## ;LEGAL?
EXCTUX <SKIPGE (T2)> ;IF THE BUFFER ISN'T EMPTY,
EXCTUX <MOVE S,-1(T2)> ;GET DEVIOS FROM THE BUFFER
TIN1: MOVEI T1,DEPIND ;INPUT NOT YET DONE?
TRNN S,IOBKTL+IODTER+IODERR+IOIMPM+IODEND
TDNE T1,DEVAIO(F)
JRST IOPTST ;GIVE FAIL RETURN TO USER
POPJ P,
;OUT UUO - LIKE OUTPUT - SKIPS IF ERRORS OR NO EMPTY BUFFER IF NON-BLOCKING I/O
TOUT:: PUSHJ P,UOUT00 ;DO OUTPUT UUO
MOVEI T1,DEPOND ;OUTPUT NOT YET DONE?
TRNN S,IOBKTL+IODTER+IODERR+IOIMPM+IOTEND
TDNE T1,DEVAIO(F)
JRST IOPTST ;GIVE FAIL RETURN TO USER
POPJ P,
IFN FTPI,<
IOPTST: AOS (P) ;INCREMENT FOR FAIL RETURN
MOVE J,.CPJOB## ;GET CURRENT JOB NUMBER
XCT OKSGNL## ;HAVE PSISER
POPJ P, ;NOPE
PJRST PSIEDN## ;LET PSISER REPORT ERROR
>
IFE FTPI,<
IOPTST==CPOPJ1## ;IF PSISER NOT INSTALLED
>
;5 UUOS FOR EACH INSTALLATION TO DEFINE
;OPCODES 42-46
SUBTTL ROUTINES TO ADVANCE BUFFERS
;ROUTINE TO ADVANCE OUTPUT BUFFER AT INTERRUPT LEVEL
;CALL: PUSHJ P,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
ADVBFE::MOVE T1,DEVOAD(F) ;USER OR EXEC VIRTUAL ADDRESS OF CURRENT BUFFER
TRNN T1,-1 ;HAS IT BEEN CLEARED BY A RELEASE?
POPJ P, ;YES, GIVE STOP I/O RETURN
PUSHJ P,SVEUF## ;PUSH THE USER BASE REGISTER AND SETUP UBR
; SO THAT CURRENT USER IS ADDRESSABLE
IFN FTMSGSER,<
MOVEI T2,DEPMSG ;IS THIS DEVICE CONTROLLED BY
TDNE T2,DEVMSG(F) ; BY MSGSER
PJRST MSGBFE## ;YES--GO ADVANCE THINGS
>
PUSH P,T3 ;ITS POSSIBLE THAT SOME DEVICE ROUTINES
; DEPEND ON T3 BEING INTACT ON RETURN
MOVSI T3,IOUSE ;SET TO TURN OFF THE USE BIT
HRRZ T2,DEVEVM(F) ;IS THIS BUFFER MAPPED BY THE EXEC MAP?
JUMPE T2,ADVBE1 ;JUMP IF NOT A MAPPED ADDRESS
MOVEM S,-1(T1) ;THE BUFFER IS ADDRESSABLE - STORE IOS
ANDCAB T3,(T1) ;GET THE SIZE AND ADDRESS OF THE NEXT BUFFER
; AND CLEAR THE USE BIT
IFN FTMP&FTKL10,<
PUSHJ P,KLBUFM ;GET BUF OUT OF CACHE
>
HRRZ T1,T3 ;ADDRESS OF START OF NEXT BUFFER
PUSHJ P,IADCKL ;MAKE SURE ITS LEGAL (MIGHT BE PAGED OUT)
JRST ADVBU2 ;ILLEGAL ADDRESS (ADR CHECK)
HRLM T3,DEVEVM(F) ;LEGAL ADR, SAVE AS NEXT BUFFER LOC
PUSHJ P,BADCK ;IS WHOLE BUFFER LEGAL AND IN CORE?
JRST ADVBU2 ;NO, STOP IO
TLZ T3,^-IOSIZ ;ENSURE JUST SIZE
PUSHJ P,ADVEVM## ;ADVANCE THE BUFFER IN EXEC VIRTUAL MEMORY
JRST ADVBU2 ;NOT ENOUGH PAGES TO COVER THE NEXT BUFFER
; UUO LEVEL WILL ALLOCATE MORE ON THE NEXT UUO
DPB T1,PDVOAD## ;STORE THE EXEC VIRTUAL ADDRESS OF THE NEXT
; BUFFER FOR THE DEVICE ROUTINE
SKIPL (T1) ;IS THE NEXT BUFFER AVAILABLE? (USE BIT ON)
JRST ADVBU2 ;NO, GIVE STOP I/O RETURN
JRST ADVBU1 ;GO CHECK FOR OTHER REASONS I/O SHOULD BE STOPPED
ADVBE1:
;HERE TO ADVANCE A BUFFER WHICH IS NOT MAPPED BY THE EXEC MAP
EXCTXU <MOVEM S,-1(T1)>
EXCTUU <ANDCAB T3,(T1)>;CLEAR THE USE BIT AND GET THE SIZE AND
; ADDRESS OF THE NEXT BUFFER
IFN FTKL10&FTMP,<
PUSHJ P,KLBUF ;GET BUF ENDPOINTS OUT OF CACHE
>
HRRZ T1,T3 ;ADDRESS OF START OF NEXT BUFFER
PUSHJ P,IADCKL ;MAKE SURE ITS LEGAL (MIGHT BE PAGED OUT)
JRST ADVBU3 ;ILLEGAL ADDRESS (ADR CHECK)
HRRM T3,DEVOAD(F) ;LEGAL ADR, SAVE AS NEXT BUFFER LOC
PUSHJ P,BADCK ;IS WHOLE BUFFER LEGAL AND IN CORE?
JRST ADVBU3 ;NO, STOP IO
EXCTUX <SKIPL (T3)> ;NEXT BUFFER AVAILABLE?
JRST ADVBU3 ;NO, GIVE STOP I/O RETURN
JRST ADVBU1 ;YES, CHECK FOR OTHER REASONS WHY I/O SHOULD STOP
;ROUTINE TO ADVANCE INPUT BUFFER AT INTERRUPT LEVEL
;CALL: PUSHJ P,ADVBFF
; 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
ADVBFF::MOVE T1,DEVIAD(F) ;USER OR EXEC VIRTUAL ADDRESS OF CURRENT BUFFER
TRNN T1,-1 ;HAS IT BEEN CLEARED BY A RELEASE?
POPJ P, ;YES, GIVE STOP I/O RETURN
PUSHJ P,SVEUF## ;PUSH THE USER BASE REGISTER AND SETUP UBR
; SO THAT CURRENT USER IS ADDRESSABLE
PUSH P,T3 ;ITS POSSIBLE THAT SOME DEVICE ROUTINES
; DEPEND ON T3 BEING INTACT UPON RETURN
IFN FTMSGSER,<
MOVEI T2,DEPMSG ;IF THIS DEVICE IS CONTROLLED
TDNE T2,DEVMSG(F) ; VIA MSGSER. SHUT IT DOWN NOW
JRST ADVBU2 ; SINCE NEXT BUFFER MAY HAVE I/O TOO
>
MOVSI T3,IOUSE ;SET TO TURN ON THE USE BIT
HRRZ T2,DEVEVM(F) ;IS THE BUFFER MAPPED BY THE EXEC MAP?
JUMPE T2,ADVBF1 ;JUMP IF NOT A MAPPED ADDRESS
MOVEM S,-1(T1) ;THE BUFFER IS ADDRESSABLE - STORE IOS
IORB T3,(T1) ;GET THE SIZE AND ADDRESS OF THE NEXT BUFFER
; AND TURN ON THE USE BIT
TLZ T3,^-IOSIZ ;CLEAR THE BOOKEEPING BITS FOR ADVEVM
HRRZ T1,T3 ;ADDRESS OF START OF BUFFER
PUSHJ P,IADCKL ;MAKE SURE ITS LEGAL (MIGHT BE PAGED OUT)
JRST ADVBU2 ;ILLEGAL ADDRESS (ADR CHECK)
HRLM T3,DEVEVM(F) ;LEGAL ADR, SAVE AS NEXT BUFFER LOC
PUSHJ P,BADCK ;IS WHOLE BUFFER LEGAL AND IN CORE?
JRST ADVBU2 ;NO, STOP IO
PUSHJ P,ADVEVM## ;ADVANCE THE BUFFER IN EXEC VIRTUAL MEMORY
JRST ADVBU2 ;NOT ENOUGH PAGES TO COVER THE NEXT BUFFER
; UUO LEVEL WILL ALLOCATE MORE ON NEXT UUO
DPB T1,PDVIAD## ;STORE THE EXEC VIRTUAL ADDRESS OF THE NEXT
; BUFFER FOR THE DEVICE ROUTINE
SKIPGE (T1) ;IS THE NEXT BUFFER AVAILABLE? (USE BIT OFF)
JRST ADVBU2 ;NO, GIVE STOP I/O RETURN
JRST ADVBU1 ;GO CHECK FOR OTHER REASONS I/O SHOULD BE STOPPED
ADVBF1:
;HERE TO ADVANCE A BUFFER WHICH IS NOT MAPPED BY THE EXEC MAP
EXCTXU <MOVEM S,-1(T1)>
EXCTUU <IORB T3,(T1)>;TURN ON THE USE BIT AND GET THE ADDRESS
; AND SIZE OF THE NEXT BUFFER
IFN FTMP&FTKL10,<
PUSHJ P,KLBUF ;GET BUF ENDS OUT OF CACHE
>
HRRZ T1,T3 ;ADDRESS OF START OF BUFFER
PUSHJ P,IADCKL ;MAKE SURE ITS LEGAL (MIGHT BE PAGED OUT)
JRST ADVBU3 ;ILLEGAL ADDRESS (ADR CHECK)
HRRM T3,DEVIAD(F) ;LEGAL ADR, SAVE AS NEXT BUFFER LOC
PUSHJ P,BADCK ;IS WHOLE BUFFER LEGAL AND IN CORE?
JRST ADVBU3 ;NO, STOP IO
EXCTUX <SKIPGE (T3)> ;IS THE BUFFER EMPTY?
JRST ADVBU3 ;NO, GIVE STOP I/O RETURN
;HERE TO SEE IF I/O SHOULD BE STOPPED SO JOB CAN BE SHUFFLED,
; SWAPPED, LOCKED, OR THE USER HAS TYPED CONTROL C
ADVBU1::LDB T2,PJOBN## ;GET JOB NUMBER OF JOB I/O IS BEING DONE FOR
CAMN T2,FORCE## ;IF TRY TO FORCE THIS JOB OUT
JRST ADVBU2 ; GIVE STOP I/O RETURN
SKIPGE T2,JBTSTS##(T2) ;IS THE JOB RUNNABLE?
TLNE T2,SHF!CMWB!CNTRLC
JRST ADVBU2 ;NO, GIVE STOP I/O RETURN
IFN FTLOCK,<
TRNN T2,LOK ;TRYING TO LOCK THE JOB IN CORE?
>
TRNE S,IOCON ;OR DISCONTINUOUS MODE I/O?
JRST ADVBU2 ;YES, SHUT DOWN THE I/O
AOSA -1(P) ;SET SKIP (CONTINUE I/O) RETURN
ADVBU2: PUSHJ P,RTNEVM## ;SHUTTING DOWN I/O, GIVE BACK ANY EVM
ADVBU3:
IFN FTMP&FTKL10,<
HRRZ T1,T3
PUSHJ P,OUCHE## ;REMOVE LINE FROM CACHE
>
JRST T3POPJ## ;RESTORE T3
;ROUTINE TO ADDRESS CHECK A BUFFER
;CALLING SEQUENCE:
; MOVE T3,USER VIRTUAL BUFFER ADDRESS
; PUSHJ P,BADRCK
; RETURN HERE ON ADDRESS CHECK
; RETURN HERE IF BUFFER IS OK
;PRESERVES T3
BADCK:
BADRCK::HRRZ T1,T3 ;T1=ADDRESS OF FIRST WORD IN THE BUFFER
PUSHJ P,IADRCK ;IN-CORE AND LEGAL?
POPJ P, ;NO
EXCTUX <HLRZ T2,(T1)> ;SIZE
ANDI T2,IOSIZ
ADDI T2,(T1) ;TOP OF BUFFER
SOJA T1,ZRNGE## ;LET VMSER CHECK THE LIMITS
IFN FTMP&FTKL10,<
;SUBROUTINE TO FIX UP A BUFFER WITH RESPET TO CACHE
; INSURES THAT THE ENDPOINTS OF A BUF ARE OUT OF CACHE
; ENTER T1 = ADDR OF BUFFER (CALL KLBUFM IF IN EVM)
; PRESERVES T3
KLBUFB: EXCTUX <HRRZ T4,1(T1)>
JRST KLBUF2
KLBUFM: SKIPA T4,1(T1) ;GET WORD COUNT
KLBUF: TDZA T4,T4 ;CHAN DEV - DONT WORRY ABOUT TOP
KLBUF2: ADDI T4,1(T1) ;POINT TO END OF BUFFER
PUSHJ P,OUCHE## ;CHASE FROM CACHE
TRNN T1,3 ;S - WORD IN SAME LINE?
SOJA T1,KLBUF1 ;NO, CHASE PREVIOUS LINE
ADDI T1,1 ;YES, POINT AT WORDCOUNT
TRNN T1,3 ;WRDCNT IN SAVE LINE?
KLBUF1: PUSHJ P,OUCHE## ;NO, CHASE WRDCNT
SKIPE T1,T4 ;IF CPU HAS TOP OF BUF IN CACHE
PJRST OUCHE## ;REMOVE TOP LINE AND RETURN
POPJ P, ;CHAN DEV - DOESN'T HAVE LOC IN CACHE
>
;ROUTINE TO ADDRESS CHECK AT UUO LEVEL ONLY
;CALL HRRZ T1,REL ADR.
; PUSHJ P,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
;
;PRESERVES ALL ACS.
UADCK1::TRNN T1,777760 ;IN USER ACS?
POPJ P, ;YES, ADDRESS IS OK
;FALL INTO UADRCK
;ROUTINE TO ADDRESS CHECK AT UUO LEVEL ONLY
;USER ACS ARE ALSO ILLEGAL(ADR IS FOR IO USE LATER AT
;INTERRUPT LEVEL)
;CALL: HRRZ T1,REL.ADR.
; PUSHJ P,UADRCK
; NEVER RETURN IF ERROR
;
;PRESERVES ALL ACS.
UADRCK::CAML T1,.UPMP+.UPHSS ;IS ADDRESS IN THE USER HIGH SEGMENT?
CAML T1,.UPMP+.UPHSE ; . . .
CAIG T1,JOBPFI## ;NO, ABOVE PROTECTED JOBDAT?
JRST ADRERR## ;IN HIGH SEG OR PROTECTED JOBDAT, ERROR
EXCTUX <SKIP (T1)> ;LEGAL ADDRESS, SEE IF IT EXISTS
ERJMP UUOFLT## ;IF NOT, SEE WHY NOT (MAYBE NEED PFH)
POPJ P, ;ADDRESS IS OK TO REFERENCE
;ROUTINE TO ADDRESS CHECK AT ANY LEVEL
;CALL: HRRZ T1,REL. ADR.
; PUSHJ P,IADRCK
; ERROR RETURN(ERROR MESSAGE NOT PRINTED,JOB NOT STOPPED)
; OK RETURN
;
;PRESERVES ALL ACS.
REPEAT 0,< ;CAN'T USE AT INTERRUPT LEVEL YET
IADRCK::EXCTUX <SKIP (T1)> ;SEE IF WE CAN TOUCH IT
ERJMP CPOPJ## ;IF WE CAN'T, TAKE ERROR RETURN
IADCKL: CAIG T1,JOBPFI## ;IS ADDRESS IN PROTECTED JOBDAT?
POPJ P, ;YES, ERROR EVEN IF IT DOES EXIST
CAML T1,.UPMP+.UPHSS ;IS ADDRESS IN USER HIGH SEGMENT?
CAML T1,.UPMP+.UPHSE ; . . .
AOS (P) ;LOW SEG ADDRESS, SUCCESSFUL RETURN
POPJ P, ;RETURN
> ;END REPEAT 0
IADRCK::PUSHJ P,FLTST## ;MAKE SURE IN CORE
POPJ P, ;ITS NOT
IADCKL: CAILE T1,JOBPFI## ;ADR. ABOVE PROT. PART OF JOB DATA AREA?
CAMLE T1,.UPMP+.UPHVA ;YES, BELOW OR EQUAL TO PROTECT.?
POPJ P, ;NO
CAML T1,.UPMP+.UPHSS
CAML T1,.UPMP+.UPHSE ;MAKE SURE PAGE IS IN LOW SEGMENT
AOS (P) ;IT IS, SKIP
POPJ P, ;RETURN
;SUBROUTINE TO ADDRESS CHECK AN ASCIZ STRING IN A USER'S ADDRESS SPACE
;CALLING SEQUENCE:
; MOVE T1, BYTE POINTER TO STRING (LH=-1 IF LEFT JUSTIFIED STRING)
; PUSHJ P,CKSTR
;DOESN'T RETURN IF A PAGE FAULT WOULD OCCUR, RETURNS CPOPJ ON AN
; ADDRESS CHECK, CPOPJ1 IF OK TO REFERENCE THE STRING, T1=
; BYTE POINTER TO THE STRING
;PRESERVES T2-T4
CKSTR:: PUSHJ P,SAVE4## ;SAVE P1-P3
MOVEI P4,200 ;DON'T LET SOME TURKEY MAKE US LOOP TOO LONG
HLRE P1,T1 ;LEFT HALF OF THE BYTE POINTER
AOSN P1 ;IS IT -1?
HRLI T1,(POINT 7,0) ;YES, MAKE IT A POINTER TO A LEFT JUSTIFIED STRING
PUSH P,T1 ;SAVE THE BYTE POINTER
PUSH P,M ;AND M
HRRI M,-1(T1) ;SETUP M TO FETCH THE STRING
MOVEI P1,44 ;SETUP ROTATE OFFSET
LDB P2,[POINT 6,T1,5] ;GET RESIDUE
SUB P1,P2
IDIVI P2,7 ;NUMBER OF BYTES IN THE FIRST WORD
PUSHJ P,GETWR1## ;GET THE FIRST WORD
JRST CKSTR4 ;ADDRESS CHECK
LSH T1,(P1) ;LEFT JUSTIFY FIRST BYTE
JRST CKSTR2 ;CHECK IT
CKSTR1: MOVEI P2,5 ;FIVE BYTES PER WORD
PUSHJ P,GETWR1## ;GET THE NEXT WORD
JRST CKSTR4 ;ADDRESS CHECK
CKSTR2: TLNN T1,(177B6) ;A NULL BYTE?
JRST CKSTR3 ;YES, STRING IS OK
LSH T1,7 ;LEFT JUSTIFY THE NEXT BYTE
SOJG P2,CKSTR2 ;JUMP IF MORE BYTES IN THIS WORD
SOJG P4,CKSTR1 ;GET NEXT WORD. IS STRING LONG?
PUSHJ P,SCDCHK## ;YES, SEE IF SCHED WANTS TO LOOK AROUND
MOVEI P4,200 ;THEN RESUME FOR ANOTHER
JRST CKSTR1 ;FRAGMENT
CKSTR3: AOS -2(P) ;SKIP RETURN
CKSTR4: POP P,M ;RESTORE M
JRST TPOPJ## ;RESTORE BYTE POINTER AND RETURN
SUBTTL DUMP MODE COMMAND LIST PROCESSING ROUTINES
;ROUTINE TO SCAN A DUMP MODE COMMAND LIST
;AND FIND THE NEXT IO COMMAND WORD. THE LIST
;CONSISTS OF IOWD FORMAT WORDS (LH=NEGATIVE
;WORD COUNT-RH=ADDRESS OF FIRST WORD MINUS 1) AND
;GO TO WORDS (LH=ANY POSITIVE VALUE-RH=ADDRESS
;OF NEXT GO TO WORD OR IOWD). THE LIST IS
;TERMINATED BY A WORD OF ALL BINARY ZEROES. WHERE
;NO GO TO WORD INTERVENES, THE WORDS OF A LIST
;OCCUPY SEQUENTIAL MEMORY LOCATIONS. TO PREVENT
;LOOPING IN THIS ROUTINE, A MAXIMUM OF 3 SUCCESSIVE GO TO
;WORDS IS PERMITTED BE FOUND BEFORE AN IOWD MUST BE
;THIS ROUTINE IS CALLED AT UUO AND INTERRUPT LEVELS
;CALL: PUSHJ P,COMCHK
;THIS ENTRY (COMCHK) SHOULD ONLY BE USED THE
;FIRST TIME THE ROUTINE IS CALLED FOR A PARTICULAR
;DUMP IO REQUEST. IT SETS UP THE BOUNDARY VALUES
;FOR SUBSEQUENT ADDRESS CHECKS AND MUST BE
;CALLED AT UUO LEVEL
;SUBSEQUENT CALLS: SET M=TO ADDRESS OF LAST COMMAND EXECUTED
;(AS RETURNED BY PREVIOUS CALL TO THIS ROUTINE)
; PUSHJ P,NXCMR
;RETURN FROM BOTH CALLS IS TO CALL +1
;WITH ACCUMULATORS SET AS FOLLOWS:
;(T2)=USER UPPER LIMIT (SET BY COMCHK-MUST BE SET UP BEFORE CALLING NXCMR)
;(T3)=USER LOWER LIMIT (SET BY COMCHK-MUST BE SET UP BEFORE CALLING NXCMR)
;(M)=ADDRESS OF IOWD FOR NEXT DUMP MODE IO OPERATION
;(T1)=THE IOWD ITSELF OR 0 IF END OF LIST
;(S)=0 IF NO ERROR, -1 IF AN ERROR
;ERRORS ARE: IO OUTSIDE THE USER'S AREA
; MORE THAN 3 GO TO WORDS (LH .GE. 0) IN SUCCESSION
; COMMAND LIST OUTSIDE THE USER'S AREA
; (COMMANDS MAY BE IN AC'S, BUT IO TO
; AC'S IS ILLEGAL
;AC'S CLOBBERED: S,T1,T2,T3,M
;USED BUT RESTORED: P1,P2,P3
COMCHK::MOVEI T3,JOBPFI## ;HIGHEST PROTECTED LOCATION IN JOBDAT
SKIPGE USRHCU## ;IS A SAVE OR GET IN PROGRESS?MAY BE RUN UUO
MOVEI T3,JOBSAV## ;YES. USE HIGHEST LOCATION NOT WRITTEN BY SAVE
SOS M ;BACK UP POINTER-IT WILL BE INCREMENTED
HRRZ T2,.UPMP+.UPHVA ;HIGHEST VIRTUAL ADDR
NXCMR:: PUSHJ P,SAVE4## ;SAVE P1-P4
LDB P4,PJOBN## ;P4=JOB NUMBER OF JOB DOING I/O
EXCH P4,J ;SAVE J IN P4 AND PUT THE JOB NUMBER IN J
PUSHJ P,SVEUB## ;MAKE THE JOB ADDRESSABLE
MOVEI T1,JS.ASA ;FLAG SAYING MEMORY REFERENCES TO USER 0-17
TDNE T1,JBTSTS##(J) ; ARE TO SHADOW AC'S - IS IT ON?
TLO J,400000 ;YES, REMEMBER THAT
MOVEI T1,(J) ;PICK UP THIS JOB'S NUMBER
CAME T1,.CPJOB## ;IS IT THE ONE WE'RE RUNNING
PUSHJ P,SETASA## ;NO, FLAG REFERENCES TO USER 0-17 AS SHADOW
; AC REFERENCES
HRREI P1,-3 ;ALLOW A MAXIMUM OF 3 GO TO WORDS
PUSH P,T2 ;SAVE HIGHEST USER LOCATION
AOSA T1,M ;POINT TO THE NEXT OR FIRST IOWD
NXCMRA: HRRM T1,M ;GET NEXT COMMAND IF THIS ONE IS A GOTO WORD
PUSHJ P,GETWRD## ;GET THE IOWD
JRST NXBAD ;ADDRESS CHECK
JUMPE T1,NXCOK ;IF 0, ITS THE LIST TERMINATOR
TLNE T1,-1 ;A GOTO WORD ?
JRST NXCHIT ;NO, A REAL IOWD, GO CHECK IT
AOJLE P1,NXCMRA ;YES, ITS A GOTO WORD
NXBAD: MOVEI S,-1 ;FLAG BAD COMMAND
TDZA T1,T1 ;ZERO T1 AS IF THE LIST HAD TERMINATED
NXCOK: MOVEI S,0 ;THE IOWD IS OK
SKIPL J ;WAS JS.ASA FLAG ON?
PUSHJ P,CLRASA## ;NO, CLEAR SHADOW AC REFERENCE FLAG
MOVE J,P4 ;RESTORE J
JRST NXOUT ;EXIT WITH T1, M AND S SET TO SHOW
;RESULTS. IF CALL WAS TO COMCHK,T2 & T3 ALSO SET
;TO USER BOUNDARIES. ALWAYS EXIT TO CALL +1
NXCHIT:
IFN FTEXE,<JUMPL J,NXCOK ;TRUCT COMCON IF SAVE IN PROGRESS
; DON'T ADDRESS-CHECK
>;END IFN FTEXE
HRRZ P2,T1 ;THIS IS IOWD OR GO TO NOT POINTING TO AC
HLRO P3,T1 ;SAVE ADDRESS POINTED TO AND NEGATIVE COUNT
CAMG P2,T3 ;IS START ABOVE PROTECTED AREA?
JRST NXBAD ;NO. REPORT ERROR
MOVMS P3 ;WORD COUNT
ADD P2,P3 ;END OF IO
IFN FTEXE,<
SKIPGE USRHCU## ;IF SAVE N IN PROGRESS,
TLZ P2,-1 ; SUPPRESS CARRY IF ADR=-1
>
CAMLE P2,(P) ;END OF IO ABOVE USER UPPER LIMIT?
JRST NXBAD ;YES, IO WOULD RUN PAST END OF USER AREA
SKIPGE USRHCU## ;SAVE IN PROGRESS?
JRST NXCOK ;YES, IOWD LIST IS OK
MOVE T2,P2 ;TOP ADR FOR IO
MOVE P2,T1 ;PRESERVE T1
MOVEI T1,1(T1) ;START ADR FOR IO
PUSHJ P,ZRNGE## ;ALL PAGES IN CORE?
JRST NXBAD ;NO, USER FIDDLED WITH HIS LIST
; (LIST WAS CHECKED BEFORE IO STARTED - WAS OK THEN)
MOVE T1,P2 ;YES, RESTORE T1
JRST NXCOK ;EXIT-FOUND A GOOD IOWD
;ROUTINE TO MAKE THE USER AREA REPRESENTED
;BY THE IOWD IN T1 ADDRESSABLE.
;IF THIS IS A KA10, THE IOWD IS BAD (ADDRESS
;CHECK), OR THE IOWD IS THE LIST TERMINATOR,
;RETURN IMMEDIATELY. IF THIS IS AN I/O BUS
;DEVICE, MAPE THE NEW IOWD IN THE EXEC
;MAP. THIS CAN ONLY FAIL IF THE NUMBER
;OF PAGES THIS JOB HAS IN THE EXEC
;MAP IS NOT GREAT ENOUGH TO COVER
;THE IOWD (ONLY HAPPEMS IF I/O INTO THE
;LIST SINCE THE LIST IS SCANNED AT UUO
;LEVEL).
NXOUT: JUMPE T1,T2POPJ## ;LAST WORD IN THE LIST OR ADDRESS CHECK?
;YES, RESTORE T2 AND RETURN
SKIPN DEVEVM(F) ; THE DEVICE GOES DIRECT TO MEMORY
; THROUGH A CHANNEL
JRST T2POPJ## ; JUST RELOCATED THE IOWD KA10 STYLE AND RETURN
PUSH P,T3 ;SAVE LOWER BOUND ON I/O
HLRE T2,T1 ;T2 = - WORD COUNT FOR CURRENT IOWD
MOVNS T2 ;T2 = POSITIVE WORD COUNT
SUBI T2,2 ;CALCULATE NUMBER OF PAGES NECESSARY
IDIVI T2,PAGSIZ##+2 ; TO COVER THIS WORD COUNT BY MAPPING THE
ADDI T2,2 ; AREA SPECIFIED BY THE IOWD IN THE EXEC MAP
LDB T3,PDEVMS## ;GET THE NUMBER OF PAGES OF EVM ALLOCATED
; TO THIS DEVICE
MOVEI S,-1 ;ASSUME THERE ARE NOT ENOUGH
CAMLE T2,T3 ;ARE THERE ENOUGH PAGES TO COVER CURRENT
; WORD COUNT?
JRST NXOUT1 ;NO, ADDRESS CHECK RETURN
PUSH P,T1 ;SAVE THE IOWD
MOVEI T3,1(T1) ;ADDRESS INTO WHICH I/O WILL BE DONE
LDB T2,PDEVMS## ;RESTORE NUMBER OF PAGES
LDB T1,PDEVM## ;GET PAGE NUMBER OF FIRST PAGE IN THE EXEC
; MAP ALLOCATED TO THIS DEVICE
PUSHJ P,MAPUEI## ;MAP THE IOWD IN THE EXEC MAP
MOVEI S,0 ;FLAG CURRENT IOWD OK
HRRM T3,(P) ;STORE EXEC VIRTUAL ADDRESS IN IOWD
POP P,T1 ;T1 = XWD -N,EXEC VIRTUAL ADDRESS FOR I/O
NXOUT1: POP P,T3 ;RESTORE LOWER BOUND ON I/O TO USER AREA
SOJA T1,T2POPJ## ;RESTORE UPPER BOUND AND RETURN
SUBTTL DDB SCAN LOGIC
;ASSIGN DEVICE IF UNASSIGNED
;CALL: MOVE J, JOB NUMBER
; MOVE F, ADDR. OF DDB
; MOVE T1,DEVICE NAME
; MOVEI T2, EITHER ASSPRG OR ASSCON
; PUSHJ P, ASSASG
; CAN'T ASSIGN RETURN
; ASSIGNED RETURN
ASSASG::
IFN FTSPL,<
PUSHJ P,SAVE2##
SETZB P1,P2 ;P1 WILL GET DEVMOD IF SPOOLING
HRRZ T3,SPLBIT##(F) ;POSSIBLE SPOOL-BIT
SKIPN DEVCHR(F) ;FAKE (TABLE) DDB?
JRST ASSAS0 ;YES, SPOOL IT
LDB T3,DEYSPL## ;SPOOL BIT FOR THE DEVICE
SKIPGE DEVSPL(F) ;IS THIS A SPOOLED DISK DDB ?
TLOA T3,DEPSPL ;YES. ENSURE COPY HAS DEPSPL ON
TDNN T3,JBTSPL##(J) ;JOB SPOOLING THIS DEVICE?
JRST ASSAS1 ;NO
MOVE P2,T3 ;SPOOL BIT
LDB T3,PJOBN## ;YES, GET OWNER OF DEVICE
MOVE T4,DEVMOD(F) ;DEVMOD
TRNE T4,ASSCON ;ASSIGNED BY CONSOLE?
CAME T3,J ;YES. TO THIS JOB?
ASSAS0: TLOA T3,DEPSPL(P2) ;NO. SET UP TO SPOOL
JRST ASSAS2 ;YES - USE PHYSICAL DEVICE
MOVE P1,DEVMOD(F) ;TELL SETDDB TO STUFF THIS IN DEVMOD
HRRI F,DSKDDB## ;SET F TO PROTOTYPE DISK DDB
ASSAS1:> ;CLOSE FTSPL CONDITIONAL
MOVE T4,DEVMOD(F) ;DEVMOD
TLNN T4,DVDSK ;DEVICE A DISK?
JRST ASAS1A ;NO
PUSHJ P,SETDDB## ;YES, GENERATE A NEW DDB
JRST ASSAS5 ;NO DDB SPACE
ASAS1A:
IFN FTSPL,<
HLLZS T3 ;LH(T3)=0 OR DEPSPL
IORM T3,DEVSPL(F) ;LIGHT SPOOL-BIT IF NEEDED
ASSAS2:> ;CLOSE FTSPL
MOVEI T3,DEPMSG
TDNE T3,DEVMSG(F) ;CONTROLLED BY MPX?
JRST ASSAS5 ;YES, ALWAYS FAIL
NOSCHEDULE ;DISABLE SCHEDULING
SCNOFF
LDB T1,PJOBN## ;GET JOB NUMBER IN DEV DATA BLOCK
CAMN T1,J ;IS IT ALREADY ASSIGNED TO THIS JOB
JRST ASSA2C ;YES
MOVEI T1,ASSPRG+ASSCON ;NO, IS IT ASSIGNED TO ANOTHER JOB?
TDNE T1, DEVMOD(F) ;ARE EITHER ASSIGNED BITS SET?
JRST ASSAS4 ;YES
HRLZI T1,DEPRAS ;GET RESTRICTED ASSIGNMENT BIT
TDNN T1,DEVSTA(F) ;IS THIS DEVICE RESTRICTED?
JRST ASSA2A ;NO, PROCEED
PUSHJ P,PRVJ## ;THIS JOB PRIVILEDGED TO ASSIGN?
JRST ASSA2A
JRST ASSA4A ;NO, SET T2=-1 AS FLAG
ASSA2A:
IFN FTMDA,<
SKIPE %SIMDA## ;MDA NOT RUNNING?
CAMN J,MDAJOB## ;OR JOB=MDAJOB
JRST ASSA2B ;YES, SKIP ALL THIS
MOVSI T1,DVCMDA ;A CONTROLLED DEVICE?
TDNE T1,DEVCHR(F) ;?
JRST ASSA4A ;YES, LOSE
ASSA2B:
>;END IFN FTMDA
PUSH P,T2 ;SAVE T2 OVER CALL TO SETDVL
PUSHJ P,SETDVL ;STORE JOB NUMBER IN DDB
POP P,T2 ;RESTORE T2
IORM T2,DEVMOD(F) ;SET IN USE BITS
ASSA2C:
IFN FTMTSET,<
TRNN T2,ASSCON ;IF ASSIGN COMMAND,
JRST ASSAS3
HLLZ T1,DEVMOD(F) ;GET CHARACTERISTICS, SET RH FOR DPB
TLNE T1,DVMTA ;CHECK FOR MTA
TLNE T1,DVTTY ;BE SURE IT ISN'T NUL!
JRST ASSAS3 ;NOT MTA
HRRI T3,MTSIZ##+1 ;GET DEFAULT MTA BLOCK SIZE
DPB T3,PBUFSZ## ; SET SYSTEM DEFAULT BUFFER
DPB T1,TDYDN1## ; SET TO FORCE INSTALLATION DENSITY
DPB T1,PBUFRM## ;CLEAR FRAME-COUNT
IFN FTDX10,<
DPB T1,PMTRTY## ;ENABLE AUTO ERROR-RETRY
>
ASSAS3:
> ;END CONDITIONAL ON FTMTSET
IORM T2,DEVMOD(F) ;SET IN USE BITS AGAIN IN CASE
; IT IS THE SAME JOB
AOSA (P) ;GIVE OK RETURN
ASSA4A: HRREI T2,-1 ;FLAG AS RESTRICTED DEVICE
ASSAS4: SCNON
SCHEDULE ;TURN SCHEDULING ON
ASSAS5: POPJ P, ;GIVE ERROR RETURN
;DVCNSG -- ROUTINE TO FIND DDB FOR THOSE UUOS
; WHICH HAVE DUAL STYLE ARGUMENT:
; (1) 0-17 = CHANNEL NUMBER (INITED)
; (2) ELSE = SIXBIT DEVICE NAME (GENERIC,...)
;CALL: MOVE T1,ARGUMENT
; PUSHJ P,DVCNSG
;RETURN CPOPJ IF NO SUCH DEVICE
;SKIP RETURN WITH F = DDB ADDRESS IF FOUND
DVCNSG::CAIL T1,HIGHXC## ;SKIP IF KNOWN NOT TO BE A UDX
PUSHJ P,UDXDDB ;SEE IF T1 IS A UDX
SKIPA ;NO--DO ORDINARY STUFF
JRST CPOPJ1## ;YES--ALL DONE
SKIPL T1 ;IF NEGATIVE
CAIL T1,HIGHXC## ; OR .GT. 17,
PJRST DEVSRG ; MUST BE SIXBIT
HRLM T1,.UPMP+.UPCTA
PUSHJ P,JDAADR ;GET ADDRESS OF THE CHANNEL TABLE SLOT
CAIL T1,.FPMC ;IS IT A LEGAL ADDRESS?
SKIPN F,(T1) ;YES, ANY DDB?
POPJ P, ;NO
JRST CPOPJ1## ;YES
;SUBROUTINES TO MAINTAIN THE LOGICAL NAME TABLE. THIS IS USED TO
; SPEED UP THE LOGICAL NAME SEARCHING.
LDVTLN==4 ;LENGTH OF THE TABLE IN WORDS.
;SUBROUTINE TO MARK THE DDB IN F AS OWNED BY THE JOB IN J.
; IF THE DEVICE HAS A NON-BLANK LOGICAL NAME IT IS PUT IN
; THE JOB'S LOGICAL NAME TABLE.
SETDVL::PUSHJ P,CLRDVL ;CLEAR CURRENT OWNER, IF ANY.
DPB J,PJOBN## ;STORE JOB NUMBER IN DDB
JUMPE J,CPOPJ## ;ALL DONE IF JOB ZERO.
SKIPN DEVLOG(F) ;HAS THE DEVICE A LOG. NAME?
POPJ P, ;NO, ALL DONE.
PUSHJ P,FNDPDB## ;FIND JOB'S PDB
POPJ P, ;NONE, FORGET IT.
SKIPLE T1,.PDDVL##(W) ;IS THERE ALREADY A DDB TABLE?
PJRST SETDV1 ;YES, JUST ADD TO EXISTING SET
; PJRST SETDVS ;NO, BUILD ONE.
;SUBROUTINE TO BUILD THE LOGICAL NAME TABLE. USED WHEN THE FIRST
; LOGICAL NAME IS ASSIGNED AND IF THE NUMBER OF LOGICAL NAMES
; BECOMES TOO LARGE.
SETDVS: MOVEI T2,LDVTLN ;OBTAIN THE TABLE SPACE
JUMPE T2,SETDV2 ; THERE IS NONE, SCAN THE DDBS.
PUSHJ P,GETWDS## ;GET THAT MANY WORDS
JRST SETDV2 ; NOT AVAIL, SCAN DDBS FOR LOG NAMES.
HRLZ T2,T1 ;GOT THE SPACE -- CLEAR THE BLOCK.
HRRI T2,1(T1) ;FORM BLT ADDRESSES
SETZM (T1) ;CLEAR FIRST WORD
BLT T2,LDVTLN-1(T1) ;CLEAR THE REST OF THE WORDS
SKIPL .PDDVL##(W) ;WERE THERE NO LOGICAL NAMES?
JRST SETDV3 ;YES, JUST STORE THIS DDB.
;COME HERE IF THERE WERE TOO MANY LOGICAL NAMES TO FIT IN THE
; TABLE. TRY TO REBUILD THE TABLE BY SCANNING THE DDBS.
MOVEM T1,.PDDVL##(W) ;STORE POINTER TO TABLE
CAME J,.UPMP+.UPJOB ;THIS JOB MAPPED?
JRST SETDVF ;NO, SEARCH THE DDB'S
PUSH P,F ;PRESERVE F
HLRZ F,DEVLST## ;SCAN ALL DDBS
SETDV4: SKIPN DEVLOG(F) ;HAS THIS DDB A LOGICAL NAME?
JRST SETDV8 ;NO, TRY NEXT DDB.
LDB T1,PJOBN## ;YES, BELONG TO THIS JOB?
CAMN T1,J
PUSHJ P,SETDV1 ;YES, PUT IN LOG NAME TABLE
SETDV8: PUSHJ P,NXDDB ;POINT AT NEXT DEVICE ON CHAIN
JUMPE F,FPOPJ##
JRST SETDV4 ;AND TEST IT
;COME HERE IF CORE WAS GOTTEN SUCCESSFULLY AND THIS IS THE FIRST
; DEVICE WITH A LOGICAL NAME.
SETDV3: MOVEM T1,.PDDVL##(W) ;STORE POINTER TO TABLE
; PJRST SETDV1 ;PUT THIS DDB IN THE TABLE
;SUBROUTINE TO ADD A DDB POINTER TO THE SET OF POINTERS ALREADY
; ASSOCIATED WITH A JOB. IF THE TABLE IS FULL IT IS RELEASED
; AND LOGICAL NAME SEARCHING WILL BE DONE BY SCANNING ALL DDBS
; UNTIL THE NUMBER OF LOGICAL NAMES GETS SMALL ENOUGH TO FIT
; IN THE TABLE. DDB POINTER IN F, JOB NUMBER IN J.
SETDV1: SKIPG T1,.PDDVL##(W) ;IS THERE A TABLE?
POPJ P, ;NO, FORGET IT.
HRLI T1,-LDVTLN ;LENGTH OF TABLE (FOR AOBJN)
SETDV7: SKIPN T2,(T1) ;IS THE WORD ZERO?
JRST SETDV5 ;YES, USE LEFT HALF.
TLZN T2,-1 ;NO, IS L.H. ZERO?
JRST SETDV5 ;YES, USE IT.
JUMPE T2,SETDV6 ;NO, IF R.H. IS ZERO, USE IT.
AOBJN T1,SETDV7 ;BOTH NON-ZERO, TRY NEXT WORD.
; PJRST SETDVF ;TOO MANY, FLUSH TABLE.
;SUBROUTINE TO RETURN THE TABLE TO FREE STORAGE AND
; ARRANGE TO USE DDB SCAN. USED IF THERE ARE TOO MANY LOGICAL
; NAMES TO FIT IN THE TABLE.
SETDVF::MOVEI T1,LDVTLN ;LENGTH OF TABLE
MOVE T2,.PDDVL##(W) ;POINT TO TABLE
PUSHJ P,GIVWDS## ;RETURN THE TABLE SPACE
;COME HERE IF THE TABLE SPACE IS UNAVAILABLE OR, AFTER RETURNING
; TABLE, IF THERE ARE TOO MANY LOGICAL NAMES.
SETDV2: SETOM .PDDVL##(W) ;FLAG NO VALID TABLE
POPJ P, ;RETURN.
;COME HERE IF L.H. IS ZERO AND THEREFORE SUITABLE FOR A DDB POINTER
SETDV5: HRLM F,(T1) ;STORE DDB POINTER IN TABLE
POPJ P, ; AND RETURN.
;COME HERE FOR R.H.
SETDV6: HRRM F,(T1) ;STORE DDB POINTER IN TABLE
POPJ P, ; AND RETURN.
;SUBROUTINE TO TERMINATE OWNERSHIP OF A DEVICE. F POINTS TO THE
; DDB. PRESERVES J.
CLRDVL::LDB T1,PJOBN## ;FIND OWNER
JUMPE T1,CPOPJ## ;NONE, NO PROBLEM.
SETZ T2, ;CLEAR JOB NUMBER IN DDB
IFN FTNET,<
MOVSI T3,DVCNET ;ON NETWORK?
TDNN T3,DEVCHR(F) ;SKIP FOR ZAPNET
>;END IFN FTNET
DPB T2,PJOBN##
PUSH P,J ;PRESERVE J
MOVE J,T1 ;J = JOB NUMBER
PUSHJ P,FNDPDB## ;LOCATE JOB'S PDB
JRST JPOPJ## ;NONE, FORGET IT.
SKIPG T1,.PDDVL##(W) ;POINT TO LOGICAL NAME TABLE
JRST CLRDV1 ;NONE, TRY TO REBUILD.
HRRZ T3,F ;GET COPY OF F WITH L.H = 0
HRLI T1,-LDVTLN ;FIND THE DEVICE
CLRDV2: SKIPN T2,(T1) ;IS WHOLE WORD ZERO?
JRST CLRDV8 ;YES, TRY NEXT WORD.
CAIN T3,(T2) ;NO, DOES R.H. POINT TO DDB?
JRST CLRDV4 ;YES.
HLRZS T2 ;NO, TRY LEFT HALF
CAIN T3,(T2) ;DOES L.H. POINT TO DDB?
JRST CLRDV3 ;YES.
CLRDV8: AOBJN T1,CLRDV2 ;NO, TRY NEXT WORD.
POP P,J ;NOT IN TABLE. RESTORE J.
POPJ P, ;EXIT.
;COME HERE IF L.H. POINTER MATCHES. CLEAR IT.
CLRDV3: HRRZS (T1) ;LEAVE R.H. POINTER, IF ANY.
JRST CLRDV5 ; CHECK FOR EMPTY BLOCK
;COME HERE FOR R.H.
CLRDV4: HLLZS (T1) ;PRESERVE L.H. POINTER, IF ANY.
; JRST CLRDV5 ; AND CHECK FOR EMPTY BLOCK.
;COME HERE TO CHECK FOR AN EMPTY BLOCK. IF THE BLOCK IS
; EMPTY IT CAN BE FREED.
CLRDV5: SKIPG T1,.PDDVL##(W) ;POINT TO LOGICAL NAME TABLE
JRST JPOPJ## ;NONE, RESTORE J AND EXIT.
HRLI T1,-LDVTLN ;BUILD AOBJN POINTER
CLRDV6: SKIPN (T1) ;CHECK POINTERS TWO AT A TIME
AOBJN T1,CLRDV6 ;DONE THEM ALL?
JUMPL T1,JPOPJ## ;AT LEAST ONE POINTER.
PUSHJ P,SETDVF ;NO POINTERS, FLUSH TABLE.
SETZM .PDDVL##(W) ;MARK JOB AS HAVING NO LOG. NAMES
JRST JPOPJ## ;RESTORE J AND RETURN.
;COME HERE IF THE TABLE IS NOT PRESENT. TRY TO REBUILD IT.
CLRDV1: JUMPE T1,JPOPJ## ;IGNORE IF "NONE" RATHER THAN "INVALID"
PUSHJ P,SETDVS ;TRY TO REBUILD TABLE
JRST JPOPJ## ;RESTORE J AND RETURN.
;SUBROUTINE TO FIND THE NEXT DDB
;ENTER WITH F=0 TO GET 1ST DDB IN SYSTEM, F=DDB ADDR TO GET NEXT DDB
;RETURNS CPOPJ WITH F=0 IF NO MORE DDBS
;CALL NXDDB TO DO A LOGICAL HLRZ F,DEVSER(F)
;CALL NXDDP TO DO A LOGICAL HLR F,DEVSER(F)
;RETURNS CPOPJ WITH F=DDB ADDRESS IF JUST SWITCHED FROM LOW DDBS
; (DEVLST CHAIN) TO HIGH DDBS (IN SWAPPABLE AREA)
;RETURNS CPOPJ1 NORMALLY, WITH F POINTING AT NEXT DDB
;PRESERVES ALL ACS (EXCEPT F)
NXDDB:: HRRZS F ;CLEAR LH
NXDDP:: JUMPE F,[HLRZ F,DEVLST## ;IF START
JRST CPOPJ1##] ;POINT TO START OF DDBS
PUSH P,T1
HRRZ T1,F ;SAVE CURRENT F
HLR F,DEVSER(F) ;STEP TO NEXT DDB
TRNE F,-1 ;IS THERE ONE?
JRST TPOPJ1## ;YES, GOOD RETURN
CAMLE T1,SYSSIZ## ;ALREADY POINTING AT FUNNY SPACE?
CAIN T1,DSKDDB## ;IF NO NETWORKS
SKIPN .UPMP ;DSKDDB IS END OF CHAIN
; BUT NO FUNNY SPACE FOR NULL JOB
TRZA F,-1 ;YES, NO MORE
HLR F,.UPMP+.UPLST ;NO, POINT AT FUNNY SPACE
JRST TPOPJ## ;AND RETURN
;ROUTINE TO SEARCH FOR A DEVICE
;CALL: HRR J,JOB NUMBER
; MOVE T1,[SIXBIT .DEVICE NAME.]
; PUSHJ P, DEVSRC
; NOT FOUND
; FOUND
DEVSRC::MOVEI T2,DD%PHY+DD%LOG ;SET UP FOR PHYSICAL SEARCH
PJRST DDBSRC ;GO DO IT
;SEARCH LOGICAL NAMES
DEVLG:: MOVEI T2,DD%LOG ;SEARCH FOR LOGICAL NAMES
PJRST DDBSRC ;GO DO IT
;COME HERE TO SEARCH FOR PHYSICAL NAME
DEVPHY::MOVEI T2,DD%PHY ;SET PHYSICAL ONLY FLAG
PJRST DDBSRC ; AND GO DO THE SEARCH
;SEARCH LOGICAL NAMES, NOT DDBS IN FUNNY SPACE
DEVCHN::MOVEI T2,DD%LOG+DD%CHN
JRST DDBSRC
;SEARCH PHYSICAL, LOGICAL NAMES, NOT DDBS IN FUNNY SPACE
DEVNFS::MOVEI T2,DD%LOG+DD%PHY+DD%CHN
PJRST DDBSRC
;ROUTINE TO SEARCH FOR A DEVICE
; (INCLUDING GENERIC NAMES)
;SAME CALL AND RETURN AS DEVSRC
DEVSRG::PUSHJ P,DEVSRC ;SEARCH PHYSICAL & LOGICAL NAMES
TDZA T3,T3 ;NOT FOUND
JRST CPOPJ1## ;FOUND
IFN FTSPL,<
;CALL DVSRSP TO SEARCH THE SPOOLING TABLE
; AND IF FAILS, GENERIC SEARCH
DVSRSP::HLLZ T2,T1 ;GENERIC NAME OF DEVICE
MOVEI F,SPLTAB## ;SCAN SPOOLABLE DEVICE TABLE FOR MATCH
SPLOOP: CAMN T2,SPLNAM##(F)
JRST SPLFND ;FOUND
ADDI F,SPLLEN##
CAIGE F,SPLTOP##
JRST SPLOOP
JRST SPLEND ;NOT A SPOOLING DEVICE - SCAN FOR GENERIC MATCH
SPLFND: HRRZ T2,SPLBIT##(F) ;SPOOLING DEVICE BIT
TDNN T2,JBTSPL##(J) ;JOB SPOOLING THIS DEVICE?
JRST SPLEND ;NO, FIND THE REAL DDB
HRRZ T2,T1
JUMPE T2,CPOPJ1## ;WE WON IF NO RH OF NAME
IFN FTNET,<
LSH T2,-6
PUSHJ P,DVSCVT
JRST SPLEND ;NO - NOT REALLY SPOOLING
PUSH P,T1
MOVE T1,T2 ;RH = SXX. IS XX A STATION?
PUSHJ P,STBSCA## ;DOES THE NODE EXIST
TDZA T3,T3 ;NO, SET T3 FOR DVASRC
JRST TPOPJ1## ;YES, GIVE SKIP RETURN
POP P,T1 ;RESTORE NAME
>;END FTNET CONDITIONAL
SPLEND: SETZ F, ;CLEAR F (NO DDB)
>;END FTSPL CONDITIONAL
IFN FTGSRC,<
PJRST DVASRC ;SEARCH FOR GENERIC, GIVE ERROR OR OK RETURN
>
IFE FTGSRC,<
SETZ T4, ;RESET FLAG
POPJ P, ;ERROR RETURN
>
IFE FTNET!FTSFD,<
DEVSRG==:DEVSRC
>
;ROUTINE TO CHECK TO SEE IF DEVICE 'OPRXXX' AND IF SO TO
;FUDGE T1 TO HAVE REAL TTY NAME IN IT
TSTOPR::
IFN FTNET,<
PUSH P,T1 ;SAVE NAME IN CASE TEST FAILS
HLRZ T2,T1 ;GET GENERIC NAME
CAIE T2,(SIXBIT/OPR/) ;IS IT OPR?
JRST TPOPJ## ;NO - BRANCH TO RESTORE OLD NAME
TRNN T1,-1 ;ANY STATION NUMBER SPECIFIED?
JRST OPRGEN ;NO - GO FIND OPR FOR THIS JOB
HRLZS T1 ;PUT NUMBER IN LH OF T1
PUSHJ P,CVTOCT ;GO CONVERT TO OCTAL DIGITS
JRST TPOPJ## ;ILLEGAL OCTAL - MUST NOT BE OPR
JUMPE T1,OPRCEN ;OPR0 IS ALWAYS CENTRAL SITE
PUSHJ P,STBSCA## ;GO SEE IF STA # IS VALID
JRST TPOPJ## ;INVALID STA - ERROR RETURN
OPRFND: CAMN T1,JBTLOC## ;IS IT AT CENTRAL SITE?
JRST OPRCEN ;YES--GO GET IT
PUSHJ P,STBOPR## ;GET OPR TTY LINE # AT THIS STA
PUSHJ P,CVTSBT ;CONVERT IT TO SIXBIT
HLRZS T1 ;PUT IN RH
HRLI T1,(SIXBIT/TTY/) ;LH = SIXBIT/TTY/
OPRRET: PJRST T2POPJ## ;THROW AWAY OLD NAME (T2) AND RETURN
OPRGEN: MOVE T1,JBTLOC##(J) ;GET STA # OF JOB
JRST OPRFND ;NO - USE JOB LOCATION FOR OPR SEARCH
OPRCEN: MOVE T1,DEVOPR## ;YES - USE OPR NAME FROM COMMON
JRST OPRRET ;SCRAP OLD NAME AND RETURN
> ;END CONDITIONAL ON FTNET
IFE FTNET,<
CAMN T1,[SIXBIT/OPR/] ;IS IT DEVICE OPR?
MOVE T1,DEVOPR## ;YES - USE OPR DEV NAME
POPJ P, ;AND RETURN
>
IFN FTNET!FTMSGSER,<
;NUMBER CONVERSION ROUTINES
;CVTOCT - CONVERT SIXBIT NUMBER LEFT JUSTIFIED IN T1 TO
;OCTAL (RIGHT JUSTIFIED) IN T1
CVTOCT::TLNN T1,770000 ;IS THERE A FIRST CHARACTER?
JUMPN T1,CPOPJ## ;NO, CAN'T BE SIXBIT
PUSH P,T2 ;SAVE ALL AC'S USED
PUSH P,T3 ;..
PUSH P,T4 ;..
MOVE T2,[POINT 6,T1] ;BYTE PTR TO T1
SETZ T3,
CVTOC2: ILDB T4,T2 ;GET SIXBIT CHAR
JUMPE T4,CVTOC1 ;NULL CHAR ENDS STRING
CAIL T4,'0' ;MUST BE BETWEEN 0 AND 7
CAILE T4,'7' ;TO BE A VALID OCTAL DIGIT
JRST CVTOC3 ;OTHERWISE ERROR RETURN
ROT T3,3 ;MAKE ROOM
IORI T3,-'0'(T4) ;PUT DIGIT IN
JRST CVTOC2 ;GO DO SOME MORE
CVTOC1: MOVE T1,T3 ;RETURN WITH OCTAL NUMBER IN T1
AOS -3(P) ;GOOD RETURN IS SKIP RETURN
PJRST CVTOC3 ;GO RESTORE AC'S AND RETURN
> ;END CONDITIONAL ON FTNET!FTMPG
;CVTSBT - CONVERT OCTAL NUMBER TO SIXBIT
CVTSBT::PUSH P,T2 ;SAVE ALL AC'S USED
PUSH P,T3 ;..
PUSH P,T4 ;..
MOVE T3,[POINT 6,T4] ;PLACE FOR RESULT
SETZ T4, ;ZERO T4
PUSHJ P,CVTSB1 ;CONVERT TO SIXBIT
MOVE T1,T4 ;RETURN RESULT IN T1
CVTOC3: POP P,T4 ;RESTORE AC'S
POP P,T3
PJRST T2POPJ## ;AND RETURN (POP T2)
CVTSB1: IDIVI T1,10 ;GET A DIGIT
HRLM T2,0(P) ;SAVE IN LH OF CURRENT STACK WORD
SKIPE T1 ;WHEN DONE - SKIP
PUSHJ P,CVTSB1 ;RECURSIVELY DO ABOVE AGAIN
HLRZ T1,0(P) ;GET BACK THE DIGIT
ADDI T1,20 ;CONVERT IT TO SIXBIT
IDPB T1,T3 ;STORE IN RETURN WORD
POPJ P,0 ;AND RETURN TO GET ANOTHER DIGIT
;OR CALLER
;SUBROUTINE TO CHECK FOR A VALID (PDP-11 COMPATABLE) 2-CHAR
; DEVICE NAME. ENTER WITH NAME IN T1, EXIT WITH NEW NAME (IF ANY)
; ALSO IN T1.
;
;CALL:
; PUSHJ P,CK2CHR
; HERE ALWAYS
;
;
CK2CHR: MOVEI T4,STLEN##-1 ;GET POINTER TO SPECIAL DEVICE TABLE
HLRZ T2,T1 ;GET THIS DEVICE NAME
DVSRC1: MOVE T3,SPCTAB##(T4) ;GET TABLE ENTRY
CAIN T2,(T3) ;IS IT THIS DEVICE?
JRST [HLL T1,T3 ;YES, RESET DEVICE NAME
POPJ P,] ;AND RETURN
SOJGE T4,DVSRC1 ;MORE IN TABLE?
POPJ P, ;NO, EXIT
;SUBROUTINE TO SEARCH DDB'S FOR A DEVICE
;
;CALL:
; MOVEI T2,FLAGS
; PUSHJ P,DDBSRC
; NOT FOUND
; FOUND
;
;FLAGS:
; DD%PHY SEARCH FOR PHYSICAL NAMES
; DD%LOG SEARCH FOR LOGICAL NAMES
;
;ON EXIT, F WILL CONTAIN THE DDB IF WE FOUND ONE
;RETURNS T2=PREDESSOR ON PHYSICAL MATCH OF DEVNAM
;
;THE ALGORITHM IS AS FOLLOWS:
;
; 1. IF LOGNAM MATCH & DD%LOG SET, TAKE THIS DEVICE
; 2. OR, IF PHYNAM MATCH & DD%PHY SET & DD%LOG NOT SET, TAKE IT
; 3. IF PHYNAM MATCH & BOTH SET, SAVE NAME TO SEE IF FIND LOGNAM MATCH
;
DD%LOG==:1B35 ;FLAG BIT DEFINITIONS
DD%PHY==:1B34
DD%CHN==:1B33
DD%PHO==:1B32 ;ON IF PHYSICAL ONLY
DDBSRC: JUMPE T1,CPOPJ## ;DEVICE NAME OF 0 NOT ALLOWED
PUSHJ P,SAVE1## ;SAVE P1
HRR P1,T2 ;SAVE FLAGS
HLRZ T2,P1 ;CHECK FOR PHYSICAL ONLY
CAIN T2,PHONLY ;IS IT THERE?
JRST [TRO P1,DD%PHO ;DISALLOW LOGICAL NAME MATCHES IN TSTDSK
JRST DEVLP7] ;AND CLEAR LOGICAL BIT
TRNN P1,DD%CHN ;SEARCH IN DEVLST CHAIN ONLY ?
TRNN P1,DD%LOG ;LOGICAL SEARCH?
JRST NOLGST ;NO, DON'T SET UP
PUSHJ P,FNDPDB## ;POINT TO PDB
JRST DEVLP7 ;NO PDB = NO LOGICAL NAMES
SKIPGE T2,.PDDVL##(W) ;IS THERE A LOG NAME TABLE?
JRST NOLGST ;IT IS INVALID, SCAN DDB'S
JUMPE T2,DEVLP7 ;NO LOGICAL NAMES
HRLI T2,-LDVTLN ;SET UP AOBJN POINTER
DEVLP4: SKIPN T3,(T2) ;IS THIS WORD CLEAR?
JRST DEVLP5 ;YES, CHECK NEXT
HLRZ F,T3 ;NO, CHECK LEFT HALF
CAMN T1,DEVLOG(F) ;LOGICAL NAME MATCH?
JUMPN F,CPOPJ1## ;YES, IF NON-BLANK
HRRZ F,T3 ;TRY RIGHT HALF
CAMN T1,DEVLOG(F) ;LOGICAL NAME MATCH?
JUMPN F,CPOPJ1## ;YES, IF NON-BLANK
DEVLP5: AOBJN T2,DEVLP4 ;CHECK ON NEXT WORD
DEVLP7: TRNN P1,DD%PHY ;PHYSICAL?
POPJ P, ;NO, NOT FOUND
TRZ P1,DD%LOG ;YES, TURN OFF LOG
NOLGST: TLZ P1,-1 ;CLEAR PHONLY
TRNN P1,DD%PHY ;PHYSICAL SEARCH?
JRST DDSRC2 ;NO DON'T SET UP
TDNN T1,[77,,-1] ;IS THIS A 2-CHAR DEVICE NAME?
PUSHJ P,CK2CHR ;YES, CHECK FOR WIERD NAMES
TRNE P1,DD%CHN ;DON'T LOOK AT DISKS IF SEARCHING ONLY DEVLST
JRST DDSRC0
PUSHJ P,TSTDSK## ;IS THIS A DISK?
JRST [TRNN P1,DD%LOG ;LOGICAL SEARCH?
JRST CPOPJ1## ;NO FOUND PHYSICAL
HRL P1,F ;YES, SAVE DDB
JRST .+1] ;AND CONTINUE
DDSRC0:
IFN FTTSK,<
PUSHJ P,TSTTSK## ;IS THIS A TSK DEVICE
CAIA ;NO, CONTINUE SEARCH
JRST CPOPJ1## ;YES, EXIT WITH F=DDB POINTER
>;END FTTSK
PUSHJ P,TSTOPR ;CHECK FOR "OPR"
MOVSI T3,DVDSK
DDSRC2: HLR F,DEVLST## ;GET START OF CHAIN
DDBSRL
DDSC2A: TRNE P1,DD%LOG ;LOGICAL NAME SEARCH?
CAME T1,DEVLOG(F) ;LOGICAL NAME MATCH?
JRST GETPHY ;NO
LDB T4,PJOBN## ;CHECK JOB #
CAMN T4,J ;THIS JOB?
JRST DDSRCV ;CLEAR SYS BITS AND GOOD RETURN
GETPHY: TRNN P1,DD%PHY ;PHYSICAL SEARCH?
JRST DDSRC3 ;NO, SKIP OVER THIS
IFN FTSPL,<
SKIPGE DEVSPL(F) ;NO MATCH ON SPOOLED DDB'S
JRST DDSRC3 ;IT IS A SPOOLED DDB
>
TDNN T3,DEVMOD(F) ;IF TSTDSK SAYS IF ISN'T A DISK,
CAME T1,DEVNAM(F) ;OR IF DEVICE NAMES DON'T MATCH...
JRST DDSRC3 ;THEN IGNORE THIS ONE (SINGLE-ACCESS)
TRNN P1,DD%LOG ;DO WE CARE ABOUT LOGICAL NAMES?
JRST DDSRCW ;NO, WE FOUND A PHYSICAL NAME
TLNN P1,-1 ;FOUND DDB ALREADY?
HRL P1,F ;SAVE THIS ADDRESS
DDSRC3: HRRZ T2,F ;SAVE PREDECESSOR
PUSHJ P,NXDDP ;POINT AT NEXT DEVICE ON CHAIN
TRNN P1,DD%CHN ;DON'T LOOK IN FUNNY SPACE IF SEARCHING
TRNN F,-1 ; ONLY DEVLST CHAIN OR IF WE RUN OUT
CAIA ; OF DDB'S
JRST DDSC2A ;NO
DDBSRU
TRNN P1,DD%PHY ;ARE WE LOOKING FOR PHYSICAL?
POPJ P, ;NO, AND WE DIDN'T FIND A LOGICAL MATCH
HLR F,P1 ;YES, GET SAVED ADDRESS
JUMPN F,CPOPJ1## ;EXIT WITH PHYSICAL DDB MATCH IF THERE WAS ONE
IFN FTRDX,<
PUSHJ P,TSTRDX## ;CHECK FOR REMOTE DATA ENTRY ROUTINE
SKIPA ;NO
JRST CPOPJ1## ;YES,
>;END IFN FTRDX
IFN FTNET,<
TRNN T1,505050 ;MUST ME NUMBERIC RT HALF
PUSHJ P,TSTNET## ;YES CHECK FOR NETWORK DEVICE
SKIPA ;NOT A NETWORK DEVICE
PJRST CPOPJ1## ;YES, FOUND THE DEVICE ON THE NETWORK
>;END FTNET
IFN FTMSGSER,<
PUSHJ P,TSTMPX## ;NO, CHECK FOR MPX DDB
SKIPA ;NO--TRY FOR TTY
JRST CPOPJ1## ;YES--ALL DONE
>;END FTMSGSER
CAME T1,[SIXBIT /TTY/] ;IS THIS PUBLIC LOGICAL NAME TTY?
JRST GETDDB## ;SEE IF IT'S A TTY
JUMPE J,CPOPJ## ;FAIL IF NOT LOGGED IN
PUSH P,U ;SAVE OUTPUT BYTE PTR(TTY) OR INIT ARG ADR
PUSHJ P,TTYFND## ;FIND TTY JOB IS ATTACHED TO
JRST UPOPJ1## ;GOOD RETURN
DDSRCV: TLZ F,-1
DDSRCW: DDBSRU
JRST CPOPJ1##
IFN FTGSRC!FTSFD,<
;DVASRC - MODIFIED DDB SEARCH ROUTINE TO SEARCH FOR GENERIC
;DEVICE NAMES
;THIS ROUTINE SEGREGATES SPECIFICATIONS INTO THREE CLASSES:
; (1) SPECIFIC DEVICE - RH OF NAME IS NUMERIC
; - ERROR RETURN TAKEN - NOT GENERIC
; (2) GLOBAL GENERIC - RH OF NAME IS NULL
; - GENERIC SEARCH DONE FIRST AT JOB SITE
; IF NO SUCH DEVICE THERE SEARCH REPEATED AT
; CENTRAL SITE - OTHERWISE FAIL
; (3) SPEFICIED GENERIC - RH OF NAME IS NN WHERE NN
; IS THE STATION TO SEARCH AT
;INTERFACE TO DVSTAS PRESERVED (T3,T4)
DVASRC::SETZ T4, ;RESET INTERNAL FLAG
HRRZ T2,T1 ;GET RH OF NAME
TRNE T2,7777 ;CHECK FOR LOCAL GENERIC DEVICE GGU
JRST DVSSRC ;NI, SPECIFIC MODE GENERIC GGGNN
;USER HAS SPECIFIED GENERIC DEVICE WITH NO STATION SPECIFICATION
IFN FTNET,<
MOVE T2,JBTLOC##(J) ;GET THIS GUY'S STAION NUMBER
PUSHJ P,DVSTAS ;SEARCH FOR A DEVICE AT THIS STATION
SKIPA T2,JBTLOC## ;FAILED - TRY CENTRAL SITE (MAYBE)
JRST CPOPJ1## ;SUCCESS - FOUND A FREE DEVICE
JUMPL T4,CPOPJ## ;FAILED BUT FOUND AT LEAST ONE DEVICE
;THAT MET THE SPEC AND WAS BUSY (T4=-1 AND NONSKIP RETURN)
;NO DEVICE OF REQUIRED TYPE AT USER'S
;SITE SO TRY CENTRAL SITE
>
JRST DVSTAS ;GO DO GENERIC SEARCH
;STILL IN FTGSRC!FTSFD CONDITIONAL
;ROUTINE TO CONVERT STATION NAME
;ENTER NAME IN T1
;EXIT CPOPJ IF STATION ILLEGAL
;EXIT CPOPJ1 IF OK, T2=STATION NUMBER
DVSCVT::PUSH P,T1 ;SAVE NAME
IFN FTNET,<
HRLZS T1 ;GET SNN
PUSHJ P,CVTOCT ;GO CONVERT NN TO OCTAL NUMBER
JRST TPOPJ## ;ERROR IN NN SPEC
;MUST NOT HAVE BEEN SNN AFTER ALL
;SO RESTORE T1 AND GIVE ERROR RETURN
MOVE T2,(P) ;GET DEVICE NAME
TRNE T2,77 ;UNIT NUMBER PRESENT?
LSH T1,-3 ;YES, RIGHT JUSTIFY STATION NUMBER
SKIPN T2,T1 ;IF NN IS ZERO PUT STA # IN T2
MOVE T2,JBTLOC## ;USE CENTRAL SITE NMBER
JRST TPOPJ1## ;GOOD RETURN.
>
IFE FTNET,<
TRNN T1,50 ;CHECK FOR
TRNN T1,20 ; 0-7
JRST TPOPJ## ;NOT 0-7
HRRZS T1 ;IF NO REMOTES, ONLY STATION ZERO LEGAL
TRZ T1,77 ;CLEAR UNIT #
CAIN T1,'00 ' ;SKIP IF STATION 0
TDZA T2,T2 ;OK, SET T2=0 FOR CENTRAL SITE
JRST TPOPJ## ;NO, ILLEGAL
JRST TPOPJ1## ;RESTORE NAME AND GOOD RETURN
>
;USER HAS SPECIFIED NNU IN RH OF NAME
DVSSRC: PUSH P,T1
PUSHJ P,DVSCVT ;CONVERT NN TO OCTAL
JRST TPOPJ## ;ILLEGAL STATION NUMBER
DPB T1,[POINT 6,T1,23] ;LEFT JUSTIFY THE UNIT NUMBER IF ANY
TRZ T1,7777 ;CLEAR THE JUNK
;AND FALL INTO GENERIC SEARCH
;WITH NN AS STATION NUMBER
PUSHJ P,DVSTAS ;FIND DEVICE
JRST TPOPJ##
JRST TPOPJ1##
;STILL IN FTGSRC!FTNET!FTSFD CONDITIONAL
;ROUTINE TO FIND A GENERIC DEVICE AT A SPECIFIC STATION
;CALL:
; LH(T1) 3 CHAR GENERIC NAME TO SEARCH ON
; RT(T1) UNIT NUMBER OR 0
; C(T2) STATION TO SEARCH AT
; RH(T3) HAS BITS TO TEST FOR FAIL ANYWAY
;THIS ROUTINE GIVES SUCCESS RETURN (SKIP) ONLY IF
; (1) A FREE DEVICE IS FOUND WITH LH OF NAME MATCHING, OR
; (2) CURRENT JOB (IN J) HAS DEVICE FOR WHICH A LH
; MATCH HAS BEEN DONE AND THE DEVMOD BITS INDICATED IN T3 ARE OFF.
;THE DDB RETURNED WILL BE ONE ALREADY ASSIGNED TO THE JOB IF
;IT MEETS THE ABOVE CRITERIA
;C(T4) ARE RETURNED AS -1 IF A DEVICE MATCH IS MADE WHETHER OR NOT
;THE DEVICE CAN BE GIVEN TO THE JOB
;C(T4) .GE. 0 IF NO SUCH DEVICE
DVSTAS: JUMPE T1,CPOPJ##
PUSHJ P,SAVE3## ;SAVE P1-3
PUSH P,T1 ;SAVE T1
MOVEI T4,0 ;CLEAR FLAG
IFN FTNET,<
SKIPN T2 ;IF ZERO STA # USE CENTRAL SITE
MOVE T2,JBTLOC## ;FOR SEARCH
>
PUSHJ P,CHKGEN ;SEARCH FOR SPECIAL GENERIC DEVICE
JRST [SETZ F,
JRST TPOPJ##] ;DIDN'T FIND IT--BAD DEVICE NAME
SETZB P2,P3 ;INITIALLY NO FREE DDB
DDBSRL
DVSTAL:
IFN FTNET,<
LDB P1,PDVTYP## ;DEVICE TYPE
CAIN P1,.TYPTY/.TYEST;A PTY?
JRST DVST1 ;YES, PTYS ARE AT THE CENTRAL SITE
LDB P1,PDVSTA## ;GET STA # FROM DDB
CAME P1,T2 ;IS IT THE RIGHT STA?
JUMPN T2,DVSNXT ;NO - TRY NEXT DDB IF NOT 0 (REMSW=0)
DVST1:>
HLLZ P1,DEVNAM(F) ;MATCH ON LH OF NAME (GENERIC)
TLNE T1,77 ;IS THIS A 2-CHAR NAME?
JRST DVST2
PUSHJ P,CKSPEC ;YES, CHECK FOR SPECIAL NAMES
JRST DVST2A
JRST DVST2 ;NONE FOUND, CONTINUE
;STILL IN FTGSRC!FTNET!FTSFD CONDITIONAL
PUSH P,T3 ;SAVE THIS
CAMN P1,[SIXBIT/LPT/] ;LL/LU
JRST DVLPTS ;IT'S A FUNNY LPT
HLRZ T3,TDVUDB##(F) ;IT'S A MAGTAPE, GET UDB
HRRZ T3,TUBCNF##(T3) ;GET CONFIG INFO
TRNN T3,TUC7TK## ;IS THIS 7-TRACK ?
SKIPA T3,[SIXBIT/M9/] ;NO, SETUP 9-TRACK
MOVSI T3,'M7 ' ;YES, SET UP NAME
JRST DVST0 ;GO COMPARE NAMES
DVLPTS: MOVSI P1,dvlptl ;SET UP BIT TO CHECK FOR LOWER CASE
TDNn P1,DEVchr(F) ;IS THIS A LC LPT?
SKIPA T3,[SIXBIT /LU/]
MOVSI T3,'LL '
DVST0: CAMN T1,T3 ;IS THIS WHAT WE WANT ?
JRST [POP P,T3
JRST DVST3] ;YES
POP P,T3 ;NO, FALL THRU NAME CHECK TO DVSNXT
DVST2: HRRZ P1,DEVNAM(F) ;GET THE UNIT NUMBER
LSH P1,14 ;POSITION TO HIGH ORDER
TRNN T1,770000 ;IS THERE S PHYSICAL UNIT FOR GENERIC
TRZ P1,770000 ;NO, CLEAR THE UNIT NUMBER
HLL P1,DEVNAM(F) ;MATCH ON LH OF NAME (GENERIC)
DVST2A: CAME P1,T1 ;
JRST DVSNXT ;N0 - TRY NEXT DDB
DVST3: MOVE P3,F ;SAVE ANYTHING HERE
HRROI T4,-1 ;SET FLAG (T4) TO -1 TO
;INDICATE THAT A DDB HAS BEEN FOUND
LDB P1,PJOBN## ;GET JOB DDB ASSIGNED TO
JUMPN P1,DVSNF ;BRANCH IF ASSIGNED TO SOMEBODY
MOVE P1,DEVMOD(F) ;GET ASSIGN BITS
TRNE P1,ASSCON+ASSPRG ;IS IT ASSIGNED TO JOB 0 ?
JRST DVSNXT ;YES - TRY NEXT DDB ANYWAY
MOVSI P1,DEPRAS ;GET RESTRICTED ASSIGNMENT BIT
TDNN P1,DEVSTA(F) ;IS THIS DEVICE RESTRICTED?
JRST DVSTA1 ;NO, PROCEED
MOVE P1,JBTPPN##(J) ;YES. GET JOB'S PRJ-PRG #
CAMN P1,FSFPPN## ;=1,2?
JRST DVSTA1 ;OK TO USE DEVICE
JUMPL M,DVSNXT ;CANNOT USE IF FROM COMMAND AND NOT 1,2
MOVSI P1,JACCT ;NOT [1,2]. CHECK PRIVILEGES
TDNN P1,JBTSTS##(J) ;JACCT ON?
JRST DVSNXT ;NO, LOOK AT OTHER DEVICES
DVSTA1: SKIPN P2 ;FOUND ONE BEFORE DON'T BOTHER
MOVE P2,F ;FOUND A FREE DEVICE THAT WE CAN USE-
;SAVE IT AND CONTINUE TO SEE IF WE
;CAN FIND ONE ALREADY ASSIGNED
;TO THIS JOB
JRST DVSNXT ;GO DO SOME MORE LOOKING
;STILL IN FTGSRC!FTNET!FTSFD CONDITIONAL
;HERE IF THIS DDB IS ALREADY ASSIGNED OR INITED TO SOME JOB
DVSNF: CAME P1,J ;DDB ASSIGNED TO THIS JOB ?
JRST DVSNXT ;NO - NICE TRY ANYWAY
TDNE T3,DEVMOD(F) ;YES -- IS HE USING THE DEVICE
;(IS THE DEVCE INIT'ED ON INIT OR
;ASSIGN'ED ON ASSIGN)?
JRST DVSNXT ;YES - CAN'T USE THIS ONE TRY NEXT
;FOUND A DEVICE ACCEPTABLE TO CALLER - OUR
;IDEAL CASE ! - GIVE GOOD RETURN WITH
DDBSRU
JRST TPOPJ1## ;F SET UP
DVSNXT: PUSHJ P,NXDDB ;POINT AT NEXT DEVICE ON CHAIN
JUMPE F,DVSNX2 ;END OF CHAIN
JRST DVSTAL ;NO, STILL LOOKING AT SAME DEVICES
DVSNX2: JUMPE P2,DVSFL ;IF WE GET HERE AND
;P2 = 0 THEN WE HAVE FOUND NO DDB'S
;THAT ARE AVAILABLE (WE MAY HAVE
;FOUND DDB'S IN USE THO) - SO GIVE
;ERROR RETURN
MOVE F,P2 ;IF P2 IS NOT 0 HOWEVER, WE WERE
;TRYING TO FIND AN ASSIGNED DEVICE
;AND FAILED BUT DID PREVIOUSLY FIND
;A FREE DEVICE - SO USE IT
DDBSRU
JRST TPOPJ1## ;GIVE GOOD RETURN WITH DDB IN F
DVSFL: DDBSRU
JUMPN T3,DVSNET ;IF T3 WAS NOT ZERO - WE FAIL HERE
JUMPE P3,DVSNET ;IF T3=0, BUT NO SUCH DEVICE, FAIL
MOVE F,P3 ;HOWEVER, IF T3=0 AND THERE WAS
JRST TPOPJ1## ;SOME DEVICE (EVEN THO NOT
;AVAILABLE) GIVE IT TO CALLER
DVSNET: PUSHJ P,GENNET## ;TRY GENERIC NETWORK
PJRST TPOPJ## ;FAIL
PJRST TPOPJ1## ;WE WIN F=DDB
> ;END CONDITIONAL ON FTGSRC!FTNET!FTSFD
;SUBROUTINE TO CHECK FOR DEVICE NAME OF <LL,LU>
;
;CALL:
; HLLZ P1,DEVNAM(F)
; PUSHJ P,CKSPEC
; RETURN HERE IF MT OR DT
; RETURN HERE IF NOT LL OR LU
; HERE IF LL/LU <AND> P1 WAS SIXBIT /LPT/
; <OR> IF M7/M9 <AND> P1 WAS MTA/MTB/MTC
;
CKSPEC: CAME T1,[SIXBIT /LU/]
CAMN T1,[SIXBIT /LL/] ;IS IT ONE OF THOSE?
JRST CKSPC3 ;YES, GO CHECK FOR LPT
CAME T1,[SIXBIT /M7/] ;M7?
CAMN T1,[SIXBIT /M9/] ;M9?
JRST CKSPC4 ;YES
CAME T1,[SIXBIT /DT/] ;IS IT A "DT"?
CAMN T1,[SIXBIT /MT/] ;OR A "MT"?
TLZ P1,77 ;IF SO, FIX P1 SO A MATCH WILL BE SEEN
POPJ P, ;RETURN
CKSPC3: CAME P1,[SIXBIT /LPT/] ;IS THIS A LPT DDB?
JRST CPOPJ1## ;NO
JRST CPOPJ2## ;YES, WE WILL DO SPECIAL STUFF
CKSPC4: TLZ P1,77 ;CLEAR CONTROLLER TAPE
CAME P1,[SIXBIT/MT/] ;MT?
JRST CPOPJ1## ;NO
JRST CPOPJ2## ;YES
;ROUTINE TO CHECK A DEVICE NAME TO SEE IF IT IS GENERIC.
;CALL: MOVE T2,SIXBIT NAME
; PUSHJ P,GNRCDV
; RETURN HERE IF GENERIC
; RETURN HERE IF NOT
GNRCDV: PUSHJ P,SAVE4## ;SAVE P1-P4
PUSHJ P,SAVT## ; AND T1-T4
PUSH P,F ; AND F
MOVE T1,T2 ;MOVE NAME TO T1
PUSHJ P,DEVLG ;LOGICAL NAME?
TLNN T1,770000 ;NO, SIXBIT ARGUMENT?
JRST FPOPJ1## ;NOT GENERIC IF LOGICAL NAME OR NOT SIXBIT
PUSHJ P,LNMTST## ;IS IT A PATH. LOGICAL NAME?
TRNE T1,77 ;NO, IS IT DEVNNN?
JRST FPOPJ1## ;NOT GENERIC IF EITHER
PUSHJ P,CK2CHR ;CONVERT 2 CHARACTER NAMES TO 3
CAME T1,[SIXBIT/TTY/] ;GENERIC TTY?
PUSHJ P,ALIASD## ;NO, GENERIC DSK?
JRST FPOPJ## ;YES, GIVE NON-SKIP RETURN
TRNE T1,-1 ;DEV
TRNE T1,7777 ; OR DEVNN?
PUSHJ P,CHKGEN ;YES, CHECK FOR GENERIC
JRST FPOPJ1## ;NOT FOUND
JRST FPOPJ## ;FOUND
;SUBROUTINE TO SEARCH THE GENERIC DEVICE TABLE
;
;CALL:
; MOVE T1,[SIXBIT .DEVICE NAME.]
; PUSHJ P,CHKGEN
; HERE IF NOT FOUND
; HERE IF FOUND WITH F = DDB
;
;p2 is saved (for assign in comcon), p1 and p3 are destroyed
CHKGEN::PUSH P,P2 ;SAVE P2
PUSH P,T1 ;SAVE OLD NAME
PUSHJ P,FXSNAM ;FIX-UP NAME
HLLZ P1,T1 ;GET DEVICE NAME
POP P,T1 ;RESTORE OLD NAME
MOVEI P2,GTLEN##-1 ;SET UP POINTER FOR GENERIC TABLE SEARCH
DVS2: HLLZ P3,GENTAB##(P2) ;GET DEVICE NAME FROM TABLE
CAMN P1,P3 ;MATCH?
JRST DVS3 ;YES, FOUND DEVICE
SOJGE P2,DVS2
JRST DVS5 ;NO, NONE ARE DEFINED
DVS3: HRRZ F,GENTAB##(P2) ;GET DDB POINTER
AOS -1(P) ;BUMP RETURN ADDRESS
SKIPN F ;SKIP RETURN IF DDB ADDRESS IN TABLE
DVS5: HLRZ F,DEVLST## ;NOT IN THE TABLE RETURN DEVLST
POP P,P2 ;GET P2 BACK
POPJ P, ;RETURN (CPOPJ OR CPOPJ1)
;SUBROUTINE TO FIX SPECIAL 2-CHAR DEVICE NAMES
;CALL:
; MOVE T1,[SIXBIT .DEVICE NAME.]
; PUSHJ P,FXSNAM
; HERE WITH T1 FIXED UP
FXSNAM::CAME T1,[SIXBIT /LU/] ;FUNNY LPT?
CAMN T1,[SIXBIT /LL/] ;...
HRLI T1,'LPT' ;YES
CAME T1,[SIXBIT /DT/] ;DT?
CAMN T1,[SIXBIT /MT/] ;MT?
TLO T1,' A' ;YES, ADD"A"
CAME T1,[SIXBIT /M7/] ;M7?
CAMN T1,[SIXBIT /M9/] ;OR M9?
HRLI T1,'MTA' ;YES
POPJ P, ;RETURN
SUBTTL BUFFER RING BUILDER & CLEARER
;ROUTINE TO SETUP N-RING IO BUFFER IN USER AREA
;CALL: MOVEI T2,ADDRESS OF BUFFER HEADER
; PUSHJ P,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 M.
; 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 T3:=IOUSE,C(JOBFF) + 1
; AND JOBFF:=C(JOBFF) + N(BUFFER SIZE + 2)
; P2 IS RESTORED.
BUFCLC::HRRZ T1,T2 ;ADDRESS OF BUFFER HEADER
PUSHJ P,UADRCK ;GET PAGE IN CORE IF IT ISN'T
PUSHJ P,SAVE4## ;SAVE P1-P4
LDB P3,PBUFSZ## ;T1=BUFFER SIZE
HRRZ P1,.JDAT+JOBFF## ;P1:=FIRST FREE LOCATION + 1
ADDI P1,1
HRRZ P2,P1
HRL P2,P3 ;P2:=BUFFER SIZE,FIRST FREE LOC + 1
ADDI P3,2 ;P3:=BUFFER SIZE + 2
HRRZ T2,M ;T2:=N=ADDRESS FIELD OF AC UUO
SKIPN T2 ;SEE IF DEFAULT
PUSHJ P,DFTNB ;YES, GET DEFAULT
HRR M,T2
MOVE P4,T2 ;PUT NO OF BUFFERS IN P4
HRRZ T1,P3 ;BUFFER SIZE+2
IMUL T1,T2 ;TIME NO. OF BUFFERS
ADDI T1,0(P2) ;ADD LOCATION OF 1ST BUFFER
SUBI T1,2 ;READJUST FOR USRREL COMPARISEN
TLZE T1,-1 ;CHECK IF HE WENT OVER 256K
PJRST ADRERR## ;BETTER NOT ALLOW THAT!
CAMG T1,.UPMP+.UPREL ;CHECK AGAINST VM USRREL
JRST BUFC1 ;ALREADY ENOUGH CORE FOR BUFFERS
SKIPE .UPMP+.UPREL ;IS THIS A VM USER?
JRST BUFC0 ;YES, MORE CORE REQUIRED
CAMG T1,.CPREL## ;WILL THIS SPACE FIT IN USER CORE?
JRST BUFC1 ;YES, FO DO INBUF CODE
; NO, AUTOMATICALLY EXPAND SIZE OF USER CORE
BUFC0: PUSH P,M ;SAVE A BUNCH OF ACS USED IN CORE AND IO WAIT
PUSH P,F
PUSH P,T4
PUSH P,T1 ;SAVE HIGHEST USRADR TO TRY FOR
PUSHJ P,IOWAIT ;CALL IOWAIT BEFORE CORUUO TO
;REDUCE MAX PDL EXCURSION
MOVE T1,(P) ;HIGHEST USER ADR TO TRY FOR
PUSHJ P,CHGCOR## ;TRY TO ASSIGN CORE
JFCL ;ERROR RETURN-LET ADR CHECK HAPPEN AND STOP JOB
POP P,T1
POP P,T4
POP P,F
POP P,M
MOVE S,DEVIOS(F) ;CHGCOR MAY HAVE ALLOWED S TO BE CHANGED
BUFC1: MOVE T2,T1 ;TOP ADDRESS
HRRZ T1,P2 ;FIRST ADDRESS
PUSHJ P,LRNGE## ;MAKE SURE ALL PAGES ARE IN CORE
BUFC2: ADD P2,P3 ;P2:=C(P2) + C(P3)
HRRZ T1,P1 ;IS LAST ADDR IN BOUNDS?
PUSHJ P,UADRCK
EXCTXU <MOVEM P2,@P1> ;BUFFER HEADER+1:=C(P2)
HRR P1,P2 ;P1 18-35:=C(P2 18-35)
SOJG P4,BUFC2 ;N:=N-1. IS N GR 0?
HRR P2,.JDAT+JOBFF##
ADDI P2,1
MOVEI T1,-2(P1) ;CHECK LAST ADR. OF HEADER
PUSHJ P,UADRCK
SUB P1,P3
IFN FTMSGSER,<
MOVE T4,P1 ;T4 = ADDRESS OF LAST BUFFER
> ;END FTMSGSER
EXCTXU <MOVEM P2,@P1> ;LINK LAST BUFFER TO FIRST BUFFER
ADDI P1,-1(P3)
HRRM P1,.JDAT+JOBFF## ;JOBFF:=C(JOBFF)+1+N(BUFFER SIZE+2)
HRRZ T3,P2 ;T3:=IOUSE,ADDRESS OF FIRST BUFFER
; IN RING.
HRLI T3,IOUSE
POPJ P, ;RETURN
;SUBROUTINE TO COMPUTE DEFAULT NO OF BUFFERS
;RETURNS NUMBER IN T2, RESPECTS T1,T3
DFTNB: MOVEI T2,2 ;ASSUME NOT A DISK
MOVSI T4,DVDSK
TDNN T4,DEVMOD(F) ;IS IT?
POPJ P, ;NOT A DISK
LDB T2,PDYBFN## ;DEFAULT PECIFIED?
JUMPN T2,CPOPJ## ;RETURN IF SO
MOVE T2,NUMBF## ;YES
POPJ P, ;RETURN WITH ANSWER
;ROUTINE TO CLEAR IO BUFFER IN USER AREA
;CALLED AT INTERRUPT AND UUO LEVEL, AT INTERRUPT LEVEL ONLY ON KA10
;CALL: HRRZ T1,REL. ADR. OF 2ND WORD OF USER BUFFER
; PUSHJ P,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 T1 18-35.
BUFCLR::PUSHJ P,UADRCK
PUSH P,T1 ;SAVE FIRST BUFFER ADR.
EXCTUX <HLRZ T2,@T1> ;T2 18-35=SIZE
ANDI T2,IOSIZ
JUMPE T2,TPOPJ## ;WORD COUNT=0 IS ILLEGAL
ADD T2,T1
PUSHJ P,LRNGE##
MOVE T1,T2
POP P,T2 ;RESTORE FIRST ADR.
NOSHUFF ;NO SHUFFLING
HRLI T2,1(T2)
ADDI T2,2
EXCTXU <SETZM -1(T2)> ;CLEAR THIRD WORD
EXCTUU <BLT T2,@T1> ;CLEAR BUFFER
SHUFFLE ;SHUFFLING
JRST CPOPJ1## ;SUCESSFUL RETURN
SUBTTL RANDOM SUBROUTINES FOR I/O
;ROUTINE TO COMPUTE 12 BIT FOLDED CHECKSUM
;CALL: PUSHJ P,CKS12
; EXIT ALWAYS RETURNS HERE
;CALCULATES FOLDED 12 BIT CHECKSUMS OF THE DATA WORDS IN THE
;BUFFER WHOSE ADDRESS IS IN AC T2.
;ON RETURN, THE LEFT HALF OF AC T1 CONTAINS A CHECKSUM OBTAINED
;BY ACCUMULATING, IN ONE'S COMPLEMENT, THE DATA WORDS AND FOLDING IT.
;AC T2 CONTAINS A 1.
CKS12:: AOS T2 ;T2:=-WORD COUNT,ADDRESS OF FIRST DATA WORD
HRRZ T1,0(T2)
MOVNS T1
AOS T2
HRL T2,T1
CLEARM T1 ;INITIALIZE TWO'S COMPLEMENT SUM
CKS12A: ADD T1,0(T2) ;TWO'S COMPLEMENT ADD
AOBJN T2,CKS12A ;DONE?
LSHC T1,-30
LSH T2,-14
ADD T1,T2
LSHC T1,-14
LSH T2,-30
ADD T1,T2
TRZE T1,770000
AOS T1
HRLZS T1
MOVEI T2,1 ;T2:=1
POPJ P,
REPEAT 0,<
;ROUTINE TO CLEAR RESIDUE OF WORD POINTED TO BY A BYTE POINTER
;CALL: PUSHJ P,CLRBYT
; EXIT ALWAYS RETURNS HERE
;CALLED WITH A BYTE POINTER IN AC T1, IT CLEARS THE REST OF THE
;WORD POINTED TO BY THE BYTE POINTER.
CLRBYT::LDB T2,[POINT 6,T1,5] ;T2:=P
DPB T2,[POINT 12,T1,11] ;T1 0-5:=0,T1 6-12:=P
SETZM T2
DPB T2,T1 ;CLEAR BITS 36-P THROUGH 35
POPJ P, ;RETURN
> ;END REPEAT 0
;ROUTINE TO RELEASE ALL DEVICES ASSIGNED TO JOB
IORELS::MOVEI T1,RELEA3 ;RELEASE ALL IO DEVICES(DON'T CLOSE)
;ROUTINE TO DO IO FOR ALL DEVICES ASSIGNED TO JOB
;CALL MOVEI T1,ADR. OF IO SUB.
; PUSHJ P,IOALL
; RETURNS WITH J=CURRENT JOB # ,UUO PRESERVED
IOALL:: PUSHJ P,SAVE3## ;SAVE P1 TO PRESERVE PHYSICAL BIT
PUSH P,T1 ;SAVE ADR. OF SUB.
PUSH P,M ;SAVE M
HLRZ P3,.UPMP+.UPCTA
HRRZ P2,USRHCU## ;HIGHEST CHANNEL NUMBER IN USE
CAILE P2,17 ;BIGGER THAN MAX NUMBER OF CHANNELS ?
STOPCD IOALL2,DEBUG,JAC, ;++JOB DATA AREA CLOBBERED
MOVNS P2
MOVSI P2,-1(P2)
HRRI P2,USRJDA##
MOVEI P1,0
MOVSI M,400000 ;DON'T RETURN ERROR CODES TO USER
IOALL0: HRRZ T1,.UPMP+.UPCTA
CAILE P1,17
JUMPE T1,IOALL2
SKIPN F,(P2) ;GET NEXT DDB ADR., IS IT IN USE?
JRST IOALL1 ;NO, KEEP GOING
MOVE S,DEVIOS(F)
HRLM P1,.UPMP+.UPCTA
MOVE T4,DEVSER(F) ;SETUP ADR. OF DEV. DISP. TABLE
LDB T1,PJOBN## ;GET JOB NUMBER WHICH JOB IS ASSIGNED TO
CAMN T1,.CPJOB## ;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
; 400 RESTART,BUT THE JOB DATA AREA DEVICE ASSIGNMENTS
; FOR SWAPPED OUT JOBS HAVE NOT
PUSHJ P,@-1(P) ;YES,CALL THE SUB.
IOALL1: AOS P1
AOBJN P2,IOALL0 ;DECREMENT USER CHANNEL NUMBER
CAILE P1,20
JRST IOALL2
HRRZ P2,.UPMP+.UPCTA
JUMPE P2,IOALL2
HRLI P2,-HIGHXC+20
MOVEI P1,20
JRST IOALL0
IOALL2: HRLM P3,.UPMP+.UPCTA
POP P,M ;RESTORE M & RETURN RESTORING T1 TOO
MOVE J,.CPJOB## ;GET JOB NO.
JRST TPOPJ##
;WAIT TILL ALL DEVICES ARE INACTIVE
IOWAIT::MOVEI T1,WAIT1##
JRST IOALL
;ROUTINE TO CLEAR PROTECTED JOB DATA AREA IN MONITOR
;AND RECLAIM FREE AREA ABOVE USER PROGRAM FOR IO BUFFERS
;CALL: PUSHJ P,SETUSR
SETUSR::HLRZ T1,.JDAT+JOBSA## ;RESET FIRST FREE LOC. FOR THIS JOB
MOVEM T1,.JDAT+JOBFF##
CLRUSR::SETZM .JDAT+JOBENB## ;INITIALIZE APR TRAPPING (I.E., NONE)
MOVEI T1,USRLO1## ;FIRST LOC+1 TO CLEAR
HRLI T1,USRLO## ;FIRST LOC.
SETZM USRLO##
BLT T1,USRHI##
SETZM USRHCU## ;CLEAR HIGHEST USER IO CHAN. IN USE
POPJ P,
;ROUTINE TO STORES IN DDB AT CLOCK LEVEL
;NEEDED SINCE NO INTERLOCK ON PI7 AND UUO LEVEL ON OTHER CPU
STORS7::
IFE FTMP,<
MOVEM S,DEVIOS(F)
>
IFN FTMP,<
MOVSI T2,IOW
EXCH S,DEVIOS(F)
TLNE S,IOW
IORM T2,DEVIOS(F)
MOVE S,DEVIOS(F)
>
POPJ P,
;ROUTINE TO FLAG DEVICE ACTIVE
;CALL MOVE S,IO STATUS BITS
; MOVE F,ADDRESS OF DEVICE DATA BLOCK
; PUSHJ P,SETACT
;CALLED BY ALL IO SERVICE ROUTINES AT UUO AND INTERRUPT LEVELS
REPEAT 0,<
ORACT: TRO S,IOACT
IORB S,DEVIOS(F)
JRST SETHNG
>
SETACT::TROA S,IOACT
CLRACT::TRZ S,IOACT
TLZ S,IOW
STOIOS::MOVEM S,DEVIOS(F)
SETHNG::LDB T1,PDVTIM## ;GET CODE FOR NO. OF SECONDS
PUSH P,T1 ;STACK THE CODE
MOVEI T1,1 ;COMPUTE 2**N-1
LSH T1,@0(P) ; ..
SUBI T1,1
DPB T1,PDVCNT## ;PUT TIME INTO THE COUNTER
IFN FTMSGSER,<
MOVEI T1,DEPMSG ;LOAD UP THE MESSAGE BIT
TDNN T1,DEVMSG(F) ;CONTROLLED BY MSGSER?
JRST TPOPJ## ;NO, ALL DONE HERE
PUSH P,F ;YES, SAVE F FOR A MOMENT
HRRZ F,DEVXTR(F) ;ADDRESS OF MPX DDB
PUSHJ P,SETHNG ;DO GOOD THINGS FOR IT TOO
POP P,F ;RESTORE DEVICE DDB ADDRESS
> ;END FTMSGSER
JRST TPOPJ## ;RESTORE T1 AND RETURN
IFN FTMP,<
;ROUTINE TO STORE S IN A RACE-FREE MANNER
;GETS THE DEVICE INTERLOCK IF NOT ON PI-LEVEL
LKSTRS::CONSO PI,PI.IPA-PI.IP7
JRST LKSTR1
PIOFF
MOVEM S,DEVIOS(F)
PJRST ONPOPD##
LKSTR1: MOVEM S,DEVIOS(F)
POPJ P,
>
DEVCHK::HLRZ F,HNGLST##
DEVCK0:
IFN FTMP,<
PUSHJ P,CHKCPI## ;DEVICE ON THIS CPU?
JRST DEVCK2 ;NO, IGNORE IT
JUMPL T4,DEVC0A ;DUAL-PORTED?
PUSHJ P,ISITQ ;YES, QUEUED PROTOCAL?
JRST DEVC0A
CAIN T1,7 ;YES, IO START ON THIS CPU?
MOVEI T1,0
CAME T1,.CPCPN##
JRST DEVCK2 ;NO, LET OTHER CPU HANDLE IT
>
DEVC0A: MOVE S,DEVIOS(F) ;IS DEVICE ACTIVE?
MOVE T4,DEVSER(F) ;DISPATCH TABLE ADDRESS
MOVE T1,DEVCHR(F) ;WORD CONTAINING DEVICE OFF-LINE BIT
TLNE T1,DVOFLN ;DID THE SERVICE ROUTINE SAY ITS OFF-LINE?
PUSHJ P,DOFL(T4) ;YES, SEE IF ITS STILL OFF-LINE
JRST DEVCK1 ;IT IS
MOVSI T1,DVOFLN ;ITS ON-LINE, CLEAR THE OFF-LINE BIT
ANDCAM T1,DEVCHR(F)
IFN FTPI,<
PUSHJ P,PSIONL## ;TELL THE USER ITS ON-LINE IF HE'S INTERESTED
>
DEVCK1: TRNN S,IOACT
JRST DEVCK2 ;NO
LDB T1,PDVCNT## ;YES,DECREMENT
SOJL T1,DEVCK2 ;0 MEANS IGNORE DEVICE
DPB T1,PDVCNT##
JUMPN T1,DEVCK2 ;HAS COUNT GONE TO 0?
PUSH P,F
PUSHJ P,DHNG(T4) ;DISPATCH TO SERVICE ROUTINES TO
; UNHANG DEVICE
PUSHJ P,DEVHNG## ;PRINT ERROR MESSAGE AND STOP JOB
POP P,F ;DO NOT PRINT MESS. AND STOP JOB RETURN
DEVCK2: HLRZ F,DEVSER(F)
JUMPN F,DEVCK0
POPJ P,
;ROUTINE TO SETUP J FOR INTERRUPT SERVICE ROUTINE
;CALL PUSHJ P,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 F;PUTS THE J POINTER (C(DEVCTR)) IN AC ITEM.
IOSET:: MOVE J,DEVCTR(F) ;J:=J POINTER=C(DEVCTR)
MOVE S,DEVIOS(F) ;GET IO STATUS FROM THE DDB
POPJ P, ;RETURN
;CALLING SEQUENCE
; PUSHJ P,IOSETC
; EXIT ALWAYS RETURNS HERE
;SETS JBFPTR18-35:=C(T2 18-35)
; JBFCTR:=C(J)*[WORD LENGTH/BYTE SIZE]
;WHERE WORD LENGTH:=36 DECIMAL
; BYTE SIZE:=C(JBFPTR6-11)
; [X]:= INTEGER PART OF X
IOSETC::ADDI U,1 ;JBFPTR12-18:=0
HRLZI T1,7777 ;JBFPTR18-35:=C(T2 18-35)+1
EXCTUU <ANDM T1,@U>
EXCTUU <HRRM T2,@U>
EXCTUU <AOS @U>
TLNN S,IO ;DO THINGS DIFFERENTLY ONLY ON INPUT.
LDB T1,PIOMOD## ;I/O MODE
CAIE T1,PIMMOD ;COUNT BYTES FOR PIM OR BYTE
CAIN T1,BYTMOD ;BYTE MODE?
SOJA U,IOSET2 ;YES, BACKUP U TO POINT AT 1ST WORD OF THE HEADER
EXCTUX <LDB T2,[POINT 6,@U,11]> ;T2:=BYTE SIZE
PUSHJ P,ITMCT1 ;JBFCTR:=C(J)*[36/BYTE SIZE]
IOSET1: ADDI U,1
EXCTXU <MOVEM J,@U>
POPJ P, ;EXIT
;HERE IF BYTE MODE I/O, STORE BYTE COUNT COMPUTED BY THE SERVICE ROUTINE
IOSET2: EXCTUX <MOVE T1,@U> ;POINTER TO THE CURRENT BUFFER
EXCTUX <HRRZ J,1(T1)> ;GET THE BYTE COUNT FROM THE BUFFER
AOJA U,IOSET1 ;STORE IT IN THE USER'S RING HEADER
;ROUTINE TO SET UP CONDITIONS FOR RETURN FROM INTERRUPT LEVEL ON
;DEVICE ERROR (UNIT RECORD)
;SERVICE ROUTINES USING THIS FACILITY MUST FOLLOW THE FOLLOWING PROTOCOL
;A. AT INTERRUPT LEVEL,
; IF NO ERROR AT END OF DATA: CLEAR IOSTBL IN LH(S)
; IF ERROR:
; 1. STOP DEVICE
; 2. PUSHJ P,DEVERR
; 3. SET INTERNAL FLAGS TO REMEMBER ERROR CONDITION TO EFFECT
; RESTART AT A LATER TIME
; 4. DISMISS INTERRUPT
;B. AT UUO LEVEL ENTRANCES THE FOLLOWING MUST BE DONE
; 1. INIT/RELEASE - RESET INTERNAL ERROR FLAGS
; 2. INPUT/OUTPUT - IF ERROR FLAGS (INTERNAL) SET:
; A. CALL HNGSTP
; B. SEE IF DEVICE OK NOW (CALL HNGSTP AGAIN IF NOT)
; C. SET DEVICE FOR RESTART FROM INFO SAVED IN INTERNAL FLAGS
; AND RESET FLAGS
; NOTE: IOSTBL WILL ALWAYS BE CLEARED AT UUO ENTRANCE TO SERVICE ROUTINE
; IF NO ERROR FLAGS SET, NORMAL EXECUTION
DEVERR::TLO S,IOSTBL ;SET ERROR FLAG
IFN FTMSGSER,<
MOVEI T1,DEPMSG ;CONTROLLED BY MSGSER ?
TDNN T1,DEVMSG(F)
JRST DEVER1 ;NO
PUSH P,F
HRRZ F,DEVXTR(F) ;YES, GET THE MPX DDB
MOVSI T1,IOSTBL
IORM T1,DEVIOS(F) ;LITE TROUBLE THERE ALSO
POP P,F ;RESTORE F
DEVER1:>
;IN I/O WAIT?
PUSHJ P,SETIOD## ;YES - WAKE UP
PUSHJ P,RTEVM## ;RETURN EVM IF ANY
PJRST CLRACT ;CLEAR I/O ACTIVE AND RETURN
;ROUTINE TO RETURN NO. OF ITEMS IN BUFFER
;CALL: PUSHJ P,ITMSET
; EXIT ALWAYS RETURNS HERE
;SETS AC J:=(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 P,ITMCNT
; EXIT ALWAYS RETURNS HERE
;SETS AC J:=C(J)*[WORD LENGHT/BYTE SIZE]
;CALLING SEQUENCE
; PUSHJ P,ITMCT1
; EXIT ALWAYS RETURNS HERE
;SETS AC J:=C(J)*[WORD LENGHT/C(T2)]
ITMSET::LDB J,[POINT 17,@DEVADR(F),17];J:=BUFFER SIZE-1
SUBI J,1
ITMCNT::LDB T2,[POINT 6,DEVPTR(F),11];T2:=BYTE SIZE
ITMCT1::MOVEI T1,44 ;J:=C(J)*[WORD LENGTH/C(T2)]
IDIV T1,T2
IMUL J,T1
POPJ P,
;ROUTINE TO SET DEVICE STATUS WORD FROM UUO
;AND SETUP S
SETIOS::PUSHJ P,WAIT2 ;WAIT FOR DEVICE (INCLUDING TTY MONITOR COMMAND
; RESPONSE WHEN USER INITS TTY)
PUSHJ P,CHKMOD ;CHECK FOR LEGAL MODE, IF NOT RIGHT DONT RETURN
TRZ M,IOACT ;LET USER SET ALL BITS EXCEPT IOACT
HRRM M,DEVIOS(F)
MOVE S,DEVIOS(F) ;SET UP "S" SINCE WE JUST CHANGED DEVIOS
MOVSI T1,DVTTY ;TTY DEVICE TYPE BIT
TDNN T1,DEVMOD(F) ;TTY?
POPJ P,
HRRZ U,DDBLDB##(F) ;YES, SET UP U
PJRST UUOLDB## ; AND TELL THE NETWORK
;CHECK FOR A LEGAL MODE FOR DEVICE
CHKMOD: LDB T2,[POINT 4,M,35] ;GET DEVICE DATA MODE
MOVEI T1,1 ;AND CHECK FOR LEGALITY
LSH T1,(T2)
TDNE T1,DEVMOD(F)
POPJ P, ;OK
PUSHJ P,TTYKLQ## ;DISCARD DDB IF IT WAS A FREE TTY
JRST ILLMOD## ;AND GIVE ILLEGAL MODE ERROR
;CHKPIM CHECKS WHETHER A DEVICE IS INITED IN PACKED IMAGE MODE
;IT GIVES 2 RETURNS:
;1 NORMAL RETURN DEVICE IS INITED IN PIM MODE
;2 SKIP RETURN DEVICE IS NOT INITED IN PIM MODE
CHKPIM::PUSH P,T1 ;SAVE T1
LDB T1,PIOMOD## ;LOAD THE MODE
CAIN T1,PIMMOD ;ENABLED IN PIM MODE
JRST TPOPJ## ;YES GIVE NON SKIP RETURN
JRST TPOPJ1## ;NO GIVE SKIP RETURN
;SETUP BYTE POINTER AND ITEM COUNT
;CALL PUSHJ P,NEWBUF
; ADDRESS CHECK WHEN SETTING UP BUFFER
; OK RETURN
NEWBUF::HRRZ T1,DEVADR(F) ;T1:=INPUT BUFFER HEADER ADDRESS
SKIPN DEVEVM(F) ;DOES THIS DDB HAVE EVM?
STOPCD .,STOP,NEV, ;++NO EVM
HLRZ T2,(T1) ;BUFFER SIZE
ANDI T2,IOSIZ ;CLEAR BOOKEEPING BITS
ADDI T2,(T1) ;LAST WORD TO CLEAR
HRLI T1,1(T1) ;MAKE A BLT POINTER
ADDI T1,2
SETZM -1(T1) ;ZERO THE FIRST WORD OF THE BUFFER
BLT T1,(T2) ;ZERO THE BUFFER
NEWBF3: MOVSI T1,7737
AND T1,DEVPTR(F) ;DEVPTR 0-5:=0, DEVPTR 12:=0
HRR T1,DEVADR(F) ;DEVPTR 18-35:=C(DEVADR 18-35) + 1
AOS T1
MOVEM T1,DEVPTR(F)
PUSHJ P,ITMSET ;J:=(BUFFER SIZE-1)*[36/BYTE SIZE]
MOVEM J,DEVCTR(F) ;DEVCTR:=ITEM COUNT
JRST CPOPJ1## ;RETURN
;ROUTINE TO SETUP BYTE POINTER ACCORDING TO DATA MODE
;CALL: PUSHJ P,SETBYT
; EXIT ALWAYS RETURNS HERE
;SETS T1 0-5:=0
; T1 6-11:=S
; T1 12-13:=0
;WHERE S=36 IF DATA MODE (S 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)
;CLOBBERS T2
SETBYT::HRLI T1,PBYTMD## ;ASSUME BYTE MODE
LDB T2,PIOMOD## ;GET MODE FROM S
CAIN T2,BYTMOD ;IS IT ?
POPJ P, ;YES, RETURN
TRNN S,14 ;IS MODE LESS THAN 10?
HRLI T1,PASCII## ;YES,ASCII OR ASCII LINE
TRNE S,14 ;10 OR GREATER?
HRLI T1,PIMAGE## ;YES, IMAGE,IMAGE BIN. OR BIN.
PUSHJ P,CHKPIM ;PACKED IMAGE MODE CHECK
SKIPA ;YES
POPJ P, ;NO
LDB T2,PDVTYP## ;PIM, IS IT TTY
CAIE T2,<.TYMPX/.TYEST> ;ALLOW PIM ON MPX
CAIN T2,<.TYTTY/.TYEST> ;TEST
HRLI T1,PIMTTY## ;YES
POPJ P,
;ROUTINE TO STORE DATA IN IOBUFFER FOR INPUT CHAR. AT A TIME DEVICES
;CALL: PUSHJ P,STODAT
; EXIT1 CHECKSUM ERROR
; EXIT2 BLOCK FULL OR BLOCK COMPLETE
; EXIT3 DATA STORED CORRECTLY
;CALLED FROM AN INPUT SERVICE ROUTINE WITH A DATA J IN AC DAT.
;STORES THE DATA J IN THE BUFFER, CHECKING TO SEE IF IT WERE
;THE FIRST J 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 P,STOSQD
; XXXX ALWAYS SKIPS
; EXIT ALWAYS RETURNS HERE
;STORES THE WORD COUNT:=C(DEVPTR 18-35) -C(DEVIAD 18-35) - 1
;IN THE BUFFER.
STODAT::TLNN S,IOFST ;IS THIS FIRST J OF BUFFER?
JRST STO0 ;NO
PUSHJ P,NEWBUF ;SET UP A NEW BUFFER. J:=(BUFFER
; SIZE - 1)*[36/BYTE SIZE]
POPJ P,
STO0: LDB T2,PIOMOD## ;DATA MODE
CAIN T2,B ;MODE=BINARY?
JRST STOBIN
TLZ S,IOFST
STO1: IDPB U,DEVPTR(F) ;STORE DATA IN BUFFER.
CAIE T2,A ;MODE=ASCII, IMAGE, OR BINARY?
CAIN T2,I
JRST STOAIB
CAIE T2,IB ;IMAGE BINARY?
CAIN T2,B ;CHECKSUM BINARY?
JRST STOAIB ;YES
ANDI U,177 ;NO, MUST BE ASCII LINE MODE.
CAIG U,14 ;LINE FEED,FORM FEED, OR VERTICAL TAB?
CAIGE U,12
JRST .+2 ;NO
JRST STOSQF ;YES
SOJGE J,CPOPJ2## ;J:=C(J)-1. IS C(J) GR OR=0?
STOE1: TRO S,IOBKTL ;IOBKTL:=1
POPJ P,
STOAIB: SOJG J,CPOPJ2##; J:=C(J)-1. IS C(J) GR 0?
CAIN T2,A ;MODE=ASCII?
JRST STOSQF ;YES
CAIN T2,B ;MODE=BINARY?
JRST STOBND ;YES, COMPUTE CHECKSUM AND CHECK.
PUSHJ P,ITMSET ;J:=(BUFFER SIZE-1)*[36/BYTE SIZE]
; - C(DEVCTR)
SUB J,DEVCTR(F)
MOVE T2,DEVIAD(F) ;STORE ITEM COUNT
AOJA J,STOSQE ;IN FIRST WORD OF BUFFER
STOSQD::TLZN S,IOFST ;FIRST CALL?
JRST STOSQF ;NO
PUSHJ P,NEWBUF ;YES, CLEAR BUFFER,SET ITEM COUNT
POPJ P, ;ADDRESS CHECK
STOSQF: HRRZ T2,DEVIAD(F) ;REL. ADR. OF BUFFER
HRRZ J,DEVPTR(F) ;J:=C(DEVPTR 18-35) -
; C(DEVIAD 18-35) -1
SUBI J,1(T2)
STOSQE: HRRM J,1(T2) ;WORD COUNT TO FIRST WORD IN BUFFER
JRST CPOPJ1## ;EXIT2. BLOCK COMPLETE
STOBIN: TLZN S,IOFST ;WILL THE NEXT J BE THE FIRST J
JRST STO1 ;OF A BUFFER? IOFST:=0
HRRZ T1,U ;YES.
CAMLE T1,J ;IS WORD COUNT LE (BUFFER SIZE-1)*
JRST STOE1 ; [36/BYTE SIZE]?
MOVE J,T1 ;J:=WORD COUNT
MOVEM U,@DEVPTR(F) ;STORE WORD COUNT IN BUFFER
JRST CPOPJ2## ;EXIT3. DATA STORED CORRECTLY.
STOBND: MOVEI T2,@DEVIAD(F)
PUSHJ P,CKS12 ;COMPUTE CHECKSUM
ADD T2,DEVIAD(F)
HLLZ T2,@T2 ;DATA CHECKSUM=COMPUTED CHECKSUM?
CAMN T1,T2
JRST CPOPJ1## ;EXIT2. BLOCK COMPLETE
TRO S,IODTER ;IODTER:=1
POPJ P, ;EXIT1. CHECKSUM ERROR
;THIS PAIR OF ROUTINES MAY BE USED BY ROUTINES
; THAT ARE CALLED FROM BOTH UUO-LEVEL AND INTERRUPT LEVEL
; TO DETERMINE IF THEY MAY BLOCK. (IE ARE AT LOGICAL
; UUO LEVEL)
UUOLVL::PUSH P,T1 ;ROUTINE TO SKIP IF AT UUO LEVEL
HRRZ T1,P ;GET THE ADDRESS OF OUR STACK
CAMLE T1,SYSSIZ## ; AND IF IT'S NOT IN THE SYSTEM'S
AOS -1(P) ; LOW SEG WE ARE AT UUO LEVEL
JRST TPOPJ##
INTLVL::PUSH P,T1 ;ROUTINE TO SKIP IF AT LOGICAL INTERRUPT LEVEL
HRRZ T1,P ;GET THE ADDRESS OF OUR STACK,
CAMG T1,SYSSIZ## ; AND IF IT'S IN THE SYSTEM LOW SEG
AOS -1(P) ; WE ARE AT INTERRUPT OR CLOCK LEVEL
JRST TPOPJ##
XLIST
$LIT
LIST
UUOEND::END