From: Joshua Wise Date: Tue, 27 May 2008 04:35:04 +0000 (-0400) Subject: ARP responder X-Git-Url: http://git.joshuawise.com/fpgaboy.git/commitdiff_plain/3a0bde75799d99fe866e3afe14a0302ffe4e66a5?ds=sidebyside ARP responder --- diff --git a/ethernet.asm b/ethernet.asm index 85d66e1..5e49ef6 100644 --- a/ethernet.asm +++ b/ethernet.asm @@ -1,35 +1,10 @@ + 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 @@ -99,7 +74,7 @@ getpacket: PUTHEX b PUTHEX c PUTSIL " byte packet from hardware." - ld hl, $D000 + ld hl, packet call ether_input ret @@ -192,86 +167,136 @@ ether_input: 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" diff --git a/serial.inc b/serial.inc new file mode 100644 index 0000000..c3ca090 --- /dev/null +++ b/serial.inc @@ -0,0 +1,100 @@ +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 "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"