*	BUFFER CONTROL DEFINITION
*	NOTE: RING BUFFERS ARE 256 BYTES LONG, ORG'D TO PAGE BOUNDARIES

	ORG	0
SDNETBUF:EMPTY	RMB	2	POINTER TO NEXT BYTE TO TAKE FROM RING BUFFER
SDNETBUF:FILL	RMB	2	POINTER TO NEXT BYTE TO PLACE IN RING BUFFER
SDNETBUF:CBSIZE	EQU	*
*	SD NET NODE REPRESENTATIVE BLOCK

	ORG	0
SDNETNRB:XBUFLK	RMB	1	TRANSMIT BUFFER LOCK
SDNETNRB:TIMEQFLINK	RMB	2	FORWARD LINK TO NEXT NRB IN ORDER LIST
SDNETNRB:TIMEQBLINK	RMB	2	BACKWARD LINK TO PREVIOUS NRB IN ORDER LIST
SDNETNRB:TIMEQDELTA	RMB	1	DELAY DELTA FROM NRB(BLINK)
SDNETNRB:RCVBUF	RMB	SDNETBUF:CBSIZE	CONTROL BLOCK FOR RECEIVE BUFFER
SDNETNRB:XMTBUF	RMB	SDNETBUF:CBSIZE	CONTROL BLOCK FOR TRANSMIT BUFFER
SDNETNRB:NODE	RMB	1	NODE NUMBER BEING REPRESENTED
SDNETNRB:STATE	RMB	1	NODE STATE
SDNETNRB:RETRY	RMB	1	NUMBER OF TIMEOUTS TO CONCLUDE DEAD
SDNETNRB:XVPOS	RMB	2	TRANSMIT VIRTUAL POSITION (MODULO 2**16)
SDNETNRB:RVPOS	RMB	2	RECEIVED VIRTUAL POSITION (MODULO 2**16)
SDNETNRB:RCVDRDY	RMB	2	LAST RCVDREADY COUNT
SDNETNRB:GOOF	RMB	1	SET THIS TO HOLLER "GOOF!!!"
SDNETNRB:TCB	RMB	TCB:SIZE	LISTENER'S TCB
SDNETNRB:TCBSTACK	RMB	20+MINSTACK	STACK SPACE FOR LISTENER TASK
SDNETNRB:STACKBASE	RMB	1	BASE OF STACK FOR LISTENER TASK FOR THIS NRB
SDNETNRB:SIZE	EQU	*
	PAGE
*	NODE STATES

	ORG	0
NODESTATE:DEAD	RMB	1	REPRESENTED NODE IS DEAD
NODESTATE:AGREEQUIT	RMB	1	REPRESENTED NODE SENT "WANTQUIT"
NODESTATE:WANTQUIT	RMB	1	NEED TO DISCONNECT FROM REPRESENTED NODE
NODESTATE:INACTIVE	RMB	1	REPRESENTED NODE IS INACTIVE
NODESTATE:ACTIVATING	RMB	1	WE ARE TRYING TO ESTABLISH CONTACT WITH REPRESENTED NODE
NODESTATE:RESYNCHED	RMB	1	REPRESENTED NODE SENT "RESYNCH"
NODESTATE:ACTIVATED	RMB	1	REPRESENTED NODE SENT "RESYNCHED"
NODESTATE:CONNECTEDR	RMB	1	REPRESENTED NODE IS CONNECTED; WE EXPECT TO RECEIVE NEXT
NODESTATE:CONNECTEDS	RMB	1	REPRESENTED NODE IS CONNECTED; WE'RE EXPECTED TO SEND NEXT
NODESTATE:QUIT	RMB	1	WE MUST SEND "QUIT" MSG TO REPRESENTED NODE


*	SDLP CONTROL FIELD

SDLPCONTROL:NORMAL	EQU	0	NORMAL SDLP MESSAGE
SDLPCONTROL:RESYNCHREQ	EQU	1	RE-SYNCHRONIZE REQUEST
SDLPCONTROL:RESYNCHED	EQU	2	RE-SYNCHRONIZED RESPONSE
SDLPCONTROL:WANTQUIT	EQU	3	WANTS TO QUIT
SDLPCONTROL:AGREEQUIT	EQU	4	AGREES TO QUIT
SDLPCONTROL:QUIT	EQU	5	QUIT!
SDLPCONTROL:RESYNCHQUIT	EQU	6	RESYNCHRONIZE, HAVE DATA, AND QUIT
*
*	NETWORK CONFIGURATION CONTROL BLOCKS
*
	ORG	0
NETCNFG:ADLC	RMB	2	POINTER TO SDNET ADLC DEVICE
NETCNFG:BUFFERSPACE	RMB	2	POINTER TO NET BUFFER SPACE
NETCNFG:BUFFEREND	RMB	2	POINTER TO END OF NET BUFFER SPACE
NETCNFG:NSOCKETS	RMB	1	NUMBER OF SOCKETS TO SET UP
NETCNFG:NNRBS	RMB	1	NUMBER OF NRBS TO SET UP
NETCNFG:NRBINDEXSIZE	RMB	1	= SIZE OF NRB LOOKUP TABLE
	PAGE
	PAGE	SD'S LINE PROTOCOL DRIVER FOR ADLC
*	LINK CONTROL TUNING PARAMETERS

	IFUND	SDNETRETRYCOUNT	HOW MANY TIMES TO TRY BEFORE DECLARING DEAD NODE
SDNETRETRYCOUNT	EQU	100
	FIN

	IFUND	SDNETEOTFUSETIME	HOW LONG TO WAIT BEFORE GIVING UP END OF MESSAGE SEARCH
SDNETEOTFUSETIME	EQU	4	60THS OF A SECOND
	FIN

	IFUND	SDNETRETRYTIME	HOW LONG TO WAIT BEFORE RETRANSMITTING OUR MESSAGE
SDNETRETRYTIME	EQU	15	60THS OF A SECOND
	FIN

	IFUND	SDNETRESPONDTIME	HOW LONG TO WAIT BEFORE RESPONDING TO A MESSAGE JUST RECEIVED
SDNETRESPONDTIME	EQU	3
	FIN

	IFUND	SDNETXMTBUFOVFTHRESHOLD	NUMBER OF BUFFER BYTES INDICATING IMMINENT BUFFER FULL CONDITION
SDNETXMTBUFOVFTHRESHOLD	EQU	200
	FIN

	IFUND	SDNETXMITTHRESHOLD	HOW MANY DATA BYTES ARE NEEDED FOR SDNET PACKET TO BE EFFICIENT
SDNETXMITTHRESHOLD	EQU	100	= 5 * MESSAGE OVERHEAD IN BYTES
	FIN

	IFUND	SDNETMSGDATASIZEMAX
SDNETMSGDATASIZEMAX	EQU	256	SPACE FOR MESSAGE BODY
	FIN
	PAGE
*	SDNET ADLC REGISTER DISPLACEMENTS
*
SDNETADLCSR1	EQU	0##14	STATUS REGISTER # 1 DISPLACEMENT
SDNETADLCSR2	EQU	1##14	STATUS REGISTER # 2 DISPLACEMENT
SDNETADLCRDR	EQU	2##14	RECEIVER DATA REGISTER
SDNETADLCCPUID	EQU	3##14	CPU IDENTITY ON NETWORK
SDNETADLCCR1	EQU	0##14	CONTROL REGISTER # 1
SDNETADLCCR2	EQU	1##14	CONTROL REGISTER # 2
SDNETADLCCR3	EQU	1##14	CONTROL REGISTER # 3
SDNETADLCTDCD	EQU	2##14	TRANSMITTER DATA (CONTINUE DATA)
SDNETADLCTDLD	EQU	3##14	TRANSMITTER DATA (LAST DATA)
SDNETADLCCR4	EQU	3##14	CONTROL REGISTER # 4
*
*	ADLC CONTROL/STATUS BIT DEFINITIONS
*
ADLCCR1TXRS	EQU	%10000000	TRANSMITTER RESET
ADLCCR1RXRS	EQU	%01000000	RECEIVER RESET
ADLCCR1DISCONTINUE	EQU	%00100000	RX FRAME DISCONTINUE
ADLCCR1TDSRMODE	EQU	%00010000	TRANSMITTER DATA SERVICE REQUEST MODE
ADLCCR1RDSRMODE	EQU	%00001000	RECEIVER DATA SERVICE REQUEST MODE
ADLCCR1TIE	EQU	%00000100	TRANSMITTER INTERRUPT ENABLE
ADLCCR1RIE	EQU	%00000010	RECEIVER INTERRUPT ENABLE
ADLCCR1AC	EQU	%00000001	ADDRESS CONTROL

ADLCCR1SELCR2	EQU	%00000000	ADDRESS CONTROL BIT TO SELECT CR2
ADLCCR2RTS	EQU	%10000000	REQUEST TO SEND CONTROL
ADLCCR2CLRTXST	EQU	%01000000	CLEAR TRANSMITTER STATUS
ADLCCR2CLRRXST	EQU	%00100000	CLEAR RECEIVER STATUS
ADLCCR2TXLAST	EQU	%00010000	TRANSMIT LAST DATA
ADLCCR2FCTDRASELECT	EQU	%00001000	FRAME COMPLETE/TDRA SELECT
ADLCCR2FMIDLE	EQU	%00000100	FLAG/MARK IDLE SELECT (F/M IDLE)
ADLCCR221BYTE	EQU	%00000010	2 BYTE/1 BYTE TRANSFER
ADLCCR2PSE	EQU	%00000001	PRIORITIZED STATUS ENABLE
	PAGE
ADLCCR1SELCR3	EQU	%00000001	ADDRESS CONTROL BIT TO SELECT CR3
ADLCCR3LOCDTR	EQU	%10000000	LOOP ON-LINE CONTROL/DTR CONTROL
ADLCCR3GAPTST	EQU	%01000000	GO ACTIVE ON POLL/TEST
ADLCCR3LOOP	EQU	%00100000	LOOP/NON-LOOP MODE
ADLCCR3FDSE	EQU	%00010000	FLAG DETECT STATUS ENABLE
ADLCCR30111IDLE	EQU	%00001000	01/11 IDLE
ADLCCR3AEX	EQU	%00000100	AUTO/ADDRESS EXTEND MODE
ADLCCR3CEX	EQU	%00000010	EXTENDED CONTROL FIELD SELECT
ADLCCR3LCF	EQU	%00000001	LOGICAL CONTROL FIELD SELECT

ADLCCR1SELCR4	EQU	%00000001	ADDRESS CONTROL BIT TO SELECT CR4
ADLCCR4NRZINRZ	EQU	%10000000	NRZI (ZERO COMPLEMENT)/NRZ SELECT
ADLCCR4ABTEX	EQU	%01000000	ABORT EXTEND
ADLCCR4ABT	EQU	%00100000	TRANSMIT ABORT
ADLCCR4RXWLS8	EQU	%00011000	RECEIVER WORD LENGTH SELECT FOR 8 BITS
ADLCCR4TXWLS8	EQU	%00000110	TRANSMITTER WORD LENGTH SELECT
ADLCCR4FFF	EQU	%00000001	DOUBLE FLAG/SINGLE FLAG INTERFRAME CONTROL

ADLCCR1SELTDLD	EQU	%00000000	ADDRESS CONTROL BIT TO SELECT TRANSMITTER DATA (LAST DATA)
ADLCSR1IRQ	EQU	%10000000	INTERRUPT REQUEST
ADLCSR1TDRAFC	EQU	%01000000	TRANSMITTER DATA REGISTER AVAILABLE/FRAE COMPLETE
ADLCSR1TXU	EQU	%00100000	TRANSMITTER UNDERRUN
ADLCSR1CTS	EQU	%00010000	CLEAR TO SEND
ADLCSR1FD	EQU	%00001000	FLAG DETECTED
ADLCSR1LOOP	EQU	%00000100	LOOP STATUS
ADLCSR1S2RQ	EQU	%00000010	STATUS REGISTER #2 READ REQUEST
ADLCSR1RDA	EQU	%00000001	RECEIVER DATA AVAILABLE

ADLCSR2RDA	EQU	%10000000	RECEIVER DATA AVAILABLE
ADLCSR2OVRN	EQU	%01000000	RECEIVER OVERRUN
ADLCSR2DCD	EQU	%00100000	DATA CARRIER DETECT
ADLCSR2ERR	EQU	%00010000	FRAME CHECK SEQUENCE/INVALID FRAME ERROR
ADLCSR2RXABT	EQU	%00001000	ABORT RECEIVED
ADLCSR2RXIDLE	EQU	%00000100	INACTIVE IDLE RECEIVED
ADLCSR2FV	EQU	%00000010	FRAME VALID
ADLCSR2AP	EQU	%00000001	ADDRESS PRESENT
	PAGE
*
*	SDNETADLCINIT -- INITIALIZE SDNET ADLC FOR OPERATION
*	CONVERTS ADLC REFERENCE CHAIN TO ABSOLUTE ADLC REFERENCES
*	ADLC REFERENCE CHAIN FORMAT:
*	EACH REFERENCE CONTAINS (RELATIVE POINTER TO NEXT REF)+(ADLC REG #)
*	LAST REFERENCE CONTAINS ZERO RELATIVE POINTER
*
*	EACH ADLC REFERENCE MUST BE CODED AS FOLLOWS:
*
*		LDAr/STAr	SDNETADLCrrr+SDNETADLCLASTREF-*	comment
*	SDNETADLCLASTREF	SET	*-3
*
*	NOTE: REFS TO ADLC MAY NOT BE MORE THAN 8K BYTES APART
*
SDNETADLCINIT	; BOOT-TIME ONLY ROUTINE
	LDX	SDOS+SDOS:CONFIGURATION	FIND THE ADLC
	LDX	CNFG:NETCNFGPTR,X
	LDX	NETCNFG:ADLC,X
	STX	SDNETADLC
SDNETADLCINITL
	LDX	SDNETADLCREFCHAIN	FOLLOW THE CHAIN!
	LDD	1,X	GET RELATIVE REFERENCE VALUE
	ORAA	#%11000000	DROP ADLC REG REF BITS AND SIGN EXTEND DISPLACEMENT
	ADDD	SDNETADLCREFCHAIN	COMPUTE POINTER TO NEXT REFERENCE
	STD	SDNETADLCREFCHAIN	AND SAVE FOR NEXT ROUND
	CLRA		SET (A,B):= ADLC REGISTER NUMBER
	LDAB	1,X	2 MSBs(B) = ADLC REGISTER NUMBER
	ROLB
	ROLB
	ROLB
	ADDD	SDNETADLC	COMPUTE ADLC REGISTER ADDRESS
	STD	1,X	STORE DESIRED ADLC REGISTER ABSOLUTE ADDRESS
	CPX	SDNETADLCREFCHAIN	AT END OF REFERENCE CHAIN ?
	BNE	SDNETADLCINITL	B/ NO, GO RESOLVE NEXT REFERENCE
	RTS

SDNETADLC	RMB	2	ADLC ADDRESS
SDNETADLCREFCHAIN	FDB	SDNETADLCLASTREF
SDNETADLCLASTREF	SET	0	END OF CHAIN MARK
*
*	ADLC Reset code
*	Executed once at system initialization
*	Leaves ...CR1RIE set, ...CR1AC reset
*
SDNETADLCRESET
	LDAA	#ADLCCR1TXRS!ADLCCR1RXRS!ADLCCR1AC	RESET TRANSMIT AND RECEIVE SECTIONS
	STAA	SDNETADLCCR1+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	CLR	SDNETADLCCR3+SDNETADLCLASTREF-*	SELECT "NON-LOOP" MODE
SDNETADLCLASTREF	SET	*-3
	LDAA	#ADLCCR4NRZINRZ!ADLCCR4RXWLS8!ADLCCR4TXWLS8
	STAA	SDNETADLCCR4+SDNETADLCLASTREF-*	SELECT 8 BIT WORD LENGTH, NRZI MODE
SDNETADLCLASTREF	SET	*-3
	LDAA	#ADLCCR1TXRS!ADLCCR1RIE	SELECT "RECEIVER INTERRUPT ENABLE", "AC=0"
	STAA	SDNETADLCCR1+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	CLR	SDNETADLCCR2+SDNETADLCLASTREF-*	SELECT "TDRA STATUS","MARK IDLE","1 BYTE"
SDNETADLCLASTREF	SET	*-3
	RTS
***** NOTE: GO HUNT FOR UNUSED LABELS
	PAGE
SDNET60HZ	; GET HERE VIA INTERRUPT EVERY 1/60TH SECOND
	INC	CLOCKTICKS	= TIME THAT HAS PASSED
	LDAA	SDNETTIMEQHEAD+SDNETNRB:TIMEQDELTA	IS TIMEQ DELAY NON-ZERO?
	BEQ	SDNET60HZ1	B/ =0, NRB IS TRYING TO SEND
	DEC	SDNETTIMEQHEAD+SDNETNRB:TIMEQDELTA	YES, DOWN COUNT IT
	BEQ	SDNET60HZ2	B/ WENT TO ZERO, TIME TO TRY TO SEND
	BRA	SDNETINTDONE1	NOT ZERO, JUST GET OUT QUICK!

SDNET60HZ1	; NRB AT HEAD OF TIME Q IS TRYING TO SEND
	LDAA	SDNETTIMEOUTFUSE	COLLISION RESOLUTION OR EOT SEARCH ACTIVE ?
	BEQ	SDNETINTDONE1	B/ NO, JUST LEAVE
	DEC	SDNETTIMEOUTFUSE	YES, DOWN COUNT DELAY
	BNE	SDNETINTDONE1	B/ STILL NON-ZERO, JUST LEAVE
	LDX	SDNETTIMEQHEAD+SDNETNRB:TIMEQFLINK	WENT TO ZERO
	CPX	#SDNETTIMEQHEAD	IS TIMEQ EMPTY ?
	BEQ	SDNETINTDONE1	B/ YES, JUST LEAVE
	STX	SDNETNRBPTR	NO, SET NRB TO FIRST ENTRY IN TIMEQ
	LDX	SDNETTIMEOUTROUTINE	AND GO TO ERROR RECOVERY ROUTINE
	JMP	0,X

SDNETSIGNALSCHED	; TELL THE SCHEDULER THAT SOMETHING HAPPENED
	CLR	SDOS+SDOS:SURPRISE	OR SOME OTHER NONSENSE TO GET ITS ATTENTION
SDNETINTDONE	; COMMON EXIT POINT FOR SDNET INTERRUPT ROUTINES
	LDAA	SDNETTIMEQHEAD+SDNETNRB:TIMEQDELTA	IS THE NRB ACTIVE ?
	ORAA	SDNETTIMEOUTFUSE	AND ARE NO OTHER DELAYS PENDING ?
	BEQ	SDNET60HZ2	B/ YES
SDNETINTDONE1	; NO NET TRANSMISSIONS ARE REQUIRED RIGHT NOW
	LDAA	CLOCKTICKS	ANY TIME PASS ?
	BNE	SDNETINTDONE2	B/ YEP.
SDNETINTRTI
	JMP	SDOS+SDOS:RTI	NO, JUST GO 'WAY (WHEW!)

SDNETINTDONE2	; CLOCK HAS TICKED, TELL SDOS
	CLR	CLOCKTICKS	SO WE DON'T DO THIS AGAIN UNTIL NEEDED
	JMP	SDOS+SDOS:CLOCKTICKED
	PAGE
SDNET60HZ2	; NRB AT HEAD OF TIMEQ NEEDS TO SEND SOMETHING
	LDX	SDNETTIMEQHEAD+SDNETNRB:TIMEQFLINK	IS TIMEQ EMPTY ?
	CPX	#SDNETTIMEQHEAD	...?
	BEQ	SDNETINTDONE1	B/ YES, NOTHING TO DO!
	STX	SDNETNRBPTR	NO, USE FIRST NRB IN TIMEQ
SDNETXINTT	; TIMEOUT OCCURRED AFTER TRANSMISSION
	LDAA	SDNETNRB:STATE,X	IS A TIMEOUT EXPECTED HERE ?
	CMPA	#NODESTATE:CONNECTEDS	B/ YES
	BEQ	SDNETINTTRYTRANSMIT	B/ YES, JUST GO TRANSMIT
	LDX	SDNETTIMEDOUTCOUNT	NO, COUNT THE TIMEOUT AS AN ERROR
	INX
	STX	SDNETTIMEDOUTCOUNT
	BRA	SDNETINTTRYTRANSMIT	GO TRY TO TRANSMIT AGAIN
	PAGE
SDNETINTDESIREXMIT	; START I/O TO HERE TO FORCE TRANSMISSION OF A MESSAGE
	LDX	SDNETDESIREXMITNRBPTR	GET NRB FOR XMIT
	INC	SDNETDESIREXMITLOCK	AND RELEASE THE LOCK
	STX	SDNETNRBPTR
	LDAA	SDNETNRB:STATE,X	IS NRB STILL CONNECTED ?
	CMPA	#NODESTATE:CONNECTEDS	(IN FACT, ARE WE SPOS'D TO SEND NEXT ?)
	BEQ	SDNETINTDESIREXMIT0	B/ YES
	CMPA	#NODESTATE:CONNECTEDR	DO WE EXPECT TO RECEIVE NEXT ?
	BNE	SDNETINTRTI	B/ NO, LEAVE NRB ALONE
	CPX	SDNETNRB:TIMEQFLINK,X	IS NRB IDLE ?
	BNE	SDNETINTRTI	B/ NO, WAIT FOR OTHER NODE'S RESPONSE
	BRA	SDNETINTDESIREXMIT1	YES, CAUSE TRANSMISSION

SDNETRINTNORESPONSE	JMP	SDNETRINTDEAD	SIGH... BACK TO LISTENING, FOLKS...

SDNETINTDESIRERCV	; START I/O TO HERE IF DATA IS NEEDED BY A SOCKET
	LDX	SDNETDESIRERCVNRBPTR	THIS IS THE NODE THAT NEEDS A TWEAK
	INC	SDNETDESIRERCVLOCK	RELEASE THE LOCK
	STX	SDNETNRBPTR	IN CASE WE DECIDE TO DO SOMETHING
	LDAB	SDNETNRB:XMTBUF+SDNETBUF:FILL+1,X	ANY DATA TO SEND ?
	SUBB	SDNETNRB:XMTBUF+SDNETBUF:EMPTY+1,X	(COMPUTE XMTRDY)
	BEQ	SDNETINTRTI	B/ NO, LEAVE NODE ALONE
	LDAA	SDNETNRB:STATE,X	ARE WE SPOS'D TO SEND NEXT ?
	CMPA	#NODESTATE:CONNECTEDS	...?
	BNE	SDNETINTRTI	B/ NO, LEAVE NODE ALONE
SDNETINTDESIREXMIT0	; WE ARE SPOS'D TO SEND NEXT
	JSR	SDNETREMOVENRBFROMTIMEQ	SO WE DON'T INSERT IT TWICE
SDNETINTDESIREXMIT1
	CLRB		SET TIME DELAY = 0
	JSR	SDNETPUTNRBINTIMEQ	ADD THIS NRB TO TIMEQ
	LDAA	SDNETTIMEOUTFUSE	COLLISION RESOLUTION OR EOT SEARCH ACTIVE ?
	BNE	SDNETINTDONE	B/ YES, JUST LEAVE
*	BRA	SDNETINTTRYTRANSMIT	NO, GO TRY TO TRANSMIT
	PAGE
*	SDNET MESSAGE TRANSMIT ROUTINE
*	ASSERT: NRB(SDNETNRBPTR) IS AT FRONT OF TIMEQ
*	FIRST SETS UP MESSAGE HEADER AND DATA PART POINTERS
*	THEN CHECKS FOR ETHER BEING FREE
*	IF FREE, THEN ACTUAL TRANSMISSION IS STARTED
*
SDNETINTTRYTRANSMIT	; TRY TO TRANSMIT
	CLR	SDNETTIMEOUTFUSE	DISABLE TRANSMISSION DELAY
	LDX	SDNETNRBPTR	GET POINTER TO NODE REP. BLOCK
	DEC	SDNETNRB:RETRY,X	DOWN COUNT # TRIES WITH NO RESPONSE
	BEQ	SDNETRINTNORESPONSE
	LDAA	SDNETNRB:NODE,X	GRAB "TO" BYTE
	LDAB	SDNETADLCCPUID+SDNETADLCLASTREF-*	GET THE "ORIGINATOR" BYTE
SDNETADLCLASTREF	SET	*-3
	STD	SDNETMSGTOFROM	AND SAVE TO/FROM IN MSG HEADER
	LDAA	SDNETNRB:NODE,X	IS THIS A BROADCAST ?
	BNE	SDNETXINT0F	B/ NO
	LDAA	#SDLPCONTROL:RESYNCHQUIT	YES, USE THIS AS CONTROL FIELD
	BRA	SDNETXINT0D

SDNETXINT0F	; NOT A BROADCAST, DECIDE WHAT TO SEND FOR CONTROL FIELD
	LDAA	SDNETNRB:STATE,X
	STAA	SDNETSTATECONTROL1+1	LOOK CONTROL FIELD UP...
	LDX	SDNETSTATECONTROL1	IN A "STATE-TO-CONTROL FIELD" XLATE TABLE
	LDAA	SDNETSTATECONTROL&$FF,X
SDNETXINT0D	; SEND (A) AS CONTROL FIELD
	STAA	SDNETMSGCONTROL
	LDX	SDNETNRBPTR
	LDD	SDNETNRB:RVPOS,X	GET THE RECEIVED COUNT MOD 2**16
	STD	SDNETMSGRVPOS	AND STORE INTO MESSAGE HEADER
	CLRA		COMPUTE READY TO RECEIVE COUNT= 255-(FILL-EMPTY)
	LDAB	SDNETNRB:RCVBUF+SDNETBUF:EMPTY+1,X
	SUBB	SDNETNRB:RCVBUF+SDNETBUF:FILL+1,X
	DECB		THIS MAGIC INCANTATION WORKS MODULO 256
	STD	SDNETMSGREADYCOUNT	AND PLACE INTO MESSAGE HEADER
	LDAA	SDNETNRB:STATE,X	IS THIS A "RESYNCH" MESSAGE ?
	CMPA	#NODESTATE:ACTIVATING	...
	BNE	SDNETXINT0E	B/ NO
	LDX	#0	YES, TRANSMIT NO DATA BYTES
	BRA	SDNETXINT0G

SDNETXINT0E	; NOT A "RESYNCH" MESSAGE
	CLRA		= (FILL-EMPTY) MOD 256
	LDAB	SDNETNRB:XMTBUF+SDNETBUF:FILL+1,X
	SUBB	SDNETNRB:XMTBUF+SDNETBUF:EMPTY+1,X
	STD	SDNETMSGXMITCOUNT	USE THIS AS THE DEFAULT TRANSMIT COUNT
	SEC		MAKE RCVDRDY LOOK 1 LARGER THAN IT REALLY IS!
	SBCB	SDNETNRB:RCVDRDY+1,X	ASSUME WE'LL SEND WHOLE BUFFER FULL
	SBCA	SDNETNRB:RCVDRDY,X	IS TARGET NODE PREPARED FOR THIS MANY ?
	BCS	SDNETXINT0C	B/ YEP.
	LDX	SDNETNRB:RCVDRDY,X	NO, USE TARGET NODE'S COUNT AS LIMIT
	INX		FUDGE BY ONE, SO TARGET NODE WILL KNOW WE HAVE DATA
*			EVEN IF HE HAS ZERO ROOM
SDNETXINT0G	; (X) HAS NUMBER OF BYTES TO SEND
	STX	SDNETMSGXMITCOUNT	SAVE TRANSMIT COUNT LIMIT
SDNETXINT0C	EQU	*
	LDX	SDNETNRBPTR
	LDD	SDNETNRB:XVPOS,X	SET UP VIRTUAL POSITION OF 1ST TRANSMITTED DATA BYTE
	STD	SDNETMSGXMITBASE
	LDD	SDNETNRB:XMTBUF+SDNETBUF:EMPTY,X	POINTER TO 1ST BYTE TO TRANSMIT
	STAA	SDNETMSGPART2	SET UP POINTER TO PART2 OF THE DATA
	CLR	SDNETMSGPART2+1	(= BASE OF RING BUFFER)
	STAA	SDNETMSGPART2END	WE'LL FILL THE BOTTOM 8 BITS LATER
	ADDB	SDNETMSGXMITCOUNT+1	COMPUTE POINTER TO END OF 1ST PART OF DATA
	BCC	SDNETXINT0H	B/ DATA CAN BE SENT IN ONE PIECE
	INCA		(A,B):=POINTER TO END OF RING BUFFER, +1
	CLRB
SDNETXINT0H	; (A,B) = END OF 1ST PART POINTER
	STD	SDNETPART1END	SAVE END OF 1ST PART POINTER
	SUBB	SDNETNRB:XMTBUF+SDNETBUF:EMPTY+1,X	= # BYTES IN 1ST PART OF DATA
	SUBB	SDNETMSGXMITCOUNT+1	(B):= # BYTES IN 2ND PART OF DATA MESSAGE
	STAB	SDNETPART2END+1	SAVE END OF PART2 OF DATA MESSAGE
*	FALL INTO SYNC TO SEE IF BUS IS BUSY
*	ASSERT: SSDA WAS SET UP TO RECEIVE WHEN WE ARRIVED HERE!
	LDAA	#ADLCCR1SELCR3	ENABLE DCD INTERRUPT
	STAA	SDNETADLCCR1+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	LDAA	#ADLCCR3LOCDTR	ENABLE DCD TO SENSE CLOCK PRESENCE
	STAA	SDNETADLCCR3+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	LDAA	SDNETADLCSR2+SDNETADLCLASTREF-*	READ DCD STATUS
SDNETADLCLASTREF	SET	*-3
	LDAA	#ADLCTXRS!ADLCCR1RIE!ADLCCR1SELCR2
	STAA	SDNETADLCCR1+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	LDAA	#ADLCCR2CLRRXST	ACK DCD STATUS
	STAA	SDNETADLCCR2+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	LDAA	SDNETADLCSR2+SDNETADLCLASTREF-*	NOW READ CURRENT DCD STATUS
SDNETADLCLASTREF	SET	*-3
	BITA	#ADLCSR2DCD	ANY CARRIER ON BUS ?
	BEQ	SDNETXINT0B	B/ BUS IS IDLE, GRAB THE ETHER!
	LDX	SDNETETHERBUSYCOUNT	ETHER IS BUSY, DELAY UNTIL TRAFFIC IS GONE
	INX		COUNT # TIMES THIS HAPPENS
	STX	SDNETETHERBUSYCOUNT
	LDAA	#SDNETEOTFUSETIME	ALSO, MAKE SURE WE DON'T WAIT FOREVER
	STAA	SDNETTIMEOUTFUSE
	LDX	#SDNETXINTMISSEDEOT	WHERE TO GO WHEN TIMEOUT OCCURS
	STX	SDNETTIMEOUTROUTINE
	JMP	SDNETINTDONE1	ASSERT: DCD INTERRUPT IS ENABLED
	PAGE
SDNETXINT0B	; ETHER APPEARS TO BE FREE, TRANSMIT NOW!
*	This is the code that sends the message
*	All message parameters have been pre-computed
*	This code is optimized for sheer speed! Don't monkey with it.
*
	LDAA	#ADLCCR1SELCR2	ENABLE THE TRANSMIT LOGIC
	STAA	SDNETADLCCR1+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	LDAA	#ADLCCR2RTS!ADLCCR2CLRTXST	ISSUE REQUEST TO SEND, CLR STATUS BITS
	STAA	SDNETADLCCR2+SDNETADLCLASTREF-*	ASSERT: SDNETADLCCR1 AC BIT = 0
SDNETADLCLASTREF	SET	*-3
	LDX	#SDNETMSGTO	POINTER TO MESSAGE HEAD
	LDAB	#ADLCSR1TDRAFC	MASK FOR "TRANSMITTER DATA REGISTER AVAILABLE"
SDNETXINTMSGHEADL	; SEND HEADER BYTES OF THE MESSAGE
	LDA	,X+	GET A HEADER BYTE, ADVANCE POINTER TO NEXT BYTE
	CMPB	SDNETADLCSR1+SDNETADLCLASTREF-*	IS ADLC READY FOR ANOTHER BYTE ?
SDNETADLCLASTREF	SET	*-3
	BEQ	SDNETXINTMSGHEADL2	B/ YES, GO SEND IT (FAST PATH=29 CYCLES/BYTE)
	PSHA		NO, SET UP TIMEOUT LOOP
	LDAA	#(100*2)/14	SLOW PATH = 61 CYCLES/BYTE, MINIMUM
SDNETXINTMSGHEADL0	; LOOP WAITING FOR ADLC TO REQUEST DATA BYTE
	CMPB	SDNETADLCSR1+SDNETADLCLASTREF-*	IS ADLC READY FOR ANOTHER BYTE ?
SDNETADLCLASTREF	SET	*-3
	BEQ	SDNETXINTMSGHEADL1	B/ YES, GO OUTPUT THE BYTE
	DECA		DOWN COUNT 80US TIMER
	BNE	SDNETXINTMSGHEADL0	B/ WAIT SOME MORE
	BRA	SDNETXINTMSGOOPS	RATS, SOMETHING WENT WRONG IN TRANSMISSION

SDNETXINTMSGHEADL1	; ADLC IS READY, SEND BYTE ON TOP OF STACK
	PULA
SDNETXINTMSGHEADL2	; ADLC IS READY, SEND BYTE IN (A)
	STAA	SDNETADLCTDCD+SDNETADLCLASTREF-*	SEND BYTE AS "CONTINUE DATA"
SDNETADLCLASTREF	SET	*-3
	CPX	#SDNETMSGDATA-1	ALL HEADER BYTES SENT ?
	BNE	SDNETXINTMSGHEADL	B/ NO, GO SEND ANOTHER
	PAGE
*
*	NOW SEND THE FIRST PART OF THE MESSAGE BODY (DATA BYTES)
*
	LDX	SDNETNRBPTR
	LDX	SDNETNRB:XMTBUF+SDNETBUF:EMPTY,X
	CPX	SDNETMSGPART1END	SEND NO DATA BYTES ?
	BEQ	SDNETXINTMSGCRC	B/ YES, GO SEND CRC
SDNETXINTMSGPART1L	; SEND BYTES FROM PART1 OF DATA PORTION OF THE MESSAGE
	LDA	,X+	GET A DATA BYTE, ADVANCE BUFFER POINTER
	CMPB	SDNETADLCSR1+SDNETADLCLASTREF-*	IS ADLC READY FOR ANOTHER BYTE ?
SDNETADLCLASTREF	SET	*-3
	BEQ	SDNETXINTMSGPART1L2	B/ YES (FAST PATH = 31 CYCLES/BYTE)
	PSHA		NO, SET UP TIMEOUT LOOP
	LDAA	#(100*2)/14	SLOW PATH = 3 CYCLES/BYTE, MINIMUM
SDNETXINTMSGPART1L0	; LOOP WAITING FOR ADLC TO REQUEST DATA BYTE
	CMPB	SDNETADLCSR1+SDNETADLCLASTREF-*	IS ADLC READY FOR ANOTHER BYTE ?
SDNETADLCLASTREF	SET	*-3
	BEQ	SDNETXINTMSGPART1L1	B/ YES, GO OUTPUT THE BYTE
	DECA		DOWN COUNT 80US TIMER
	BNE	SDNETXINTMSGPART1L0	B/ WAIT SOME MORE
	BRA	SDNETXINTMSGOOPS	RATS, SOMETHING WENT WRONG INTRANSMISSION

SDNETXINTMSGPART1L1	; ADLC IS READY, SEND BYTE ON TOP OF STACK
	PULA
SDNETXINTMSGPART1L2	; ADLC IS READY, SEND BYTE IN (A)
	STAA	SDNETADLCTDCD+SDNETADLCLASTREF-*	SEND BYTE AS "CONTINUE DATA"
SDNETADLCLASTREF	SET	*-3
	CPX	SDNETMSGPART1END	ALL PART 1 BYTES SENT ?
	BNE	SDNETXINTMSGPART1L	B/ NO, GO SEND ANOTHER
	PAGE
*
*	NOW SEND PART2 OF THE DATA PART OF THE MESSAGE
*
	LDX	SDNETMSGPART2	GET ADDRESS OF SECOND PART OF MESSAGE
	CPX	SDNETMSGPART2END	ANY BYTES TO SEND IN PART 2 ?
	BEQ	SDNETXINTMSGCRC	B/ NO, GO SEND CRC
SDNETXINTMSGPART2L	; SEND PART 2 DATA BYTES OF THE MESSAGE
	LDA	,X+	GET A PART 2 BYTE, ADVANCE BUFFER POINTER
	CMPB	SDNETADLCSR1+SDNETADLCLASTREF-*	IS ADLC READY FOR ANOTHER BYTE ?
SDNETADLCLASTREF	SET	*-3
	BEQ	SDNETXINTMSGPART2L2	B/ YES, GO SEND IT (FAST PATH=31 CYCLES/BYTE)
	PSHA		NO, SET UP TIMEOUT LOOP
	LDAA	#(100*2)/14	SLOW PATH = 63 CYCLES/BYTE, MINIMUM
SDNETXINTMSGPART2L0	; LOOP WAITING FOR ADLC TO REQUEST DATA BYTE
	CMPB	SDNETADLCSR1+SDNETADLCLASTREF-*	IS ADLC READY FOR ANOTHER BYTE ?
SDNETADLCLASTREF	SET	*-3
	BEQ	SDNETXINTMSGPART2L1	B/ YES, GO OUTPUT THE BYTE
	DECA		DOWN COUNT 80US TIMER
	BNE	SDNETXINTMSGPART2L0	B/ WAIT SOME MORE
	BRA	SDNETXINTMSGOOPS	RATS, SOMETHING WENT WRONG IN TRANSMISSION

SDNETXINTMSGPART2L1	; ADLC IS READY, SEND BYTE ON TOP OF STACK
	PULA
SDNETXINTMSGPART2L2	; ADLC IS READY, SEND BYTE IN (A)
	STAA	SDNETADLCTDCD+SDNETADLCLASTREF-*	SEND BYTE AS "CONTINUE DATA"
SDNETADLCLASTREF	SET	*-3
	CPX	SDNETMSGPART2END	ALL PART 2 BYTES SENT ?
	BNE	SDNETXINTMSGPART2L	B/ NO, GO SEND ANOTHER
SDNETXINTMSGCRC	; ALL MESSAGE BYTES ARE SENT, NOW SEND CRC
	LDAA	#ADLCCR2TXLAST	FORCE TRANSMISSION OF LAST BYTE AND CRC
	STAA	SDNETADLCCR2+SDNETADLCLASTREF-*	(ALSO CLEARS RTS)
SDNETADLCLASTREF	SET	*-3
	LDAA	SDNETADLCSR1+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	CMPA	#0	CHECK THAT SENDING CRC DIDN'T CAUSE ANY ERRORS
	BNE	SDNETXINTMSGOOPS1	RATS, SOMETHING WENT WRONG IN TRANSMISSION
****	MESSAGE HAS BEEN COMPLETELY TRANSMITTED! ****
	LDAA	#ADLCCR1SELCR3	DISABLE DTR TO KILL DCD SENSE
	STAA	SDNETADLCCR1+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	LDAA	#0
	STAA	SDNETADLCCR3+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	LDAA	#ADLCCR1TXRS!ADLCCR1RIE	THEN SET UP TO RECEIVE RESPONSE
	STAA	SDNETADLCCR1+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	LDX	SDNETXMITOKCOUNT	COUNT # TIMES WE SUCCEED IN TRANSMISSION
	INX
	STX	SDNETXMITOKCOUNT
	LSR	SDNETXDELAYMASK	WE APPEAR TO HAVE SUCCESSFULLY TRANSMITTED A MESSAGE
	ROR	SDNETXDELAYMASK+1	SHORTEN TRANSMIT CONFLICT RESOLUTION WINDOW
	JSR	SDNETREMOVENRBFROMTIMEQ	TAKE NRB OFF THE TIME Q
	LDX	SDNETNRBPTR	IS THIS A BROADCAST MESSAGE ?
	LDAA	SDNETNRB:NODE,X	(IT IS IF NODE NUMBER = 0)
	BNE	SDNETXINT1	B/ NOT A BROADCAST MESSAGE, LEAVE NRB ALONE
*	BROADCAST MESSAGE, RELEASE THE BUFFER CONTENTS, LEAVE NRB OUT OF TIMEQ
	LDAA	SDNETNRB:XMTBUF+SDNETBUF:FILL+1,X
	STAA	SDNETNRB:XMTBUF+SDNETBUF:EMPTY+1,X
	JMP	SDNETSIGNALSCHED	AND WAKE UP BROADCAST TRANSMIT TASK
	PAGE
SDNETXINT1	; NON-BROADCAST MESSAGE JUST TRANSMITTED
	LDAA	SDNETNRB:STATE,X
	CMPA	#NODESTATE:QUIT	WERE WE JUST SPOS'D TO SEND "QUIT" ?
	BEQ	SDNETXINTQUIT	B/ YES, GO CLEAN UP
	CMPA	#NODESTATE:CONNECTEDS	ARE WE IN "SPOSD TO SEND" STATE ?
	BNE	SDNETXINT2B	B/ NO
	LDAA	#NODESTATE:CONNECTEDR	YES, FORCE STATE TO "SPOSD TO RECEIVE"
	STAA	SDNETNRB:STATE,X
SDNETXINT2B
	CMPA	#NODESTATE:CONNECTEDR	IN A "SPOSD TO RECEIVE NEXT" STATE ?
	BNE	SDNETXINT2A	B/ NO, MUST BE SPECIAL FUNCTION, FORCE A TIMEOUT
	LDAB	SDNETNRB:XMTBUF+SDNETBUF:FILL+1,X	DO WE HAVE DATA TO SEND?
	SUBB	SDNETNRB:XMTBUF+SDNETBUF:EMPTY+1,X	...?
	BEQ	SDNETXINT2C	B/ NO DATA TO SEND, DON'T SET TIMEOUT
SDNETXINT2A	; MUST SET A TIMEOUT
	LDAB	#SDNETRETRYTIME	SET TIME DELAY BEFORE RETRY
	JSR	SDNETPUTNRBINTIMEQ	PUT NRB IN TIMEQ TO BE PROCESSED LATER
SDNETXINT2C
	JMP	SDNETINTDONE	AND WAIT FOR A RESPONSE

SDNETXINTQUIT	; WE JUST FINISHED SENDING "QUIT"
	JMP	SDNETRINTDEAD	NOW FOR THE COUP DE GRACE
	PAGE
SDNETXINTMSGOOPS	; TRANSMISSION FAILED
	INS		THROW AWAY THE BYTE WE WERE ABOUT TO SEND
SDNETXINTMSGOOPS1	; TRANSMISSION FAILED, KILL IT OFF!
	LDAA	SDNETADLCSR1+SDNETADLCLASTREF-*	CHECK FOR TX UNDERFLOW
SDNETADLCLASTREF	SET	*-3
	BITA	#ADLCSR1TXU
	BNE	*	B/ TX UNDERFLOW IS IMPOSSIBLE!
	LDAA	#ADLCCR1SELCR4
	STAA	SDNETADLCCR1+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	LDAA	#ADLCCR4NRZINRZ!ADLCCR4ABTEX!ADLCCR4ABT!ADLCCR4RXWLS8!ADLCCR4TXWLS8
	STAA	SDNETADLCCR4+SDNETADLCLASTREF-*	FORCE TRANSMISSION OF AN ABORT
SDNETADLCLASTREF	SET	*-3
	LDAA	#ADLCCR1RIE!ADLCCR1SELCR2	SELECT AC=0
	STAA	SDNETADLCCR1+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	LDAA	#ADLCCR2FCTDRA	WAIT FOR ABORT COMPLETE
	STAA	SDNETADLCCR2+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	LDAB	#ADLCSR1TDRAFC
SDNETXINTWAITABORTDONE
	BITB	SDNETADLCSR1+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	BNE	SDNETXINTWAITABORTDONE	B/ ABORT TRANSMIT NOT COMPLETE
	LDAA	#ADLCCR1TXRS!ADLCCR1RIE	ENABLE RECIEVER PART OF ADLC
	STAA	SDNETADLCCR1+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	LDX	SDNETCOLLISIONCOUNT	BUMP # COLLISIONS ENCOUNTERED
	INX
	STX	SDNETCOLLISIONCOUNT
	SEC		XMIT CONFLICT, COMPUTE NEW DELAY
	ROL	SDNETXDELAYMASK+1
	ROL	SDNETXDELAYMASK
	LDD	SDOS+SDOS:CLOCK+1
	EORB	SDNETCOLLISIONCOUNT+1	TO PREVENT DELAY FROM BEING PERMANENTLY ZERO, THEREBY CAUSING TIMEOUT
	ANDA	SDNETXDELAYMASK
	ANDB	SDNETXDELAYMASK+1
	BEQ	SDNETTRYTRANSMITJ	B/ RANDOM DELAY = 0, GO TRY TO TRANSMIT
	STAB	SDNETTIMEOUTFUSE	SET FUSE FOR COLLISION RESOLUTION
	LDX	#SDNETTRYTRANSMIT	SET UP TO RETRANSMIT IF BUS IS QUIET AFTER DELAY
	STX	SDNETTIMEOUTROUTINE
	JMP	SDNETINTDONE1	NOW LEAVE!

SDNETXINTMISSEDEOT	; TIMEOUT ON EOT SEARCH OCCURRED
	LDX	SDNETMISSEDEOTCOUNT	BUMP GOOF COUNT
	INX
	STX	SDNETMISSEDEOTCOUNT
SDNETTRYTRANSMITJ
	JMP	SDNETTRYTRANSMIT	GO TRY TO TRANSMIT AGAIN
*	WHAT IF SENDER IS CRAZY, SENDS COUNT=X, ACTUAL COUNT = Y?
*	SDNET SDLP MESSAGE FORMAT:
*
* --------------------------------------------------------------------------------
* !  TO  ! FROM ! CNTRL !  RCVDOK  ! RCVRDY ! XMTCNT ! XMTBASE ! ..DATA... ! CRC !
* --------------------------------------------------------------------------------
*    1B     1B     1B        2B        2B       2B       2B         nB        2B
*
*
*	TO = DESTINATION COMPUTER (:00 = "ALL" )
*	FROM = SOURCE COMPUTER (MUST BE <> 0)
*	CNTRL = CONTROL CODE (USED TO ESTABLISH/BREAK COMM LINK)
*	RCVDOK = POSITION IN VIRTUAL STREAM OF FIRST BYTE NOT RECEIVED (CORRECTLY) YET
*			MODULO 2^16
*	RCVRDY = SUGGESTED MAXIMUM XMTCNT FOR USE BY OTHER COMPUTER
*			USUALLY = SIZE OF "FROM" COMPUTER'S REMAINING RECEIVER BUFFER SPACE
*	XMTCNT = NUMBER OF ..DATA.. BYTES SENT IN THIS MESSAGE
*			MUST BE ACKNOWLEDGED BY ANOTHER CLOSE DATA LINK COMMAND
*	XMTBASE = POSITION OF FIRST ..DATA.. BYTE IN "TO" COMPUTER'S RECEIVE FILE
*			MODULO 2^16
*	..DATA.. = STREAM OF DATA BYTES FOR "TO" COMPUTER
*			(MAX OF 2^16-1; OMITTED IF XMTCNT = 0 )
*	CRC = CRC OF MESSAGE USING CRC-CCITT AS DIVISOR POLYNOMIAL
*
SDNETINTERRUPT0	; ADLC HAS NOT RECEIVED ERROR-FREE DATA
	LDAA	SDNETADLCSR2+SDNETADLCLASTREF-*	DOES ADLC HAVE SOMETHING TO SAY ?
SDNETADLCLASTREF	SET	*-3
	BEQ	SDOS+SDOS:IOINT	B/ NO, GO DO CONVENTIONAL POLL
	INC	SDOS+SDOS:STACKSWITCHED	PERFORM STACK SWITCH
	BNE	SDNETINTERRUPT0A	B/ STACK SWITCH ALREADY PERFORMED
	LDX	SDOS+SDOS:CURRENTASK
	STS	TCB:STACK,X
	LDX	SDOS+SDOS:CONFIGURATION
	LDS	CNFG:INTSTACK,X
SDNETINTERRUPT0A	; STACK SWITCH COMPLETED
	BITA	#ADLCSR2RDA!ADLCSR2OVRN!ADLCSR2ERR!ADLCSR2RXABT!ADLCSR2RXIDLE
	BNE	SDNETINTERUPT0B	B/ ADLC TELLS US ABOUT AN ERROR
	BITA	#ADLCSR2DCD	DATA CARRIER DETECT INTERRUPT ?
	BEQ	*	B/ NO, IMPOSSIBLE STATUS HERE!
*	DCD INTERRUPT --> MUST BE SEARCHING FOR END OF TRANSMISSION
*	DISABLE THE DCD INPUT BY SHUTTING OFF DTR
*	ACK THE DCD INTERRUPT, AND THEN GO ATTEMPT TO TRANSMIT
	JMP	SDNETINTTRYTRANSMIT	GO DECIDE WHAT TO SEND, FIRST

SDNETINTERRUPT0B	; ADLC DETECTED AN ERROR
	LDAA	#ADLCCR2CLRRXST	ACKNOWLEDGE THE ERROR
	STAA	SDNETADLCCR2+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	JMP	SDNETINTENBRCV	GO SET UP TO RECEIVE AGAIN
	PAGE
SDNETINTERRUPT	; FIRST PLACE IN POLL CHAIN, STACKS NOT SWITCHED
*	ASSERT: ADLCCR1TXRESET HELD HIGH WHILE RECEIVING INHIBITS ADLCSR1TDRAFC, ADLCSR1TXU
*	ADLCCR2RTS HELD LOW WHILE RECEIVING INHIBITS CTS
*	ADLCCR3FDSE PERMANENTLY HELD LOW, INHIBITS ADLCSR1FD
*	ADLCCR3LOOP PERMANENTLY HELD LOW, INHIBITS ADLCSR1LOOP
	LDX	SDNETADLCSR1+SDNETADLCLASTREF-*	DOES ADLC HAVE DATA FOR US ?
	CPX	#(ADLCSR1IRQ!ADLCSR1S2RQ!ADLCSR1RDA)##8!ADLCSR2RDA!ADLCSR2AP
	BNE	SDNETINTERRUPT0	B/ NOT ERROR-FREE RECEIVED DATA
	LDAA	SDNETADLCRDR+SDNETADLCLASTREF-*	GRAB "TO" BYTE
SDNETADLCLASTREF	SET	*-3
	STAA	SDNETMSGTO	ASSUME ALL 3 FIFO REGS FULL AT START OF THIS INST.
	LDAB	#ADLCSR1IRQ+ADLCSR1RDA	MASK TO DETECT INTERRUPT RQ FOR RCV DATA
	CMPB	SDNETADLCSR1	DOES ADLC HAVE ANOTHER ERROR-FREE DATA BYTE ?
SDNETADLCLASTREF	SET	*-3
	BNE	SDNETINTERRUPT1	B/ NO
	LDAA	SDNETADLCRDR+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	STAA	SDNETMSGFROM	SAVE THE "WHO FROM" BYTE
	CMPB	SDNETADLCSR1	DOES ADLC HAVE ANOTHER ERROR-FREE DATA BYTE ?
SDNETADLCLASTREF	SET	*-3
	BNE	SDNETINTERRUPT2	B/ NO
	LDAA	SDNETADLCRDR+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	STAA	SDNETMSGCONTROL	SAVE THE CONTROL BYTE
	CMPB	SDNETADLCSR1	DOES ADLC HAVE ANOTHER ERROR-FREE DATA BYTE ?
SDNETADLCLASTREF	SET	*-3
	BNE	SDNETINTERRUPT3	B/ NO
	LDAA	SDNETADLCRDR+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	STAA	SDNETMSGRVPOS	SAVE THE UPPER 8 BITS OF RECEIVED VIRTUAL POSITION
	CMPB	SDNETADLCSR1	DOES ADLC HAVE ANOTHER ERROR-FREE DATA BYTE ?
SDNETADLCLASTREF	SET	*-3
	BNE	SDNETINTERRUPT4	B/ NO
	LDAA	SDNETADLCRDR+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	STAA	SDNETMSGRVPOS+1	YES, NOW WE HAVE 64 US. TO PLAY AROUND IN!
	LDX	#SDNETMSGREADYCOUNT	= ADDRESS OF NEXT BYTE TO FILL
	JMP	SDNETINTERRUPT5

SDNETINTERRUPT1
	LDX	#SDNETMSGTO	= ADDRESS OF NEXT BYTE TO FILL
	JMP	SDNETINTERRUPT5
SDNETINTERRUPT2
	LDX	#SDNETMSGCONTROL	= ADDRESS OF NEXT BYTE TO FILL
	JMP	SDNETINTERRUPT5
SDNETINTERRUPT3
	LDX	#SDNETMSGRVPOS	= ADDRESS OF NEXT BYTE TO FILL
	JMP	SDNETINTERRUPT5
SDNETINTERRUPT4
	LDX	#SDNETMSGRVPOS+1
SDNETINTERRUPT5	; ADLC DID NOT HAVE ERROR-FREE BYTE...
	LDAA	SDNETMSGTO	IS THIS MESSAGE INTENDED FOR US ?
	BEQ	SDNETINTERRUPT6	B/ YES, ITS A BROADCAST
	CMPA	SDNETADLCCPUID+SDNETADLCLASTREF-*	MATCHING CPU ID ?
SDNETADLCLASTREF	SET	*-3
	BNE	SDNETINTENBRCV	B/ MESSAGE IS NOT FOR US, GO AWAY...
SDNETNETINTERRUPT6
	LDAA	#(100*2)/14	= # TIMES AROUND FOLLOWING LOOP BEFORE TIMEOUT
SDTEINETRRUPT6A
	CMPB	SDNETADLCSR1+SDNETADLCLASTREF-*	DID MORE DATA ARRIVE ?
	BEQ	SDNETINTERRUPT7	B/ YES, GO SAVE IT!
	DECA		DOWN COUNT TIMEOUT
	BNE	SDNETINTERRUPT6A	B/ TIMEOUT FUSE NOT BURNED UP, YET
	JMP	SDNETRINTDONE
SDNETINTERRUPT7	; DATA BYTE HAS ARRIVED
	LDAA	SDNETADLCRDR+SDNETADLCLASTREF-*	GRAB THE DATA BYTE
SDNETADLCLASTREF	SET	*-3
	STA	,X+	SAVE THE DATA BYTE, ADVANCE THE BUFFER POINTER
	CPX	#SDNETMSGDATA+SDNETMSGDATASIZEMAX	= FIRST PLACE WE CAN'T STORE DATA
	BNE	SDNETINTERRUPT6	B/ BUFFER NOT EXHAUSTED YET
	LDX	#0	WE'RE WILLING TO LISTEN TO 65536 MORE BYTES...
	JMP	SDNETINTERRUPT8A

SDNETINTERRUPT8	; DATA BYTE HAS ARRIVED, CAREFULLY IGNORE IT
	DEX		DOWN COUNT BYTES IGNORED IN THE MESSAGE
	BEQ	SDNETRINTDONE	B/ THERE CAN'T POSSIBLY BE THIS MANY BYTES IN A MESSAGE
	LDAA	SDNETADLCRDR+SDNETADLCLASTREF-*	GRAB THE BYTE, ACKING IT
SDNETINTERRUPT8A
	LDAA	#(100*2)/14	= # TIMES AROUND LOOP BEFORE TIMEOUT
SDNETINTERRUPT8B
	CMPB	SDNETADLCSR1+SDNETADLCLASTREF-*	DATA BYTE READY ?
SDNETADLCLASTREF	SET	*-3
	BEQ	SDNETINTERRUPT8	B/ YES, GO EAT IT
	DECA		DOWN COUNT TIMEOUT FUSE
	BNE	SDNETINTERRUPT8B	B/ TIMEOUT NOT EXHAUSTED YET
SDNETRINTDONE	; DONE RECEIVING MESSAGE
	STX	SDNETPHASE1CNT	SAVE POINTER TO "LAST" BYTE RECEIVED
	INC	SDOS+SDOS:STACKSWITCHED	SOME FREE TIME, SWITCH STACK POINTERS
	BNE	SDNETRINTDONE1	B/ ALREADY SWITCHED
	LDX	SDOS+SDOS:CURRENTASK
	STS	TCB:STACK,X
	LDX	SDOS+SDOS:CONFIGURATION
	LDS	CNFG:INTERRUPTSTACK,X
SDNETRINTDONE1	; STACKS ARE NOW SWITCHED
	LDAA	SDNETADLCSR2+SDNETADLCLASTREF-*	FIND OUT WHY WE LEFT LOOP
SDNETADLCLASTREF	SET	*-3
	BITA	#ADLCSR2OVRN	WAS IT BECAUSE OF OVERRUN ?
	BNE	SDNETRINTOVRUN	B/ YEP.
	BITA	#ADLCSR2ERR	BECAUSE OF FRAMING OR CRC ERROR ?
	BNE	SDNETRINTERR	B/ YES
	BITA	#ADLCSR2FV	BECAUSE OF COMPLETE, VALID FRAME ?
	BNE	SDNETGOODFRAME	B/ YES, GO PROCESS MESSAGE CONTENTS
	LDX	SDNETUNUSUALCOUNT	RCV FAILED FOR ODD REASON
	INX
	STX	SDNETUNUSUALCOUNT
	BRA	SDNETINTENBRCV

SDNETRINTTMO	EQU	*	DID NOT RECEIVE DATA IN 100 US., TIMED OUT! ****
	LDX	SDNETNOCLOCKCOUNT	BUMP NUMBER OF TIMES "TMO" OCCURS
	INX
	STX	SDNETNOCLOCKCOUNT
	BRA	SDNETINTENBRCV	IGNORE MESSAGE, WAIT FOR ANOTHER

SDNETRINTRTI	EQU	*	AND EXIT
	JMP	SDOS+SDOS:RTI

SDNETRINTERR	; FRAMING OR CRC ERROR
	LDX	SDNETBADCRCCOUNT	BUMP BAD CRC RCVD COUNTER
	INX
	STX	SDNETBADCRCCOUNT
	JMP	SDNETINTENBRCV	NOTHING INTERESTING HAPPENED...
	PAGE
SDNETRINTOVRUN	EQU	*	OVERRUN OCCURRED, DATA LOST
	LDX	SDNETOVRUNCOUNT	BUMP # OVERRUNS ENCOUNTERED
	INX
	STX	SDNETOVRUNCOUNT
	LDAA	SDNETMSGTO	IS MESSAGE FOR US EXPLICITLY ?
	CMPA	SDNETADLCCPUID+SDNETADLCLASTREF-*	...?
SDNETADLCLASTREF	SET	*-3
	BEQ	SDNETINTENBRCV	B/ NO, DON'T CAUSE A COLLISION
	LDAA	#ADLCCR2RTS	SEND AN EXTENDED ABORT
	STAA	SDNETADLCCR2+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	LDAA	#ADLCCR1AC	SELECT AC=1
	STAA	SDNETADLCCR1+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	LDAA	#ADLCCR4NRZINRZ!ADLCCR4ABTEX!ADLCCR4ABT!ADLCCR4RXWLS8!ADLCCR4TXWLS8
	STAA	SDNETADLCCR4+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	LDAA	#0	NOW SHUT OF RTS
	STAA	SDNETADLCCR1+SDNETADLCLASTREF-*	SELECT AC=0
SDNETADLCLASTREF	SET	*-3
	STAA	SDNETADLCCR2+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3

SDNETINTENBRCV	; ENABLE THE RECEIVER
	LDAA	#ADLCCR1RXRS!ADLCCR1TXRS	RESET BOTH RECEIVER AND TRANSMITTER
	STAA	SDNETADLCCR1+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	LDAA	#ADLCCR1TXRS!ADLCCR1RIE	SET UP TO INTERRUPT ON RCV
	STAA	SDNETADLCCR1+SDNETADLCLASTREF-*
SDNETADLCLASTREF	SET	*-3
	LDX	SDNETENBRCVCOUNT	BUMP NUMBER OF TIMES WE ENABLED THE RECEIVER
	INX
	STX	SDNETENBRCVCOUNT
	JMP	SDNETINTDONE
	PAGE
SDNETGOODFRAME	; A GOOD FRAME HAS BEEN RECEIVED
	LDX	SDNETGOODCRCCOUNT	BUMP # GOOD MESSAGES WE HAVE RECEIVED
	INX
	STX	SDNETGOODCRCCOUNT
	LDX	SDNETNRBPTR
	LDAA	#SDNETRETRYCOUNT	WE GOT THROUGH!
	STAA	SDNETNRB:RETRY,X	SET RETRY COUNTER BACK TO MAXIMUM
	LDB	SDNETMSGFROM	A MESSAGE FROM MYSELF ?
	CMPB	SDNETADLCCPUID+SDNETADLCLASTREF-*	...?
SDNETADLCLASTREF	SET	*-3
	BEQ	SDNETINTENBRCV	B/ YES, WHOEVER SENT IT MUST BE CRAZY, IGNORE
	CMPB	#SDNETNODEMAX	DO WE HAVE AN NRB FOR THIS NODE ?
	BHI	SDNETINTENBRCV	B/ NO, WE'LL JUST IGNORE THIS MESSAGE
	STB	SDNETMSGFROM	ELSE SAVE IT
	CLRA		FIND NODE REPRESENTATIVE BLOCK ADDRESS
	ASLD
	IF	M6800!M6801
	ADDD	#SDNETNRBTABLE
	STD	SDNETNRBPTR
	LDX	SDNETNRBPTR
	LDX	0,X
	ELSE	(M6809)
	LDX	#SDNETNRBTABLE
	LDX	D,X
	FIN
	BEQ	SDNETINTENBRCV	B/ NO NRB REPRESENTATIVE, IGNORE MESSAGE
	PAGE
SDNETRINT1A	; RE-ENTRY POINT FOR BROADCAST MESSAGE RECEIVER CODE
	STX	SDNETNRBPTR
	LDAA	SDNETNRB:STATE,X	IF NODE REPRESENTATIVE IS MARKED AS 'DEAD',
	CMPA	#NODESTATE:DEAD	THEN IGNORE ANY MESSAGES FOR IT
	BEQ	SDNETINTENBRCV	B/ A ZOMBIE! EEEK!
	LDX	SDNETNRBPTR	COMPUTE READY TO RECEIVE COUNT
	CLRA		= 255-(FILL-EMPTY)
	LDAB	SDNETNRB:RCVBUF+SDNETBUF:EMPTY+1,X
	SUBB	SDNETNRB:RCVBUF+SDNETBUF:FILL+1,X
	DECB		THIS INCANTATION WORKS MODULO 256!
	STD	SDNETFREEBYTES
	LDX	SDNETNRBPTR	SET TENTATIVE FILL POINTER...
	LDX	SDNETNRB:RCVBUF+SDNETBUF:FILL,X	TO FIRST FREE BYTE OF BUFFER CHAIN
	STX	SDNETBUFPTR
	LDAA	SDNETMSGTO	BROADCAST MESSAGE ?
	BNE	SDNETRINT1C	B/ NO, MUST BE NORMAL DATA MESSAGE
	LDD	SDNETFREEBYTES	DECIDE IF WE CAN KEEP ENTIRE BROADCAST MESSAGE
	SUBD	SDNETMSGXMITCOUNT
	BCS	SDNETINTENBRCVJ	B/ CAN'T KEEP ENTIRE MESSAGE, "SOUR GRAPES..."
	LDX	SDNETMSGXMITCOUNT	SET PHASE 2 COUNT = ALL TRANSMITTED BYTES
	STX	SDNETPHASE2CNT
	LDX	#0	CAN KEEP ENTIRE MESSAGE, SET PHASE 3 COUNT TO 0
	STX	SDNETPHASE3CNT
	JMP	SDNETRINT4A	GO SAVE THE DATA BYTES

SDNETINTENBRCVJ	JMP	SDNETINTENBRCV

SDNETRINTELSEJ	JMP	SDNETRINTELSE

SDNETRINTCRCJ	JMP	SDNETRINTCRC
	PAGE
SDNETRINT1C	; MUST BE NORMAL DATA MESSAGE
	LDD	SDNETPHASE1CNT	COMPUTE # BYTES RECEIVED
	SUBD	#SDNETMSGDATA
	SUBD	SDNETMSGXMITCNT
	BHI	SDNETRINTCONFUSED	B/ # RCVD < XMITCNT FIELD, OTHER NODE IS NUTS
	BEQ	???
	LDD	#SDNETMSGDATASIZEMAX	FORCE # BYTES SENT...
	STD	SDNETMSGXMITCNT	TO BE SAME AS # BYTES RECEIVED
*
*				...DATA... PART OF MESSAGE
*	--------------------------------------------------------------------
*	!  <-- PHASE 1 CNT --> ! <-- PHASE 2 CNT --> ! <-- PHASE 3 CNT --> !
*	--------------------------------------------------------------------
*	^                      ^                                           ^
*	!                      !                                           !
*	! <----------------------- SDNETMSGXCNT -------------------------> !
*	!                      !
*	\                  SDNETNRB:RVPOS
*	  SDNETMSGXMITBASE
*
*
*	IF SDNETMSGXMITBASE <= SDNETNRB:RVPOS
*	AND SDNETMSGXMITBASE+SDNETMSGXCNT > SDNETNRB:RVPOS
*	THEN PHASE1CNT:=SDNETNRB:RVPOS-SDNETMSGXMITBASE;
*	     PHASE2CNT:=MIN(availablebufferspace,
*                          SDNETMSGXMITBASE+SDNETMSGXCNT-SDNETNRB:RVPOS);
*	     PHASE3CNT:=SDNETMSGXCNT-(PHASE1CNT+PHASE2CNT);
*	ELSE PHASE1CNT:=0;
*	     PHASE2CNT:=0;
*	     PHASE3CNT:=SDNETMSGXCNT;
*	FI

	LDX	SDNETNRBPTR
	LDD	SDNETNRBRVPOS,X	IS SDNETMSGXMITBASE <= SDNETNRB:RVPOS ?
	SUBD	SDNETMSGXMITBASE	NOTE: -32768 <= ACTUALRVPOS-ACTUALXMITBASE <= 32767 !
	BMI	SDNETRINTELSEJ	B/ NO...
	STD	SDNETPHASE1CNT	YES, SAVE PHASE1 SKIP COUNT
	LDD	SDNETMSGXMITCOUNT	COMPUTE MIN(...)
	SUBD	SDNETPHASE1CNT
	BMI	SDNETRINTELSEJ	B/ SDNETMSGXBASE+SDNETMSGXMITCOUNT < SDNETNRB:RVPOS
	STD	SDNETPHASE2CNT	ASSUME SDNETMSGXBASE+SDNETMSGXMITCOUNT-SDNETNRB:RVPOS IS MIN
	SUBD	SDNETFREEBYTES
	BCS	SDNETRINT2	B/ ASSUMPTION WAS RIGHT
	LDX	SDNETFREEBYTES	OOPS, ASSUMPTION WAS WRONG
	STX	SDNETPHASE2CNT	USE availablebufferspace AS MIN
SDNETRINT2
	PAGE
	LDX	SDNETPHASE2CNT	ANY BYTES TO SAVE ?
	BEQ	SDNETRINT6A	B/ NO
	LDD	SDNETMSGDATA	COMPUTE ADDRESS OF 1ST BYTE TO SAVE
	ADDD	SDNETPHASE1CNT
	STD	SDNETPART1	= COPY FROM ADDRESS
	LDX	SDNETNRBPTR	GET BUFFER FILL POINTER
	LDD	0	SAVE BLOCK MOVE TASK LOCATIONS
	PSHD
	LDD	2
	PSHD
	LDD	4
	PSHD
	LDD	SDNETNRB:RCVBUF+SDNETBUF:FILL,X
	STD	0	= "TO" LOCATION
	***** NEEDS WORK HERE!
	PULD		RESTORE BLOCK MOVE TASK LOCATIONS
	STD	4
	PULD
	STD	2
	PULD
	STD	0
SDNETRINTCONFUSED	; UNTESTED
	JSR	SDNETREMOVENRBFROMTIMEQ	OTHER NODE IS CRAZED
	LDAA	SDNETMSGCONTROL
	CMPA	#SDLPCONTROL:RESYNCHREQ
	BNE	SDNETRINTCONFNOTRESYNCH
	JMP	SDNETRINTDEAD	IF RESYNCH REQUEST, JUST KILL THIS NRB
SDNETRINTCONFNOTRESYNCH
	JMP	SDNETRINTSENDQUIT
	PAGE
SDNETRINTELSE	EQU	*
	LDX	#0	SET SAVED COUNT TO ZERO
	STX	SDNETPHASE2CNTSV
SDNETRINTMSGOK	EQU	*	GOT THE MESSAGE OK!
*
*	IF SDNETMSGRVPOS - SDNETNRB:XVPOS  > SDNETNRB:XMTRDY
*	OR SDNETMSGRVPOS < SDNETNRB:XVPOS
*	THEN OTHER COMPUTER IS CONFUSED!!!
*	ELSE
*		LET DELTA:= THE DIFFERENCE
*		SDNETNRB:XMTBUF(EMPTY):=...(EMPTY)+DELTA (ACROSS BUFFER BOUNDARIES)
*		SDNETNRB:XVPOS:=SDNETMSGXVPOS
*	FI
*	NOTE: IF OTHER NODE IS NOT CONFUSED,...
*		THEN SDNETMSGVPOS >= SDNETNRB:XVPOS!
*
	LDD	SDNETMSGRVPOS	COMPUTE DELTA = RDRVPOS - XVPOS
	SUBD	SDNETNRB:XVPOS,X
	STD	SDNETMSGELTA	SAVE THE DELTA
	CLRA		COMPUTE XMTRDY COUNT
	LDAB	SDNETNRB:XMTBUF+SDNETBUF:FILL+1,X	= FILL-EMPTY
	SUBB	SDNETNRB:XMTBUF+SDNETBUF:EMPTY+1,X
	SUBD	SDNETMSGELTA	IF DELTA > XMTCNT THEN HE'S CONFUSED
	BCS	SDNETRINTCONFUSED	B/ OTHER NODE IS DEFINITELY CONFUSED
	LDAB	SDNETNRB:XMTBUF+SDNETBUF:EMPTY+1,X	OK, ADVANCE TRANSMIT BUFFER POINTER
	ADDB	SDNETMSGELTA+1
	STAB	SDNETNRB:XMTBUF+SDNETBUF:EMPTY+1,X
	LDD	SDNETNRB:XVPOS,X	ADVANCE XVPOS BY DELTA
	ADDD	SDNETMSGELTA
	STD	SDNETNRB:XVPOS,X
	LDD	SDNETMSGREADYCOUNT	SAVE THE RECEIVED READY COUNT
	STD	SDNETNRB:RCVDRDY,X
	LDX	SDNETMSGXMITCOUNT	ANY DATA RECEIVED ?
	BEQ	SDNETRINTMSGOK3	B/ NO
	LDX	SDNETNRBPTR	YES, AND WE RECEIVED IT CORRECTLY
	LDAB	SDNETNRB:RCVBUF+SDNETBUF:FILL+1,X
	ADDB	SDNETPHASE2CNTSV+1	BUMP # BYTES RECEIVED CORRECTLY
	STAB	SDNETNRB:RCVBUF+SDNETBUF:FILL+1,X
	LDAA	SDNETNRB:NODE,X	IS THIS THE BROADCAST RECEIVER NRB ?
	BEQ	SDNETRINTCASTRCVD	B/ YES, LEAVE :RVPOS ALONE
*	ALSO, LEAVE NRB ZERO IN TIMEQ IF IT IS ALREADY THERE
*	THIS ENSURES THAT IT GETS ITS CHANCE TO BROADCAST CORRECTLY
	LDD	SDNETNRB:RVPOS,X	ADJUST POSITION IN RECEIVED VIRTUAL FILE
	ADDD	SDNETPHASE2CNTSV	= # BYTES RETAINED BY PHASE 2
	STD	SDNETNRB:RVPOS,X	CARRY OUT IS LOST --> MODULO 2^16, AS SPEC'D
	PAGE
SDNETRINTMSGOK3
	CLR	SDOS+SDOS:SURPRISE	SIGNAL SCHEDULER HERE
	JSR	SDNETREMOVENRBFROMTIMEQ	IN CASE WE AREN'T GOING TO SET ANOTHER TIMEOUT
	LDAB	SDNETMSGCONTROL	NOW BRANCH ON CONTROL MESSAGE TYPE
	LDAA	SDNETNRB:STATE,X
	CMPA	#NODESTATE:ACTIVATING	TRYING TO ACTIVATE THIS NODE ?
	BEQ	SDNETRINTACTIVATING	B/ YES
	CMPB	#SDLPCONTROL:RESYNCHQUIT-1	A BROADCAST STYLE CONTROL CODE ?
	BHI	SDNETRINTSENDQUIT	B/ NOT A VALID CONTROL CODE, BUT CRC IS RIGHT !?
	ASLB		DO TABLE JUMP ON CONTROL CODE
	IF	M6800!M6801
	STAB	SDNETCONTROL1+1
	LDX	SDNETCONTROL1
	LDAB	(SDNETCONTROL&$FF)+1,X
	PSHB
	LDAB	SDNETCONTROL&$FF,X
	PSHB
	LDX	SDNETNRBPTR	GRAB NRB POINTER AGAIN
*	LDAA	SDNETNRB:STATE,X	FOR CONVENIENCE OF CALLED ROUTINE
	RTS		GO TO CONTROL MESSAGE HANDLER
	ELSE	(M6809)
	LDY	#SDNETCONTROL
	JMP	[B,Y]
	FIN

SDNETRINTCASTRCVD	BRA	SDNETSIGNALENBRCV	GO WAKE UP BROADCAST LISTENER TASK
	PAGE
SDNETRINTACTIVATING	; WE ARE TRYING TO ACTIVATE THIS NRB
	CMPB	#SDLPCONTROL:RESYNCHREQ	DID WE GET A "RESYNCH" MESSAGE ?
	BEQ	SDNETRINTRESYNCH1	B/ THAT'S OK WITH US
	CMPB	#SDLPCONTROL:RESYNCHED	DID WE GET PROPER RESPONSE TO "RESYNCH" ?
	BNE	SDNETRINSTANT	B/ NO, GO SEND INSTANT RESYNCH AGAIN!
	LDAA	#NODESTATE:ACTIVATED	YES! SWITCH TO ACTIVATED
	BRA	SDNETRNEWSTATE

SDNETRINTRESYNCH	; RE-SYNCH REQUEST
	LDAB	SDNETMSGXMITCOUNT	DID WE RECEIVE ANY DATA WITH "RESYNCH" ?
	ORAB	SDNETMSGXMITCOUNT+1	...?
	BNE	SDNETRINTDEAD	B/ YES, THAT'S TOTAL GARBAGE...
	CMPA	#NODESTATE:INACTIVE	RESYNCH REQUEST LEGAL ONLY IF INACTIVE
	BCS	SDNETRINTDEAD	B/ NO SUCH LUCK, KILL THIS GUY.
	CMPA	#NODESTATE:RESYNCHED	ACTIVATING OR RESYNCHED STATE ?
	BHI	SDNETRINTDEAD	B/ NO, KILL OFF THE NRB
SDNETRINTRESYNCH1	; SWITCH TO "RESYNCHED" STATE
	LDAA	#NODESTATE:RESYNCHED	OK, SWITCH TO "RESYNCHED" STATE
SDNETRNEWSTATE	; SET NEW STATE TO (A) AND SEND INSTANT RESPONSE
	STAA	SDNETNRB:STATE,X
SDNETRINSTANT	; SEND RESPONSE INSTANTLY
	CLRB		SET TIME DELAY = 0
	JSR	SDNETPUTNRBINTIMEQ
	JMP	SDNETINTDONE

SDNETRINTRESYNCHED	; RE-SYNCHRONIZED MESSAGE WAS RECEIVED
	CMPA	#NODESTATE:ACTIVATED	THEN ITS OK...
	BNE	SDNETRINTSENDQUIT	B/ NOT LEGAL HERE
	BRA	SDNETRINTNORMAL1	WE DON'T NEED TO SEND INSTANT RESPONSE
	PAGE
SDNETRINTWANTQUIT	; "WANT TO QUIT" REQUEST RECEIVED
	CMPA	#NODESTATE:INACTIVE	IN THIS STATE, ITS NOT RIGHT TO GET "WANTQUIT"
	BEQ	SDNETRINTSENDQUIT	SO SEND A QUIT TO KILL NODE OFF
	LDAA	#NODESTATE:AGREEQUIT	GO TO "AGREE TO QUIT" STATE
	BRA	SDNETRNEWSTATE	GO SET STATE AND SEND INSTANT RESPONSE

SDNETRINTQUIT	; "QUIT!" MESSAGE RECEIVED
SDNETRINTDEAD	; OTHER NODE CROAKED OR WENT CRAZY, GIVE UP!
	JSR	SDNETREMOVENRBFROMTIMEQ	SO HE BECOMES VERY UNINTERESTING
	LDAA	#NODESTATE:DEAD	MARK THE NODE STATE APPROPRIATELY
	STAA	SDNETNRB:STATE,X
	CLR	SDNETNRB:XVPOS,X	ZERO THE TRANSMIT VIRTUAL POSITION
	CLR	SDNETNRB:XVPOS+1,X
	CLR	SDNETNRB:RVPOS,X	ZERO THE RECEIVE VIRTUAL POSITION
	CLR	SDNETNRB:RVPOS+1,X
	LDAA	#SDNETRETRYCOUNT	SET RETRY COUNTER TO MAX???
	STAA	SDNETNRB:RETRY,X
*	IT DOESN'T DO ANY GOOD TO KILL TRANSMIT BUFFER POINTERS,
*	SINCE USER/LISTENER TASK MIGHT BE FILLING TRANSMIT BUFFER AT THIS INSTANT
SDNETSIGNALENBRCV	; SIGNAL THE SCHEDULER AND ENABLE TO RECEIVE
	CLR	SDOS+SDOS:SURPRISE	SIGNAL THE SCHEDULER
	JMP	SDNETINTENBRCV	GO WAKE THE LISTENER TASK!
	PAGE
SDNETRINTNORMAL	; "NORMAL" MESSAGE RECEIVED
	CMPA	#NODESTATE:RESYNCHED-1	THIS IS OK...
*	THIS TEST ALSO INCLUDES ACTIVATED, CONNECTEDR AND CONNECTEDS
	BHI	SDNETRINTNORMAL1	GO DECIDE WHAT TO DO NEXT
	CMPA	#NODESTATE:WANTQUIT	MIGHT BE RESPONSE TO THIS IF MISSED
	BEQ	SDNETRINSTANT	B/ YES, GO SEND HIM OUR REQUEST AGAIN
SDNETRINTAGREEQUIT	; "AGREE TO QUIT" MESSAGE RECEIVED
SDNETRINTSENDQUIT	; CHANGE STATE TO QUIT AND SEND RESPONSE
	LDAA	#NODESTATE:QUIT	MARK THE NODE AS DEAD
	BRA	SDNETRNEWSTATE	AND GO SEND "QUIT!" RESPONSE (JUST ONCE!)

SDNETRINTNORMAL1	; DECIDE IF WE SHOULD RESPOND OR NOT
	LDAA	#NODESTATE:CONNECTEDR	ASSUME WE WILL RESPOND INSTANTLY
	STAA	SDNETNRB:STATE,X	(I.E., WE WILL XMIT AND THEN WAIT FOR MESSAGE)
	CLRA		COMPUTE TRANSMIT BUFFER READY TO (A,B)
	LDAB	SDNETNRB:XMTBUF+SDNETBUF:FILL+1,X	ANY DATA BYTES TO SEND ?
	SUBB	SDNETNRB:XMTBUF+SDNETBUF:EMPTY+1,X
	BEQ	SDNETRINTNORMAL3	B/ NO DATA TO SEND
	SUBD	SDNETXMITTHRESHOLDVALUE	ENOUGH BYTES TO SEND EFFICIENT MESSAGE ?
	BCS	SDNETRINTNORMAL1B	B/ NOT ENOUGH TO SEND
	LDD	SDNETNRB:RCVDRDY,X	ENOUGH TO SEND, DOES RECEIVER HAVE ROOM FOR ALL OF IT ?
	SUBD	#SDNETXMITTHRESHOLD
	BCC	SDNETRINSTANT	B/ YES, SEND REPLY NOW!
SDNETRINTNORMAL1B	; "SOMETHING TO SEND" EXCUSE IS NOT GOOD ENOUGH YET
	LDX	SDNETMSGXMITCOUNT	DID OTHER NODE SEND US SOME DATA ?
	BEQ	SDNETINTNORMAL2	B/ NO, TAKE OUR TIME ABOUT RESPONDING
SDNETRINTNORMAL1A
	LDX	SDNETNRBPTR	YES, DO WE HAVE ENOUGH RECEIVER BUFFER ROOM...
	CLRA		= 256-(FILL-EMPTY)
	LDAB	SDNETNRB:RCVBUF+SDNETBUF:EMPTY+1,X
	SUBB	SDNETNRB:RCVBUF+SDNETBUF:FILL+1,X
	DECB
	SUBD	#SDNETXMITTHRESHOLD	FOR OTHER NODE TO SEND EFFICIENT MESSAGE ?
	BCC	SDNETRINSTANT	B/ YES, SEND OUR RESPONSE NOW!
SDNETINTNORMAL2	; RESPOND TO OTHER NODE'S TRANSMISSION AFTER SUITABLE DELAY
	LDX	SDNETNRBPTR	SINCE (X) IS GARBAGE HERE
	LDAA	#NODESTATE:CONNECTEDS	REMEMBER WE ARE "SPOSD TO SEND" NEXT
	STAA	SDNETNRB:STATE,X
	LDAB	#SDNETRESPONDTIME	DELAY A LITTLE TO LET TRANSMIT BUFFER FILL
	JSR	SDNETPUTNRBINTIMEQ	SHORTENING "RESPONDTIME"...
SDNETINTNORMAL2A
	JMP	SDNETINTENBRCV

SDNETINTDONEJ
	JMP	SDNETINTDONE	INCREASES RESPONSIVENESS

SDNETRINTNORMAL3	; NOTHING TO SEND
	LDX	SDNETMSGXMITCOUNT	DID OTHER NODE SEND US DATA ?
	BEQ	SDNETINTNORMAL2A	B/ NO, DON'T SEND A RESPONSE
	BRA	SDNETRINTNORMAL1A	YES, GO SEE IF ENOUGH RECEIVER ROOM
	PAGE
SDNETINTDESIREKILL	; SOCKET MANAGER WANTS TO KILL AN NRB
	LDX	SDNETDESIREKILLNRBPTR	AND THIS IS THE VIRGIN TO BE SACRIFICED
	INC	SDNETDESIREKILLLOCK	RELEASE THE LOCK ON THE VIRGIN
SDNETRINTDEADJ1
	BRA	SDNETRINTDEAD	AND GO MARK HER AS DEAD

SDNETINTDESIREQUIT	; SOCKET MANAGER WANTS TO DISCONNECT FROM AN NRB
	LDX	SDNETDESIREQUITNRBPTR	AND THIS IS THE GUY
	INC	SDNETDESIREQUITLOCK	LET GO THE LOCK
	STX	SDNETNRBPTR	SAVE THE NRB BASE
	JSR	SDNETREMOVENRBFROMTIMEQ	TAKE NRB OUT OF WHERE HE IS
	LDAA	SDNETNRB:STATE,X
	CMPA	#NODESTATE:CONNECTEDR	STILL CONNECTED ?
	BEQ	SDNETINTDESIREQUIT1	B/ YEP.
	CMPA	#NODESTATE:CONNECTEDS	...?
	BNE	SDNETRINTDEADJ1	B/ NO, KILL IT OFF QUICK!
SDNETINTDESIREQUIT1
	LDAA	#NODESTATE:WANTQUIT	YES, MARK HIM AS "WANT QUIT"
	JMP	SDNETRNEWSTATE	GO SEND THE REQUEST

SDNETINTDESIREDELAYEDXMIT	; SOCKET MANAGER WANTS TO TRANSMIT DATA...
*	BUT DOESN'T HAVE ENOUGH DATA TO JUSTIFY IT RIGHT NOW
*	SO WE'LL LIGHT A FUSE, AND SEND IT LATER WHEN FUSE GOES OFF,
*	OR MORE DATA ARRIVES
	LDX	SDNETDESIREDELAYEDXMITNRBPTR	GET NRB SELECTED
	INC	SDNETDESIREDELAYEDXMITLOCK	FREE THE LOCK
	STX	SDNETNRBPTR
	CPX	SDNETNRB:TIMEQFLINK,X	IS NRB STILL IDLE ?
	BNE	SDNETINTDONEJ	B/ NO, IGNORE STARTIO REQUEST
	LDAA	SDNETNRB:STATE,X	DO WE EXPECT TO RECEIVE NEXT ?
	CMPA	#NODESTATE:CONNECTEDR	...?
	BEQ	SDNETINTNORMAL2	YES, PLACE NRB IN TIMEQ FOR LATER TRANSMISSION
	CMPA	#NODESTATE:INACTIVE	IS THIS NRB CURRENTLY ASLEEP ?
	BNE	SDNETINTDONEJ	B/ NO, SOCKET NOT IN STATE IN WHICH START IO ISSUED, SO IGNORE THE STARTIO
**** WHAT IF BROADCAST??? SET RCVDRDY = MAX???
	LDAA	#NODESTATE:ACTIVATING	MUST BE TIME TO WAKE THIS GUY UP
	JMP	SDNETRNEWSTATE	GO SET STATE AND TRANSMIT
	PAGE
	IF	M6800!M6801
SDNETCONTROL1	FDB	SDNETCONTROL&$FF00
	FIN
*
*	BRANCH TABLE USED TO BRANCH ON RECEIVED MESSAGE TYPE
SDNETCONTROL	FDB	SDNETRINTNORMAL	SDLPCONTROL:NORMAL
	FDB	SDNETRINTRESYNCH	SDLPCONTROL:RESYNCH
	FDB	SDNETRINTRESYNCHED	SDLPCONTROL:RESYNCHED
	FDB	SDNETRINTWANTQUIT	SDLPCONTROL:WANTQUIT
	FDB	SDNETRINTAGREEQUIT	SDLPCONTROL:AGREEQUIT
	FDB	SDNETRINTQUIT	SDLPCONTROL:QUIT
	PAGE
*	SDNETREMOVENRBFROMTIMEQ -- REMOVES NRB SELECTED BY SDNETNRBPTR...
*	FROM THE TIME PROCESSING QUEUE
*	PRESERVES SDNETNRBPTR
*
SDNETREMOVENRBFROMTIMEQ
	LDX	SDNETTIMEQHEAD+SDNETNRB:TIMEQFLINK	FIND FIRST NRB IN QUEUE
	LDAA	SDNETTIMEQHEAD+SDNETNRB:TIMEQDELTA	SET HIS DELAY...
	STAA	SDNETNRB:TIMEQDELTA,X	TO REMAINING DELAY BEFORE TIMEOUT
	LDX	SDNETNRBPTR	THIS IS THE GUY TO PULL OUT OF THE QUEUE
	LDAA	SDNETNRB:TIMEQDELTA,X	GRAB HIS DELAY
	PSHA		AND SAVE IT SO WE CAN ADD TO NEXT NRB'S DELAY
	LDD	SDNETNRB:TIMEQFLINK,X	FIND NRB THAT FOLLOWS ONE TO BE REMOVED
	LDX	SDNETNRB:TIMEQBLINK,X	FIND NRB PRECEDING ONE TO BE REMOVED
	STD	SDNETNRB:TIMEQFLINK,X	MAKE PRECEDING NRB POINT TO NEXT NRB
	STX	SDNETINTTEMPX	SAVE PRECEDING NRB'S ADDRESS
	LDX	SDNETNRB:TIMEQFLINK,X	GRAB ADDRESS OF FOLLOWING NRB
	PULA		GET DELAY FROM NRB BEING REMOVED
	ADDA	SDNETNRB:TIMEQDELTA,X	ADD TO DELAY OF FOLLOWING NRB
	STAA	SDNETNRB:TIMEQDELTA,X	AND UPDATE FOLLOWING NRB DELAY
	LDD	SDNETINTTEMPX	MAKE FOLLOWING NRB POINT BACKWARDS TO PRECEDING NRB
	STD	SDNETNRB:TIMEQBLINK,X
	LDX	SDNETTIMEQHEAD+SDNETNRB:TIMEQFLINK	SET TIME DELAY...
	LDAA	SDNETNRB:TIMEQDELTA,X	TO DELTA IN FIRST NRB OF TIMEQ
	STAA	SDNETTIMEQHEAD+SDNETNRB:TIMEQDELTA
SDNETLINKNRBTOSELF	; ENTRY POINT USED BY INITZ ROUTINES
	LDX	SDNETNRBPTR	NOW MAKE REMOVED NRB POINT TO SELF
	LDD	SDNETNRBPTR
	STD	SDNETNRB:TIMEQFLINK,X
	STD	SDNETNRB:TIMEQBLINK,X
	RTS		AND EXIT
	PAGE
*
*	SDNETPUTNRBINTIMEQ -- PLACES NRB SELECTED BY SDNETNRBPTR...
*	INTO TIME PROCESSING QUEUE, ACCORDING TO (B)
*	NRB SELECTED BY SDNETNRBPTR MUST NOT BE IN TIME QUEUE ALREADY
*	SDNETNRBPTR IS SET TO FIRST NRB IN Q WHEN DONE
*
SDNETPUTNRBINTIMEQ
	LDX	SDNETTIMEQHEAD+SDNETNRB:TIMEQFLINK	WHIZ DOWN QUEUE LOOKING FOR PROPER PLACE
	LDAA	SDNETTIMEQHEAD+SDNETNRB:TIMEQDELTA	BUT FIRST, PLACE REMAINING TIME...
	STAA	SDNETNRB:TIMEQDELTA,X	INTO FIRST BLOCK ON LIST
	CPX	#SDNETTIMEQHEAD	IS QUEUE EMPTY ?
	BEQ	SDNETPUTNRBINQ2	B/ Q IS EMPTY, PUT NEW GUY IN (ANYWHERE!)
SDNETPUTNRBINQ1	; CHECK TO SEE IF THIS IS PROPER INSERT POINT
	SUBB	SDNETNRB:TIMEQDELTA,X	DECREASE TOTAL DELAY BY DELTA
	BCS	SDNETPUTNRBINQ3	B/ WENT NEGATIVE, THIS IS INSERT POINT!
	LDX	SDNETNRB:TIMEQFLINK,X	STILL POSITIVE, ON TO NEXT NRB IN Q
	CPX	#SDNETTIMEQHEAD	AT END OF Q ?
	BNE	SDNETPUTNRBINQ1	B/ NOPE, GO CHECK AGAIN
SDNETPUTNRBINQ2	; INSERT NEW NRB IN Q AT (X)
	PSHB		SAVE COMPUTED DELTA
	LDD	SDNETNRB:TIMEQBLINK,X	FIND NRB PREVIOUS TO INSERT POINT
	STX	SDNETINTTEMPX	SAVE INSERT POINT ADDRESS
	LDX	SDNETNRBPTR	MAKE INSERTED NODE POINT BACKWARD TO PREV NRB
	STD	SDNETNRB:TIMEQBLINK,X
	LDD	SDNETINTTEMPX	MAKE INSERTED NODE POINT TO INSERT POINT NRB
	STD	SDNETNRB:TIMEQFLINK,X
	PULB		GRAB COMPUTED DELTA
	STAB	SDNETNRB:TIMEQDELTA,X	AND SAVE IT IN INSERTED NRB
	LDX	SDNETNRB:TIMEQBLINK,X	MOVE BACK TO PREV NRB
	LDD	SDNETNRBPTR	MAKE PREV NRB POINT TO NEWLY INSERTED NRB
	STD	SDNETNRB:TIMEQFLINK,X
	LDX	SDNETINTTEMPX	MAKE INSERT POINT BACK LINK =...
	STD	SDNETNRB:TIMEQBLINK,X	NEWLY INSERTED NODE
	LDX	SDNETTIMEQHEAD+SDNETNRB:TIMEQFLINK	GET POINTER TO FIRST NRB ON Q
	STX	SDNETNRBPTR	THIS IS THE MOST INTERESTING GUY IN THE Q
	LDAA	SDNETNRB:TIMEQDELTA,X	GET REMAINING DELAY
	STAA	SDNETTIMEQHEAD+SDNETNRB:TIMEQDELTA	AND SAVE IT AS NEXT TIMEOUT
	RTS		WHEW! ALL DONE

SDNETPUTNRBINQ3	; THIS IS INSERT POINT, ADJUST DELTA IN INSERT POINT NRB
	TBA		SAVE NEGATIVE DIFFERENCE
	ADDB	SDNETNRB:TIMEQDELTA,X	COMPUTE INSERTED NRB'S ACTUAL DELTA
	NEGA		= INSERT POINT NRB'S NEW DELTA
	STAA	SDNETNRB:TIMEQDELTA,X
	BRA	SDNETPUTNRBINQ2	GO INSERT NEW NRB
	PAGE
SDNETNRBPTR	RMB	2	POINTER TO NODE REPRESENTATIVE BLOCK
SDNETXDELAYMASK	FDB	0	QUADRATIC TRANSMIT CONFLICT RESOLUTION WINDOW MASK
SDNETMSGDELTA	FDB	0	= SDNETMSGVPOS-SDNETNRB:XVPOS
SDNETDESIREDELAYEDXMITNRBPTR	FDB	0	POINTER TO NRB
SDNETDESIREDELAYEDXMITLOCK	FCB	1	LOCK FOR SDNETDESIREDELAYEDXMITNRBPTR
SDNETDESIREXMITNRBPTR	FDB	0	POINTER TO NRB
SDNETDESIREXMITLOCK	FCB	1	LOCK FOR SDNETDESIREXMITNRBPTR
SDNETDESIRERCVNRBPTR	FDB	0	POINTER TO NRB
SDNETDESIRERCVLOCK	FCB	1	LOCK FOR SDNETDESIRERCVNRBPTR
SDNETDESIREQUITNRBPTR	FDB	0	POINT TO NRB
SDNETDESIREQUITLOCK	FCB	1	LOCK FOR SDNETDESIREQUITNRBPTR
SDNETDESIREKILLNRBPTR	FDB	0	POINTER TO NRB
SDNETDESIREKILLLOCK	FCB	1	LOCK FOR SDNETDESIREKILLNRBPTR
SDNETBUFCNT	FCB	0	BUFFER BYTE COUNT; CONTROLS SMALL LOOPS
SDNETBUFPTR	FDB	0	TENTATIVE RECEIVER BUFFER FILL POINTER
SDNETINTTEMPX	FDB	0	TEMPORARY SAVE FOR X REGISTER

SDNETMSGTO	RMB	1	WHO MESSAGE WAS SENT TO
SDNETMSGFROM	FCB	0	WHO WE RECEIVED THE MESSAGE FROM
SDNETMSGCONTROL	FCB	SDLPCONTROL:NORMAL	CONTROL BYTE SENT BY OTHER COMPUTER
SDNETMSGRVPOS	RMB	2	VIRTUAL POSITION OF OUR FILE THAT OTHER COMPUTER HAS
SDNETMSGREADYCOUNT	RMB	2	AVAILABLE BUFFER SPACE THAT OTHER COMPUTER HAS
SDNETMSGXMITCOUNT	RMB	2	# DATA BYTES SENT BY OTHER COMPUTER IN THIS MESSAGE
SDNETMSGXMITBASE	RMB	2	VIRTUAL ADDRESS MOD 2**16 OF FIRST DATA BYTE IN MESSAGE
SDNETMSGDATA	RMB	SDNETMSGDATASIZEMAX	PLACE FOR RECEIVER TO RECEIVE TRANSMITTED DATA
SDNETPHASE1CNT	RMB	2	NUMBER OF DATA BYTES TO IGNORE
SDNETPHASE2CNT	RMB	2	NUMBER OF DATA BYTES TO PLACE INTO RECEIVER BUFFER
SDNETPHASE3CNT	RMB	2	NUMBER OF DATA BYTES TO IGNORE
SDNETMSGPART1END	RMB	2	POINTER TO END OF 1ST PART OF DATA
SDNETMSGPART2	RMB	2	POINTER TO BEGIN OF 2ND PART OF DATA
SDNETMSGPART2END	RMB	2	POINTER TO END OF 2ND PART OF DATA

SDNETTIMEOUTFUSE	FCB	0	FUSE FOR COLLISION RESOLUTION AND EOT SEARCH
SDNETTIMEOUTROUTINE	FDB	0	POINTS TO TIMEOUT HANDLER
CLOCKTICKS	FCB	0	60THS OF A SECOND NOT YET TOLD TO SDOS
	PAGE
*
*	STATISTICS ABOUT LINK
*
SDNETENBRCVCOUNT	FDB	0	# TIMES WE ENABLED RECIEVER TO HEAR NEW MESSAGE
SDNETBADCRCCOUNT	FDB	0	# MSGS WITH BAD CRC RECEIVED
SDNETGOODCRCCOUNT	FDB	0	# MSGS WITH GOOD CRC RECEIVED
SDNETOVRUNCOUNT	FDB	0	# MSGS FOR WHICH WE WEREN'T FAST ENOUGH TO GET ALL THE BYTES
SDNETMISSEDEOTCOUNT	FDB	0	# TIMES WE SEARCHED FOR EOT AND TIMED OUT
SDNETNOCLOCKCOUNT	FDB	0	# TIMES RECEIVED MESSAGE STOPPED IN MIDDLE
SDNETCOLLISIONCOUNT	FDB	0	# TIMES THAT A COLLISION OCCURRED ON TRANSMIT
SDNETXMITOKCOUNT	FDB	0	# TIMES WE SUCCESSFULLY SENT A COMPLETE MESSAGE
SDNETETHERBUSYCOUNT	FDB	0	# TIMES ETHER WAS BUSY WHEN WE WANTED TO TRANSMIT
SDNETTIMEDOUTCOUNT	FDB	0	# TIMES WE TIMED OUT EXPECTING A RESPONSE

SDNETTIMEQHEAD1	FDB	SDNETTIMEQHEAD	SDNETNRB:TIMEQFLINK
	FDB	SDNETTIMEQHEAD	SDNETNRB:TIMEQBLINK
	FCB	0	SDNETNRB:TIMEQDELTA
SDNETTIMEQHEAD	EQU	SDNETTIMEQHEAD1-SDNETNRB:TIMEQFLINK

SDNETSTATECONTROL1	FDB	SDNETSTATECONTROL&$FF00	USED TO INDEX SDNETSTATECONTROL
*
*	TRANSLATE TABLE USED TO CONVERT SDNETNRB:STATE INTO SDLPCONTROL:XXXX
*
SDNETSTATECONTROL
	FCB	SDLPCONTROL:QUIT	NODESTATE:DEAD
	FCB	SDLPCONTROL:AGREEQUIT	NODESTATE:AGREEQUIT
	FCB	SDLPCONTROL:WANTQUIT	NODESTATE:WANTQUIT
	FCB	SDLPCONTROL:RESYNCHED	NODESTATE:INACTIVE
	FCB	SDLPCONTROL:RESYNCHREQ	NODESTATE:ACTIVATING
	FCB	SDLPCONTROL:RESYNCHED	NODESTATE:RESYNCHED
	FCB	SDLPCONTROL:NORMAL	NODESTATE:ACTIVATED
	FCB	SDLPCONTROL:NORMAL	NODESTATE:CONNECTEDR
	FCB	SDLPCONTROL:NORMAL	NODESTATE:CONNECTEDS
	FCB	SDLPCONTROL:QUIT	NODESTATE:QUIT

SDNETXMITTHRESHOLDVALUE	; CELL HOLDING MIN(SDNETXMTBUFOVFTHRESHOLD,SDNETXMITTHRESHOLD)
	IF	SDNETXMTBUFOVFTHRESHOLD>>SDNETXMITTHRESHOLD
	FDB	SDNETXMITTHRESHOLD	ENOUGH BYTES FOR "EFFICIENT" MESSAGE
	ELSE
	FDB	SDNETXMTBUFOVFTHRESHOLD
	FIN

SDNETPATCH	RPT	50
	FCB	0
