1
0
mirror of https://github.com/PDP-10/stacken.git synced 2026-03-01 01:19:17 +00:00
Files
Lars Brinkhoff 6e18f5ebef Extract files from tape images.
Some tapes could not be extracted.
2021-01-29 10:47:33 +01:00

3450 lines
112 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
TITLE IPCSER -- INTER PROCESS COMMUNICATION FACILITY V366
SUBTTL J. SAUTER/T. WACHS/LSS/CDO/JMF/DPM 23-AUGUST-88
SEARCH F,S,DEVPRM
$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 VIPCSR,366 ;VERSION NUMBER FOR GLOB AND MAP
ENTRY IPCSER ;LOAD THIS MODULE IF REQUESTED
IPCSER::
;IPCSER PROVIDES A FACILITY WHICH PERMITS TWO JOBS TO EFFICIENTLY
; EXCHANGE LIMITED AMOUNTS OF DATA. THE MONITOR MAY ALSO PARTICIPATE
; IN THIS EXCHANGE BY MEANS OF "EXEC PSEUDO-PROCESSES".
;DATA STRUCTURES:
XX=. ;REMEMBER LOCATION
;EXECUTIVE PROCESS CONTROL BLOCK
PHASE 0
;NOTE THAT .EPIPC,.EPIPA, .EPIPQ MUST REMAIN IN THIS ORDER
; (SAME ORDER AS .PDIPC, .PDIPA, .PDIPQ, .PDIPL, .PDPID, .PDIPI, .PDIPN)
.EPIPC:! BLOCK 1 ;LH=POINTER TO OLDEST PACKET
;18-26 = PACKETS SENT & NOT RECEIVED
;27-35 = PACKETS WAITING TO BE REC.
.EPIPA:! BLOCK 1 ;LH = COUNT OF SENDS SINCE LOGIN
;RH = COUNT OF RECEIVES SINCE LOGIN
.EPIPQ:! BLOCK 1 ;FLAGS AND QUOTAS
IP.DSB==(1B0) ;RECEIVER IS DISABLED
IP.HBS==(1B1) ;QUOTAS HAVE BEEN SET
IP.DPR==(1B2) ;AT LEAST 1 PID FOR JOB IS TO BE DROPPED ON RESET
IP.DPL==(1B3) ;AT LEAST 1 PID TO BE DROPPED ON LOGOUT
IP.LOK==(1B4) ;QUEUE IS INTERLOCKED
;9-17 = PID QUOTA
;18-26 = SEND QUOTA
;27-35 = RECEIVE QUOTA
IP.SBT==1000 ;1ST BIT IN SEND QUOTA/COUNT BYTE
IP.CTX==:IP.HBS+IP.DPL+777 ;FLAGS TO PRESERVE ON CONTEXT CHANGES (SEE CTXSER)
.EPIPL:! BLOCK 1 ;IPCF QUEUE INTERLOCK WORD
;LH = JCH WHOSE QUEUE IS INTERLOCKED
;RH = JCH WHO INTERLOCKED OUR QUEUE
.EPPID:! BLOCK 1 ;PID FOR PID SPECIFIC RECEIVES
.EPIPI:! BLOCK 1 ;PID OF THIS JOB'S SYS:INFO
.EPIPN:! BLOCK 1 ;LH=POINTER TO LAST IN QUEUE
.EPQSN:! BLOCK 1 ;SEQUENCE NUMBERS
.EPEPA:! BLOCK 1 ;EXEC PSEUDO-PROCESS PACKET ADDRESS
.EPADR:!BLOCK 1 ;PUSHJ @ HERE WHEN A PACKET ARRIVES
; FOR THIS PROCESS.
DEPHASE
;DEFINITION OF PACKET DESCRIPTOR BLOCK
PHASE 0
.IPCFL::!BLOCK 1 ;LINK AND FLAGS
IP.CFB==(1B0) ;UUO BLOCK: DONT BLOCK READ UUO
IP.IAS==(1B1) ;UUO BLOCK: INDIRECT ADDRESS FOR SENDER'S PID
IP.IAR==(1B2) ;UUO BLOCK: INDIRECT ADDRESS FOR RECEIVER'S PID
;IN PACKET, LH = POINTER TO NEXT
IP.LPC==(1B3) ;UUO BLOCK: "LAST PHONE CALL" - SEND EVEN THO QUOTA
; IS OVERDRAWN (ONLY ALLOWS OVERDRAW OF 1)
IP.TTL==(1B4) ;UUO BLOCK-TRUNCATE PACKET IF TOO LONG
IP.LPK==(1B5) ;PACKET IS LONGER THAN MAX SYSTEM SIZE (PRIVID)
IP.RFP==(1B6) ;RECEIVE FOR A PARTICULAR PID
IP.SIP==1B18 ;SENDER IS PRIVILEGED
IP.CFV==1B19 ;VM PAGE MODE
IP.CFZ==1B20 ;DATA LENGTH=0
IP.AKR==1B21 ;SENDER REQUESTS ACKNOWLEGEMENT FROM RECEIVER
IP.CFE==77B29 ;(UNPRIV) ERROR RETURN
IP.CFM==77B35 ;SPECIAL MESSAGE FIELD
.IPCMN==1 ;MESSAGE 1: MESSAGE WAS UNDELIVERABLE
.IPCFS::!BLOCK 1 ;SENDER'S PID
.IPCFR::!BLOCK 1 ;RECEIVER'S PID
.IPCFP::! ;LH = LENGTH OF PACKET'S DATA
;IN UUO BLOCK, RH=USER'S PACKET BUFFER
.IPCFI::!BLOCK 1 ;IN PACKET, THE FOLLOWING FIELDS APPLY:
IP.DSK==:1B0 ;DISK ADDRESS
IP.FRE==1B1 ;**FREE**
IP.LEN==1777B12 ;LENGTH OF DATA (PACKET ONLY!)
IP.SLN==:^D10 ;SIZE OF LENGTH FIELD
IP.PLN==:^D12 ;POSITION
IP.OIQ==PM.OIQ
IP.SSP==PM.SSP
IP.ADR==PM.ADR ;ADDRESS
IP.NAD==PM.NAD ;NOT ADDRESS
IP.SAD==PM.SAD ;SIZE OF ADDRESS FIELD
.IPCFM::!BLOCK 0 ;MINIMUM LENGTH OF DESCRIPTOR BLOCK
.IPCFU::!BLOCK 1 ;SENDER'S PPN. FILLED IN BY MONITOR ON SEND
;UUO NEVER FILLED IN BY USER.
.IPCFC::!BLOCK 1 ;SENDER'S CAPABILITIES WORD. FILLED IN SAME
;FASHION AS .IPCFU.
IP.JAC==(1B0) ;SENDER HAS JACCT ON
IP.JLG==(1B1) ;SENDER IS LOGGED-IN
IP.SXO==(1B2) ;SENDER IS EXECUTE-ONLY
IP.POK==(1B3) ;SENDER CAN POKE THE MONITOR
IP.IPC==(1B4) ;SEND HAS IPCF PRIVS
;BITS 18:26 = CTX # OF SENDER
;BITS 27:35 = JOB # OF SENDER
.IPCFD::!BLOCK 0 ;IN PACKET ONLY, START OF DATA.
DEPHASE
RELOC XX ;DONT WASTE ANY SPACE
; IPCFM. DEFINITIONS
;FLAGS WORD
IP.CMP==(1B0) ;PRIVILEGED PACKET
IP.CMI==(1B1) ;INIDIRECT SENDER ADDRESS
IP.CMD==(7B17) ;DESTINATION SPECIAL PROCESS NUMBER (1=IPCC,2=INFO,3=LOCAL-INFO)
IP.CML==0,,-1 ;LENGTH OF BLOCK
IP.CMX==<(-1B17)>-<IP.CMD!IP.CMI!IP.CMP> ;RESERVED (FREE) BITS
; COMMONLY-USED BYTE POINTERS
TRNPTR: POINT 9,.IPCFC(P1),35
TRNPT2: POINT 9,.IPCFC(P2),35
PKLNP2: POINT IP.SLN,.IPCFI(P2),IP.PLN
PKLNP1: POINT IP.SLN,.IPCFI(P1),IP.PLN
PKLNT1: POINT IP.SLN,.IPCFI(T1),IP.PLN
PKLNT2::POINT IP.SLN,.IPCFI(T2),IP.PLN
PKADT1: POINT IP.SAD,.IPCFI(T1),^L<IP.ADR>+IP.SAD-1
PKADP1: POINT IP.SAD,.IPCFI(P1),^L<IP.ADR>+IP.SAD-1
PQTAPT: POINT 9,.EPIPQ(W),17
RCCNT: POINT 9,.EPIPC(W),35
RCQTA: POINT 9,.EPIPQ(W),35
RTNERR: POINT 6,.IPCFL(P1),29
RTNER2: POINT 6,.IPCFL(P2),29
DESTP4: POINT 3,P4,17 ;DESTINATION CODE IN IPCFM PROCESSING
; SPOOLED PARAMETER BLOCK DEFINITIONS
SPBPCP==0 ;NUMBER OF COPIES
SPBPFM==1 ;FORMS NAME
SPBPLM==2 ;LIMIT
SPBPSF==3 ;SPOOLING FLAGS
SPBPDA==4 ;DEVICE ATTRIBUTES
SPBPND==5 ;NODE
SPBPAF==6 ;AFTER PARAMETER
SPBNM1==7 ;SIXBIT USER NAME (WORD 1)
SPBNM2==10 ;SIXBIT USER NAME (WORD 2)
SPBACT==:11 ;START OF ACCOUNT STRING
MAXACS==:^D8 ;MAXIMUM LENGTH OF ACCOUNT STRING
;MUST MATCH ONE IN COMMON
SPBMAX==:SPBACT+MAXACS ;TOTAL LENGTH OF SPB
;DESCRIPTION OF SPOOL, LOGIN AND LOGOUT MESSAGES
; ALL MESSAGES FROM IPCC TO QUASAR HAVE A TWO WORD HEADER AS
; DESCRIBED BELOW. THE LOGOUT MESSAGE CONSISTS SOLELY OF THESE
; TWO WORDS, AND THE SPOOL MESSAGE HAS FILE INFORMATION APPENDED,
; THE LOGIN MESSAGE HAS JOB INFORMATION APPENDED.
XX=. ;REMEMBER LOCATION
PHASE 0 ;START AT 0
GALMSG:!BLOCK 1 ;MESSAGE HEADER
; XWD LENGTH,,FUNCTION
GALSTS:!BLOCK 1 ;STATUS WORD
GALBSN==177B8 ;BATCH STREAM NUMBER (IF GALBAT)
GALJOB==777B17 ;BITS 0-17 IS JOB NUMBER
GALLOC==777000 ; 18-26 IS LOCATION
GALFLG==777 ; 27-35 ARE FLAGS
GALBAT==1B27 ;BATCH JOB
GALDFR==1B28 ;DEFERRED SPOOLING
GALBSS==1B29 ;BATCH STREAM NUMBER SET
LGMSIZ==.-GALMSG ;SIZE OF LOGOUT MESSAGE
SCMSIZ==.-GALMSG ;SIZE OF SCHEDULE BITS CHANGE MESSAGE
SPMUSR:!BLOCK 2 ;USER NAME IN 6BIT
SPMIDV:!BLOCK 1 ;INITED DEVICE
SPMSTR:!BLOCK 1 ;STRUCTURE NAME
SPMFIL:!BLOCK 1 ;FILENAME
SPMEFN:!BLOCK 1 ;ENTER'ED FILE NAME (RIBSPL, DEVSPN)
SPMFSZ:!BLOCK 1 ;FILE SIZE IN BLOCKS
SPMEXT:!BLOCK 1 ;SPOOLED FILE EXTENSION
SPMPRM:!BLOCK SPBMAX ;SPACE FOR SPOOLING OPTION BLOCK
SPMSIZ==.-GALMSG ;SIZE OF SPOOL MESSAGE
PHASE GALSTS+1
LOMUSR:!BLOCK 2 ;USER NAME IN 6BIT
LOMCTL:!BLOCK 1 ;CONTROLLERS JOB NUMBER
LOMTTY:!BLOCK 1 ;TTY
LOMSIZ==.-GALMSG
DEPHASE
RELOC XX ;RECLAIM SPACE
;ERROR CODES:
IPCAC%==1 ;ADDRESS CHECK (UUO BLOCK OR PACKET BUFFER)
IPCNL%==2 ;NOT LONG ENOUGH (UUO BLOCK)
IPCNP%==3 ;NO PACKET IN LIST (READ UNBLOCKED)
IPCIU%==4 ;(PAGE) IN USE (PART OF VIRTUAL FEATURE)(PAGE IS LOCKED)
IPCTL%==5 ;(PACKET) TOO LONG (FOR USER'S BUFFER)
IPCDU%==6 ;DESTINATION UNKNOWN (SEND)
IPCDD%==7 ;DESTINATION DISABLED (SEND)
IPCRS%==10 ;(NO) ROOM (IN) SENDER'S (QUOTA)
IPCRR%==11 ;(NO) ROOM (IN) RECEIVER'S (QUOTA)
IPCRY%==12 ;(NO) ROOM (IN) SYSTEM (STORAGE)
IPCUP%==:13 ;UNKNOWN PAGE (SEND) EXISTING PAGE (REC)
IPCIS%==14 ;INVALID SEND ADDRESS
IPCPI%==15 ;PRIVILEGES INSUFFICIENT
IPCUF%==16 ;UNKNOWN FUNCTION
IPCBJ%==17 ;BAD JOB NUMBER
IPCPF%==20 ;PIDTAB FULL
IPCPR%==21 ;PAGED PACKET REQUESTED, REGULAR PACKET IN QUEUE OR VICE VERSA(VM)
IPCIE%==:22 ;PAGING IO ERROR (VM)
IPCBI%==23 ;BAD INDEX SPECIFIED FOR SYSTEM PID TABLE
IPCUI%==24 ;UNDEFINED ID IN SYSTEM PID TABLE
IPCRU%==25 ;RECEIVER UNKNOWN
IPCRP%==:26 ;NO PHYSICAL ROOM (FOR A MAP, EG.)
IPCRV%==:27 ;NO VIRTUAL ROOM
IPCCF%==71 ;[SYSTEM]IPCC REQUEST BY [SYSTEM]INFO FAILED
IPCQP%==73 ;PID QUOTA EXCEEDED
;SUBROUTINE TO VALIDATE ARGUMENTS AND FETCH THEM INTO P1-P4.
; SKIP RETURN ON OK, LEAVES ADDR OF ARG IN M.
VALARG: HLRZ T2,T1 ;GET USER'S AC LEFT HALF
CAIGE T2,.IPCFM ;LONG ENOUGH?
JRST ERRNL ;NO.
MOVE P4,T1 ;YES, COPY USER'S AC
HRRI M,.IPCFL(P4) ;FIRST LOCATION OF BLOCK
PUSHJ P,GETWRD## ;FETCH .IPCFL
JRST ERRAC ;ADDRESS CHECK
MOVE P1,T1 ;PUT .IPCFL IN P1
PUSHJ P,GETWR1## ;FETCH SENDER'S PID
JRST ERRAC ;ADDRESS CHECK
TLNN P1,IP.IAS ;IS SENDER'S PID INDIRECTED?
JRST VALAR1 ;NO.
HRR M,T1 ;YES, GET ADDRESS
TLNN T1,-1 ;LH = 0?
PUSHJ P,GETWRD## ;YES, FETCH THAT WORD.
JRST ERRAC ;ADDRESS CHECK
VALAR1: PUSHJ P,CTXJCH## ;CONVERT POSSIBLE JOB # TO JOB/CONTEXT HANDLE
JFCL ;MUST HAVE BEEN A PID
MOVE P2,T1 ;PUT .IPCFS IN P2
HRRI M,.IPCFR(P4) ;THIRD LOCATION OF BLOCK
PUSHJ P,GETWRD## ;FETCH RECEIVER'S PID
JRST ERRAC ;ADDRESS CHECK
TLNN P1,IP.IAR ;IS RECEIVER'S PID INDIRECTED?
JRST VALAR2 ;NO.
HRR M,T1 ;YES, PUT ADDRESS IN M
TLNN T1,-1 ;IS LH = 0?
PUSHJ P,GETWRD## ;YES, GET THE WORD.
JRST ERRAC ;ADDRESS CHECK
VALAR2: PUSHJ P,CTXJCH## ;CONVERT POSSIBLE JOB # TO JOB/CONTEXT HANDLE
JFCL ;MUST HAVE BEEN A PID
MOVE P3,T1 ;GET RECEIVER PID
CAMN P3,%IPCFP## ;PUBLIC VALUE FOR [SYSTEM]IPCF?
MOVE P3,PIDTAB## ;YES, CONVERT TO ACTUAL VALUE
HRRI M,.IPCFP(P4) ;FOURTH LOCATION OF BLOCK
PUSHJ P,GETWRD## ;FETCH PACKET DESCRIPTOR
JRST ERRAC ;ADDRESS CHECK
HRRI M,.IPCFL(P4) ;POINT BACK TO FRONT OF BLOCK
MOVE P4,T1 ;PUT .IPCFP IN P4
TRNN P1,IP.CFV ;ASKING FOR A PAGE?
JRST VALAR3 ;NO
HLRZ T1,P4 ;YES, EXACTLY 1 PAGE?
TLNE P1,IP.TTL ;TRUNCATE IF TOO LONG?
JUMPE T1,VALAR3 ;YES, LENGTH =0 IS OK
CAIE T1,PAGSIZ
JRST ERRTL ;CANT DO MORE THAN 1 PAGE AT A TIME
HRRZS P4 ;OK, SET LENGTH OF DATA TO 0 (NO DATA WDS IN PACKET)
MOVE T3,J ;COPY JOB/CONTEXT HANDLE
ANDI T3,JOBMSK## ;KEEP ONLY THE JOB NUMBER
MOVSI T1,LOKSEG ;LOCKED BITS
TDNN T1,JBTSTS##(T3) ;LOW SEG LOCKED
TDNE T1,JBTSGN##(T3) ;OR HIGH SEG LOCKED
PJRST ERRIU ;YES, GIVE ERROR
HRLI P4,-1
HRRZI T1,(P4) ;GET PAGE #
PUSHJ P,LGLPG## ;LEGAL?
PJRST ERRAC ;NO, ADDRESS CHECK.
JRST VALAR4
VALAR3: HRRZ T1,P4 ;START ADR
PUSHJ P,CHKADR ;CHECK IT
PJRST ERRAC
HLRE T2,P4
JUMPLE T2,[JUMPE T2,VALAR4 ;OK IF NO DATA WORDS
JRST ERRNL]
ADDI T1,-1(T2) ;TOP ADR
PUSHJ P,CHKADR ;CHECK
PJRST ERRAC
VALAR4: MOVE J,.CPJOB## ;GET OUR JOB NUMBER
MOVSI T1,JP.IPC ;NO PRIV BIT DEFINED
TRNN P1,-1-IP.CFE-IP.CFV-IP.AKR ;PRIV'D FUNCTION?
TRNA ;NO, DON'T NEED TO CHECK
PUSHJ P,PRVBIT## ;YES, GOT PRIVS?
AOSA (P) ;EVERYTHING OK
JRST ERRPI ;NO PRIVS FOR PRIV'D FUNCTION
MOVE T1,J ;GET OUR JOB NUMBER
PUSHJ P,CTXIPC## ;AND OUR IPCF DATA BLOCK ADDRESS
STOPCD .,STOP,NIJ, ;++ NO IPCF DATA BASE FOR JOB/CONTEXT
POPJ P, ;RETURN
;SUBROUTINE TO ADDRESS CHECK
CHKADR: PUSH P,T1
PUSH P,M ;SAVE M
HRR M,T1
PUSHJ P,GETWRD##
SOS -2(P)
POP P,M
PJRST TPOPJ1##
;SUBROUTINE TO LOAD J AND W BASED ON PID IN T1.
;RETURNS CPOPJ ON ERROR, ERROR CODE IN T1
;RETURNS CPOPJ1 IF OK
VALPID: JUMPE T1,VALPD4 ;ZERO PID IS INVALID
TLNN T1,-1 ;REAL PID, JOB # OR JOB/CONTEXT HANDLE?
JUMPG T1,VALPD1 ;JOB NO OR JCH
MOVE T2,T1 ;COPY OF PID
AND T2,%IPCPM## ;MASK TO INDEX
CAMGE T2,%IPCMP## ;IN RANGE?
SKIPN T2,PIDTAB##(T2) ;YES, PICK UP ENTRY.
JRST VALPD4 ;NO ENTRY HERE
MOVE T3,T2 ;SAVE IT FOR LATER
XOR T2,T1 ;CLEAR BITS IN COMMON
TDZ T2,%IPCPM## ;CLEAR UNWANTED BITS
JUMPN T2,VALPD4 ;SEQ # ARE THE SAME IF 0
ANDI T3,JCHMSK## ;KEEP ONLY JOB/CONTEXT HANDLE
SKIPA J,T3 ;SET J
VALPD1: MOVE J,T1
JUMPE J,VALPD3 ;EXECUTIVE PROCESS
MOVE T1,J ;GET JOB/CONTEXT HANDLE
PUSHJ P,CTXIPC## ;POINT TO IPCF DATA BLOCK
JRST VALPD4 ;NONE - PID IS BAD
VALPD2: AOS (P) ;GIVE GOOD RETURN
PJRST SETIPQ ;SET/GET QUOTA WORD
VALPD3: HLRZ W,T1 ;GET EXEC PROCESS PID NUMBER
MOVE W,EXPROC##-1(W) ;GET CONTROL BLOCK ADDRESS
; HRLS W ;SAVE LOC OF EXEC CTL BLOCK
JRST VALPD2
;HERE ON ERROR
VALPD4: MOVEI T1,IPCIS% ;ERROR CODE
POPJ P,
;ERROR ROUTINES. THESE LOAD IPCXX% INTO T1 FOR EACH ERRXX.
; ERROR ROUTINES ARE CALLED VIA PUSHJ, BUT THEY NEVER RETURN.
;THE POSITION RELATIVE TO ERRAC DEFINES THE ERROR VALUE.
ERCODE ERRAC,IPCAC% ;(1) ADDRESS CHECK
ERCODE ERRNL,IPCNL% ;(2) NOT LONG ENOUGH
ERCODE ERRNP,IPCNP% ;(3) NO PACKET IN QUEUE
ERCODE ERRIU,IPCIU% ;(4) PAGE IN USE (VIRTUAL FEATURE)
ERCODE ERRTL,IPCTL% ;(5) PACKET TOO LONG
ERCODE ERRDU,IPCDU% ;(6) DESTINATION UNKNOWN
ERCODE ERRDD,IPCDD% ;(7) DESTINATION DISABLED
ERCODE ERRRS,IPCRS% ;(10) NO ROOM IN SENDER'S QUOTA
ERCODE ERRRR,IPCRR% ;(11) NO ROOM IN RECEIVER'S QUOTA
ERCODE ERRRY,IPCRY% ;(12) NO ROOM IN SYSTEM FOR PACKET
ERCODE ERRUP,IPCUP% ;(13) UNKNOWN PAGE (SEND) OR ALREADY EXISTING (REC)
ERCODE ERRIS,IPCIS% ;(14) INVALID SENDER'S ADDRESS
ERCODE ERRPI,IPCPI% ;(15) INSUFFICIENT PRIVILEGES
ERCODE ERRUF,IPCUF% ;(16) - UNKNOWN FUNCTION
ERCODE ERRBJ,IPCBJ% ;(17) - BAD JOB NUMBER
ERCODE ERRPF,IPCPF% ;(20) - PIDTAB FULL
ERCODE ERRPR,IPCPR% ;(21) - PAGE REQUESTED, NOT-A-PAGE IN QUEUE
ERCODE ERRIE,IPCIE% ;(22) - PAGING IO ERROR
ERCODE ERRBI,IPCBI% ;(23) - BAD INDEX FOR .GTSID
ERCODE ERRUI,IPCUI% ;(24) - UNDEFINED ID REQUESTED
ERCODE ERRRU,IPCRU% ;(25) - RECEIVER UNKNOWN OR DOES NOT BELONG TO JOB
SUBTTL IPCFR - RECEIVE UUO
UIPCFR::PUSHJ P,SAVE4## ;SAVE P1-P4
PUSH P,T1 ;SAVE USER ARG ON THE STACK
PUSHJ P,VALARG ;LOAD ARGS
JRST [POP P,(P) ;BRING STACK INTO PHASE
POPJ P,] ;AND RETURN
TLNN P1,IP.RFP ;RECEIVE FOR PARTICULAR PID?
JRST IPFR1 ;NO
MOVE T1,P3 ;YES, MAKE SURE PID IS OK
PUSHJ P,VALPID
TRNA ;NO
CAME J,.CPJCH## ;PID DESTINED FOR US?
JRST [POP P,(P) ;BAD PID OR DOESNT BELONG TO JOB
JRST ERRRU]
JRST IPFR0
IPFR1: MOVE T1,J ;GET JOB NUMBER
PUSHJ P,CTXIPC## ;RETURN CURRENT IPCF DATA BASE
JRST [POP P,(P)
JRST ERRRU]
IPFR0: SETZM .EPPID(W) ;NOT WAITING FOR A PARTICULAR PID
POP P,T4 ;RESTORE T1 INTO T4
HLRZS T4 ;JUST NEED THE LENGTH
IPFR2: PUSH P,J ;SAVE J
IPFR2A: MOVE J,.CPJOB ;LOCK OUR QUEUE
PUSHJ P,IPCLOK
HLRZ P2,.EPIPC(W) ;POINTER TO OLDEST PACKET
IPFR3: JUMPE P2,IPFR14 ;NONE.
TLNE P1,IP.RFP ;RECEIVE FOR A PID?
CAMN P3,.IPCFR(P2) ;YES, IS THIS A MATCH
JRST IPFR4 ;WE HAVE A PACKET
HLRZ P2,.IPCFL(P2) ;NO MATCH, TRY NEXT PACKET IN QUEUE
JRST IPFR3
IPFR4: HRRZ T1,.IPCFL(P2) ;GET FLAG WORD
TRNE T1,IP.CFV ;PAGED PACKET?
TRZE P1,IP.CFV ;MUST HAVE REQUESTED A PAGE
TRNE P1,IP.CFV ;ERR IF REQUESTED A PAGE
JRST [POP P,J ;RESTORE J
PUSHJ P,IPCULK ;UNLOCK
JRST ERRPR ] ;WRONG MODE
MOVE P3,T1
TRNN P1,IP.SIP ;IS CALLER PRIV AND ASKING FOR PRIVS?
TRZ T1,IP.SIP ;NO, HE DOESNT CARE IF PACKET PRIV
HLRZ T2,P4 ;SPACE PROVIDED
LDB T3,PKLNP2 ;LENGTH OF PACKET
TLNE P3,IP.CFV ;PAGE?
SETO T3, ;BY NEGATIVE LENGTH
SUB T3,T2
SKIPG T3 ;LONG ENOUGH?
TLZA P1,IP.TTL ;YES, CLEAR TTL BIT
TLO T1,IP.TTL ;NO, SET TTL IN UUO BLOCK
PUSHJ P,PUTWRD## ;STORE IN USER'S ARG BLOCK
JRST IPFR17 ;ADDRESS CHECK
MOVE T1,.IPCFS(P2) ;GET SENDER'S PID
PUSHJ P,PUTWR1## ;STORE SENDER'S PID
JRST IPFR17 ;ADDRESS CHECK
MOVE T1,.IPCFR(P2) ;RECEIVER'S PID
PUSHJ P,PUTWR1## ;STORE RECEIVER'S PID
JRST IPFR17 ;ADDRESS CHECK
TLNN P1,IP.TTL ;TRUNCATE IF TOO LONG?
JUMPG T3,[POP P,J ;PHASE STACK
PUSHJ P,IPCULK
JRST ERRTL];ERROR IF TOO LONG
;COME HERE TO COPY PACKET TO USER'S CORE.
LDB T1,PKLNP2
MOVSI T1,(T1) ;GET LENGTH
HRR T1,P4 ;HDR
TRNE P3,IP.CFV
HRLI T1,PAGSIZ ;WHOLE PAGE
TLNE P1,IP.TTL ;PACKET TOO LONG?
HLL T1,P4 ;YES, TELL TRUNCATED LENGTH
PUSHJ P,PUTWR1## ;TELL USER THE LENGTH
JRST IPFR17
SUBI T4,.IPCFU ;SEE IF HE WANTS SENDER PPN
JUMPLE T4,IPFR4D ;NO
MOVE T1,.IPCFU(P2) ;GET SENDER'S PPN
PUSHJ P,PUTWR1## ;YES, GIVE IT TO HIM
JRST IPFR17
SOJLE T4,IPFR4D ;WANT .IPCFC?
MOVE T1,.IPCFC(P2) ;GET CAPABILITIES WORD
PUSHJ P,PUTWR1## ;YES, GIVE IT TO HIM
JRST IPFR17
IPFR4D: LDB T1,PKLNP2 ;GET LENGTH OF PACKET
TRNN P3,IP.CFV ;PAGE?
TLNE P1,IP.TTL ;TOO LONG?
HLRE T1,P4 ;YES, JUST FILL HIS BLOCK
JUMPLE T1,IPFR6 ;NOTHING TO STORE IF 0 WDS IN PACKET
HRRI M,-1(P4) ;USER'S ADDRESS
MOVN T2,T1 ;FORM AOBJN WORD
HRLZS T2
HRR T2,P2 ;ADR OF PACKET
IPFR5: MOVE T1,.IPCFD(T2) ;FETCH DATA FROM EXEC
PUSHJ P,PUTWR1## ;STORE IN USER'S AC
JRST IPFR17
AOBJN T2,IPFR5 ;COPY WHOLE PACKET
IPFR6: POP P,J ;GET BACK JOB/CONTEXT HANDLE
TRNN P3,IP.CFV ;WHOLE PAGE?
JRST IPFR7 ;NO
TLNE P1,IP.TTL ;TOO LONG?
JRST [IFN FTMP,<
PUSHJ P,UPMM##
>
MOVE T2,.IPCFI(P2)
TLZ T2,(IP.NAD^!<IP.DSK!IP.OIQ!IP.SSP>)
PUSH P,W
SKIPE T2 ;FORGET IT IF IO ERROR
PUSHJ P,IPCDEL##
POP P,W
IFN FTMP,<
PUSHJ P,DWNMM##
>
JRST IPFR7 ]
HRRZ T1,P4 ;NO, GET VIRTUAL PAGE NO
IPFR6A:
IFN FTMP,<
PUSHJ P,UPMM##
>
MOVE T2,.IPCFI(P2) ;DSK OR CORE ADDR
TLZ T2,(IP.NAD^!<IP.DSK!IP.OIQ!IP.SSP>)
JUMPE T2,[IFN FTMP,<
PUSHJ P,DWNMM##
>
PUSHJ P,IPCULK
JRST ERRIE ]
PUSH P,J ;SAVE JOB/CONTEXT HANDLE
ANDI J,JOBMSK## ;THE REST OF THE WORLD DOESN'T KNOW ABOUT CTX
PUSH P,W ;SAVE FROM DESTRUCTION BY VMSER
TLNN T2,(IP.DSK) ;IF THIS IS NOT A DISK ADDRESS
JRST IPFR6C ;THEN IPCINS WILL TAKE CARE OF IT
PUSH P,T2 ;SAVE T2
TLZ T2,(PM.NAD) ;CLEAR BITS
PUSHJ P,ONIPQ## ;IS IT ON THE "IP" QUEUE?
JRST IPFR6B ;NO
SSX T4,MS.MEM ;PAGTAB SECTION
DPB J,[POINT PT.SJB,PAGTAB(T4),<^L<PT.JOB>+PT.SJB-1>]
MOVEI T2,PIOWQ## ;PUT JOB IN PAGING I/O WAIT
DPB T2,PJBSTS##
IFN FTMP,<
PUSHJ P,DWNMM## ;GIVE UP THE MM
>
PUSHJ P,WSCHED## ;WAIT
POP P,(P) ;CLEAR STACK
POP P,W ;RESTORE W & J
POP P,J
JRST IPFR6A ;LOOK AGAIN
IPFR6B: POP P,T2 ;RESTORE ENTRY
IPFR6C: S0PSHJ IPCINS## ;PUT PAGE INTO THIS MAP
TDZA T2,T2 ;LOST
SETO T2, ;WON
IFN FTMP,<
PUSHJ P,DWNMM##
>
POP P,W ;RESTORE W
POP P,J ;RESTORE J
JUMPN T2,IPFR7 ;GO IF WON
PUSHJ P,IPCULK
JUMPL M,CPOPJ## ;DONE IF COMMAND (?)
JRST STOTAC## ;RETURN CODE TO USER
;COME HERE TO DECREMENT RECEIVER'S AND SENDER'S COUNTERS,
; FREE EXEC COPY OF PACKET, ETC. NO ERROR EXITS ARE
; PERMITTED BEYOND THIS POINT SINCE EXEC INFORMATION IS
; ALTERED.
IPFR7: XMOVEI T2,.EPIPC-.IPCFL(W) ;PRESET PREDECESSOR
IPFR8: HLRZ T3,.IPCFL(T2)
CAIN T3,(P2) ;THIS PACKET LINK TO OURS?
JRST IPFR9 ;YES
MOVE T2,T3 ;NO, TEST NEXT
JRST IPFR8
IPFR9: SYSPIF
HLRZ T1,.IPCFL(P2) ;POINTER TO NEXT PACKET
HRLM T1,.IPCFL(T2) ;LINK PREDECESSOR TO NEXT
SKIPN T1 ;END OF QUEUE?
HRRM T2,.EPIPN(W) ;YES, PRED IS NEW END
SYSPIN
IPFR10: JUMPE T1,IPFR12
MOVE T2,.IPCFR(P2) ;RECEIVER PID
TLNE P1,IP.RFP ;RECEIVE FOR A PID?
CAMN T2,.IPCFR(T1) ;YES, IS THIS PACKET A MATCH?
JRST IPFR11 ;THIS IS NEXT PACKET
HLRZ T1,.IPCFL(T1) ;NO MATCH, TRY NEXT
JRST IPFR10
IPFR11: MOVE T2,T1 ;COPY USEABLE ADDRESS
LDB T1,PKLNT2 ;GET LENGTH OF NEXT PACKET
MOVSI T1,(T1) ;WHERE IT SHOULD BE
HRR T1,.IPCFL(T2) ;FLAGS FOR NEXT PACKET
TRNE T1,IP.CFV ;PAGE?
HRLI T1,PAGSIZ ;YES, SET LENGTH
IPFR12: PUSHJ P,IPCULK
PUSHJ P,STOTAC## ;RETURN INFO ABOUT NEXT PACKET IN AC
SOS .EPIPC(W) ;DEC COUNT OF PACKETS WAITING
AOS T1,.EPIPA(W) ;INCR RECEIVE COUNT
TRNN T1,-1
SOS .EPIPA(W) ;OVERFLOW, COUNT IT DOWN AGAIN
;NOW MOVE TO THE SENDER'S ENVIRONMENT TO DECREMENT THE
; COUNT OF HIS UNRECEIVED SENDS. SENDER'S PID HAS BEEN
; KEPT IN P1 FROM WAY BACK.
MOVE T2,.IPCFS(P2) ;IS SENDER A SYSTEM PROCESS?
AND T2,%IPCPM##
CAIGE T2,%IPCNS##
TDZA T2,T2 ;YES, DON'T USE .IPCFC
LDB T2,TRNPT2 ;IF TURNED-AROUND MSG THE PID
SKIPN T1,T2 ; MAY HAVE BEEN DESTROYED,
MOVE T1,.IPCFS(P2) ;SO GET W FROM PID
PUSH P,J ;SAVE J
PUSHJ P,VALPID ;SET UP J & W
JRST IPFR13 ;NO GOOD, SENDER MUST BE GONE.
PUSHJ P,DECSNX ;DECREMENT PACKETS SENT BUT NOT RECEIVED
IPFR13: LDB T1,PKLNP2 ;GET LENGTH
CAIL T1,PAGSIZ ;PAGE?
SETZ T1, ;YES, NO DATA WORDS
ADDI T1,.IPCFD ;PLUS OVERHEAD WORDS
HRRZ T2,P2 ;ADDRESS
PUSHJ P,GIVWDS## ;FREE THE PACKET SPACE
SOSL %CNIIP## ;DEC COUNT OF PACKETS OUTSTANDING
PJRST JPOPJ1##
STOPCD .+1,DEBUG,PCN, ;++PACKET COUNT NEGATIVE
SETZM %CNIIP## ;CONTINUED - ZERO COUNT SO WONT STOP AGAIN
PJRST JPOPJ1## ;RESTORE J AND SKIP-RETURN
;COME HERE IF THERE IS NO PACKET IN THE USER'S LIST.
IPFR14: JUMPGE P1,IPFR15
PUSHJ P,IPCULK ;UNLOCK
POP P,J
JRST ERRNP ;BIT 0 = DONT BLOCK
IPFR15: TLNE P1,IP.RFP ;IF A PARTICULAR PID
MOVEM P3,.EPPID(W) ;TELL WORD WE WANT ONLY THIS
PUSH P,W ;SAVE IPCF DATA BLOCK ADDRESS
PUSHJ P,FNDPDS## ;AND POINT W AT PDB
MOVSI T1,IPCACE## ;FLAG HIBERNATING FOR IPCF
IORB T1,JBTRTD##(J)
MOVEI T1,SLPQ## ;PUT JOB IN SLEEP QUEUE
DPB T1,PJBSTS##
PUSHJ P,IPCULK ;UNLOCK
PUSHJ P,CLRIPT## ;ZAP IN-CORE PROTECT SO JOB CAN BE SWAPPED
PUSHJ P,WSCHED## ;WAIT FOR AWAKENING
MOVE T1,(P) ;GET POINTER TO IPCF DATA BLOCK
SETZM .EPPID(T1) ;NO LONGER RECEIVING FROM A SPECIFIC PID
XCT NOPISK## ;IF USER IS USING PSI
SKIPN @JBTPIA##(J) ;SKIP IF PENDING COUNT IS UP
JRST [POP P,W ;RESTORE W
JRST IPFR2A] ;NO PENDING INTERRUPTS, TRY AGAIN
POP P,W ;RESTORE W
POP P,J ;RESTORE J
SOS .JDAT+JOBPD1##+1 ;FORCE UUO TO RESTART
POPJ P, ;AFTER INTERRUPT IS GRANTED
;HERE ON ADDRESS CHECK DURING RECEIVE. FIX STACK, UNLOCK, AND RETURN ERROR
IPFR17: POP P,J
PUSHJ P,IPCULK
PJRST ERRAC
SUBTTL IPCFS - SEND UUO
UIPCFS::PUSHJ P,SAVE4## ;SAVE P1-P4
PUSHJ P,VALARG ;LOAD ARGS
POPJ P, ;WRONG
MOVE T1,J ;GET JOB NUMBER
PUSHJ P,CTXIPC## ;FIND IPCF DATA BASE
POPJ P, ;NO SUCH JOB OR CONTEXT
PUSHJ P,SETIPQ ;SET/GET QUOTA WORD
LDB T1,[POINT 9,T2,26] ;SEND QUOTA
LDB T2,[POINT 9,.EPIPC(W),26] ;SEND COUNT
MOVEI T3,1 ;ASSUME ONE LAST CALL
TRNE P1,IP.SIP ;PRIVS?
MOVEI T3,777 ;YES, LOTS OF CALLS
TLNE P1,IP.LPC ;LAST PHONE CALL?
ADD T1,T3 ;YES, BUMP THE QUOTA
CAILE T1,777 ;OVERFLOW?
MOVEI T1,777 ;YES, NOBODY IS ALLOWED TO OVERFLOW
CAMG T1,T2 ;QUOTA DEPLETED?
JRST ERRRS ;YES, DON'T SEND
JUMPN P3,IPCS1 ;IF REC'R FIELD IS 0,
SKIPN P3,.EPIPI(W) ; SEND MSG TO [SYSTEM]INFO FOR THIS JOB
MOVE P3,%SIINF## ; (LOCAL OR GLOBAL)
JUMPE P3,ERRDU ;DESTINATION UNKNOWN IF NO [SYSTEM]INFO
;COME HERE TO VALIDATE SENDER'S PID
IPCS1: JUMPN P2,IPCS4 ;"SENDER'S PID" SPECIFIED?
MOVN T1,%IPCMP## ;NO, FIND A DEFAULT PID
HRLZS T1
SKIPN T2,PIDTAB##(T1) ;SEARCH FOR A VALID PIDTAB ENTRY
IPCS2: AOBJN T1,.-1
JUMPGE T1,IPCS3 ;DONE, NO PIDS FOR THIS JOB
ANDI T2,JCHMSK## ;ISOLATE JCH
CAME T2,J ;THIS JCH?
JRST IPCS2 ;NO.
MOVE P2,PIDTAB##(T1) ;PUT ENTRY IN P2
TRZ P2,JOBMSK## ;REMOVE JOB NUMBER
TROA P2,(T1) ;INCLUDE PID INDEX
IPCS3: MOVE P2,J ;NO PIDS, USE JOB NUMBER
IPCS4: PUSH P,J ;SAVE J
MOVE T1,P2 ;GET SENDER'S PID
PUSHJ P,VALPID ;CHECK OUT SENDER
JRST [TRNE P1,IP.SIP ;PRIV'D?
JRST IPCS5 ;YES, OK (TURNING AROUND A MSG CAUSE REC'R DIED)
POP P,J ;NO - INVALID SENDER
JRST ERRIS]
JUMPE J,[POP P,J ;CANT SEND "FROM" AN EXEC PROCESS
JRST ERRIS]
SUB J,(P) ;PID IS LEGAL, IS IT HIS?
TRNN P1,IP.SIP ;IF SENDER ISN'T PRIV'D,
JUMPN J,[POP P,J
PJRST ERRIS] ; SEND MUST BE FROM HIS JOB
;COME HERE TO VALIDATE RECEIVER
IPCS5: MOVE T1,P3 ;PUT PID INTO T1
IFN FTMP,<
PUSHJ P,UPMM## ;LOCK FOR PDB
>
PUSHJ P,VALPID ;SET UP J AND W
JRST [POP P,J ;RESTORE J
IFN FTMP,<
PUSHJ P,DWNMM## ;FAILED
>
JRST ERRDU] ;DESTINATION UNKNOWN
;COME HERE TO CHECK THAT THE RECEIVER'S QUOTA IS NOT
; EXHAUSTED AND THAT THE RECEIVER IS NOT DISABLED.
LDB T1,RCCNT ;RECEIVE COUNT
LDB T2,RCQTA ;RECEIVE QUOTA
CAMN P3,.EPPID(W) ;ID REC'R BLOCKED FOR THIS PID
AOS T2 ;LET HIM GO 1 OVER QUOTA
EXCH J,(P) ;RESTORE SENDER, SAVE RECEIVER
CAML T1,T2 ;QUOTA EXHAUSTED?
JRST [POP P,J
IFN FTMP,<
PUSHJ P,DWNMM##
>
JRST ERRRR ]
SKIPGE .EPIPQ(W) ;NO, IS RECEIVER DISABLED?
JRST [POP P,J
IFN FTMP,<
PUSHJ P,DWNMM##
>
JRST ERRDD ]
HLRE T2,P4 ;GET DATA LENGTH
CAMG T2,%CNIPL## ;TOO LONG?
JRST IPCS5B ;NO
TLNN P1,IP.LPK ;TRYING TO SEND A LONG MESSAGE?
JRST IPCS5A ;PACKET TOO LONG
PUSHJ P,[PUSHJ P,SAVJW##
ANDI J,JOBMSK##
MOVSI T1,JP.IPC ;ONLY ALLOWD IF IPCF PRIVS
PJRST PRVBIT##] ;PRIV'ED?
JRST IPCS6 ;YES, PROCEED
IPCS5A:
IFN FTMP,< PUSHJ P,DWNMM##>
POP P,J ;FIX STACK
JRST ERRTL ;PACKET TOO LONG
IPCS5B: JUMPG T2,IPCS6
TRNN P1,IP.CFV
TROA P1,IP.CFZ
SETZ T2,
IPCS6: ADDM T2,%IPTWT## ;COUNT TOTAL NUMBER OF WORDS XFERRED
ADDI T2,.IPCFD ;NO, GET ROOM TO HOLD BLOCK
PUSHJ P,GETWDS## ;IN EXEC CORE
JRST [POP P,J
IFN FTMP,<
PUSHJ P,DWNMM##
>
JRST ERRRY ]
TRNE P1,70 ;SENDER FIELD 0?
JRST IPCS7
CAMN P2,%SIINF## ;YES, SENDER =[SYSTEM]INFO?
TRO P1,20 ;YES
CAMN P2,.EPIPI(W) ;SENDER=LOCAL[SYSTEM]INFO?
TRO P1,30 ;YES
IPCS7: HRRZM P1,.IPCFL(T1) ;STORE FLAGS (LH=INTERNAL POINTER)
MOVEM P2,.IPCFS(T1) ;STORE SENDER'S PID (FUDGED)
MOVEM P3,.IPCFR(T1) ;STORE RECEIVER'S PID
SETZM .IPCFI(T1) ;CLEAR WORD FOR LATER
HLRE T3,P4 ;SIZE
SKIPGE T3 ;LONG?
MOVEI T3,PAGSIZ ;YES
DPB T3,PKLNT1 ;STORE LENGTH
IFN FTMP,<
PUSHJ P,DWNMM## ;DON'T CARE ABOUT PDB ANY MORE
>
PUSH P,J ;SAVE SENDER INFO
PUSH P,W
EXCH T1,P2 ;GET FUDGED SENDERS PID
PUSHJ P,VALPID ;AND FIND ITS JOB
MOVE J,-1(P) ;USE CURRENT J IF NOT HERE
MOVE T1,P2 ;RESTORE T1
POP P,W ;AND W
MOVE T3,J ;GET FUDGED SENDER'S JOB/CONTEXT HANDLE
ANDI T3,JOBMSK## ;REDUCE TO A JOB NUMBER
MOVE T3,JBTPPN##(T3) ;GET FUDGED SENDER PPN
MOVEM T3,.IPCFU(T1) ;SAVE IT
PUSHJ P,IPCSCA ;STORE CAPABILITIES
POP P,J ;AND RESTORE REAL SENDERS J
HRRI M,-1(P4) ;POINTER TO BLOCK IN USER CORE
MOVE P3,T1 ;COPY ADDR OF CORE BLOCK
HLLZ P2,P4 ;FORM AOBJN WORD
JUMPLE P2,IPCS9 ;DONT STORE DATA IF LENGTH=0
HLRZ T3,P2 ;GET TOTAL WORDS IN RH OF AN AC
MOVNS P2
HRR P2,T1
PUSH P,J ;SAVE SENDER'S JCH
MOVE J,.CPJOB## ;GETWRD WANTS A REAL JOB NUMBER
IPCS8: PUSHJ P,GETWD1## ;GET WORD FROM USER CORE
MOVEM T1,.IPCFD(P2) ;STORE DATA WORD
AOBJN P2,IPCS8 ;COPY WHOLE BLOCK
POP P,J ;RESTORE SENDER'S JCH
;COME HERE WITH P3 POINTING TO A BLOCK IN EXEC CORE
; CONTAINING THE UUO ARGS AND THE DATA. MOVE TO RECEIVER'S
; ENVIRONMENT AND PUT THE PACKET ON HIS LIST.
IPCS9:
TRNE P1,IP.CFV ;PAGE MODE?
JRST IPCS9C ;YES
POP P,J ;RECEIVER'S JCH
PUSHJ P,IPCLOK ;LOCK QUEUE
IFN FTMP,<
PUSHJ P,UPMM## ;GUARD PDB GOING AWAY AGAIN
>
MOVE T1,.IPCFR(P3) ;MAKE SURE IT'S STILL THERE
PUSHJ P,VALPID
IPCS9A: SKIPA T1,P4 ;RECEIVER WENT AWAY
JRST IPCS13 ;PUT PACKET ON QUEUE
IFN FTMP,<
PUSHJ P,DWNMM##
>
HLRES T1 ;SWAP HALVES
ADDI T1,.IPCFD
MOVEI T2,(P3) ;ADDRESS
PUSHJ P,GIVWDS## ;RETURN THE SPACE
JRST ERRDU
IPCS9C:
HRRZ T1,P4 ;PAGE - GET ITS VIRTUAL PAGE NUMBER
MOVEM W,(P) ;SAVE FROM DESTRUCTION
PUSH P,J ;SAVE JOB/CONTEXT HANDLE
ANDI J,JOBMSK## ;STRIP OFF CTX # SO VMSER DOESN'T GET UPSET
S0PSHJ IPCRMV## ;REMOVE FROM SENDERS MAP
JRST [IFN FTMP,<PUSHJ P,DWNMM##>
POP P,J ;RESTORE J
POP P,W ;RESTORE W
HRRZ T2,P3 ;ERROR - GET ADR OF 4-WD BLOCK
MOVEI T1,.IPCFD ;LENGTH OF BLOCK
PUSHJ P,GIVWDS## ;RETURN THE SPACE
JRST ERRUP] ;AND ERROR RETURN
POP P,J ;RESTORE J
POP P,W ;RESTORE W
AOS %IPTPT## ;COUNT A PAGE TRANSFERRED
MOVE P2,T2 ;SAVE CORE ADR
MOVE T1,.IPCFR(P3) ;RECEIVER
PUSHJ P,VALPID ;SET UP J AND W
JRST IPS11A ;SHOULD NEVER HAPPEN
JUMPL P2,IPCS12 ;PAGE ON DSK? GO IF YES
MOVE T2,J ;COPY JOB/CONTEXT HANDLE
ANDI T2,JOBMSK## ;REDUCE TO A JOB NUMBER
SKIPGE T1,JBTSTS##(T2) ;JOB RUNNING?
TLNE T1,SWP ; AND IN CORE?
JRST IPCS11 ;NO, PAGE THE PAGE OUT
IFN FTLOCK,<
SKIPN T1,LOCK## ;ALWAYS PAGE IT IF SOMEONE IS LOCKING
>
HLRZ T1,.EPIPC(W) ;YES
JUMPN T1,IPCS11 ;PAGE OUT PACKET IF WONT BE FIRST ON 0
SKIPE T1,.EPPID(W) ;IF JOB IS BLOCKED WAITING FOR
CAME T1,.IPCFR(P3) ; A PARTICULAR PID
JUMPN T1,IPCS11 ;PAGE OUT IF NOT RIGHT SENDER
MOVSI T1,IPCACE## ;1ST IN QUEUE, IS REC'R HIBERING FOR IPC?
TDNE T1,JBTRTD##(T2)
JRST IPCS10 ;YES, DONT PAGE OUT THE PAGE
HRROI T1,C$IPC ;NO, IS HE PSI'ING FOR IPC?
PUSHJ P,PSITST##
JRST IPCS11 ;NOT ENABLED, PAGE OUT THE PAGE
;ENABLED OR HIBERING FOR THE PAGE, SEE IF ROOM IN CORE
IPCS10: MOVE T1,MAXMAX## ;TOTAL USER CORE ON SYSTEM
SUB T1,CORMAX## ;MAX SIZE A JOB CAN BECOME
LSH T1,W2PLSH ;NUMBER OF PAGES AVAILABLE FOR IPCF
MOVE T2,%CNPIC## ;NUMBER OF PAGES IN USE BY IPCF
ADDI T2,1 ;NUMBER WHICH WILL BE IN USE
CAMLE T2,T1 ;ENOUGH ROOM?
JRST IPCS11 ;NO, PAGE OUT THE PAGE
MOVEM T2,%CNPIC## ;IPCF PAGES IN CORE
JRST IPCS12 ;LEAVE THE PAGE IN CORE
IPCS11:
MOVE J,.CPJOB## ;RESTORE J
MOVE T2,P2
S0PSHJ IPCPAG## ;PAGE OUT THE PAGE
MOVEI T2,0 ;PAGING I/O ERROR
MOVE P2,T2
MOVE T1,.IPCFR(P3) ;RECEIVER'S PID
PUSHJ P,VALPID
SKIPA J,.CPJCH## ;OOPS, POINT J BACK TO US
JRST IPCS12 ;ALL IS WELL
IPS11A:
PUSHJ P,IPCULK
MOVEI T2,(P3) ;DEALLOCATE PACKET
MOVEI T1,.IPCFD ;..
PUSHJ P,GIVWDS## ;SINCE WON'T BE SENDING
SKIPN T2,P2 ;GET PAGE BACK
JRST [IFN FTMP,<PUSHJ P,DWNMM##>
JRST ERRIE] ;PAGING I/O ERROR
MOVEI T1,(P4) ;WHERE TO PUT IT
PUSH P,J ;SAVE J
ANDI J,JOBMSK## ;REDUCE TO A JOB #
PUSH P,W ;SAVE W
S0PSHJ IPCINS## ;PUT IT BACK
JRST [IFN FTMP,<
PUSHJ P,DWNMM## ;RECEIVER IS GONE
>
POP P,W ;RESTORE W
POP P,J ;RESTORE J
JRST ERRIE] ;PAGING I/O ERROR
IFN FTMP,<
PUSHJ P,DWNMM## ;RECEIVER IS GONE
>
POP P,W ;RESTORE W
POP P,J ;RESTORE J
JRST ERRDU ;RECEIVER WENT AWAY
IPCS12: IORM P2,.IPCFI(P3) ;SAVE DSK ADR IN PACKET
IPCS13: SYSPIF
SKIPN T2,.EPIPN(W) ;PICK UP END OF QUEUE
XMOVEI T2,.EPIPC-.IPCFL(W) ;EMPTY QUEUE
HRLM P3,.IPCFL(T2) ;SAVE THIS PACKET ON END OF QUEUE
HRRM P3,.EPIPN(W) ;SET UP PNTR TO NEW END-OF-QUEUE
AOS %CNIIP## ;INCREMENT OUTSTANDING PACKETS
AOS .EPIPC(W) ;INC COUNT
SYSPIN
IFN FTMP,<PUSHJ P,DWNMM##> ;DONE
;COME HERE AFTER THE PACKET IS ON THE RECEIVER'S LIST.
MOVE T1,.IPCFS(P3) ;SENDER (MIGHT NOT BE SAME J)
PUSHJ P,VALPID ;SET UP (PRIV'D JOB CAN SEND FROM ANOTHER JOB)
PJRST IPCS14 ;BAD - TURNING AROUND MSG TO A DROPPED PID
MOVEI T1,IP.SBT ;INCREMENT SEND COUNT
ADDM T1,.EPIPC(W)
HLRZ T1,.EPIPA(W) ;COUNT OF SEND UUOS
ADDI T1,1
TRNE T1,-1 ;OVERFLOW?
HRLM T1,.EPIPA(W) ;NO, STORE INCREMENTED COUNT
IPCS14: AOS %CNIPS## ;INCREMENT SENT PACKETS
;COME HERE TO AWAKEN A USER JOB OR PUSHJ TO AN EXEC PROCESS
; THAT HAS JUST HAD A PACKET ARRIVE ON ITS LIST.
PUSHJ P,IPCULK ;UNLOCK RECEIVER'S QUEUE
MOVE T1,.IPCFR(P3) ;RECEIVER'S PID
PUSHJ P,VALPID ;SET UP J AND W
PJRST CPOPJ1## ;SHOULD NEVER HAPPEN
JUMPE J,EXECPR ;SPECIAL HANDLING FOR EXEC PROCESS
PUSHJ P,WAKEUP
PJRST CPOPJ1## ;AND GIVE SKIP RETURN
;SUBROUTINE TO STORE CAPABILITIES OF THE SENDER
;CALLING SEQUENCE:
; MOVEI T1,ADDRESS OF THE PACKET HEADER
; MOVE J,JOB NUMBER OF THE SENDER
; PUSHJ P,IPCSCA
;ALWAYS RETURN CPOPJ
IPCSCA: PUSH P,T1 ;SAVE PACKET HEADER ADDRESS
MOVE T1,J ;COPY JOB/CONTEXT HANDLE
ANDI T1,JOBMSK## ;REDUCE TO A JOB NUMBER
MOVE T4,J ;CLEAR CAPABILITIES
MOVE T3,JBTSTS##(T1) ;GET JBTSTS
TLNE T3,JACCT ;SENDER HAS JACCT?
TLO T4,IP.JAC ;YES
TLNE T3,JLOG ;SENDER HAS JLOG?
TLO T4,IP.JLG ;YES
TRNE T3,JS.XO ;IS SENDER XCT ONLY?
TLO T4,IP.SXO ;YUP!
MOVE T3,JBTPRV##(T1) ;GET JBTPRV WORD
TLNE T3,JP.POK ;CAN SENDER POKE MONITOR?
TLO T4,IP.POK ;YES,
TLNE T3,JP.IPC ;DOES HE HAVE IPCF PRIVS?
TLO T4,IP.IPC ;YES
MOVSI T3,(UP.IYB) ;IN YOUR BEHALF?
TDNE T3,.USBTS ;TEST
TLZ T4,IP.JAC ;AS IF NOT PRIVED
POP P,T1 ;GET PACKET HEADER BACK
MOVEM T4,.IPCFC(T1) ;AND STORE SENDER'S CAPABILITIES
POPJ P, ;RETURN
;COME HERE IF EXEC PROCESS.
EXECPR: HRRZ T1,W ;NON-OFFSET LOC OF EXEC CTL BLOCK
PUSHJ P,@.EPADR(T1) ;CALL THE PACKET HANDLER
PJRST CPOPJ1## ;GIVE SKIP-RETURN
WAKEUP:
SIGNAL C$IPC ;SIGNAL MESSAGE AVAILABLE
JFCL
MOVE T1,J ;WHERE CTXSER EXPECTS IT
PUSHJ P,CTXWAK## ;WAKE JOB IN CASE PSISER COULDN'T
POPJ P, ;RETURN NON-SKIP
POPJ P, ;IF FAIL OR SUCCEED
;SUBROUTINE TO SET UP STATUS WORD FOR INTERRUPT
STRSIG::SE1ENT ;ENTER SECTION 1
PUSHJ P,SAVJW## ;SAVE J AND W
MOVE T1,J ;GET JOB/CONTEXT HANDLE
PUSHJ P,CTXIPC## ;FIND THE IPCF DATA BASE
POPJ P, ;NO SUCH JOB OR CONTEXT
MOVEI T2,0 ;IN CASE NO PACKETS
HLRZ T1,.EPIPC(W) ;LOC OF 1ST PACKET
JUMPE T1,CPOPJ## ;RETURN T2 = 0 IF NONE
LDB T2,PKLNT1 ;GET LENGTH OF TOP PACKET
MOVSI T2,(T2) ;TO LEFT HALF
HRR T2,.IPCFL(T1) ;FLAGS
TRNE T2,IP.CFV ;PAGE?
HRLI T2,PAGSIZ ;YES, LENGTH = 1 PAGE
POPJ P, ; AND RETURN
SUBTTL IPCFQ - QUERY UUO
UIPCFQ::PUSHJ P,SAVE1##
HRR M,T1 ;ADDRESS OF UUO BLOCK
HLRZ T4,T1 ;SAVE COUNT
PUSHJ P,GETWRD## ;GET WORD 0
JRST ERRAC
MOVE P1,T1 ;SAVE PRIV BIT
MOVE T1,J ;GET JOB NUMBER
PUSHJ P,CTXIPC## ;FIND IPCF DATA BASE
JRST ERRBJ ;NO SUCH JOB OR CONTEXT
PUSHJ P,IPCLOK ;LOCK OUR QUEUE
HLRZ T2,.EPIPC(W) ;IS THERE A PACKET?
JUMPN T2,IPCFQ0 ;CONTINUE
PUSHJ P,IPCULK ;UNLOCK
PJRST ERRNP ;RETURN FOR NONE
IPCFQ0: MOVE J,.CPJOB## ;GETWRD/PUTWRD LIKES REAL JOB NUMBERS
TLNN P1,IP.RFP ;WANT SPECIFIC PID?
JRST IPCFQ4 ;NO
ADDI M,2
PUSHJ P,GETWRD## ;YES, GET THE PID
JRST IPCFQ5
TLNN P1,IP.IAR ;IS RECEIVER'S PID INDIRECTED?
JRST IPCFQ7 ;NO
MOVE T3,M ;PRESERVE M
HRR M,T1 ;PUT PID ADDRESS IN M
PUSHJ P,GETWRD## ;GET THE PID
JRST IPCFQ5 ;ADDRESS CHECK
MOVE M,T3 ;RESTORE M
IPCFQ7: SUBI M,2
IPCFQ1: CAMN T1,.IPCFR(T2) ;THIS PACKET FROM THAT PID?
JRST IPCFQ4 ;YES, INFORM HIM
HLRZ T2,.IPCFL(T2) ;NO, TRY NEXT
JUMPN T2,IPCFQ1
PUSHJ P,IPCULK ;UNLOCK QUEUE
JRST ERRNP
IPCFQ4: HRRZ T1,.IPCFL(T2) ;YES, PASS INFO TO CALLER
TRNN P1,IP.SIP ;IS HE PRIV?
TRZ T1,IP.SIP ;NO, SUPPRESS PRIV BIT IN PACKET
PUSHJ P,PUTWRD## ;STORE .IPCFL
JRST IPCFQ5 ;ADDRESS CHECK.
MOVE T1,.IPCFS(T2) ;SENDER'S PID
PUSHJ P,PUTWR1## ;STORE SENDER'S PID
JRST IPCFQ5
MOVE T1,.IPCFR(T2) ;RECEIVER'S PID
PUSHJ P,PUTWR1## ;STORE RECEIVER'S PID
JRST IPCFQ5 ;ADDRESS CHECK
MOVE T3,.IPCFL(T2) ;FLAGS
LDB P1,PKLNT2 ;LENGTH
TRNE T3,IP.CFV ;PAGE?
MOVEI P1,PAGSIZ ;YES, THEN LENGTH= 1 PAGE
LDB T1,RCCNT ;COUNT
HRLI T1,(P1)
PUSHJ P,PUTWR1## ;STORE IN USER'S CORE
JRST IPCFQ5 ;ADDRESS CHECK
MOVE T1,.IPCFU(T2) ;GET SENDERS PPN
CAIG T4,.IPCFU ;DID HE ASK FOR IT?
PJRST IPCFQ6 ;NO, JUST RETURN
PUSHJ P,PUTWR1## ;YES, GIVE IT TO HIM
JRST IPCFQ5
MOVE T1,.IPCFC(T2) ;GET SENDERS PRIVS
CAIG T4,.IPCFC ;DID HE ASK FOR THEM?
PJRST IPCFQ6 ;NO, RETURN
PUSHJ P,PUTWR1## ;YES, GIVE THEM TO HIM
IPCFQ5: SKIPA T4,[ERRAC] ;FAILED
IPCFQ6: MOVEI T4,CPOPJ1## ;GOOD RETURN
PUSHJ P,IPCULK
JRST (T4)
SUBTTL IPCFM - MISC. FUNCTION UUO
;DEFINE THE EXTENDED ERROR CODES USED
ERCODX ERRACX,IPCAC% ;ADDRESS CHECK ERROR
ERCODX ERRUFX,IPCUF% ;UNKNOWN FUNCTION
ERCODX ERRRYX,IPCRY% ;NO ROOM ERROR
ERCODX ERRDUX,IPCDU% ;DESTINATION UNKNOWN
ERCODX ERRISX,IPCIS% ;INVALID SENDER
ERCODX ERRPIX,IPCPI% ;PRIVILEGES INSUFFICIENT
ERCODX ERRTLX,IPCTL% ;TOO LONG A PACKET/BUFFER
ERCODX ERRNLX,IPCNL% ;PACKET/BUFFER NOT LONG ENOUGH
UIPCFM::PUSHJ P,SAVE4## ;PRESERVE OUR REGISTERS
PUSHJ P,SAVJW## ;DITTO
IFN FTXMON,PUSHJ P,SSPCS## ;SAVE PCS IN CASE WE CHANGE IT
PUSHJ P,SXPCS## ;SETUP NEW PCS FOR EXTENDED ARGUMENTS
JRST ERRAC ;ADDRESS CHECK
MOVE M,T1 ;FOR ADDRESSING
PUSHJ P,GETEWD## ;GET FLAGS WORD
JRST ERRACX ;ADDRESS CHECK
TLNE T1,IP.CMX ;CHECK IF UNDEFINED FLAGS ARE ON
JRST ERRUFX ;YES, UNKNOWN FUNCTION
MOVE P4,T1 ;NO, SAVE FLAGS+LENGTH
HRRES T1 ;ISOLATE LENGTH
CAIL T1,2 ;TOO FEW ARGUMENTS?
CAILE T1,3 ;OR MORE THAN DEFINED?
JRST ERRUFX ;YES, UNKNOWN FUNCTION
MOVE P3,T1 ;NO, SAVE LENGTH
MOVSI T1,JP.IPC ;PRIV BIT TO TEST
TLNE P4,IP.CMP ;WANT TO SEND A PRIV'ED PACKET?
PUSHJ P,PRVBIT## ;YES, CHECK
CAIA ;PRIV'ED OR NONE NEEDED
TLZ P4,IP.CMP ;NO PRIVS--CLEAR FLAG
LDB T1,DESTP4 ;GET DESTINATION CODE
CAILE T1,3 ;ONE OF THOSE WE CAN TALK TO?
JRST ERRDUX ;NO, DESTINATION UNKNOWN
PUSHJ P,GETEW1## ;GET PACKET ADDRESS
JRST ERRACX ;ADDRESS CHECK
MOVE P1,T1 ;STORE ADDRESS OF PSEUDO-PACKET
SETZ T1, ;START BY ASSUMING ZERO
CAIGE P3,3 ;USER SPECIFY AN IYB WORD?
JRST IPCFM1 ;NO, USE ZERO
PUSHJ P,GETEW1## ;YES, FETCH IT
JRST ERRACX ;ADDRESS CHECK IF CAN'T
TLZN P4,IP.CMI ;INDIRECTING IT?
JRST IPCFM1 ;NO, USE THIS VALUE
IFN FTXMON,XSFM T2 ;YES, SAVE CURRENT PCS
PUSHJ P,SXPCS## ;CHANGE FOR THIS ARGUMENT
JRST ERRACX ;ADDRESS CHECK
MOVE M,T1 ;FOR FETCHING
PUSHJ P,GETEWD## ;GET PID TO FETCH
JRST ERRACX ;ADDRESS CHECK
IFN FTXMON,<
EXCH T1,T2 ;SAVE AND GET OLD PCS
PUSHJ P,STPCS## ;MAKE SURE PCS IS RIGHT
MOVE T1,T2 ;GET PID IN T1
> ;END OF IFN FTXMON
IPCFM1: SKIPN T1 ;WAS ONE GIVEN?
MOVE T1,.CPJCH## ;NO, SPECIFY THE USER
MOVE P2,T1 ;SAVE THE IN-YOUR-BEHALF PID
PUSHJ P,VALPID ;IS IT VALID AT ALL?
JRST ERRISX ;NO, INVALID SENDER
JUMPE J,ERRPIX ;NOT ALLOWED ON BEHALF OF EXEC PROCESS
JUMPL P4,IPCFM2 ;DON'T TEST PRIVS TWICE
.CREF IP.CMP ; (SHOW BIT TESTED)
MOVE T2,J ;COPY JCH OF PID
MOVE J,.CPJOB## ;FOR PRIV TEST
MOVSI T1,JP.IPC ;PRIV BIT NEEDED
CAME T2,.CPJCH## ;IF USER'S OWN JCH,
PUSHJ P,PRVBIT## ;OR HAS PRIVS,
CAIA ;PRIV'ED OR NONE NEEDED
JRST ERRPIX ;PRIVILEGES INSUFFICIENT
MOVE J,T2 ;RESTORE JCH
IPCFM2: MOVE T1,P1 ;COPY PSEUDO-PACKET ADDRESS
PUSHJ P,SXPCS## ;SETUP PCS FOR FETCHING
JRST ERRACX ;ADDRESS CHECK IF CAN'T
MOVE M,P1 ;FOR FETCHING
PUSHJ P,GETEWD## ;GET WORD CONTAINING LENGTH
JRST ERRACX ;ADDRESS CHECK
HLRZ T2,T1 ;ISOLATE LENGTH
CAILE T2,776 ;IN POSSIBLE RANGE?
JRST ERRTLX ;NO, PACKET TOO LONG
JUMPE T2,ERRNLX ;ZERO IS NOT LONG ENOUGH
MOVE P3,T2 ;PRESERVE BUFFER LENGTH
MOVE T1,M ;GET SOURCE POINTER
PUSHJ P,ARNGE## ;RANGE-CHECK THE ARGUMENTS
TRN ;NON-EXISTANT AND ILLEGAL FOR I/O ARE BOTH BAD
JRST ERRACX ;ADDRESS CHECK
LDB T2,DESTP4 ;GET DESTINATION CODE
CAIE T2,1 ;IPCC?
JRST IPCFM3 ;NO, GO TEST FOR INFO
MOVEI T2,.IPCFD(P3) ;YES, GET TOTAL EXEC PACKET LENGTH
PUSHJ P,GETWDS## ;ALLOCATE THE PACKET
JRST ERRRYX ;NO SPACE IN EXEC FOR PACKET
MOVEM J,.IPCFC(T1) ;SAVE EFFECTIVE SENDER'S ID
MOVEI T3,.IPCFD(T1) ;DESTINATION OF BLT
JRST IPCFM4 ;JOIN COMMON CODE
IPCFM3: CAILE P3,776-6 ;CHECK LENGTH AGAINST GALAXY AND INFO OVERHEAD
JRST ERRTLX ;TOO LONG FOR INFO
CAIE T2,2 ;[SYSTEM]INFO?
MOVEI M,.EPIPI(W) ;NO, GET [LOCAL]INFO
CAIN T2,0 ;IF DEFAULT INFO
SKIPE (M) ;AND NO [LOCAL]INFO
CAIN T2,2 ;OR IF [SYSTEM]INFO
MOVEI M,%SIINF## ;GET [SYSTEM]INFO'S PID
SKIPN (M) ;IS INFO RUNNING?
JRST ERRDUX ;NO, DESTINATION UNKNOWN
MOVEI T2,6(P3) ;GET SIZE NEEDED FOR GOPHER MESSAGE
PUSHJ P,GTFWDC## ;OBTAIN SOME FREE SPACE
JRST ERRRYX ;NO SPACE IN EXEC FOR PACKET
MOVEI T3,6(T1) ;DESTINATION OF BLT
;JOIN COMMON CODE
IPCFM4: MOVE T4,P2 ;COPY USER'S SENDER ID
MOVE P2,T1 ;COPY PACKET ADDRESS
XSFM T2 ;GET PCS
HRLZS T2 ;WHERE IT BELONGS
HRR T2,P1 ;USER SOURCE OF PACKET
MOVEI T1,(P3) ;GET LENGTH
MOVE P1,T2 ;KEEP A COPY OF THE GLOBAL ADDRESS
XBLTUX T1 ;COPY INTO EXEC PACKET
LDB T1,DESTP4 ;GET DESTINATION CODE AGAIN
CAIE T1,1 ;IS IT FOR [SYSTEM]IPCC?
JRST IPCFM5 ;NO, GO HANDLE GOPHER-TO-INFO
MOVS M,.USMUO ;RESTORE UUO AC NOW THAT FETCHING DONE
SETZM .IPCFI(P2) ;CLEAR DISK FLAG (NOT PAGED PACKET)
DPB P3,PKLNP2 ;STORE DATA LENGTH
MOVEM T4,.IPCFS(P2) ;STORE SENDER'S ID
SETZM .IPCFL(P2) ;CLEAR LINK AND FLAGS
MOVE T1,PIDTAB## ;GET PID OF [SYSTEM]IPCC
MOVEM T1,.IPCFR(P2) ;SET AS RECEIVER
MOVEI T1,IP.SIP ;SENDER IS PRIVILEGED
TLNE P4,IP.CMP ;WANT TO INVOKE PRIVS?
MOVEM T1,.IPCFL(P2) ;YES, SET THE FLAG
PUSH P,P1 ;SAVE USER'S PACKET ADDRESS
MOVE P1,P2 ;MOVE PACKET FOR [SYSTEM]IPCC
PUSHJ P,IPCFPD ;DISPATCH [SYSTEM]IPCC FUNCTION
SKIPA P2,T1 ;PRESERVE ERROR CODE
SETZ P2, ;OR LACK OF ONE
LDB T1,PKLNP1 ;GET PACKET LENGTH
MOVEI T2,.IPCFD(P1) ;EXEC DATA SOURCE
POP P,T3 ;USER DATA DESTINATION
XBLTXU T1 ;COPY BACK TO USER
LDB T1,PKLNP1 ;GET LENGTH AGAIN
ADDI T1,.IPCFD ;ACCOUNT FOR OVERHEAD
MOVEI T2,(P1) ;PACKET ADDRESS
PUSHJ P,GIVWDS## ;RETURN FREECORE
SKIPE T1,P2 ;SEE IF ERROR CODE GIVEN
JRST STOTAC## ;YES, PROPAGATE ERROR TO USER
JRST CPOPJ1## ;ALSO SUCCESSES
;HERE FOR GOPHER SENDS TO INFO
IPCFM5: HRRZ T1,6(P2) ;GET USER'S FUNCTION
HRLI T1,1(P3) ;AND LENGTH OF THIS SUB-BLOCK
MOVEM T1,5(P2) ;STORE IT WHERE INFO EXPECTS IT
MOVEM T4,6(P2) ;PUT IYB WORD HERE FOR INFO
MOVSI T1,6(P3) ;GET LENGTH OF OUR PACKET
HRRI T1,.IPCIG ;AND OUR FUNCTION
MOVEM T1,QUELNH(P2) ;PUT LENGTH,,GALAXY FUNCTION IN GALAXY HEADER
MOVSI T1,(1B0) ;REQUEST AN ACK
MOVEM T1,QUEFLG(P2) ;IN GALAXY MESSAGE
MOVE T1,.CPJCH## ;WHAT JOB IS DOING THIS
HRL T1,%CNIPS## ;SEQUENCE NUMBER
MOVEM T1,QUEJOB(P2) ;SAVE AS ACK CODE
SETZM QUEMBZ(P2) ;NO USE FOR .OFLAGS
MOVEI T1,1 ;OUR TOTAL ARG COUNT
MOVEM T1,QUEARC(P2) ;SET IN GALACTIC HEADER
MOVE T1,T4 ;GET IYB VALUE AGAIN
PUSHJ P,VALPID ;OBTAIN ITS JCH
MOVE J,.CPJCH## ;ASSUME IT'S OURS IF IT WENT AWAY
MOVE T4,J ;COPY
ANDI T4,JOBMSK## ;KEEP ONLY JOB PORTION
MOVE T4,JBTPPN##(T4) ;GET PPN OF ASSOCIATED JOB
MOVE J,.CPJOB## ;GET OUR JOB BACK AGAIN
PUSHJ P,FNDPDS## ;AND OUR PDB
HLRZ T1,QUEJOB(P2) ;GET THE SEQUENCE NUMBER WE USED
HRRM T1,.PDQSN##(W) ;SAVE FOR RESPONSE VALIDATION
MOVE T3,%SIGFR## ;GET PID OF [SYSTEM]GOPHER
MOVE T2,P2 ;COPY PACKET ADDRESS
HRLI T2,6(P3) ;SET XWD LENGTH,ADDRESS
MOVE T1,M ;COPY PID ADDRESS
MOVS M,.USMUO ;NOW RESTORE UUO AC FOR ERROR RETURNS
HRLI T1,40 ;FROM [SYSTEM]GOPHER
TLNE P4,IP.CMP ;PRIV'ED PACKET DESIRED?
TLO T1,IP.SIP ;YES, LIGHT PRIV BIT
PUSHJ P,SENDSP ;SEND FROM GOPHER TO INFO, AND BACK AGAIN
JRST [MOVEI T1,IPCCF% ;IPCC REQUEST FROM INFO FAILURE
PJRST STOTAC] ;RETURN THIS ERROR
HLRZ P2,.PDEPA##(W) ;BY NOW WE HAVE OUR OWN PDB IN W
LDB T1,RTNER2 ;GET ERROR CODE RETURNED (IF ANY)
SKIPN T1 ;IF NONE,
AOS (P) ;THEN WILL EVENTUALLY SKIP RETURN
SKIPE T1 ;ELSE,
PUSHJ P,STOTAC## ;SET THE ERROR CODE TO RETURN
HLRZ T1,.IPCFD+5(P2) ;GET LENGTH RETURNED BY INFO
CAILE T1,(P3) ;WILL DATA FIT IN USER'S BUFFER?
MOVEI T1,(P3) ;NO, ONLY COPY AS MUCH AS WILL FIT
SUBI T1,1 ;WE DON'T TRANSFER THE FUNCTION WORD
AOS T3,P1 ;GET USER DESTINATION ADDRESS
MOVEI T2,.IPCFD+6(P2) ;AND MONITOR SOURCE ADDRESS
XBLTXU T1 ;COPY ANSWER FOR THE USER
LDB T1,PKLNP2 ;GET LENGTH OF PACKET
ADDI T1,.IPCFD ;ACCOUNT FOR OVERHEAD WORDS
MOVE T2,P2 ;COPY ADDRESS
PJRST GIVWDS## ;GIVE BACK EXEC CORE AND RETURN FROM UUO
SUBTTL [SYSTEM]IPCF - THE EXEC PROCESS
IPCFPR::PUSHJ P,SAVE3##
IFN FTMP,<
PUSHJ P,ONCPU0## ;ONLY ONE CPU AT A TIME
>
IPCF1: TLO M,FLMCOM ;SET SO ERR WONT CALL STOTAC
PUSHJ P,GETPAK ;GET OLDEST PACKET
POPJ P, ;NONE, EXIT.
HRRZ P1,T1 ;PACKET ADDRESS
MOVE T1,.IPCFL(P1) ;GET FLAGS
TRNE T1,1 ;TURNED-AROUND MSG?
JRST IPCF3 ;YES, JOB MUST HAVE LOGGED OUT
PUSHJ P,IPCFPD ;DISPATCH THE FUNCTION
JFCL ;ERROR ALREADY STORED IN PACKET HEADER
PUSHJ P,DECSSW ;DECREMENT SENDER'S COUNTS
;IN ORDER FOR THE JOB TO RECEIVE THE MSG IT MUST BE ENABLED
;ANSWER WILL THUS ENABLE THE JOB. IN ORDER TO PREVENT THIS
;BIT 0 OF P1 MUST BE LIT BY THE SUBROUTINE (DISABLE FUNCTION)
PUSHJ P,ANSWER ;TURN PACKET AROUND TO USER
JRST IPCF1 ;AND CHECK FOR ANOTHER.
IPCF3: PUSHJ P,NXTPAK ;MAKE NEXT PACKET THE OLDEST
SOS .EPIPC(W) ;FIX UP THE COUNTS
PUSH P,W
LDB T1,TRNPTR ;SENDER JOB NO
PUSHJ P,VALPID ;SET W
JRST IPCF4 ;OOPS, HE REALLY IS GONE
PUSHJ P,DECSNX ;DECREMENT PACKETS SENT BUT NOT RECEIVED
IPCF4: POP P,W
PUSHJ P,REMPAK ;GET RID OF THIS PACKET
JRST IPCF1 ;AND GO LOOK AT NEXT PACKET
;HERE TO DISPATCH [SYSTEM]IPCC FUNCTIONS
IPCFPD: HRRE T4,.IPCFD(P1) ;PICK UP CODE (WORD 0)
CAML T4,[IPCFCF] ;A CUSTOMER DEFINED FUNCTION?
CAILE T4,IPCFM ;VALID?
SKIPA T4,BADCOD ;NO, SET FOR ERROR
MOVE T4,BADCOD(T4) ;YES, GET DISPATCH ADR
MOVE T1,.IPCFS(P1) ;SENDER
LDB T2,PKLNP1 ;LENGTH
MOVE T3,.IPCFL(P1) ;FLAGS
PUSH P,W ;PRESERVE W
TRNE T3,IP.CFV ;PAGE?
JRST MODERR ;MODE ERROR (IPCC ONLY TAKES PACKETS)
TRNN T3,IP.SIP ;JOB HAVE PRIV'S?
JUMPL T4,PRVERR ;NO, ERROR IF FUNCTION REQUIRES PRIVS
LDB P2,[POINT 3,T4,17] ;GET NEEDED LENGTH OF UUO BLOCK
CAIGE T2,(P2) ;UUO BLOCK LONG ENOUGH?
JRST SHRTER ;NO, ERROR
HRRZS T4 ;CLEAR USED-UP JUNK
PUSHJ P,(T4) ;DISPATCH
JRST IPFD2 ;STORE ERROR IN HEADER
JRST WPOPJ1## ;RESTORE W AND RETURN SUCCESS
;DISPATCH ERRORS -
MODERR: MOVEI T1,IPCPR%
JRST IPFD2 ;SET BAD ERROR CODE
SHRTER: SKIPA T1,[IPCNL%] ;UUO BLOCK NOT LONG ENOUGH
PRVERR: MOVEI T1,IPCPI% ;PRIV'S INSUFFICIENT
IPFD2: DPB T1,RTNERR ;BAD - STORE ERROR CODE IN FLAG WORD
JRST WPOPJ## ;RESTORE W AND RETURN ERROR
;SUBROUTINE TO GET POINTER TO PACKET INTO T1.
GETPAK: HLRZ T1,.EPIPC(W) ;POINTER OR ZERO
JUMPE T1,CPOPJ## ;NONE.
PJRST CPOPJ1## ;HAVE ONE - SKIP RETURN
;SUBROUTINE TO DECREMENT COUNT OF PACKETS SENT BUT NOT RECEIVED
DECSND: MOVE T1,.IPCFS(P1) ;SENDERS PID
PUSHJ P,VALPID ;GET W
POPJ P, ;SHOULDN'T HAPPEN
DECSNX: MOVNI T1,IP.SBT ;BYTE-ALIGNED MINUS ONE
MOVE T2,.EPIPC(W) ;OUTSTANDING SEND COUNT, ETC.
TRNE T2,777000 ;COUNT NON-ZERO?
ADDM T1,.EPIPC(W) ;DECREMENT
POPJ P, ;RETURN
DECSSW: PUSH P,W
PUSHJ P,DECSND
JRST WPOPJ##
;SUBROUTINE TO MAKE NEXT PACKET THE OLDEST
NXTPAK: SYSPIF
HLRZ T1,.IPCFL(P1) ;NEXT PACKET
HRLM T1,.EPIPC(W) ; IS NOW THE OLDEST
SKIPN T1 ;EMPTY QUEUE?
SETZM .EPIPN(W) ;YES, CLEAR END POINTER
JRST ONPOPJ## ; AND RETURN
;DISPATCH TABLE FOR [SYSTEM]IPCF
;EACH SUBROUTINE IS CALLED WITH P1 POINTING TO THE PACKET
; IN EXEC STORAGE
;P2-P4 ARE AVAILABLE FOR USE
;T1=PID OF SENDER T2=LENGTH OF DATA T3=FLAGS
;W AND J ARE SET UP FOR RECEIVER, BUT MAY BE CHANGED
IPCFTL: ;ADD CUSTOMER DEFINED FUNCTIONS HERE
BADCOD: EXP ERRUF ;(BAD CODE) - UNKNOWN FNCTN
IPCFTB: XWD 000000,ENABL ;(01) ENABLE
XWD 000000,DISAB ;(02) DISABLE
XWD 000003,WHOIS ;(03) TELL PID OF [SYSTEM]INFO
XWD 400003,MKINFO ;(04) MAKE [SYSTEM]INFO
XWD 000002,DESTRY ;(05) DESTROY A PID
XWD 000003,CREATE ;(06) CREATE A PID
XWD 400003,QUOTA ;(07) SET QUOTA
XWD 400003,OWNER ;(10) CHANGE OWNERSHIP OF A PID
XWD 000003,JOBNO ;(11) FIND JOB NUBER FOR A PID
XWD 000004,RDPIDS ;(12) FIND PID(S) FOR A JOB
XWD 000003,RDQTA ;(13) FIND QUOTA FOR A JOB
XWD 400002,CPOPJ1## ;(14) WAKE UP JOB HIB'ING FROM RESET
IPCFRF: EXP ERRUF ;(15) SENT BY IPCF ON RESET
XWD 400003,SPQTA ;(16) SET PID QUOTA
XWD 000003,RPQTA ;(17) READ PID QUOTA
EXP ERRUF ;(20)
EXP ERRUF ;(21)
EXP ERRUF ;(22)
XWD 000003,SIDFND ;(23) FIND IN SYSTEM PID TABLE
XWD 400003,SIDSET ;(24) SET SYSTEM PID TABLE
XWD 000003,SIDRD ;(25) READ SYSTEM PID TABLE
IPCFSM: EXP ERRUF ;(26) SPOOL MSG SENT "TO" QUASAR
IPCFLM: EXP ERRUF ;(27) LOGOUT MESSAGE SENT "TO" QUASAR
IPCFTM: EXP ERRUF ;(30) TAPE LABELING MESSAGE
IPCFUO: EXP ERRUF ;(31) MOUNTABLE UNIT ON-LINE
IPCFON: EXP ERRUF ;(32) LOGON MESSAGE SENT "TO" QUASAR
EXP ERRUF ;(33) ACCOUNTING MESSAGES
IPCFDE: EXP ERRUF ;(34) MDA CONTROLLED DEVICE DEASSIGNED OR RELEASED
IPCFME: EXP ERRUF ;(35) MOS MEMORY ERROR TO TGHA
IPCFCS: EXP ERRUF ;(36) CSHIFT MESSAGE TO ACTDAE (OBSOLETE)
IPCFRL: EXP ERRUF ;(37) RESET OF T/S JOB WITH LOCKED STR. TO MDA
IPCFGM: EXP ERRUF ;(40) QUEUE. UUO FUNCTION TO A GALAXY COMPONENT
IPCFSC: EXP ERRUF ;(41) SEARCH LIST CHANGE TO MDA
IPCFAT: EXP ERRUF ;(42) PRIMARY PORT ATTACH (TO MDA)
IPCFDT: EXP ERRUF ;(43) PRIMARY PORT DETACH (TO MDA)
IPCFXC: EXP ERRUF ;(44) DISK UNIT EXCHANGE (TO MDA)
IPCFRM: EXP ERRUF ;(45) STRUCTURE REMOVAL (TO MDA)
IPCFMT: EXP ERRUF ;(46) MAGTAPE UNIT ACCESSIBLE (TO MDA)
IPCFST: EXP ERRUF ;(47) STRUCTURE MOUNT (TO MDA)
INFMSG: EXP ERRUF ;(50) [SYSTEM]INFO REQUEST VIA GOPHER
IPCSCM: EXP ERRUF ;(51) SCHEDULE BITS CHANGE MSG "TO" QUASAR
.IPCTL==:IPCFTM-IPCFTB+1
.IPCUO==IPCFUO-IPCFTB+1
.IPCDE==:IPCFDE-IPCFTB+1
.IPCME==:IPCFME-IPCFTB+1
.IPCRL==:IPCFRL-IPCFTB+1 ;MESSAGE # FOR MDA RESET
.IPCGM==:IPCFGM-IPCFTB+1
.IPCSC==:IPCFSC-IPCFTB+1
.IPCAT==IPCFAT-IPCFTB+1
.IPCDT==IPCFDT-IPCFTB+1
.IPCXC==IPCFXC-IPCFTB+1
.IPCRM==IPCFRM-IPCFTB+1
.IPCMT==IPCFMT-IPCFTB+1
.IPCST==IPCFST-IPCFTB+1
.IPCIG==INFMSG-IPCFTB+1
IPCFM==.-IPCFTB ;LENGTH OF TABLE
IPCFCF==IPCFTL-BADCOD ;MOST NEGATIVE CUSTOMER FUNCTION
;SUBROUTINE TO GIVE ANSWER TO AN EXEC CALL
ANSWER: MOVEI T2,1
REPEAT 0,< ;NOT NEEDED TILL OTHER EXEC PROCESSES EXIST
CAMN T1,PIDTAB## ;SENDER = [SYSTEM]IPCF?
>
;ENTER HERE TO INDICATE MESSAGE SENT BY OTHER THAN IPCC (SENDER'S CODE IN T2)
ANSWE1: MOVE T1,.IPCFR(P1) ;SWITCH SENDER & RECEIVER
DPB T2,[POINT 3,.IPCFL(P1),32] ;TELL REC'R THAT MSG IS FROM IPCF
EXCH T1,.IPCFS(P1)
MOVEM T1,.IPCFR(P1)
MOVE T1,.IPCFL(P1) ;IF A WHOLE PAGE PASSED,
TRNE T1,IP.CFV ; DON'T CLEAR ITS ADDRESS
JRST ANSWE2
MOVSI T1,(IP.NAD) ;CLEAR ADDRESS
ANDM T1,.IPCFI(P1)
ANSWE2: PUSHJ P,NXTPAK ;MAKE PACKET THE OLDEST
SETZM .IPCFC(P1) ;CLEAR FLAG WRDS ON SEND FROM
SETZM .IPCFU(P1) ; AN EXEC PROCESS
PUSHJ P,SNDMSG ;RETURN PACKET TO SENDER OF ORIGINAL MSG
PUSHJ P,REMPAK ;COULDNT DO IT - REMOVE THE PACKET
SOS .EPIPC(W)
AOS T1,.EPIPA(W) ;COUNT OF RECEIVES SINCE LOGIN
TRNN T1,-1 ;OVERFLOW?
SOS .EPIPA(W) ;YES, SET IT BACK
POPJ P, ;AND RETURN TO CALLER
;SUBROUTINE TO REMOVE THE OLDEST PACKET.
REMPAK::SE1ENT ;ENTER SECTION 1
HRRZ T2,P1 ;ADR OF PACKET TO REMOVE
SOS %CNIIP## ;DEC COUNT OF OUTSTANDING PACKETS
LDB T1,PKLNT2 ;LENGTH OF DATA
IFN FTMP,<
PUSHJ P,UPMM## ;NEED MM IN CASE PAGE
>
PUSH P,.IPCFI(P1) ;SAVE POSSIBLE PAGE #+BITS
MOVEI T3,IP.CFV ;PAGED PACKET?
TDNE T3,.IPCFL(P1) ;?
TDZA T1,T1 ;YES, NO DATA
SETZM (P) ;IF PACKET, NO PAGE TO RETURN
ADDI T1,.IPCFD ;PLUS OVERHEAD
PUSHJ P,GIVWDS## ;RETURN THE PACKET (OR HEADER)
POP P,T2 ;RESTORE ADDRESS OR NOTHING
IFN FTMP,<
JUMPE T2,DWNMM## ;RETURN THE MM
>
IFE FTMP,<
JUMPE T2,CPOPJ## ;NOTHING TO RETURN IF PAGING I/O ERROR
>
PUSH P,W ;SAVE W
PUSHJ P,IPCDEL## ;DELETE PAGE
IFN FTMP,<
PUSHJ P,DWNMM##
>
JRST WPOPJ## ;RESTORE W AND RETURN
;SUBROUTINE TO SEND A PACKET. ADDRESS OF UUO ARGS AND PACKET
; DATA IN P1. SOURCE MUST BE AN EXEC PROCESS, TARGET
; MAY BE EITHER EXEC OR USER. TARGET MUST BE USER
; IF AT INTERRUPT LEVEL. SKIP RETURN ON OK,
; NON-SKIP RETURN HAS T1=ERROR CODE.
SNDMSG: PUSHJ P,SAVE3## ;SAVE P2 AND 3
MOVE P2,J ;SAVE J
MOVE P3,W ;SAVE W
MOVE T1,.IPCFR(P1) ;CHECK RECEIVER
PUSHJ P,VALPID ;SET UP J AND W
JRST SNDERR ;DESTINATION UNKNOWN
MOVSI T1,IP.DSB ;SET TO ENABLE RECEIVER
TLNN P1,400000 ;UNLESS BIT 0 ON IN P1
ANDCAM T1,.EPIPQ(W) ;HE IS NOW ENABLED
LDB T1,RCQTA ;RECEIVE QUOTA
LDB T2,RCCNT ;RECEIVE COUNT
CAMG T1,T2 ;ROOM LEFT?
JRST SNDERR
AOS .EPIPC(W) ;INCR COUNT OF REC'D MSGS
;COME HERE TO PUT THE MESSAGE ON THE RECEIVER'S LIST
SYSPIF ;NO INTERRUPT HERE
SKIPN T2,.EPIPN(W) ;END OF QUEUE
XMOVEI T2,.EPIPC-.IPCFL(W) ;EMPTY
HRRM P1,.EPIPN(W) ;NEW END OF QUEUE
HRLM P1,.IPCFL(T2) ;SAVE THIS PACKET ON END OF QUEUE
HRRZS .IPCFL(P1) ;ZERO LINK OF THE PACKET
SYSPIN ;ALLOW INTERRUPTS AGAIN
;COME HERE AFTER PUTTING PACKET ON LIST. UPDATE COUNTERS.
PUSH P,W ;NEEDED LATER IF EXEC PROCESS
PUSH P,J ;SAVE FROM DESTRUCTION
MOVE T1,.IPCFS(P1) ;GET SENDER'S PID
PUSHJ P,VALPID ;SET UP W
JFCL ;CAN'T FAIL CUZ ALREADY VERRIFIED
POP P,J ;RESTORE J
HRRZ T1,.EPIPC(W) ;INCREMENT COUNT OF MSGS SENT
ADDI T1,IP.SBT
MOVEI T2,IP.SBT
TLNN T1,-1
ADDM T2,.EPIPC(W) ;MUST USE ADDM TO AVOID SMP RACE
HLRZ T1,.EPIPA(W) ;COUNT OF SENDS
ADDI T1,1 ;INCREMENT IT
TRNE T1,-1 ;OVERFLOW?
HRLM T1,.EPIPA(W) ;NO, STORE INCREMENTED COUNT
POP P,W ;RESTORE POSSIBLE EXEC PROCESS BLOCK
JUMPN J,SND3 ;IS DEST A USER JOB?
PUSHJ P,@.EPADR(W) ;NO, GO RUN EXEC PROCESS.
JRST SND4 ;RETURN TO MAIN LINE.
;COME HERE TO AWAKEN A USER'S JOB.
SND3: PUSHJ P,WAKEUP
SND4: AOS %CNIPS## ;INC TOTAL PACKETS SENT
AOS (P) ;SKIP RETURN
JRST SNDER1 ;RESTORE AC'S
;HERE ON A SEND ERROR
SNDERR: HRRZ T1,.IPCFD(P1) ;CODE
CAIE T1,6 ;CREATE A PID?
JRST SNDER1 ;NO
MOVE T2,.IPCFL(P1) ;FLAGS WORD
TRNE T2,IP.CFE ;IF NO ERROR ON CREATING THE PID,
JRST SNDER1
MOVE T1,.IPCFD+2(P1) ;GET RID OF IT
AND T1,%IPCPM## ;INDEX INTO TABLE
SETZM PIDTAB##(T1)
SOS %IPCNP## ;DECR CURRENT # OF PIDS
SNDER1: MOVE W,P3 ;RESTORE W
MOVE J,P2 ;RESTORE J
POPJ P,0 ;RETURN
;ENABLE THE OWNER OF THE PID IN WORD 1, OR THE SENDER IF WORD
; 1 IS NOT PROVIDED. USE OF WORD 1 IS A PRIV. FUNCTION.
ENABL: CAIGE T2,2 ;WORD 1 SUPPLIED?
PJRST CPOPJ1## ;NO, SENDER IS AUTOMATICALLY ENABLED
TRNN T3,IP.SIP ;NO, PRIV'D?
PJRST ERRPI ;NO, ERROR
MOVE T1,.IPCFD+1(P1) ;YES, GET PID SUPPLIED
ENABL1: PUSHJ P,VALPID ;SET UP J AND W.
POPJ P, ;BAD PID, FLUSH
MOVSI T1,IP.DSB ;CLEAR JOB'S DISABLE BIT
ANDCAM T1,.EPIPQ(W)
PJRST CPOPJ1## ;AND GOOD RETURN
;DISABLE THE OWNER OF THE PID IN WORD 1, OR SENDER IF NO WORD 1.
; USE OF WORD 1 IS A PRIV. FUNCTION.
DISAB: TRNE T3,IP.SIP ;PRIV'D?
CAIGE T2,2 ;YES, WORD 1 SUPPLIED?
TLOA P1,400000 ;NO, USE SENDER (ALREADY IN T1), DONT ENABLE HIM
MOVE T1,.IPCFD+1(P1) ;YES, GET PID SUPPLIED
CAIL T2,2 ;TRYING TO DISABLE ANOTHER JOB?
JUMPL P1,ERRPI ;YES, ERR IF NOT PRIV'D
PUSHJ P,VALPID ;SET UP J AND W
POPJ P, ;WRONG, FLUSH
JUMPE J,ERRPI ;DON'T ALLOW DISABLING AN EXEC PSEUDO PROCESS
MOVSI T1,IP.DSB ;SET JOB'S DISABLE BIT
IORM T1,.EPIPQ(W)
PJRST CPOPJ1## ;GOOD RETURN
;MAKE A [SYSTEM]INFO. ARG IS NOT CHECKED SINCE IT MAY BE
; DELIBERATELY INVALID (I.E., 0) TO TERMINATE A LOCAL
; [SYSTEM]INFO OR TO INDICATE THAT THE REAL [SYSTEM]INFO IS LOGGING
; OUT.
MKINFO: SKIPN T1,.IPCFD+2(P1) ;USER OR SYS?
JRST MKINF2 ;SYS.
PUSHJ P,VALPID ;SET UP J AND W FOR TARGET
POPJ P, ;NONE SUCH, FLUSH
JUMPE J,CPOPJ## ;NOT VALID FOR EXEC PROCESSES
SKIPN %SIINF## ;IF NO GLOBAL OR LOCAL [SYSTEM]INFO
SKIPE .EPIPI(W) ; IS RUNNING THEN MAKING A LOCAL IS OK
SKIPA T1,.IPCFS(P1) ;IF SENDER CHECKS OUT
JRST MKINF1 ;NONE RUNNING NOW - OK
CAME T1,%SIINF## ;IS SENDER GLOBAL [SYSTEM]INFO?
CAMN T1,.EPIPI(W) ; OR LOCAL [SYSTEM]INFO?
MKINF1: SKIPA T2,.IPCFD+1(P1) ;YES, GET PID TO BECOME THE LOCAL [SYSTEM]INFO
JRST ERRPI ;NO, ERROR RETURN
MOVEM T2,.EPIPI(W) ;STORE WITHOUT CHECKING
PJRST CPOPJ1## ;GOOD RETURN
;COME HERE TO MAKE SYSTEM'S [SYSTEM]INFO
MKINF2: MOVE T1,.IPCFD+1(P1) ;THE PID
MOVEM T1,.IPCFD+2(P1) ;MOVE IT OVER
MOVEI T1,1 ;SYSID INDEX
MOVEM T1,.IPCFD+1(P1) ;INTO BLOCK
PJRST SIDSET ;USE COMMON CODE
;SEND MESSAGE IDENTIFYING [SYSTEM]INFO
WHOIS: SKIPN T1,.IPCFD+1(P1) ;YES, GET JOB NO WHOSE INFO IS WANTED
MOVE T1,.IPCFS(P1) ;NO, TELL HIM HIS OWN [SYSTEM]INFO
PUSHJ P,VALPID ;LOAD J AND W
POPJ P, ;BAD PACKET
SKIPE J ;EXEC PROCESS HAS NO PDB
SKIPN T2,.EPIPI(W) ;PID OF [SYSTEM]INFO
MOVE T2,%SIINF## ;EXEC OR NO LOCAL SPECIFIED
MOVEM T2,.IPCFD+2(P1) ;THE ONE WORD OF DATA
PJRST CPOPJ1## ;GOOD RETURN
;CREATE A PID. WORD 1 HAS JOB NUMBER, BIT 0=1 IF DROP PID ON RESET
CREATE: PUSHJ P,SAVJW## ;SAVE J AND W
MOVE T1,.IPCFD+1(P1) ;USER ARG
TLZ T1,400000 ;REMOTE TYPE FLAG
JUMPE T1,ERRBJ
TLNE T1,377777 ;ONLY SIGN BIT IS GOOD
JRST ERRBJ ;BAD ARGS
PUSHJ P,CTXIPC## ;POINT TO IPCF DATA BASE
JRST ERRBJ ;NO SUCH JOB OR CONTEXT
HRRM J,.IPCFD+1(P1) ;UPDATE CONTEXT NUMBER (MAYBE 0 WAS GIVEN)
TRNE T3,IP.SIP ;PRIVILEGED PACKET?
JRST CREAT3 ;YES, DON'T CHECK PID QUOTA
HRRZ T3,.IPCFC(P1) ;NO, GET SENDER'S JCH
CAME T3,J ;ATTEMPTING TO AFFECT SOMEONE ELSE?
JRST ERRPI ;YES, GIVE PRIVILEGE ERROR
LDB T3,PQTAPT ;NO, GET PID QUOTA
JUMPE T3,CREAT2 ;QUOTA EXCEEDED
MOVSI T3,IP.DPL!IP.DPR;NO, GET PID-DEFINED FLAGS
TDNN T3,.EPIPQ(W) ;ANY PIDS DEFINED FOR THIS JOB?
JRST CREAT3 ;NO, IT FITS IN THE QUOTA THEN
CAML T3,%IPCMP## ;QUOTA MORE THAN POSSIBLE NUMBER OF PIDS?
JRST CREAT3 ;YES, CAN'T BE EXCEEDING QUOTA
MOVN P2,%IPCMP## ;SET AOBJN WORD TO SCAN TABLE
HRLZS P2
SETZ T1, ;CLEAR COUNT OF PIDS FOR THIS JCH
SKIPN T2,PIDTAB##(P2) ;FIND A SLOT IN USE
CREAT1: AOBJN P2,.-1 ;LOOP OVER ENTIRE TABLE
JUMPGE P2,CREAT3 ;WITHIN QUOTA
CAIE J,(T2) ;FOR THE SAME JCH?
JRST CREAT1 ;NO, KEEP LOOKING
ADDI T1,1 ;YES, COUNT ANOTHER IN USE
CAIGE T1,(T3) ;EXCEEDING QUOTA?
JRST CREAT1 ;NOT YET, KEEP LOOKING
CREAT2: MOVEI T1,IPCQP% ;YES, PID QUOTA EXCEEDED ERROR
POPJ P, ;RETURN FAILURE TO CALLER
CREAT3: MOVN P2,%IPCMP## ;SET AOBJN WORD TO SCAN TABLE
HRLZS P2
SKIPE PIDTAB##(P2) ;FIND AN EMPTY SLOT
AOBJN P2,.-1
JUMPGE P2,ERRPF ;ERROR IF TABLE FULL
AOS T2,%IPCTP## ;TOTAL # OF PIDS SINCE RELOAD
HRLZS T2 ;LH=UNIQ #, RH=JOB/CONTEXT HANDLE
IOR T2,.IPCFD+1(P1) ;ADD JOB NO, (BIT 0 IF DROP ON RESET)
MOVEM T2,PIDTAB##(P2)
TRZ T2,JOBMSK## ;REMOVE JOB NUMBER
IORI T2,(P2) ;INSERT INDEX INTO TABLE FOR PID AS TOLD
MOVEM T2,.IPCFD+2(P1) ; TO USER ("PUBLIC" PID)
MOVSI T3,IP.DPR
SKIPL T2 ;DROP PID ON RESET?
MOVSI T3,IP.DPL ;NO, DROP ON LOGOUT
IORM T3,.EPIPQ(W) ;REMEMBER THAT FACT
AOS %IPCNP## ;INCR CURRENT # OF PIDS
PJRST CPOPJ1## ;AND GOOD RETURN
;FIND JOB NUMBER ASSOCIATED WITH A PID
JOBNO: MOVE T1,.IPCFD+1(P1) ;PID
PUSHJ P,VALPID ;LEGAL?
PJRST ERRBJ ;NO
MOVEM J,.IPCFD+2(P1) ;YES, RETURN JOB NO TO CALLER
PJRST CPOPJ1## ;AND TAKE GOOD RETURN
;TELL QUOTA FOR A JOB
RDQTA: MOVE T1,.IPCFD+1(P1) ;JOB NUMBER (OR SOME PID FOR JOB)
PUSHJ P,VALPID ;LEGAL?
PJRST ERRBJ ;NO
MOVE T1,.EPIPQ(W) ;YES, GET QUOTA
HRRZM T1,.IPCFD+2(P1) ;SAVE IN PACKET
PJRST CPOPJ1## ;AND GOOD RETURN
;SET QUOTA FOR PID IN WORD 2.
QUOTA: MOVE T1,.IPCFD+1(P1) ;PICK UP JOB NUMBER
PUSHJ P,VALPID ;SET UP J + W
PJRST ERRBJ ;ERROR, FLUSH
MOVE T2,.IPCFD+2(P1) ;GET QUOTA WORD
HRRM T2,.EPIPQ(W) ;STORE AS NEW QUOTA
PJRST CPOPJ1## ;GOOD RETURN
;READ PID QUOTA FOR PID IN WORD 2
RPQTA: MOVE T1,.IPCFD+1(P1) ;PICK UP JCH
PUSHJ P,VALPID ;SET UP J & W
JRST ERRBJ ;ERROR, FLUSH
LDB T2,PQTAPT ;GET PID QUOTA
MOVEM T2,.IPCFD+2(P1) ;STORE IN ANSWER
JRST CPOPJ1## ;GOOD RETURN
;SET PID QUOTA FOR PID IN WORD 2
SPQTA: MOVE T1,.IPCFD+1(P1) ;PICK UP JCH
PUSHJ P,VALPID ;SET UP J & W
JRST ERRBJ ;ERROR, FLUSH
MOVE T2,.IPCFD+2(P1) ;GET QUOTA WORD
DPB T2,PQTAPT ;STORE IT
JRST CPOPJ1## ;GOOD RETURN
;TELL PID(S) ASSOCIATED WITH A JOB
RDPIDS: MOVEI P2,-2(T2) ;NUMBER OF VALUES TO RETURN
SKIPLE T1,.IPCFD+1(P1) ;DESIRED JOB NUMBER
PUSHJ P,CTXIPC## ;MAKE SURE IT HAS IPCF DATA
JRST ERRBJ ;BAD JOB NUMBER
SKIPN T1,.IPCFD+2(P1) ;STARTING PID
JRST RDPID1 ;START AT BEGINNING OF TABLE
PUSHJ P,VALPID ;CHECK IT OUT
PJRST ERRDU ;CANT START AT AN ILLEGAL PID
MOVE T1,.IPCFD+2(P1) ;OK, GET PID AGAIN
AND T1,%IPCPM## ;GET START INDEX INTO TABLE
RDPID1: MOVE T2,.IPCFD+1(P1) ;RETRIEVE DESIRED JOB/JCH
MOVNS P2
HRLZS P2 ;SET AN AOBJN WORD FOR STORING VALUES
HRR P2,P1
MOVN T3,%IPCMP## ;MAKE AN AOBJN WORD
HRLZS T3 ; FOR SCANNING PIDTAB
ADDI T1,1
HRLS T1
ADD T1,T3
RDPID2: SKIPN T3,PIDTAB##(T1) ;GET A PID
JRST RDPID3 ;LOOK FOR NEXT
TRNN T2,CTXMSK## ;MATCHING ON A JCH?
TRZ T3,CTXMSK## ;NO, CLEAR SO MATCH ONLY ON JOB NUMBER
ANDI T3,JCHMSK## ;JOB NUMBER OR JCH
CAIE T3,(T2) ;MATCH TARGET?
JRST RDPID3 ;NO
MOVE T3,PIDTAB##(T1) ;YES, GET FULL PID AGAIN
TRZ T3,JOBMSK## ;REMOVE JOB NO
IORI T3,(T1) ;ADD INDEX
MOVEM T3,.IPCFD+2(P2) ;SAVE IN PACKET
AOBJP P2,CPOPJ1## ;DONE IF NO MORE ROOM
RDPID3: AOBJN T1,RDPID2 ;SCAN WHOLE TABLE
SETZM .IPCFD+2(P2) ;TERMINATE WITH A 0
PJRST CPOPJ1## ;AND TAKE GOOD RETURN
;DESTROY A PID.
DESTRY: MOVE T1,.IPCFD+1(P1) ;PID BEING DESTROYED
PUSHJ P,CHKSID ;SEE IF A SYSTEM PID
PJRST ERRPI ;YES, CAN'T DO THAT
PUSHJ P,VALPID ;VALIDATE IT
PJRST ERRBJ ;NO GOOD, FLUSH
MOVE P3,W ;OLD PDB LOC IN P3
MOVE P4,J ;OLD JCH
MOVE P2,.IPCFD+1(P1) ;PID
MOVE T1,.IPCFS(P1) ;SENDER
PUSHJ P,VALPID ;SET UP W
POPJ P, ;NO GOOD (SHOULD NEVER HAPPEN)
MOVE T1,.IPCFL(P1) ;GET FLAGS AGAIN
TRNN T1,IP.SIP ;PRIVILEGED JOB?
CAMN P4,J ;OR DOING IT TO HIS OWN PID?
TRNA ;YES, IT'S OK
JRST ERRPI ;NO, INSUFFICIENT PRIVILEGES
CAMN P2,.IPCFS(P1) ;SENDER DESTROYING HIS OWN PID?
MOVEM J,.IPCFS(P1) ;YES, SEND ANSWER BACK TO THE JOB NO.
MOVE T2,P2
AND T2,%IPCPM## ;MASK TO INDEX
SETZM PIDTAB##(T2)
PUSHJ P,CHANGE ;PUT ANY MSGS FOR PID INTO SENDER'S QUEUE
SOS %IPCNP## ;DECREMENT COUNT OF CURRENT PID'S
MOVE J,HIGHJB## ;DO ALL JOBS
DSTRY1: PUSHJ P,FNDPDB## ;SET UP W
JRST DSTRY2 ;NO JOB
CAMN P2,.EPIPI(W) ;DESTROY LOCAL INFO FOR THIS JOB?
SETZM .EPIPI(W) ;CLEAR IT!
DSTRY2: SOJG J,DSTRY1 ;LOOP FOR ALL JOBS.
PJRST CPOPJ1## ;AND GOOD RETURN
;CHANGE THE OWNERSHIP OF A PID. WORD 1 HAS THE PID, WORD 2 THE NEW
; JOB NUMBER.
OWNER: MOVE T1,.IPCFD+1(P1) ;PID TO CHANGE
PUSHJ P,CHKSID ;SEE IF A SYSTEM PID
PJRST ERRPI ;YES, CAN'T DO THAT
PUSHJ P,VALPID ;SET UP J + W
PJRST ERRDU ;BAD PID
MOVE T2,.IPCFD+1(P1) ;GET PID BEING CHANGED
CAMN T2,.IPCFS(P1) ;GIVING SELF AWAY?
MOVEM J,.IPCFS(P1) ;YES, SEND BACK TO JOB
JUMPE J,ERRDU ;CANNOT CHANGE OWNERSHIP OF EXEC PROC.
MOVE P3,W ;SOURCE PDB
SKIPG T1,.IPCFD+2(P1)
PJRST ERRBJ ;BAD JOB NUMBER
PUSHJ P,CTXIPC## ;FIND IPCF DATA BLOCK
PJRST ERRBJ ;NO SUCH JOB OR CONTEXT
MOVE P2,.IPCFD+1(P1) ;PID TO CHANGE IN P2
PUSHJ P,CHANGE ;CHANGE THE OWNERSHIP OF THE PID
MOVE T1,P2 ;GET OLD PID
AND T1,%IPCPM## ;MASK TO INDEX
MOVE T2,PIDTAB##(T1) ;GET OLD PID
TRZ T2,JOBMSK## ;REMOVE OLD JOB
IOR T2,.IPCFD+2(P1) ;INCLUDE NEW JOB
MOVEM T2,PIDTAB##(T1) ;STORE BACK IN PID TABLE
PJRST CPOPJ1## ;AND GOOD RETURN
;SUBROUTINE TO CHANGE THE OWNERSHIP OF A PID
;ENTER W=PDB OF NEW OWNER P2=PID TO CHANGE P3=PDB OF OLD OWNER
CHANGE: XMOVEI T2,.EPIPC-.IPCFL(P3) ;WHERE TO UNQUEUE FROM
CHNGE3: HLRZ T3,.IPCFL(T2) ;NEXT ITEM FROM QUEUE
JUMPE T3,CPOPJ## ;DONE IF 0
CAME P2,.IPCFR(T3) ;FOR THE PID BEING CHANGED?
JRST CHNGE4 ;NO
CAMN W,P3 ;CHANGING OWNERSHIP TO SAME JOB NO?
MOVEM J,.IPCFR(T3) ;YES, MAKE REC'R BE THE JOB ITSELF
; (OTHERWISE A LOOP MAY RESULT)
SYSPIF
SKIPN T1,.EPIPN(W) ;END OF QUEUE
XMOVEI T1,.EPIPC-.IPCFL(W) ;EMPTY
HRLM T3,.IPCFL(T1) ;YES, PUT ON NEW QUEUE
HLLZ T4,.IPCFL(T3) ;QUEUE POINTER OF THIS PACKET
HLLM T4,.IPCFL(T2) ;REMOVE FROM OLD QUEUE
HRRZS .IPCFL(T3) ;LAST ENTRY ON NEW QUEUE
HRRM T3,.EPIPN(W) ;END OF NEW QUEUE
SKIPN T4 ;IF END OF OLD QUEUE
HRRM T2,.EPIPN(P3) ; MAKE PRED THE END
SYSPIN
PUSH P,T2
PUSHJ P,WAKEUP ;PSI OR UNHIBER NEW RECEIVER
POP P,T2
SOS .EPIPC(P3) ;UPDATE COUNTS FOR OLD AND NEW OWNERS
AOSA .EPIPC(W)
CHNGE4: MOVE T2,T3 ;STEP TO NEXT ENTRY IN (OLD) QUEUE
JRST CHNGE3 ;AND TEST IT
;FUNCTION 23: FIND IN SYSTEM PID TABLE
SIDFND: MOVE T1,.IPCFD+1(P1) ;THE PID REQUESTED
PUSHJ P,CHKSID ;SEE IF A SYSTEM PID
TRNA ;YES, SKIP ON
JRST ERRUI ;NO, UNDEFINED ID REQUESTED ERROR
SUBI T2,<.GTSID##-.GTCSD##> ;OFFSET TO REAL TABLE INDEX
MOVEM T2,.IPCFD+2(P1) ;STORE AS ANSWER
JRST CPOPJ1## ;RETURN GOODNESS
;FUNCTION 24: SET SYSTEM PID TABLE
SIDSET: PUSHJ P,CHKIDX ;GET INDEX AND CHECK IT
JRST ERRBI ;BAD INDEX
JUMPE T2,ERRBI ;DON'T LET HIM SET IPCC
SETZ J, ;IN CASE CLEARING THE TABLE
SKIPN T1,.IPCFD+2(P1) ;GET PID FROM USER
JRST SETST1 ;ZERO MEANS CLEAR THE ENTRY
PUSHJ P,VALPID ;VALIDATE THE PID
POPJ P, ;RETURN ERROR CODE
MOVE T2,.IPCFD+1(P1) ;GET INDEX BACK
MOVE T1,.IPCFD+2(P1) ;GET THE PID
SETST1: MOVE T3,SIDJOB##(T2) ;CHECK OWNER
CAME T3,.CPJOB## ;AGAINST CALLER
JUMPN T3,ERRPI ;ERROR IF NOT OWNER OF TABLE ENTRY
MOVEM T1,.GTSID##(T2) ;STORE IT
MOVE T3,.CPJOB## ;GET OUR JOB NUMBER
MOVEM T3,SIDJOB##(T2) ;AND IN JOB NUMBER TABLE
CAIN T2,1 ;[SYSTEM]INFO
MOVEM T1,%CNIPI## ;YES, UPDATE OLD GETTAB
MOVSI T2,IP.DPL ;GET DROP-ON-LOGOUT BIT
CAMN T1,J ;USING JOB NUMBER AS PID?
IORM T2,.EPIPQ(W) ;YES, LIGHT IT FOR THIS JOB
JRST CPOPJ1## ;AND RETURN SUCCESS
;FUNCTION 25: READ SYSTEM PID TABLE
SIDRD: PUSHJ P,CHKIDX ;GET INDEX AND CHECK IT
JRST ERRBI ;BAD INDEX
MOVE T1,.GTSID##(T2) ;GET THE PID
MOVEM T1,.IPCFD+2(P1) ;GIVE IT TO THE USER
PJRST CPOPJ1## ;AND RETURN SUCCESSFUL
;CHKIDX -- ROUTINE TO VALIDATE INDEX AND RETURN IT IN T2.
; SKIP IF OK, NON-SKIP IF NO GOOD.
CHKIDX: HRREI T1,.GTCSD##-.GTSID## ;GET MINIMUM INDEX
MOVEI T3,SDTBLN## ; AND MAXIMUM
MOVE T2,.IPCFD+1(P1) ;GET INDEX REQUESTED
CAML T2,T1 ;TOO LOW
CAMLE T2,T3 ; OR TOO HIGH
POPJ P, ;YES
PJRST CPOPJ1## ;NO, IN RANGE
;HERE FROM UUOCON ON A LOGOUT UUO
IPCLGO::SE1ENT ;ENTER SECTION 1
PUSHJ P,SAVJW## ;SAVE J AND W
PUSHJ P,SAVE2## ;SAVE P1
PUSHJ P,QSRLGO ;SEND LOGOUT MESSAGE TO QUASAR
SETZ P1, ;MATCH ON ALL PIDS OWNED BY JOB
MOVSI T1,IP.DPL ;LOAD UP THE LOGOUT FLAG
JRST IPCFR1 ;SEND MSG TO INFO, DROP PIDS ETC.
;HERE FROM CTXSER ON POPPING A CONTEXT
IPCPOP::PUSHJ P,SAVE2## ;SAVE OUR P ACS
MOVEI P1,2 ;DOING A POP
MOVSI T1,IP.DPL ;SET UP CONDITION FOR TEST
JRST IPCFR1 ;JOIN COMMON CODE FOR LOGOUT/POP/RESET
;HERE FROM UUOCON ON A RESET UUO. SEND A MESSAGE TO INFO AND
; DESTROY THE APPROPRIATE PIDS.
IPCFRC::SE1ENT ;ENTER SECTION 1
PUSHJ P,SAVE2## ;SAVE P1
MOVEI P1,1 ;DOING A RESET
MOVSI T1,IP.DPR ;SET UP CONDITION FOR TEST
;COMMON CODE FOR RESET, POP, AND LOGOUT STARTS HERE
IPCFR1: PUSHJ P,SAVJW## ;SAVE FROM DESTRUCTION
PUSH P,T1 ;SAVE IP.DP? BIT
MOVE T1,J ;GET JOB IN QUESTION
PUSHJ P,CTXIPC## ;RETURN IPCF DATA BLOCK ADDRESS
JRST TPOPJ## ;BAD JOB OR CONTEXT NUMBER??
MOVE T1,J ;COPY UPDATED JOB/CONTEXT HANDLE
EXCH T1,(P) ;GET IP.DP? BACK
PUSHJ P,TURNQ ;TURN ANY MSGS AROUND FOR THIS JOB
TDNN T1,.EPIPQ(W) ;IF CONDITIONS AREN'T MET
JRST TPOPJ## ;DON'T SEND A MESSAGE TO ANYBODY
ANDCAM T1,.EPIPQ(W) ;AND SAY "NO MORE"
POP P,J ;GET JOB/CONTEXT HANDLE BACK
SKIPN P1 ;DROP PID ON LOGOUT?
ANDI J,JOBMSK## ;YES--KEEP ONLY THE JOB NUMBER
MOVEI T2,2 ;2 WORD MESSAGE TO INFO
PUSHJ P,GTFWDC## ;GET SPACE FOR MESSAGE
TDZA T4,T4 ;ISN'T ANY
MOVE T4,T1 ;REMEMBER WHERE IT IS
JUMPE T4,IPCLG0 ;WAS THERE ANY
MOVEI T2,IPCFRF-IPCFTB+1 ;CODE FOR RESET/LOGOUT
MOVEM T2,0(T4) ;SAVE IT
HRR P2,J ;GET FLAG,,JOB
MOVEM P2,1(T4) ;STORE
IPCLG0: MOVN P2,%IPCMP## ;SET AN AOBJN WORD FOR LOOKING
HRLZS P2 ; AT ALL OF PIDTAB
IPCLG1: MOVE T2,PIDTAB##(P2) ;GET PIDTAB ENTRY
JUMPE P1,IPCLG4 ;JUMP IF LOGGING OUT
CAIN P1,2 ;POPPING A CONTEXT?
JRST IPCLG5 ;YES, DROP BY JCH
TLNN T2,(1B0) ;DROP THIS PID?
JRST IPCLG2 ;NO--KEEP LOOKING
SKIPA T1,T2 ;COPY PID
IPCLG4: ANDI T2,JOBMSK## ;KEEP ONLY JOB NUMBER IF LOGGING OUT
IPCLG5: ANDI T2,JCHMSK## ;JOB/CONTEXT NUMBER
CAIE T2,(J) ;FOR THIS ONE?
JRST IPCLG2 ;NO
MOVE T1,PIDTAB(P2) ;COPY PID
SETZM PIDTAB##(P2) ;AND CLEAR PIDTAB ENTRY
SOS %IPCNP## ;1 LESS PID CURRENTLY ACTIVE
TRZ T1,JOBMSK## ;REMOVE JOB NUMBER
IORI T1,0(P2) ;INSERT PIDTAB INDEX
HRREI T2,.GTCSD##-.GTSID##
IPCLG3: CAMN T1,.GTSID##(T2) ;THIS IT
JRST [SETZM .GTSID##(T2) ;YES, CLEAR ENTRY
SETZM SIDJOB##(T2) ;AND THE JOB NUMBER
JRST .+1] ;RETURN A LINE
CAIGE T2,SDTBLN##
AOJA T2,IPCLG3
MOVE T2,%SIINF## ;INFO'S PID
MOVEM T2,%CNIPI## ;KEEP THE GETTAB STRAIGHT
IPCLG2: AOBJN P2,IPCLG1 ;DO FOR ALL ENTRIES IN PIDTAB
JUMPE T4,CPOPJ##
MOVEI T1,%SIINF## ;LOCATION OF INFO'S PID
SKIPE .EPIPI(W) ;PRIVATE INFO?
MOVEI T1,.EPIPI(W) ;YES, USE IT
HRLI T4,2 ;INSERT SIZE
PJRST SNDFFC ;SEND IT AND RETURN
;SUBROUTINE TO TURN MESSAGES AROUND FOR A JOB ON RESET/LOGOUT
;CALL WITH T1=IP.DPR OR IP.DPL IN T1
;IF IP.DPR, TURNS AROUND ONLY THOSE MESSAGES FOR PIDS TO BE DROPPED ON RESET
;IF IP.DPL, TURNS AROUND ALL MESSAGES
;PRESERVES T1
TURNQ: PUSHJ P,SAVE4## ;SAVE P1-P4
PUSH P,J ;SAVE J
MOVE P3,J
PUSH P,T1
XMOVEI P2,.EPIPC-.IPCFL(W) ;PRESET PREDECESSOR
TLNN T1,IP.DPR
TLO P2,-1 ;P2 NEGATIVE IF LOGOUT
PUSHJ P,IPCLOK ;LOCK OUR QUEUE
PUSH P,.EPIPL(W) ;WE'RE GOING TO FORGET WE OWN OUR OWN FOR A WHILE
HRRZS .EPIPL(W) ;SAY WE DON'T OWN ANYTHING FOR NOW
TURNQ0: HLRZ P1,.IPCFL(P2) ;GET NEXT ENTRY IN QUEUE FOR JOB
TURNQ1: JUMPE P1,TURNQ7 ;DONE IF 0
SKIPL T1,.IPCFR(P1) ;IF REC'R IS TO BE DROPPED ON LOGOUT,
JUMPGE P2,TURNQ6 ; STEP TO NEXT PACKET IF THIS IS RESET
AOS T2,.IPCFL(P1) ;SET BIT 35 (UNDELIVERABLE) IN PACKET HEADER
MOVE P4,W ;SAVE PDB OF JOB DOING TURNING
TRNE T2,2 ;ALREADY BEEN THIS WAY?
JRST TURNQ4 ;YES, MAKE THE PACKET GO AWAY
EXCH T1,.IPCFS(P1)
MOVEM T1,.IPCFR(P1)
PUSHJ P,VALPID ;SET W FOR REC'R (ORIGINAL SENDER)
JRST TURNQ4 ;HE'S GONE TOO - REMOVE THE PACKET
CAME J,.CPJCH ;DON'T TRY TO GET OUR OWN AGAIN
PUSHJ P,IPCLOK ;LOCK HIS QUEUE (FORGETTING WE OWN OURS FOR NOW)
DPB P3,TRNPTR ;SAVE JOB NUMBER FOR TURN-AROUND RCV.
PUSHJ P,DECSNX ;DECREMENT PACKETS SENT BUT NOT RECEIVED
AOS .EPIPC(W) ;INCREMENT RECV COUNT
EXCH W,P4 ;RESTORE W OF LOGGING-OUT JOB
MOVEI T2,777 ;ADJUST COUNT OF OLD JOB
ADDM T2,.EPIPC(W)
SYSPIF
SKIPN T1,.EPIPN(P4)
XMOVEI T1,.EPIPC-.IPCFL(P4)
HRRM P1,.EPIPN(P4)
HRLM P1,.IPCFL(T1) ;STICK THIS PACKET ON END OF QUEUE
MOVE T1,.IPCFL(P1) ;LINK TO NEXT IN OLD JOB'S QUEUE
HRRZS .IPCFL(P1) ;THIS IS END IN FORMER SENDER'S QUEUE
HLRZ P1,T1 ;POINT P1 TO NEXT IN OLD QUEUE
HRLM P1,.IPCFL(P2) ;LINK NEXT TO PREDECESSOR IN OLD Q
SKIPN P1
HRRM P2,.EPIPN(W)
SYSPIN
CAME J,.CPJCH ;DON'T UNLOCK OURSELVES
PUSHJ P,IPCULK ;UNLOCK
JUMPN J,[PUSHJ P,WAKEUP ;WAKE UP ORIGINAL SENDER
JRST TURNQ1] ;GO TURN AROUND NEXT MSG
EXCH W,P4
HRRZ T1,W ;LOC OF EXEC PID
PUSHJ P,@.EPADR(T1) ;CALL THE EXEC PROCESS
MOVE W,P4
JRST TURNQ1 ;GO TURN AROUND NEXT MSG IN QUEUE
;HERE IF MSG COULDN'T BE TURNED AROUND
TURNQ4: LDB T1,TRNPTR ;GET JOB NUMBER
PUSHJ P,VALPID ;VALIDATE IT
JRST TURNQ5
PUSHJ P,DECSNX ;DECREMENT PACKETS SENT BUT NOT RECEIVED
TURNQ5: MOVE W,P4 ;RESTORE PDB OF JOB DOING TURNING
SYSPIF
HLRZ T1,.IPCFL(P1) ;LINK TO NEXT PACKET
HRLM T1,.IPCFL(P2) ;MAKE NEXT IN QUEUE
SKIPN T1
HRRM P2,.EPIPN(W)
SOS .EPIPC(W) ;DECREMENT USER'S RECEIVE COUNT.
SYSPIN
PUSHJ P,REMPAK ;REURN THIS PACKET TO FREE CORE
JRST TURNQ0 ;AND TRY NEXT PACKET
;HERE IF PACKET IS FOR A PID TO BE DROPPED ON LOGOUT, THIS IS RESET
TURNQ6: HRR P2,P1 ;SAVE POINTER TO LAST ON OLD QUEUE
JRST TURNQ0 ;GO PROCESS NEXT QUEUE ENTRY
;HERE WHEN DONE
TURNQ7: MOVE T1,-2(P)
PUSHJ P,CTXIPC## ;SET J,W
MOVEI W,-.EPIPL(P) ;?
POP P,.EPIPL(W)
MOVE T2,-2(P) ;GET IP.DP? BIT AGAIN
MOVSI T1,IP.DSB ;SET JOB'S DISABLE BIT
TLNE T2,IP.DPL ;IF REALLY GOING AWAY
IORM T1,.EPIPQ(W) ; (YES)
PUSHJ P,IPCULK ;AND RETURN OUR LOCK
POP P,T1 ;RESET T1
PJRST JPOPJ## ;AND RETURN TO CALLER
SUBTTL IPCC INTERFACE FOR BATCH AND SPOOLING
;HERE ON THE CLOSE OF A SPOOLED FILE FROM FILUUO. CALLED WITH F
; CONTAINING THE ADDRESS OF THE SPOOLED DDB.
QSRSPL::SE1ENT ;ENTER SECTION 1
PUSHJ P,SAVT## ;SAVE T1 - T4
PUSH P,J ;SAVE J
LDB J,PJOBN## ;LOAD UP J
MOVSI T1,SPMSIZ ;MESSAGE SIZE
HRRI T1,IPCFSM-IPCFTB+1 ;SPOOL FUNCTION
PUSHJ P,FNDPDS## ;SETUP W
PUSHJ P,SETQSR ;SETUP THE PACKET
SKIPE T3,DEVSPM##(F) ;GET ADDR OF SPOOLED PARAMETER BLOCK
SKIPN T1,SPBNM1(T3) ;HAVE A USER NAME?
SKIPA T1,.PDNM1##(W) ;GET NAME FROM USER BLOCK
SKIPA T2,SPBNM2(T3) ;SECOND HALF
MOVE T2,.PDNM2##(W) ;GET SECOND HALF
DMOVEM T1,SPMUSR(T4) ;STORE IT
MOVE T1,DEVNAM(F) ;GET INITED DEVICE
MOVEM T1,SPMIDV(T4) ;AND SAVE IT
HLRZ T1,DEVUNI##(F) ;GET ADR OF UDB
HRRZ T1,UNISTR(T1) ;GET ADR OF SDB
MOVE T1,STRNAM##(T1) ;GET STRUCTURE NAME
MOVEM T1,SPMSTR(T4) ;STORE IT
MOVE T1,DEVFIL(F) ;GET FILENAME
MOVEM T1,SPMFIL(T4) ;STORE IT
HLLZ T1,DEVEXT(F) ;GET EXTENSION
HLLM T1,SPMEXT(T4) ;STORE IT
SKIPN T1,DEVSPN##(F) ;GET ENTER'ED NAME IF SETUP
MOVE T1,JBTNAM##(J) ;USE PROG NAME IF 0.
MOVEM T1,SPMEFN(T4) ;AND SAVE IT
MOVE T1,DEVACC##(F) ;GET ADDRESS OF ACCESS TABLE
MOVE T1,ACCWRT##(T1) ;GET BLOCKS WRITTEN
MOVEM T1,SPMFSZ(T4) ;AND SAVE FILE SIZE
HRLZ T1,DEVSPM##(F) ;GET ADDRESS OF SPOOLING OPTION BLOCK
JUMPE T1,QSRSP1 ;IF NO PARAMETER BLOCK
HRRI T1,SPMPRM(T4) ;WHERE TO COPY BLOCK TO
JRST QSRSP2 ;AND SEND IT ALL
QSRSP1: HRLI T1,SPMPRM(T4) ;PREPARE TO CLEAR BLOCK
HRRI T1,SPMPRM+1(T4) ;...
SETZM SPMPRM(T4) ;CLEAR FIRST WORD
QSRSP2: BLT T1,SPMPRM+SPBMAX-1(T4) ;CLEAR OR MOVE ALL PARMS
SKIPE DEVUPP##(F) ;IN-YOUR-BEHALF ENTER DONE?
JRST QSRSP3 ;YES--ACCT STRING ALREADY SETUP
MOVSI T1,.PDACS##(W) ;WILL USE ACCT STRING FROM PDB
HRRI T1,SPMPRM+SPBACT(T4) ;SET UP BLT
BLT T1,SPMPRM+SPBMAX-1(T4) ;COPY ACCT STRING
QSRSP3: MOVEI T1,%SIQSR## ;SEND TO QUASAR
PUSH P,T4 ;SAVE MESSAGE ADDRESS
SKIPN T2,DEVUPP##(F) ;GET IN-YOUR-BEHALF PPN
MOVE T2,JBTPPN##(J) ;ISN'T ONE SO USE OUR PPN INSTEAD
EXCH T2,T4 ;SENDS0 WANTS PPN IN T4, AND
PUSHJ P,SENDS0 ; T2 POINTING TO MESSAGE
JFCL ;IGNORE PROBLEMS
POP P,T2 ;GET BACK MESSAGE ADDRESS
HLRZ T1,(T2) ;LENGTH IN T1
HRRZS T2 ;JUST ADDRESS
PUSHJ P,GVFWDS## ;RETURN THE FREECORE
JRST JPOPJ##
SUBTTL QUEUE. UUO - UUO TO SEND A MESSAGE TO A GALAXY COMPONENT
;UUO TO SEND A MESSAGE TO A GALAXY COMPONENT AND OPTIONALLY WAIT FOR A RESPONSE
;CALLING SEQUENCE:
; MOVE AC,[LENGTH,,ADDRESS]
; QUEUE. AC,
; ERROR RETURN
; NORMAL RETURN
;ERROR RETURNS FROM THE QUEUE. UUO
QUIAL%==1
QUILF%==2
QUNFS%==3
QUADC%==4
QUCNR%==5
QUFER%==6
QUSOC%==7
QUNPV%==10
QUTMO%==11
ERCODE QUEIAL,QUIAL% ;ILLEGAL ARGUMENT LIST
ERCODE QUEILF,QUILF% ;ILLEGAL FUNCTION
ERCODE QUENFS,QUNFS% ;NO MONITOR FREE CORE
ERCODE QUEADC,QUADC% ;ADDRESS CHECK
ERCODE QUECNR,QUCNR% ;COMPONENT NOT RUNNING - NO SYSTEM PID
ERCODE QUEFER,QUFER% ;FATAL ERROR RETURNED FROM COMPONENT
ERCODE QUESOC,QUSOC% ;SOMEONE IS CONFUSED (INVALID MESSAGE FROM COMPONENT)
ERCODE QUENPV,QUNPV% ;ASKING FOR PRIVS BUT ISN'T PRIVILEGED
ERCODE QUETMO,QUTMO% ;TIMEOUT LIMIT EXPIRED
GLXINF::PUSHJ P,SAVE4##
FRAME GLXPID ;DESTINATION PID TO USE (.QUPID)
HLRZ P1,T1 ;GET UUO BLOCK LENGTH
CAIGE P1,3 ;MUST BE AT LEAST ONE REAL ARGUMENT
JRST QUEIAL ;ILLEGAL ARGUMENTS
HRRI M,(T1) ;POINT TO FLAG WORD
PUSHJ P,GETWRD## ;GET IT
JRST QUEADC ;ADDRESS CHECK
TLNE T1,<(QU.LFB^!QU.FLG)>;ANY UNDEFINED FLAG BITS ON?
JRST QUEIAL ;YES, ILLEGAL ARGUMENT LIST
TLNN T1,(QU.HLN) ;HEADER LENGTH GIVEN?
TLO T1,3 ;NO, USE DEFAULT
LDB P2,[POINT 6,T1,17] ;GET HEADER LENGTH
CAIG P2,5 ;IF OUT OF RANGE,
CAIGE P1,2(P2) ;OR NOT AT LEAST TWO REAL ARGS,
JRST QUEIAL ;IS ILLEGAL ARGUMENT LIST
TLNE T1,(QU.PRP) ;PRIVILEGED ASKING FOR PRIVILEGES?
PUSHJ P,PRVJC## ;YES, THEN MUST BE PRIVILEGED
SKIPA U,T1 ;PRIV'D OR NOT ASKING FOR THEM
JRST QUENPV ;NOT PRIV'D
HRRES T1 ;GET FUNCTION CODE
JUMPE T1,QUEILF ;ZERO IS ILLEGAL
CAML T1,[.GTQFC##-.GTQFT##] ;CUSTOMER FUNCTION?
CAILE T1,QUTBLN## ;DEC FUNCTION?
JRST QUEILF ;NO TO EITHER
;VALIDATE AND SAVE NODE NAME HERE
SETZ W, ;IN CASE NOT PRESENT
CAIGE P2,2 ;NODE ARGUMENT GIVEN?
JRST GLXI99 ;NO, SKIP IT
PUSHJ P,GETWR1## ;GET NODE NUMBER OR NAME
JRST QUEADC ;ADDRESS CHECK
IFN FTNET,<
SKIPN T2,T1 ;COPY NODE NUMBER/NAME
MOVE T1,JBTLOC## ;AND LOCAL STATION
CAMN T2,[-1] ;WANT LOCATED STATION?
MOVE T1,JBTLOC##(J) ;YES
PUSHJ P,[NETDBJ ;VALIDATE (COULD BE A NAME)
JRST NODE.S##]
SKIPA W,T1 ;MAYBE AN OFFLINE NODE
JRST [HLRZ W,NDBSNM##(W) ;POINT TO NDB FOR STATION
MOVE W,(W) ;TRANSLATE STATION NUMBER TO NAME
JRST .+1] ;AND CONTINUE
> ;END FTNET
GLXI99: S0PSHJ INWAT## ;WAIT FOR INPUT TO STOP
;GET LENGTH,,ADDRESS OF RESPONSE BUFFER AND MAKE SURE ITS IN CORE
CAIGE P2,3 ;RESPONSE BUFFER PRESENT?
JRST [JUMPL U,QUEIAL ;NO, BUT REQUESTED
SETZ P4, ;NO, REMEMBER THAT
JRST GLXI98] ;AND SKIP THE FETCH
PUSHJ P,GETWR1## ;GET RESPONSE BUFFER POINTER
JRST QUEADC ;ADDRESS CHECK
MOVE P4,T1 ;SAVE FOR LATER
JUMPGE U,GLXI98 ;SKIP RSP BFR ADDR CHECK IF NO RESPONSE WANTED
HLRZ T2,T1 ;GET LENGTH IN T2
HRLI T1,(IFIW) ;ADDRESS IN T1
PUSHJ P,ARNGE## ;RANGE CHECK
JRST QUEADC ;ADDRESS CHECK
JFCL ;OK IF NOT I/O LEGAL
GLXI98: CAIGE P2,4 ;TIMEOUT VALUE PRESENT?
JRST GLXI97 ;NO, DON'T FETCH IT
PUSHJ P,GETWR1## ;YES, GET IT
JRST QUEADC ;ADDRESS CHECK
TDNE T1,[^-QU.TIM] ;ANY RESERVED BITS ON?
JRST QUEIAL ;YES, ERROR
HRL P1,T1 ;SAVE TIMEOUT VALUE
CAIGE P2,5 ;DESTINATION PID PRESENT?
JRST GLXI97 ;NO, DON'T FETCH IT
PUSHJ P,GETWR1## ;YES, GET IT
JRST QUEADC ;ADDRESS CHECK
JUMPN T1,GLXI96 ;GO WITH IT IF WE HAVE IT
GLXI97: HRRE T1,U ;NO, GET FUNCTION AGAIN
HRRZ T1,.GTQFT##(T1) ;GET ADDRESS OF ASSOCIATED PID
JUMPE T1,QUEILF ;ILLEGAL FUNCTION IF NO MATCHING PID
SKIPN T1,(T1) ;DOES IT EXIST?
JRST QUECNR ;COMPONENT NOT RUNNING
GLXI96: MOVEM T1,GLXPID ;SAVE THE DESTINATION PID
;HERE TO SCAN THE ARGUMENT LIST MAKING SURE ITS IN CORE AND DETERMINING
; THE NUMBER OF WORDS OF CORE NECESSARY FOR BUILDING THE GALAXY MESSAGE
GLXIN0: MOVNS P2 ;-VE HEADER LENGTH
ADDI P2,(P1) ;COUNT OF ARGUMENT WORDS
MOVEI P3,QUESDL ;5 WORD GALAXY HEADER, 2 WORD FUNCTION BLOCK
; 2 WORDS FOR OPR, 3 WORDS FOR USER'S NAME,
; ACTSTL + 1 FOR ACCOUNT STRING
GLXIN1: PUSHJ P,NXTARG
JRST GLXIN2
LDB T2,[POINT 9,T1,17] ;LENGTH OF THE ARGUMENT
ADDI P3,1(T2) ;LENGTH OF DATA BLOCK + 1 FOR HEADER WORD
JRST GLXIN1 ;LOOP BACK
;HERE TO ALLOCATE THE CORE TO BUILD THE MESSAGE
GLXIN2: MOVE T2,P3
CAIG T2,PAGSIZ-2
PUSHJ P,GTFWDC##
JRST QUENFS
;HERE TO BUILD GALAXY HEADER BLOCK, NODE, AND ACCOUNT STRING BLOCKS
HRL P3,T1 ;SAVE ADDRESS OF THE FREE CORE
HRLZ T2,P3
HRRI T2,.IPCGM ;FUNCTION IS GALAXY MESSAGE
MOVEM T2,QUELNH(T1) ;LENGTH OF THE ENTIRE BLOCK,,GALAXY FUNCTION
HRRZ T2,U ;FUNCTION
TLNE U,(QU.PRP) ;PRIVILEGED?
TLNN U,(QU.NBR) ;ASKING NOT TO BLOCK?
CAIA ;NO, BLOCK
CAIE T2,%QWTO##-.GTQFT## ;WTO IS THE ONLY NON-BLOCKING FUNCTION NOW
CAIN T2,%QWTOR##-.GTQFT## ;WTOR?, IF SO DON'T ASK FOR AN ACK
TDZA T2,T2 ;YES, DON'T REQUEST AN ACK
MOVSI T2,(1B0) ;NO, REQUEST AN ACK
MOVEM T2,QUEFLG(T1)
HRLZ T2,%CNIPS## ;SEQUENCE NUMBER
HRR T2,J ;JOB NUMBER OF REQUESTOR
MOVEM T2,QUEJOB(T1) ;STORE FOR ACKNOLEGMENT
HLRZM P1,QUEMBZ(T1) ;SAVE TIMEOUT VALUE FOR A WHILE
MOVEI T2,QUEIGL ;SET INITIAL ARGUMENT COUNT TO
MOVEM T2,QUEARC(T1) ; THE NUMBER OF INTERNAL BLOCKS GENERATED
MOVE T2,[QUEFCL,,.WTUFC] ;FUNCTION BLOCK
MOVEM T2,QUEFCH(T1) ;STORE THAT
HRRZM U,QUEFCN(T1) ;USER SUPPLIED FUNCTION CODE
MOVE T2,[QUEONL,,.WTDES] ;OPERATOR BLOCK
MOVEM T2,QUEONH(T1)
MOVEM W,QUEONN(T1) ;OPERATOR NODE NAME
PUSHJ P,FNDPDS## ;FIND THE PDB
HLRZ T2,QUEJOB(T1)
HRRM T2,.PDQSN##(W)
MOVE T2,[QUEUNL,,.WTNAM]
MOVEM T2,QUEUNH(T1)
MOVE T2,.PDNM1##(W)
MOVE T3,.PDNM2##(W)
DMOVEM T2,QUEUSN(T1)
MOVE T2,[QUEACL,,.WTACT]
MOVEM T2,QUEACH(T1) ;ACCOUNT STRING BLOCK
MOVEI T2,ACTSTL##
JUMPE T2,GLXIN3
MOVSI T2,.PDACS##(W) ;ADDRESS OF THE ACCOUNT STRING
HRRI T2,QUEACS(T1) ;WHERE TO STORE IT IN THE MESSAGE
BLT T2,QUEACS+ACTSTL-1(T1) ;COPY THE ACCOUNT STRING
;HERE TO COPY THE USERS ARGUMENT LIST TO THE GALAXY MESSAGE
GLXIN3: PUSHJ P,GETTAC## ;GET BACK THE POINTER TO USERS ARGUMENT LIST
HRRI M,-1(T1) ;ADDRESS - 1 OF FIRST WORD
LDB P2,[POINT 6,U,17] ;GET HEADER LENGTH
ADDI M,(P2) ;ADDRESS -1 OF FIRST ARGUMENT WORD
MOVNS P2 ;-VE NUMBER OF HEADER WORDS
ADDI P2,(P1) ;NUMBER OF ARGUMENT WORDS
HLRZ T1,P3 ;GET MESSAGE ADDRESS
MOVEI P1,QUESDL(T1) ;WHERE TO STORE ARGUMENTS
GLXIN4: PUSHJ P,NXTARG ;NEXT ARGUMENT
JRST GLXIN7 ;PROCESSED ALL ARGUMENTS
HLRZ T3,P3 ;GET MESSAGE ADDRESS
AOS QUEARC(T3) ;COUNT THE BLOCK ABOUT TO BE ADDED
LDB T3,[POINT 9,T1,17] ;LENGTH OF THE DATA BLOCK
HRRZ T4,T1 ;FUNCTION
HRLI T4,1(T3) ;LENGTH,,FUNCTION
MOVEM T4,(P1) ;STORE THAT
AOS P1 ;WHERE TO STORE DATA
GLXIN5: EXCTUX <MOVE T4,@T2> ;GET DATA
MOVEM T4,(P1) ;STORE DATA IN THE MESSAGE
SKIPL T1 ;IMMEDIATE ARGUMENT?
AOJA T2,GLXIN6 ;NO--ADVANCE TO NEXT WORD OF DATA
HRRI T2,1(T2) ;IMMEDIATE ARGS CAN'T CROSS SECTION BOUNDRIES
GLXIN6: SOSLE T3 ;MOVED ALL DATA ITEMS?
AOJA P1,GLXIN5 ;NO, GET THE NEXT ONE
AOJA P1,GLXIN4 ;GET NEXT ARGUMENT
;HERE TO SEND THE MESSAGE TO THE APPROPRIATE GALAXY COMPONENT
GLXIN7: MOVEI T1,GLXPID ;ADDRESS OF DESTINATON PID
HRLI T1,40 ;FROM [SYSTEM] GOPHER
MOVS T2,P3 ;LENGTH,,ADDRESS OF MESSAGE
PUSH P,T2
MOVE T3,PIDTAB##+1
ADDI T3,1
MOVE T4,JBTPPN##(J)
SSXE T2,0 ;EXTENDED ADDRESSING HACK
MOVE P2,QUEMBZ(T2) ;GET TIMEOUT LENGTH
SETZM QUEMBZ(T2) ;MUST BE ZERO FOR GALAXY
TLNE U,(QU.NBR) ;WANT NON-BLOCKING?
JRST [
IFN FTXMON,<
MOVE T2,(P) ;RECOVER XWD
>
PUSHJ P,SENDS0 ;YES, SEND AND DON'T WAIT FOR A RESPONSE
JRST [PUSHJ P,QUECNR
JRST SNDFFR]
AOS -1(P)
JRST SNDFFR]
MOVE T2,QUEJOB(T2) ;GET SEQUENCE NUMBER IN LH
HRR T2,P2 ;AND TIMEOUT LIMIT
PUSHJ P,GFRTMO ;SET UP A TIMEOUT CLOCK REQUEST
POP P,T2 ;GET PACKET POINTER BACK FROM STACK
PUSHJ P,SENDSP
JRST QUECNR
;HERE TO GIVE THE USER THE RESPONSE IF HE WANTS ONE
HLRZ T2,.PDEPA##(W) ;** IT'S OK TO USE .PDEPA HERE
JUMPE T2,QUETMO ;TIMEOUT FAILURE
PUSHJ P,GFRCLN ;CLEANUP AFTER QUEUE. UUO TIMEOUT
MOVE T1,.IPCFD+1(T2)
TLNE T1,100000
JRST [PUSHJ P,QUEFER
JRST .+2] ;ERROR RETURN BUT GIVE USER RESPONSE
AOS (P)
SKIPL U ;USER WANT A RESPONSE?
JRST GLXI12 ;NO, TOSS THE ACK OR RESPONSE
TLNE T1,200000 ;ACK OR RESPONSE?
JRST [SETZB P2,P3 ;ACK, SO INDICATE ZERO LENGTH RESPONSE
JRST GLXI10]
HRRZ T1,.IPCFD+4(T2)
MOVEI T2,.IPCFD+5(T2)
GLXIN8: HRRZ T3,(T2)
CAIN T3,.CMTXT
JRST GLXIN9
HLRZ T3,(T2)
ADD T2,T3
SOJG T1,GLXIN8
PUSHJ P,QUESOC
JRST GLXI12
GLXIN9: MOVEI P1,1(T2) ;ADDRESS OF ACTUAL RESPONSE
HLRZ P2,(T2) ;TOTAL LENGTH OF RETURNED RESPONSE
SUBI P2,1 ;OFFSET FOR GALAXY BLOCK HEADER
HLRZ P3,P4
GLXI10: MOVE T1,P2 ;LENGTH OF THE RESPONSE
CAMLE P2,P3
TRO T1,WT.RWT
TRO T1,WT.RBR ;INDICATE RESPONSE BLOCK
PUSHJ P,STOTAC## ;STORE RESPONSE LENGTH PLUS POSSIBLE TRUNCATED BIT
JUMPE P2,GLXI12
HRRI M,-1(P4)
GLXI11: MOVE T1,(P1)
PUSHJ P,PUTWD1##
AOS P1
SOSLE P2
SOJG P3,GLXI11
GLXI12: HLRZ T2,.PDEPA##(W)
LDB T1,PKLNT2
ADDI T1,.IPCFD
PJRST GIVWDS##
;RETURNS T1 = ARGUMENT <I>B0+<LENGTH>B17+<TYPE>B35, T2 = ADDRESS OF DATA
; UNDEFINED BITS MUST BE ZERO
NXTARG: SOJL P2,CPOPJ## ;COUNT WORD PAIRS
PUSHJ P,GETWR1## ;GET .QUARG WORD (IMMEDIATE/LENGTH/TYPE)
JRST NXTAD1 ;QUEADC, BUT POP STACK BY ONE.
TLNN T1,777 ;WORD COUNT SPECIFIED?
TLO T1,1 ;NO--DEFAULT TO ONE
HLRZ T2,T1 ;NUMBER OF WORDS OF ARGUMENT IS IN LEFT HALF
ANDI T2,777 ;STRIP OFF ANY FLAGS THERE MIGHT BE
TLNN T1,377000 ;ANY ILLEGAL BITS TURNED ON?
CAIGE T2,1 ;REASONABLE LENGTH?
JRST NXTIAL ;ILLEGAL ARGUMENT
PUSH P,T1 ;SAVE ON STACK
HRRI M,1(M) ;ADVANCE UUO POINTER (DON'T CROSS SECTIONS)
MOVE T1,M ;GET .QUARV WORD (ADDRESS)
TLZ T1,-1-MXSECN ;STRIP OFF ALL BUT SECTION,,ADDRESS
SKIPL (P) ;IMMEDIATE ARGUMENT?
JRST NXTAR1 ;NO
HRLI T1,(IFIW) ;ALWAYS USE LOCAL ADDRESS
JRST NXTAR2 ;ONLY NEED TO DO ADDRESS CHECKING
NXTAR1: PUSHJ P,EACALC## ;DO EA CALC (T1 GETS NEW ADDR, T2 IS SAVED)
JRST NXTAD2 ;ILLEGAL ADDRESS REFERENCE
NXTAR2: PUSHJ P,ARNGE## ;RANGE CHECK
JRST NXTAD2 ;ADDRESS CHECK
JFCL ;OK IF NOT I/O LEGAL
SKIPL (P) ;IMMEDIATE ARGUMENT?
MOVEI T2,1 ;NO--TWO WORD PAIRS
SUBI P2,(T2) ;ACCOUNT FOR ARGS IN UUO BLOCK
ADD T2,M ;POINT PAST CURRENT ARGUMENT
HRRI M,-1(T2) ;DON'T CROSS SECTION BOUNDRIES
MOVE T2,T1 ;T2 GETS ADDRESS
JRST TPOPJ1## ;RETURN WITH WORD COUNT/FUNCTION IN T1
NXTIAL: POP P,(P) ;POP CALL TO NXTARG
PJRST QUEIAL ; AND GIVE "ILLEGAL ARGUMENT" ERROR
NXTAD2: POP P,(P) ;POP CALL TO NXTARG
NXTAD1: POP P,(P) ; POP AN AC
PJRST QUEADC ; AND GIVE "ADDRESS CHECK" ERROR
;HERE ON LOGOUT UUO. LOGOUT MESSAGE IS SENT TO QUASAR IF %SIQSR
; CONTAINS A VALID PID.
QSRLGO: PUSHJ P,SETLMG ;SETUP THE MESSAGE
PUSH P,T4 ;SAVE MESSAGE ADDRESS
MOVEI T1,%SIOPR## ;PID OF [SYSTEM]OPERATOR-CONTROLLER
MOVE T2,(P) ;POINT TO PACKET
PUSHJ P,SENDSI ;SEND IT OFF
JFCL ;IGNORE ERRORS
MOVEI T1,%SIQSR## ;PID OF [SYSTEM]QUASAR
MOVE T2,(P) ;POINT TO PACKET
PUSHJ P,SENDSI ;SEND MESSAGE
JFCL ;IGNORE ERRORS
MOVE T1,JBTPRG##(J) ;GET PROGRAM NAME
CAME T1,LGINAM## ;RUNNING LOGIN?
CAMN T1,LGONAM## ; OR LOGOUT?
TRNA ;YES--PROCEED
PJRST SNDFFR ;NO--RELEASE CODE AND RETURN
CAMN J,ACTJOB## ;IS IT THE ACCOUNTING DAEMON?
PJRST SNDFFR ;YES--RELEASE CORE AND RETURN
MOVE T1,[40,,%SIACT##]
MOVE T2,(P) ;GET PACKET
MOVE T3,PIDTAB##+1
ADDI T3,1
MOVE T4,JBTPPN##(J)
PUSHJ P,SENDSP ;SEND TO ACTDAE, WAIT FOR RESPONSE
JRST SNDFFR
HLRZ T2,.PDEPA(W)
LDB T1,PKLNT2
ADDI T1,.IPCFD
SKIPE T2
PUSHJ P,GIVWDS##
JRST SNDFFR
;HERE ON LOGIN UUO TO SEND MESSAGE TO QUASAR
QSRLGI::SE1ENT ;ENTER SECTION 1
MOVSI T1,LOMSIZ ;SIZE OF MESSAGE
HRRI T1,IPCFON-IPCFTB+1 ;CODE
PUSHJ P,SETQSR ;SETUP THE MESSAGE
DMOVE T1,.PDNM1##(W) ;GET USER NAME
DMOVEM T1,LOMUSR(T4) ;STORE
PUSH P,F
PUSH P,T4
MOVE F,TTYTAB##(J)
PUSHJ P,CTLJBD##
POP P,T4
MOVEM T1,LOMCTL(T4)
MOVE T1,DEVNAM(F)
MOVEM T1,LOMTTY(T4)
POP P,F
SNDQSR: MOVEI T1,%SIQSR##
PJRST SNDFFC ;AND SEND MESSAGE TO QUASAR
;SNDSCM -- ROUTINE TO SEND A SCHEDULE BITS CHANGE MSG TO QUASAR.
; NO ARGS
SNDSCM::SE1ENT ;ENTER SECTION 1
MOVEI T2,SCMSIZ ;GET NUMBER OF WORDS NEEDED
PUSHJ P,GETWDS##
POPJ P, ;FAILED
MOVE T2,[XWD SCMSIZ,IPCSCM-IPCFTB+1]
MOVEM T2,(T1) ;STORE LEN,,FUNCTION CODE
HRLI T1,SCMSIZ ;SETUP LEN,,MSG ADDR FOR SNDMDX
PUSH P,T1
MOVEI T1,%SIQSR## ;GET QUASAR'S PID ADDRESS
PJRST SNDMDX ;SEND THE MESSAGE
;SETQSR -- ROUTINE TO SETUP A PACKET TO SEND TO QUASAR. CALL
; WITH T1 CONTAINING SIZE,,CODE, RETURN QSRMSG BLOCK
; WITH GALMSG AND GALSTS ALL SETUP.
;RETURNS T4=LEN,,ADDR OF MESSAGE
SETLMG: MOVSI T1,LGMSIZ ;SIZE OF MESSAGE
HRRI T1,IPCFLM-IPCFTB+1 ;CODE
; PJRST SETQSR ;SETUP THE MESSAGE
SETQSR: PUSHJ P,SAVJW## ;SAVE J AND W
ANDI J,JOBMSK## ;KEEP ONLY JOB NUMBER
PUSHJ P,FNDPDS## ;POINT W AT THE PDB
PUSH P,T1
HLRZ T2,T1
PUSHJ P,GFWDCD##
STOPCD .,JOB,NCM, ;++NO CORE FOR MESSAGE
MOVE T4,T1
POP P,GALMSG(T4)
; HLL T4,GALMSG(T4)
HRLZ T1,J ;GET JOB,,0
LDB T2,PDYBSN## ;GET BATCH STREAM NUMBER
LSH T2,^D27 ;SHIFT OVER
IOR T1,T2 ; OR IT IN
MOVSI T2,(JB.BSS) ;GET BATCH STREAM SET BIT
TDNE T2,.PDOBI##(W) ;IS IT ON?
TRO T1,GALBSS ;YES-TELL QUASAR
IFN FTNET,<
HRRZ T2,JBTLOC##(J) ;GET HIS LOCATION
LSH T2,^D9 ;SHIFT OVER 9 BITS
IOR T1,T2 ;OR IT IN
> ;END IFN FTNET
MOVSI T2,(JB.LBT) ;GET BATCH BIT
TDNE T2,JBTLIM##(J) ;IS HE A BATCH JOB?
TRO T1,GALBAT ;YES, SET THE FLAG
MOVEI T2,JB.DFR ;GET DEFERED BIT
TDNE T2,JBTSPL##(J) ;TEST IT
TRO T1,GALDFR ;ITS ON
MOVEM T1,GALSTS(T4) ;AND STORE 2ND DATA WORD
HLL T4,GALMSG(T4) ;COPY LENGTH
TLO T4,(IFIW) ;LIGHT CROCKY BIT
POPJ P, ;AND RETURN
IFN FTMDA,<
;SUBROUTINE TO SEND THE CONTENTS OF T1 AND T2 TO [SYSTEM]MDC
;CALLING SEQUENCE: (MAY BE CALLED AT INTERRUPT LEVEL)
; MOVE T1,UNIT NAME
; MOVEI T2,DEVICE TYPE
; PUSHJ P,SNDMDC
;RETURNS CPOPJ IF THE MESSAGE COULDN'T BE SENT, CPOPJ1 IF OK
LEN.UO==3 ;LENGTH OF MSG
SNDMDC::SE1ENT ;ENTER SECTION 1
PUSH P,T1 ;SAVE ARGUMENTS
PUSH P,T2
MOVEI T2,LEN.UO ;GET THREE WORDS OF FREE STORAGE
PUSHJ P,GETWDS##
JRST [POP P,T2 ;FAIL
JRST TPOPJ##]
MOVE T2,[XWD LEN.UO,.IPCUO]
MOVEM T2,(T1)
POP P,T2 ;DEVICE TYPE
MOVEM T2,2(T1)
POP P,1(T1) ;UNIT NAME
HRLI T1,LEN.UO ;LENGTH OF BLOCK
PUSH P,T1 ;SAVE LEN,,ADDR
MOVEI T1,%SIDOL## ;ASSUME DISK
CAIE T2,.TYDSK ;TRUE?
MOVEI T1,%SITOL## ;NO, SEND IT TO PULSAR
>
;HERE WITH ADDR OF RECVR PID IN T1
;LEN,,MSG ADDRS IN 0(P)
;ALWAYS RETURNS
;LEN WORDS AT ADDR
SNDMDX::MOVE T2,(P) ;GET ADDR OF MESSAGE AGAIN
PUSH P,J ;SAVE J
PUSH P,W ;SAVE W
SETZB J,T4 ;JOB NUMBER AND PPN OF SENDER ARE ZERO
PUSHJ P,SENDS0 ;SEND THE MESSAGE
SOS -3(P) ;FAILED
POP P,W ;RESTORE W
POP P,J ;RESTORE J
POP P,T2 ;AND FREE CORE ADDRESS
HLRZ T1,T2 ;GET # OF WORDS TO RETURN
HRRZS T2 ;CLEAR LH OF GIVWDS
AOS (P) ;SKIP RETURN IF SUCCESSFUL
PJRST GIVWDS## ;RETURN FREE CORE
IFN FTMDA,<
;ROUTINE TO SEND A MESSAGE TO MDA WHEN A CONTROLLED DEVICE
; HAS BEEN REASSIGNED
;CALL: F-DDB ADDRESS
; J-JOB NUMBER
;RETURNS-CPOPJ IF MESSAGE NOT SENT
; CPOPJ1 IF OK
LEN.DE==4 ;MINIMUM LENGTH OF DEASSIGN MESSAGE
SNDFIN::TDZA T1,T1 ;NO FLAG FOR DEASSIGN
SNDVSS::MOVSI T1,400000 ;GET FLAG INDICATING VOL SWITCH
MOVEI T2,LEN.DE ;ASSUME UNINTERESTING DEVICE
MOVEI T3,0 ;AND NO DATA
LDB T4,PDVTYP## ;GET DEVICE TYPE
CAIE T4,.TYDTA ;DECTAPE?
JRST SNDFI1 ;NO
MOVEI T2,LEN.DE+2 ;STANDARD LENGTH PLUS DATA WORDS
MOVEI T3,DTXWRD##(F) ;POINT TO START OF DTA DATA
HRLI T3,-2 ;TWO WORDS
JRST SNDFI2 ;JOIN COMMON CODE
SNDFI1: CAIE T4,.TYMTA ;MAGTAPE?
JRST SNDFI2 ;NO
MOVEI T2,LEN.DE+6 ;STANDARD LENGTH PLUS DATA WORDS
MOVE T3,TDVUDB##(F) ;UDB ADDRESS
MOVEI T3,TUBCRD##(T3) ;POINT TO START OF UDB DATA QUASAR NEEDS
HRLI T3,-6 ;SIX WORDS LONG
SNDFI2: PUSH P,T2 ;SAVE LENGTH
PUSH P,T3 ;SAVE AOBJN POINTER
HLL T4,T1 ;GET FLAG SO MDA KNOWS WHAT TO DO WITH STATS
PUSH P,T4 ;SAVE FLAG,,DEVICE TYPE
PUSHJ P,GETWDS## ;GET CORE
JRST [POP P,T4
POP P,T3
JRST T2POPJ##]
LDB T2,PJOBN## ;GET JOB NUMBER
MOVEM T2,3(T1) ;SAVE IT
POP P,2(T1) ;DEVICE TYPE
MOVE T2,DEVNAM(F) ;GET DEVICE NAME
MOVEM T2,1(T1) ;SAVE IT
POP P,T3 ;GET AOBJN POINTER
POP P,T2 ;GET MESSAGE LENGTH
HRLZS T2 ;LH=LENGTH
HRRI T2,.IPCDE ;RH=IPCF FUNCTION
MOVEM T2,0(T1) ;MESSAGE CODE
JUMPGE T3,SNDFI4 ;JUMP IF NO DATA TO STORE
MOVE T4,T1 ;COPY MESSAGE ADDRESS
SNDFI3: MOVE T2,(T3) ;GET A WORD
MOVEM T2,4(T4) ;PUT A WORD
ADDI T4,1 ;POINT TO NEXT LOC
AOBJN T3,SNDFI3 ;LOOP
SNDFI4: HLL T1,(T1) ;GET LENGTH FROM MESSAGE
;HERE WITH LEN,,ADRS OF MESSAGE IN T1
;TO SEND MESSAGE TO MDA, AND RETURN FREE
;CORE USED BY THE MESSAGE
SNDF.1: SE1ENT ;ENTER SECTION 1
PUSH P,T1 ;SAVE SO WE CAN RETURN IT
MOVEI T1,%SIMDA## ;WHO TO SEND TO
PJRST SNDMDX ;SEND IT OFF, RETURN THE CORE
>;END IFN FTMDA
;HERE WHEN A T/S JOB WHICH OWNS LOCKED FILE
;STRUCTURES DOES A RESET. MDA WILL GET MESSAGE
;WITH RESET'S JOB NUMBER.
;CALL - J - JOB #
;RETURNS-
; POPJ - NO MDA
; CPOPJ1 - SENT
IFN FTMDA,<
LEN.RS==2 ;LENGTH OF RESET MESSAGE
SNDMDR::MOVEI T2,LEN.RS ;GET MESSAGE LENGTH
PUSHJ P,GETWDS## ;GET THAT MUCH SPACE
POPJ P, ;CAN'T, GIVE UP
MOVE T2,[XWD LEN.RS,.IPCRL] ;HEADER WORD
MOVEM T2,0(T1) ;MARK THE MESSAGE
MOVEM J,1(T1) ;SAY WHO'S RESETTING
HRLI T1,LEN.RS ;COUNT THE FREE SPACE
PJRST SNDF.1 ;SEND IT OFF!
> ;END IFN FTMDA
IFN FTMDA,<
;HERE WHEN A JOB CHANGES ITS SEARCH LIST
;MDA WILL GET A COPY OF THE NEW LIST
;CALL -
; T1, ADDR OF MESSAGE (IN FREE CORE)
; T2, LEN OF MESSAGE SPACE
;RETURNS
; POPJ NO MDA
; CPOPJ1 SENT
;NOTE: THE SPACE OCCUPIED BY THE MESSAGE IS ALWAYS RETURNED
SNDMDN::HRLI T1,(T2) ;COUNT THE BLOCK
PJRST SNDF.1 ;SEND IT
>;END IFN FTMDA
IFN FTMDA,<
LEN.AT==4 ;LENGTH OF ATTACH MSG
LEN.DT==4 ;LENGTH OF DETACH MSG
;ATTMPA - NOTIFY MDA OF PORT ATTACHMENT
;CALL: MOVE T1, PRIMARY PORT NAME
; MOVE T2, SECONDARY PORT NAME
; MOVE U, UDB JUST ATTACHED
; PUSHJ P,ATTMPA
; <RETURN>
ATTMPA::SKIPE DINITF## ;SYSTEM INITIALIZATION?
POPJ P, ;NO ONE TO INFORM
PUSH P,T1 ;SAVE PRIMARY PORT NAME
PUSH P,T2 ;SAVE SECONDARY PORT NAME
MOVEI T2,LEN.AT ;LENGTH OF ATT/DET MSG
PUSHJ P,GETWDS## ;GET SOME SPACE
JRST [POP P,T2
JRST TPOPJ##]
MOVE T2,[XWD LEN.AT,.IPCAT] ;LEN,,MSG TYPE
MOVEM T2,0(T1) ;MARK THE HEADER
MOVE T2,UDBNAM(U) ;GET ATTACHED PORT NAME
MOVEM T2,1(T1) ;PUT IN MESSAGE
POP P,3(T1) ;STORE SECONDARY PORT NAME
POP P,2(T1) ;STORE PRIMARY PORT NAME
HRLI T1,LEN.AT ;COUNT THE BLOCK
ATTMP1: PUSHJ P,SNDF.1 ;SEND IT OFF
JFCL ;CAN'T? OH WELL
POPJ P,
;DETMPA - NOTIFY MDA OF PORT DETACH
; U/ UDB JUST DETACHED
; T1/SIXBIT NEW PRIMARY UNIT (PERHAPS 0)
; RETURN CPOPJ ALWAYS
DETMPA::PUSH P,T1 ;SAVE NEW PRIMARY
MOVEI T2,LEN.DT ;LENGTH OF MSG
PUSHJ P,GETWDS## ;GET A MESSAGE BLOCK
JRST TPOPJ## ;OH WELL
MOVE T2,[XWD LEN.DT,.IPCDT] ;LEN,,MSG TYPE
MOVEM T2,0(T1) ;MARK HEADER
MOVE T2,UDBNAM(U) ;DETACHED UNIT NAME
MOVEM T2,1(T1) ;THAT'S 1ST ITEM
POP P,2(T1) ;NEW PRIMARY OR ZERO
SETZM 3(T1) ;NO SECONDARY PORT NOW
HRLI T1,LEN.DT ;COUNT THE MSG
PJRST ATTMP1 ;SEND IT
;XCHMPA - NOTIFY MDA OF DISK UNIT EXCHANGE
; P1 / FIRST UDB ADDRESS
; U / SECOND UDB ADDRESS
; RETURN CPOPJ ALWAYS
LEN.XC==3
XCHMPA::MOVEI T2,LEN.XC ;GET MSG LENGTH
PUSHJ P,GETWDS## ;GET SOME CORE
POPJ P, ;CANT
MOVE T2,[LEN.XC,,.IPCXC] ;LEN,,MSG TYPE
MOVEM T2,0(T1) ;STORE IT
MOVE T2,UDBNAM(P1) ;GET FIRST UNIT NAME
MOVEM T2,1(T1) ;STORE IT
MOVE T2,UDBNAM(U) ;GET SECOND UNIT NAME
MOVEM T2,2(T1) ;STORE IT
HRLI T1,LEN.XC ;COUNT THE MSG
PJRST ATTMP1 ;SEND MSG AND RETURN
;REMMPA - NOTIFY MDA OF A STRUCTURE REMOVAL
; F / STR D.B.
; RETURN CPOPJ ALWAYS
LEN.RM==2
REMMPA::MOVEI T2,LEN.RM ;GET MSG LENGTH
PUSHJ P,GETWDS## ;GET SOME CORE
POPJ P, ;CAN'T
MOVE T2,[LEN.RM,,.IPCRM] ;LEN,,MSGTYPE
MOVEM T2,0(T1) ;STORE IT
MOVE T2,STRNAM##(F) ;GET STR NAME
MOVEM T2,1(T1) ;STORE IT
HRLI T1,LEN.RM ;COUNT THE MSG
PJRST ATTMP1 ;SEND MSG AND RETURN
;STRMPA - NOTIFY MDA OF A STRUCTURE MOUNT
; F / STR D.B.
; RETURN CPOPJ ALWAYS
STRMPA::PUSHJ P,SAVE1## ;NEED A PRESERVED AC
MOVEI P1,1+1+1 ;NEED ONE OVERHEAD WORD + 1 FOR STR NAME + 1 FOR UNIT
HLRZ T1,STRUNI##(F) ;PICK UP FIRST UNIT IN STR
STRMP1: HLRZ T1,UNISTR(T1) ;FIND NEXT UNIT
SKIPE T1 ;END OF CHAIN?
AOJA P1,STRMP1 ;NOT YET
MOVE T2,P1 ;GET NUMBER OF WORDS NEEDED
PUSHJ P,GETWDS## ;GET SOME CORE
POPJ P, ;CAN'T
MOVEI T3,.IPCST ;FUNCTION CODE
HRLI T3,(P1) ;LENGTH
MOVEM T3,0(T1) ;STORE IT
MOVE T3,STRNAM##(F) ;GET STR NAME
MOVEM T3,1(T1) ;STORE IT
MOVSI P1,(P1) ;SAVE [LENGTH,,MESSAGE ADDRESS]
HRR P1,T1
HLRZ T3,STRUNI##(F) ;GET FIRST UDB ADDR
STRMP2: MOVE T2,UDBNAM(T3) ;GET UNIT NAME
MOVEM T2,2(T1) ;SAVE
HLRZ T3,UNISTR(T3) ;GET LINK TO NEXT UDB
SKIPE T3 ;END OF CHAIN?
AOJA T1,STRMP2 ;NOT YET
MOVE T1,P1 ;GET MESSAGE ADDRESS BACK
PJRST ATTMP1 ;SEND IT AND RETURN
>;IFN FTMDA
IFN FTMDA,<
;MTAMPA- NOTIFY MDA OF A NEW MAGTAP UNIT BEING ACCESSIBLE
; F/ MAGTAPE DDB ADDRESS
; RETURN CPOPJ ALWAYS
LEN.MT==2
MTAMPA::MOVEI T2,LEN.MT ;GET MSG LENGTH
PUSHJ P,GETWDS## ;GET CORE
POPJ P, ;CANT
MOVE T2,[LEN.MT,,.IPCMT] ;LEN,,TYPE
MOVEM T2,0(T1) ;SAVE IT
MOVE T2,DEVNAM(F) ;GET DRIVE NAME
MOVEM T2,1(T1) ;SAVE IT
HRLI T1,LEN.MT ;SET LENGTH
PJRST ATTMP1 ;SEND MSG AND RETURN
>;END IFN FTMDA
;SUBROUTINE TO SEND A PACKET TO A PID AND WAIT FOR A RESPONSE
; FROM THE RECEIVER
;CALLING SEQUENCE:
; MOVE T1,["SENT BY",,%SIDXXX]
; OR MOVE T1,RECEIVER'S PID
; MOVE T2,[LENGTH,,ADDRESS]
; MOVE T3,SENDER'S PID
; MOVE T4,SENDER'S PPN
; PUSHJ P,SENDSP ;IF SENDING TO A SPECIAL SYSTEM PROCESS
; OR PUSHJ P,SENDAP ;IF SENDING TO AN ARBITRARY PID
;RETURNS CPOPJ IF THE MESSAGE COULLD NOT BE DELIVERED
; RETURNS CPOPJ1 IF THE MESSAGE WAS SUCCESSFULLLY SENT AND A REPLY
; HAS BEEN RECEIVED. THE POINTER TO THE PACKET RECEIVED IS IN .EPEPA.
; IF THE SIGN BIT OF T2 IS LIT, IT IS THE CALLLER'S RESPONSIBILLITY
; TO RETURN THE PACKET TO MONITOR FREE CORE AFTER PROCESSING ITS CONTENTS
SENDAP::SE1ENT ;ENTER SECTION 1
PUSHJ P,SAVE4##
PUSH P,T2 ;SAVE POINTER
MOVE P4,T3
MOVE P3,T1
MOVE P2,T2
PUSHJ P,VALPID
JRST SENDP3
AND P3,%IPCPM##
ADDI P3,PIDTAB## ;ADDRESS OF THE PID IN PIDTAB
PUSH P,J
PUSH P,W
MOVE J,.CPJOB##
PUSHJ P,SENDS1
JRST SENDP2
JRST SENDP1
SENDSP::SE1ENT ;ENTER SECTION 1
PUSH P,T2
PUSH P,J
PUSH P,W
MOVE J,.CPJOB##
PUSHJ P,SENDS0
JRST SENDP2
SENDP1: SKIPL T2,-2(P) ;ARE WE SUPPOSED TO RETURN THE CORE?
PUSHJ P,SNDFFD ;YES, DO SO
SETOM -2(P) ;DON'T RETURN IT TWICE
MOVE J,.CPJOB##
PUSHJ P,FNDPDS## ;POINT W AT THE PDB
MOVEI T1,EV.IPC
PUSHJ P,ESLEEP##
HRRZ T1,.PDEPA##(W)
JUMPN T1,SENDP1 ;THIS DEPENDS ON A SYSTEM PROCESS NOT SENDING
; TO [SYSTEM]IPCC
AOS -3(P)
SENDP2: POP P,W
POP P,J
SENDP3: SKIPL (P) ;ARE WE SUPPOSED TO RETURN THE CORE?
PJRST SNDFFR ;YES, DO SO
POP P,(P) ;NO, TRIM STACK
POPJ P, ;AND RETURN
;HERE ON RECEIPT OF A MESSAGE SENT TO THE EXEC PSUEDO-PROCESS
; [SYSTEM]GOPHER IF THE INTENDED RECEIVING PROCESS IS BLOCKED WAITING
; FOR A RESPONSE, STORE THE ADDRESS OF THE PACKET IN THE RECEIVER'S
; PDB AND WAKEUP THE RECEIVER. OTHERWISE, RETURN THE PACKET AS
; UNDELIVERABLE.
IPCSPR::PUSHJ P,SAVE1##
IFN FTMP,<
PUSHJ P,ONCPU0## ;ONLY ONE CPU AT A TIME
>
IPCSP1: PUSHJ P,GETPAK
POPJ P,
HRRZ P1,T1
HRRZ T1,.IPCFD(P1)
CAIE T1,.WTORR ;WTOR RESPONSE?
CAIN T1,.OMACK ;OR AN ACK?
JRST [PUSH P,W ;YES, SAVE CURRENT
HRRZ T1,.IPCFD+2(P1) ;GET JOB/CONTEXT HANDLE
PUSHJ P,CTXIPC## ;SET UP J AND W
JRST IPCSP5 ;CAN'T
MOVE T1,W ;COPY
POP P,W ;RESTORE ORIGINAL
HLRZ T2,.IPCFD+2(P1) ;GET SEQUENCE NUMBER
HRRZ T3,.EPQSN(T1) ; AND VALUE AT SEND
CAME T2,T3 ;ONE WE'RE WAITING FOR
JRST IPCSP2 ;NO, PITCH IT
JRST IPCSP3] ;NOW PROCESS IT
IFN FTFDAE,< ;VALIDATE FILDAE SEQUENCE NUMBERS
MOVE T2,.IPCFS(P1) ;FIND OUT WHO SENT THIS MESSAGE
CAME T2,%SIFDA##
JRST IPCSP4 ;NOT THE FILE DAEMON? CONTINUE ONWARD
PUSH P,W ;SAVE CURRENT
HRRZ T1,.IPCFD(P1) ;GET JOB/CONTEXT HANDLE FROM MESSAGE
PUSHJ P,CTXIPC## ;SET UP J AND W
JRST IPCSP5 ;HE MUST HAVE LOGGED OUT
MOVE T1,W ;GET NEW
POP P,W ;RESTORE ORIGINAL
HLRZ T2,.IPCFD(P1) ;GET THE SEQUENCE NUMBER FROM FILDAE
JUMPE T2,IPCSP4 ;ZERO? MUST BE OLD VERSION OF FILDAE
HLRZ T3,.EPQSN(T1) ;GET THE NUMBER WE SAVED BEFORE
CAME T2,T3 ;DO THEY MATCH?
JRST IPCSP2 ;NO, BIT-BUCKET THIS MESSAGE
IPCSP4:
> ;END IFN FTFDAE
PUSH P,W ;SAVE CURRENT
HRRZ T1,.IPCFD(P1) ;GET JOB/CONTEXT HANDLE FROM MESSAGE
PUSHJ P,CTXIPC## ;SET UP J AND W
JRST IPCSP5
MOVE T1,W ;GET NEW
POP P,W ;RESTORE ORIGINAL
IPCSP3: PUSH P,T1 ;SAVE IPC BLOCK
MOVE T1,J ;COPY TARGET JCH
PUSHJ P,CTXSTS## ;GET JBTSTS & JBTST2
JRST IPCSP6 ;ABORT
LDB T3,[POINT ESLPSZ,T2,ESLPBP] ;GET EVENT WAIT REASON
POP P,T1 ;RESTORE IPC BLOCK
MOVE T2,.IPCFS(P1) ;GET SENDER'S ID
CAMN T2,.EPEPA(T1) ;SENDER MATCH?
CAIE T3,EV.IPC ;AND EW WAS FOR IPCF?
JRST IPCSP2 ;NO, PITCH IT
HRLZM P1,.EPEPA(T1) ;SAVE PACKET ADDRESS
SOS .EPIPC(W) ;WE GOT RID OF THE MESSAGE
PUSHJ P,NXTPAK ;MAKE SURE WE DID
MOVE T1,J ;COPY TARGET JCH
PUSHJ P,CTXEWK## ;EWAKE TARGET
JFCL ;(SHOULD SKIP)
PUSHJ P,DECSSW ;CLEAR THE COUNTS (RESPECTING W)
SOS %CNIIP## ;ONE FEWER SYSTEM PACKETS
JRST IPCSP1 ;LOOP FOR ALL GOPHER MESSAGES
IPCSP6: POP P,T1 ;RESTORE IPC BLOCK
IPCSP5: POP P,W ;LIKEWISE
IPCSP2: MOVEI T1,IPCDU% ;DESTINATION UNKNOWN ERROR
DPB T1,RTNERR ;RETURN TO ERRANT SENDER
PUSHJ P,DECSSW ;FIX THE COUNTS
MOVEI T2,4 ;FROM [SYSTEM]GOPHER
PUSHJ P,ANSWE1 ;RESPOND
JRST IPCSP1 ;LOOP OVER QUEUE OF GOPHER MESSAGES
SUBTTL TIMEOUT LOGIC FOR [SYSTEM] GOPHER
;GFRTMO -- ROUTINE TO SET UP A TIME LIMIT FOR A GOPHER RESPONSE
;
;CALL:
; MOVE T2,[QUEUE-SEQUENCE-NUMBER,,TIME-LIMIT-IN-SECONDS]
; PUSHJ P,GFRTMO
;
; RETURN HERE ALWAYS
;
;PRESERVES T1-T4
;
;RETURNS FREECORE ADDRESS USED IN P2
GFRTMO: TRNN T2,-1 ;ANYTHING TO DO?
POPJ P, ;NO, GET OUT
PUSHJ P,SAVT## ;YES, SAVE SOME REGISTERS
SETZ P2, ;NO ADDRESS YET
PUSH P,T2 ;AND THE TIMER VALUE
MOVEI T2,1 ;NEED A WORD
PUSHJ P,GETPKT ;GET SOME CORE
JRST T2POPJ## ;SHOULD NEVER GET HERE
HRRZ T2,(P) ;RESTORE TIME VALUE
IMUL T2,TICSEC## ;CONVERT TO JIFFIES
TLNE T2,-1 ;EXCEED CLOCK SIZE?
MOVEI T2,-1 ;YES, USE MAXIMUM
HRLI T2,GFRABT ;ROUTINE TO CALL AT EXPIRATION
POP P,T3 ;RESTORE SEQUENCE NUMBER
HRR T3,.CPJCH## ;JCH TO AWAKEN
MOVEM T3,(T1) ;SAVE FOR GFRABT
SYSPIF ;INTERLOCK QUEUE
IDPB T2,CLOCK## ;STUFF ROUTINE,,TIME
IDPB T1,CLOCK## ;AND DATA
SETOM CLKNEW## ;THERE'S A NEW REQUEST
SYSPIN ;ALLOW OTHERS AGAIN
MOVE P2,T1 ;SAVE BLOCK POINTER
POPJ P, ;RETURN
;GFRCLN -- CLEAN UP UNEXPIRED GOPHER TIMER
;
;CALL:
; P2/ AS RETURNED BY GFRTMO
;
;RETURNS +1 ALWAYS
GFRCLN: TRNN P2,-1 ;ANYTHING TO DO?
POPJ P, ;NO
PUSHJ P,SAVT## ;MAYBE, SAVE SOME ACS
MOVE T1,P2 ;COPY DATA VALUE
MOVE T2,[GFRABT,,1] ;ROUTINE,,NEW TIMER
PUSHJ P,CLKCHG## ;EXPIRE SOON
POPJ P, ;OK IF NONE
POPJ P, ;DONE
;GFRABT -- ABORT A TIMED GOPHER REQUEST
;
;CALL:
; MOVEI T1,ADDRESS OF WORD SAVED BY GFRTMO
; PUSHJ P,GFRABT
;
; RETURN HERE ALWAYS
;
;CLOBBERS T1-T4, J & W.
GFRABT: SE1ENT ;IPCSER RUNS IN SECTION ONE
PUSH P,(T1) ;SAVE DATA WORD
SETZM (T1) ;CLEAR OUT STALE DATA
MOVEI T2,1 ;LENGTH
EXCH T2,T1 ;GIVWDS & GETWDS DISAGREE ON ARGUMENT ORDER
PUSHJ P,GIVWDS## ;RETURN THE CORE BLOCK
HRRZ T1,(P) ;GET TARGET JCH
PUSHJ P,CTXIPC## ;SETUP FOR IPCF DATA MUNGING
JRST TPOPJ## ;GIVE UP IF CAN'T
HRRZ T1,.EPQSN(W) ;GET QUEUE-UUO SEQUENCE NUMBER
HLRZ T2,(P) ;AND OLD VALUE
CAME T2,T1 ;MATCH?
JRST TPOPJ## ;NO, DON'T TOUCH THE USER
MOVE T1,.EPEPA(W) ;GET PID WHO CAN ANSWER
TRNE T1,-1 ;IF STILL THERE,
CAMN T1,%SIFDA## ;AND REALLY FOR A QUEUE. UUO,
JRST TPOPJ## ;(NO, DON'T TRASH CORE)
SETZM .EPEPA(W) ;STILL WAITING, ZAP PID WORD FOR GOPHER CHECK
HRRZ T1,(P) ;GET JCH
PUSHJ P,CTXEWK## ;BREAK IT OUT OF EVENT WAIT
JFCL ;IT WENT AWAY?
JRST TPOPJ## ;RETURN TO CLOCK1
SUBTTL MONITOR INTERFACE ROUTINES
;SENDSI -- ROUTINE TO SEND A MESSAGE TO ANY SPECIAL SYSTEM PROCESS
;
;CALL:
; MOVEI T1,%SIXXX
; HRLI T1,"SENT BY [SYSTEM]?", 0 IF IPCC
; MOVE T2,[XWD LEN,ADR]
; MOVE T3,SYSTEM PID, IGNORED IF IPCC
; PUSHJ P,SENDSI
;
; ALWAYS RETURN HERE
;
;USES T1-T4
;
;NOTE: THE BLOCK SPECIFIED BY THE CALLER BELONGS "TO THE CALLER".
; IT IS COPIED AND RETURNED TO THE CALLER INTACT. SPECIFICALLY,
; IF THE CALLER GOT THE BLOCK FROM THE SYSTEM FREE SPACE, "HE"
; MUST RETURN IT.
;
SNDFFC::SE1ENT ;ENTER SECTION 1
PUSH P,T4
MOVE T2,T4
PUSHJ P,SENDSI
JFCL
SNDFFR: POP P,T2
SNDFFD: TLZ T2,(IFIW) ;CLEAR CROCKY BIT
HLRZ T1,T2
HRRZS T2
PJRST GVFWDS##
SENDSI::SE1ENT ;ENTER SECTION 1
PUSHJ P,SAVJW## ;SAVE J AND W
MOVE T4,JBTPPN##(J) ;SENDER'S PPN
;ENTER HERE WITH (T4) = SENDER'S PPN
SENDS0: TLZ T2,(IFIW) ;CLEAR CROCKY BIT
PUSH P,T1
HRRZS T1
SKIPN 0(T1)
JRST TPOPJ##
POP P,T1
PUSHJ P,SAVE4## ;SAVE P1-P4
MOVE P4,T3
MOVE P3,T1 ;SAVE T1
MOVE P2,T2 ; AND T2
MOVE P1,T4
TLNE P3,-1
JRST SENDS1
HRLI P3,10
MOVE P4,PIDTAB##
;FALL INTO SENDS1
SENDS1: HLRZ T2,P2 ;GET LENGTH
ADDI T2,.IPCFD ;ADD HEADER
PUSHJ P,GETPKT ;GET FREE SPACE
POPJ P,
MOVEM P1,.IPCFU(T1)
HLRZM P3,.IPCFL(T1)
MOVEM P4,.IPCFS(T1)
HRL P1,P2 ;GET SOURCE,,0
HRRI P1,.IPCFD(T1) ;GET SOURCE,,DEST
HLRZ P4,P2 ;GET LEN
MOVSI T2,IP.LPK ;GET "LARGE PACKET"
CAMLE P4,%CNIPL## ;IS IT LARGE?
IORM T2,.IPCFL(T1) ;YES, SET IT
ADDI P4,.IPCFD-1(T1) ;GET END OF MSG
BLT P1,(P4) ;MOVE THE MSG OVER
HRRZ T2,P3 ;ISOLATE ADDRESS
MOVE T2,(T2) ;GET RECEIVER'S PID
MOVEM T2,.IPCFR(T1) ;SAVE IT
MOVE P1,T1 ;COPY PACKET ADDRESS FOR SAFE KEEPING
MOVE T1,J ;GET JOB/CONTEXT HANDLE
PUSHJ P,CTXIPC## ;SENDER'S IPCF DATA BLOCK ADDR
PUSHJ P,S..NIJ ;LOOSE
MOVE T1,P1 ;RESTORE FOR IPCSCA
MOVEM T2,.EPEPA(W) ;STORE THE PID OF WHO CAN ANSWER
SETZM .IPCFI(T1) ;ZERO REST OF WORD
HLRE T3,P2 ;LENGTH
SKIPGE T3
MOVEI T3,PAGSIZ ;IF FULL PAGE
DPB T3,PKLNT1 ;AND STORE LENGTH
PUSHJ P,IPCSCA ;SET CAPABILITIES OF THE JOB PACKET IS BEING SENT FOR
AOS %CNIIP## ;ONE MORE IN
PUSHJ P,SNDMSG ;SEND IT
JRST SENDS2 ;LOSE!
JRST CPOPJ1##
SENDS2: HLRZ T1,P2 ;GET MSG LENGTH
ADDI T1,.IPCFD ;ADD HDR SIZE
HRRZ T2,P1 ;GET ADR
SOS %CNIIP## ;1 LESS MESSAGE
PJRST GIVWDS## ;RETURN SPACE AND RETURN
;GETPKT -- GET A PACKET OF FREE CORE. CALL WITH T2 CONTAINING
; NUMBER OF WORDS NEEDED. RETURNS WITH ADDRESS OF PACKET
; IN T1. GETPKT "WAITS" IF NO FREE SPACE IS AVAILABLE. ALWAYS
; RETURNS CPOPJ.
GETPKT: PUSH P,T2
GETPK0: PUSHJ P,GETWDS## ;GET THE FREE SPACE
JRST GETPK1 ;LOSE, WAIT
JRST T2POJ1## ;WIN!!
GETPK1: JUMPE J,T2POPJ## ;LOSE IF AT INTERRUPT LEVEL
PUSH P,J
ANDI J,JOBMSK##
PUSH P,W
PUSHJ P,FNDPDS## ;POINT W AT THE PDB
MOVEI T1,1 ;ONE SECOND
PUSHJ P,SLEEPF## ;SLEEP
POP P,W
POP P,J
MOVE T2,(P)
JRST GETPK0 ;AND TRY AGAIN
;CHKSID -- CHECK IF PID IS ONE OF THE "FRIENDS OF THE MONITOR"
;CALLED WITH T1=THE PID
;RETURNS WITH T2=OFFSET FROM .GTCSD
;RETURNS CPOPJ IF TRUE, CPOPJ1 OTHERWISE
CHKSID: MOVEI T2,SDTBLN##+<.GTSID##-.GTCSD##> ;NUMBER OF PIDS
CHKS.1: CAMN T1,.GTCSD##(T2) ;THIS IT
POPJ P, ;YES, RETURN
SOJGE T2,CHKS.1 ;NO, TRY THE NEXT
JRST CPOPJ1## ;NOT A SYSTEM
SUBTTL LOCK UUO INTERFACE
IFN FTLOCK,<
;SUBROUTINE TO FIND AN INCORE IPCF PAGE IN SOME JOB'S IPCF QUEUE
;CALL WITH T2=PHYSICAL PAGE NUMBER, U=DISK ADDRESS TO REPLACE IT WITH
;RETURNS CPOPJ IF NOT FOUND, RETURNS CPOPJ1 IF FOUND, DISK ADDRESS STORED
LOKIPC::SE1ENT ;ENTER SECTION 1
PUSHJ P,SAVJW## ;SAVE J AND W
MOVE J,HIGHJB## ;SCAN ALL JOBS
LOKIP1: MOVE T1,J ;COPY JOB NUMBER
TLO T1,400000 ;STEP THROUGH CONTEXT BLOCKS
PUSHJ P,CTXIPC## ;FIND THIS JCH'S IPCF DATA BASE
JRST LOKIP4 ;NO PAGES IN ITS QUEUE IF NO PDB
XMOVEI T1,.EPIPC-.IPCFL(W) ;SET PREDESESSOR
LOKIP2: HLRZ T1,.IPCFL(T1) ;NEXT ENTRY IN THE QUEUE
JUMPE T1,LOKIP3 ;GO IF THE LAST
MOVE T3,.IPCFI(T1) ;ADDRESS OF PAGE IF IT IS ONE
TLZ T3,(IP.NAD^!IP.DSK) ;CLEAR ALL BUT ADDRESS AND DISK BIT
CAME T2,T3 ;SAME PHYSICAL PAGE?
JRST LOKIP2 ;NO, LOOK ON
DPB U,PKADT1 ;STORE DISK ADDRESS WHERE IT WILL
; BE ON THE SWAPPING SPACE
JRST CPOPJ1## ;FOUND RETURN
LOKIP3: TRNE J,CTXMSK## ;CTXSER LOADED?
JRST LOKIP1 ;YES--GO DO IT FOR NEXT CONTEXT
LOKIP4: ANDI J,JOBMSK## ;REDUCE TO A JOB NUMBER
SOJG J,LOKIP1 ;LOOK AT THE NEXT JOB'S QUEUE
POPJ P, ;PAGE NOT IN ANY QUEUE
>
SUBTTL IPCF QUEUE INTERLOCK
;ROUTINE TO LOCK THE JOB'S IPCF QUEUE
;REQUIRES J SET UP.
IPCLOK::SE1ENT ;ENTER SECTION 1
PUSHJ P,SAVJW## ;SAVE J AND W
PUSH P,T1 ;SAVE T1
PUSH P,T2 ;SAVE T2
MOVE T1,J ;TARGET JCH
IPLOK1:
PUSH P,T1 ;SAVE T1
ANDI T1,JOBMSK## ;JOB ONLY
PUSHJ P,UPCX## ;GET THE CX RESOURCE
POP P,T1 ;RESTORE FULL JCH
PUSHJ P,CTXIPC## ;SET UP J AND W
JRST IPLOK4 ;NO SUCH JOB OR CONTEXT
SKIPN J ;NULL JOB (EXEC PROCESS)?
TRO J,CTXMSK## ;GIVE IT A CONTEXT NUMBER JUST FOR THIS
IPLOK2: MOVE T1,.CPJCH## ;GET OUR JCH
MOVEI T2,-1 ;MASK FOR TARGET JCH
SYSPIF ;AVOID RACES
TDNE T2,.EPIPL(W) ;SOMEONE ALREADY OWN THIS GUY'S INTERLOCK?
JRST IPLOK5 ;YES--MUST WAIT
HRRM T1,.EPIPL(W) ;ELSE SET OUR JCH AS HIS OWNER
MOVE T1,.CPJOB
HLLZS JBTIPC##(T1) ;CLEAR WE MIGHT HAVE BEEN WAITING
PUSHJ P,FPDBT1## ;GET PDB
JRST [HLLZS .EPIPL(W) ;DON'T OWN IT AFTER ALL
JRST IPLOK4 ] ;??
HRLM J,.PDIPL##(T1) ;SAVE WHOSE JCH WE OWN
SYSPIN ;TURN PI SYSTEM ON AGAIN
IPLOK4:
PUSHJ P,DWNCX## ;GIVE UP CX ON JOB
JRST TTPOPJ## ;RESTORE T1, T2, AND RETURN
IPLOK5: SYSPIN
MOVEI T2,IPQ## ;PUT JOB IN
EXCH T1,J ;.CPJCH-->J,TARGET TO T1
ANDI J,JOBMSK## ;JOB ONLY
DPB T2,PJBSTS## ;IN IP INTERLOCK WAIT
HRRM T1,JBTIPC##(J) ;SAVE THE JCH WE WANT
PUSHJ P,DWNCX## ;GIVE UP THAT JOB'S CX
POP P,T2
POP P,T1
PJRST WSCHED## ;WAIT
; HERE TO UNLOCK AN IPCF QUEUE
IPCULK::SE1ENT ;ENTER SECTION 1
PUSHJ P,SAVJW## ;SAVE J AND W
PUSH P,T1 ;SAVE T1
PUSH P,T2 ;SAVE T2
HRRZ T1,.CPJOB## ;GET OUR JOB NUMBER
;WE ARE NOT GETTING THE CX FOR OUR OWN PDB HERE SINCE AT UUO LEVEL
;IF IT EVER BECOMES NECESSARY TO DO SO, MUST BE SURE CALLERS OF THIS ROUTINE
;DON'T ALREADY HAVE A CX
PUSHJ P,FPDBT1## ;GET OUR PDB ADDR
JRST TTPOPJ## ;??
MOVE T2,T1 ;COPY
MOVSI T1,-1 ;INTERLOCKED JOB MASK
AND T1,.PDIPL##(T2) ;TRANSFER JCH TO T1
ANDCAM T1,.PDIPL##(T2) ;CLEAR THAT WE OWN A THIS JCH'S INTERLOCK
HLRZS T1 ;MAKE IT A REAL JOB/CONTEXT HANDLE
PUSH P,F ;SAVE F
JUMPE T1,IPCUL4 ;HMMM....
PUSHJ P,[MOVE F,T1
ANDI T1,JOBMSK## ;UPCX AND FRIENDS ONLY NEED JOB
PUSHJ P,CXOWN## ;OWN THE CX?
PUSHJ P,GGVCX## ;NO, GET IT
MOVE T1,F ;GET JOB #
PUSHJ P,CTXIPC## ;SET UP J AND W FOR TARGET JCH
POPJ P, ;IT WENT AWAY?
HLLZS .EPIPL(W) ;CLEAR OUR JOB NUMBER
POPJ P, ] ;RETURN
IPCUL4: SETZ F,
PUSHJ P,[PUSH P,T1 ;SAVE T1 (SRFREE ALREADY HAD)
PUSH P,J ;SAVE J (SRFREE ALREADY HAD)
MOVE J,.CPJOB
PJRST SRFRIP##]
POP P,F
JRST TTPOPJ## ;RESTORE T1, T2 AND RETURN
;HERE SO SCHEDULAR CAN CHECK TO SEE IF WE OWN AN IPCF RESOURCE
;SKIP RETURN IF DO, NON-SKIP IF DON'T
OWNIP:: PUSH P,T1 ;SAVE T1
MOVEI T1,(J) ;CURRENT JOB
PUSHJ P,GETCX## ;TRY TO GET OUR OWN CX RESOURCE
JRST .-1 ;HOPE WE DON'T KAF
PUSHJ P,FPDBT1## ;FIND PDB
JRST TSTIP1
HLRZ T1,.PDIPL##(T1) ;INTERLOCK WORD
SKIPE T1 ;OWN ANYONE'S?
AOS -1(P) ;YES
TSTIP1: PUSHJ P,GIVCX## ;RETURN CX
JRST TPOPJ## ;DO OWN SOMEONES
;HERE FOR UNWIND CODE IN SCHED1. RETURNS IN T3 THE JOB # OF THE JOB WHO OWNS
;THE IPCF INTERLOCK WHICH THE JOB IN J DESIRES
UNWIPC::SE1ENT ;ENTER SECTION 1
HRRZ T3,JBTIPC##(J) ;GET THE JCH HE WANTS
JUMPE T3,CPOPJ## ;
PUSHJ P,SAVJW## ;SAVE J,W
PUSH P,T1 ;AND T1
MOVE J,T3 ;DESIRED JCH
ANDI J,JOBMSK##
PUSHJ P,GETCX## ;CAN WE GET HIS?
JRST NIPUNW ;FLAG CAN'T TELL WHO OWNS IP
MOVE T1,T3 ;DESIRED JCH
PUSHJ P,CTXIPC## ;CALL CTXSER
JRST NIPOWN ;FLAG IP UNOWNED
HRRZ T3,.EPIPL(W) ;GET THE OWNER JCH
ANDI T3,JOBMSK##
PUSHJ P,GIVCX## ;RETURN CX
JRST TPOPJ##
NIPOWN: TDZA T3,T3 ;NO OWNER
NIPUNW: SETO T3, ;CAN'T UNWIND SINCE CAN'T FIND WHO OWNS IP
PUSHJ P,GIVCX##
JRST TPOPJ##
;HERE FROM SCHEDULAR TO GIVE JOB IN J THE IPCF RESOURCE HE WANTS
;SKIP RETURN IF GOT IT, ELSE NON-SKIP
SCDIP:: SE1ENT ;ENTER SECTION 1
HRRZ T3,JBTIPC##(J) ;GET THE JCH HE WANTS
JUMPE T3,CPOPJ## ;
PUSHJ P,SAVJW## ;SAVE J,W
MOVEI J,(T3) ;GET JOB # FOR THIS JCH
ANDI J,JOBMSK##
PUSHJ P,GETCX## ;SEE IF CAN GET CX
POPJ P, ;LOSE IF CAN'T GET IT
PUSH P,T1 ;AND T1
MOVE T1,T3 ;DESIRED JCH
PUSHJ P,CTXIPC## ;CALL CTXSER
JRST SCDIP1 ;WAKE JOB ANYWAY
PUSH P,T2 ;CTXSER USES T2
SYSPIF
HRRZ T3,.EPIPL(W) ;GET THE OWNER JCH
JUMPN T3,[SYSPIN ;OH WELL, SOMEONE ELSE SNUCK IN
PUSHJ P,GIVCX##
JRST TTPOPJ##]
HRRZ T1,-4(P) ;GET OUR JCH
PUSHJ P,CTXJCH##
HRRZ T1,-4(P) ;HUH?
HRRM T1,.EPIPL(W) ;WE OWN IT
ANDI T1,JOBMSK
HLLZS JBTIPC##(T1) ;CLEAR OUR WAITING
PUSHJ P,FPDBT1## ;GET PDB
CAIA ;HUH?
HRLM J,.PDIPL(T1) ;SET OUR OWNING
SYSPIN
POP P,T2
SCDIP1: PUSHJ P,GIVCX##
JRST TPOPJ1##
SUBTTL MIGRATION
;SUBROUTINE TO FIND SWAPPED-OUT IPCF PAGES ON A UNIT BEING REMOVED FROM THE ASL
;RETURNS CPOPJ1 IF A PAGE IS FOUND, T4 = DISK ADDRESS OF PAGE,
; T1 = THE ADDRESS IN THE IPCF PACKET CONTAINING THE DISK ADDRESS
; CPOPJ IF NO MORE IPCF PAGES ON THE UNIT BEING REMOVED
FNDIPC::SKIPA J,HIGHJB## ;SCAN ALL JOBS
FNDIP0::MOVM J,MIGRAT## ;START WITH JOB WE LEFT OFF WITH
SE1ENT ;ENTER SECTION 1
PUSH P,J ;SAVE IT
FNDIP1: MOVE T1,(P) ;NEXT
TLO T1,(1B0) ;SET STEP FLAG FOR CTXSER
PUSHJ P,CTXIPC## ;SAVE IT
JRST FNDIP4 ;NO PAGES IN ITS QUEUE IF NO PDB
PUSHJ P,IPCLOK
MOVEM J,(P) ;SAVE LAST CONTEXT
ANDI J,JOBMSK ;KEEP JUST JOB # FOR COMPARISON
MOVN T1,MIGRAT## ;GET CURRENT MIGRATE IPCF JOB
CAILE T1,(J) ;IF NEW JOB LESS THAN OLD JOB THEN
MOVNM J,MIGRAT## ;FLAG LOOKING AT THIS JOB
XMOVEI T1,.EPIPC-.IPCFL(W) ;SET PREDESESSOR
FNDIP2: HLRZ T1,.IPCFL(T1) ;NEXT ENTRY IN THE QUEUE
JUMPE T1,FNDIP3 ;GO IF THE LAST
SKIPL T4,.IPCFI(T1) ;DISK ADDRESS?
JRST FNDIP2 ;NO, LOOK ON
TLZ T4,(IP.NAD) ;DON'T CONFUSE VMSER WITH BAD MAP CONTENTS
PUSHJ P,TSTUN## ;ON THE UNIT BEING REMOVED FROM THE ASL?
JRST [LDB T4,PKADT1 ;GET DISK ADDRESS
MOVEI T1,.IPCFI(T1) ;WHERE TO STORE NEW DSK ADDR WHEN MIGRATED
POP P,(P) ;FIX STACK
JRST CPOPJ1##] ;GIVE PAGE FOUND RETURN
JRST FNDIP2
FNDIP3: PUSHJ P,IPCULK
JRST FNDIP1 ;LOOK AT NEXT CONTEXT
FNDIP4: SOJLE J,TPOPJ## ;FIX STACK AND RETURN
MOVEM J,(P)
JRST FNDIP1 ;CHECK NEXT JOB
;ROUTINE CALLED ON IPCF SEND FROM VMSER (IPCRMV) TO GET INTERLOCK
;FOR RECEIVING JOB AND WAIT UNTIL SAFE WRT SWAP MIGRATION.
;CALL WITH P3=ADDRESS OF PACKET, T1=PAGE NUMBER
;ALL ACS PRESERVED
IPMCHK::SE1ENT ;ENTER SECTION 1
PUSHJ P,SAVT## ;BE SAFE NOW
PUSH P,J
PUSH P,W ;SAVE J,W
MOVE T1,.IPCFR(P3) ;RECEIVER
PUSHJ P,VALPID
JRST IPCSOK ;SHOULDN'T HAPPEN
IPMCK1: MOVE T1,-3(P) ;RESTORE PAGE NUMBER
PUSHJ P,IPCLOK ;LOCK RECIEVER'S IPCF QUEUE
PUSHJ P,GTPME## ;GET PAGE MAP SLOT
MOVE T3,T2 ;SAVE MAP CONTENTS
PUSHJ P,TSWST## ;IS IT IN THE WORKING SET?
SKIPA T4,T3 ;NO, CHECK MORE
JRST IPCWS ;SEE IF SHOULD WAIT FOR FILFND
PUSHJ P,TSTUN## ;IS IT ON THE BAD UNIT?
CAIA ;YES, MUST WAIT
JRST IPCSOK ;NO, CAN JUST RETURN WITH INTERLOCK
MOVN T1,MIGRAT## ;SEE IF ANYTHING BEING MIGRATED
JUMPE T1,IPCSOK ;"0" IS A SPECIAL CASE
CAILE T1,(J) ;HAS THE IPCF STUFF ALREADY PASSED US?
JRST IPCSOK ;NO, RETURN
IPCSWT: PUSHJ P,IPCULK ;UNLOCK QUEUE
PUSHJ P,IPMWAT## ;YES, MUST WAIT ON PAGE
JRST IPMCK1 ;GET INTERLOCK AND TRY AGAIN
IPCWS: SKIPGE MIGRAT## ;IS FILFND WAITING FOR PAGING QUEUES TO CLEAR?
JRST IPCSWT ;YES, DON'T CLUTTER THEM UP
IPCSOK: POP P,W ;RESTORE OLD J,W
POP P,J
POPJ P,
;SUBROUTINE TO SET IPCF QUOTA IF NOT SET. USES T2. W POINTS TO IPCF BLOCK
;TO SET QUOTA IN
;NOTE THAT THIS CAN BE DONE FASTER WITH MOVE/MOVEM OF .EPIPQ, THAT
;IS A RACE WITH THE CLEARING OF THE JOB IN .EPIPQ IN ROUTINE IPCULK
;RETURNS WITH .EPIPQ(W) IN T2
SETIPQ: MOVE T2,.EPIPQ(W) ;GET QUOTA WORD
TLNE T2,IP.HBS ;BEEN SET?
POPJ P, ;YES, DO NOTHING
HRLOI T2,IP.HBS!777 ;SAVE ALL LH BITS EXCEPT QUOTA
ANDCAM T2,.EPIPQ(W) ;CLEARING ANY QUOTA THERE
MOVE T2,%CNIPQ## ;VALUE + 'SET' BIT
TSO T2,%CNIPD## ;ADD IN PID QUOTA DEFAULT
IORB T2,.EPIPQ(W) ;SET DEFAULTS
POPJ P,
LIT
IPCEND: END