]> Joshua Wise's Git repositories - fpgaboy.git/blame_incremental - ethernet.asm
IP
[fpgaboy.git] / ethernet.asm
... / ...
CommitLineData
1 INCLUDE "serial.inc"
2
3ETH_STATUS EQU $FF68
4ETH_DATA EQU $FF69
5ARP_ENTRIES EQU 6
6ARP_ENTRY_SIZE EQU 13
7
8 SECTION "config", HOME[$0]
9myMAC: db $12, $34, $56, $78, $9A, $00
10myIP: db $0A, $00, $00, $02
11myMask: db $FF, $00, $00, $00
12myGW: 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
34start:
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
46zerobss:
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
58getpacket:
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
81ether_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
169arp_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
279ip_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
399icmp_input:
400 PUTSIL "icmp_input: too lazy to parse -- fuck off"
401 ret
402
403udp_input:
404 PUTSIL "udp_input: too lazy to parse -- fuck off"
405 ret
406
407packet_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
424bssstart DS 0
425packet DS 1552
426arptable DS ARP_ENTRIES * ARP_ENTRY_SIZE
427bssend DS 0
This page took 0.030648 seconds and 4 git commands to generate.