+ INCLUDE "serial.inc"
+
ETH_STATUS EQU $FF68
ETH_DATA EQU $FF69
+ARP_ENTRIES EQU 6
+ARP_ENTRY_SIZE EQU 13
-PUTC: MACRO
- ld a, \1
- call putc
- ENDM
-
-PUTS: MACRO
- ld hl, \1
- call puts
- ENDM
-
-PUTSI: MACRO
- push hl
- call putsi
- db \1, 0
- pop hl
- ENDM
-
-PUTSIL: MACRO
- push hl
- call putsi
- db \1, 13, 10, 0
- pop hl
- ENDM
-
-PUTHEX: MACRO
- ld a, \1
- call puthex
- ENDM
-
SECTION "config", HOME[$0]
myMAC: db $12, $34, $56, $78, $9A, $00
myIP: db $0A, $00, $00, $02
PUTHEX b
PUTHEX c
PUTSIL " byte packet from hardware."
- ld hl, $D000
+ ld hl, packet
call ether_input
ret
ret
arp_input:
+ ; First, verify that this is an ARP packet that we can handle.
+ ld c, 7
+ ld de, .expectedarp
+.cklp: xor a
+ cp c
+ jr z, .ckdone
+ ld a, [de]
+ cp [hl]
+ jr nz, .badarp
+ inc de
+ inc hl
+ dec c
+ jr .cklp
+.ckdone:
+ ld a, [hli]
+ cp 1
+ jr z, .req
+ cp 2
+ jp z, .resp
+.badarp:
+ PUTSIL "arp_input: Unknown protocol hardware or request"
+ ret
+.expectedarp:
+ db $00, $01, $08, $00, $06, $04, $00
+
+.req:
+ PUTSIL "arp_input.req: Request"
+ ; Is it asking about us?
+ push hl
+ ld b, 0
+ ld c, $10 ; SHA + SPA + THA
+ add hl, bc
+ ld de, myIP
+ ld c, 4
+.iplp: ld a, [de]
+ cp [hl]
+ jp nz, .notourip
+ inc de
+ inc hl
+ dec c
+ jr nz, .iplp
+ PUTSIL "arp_input.req: Aimed at us."
+ pop hl ; Now synthesize a response packet.
+ push hl
+ dec hl
+ ld a, $02 ; Reply!
+ ld [hli], a
+ ld d, h
+ ld e, l
+ ld hl, 10 ; SHA + SPA
+ add hl, de ; Now DE points at SHA, and HL points at THA
+ ld c, 10
+.dcl: ld a, [de]
+ ld [hli], a
+ inc de
+ dec c
+ jr nz, .dcl
+ pop hl ; HL now points at SHA
+ ld de, myMAC
+ ld c, $06
+.mcl: ld a, [de]
+ ld [hli], a
+ inc de
+ dec c
+ jr nz, .mcl
+ ld de, myIP ; HL now points at SPA
+ ld c, $04
+.icl: ld a, [de]
+ ld [hli], a
+ inc de
+ dec c
+ jr nz, .icl
+ ld d, h
+ ld e, l ; HL now points at THA
+ ld hl, -32
+ add hl, de ; HL has now been backed up to the start of the ethernet header.
+ ld d, h
+ ld e, l ; DE now points at the dest
+ ld hl, 6
+ add hl, de ; HL now points at the source
+ ld c, $06
+.sdcl: ld a, [hli]
+ ld [de], a
+ inc de
+ dec c
+ jr nz, .sdcl
+ ld hl, myMAC ; DE now points at the source
+ ld c, $06
+.smcl: ld a, [hli]
+ ld [de], a
+ inc de
+ dec c
+ jr nz, .smcl
+ ld hl, -12
+ add hl, de ; HL now points at the start of the packet -- should be C000!
+ ld b, 0
+ ld c, 64 ; Minimum size packet; avoid transmitting a runt
+ call packet_send
+ PUTSIL "arp_input.req: sent response!"
+ ret
+.notourip:
+ PUTSIL "arp_input.req: Not aimed at us; ignoring."
+ pop hl
+ ret
+
+.resp:
+ PUTSIL "arp_input.resp: Response"
ret
ip_input:
ret
+packet_send:
+ ld a, [ETH_STATUS] ; Wait for the port to become available.
+ and $01
+ jr nz, packet_send
+ ld a, b
+ ld [ETH_DATA], a
+ ld a, c
+ ld [ETH_DATA], a
+.pkts: ld a, b
+ or c
+ ret z
+ dec bc
+ ld a, [hli]
+ ld [ETH_DATA], a
+ jr .pkts
+
SECTION "ethdata", BSS
bssstart DS 0
packet DS 1552
+arptable DS ARP_ENTRIES * ARP_ENTRY_SIZE
bssend DS 0
-
-
-; SERIAL ROUTINES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- SECTION "serial", HOME
-
-putc:
- push af
-.waitport:
- ld a,[$FF53]
- and $01
- jr nz,.waitport
- pop af
- ld [$FF52],a
- ret
-
-puts:
- ld a, [hli]
- cp $00
- ret z
- call putc
- jr puts
-
-EX_SP_HL: MACRO
- push de
- di
- add sp, 2
- pop de
- push hl
- ld l, e
- ld h, d
- add sp, -2
- ei
- pop de
- ENDM
-
-putsi:
- pop hl
- push af
- push bc
- push de
-.lp: ld a, [hli]
- or a
- jr z, .done
- call putc
- jr .lp
-.done: pop de
- pop bc
- pop af
- push hl
- ret
-
-puthex: ; Put two hex nibbles to the serial console.
- push bc
- push hl
- push af
- swap a
- and $0F
- ld hl,hex
- ld b,0
- ld c,a
- add hl,bc
- ld a, [hl]
- call putc
- pop af
- and $0F
- ld hl,hex
- ld c,a
- add hl,bc
- ld a, [hl]
- call putc
- pop hl
- pop bc
- ret
-hex: db "0123456789ABCDEF"