Google
 

Trailing-Edge - PDP-10 Archives - BB-V552A-SB_1983 - d60ser.mac
There are 4 other files named d60ser.mac in the archive. Click here to see a list.
TITLE D60SER -- UUO AND INTERRUPT SERVICE FOR THE DL11 AND DTE-20 DN60 SERIES - V020
SUBTTL	ED FORTMILLER/EGF and JOHN SAUTER/JBS  29 JAN 80

	SEARCH	F,S
	$RELOC
	$HIGH




;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION
; 1976,1977,1978,1979,1980,1982
XP	V60SER,020			;VERSION NUMBER

ENTRY	D60SER
D60SER:

;DEFINE THE DN60 FUNCTION CODES
;
	F6.RD==:1			;READ DATA
	F6.WD==:2			;WRITE DATA
	F6.RDS==:3			;READ DEVICE STATUS
	F6.WDC==:4			;WRITE DEVICE STATUS
	F6.RLS==:5			;READ LINE STATUS
	F6.WLC==:6			;WRITE LINE COMMAND
	F6.R6S==:7			;READ DN60 STATUS
	F6.W6C==:^D8			;WRITE DN60 COMMAND

	F6.QMX==:^D8			;LARGEST FUNCTION ALLOWED IN
					; .QUE11 FUNCTION

	F6.EXM==:^D9			;EXAMINE PDP11 MEMORY
	F6.DEP==:^D10			;DEPOSIT INTO PDP11 MEMORY
	F6.MAX==:^D10			;LARGEST FUNCTION CODE

;BIT DEFINITIONS IN THE (LH) OF DLXCEU

;DEFINE A BIT THAT GETS SET IN THE (LH) OF DLXCEU TO
; INDICATE THAT THE .C11UQ FUNCTION IS THE ONE BEING DONE
;
	D6.Q11==:1			;.C11QU FUNCTION IN PROGRESS

;DEFINE A BIT WHICH WHEN SET IN THE (LH) OF DLXCEU INDICATES
; THAT THE JOB WAS LOCKED BEFORE ISSUING THE CAL11. UUO. THIS
; BIT WILL NOT BE SET FOR EXM/DEP AS WE DON'T SET NSHF OR NSWP
; IN THIS CASE.
;
	D6.ALK==:2			;SET IF JOB LOCKED PRIOR TO
					; DOING .C11QU
;D60DSP	ROUTINE CALLED BY NETSER THAT DISPATCHES TO THE PROPER FEK FUNCTION
;CALL	T1 := FUNCTION CODE
;	J := FEK ADDRESS
;RETURN	CPOPJ

D60DSP::CAIL	T1,FF.ONC	;RANGE CHECK THE FUNCTION
	CAILE	T1,FF.CPW	;  CODE AND STOP IF BAD
	STOPCD	CPOPJ,DEBUG,BFC,;++ BAD FUNCTION CODE TO FEK
	JRST	@.+1(T1)	;DISPATCH TO APPRIOATE ROUTINE
	JRST	CPOPJ##		;ONCE ONLY CODE
	JRST	D60SEC		;ONCE/SECOND CODE
	JRST	CPOPJ##		;SET UP A READ REQUEST
	JRST	CPOPJ##		;SET UP A WRITE REQUEST
	JRST	CPOPJ##		;CRASH THE FEK (CPU WENT DOWN?)
	JRST	D60DWN##	;EXIT PRIMARY PROTOCOL
	JRST	D60UP##		;START PRIMARY PROTOCOL
	JRST	CPOPJ##		;WE DON'T CARE ABOUT STATION CONTROL
	JRST	CPOPJ##		;SYSTEM SLEEP.  WHAT SHOULD I DO?
	JRST	CPOPJ##		;SYSTEM WAKE.  WHAT SHOULD I DO?


;COME HERE FOR EACH DN60 ONCE A SECOND
;
D60SEC:	SKIPN	W,FEKUNI##(J)		;PICK UP POINTER TO BASE TABLE
	  POPJ	P,			;NONE, DO NOTHING.
	PUSHJ	P,SAVE1##		;P1 USED FOR WINDOW POINTER
	SKIPL	P1,DLXWIN##(W)		;POINT P1 TO DL10 WINDOW
					; THIS WILL SKIP IF A DTE
	XCT	DLXSTA##(W)		;MARK -10 AS BEING ALIVE
	SKIPN	T2,DLXTIM##(W)		;SEE IF TIMING (NONE 0)
	  POPJ	P,			;NOT TIMING
	SKIPE	T1,DLXCEU##(W)		;CAL11. UUO BEING USED?
	CAMLE	T2,UPTIME##		;SEE IF WE TIMED OUT?
	  POPJ	P,			;NOT TIMED OUT YET
	SETZM	DLXTIM##(W)		;CLEAR OUT TIME
D60SE3:	PUSHJ	P,D60WAK		;GET THE JOB OUT OF EW AND EXIT
	PJUMPLE	P1,D6STMO##		;TAKE CARE OF TIMEOUT WHEN
					; THE PDP11 WON'T SPEAK ON A DTE.
	POPJ	P,			;RETURN
					; THE ONCE A SECOND ROUTINE
;HERE TO FINISH THE SETUP WHEN THE PDP11 IS FIRST
; RECOGNIZED AS BEING A PDP11.
;
; CALL:	JRST	D60SUP			;W POINTS TO THE BASE TABLE
;
D60SUP::SETZM	DLXCEU##(W)		;CLEAR CAL11. USERS JOB NUMBER
	MOVE	T1,[XWD MC11FN,C11FTB]
	MOVEM	T1,DLXCAL##(W)		;CAL11. POINTER
	MOVE	T1,@DLXFEK##(W)		;GET FIRST WORD OF FEK
	TLO	T1,FK.ONL		;SET ON-LINE BIT
	HLLM	T1,@DLXFEK##(W)		;PUT BACK FLAGS HALF
	MOVE	T1,DLXFEK##(W)		;GET FEK ADDRESS
	HRRZM	W,FEKUNI##(T1)		;STORE ADDRESS OF BASE TABLE
	POPJ	P,			;DONE WITH INITIALIZATION
SUBTTL	CAL11. UUO

;COME HERE ON CAL11. UUO FROM COMDEV.

;CALLING SEQUENCE IS:
;	MOVE	AC,[XWD LENGTH,BLOCK]
;	CAL11.	AC,
;	  ERROR RETURN
;	OK RETURN

;BLOCK:	EXP	FUNCTION CODE
;	ARGUMENT (1) ...
;

;ENTER FROM COMDEV WITH WINDOW POINTER IN P1 OR XWD -1,DTE #,
;  DL10 BASE IN W, LENGTH OF BLOCK IN T3.

;COMDEV DOES THE DISPATCH BASED ON THE FOLLOWING TABLE.  THE
;  HIGH ORDER BIT, IF SET, INDICATES THAT THE USER MUST HAVE
;  THE "POKE" PRIV.


C11FTB:	XWD	400000,DEP11		;(0) DEPOSIT TO -11
	XWD	400000,EXAM11		;(1) EXAMINE THE -11
	XWD	400000,QUE11		;(2) PERFORM A DN60 FUNCTION
	XWD	0,NAME11		;(3) RETURN NAME OF PGM IN 11
	XWD	0,DOWN11		;(4) IS PORT UP OR DOWN?
	XWD	400000,CPOPJ##		;(5) SEND
	XWD	400000,CPOPJ##		;(6) RECEIVE
	XWD	0,TYP11			;(7) TYPE
MC11FN==.-C11FTB			;LENGTH OF TABLE

; VALUES OF BITS IN DLXSWD:

D60.DP==:1			;DEPOSIT
D60.EX==:2			;EXAMINE
D60.ER==:4			;ADDRESS ERROR

SUBTTL	CAL11. UUO ERROR CODES

COMMENT	\

	CODE	MEANING
	----	-------

	1	Caller does not have POKE privledges
	2	The function is undefined on this type of front end
	3	Invalid DL10 port number
	4	CAL11. facility in use, try again later
	5	No answer from the front end after 1-2 seconds
	6	Queue entry too short  (DC76 only)
	7	Not enough arguments
	10	Examine/Deposit address was invalid (more than 16
		bits or the front end flagged it as invalid), or
		the deposit data was more than 16 bits
	11	In QUE11, Illegal function code,
		Address check, Illegal byte size, Byte offset is
		outside the buffer or the buffer is too large
		 (requires more than 16 DL10 byte pointers)
	12	DTESER couldn't get any free core
	13	DTE - reload bit set or primary protocol is
		not running.
	14	DTE - there never will be enough EVM

\
;SUBROUTINE TO EXAMINE OR DEPOSIT PDP11 MEMORY
;
; CALL:	MOVE	T3,+LENGTH
;	MOVEI	P1,BEGINNING ADDRESS OF THE WINDOW
;			OR -1,,DTE PORT NUMBER
;	MOVEI	W,ADDRESS OF THE BASE TABLE
;
DEP11:	SUBI	T3,1			;MUST HAVE ADDRESS AND DATA
	JSP	T4,GETADR		;GET THE ADDRESS TO DEPOSIT INTO
	PUSHJ	P,GETWD1##		;GET THE WORD TO BE DEPOSITED
	SKIPL	T4,T1			;MAKE SURE DEPOSIT DATA IS
	CAILE	T4,177777		; IN THE RANGE OF 0-177777
	  PJRST	ECOD10##		;**ERROR-10** BECAUSE DEPOSIT
					; DATA TO LARGE.
	HRLI	T4,-1			;FLAG ITS A DEPOSIT
	MOVEI	T1,D60.DP		;DEPOSIT FUNCTION
	JRST	DEPEXM			;NOW GO ATTEMPT TO DO THE DEPOSIT

EXAM11:	JSP	T4,GETADR		;GET THE ADDRESS TO EXAMINE
	SETZ	T4,			;ZERO THE DATA WORD AND FLAG EXAMINE
	MOVEI	T1,D60.EX		;EXAMINE FUNCTION

DEPEXM:	POP	P,W			;RESTORE BASE TABLE INDEX
	SKIPL	T3			;SEE IF ADDRESS IS IN THE
	CAILE	T3,177777		; RANGE OF 0-177777
	  PJRST	ECOD10##		;**ERROR-10** BECAUSE OF ILLEGAL ADDRESS
	JSP	T2,CHKCEU		;SEE IF ANYONE USING CAL11
					; **ERROR-4** IF SO
	PJUMPL	P1,D6SED##		;GO TAKE CARE OF DTE DEPOSIT/EXAMINE
	PJRST	D6DED##			;GO TAKE CARE OF DL10 DEP/EXM

;SUBROUTINE TO RETURN THE TYPE OF PDP11
;
TYP11:	MOVEI	T1,3			;DN60 TYPE FRONT-END (.C1D60)
	PJRST	STOTC1##		;RETURN DN60 TYPE
;HERE TO GET AN EXAMINE/DEPOSIT ADDRESS
;
; CALL:	JSP	T4,GETADR		;T3 CONTAINS THE LENGTH
;	RETURN				;UNLESS LENGTH TOO SHORT, THEN
;					; GIVE ERROR-7 TO THE USER. ON
;					; NON ERROR RETURN:
;					;  AC (W) IS SAVED ON THE PDL
;					;  AC (T3) CONTAINS THE ADDRESS
;
GETADR:	SOJL	T3,ECOD7##		;**ERROR-7** IF NOT ENOUGH ARGS
	PUSH	P,W			;SAVE AC (W)
	PUSHJ	P,GETWD1##		;GET THE ADDRESS TO EXAMINE/DEPOSIT
	MOVE	T3,T1			;COPY ADDRESS HERE
	JRST	(T4)			;RETURN TO THE CALLER

;HERE TO PERFORM .C11QU (2) FUNCTION
;
; CALL:	MOVE	T3,+LENGTH
;	MOVE	P1,BEGINNING ADDRESS OF THE WINDOW
;			OR -1,,DTE PORT NUMBER
;	MOVEI	W,ADDRESS OF THE BASE TABLE
;
QUE11:	SUBI	T3,5			;SEE IF ENOUGH ARGS SUPPLIED
	PJUMPL	T3,ECOD7##		;**ERROR-7** BECAUSE NOT ENOUGH ARGS
	JSP	T2,CHKCEU		;SEE IF ANYONE USING THE CAL11. UUO
					; **ERROR-4** IF SO
	PUSHJ	P,GET1WD		;GET  LINE NUMBER,,DEVICE NUMBER
	MOVE	P2,T1			;SAVE LINE NUMBER,,DEVICE NUMBER
	PUSHJ	P,GET1WD		;GET  NUMBER OF BYTES,,FUNCTION CODE
	HRRZ	P4,T1			;REMEMBER THE FUNCTION CODE
	CAIL	P4,1			;RANGE CHECK THE FUNCTION
	CAILE	P4,F6.QMX		; FOR A RANGE OF 1-10.
	  PJRST	ECOD11##		;**ERROR-11** BECAUSE OF ILLEGAL FUNCTION CODE
	HLL	P4,T1			;REMEMBER TOTAL NUMBER OF BYTES
	MOVSS	P4			;FUNCTION CODE,,NUMBER OF BYTES
	PUSHJ	P,GET1WD		;GET  LENGTH OF BUFFER,,BUFFER ADDRESS
	MOVE	P3,T1			;REMEMBER LENGTH,,BUFFER ADDRESS
	PUSHJ	P,ADRCHK		;ADDRESS CHECK THE BUFFER
	  PJRST	ECOD11##		;**ERROR-11** BECAUSE OF ADDRESS CHECK
	HLRZ	T4,P3			;GET THE LENGTH OF THE BUFFER
	ANDI	P3,-1			;LEAVE ONLY THE BUFFER ADDRESS
	PUSHJ	P,GET1WD		;GET  NUMBER OF BYTES PER WORD(12 BITS),
					; POSITION OF FIRST BYTE (24 BITS)
	MOVE	F,T1			;GET THE POSITION IN HERE
	TLZ	F,777700		;KEEP ONLY THE POSITION OF THE FIRST BYTE
	LSH	T1,-^D24		;KEEP ONLY THE NUMBER OF BYTES PER WORD
	MOVEI	S,4			;ASSUME MIN NUMBER OF BYTES PER
					; WORD FOR A DTE
	SKIPL	P1			;BUT ARE WE TALKING TO A DTE?
	  MOVEI	S,3			;NO SET MIN NUMBER OF BYTES PER
					; WORD FOR A DL10
	CAML	T1,S			;RANGE CHECK BYTE SIZE
	CAILE	T1,6			; FOR A RANGE OF (3-6 FOR A DL10)
					; AND (4-6 FOR A DTE)
	  PJRST	ECOD11##		;**ERROR-11** BECAUSE OF ILLEGAL BYTE SIZE
	MOVE	S,T1			; AND REMEMBER IT.
;
;TO COMPUTE THE FIRST ADDRESS USING IN THE BUFFER
;
;	(BYTE POSITION)/(BYTE SIZE)+(BUFFER ADDRESS)
;	AC(U) IS USED TO REMEMBER THE REMAINDER FROM
;	 (BYTE POSITION)/(BYTE SIZE) FOR LATER USE
;
	MOVE	T1,F			;GET BYTE POSITION
	IDIV	T1,S			;(BYTE POSITION)/(BYTE SIZE)
	MOVE	U,T2			;REMEMBER THE REMAINDER
	ADD	T1,P3			;PRESTO, THE FIRST ADDRESS
;
;TO COMPUTE THE LAST ADDRESS USED IN THE BUFFER
;
;	(((BYTE POSITION)+(NUMBER OF BYTES)-1)/(BYTE SIZE))+(BUFFER ADDRESS)
;
	MOVE	T2,F			;GET POSITION OF THE FIRST BYTE
	ADDI	T2,-1(P4)		;ADD IN THE NUMBER OF BYTES - 1
	IDIV	T2,S			;NOW DIVIDE BY THE BYTE SIZE
	ADD	T2,P3			;ADD THE BUFFER ADDRESS AND
					; PRESTO THE LAST ADDRESS USED.
	MOVE	T3,P3			;GET THE BUFFER ADDRESS
	ADDI	T3,-1(T4)		; AND ADD THE LENGTH-1
	CAMLE	T2,T3			;SEE IF COMPUTED BUFFER
					; IS WITHIN THE REAL BUFFER
	  PJRST	ECOD11##		;**ERROR-11** BECAUSE OF ADDRESS CHECK
;
;TO COMPUTE THE WORD COUNT
;
;	(LAST ADDRESS)-(FIRST ADDRESS)+1
;
	SUBI	T2,-1(T1)		;COMPUTE LENGTH OF BUFFER WHICH
					; WE'LL REFER TO AS  "WORD COUNT"
	PJUMPL	P1,D6SQ11##		;GO PERFORM THE FUNCTION USING A DTE
	PJRST	D6DQ11##		;GO PERFORM THE FUNCTION USING A DL10
;COME HERE TO RETURN THE NAME OF THE PDP-11 PROGRAM.
; IN THE CASE OF A PDP11 ON A DL10 THE NAME RETURNED
; WILL BE THE NAME THE PDP11 GAVE US BUT ON A DTE
; THE NAME WILL BE RETURNED FROM THE BASE TABLE.
;
; CALL:	PUSHJ	P,NAME11		;W POINTS TO THE BASE TABLE
;
NAME11:	MOVE	T1,DLXNMT##(W)		;PICK UP NAME
	PJRST	STOTC1##		;SKIP RETURN, GIVING  NAME

;COME HERE TO TELL THE STATUS OF THE PDP-11 PROGRAM.
; RETURN A 1 TO THE USER IF THE PDP11 IS UP
; OR 0 IF ITS DOWN.
;
; CALL:	PUSHJ	P,DOWN11		;P1 CONTAINS DL10 WINDOW ADDRESS
;					; OR -1,,DTE NUMBER
;					;W POINTS TO THE BASE TABLE
;
DOWN11:	SKIPGE	P1			;SKIP IF ON A DL10
	  JRST	DWND6S##		;GO HANDLE A DTE
	SKIPG	T1,DLXDWN##(P1)		;GET STATUS
D60RT0:: TDZA	T1,T1			;PDP-11 IS DOWN
D60RT1::  MOVEI	T1,1			;UP.
	PJRST	STOTC1##		;SKIP RETURN.
;THIS ROUTINE IS CALLED TO PUT A JOB INTO
; THE EVENT WAIT STATE.
;
; CALL:	PUSHJ	P,EVWAIT		;W POINTS TO THE BASE TABLE
;	RETURN				;ALWAYS
;
D60EVW::PUSH	P,M			;SAVE "M"
D60EV1:	MOVEI	T1,EV.D60		;THE EVENT WAIT CODE FOR THE DN60
	MOVE	J,.CPJOB##		;GET THE JOB NUMBER
	PUSHJ	P,FSLEEP##		;PUT JOB INTO EVENT WAIT
	SKIPE	DLXTIM##(W)		;SEE IF A DN60 WAKE
	  JRST	D60EV1			;NO, IT WAS SOME OTHER CLOWN
					; SO GO WAIT SOME MORE.
	SETZM	DLXCEU##(W)		;FREE UP THE CAL11. UUO
	PJRST	MPOPJ##			;RESTORE "M" AND RETURN TO
					; THE CALLER

;THIS ROUTINE IS CALLED TO GET A DN60 JOB OUT OF
; EVENT WAIT
;
; CALL:	PUSHJ	P,D60WAK		;T1 CONTANS JOB NUMBER
;					;W POINTS TO THE BASE TABLE
;	RETURN				;WITH DLXTIM = 0
;
D60WAK::PUSH	P,J			;SAVE J
	SETZM	DLXTIM##(W)		;FLAG WE GOT THE JOB OUT OF EW
	PUSHJ	P,D60LKC		;SEE IF WE ARE TO UNLOCK HIM
					; ALSO RETURNS JOB NUMBER IN T1
	  PUSHJ	P,D60ULJ		;YES, WE LOCKED HIM SO UNLOCK HIM
	POP	P,J			;RESTORE J
	PJRST	EWAKE##			;GO GET HIM OUT OF EW

;THIS ROUTINE IS CALLED TO PUT THE TIME IN
; THE BASE TABLE THAT THE JOB TIMES OUT AT.
;
; CALL:	PUSHJ	P,SETTIM		;T1 CONTAINS NUMBER OF SECONDS
;					;W  POINTS TO THE BASE TABLE
;	RETURN				;ALWAYS
;
D60TIM::IMULI	T1,JIFSEC##		;CONVERT TO JIFFYS
	ADD	T1,UPTIME##		;ADDING THIS MAKES THE TIME
					; THAT WE TIME-OUT AT.
	MOVEM	T1,DLXTIM##(W)		;SAVE SO ONCE-A-SECOND CODE
					; WILL KNOW THE TIME-OUT TIME
	POPJ	P,			;RETURN TO CALLER
;SUBROUTINE TO GET 1 WORD FROM THE USERS BLOCK
;
; CALL:	PUSHJ	P,GET1WD		;
;	RETURN				;T1 HAS THE WORD
;
GET1WD:	PUSH	P,W			;MUST PRESERVE AC(W)
	PUSHJ	P,GETWD1##		;GET A WORD FROM USER BLOCK
	PJRST	WPOPJ##			;RESTORE AC(W)
					; AND RETURN WITH WORD IN AC(T1)

;SUBROUTINE TO CHECK IF THE CAL11. UUO IS IN USE
;
; CALL:	JSP	T2,CHKCEU		;
;	RETURN				;IF NOT IN USE, IF IN
;					; USE GIVE **ERROR-4**
;
CHKCEU:	HRRZ	S,DLXCEU##(W)		;GET JOB NUMBER FROM BASE TABLE
	CAMN	J,S			;IS THIS THE USER WHO IS WAITING?
	  SETZM	DLXCEU##(W)		;YES, MUST HAVE USED ^C
	SKIPE	DLXCEU##(W)		;SEE IF ANY USER WAITING
	  PJRST	ECOD4##			;**ERROR-4** BECAUSE UUO IS BEING USED
	PJRST	(T2)			;RETURN TO THE CALLER

;SUBROUTINE TO UNLOCK THE JOB
;
; CALL:	PUSHJ	P,D60ULJ		;WITH JOB NUMBER IN T1
; CALL:	PUSHJ	P,D60UNL		;IF JOB NUMBER UNKNOWN (UUO LEVEL)
;	RETURN				;T1 PRESERVED, J CONTAINS JOB NUMBER
;
D60ULJ::SKIPA	J,T1			;GET JOB NUMBER FROM T1
D60UNL::MOVE	J,.CPJOB##		;GET THE JOB NUMBER
	PUSH	P,T1			;SAVE THIS
	MOVSI	T1,NSHF!NSWP		;THE LOCK BITS
	ANDCAM	T1,JBTSTS##(J)		;CLEAR THE JOB
	PJRST	TPOPJ##			;RESTORE T1 AND RETURN

;SUBROUTINE TO DETERMINE IF THE JOB IS TO BE UNLOCKED
; BEFORE RETURNING THE TO USER
;
; CALL:	PUSHJ	P,D60LKC		;W POINTS TO THE BASE TABLE
;	  RETURN			;IF NEED TO UNLOCK AND T1 CONTAINS JOB NUMBER
;	RETURN				;IF NOT TO UNLOCK JOB AND T1
;					; CONTAINS JOB NUMBER
;
D60LKC::MOVE	T1,DLXCEU##(W)		;GET BITS,,JOB NUMBER
	TLZN	T1,D6.Q11		;QUE11 FUNCTION?
	  PJRST	CPOPJ1##		;NO, EXM/DEP
	TLZN	T1,D6.ALK		;YES, WAS HE LOCKED BEFORE CAL11. ?
	  POPJ	P,			;NO, WE MUST UNLOCK HIM
	PJRST	CPOPJ1##		;YES, DON'T UNLOCK HIM
;SUBROUTINE TO VERIFY THAT THE REQUIRED PAGES ARE
;  VALID AND IN CORE.  IF VM IF THE PAGE(S) ARE NOT IN
;  CORE ATTEMPT TO BRING THEM IN.
;
; CALL:	PUSHJ	P,ADRCHK		;P3 CONTAINS  XWD LENGTH,START ADDRESS
;	RETURN				;IF ANY ADDRESS ERRORS
;	RETURN				;IF BUFFER IS IN CORE
;
ADRCHK:	HRRZ	T1,P3			;LOW ADDRESS OF BUFFER
	HLRZ	T2,P3			;THE LENGTH OF THE BUFFER
	ADDI	T2,-1(P3)		;LAST ADDRESS OF THE BUFFER
	PUSH	P,T2			;SAVE THE LAST ADDRESS
IFN	FTVM,<
ADRC1:	PUSHJ	P,FLTST##		;SEE IF PAGE FAULT WILL HAPPEN
	  PJRST	UUOFLT##		;PAGE FAULT - CALL THE PFH
>;END IFN FTVM
	PUSHJ	P,IADRCK##		;MAKE SURE VALID ADDRESS
	  PJRST	T2POPJ##		;BAD ADDRESS - CLEAN PDL AND NON-SKIP RETURN
IFN	FTVM,<
	ADDI	T1,PAGSIZ##		;GO TO THE NEXT PAGE
	CAMGE	T1,(P)			; BEYOND THE END OF OUR BUFFER
	  JRST	ADRC1			;NO, CHECK THIS PAGE
>;END IFN FTVM
	POP	P,T1			;GET THE LAST ADDRESS OF THE BUFFER
IFN	FTVM,<
	PUSHJ	P,FLTST##		;SEE IF PAGE FAULT WILL HAPPEN
	  PJRST	UUOFLT##		;PAGE FAULT - CALL THE PFH
>;END IFN FTVM
	PJRST	IADRCK##		;CHECK THE LAST ADDRESS
	$HIGH

	$LIT

D60END::END