Google
 

Trailing-Edge - PDP-10 Archives - tops20_v6_1_tcpip_distribution_tp_ft6 - 6-1-sources/ddtgp.mac
There are 16 other files named ddtgp.mac in the archive. Click here to see a list.
; COPYRIGHT (C) 1984 BY
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.

	TITLE DDTGP DDT11 GET/PUT ROUTINES AND OTHER SUPPORT FOR THEM

	SEARCH	DDTSYM,JOBDAT,MACTEN,UUOSYM,MONSYM
IFN FTT20,	SEARCH MACSYM


	SALL			;GET NICE LISTINGS FOR A CHANGE
	.HWFRMT			;AND SKIP THE FANCY BITS
	.DIRECTIVE FLBLST

ENTGP (ENTRY)			; ENTRY POINTS FOR THIS ROUTINE
ENT11 (EXTERN)
ENTFIL (EXTERN)
ENTSIM (EXTERN)

GLOB (DEFOUT)

;HERE BECAUSE FILE TO BE READ IS BINARY TAPE

SETBIN:	SWTCHK BINARY
	DBGTYP DB.INI,<%Setting file type to BINARY
>
	TXO FLG,F.FLOP
	MOVEI T1,EX.MEM
	MOVEM T1,ETYPE
	RET SKIP,SETBIN

;HERE BECAUSE FILE TO BE READ IS NETLDR (OR EQUIVALENT) DUMP

SETDMP:	SWTCHK DUMP
	SWTCHK LSD
	DBGTYP DB.INI,<%Setting file type to LSD
>
	TXZ FLG,F..FOO
	MOVEI T1,EX.MEM
	MOVEM T1,ETYPE
	RET SKIP,SETDMP

;HERE TO FLAG THAT WE ARE WORKING ON A LARGE DUMP

SETMCS:	SWTCHK MCBSYS
	DBGTYP DB.INI,<%Setting file type to MCB system
>
	SETOM F.MCB
	SETOM F.MSYS		;EXAMINE UNRUN MCB
	MOVEI T1,1
	MOVEM T1,DEFOUT		; SET OUTPUT MODE TO MCBSYS
	MOVE T1,[SIXBIT /SYSMCB/]
	MOVEM T1,DEFEXT
	JRST SETFOX

SETMCB:	SWTCHK MCBDMP
	DBGTYP DB.INI,<%Setting file type to MCB dump
>
	SETOM F.MCB
	MOVE T1,[SIXBIT /DMPSYS/]
	MOVEM T1,DEFEXT
	JRST SETFOX
				; AND FALL INTO SETFOO

;THIS ROUTINE IS CALLED IF THE TYPE OF DUMP IS "DTELDR", I.E.
; WORD,,WORD IN THE FILE.

;HERE TO SET F..FOO FOR /DISASSEMBLY OR /DTELDR

SETFOO:	SWTCHK DTELDR
	DBGTYP DB.INI,<%Setting file type to DTELDR
>
	MOVE T1,[SIXBIT /BIN   /]
	MOVEM T1,DEFEXT
SETFOX:	TXO FLG,F..FOO
	MOVEI T1,EX.MEM
	MOVEM T1,ETYPE
	RET SKIP,SETFOX

;HERE IF THE USER TYPES /MCB:node

SETDFE:	SWTCHK MCB
IFE FTT20,<
	PUSH P,T1
	MOVE T1,[XWD -1,.GTPRV]	;GET THE PRIV'S
	CALLI T1,41		;A GETTAB IN HIDING
	SETZ T1,		;ALWAYS A 0 IF IT FAILS
	TXNN T1,JP.POK		;PUT REQUIRES POKE
	JRST [POP P,T1
	 TYPE	<?MCB switch requires POKE priv
>
	 RET, SETDFE]
	POP P,T1
>;END IFE FTT20

IFN FTT20,<
	MOVX	AC1,.FHSLF	;OURSELF
	RPCAP			;READ OUR PROCESS CAPABILITIES
	TXNN	AC3,SC%WHL!SC%OPR	;ARE WE WHELL OR OPERATOR?
	JRST	[TYPE <?MCB switch requires WHEEL or OPERATOR privs
>				;TELL THE USER THE BAD NEWS
		 RET, SETDFE]	;AND RETURN
>;END IFN FTT20

	SETOM F.MCB
	CAIE T5,":"		;IS THIS THE END OF THE LINE?
	JRST [TYPE <?
?MCB switch requires node name as an argument
>
		RET ,SETDFE]
	CALL SIXIN		;GET THE NODE NAME
	RET ,SETDFE
	SKIPN T1		;WAS A NODE NAME SUPPLIED?
	JRST [TYPE <?
?MCB switch requires node name as an argument
>
		RET ,SETDFE]
	MOVEM T1,FENAME		;SAVE THE NODE NAME
	MOVE T1,[400000,,OPNMCB]
IFN DEBUG,<
	SKIPE QX,F.DEBU
	TXNN QX,DB.INI!DB.EXD
	JRST SETMC1
	PUSH P,T1
	TYPE <%Setting start address to OPNMCB for the /MCB switch
%Setting node name to >
	MOVE T1,FENAME
	CALL SIXTYP
	CALL CRLTYP
	POP P,T1
SETMC1:
>
	MOVEM T1,LASTSW
	RET SKIP,SETDFE

OPNMCB:	MOVE T2,OSTYPE		;GET OS TYPE
	CAMN T2,[T.TOP10]
	JRST OMCB10		;YES
	CAMN T2,[T.TOP20]
	JRST OMCB20		;YES
	TYPE <?
?Examine of running MCB only supported under TOPS10/20
>
	JRST DDT11

OMCB10:	MOVEI T1,EX.MC1		;EXAMINE TYPE IS TOPS-10 MCB CODE
	MOVEM T1,ETYPE		; SAVE THIS FOR LATER
;
; FIRST BUILD THE ARGUMENT BLOCK FOR THE NSP. UUO
; THIS WILL START IN NODARG, AND IS 5 WORDS LONG
;
	MOVE T1,[NS.WAI!<.NSFEA,,5>] ; FUNCTION, LENGHT OF BLOCK
	MOVEM T1,NODARG+.NSAFN
	SETZM NODARG+.NSACH	; CLEAR CHAN NUMBER
	MOVEI T1,STCMSG		; BUILD CONNECT BLOCK HERE
	MOVEM T1,NODARG+.NSAA1	; FIRST ARGUMENT WORD
	SETZM NODARG+.NSAA2	; SEGMENT SIZE, USE DEFAULT
	SETZM NODARG+.NSAA3	; FLOW CONTROL, USE DEFAULT
;
; BUILD THE CONNECT BLOCK.  THIS WILL BE IN STCMSG
; AND IS 4 WORDS LONG
;
	MOVEI T1,4		; LENGTH OF CONNECT BLOCK
	MOVEM T1,STCMSG		; SET UP FIELD FOR DECNET
	MOVEI T1,STCIMS
	MOVEM T1,STCMSG+.NSCND	; POINT TO NODE NAME
;
; THE NODE NAME BLOCK IS IN STCIMS, STARTING AT THE FIRST LOCATION
;
	MOVE AC1,[POINT 8,STCIMS+1]
	MOVE AC3,[POINT 6,FENAME]	; POINT TO SIXBIT NAME
	CALL STRBLT
	HRL T1,T2
	HRRI T1,3
	MOVEM T1,STCIMS		; THE FIRST THREE WORDS ARE THE THE NAME STRING
;
; AT STCIMS+3, WE BUILD THE SOURCE AND DESTINATION BLOCKS.
; THE SAME BLOCK IS USED, SO TASK DNDDT WILL REQUEST A CONNECTION 
; TO A TASK NAMED DNDDT
;
	MOVEI T1,STCIMS+3
	MOVEM T1,STCMSG+.NSCSD	; POINT TO SOURCE BLOCK
	MOVEM T1,STCMSG+.NSCDD	; ALSO TO THE DESTINATION BLOCK
	MOVEI T2,.NSDPN+1
	MOVEM T2,.NSDFL(T1)	; LENGTH OF SOURCE BLOCK
	MOVEI T2,1
	MOVEM T2,.NSDFM(T1)	; TYPE 1 ==> PROCESS (TASK) NAMED CONNECT
	SETZM .NSDOB(T1)	;  OBJECT TYPE
	SETZM .NSDPP(T1)	; NO PPN
	MOVEI T2,.NSDPN+1(T1)	; POINT TO STRING BLOCK OF TASK NAME
	MOVEM T2,.NSDPN(T1)	; SAVE THE POINTER
	PUSH P,T1
;
; T2 NOW POINTS TO THE SOURCE BLOCK TO BUILD
;
	MOVE T3,[SIXBIT /DNDDT/]
	MOVSI AC1,(POINT 8,0)
	PUSH P,T2
	HRRI AC1,1(T2)
	MOVE AC3,[POINT 6,T3]
	CALL STRBLT
	POP P,T2
	MOVE T1,[5,,3]
	MOVEM T1,.NSASL(T2)
	POP P,T1
	MOVEI T1,NODARG
	NSP. T1,
	 JRST [	TYPE <
?NSP. UUO failed due to a network error
>
		JRST DDT11]
	MOVE T1,NODARG+.NSACH
	MOVEM T1,FE.JFN		;  SAVE IT FOR LATER IN AN OBVIOUS PLACE
IFN DEBUG,<
	SKIPE QX,F.DEBU
	TXNN QX,DB.INI!DB.EXD
	JRST OPMCB2
	TYPE <%Connection to node >
	MOVE T1,FENAME
	CALL SIXTYP
	TYPE <, task DNDDT established.
>
OPMCB2:
>
	SETZM MEMORY
	JRST LEVL.0


; ROUTINE TO MOVE A SIXBIT STRING TO A ABIT STRING, MAX OF SIX BYTES,
; COUNT IN T2, INPUT POINTER IN AC3, OUTPUT POINTER IN AC1

STRBLT:	SETZ T2,
	MOVSI T4,-6		; ONLY 6 BYTES
	PUSH P,T5
GETN2:	ILDB T5,AC3		; GET NEXT BYTE
	JUMPE T5,GOTN2		; FINISHED?
	ADDI T5,40		; CONVERT TO ASCII
	AOS T2
	IDPB T5,AC1
	AOBJN T4,GETN2
GOTN2:	POP P,T5
	RET ,STRBLT

OMCB20:	MOVEI T1,EX.MCB		;EXAMINE TYPE IS RUNNING MCB
	MOVEM T1,ETYPE		;SAVE EXAMINE TYPE
	MOVE AC1,[POINT 7,FE.MSG] ;BUILD LOGICAL LINK FILENAME HERE
	HRROI AC2,[ASCIZ /DCN:/]
	SETZB AC3,AC4
	SOUT
	MOVE AC2,FENAME
	MOVE AC3,[POINT 6,AC2]	;POINT TO SIXBIT NAME
	MOVSI AC4,-6		;ONLY 6 BYTES
	CALL STRBLT
	HRROI AC2,[ASCIZ /-TASK-DNDDT./]
	SETZB AC3,AC4
	SOUT
	SETZ AC2,
	IDPB AC2,AC1		;ASCIZ FILE NAME
	MOVX AC1,GJ%SHT
	HRROI AC2,FE.MSG	;POINT TO FILENAME
IFN DEBUG,<
	SKIPE QX,F.DEBU
	TXNN QX,DB.INI!DB.EXD
	JRST GOTN1
	TYPE <%Opening connection to >
	HRRZ T1,AC2
	CALL TYPSTR
	CALL CRLTYP
GOTN1:
>
	GTJFN			;GET A JFN
	 ERJMP [TYPE <?
?GTJFN for logical link failed because:
>
		JRST OPNFE9]
	MOVE AC2,[OF%RD+OF%WR+10B5] ;8 BIT BYTES
	OPENF			;OPEN THE LOGICAL LINK
	 ERJMP [TYPE <?
?OPENF failed for logical link because:
>
		JRST OPNFE9]
	HRRZM AC1,FE.JFN	;LOGICAL LINKS JFN
	SETZM MEMORY		;NOT USING MEMORY
	JRST LEVL.0


;HERE IF USERS TYPES /FE:

SET.FE:	SWTCHK FE
	MOVE T1,OSTYPE		;GET SYSTEM TYPE
	TXNN T1,T.TOP20!T.TOP10	;SEE IF IT IS ALLOWED
	JRST [	TYPE <?
?Use of the /FE switch is illegal when not on TOPS-10/20
>
		RET ,SET.FE]
	CAIE T5,":"
	JRST [	TYPE <?
?Front End number required for the /FE switch
>
		RET ,SET.FE]
	CALL DECINP		;GET THE FRONTEND #
	JRST [	TYPE <?
?Front End number required for the /FE switch
>
		RET ,SET.FE]
	MOVE T2,OSTYPE		;GET OPS TYPE
	TXNE T2,T.TOP10		;IF TOPS-10, DO DIFFERENTLY (BETTER)
	 JRST [	JUMPL T1,[RET ,SET.FE]	;DISALLOW JUNK
		IDIVI T1,^D10	;SPLIT CPU/DTE
		CAIG T1,5	;IF CPU TOO BIG
		CAILE T2,3	;OR DTE TOO BIG
		RET ,SET.FE	;DON'T EVEN TRY
		HRLI T2,(T1)	;CPU,,DTE
		MOVEM T2,FE.CPU ;SAVE FOR DTE. UUOS
		SETZM FE.FED	;START WITH FED # 0
		SETOM FENAME	;CONFUSE TOPS-20
		MOVE T1,[400K,,OPNF10] ;THIS IS AN ACTION SWITCH
		MOVEM T1,LASTSW
		DBGTYP DB.INI,<%Setting start address to OPNF10 for the /FE switch
>
		MOVEI T1,EX.FE1 ;TOPS-10 20F
		MOVEM T1,ETYPE	;SAVE FOR EXAMINE CODE
		RET SKIP,SET.FE]
	CAIG T1,^D9		;BE SURE NOT TOO LARGE
	CAIGE T1,0		;BE SURE POSITIVE
	JRST [	TYPE <?
?Number typed for /FE: not in range of 0-9
>
		RET ,SET.FE]
	SKIPA T2,[EX.FE0]
SETD62:	MOVEI T2,EX.D62		; set DN62 type FE

SETFET:	MOVEM T2,ETYPE		; T1/FE number, T2/fe type
	CAIE T2,EX.D62
	JRST SETFE0
	LSH T1,10		; if DN62, use higher numbered fe to avoid
	IOR T1,[ASCII \FE10:\]	; assignment problems
	JRST SETFE1

SETFE0:	LSH T1,17
	IOR T1,[ASCII \FE0:\]

SETFE1:	MOVEM T1,FENAME		;REMEMBER WE'RE DOING FRONT END STUFF
	MOVE T1,[400000,,OPENFE]
	MOVEM T1,LASTSW
	DBGTYP DB.INI,<%Setting start address to OPENFE for the /FE switch
>
	RET SKIP,SET.FE

OPENFE:	MOVX AC1,GJ%SHT!GJ%OLD
	HRROI AC2,FENAME	;NAME OF  FRONT END
	GTJFN			;GET A JFN FOR THE FRONT END
	ERJMP [	TYPE <?
?GTJFN for the FE device failed because:>
		JRST OPNFE9]
	MOVEM AC1,FE.JFN	;SAVE JFN
	MOVE AC2,ETYPE		;check which type of FE
	CAIE AC2,EX.D62
	SKIPA AC2,[200000,,OF%WR!OF%RD]
	MOVE AC2,[100000,,OF%WR!OF%RD] ;DN62 uses 8 bit bytes
	OPENF
	ERJMP [	TYPE <?
?OPENF for the FE device failed because:>
		JRST OPNFE9]
	MOVEI AC2,.MODTE	;OPEN DTE
	SETZ AC3,
	MTOPR
OPNFE8:	SETZM MEMORY		;NOT USING MEMORY
	JRST LEVL.0

OPNFE9:	MOVEI AC1,.PRIOU	;OUTPUT ON TTY
	HRLOI AC2,.FHSLF	;FOR OURSELVES
	SETZ AC3,
	ERSTR
	SETZM FENAME
	JRST DDT11		;TRY AGAIN

				;HERE TO GET A FE DEVICE ON TOPS-10

OPNF10:	MOVE T1,[.DTEGF,,FE.CPU] ;TRY TO GET A FED
	DTE. T1,		;PLEASE...
	 JRST [	CAIN T1,DTENF%	;DOESN'T EXIST?
		JRST [	TYPE <?
?No FE devices available
>
			JRST DDT11]
		CAIE T1,DTEFB%	;THIS ONE BUSY?
		JRST [	TYPE <?
?DTE. UUO error
>
			JRST DTEERR] ;NO, CONFUSED
		AOS FE.FED	;TRY NEXT
		JRST OPNF10]
	SETOM FE.JFN		;CONFUSE THE TOPS-20 CODE
	JRST OPNFE8		;AND GO FINISH UP

;HERE FOR /LINE IN COMMAND LINE

SETLIN:	SWTCHK LINE
	MOVE T1,OSTYPE
	TXNN T1,T.TOP10
	JRST [	TYPE <?
?Illegal /LINE switch when not on TOPS-10
>
		RET ,SETLIN]
	CAIE T5,":"
	JRST [	TYPE <?
?Line switch requires an argument
>
		RET ,SETLIN]
	CALL SIXIN		;GET LINE ARGUMENT
	JRST [	TYPE <?
?Illegal argument for /LINE switch
>
		RET ,SETLIN]
	SKIPN T1
	JRST [	TYPE <?
?Line switch requires an argument
>
		RET ,SETLIN]
	CALL SIXOCT		;CONVERT TO NUMBER
	JRST [	TYPE <?
?Illegal argument for the /LINE switch
>
		RET ,SETLIN]
	AOS T1
	MOVEM T1,LINE
IFN DEBUG,<
	SKIPE QX,F.DEBU
	TXNN QX,DB.INI!DB.EXD
	JRST SETLI1
	TYPE <%Setting the line number to >
	MOVE T1,LINE
	CALL OCTYPE
	CALL CRLTYP
SETLI1:
>
	MOVEI T1,EX.NOD
	MOVEM T1,ETYPE
	RET SKIP,SETLIN

;HERE FOR /NODE IN COMMAND LINE

SETNOD:	SWTCHK NODE
	MOVE T1,OSTYPE
	TXNN T1,T.TOP10
	JRST [	TYPE <?
?Illegal /NODE: when not on TOPS-10
>
		RET ,SETNOD]
	CAIE T5,":"
	JRST [	TYPE <?
?Node switch requires an argument
>
		RET ,SETNOD]
	CALL SIXIN		;GET NODE ARGUMENT
	JRST [	TYPE <?
?Illegal argument for the /NODE switch
>
		RET ,SETNOD]
	SKIPN T1
	JRST [	TYPE <?
?Node switch requires an argument
>
		RET ,SETNOD]
	MOVEM T1,NODE.N		;SAVE NODE NAME
IFN DEBUG,<
	SKIPE QX,F.DEBU
	TXNN QX,DB.INI!DB.EXD
	JRST SETNO1
	TYPE <%Setting start address to LEVL.0 for the /NODE switch
%Setting the node to access to >
	MOVE T1,NODE.N
	CALL SIXTYP
	CALL CRLTYP
SETNO1:
>
	SETZM FE.JFN		;NOT DOING /FE STUFF
	CALL CLRMEM		;FORGET ANYTHING ALREADY READ
	 JFCL			;DONE CARE ABOUT ERROR
	MOVE T1,[400000,,LEVL.0]
	MOVEM T1,LASTSW
	MOVEI T1,EX.NOD
	MOVEM T1,ETYPE
	RET SKIP,SETNOD

;HERE FOR /PORT

SETPRT:	SWTCHK PORT
	CAIE T5,":"
	JRST [	TYPE <?
?Port switch requires an argument
>
		RET ,SETPRT]
	CALL SIXIN		;GET SIXBIT ARGUMENT
	JRST [	TYPE <?
?Illegal argument for the /PORT switch
>
		RET ,SETPRT]
	SKIPN T1
	JRST [	TYPE <?
?Port switch requires an argument
>
		RET ,SETPRT]
	CALL SIXOCT		;CONVERT TO OCTAL
	JRST [	TYPE <?
?Illegal value for the /PORT switch
>
		RET ,SETPRT]
	ANDI T1,17		;ALLOW FOR 8 DL10 PORTS PLUS 8 DN6X
	HRROM T1,PORT		;SAVE PORT NUMBER
	MOVE T2,OSTYPE		; CHECK MONITOR TYPE
	TXNE T2,T.TOP20		; IF TOPS-20 THEN HAVE TO DO FE TYPE IO
	JRST [	 CALL PROTYP	;DTEREMINE PROTOCOL VERSION NUMBER
		 SKIPE PVTYP	; SKIP IF FE OR DN22
		 JRST SETPR5	; VERSION 5 PROTOCOL
		 CALL QUED60	; SET UP ENQUEUE STRING
		 ANDI T1,7	; REMOVE DTE OFFSET TO GET FE NUMBER
		 SKIPGE PTYPE	; CHECK FOR DN22
		 JRST SETPR5	; YES, ALL DONE
		 JRST SETD62]	; NOW GO SET TYPE DN62
	SKIPA T1,[EX.PORT]
SETPR5:	MOVEI T1,EX.D62
	MOVEM T1,ETYPE
	MOVE T1,[400000,,LEVL.0]
	MOVEM T1,LASTSW
IFN DEBUG,<
	SKIPE QX,F.DEBU
	TXNN QX,DB.INI!DB.EXD
	JRST SETPR6
	TYPE <%Setting start address to LEVL.0 for the /PORT switch
%Setting the port to access to >
	MOVE T1,PORT
	CALL OCTYPE
	CALL CRLTYP
SETPR6:
>
	RET SKIP,SETPRT

;HERE FOR A /UBA COMMAND LINE

SETUBA:	SWTCHK UBA
	TXNN FLG,F.EXEC
	JRST [	TYPE <?
?Illegal /UBA switch when not in EXEC mode
>
		RET ,SETUBA]
	CAIN T5,":"		;WAS BREAK A COLON ?
	CALL DECINP		;GET ADAPTER NUMBER TO USE
	JRST [	TYPE <?
?Illegal argument for the /UBA switch
>
		RET ,SETUBA]
	HRLZ T3,T1		;COPY NEW UBA NUMBER
	TXNE FLG,F.EXEC		;RUNNING EXEC MODE ?
	RDIO T1,UBA.SR(T3)	;SEE IT THERE IS SUCH A UBA
	JRST [	MOVEM T3,UBACTL	;SAVE IT
		RET SKIP,SETUBA]
	TYPE <?
?Illegal value for the /UBA switch
>
	RET ,SETUBA

;ROUTINE TO GET A WORD FROM THE PDP-11
; CALL CALL GETWRD		;WITH ADR IN T1, NUMBER OF BYTES IN T2
;	ERROR RETURN	ERROR CODE IN T1
;	SUCCES	DATA IN T1
GETWRD:	CALL SAVE35		;SAVE T3, T4, & T5
	ANDI T1,-1		;CLEAR ANY EXTRA ADDR BITS
	SKIPN F.MCB
	ANDI T1,177777		;NO, CLEAR MORE BITS
	SKIPE PDP8F
	ANDI T1,077777		;STRIP EXTRA BITS
	SKIPN T2
	JRST [	TYPE <?
?Fatal error - GETWRD called asking for 0 bytes
>
		JRST DDT11]	; START OVER
IFN DEBUG,<
	MOVE QX,F.DEBU		; GET THE DEBUG SWITCH VALUE
	TXNN QX,DB.EXD		; ARE WE REPORTING EXAMINE AND DEPOSIT
	JRST GETWD4		; NO, SKIP ALL THIS JUNK
	PUSH P,T1		; SAVE SOME AC'S
	PUSH P,T2
	TYPE <%Memory examine to location >
	MOVE T1,-1(P)		; GET THE EXACT LOCATION, PLEASE
	CALL OCTYPE		; TYPE OUT THE NUMBER
	TYPE <, for >
	MOVE T1,(P)		; GET THE LENGTH
	CALL OCTYPE
	TYPE < bytes.
>
	POP P,T2
	POP P,T1
GETWD4:
>
	SKIPE CACHEL		;IS THERE DATA IN CACHE ?
	TXNN FLG,F.CACH		;AND MAY WE USE CACHE ?
	JRST GETWD1		;NO CACHE OR CAN'T USE IT
	CAMGE T1,CACHEL		;IS REQUEST TOO LARGE ?
	CAMGE T1,CACHEA		;OR TOO SMALL
	JRST GETWD1		;NO
GETWD0:	DBG1TYP DB.EXD,<%  Data will be fetched from cache.
>
	MOVE T4,[POINT 8,CACHE]	;POINTER TO CACHE
	SKIPE PDP8F
	MOVE T4,[POINT 12,CACHE]
	MOVE T3,T1		;COPY ADDRESS OF BYTE TO GET
	SUB T3,CACHEA		;MAKE RELATIVE
	CAIA
	IBP T4			;SKIP NEXT BYTE
	SOJGE T3,.-1
	ILDB T1,T4		;GET LOW ORDER BYTE OF REQUESTED WORD
	SKIPE PDP8F
	JRST GETWD3
	ILDB T2,T4		;GET HIGH ORDER BYTE OF REQUESTED WORD
	DPB T2,[POINT 8,T1,27]
GETWD3:	ANDI T1,177777		;STRIP EXTRA BITS
	RET SKIP,GETWRD

GETWD1:	MOVE T4,ETYPE
	JRST @[	GETMEM		;MEMORY
		GET.C1		;CALL-11
		GETNOD		;NODE. UUO
		GET.FE		;FE0 ON TOPS-20
		GET.C1		;DN60 ON TOPS-10
		GETD62		;DN60 ON TOPS-20, BOTH DN20 AND DN22
		GETMCB		;MCB
		GT.F10		;FE0 on TOPS-10
		GETMC1		;MCB ON TOPS-10
			](T4)

GETMC1:	DBG1TYP DB.EXD,<% Examine is thru the MCB logical link interface.
>
	CALL GMCBP1		; BUILD THE REQUEST MESSAGE
	MOVE T1,[NS.WAI!NS.EOM!<.NSFDS,,4>] ; WAIT OPERATION, SEND DATA
	MOVEM T1,NODARG+.NSAFN	; START BUILDING REQUEST
	MOVE T1,FE.JFN		; OF COURSE, WE NEED THE JFN ON THE -10
	MOVEM T1,NODARG+.NSACH
	MOVEI T1,7		; THIS IS A SEVEN BYTE MESSAGE
	MOVEM T1,NODARG+.NSAA1
	MOVE T1,[POINT 8,FE.MSG] ; POINTER TO THE DATA SECTION OF MESSAGE
	MOVEM T1,NODARG+.NSAA2
	MOVEI T1,NODARG		; FINNALY, A POINTER TO OUR ARGUMENT BLOCK
	NSP. T1,
	 JRST [	TYPE <?
?NSP. send to the MCB failed.
>
		SETZ T2,
		RET ,GETMC1]
	MOVE T1,[NS.WAI!<.NSFDR,,4>] ; WAIT OPERATION, READ DATA
	MOVEM T1,NODARG+.NSAFN	; START BUILDING REQUEST
	MOVE T1,FE.JFN		; OF COURSE, WE NEED THE JFN ON THE -10
	MOVEM T1,NODARG+.NSACH
	MOVEI T1,4		; THIS IS A FOUR BYTE MESSAGE
	MOVEM T1,NODARG+.NSAA1
	MOVE T1,[POINT 8,FE.MSG] ; POINTER TO THE DATA SECTION OF MESSAGE
	MOVEM T1,NODARG+.NSAA2
	MOVEI T1,NODARG		; FINNALY, A POINTER TO OUR ARGUMENT BLOCK
	NSP. T1,
	 JRST [	TYPE <?
?NSP. send response from the MCB failed.
>
		SETZ T2,
		RET ,GETMC1]
	MOVE T2,[POINT 8,FE.MSG]
	ILDB T3,T2
	CAIE T3,1
	 JRST [	TYPE <?
?Bad message from the MCB.  No good reason.
>
		MOVE T1,T3
		SETZ T2,
		RET ,GETMC1]
	IBP T2
	ILDB T1,T2
	ILDB T3,T2
	LSH T3,^D8
	OR T1,T3
	JRST GETWD3


; HERE TO BUILD THE GET MESSAGE FOR A MCB DNDDT TASK

GMCBP1:	MOVE T2,[BYTE(8) ^D13,0,0,0] ; FUNCTION CODE IS 13
	MOVEM T2,FE.MSG		; AND THIS WILL START AT FE.MSG
	MOVE T2,[BYTE(8) 0,0,2,0] ; REQUEST IS FOR TWO BYTES
	MOVEM T2,FE.MSG+1
	MOVE T3,T1
	MOVE T1,[POINT 8,FE.MSG,15] ; POINT TO START OF FIELD
	MOVEI T2,4		; FOUR BYTES OF ADDRESS
GETW1C:	IDPB T3,T1		; ADD EACH BYTE OF THE ADDRESS WE WISH
	LSH T3,-^D8		; TO LOOK AT
	SOJG T2,GETW1C
	RET ,GMCBP1		; DONE, BACK TO WENCE WE CAME


GETMCB:	DBG1TYP DB.EXD,<% Examine is thru the MCB logical link interface.
>
	CALL GMCBP1
	MOVE AC1,FE.JFN
	MOVE AC2,[POINT 8,FE.MSG]
	MOVNI AC3,7
	SOUTR
	 ERJMP [TYPE <?
?SOUTR send response from the MCB failed.
>
		SETZ T2,
		RET ,GETMCB]
	MOVE AC2,[POINT 8,FE.MSG]
	MOVNI AC3,4
	SINR
	 ERJMP [TYPE <?
?SINR send response from the MCB failed.
>
		SETZ T2,
		RET ,GETMCB]
	MOVE T2,[POINT 8,FE.MSG]
	ILDB T3,T2
	CAIE T3,1
	 JRST [	TYPE <?
?Bad message from the MCB.  No good reason.
>
		SETZ T2,
		MOVE T1,T3
		RET ,GETMCB]
	IBP T2
	ILDB T1,T2
	ILDB T3,T2
	LSH T3,^D8
	OR T1,T3
	JRST GETWD3


;HERE TO DO CALL11 UUO TO GET DATA
GET.C1:	DBG1TYP DB.EXD,<% Examine is thru the CALL11 UUO.
>
	SETZ T4,
	HRRZM T1,T3
GETWDR:	MOVEI T2,1		;FUNCTION 1
	MOVE T1,[3,,T2]
	HRL T2,PORT		;ADD PORT NUMBER
	CAL78. T1,
	SKIPA T1,[3,,T2]
	JRST GETWD2
	CAL11. T1,
	JRST [	CAIE T1,4	;ERROR 4, ?ALREADY IN USE?
		RET ,GETWDR
		MOVE T1,^D100	;WAIT A WHILE
		HIBER T1,	;SEE HOW LONG IT TAKES
		RET ,GETWDR
		JRST GETWDR]	;AND TRY AGAIN
GETWD2:	HRRZ T2,T3		;GET ADDRESS WE WERE GETTING

GTWD2A:	CALL PUTBCH		;PUT BYTE INTO THE CACHE
	LSH T1,-^D8		;ADJUST DATA
	AOS T2
	CALL PUTBCH		;ALSO HIGH ORDER BYTE
	MOVE T1,T3		;GET ADDRESS AGAIN
	MOVEI T2,2		;NUMBER OF BYTES TO GET
	JRST GETWD0		;GET DATA FROM THE CACHE

GETD62:	DBG1TYP DB.EXD,<% Examine is thru the TOPS-20/DN60 interface.
>
	CALL D62EXM		;examine DN60/TOPS20 FE
	SKIPA T1,AC1		;move error code to the right place
	SKIPA T3,T2		;suc'd - move address for GETWD2
	RET ,GETD62
	JRST GTWD2A

;HERE TO GET A WORD FROM CORE IN 10 MEMORY
GETMEM:	DBG1TYP DB.EXD,<% Examine is to simulated memory.
>
	MOVE T4,MEMORY
	CAMLE T1,MEMLIM		;IS IT IN RANGE ?
	JRST [HRRZ MA,T1	;ADR WE WANT
		CALL IOLDM1
		RET ,GETMEM
		JRST GETWD3 ]	;WON
	SKIPE PDP8F
	JRST GTMEM8		;GET WORD OF 8 MEMORY
repeat 0,<
	TXNN T1,600000		;IS THE ADDRESS OVER 32K
	SKIPN F.MCB
	JRST GTMEM4		;NO, SKIP THIS STUFF
	PUSH P,T3		;SAVE AN AC, SHOOT A PREPIE
	MOVE T3,T1		;GET A COPY OF THE ADDRESS
	ASH T3,-^D13		;SHIFT OUT THE PAGE BITS
	MOVE T3,PAR0(T3)	;GET THE ADDRESS OF THE REAL WORD
	ASH T3,6		;MOVE TO BASE ADDRESS
	ANDI T1,17777		;CLEAR OUT THE EXTRA ADDRESS BITS.
	ADD T1,T3		;AND BUILD IT BACK TO A PHYSICAL ADDRESS
	POP P,T3		;PUT BACK THE AC
	CAIL T1,777700		;IO PAGE ?
	CAILE T1,777707		;YES, AND EVEN AN AC FETCH...
	JRST GTMEM4		;NO, SOME PLACE ELSE
	ANDI T1,7		;GET JUST THE NUMBER
	MOVE T1,REG0(T1)	;GET THE AC, ITSELF
	JRST GETWD3		;AND JOIN THE MAIN LINE
>
GTMEM4:	IDIVI T1,4		;WE KEEP 4 BYTES IN 36BIT WORD
	ADD T1,MEMORY		;ADD RELOCATION
	TRNE T2,2
	SKIPA T1,(T1)
	HLR T1,(T1)
	TRNE T2,1		;DID HE ASK FOR LH BYTE ?
	LSH T1,-^D8		;YES
	JRST GETWD3

;HERE TO GET A PDP8 WORD FROM CORE IN 10 MEMORY

GTMEM8:	IDIVI T1,2
	ADD T1,MEMORY		;RELOCATE
	LDB T1,[	POINT 18,(T1),17
			POINT 18,(T1),35 ](T2)
	ANDI T1,007777
	JRST GETWD3

;HERE TO EXAMINE MEMORY FROM ANOTHER NETWORK NODE

GETNOD:	DBG1TYP DB.EXD,<% Examine is thru a STC message to a NODE.
>
	CALL SETUPN		;BEGIN BUILDING MSG<LINE><CODE><ADR>
	EXP 1			;CODE FOR EXAMINE REQUESTS IS 1
	MOVEM T1,T3		;SAVE ADDRESS
	ADDI T1,(T2)		;MAKE LIMIT ADDRESS
	CALL PUTADR		;PUT LIMIT ADDRESS INTO THE MESSAGE
	CALL NODSET		;DO NODE UUO
	RET ,GETNOD
	CAIE T1,12		;CODE FOR EXAMINE DATA IS 12
	JRST STCERR
	PUSH P,T3		;SAVE ADDRESS WE WENT FOR
	HLRZ T3,NODARG+3	;GET BYTE COUNT FROM MSG
	SUBI T3,4		;SUBTRACT BYTES WE ALREADY READ
	ILDB T2,T4		;GET LOW ORDER 8 BITS OF ADDRESS
	ILDB T1,T4		;GET HIGH ORDER 8 BITS
	DPB T1,[POINT 8,T2,27]
	SKIPE PDP8F
	JRST GTNOD3
	SOS T3			;COUNT BYTE
	ILDB T1,T4
	DPB T1,[POINT 8,T2,19]
GTNOD3:	ILDB T1,T4		;GET NEXT BYTE OF DATA
	SKIPN PDP8F
	JRST GTNOD4
	PUSH P,T1		;SAVE LOW ORDER BITS
	ILDB T1,T4		;GET HIGH ORDER BITS
	DPB T1,[POINT 6,(P),29]
	POP P,T1
	SOS T3			;KEEP COUNT HONEST
GTNOD4:	CALL PUTBCH		;PUT BYTE INTO THE CACHE
	AOS T2			;ADVANCE ADDRESS
	SOJG T3,GTNOD3
	POP P,T1		;GET ADDRESS WE WENT FOR
	JRST GETWD0

;HERE TO GET DATA FROM A /FE DEVICE

GET.FE:	DBG1TYP DB.EXD,<% Examine is thru the TOPS-20/FE device.
>
	MOVE T3,[BYTE (16)IO.RLB(8)"E","M"]
	MOVEM T3,FE.MSG
	SETZM FE.MSG+1
	SETZM FE.MSG+2
	PUSH P,T1		;SAVE THE ADDR
	LSH T1,24
	HRRI T1,2*20
	MOVEM T1,FE.MSG+2	;BYTE(16)ADR,2
	MOVE AC1,FE.JFN		;GET JFN FOR FE DEVICE
	MOVE AC2,[442000,,FE.MSG]
	MOVNI AC3,6
	SOUT
	ERJMP [	POP P,T1
		RET ,GET.FE]
	MOVEI AC2,.MOEOF
	SETO AC3,
	MTOPR
	ERJMP [	POP P,T1
		RET ,GET.FE]
	CALL GETFEM		;GET RESPONSE
	JRST [	POP P,T1
		RET ,GET.FE]	;ERROR RETURN
	LDB T1,[POINT ^D16,FE.MSG+3,15]
	POP P,T3		;GET ADR OFF STACK
	JRST GETWD3		;ERROR RETURN

GETFEM:	MOVE AC2,[POINT 16,FE.MSG] ;POINTER TO FRONT END MESSAGE
	MOVNI AC3,6
	SIN			;GET IT
	ERJMP [RET ,GETFEM]
	LDB AC3,[POINT 16,FE.MSG+2,31]
	JUMPLE	AC3,GTFEM3	;NO MORE
	LSH AC3,-1		;CONVERT TO WORDS
	MOVN AC3,AC3
	SIN
	ERJMP [RET ,GETFEM]
GTFEM3:	LDB T1,[POINT 8,FE.MSG+1,31]
	MOVN T1,T1		;RETURN STATUS
	ANDI T1,377
	TRNE T1,200
	RET SKIP,GETFEM

;HERE TO DO THE WORK UNDER TOPS-10

GT.F10:	DBG1TYP DB.EXD,<% Examine is thru the TOPS-10/FE device.
>
	HRLI T1,IO.RLB		;SET UP HEADER FOR READ FCN
	CALL ME.SET		;...
	MOVE T1,[.DTEOF,,FE.CPU] ;DO OUTPUT
	DTE. T1,		;TO ME: (PLEASE)
	JRST [
DTEERR: 	TRO T1,400	;Make DTE. error codes distinct
		RET ,GT.F10]
	CALL FE.RPY		;READ THE REPLY
	RET ,GT.F10
	CAILE T1,FE.MAX		;TOO MUCH DATA?
	JRST [
FE$BLT:		TYPE <?
?Bad PDP-11 Message
>
		 JRST DDT11]	;YES, WE LOSE SYNC
	ASH T1,-1		;BYTES TO WORDS
	HRLI T1,FE.MSG+3	;WHERE TO PUT DATA
	MOVSM T1,FE.BUF
	MOVE T1,[.DTEIF,,FE.CPU] ;READ IT
	DTE. T1,		;...
	 JRST DTEERR
	LDB T1,[POINT 16,FE.MSG+3,17] ;DATA
	JRST GETWD3

;SUBROUTINE TO SET UP A MESSAGE HEADER FOR THE ME: DEVICE
;CALL WITH T1/ IO.xLB,,ADDRESS

ME.SET:	HLLZM T1,FE.MSG+0	;SET IO FUNCTION
	HRLI T1,2		;DATA BYTES TO BE TRANSFERED
	MOVSM T1,FE.MSG+2	;(PARAM-2,,BYTE-CNT)
	SETZM FE.MSG+1		;(UNIT,,PARAM-1)
	MOVEI T1,(<BYTE (2)0(8)"E","M">) ;SET DEVICE NAME
	HRRM T1,FE.MSG+0	;IN HEADER
	MOVE T1,[<14/2>,,FE.MSG] ;WORD COUNT TO SEND,,ADDRESS
	MOVEM T1,FE.BUF		;FOR FEDSER
	RET ,ME.SET

;SUBROUTINE TO READ ME: REPLY HEADER
;NON-SKIP T1 IS ERROR CODE, SKIP T1 IS # DATA BYTES TO FOLLOW

FE.RPY:	MOVE T1,[<14/2>,,FE.MSG] ;READ HEADER ONLY
	MOVEM T1,FE.BUF		;SET UP FOR UUO
	MOVE T1,[.DTEIF,,FE.CPU] ;READ DATA FUNCTION
	DTE. T1,		;...
	 JRST DTEERR		;OOPS!
	LDB T1,[POINT 8,FE.MSG+1,35] ;GET $DSW
	MOVNS T1		;MAKE ERRORS POSITIVE
	ANDI T1,377		;...
	TRNN T1,200		;ERROR?
	RET ,FE.RPY
	LDB T1,[POINT 16,FE.MSG+2,35] ;HOW MUCH DATA FOLLOWS?
	RET SKIP,FE.RPY

;HERE TO BEGIN A NODE UUO MSG <LINE><CODE><ADDRESS>
; CALL MOVE T1,<ADR>
;	CALL SETUPN
;	EXP <CODE>

SETUPN:	PUSH P,T1		;SAVE ADDRESS
	MOVE T4,[POINT 8,STCMSG] ;POINTER TO STATION CONTROL MSG
	MOVE T1,LINE		;0 = SELF, 1-N IS LINE NUMBER
	IDPB T1,T4		;MSG IS FOR NODE
	MOVE T1,@-1(P)		;GET CODE
	IDPB T1,T4
	POP P,T1		;GET ADDRESS BACK
	CALL PUTADR		;PUT ADDRESS INTO THE MESSAGE
	RET SKIP,SETUPN

;HERE TO PUT AN ADDRESS IN A NODE UUO STRING

PUTADR:	PUSH P,T1
	SKIPE PDP8F
	ANDI T1,077777		;STRIP EXTRA BITS
	IDPB T1,T4		;PUT LOW ORDER BYTE OF ADR INTO MSG
	ROT T1,-^D8
	IDPB T1,T4
	ROT T1,-^D8
	SKIPE PDP8F
	JRST PUTAD1
	IDPB T1,T4
PUTAD1:	POP P,T1
	RET ,PUTADR

;HERE TO DO A NODE UUO
; CALL CALL NODSET
;	ERROR RETURN	CODE IN T1
;	RETURNS WITH T4 POINTING TO INPUT MSG AND CODE IN T1

NODSET:	PUSH P,[POINT 8,STCMSG]
	MOVEI T1,1		;INITIALIZE LENGTH COUNTER
NODSE1:	IBP (P)			;ADVANCE DUMMY POINTER
	CAME T4,(P)
	AOJA T1,NODSE1
	HRLI T1,STCMSG
	MOVSM T1,NODARG+2
	POP P,T1		;CLEAN OFF STACK
	MOVEI T1,4		;NUMBER OF WORDS IN ARGUMENT
	MOVEM T1,NODARG
	MOVE T1,NODE.N		;NODE NAME
	MOVEM T1,NODARG+1
	MOVE T1,[400,,STCIMS]	;INPUT MSG SLOT
	MOVEM T1,NODARG+3
	MOVE T1,[3,,NODARG]	;FUNCTION IS SEND STC MSG
	NODE. T1,
	RET ,NODSET
	MOVE T4,[POINT 8,STCIMS] ;POINTER TO INPUT MESSAGE
	ILDB T1,T4		;GET FIRST BYTE (= LINE# OR SELF)
	CAME T1,LINE
	JRST CALER0		;DESCRIBE FAULT
	ILDB T1,T4		;GET MESSAGE SUBTYPE
	RET SKIP,NODSET

STCERR:	TYPE <? STC error - msg =>
	HLRZ T4,NODARG+3
	SKIPA T5,[POINT 8,STCIMS]
STCER3:	CALL COMTYP		;TYPE A COMMA
	MOVEI T1,"<"
	CALL TYPCHR
	ILDB T1,T5
	CALL OCTYPE
	MOVEI T1,">"
	CALL TYPCHR
	SOJG T4,STCER3
	SETO T1,		;SAY WE PRINTED THE ERROR
	RET ,STCERR

;HERE TO PUT A BYTE INTO THE CACHE
; CALL MOVE T1,<BYTE>
;	MOVE T2,<ADR>
;	CALL PUTBCH
;	RETURN

PUTBCH:	DBG1TYP DB.EXD,<% Data will be written to cache.
>
	PUSHJ P,SAVE4
	SKIPE T3,CACHEL		;IS CACHE EMPTY ?
	CAMG T2,CACHEA		;IS NEW BYTE BELOW CACHE ADDRESS ?
	JRST PTBCH2		;FLUSH CACHE
	SUB T3,CACHEA		;HOW MANY BYTES ALREADY IN THE CACHE ?
	CAIGE T3,CACHSZ		;SMALL ENOUGH ?
	JRST PTBCH1		;YES
	MOVEI T3,4		;REDUCE CONTENTS BY 4 BYTES = ON 10 WORD
	SKIPE PDP8F
	MOVEI T3,3		;REDUCE CONTENTS BY 3 WORDS = ONE 10 WORD
	ADDM T3,CACHEA
	MOVE T3,[CACHE+1,,CACHE] ;BLT POINTER
	BLT T3,CACHE+<CACHSZ/4>-1 ;SHUFFLE CACHE
PTBCH1:	CAMN T2,CACHEL		;ARE TRYING TO ADD ONE BYTE TO CACHE ?
	JRST PTBCH4		;YES
PTBCH2:	MOVEM T2,CACHEA		;BEGIN CACHE HERE
PTBCH4:	MOVEM T2,CACHEL		;THIS IS THE NEW CACHE LIMIT
	AOS CACHEL		;MAKE ONE PLUS
	SUB T2,CACHEA		;HOW MANY BYTES TO NEW BYTE ?
	MOVE T3,[POINT 8,CACHE]
	SKIPE PDP8F
	MOVE T3,[POINT 12,CACHE]
	CAIA
	IBP T3
	SOJGE T2,.-1
	IDPB T1,T3		;PUT BYTE INTO THE CACHE
	RET ,PUTBCH

;ROUTINE TO DEPOSIT BYTES IN PDP-11 MEMORY
; CALL MOVE T1,<ADR TO DEPOSIT TO>
;				;DATA STARTS AT DATA - DAT POINTS TO LAST BYTE
;	CALL PUTBYT		;WITH ADR IN T1
;	LOSE RETURN <CODE IN T1>
;	WIN RETURN

PUTBYT:	CALL SAVE35		;SAVE T3, T4, & T5
IFN DEBUG,<
	MOVE QX,F.DEBU		; GET THE DEBUGGER FLAG
	TXNN QX,DB.EXD		; ARE WE WATCHING EXAMINE DEPOSIT ?
	JRST PUTBY3		; NO, SKIP THIS CRAP
	PUSH P,T1		; SAVE THE ADDRESS OF THE DATA
	TYPE <%Memory deposit to location >
	MOVE T1,(P)		; GET THE ADDRESS BACK
	CALL OCTYPE		; TYPE THE LOCATION FOR ALL TO SEE
	TYPE <, for >		; GET READY...
	SKIPE PDP8F
	SKIPA T2,[POINT 12,DATA]
	MOVE T2,[POINT 8,DATA]
	MOVE T4,T2		; AND SAVE A COPY OF THIS...
	SETZ T5,		; CLEAR A COUNTER FOR NOW
	ILDB T1,T2		; GET THE FIRST BYTE
	AOS T5			; AND COUNT IT AS DATA
	CAME T2,DAT		; IS THAT THE LAST BYTE?
	JRST .-3		; NO, KEEP LOOKING
	MOVE T1,T5		; GET THE NUMBER HERE, PLEASE
	CALL DECTYP		; AND TEL EVERYONE HOW LONG IT WAS
	TYPE < bytes.
	% Data is >
	MOVE T1,TYPDAT		; GET TYPE OF DATA FIRST
	XCT [	MOVEI T1,[ASCIZ \UNKNOWN TYPE - \]
		MOVEI T1,[ASCIZ \NUMERIC - \]
		MOVEI T1,[ASCIZ \ASCII - \]
		MOVEI T1,[ASCIZ \INSTRUCTION - \]](T1)
	CALL TYPSTR		; TYPE THE DATA TYPE OUT

PUTBY6:	CALL LATYPE		; TYPE LEFT ANGLE
	ILDB T1,T4		; GET THE DATA BYTE
	CALL OCTYPE		; TYPE IT OUT...
	CALL RATYPE		; TYPE OUT THE OTHER HALF
	CAMN T4,DAT		; IS THAT THE LAST ONE
	JRST PUTBY5		; YES, SO GET OUT
	CALL COMTYP		; GIVE A SMALL SEPERATOR
	JRST PUTBY6		; AND LOOP FOR MORE
PUTBY5:	CALL CRLTYP
	POP P,T1		; RESTORE ADDR
PUTBY3:>
	MOVE T5,DAT		;SAVE POINTER TO LAST DATA BYTE
	SKIPE PDP8F
	SKIPA T2,[POINT 12,DATA]
	MOVE T2,[POINT 8,DATA]
	MOVEM T2,DAT
	MOVE T4,ETYPE
	JRST @[	PUTMEM		;MEMORY
		PUT.C1		;CALL-11
		PUTNOD		;NODE. UUO
		PUT.FE		;FE0 ON TOPS-20
		PUT.C1		;DN60 ON TOPS-10
		PUTD62		;DN60 ON TOPS-20, BOTH DN20 AND DN22
		PUTMCB		;MCB
		PUT.FE		;20F/TOPS-10
		PUTMC1		; TOPS-10 MCB
			](T4)

PUTMC1:	DBG1TYP DB.EXD,<% Deposit is thru the MCB logical link interface.
>
	CALL PMCB1		; BUILD COMMON MESSAGE FOR MCB
	MOVE AC1,[NS.WAI!NS.EOM!<.NSFDS,,4>] ; WAIT OPERATION, SEND DATA
	MOVEM AC1,NODARG+.NSAFN	; START BUILDING REQUEST
	MOVE AC1,FE.JFN		; OF COURSE, WE NEED THE JFN ON THE -10
	MOVEM AC1,NODARG+.NSACH
	MOVEI AC1,7(T2)		; THIS IS A SEVEN BYTE MESSAGE PLUS DATA
	MOVEM AC1,NODARG+.NSAA1
	MOVE AC1,[POINT 8,FE.MSG] ; POINTER TO THE DATA SECTION OF MESSAGE
	MOVEM AC1,NODARG+.NSAA2
	MOVEI AC1,NODARG	; FINNALY, A POINTER TO OUR ARGUMENT BLOCK
	NSP. AC1,
	 JRST [	TYPE <?
?NSP. send to the MCB failed.
>
		SETZ T2,
		RET ,GETMC1]
	MOVE AC1,[NS.WAI!<.NSFDR,,4>] ; WAIT OPERATION, READ DATA
	MOVEM AC1,NODARG+.NSAFN	; START BUILDING REQUEST
	MOVE AC1,FE.JFN		; OF COURSE, WE NEED THE JFN ON THE -10
	MOVEM AC1,NODARG+.NSACH
	MOVEI AC1,1		; A ONE BYTE OK FLAG
	MOVEM AC1,NODARG+.NSAA1
	MOVE AC1,[POINT 8,FE.MSG] ; POINTER TO THE DATA SECTION OF MESSAGE
	MOVEM AC1,NODARG+.NSAA2
	MOVEI AC1,NODARG	; FINNALY, A POINTER TO OUR ARGUMENT BLOCK
	NSP. AC1,
	 JRST [	TYPE <?
?NSP. send response from the MCB failed.
>
		SETZ T2,
		RET ,GETMC1]
	MOVE AC2,[POINT 8,FE.MSG]
	ILDB AC3,AC2
	CAIE AC3,1
	 JRST [	TYPE <?
?Bad message from the MCB.  No good reason.
>
		MOVE AC1,AC3
		SETZ T2,
		RET ,GETMC1]
	JRST GETWD3


; HERE TO BUILD THE COMMON PART OF A MCB MESSAGE FOR DEPOSIT

PMCB1:	MOVE AC1,[BYTE(8) ^D12,0,0,0] ;A NICE DEPOSIT MESSAGE
	MOVEM AC1,FE.MSG
	MOVE AC1,[BYTE(8) 0,0,0,0]
	MOVEM AC1,FE.MSG+1
	MOVE AC1,[POINT 8,FE.MSG+1,23] ;WHERE TO PUT THE DATA
	SETZ T2,		;BYTE COUNT
PBTMCB:	ADDI T2,1
	ILDB AC2,DAT
	IDPB AC2,AC1
	CAME T5,DAT
	JRST PBTMCB
;
; THE FOLLOWING THREE INSTRUCTIONS ARE FOR A LDW CROCK THAT I HAVE NO BETTER
; WAY ARROUND AT THIS TIME.   SIGH...
;
	MOVE AC2,TYPDAT		; GET THE DATA TYPE WE ARE PUTING IN MEMORY
	CAIN AC2,DAT.NU		; IS IT NUMERIC?
	MOVEI T2,2		; YES, CORRECT THE DATA TO TWO BYTES LONG
				; INSTAED OF THE THREE THAT ARE THERE...
IFN DEBUG,<
	MOVE QX,F.DEBU
	TXNE QX,DB.EXD
	CAIE AC2,DAT.NU
	JRST PUTMC2		; SKIP THE DEBUG STUFF...
	TYPE <% Data length is corrected to 2 bytes
>
PUTMC2:>
	DPB T2,[POINT 8,FE.MSG+1,23] ;BYTE COUNT
	MOVE AC1,[POINT 8,FE.MSG,15]
	MOVEI AC2,4
	PUSH P,T1
PAFMCB:	IDPB T1,AC1
	LSH T1,-^D8
	SOJG AC2,PAFMCB
	POP P,T1
	RET ,PMCB1



PUTMCB:	DBG1TYP DB.EXD,<% Deposit is thru the MCB logical link interface.
>
	CALL PMCB1
	MOVE AC1,FE.JFN
	MOVE AC2,[POINT 8,FE.MSG]
	ADDI T2,7
	MOVN AC3,T2
	SOUTR
	 ERJMP [RET ,PUTMCB]
	MOVE AC2,[POINT 8,FE.MSG]
	MOVNI AC3,1
	SINR
	 ERJMP [RET ,PUTMCB]
	LDB AC1,[POINT 8,FE.MSG,7]
	CAIE AC1,1
	RET ,PUTMCB
	JRST GETWD3

;HERE WHEN PUTTING BYTES WITH CAL11. OR CAL78. UUO'S

PUT.C1:	DBG1TYP DB.EXD,<% Deposit is thru CAL11. or CAL78. UUO.
>
	MOVEM T1,T3		;SAVE ADR TO DEPOSIT INTO
PUTP.2:	ILDB T4,DAT		;GET LOW ORDER BYTE
	TRNN T3,1
	CAMN T5,DAT
	JRST PUTP.4
	ILDB T1,DAT		;GET HIGH ORDER BYTE
	DPB T1,[POINT 8,T4,27]
PUTP.4:	MOVEI T2,0		;FUNCTION 0
	MOVE T1,[3,,T2]
	HRL T2,PORT		;ADD PORT NUMBER
	CAL78.	T1,
	SKIPA T1,[3,,T2]
	JRST PUTP.8		;WIN RETURN
	CAL11.	T1,
	JRST [	CAIE T1,4	;ALREADY IN USE?
		RET ,PUT.C1
		MOVEI T1,^D100	;WAIT A WHILE
		HIBER T1,	;AND SEE
		RET ,PUT.C1
		JRST PUTP.4]	;TRY AGAIN
PUTP.8:	HRRZI T3,2(T3)
	TRZ T3,1
	CAME T5,DAT
	JRST PUTP.2
	JRST GETWD3		;WIN RETURN

; PUTD62 - stuff words into a TOPS20 DN60 FE
;	shamelessy(and probably foolishly) plagerized from PUT.C1

PUTD62:	DBG1TYP DB.EXD,<% Deposit is thru the DN62 TOPS-20 interface.
>
	MOVEM T1,T3		;SAVE ADR TO DEPOSIT INTO
PT6.2:	ILDB T2,DAT		;GET LOW ORDER BYTE
	TRNN T3,1
	CAMN T5,DAT
	JRST PT6.4
	ILDB T4,DAT		;GET HIGH ORDER BYTE
	DPB T4,[POINT 8,T2,27]
PT6.4:	MOVE T1,T3		;get the place to crammit
	CALL D62DEP		; so deposit it
	SKIPA T1,AC1		; loser
	JRST PT6.8
	RET ,PUTD62

PT6.8:	HRRZI T3,2(T3)
	TRZ T3,1
	CAME T5,DAT
	JRST PT6.2
	JRST GETWD3		;WIN RETURN

;HERE WHEN PUTTING BYTES WITH NODE. UUO

PUTNOD:	DBG1TYP DB.EXD,<% Deposit is thru the NODE. UUO.
>
	CALL SETUPN		;BEGIN NODE. MSG <LINE><CODE><ADR>
	EXP 2			;CODE FOR DEPOSIT IS 2
PUTND2:	ILDB T1,DAT		;GET NEXT BYTE
	IDPB T1,T4		;PUT NEXT BYTE INTO MESSAGE
	CAME T5,DAT		;DONE ENOUGH YET ?
	JRST PUTND2		;NOT YET
	CALL NODSET		;SEND MSG
	RET ,PUTNOD
	CAIE T1,11		;DID WE GET AN ACCEPT ?
	JRST STCERR
	JRST GETWD3

;DEAL WITH RSX20F/TOPS-10 DEPOSITS HERE
;T1/<STARTING ADDRESS> T5/<BP TO LAST BYTE> DAT/<BP TO FIRST BYTE>

PUT.FE:	DBG1TYP DB.EXD,<% Deposit is thru the TOPS-20 FE device.
>
	HRLI T1,IO.WLB		;SET WRITE FCN
	CALL ME.SET		;SET UP HEADER
	MOVNI T3,FE.MAX		;SET LIMIT ON DEPOSIT
	MOVE T4,[POINT 18,FE.MSG+3] ;POINT TO DATA MESSAGE
PT.F1A:	ILDB T1,DAT		;GET A BYTE
	TRNN T3,1		;EVEN?
	IDPB T1,T4		;COPY TO FE BUFFER
	TRNE T3,1		;ODD?
	JRST [	PUSH P,T5	;SAVE END
		MOVE T5,T4	;AND GET LAST WORD DEPOSITED
		ADD T5,[100000,,0] ;POINT TO HIGH BYTE
		TLC T5,003200	;AND CHANGE BYTE SIZE
		DPB T1,T5	;INSERT IT
		POP P,T5	;RESTORE END
		JRST .+1]	;...
	CAME T5,DAT		;GOT LAST?
	AOJL T3,PT.F1A		;NO, DO NEXT
	JUMPGE T3,[TYPE <?
?Deposit size exceeds 20F max
>
		RET ,PUT.FE]
	ADDI T3,FE.MAX+1	;NUMBER OF BYTES ACTUALLY MOVED
	HRRM T3,FE.MSG+2	;STUFF IN HEADER
	AOJ T3,			;ROUND BYTES TO WORDS
	ASH T3,-1		;AND CONVERT
	MOVSS T3
	ADDM T3,FE.BUF		;ADD TO AMT XFERED BY UUO
	MOVE T1,OSTYPE		;GET OS TYPE
	TXNN T1,T.TOP10		;TOPS-10?
	 JRST PT.F20		;YES, DO THAT
	MOVE T1,[.DTEOF,,FE.CPU] ;ZAP MSG OUT
	DTE. T1,
	 JRST DTEERR		;...
	CALL FE.RPY		;READ REPLY
	RET ,PUT.FE
	SKIPE T1		;IF ASSOCIATED
	 JRST FE$BLT		;BLAT...DATA WITH WRITE REPLY IS BAD
	JRST GETWD3		;OK, DONE

;TOPS-20 DEPOSIT

PT.F20:	MOVE AC1,FE.JFN		;GET THE JFN OF FE:
	MOVE AC2,[POINT 18,FE.MSG] ;POINT TO MESSAGE
	HLRZ AC3,FE.BUF		;GET WC FROM TOPS-10
	MOVNS AC3		; - WC
	SOUT			;SLITHER
	 ERJMP [RET ,PT.F20]	;BLAT
	MOVEI AC2,.MOEOF	;FORCE BUFFER OUT
	SETO AC3,		;BUT DON'T SEND EOF
	MTOPR			;FLOP
	 ERJMP [RET ,PT.F20]
	CALL GETFEM		;GET REPLY
	RET ,PT.F20
	SKIPE AC3		;DATA WITH WRITE REPLY?
	 JRST FE$BLT		;BLAT?
	JRST GETWD3		;OK, DONE

;HERE WHEN PUTTING BYTES IN 11 MEMORY

PUTMEM:	DBG1TYP DB.EXD,<% Deposit is to simualted memory.
>
	MOVE T4,MEMORY		;GET THE START OF OUR MEMORY
	MOVEM T1,T2		;PUT ADR IN OTHER REG
PTMEM2:	CAML T2,MEMLIM		;IS ADR IN RANGE ?
	JRST PTMEM4		;NO
	ILDB T1,DAT		;GET NEXT BYTE OF DATA
	CALL PUTFOO		;PUT LOW ORDER BYTE INTO MEMORY
	CAME T5,DAT		;DONE ALL OF IT ?
	AOJA T2,PTMEM2		;NO SO LOOP BACK FOR NEXT BYTE
	JRST GETWD3

;HERE TO DEPOSIT IN SIMULATED DEVICES
PTMEM4:	MOVEM T2,MA		;PUT ADDRESS IN CORRECT REG
	PUSH P,T5		;SAVE LIMIT
PTMEM5:	ILDB T1,DAT		;GET NEXT BYTE OF DATA
	MOVE T2,(P)		;GET LIMIT
	CAME T2,DAT		;IS THIS LAST BYTE TO DEPOSIT ?
	TRNE MA,1		;IS THIS AN ODD BYTE ?
	JRST PTMEM6		;MUST USE BYTE STORE
	ILDB T2,DAT		;GET LH OF WORD
	DPB T2,[POINT 8,T1,27]
	CALL IOSTOR		;STORE THE WORD
	JRST PTMEM7
PTMEM6:	CALL IOBSTO		;TRY TO WRITE BYTE IN THE IO AREA
PTMEM7:	MOVE T1,(P)		;GET LIMIT
	CAME T1,DAT		;DONE ALL OF IT
	AOJA MA,PTMEM5
	POP P,T1		;CLEAN OFF STACK
	JRST GETWD3		;WIN RETURN
repeat 0,<

;HERE WHEN PUTTING BYTES IN 11 MEMORY

PUTMEM:	MOVE T4,MEMORY		;GET THE START OF OUR MEMORY
	MOVEM T1,T2		;PUT ADR IN OTHER REG
	PUSH P,T3
	ANDI T1,177777
	CAIL T1,177700		;IF WE ARE			
	CAILE T1,177707		;  MODIFYING A			
	JRST PTMEM1		;  REGISTER,			
	ANDI T1,7		;  CHANGE ONLY			
	ILDB T3,DAT		;  THE SPECIAL REGISTERS	
	DPB T3,[POINT 8,REG0(T1),35]
	ILDB T3,DAT
	DPB T3,[POINT 8,REG0(T1),27]
	POP P,T3
	JRST GETWD3		;  AND DON'T STORE INTO MEMORY	
PTMEM1:	CAIL T1,172340		;IF WE ARE			
	CAIL T1,172360		;  MODIFYING			
	JRST PTMEM2		;  A PAR,			
	ANDI T1,17		;  MODIFY THE			
	ASH T1,-1		;  SPECIAL			
	PUSH P,DAT		;  REGISTERS			
	ILDB T3,DAT		;  AS WELL AS			
	DPB T3,[POINT 8,PAR0(T1),35]
	ILDB T3,DAT		;  THE MEMORY			
	DPB T3,[POINT 8,PAR0(T1),27]
	POP P,DAT
PTMEM2:	POP P,T3
	CAML T2,MEMLIM		;IS ADR IN RANGE ?
	JRST PTMEM4		;NO
	ILDB T1,DAT		;GET NEXT BYTE OF DATA
	SKIPN F.MCB
	JRST PTMEM3		;  DON'T DO RELOCATION		
	CALL PUTMDM		;DO RELOCATION			
	JRST PTME3A
PTMEM3:	CALL PUTFOO		;PUT LOW ORDER BYTE INTO MEMORY
PTME3A:	CAME T5,DAT		;DONE ALL OF IT ?
	AOJA T2,PTMEM2		;NO SO LOOP BACK FOR NEXT BYTE
	JRST GETWD3

;HERE TO DEPOSIT IN SIMULATED DEVICES

PTMEM4:	MOVEM T2,MA		;PUT ADDRESS IN CORRECT REG
	PUSH P,T5		;SAVE LIMIT
PTMEM5:	ILDB T1,DAT		;GET NEXT BYTE OF DATA
	MOVE T2,(P)		;GET LIMIT
	CAME T2,DAT		;IS THIS LAST BYTE TO DEPOSIT ?
	TRNE MA,1		;IS THIS AN ODD BYTE ?
	JRST PTMEM6		;MUST USE BYTE STORE
	ILDB T2,DAT		;GET LH OF WORD
	DPB T2,[POINT 8,T1,27]
	CALL IOSTOR		;STORE THE WORD
	JRST PTMEM7
PTMEM6:	CALL IOBSTO		;TRY TO WRITE BYTE IN THE IO AREA
PTMEM7:	MOVE T1,(P)		;GET LIMIT
	CAME T1,DAT		;DONE ALL OF IT
	AOJA MA,PTMEM5
	POP P,T1		;CLEAN OFF STACK
	JRST GETWD3		;WIN RETURN

;HERE TO PUT A BYTE INTO THE LARGE ADDRESS SPACE, USING MAPPING

PUTMDM:	TXNE T2,600000		;LARGER THAN 32K?
	JRST PUTMD0		;YES, SKIP THIS STUFF
	PUSH P,T3		; SAVE AN AC, EAT A PREPIE
	MOVE T3,T2		; COPY OF THE ADDRESS
	ANDI T3,177777		; 16 BIT ADDRESS, PLEASE
	ASH T3,-^D13		; CONVERT IT MAP REG.
	MOVE T3,PAR0(T3)	; MAP IT AWAY
	ASH T3,6		; BUMP IT UP
	ANDI T2,17777		; CLEAR EXTRA BITS, PLEASE
	ADD T2,T3		; WHERE IT IS IN CORE
PUTMD0:	POP P,T3
	CALL PUTFOO		; DO THE REAL WORK
	RET ,PUTMEM
>

;HERE TO PUT A BYTE INTO A CORE DUMP
; CALL CALL PUTFOO	WITH DATA IN T1, ADR IN T2

PUTFOO:	CALL SAVE4
	PUSH P,T1
	ANDI T2,-1		; STRIP EXTRA BITS
	SKIPN F.MCB
	ANDI T2,177777		;STRIP EXTRA BITS (& LH)
	PUSH P,T2
	SKIPE MEMORY		;DO WE HAVE A BASE ADDRESS FOR DUMPS ?
	JRST PUTBY1
	CALL POSYMT		;BE SURE SYMBOL TABLE IS WHERE IT BELONGS
	MOVE T1,SYMBEG		;WHERE WE WILL PUT DATA
	HRRZM T1,MEMORY		;POINT TO WHERE MEMORY WILL BE
	SETOM MEMLIM
	HRLI T1,T1		;MAKE MEMUSE POINTER
	MOVEM T1,MEMUSE		;SAVE POINTER TO MEMORY USAGE TABLE
PUTBY1:	MOVE T2,(P)		;GET ADDRESS WE WANT OFF STACK
	CAMG T2,MEMLIM		;IS ADDRESS LARGER THAN PREVIOUS LIMIT ?
	JRST PUTBY4		;NO
	MOVEI T1,4000		;GET ANOTHER 2K PDP10 WORDS
PUTBY2:	MOVE T2,T1		;NUMBER OF PDP-10 WORDS TO ADD
	LSH T2,2		;MAKES NUMBER OF PDP11 BYTES
	SKIPE PDP8F
	LSH T2,-1		;MAKES NUMBER OF PDP8 WORDS
	ADDM T2,MEMLIM
	CALL MOVSMT		;MOVE THE SYMBOL TABLE UP AGAIN
	MOVE T1,MEMLIM		;GET SIMULATED MEMORY SIZE
	IDIVI T1,^D36		;NEW SIZE FOR MEMUSE
	AOS T1			;JUST IN CASE
	ADDI T1,777		;ROUND TO NEXT PAGE
	ANDI T1,777000		;ROUND TO NEXT PAGE
	SUB T1,MEMORY
	ADD T1,MEMUSE		;MAKES HOW MANY MORE WORDS WE NEED
	ANDI T1,-1
	SKIPE T1		; DO WE NEED THE MOVE?
	CALL MOVMEM		; YES, MOVE MEMORY TO ADJUST FOR THIS
	CALL MAPCOR		;UPDATE MEMORY MAP
	JRST PUTBY1		;BACK TO BE SURE THAT WAS ENOUGH

PUTBY4:	MOVE T1,(P)		;GET ADR OFF STACK
	IDIVI T1,^D36		;CONVERT BYTE ADDRESS TO BIT ADDRESS
	MOVSI T3,400000
	MOVNS T2
	LSH T3,(T2)		;POSITION BIT
	IORM T3,@MEMUSE
	POP P,T2
	POP P,T1
	SKIPE PDP8F
	JRST PUTBY7
	IDIVI T2,^D4
	ADD T2,MEMORY		;RELOCATE
	DPB T1,[POINT 8,(T2),17
		POINT 8,(T2),9
		POINT 8,(T2),35
		POINT 8,(T2),27 ](T3)
	RET ,PUTFOO

;HERE TO PUT A PDP8 WORD IN MEMORY

PUTBY7:	IORI T1,10000		;FLAG WORD IS HERE
	IDIVI T2,2		;PUT 2 8 WORDS IN A PDP10 WORD
	ADD T2,MEMORY		;RELOCATE
	DPB T1,[POINT 18,(T2),17
		POINT 18,(T2),35 ](T3)
	RET ,PUTFOO

; D62EXM - EXAMINE A TOPS-20 DN60 FRONT END
;	T1/ADDRESS TO EXAMINE
; RETURNS:
;	FALSE - AC1/ERROR CODE
;	TRUE  - T1/DATA
;		T2/ADDRESS EXAMINED

D62EXM:	SETZ AC0,		; CLEAR THIS AS A COUNTER
	MOVEI AC1,1		; A VERY SHORT TIME TO WAIT
	SKIPA 			; AND JUMP INTO THE CODE LINE
D62EXW:	MOVEI AC1,^D50
	DISMS
	ADDI AC0,1		; COUNT THAT WE FAILED AND WAITED
IFN DEBUG,<
	CAIN AC0,1		; FIRST TIME HERE?
	JRST D62EX3		; YES, SKIP THIS
	DBGTYP DB.EXD,<%Error obtaining DTE for Examine/Deposit
>
D62EX3:
>
	CAIN AC0,100		; 64 FAILURES ?
D62EX4:	JRST [	MOVEI T2,GENERR	; GENERAL ERROR TYPE
		MOVEI AC1,ER.DTE ; DTE TIME OUT ERROR
		RET ,D62EXM]
	SKIPE PVTYP		; GET PORT TYPE
	JRST D62EX1		; NOT VERSION 5, MATE
	CALL FESUP		; get the port
	JRST D62EXW		; can't have it yet
D62EX1:	SETZM @D10DT		; set up the DN60 request header
	MOVEI T2,D6.EXM
	DPB T2,D10FN		; the appropriate function
	DPB T1,D10AD		; and where
	CALL PUTHDR		; Output the header to say read data
	RET ,D62EXM
	SKIPE PVTYP
	JRST D62EX2
	CALL GETHDR		; Get the response header
	RET ,D62EXM
D62EX2:	LDB T1,D11DT		; get the data
	LDB T2,D11AD		; get the address back
	RET SKIP,D62EXM

; D62DEP - deposit word in TOPS-20 DN60 front end
;	T2/data to deposit
;	T1/address to stuff it
; RETURNS:
;	false - AC1/error code
;	true  - original args

D62DEP:	SETZ AC0,
	MOVEI AC1,1
	SKIPA
D62DEW:	MOVEI AC1,^D50		; THE AMOUNT OF TIME TO WAIT
	DISMS			; SLEEP FOR A SHORT TIME
	ADDI AC0,1		; COUNT THIS
IFN DEBUG,<
	CAIN AC0,1		; IS THIS THE FIRST PASS?
	JRST D62DE3		; YES, NO PROBLEM

	DBGTYP DB.EXD,<%Error obtaining DTE for Examine/Deposit
>
D62DE3:
>
	CAIN AC0,^D64		; TOO MANY TIMES THAT WE FAILED?
	JRST D62EX4		; YES, SO COMPLAIN
	SKIPE PVTYP
	JRST D62DP1
	CALL FESUP		; get the port
	JRST D62DEW		; all booked for now
D62DP1:	DPB T2,D10DT		; set up the  DN60 request header
	DPB T1,D10AD
	MOVEI AC1,D6.DEP
	DPB AC1,D10FN
	CALL PUTHDR		; Output the transmit header
	RET ,D62DEP
	SKIPE PVTYP
	RET SAFE,D62DEP
	JRST GETHDR		; have to read the response to complete the transaction

; PUTHDR - create a transmit header for read/write function that contains
;	the number of bytes to read/write in it. This routine is invoked before
;	each read/write is done if more data is needed to be read/written.
;	This routines also transmits the header and makes sure that it has gone
;	out.

PUTHDR:	SKIPE PVTYP
	JRST PUTHD5
	MOVE AC1,FE.JFN		; Get the JFN for the FE
	MOVE AC2,[POINT 8,XMTHDR] ; Point to the transmit header
	MOVNI AC3,6		; Get the string byte count
	SKIPGE	PTYPE		; Check for 2020 style I/O
	JRST WR2020		;  and output the header 2020 style
	SOUT			; Output the header to the device
	ERJMP [RET ,PUTHDR]	;  Can't talk to FE

; IOBRK - To create a break in the I/O stream and force the current buffers
;	to be flushed or finished reading in.

IOBRK:	MOVE AC1,FE.JFN		; Get the JFN of the FE device
	MOVX AC2,.MOEOF		; Get the EOF function
	MOVEI AC3,1		; Clear FE buffers w/o doing real EOF
	MTOPR			; Force I/O completion
	ERJMP [RET ,IOBRK]	;  Can't talk to FE
	RET SKIP,IOBRK

PUTHD5:	MOVEI AC2,PUTARG
	MOVE AC1,PORT
	ANDI AC1,7
	MOVEM AC1,BT6DTE(AC2)
	MOVEI AC1,6
	HRLM AC1,BT6HDR(AC2)
	MOVEI AC1,XMTHDR
	HRRM AC1,BT6HDR(AC2)
	SETZM BT6DBC(AC2)
	SETZM BT6PTR(AC2)
	MOVEI AC1,.BTD60
	BOOT
	ERJMP [MOVE AC1,PUTARG+BT6ERR
		RET ,PUTHDR]
	RET SKIP,PUTHDR

; GETHDR - To read a receive header from the port that we are currently
;	talking to.

GETHDR: MOVE AC1,FE.JFN		; Get the JFN of the FE
	MOVE AC2,[POINT 8,RCVHDR] ; Point to the receive header string
	MOVNI AC3,6		; 6 bytes in the header
	SKIPGE PTYPE		; Check for 2020 style I/O
	JRST RD2020		; Read header 2020 style
	SIN			; Read the header from the FE
	ERJMP [RET ,GETHDR]	;  Can't talk to FE
	JRST IOBRK

; WR2020 - This routine is used to simulate the SOUT to a front end
;	     device. It actually ships the data over a synchronous link
;	     using DDCMP to a DN200

; Parameters -

;	AC1/	Ignored JFN
;	AC2/	Byte pointer to string
;	AC3/	Negative byte count

WR2020: MOVMM AC3,.BTLEN+BTARG 	; Set the byte count to transfer
	MOVEM AC2,.BTMSG+BTARG	; Set pointer to 8 bit byte area
	MOVE AC1,PORT		; Get synchronous line number
	HRRZM AC1,.BTDTE+BTARG 	; Set it as the DTE/line in BOOT block
	MOVEI AC2,BTARG		; Get location of BOOT arg block
	MOVX AC1,.BTSDD		; Send DDCMP message to DN200
	BOOT
	ERJMP [RET ,WR2020]
	RET SKIP,WR2020

; RD2020 - To read a string from a DN200 that is connected by a DDCMP
;	     synchronous link. This routine simulates the SIN JSYS that
;	     is normally used with a front end device.

; Parameters -

;	AC1/	Ignored JFN
;	AC2/	Byte pointer to input buffer
;	AC3/	Negative byte count to input

RD2020: DMOVEM AC2,RDSAVE	; Save the read arguments
	MOVE AC1,PORT		; Get synchronous line number
	HRRZM AC1,.BTDTE+BTARG 	; Set it as the DTE/line in BOOT block

RD20ST: MOVMM AC3,.BTLEN+BTARG 	; Set the byte count to transfer
	MOVEM AC2,.BTMSG+BTARG	; Set pointer to data buffer
	MOVEI AC2,BTARG		; Get location of BOOT arg block
	MOVX AC1,.BTRDD		; Read DDCMP message function
	BOOT			; Do the read
	ERJMP [RET ,RD2020]	;  BOOT JSYS failed
	MOVE AC1,.BTLEN+BTARG	; Get transfered length/error code
	JUMPE AC1,R20AGN
	TXNN AC1,BT%CTL		; Check for control message flag
	RET SAFE,RD2020
	CAXE AC1,BT%CTL+.BTCMP	; Transmission complete?
	RET ,RD2020
				;  with time
R20AGN:	MOVEI AC1,^D50		;A SHORT TIME
	DISMS
	DMOVE AC2,RDSAVE
	JRST RD20ST

; FESUP - set up port for private use
;	RESTRICTION: must be called from the caller's top level

FESUP:				; set up port for molesting in private
	SKIPGE PTYPE		; Check for KS10 style I/O
	JRST FESUP1
	CALL SELDTE		;  Make the link to the correct DTE
	RET ,FESUP		;  If didn't work give error return
FESUP1:				; Enqueue the port for SIN/SOUT I/O
				; fall into  enq function

;ENQD60 - To ENQ a DN60 front end to block others from using it while

ENQD60:	MOVEI AC2,ENQBLK	; this must be called from the caller's top level
	MOVX AC1,.ENQBL		; Get the enqueue function number
	ENQ			;  and try to do it.
	RET ,ENQD60		;  False return if we can't ENQ
	POP P,AC1
	CALL 1(AC1)		; call the true return so the caller
				; will return here for dequeing the port
	JRST [	PUSH P,AC1	; error return - deque the port
		CALL DEQD60	; the original error is returned
		NOP		; ignore addtional failures
		POP P,AC1
		RET ,ENQD60]
				; this returns sucs - just fall into DEQD60

;DEQD60 - To dequeue a DN60 on a port so that others can use it again.

DEQD60: MOVEI AC2,ENQBLK
	MOVX AC1,.DEQDR		; Get the DEQ function code
	DEQ
	RET ,DEQD60
	RET SKIP,DEQD60

; QUED60 -  make up the argument block needed to ENQ/DEQ a specific port.

;	T1/ port number

QUED60:	PUSH P,T1
	SKIPGE	PTYPE
	ANDI T1,7		; for DN22, use line no.
	DPB T1,QPRT0		; just cram two octal segments in string
	LSH T1,-3
	DPB T1,QPRT1
	POP P,T1
	RET ,QUED60

; SELDTE - To select which DTE is currently attached to the FEn: device
;	that was previously opened.

;	PORT/	DTE # to be selected
; RETURN:
;	True	was successful
;	False	MTOPR Jsys failed and the error code is in AC1

SELDTE:	MOVE AC1,PORT		;get the dte #
	MOVX AC2,.MODTE		; Select the appropriate DTE
	HRROI AC3,-10(AC1)	; Get the port number
	CAMN AC3,LSTDTE		; Was it the same as the last one used?
	RET SAFE,SELDTE
	HRRZ AC3,AC3		; Make it only the DTE number
	MOVE AC1,FE.JFN		; Use the FE JFN already opened
	MTOPR			; Do the select
	ERJMP DSLERR		;  Didn't work, bad DTE
	HRROM AC3,LSTDTE	; Save the last DTE to be selected
	RET SKIP,SELDTE		; It is now selected on the DTE

DSLERR: SETZM LSTDTE		; Clear the last DTE selected (none)
	MOVX AC1,.FHSLF		; Get the last error that occurred
	GETER			;  in this process
	HRRZ AC1,AC2		; Set the error value
	RET ,DLSERR		;  and return flaging failure.

; CPUTYP - cleverly determine what processor we are on

CPUTYP:	JFCL .+1		; CLEAR THE FLAGS
	JRST .+1		; SEE IF WE CHANGE THE PC FLAG
	JFCL AC1,PDP6		; YES,IT WAS A PDP-6
	SETO AC1,		; SET AC TO -1
	AOBJN AC1,.+1		; SEE HOW IT ADDS 1,,1 TO -1
	JUMPN AC1,KA10		; ON A KA, IT IS TWO FULL ADDS
	BLT AC1,0		; NOOP BLT
	JUMPE AC1,KI10		; KI WONT UPDATE THE WORD
	DMOVE AC1,[EXP 1,0]	; 1, AND NO STRING POINTER
	DMOVE AC3,AC1		; OFFSET OF 1
	EXTEND	AC1,[CVTBDO]	; CONVERT DECIMAL TO BINARY WITH OFFSET
	TLNE AC4,200000		; LOOK FOR KL MICROCODE BUG
KL10:	SKIPA AC1,[P.KL10]	; set KL10 type
KS10:	MOVX AC1,P.KS10		; set KS10 type
SETCPU:	MOVEM AC1,PTYPE		; set the cpu type
	RET ,CPUTYP

KA10:	SKIPA AC1,[P.KA10]	; set KA10 type
KI10:	MOVX AC1,P.KI10		; set KI10 type
	JRST SETCPU

PDP6:	MOVX AC1,P.PDP6		; set PDP-6 type
	JRST SETCPU

PROTYP:	CALL CPUTYP
	SKIPGE PTYPE		;ARE WE A 2020
	JRST PRODFL		;YES, NO DTE CODE
	MOVEI AC2,PROARG
	MOVE AC1,PORT
	ANDI AC1,7
	MOVEM AC1,.BTDTE(AC2)	; STUFF IN DTE NUMBER
	MOVEI AC1,.BTSTS	; READ STATUS FUNCTION
	BOOT			; GET IT....
	ERJMP PRODFL		; FAIL, WE LOSE BIG
	MOVE AC1,PROARG+.BTCOD
	JUMPL AC1,PRODF1
	CAIE AC1,.VND60		; DN60 ?
PRODFL:	SETZ AC1,		; NO, WE LOSE BIG
PRODF1:	MOVEM AC1,PVTYP
	RET ,PROTYP

;HERE TO CLEAR MEMORY OUT

CLRMEM:	SKIPN T1,MEMORY		;DID WE READ INTO MEMORY BEFORE ?
	RET SAFE,CLRMEM
	HRL T1,SYMBEG		;BUILD BLT POINTER
	HRRZ T2,SYMEND
	ADDI T2,(T1)
	SUB T2,SYMBEG
	HRRZM T1,SYMBEG		;NEW BEGINNING OF SYMBOL TABLE
	BLT T1,(T2)
	MOVE T1,.JBFF##
	CAMN T1,SYMEND
	MOVE T1,T2		;THIS IS NEW .JBFF##
	MOVEM T2,SYMEND
	HRRZM T1,.JBFF##
	HRLM T1,.JBSA##
	CORE T1,
	JRST CORERR
	SETZM MEMORY
	SETOM MEMLIM
	RET SKIP,CLRMEM

; DATA FOR THESE ROUTINES

;THE CACHE IS SO WORK OVER SYNCHRONOUS LINE WILL BE FASTER
CACHEL:	0			;CACHE LIMIT, I.E. 1ST NONEXISTEN BYTE ADR IN CACHE
CACHEA:	0			;ADDRESS REPRESENTED BY FIRST ADR IN CACHE
CACHSZ==400			;NUMBER OF WORDS IN CACHE
CACHE:	BLOCK <CACHSZ/4>

PUTARG:
BTARG:	BLOCK BT6SIZ		; BOOT JSYS argument block

RDSAVE: BLOCK 1			; Save area for RD2020 arguments
RDSLEN: BLOCK 1			;  including the length
DEFOUT:: BLOCK 1		; DEAFULT OUTPUT

D10FN:	POINT 16,XMTHDR,15	; fcn code to 11
D10AD:	POINT 16,XMTHDR,31	; examine/deposit address
D10DT:	POINT 16,XMTHDR+1,15	; deposit data
D11RS:	POINT 8,RCVHDR,7	; result code from FE
D11FN:	POINT 8,RCVHDR,15	; function performed
D11AD:	POINT 16,RCVHDR,31	; examine/deposti address
D11DT:	POINT 16,RCVHDR+1,15	; examine data

LSTDTE: BLOCK 1			; Last DTE that was selected

RCVHDR:: BLOCK 0		; Receive header
XMTHDR:: BLOCK D6HWSZ		; Transmit header
XMSG:	BLOCK <274/4+1>		; DDCMP QUEUE FLUSH AREA

ENQBLK: XWD 1,5			; 1 lock,,length of block is 5
	XWD 0,0			; PSI chn 0,, ID
	EXP EN%BLN+EN%LTL+<0,,-3> ; long term data base,, Operator only
	POINT 7,QD60BF		; Pointer to string of resource name
	XWD 0,0			; 1 resource,, number of accesses

QPRT0:	POINT 3,QD60BF+1,20	; Low order digit of port number
QPRT1:	POINT 3,QD60BF+1,13	; High order digit of port number
QD60BF: ASCIZ	\DN60-P00\	; Same name as used by D60SPD and

NODARG:	BLOCK 5
STCMSG:	BLOCK 20
STCIMS:	BLOCK 110
FENAME:	Z			;THIS IS ASCIZ \FE#:\ IF USING TOPS20 FRONT END
	Z
FE.JFN:	Z			;JFN FOR THE FRONT END DEVICE
FE.MSG:	BLOCK <<14+FE.MAX>+3>/4	;MESSAGE FOR FRONT END

;KEEP IN ORDER
FE.CPU:	BLOCK 1			;CPU,,DTE
FE.FED:	BLOCK 1			;FED #
FE.STS:				;Will the turkey who keeps putting a BLOCK 1 here please stop
FE.BUF:	BLOCK 1			;ABOVE 3 WORDS ARE DTE. ARG BLK
;KEPT IN ORDER

ETYPE:	Z			;TYPE OF EXAMINE ANE DEPOSIT WE WILL DO

PORT:	Z			;-1,,PORT NUMBER FOR CALL11 UUO'S

NODE.N:	Z			;NAME OR NODE NUMBER WE ARE WORKING WITH

LINE:	Z			;LINE NUMBER ON NODE WE ARE WORKING WITH

PTYPE:	0			; processor type

PVTYP:	BLOCK 1

PROARG:	BLOCK 2

	END