-
Notifications
You must be signed in to change notification settings - Fork 22
/
etherload.a65
180 lines (151 loc) · 3.57 KB
/
etherload.a65
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
; Simple ethernet programme loader for C65GS.
; Reads and checks packets, and then runs code contained in the packets.
; This keeps the programme VERY small.
; Now supports ARP replies to make life easier.
; make it start with SYS53000
.word $CF08
.org $CF08
.scope
programentrypoint:
; C65GS io
lda #$47
sta $d02f
lda #$53
sta $D02f
; Map ethernet registers at $6000 - $7FFF
; Ethernet controller really lives $FFDE000 - $FFDEFFF, so select $FF megabyte section for MAP LO
lda #$ff
ldx #$0f
ldy #$00
ldz #$00
map
eom
; now enable mapping of $DE000-$DFFFF at $6000
; MAPs are offset based, so we need to subtract $6000 from the target address
; $DE000 - $6000 = $D8000
lda #$80
ldx #$8d
ldy #$00
ldz #$00
map
eom
; Ethernet registers should now be visible from $6000 - $6FFF
; read buffer will be at $6800 - $6FFF
; length of frame is in $6FFE / $6FFF in little-endian byte order
; so LDA $6FFE ; LDX $6FFF ; jsr $BDCD should print packet length to screen
; make sure ethernet transceiver is on and not generating IRQs
; (we will poll it).
; also make sure that we acknowledge the last received packet so that the
; ethernet controller knows it can receive.
lda $d6e1
lsr
and #$02
ora #$01
sta $d6e1
loop:
waitingforpacket:
lda $d6e1
and #$20
beq waitingforpacket
; clear eth RX signal, and leave ethernet tranceiver on
; and make last used RX buffer visible
lda $d6e1
and #$04
lsr
ora #$01
sta $d6e1
; Got a packet.
; check whether it is UDP port 4510
; or whether it is an ARP request
; Here we want to check that $680E - $6817 =
; 08 06 00 01 08 00 06 04 00 01
ldx #$09
arploop0:
lda $680e,x
cmp arptemplate,x
bne notarp
dex
bpl arploop0
; check that IP address asked for ends in .65
lda $682b
cmp #65
bne notarp
; ok, so we have an ARP request.
; now we need to build the ARP reply and send it.
; We should copy the sender's
; XXX for now just increment border colour
; set output packet size
; 6+6+2 bytes ethernet header + 28 bytes of ARP reply = 42
lda #<42
sta $d6e2
lda #>42
sta $d6e3
; copy fixed ARP fields (we will overwrite some later)
; (note that TX buffer lacks 2 byte RX buffer header)
ldx #$14
arploop1:
lda $6802,x
sta $6800,x
dex
bpl arploop1
; Copy ethernet source to ethernet destination in TX buffer
; Set our mac address in ethernet source address field in TX buffer
ldx #$05
arploop2:
lda $6808,x ; requestors mac from RX ethernet header
sta $6800,x ; requestors mac into TX ethernet header
lda #$40
sta $6806,x ; our mac in ethernet header
sta $6816,x ; our mac in ARP payload
dex
bpl arploop2
; set packet as ARP reply
lda #$02 ; $02 = reply, $01 = request
sta $6815
ldx #$03
; copy requested IP address into reply IP address field
arploop3:
lda $6828,x
sta $681c,x
dex
bpl arploop3
; copy requestors MAC+IP into target MAC+IP fields
ldx #9
arploop4:
lda $6818,x
sta $6820,x
dex
bpl arploop4
; packet should now all be ready - hit TX button
lda #$01
sta $d6e4
notarp:
; is it IPv4?
lda $6810
cmp #$45
bne waitingforpacket
; is it UDP?
lda $6819
cmp #$11
bne waitingforpacket
; UDP port #4510
lda $6826
cmp #>4510
bne waitingforpacket
lda $6827
cmp #<4510
bne waitingforpacket
; packet body begins at $0444 / $682C.
; if it begins with $A9 = LDA immediate, then jsr to the packet body.
; packet body can do whatever is required to load data, keeping this
; programme very simple.
lda $682c
cmp #$a9
bne loop
jsr $682C
jmp loop
arptemplate:
.byte $08,$06,$00,$01,$08,$00,$06,$04,$00,$01
.checkpc $CFFF
.scend
.outfile "etherload.prg"