Trailing-Edge
-
PDP-10 Archives
-
bb-d868b-bm_tops20_v3a_2020_dist
-
3a-sources/qsripc.mac
There are 28 other files named qsripc.mac in the archive. Click here to see a list.
TITLE QSRIPC -- IPC Handler for QUASAR
SUBTTL Larry Samberg C.D. O'Toole 7 Nov 76
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1974, 1975, 1976, 1977, 1978 BY
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
SEARCH QSRMAC ;PARAMETER FILE
PROLOGUE(QSRIPC) ;GENERATE THE NECESSARY SYMBOLS
;GLOBAL ROUTINES IN THIS MODULE USE ALL ACCUMULATORS EXCEPT:
; P1,P2,P3,P4, AND M
;QSRIPC DOES NOT CONTAIN ANY STOPCD'S
;MODULE STORAGE
IPCASV: BLOCK 1 ;ASSOCIATED VARIABLE FOR NEXT RECEIVE
IPCPND: EXP -1 ;SET TO -1 WHEN A RECEIVE INTERRUPT IS IGNORED.
SUBTTL Global Entry Points in QSRIPC
INTERN C$INIT ;Initialize the IPC Handler
INTERN C$GET ;Get next message from the IPC queue
INTERN C$RAPK ;Receive all outstanding IPCF packets
INTERN C$PUT ;Put IPC core back in free list
INTERN C$INT ;Interrupt Level Entry
INTERN C$SEND ;Send an IPCF Message
INTERN C$RSND ;Re-send messages that failed
SUBTTL C$INIT -- IPC Handler Initialization
;C$INIT SETS UP FOR INITIAL QUERRY AND ESTABLISHES A PID FOR [SYSTEM]QUASAR
C$INIT: MOVEI S1,SP.QSR ;CREATE A [SYSTEM]QUASAR
PUSHJ P,I$EPID## ;ASK [SYSTEM]IPCC
MOVEM S1,G$QPID## ;REMEMBER OUR PID
POPJ P, ;AND RETURN
SUBTTL C$GET -- Routine to return next IPC message
;RETURNS THE NEXT MESSAGE FROM THE IPCF RECIEVE QUEUE.
; RETURNS WITH "AP" POINTING TO THE MESSAGE. IF
; AP CONTAINS ZERO ON RETURN, NO REQUESTS ARE IN THE
; QUEUE.
C$GET: PUSHJ P,C$RAPK ;RECEIVE ALL OUTSTANDING PACKETS
LOAD AP,<HDRIPC##+.QHLNK>,QH.PTF ;GET POINTER TO 1ST ENTRY
PJUMPE AP,.POPJ## ;RETURN IF NONE
MOVEI H,HDRIPC## ;LOAD H
PJRST M$DLNK## ;DLINK THE ENTRY AND RETURN
SUBTTL C$RAPK -- Receive all outstanding Packets
;CALLED TO GET ANY MESSAGES IN OUR RECEIVE QUEUE IF IPCPND HAS BEEN SET
C$RAPK: SKIPL IPCPND ;ANYTHING PENDING?
POPJ P, ;NO, RETURN
PUSHJ P,I$NOIN## ;TURN OFF INTERRUPTS
ZERO IPCPND ;CLEAR PENDING FLAG
PUSHJ P,I$IPQ## ;QUERY THE QUEUE
JUMPE S1,.POPJ## ;NOTHING THERE, SKIP THE RECEIVE
MOVEM S1,IPCASV ;ELSE SAVE ASSOCIATED VARIABLE
PJRST IPCRCV ;EMPTY OUR RECEIVE QUEUE
SUBTTL C$PUT -- Routine to return free IPC core
;THIS ROUTINE IS CALLED TO PLACE AN IPC QUEUE ENTRY BACK INTO
; THE FREE SPACE. A CHECK IS MADE TO SEE IF IT IS A PAGED
; MESSAGE, AND IF SO THE PAGE IS RELEASED FIRST. CALLED
; WITH AP POINTING TO THE ENTRY.
C$PUT: MOVEI H,HDRIPC## ;SET UP H FOR M$PFRE
MOVE S1,IPCFLG(AP) ;GET FLAGS
TXNN S1,IP.CFV ;IS IT PAGED?
PJRST M$PFRE## ;NO, RETURN VIA PFRE
MOVE T1,AP ;YES, SAVE AP
LOAD AP,IPCMES(AP),IPM.AD ;GET THE PAGE NUMBER
PUSHJ P,M$RELP## ;RELEASE THE PAGE
MOVE AP,T1 ;RESTORE AP
PJRST M$PFRE## ;AND RETURN VIA PFRE
SUBTTL C$INT -- Interrupt Level Entry
;SAVES ALL NECESSARY ACS AND CALLS IPCRCV TO RECEIVE ALL OUTSTANDING
; PACKETS.
;
;IF THE INTERRUPTED PC IS IN THE MEMORY MANAGER, THE INTERRUPT
; IS IGNORED TO AVOID ANY RACE CONDITIONS.
C$INT: DMOVEM S1,INT.A ;SAVE S1 AND S2 FIRST
MOVEM P,INT.P ;SAVE SOMEBODYS P
MOVE P,[IOWD INTPSZ,INT.B] ;SET UP OUR OWN PUSHDOWN STACK
SKIPGE IPCPND ;IF "PENDING" IS SET,
JRST INT.4 ; IGNORE THE INTERRUPT
PUSHJ P,I$OKIN## ;OK TO PROCESS INTERRUPT
JUMPN S1,INT.1 ;JUMP IF OK TO PROCESS IT
SETOM IPCPND ;MARK TO LOOK AGAIN LATER
JRST INT.4 ;DISMISS IT NOW
INT.1: PUSH P,AP ;SAVE AP
PUSH P,H ;SAVE H
PUSH P,TEMP ;SAVE TEMP
INT.2: PUSHJ P,I$GMIS## ;GET MESSAGE INTERRUPT STATUS
JUMPE S1,INT.3 ;0, NO MESSAGE THERE
MOVEM S1,IPCASV ;SAVE ASSOCIATED VARIABLE
PUSHJ P,IPCRCV ;RECEIVE A PACKET
INT.3: POP P,TEMP ;RESTORE TEMP
POP P,H ;RESTORE H
POP P,AP ;RESTORE AP
SKIPA ;SKIP DEFER COUNTER
INT.4: $COUNT (IPCD) ;NO. OF DEFERED IPCF INTERRUPTS
$COUNT (IPCI) ;TOTAL NUMBER OF IPCF INTERRUPTS
PUSHJ P,I$POST## ;AND POST THE INTERRUPT
DMOVE S1,INT.A ;GET S1 AND S2 BACK
MOVE P,INT.P ;RESTORE INTERRUPTED STACK
JRST I$DBRK## ;DISMISS THE INTERRUPT
INT.A: BLOCK 2 ;SAVED S1 AND S2 DURING INTERRUPT
INT.B: BLOCK ^D20 ;STACK TO BE USED AT INTERRUPT LEVEL
INTPSZ==.-INT.B ;LENGTH OF IT
INT.P: BLOCK 1 ;INTERRUPTED P (STACK)
SUBTTL IPCRCV -- Routine to Receive IPCF Packets
;THIS ROUTINE IS CALLED WITH LOCATION "IPCASV" CONTAINING THE
; ASSOCIATED VARIABLE OF THE FIRST MESSAGE TO BE RECEIVED.
; IT LOOPS THROUGH AND RECEIVES ALL OUTSTANDING IPCF MESSAGES.
; IT IS CALLED AT BOTH INTERRUPT LEVEL AND PROGRAM LEVEL.
;
;USES S1,S2,H,AP
IPCRCV: ZERO IPCPND ;CLEAR PENDING FLAG
MOVEI H,HDRIPC## ;LOAD ADDRESS OF IPCF QUEUE HDR
IPCR.1: PUSHJ P,M$GFRE## ;GET A FREE CELL
ZERO IPCFLG(AP) ;CLEAR THE OLD FLAG WORD
ZERO IPCR.A ;CLEAR PAGE WORD
MOVE S1,IPCASV ;GET THE ASSOCIATED VARIABLE
TXNE S1,IP.CFV ;SKIP IF NOT PAGED
JRST IPCR.2 ;PAGED, BRANCH
MOVEI S1,IPCDAT(AP) ;POINT TO FIRST WORD OF SHORT MESSAGE
HRL S1,G$MPS## ;GET SIZE OF MESSAGE IN LH
MOVEM S1,IPCMES(AP) ;AND STORE IN IPC HEADER
JRST IPCR.4 ;RECEIVE THE PACKET AND RETURN
IPCR.2: PUSH P,AP ;SAVE ADDRESS OF QUEUE ENTRY
PUSHJ P,M$NXPG## ;GET ADDRESS OF A NON-EX PAGE
MOVEM AP,IPCR.A ;AND STORE THE PAGE NUMBER
JUMPN AP,IPCR.3 ;OK IF GOT A PAGE FOR THE MESSAGE
SETOM IPCPND ;SET THE REQUEST-PENDING FLAG
POP P,AP ;LOAD ADDRESS OF THE IPC CELL
PJRST M$PFRE## ;AND RETURN IT TO THE FREE SPACE
IPCR.3: POP P,S2 ;GET POINTER TO QUEUE ENTRY BACK
HRLI AP,1000 ;AND THE SIZE
MOVEM AP,IPCMES(S2) ;STORE IN IPCF HEADER
MOVX S1,IP.CFV ;GET PAGE-MODE BIT
MOVEM S1,IPCFLG(S2) ;AND STORE IT IN FLAG WORD
MOVE AP,S2 ;AND GET THE ADDRESS OF THE QUEUE ENTRY
IPCR.4: MOVX S1,IP.CFP!IP.TTL ;WANT TO SEE CALLERS PRIVS AND TRUNCATE
IORM S1,IPCFLG(AP) ;SO ASK TO SEE SENDERS IP.CFP
MOVE S1,G$QPID## ;GET MY PID
MOVEM S1,IPCRCR(AP) ;AND SAVE IT AS RECEIVER'S PID
MOVEI S1,IPCRSZ ;LOAD THE HEADER SIZE
MOVEI S2,IPCFLG(AP) ;AND THE ADDRESS
PUSHJ P,I$IPR## ;RECIEVE IT
$COUNT (RIPC)
MOVEM S1,IPCASV ;SAVE ASSOC. VAR. FOR THE NEXT ONE
PUSHJ P,M$ELNK## ;LINK IT IN AT THE END
SKIPE AP,IPCR.A ;GET PAGE NUMBER AND SKIP IF NOT THERE
PUSHJ P,M$IPRC## ;AND TELL QSRMEM THAT IT NOW EXISTS
SKIPE IPCASV ;ANYTHING LEFT TO DO?
JRST IPCR.1 ;YES, LOOP
POPJ P, ;NO, RETURN
IPCR.A: BLOCK 1 ;PAGE NUMBER IF PAGED RECEIVE
SUBTTL C$SEND -- Routine to send IPCF Message
;C$SEND ROUTINES ARE CALLED WITH AP POINTING TO THE PACKET DESCRIPTOR
; BLOCK FOR THE MESSAGE TO BE SENT. THE MESSAGE IS SENT, AND
; IF IT WAS PAGED, M$RELP IS CALLED TO DESTROY THE PAGE.
; LEFT HALF OF AP CONTAINS FLAGS FOR THIS SEND.
C$SEND: MOVEM AP,SEND.A ;SAVE AP FOR LATER
MOVE S1,.IPCFL(AP) ;GET THE FLAG WORD
TXNN S1,IP.CFV ;PAGE MODE?
JRST SEND.1 ;NO, NO PROBLEM
HRRZ AP,.IPCFP(AP) ;GET PAGE NUMBER
PUSHJ P,M$IPSN## ;NOTIFY THE MEMORY MANAGER
MOVE AP,SEND.A ;GET AP BACK
SEND.1: MOVE S2,G$QPID## ;ASSUME FROM [SYSTEM]QUASAR
SKIPN .IPCFS(AP) ;SENDER SUPPLIED
MOVEM S2,.IPCFS(AP) ;NO, STORE AS SENDER'S PID
TXNE AP,IPS.TF ;SKIP PASS OVER IPS QUEUE
JRST SEND.4 ;YES, GO TRY TO SEND IT
LOAD S1,<HDRIPS##+.QHLNK>,QH.PTF ;GET PTR TO 1ST ITEM IN IPS QUEUE
LOAD S2,.IPCFR(AP) ;GET THE PID WE'RE SENDING TO
SEND.2: JUMPE S1,SEND.4 ;NOTHING LEFT IN IPS QUEUE, DONE
CAME S2,IPCRCR(S1) ;SAME GUY??
JRST SEND.3 ;NO, KEEP LOOPING
TXNE AP,IPS.ID ;IGNORE IF DUPLICATE IN IPS QUEUE
TXO AP,IPS.IF ;YES, LITE IGNORE ALL FAILURES
MOVEI S1,IPE.RQ ;YES, LOAD A PHONY ERROR CODE
JRST SNDFAI ;AND QUEUE UP THE MESSAGE
SEND.3: LOAD S1,.QELNK(S1),QE.PTN ;GET POINTER TO NEXT
JRST SEND.2 ;AND KEEP LOOPING
SEND.4: MOVEI S1,IPCHSZ ;LOAD THE HEADER SIZE
HRRZ S2,AP ;AND THE ADDRESS
PUSHJ P,I$IPS## ;SEND IT
JUMPL S2,SNDFAI ;S2=-1 MEANS FAILURE
$COUNT (SIPC)
MOVE S2,.IPCFL(AP) ;GET THE FLAG WORD
TXNN S2,IP.CFV ;PAGE-MODE SEND?
POPJ P, ;NO, JUST RETURN
HRRZ AP,.IPCFP(AP) ;GET THE PAGE NUMBER
PJRST M$RELP## ;RELEASE THE PAGE AND RETURN
SEND.A: BLOCK 1 ;STORE AP AROUND CALLS TO QSRMEM
SUBTTL SNDFAI -- IPCF Send Failure
;SNDFAI IS CALLED WHEN THE IPCF SEND ROUTINE C$SEND GETS THE
; ERROR RETURN FROM THE IPCF SEND ROUTINE. IF THE ERROR
; IS RECOVERABLE AT SOME POINT, THE MESSAGE IS LINKED TO
; THE END OF THE IPS QUEUE FOR A RETRY LATER, OTHERWISE
; THE MESSAGE IS SIMPLY FORGOTTEN ABOUT.
;
;IF THE SEND FAILURE IS DUE TO AN INVALID RECEIVER, WE IGNORE
; THE FAILURE, AND IF THE INTENDED RECEIVER WAS A KNOWN
; COMPONENT, WE ATTEMPT TO KILL THE PSB.
;
;ON ENTERING, S1 CONTAINS THE ERROR CODE AND AP CONTAINS ADDRESS OF
; PACKET DESCRIPTOR BLOCK OF THE BAD SEND (ALSO IN "SEND.A").
SNDFAI: $COUNT (IPCF)
CAIN S1,IPE.SF ;SYSTEM FREE SPACE USED UP?
JRST SNDF.1 ;YES, TRY AGAIN LATER
TXNE AP,IPS.IF ;IGNORE FAILURES
SETOB S1,.IPCFR(AP) ;YES, PHONY PID AND ERROR CODE
CAIE S1,IPE.SQ ;MY SEND QUOTA FULL?
CAIN S1,IPE.RQ ;OR HIS REC QUOTA FULL?
JRST SNDF.1 ;YES, QUEUE UP THE MESSAGE
;HERE IF WE WANT TO IGNORE THE ERROR. RETURN THE PAGE (IF IT
; WAS A PAGED SEND), AND IF THE RECEIVER'S PID IS NON-ZERO
; ATTEMPT TO KILL HIS PSB.
$COUNT (IPCU)
PUSH P,.IPCFR(AP) ;SAVE RECEIVER'S PID
MOVE S1,.IPCFL(AP) ;GET FLAG WORD
TXNN S1,IP.CFV ;IS IT PAGED?
JRST SNDF.0 ;NO, NOTIFY EVERYBODY
HRRZ AP,.IPCFP(AP) ;YES, GET PAGE NUMBER
PUSH P,AP ;SAVE AP
PUSHJ P,M$IPRC## ;PRETEND THAT WE REC'ED IT
POP P,AP ;GET PAGE NUMBER BACK
PUSHJ P,M$RELP## ;AND RELEASE IT
SNDF.0: POP P,S1 ;GET PID BACK
PJRST G$SFAL## ;NOW TELL EVERYBODY
;CONTINUED FROM PREVIOUS PAGE
;HERE IF WE CAN QUEUE UP THE MESSAGE FOR A LATER RETRY
SNDF.1: MOVEI S1,^D15 ;SET A SLEEP TIME OF 15 SECS
PUSHJ P,I$SVAL## ; SO THAT RE-SEND HAPPENS QUICKLY
SAVE H ;SAVE THE QUEUE HEADER
MOVEI H,HDRIPS## ;LOAD ADR OF IPS HEADER
PUSHJ P,M$GFRE## ;GET A FREE CELL
MOVE S1,SEND.A ;GET ADDRESS OF PDB OF BAD SEND
MOVS S2,S1 ;MAKE SOURCE OF BLT POINTER
HRRI S2,IPCFLG(AP) ;SET DEST OF BLT
BLT S2,IPCMES(AP) ;BLT THE PDB
MOVE S2,.IPCFL(S1) ;GET THE FLAG WORD
TXNE S2,IP.CFV ;IS IT PAGED?
JRST SNDF.2 ;YES, HANDLE THE PAGE
MOVS S2,.IPCFP(S1) ;NO, GET ADR,,SIZE
HRRI S1,IPCDAT(AP) ;GET 0,,DEST
HRRM S1,IPCMES(AP) ;SAVE IT AS ADR OF MSG IN PDB
HLL S1,S2 ;GET SOURCE,,DEST
ADDI S2,-1(S1) ;GET END-OF-BLT ADR
BLT S1,(S2) ;BLT THE MESSAGE
PJRST M$ELNK## ;LINK INTO IPS QUEUE
SNDF.2: PUSH P,IPCMES(AP) ;SAVE ADR WORD
PUSHJ P,M$ELNK## ;LINK ENTRY INTO IPS QUEUE
POP P,AP ;GET LEN,,ADR BACK
HRRZS AP ;JUST GET ADR (PAGE NO.)
PJRST M$IPRC## ;NOTIFY "MEM" AND RETURN
SUBTTL C$RSND -- Resend Unsendable Messages
;C$RSND IS CALLED EACH TIME THRU THE MAIN LOOP. IT ATTEMPTS TO
; RESEND EVERYTHING IN THE "IPS" QUEUE AGAIN.
C$RSND: PUSHJ P,.SAVE1## ;SAVE P1 FIRST
LOAD P1,<HDRIPS##+.QHLNK>,QH.PTF ;LOAD PTR TO 1ST IN IPS QUEUE
ZERO <HDRIPS##+.QHLNK> ;MAKE BELIEVE THERE'S NOTHING THERE
RSND.1: PJUMPE P1,.POPJ## ;NOTHING THERE (FOR REAL), RETURN
MOVEI AP,IPCFLG(P1) ;POINT AP TO THE MSG PDB
PUSHJ P,C$SEND ;AND SEND THE MESSAGE
MOVE AP,P1 ;COPY THE ADDRESS OF THE CELL
LOAD P1,.QELNK(P1),QE.PTN ;GET THE POINTER TO THE NEXT ONE
MOVEI H,HDRIPS## ;INSURE A PROPER HEADER
PUSHJ P,M$PFRE## ;AND PFRE THE CELL.
;**WARNING**
; DO NOT CALL DLNK OR RFRE!!!
JRST RSND.1 ;AND LOOP
END