NEW
  AUTO 3,1
				.LIST OFF	
*/--------------------------------------
* # ARP.Clear
*  Clear ARP Cache
* **In:** 
* ## RETURN VALUE 
*\--------------------------------------
ARP.Clear		lda hARPCache
				bne .1
				
				>LDYAI K.ARPCACHE.SIZE*S.ARPCACHE 
				>SYSCALL2 GetMem0
				bcs .9
				stx hARPCache
				rts

.1				jsr ARP.GetCache

				lda #0
				tay
				
.2				sta (ZPCachePtr),y
				iny
				cpy #K.ARPCACHE.SIZE*S.ARPCACHE
				bne .1

				clc
.9				rts
*/--------------------------------------
* # ARP.Query
*  Query ARP Cache and returns HW address
* **In:**
*  PUSHW PTR to MAC (to fill)
*  PUSHW PTR to IP
* ## RETURN VALUE
*  CC: hit: MAC filled
*  CS: missed 
*\--------------------------------------
ARP.Query		>PULLW ZPPtrIP			IP
				>PULLW ZPPtrMAC			MAC
				
				ldy #3
.1				lda (ZPPtrIP),y
				sta ARP.TmpCache+S.ARPCACHE.IP,y
				dey
				bpl .1
				jsr ARP.QUERY.I
				bcs .9
				
				ldy #5
.2				lda ARP.TmpCache+S.ARPCACHE.MAC,y
				sta (ZPPtrMAC),y
				dey
				bpl .2
				clc
.9				rts				
*/--------------------------------------
* # ARP.Add
*  Add a static ARP cache record
* **In:**
*  PUSHW PTR to MAC
*  PUSHW PTR to IP
*\--------------------------------------
ARP.Add			>PULLW ZPPtrIP			IP
				>PULLW ZPPtrMAC			MAC
				
				stz ARP.TmpCache+S.ARPCACHE.TTL
				stz ARP.TmpCache+S.ARPCACHE.TTL+1

				ldy #3

.1				lda (ZPPtrIP),y
				sta ARP.TmpCache+S.ARPCACHE.IP,y
				dey
				bpl .1
				
				ldy #5

.2				lda (ZPPtrMAC),y
				sta ARP.TmpCache+S.ARPCACHE.MAC,y
				dey
				bpl .2

				lda #S.ARPCACHE.S.RESOLVED+S.ARPCACHE.S.STATIC
				
ARP.ADD.I		sta ARP.TmpCache

				jsr ARP.FIND.BY.IP
				bcc .1
				jsr ARP.FIND.FREE
				
.1				ldy #S.ARPCACHE-1

.2				lda ARP.TmpCache,y
				sta (ZPCachePtr),y
				dey
				bpl .2
				
				clc
				rts
*/--------------------------------------
* # ARP.GetCache
*  Return a Ptr to ARP Cache Table
* **In:**
* ## RETURN VALUE
*   Y,A = PTR to ARP.CACHE
*\--------------------------------------
ARP.GetCache	lda hARPCache
				>SYSCALL2 GetMemPtr
				bcs .9
				>STYA ZPCachePtr
				
.9				rts
*--------------------------------------
*				PRIVATE
*--------------------------------------
ARP.AddFromFrameInPtr
				ldy #S.IP.SRC+3
				ldx #3
				
.1				lda (ZPFrameInPtr),y
				sta ARP.TmpCache+S.ARPCACHE.IP,x
				dey
				dex
				bpl .1
				
				ldy #S.ETH.SRCMAC+5
				ldx #5
				
.2				lda (ZPFrameInPtr),y
				sta ARP.TmpCache+S.ARPCACHE.MAC,x
				dey
				dex
				bpl .2
				
				lda #K.ARP.TTL
				sta ARP.TmpCache+S.ARPCACHE.TTL
				lda /K.ARP.TTL
				sta ARP.TmpCache+S.ARPCACHE.TTL+1
				
				lda #S.ARPCACHE.S.RESOLVED
				jmp ARP.ADD.I
*--------------------------------------
ARP.IN			ldy #S.ARP.TPA+3
				ldx #3

.1				lda (ZPFrameInPtr),y
				cmp IPCFG+S.IPCFG.IP,x
				bne ARP.IN.EXIT
				dey
				dex
				bpl .1
				
				ldy #S.ARP.OPERATION+1	HI byte
				lda (ZPFrameInPtr),y
				cmp #S.ARP.OPERATION.REQ
				beq ARP.IN.REQ
				
				cmp #S.ARP.OPERATION.REP
				beq ARP.IN.REP
				
ARP.IN.EXIT		lda hFrameIn
				beq .8
				stz hFrameIn
				>SYSCALL2 FreeMem
.8				clc
				rts
				
ARP.IN.REQ		ldy #S.ARP.SPA+3
				ldx #3
				
.1				lda (ZPFrameInPtr),y
				sta ARP.REP.TPA,x
				dey
				dex
				bpl .1
				
				ldy #S.ARP.SHA+5
				ldx #5
				
.2				lda (ZPFrameInPtr),y
				sta ARP.REP.DSTMAC,x
				sta ARP.REP.THA,x
				dey
				dex
				bpl .2
				
				>LDYA L.ARP.REP
				jsr ARP.Send
				
				bra ARP.IN.EXIT

ARP.IN.REP		lda #K.ARP.TTL
				sta ARP.TmpCache+S.ARPCACHE.TTL
				lda /K.ARP.TTL
				sta ARP.TmpCache+S.ARPCACHE.TTL+1
				
				ldy #S.ARP.SPA+3
				ldx #3
				
.1				lda (ZPFrameInPtr),y
				sta ARP.TmpCache+S.ARPCACHE.IP,x
				dey
				dex
				bpl .1

				ldy #S.ARP.SHA+5
				ldx #5
				
.2				lda (ZPFrameInPtr),y
				sta ARP.TmpCache+S.ARPCACHE.MAC,x
				dey
				dex
				bpl .2
				
				lda #S.ARPCACHE.S.RESOLVED
				
				jsr ARP.ADD.I
				jmp ARP.IN.EXIT
*--------------------------------------
ARP.QUERY.I		jsr ARP.FIND.BY.IP
				bcs .3					send an ARP request

				lda (ZPCachePtr)		get status...
				bpl .9					Pending...
				
				ldy #S.ARPCACHE.MAC
				
.2				lda (ZPCachePtr),y
				sta ARP.TmpCache,y
				iny
				cpy #S.ARPCACHE.MAC+6
				bne .2
				
				ldy #S.ARPCACHE.TTL
				lda #K.ARP.TTL
				sta (ZPCachePtr),y
				iny
				lda /K.ARP.TTL
				sta (ZPCachePtr),y
				
				clc
				rts

.3				ldx #3

.4				lda ARP.TmpCache+S.ARPCACHE.IP,x
				sta ARP.REQ.TPA,x
				dex
				bpl .4
				
				>LDYA L.ARP.REQ
				jsr ARP.Send
				bcs .99
				
				lda #K.ARP.PENDING.TTL
				sta ARP.TmpCache+S.ARPCACHE.TTL
				stz ARP.TmpCache+S.ARPCACHE.TTL+1
				
				lda #S.ARPCACHE.S.PENDING
				jsr ARP.ADD.I
				
.9				lda #ERR.ARP.PENDING
				sec		
.99				rts		
*--------------------------------------
ARP.FIND.BY.IP	jsr ARP.GetCache

				ldx #K.ARPCACHE.SIZE
				
.1				lda (ZPCachePtr)
				beq .3

				ldy #S.ARPCACHE.IP
				
.2				lda ARP.TmpCache,y
				cmp (ZPCachePtr),y
				bne .3
				iny
				cpy #S.ARPCACHE.IP+4 
				bne .2
				
				clc
				rts
				
.3				lda ZPCachePtr
				clc
				adc #S.ARPCACHE
				sta ZPCachePtr
				bcc .8
				inc ZPCachePtr+1
				
.8				dex
				bne .1

				sec
				rts
*--------------------------------------
ARP.FIND.FREE	jsr ARP.GetCache

				lda #$ff
				sta TmpDWord
				sta TmpDWord+1

				ldx #K.ARPCACHE.SIZE
				
.1				lda (ZPCachePtr)
				beq .8
				bpl .6
				
				ldy #S.ARPCACHE.TTL
				lda (ZPCachePtr),y
				sec
				sbc TmpDWord
				iny
				lda (ZPCachePtr),y
				sbc TmpDWord+1
				bcc .6
				
				lda (ZPCachePtr),y
				sta TmpDWord+1
				dey
				lda (ZPCachePtr),y
				sta TmpDWord
				
				>LDYA ZPCachePtr
				>STYA ZPTmpPtr1			save lowest TTL slot ...

.6				lda ZPCachePtr
				clc
				adc #S.ARPCACHE
				sta ZPCachePtr
				bcc .7
				inc ZPCachePtr+1
				
.7				dex
				bne .1
				
				>LDYA ZPTmpPtr1
				>STYA ZPCachePtr
				lda #0
				sta (ZPCachePtr)
				
.8				clc
				rts
*--------------------------------------
ARP.EXPIRE		jsr ARP.GetCache
				
				ldx #K.ARPCACHE.SIZE
				
.1				lda (ZPCachePtr)
				beq .2
				and #S.ARPCACHE.S.STATIC
				bne .2
				
				ldy #S.ARPCACHE.TTL
				sec
				lda (ZPCachePtr),y
				sbc #1
				sta (ZPCachePtr),y
				iny
				lda (ZPCachePtr),y
				sbc #0
				sta (ZPCachePtr),y
				bcs .2
				
				lda #0
				sta (ZPCachePtr)
				
.2				lda ZPCachePtr
				clc
				adc #S.ARPCACHE
				sta ZPCachePtr
				bcc .3
				inc ZPCachePtr+1
				
.3				dex
				bne .1
				rts
*--------------------------------------
ARP.Send		>STYA IOCTL+S.IOCTL.BUFPTR
				>LDYAI S.ARP
				>STYA IOCTL+S.IOCTL.BYTECNT
				jmp FRM.Send.IOCTL
*--------------------------------------
MAN
SAVE USR/SRC/LIB/LIBTCPIP.S.ARP
LOAD USR/SRC/LIB/LIBTCPIP.S
ASM
