NEW
  AUTO 3,1
				.LIST OFF	
*--------------------------------------
TCP.IN			jsr FRM.GetTargetSKT.TCPUDP
				jsr SKT.FindMatchingLocRem
				bcs TCP.IN.JMP.DISCARD	no socket, go discard

				ldy #S.TCP.OPTIONS
				lda (ZPFrameInPtr),y
				and #S.TCP.OPTIONS.RST	RST ? go Kill this socket...
				bne TCP.IN.RST			...and discard frame

				ldy #S.SOCKET.TCP.S
				lda (ZPPtrSKT),y
				asl
				tax
				jmp (J.TCP.IN,x)
*--------------------------------------
TCP.IN.RST		lda SKT.TABLE,x
				jsr SKT.shutdown
*--------------------------------------
TCP.IN.JMP.OPENED
TCP.IN.JMP.CLOSED
TCP.IN.JMP.DISCARD
				jmp FRM.DiscardIn
*--------------------------------------
TCP.IN.JMP.LISTEN
				ldy #S.SOCKET.T			Create a new client socket
				lda (ZPPtrSKT),y
				tax						Same type a listening socket
				iny						#S.SOCKET.PROTO
				lda (ZPPtrSKT),y
				jsr SKT.Socket.I		get new socket in ZPTmpPtr1
				bcs TCP.IN.JMP.DISCARD

				jsr SKT.AddToQueueA		Queued successfully ?
				bcs TCP.IN.JMP.DISCARD	no, discard frame and new socket		

				jsr ARP.AddFromFrameInPtr
				lda ZPTmpPtr1
				sta ZPPtrSKT
				lda ZPTmpPtr1+1
				sta ZPPtrSKT+1

				jsr SKT.SetLocAddr
				jsr SKT.SetRemAddr

				jsr SKT.NewTCB
				bcs .99

				jsr TCP.IN.ACKTheSYN
				lda #S.TCP.OPTIONS.SYN+S.TCP.OPTIONS.ACK
				jsr TCP.OUT.SendOptA	SYN received, Send SYN.ACK
				bcs .9

				lda #S.SOCKET.TCP.S.SYNRCVD
				jmp SKT.StoreTCB.S
.9				lda #ERR.SKT.OOS
.99				rts
*--------------------------------------
TCP.IN.JMP.SYNSENT
				ldy #S.TCP.OPTIONS		SYN Send, only accept SYN.ACK packet, then Send ACK 
				lda (ZPFrameInPtr),y
				and #S.TCP.OPTIONS.SYN+S.TCP.OPTIONS.ACK
				cmp #S.TCP.OPTIONS.SYN+S.TCP.OPTIONS.ACK
				bne .9

				jsr SKT.GetTCB
				ldx #3
				ldy #S.TCP.ACKNUM+3

				sec						Check if ACK=OUTNEXTSEQ+1

.1				lda SKT.Cache+S.SOCKET.TCP.OUTNEXTSEQ,x
				adc #0
				sta	SKT.Cache+S.SOCKET.TCP.OUTNEXTSEQ,x 
				eor (ZPFrameInPtr),y
				bne .9
				dey
				dex
				bpl .1

				jsr TCP.IN.ACKTheSYN

				lda #S.TCP.OPTIONS.ACK
				jsr TCP.OUT.SendOptA	SYN.ACK received, Send, ACK
				bcs .9
				lda #S.SOCKET.TCP.S.ESTBLSH
				jmp SKT.StoreTCB.S
.9				lda #S.TCP.OPTIONS.RST
				jsr TCP.OUT.SendOptA	Send RST
				ldx SKT.Index
				lda SKT.TABLE,x
				jmp SKT.shutdown
*--------------------------------------
TCP.IN.JMP.SYNRCVD
				ldy #S.TCP.OPTIONS		SYN Received, SYN.ACK Sent, only accept ACK packet
				lda (ZPFrameInPtr),y
				cmp #S.TCP.OPTIONS.ACK
				bne .8
				jsr SKT.GetTCB
			
				ldx #3
				ldy #S.TCP.ACKNUM+3

				sec

.1				lda	SKT.Cache+S.SOCKET.TCP.OUTNEXTSEQ,x 	Check if ACK=OUTNEXTSEQ+1
				adc #0
				sta SKT.Cache+S.SOCKET.TCP.OUTSENTSEQ,x 		setup SEQNUM
				sta	SKT.Cache+S.SOCKET.TCP.OUTNEXTSEQ,x		...and update NEXTSEQ
				eor (ZPFrameInPtr),y
				bne .8
				dey
				dex
				bpl .1
				lda #S.SOCKET.TCP.S.ESTBLSH
				jmp SKT.StoreTCB.S
			
.8				clc
.9				rts
*--------------------------------------
TCP.IN.JMP.ESTBLSH
				.DO IPDEBUG=1
				jsr DEBUG.IPID
				.FIN
				jsr SKT.GetTCB

				ldy #S.TCP.OPTIONS
				lda (ZPFrameInPtr),y
				and #S.TCP.OPTIONS.ACK	Remote side ACKed data ?
				beq .4
* Ack sent data 
				ldy #S.TCP.ACKNUM+3		Get new ACK number from FrameIn...
				ldx #3					Substract old ACK from socket

				sec

.1				lda (ZPFrameInPtr),y
				pha
				sbc SKT.Cache+S.SOCKET.TCP.OUTSENTSEQ,x
				sta TmpDWord,x
				pla						....and Set SEQ = new SEQ
				sta SKT.Cache+S.SOCKET.TCP.OUTSENTSEQ,x
				dey
				dex
				bpl .1

				lda TmpDWord+3
				ldx TmpDWord+2
				bne .2
				tay
				beq .4

.2				pha

				clc
				adc SKT.Cache+S.SOCKET.TCP.OUTTAIL
				sta SKT.Cache+S.SOCKET.TCP.OUTTAIL

				txa
				adc SKT.Cache+S.SOCKET.TCP.OUTTAIL+1
				and /K.TCP.WSIZE-1
				sta SKT.Cache+S.SOCKET.TCP.OUTTAIL+1
				pla
				clc
				adc SKT.Cache+S.SOCKET.TCP.OUTFREE
				sta SKT.Cache+S.SOCKET.TCP.OUTFREE
				txa
				adc SKT.Cache+S.SOCKET.TCP.OUTFREE+1
				sta SKT.Cache+S.SOCKET.TCP.OUTFREE+1

				lda SKT.Cache+S.SOCKET.TCP.OUTUSED
				sec
				sbc TmpDWord+3
				sta SKT.Cache+S.SOCKET.TCP.OUTUSED
				lda SKT.Cache+S.SOCKET.TCP.OUTUSED+1
				sbc TmpDWord+2
				sta SKT.Cache+S.SOCKET.TCP.OUTUSED+1

				jsr SKT.StoreTCB
* Store incoming data
.4				jsr TCP.IN.SetDataInPtrAndLen
				lda ZPDataInLen			Incoming Data in this frame ?
				ora ZPDataInLen+1
				beq .7					No data, ...

				ldy #S.TCP.SEQNUM+3
				ldx #3

.5				lda (ZPFrameInPtr),y
				eor SKT.Cache+S.SOCKET.TCP.INSEQNUM,x
				bne .9					Missed a frame.....

.51				dey
				dex
				bpl .5

				ldy #S.SOCKET.T			Create a new client socket
				lda (ZPPtrSKT),y
				cmp #S.SOCKET.T.STREAM
				bne .52
				jsr SKT.AddDataToSktIn	yes, queue data if there is room for....
				bra .59
				
.52				lda hFrameIn
				jsr SKT.AddToQueueA
				bcs .9
				
.59				lda ZPDataInLen
				ldy ZPDataInLen+1
				ldx #S.SOCKET.TCP.INSEQNUM
				jsr TCP.AddAYToSktCacheAtX

.6				jsr SKT.StoreTCB		update socket
*				jsr TCP.SetSocketTCPO.ACK	...and ack data
				lda #S.TCP.OPTIONS.ACK
				jsr TCP.OUT.SendOptA
*				bcs *

.7				ldy #S.TCP.OPTIONS
				lda (ZPFrameInPtr),y
				and #S.TCP.OPTIONS.FIN
				beq .8

				lda #S.SOCKET.TCP.S.CLWAIT
				ldy #S.SOCKET.TCP.S
				sta (ZPPtrSKT),y
				jsr TCP.IN.ACKTheFIN
				lda #S.TCP.OPTIONS.FIN+S.TCP.OPTIONS.ACK
				jsr TCP.SetSocketTCPO	FIN received, Send FIN.ACK		
*				jsr TCP.OUT.SendOptA

.8				clc
				rts

.9				sec
				rts
*--------------------------------------
TCP.IN.JMP.LASTACK
				ldy #S.TCP.OPTIONS		only accept ACK packet
				lda (ZPFrameInPtr),y
				bit #S.TCP.OPTIONS.ACK
				beq .8
				ldy #S.SOCKET.TCP.S
				lda #S.SOCKET.TCP.S.TIMEWT
				sta (ZPPtrSKT),y
.8
*--------------------------------------
TCP.IN.JMP.CLWAIT
				clc						Wait for SKT.shutdown
				rts
*--------------------------------------
TCP.IN.JMP.FINWT1
				jsr SKT.GetTCB
				ldy #S.TCP.OPTIONS		FIN sent, accept ACK or FIN/ACK packet
				lda (ZPFrameInPtr),y
				bit #S.TCP.OPTIONS.FIN
				bne .1

				lda #S.TCP.OPTIONS.FIN+S.TCP.OPTIONS.ACK
				jsr TCP.OUT.SendOptA	Send FIN.ACK		
				bcs TCP.IN.JMP.TIMEWT.RTS

				lda #S.SOCKET.TCP.S.FINWT2
				jmp SKT.StoreTCB.S

.1				jsr TCP.IN.ACKTheFIN	FIN/ACK

				lda #S.TCP.OPTIONS.FIN+S.TCP.OPTIONS.ACK
				bra TCP.IN.JMP.FINWT.ACK	Send FIN.ACK		
*--------------------------------------
TCP.IN.JMP.FINWT2
				ldy #S.TCP.OPTIONS		only accept ACK packet
				lda (ZPFrameInPtr),y

				bit #S.TCP.OPTIONS.ACK
				beq TCP.IN.JMP.TIMEWT
				jsr SKT.GetTCB
				jsr TCP.IN.ACKTheFIN

				lda #S.TCP.OPTIONS.ACK

TCP.IN.JMP.FINWT.ACK
				jsr TCP.OUT.SendOptA	FIN received, Send ACK		
				bcs TCP.IN.JMP.TIMEWT.RTS
			
				lda #S.SOCKET.TCP.S.TIMEWT
				jmp SKT.StoreTCB.S
*--------------------------------------
TCP.IN.JMP.CLOSING
				ldy #S.TCP.OPTIONS		only accept ACK packet
				lda (ZPFrameInPtr),y
				bit #S.TCP.OPTIONS.ACK
				beq .1
				ldy #S.SOCKET.TCP.S
				lda #S.SOCKET.TCP.S.TIMEWT
				sta (ZPPtrSKT),y
.1
*				clc
*				rts
*--------------------------------------
TCP.IN.JMP.TIMEWT
				clc						Wait for TCP.Close
TCP.IN.JMP.TIMEWT.RTS
				rts
*--------------------------------------
TCP.IN.ACKTheSYN
				ldy #S.TCP.SEQNUM+3		Get Remote SEQ
				ldx #3
				sec
.3				lda (ZPFrameInPtr),y	Set OUTACK=SEQ+1 for new socket...
				adc #0
				sta SKT.Cache+S.SOCKET.TCP.INSEQNUM,x
				dey
				dex
				bpl .3

				rts
*--------------------------------------
TCP.IN.ACKTheFIN
				jsr TCP.SetSocketTCPO.ACK
				ldx #3
.1				inc	SKT.Cache+S.SOCKET.TCP.INSEQNUM,x
				bne .8
				dex
				bpl .1

.8				rts
*--------------------------------------
TCP.IN.SetDataInPtrAndLen
				ldy #S.IP.TOTAL.LENGTH+1
				lda (ZPFrameInPtr),y
				sec
				sbc #S.IP-S.ETH.EII
				sta ZPDataInLen

				dey
				lda (ZPFrameInPtr),y
				sbc /S.IP-S.ETH.EII
				sta ZPDataInLen+1
				ldy #S.TCP.DATAOFFSET
				lda (ZPFrameInPtr),y
				and #$F0				Get TCP Header len in DWORD
				lsr
				lsr
				sta ZPDataInPtr			TMP Storage

				lda ZPDataInLen
				sec
				sbc ZPDataInPtr			TMP Storage
				sta ZPDataInLen
				bcs .1
				dec ZPDataInLen+1
.1				lda ZPFrameInPtr
				clc
				adc #S.IP
				pha
				lda ZPFrameInPtr+1
				adc /S.IP
				tax
				pla
				clc
				adc ZPDataInPtr			TMP Storage
				bcc .2
				inx
.2				sta ZPDataInPtr
				stx ZPDataInPtr+1
TCP.IN.RTS		rts
*--------------------------------------
TCP.SENDCLOSE	ldx #0

.1				phx
				lda SKT.TABLE,x
				beq .8
				>SYSCALL2 GetMemPtr
				>STYA ZPPtrSKT

				ldy #S.SOCKET.AF
				lda (ZPPtrSKT),y
				cmp #AF.INET
				bne .8
				iny					#S.SOCKET.T
				lda (ZPPtrSKT),y
				cmp #S.SOCKET.T.SEQPACKET
				bcc .8
				ldy #S.SOCKET.TCP.S
				lda (ZPPtrSKT),y
				cmp #S.SOCKET.TCP.S.TIMEWT
				beq .4
				cmp #S.SOCKET.TCP.S.ESTBLSH
				bne .2
				jsr SKT.GetTCB
				jsr TCP.OUT
				bra .8
.2				cmp #S.SOCKET.TCP.S.OPENED
				bne .8
				jsr SKT.GetTCB
				lda #S.TCP.OPTIONS.SYN
				jsr TCP.OUT.SendOptA	Send SYN
				bcs .8					failed ARP lookup....

				lda #S.SOCKET.TCP.S.SYNSENT
				jsr SKT.StoreTCB.S
				bra .8

				lda #S.TCP.OPTIONS.SYN
				jsr TCP.OUT.SendOptA	Send SYN
				bra .8
.4				ldy #S.SOCKET.SQ.hInMem
				lda (ZPPtrSKT),y
				beq .5
				.DO AUXPIPE=1
				>SYSCALL2 FreeStkObj
				.ELSE
				>SYSCALL2 freemem
				.FIN
.5				ldy #S.SOCKET.SQ.hOutMem
				lda (ZPPtrSKT),y
				beq .6

				.DO AUXPIPE=1
				>SYSCALL2 FreeStkObj
				.ELSE
				>SYSCALL2 freemem
				.FIN
.6				plx
				phx
				lda SKT.TABLE,x
				stz SKT.TABLE,x
				>SYSCALL2 freemem
.8				plx
				inx
				cpx #K.SKTTABLE.SIZE
				bne .1

.9				rts
*--------------------------------------
TCP.OUT			lda SKT.Cache+S.SOCKET.TCP.OUTTOSEND+1
				ldy SKT.Cache+S.SOCKET.TCP.OUTTOSEND
				bne .1
			
				tax
				bne .1
*	Y,A=0 : no data to send		
		
				ldy #S.SOCKET.TCP.O
				lda (ZPPtrSKT),y
				bne TCP.OUT.SendOptA	a least an option...
				clc						No data, no flag....exit
.9				rts

.1				cpy #K.TCP.MSS
				pha
				sbc /K.TCP.MSS			OUTDATA > MSS ?
				pla
				bcc .2					no....keep data len

				>LDYAI K.TCP.MSS		yes send only MSS
.2				jsr TCP.NewFrame
				bcs .9

				jsr SKT.GetDataFromSktOut

				ldy #S.TCP.WINDOW
				lda SKT.Cache+S.SOCKET.TCP.INFREE+1
				sta (ZPFrameOutPtr),y
				iny
				lda SKT.Cache+S.SOCKET.TCP.INFREE
				sta (ZPFrameOutPtr),y

TCP.OUT.SEQSEND	lda #S.TCP.OPTIONS.ACK+S.TCP.OPTIONS.PSH
				jsr TCP.OUT.Send
				bcs TCP.OUT.Send.RTS

				lda ZPDataOutLen
				ldy ZPDataOutLen+1
				ldx #S.SOCKET.TCP.OUTNEXTSEQ
				jsr TCP.AddAYToSktCacheAtX

				jmp SKT.StoreTCB		exits with CC
*--------------------------------------
TCP.OUT.SendOptA
				jsr TCP.SetSocketTCPO

				>LDYAI 0
				jsr TCP.NewFrame
				bcs TCP.OUT.Send.RTS

				ldy #S.SOCKET.TCP.INFREE+1
				lda (ZPPtrSKT),y
				tax
				dey
				lda (ZPPtrSKT),y
				ldy #S.TCP.WINDOW+1
				sta (ZPFrameOutPtr),y
				dey
				txa
				sta (ZPFrameOutPtr),y

				ldy #S.SOCKET.TCP.O
				lda (ZPPtrSKT),y

TCP.OUT.Send	ldy #S.TCP.OPTIONS
				sta (ZPFrameOutPtr),y
				bit #S.TCP.OPTIONS.ACK
				beq .2
				
				ldx #3
				ldy #S.TCP.ACKNUM+3

.1				lda SKT.Cache+S.SOCKET.TCP.INSEQNUM,x
				sta (ZPFrameOutPtr),y
				dey
				dex
				bpl .1

.2				ldx #3
				ldy #S.TCP.SEQNUM+3

.3				lda SKT.Cache+S.SOCKET.TCP.OUTNEXTSEQ,x
				sta (ZPFrameOutPtr),y
				dey
				dex
				bpl .3

				sec						DONT Queue if fail

				jsr FRM.SendIP
				bcs TCP.OUT.Send.RTS
				ldy #S.SOCKET.TCP.O
				lda #0
				sta (ZPPtrSKT),y

*				clc
TCP.OUT.Send.RTS
				rts
*--------------------------------------
TCP.SetSocketTCPO.ACK
				lda #S.TCP.OPTIONS.ACK
TCP.SetSocketTCPO
				ldy #S.SOCKET.TCP.O
				ora (ZPPtrSKT),y
				sta (ZPPtrSKT),y
				rts
*--------------------------------------
TCP.NewFrame	ldx #S.IP.PROTOCOL.TCP
				jsr FRM.NewIP
				bcs .9
				jsr SKT.SetFrameOutDstIP

				jsr SKT.SetFrameOutTCPUDPPorts
				ldy #S.TCP.DATAOFFSET
				lda #$50				Header size = 5 DWORDS
				sta (ZPFrameOutPtr),y
				clc
.9				rts
*--------------------------------------
TCP.AddAYToSktCacheAtX
				clc
				adc SKT.Cache+3,x
				sta SKT.Cache+3,x
				tya
				adc SKT.Cache+2,x
				sta SKT.Cache+2,x
				bcc .8
				inc SKT.Cache+1,x
				bne .8
				inc SKT.Cache,x
.8				rts
*--------------------------------------
				.DO IPDEBUG=1
DEBUG.IPID		ldy #S.IP.IDENTIFICATION
				lda (ZPFrameInPtr),y
				>PUSHA
				iny
				lda (ZPFrameInPtr),y
				>PUSHA
				>PUSHBI 2
				>LDYA L.MSG.IPID
				>SYSCALL printf
				rts
				.FIN
*--------------------------------------
MAN
SAVE USR/SRC/LIB/LIBTCPIP.S.TCP
LOAD USR/SRC/LIB/LIBTCPIP.S
ASM
