NEW
  AUTO 3,1
				.LIST OFF	
*--------------------------------------
FRM.GetTargetSKT.TCPUDP
				ldy #S.TCPUDP.SRCPORT
				lda (ZPFrameInPtr),y
				sta SKT.REM.ADDR+S.SOCKADDR.PORT+1
				iny
				lda (ZPFrameInPtr),y
				sta SKT.REM.ADDR+S.SOCKADDR.PORT
				
				iny						#S.TCPUDP.DSTPORT
				lda (ZPFrameInPtr),y
				sta SKT.LOC.ADDR+S.SOCKADDR.PORT+1
				iny
				lda (ZPFrameInPtr),y
				sta SKT.LOC.ADDR+S.SOCKADDR.PORT

FRM.GetTargetSKT.RAW
				ldy #S.IP.SRC+3
				ldx #3
				
.1				lda (ZPFrameInPtr),y
				sta SKT.REM.ADDR+S.SOCKADDR.ADDR,x
				dey
				dex
				bpl .1
				
				ldy #S.IP.DST+3
				ldx #3
				
.2				lda (ZPFrameInPtr),y
				sta SKT.LOC.ADDR+S.SOCKADDR.ADDR,x
				dey
				dex
				bpl .2
				
				rts				
*--------------------------------------
* FRM.NewIP
*  In:
*  Y,A = DataLen
*  X = S.IP.PROTOCOL.xxx
* Out:
*  Y,A = Frame PTR
*  X = hMem
*--------------------------------------
FRM.NewIP		stx	.8+1
				>STYA ZPDataOutLen
				cpx #S.IP.PROTOCOL.TCP
				bne .1
				lda #S.TCP
				bra .4
				
.1				cpx #S.IP.PROTOCOL.UDP
				bne .2
				lda #S.UDP
				bra .4
				
.2				lda #S.IP
				bra .4
				
.4				sta	.5+1 				save Header len for reset later
				clc
				adc ZPDataOutLen
				sta ZPFrameOutLen
				tay
				
				lda #0
				adc ZPDataOutLen+1
				sta ZPFrameOutLen+1
				
				>SYSCALL2 getmem
				bcs .9
				
				stx hFrameOut
				>STYA ZPFrameOutPtr

				ldy #0
				
.5				ldx #$ff				Self Modified, header length
				
				lda #0

.6				sta (ZPFrameOutPtr),y
				iny
				dex
				bne .6
				
				tya
*				clc
				adc ZPFrameOutPtr
				sta ZPDataOutPtr
				
				lda #0
				adc ZPFrameOutPtr+1
				sta ZPDataOutPtr+1
				
				lda IPCFG+S.NETCFG.DevFlags
				and #S.DCB.NIC.FLAGS.IPOFFLOAD
				bne .7
				
				ldy #S.ETH.EII.TYPE
				lda /S.ETH.EII.TYPE.IP
				sta (ZPFrameOutPtr),y		
				iny
				lda #S.ETH.EII.TYPE.IP
				sta (ZPFrameOutPtr),y

				ldy #S.IP.V.IHL.DSCP.ECN
				lda #$45
				sta (ZPFrameOutPtr),y
				
*				iny
*				lda #$0
*				sta (ZPFrameOutPtr),y

*				ldy #S.IP.FRAGMENT.FLAGS 
*				sta (ZPFrameOutPtr),y
*				iny
*				sta (ZPFrameOutPtr),y
				
				ldy #S.IP.IDENTIFICATION+1
				
				lda IP.ID
				ldx IP.ID+1
				inc
				bne .61
				inx
				stx IP.ID+1
				
.61				sta IP.ID
				
				sta (ZPFrameOutPtr),y
				dey
				txa
				sta (ZPFrameOutPtr),y

				ldy #S.IP.TTL
				lda #K.IP.TTL
				sta (ZPFrameOutPtr),y
		
.7				ldy #S.IP.PROTOCOL

.8				lda #$ff
				sta (ZPFrameOutPtr),y
				
.9				rts
*--------------------------------------
FRM.SendIP		ldx #3					Copy SRC.IP even if IP offload
				ldy #S.IP.SRC+3			for proper UDP/TCP CRC calculation
				
.1				lda IPCFG+S.IPCFG.IP,x
				sta (ZPFrameOutPtr),y	
				dey
				dex
				bpl .1
				
				lda IPCFG+S.NETCFG.DevFlags
				and #S.DCB.NIC.FLAGS.IPOFFLOAD
				bne .21
				
				ldy #S.IP.TOTAL.LENGTH+1
				lda ZPFrameOutLen
				sec
				sbc #S.ETH.EII
				sta (ZPFrameOutPtr),y
				dey
				lda ZPFrameOutLen+1
				sbc /S.ETH.EII
				sta (ZPFrameOutPtr),y
				
				lda #0
				ldy #S.IP.HDR.CHECKSUM
				sta (ZPFrameOutPtr),y
				iny
				sta (ZPFrameOutPtr),y
				
				stz IP.CHECKSUM			RESET IP CHECKSUM
				stz IP.CHECKSUM+1

				clc

				ldy #S.IP.V.IHL.DSCP.ECN
				ldx #10					10 words for IP Header
				
.2				lda (ZPFrameOutPtr),y
				adc IP.CHECKSUM
				sta IP.CHECKSUM

				iny
				lda (ZPFrameOutPtr),y
				adc IP.CHECKSUM+1
				sta IP.CHECKSUM+1
				iny
				dex
				bne .2
				
				ldy #S.IP.HDR.CHECKSUM
				lda IP.CHECKSUM
				adc #0
				eor #$FF
				sta (ZPFrameOutPtr),y
				iny
				lda IP.CHECKSUM+1
				adc #0
				eor #$FF
				sta (ZPFrameOutPtr),y

.21				ldy #S.IP.PROTOCOL
				lda (ZPFrameOutPtr),y
				cmp #S.IP.PROTOCOL.TCP
				bne .3
				jsr IP.ComputeTCPChecksum
				bra .5
				
.3				cmp #S.IP.PROTOCOL.UDP
				bne .4
				
				lda ZPFrameOutLen
				sec
				sbc #S.IP
				
				ldy #S.UDP.LENGTH+1
				sta (ZPFrameOutPtr),y
				
				lda ZPFrameOutLen+1
				sbc /S.IP
				
				dey
				sta (ZPFrameOutPtr),y				
				
				jsr IP.ComputeUDPChecksum
				bra .5
				
.4				cmp #S.IP.PROTOCOL.ICMP
				bne .5
				jsr IP.ComputeICMPChecksum
				
.5				lda IPCFG+S.NETCFG.DevFlags
				and #S.DCB.NIC.FLAGS.ARPOFFLOAD
				bne .6

				jsr IP.SetDestMAC
				bcs FRM.Queue
				
.6				jsr FRM.Send
				bcs FRM.Queue
				
				jsr	FRM.Discard
				clc
				rts
*--------------------------------------
FRM.Queue		ldy hFrameOut			no hFrame, cannot queue for retry
				beq .9

				ldx FRM.QUEUE.Head
				inx
				cpx #K.FRMQUEUE.SIZE
				bne .1
				
				ldx #0
				
.1				cpx FRM.QUEUE.Tail
				beq FRM.Discard
				
				ldy FRM.QUEUE.Head
				stx FRM.QUEUE.Head

				sta	FRM.QUEUE.State,y
				lda #K.FRMSEND.RETRY
				sta FRM.QUEUE.Retry,y
				lda hFrameOut
				sta FRM.QUEUE.hMem,y
				lda ZPFrameOutLen
				sta FRM.QUEUE.LenL,y
				lda ZPFrameOutLen+1
				sta FRM.QUEUE.LenH,y
				
.9				sec
				rts
*--------------------------------------
FRM.Discard		lda hFrameOut
				beq .9
				>SYSCALL2 FreeMem
				stz hFrameOut
.9				sec
				rts
*--------------------------------------
FRM.Retry		ldx FRM.QUEUE.Tail

.10				cpx FRM.QUEUE.Head
				beq .8					Queue is empty, exit...
				
				lda FRM.QUEUE.hMem,x
				>SYSCALL2 GetMemPtr
				>STYA ZPFrameOutPtr
				
				ldx FRM.QUEUE.Tail
				
				lda FRM.QUEUE.LenL,x
				sta ZPFrameOutLen
				lda FRM.QUEUE.LenH,x
				sta ZPFrameOutLen+1

				lda FRM.QUEUE.State,x
				cmp #ERR.ARP.PENDING
				bne .1

				jsr IP.SetDestMAC		Err is ARP or higher, retry getting MAC
				bcs .2					still error getting dest MAC
				
.1				jsr FRM.Send			try sending again to DRV
				bcc .3
	
.2				ldx FRM.QUEUE.Tail		save error...
				sta FRM.QUEUE.State,x	
				dec FRM.QUEUE.Retry,x	
				bne .8					exit....until next run!
	
.3				ldx FRM.QUEUE.Tail		Success,or max retry, discard entry
				lda FRM.QUEUE.hMem,x
				>SYSCALL2 FreeMem
				
				ldx FRM.QUEUE.Tail
				inx
				cpx #K.FRMQUEUE.SIZE
				bne .5
				
				ldx #0
				
.5				stx FRM.QUEUE.Tail
				bra .10
				
.8				rts
*--------------------------------------
FRM.Send		ldx #3
				
.1				lda ZPFrameOutPtr,x		Get Frame Ptr & Len
				sta IOCTL+S.IOCTL.BUFPTR,x
				dex
				bpl .1
				
FRM.Send.IOCTL	>PUSHW L.IOCTL
				>PUSHBI IOCTL.WRITE
				lda IPCFG+S.NETCFG.DevID
				>SYSCALL2 IOCTL
				rts
*--------------------------------------
MAN
SAVE USR/SRC/LIB/LIBTCPIP.S.FRM
LOAD USR/SRC/LIB/LIBTCPIP.S
ASM
