X-Git-Url: http://git.joshuawise.com/fpgaboy.git/blobdiff_plain/a6035e0c1b5785205c73dd6510e0b83631bda75b..refs/heads/master:/ethernet.asm diff --git a/ethernet.asm b/ethernet.asm index 85d66e1..8fb4fed 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,261 @@ 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 -ip_input: +.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 - SECTION "ethdata", BSS -bssstart DS 0 -packet DS 1552 -bssend DS 0 - +ip_input: + ; check for ipv4 + ld a, [hl] + ld c, a + and $F0 + swap a + sub $04 + jr z, .ip_isv4 + PUTSIL "ip_input: not ipv4 -- fuck off" + ret +.ip_isv4 + ; get length + ld a, c + and $0F + sla a + ld c, a + sla a + sub $14 + ld b, a + push bc -; SERIAL ROUTINES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - SECTION "serial", HOME + ; check checksum + xor a + ld d, a + ld e, a + push hl +.ip_cksumloop: + ld a, [hli] + ld b, a + ld a, [hli] + add e + ld e, a + ld a, b + add d + ld d, a + jr nc, .ip_noinc + inc de +.ip_noinc: + dec c + jr nz, .ip_cksumloop -putc: - push af -.waitport: - ld a,[$FF53] - and $01 - jr nz,.waitport - pop af - ld [$FF52],a + ; checksum ok + pop hl + ld a, d + or e + jr z, .ip_cksumgood + ld a, d + and e + cpl + or a + jr z, .ip_cksumgood + PUTSIL "ip_input: checksum fail -- bailing" + pop hl ret +.ip_cksumgood: + PUTSIL "ip_input: checksum good" + ld b, $00 + ld c, $0C + add hl, bc + ld c, $04 -puts: + ; print source IP + PUTSI "ip_input: this packet is from 0x" +.ip_get_srcip: ld a, [hli] - cp $00 - ret z - call putc - jr puts + PUTHEX a + dec c + jr nz, .ip_get_srcip + PUTSIL "." -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 + ; check dest IP + ld d, myIP >> 8 + ld e, myIP & $FF + ld c, $04 +.ip_chkip: + ld b, [hl] + inc hl + ld a, [de] + inc de + cp b + jr nz, .ip_ipfail + dec c + jr nz, .ip_chkip -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 + PUTSIL "ip_input: wheeeeeeeeeeeeeeee" + ; get protocol in A + ld d, $FF + ld e, -$0B + add hl, de + ld a, [hl] + ld d, $00 + ld e, $0B + add hl, de + + ; make hl point at beginning of data pop bc - pop af - push hl + ld c, b + ld b, $00 + add hl, bc + + ; ok, pass it off to something else + cp $01 + jr z, .ip_icmp + cp $11 + jr z, .ip_udp 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 +.ip_icmp: + call icmp_input + ret + +.ip_udp: + call udp_input + ret + +.ip_ipfail: + PUTSIL "ip_input: this packet is not to our IP address. Bailing." pop hl - pop bc ret -hex: db "0123456789ABCDEF" + +icmp_input: + PUTSIL "icmp_input: too lazy to parse -- fuck off" + ret + +udp_input: + PUTSIL "udp_input: too lazy to parse -- fuck off" + 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