Google
 

Trailing-Edge - PDP-10 Archives - bb-d868a-bm - 3-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