]>
Commit | Line | Data |
---|---|---|
3a0bde75 JW |
1 | INCLUDE "serial.inc" |
2 | ||
43282fcf JW |
3 | ETH_STATUS EQU $FF68 |
4 | ETH_DATA EQU $FF69 | |
3a0bde75 JW |
5 | ARP_ENTRIES EQU 6 |
6 | ARP_ENTRY_SIZE EQU 13 | |
43282fcf | 7 | |
43282fcf JW |
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 | |
a6035e0c | 36 | call zerobss |
43282fcf | 37 | PUTSIL "Ethernet test ROM" |
a6035e0c | 38 | .lp: xor a ; Reset state machines |
43282fcf | 39 | ld [ETH_STATUS], a |
a6035e0c | 40 | ld a, [ETH_STATUS] ; Load current status |
43282fcf JW |
41 | ld [$FF51], a |
42 | and $02 ; New packet? | |
43 | call nz, getpacket | |
44 | jr .lp | |
45 | ||
a6035e0c JW |
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 | ||
43282fcf JW |
58 | getpacket: |
59 | ld a, [ETH_DATA] | |
60 | ld b, a | |
61 | ld a, [ETH_DATA] | |
62 | ld c, a | |
63 | push bc | |
a6035e0c | 64 | ld hl, packet |
43282fcf JW |
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." | |
3a0bde75 | 77 | ld hl, packet |
43282fcf JW |
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 | |
a6035e0c JW |
124 | ; Done? Then it was to us! |
125 | jr .us | |
126 | .notus: ; Was it to broadcast? | |
43282fcf | 127 | pop hl |
a6035e0c JW |
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 | |
43282fcf | 155 | |
a6035e0c JW |
156 | .unknownproto: |
157 | PUTSIL "ether_input: Unknown protocol; dropping" | |
43282fcf | 158 | ret |
a6035e0c JW |
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 | |
43282fcf JW |
167 | ret |
168 | ||
a6035e0c | 169 | arp_input: |
3a0bde75 JW |
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" | |
a6035e0c JW |
277 | ret |
278 | ||
279 | ip_input: | |
f8fc1367 JW |
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" | |
a6035e0c JW |
405 | ret |
406 | ||
3a0bde75 JW |
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 | ||
a6035e0c JW |
423 | SECTION "ethdata", BSS |
424 | bssstart DS 0 | |
425 | packet DS 1552 | |
3a0bde75 | 426 | arptable DS ARP_ENTRIES * ARP_ENTRY_SIZE |
a6035e0c | 427 | bssend DS 0 |