PR#3
PREFIX /A2OSX.SRC
NEW
INC 1
AUTO 6
				.LIST OFF
				.OP	65C02
				.OR	$2000
				.TF /A2OSX.BOOT/BIN/PING
*--------------------------------------
				.INB INC/MACROS.I
				.INB INC/A2OSX.I
				.INB INC/LIBTCPIP.I
*--------------------------------------
TIMEOUT.MAX		.EQ 20					2 sec.
*--------------------------------------
ZPFrameBase1	.EQ ZPBIN
ZPFrameLen1		.EQ ZPBIN+2
ZPFramePtr1		.EQ ZPBIN+4
ZPIPCfgPtr		.EQ ZPBIN+6
*--------------------------------------
*			File Header (16 Bytes)
*--------------------------------------
CS.START		cld
				jmp (.1,x)
				.DA #$61				6502,Level 1 (65c02)
				.DA #1					BIN Layout Version 1
				.DA 0
				.DA CS.END-CS.START		Code Length To Relocate
				.DA DS.END-DS.START		Data Segment to Allocate
				.DA 0
				.DA 0
*--------------------------------------
.1				.DA CS.INIT
				.DA CS.RUN
				.DA CS.DOEVENT		
				.DA	CS.QUIT
L.LIBTCPIP		.DA LIBTCPIP
L.MSG0			.DA MSG0
L.MSG1			.DA MSG1
L.MSG2			.DA MSG2
L.MSG3			.DA MSG3
				.DA 0
*--------------------------------------
CS.INIT			>SYSCALL SYS.GetArgC
				cmp #1
				bne .1
				
				lda #SYSMGR.ERRSYN
				sec
				rts
				
.1				>LDYA L.LIBTCPIP
				>SYSCALL SYS.LoadLibYA
				sta hLIBTCPIP

				>LIBCALL hLIBTCPIP,LIBTCPIP.GET.IPCFG	is TCPIP loaded ?
				bcs .9
				>STYA ZPIPCfgPtr
				
				lda (ZPIPCfgPtr)		Configured ?
				bpl .9
				
				ldy #S.IPCFG.HDEV
				lda (ZPIPCfgPtr),y
				sta hDev
				
				lda A2OSX.RANDOM16
				ldy #Identifier
				sta (pData),y
				lda A2OSX.RANDOM16+1
				iny
				sta (pData),y

				lda #0
				ldy #Sequence
				sta (pData),y
				iny
				sta (pData),y
				
				lda (pPs)
				ora #S.PS.F.EVENT		Now accept events
				sta (pPs)
				clc
				
.9				rts
*--------------------------------------
CS.RUN			jsr Init.Timeout

.1				>PUSHW pData			DST.IP
				lda #1
				>SYSCALL SYS.GetArgA
				>PUSHYA
				>LIBCALL hLIBTCPIP,LIBTCPIP.HST.GETBYNAME
				bcc .2		
				>SYSCALL SYS.Sleep
				jsr Wait.Timeout
				bcc .1
				
				lda #1
				>SYSCALL SYS.GetArgA
				>PUSHYA
				>LDYA L.MSG0
				>SYSCALL SYS.PrintFYA
				lda #1
				sec
				rts

.2				lda #1
				>SYSCALL SYS.GetArgA
				>PUSHYA
				
				ldy #3
				>PUSHB (pData),y			DST.IP+3	
				dey
				>PUSHB (pData),y			DST.IP+2
				dey
				>PUSHB (pData),y			DST.IP+1
				>PUSHB (pData)				DST.IP
				>LDYA L.MSG1
				>SYSCALL SYS.PrintFYA
		
CS.RUN.ECHO		>LIBCALL hLIBTCPIP,LIBTCPIP.NEW.ICMP.FRAME
				>STYA ZPFrameBase1
				txa
				ldy #hFrame
 				sta (pData),y

				lda #S.ICMP+32-2
				sta (ZPFrameBase1)
				lda /S.ICMP+32-2
				ldy #1
				sta (ZPFrameBase1),y
				
				ldx #3
				ldy #0
.10				lda (pData),y
				pha
				iny
				dex
				bpl .10
				
				ldx #3
				ldy #S.IP.DST+3
.1				pla
				sta (ZPFrameBase1),y
				dey
				dex
				bpl .1
				
				ldy #S.ICMP.TYPE
				lda #S.ICMP.TYPE.ECHOREQ
				sta (ZPFrameBase1),y
				
				ldy #Identifier
				lda (pData),y
				tax
				iny
				lda (pData),y
				
				ldy #S.ICMP.IDENTIFIER+1
				sta (ZPFrameBase1),y
				dey
				txa
				sta (ZPFrameBase1),y
				
				ldy #Sequence+1
				lda (pData),y
				tax		
				dey
				lda (pData),y 
				inc
				sta (pData),y
				bne .2
				pha
				inx
				txa
				sta (pData),y
				pla
				
.2				ldy #S.ICMP.SEQUENCE
				sta (ZPFrameBase1),y
				iny
				txa
				sta (ZPFrameBase1),y
				
				ldx #31
				ldy #S.ICMP+31
.21				txa
				and #$0f
				ora #$60
				sta (ZPFrameBase1),y
				dey
				dex
				bpl .21
				
				jsr Init.Timeout
				
.3				ldy #hFrame
				lda (pData),y
				>SYSCALL SYS.GetMemPtrA
				>PUSHYA
				>LIBCALL hLIBTCPIP,LIBTCPIP.SEND.ICMP.FRAME
				bcc .4
				>SYSCALL SYS.Sleep
				
				jsr Wait.Timeout
				bcc .3

.4				ldy #hFrame
				lda (pData),y
				>SYSCALL SYS.FreeMemA
				
				ldy #bReply
				lda #0
				sta (pData),y
				
				jsr Init.Timeout
				
CS.RUN.WAIT		>SYSCALL SYS.Sleep
				ldy #bReply
				lda (pData),y
				bne .1

				ldy #bCTRLC
				lda (pData),y
				bne CS.RUN.ERROR
				
				jsr Wait.Timeout
				bcc CS.RUN.WAIT
				
				ldy #3
				>PUSHB (pData),y			DST.IP+3	
				dey
				>PUSHB (pData),y			DST.IP+2
				dey
				>PUSHB (pData),y			DST.IP+1
				>PUSHB (pData)				DST.IP
				>LDYA L.MSG2
				>SYSCALL SYS.PrintFYA

.1				ldy #bCTRLC
				lda (pData),y
				bne CS.RUN.ERROR
				ldy #TimeOut
				lda (pData),y
				beq .2
				
				>SYSCALL SYS.Sleep
				bra .1
				
.2				jmp CS.RUN.ECHO
				
CS.RUN.ERROR	sec
				rts
*--------------------------------------
CS.DOEVENT		lda (pEvent)
				bpl .1					is it a TIMER event?
				
				ldy #TimeOut
				lda (pData),y
				beq .9
				
				dec
				sta (pData),y
				sec						do not discard TIMER event
				rts
				
.1				lda (pEvent)
				and #S.EVT.F.KEY		is it a KEY event?
				beq .2
				
				ldy #S.EVT.hDEV			is Event from active IN device?
				lda (pEvent),y
				ldy #S.PS.hINDEV
				cmp (pPs),y
				bne .9
				
				ldy #S.EVT.DATAHI		is it an O or SAPPLE key ?
				lda (pEvent),y
				bne	.9
				
				ldy #S.EVT.DATALO	
				lda (pEvent),y
				cmp #$03				Ctrl-C
				bne .8
				
				lda #$FF
				ldy #bCTRLC
				sta (pData),y
				bra .8
				
.2				lda (pEvent)
				and #S.EVT.F.NET
				beq .9
				
				ldy #S.EVT.hDEV
				lda (pEvent),y
				cmp hDev
				bne .9
				
				ldy #S.EVT.DATALO		Get Frame hMem
				lda (pEvent),y
				>SYSCALL SYS.GetMemPtrA
				>STYA ZPFrameBase1
				
				ldy #S.IP.PROTOCOL
				lda (ZPFrameBase1),y
				cmp #S.IP.PROTOCOL.ICMP
				
				bne .9
				
				ldy #S.ICMP.TYPE
				lda (ZPFrameBase1),y
				cmp #S.ICMP.TYPE.ECHOREP
				bne .9
				
				ldy #S.ICMP.IDENTIFIER
				lda (ZPFrameBase1),y
				tax
				iny
				lda (ZPFrameBase1),y
				ldy #Identifier+1 
				cmp (pData),y
				bne .9
				dey
				txa
				cmp (pData),y
				bne .9
				
				jsr CS.EVENT.REPLY
.8				clc
				rts	
				
.9				sec
				rts
*--------------------------------------
CS.EVENT.REPLY	lda #TIMEOUT.MAX
				sec
				ldy #TimeOut
				sbc (pData),y
				
				stz TimeOut.ms
				stz TimeOut.ms+1
				
				tay
				beq .3
				
.1				lda TimeOut.ms
				clc 
				adc #100
				sta TimeOut.ms
				bcc .2
				inc TimeOut
.2				dey
				bne .1
				
.3				>PUSHW TimeOut.ms
				ldy #S.IP.TTL
				>PUSHB (ZPFrameBase1),y
				
				ldy #S.ICMP.SEQUENCE+1
				>PUSHB (ZPFrameBase1),y
				dey 
				>PUSHB (ZPFrameBase1),y
				
				ldy #S.IP.SRC+3
				>PUSHB (ZPFrameBase1),y
				dey
				>PUSHB (ZPFrameBase1),y
				dey
				>PUSHB (ZPFrameBase1),y
				dey
				>PUSHB (ZPFrameBase1),y
				
				>LDYA L.MSG3
				>SYSCALL SYS.PrintFYA
				
				ldy #bReply
				lda (pData),y
				inc
				sta (pData),y
				rts
*--------------------------------------
CS.QUIT			lda hLIBTCPIP
				>SYSCALL SYS.UnloadLibA
				clc
				rts
*--------------------------------------
Init.Timeout	ldy #TimeOut
				lda #TIMEOUT.MAX
				sta (pData),y
				rts
*--------------------------------------
Wait.TimeOut	sec
				ldy #TimeOut
				lda (pData),y
				beq .9
				ldy #bCTRLC
				lda (pData),y
				bmi .9
				clc
.9				rts
*--------------------------------------
CS.END
LIBTCPIP		>PSTRING "libtcpip.o"
MSG0			>CSTRING "%S: Unknown host\n"
MSG1			>CSTRING "PING %d.%d.%d.%d (%S)\n"
MSG2			>CSTRING "%d.%d.%d.%d: TimeOut/Host unreachable\n"
MSG3			>CSTRING "32 bytes from %d.%d.%d.%d, icmp_seq=%D, ttl=%d, time=%D ms\n"
hLIBTCPIP		.BS 1
hDev			.BS 1
TimeOut.ms		.BS 2
*--------------------------------------
				.DUMMY
				.OR 0
DS.START
DST.IP			.BS 4
hFrame			.BS 1
TimeOut			.BS 1
Identifier		.BS 2
Sequence		.BS 2
bCTRLC			.BS 1
bReply			.BS 1
DS.END
				.ED
*--------------------------------------
MAN
SAVE BIN/PING.S
ASM
