TITLE UUOCON - UUO HANDLER AND UUO+IO ROUTINES - V2063 SUBTTL /CHW/TL/RCC/CMF/PH/GDR/DAL/EVS/TW/JMF/DRT/JBS/RCB 26-JULY-88 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,2063 ;THIS MACRO PUTS VERSION NO. IN STORAGE MAP AND GLOB UUOCON::ENTRY UUOCON ;ALWAYS LOAD UUOCON(IF LIB SEARCH) IFNDEF MAXCAL, ;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, ;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,UDEVNM,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) < > ;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, > 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, ;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) > 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 ;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, ; 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 TOO (LEAVE ROOM FOR 22 BIT ADR) ; USEFUL IN CASE OF CRASH CAUSED BY POKE MOVE T1,[.SWEPK,,.ERSWE] ;EVENT,,ERROR CODES FOR DAEMON HRRZ U,P2 ;SECOND WORD OF ERPTBK HLRZ F,P2 ;IS ADDRESS POKED SKIPE [M.LPOK##] ;ONLY IF HE WANTS TO LOG POKES PUSHJ P,DAERPT## ;TELL DAEMON TO LOG IT SETZ F, ;NOT AN I/O UUO JRST CPOPJ1## ;SKIP RETURN POKE.1: SYSPIN ;TURN ON SYSTEM PJRST ECOD1## ;RETURN CODE 1 > IFE FTPOKE, ;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,(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 ;YES, ILLEGAL FUNCTION IF BREAK POINTS ARE INSERTED SETZ F, ;F=0, U=FUNCTION MOVE T1,[.SWESN,,.ERSWE] ;EVENT,, SOFTWARE EVENT REPORT PUSHJ P,DAERPT## ;GET IT RECORDED IN THE ERROR FILE PUSHJ P,SAVE4## ;SAVE WORKING ACS HRRZ P2,SYSBPP## ;NUMBER OF BREAK POINTS WHICH HAVE BEEN DEFINED HLRZ P3,SYSBPP## ;ADDRESS OF THE BREAK POINT TABLE MOVSI P4,(JRST) ;BREAK POINT INSTRUCTION IS A JRST TO THE BREAK POINT CODE SYSPIF ;LOCK SYSTEM SNPIB1: MOVS P1,(P3) ;ADDRESS OF THE BREAK POINT MOVE T1,(P1) ;MONITOR INSTRUCTION MOVSS P1 ;ADDRESS OF THE BREAK POINT CODE HRRI P4,(P1) ;JRST TO THE BREAK POINT CODE MOVEM T1,SNPRMI(P1) ;STORE MONITOR INSTRUCTION IN BREAK POINT CODE HLRZS P1 ;VIRTUAL ADDRESS OF THE BREAK POINT PUSHJ P,POKADR ;MAKE IT WRITABLE MOVEM P4,(P1) ;STORE JRST TO BREAK POINT CODE AT THE BREAK POINT AOS P3 ;NEXT ENTRY IN THE BREAK POINT TABLE SOJG P2,SNPIB1 ;INSERT ALL OF THE BREAK POINTS SYSPIN ;NOW, UNLOCK THE SYSTEM JRST CPOPJ1## ;AND GIVE THE USER THE GOOD RETURN ;HERE TO REMOVE BREAK POINTS (FUNCTION 2) SNPRBP: CAME J,SYSBPJ## ;THIS JOB OWN THE BREAK POINT FACILITY JRST SNPSAS ;NO, SOMEONE ELSE IS SNOOPING 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 CODE RETURNED IN AC ; ; ;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 ; ;NO SUCH DEVICE ; ;ILLEGAL UNIT ON DEVICE ; ;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 ; ;NO SUCH DEVICE ; ;ILLEGAL UNIT ON DEVICE ; ;W = KDB, U = UDB DIAKDU: 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,CPOPJ## ;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 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, IFN FTKL10,< DIACLR::SE1ENT ;ENTER SECTION ONE IFN FTSCA, ;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, ;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&,< 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& ;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,- ;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,- ;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,- ;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 (,ASU,DIADSP) ;ASSIGN UNIT DIAGDS (,AAU,DIADSP) ;ASSIGN ALL UNITS DIAGDS (,RAU,DIADSP) ;RELEASE CHANNEL/KON ALL UNITS DIAGDS (,SCP,DIADSP) ;SPECIFY CHANNEL PROG DIAGDS (,RCP,DIADSP) ;RELEASE CHANNEL PROG DIAGDS (,GCS,DIADSP) ;GET CHANNEL STATUS DIAGDS (,AKU,DIAKUN) ;GET KONTROLLER AND UNIT #S >; END IFN FTKL10 DIAGDS (,ACS,DIAXSB) ;READ CSB DIAGDS (,ADS,DIAXSB) ;READ DSB IFN FTKL10,< DIAGDS (,SCR,DIADSP) ;CHANNEL PGM FOR READ REVERSE >; END IFN FTKL10 DIAGDS (,GUI,CPOPJ1##) ;GET USER I/O IFN FTKL10,< DIAGDS (,ELD,DIADSP) ;ENABLE MICROCODE LOADING DIAGDS (,DLD,DIADSP) ;DISABLE MICROCODE LOADING DIAGDS (,LOD,DIADSP) ;LOAD MICROCODE DIAGDS (,ISM,DIADSP) ;SET IPA CHANNEL MAINT MODE DIAGDS (,ICM,DIADSP) ;CLEAR IPA CHANNEL MAINT MODE DIAGDS (,SBD,DIASBD) ;EXECUTE SBUS DIAG FUNCTION DIAGDS (,DSN,DIADSN) ;READ DEVICE SERIAL NUMBER >; END IFN FTKL10 IFN FTKS10,< DIAGDS (,RUR,DIARUR) ;READ UNIBUS REGISTER >; END IFN FTKS10 IFN FTKL10&,< DIAGDS (,ADB,DIAADB) ;ALLOCATE IPA20 DUMP BUFFER >; END IFN FTKL10& DIAGDS (,OKI,DIAKIN) ;OBTAIN KONTROLLER INFO DIAGDS (,OUI,DIAUIN) ;OBTAIN UNIT INFO DIAGDS (,LKU,DIALKU) ;LIST KONTROLLER'S UNITS DIAGDS (,SDS,DIADSP) ;SET DEVICE STATUS DIAGDS (,DVR,DIAREG) ;READ DEVICE REGISTERS IFN FTKL10,< DIAGDS (,GTM,MOSGTM##) ;GET MEMORY DIAGDS (,GVM,MOSGVM##) ;GIVE MEMORY IFN FTSCA,< DIAGDS (,RRS,DIARRS##) ;RESET REMOTE SYSTEM DIAGDS (,SRS,DIASRS##) ;START REMOTE SYSTEM DIAGDS (,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, ;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, ;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 ; ;TIMESHARING ALREADY STOPPED ; ;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 ;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, ; ; ; ... ;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 ; ; ;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, ;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- ;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, CAMN T1,[SIXBIT /NUL/] ;NUL DEVICE? 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 ;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, ;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, ;NO DTE SUPPORT C11KDX: IFN FTKL10, ;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, ;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, ;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), NETFNL: NETFNS ;TABLE OF ARG LIST LENGTHS NETFMX==.-NETFNL-1 ;MAXIMUM NET. FUNCTION CODE DEFINE NETFUN(LENGTH,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,^- 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 ;DOES HE WANT NODE NAME? JRST NTDIS1 ;NO IFE FTNET, ;NULL NODE NAME IF NO NETWORKS IFN FTNET, ;GET OUR NODE NAME PUSHJ P,PU6STB ;PUT SIXBIT INTO STRING BLOCK JRST NOPADC ;CAN'T NTDIS1: EXCTUX ;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, ;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 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 ;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,< >> TYPTAB: TYPES TYPES TYPES REPEAT .TYRX2-<.-TYPTAB>,< EXP 0> TYPES 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, ;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 ;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 ;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,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 SUB T2,BATMIN## ;HOW MANY JOB SLOTS RESERVED FOR BATCH 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 ,,< IFE FT,< JOBMXL##+B29,,NULGTB> IFN FT,< JOBMXL##+B29+J,,TBL> > IFIDN ,,< IFE FT,< JBTMXL##+B29,,NULGTB> IFN FT,< JBTMXL##+B29+J,,TBL> > IFIDN ,

,< IFE FT,< JOBMXL##+B29,,NULGTB> IFN FT,< JOBMXL##+B29+W,,TBL> > IFIDN ,,< IFE FT,< NULGTB> IFN FT,< MAX+B29+J,,TBL> > IFIDN ,,< IFE FT,< NULGTB> IFN FT,< EXP B8+B11+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:: FIRST,,LAST > IFB ,< FIRST,,LAST > >> RNGTAB: 0 ;ENTRY 0 NOT USED RANGE 1,,,NUM RANGE 1,CTTWDT##-TTTWDT##,TTTWDN##+CTTWDT##-TTTWDT##-1,TTT RANGE 1,<.GTCSD##-.GTSID##>,SDTBLN##,SID RANGE 1,,,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,<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,<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##,<B26> ;(210) KDB CHAIN HEADERS GT 1,I,DDBTAB##,<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, 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 ;(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 ;(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 ;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 TDNN T2,JBTSTS##(J) ;SKIP IF JOB NOT LOGGED IN JRST CHGPP1 ;NOT-LOGGED-IN IS GOLDEN MOVE T2,T1 ;COPY NEW PPN TO A SAFER PLACE MOVE T1,[!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. UDEVNM: PUSHJ P,DVCNSG ;SEARCH FOR CHANNEL OR DEVICE JRST RTZER ;NONE--RETURN ERROR AS 0 TLZ F,-1 CAIE F,DSKDDB## ;T1 IS MORE SPECIFIC THAN 'DSK' MOVE T1,DEVNAM(F) ;GET PHYSICAL NAME JRST STOTC1## ;PUT IN AC AND RETURN SUBTTL REAL-TIME AND HIBWAKE FEATURE ;UUO TO SET JOB TO USE IO IN USER MODE ;AND TO SET PI INTERRUPT LOCATION IN LOWER CORE(WORKS ONLY ON P-10'S -SEE NEXT PAGE) ;CALL: CALL AC,[SIXBIT /TRPSET/] ; ERROR RETURN, USER NOT ALLOWED TO DO IO IN USER MODE ; OK RETURN ;WHERE RH(AC)=REL ADR. OF 1 INSTRUCTION TO BE MOVED INTO ;THE MONITOR PI TRAP LOCATION(40-57) AS SPECIFIED BY LH(AC) ;RELOCATION OF JOB IS ADDED TO RH OF INSTRUCTION AS IT IS MOVED. ;ALSO THE RELOCATION IS ADDED TO THE RH OF WORD IN USER AREA SPECIFIED BY ;RH OF USER INSTRUCTION IN CASE IT IS A BLKO/BLKI POINTER ;THE USER MUST RESET EVERY TRPSET CALL IF BLKI/BLKO POINTER ;AND SHOULD SET RH TO 0 IF JSR PC WORD ;THE APR IS ALSO SET SO USER MAY DO IO IN USER MODE ;TO SET USER MODE IO WITHOUT SETTING LOWER CORE, C(AC)=0 ;STOP TIME SHARING ONLY IF AC IS NON-ZERO(IE RUN ONLY JOB 1) TRPSET: TDZA T3,T3 ;FORCE CALL TO DAERPT TRPSTU: SETOM T3 ;DON'T CALL DAERPT (DIAG. UUO) MOVE T2,JBTPRV##(J) ;IS JOB PRIVILEGED TO DO TRPSET UUO? 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 HRRZ U,T1 ;SECOND WORD OF ERPTBK IS CONTENTS HLRZ F,T1 ; OF AC AT TRPSET CALL MOVE T1,[.SWETP,,.ERSWE] ;EVENT,,ERROR CODES FOR DAEMON PUSHJ P,DAEDSJ## ;TELL DAEMON TO LOG IT 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, ;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,(B2+PM.PUB) ;MAP THE UPT 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,(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,(B2) ;SWAPPED? JRST JPKEVS ;YES HRLI T1,(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 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 T1 ;IS IT SECTION 0? SKIPA T1,.JBPK+.UMUPM ;YES, USE .UPMAP MOVE T1,.JBPK+SECTAB(T1) ;ELSE GET SECTION POINTER TLNE T1,(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,(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 T1,P2 ;SECTION RELATIVE ADDRESS IN HIS AREA LSH T1,W2PLSH ;PAGE # SKIPN T1,.JBPK(T1) ;DOES PAGE EXIST IN HIS MAP? JRST JKXIAD ;NON-EXISTENT CAMN T1,[PM.ZER] ;ABZ PAGE? JRST JKXABZ ;YES TLNE T1,(PM.COR) ;IN CORE? JRST JPKLW7 ;YES 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,(<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,(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,(B2!PM.WRT) MOVEM T2,.UPMP+.UMJBK ;POINT .JBPK AT IT CLRPT .JBPK SOS T1 HRLI T1,-PAGSIZ MOVEM T1,DEVDMP##(F) AOS -<4+>>(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 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 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 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 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 ;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 ;PICK UP PNTR TO NEXT BUF EXCTUU ;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 ;RESTORE BUFFER RING EXCTUX ;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, ;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, ;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 ;FIRST WORD OF 3 WORD BUFFER HEADER EXCTUX ;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 ;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 ;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 ;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 ;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 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 EXCTXU ;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 ;LIST NOT RING > UOBF1: HRRZ T1,T2 ;CHECK ADR OF BUF HEADER PUSHJ P,UADRCK EXCTXU ;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 HRRM 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 ; CLEAR FIRST WORD (CURRENT BUFFER) OF 3 WORD HEADER PUSH P,T2 EXCTXU ;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 ;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:!JRST WCHFI2 ;PATCH TO JFCL TO ENABLE THIS NIFTY FEATURE MOVEI T1,[ASCIZ / exec/] ;GET BLURB MOVSI T2,(XC.USR) ;SEE IF EXEC MODE UUO TDNN T2,.USMUO ;IDENTIFY EXEC MODE PUSHJ P,CONMES## TDNN T2,.USMUO ;EXEC MODE PC COMES FROM .USMUP SKIPA T2,.USMUP MOVE T2,JOBPDO+1 ;USER PC COMES FROM UUO WHICH STARTED THIS 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 ;AND THEN MAKE IT AVAILABLE SETNEW: EXCTUU ;POINT HEADER TO NEW RING HRR T2,M ;AND RESET PTR TO CURRENT BUFFER HRLZI T1,IOUSE ;BUFFER IN USE BIT EXCTUU ;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 ;IT 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 ;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 ;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 JRST INPT1A IN1A: EXCTUX ;MAKE SURE A FAULT WONT HAPPEN PUSHJ P,FLTST## ; BEFORE WE ADVANCE THE BUFFER HEADER JRST UUOFLT## ;OOPS - GET THE PAGE IN CORE EXCTUX MOVSI T2,1 ;WRD 1 MUST BE IN CORE HLRZS T2 ADDI T2,(T1) PUSHJ P,LRNGE## EXCTUX 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 ;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 PUSHJ P,OUCHE## ;GET IT BACK TO MEMORY > MOVSI T3,IOUSE EXCTUU ;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 ;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 ;GET LOC OF NEXT BUFFER PUSHJ P,UADRCK ;MAKE SURE ITS OK SOJLE T3,INPT0B ;LAST BUFFER TO CHECK IF T3 = 0 EXCTUX ;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 ANDI T3,IOSIZ ;YES, IS THE WHOLE BUFFER IN CORE? ADDI T1,(T3) PUSHJ P,FLTST## INPT0D: EXCTUX ;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 ;IS THE USE BIT SET? INPT0G: PUSHJ P,CALIN ;NO, START SERVICE ROUTINE FILLING EMPTY BUFFER INPT0C: EXCTUX ;GET USE BIT FOR NEXT BUFFER INPT0A: EXCTUX ;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 ;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 ;PICK UP THE UDX MOVE T1,U ;ADDRESS OF RING HEADER EXCTUU ;STORE FOR USER TO SEE INPT2A: > EXCTUX ;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 ;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 ;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 & INPUT INPUTF: JUMPE T1,INPTF1 ;IF A BUFFER ADR IS SPECIFIED, PUSHJ P,BRNGE## ;MAKE SURE WHOLE BUFFER IS IN CORE EXCTUX ;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 ;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 ;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 PROTOCAL? POPJ P, ;NO MOVE T1,DEVNBF(F) ;YES EXCH T1,DEVSBF(F) ;SAVE CURRENT DEVNBF, RESTORE SAVED VALUE MOVEM T1,DEVNBF(F) ; (SWITCHING FROM INPUT TO OUTPUT OR VICE VERSA) POPJ P, >> CALIN:: MOVSI S,IOSTBL ;RESET ERROR FLAG IFN 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 ;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 ; 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 ;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 ;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 ;GET RH OF BYTE POINTER. EXCTUX ;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 ;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 ;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 ;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 ;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 ;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 ;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 EXCTUU ;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 ;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 ; AFTER AN OFF-LINE INTERCEPT EXCTUX ;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 ;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 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 ;VIRGIN RING BIT:=0 HRRM T1,DEVOAD(F) OUTS: PUSHJ P,OUTFCL ;MAYBE CLEAR THE BUFFER JRST ADRERR## ;ADDRESS CHECK EXCTUX EXCTUX 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 ;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 ;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 ;SAVE IN RING HEADER HRRM M,DEVOAD(F) ;SAVE AS NEXT BUF TO WRITE HRLZI T1,IOUSE EXCTUU ;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, ;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 ;CURRENT USER BUFFER MOVEI T1,-1(T2) ;DEVIOS WORD PUSHJ P,LRNGE## ;LEGAL? EXCTUX ;IF THE BUFFER ISN'T EMPTY, EXCTUX ;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 EXCTUU ;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 ;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 EXCTUU ;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 ;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 ;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 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 ;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 ;

B27+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,(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 ;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 HRRZ P2,T1 ;THIS IS IOWD OR GO TO NOT POINTING TO AC HLRO P3,T1 ;SAVE ADDRESS POINTED TO AND NEGATIVE COUNT CAMG P2,T3 ;IS START ABOVE PROTECTED AREA? JRST NXBAD ;NO. REPORT ERROR MOVMS P3 ;WORD COUNT ADD P2,P3 ;END OF IO SKIPGE USRHCU## ;IF SAVE N IN PROGRESS, TLZ P2,-1 ; SUPPRESS CARRY IF ADR=-1 EXCH P2,T1 ;SAVE T1 SKIPL DEVISN(F) ;DON'T CLEAR SECTION NUMBER IF MULTI-SECTION I/O HRRZS T1 ;TOP OF USER'S AREA 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 ;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, ; PUSHJ P,KONUSN ; ERROR RETURN ; NORMAL RETURN ; ;WHERE 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, 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 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 ; ;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 P1 WAS SIXBIT /LPT/ ; IF M7/M9 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 ;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, ;T4 = ADDRESS OF LAST BUFFER EXCTXU ;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, ;SAVE PCS AND SET IT TO ZERO MOVE T1,P1 ;RESTORE T1 EXCTUX ;SAVE USER ACS FOR UUO ARGUMENTS EXCTUX EXCTUX 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 ;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 ;
B27+B35 TLO T2,(PG.IDC) ;DON'T CARE IF PAGES ALEREADY EXIST EXCTXU ;STORE STARTING SECTION/PAGE NUMBER ALCOR1: MOVE T1,[.PAGCD,,P2] ;CREATE A PAGE EXCTXU ;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 ;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 ;MODIFY ORIGINAL REQUEST MOVE T1,[.PAGCD,,P2] ;PAGE. UUO ARGUMENT POINTER EXCTXU ;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 ;RESTORE USER ACS EXCTXU EXCTXU 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 ;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 ;CLEAR THE THIRD WORD HRLI T2,1(T2) ADDI T2,2 EXCTUU ;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 EXCTUU EXCTUU 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 ;T2:=BYTE SIZE PUSHJ P,ITMCT1 ;JBFCTR:=C(J)*[36/BYTE SIZE] IOSET1: ADDI U,1 EXCTXU POPJ P, ;EXIT ;HERE IF BYTE MODE I/O, STORE BYTE COUNT COMPUTED BY THE SERVICE ROUTINE IOSET2: EXCTUX ;POINTER TO THE CURRENT BUFFER EXCTUX ;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