Google
 

Trailing-Edge - PDP-10 Archives - BB-D351B-SM - sources/c11sim.mac
There are 9 other files named c11sim.mac in the archive. Click here to see a list.
; C11SIM - CAL11. simulation for TOPS20.

;
;		     COPYRIGHT (c) 1980, 1979, 1978,1977
;                    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.
;
	SUBTTL	Entries, Universals, and version

	ENTRY	CAL11$			; CAL11. simulation routines
	ENTRY	FLSHFE			; 2020 DDCMP Q flush routine
	ENTRY	PRCTYP			; Processor typing routine

	SEARCH	MACTEN,UUOSYM,MONSYM

	%%MACT==%%MACT			; Show MACTEN version
	%%UUOS==%%UUOS			; Show UUOSYM version
;	%%MONS==%%MONS			; Show MONSYM version

	SALL				; Suppress macro expansion

; Version information

	C11VER==1			; Major version number
	C11MIN==2			; Minor version number
	C11EDT==23			; Edit level
	C11WHO==0			; Who last patched

	TWOSEG				; Two segment program
	RELOC	400000			; Start in the HISEG

; Now Define a Title Macro

	DEFINE	..TITL(V,E,W),<
IFE	W,<TITLE C11SIM  CAL11. UUO (.C11QU) Simulation Facility - Ver V(E)>
IFN	W,<TITLE C11SIM  CAL11. UUO (.C11QU) Simulation Facility - Ver V(E)-W>
>

; Now make a Title

	..TITL	\C11VER,\C11EDT,\C11WHO
	SUBTTL	Revision History

; Revision History
;
; Edit 16 - June 29, 1977
;
; Edit 17 - September 29, 1977
;		Remove SIBE to improve performance. TOPS-20 Monitor Group
;		claims that if the -11 crashes the SIN will give an error
;		return.
; Edit 20 - September 25, 1978
;		Add Macro definitions for accessing RCVHDR and XMTHDR.
;		Fix bug in returning JSYS error code. Change LIMBYT from
;		4000 to 4064 (MAXBYT*16).
;
; Edit 21 - May 2, 1979
;		Add 2020 support code. Add new copyright notice. Remove
;		ego-building initials from code.
;
; Edit 22 - May 11, 1979
;		Put check for sending more than LIMBYT bytes to front-end
;		at the correct place to prevent -11 from receiving two
;		successive headers.
;
; Edit 23 - May 15, 1979
;		Word allignment no longer required for reading and writing
;		to the DN22 so take out the extra layer of buffering.
;
	SUBTTL	Definitions

; AC Definitions

	T1=1				; Temporary
	T2=2
	T3=3
	T4=4
	C11=5				; Points to the CAL11. Block
	P=17				; Points to the Pushdown list

	ND	MXB220,^O274		; Maximum number of bytes that 2020
					;  can ship over DDCMP link.
	ND	MAXBYT,^D254		; Maximum number of bytes that can be
					;  to the PDP11 at a time.
	ND	LIMBYT,<MAXBYT*^D16>	; Maximum number of bytes to transfer
					;  without giving up the resources.
	SUBTTL	CAL11. UUO Definitions

; Functions

	.C11DP==0			; Deposit function
	.C11EX==1			; Examine function
	.C11QU==2			; Queue request function
	.C11NM==3			; Return name of program running
	.C11UP==4			; Return 0 if PDP11 is down
					; Return 1 if PDP11 is up

; Error codes

	C11NP%==1			; Caller does not have POKE privileges
	C11UF%==2			; The function is undefined on this
					;  type of front end
	C11ND%==3			; Invalid DL10 port number
	C11IU%==4			; CAL11. in use, try again later
	C11NA%==5			; No answer from the front end after
					;  1-2 seconds
	C11TS%==6			; Queue entry too short  (DC76 only)
	C11NE%==7			; Not enough arguments
	C11AI%==10			; Examine/Deposit address was invalid
					;  (more than 16 bits or front end
					;  flagged it as invalid), or deposit
					;  data was more than 16 bits
	C11OR%==11			; In .C11QU, illegal function code,
					;  address check, illegal byte size,
					;  byteoffset is outside buffer, or
					;  buffer is too large (requires more
					;  than 16 DL10 byte pointers), or more
					;  than 4095 bytes on a DTE20.

; Result codes returned by PDP11 in header

	RC.SUC==1			; Operation successful
	RC.DLY==2			; Operation delayed
	RC.REJ==3			; Operation rejected, read status
; For .C11QU function
;
;	MOVE	AC,[XWD	Length,Address]
;	CAL11.	AC,
;	  Error return
;	Success return
;
;
; ADR:	XWD	Port number,.C11QU
;	XWD	Line number,Device number
;	XWD	Number of bytes,Function code
;	XWD	Length of buffer,Buffer address
;	BYTE (12) Number of bytes per word (24) Position of first byte
;	XWD	Number of bytes transferred,Result code

; Definitions to access the "C11BLK"

	DEFST.	(C%PORT,0(C11),-1B17)	; The port number
	DEFST.	(C%LINE,1(C11),-1B17)	; The line number
	DEFST.	(C%DEV,1(C11),777777)	; The device number
	DEFST.	(C%NBYT,2(C11),-1B17)	; The number of bytes
	DEFST.	(C%FC,2(C11),777777)	; The function code
	DEFST.	(C%BUFS,3(C11),-1B17)	; The buffer size in words
	DEFST.	(C%BUFA,3(C11),777777)	; The buffer address
	DEFST.	(C%BPW,4(C11),-1B11)	; The number of bytes per word
	DEFST.	(C%PFB,4(C11),77777777)	; The position of the first byte
	DEFST.	(C%BXFD,5(C11),-1B17)	; The number of bytes transferred
	DEFST.	(C%RC,5(C11),777777)	; The result code

; Definitions to access XMTHDR

	DEFST.	(X%FC,XMTHDR,377B15)	; Function code
	DEFST.	(X%LINE,XMTHDR,377B23)	; Line number
	DEFST.	(X%DEV,XMTHDR,377B31)	; Device number
	DEFST.	(X%LEN,XMTHDR+1,377B15)	; Number of data bytes

; Definitions to access RCVHDR

	DEFST.	(R%RC,RCVHDR,377B7)	; Result code returned by PDP11
	DEFST.	(R%LINE,RCVHDR,377B23)	; Line number
	DEFST.	(R%DEV,RCVHDR,377B31)	; Device number
	DEFST.	(R%LEN,RCVHDR+1,377B15)	; Number of data bytes the -11 absorbed
	SUBTTL	Simulate the CAL11. UUO

; Here to simulate the .C11QU function of the CAL11. UUO
;
; CALL:	PUSHJ	P,CAL11$		; AC 1 points to the CAL11. block
;					; AC 2 contains the JFN (TOPS20)
;					;   or -1,,line number on 2020.
;					; AC P points to a PDL
;	ERROR RETURN			; T1 contains the error code
;	OK	RETURN			; T1 points to the CAL11. block
;					; T2 contains the JFN

CAL11$:	PUSH	P,1			; Remember where CAL11. block is
	MOVE	1,[XWD	2,SAVEAC]	; Save AC'S 2-5
	BLT	1,SAVEAC+3		; Do it
	POP	P,C11			; Put adr of CAL11. block here
	HRRZM	2,JFN			; Remember the JFN (TOPS20)
	MOVEM	P,PDL			; Remember where the PDL was
	STORE	(T1,FIRZRO,LSTZRO,0)	; Zero from FIRZRO thru LSTZRO
	LOAD.	(T3,C%PORT)		; Get the port number
	SUBX	T3,10			; Make it the DTE number
	CAXL	T3,0			; Make sure its in
	 CAXLE	T3,3			;  the range of 0-3 (10-13)
	  PJRST	ILLPRT			; Illegal port number
	MOVX	T2,<POINT 8,XMTHDR,7>	; Pointer to where the XMT HDR is
	LOAD.	(T1,C%FC)		; Get the function code
	IDPB	T1,T2			; Put function code in XMIT HDR
	LOAD.	(T1,C%LINE)		; Get the line number
	IDPB	T1,T2			; Put the line number in the XMIT HDR
	LOAD.	(T1,C%DEV)		; Get the line number
	IDPB	T1,T2			; Put the device number in the XMIT HDR
	IBP	T2			; Go over high order of length
					;  cause can only have 8 bits worth
					;  under TOPS20
	LOAD.	(T1,C%NBYT)		; Get number of bytes
	 JUMPLE	T1,ILLARG		; Zero is illegal
	SKIPE	KSFLG			; Check for 2020
	 JRST	[CAXLE	T1,MXB220	;  Check for max bytes for DDCMP
		  MOVX	T1,MXB220	;   Too many .. truncate
		 JRST	HDR.5]
	CAXLE	T1,MAXBYT		; Larger than max allowed?
	 MOVX	T1,MAXBYT		;  Set to max for DTE
HDR.5:	IDPB	T1,T2			; Put the number of bytes in XMIT HDR
	MOVE	1,C11			; Point reg. 1 to CAL11. block
	PUSHJ	P,ENQ$			; Request access
	 JRST	[CAIE	T1,ENQX6	;  Inuse?
		  PJRST	JSYER1		;   Yes, give JSYS error
		 PJRST	C11E4]		;  Yes, give CAL11. error 4
	MOVE	T1,JFN			; JFN for SOUT
	MOVX	T2,<POINT 8,XMTHDR>	; Pointer to the xmit hdr for SOUT
	MOVX	T3,-6			; Length of header to go out
	SKIPE	KSFLG			;  Check for 2020
	 JRST	[PUSHJ	P,FLSHFE	;   Yes .. so flush any garbage msgs
		  JFCL
		 PUSHJ	P,WR2020	;   Write to the DN200
		  JRST	TIMOUT		;    No answer from front end
		 JRST	CL1S.2]		;   Continue on.
	SOUT				; Output the header
	 ERJMP	JSYER2			;  SOUT failed on FE device
	PUSHJ	P,FLUSH			; Make sure header is out of TOPS20
CL1S.2:	LOAD.	(T1,C%FC)		; Get function code
	TRNN	T1,1			; Odd function code means read
	 JRST	WRITE			;  take care of write
; Here for read functions 

READ:	PUSHJ	P,GETHDR		; Get the header
	LOAD.	(T1,R%LEN)		; Get num of bytes returned in the HDR
	MOVEM	T1,NBXFR		; Save no of bytes
	JUMPE	T1,READFN		; If no bytes to follow don't read any
	PUSHJ	P,MKPNT			; Make pointer to buffer in T2
	LOAD.	(T4,R%LEN)		; Get number of bytes again
	MOVNS	T3			; Length of user's buffer
	CAMLE	T4,T3			; Will message fit?
	 PJRST	ILLARG			;  No, give error.
	MOVN	T3,T4			; Yes, read as many bytes told by HDR
	SKIPE	KSFLG			; Check if working on a 2020
	 JRST	[PUSHJ	P,RD2020	;  Yes .. so read 2020 style
		  JRST	JSYER3		;   Error while reading from FE
		 JRST	READFN]		;  Get result (don't need to break I/O)
	SIN				; Get the data portion
	 ERJMP	JSYER3			;  Input from FE device failed
	PUSHJ	P,FLUSH			; Make sure TOPS20 doesn't hold back
READFN:	LOAD.	(T1,R%RC)		; Get result code
	LOAD.	(T2,R%LEN)		; Get number of bytes transferred
	JRST	SRCBYT			; Exit
; Here for write functions

WRITE:	LOAD.	(T1,C%NBYT)		; Save byte count specified
	MOVEM	T1,TOTBYT		;  for restoring at exit
	LOAD.	(T1,C%PFB)		; Save position of first byte
	MOVEM	T1,POSBYT		;  for restoring later
WRITEB:	PUSHJ	P,MKPNT			; Prepare for more, point to data
	SKIPE	KSFLG			; Check for working on a 2020
	 JRST	[PUSHJ	P,WR2020	;  Yes .. so write 2020 style to FE
		  JRST	JSYER4		;   Error while writing
		 JRST	WRIT.5]		;  Go get header (no I/O break needed)
	SOUT				; Send the data
	 ERJMP	JSYER4			;  Output to FE device failed
	PUSHJ	P,FLUSH			; Make sure data is out of TOPS20
WRIT.5:	PUSHJ	P,GETHDR		; Get HDR with length and result code
	LOAD.	(T2,R%LEN)		; Count of bytes returned
	ADDM	T2,NBXFR		; Update # of bytes xferred
	LOAD.	(T1,R%RC)		; Get result code
	CAXE	T1,RC.SUC		; Successful?
	 JRST	FINIS2			;  No, tell the caller
	LOAD.	(T1,C%PFB)		; Update the position
	ADD	T1,T2			;  of first byte in
	STOR.	(T1,C%PFB)		;  the CAL11. block
	LOAD.	(T1,C%NBYT)		; Update the count
	SUB	T1,T2			;  of bytes left to
	STOR.	(T1,C%NBYT)		;  transfer for next time
	JUMPE	T1,FINISH		; Exit if nothing left
	MOVE	T2,NBXFR		; Transferred enough
	CAXL	T2,LIMBYT		;  to take a break?
	 JRST	FINISD			;   Yes, give delayed result
	SKIPE	KSFLG			; Check for 2020
	 JRST	[CAXLE	T1,MXB220	;  Check for max bytes for DDCMP
		  MOVX	T1,MXB220	;   Too many .. truncate
		 JRST	WRT.5]
	CAXLE	T3,MAXBYT		; Larger than max allowed?
	 MOVX	T3,MAXBYT		;  Set to max for DTE
WRT.5:	STOR.	(T1,X%LEN)		; Put number of bytes in xmit header
	MOVE	T1,JFN			; Prepare to send header
	MOVX	T2,<POINT 8,XMTHDR>	; Point to xmit header
	MOVX	T3,-6			; Length of xmit header
	SKIPE	KSFLG			; Check for a 2020
	 JRST	[PUSHJ	P,WR2020	;  Yes .. so write on DDCMP link
		  JRST	JSYER5		;   Error while sending header
		 JRST	WRITEB]		;  Done sending header, go try again
	SOUT				; Output header
	 ERJMP	JSYER5			;  Output to FE device failed
	PUSHJ	P,FLUSH			; Make sure header is out of TOPS20
	JRST	WRITEB			; Loop till all done

FINISD:	SKIPA	T1,[EXP	RC.DLY]		; Give delayed return
FINISH:	LOAD.	(T1,R%RC)		; Get result code in T1
FINIS2:	MOVE	T2,TOTBYT		; Restore total byte count
	STOR.	(T2,C%NBYT)		;  in the CAL11. block
	MOVE	T2,POSBYT		; Restore byte-position
	STOR.	(T2,C%PFB)		;  also
	MOVE	T2,NBXFR		; Get count of bytes xferred
SRCBYT:	STOR.	(T1,C%RC)		; Put where CAL11. UUO would
	STOR.	(T2,C%BXFD)		; Put where CAL11. UUO would put count
	AOS	(P)			; Give skip return
	MOVE	1,C11			; Restore AC 1
	PJRST	RELDEV			; Deque device, restore AC'S
	SUBTTL	Routines

; Here to get the header
;
; CALL:	PUSHJ	P,GETHDR		; JFN contain JFN
;	 RETURN				; If SIN fails
;	RETURN				; Success with header in "RCVHDR"

GETHDR:	MOVE	T1,JFN			; JFN
	MOVX	T2,<POINT 8,RCVHDR>	; Where to put the header
	MOVX	T3,-6			; 6 bytes of header
	SKIPE	KSFLG			; Check for a 2020
	 JRST	GH2020			;  Yes .. so read from DDCMP link
	SIN				; Get the header
	 ERJMP	JSYER6			;  Input from FE device failed
	PJRST	FLUSH			; Return with header in "RCVHDR"

GH2020:	PUSHJ	P,RD2020		; Read header 2020 style
	 JRST	JSYER6			;  Error while reading header
	POPJ	P,			; Return (I/O break not needed)


; Routine to make sure data gets out
;
; CALL:	PUSHJ	P,FLUSH
;	RETURN

FLUSH:	MOVE	T1,JFN			; JFN
	MOVX	T2,.MOEOF		; Force output
	MOVX	T3,1			; Flush buffers w/o sending real EOF
	MTOPR				; Make sure all is output
	 ERJMP	JSYER7			;  Buffer flushing on FE device failed
	POPJ	P,			; Return
; Routine to make a pointer to the buffer
;
; CALL:	PUSHJ	P,MKPNT
;	RETURN				; T1 contains JFN
;					; T2 contains pointer
;					; T3 contains neg length

MKPNT:	LOAD.	(T2,C%BPW)		; Get number of bytes per word
	CAXL	T2,4			; Can only have 4-6
	 CAXLE	T2,6			;  bytes per word
	  PJRST	ILLARG			;   Bytes per word out of range
	LOAD.	(T3,C%BUFA)		; Get address of buffer
	LOAD.	(T4,C%BUFS)		; Get size of buffer in words
	ADDI	T4,-1(T3)		; Point to last address in the buffer.
	HLL	T3,[POINT 8,		; 4 bytes per word
		    POINT 7,		; 5 bytes per word
		    POINT 6,]-4(T2)	; 6 bytes per word
	LOAD.	(T2,C%PFB)		; Get number of bytes
	ADJBP	T2,T3			; Point to right place
	LOAD.	(T1,C%NBYT)		; Get number of bytes
	ADJBP	T1,T2			; Figure last address in the buffer
	CAIGE	T4,(T1)			; Exceeding buffer?
	 PJRST	ILLARG			;  Yes, illegal arg in argument block
	LOAD.	(T3,C%NBYT)		; Get number of bytes
	SKIPE	KSFLG			; Check for 2020
	 JRST	[CAXLE	T3,MXB220	;  Check for max bytes for DDCMP
		  MOVX	T3,MXB220	;   Too many .. truncate
		 JRST	MKP.5]
	CAXLE	T3,MAXBYT		; Larger than max allowed?
	 MOVX	T3,MAXBYT		;  Set to max for DTE
MKP.5:	MOVNS	T3			; Make negative byte count
	MOVE	T1,JFN			; Return JFN in T1
	POPJ	P,			; Return T2 contains pointer
					;  and T3 contains -length
					;  and T1 contains the JFN
; Here on various JSYS errors

JSYER1:	JSP	T2,JSYERX		; Error 1
JSYER2:	JSP	T2,JSYERX		; Error 2
JSYER3:	JSP	T2,JSYERX		; Error 3
JSYER4:	JSP	T2,JSYERX		; Error 4
JSYER5:	JSP	T2,JSYERX		; Error 5
JSYER6:	JSP	T2,JSYERX		; Error 6
JSYER7:	JSP	T2,JSYERX		; Error 7
JSYER8:	JSP	T2,JSYERX		; Error 8
JSYERX:	SUBX	T2,JSYER1		; Compute the
	HRRZS	T2			;  error code (1-8)
JSYERC:	MOVEM	T2,JSYERR		; Remember the error code
	MOVX	T1,.FHSLF		; Get the JSYS
	GETER				;  error code from the monitor
	HRRZ	T1,T2			; Get it in T1 for return from this
	JRST	ERRRET			; Return from the CAL11. simulation

; Here if we timed out waiting for a response from the PDP11

TIMOUT:	MOVX	T1,C11NA%		; Timeout error code
	JRST	ERRRET			; Give error return

; Here if a lock was already requested for the device

C11E4:	MOVX	T1,C11IU%		; Device in use
	JRST	ERRRET			; Give error return

; Here if a illegal argument discovered in the CAL11. function block

ILLARG:	MOVX	T1,C11OR%		; Illegal arg return
	JRST	ERRRET			; Give error return

; Here if the port number is out of range in the CAL11. function block

ILLPRT:	MOVX	T1,C11ND%		; Illegal port number
ERRRET:	MOVE	P,PDL			; Reset PDL pointer
RELDEV:	PUSH	P,T1			; Save this as it has user info in it
	PUSHJ	P,DEQ$			; Deq the device
	 PJRST	JSYER8			;  Deq didn't work
	POP	P,T1			; Restore this AC
RESEXT:	MOVE	5,[XWD	SAVEAC,2]	; Restore AC'S
	BLT	5,5			;  2-5
	POPJ	P,			; Return to caller
	SUBTTL	Routines to read/write to a DN200

; Routine - FLSHFE
;
; Function - This routine has two functions.  First it insures that
;	the processor type has been checked and second if it is a 2020
;	it will flush the DDCMP monitor Q's.
;
; Parameters -
;
;	T1/	Line number for DN200

FLSHFE:	SKIPN	APRNUM			; Is the CPU serial number known
	 PUSHJ	P,PRCTYP		;  No .. go check processor type
	SKIPN	KSFLG			; Check for a 2020
	 JRST	CPOPJ1			;  No .. so just return

	PUSH	P,T2			; Save a register

	MOVEI	T2,BTARG		; Point to BOOT argument block
	MOVEM	T1,.BTDTE(T2)		; Set the line number

FLSH.1:	MOVX	T1,MXB220		; Get maximum possible byte count
	MOVEM	T1,.BTLEN(T2)		; Set number of bytes to read
	MOVE	T1,[POINT 8,XMSG]	; Point to message area
	MOVEM	T1,.BTMSG(T2)		; Set pointer to 8 bit byte area
	MOVX	T1,.BTRDD		; Read DDCMP message function code
	BOOT				; Do the read
	 ERJMP	FLSH.6			;  Error while flushing
	SKIPE	.BTLEN(T2)		; Check for no message returned
	 JRST	FLSH.1			;  Message there .. continue Q flush
	MOVE	T1,.BTDTE(T2)		; Done flushing .. restore line number
	AOS	-1(P)			; Success is a skip return

FLSH.6:	POP	P,T2			; Restore a register
	POPJ	P,			; Return	
; Routine - WR2020
;
; Function - To simulate a SOUT JSYS to a FE device.  Actually it ships the
;	data over a DDCMP link on a 2020 to a DN200 (or equivalent).
;
; Parameters -
;
;	T1/	Line number
;	T2/	Byte pointer to string
;	T3/	Negative byte count

WR2020:	PUSH	P,T4			; Save some registers

	MOVEM	T1,.BTDTE+BTARG		; Set the line number
	MOVMM	T3,.BTLEN+BTARG		; Set the byte count to transfer
	MOVEM	T2,.BTMSG+BTARG		; Set pointer in BOOT block
	SKIPLE	T3			; Check for illegal byte count
	 JRST	WR2.F			;  Yes .. error return
	MOVEI	T2,BTARG		; Get pointer to BOOT arg block
	MOVX	T1,.BTSDD		; Send DDCMP message to DN200
	BOOT
	 ERJMP	WR2.F			;  BOOT failed .. can't talk to FE
	MOVE	T1,.BTDTE+BTARG		; On success .. get line number back
	SETZ	T3,			; Say that all bytes were output
	AOS	-1(P)			; Skip return (success)

WR2.F:	POP	P,T4			; Restore registers
	POPJ	P,			; Return
; Routine - RD2020
;
; Function - To simulate a SIN JSYS to a FE device on a 2020 DN200 DDCMP link.
;
; Parameters -
;
;	T1/	Line number of DUP to DN200
;	T2/	Byte pointer to string destination
;	T3/	Negative byte count to read in

RD2020:	PUSH	P,T4			; Save a register

	DMOVEM	T1,RDSAVE		; Save the read arguments
	MOVEM	T3,RDSLEN		;  including the data string length
	MOVX	T4,20			; Set up the retry counter so that
	MOVEM	T4,RETRY		;  we try at least 5 seconds worth
	MOVEI	T2,BTARG		; Get location of BOOT arg block
	MOVEM	T1,.BTDTE(T2)		; Set the line number in BOOT block

RD20ST:	MOVMM	T3,.BTLEN(T2)		; Set the byte count to transfer
	MOVE	T1,RDSAVE+1		; Point to message area
	MOVEM	T1,.BTMSG(T2)		; Set pointer to 8 bit byte area
	MOVX	T1,.BTRDD		; Read DDCMP message function
	BOOT				; Do the read
	 ERJMP	RD2.F			;  BOOT failed .. can't listen to DN200
	SKIPN	T1,.BTLEN(T2)		; Get transfered length/error code
	 JRST	R20RTY			;  If zero .. must try again
	TXNN	T1,BT%CTL		; Check for control message flag
	 JRST	R20OK			;  No .. so message was read ok
	CAXE	T1,BT%CTL+.BTCMP	; Transmission complete?
	 JRST	RD2.F			;  No .. line just glitched .. FE dead
	JRST	R20AGN			; Try to read it again

R20RTY:	SOSGE	T4,RETRY		; Have we already tried enough?
	 JRST	RD2.F			;  Yes .. FE not answering because dead
	MOVE	T1,[DEC 1000,1000,1000,1000,1000,100,100,100
		    DEC 100,100,100,100,100,100,100,100](T4)
	DISMS				; Increasing sleep increments
R20AGN:	MOVE	T3,RDSLEN		; Get length to read back again
	JRST	RD20ST			; Go try to read it again

R20OK:	ADDM	T1,RDSLEN		; Make it minus the number yet to get
	MOVE	T1,RDSAVE		; Restore line number on success
	MOVE	T3,RDSLEN		; Get updated string length
	AOS	-1(P)			; Skip return is success

RD2.F:	POP	P,T4			; Restore registers
	POPJ	P,			; Return
	SUBTTL	PRCTYP -- Routine to type the processor

; Routine - PRCTYP
;
; Function -
;
;	This routine determines whether we are running on a KL or KS system.
;
; Parameters - none
;
; Returns - +1 always
;
;	APRNUM/	Contains the processor serial number
;	KSFLG/	0 if KL, non-zero if KS

PRCTYP:	PUSH	P,T1			; Save some registers
	PUSH	P,T2
	MOVE	T1,[SIXBIT \APRID\]	; Table in TOPS20 to check
	SYSGT				;  for the processor serial number
	MOVEM	T1,APRNUM		; Save the processor serial number
	SETZM	KSFLG			; Default to KL
	CAIL	T1,^d4096		; Test for a KS serial number
	 SETOM	KSFLG			;  Yes .. so set such an indicator
	POP	P,T2			; Restore the registers
	POP	P,T1
	POPJ	P,
; Routine to get sole access of a FE device
;
; CALL:	PUSHJ	P,ENQ$			; AC(1) points to the CAL11. block
;	 RETURN				;  with JSYS error code in AC(1)
;	RETURN				; If got device and "$ENQF" is
;					;  set to -1.

ENQ$::	HLRZ	T1,(1)			; Get the port number
	DPB	T1,[POINT 3,ENQBUF+1,20] ; Put in low digit in ASCIZ string
	LSH	T1,-3			; Get next digit (should be 0 for now)
	DPB	T1,[POINT 3,ENQBUF+1,13] ; Put in high digit in ASCIZ string
	MOVX	T1,.ENQBL		; ENQ function code, blocking
	MOVEI	T2,ENQBLK		; Point to the argument block
	ENQ				; Request access
	 ERJMP	CPOPJ			;  Give non skip return
	SETOM	$ENQF			; Flag we got the device

CPOPJ1:	AOS	(P)			; Skip return
CPOPJ:	POPJ	P,			; Return to caller



; Routine to release the device
;
; CALL:	PUSHJ	P,DEQ$
; 	 RETURN				; If DEQ fails
;	RETURN				; Device dequeued and "$ENQF" = 0.

DEQ$::	SKIPN	$ENQF			; Do we have the device?
	 JRST	CPOPJ1			;  No, give skip return
	SETZM	$ENQF			; Flag we let go
	MOVX	T1,.DEQDR		; DEQ function code
	MOVEI	T2,ENQBLK		; Point to the function block
	DEQ				; Let go of the device
	 ERJMP	CPOPJ			; Give nonskip return
	JRST	CPOPJ1			;  and give skip return

; ENQ/DEQ argument block

ENQBLK:	XWD	1,5			; 1 lock,,length is 5
	XWD	0,0			; CHN 0,,ID
	EXP	EN%BLN+EN%LTL+<0,,-3>	; Long term,, OPERATOR only
	POINT	7,ENQBUF		; String pointer
	XWD	0,0			; 1 resource,,Num of accesses

; Don't show listing of literals

	XLIST
	LIT
	LIST
	SUBTTL	Low segment storage


	RELOC

ENQBUF:	ASCIZ	\DN60-P00\		; Build the ENQ/DEQ string here

JFN:	BLOCK	1			; Save the JFN here
PDL:	BLOCK	1			; Save ACP here

SAVEAC:	BLOCK	4			; Save AC'S 2-5 here

APRNUM:: BLOCK	1			; Proccessor serial number
KSFLG::	BLOCK	1			; Flag set for 2020
XMSG:	BLOCK	^O275/4			; Buffer for flushing DDCMP q's.
BTARG:	BLOCK	5			; BOOT JSYS argument block
RDSAVE:	BLOCK	2			; Temporary locals for RD2020 arg's
RDSLEN:	BLOCK	1
RETRY:	BLOCK	1			; BOOT JSYS retry counter

FIRZRO:					; From FIRZRO thru LSTZRO get zero'd
XMTHDR:	BLOCK	2			; Transmission header

RCVHDR:	BLOCK	2			; Recieve header

$ENQF::	BLOCK	1			; If nonzero, we have a device enq'd.

POSBYT:	BLOCK	1			; Position of first byte
TOTBYT:	BLOCK	1			; Total byte count
NBXFR:	BLOCK	1			; Bytes transferred
JSYERR:	BLOCK	1			; JSYS error code (1-8)

	LSTZRO==.-1			; Last location that gets zero'd

	END
; Local Modes:
; Comment Start:;
; Mode:MACRO
; Comment Column:40
; Auto Save Mode:2
; Word Abbrev Mode:1
; End: