		.ORG 0

PBASE		.EQU 80h

P0_CMD		.EQU PBASE
P0_PSTART	.EQU PBASE+1
P0_PSTOP	.EQU PBASE+2
P0_BOUND	.EQU PBASE+3
P0_TPSR		.EQU PBASE+4
P0_TBCR0	.EQU PBASE+5
P0_TBCR1	.EQU PBASE+6
P0_ISR		.EQU PBASE+7
P0_RSAR0	.EQU PBASE+8
P0_RSAR1	.EQU PBASE+9
P0_RBCR0	.EQU PBASE+10
P0_RBCR1	.EQU PBASE+11
P0_RCR		.EQU PBASE+12
P0_TCR		.EQU PBASE+13
P0_DCR		.EQU PBASE+14
P0_IMR		.EQU PBASE+15

P0_CLDA0	.EQU PBASE+1
P0_CLDA1	.EQU PBASE+2
P0_TSR		.EQU PBASE+4
P0_CRDA0	.EQU PBASE+8
P0_CRDA1	.EQU PBASE+9
P0_RSR		.EQU PBASE+12

P1_PAR		.EQU PBASE+1
P1_CURR		.EQU PBASE+7
P1_MAR		.EQU PBASE+8

ASIC		.EQU PBASE+16

RX_START	.EQU 6
MEM_SIZE	.EQU 40h

	CALL CLS
	CALL INIT
	MVI A,22h
	OUT P0_CMD
L1:	CALL POLL
	JZ L1
	MVI B,10
	LXI D,1000h
	CALL DUMP
	LHLD PKTYPE
	XCHG
	LXI H,PK_PTAB
	CALL SWITCH
	JMP L1

CHKSUM:	XRA A	; HL - addr, C - len
	MOV B,A
	MOV D,A
	MOV E,A
	MOV A,C
	RRC
	MOV C,A
	JNC CHKS1
	PUSH H
	DAD B
	DAD B
	MOV E,M
	POP H
CHKS1:	INX H
	MOV A,M
	ADD E
	MOV E,A
	DCX H
	MOV A,M
	ADC D
	MOV D,A
	INX H
	INX H
	JNC $+4
	INR B
	DCR C
	JNZ CHKS1
	MOV L,B
	MVI H,0
	DAD D
NEG:	MOV A,L
	CMA
	MOV L,A
	MOV A,H
	CMA
	MOV H,A
	ORA L
	RET

IP_IS_BC:LXI D,MY_MASK	; HL - addr of IP
	LXI B,4FFh
IP_ISBC:LDAX D
	ORA M
	ANA C
	MOV C,A
	INX D
	INX H
	DCR B
	JNZ IP_ISBC
	INR A
	RET

IP_PROC:LXI H,IP_VIHL
	MOV A,M
	CPI 45h
	RNZ
	LDA IP_TTL
	ORA A
	RZ
	MVI C,20
	CALL CHKSUM
	RNZ
	LXI D,MY_IP
	LXI H,IP_DEST_IP
	CALL IPCMP
	JZ IP_PRC1
	LXI H,IP_DEST_IP
	CALL IP_IS_BC
	RNZ
IP_PRC1:LDA IP_PROTO
	MOV E,A
	MVI D,0
	LXI H,IP_PTAB
SWITCH:	MOV A,M	; HL - table, DE - key
	CMP E
	INX H
	MOV C,A
	MOV A,M
	INX H
	JNZ SWITC1
	CMP D
	JNZ SWITC1
	MOV A,M
	INX H
	MOV H,M
	MOV L,A
	PCHL
SWITC1:	ORA C
	RZ
	INX H
	INX H
	JMP SWITCH

ICMP_PROC:LDA ICMP_TYPE
	CPI 8
	RNZ
	LXI H,IP_DEST_IP
	LXI D,IP_SRC_IP
	CALL COPYIP
	LXI H,IP_SRC_IP
	LXI D,MY_IP
	CALL COPYIP
	LXI H,0
	SHLD IP_CHKSUM
        LXI H,IP_VIHL
	MVI C,20
	CALL CHKSUM
	MOV A,H
	MOV H,L
	MOV L,A
	SHLD IP_CHKSUM
	XRA A
	STA ICMP_TYPE
	MOV L,A
	MOV H,A
	SHLD ICMP_CHKSUM
	LHLD IP_LEN
	MOV A,H
	MOV H,L
	MOV L,A
	PUSH H
	LXI D,-20
	DAD D
	MOV C,L
	LXI H,ICMP_TYPE
	CALL CHKSUM
	MOV A,H
	MOV H,L
	MOV L,A
	SHLD ICMP_CHKSUM
	LXI H,PKHDST ; better from ARP table!
	LXI D,PKHSRC
	CALL COPYMAC
	LXI D,MACADR
	CALL COPYMAC
	POP H
	LXI D,14
	DAD D
	MOV B,H
	MOV C,L
	JMP TRANSB

TCP_PROC:
	RET

UDP_PROC:
	RET

ARP_PROC:LHLD ARP_OPCODE
	XCHG
	LXI H,ARP_PTAB
	JMP SWITCH

ARP_REQ:LXI D,MY_IP
	LXI H,ARP_T_IP
	CALL IPCMP
	RNZ
	LXI H,PKHDST
	LXI D,PKHSRC
	CALL COPYMAC
	LXI D,MACADR
	CALL COPYMAC
	MVI A,2
	STA ARP_OPCODE+1
	LXI H,ARP_T_MAC
	LXI D,ARP_S_MAC
	MVI B,10
	CALL COPY
	LXI H,ARP_S_MAC
	LXI D,MACADR
	MVI B,10
	CALL COPY
	LXI B,2Ah
	JMP TRANSB

ARP_REPL:
	RET

INIT:	MVI A,61h
	OUT P0_CMD
	LXI D,MACADR
	MVI C,6
	LXI H,INI1+1
	MVI M,P1_PAR
INI1:	IN 0
	STAX D
	INX D
	INR M
	DCR C
	JNZ INI1
	MVI A,RX_START
	OUT P1_CURR
	MVI A,21h
	OUT P0_CMD
	MVI A,RX_START
	OUT P0_PSTART
	MVI A,MEM_SIZE
	OUT P0_PSTOP
	OUT P0_BOUND
	XRA A
	OUT P0_TPSR
	OUT P0_TCR
	OUT P0_IMR
	MVI A,4
	OUT P0_RCR
	MVI A,48h
	OUT P0_DCR
	MVI A,0FFh
	OUT P0_ISR
	RET

SETDMA:	MVI A,22h	; DE - addr, BC - len
	OUT P0_CMD
	MOV A,E
	OUT P0_RSAR0
	MOV A,D
	OUT P0_RSAR1
	MOV A,C
	OUT P0_RBCR0
	MOV A,B
	OUT P0_RBCR1
	RET

READ:	CALL SETDMA	; HL - buffer, DE - addr, BC - len
	MVI A,0Ah
	OUT P0_CMD
READ1:	IN ASIC
	MOV M,A
	INX H
	DCX B
	MOV A,B
	ORA C
	JNZ READ1
	RET

WRITE:	CALL SETDMA	; HL - buffer, DE - addr, BC - len
	MVI A,12h
	OUT P0_CMD
WRITE1:	MOV A,M
	OUT ASIC
	INX H
	DCX B
	MOV A,B
	ORA C
	JNZ WRITE1
	RET

POLL:	IN P0_RSR
	ANI 1
	RZ
	MVI A,62h
	OUT P0_CMD
	IN P1_CURR
	CPI MEM_SIZE
	JC POLL1
	MVI A,RX_START
POLL1:	MOV C,A
	MVI A,22h
	OUT P0_CMD
	IN P0_BOUND
	CPI MEM_SIZE
	JC POLL2
	MVI A,RX_START
POLL2:	MOV D,A
	SUB C
	RZ
	MVI E,0
	LXI B,4
	LXI H,PKHDR
	CALL READ
	LHLD PKLEN
	DAD D
	LXI B,-(MEM_SIZE*256)-1
	DAD B
	JNC POLL3
	INX H
	PUSH H
	XRA A
	SUB E
	MOV C,A
	MVI A,MEM_SIZE
	SBB D
	MOV B,A
	LXI H,PKHDR
	CALL READ
	POP B
	LXI D,RX_START*256
	JMP POLL4
POLL3:	LHLD PKLEN
	MOV C,L
	MOV B,H
	LXI H,PKHDR
POLL4:	CALL READ
	LDA PKNXT
	CPI RX_START
	JNZ $+5
	MVI A,MEM_SIZE
	OUT P0_BOUND
	ORA A
	RET

TRANSB:	LXI H,PKBUF
TRANS:	IN P0_CMD	; HL - packet, BC - len
	ANI 4
	JNZ TRANS
	MOV E,A
	MOV D,A
	PUSH B
	CALL WRITE
	POP B
	XRA A
	OUT P0_TPSR
	MOV A,C
	OUT P0_TBCR0
	MOV A,B
	OUT P0_TBCR1
	MVI A,6
	OUT P0_CMD
	RET

IPCMP:	MVI B,4
MEMCMP:	LDAX D	; DE,HL - addr, B - len
	SUB M
	RNZ
	INX D
	INX H
	DCR B
	JNZ MEMCMP
	XRA A
	RET

COPYIP:	MVI B,4
	JMP COPY
COPYMAC:MVI B,6
COPY:	LDAX D	; DE - src, HL - dest, B - len
	MOV M,A
	INX D
	INX H
	DCR B
	JNZ COPY
	RET

CLS:	LXI H,76D0h
CLS1:	MVI M,0
	INR L
	JNZ CLS1
	INR H
	MOV A,H
	CPI 80H
	JNZ CLS1
	RET

PRHEX:	PUSH PSW	; A - value, HL - cur addr
	RRC
	RRC
	RRC
	RRC
	CALL $+4
	POP PSW
	ANI 0Fh
	ADI 30h
	CPI 3Ah
	JC $+5
	ADI 7
	MOV M,A
	INX H
	RET

DUMP:	LXI H,776Fh	; DE - addr, B - lines count
DUMP1:	PUSH B
	PUSH H
	MOV A,D
	CALL PRHEX
	MOV A,E
	CALL PRHEX
	MVI M,':'
	INX H
	INX H
	PUSH D
DUMP2:	LDAX D
	INX D
	CALL PRHEX
	INX H
	MOV A,E
	ANI 0Fh
	JNZ DUMP2
	POP D
	POP H
	PUSH H
	LXI B,55
	DAD B
DUMP3:	LDAX D
	INX D
	CPI 20h
	JC $+8
	CPI 80h
	JC $+5
	MVI A,'.'
	MOV M,A
	INX H
	MOV A,E
	ANI 0Fh
	JNZ DUMP3
	POP H
	LXI B,78
	DAD B
	POP B
	DCR B
	JNZ DUMP1
	RET	

PK_PTAB:.DW PKT_IP,IP_PROC
	.DW PKT_ARP,ARP_PROC
	.DW 0

IP_PTAB:.DW 1,ICMP_PROC
	.DW 6,TCP_PROC
	.DW 17,UDP_PROC
	.DW 0

ARP_PTAB:.DW 100h,ARP_REQ
	.DW 200h,ARP_REPL
	.DW 0

BC_IP:	.DB 255,255,255,255

MACADR:	.DW 0,0,0
MY_IP:	.DB 192,168,22,2
MY_MASK:.DB 255,255,0,0

PKHDR:		.EQU 1000h
PKNXT:		.EQU PKHDR+1
PKLEN:		.EQU PKHDR+2
PKBUF:		.EQU PKHDR+4

PKHDST		.EQU PKBUF
PKHSRC		.EQU PKBUF+6
PKTYPE		.EQU PKBUF+12
PKDATA		.EQU PKBUF+14

PKT_IP		.EQU 0008h
PKT_ARP		.EQU 0608h

ARP_HWTP	.EQU PKDATA
ARP_PRTP	.EQU PKDATA+2
ARP_HWSZ	.EQU PKDATA+4
ARP_PRSZ	.EQU PKDATA+5
ARP_OPCODE	.EQU PKDATA+6
ARP_S_MAC	.EQU PKDATA+8
ARP_S_IP	.EQU PKDATA+14
ARP_T_MAC	.EQU PKDATA+18
ARP_T_IP	.EQU PKDATA+24

IP_VIHL		.EQU PKDATA
IP_TOS		.EQU PKDATA+1
IP_LEN		.EQU PKDATA+2
IP_IDENT	.EQU PKDATA+4
IP_FLAGS	.EQU PKDATA+6
IP_TTL		.EQU PKDATA+8
IP_PROTO	.EQU PKDATA+9
IP_CHKSUM	.EQU PKDATA+10
IP_SRC_IP	.EQU PKDATA+12
IP_DEST_IP	.EQU PKDATA+16
IP_DATA		.EQU PKDATA+20

ICMP_TYPE	.EQU IP_DATA
ICMP_CODE	.EQU IP_DATA+1
ICMP_CHKSUM	.EQU IP_DATA+2
ICMP_IDENT	.EQU IP_DATA+4
ICMP_SEQNUM	.EQU IP_DATA+6
ICMP_DATA	.EQU IP_DATA+8

	.END
