IP
[fpgaboy.git] / ethernet.asm
1         INCLUDE "serial.inc"
2
3 ETH_STATUS EQU $FF68
4 ETH_DATA EQU $FF69
5 ARP_ENTRIES EQU 6
6 ARP_ENTRY_SIZE EQU 13
7
8         SECTION "config", HOME[$0]
9 myMAC:  db $12, $34, $56, $78, $9A, $00
10 myIP:   db $0A, $00, $00, $02
11 myMask: db $FF, $00, $00, $00
12 myGW:   db $0A, $00, $00, $01
13
14         SECTION "boot", HOME[$100]
15         jr start
16         nop
17         nop
18         
19         db $CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83       ;<<< no $00,$c3,$50,$01
20         db $00,$0C,$00,$0D,$00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6
21         db $DD,$DD,$D9,$99,$BB,$BB,$67,$63,$6E,$0E,$EC,$CC,$DD,$DC,$99,$9F
22         db $BB,$B9,$33,$3E     ; Standard Nintendo DO NOT CHANGE...
23
24         db "GB Ethernet     "  ; Cart name   16bytes
25         db $00,$00,$00         ; Not used
26         db $00                 ; Cart type   ROM Only
27         db $00                 ; ROM Size    32k
28         db $00                 ; RAM Size     0k
29         db $cf,$08             ; Maker ID Matthew Johnson
30         db $01                 ; Version     =1
31         db $87                 ; Complement check (Important)
32         db $ff,$ff             ; Cheksum, fix this if you are going to
33
34 start:
35         ld sp, $D800
36         call zerobss
37         PUTSIL "Ethernet test ROM"
38 .lp:    xor a                   ; Reset state machines
39         ld [ETH_STATUS], a
40         ld a, [ETH_STATUS]      ; Load current status
41         ld [$FF51], a
42         and $02         ; New packet?
43         call nz, getpacket
44         jr .lp
45
46 zerobss:
47         ld hl, bssstart
48         ld bc, bssend - bssstart
49 .lp:    ld a, b
50         or c
51         ret z
52         dec bc
53         xor a
54         ld [hli], a
55         ld a, h
56         jr .lp
57
58 getpacket:
59         ld a, [ETH_DATA]
60         ld b, a
61         ld a, [ETH_DATA]
62         ld c, a
63         push bc
64         ld hl, packet
65 .cplp:  ld a, b
66         or c
67         jr z, .done
68         dec bc
69         ld a, [ETH_DATA]
70         ld [hli], a
71         jr .cplp
72 .done:  pop bc
73         PUTSI "getpacket: Got "
74         PUTHEX b
75         PUTHEX c
76         PUTSIL " byte packet from hardware."
77         ld hl, packet
78         call ether_input
79         ret
80
81 ether_input:
82         push hl
83         PUTSI "ether_input: Packet to "
84         PUTHEX [hli]
85         PUTC $3A
86         PUTHEX [hli]
87         PUTC $3A
88         PUTHEX [hli]
89         PUTC $3A
90         PUTHEX [hli]
91         PUTC $3A
92         PUTHEX [hli]
93         PUTC $3A
94         PUTHEX [hli]
95         PUTSI " from "
96         PUTHEX [hli]
97         PUTC $3A
98         PUTHEX [hli]
99         PUTC $3A
100         PUTHEX [hli]
101         PUTC $3A
102         PUTHEX [hli]
103         PUTC $3A
104         PUTHEX [hli]
105         PUTC $3A
106         PUTHEX [hli]
107         PUTSI " protocol "
108         PUTHEX [hli]
109         PUTHEX [hli]
110         PUTSIL "."
111         pop hl
112         
113         ; Verify the destination MAC.
114         push hl
115         ld de, myMAC
116         ld c, $06
117 .maclp: ld a, [de]
118         cp [hl]
119         jr nz, .notus
120         inc de
121         inc hl
122         dec c
123         jr nz, .maclp
124         ; Done? Then it was to us!
125         jr .us
126 .notus: ; Was it to broadcast?
127         pop hl
128         push hl
129         ld c, $06
130 .bclp:  ld a, [hli]
131         cp $FF
132         jr nz, .notbc
133         dec c
134         jr nz, .bclp
135
136 .us:    PUTSIL "ether_input: It's to us!"
137         ; Which protocol does it belong to?
138         pop hl
139         ld b, $00
140         ld c, 12
141         add hl, bc      ; Skip source and dest MAC.
142         ld a, [hli]
143         cp $08
144         jr nz, .unknownproto
145         ld a, [hli]
146         cp $06
147         jr z, .arp
148         cp $00
149         jp z, .ip
150         jr .unknownproto
151
152 .notbc: pop hl
153         PUTSIL "ether_input: Not addressed to us and not broadcast."
154         ret
155         
156 .unknownproto:
157         PUTSIL "ether_input: Unknown protocol; dropping"
158         ret
159
160 .arp:
161         PUTSIL "ether_input: ARP packet"
162         call arp_input
163         ret
164 .ip:
165         PUTSIL "ether_input: IP packet"
166         call ip_input
167         ret
168
169 arp_input:
170         ; First, verify that this is an ARP packet that we can handle.
171         ld c, 7
172         ld de, .expectedarp
173 .cklp:  xor a
174         cp c
175         jr z, .ckdone
176         ld a, [de]
177         cp [hl]
178         jr nz, .badarp
179         inc de
180         inc hl
181         dec c
182         jr .cklp
183 .ckdone:
184         ld a, [hli]
185         cp 1
186         jr z, .req
187         cp 2
188         jp z, .resp
189 .badarp:
190         PUTSIL "arp_input: Unknown protocol hardware or request"
191         ret
192 .expectedarp:
193         db $00, $01, $08, $00, $06, $04, $00
194
195 .req:
196         PUTSIL "arp_input.req: Request"
197         ; Is it asking about us?
198         push hl
199         ld b, 0
200         ld c, $10       ; SHA + SPA + THA
201         add hl, bc
202         ld de, myIP
203         ld c, 4
204 .iplp:  ld a, [de]
205         cp [hl]
206         jp nz, .notourip
207         inc de
208         inc hl
209         dec c
210         jr nz, .iplp
211         PUTSIL "arp_input.req: Aimed at us."
212         pop hl  ; Now synthesize a response packet.
213         push hl
214         dec hl
215         ld a, $02       ; Reply!
216         ld [hli], a
217         ld d, h
218         ld e, l
219         ld hl, 10       ; SHA + SPA
220         add hl, de      ; Now DE points at SHA, and HL points at THA
221         ld c, 10
222 .dcl:   ld a, [de]
223         ld [hli], a
224         inc de
225         dec c
226         jr nz, .dcl
227         pop hl          ; HL now points at SHA
228         ld de, myMAC
229         ld c, $06
230 .mcl:   ld a, [de]
231         ld [hli], a
232         inc de
233         dec c
234         jr nz, .mcl
235         ld de, myIP     ; HL now points at SPA
236         ld c, $04
237 .icl:   ld a, [de]
238         ld [hli], a
239         inc de
240         dec c
241         jr nz, .icl
242         ld d, h
243         ld e, l         ; HL now points at THA
244         ld hl, -32
245         add hl, de      ; HL has now been backed up to the start of the ethernet header.
246         ld d, h
247         ld e, l         ; DE now points at the dest
248         ld hl, 6
249         add hl, de      ; HL now points at the source
250         ld c, $06
251 .sdcl:  ld a, [hli]
252         ld [de], a
253         inc de
254         dec c
255         jr nz, .sdcl
256         ld hl, myMAC    ; DE now points at the source
257         ld c, $06
258 .smcl:  ld a, [hli]
259         ld [de], a
260         inc de
261         dec c
262         jr nz, .smcl
263         ld hl, -12
264         add hl, de      ; HL now points at the start of the packet -- should be C000!
265         ld b, 0
266         ld c, 64        ; Minimum size packet; avoid transmitting a runt
267         call packet_send
268         PUTSIL "arp_input.req: sent response!"
269         ret
270 .notourip:
271         PUTSIL "arp_input.req: Not aimed at us; ignoring."
272         pop hl
273         ret
274         
275 .resp:
276         PUTSIL "arp_input.resp: Response"
277         ret
278
279 ip_input:
280         ; check for ipv4
281         ld a, [hl]
282         ld c, a
283         and $F0
284         swap a
285         sub $04
286         jr z, .ip_isv4
287         PUTSIL "ip_input: not ipv4 -- fuck off"
288         ret
289 .ip_isv4
290         ; get length
291         ld a, c
292         and $0F
293         sla a
294         ld c, a
295         sla a
296         sub $14
297         ld b, a
298         push bc
299
300         ; check checksum
301         xor a
302         ld d, a
303         ld e, a
304         push hl
305 .ip_cksumloop:
306         ld a, [hli]
307         ld b, a
308         ld a, [hli]
309         add e
310         ld e, a
311         ld a, b
312         add d
313         ld d, a
314         jr nc, .ip_noinc
315         inc de
316 .ip_noinc:
317         dec c
318         jr nz, .ip_cksumloop
319
320         ; checksum ok
321         pop hl
322         ld a, d
323         or e
324         jr z, .ip_cksumgood
325         ld a, d
326         and e
327         cpl
328         or a
329         jr z, .ip_cksumgood
330         PUTSIL "ip_input: checksum fail -- bailing"
331         pop hl
332         ret
333 .ip_cksumgood:
334         PUTSIL "ip_input: checksum good"
335         ld b, $00
336         ld c, $0C
337         add hl, bc
338         ld c, $04
339
340         ; print source IP
341         PUTSI "ip_input: this packet is from 0x"
342 .ip_get_srcip:
343         ld a, [hli]
344         PUTHEX a
345         dec c
346         jr nz, .ip_get_srcip
347         PUTSIL "."
348
349         ; check dest IP
350         ld d, myIP >> 8
351         ld e, myIP & $FF
352         ld c, $04
353 .ip_chkip:
354         ld b, [hl]
355         inc hl
356         ld a, [de]
357         inc de
358         cp b
359         jr nz, .ip_ipfail
360         dec c
361         jr nz, .ip_chkip
362
363         PUTSIL "ip_input: wheeeeeeeeeeeeeeee"
364         ; get protocol in A
365         ld d, $FF
366         ld e, -$0B
367         add hl, de
368         ld a, [hl]
369         ld d, $00
370         ld e, $0B
371         add hl, de
372
373         ; make hl point at beginning of data
374         pop bc
375         ld c, b
376         ld b, $00
377         add hl, bc
378
379         ; ok, pass it off to something else
380         cp $01
381         jr z, .ip_icmp
382         cp $11
383         jr z, .ip_udp
384         ret
385
386 .ip_icmp:
387         call icmp_input
388         ret
389
390 .ip_udp:
391         call udp_input
392         ret
393
394 .ip_ipfail:
395         PUTSIL "ip_input: this packet is not to our IP address. Bailing."
396         pop hl
397         ret
398
399 icmp_input:
400         PUTSIL "icmp_input: too lazy to parse -- fuck off"
401         ret
402
403 udp_input:
404         PUTSIL "udp_input: too lazy to parse -- fuck off"
405         ret
406
407 packet_send:
408         ld a, [ETH_STATUS]      ; Wait for the port to become available.
409         and $01
410         jr nz, packet_send
411         ld a, b
412         ld [ETH_DATA], a
413         ld a, c
414         ld [ETH_DATA], a
415 .pkts:  ld a, b
416         or c
417         ret z
418         dec bc
419         ld a, [hli]
420         ld [ETH_DATA], a
421         jr .pkts
422
423         SECTION "ethdata", BSS
424 bssstart        DS 0
425 packet          DS 1552
426 arptable        DS ARP_ENTRIES * ARP_ENTRY_SIZE
427 bssend          DS 0
This page took 0.036534 seconds and 4 git commands to generate.