blob: 44915ebb3a79d0f1a6eb7ea834866e6ef45fe816 [file] [log] [blame]
kthacker6de67752006-04-17 15:02:26 +00001/*
2 * Copyright (c) 2001, Adam Dunkels.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote
14 * products derived from this software without specific prior
15 * written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
18 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * This file is part of the C64 RealAudio server demo project.
30 *
31 * $Id: cs8900a.c,v 1.1 2006/04/17 15:02:39 kthacker Exp $
32 *
33 */
34
35/* cs8900a.c: device driver for the CS8900a chip in 8-bit mode. Mostly
36 written in 6502 assembler for speed. */
37
38#include "cs8900a.h"
39#include "uip.h"
40#include "uip_arp.h"
41
42/*#define UIP_ETHADDR0 0x00
43#define UIP_ETHADDR1 0x00
44#define UIP_ETHADDR2 0x00
45#define UIP_ETHADDR3 0x64
46#define UIP_ETHADDR4 0x64
47#define UIP_ETHADDR5 0x64*/
48
49extern u8_t *cs8900a_rxtxreg,
50 *cs8900a_txcmd,
51 *cs8900a_txlen,
52 *cs8900a_packetpp,
53 *cs8900a_ppdata;
54
55static u16_t len;
56static u8_t r;
57
58
59/*-----------------------------------------------------------------------------------*/
60#pragma optimize(push, off)
61void
62cs8900a_init(void)
63{
64 /* Turn on transmission and reception of frames. */
65 /* PACKETPP = 0x0112;
66 PPDATA = 0x00c0; */
67 asm("lda #$12");
68 asm("sta %v", cs8900a_packetpp);
69 asm("lda #$01");
70 asm("sta %v+1", cs8900a_packetpp);
71 asm("lda #$c0");
72 asm("sta %v", cs8900a_ppdata);
73 asm("lda #$00");
74 asm("sta %v+1", cs8900a_ppdata);
75
76 /* Accept valid unicast+broadcast frames. */
77 /* PACKETPP = 0x0104;
78 PPDATA = 0x0d05; */
79 asm("lda #$04");
80 asm("sta %v", cs8900a_packetpp);
81 asm("lda #$01");
82 asm("sta %v+1", cs8900a_packetpp);
83 asm("lda #$05");
84 asm("sta %v", cs8900a_ppdata);
85 asm("lda #$0d");
86 asm("sta %v+1", cs8900a_ppdata);
87
88 /* Set MAC address. */
89 /* PACKETPP = 0x0158;
90 PPDATA = (ETHADDR1 << 8) | (ETHADDR0); */
91 asm("lda #$58");
92 asm("sta %v", cs8900a_packetpp);
93 asm("lda #$01");
94 asm("sta %v+1", cs8900a_packetpp);
95 asm("lda %v", uip_ethaddr);
96 asm("sta %v", cs8900a_ppdata);
97 asm("lda %v+1", uip_ethaddr);
98 asm("sta %v+1", cs8900a_ppdata);
99
100 /* PACKETPP = 0x015a;
101 PPDATA = (ETHADDR3 << 8) | (ETHADDR2); */
102 asm("lda #$5a");
103 asm("sta %v", cs8900a_packetpp);
104 asm("lda #$01");
105 asm("sta %v+1", cs8900a_packetpp);
106 asm("lda %v+2", uip_ethaddr);
107 asm("sta %v", cs8900a_ppdata);
108 asm("lda %v+3", uip_ethaddr);
109 asm("sta %v+1", cs8900a_ppdata);
110
111 /* PACKETPP = 0x015c;
112 PPDATA = (ETHADDR5 << 8) | (ETHADDR4); */
113 asm("lda #$5c");
114 asm("sta %v", cs8900a_packetpp);
115 asm("lda #$01");
116 asm("sta %v+1", cs8900a_packetpp);
117 asm("lda %v+4", uip_ethaddr);
118 asm("sta %v", cs8900a_ppdata);
119 asm("lda %v+5", uip_ethaddr);
120 asm("sta %v+1", cs8900a_ppdata);
121
122}
123#pragma optimize(pop)
124/*-----------------------------------------------------------------------------------*/
125#pragma optimize(push, off)
126void
127cs8900a_send(void)
128{
129 if(uip_len > UIP_BUFSIZE) {
130 asm("inc $d020");
131 return;
132 }
133
134 /* Transmit command. */
135 asm("lda #$c0");
136 asm("sta %v", cs8900a_txcmd);
137 asm("lda #$00");
138 asm("sta %v+1", cs8900a_txcmd);
139 asm("lda _uip_len");
140 asm("sta %v", cs8900a_txlen);
141#if UIP_BUFSIZE > 255
142 asm("lda _uip_len+1");
143#else
144 asm("lda #0");
145#endif
146 asm("sta %v+1", cs8900a_txlen);
147
148 asm("ldx #8");
149 asm("tryagain:");
150 /* Check for avaliable buffer space. */
151 asm("lda #$38");
152 asm("sta %v", cs8900a_packetpp);
153 asm("lda #$01");
154 asm("sta %v+1", cs8900a_packetpp);
155 asm("lda %v+1", cs8900a_ppdata);
156 asm("and #1");
157 asm("bne send");
158
159 /* No space avaliable, skip a received frame and try again. */
160 asm("lda #$02");
161 asm("sta %v", cs8900a_packetpp);
162 asm("lda #$01");
163 asm("sta %v+1", cs8900a_packetpp);
164 asm("lda %v", cs8900a_ppdata);
165 asm("ora #$40");
166 asm("sta %v", cs8900a_ppdata);
167
168 asm("dex");
169 asm("bne tryagain");
170
171 asm("bailout:");
172 return;
173
174 /* Send the frame. */
175 asm("send:");
176
177
178 /* First, send 40+14=54 bytes of header. */
179
180 asm("ldx #54");
181 asm("ldy #0");
182 asm("sendloop1:");
183 asm("lda _uip_buf,y");
184 asm("sta %v", cs8900a_rxtxreg);
185 asm("lda _uip_buf+1,y");
186 asm("sta %v+1", cs8900a_rxtxreg);
187 asm("iny");
188 asm("iny");
189 asm("dex");
190 asm("dex");
191 asm("bne sendloop1");
192
193 if(uip_len <= 54) {
194 return;
195 }
196
197 /* Next, send rest of the packet. */
198
199 uip_len -= 54;
200
201
202 asm("lda ptr1");
203 asm("pha");
204 asm("lda ptr1+1");
205 asm("pha");
206
207 asm("lda _uip_appdata");
208 asm("sta ptr1");
209 asm("lda _uip_appdata+1");
210 asm("sta ptr1+1");
211
212 asm("sendloop2:");
213 asm("lda _uip_len");
214 asm("tax");
215 asm("and #1");
216 asm("beq noinc");
217 asm("inx");
218 asm("noinc:");
219#if UIP_BUFSIZE > 255
220 asm("lda _uip_len+1");
221#else
222 asm("lda #0");
223#endif
224 asm("beq nozero");
225 asm("ldx #0");
226 asm("nozero:");
227 asm("ldy #0");
228 asm("sendloop:");
229 asm("lda (ptr1),y");
230 asm("sta %v", cs8900a_rxtxreg);
231 asm("iny");
232 asm("lda (ptr1),y");
233 asm("sta %v+1", cs8900a_rxtxreg);
234 asm("iny");
235 asm("dex");
236 asm("dex");
237 asm("bne sendloop");
238 asm("inc ptr1+1");
239#if UIP_BUFSIZE > 255
240 asm("dec _uip_len+1");
241 asm("bpl sendloop2");
242#endif
243
244 asm("pla");
245 asm("sta ptr1+1");
246 asm("pla");
247 asm("sta ptr1");
248}
249#pragma optimize(pop)
250/*-----------------------------------------------------------------------------------*/
251#pragma optimize(push, off)
252static void
253skip_frame(void)
254{
255 /* PACKETPP = 0x0102;
256 PPDATA = PPDATA | 0x0040; */
257 asm("lda #$02");
258 asm("sta %v", cs8900a_packetpp);
259 asm("lda #$01");
260 asm("sta %v+1", cs8900a_packetpp);
261 asm("lda %v", cs8900a_ppdata);
262 asm("ora #$40");
263 asm("sta %v", cs8900a_ppdata);
264}
265#pragma optimize(pop)
266/*-----------------------------------------------------------------------------------*/
267#pragma optimize(push, off)
268u8_t
269cs8900a_poll(void)
270{
271 /* Check receiver event register to see if there are any valid
272 unicast frames avaliable. */
273 /* PACKETPP = 0x0124;
274 if(PPDATA & 0x000d == 0x0000) {
275 return 0;
276 }
277 */
278 asm("lda #$24");
279 asm("sta %v", cs8900a_packetpp);
280 asm("lda #$01");
281 asm("sta %v+1", cs8900a_packetpp);
282 asm("lda %v+1", cs8900a_ppdata);
283 asm("and #$0d");
284 asm("cmp #$00");
285 asm("bne noreturn");
286 /* No frame ready. */
287 return 0;
288
289 asm("noreturn:");
290 /* Process the incoming frame. */
291
292 /* Read receiver event and discard it. */
293 /* dummy = RXTXREG; */
294
295 asm("lda %v+1", cs8900a_rxtxreg);
296 asm("sta _len+1");
297 asm("lda %v", cs8900a_rxtxreg);
298 asm("sta _len");
299
300 /* Read frame length. */
301 /* len = uip_len = RXTXREG; */
302 asm("lda %v+1", cs8900a_rxtxreg);
303 asm("sta _len+1");
304 asm("sta _uip_len+1");
305 asm("lda %v", cs8900a_rxtxreg);
306 asm("sta _len");
307 asm("sta _uip_len");
308
309
310 if(len > UIP_BUFSIZE) {
311 skip_frame();
312 return 0;
313 }
314
315 /* Read bytes into uip_buf. */
316 asm("lda ptr1");
317 asm("pha");
318 asm("lda ptr1+1");
319 asm("pha");
320
321 asm("lda #<_uip_buf");
322 asm("sta ptr1");
323 asm("lda #>_uip_buf");
324 asm("sta ptr1+1");
325
326 asm("lda _len+1");
327 asm("beq read256");
328
329 /* Read first 256*n bytes. */
330 asm("ldy #0");
331 asm("read256loop:");
332 asm("lda %v", cs8900a_rxtxreg);
333 asm("sta (ptr1),y");
334 asm("iny");
335 asm("lda %v+1", cs8900a_rxtxreg);
336 asm("sta (ptr1),y");
337 asm("iny");
338 asm("bne read256loop");
339 asm("inc ptr1+1");
340
341 asm("dec _len+1");
342 asm("bne read256loop");
343
344 /* Read last 255 or less bytes. */
345 asm("read256:");
346 asm("lda _len");
347 asm("lsr");
348 asm("bcc noinc");
349 asm("inc _len");
350 asm("noinc:");
351 asm("ldy #$0");
352 asm("readloop:");
353 asm("lda %v", cs8900a_rxtxreg);
354 asm("sta (ptr1),y");
355 asm("iny");
356 asm("lda %v+1", cs8900a_rxtxreg);
357 asm("sta (ptr1),y");
358 asm("iny");
359 asm("cpy _len");
360 asm("bne readloop");
361
362 asm("pla");
363 asm("sta ptr1+1");
364 asm("pla");
365 asm("sta ptr1");
366 return len;
367}
368#pragma optimize(pop)