Google
 

Trailing-Edge - PDP-10 Archives - BB-FP64A-SB_1986 - 10,7/kdpdpy/dupcom.mac
There are 4 other files named dupcom.mac in the archive. Click here to see a list.
	.TITLE	KDUPMC - COMMUNICATION IO PROCESSOR MICROCODE FOR THE DUP11
;
; COPYRIGHT (C)	1978
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. 01754
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE FOR USE ONLY ON
; A SINGLE COMPUTER SYSTEM AND MAY BE COPIED ONLY 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
; EXCEPT FOR USE ON SUCH SYSTEM AND TO ONE WHO AGREES TO
; THESE LICENSE TERMS.  TITLE TO AND OWNERSHIP OF THE
; SOFTWARE SHALL AT ALL TIMES REMAIN IN DEC
;
; THE INFORMATION IN THIS DOCUMENT IS SUBJECT TO CHANGE
; WITHOUT NOTICE AND SHOULD NOT BE CONSTRUED AS A COM-
; MITMENT BY DIGITAL EQUIPMENT CORPORATION.
;
; DEC ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY
; OF ITS SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY
; DEC.
;
; DISTRIBUTED SYSTEMS SOFTWARE ENGINEERING
;
	.SBTTL	TABLE OFFSET DEFINITIONS
	.IDENT	/V1.0A/
;	FILE	DUPEQU.MAC
 
	.NLIST	CND
 
 
BIT0=1
BIT1=2
BIT2=4
BIT3=10
BIT4=20
BIT5=40
BIT6=100
BIT7=200
 
 
; RAM TABLE OFFSETS PER DDCMP/SDLC LINE
 
D.RSTR=0		;TIMER RESTART VALUE
 
D.TIME=D.RSTR+1		;TIMER VALUE
 
D.CSR=D.TIME+1		;CSR ADDRESS (2 BYTES)
 
D.STS=D.CSR+2		;STATUS
	DS.CRI=BIT7		;BIT STUFF CRC INHIBIT
	DS.SLT=BIT7		;DDCMP SELECT ON CURRENT MESSAGE
	DS.QSC=BIT6		;Q-SYNC BIT
	DS.DEC=BIT5		;DEC MODE
	DS.IGN=BIT4		;IGNORE CURRENT MESSAGE
	DS.HDX=BIT3		;HALF DUPLEX LINE
	DS.SEC=BIT2		;SECONDARY STATION
	DS.DSR=BIT1		;LAST STATE OF DATA SET READY
	DS.NUM=BIT0		;RECEIVING NUMBERED MESSAGE
 
D.RPTR=D.STS+1		;RECEIVE STATE POINTER
 
D.SADR=D.RPTR+1		;SECONDARY ADDRESS
 
D.DCC1=D.SADR+1		;DDCMP DATA CHARACTER COUNT(LOW BYTE)
 
D.DCC2=D.DCC1+1		;DDCMP DATA CHARACTER COUNT(HIGH BYTE)
; THE ABOVE TWO BYTES WILL BE USED AS THE LOCAL DELAY BUFFER FOR SDLC.
 
D.SILO=D.DCC1		;TWO CHARACTER SDLC SILO
 
D.RDP=D.DCC2+1		;CURRENT RECEIVE DESCRIPTOR POINTER (3 BYTES)
 
D.ARLP=D.RDP+3		;ALTERNATE LINK POINTER (3 BYTES)
 
D.ORBC=D.ARLP+3		;ORIGINAL RECEIVE BYTE COUNT (2 BYTES)
 
D.ORBA=D.ORBC+2		;ORIGINAL RECEIVE CURRENT BUFFER ADDRESS (3 BYTES)
 
D.RBD=D.ORBA+3		;CURRENT RECEIVE BUFFER DESCRIPTOR(5 BYTES)
 D.RBDC=D.RBD		;CURRENT RECEIVE COUNTER

 D.RBDA=D.RBDC+2	;CURRENT RECEIVE BUFFER ADDRESS
 D.RBDF=D.RBDA+2	;FLAG BIT BYTE
	DR.LST=BIT7		;DESCRIPTOR IS LAST IN LIST 
	DR.ABA=BIT6		;ALTERNATE BUFFER IS ASSIGNED
	DR.CBA=BIT5		;CURRENT BUFFER IS ASSIGNED
	DR.17=BIT3		;RCV ADDRESS BIT 17
	DR.16=BIT2		;RCV ADDRESS BIT 16
	DR.FST=BIT0		;FIRST CHARACTER IN CURRENT BUFFER
 
D.ERC=D.RBD+5		;EVEN RECEIVE CHARACTER
 
D.XDP=D.ERC+1		;CURRENT TRANSMIT DESCRIPTOR POINTER (3 BYTES)
 
D.AXLP=D.XDP+3		;ALTERNATE TRANSMIT LINK POINTER (3 BYTES)
 
D.OXBC=D.AXLP+3		;ORIGINAL TRANSMIT BYTE COUNT (2 BYTES)
 
D.DUMMY=D.OXBC+2	;3 BYTES OF DUMMY DATA
 
D.XBD=D.DUMMY+3		;CURRENT TRANSMIT BUFFER DESCRIPTOR (5 BYTES)
 D.XBDC=D.XBD		;COUNT (LOW BYTE)
 D.XBDA=D.XBDC+2	;ADDRESS (LOW BYTE)
 D.XBDF=D.XBDA+2	;FLAG BITS BYTE
	DX.LST=DR.LST		;DISCRIPTOR IS LAST IN LIST
	DX.ABA=DR.ABA		;ALTERNATE XMT BUFFER ASSIGNED
	DX.CBA=DR.CBA		;CURRENT XMT BUFFER ASSIGNED
	DX.SYN=BIT4		;SEND SYNCS
	DX.17=BIT3				;XMT ADDRESS BIT 17
	DX.16=BIT2				;XMT ADDRESS BIT 16
	DX.EOM=BIT1				;END OF MESSAGE
	DX.SOM=BIT0				;START OF MESSAGE
 
D.OXC=D.XBD+5		;ODD TRANSMIT CHARACTER
 
D.SYNC=D.OXC+1		;TRANSMIT SYNC COUNT
 
D.XSTS=D.SYNC+1		;TRANSMIT STATUS FLAGS
	DT.ABT=BIT0!BIT4  ;TRANSMIT ABORT PENDING
	DT.AB1=BIT1	;TRANSMIT ABORT STAGE 1 PENDING
 
D.LNG=60			;LENGTH OF TABLE
 
; RAM OFFSET PER COMM IOP
 
P.MSTA=2000		;LAST RAM LOCATION + 1
P.SLOT=P.MSTA-1		;COMPLETION SILO NEXT OUT POINTER
P.SLIN=P.SLOT-1		;COMPLETION SILO NEXT IN POINTER
P.PORT=P.SLIN-1		;PORT SERVICE ROUTINE
P.PLST=P.PORT
	SENTRY=6	;SIZE OF A SILO ENTRY
	NMSENT=29.	;NUMBER OF SILO ENTRIES
P.NPR=P.PLST-<SENTRY*NMSENT>	;COMPLETION SILO
	SILOED=P.PLST-SENTRY	;LAST ENTRY IN SILO
P.LADR=P.NPR-<MAXDEV*2>	;TABLE OF LINE TABLE ADDRESSES
;
; SCRATCH PAD DEFINITIONS
;
	SP.CHR=SP7		;LOW BYTE OF DUP'S CSR2 (RECEIVE CHARACTER)
	SP.RST=SP10		;HIGH BYTE OF DUP'S CSR2 (RECEIVE CHARACTER STATUS)
	SP.STS=SP11		;COMM IOP STATUS REGISTER
	SP.LN=SP12		;COMM IOP LINE # CURRENTLY SELECTED
	SP.RM0=SP13		;RAM TABLE ADDRESS FOR CURRENT LINE - BITS 0-7
	SP.RM1=SP14		;RAM TABLE ADDRESS FOR CURRENT LINE - BITS 8&9
	SP.SB1=SP15		;SUBROUTINE RETURN ADDRESS (LEVEL B SUBROUTINES)
	SP.SUB=SP16		;SUBROUTINE RETURN ADDRESS (LEVEL A SUBROUTINES
	SP.CS0=SP17		;IMAGE OF CSR0 (LOW BYTE)


; DUP-11 INTERFACE RELATED EQUATES
;	RECEIVE CONTROL AND STATUS REGISTERS (XX0)
 
;		LOW BYTE
DUPDTR=BIT1		;DATA TERMINAL READY
DUPRTS=BIT2		;REQUEST TO SEND
DUPREN=BIT4		;ENABLE RECEIVER
DUPRDN=BIT7		;RECEIVE DONE
;		HIGH BYTE
DUPSSY=BIT0		;STRIP SYNC
DUPDSR=BIT1		;DATA SET READY
 
 
;RECEIVE DATA BUFFER REGISTER -RXDBUF (XX2)
 
;		HIGH BYTE
DUPRSM=BIT0		;RECEIVE START OF MESSAGE
DUPREM=BIT1		;RECEIVE END OF MESSAGE
DUPRAB=BIT2		;RECEIVE ABORT
DUPCPE=BIT4		;CRC/PARITY ERROR
DUPOVR=BIT6		;OVERUN ERROR
DUPRE=BIT7		;RECEIVE ERROR
 
;PARAMETER CONTROL AND STATUS REGISTER -PARCSR (XX2)
 
;		HIGH BYTE
DUPCRI=BIT1		;CRC INHIBIT
DUPSAM=BIT4		;SECONDARY ADDRESS MODE
DUPDEC=BIT7		;DEC MODE
 
;TRANSMIT CONTROL AND STAUS REGISTER-TXCSR (XX4)
;		LOW BYTE
DUPHDX=BIT3		;HALF DUPLEX MODE
DUPSND=BIT4		;SEND
DUPTXD=BIT7		;TRANSMIT DONE
 
;		HIGH BYTE
DUPDR=BIT0			;DEVICE RESET
 
;TRANSMIT DATA BUFFER REGISTER - TXDBUF (XX6)
 
;		HIGH BYTE
DUPTSM=BIT0		;TRANSMIT START OF MESSAGE
DUPTEM=BIT1		;TRANSMIT END OF MESSAGE
DUPTAB=BIT2		;TRANSMIT ABORT
 
 
;NPR CONTROL EQUATES
 
DATO=021			;WORD OUT NPR
DATOB=221			;BYTE OUT NPR
HLDBUS=002			;HOLD BUS
 
 
;DDCMP EQUATES
 
SOH=201			;START OF HEADER-NUMBERED MESSAGE
ENQ=005			;ENQUIRY
DLE=220			;DELETE-MAINTAINANCE MESSAGE
SYNC=226		;SYNC CHARACTER
 
SYNCNT=7		;NUMBER OF SYNC'S TO TRANSMIT
 
 
 
;CONTROL/BUFFER ADDRESS OUT PARAMETERS
 
C.BAOX=200		;BA OUT FOR TRANSMIT OPERATION
C.BAOR=204		;BA OUT FOR RECEIVE OPERATION
C.CLOX=201		;CONTROL OUT  FOR TRANSMIT OPERATION
C.CLOR=205		;CONTROL OUT FOR RECEIVE OPERATION
 
EOM=20			;END OF MESSAGE
 
;ERROR CODES
 
ER.ABO=6		;RECEIVE ABORT (BIT STUFF)
ER.HBC=10		;DDCMP HEADER BCC ERROR
ER.CRC=12		;RECEIVE CRC ERROR
ER.NBA=14		;NO BUFFER AVAILABLE (RECEIVE)
ER.DSR=16		;DATA SET READY TRANSITION
ER.NXM=20		;NON-EXISTENT MEMORY
ER.UNR=22		;TRANSMIT UNDERRUN
ER.OVR=24		;RECEIVE OVERRUN
ER.KIL=26		;USER KILL
 
 
	MAXDEV=16.	;MAXIMUM NUMBER OF DUP'S GEN'ED FOR
	.PAGE
	.SBTTL	INIT - INITIALIZATION
;	FILE	IDLE.DUP

;+
; **INIT-INITIALIZATION ROUTINE**
;
; INPUTS:
;	BRG = 0 (MASTER CLEAR)
;	MAR = 0 (MASTER CLEAR)
; OUTPUTS:
;	RAM IS CLEARED EXCEPT FOR THE COUNTERS IN THE POLLING LIST
;	WHICH ARE SET TO MINUS ONE TO INDICATE NO ACTIVE DEVICES.
;	THE ADDRESSES OF EACH LINE TABLE IS PUT IN A TABLE AT P.LADR
;	THE CSR'S ARE ALSO CLEARED
;-

$KDPMC::			;START OF CODE GLOBAL LABEL

INIT:	OUT	BR,SELB,OINCON	;ZERO THE INPUT CONTROL CSR
	OUT	BR,SELB,OOCON	;ZERO THE OUTPUT CONTROL CSR
	SP	BR,SELB,SP.RM1	;CLEAR OUT RAM ADDRESS HIGH SCRATCH PAD
	SP	BR,SELB,SP.RM0	;CLEAR LOW BYTE OF ADDRESS
	SP	BR,SELB,SP4	;ZERO SP4
10$:	MEMINC	IMM,0		;ZERO THE NEXT MEMORY LOCATION
	SPBR	IBUS,NPR,SP0	;READ THE NPR CONTROL REGISTER
	BRWRTE	BR,ADD,SP0	;SHIFT IT LEFT
	BR7	20$		;OVERFLOWED MAR TO 10 BITS - ALL DONE
	ALWAYS	10$		;KEEP ZEROING RAM
 
; MAR = 0 FROM OVERFLOW
 
20$:
	BRWRTE	IMM,MAXDEV*2	;MAXIMUM NUMBER OF DEVICES GENED FOR TIMES 2
	SP	BR,SELB,SP5	;SAVE IT IN A SCRATCH PAD
INIT1:
	BRWRTE	TWOA,SP4,INCMAR	;GET CURRENT LINE TIMES 2
	SP	BR,SELB,SP0		;SAVE IT IN SP0
	COMP	BR,SP5		;ARE WE FINISHED WITH ALL LINES
	Z	40$		;ALL DONE
	SP	INCA,SP4	;ONE MORE LINE INITIALIZED
	MEM	IMM,377		;INITIALIZE POLLING COUNTER TO MINUS ONE
	BRWRTE	IMM,P.LADR,LDMAPG	;LOAD THE BRG WITH THE ADDRESS OF
				;THE LINE TABLE ADDRESS TABLE AND SET THE
				;MAR HI TO THAT ADDRESS
	LDMA	BR,ADD,SP0	;POINT TO THIS LINES ENTRY IN THE TABLE
	MEMINC	SELA,SP.RM0	;SAVE THE LINE TABLE ADDRESS
	MEM	SELA,SP.RM1	;LOW AND HI
	ALWAYS	NXTTBL		;"CALL" ROUTINE TO CALCULATE ADDRESS OF
				;NEXT LINE'S TABLE (OFFSET BY D.TIME)
				;RETURN MADE TO INIT1 WITH MAR&SP.RM0,1 SET
40$:	LDMAP	IMM,P.PORT	;LOAD MAR HIGH WITH ADDRESS OF PORT STATUS BYTE
	LDMA	IMM,P.PORT	;LOAD MAR LOW
	MEMADR	RDOSET,INCMAR	;ADDRESS OF ROUTINE TO CHECK FOR OUTPUT COMPLETIONS
	MEMINC	IMM,P.NPR	;INITIALIZE COMPLETION SILO IN POINTER
	MEM	IMM,377		;INITIALIZE COMPLETION SILO OUT POINTER (LOGICAL ZERO)
				;FALL INTO IDLE LOOP
	.SBTTL	IDLE - IDLE LOOP

;+
; **IDLE-LOOP BETWEEN PORT AND DEVICE SERVICE
;
; INPUTS:
;	P.PORT = ADDRESS OF NEXT PORT SERVICE ROUTINE
;
; OUTPUTS:
;	IF THE PGMCLK BIT IN THE MISC REG HAS EXPIRED,
;	THE DEVICES ARE POLLED AND SERVICED BY THE TIMER ROUTINE
;	IN ANY CASE, THE NEXT PORT ROUTINE IS BRANCHED TO.
;
;	MAR  = P.PORT
;	ALL PORT ROUTINES RETURN TO IDLE
;-

IDLE:	SPBR	IBUS,UBBR,SP0	;READ THE BUS REQUEST REGISTER AND
				;STORE THE IMAGE IN SP0 AND THE BRG
	BR4	TIMER		;BRANCH IF THE TIMER HAS EXPIRED
IDLE1:	LDMA	IMM,P.PORT	;LOAD MAR TO POINT TO PORT STATUS
	LDMAP	IMM,P.PORT	;LOAD MAR HIGH
	.ALWAY	MEMX,SELB,0	;TIMER HAS NOT EXPIRED YET, CHECK THE
				;DATA PORT TO SEE IF ANY PROCESSING IS REQUIRED
				;RAM CONTAINS THE ADDRESS OF THE APPROPRIATE
				;SERVICE ROUTINE
				; RQISET --> WAITING FOR RQI TO SET
				; RDICLR --> WAITING FOR RDYI TO CLEAR
				; RDOSET --> WAITING FOR A COMPLETION
				; RDOCLR --> WAITING FOR RDYO TO CLEAR
	.SBTTL	DATA PORT PROCESSING ROUTINES
;+
; **RDOCLR-WAITING FOR READY OUT TO BE CLEARED BY THE PDP-11**
;
; INPUTS:
;	MAR = PORT SERVICE ROUTINE (P.PORT)
; OUTPUTS:
;	THIS ROUTINE WAITS FOR READY OUT TO BE CLEARED BY THE PDP-11
;	THUS SIGNALING IT IS DONE.  IT ALSO CHECKS IF OUTPUT INTERRUPTS
;	ARE REQUESTED IN THE MEANTIME AND WILL GENERATE ONE IF THEY WERE
;	NOT REQUESTED WHEN RDYO WAS SET.
;
;	WHEN RDYO IS CLEARED, CONTROL IS PASSED TO RQISET TO CHECK
;	FOR PENDING PORT REQUESTS
;
;	NOTE: THERE EXISTS THE POSSIBILITY OF AN INTERRUPT BEING GENERATED
;	IF IEO IS CLEARED AT ANY TIME AFTER IT IS TESTED BY THE MICROPROCESSOR
;	(APPROX A 1.5US WINDOW)
;-

RDOCLR:
	BRWRTE	IBUS,OCON		;READ CONTROL CSR BSEL2
	BR7	RDOST1			;READY OUT STILL SET, CHECK INTERRUPTS
;
; ENTER HERE IF AN OUTPUT INTERRUPT HAS ALREADY BEEN GENERATED
;
RDOCL1:
	BRWRTE	IBUS,OCON		;READ OUTPUT CONTROL CSR
	BR7	IDLE			;READY OUT STILL SET
	BRWRTE	IMM,0			;CLEAR OUTPT CONTROL CSR
	OUT	BR,SELB,OOCON		;..
	MEMADR	RQISET			;LOOK FOR RQI NEXT
	ALWAYS	IDLE			;BACK TO IDLE LOOP
;+
; **RDOSET-MICROPROCESSOR COMPLETION POSTING**
;
; INPUTS:
;	MAR = PORT SERVICE ROUTINE (P.PORT)
; OUTPUTS:
;	CHECK THE COMPLETION SILO TO SEE IF ANY COMPLETIONS ARE PENDING.
;	IF THERE ARE POST THE COMPLETION TO THE PDP-11 
;	SILO POINTERS (P.SLOT,P.SLIN) ARE UPDATED
;	AND WAIT FOR RDYO TO CLEAR (RDOCLR)
;	OTHERWISE CHECK TO SEE IF THE PDP-11 HAS ANY INPUT DATA (RQISET)
;-

RDOSET:
	MEMADR	RQISET			;LOOK FOR RQI NEXT
	LDMA	IMM,P.SLOT	;SET MAR TO COMPLETION SILO NEXT OUT POINTER
	LDMA	MEMX,SELB	;POINT COMPLETION TO NEXT OUT ENTRY
	Z	IDLE		;THE POINTER IS ZERO THEREFORE THE SILO IS EMPTY
 
; A COMPLETION OUTPUT IS PENDING IN THE COMPLETION SILO. MAR POINTS TO THE
; NEXT ENTRY
	OUT	MEMI,SELB,OLINEN ;WRITE THE LINE NUMBER BYTE
 
; READ THE SECOND WORD OF THE COMPLETION SILO AND SET UP CSR 4
 
	OUT	MEMI,SELB,OPORT1 ;WRITE PORT BYTE 1
	OUT	MEMI,SELB,OPORT2 ;AND PORT BYTE 2
 
; READ THE THIRD WORD OF THE COMPLETION SILO AND SET UP CSR 6
 
	OUT	MEMI,SELB,OPORT3 ;WRITE PORT BYTE 3
	OUT	MEMI,SELB,OPORT4 ;AND PORT BYTE 4
 
	OUT	MEMI,SELB,OOCON	;WRITE THE NEW OUTPUT CNTRL CSR
 
; INCREMENT THE SILO NEXT OUT POINTER
 
	LDMA	IMM,P.SLIN	;SET MAR TO POINT TO COMPLETION SILO NEXT IN OFFSET
	SP	MEMI,SELB,SP1	;SAVE THE NEXT IN POINTER IN SP1
	SP	MEMX,SELB,SP0	;SAVE THE NEXT OUT POINTER IN SP0
	MEM	IMM,P.NPR	;ASSUME THE SILO IS GOING TO WRAP AROUND
	BRWRTE	IMM,SILOED	;OFFSET TO LAST SILO ENTRY
	COMP	BR,SP0		;COMPARE CURRENT OUT POINTER WITH END OF SILO
	Z	50$		;IT WRAPPED AROUND - ALREADY SET UP
	BRWRTE	IMM,SENTRY	;GET THE SIZE OF A SILO ENTRY
	MEM	BR,ADD,SP0	;INCREMENT NEXT OUT POINTER AND SAVE IT
 
; IF SILO IS NOW EMPTY "ZERO" THE NEXT OUT POINTER
 
50$:	COMP	MEMX,SP1		;COMPARE OUT POINTER TO IN POINTER
	Z	70$		;THEY ARE THE SAME
	ALWAYS	80$		;THEY ARE DIFFERENT
70$:	MEM	IMM,377		;THE SILO IS EMPTY - SET NEXT OUT POINTER
				;TO A LOGICAL ZERO (-1)
80$:	LDMA	IMM,P.PORT	;SET MAR TO POINT TO PORT STATUS
RDOST1:
	SPBR	IBUS,INCON,SP0		;READ INPUT CONTROL CSR
	BR4	RDOST2			;OUTPUT INTERRUPT REQUESTED
	MEMADR	RDOCLR			;STATE TO WAITING FOR READY OUT CLEARING
	ALWAYS	IDLE			;BACK TO IDLE LOOP

RDOST2:	MEMADR	RDOCL1			;STATE TO WAITING FOR READY OUT CLEARING
	BRWRTE	IMM,300			;MASK FOR BUS REQUEST AND XX4
RDOST3:	OUT	BR,SELB,OBR		;GENERATE AN INTERRUPT
	ALWAYS	IDLE			;BACK TO IDLE LOOP
 
;+
; **RQISET-REQUEST IN SET, THE PDP-11 HAS REQUESTED THE DATA PORTS
;
; INPUTS:
;	MAR = PORT SERVICE ROUTINE (P.PORT) 
; OUTPUTS:
;	CHECK TO SEE IF REQUEST IN HAS BEEN SET BY THE PDP-11. IF SO,
;	SET READY IN AND LET THE PDP-11 SET UP A COMMAND IN THE DATA PORTS
;	IF INPUT INTERRUPTS ARE REQUESTED, GENERATE ONE
;	TRANSFER CONTROL TO RDICLR TO WAIT UNTIL THE PDP-11 IS DONE
;-

RQISET:	BRWRTE	IBUS,INCON		;READ INPUT CONTROL CSR
	BR7	10$			;REQUEST IN SET
	ALWAYS	RDOSET			;SEE IF ANY COMPLETIONS TO POST

10$:	SP	IMM,20,SP0		;MASK TO SET READY IN
	OUT	SELA,OOCON		;SET IN OUPUT CONTROL CSR
	BR0	RQIST1			;INTERRUPT ENABLE IS SET
	MEMADR	RDICLR			;STATE TO WAITING FOR RDYI TO CLEAR
	ALWAYS	IDLE			;BACK TO IDLE LOOP

RQIST1:	MEMADR	RDICL1			;STATE TO WAITING FOR RDYI TO CLEAR
	BRWRTE	IMM,200			;MASK FOR BUS REQUEST AND XX0
	ALWAYS	RDOST3			;GENERATE AN INTERRUPT
;+
; **RDICLR-WAIT FOR READY IN TO CLEAR (DATA PORTS HAVE BEEN SET UP)**
;
; INPUTS:
;	MAR = PORT SERVICE ROUTINE (P.PORT)
; OUTPUTS:
;	CHECK TO SEE IF THE PDP-11 HAS CLEARED READY IN SIGNIFYING
;	THAT IT HAS SET UP THE DATA PORTS.  IF SO THEN DISPATCH TO THE
;	PROPER ROUTINE TO HANDLE THE REQUEST BASED ON
;	BIT 0&1 OF THE  CONTROL CSR BSEL2
;-
 
; RDYI CLEAR ROUTINE IS ENTERED HERE IF INTERRUPT ENABLE WAS NOT
; SET WHEN THE COMMIOP SET READY IN. IF IN THE  MEANTIME INTERRUPT ENABLE
; WAS SET, IT WILL BE SEEN HERE AND AN INTERRUPT WILL BE GENERATED
 
	.ENABL	LSB
RDICLR:
	BRWRTE	IBUS,OCON		;READ OUTPUT CONTROL CSR
	BR4	5$			;READY IN STILL SET
	ALWAYS	10$			;PDP-11 CLEARED RDYI. DONT BOTHER
					;CHECKING FOR IEI JUST PROCESS THE DATA
5$:	BRWRTE	IBUS,INCON		;READ CONTROL CSR
	BR0	RQIST1			;INTERRUPT REQUESTED
RDICL1:
	BRWRTE	IBUS,OCON		;READ OUTPUT CONTROL CSR
	BR4	IDLE			;RDYI STILL SET
10$:	MEMADR	RDOSET			;STATE TO WAIT FOR COMPLETIONS
 
; READY IN CLEAR
 
	BRWRTE	IMM,P.LADR	;GET ADDRESS OF LINE TABLE ADDR TABLE
	SP	BR,SELB,SP5	;SAVE IT IN SP5
	SP	IBUS,LINENM,SP.LN	;READ THE LINE NUMBER
	BRWRTE	BR,TWOA,SP.LN	;MULTIPY IT BY TWO
	LDMA	BR,ADD,SP5	;POINT TO ENTRY IN TABLE FOR THIS LINE
	SP	MEMI,SELB,SP.RM0	;GET THE ADDRESS OF THIS LINE'S TABLE
				;(LOW) AND SAVE IT IN SP.RM0
	SP	MEMX,SELB,SP.RM1,LDMAPG	;GET THE ADDRESS (HIGH) AND POINT
				;THE MAR HI TO THIS ADDRESS
	LDMA	SELA,SP.RM0	;SET MAR LOW
15$:
	BRWRTE	IMM,14,INCMAR	;SET UP DUP CSR BY SETTING ADDR BITS 16-17
	OUT	BR,SELB,OBR,INCMAR ;WRITE EXTENDED MEM BITS FOR OUT NPR
	OUTPUT	MEMI,SELB,OBA1	;WRITE OUT LOW BYTE OF CSR ADDRESS
	OUTPUT	MEMI,SELB,OBA2	;WRITE OUT HIGH BYTE
	LDMA	SELA,SP.RM0	;POINT BACK TO START OF LINE TABLE

				;REGISTERS FOR COMMAND ROUTINES
				; MAR=LINE TABLE  SP.LN=LINE NUMBER
				; SP.RM0,1=LINE TABLE ADDR
				; NPR OUTPUT ADDR=DEVICE CSR 0

	BRWRTE	IBUS,OCON	;GET ORIGINAL IMAGE OF INPUT CONTROL CSR
				;READ FROM BSEL2 TO AVOID RAM BIT SET PROBLEM
				;BY THIS TIME ALL BITS WILL HAVE SETTLED
	BR1	20$		;BIT 1 SET
	BR0	CONIN		;BIT 1=0 AND BIT 0=1 -> CONTROL IN REQUEST
	ALWAYS	BAIN		;BIT 0&1=0 -> BUFFER ADDRESS IN REQUEST
20$:	BR0	BASEIN		;BIT 1=1 BIT 0=1 -> BASE IN REQUEST
				;BIT 1=1 BIT 0=0 -> ILLEGAL REQUEST
	.DSABL	LSB
 
; ABOVE THREE ROUTINES RETURN HERE AFTER REQUEST HAS BEEN PROCESSED
 
RQICL2:	BRWRTE	IMM,0		;CLEAR OUT CONTROL CSR
	OUT	BR,SELB,OOCON	;..
	SPBR	IBUS,UBBR,SP0	;READ THE MISC REGISTER
	BR0	NXMERR		;IF BIT 0 SET, THEN A NON-EXISTENT MEMORY
				;ERROR OCCURRED, REPORT IT.
	ALWAYS	IDLE		;OTHERWISE, BACK TO IDLE LOOP
	.SBTTL	TIMER - TIMER SERVICE
;+
; **TIMER-TIMER SERVICE ROUTINE**
;
; INPUTS:
;	BRG & SP0 = IMAGE OF BUS REQUEST REGISTER
;
; OUTPUTS:
;	EACH DEVICES TIMER COUNTER IS DECREMENTED AND TESTED FOR
;	AN EXPIRATION.  IF THE COUNTER WENT TO ZERO THE DEVICE
;	IS POLLED TO SEE IF IT HAS A TRANSMIT DONE OR A RECEIVE DONE
;	AND IF SO IT IS SERVICED.  IF NONE OF THE DEVICES REQUIRES
;	SERVICING THE MODEM TIMER IS DECREMENTED AND IF IT EXPIRED
;	MODEM CHANGES ARE CHECKED.
;	WHEN A DEVICE DONE SERVICE ROUTINE IS FINISHED THIS ROUTINE
;	CONTINUES WITH THE NEXT DEVICE.
;-
	.ENABL	LSB
TIMER:	BRWRTE	IMM,121		;MASK TO CLEAR ALL BUT TIMER, XX4 AND NXM
				;N.B. THE TIMER WILL ALREADY BE SET TO ONE
				;FROM IT EXPIRING SO THE MASK IS GUARANTEED
				;TO LEAVE IT A ONE FOR RESETTING
	OUT	BR,AANDB,OBR	;AND THE MASK WITH THE PREVIOUS CONTENTS OF
				;THE BUS REQUEST REGISTER RESETING THE
				;TIMER
	BRWRTE	IMM,0		;ZERO THE BRG
	SP	BR,SELB,SP.LN	;START WITH LINE ZERO
	SP	BR,SELB,SP.RM0,LDMAR	;SAVE THE ADDRESS IN RAM ADDRESS SCRATCH PAD
	SP	BR,SELB,SP.RM1,LDMAPG	;INITIALIZE SCRATCH PAD WITH THE HIGH BITS
	ALWAYS	TIMRT1		;START POLLING
 
 
; MAIN POLLING LOOP
; RECEIVE DONE  ROUTINES RETURN HERE

TIMRTN:
 
10$:
	SPBR	IBUS,UBBR,SP0	;READ THE MISC.  REGISTER
	BR0	NXMERR		;NXM ERROR OCCURRED DURING LAST POLL
	SP	BR,INCA,SP.LN	;ONE LESS DEVICE TO POLL
	BRWRTE	IMM,MAXDEV	;CHECK TO SEE IF LAST DEVICE
	COMP	BR,SP.LN	;HAS BEEN POLLED
	Z	IDLE1		;ALL DONE - BACK TO IDLE LOOP
	BRWRTE	IMM,P.LADR,LDMAPG	;GET STARTING ADDRESS FOR TABLE
				;OF LINE TABLE ADDRESSES AND SET MAR HI
	SP	BR,SELB,SP0	;SAVE IT IN SP0
	BRWRTE	BR,TWOA,SP.LN	;MAKE LINE NUMBER A DOUBLE BYTE INDEX
	LDMA	BR,ADD,SP0	;SET ADDRESS FOR ENTRY OF THIS LINE
	SP	MEMI,SELB,SP.RM0	;SAVE ADDRESS FOR THIS LINE
	SP	MEMX,SELB,SP.RM1,LDMAPG	;HIGH 2 BITS AND LOAD MAR HI
	LDMA	BR,SELA,SP.RM0	;LOAD MAR LOW
TIMRT1:
	BRWRTE	MEMI,SELB	;SAVE THE RESTART VALUE IN THE BRG
				;AND INCREMENT THE MAR
				;IN CASE THE TIMER EXPIRED
	SP	MEMX,SELB,SP0	;READ THE COUNTER FOR THIS DEVICE
	Z	10$		;THE DEVICE IS NOT ACTIVE
	MEM	BR,DECA,SP0	;DECREMENT THE COUNTER AND WRITE IT
				;BACK TO MEMORY
	C	10$		;LOOK AT THE NEXT DEVICE'S COUNTER

; TIMER HAS EXPIRED - SEE IF THERE ARE ANY "DONES" PENDING
; INPUTS:
;	BRG = RESET VALUE

30$:	MEMINC	BR,SELB		;RESET THE COUNTER TO THE INITIAL VALUE
	OUTPUT	MEMI,SELB,IBA1 ;STORE THE LOW BYTE OF THE DEVICES
				;CSR INTO THE LOW BYTE OF THE INPUT BUFFER
				;ADDRESS REGISTER
	OUTPUT	MEMI,SELB,IBA2 ;DO THE SAME WITH THE HIGH BYTE
				;AND INCRMENT THE MAR TO STATUS BYTE
	BRWRTE	IMM,14!DATI		;MASK TO SET EXTENDED MEMORY BITS
				; DO AN INPUT NPR
	OUT	BR,SELB,ONPR	;START THE NPR
	SP	MEMX,SELB,SP.STS	;SAVE THE STATUS BYTE IN SP.STS
40$:	BRWRTE	IBUS,NPR	;READ THE NPR REQUEST REGISTER
	BR0	40$		;WAIT FOR THE NPR TO COMPLETE
	SPBR	IBUS,INDAT2,SP1	;READ THE HIGH BYTE OF CSR 0
				;SAVE IT IN SP1 FOR XMTDON
	BRWRTE	BR,AXORB,SP.STS	;SEE IF ANY CHANGE IN THE DSR STATE
	BR1	DSRCHG		;DATA SET READY HAS CHANGED STATES
	SP	IBUS,IIBA1,SP0		;READ LOW BYTE OF CSR0'S ADDRESS
	SPBR	IBUS,INDAT1,SP.CS0	;READ THE LOW BYTE OF THE DEVICES CSR
	BR7	60$			;RECEIVE DONE SET
;
; SEE IF TRANSMIT DONE SET
;
45$:	BRSHFT			;SHIFT THE CSR IMAGE
	BR1	XMTDON		;REQUEST TO SEND SET
;
; RETURN HERE AFTER FINISHED PROCESSING THE TRANSMITTER
;
TIMRT3:
50$:
	BRWRTE	BR,SELA,SP.CS0	;RE-READ IMAGE OF CSR0
	BR7	RCVDON		;RECEIVE DONE WAS SET
	ALWAYS	10$		;NOT SET - RETURN
;
; RECEIVE DONE FOUND SET
;
60$:
	BRWRTE	IMM,2		;PREPARE TO ADD TWO TO THIS ADDRESS
 
	OUTPUT	BR,ADD,IBA1	;ADD TWO TO THE ADDRESS IN SP0 GETTING THE ADDRESS
				; OF CSR2 WHICH CONTAINS THE RECEIVE
				;CHARACTER IN THE LOW BYTE AND THE
				;STATUS IN THE HIGH BYTE
	BRWRTE	IMM,14!DATI		;MASK TO SET EXTENDED MEMORY BITS
				;AND TO START THE NPR
	OUT	BR,SELB,ONPR	;START THE NPR TO READ CSR2
70$:	BRWRTE	IBUS,NPR	;READ THE NPR STATUS REGISTER
	BR0	70$		;NPR IS NOT DONE YET
	SP	IBUS,INDAT1,SP.CHR	;SAVE THE CHARACTER IN A SCRATCH PAD
	SP	IBUS,INDAT2,SP.RST	;SAVE THE CHARACTER'S STATUS
	BRWRTE	BR,SELA,SP.CS0		;RESTORE THE BRG FOR XMIT DONE TESTING
	ALWAYS	45$			;SEE IF ANY XMIT DONES
 
					;UPON TRANSFER TO XMTDON OR RCVDON
				;THE FOLLOWING LOCATIONS HAVE BEEN SET UP
				;FOR ENTRY TO THE "DONE" PROCESSOR:
				; SP.RM1 -> BITS 8&9 OF RAM TABLE ADDRESS
				; SP.RM0 -> BITS 0-7 OF RAM TABLE ADDRESS
				; MAR --> STATUS (D.STS) IN LINE TABLE
				; SP.LN --> LINE NUMBER
				; SP.CS0 --> IMAGE OF LOW BYTE OF CSR 0
				; SP.STS --> IMAGE OF D.STS
				; SP0 --> LOW BYTE OF CSR 0 ADDRESS
				; SP1 --> HIGH BYTE OF CONTENTS OF CSR 0
				; NPR INPUT ADDR -> DEVICE CSR 0
				;IF RECV DONE, 
				; SP.CHR --> RECEIVED CHARACTER
				; SP.RST --> RCV CHAR STATUS (CSR2 MSB)
	.DSABL	LSB
;%	FILE	DUPUSER.MAC

;INDIRECT RETURNS THROUGH PAGE ZERO
 
;******FOLLOWING INSTRUCTIONS MUST RESIDE IN MICRO PAGE ZERO******
 
 
;RETURN FROM INCOUT DUE TO A CALL FROM BOUT ROUTINE
BOUTR0:	ALWAYS	QPDATA	;GO TO QPDATA ON RETURN
 
 
;RETURN FROM INCOUT DUE TO A CALL FROM XMTSND
XMTEM0:	ALWAYS	XMTBC0


;RETURN FROM LSILO DUE TO A CALL FROM RB3
RB3P0:	ALWAYS	STORE	;GO TO STORE ROUTINE ON RETURN
	.SBTTL	BASEIN-BASE IN SERVICE ROUTINE
 
;+
;
;			B A S E  I N
;
;
;
;CALLED BY:	RDICLR
;
;INPUTS:
;	KMC BSEL3		=LINE NUMBER
;	KMC SEL6 <3:12>		=CSR ADDR FOR CURRENT DUP
;	SP.RM0,SP.RM1		=LINE TABLE ADDRESSES
;	MAR 			=LINE TABLE 
;OUTPUTS:
;	DUP CSR ADDR IS SAVED IN THE LINE TABLE (D.CSR)
;	DUP IS RESET
;-
 
BASEIN:
;SAVE CURRENT DUP CSR ADDR IN RAM
 
	SP	IBUS,PORT3,SP0,INCMAR	;GET CSR ADDR INTO SP0
	BRWRTE	IMM,370,INCMAR		;MASK TO STRIP 3 LSB'S OF CSR ADDR
	MEM	BR,AANDB,SP0	;STRIP THEM AND STORE IN RAM
	OUTPUT	MEMI,SELB,OBA1	;SAVE CSR IN OUT ADDRESS REGISTERS
	SP	IBUS,PORT4,SP0	;GET HIGH BYTE INTO SP0
	BRWRTE	IMM,340		;MASK TO SET 3 MSB'S
	MEM	BR,AORB,SP0	;SAVE IT IN RAM WITH 3 HIGH BITS SET TO ONES
	OUTPUT	MEMX,SELB,OBA2	;SAVE HIGH BYTE OF CSR ADDRESS
 
BASEI1:
;DEVICE RESET THE DUP
 
	BRWRTE	IMM,DUPDR	;SET PROPER BIT (BIT 0) IN OUTDATA HB
	OUTPUT	BR,SELB,OUTDA2
	CALLSR	SP.SUB,INCOB,RQICL2,5	;DO THE NPR TO MASTER CLEAR THE DUP
				;AND RETURN TO CLEAR READY IN
; RESET IS A 2 MICRO-SECOND ONE SHOT.IT IS ASSUMED THAT BEFORE THE DUP
;IS ACCESSED AGAIN, THIS PERIOD WILL HAVE ELAPSED.
	.SBTTL	CONIN-CONTROL IN PROCESS ROUTINE
 
;+
;
;			C O N T R O L  I N
;
;
;
;CALLED BY:	RDICLR
;
;INPUTS:
;	BSEL4 (PORT1)	=POLLING COUNT
;	BSEL6 (PORT3)	=SECONDARY ADDRESS
;	BSEL7 (PORT4)	=CONTROL FLAGS
;	SP.RM0,SP.RM1	=LINE TABLE ADDRESS
;	MAR		=LINE TABLE ADDRESS
;	OUT BA		=DUP'S CSR 0
;OUTPUTS:
;	VARIOUS LINE TABLE LOCATIONS AND DUP FUNCTIONS ARE INITIALIZED ACCORDING TO
;	THE CONTROL IN PARAMETERS.THESE INCLUDE:
;		DUP CSR XX0-STRIP SYNC FOR DEC MODE
;		DUP CSR XX2-DEC MODE&SYNC CHARACTER FOR DDCMP OR SEC MODE,
;		  SEC ADDRESS FOR BITSTUFF MODE
;		DUP CSR XX4-HALFDUPLEX
;-
 
CONIN:
	BRWRTE	IBUS,PORT4	;READ BSEL 7
	BR0	10$		;ENABLE LINE IS SET
	SPBR	IMM,0,SP0,INCMAR	;CLEAR SP0
	MEMINC	DECA,SP0	;WRITE A 377 TO D.TIME DISABLING THIS LINE
	ALWAYS	20$
 
10$:	MEMINC	IBUS,PORT1	;SET TIMER RESTART VALUE
	MEMINC	IBUS,PORT1	;AND TIMER ENABLING THE LINE
	BRWRTE	IMM,DUPDTR!DUPREN	;VALUE TO SET  DTR AND RECEIVE ENABLE
 
; BRG = DUPDTR!DUPREN IF ENABLE WAS REQUEST OR 0 IF DISABLE
 
20$:	OUTPUT	BR,SELB,OUTDA1,INCMAR	;VALUE TO SET OR CLEAR DTR,RCV ENABLE
	BRWRTE	IBUS,PORT4,INCMAR	;REREAD BSEL7
					;MAR = D.STS
	MEM	IMM,DUPSSY	;ASSUME DEC MODE BY STORING STRIP SYNC
				;BIT TEMPORARILY IN MEMORY
	BR7	30$		;IT IS DEC MODE
	MEM	IMM,0		;BIT STUFF MODE - DON'T SET STRIP SYNC
30$:	OUTPUT	MEMX,SELB,OUTDA2	;STORE STRIP SYNC SETTING
	BRWRTE	IMM,DATO	;DO AN OUTPUT NPR 
	OUT	BR,SELB,ONPR	;REQUEST THE NPR
40$:	BRWRTE	IBUS,NPR	;SEE IF NPR DONE YET
	BR0	40$		;WAIT FOR IT
 
CONIN2:
	SPBR	IBUS,PORT4,SP0	;REREAD BSEL7
	BR7	10$		;DEC MODE?
; LOAD SYNC CHARACTER/SECONDARY ADDRESS INTI XX2 LOW BYTE
 
	OUTPUT	IBUS,PORT3,OUTDA1 ;NO,SO LOAD SEC ADDRESS FIELD
	MEM	IMM,DS.CRI	;ASSUME CRC INHIBIT
	BR1	5$		;BRANCH IF IT IS CRC INHIBIT
	MEM	IMM,0		;CLEAR D.STS
5$:	BRWRTE	IMM,DUPSAM!DUPCRI ;SET SECONDARY ADDRESS MODE,CRC INHIBIT
	ALWAYS	20$
; UPDATE XX3
10$:
	MEM	IMM,SYNC	;MOVE SYNC CHARACTER TO MEMORY IN ORDER
				;TO SAVE THE BRG
	OUTPUT	MEMX,SELB,OUTDA1 ;MOVE IT TO OUT DATA REGISTER
	MEM	IMM,DS.SEC!DS.DEC	;ASSUME DEC AND SEC MODE
	BR4	15$			;BRANCH IF SEC MODE
	MEM	IMM,DS.DEC		;NO,JUST DEC MODE
15$:	BRWRTE	IMM,DUPDEC	 ;ISOLATE DEC MODE,CRC INHIBIT
;NOTE: DUP SOULD NOT BE SET TO SECONDARY ADDRESS MODE WHILE IN DEC MODE.THIS
;WILL INHIBIT RECEIVE DONES.
20$:
	OUTPUT	BR,AANDB,OUTDA2 	;MODE CRC INHIBIT&AND LOAD INTO OUTADA2
	CALLSB	SP.SUB,IC2OUT		;WRITE IT OUT TO XX3,XX2
; UPDATE DUP XX5,XX4
 
CONIN3:
	BRWRTE	IBUS,PORT4
	BRSHFT
	BR4	30$			;HALF DUPLEX MODE
;FULL DUPLEX MODE,CLEAR XX4
 
	BRWRTE	IMM,0
	ALWAYS 	40$
 
;HALF DUPLEX MODE, SET HALF DUPLEX BIT IN XX4
 
30$:
	.IIF NE	DS.HDX-DUPHDX	.ERROR DS.HDX ;DS.HDX NO LONGER EQUALS DUPHDX
	BRWRTE	IMM,DUPHDX	;HALF DUPLEX MASK (SAME AS DX.HDX)
	SP	BR,SELB,SP0	;SAVE IT IN SP0
	MEM	MEMX,AORB,SP0	;SET HALF DUPLEX IN D.STS
40$:
 
	OUTPUT	BR,SELB,OUTDA1,INCMAR	;WRITE HALF DUPLEX MASK
				;MAR = D.RPTR (RECV STATE POINTER)
 
; SET RECEIVE STATE POINTER
 
	RSTATE	RDH1		;ASSUME DEC MODE
	BRWRTE	IBUS,PORT4	;REREAD BSEL 7
	BR7	50$		;IT IS
	RSTATE	RB1		;BIT STUFF MODE
 
;CLEAR XX5
50$:	BRWRTE	IMM,0
	OUTPUT	BR,SELB,OUTDA2,INCMAR
				;MAR = D.SADR (SECONDARY ADDRESS)
 
	MEMINC	IBUS,PORT3	;SAVE SECONDARY ADDRESS
	BRWRTE	IMM,D.XSTS	;OFFSET OF TRANSMIT ABORT STATUS
	LDMA	BR,ADD,SP.RM0	;SET MAR
	MEM	IMM,0		;CLEAR ANY PENDING STATUS
 
;WRITE TWO BYTES INTO XX4/XX5
 
	CALLSR	SP.SUB,IC2OUT,RQICL2	;SHIP IT AND RETURN TO CALLER
  
	.SBTTL	BAIN-BUFFER ADDRESS IN SERVICE ROUTINE
 
;+
;		B U F F E R  A D D R E S S  I N
; 
;CALLED BY:	RDICLR
;
;INPUTS:
;	SEL4,BSEL7 <7:6>	=BUFFER DESCRPTR LIST ADDR
;	BSEL7<5:4>	=KILL ASSIGN AND KILL BITS
;	SP.RM0,SP.RM1	=LINE TABLE ADDRESS
;	MAR 		=LINE TABLE
;	OUT BA		=DUP'S CSR ADDRESS
;OUTPUTS:
;	BUFFER DESCRIPTOR ADDRESS DEFINED BY THE BA IN IS LOADED INTO
;	THE APPROPRIATE (RECEIVE/TRANSMIT) DESCRIPTOR POINTER.
;	IF THE CURRENT BUFFER IS THE ONE JUST ASSIGNED,LINE TABLE LOCATIONS
;	(BUFFER ADDRESS,BYTE COUNT) ARE UPDATED. OTHERWISE DR.ABA IS SET (ALT ASGNED)
;	IF THE CURRENT BUFFER FOR TRANSMISSION IS BEING ASSIGNED,FIRST ODD
;	CHARACTER IN THE TRANSMIT BUFFER IS SAVED IN D.OXC
;	IF THE CURRENT BUFFER FOR RECEPTION IS BEING ASSIGNED,DR.FST IS SET
;-

BAIN:
 
;LOAD RECEIVE CONTROL AND STATUS REGISTER INTO SP.CS0
 
	OUTPUT	IBUS,IOBA1,IBA1	;SET INBA 7:0
	OUTPUT	IBUS,IOBA2,IBA2	;SET INBA 15:8
	BRWRTE	IMM,<BIT3!BIT2!DATI>	;SET EXT BITS AND 
	OUT	BR,SELB,ONPR	;DO IN NPR
;DETERMINE TYPE OF IO REQUIRED (RECEIVE OR TRANSMIT)
 
	BRWRTE	IBUS,OCON	;GET OUTPUT CONTROL REGISTER
	BRSHFT
	BR1	BARCV		;BAIN FOR RECEIVE
 
;BAIN FOR TRANSMIT OPERATION
	BRWRTE	IMM,D.XDP	;ADDRESS D.XDP
	ALWAYS	BAIN1
;BAIN FOR RECEIVE OPERATION
BARCV:	BRWRTE	IMM,D.RDP	;ADDRESS D.RDP
BAIN1:
	BRWRTE	BR,ADD,SP.RM0	;BR=ADDRESS OF D.RDP OR D.XDP
	SP	BR,SELB,SP6	;SET SP6=THAT ADDRESS
10$:	BRWRTE	IBUS,NPR	;WAIT FOR NPR COMPLETION
	BR0	10$
	SP	IBUS,INDAT1,SP.CS0	;LOAD RCV CSR (XX0) INTO SP.CS0
 
;CHECK IF THERE IS A KILL
 
	BRWRTE	IBUS,PORT4		;GET PORT 4 INTO BR
	BR4	KILLAL			;BRANCH TO KILL ROUTINE
 
 
; THIS IS A VALID BUFFER ASSIGNMENT
;(ALSO ENTRY POINT AFTER A KILL IF A NEW BUFFER IS ASSIGNED)
BAIN0:
 
;CHECK IF CURRENT OR ALTERNATE OPERATION
	BRWRTE	IMM,<D.RBDF-D.RDP>	;OFFSET TO FLAG BYTE FOR CURRENT OPERATION
	LDMA	BR,ADD,SP6	;ADDRESS FLAG BYTE
	SPBR	MEMX,SELB,SP5	;GET FLAGS INTO BR,SP5
	BRSHFT
	BR4	BAALT		;CURRENT BUFFER ALREADY ASSIGNED
;CURRENT BUFFER NOT ASSIGNED,ASSIGN CURRENT BUFFER
	MEM	IMM,DR.CBA	;SET CURRENT BUFFER ASSIGNED & CLEAR
				;ALL OTHER BITS IN FLAG BYTE
	LDMA	BR,SELA,SP6	;ADDRESS D.RDP/D.XDP
;SAVE LIST ADDRESS AT CURRENT MEMORY LOCATION
BAIN2:
	MEMINC	IBUS,PORT1	;ADDRESS 7:0
	MEMINC	IBUS,PORT2	;ADDRESS 15:8
	SP	IBUS,PORT4,SP0	;GET EXT ADDRESS
	BRWRTE	IMM,300		;BR=MASK TO ISOLATE EXT ADDRESS
	BRWRTE	BR,AANDB,SP0	;BR=JUST EXT ADDRESS BITS
	BRSHFT			;SHIFT IT INTO PROPER POSITION
	BRSHFT
	BRSHFT
	BRSHFT
	MEM	BR,SELB		;SAVE EXT ADDRESS
 
;IF THE CURRENT BUFFER IS BEING ASSIGNED,DO SPECIAL THINGS
	BRWRTE	BR,TWOA,SP5	;SP5 HAS FLG BITS
	BR7	RQICL2		;ALTERNATE BUFFER ASSIGNED,EXIT
;CURRENT BUFFER BEING ASSIGNED,MOVE DESCRIPTOR PARAMETRS INTO RAM
	CALLSR	SP.SB1,NXDSCP,RQICR2	;RETURN TO IDLE THROUGH PAGE 2
;LABEL TO USE "ALWAYS NXDSCP" IN THE ABOVE MACRO AS AN INTER PAGE RETURRN
NXDP1=.-2
 
;ASIGNING ALTERNATE BUFFER
BAALT:
 
	BRWRTE	IMM,DR.ABA	;SET DR.ALT(=DX.ALT)BIT
	MEM	BR,AORB,SP5
	SP	MEMX,SELB,SP5	;SET SP5=NEW FLAGS
	BRWRTE	IMM,<D.ARLP-D.RDP>	;ADDRESS ALTERNATE POINTER
	LDMA	BR,ADD,SP6
	ALWAYS	BAIN2		;SAVE LIST POINTER IN RAM
	.SBTTL	XMTDON - TRANSMIT DONE
;	FILE	DUXMIT.MAC
 
;+
; **-XMTDON-ROUTINE TO LOOK FOR AND HANDLE A DUP TRANSMIT DONE**
;
; CALLED BY:	TIMER
;
; INPUTS:
;	SP0	= LOW BYTE OF DUP'S CSR0 ADDRESS
;	SP1	= HIGH BYTE OF DUP'S CSR0 (CTS STATUS)
;	SP.RM0-RM1	= RAM TABLE ADDRESS
;	SP.CS0	= LOW BYTE OF CSR0 (CONTAINS STATE OF RTS & RECV. ENABLE)
;	SP.LN	= LINE NUMBER
;	MAR AND SP.STS	= STATUS BYTE IN LINE'S TABLE
;	IN DATA ADDRESS	= DUP'S CSR 0
;
; OUTPUTS:
;	IN THE NORMAL CASE THE NEXT CHARACTER IS TRANSMITTED.  SPECIAL
;	CASES INCLUDE HANDLING SYNC TRANSMISSION, CRC TRANSMISSION
;	AND ERROR CONDITIONS.
;-
 
XMTDON:
	BRWRTE	SELA,SP1	;READ THE HIGH BYTE OF CSR 0
	BRSHFT
	BR4	10$		;CLEAR TO SEND IS SET
	ALWAYS	TIMRT3		;NO, SET CHECK FOR RECEIVE DONES
10$:	BRWRTE	IMM,4		;PREPARE TO POINT TO CSR4
	OUTPUT	BR,ADD,IBA1	;SET IT UP
	BRWRTE	IMM,14!DATI		;MASK TO SET EXTENDED MEMORY BITS
				;AND START NPR
	OUT	BR,SELB,ONPR	;START THE NPR
20$:	BRWRTE	IBUS,NPR	;IS THE NPR DONE YET
	BR0	20$		;NO, WAIT FOR IT
	BRWRTE	IBUS,INDAT1	;READ THE TRANSMIT CNTROL REGISTER
	BR7	XMTDN1		;TRANSMIT DONE SET
	ALWAYS	TIMRT3		;TRANSMIT NOT DONE - RETURN
 
; TRANSMIT DONE FOUND
 
	.ENABL	LSB
XMTDN1:
	OUTPUT	IBUS,IIBA1,OBA1	;COPY INPUT ADDRESS TO OUTPUT
	OUTPUT	IBUS,IIBA2,OBA2	;ADDRESS
	SP	IBUS,UBBR,SP0	;READ THE CONTENTS OF THE BUS REQ REG
	BRWRTE	IMM,101		;MASK TO CLEAR ALL BUT NXM AND XX4 BITS
	SP	BR,AANDB,SP0	;CLEAR THEM
	BRWRTE	IMM,14		;EXTENDED MEMORY BITS
	OUT	BR,AORB,OBR	;SET THEM UP
	BRWRTE	IMM,D.XSTS	;LOOK AT TRANSMIT STATUS BYTE
	LDMA	BR,ADD,SP.RM0	; LOAD THE MAR
	SPBR	MEMX,SELB,SP0	;READ THE BYTE
	BR4	XMTABT		;TRANSMIT ABORT PENDING
	BRWRTE	IMM,D.XBDF	;LOOK AT TRANSMITTER FLAGS WORD
	LDMA	BR,ADD,SP.RM0	; (LOAD MAR)
	BRWRTE	MEMX,SELB	;READ THE FLAGS WORD
	BRSHFT			;SHIFT IT RIGHT
	BR4	50$		;BUFFER IS ASSIGNED
 
; THIS DONE IS THE RESULT OF A BUFFER TERMINATING AND NO SUBSEQUENT BUFFERS ASSIGNED
 
	BR0	10$		;LAST BUFFER HAD END OF MESSAGE SET
	ALWAYS	TIMRT3		;PREVIOUS BUFFER WAS NOT THE END OF
				;MESSAGE - WAIT FOR THE NEXT BUFFER
				;OR AN UNDERRUN ERROR
10$:	SP	IBUS,IOBA1,SP0	;READ THE LOW BYTE OF OUT ADDRESS (CSR 4)
	BRWRTE	IMM,370		;MASK TO CHANGE IT TO CSR 0
	OUTPUT	BR,AANDB,OBA1	;MAKE IT CSR 0
	BRWRTE	IMM,377-DUPRTS		;MASK TO CLEAR RTS
	SPBR	BR,AANDB,SP.CS0		;AND IMAGE OF CSR 0
	OUTPUT	BR,SELB,OUTDA1	;IMAGE OF CSR 0 WITH RTS CLEAR
	ALWAYS	XMTSN0			;START THE NPR THEN RETURN TO TIMER LOOP
 
; BUFFER IS ASSIGNED
 
XMTDN3:
50$:
	BRWRTE	IBUS,INDAT1	;READ THE TRANSMIT CNTROL REGISTER
	BR4	55$		;SEND SET
	BRWRTE	IBUS,INDAT2	;GET THE BYTE CONTAINING TX ACTIVE
	BR1	TIMRT3		;IF SET, DON'T SET SEND YET.
				;NOTE THAT THE DUP MAY GET IN AN ILLEGAL
				;SET IF SEND IS DROPPED AND REASSERTED BEFORE
				;TX ACTIVE CLEARS
	SP	IMM,DUPSND,SP0	;MASK TO SET SEND
	ALWAYS	XMTSND		;"CALL" SEND ROUTINE AND RETURN TO TIMER LOOP
;
; ENTER HERE AFTER COMPLETING ONE BUFFER AND FIND ANOTHER ASSIGNED
; THE BRG CURRENTLY CONTAINS THE TRANSMIT FLAGS BYTE ROTATED
;
XMTDN4:	BR7	TIMRT3		;START OF MESSAGE SET - INDICATES PREVIOUS
				;MESSAGE ENDED WITH AN EOF HENCE A TEOM
				;HAS JUST BEEN SENT SO WAIT FOR NEXT TDONE
55$:	SPBR	MEMX,SELB,SP0	;READ THE FLAGS AGAIN
	BR0	120$		;START OF MESSAGE FLAG SET
60$:	CALLSR	SP.SUB,DECNT,XMTCNT,D.XBDC ;DECREMENT THE BYTE COUNT
 
; ABOVE SUBROUTINE RETURNS HERE IF THE BYTE COUNT WAS NOT ZERO
; IF BYTE COUNT WAS ZERO, END OF BUFFER CONDITIONS ARE CHECKED IN XMTCNT
 
XMTDN2:	SPBR	MEMX,SELB,SP1	;READ THE LOW BYTE OF THE ADDRESS
				;AND SAVE IT IN THE BRG
	MEMINC	INCA,SP1	;INCREMENT ADDRESS AND STORE IT BACK
	BR0	110$		;ODD CHARACTER (ALREADY BEEN READ)
				;OTHERWISE ITS AN EVEN CHARACTER

; TRANSMIT EVEN CHARACTER
;  MUST READ A WORD FROM MEMORY
;
				;NO NEED TO WORRY ABOUT CARRY SINCE THERE
				;CAN'T BE ON AN EVEN TO ODD INCREMENT
	OUTPUT	BR,SELB,IBA1	;BUFFER ADDRESS TO IN ADDRESS FIELD
	OUTPUT	MEMI,SELB,IBA2	;..
	BRWRTE	IMM,14		;MASK TO ISOLATE EXTENDED MEMORY BITS
	SP	BR,AANDB,SP0	;MASK FLAGS WORD
	OUT	INCA,ONPR	;SET EXTENDED MEM BITS AND NPR REQUEST BIT
	BRWRTE	IMM,0		;ZERO THE BRG
	OUTPUT	BR,SELB,OUTDA2	;CLEAR ALL DUP CONTROL BITS
80$:	BRWRTE	IBUS,NPR	;READ THE NPR STATUS REGISTER
	BR0	80$		;NPR NOT DONE YET
	OUTPUT	IBUS,INDAT1,OUTDA1,INCMAR ;MOVE CHARACTER TO OUTDATA FIELD
				;AND MOVE THE MAR TO ODD CHARACTER SAVE BYTE
	MEM	IBUS,INDAT2	;SAVE THE ODD CHARACTER IN RAM

; "RETURN" POINT FROM XMTSYN
WRTRT:
	SP	IBUS,IOBA1,SP0	;READ CURRENT OUTPUT ADDRESS (CSR4)
	BRWRTE	IMM,2		;VALUE TO ADD
	OUTPUT	BR,ADD,OBA1	;POINT TO CSR6
	BRWRTE	IMM,DATO	;MASK TO DO OUT NPR
; THIS IS THE "RETURN" POINT FROM XMTSND AND XMTSN0
XMTDN6:
	OUT	BR,SELB,ONPR	;DO THE NPR
90$:	BRWRTE	IBUS,NPR	;WAIT FOR IT TO COMPLETE
	BR0	90$		;NOT YET
	ALWAYS	TIMRT3		;RETURN TO TIMER LOOP
 
; TRANSMIT ODD DATA CHARACTER
;
; INPUTS:
;	"C" BIT IS SET OR CLEAR DEPENDING ON CARRY FROM INCREMENT OF LOW BYTE
;	MAR	= D.XBDA+1
 
110$:	C	113$		;IF CARRY SET THEN MUST INCRMENT HIGH 10 BITS OF ADDR
	BRWRTE	IMM,0,INCMAR	;ZERO THE BRG AND POINT MAR TO D.XBDF
	ALWAYS	116$		;OTHERWISE NO NEED TO
113$:	CALLSB	SP.SUB,INCMM	;INCREMENT THE BUFFER ADDRESS (HIGH 10 BITS)
				;RETURNS WITH MAR POINTING TO D.XBDF
	BRWRTE	IMM,0		;ZERO THE BRG 
116$:	OUTPUT	BR,SELB,OUTDA2,INCMAR	;CLEAR ALL DUP CONTROL BITS
				;AND POINT MAR TO ODD TRANSMIT CHARACTER
	OUTPUT	MEMX,SELB,OUTDA1	;MOVE THE CHARACTER TO THE OUTDATA FIELD
	ALWAYS	WRTRT		;INCREMENT OUT ADDR BY 2 (CSR6) AND DO AN
				;NPR TO WRITE OUT THE CHARACTER
				;RETURN TO THE TIMER LOOP
 
; START OF MESSAGE SET
;
; BRG AND SP0 = (D.XBDF)
 
120$:
	BR4	XMTSYN		;RESYNC REQUESTED
	BRWRTE	IBUS,INDAT2	;READ HIGH BYTE OF CSR4
	BR7	121$		;UNDERRUN OCCURRED, SEND 2 SOM'S
.IIF NE	DX.SOM-1 .ERROR	;FOLLOWING DECA WILL NO LONGER CLEAR DX.SOM FLAG
	MEM	DECA,SP0	;CLEAR IT
	BRWRTE	SELA,SP.STS	;GET THE STATUS BYTE
	BRSHFT
	BR4	60$		;DEC MODE (DDCMP)
121$:
	BRWRTE	IMM,DUPTSM	;START OF MESSAGE BIT
	OUTPUT	BR,SELB,OUTDA2	;SET START OF MESSAGE
	ALWAYS	WRTRT		;COMMON CODE TO INCR OUT ADDR BY 2
				;DO AN NPR AND RETURN TO TIMER LOOP
	.DSABL	LSB
	.SBTTL	RCVDON-RECEIVED CHARACTER PROCESSOR
;	FILE	DUPRCV.MAC
 
;+
;	R E C E I V E  C H A R A C T E R  P R O C E S S O R
; 
; 
;CALLED BY:	TIMER
;
;INPUTS:
;	SP.RM0,SP.RM1	=ADDRESS OF CURRENT LINE TABLE
;	SP.CS0   =DUP RECEIVE STATUS REGISTER
;	SP.CHR   =RECEIVED CHARACTER
;	SP.RST   =STATUS OF CHARACTER
;OUTPUTS:
;	CHECKS FOR RECEIVE ERRORS, THEN BRANCHES TO A RECEIVE STATE PROCESSOR
;	USING D.RPTR FROM LINE TABLE.  RSTATE MACRO CHANGES STATE SETTINGS.
;	RECIEVE STATE INITIALIZED BY CONTROL IN.
;-
 
RCVDON:
	BRWRTE	IMM,D.STS		;OFFSET TO STATUS BYTE
	LDMA	BR,ADD,SP.RM0		;SET UP MAR
	LDMAP	SELA,SP.RM1		;LOAD MAR HI
	SP	MEMI,SELB,SP.STS	;SAVE STATUS BYTE IN SP
 
; CHECK IF ANY ERROR ON RECEIVED CHARACTER
 
	BRWRTE	BR,SELA,SP.RST		;GET HIGH BYTE OF RECEIVE BUFFER
	BR7	DUPRER			;RECEIVE ERROR ***
 
;CHARACTER IS ERROR FREE
 
;DISPATCH TO THE CURRENT RECEIVE STATE PROCESSOR.
 
	.ALWAY	MEMX,SELB,RP		;DISPATCH VIA STATE POINTER

; ***NOTE: ALL STATE PROCESSORS MUST BE IN PAGE RP
 
	.PAGE
	.SBTTL	BIT-STUFF PROTOCOL RECEIVE PROCESSORS
;	FILE	DUPSDLC.MAC
 
RP=<.-START>&3000*4	;PAGE ADDRESS OF RECEIVE STATE PROCESSORES


	.SBTTL	RB1-BIT STUFF RECEIVE STATE ONE
 
;+ 
; 
;	B I T  S T U F F  R E C E I V E  S T A T E  O N E
; 
;ENTERED FROM:	RCVDON 
;
;INPUTS: 
;	MAR	=RECEIVER STATE POINTER (D.RPTR)
;
;OUTPUTS:
;	RECEIVE STATE POINTER IS SET TO STATE TWO
;-
 
RB1:
	RSTATE	RB2			;SET TO STATE 2
 
	BRADDR	TIMRTN			;ULTIMATE RETURN ADDRESS
	SP	BR,SELB,SP.SUB,INCMAR	;STORE IN RETURN SCRATCH PAD
	ALWAYS	LSILO			;JUMP TO ROUTINE TO SILO CHARACTER
					;RETURN TO TIMER
	.SBTTL	RB2-BIT STUFF RECEIVE STATE TWO
 
;+ 
; 
;	B I T  S T U F F  R E C E I V E  S T A T E  T W O
; 
;ENTERED FROM:	RCVDON 
; 
;INPUTS:
;	MAR	=RECEIVE STATE POINTER (D.RPTR)
;
;OUTPUTS:
;	STATE POINTER IS SET TO STATE THREE
;	CURRENT RECEIVED CHARACTER IS PUSHED INTO THE LOCAL TWO CHARACTER SILO
;-

RB2:
	RSTATE	RB3		;SET STATE THREE
	BRADDR	TIMRTN		;RETURN ADDRESS TO POLLING LOOP
	SP	BR,SELB,SP.SUB,INCMAR
	ALWAYS	LSILO		;PUSH SILO AND RETURN TO TIMER
	.SBTTL	RB3-BIT STUFF RECEIVE STATE THREE
 
;+ 
; 
;	B I T  S T U F F  R E C E I V E  S T A T E  T H R E E
; 
; ENTERED FROM:	RCVDON 
; 
; INPUTS:
;	MAR = RECEIVE STATE POINTER (D.RPTR)
;	BR = HIGH BYTE OF CSR0 (SP.RST - RECEIVE CHARACTER STATUS)
; OUTPUTS:
;	CHECK FOR END OF MESSAGE, IF END GOTO RBDONE
;	ELSE STORE THE CHARACTER AND STAY IN THIS STATE
;-
 
RB3:
 
; CHECK IF END OF MESSAGE
 
	BR1	RBDONE			;END OF RECEIVED MESSAGE
 
;NOT END OF RECEIVED MESSAGE
 
	BRADDR	RB3P0			;RETURN ADDRESS TO STORE
	SP	BR,SELB,SP.SUB,INCMAR	;SAVE RETURN ADDRESS
					;FALL INTO LSILO
	.SBTTL	LSILO-PUSH CHARACTER INTO LOCAL TWO CHARACTER SILO
 
;+
; 
; 	P U S H  C H A R A C T E R  I N T O  L O C A L  S I L O
; 
; CALLED BY:	BIT STUFF RECEIVE STATES; RB1,RB2,RB3
; 
; INPUTS:
;	SP.SUB=RETURN ADDRESS
;	SP.CHR=CHARACTER TO BE PUSHED INTO LOCAL TWO CHARACTER SILO
;	MAR = D.SADR
;
; OUTPUTS:
;	CHARACTER IN SP.CHR IS PUSHED INTO SILO
;	UNDERFLOW CHARACTER FROM THE SILO IS LOADED INTO SP.CHR
;	IF IN CRC INHIBIT MODE,INPUT CHARACTER IS DIRECTLY STORED
;	IN MEMORY.
;-
 
LSILO:
 
	BRWRTE	SELA,SP.STS,INCMAR	;GET STATUS BYTE
					;MAR NOW POINTS TO D.SILO
	BR7	STORE		;STORE CHARACTER IF CRC INHIBIT
	SP	MEMX,SELB,SP0	;TEMPORARILY STORE TOP SILO CHR IN SP0
	MEMINC	SELA,SP.CHR	;LOAD NEW CHARACTER INTO TOP SILO POSITION
	SP	MEMX,SELB,SP.CHR	;LOAD UNDERFLOW CHR. INTO SP.CHR
	MEM	SELA,SP0	;STORE OLD TOP CHR INTO BOTTOM POSITION IN SILO
	RTNSUB	SP.SUB,P0	;RETURN
 
	.SBTTL	RBDONE - END OF BIT STUFF MESSAGE RECEIVED

;+
;
;	END OF BIT STUFF MESSAGE RECEIVED
;
; ENTERED BY:	RB3
;
; INPUTS:
;	MAR	=RECEIVE STATE POINTER (D.RPTR)
;
; OUTPUTS:
;	RECEIVE STATE POINTER RESET TO ONE
;	GENERAL END OF RECEIVE MESSAGE ROUTINE CALLED
;-
 
RBDONE:
	RSTATE	RB1		;SET RECEIVE STATE 1
	CALLSR	SP.SB1,EOFMSG,TIMRP2 ;CALL END OF MESSAGE ROUTINE AND 
				; RETURN TO TIMER'S POLLING LOOP
	.SBTTL	DDCMP RECEIVE STATE PROCESSORS
;	FILE	DUPDDCMP.MAC
 
;+ 
; 
;	D D C M P  R E C E I V E  S T A T E  P R O C E S S O R S
; 
; 
; DDCMP RECEIVE STATE PROCESSORS FOR THE COMIOP-DUP FOLLOW.
;- 
	.SBTTL	RDH1-RECEIVING FIRST DDCMP HEADER CHARACTER
 
 
;+
;	R E C E I V I N G  F I R S T  D D C M P  C H A R A C T E R
; 
; ENTERED FROM:	RCVDON
;
; INPUTS:
;	MAR    = RECEIVE STATE POINTER (D.RPTR)
;	SP.CHR = CURRENT RECEIVE CHARACTER
;	SP.LN  = CURRENT LINE NUMBER
;	SP.CS0 = IMAGE OF LOW BYTE OF DUP'S CSR0
;
; OUTPUTS:
;	RECEIVE STATE POINTER IS SET TO THE SECOND DDCMP RECEIVE STATE.
;	RECEIVE STATUS BYTE D.STS IS UPDATED TO INDICATE WHETHER A
;	NUMBERED MESSAGE (SOH OR DLE) OR AN UNNUMBERED MESSAGE (ENQ) IS RECEIVED.
;	A CONTROL OUT IS GENERATED IF AN ILLEGAL HEADER CHARACTER IS RECEIVED.
;IF THE CHARACTER IS LEGAL, STORE ROUTINE IS CALLED TO SAVE IT IN THE USER
;RECEIVE BUFFER.
;IF THE CHARACTER IS SYNC OR PAD,RESYNC THE RECEIVER
;-
 
 
RDH1:
; SET RECEIVE STATE TWO
	RSTATE	RDH2		;SET RECEIVE STATE TWO
 
; SET RAM ADDRESS TO RECEIVE STATUS BYTE
 
	BRWRTE	IMM,D.STS	;OFFSET INTO BR
	LDMA	BR,ADD,SP.RM0
;RESET SELECT,Q-SYNC,IGNORE AND NUMBERED MESSAGE BITS
 
	BRWRTE	IMM,<377-DS.SLT-DS.QSC-DS.IGN-DS.NUM> ;MASK TO CLEAR THOSE BITS
	MEM	BR,AANDB,SP.STS	;CLEAR THOSE BITS AND SAVE
	SP	MEMX,SELB,SP.STS	;GET NEW STATUS
 
; DETERMINE TYPE OF MESSAGE.INPUT CHARACTER IS AVAILABLE IN SP.CHR
 
	BRWRTE	IMM,SOH		;IS IT AN SOH?
	COMP	BR,SP.CHR
	Z	10$		;YES,NUMBERED MESSAGE
 
	BRWRTE	IMM,ENQ		;IS IT AN ENQ?
	COMP	BR,SP.CHR		
	Z	STORE		;YES,UNNUMBERED MESSAGE
 
	BRWRTE	IMM,DLE		;IS IT A DLE?
	COMP	BR,SP.CHR		
	Z	10$		;YES,MAINTAINANCE (NUMBERED) MESSAGE
 
; UNRECOGNIZED START OF HEADER CHARACTER - JUST RESYNC
 
	ALWAYS	RSNCRT		;RESYNC AND RETURN TO TIMER
 
;A NUMBERED MESSAGE IS BEING RECEIVED(SOH OR DLE). SET 'NUMBERED MESSAGE
;BEING RECEIVED' IN D.STS
 
10$:
	BRWRTE	IMM,DS.NUM	;MASK TO SET IT
	MEM	BR,AORB,SP.STS	;OR IT IN INTO D.STS
	ALWAYS	STORE		;STORE FIRST DDCMP CHARACTER IN RECEIVE BUFFER
	.SBTTL	RDH2-RECEIVING SECOND DDCMP HEADER CHARACTER
 
;+ 
; 
;	R E C E I V I N G  S E C O N D  D D C M P  C H A R A C T E R
; 
; ENTERED FROM:	RCVDON
; 
; INPUTS:
;	MAR	= RECEIVE STATE POINTER (D.RPTR)
;	SP.CHR	= RECEIVED CHARACTER
; 
; OUTPUTS:
;	RECEIVE STATE POINTER IS CHANGED TO RECEIVE STATE THREE.  CURRENT
; RECEIVED CHARACTER (LOW ORDER BYTE COUNT IN THE CASE OF A NUMBERED
; MESSAGE) IS SAVED IN D.DCC1. STORE ROUTINE IS CALLED TO STORE THE CURRENT
; RECEIVED CHARACTER IN THE USER RECEIVE BUFFER
;- 
 
RDH2:
 
; UPDATE RECEIVE STATE POINTER TO STATE THREE
 
	RSTATE	RDH3
 
; SAVE CHARACTER COUNT (TYPE IF UNNUMBERED MESSAGE) IN D.DCC1
 
	BRWRTE	IMM,D.DCC1	;ADDRESS D.DCC1
	LDMA	BR,ADD,SP.RM0
	MEM	SELA,SP.CHR	;CURRENT CHARACTER AVAILABLE IN SP.CHR
 
; STORE CURRENT RECEIVED CHARACTER IN USER BUFFER
 
	ALWAYS	STORE
	.SBTTL	RDH3-RECEIVING THIRD DDCMP HEADER CHARACTER
 
;+ 
; 
;	R E C E I V I N G  T H I R D  D D C M P  C H A R A C T E R
; 
; ENTERED FROM:	RCVDON
; 
; INPUTS:
;	MAR	= RECEIVE STATE POINTER (D.RPTR)
;	SP.CHR	= RECEIVED CHARACTER
; 
; OUTPUTS:
;	RECEIVE STATE POINTER IS CHANGED TO STATE FOUR OF DDCMP RECEIVE PROCESSOR.
; HIGH ORDER SIX BITS OF THE CHARACTER COUNT (MEANINGFUL ONLY TO
; NUMBERED MESSAGES) ARE STORED IN D.DCC2. Q-SYNC AND SELECT BITS ARE UPDATED
; IN D.STS.
;- 
 
RDH3:
 
; SET RECEIVE STATE POINTER TO STATE FOUR
 
	RSTATE	RDH4
 
; SAVE HIGH ORDER SIX BITS OF BYTE COUNT (NOT MEANINGFUL FOR UNNUMBERED MESSAGE)
 
	BRWRTE	IMM,D.DCC2	;ADDRESS D.DCC2
	LDMA	BR,ADD,SP.RM0
	BRWRTE	IMM,77		;MASK TO STRIP HIGH ORDER 2 BITS
	MEM	BR,AANDB,SP.CHR	;STRIP THEM FROM CURRENT CHR AND STORE IN RAM
 
; UPDATE SELECT AND Q-SYNC BITS IN D.STS
 
	SP	BR,AANDB,SP.STS	;STRIP OLD SEL. Q-SYNC BITS IN SP.STS
	BRWRTE	IMM,D.STS	;ADDRESS D.STS
	LDMA	BR,ADD,SP.RM0
	BRWRTE	IMM,300		;MASK TO ISOLATE NEW SELECT,Q-SYNC BITS
	BRWRTE	BR,AANDB,SP.CHR	;GET NEW BITS INTO BR
	MEM	BR,AORB,SP.STS	;UPDATE D.STS
 
; STORE CURRENT RECEIVED CHARACTER IN USER RECEIVE BUFFER
 
	ALWAYS	STORE
 
	.SBTTL	RDH4-RECEIVING FOURTH DDCMP HEADER CHARACTER
 
;+ 
; 
;	R E C E I V I N G  F O U R T H  D D C M P  C H A R A C T E R
;			(RESPONSE FIELD)
; 
; ENTERED FROM:	RCVDON
; 
; INPUTS:
;	MAR	= RECEIVE STATE POINTER (D.RPTR)
;	SP.CHR	= RECEIVED CHARACTER
; 
; OUTPUTS:
;	RECEIVE STATE POINTER IS CHANGED TO STATE FIVE OF RECEIVE PROCESSOR.
; THE CURRENT CHARACTER (RESPONSE FIELD) IS STORED IN USER RECEIVE BUFFER.
;- 
 
RDH4:
 
; SET RECEIVE STATE POINTER TO STATE FIVE
 
	RSTATE	RDH5
 
; STORE CURRENT CHARACTER (RESPONSE FIELD) IN USER RECEIVE BUFFER
 
	ALWAYS STORE
	.SBTTL	RDH5-RECEIVING FIFTH DDCMP HEADER CHARACTER
 
;+ 
; 
;	R E C E I V I N G  F I F T H  D D C M P  C H A R A C T E R
;			(MESSAGE NUMBER FIELD)
; 
; ENTERED FROM:	RCVDON
; 
; INPUTS:
;	MAR	= RECEIVE STATE POINTER (D.RPTR)
;	SP.CHR	= RECEIVED CHARACTER
; 
; OUTPUTS:
;	RECEIVE STATE POINTER IS SET TO STATE SIX.  CURRENT CHARACTER (MESSAGE
; NUMBER FIELD) IS STORED IN THE USER RECEIVE BUFFER.
;- 

RDH5:
 
; SET RECEIVE STATE POINTER TO STATE SIX
 
	RSTATE	RDH6
 
;STORE CURRENT CHARACTER (MESSAGE NUMBER) IN USER BUFFER
 
	ALWAYS	STORE
	.SBTTL	RDH6-RECEIVING SIXTH DDCMP HEADER CHARACTER
 
;+ 
; 
;	R E C E I V I N G  S I X T H  D D C M P  C H A R A C T E R
;			(STATION ADDRESS FIELD)
; 
; ENTERED FROM:	RCVDON
;
; INPUTS:
;	MAR	= RECEIVE STATE POINTER (D.RPTR)
;	SP,CHR	= RECEIVES CHARACTER
; 
; OUTPUTS:
;	RECEIVE STATE POINTER IS SET TO PROCESS FIRST HEADER CRC CHARACTER.
; IF THE USER STATION IS A SECONDARY STATION AND THERE IS AN ADDRESS MISMATCH,
; THE IGNORE BIT IS SET IN D.STS.
;- 

RDH6:
 
;SET RECEIVE STATE POINTER TO PROCESS FIRST HEADER CRC
 
	RSTATE	RHCRC1
 
;CHECK IF SECONDARY STATION
 
	BRWRTE	SELA,SP.STS,INCMAR	;LOAD D.STS INTO BR AND ADDRESS D.SADR
	BRSHFT			;SHIFT IT RIGHT
	BR1	10$		;BRANCH IF SECONDARY STATION
 
; CURRENT STATION IS NOT A SECONDARY STATION, NO ADDRESS CHECKING NECESSARY
 
	ALWAYS	STORE		;STORE CHARACTER IN REC BUFFER
 
; CURRENT STATION IS A SECONDARY STATION.
 
10$:
 
;CHECK IF ADDRESS MATCH (MAR MUST NOW BE POINTING AT D.SADR)
	COMP	MEMX,SP.CHR	;ADDRESS MATCH?
	Z	STORE		;YES,STORE THE CHARACTER
 
; STATION IS A SECONDARY STATION, BUT IS NOT ADDRESSED 
; SET IGNORE MODE
 
	BRWRTE	IMM,D.STS	;ADDRESS  STATUS BYTE
	LDMA	BR,ADD,SP.RM0
	BRWRTE	IMM,DS.IGN	;MASK TO SET IGNORE MODE
	MEM	BR,AORB,SP.STS	;WRITE IT BACK INTO RAM WITH IGNORE BIT SET
	ALWAYS	STORE		;STORE CURRENT CHARACTER
	.SBTTL	RHCRC1-RECEIVING FIRST DDCMP HEADER CRC
 
;+ 
; 
;	R E C E I V I N G  F I R S T  D D C M P  H E A D E R  C R C
; 
; ENTERED FROM:	RCVDON
; 
; INPUTS:
;	MAR	= RECEIVE STATE POINTER (D.RPTR)
; 
; OUTPUTS:
;	RECEIVE STATE POINTER IS SET TO PROCESS SECOND DDCMP HEADER
; CRC CHARACTER.
;-

RHCRC1:
 
;SET RECEIVE STATE POINTER TO RECEIVE SECOND DDCMP HEADER CRC
 
	RSTATE	RHCRC2

; ** PAGE ONE RETURN TO TIMER FOR RECEIVE ROUTINES **

TIMRP1:	ALWAYS	TIMRTN		;RETURN TO THE TIMER LOOP
.IIF NE	<<TIMRP1-START>/1000-1> .ERROR ;LABEL "TIMRP1" NO LONGER ON PAGE 1
	.SBTTL	RHCRC2-RECEIVING SECOND DDCMP HEADER CRC
 
;+ 
;
;	R E C E I V I N G  S E C O N D  D D C M P  H E A D E R  C R C
; 
; ENTERED FROM:	RCVDON
; 
; INPUTS:
;	MAR	= RECEIVE STATE POINTER (D.RPTR)
;	BR = HIGH BYTE OF CSR 2 (SP.RST - RECEIVE CHARACTER STATUS)
;
; OUTPUTS:
;	DUP HAS RECEIVED SECOND HEADER CRC CHAR.
;	CHECK IF HEADER CRC IS VALID, IF NOT POST ERROR CNTRL OUT.
;	IF THIS IS AN UNNUMBERED MESG, PROCESS NOW.
;	ELSE (NUMBERED OR MAINT), STATE IS SET TO RECEIVE DATA.
;-
 
RHCRC2:
 
; SET RECEIVE STATE POINTER TO RECEIVE DDCMP DATA
 
	RSTATE	RDDATA
 
; CHECK IF THERE IS A CRC ERROR
 
	BR4	10$		;CRC=0,MESSAGE IS OK
	ALWAYS	ERR10		;***CRC ERROR***
 
;CHECK IF THE CURRENT MESSAGE IS A NUMBERED MESSAGE
 
10$:
	BRWRTE	SELA,SP.STS	;LEFT SHIFT D.STS AND LOAD INTO BR
	BR0	TIMRTN		;RECEIVING NUMBERED MESSAGE
				;RETURN TO TIMER
 
;RECEIVING UNNUMBERED MESSAGE
 
	ALWAYS	MSGIN		;PROCESS ONE MESSAGE
	.SBTTL	RDDATA-RECEIVING DDCMP DATA CHARACTERS
 
;+ 
; 
;	R E C E I V I N G  D D C M P  D A T A  C H A R A C T E R S
; 
; ENTERED FROM:	RCVDON
; 
; INPUTS:
;	MAR	= RECEIVE STATE POINTER (D.RPTR)
; 
; OUTPUTS:
;	THE DATA BYTE COUNT IS DECREMENTED.
;	IF ALL DATA IS RECEIVED, THIS IS THE FIRST CRC CHAR.
;	OTHERWISE, STORE THE DATA IN BUFFER IF FOR THIS STATION.
;-
 
RDDATA:
 
;CHECK IF LAST DDCMP DATA CHARACTER
 
	CALLSR	SP.SUB,DECDCC,DECP2	;DECREMENT DDCMP DATA CHARACTER COUNT
RDATA1:
	C	10$		;BRANCH IF COUNT NOT -1
 
;CURRENT CHARACTER IS THE FIRST DDCMP DATA CRC CHARACTER
 
	ALWAYS	RDCRC1
 
 
; STORE CURRENT DATA CHARACTER IN USER RECEIVE BUFFER IF THE CURRENT MESSAGE
;IS ADDRESSED TO THIS STATION.
 
10$:
	BRWRTE	SELA,SP.STS	;GET SP.STS(=D.STS)
	BR4	TIMRTN		;MESSAGE NOT FOR THIS STATION
 
; DATA CHARACTER IS PART OF A NUMBERED MESSAGE ADDRESSED TO THIS STATION,SAVE IT
 
	ALWAYS	STORE
 
	.SBTTL	RDCRC1-RECEIVING FIRST DDCMP DATA CRC
 
;+ 
; 
;	R E C E I V I N G  F I R S T  D D C M P  D A T A  C R C
; 
; ENTERED FROM:	RDDATA
; 
; INPUTS:
; 
; OUTPUTS:
;	RECEIVE STATE POINTER IS SET TO PROCESS SECOND DATA CRC
;- 

RDCRC1:
 
;SET RECEIVE STATE POINTER TO SECOND DATA CRC PROCESSOR
 
	BRWRTE	IMM,D.RPTR	;ADDRESS D.RPTR (SINCE IT WAS CHANGED IN
	LDMA	BR,ADD,SP.RM0	;THE PREVIOUS STATE)
	RSTATE	RDCRC2
	ALWAYS	TIMRTN		;RETURN TO TIMER
 
	.SBTTL	RDCRC2-RECEIVING SECOND DATA CRC
 
;+ 
;
;	R E C E I V I N G  S E C O N D  D A T A  C R C
; 
; ENTERED FROM:	RCVDON
; 
; INPUTS:
;	BR = HIGH BYTE OF CSR2 (SP.RST - RECEIVE CHARACTER STATUS)
; OUTPUTS:
; IF A CRC ERROR IS DETECTED ON THE CURRENT MESSAGE,A CONTROL OUT IS GENERATED.
; IF THE MESSAGE IS GOOD, MSGIN ROUTINE IS EXECUTED TO PROCESS IT
;-
 
RDCRC2:
 
; CHECK FOR CRC ERROR
 
	BR4	MSGIN		;CRC OK,USE COMMON CODE
	ALWAYS	ERR12		;***CRC ERROR ON DATA***
 
 
;+
;
;	 RETURN TO TIMER LOOP FROM RECEIVE STORE ROUTINES
;
; ENTERED FROM:	RCVEXT (SUBR RETURN)
;
; INPUTS:
;	NPR STARTED EARLIER IN STORE RECVD CHAR ROUTINES
;
; OUTPUTS:
;	WAIT FOR NPR TO COMPLETE AND RETURN TO TIMER
;-

.IIF NE <NPRWP1-START>/1000-1	.ERROR	;NPRWP1 IS NOT ON PAGE ONE
NPRWP1:
	BRWRTE	IBUS,NPR	;READ NPR CONTROL REGISTER
	BR0	NPRWP1		;NOT DONE YET
	ALWAYS	TIMRTN		;RETURN TO TIMER LOOP
	.SBTTL	DSRCHG-DATA SET READY CHANGE

;+
; **DSRCHG-ROUTINE TO GIVE A DATA SET READY CHANGE CONTROL OUT**
;
; CALLED BY:	TIMER
;
; INPUTS:
;	SP0 = IMAGE OF DUP'S CSR 1 (DSR=BIT 1)
;	MAR = D.STS
;
; OUTPUTS:
;	MAR = D.STS
;	D.STS (BIT 1) = CURRENT SETTING OF DSR
;-
DSRCHG:
	.IIF NE	DS.DSR-SP2	.ERROR DS.DSR	;DS.DSR NO LONGER EQUALS SP2
	SP	IMM,DS.DSR,SP2	;GET MASK FOR DSR INTO SP2
	MEM	MEMX,AXORB,SP2	;RECORD THE CURRENT STATE OF DSR
				;IF IT WAS SET CLEAR IT, IF IT WAS CLEAR
				;SET IT
	CALLSR	SP.SUB,COUTX,TIMRP3,ER.DSR	;QUEUE A CONTROL OUT AND
				;RETURN TO TIMER LOOP
	.SBTTL	MSGIN-DDCMP MESSAGE PROCESSOR

;+
;
;		D D C M P  M E S S A G E  I N
; 
; ENTERED FROM:	RDCRC2(NUMBERED), RHCRC2(UNNUMBERED)
;
; A COMPLETE DDCMP MESSAGE (NUMBERED OR UNNUMBERED) HAS BEEN RECEIVED WITHOUT
; A CRC ERROR.PROCESS IT.
;
; INPUTS:
;	MAR	= RECEIVE STATE POINTER (D.RPTR)
;
; OUTPUTS:
;	RECEIVE STATE RESET TO FIRST HEADER CHAR.
;	IF MESG IS FOR US, POST A BA OUT.
;	ELSE, RESET BUFFER POINTERS IN LINE TABLE.
;-
 
MSGIN:
 
; INITIALIZE RECEIVE STATE POINTER
	RSTATE	RDH1
 
; CHECK IF THIS MESSAGE IS TO BE IGNORED
	BRWRTE	SELA,SP.STS	;SET BR=SP.STS
	BR4	10$		;IGNORE CURRENT MESSAGE
 
; MESSAGE IS WITHOUT ERROR AND ADDRESSED TO THIS STATION. GENERATE A BA OUT
 
	CALLSR	SP.SB1,EOFMSG,MSGIN1	;POST THE COMPLETION AND RETURN TO MSGIN1
 
;CURRENT MESSAGE IS NOT FOR THIS STATION,IGNORE IT
 
10$:
; RECEIVE BUFFER ADDRESS AND BYTE COUNT WAS ADVANCED AT THE BEGINNING OF
;THIS MESSAGE, RESET IT.
	BRWRTE	IMM,D.ORBC		;ADDRESS D.ORBC
	LDMA	BR,ADD,SP.RM0

;SAVE ORIGINAL PARAMETERS IN SCRATCH PADS
	SP	MEMI,SELB,SP4		;SAVE ORIGINAL BYTE COUNT IN SP4,SP3
	SP	MEMI,SELB,SP3
	SP	MEMI,SELB,SP2		;SAVE ORIGINAL ADDRESS IN SP2,SP1&SP0
	SP	MEMI,SELB,SP1
	SP	MEMI,SELB,SP0

;RESTORE THEM INTO CURRENT PARAMETERS
 
	MEMINC	SELA,SP4		;RESTORE BYTE COUNT
	MEMINC	SELA,SP3
	MEMINC	SELA,SP2		;RESTORE BUFFER ADDRESS IN CURRENT AREA
	MEMINC	SELA,SP1		
	MEMINC	SELA,SP0

;CHECK IF Q-SYNC BIT SET
 
.IIF NE	<MSGIN1-START>/1000-2	.ERROR	;MSGIN1 IS NOT ON PAGE TWO
MSGIN1:
	BRWRTE	TWOA,SP.STS	;READ STATUS REGISTER
	ALWAYS	PATCHA		;JUMP TO PATCH, PATCH BRANCHES TO 
				;RSNCRT OR TIMRTN ON BR7
	.SBTTL	KILLAL-KILL XMT OT RCV OPERATION
 
;+
;
;	KILL RECEIVE OR TRANSMIT BUFFERS
;
; CALLED BY:	BAIN
;
; INPUTS:
;	BSEL2<2> (OCON)	=IN I/O (1=RECV, 0=XMIT)
;	BSEL7<5> (PORT4)=KILL ASSIGN
;
; OUTPUTS:
;	DEASSIGNS EITHER TRANSMIT OF RECEIVE BUFFERS DEPENDING ON THE IN I/O BIT.
;	IF ASSIGNMENT IS REQUESTED(KILL ASSGN), BAIN IS RETURNED TO .
;	ELSE IT RETURNS DIRECTLY TO RDICLR.
;-
 
KILLAL:
 
;DETERMINE WHETHER THE TRANSMIT OR RECEIVE OPERATION IS TO BE KILLED
 
	BRWRTE	IBUS,OCON	;GET BSEL2
	BRSHFT
	BR1	KILLRC		;KILL RECEIEV OPERATION

;KILL TRANSMIT OPERATION
 
KILLXM:
	BRWRTE	IMM,D.XSTS	;POINT TO TRANSMIT STATUS BYTE
	LDMA	BR,ADD,SP.RM0	; LOAD THE MAR
	SP	MEMX,SELB,SP0	;READ THE STATUS BYTE
	BRWRTE	IMM,DT.ABT!DT.AB1	;ABORT PENDING FLAG
	MEM	BR,AORB,SP0	;OR IT BACK TO MEMORY
	BRWRTE	IMM,C.CLOX	;SET CONTROL OUT FOR XMT
	ALWAYS	KILCOM		;USE COMMON CODE
 
;KILL RECEIVE OPERATION
 
KILLRC:
	CALLSB	SP.SB1,RESYNC	;RESYNC RECEIVER
	BRWRTE	IMM,C.CLOR	;SET CONTROL OUT FOR RECEIVE
 
KILCOM:
	SP	BR,SELB,SP2	;SAVE BSEL2 IMAGE
	BRWRTE	IMM,ER.KIL	;REASON CODE 'KILL'
	SP	BR,SELB,SP3	;INTO SP3
	CALLSB	SP.SB1,COUT	;QUEUE CONTROL OUT
;*****FOLLWING INSTRUCTION MUST BE IN PAGE 2 DUE TO RETURN FROM COUT****
KILLC1:
	BRWRTE	IMM,<D.RBDF-D.RDP> ;ADDRESS FLAGS BYTE
	LDMA	BR,ADD,SP6
	MEM	IMM,<DX.EOM!DX.LST>	;CLEAR ALL BUFFER ASSIGN FLAGS
	BRWRTE	IBUS,PORT4	;GET NEW PORT4 BACK
	BRSHFT
	BR4	BAIN0		;NEW BUFFER ASSIGNED
RQICR2:	ALWAYS	RQICL2		;NO NEW BUFFER
;******FOLLOWING INSTRUCTIONS MUST RESIDE IN PAGE TWO SINCE IT IS USED BY
.IIF LT	<<.-START/1000>-2>	.ERROR	;THE FOLLOWING LABELS ARE OFF PAGE 2
; CERTAIN SUBROUTINES TO RETURN TO THE PROPER PAGE OF CALLER******

;RETURN TO TIMER FROM RECEIVE ROUTINES
TIMRP2:	ALWAYS	TIMRTN
 
;RETURN FROM CONTROL OUT DUE TO A CALL FROM RERROR
RERRP2:	ALWAYS	ERREXT

;A RETURN FROM DECDCC DUE TO A CALL FROM RDDATA
DECP2:	ALWAYS	RDATA1
 
.IIF GT <<.-START-2>/1000>-2>	.ERROR ;THE ABOVE LABELS ARE OFF PAGE 2
	.SBTTL	XMTSYN - TRANSMIT SYNC'S OR ZERO BITS
;	FILE	XMTAUX.MAC
 
;+
; **XMTSYN-RESYNC TRANSMITTER REQUESTED**
;
; CALLED BY:	XMTDON
;
; INPUTS:
;	OUTPUT NPR ADDRESS = DUP'S CSR4
;	SP0 = FLAGS BYTE OF XMIT DESCRIPTOR
;	MAR = FLAGS BYTE OF XMIT DESCRIPTOR
;
; OUTPUTS:
;	BIT STUFF MODE - 16 ZERO BITS ARE TRANSMITTED
;	DEC MODE - SYNC CHARACTERS ARE TRANSMITTER
;-
 
XMTSYN:
	BRWRTE	SELA,SP.STS	;GET THE STATUS BYTE 
	BRSHFT			;SHIFT THE STATUS RIGHT
	BR4	80$		;DEC MODE (DDCMP)
	BRWRTE	IMM,0		;ZERO THE BRG
	OUTPUT	BR,SELB,OUTDA1	;ZERO THE LOW BYTE OF OUT DATA
	OUTPUT	IMM,DUPTSM!DUPTEM,OUTDA2	;SET BOTH START OF MESSAGE AND END OF MESSAGE
75$:	BRWRTE	IMM,377-DX.SYN	;MASK TO CLEAR RESYNC FLAG
	MEM	BR,AANDB,SP0	;CLEAR IT AND WRITE NEW FLAGS WORD TO RAM
	ALWAYS	WRTRT		;INCREMENT OUTPUT ADDRESS BY 2,
				;DO AN NPR AND RETURN TO TIMER LOOP
 
80$:	BRWRTE	IMM,SYNC	;GET SYNC CHARACTER
	OUTPUT	BR,SELB,OUTDA1,INCMAR	;WRITE IT TO LOW BYTE OF OUT DATA
	BRWRTE	IMM,DUPTSM	;START OF MESSAGE BIT
	OUTPUT	BR,SELB,OUTDA2,INCMAR	;WRITE IT TO HIGH BYTE
				;MAR IS NOW AT D.SYNC (SYNC COUNTER)
	SP	MEMX,SELB,SP1	;READ SYNC COUNTER INTO THE SCRATCH PAD
	MEM	DECA,SP1	;DECREMENT THE COUNT
	C	WRTRT		;COUNT NOT ZERO YET - DO THE NPR
				;AND RETURN TO THE POLLING LOOP
	BRWRTE	IMM,D.XBDF	;ADDRESS OF FLAGS BYTE IN XMIT DESCRIPTOR
	LDMA	BR,ADD,SP.RM0	;RESET THE MAR TO FLAGS BYTE
	ALWAYS	75$		;CLEAR RESYNC FLAG
	.SBTTL	XMTCNT - DECREMENT TRANSMIT BYTE COUNT
 
;+
;	**XMTCNT-DECREMENT XMIT COUNT RETURN
;	**XMTBCZ-ZERO BYTE COUNT**
;
; CALLED BY:	XMTDON
;
; INPUTS:
;	INPUT AND OUTPUT ADDRESS = DUP'S CSR 4
;	SP0 = D.XBDF (FLAGS BYTE)
;
; OUTPUTS:
;	RETURN TO XMTDON IF BYTE COUNT NOT ZERO.
;	ELSE: UNDERRUN CHECKED
;	EOM SENT IF SET IN BUFFER DESC
;	BUFFER ADDR OUT QUEUED.
;	IF ANOTHER BUFFER IS THERE, RETURN TO XMTDON TO XMIT
;	ELSE, RETURN TO TIMER
;-
 
; THE LABEL XMTCNT MUST RESIDE IN PAGE 2
.IIF NE <XMTCNT-START/1000-2>	.ERROR	;PAGE 2 RELOCATION ERROR - XMTCNT
 
; TRANSMIT DECREMENT COUNT ROUTINE RETURNS HERE
XMTCNT:	C	XMTDN2		;BYTE COUNT NOT ZERO
				;BYTE COUNT ZERO - FALL INTO XMTBCZ
	.ENABLE	LSB
XMTBCZ:
	BRWRTE	IBUS,INDAT2	;READ HIGH BYTE OF CSR4
	BR7	XMTUNR		;UNDERRUN
	BRWRTE	BR,SELA!SP0	;READ THE FLAGS WORD INTO THE BRG
	BR1	A160$		;END OF MESSAGE SET
XMTBC0:
100$:	CALLSB	SP.SB1,BAOX	;DO A BUFFER ADDRESS OUT COMPLETION
				;***NOTE*** BAOX MUST NOT DESTROY THE
				;OUTPUT BUFFER ADDRESS CURRENTLY SET AT
				;THE DUP'S CSR 4 OR 6
XMTBC1:
	BRWRTE	IMM,374		;RESET OUT BA TO POINT TO CSR4
	SP	IBUS,IOBA1,SP0	;READ OLD BA WHICH WAS CSR4 OR 6
	OUTPUT	BR,AANDB,OBA1	;SET CSR4 OFFSET
	BRWRTE	IMM,D.XBDF	;ADDRESS OF TRANSMIT FLAGS WORD
	LDMA	BR,<ADD!SP.RM0>	;POINT TO FLAGS WORD
	SPBR	MEMX,SELB,SP0	;READ THE FLAGS WORD TO THE BRG
	BROTAT			;ROTATE IT RIGHT
	BR4	XMTDN4		;ANOTHER BUFFER - SEND NEXT CHARACTER
 
; NO MORE BUFFER'S ASSIGNED.  IF THE PREVIOUS BUFFER HAD THE END OF MESSAGE
; FLAG SET THEN SHUT DOWN THE TRANSMITTER, OTHERWISE, WAIT FOR THE NEXT
; BUFFER OF THE MESSAGE TO BE ASSIGNED
 
	BR0	A170$		;END OF MESSAGE FLAG SET
	ALWAYS	TIMRT3		;NOT THE END OF MESSAGE - EXIT
	.SBTTL	XMTABT - TRANSMIT ABORT PENDING

;+
;	**XMTABT-TRANSMIT ABORT PENDING
;
; CALLED BY:	XMTDON
;
; INPUTS:
;	BRG	= XMIT STATUS (D.XSTS)
;	MAR	= D.XSTS
; OUTPUTS:
;	IF STAGE ONE, GOTO XMTAB1 TO TRANSMIT ABORT CHARS
;	STAGE TWO, CHECKS FOR ASSIGNED BUFFERS.
;	IF NONE, DUP SEND IS CLEARED.
;-
 
XMTABT:
	BR1	XMTAB1		;STAGE ONE OF ABORT PENDING
	MEM	IMM,0		;CLEAR ABORT PENDING FLAG
	BRWRTE	IMM,D.XBDF	;OFFSET TO TRANSMIT BUFFER FLAGS
	LDMA	BR,ADD,SP.RM0	;ADDRESS IT
	BRWRTE	MEMX,SELB	;READ THE FLAGS
	BRSHFT			;SHIFT THEM RIGHT
	BR4	XMTDN3		;BUFFER ASSIGNED, START NEXT MESSAGE
				;BUFFER NOT ASSIGNED, CLEAR SEND
120$:	SP	IMM,0,SP0	;MASK TO CLEAR SEND
				;FALL INTO XMTSND
	.SBTTL	XMTSND - SET OR CLEAR DUP SEND

;+
; **XMTSND-ROUTINE TO SET OR CLEAR SEND IN THE DUP
;
; CALLED BY:	XMTDON
; ENTERED FROM:	XMTABT
;
; INPUTS:
;	SP0 = MASK TO SET OR CLEAR SEND
;	SP.STS = D.STS
;
; OUTPUTS:
;	START NPR TO CHANGE SEND AND RETURN TO XMTDON
;
;-
 
XMTSND:
	BRWRTE	IMM,DS.HDX	;MASK FOR HALF DUPLEX
	BRWRTE	BR,AANDB,SP.STS	;ISOLATE HALF DUPLEX FLAG
	OUTPUT	BR,AORB,OUTDA1	;STORE "SEND" MASK IN OUT DATA LOW BYTE
XMTSN0:
	BRWRTE	IMM,DATOB	;MASK TO DO A BYTE OUT NPR
	ALWAYS	XMTDN6		;START THE NPR AND RETURN TO TIMER LOOP

 
;+
; END OF MESSAGE FLAG SET - SEND A EOM
; CALLED BY:	XMTBCZ
;-
 
A160$:	BRWRTE	IMM,DUPTEM	;SET TRANSMIT END OF MESSAGE
	OUTPUT	BR,SELB,OUTDA2	;SAVE FLAG IN OUT DATA HIGH BYTE
	CALLSR	SP.SUB,IC2OUT,XMTEM0	;WRITE IT OUT TO THE DUP
				;AND RETURN TO XMTBC0
 

;+
; END OF MESSAGE SET AND NO MORE BUFFER ASSIGNED - SEND PADS
;	THIS FILLS THE DUP SILO SO THE EOM CHAR GETS TO THE LINE
;	USE ABORT SEQUENCE TO SEND TWO PAD(377) CHARS.
; ENTERED FROM:	XMTBCZ
;-
 
A170$:	BRWRTE	IMM,D.XSTS	;ADDRESS TRANSMIT STATUS BYTE
	LDMA	BR,ADD,SP.RM0	;SET THE MAR
	MEM	IMM,DT.ABT!DT.AB1	;SET UP FOR AN ABORT
	ALWAYS	TIMRT3		;RETURN TO TIMER LOOP



;+
; UNDERRUN ERROR
; CALLED FROM:	XMTBCZ
;- 
XMTUNR:
	BRWRTE	IMM,ER.UNR	;TRANSMIT UNDERRUN ERROR CODE
	SP	BR,SELB,SP3	;SAVE IT IN SP3 FOR SUBROUTINE
	CALLSR	SP.SB1,COUX,XMTBC1,C.CLOX	;DO A CONTROL OUT
				;AND RETURN TO XMTBC1
	.DSABL	LSB
	.SBTTL	XMTAB1 - TRANSMIT ABORT STAGE ONE
;+
; **XMTAB1-ROUTINE TO PERFORM A TRANSMIT ABORT
;
; ENTERED FROM:	XMTABT
;
; INPUTS:
;	INPUT AND OUTPUT ADDRESS = DUP'S CSR 4
;	MAR = D.XSTS
;	SP0 = (D.XSTS)
;
; OUTPUTS:
;	D.XSTS IS DECREMENTED
;	AN ABORT CHARACTER IS SENT
;
;	D.XSTS LOW ORDER BITS WERE SET TO 11, XMTABT WILL BRANCH HERE IF
;	BIT 1 IS SET. THUS TWO ABORT CHARS GET SENT.
;-

XMTAB1:
	MEM	DECA,SP0	;ONE LESS ABORT TO SEND
	BRWRTE	IMM,DUPTAB	;DUP TRANSMIT ABORT BIT
	OUTPUT	BR,SELB,OUTDA2	;MOVE IT TO OUT DATA
	ALWAYS	WRTRT		;RETURN TO XMTDON TO DO THE NPR
	.PAGE
	.SBTTL	STORE-STORE RECEIVED CHARACTER IN CORE
;	FILE	DUPSTORE.MAC
 
;+ 
;
;	S T O R E  R E C E I V E D  C H A R A C T E R
; 
; ENTERED FROM:	RECEIVE STATE ROUTINES
; 
; INPUTS:
;	 SP.CHR=CURRENT RECEIVED CHARACTER
;
; OUTPUTS:
;	A WORD TRANSFER IS MADE TO THE USER BUFFER IN PDP-11 CORE WHEN
; A PAIR OF CHARACTERS ARE RECEIVED. ANY CHARACTER DESTINED FOR AN EVEN CORE
; BUFFER ADDRESS IS LOCALLY BUFFERED UNTIL THE NEXT CHARACTER IS RECEIVED.HOWEVER,
; BYTE TRANSFERS ARE SOMETIMES MADE DURING CERTAIN MESSAGE AND BUFFER BOUNDRY
; CONDITIONS.
;- 
 
STORE:
 
;CHECK IF A RECEIVE BUFFER IS AVAILABE
	BRWRTE	IMM,D.RBDF		;ADDRESS D.RBDF
	LDMA	BR,ADD,SP.RM0
	SPBR	MEMX,SELB,SP2		;LOAD IT INTO BR AND SP2
	BRSHFT
	BR4	10$			;BUFFER AVAILABLE
 
; A CHARACTER IS RECEIVED,BUT THERE IS NO RECEIVE BUFFER TO STORE IT
 
	BRADDR	TIMRP2		;ULTIMATE RETURN FROM RESYNC
	SP	BR,SELB,SP.SB1	;SAVE IT IN RETURN SCRATCH PAD
	CALLSR	SP.SUB,COUTX,RESYNC,ER.NBA ;Q PORT DATA AND RETURN TO TIMER
;NOTE: A REGULAR CONTROL OUT IS NOT SENT BECAUSE IT MODIFIES PDP-11
;MEMORY ADDRESSED BY CURRENT DESCRIPTOR POINTER. SINCE THE DESCRIPTOR
;POINTER IS INVALID AT THIS TIME, THIS IS PROHIBITED.

10$:
; DECREMENT RECEIVE BYTE COUNT
 
	CALLSB	SP.SUB,DRCNT
; NOTE: DRCNT DECREMENTS THE BYTE COUNT AND STORES IT BACK INTO RAM. 
 
	C	CHKODD		;BRANCH IF COUNT NOT -1
 
;CURRENT BUFFER IS FULL,SO SEND BA OUT ETC BEFORE PROCESSING CURRENT CHARACTER
EOFBUF:
	SPBR	MEMX,SELB,SP2	;GET THE LOW BYTE OF THE BUFFER ADDRESS
	BR0	5$		;BUFFER ENDED ON AN ODD ADDRESS THEREFORE
				;THE LAST RECEIVE CHARACTER IS STILL IN THE
				;KMC RAM AND IT MUST BE WRITTEN OUT
;
; OTHERWISE ALL RECEIVE DATA HAVE BEEN WRITTEN TO THE BUFFER
;
	ALWAYS	10$
;
5$:
	CALLSB	SP.SUB,SETRBA	;SET OUTBA TO CURRENT INPUT ADDRESS IN REC BUFF
	BRWRTE	BR,DECA,SP2	;BUFFER ADDRESS MUST BE DECREMENTED TO POINT
				;TO EVEN BYTE ADDRESS
	OUTPUT	BR,SELB,OBA1	;RESET IT
	BRWRTE	IMM,DATOB,INCMAR	;MASK TO DO A BYTE TRANSFER
					;MAR NOW POINT TO D.ERC
	OUTPUT	MEMX,SELB,OUTDA1	;GET THE EVEN RECEIVE CHARACTER
	OUT	BR,SELB,ONPR		;START THE NPR
10$:
	BRADDR	STORE		;SET UP RETURN ADDRESS TO STORE
	SP	BR,SELB,SP.SB1
20$:	BRWRTE	IBUS,NPR	;IN CASE AN NPR WAS STARTED WAIT FOR IT TO COMPLETE
	BR0	20$		;WAIT UNTIL DONE
	ALWAYS	BAORC	;SEND BAOUT FOR RECEIVE BUFFER COMPLETEION
;NOTE: ORIGINAL INPUT PARAMETERS TO STORE MUST BE INTACT AT THIS POINT
; CHECK IF CURRENT RECEIVE BUFFER ADDRESS IS ODD
CHKODD:
 
	BRWRTE	MEMX,SELB	;GET LOW BYTE OF BUFFER ADDR INTO BR
				;MAR NOW POINT TO HIGH ADDR BYTE
	BR0	STRODD		;BRANCH IF RECEIVE BUFFER ADDRESS IS ODD
;		 CURRENT RECEIVE BUFFER ADDRESS IS EVEN
 
 
STREVN:
;
; SP2 CONTAINS THE IMAGE OF D.RBDF
; MAR POINTS TO LOW BYTE OF BUFFER ADDRESS
;
 
	INCMA			;MAR NOW POINTS TO HIGH BYTE OF ADDRESS
; CLEAR "FIRST CHARACTER IN BUFFER" INDICATOR
 
	BRWRTE	IMM,<377-DR.FST>,INCMAR ;MASK TO CLEAR DR.FST
				;MAR POINT TO FLAGS BYTE
	MEMINC	BR,AANDB,SP2	;CLEAR DR.FST
				;MAR POINTS TO D.ERC
 
; STORE THE CURRENT RECEIVE CHARACTER IN LOCAL BUFFER
 
	MEM	SELA,SP.CHR	;STORE REC'D CHARACTER IN D.ERC
 
 
	ALWAYS	RCVEXT
;		CURRENT RECEIVE BUFFER ADDRESS IS ODD
 
 
STRODD:
;
; SP2 CONTAINS THE IMAGE OF D.RBDF
; MAR POINTS TO LOW BYTE OF RECEIVE BUFFER ADDRESS
 
	CALLSB	SP.SUB,SETRBA	;SET OUTBA TO CURRENT INPUT ADDRESS IN REC BUFF
 
; LOAD ODD (CURRENT) CHARACTER INTO OUTDATA HB
 
	BRWRTE	BR,SELA,SP.CHR,INCMAR	;MOVE CHARACTER INTO BR FIRST
					;MAR NOW POINTS TO D.ERC
	OUTPUT	BR,SELB,OUTDA2	;NOW MOVE IT INTO OUTDATA 15:8
	OUTPUT	MEMX,SELB,OUTDA1	;LOAD EVEN RECEIVE CHARACTER INTO OUTDATA 7:0
; CHECK IF THE CURRENT ODD CHARACTER IS DESTINED FOR FIRST LOCATION OF BUFFER
 
	BRWRTE	MEMX,SELA,SP2	;LOAD IMAGE OF D.RBDF INTO BR
	BR0	10$		;BRANCH IF FIRST CHARACTER OF BUFFER
 
; CURRENT CHARACTER IS DESTINED FOR ODD CORE ADDRESS AND IS NOT THE FIRST
;CHARACTER IN THE BUFFER. THEREFORE IT IS SAFE TO DO A WORD TRANSFER.
 
	BRWRTE	IMM,DATO	;MASK TO START WORD OUT NPR
	ALWAYS	20$		;DO NPR AND EXIT
;NOTE: DURING THE ABOVE WORD NPR, THE CORE ADDRESS IS ODD. THE HARDWARE SHOULD
;AUTOMATICALLY IGNORE BIT0 OF CORE ADDRESS.
 
 
; CURRENT RECEIVED CHARACTER IS DESTINED FOR AN ODD CORE ADDRESS.
;BUT THIS ADDRESS HAPPENS TO BE THE FIRST LOCATION OF THE CURRENT BUFFER.
;THEREFORE DO A BYTE TRANSFER.
 
10$:
 
	BRWRTE	IMM,DATOB	;MASK TO SEND ONE BYTE(ODD CHARACTER)
20$:
	OUT	BR,SELB,ONPR	;START NPR
				;NOTE: NPR COMPLETION IS CHECKED FOR AFTER
				;RETURN FROM INCMEM
 
;FALL INTO RCVEXT
 
;		COMMON EXIT FROM STORE ROUTINE
 
 
RCVEXT:
 
;INCREMENT RECEIVE BUFFER POINTER
 
; ADDRESS D.RBDA
 
	BRWRTE	IMM,D.RBDA
	LDMA	BR,ADD,SP.RM0
 
; INCREMENT MEMORY LOCATIONS
 
	CALLSR	SP.SUB,INCMEM,NPRWP1,1	;INCREMENT MEMORY & RETURN 
					;TO WAIT FOR NPR COMPLETION
	.SBTTL	EOFMSG-END OF MESSAGE
 
;+ 
; 
;		E N D  O F  R E C E I V E D  M E S S A G E
; 
; CALLED BY:	RBDONE(BIT STUFF), MSGIN(DDCMP)
; 
;INPUTS:
;	SP.SB1=RETURN ADDRESS
;	D.RBD=CURRENT INPUT ADDRESS
;OUTPUTS:
;	STORES IN RECEIVE BUFFER ANY RESIDUAL EVEN CHARACTER THAT IS SAVED
;	IN THE LOCAL BUFFER (D,ERC)
;	GENERATES A BAOUT. ULTIMATE RETURN TO LOCATION SPECIFIED BY SP.SB1
;-
 
EOFMSG:
 
;CHECK IF THE LAST RECEIVED CHARACTER WAS EVEN
 
	BRWRTE	IMM,D.RBDA	;SET TO POINT TO BUFFER ADDRES
	LDMA	BR,ADD,SP.RM0	;SET THE MAR
	SPBR	MEMX,SELB,SP2	;READ THE LOW BYTE OF THE ADDRESS
	BR0	10$		;BRANCH IF ODD
; CURRENT RECEIVE BUFFER IS EVEN,THAT MEANS LAST RECEIVED CHARACTER WAS
;DESTINED FOR AN ODD ADDRESS AND ALREADY BEEN TRANSFERED TO RECEIVE
;BUFFER.
 
	ALWAYS	BAORE		;SEND BAOUT
 
;CURRENT RECEIVE BUFFER ADDRESS IS ODD. THEREFORE THE PREVIOUS CHARACTER
;DESTINED FOR AN EVEN ADDRESS IS STORED LOCALLY. TRANSFER IT TO CORE
 
10$:
 
	CALLSB	SP.SUB,SETRBA	;SET RECEIVE BUFFER ADDRESS
	BRWRTE	DECA,SP2,INCMAR	;DECREMENT ADDRESS TO GET EVEN BYTE
				;MAR POINTS TO D.ERC
	OUTPUT	BR,SELB,OBA1	;PUT ADDR IN THE OBA REG
	OUTPUT	MEMX,SELB,OUTDA1	;LOAD EVEN CHAR INTO OUT DATA
	BRWRTE	IMM,DATOB	;WRITE OUT RESIDUAL EVEN RECEIVED
	OUT	BR,SELB,ONPR	;INTO CORE
20$:	BRWRTE	IBUS,NPR	;AND WAIT FOR NPR TO COMPLETE
	BR0	20$
 
;FALL INTO BAORE
	.SBTTL	BAORE-BA OUT FOR END OF RECEIVED MESSAGE
 
;+ 
; 
;	B A  O U T  F O R  E N D  O F  R E C E I V E D  M E S S A G E
; 
; ENTERED FROM:	EOFMSG
; 
;INPUTS:
;	SP.SB1=RETURN ADDRESS
; 
;OUTPUTS:
;	INPUT PARAMETERS FOR BOUT ARE SET UP
;	BOUT IS EXECUTED
;-

BAORE:
 
;SET SP3 TO INDICATE END OF MESSAGE
 
	BRWRTE	IMM,EOM
	SP	BR,SELB,SP3
 
;SET SP2 TO INDICATE BAOUT FOR RECEIVE OPERATION
 
	BRWRTE	IMM,C.BAOR

; FOLLOWING CODE IS SHARED WITH THE ERROR ROUTINES IN DUPERR
ENTRY2:
	SP	BR,SELB,SP2
;SET SP6=ADDRESS OF D.RDP
	BRWRTE	IMM,D.RDP	;BR=D.RDP
	BRWRTE	BR,<ADD!SP.RM0>	;BR=ADDRESS OF D.RDP/D.XDP
	SP	BR,SELB,SP6	;SP6=BR
 
;FALL INTO BOUT/COUT
 
	.SBTTL	BOUT/COUT-BA OR CONTROL OUT (WITH DESCRIPTOR UPDATED)
 
;+ 
; 
;		B A  O R  C O N T R O L  O U T
;		(CURRENT DESCRIPTOR IS UPDATED)
; 
; THIS IS COMMON CODE SHARED BY THOSE BAOUT ROUTINES AND  CONTROL OUT 
;ROUTINES THAT REQUIRE AN UPDATE OF BYTE COUNT IN THE RECEIVE OR TRANSMIT 
;DESCRIPTORS.
; 
; ENTERED FROM:	BAORE
; CALLED BY:	KILLAL
; 
;INPUTS:
;	SP.SB1	-RETURN ADDRESS.
;	SP2	-CODE TO INDICATE BAOUT OR CONTROL OUT (KMC CSR2 IMAGE)
;	SP3	-ERROR CODE
;	SP6	-ADDRESS OF D.RDP(RECEIVE) OR D.XDP(TRANSMIT)
; 
;OUTPUTS:
;	BYTE COUNT IN THE CURRENT TRANSMIT OR RECEIVE DESCRIPTOR IS UPDATED
;BY SUBTRACTING THE CONTENTS OF D.RBDC OR D.XBDC FROM IT.
;SP4,SP5,SP6 ARE LOADED WITH THE CURENT DESCRIPTOR ADDRESS AND QPDATA
;ROUTINE IS EXECUTED.
;- 
 
BOUT:
COUT:
 
;SET OUBA TO CURRENT DESCRIPTOR
 
	LDMA	SELA,SP6		;ADDRESS DESCRIPTOR ADDRESS POINTER
	OUTPUT	MEMI,SELB,OBA1		;ADDRESS 7:0
	OUTPUT	MEMI,SELB,OBA2		;ADDRESS 15:8
	SP	IBUS,UBBR,SP0		;GET CURRENT BUS REQ REG
	BRWRTE	IMM,101			;CLEAR ALL BUT VEC XX4,NXM
	SP	BR,AANDB,SP0
	SP	MEMX,SELB,SP1		;GET FLAGS BYTE (MEM EXT BITS) **V0.10**
	BRWRTE	IMM,14			;EXTRACT MEM EXT BITS
	BRWRTE	BR,AANDB,SP1		;MASK OFF ALL OTHER BITS
	OUT	BR,AORB,OBR		;LOAD EXT ADDRESS BITS
;SUBTRACT CURRENT BYTE COUNT FROM ORIGINAL BYTE COUNT TO GET # OF CHARACTERS
;RECEIVED/TRANSMITTED IN THIS BUFFER
	BRWRTE	IMM,<D.ORBC-D.RDP>	;ADDRESS ORIGINAL BUFFER COUNT
	LDMA	BR,ADD,SP6
	SP	MEMI,SELB,SP0		;AND SAVE IT IN SP0
	SP	MEMX,SELB,SP1		;AND HIGH BYTE INTO SP1
	BRWRTE	IMM,<D.RBDC-D.RDP>	;ADDRESS CURRENT COUNT
	LDMA	BR,ADD,SP6
	OUTPUT	MEMI,SUB,OUTDA1		;OUTDA1=ORG 7:0-CUR7:0
	BRWRTE	MEMI,SUBC,SP1		;BR=ORG15:8-CUR15:8
	OUTPUT	BR,SELB,OUTDA2,INCMAR	;STORE IT IN OUTDATA 1 **V0.11**
 
;OUTDATA NOW CONTAINS THE NUMBER OF CHARACTERS TRANSFERED FROM/TO
;THE CURRENT BUFFER
; WRITE IT INTO CURRENT DESCRIPTOR
	BRADDR	BOUTR0			;RETURN ADDRESS INTO BR **V0.11**
	SP	BR,SELB,SP.SUB,INCMAR	;SAVE IN SP.SUB (MAR = FLAGS)
	BRWRTE	MEMX,SELB		;READ FLAGS
	BRSHFT				;SHIFT RIGHT
	BR4	IC2OUT			;IF BUFFER ASSIGNED, WRITE NEW BC
	ALWAYS	QPDATA			;OTHERWISE DON'T (CAN GET HERE FROM
					;KILL CODE WITH NO BUFFER ASSIGNED) **V0.11**
 
;CURRENT DESCRIPTOR IS NOW COMPLETELY UPDATED

	.SBTTL	BAORC-BA OUT FOR RECEIVE BUFFER COMPLETION
 
;+ 
; 
;	B A  O U T  F O R  R E C E I V E  B U F F E R  C O M P L E T I O N
; 
; CALLED BY:	STORE
;
;INPUTS:
;	SP.SB1=RETURN ADDRESS
; 
;OUTPUTS:
;	INPUT PARAMETERS FOR COUX ARE SET UP
;	COUX IS EXECUTED
;-

BAORC:
 
;SET SP3 TO INDICATE END OF MESSAGE
 
	BRWRTE	IMM,0
	SP	BR,SELB,SP3
 
;SET SP2 TO INDICATE BAOUT FOR RECEIVE OPERATION
 
	BRWRTE	IMM,C.BAOR
	SP	BR,SELB,SP2
 
; SET SP6=ADDRESS OF D.RDP
	BRWRTE	IMM,D.RDP	;BR=D.RDP
	ALWAYS	ENTRY1		;USE COMMON CODE IN COUX
	.SBTTL	COUTX-CONTROL OUT FOR TRANSMIT OPERATION
 
;+ 
; 
;	C O N T R O L  O U T  F O R  X M T  O P E R A T I O N S
; 
; CALLED BY:	DSRCHG,STORE,NXMERR
; 
;INPUTS:
;	SP.SUB=RETURN ADDRESS
;	BRG	=ERROR CODE
;OUTPUTS:
;	A CONTROL OUT IS QUEUED WITH THE BUFFER DESCRIPTOR ADDRESS ZEROED.
;- 
 
COUTX:
	SP	BR,SELB,SP3	;SAVE ERROR CODE IN SP3
	SPBR	IMM,0,SP0	;SET UP SCRATCH PADS FOR QPDATA
	SP	BR,SELB,SP1	;..
	SP	BR,SELB,SP4	;..

;SET SP2 TO INDICATE CONTROL OUT FOR XMT OPERATION
	BRWRTE	IMM,C.CLOX	;CSR2 IMAGE INTO SP2
	SP	BR,SELB,SP2
	ALWAYS	QPDAT1		;QUEUE THE CONTROL OUT
	.SBTTL	BAOX/COUX-BA/CONTROL OUT FOR TRANSMIT BUFFER COMPLETION
;+ 
; 
;	B A  O U T  F O R  X M T  B U F F E R  C O M P L E T I O N
; 
;CALLED BY:	XMTBCZ
; 
;INPUTS:
;	SP.SB1=RETURN ADDRESS
; 
;OUTPUTS:
;	INPUT PARAMETERS FOR QPDATA ARE SET UP
;	A BUF ADDR OUT IS QUEUED.
;-

BAOX:
 
;SET SP3 TO INDICATE BUFFER COMPLETION
 
	BRWRTE	IMM,0
	SP	BR,SELB,SP3
 
;SET BRG TO INDICATE BA OUT FOR TRANSMIT OPERATION
 
	BRWRTE	IMM,C.BAOX
;	FALL INTO COUX


;+
; **COUX-ROUTINE TO QUEUE A TRANSMIT CONTROL OUT WITH BUFFER ADDRESS**
;
; CALLED BY:	XMTUNR
; ENTERED FROM:	BAOX
;
; INPUTS:
;	SP.SB1 = RETURN ADDR
;	SP3 = ERROR CODE
;	BRG = BSEL2 CODE (NORMALLY C.CLOX)
;
; OUTPUTS:
;	PARAMETERS FOR QPDATA ARE SET UP
;	SO A COMPLETION WILL BE QUEUED TO THE PDP-11
;-

COUX:
	SP	BR,SELB,SP2	;PUT BSEL2 CODE IN SP2
 
;SET SP6=ADDRESS OF D.XDP
	BRWRTE	IMM,D.XDP	;BR=D.XDP

;COMMON CODE, USED BY BAORC ALSO
ENTRY1:
	BRWRTE	BR,ADD,SP.RM0	;BR=ADDRESS OF D.RDP/D.XDP
	SP	BR,SELB,SP6	;SP6=BR
 
;	FALL INTO QPDATA
 
	.SBTTL	QPDATA-QUEUE PORT DATA
 
;+ 
; 
;	Q U E U E  P O R T  D A T A
; 
; ENTERED AT QPDATA FROM:	BOUT,COUX
; ENTERED AT QPDAT1 FROM:	COUTX
; 
; INPUTS:
;	SP.SB1=RETURN ADDRESS
;	SP.LN=LINE NUMBER
;	SP2=CLO(R/T) TO SEND CONTROL OUT,=BAO(R/T) TO SEND BAOUT
;	SP3	=ERROR CODE WITH THE ERROR BIT SET
;	SP6	=ADDRESS OF D.RDP/D.XDP
;OUTPUTS:
;	SIX BYTES OF CONTROL OUT DATA IS STUFFED INTO THE LOCAL COMPLETION SILO.
;	ENTRY AT QPDATA: CALLER'S RETURN IN SP.SB1, EXECUTE STFSLO AND NXBUF
;	ENTRY AT QPDAT1: CALLER'S RETURN IN SP.SUB, EXECUTE STFSLO AND RETURN
;-
 
QPDATA:
	BRADDR	NXBUF		;ADDRESS FOR STUFF SILO TO RETURN TO
	SP	BR,SELB,SP.SUB	;SAVE IT IN RETURN SCRATCH PAD
 
;GET CURRENT DESCRIPTOR ADDRESS INTO SCRATCH PADS
 
	LDMA	SELA,SP6	;ADDRESS CURRENT DESCRIPTOR POINTER
	SP	MEMI,SELB,SP0	;SP0=ADDRESS 7:0
	SP	MEMI,SELB,SP1	;SP1=ADDRESS 15:8
	SP	MEMX,SELB,SP4	;SP4=ADDRESS 17:16
 
; ADDRESS 'NEXT IN' LOCATION IN LOCAL SILO
 
QPDAT1:
	LDMA	IMM,P.SLIN	;ADDRESS NEXT IN POINTER
	LDMAP	IMM,P.SLIN
	LDMA	MEMX,SELB	;ADDRESS LOCATION POINTED TO BY P.SLIN
 
;STORE BYTE 0 WORD 1 INTO SILO
 
	MEMINC	SELA,SP.LN	;LOAD LINE NUMBER
	MEMINC	SELA,SP0	;LOAD DESCRIPTOR ADDRESS 7:0
	MEMINC	SELA,SP1	;LOAD DESCRIPTOR ADDRESS 15:0
	MEM	SELA,SP3	;STORE ERROR CODE (FOR CONTROL OUT ONLY)
	BRWRTE	SELA,SP2	;BUT IS THIS A CONTROL OUT?
	BR0	10$		;YES
	MEM	IMM,0		;NO,CLEAR ERROR CODE
	ALWAYS	20$
10$:	BRWRTE	IMM,0		;CONTROL OUT,CLEAR SP3
	SP	BR,SELB,SP3
20$:
	SP	TWOA,SP4,INCMAR	;SHIFT EXT ADDRESS LEFT TO POSITION
	SP	TWOA,SP4
	SP	TWOA,SP4
	SPBR	TWOA,SP4
	MEMINC	BR,AORB,SP3 	;STORE EOM BIT AND EXT MEM BITS IF BA OUT
	MEMINC	SELA,SP2	;CONTROL OUT OR BAOUT CODE
;FALL INTO STUFF SILO ROUTINE
 
	.SBTTL	STFSLO-STUFF COMPLETION SILO SUBROUTINE
 
;+ 
;
;		S T U F F  C O M P L E T I O N  S I L O				
;										
; ENTERED FROM:	QPDATA
; 
; INPUTS:
;	SP.SB1=ULTIMATE RETURN ADDRESS
;	SP.SUB=RETURN FOR STUFF SILO
; 
;	THE THREE SILO WORDS MUST ALREADY BE IN RAM STARTING AT LOCATION 
;	POINTED TO BY P.SLIN.
;
; OUTPUTS:
;	SILO POINTERS ARE UPDATED. IF THERE WAS A SILO OVERFLOW,BIT 16 OF
;	THE FIRST WORD IS SET TO 1.
;-
 
STFSLO:
 
; CHECK IF SILO IS EMPTY OR FULL
 
	LDMA	IMM,<P.SLIN>		;GET NEXT IN
	SP	MEMI,SELB,SP0		;INTO BR,SP0
	BRWRTE	MEMX,SELB		;AND NEXT OUT INTO THE BR
	Z	30$			;SILO IS EMPTY
	COMP	BR,SP0			;NEXTIN=NEXT OUT?
	Z	40$			;YES,SILO IS FULL
 
; SILO IS NOT FULL
 
; INCREMENT NEXT IN BY ONE ENTRY LENGTH
10$:
	LDMA	IMM,<P.SLIN&377>	;MAR=ADDRESS OF NEXT IN POINTER
	BRWRTE	IMM,SILOED		;OFFSET OF LAST ENTRY
	COMP	BR,SP0			;NEXT IN=LAST ENTRY IN SILO?
	Z	20$			;YES,WRAP NEXT IN
	BRWRTE	IMM,SENTRY		;BR=ONE ENTRY SIZE
	MEM	BR,ADD,SP0		;INCREMENT P.SLIN BY ONE ENTRY SIZE
	RTNSUB	SP.SUB,P3		;RETURN
 
; WRAP NEXT IN
20$:	MEM	IMM,P.NPR		;SET NEXT IN=P.NPR
	RTNSUB	SP.SUB,P3
; SILO IS EMPTY,SET NEXT OUT=NEXT IN
 
30$:	MEM	SELA,SP0		;STORE NEXT IN P.SLOT
	ALWAYS	10$			;STORE ONE ENTRY
 
; SILO IS FULL, SET ERROR BIT IN CURRENT NEXT IN RAM LOCATION
 
40$:
	LDMA	SELA,SP0		;LOAD MAR TO ADDRESS SILO ENTRY
	SP	IMM,200,SP0		;LOAD ERROR CODE MASK
	MEM	MEMX,AORB,SP0		;OR OVERRUN BIT ONTO LINE NUMBER
	RTNSUB	SP.SUB,P3
	.SBTTL	NXBUF-GET NEXT  BUFFER
 
;+
;			N E X T  B U F F E R
;
; ENTERED FROM:	STFSLO
;
; INPUTS:
;	SP.SB1	=RETURN ADDRESS
;	SP6	=ADDRESS OF D.RDP OR D.XDP
;	
; OUTPUTS:
;	1) CURRENT  DESCRIPTOR POINTER  IS MODIFIED TO POINT
;	TO THE NEXT DESCRIPTOR IN THE CURRENT LIST
;	2) IF NO MORE DESCRIPTORS ARE AVAILABLE IN THE CURRENT LIST, 
;	D.RDP/D.XDP IS SET TO POINT TO THE FIRST DESCRIPTOR IN THE ALTERNATE LIST.
;	THE "ALTERNATE LIST ASSIGNED" BIT IS CLEARED
;	3) IF THE ALTERNATE LIST IS NOT ASSIGNED IN THE ABOVE CASE,THE"CURRENT
;	LIST ASSIGNED" BIT IS CLEARED.
;	4) IF THE NEW DESCRIPTOR IS THE LAST ONE IN ITS LIST THE "LAST DESCRIPTOR
;	IN LIST" INDICATOR IS SET.
;
;	THIS ROUTINE; CHECKS IF CURRENT DESCRIPTOR IS LAST ON LIST
;	IF SO, BRANCH TO NXLST
;	OTHERWISE, ADD 6 TO LIST POINTER AND GOTO NXDSCP TO LOAD DESC
;-

NXBUF:
 
; CHECK IF THE CURRENT BUFFER DESCRIPTOR IS THE LAST ONE IN THE CURRENT LIST
 
	BRWRTE	IMM,<D.RBDF-D.RDP>	;ADDRESS FLAG BYTE
	LDMA	BR,ADD,SP6
	LDMAP	SELA,SP.RM1		;SINCE STUFF SILO CHANGED PAGE
	SPBR	MEMX,SELB,SP0		;LOAD FLAG BYTE INTO BR,SP0
	BR7	NXLST			;LAST DESCRIPTOR IN LIST,GET NEXT LIST
 
;	CURRENT BUFFER DESCRIPTOR IS NOT THE LAST ONE IN THE LIST
;ADD 6 TO CURRENT DESCRIPTOR ADDRESS TO GET THE NEXT DESCRIPTOR ADDRESS
	LDMA	SELA,SP6		;ADDRESS CURRENT DESCRIPTOR POINTER
	CALLSR	SP.SUB,INCMEM,NXDP1,6.	;CALL TO INCRE PNTR BY 6
					;RETURN TO NXDSCP

	.SBTTL	NXLST-GET NEXT BUFFER LIST
 
;+ 
; 
;			N E X T  L I S T
; 
; ENTERED FROM:	NXBUF
; 
; INPUTS:
;	SP.SB1	=RETURN ADDRESS
;	MAR,MARP=D.RBDF OR D.XBDF
;	SP0	=CONTENTS OF D.RBDF OR D.XBDF
;	SP6	=ADDRESS OF D.RBD OR D.XBD
; 
; OUTPUTS:
;	CHECK IF ALTERNATE LIST IS ASSIGNED
;	IF NOT, CLEAR BUFFER ASSIGNED BIT AND RETURN
;	IF SO, CLEAR ALTERNATE ASSIGNED BIT AND UPDATE CURRENT LIST PNTR
;	DROP INTO NXDSCP TO LOAD NEW DESC INTO LINE TABLE.
;-

NXLST:
 
; CHECK IF THE ALTERNATE LIST IS ASSIGNED
;	(MAR=D.RBDF FOR REC OR D.XBDF FOR XMT,SP0=ITS CONTENTS
 
	BRWRTE	TWOA,SP0	;LEFT SHIFT 
	BR7	10$		;BRANCH IF ALTERNATE LIST IS ASSIGNED
 
; ALTERNATE LIST IS NOT ASSIGNED. CLEAR 'CURRENT BUFFER ASSIGNED BIT AND RETURN
 
	BRWRTE	IMM,<377-DR.CBA> ;MASK TO CLEAR DR.CBA
	MEM	BR,AANDB,SP0	;CLEAR IT AND STORE RESULT IN D.RBDF/D.XBDF/
;*************ONE OF THE RETURN POINTS FOR BA,CONTROL ETC.**********
	RTNSUB	SP.SB1,P2	;RETURN
;********************************************************************
 
 
; ALTERNATE LIST IS ASSIGNED.
10$:
 
;CLEAR 'ALTERNATE LIST ASSIGNED' BIT
	BRWRTE	IMM,<377-DR.ABA> ;MASK TO CLEAR DS.ABA
	MEM	BR,AANDB,SP0	;STORE IT IN RAM
 
;MOVE ALTERNATE LIST POINTER INTO CURRENT DECRIPTOR POINTER
	BRWRTE	IMM,<D.ARLP-D.RDP> ;OFFSET FROM CURRENT DESCRIPTOR POINTER
	LDMA	BR,ADD,SP6	;ADDRESS ALTERNATE POINTER
	SP	MEMI,SELB,SP0	;SP0=ADDRESS 7:0
	SP	MEMI,SELB,SP1	;SP1=ADDRESS 15:8
	SP	MEMI,SELB,SP2	;SP2=ADDRESS 17:16
	LDMA	SELA,SP6	;ADDRESS CURRENT POINTER
	MEMINC	SELA,SP0	;STORE ADDRESS 7:0
	MEMINC	SELA,SP1	;STORE ADDRESS 15:8
	MEM	SELA,SP2	;AND EXT ADDRESS
				;FALL INTO NXDSCP
	.SBTTL	NXDSCP - GET NEXT DESCRIPTOR

;+
;
;	**NXDSCP-ROUTINE TO LOAD THE NEXT DESCRIPTOR INTO LINE TABLE
;
; ENTERED FROM:	NXLST
; CALLED FROM:	BAIN
;
;INPUTS:
;	SP6=ADDRESS OF THE CURRENT DESCRIPTOR FOR CURRENT OPERATION (ADDRESS
;	OF D.RDP OR D.XDP)
;
; OUTPUTS:
;	THE NEW DESCRIPTOR IS FETCHED FROM PDP-11 MEMORY AND STORE IN THE LINE TABLE.
;	IF A TRANSMIT BUFFER, ANY ODD LEADING CHARACTER IS PREFETCHED
;	IF A RECEIVE BUFFER, THE FIRST CHARACTER FLAG(DR.FST) IS SET
;-

NXDSCP:
 
;SET INBA TO THE CURRENT DESCRIPTOR ADDRESS
	LDMA	SELA,SP6	;ADDRESS CURRENT DESCRIPTOR POINTER
	OUTPUT	MEMI,SELB,IBA1	;ADDRESS 7:0
	OUTPUT	MEMI,SELB,IBA2	;ADDRESS 15:8
	BRWRTE	IMM,1		;START NPR 
	SP	BR,SELB,SP0
	OUT	MEMI,AORB,ONPR	;ADRESS 17:16
 
 
;MOVE NEW BUFFER ADDRESS AND BYTE COUNT INTO ORIGINAL BUF ADDRESS AND COUNT AREA
 
5$:	BRWRTE	IBUS,NPR	;WAIT FOR BUFFER ADDRESS 15:0
	BR0	5$
	SP	IBUS,INDAT1,SP4,INCMAR	;TEMPORARILY SAVE ADD 7:0 IN SP4
	SP	IBUS,INDAT2,SP5,INCMAR	;AND ADDRESS 15:8 IN SP5
	CALLSB	SP.SUB,IC2IN	;READ BYTE COUNT FROM DESCRIPTOR
	SP	IBUS,INDAT1,SP2,INCMAR	;SAVE LOW BYTE IN SP2
	SP	IBUS,INDAT2,SP3	;AND HIGH COUNT IN SP3
;MAR IS NOW POINTING TO D.ORBC/D.OXBC
	MEMINC	IBUS,INDAT1	;SAVE LOW BYTE OF COUNT
	MEMINC	IBUS,INDAT2	;SAVE HIGH BYTE OF COUNT
	MEMINC	SELA,SP4	;NOW STORE DESCP ADDRESS 7:0
	MEMINC	SELA,SP5	;AND ADDRESS 15:8 IN RAM
 
; UPDATE EXTENDED ADDRESS BITS OF BUFFER & LAST DESCRIPTOR BIT
	CALLSB	SP.SUB,IC2IN	;READ NEXT DESCRIPTOR WORD
	SP	IBUS,INDAT2,SP0	;LOAD HIGH BYTE (FLAGS,EXT ADDR)INTO SP0
	MEMINC	IBUS,INDAT2	;SAVE FLAGS BYTE
	MEMINC	SELA,SP2	;SAVE LOW BYTE OF COUNT
	MEMINC	SELA,SP3	;SAVE HIGH BYTE
	MEMINC	SELA,SP4	;SAVE BUFFER ADDRESS IN CURRENT AREA
	MEMINC	SELA,SP5
	SP	MEMX,SELB,SP2	;SAVE OLD FLAGS IN SP2
	BRWRTE	IMM,<DR.CBA!DR.ABA>	;STRIP ALL BUT THESE
	BRWRTE	BR,AANDB,SP2	;AND LOAD IT NTO BR
	MEM	BR,AORB,SP0	;OR IN NEW FLAGS
 
;CHECK IF RECEIVE OR TRANSMIT OPERATION
	BRWRTE	IMM,D.RDP	;SET BR TO
	BRWRTE	BR,ADD,SP.RM0	;RAM ADDRESS OF D.RDP
;IF THIS IS A RECEIVE OPERATION,SP6 WILL BE EQUAL TO THIS VALUE
	COMP	BR,SP6		;BR=SP6?
	Z	NXRBUF		;SP6=ADDRESS OF D.RDP,RECEIVE OPERATION

;TRANSMIT OPERATION,DO SPECIAL THINGS FOR IT
;READ READ CHARACTER INTO D.OXC IF THE FIRST BUFFER ADDRESS IS ODD
	BRWRTE	DECA,SP4,INCMAR	;SP4 HAS LOW BYTE OF BUFFER ADDRESS
	BR0	30$		;ADDRESS IS EVEN
;FIRST TRANSMIT BUFFER ADDRESS IS ODD,MOVE FIRST CHARACTER INTO D.OXC
10$:
	OUTPUT	BR,SELB,IBA1	;SET ADR 7:0 OF XMT BUFFER
	BRWRTE	SELA,SP5	;SP5 HAS ADR 15:8
	OUTPUT	BR,SELB,IBA2	;SET ADDRESS 15:8
	BRWRTE	IMM,BIT3!BIT2	;MASK TO ISOLATE EXT ADDRESS
	SP	BR,AANDB,SP0	;SP0=EXT ADDRESS
	OUT	INCA,ONPR	;START NPR (SP0 HAS EXT ADDRESS)
20$:	BRWRTE	IBUS,NPR	;WAIT FOR NPR TO COMPLETE
	BR0	20$
30$:
; MAR IS NOW POINTING TO D.OXC
	MEMINC	IBUS,INDAT2		;SAVE ODD CHARACTER
	MEMINC	IMM,SYNCNT		;RESET SYNC COUNT
;RAISE REQUEST TO SEND IF IT IS NOT ALREADY SET
	BRWRTE	SELA,SP.CS0		;RTS SET?
	BRSHFT
	BR1	NXBEXT			
	MEM	IMM,0			;CLEAR ABORT FLAGS **V0.7**
	BRWRTE	IMM,DUPRTS	;SET RTS
	SPBR	BR,AORB,SP.CS0	;OR MASK WITH ORIGINAL DUP REGISTER
	OUTPUT	BR,SELB,OUTDA1	;SHIP IT INTO DUP REGISTER
	CALLSB	SP.SUB,ADRCSR	;ADDRESS DUP
;************ ULTIMATE RETURN FOR BA & CONTROL OUT*************
 
NXBEXT:	RTNSUB	SP.SB1,P2	;RETURN
 
;***************************************************************
 
;ASSIGNING RECEIVE BUFFER,SET FIRST CHR IN BUFFER
NXRBUF:
	BRWRTE	IMM,DR.LST!DR.ABA!DR.CBA!DR.17!DR.16	;CLEAR IRRELEVANT BITS *V0.7*
	SP	MEMX,SELB,SP0	;SP0=FLAGS
	SP	BR,AANDB,SP0	;SAVE THE RELEVANT BITS *V0.7*
	.IIF	NE	DR.FST-1	.ERROR 	;INCA NO LONGER SETS DR.FST
	MEM	INCA,SP0	;SET FIRST CHR IN BUFFER FLAG
	RTNSUB	SP.SB1,P2
;NOTE: RECEIVER WAS ENABLED AT CONTROL TIME
	.SBTTL	ERROR PROCESSING ROUTINES

;+
; **DUPRER-ERROR DETECTED BY DUP OR MICROCODE ON THE RECEIVER
;
; ENTERED FROM:	RCVDON
;
; INPUTS:
;	MAR = RECEIVE STATE POINTER
; OUTPUTS:
;	CONTROL OUT IS GENERATED.
;	FALL INTO RESYNC AND RETURN TO TIMER ROUTINE
;-

; DUP HARDWARE DETECTED RECEIVE ERROR
 
DUPRER:
 
; DUP HARDWARE HAS DETECTED AN ERROR ON RECEIVED CHARACTER. ANALYZE IT.
 
	BR4	ERR12		;CRC ERROR
	BRWRTE	TWOA,SP.RST	;SHIFT RECEIVE STATUS LEFT
	BR7	OVRUN		;CHARACTER OVERRUN
;
; OTHERWISE MUST BE ABORT
;
ABORT:
 
	BRWRTE	IMM,ER.ABO		;ERROR CODE
	ALWAYS	RERROR			;SEND A CONTROL OUT

; 
; INVALID DDCMP HEADER BCC
; ENTERED FROM:	RHCRC2
; 
ERR10:
 
	BRWRTE	IMM,ER.HBC	;ERROR CODE INTO BR
	ALWAYS	RERROR		;EXECUTE COMMON ERROR SUBROUTINE
 
; 
; BCC ERROR ON RECEIVED MESSAGE
; ENTERED FROM:	DUPRER,RDCRC2 
ERR12:
 
	BRWRTE	IMM,ER.CRC	;ERROR CODE INTO BR
	ALWAYS	RERROR		;COMMON ERROR CODE
 
 
; CHARACTER OVERRUN
 
OVRUN:
 
	BRWRTE	IMM,ER.OVR	;ERROR CODE
				;FALL INTO RERROR
;SEND CONTROL OUT
 
RERROR:
 
	SP	BR,SELB,SP3	;ERROR CODE INTO SP3
	CALLSR	SP.SB1,ENTRY2,RERRP2,C.CLOR ;CONTROL OUT SUB ROUTINE
ERREXT:				;RETURN HERE AFTER SUBROUTINE
;	FALL INTO RSNCRT
	.SBTTL	RSNCRT - RESYNC AND RETURN TO TIMER
;+
;
;	**RSNCRT-RESYNC RECEIVER AND RETURN TO TIMER POLLING LOOP
;
; ENTERED FROM:	DUPRER,RDH1,MSGIN
;
; INPUTS:	NONE
; OUTPUTS:
;	SET UP RETURN TO TIMER THEN FALL INTO RESYNC
;-

RSNCRT:
	BRADDR	TIMRP2		;RETURN TO TIMER VIA PAGE 2
	SP	BR,SELB,SP.SB1
;	ALWAYS	RESYNC		;AFTER RESYNCING THE RECEIVER
; FALL INTO RESYNC
	.SBTTL	RESYNC-RESYNC DUP-11 RECEIVER
 
;+
;	R E S Y N C  D U P-1 1  R E C E I V E R
;
; ENTERED FROM:	RSNCRT
; CALLED BY:	ERREXT,KILLRC,STORE
; 
;INPUTS:
;	SP.SB1=RETURN ADDRESS
;	SP.CS0=RECEIVE STATUS REGISTER LOW BYTE
;OUTPUTS:
;	CURRENT DUP-11 RECEIVER ENABLE BIT IN ITS RECEIVE STATUS REGISTER
;	IS CLEARED.IT IS THEN SET THUS INITIALIZING DUP RECEIVER LOGIC.
;	RECEIVER STATE POINTER IS RESET.
;	RETURN TO ADDRESSES IN PAGE TWO
;-
 
RESYNC:
 
;CLEAR RECEIVE ENABLE BIT
	LDMAP	SELA,SP.RM1		;SET UP PAGE ADDRESS
	BRWRTE	IMM,<377-DUPREN>
	SPBR	BR,AANDB,SP.CS0	 	;LOAD ORIGINAL STATUS WITH RCV ENABLE
	OUTPUT	BR,SELB,OUTDA1	;BIT CLEARED INTO OUTDA1
	CALLSB	SP.SUB,ADRCSR	;SET UP OUT BA TO DUP'S CSR AND DO A
				;BYTE NPR
 
;NOW SET RECEIVE ENABLE BIT
 
	BRWRTE	IMM,DUPREN	;MASK TO SET REC ENABLE BIT
	SPBR	BR,AORB,SP.CS0	;MASK IN THE ORIGINAL STATUS
	OUTPUT	BR,SELB,OUTDA1	;AND RECEIVE ENABLE BIT INTO OUTDA1
	BRWRTE	IMM,DATOB	;WRITE IT INTO 
	OUT	BR,SELB,ONPR	;RECEIVE STATUS REGISTER
;	***NPR STARTED***
; RESET RECEIVE PARAMETERS
	BRWRTE	MEMX,SELB,INCMAR	;BR=D.STS,ADDRESS D.RPTR
 
;RESET RECEIVE STATE POINTER FOR DDCMP/BITSTUFF
 
	RSTATE	RDH1		;SET DDCMP INTIAL RECEIVE STATE
	BRSHFT
	BR4	20$		;BRANCH IF DEC MODE
	RSTATE	RB1		;SET BIT STUFF INITIAL STATE
20$:	BRWRTE	IBUS,NPR	;WAIT FOR PREVIOUS NPR TO COMPLETE
	BR0	20$		;NOT YET
	RTNSUB	SP.SB1,P2	;RETURN TO PAGE 2
	.SBTTL	SETRBA-SET OUTBA TO CURRENT INPUT ADDRESS IN USER RECEIVE BUFFER
 
;+
; 	SET OUTBA TO CURRENT INPUT ADDRESS IN RECEIVE BUFFER
;
; CALLED BY:	STORE,STRODD,EOFMSG
;
; INPUTS:
;	SP.SUB = RETURN ADDRESS ON PAGE 2
;	MAR = D.RBDA
; OUTPUTS:
;	OBA,OBR	= ADDRESS POINTED TO BY MAR
;	MAR	= D.RBDF
;-
 
SETRBA:
 
	OUTPUT	MEMI,SELB,OBA1	;SET OUTBA 7:0
	OUTPUT	MEMI,SELB,OBA2	;SET OUTBA 15:0
	SP	IBUS,UBBR,SP0	;SP0=BUS REQUEST REGISTER
	BRWRTE	IMM,101		;MASK TO CLEAR ALL BUT VEC XX4,NXM BITS
	SP	BR,AANDB,SP0
	BRWRTE	IMM,14		;MASK TO CLEAR UNWANTED BITS IN EXT. ADDRESS
	SP	BR,SELB,SP1	;SAVE THE MASK IN SP1
	BRWRTE	MEMX,AANDB,SP1	;BR=JUST THE EXT ADR
	OUT	BR,AORB,OBR	;OR IN THE EXT ADDRESS
	RTNSUB	SP.SUB,P2	;RETURN TO PAGE 2
	.SBTTL	DECDCC-DECREMENT DDCMP DATA CHARACTER COUNT
 
;+ 
; 
;	D E C R E M E N T  D D C M P  D A T A  C H A R A C T E R  C O U N T
; 
; CALLED BY:	RDDATA
; 
;INPUT:
;	SP.SUB=RETURN ADDRESS
;OUTPUT:
; DDCMP DATA CHARACTER COUNT FOR THE CURRENT MESSAGE IS DECREMENTED BY ONE.
;	C BIT IS SET IF AND ONLY IF THE NEW BYTE COUNT IS NOT -1
;	COMMON CODE IN DECNT IS USED.
;- 
 
DECDCC:
 
;ADDRESS DDCMP DATA CHARACTER COUNT SAVE AREA IN RAM
	BRWRTE	IMM,D.DCC1
	ALWAYS	DECNT		;EXECUTE COMMON CODE
	.SBTTL	DRCNT/DECNT-DECREMENT BUFFER COUNT
 
;+ 
; 
;	D E C R E M E N T  B U F F E R  B Y T E  C O U N T
; 
; CALLED BY:	STORE
; DECNT CALLED BY:	XMTDON
; 
;INPUT:
;	SP.SUB=RETURN ADDRESS
;OUTPUT:
;	BYTE COUNT FOR THE CURRENT LINE IS DECREMENTED BY ONE
;	C BIT IS SET IF AND ONLY IF THE NEW BYTE COUNT IS NOT -1
;	MAR IS LEFT POINTING TO ADDRESS FOLLOWING BYTE COUNT
;
; SCRATCH PADS USED:	SP1,SP.RM0,SP.SUB
;-
 
DRCNT:
 
; ADDRESS RECEIVE BYTE COUNT SAVE AREA (D.RBDC)
	BRWRTE	IMM,D.RBDC

;
; FOLLOWING CODE IS SHARED BY DECDCC AND DRCNT.
; INPUTS:	BRG = LINE TABLE OFFSET OF BYTE COUNT
;
 
DECNT:
	LDMA	BR,ADD,SP.RM0	
	SP	MEMX,SELB,SP1	;GET LOW BYTE COUNT INTO SP1
	MEMINC	DECA,SP1	;DECREMENT IT AND WRITE IT BACK
	Z	10$		;BRANCH IF ZERO
	INCMA			;INCREMENT PAST HIGH BYTE OF COUNT
	RTNSUB	SP.SUB,P2	;RETURN TO CALLLER

; BORROW FROM HIGH BYTE, DECREMENT HIGH BYTE
10$:	SP	MEMX,SELB,SP1	;GET HIGH BYTE INTO SP1
	MEMINC	DECA,SP1	;DECREMENT IT AND STORE IT BACK
	RTNSUB	SP.SUB,P2	;RETURN
	.SBTTL	INCOUT/IC2OUT/INCOB-OUT NPR TO CURRENT ADDRESS+OFFSET
 
;+ 
;
;		INCREMENT OUTBA AND OUTPUT  SUBROUTINE	
;
; CALLED BY: (INCOB):	BAIN
;            (IC2OUT):	CONIN,XMTBCZ,COUT
; 
; INPUTS:
;	BR	=INCREMENT
;	SP.SUB	=RETURN ADDRESS
;	ENTRY POINTS INCOUT,IC2OUT,INCOB
; 
; OUTPUTS:
;	THE DEVICE ADDRESS (OUT BA 17:0) FOR AN OUT NPR OPERATION
; IS INCREMENTED BY A FACTOR EQUAL TO THE CONTENTS OF BR.
; THEN A BYTE OR WORD TRANSFER WITH OR WITHOUT BUSHOLD IS PERFORMED DEPENDING
; ON THE ENTRY POINT.
; RETURNED TO THE ADDRESS IN CURRENT PAGE SPECIFIED BY SP.SUB
; BUSHOLD ENTRYS REMOVED BECAUSE OF INTERFERENCE PROBLEMS
; 
; REGISTERS USED:
;	BR,UBBR,SP0,SP1,SP.SUB
; 
; REGISTERS DESTROYED (OR CHANGED)
;	BR,UBBR,SP0,SP1
;- 
 
; ENTRY POINT TO DO BYTE NPR WITHOUT BUS HOLD
INCOB:
	SP	IMM,221,SP1	;MASK TO DO BYTE OUT NPR ***TRICKY INSTR***
	ALWAYS	INCOT1		;COMMON CODE


;ENTRY TO INCREMENT BY 2 AND DO WORD TRANSFER
IC2OUT:
	BRWRTE	IMM,2

 
; ENTRY TO DO WORD TRANSFER WITHOUT BUS HOLD
INCOUT:
	SP	IMM,21,SP1	;MASK TO DO WORD OUT NPR ****TRICKY INSTR***
 
INCOT1:
; INCREMENT OUTBA 7:0
 
	SP	IBUS,IOBA1,SP0	;READ OUTBA7:0 INTO SP0
	OUTPUT	BR,ADD,OBA1	;ADD INCREMNT AND RESTORE(SP0 IS SELECTED
 
; INCREMENT OUTBA 15:0
 
10$:	SP	IBUS,IOBA2,SP0	;READ OUTBA15:8 INTO SP0
	OUTPUT	BR,APLUSC,OBA2	;ADD CARRY TO OUTBA15:8(SP0 SELECTED)
	C	30$		;CARRY,INCREMENT EXTENDED ADDRESS
20$:	ALWAYS	40$		;NPR AND RETURN
 
; INCREMENT OUTBA 17:16
30$:	SP	IBUS,UBBR,SP0	;LOAD UBBR INTO DP0
	BRWRTE	IMM,4		;ADD ONE TO EXT. ADDRESS
	SP	BR,ADD,SP0	
	BRWRTE	IMM,115		;MASK TO SET CLOCK BIT=0
	OUT	BR,AANDB,OBR	;STORE UPDATED VALUE INTO UBBR

;NOW DO THE NPR
40$:
	SP	IBUS,NPR,SP0	;GET NPR REGISTER INTO SP0
	BRWRTE	IMM,155		;STRIP NPR CONTROL BITS
	BRWRTE	BR,AANDB,SP0	;SAVE RESULTS IN BR
	BRWRTE	BR,AORB,SP1	;OR IN THE NEW NPR CONTROL BITS
	OUT	BR,SELB,ONPR	;LOAD THE NEW BYTE INTO NPR REGISTER

; WAIT FOR NPR TO COMPLETE
WAIT:
10$:	BRWRTE	IBUS,NPR	;WAIT FOR NPR TO COMPLTE
	BR0	10$
	RTNSUB	SP.SUB,P0
	.SBTTL	ADRCSR-SET OUTBA=DUP'S CSR ADDRESS
 
;+ 
; 
;		SET OUTBA TO DUP CSR
;
; CALLED BY:	NXDSCP, RESYNC
;
;INPUTS:
;	SP.SUB	=RETURN ADDRESS
;	OUTDA1 = VALUE TO BE WRITTEN TO DUP'S CSR0
;OUTPUTS:
;	OUTBA=ADDRESS OF CURRENT DUP
;	START A BYTE NPR TO CSR0 AND WAIT FOR ITS COMPLETION
;	MAR = D.STS
;-
 
ADRCSR:
	BRWRTE	IMM,D.CSR	;ADDRESS D.CSR
	LDMA	BR,ADD,SP.RM0
	OUTPUT	MEMI,SELB,OBA1	;SET OUTBA 7:0
	OUTPUT	MEMI,SELB,OBA2	;SET OUTBA 15:8
	SP	IBUS,UBBR,SP0	;GET BUS REQ REG
	BRWRTE	IMM,101		;KEEP VEC XX4,NXM BITS
	SP	BR,AANDB,SP0
	BRWRTE	IMM,14		;SET EXT ADDRESS BITS
	OUT	BR,AORB,OBR	;SP0 IMPLIED FOR B SIDE
	BRWRTE	IMM,DATOB	;BYTE OUT NPR MASK
	OUT	BR,SELB,ONPR	;START THE NPR
	ALWAYS	INCIN1		;RETURN VIA SP.SUB,P3
				;USE CODE IN INCIN
 



;*** PAGE 3 RETURN TO TIMER FOR RECEIVE ROUTINES ***
.IIF NE	<TIMRP3-START/1000-3>	.ERROR	;PAGE 3 RELOCATION ERROR TIMRP3
TIMRP3:	ALWAYS	TIMRTN		;RETURN TO POLLING LOOP FROM DSRCHG
	.SBTTL	NXTTBL - ROUTINE TO CALCULATE THE ADDRESS OF THE NEXT TABLE
;	FILE	SUBR.MAC
 
;+
; **-NXTTBL-CALCULATE RAM ADDRESS OF NEXT LINE'S TABLE**
;
; CALLED FROM:	INIT
;
; INPUTS:
;	SP.RM0-1 = PREVIOUS RAM TABLE ADDRESS
;
; OUTPUTS:
;	MAR AND SP.RM0-1 ARE SET TO ADDRESS OF NEXT TABLE ENTRY
;-
NXTTBL:
	BRWRTE	IMM,D.LNG	;GET THE LENGTH OF A RAM TABLE ENTRY
	SP	BR,ADD,SP.RM0,LDMAR	;POINT TO NEXT ENTRY AND LOAD MAR
	NODST	BR,ADD,SP.RM0	;WOULD THIS LINE TABLE CROSS A PAGE BOUNDARY?
	C	10$		;YES, MAKE IT START AT THE BEGINNING OF THE
				;NEXT PAGE
	LDMAP	SELA,SP.RM1		;LOAD MAR HIGH
	ALWAYS	INIT1		;BACK TO INITIALIZE LOOP

10$:	SP	APLUSC,SP.RM1,LDMAPG	;INCREMENT THE PAGE NUMBER AND LOAD
				;MAR HIGH
	BRWRTE	IMM,0		;ZERO THE BRG
	SP	BR,SELB,SP.RM0,LDMAR	;ZERO THE LOW 8 BITS OF THE MAR AND
				;SP.RM0
	ALWAYS	INIT1		;BACK TO INITIALIZE LOOP
	.SBTTL	INCIN/INCINH/IC2IN - EIGHTEEN BIT ADD TO INPUT ADDRESS
;+
; **INCIN/INCINH-ROUTINE TO DO 18 BIT TO THE INPUT ADDRESS**
;
; CALLED BY: (IC2IN):	NXDSCP
;
; CALLING SEQUENCE:
;	CALLSB	SP.SUB,INCIN,ADDEND	;ADD "ADDEND" TO IN BA AND DO
;					;AN NPR WITH BUS HOLD CLEAR
;	CALLSB	SP.SUB,INCINH,ADDEND	;ADD "ADDEND TO IN BA AND DO
;					;AN NPR WITH BUS HOLD SET
;	CALLSB	SP.SUB,IC2IN		;ADD 2 TO IN BA AND DO AN NPR
;					;WITH BUS HOLD CLEAR
;					;N.B. CALLING SEQUENCE IS ONE INSTR LESS
;
; INPUTS:
;	INPUT BUFFER ADDRESS MUST BE SET UP IN THE I/O BUS INCLUDING
;	THE EXTENDED MEMORY BITS IN THE NPR CONTROL REGISTER
;
;	BRG = ADDEND
;
; OUTPUTS:
;	THE INPUT ADDRESS IS INCREMENTED BY THE BRG CONTENTS, THE NPR IS STARTED
;	AND THE ROUTINE WAITS FOR IT TO COMPLETE.
;	NOTE: BUS HOLD OPTIONS NOT USED TO PREVENT INTERFERENCE WITH OTHER
;	 UNIBUS DEVICES.
;-
	.ENABL	LSB

;*******************************
;INCINH:	SP	IMM,0,SP1	;WRITE A ONE TO SP 1 ***** TRICKY INSTRUCTION ****
;	SP	BR,INCA,SP1	;MAKE IT A TWO IN ORDER TO MASK ON BUS HOLD BIT
;	ALWAYS	5$		;TO COMMON CODE
;***** ABOVE CODE NOT USED******
 
IC2IN:	BRWRTE	IMM,2		;MOST COMMON INCREMENT VALUE
				;FALL INTO INCIN
INCIN:
;**************
;	SP	IMM,1,SP1	;WRITE A ONE TO SCRATCH PAD ONE **** TRICKY INSTR.****
;				;LEAVES BIT 1 A ZERO TO MASK OFF BUS HOLD
;**************

5$:	SP	IBUS,IIBA1,SP0	;GET THE CURRENT LOW BYTE OF THE INPUT ADDRESS
	OUTPUT	BR,ADD,IBA1	;NEW LOW BYTE OF INPUT ADDRESS
	SP	IBUS,IIBA2,SP0	;GET THE HIGH BYTE OF THE INPUT ADDRESS
	OUTPUT	APLUSC,IBA2	;ADD ANY CARRY FROM PREVIOUS ADD TO HIGH BYTE
	SP	IBUS,NPR,SP0	;GET THE NPR REGISTER CONTENTS
	C	50$		;A PLUS C CAUSED A CARRY TO EXTENDED MEMORY BITS
30$:	BRWRTE	IMM,16		;MASK TO EXT. MEM. BIT OVERFLOW
	SP	BR,AANDB,SP0	;MASK OFF UNWANTED BITS
	OUT	BR,INCA,ONPR	;START THE NPR

; THE FOLLOWING CODE SHARED WITH ADRCSR
INCIN1:
40$:	BRWRTE	IBUS,NPR	;READ THE NPR CONTROL REGISTER
	BR0	40$		;WAIT FOR THE NPR TO FINISH
	RTNSUB	SP.SUB,P3	;RETURN TO CALLER
 
50$:	BRWRTE	IMM,4		;VALUE TO ADD TO INCREMENT EXTENDED MEMORY
	SP	BR,ADD,SP0	;ADD TO PREVIOUS EXTENDED MEM BITS
	ALWAYS	30$		;BRANCH TO COMMON CODE
	.DSABL	LSB
	.SBTTL	INCMEM - EIGHTEEN BIT ADD TO ADDRESS POINT TO BY MAR
;+
; **INCMEM-18 BIT ADD TO RAM**
;
; CALLED BY: (INCMEM):	RCVEXT, NXBUF
;             (INCMM):	XMTDON
;
; CALLING SEQUENCE:
;	CALLSB	SP.SUB,INCMEM,ADDEND
;		OR
;	CALLSB	SP.SUB,INCMM	;TO INCREMENT MEMORY BY STATE OF "C" BIT
;
; INPUTS:
;	MAR = ADDRESS IN RAM OF LOW BYTE TO DO ADD
;	BRG = ADDEND
; INPUTS TO INCMM:
;	MAR = SAME AS ABOVE
;	"C" BIT SET OR CLEAR
; OUTPUTS:
;	RESULT IS IN RAM
;	MAR = ORIGINAL MAR + 2
;
;	USES SCRATCH PAD 0
;-

INCMEM:	SP	BR,SELB,SP0	;MOVE ADDEND TO SP 0
	MEMINC	MEMX,ADD,SP0	;ADD TO LOW BYTE OF RAM
INCMM:
	SP	MEMX,SELB,SP0	;MOVE HIGH BYTE FROM RAM TO SP0
	MEMINC	BR,APLUSC,SP0	;ADD CARRY FROM LOW BYTE
	C	10$		;LAST ADD CAUSE CARRY TO EXTENTED MEMORY BITS
	RTNSUB	SP.SUB,P1	;ALL DONE
10$:	SP	MEMX,SELB,SP0	;READ EXTENDED MEMORY BITS
				;IN POSITIONS 2 & 3
	BRWRTE	IMM,4		;INCREMENT EXTENDED MEMORY BITS
	MEM	BR,ADD,SP0	;ADD "ONE" OF HIGH ORDER BITS
	RTNSUB	SP.SUB,P1	;RETURN TO CALLER
	.SBTTL	NXMERR - NONEXISTENT MEMORY ERROR
;+
; **NXMERR-MICROPROCESSOR HAS DETECTED A NONEXISTENT MEMORY ERROR**
;
; CALLED BY:	RDICLR, TIMER
;
; OUTPUTS:
;	CONTROL OUT IS GENERATED
;	N.B. THE NXM ERROR IS CHECKED ONLY AFTER SERVICING A USER
;	REQUEST  (RQI) AND AFTER SERVICING A DUP NOT AFTER EACH
;	NPR. THUS THE ONLY RELEVANT INFORMATION IS THE LINE NUMBER.
;-

NXMERR:
	BRWRTE	IMM,100		;MASK TO PRESERVE STATE OF XX4 BIT
	OUT	BR,AANDB,OBR	;CLEAR NXM ERROR BIT
	CALLSB	SP.SUB,COUTX,ER.NXM	;POST THE ERROR
	ALWAYS	IDLE		;BACK TO IDLE LOOP




	.SBTTL	PATCH - PATCH AREA
;+
; **PATCHA - PATCH MSGIN
; ENTERED FROM:	MSGIN
; INPUTS:
;	BRG	= SP.STS SHIFTED LEFT ONE
; OUTPUTS:
;	GOTO RSNCRT IF Q-SYNC SET (LS.QSC)
;	GOTO TIMRTN IF NOT
;-

PATCHA:	BR7	RSNCRT		;RESYNC RECEIVER AND RETURN TO TIMER
	ALWAYS	TIMRTN		;RETURN TO TIMER

	$KDPML==.-$KDPMC+63./64.		;NUMBER OF 32 WORD BLOCKS
	.END