Google
 

Trailing-Edge - PDP-10 Archives - bb-d868c-bm_tops20_v4_2020_distr - language-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

;
;
;                COPYRIGHT (c) 1975,1976,1977,1978,1979
;                    DIGITAL EQUIPMENT CORPORATION
;
;     THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY  BE  USED
;     AND COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE
;     AND WITH THE INCLUSION OF THE ABOVE COPYRIGHT NOTICE.   THIS
;     SOFTWARE  OR ANY OTHER COPIES THEREOF MAY NOT BE PROVIDED OR
;     OTHERWISE MADE AVAILABLE TO ANY OTHER PERSON.  NO  TITLE  TO
;     AND OWNERSHIP OF THE SOFTWARE IS HEREBY TRANSFERRED.
;
;     THE INFORMATION  IN  THIS  SOFTWARE  IS  SUBJECT  TO  CHANGE
;     WITHOUT  NOTICE  AND SHOULD NOT BE CONSTRUED AS A COMMITMENT
;     BY DIGITAL EQUIPMENT CORPORATION.
;
;     DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY
;     OF  ITS  SOFTWARE  ON  EQUIPMENT  WHICH  IS  NOT SUPPLIED BY
;     DIGITAL.

	SEARCH	QSRMAC,GLXMAC	;PARAMETER FILE

	PROLOGUE(QSRIPC)	;GENERATE THE NECESSARY SYMBOLS


MSGSIZ:	BLOCK	1		;RECIEVED MESSAGE LENGTH
SUBTTL	Global Entry Points in QSRIPC


	INTERN	C$GET		;Get next message from the IPC queue
	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$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:	MOVEI	H,HDRIPC##		;LOAD H
	PUSHJ	P,C%RECV		;GET ANY INCOMING MESSAGES
	JUMPT	GET.1			;GOT ONE, INCLUDE IN IPC QUEUE
	LOAD	AP,.QHLNK(H),QH.PTF	;GET POINTER TO 1ST ENTRY
	JUMPE	AP,.RETT		;RETURN IF NONE
	PJRST	M$DLNK##		;DLINK THE ENTRY AND RETURN

GET.1:	$COUNT	(RIPC)			;TALLY MESSAGES RECEIVED
	MOVE	T1,S1			;COPY MDB ADDRESS
	PUSHJ	P,M$GFRE##		;GET A CELL FOR THE MESSAGE
	MOVE	S1,MDB.SI(T1)		;GET SENDER'S SPECIAL INDEX
	MOVEM	S1,IPCIDX(AP)		;...
	MOVE	S1,MDB.SP(T1)		;SENDERS PID
	MOVEM	S1,IPCSDR(AP)		;...
	MOVE	S1,MDB.RP(T1)		;RECEIVERS PID
	MOVEM	S1,IPCRCR(AP)		;...
	MOVE	S1,MDB.CD(T1)		;SENDERS CONNECTED DIRECTORY
	MOVEM	S1,IPCCDI(AP)		;...
	MOVE	S1,MDB.SD(T1)		;SENDERS LOGGED IN DIRECTORY
	MOVEM	S1,IPCSID(AP)		;...
	MOVE	S1,MDB.PV(T1)		;SENDERS PRIVS
	MOVEM	S1,IPCPRV(AP)		;...
	LOAD	S1,MDB.MS(T1),MD.CNT	;LENGTH OF RECEIVED DATA
	STORE	S1,IPCMES(AP),IPM.CT	;...
	STORE	S1,MSGSIZ		;SAVE THE MSG LENGTH HERE ALSO
	MOVE	T2,[POINT 7,IPCACT(AP)]	;GET A DESTINATION BYTE POINTER.
	MOVE	S1,[POINT 7,G$ACTS##]	;GET SOURCE POINTER
GET.2:	ILDB	S2,S1			;COPY THE ACCOUNT STRING FROM THE
	IDPB	S2,T2			;MDB TO THE MESSAGE QUEUE ENTRY.
	JUMPN	S2,GET.2		;END ON A NULL,,ELSE CONTINUE
	MOVE	S2,MDB.FG(T1)		;FLAGS
	MOVEM	S2,IPCFLG(AP)		;...
	LOAD	S1,MDB.MS(T1),MD.ADR	;ADDRESS OF RECEIVED DATA
	TXNN	S2,IP.CFV		;A PAGE MODE MESSAGE
	  JRST	GET.3			;NO, MUST MOVE THE DATA
	STORE	S1,IPCMES(AP),IPM.AD	;STORE THE ADDRESS
	JRST	GET.4			;AND LINK IT IN

	;CONTINUED ON THE NEXT PAGE
	;CONTINUED FROM THE PREVIOUS PAGE


GET.3:	HRLS	S1			;SOURCE = ADDRESS IN GLXIPC
	HRRI	S1,IPCDAT(AP)		;DESTIN = QUEUE SPACE
	STORE	S1,IPCMES(AP),IPM.AD	;STORE THAT NOW THAT WE HAVE IT
	MOVE	S2,G$MPS##		;GET THE MIN PACKET SIZE
	CAIGE	S2,SPL.SZ		;IF ITS LESS THEN THE SPOOL SIZE,
	MOVEI	S2,SPL.SZ		;    THEN USE THE SPOOL SIZE
	CAMGE	S2,MSGSIZ		;IF THE MSG SIZE IS GREATER THEN THE
	MOVEM	S2,MSGSIZ		;    QUEUE SIZE,,USE THE QUEUE SIZE
	MOVE	S2,MSGSIZ		;NOW USE THE MSG LENGTH FOR THE BLT
	ADDI	S2,(S1)			;COMPUTE END ADDRESS
	BLT	S1,-1(S2)		;MOVE THE MESSAGE TO OUR QUEUE SPACE

GET.4:	PUSHJ	P,M$ELNK##		;ADD NEW ENTRY AT THE END
	JRST	C$GET			;KEEP DOING THIS UNTIL NO MORE MESSAGES
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
	LOAD	S1,IPCMES(AP),IPM.AD	;GET THE ADDRESS OF THE MESSAGE
	ADR2PG	S1			;CONVERT TO A PAGE NUMBER
	MOVE	S2,IPCFLG(AP)		;GET FLAGS
	TXNE	S2,IP.CFV		;IS IT PAGED?
	  PUSHJ	P,M%RELP		;YES, RELEASE THE PAGE
	PJRST	M$PFRE##		;AND RETURN VIA PFRE
SUBTTL	C$INT  --  Interrupt Level Entry

;TELL IPCF MODULE THAT AN IPCF INTERRUPT HAS OCCURED

C$INT:	$BGINT(INT.PL)			;ASSUME INTERRUPT CONTEXT
	$COUNT	(IPCI)			;COUNT IPCF INTERRUPTS
	PUSHJ	P,C%INTR		;CALL SUPPORT INTERRUPT ROUTINE
	$DEBRK				;AND DISMISS THE INTERRUPT
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	S1,.IPCFP(AP)		;GET PAGE NUMBER
	PUSHJ	P,M%IPSN		;NOTIFY GLXMEM
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
	JUMPF	SNDFAI			;IF FAILS, FIND OUT WHY
	$COUNT	(SIPC)


	MOVE	S2,.IPCFL(AP)		;GET THE FLAG WORD
	TXNN	S2,IP.CFV		;PAGE-MODE SEND?
	$RETT				;NO, JUST RETURN
	HRRZ	S1,.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	S1,.IPCFP(AP)		;YES, GET PAGE NUMBER
	PUSHJ	P,M%IPRC		;PRETEND THAT WE REC'ED IT
	HRRZ	S1,.IPCFP(AP)		;GET PAGE NUMBER AGAIN
	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,1			;GET 1 MINUTE
	PUSHJ	P,I$AFT##		;AGE IT
	PUSHJ	P,G$STIM##		;AND STORE WAKEUP TIME
	$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,S1			;GET LEN,,ADR BACK
	HRRZS	S1			;JUST GET ADR (PAGE NO.)
	PJRST	M%IPRC			;NOTIFY GLXMEM AND RETURN THROUGH IT
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:	SKIPN	HDRIPS##+.QHLNK		;MAKE A VERY FAST CHECK FIRST
	$RETT				;NOTHING THERE, RETURN
	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:	JUMPE	P1,RSND.2		;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

RSND.2:	SKIPN	HDRIPS+.QHLNK		;IS THERE ANYTHING IN THE QUEUE?
	$RETT				;NO, RETURN
	MOVEI	S1,1			;LOAD 1 MINUTE
	PUSHJ	P,I$AFT##		;FROM NOW
	PUSHJ	P,G$STIM##		;SET ALARM CLOCK
	$RETT				;AND RETURN
	END