Trailing-Edge
-
PDP-10 Archives
-
bb-bt99q-bb
-
uuocon.x23
There is 1 other file named uuocon.x23 in the archive. Click here to see a list.
TITLE UUOCON - UUO HANDLER AND UUO+IO ROUTINES - V2075
SUBTTL /CHW/TL/RCC/CMF/PH/GDR/DAL/EVS/TW/JMF/DRT/JBS/RCB 16-MAY-89
SEARCH F,S,DEVPRM,BTSPRM
$RELOC
$HIGH
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION
; 1973,1974,1975,1976,1977,1978,1979,1980,1982,1984,1986,1988.
;ALL RIGHTS RESERVED.
.CPYRT<1973,1988>
XP VUUOCN,2075 ;THIS MACRO PUTS VERSION NO. IN STORAGE MAP AND GLOB
UUOCON::ENTRY UUOCON ;ALWAYS LOAD UUOCON(IF LIB SEARCH)
IFNDEF MAXCAL,<XP MAXCAL,56>
;DEFINE HIGHEST CALLI UUO WHICH HAS
; CORRESPONDING CALL UUO
; TABLE OF CONTENTS FOR UUOCON
;
;
; SECTION PAGE
; 1. UUO DISPATCH ROUTINE...................................... 2
; 2. CALL & CALLI UUO'S........................................ 7
; 3. EXIT & SETPOV UUO'S....................................... 19
; 4. RESET & APRENB UUO'S...................................... 20
; 5. MISC. ACCOUNTING UUOS (JOBNO,JOBTIM,DATE & MSTIME)........ 24
; 6. SLEEP SERVICE FOR SLEEP UUO, DTA, MTA AND SCNSER.......... 26
; 7. PEEK UUO.................................................. 27
; 8. POKE. UUO................................................. 28
; 9. PERF. MUUO................................................ 31
; 10. CALLS TO SEGCON FOR SETUWP AND REMAP...................... 35
; 11. TRIVIAL UUOS (LIGHTS, TIMER AND SWITCH)................... 36
; 12. DVPHY. UUO................................................ 37
; 13. DEVCHR AND DEVSIZ UUO'S................................... 39
; 14. GETPPN AND DEVPPN UUO'S (ALSO RTZER)...................... 45
; 15. IONDX. UUO............................................... 46
; 16. SUBROUTINE TO FIND A DDB GIVEN ITS IO INDEX............... 48
; 17. GTNTN./GTXTN. UUO'S FOR TTY NAMES......................... 50
; 18. MVBFH. UUO
; 18.1 MOVE BUFFER HEADERS............................... 52
; 19. DEVSTS, DEVLNM, DEVRST, AND DEVURS UUO'S.................. 53
; 20. SETDDT, WAIT AND GETLIN CALLI'S ; WAIT2 AND GETPPL........ 56
; 21. ACCT. UUO - ACCOUNTING UUO................................ 59
; 22. LOGIN, LOGOUT AND ATTACH UUO'S............................ 61
; 23. GETTAB UUO................................................ 67
; 24. SETNAM & CNGPPN UUO'S..................................... 73
; 25. DEVNAM UUO................................................ 74
; 26. REAL-TIME AND HIBWAKE FEATURE............................. 75
; 27. DAEMON UUO'S AND ROUTINES................................. 84
; 28. ALLOC. UUO................................................ 91
; 29. DEVOP. UUO................................................ 95
; 30. FILOP. UUO................................................ 97
; 31. PERF. UUO................................................. 109
; 32. CLOSE UUO................................................. 110
; 33. INBUF & OUTBUF UUO'S...................................... 114
; 34. OPEN & INIT UUO'S......................................... 115
; 35. COMMON PART OF LOOKUP AND ENTER........................... 121
; 36. COMMON PART OF RENAME, USETI/O, UGETF AND UTPCLR.......... 123
; 37. COMMON PART OF INPUT AND OUTPUT UUO'S..................... 124
; 38. RELEASE UUO............................................... 140
; 39. STATUS SETTING AND GETTING UUO'S.......................... 142
; 40. ROUTINES TO ADVANCE BUFFERS............................... 144
; 41. DUMP MODE COMMAND LIST PROCESSING ROUTINES................ 152
; 42. DDB SCAN LOGIC............................................ 156
; 43. BUFFER RING BUILDER & CLEARER............................. 178
; 44. RANDOM SUBROUTINES FOR I/O................................ 182
;THE CALL UUO ROUTINES AND THE IO UUO ROUTINES
;SOME UUO DO DISPATCH TO OTHER ROUTINES OUTSIDE OF UUOCON
;SYSTEM UUOS(40-77) FIRST SAVE THE USERS ACS IN RELATIVE LOC 0-17
;THEN THE FOLLOWING ACS ARE LOADED UP BEFORE DISPATCHING:
; P ;PUSHDOWN LIST IN CURRENT JOB DATA AREA
; M ;THE CONTENTS OF LOC 40
; EXCEPT THAT ON A CALL OR CALLI UUO, THE ADDRESS IS
; MODIFIED TO BE THE AC OF THE UUO,FOR
; PICKING UP ARGUMENTS.
; F ;ADR. OF DEVICE DATA BLOCK
; S ;DEVICE IO STATUS WORD
; T1 ;(CALLI) CONTENTS OF AC
; T4 ;ADR. OF DEVICE SERVICE ROUT. DISPATCH TABLE
; P1 ;THE USER IO CHANNEL(AC FIELD) OF UUO
;LH BIT 0=1 (PHONLY) IF ONLY PHYSICAL DEVICE WANTED
; IE NO LOGICAL NAME SEARCH
;RETURN IS PUSHED ON END OF PD LIST
;THEN IF CALL WAS FROM USER MODE, THE UUO ROUTINE IS CALLED
;WITH A PUSHJ, SO THAT ALL UUO ROUTINE RETURN WITH A POPJ P,
;WHICH WILL RETURN CONTROL TO UUOCON WHICH WILL RESTORE USERS
;ACS AND RETURN TO HIM
;IF THE CALL IS FROM EXEC MODE, THE UUO ROUTINE IS CALLED
;BY DOING JUST A JRST, WHEN THE UUO ROUTINE RETURNS WITH
;A POPJ, IT WILL RETURN TO THE EXEC WITHOUT RESTORING
;ANY ACS
; CONTROL MAY ALWAYS BE RETURNED BY EXECUTING A
; POPJ P,
; WHICH WILL RESTORE THE ACS, APR BITS, AND RETURN.
; THE UUO HANDLER IS PURE IF THE FOLLOWING RESTRICTIONS ARE OBSERVED.
; RESTRICTIONS: UUOS CANNOT BE CALLED BY INTERRUPT SERVICE ROUTINES.
;ALL UUO'S SHOULD PRESERVE THE PRESERVED AC'S P1-P4
SUBTTL UUO DISPATCH ROUTINE
;HERE FROM COMMON
UUOSY1::HRLZ M,.USMUO ;UUO OP CODE
IOR M,.USMUE ;RESULTS OF THE EFFECTIVE ADDRESS CALCULATION
MOVE J,.CPJOB## ;SET UP J IN CASE UUOERR
; (GIVRES EXPECTS J SET UP)
TLNN M,740000 ;SYSTEM UUO?
JRST UUOERR## ;NO, 0-37 ARE ILLEGAL, PRINT ERROR
MOVE T1,.USMUO ;MUUO FLAGS
TLNE T1,(XC.USR) ;DON'T PUSH FLAGS IF EXEC MODE UUO
PUSH P,.USMUO ;PUSH FLAGS
PUSH P,.USMUP ;SAVE RETURN ON PUSH DOWN LIST
PUSHJ P,FNDPDS## ;FIND JOB'S PDB
AOS .PDUUC##(W) ;COUNT THE UUO
LDB T2,[POINT 9,M,8];PICK UP UUO OP CODE
CAIL T2,100 ;ILLEGAL INSTRUCTION?
JRST ILLINS## ;YES, STOP JOB AND PRINT ERROR
LDB P1,PUUOAC## ;SETUP USER DEVICE CHANNEL NUMBER
HRRZ T3,USRHCU##
SKIPE F,USRJDA##(P1) ;GET ADDRESS OF DEVICE DATA BLOCK
CAMLE P1,T3
JRST NOCHAN ;CHANNEL NOT ASSIGNED
HRLM P1,.USCTA ;STORE CHANNEL NUMBER
DISP3: MOVE S,DEVIOS(F)
MOVE T4,DEVSER(F) ;SETUP IO SERVICE DISPATCH
; TABLE ADDRESS
CAIL T2,LNGUUO ;LONG DISPATCH TABLE UUO?
JRST DISP1 ;YES
DISP0: ROT T2,-1 ;DIVIDE UUO OPCODE BY 2, SAVE REMAINDER
MOVE U,UUOTAB-20(T2) ;GET DISPATCH TABLE ENTRY
MOVE T1,M ;ADR INTO T1 FOR UUOCHK
MOVE T3,CHKTAB-20(T2);GET CHECK-BITS FOR THE UUO
DISP2: JUMPL T2,DISP2A ;WAS UUO ODD?
MOVS U,U ;NO, USE LH OF DISPATCH ENTRY
MOVSS T3
DISP2A:
IFN FTMP,<
TRNN T3,UU.CP1 ;CAN UUO BE EXECUTED ON ANY CPU
PUSHJ P,ONCPU0## ;NO, GET ONTO BOOTSTRAP CPU
>
IFN FTXMON,<
TRNE M,^-17 ;ONLY IF A REAL EFFECTIVE ADDRESS
TRNN T3,UU.PCS ;DOES UUO DO ITS OWN SECTION ADJUSTMENTS?
JRST DISP4 ;YES, DON'T CHEAT IT
PUSH P,T1 ;NO, SAVE T1
LDB T1,[POINT SECWID,M,SECPOS] ;GET SECTION TO BE USED
PUSHJ P,STPCS## ;SET IT UP AS PCS
DPB T1,[POINT SECWID,.USUPF,SECPOS] ;SAVE AS UUO PCS (FOR CONTEXT SWITCHING)
POP P,T1 ;RESTORE AC CONTENTS
DISP4:
> ;END OF IFN FTXMON
TRNE T3,UU.MSK ;CHECK ARGUMENTS FOR VALIDITY?
PUSHJ P,UUOCHK## ;YES (DONT ALLOW PAGE FAULT IN UUO PROCESSING)
IFN FTXMON,<
HRLI U,(MCSEC1) ;ASSUME UUO CAN BE EXECUTED IN SECTION 1
TRNE T3,UU.SE1 ;CAN UUO BE EXECUTED IN SECTION 1?
XJRST [MCSEC1+.+1] ;YES, GET INTO SECTION 1
> ;END IFN FTXMON
MOVE T2,.USMUO ;UUO FROM SYSTEM?
TLNN T2,(XC.USR)
JRST (U) ;YES
PUSHJ P,ANYUUO## ;CALL PSISER SINCE THIS IS A FUNNY
; CONDITION
;***NOTE: THIS ROUTINE SKIPS TO ABORT THE UUO. IT MUST BE PRIOR TO THE
; PUSHJ P,(U) SO IT WILL SKIP INTO UUOXIT
;DISPATCH TO UUO ROUTINE
;THE FOLLOWING CODE IS EXECUTED ON ALL RETURN TO USER PROGRAMS
;BUT IS NEVER EXECUTED ON RETURNS FROM EXEC UUOS(SAVGET)
PUSHJ P,(U) ;NO, FROM USER. ALL
; UUO ROUTINES RETURN WITH POPJ
JRST USRXIT ;NO SKIP RETURN TO USER
USRXT1: PUSHJ P,INCPD1##
USRXIT::XJRST [0+.+1] ;DO THE REST OF THIS IN SECTION 0
IFN FTNET,<NTDBUG NO,EITHER> ;MUST NOT HAVE THE INTERLOCK. ANY LEVEL OK.
JUMPE F,UUOND1 ;NO DDB
HRRZ T1,DEVSER(F) ;GET DISPATCH TABLE ADDRESS
IFN FTNET,<
CAIN T1,NETDSP## ;IS IT A NETWORK DEVICE?
JRST [PUSHJ P,ZAPNET## ;YES, DISCONNECT IF NO LONGER NEEDED
JRST UUOND1] ;RETURN TO USER IN EITHER CASE
> ;END IFN FTNET
CAIN T1,SCNDSP## ;IS IT A TTY DDB?
PUSHJ P,TTYKLQ## ;YES, GIVE IT UP IF NOT IN USE
UUOND1: MOVSI T1,37 ;GET MASK OF IR+IND FIELDS
IORM T1,.USMUO ;OR INTO 40 SO UUO WATCHERS SEE IT
SETZM .USPFU ;CLEAR COUNT OF PAGE FAULTS IN THIS UUO
MOVE J,.CPJOB## ;CURRENT JOB NUMBER
IFN FTMP,<
PUSHJ P,UXITMP## ;CHECK IF JOB IS RUNNABLE ON THIS CPU
JRST [MOVE T1,JBTSTS##(J) ;NO, GO DO A RESCHEDULE
JRST USRXT2]
>
MOVE T1,JBTSTS##(J) ;JOB STATUS WORD
TDNN T1,[XWD STOPIO!CNTRLC,JS.DEP!JS.MPE] ;IS MONITOR TRYING TO STOP THIS
; USERS IO OR IS HE TRYING TO STOP HIS JOB
; (BY TYPING ^C WHILE HE WAS IN MONITOR)?
; OR HAD ERROR AND IS IN DAEMON ERROR PAUSE?
; OR MEM PAR ERR (WHILE IN MONITOR BUT BAD ADR
; PROVED TO BE IN USER MODE)
SKIPE .CPTMF## ;NO. HAS CLOCK TICKED WHILE IN MONITOR?
JRST USRXT2 ;YES, GO CALL SCHEDULER
CAME J,FORCEF## ;TRYING TO SWAP THIS JOB
SKIPE SCDRTF## ;NO, SHOULD WE DO A HIGH PRIORITY RESCHEDULE
;------ NOTE - 'UUODON' MUST LABEL THE PC STORED BY THIS PUSHJ
;USED FOR CONTROL C INTERCEPT TO DETECT USER STOPPED ON THIS CALL TO SCHED
USRXT2: PUSHJ P,USCHD1## ;YES, GO CALL SCHEDULER
UUODON:: ; SAVE CURRENT JOB NO (J)
;---------------- ; NOTE: USCHD1 POPS PUSHJ PC INTO JOBPC
; WHEN RESCHEDULING JOB
;HERE TO RETURN TO USER - CHECK IF USER TRAP PENDING
USRRET::
IFN FTKL10,<
MOVEI T1,JS.ABP ;EXEC MODE ADDRESS BREAK BIT
TDNE T1,JBTST2##(J) ;DID ONE OCCUR DURING THIS UUO?
PUSHJ P,EXCABK## ;YES, GO PROCESS IT
>
XCT PINOJN## ;SKIP IF CANNOT GRANT INTERRUPTS
PUSHJ P,PSIGEN## ;CAN, GIVE ANY TO THE USER
MOVE P1,JBTSTS##(J) ;STATUS WORD FOR CURRENT USER
; ON THIS CPU
TRNN P1,UTRP ;SEE IF TRAP PENDING
JRST USRXNT ;NO--PROCEED BELOW
;HERE WHEN TRAP SET UP WHILE JOB WAS DOING A UUO.
;TYPE OF TRAP IS IN .JBFDV:
; -1 IF .JBINT TRAP (E.G., ^C)
; 0,,ADDR IF START AT ADDR (E.G., .DDT)
MOVE T2,(P) ;GET RETURN PC
SKIPGE T4,.JDAT+JOBFDV## ;GET NEW PC
JRST USRXJI ;NO--GO DO .JBINT
MOVEM T2,.JDAT+JOBOPC## ;STORE INTERRUPTED PC
HRRM T4,(P) ;STORE NEW PC
JRST USRXCT ;AND GO FINISH INTERRUPT
USRXJI: MOVEI T4,0 ;CLEAR BITS
PUSHJ P,CHKINT## ;SEE IF INT BLOCK OK
JRST USRXCT ;NO--JUST CLEAR TRAP
PUSHJ P,DOINT1## ;YES--SWITCH PC
USRXCT: MOVEI P1,UTRP ;CLEAR
ANDCAB P1,JBTSTS##(J) ; TRAP FLAG
;HERE TO RESTORE USER HARDWARE STATE AND JUMP TO USER
USRXNT: PUSHJ P,ZAPEPL## ;RESET EXTENDED PDL IF ANY USED
TRNE P1,JS.NTO ;NON-BLOCKING TTY I/O?
USRXNX::PUSHJ P,TTMORE## ;YES, DO IT NOW
JRST UMPRET## ;RETURN TO COMMON FOR UUO EXIT
NOCHAN: SKIPL USRHCU## ;SAVE/SET IN PROGRESS?
CAMG P1,USRHCU## ;NO, MAKE SURE LEGAL CHANNEL
SKIPA ;DON'T ZERO F - IT POINTS TO A DDB
MOVEI F,0 ;INDICATE NO DDB
MOVSI T3,(XC.USR)
CAIE T2,70 ;YES,IS IT CLOSE OR RELEASE?
CAIN T2,71 ;CLOSE AND RELEASE ALWAYS LEGAL
; EVEN THOUGH NO DEVICE ASSIGNED
JRST NOOP ;YES, DO NO-OP FOR EXEC OR USER
TDNE T3,.USMUO ;UUO FROM USER?
;IF FROM EXEC, PROBABLY SAVGET
; WHICH SETS USRCHN NEG. IN LH
CAIGE T2,IOUUO ;YES, IS THIS AN IO UUO?
JRST DISP3 ;NO, GO DISPATCH
JRST IOIERR## ;NO, PRINT IO TO UNASSIGNED CHANNEL
; AND STOP JOB
NOOP: TDNE T3,.USMUO ;YES,IS UUO FROM USER?
JRST USRXIT ;YES, RETURN TO HIM (RESTORE ACS)
POPJ P, ;NO, RETURN TO EXEC (DO NOT RESTORE ACS)
DISP1: MOVE T1,DEVMOD(F) ;LONG DISPATCH TABLE UUO
SKIPL DEVSPL(F) ;LONG DISPATCH TABLE IF SPOOLED
TLNE T1,DVLNG ;DOES THIS DEVICE HAVE A LONG
; DISPATCH TABLE?
JRST DISP0 ;YES, DISPATCH
CAIGE T2,76 ;NO, IS UUO LOOKUP OR ENTER?
JRST USRXIT ;NO, RETURN TO USER
HRRI T1,DVIN ;YES, TEST IF DEVICE LEGAL
CAIN T2,77 ;LOOKUP?
HRRI T1,DVOUT ;NO, TEST FOR OUTPUT DEVICE (ENTER)
TLNE T1,(T1) ;IF LOOKUP, TEST FOR INPUT DEVICE (DVIN)
JRST USRXT1 ;DEVICE AND FUNCTION AGREE, SKIP RETURN
PUSHJ P,GETWD1## ;NOT AGREE, GET E+1
HRRI T1,0 ;ERROR CODE 0, FILE-NOT-FOUND SHOULD NOT MESS UP UPDATES
PUSHJ P,PUTWDU## ;PUT BACK IN E+1
JRST USRXIT ;AN NON SKIP RETURN TO USER
;TABLE OF UUO DISPATCH ADDRESSES
;IN FORMAT:
; XWD 40,41
; XWD 42,43
; .
; XWD 76,77
UUOTAB: UCALL,,UINIT ;(40,41)CALL,INIT
UUOERR##,,UUOERR## ;(42,43)FIVE UUOS FOR EACH INSTALLATION
UUOERR##,,UUOERR## ;(44,45)TO DEFINE AS THEY SEE FIT
UUOERR##,,UCALLI ;(46,47),CALLI
UOPEN,,TTYUUO## ;(50,51)OPEN, TTCALL
UUOERR##,,UUOERR## ;(52,53)
UUOERR##,,URENAM ;(54,55),RENAME
XP IOUUO,55 ;LOWEST IO UUO(RENAME)
TIN,,TOUT ;(56,57)IN,OUT
SETIOS,,USTATO ;(60,61)SETSTS,STATO
USTATS,,USTATZ ;(62,63)GETSTS,STATZ
UINBF,,UOUTBF ;(64,65)INBUF,OUTBUF
UIN,,UOUT ;(66,67)INPUT,OUTPUT
CLOSE1,,URELEA ;(70,71)CLOSE,RELEASE
XP LNGUUO,72 ;LOWEST LONG DISPATCH TABLE UUO
UMTAPE,,UDGF ;(72,73)MTAPE,GETF
UDSI,,UDSO ;(74,75)USETI,USETO
UDLK,,UDEN ;(76,77)LOOKUP,ENTER
;UUOS 42, 43, 44, 45, AND 46 ARE FOR CUSTOMERS TO DEFINE AS THEY PLEASE
;UUOS 40, 41 AND 47 THROUGH 77 ARE DEFINED BY DIGITAL
;UUOS 52,53 AND 54 ARE RESERVED FOR EXPANSION BY DIGITAL
;TABLE OF CHECK-BITS FOR UUOS
CHKTAB::UU.PCS+UU.EA+UU.CP1,,UU.CP1+3 ;CALL,INIT
0,,0 ;42,43
0,,0 ;44,45
0,,UU.CP1 ;46,CALLI
UU.PCS+UU.CP1+UU.EA+3,,UU.PCS+UU.CP1+UU.SE1+UU.EA ;OPEN,TTCALL
0,,0 ;52,53
0,,UU.PCS+UU.CP1+UU.LER ;54,RENAME
UU.PCS+UU.CP1,,UU.PCS+UU.CP1 ;IN,OUT
UU.CP1,,UU.CP1 ;SETSTS,STATO
UU.PCS+UU.CP1,,UU.CP1 ;GETSTS,STATZ
UU.CP1,,UU.CP1 ;INBUF,OUTBUF
UU.PCS+UU.CP1,,UU.PCS+UU.CP1 ;INPUT,,OUTPUT
UU.CP1,,UU.CP1 ;CLOSE,,RELEASE
UU.CP1,,UU.PCS+UU.CP1 ;MTAPE,UGETF
UU.PCS+UU.CP1,,UU.PCS+UU.CP1 ;USETI,USETO
UU.PCS+UU.CP1+UU.LER,,UU.PCS+UU.CP1+UU.LER ;LOOKUP,ENTER
SUBTTL CALL & CALLI UUO'S
; CALLING SEQUENCE
; CALL D,[SIXBIT/NAME/]
; WHERE NAME IS THE NAME OF A SYSTEM ROUTINE.
; IF NO SYSTEM ROUTINE WITH THE SPECIFIED NAME IF FOUND, THIS ROUTINE
; EXITS TO UUOERR.
;CONTENTS OF USER AC PLACED IN AC T1, M SET TO POINT TO USER AC
;J SET TO JOB NUMBER
UCALL: PUSHJ P,UCALLX ;CALCULATE CALLI INDEX
POPJ P, ;BAD ARGUMENT
JRST UCALLI ;LIKE CALLI
UCALLX::PUSHJ P,GETWDU## ;SET T1 FROM CONTENTS OF EFFECTIVE ADDRESS OF
; UUO FROM EITHER HIGH OR LOW SEG
; DO NOT RETURN IF ERROR
; SET J TO CURRENT JOB NO.
MOVNI T2,UCLLEN+CCLLEN ;LENGTH OF TABLE
CAME T1,CCLTAB+UCLLEN+CCLLEN(T2) ;SEARCH SYSTEM ROUTINE NAME TABLE
AOJL T2,.-1
HRRI T2,UCLLEN(T2)
JUMPGE T2,CPOPJ## ;IF NOT FOUND, NO. OF UUO
HRRM T2,M ;STORE INDEX IN UUO, JUST AS IF USER HAD DONE CALLI UUO
JRST CPOPJ1## ;GOOD RETURN
;CALL UUO FALLS IN HERE
;CALLI UUO - CALL IMMEDIATE
;CALLI D,E
;WHERE E IS RELATIVE INDEX IN CALL TABLE
UCALLI::MOVE T1,T2 ;SAVE USER/EXEC BIT
HRRE T2,M ;GET CALLI NUMBER(POS.=DIGITAL,NEG.=CUSTOMER DEFINED)
JUMPL T2,UCALL1 ;IF ARGUMENT IS POSITIVE,
TRZE T2,UPHNLY ;IS BIT 19=1?
HRLI P1,PHONLY ;YES, PHYSICAL DEVICES ONLY
JRST UCALL2
UCALL1: TRON T2,UPHNLY ;ARGUMENT NEG, IS BIT 19=0?
HRLI P1,PHONLY ;YES, PHYSICAL ONLY
UCALL2: CAML T2,MCCLEN ;MORE NEGATIVE THAN MOST NEGATIVE CUSTOMER DEFINED UUO?
CAIL T2,UCILEN ;MORE POSITIVE THAN HIGHEST DIGITAL DEFINED CALLI?
POPJ P, ;YES, RETURN TO USER TREAT AS NO-OP SO
; PROGRAMS AHEAD OF MONITOR WILL STILL
; RUN WITHOUT ERROR MESSAGE
TLNE T1,(XC.USR) ;NO, UUO WAS FROM MONITOR?
POP P,(P) ;NO, REMOVE RETURN
HRR M,P1 ;UUO AC FIELD
PUSHJ P,GTWST2## ;PICK UP CONTENTS OF USER AC
ROT T2,-1 ;DIVIDE BY 2 AND SAVE REMAINDER
MOVE U,UCLJMP(T2) ;GET DISPATCH TABLE ENTRY
MOVE T3,CHKTBC(T2) ;GET CHECK-BITS
JRST DISP2 ;AND GO DISPATCH
;CALL UUO DISPATCH TABLE
;NEW UUOS MUST BE ADDED AT END SINCE CALLI DEPENDS ON POSITION IN TABLE.
;CUSTOMERS SHOULD ADD UUOS IN CNAMES MACRO SO CALLI ADDRESS WILL BE NEGATIVE.
;IN THIS WAY BOTH DIGITAL AND ITS CUSTOMERS CAN ADD UUOS WITHOUT CONFLICT,
;DIGITAL GOING POSITIVE, CUSTOMERS GOING NEGATIVE.
DEFINE CNAMES <
XLIST
IFN FTPATT,<
X CPOPJ,CPOPJ##,UU.CP1 ;(-3) PLACE FOR CUSTOMERS TO PATCH UUOS
X CPOPJ,CPOPJ##,UU.CP1 ;(-2) PLACE FOR CUSTOMERS TO PATCH UUOS
> ;END IFN FTPATT
X LIGHTS,LIGHTS,UU.CP1 ;(-1) SET LIGHTS ON CONSOLE
> ;END DEFINE CNAMES
DEFINE NAMES,<
X RESET,RESET,UU.CP1 ;(000) RESET IO
X DDTIN,DDTIN##,UU.CP1+UU.SE1+UU.EA+25 ;(001)READ DDT CHARACTER
X SETDDT,SETDDT,UU.CP1 ;(002) SET DDT ADDRESS IN JOB DATA AREA
X DDTOUT,DDTOUT##,UU.CP1+UU.SE1+UU.EA+25 ;(003) SEND DDT CHARACTER
X DEVCHR,UDVCHR,UU.CP1 ;(004) READ DEVICE CHARACTERISTICS
X DDTGT,CPOPJ##,UU.CP1 ;(005) GET DDT MODE
X GETCHR,UDVCHR,UU.CP1 ;(006) READ DEVICE CHARACTERISTICS
X DDTRL,CPOPJ##,UU.CP1 ;(007) RELEASE DDT MODE
X WAIT,WAIT,UU.CP1 ;(010) WAIT FOR I/O TO STOP
X CORE,CORUUO##,UU.CP1 ;(011) CHANGE CORE ALLOCATIONS
X EXIT,EXIT,UU.CP1 ;(012) CAUSE PROGRAM TO EXIT
X UTPCLR,UTPCLR,UU.CP1 ;(013) CLEAR DECTAPE DIRECTORY
X DATE,UDATE,UU.CP1 ;(014) READ DATE IN DECSYSTEM-10 FORMAT
X LOGIN,ULOGIN,UU.MEA+UU.CP1 ;(015) LOGIN JOB
X APRENB,APRENB,UU.CP1 ;(016) ENABLE APR TRAPPING
X LOGOUT,LOGOUT,UU.CP1 ;(017) TERMINATE JOB
X SWITCH,SWITCH,UU.CP1 ;(020) RETURN CONSOLE DATA SWITCHES
X REASSI,REASSI##,UU.CP1 ;(021) REASSIGN DEVICE TO ANOTHER JOB
X TIMER,TIMER,UU.CP1 ;(022) READ TIME OF DAY (JIFFIES)
X MSTIME,MSTIME,UU.CP1 ;(023) READ TIME OF DAY (MILLISECONDS)
;CONTINUED ON NEXT PAGE
X GETPPN,GETPPN,UU.CP1 ;(024) RETURN PROJECT-PROGRAMMER NUMBER
X TRPSET,TRPSET,UU.LEA+UU.CP1 ;(025) SET PI TRAP LOC, AND USER I/O
X TRPJEN,UUOERR##,UU.CP1 ;(026) DISMISS INTERRUPT TO EXEC MODE
X RUNTIM,JOBTIM,UU.CP1 ;(027) RETURN TOTAL JOB RUNNING TIME
X PJOB,JOBNO,UU.CP1 ;(030) RETURN JOB NUMBER
X SLEEP,SLEEP,UU.CP1 ;(031) SLEEP FOR N SECONDS
X SETPOV,SETPOV,UU.CP1 ;(032) SET PUSH DOWN OVERFLOW TRAP
X PEEK,UPEEK,UU.CP1 ;(033) READ A WORD OF MONITOR CORE
X GETLIN,GETLN,UU.CP1 ;(034) READ CONTROLLING JOB'S TTY NAME
X RUN,URUN##,UU.EA+6+UU.CP1 ;(035) RUN PROGRAM FROM DEV:FILE[PATH]
X SETUWP,SETUWP,UU.CP1 ;(036) SET/CLEAR USER WRITE PROTECT
X REMAP,REMAP,UU.CP1 ;(037) REMAP TOP OF LOW SEG TO HIGH SEG
X GETSEG,UGTSEG##,UU.EA+6+UU.CP1 ;(040) GET SHARABLE HIGH SEG
X GETTAB,GETTAB,UU.CP1 ;(041) GET EXEC ADDRESS OF A JOB TABLE
X SPY,USPY##,UU.CP1 ;(042) MAP MONITOR'S LOW SEG
X SETNAM,SETNAM,UU.CP1 ;(043) SETNAME OF THIS PROGRAM
;LAST CALLI IN 4.50
X TMPCOR,TMPUUO##,UU.EA+UU.CP1+2 ;(044) TEMPORARY FILE STORAGE UUO (CCL)
X DSKCHR,DSKCHR##,UU.CP1+UU.LEA ;(045) RETURN DISK CHARACTERISTICS
;LAST CALLI IN 4.72
X SYSSTR,SYSTUU##,UU.CP1 ;(046) RETURN NEXT STRUCTURE IN SYSTEM
X JOBSTR,JOBSTR##,UU.LEA+UU.CP1 ;(047) RETURN NEXT STRUCTURE IN JOB S/L
X STRUUO,STRUUO##,UU.CP1+UU.LEA ;(050) PERFORM STRUCTURE FUNCTIONS
X SYSPHY,SYSPHY##,UU.CP1 ;(051) RETURN PHYSICAL DISK UNITS
X FRECHN,CPOPJ##,UU.CP1 ;(052) RETURN FIRST FREE I/O CHANNEL
X DEVTYP,UDVTYP,UU.CP1 ;(053) EXTENDED DEVICE CHARACTERISTICS
;CONTINUED ON NEXT PAGE
X DEVSTS,DEVST,UU.CP1 ;(054) DEVSTS
X DEVPPN,DEVPPU,UU.CP1 ;(055) RETURN PPN FOR DEVICE
X SEEK,CPOPJ##,UU.CP1 ;(056) SEEK
;LAST CALLI IN 5.01
X RTTRP,RTTRP##,UU.CP1+UU.EA+4 ;(057) REAL TIME TRAP
X LOCK,LOKJOB## ;(060) LOCK JOB IN CORE
X JOBSTS,UJBSTS##,UU.CP1+UU.SE1 ;(061) READ STATUS OF JOB AND ITS PTY
X LOCATE,ULOCAT,UU.CP1+UU.SE1 ;(062) SET STATION FOR SPOOLING
X WHERE,UWHERE,UU.SE1 ;(063) READ STATION FOR DEVICE
X DEVNAM,UDVNAM,UU.CP1 ;(064) GET PHYSICAL DEVICE NAME
X CTLJOB,CTLJOB##,UU.CP1 ;(065) FIND CONTROLLER OF THIS JOB
X GOBSTR,GOBSTR##,UU.CP1+UU.LEA ;(066) GENERALIZED JOBSTR
;LAST CALLI IN 5.02
X FOO,CPOPJ##,UU.CP1 ;(067) FOO
X FOO,CPOPJ##,UU.CP1 ;(070) FOO
X HPQ,HPQ##,UU.CP1 ;(071) SET HIGH PRIORITY QUEUE
X HIBER,HIBUUO,UU.CP1 ;(072) SLEEP UNTIL INTERRUPT
X WAKE,WAKUUO,UU.CP1 ;(073) WAKE UUO
X CHGPPN,CHGPPN,UU.CP1 ;(074) CHANGE PPN
X SETUUO,SETUUO##,UU.CP1 ;(075) SET SYSTEM/JOB PARAMETERS
X DEVGEN,DEVGEN,UU.CP1 ;(076) DEVICE GENERIC NUMBER UUO
X OTHUSR,GETPPL,UU.CP1 ;(077) CHECK FOR OTHER JOBS SAME PPN
X CHKACC,ACCCHK##,UU.CP1+UU.EA+3 ;(100) ACCESS ALLOWED UUO
X DEVSIZ,DVSIZ,UU.CP1 ;(101) RETURN BUFFER SIZE
X DAEMON,CALDAE,UU.CP1+UU.LEA ;(102) CALL DAEMON
X JOBPEK,JOBPEK,UU.CP1+UU.EA+2 ;(103) READ/WRITE ANOTHER JOB'S CORE
X ATTACH,UATTAC,UU.CP1+UU.SE1 ;(104) ATTACH OR DETACH JOBS
X DAEFIN,DAEFIN,UU.LEA+UU.CP1 ;(105) DAEMON FINISHED
X FRCUUO,FRCUUO,UU.LEA+UU.CP1 ;(106) FORCE COMMAND FOR JOB
X DEVLNM,DEVLNM,UU.CP1 ;(107) SET DEVICE LOGICAL NAME
;LAST CALLI IN 5.03
;CONTINUED ON NEXT PAGE
X PATH.,PTHUUO##,UU.CP1+UU.LEA ;(110) TEST/SET FULL PATHS TO FILES
X METER.,CPOPJ## ;(111) PERFORMANCE METERING (OBSOLETE)
X MTCHR.,MTACHR##,UU.CP1 ;(112) GET MAGTAPE CHARACTERISTICS
X JBSET.,UJBSET##,UU.EA+2+UU.CP1 ;(113) JOB SETUUO
X POKE.,POKE,UU.CP1+UU.EA+3 ;(114) CHANGE MONITOR
X TRMNO.,TRMNO##,UU.CP1+UU.SE1 ;(115) TERMINAL NUMBER FOR JOB
X TRMOP.,TRMOP##,UU.LEA+UU.CP1+UU.SE1 ;(116) TERMINAL OPERATIONS UUO
X RESDV.,RESDV,UU.CP1 ;(117) RESET DEVICE OR CHANNEL
X UNLOK.,UUNLOK##,UU.CP1+UU.SE1 ;(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 OPR 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) PDP11 COMMUNICATIONS
X MTAID.,MTARID##,UU.CP1 ;(126) SET MAGTAPE REELID
X IONDX.,UIONDX,UU.CP1 ;(127) RETURN IO INDEX
X CNECT.,CONECT##,UU.CP1+UU.EA+1 ;(130) CONNECT A DEVICE TO MPX CHANNEL
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 PI SYSTEM
X PISYS.,PISYS##,UU.CP1 ;(136) MANIPULATE PI SYSTEM
X DEBRK.,DEBRK##,UU.CP1 ;(137) DISMISS A SOFTWARE INTERRUPT
X PISAV.,PISAVE##,UU.CP1+UU.LEA ;(140) SAVE THE PI SYSTEM
X PIRST.,PIRST##,UU.CP1+UU.EA+UU.CEA ;(141) RESTORE THE PI SYSTEM
X IPCFR.,UIPCFR##,UU.CP1+UU.SE1 ;(142) IPCF READ
X IPCFS.,UIPCFS##,UU.CP1+UU.SE1 ;(143) IPCF SEND
X IPCFQ.,UIPCFQ##,UU.CP1+UU.SE1 ;(144) IPCF QUERY
X PAGE.,UPAGE.##,UU.CP1 ;(145) PAGING UUOS
X SUSET.,USUSET##,UU.CP1 ;(146) SUPER USETI/O
X COMPT.,CPOPJ##,UU.CP1 ;(147) CALL TO COMPATABILITY PACKAGES
;LAST CALLI IN 5.07/6.01
X SCHED.,SCHED.##,UU.CP1 ;(150) SET/READ SCHEDULER PARAMETERS
X ENQ.,UENQ##,UU.CP1 ;(151) ENQUEUE
X DEQ.,UDEQ##,UU.CP1 ;(152) DEQUEUE
X ENQC.,UENQC##,UU.CP1 ;(153) ENQ CONTROLLER
;CONTINUED ON NEXT PAGE
X TAPOP.,UTAPOP##,UU.LEA+UU.CP1 ;(154) PERFORM MAGTAPE FUNCTIONS
X FILOP.,FILOP,UU.CP1+UU.LEA ;(155) PERFORM FILE OPERATIONS
X CAL78.,CALL78##,UU.CP1 ;(156) DAS78 COMMINUCATIONS
X NODE.,NODE.U##,UU.CP1+UU.SE1 ;(157) ANF-10 NETWORK FUNCTIONS
X ERRPT.,UERRPT##,UU.CP1 ;(160) ERROR REPORTING UUO FOR DAEMON
X ALLOC.,CPOPJ##,UU.CP1 ;(161) OBSOLETE
X PERF.,UPERF.,UU.CP1 ;(162) PERFORMANCE ANALYSIS UUO
;LAST UUO IN 6.02
X DIAG.,DIAUUO,UU.CP1+UU.SE1 ;(163) DIAGNOSTIC UUO
X DVPHY.,UDVPHY,UU.CP1 ;(164) RETURN DEVICE NAMES
X GTNTN.,GTNTN,UU.CP1+UU.SE1 ;(165) GET THE NETWORK TTY NUMBER
X GTXTN.,GTXTN,UU.CP1+UU.SE1 ;(166) GET THE -10 TTY NAME
X ACCT.,ACCT,UU.CP1 ;(167) ACCOUNTING UUO
X DTE.,UDTE##,UU.CP1 ;(170) MANIPULATE DTE DEVICES
X DEVOP.,UDEVOP,UU.CP1+UU.LEA ;(171) PERFORM DEVICE FUNCTIONS
X SPPRM.,SPPRM,UU.CP1+UU.LEA ;(172) SET SPOOLING PARAMETERS
;LAST UUO IN 6.03
X MERGE.,UMERGE##,UU.CP1+UU.EA+6 ;(173) MERGE .EXE FILE INTO CORE IMAGE
X UTRP.,UUTRP,UU.CP1+UU.LER ;(174) SET USER TRAPPING
X PIJBI.,PIJOB##,UU.CP1 ;(175) GENERATE CROSS JOB PI INTERRUPTS
X SNOOP.,SNOOP,UU.CP1 ;(176) SNOOP. UUO
X TSK.,UTSK##,UU.CP1 ;(177) ANF-10 TASK COMMUNICATIONS
X KDP.,UKDP##,UU.CP1 ;(200) MANIPULATE KDP DEVICES
;LAST UUO IN 7.00
X QUEUE.,GLXINF##,UU.CP1+UU.SE1 ;(201) COMMUNICATE WITH SYSTEM PIDS
X RECON.,RECON,UU.CP1+UU.SE1 ;(202) PERFORM SYSTEM RECONFIGURATION
;LAST UUO IN 7.01
X PITMR.,PITMR##,UU.CP1 ;(203) SET PI TIMER
X ACCLG.,ACCLOG,UU.CP1 ;(204) LOGIN INTERLOCK
X NSP.,SCUUUO##,UU.CP1+UU.SE1 ;(205) DECNET I/O
X NTMAN.,NTMAN##,UU.CP1+UU.SE1 ;(206) DECNET NETWORK MANAGEMENT
X DNET.,DNET##,UU.CP1+UU.SE1 ;(207) DECNET INFORMATION
X SAVE.,USAVE##,UU.CP1+UU.EA+6 ;(210) SAVE CORE IMAGE ON DISK
X CMAND.,CMAND,UU.CP1 ;(211) USER DEFINABLE COMMANDS
X PIBLK.,PIBLK##,UU.CP1 ;(212) READ PI INTERRUPT BLOCK
X SCS.,SCS##,UU.CP1+UU.SE1 ;(213) SCS. UUO
X SEBLK.,USEBLK##,UU.CP1 ;(214) READ SYSTEM ERROR BLOCK (DAEMON)
;LAST UUO IN 7.02
X CTX.,CTXUUO##,UU.CP1!UU.SE1 ;(215) MANIPULATE JOB CONTEXTS
X PIFLG.,PIFLG##,UU.CP1 ;(216) SET/READ PI FLAGS
X IPCFM.,UIPCFM##,UU.SE1 ;(217) IPCF MULTI-PURPOSE UTILITY
X LLMOP.,ULLMOP##,UU.CP1+UU.SE1 ;(220) PERFORM ETHERNET DIAGNOSTICS
X LATOP.,.LATOP##,UU.SE1 ;(221) PERFORM LAT FUNCTIONS
X KNIBT.,UKNIBT##,UU.CP1!UU.SE1 ;(222) PERFORM KLNI BOOT FUNCTIONS
X CHTRN.,UCHTRN##,UU.CP1 ;(223) CHARACTER TRANSLATION
X ETHNT.,UETHNT##,UU.CP1!UU.SE1 ;(224) ETHERNET I/O
X ENTVC.,ENTVC,UU.CP1!UU.SE1 ;(225) MANIPULATE PROGRAM ENTRY VECTORS
X NETOP.,NETOP,UU.CP1!UU.SE1 ;(226) MULTI-PURPOSE NETWORK FUNCTIONS
;LAST UUO IN 7.03
X DDP.,DDPUUO##,UU.CP1 ;(227) MANIPULATE DDP DEVICES
X SEGOP.,SEGOP##,UU.CP1 ;(230) MANIPULATE HIGH SEGMENTS
;***ADD NEW CALLI'S ABOVE THIS LINE *****
IFN FTPATT,<
X CPOPJ,CPOPJ##,UU.CP1 ;2 SPARE UUO'S FOR PATCHING - DIGITAL ONLY
X CPOPJ,CPOPJ##,UU.CP1 ;ALWAYS ADD NEW UUO'S ABOVE THESE
>
;CUSTOMERS SHOULD ADD UUO'S ABOVE
;IN CNAMES MACRO RATHER THAN NAMES MACRO
; SO THAT THEIR CALLI INDICES WILL
; BE NEGATIVE
LIST
SALL
>
;GENERATE SIXBIT TABLE OF UUO NAMES
DEFINE X (A,B,C) <
<EXP SIXBIT /A/>
>
;GENERATE CUSTOMER CALL/CALLI UUO'S
MCCLEN::EXP -CCLLEN
CCLTAB: CNAMES
CCLLEN==.-CCLTAB ;LENGTH OF CUSTOMER DEFINED CALL/CALLI UUO'S
;(MINIMUM CALLI NUMBER, TOO)
;GENERATE DIGITAL UUO'S
DEFINE X (A,B,C) <
IFL .-UCLTAB-MAXCAL,<EXP SIXBIT /A/>
>
UCLTAB: NAMES
XP UCLLEN,.-UCLTAB ;DEFINE LENGTH OF DIGITAL UUO TABLE
DEFINE X (A,B,C)
< ZZ==ZZ+1
DEFINE XX (D) ;DEFINE XX IN CASE ODD NUMBER OF CUSTOMER UUO'S
< XWD CPOPJ##,D
>>
ZZ==0
;COUNT NUMBER OF CUSTOMER DEFINED UUO'S
CNAMES
;GENERATE HALF WORD UUO DISPATCH TABLE
DEFINE X (A,B,C)
< IFE ZZ&1,
< DEFINE XX (D)
<
XWD B,D
>>
IFN ZZ&1,
<
XX B
>
ZZ==ZZ+1
>
;GENERATE CUSTOMER TABLE
CUSTAB: CNAMES
ZZ==0
;GENERATE DIGITAL TABLE
UCLJMP: NAMES
IFN ZZ&1,<XX CPOPJ##> ;GEN. LAST WORD IF ODD NUMBER OF UUOS
UCILEN==:<.-UCLJMP>*2 ;MAX DIGITAL CALLI INDEX
DEFINE X(A,B,C)
< ZZ==ZZ+1
>
DEFINE XX(D) ;DEFINE XX IN CASE ODD NO. OF CUST. CALLI'S
< XWD 0,D
>
ZZ==0
;COUNT NUMBER OF CUSTOMER CALLI'S
CNAMES
DEFINE X (A,B,C)
<IFE ZZ&1,
<DEFINE XX (D)
<
XWD C,D
>>
IFN ZZ&1,
<
XX C
>
ZZ==ZZ+1
>
CNAMES
ZZ==0
CHKTBC::NAMES
IFN ZZ&1,< XX 0>
SUBTTL EXIT & SETPOV UUO'S
;EXIT UUO ROUTINE
;CALL: CALL FIELD, [SIXBIT/EXIT/]
;IF FIELD - 0, PRINT EXIT ^C. CONT WILL NOT WORK
EXIT: MOVSI T1,JLOG
TDNN T1,JBTSTS##(J) ;IS THIS JOB LOGGED IN?
JRST LOGOUT ;NO, GO DESTROY JOB
JUMPN P1,MONRET ;AC FIELD NON-ZERO?
PUSHJ P,IORELS ;NO, RELEASE ALL DEVICES
PUSHJ P,RESET ;AFTER CLOSING OUT FILES, RELEASE RT DEV
;UNLOCK JOB, RESET APR
MOVSI T1,(JS.SAC) ;BIT TO TEST
TDNE T1,JBTST2##(J) ;DOING AN AUTO-RESTORE ON PROGRAM EXIT?
JRST MONRET ;YES, DON'T TYPE EXTRA JUNK
PUSHJ P,TTYFUW## ;FIND TTY FOR CURRENT JOB
; SET J TO JOB NO.,U TO LDB ADDRESS
; F TO TTY DDB
JSP T1,PHOLD## ;MOVE "EXIT" TO OUTPUT BUFFER
; AND STOP JOB, AND START TTY, CONT WILL NOT WORK
ASCIZ /
EXIT/
; CALL 1,[SIXBIT/EXIT/] - RETURN TTY TO MONITOR MODE,
; STOP JOB, BUT DO NOT RELEASE DEVICES
;TYPE . WITH NO CRLF, ALLOW CONT COMMAND TO RETURN AFTER UUO
MONRET::MOVSI T1,(JS.SAC) ;BIT TO TEST
TDNE T1,JBTST2##(J) ;DOING AN AUTO-RESTORE ON PROGRAM EXIT?
JRST [PUSHJ P,TTYFNU## ;FIND TTY
MOVSI T1,(UP.DST) ;GET HNGSTP BIT
IORM T1,.USBTS ;LIGHT IT FOR STOP1C PROCESSING
JUMPE U,MONRE1 ;DON'T TOUCH LDB IF DETACHED
MOVSI T1,LDLCOM## ;COMMAND MODE BIT
SE1XCT <ANDCAM T1,LDBDCH##(U)> ;CLEAR IT (STOP COMCON)
JRST MONRE1] ;DON'T TYPE OUT OR ALLOW COMMANDS
PUSHJ P,TTYFUW## ;WAIT FOR A TTY TO TYPE ON
PUSHJ P,PRRSP3## ;NO--PRINT [XXX], CRLF, DOT
PUSHJ P,TTYSTC## ;PUT TTY INTO COMMAND MODE
MONRE1: PUSHJ P,STOP1C## ;START TTY IN MONITOR MODE AND STOP JOB, BUT ALLOW
; CONTINUE TO WORK (RETURN CONTROL AFTER EXIT UUO)
JRST USCHED## ;CALL SCHEDULER WHICH WILL SET CURRENT JOB
; WITH RUN BIT OFF AND WILL STOP JOB
;SETPOV - SET PUSH DOWN OVERFLOW TRAP
;CALL MOVE AC,ADR. OF TRAP ON PD OVF
; CALL AC,[SIXBIT /SETPOV/]
SETPOV: MOVEM T1,.JDAT+JOBAPR##
MOVEI T1,AP.POV
JRST APRENB ;SET TRAP LOC.
SUBTTL RESET & APRENB UUO'S
RESET::
IFN FTKL10,<
PUSHJ P,GIVPMR##
PUSHJ P,FEDRST## ;RELEASE FRONT END DEVICE
>;END IFN FTKL10
PUSHJ P,SNPRST ;REMOVE BREAK POINTS
IFN FTHPQ,< ;HIGH PRIORITY QUEUE FEATURE?
LDB T2,HPQSPT## ;CONSOLE COMMAND HPQ SETTING
>
HRLOI T1,HPQMSK## ;MASK OUT LH BITS LEAVE RH SAME
; (REAL TIME DEVICE COUNT)
ANDM T1,JBTRTD##(J) ;CLEAR ALL BUT CONSOLE COMMAND HPQ
IFN FTHPQ,< ;HIGH PRIORITY QUEUE
DPB T2,HPQPNT## ;RESTORE CONSOLE COMMAND AS OPERATING QUEUE
> ;END FTHPQ
IFN FTNET,<
;THIS CALL MUST PRECEED THE CALL TO UNLOCK BELOW
PUSHJ P,NETCTC## ;ALSO CALL NETSER ON CONTROL ^C
>;END FTNET
IFN FTSCA,<
PUSHJ P,SCSRST## ;CALL SCSUUO ON RESET
>; END IFN FTSCA
IFN FTENET,<
PUSHJ P,ENTRST## ;CALL ETHUUO ABOUT RESET
PUSHJ P,LATRST## ;CALL LATSER ABOUT RESET
IFN FTKL10,<
PUSHJ P,KNIRST## ;CALL KNISER ABOUT RESET
>; END IFN FTKL10
>; END IFN FTENET
IFN FTDECNET,<
SNCALL (SCURST##,MS.HGH) ;RESET DECNET-10
>
IFN FTLOCK,<
PUSHJ P,UNLOCK## ;TURN OFF NSHF AND NSWP AND RETURN CORE
JFCL
>
PUSHJ P,CLRLPG## ;CLEAR ALL LOCKED PAGES
MOVEI T1,[CAMN J,.CPSTS##-.CPCDB##(P1) ;MAKE SURE SCHEDULING ALLOWED
SETZM .CPSTS##-.CPCDB##(P1)
POPJ P,]
; IN CASE THIS FOLLOWS A TRPSET UUO
;(IF STOPTS IS NON-ZERO, THIS MUST BE
; THE JOB THAT STOPPED TIME SHARING)
PUSHJ P,CPUAPP## ;ZERO .CPSTS FOR ALL CPU'S
IFN FTMP,<
PUSHJ P,CRESET## ;RESET UUO SET CPU SPECIFICATION
>
PUSHJ P,HRESET## ;FLAG USER AS HAVING UWP ON FOR HIGH SEG
; AND DO DATAO TO SET UWP ON
PUSHJ P,FNDPDS## ;FIND THE JOB PDB
HRRZ T2,.PDSCX##(W) ;ADDRESS OF JOB'S SAVED CONTEXT
MOVEI T1,NWSCTX ;NUMBER OF WORDS OF SAVED CONTEXT
SKIPE T2 ;HAS THE JOB'S CONTEXT BEEN SAVED?
PUSHJ P,GIVWDS## ;YES, RETURN SPACE TO MONITOR FREE CORE
HLLZS .PDSCX##(W) ;INDICATE NO SAVED CONTEXT
HRRZS .PDLBS##(W) ;CLEAR LARGE DISK BUFFERS IF SET BY UUO
PUSHJ P,CLRBRK## ;CLEAR ADDRESS BREAK IF SET BY UUO
PUSHJ P,CLRPSI## ;RESET SOFTWARE INTERRUPT STATUS
PUSHJ P,ENQRST## ;CLEAR ALL LOCKS
PUSHJ P,IPCFRC## ;SIGNAL RESET TO SYS:INFO
MOVEI T1,RELEA1 ;RELEASE ALL DEVICES
PUSHJ P,IOALL ; WITHOUT WAITING
PUSHJ P,TTYRES## ;NORMALIZE CONTROLLING TTY, IF ANY
MOVEI T1,HIGHXC##-20 ;NUMBER OF EXTENDED CHANNELS
HRRZ T2,.USCTA
SKIPE T2 ;STILL HAVE FUNNY SPACE?
PUSHJ P,GVFWDS## ;GIVE IT BACK
HLLZS .USCTA
HLLZS JBTDDB##(J) ;NOT IN IOWAIT NOW (FOR ^T'ERS)
PUSHJ P,SETUSR ;CLEAR USERS JOB DATA AREA
IFN FTMDA,<
PUSHJ P,MDARST ;CHECK ANY STRUCTURE LOCKS
> ;END FTMDA
PUSHJ P,FNDPDS## ;FIND THE JOB PDB
PUSH P,P2 ;SAVE AWAY P2
SKIPE P2,.PDTSL##(W) ;JOB HAVE A TEMPORARY SEARCH LIST?
PUSHJ P,SLGVT## ;YES, GIVE IT BACK
POP P,P2 ;RESTORE P2
MOVSI T1,777777-USRMOD ;CLEAR ALL UUO PC FLAGS IN LH, EXCEPT USER MODE
ANDCAM T1,.JDAT+JOBPD1## ;LEAVE USER MODE OFF TOO, IF EXEC DOING CALL RESET
; FALL INTO APRENB WITH RH T1=0
; SO THAT ALL APR INTERRUPTS WILL BE DISABLED
;ROUTINE TO SET UP APR FOR USER TRAPPING
;CALL: CALL AC,[SIXBIT /APRENB/]
;WITH FOLLOWING APR CONSO FLAG BITS
;TO INDICATE WHICH APR CONDITIONS SHOULD
;TRAP TO USER WHEN TRAP OCCURS FROM USER MODE
;1B18 ;DO NOT DISABLE SELECTED CONDITIONS (EXCEPT CLOCK) SEE APRINT
;1B19 ;PUSHDOWN OVERFLOW
;1B22 ;ILLEGAL MEMORY
;1B23 ;NON-EXISTENT MEMORY
;1B26 ;CLOCK
;1B29 ;FLOATING POINT OVERFLOW
;1B32 ;ARITH. OVERFLOW
APRENB::HRRM T1,.JDAT+JOBENB## ;SET RH TO CONSO BITS IN JOB DATA AREA
; USED EVERY TIME IS STARTED UP
; JRST SETAPR## ;GO ENABLE/DISABLE APR FOR FOV AND HR OV
; ALSO SET APR CONSO INSTR. FOR PROPER FLAGS
; AND RETURN TO USER
;ROUTINE TO ENABLE/DISABLE APR FOR TRAPPING TO USER AND EXEC
;CALL: MOVEI T1, APR CONSO FLAGS FOR USER TRAPPING
; PUSHJ P,SETAPR
; RETURN WITH APR RESET AND INTERRUPT LOCATION CONSO'S SET
SETAPR::
SETAP1::PUSHJ P,SETRP ;SETUP THE TRAP LOCATIONS (PAGE FAULT,
; ARITHMETIC, PDL OVF)
; PJRST SETCNA ;SET USER ENABLES FOR NXM AND CLOCK AND
; SET THE APR PIA AND EXIT
;SUBROUTINE TO SETUP USER'S APR CONSO MASK AND THE APR PIA
;CALLING SEQUENCE:
; MOVE T1,USER'S APR ENABLE BITS
; PUSHJ P,SETCNA
; ALWAYS RETURN HERE
SETCNA::HRL T1,T1 ;COPY ENABLE BITS TO LEFT HALF
TLZ T1,-1-XP.CLK-UE.PEF-UE.NXM ;CLEAR ALL BUT CLOCK, NXM, & PARITY
HRR T1,.CPEEB## ;SET MONITOR ENABLE BITS
CONO PI,PI.OFF ;DISALLOW INTERRUPTS WHILE CHANGING APR BITS
HLRM T1,.CPCN1## ;USER'S ENABLE BITS
HRRM T1,.CPCON## ;MONITOR'S ENABLE BITS
CONO APR,IP.ECI+APRCHN## ;SET CLOCK ENABLE AND APR PIA
CONO PI,PI.ON ;RESTORE PI
POPJ P, ;RETURN
;ROUTINE TO SETUP USER TRAP LOCATIONS AS SPECIFIED BY USER ENABLE BITS
; PAGE FAULT (ILL. MEM. REF.), ARITHMETIC (INTEGER OVERFLOW, FLOATING
; POINT OVERFLOW OR UNDERFLOW, AND DIVIDE CHECK), PUSH DOWN LIST OVERFLOW
; TRAP 3 IS ALWAYS IGNORED IN USER MODE.
;CALLING SEQUENCE:
; MOVE T1,USER ENABLE BITS
; PUSHJ P,SETRP
; ALWAYS RETURN HERE
;T1 IS PRESERVED.
SETRP: TRNE T1,AP.AOV+AP.FOV;IS HE?
TDZA T2,T2 ;YES, SET TO FIELD TRAPS
MOVSI T2,(JFCL) ;IGNORE ARITHMETIC TRAPS IF USER NOT ENABLED
HRRI T2,UE.AOT ;SET DISPATCH ADDRESS
MOVEM T2,.USAOT ;STORE IN UPT
MOVEI T2,UP.PDT ;IF USER NOT ENABLED FOR POV HANDLE LIKE EXEC POV
TRNE T1,AP.POV ;IS HE ENABLED?
MOVEI T2,UE.PDT ;YES, HANDLE DIFFERENTLY
MOVEM T2,.USPDT ;YES, SET FOR SEPDLO OR SUPDLO TO HANDLE PDL OV
PJRST APPSI## ;SETUP TRAP LOCATIONS FOR ANY INTERRUPTS THE
; USER IS ENABLED FOR
;HERE WHENEVER ANY JOB DOES A RESET
;CALL WITH J=JOB
IFN FTMDA,<
MDARST: PUSHJ P,FNDPDS##
MOVE T1,DATE## ;GET NOW
MOVEM T1,.PDSTM##(W) ;MARK LAST RESET TIME
MOVSI T1,(JS.OLS) ;GET OWNS LOCKED STR BIT
TDNN T1,JBTST2##(J) ;OWN ANY AT ALL?
POPJ P, ;NO, ALL DONE
ANDCAM T1,JBTST2##(J) ;YES, NOTED
;SAVE PDB
PUSHJ P,SNDMDR## ;INFORM MDA
POPJ P, ;IGNORE ERROR
POPJ P,
> ;END FTMDA
SUBTTL UTRP. UUO - SET TRAP LOCATIONS
;UUO ALLOWS A PROGRAM TO PLACE AN INSTRUCTION (ADDRESS OF LUUO BLOCK) IN TRAP
; LOCATIONS. MAKES OVERFLOW, UNDERFLOW TRAPPING FAST, LUUOS IN NON-ZERO SECTIONS
; POSSIBLE.
;CALLING SEQUENCE:
; MOVE AC,[FUNCTION,,ADDRESS]
; UTRP. AC,
; ERROR RETURN
; NORMAL RETURN
UTADC%==1 ;ADDRESS CHECK
UTUNF%==2 ;UNKNOWN FUNCTION
UTBTN%==3 ;BAD TRAP NUMBER
UTIUT%==4 ;ILLEGAL USER TRAP INSTR
ERCODE UTEADC,UTADC%
ERCODE UTEUNF,UTUNF%
ERCODE UTEBTN,UTBTN%
ERCODE UTEIUT,UTIUT%
UUTRP: HLRZ U,T1 ;GET FUNCTION
CAILE U,NUTRPF ;LEGAL FUNCTION?
JRST UTEUNF ;NO
HRR M,T1 ;ADDRESS OF ARGUMENT LIST
PUSHJ P,GETWRD## ;GET ARGUMENT COUNT
JRST UTEADC ;ADDRESS CHECK
PUSHJ P,SAVE1## ;SAVE AN AC
MOVE P1,T1 ;ARGUMENT COUNT TO P1
JRST @UTPTBL(U) ;DISPATCH TO SET OR READ TRAP LOCATIONS
UTPTBL: UTPRED
UTPSET
NUTRPF==.-UTPTBL-1
;HERE TO READ CONTENTS OF TRAP LOCATIONS
UTPRED: PUSHJ P,GETTRN ;GET TRAP NUMBER
POPJ P, ;ADDRESS CHECK OR BAD TRAP NUMBER
MOVE T1,.USTVC(U) ;GET CONTENTS OF TRAP LOCATION
PUSHJ P,PUTWR1## ;STORE IT FOR THE USER
JRST UTEADC ;ADDRESS CHECK
SOJG P1,UTPRED ;EXHAUSED COUNT?
JRST CPOPJ1## ;YES, GIVE GOOD RETURN
;HERE TO SET CONTENTS OF TRAP LOCATION
UTPSET: PUSHJ P,GETTRN ;GET TRAP NUMBER
POPJ P, ;ADDRESS CHECK OR BAD TRAP NUMBER
PUSHJ P,GETWR1## ;GET INSTRUCTION/ADDRESS TO STORE IN TRAP LOCATION
JRST UTEADC ;ADDRESS CHECK
JUMPE U,UTPSE2 ;ANY VALUE IS FINE FOR LUUO BLOCK
TLNE T1,777000 ;OPCODE ZERO?
JRST UTPSE2 ;NO, JUST GO STUFF
JUMPN T1,UTEIUT ;ILLEGAL UNLESS DEFAULTING
PUSH P,.USTVC ;SAVE CURRENT CONTENTS OF ALL TRAP LOCATIONS
PUSH P,.USTVC+1
PUSH P,.USTVC+2
PUSH P,.USTVC+3
MOVE T1,.JDAT+JOBENB##
PUSHJ P,SETRP ;SETUP TRAP LOCATIONS TO MONITOR DEFAULTS
MOVE T1,(U) ;GET MONITOR DEFAULT FOR CURRENT TRAP NUMBER
POP P,.USTVC+3 ;RESTORE ALL OTHER TRAP LOCATIONS
POP P,.USTVC+2
POP P,.USTVC+1
POP P,.USTVC
UTPSE2: MOVEM T1,.USTVC(U) ;STORE USER SUPPLIED INTRUCTION/ADDRESS, OR DEFAULT
SOJG P1,UTPSET ;LOOP OVEN ENTIRE ARGUMENT LIST
JRST CPOPJ1## ;AND GIVE DONE GOOD RETURN
;SUBROUTINE TO FETCH AND VALIDATE A TRAP NUMBER, RETURNS CPOPJ IF BAD, CPOPJ1
; IF OKAY, TRAP NUMBER IN U
GETTRN: PUSHJ P,GETWR1## ;GET NEXT TRAP NUMBER
JRST UTEADC ;ADDRESS CHECK
SKIPL T1 ;NEGATIVE TRAP NUMBERS ARE ILLEGAL
CAILE T1,2 ;SO ARE TRAP NUMBERS GREATER THAN 2
JRST UTEBTN ;BAD TRAP NUMBER
MOVEI U,(T1) ;RETURN TRAP NUMBER IN U
SOJA P1,CPOPJ1## ;DECREMENT ARGUMENT COUNT AND GOOD RETURN
SUBTTL MISC. ACCOUNTING UUOS (JOBNO,JOBTIM,DATE & MSTIME)
;RETURN JOB NUMBER FOR THIS JOB
JOBNO: SKIPA T1,J ;JOB NUMBER
; SKIP AND STORE T1 IS USER AC
;RETURN THE DATE TO THE USER
UDATE: MOVE T1,THSDAT##
JRST STOTAC##
;RETURN JOB RUNNING TIME IN MILLISECONDS
JOBTIM: PUSHJ P,JOBTMM ;GET JOBS RUN TIME
PJRST STOTAC## ; AND STORE IT
;THIS CODE DEPENDS UPON RTUPS BEING AN INTEGRAL MULTIPLE OF ^D100000
JOBTMM::MOVEI T3,RTUPS3## ;ASSUME MILLISECOND RESOLUTION
TLZE T1,(1B0) ;IF SIGN BIT = 1
MOVEI T3,RTUPS5## ; RETURN 10 USEC. RESOLUTION
IMUL T3,TICSEC##
PUSH P,T3 ;SAVE FOR LATER DIV
PUSHJ P,LGLPR1## ;SKIP IF LEGAL JOB NUMBER (0 IS OK)
JRST JOBTM3
SKIPN T1
SKIPA T1,J
MOVE J,T1 ;J PROCESS # IN QUESTION
PUSHJ P,UDCPUT## ;UPDATE CPU TIME IF PROCESS IS RUNNING SOMEWHERE
PUSHJ P,FNDPDB## ;FIND THE PDB
JRST JOBTM3 ;IF NONE RETURN ZERO
MOVE J,.CPJOB## ;SETUP J FROM JOB
IFN FTEMRT,<
MOVEI T1,ST%EMR ;EBOX MBOX ROUTINE?
TDNN T1,CNFST2## ;?
JRST JOBTM1 ;NO, COMPUTE RUNTIME NORMAL WAY
;YES,
MOVE T1,.PDMB2##(W) ;GET REMAINDER FROM MBOX JIFFY CALCULATION
MULI T1,RTUPS## ;COMPUTE LEFTOVER*RTUPS/MBOX TICKS PER JIFFY
DIV T1,.CPMBJ## ;LEAVE IN T1
MOVE T3,.PDEB2##(W) ;SAME FOR EBOX TICKS
MULI T3,RTUPS##
DIV T3,.CPEBJ##
ADD T3,T1 ;RESULT CANNOT BE GREATER THAN 2*RTUPS,
; WHICH FITS IN 36 BITS
MOVE T1,.PDEBT##(W) ;GET EBOX TICKS
ADD T1,.PDMBT##(W) ;COMPUTE EBOX/MBOX HIGH ORDER RUNTIME
MULI T1,RTUPS## ;CONVERT TO HIGH PRECISION UNITS
ADD T2,T3 ;ADD LOW ORDER PART FROM T3
JRST JOBTM2 ;GO JOIN COMMON CODE AGAIN
JOBTM1:>;END FTEMRT
MOVE T1,.PDTTM##(W) ;TOTAL JOB RUNNING TIME
MULI T1,RTUPS## ;EXPAND TO FULL PRECISION
ADD T2,.PDTT2##(W) ;ADD JIFFY FRACTION
JOBTM2: TLZE T2,(1B0) ; DOUBLE PRECISION
AOS T1
POP P,T3
DIV T1,T3
POPJ P,
JOBTM3: SETZM (P) ;RETURN ZERO
JRST TPOPJ##
;RETURN TIME OF DAY IN MILLISECONDS
MSTIME: MOVE T1,TIME## ;USE APR CLOCK BECAUSE IT HAS BETTER LONG
; TERM ACCURACY
IMULI T1,^D1000 ;CONVERT TO MILLISECONDS
IDIV T1,TICSEC##
JRST STOTAC##
SLEEPF::PUSH P,F ;PRESERVE F
PUSHJ P,SLEEP ;ZZZZZ
JRST FPOPJ## ;RESTORE F AND RETURN
SUBTTL SLEEP SERVICE FOR SLEEP UUO, DTA, MTA AND SCNSER.
;PUT JOB TO SLEEP FOR NSECONDS
;CALL CALL AC,[SIXBIT /SLEEP/]
;AC=XWD LOC,N N=NUMBER OF SECONDS TO SLEEP
;IF LH(AC)NON-0, SLEEP ONLY IF LOC THROUGH LOG+17
; MATCHES THE CURRENT JOBSTS ON THAT CHAN, OR IS 0
SLEEP:: IMUL T1,TICSEC## ;CONVERT TO TICKS
ANDI T1,7777
TDZA F,F ;LET WORLD KNOW THIS ISN'T AN I/O UUO
HSLEEP: TLO T1,(1B0) ;FLAG IT'S FROM HIBER
TRNN T1,7776 ;0 TIME?(CHECK ONLY 12 BITS)
HRRI T1,2 ;YES. SLEEP 1 JIFFY
PUSHJ P,SAVT## ;PRESERVE T2-T4 FOR CALLER
PUSH P,T1 ;SAVE SLEEP TIME
PUSH P,W ;SAVE W FOR DTASRN WHERE IT POINTS
; TO CONTROLER DATA BLOCK
PUSHJ P,FNDPDS## ;FIND THE PDB OR STOP
LDB T2,PDYIPT## ;GET PROTECT TIME
CAIGE T2,(T1) ;SLEEPING LONGER THAN PROTECT TIME?
PUSHJ P,CLRIPT## ;YES. CLEAR PROTECT TIME
POP P,W
HRLI T1,CTXWKJ## ;ADR. IN RUNCSS WHEN JOB WAKES UP
MOVEI T2,CLKR
TDNE T2,JBTSTS##(J) ;DOES THIS JOB HAVE A CLOCK QUEUE
; REQUEST IN CLOCK QUEUE?
JRST XSLEEP ;YES, DO NOT PUT ANOTHER ONE IN
SSLEEP: MOVE T2,.CPJCH## ;NO, GET JCH TO AWAKEN
SYSPIF
IDPB T1,CLOCK##
IDPB T2,CLOCK##
SETOM CLKNEW## ;NEW ENTRY HAS BEEN MADE
SYSPIN
JRST SLPNAP ;SET JOB STATUS WORD SO JOB WILL NOT RUN
XSLEEP: MOVE T2,T1 ;TIME TO SLEEP
MOVE T1,.CPJCH## ;JCH TO AWAKEN
PUSHJ P,CLKCHG## ;FIX UP THE CLOCK REQUEST
JRST SSLEEP ;NO ENTRY FOUND IN THE CLOCK QUEUE
; SO MAKE ONE NOW
SLPNAP: POP P,T1 ;RESTORE SLEEP TIME
DMOVEM 16,.JDAT+JOBDAC##+16 ;[~~] SETSTT RESTORES 16&17 FROM HERE.
MOVE T2,TICSEC## ;GET SECONDS WORTH OF JIFFIES
JUMPL T1,SETHBR## ;DON'T RESTORE SLPQ/NAPQ IF HIBER (HSLEEP)
CAILE T2,(T1) ;SLEEPING LONGER THAN A SECOND?
JRST SETNAP## ;NO, JUST GIVE THIS JOB A NAP
JRST SETSLP## ;YES, PUT THIS JOB TO SLEEP
SUBTTL PEEK UUO
;PEEK INTO MONITOR UUO
;CALL MOVEI AC,<MONITOR ADDRESS>
; CALL AC,[SIXBIT .PEEK.]
IFN FTPEEKSPY,< ;PEEK AND SPY
UPEEK: JUMPL T1,RTZER ;RETURN 0 IF NEGATIVE ARGUMENT
MOVE T2,T1 ;SAVE ARG
MOVSI T1,PVSPYA ;SEE IF USER MAY SPY ON ALL CORE
PUSHJ P,PRVBIT## ;..
JRST GOPEEK ;YES OK
JUMPL P1,RTZER ;PHYSICAL ONLY REQUIRES PEEK ON ALL
; OF CORE PRIVILEGES
MOVSI T1,PVSPYM ;NO. MAY HE SPY ON MONITOR?
PUSHJ P,PRVBIT## ;..
JRST PEEK1 ;YES
JRST RTZER ;NO. ERROR, RETURN 0.
PEEK1: MOVE T3,T2 ;COPY ADDRESS
CAMGE T3,SYSSIZ## ;IS HE ASKING FOR LEGAL VALUE?
JRST GOPEK1 ;YES
CAIL T3,CSBORG## ;IS THIS IN THE
CAML T3,MONVFF## ; HISEG
JRST RTZER ; NO
GOPEEK: JUMPGE P1,GOPEK1 ;VIRTUAL
CAMGE T2,MEMSIZ## ;IF PHYSICAL, IS IT LEGAL?
GOPEK1: PUSHJ P,PPPADR ;IF PHYSICAL ONLY, GET VIRTUAL ADR
JRST RTZER
MOVE T1,0(T2) ;YES. GET WORD
JRST STOTAC## ;RETURN IT TO USER IN AC.
> ;END IFN FTPEEKSPY
SUBTTL POKE. UUO
;POKE. -- PRIVILEGED UUO TO ALTER THE MONITOR
;CALL: MOVE AC,[3,,BLOCK]
; POKE. AC,
; ERROR
; OK
;ERROR RETURN WITH AC UNCHANGED IF NOT IMPLEMENTED
; AC=0 IF NOT PRIVILEGED
; AC=1 IF BAD MATCH
; AC=2 IF BAD ADDRESS
;
;BLOCK: LOCATION
; +1 OLD VALUE
; +2 NEW VALUE
IFN FTPOKE,<
POKE: PUSHJ P,SAVE2## ;SAVE P1-P2
MOVE P2,T1 ;SAVE ARGUMENT
MOVSI T1,JP.POK ;CHECK FOR POKE
PUSHJ P,PRVBIT## ; PRIVILEGES
CAIA
JRST RTZER ;NO--BOMB USER
HRR M,P2 ;POINT TO BLOCK
PUSHJ P,GETWDU## ;GET LOCATION
CAIL T1,CSBORG## ;BELOW THE BOTTOM OF THE MONITOR VIRTUAL ADDRESS SPACE?
CAML T1,MONVFF## ;BELOW THE TOP OF THE MONITOR VIRTUAL ADDRESS SPACE?
CAIA
JRST POKE0
JUMPGE P1,POKE0 ;ALLOW IF VIRTUAL ADDRESS
CAILE T1,17 ;CHECK ADDRESS
CAML T1,MEMSIZ## ; SEE IF LEGAL
PJRST ECOD2## ;NO--BOMB USER WITH ERROR 2
POKE0: MOVE T2,T1
MOVE P2,T2
PUSHJ P,PPPADR ;GET VIRTUAL ADR IF ARG IS PHYSICAL ADR
JRST ECOD2##
MOVE P1,T2 ;SAVE ADDRESS
PUSHJ P,GETWD1## ;GET USER'S IDEA OF OLD CONTENTS
PUSH P,T1 ;SAVE IT
PUSHJ P,GETWD1## ;GET NEW VALUE
PUSHJ P,POKADR ;COMPUTE ADDRESS (PRESERVES T1)
POP P,T4 ;RESTORE USER'S IDEA OF OLD CONTENTS
SYSPIF ;TO BE SAFE
CAME T4,(P1) ;COMPARE OLD VALUE
JRST POKE.1 ;FAIL--BOMB USER
CAIL P1,JBTPPN## ;RANGE-CHECK
CAIL P1,JBTPPN##+JOBN## ;FOR PPN TABLE
JRST POKE2 ;NOT A PPN
PUSHJ P,PPNCHK ;SEE IF WE LIKE THE PPN
JRST POKE.1 ;FAILED
POKE2: 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 IN CASE OF CRASH
MOVEI T1,.SWEPK ;EVENT CODE (POKE)
MOVE T2,P2 ;EVENT-SPECIFIC DATA WORD (ADDR POKED)
SKIPE [M.LPOK##] ;WANT TO LOG POKES?
PUSHJ P,SWESEB## ;LOG EVENT
SETZ F, ;NOT AN I/O UUO
JRST CPOPJ1## ;SKIP RETURN
POKE.1: SYSPIN ;TURN ON SYSTEM
PJRST ECOD1## ;RETURN CODE 1
>
IFE FTPOKE,<POKE==CPOPJ##>
;SUBROUTINE TO COMPUTE ADDRESS FOR POKE OR SNOOP
;PRESERVES T1
POKADR: CAIL P1,CSBORG## ;BELOW THE HIGH SEGMENT?
CAML P1,MONVFF## ;OR ABOVE THE HIGH SEGMENT?
POPJ P, ;YES, MUST BE MAPPED ONE-TO-ONE
MOVE T2,P1 ;MONITOR VIRTUAL ADDRESS
LSH T2,W2PLSH
HRLI T2,(POINT 36,0,35)
ADD T2,.CPMAP## ;RELOCATE FOR THIS CPU
LDB T3,T2 ;GET CONTENTS OF EXEC MAP SLOT CORRESPONDING TO THE PAGE
IFN FTKL10&FTMP,<
TDZE T3,[PM.CSH] ;CACHED?
PUSHJ P,UNCACH## ;UNCACHE THE PAGE FOR ALL CPUS
>
TDO T3,[PM.WRT] ;ALLOW WRITING
MOVEM T3,.UPMP+.UMTMP
MOVEI T2,.TEMP/PAGSIZ ;VIRTUAL PAGE NUMBER TO USE IN PER-PROCESS MAPPED ADDRESS
DPB T2,[POINT 9,P1,26] ;MONITOR VIRTUAL ADDRESS FOR POKE/SNOOP
CLRPGT ;CLEAR PAGING MEMORY SO NEW MAPPING IS USED
POPJ P, ;AND RETURN
;SUBROUTINE TO MAKE A PHYSICAL ADDRESS ADDRESSABLE IF PHYSICAL ONLY
; UUO OR UUO ARGUMENT IS .GT. 256K.
;
;CALL WITH (T2) = PHYSICAL ADDRESS
;RETURNS WITH (T2) = VIRTUAL ADDRESS WHICH MAPS TO PHYSICAL ADDRESS
IFN FTPEEKSPY!FTPOKE,<
PPPADR: MOVE T1,T2
SKIPGE P1 ;PHYSICAL ONLY UUO?
JRST PPPAD1 ;NO
PUSHJ P,PPPV2P
POPJ P,
TLNN T2,-1
JRST CPOPJ1##
PPPAD1: LSH T1,W2PLSH ;PAGE NUMBER
HRLI T1,(<PM.DCD>B2+PM.WRT+PM.PUB)
MOVEM T1,.UPMP+.UMTMP
ANDI T2,PG.BDY ;COMPUTE VIRTUAL ADDRESS OF LOC
IORI T2,.TEMP
CLRPT .TEMP
JRST CPOPJ1##
PPPV2P::SE1ENT
MAP T1,(T2)
PUSHJ P,FLTCHK##
POPJ P,
TLZ T1,(MP.NAD)
JRST CPOPJ1##
>
SUBTTL SNOOP. UUO - INSERT BREAK POINTS IN THE MONITOR
;UUO ALLOWS A PROGRAM TO INSERT BREAK POINTS IN THE MONITOR
; USEFUL FOR PERFORMANCE ANALYSIS, FAULT INSERTION, TRACE FUNCTIONS, ETC.
;CALLING SEQUENCE:
; MOVE AC,[FUNCTION,,ADDRESS]
; SNOOP. AC,
; ERROR RETURN
; NORMAL RETURN
SNOOP: HLRZ U,T1 ;FUNCTION
CAILE U,NLSNOP ;IS IT LEGAL?
JRST SNPIAL ;NO, ILLEGAL ARGUMENT LIST
PUSHJ P,PRUSET ;T1 = LENGTH OF THE ARGUMENT LIST
JRST SNPNPV ;NOT PRIVILEGED
JRST @SNPDSP(U) ;DISPATCH
SNPDSP: SNPDBP ;(0) DEFINE BREAK POINTS
SNPIBP ;(1) INSERT BREAK POINTS
SNPRBP ;(2) REMOVE BREAK POINTS
SNPUBP ;(3) UNDEFINE BREAK POINTS
SNPNUL ;(4) NULL FUNCTION. FOR BREAKPOINTS.
NLSNOP==.-SNPDSP-1
Comment @
Usefull labels for Breakpoints:
BP$000 Gets called by the .SONUL breakpoint function. Usefull for being
able to execute code at UUO level.
BP$001 Gets called right before the breakpoints are removed. Usefull for
installing cleanup code which gets called on a reset.
@
;ERROR RETURNS FROM THE SNOOP UUO
SOIAL%==1
SONPV%==2
SOSAS%==3
SOMBX%==4
SOIBI%==5
SONFS%==6
SOADC%==7
SOINL%==10
SOWMS%==11
ERCODE SNPIAL,SOIAL% ;ILLEGAL ARGUMENT LIST
ERCODE SNPNPV,SONPV% ;NOT PRIVILEGED
ERCODE SNPSAS,SOSAS% ;SOMEONE IS ALREADY SNOOP.'ING
ERCODE SNPMBX,SOMBX% ;MAXIMUM NUMBER OF BREAKPOINTS EXCEEDED
ERCODE SNPIBI,SOIBI% ;FUNCTION ILLEGAL BECAUSE BREAKPOINTS ALREADY INSERTED
ERCODE SNPNFS,SONFS% ;NO MONITOR FREE CORE
ERCODE SNPADC,SOADC% ;ADDRESS CHECK
ERCODE SNPINL,SOINL% ;ILLEGAL FUNCTION IF NOT LOCKED
ERCODE SNPWMS,SOWMS% ;WRONG MONITOR CHECKSUM
;OFFSETS IN BREAKPOINT CODE BLOCK
SNPAOS==0 ;AOS .+SNPCNT
SNPUSI==1 ;USER SUPPLIED INSTRUCTION
SNPSER==2 ;SOSA AT ERROR RETURN OF USER INSTRUCTION
SNPSNR==3 ;SOSA AT NORMAL RETURN OF USER INSTRUCTION
SNPRMI==4 ;REPLACED MONITOR INSTRUCTION
SNPJER==5 ;JRST AT ERROR RETURN OF MONITOR INSTRUCTION
SNPJNR==6 ;JRST AT NORMAAL RETURN OF MONITOR INSTRUCTION
SNPCNT==7 ;CURRENT USE COUNT FOR THIS BREAKPOINT
SNPBCB==^D8 ;SIZE OF BREAKPOINT CODE BLOCK
;HERE TO DEFINE BREAK POINTS (FUNCTION 0)
SNPDBP: SYSPIF ;INTERLOCK SYSTEM
SKIPE SYSBPJ## ;SNOOP FACILITY ALREADY IN USE?
CAMN J,SYSBPJ## ;YES, IN USE BY THIS JOB?
CAIA ;FREE OR IN USE BY THIS JOB, ALL IS WELL
JRST [SYSPIN ;UNLOCK
JRST SNPSAS] ;SOMEONE ALREADY SNOOPING
MOVEM J,SYSBPJ## ;RESERVE THE SNOOP FACILITY FOR THIS JOB
SYSPIN ;UNLOCK THE SYSTEM AND PROCEDE
JUMPLE T1,[PUSHJ P,RTNBPS ;NEGATIVE OR ZERO ARGUMENT LIST LENGTH IS ILLEGAL
JRST SNPIAL] ;RETURN BREAK POINTS AND GIVE ERROR RETURN
TRNE T1,1 ;MUST BE ODD
CAIGE T1,3 ;AND GE 3
JRST [PUSHJ P,RTNBPS ;RETURN BREAK POINTS
JRST SNPIAL] ;AND GIVE ILLEGAL ARGUMENT LIST ERROR RETURN
HRRZ T2,SYSBPP## ;NUMBER OF BREAK POINTS DEFINED SO FAR
LSH T2,1 ;TIMES 2 WORDS PER ARGUMENT
MOVNS T2 ;MINUS TWO TIMES THE NUMBER OF B.P.S ALREADY DEFINED
CAILE T1,2*MAXNBP##+1(T2)
JRST SNPMBX ;MAXIMUM NUMBER OF BREAK POINTS EXCEEDED
PUSHJ P,CKBINS ;SEE IF BREAK POINTS HAVE BEEN INSERTED
JRST SNPIBI ;THEY HAVE, ILLEGAL FUNCTION IF BREAK POINTS ARE INSERTED
PUSHJ P,SAVE2## ;SAVE P1-P2
SOS P1,T1 ;CHECKSUM WORD
LSH P1,-1 ;TWO WORDS PER BREAK POINT
PUSHJ P,GETWR1## ;GET THE MONITOR CHECKSUM
JRST [PUSHJ P,RTNBPS ;ADDRESS CHECK, RETURN BREAK POINTS
JRST SNPADC] ;AND GIVE AN ERROR RETURN
CAME T1,MSTCKS## ;USER SUPPLIED CHECKSUM AGREE WITH MONITOR COMPUTED ONE?
JRST [PUSHJ P,RTNBPS ;NO, RETURN BREAK POINTS
JRST SNPWMS] ;AND GIVE WRONG MONITOR CHECKSUM RETURN
HRRZ T1,SYSBPP## ;CURRENT NUMBER OF BREAK POINTS DEFINED
JUMPN T1,[HLRZ P2,SYSBPP## ;POINTER TO THE BREAK POINT TABLE
ADDI P2,(T1) ;NEXT FREE SLOT IN BREAK POINT TABLE
JRST SNPDB1] ;GO DEFINE NEXT BREAK POINT
MOVEI T2,MAXNBP## ;NO BREAK POINTS DEFINED YET, ALLOCATE A BREAK POINT TABLE
PUSHJ P,GTFWDC## ;GET SPACE
JRST SNPNFS ;NO FUNNY SPACE AVAILABLE
HRLZM T1,SYSBPP## ;STORE THE ADDRESS OF THE TABLE, NO B.P.S DEFINED YET
MOVE P2,T1 ;WORKING INDEX INTO THE TABLE
;HERE WITH P2 = POINTER TO THE BREAK POINT TABLE
;A BREAK POINT CODE BLOCK (BPCB) LOOKS LIKE THIS
;BPCB+SNPAOS AOS BPCB+SNPCNT ;EXECUTING BREAK POINT
;BPCB+SNPUSI USER SUPPLIED BREAK POINT INSTRUCTION
;BPCB+SNPSER SOSA BPCB+SNPCNT ;DONE EXECUTION OF BP, NON-SKIP
;BPCB+SNPSNR SOSA BPCB+SNPCNT ;DONE EXECUTION OF BP, SKIP
;BPCB+SNPRMI REPLACED MONITOR INSTRUCTION, 0 IF BPS NOT INSERTED
;BPCB+SNPJER JRST BP+1
;BPCB+SNPJNR JRST BP+2
;BPCB+SNPCNT NON-ZERO IF THE BREAK POINT IS CURRENTLY BEING EXECUTED
SNPDB1: PUSHJ P,GETWR1## ;MONITOR ADDRESS WHERE BREAK POINT IS TO BE INSERTED
JRST [PUSHJ P,RTNBPS ;;ADDRESS CHECK, RETURN BREAK POINTS
JRST SNPADC] ;AND GIVE ADDRESS CHECK ERROR RETURN
TLZ T1,-1 ;CLEAR LH JUNK
CAIG T1,17 ;TRYING TO INSERT IT IN AN AC?
JRST [PUSHJ P,RTNBPS ;YES, RETURN BREAKPOINTS
JRST SNPIAL] ;AND GIVE ILL ARG LIST RETURN
HRLM T1,(P2) ;STORE MONITOR ADDRESS OF THE BREAK POINT
MOVEI T2,SNPBCB ;EIGHT WORDS ARE REQUIRED FOR THE BREAK POINT CODE
PUSHJ P,GETWDS## ;GET THE SPACE
JRST [PUSHJ P,RTNBPS ;NOT AVAILABLE, RETURN BREAK POINTS
JRST SNPNFS] ;AND GIVE NO FREE SPACE ERROR RETURN
HRRM T1,(P2) ;STORE ADDRESS OF THE CODE BLOCK ASSOCIATED WITH THIS B.P.
AOS SYSBPP## ;ONE MORE BREAK POINT DEFINED
PUSHJ P,GETWR1## ;BREAK POINT INSTRUCTION
JRST [PUSHJ P,RTNBPS ;ADDRESS CHECK, RETURN BREAK POINTS
JRST SNPADC] ;AND GIVE ADDRESS CHECK ERROR RETURN
HRRZ T2,(P2) ;RESTORE ADDRESS OF THE CODE BLOCK
MOVSI T3,(AOS) ;AOS
HRRI T3,SNPCNT(T2) ; BP CODE + SNPCNT
MOVEM T3,SNPAOS(T2) ;STORE THAT TO BE EXECUTED BEFORE BP INSTRUCTION
SETZM (T3) ;BREAK POINT ISN'T IN EXECUTION
MOVEM T1,SNPUSI(T2) ;STORE THE USER SUPPLIED BREAK POINT INSTRUCTION
SETZM SNPRMI(T2) ;INDICATE THAT BREAK POINT HAS NOT BEEN INSERTED YET
HRLI T3,(SOSA) ;SOSA BP CODE + SNPCNT
MOVEM T3,SNPSER(T2) ;BREAK POINT INSTRUCTION DIDN'T SKIP
MOVEM T3,SNPSNR(T2) ;BREAK POINT INSTRUCTION SKIPPED
MOVSI T1,(JRST) ;UNCONDITIONAL JUMP
HLRZ T3,(P2) ;MONITOR ADDRESS OF THE BREAK POINT
ADDI T1,1(T3) ;BREAK POINT ADDRESS + 1
MOVEM T1,SNPJER(T2) ;JRST BP+1
ADDI T1,1 ;BREAK POINT ADDRESS + 2
MOVEM T1,SNPJNR(T2) ;JRST BP+2
IFN FTKL10&FTMP,<
PUSH P,P1 ;SAVE COUNT
HLRZ P1,(P2) ;EXEC VIRTUAL ADDRESS OF THE B.P.
PUSHJ P,POKADR ;MAKE SURE THAT THE PAGE IS UNCACHED IN ALL MAPS
POP P,P1 ;RESTORE COUNT
>
AOS P2 ;NEXT SLOT IN THE BREAK POINT TABLE
SOJG P1,SNPDB1 ;LOOP OVER THE USER'S ENTIRE ARGUMENT LIST
JRST CPOPJ1## ;AND GIVE GOOD RETURN
;HERE TO INSERT BREAK POINTS (FUNCTION 1)
SNPIBP: PUSHJ P,LOKEVC## ;JOB MUST BE LOCKED CONTIGUOUSLY IN EVM
JRST SNPINL ;ITS NOT, ILLEGAL IF NOT LOCKED ERROR RETURN
CAME J,SYSBPJ## ;IS THIS JOB THE CURRENT OWNER OF THE SNOOP FACILITY?
JRST SNPSAS ;NO, SOMEONE ELSE IS ALREADY SNOOPING
PUSHJ P,CKBINS ;HAVE BREAK POINTS ALREADY BEEN INSERTED?
JRST SNPIBI ;ILLEGAL FUNCTION IF BREAK POINTS INSERTED
SETZB F,T2 ;F=0, EVENT-SPECIFIC DATA WORD
MOVEI T1,.SWESN ;EVENT CODE (SNOOP)
PUSHJ P,SWESEB## ;LOG EVENT
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
AOS (P) ;SET FOR SKIP RETURN TO USER
;FALL INTO REMBPS
REMBPS: PUSHJ P,CKBINS ;BREAK POINTS ACTUALLY INSERTED?
SKIPA ;YES
POPJ P, ;NO, SO ALL IS KOSHER
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
>
POPJ P, ;RETURN
;HERE TO UNDEFINE BREAK POINTS (FUNCTION 3)
SNPUBP: CAME J,SYSBPJ## ;CURRENT JOB OWN THE SNOOP FACILITY?
JRST SNPSAS ;NO, SOMEONE ELSE IS ALREADY SNOOPING
PUSHJ P,CKBINS ;ARE BREAK POINTS INSERTED?
JRST SNPIBI ;YES, ILLEGAL IF BREAK POINTS ARE INSERTED
AOS (P) ;SET FOR SKIP RETURN
PJRST RTNBPS
;THE NULL FUNCTION
SNPNUL: CAME J,SYSBPJ## ;THIS BEING EXECUTED BY SNOOP OWNER?
JRST SNPSAS ; NOPE. SOMEONE ELSE.
BP$000: POPJ P, ;FINISHED
JRST CPOPJ1## ;IN CASE SNOOPED INSTRUCTION SKIPS.
;MISC. SUBROUTINES
RTNBPS: PUSHJ P,SAVE2## ;SAVE P1-P2
BP$001:!HRRZ P1,SYSBPP## ;NUMBER OF DEFINED BREAK POINTS
HLRZ P2,SYSBPP## ;ADDRESS OF THE BREAK POINT TABLE
JUMPE P1,RTNBP2 ;JUMP IF NO BREAK POINTS CURRENTLY DEFINED
RTNBP1: MOVEI T1,SNPBCB ;EIGHT WORDS PER BREAK POINT CODE BLOCK
HRRZ T2,(P2) ;ADDRESS OF THIS BREAK POINT CODE BLOCK
PUSHJ P,GIVWDS## ;RETURN THE MONITOR FREE CORE
AOS P2 ;NEXT ENTRY IN THE BREAK POINT TABLE
SOJG P1,RTNBP1 ;LOOP OVER THE ENTIRE BREAK POINT TABLE
RTNBP2: MOVEI T1,MAXNBP## ;LENGTH OF THE BREAK POINT TABLE
HLRZ T2,SYSBPP## ;ADDRESS OF THE BREAK POINT TABLE
SKIPE T2 ;IF A TABLE HAS BEEN ALLOCATED,
PUSHJ P,GVFWDS## ; RETURN THE SPACE
SETZM SYSBPJ## ;NO LONGER ANYONE SNOOPING
SETZM SYSBPP## ;AND NO BREAK POINT TABLE IS ALLOCATED
POPJ P, ;RETURN
CKBINS: HRRZ T2,SYSBPP## ;NUMBER OF BREAK POINTS
JUMPE T2,CPOPJ1## ;BREAK POINTS AREN'T INSERTED IF NONE ARE DEFINED
HLRZ T2,SYSBPP## ;ADDRESS OF THE BREAK POINT TABLE
HRRZ T2,(T2) ;ADDRESS OF BREAK POINT CODE BLOCK FOR FIRST BREAK POINT
SKIPN SNPRMI(T2) ;IF NON-ZERO, BREAK POINTS HAVE BEEN INSERTED
AOS (P) ;ZERO, BREAK POINT IS DEFINED BUT NOT INSERTED
POPJ P, ;GIVE INSERTED OR NOT INSERTED RETURN
SNPRST: CAME J,SYSBPJ## ;DOES JOB DOING THE RESET OWN THE SNOOP FACILITY?
POPJ P, ;NO, NOTHING TO DO
PUSHJ P,REMBPS ;REMOVE BREAK POINTS IF INSERTED
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
REPEAT 0,<
;FUNCTIONS DEFINED IN FILIO AND TAPUUO:
1 ASSIGN SINGLE UNIT
2 ASSIGN ALL UNITS ON A CHAN/KONTROLLER
3 RELEASE CHANNEL/KONTROLLER AND ALL UNITS
4 SPECIFY CHANNEL PROGRAM
5 RELEASE CHANNEL PROGRAM
6 GET CHANNEL STATUS
7 GET KONTROLLER AND UNIT NUMBERS
12 SPECIFY CHANNEL PROGRAM FOR READ IN REVERSE
15 SHUTDOWN I/O ON TAPE CHANNEL
16 START I/O ON TAPE CHANNEL
17 ENABLE MICROCODE LOADING
20 DISABLE MICROCODE LOADING
21 LOAD MICROCODE
FUNCTIONS DEFINED IN UUOCON
10 READ CSB
11 READ DSB
13 ENABLE/DISABLE AUTO LOAD OF DX20'S
14 OBTAIN USER IOT
24 EXECUTE S-BUS DIAGNOSTIC FUNCTION
FUNCTIONS DEFINED IN MOSSER
100 GET MEMORY
101 GIVE MEMORY
FUNCTIONS DEFINED IN KLPSER AND KNISER
22 SET IPA CHANNEL MAINTENANCE MODE
23 CLEAR IPA CHANNEL MAINTENANCE MODE
FUNCTIONS DEFINED IN KLPSER
105 RESET REMOTE SYSTEM
106 START REMOTE SYSTEM
107 PORT COUNTER FUNCTIONS
112 WRITE CI MAINTENANCE DATA
113 READ CI MAINTENANCE DATA
>
DIAUUO: PUSHJ P,SAVE4## ;DO THIS NOW
PUSH P,T1
HRR M,T1 ;ADR OF BLOCK
PUSHJ P,GETWDU## ;GET ARG
MOVSI P4,-DIDSLN ;AOBJN POINTER TO DIAG TABLE
DIAUO1: LDB T3,[POINT 9,DIADST(P4),17] ;GET FUNCTION
CAIE T3,(T1) ;THIS FUNCTION?
AOBJN P4,DIAUO1 ;NO
JUMPGE P4,[POP P,T1
JRST DIAAIF]
MOVE P4,DIADST(P4) ;GET DISPATCH WORD
MOVE P2,T1 ;MOVE FUNCTION TO P2
;IF GOING TO DO IO HE'D BETTER BE ALL IN CORE
TLNE P4,(DI.NVR) ;NOT ALLOWED TO BE VIRTUAL?
SKIPN .USVRT ;NO, IS HE?
JRST DIAUO2 ;NOT VIRTUAL OR DON'T CARE
POP P,(P) ;FIX STACK
JRST DIAAVC ;LOSE
DIAUO2: TLNN P4,(DI.UIO) ;GIVE USER I/O ON THIS FUNCTION?
JRST DIAUO3 ;NO
SETZ T1, ;SAY WE WANT USER-IOT
PUSHJ P,STOTAC## ;TRPSET CALLS GETTAC
PUSHJ P,TRPSTU ;CHECK PRIVS, SET USRIOT
JRST [POP P,(P) ;NO PRIVS, LOSE
JRST DIAANP]
DIAUO3: POP P,T1 ;OK, RESTORE ARGUMENT
TLNE P4,(DI.UIO) ;DIDN'T CALL TRPSET
PUSHJ P,STOTAC## ;TRPSET STORES 0 IN THE AC
HRR M,T1 ;POINT BACK TO THE USER'S ARG BLOCK
TLNE P4,(DI.NON) ;CHECK N?
JRST DIAUO4 ;NO
HLRE T2,T1 ;NUMBER OF ARGUMENTS
JUMPGE T2,DIAAIA ;ILLEGAL N
MOVN P1,T2 ;P1=NUMBER OF ARGS
CAIGE P1,2 ;LEGAL?
JRST DIAAIA ;ILLEGAL N
DIAUO4: SETZ F, ;NO DDB YET
HLRZ T1,P2 ;GET POSSIBLE CPU NUMBER
TLZ P2,-1 ;AND CLEAR THE ARGUMENT
IFE FTMP,<
TLNE P4,(DI.CPU) ;WOULD FUNCTION ACCEPT CPU NUMBER?
JUMPN T1,DIAABA ;YES, GIVE AN ERROR IF ONE SPECIFIED
>; END IFE FTMP
IFN FTMP,<
TLNN P4,(DI.CPU) ;CPU NUMBER SUPPLIED IN FUNCTION WORD?
JRST DIAUO5 ;NO
PUSHJ P,ONCPUS## ;GET ON THAT CPU
JRST DIAANR ;NOT RUNNING
DIAUO5:
>; END IFN FTMP
TLNN P4,(DI.KDB!DI.UDB!DI.DEV) ;NEED ONE OF THESE?
JRST DIAUO7 ;NO
PUSHJ P,GETWD1## ;GET KON/UNIT WORD
TLNE P4,(DI.DEV) ;CPU/KONT/UNIT DESIGNATOR?
JRST DIAUO6 ;YES
LDB T2,[POINT 7,T1,6] ;CONTROLLER NUMBER
PUSHJ P,DIAKDU ;FIND THE SPECIFIED KDB/UDB
JRST DIAAIC ;NO SUCH DEVICE
JRST DIAAIU ;ILLEGAL UNIT NUMBER
JRST DIAUO7 ;FINISH UP
DIAUO6: MOVE T2,T1 ;COPY ARGUMENT
PUSHJ P,DIADEV ;FIND THE SPECIFIED DEVICE
JRST DIAAIC ;NO SUCH DEVICE
JRST DIAAIU ;ILLEGAL UNIT
DIAUO7: SSX P4,IFIW ;AVOID ILL MEM REFS
JRST (P4) ;GO DISPATCH
;ROUTINE TO FIND A DEVICE
;CALL: PUSHJ P,DIADEV
; <RETURN 1> ;NO SUCH DEVICE
; <RETURN 2> ;ILLEGAL UNIT ON DEVICE
; <RETURN 3> ;W = KDB, U = UNIT #, F = DDB
DIADEV: SETZB W,U ;NO KDB OR UDB YET
SETZ F, ;NO DDB YET
MOVE P1,T2 ;COPY ARGUMENT
;CHECK FOR A POSSIBLE CPU NAME
IFE FTMP,<
CAMN T2,.CPPHY## ;OUR NAME?
JRST CPOPJ2## ;THEN IT'S A CPU (U ALREADY = ZERO)
> ;END IFN FTMP
IFN FTMP,<
PUSHJ P,CPUFND## ;DOES CPU EXIST?
JRST DIADE1 ;NOT A CPU
CAIL T1,M.CPU## ;REASONABLE NUMBER?
JRST CPOPJ1## ;ILLEGAL UNIT OF A SORT
MOVE U,T1 ;COPY CPU NUMBER
JRST CPOPJ2## ;AND RETURN
> ;IFN FTMP
;SEARCH FOR A POSSIBLE KONTROLLER
DIADE1: HLLZ T2,P1 ;GET KONTROLLER PORTION OF DEVICE NAME
MOVSI T1,-TYPMAX-1 ;SET TO SEARCH ALL OF KDBTAB
PUSHJ P,FNDKON ;LOOK FOR A KDB WITH THIS NAME
JRST [CAMN T2,P1 ;SECOND TIME THROUGH?
JRST DIADE2 ;GO TRY FOR A RANDOM DEVICE
MOVE T2,P1 ;LOAD UP FULL NAME (WITH POSSIBLE CPU NUMBER)
JRST .-2] ;AND TRY AGAIN
MOVE W,T3 ;COPY KDB ADDRESS
MOVNI U,1 ;ASSUME ALL DRIVES
HRRZ T1,P1 ;GET DRIVE DESIGNATOR
JUMPE T1,CPOPJ2## ;ONLY KONTROLLER SPECIFIED
PUSHJ P,DIANUM ;TRANSLATE TO UNIT NUMBER
JRST DIADE2 ;NOT NUMERIC
MOVE U,T1 ;COPY DRIVE NUMBER
JRST CPOPJ2## ;RETURN
;SEARCH FOR A POSSIBLE DEVICE NAME
DIADE2: MOVE T1,P1 ;GET ARGUMENT BACK AGAIN
PUSHJ P,DEVPHY ;SCAN THE DDBS FOR A MATCH
POPJ P, ;NO SUCH DEVICE
JRST CPOPJ2## ;RETURN WITH DDB IN F
DIANUM: SKIPN T3,T1 ;COPY
JRST CPOPJ1## ;ZERO
SETZ T1, ;CLEAR RESULT
MOVE T4,KDBDSP(W) ;DRIVER DISPATCH
MOVE T4,DRVCNF(T4) ;GET INTERESTING BITS
TRNE T4,DR.NMC ;CPU NUMBER ENCODED IN KONT NAME?
SOJA T1,CPOPJ1## ;YES--THEN NOT REALLY A DRIVE DESIGNATOR
TRNE T4,DR.DDN ;USING DECIMAL NUMBERS?
SKIPA T4,[12] ;YES
MOVEI T4,10 ;ELSE OCTAL
DIANU1: TLNE T3,770000 ;LEFT JUSTIFIED?
JRST DIANU2 ;YES
LSH T3,6 ;SLIDE OVER SOME
JRST DIANU1 ;LOOP BACK
DIANU2: LSHC T2,6 ;GET A CHARACTER
ANDI T2,77 ;MASK DOWN
CAIL T2,'0' ;RANGE
CAILE T2,'0'(T4) ; CHECK
POPJ P, ;NOT NUMERIC
IMULI T1,(T4) ;SCALE RESULT
ADDI T1,-'0'(T2) ;INCLUDE DIGIT
JUMPN T3,DIANU2 ;LOOP IF MORE
JRST CPOPJ1 ;AND RETURN
;ROUTINE TO SCAN THE KDBS AND UDBS FOR A MATCH
;CALL: PUSHJ P,DIAKDU
; <RETURN 1> ;NO SUCH DEVICE
; <RETURN 2> ;ILLEGAL UNIT ON DEVICE
; <RETURN 3> ;W = KDB, U = UDB
DIAKDU: PUSH P,P1 ;SAVE P1 (UUO ARG COUNT)
MOVSI P1,-TYPMAX-1 ;AOBJN POINTER TO KDB TABLE
DIAKD1: SKIPN W,KDBTAB##(P1) ;GET A KDB ADDRESS
DIAKD2: AOBJN P1,DIAKD1 ;TRY ANOTHER
JUMPGE P1,P1POPJ## ;CAN'T FIND SPECIFIED DEVICE
DIAKD3:
IFN FTMP,<
MOVE T3,KDBCAM(W) ;CPU ACCESSIBILITY MASK
TDNE T3,.CPBIT## ;IS IT US?
> ;END IFN FTMP
CAME T2,KDBDVC(W) ;YES, RIGHT CONTROLLER?
JRST DIAKD5 ;NO, TRY NEXT KDB
SKIPG KDBUNI(W) ;MULTI-UNIT CONTROLLER?
JRST DIAKD4 ;NO, USE UNIT NUMBER
HLRZ T3,KDBUNI(W) ;YES. GET THIS KDB'S UNIT NUMBER
LDB T4,[POINT 3,T1,29]
CAIE T3,(T4) ;RIGHT UNIT (KDB)?
JRST DIAKD5 ;NO. TRY NEXT KDB
LDB P3,[POINT 3,T1,35] ;YES. GET SLAVE NUMBER
CAIA
DIAKD4: LDB P3,[POINT 3,T1,29] ;GET UNIT NUMBER
ADD P3,KDBIUN(W) ;POINT TO RIGHT UDB
POP P,P1 ;RESTORE P1
SKIPN U,(P3) ;IS THERE SUCH A UNIT?
JRST CPOPJ1## ;NO
JRST CPOPJ2## ;RETURN GOODNESS
DIAKD5: SKIPE W,KDBNXT(W) ;STEP TO NEXT KDB
JRST DIAKD3 ;GO TEST IT
JRST DIAKD2 ;TRY ANOTHER DEVICE TYPE
;HERE TO GET KONTROLLER/UNIT
DIAKUN: PUSHJ P,GETWD1## ;GET DEVICE NAME
MOVEI T2,DD%PHY!DD%LOG!DD%ALT ;PHYSICAL, LOGICAL, ALTERNATE PORTS
PUSHJ P,DDBSRC ;SCAN THE DDBS FOR A MATCH
TDZA T3,T3 ;NOT FOUND
JRST DIAKU1 ;ONWARD
PUSHJ P,DVSRSP ;MAYBE A SPOOLED DEVICE (DISK)?
JRST DIAAIU ;NO SUCH DEVICE
DIAKU1: LDB T2,PDVTYP## ;GET DEVICE TYPE
SKIPN W,KDBTAB##(T2) ;GET KDB ADDRESS
JRST DIAAIU ;KNOWN DEVICE BUT NO DIAG CODE
MOVEI P2,.DIAKU ;SET UP FUNCTION
PJRST DIADSP ;GO DISPATCH
;HERE FROM STOP1A ON ^C OR EXIT, HALT,... ;OR FROM HNGDSK
IFN FTKS10,<DIACLR==:CPOPJ##>
IFN FTKL10,<
DIACLR::SE1ENT ;ENTER SECTION ONE
IFN FTSCA,<PUSHJ P,PPDCLR##> ;CLEAR STALE STUFF IN PCBS
PUSH P,M ;SAVE M
HRROS M ;SO DON'T STORE IN USER'S ACS
PUSHJ P,TPDSIA## ;START UP TAPE SCHEDULING
JFCL
POP P,M ;RESTORE M
PUSHJ P,FNDPDB## ;FIND FDB
POPJ P, ;THERE ISN'T ONE
SKIPN F,.PDDIA##(W) ;DIAG GOING?
POPJ P, ;NO
PUSHJ P,SAVE3## ;YES, SAVE SOME ACS
SETZ P2, ;ENTRY 0 = ^C POINT
> ;END IFN FTKL10
;HERE TO DISPATCH WITH THE FOLLOWING ACS SETUP FOR THE DRIVER:
; P1 = NUMBER OF ARGUMENTS
; P2 = FUNCTION CODE
; P3 = SUBROUTINE
; W = KDB ADDRESS
; U = UDB ADDRESS
; F = CONTENTS OF .PDDIA
DIADSP: JUMPN F,DIADS2 ;DON'T RESET F IF ALREADY FOUND A DDB
PUSH P,W ;SAVE POSSIBLE KDB ADDRESS
PUSHJ P,FNDPDS## ;RELOAD W WITH PDB ADDRESS
HRRZ F,.PDDIA##(W) ;MAYBE THERE'S A DIAG. DDB
POP P,W ;RESTORE POSSIBLE KDB ADDRESS
JUMPN W,DIADS1 ;NOT CPU IF ACS 'F' OR 'W' NON-ZERO
XMOVEI T2,CPUDIA## ;SPECIAL CPU/DIAG TABLE
JRST DIADS3 ;ENTER LOOP
DIADS1: SKIPA T2,KDBDSP(W) ;GET DRIVER DISPATCH FROM KDB
DIADS2: MOVE T2,DEVDRV(F) ;GET DRIVER DISPATCH FROM DDB
JUMPE T2,DIANUI ;GIVE UP IF NO DISPATCH
SKIPN T2,DRVDIA(T2) ;SUPPORT DIAG UUO?
JRST DIANUI ;NOPE
DIADS3: XMOVEI T3,1(T2) ;IGNORE FIRST (PREPROCESSOR) ENTRY
DIADS4: SKIPN (T3) ;END OF TABLE?
JRST DIANUI ;FUNCTION NOT SUPPORTED BY DRIVER
HLRZ T4,(T3) ;GET A FUNCTION CODE
CAIE T4,(P2) ;A MATCH?
AOJA T3,DIADS4 ;TRY ANOTHER
HRRZ P3,(T3) ;GET SUBROUTINE ADDRESS
IFN FTXMON,<HLL P3,T2> ;MAKE RELATIVE TO SECTION WHERE TABLE LIVES
PUSHJ P,@(T2) ;CALL PREPROCESSOR SUBROUTINE (WILL CALL C(P3))
DIANUI:: SKIPA T1,[XC.UIO] ;LOST
JRST CPOPJ1## ;RETURN
ANDCAM T1,.JDAT+JOBPD1## ;CLEAR USRIOT IF ERROR
MOVSI T1,NSWP!NSHF ;JOB IS NOW MOVABLE
MOVE J,.USJOB ;J MAY HAVE BEEN CLOBBERED
ANDCAM T1,JBTSTS##(J) ;UNLOCK JOB
POPJ P, ;RETURN
IFN FTKL10,<
;FINISH UP GET CHANNEL STATS
;ENTER WITH P1=NO OF ARGS, P2=LOC OF ICWA
DIAGCS::MOVEI T2,-4(P1) ;SAVE NO OF ARGS -4
HRRZ T3,(P2) ;SAVE ADDR OF 1ST IOWD
CAILE P1,4 ;ASKING FOR TOO MUCH?
MOVEI P1,4 ;YES, MAX HE CAN GET
DIAGC1: MOVE T1,(P2) ;GET A WORD FROM LOW CORE
PUSHJ P,PUTWD1## ;TELL USER
SOJLE P1,DIAGC2 ;DONE IF 0
AOJA P2,DIAGC1 ;GET NEXT WORD
DIAGC2: JUMPLE T2,CPOPJ1## ;RETURN IF HE DOESN'T WANT CCWS STORED
DIAGC3: MOVE T1,(T3) ;GET A CCW
PUSHJ P,PUTWD1## ;GIVE IT TO THE USER
JUMPE T1,CPOPJ1## ;RETURN AFTER STORING TERMINATING ZERO
SOJLE T2,CPOPJ1## ;RETURN IF COUNT EXHAUSTED
TLNN T1,577777 ;REAL IOWD?
SOS T3,T1 ;CHAN JUMP - GET NEW ADDRESS
AOJA T3,DIAGC3 ;GO GET NEXT IOWD
>; END IFN FTKL10
;HERE FOR THE CODE COMMON TO BOTH READ CPU STATUS BLOCK AND READ
;DEVICE STATUS BLOCK
DIAXSB: MOVSI T1,JP.POK ;MUST HAVE POKE PRIVS OR
PUSHJ P,PRVBIT## ;BE [1,2] OR JACCT
SKIPA ;HE'S OK
JRST DIAANP ;NOT ENOUGH PRIVS
PUSHJ P,GETWD1## ;GET CPU NUMBER
SKIPL T1 ;IF NEGATIVE
CAIL T1,M.CPU## ;OR GREATER THAN THE NUMBER OF CPUS
JRST DIAANC ;IT'S ILLEGAL
IFN FTMP,<
PUSHJ P,ONCPUS## ;GET TO THAT CPU
JRST DIAANR ;CPU NOT RUNNING
>
CAIL P2,.DIACS ;FUNCTION CODE IN RANGE?
CAILE P2,.DIADS ;...?
JRST DIAAIF ;NO, CAUGHT IT JUST IN TIME
PJRST @.+1-.DIACS(P2) ;DO THE FUNCTION SPECIFIC STUFF IN COMMON
IFIW DIACSB## ;READ CPU STATUS BLOCK
IFIW DIADSB## ;READ DEVICE STATUS BLOCK
;HERE TO EXECUTE AN S-BUS DIAGNOSTIC FUNCTION
IFN FTKL10,<
DIASBD: CAIE P1,3 ;MUST BE 3 WORDS IN ARGUMENT BLOCK
JRST DIAAIA ;BAD ARGUMENT LIST LENGTH
MOVSI T1,JP.POK ;MUST HAVE POKE PRIVS OR
PUSHJ P,PRVBIT## ;BE [1,2] OR JACCT
SKIPA ;HE'S OK
JRST DIAANP ;NOT ENOUGH PRIVS
PUSHJ P,GETWD1## ;GET SECOND WORD OF BLOCK (TO-MEMORY WORD)
SETZ T2, ;CLEAR FROM-MEMORY WORD
SBDIAG T1 ;DO THE FUNCTION
PUSH P,T2 ;SAVE FROM-MEMORY WORD
PUSHJ P,PUTWDU## ;RETURN UPDATED TO-MEMORY WORD
POP P,T1 ;RESTORE FROM-MEMORY WORD
PUSHJ P,PUTWD1## ;RETURN FROM-MEMORY WORD
JRST CPOPJ1## ;SKIP RETURN
>; END IFN FTKL10
;HERE TO READ A UNIBUS REGISTER
IFN FTKS10,<
DIARUR: CAIE P1,2 ;MUST BE 2 WORDS IN ARGUMENT BLOCK
JRST DIAAIA ;BAD ARGUMENT LIST LENGTH
MOVSI T1,JP.POK ;MUST HAVE POKE PRIVS OR
PUSHJ P,PRVBIT## ;BE [1,2] OR JACCT
SKIPA ;HE'S OK
JRST DIAANP ;NOT ENOUGH PRIVS
PUSHJ P,GETWD1## ;GET SECOND WORD OF BLOCK (UNIBUS REGISTER)
PUSHJ P,UBGOOD## ;WILL IT PAGE FAULT?
JRST DIAANU ;YES, RETURN AN ERROR
RDIO T1,(T1) ;READ THE REGISTER
JRST STOTC1## ;RETURN IN AC AND SKIP RETURN
>; END IFN FTKS10
;HERE TO ALLOCATE A BUFFER IN WHICH TO DUMP THE IPA20 DRAM
IFN FTKL10&<FTSCA!FTENET>,<
DIAADB: MOVSI T1,JP.POK ;MUST HAVE POKE PRIVS OR
PUSHJ P,PRVBIT## ;BE [1,2] OR JACCT
SKIPA ;HE'S OK
JRST DIAANP ;NOT ENOUGH PRIVS
SKIPE IPKDDB(W) ;BUFFER ALREADY ALLOCATED?
JRST CPOPJ1## ;YES, NOTHING TO DO
MOVEI T2,DRMSIZ ;SIZE OF THE DRAM IN WORDS
PUSHJ P,GFWNZS## ;ALLOCATE SPACE
JRST DIAAFC ;NO FREE CORE
MOVEM T1,IPKDDB(W) ;SAVE THE ADDRESS
MOVE T2,T1 ;COPY THE BUFFER ADDRESS
AOS T3,T1 ;BUILD A BLT POINTER
MOVEI T1,DRMSIZ-1 ;NUMBER OF WORDS TO ZERO
SETZM (T2) ;ZERO FIRST WORD
EXTEND T1,[XBLT] ;ZERO THE REST OF THE BUFFER
JRST CPOPJ1## ;SKIP RETURN
>; END IFN FTKL10&<FTSCA!FTENET>
;READ DEVICE SERIAL NUMBER
DIADSN: JUMPE W,DIAAIU ;ILLEGAL UNIT IF NO KDB OR UDB GIVEN
XMOVEI T3,KDBSER(W) ;ASSUME KONTROLLER S/N WANTED
PUSHJ P,DIAUDB ;TRANSLATE C(U) TO UDB ADDR IN T2
CAIA ;WANTS KONTROLLER
XMOVEI T3,UDBDSN(T2) ;POINT TO S/N FOR DRIVE
MOVE T1,0(T3) ;WORD ONE
PUSHJ P,PUTWD1## ;RETURN TO USER
MOVE T1,1(T3) ;WORD TWO
PUSHJ P,PUTWD1## ;GIVE TO USER
JRST CPOPJ1## ;RETURN GOODNESS
;ROUTINE TO FIND THE TUB ASSOCIATED FOR THE DRIVE IN AC 'U'
DIAUDB: JUMPL U,CPOPJ## ;CALLER REALLY WANTS KDB IF -1
MOVE T1,KDBIUN(W) ;DRIVE TABLE
DIAUD1: SKIPN T2,(T1) ;GET A UDB
JRST DIAUD2 ;NONE THERE
CAMN U,UDBPDN(T2) ;FOUND THE UDB?
JRST CPOPJ1## ;YES
DIAUD2: CAMGE T1,KDBFUN(W) ;END OF TABLE?
AOJA T1,DIAUD1 ;KEEP SEARCHING
POPJ P, ;NON-EXISTANT DRIVE
;READ DEVICE REGISTERS
DIAREG: PUSHJ P,SAVE3## ;SAVE SOME ACS
JUMPN W,DIARG1 ;SKIP DDB STUFF IF A KONTROLLER GIVEN
SKIPE P1,F ;NEED A DDB
SKIPN T2,DEVDRV(F) ;GET DRIVER DISPATCH
JRST DIAABA ;SAY BAD ARGUMENT LIST
MOVE P2,DRVDDL(T2) ;COPY DDB LENGTH
JRST DIARG2 ;GO RETURN DATA
;HERE IF AT LEAST A KONTROLLER
DIARG1: MOVE P1,W ;SAVE DATA STRUCTURE ADDRESS
MOVE T2,KDBDSP(W) ;GET ITS DISPATCH TABLE
MOVE P2,DRVKLN(T2) ;ASSUME WILL BE SNIFFING AT THE KDB
JUMPL U,DIARG2 ;ANY UNIT NUMBER?
;HERE TO FIND THE UDB
PUSHJ P,DIAUDB ;FIND UDB
JRST DIAAIU ;ILLEGAL UNIT
MOVE P1,T2 ;COPY UDB ADDRESS
MOVE T2,KDBDSP(W) ;GET DISPATCH AGAIN
MOVE P2,DRVULN(T2) ;AND THE UDB LENGTH
;HERE WITH P1 = DATA STRUCTURE AND P2 = LENGTH
DIARG2: PUSHJ P,GETWD1## ;GET WORD COUNT WORD
HRRE T2,T1 ;GET STARTING OFFSET
CAIL T2,0 ;RANGE
CAIL T2,(P2) ; CHECK
JRST DIAAIA ;ILLEGAL NUMBER OF ARGUMENTS
SKIPL P3,T1 ;COPY AOBJN POINTER
JRST DIAAIA ;DOESN'T WANT ANY WORDS COPIED??
;NOW RETURN THE REQUESTED WORDS
DIARG3: HRRZ T1,P3 ;GET OFFSET
ADD T1,P1 ;INDEX INTO KDB/UDB
MOVE T1,(T1) ;FETCH A WORD
PUSHJ P,PUTWD1## ;STORE IN USER'S ARGUMENT BLOCK
SOSLE P2 ;END OF KDB/UDB?
AOBJN P3,DIARG3 ;LOOP FOR ALL REQUESTED WORDS
JRST CPOPJ1## ;RETURN
;HERE TO OBTAIN KONTROLLER INFORMATION
DIAKIN: CAIGE P1,4+IFN FTKS10,<1> ;MUST HAVE ROOM FOR RESPONSE
JRST DIAAIA ;ERROR IF NOT
PUSHJ P,GETWD1## ;GET KONTROLLER NAME
MOVE T2,T1 ;POSITION FOR FNDKON
MOVSI T1,-<TYPMAX+1> ;SEARCH ENTIRE TABLE
PUSHJ P,FNDKON ;GET KONTROLLER BY NAME
JRST DIAAIC ;NONESUCH
MOVE T4,KDBDSP(T3) ;GET DRIVER DISPATCH TABLE
LDB T1,[POINTR(DRVCNF(T4),DR.DVT)] ;GET DEVICE TYPE
LSHC T1,-6 ;POSITION FOR CANONICAL RETURN
LDB T1,[POINTR(DRVCF2(T4),DR.KTY)] ;GET KONTROLLER TYPE
LSHC T1,-14 ;POSITION
LDB T1,[POINTR(DRVCF2(T4),DR.DMX)] ;MAX. DRIVES THIS KONTROLLER
LSHC T1,-6 ;POSITION
MOVE T1,KDBCAM(T3) ;GET CPU ACCESSABILITY MASK
LSHC T1,30 ;POSITION
SKIPL KDBUNI(T3) ;IF MULTI-UNIT KON ON CHANNEL,
TLO T1,(1B0) ;NOTE THAT
SKIPE DRVULP(T4) ;IF LOADABLE MICROCODE,
TLO T1,(1B1) ;NOTE THAT
PUSHJ P,PUTWD1## ;STORE INTO USER'S RETURN BLOCK
IFN FTKL10,<
MOVE T1,KDBDVC(T3) ;GET 7-BIT DEVICE CODE
SUBI P1,4 ;OFFSET FOR HOW MANY WORDS WE DO
>
IFN FTKS10,<
MOVE T1,KDBCHN(T3) ;POINT TO CHN DB
MOVE T1,CHNDVC(T1) ;GET DEVICE INFO
LSH T1,-32 ;POSITION IVI
ANDI T1,177 ;MASK TO VALUE WE WANT
SUBI P1,5 ;OFFSET FOR HOW MANY WORDS WE DO
>
SKIPGE T2,KDBUNI(T3) ;GET MASSBUSS UNIT
TDZA T2,T2 ;ZERO IF NOT MULTI-UNIT
HLRZS T2 ;LH QUANTITY
DPB T2,[POINT 3,T1,35-7] ;INCLUDE IN WORD
LSH T1,2 ;MAKE 9-BIT DVC/IVI
PUSHJ P,PUTWD1## ;STUFF INTO USER'S BLOCK
IFN FTKS10,<
MOVE T1,KDBDVC(T3) ;GET CSR (OR OTHER UNIBUS ADDRESS)
PUSHJ P,PUTWD1## ;GIVE THAT TO USER AS WELL
>
DIAKI1: JUMPLE P1,CPOPJ1## ;RETURN SUCCESS AT END OF BLOCK
SETZ T1, ;GET A ZERO
PUSHJ P,PUTWD1## ;STORE IT IN UNUSED WORD
PUSHJ P,SCDCHK## ;DON'T KAF
SOJA P1,DIAKI1 ;CLEAR ALL UNUSED WORDS IN ARG BLOCK
;HERE TO RETURN UNIT INFORMATION
DIAUIN: CAIGE P1,6 ;CAN WE RETURN ALL THE INFO?
JRST DIAAIA ;ERROR IF NOT
PUSHJ P,GETWD1## ;GET NAME OF UDB IN QUESTION
MOVE T4,T1 ;SAVE AGAINST FNDKON
HLLZ T2,T1 ;KEEP LH AS KDB NAME
MOVSI T1,-<TYPMAX+1> ;SEARCH ALL OF KDBTAB
PUSHJ P,FNDKON ;GO FOR IT
JRST DIAAIC ;NO MATCHING KONTROLLER
MOVE T2,KDBIUN(T3) ;START OF UDB TABLE
DIAUI1: SKIPN T1,(T2) ;IS THERE A UDB HERE?
JRST DIAUI2 ;NO, LOOK FOR ANOTHER
CAMN T4,UDBNAM(T1) ;YES, DOES IT MATCH
JRST DIAUI3 ;YES, GO FOR IT
DIAUI2: CAMGE T2,KDBFUN(T3) ;NO, HAVE WE CHECKED THE LAST POSSIBLE UNIT?
AOJA T2,DIAUI1 ;LOOK UNTIL WE HAVE
JRST DIAAIU ;ERROR--ILLEGAL UNIT
DIAUI3: MOVE T4,T1 ;PUT UDB ADDRESS IN BETTER PLACE
PUSHJ P,GETWD1## ;GET AOBJN POINTER TO KONT TABLE
PUSH P,M ;SAVE ARG BLOCK POINTER
HLLZ T2,T1 ;GET -COUNT
CAMGE T2,[-MXPORT,,0] ;WITHIN RANGE?
MOVSI T2,-MXPORT ;ADJUST IT
XMOVEI T3,UDBKDB(T4) ;POINT TO UNIT'S KDB TABLE
HLL T1,T2 ;GET # ENTRIES WE WILL RETURN
PUSHJ P,PUTWDU## ;UPDATE ARG BLOCK
HRRI M,-1(T1) ;SETUP FOR STORING KDB NAMES
DIAUI4: SKIPE T1,(T3) ;GET A KDB ADDRESS
MOVE T1,KDBNAM(T1) ;AND ITS NAME
PUSHJ P,PUTWD1## ;RETURN TO USER
AOS T3 ;ADVANCE POINTER
AOBJN T2,DIAUI4 ;LOOP THROUGH TABLE
POP P,M ;RESTORE ARG BLOCK POINTER
MOVE T1,UDBDSN(T4) ;GET FIRST HALF OF SERIAL NUMBER
PUSHJ P,PUTWD1## ;RETURN IT
MOVE T1,UDBDSN+1(T4) ;SECOND HALF
PUSHJ P,PUTWD1## ;BE COMPLETE
MOVE T1,UDBPDN(T4) ;PHYSICAL DEVICE NUMBER
TSO T1,UDBCAM(T4) ;CPU ACCESS MASK IN LH
PUSHJ P,PUTWD1## ;STORE THAT FOR USER AS WELL
SUBI P1,6 ;OFFSET FOR HOW MANY WE USED
JRST DIAKI1 ;STORE ZEROS IN UNUSED WORDS
;HERE TO RETURN A LIST OF UNITS ON A GIVEN KONTROLLER
DIALKU: CAIGE P1,3 ;ENOUGH FOR KDB NAME AND AT LEAST ONE UNIT?
JRST DIAAIA ;ERROR IF NOT
PUSHJ P,GETWD1## ;GET KDB NAME
MOVE T2,T1 ;COPY ITS NAME
MOVSI T1,-<TYPMAX+1> ;SET TO SEARCH ENTIRE TABLE
PUSHJ P,FNDKON ;FIND DESIRED KDB
JRST DIAAIC ;NONESUCH
MOVE T4,KDBDSP(T3) ;POINT TO DRIVER DISPATCH TABLE
LDB T1,[POINTR(DRVCF2(T4),DR.DMX)] ;MAX. DRIVES ON KONTROLLER
CAIGE P1,2(T1) ;HAVE A BIG ENOUGH ARG. BLOCK?
JRST DIAAIA ;NO, DON'T CAUSE ANY DAMAGE
SETZ T4, ;KEEP A COUNT OF NUMBER OF NAMES WE RETURN
MOVE T2,KDBIUN(T3) ;START OF UDB TABLE
DIALK1: SKIPE T1,(T2) ;GET NEXT UDB POINTER
MOVE T1,UDBNAM(T1) ;AND ITS NAME
JUMPE T1,DIALK2 ;SKIP OVERHEAD IF NONE
AOJ T4, ;COUNT UP ANOTHER NAME
PUSHJ P,PUTWD1## ;STUFF IN USER'S BLOCK
DIALK2: CAMGE T2,KDBFUN(T3) ;WAS THIS THE LAST POSSIBLE UNIT?
AOJA T2,DIALK1 ;LOOP OVER ALL POSSIBLE UNITS
MOVE T1,T4 ;GET NUMBER OF UNIT NAMES STORED
PUSHJ P,STOTAC## ;TELL USER HOW MANY THERE WERE
SUBI P1,2(T4) ;ACCOUNT FOR HOW MANY WE USED
JRST DIAKI1 ;CLEAR OUT REMAINDER AND SUCCEED
;DIAG SUPPORT FOR UNIT RECORD DEVICES
URDDIA::IFIW URDPPR ;PREPROCESSOR ROUTINE
DIAFNC (SDS,URDSDS,URDSDS) ;SET DEVICE STATUS
DIAFNC ;TERMINATE TABLE
URDPPR: JRST (P3) ;GO PROCESS DIAG. UUO
;SET DEVICE STATUS
URDSDS:
IFN FTMP,<
LDB T1,DEYCPU## ;GET CPU FOR TARGET DEVICE
PUSHJ P,ONCPUN## ;PUT US ON THAT CPU
> ;END IFN FTMP
PUSHJ P,GETWD1## ;GET NEXT ARGUMNET
CAIL T1,0 ;RANGE
CAILE T1,SDSLEN ; CHECK
JRST DIAABA ;BAD ARGUMENT LIST
JRST @SDSTAB(T1) ;GO DISPATCH BASED ON SUB-FUNCTION
SDSTAB: IFIW DIAABA ;SET IGNORE (ILLEGAL)
IFIW DIAABA ;CLEAR IGNORE (ILLEGAL)
IFIW DDBDET ;SET DETACHED
IFIW DDBATT ;SET ATTACHED
SDSLEN==.-SDSTAB ;LENGTH OF TABLE
;DISPATCH TABLE FOR DIAG
DEFINE DIAGDS (FLAGS,CODE,ADDR)<
%%FLG==0
IRP FLAGS,<
%%FLG=%%FLG!DI.'FLAGS
>
EXP %%FLG!<<.DI'CODE>B17+ADDR>
>
;FLAG BITS:
DI.KDB==1B0 ;NEEDS KONTROLLER
DI.UDB==1B1 ;NEEDS UNIT
DI.UIO==1B2 ;GIVE USER USER I/O
DI.NVR==1B3 ;USER CAN'T BE VIRTUAL
DI.NON==1B4 ;DON'T BOTHER TO CHECK N
DI.CPU==1B5 ;CPU NUMBER SPECIFIED IN LH OF FNC WORD
DI.DEV==1B6 ;NEEDS SOME SORT OF DEVICE
;NOTE THAT THE DISPATCH ENTRY IS NOT GIVEN FOR DEVICE SPECIFIC FUNCTIONS
DIADST:
IFN FTKL10,<
DIAGDS (<KDB,UDB,UIO,NVR>,ASU,DIADSP) ;ASSIGN UNIT
DIAGDS (<KDB,UDB,UIO,NVR>,AAU,DIADSP) ;ASSIGN ALL UNITS
DIAGDS (<KDB,UDB,UIO,NVR>,RAU,DIADSP) ;RELEASE CHANNEL/KON ALL UNITS
DIAGDS (<KDB,UDB,UIO,NVR>,SCP,DIADSP) ;SPECIFY CHANNEL PROG
DIAGDS (<KDB,UDB,UIO,NVR>,RCP,DIADSP) ;RELEASE CHANNEL PROG
DIAGDS (<KDB,UDB,UIO,NVR>,GCS,DIADSP) ;GET CHANNEL STATUS
DIAGDS (<NON>,AKU,DIAKUN) ;GET KONTROLLER AND UNIT #S
>; END IFN FTKL10
DIAGDS (<NON>,ACS,DIAXSB) ;READ CSB
DIAGDS (<NON>,ADS,DIAXSB) ;READ DSB
IFN FTKL10,<
DIAGDS (<KDB,UDB,UIO,NVR>,SCR,DIADSP) ;CHANNEL PGM FOR READ REVERSE
>; END IFN FTKL10
DIAGDS (<UIO,NON>,GUI,CPOPJ1##) ;GET USER I/O
IFN FTKL10,<
DIAGDS (<KDB,UDB,NON,CPU>,ELD,DIADSP) ;ENABLE MICROCODE LOADING
DIAGDS (<KDB,UDB,NON,CPU>,DLD,DIADSP) ;DISABLE MICROCODE LOADING
DIAGDS (<KDB,UDB,NON,CPU>,LOD,DIADSP) ;LOAD MICROCODE
DIAGDS (<KDB,CPU>,ISM,DIADSP) ;SET IPA CHANNEL MAINT MODE
DIAGDS (<KDB,CPU>,ICM,DIADSP) ;CLEAR IPA CHANNEL MAINT MODE
DIAGDS (<CPU>,SBD,DIASBD) ;EXECUTE SBUS DIAG FUNCTION
DIAGDS (<DEV>,DSN,DIADSN) ;READ DEVICE SERIAL NUMBER
>; END IFN FTKL10
IFN FTKS10,<
DIAGDS (<CPU>,RUR,DIARUR) ;READ UNIBUS REGISTER
>; END IFN FTKS10
IFN FTKL10&<FTSCA!FTENET>,<
DIAGDS (<DEV>,ADB,DIAADB) ;ALLOCATE IPA20 DUMP BUFFER
>; END IFN FTKL10&<FTSCA!FTENET>
DIAGDS (,OKI,DIAKIN) ;OBTAIN KONTROLLER INFO
DIAGDS (,OUI,DIAUIN) ;OBTAIN UNIT INFO
DIAGDS (,LKU,DIALKU) ;LIST KONTROLLER'S UNITS
DIAGDS (<DEV>,SDS,DIADSP) ;SET DEVICE STATUS
DIAGDS (<DEV>,DVR,DIAREG) ;READ DEVICE REGISTERS
IFN FTKL10,<
DIAGDS (<UIO>,GTM,MOSGTM##) ;GET MEMORY
DIAGDS (<UIO,NON>,GVM,MOSGVM##) ;GIVE MEMORY
IFN FTSCA,<
DIAGDS (,RRS,DIARRS##) ;RESET REMOTE SYSTEM
DIAGDS (,SRS,DIASRS##) ;START REMOTE SYSTEM
DIAGDS (<CPU>,ACC,DIACTR##) ;PORT COUNTER FUNCTIONS
DIAGDS (,WCM,DIAWMD##) ;WRITE CI MAINTENANCE DATA
DIAGDS (,RCM,DIARMD##) ;READ CI MAINTENANCE DATA
>; END IFN FTSCA
>; END IFN FTKL10
DIDSLN==.-DIADST ;LENGTH OF TABLE
DEFINE X (COD,VAL),<
ERCODE DIA'COD,VAL
INTERN DIA'COD
>
DIAECD
SUBTTL RECON. UUO - SYSTEM LOGICAL RECONFIGURATION UUO
;THIS UUO PROVIDES THE SUPPORT NECESSARY FOR A USER PROGRAM TO LOGICALLY
; RECONFIGURE THE SYSTEM AND SUSPEND ITS OPERATION TEMPORARLY SO THAT
; OPERATIONS CAN PHYSICALLY RECONFIGURE AND THEN RESUME
;CALLING SEQUENCE:
; MOVE AC,[FUNCTION,,ADDRESS]
; RECON. AC,
; ERROR RETURN
; NORMAL RETURN
RECON: HLRE U,T1 ;FUNCTION
CAML U,[NLRECC] ;IS IT A LEGAL CUSTOMER FUNCTION?
CAILE U,NLRECN ;IS IT LEGAL?
JRST RCNIAL ;ILLEGAL ARGUMENT LIST
PUSHJ P,PRUSET ;GET LENGTH OF ARGUMENT LIST AND CHECK PRIVS
JRST RCNNPV ;NOT PRIVILEGED
JRST @RCNDSP(U) ;DISPATCH
RCNCST: ;CUSTOMER FUNCTIONS GO HERE
RCNDSP: IFIW RCNROM ;(0) RUN ONLY ME
IFIW RCNSPN ;(1) SUSPEND SYSTEM
IFIW RCNCI7 ;(2) TAKE CI7 CONTINUABLE DUMP
IFIW RCNNAR ;(3) SET/CLEAR DF.NAR
IFIW RCNBTX ;(4) SUPPLY NEW VALUE OF BOOTXT
IFIW RCNRLD ;(5) RELOAD THE SYSTEM
IFIW RCNATC ;(6) FORCE AUTCON TO RUN
IFIW CPOPJ## ;(7) DETACH CPU OR DEVICE (OBSOLETE)
IFIW CPOPJ## ;(10) ATTACH CPU OR DEVICE (OBSOETE)
IFIW RCNMOL ;(11) SET MEMORY ON-LINE
IFIW RCNMOF ;(12) SET MEMORY OFF-LINE
IFIW RCNCPU ;(13) FIND CPU MASK FOR A DEVICE
IFIW CPOPJ## ;(14) WAIT FOR ACTIVE I/O TO STOP (OBSOLETE)
IFIW RCNSDF ;(15) SET DUMP/RELOAD FLAGS IN DEBUGF
IFIW RCNCDF ;(16) CLEAR DUMP/RELOAD FLAGS IN DEBUGF
IFIW RCNRBM ;(17) READ BOOTSTRAP MICROCODE INFORMATION
IFIW RCNSBM ;(20) SUPPLY NEW BOOTSTRAP MICROCODE
NLRECN==.-RCNDSP-1
NLRECC==RCNCST-RCNDSP
;ERROR RETURNS
RCIAL%==1
RCNPV%==2
RCNTS%==3
RCNIJ%==4
RCNCD%==5
RCNAC%==6
RCNIS%==7
RCNIC%==10
RCNCR%==11
RCNCA%==12
RCNDS%==13
RCNAA%==14
RCNID%==15
RCNDU%==16
RCNND%==17
RCNNL%==20
RCNMM%==21
RCNTB%==22
RCNLJ%==23
RCNBN%==24
RCNEM%==25
RCMLD%==26
ERCODE RCNIAL,RCIAL% ;ILLEGAL ARGUMENT LIST
ERCODE RCNNPV,RCNPV% ;NOT PRIVILEGED
ERCODE RCNTAS,RCNTS% ;TIME-SHARING ALREADY STOPPED ON SOME CPU
ERCODE RCNIJN,RCNIJ% ;ILLEGAL JOB NUMBER
ERCODE RCNCND,RCNCD% ;SYSTEM CANNOT BE SNAP SHOTTED
ERCODE RCNADC,RCNAC% ;ADDRESS CHECK
ERCODE RCNIST,RCNIS% ;ILLEGAL STRING
ERCODE RCNICN,RCNIC% ;ILLEGAL CPU NUMBER
ERCODE RCNCIR,RCNCR% ;CPU STILL RUNNING
ERCODE RCNCAD,RCNCA% ;CAN'T ATTACH DISK
ERCODE RCNDIS,RCNDS% ;DEVICE IS SPOOLED
ERCODE RCNDAA,RCNAA% ;DEVICE IS ALREADY ATTACHED
ERCODE RCNILD,RCNID% ;ILLEGAL DEVICE
ERCODE RCNDIU,RCNDU% ;DEVICE IN USE
ERCODE RCNCDD,RCNND% ;CAN NOT DETACH DISK
ERCODE RCNLNL,RCNNL% ;LOKCON NOT LOADED
ERCODE RCNRMM,RCNMM% ;REMOVING MONITOR MEMORY
ERCODE RCNJTB,RCNTB% ;JOB(S) TOO BIG
ERCODE RCNMLJ,RCNLJ% ;MOVING LOCKED JOB(S)
ERCODE RCNBNA,RCNBN% ;BOOTSTRAP NOT AVAILABLE
ERCODE RCNNEM,RCNEM% ;NON-EXISTANT MICROCODE
ERCODE RCNMLD,RCMLD% ;MICROCODE LENGTHS DIFFER
;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
PUSHJ P,RECROM ;SET TO "RUN ONLY ME"
JRST RCNTAS ;TIME-SHARING HAS ALREADY BEEN STOPPED
JRST CPOPJ1## ;TELL THE USER THAT HE DID GOOD
;HERE TO SUSPEND THE SYSTEM (FUNCTION 1)
RCNSPN: PUSH P,T1 ;SAVE MONBTS ADDRESS
IFN FTMP,<PUSHJ P,ONCPU0##> ;GET ON THE BOOT CPU
PUSHJ P,RECROM ;SET TO "RUN ONLY ME"
JRST RCNTAS ;NOT MUCH WE CAN DO!
MOVEI T1,[ASCIZ /Expect an interruption of service/]
PUSHJ P,RECSAL ;SEND ALL, BUT DON'T WAIT FOR COMPLETION
MOVEI T1,5 ;SLEEP FOR A BIT
PUSHJ P,SLEEP
PUSHJ P,RCNIOW ;WAIT FOR I/O TO COMPLETE
MOVEI T1,[ASCIZ /Suspending system operation/]
PUSHJ P,RECSAW ;SEND ALL AND WAIT FOR COMPLETION
HRROI T1,[IORM T2,.CPRUN##-.CPCDB##(P1) ;LIGHT SUSPEND BIT
POPJ P,]
MOVSI T2,(CR.SPD) ;GET THE SUSPEND BIT
PUSHJ P,CPUAPP## ;MAKE ALL GO AWAY EXECPT FOR BOOT
PUSHJ P,RCNIOW ;WAIT FOR I/O TO COMPLETE
POP P,T1 ;GET BACK USER AC, WHICH CONTAINS MONBTS ADDR
HRRZM T1,MBTCOM## ;STORE IT INTO THE MONBTS COMMUNICATION AREA
MOVEI T1,SYSRST## ;RESTART ADDRESS
HRRM T1,.JBSA## ;STORE THAT FOR REBOOT
MOVSI T1,(CR.SPD!CR.TSS) ;SUSPEND THIS CPU AND SNAP SHOT BITS
IORM T1,.CPRUN## ;MAKE US GO AWAY AS SOON AS THE NULL JOB RUNS
MOVEI T1,^D10 ;LET THINGS SETTLE DOWN
PUSHJ P,SLEEP ;ZZZZZZ
MOVEI T1,[SETZM .CPSTS##-.CPCDB##(P1) ;CLEAR TIMESHARING STOPPED
POPJ P,]
PUSHJ P,CPUAPP## ;DO IT FOR ALL CPUS
MOVSI T1,(CR.TSS) ;DUMP FAILED BIT
TDNN T1,.CPRUN## ;DID IT FAIL?
JRST RCNSP3 ;SYSTEM WAS RESUMED, GIVE GOOD RETURN TO USER
ANDCAM T1,.CPRUN## ;YES, CANNOT SUSPEND THE SYSTEM
JRST RCNCND ;GIVE THE USER AN ERROR RETURN
RCNSP3: MOVEI T1,[ASCIZ /System resumed/]
AOS (P) ;SET FOR SKIP RETURN
PJRST RECSAL ;SEND ALL, DON'T WAIT FOR COMPLETION
;HERE TO TAKE A CI7 CONTINUABLE DUMP (FUNCTION 2)
RCNCI7: MOVE T1,JBTPPN##(J) ;GET PPN OF JOB
CAME T1,FFAPPN## ;MUST BE 1,2 TO DO THIS
JRST RCNNPV ;NO, NOT PRIVILEGED
MOVSI T1,(DF.RDC!DF.DDC) ;DON'T DO THIS IF WE WILL RELOAD
TDNN T1,DEBUGF## ; ON IT OR IF WE WON'T TAKE THE DUMP
PUSHJ P,BTAVAL## ;IS THE BOOTSTRAP AVAILABLE?
JRST RCNCND ;NO, CAN'T DO IT
STOPCD .+1,DEBUG,CI7, ;++CI7 CONTINUABLE SNAPSHOT DUMP
JRST CPOPJ1## ;GIVE SUCCESS RETURN
;HERE TO SET/CLEAR DF.NAR IN DEBUGF TO ENABLE/DISABLE AUTO RELOADS.
; (FUNCTION 3)
RCNNAR: CAIE T1,2 ;MUST HAVE EXACTLY ONE ARGUMENT
JRST RCNIAL ;ELSE ILLEGAL
PUSHJ P,GETWR1## ;GET THE ARGUMENT
JRST RCNADC ;ADDRESS CHECK
MOVSI T2,(DF.NAR) ;GET THE RELEVANT BIT
SKIPE T1 ;WANT TO SET THE BIT?
IORM T2,DEBUGF## ;YES, DO SO
SKIPN T1 ;WANT TO CLEAR THE BIT?
ANDCAM T2,DEBUGF## ;YES, DO SO
JRST CPOPJ1## ;GIVE SUCCESS RETURN
;HERE TO SPECIFY A NEW BOOTXT STRING (FUNCTION 4)
RCNBTX: SOJLE T1,RCNIAL ;DISCOUNT THIS WORD, CHECK FOR LENGTH ERROR
CAILE T1,BTXLEN## ;IS IT TOO LONG?
JRST RCNIAL ;YES, GIVE ERROR RETURN
PUSHJ P,SAVE3## ;SAVE P1-P3
MOVE P1,T1 ;SAVE +LENGTH FOR FIRST LOOP
MOVN P2,T1 ; AND -LENGTH FOR SECOND LOOP
MOVE P3,M ;SAVE M ALSO
RCNBT1: PUSHJ P,GETWR1## ;GET NEXT WORD IN STRING
JRST RCNADC ;ADDRESS CHECK
MOVE T2,[POINT 7,T1] ;GET BYTE POINTER TO STRING
RCNBT2: ILDB T3,T2 ;GET NEXT BYTE
JUMPE T3,RCNBT3 ;GO IF FOUND THE END
CAIN T3,12 ;ANY LINE FEEDS IN THE STRING?
JRST RCNIST ;YES, CR+LF WILL SCREW UP BOOT (RESTRICT TO CR)
TLNE T2,(76B5) ;DONE WITH THIS WORD YET?
JRST RCNBT2 ;NO, CONTINUE
SOJG P1,RCNBT1 ;YES, GET NEXT WORD
JRST RCNIAL ;SIZE OF STRING WAS WRONG
RCNBT3: SOJN P1,RCNIAL ;SIZE OF STRING WAS WRONG
HRLZ P1,P2 ;MAKE AOBJN POINTER TO STRING WORDS
MOVE M,P3 ;RESTORE M
RCNBT4: PUSHJ P,GETWD1## ;GET NEXT WORD IN STRING
MOVEM T1,BOOTXT##(P1) ;STORE IN MEMORY
AOBJN P1,RCNBT4 ;LOOP FOR ALL WORDS
JRST CPOPJ1## ;GIVE SKIP RETURN
;HERE TO RELOAD THE SYSTEM. (FUNCTION 5)
RCNRLD: MOVE T1,JBTPPN##(J) ;GET PPN OF JOB
CAME T1,FFAPPN## ;MUST BE 1,2 TO DO THIS
JRST RCNNPV ;NO, NOT PRIVILEGED
IFN FTMP,<PUSHJ P,ONCPU0##> ;GET TO THE BOOT CPU (FOR AESTHETIC REASONS)
MOVSI T1,(DF.RIP) ;RELOAD IN PROGRESS
IORM T1,DEBUGF## ;TELL DIE AND REBOOT ABOUT IT
STOPCD .,STOP,RLD, ;++RELOAD MONITOR
;HERE TO FORCE AUTCON TO RUN AND POSSIBLY ADD DEVICES. (FUNCTION 6)
RCNATC: CAIE T1,2 ;MUST BE EXACTLY 1 ARGUMENT
JRST RCNIAL ;ILLEGAL ARGUMENT LIST
PUSHJ P,GETWR1## ;GET CPU NUMBER
JRST RCNADC ;ADDRESS CHECK
CAME T1,[-1] ;ALL CPUS?
CAIG T1,M.CPU## ;NO, A LEGAL CPU?
CAIA ;ALL OR LEGAL
JRST RCNICN ;ILLEGAL CPU SPECIFIED
MOVE T3,T1 ;SAVE CPU ARGUMENT
PUSHJ P,RECROM ;SET "RUN ONLY ME"
JRST RCNTAS ;TIMESHARING ALREADY STOPPED
PUSHJ P,RCNIOW ;WAIT FOR I/O TO STOP
JUMPL T3,RCNAC1 ;GO IF ALL CPUS SPECIFIED
PUSHJ P,SAVE1## ;SAVE AN AC
IMULI T3,.CPLEN## ;OFFSET INTO CDBS FOR THIS CPU
MOVE P1,.C0SLF##(T3) ;CDB FOR SPECIFIED CPU
PUSHJ P,RCNDOA ;AUTOCONFIGURE DEVIECS ON THAT CPU
JRST RCNAC2 ;ONWARD
RCNAC1: MOVEI T1,RCNDOA ;SUBROUTINE TO EXECUTE ACROSS CPUS
PUSHJ P,CPUAPP## ;DO THE AUTOCONFIGURATION ON ALL CPUS
RCNAC2: PUSHJ P,RECCRM ;CLEAR "RUN ONLY ME"
JRST CPOPJ1## ;GOOD RETURN
;SUBROUTINE TO CAUSE AUTCON TO BE RUN ON A SPECIFIED CPU
;CALL WITH P1 = THE CDB ADDRESS FOR THE CPU
RCNDOA:
IFN FTMP,<
MOVE T1,.CPCPN##-.CPCDB##(P1) ;CPU NUMBER
PUSHJ P,ONCPUS## ;GET ONTO THE CORRECT CPU
POPJ P, ;NOOP IF NOT RUNNING
> ;END IFN FTMP
PJRST AUTCPU## ;DO IT
;HERE TO SET MEMORY ON LINE (FUNCTION 11)
RCNMOL: PUSHJ P,RCNMEM ;DO ARGUMENT CHECKING
POPJ P, ;PROPAGATE FAILURE
PUSHJ P,SAVE2## ;SO COMCON WON'T CLOBBER THEM
AOS (P) ;WE WILL SUCCEED
PJRST MEMONU## ;HAVE COMCON PUT THE PAGES ON-LINE
RCNMEM: CAIGE T1,3 ;HAVE ENOUGH ARGUMENTS?
JRST RCNIAL ;NO, ILLEGAL ARGUMENT LIST
PUSHJ P,GETWR1## ;GET FIRST PAGE TO SET ONLINE
JRST RCNADC ;ADDRESS CHECK
MOVE T2,T1 ;SAVE IT
PUSHJ P,GETWR1## ;GET FIRST PAGE TO LEAVE ALONE (LAST PAGE+1)
JRST RCNADC ;ADDRESS CHECK
EXCH T1,T2 ;GET IN RIGHT ORDER
TLNN T1,-1 ;IF EITHER IS RIDICULOUS
TLNE T2,-1 ; ...
JRST RCNIAL ;ILLEGAL ARGUMENT LIST
CAML T1,T2 ;MUST BE IN RIGHT ORDER
JRST RCNIAL ;OR ILLEGAL ARG LIST
JRST CPOPJ1## ;GIVE OK RETURN
;HERE TO SET MEMORY OFF LINE (FUNCTION 12)
RCNMOF: SKIPN [M.LOK##] ;IS LOKCON LOADED?
JRST RCNLNL ;ERROR IF NOT
IFN FTMP,<
PUSHJ P,ONCPU0## ;AVOID POSSIBLE RACE WITH COMCON
>
PUSHJ P,RCNMEM ;CHECK OUR ARG LIST
POPJ P, ;PROPAGATE FAILURE
PUSHJ P,CKMOL## ;CHECK THAT RANGE DOESN'T OVERLAP THE MONITOR
JRST RCNRMM ;IT DOES SO WE CAN'T DO IT
LDB T3,[POINT 14,NWCORE##,26] ;GET TOTAL SIZE (ON OR OFF)
CAIL T1,(T3) ;LOWER BOUND BEYOND END?
JRST CPOPJ1## ;YES, IT'S ALREADY OFF
CAIL T2,(T3) ;UPPER BOUND BEYOND END?
MOVE T2,T3 ;YES,CHANGE UPPER BOUND
PUSH P,T1 ;SAVE LOWER BOUND
PUSH P,T2 ;AND UPPER BOUND
PUSHJ P,NEWCMX## ;SEE IF ALL JOBS CAN CONTINUE TO RUN
JUMPLE T1,[ADJSP P,-2 ;IF .LE. 0, REMOVING MONITOR MEMORY
JRST RCNRMM];GO EXPLAIN THE PROBLEM
PUSH P,J ;SAVE J
MOVEI J,0 ;STARTING WITH JOB 0,
PUSHJ P,JBSTBG## ;MAKE SURE ALL JOBS CAN STILL RUN (I.E., NONE IS TOO BIG)
JRST RCNMF2 ;NONE ARE
POP P,J ;RESTORE J
ADJSP P,-2 ;BALANCE STACK
JRST RCNJTB ;JOB(S) TOO BIG
RCNMF2: MOVEI J,0 ;STARTING WITH JOB 0,
DMOVE T1,-2(P) ;RETRIEVE BOUNDS
PUSHJ P,CKLJB## ;SEE IF RANGE OVERLAPS SOME LOCKED JOB
JRST RCNMF3 ;IT DOESN'T SO ALL IS WELL
POP P,J ;RESTORE J
ADJSP P,-2 ;BALANCE STACK
JRST RCNMLJ ;ERROR IF NEED TO MOVE LOCKED JOB(S)
RCNMF3: POP P,J ;RESTORE J
POP P,T2 ;RESTORE UPPER BOUND
POP P,T1 ;AND LOWER BOUND
AOS (P) ;WILL SUCCEED NOW
PJRST MEMOFU## ;GO SET THE MEMORY OFF-LINE
;HERE TO FIND THE CPU ACCESSABILITY MASK FOR A DEVICE (FUNCTION 13)
RCNCPU: CAIGE T1,2 ;MUST HAVE AT LEAST ANOTHER WORD
JRST RCNIAL ;ILLEGAL ARGUMENT LIST
PUSHJ P,GETWR1## ;GET DEVICE TO DETACH
JRST RCNADC ;ADDRESS CHECK
CAME T1,[SIXBIT /CPU/] ;IS IT GENERIC CPU?
JRST RCNCP1 ;NO, TRY FOR SPECIFIC CPU
IFN FTMP,<
SETZ T2, ;YES, ZERO BIT ACCUMULATION
MOVEI T1,[MOVE T1,.CPRUN##-.CPCDB##(P1) ;GET RUN BITS
TLNN T1,(CR.NRN!CR.RMV!CR.DET!CR.SPD) ;IS IT AVAILABLE?
TDO T2,.CPBIT##-.CPCDB##(P1) ;YES, ADD IN ITS BIT
POPJ P,] ;END OF ROUTINE
PUSHJ P,CPUAPP## ;COLLECT THE BITS FOR ALL RUNNING CPUS
MOVE T1,T2 ;COPY BIT MASK TO RETURN AC
>
IFE FTMP,<
MOVE T1,.CPBIT## ;GET OUR BIT
>
JRST STOTC1## ;RETURN BIT MASK TO USER
RCNCP1: MOVE T2,T1 ;COPY FOR FINDERS
IFN FTMP,<
PUSHJ P,CPUFND## ;IS IT A CPU?
JRST RCNCP2 ;NO, TRY DEVICES
CAIL T1,M.CPU## ;YES, IS IT IN RANGE?
JRST RCNICN ;NO, GIVE ERROR
MOVE T1,T3 ;COPY MASK
ANDI T1,77 ;KEEP ONLY LOW PORTION
>
IFE FTMP,<
MOVE T1,.CPBIT## ;GET OUR BIT (IN CASE IT'S US)
CAME T2,.CPPHY## ;IS IT OUR PHYSICAL NAME?
CAMN T2,.CPLOG## ;OR OUR LOGICAL NAME?
>
JRST STOTC1## ;YES, RETURN ITS BIT TO THE USER
RCNCP2: MOVE T1,T2 ;RESTORE DEVICE NAME
PUSHJ P,DEVPSN ;SEARCH FOR DEVICE
JRST RCNCP4 ;CHECK FOR DISK UNIT ANYWAY
SKIPGE DEVSPL(F) ;SPOOLED?
JRST RCNDIS ;YES, ERROR
MOVE T2,DEVMOD(F) ;CHECK TO SEE IF THIS IS DSK
TLNE T2,DVDSK ;TRYING TO FIND A DISK?
JRST RCNCP4 ;YES, DO IT DIFFERENTLY
IFN FTMP,<
TLNE T2,DVTTY ;TTY?
SKIPN U,DDBLDB##(F) ;YES, GET LDB
JRST RCNC2A ;NOT TTY OR NO LDB, USE DDB
LDB T2,LDPCPU## ;GET OWNING CPU
JRST RCNC2B ;CONTINUE
RCNC2A: LDB T2,DEYCPF## ;GET OWNING CPU NUMBER
CAIE T2,CPFBIT## ;NEED A BIT MASK?
JRST RCNC2B ;NO
LDB T1,PDVTYP## ;GET DEVICE TYPE
CAIE T1,.TYMTA ;MAGTAPE?
STOPCD RCNC2B,DEBUG,NMCPUM, ;++NEED MISSING CPU MASK
SKIPE T1,TDVUDB##(F) ;YES, GET ITS UDB ADDRESS
MOVE T1,UDBCAM(T1) ;AND THE CPU ACCESSABILITY MASK
JRST STOTC1## ;RETURN WINNING MASK TO USER
RCNC2B: MOVEI T1,1 ;GET A BIT
LSH T1,(T2) ;CONVERT TO A MASK
CAIN T2,CPFBOO## ;GENERIC BOOT CPU?
MOVEI T1,77 ;YES, ALL CPUS CAN REACH IT
>
IFE FTMP,<
RCNCP3: MOVEI T1,1 ;BOTTOM BIT ONLY IF NO MP
>
JRST STOTC1## ;RETURN WINNITUDE TO USER
;HERE TO FIND A DSK
RCNCP4: PUSHJ P,SRSTR## ;LOOK FOR A STRUCTURE
JRST RCNCP6 ;NO, TRY FOR A UNIT
IFE FTMP,<
JRST RCNCP3 ;GO WITH CPU0 IF VALID STR
>
IFN FTMP,<
MOVEI T3,77 ;START BY ASSUMING AVAILABLE ON ALL CPUS
RCNCP5: PUSHJ P,GETCAM## ;GET BITS FOR THIS SPINDLE
AND T3,T1 ;STRUCTURES ARE RESTRICTIVELY ACCUMULATED
HLRZ U,UNISTR(U) ;GET NEXT UNIT IN STRUCTURE
JUMPN U,RCNCP5 ;LOOP OVER ALL UNITS IN STR
MOVE T1,T3 ;PUT BITS IN RIGHT AC
JRST STOTC1## ;RETURN BITS WITH WINNITUDE
> ;END OF IFN FTMP
;HERE TO FIND A DISK UNIT
RCNCP6: SETO T2, ;ALLOW ONLY FULL MATCHES, NOT ABBREVIATIONS
PUSHJ P,SRUNA## ;LOOK FOR A MATCHING UNIT
JRST RCNILD ;NOT A DISK, SO IT'S ILLEGAL
JFCL ;LOGICAL MATCH IS OK
IFE FTMP,<
JRST RCNCP3 ;RETURN ONLY CPU IF NO SMP FEATURE
>
IFN FTMP,<
PUSHJ P,GETCAM## ;GET BITS FOR THE SPINDLE (BOTH PORTS)
JRST STOTC1## ;RETURN IT WINNINGLY TO THE USER
>
;HERE TO WAIT FOR ALL I/O ON THE SYSTEM TO CEASE (FUNCTION 14)
RCNIOW::MOVEI F,DEVLST##-DEVSER ;START AT FIRST DDB
RCNIO1: HLRZ F,DEVSER(F) ;STEP TO NEXT DDB
JUMPE F,RCNIO3 ;DONE WITH LOW CORE DDBS
LDB T1,PDVTIM## ;GET HUNG TIMER
JUMPE T1,RCNIO1 ;IGNORE DEVICES WHICH CAN'T HANG
MOVEI T1,IOACT ;I/O ACTIVE BIT
TDNN T1,DEVIOS(F) ;IS IT ON HERE?
JRST RCNIO1 ;NO, KEEP LOOKING
RCNIO2: SETZ T1, ;YES, SET ARGUMENT FOR A TICK
PUSHJ P,SLEEP ;SNOOZE A BIT
JRST RCNIOW ;AND START LOOKING AGAIN
;HERE WHEN NO LOW CORE DDB HAS IOACT LIT
RCNIO3: HLRZ T1,SYSCHN## ;POINT TO FIRST CHANNEL DB ON SYSTEM
RCNIO4: SKIPL CHNBSY(T1) ;IS THIS CHANNEL ACTIVE?
JRST RCNIO2 ;YES, SNOOZE A WHILE
HLRZ T1,CHNSYS(T1) ;NO, POINT TO NEXT DB
JUMPN T1,RCNIO4 ;CHECK ALL CHANNEL DATA BLOCKS FOR BUSY
MOVE T1,[ACTDRB,,ACTDRB] ;WHAT AN EMPTY DRB QUEUE LOOKS LIKE
CAME T1,ACTDRB## ;CI DISK I/O PENDING?
JRST RCNIO2 ;YES--DO IT ALL OVER AGAIN
POPJ P, ;RETURN
;HERE TO SET/CLEAR DUMP/RELOAD BITS IN DEBUGF (FUNCTIONS 15 AND 16)
DFFLGS==DF.RDC!DF.RJE!DF.NAR!DF.CP1!DF.DDC!DF.DJE!DF.DCP ;LEGAL FLAGS TO DIDDLE
RCNSDF: SKIPA P1,[IORB T1,DEBUGF##] ;GET INSTRUCTION TO EXECUTE FOR SET
RCNCDF: MOVE P1,[ANDCAB T1,DEBUGF##] ;GET INSTRUCTION TO EXECUTE FOR CLEAR
CAIE T1,2 ;MUST BE EXACTLY ONE ARGUMENT
JRST RCNIAL ;ILLEGAL ARGUMENT LIST
PUSHJ P,GETWR1## ;GET FLAGS
JRST RCNADC ;ADDRESS CHECK
AND T1,[DFFLGS] ;KEEP JUST LEGAL FLAGS
XCT P1 ;SET/CLEAR THE FLAGS
PJRST STOTC1## ;STORE NEW FLAGS IN AC AND SKIP RETURN
;HERE TO READ BOOTSTRAP MICROCODE INFORMATION
RCNRBM: CAIGE T1,2 ;MUST BE AT LEAST TWO WORDS
JRST RCNIAL ;BAD ARGUMENT LIST LENGTH
PUSHJ P,SAVE3## ;FREE UP SOME AC'S
MOVE P1,T1 ;SAVE ARGUMENT BLOCK LENGTH
PUSHJ P,BTAVAL## ;SEE IF BOOTSTRAP IS AVAILABLE
JRST RCNBNA ;NO
MOVE P2,T2 ;COPY VIRTUAL ADDRESS OF BOOTSTRAP AREA
MOVSI T3,-UCDNUM ;SET TO SCAN FOR EXISTANT MICROCODES
SETZ T1, ; AND COUNT THEM TOO
RCNRB1: SKIPE .BTUCD(T2) ;LENGTH NON-ZERO?
ADDI T1,1 ;YES, MICROCODE EXISTS
ADDI T2,2 ;ADVANCE TO NEXT PAIR OF MICROCODE DESCRIPTORS
AOBJN T3,RCNRB1 ;LOOP FOR MAXIMUM NUMBER OF MICROCODES
PUSHJ P,PUTWR1## ;STORE THE NUMBER OF ENTRIES RETURNED
JRST RCNADC ;ADDRESS CHECK
JUMPE T1,CPOPJ1## ;IF NO MICROCODES, WE'RE DONE
LSH T1,1 ;ACCOUNT FOR TWO-WORD RETURNED DATA PAIRS
CAILE T1,-2(P1) ;DID USER SPECIFY A LONG ENOUGH ARGUMENT LIST?
JRST RCNIAL ;NO, BAD ARGUMENT LIST LENGTH
MOVSI P1,-UCDNUM ;SET TO SCAN THROUGH MICROCODES AGAIN
MOVE P3,P2 ;COPY BOOTSTRAP VECTOR ADDRESS
RCNRB2: SKIPN T1,.BTUCD(P2) ;CHECK LENGTH, DOES MICROCODE EXIST?
JRST RCNRB3 ;NO
HRL T1,P1 ;COPY MICROCODE INDEX
PUSHJ P,PUTWR1## ;STORE IT
JRST RCNADC ;ADDRESS CHECK
MOVE T1,.BTUCD+1(P2) ;GET OFFSET TO MICROCODE DATA
ADD T1,P3 ;GET ACTUAL ADDRESS OF MICROCODE DATA
MOVE T1,(T1) ;GET FIRST WORD (VERSION NUMBER)
PUSHJ P,PUTWR1## ;STORE IT
JRST RCNADC ;ADDRESS CHECK
RCNRB3: ADDI P1,1 ;NEXT MICROCODE INDEX
ADDI P2,2 ;ACCOUNT FOR TWO WORD ENTRIES
AOBJN P1,RCNRB2 ;LOOP FOR REMAINDER OF ENTRIES
JRST CPOPJ1## ;SKIP RETURN
;HERE TO SUPPLY A NEW BOOTSTRAP MICROCODE
RCNSBM: CAIGE T1,3 ;MUST BE AT LEAST THREE WORDS
JRST RCNIAL ;BAD ARGUMENT LIST LENGTH
PUSHJ P,SAVE3## ;FREE UP SOME AC'S
PUSHJ P,BTAVAL## ;SEE IF BOOTSTRAP IS AVAILABLE
JRST RCNBNA ;NO
MOVE P1,T2 ;COPY VIRTUAL ADDRESS OF BOOTSTRAP AREA
PUSHJ P,GETWR1## ;GET NEXT WORD OF BLOCK (UCODE INDEX,,LENGTH)
JRST RCNADC ;ADDRESS CHECK
HLRZ T2,T1 ;COPY UCODE INDEX
ADD T2,P1 ;OFFSET BY BASE OF MICROCODE
SKIPN T3,.BTUCD(T2) ;DOES THIS MICROCODE EXIST (NON-ZERO LENGTH)?
JRST RCNNEM ;NOPE
CAIE T3,(T1) ;LENGTHS MATCH?
JRST RCNMLD ;NOPE
MOVE P3,.BTUCD+1(T2) ;GET OFFSET TO MICROCODE WITHIN BOOTSTRAP
ADD P3,P1 ;INCLUDE BASE OF MICROCODE
MOVE P1,.BTUCD(T2) ;COPY LENGTH OF MICROCODE
PUSHJ P,GETWR1## ;GET NEXT WORD OF BLOCK (ADDRESS OF UCODE DATA)
JRST RCNADC ;ADDRESS CHECK
MOVE P2,T1 ;SET UP FOR AN XBLT
MOVE T2,P1 ;COPY LENGTH OF MICROCODE
PUSHJ P,ARNGE## ;CHECK VALIDITY OF ADDRESSES
JRST RCNADC ;ADDRESS CHECK
JRST RCNADC ;DITTO
DMOVE T1,P1 ;COPY ACS
MOVE T3,P3 ;IN CASE OF KS-10
XBLTUX T1, ;COPY THE MICROCODE
JRST CPOPJ1## ;SKIP RETURN
;ROUTINE TO SET FOR "RUN ONLY ME" FOR RECON. UUO FUNCTIONS
;CALL:
; J/ JOB NUMBER TO "RUN ONLY"
; PUSHJ P,RECROM
; <NON-SKIP> ;TIMESHARING ALREADY STOPPED
; <SKIP> ;TIMESHARING STOPPED FOR ALL BUT SPECIFIED JOB
RECROM::
IFN FTMP,<
PUSHJ P,SBSCD## ;GET SCHEDULAR INTERLOCK (RESTORE ON POPJ)
>; END IFN FTMP
MOVEI T1,[CAME T2,.CPSTS##-.CPCDB##(P1)
SKIPN .CPSTS##-.CPCDB##(P1)
CAIA
SETO T2,
POPJ P,]
MOVE T2,.CPJOB## ;GET JOB NUMBER OF REQUESTOR
PUSHJ P,CPUAPP## ;HAS TIME-SHARING BEEN STOPPED ON ANY CPU?
JUMPL T2,CPOPJ## ;ERROR RETURN IF TIMESHARING ALREADY STOPPED
MOVEI T1,[MOVEM J,.CPSTS##-.CPCDB##(P1)
POPJ P,]
AOS (P) ;SET FOR SKIP RETURN
PJRST CPUAPP## ;MAKE THIS JOB THE ONLY RUNNABLE JOB ON SYSTEM
;ROUTINE TO CLEAR "RUN ONLY ME"
RECCRM::MOVEI T1,[SETZM .CPSTS##-.CPCDB##(P1)
POPJ P,]
PJRST CPUAPP## ;CLEAR "RUN ONLY ME"
;ROUTINES TO DO SEND ALL FOR RECON. UUO FUNCTIONS.
;CALL:
; T1/ TEXT ADDRESS
; PUSHJ P,RECSAL/RECSAW
;RECSAW WAITS FOR THE MESSAGE TO BE OUTPUT BEFORE RETURNING.
;BOTH ROUTINES EXPECT TO BE RUNNING ON BOOT CPU SO SNDCTR IS
;INTERLOCKED WITH RESPECT TO COMCON.
RECSAL: TDZA T2,T2 ;NO WAIT
RECSAW: SETO T2, ;WAIT
PUSH P,T2 ;SAVE THE FLAG
PUSH P,T1 ;SAVE THE TEXT ADDRESS
RECSA1: SKIPN SNDCTR## ;SEND ALL IN PROGRESS?
JRST RECSA2 ;NO
MOVEI T1,1 ;YES, SLEEP FOR A SECOND
PUSHJ P,SLEEP
JRST RECSA1 ;CHECK AGAIN
RECSA2: POP P,T1 ;RESTORE TEXT ADDRESS
PUSHJ P,RECSAX ;DO THE CO-ROUTINE CALL TO FRCSET
POP P,T2 ;GET THE WAIT FLAG
JUMPE T2,CPOPJ## ;RETURN IF NO WAIT FOR OUTPUT NEEDED
RECSA3: MOVEI T1,1 ;SLEEP FOR A SECOND
PUSHJ P,SLEEP
SKIPE SNDCTR## ;SEND ALL COMPLETED?
JRST RECSA3 ;NO, SLEEP A LITTLE LONGER
POPJ P, ;ALL DONE
RECSAX: PUSHJ P,FRCSET## ;SET UP TO TYPE ON FRCLIN
PUSH P,T1 ;SAVE TEXT ADDRESS
PUSHJ P,INLMES## ;INSERT THE "SEND ALL "
ASCIZ /SEND ALL /
POP P,T1 ;RESTORE TEXT ADDRESS
PUSHJ P,CONMES## ;OUTPUT IT
PJRST CRLF## ;APPEND A CRLF AND RETURN
;HERE FROM CLOCK1 WHEN SNAPSHOT HAS BEEN TAKEN TO STICK OUR HEAD IN THE SAND
RMVCPU::
IFN FTKL10,<
IFN FTENET,<
PUSHJ P,KNIRMV## ;ZAP THE KLNI
>; END IFN FTENET
IFN FTSCA,<
PUSHJ P,PPDRMV## ;ZAP THE KLIPA
>; END IFN FTSCA
MOVEI T1,LG.CSL!LG.CSW ;TURN OFF CACHE BITS
ANDCAM T1,.CPEBR## ;FOR 400 RE-START
MOVE F,.CPCPN## ;CPU NUMBER
MOVE F,DTEMAS##(F) ;THE MASTER DTE
PUSHJ P,TTDRLD## ;CLEAR F.E. TTY STATUS
PUSHJ P,SVPPC## ;TURN OFF "KEEP ALIVE"
>
IFN FTKS10,<
PUSHJ P,DISKAL## ;DISABLE KEEP ALIVE
>
PUSHJ P,CSDMP## ;EMPTY CACHE
AOS .CPCSN## ;INSURE SWEEP GETS RECORDED
CONO PI,CLRPIS## ;DON'T MAINTAIN OK WORDS
CONO APR,APRRST## ;BLAST THE PROCESSOR
MOVE 1,.+1 ;GET AN INFINITE LOOP
JRST 1 ;AND DISAPPEAR
SUBTTL CMAND. UUO PLAY WITH USER-DEFINABLE COMMANDS.
CMAND: HLRZ U,T1 ;GET FUNCTION CODE
CAIL U,NLCMDN ;RANGE CHECK
JRST CMDIAL ;BAD FUNCTION CODE
HRR M,T1 ;POINT TO OUR ARGUMENT LIST NOW.
JRST @CMDDSP(U) ;AND DISPATCH
CMDDSP: IFIW CMDINT ;INITIALIZE AND INSERT COMMANDS
IFIW CMDADD ;ADD COMMANDS TO TABLE
IFIW CMDDEL ;DELETE A COMMAND FROM TABLE.
IFIW CMDLST ;LIST COMMAND NAMES
IFIW CMDRET ;RETURN INFORMATION ABOUT A COMMAND
IFIW CMDDMP ;DUMP COMMAND DATA BASE
NLCMDN==.-CMDDSP
;ERROR CODES RETURNED
CMIAL%==1 ;ILLEGAL ARGUMENT LIST
CMADC%==2 ;ADDRESS CHECK
CMNER%==3 ;NOT ENOUGH ROOM IN FUNNY SPACE
CMDNF%==4 ;DID NOT FINISH (NO ROOM IN USER BUFFER)
CMNSN%==5 ;NO SUCH NAME (FOR .CMRET FUNCTION)
ERCODE CMDIAL,CMIAL% ;DEFINE ERROR RETURNS
ERCODE CMDADC,CMADC%
ERCODE CMDNER,CMNER%
ERCODE CMDDNF,CMDNF%
ERCODE CMDNSN,CMNSN%
;BYTE SIZE VALUES FOR .PDUNQ
CM.BSZ==6 ;BYTE SIZE IN BITS
CM.BPW==^D36/CM.BSZ ;NUMBER OF BYTES PER WORD
CM.BP1==CM.BPW-1 ;ROUND-UP VALUE FOR WORDS TO STORE BYTES
CM.BPE==2*CM.BPW+1 ;NUMBER OF BYTES PER COMMAND ENTRY IN TABLE
;SACFLG VALUE FOR COMCON
XP CM.SAC,40 ;AUTO-PUSH COMMAND
;XP CM.???,20 ;FREE BIT
;XP CM.UNQ,17 ;UNIQUENESS BITS
;FUNCTION .CMINI
;DEFINE A NEW COMMAND LIST
CMDINT: PUSHJ P,SAVE1## ;IN CASE RECURSIVE UUO (HA!)
PUSHJ P,RMVCMD ;REMOVE ANY CURRENTLY DEFINED USER COMMANDS
PUSHJ P,CMDCNT ;COUNT NUMBER OF COMMANDS TO DEFINE
POPJ P, ;PROPAGATE ERROR
CMDIN1: JUMPE P1,CPOPJ1 ;IF NO COMMANDS TO DEFINE, RETURN SUCCESS.
PUSHJ P,CMDCOR ;GET CORE FOR OUR FREECORE DIRECTORY.
POPJ P,
PUSHJ P,CMDINS ;AND ADD COMMANDS SUPPLIED IN THIS UUO
POPJ P, ;PROPAGATE ERROR.
RETSKP ;RETURN SUCCESS.
;FUNCTION .CMADD
;UUO FUNCTION TO ADD COMMANDS TO OUR LIST.
CMDADD: PUSHJ P,SAVE1## ;AVOID TRASHING A MONITOR UUO.
PUSHJ P,CMDCNT ;COUNT NUMBER OF COMMANDS TO ADD
POPJ P, ;HMM. MUST HAVE HAD A BUM ADDRESS
SETZ T1, ;START COUNTING FROM 0
SKIPN T2,.PDCMN##(W) ;GET POINTER TO COMMAND NAMES
JRST CMDIN1 ;NONE DEFINED. CALL THE DEFINE CODE.
CMDAD1: SKIPN (T2) ;IS THIS COMMAND DEFINED?
AOJ T1, ;NO, BUMP COUNT OF AVAILABLE COMMANDS.
AOBJN T2,CMDAD1 ;AND CONTINUE FOR ALL COMMANDS IN DIRECTORY.
CAMG P1,T1 ;DO WE HAVE ENOUGH ROOM TO DEFINE COMMANDS?
JRST CMDAD4 ;YES, JUST ADD THEM.
HLRO T2,.PDCMN##(W) ;GET NEGATIVE SIZE OF CURRENT COMMAND DIRECTORY
ADD T2,T1 ;CONVERT TO NEGATIVE NUMBER OF COMMANDS TAKEN
SUB P1,T2 ;TOTAL NUMBER OF COMMANDS WE WILL NEED.
PUSHJ P,CMDXPN ;NOT ENOUGH ROOM, EXPAND OUR DIRECTORY.
POPJ P, ;PROPAGATE ERROR.
CMDAD4: PJRST CMDINS ;AND INSERT OUR COMMANDS
;FUNCTION .CMDEL
;DELETE COMMANDS
CMDDEL: PUSHJ P,SAVE4##
PUSHJ P,GETWRD## ;GET NUMBER OF COMMANDS TO DELETE
JRST CMDADC ;BLOW UP
MOVE P1,T1 ;COPY NUMBER OF COMMANDS TO DO
CMDDE1: SOJLE P1,CPOPJ1## ;RETURN SUCCESS.
PUSHJ P,GETWR1## ;GET NEXT COMMAND NAME TO DELETE
JRST CMDADC ;BAD ADDRESS
PUSHJ P,CMDINI ;INITIALIZE POINTERS
JUMPE P2,CMDDE1 ;IF NO COMMANDS, DON'T TRY SEARCHING
JUMPE T1,CMDDE1 ;IF NULL COMMAND, PUNT
CMDDE2: CAME T1,(P2) ;IS THIS THE COMMAND WE WANT?
JRST CMDDE3 ;NOPE, TRY FOR NEXT ONE
PUSHJ P,CMDREM ;REMOVE IT.
CMDDE3: PUSHJ P,CMDADV ;ADVANCE POINTERS
JRST CMDDE2 ;AND TRY NEXT LOCATION IN COMMAND DIRECTORY
JRST CMDDE1 ;AND DO THE NEXT COMMAND HE SUPPLIED US WITH
;FUNCTION .CMLST
;LIST THE COMMAND NAMES WE HAVE DEFINED. SUITABLE FOR USE BY "HELP" IN
;INFORMING THE USER SIMPLY THE NAMES AND NUMBER OF COMMANDS HE HAS DEFINED.
CMDLST: PUSHJ P,SAVE4## ;SINCE CMDINI TRASHES ALL 4 P REGISTERS
SETZ P1, ;START WITH ZERO COMMANDS
PUSHJ P,CMDINI ;INITIALIZE POINTERS TO COMMAND LISTS
JUMPE P2,CMDLS4 ;IF NO COMMANDS, DON'T COUNT EM
CMDLS1: SKIPE (P2) ;DO WE HAVE A COMMAND NAME DEFINED?
SKIPN (P3) ;AND DO WE HAVE A POINTER TO A COMMAND BLOCK?
SKIPA ;NO, DON'T COUNT THIS COMMAND
AOJ P1, ;INCREMENT NUMBER OF COMMANDS WE HAVE FOUND
PUSHJ P,CMDADV ;ADVANCE TO NEXT COMMAND POINTER
JRST CMDLS1 ;AND GO TRY TO COUNT ANOTHER COMMAND
CMDLS4: PUSHJ P,GETWRD## ;FIND OUT HOW MANY WORDS HE HAS ALLOCATED FOR US
JRST CMDADC ;ADDRESS CHECK.
EXCH T1,P1 ;SAVE NUMBER OF WORDS WE ARE ALLOWED
PUSHJ P,PUTWRD## ;TELL THE USER HOW MANY COMMANDS WE HAVE
JRST CMDADC ;ADDRESS CHECK, TELL HIM NOT TO USE HISEG
PUSHJ P,CMDINI ;RE-INITIALIZE POINTERS TO COMMANDS
JUMPE P2,CPOPJ1## ;IF NO COMMANDS, RETURN
CMDLS2: SKIPE T1,(P2) ;DO WE HAVE A COMMAND NAME DEFINED?
SKIPN (P3) ;AND DOES IT HAVE A POINTER TO A COMMAND BLOCK
JRST CMDLS3 ;NO, SKIP IT
PUSHJ P,CMDPUT ;PUT THIS COMMAND NAME IN HIS BLOCK
POPJ P, ;PROPAGATE ERROR
CMDLS3: PUSHJ P,CMDADV ;ADVANCE TO NEXT COMMAND
JRST CMDLS2 ;AND GO GET THE NEXT NAME TO STORE
RETSKP ;RETURN SUCCESS, WE HAVE GIVEN HIM ALL NAMES
;FUNCTION .CMRET
;RETURN INFORMATION ON A SINGLE COMMAND
CMDRET: PUSHJ P,SAVE4## ;SINCE CMDINI DESTROYS ALL P ACS
PUSHJ P,GETWRD## ;GET NUMBER OF WORDS WE ARE ALLOWED TO RETURN
JRST CMDADC ;BOGUS ADDRESS
MOVE P1,T1 ;SAVE NUMBER OR WORDS WE ARE ALLOWED
HRRZ T1,M ;FIRST ADDRESS WE ARE GOING TO RETURN TO
HRLI T1,(IFIW) ;MAKE SECTION RELATIVE
MOVE T2,P1 ;GET WORD COUNT
PUSHJ P,ARNGE## ;RANGE CHECK ARGUMENTS
JRST CMDADC ;ADDRESS CHECK
JFCL ;ADDRESS OK BUT ILLEGAL FOR I/O (IGNORED HERE)
PUSHJ P,GETWR1## ;GET NEXT WORD (NAME TO SEARCH FOR)
JRST CMDADC ;ADDRESS CHECK
SUBI M,2 ;SO THAT WE CAN OVERWRITE THESE ARGUMENTS
PUSHJ P,CMDINI ;INITIALIZE COMMAND TABLE POINTERS
JUMPE P2,CMDNSN ;IF NO COMMANDS, WE AREN'T GOING TO FIND IT
CMDRE2: CAMN T1,(P2) ;IS THIS THE COMMAND WE ARE LOOKING FOR?
JRST [SKIPN U,(P3) ;DOES IT HAVE A BLOCK POINTER?
JRST .+1 ;NOPE, IGNORE IT
JRST CMDCRT] ;AND LIST THE COMMAND INTO HIS BUFFER
PUSHJ P,CMDADV ;NO, ADVANCE TO NEXT COMMAND
JRST CMDRE2 ;AND LOOK FOR NEXT COMMAND
JRST CMDNSN ;NO SUCH COMMAND NAME
;FUNCTION .CMDMP
;DUMP THE COMMAND DATA BASE. SUITABLE FOR READING/RESTORING AN ENTIRE
;COMMAND DATA BASE ACROSS LOGINS.
CMDDMP: PUSHJ P,SAVE4## ;AVOID TRASHING A MONITOR UUO
PUSHJ P,GETWRD## ;GET NUMBER OF WORDS WE ARE ALLOWED TO RETURN
JRST CMDADC ;HE GAVE US A TURKEY ADDRESS.
MOVE P1,T1 ;SAVE NUMBER OF WORDS WE ARE ALLOWED TO RETURN
HRRZ T1,M ;FIRST ADDRESS WE ARE GOING TO RETURN STUFF TO.
HRLI T1,(IFIW) ;MAKE SECTION RELATIVE
MOVE T2,P1 ;GET WORD COUNT
PUSHJ P,ARNGE## ;RANGE CHECK ARGUMENTS
JRST CMDADC ;ADDRESS CHECK
JFCL ;ADDRESS OK BUT ILLEGAL FOR I/O (IGNORED HERE)
SUBI M,1 ;SINCE WE DO PUTWD1'S LATER
PUSHJ P,CMDINI ;INITIALIZE POINTERS
JUMPE P2,CMDDM9 ;IF NO COMMANDS, TELL HIM THAT.
CMDDM1: SKIPE (P2) ;DO WE HAVE A COMMAND DEFINED?
SKIPN U,(P3) ;GET POINTER TO THIS COMMAND'S BLOCK
JRST CMDDM8 ;NO COMMAND, TRY FOR NEXT COMMAND
PUSHJ P,CMDCRT ;RETURN THIS COMMAND TO USER'S BUFFER
POPJ P, ;HMM. MUSTA RUN OUTA BUFFER SPACE
CMDDM8: PUSHJ P,CMDADV ;ADVANCE POINTERS
JRST CMDDM1 ;AND RETURN NEXT COMMAND
CMDDM9: SETZ T1, ;A ZERO WORD TERMINATOR
PUSHJ P,CMDPUT ;TERMINATE LIST OF COMMANDS
POPJ P, ;WHAT TERRIBLE LUCK!
RETSKP
;UTILITY ROUTINES, CALLED BY ABOVE FUNCTIONS
;RETURN A COMMAND TO USER'S BUFFER.
;ARGS
;P1/ NUMBER OF WORDS LEFT IN USERS BUFFER
;P2-P4/ AS SET UP BY CMDINI AND CMDADV
CMDCRT: MOVE T4,(U) ;GET NUMBER OF WORDS IN OUR BLOCK
MOVEI T1,1(T4) ;MAKE IT NUMBER OF WORDS USER UNDERSTANDS
LDB T2,P4 ;GET UNIQUENESS BITS
HRL T1,T2 ;MAKE IT THE FLAGS IN LEFT HALF
PUSHJ P,CMDPUT ;PUT THIS WORD IN USER'S BUFFER
POPJ P, ;HMM. WE JUST RAN OUT OF ROOM.
MOVE T1,(P2) ;GET COMMAND NAME
PUSHJ P,CMDPUT ;PUT IT IN THE USER'S BUFFER
POPJ P, ;RAN OUT OF ROOM.
SUBI T4,1 ;DECREMENT NUMBER OF WORDS LEFT TO GO
CMDCR3: ADDI U,1 ;POINT TO NEXT WORD IN COMMAND BLOCK
MOVE T1,(U) ;GET WORD FROM COMMAND BLOCK
PUSHJ P,CMDPUT ;AND PUT IT IN USER'S BLOCK
POPJ P,
SOJG T4,CMDCR3 ;DO UNTIL FINISHED THIS BLOCK
RETSKP ;RETURN INDICATING THAT IT FIT.
;PUT WORDS INTO USER'S BUFFER, CHECKING TO MAKE SURE THEY FIT.
;PRESERVES THE T ACS, MODIFIES M AND P1
CMDPUT: PUSHJ P,SAVT## ;AVOID TRASHING T ACS
SOJLE P1,CMDDNF ;MAKE SURE WE CAN FIT THIS IN USER'S BUFFER
PUSHJ P,PUTWR1## ;PUT THIS IN NEXT WORD OF USER'S BUFFER
JRST CMDADC ;ADDRESS CHECK
RETSKP ;RETURN SUCCESS
;REMOVE A COMMAND FROM TABLES.
;CALL WITH (P2)NAME, (P3)DISPATCH, P4/BPT TO UNIQNESS
CMDREM: SETZB T2,(P2) ;YUP, WIPE COMMAND NAME
EXCH T2,(P3) ;WIPE DISPATCH POINTER
HRRZ T1,(T2) ;GET NUMBER OF WORDS IN ENTRY
PUSHJ P,GVFWDS## ;RETURN THE FUNNY SPACE
SETZ T2, ;CLEAR AGAIN.
DPB T2,P4 ;AND WIPE UNIQUENESS BITS (JUST FOR GRINS)
POPJ P, ;AND RETURN.
;ADVANCE POINTERS TO NEXT COMMAND. MADE INTO ROUTINE TO GUARANTEE EVERYONE
;USES SAME PROCEDURE.
CMDADV: AOJ P3, ;INCREMENT POINTER TO DISPATCH
IBP P4 ;INCREMENT UNIQUENESS POINTER
AOBJN P2,CPOPJ ;RETURN NON SKIP IF STILL THINGS TO LOOK AT
RETSKP ;NOTHING MORE TO LOOK AT. SKIP RETURN.
;INITIALIZE POINTERS FOR ABOVE. SETS UP P2,P3,P4
;CHECK FOR P2=0 TO INDICATE NO COMMAND DATA BASE
CMDINI: MOVE P2,.PDCMN##(W) ;GET POINTER TO COMMAND NAMES
HRRZ P3,.PDUNQ##(W) ;GET POINTER TO COMMAND DISPATCHES
HRLI P4,(POINT CM.BSZ,,CM.BSZ-1) ;BYTE POINTER FOR UNIQUENESS BITS
HLR P4,.PDUNQ##(W) ;GET POINTER TO OUR TABLE OF UNIQUENESS
POPJ P,
;EXPAND COMMAND DIRECTORY. NEW NUMBER OF COMMANDS IN P1.
CMDXPN: PUSHJ P,SAVE2## ;AVOID TRASHING OUR TOP LEVEL
MOVE P2,.PDCMN##(W) ;SAVE A POINTER TO CURRENT COMMAND LIST
PUSHJ P,CMDCOR ;AND ALLOCATE MORE CORE.
POPJ P, ;PROPAGATE THIS ERROR.
HLRO T3,P2 ;MINUS NUMBER OF COMMAND SLOTS WE USED TO HAVE
MOVNS T3 ;NUMBER OF COMMAND SLOTS
HRL T1,P2 ;POINTER TO OLD COMMAND DIRECTORY
HRR T1,.PDCMN##(W) ;POINTER TO NEW COMMAND DIRECTORY
MOVE T2,T3 ;COPY NUMBER OF COMMANDS TO COPY
ADDI T2,(T1) ;POINTER TO FIRST WORD BEYOND THESE COMMANDS.
BLT T1,-1(T2) ;COPY OLD COMMANDS TO NEW TABLE.
HRR T1,.PDUNQ##(W) ;POINTER TO NEW DISPATCHES TABLE
HRRZ T2,T1 ;DESTINATION FOR BLT
ADD T2,T3 ;POINT TO FIRST WORD BEYOND DISPATCHES.
BLT T1,-1(T2) ;COPY NEW DISPATCHES.
IDIVI T3,CM.BPW ;NUMBER OF WORDS IN UNQTAB
HLR T1,.PDUNQ##(W) ;NEW POINTER TO UNQTAB
HRRZ T2,T1 ;DESTINATION FOR BLT
ADD T2,T3 ;POINT TO FIRST WORD BEYOND UNQTAB
BLT T1,-1(T2) ;AND COPY THE UNQTAB DATA
IMULI T3,CM.BPE ;NUMBER OF WORDS FOR USED FOR ENTIRE TABLE
MOVE T1,T3 ;COPY NUMBER OF WORDS TO RETURN
HRRZ T2,P2 ;WHERE OUR TABLE IS
PUSHJ P,GVFWDS## ;AND RETURN FUNNY FOR OLD COMMAND DIRECTORY
RETSKP ;RETURN SUCCESS
;ALLOCATE CORE FOR COMMANDS DIRECTORY. RETURNS WITH .PDCMN AND .PDUNQ SET UP
;AND ALL COMMAND NAMES SET TO ZERO.
CMDCOR: PUSHJ P,SAVE2## ;PRESERVE P ACS
MOVEI T2,CM.BP1(P1) ;NUMBER OF COMMANDS TO DEFINE (ROUNDING UP)
IDIVI T2,CM.BPW ;NUMBER OF WORDS IN UNQTAB
MOVE P2,T2
IMULI T2,CM.BPW ;NUMBER OF WORDS FOR OUR TABLES (MULTIPLE OF 6)
MOVE P1,T2
ASH T2,1 ;NUMBER OF WORDS FOR NAMES+DISPATCH
ADD T2,P2 ;ADD IN NUMBER OF WORDS FOR UNQTAB
PUSHJ P,GTFWDC## ;GET CACHED FUNNY SPACE.
JRST CMDNER ;NOT ENOUGH ROOM.
MOVE T2,T1 ;POINTER TO COMMAND NAMES
ADD T2,P1 ;POINTER TO COMMAND DISPATCHES
MOVEI T3,1(T1) ;MAKE A BLT POINTER TOWARDS NAMES
HRL T3,T1 ;LEFT HALF OF BLT POINTER
SETZM (T1) ;CLEAR FIRST WORD OF COMMAND NAMES
BLT T3,-1(T2) ;AND ALL THE REST OF THE WORDS TOO.
MOVN T3,P1 ;NEGATIVE NUMBER OF COMMANDS ALLOWED IN LIST
HRL T1,T3 ;MAKE AN AOBJN POINTER TO COMMANDS
MOVE T3,T2 ;POINTER TO COMMAND DISPATCHES
ADD T3,P1 ;POINTER TO COMMAND UNQTAB
HRL T2,T3
MOVEM T2,.PDUNQ##(W) ;SAVE POINTERS (NOTE ORDER: .PDCMN CAN'T BE
MOVEM T1,.PDCMN##(W) ; SAVED UNTIL .PDUNQ IS SET UP)
RETSKP
;INSERT COMMANDS SUPPLIED BY UUO TO OUR LIST OF USER DEFINED COMMANDS. IT IS
;THE RESPONSOBILITY OF THE CALLER TO INSURE THAT THERE ARE ENOUGH AVAILABLE
;COMMAND SLOTS IN THE COMMAND DIRECTORY (.PDCMN).
CMDINS: PUSHJ P,SAVE4## ;AVOID TRASHING ACS.
PUSHJ P,CMDINI ;INITIALIZE POINTERS
CMDIN2: UMOVE U,(M) ;GET LENGTH OF COMMAND ENTRY
JUMPE U,CPOPJ1 ;AT END, EXIT.
UMOVE P1,1(M) ;GET COMMAND NAME
JUMPE P1,CMDIN6 ;IF NO COMMAND NAME, PITCH IT.
CMDI25: CAMN P1,(P2) ;IS THIS THE SAME COMMAND AS OURS?
JRST CMDIN4 ;YES, USE IT.
PUSHJ P,CMDADV ;ADVANCE POINTERS
JRST CMDI25 ;AND TRY FOR ANOTHER COMMAND
PUSHJ P,CMDINI ;INITIALIZE POINTERS AGAIN
CMDIN3: SKIPN (P2) ;IS THIS COMMAND NAME TAKEN?
JRST CMDIN5 ;NO, CONTINUE
PUSHJ P,CMDADV ;ADVANCE POINTERS
JRST CMDIN3 ;AND TRY FOR ANOTHER SLOT
STOPCD RMVCMD,DEBUG,NCE ;++NO COMMAND SLOT AVAILABLE.
CMDIN4: PUSHJ P,CMDREM ;REMOVE THIS COMMAND
CMDIN5: HLRZ T1,U ;GET UNIQNESS BITS
DPB T1,P4 ;STORE FOR THIS COMMAND
HRRZS U ;CLEAR FLAGS
CAIGE U,3 ;MUST CONTAIN AT LEAST UP TO .CMFIL
JRST CMDIAL ;ILLEGAL ARGUMENT LIST.
SOS T2,U ;OUR TABLE IS ONE WORD SHORTER THAN USER'S
PUSHJ P,GTFWDC## ;GET SOME CACHED FREESPACE
JRST CMDNER ;NO MORE ROOM
MOVEM T1,(P3) ;SAVE POINTER TO THIS BLOCK
HRRZM U,(T1) ;SAVE LENGTH IN BLOCK
MOVEI T2,1(T1) ;DESTINATION OF THIS BLOCK
HRLI T2,2(M) ;SOURCE FROM USER
ADDI T1,-1(U) ;POINT TO LAST WORD IN OUR BLOCK
EXCTUX <BLT T2,(T1)> ;AND COPY OUR DATA
MOVEM P1,(P2) ;AND NOW SAVE THE COMMAND NAME
CMDIN6: ADDI M,1(U) ;POINT PAST THIS COMMAND
JRST CMDIN2 ;AND ADD THE NEXT COMMAND
;COUNT COMMANDS SUPPLIED IN UUO. RETURNS NUMBER OF COMMANDS TO DEFINE IN P1
CMDCNT: SETZ P1, ;START WITH 0 COMMANDS COUNTED.
PUSHJ P,SAVUM## ;SAVE M (U AND W GO ALONG FOR THE RIDE)
CMDCN1: PUSHJ P,GETWRD## ;GET FIRST WORD OF ARGUMENT (LENGTH)
JRST CMDADC ;ADDRESS CHECK.
JUMPE T1,CPOPJ1## ;END OF LIST, GET CORE TO STORE THESE IN.
HRRZS T1 ;CLEAR FLAGS AWAY THIS TIME.
CAIL T1,4 ;MUST CONTAIN UP TO THE FILENAME
CAILE T1,MAXLVL##+6 ;SFDS+PPN+EXT+NAME+DEV+COMMAND+FLAGS
JRST CMDIAL ;ILLEGAL ADDRESS LIST
MOVE T2,T1 ;SAVE LENGTH
ADDI M,2 ;POINT TO NAME OF COMMAND
PUSHJ P,GETWRD## ;GET COMMAND NAME
JRST CMDADC ;ADDR CHECK
JUMPE T1,CMDIAL ;MUST HAVE A NAME
ADDI M,-2(T2) ;POINT TO NEXT COMAND BLOCK
AOJA P1,CMDCN1 ;AND FIND ANOTHER COMMAND
;REMOVE ALL COMMANDS.
RMVCMD:
PUSHJ P,SAVE4## ;WE USE P1 AND P2
PUSHJ P,CMDINI ;INITIALIZE POINTERS
JUMPE P2,CPOPJ## ;IF NO POINTER TO NAMES, SUCCESS
RMVCM1: SKIPE (P2) ;ZERO OUT THE COMMAND NAME FIRST
SKIPN T2,(P3) ;AND GET POINTER TO THE FILESPEC BLOCK
JRST RMVCM2 ;NO NAME OR POINTER, IGNORE THIS COMMAND
PUSHJ P,CMDREM ;REMOVE THIS COMMAND
RMVCM2: PUSHJ P,CMDADV ;ADVANCE POINTERS
JRST RMVCM1 ;AND DO ANOTHER COMMAND
HLRO T1,.PDCMN##(W) ;GET NUMBER OF ENTRIES
IMUL T1,[-CM.BPE] ;CONVERT TO POSITIVE NUMBER OF 6 BIT BYTES
ADDI T1,CM.BP1 ;ROUND UP TO NEAREST WORD
IDIVI T1,CM.BPW ;AND CONVERT BACK DOWN TO NUMBER OF WORDS
HRRZ T2,.PDCMN##(W) ;GET POINTER TO TABLE
PUSHJ P,GVFWDS## ;AND RETURN THE TABLES THEMSELVES.
SETZM .PDCMN##(W) ;WIPE POINTER TO COMMAND NAMES
SETZM .PDUNQ##(W) ;AND POINTER TO UNQTAB AND DISPATCHES
POPJ P,
SUBTTL CALLS TO SEGCON FOR SETUWP AND REMAP
;SET OR CLEAR USER MODE WRITE PROTECT BIT IN HIGH SEG FOR THIS USER ONLY
;CALL: MOVEI AC,0 OR 1
; CALL AC,[SIXBIT /SETUWP/] OR CALLI AC,34
; ERROR - MACHINE OR MONITOR CANNOT HANDLE TWO REG, OR TRYING TO CLEAR
; ;UWP OF A SHARABLE SEG(AC=1 ON RETURN)
; OK RETURN - AC CONTAINS PREVIOUS SETTING( OR JOB HAS NO HIGH SEG)
SETUWP=USTUWP## ;GO TO ROUTINE IN SEGCON
;IF FT2REL=0, SETUWP DOES RTZER
;UUO TO REMAP TOP PART OF LOW SEGMENT INTO HIGH SEGMENT
;PREVIOUS HIGH SEG(IF ANY) IS KILLED AND A NEW SEGMENT NUMBER IS ASSIGNED
;TO THIS JOB. REMAP IS USED BY LOADER AND GET
;CALL: MOVEI AC,NEW HIGHEST USER ADR IN LOW SEG(EXEC ORS IN 1777)
; CALL AC,[SIXBIT /REMAP/] OR CALLI AC,35
; ERROR RETURN, MACHINE OR EXEC CANNOT HANDLE 2 REG OR DESIRED ADR
; ;GREATER THAN OLD LOW SEG
; OK RETURN, LOW SEG ABOVE ARG NOW THE HIGH SEG
REMAP=UREMAP## ;CORE1 MODULE IN SEGCON
SUBTTL TRIVIAL UUOS (LIGHTS, TIMER AND SWITCH)
;SET LIGHTS ON CONSOLE FROM USER PROGRAM
;CALL AC,[SIXBIT /DATAO/] OR CALLI AC,-1
;THIS IS AN EXAMPLE OF A USER DEFINED UUO WITH A NEGATIVE CALLI ARG.
LIGHTS:
POPJ P, ;RETURN TO HIM
;RETURN TIME OF DAY IN JIFFIES (60THS,50THS OR MS)
TIMER: SKIPA T1,TIME## ;FALL INTO STOTAC
;RETURN DATA SWITCHES
SWITCH: SETZ T1, ;RETURN ZERO
JRST STOTAC## ;GO STORE VALUE
SUBTTL ENTVC. UUO
;THE ENTVC. UUO SETS OR RETURNS THE PROGRAMS CURRENT ENTRY VECTOR
;CALLING SEQUENCE:
; XMOVEI AC,ADDR
; ENTVC. AC,
; <ERROR RETURN>
; <NORMAL RETURN>
; ...
;ADDR/ FUNCTION ;READ OR SET (SIGN BIT ON MEANS SET)
;ADDR+1/LENGTH ;(JRST) OR 0-N (WHERE N IS .LE.37)
;ADDR+2/EXEC-ADDR ;30 BIT ADDRESS OF ENTRY VECTOR OR START ADDRESS
; ; IF LENGTH = 0 OR (JRST)
;
ENTVC: PUSHJ P,SAVE4## ;SAVE SOME ACS
MOVEI T2,3 ;WANT THREE WORDS OF ARG LIST
PUSHJ P,ARNGE## ;SEE IF THE LIST IS WELL-FORMED
JRST ENVADC ;NO
JFCL ;IGNORE I/O ILLEGAL HERE
PUSHJ P,SXPCS## ;MAKE SURE THE REFERENCES WILL WORK
JRST ENVADC ;ADDRESS CHECK
SKIPL T1 ;IF GLOBAL,
SOSA T1 ;PRE-DECREMENT GLOBALLY
HRRI T1,-1(T1) ;ELSE LOCALLY
MOVE M,T1 ;POINT AT ARGUMENT LIST (PREDECREMENTED)
MOVSI P4,-3 ;FETCH 3 ARGS INTO P1-P3
ENTVC1: PUSHJ P,GETEW1## ;GET NEXT ARG
JRST ENVADC ;ADDRESS CHECK
MOVEM T1,P1(P4) ;STORE ARGUMENT IN AN AC
AOBJN P4,ENTVC1 ;FETCH ALL 3 ARGUMENTS
SKIPN P2 ;LENGTH = 0?
MOVEI P2,(JRST) ;YES, SUBSTITUTE (JRST)
HRRZ T1,P1 ;FUNCTION CODE
JUMPN T1,ENVIFC ;ONLY FUNCTION 0 IS DEFINED FOR NOW
TLNE P1,377777 ;ANY UNKNOWN BITS?
JRST ENVIAL ;ILLEGAL ARG LIST
JUMPL P1,ENTVC4 ;GO IF SET FUNCTION
;HERE TO READ THE ENTRY VECTOR
SKIPE P3,.USUSA ;ENTRY VECTOR SETUP?
JRST ENTVC2 ;YES
MOVEI P2,(JRST) ;NO, JUST RETURN STARTING ADDRESS
SKIPE P3,.USUSN ;INCLUDING SECTION IF APPLICABLE
LSH P3,P2WLSH ; ..
HRR P3,.JDAT+.JBSA##; ..
TRNN P3,-1 ;EXCEPT IF NO START ADDRESS,
SETZB P2,P3 ;THEN THERE'S NOTHING AT ALL
JRST ENTVC3 ;STORE THE ANSWERS AND RETURN
ENTVC2: LDB P2,[POINT 5,P3,5] ;LENGTH
TLZ P3,(77B5) ;VIRTUAL ADDRESS OF THE ENTRY VECTOR
JUMPN P2,ENTVC3 ;RETURN ANSWER IF HAVE A REAL LENGTH
MOVEI P2,(JRST) ;NO, ADMIT TO START ADDRESS FORMAT
CAIN P3,1 ;IF SPECIAL FOR S0,
SETZ P3, ;WE HAVE NO ADDRESS
TRNE P3,-1 ;IF HAVE AN ADDRESS TO USE,
JRST ENTVC3 ;THEN USE IT
PUSH P,M ;NO, SAVE USER ADDRESS
HLLZ M,P3 ;GET SECTION FOR REFERENCE
HRRI M,.JBSA## ;USE ITS JOBDAT
PUSHJ P,PFHMWD## ;FETCH START ADDRESS
SETZ T1, ;GOT NOTHING
TLZ T1,-1 ;IGNORE JOBFF
SKIPN P3,T1 ;UPDATE IF HAVE A VALUE
TDZA P2,P2 ;NO, ZERO THE LENGTH AFTER ALL
HLL P3,M ;YES, RETRIEVE SECTION NUMBER
POP P,M ;RESTORE USER ADDRESS
ENTVC3: SUBI M,1 ;BACK UP FOR STORING ANSWERS
MOVE T1,P2 ;LENGTH TO T1
PUSHJ P,PUTEWD## ;STORE THAT
JRST ENVADC ;ADDRESS CHECK
MOVE T1,P3 ;ADDRESS TO T1
PUSHJ P,PUTEW1## ;STORE THAT
JRST ENVADC ;ADDRESS CHECK
JRST CPOPJ1## ;AND GIVE SKIP RETURN TO THE USER
;HERE TO SET THE ENTRY VECTOR
ENTVC4: SKIPN P2 ;IF CLEARING LENGTH
SETZ P3, ;ALSO CLEAR ADDRESS
JUMPE P2,ENTVC5 ;JUST STORE IT IF CLEARING
CAIN P2,(JRST) ;JUST SETTING THE START ADDRESS?
JRST ENTVC5 ;YES, JUST STORE THE ADDRESS AND RETURN
SKIPL P2 ;MUST HAVE POSITIVE LENGTH
CAILE P2,37 ;LENGTH LESS THAN 32 WORDS?
JRST ENVIAL ;DON'T HAVE ROOM FOR ANY MORE SO SAY ILL ARG
TRO P2,40 ;TO MAKE IT EASY TO TEST FOR "REAL" ENTRY VECTOR
DPB P2,[POINT 6,P3,5] ;FOR .USUSA
CAIGE P2,42 ;EXCLUDING A REENTER ADDRESS?
SETZM .JDAT+.JBREN## ;YES, DON'T CONFUSE HUMANS
SETZM .JDAT+.JBVER## ;ALWAYS CLEAR THIS IN CASE OMITTED FROM VECTOR
CAIGE P2,43 ;SPECIFYING A VERSION NUMBER?
JRST ENTVC5 ;NO, JUST STORE NUMBERS AND RETURN
MOVE M,P3 ;ARG LIST POINTER
ADDI M,2 ;WHERE THE VERSION NUMBER IS
TLZ M,770000 ;ISOLATE THE ADDRESS
PUSHJ P,GETXWD## ;GET THE VERSION NUMBER
JRST ENTVC5 ;IGNORE ADDRESS CHECK
MOVEM T1,.JDAT+.JBVER## ;STORE IT WHERE HUMANS LOOK
ENTVC5: SKIPE P2 ;IF REAL LENGTH,
SKIPE P3 ;FOR S0 JOBDAT,
CAIA ;NO
MOVEI P3,1 ;YES, FIX IT
MOVEM P3,.USUSA ;STORE ADDRESS OF ENTRY VECTOR
JRST CPOPJ1## ;AND TELL HIM HE DID GOOD
;ERROR CODES
EVIAL%==1 ;ILLEGAL ARGUMENT LIST
EVIFC%==2 ;ILLEGAL FUNCTION CODE
EVADC%==3 ;ADDRESS CHECK
ERCODX ENVIAL,EVIAL%
ERCODX ENVIFC,EVIFC%
ERCODX ENVADC,EVADC%
SUBTTL DVPHY. UUO
;THE DVPHY. UUO RETURNS THE PHYSICAL NAMES OF ALL THE DEVICES OF A
; CERTAIN TYPE OR OPTIONALLY, THE PHYSICAL NAMES OF ALL THE DEVICES
; ON THE SYSTEM (EXCLUDING PTYS, TTYS, MPXS, AND DSK).
;CALLING SEQUENCE:
; MOVE AC,[N,,ADDR] ;COUNT,,ARGUMENT
; DVPHY. AC, ;OR CALLI AC,164
; <ERROR RETURN>
; <NORMAL RETURN>
;WHERE
;ADDR: DEVICE TYPE OR -1 IF ALL DEVICES
;+1 0 FOR FIRST CALL, PREVIOUS DEVICE NAME ON SUBSEQUENT CALLS
;NEXT PHYSICAL DEVICE NAME IS RETURNED IN ADDR+1 OR 0 IF LAST
; DEVICE IN THE SYSTEM OF THAT TYPE.
UDVPHY: 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,DVPKON ;MAYBE KONTROLLER HACK
MOVE P1,T1 ;SAVE ARGUMENT
PUSHJ P,GETWD1## ;GET NEXT ARG
JUMPGE P1,DVPHY2 ;GO IF DONT WANT EVERYTHING
HLRZ F,DEVLST## ;ALL, START AT START OF DEVS
JUMPE T1,DVPHY1 ;GO IF FIRST CALL
PUSHJ P,DEVPHY ;NOT FIRST, FIND THIS DEVICE
JRST DPENPD ;NOT THERE
PUSHJ P,NXDDB ;POINT AT NEXT DEVICE ON CHAIN
JUMPE F,DVPHY4
DVPHY1: PUSHJ P,NOTPTD ;FIND NEXT DEVICE
JRST DVPHY4 ;NO MORE, RETURN A ZERO
JRST DVPHY6 ;WON, STORE T1 AND SKIP RETURN
DVPHY2: JUMPN T1,DVPHY3 ;GO IF NOT 1ST CALL
MOVE T1,P1 ;AND HERE I GOT CONFUSED
PUSHJ P,DVSDVT
JRST DPENDT
JRST DVPHY5
DVPHY3: PUSHJ P,DEVPHY
JRST DPENPD
DVPHY7: PUSHJ P,NXDDB ;POINT AT NEXT DEVICE ON CHAIN
JUMPE F,DVPHY4
LDB T1,PDVTYP##
CAIE T1,.TYDSK
CAME T1,P1
DVPHY4: TDZA T1,T1
DVPHY5: MOVE T1,DEVNAM(F)
JUMPE T1,DVPHY6 ;IF NO DEVICE, JUST STORE
CAIE P1,.TYTTY ;IS IT A TTY?
JRST DVPHY6 ;NO, JUST STORE
MOVE T2,DDBLDB##(F) ;YES, GET ASSOCIATED LDB
JUMPE T2,DVPHY7 ;SKIP THIS ONE IF NOT ATTACHED
DVPHY6: AOS (P)
PJRST PUTWDU##
;HERE TO RETURN KONTROLLER NAMES
DVPKON: HRRZ T4,M ;SAVE START OF INTERESTING ARGUMENTS
HLRE T2,T1 ;GET LH OF AOBJN WORD
CAML T2,[-100] ;RANGE
CAIL T2,0 ; CHECK
JRST DPENDT ;ILLEGAL DEVICE SEARCH REQUESTED
HRRZ T2,T1 ;GET RH OF AOBJN WORD
CAILE T2,77 ;WITHIN RANGE OF DEFINABLE DEVICES?
JRST DPENDT ;ILLEGAL DEVICE SEARCH REQUESTED
CAILE T2,TYPMAX ;WITHIN RANGE OF KNOWN DEVICES?
JRST [SETZB T1,T2 ;NO, SET TO RETURN ZEROS
JRST DVPKO4] ;AND DO SO
SUBI T2,<TYPMAX+1> ;FIND LEAST LEGAL LH
HLRE T3,T1 ;GET USER'S LH
CAMGE T3,T2 ;IS USER'S ARG IN RANGE?
HRL T1,T2 ;NO, KEEP IT WITHIN THE TABLE
MOVE T2,T1 ;COPY TO A SAFE PLACE
PUSHJ P,GETWD1## ;GET STARTING KONTROLLER NAME
EXCH T1,T2 ;SHUFFLE ARGS A BIT
PUSHJ P,FNDKON ;FIND SPECIFIED KONTROLLER
JUMPN T2,DPENDT ;ILLEGAL DEVICE
JUMPE T2,DVPKO2 ;RETURN FIRST NAME IF DESIRED
;NOW SCAN FOR THE NEXT KDB
DVPKO1: SKIPE T3,KDBNXT(T3) ;LINK TO NEXT
JRST DVPKO3 ;AND RETURN THIS NAME
SKIPA ;FIRST TIME HERE
SKIPN T3,KDBTAB##(T1) ;GET FIRST KDB OF THIS TYPE
AOBJN T1,.-1 ;ADVANCE TO NEXT DEVICE TYPE
DVPKO2: SKIPGE T1 ;SKIP IF POINTER RAN OUT
DVPKO3: SKIPA T2,KDBNAM(T3) ;RETURN THIS NAME
SETZ T2, ;ZERO MEANS NO MORE KONTROLLERS
DVPKO4: TLO T4,-1 ;INDICATE SUCCESS
HRRZ M,T4 ;GET USER ARG BLOCK ADDR BACK
PUSHJ P,PUTWDU## ;UPDATE AOBJN POINTER
MOVE T1,T2 ;GET KONTROLLER NAME
PUSHJ P,PUTWD1## ;UPDATE IT TOO
SKIPG T4 ;FAILURE?
AOS (P) ;NO--SKIP
POPJ P, ;RETURN
FNDKON: SKIPN T3,KDBTAB##(T1) ;GET INITIAL KDB OF THIS TYPE
JRST FNDKO2 ;NONE THERE
JUMPE T2,CPOPJ1## ;RETURN IF LOOKING FOR FIRST KONTROLLER
FNDKO1: CAMN T2,KDBNAM(T3) ;MATCH?
JRST CPOPJ1## ;YES
SKIPE T3,KDBNXT(T3) ;LINK TO NEXT
JRST FNDKO1 ;KEEP SEARCHING
FNDKO2: AOBJN T1,FNDKON ;TRY NEXT DEVICE TYPE
POPJ P, ;GIVE UP
;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: SKIPN F,DDBTAB##(T1) ;SEE IF AUTCON KNOWS ABOUT THIS TYPE
HLRZ F,DEVLST## ;ELSE MUST SCAN THE WHOLE CHAIN
JUMPE F,CPOPJ## ;PUNT IF EMPTY (SUB-)LIST
DVSDV1: SKIPE T2,DEVNAM(F) ;SEE IF IT'S A PROTOTYPE
TLNN T2,-1 ;OR HAS NO USEFUL NAME
JRST DVSDV2 ;YES, SKIP THIS ONE
LDB T2,PDVTYP## ;GET DEVICE TYPE
CAIN T2,(T1) ;MATCH?
JRST CPOPJ1## ;YES
DVSDV2: PUSHJ P,NXDDB ;ADVANCE TO NEXT DDB
JUMPE F,CPOPJ## ;THERE ARE NO MORE
JRST DVSDV1 ;LOOP BACK AND TRY AGAIN
;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
XWD ZERO5,.TYTTY
XWD ZERO5,.TYDSK
XWD ZERO5,.TYMPX
XWD ZERO5,.TYTSK
XWD ZERO5,TYPMAX+1
NOTTTL==.-NOTTBL
;DVPHY. ERROR CODES
DVPIA%==1 ;INVALID ARGUMENT LIST
DVPIT%==2 ;INVALID DEVICE TYPE
DVPNP%==3 ;NO SUCH PHYSICAL DEVICE
DVPNT%==4 ;NO SUCH DEVICE TYPE
ERCODE DPEIAL,DVPIA% ;INVALID ARGUMENT LIST
ERCODE DPEIDT,DVPIT% ;INVALID DEVICE TYPE
ERCODE DPENPD,DVPNP% ;NO SUCH PHYSICAL DEVICE
ERCODE DPENDT,DVPNT% ;NO SUCH DEVICE TYPE
SUBTTL DEVCHR AND DEVSIZ UUO'S
;RETURN DEVICE CHARACTERISTICS
UDVCHR: PUSHJ P,DVCHR ;CALL INTERNAL ROUTINE TO DO THE WORK
PJRST STOTAC## ;AND RETURN THE ANSWER TO THE USER
DVCH1: TLOE P1,PHONLY ;ALREADY HAVE REAL DEVICE ?
JRST DVCH2 ;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 DVCH2 ;SKIP OVER SAVE AND CLEARING P2
DVCHR: PUSHJ P,SAVE2## ;SAVE P1-P2
SETZ P2, ;FIRST CALL - ZERO P2
DVCH2: PUSHJ P,DVCNSG ;SEARCH FOR DEVICE
JRST ZPOPJ## ;NOT A DEVICE, GIVE ERROR
SETZ T3,
TLNN P1,PHONLY ;DON'T CHECK FOR LNM IF PHYSICAL ONLY
PUSHJ P,LNMNUL## ;LOGICAL NAME MAPPED TO NUL?
CAMN T1,[SIXBIT /NUL/] ;OR EXPLICIT NUL REFERENCE?
MOVEI T3,-1-TTYATC ;YES, LH WILL BE CHANGED
SKIPE DEVCHR(F) ;IF NOT A FAKE DDB,
SKIPL DEVSPL(F) ;IF A SPOOLED DEVICE,
DVCH3: SKIPA T1,DEVMOD(F)
JRST DVCH1 ; GO GET DEVMOD FOR REAL DEVICE
PUSHJ P,CHKSPL ;DEVICE SPOOLED?
TRZA T1,ASSCON!ASSPRG ;YES, IGNORE WHAT REAL DEV IS DOING
JRST DVCH4 ;NO
IOR T1,P2 ; AND SET ASSCON, ASSPRG FROM SPOOLED DDB
TLO T1,DVAVAL ;YES, SET AVAILABLE-BIT
DVCH4: LDB T2,PJOBN## ;GET JOB NO. USING DEVICE
CAME T2,.CPJOB## ;DOES CURRENT USER ALREADY HAVE IT?
TRNN T1,ASSCON+ASSPRG ;NO, IS IT ASSIGNED?
TLO T1,DVAVAL ;NO, BUT HE CAN GET IT.
IFN FTNET,<
TLNN T1,DVTTY ;IS THIS A TTY?
JRST DVCH5 ;NO, SKIP VTM TEST
MOVE T2,DDBLDB(F) ;YES, GET LDB
JUMPE T2,DVCH5 ;OK IF NONE
SE1XCT <SKIPGE LDBREM##(T2)> ;VTM + SET HOST?
TLZ T1,DVAVAL ;YES, IT'S NOT AVAILABLE AFTER ALL
DVCH5:>
TLO T1,(T3) ;SET LH = -1 IF NUL:
POPJ P, ;RETURN
;SUBROUTINE TO DETERMINE IF CHARACTERISTICS OF DDB IN F SHOULD BE
; REPLACED BY THOSE OF THE SPOOLED DEVICE.
;CALL IS
; MOVE F,DDB-ADR
; PUSHJ P,CHKSPL
; SPOOLED RETURN
; NOT SPOOLED RETURN
;SPOOLED BIT FOR DEVICE (DEYSPL) RETURNED IN T2; OTHER ACS PRESERVED
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
;RETURN DEVICE TYPE (AND OTHER PROPERTIES)
UDVTYP: AOS (P) ;SKIP-RETURN SINCE UUO IS IMPLIEMENTED
PUSHJ P,DVTYP
PJRST STOTAC## ;AND STORE THE ANSWER
DVTYP: PUSH P,T1 ;SAVE DEVICE NAME
PUSHJ P,DVCHR ;GET DEVICE CHARACTERISTICS
JUMPE T1,T2POPJ## ;NO SUCH DEV - RETURN 0
DVTY1:
PUSHJ P,CHKSPL ;SEE IF DEVICE IS SPOOLED
TLOA T2,.TYSPL!DVAVAL ;YES, SPOOL+AVAILABLE
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
SKIPN DEVCHR(F) ;FROM TABLE?
HLRZ T2,SPLBIT##(F) ;YES, GET TYPE-NUMBER
TRZE T2,DERLEN ;VARIABLE BUFFER SIZE?
TLNE T1,.TYSPL ;YES, BEING SPOOLED?
JRST .+2 ;YES
TLO T1,.TYVAR ;UNSPOOLED, VARIABLE DEV
HRR T1,T2 ;GET TYPE INTO T1
SKIPN T2 ;IF A DISK,
JUMPL T3,DVTY2 ; IF "DVDIRIN" IS ON ITS NUL:
CAIE T2,.TYRDA ;IS IT A RDA
CAIN T2,.TYTSK ;IS IT A TASK
TLOA T1,.TYINT ;YES, SET INTERACTIVE MODE
CAIG T2,.TYDTA ;DSK OR DTA?
TLO T1,.TYMAN ;YES - LOOKUP/ENTER MANDATORY
DVTY2: LDB T2,PJOBN## ;OWNER OF DEVICE
SKIPE DEVCHR(F) ;NO OWNER IF SPOOLED
DPB T2,[POINT 9,T1,26] ;IN BITS 18-26
IFN FTMPXSER,<
TLO T1,TY.MPX ;ASSUME OK
PUSHJ P,LGLMPX## ;IS IT OK?
TLZ T1,TY.MPX ;NO--CLEAR BIT
>
MOVSI T2,DVLPTL ;IS THIS A LOWER CASE LPT?
TDNE T2,DEVCHR(F)
TLO T1,TY.LL ;YES
MOVSI T2,DVCMDA ;IS THIS AN
TDNE T2,DEVCHR(F) ;MDA DEVICE?
TLO T1,TY.MDA ;YES
POPJ P,
SUBTTL CAL11. UUO
;UUO TO COMMUNICATE WITH PDP11S
CALL11: PUSH P,T1 ;SAVE USER'S ARG
HRLOI P2,377777 ;ASSUME PRIV. JOB.
PUSHJ P,PRUSET ;SKIP IF PRIV.
TLO P2,400000 ;NOT PRIV.
POP P,T1 ;RESTORE USER'S ARG
HRR M,T1 ;GET USER'S AC
HLRE T3,T1 ;GET COUNT
JUMPLE T3,ECOD7## ;.LE. ZERO ARGS NOT ENOUGH!
PUSHJ P,GETWDU## ;GET FUNCTION CODE INTO T1
SOJL T3,ECOD7## ;ERROR CODE 7: NOT ENOUGH ARGS
MOVE P3,T3 ;SAVE LENGTH
MOVE P1,T1 ;COPY FUNCTION WORD TO A SAFER PLACE
SKIPL P1 ;OLD STYLE FUNCTION WORD?
PUSHJ P,C11OLD ;YES--HACK IT UP A BIT
PUSHJ P,C11ARG ;DECODE THE TYPE, CPU, AND PORT NUMBER
POPJ P, ;RETURN ON ERRORS
MOVE T3,P3 ;RESTORE LENGTH
SKIPN T2,DLXCAL##(W) ;GET CAL11. TABLE POINTER
MOVE T2,[XWD CAL11L,CAL11D] ;NONE, USE DEFAULT
HLRZ T4,T2 ;GET LENGTH OF TABLE
CAML T1,T4 ;FUNCTION TOO LARGE?
JRST ECOD2## ;YES, ERROR CODE 2.
ADD T2,T1 ;NO, POINT TO TABLE ENTRY
MOVE T1,0(T2) ;PICK UP ENTRY
AND T1,P2 ;CLEAR SIGN BIT IF PRIV
JUMPL T1,ECOD1## ;IF STILL SET, NEED PRIV.
PUSHJ P,0(T1) ;GO DO FUNCTION
POPJ P, ;PROPAGATE ERROR BACK TO USER
PJRST CPOPJ1## ;SKIP RETURN
;TABLE FOR CAL11. UUO IF THERE IS NO SERVICE ROUTINE
CAL11D: XWD 400000,ECOD2## ;(0) DEPOSIT
XWD 400000,ECOD2## ;(1) EXAMINE
XWD 400000,ECOD2## ;(2) QUEUE A MESSAGE
XWD 0,CAL11N ;(3) RETURN NAME
XWD 0,CAL11S ;(4) UP/DOWN STATUS
XWD 400000,ECOD2## ;(5) SEND
XWD 400000,ECOD2## ;(6) RECEIVE
XWD 0,CAL11T ;(7) TYPE
CAL11L==.-CAL11D ;LENGTH OF TABLE
;CROCK TO FUDGE UP A NEW FORMAT FUNCTION WORD FROM AN OLD STYLE WORD.
;THIS INSURES COMPATIBILITY WITH PRE-702 MONITORS. EARLY 702 NONSENSE
;USING 400+DTE NUMBERS LOSE. SO DO KMC/DUPS. TO ALLOW CAL11. TO STILL
;WORK ON CPUS OTHER THAN CPU ZERO, WE'LL PICK UP THE JOB'S SET CPU COMMAND
;ARGUMENT AND SET THE CPU NUMBER TO THE FIRST CPU AVAILABLE. NO CHECKING
;IS DONE AT THIS TIME TO MAKE SURE THE SELECTED CPU HAS THE PORT WE'RE
;INTERESTED IN. THAT'LL GET CAUGHT LATER.
C11OLD: HLRZ T1,P1 ;GET PORT NUMBER
CAIGE T1,10 ;DL10 PORT?
TDZA T1,T1 ;YES
MOVEI T1,.C11DT ;MUST BE A DTE
TLZ P1,777770 ;KEEP ONLY THE PORT NUMBER
DPB T1,C11TYP ;SET THE TYPE CODE
TLO P1,(C1.1NF) ;SET NEW FORMAT
IFN FTMP,<
MOVE T1,JBTSPS##(J) ;SEE IF THE USER
TRC T1,7777 ; GAVE A SET CPU
TRCE T1,7777 ; COMMAND OR UUO
SKIPA T1,.CPCPN## ;RUN ON THIS CPU
MOVEI T1,0 ;LOCK HIM ON CPU0
DPB T1,C11CPU ;STORE IT
> ;END IFN FTMP
POPJ P, ;RETURN
;HERE TO DECODE THE TYPE, CPU, PORT NUMBER, AND FUNCTION CODE
;CALL: MOVE P1,FUNCTION WORD
; PUSHJ P,C11ARG
;
;ON RETURN, W=BASE TABLE ADDR, P1=WINDOW ADDR, T1=FUNCTION CODE
C11ARG: LDB T1,C11TYP ;GET THE TYPE CODE
LDB T2,C11CPU ;GET THE CPU NUMBER
LDB T3,C11POR ;GET THE PORT NUMBER
HRRZ T4,P1 ;GET THE FUNCTION CODE
CAILE T2,M.CPU-1 ;LEGAL CPU NUMBER?
JRST ECOD16## ;NO
CAIN T1,.C11DL ;DL10?
JRST C11DLX ;YES
CAIN T1,.C11DT ;DTE-20?
JRST C11DTX ;YES
CAIN T1,.C11KD ;KDP?
JRST C11KDX ;YES
CAIN T1,.C11DR ;DMR?
JRST C11DRX ;YES
JRST ECOD17## ;ILLEGAL TYPE CODE
C11DLX:
IFN FTKL10,<
SKIPN [EXP DL10XI##] ;ANY DL10S?
JRST ECOD21## ;NO DL10 SUPPORT
;REMOVE THE FOLLOWING INSTUCTION IF DL10S ARE MADE TO WORK ON CPU1
MOVEI T2,0 ;GET THE CPU NUMBER
CAIL T3,10 ;DL10 HAS PORTS 0-7
JRST ECOD20## ;ILLEGAL PORT NUMBER
MOVE T1,T2 ;GET THE CPU NUMBER
LSH T1,3 ;TIME THE NUMBER OF DL10 PORTS PER CPU (8)
ADDI T1,(T3) ;PLUS THE PORT NUMBER
SKIPE W,DLXBAT##(T1) ;GET THE BASE TABLE FOR THIS PORT
SKIPN P1,DLXWIN##(W) ;GET THE WINDOW ADDRESS
JRST ECOD3## ;THERE ISN'T ONE
JRST C11CPN ;GO PUT US ON THE RIGHT CPU
> ;END IFN FTKL10
IFN FTKS10,<JRST ECOD21##> ;NO DL10 SUPPORT
C11DTX:
IFN FTKL10,<
CAIL T3,4 ;DTE HAS PORTS 0-3
JRST ECOD20## ;ILLEGAL PORT NUMBER
MOVE T1,T2 ;THE CPU NUMBER
LSH T1,2 ;TIMES THE NUMBER OF DTES PER CPU (4)
ADDI T1,(T3) ;PLUS THE DTE NUMBER
SKIPN W,DTEBAS##(T1) ;HAVE ONE FOR THIS DTE?
JRST ECOD3## ;NO
MOVE P1,DLXWIN##(W) ;GET CPU#,,DTE#
JRST C11CPN ;GO PUT US ON THE RIGHT CPU
> ;END IFN FTKL10
IFN FTKS10,<JRST ECOD22##> ;NO DTE SUPPORT
C11KDX:
IFN FTKL10,<JRST ECOD23##> ;NO KDP SUPPORT
IFN FTKS10,<
CAIL T3,M.KDUP## ;VALID LINE NUMBER
JRST ECOD3## ;NOPE
MOVE W,KDPBAS##(T3) ;GET BASE TABLE ADDRESS
JRST C11CPN
> ;END IFN FTKS10
C11DRX:
IFN FTKL10,<JRST ECOD24##> ;NO DMR SUPPORT
IFN FTKS10,<
CAIL T3,M.DMRN## ;VALID LINE NUMBER
JRST ECOD3## ;NOPE
MOVE W,DMRBAS##(T3) ;GET BASE TABLE ADDRESS
> ;END IFN FTKS10
C11CPN:
IFE FTMP,<JUMPN T2,ECOD16##> ;WEED OUT JUNK CPU NUMBERS
IFN FTMP,<
MOVE T1,T2 ;GET THE CPU NUMBER
PUSHJ P,ONCPUS## ;SWITCH TO THAT CPU
JRST ECOD16## ;CPU NOT RUNNING
> ;END IFN FTMP
HRRZ T1,T4 ;GET THE FUNCTION CODE
JRST CPOPJ1## ;AND RETURN
;BYTE POINTERS TO FIELDS IN THE FUNCTION WORD
C11TYP: POINT 3,P1,11 ;TYPE CODE
C11CPU: POINT 3,P1,14 ;CPU NUMBER
C11POR: POINT 3,P1,17 ;PORT NUMBER
CAL11N::MOVE T1,DLXNMT##(W) ;GET NAME
JRST STOTC1## ;AND RETURN
CAL11T::SKIPE T1,DLXFEK##(W) ;GET ADDRESS OF FEK
HRLZ T1,FEKNNM(T1) ;GET NODE NUMBER (IF ANY)
HRR T1,DLXTYP##(W) ;GET TYPE OF FRONT END
JRST STOTC1## ;RETURN
CAL11S::SKIPE T1,DLXFEK##(W) ;GET ADDR OF FEK FOR THIS PORT
SKIPL T1,FEKBLK(T1) ;SKIP IF PORT UP
TDZA T1,T1 ;DOWN
MOVEI T1,1 ;UP
JRST STOTC1## ;SKIP RETURN
SUBTTL NETOP. UUO
;CALL: XMOVEI AC,ARGLIS
; NETOP. AC,
; ERROR CODE IN AC
; SUCCESS, AC UNCHANGED
;
;
NETOP: PUSHJ P,SXPCS## ;VALIDATE THE ARG BLOCK POINTER
JRST NOPADC ;ADDRESS ERROR
MOVE M,T1 ;COPY FOR FETCHING
PUSHJ P,GETEWD## ;GET LENGTH,,FCN
JRST NOPADC ;ADDRESS ERROR
MOVE T4,T1 ;SAVE IT
HLRZ T2,T1 ;GET LENGTH OF ARG BLOCK
HRRZS T1 ;ISOLATE FUNCTION CODE
SKIPE T1 ;FUNCTION 0 IS ILLEGAL
CAILE T1,NETFMX ;LEGAL FUNCTION CODE?
JRST NOPILF ;NOPE
CAMGE T2,NETFNL(T1) ;ARG LIST LONG ENOUGH?
JRST NOPLTS ;NOPE
MOVE T1,M ;GET ADDRESS OF ARG LIST
PUSHJ P,ARNGE## ;ADDRESS CHECK THE ARG BLOCK ITSELF
JRST NOPADC ;NOT ALL ADDRESSABLE
JRST NOPADC ;CAN'T STORE RESULTS
HRRZ T1,T4 ;GET FCN CODE AGAIN
PJRST @NETFND(T1) ;AND GO FOR IT
DEFINE NETFNS,<
NETFUN (0,NOPILF) ;; 0 - ILLEGAL FUNCTION
NETFUN (7,NET.DI) ;; 1 - DEVICE INFO
>
DEFINE NETFUN(LENGTH,DISPATCH),<EXP LENGTH>
NETFNL: NETFNS ;TABLE OF ARG LIST LENGTHS
NETFMX==.-NETFNL-1 ;MAXIMUM NET. FUNCTION CODE
DEFINE NETFUN(LENGTH,DISPATCH),<IFIW DISPATCH>
NETFND: NETFNS ;TABEL OF DISPATCH ADDRESSES
NOADC%==1 ;ADDRESS CHECK
NOILF%==2 ;ILLEGAL FUNCTION
NOLTS%==3 ;ARG LIST TOO SHORT
NONSD%==4 ;NO SUCH DEVICE
NODNC%==5 ;DEVICE NOT CONNECTED
NONTY%==6 ;DEVICE IS NOT A TTY
ERCODX NOPADC,NOADC%
ERCODX NOPILF,NOILF%
ERCODX NOPLTS,NOLTS%
ERCODX NOPNSD,NONSD%
ERCODX NOPDNC,NODNC%
ERCODX NOPNTY,NONTY%
INTERN NOPADC,NOPDNC ;ERRORS NEEDED BY NRTSER & LATSER
;FUNCTION CODE 1 - .NOGDI - Device info
; User must fill in words 0 and 2 of arg block
;
;ARGLIS+0/ LENGTH,,FUNCTION
; +1/ Flags indicating how device is connected
; +2/ SIXBIT DEVICE NAME, UDX, OR OPEN CHANNEL NUMBER
; +3/ Output, same results as DEVCHR UUO
; +4/ Output, same results as DEVTYP UUO
; +5/ ADDRESS OF STRING BLOCK FOR OUTPUT NODE NAME STRING
; +6/ ADDRESS OF STRING BLOCK FOR OUTPUT PORT NAME STRING
;
NET.DI: PUSHJ P,SAVE2## ;GET A COUPLE OF ACS TO USE
UMOVE T1,2(M) ;GET DEVICE/UDX/CHANNEL
MOVE P1,T1 ;SAVE IT
S0PSHJ DVCHR ;FIND DDB AND GET DEVCHR UUO STUFF
JUMPE T1,NOPNSD ;NO SUCH DEVICE
UMOVEM T1,3(M) ;STORE DEVCHR UUO INFO
S0PSHJ [PUSH P,P1 ;;PUSH DEVICE NAME AND
PJRST DVTY1] ;CALL DEVTYP ROUTINE
UMOVEM T1,4(M) ;SAVE DEVTYP INFO FOR USER
ANDI T1,77 ;CLEAR ALL BUT DEVICE TYPE
CAIE T1,.TYTTY ;IS IT A TTY?
JRST NOPNTY ;NOPE, PUNT.
SKIPN U,DDBLDB##(F) ;GET LDB ADDRESS FOR TTY
JRST NOPDNC ;NOT CONNECTED
HLLZ T1,LDBTTW##(U) ;GET WORD WITH NET TYPE BITS
TLNN T1,LTLUSE## ;IS IT IN USE?
JRST NOPDNC ;NOT CONNECTED
TLZ T1,^-<LTLANF##!LTLNRT##!LTLLAT##>
UMOVEM T1,1(M) ;TELL USER THE NETWORK TYPE
JFFO T1,.+2 ;ENCODE THE FIRST NET TYPE WE FIND
JRST NETDIS ;NO BITS, TREAT LOCAL LIKE ANF
PJRST @[IFIW NETDIA## ;ANF
IFIW NETDID## ;DECNET (CTERM OR NRT)
IFIW NETDIL##](T2) ;LAT
SUBTTL NETOP. UUO
;NETDIS - NETOP. function to return node and port ID for a local TTY
;
;Call: (in section 1 already)
;
; F/ DDB of terminal
; U/ LDB of terminal
; M/ Address of user's NETOP. arg list
;Return:
; ECDX? depending on error
; RETSKP node name stored in string block pointed to by user's arg list
;
;Uses P1,P2 (already saved by higher routine), T1-T4, M
NETDIS: MOVE P1,M ;SAVE ARG LIST POINTER
IFN FTNET,<
PUSHJ P,GTNTS1 ;GET NODE#,,LINE# IN T1
JRST NOPDNC ;NOT CONNECTED
>
EXCTUX <SKIPN M,5(P1)> ;DOES HE WANT NODE NAME?
JRST NTDIS1 ;NO
IFE FTNET,<SETZ T1,> ;NULL NODE NAME IF NO NETWORKS
IFN FTNET,<MOVE T1,STANAM##> ;GET OUR NODE NAME
PUSHJ P,PU6STB ;PUT SIXBIT INTO STRING BLOCK
JRST NOPADC ;CAN'T
NTDIS1: EXCTUX <SKIPN M,6(P1)>;DOES THE GUY WANT PORT NAME?
JRST CPOPJ1## ;NO, DONE
MOVE T1,DEVNAM(F) ;YES, GET DEVICE NAME
PUSHJ P,PU6STB ;STORE SIXBIT NAME INTO STRING BLOCK
JRST NOPADC ;NO LUCK
JRST CPOPJ1## ;DONE
;
;PU6STB - STORE A SIXBIT WORD INTO USER'S 8 BIT STRING BLOCK
;
;CALL: M/ADDRESS OF STRING BLOCK
; T1/SIXBIT WORD
;
;RETURN: +1 ADDRESS CHECK
; +2 SUCCESS
;
PU6STB::PUSHJ P,SAVE2## ;GET A COUPLE OF SPARE REGS
MOVE P1,T1 ;SAVE THE SIXBIT
MOVE T1,M ;COPY BLOCK POINTER
IFN FTXMON,<PUSHJ P,SSPCS##> ;PRESERVE PCS IN CASE WE NEED TO CHANGE IT
PUSHJ P,SXPCS## ;VALIDATE ITS FORM
POPJ P, ;NO GO
MOVEI T4,2 ;STRING BLOCK MIGHT ONLY NEED TO BE 2 LONG
TRNE P1,7777 ;UNLESS WE HAVE 5 OR 6 CHARS
MOVEI T4,3 ;THEN IT NEEDS TO BE 3 WORDS LONG
PUSHJ P,GETEWD## ;SEE HOW LONG IT IS
POPJ P, ;NOT ADDRESSABLE AT ALL!
HRRZ T3,T1 ;GET LENGTH IN WORDS
CAIGE T3,(T4) ;IF IT'S NOT LONG ENOUGH
POPJ P, ;THEN PUNT
PUSH P,M ;SAVE START ADDRESS OF STRING BLOCK
SETZ T4, ;NO CHARS DONE YET
PU6ST1: HRLI T4,-4 ;4 CHARS PER WORD
SETZ T1, ;ZAP THE TARGET WORD
MOVE T2,[POINT 8,T1] ;SET UP BYTE POINTER
PU6ST2: JUMPE P1,PU6ST3 ;IF NO MORE CHARS, QUIT
SETZ P2, ;ZAP THE FREE AC
ROTC P1,6 ;GET NEXT CHAR IN P2
ADDI P2," " ;MAKE IT ASCII
IDPB P2,T2 ;STORE IT
AOBJN T4,PU6ST2 ;KEEP STUFFING
PU6ST3: JUMPE T1,PU6ST4
PUSHJ P,PUTEW1## ;STORE A WORD OF RESULT
JRST MPOPJ## ;CAN'T
JRST PU6ST1 ;KEEP DOING IT
PU6ST4: POP P,M ;GET BACK ORIGINAL ADDRESS
HRL T3,T4 ;RECORD HOW MANY CHARS DONE
MOVE T1,T3
PJRST PUTEWD## ;INFORM THE USER (MAYBE TAKE FAIL RETURN)
;RETURN BUFFER SIZE, STANDARD NO OF BUFFERS
;CALL: MOVE AC,LOC OF (2 WORRD) OPEN BLOCK
;CALLI AC,DVSIZ
;NOT IMPLEMENTED RETURN
;AC=XWD NO OF BUFS,BUF SIZE
DVSIZ: PUSHJ P,SAVE1## ;SAVE P1
PUSH P,M ;SAVE M
HRR M,T1 ;GET LOC OF OPEN-BLOCK
PUSHJ P,GETWDU## ;GET MODE
MOVE P1,T1 ;SAVE IT
PUSHJ P,GETWD1## ;GET DEVICE
PUSHJ P,DVCNSG ;FIND ITS DDB
TDZA T1,T1 ;NOT A DEVICE
SKIPA M,P1 ;FOUND - SET M=MODE
SOJA T1,SIZRET ;NOT A DEV - RETURN AC=-1
MOVEI T2,1 ;SET FOR MODE TEST
ANDI P1,17 ;GET MODE ALONE
LSH T2,(P1) ;POSITION THE BIT
SETZI T1, ;IF MODE IS ILLEGAL,
CAIL P1,SD ;TEST FOR DUMP MODE
JRST SIZRT1 ;IT IS, RETURN AC=0
MOVNI T1,2
TDNN T2,DEVMOD(F) ; RETURN AC=-2
PJRST SIZRET
PUSHJ P,CHKSPL ;SPOOLED DEVICE?
MOVEI F,DSKDDB## ;YES, SET FOR A DISK
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
SUBTTL DEVGEN UUO
;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
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
SE1XCT <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
CAIN T1,.TYTSK ;TSK?
JRST DSKUDX ;YES, RETURN CHANNEL
MOVE T3,T1
LSH T1,9 ;ALLOW FOR UNIT NUMBER
LDB T2,PUNIT## ;PICK UP UNIT NUMBER
CAIN T3,.TYRDA ;RDX DEVICE
ANDI T2,7 ;YES, ONLY LOW ORDER 3 BITS
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
CAIN T3,.TYPTY
SKIPA
IOR T1,T2
CAIN T3,.TYRDA ;RDX DEVICE
JRST DEVUD1 ;YES
CAIN T3,.TYRX2 ;FLOPPY DISK
JRST DEVUD1 ;YES
CAIE T3,.TYMTA ;IS THIS A MAG TAPE
CAIN T3,.TYDTA ; 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 ;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 ;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>
REPEAT .TYRX2-<.-TYPTAB>,<
EXP 0>
TYPES <RXA>
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: S0PSHJ 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
MOVE U,DDBLDB##(F) ;GET THE LDB
PUSHJ P,GTNTS1 ;GET [NODE #,,LINE #] IN T1
JRST ECOD2## ;TTY NOT CONNECTED
PJRST STOTC1## ;RETURN THE NODE,,LINE
;COMMON SUBROUTINE TO GET NODE AND LINE NUMBER
;ARG U=LDB ADDRESS
;RETURN CPOPJ IF TTY NOT CONNECTED OR SET HOSTED AWAY
; CPOPJ1 WITH T1=XWD NODE NUMBER,LINE NUMBER
GTNTS0::SE1ENT ;ENTRY FROM SECTION 0
GTNTS1:: ;ENTRY FROM SECTION 1
IFN FTNET,<
SKIPL T1,LDBTTW##(U) ;ANF NETWORK VIRTUAL TERMINAL?
JRST GTNTSL ;NO, LOCAL TTY
MOVE T2,LDBREM##(U) ;GET THE WORD WITH "CONNECTED" BIT
TLNN T2,LRLCON## ;IS THIS TERMINAL CONNECTED
POPJ P, ;TERMINAL NOT CONNECTED.
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 CPOPJ1 ;EXIT
GTNTSL: TLNE T1,LTLUSE## ;MUST BE REALLY CONNECTED TO SOMETHING
SKIPGE LDBREM##(U) ;IF LOCAL LINE SET HOSTED AWAY
POPJ P, ;THEN GIVE NOT CONNECTED RETURN
> ;END IFN FTNET
LDB T1,LDPLNO## ;GET THE LINE NUMBER
IFN FTNET,<
HRL T1,JBTLOC## ;GET THE LOCAL NODE NUMBER
>
PJRST CPOPJ1 ;GIVE GOOD RETURN
;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
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
SKIPGE LDBTTW##(T2) ;ANF NETWORK TERMINAL?
JRST ECOD1## ;YES, ILLEGAL DEVICE
> ;END IFN FTNET
GTXTN5: S0PSHJ 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 LOCATE UUO
;LOCATE UUO (CALLI 62)
;PLACES THE CALLER AT THE DESIRED STATION SITE
;CALL: AC HAS STATION NAME OR NUMBER TO LOCATE AT
ULOCAT: NETDBJ ;INTERLOCK THIS WITH NETSER
SKIPE F,TTYTAB##(J) ;POINT TO JOB'S TTY
CAME T1,[EXP -1] ;IF ARG IS -1...
JRST ULOCA1 ;NO
PUSHJ P,FNDDEV ;PUT JOB WHERE TTY IS
JRST ULOCA2 ;LOCATE THE JOB
ULOCA1: MOVE T2,T1 ;COPY ARGUMENT
PUSHJ P,CVTOCT ;CONVERT TO OCTAL
MOVE T1,T2 ;CAN'T, RESTORE
SKIPN T1 ;0 IMPLIES LOCAL STATION
SKIPA T1,JBTLOC## ;USE CENTRAL STATION NUMBER
SKIPE [M.ANF##] ;ANF-10 MONITOR?
TLNN T1,-1 ;AND POSSIBLY A NODE NAME?
JRST ULOCA2 ;NO, MUST BE NODE NUMBER
PUSHJ P,SRCNDB## ;DO WE KNOW ABOUT IT?
POPJ P, ;NO, CAN'T LOCATE
HLRZ T1,NDBNNM##(W) ;GET NODE NUMBER
ULOCA2: CAILE T1,77 ;IS THE STATION IN RANGE
POPJ P, ;NO, ERROR RETURN
MOVEM T1,JBTLOC##(J) ;LOCATE JOB
JRST CPOPJ1## ;GIVE GOOD RETURN
;ROUTINE TO FIND LOCATION OF A DEVICE
;RETURN WITH T1=LOCATION
FNDDEV::LDB T1,PDVSTA## ;GET DDB LOCATION
MOVSI T2,DVTTY ;SEE IF
TDNN T2,DEVMOD(F) ; TTY
POPJ P, ;NO.
MOVE U,DDBLDB##(F) ;YES, SET UP U
PJRST FNDSTA## ;AND COMPUTE FROM LDB
SUBTTL WHERE UUO
;WHERE UUO (CALLI 63)
;IF AC CONTAINS 0 TO 17 THE CALLER WANTS THE LOCATION OF THE DEVICE
;INITED ON THE CHANNEL NUMBER SPECIFIED IN AC. LH(AC) = STA STATUS BITS
;IF AC IS GREATER THAN 17 IT IS ASSUMED TO BE A SIXBIT DEVICE NAME
;THAT THE CALLER WISHES TO KNOW THE STATION OF. LH(AC) = STA STATUS BITS
UWHERE: NETDBJ ;INTERLOCK THIS WITH NETSER
CAMN T1,[SIXBIT/OPR/] ;IS IT AN OPR
JRST UWHER2 ;USE THE JOB LOCATION
PUSHJ P,DVCNSG ;SEARCH FOR DEVICE OR CHANNEL
JRST RTZER ;NONE--RETURN ERROR AS 0
PUSHJ P,FNDDEV ;GET STATION NUMBER
JUMPN T1,UWHER1 ;USE IT IF NON ZERO
LDB T2,PDVTYP## ;GET TYPE OF DEVICE
CAIE T2,.TYD78 ;IF DAS78 DEV LEAVE IT 0
MOVE T1,JBTLOC## ; OTHERWISE USE CENTRAL SITE NUMBER
UWHER1: SKIPN DEVCHR(F) ;IF A "FAKE" DDB,
UWHER2: HRRZ T1,JBTLOC##(J) ;TELL WHERE JOB IS
IFN FTKL10,<
LDB T2,PDVTYP## ;GET TYPE OF DEVICE
CAIN T2,.TYD78 ;A DAS78 DEVICE?
JRST STOTC1## ;STATUS BITS TO 0 AND RETURN
> ;END IFN FTKL10
CAME T1,JBTLOC## ;CENTRAL SITE?
SKIPN [M.ANF##] ;ANF-10 MONITOR?
JRST STOTC1## ;YES, STATUS BITS ALL ZERO
IFN FTNET,<
PUSHJ P,SRCNDB## ;FIND THE NODE BLOCK
JRST RTZER ;DOES NO EXIST
HLRZ T1,NDBNNM##(W) ;GET THE NODE NUMBER
>;END IFN FTNET
JRST STOTC1## ;STORE T1 IN USER'S AC
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,.USCTA ;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
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
CAIG F,SPLTOP## ;IF IN SPLTAB,DEVJOB
CAIGE F,SPLTAB## ;INVALID, BUT SHOULD BE 0
CAIA ;(NOT THE CASE)
JRST DEVLN3 ;YES..NOT ASSIGNED
LDB T2,PJOBN##
MOVE T1,DEVMOD(F) ;DEVICE INITED OR ASSIGNED?
CAMN T2,J ;MY DEVICE
TRNN T1,ASSCON!ASSPRG
IFE FTMDA,<JRST DEVLN3> ;NO, RETURN -3
IFN FTMDA,<
JRST [CAME J,MDAJOB ;IS MDA DOING THIS?
JRST DEVLN3 ;NO, CAN'T SUCCEED
JUMPE T2,.+1 ;YES, CONTINUE IF NO OWNER
CAME T2,MDAJOB ; OR MDA IS RESPONSIBLE FOR DDB
JRST DEVLN3
JRST .+1] ;LET MDA GET UNOWNED DEVICE
>;END IFN FTMDA
PUSHJ P,SAVE1## ;SAVE P1
PUSHJ P,GETWD1## ;GET LOGICAL NAME
LDB J,PJCHN## ;SET TARGET JOB/CONTEXT HANDLE
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
MOVE T1,DEVMOD(F) ;IF NOT ASSIGNED ...
TRNE T1,ASSCON!ASSPRG ;DON'T FIX LOGICAL NAME TABLE
DPB J,PJCHN## ;STORE JCH IN DDB
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
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
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?
TRNE S,760000 ;ANY ERRORS?
PJRST WAIT1## ;YES, JUST WAIT FOR I/O TO STOP
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 FTMPXSER,<
LDB T1,PDVTYP## ;DEVICE TYPE
CAIN T1,.TYMPX ;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
>
IFN FTKL10&FTMP,<
PUSHJ P,UPDNBF ;INCREMENT DEVNBF FOR THIS BUFFER
>
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
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
MOVE T2,JBTSTS##(J) ;GET JOB STATUS
TLNE T2,JLOG ;NOT LOGGED IN
TLNE T2,JACCT ;OR JACCT
CAIA ;IS OK
JRST ACTNPV ;ELSE NOT PRIVED
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
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
ULOGIN: 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,JBTPPN##(J) ;GET OUR PPN
MOVEM T1,.PDLPN##(W) ; AND SAVE AS LOGGED-IN PPN
MOVE T1,JBTPRV##(J) ;GET MY PRIVILEGE WORD
MOVEM T1,.PDCAP##(W) ; AND SAVE AS CAPABILITY WORD
PUSHJ P,SLPTR## ;GET POINTER TO SEARCH LIST IN P2
JRST LOGIN2 ;ERROR, DON'T TRY TO TELL QUASAR
MOVE P1,P2 ;FILFND WANTS S/L POINTER IN P1
PUSHJ P,SLNMSG## ;TELL QUASAR JOB'S SEARCH LIST
JFCL ;QUASAR NOT RUNNING
LOGIN2: PUSHJ P,SETLOG## ;SET JLOG, INCREMEN LOGNUM, BATNUM
PUSHJ P,QSRLGI##
MOVE T2,[JACCT,,JS.XO] ;RESET THESE BITS TO INDICATE LOG-IN IS
ANDCAM T2,JBTSTS##(J) ; NOW COMPLETE AND ^C IS AGAIN PERMITTED.
MOVSI T2,(UP.CXO)
ANDCAM T2,.USBTS ;CLEAR XO CORE IMAGE
HRRZ M,.JDAT+JOBPD1##+1 ;LOCATION OF UUO IN USER AREA
SKIPN %SIQSR## ;QUASAR RUNNING?
TDZA T2,T2 ;NO--MPB BATCH SYSTEM
MOVSI T2,(JB.LBT) ;GET THE BATCH BIT
TDNE T2,JBTLIM ;IS IT BATCH?
AOS BATNUM## ;YES, INCREMENT BATCH COUNT.
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.
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
XWD W,.PDCNO## ;CHARGE NUMBER THIS JOB
LOGTOP==.-LOGTAB ;NO. OF TABLES TO BE SET
;ACCLOG UUO
ACCLOG: PUSHJ P,SAVE2## ;SAVE P1-P2
MOVE P1,T1 ;STORE OUR FLAGS
TLNN P1,(AC.MAX!AC.BMX!AC.DCR) ;AT LEAST ONE BIT ON?
JRST ACLILL ;NO, SO GIVE HIM AN ERROR
SYSPIF ;NOW LOCK THIS CODE
TLNN P1,(AC.MAX) ;DO WE WANT LOGMAX CHECKING?
JRST ACLBAT ;NO, SO CHECK BATMAX
MOVE T2,LOGMAX## ;GET MAX NUMBER OF JOBS
TLNN P1,(AC.BMX) ;BATCH LOGIN?
SUB T2,BATMIN## ;INCLUDE RESERVED BATCH SLOTS IN TALLY
CAMG T2,LOGNUM## ;IF MORE SLOTS THAN JOBS LOGGED IN THEN SKIP
JRST ACLMXF ;NO ROOM, ERROR FAIL FOR LOGMAX
ACLBAT: TLNN P1,(AC.BMX) ;DO WE WANT BATMAX CHECKING?
JRST ACLDCR ;NO, SO CHECK IF LOGIN FAILED
MOVE T2,BATNUM## ;GET CURRENT NUMBER OF BATCH JOBS
CAMLE T2,BATMAX## ;IF LESS THAN OR EQUAL ITS OK (SCNSER DID INC)
JRST ACLBMF ;GREATER, SO GO KILL THIS
ACLDCR: TLNN P1,(AC.DCR) ;IS THIS A JOB THAT FAILED TO LOGIN?
JRST ACLDON ;NO, ALL DONE
SYSPIN ;UNLOCK, WE SHOULD BE CLEAR NOW
PUSHJ P,FNDPDS## ;GET POINTER TO PDB
MOVSI T1,(PD.LGN) ;GET THE COUNT BIT
TDNN T1,.PDDFL##(W) ;IS IT SET?
TRNA ;NO, SO SKIP
JRST ACLDCE ;YES, THEN DON'T DO DECR.
MOVSI T1,JLOG ;GET THE LOGIN BIT
TDNE T1,JBTSTS##(J) ;ARE WE LOGGED IN?
JRST ACLJLE ;YES, WE CAN'T DECREMENT IF LOGGED IN
MOVSI T1,(PD.LGN) ;NO, GET THE RIGHT BITS BACK
IORM T1,.PDDFL##(W) ;MARK THAT WE'RE DECREMENTING
SOS LOGNUM## ;THEN DECREMENT LOGNUM
JRST CPOPJ1## ;AND WE ARE DONE
ACLDON: MOVSI T1,(PD.LGN) ;GET THE COUNT BIT
TDNN T1,.PDDFL##(W) ;IS IT ALREADY OFF?
JRST ACLRTN ;YES, THEN RETURN
ANDCAM T1,.PDDFL##(W) ;NO, SO CLEAR IT AND
AOS LOGNUM## ;INCREMENT LOGNUM
ACLRTN: SYSPIN ;UNLOCK NOW
JRST CPOPJ1## ;AND RETURN TO USER
ACLMXF: SYSPIN ;LOGMAX FAILURE, TURN LOCK OFF
JRST ACLMXE ;RETURN WITH ERROR
ACLBMF: SYSPIN ;BATMAX FAILURE, TURN LOCK OFF
JRST ACLBME ;RETURN AN ERROR
ERCODE ACLMXE,ACLMX% ;LOGMAX CHECK FAILED (TOO MANY)
ERCODE ACLBME,ACLBM% ;BATMAX CHECK FAILED (TOO MANY)
ERCODE ACLILL,ACLIL% ;ACCLG. ERROR, INCORRECT BITS SET
ERCODE ACLJLE,ACLJL% ;ACCLG. ERROR, USER TRIED DECR WITH JLOG ON
ERCODE ACLDCE,ACLDC% ;ACCLG. ERROR, DECR TRIED WITHOUT INCR DONE
;LOGOUT UUO
LOGOUT: PUSHJ P,TTYFNU##
MOVE T1,JBTSTS##(J) ;JOB STATUS
TLNN T1,JLOG ;LOGGED IN?
JRST LOGOUA ;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,LGINAM## ;RUNNING LOGIN
CAMN T1,LGONAM## ; OR LOGOUT?
CAIA ;YES, ALLOWED TO DO THIS
JRST EXIT
LOGOUA: MOVSI T1,(PD.LGO) ;INDICATE LOGOUT UUO IN PROGRESS
IORM T1,.PDDFL##(W) ; ..
JRST JOBKL## ;GO DO THE WORK
;ATTACH UUO - PRIVILEGED, FOR DAEMON, ATTACH COMMAND.
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 RTZERP ;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 RTZERP ;NO. GIVE FAIL RETURN.
MOVE 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 RTZERP ;NO, FAIL RETURN
SKIPA T1,(P) ;YES, RESTORE JOB NUMBER
UATC1A: HRR T1,J ;NEGATIVE JOB ARGUMENT MEANS SELF
HRRZS T1 ;MAKE SURE NO LEFT HALF BITS
HRRZ F,TTYTAB##(T1) ;DDB OF JOB DESIRED
JUMPE F,RTZERP ;IF NONE, FAIL RETURN
MOVE 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 RTZERP ;NO. FAIL RETURN.
MOVE T2,LINTAB##(T1) ;"TO" TTY
IFN FTNET,<
SKIPL LDBTTW##(T2) ;ANF NETWORK TERMINAL?
JRST UATC1W ;NO, PROCEED
MOVE T3,LDBREM##(T2) ;GET THE REMOTE WORD
TLNN T3,LRLCON## ;IS THIS TTY CONNECTED?
JRST RTZERP ;NO, NEVER MIND!
> ;END IFN FTNET
UATC1W: JUMPE U,UATC1X ;JUMP IF NO "FROM" TTY
IFN FTNET,<
SKIPGE LDBREM##(U) ;IF LOCAL LINE SET HOSTED AWAY
JRST RTZERP ;THEN NOT AVAILABLE FOR ATTACH
>
PUSHJ P,PTYDTC## ;DETACH VIA F
UATC1X: HLRZ U,0(P) ;GET LINE NUMBER
MOVE 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 RTZERP ;FAIL RETURN (SHOULDN'T HAPPEN)
MOVEI T1,JS.RPC ;JOB ALLOWED MONITOR LEVEL?
TDNE T1,JBTST2##(J)
HRLI P1,200000 ;NO--FORCE USER MODE
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 RTZERP ;NO, RETURN
PUSHJ P,TTYSRC## ;YES, SET UP 4
PJRST RTZERP ;SHOULD NEVER FAIL
HLRZ T1,(P) ;GET TTY NUMBER HE WANTED DET'D
TRZ T1,600000 ;GET RID OF FLAGS
CAIN T1,177777 ;IS IT -1? (DEFAULT FOR SELF)
JRST UATAC6 ;YES, CHECK USER MODE
LDB P1,LDPLNO## ;GET REAL TTY NUMBER
CAME T1,P1 ;SAME?
PJRST RTZERP ;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 RTZERP ;NO, RETURN
JRST UATAC3 ;YES, NOW DET HIM.
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 ;RANGE TABLE?
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 GETTB1 ;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 GETTB5 ;NO, GO GET THE ANSWER
GETTB1: CAIE T1,GT.RNG ;RANGE?
CAIN T1,GT.ITM ;OR ITEM INDEX?
JRST GETTB2 ;YES
CAIL T2,-2 ;WANT JOB'S HIGH SEGMENT?
MOVE J,.CPJOB## ;YES, INDEX = CURRENT JOB NUMBER
CAIE T2,-2 ;YES--SEE IF REQUESTING HI-SEG
JRST GETTB2 ;NO--SKIP AHEAD
PUSH P,T1 ;SAVE T1
PUSHJ P,FNSPCS## ;GET HIGH SEG FOR THIS SECTION
PUSHJ P,[JUMPL J,CPOPJ1## ;OK IF SPY
PUSH P,T1 ;SAVE ONE FOUND
PUSHJ P,NXSPCS## ;ARE THERE ANY MORE
JRST TPOPJ## ;NO MORE
ADJSP P,-3 ;FIX STACK
POPJ P, ] ;ERROR RETURN (AMBIGUOUS)
JUMPE T1,TPOPJ## ;NO SEGMENT AT ALL, RESTORE T1 AND ERROR
POP P,T1
TLZ J,-1
;AT THIS POINT T3=TABLE NUMBER AND J=INDEX
GETTB2: 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
JUMPN T2,GETTB3 ;JUMP IF NON-ZERO MAXIMUM
CAIE T1,GT.ITM ;INDEXED BY ITEM?
JRST RTZER1 ;NO, THEN NUMTAB IS REALLY WRONG
HRRZ T4,NUMTAB(T3) ;GET TABLE ADDRESS FROM NUMTAB
CAIN T4,NULGTB ;THE "NULL" GETTAB TABLE?
JRST RTZER1 ;YES, TABLE NOT IN MONITOR
JRST GETTB4 ;TABLE WITH ONE ENTRY, GO PROCESS IT
GETTB3: CAIE T4,.GTRNG
JRST GETTB4
CAIE T1,GT.RNG
SKIPA T1,T2
MOVE T1,RNGTAB(T2)
JRST STOTC1##
GETTB4: SKIPL J ;SKIP IF TOO SMALL
CAMLE J,T2 ;SKIP IF VALID INDEX
POPJ P, ;INDEX IS TOO BIG
CAIE T1,GT.PDB ;IS DATA IN PDB?
JRST GETTB5 ;NO--GET FROM TABLE
PUSHJ P,FNDPDB## ;TRY TO FIND PDB
JRST RTZER1 ;NO PDB, RETURN ZERO
HRRZ T3,NUMTAB(T3) ;INDEX INTO PDB
ADD T3,W ;ADD PDB ADDRESS TO GET OFFSET INTO PDB
MOVE T1,(T3) ;COPY THE PDB DATUM
JRST STOTC1## ;STORE AS ANSWER
GETTB5: CAIN T3,.GTSGN ;IS THIS .GTSGN?
JRST GETTB6 ;YES--HANDLE SPECIALLY
MOVE T1,@NUMTAB(T3) ;GET WORD
JRST STOTC1## ;SKIP RETURN T1 IN HIS AC
GETTB6: SETZB T1,T2 ;START FROM THE BEGINNING, PRESET RETURN AC
PUSHJ P,GNXHSB## ;FIND A HISEG BLOCK FOR THE JOB IN J
JRST GETTB7 ;RETURN FROM T2
MOVE T2,.HBSGN(T1) ;REMEMBER THE ENTRY
PUSHJ P,GNXHSB## ;GET THE NEXT ONE
JRST GETTB7 ;RETURN FROM T2 IF ONLY ONE HISEG
JRST ECOD0## ;PUNT IF TWO OR MORE HISEGS FOR THE TARGET JOB
GETTB7: MOVE T1,T2 ;GET RETURN VALUE (0 OR OLD JBTSGN ENTRY)
JRST STOTC1## ;SKIP RETURN T1 IN USER 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,,NULGTB>
IFN FT,< JOBMXL##+<GT.JOB>B29+J,,TBL>
>
IFIDN <TYPE>,<S>,<
IFE FT,< JBTMXL##+<GT.SEG>B29,,NULGTB>
IFN FT,< JBTMXL##+<GT.SEG>B29+J,,TBL>
>
IFIDN <TYPE>,<P>,<
IFE FT,< JOBMXL##+<GT.JOB>B29,,NULGTB>
IFN FT,< JOBMXL##+<GT.PDB>B29+W,,TBL>
>
IFIDN <TYPE>,<I>,<
IFE FT,< NULGTB>
IFN FT,< MAX+<GT.ITM>B29+J,,TBL>
>
IFIDN <TYPE>,<R>,<
IFE FT,< NULGTB>
IFN FT,< EXP <OFS>B8+<GT.RNG>B11+<J>B17+TBL>
>
>
NULGTB::0 ;THE NULL GETTAB TABLE - SATISFY DUMMY GLOBALS
DEFINE RANGE(FT,FIRST,LAST,RNG,NAME),<
IFN FT,<
RNG'OFS==.-RNGTAB
IFNB <NAME>,<
NAME:: FIRST,,LAST
>
IFB <NAME>,<
FIRST,,LAST
>
>>
RNGTAB: 0 ;ENTRY 0 NOT USED
RANGE 1,<GTBSTT-NUMTAB>,<GTTBLN-1>,NUM
RANGE 1,CTTWDT##-TTTWDT##,TTTWDN##+CTTWDT##-TTTWDT##-1,TTT
RANGE 1,<.GTCSD##-.GTSID##>,SDTBLN##,SID
RANGE 1,<CCNTAB##-TCNTAB##>,<TCNLIM##-TCNTAB##>,TCN
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 1,P,.PDTTM## ;(004) RUNTIME IN JIFFIES
GT 1,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
.GTSGN==.-NUMTAB
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 1,J,JBTRCT## ;(017) DISK READS
GT 1,J,JBTWCT## ;(020) DISK WRITES
EXP NULGTB ;(021) UNUSED
EXP NULGTB ;(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
EXP NULGTB ;(027) UNUSED
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 1,P,.PDCNO## ;(033) CHARGE NUMBER
EXP NULGTB ;(034) UNUSED
GT 1,J,JBTWCH## ;(035) WATCH BITS
GT 1,J,JBTSPL## ;(036) SPOOL TABLE
GT FTRTTR!FTHPQ,J,JBTRTD## ;(037) REAL TIME
GT 1,J,JBTLIM## ;(040) CORE AND TIME LIMITS
EXP NULGTB ;(041) UNUSED
EXP NULGTB ;(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 1,I,WHYTXT##,WHYMXL## ;(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 1,I,PIDTAB##,MIDMXL## ;(076) PROCESS ID TABLE
GT 1,I,IPCTAB##,IPCMXL## ;(077) IPCF MISC. DATA
GT 1,S,JBTUPM## ;(100)POINTER TO USER PAGE MAP
GT 1,I,WATTAB##,WTCMXL## ;(101) WATCH COMMANDS*
GT 1,P,.PDCVL## ;(102) CURRENT VM LIMITS
GT 1,P,.PDMVL## ;(103) MAX VM LIMITS
GT 1,P,.PDIPA## ;(104) IPCF STATISTICS
GT 1,P,.PDIPC## ;(105) IPCF POINTERS
GT 1,P,.PDIPI## ;(106) THIS JOB'S [SYSTEM]INFO
GT 1,P,.PDIPQ## ;(107) FLAGS AND QUOTAS
EXP NULGTB ;(110) OBSOLETE
GT FTKL10,P,.PDABS## ;(111) ADDRESS BREAK SETTING
EXP NULGTB ;(112) RESERVED
GT 1,I,.GTVM##,GTVMXL## ;(113) VM DATA
GT 1,P,.PDVRT## ;(114) PAGING RATES
GT 1,I,.GTSST##,SSDMXL## ;(115) SCHEDULER STATISTICS
EXP NULGTB ;(116) OBSOLETE
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 NULGTB ;(124) UNUSED
EXP NULGTB ;(125) UNUSED
;CONTINUED ON NEXT PAGE
GT 1,R,.GTSID##,,SIDOFS ;(126) SPECIAL PIDS
GT 1,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,I,NETGTT##,.NTMXL## ;(141) NETSER PERF MEASUREMENTS
GT FTPSCD,I,SCDPER##,%PERLN## ;(142) PERFORMANCE TABLE
GT 1,P,.PDVKC## ;(143)JOB'S VIRTUAL KCT
GT 1,P,.PDUUC## ;(144)JOB'S UUO COUNT
GT 1,P,.PDSFD## ;(145) FIRST SFD 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 1,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,DVSXCT##,LENDVS## ;(160) CONI/DATAI DEVICE STATUS
GT FTNET,I,NDBTBL##,NDBMXL## ;(161) NDB BYTE POINTERS
GT 1,J,JBTPDB## ;(162) JOB PDB ADDRESS
GT 1,P,.PDEQJ## ;(163) ENQ Q-HEADER
GT 1,I,DFLTTB##,DFLMXL## ;(164) SET DEFAULT COMMAND ARGUMENTS
GT 1,P,.PDLBS## ;(165) BIG BUFFERS
GT 1,P,.PDPGM## ;(166) PROGRAM TO RUN
GT FTMDA,P,.PDSTM## ;(167) TIME OF LAST RESET
GT FTDECNET,I,DCNGTB##,DCNGTL## ;(170) DECNET Q-HEADERS
GT FTDECNET,P,.PDSJB## ;(171) PTR TO DECNET SESSION JOB BLOCK
EXP NULGTB ;(172) OBSOLETE. DECNET QUOTA WORD
GT FTNET,I,.GTNDA##,NDAMXL## ;(173) NDB ADDRESS TABLE
GT FTNET,I,OBJTAB##,AOTMXL## ;(174) ANF-10 OBJECT TRANSLATION
;CONTINUED ON NEXT PAGE
GT 1,I,CTXTAB##,CTXMXL## ;(175) CONTEXT DATA
GT 1,S,JBTIMI## ;(176) IMAGE IN (PHYSICAL PROGRAM) SIZE
GT 1,S,JBTIMO## ;(177) IMAGE OUT SIZE
GT 1,J,JBTDDB## ;(200) I/O WAIT DDB
GT 1,J,JBTVIR## ;(201) VIRTUAL PROGRAM SIZE
GT FTENET,I,ETHGTB##,ETHMXL## ;(202) ETHERNET INFORMATION
EXP 0 ;(203) OBSOLETE (HIGH SEG SECTION #)
GT 1,I,CSTTAB##,COMMXC## ;(204) CUSTOMER DEFINED COMMANDS
GT 1,I,NXMTAB##,NXMMXL## ;(205) NON-EX MEMORY BIT TABLE
GT 1,I,BOOTXT##,BTXMXL## ;(206) BOOTS AUTO-RELOAD STRING
GT 1,I,.GTCHN##,CHNMXL## ;(207) CHANNEL DATA BLOCK OFFSETS
GT 1,I,KDBTAB##,<<TYPMAX>B26> ;(210) KDB CHAIN HEADERS
GT 1,I,DDBTAB##,<<TYPMAX>B26> ;(211) DDB CHAIN HEADERS
GT 1,R,TCNTAB##,,TCNOFS ;(212) SIXBIT TTY CLASS NAMES
GT 1,P,.PDLPN## ;(213) LOGGED-IN PPN
;INSERT NEW TABLES ABOVE HERE
IFN FTPATT,<
Z ;FOR PATCHING
Z
>
GTTBLN=.-NUMTAB ;LENGTH OF TABLE
$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,1,1,1,1,POKE,PEEK,1,1,1,1,1,1,MIC,MLOG,MDA>
;(1) REAL-TIME AND SCHEDULING FEATURES
FTBITS<HPQ,1,1,RTTRAP,1,LOCK,0,0,1,1,NSCHED,PSCD,1>
;(2) COMMAND FEATURES (THIS WORD IS FULL)
FTBITS<1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1>
;(3) ACCOUNTING FEATURES
FTBITS<1,1,1,1,1,FDAE,EMRT,1>
;(4) NON I/O FEATURES NOT RELATED TO DEBUGGING (THIS WORD IS FULL)
FTBITS<1,MP,1,1,1,1,1,0,0,0,1,0,KL10,1,KS10,1,SCA>
;(5) NON I/O DEBUGGING FEATURES
FTBITS<0,0,1,1,0,PATT,1,RSP,1>
;(6) DISK UUO FEATURES (THIS WORD IS FULL)
FTBITS<1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1>
;(7) DISK "INVISIBLE" FEATURES (THIS WORD IS FULL)
FTBITS<1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0>
;(10) SCANNER, RP04 FEATURES
FTBITS<0,0,0,1,1,1,1,1,1,1,0,0,1,0,1,1>
;(11) OTHER PERIPHERALS (THIS WORD IS FULL)
FTBITS<1,1,1,1,1,NET,1,1,1,1,MPXS,1,1,1,TLAB,1,1>
;(12) OTHER PERIPERALS (SECOND WORD)
FTBITS<1>
;(13) DISK "INVISIBLE" FEATURES (SECOND WORD)
FTBITS<DUAL>
;(14) DISK UUO FEATURES (SECOND WORD)
FTBITS<1,1>
;(15) LIST OF MONITOR NON-I/O FEATURES WHICH DIRECTLY IMPACT CUSPS (SECOND WORD)
FTBITS <1>
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
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)
MOVSI T2,(IC.LIP) ;UUO DONE FROM A PUBLIC PAGE?
TDNN T2,.JDAT+JOBPD1##
JRST SETNM2 ;NO, THEN ALWAYS LEGAL TO CLEAR XO
SETZ T1, ;START WITH FIRST SEGMENT
SETNM1: PUSHJ P,GNXHSB## ;GET NEXT HIGH SEGMENT DATA BLOCK
JRST SETNM2 ;IF THE END, MUST BE OK TO CLEAR XO
MOVE T3,.HBSGN(T1) ;GET SEGMENT BITS
TLNE T3,GTSSEG ;HE SEG CONCEALED?
JRST SETNM4 ;YES, THEN CAN'T CLEAR XO
JRST SETNM1 ;TRY NEXT SEGMENT
SETNM2: MOVEI T2,JS.RUU!JS.XO!JS.XOR ;CLEAR EXECUTE ONLY SO CAN SAVE
ANDCAM T2,JBTSTS##(J) ; A PROGRAM LOADED BY XO LOADER
; ALWAYS CLEAR JACCT WITH JS.XO
SETZ T1, ;START WITH FIRST SEGMENT
SETNM3: PUSHJ P,GNXHSB## ;GET NEXT HIGH SEGMENT DATA BLOCK
JRST SETNM4 ;THAT WAS THE LAST ONE
MOVE T3,.HBSGN(T1) ;GET SEGMENT BITS
TLNE T3,GTSSEG ;SEGMENT CONCEALED (ONLY IF IC.LIP CLEAR)?
TLO T3,REDOMP ;YES, MAP MUST BE REDONE
MOVEM T3,.HBSGN(T1) ;PUT BITS BACK
JRST SETNM3 ;NEXT SEGMENT
SETNM4: MOVSI T2,(UP.GET!UP.CXO) ;CLEAR GET IN PROGRESS FLAG
ANDCAM T2,.USBTS
PUSHJ P,MAPHGH## ;REDO THE MAP IN CASE CONCEALED
MOVE T1,JBTPRG##(J) ;RESTORE NAME
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 /:/
PUSH P,P2
SETZ P2, ;NOT VERSION COMMAND, DON'T CALL PGMFIL
PUSHJ P,VERBTH## ;TYPE NAME AND VERSION
POP P,P2
PJRST PRRBKC## ;TYPE RIGHT BRACKET <CRLF>
;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
CAMN T1,.PDLPN##(W) ;RETURNING TO OUR LOGGED-IN PPN?
JRST CHGPP1 ;NOT-LOGGED-IN IS GOLDEN
MOVE T2,T1 ;COPY NEW PPN TO A SAFER PLACE
MOVE T1,[<JP.POK,,0>!CHGPPP##] ;EITHER POKE OR CUST PRIV
PUSHJ P,PRVBIT## ; OR JACCT OR [1,2]
SKIPA T1,T2 ;YES (I HATE BACKWARDS RETURNS)
POPJ P, ;NO, USER LOSES
PUSHJ P,PPNCHK ;SEE IF WE LIKE THE PPN
POPJ P, ;PPN CANNOT BE CHANGED
CHGPP1: MOVEM T1,JBTPPN##(J) ;OK, CHANGE PPN
JRST CPOPJ1## ;AND GIVE OK RETURN
;THIS ROUTINE IS FURNISHED AS AN EXAMPLE OF HOW CUSTOMERS MIGHT
;WHAT TO EXCLUDE CHANGING TO PARTICULAR PPNS.
PPNCHK: CAMN T1,FFAPPN## ;OPERATOR?
JRST CPOPJ1## ;OK TO CHANGE TO [OPR]
CAML T1,MFDPPN## ;ALLOWING PPN CHANGES TO ONE OF
CAMLE T1,NEWPPN## ; THESE COULD BE QUITE DISASTEROUS
PPNCH1: AOS (P) ;OTHER CHECKS COULD BE MADE HERE
POPJ P, ;DON'T ALLOW SPECIAL SYSTEM PPNS
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.
UDVNAM: PUSHJ P,DVCNSG ;SEARCH FOR CHANNEL OR DEVICE
JRST RTZER ;NONE--RETURN ERROR AS 0
TLZ F,-1
CAIE F,DSKDDB## ;CLAIM TO BE GENERIC DSK?
SKIPA T1,DEVNAM(F) ;USE NAME FROM DDB
PUSHJ P,LNMNUL## ;LOGICAL NAME MAPPED TO NUL?
CAIA ;NO--LEAVE NAME ALONE
MOVSI T1,'NUL' ;ELSE RETURN NUL
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)
TRPSET: TDZA T3,T3 ;FORCE SW EVENT LOGGING
TRPSTU: SETOM T3 ;DON'T LOG SW EVENT (DIAG. UUO)
MOVE T2,JBTPRV##(J) ;IS JOB PRIVILEGED TO DO TRPSET UUO?
MOVE T4,JBTSTS##(J) ;...
AND T4,T3 ;KEEP JACCT BIT IF DIAG. ONLY
TLNN T2,PVTRPS ;DOES JOB HAVE TRPSET PRIV?
TLNE T4,JACCT ;OR JACCT IF DIAG. UUO?
SKIPA ;YES, CONTINUE
POPJ P, ;NO, ERROR RETURN
IFN FTMP,<
TRPSE0: PUSHJ P,LOKSCD## ;GET SCHEDULAR INTERLOCK
SKIPE .CPSTS## ;TIMESHARING STOPPED?
CAMN J,.CPSTS## ;YES, BY THIS JOB?
JRST TRPSE1 ;NOT STOPPED, OR STOPPED BY THIS JOB
PUSHJ P,ULKSCD## ;RELEASE SCHEDULAR INTERLOCK
PUSHJ P,WSCHED## ;WAIT FOR OTHER JOB TO FINISH
JRST TRPSE0 ;AND TRY AGAIN
TRPSE1: PUSHJ P,TRPSTX ;DO TRPSET CODE
SKIPA ;PROPOGATE NON-SKIP RETURN
AOS (P) ;PROPOGATE SKIP RETURN
PJRST ULKSCD## ;RELEASE SCHEDULAR INTERLOCK AND RETURN
>; END IFN FTMP
;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE
TRPSTX: SETZM .CPSTS## ;CLEAR THE STOP TIME SHARING FLAG
CAMN J,TGHJOB## ;TGHA?
JRST TRPST0 ;WE DON'T TRUST HIM, BUT HAVE NO CHOISE
MOVE T2,T1 ;EVENT-SPECIFIC DATA WORD (TRPSET AC)
MOVEI T1,.SWETP ;EVENT CODE (TRPSET)
PUSHJ P,SWESEB## ;LOG EVENT
SETZ F, ;AVOID IME
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##> ;JOB MUST BE LOCKED IN EVM
POPJ P, ;NO (OR LOCKING UNSUPPORTED), 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,.CPEPT## ;ADD IN TRAP 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.
;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##
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
MOVE P1,T1 ;SAVE ARGUMENT
SKIPE .USWLC ;USER WRITE-LOCKED PAGES?
JRST HIBE4A ;YES
MOVEI T1,UP.NVS ;JOB HAS PAGES ON THE DISK BIT
SKIPE .USVRT ;JOB VIRTUAL?
TDNE T1,.USBTS ;YES, DO WE KNOW ABOUT WRITE LOCKED PAGES?
CAIA ;JOB NOT VIRTUAL OR WE HAVE ALREADY COUNTED WLP
PUSHJ P,XPANDH## ;CAUSE PAGES TO BE WRITE LOCKED
HIBE4A: MOVE T1,P1 ;RESTORE ARGUMENT
HLRZ T2,T1 ;GET THE PROTECTION BITS
DPB T2,HIBPRT## ;STORE PROTECTION CODE IN LEFT HALF OF JBTRTD(J)
TRNN T2,TTILCE## ;TTY WAKEUPS ENABLED?
TRZ T2,UDIUUB## ;NO, CAN'T BE DEMANDING INPUT
MOVEI T3,TTIUDI## ;USER DEMANDING INPUT BIT
ANDCAM T3,JBTRTD##(J) ;ASSUME SHOULD BE CLEAR
TRNE T2,UDIUUB## ;DOES THE USER WANT INPUT?
IORM T3,JBTRTD##(J) ;YES, FLAG IT
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
TRNE T2,TTILCE## ;IS JOB GOING INTO CHARACTER MODE?
PUSHJ P,HIBTTY## ;YES, GO SET UP LINE CHARACTERISTICS
JUMPGE T1,HIBER2 ;DOES JOB WANT TO BE SWAPPED OUT IMMEDIATELY?
; (HBRSWP SET)
PUSHJ P,ZERIPT## ;YES, MARK HIM AS SWAPPABLE.
MOVE T1,P1 ;PICKUP. ARGUMENT OF UUO AGAIN
HIBER2: HLRZ T2,T1 ;SAVE THE FLAGS
HRRZS T1 ;GET THE SLEEP TIME IN MILLISEC
JUMPE T1,HIBER0 ;IF NO SLEEP TIME,DONT ENTER CLOCK REQUEST
IMUL T1,TICSEC## ;CONVERT TO JIFFIES
TRNE T2,HBRSEC## ;IS SLEEP TIME ACTUALLY IN SECONDS?
JRST HIBER5 ;YES,DON'T DIVIDE
IDIVI T1,^D1000 ;CONVERT FROM MILLISECONDS
SKIPE T2 ;IS THIS AN EVEN NUMBER OF JIFFIES
AOS T1 ;NO, ALWAYS ROUND UP TO NEXT JIFFY
HIBER5: CAMGE T1,TICSEC##
SKIPA P1,[NAPQ##] ;NAP IF .LT. SECOND
HIBER0: MOVEI P1,SLPQ## ;PREPARE TO PUT JOB IN SLEEP QUEUE
PUSH P,T1 ;SAVE ADJUSTED SLEEP TIME
MOVSI T2,WAKEB## ;CHECK IF JOB HAS BEEN AWAKENED
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 TPOPJ1## ;GIVE A SKIP RETURN TO THE USER
HIBER1: DPB P1,PJBSTS## ;STORE THE SLEEP CODE IN JBTSTS WORD
SYSPIN ;RESTORE PI SYSTEM
AOS -1(P) ;GIVE SKIP RETURN WHEN JOB WAKES UP
POP P,T1 ;RESTORE ADJUSTED SLEEP TIME
CAILE T1,777777 ;WAS THIS A VERY LARGE NUMBER
MOVEI T1,777777 ;YES, THEN SLEEP THE MAXIMUM TIME
JUMPN T1,HSLEEP ;GO ENTER SLEEP TIME IN CLOCK REQUEST QUEUE
HIBER3: PUSHJ P,FNDPDS## ;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:
MOVE T2,T1 ;GET JOB NUMBER OF WAKER
SIGNAL C$WAKE ;SIGNAL WAKEUP
JFCL ;ALWAYS WAKE JOB (IN CASE PSISER DIDN'T)
MOVSI T2,(JS.HIB) ;JOB DID SLEEP UUO BIT
TDNN T2,JBTST2##(J) ;SLEEP OR HIBER?
JRST SETWAK ;SLEEP, JUST SET WAKE BIT
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
CAMGE T1,FRSHPQ## ;PRE-EMPTIVE HPQ?
JRST CPOPJ1## ;NO
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
SKIPE T3,SCDRTF## ;IS THERE A FORCED SCHEDULE TO BE DONE
TRNN T3,-1 ;FOR A REAL JOB?
MOVNM J,SCDRTF## ;FLAG
TDNN T2,JBTSTS##(J) ;IS THIS JOB SWAPPED OUT
JRST WAKOK3 ;NO. PROCEED.
SKIPG T2,SCDRTF## ;ANYONE IN SCDRTF?
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,SCDRTF## ;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
;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
CPLOCK (SCD) ;UNTIL JOB GETS PUT INTO JDCQ
PUSHJ P,STDAEM## ;IS DAEMON RUNNING?
JRST [CPUNLK (SCD)
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
CPUNLK (SCD) ;DAEMON CAN RUN NOW
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 IN PER-PROCESS SPACE
; AS IF MAPPED THROUGH SPECIFIED JOB'S MAP
JOBPEK: HRR M,T1 ;SET UP FOR CALLS TO GETWRD
HLRZ T2,T1 ;SAVE LENGTH
PUSHJ P,GETWRD## ;GET FIRST WORD (PRESERVES T2)
JRST RTZER ;BAD ARG LIST
MOVE P1,T1 ;SAVE FIRST WORD
MOVSI T1,JP.POK ;ONLY POKE PRIVS WILL WIN FOR A WRITE FUNCTION
TLNN P1,(JK.WRT) ;BUT IF WRITE IS OFF,
TLO T1,PVSPYA ; ALLOW SPYALL PRIVS TO LET THE USER READ
PUSHJ P,PRVBIT## ;USER SUFFICIENTLY PRIVILEGED (PRESERVES T2)?
SKIPA T1,P1 ;YES, RE-LOAD T1 AND SKIP
JRST JPKNPV ;NO, ERROR
MOVSI P1,(JK.ALL) ;FLAGS
AND P1,T1 ;SAVE THEM IN P1
JUMPE T2,JPKOLD ;OLD FORMAT
CAIGE T2,4 ;MUST BE AT LEAST 4 ARGS
JRST RTZER
HRRI P1,(T1) ;JCH IN RH(T1)
LDB P4,[POINT 10,T1,17] ;COUNT
PUSHJ P,GETWR1## ;GET NEXT WORD
JRST RTZER ;(CURRENTLY IGNORED)
PUSHJ P,GETWR1##
JRST RTZER
MOVE P2,T1 ;READ ADDRESS
PUSHJ P,GETWR1## ;WRITE ADDRESS
JRST RTZER
MOVE P3,T1
JRST JPKCMN
JPKOLD: HRRZ P4,T1 ;COUNT TO P4
LDB T1,[POINT 9,T1,17] ;JOB #
IORI P1,(T1) ;IN RH(P1)
PUSHJ P,GETWR1## ;GET ADDRESS WORD
JRST RTZER
HLRZ P2,T1 ;READ ADDR
HRRZ P3,T1 ;WRITE ADDR
JPKCMN: TLNE P1,(JK.WRT) ;WRITE?
EXCH P2,P3 ;YES, ADDRESSES ARE BACKWARDS
TLNE P1,(JK.EVA!JK.UPM) ;OTHER GUY TO BE MAPPED THROUGH EVM?
TLO P2,(JK.EVA) ;YES, SET THAT
TLNE P1,(JK.UPM) ;AND IF UPT
HRRI P2,.UPMP ;FORCE IT
;HERE WITH DATA SET UP AS THE FOLLOWING:
;
; P1=FLAGS,,OTHER JCH
; J=OUR JOB #
; P2=OTHER ADDRESS (+JK.EVA IF APPLICABLE)
; P3=OUR ADDRESS (+JK.EVA IF APPLICABLE)
; P4=# WORDS TO TRANSFER
JOBPK0: SETZ F, ;FLAG INDICATING WE HAVE DDB
MOVE T1,P3 ;ADDRESS IN OUR JOB
TLZ T1,(JK.ALL) ;CLEAR FLAGS
MOVEI T2,(P4) ;GET LIMIT
PUSHJ P,ARNGE## ;CHECK IT
JRST JPKIAD ;NO
JFCL ;DON'T CARE IF I/O ILLEGAL FOR NOW
;HERE WITH ADDRESS IN OUR JOB VERIFIED AS LEGAL
JOBPK1: TLNN P2,(JK.EVA) ;IS HIS ADDRESS IN EVM?
JRST JOBPK2 ;NO, CAN'T VERIFY ANYTHING ABOUT IT YET
MOVEI T2,(P2) ;IN EVM, GET ADDRESS
CAIL T2,FYSORG
CAILE T2,.LPPP-1 ;IS IT LEGAL?
JRST JPKIAD ;NO
JOBPK2: PUSHJ P,SIPCHK ;SEE IF JOB IS STABLE, GET THE MM IF IT IS
JRST JPKDNA ;NOT AVAILABLE
HRRZ T1,P1 ;GET OTHER JCH
PUSHJ P,CTXJPK## ;GET JBTSWP POINTER (MAY NOT BE SWAPPED)
JRST JKIJC0 ;ILLEGAL JOB/CONTEXT NUMBER
JOBPK7: JUMPE T2,JOBPK3 ;JOB IS IN CORE
JPKSUP: PUSHJ P,GETSCR ;GET DDB, BUFFER PAGE, AND REMEMBER IT
JRST JKSER0 ;OOPS
EXCH T1,T2 ;UPT POINTER TO T1, IOWD TO T2
PUSH P,T1 ;SAVE UPT POINTER
PUSHJ P,REDSWP ;READ THE SWAPPING SPACE
JRST JKSERR ;OOPS
PUSHJ P,SIPCHK ;SEE IF JOB IS IN TRANSIT AGAIN
JRST JKDNA1 ;DATAT NOT AVAILABLE
HRRZ T1,P1 ;GET OTHER JCH
PUSHJ P,CTXJPK## ;GET SWAP PARAMETER AGAIN
JRST JKIJCH ;WENT AWAY
PUSHJ P,GETSCR ;REMAP .JBPK IN CASE WE GOT SWAPPED
JRST JKSERR
POP P,T3 ;RESTORE OLD POINTER
CAMN T3,T2 ;CHANGED?
JRST JOBPK5 ;NO, ASSUME UPT READ IS RIGHT
JUMPN T2,JPKSUP ;SWAPPED AT A DIFFERENT ADDR, TRY AGAIN
HRRZ T1,P1 ;(LOAD JCH FOR BELOW)
JOBPK3: ANDI T1,JOBMSK ;ONLY JOB #
HRRZ T1,JBTUPM##(T1) ;GET UPT PAGE
HRLI T1,(<PM.DCD>B2+PM.PUB+PM.WRT) ;MAP THE UPT, MAY NEED TO WRITE
MOVEM T1,.UPMP+.UMJBK ;SET MAP SLOT
CLRPT .JBPK ;CLEAR THAT
;HERE WITH THE "OTHER" UPT MAPPED AT .UMJBK
;T2 CONTAINS SWAPPING POINTER FOR UPT IF JOB IS SWAPPED
JOBPK5: TLNE P2,(JK.EVA) ;IS IT IN EVM?
JRST JPKEVM ;YES, NO ADDRESS CHECKING
HRRZ T1,P1 ;JCH
PUSHJ P,CTXSGN## ;GET SEGMENT INFO (JBTSGN INTO T1)
JRST JKIJCH ;GONE AWAY?
JUMPE T1,JPKLW0 ;CAN'T BE IN HS IF THERE ISN'T ANY
PUSH P,T2 ;SAVE UPT POINTER
JOBP5B: LDB T3,[PSG2LH+.HBSG2(T1)] ;GET SECTION HIGH SEG IS IN
HLRZ T4,P2 ;MIGHT BE IN HIS HIGH SEG
TRZ T4,(JK.ALL) ;CLEAR FLAGS (LEAVING SECTION #)
CAIE T4,(T3) ;IS THIS RIGHT SECTION?
JRST JOBP5A
MOVEI T3,(P2) ;NOT IN EVM, ADDR CHECK HIS (SECT REL) ADDR
PUSH P,J ;SAVE J
SKIPGE J,.HBSGN(T1) ;GET SEGMENT #
SKIPA T2,[PSPOLH+.HBSPO(T1)]
SKIPA T2,JBYHSO##
SKIPA T4,J ;SIZE IF SPY SEG
TLZA J,-1 ;CLEAR BITS
TLZA T4,-1 ;CLEAR BITS
HLRZ T4,JBTADR##(J) ;GET TOP
LDB T2,T2 ;GET ORIGIN
LSH T2,P2WLSH
JUMPN T4,JOBP5C ;JBTADR SET UP (OR SPY SEG)
LDB T4,IMGOUT## ;SIZE ACTUALLY ON SWAP SPACE (NOT
;QUITE RIGHT IF EXPANDING, BUT SAFER)
LSH T4,P2WLSH ;CONVERT TO WORDS
SOS T4
JOBP5C: ADDI T4,(T2) ;END OF HIGH SEG
HLL T4,.HBSGN(T1) ;BITS TO T4
POP P,J ;RESTORE J
CAIL T3,(T2) ;IN HIS HIGH SEG?
CAILE T3,(T4) ;?
JRST JOBP5A
JUMPLE T4,JPKLOW ;SPY SEG
TLNN T4,SHRSEG ;SHARABLE?
JRST JPKLOW ;NON-SHARABLE, CAN'T BE SHARABLE TOO
;HERE FOR JOBPEK INVOLVING SHARABLE HIGH SEG
JPKHI: HRRZ J,.HBSGN(T1) ;GET SEGMENT NUMBER, MINUS CRUD
SKIPN JBTADR##(J) ;IS HIGH SEG IN CORE?
JRST JPKHSW ;NO, SWAPPED
JPKHI1: MOVNS T2 ;MAKE NEGATIVE
ADDI T2,(P2) ;RELATIVE ADDRESS
LSH T2,W2PLSH ;PAGE # TO FIND
PUSHJ P,SNPAGS## ;FIND IT
HRLI T1,(<PM.DCD>B2!PM.WRT!PM.PUB!PM.COR) ;PAGE POINTER
MOVEM T1,.UPMP+.UMJBK ;MAKE ADDRESSABLE
CLRPT .JBPK
TLNE P1,(JK.WRT) ;WRITING?
PUSHJ P,ZERSWP## ;CLEAR DISK COPY OF HIGH SEG
MOVE J,.CPJOB## ;GET JOB # BACK
MOVSI T1,(PM.COR) ;FLAG NO SWAP SPACE TO WRITE
POP P,T2 ;RESTORE UPT POINTER
JRST JPKMOV ;MOVE THE DATA
JOBP5A: SKIPN T1,.HBLNK(T1) ;CHECK NEXT SEGMENT
JRST JPKLOW ;NOT IN ANY HIGH SEG
JRST JOBP5B ;LOOP BACK
;HERE IF HIGH SEG SWAPPED
;J HAS HISEG #, T2 HAS SWAPPING POINTER FOR JCH WE ARE LOOKING AT
JPKHSW: HRRZ T3,P2 ;OTHER ADDRESS
SUB T3,T2 ;MAKE RELATIVE TO HIGH SEG ORIGIN
LSH T3,W2PLSH ;PAGE IN QUESTION
SKIPL T1,JBTSWP##(J) ;IS HIGH SEG FRAGMENTED?
JRST JPKHS5 ;NO, EASY CASE
JPKHS1: SKIPGE T4,(T1) ;POINTER TO ANOTHER FRAGMENT?
JRST [MOVEI T1,(T4) ;YES, GO TO IT
JRST JPKHS1 ]
JUMPE T4,JKSERR ;HUH?
LDB T4,FRGCT4## ;GET COUNT OUT OF T4
CAILE T4,(T3) ;DESIRED ADDRESS IN THIS FRAG?
JRST JPKHS4 ;YES
SUBI T3,(T4) ;NO, SUBTRACT OUT
AOJA T1,JPKHS1 ;LOOK AT NEXT FRAG
JPKHS4: MOVE T1,(T1) ;ENTRY
JPKHS5: TLZ T1,(PM.NAD) ;(KEEP ONLY A DISK ADDRESS, THIS SYMBOL CLOSE)
ADDI T1,(T3) ;ACTUAL SWAPPING POINTER
POP P,T3 ;UPT POINTER
MOVE T2,T1 ;SAVE DISK ADDR
PUSHJ P,GETSCR ;GET SWAPPING SPACE
JRST JKSER0
EXCH T1,T2 ;IOWD TO T2, POINTER TO T1
PUSH P,T3 ;UPT POINTER
PUSH P,T1 ;HS SWAP POINTER
TLNE P1,(JK.WRT) ;WRITING?
CAIE P4,PAGSIZ ;EXACTLY ONE PAGE?
JRST JPKHS6 ;NO
TRNN P2,PG.BDY ;AND STARTING ON A PAGE BOUNDARY?
JRST JPKHS7 ;WRITING ONE PAGE ON PAGE BOUNDARY
JPKHS6:
PUSHJ P,REDSWP
JRST JKSER2
JPKHS7: PUSH P,J ;SAVE J
MOVE J,.CPJOB## ;IN CASE WE SLEEP
PUSHJ P,SIPCHK ;SEE IF JOB STABLE
JRST JKDNA3 ;NOT AVAILABLE
POP P,J ;RESTORE J
PUSHJ P,CTXJPK##
JRST JKIJC2
POP P,T1 ;RESTORE SWAPPING POINTER
POP P,T3 ;OLD POINTER
SKIPE JBTADR##(J) ;HIGH SEG STILL OUT
JRST JPKHI1 ;LOOK AGAIN
MOVE J,.CPJOB## ;RESTORE JOB # TO J
CAMN T2,T3 ;JOB IN SAME PLACE?
JRST JPKMOV ;YES, ASSUME OK
JRST JOBPK7 ;JOB CHANGED STATE
;HERE FOR JOBPEK INTO EVM
;T2 HAS UPT SWAPPING POINTER
JPKEVM: TLNE P1,(JK.UPM) ;UPT?
JRST JPKMOV ;YES, ALREADY MAPPED
MOVEI T1,(P2) ;GET ADDRESS
SUBI T1,FYSORG ;RELATIVE PAGE IN FUNNY SPACE
LSH T1,W2PLSH ;CONVERT TO PAGE
SKIPN T1,.JBPK+.UMORG(T1) ;GET POINTER FOR THIS PAGE
JRST JKXIAD ;NON-EXISTANT
TLNN T1,(<PM.DCD>B2) ;SWAPPED?
JRST JPKEVS ;YES
HRLI T1,(<PM.DCD>B2!PM.PUB!PM.COR!PM.WRT) ;MAKE SURE WE KNOW NO SWAP SPACE
MOVEM T1,.UPMP+.UMJBK
CLRPT .JBPK
JRST JPKMOV
JPKEVS: TLZ T1,(PM.NAD) ;SAVE SWAPPING POINTER
DMOVE T3,T1 ;SAVE UPT POINTER (T4) AND THIS POINTER (T3)
PUSHJ P,GETSCR ;GET DDB IF IF DON'T HAVE ALREADY
JRST JKSER0 ;ERROR
PUSH P,T3 ;SAVE THIS PAGE POINTER
PUSH P,T4 ;SAVE UPT POINTER
PUSHJ P,SIPCHK ;SWAPPING I/O IN PROGRESS NOW?
JRST JKDNA2 ;NOT AVAILABLE
HRRZ T1,P1 ;OTHER JCH
PUSHJ P,CTXJPK## ;FIND INTERESTING PARAMETERS
JRST JKIJC2 ;ILLEGAL JOB
POP P,T3 ;RESTORE UPT POINTER
POP P,T1 ;AND POINTER FOR THIS PAGE
CAME T2,T3 ;UPT STILL IN SAME PLACE?
JRST JOBPK7 ;NO
TLNE P1,(JK.WRT) ;WRITING?
TLNE P2,PG.BDY ;YES, ON A PAGE BOUNDARY?
JRST JPKES1 ;NO
CAIN P4,PAGSIZ ;AND WRITING EXACTLY A PAGE?
JRST JPKMOV ;NO READING IF WRITING EXACTLY A PAGE
JPKES1: PUSH P,T3 ;SAVE UPT POINTER
PUSH P,T1 ;AND POINTER TO THIS SLOT
MOVE T2,DEVDMP##(F) ;GET IOWD
PUSHJ P,REDSWP ;READ SWAPPING SPACE
JRST JKSER2 ;LOSE
PUSHJ P,SIPCHK ;SEE IF SWAPPING I/O IN PROGRESS NOW
JRST JKDNA2 ;NOT AVAILABLE
HRRZ T1,P1
PUSHJ P,CTXJPK## ;GET SWAPPING POINTER
JRST JKIJC2
POP P,T1 ;RESTORE SWAPPING PTR FOR THIS SLOT
POP P,T3 ;AND FOR UPT
CAMN T2,T3 ;JOB SAME PLACE?
JRST JPKMOV ;YES
JRST JOBPK7
;HERE FOR LOW SEG, SPY SEG, OR NON-SHARABLE HIGH SEG
;T1 HAS SECTION # INVOLVED, UPT SWAPPING PONTER (IF SWAPPED, ZERO IF NOT) ON STACK
;UPT MAPPED THROUGH .UMJPK
JPKLOW: POP P,T2 ;RESTORE SWAPPING POINTER
JPKLW0: HLRZ T1,P2 ;GET SECTION #
JPKLW1: CAILE T1,MXSECN ;LEGAL SECTION?
JRST JKXIAD ;NO, FLUNK OUT NOW
SKIPN T2 ;UPT IN CORE?
SKIPN .JBPK+.UPWLP ;MAP CONTAIN WRITE LOCKED PAGES?
TDZA T3,T3 ;NO TO EITHER, THIS IS EASY
MOVE T3,.UPMP+.UMJBK ;YES TO BOTH, REMEMBER WHERE UPT IS
SKIPN T1 ;IS IT SECTION 0?
SKIPA T1,.JBPK+.UMUPM ;YES, USE .UPMAP
MOVE T1,.JBPK+SECTAB(T1) ;ELSE GET SECTION POINTER
TLNE T1,(<PM.DCD>B2) ;IN CORE?
JRST JPKLW2
JPKSUM: TLZ T1,(PM.NAD) ;CLEAR BITS
MOVE T3,T1 ;SAVE SECTION MAP POINTER
PUSHJ P,GETSCR ;GET SCRATCH DDB IF NEEDED
JRST JKSER0 ;OH WELL
MOVE T1,T3 ;RESTORE POINTER TO PAGE WE WANT
PUSH P,T2 ;SAVE T2
MOVE T2,DEVDMP##(F) ;(NOTE THAT MAP ONLY SWAPPED IF UPT WAS)
PUSHJ P,REDSWP ;READ SWAPPING SPACE
JRST JKSERR ;FIX STACK
PUSHJ P,SIPCHK ;GET MM AND CHECK IN PROGRESS STATE
JRST JKDNA1 ;ERROR
HRRZ T1,P1
PUSHJ P,CTXJPK## ;GET UPT POINTER AGAIN
JRST JKIJCH ;FIX STACK AND RETURN
POP P,T3 ;RESTORE SAVED POINTER
CAME T3,T2 ;STILL THE SAME?
JRST JOBPK7 ;JOB CHANGED STATE
PUSHJ P,GETSCR ;IN CASE WE GOT SWAPPED
JRST JKSER0
JRST JPKLW4 ;YES,CONTINUE
;HERE WITH JOB IN CORE
JPKLW2: TLNN T1,(<PM.ACD^!PM.DCD>B2) ;IS THIS INDIRECT SECTION?
JRST JPKLW3 ;NO
LDB T1,[POINT 5,T1,17] ;GET SECTION #
JRST JPKLW1 ;CONTINUE
JPKLW3: TLZ T1,(PM.CSH) ;JUST TO BE SAFE
MOVEM T1,.UPMP+.UMJBK ;MAP USER MAP AT .JBPK
CLRPT .JBPK
JPKLW4: HRRZ T4,P2 ;SECTION RELATIVE ADDRESS IN HIS AREA
LSH T4,W2PLSH ;PAGE #
SKIPN T1,.JBPK(T4) ;DOES PAGE EXIST IN HIS MAP?
JRST JKXIAD ;NON-EXISTENT
CAMN T1,[PM.ZER] ;ABZ PAGE?
JRST JKXABZ ;YES
TLNN T1,(PM.COR) ;IN CORE?
JRST JPKPAG ;NO
SKIPE T3 ;MAP CONTAIN WRITE LOCKED PAGES?
TLOE T1,(PM.WRT) ;AND IS THIS PAGE WRITE LOCKED?
JRST JPKLW7 ;NO TO EITHER, JUST DO THE COPY
TLNN P1,(JK.WRT) ;WRITING?
JRST JPKLW7 ;NO, NO NEED TO WRITE ENABLE THE PAGE
MOVEM T1,.JBPK(T4) ;STORE POINTER BACK WITH PM.WRT ON
MOVEM T3,.UPMP+.UMJBK ;AND STORE POINTER TO UPT SO CAN DECREMENT WLP
CLRPGT ;CLEAR EVERYTHING SINCE MAY BE DOING THIS TO US
SOS .JBPK+.UPWLP ;DECREMENT COUNT OF WRITE LOCKED PAGES
S1PSHJ [PUSHJ P,SAVT## ;ALL T'S ARE IMPORTANT
MOVE T2,T1 ;ARGUMENT FOR RTNFS0
PJRST RTNFS0##];RETURN SWAPPING SPACE
JRST JPKLW7 ;GO DO THE COPY
JPKPAG: MOVE T3,T1 ;SAVE PAGE TO WRITE
PUSHJ P,GETSCR ;GET DDB ET ALL IF WE DON'T HAVE ALREADY
JRST JKSER0
PUSH P,T2 ;UPT POINTER
PUSH P,T3 ;PAGE TO READ
MOVE T2,T1 ;IOWD TO T2
MOVE T1,T3 ;PAGE TO READ
TLNE P1,(JK.WRT) ;IS THIS A WRITE?
CAIE P4,PAGSIZ ;OF EXACTLY ONE PAGE?
JRST JPKPG2 ;NO, MUST READ
TRNN P2,HLGPNO ;AND ONLY WORKS IF STARTING ON PAGE BOUNDARY
JRST JPKPG4
JPKPG2: MOVE T1,(P) ;RESTORE ADDRESS
TLZ T1,(PM.NAD)
PUSHJ P,REDSWP
JRST JKSER2 ;LOSE
JPKPG4: PUSHJ P,SIPCHK ;GET MM
JRST JKDNA2
PUSHJ P,GETSCR ;MAKE SURE MAPPING IS RIGHT
JRST JKSER2
HRRZ T1,P1
PUSHJ P,CTXJPK## ;GET SWAPPING PIONTER AGAIN
JRST JKIJC2 ;LOSE
POP P,T1
POP P,T3 ;RESTORE SAVED POINTER
CAME T2,T3 ;CONTEXT STAYED IN SAME PLACE?
JRST JOBPK7 ;NO
JRST JPKMOV ;CONTINUE
JPKLW7: HRLI T1,(<<PM.DCD>B2!PM.WRT!PM.COR!PM.PUB>) ;BE SURE PAGE ACCESIBLE AND WRITABLE (AND NOT CACHED)
MOVEM T1,.UPMP+.UMJBK
CLRPT .JBPK
;HERE WITH DATA TO BE MOVED TO/FROM .JBPK
JPKMOV: MOVEI T4,.JBPK ;POINT TO WHERE DATA IS
DPB P2,[POINT 9,T4,35] ;PAGE OFFSET
PUSH P,T1 ;SAVE PAGE POINTER
HLRZ T1,P3 ;SECTION
PUSHJ P,STPCS##
POP P,T1
HRLI T4,(P3) ;GET OUR ADDRESS
MOVSI T3,(XCT) ;INSTURCTION TO DO
TLNN P1,(JK.WRT) ;WRITING?
TLOA T3,(Z PX.MEM,) ;READING, SET MONITOR TO USER
TLOA T3,(Z PX.SRC,) ;WRITING, SET USER TO MONITOR
MOVSS T4 ;IF READING, ADDRESSES ARE REVERSED
HRRI T3,[BLT T4,(T2)] ;INSTR TO EXECUTE
LDB T2,[POINT 9,P2,35] ;PAGE OFFSET IN OTHER MAP
ADDI T2,-1(P4) ;IF ALL, # OF WORDS WE WOULD TRANSFER
CAIGE T2,PAGSIZ ;CROSS A PAGE BOUNDARY IF WE DO?
JRST JPKMO4 ;NO, NO SWEAT
LDB T2,[POINT 9,P2,35] ;GET OFFSET AGAIN
SUBI T2,PAGSIZ ;COMPUTE ACTUAL TRANSFER SIZE WE CAN MAKE
MOVNS T2
ADD P2,T2 ;UPDATE FOR NEXT TIME
ADD P3,T2 ;..
SUB P4,T2 ;# WORDS LEFT
JRST JPKMO5
JPKMO4: MOVEI T2,(P4) ;# OF WORDS TO MOVE
SETZ P4, ;# OF WORDS LEFT AFTER
JPKMO5: ADDI T2,-1(T4) ;LAST WORD WRITTEN
XCT T3 ;XCT PROPER PXCT
IFN FTMP,<
ERJMP [PUSHJ P,DWNMM##
JRST JPKIAD ]
>
IFE FTMP,<
ERJMP JPKIAD
>
IFN FTMP,<
PUSHJ P,DWNMM##
>
TLNN T1,(PM.COR) ;WAS PAGE IN CORE?
TLNN P1,(JK.WRT) ;NO, WAS THIS A WRITE?
JRST JPKMO6 ;DONE IF READ OR PAGE WASN'T SWAPPED
TLZ T1,(PM.NAD)
MOVE T2,DEVDMP##(F) ;DUMP IOWD
PUSHJ P,WRTSWP ;WRITE SWAPPING SPACE BACK
JRST JPKIOE
JPKMO6: JUMPN P4,JOBPK2
JRST CPOPJ1##
;SUBROUTINE TO SEE IF JOB IS STABLE. RETURNS CPOPJ1 WITH THE MM IF JOB IS
;(JOB MAY BE IN OR OUT OF CORE, BUT CANNOT MOVE UNTIL MM RETURNED)
;RETURNS CPOPJ W/O MM IF AIO SET AND WE WOULD HAVE HAD TO BLOCK
;ENTER WITH P1=FLAGS,,OTHER JOB #
;USES T1-T4
SIPCHK: MOVSI T2,(JS.SIP) ;IS JOB SWAPPING?
MOVEI T3,(P1)
ANDI T3,JOBMSK## ;GET HIS JOB #
IFN FTMP,<
PUSHJ P,MMOWN##
PUSHJ P,UPMM## ;GET THE MM
>
CAME T3,FIT## ;SWAPPER WAITING ON THIS JOB?
CAMN T3,FORCE## ;?
JRST SIPCK2 ;YES, DELAY
TDNE T2,JBTST2##(T3) ;OR IS JOB SWAPPING?
JRST SIPCK2 ;YES
MOVEI T1,(P1) ;GET JCH
PUSHJ P,CTXSGN## ;GET HIGH SEG #
JRST SIPCK5 ;OH WELL
JUMPE T1,SIPCK6
SIPCK3: SKIPLE T2,.HBSGN(T1) ;SPY SEGS DON'T GET SWAPPED MOST OF THE TIME
TLNE T2,SHRSEG ;AND NON-SHARABLE ONES GO WITH THE LOW SEG
JRST SIPC3A ;MAY BE MORE SEGS
HRRZS T2 ;CLEAR JUNK
CAMN T2,FIT## ;THIS SEG?
JRST SIPCK2 ;YES, DELAY
SIPC3A: HRRZ T1,.HBLNK(T1) ;NEXT SEG
JUMPN T1,SIPCK3
SIPCK6: SKIPLE T4,JBTHSQ## ;ANY JOBS IN HSQ QUEUE?
TLZA T4,-1 ;YES, GO FORWARD
JRST SIPCK5 ;DONE
SIPCK4: CAIN T4,(T3) ;THIS JOB IN THE HSQ QUEUE?
JRST SIPCK2 ;YES
HRRE T4,JBTJIL##(T4) ;NEXT JBTHSQ ENTRY
JUMPG T4,SIPCK4 ;CONTINUE IF MORE
SIPCK5:
IFN FTMP,<
PUSH P,J ;SAVE J
MOVEI J,(T3)
TRNE P1,CTXMSK## ;IF NO CONTEXT NUMBER SPECIFIED
PUSHJ P,CTXJCJ## ;GET CURRENT CONTEXT
MOVEI T1,(P1) ;CURRENT IS THIS ONE
CAIE T1,(P1) ;IS CURRENT CONTEX ONE WHICH IS RUNNING?
JRST JPOPJ1## ;NO, NO NEED TO CHECK CACHE (WAS SWEPT WHEN
;THIS CONTEXT WENT TO THE SWAP SPACE)
PUSHJ P,ANYRUN## ;RUNNING ON SOME CPU?
JRST SIPCK1 ;CACHE ALWAYS WRONG
IFN FTKL10,<
PUSHJ P,SBCCSH## ;IS DATA VISIBLE?
> ;END FTKL10
JRST JPOPJ1## ;OK TO PROCEED
SIPCK1: POP P,J
TLNE P1,(JK.AIO) ;DON'T BLOCK?
PJRST DWNMM## ;NO, GIVE UP THE MM AND RETURN
> ;END IFN FTMP
IFE FTMP,<
JRST CPOPJ1##
>
SIPCK2:
IFN FTMP,<
PUSHJ P,DWNMM## ;YES, DELAY
>
SETZ T1,
PUSHJ P,SLEEPF
JRST SIPCHK
;ERROR RETURNS WHICH FIX THE STACK, RETURN MM
JKDNA3: POP P,(P)
JKDNA2: POP P,(P)
JKDNA1: POP P,(P)
MOVEI T1,JPKDNA
JRST JPKERR
JKXIAD: SKIPA T1,[JPKIAD]
JKXIJN: MOVEI T1,JPKIJN
JRST JPKERR
JKIJC2: POP P,(P)
JRST JKIJCH
JKSER2: POP P,(P) ;FIX STACK ONE MORE
JKSERR: SKIPA T1,[JPKIOE]
JKIJCH: MOVEI T1,JPKIJN
POP P,(P)
JRST JPKERR
JKIJC0: MOVEI T1,JPKIJN
JRST JPKERR
JKXABZ: SKIPA T1,[JPKABZ]
JKSER0: MOVEI T1,JPKIOE
JPKERR: MOVE J,.CPJOB## ;IN CASE WAS DOING HIGH SEG
IFN FTMP,<
PUSHJ P,TGVMM## ;GIVE UP MM IF OWNED
>
JRST (T1)
;ERROR CODES RETURNED BY JOBPEK
ERCODE JPKNPV,JKNPV% ;NOT PRIVILEGED
ERCODE JPKIJN,JKIJN% ;ILLEGAL JOB NUMBER
ERCODE JPKIAD,JKIAD% ;ILLEGAL ADDRESS
ERCODE JPKDNA,JKDNA% ;DATA NOT ADDRESSABLE
ERCODE JPKIOE,JKIOE% ;I/O ERROR
ERCODE JPKMNC,JKSWP% ;MONITOR IS NOT CAPABLE
ERCODE JPKABZ,JKABZ% ;ALLOCATED BUT ZERO PAGE
;STILL IN FTDAEM CONDITIONAL
;SUBROUTINE TO ALLOCATE A DDB AND A PAGE OF FUNNY SPACE TO READ
; PAGES FROM THE SWAPPING SPACE INTO
;CALLING SEQUENCE:
; PUSHJ P,GETSCR
; ERROR RETURN - NO CORE AVAILABLE
; NORMAL RETURN - F POINTS AT THE DDB,
; T2 AND DEVDMP(F) ARE IOWDS POINTING TO FUNNY SPACE PAGE
GETSCR: JUMPE F,GETSC1 ;NEED TO DO SOMETHING
HRRZ T1,DEVDMP##(F) ;GET IOWD
AOS T1 ;VIRTUAL ADDRESS IN REAL FUNNY SPACE
MAP T1,(T1) ;GET PAGE
LSH T1,W2PLSH ;GET PAGE #
ANDI T1,PM.PAG ;SAVE ONLY PAGE #
HRLI T1,(<PM.DCD>B2!PM.WRT)
MOVEM T1,.UPMP+.UMJBK ;POINT .JBPK BACK AT IT
CLRPT .JBPK
MOVE T1,DEVDMP##(F)
JRST CPOPJ1##
GETSC1:
PUSH P,T2
PUSH P,T3
PUSH P,T4 ;SAVE MOST OF THE TS
IFN FTMP,<
PUSHJ P,MMOWN## ;OWN MM?
JSP T2,GTSCMM ;NO, REMEMBER THAT AND PROCEED
PUSHJ P,DWNMM## ;GIVE UP MM, BELOW ROUTINES GET BY HAND
SETZ T2,
GTSCMM: PUSH P,T2 ;SAVE MM FLAG
>; END IFN FTMP
MOVEI T2,DDBLEN##
PUSHJ P,GFWDUD##
JRST GTSCER
PUSHJ P,FAKDDX##
JRST GTSCER
PUSH P,R
SETZ R, ;CLEAR R
MOVSI T1,(1B0) ;WANT IT UNCACHED
PUSHJ P,CREFSP## ;GET FUNNY SPACE PAGE
JRST GTSCRR ;RESTORE R AND ERROR
MAP T2,(T1) ;GET PHYSICAL ADDRESS
LSH T2,W2PLSH ;CONVERT TO PAGE #
ANDI T2,PM.PAG ;PAGE # ONLY
HRLI T2,(<PM.DCD>B2!PM.WRT)
MOVEM T2,.UPMP+.UMJBK ;POINT .JBPK AT IT
CLRPT .JBPK
SOS T1
HRLI T1,-PAGSIZ
MOVEM T1,DEVDMP##(F)
AOS -<4+<IFN FTMP,<1>>>(P)
GTSCRR: POP P,R
GTSCER:
IFN FTMP,<
POP P,T2 ;RESTORE MM FLAG
SKIPN T2
PUSHJ P,UPMM## ;IF HAD THE MM, GET IT BACK
>
POP P,T4
POP P,T3
POP P,T2
POP P,(P) ;RESTORE CALLER'S ADDRESS
PUSHJ P,@1(P) ;AND GIVE (SKIP) CO-ROUTINE RETURN
CAIA ;FAIL
AOS (P)
GIVCOR: JUMPE F,CPOPJ##
PUSH P,T1 ;SAVE T1
MOVEI T1,PAGSIZ
AOS T2,DEVDMP##(F)
HRRZS T2
PUSHJ P,GVFWDS##
PUSHJ P,CLRDDB##
JRST TPOPJ##
;SUBROUTINE TO READ/WRITE SWAPPING SPACE
;CALLING SEQUENCE:
; MOVE T1,SWAPPING POINTER
; MOVE T2,IOWD
; PUSHJ P,RED/WRTSWP
; ERROR RETURN - I/O ERROR
; NORMAL RETURN, T1 = IOWD
REDSWP: TDZA S,S
WRTSWP: MOVSI S,IO
PUSHJ P,SWPADR##
STOPCD (CPOPJ,DEBUG,SDS) ;++SWPADR DIDN'T SKIP
JUMPLE U,CPOPJ## ;I/O ERROR IF UNIT GONE
IFN FTMP,<
PUSHJ P,REMMM##
>
PUSH P,J ;STOAU TRASHES J
PUSHJ P,STOAU##
EXCH T1,T2
PUSH P,.USMBF
MOVEM T1,.USMBF
PUSHJ P,MONIOU## ;I/O NOT USING DISK CACHE
EXCH T1,T2
POP P,.USMBF
POP P,J
JUMPE T3,CPOPJ1##
POPJ P,
;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
;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,-TTFCML## ;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
MOVE 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
MOVE 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
JRST TPOPJ##
SUBTTL SPPRM. UUO
;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
SKIPN DEVCHR(F)
PJRST ECOD2## ;YES--NOT ASSIGNED OR INITED
;FALL INTO SPPRM1
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
PUSHJ P,SETSPB## ;CREATE SPB AND SET UP DEVSPM IF NECESSARY
; RETURNS WITH T1 POINTING TO SPB
PJRST ECOD4## ;NO FREE CORE
SKIPN DEVCHR(F) ;FAKE DDB?
PJRST ECOD2## ;YES--NOT ASSIGNED OR INITED
;FALL INTO SPPRM1
SPPRM1: SUBI P1,2 ;ADJUST FOR DEVICE NAME AND FUNCTION
JUMPLE P1,SPPRM3 ;IF NO ARGS TO SAVE
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
SPPRM3: 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 ;LOAD STD VFU (DEP)
XWD 2,DVPCAL ;ENABLE NON-STD VFU LOAD (DEP)
XWD 3,DVPCAL ;DISABLE VFU LOAD
XWD 11,DVPCAL ;LOAD RSX-20F LP RAM
XWD 12,DVPCAL ;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
XWD 1005,DVPCAL ;READ/SET FORMS TYPE (DEP)
XWD 1006,DVPCL1 ;READ/CLEAR DECTAPE READ/WRITE INFO
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
UDEVOP: 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
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: LDB T2,PJOBN## ;GET JOB WHO OWNS DEVICE
CAME T2,J ;DO WE OWN IT?
TRNE T1,1000 ;READ?
CAIA ;OK
JRST ECOD6## ;DEVICE MUST BE INITED
DVPCL1:
IFN FTMP,<
PUSHJ P,SETCPP## ;GET ON CPU WHICH OWNS DEVICE
JRST ECOD7## ;CPU DEAD, SAY DEVICE OFFLINE
>
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/SET 'CONTROLLED BY MDA BIT (DVCMDA)
;
LBLBTS==(77000,,0) ;BITS 'FINP+LBLNED+LBLWAT+LBLSTP+FOUT+LBLEOF'
DVPMDC: TDZA T3,T3 ;INDICATE 'CLEAR' FUNCTION
DVPMDS: MOVEI T3,1 ;INDICATE 'SET' FUNCTION
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
SKIPN T3 ;MUST BE CLEARING MAG TAPE
TLNN T2,DVMTA ; STATUS BIT - IF NO, THEN
SKIPA ; DO NOT CLEAR THE
TLO T3,400000 ; TAPE LABELING STATUS BITS
MOVSI T2,DVCMDA ;LOAD UP DVCMDA
XCT [ANDCAM T2,DEVCHR(F)
IORM T2,DEVCHR(F)](T3) ;CLEAR/SET DVCMDA
JUMPGE T3,CPOPJ1## ;RETURN IF NOT CLEARING DVCMDA FOR MTA
MOVE S,DEVIOS(F) ;LOAD UP S
TLZ S,LBLBTS ;CLEAR TAPE LABELING BITS
MOVEM S,DEVIOS(F) ;SAVE NEW STATE
JRST CPOPJ1## ;RETURN
>;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 FILOP. FUNCTION WORD
FO.PRV==(1B0) ;USE PRIVILEGES
FO.ASC==(1B1) ;ASSIGN EXTENDED CHANNEL
FO.UOC==(1B2) ;USE ALREADY-OPENED CHANNEL
FO.CFW==(1B3) ;CHANNEL ADDRESS AND FUNCTION CODE WORD
FO.CHN==(777B17) ;CHANNEL NUMBER FIELD
FO.FNC==777777 ;FUNCTION CODE FIELD OR ADDRESS
;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
FOP.OC==(1B14) ;USE ALREADY-OPENED CHANNEL
FOP.AW==(1B15) ;ALLOCATION IS SPECIFIED IN WORDS
FOP.RD==(1B16) ;DEVICE MUST BE A DISK
;DISPATCH TABLE FOR FILOP. FUNCTIONS
FOPTAB:
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+FOP.RD,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
XWD FOP.RD,CPOPJ1## ;(25) SEEK
XWD FOP.RD,FOPRRC ;(26) REWRITE RIB IF CHANGED
EXP FOPGTF ;(27) UGETF
EXP FOPMTP ;(30) MTAPE
EXP FOPUTP ;(31) UTPCLR
XWD FOP.RN+FOP.LK+FOP.AW,FOPEN ;(32) RENAME W/ALLOC. IN WORDS
EXP FOPFIL ;(33) RETURN FILESPEC
EXP FOPXIN ;(34) EXTENDED DUMP MODE INPUT
EXP FOPXOU ;(35) EXTENDED DUMP MODE OUTPUT
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,FOPE65 ;ILLEGAL IF NEGATIVE OR ZERO
HRR M,T1 ;POINT TO FIRST ARGUMENT
PUSHJ P,GETWDU## ;GET FIRST ARGUMENT
TLO T2,FOP.PV ;ASSUME PRIVILEGES DESIRED
TLZE T1,FO.ASC ;ASSIGN A FREE CHANNEL?
TLO T2,FOP.XC ;YES, REMEMBER THAT
TLZE T1,FO.UOC ;USE ALREADY-OPENED CHANNEL?
TLO T2,FOP.OC ;YES--REMEMBER IT
TLZE T1,FO.PRV ;DOES HE WANT TO BE PRIV'D?
PUSHJ P,PRVJO## ;IS HE PRIV'ED
TLZ T2,FOP.PV ;NO, CLEAR THE BIT
TLZN T1,FO.CFW ;CHANNEL AND FUNCTION WORD?
JRST FILOP1 ;NO, PROCEED TRADITIONALLY
HRR M,T1 ;POINT TO CHANNEL AND FUNCTION WORD
PUSHJ P,GETWDU## ;GET IT
MOVE P1,T1 ;SAVE IT
HLR M,T1 ;POINT TO CHANNEL WORD
TLNE T2,FOP.XC ;ASSIGN AN EXTENDED CHANNEL?
TDZA T1,T1 ;YES, DON'T USE STALE CHANNEL NUMBER
PUSHJ P,GETWDU## ;GET CHANNEL NUMBER
EXCH T1,P1 ;GET BACK FUNCTION CODE
JUMPL P1,FOPE61 ;NEGATIVE CHANNEL NUMBER IS TOO BIG
SKIPA M,FOPAP ;RESTORE M
FILOP1: LDB P1,[POINT 9,T1,17] ;EXTRACT CHANNEL NUMBER
CAILE P1,HIGHXC## ;OUT OF RANGE?
JRST FOPE61 ;ERROR - CHANNEL TOO BIG
ANDI T1,-1 ;REDUCE TO JUST FUNCTION CODE
CAILE T1,FOPMAX ;FUNCTION TOO BIG?
JRST FOPE60 ;ERROR - UNKNOWN FILOP. FUNCTION
TLNE T2,FOP.XC ;ASSIGN AN EXTENDED CHANNEL?
JUMPN P1,FOPE62 ;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,.USCTA ;STORE UDX FOR THIS UUO
CAIE T2,FOPEN ;OPEN?
JRST [MOVE T4,DEVMOD(F) ;DEVICE CHARACTERISTICS
TLNN T4,DVTTY ;NUL SAYS ITS A DSK
TLNN T4,DVDSK ;IS IT A DSK?
TLNN T3,FOP.RD ;NO IS A DSK REQUIRED
JRST (T2) ;NO, JUST DISPATCH
JRST CPOPJ1##] ;YES, FUNCTIONS IS A NOOP
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,.USCTA
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,.USCTA ;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: SKIPL USRHCU## ;SAVE/GET IN PROGRESS?
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
;ROUTINE TO STORE IN-YOUR-BEHALF PPN IF SPECIFIED
FOPIYB: HRRZ T1,-2(P) ;# OF ARGUMENTS
MOVE T2,DEVMOD(F) ;DEVICE CHARACTERISTICS
SKIPGE DEVSPL(F) ;SPOOLED DEVICE?
TLO T2,DVDSK ;YES--PRETEND IT'S A DISK
CAIL T1,10 ;8TH ARGUMENT SPECIFICATION
TLNN T2,DVDSK ;ONLY IF A DSK
POPJ P, ;NO
HRR M,-3(P) ;GET ARGUMENT POINTER
HRRI M,7(M) ;POINT TO "IN-YOU-BEHALF" PPN
PUSHJ P,GETWDU## ;GET IT
TLNE P2,FOP.PV ;DON'T STORE IF NOT PRIV'ED PROG INVOKING PRIVS
MOVEM T1,DEVUPP##(F) ;STORE IT FOR FNDFIL
MOVSI T1,(UP.IYB) ;IN YOUR BEHALF (FOR IPCSER)
SKIPE DEVUPP##(F) ;SPECIFIED?
IORM T1,.USBTS ;YES
POPJ P,
;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
;CHECK OUT THE LOOKUP/ENTER AND RENAME/DELETE BLOCKS, IF ANY
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
TRNN M,-1 ;LOOKUP/ENTER BLOCK GIVEN?
JRST FOPN0A ;NO
PUSHJ P,FCLERB ;CHECK LOOKUP/ENTER BLOCK
JRST FOPE63 ;ADDRESS CHECK
FOPN0A: JUMPE P2,FOPEN0 ;JUMP IF NO RENAME/DELETE BLOCK
HRR M,P2 ;ADDRESS OF THE RENAME/DELETE BLOCK
PUSHJ P,FCLERB ;MAKE SURE THATS IN CORE
JRST FOPE63 ;ADDRESS CHECK
;RANGE CHECK THE "RETURNED" PATH BLOCK, IF ANY
FOPEN0: HRRZ T4,FOPFLG ;GET ARG COUNT
CAIGE T4,7 ;PATH POINTER
JRST FOPEN6 ;NO--ALL IS WELL
HRR M,FOPAP ;GET ARG POINTER
HRRI M,6(M) ;PATH PTR
PUSHJ P,GETWRD## ;GET ARGUMENT
JRST FOPE63 ;ADDRESS CHECK READING ARGUMENTS
JUMPE T1,FOPEN6 ;JUMP IF PATH ISN'T REQUIRED
TLNN T1,-1 ;LENGTH SPECIFIED?
TLO T1,3 ;NO, DEFAULT TO 3
HLRZ T2,T1 ;COPY LENGTH
HRLI T1,(IFIW) ;MAKE SECTION RELATIVE
PUSHJ P,ARNGE## ;RANGE CHECK
JRST FOPE63 ;ADDRESS CHECK
JFCL ;ADDRESS OK BUT ILLEGAL FOR I/O (IGNORED HERE)
; RANGE CHECK THE "RETURNED" FILESPEC BLOCK, IF ANY
FOPEN6: CAIGE T4,11 ;HAVE A POINTER?
JRST FOPVMX ;NO
HRR M,FOPAP ;GET ARGUMENT POINTER
HRRI M,10(M) ;FILESPEC BLOCK OFFSET
PUSHJ P,GETWRD## ;GET ARGUMENT
JRST FOPE63 ;ADDRESS CHECK READING ARGUMENT
HLRE T2,T1 ;GET THE LENGTH
JUMPE T2,FOPVMX ;OK IF NO POINTER
JUMPL T2,FOPE66 ;FILESPEC BLOCK LENGTH NEGATIVE OR ZERO?
HRLI T1,(IFIW) ;MAKE SECTION RELATIVE
PUSHJ P,ARNGE## ;RANGE CHECK
JRST FOPE63 ;ADDRESS CHECK
JFCL ;ADDRESS OK BUT ILLEGAL FOR I/O (IGNORED HERE)
;ALLOCATE AN "EXTENDED" I/O CHANNEL IF NECESSARY
FOPVMX: MOVSI T1,FOP.XC ;EXTENDED CHANNEL REQUESTED BIT
TDNN T1,FOPFLG ;WAS AN EXTENDED CHANNEL REQUESTED?
JRST FOPVM4 ;NO, PROCEED TRADITIONALLY
HRRZ T1,.USCTA ;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 FOPE56 ;ERROR - NO PER-PROCESS SPACE AVAILABLE
HRRM T1,.USCTA ;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 FOPE57 ;ERROR - NO FREE CHANNELS AVAILABLE
;HERE WHEN AN AVAILABLE CHANNEL WAS FOUND
FOPVM3: ADDI P1,20 ;EXTENDED CHANNEL NUMBER
SETZ F, ;IF WE JUST ASSIGNED A CHANNEL, IT AIN'T OPEN
;STORE CHANNEL NUMBER FOR THE USER
FOPVM4: HRLM P1,.USCTA ;CHANNEL NUMBER
MOVE P2,FOPFLG ;GET THE FILOP CONTROL FLAGS
HRR M,FOPAP ;GET ARGUMENT POINTER
PUSHJ P,GETWDU## ;GET CHANNEL NUMBER
DPB P1,[POINT 9,T1,17] ;STORE POSSIBLE EXTENDED CHANNEL NUMBER
TLNE T1,FO.ASC ;ASSIGN EXTENDED CHANNEL?
TLNN T1,FO.CFW ;AND CHANNEL AND FUNCTION WORD?
JRST FOPVM5 ;NO, PROCEED TRADITIONALLY
HRR M,T1 ;POINT TO FUNCTION WORD
PUSHJ P,GETWDU## ;GET CHANNEL AND FUNCTION WORD
HLR M,T1 ;POINT TO CHANNEL NUMBER WORD
SKIPA T1,P1 ;GET CHANNEL NUMBER
FOPVM5: TLZE T1,FO.ASC ;CLEAR THE ASSIGN EXT CHAN BIT
PUSHJ P,PUTWDU## ;STORE CHANNEL FOR THE USER IF REQUESTED
HRR M,FOPAP ;RESTORE ARGUMENT POINTER
TLNN P2,FOP.OC ;USE ALREADY-OPENED CHANNEL?
JRST FOPVM6 ;NO, MUST DO AN OPEN
JUMPE F,FOPE46 ;A CHANNEL MUST BE OPEN
TLNE P2,FOP.RN!FOP.DL;CHANNEL OPEN, IF FOR A RENAME OR DELETE
TLNE F,LOOKB!ENTRB ;THEN A FILE MUST BE LOOKUP'ED AS WELL
JRST FOPEN2 ;VALID CHANNEL - SKIP THE OPEN
JRST FOPE46 ;ERROR - CHANNEL NOT OPENED
;HERE TO OPEN A NEW FILE FOR SOME SORT OF ACCESS
FOPVM6: HRRI M,1(M) ;POINT TO OPEN BLOCK
MOVE T1,.USFOP
MOVEM T1,FOPEXT
; TLNE P2,FOP.RN+FOP.DL ;RENAMES OR DELETES
; JUMPN F,FOPEN2 ;YES, GO IF THE FILE IS ALREADY OPEN
MOVSI T1,(UP.FIP) ;MARK FILOP
IORM T1,.USBTS ;IN PROGRESS
PUSHJ P,UOPEN ;TRY TO OPEN
JRST FOPOER ;CAN NOT OPEN
MOVSI T1,DVDSK ;DISK DDB?
TDNN T1,DEVMOD(F)
JRST FOPVM7 ;NO, NO SUPER I/O IF NOT A DISK
MOVSI T1,DEPSIO## ;CLEAR THE BIT INITIALLY
ANDCAM T1,DEVPTB##(F)
TLNN P2,FOP.SO ;SUPER I/O FOR THIS FUNCTION?
JRST FOPVM7 ;NO
IORM T1,DEVPTB##(F) ;LIGHT BIT SO SETSUP KNOWS
FOPVM7: HRRZ T1,FOPFLG ;GET ARG COUNT
CAIN T1,4 ;ONLY DOING AN OPEN?
JRST FOPFSP ;YES--SEE IF RETURNED FILESPEC WANTED
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
SKIPG T2 ;SKIP IF NUMBER GIVEN
MOVEI T2,0 ;ELSE USE DEFAULT
HRRZ T3,FOPFLG ;GET ARGUMENT COUNT
HRR M,FOPAP ;GET ARGUMENT POINTER
HRRI M,12(M) ;POINT AT BUFFER SIZE WORD
CAIL T3,13 ;SIZE WORD SPECIFIED?
PUSHJ P,GETWDU## ;YES, GET SIZE
CAIGE T3,13 ;SIZE WORD SPECIFIED?
TDZA U,U ;NO, USE DEFAULT BUFFER SIZE
HLRZ U,T1 ;YES, USE USER SUPPLIED BUFFER SIZE
CAIGE T3,12 ;BUFFER STARTING ADDRESS SPECIFIED?
JRST FOPENA ;NO, DO NORMAL OUTBUF
HRR M,FOPAP ;GET ARGUMENT POINTER
HRRI M,11(M) ;POINT AT BUFFER STARTING ADDRESS
PUSHJ P,GETWDU## ;GET BUFFER STARTING ADDRESS
HLRZS T1 ;OUTPUT BUFFER STARTING ADDRESS
JUMPE T1,FOPENA ;IF ZERO, SETUP THE BUFFERS AT JOBFF
HRR M,T2 ;NUMBER OF BUFFERS
PUSHJ P,FOUTBF ;SET UP OUTPUT RING STARTING AT (T1)
JRST FOPEN1 ;CHECK FOR INPUT BUFFERS
FOPENA: SKIPN T1,FOPEXT
MOVE T1,.JDAT+JOBFF##
MOVEM T1,.JDAT+JOBFF##
MOVEM T1,.USFOP
HRR M,T2 ;PUT IN M
PUSHJ P,UOUTBS ;DO THE OUTBUF
FOPEN1: HRRE T2,FOPTMP ;GET THE NUMBER OF INPUT
; BUFFERS REQUESTED
JUMPE T2,FOPEN2 ;JUMP IF NONE REQUESTED
SKIPG T2 ;SKIP IF NUMBER GIVEN
MOVEI T2,0 ;ELSE USE DEFAULT
HRRZ T3,FOPFLG ;GET ARGUMENT COUNT
HRR M,FOPAP ;GET ARGUMENT POINTER
HRRI M,12(M) ;POINT AT BUFFER SIZE WORD
CAIL T3,13 ;SIZE WORD SPECIFIED?
PUSHJ P,GETWDU## ;YES, GET SIZE
CAIGE T3,13 ;SIZE WORD SPECIFIED?
TDZA U,U ;NO, USE DEFAULT BUFFER SIZE
HRRZ U,T1 ;YES, USE USER SUPPLIED BUFFER SIZE
CAIGE T3,12 ;BUFFER STARTING ADDRESS SPECIFIED?
JRST FOPENB ;NO, DO NORMAL INBUF
HRR M,FOPAP ;GET ARGUMENT POINTER
HRRI M,11(M) ;POINT AT BUFFER STARTING ADDRESS
PUSHJ P,GETWDU## ;GET BUFFER STARTING ADDRESS
HRRZS T1 ;INPUT BUFFER STARTING ADDRESS
JUMPE T1,FOPENB ;IF ZERO, SETUP BUFFERS AT JOBFF
HRR M,T2 ;NUMBER OF BUFFERS
PUSHJ P,FINBF ;SET UP INPUT RING STARTING AT (T1)
JRST FOPEN2 ;CHECK FOR INPUT BUFFERS
FOPENB: HRR M,T2 ;NUMBER OF BUFFERS
PUSHJ P,UINBS ;BUILD BUFFERS
;HERE TO DO LOOKUP AND/OR ENTER
FOPEN2: HRRZ T1,FOPFLG ;GET # OF ARGUMENTS
CAIN T1,5 ;DONE YET?
JRST FOPFSP ;YES--SEE IF RETURNED FILESPEC WANTED
MOVE P2,FOPFLG ;FLAGS
MOVE T1,DEVIOS(F) ;DEVICE STATUS
LDB T1,PIOMOD## ;I/O MODE
TLNE P2,FOP.AP ;APPENDING?
CAIL T1,SD ;AND BUFFERED MODE?
JRST FOPN2A ;NO TO EITHER
MOVE T1,DEVMOD(F) ;DEVICE CHARACTERISTICS
TLNN T1,DVTTY ;NUL:?
TLNN T1,DVDSK ;MAKE SURE ITS REALLY A DSK
JRST FOPN2A ;SKIP THIS IF NOT A REAL DISK
HLRZ U,DEVBUF(F) ;POINTER TO OUTPUT BUFFER HEADER
PUSHJ P,OUTF ;MAKE SURE CAN'T PAGE FAULT AFTER LOOKUP/ENTER
FOPN2A: HLLZ T1,FOPFLG ;GET CONTROL FLAGS BACK
MOVSI T2,(UP.FIP) ;FILOP IN PROGRESS
TLNN T1,FOP.PV ;WANT TO USE OUR PRIVS?
TLO T2,(UP.IYB) ;NO, THEN LIE ABOUT JACCT
IORM T2,.USBTS ;FOR ACCESSOR'S IPCF CAPABILITIES
TLNE T1,FOP.RN!FOP.DL;IF A RENAME OR DELETE FUNCTION
TLNN T1,FOP.OC ;ON AN ALREADY-OPENED CHANNEL
CAIA ; (IT ISN'T)
JRST FOPEN8 ;JUST DO THE RENAME/DELETE
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
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
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
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
PUSHJ P,FOPIYB ;STORE IN-YOUR-BEHALF PPN IF NEEDED
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
TRZ T1,RB.BIT
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
HLRZ T1,FOPBLK ;GET FLAG BITS
ANDI T1,RB.BIT
IORI 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
MOVE T2,T1
TRZ T2,RB.BIT
CAIL T2,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## ;..
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
JUMPE T1,FOPN8B ;RENAME TO ZERO (DELETE) IS A SHORT BLOCK
TLNN T1,-1 ;EXTENDED BLOCK
HRRI M,UUXNAM(M) ;YES, POINT AT THE FILE NAME
FOPN8B: 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
MOVSI T1,DEPALW ;ALLOCATION-IN-WORDS FLAG
TLNE P2,FOP.AW ;IS HE DOING IT?
IORM T1,DEVJOB(F) ;YES, TELL FILSER
MOVEI T1,UUNEXT-UUNNAM(M) ;WHERE THE EXTENSION IS STORED
HRLZM T1,FOPEXT ;SAVE THAT IN CASE OF AN ERROR
MOVE T2,DEVMOD(F) ;DEVICE CHARACTERISTICS
TLNN T2,DVLNG ;LONG DISPATCH VECTOR?
JRST FOPN8A ;NO, DON'T ATTEMPT A RENAME
PUSHJ P,FOPIYB ;STORE IN-YOUR-BEHALF PPN IF NEEDED
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
MOVE T1,DEVMOD(F) ;DEVICE CHARACTERISTICS
TLNN T1,DVTTY ;AVOID NUL:
TLNN T1,DVDSK ;ONLY DISKS HAVE PATHS
JRST FOPEN9 ;NOT A DISK, SO DON'T DO THE PATH
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
HLRZS 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,FLMCOM ;SO FILUUO DOESN'T CLOBBER USER'S AC
PUSHJ P,PTHUUO## ;DO THE PATH UUO
JFCL ;SHOULD NEVER FAIL
TLZ M,FLMCOM
HRLM P1,.USCTA ;RESET IO CHAN
PUSHJ P,SETUF ;F GOT WIPED
JRST FOPXI1 ;CAN'T HAPPEN
FOPEN9: MOVE P2,FOPFLG ;GET FLAGS
TLZN P2,FOP.NF ;CREATING INSTEAD OF UPDATING
JRST FOPN9A ;NO--CONTINUE
MOVEM P2,FOPFLG ;YES--CLEAR FLAG
MOVSI T1,DEPFFA ;FORCE FILE INTO
IORM T1,DEVJOB(F) ; UPDATE MODE
HRRI M,CLSDLL ;DON'T DEALLOCATE
PUSHJ P,CLOSE1 ; ..
PUSHJ P,WAIT1## ; ..
TLNE F,OCLOSB ;DID THE CLOSE REALLY HAPPEN?
JRST FOPN3A ;YES, MUST BE SFD, LET FILSER GIVE HIM ERROR
FOPN9A: SKIPE P2,FOPFLG ;GET FLAGS
TLNN P2,FOP.AP ;WANT TO APPEND?
JRST FOPFSP ;NO--SEE IF RETURNED FILESPEC WANTED
MOVE T1,DEVMOD(F) ;IS THIS A DISK
TLNE T1,DVTTY ;NUL:?
JRST FOPFSP ;YES--SEE IF RETURNED FILESPEC WANTED
TLNN T1,DVDSK ; ..
JRST FOPN11 ;NO, ALL DONE UNLESS AN MTA
MOVEI T1,UP.MLB ;MERGE LAST BLOCK
IORM T1,.USBTS ; IF WE CAN
;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
JUMPE T1,FOPN10 ;DON'T TRY TO MERGE IF NEW FILE
MOVEM T1,FOPTMP ;SAVE BLK #
HLRZ U,DEVBUF(F) ;GET RING ADR
MOVE T1,FOPFLG ;GET THE FLAGS
HRR T1,.USBTS ;AND RELEVANT UPT BITS FOR TESTING
TLNE T1,FOP.AP ;IF THIS IS APPEND,
TRNN T1,UP.MLB ;ONLY DO THIS IF FOPEN2 DIDN'T
PUSHJ P,OUTF ;UNVIRGINIZE HEADER - ZERO BUFFER
MOVE T1,FOPTMP ;RESTORE BLK #
HRRZ T3,DEVACC##(F) ;ADDRESS OF A.T. AGAIN
MOVEI T2,UP.MLB ;MERGE LAST BLOCK FLAG
TDNN T2,.USBTS ;SHOULD WE?
JRST FOPN10 ;NO - DON'T READ IN LAST BLOCK
ANDCAM T2,.USBTS ;YES - CLEAR THE FLAG AND CONTINUE
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(FOPTMP) INTO BUFFER AT C(T3)
MOVEM T2,FOPBLK ;SAVE WORD COUNT
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
IFN FTXMON,<
SETZ T2, ;NO PARTIAL SECTION UPDATES FROM MAPIO
DPB T2,DEYISN## ;SAVE IN CASE CHECKSUM NEEDED
>
MOVE W,FOPTMP ;BLOCK #
PUSHJ P,USETO0## ;SETUP POINTERS
MOVEM S,FOPTMP ;SAVE STATUS
TRO S,D ;SET DUMP MODE
TLZ S,IO ;READING
PUSHJ P,UUOSET## ;MAKE EVERYTHING OK
JRST FCLOSI ;RETURN IOIMPM
PUSHJ P,UUOPWR## ;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
HLRZ U,DEVBUF(F) ;RING HEADER
HRRZ T2,DEVOAD(F) ;FOR BYTE POINTER
EXCTUX <HLRZ J,(T2)> ;BUFFER SIZE
TRZ J,400177 ;CLEAR EXTRANEOUS BITS
SUB J,FOPBLK ;MINUS WORDS WE READ
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,USETO0## ;SET POINTERS
JRST FOPFSP ;SEE IF RETURNED FILESPEC WANTED
FOPN11: TLNN T1,DVMTA ;MAGTAPE?
JRST FOPFSP ;NO--SEE IF RETURNED FILESPEC WANTED
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 FOPFSP ; DONE--SEE IF RETURNED FILESPEC WANTED
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
MOVE T3,DEVSER(F) ;DISPATCH ADDRESS
PUSHJ P,DIN(T3) ;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 FOPN13 ;WIN, CONTINUE ONWARD
FOPN12: PUSHJ P,BUFCLR ;ZERO THE BUFFER
JFCL ;SHOULD NEVER HAPPEN
FOPN13:
IFN FTTLAB,<
MOVE U,TDVUDB##(F) ;UDB ADDRESS
LDB T1,TUYLTP## ;GET LABEL TYPE
SKIPE T1 ;BYPASS?
SKIPN %SITLP## ;LABLE PROCESSOR?
JRST FOPFSP ;NO--SEE IF RETURNED FILESPEC WANTED
MOVEI T1,LR.CLI ;SEND INPUT CLOSE
PUSHJ P,TPCLSX## ;MSG TO MDA
>
JRST FOPFSP ;DONE--SEE IF RETURNED FILESPEC WANTED
DOMTAP: PUSHJ P,MTAPE0## ;TEL TAPUUO WHAT TO DO
PUSHJ P,TPSKPW## ;WAIT, THEN CONTINUE
TRNN S,IODERR!IODTER!IOIMPM
AOSA (P) ;WON
HRRZ T1,S ;LOST, RETURN ERROR STATUS BITS
POPJ P, ;RETURN TO CALLER
;HERE TO DO A USETI AND RETURN STATUS
FUSTI: SKIPA W,[DSI] ;DISPATCH TO USETI
;HERE TO DO A USETO AND RETURN STATUS
FUSTO: MOVEI W,DSO ;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
MOVE T4,DEVMOD(F) ;GET DEVICE CHARACTERISTICS
TLNE T4,DVDSK ;IF DISK,
TLNE F,ENTRB!LOOKB ;AND NO ENTER OR LOOKUP,M=ADDR OF BLK#
HRR M,W ;(NO) SETUP M WITH BLOCK#
TLNN T4,DVLNG ;LONG DISPATCH TABLE?
JRST FOPFSP ;NO, DON'T DISPATCH (NO-OP)
IFN FTMP,<
PUSHJ P,SETCPF## ;GET ON RIGHT CPU
>
PUSH P,T1 ;SAVE T1
PUSHJ P,WAIT2 ;WAIT FOR I/O
MOVE T1,(P) ;GET DISPATCH OFFSET BACK
CAIN T1,DSO ;USETO?
SKIPA T1,[IOERR] ;YES--ONLY CHECK REAL I/O ERROS
MOVEI T1,IOERR+IODEND ;ELSE CHECK I/O ERRORS PLUS EOF
EXCH T1,(P) ;SAVE CONDITIONS TO CHECK,GET DISPATCH OFFSET
ADD T1,DEVSER(F) ;DISPATCH TABLE ADDR
PUSHJ P,(T1) ;CALL USET CODE
HRRZ T1,DEVIOS(F) ;I/O STATUS
TDNN T1,(P) ;ERRORS OR END OF FILE?
AOS -1(P) ;NO, SKIP RETURN TO THE USER
POP P,(P) ;TRIM STACK
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
HRRI M,CLSDLL ;DON'T DEALLOCATE
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
TLNN T1,DVTTY ;GOOD RETURN IF NUL
TLNN T1,DVDSK ;DISK?
JRST FOPFSP ;NO--SEE IF RETURNED FILESPEC WANTED
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 T2,WAIT ;WAIT
JRST FOPOU1
FOPXIN: PUSHJ P,FOPLM ;MAKE SURE ITS DUMP MODE AND IF SO, SET DEPSOO
FOPIN: MOVEI T2,TIN ;INPUT
MOVEI T3,DSI ;USETI
JRST FOPOU3
FOPXOU: PUSHJ P,FOPLM ;MAKE SURE ITS DUMP MODE AND IF SO, SET DEPSSO
FOPOUT: MOVEI T2,TOUT ;OUTPUT
MOVEI T3,DSO ;USETO
FOPOU3: ADD T3,DEVSER(F) ;DISPATCH TABLE
HRRZ T1,FOPFLG
MOVE T4,DEVMOD(F)
CAIG T1,2 ;MORE THAN 2 ARGUMENTS?
JRST FOPOU2 ;NO, SKIP USETI/USETO CODE
PUSH P,M ;SAVE CURRENT ARGUMENT POINTER
HRRI M,2(M) ;GET THE THIRD ARGUMENT
PUSHJ P,GETWDU## ;GET THE BLOCK NUMBER ADDRESS
JUMPE T1,FOPOU5 ;IF ADDRESS=0, THEN NO USETI/O
HRR M,T1 ;POINT TO THE ADDRESS
PUSHJ P,GETWDU## ;READ THE ACTUAL BLOCK NUMBER
PUSH P,W ;SAVE W
MOVE W,T1 ;PUT IT IN W
PUSH P,T2 ;SAVE ADDRESS OF I/O ROUTINE
TLNN T4,DVLNG ;LONG DISPATCH TABLE?
JRST FOPOU4 ;NO, DON'T DISPATCH (NO-OP)
IFN FTMP,<
PUSHJ P,SETCPF## ;GET ON RIGHT CPU
>
PUSH P,T3 ;SAVE T3
PUSHJ P,WAIT2 ;WAIT FOR I/O
POP P,T3 ;RESTORE T3
PUSHJ P,(T3) ;CALL USETI/USETO
FOPOU4: POP P,T2 ;RESTORE ADDRESS OF I/O ROUTINE
POP P,W ;RESTORE W
FOPOU5: POP P,M ;RESTORE ARGUMENT POINTER
HRRZ T1,FOPFLG
FOPOU2: CAIG T1,1 ;MORE THAN 1 ARGUMENT?
TDZA T1,T1 ;NO, NO BUFFER ADDRESS
PUSHJ P,GETWD1## ;YES, GET THE BUFFER ADDRESS
HRR M,T1
IFN FTXMON,<
SKIPGE DEVISN(F) ;MULTI-SECTION I/O?
DPB T1,[POINT 23,M,35] ;YES, THEN ALLOW IOWD LIST TO START IN ANY SECTION
>
HRRZ T4,DEVSER(F)
FOPOU1: PUSHJ P,(T2) ;DO THE IN, OUT, OR WAIT
AOS (P) ;GOOD RETURN
MOVSI T1,DEPSOO ;MULTI-SECTION I/O BIT
ANDCAM T1,DEVISN(F) ;CLEAR THAT ALWAYS
HRRZ T1,S ;DEVICE STATUS
PJRST STOTAC## ;RETURN THAT FOR THE USER
FOPLM: LDB T1,PIOMOD## ;GET I/O MODE
CAIGE T1,SD ;ONLY DUMP MODE IS LEGAL
JRST [POP P,(P) ;POP OFF CALLER'S RETURN ADDRESS
MOVEI T1,IDMERR;ILLEGAL DATA MODE ERROR CODE
JRST STOTAC##] ;RETURN THAT TO THE USER
MOVSI T1,DEPSOO ;OK FOR IOWDS TO CROSS SECTION BOUNDARIES
IORM T1,DEVISN(F) ;LITE THAT FOR V2PADR
POPJ P, ;RETURN
FOPLP: AOS -1(P) ;FILOP. WILL SKIP
MOVE T1,DEVMOD(F) ;MUST HAVE LONG DISPATCH TABLE
TLNN T1,DVLNG
JRST TPOPJ## ;ELSE FILOP. EXITS IMMEDIATELY
MOVE T4,DEVSER(F) ;GET ADDR OF DISPATCH TABLE
POPJ P,
FOPRRC: AOS (P)
PJRST FWRBIC## ;YES, REWRITE RIB IF CHANGED
; RETURN THE FILESPEC ASSOCIATED WITH A CHANNEL
; POSSIBLE ERRORS ARE:
; ADDRESS CHECK READING ARGUMENTS
; ADDRESS CHECK STORING ANSWER
; NEGATIVE OR ZERO ARGUMENT COUNT
; ARGUMENT LIST TOO SHORT
;
FOPFIL: PUSHJ P,FOPFI0 ;GET THE FILESPEC
PJRST FOPXIT ;FAILED--PROPAGATE ERROR BACK
JRST CPOPJ1## ;RETURN
FOPFI0: PUSHJ P,SAVE2## ;SAVE P1 AND P2
MOVE P1,DEVMOD(F) ;GET DEVICE TYPE BITS
PUSHJ P,GETWR1## ;GET THE WORD COUNT AND ARGUMENT BLOCK ADDRESS
JRST FOPF63 ;ADDRESS CHECK READING ARGUMENTS
HLRE P2,T1 ;COPY WORD COUNT
JUMPLE P2,FOPF65 ;NEGATIVE OR ZERO ARGUMENT COUNT?
HRRI M,-1(T1) ;POINT TO THE ARGUMENT BLOCK
; NODE NAME
REPEAT 0,< ;NODE NAME RESERVED FOR NOW
IFE FTNET,<MOVEI T1,0> ;CLEAR NODE NAME IF NO NETWORKS
IFN FTNET,<
PUSHJ P,FNDDEV ;GET STATION NUMBER
SKIPN T1 ;USE IT IF NON ZERO
MOVE T1,JBTLOC## ; OTHERWISE USE CENTRAL SITE NUMBER
SKIPN DEVCHR(F) ;A SPOOLED DDB?
HRRZ T1,JBTLOC##(J) ;YES--USE JOB'S LOCATION
NETDBL ;GET THE NETSER INTERLOCK
PUSHJ P,SRCNDB## ;FIND THE NODE BLOCK
TDZA T1,T1 ;CAN'T, SO RETURN ZERO
HLRZ T1,NDBSNM##(W) ;GET THE ADDRESS OF THE NODE NAME
MOVE T1,(T1) ;GET THE SIXBIT NODE NAME
NETDBU ;RELEASE THE NETSER INTERLOCK
>;END IFN FTNET
> ;END REPEAT 0
MOVEI T1,0 ;NODE NAME RESERVED FOR NOW
PUSHJ P,FOPFIX ;STORE THE NODE NAME
; DEVICE
MOVE T1,DEVNAM(F) ;GET DEVICE NAME
TLNN P1,DVDSK ;A DISK?
JRST FOPFI1 ;NO--GO CLEAN UP DEVICE NAME
HRRZ T2,DEVUNI##(F) ;UDB POINTER
JUMPE T2,FOPFI2 ;NO UNIT IF A KNOWN SEGMENT
MOVE T1,UDBNAM(T2) ;MAYBE JUST OPENED A UNIT
SKIPN UNILOG(T2) ;BETTER CHECK
JRST FOPFI2 ;NOT PART OF A STRUCTURE
HRRZ T2,DEVACC##(F) ;GET ACCESS TABLE ADDRESS
JUMPE T2,FOPFI2 ;MAY BE ZERO (SUPER I/O)
LDB T2,ACYFSN## ;GET STRUCTURE NUMBER
MOVE T1,@TABSTR##(T2);FINALLY GET STRUCTURE NAME
JRST FOPFI2 ;SKIP NETWORK STUFF
FOPFI1:
REPEAT 0,< ;DON'T ASSEMBLE IF NODE NAME RESERVED FOR FUTURE
TLNE P1,DVTTY ;A TTY?
JRST FOPFI2 ;YES--DON'T MESS WITH THE NAME
LSHC T1,-6 ;SHIFT UNIT NUMBER INTO T2
LSH T1,-^D12 ;SHIFT OUT STATION NUMBER
LSHC T1,^D18 ;LEFT JUSTIFY DEVICE AND UNIT IN T1
> ;END REPEAT 0
FOPFI2: PUSHJ P,FOPFIX ;STORE THE DEVICE NAME
; FILE NAME AND EXTENSION
TLNN P1,DVDIR ;A DIRECTORY DEVICE?
JRST FOPFI6 ;NO--FINISH UP
MOVE T1,DEVFIL(F) ;GET FILE NAME
PUSHJ P,FOPFIX ;STORE IT
HLLZ T1,DEVEXT(F) ;GET EXTENSION
PUSHJ P,FOPFIX ;STORE IT
; DIRECTORY
TLNN P1,DVDSK ;CAN ONLY BE A DISK
JRST FOPFI6 ;ALL OTHERS DON'T HAVE A DIRECTORY
MOVE T1,DEVPPN(F) ;GET THE PPN
PUSHJ P,FOPFIX ;STORE IT
HRRZ P1,DEVSFD##(F) ;GET PATH POINTER
JUMPE P1,FOPFI6 ;THERE ISN'T ONE
PUSH P,[0] ;MARK THE END OF THE PATH
FOPFI3: PUSH P,NMBNAM##(P1) ;SAVE THE SFD NAME
FOPFI4: HLRZ P1,NMBPPB##(P1) ;BACK ONE LEVEL
TRZN P1,NMPUPT## ;NAME SHOULD BE OUTPUT?
JUMPN P1,FOPFI4 ;NO, GET NEXT LEVEL IF NOT AT END
JUMPN P1,FOPFI3 ;YES, SAVE NAME AND GET NEXT LEVEL
FOPFI5: POP P,T1 ;GET AN SFD NAME
JUMPE T1,FOPFI6 ;END OF PATH--FINISH UP
PUSHJ P,FOPFIX ;STORE IN THE USER'S BLOCK
JRST FOPFI5 ;LOOP OVER WHOLE PATH
; TERMINATE THE LIST WITH A NULL WORD
FOPFI6: MOVEI T1,0 ;GET A ZERO
PUSHJ P,FOPFIX ;TERMINATE THE BLOCK
JRST CPOPJ1## ;AND RETURN
; STORE A WORD IN THE USER'S ARGUMENT BLOCK
FOPFIX: SOJL P2,FOPF66 ;ARGUMENT LIST TOO SHORT?
PUSHJ P,PUTWR1## ;STORE THE WORD
JRST FOPF64 ;ADDRESS CHECK STORING ARGUMENTS
POPJ P, ;RETURN
; ERROR RETURNS
FOPF63: MOVEI T1,ACRERR ;ADDRESS CHECK READING ARGUMENTS
POPJ P, ;RETURN
FOPF64: MOVEI T1,ACSERR ;ADDRESS CHECK STORING ANSWER
POP P,(P) ;PRUNE STACK
POPJ P, ;RETURN
FOPF65: MOVEI T1,NZAERR ;NEGATIVE OR ZERO ARGUMENT COUNT
POPJ P, ;RETURN
FOPF66: MOVEI T1,ATSERR ;ARGUMENT BLOCK TOO SHORT
POP P,(P) ;PRUNE STACK
POPJ P, ;RETURN
;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,.USCTA ;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,.USCTA ;NO
ADDI T1,-20(T2) ;ADDRESS OF EXTENDED CHANNEL
POPJ P, ;RETURN
;FILOP. EXIT ROUTINES
FOPFSP: HRRZ T1,FOPFLG ;GET ARG BLOCK LENGTH
CAIGE T1,11 ;INCLUDED A POINTER TO A FILESPEC BLOCK?
JRST FOPWIN ;NO--FINISH UP
PUSHJ P,GETTAC## ;LOAD T1 WITH USER'S AC
HRRI M,7(T1) ;POINT TO FILESPEC POINTER -1
PUSHJ P,FOPFI0 ;RETURN FILESPEC ASSOCIATED WITH THE CHANNEL
JFCL ;IGNORE THE FACT THAT THE BLOCK MIGHT BE TOO
; SHORT, BECAUSE WE CAN'T RETURN AN ERROR AT
; THIS POINT.
FOPWIN: MOVNI T1,1 ;INDICATE SUCCESS
JRST FOPXIT ;STANDARD EXIT
;ILLEGAL UUO
FOPILU: MOVEI T1,ILUERR ;ERROR CODE
JRST FOPXIT ;EXIT UUO
FOPE46: MOVEI T1,CNOERR ;CHANNEL-NOT-OPEN ERROR
JRST FOPXI1 ;ERROR RETURN TO USER
FOPE56: MOVEI T1,NPCERR ;NO-PER-PROCESS-SPACE ERROR
JRST FOPXI1 ;ERROR RETURN TO USER
FOPE57: MOVEI T1,NFCERR ;NO-FREE-CHANNEL ERROR
JRST FOPXI1 ;ERROR RETURN TO USER
FOPE60: MOVEI T1,UFFERR ;UNKNOWN-FILOP.-FUNCTION ERROR
JRST FOPXI1 ;ERROR RETURN TO USER
FOPE61: MOVEI T1,CTBERR ;CHANNEL-TOO-BIG ERROR
JRST FOPXI1 ;ERROR RETURN TO USER
FOPE62: MOVEI T1,CIFERR ;CHANNEL-ILLEGAL ERROR
JRST FOPXI1 ;ERROR RETURN TO USER
FOPE63: MOVEI T1,ACRERR ;ADDRESS CHECK READING ARGUMENTS
JRST FOPXIT ;ERROR RETURN TO USER
FOPE64: MOVEI T1,ACSERR ;ADDRESS CHECK STORING ANSWER
JRST FOPXIT ;ERROR RETURN TO USER
FOPE65: MOVEI T1,NZAERR ;NEGATIVE OR ZERO ARGUMENT COUNT
JRST FOPXIT ;ERROR RETURN TO USER
FOPE66: MOVEI T1,ATSERR ;ARGUMENT BLOCK TOO SHORT
JRST FOPXIT ;ERROR RETURN TO USER
;OPEN ERROR
FOPOER: HRRZ T1,T4 ;POSITION ERROR CODE FROM UOPEN
JRST FOPXI1 ;AND GIVE ERROR RETURN TO USER
;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: JUMPE F,FOPXI1
MOVSI T2,DEPFOP!DEPFFA!DEPALW ;MUST CLEAR THESE OR DDB
; CAUSE PROBLEMS ON NEXT UUO
ANDCAM T2,DEVJOB(F) ;ZAP!
MOVE T2,DEVMOD(F)
FOPXI1: SETZM .USFOP ;FILOP. IS DONE
MOVSI T2,(UP.IYB!UP.FIP) ;IN YOUR BEHALF
ANDCAM T2,.USBTS ;CLEAR THAT
REPEAT 0,< ;NOT A REAL GOOD IDEA RIGHT NOW
MOVE T2,FOPFLG ;GET FLAGS BACK
TLNE T2,FOP.OC ;DID WE USE AN OPEN CHANNEL?
JRST FOPXI2 ;YES, NOTHING ELSE TO DO
JUMPE F,FOPXI2 ;DITTO IF NO DDB
TLNN T2,FOP.RN!FOP.DL ;RENAME OR DELETE?
JUMPL T1,FOPXI2 ;NO, ONLY CLOSE (MAYBE) IF ERRORS
HRR M,FOPAP ;GET ADDRESS OF BLOCK
PUSH P,T1 ;SAVE RETURN STATUS
PUSHJ P,GTWST2## ;GET FIRST WORD
HRRZ T1,FOPTAB(T1) ;GET DISPATCH ADDRESS
TLNN T2,FOP.RN!FOP.DL ;RENAME OR DELETE?
CAIN T1,FOPEN ;NO, WAS THIS AN OPEN FUNCTION?
PUSHJ P,URELEA ;YES, RELEASE THE CHANNEL
POP P,T1 ;RESTORE RETURN STATUS
>; END REPEAT 0
FOPXI2: JUMPL T1,CPOPJ1## ;ALL DONE IF NO ERRORS
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,GETWRD## ;GET FIRST WORD OF BLOCK
POPJ P, ;ADDRESS CHECK
MOVEI T4,UUNPPN ;OFFSET TO PPN/PATH POINTER IN SHORT BLOCK
SKIPE T2,T1 ;COPY WORD COUNT WORD
TLNE T2,-1 ;EXTENDED UUO?
JRST FCLER1 ;ZERO WORD IS SHORT BLOCK
MOVEI T4,UUXPPN ;OFFSET TO PPN/PATH POINTER IN EXTENDED BLOCK
TRZA T2,RB.BIT ;CLEAR OLD STYLE BIT
FCLER1: MOVEI T2,3 ;4 WORDS
CAIL T2,(T4) ;ROOM ENOUGH FOR A PATH?
SKIPN T1 ;OR DOING A DELETE?
SETZ T4, ;NO OR YES, DON'T CHECK PATH BLOCK
AOS T2 ;LENGTH DIDN'T INCLUDE .RBCNT
HRRZ T1,M ;START ADDRESS
HRLI T1,(IFIW) ;MAKE SECTION RELATIVE
PUSHJ P,ARNGE## ;RANGE CHECK
POPJ P, ;ADDRESS CHECK
JFCL ;ADDRESS OK BUT ILLEGAL FOR I/O (IGNORED HERE)
JUMPE T4,CPOPJ1## ;ALL DONE IF NO PATH POINTER
PUSH P,M ;SAVE M
ADDI M,(T4) ;OFFSET TO PPN/PATH POINTER
PUSHJ P,GETWRD## ;GET IT
JRST MPOPJ## ;ADDRESS CHECK
JUMPE T1,MPOPJ1## ;RETURN IF NOT A PATH POINTER
TLNE T1,-1 ;DITTO
JRST MPOPJ1## ;ALL DONE
HRRI M,1(T1) ;POINT AT PPN WORD-1 IN PATH BLOCK
MOVE T2,SFDLVL## ;MAXIMUM SFD NESTING
FCLER2: PUSHJ P,GETWR1## ;GET NEXT WORD OF BLOCK
JRST MPOPJ## ;ADDRESS CHECK
JUMPE T1,MPOPJ1## ;DONE IF HIT A ZERO WORD
SOJGE T2,FCLER2 ;KEEP LOOKING FOR A ZERO WORD
JRST MPOPJ1## ;SFD LEVEL EXHAUSTED, RETURN
;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 FOPTS2 ;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
FOPTS2: TLNN T1,DVOUT ;IS IT OUTPUT?
JRST FOPTS1 ;NO, DON'T CHECK DEVSPL
SKIPGE DEVSPL(F) ;IF SPOOLED OUTPUT,
JRST CPOPJ1## ; THEN DO THE ENTER
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: TDNN T1,DEVJOB(F) ;IF NOT UPDATE RIB
JRST CLOSE1 ; CAN'T KEEP ENQ LOCKS
MOVEI T1,UP.MLB ;FOP.UR FUNCTION IN PROGRESS
ANDCAM T1,.USBTS ; SO ASSUME NO OUTPUT WILL BE REQUIRED.
JRST CLOSE2 ;CHECKPOINTING, ALLOWED TO KEEP ENQ LOCKS
CLOSE1::
PUSHJ P,ENQCLS## ;CHECK FOR LOCKS STILL OUT
SKIPA ;THERE WERE SOME
JRST CLOSE2 ;THERE WERE NO LOCKS
NQABRT: MOVEI T4,IOBKTL ;SET ERROR BIT...
IORM T4,DEVIOS(F) ;... IN DEVIOS
POPJ P, ;ABORT UUO
CLOSE2: LDB T4,PJCHN## ;GET JCH FOR THIS DDB
CAME T4,.CPJCH## ;SAME AS EXECUTING JOB?
POPJ P, ;DON'T TOUCH
IFN FTMP,<PUSHJ P,SETCPF##> ;GET JOB ON THE RIGHT CPU TO DO FILE OPERATION
SETZM .USFOP
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,[PUSHJ P,SSPCS## ;DCLI ROUTINE MAY CHANGE PCS
JRST 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,[PUSHJ P,SSPCS## ;SAVE PCS IN CASE ROUTINE CHANGES IT
JRST DCLI(T4)] ;AND CLOSE INPUT SIDE
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 UCLS8 ;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,[PUSHJ P,SSPCS## ;ROUTINE MAY CHANGE PCS
JRST DCL(T4)] ;SO SAVE FOR IT
JRST UCLS8
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
MOVE T4,DEVSER(F)
MOVEI T1,DEPAIO!DEPOND
PUSH P,DEVAIO(F) ;SAVE STATUS FOR LATER USE.
ANDCAM T1,DEVAIO(F) ;DON'T ALLOW NON-BLOCKING I/O DURING CLOSE
PUSHJ P,[PUSHJ P,SSPCS## ;ROUTINE MAY CHANGE PCS
JRST DCL(T4)] ;SO SAVE IT
POP P,T1 ;RETRIEVE OLD STATUS.
ANDI T1,DEPAIO ;SET NON BLOCKING BIT IN T1.
IORM T1,DEVAIO(F) ;RESET, IF IT WAS SET.
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
UCLS8: MOVSI T2,DVDSK ;GET DISK BIT
TDNE T2,DEVMOD(F) ;IS THIS A DISK?
SETZM DEVUPP##(F) ;CLEAR IN-YOUR-BEHALF PPN
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 UCLS8 ;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.
FINBF: MOVEI T3,BUFCLF ;SETUP RING FILOP STYLE
JRST UINBF1 ;JOIN COMMON CODE
UINBF:: MOVEI U,0 ;USE DEFAULT BUFFER SIZE
UINBS: PUSHJ P,BUFNZS ;CHECK FOR NON-ZERO SECTION, DON'T RETURN IF SO
MOVEI T3,BUFCLC ;SETUP BUFFER AT JOBFF
UINBF1: 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,(T3) ;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
FOUTBF: MOVEI T3,BUFCLF ;SETUP RING FILOP STYLE
JRST UOUTB1 ;JOIN COMMON CODE
UOUTBF::MOVEI U,0 ;USE DEFAULT BUFFER SIZE
UOUTBS: PUSHJ P,BUFNZS ;CHECK FOR NON-ZERO SECTION, DON'T RETURN IF SO
MOVEI T3,BUFCLC ;SETUP BUFFER AT JOBFF
UOUTB1: 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,(T3) ;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 FTMPXSER,<
LDB T1,PDVTYP## ;GET DEVICE TYPE BYTE
CAIN T1,.TYMPX ;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
;SUBROUTINE TO CHECK IF INBUF/OUTBUF WAS DONE IN A NON-ZERO SECTION. I.E.,
; JOBFF IS MEANINGLESS. DOESN'T RETURN IF SO. USES ONLY T3
BUFNZS: SE1ENT ;MUST BE IN SECTION 1
XSFM T3 ;GET FLAGS AND PCS
ANDI T3,MXSECN ;ISOLATE PCS
JUMPE T3,CPOPJ## ;OK IF SECTION ZERO
LSH T3,P2WLSH ;PAGE ZERO IN SECTION
MOVE T3,@[IW MS.MAP,UMAPS(T3)] ;GET POINTER FOR PAGE ZERO OF SECTION
CAME T3,@[IW MS.MAP,UMAPS] ;SAME AS PAGE 0 IN SECTION 0?
S0JRST ILLBUF## ;NO, ILLEGAL INBUF/OUTBUF
POPJ P, ;OK RETURN
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:
MOVE J,.CPJCH## ;GET CURRENT JOB'S JOB/CONTEXT HANDLE
PUSHJ P,ENQCLS## ;ANY LOCKS OUT?
JRST UOPE33 ;ERROR - ENQ LOCKS OUTSTANDING
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)
MOVE J,.CPJOB## ;GET ONLY JOB # NOW
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,URELEA ;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
MOVSI T2,(UP.FIP) ;FILOP. IN PROGRESS?
TLNN T1,-1 ;OR LH NON-ZERO?
TDNE T2,.USBTS ;...
JRST UINIA1 ;YES
CAIGE T1,1000 ;LEGAL UDX FOR AN OPEN UUO?
JRST UOPE12 ;NO, RETURN 'NO SUCH DEVICE' ERROR
UINIA1: 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 FTNET,<
PUSHJ P,DEVSRC ;SEARCH FOR DEVICE
>
PUSHJ P,DVSRSP ;DOES ANY DEV OF THIS TYPE EXIST?
CAIA ;ERROR
JRST UINIT7 ;FOUND IT, PLUNGE AHEAD
PUSHJ P,UDXDDB ;SEE IF A UDX WAS SUPPLIED
JRST UOPE12 ;ERROR - NO SUCH DEVICE
JRST UINIT2 ;FOUND UDX-CHARGE AHEAD
UINIT7:
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
MOVEI T3,ASSPRG ;FLAG THAT INIT'ED DEV UNACCEPTABLE
PUSH P,F ;SAVE DDB LOC
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 UOPE1D ;NO - LOSE
UINIT1: POP P,(P) ;YES - WIN
UINIT2: MOVE T2,JBTSTS##(J) ;IS THIS JOB
TLNE T2,JLOG ; LOGGED IN?
JRST UINI2A ;YES, CONTINUE
LDB T2,PDVTYP## ;GET DEVICE TYPE
CAIE T2,.TYDSK ;IS IT A DISK?
CAIN T2,.TYTTY ;OR A TERMINAL
JRST UINI2A ;YES, ALWAYS ALLOWED
CAIN T2,.TYTSK ;IS IT A TASK?
JRST UINI2A ;YES, ALWAYS ALLOWED
JRST UOPE32 ;ERROR - ILLEGAL IF NOT LOGGED IN
UINI2A: MOVE M,(P) ;RESTORE USER'S MODE SETTING
TLNE M,^-.OPALL&777770 ;ANY UNDEFINED OPEN BITS SET?
JRST UOPE54 ;ERROR - UNKNOWN OPEN BITS
PUSH P,T1 ;SAVE NAME USER SUPPLIED
CAMN T1,[SIXBIT /NUL/] ;ALL MODES ARE LEGAL FOR NUL:
JRST UINI2C ;SO DON'T EVEN BOTHER CHECKING
PUSHJ P,CHKMOD ;CHECK FOR LEGAL MODE
JRST UOPE53 ;ERROR - ILLEGAL DATA MODE
UINI2C:
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, GET NO OF USER CHANS DEV INITED ON
HRR T3,T2 ;SAVE OLD NUMBER
AOS T2 ;INCREASE CHANNEL COUNT
CAILE T2,1 ;MORE THAN ONE CHANNEL OPEN ON THIS DEVICE?
JRST [MOVEI T4,DNAERR ;YES, GET AN ERROR CODE
JRST UINIT6] ;DON'T ALLOW THIS
DPB T2,IADPTR## ;STORE UPDATED CHANNEL COUNT FOR THIS DEV(DTA)
UINITB: MOVEI T2,ASSPRG ;TRY TO ASSIGN IT BY PROGRAM
SETZM M
MOVE J,.CPJCH## ;ASSIGN BY JOB/CONTEXT HANDLE
PUSHJ P,ASSASD ;TRY TO GET THE DEVICE FOR I/O
JRST UINIT6 ;NOT AVAILABLE, GIVE ERROR RETURN (POP T1)
ANDI J,JOBMSK## ;REDUCE TO JCH TO A JOB NUMBER
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
JRST UINITX
MOVE T2,JBTPPN##(J) ;PROJ PROG NUMBER FOR CURRENT JOB
CAME T2,FFAPPN## ;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 ;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 ;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
JRST UINIB3
MOVE T2,DEVRRC##(F)
TLZ T2,DEPRRC##!DEPRHC##!DEPPHO##!DEPLBF##
TLNE M,.OPRRC ;REWRITE RIB ON CHANGE?
TLO T2,DEPRRC## ;YES
SKIPGE P1 ;PHYSICAL ONLY?
TLO T2,DEPPHO## ;YES, REMEMBER THAT.
TLNE M,.OPLBF ;USE LARGE BUFFERS?
TLO T2,DEPLBF## ;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,.USCTA
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: TLZ F,^-SYSDEV ;CLEAR LEFTOVER BITS FROM PREVIOUS CHANNEL
SETZ T1, ;CLEAR THE EXTENDED ERROR STATUS
DPB T1,PDVESE## ;
IFN FTXMON,<
LDB T1,[POINT 5,.USUPF,17] ;GET PCS
MOVEM T1,DEVISN(F) ;SAVE IT FOR SECTION RELATIVE I/O
>
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
UOPE1D: POP P,(P) ;ADJUST STACK
UOPE12: MOVEI T4,NSDERR ;NO-SUCH-DEVICE ERROR
JRST UINITE ;ERROR RETURN
UOPE33: PUSHJ P,NQABRT ;SET I/O ERROR
MOVEI T4,ENQERR ;ENQ-LOCKS-OUTSTANDING ERROR
POPJ P, ;ERROR RETURN
UOPE32: MOVEI T4,NLIERR ;NOT-LOGGED-IN ERROR
JRST UINITE ;ERROR RETURN
UOPE53: MOVSI T4,(UP.FIP) ;CALLED FROM
TDNN T4,.USBTS ; A FILOP.?
JRST ILLMOD## ;NO, STOMP ON USER JOB
PUSHJ P,TTYKLQ## ;KILL OFF TTY DDB IF NECESSARY
MOVEI T4,IDMERR ;ILLEGAL-DATA-MODE ERROR
JRST UINITD ;ERROR RETURN
UOPE54: MOVEI T4,UOBERR ;UNKNOWN-OPEN-BITS ERROR
JRST UINITE ;ERROR RETURN
UINIT6: PUSH P,T4 ;PRESERVE ERROR CODE FROM ASSASD
PUSHJ P,TTYKLQ## ;IF IT WAS A FREE TTY, DISCARD DDB
POP P,T4 ;RESTORE ERROR CODE
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
MOVSI T3,(UP.FIP) ;GET FILOP BIT
TDNN T3,.USBTS ;CALLED 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
;DISPATCH TABLE
;DISPATCH TO DEVICE DEPENDENT SERVICE ROUTINE
;ENTER UUO - ENTER FILE NAME IN DIRECTORY
UDEN: PUSHJ P,SAVE4##
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.
MOVE T4,DEVSER(F) ;RESTORE DISPATCH ADDRESS
PUSHJ P,DEN(T4) ;ATTEMPT AN ENTER
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##
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
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)
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: PUSH P,M ;PRESERVE M FROM CORRUPTION
PUSHJ P,FCLERB ;CHECK LOOKUP/ENTER/RENAME BLOCK
JRST ADRERR## ;ADDRESS CHECK
JRST MPOPJ## ;RESTORE M AND RETURN
;ROUTINE TO PRINT WATCH-FILE DATA
;CALL: HRR M,UVA OF ERROR CODE (HRRI M,0 IF SUCCESS)
; PUSHJ P,WCHFIL
; CAI 'X'
WCHFIL::MOVEI T1,UP.SWF ;ALREADY TYPED IT?
TDNE T1,.USBTS
JRST [ANDCAM T1,.USBTS ;YES, CLEAR THE FLAG
POPJ P,]
MOVE J,.CPJOB## ;GET J SET UP CORRECTLY
MOVE T1,JBTWCH##(J) ;GET WATCH BITS
HRR T1,JBTSTS##(J) ;AND SHADOW ACS AND OTHER FLAGS
HRRZ T2,.USMUO ;GET MUUO OPCODE
TRNE T1,JS.ASA ;REFERENCE TO SHADOW ACS?
CAIN T2,(ENTER) ;AND NOT ENTER (IMPLYING SAVE)?
CAIA ;SAVE - WATCH IT
POPJ P, ;RUN/GET - DON'T WATCH
TRNN T1,JS.XO ;EXECUTE ONLY?
TLNN T1,JW.WFL ;NO, WANT TO SEE THIS?
POPJ P, ;NO, RETURN
PUSH P,U ;SAVE A BUNCH OF ACS
PUSH P,S
PUSH P,F
PUSHJ P,TTYFND## ;SET U TO LDB OF CONTROLLING TERMINAL
POP P,F
JUMPE U,WCHFI4 ;SKIP OUTPUT IF DETACHED
PUSHJ P,PRLBK## ;PRINT LEFT BRACKET
MOVE T1,DEVJOB(F) ;CHECK IF FILOP. IN PROGRESS
TLNN T1,DEPFOP
JRST WCHFI1 ;NOT FILOP., SKIP THE "F"
PUSHJ P,INLMES##
ASCIZ /F/
WCHFI1: HRRZ T3,@-2(P) ;GET CODE SUPPLIED BY CALLER
PUSHJ P,COMTYO## ;TYPE IT
HLRZ T1,.USCTA ;GET CURRENT CHANNEL
PUSHJ P,PRTDI8## ;TYPE IT
PUSHJ P,INLMES## ;SEPARATE
ASCIZ /: /
PUSHJ P,PRTDDB## ;PRINT DDB INFO
WCHPCP: MOVEI T1,[ASCIZ / exec/] ;GET BLURB
MOVSI T2,(XC.USR) ;SEE IF EXEC MODE UUO
TDNN T2,JOBPDO ;IDENTIFY EXEC MODE
PUSHJ P,CONMES##
MOVE T2,JOBPDO+1 ;FETCH PC FROM JOBPDO
SUBI T2,1 ;BACK OFF TO ACTUAL PC OF UUO
PUSHJ P,INLMES## ;MORE NOISE
ASCIZ / PC:/
PUSHJ P,UDPCP## ;PRINT (ALLOWING SECTION NUMBER)
WCHFI2: TRNN M,-1 ;ANY ERROR SET?
JRST WCHFI3 ;NO, QUIT NOW
PUSHJ P,INLMES## ;APPEND SOME ERROR TEXT
ASCIZ /, error /
PUSHJ P,GETWDU##
HRRZS T1
PUSHJ P,PRTDI8##
WCHFI3: PUSHJ P,PRRBK##
PUSHJ P,PCRLF##
WCHFI4: POP P,S
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
MOVE T4,DEVSER(F) ;RESTORE DISPATCH ADDRESS
IFN FTMP,<
PUSHJ P,SETCPF## ;SET CPU FOR FILE OPERATION
>
JRST RNMSEG## ;OLD FILE IS .SHR AND RENAME SUCCESSFUL.
;HERE FROM SEGCON
UDREN::
PUSHJ P,DRN(T4) ;DO THE RENAME
SOSA (P) ;FAILURE
TRZ M,-1 ;SUCCESS
PUSHJ P,WCHFIL ;TELL THE WATCHER
CAI "R"
PJRST CPOPJ1##
;USETO UUO - SET NEXT OUTPUT BLOCK NUMBER(DECTAPE)
UDSO:
HRRE W,M ;BLOCK NUMBER
CAME W,[-1] ;IF NOT USETO TO BLOCK OF FILE
TLZ W,-1 ;CLEAR HIGH ORDER BITS
IFN FTMP,<
PUSHJ P,SETCPF## ;SET CPU FOR FILE OPERATION
>
PUSHJ P,WAIT2 ;WAIT FOR IO, FIX OUTPUT BUFFERS
JRST DSO(T4)
;USETI UUO - SET NEXT INPUT BLOCK NUMBER
UDSI:
HRRE W,M ;BLOCK NUMBER
CAME W,[-1] ;BLOCK-1 MEANS END OF FILE,IS IT?
CAML W,MUSTMX## ;TRYING TO READ EXTENDED RIB?
CAIA ;YES
TLZ W,-1 ;NO,CLEAR HIGH BITS FOR COMPATIBILITY
IFN FTMP,<
PUSHJ P,SETCPF## ;SET CPU FOR FILE OPERATION
>
PUSHJ P,WAIT2 ;WAIT FOR IO, FIX OUTPUT BUFFERS
JRST DSI(T4)
;ENTER HERE FROM FILOP.
FOPGTF: PUSHJ P,FOPLP ;MUST HAVE LONG DISPATCH TABLE
LDB T1,PUUOAC## ;GET AC NUMBER
HRR M,T1 ;WHERE TO STORE BLOCK NUMBER
;UGETF UUO - GET NEXT FREE BLOCK
UDGF:
IFN FTMP,<
PUSHJ P,SETCPF## ;SET CPU FOR FILE OPERATION
>
JRST DGF(T4)
;HERE FROM FILOP.
FOPMTP: HRRZ T1,FOPFLG ;MUST HAVE AT LEAST TWO ARGS
CAIGE T1,2
JRST FOPILU
PUSHJ P,GETWD1## ;GET NEXT ARG
HRR M,T1 ;STORE AS THE MTAPE BITS
PUSHJ P,FOPLP ;MUST HAVE LONG DISPATCH TABLE
;MTAPE UUO - MAGTAPE OPERATIONS
UMTAPE:
IFN FTMP,<
PUSHJ P,SETCPF## ;SET CPU FOR FILE OPERATION
>
JRST DMT(T4)
;HERE FROM FILOP.
FOPUTP: PUSHJ P,FOPLP ;DO SPECIAL STUFF FOR FILOP.
;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: 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
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
>
TLZ S,IO ;INDICATE READING AGAIN
MOVEM S,DEVIOS(F)
UIN01: TLO F,INPB ;FOR THIS DEVICE.
TLZ F,ICLOSB
PUSHJ P,JDAADR ;IN LH OF CURRENT JOB DEVICE CHANNEL
HLLM F,(T1)
IFN FTMP,<
PUSHJ P,SETCPF## ;GET JOB ON RIGHT CPU TO DO IO
; IF NON-QUEUED PROTOCOL
>
LDB T1,PIOMOD## ;IO MODE
CAIL T1,SD ;IS THE IO MODE DUMP(SD,D,DR)?
JRST INDMP ;YES
IN1:
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
IFN FTMP&FTKL10,<
SUBI T1,1 ;POINT AT S-WORD (SWEEP NUMBER)
PUSHJ P,UADRCK ;MAKE SURE IT IS IN
>
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 INPT1A
IN1A: 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 FTMPXSER,<
LDB T1,PDVTYP## ;GET DEVICE TYPE
CAIE T1,.TYMPX
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 FTMPXSER
EXCTUX <HRRZ T2,@U> ;RESTORE T2
IFN FTMP&FTKL10,<
MOVE T4,.CPCSN## ;GET CACH-SWEEP NUMBER
HRL T4,.CPCPN## ;SAVE CPU NUMBER
TLO T4,IO ;INSURE IO IS ON
MOVEI T1,-1(T2) ;SAVE IN BUFFER HEADER FOR FILLER
EXCTXU <MOVEM T4,@T1>
PUSHJ P,OUCHE## ;GET IT BACK TO MEMORY
>
MOVSI T3,IOUSE
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 ;GET IT OUT OF CACHE
PUSHJ P,OUCHE##
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 .USREL
SKIPE .USVRT ;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 FTMPXSER,<
PUSHJ P,CHKMPX## ;AN MPX DDB OR A DDB CONNECTED TO AN MPX?
JRST INPT3A ;YES, LET MPXSER 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 FTMPXSER,<
LDB J,PDVTYP## ;GET THE DEVICE TYPE
CAIE J,.TYMPX ;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
INPT1A:
IFN FTMP&FTKL10,<
HRRZ T1,T2 ;GET USE BIT OUT OF CACHE
PUSHJ P,OUCHE## ;CACHE MIGHT BE WRONG IF
MOVSI T1,IOUSE ;NON-BLOCKING I/O
EXCTUX <TDNE T1,@T2> ;TRY AGAIN
JRST IN1A ;CAHE WAS WRONG (RARE)
>
INPT1: TRNN S,IOACT ;IF DEVICE ISNT ALREADY GOING
PUSHJ P,CALIN ; START IT NOW
JRST INPT2 ;BLOCK UNTIL BUFFER FILLED
INEOF: MOVSI T1,DEPSIE
TDNE T1,DEVJOB(F) ;SYNCH ON ERROR?
TRNN S,IODEND ;YES, AVOID KAF IF TAPE
TDNE S,[XWD IOEND,IODERR+IOBKTL+IODTER+IOIMPM]
CAIA ; EOF OR ERROR BIT SET BY SERVICE ROUTINE
; 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
IFN FTMP,<
HRRZ T1,DEVIAD(F)
HRRZ T2,DEVEVM(F) ;GET EVM ADDRESS IF ANY
SKIPE T2 ;STILL HAVE EVM?
MOVEM S,-1(T1) ;YES, PUT S-WORD BACK (BUFFER IN EVM)
SKIPN T2 ;STILL HAVE EVM?
EXCTXU <MOVEM S,-1(T1)> ;NO, PUT S-WORD BACK
>
POPJ P, ;RETURN TO USER'S PROGRAM
INEOF1: MOVE T1,DEVAIO(F) ;ASYNC?
TRNN T1,DEPAIO
IFE FTMP,<
JRST UUOER1## ;MONITOR ERROR
>
IFN FTMP,<
JRST INPT1 ;START OVER
>
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 & INBUF
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,CPFBOO## ;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 PROTOCOL?
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 FTMPXSER,<
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
MOVSI T1,DEPSIE
TDNE T1,DEVJOB(F)
TRNN S,IOBKTL+IODTER+IODERR+IOIMPM+IODEND
SKIPA ;NO ERRORS OR DOESN'T CARE
POPJ P, ;WAIT FOR ERRORS TO CLEAR
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:
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 FTMPXSER,<
LDB T1,PDVTYP## ;GET THE DEVICE TYPE
CAIN T1,.TYMPX ;IS THIS MPX?
PJRST MSGOUT## ;YES--CALL MPXSER
> ;END FTMPXSER
;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:
IFN FTMP,<
PUSHJ P,SETCPF## ;SET JOB ON CPU OWNING DEVICE
; IF NON-QUEUED PROTOCOL
>
LDB T1,PIOMOD## ;GET DATA MODE SET BY INIT OR SETSTS.
CAIL T1,SD ;IS IT DUMP MODE(SD,DR,D)?
JRST OUTDMP ;YES.
PUSHJ P,OUTA ;NO, CHECK FOR NON-ZERO ADDRESS(USER
; CHANGING RING)
TLO S,IO ;INDICATE WRITING AGAIN
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 OUT3A ;THEN JUST START THE DEVICE
MOVE T4,DEVMOD(F) ;GET CHARACTERISTICS
EXCTUX <HRRZ T1,@U> ;GET RH OF BYTE POINTER.
EXCTUX <HLR T4,(T2)> ;GET FULL SIZE OF BUFFER
TRNN T4,-1 ;VIRGIN RING?
HRRI T4,200 ;YES, ASSUME 200 WORDS IN BUFFER
TRZ T4,400000 ; FOR CHECK IF DTA OR DSK
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.
TRNN S,IOWC ;WANT USER WORD COUNT
JRST OUT2B1 ;NO
OUT2: EXCTUX <HRRZ T1,@T2> ;YES
LDB T3,PIOMOD## ;I/O MODE
CAIE T3,BYTMOD ;BYTE MODE?
JRST OUT2B1 ;NO, DON'T NEED TO CONVERT
PUSH P,T2 ;SAVE L(WRDCNT WORD)
EXCTUX <LDB T3,[POINT 6,@U,11]> ;GET BYTE SIZE
MOVEI T2,^D36 ;# BITS IN WORD
IDIVI T2,(T3) ;BYTES PER WORD
IDIVI T1,(T2) ;BYTE COUNT BECOMES WORD COUNT
SKIPE T2 ;ROUND UP FOR PARTIAL WORDS
ADDI T1,1 ;T1 HAS WORD COUNT
POP P,T2
OUT2B1: SKIPGE T3,T1 ;PRESERVE USER'S WORDCOUNT
PJRST ADRERR## ;NEGATIVE WORDCOUNTS ARE ILLEGAL
TLNE T4,DVDSK!DVDTA ;IF DISK OR DTA,
MOVEI T1,-1(T4) ; MAKE SURE WHOLE BUFFER IS THERE
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?
CAIN T1,PIMMOD ;OR PACKED IMAGE MODE?
JRST OUT2B2 ;YES, COMPUTE EXACT NUMBER OF BYTES
CAIE T1,A8 ;ALSO EXACT IF 8-BIT ASCII
JRST OUT2A ;NO
OUT2B2: JUMPE T3,OUT2A ;DON'T COMPUTE IF = 0
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
JUMPGE T2,OUT2A ;POSITIVE NUMBER OF WORDS
TRNE T3,-1 ;NEGATIVE WORDS LEGAL ONLY IF RESOLVES TO 0 BYTES
PJRST ADRERR ;NEGATIVE NUMBER OF BYTES LOSE
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,UPDNBF ;UPDATE DEVNBF IF QUEUED PROTOCOL
>
OUT3: MOVSI T1,DEPADV ;DON'T DEADVANCE BUFFERS BIT
ANDCAM T1,DEVADV(F) ;CLEAR BEFORE RETRY. REPEAT OF ERRORS
; WILL SET IT AGAIN.
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
TLZE S,IOSTBL ;ERROR OCCURED?
JRST OUT3A ;YES
IFN FTMP,<
IFN FTKL10,<
MOVE T1,T2 ;GET OLD USE BIT OUT OF CACHE
PUSHJ P,OUCHE##
>
TRNN S,IOBKTL+IODTER+IODERR+IOIMPM+IOTEND
EXCTUX <SKIPL @T2> ;BUFFER REALLY EMPTY?
>
JRST OUTS ;YES, RETURN TO USER
OUT3A: HRL W,S ;COPY IOACT TO W
IFN FTKL10&FTMP,<
PUSHJ P,ISITQ ;QUEUED PROTOCOL?
JRST OUT3 ;NO
PUSHJ P,CKNBF## ;YES UPDATE DEVNBF
>
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
IFN FTKL10&FTMP,<
;ROUTINE TO UPDATE DEVNBF FOR OUTPUT
UPDNBF: PUSHJ P,ISITQ ;NON-TTY, QUEUED PROTOCOL
POPJ P, ;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)
PJRST CKNBF## ;ADD IT TO LH IF ON RIGHT CPU
>
OUTF: TLO S,IO ;INDICATE OUTPUT FOR IOSETC
IFN FTKL10&FTMP,<
PUSHJ P,ISITQ ;QUEUED PROTOCOL
JRST .+3 ;NO, PRESS ON
SETZM DEVNBF(F) ;NO BUFFERS LEFT AROUND IF VIRGIN RING
SETZM DEVSBF(F) ;...
>
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: PUSHJ P,OUTFCL ; TO ENSURE THAT A FAULT WONT HAPPEN
JRST ADRERR## ; AFTER THE VIRGIN-RING BIT IS CLEARED
HRLZI T1,IOUSE
EXCTUU <ANDCAB T1,@U> ;VIRGIN RING BIT:=0
HRRM T1,DEVOAD(F)
OUTS: PUSHJ P,OUTFCL ;MAYBE CLEAR THE BUFFER
JRST ADRERR## ;ADDRESS CHECK
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
;HERE TO CLEAR THE BUFFER POINTED TO BY THE RING HEADER (MAYBE)
OUTFCL: 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
PJRST BUFCLR ;NO, CLEAR BUFFER AND RETURN
PUSHJ P,UADRCK ;MAKE SURE FIRST WORD IS IN CORE
PUSHJ P,BRNGE## ;MAKE SURE BUFFER IS ALL IN CORE
JRST CPOPJ1## ;YES, SKIP CLEARING THE NEXT BUFFER
CALOUI: TLNE W,IOACT
POPJ P,
MOVSI S,IOSTBL ;CLEAR TROUBLE FLAG
ANDCAB S,DEVIOS(F)
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
LDB T2,PDVTYP## ;GET DEVICE TYPE
CAIE T2,.TYMTA
TRZ T1,IOTEND ;NO, EOT IS NO GOOD HERE!
TRNE T1,IOBKTL+IODTER+IODERR+IOIMPM+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
TLO S,IO ;INDICATE OUTPUT
;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
SKIPGE DEVISN(F) ;DOING MULTI-SECTION I/O?
JRST PFHMSI## ;YES, LET PFH HANDLE DIFFERENT IOWD FORMAT
JRST PFHDMP## ;LET PFH HANDLE WHAT DMPEV USED TO DO
REPEAT 0,<
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,.USCTA ;PUT CHANNEL #
; (IN CASE OF TROUBLE AND CALL HNGSTP)
PUSHJ P,RELEA1 ;RESET IT
JRST CPOPJ1## ;SKIP RETURN
SUBTTL RELEASE UUO
;HERE FROM FILOP.
FOPREL: AOS (P) ;GOOD RETURN
;RELEASE A DEVICE
URELEA::TRZ M,-1 ;CLOSE BOTH INPUT AND OUTPUT
PUSHJ P,CLOSE1
PUSHJ P,WAIT1## ;WAIT FOR DEVICE TO BECOME INACTIVE
;HERE TO RELEASE WITHOUT CLOSING DEVICE
RELEA1::LDB T2,PJCHN## ;GET OWNING JOB/CONTEXT HANDLE
CAME T2,.CPJCH## ;SAME AS CURRENT JCH?
POPJ P, ;NO--DON'T LET GO
HRRZ T4,DEVSER(F) ;RESTORE T4
IFN FTMP,<
PUSHJ P,SETCPP## ;SKIP IF CPU IS ALIVE
SKIPA ;DETACHED
> ;END IFN FTMP
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
RELEA2: PUSHJ P,NXTCH ;GET NEXT CHANNEL
JRST RELEA3 ;FINISHED
CAIN T1,(F) ;SAME DEVICE ON ANOTHER CHANNEL?
JRST P1POPJ## ;YES, EXIT
JRST RELEA2 ;LOOP FOR THE NEXT OPEN CHANNEL
RELEA3: POP P,P1 ;RESTORE P1
;HERE FROM ERROR STOP ROUTINES (SWAP READ ERROR, PARITY ERROR, ETC.)
RELEA4::LDB T2,PJCHN## ;GET JOB/CONTEXT HANDLE
TRZ T2,CTXMSK## ;CLEAR OUT CONTEXT NUMBER
DPB T2,PJCHN## ;UPDATE
IFN FTXMON,<SETZM DEVISN(F)> ;CLEAR I/O SECTION NUMBER
MOVEI T3,0 ;CLEAR USER ADDRESS
PUSHJ P,RTIEVM ;RETURN EVM FOR INPUT
MOVEI T3,0 ;CLEAR USER ADDRESS
PUSHJ P,RTOEVM ;RETURN EVM FOR OUTPUT
MOVEI T1,DEPAIO ;ASYNCH BIT
ANDCAM T1,DEVAIO(F) ;CLEAR NON-BLOCKING I/O FLAG
MOVEI T2,ASSPRG ;CLEAR ASSIGNED BY PROGRAM BIT
RELEA6::MOVE T1,DEVMOD(F) ;SAVE OLD DEVMOD
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
ANDI T1,ASSCON ;KEEP JUST THE "ASSIGNED BY COMMAND" BIT
PUSH P,T1 ;AND SAVE IT FOR LATER
SETZM DEVBUF(F) ;NO BUFFER HEADERS
SKIPE DEVPSI(F) ;SOMEONE PSI'ING ON THIS DEVICE
PUSHJ P,PSIRMV## ;YES, REMOVE FROM PSI CHAIN
IFN FTMDA,<
PUSH P,W ;SAVE FROM IPCSER
MOVSI T1,DVCMDA ;SEE IF MDA CONTROLS THIS DEVICE
TDNE T1,DEVCHR(F) ;DOES IT?
PUSHJ P,SNDFIN## ;TELL MDA
JFCL ;IGNORE ERROR
POP P,W ;RESTORE W
>;END FTMDA
PUSHJ P,TPMRES## ;RESET MAGTAPE DDB PARAMETERS
MOVE T2,DEVMOD(F) ;PUT DEVMOD IN T2
TLNN T2,DVTTY ;DON'T BE FOOLED BY NULL
TLNN T2,DVMTA ;A MAGTAPE?
JRST RELE6A ;NO
SKIPE (P) ;ASSIGNED BY COMMAND BEFORE?
PUSHJ P,TPSTAT## ;YES--REPORT TAPE STATS, CLEAR TUB COUNTERS
RELE6A: POP P,(P) ;TRIM STACK
PUSHJ P,CLRDVL ;DISCONNECT JOB FROM DDB
IFN FTNET,<
MOVSI T1,DVCNET ;CHECK FOR A NETWORK DEVICE
TDNE T1,DEVCHR(F) ;IS IT
PJRST ZAPNET## ;YES, DISCONNECT DEVICE IF NO LONGER NEEDED
> ;END IFN FTNET
MOVE T2,DEVMOD(F) ;GET DEVMOD
SKIPL DEVSPL(F) ;IS DEVICE A SPOOLED DISK
TLNE T2,DVDSK ;IS DEVICE A DSK
PJRST CLRDDB## ;YES-RETURN DDB TO STORAGE
LDB T2,PDVTYP## ;GET THE DEVICE TYPE
IFN FTMPXSER,<
CAIN T2,.TYMPX ;IS THIS AN MPX DDB?
PJRST ZAPMPX## ;YES--KILL IT OFF
> ;END FTMPXSER
IFN FTKS10,<
CAIN T2,.TYKDP ;IS THIS A KDP DDB?
PJRST ZAPKDP## ; IF SO, DELETE IT
CAIN T2,.TYDMR ;IS THIS A DMR DDB?
PJRST ZAPDMR## ;YES, DELETE IT
>
IFN FTKL10,<
CAIN T2,.TYDTE
PJRST ZAPDTE##
>
PJRST XTKLDB## ;GO KILL XTC DDB IF NECESSARY
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::
PUSHJ P,XTCIOS## ;GET S
TRNE S,(M) ;SKIP IF ANY INDICATED BITS ARE ONE
AOS (P)
POPJ P, ;RETURN TO USER
;HERE FROM FILOP.
FOPGST: AOS (P) ;GOOD RETURN
LDB T1,PUUOAC##
HRR M,T1
;CALLING SEQUENCE
; STATUS D,ADR
; EXIT ALWAYS RETURNS HERE
;STORES I/O STATUS WORD OF DEVICE ON CHANNEL D IN LOCATION ADR.
USTATS::
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::
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
LDB T1,PDVTYP## ;GET THE DEVICE TYPE
CAIE T1,.TYMTA
TRZ S,IOTEND ;EOT IS ONLY GOOD ON MAGTAPE
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,
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
;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::PUSHJ P,SVEUF## ;PUSH THE USER BASE REGISTER AND SETUP UBR
; SO THAT CURRENT USER IS ADDRESSABLE
PUSHJ P,SPCS## ;SETUP PCS
PUSHJ P,ADVBFO ;ADVANCE OUTPUT BUFFER
POPJ P, ;STOP
PJRST ADVSWP ;GO, UNLESS SWAPPER SAYS NO
ADVBFO::HRRZ 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
IFN FTMPXSER,<
MOVEI T2,DEPMSG ;IS THIS DEVICE CONTROLLED BY
TDNE T2,DEVMSG(F) ; BY MPXSER
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)
JFCL ;PAGE NOT IN CORE
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
>
HRRZS 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)
JFCL ;PAGE NOT IN CORE (UPDATE DEVOAD BUT STOP I/O)
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::PUSHJ P,SVEUF## ;PUSH THE USER BASE REGISTER AND SETUP UBR
; SO THAT CURRENT USER IS ADDRESSABLE
PUSHJ P,SPCS## ;SETUP PCS
PUSHJ P,ADVBFI ;ADVANCE INPUT BUFFER
POPJ P, ;STOP
PJRST ADVSWP ;GO, UNLESS SWAPPER SAYS NO
ADVBFI::HRRZ 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
PUSH P,T3 ;ITS POSSIBLE THAT SOME DEVICE ROUTINES
; DEPEND ON T3 BEING INTACT UPON RETURN
IFN FTMPXSER,<
MOVEI T2,DEPMSG ;IF THIS DEVICE IS CONTROLLED
TDNE T2,DEVMSG(F) ; VIA MPXSER. 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)
JFCL ;PAGE NOT IN CORE
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
>
HRRZS T1,T3 ;ADDRESS OF START OF BUFFER
PUSHJ P,IADCKL ;MAKE SURE ITS LEGAL (MIGHT BE PAGED OUT)
JRST ADVBU3 ;ILLEGAL ADDRESS (ADR CHECK)
JFCL ;PAGE NOT IN CORE (UPDATE DEVIAD BUT STOP IO)
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 LET I/O CONTINUE
ADVBU1::AOS -1(P) ;SET SKIP (CONTINUE I/O) RETURN
JRST ADVBU3
;HERE TO STOP EVM DEVICE
ADVBU2: PUSH P,T3 ;SAVE ADDR OF BUFFER
PUSHJ P,RTNEVM ;SHUTTING DOWN I/O, GIVE BACK ANY EVM
POP P,T3
;HERE TO STOP NON-EVM DEVICE
ADVBU3:
IFN FTMP&FTKL10,<
HRRZ T1,T3
PUSHJ P,OUCHE## ;REMOVE LINE FROM CACHE
>
JRST T3POPJ## ;RESTORE T3
;HERE TO SEE IF I/O SHOULD BE STOPPED SO JOB CAN BE SHUFFLED,
; SWAPPED, LOCKED, OR THE USER HAS TYPED CONTROL C
;RETURNS CPOPJ IF WE SHOULD STOP I/O, CPOPJ1 TO CONTINUE I/O
;PRESERVES T3
ADVSWP::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 ADVSW2 ; GIVE STOP I/O RETURN
SKIPGE T2,JBTSTS##(T2) ;IS THE JOB RUNNABLE?
TLNE T2,SHF!CMWB!CNTRLC
JRST ADVSW2 ;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 ADVSW2 ;YES, SHUT DOWN THE I/O
JRST CPOPJ1 ;OK TO CONTINUE I/O
;HERE TO STOP DEVICE BECAUSE SWAPPER WANTS TO SWAP THE JOB
ADVSW2: PUSH P,T3 ;SAVE T3
PUSHJ P,RTNEVM ;GIVE BACK ANY EVM
JRST T3POPJ## ;NOSKIP
;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, ;ILLEGAL
POPJ P, ;NOT IN CORE
EXCTUX <HLRZ T2,(T1)> ;SIZE
ANDI T2,IOSIZ
JUMPE T2,CPOPJ
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 SAME 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::PUSHJ P,IADRCK ;ADDRESS IN CORE AND LEGAL?
JRST ADRERR## ;ILLEGAL, IN HI SEG, SPY PAGE, OR PROTECTED JOBDAT
JRST UUOFLT## ;LEGAL, BUT PAGED OUT, ACCESS ALLOWED OFF, OR ABZ
POPJ P, ;IN CORE AND LEGAL
;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,.USHSS ;IS ADDRESS IN USER HIGH SEGMENT?
CAMLE T1,.USHSE ; . . .
AOS (P) ;LOW SEG ADDRESS, SUCCESSFUL RETURN
POPJ P, ;RETURN
> ;END REPEAT 0
;ROUTINE TO CHECK AN ADDRESS TO SEE IF ITS LEGAL AND IN CORE
;CALLING SEQUENCE:
; MOVEI T1,ADDRESS TO BE CHECKED
; PUSHJ P,IADRCK OR IADCKL
; ... RETURN HERE IF ILLEGAL ADDRESS
; ... RETURN HERE IF PAGE ADDRESS IS IN A PAGE PAGED OUT, ACCESS ALLOWED OFF, OR ABZ
; ... RETURN HERE IF ADDRESS IS IN CORE AND LEGAL
IADCKL::
IADRCK::TLNE T1,-1-MXSECN ;DON'T ALLOW CRUFT IN THE LEFT HALF
POPJ P, ;ILLEGAL ADDRESS
SE1ENT ;MUST BE IN SECTION 1
PUSH P,T1 ;SAVE WORKING ACS
PUSH P,T2
XSFM T2 ;GET FLAGS AND PCS
HLRZS T1 ;POSSIBLE SECTION NUMBER
ADD T2,T1 ;ADD AS OFFSET PROM PCS SECTION
ANDI T2,MXSECN ;ISOLATE PCS
CAIG T2,MXSECN ;ADDRESS CHECK IF ILLEGAL SECTION NUMBER
SKIPN .UPMP+SECTAB(T2);SECTION EXIST?
JRST TTPOPJ## ;NO, THAT'S AN ADDRESS CHECK
LSH T2,P2WLSH ;POSITION SECTION NUMBER
HRRZ T1,-1(P) ;IGNORE JUNK WHICH MIGHT BE IN THE LEFT HALF
SKIPL USRHCU## ;IF SAVE IN PROGRESS, ITS OK
CAILE T1,JOBPFI## ;ADDRESS ABOVE PROTECTED JOB DATA AREA?
JRST IADCK1 ;YES
MOVE T1,@[IW MS.MAP,UMAPS(T2)] ;POINTER FOR PAGE 0 OF PCS SECTION
CAMN T1,@[IW MS.MAP,UMAPS] ;SAME AS POINTER FOR PAGE 0 OF SECTION 0?
JRST TTPOPJ## ;YES, ATTEMPT TO DO I/O BELOW JOBPFI
IADCK1: HRRZ T1,-1(P) ;RESTORE ADDRESS WITHIN SECTION
LSH T1,W2PLSH ;PAGE NUMBER FROM ADDRESS
IOR T1,T2 ;<SECTION NUMBER>B27+<PAGE NUMBER>B35
SKIPN T2,@[IW MS.MAP,UMAPS(T1)] ;GET POINTER WHICH MAPS ADDRESS
JRST TTPOPJ## ;ZERO IS ILLEGAL
SKIPL USRHCU## ;IF SAVE IS IN PROGRESS, DON'T CHECK PM.NIA
TLNN T2,(PM.NIA) ;IS I/O ALLOWED INTO THIS PAGE (NOT HI SEG)?
CAIA ;SAVE OR NOT A HIGH SEGMENT PAGE
JRST TTPOPJ## ;I/O NOT ALLOWED, ADDRESS CHECK
LDB T2,[POINT 3,T2,2] ;EXTRACT POINTER TYPE
JUMPE T2,IADCK2 ;JUMP IF PAGED OUT, ACCESS ALLOWED OFF, OR ABZ
CAIE T2,PM.DCD ;POINTER TYPE = DIRECT?
JRST TTPOPJ## ;NO, MUST BE INDIRECT OR SHARE, ADDRESS CHECK
LSH T1,S2PLSH ;BACK TO SECTION NUMBER
HRR T1,-1(P) ;ADDRESS WITHIN SECTION BEING CHECKED
SKIPL USRHCU## ;IF NOT A SAVE IN PROGRESS,
PUSHJ P,CHKWLP## ;MAKE SURE PAGE CONTAINING ADDRESS IS WRITABLE
AOS -2(P) ;PAGE IS IN CORE, LEGAL, AND ACCESSIBLE
IADCK2: AOS -2(P) ;PAGE EXISTS, BUT IS OUT, AA OFF, OR ABZ
JRST TTPOPJ## ;RESTORE ACS AND RETURN
SUBTTL EVM HANDLING ROUTINES
;ROUTINE TO DETERMINE WHETHER A DEVICE NEEDS THE USER AREA
;REPRESENTED IN THE CURRENT I/O OPERATION TO BE
;MAPPED IN EXEC VIRTUAL MEMORY
;CALLING SEQUENCE:
;
; MOVE F,ADDRESSS OF DEVICE DATA BLOCK
; PUSHJ P,MAPDEV
; RETURN HERE IF NO MAPPING REQUIRED
; RETURN HERE IF BUFFERS OR IOWDS MUST BE MAPPED
MAPDEV::PUSH P,T1 ;SAVE P1
MOVEI T1,DEPEVM ;GET "DEVICE DOESN'T NEED EVM" BIT
TDNN T1,DEVTYP(F) ;SKIP IF MAPPING NOT REQUIRED
PJRST TPOPJ1## ;PTY, TTY, AND CHANNEL DEVICES ARE NOT
; MAPPED IN EXEC VIRTUAL MEMORY
PJRST TPOPJ## ;ALL I/O BUS DEVICE REQUIRE MAPPING IN
; EXEC VIRTUAL MEMORY
;ROUTINE TO MAP USER AREA IN THE EXEC MAP
;CALLING SEQUENCE:
;
; MOVE T1,PAGE NUMBER OF STARTING PAGE IN THE EXEC MAP
; MOVE T2,NUMBER OF PAGES
; MOVE T3,USER VIRTUAL ADDRESS
; PUSHJ P,MAPUEV
;OR
; PUSHJ P,MAPUEI IF AT INTERRUPT LEVEL SO EBR,UBR WILL BE
; RESTORED SO DO NOT NEED TO PURGE ASSOCIATIVE MEMORY
; RETURNS HERE - T1=PAGE NUMBER IN THE EXEC MAP, T3=EXEC VIRTUAL
; ADDRESS WHICH CORRESPONDS TO USER VIRTUAL ADDRESS,
; AND ASSOCIATIVE MEMORY IS PURGED
MAPUEV::PUSHJ P,SAVE3## ;SAVE P1-P3
PUSHJ P,MAPUE1 ;MAP THE USER IN EXEC VIRTUAL MEMORY
CAIE T2,1 ;DO WE NEED TO DO MORE
CLRPGT ;RESET THE EXEC BASE REGISTER SO
; THE ASSOCIATIVE MEMORY WILL BE FLUSHED
; AND THE NEW MAPPING WILL BE IN EFFECT
POPJ P, ;RETURN
MAPUEI::PUSHJ P,SAVE3## ;SAVE P1-P3
MAPUE1: SE1ENT
MOVE P2,T1
IFN FTXMON,<
XSFM P3 ;GET PCS
LSH P3,S2PLSH ;CONVERT TO SECTION #
>
HRLI P2,(POINT 36,0)
ADD P2,.CPMAP##
LDB P1,[POINT 9,T3,26]
IFN FTXMON,<
HRLI P3,(MS.MAP)
ADDI P3,UMAPS-1(P1)
>
IFE FTXMON,<
MOVEI P3,.UPMAP-1(P1)
>
MAPUE2: AOS P3 ;INCREMENT
MOVE P1,(P3) ;COPY A PORTION OF THE USER'S MAP TO
ANDI P1,17777 ;CLEAR ALL ACCESS BITS
HRLI P1,(<PM.DCD>B2+PM.WRT+PM.PUB)
IDPB P1,P2 ; THE EXEC MAP
SOJG T2,MAPUE2 ;COPY AS MANY PAGES AS ARE TO BE MAPPED IN EVM
DPB T1,[POINT 9,T3,26]
;FORM AN EXEC VIRTUAL ADDRESS FROM THE EXEC
; PAGE NUMBER AND THE USER VIRTUAL ADDRESS
POPJ P, ;RETURN
;ROUTINE TO MAP A USER BUFFER IN EXEC VIRTUAL MEMORY
;CALLING SEQUENCE:
; MOVE T1,BUFFER SIZE
; MOVE T3,USER VIRTUAL ADDRESS OF BUFFER
; MOVE F,ADDRESS OF THE DDB
; PUSHJ P,GTEVBF
; RETURN HERE ONLY IF REQUEST COULD NEVER BE SATISFIED (THERE WILL
; NEVER BE ENOUGH SLOTS AVAILABLE IN THE EXEC MAP)
; RETURN HERE - T1=BYTE (18)0(9) EXEC VIRTUAL PAGE # (9) # OF EXEC PAGES
; T3 = THE EXEC VIRTUAL ADDRESS OF THE BUFFER
GTEVBF::SUBI T1,2 ;COMPUTE THE UPPER BOUND ON THE NUMBER OF PAGES
IDIVI T1,PAGSIZ+2 ; OF EXEC VIRTUAL MEMORY WHICH MIGHT BE
ADDI T1,2 ; REQUIRED TO COVER THIS BUFFER OR IOWD
CAMLE T1,EVBMAX## ;WILL THAT NUMBER OF PAGES EVER BE AVAILABLE?
POPJ P, ;NO, ERROR RETURN
PUSH P,T1 ;SAVE NUMBER OF PAGES BEING REQUESTED
GTEVB1: PUSH P,T3 ;SAVE THE USER VIRTUAL ADDRESS
PUSHJ P,GETEVM ;ATTEMPT TO GET ENOUGH PAGES TO SATISFY THE REQUEST
JRST GTEVBW ;NOT ENOUGH AVAILABLE (WAIT FOR SOME TO BE FREED UP)
POP P,T3 ;RESTORE THE USER'S VIRTUAL ADDRESS
MOVE T2,(P) ; AND THE NUMBER OF PAGES
PUSHJ P,MAPUEV ;MAP THE BUFFER OR IOWD IN THE EXEC MAP
MOVE T1,T3 ;T1 = EXEC VIRTUAL ADDRESS OF THE BUFFER OR IOWD
POP P,T2 ;MAKE T1 = EXEC VIRTUAL ADDRESS OF SAME
DPB T2,[POINT 9,T1,35]
JRST CPOPJ1## ;GIVE OK RETURN
GTEVBW: POP P,T3 ;RESTORE T3
PUSHJ P,EVWAIT## ;WAIT UNTIL SOME EVM IS FREED UP
MOVE T1,(P) ;RESTORE THE NUMBER OF PAGES REQUIRED
JRST GTEVB1 ;TRY AGAIN
;SUBROUTINE TO GET EXEC VIRTUAL MEMORY
;CALLING SEQUENCE:
;
; MOVE T1,NUMBER OF CONTIGOUS PAGES REQUIRED
; PUSHJ P,GETEVM
; ... ERROR RETURN - NOT ENOUGH AVAILABLE, T1 = LARGEST NUMBER SEEN
; ... OK RETURN - T1 = PAGE NUMBER OF FIRST AVAILABLE PAGE
GETEVM::MOVEI T2,EVMPTR## ;POINT TO EXEC-MAP USAGE TABLE
PUSHJ P,GETBIT## ;GET, SET BITS IN THE TABLE FOR THESE PAGES
POPJ P, ;NOT ENOUGH AVAILABLE, RETURN WITH T1= LARGEST HOLE
JRST CPOPJ1## ;AND GIVE SUCCESS RETURN
;ROUTINE TO GIVE BACK SLOTS IN THE EXEC MAP
;CALLING SEQUENCE:
; MOVE T1,NUMBER OF PAGES
; MOVE T2,EXEC VIRTUAL ADDRESS
; PUSHJ P,GIVEVM
; ALWAYS RETURN HERE
GIVEVM::LDB T2,[POINT 9,T2,26]
IDIVI T2,^D36 ;WHICH WORD
HRLS T2 ;PUT WORD NUMBER IN THE LEFT HALF
ADD T2,EVMPTR## ;MAKE AOBJN POINTER POINT TO THE WORD CONTAINING
; THE FIRST BIT TO CLEAR
PUSH P,T4 ;SETZRS CLOBBER T4
PUSHJ P,SETZRS## ;GIVE BACK THE EVM
PUSHJ P,EVFREE## ;WAKE UP ALL WAITERS FOR EVM
SETZM EVREQ## ;SO NEXT CALLER TO EVWAIT WILL WAIT (IMMEDIATELY)
JRST T4POPJ## ;RETURN
;SUBROUTINE TO GET EVM IF NEEDED FOR OUTPUT
;CALLING SEQUENCE:
; MOVE F,DDB ADDRESS
; PUSHJ P,GTOEVM
; RETURN HERE
;NEVER RETURN IF TO MUCH EVM IS REQUIRED
GTOEVM::SKIPA T3,PDVOAD## ;POINTER TO UVA OF THE BUFFER
; PJRST GTBEVM ;MAP THE BUFFER IN EVM
;SUBROUTINE TO GET EVM IF NEEDED FOR INPUT
;CALLING SEQUENCE:
; MOVE F,DDB ADDRESS
; PUSHJ P,GTIEVM
; RETURN HERE
;NEVER RETURN IF TO MUCH EVM IS REQUIRED
GTIEVM::MOVE T3,PDVIAD## ;POINTER TO UVA OF THE BUFFER
; PJRST GTBEVM ;MAP THE BUFFER IN EVM
;FALL INTO GTBEVM
;SUBROUTINE TO ACCOUNT FOR THE FACT THAT BUFFERS
; ARE TWO WORDS LONGER THAN THE NUMBER OF DATA
; WORDS IN THE BUFFER AND THE FACT THAT THE LINK
; WORD IS REALLY THE SECOND WORD OF THE BUFFER
;CALLING SEQUENCE:
; MOVE T3,POINTER TO THE CURRENT BUFFER (UVA)
; PUSHJ P,GTBEVM
; RETURN HERE T1 = # OF PAGES + STARTING PAGE #, T3 = EVA OF BUFFER
;NEVER RETURN IF NOT ENOUGH EVM
GTBEVM: PUSHJ P,MAPDEV ;IS CURRENT DEVICE A PTY, TTY, OR ON A CHANNEL?
POPJ P, ;YES, DO NOT ALLOCATE ANY EVM
PUSH P,T3 ;SAVE THE USER VIRTUAL ADDRESS OF THIS BUFFER
; SO CAN RETURN EVM ON HUNG DEVICE, ETC.
HRRZ T3,@T3 ;USER VIRTUAL ADDRESS OF THE BUFFER
EXCTUX <HLRZ T1,(T3)> ;SIZE OF THE BUFFER
TRZ T1,IOUSE ;T1 = NUMBER OF DATA WORDS - USE BIT
SUBI T3,1 ;POINT TO ACTUAL FIRST WORD OF THE BUFFER
ADDI T1,2 ;ACCOUNT FOR THE TWO OVERHEAD WORDS IN
; THE BUFFER
PUSHJ P,GTEVBF ;MAP THE BUFFER IN EVM - WAIT UNTIL
; SOME IS AVAILABLE IF NECESSARY
JRST ADRERR## ;NEVER WILL BE ENOUGH EVM
HRL T1,@(P) ;SAVE USER VIRTUAL ADDRESS OF THE BUFFER
ADDI T3,1 ;BUMP BUFFER ADDRESS TO THE LINK WORD
PIOFF ;GUARD AGAINST INTERRUPTS
MOVEM T1,DEVEVM(F) ;SAVE THE STARTING PAGE NUMBER AND NUMBER
; OF PAGES OF EVM FOR ADVANCING BUFFERS
; AND RETURNING EVM
DPB T3,(P) ;STORE THE EVA OF THE BUFFER FOR THE DEVICE ROUTINE
PION ;NOW, ALLOW INTERRUPTS AGAIN
JRST T2POPJ## ;RETURN
;SUBROUTINE TO RESTORE EVM AFTER GIVING IT
; UP ON A CALL TO THE SCHEDULER (CONTROL BUSY, HUNG DEVICE, ETC.)
;CALLING SEQUENCE:
; MOVE F,ADDRESS OF DEVICE DATA BLOCK
; MOVE S,DEVIOS(F) ;DEVICE STATUS
; PUSHJ P,RSTEVM
; RETURN HERE IF NO ADDRESS CHECK WITH DEVEVM(F) SETUP
RSTEVM::LDB T1,PIOMOD## ;GET DATA MODE
CAIL T1,SD ;DUMP MODE?
PJRST DMPEV ;YES, GET EVM DUMP MODE STYLE
TLNE S,IO ;BUFFERED MODE, INPUT OR OUTPUT?
PJRST GTOEVM ;OUTPUT, GET BUFFERED OUTPUT EVM
PJRST GTIEVM ;INPUT, GET BUFFERED INPUT EVM
;SUBROUTINE TO DETERMINE IF A DEVICE NEEDS EVM TO DO DUMP
; MODE I/O AND IF SO TO SCAN THE IOWD LIST TO FIND THE
; IOWD WHICH HAS THE LARGEST WORD COUNT AND ALLOCATE
; ENOUGH EVM TO COVER THAT IOWD.
;CALLING SEQUENCE:
; MOVE M,USER VIRTUAL ADDRESS OF IOWD LIST
; MOVE F,ADDRESS OF DEVICE DATA BLOCK
; PUSHJ P,DMPEV
; RETURN HERE IF NO ADDRESS CHECK WITH DEVEVM(F) SETUP
;PRESERVES T1
DMPEV:: PUSHJ P,SAVE4## ;SAVE P1-P4
MOVE P1,T1 ;SAVE T1
IFN FTXMON,<
HRRZ T1,DEVISN(F) ;GET SECTION NUMBER FOR I/O
PUSHJ P,SVPCS## ;SAVE OLD PCS, SETUP PCS TO SEGMENT NUMBER FOR I/O
>
PUSH P,U ;SAVE U
MOVEI U,0 ;ASSUME THE DEVICE DOES NOT REQUIRE EXEC VIRTUAL
; MEMORY TO DO I/O (DSK, MTA, TTY, PTY)
PUSHJ P,MAPDEV ;NEED EVM TO DO I/O?
TLO U,400000 ;EVM NOT REQUIRED - SET U NEGATIVE
PUSH P,P1 ;SAVE DISPATCH ADDRESS
PUSH P,M ;SAVE THE UUO FOR THE DEVICE ROUTINE
SOS M ;COMPENSATE FOR GETWD1
MOVEI P2,0 ;LARGEST WORD COUNT SEEN SO FAR
MOVEI P3,1000 ;GUARD AGAINST A LOOP (GOTO IOWDS)
DMPEV1: PUSHJ P,GETWD1## ;GET AN IOWD
JUMPE T1,DMPEV4 ;JUMP IF LAST IOWD IN THE LIST
HLRO P1,T1 ;THIS IOWD'S WORD COUNT
TLNE T1,-1 ;A GOTO WORD?
JRST DMPEV2 ;NO, A REAL IOWD
HRRI M,-1(T1) ;A GOTO WORD (POINTS TO THE NEXT IOWD)
JRST DMPEV3 ;GET NEXT IOWD
DMPEV2: MOVNS P1 ;P1 = POSITIVE WORD COUNT FOR THIS IOWD
CAMLE P1,P2 ;GREATER THAN THE LARGEST WORD COUNT SEEN SO FAR?
MOVE P2,P1 ;YES, REMEMBER IT AS LARGEST SEEN
MOVEI T1,1(T1) ;START ADR OF THE IOWD
MOVE T2,P1 ;TOP ADR OF THE IOWD
ADDI T2,-1(T1)
PUSHJ P,TRNGE## ;MAKE SURE THE REQUIRED PAGES ARE IN CORE
DMPEV3: SOJG P3,DMPEV1 ;GET NEXT IOWD IN THE LIST
JRST ADRERR## ;TOO MANY IOWDS (PROBABLY A GOTO WORD LOOP,
; STOP THE JOB AND REPORT THE ERROR)
DMPEV4: POP P,M ;RESTORE THE UUO AND THE POINTER TO THE FIRST
; IOWD IN THE LIST
JUMPL U,DMPEV5 ;DONT ACTUALLY NEED EVM IF U NEGATIVE
PUSHJ P,GETWDU## ;GET THE FIRST IOWD IN THE LIST AGAIN
MOVEI T3,1(T1) ;USER VIRTUAL ADDRESS WHERE I/O WILL START
MOVE T1,P2 ;NUMBER OF WORDS OF EXEC VIRTUAL MEMORY REQUIRED
; TO COVER THE LARGEST IOWD FOUND IN THE IOWD
; LIST
PUSHJ P,GTEVBF ;GET ENOUGH EVM TO COVER THE LARGEST WORD IN
; THE LIST (WAIT UNTIL AVAILABLE IF NECESSARY)
JRST ADRERR## ;WHOOPS! NEVER WILL BE ENOUGH
MOVEM T1,DEVEVM(F) ;DEVEVM = BYTE (18)0(9)EV PAGE #(9)# OF PAGES
DMPEV5: POP P,T1 ;RESTORE DISPATCH ADDRESS
JRST UPOPJ## ;RESTORE U AND RETURN
;ROUTINE TO RETURN ANY EVM A DEVICE MAY HAVE WHEN A SHARABLE RESOURCE
; WHICH CURRENTLY BELONGS TO THE JOB WHICH HAS THE DEVICE IS GIVEN UP.
;CALLING SEQUENCE:
; MOVE F,ADDRESS OF DEVICE DATA BLOCK OR 0 IF NONE
; PUSHJ P,RTEVM
;ALL ACS ARE RESPECTED.
RTEVM:: SKIPE F ;IS THIS A RESOURCE ASSOCIATED WITH I/O?
; I.E., IS THERE A DEVICE DATA BLOCK?
SKIPN DEVEVM(F) ;DOES THE JOB HAVE EVM?
POPJ P, ;NO, JUST RETURN
PUSHJ P,SAVT## ;IT IS THE TRADITION NOT TO CLOBBER ACS HERE
HRRZ T1,P
CAMLE T1,SYSSIZ## ;DON'T CHANGE UBR IF P POINTS TO USER
JRST RTNEVM ;GIVE UP EVM FOR MAPPING I/O
PUSHJ P,SVEUF## ;SAVE THE UBR AND SET IT UP SO CAN ADDRESS CURRENT JOB
PUSHJ P,SPCS## ;ALSO, SETUP PCS
PJRST RTNEVM ;GIVE UP EVM FOR MAPPING I/O IF ANY
;HERE TO GIVE UP EVM THAT THIS DEVICE HAS FOR INPUT OPERATIONS
RTEVMI::HLRZ T3,DEVEVM(F) ;USER VIRTUAL ADDRESS OF CURRENT BUFFER
JUMPE T3,CPOPJ## ;ZERO MEANS NO EVM REQUIRED FOR THE I/O
PJRST RTIEVM ;GIVE BACK THE EVM
;HERE TO GIVE UP EVM THAT THIS DEVICE HAS FOR OUTPUT OPERATIONS
RTEVMO::HLRZ T3,DEVEVM(F) ;USER VIRTUAL ADDRESS OF CURRENT BUFFER
JUMPE T3,CPOPJ## ;ZERO MEANS NO EVM REQUIRED FOR THE I/O
PJRST RTOEVM ;GIVE BACK THE EVM
;ROUTINE TO RETURN SLOTS IN THE EXEC MAP USED TO MAP USER BUFFERS
;CALLING SEQUENCE:
;
; MOVE T3,USER VIRTUAL ADDRESS OF BUFFER
; PUSHJ P,RTNEVM
; ALWAYS RETURN HERE
RTNEVM::MOVS T3,DEVEVM(F) ;ANY EVM ALLOCATED TO THIS DEVICE?
JUMPE T3,CPOPJ## ;NO, JUST RETURN
TRNN T3,-1 ;DUMP MODE I/O?
JRST RTNEV1 ;YES, DON'T CLOBBER DEVXAD
HRLI T3,0
TLNN S,IO ;OUTPUT?
JRST RTIEVM ;NO, GO RETURN INPUT EVM
RTOEVM::DPB T3,PDVOAD## ;STORE UVA IN DEVOAD
JRST RTNEV1 ;RETURN EVM
RTIEVM::DPB T3,PDVIAD## ;STORE UVA IN DEVIAD
RTNEV1: HRRZ T2,DEVEVM(F) ;PAGE NUMBER AND NUMBER OF PAGES OF EVM
LDB T1,[POINT 9,T2,35]
SETZM DEVEVM(F) ;FLAG NO LONGER ANY EVM
PJUMPN T1,GIVEVM ;RETURN THE EVM TO THE FREE POOL AND TELL
; THE SCHEDULAR THAT EVM IS AVAILABLE IF ANY
; JOB IS WAITING FOR SOME
POPJ P, ;RETURN
;ROUTINE TO CALL THE SCHEDULER AND REMEMBER IF A JOB HAS EVM OR NOT.
; IF SO, RESTORE THE EVM WHEN THE JOB BECOMES RUNNABLE AGAIN.
;PRESERVES ALL ACS
RMEVM:: SKIPE F ;IS THERE A DDB?
SKIPN DEVEVM(F) ;AND DOES IT HAVE EVM?
PJRST WSCHD1## ;NO--JUST RESCHEDULE
TRNE S,IOACT ;DON'T RETURN EVM IF THE DDB
JRST WSCHD1## ; IS I/O ACTIVE
PUSHJ P,RTEVM ;YES--RETURN THE EVM SINCE JOB MAY GET SWAPPED
PUSHJ P,WSCHD1## ;RESCHEDULE
PUSHJ P,SAVT## ;SAVE T2-T4
PJRST RSTEVM ;RESTORE THE EVM
;AND RETURN TO THE CALLER
;ROUTINE TO ADVANCE A BUFFER IN EXEC VIRTUAL MEMORY
;CALLING SEQUENCE:
;
; MOVE T3,XWD NEXT BUFFER SIZE,NEXT USER VIRTUAL BUFFER ADDRESS
; RETURN HERE IF NOT ENOUGH PAGES ALLOCATED IN EXEC MAP TO ADVANCE BUFFER
; RETURN HERE - BUFFER ADVANCED
; T1 = EXEC VIRTUAL ADDRESS OF BUFFER
; T3 = USER VIRTUAL ADDRESS OF BUFFER
ADVEVM::PUSH P,T3 ;SAVE BUFFER SIZE,,BUFFER ADDRESS
HRRZ T1,DEVEVM(F) ;BYTE (18)0(9) EXEC VIRTUAL PAGE #(9)# OF EXEC PAGES
HRLM T3,DEVEVM(F) ;STORE UVA OF NEXT BUFFER
HLRZ T2,T3 ;GET BUFFER SIZE
;DON'T NEED TO SUBTRACT 2 SINCE THE BUFFER IS ACTUALLY
; TWO WORDS LONGER THAN THE NUMBER OF DATA WORDS IT CONTAINS
; SUBI T2,2 ;COMPUTE THE UPPER BOUND ON THE NUMBER
IDIVI T2,PAGSIZ+2 ; OF PAGES WHICH MAY BE REQUIRED TO
ADDI T2,2 ; MAP THIS BUFFER IN EXEC VIRTUAL MEMORY
LDB T3,[POINT 9,T1,35]
CAMLE T2,T3 ;DOES THE DEVICE HAVE A ENOUGH EVM TO MAP THIS BUFFER?
JRST T3POPJ## ;NO, STOP THE I/O (ENOUGH PAGES WILL BE
; AQUIRED THE NEXT TIME AROUND AT UUO LEVEL)
LDB T1,[POINT 9,T1,26]
HRRZS T3,(P) ;T3 = USER VIRTUAL ADDRESS OF THE NEXT BUFFER
SOS T3 ;T3 = ADDRESS OF FIRST WORD OF THE BUFFER
PUSHJ P,MAPUEV ;MAP THE NEXT BUFFER IN THE EXEC MAP
EXCH T3,(P) ;RESTORE THE USER VIRTUAL ADDRESS OF THE
; BUFFER IN CASE I/O MUST BE STOPPED FOR
; SOME OTHER REASON
AOS (P) ;BUMP BUFFER POINTER TO THE LINK WORD
PJRST TPOPJ1## ;T1 = EXEC VIRTUAL ADDRESS OF THE BUFFER
;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:: PUSH P,T2 ;PRESERVE T2 AS ADVERTISED
PUSHJ P,CKSTRL ;ADDRESS CHECK THE STRING
JRST T2POPJ## ;RETURN NON-SKIP
AOS -1(P) ;PROPAGATE SKIP RETURN
JRST T2POPJ## ;AFTER RESTORING T2
;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,CKSTRL
;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, T2=LENGTH OF STRING
;PRESERVES T3-T4
CKSTRL::PUSHJ P,SAVE4## ;SAVE P1-P3
SETZ T2, ;INITIALIZE STRING LENGTH COUNTER
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
AOS T2 ;INCREMENT CHARACTER COUNT
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,.USHVA ;HIGHEST VIRTUAL ADDR
NXCMR:: PUSHJ P,SAVE4## ;SAVE P1-P4
MOVEI P4,0 ;ZERO DEYISN
DPB P4,DEYISN## ; SINCE NOT MEANINGFUL FOR A NEW IOWD
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
PUSHJ P,SPCS## ;ALSO SETUP PCS
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,GETMWD## ;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: JUMPL J,NXCOK ;TRUST COMCON IF SAVE IN PROGRESS
; DON'T ADDRESS-CHECK
MOVEI P2,1(T1) ;POINT TO REAL (SECTION-LOCAL) START
HLRO P3,T1 ;SAVE ADDRESS POINTED TO AND NEGATIVE COUNT
SKIPL USRHCU## ;IF USER I/O,
JRST NXCHI2 ;CHECK ANOTHER WAY
CAMG P2,T3 ;IS START ABOVE PROTECTED AREA?
JUMPN P2,NXBAD ;NO. REPORT ERROR
JRST NXCHI3 ;SKIP USER MODE CHECK
NXCHI2: EXCH T1,P2 ;SAVE T1 AND SETUP TO CHECK ADDRESS
PUSHJ P,IADRCK ;IS THE START ADDRESS LEGAL?
JFCL ;NOT LEGAL AT ALL
JRST NXBAD ;ILLEGAL FOR I/O
EXCH T1,P2 ;RESTORE ACS
NXCHI3: SETCA P3, ;WORD COUNT MINUS ONE
ADD P2,P3 ;END OF IO
EXCH P2,T1 ;SAVE T1
PUSHJ P,IADRCK ;LEGAL?
JFCL ;BAD ADDRESS
JRST NXBAD ;PAGE FAULT (SHOULDN'T HAPPEN SINCE LIST WAS CHECKED)
MOVE T2,T1 ;TOP ADR FOR IO
SKIPGE USRHCU## ;SAVE IN PROGRESS?
JRST NXCHI1 ;YES, IOWD LIST IS OK
MOVEI T1,1(P2) ;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)
NXCHI1: 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
HRRM T3,(P) ;STORE EXEC VIRTUAL ADDRESS IN IOWD
POP P,T1 ;T1 = XWD -N,EXEC VIRTUAL ADDRESS FOR I/O
TDZA S,S ;FLAG CURRENT IOWD OK
NXOUT1: MOVEI T1,1 ;SOJA WILL MAKE ZERO
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::PUSH P,T4 ;PRESERVE CALLER'S T4
PUSHJ P,ASSASD ;DO THE WORK
JRST T4POPJ## ;ERROR - RESTORE T4
POP P,T4 ;RESTORE T4
JRST CPOPJ1 ;SUCCESSFUL RETURN
ASSASD:
PUSHJ P,SAVE2##
SETZB P1,P2 ;P1 WILL GET DEVMOD IF SPOOLING
HRRZ T3,SPLBIT##(F) ;POSSIBLE SPOOL-BIT
MOVE T4,J ;GET JCH
ANDI T4,JOBMSK## ;MASK DOWN TO A JOB NUMBER
SKIPN DEVCHR(F) ;FAKE (TABLE) DDB?
JRST ASSAS0 ;YES, SPOOL IT
LDB T3,DEYSPL## ;SPOOL BIT FOR THE DEVICE
SKIPL DEVSPL(F) ;IS THIS A SPOOLED DISK DDB ?
JRST ASAS0A ;NO, GO ON
TLO T3,DEPSPL ;YES. ENSURE COPY HAS DEPSPL ON
SKIPA P1,DEVMOD(F) ;GET THE SPOOLED MODES WORD
ASAS0A: TDNN T3,JBTSPL##(T4) ;JOB SPOOLING THIS DEVICE?
JRST ASSAS1 ;NO
MOVE P2,T3 ;SPOOL BIT
LDB T3,PJCHN## ;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: SKIPGE DEVSPL(F) ;SPOOLED?
JRST ASAS1B ;GENERATE A DDB
MOVE T4,DEVMOD(F) ;DEVMOD
TLNE T4,DVDSK ;DEVICE A DISK?
JRST ASAS1B ;YES
IFN FTNET,<
TLNN T4,DVTTY ;DEVICE A TTY?
JRST ASAS1A ;NO
MOVE T3,DDBLDB##(F) ;GET LDB POINTER
JUMPE T3,ASAS1A ;IF NONE, ALLOW THE ASSIGN
SE1XCT <SKIPGE LDBREM##(T3)> ;IF LOCAL LINE SET HOSTED AWAY
JRST ASSE11 ;YES, ERROR - DEVICE NOT AVAILABLE
> ;END IFN FTNET
JRST ASSAS2 ;SKIP DISK-ONLY STUFF
ASAS1B: PUSHJ P,SETDDB## ;YES, GENERATE A NEW DDB
JRST ASSE16 ;ERROR - NO MONITOR DDB SPACE
ASAS1A:
HLLZS T3 ;LH(T3)=0 OR DEPSPL
IORM T3,DEVSPL(F) ;LIGHT SPOOL-BIT IF NEEDED
ASSAS2: MOVEI T3,DEPMSG
TDNE T3,DEVMSG(F) ;CONTROLLED BY MPX?
JRST ASSE55 ;ERROR - DEVICE IN USE BY MPX
NOSCHEDULE ;DISABLE SCHEDULING
LDB T1,PJCHN## ;GET JOB NUMBER IN DEV DATA BLOCK
MOVEI T4,ASSPRG ;BIT TO TEST
TDNN T4,DEVMOD(F) ;ASSIGNED BY PROGRAM?
TRNN T2,ASSCON ;ASSIGN COMMAND?
SKIPA T3,J ;NO--USE JCH FROM JOB DOING THE ASSIGN
SKIPA T3,T1 ;COPY
JRST ASSA2Z ;SKIP SOME WORK IF CAN
ANDI T3,CTXMSK## ;KEEP ONLY THE JOB NUMBER
MOVE T4,J ;GET JCH
ANDI T4,JOBMSK## ;KEEP ONLY THE CONTEXT NUMBER
IOR T3,T4 ;FORM JCH FROM DDB INFO
ASSA2Z: TRNN T1,CTXMSK## ;ANY CONTEXT SPECIFIED IN DDB?
ANDI T3,JOBMSK## ;NO, THEN ONLY COMPARE JOB #S
CAMN T1,T3 ;IS IT ALREADY ASSIGNED TO THIS JOB
JRST ASSA2C ;YES--ASSIGN WINS
MOVEI T1,ASSPRG+ASSCON;NO, IS IT ASSIGNED TO ANOTHER JOB?
TDNN T1,DEVMOD(F) ;ARE EITHER ASSIGNED BITS SET?
JRST ASSA2Y ;PRESS ON
LDB T1,PJCHN## ;GET JOB/CONTEXT HANDLE
TRZE T1,CTXMSK## ;INITIED BY A CONTEXT?
TRNE T3,CTXMSK## ;AND INITING BY A CONTEXT?
SKIPA ;NO GOOD
CAIE T1,(T3) ;SAME JOB NUMBER?
JRST ASSE47 ;ASSIGNED TO ANOTHER JOB/CONTEXT
LDB J,PJCHN## ;FAKE OUT COMCON WITH JOB/CONTEXT HANDLE
ASSA2Y: HRLZI T1,DEPRAS ;GET RESTRICTED ASSIGNMENT BIT
PUSH P,J ;SAVE TARGET JCH
TDNN T1,DEVSTA(F) ;IS THIS DEVICE RESTRICTED?
JRST ASSA2A ;NO, PROCEED
ANDI J,JOBMSK## ;KEEP ONLY THE JOB NUMBER
PUSHJ P,PRVJ## ;THIS JOB PRIVILEDGED TO ASSIGN?
JRST ASSA2A ;YES
POP P,J ;NO--RESTORE JCH
JRST ASSE50 ;SET T2=-1 AS FLAG AND RETURN ERROR
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?
TDNN T1,DEVCHR(F) ;?
JRST ASSA2B ;NO--OK TO ASSIGN
POP P,J ;RESTORE JCH
JRST ASSE51 ;ERROR - DEVICE CONTROLLED BY MDA
ASSA2B:
>;END IFN FTMDA
POP P,J ;RESTORE JCH
DPB J,PJCHN## ;STORE JCH IN DDB
IORM T2,DEVMOD(F) ;SET IN USE BITS
JRST ASSA2D ;ONWARD
ASSA2C: DPB J,PJOBN## ;STORE JOB IN THE DDB
TRNN T2,ASSCON ;ASSIGN COMMAND?
DPB J,PJCHN## ;STORE JCH IN THE DDB
ASSA2D: TRNN T2,ASSCON ;IF ASSIGN COMMAND,
JRST ASSAS3
PUSH P,T2 ;SAVE FROM DESTRUCTION
PUSHJ P,TPMRES## ;RESET MAGTAPE DDB PARAMETERS
POP P,T2 ;RESTORE ASSIGN BIT
ASSAS3: IORM T2,DEVMOD(F) ;SET IN USE BITS AGAIN IN CASE SAME JOB
AOSA (P) ;GIVE OK RETURN
ASSA4A: HRREI T2,-1 ;FLAG AS RESTRICTED DEVICE
ASSAS4: SCHEDULE ;TURN SCHEDULING ON
POPJ P, ;GIVE ERROR RETURN
ASSE11: MOVEI T4,DNAERR ;DEVICE-NOT-AVAILABLE ERROR
POPJ P, ;ERROR RETURN
ASSE16: MOVEI T4,NETERR ;NOT-ENOUGH-TABLE-SPACE ERROR
POPJ P, ;ERROR RETURN
ASSE47: LDB T1,PJCHN## ;REFETCH JOB NUMBER OWNING DESIRED DEVICE
MOVEI T4,DAJERR ;ASSUME IN USE BY ANOTHER JOB/CONTEXT
JUMPN T1,ASSAS4 ;RETURN IF GUESSED RIGHT
MOVEI T4,DDUERR ;WRONG, JOB 0, DEVICE-DOWN (DETACHED) ERROR
JRST ASSAS4 ;ERROR RETURN
ASSE50: MOVEI T4,DRSERR ;DEVICE-IS-RESTRICTED ERROR
JRST ASSA4A ;ERROR RETURN
ASSE51: MOVEI T4,DCMERR ;DEVICE-IS-MDA'ED ERROR
JRST ASSA4A ;ERROR RETURN
ASSE55: MOVEI T4,DUMERR ;DEVICE-IN-USE-BY-MPX ERROR
POPJ P, ;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,.USCTA
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
;SUBROUTINE TO TERMINATE OWNERSHIP OF A DEVICE. F POINTS TO THE
; DDB. PRESERVES J.
CLRDVL::LDB T1,PJCHN## ;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,PJCHN## ;CLEAR JOB/CONTEXT HANDLE
POPJ P, ;EXIT.
;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
CAIL T1,FYSORG ;DDB LIVE WITHIN
CAIL T1,FYSORG+FYSSIZ ; FUNNY SPACE?
SKIPN .USJOB ;NO--IS A REAL JOB MAPPED?
TRZA F,-1 ;NO MORE DDBS
HLR F,.USLST ;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 PHY,LOGNAMES,FLAG DEASSIGN
DEVDEA: MOVEI T2,DD%PHY+DD%LOG+DD%DEA
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
;NOTE THAT ON SKIP-REUTURN, T2 IS SETUP WITH PREDECESSOR DDB ADDRESS.
;BE CAREFUL NOT TO BREAK THIS.
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
DEVPSN::MOVEI T2,DD%PHY!DD%ALT ;SEARCH PHYSICAL AND SECONDARY UNITS
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
JRST DVSRSP
DEVSRD::PUSHJ P,DEVDEA ;SEARCH PHY,LOG,FLAG DEASSIGN
TDZA T3,T3 ;NOT FOUND
JRST CPOPJ1## ;FOUND
;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)
PJRST DVASRC ;SEARCH FOR GENERIC, GIVE ERROR OR OK RETURN
;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
S0PSHJ 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
JUMPN J,OPRFND ;IS J EQUAL TO 0?
HLRZ T2,LDBREM##(U) ;YES, GET NDB POINTER IF ANY
SKIPE T2 ;IS HE LOCAL?
HLRZ T1,(T2) ;NO, GET NODE # FROM NDB.
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!FTMPXSER,<
;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
PUSH P,T2 ;SAVE IN LH OF CURRENT STACK WORD
SKIPE T1 ;WHEN DONE - SKIP
PUSHJ P,CVTSB1 ;RECURSIVELY DO ABOVE AGAIN
POP P,T1 ;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
;KONUSN - RETURN USER TYPE (DD.XXX) GIVEN USER NAME (SIXBIT/XXX/)
;CALL IS:
;
; MOVX T1,<NAM>
; PUSHJ P,KONUSN
; ERROR RETURN
; NORMAL RETURN
;
;WHERE <NAM> IS THE SIXBIT USER NAME (E.G., 'NOBODY', ETC.)
;
;ON ERROR RETURN, THE NAME IS UNKNOWN.
;
;ON NORMAL RETURN, T2 HAS THE USER TYPE (E.G., DD.NOB)
;
;USES T2.
KONUSN::MOVSI T2,-DTNAML ;LENGTH OF TABLE OF NAMES TO SEARCH
CAME T1,DTNAME(T2) ;NAME MATCH?
AOBJN T2,.-1 ;NO, SEARCH REST OF TABLE
JUMPG T2,CPOPJ## ;ERROR IF NO MATCH
ANDI T2,-1 ;RETURN ONLY POSITIVE USER TYPE
JRST CPOPJ1## ;SUCCESSFUL RETURN
;DTNAMES - LINE "USER"S
DEFINE X (NAM),<
IFN .-DTNAME-DD.'NAM,<PRINTX ? DTNAME NAM entry out of order>
SIXBIT\NAM\
> ;END DEFINE X
DTNAME::X (NOBODY)
X (ANF)
X (DECNET)
X (PROGRA)
X (IBM)
DTNAML==.-DTNAME
;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 [ALLOW] PHYSICAL NAMES
; DD%LOG SEARCH FOR [ALLOW] LOGICAL NAMES
; DD%CHN DISALLOW DEVICES IN PER-PROCESS SPACE
; DD%NDS DISALLOW DISK-TYPE DEVICES
;
;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 ;ALLOW LOGICAL NAMES
DD%PHY==:1B34 ;ALLOW PHYSICAL NAMES
DD%CHN==:1B33 ;DISALLOW PER-PROCESS DEVICES (DDBS)
DD%PHO==:1B32 ;ON IF PHYSICAL ONLY
DD%DEA==:1B31 ;DEASSIGN FLAG
DD%ALT==:1B30 ;SEARCH ALTERNATE (SECONDARY) PORT FOR UNITS
DDBSRC: TRNE J,-1-JOBMSK## ;JCH?
JRST DDBSCC ;YES, GO SEARCH FOR DEVICE
PUSH P,T1 ;SAVE DEVICE NAME
PUSH P,T2 ;AND FLAGS
PUSHJ P,CTXJCJ## ;GET CURRENT CONTEXT FOR JOB NUMBER IN J
JUMPN J,TTPOPJ## ;NO CONTEXT, NO DEVICES
POP P,T2 ;RESTORE FLAGS
EXCH T1,(P) ;RESTORE DEVICE, SAVE JCH
EXCH J,(P) ;GET JCH, SAVE JOB NUMBER
PUSHJ P,DDBSCC ;SEARCH FOR DEVICE
JRST JPOPJ## ;NO SUCH DEVICE
JRST JPOPJ1## ;FOUND RETURN
DDBSCC: 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
MOVEI F,.USLST-DEVSER ;SET PREDESSOR
DEVLP4: HLRZ F,DEVSER(F) ;GET A DDB ADDRESS
JUMPE F,NOLGST ;CONTINUE IF NO MORE
PUSHJ P,DDSCNM ;NAMES AND JCHS MATCH?
JRST CPOPJ1## ;YES, FOUND RETURN
JRST DEVLP4 ;GO CHECK OUT THE NEXT ONE
DEVLP7: TRNN P1,DD%PHY ;PHYSICAL?
POPJ P, ;NO, NOT FOUND
TRZ P1,DD%LOG ;YES, TURN OFF LOG
NOLGST: PUSH P,J ;SAVE JCH FOR COMPARISONS
ANDI J,JOBMSK## ;KEEP ONLY JOB NUMBER FOR TEST ROUTINES
TLZ P1,-1 ;CLEAR PHONLY
TRNN P1,DD%PHY ;PHYSICAL SEARCH?
JRST DDSRC2 ;NO DON'T SET UP
TRNE P1,DD%CHN ;DON'T LOOK AT DISKS IF SEARCHING ONLY DEVLST
JRST DDSRC0
CAMN T1,['SY '] ;PDP-11 STYLE OF SYS:?
MOVSI T1,'SYS' ;YES, SUBSTITUTE HERE AS TSTDSK WON'T
;(CK2CHR WOULD BUT WE DON'T WANT TO CALL IT HERE)
PUSHJ P,TSTDSK## ;IS THIS A DISK?
JRST [TRNN P1,DD%LOG ;LOGICAL SEARCH?
JRST JPOPJ1## ;NO FOUND PHYSICAL
HRL P1,F ;YES, SAVE DDB
JRST .+1] ;AND CONTINUE
DDSRC0: PUSHJ P,TSTTSK## ;IS THIS A TSK DEVICE
CAIA ;NO, CONTINUE SEARCH
JRST JPOPJ1## ;YES, EXIT WITH F=DDB POINTER
TDNN T1,[77,,-1] ;IS THIS A 2-CHAR DEVICE NAME?
PUSHJ P,CK2CHR ;YES, CHECK FOR WEIRD NAMES
PUSHJ P,TSTOPR ;CHECK FOR "OPR"
MOVSI T3,DVDSK
DDSRC2: DDBSRL
HLR F,DEVLST## ;GET START OF CHAIN
DDSC2A: TRNN P1,DD%LOG ;LOGICAL NAME SEARCH?
JRST GETPHY ;NO
MOVE J,(P) ;RETRIEVE JCH
PUSHJ P,DDSCNM ;YES, NAMES AND JCHS MATCH?
JRST DDSRCV ;YES, CLEAR SYS BIT AND RETURN GOODNESS
ANDI J,JOBMSK## ;NO, BACK TO JOB NUMBER
GETPHY: TRNN P1,DD%PHY ;PHYSICAL SEARCH?
JRST DDSRC3 ;NO, SKIP OVER THIS
SKIPGE DEVSPL(F) ;NO MATCH ON SPOOLED DDB'S
JRST DDSRC3 ;IT IS A SPOOLED DDB
TDNN T3,DEVMOD(F) ;IF TSTDSK SAYS IT 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?
JRST JPOPJ## ;NO, AND WE DIDN'T FIND A LOGICAL MATCH
HLRZ F,P1 ;YES, GET SAVED ADDRESS
IFN FTNET,<
HLRZ T2,DEVNAM(F) ;GET LH(NAME)
TRNN P1,DD%DEA ;UNLESS DEASSIGN,
CAIE T2,'TSK' ;DON'T MATCH AN OLD TSK DEVICE
> ;END IFN FTNET
JUMPN F,JPOPJ1## ;EXIT WITH PHYSICAL DDB MATCH IF THERE WAS ONE
IFN FTNET,<
TRZE P1,DD%LOG ;NO LONGER CARE ABOUT LOGICALS
PUSHJ P,TSTTSK## ;TRY THIS AGAIN
CAIA ;NO
JRST JPOPJ1## ;WIN WITH OUR TSK
PUSHJ P,TSTDDP## ;CHECK FOR DDP DEVICE
SKIPA ;NO
JRST JPOPJ1## ;YES
PUSHJ P,TSTRDX## ;CHECK FOR REMOTE DATA ENTRY ROUTINE
SKIPA ;NO
JRST JPOPJ1## ;YES,
TRNN T1,505050 ;MUST BE NUMERIC RT HALF
PUSHJ P,TSTNET## ;YES CHECK FOR NETWORK DEVICE
SKIPA ;NOT A NETWORK DEVICE
PJRST JPOPJ1## ;YES, FOUND THE DEVICE ON THE NETWORK
>;END FTNET
IFN FTMPXSER,<
PUSHJ P,TSTMPX## ;NO, CHECK FOR MPX DDB
SKIPA ;NO--TRY FOR TTY
JRST JPOPJ1## ;YES--ALL DONE
>;END FTMPXSER
IFN FTKS10,<
PUSHJ P,TSTKDP## ;SEE IF IT'S A LEGAL KDP
SKIPA ;IT ISN'T
JRST JPOPJ1## ;IT IS. RETURN IT
PUSHJ P,TSTDMR## ;WELL, SEE IF A DMR
CAIA ;NO
JRST JPOPJ1## ;YES, SUCCESS
>;END FTKS10
IFN FTKL10,<
PUSHJ P,TSTDTE## ;DTE DEVICE?
SKIPA ;NO
JRST JPOPJ1## ;YES, ALL DONE
>
CAME T1,[SIXBIT /TTY/] ;IS THIS PUBLIC LOGICAL NAME TTY?
JRST GETDDB## ;SEE IF IT'S A TTY
JUMPE J,JPOPJ## ;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
POP P,U
JRST JPOPJ1## ;GOOD RETURN
DDSRCV: TLZ F,-1
DDSRCW: DDBSRU
JRST JPOPJ1##
;SUBROUTINE TO SEE IF LOGICAL NAMES AND JCHS MATCH. ENTER F=DDB TO CHECK,
; EXIT CPOPJ IF THEY MATCH, CPOPJ1 IF THEY DON'T MATCH
DDSCNM: JUMPE F,CPOPJ1## ;NO MATCH IF F=0
CAME T1,DEVLOG(F) ;LOGICAL NAMES MATCH?
JRST CPOPJ1## ;NO
LDB T4,PJCHN## ;GET JCH
CAMN J,T4 ;JCHS MATCH?
POPJ P, ;YES, WE HAVE A WINNER
TRNN T4,-1-JOBMSK## ;IF DDB DOESN'T CONTAIN A CONTEXT NUMBER (NOT
XOR T4,J ; INITED), MATCH ON JOB NUMBERS IS OK
TRNE T4,JOBMSK## ;DO THEY MATCH?
AOS (P) ;NO
POPJ P, ;RETURN
;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
;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##
;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
>
;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
IFN FTNET,<HLRZ F,DEVLST> ;MAY ONLY BE A NETWORK DEVICE
IFE FTNET,<
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 ;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
PUSH P,T3 ;SAVE THIS
CAMN P1,[SIXBIT/LPT/] ;LL/LU
JRST DVLPTS ;IT'S A FUNNY LPT
PUSHJ P,TPMDVS## ;CONVERT 'MT' INTO 7 OR 9-TRACK EQUIVALENT
SETZ T3, ;NOT A MAGTAPE?
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 A 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 ;NO - 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,PJCHN## ;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,FFAPPN## ;=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
;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 DEVICE 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
;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
SETZ F, ;DEVLG FAILED, CAN'T TRUST C(F)
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
PUSHJ P,ALIASD## ;GENERIC DSK?
JRST FPOPJ## ;YES, GIVE NON-SKIP RETURN
TRNN T1,-1 ;DEV?
JRST GNRCD1 ;CHECK GENTAB
TRNN T1,7700 ;DEVN?
JRST FPOPJ1## ;CANNOT BE GENERIC IF 4 CHARACTERS LONG
POP P,F ;RESTORE F
SKIPN T1,DEVDRV(F) ;GET DRIVER DISPATCH
POPJ P, ;IF NO DISPATCH, ASSUME GENERIC
MOVE T1,DRVCNF(T1) ;GET INTERESTING BITS
TRNN T1,DR.NET ;DEVICE HAVE ENCODED ANF-10 STATION NUMBERS?
AOS (P) ;THEN 5 CHARACTER NAMES AREN'T GENERIC
POPJ P, ;RETURN
GNRCD1: 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
HLRZS P1 ;PUT NAME IN RH
DDBSRL ;INTERLOCK DDB SCANNING
MOVE P2,GENPTR## ;AOBJN POINTER TO GENERIC DDB TABLE
DVS2: CAMN P1,GENTAB##(P2) ;MATCH?
JRST DVS3 ;YES, FOUND DEVICE
AOBJN P2,.+1 ;ACCOUNT FOR TWO WORD ENTRIES
AOBJN P2,DVS2 ;KEEP SEARCHING
JRST DVS5 ;NO, NONE ARE DEFINED
DVS3: MOVE F,GENTAB##+1(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
DDBSRU ;RELEASE INTERLOCK
HRLZS P1 ;RESTORE NAME TO LH
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
;ATTACH UNIT RECORD DEVICE
DDBATT::SKIPN DEVCHR(F) ;IS IT A "FAKE" DDB?
POPJ P, ;YES, CAN'T ATTACH SPOOLED DEVICE
LDB T1,PJOBN## ;GET JOB NUMBER
MOVEI T2,ASSCON ;BIT TO TEST
TDNE T2,DEVMOD(F) ;WAS DEVICE DETACHED?
JUMPN T1,RCNDAA ;IS IT JOB ZERO?
ANDCAM T2,DEVMOD(F) ;CLEAR ASSIGNED BY CONSOLE COMMAND BIT
SETZM DEVLOG(F) ;CLEAR LOGICAL NAME ASSIGNMENT
DPB T1,PJOBN## ;SET JOB NUMBER
PUSHJ P,TPMRES## ;RESET MAGTAPE DDB PARAMETERS
JRST CPOPJ1## ;RETURN SUCCESS
;DETACH A UNIT RECORD DEVICE
DDBDET::MOVEI T2,ASSPRG ;BIT TO TEST
TDNE T2,DEVMOD(F) ;DEVICE IN USE?
POPJ P, ;CAN'T DETACH IT
LDB T3,PDVTYP## ;GET DEVICE TYPE
CAIE T3,.TYPTY ;IS IT A PTY?
TLNE T2,DVTTY ;IS IT A TTY?
POPJ P, ;YES, ILLEGAL DEVICE
MOVEI T2,ASSCON ;FOUND-SET UP ASSIGNED BY CONSOLE
PUSHJ P,ASSASG ;TRY TO ASSIGN
POPJ P, ;CAN'T ASSIGN
SKIPGE DEVSPL(F) ;SPOOLED?
PJRST CLRDDB## ;ERROR WHEN DEVICE IS SPOOLED
TLNE F,SYSDEV ;IS THIS SYSTEM DEVICE?
POPJ P, ;YES, ILLEGAL DEVICE
MOVEI T1,0 ;NO. SET JOB NUMBER TO ZERO
DPB T1,PJOBN## ; ..
JRST CPOPJ1## ;RETURN SUCCESSFUL
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.
;ENTER AT BUFCLF WITH T1 = WHERE TO BUILD BUFFERS
;IF U IS NON-ZERO, SETUP BUFFERS (U) SIZE, IF U IS ZERO, USE DEFAULT BUFFER SIZE
BUFCLF: PUSH P,.JDAT+JOBFF## ;SAVE JOBFF
HRRM T1,.JDAT+JOBFF##;WHERE TO SETUP THE RING
PUSHJ P,BUFCLC ;SETUP THE RING
POP P,.JDAT+JOBFF## ;RESTORE JOBFF TO ORIGINAL VALUE
POPJ P, ;AND RETURN
;HERE TO ACTUALLY BUILD THE USER'S BUFFER RING STRUCTURE, ALLOCATING
;MEMORY AS NEEDED BASED ON USER'S .JBFF
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
SKIPN P3,U ;BUFFER SIZE SUPPLIED BY THE USER?
LDB P3,PBUFSZ## ;NO, P3=DEFAULT BUFFER SIZE
HRRZ P1,.JDAT+JOBFF##;P1:=FIRST FREE LOCATION
ADDI P1,1 ;P1:=FIRST BUFFER'S LINK (.BFHDR) WORD
HRRZ P2,P1 ;WORKING COPY FOR LINKING RING
HRL P2,P3 ;P2:=BUFFER SIZE,FIRST FREE LOC + 1
ADDI P3,2 ;P3:=BUFFER SIZE + 2 (INCLUDE .BFSTS & .BFHDR)
HRRZ T2,M ;T2:=N="E" FIELD OF AC UUO=COUNT OF BUFFERS
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 ;TIMES NO. OF BUFFERS
ADDI T1,0(P2) ;ADD LOCATION OF 1ST BUFFER
SUBI T1,1 ;READJUST FOR USRREL COMPARISON
TLZE T1,-1 ;CHECK IF HE WENT OVER 256K
PJRST ADRERR## ;BETTER NOT ALLOW THAT!
MOVE T2,T1 ;SAVE HIGHEST ADDRESS IN THE RING
MOVEI T1,-1(P1) ;START ADDRESS OF RING INCLUDING FIRST "S WORD"
BUFCL0: PUSHJ P,IADRCK ;SEE IF PAGE EXISTS AND IS IN CORE
JRST BUFCL4 ;DOESN'T EXIST OR ILLEGAL
JRST UUOFLT## ;PAGED OUT
TRZ T1,PG.BDY ;ROUND DOWN
ADDI T1,PAGSIZ ;NEXT PAGE
CAMG T1,T2 ;CHECKED ALL THE NEEDED PAGES?
JRST BUFCL0 ;NO, CHECK THE NEXT PAGE
JRST BUFCL5 ;HAVE ENOUGH CORE, GO CREATE RING
;MUST ALLOCATE USER MEMORY TO HOLD THE RING
BUFCL4: PUSH P,M ;SAVE A BUNCH OF ACS USED IN CORE AND IO WAIT
PUSH P,F
PUSH P,T4
PUSHJ P,ALCORE ;TRY TO ASSIGN CORE
POP P,T4
POP P,F
POP P,M
MOVE S,DEVIOS(F) ;ALCORE MAY HAVE ALLOWED S TO BE CHANGED
;MEMORY ALLOCATED, BUILD THE RING STRUCTURE
BUFCL5: HRRZ T1,P2 ;FIRST ADDRESS
PUSHJ P,LRNGE## ;MAKE SURE ALL PAGES ARE IN CORE
HRRZ T2,P2 ;SAVE FIRST ADDRESS + 1
BUFCL6: 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,BUFCL6 ;N:=N-1. IS N GR 0?
HRR P2,T2
MOVEI T1,-2(P1) ;CHECK LAST ADR. OF HEADER
PUSHJ P,UADRCK
SUB P1,P3
IFN FTMPXSER,<MOVE T4,P1> ;T4 = ADDRESS OF LAST BUFFER
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 ALLOCATE CORE TO BUILD A BUFFER RING
;CALL WITH T1=WHERE TO BEGIN ALLOCATION, T2=HIGHEST ADDRESS IN RING
;RETURNS T2=HIGHEST ADDRESS IN THE RING
ALCORE::PUSHJ P,SAVE4## ;ACS MIGHT GET CLOBBERED BY THE UUO
MOVE P1,T1 ;SAVE T1
XSFM T1 ;SAVE PCS, SET IT TO CURRENT VALUE
IFN FTXMON,<PUSHJ P,SVPCS##> ;SAVE PCS AND SET IT TO ZERO
MOVE T1,P1 ;RESTORE T1
EXCTUX <PUSH P,P1> ;SAVE USER ACS FOR UUO ARGUMENTS
EXCTUX <PUSH P,P2>
EXCTUX <PUSH P,P3>
PUSH P,T2 ;SAVE HIGHEST ADDRESS
PUSH P,.USCTA ;THE PAGE UUO CLOBBERS THIS
PUSH P,.USMUO ; AND THIS ONE TOO
LSH T1,W2PLSH ;STARTING PAGE NUMBER
LSH T2,W2PLSH ;ENDING PAGE NUMBER
SUBI T2,-1(T1) ;T2:=NUMBER OF PAGES NEEDED
EXCTXU <MOVNM T2,P2> ;SET NEGATIVE/REPEAT PAGE. COUNT
XSFM T2 ;GET FLAGS AND PCS
ANDI T2,MXSECN ;ISOLATE PCS
LSH T2,P2WLSH ;BIG PAGE NUMBER
IOR T2,T1 ;<SECTION NUMBER>B27+<PAGE NUMBER>B35
TLO T2,(PG.IDC) ;DON'T CARE IF PAGES ALEREADY EXIST
EXCTXU <MOVEM T2,P3> ;STORE STARTING SECTION/PAGE NUMBER
ALCOR1: MOVE T1,[.PAGCD,,P2] ;CREATE A PAGE
EXCTXU <MOVEM T1,P1> ;STORE PAGE UUO ARGUMENT LIST
PAGE. P1, ;CREATE THE [PHYSICAL] PAGE(S)
CAIA ;OOPS, SEE IF NEED TO GO VIRTUAL
JRST ALCOR6 ;NEW MEMORY ALLOCATED SUCCESSFULLY
EXCTUX <MOVE T1,P1> ;RETRIEVE PAGE. UUO ERROR CODE
CAIE T1,PAGLE% ;"CORE LIMIT EXCEEDED"?
JRST ALCOR6 ;NOPE, FLICK IT IN
MOVSI T1,(PG.DSK+PG.IDC) ;PA.GCD - CREATE ON DISK ('VIRTUAL') FLAG
EXCTXU <IORM T1,P3> ;MODIFY ORIGINAL REQUEST
MOVE T1,[.PAGCD,,P2] ;PAGE. UUO ARGUMENT POINTER
EXCTXU <MOVEM T1,P1> ;STORE PAGE. UUO ARGUMENT LIST
PAGE. P1, ;CREATE THE [VIRTUAL] PAGE(S)
JFCL ;IGNORE ERROR,
; IF ILLEGAL PAGE NUMBER OR NOT ENOUGH CORE,
; AN ADDRESS CHECK WILL OCCUR
ALCOR6: POP P,.USMUO ;RESTORE PER-PROCESS INFO THAT
POP P,.USCTA ; THE PAGE. UUO CLOBBERED
POP P,T2 ;RESTORE HIGHEST ADDRESS
EXCTXU <POP P,P3> ;RESTORE USER ACS
EXCTXU <POP P,P2>
EXCTXU <POP P,P1>
POPJ P, ;AND 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
MOVSI T4,DEPLBF##
TDNE T4,DEVLBF##(F) ;LARGE BUFFERS?
SKIPA T2,NUMLBF## ;YES, USE NUMLBF
MOVE T2,NUMBF## ;NO, USE NUMBF
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##
HRRZ T1,T2
POP P,T2 ;RESTORE FIRST ADR.
NOSHUFF ;NO SHUFFLING
EXCTXU <SETZM 1(T2)> ;CLEAR THE THIRD WORD
HRLI T2,1(T2)
ADDI T2,2
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,URELEA ;RELEASE ALL IO DEVICES
;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
PUSHJ P,SSEC0## ;DON'T REALLY NEED S0, BUT ROUTINE IN T1 IS
;S0 BASED AND WE WANT TO RETURN TO S1 IF THAT
;WHERE WE WERE CALLED FROM
PUSH P,T1 ;SAVE ADR. OF SUB.
PUSH P,M ;SAVE M
HLRZ P3,.USCTA
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
IOALL0: MOVSI M,FLMCOM ;DON'T RETURN ERROR CODES TO USER
HRRZ T1,.USCTA
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,.USCTA
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,.USCTA
JUMPE P2,IOALL2
HRLI P2,-HIGHXC+20
MOVEI P1,20
JRST IOALL0
IOALL2: HRLM P3,.USCTA
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 FTMPXSER,<
MOVEI T1,DEPMSG ;LOAD UP THE MESSAGE BIT
TDNN T1,DEVMSG(F) ;CONTROLLED BY MPXSER?
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 FTMPXSER
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,
>
;ROUTINE TO PERFORM HUNG DEVICE CHECKING
DEVCHK::PUSHJ P,SAVE1## ;SAVE P1
MOVSI P1,-TYPMAX-1 ;AOBJN POINTER
DEVCK1: SKIPN F,DDBTAB##(P1) ;GET A DDB
JRST DEVCK4 ;TRY NEXT DEVICE TYPE
LDB T1,PDVTIM## ;PROTOTYPE--GET POSSIBLE HUNG TIMER VALUE
JUMPE T1,DEVCK4 ;THIS TYPE OF DDB DOESN'T QUALIFY
SKIPE DEVNAM(F) ;IF IT HAS A NAME,
JRST DEVCK3 ;START HERE (AND ASSUME IT NEEDS THE TIMING)
DEVCK2: HLRZ F,DEVSER(F) ;LINK TO NEXT DDB
JUMPE F,CPOPJ## ;END OF CHAIN?
DEVCK3: LDB T1,PDVTYP## ;GET DEVICE TYPE
CAIN T1,(P1) ;SAME GROUP?
JRST DEVCK5 ;YES
DEVCK4: AOBJN P1,DEVCK1 ;ADVANCE TO NEXT DEVICE TYPE
POPJ P, ;DONE
DEVCK5:
IFN FTMP,<
PUSHJ P,CHKCPI## ;DEVICE ON THIS CPU?
JRST DEVCK2 ;NO, IGNORE IT
CAME T1,.CPBIT## ;THE ONLY CPU?
PUSHJ P,ISITQ ;NO, QUEUED PROTOCAL?
JRST DEVCK6 ;NO
CAIN T1,PCLCP0## ;YES, DID I/O START ON THIS CPU?
MOVEI T1,0
CAME T1,.CPCPN##
JRST DEVCK2 ;NO, LET OTHER CPU HANDLE IT
> ;END IFN FTMP
DEVCK6: 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 DEVCK7 ;IT IS
MOVSI T1,DVOFLN ;ITS ON-LINE, CLEAR THE OFF-LINE BIT
ANDCAM T1,DEVCHR(F)
PUSHJ P,PSIONL## ;TELL THE USER ITS ON-LINE IF HE'S INTERESTED
DEVCK7: 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 ;YES
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
JRST DEVCK2 ;ON TO THE NEXT DEVICE
;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
CAIN T1,A8 ;8-BIT ASCII 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 FTMPXSER,<
MOVEI T1,DEPMSG ;CONTROLLED BY MPXSER ?
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,
;HERE FROM FILOP.
FOPSST: HRRZ T1,FOPFLG
CAIGE T1,2
JRST FOPILU
PUSHJ P,GETWD1##
HRR M,T1
AOS (P) ;GOOD RETURN
;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
JRST ILLMOD## ;BOMB THE USER JOB
TRZ M,IOACT ;LET USER SET ALL BITS EXCEPT IOACT
MOVE T1,DEVMOD(F) ;GET DEVICE TYPE BITS
TLNE T1,DVDSK ;IF A DISK
TRZ M,IOSFA## ;DON'T LET USER SET IOSFA EITHER
HRRM M,DEVIOS(F)
MOVE S,DEVIOS(F) ;SET UP "S" SINCE WE JUST CHANGED DEVIOS
TLNE T1,DVTTY ;IS IT A TTY
TLNE T1,DVDSK ; AND NOT A DISK (NUL)?
POPJ P,
MOVE U,DDBLDB##(F) ;YES, SET UP U
JUMPE U,CPOPJ## ;FORGET IT IF DETACHED
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)
TDNN T1,DEVMOD(F)
POPJ P, ;ILL DATA MODE
JRST CPOPJ1## ;DATA MODE OK, SUCCESSFUL RETURN
;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
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,1000 ;ASSUME BYTE MODE
LDB T2,PIOMOD## ;GET MODE FROM S
CAIE T2,A8 ;8-BIT OR BYTE MODE
CAIN T2,BYTMOD ;IS IT ?
POPJ P, ;YES, RETURN
TRNN S,14 ;IS MODE LESS THAN 10?
HRLI T1,700 ;YES,ASCII OR ASCII LINE
TRNE S,14 ;10 OR GREATER?
HRLI T1,4400 ;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 ;PIM ON MPX
CAIN T2,.TYTTY ;TEST
HRLI T1,1000 ;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
SUBTTL SUPPORT FOR THE DDB SCANNING INTERLOCK
IFN FTMP,<
;INTERLOCK DDB SCANNING
DDBLOK::CONI PI,.CPDBI## ;SAVE STATE OF INTERRUPT SYSTEM
CONO PI,DSKPIF## ;TURN OFF DISK PI CHANNEL
SKIPGE INTRDD## ;AVOID DMA OVERRUNS
AOSE INTRDD## ;BUSY
JRST .-2 ;SPIN
APRID INTODD## ;REMEMBER INTERLOCK OWNER
POPJ P, ;RETURN
;RELEASE INTERLOCK
DDBULK::SETOM INTRDD## ;RELEASE INTERLOCK
SETOM INTODD## ;RESET INTERLOCK OWNER
EXCH T1,.CPDBI## ;GET SAVED PI SYSTEM STATE
ANDI T1,177 ;ISOLATE CHANNELS
TRO T1,PI.TNP ;TURN ON SELECTED PIS
EXCH T1,.CPDBI## ;RESTORE T1
CONO PI,@.CPDBI## ;RESTORE PI SYSTEM STATE
POPJ P, ;RETURN
> ;END IFN FTMP
$CSUB
;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##
$HIGH
XLIST
$LIT
LIST
UUOEND::END