Google
 

Trailing-Edge - PDP-10 Archives - bb-j710b-bm_tops20_v41_tools - tools/ddt11/ddtgp.mac
There are 16 other files named ddtgp.mac in the archive. Click here to see a list.
	TITLE DDTGP DDT11 GET/PUT ROUTINES AND OTHER SUPPORT FOR THEM

	SUBTTL	LISTING CONTROL, AND OTHER USEFUL STUFF

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

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

; THINGS WE NEED FROM OTHER MODULES

EXTERN MEMORY,MEMLIM,MEMUSE,MOVMEM,MAPCOR,MOVSMT,SYMBEG,CORERR
EXTERN SAVE4,SAVE35,POSYMT,SIXIN,SIXOCT,OSTYPE,DECINP,DDT11
EXTERN LASTSW,LEVL.0,IOSTOR,IOBSTO,IOLOAD,UBACTL,PDP8F
EXTERN DAT,DATA,TYPCHR,COMTYP,CALER0,OCTYPE,TYPSTR,RSKP,R,SYMEND
EXTERN SWTTST

; ENTRY POINTS FOR THIS ROUTINE

ENTRY PUTFOO,DTEERR,QUED60,TPOPJ,GETWRD,PUTBYT,SETUPN,CLRMEM
ENTRY NODSET,GETMEM,ETYPE,CACHEL,CACHE,NODE.N,LINE,PORT
ENTRY SET.FE,SETBIN,SETDFE,SETDMP,SETFOO,SETLIN
ENTRY SETMCB,SETMCS,SETNOD,SETPRT,SETUBA
;HERE BECAUSE FILE TO BE READ IS BINARY TAPE

SETBIN:	SWTCHK BINARY
	TXO	FLG,F.FLOP
	MOVEI T1,EX.MEM
	MOVEM T1,ETYPE
	RETSKP
;HERE BECAUSE FILE TO BE READ IS NETLDR (OR EQUIVALENT) DUMP

SETDMP:	SWTCHK DUMP
	SWTCHK LSD
	TXZ FLG,F..FOO
	MOVEI T1,EX.MEM
	MOVEM T1,ETYPE
	RETSKP


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

SETMCS:	SWTCHK MCBSYS
	TXO FLG,F.MSYS		;EXAMINE UNRUN MCB
	JRST SETFOX
SETMCB:	SWTCHK MCBDMP
	TXO FLG,F.MCB		; SET LARGE DUMP BIT
	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
SETFOX:	TXO FLG,F..FOO
	MOVEI T1,EX.MEM
	MOVEM T1,ETYPE
	RETSKP
;HERE IF THE USER TYPES /MCB:node

SETDFE:	SWTCHK MCB
	TXO FLG,F.MCB		;ALLOW LARGE ADDRESSES
	MOVEI T1,EX.MCB		;EXAMINE TYPE IS RUNNING MCB
	MOVEM T1,ETYPE		;SAVE EXAMINE TYPE
	CAIE T5,":"		;IS THIS THE END OF THE LINE?
	JRST [TYPE <
?MCB switch requires node name as an argument
>
		RET]
	CALL SIXIN		;GET THE NODE NAME
	 RET			;FAILURE RETURN
	SKIPN T1		;WAS A NODE NAME SUPPLIED?
	JRST [TYPE <
?MCB switch requires node name as an argument
>
		ret]
	MOVEM T1,FENAME		;SAVE THE NODE NAME
	MOVE T1,[400000,,OPNMCB]
	MOVEM T1,LASTSW
	RETSKP			;SUCCESSFUL RETURN

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:	TYPE <
?Examine running MCB not yet implemented for TOPS10
>
	JRST DDT11

OMCB20:	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
	PUSH P,T5		;SAVE T5
GETN:	ILDB T5,AC3		;GET NEXT BYTE
	JUMPE T5,GOTN		;FINISHED?
	ADDI T5,40		;CONVERT TO ASCII
	IDPB T5,AC1		;
	AOBJN AC4,GETN		;
GOTN:	POP P,T5		;RESTORE T5
	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
	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
	JRST OPNFE8
;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]
	CAIE T5,":"
	JRST	[TYPE <
?Front End number required for the /FE switch
>
		RET]
	CALL	DECINP		;GET THE FRONTEND #
	JRST [	TYPE <
?Front End number required for the /FE switch
>
		RET]
	MOVE	T2,OSTYPE	;GET OPS TYPE
	TXNE	T2,T.TOP10	;IF TOPS-10, DO DIFFERENTLY (BETTER)
	 JRST	[JUMPL	T1,R	;DISALLOW JUNK
		 IDIVI	T1,^D10	;SPLIT CPU/DTE
		 CAIG	T1,5	;IF CPU TOO BIG
		  CAILE	T2,3	;OR DTE TOO BIG
		 RET		;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
		 MOVEI	T1,EX.FE1 ;TOPS-10 20F
		 MOVEM	T1,ETYPE  ;SAVE FOR EXAMINE CODE
		 RETSKP]
	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]
	SKIPA	T2,[EX.FE0]
SETD62:	MOVX	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
	RETSKP
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]
	CAIE T5,":"
	JRST [TYPE <
?Line switch requires an argument
>
		RET]
	CALL	SIXIN		;GET LINE ARGUMENT
	JRST [	TYPE <
?Illegal argument for /LINE switch
>
		RET]
	SKIPN T1
	JRST [TYPE <
?Line switch requires an argument
>
		RET]
	CALL	SIXOCT		;CONVERT TO NUMBER
	JRST [	TYPE <
?Illegal argument for the /LINE switch
>
		RET]
	AOS	T1
	MOVEM	T1,LINE
	MOVEI T1,EX.NOD
	MOVEM T1,ETYPE
	RETSKP
;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]
	CAIE T5,":"
	JRST [TYPE <
?Node switch requires an argument
>
		RET]
	CALL SIXIN		;GET NODE ARGUMENT
	JRST [	TYPE <
?Illegal argument for the /NODE switch
>
		RET]
	SKIPN T1
	JRST [TYPE <
?Node switch requires an argument
>
		RET]
	CALL SIXOCT		;CONVERT TO NUMBER
	JRST [	TYPE <
?Illegal value for the /NODE switch
>
		RET]
	MOVEM T1,NODE.N		;SAVE NODE NAME
	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
	RETSKP
;HERE FOR /PORT

SETPRT:	SWTCHK PORT
	CAIE T5,":"
	JRST [TYPE <
?Port switch requires an argument
>
		RET]
	CALL	SIXIN		;GET SIXBIT ARGUMENT
	JRST [	TYPE <
?Illegal argument for the /PORT switch
>
		RET]
	SKIPN T1
	JRST [TYPE <
?Port switch requires an argument
>
		RET]
	CALL	SIXOCT		;CONVERT TO OCTAL
	JRST [	TYPE <
?Illegal value for the /PORT switch
>
		RET]
	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	CPUTYP	; determine cpu type to dsitinguish DN20,DN22
		 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 ETYPE
	MOVE	T1,[400000,,LEVL.0]
	MOVEM	T1,LASTSW
	MOVEI T1,EX.PORT
	MOVEM T1,ETYPE
	RETSKP
;HERE FOR A /UBA COMMAND LINE

SETUBA:	SWTCHK UBA
	TXNN FLG,F.EXEC
	JRST [	TYPE <
?Illegal /UBA switch when not in EXEC mode
>
		RET]
	CAIN T5,":"		;WAS BREAK A COLON ?
	CALL DECINP		;GET ADAPTER NUMBER TO USE
	JRST [	TYPE <
?Illegal argument for the /UBA switch
>
		RET]
	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
		RETSKP]
	TYPE	<
?Illegal value for the /UBA switch
>
	RET
	SUBTTL	ROUTINES TO HANDLE PDP11 MEMORY

;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
	TXNN FLG,F.MCB		;IS THIS AN MCB (I.E. LARGE) DUMP?
	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
>
		HALT]
	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:	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,-1		;STRIP EXTRA BITS
	AOS	(P)		;SKIP RETURN
	RET

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](T4)		;FE0 ON TOPS-10
GETMCB:	MOVE T2,[BYTE(8) ^D13,0,0,0]
	MOVEM T2,FE.MSG
	MOVE T2,[BYTE(8) 0,0,2,0]
	MOVEM T2,FE.MSG+1
	MOVE T3,T1
	MOVE T1,[POINT 8,FE.MSG,15]
	MOVEI T2,4
GETW1C:	IDPB T3,T1
	LSH T3,-^D8
	SOJG T2,GETW1C
	MOVE AC1,FE.JFN
	MOVE AC2,[POINT 8,FE.MSG]
	MOVNI AC3,7
	SOUTR
	 ERJMP [SETZ T2,
		RET]
	MOVE AC2,[POINT 8,FE.MSG]
	MOVNI AC3,4
	SINR
	 ERJMP [SETZ T2,
		RET]
	MOVE T2,[POINT 8,FE.MSG]
	ILDB T3,T2
	CAIE T3,1
	 JRST [MOVE T1,T3
		SETZ T2,
		RET]
	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:	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
		MOVE T1,^D100	;WAIT A WHILE
		HIBER T1,	;SEE HOW LONG IT TAKES
		 RET
		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:	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
	JRST	GTWD2A
;HERE TO GET A WORD FROM CORE IN 10 MEMORY
GETMEM:	MOVE T4,MEMORY
	CAMLE	T1,MEMLIM	;IS IT IN RANGE ?
	JRST	[HRRZ	MA,T1		;ADR WE WANT
		CALL	IOLOAD-1
		JRST	R		;ERROR RETURN
		JRST	GETWD3 ]	;WON
	SKIPE	PDP8F
	JRST	GTMEM8		;GET WORD OF 8 MEMORY
repeat 0,<
	TXNN T1,600000		;IS THE ADDRESS OVER 32K
	TXNN FLG,F.MCB		;ARE WE DOING A LARGE DUMP?
	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:	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
	JRST	R		;ERROR RETURN
	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:	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 TPOPJ
	MOVEI AC2,.MOEOF
	SETO AC3,
	MTOPR
	ERJMP TPOPJ
	CALL GETFEM		;GET RESPONSE
	JRST TPOPJ		;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	R
	LDB	AC3,[POINT 16,FE.MSG+2,31]
	JUMPLE	AC3,GTFEM3	;NO MORE
	LSH AC3,-1		;CONVERT TO WORDS
	MOVN	AC3,AC3
	SIN
	ERJMP	R
GTFEM3:	LDB	T1,[POINT 8,FE.MSG+1,31]
	MOVN	T1,T1		;RETURN STATUS
	ANDI	T1,377
	TRNE	T1,200
	AOS (P)
	RET
;HERE TO DO THE WORK UNDER TOPS-10

GT.F10:	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]
	CALL FE.RPY		;READ THE REPLY
	 RET
	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

;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
	LDB	T1,[POINT 16,FE.MSG+2,35] ;HOW MUCH DATA FOLLOWS?
	RETSKP FAST
;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
	RETSKP FAST

;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	TPOPJ
	IDPB	T1,T4
TPOPJ:	POP	P,T1
	RET
;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			;ERROR RETURN
	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
	RETSKP FAST

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
;HERE TO PUT A BYTE INTO THE CACHE
; CALL	MOVE	T1,<BYTE>
;	MOVE	T2,<ADR>
;	CALL	PUTBCH
;	RETURN

PUTBCH:	PUSH	P,T1
	PUSH	P,T2
	PUSH	P,T3
	PUSH	P,T4
	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
	POP	P,T4
	POP	P,T3
	POP	P,T2
	JRST TPOPJ
;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
	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](T4)		;20F/TOPS-10

PUTMCB:	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
	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
	MOVE AC1,FE.JFN
	MOVE AC2,[POINT 8,FE.MSG]
	ADDI T2,7
	MOVN AC3,T2
	SOUTR
	 ERJMP R
	MOVE AC2,[POINT 8,FE.MSG]
	MOVNI AC3,1
	SINR
	 ERJMP R
	LDB AC1,[POINT 8,FE.MSG,7]
	CAIE AC1,1
	 RET
	JRST GETWD3
;HERE WHEN PUTTING BYTES WITH CAL11. OR CAL78. UUO'S

PUT.C1:	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
		MOVEI T1,^D100	;WAIT A WHILE
		HIBER T1,	;AND SEE
		 RET
		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:	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

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:	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
	JRST	R		;ERROR RETURN
	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:	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]	;ERROR CODE RANDOM
	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			;ERROR, RETURN CODE
	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	R		;BLAT
	MOVEI	AC2,.MOEOF	;FORCE BUFFER OUT
	SETO	AC3,		;BUT DON'T SEND EOF
	MTOPR			;FLOP
	 ERJMP	R
	CALL	GETFEM		;GET REPLY
	 RET
	SKIPE	AC3		;DATA WITH WRITE REPLY?
	 JRST	FE$BLT		;BLAT?
	JRST	GETWD3		;OK, DONE
;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
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
	TXNN	FLG,F.MCB	;IF DUMP IS NOT /MCBDMP,	
	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
>
;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
	TXNN FLG,F.MCB		; LARGE DUMP?  IF NOT...
	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
	CALL	MOVMEM		;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

;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
	SUBTTL	TOPS-20 DN60 CRUFT

; D62EXM - examine a TOPS-20 DN60 front end
;	T1/address to examine
; RETURNS:
;	false - AC1/error code
;	true  - T1/data
;		T2/address examined

D62EXW:	MOVEI	AC1,^D50
	DISMS

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
	SKIPE PVTYP
	JRST D62EX2
	CALL	GETHDR			; Get the response header
	RET
D62EX2:	LDB	T1,D11DT		; get the data
	LDB	T2,D11AD		; get the address back
	RETSKP FAST			; and suc


; 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

D62DEW:	MOVEI	AC1,^D50
	DISMS

D62DEP:	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
	SKIPE PVTYP
	RETSKP SAFE
	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	R			;  Can't talk to FE
	JRST	IOBRK			; Make sure the header gets output.

PUTHD5:	MOVEI AC2,PUTARG
	MOVE AC1,PORT
	ANDI AC1,7
	MOVEM AC1,BT6DTE(AC2)
	MOVEI AC1,6
	HRLM AC1,BT6HDR(T2)
	MOVEI AC1,XMTHDR
	HRRM AC1,BT6HDR(AC2)
	SETZM BT6DBC(AC2)
	SETZM BT6PTR(AC2)
	MOVEI AC1,.BTD60
	BOOT
	ERJMP V5ERR
	RETSKP FAST

V5ERR:	MOVE AC1,PUTARG+BT6ERR
	RET


; 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	R			;  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
	MOVX	AC3,1			; Clear FE buffers w/o doing real EOF
	MTOPR				; Force I/O completion
	ERJMP	R			;  Can't talk to FE
	RETSKP FAST			; The I/O was completed succesfully.

; 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	R			; JSYS failed
	RETSKP FAST			; Sucess in sending data
; 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	R			;  BOOT JSYS failed
	MOVE	AC1,.BTLEN+BTARG 	; Get transfered length/error code
	JUMPE AC1,RDSAVE
	TXNN	AC1,BT%CTL		; Check for control message flag
	RETSKP SAFE
	CAXE	AC1,BT%CTL+.BTCMP	; Transmission complete?
	JRST	R			;  No .. so front end not running
					;  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				;  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				;  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]
					; 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				; error on the way out
	RETSKP	FAST			; it suc'd

; 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
; 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?
	RETSKP	SAFE			;  Yes so assume he is still set up.
	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
	RETSKP	FAST			; 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				;  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
	MOVEI	AC3,1			; OFFSET OF 1
	EXTEND	AC1,[CVTDBO]		; 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
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 AC2,.BTSTS		; READ STATUS FUNCTION
	BOOT				; GET IT....
	ERJMP PRODFL			; FAIL, WE LOSE BIG
	MOVE AC1,PROARG+.BTCOD
	CAIE AC1,.VND60			; DN60 ?
PRODFL:	SETZ AC1,			; NO, WE LOSE BIG
	MOVEM AC1,PVTYP
	RET
;HERE TO CLEAR MEMORY OUT

CLRMEM:	SKIPN	T1,MEMORY	;DID WE READ INTO MEMORY BEFORE ?
	RETSKP SAFE
	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
	RETSKP
; 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

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	2			; Receive header

XMTHDR:: BLOCK	D6HWSZ			; Transmit header

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

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
 P.KS10==1B0				; KS10 - deliberately the sign bit
 P.KL10==1B1				; KL10
 P.KI10==1B2				; KI10
 P.KA10==1B3				; KA10
 P.PDP6==1B4				; PDP-6

PVTYP:	BLOCK 1

PROARG:	BLOCK 2

	END