blob: 872691b8f9aa9a1b45055a231f69b3641c765e46 [file] [log] [blame]
oliverschmidtd36173a2005-01-22 02:56:00 +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 *
oliverschmidt356f3662005-05-22 14:04:00 +000031 * $Id: cs8900a.c,v 1.8 2005/05/22 14:04:21 oliverschmidt Exp $
oliverschmidtd36173a2005-01-22 02:56:00 +000032 *
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
oliverschmidt2fa33232005-01-26 21:33:29 +000042extern u8_t lanslot;
oliverschmidtd36173a2005-01-22 02:56:00 +000043extern u8_t *cs8900a_rxtxreg,
oliverschmidt2fa33232005-01-26 21:33:29 +000044 *cs8900a_txcmd,
45 *cs8900a_txlen,
46 *cs8900a_packetpp,
47 *cs8900a_ppdata;
oliverschmidtd36173a2005-01-22 02:56:00 +000048
oliverschmidt2fa33232005-01-26 21:33:29 +000049static u8_t idx;
oliverschmidtd36173a2005-01-22 02:56:00 +000050static u16_t len;
oliverschmidt2fa33232005-01-26 21:33:29 +000051static u16_t cnt;
oliverschmidtd36173a2005-01-22 02:56:00 +000052
53
54/*-----------------------------------------------------------------------------------*/
55#pragma optimize(push, off)
56void
57cs8900a_init(void)
58{
oliverschmidt2fa33232005-01-26 21:33:29 +000059 asm("lda %v", lanslot);
oliverschmidt356f3662005-05-22 14:04:00 +000060 asm("beq %g", bailout);
oliverschmidt2fa33232005-01-26 21:33:29 +000061 asm("asl");
62 asm("asl");
63 asm("asl");
64 asm("asl");
65 asm("sta %v", idx);
66 asm("tax");
67
oliverschmidtd36173a2005-01-22 02:56:00 +000068 /* Turn on transmission and reception of frames. */
69 /* PACKETPP = 0x0112;
70 PPDATA = 0x00c0; */
71 asm("lda #$12");
oliverschmidt2fa33232005-01-26 21:33:29 +000072 asm("sta %v,x", cs8900a_packetpp);
oliverschmidtd36173a2005-01-22 02:56:00 +000073 asm("lda #$01");
oliverschmidt2fa33232005-01-26 21:33:29 +000074 asm("sta %v+1,x", cs8900a_packetpp);
oliverschmidtd36173a2005-01-22 02:56:00 +000075 asm("lda #$c0");
oliverschmidt2fa33232005-01-26 21:33:29 +000076 asm("sta %v,x", cs8900a_ppdata);
oliverschmidtd36173a2005-01-22 02:56:00 +000077 asm("lda #$00");
oliverschmidt2fa33232005-01-26 21:33:29 +000078 asm("sta %v+1,x", cs8900a_ppdata);
oliverschmidtd36173a2005-01-22 02:56:00 +000079
80 /* Accept valid unicast+broadcast frames. */
81 /* PACKETPP = 0x0104;
82 PPDATA = 0x0d05; */
83 asm("lda #$04");
oliverschmidt2fa33232005-01-26 21:33:29 +000084 asm("sta %v,x", cs8900a_packetpp);
oliverschmidtd36173a2005-01-22 02:56:00 +000085 asm("lda #$01");
oliverschmidt2fa33232005-01-26 21:33:29 +000086 asm("sta %v+1,x", cs8900a_packetpp);
oliverschmidtd36173a2005-01-22 02:56:00 +000087 asm("lda #$05");
oliverschmidt2fa33232005-01-26 21:33:29 +000088 asm("sta %v,x", cs8900a_ppdata);
oliverschmidtd36173a2005-01-22 02:56:00 +000089 asm("lda #$0d");
oliverschmidt2fa33232005-01-26 21:33:29 +000090 asm("sta %v+1,x", cs8900a_ppdata);
oliverschmidtd36173a2005-01-22 02:56:00 +000091
92 /* Set MAC address. */
93 /* PACKETPP = 0x0158;
94 PPDATA = (ETHADDR1 << 8) | (ETHADDR0); */
95 asm("lda #$58");
oliverschmidt2fa33232005-01-26 21:33:29 +000096 asm("sta %v,x", cs8900a_packetpp);
oliverschmidtd36173a2005-01-22 02:56:00 +000097 asm("lda #$01");
oliverschmidt2fa33232005-01-26 21:33:29 +000098 asm("sta %v+1,x", cs8900a_packetpp);
oliverschmidtd36173a2005-01-22 02:56:00 +000099 asm("lda %v", uip_ethaddr);
oliverschmidt2fa33232005-01-26 21:33:29 +0000100 asm("sta %v,x", cs8900a_ppdata);
oliverschmidtd36173a2005-01-22 02:56:00 +0000101 asm("lda %v+1", uip_ethaddr);
oliverschmidt2fa33232005-01-26 21:33:29 +0000102 asm("sta %v+1,x", cs8900a_ppdata);
oliverschmidtd36173a2005-01-22 02:56:00 +0000103
104 /* PACKETPP = 0x015a;
105 PPDATA = (ETHADDR3 << 8) | (ETHADDR2); */
106 asm("lda #$5a");
oliverschmidt2fa33232005-01-26 21:33:29 +0000107 asm("sta %v,x", cs8900a_packetpp);
oliverschmidtd36173a2005-01-22 02:56:00 +0000108 asm("lda #$01");
oliverschmidt2fa33232005-01-26 21:33:29 +0000109 asm("sta %v+1,x", cs8900a_packetpp);
oliverschmidtd36173a2005-01-22 02:56:00 +0000110 asm("lda %v+2", uip_ethaddr);
oliverschmidt2fa33232005-01-26 21:33:29 +0000111 asm("sta %v,x", cs8900a_ppdata);
oliverschmidtd36173a2005-01-22 02:56:00 +0000112 asm("lda %v+3", uip_ethaddr);
oliverschmidt2fa33232005-01-26 21:33:29 +0000113 asm("sta %v+1,x", cs8900a_ppdata);
oliverschmidtd36173a2005-01-22 02:56:00 +0000114
115 /* PACKETPP = 0x015c;
116 PPDATA = (ETHADDR5 << 8) | (ETHADDR4); */
117 asm("lda #$5c");
oliverschmidt2fa33232005-01-26 21:33:29 +0000118 asm("sta %v,x", cs8900a_packetpp);
oliverschmidtd36173a2005-01-22 02:56:00 +0000119 asm("lda #$01");
oliverschmidt2fa33232005-01-26 21:33:29 +0000120 asm("sta %v+1,x", cs8900a_packetpp);
oliverschmidtd36173a2005-01-22 02:56:00 +0000121 asm("lda %v+4", uip_ethaddr);
oliverschmidt2fa33232005-01-26 21:33:29 +0000122 asm("sta %v,x", cs8900a_ppdata);
oliverschmidtd36173a2005-01-22 02:56:00 +0000123 asm("lda %v+5", uip_ethaddr);
oliverschmidt2fa33232005-01-26 21:33:29 +0000124 asm("sta %v+1,x", cs8900a_ppdata);
oliverschmidt356f3662005-05-22 14:04:00 +0000125bailout:
oliverschmidtd36173a2005-01-22 02:56:00 +0000126}
127#pragma optimize(pop)
128/*-----------------------------------------------------------------------------------*/
129#pragma optimize(push, off)
130void
131cs8900a_send(void)
132{
oliverschmidt2fa33232005-01-26 21:33:29 +0000133 asm("ldx %v", idx);
oliverschmidt356f3662005-05-22 14:04:00 +0000134 asm("beq %g", bailout);
oliverschmidt2fa33232005-01-26 21:33:29 +0000135
oliverschmidtd36173a2005-01-22 02:56:00 +0000136 /* Transmit command. */
137 asm("lda #$c0");
oliverschmidt2fa33232005-01-26 21:33:29 +0000138 asm("sta %v,x", cs8900a_txcmd);
oliverschmidtd36173a2005-01-22 02:56:00 +0000139 asm("lda #$00");
oliverschmidt2fa33232005-01-26 21:33:29 +0000140 asm("sta %v+1,x", cs8900a_txcmd);
141 asm("lda %v", uip_len);
142 asm("sta %v,x", cs8900a_txlen);
143 asm("lda %v+1", uip_len);
144 asm("sta %v+1,x", cs8900a_txlen);
oliverschmidtd36173a2005-01-22 02:56:00 +0000145
oliverschmidt2fa33232005-01-26 21:33:29 +0000146 asm("ldy #8");
oliverschmidtac661242005-03-09 23:31:23 +0000147tryagain:
oliverschmidtd36173a2005-01-22 02:56:00 +0000148 /* Check for avaliable buffer space. */
149 asm("lda #$38");
oliverschmidt2fa33232005-01-26 21:33:29 +0000150 asm("sta %v,x", cs8900a_packetpp);
oliverschmidtd36173a2005-01-22 02:56:00 +0000151 asm("lda #$01");
oliverschmidt2fa33232005-01-26 21:33:29 +0000152 asm("sta %v+1,x", cs8900a_packetpp);
153 asm("lda %v+1,x", cs8900a_ppdata);
oliverschmidtd36173a2005-01-22 02:56:00 +0000154 asm("and #1");
oliverschmidtac661242005-03-09 23:31:23 +0000155 asm("bne %g", send);
oliverschmidtd36173a2005-01-22 02:56:00 +0000156
157 /* No space avaliable, skip a received frame and try again. */
158 asm("lda #$02");
oliverschmidt2fa33232005-01-26 21:33:29 +0000159 asm("sta %v,x", cs8900a_packetpp);
oliverschmidtd36173a2005-01-22 02:56:00 +0000160 asm("lda #$01");
oliverschmidt2fa33232005-01-26 21:33:29 +0000161 asm("sta %v+1,x", cs8900a_packetpp);
162 asm("lda %v,x", cs8900a_ppdata);
oliverschmidtd36173a2005-01-22 02:56:00 +0000163 asm("ora #$40");
oliverschmidt2fa33232005-01-26 21:33:29 +0000164 asm("sta %v,x", cs8900a_ppdata);
oliverschmidtd36173a2005-01-22 02:56:00 +0000165
oliverschmidt2fa33232005-01-26 21:33:29 +0000166 asm("dey");
oliverschmidtac661242005-03-09 23:31:23 +0000167 asm("bne %g", tryagain);
oliverschmidt356f3662005-05-22 14:04:00 +0000168bailout:
oliverschmidtd36173a2005-01-22 02:56:00 +0000169 return;
170
171 /* Send the frame. */
oliverschmidtac661242005-03-09 23:31:23 +0000172send:
oliverschmidtd36173a2005-01-22 02:56:00 +0000173
oliverschmidt3ff1aaa2005-02-23 22:41:30 +0000174 /* First, send 14+40=54 bytes of header. */
oliverschmidtd36173a2005-01-22 02:56:00 +0000175 asm("ldy #0");
oliverschmidtac661242005-03-09 23:31:23 +0000176sendloop1:
oliverschmidt2fa33232005-01-26 21:33:29 +0000177 asm("lda %v,y", uip_buf);
178 asm("sta %v,x", cs8900a_rxtxreg);
oliverschmidtd36173a2005-01-22 02:56:00 +0000179 asm("iny");
oliverschmidt2fa33232005-01-26 21:33:29 +0000180 asm("lda %v,y", uip_buf);
181 asm("sta %v+1,x", cs8900a_rxtxreg);
oliverschmidtd36173a2005-01-22 02:56:00 +0000182 asm("iny");
oliverschmidt3ff1aaa2005-02-23 22:41:30 +0000183 asm("cpy #%b", UIP_LLH_LEN + UIP_TCPIP_HLEN);
oliverschmidtac661242005-03-09 23:31:23 +0000184 asm("bne %g", sendloop1);
oliverschmidtd36173a2005-01-22 02:56:00 +0000185
oliverschmidt3ff1aaa2005-02-23 22:41:30 +0000186 if(uip_len <= UIP_LLH_LEN + UIP_TCPIP_HLEN) {
oliverschmidtd36173a2005-01-22 02:56:00 +0000187 return;
188 }
189
190 /* Next, send rest of the packet. */
oliverschmidte2c08622005-03-16 22:38:54 +0000191 cnt = uip_len - (UIP_LLH_LEN + UIP_TCPIP_HLEN);
oliverschmidtd36173a2005-01-22 02:56:00 +0000192
oliverschmidt2fa33232005-01-26 21:33:29 +0000193 asm("ldx %v", idx);
194
oliverschmidtb65645c2005-03-13 21:15:26 +0000195 asm("lda %v", cnt);
oliverschmidt2fa33232005-01-26 21:33:29 +0000196 asm("lsr");
oliverschmidtac661242005-03-09 23:31:23 +0000197 asm("bcc %g", noinc);
oliverschmidtb65645c2005-03-13 21:15:26 +0000198 asm("inc %v", cnt);
oliverschmidtac661242005-03-09 23:31:23 +0000199 asm("bne %g", noinc);
oliverschmidtb65645c2005-03-13 21:15:26 +0000200 asm("inc %v+1", cnt);
oliverschmidtac661242005-03-09 23:31:23 +0000201noinc:
oliverschmidtd36173a2005-01-22 02:56:00 +0000202
oliverschmidt2fa33232005-01-26 21:33:29 +0000203 asm("lda %v", uip_appdata);
oliverschmidtd36173a2005-01-22 02:56:00 +0000204 asm("sta ptr1");
oliverschmidt2fa33232005-01-26 21:33:29 +0000205 asm("lda %v+1", uip_appdata);
oliverschmidtd36173a2005-01-22 02:56:00 +0000206 asm("sta ptr1+1");
207
oliverschmidtd36173a2005-01-22 02:56:00 +0000208 asm("ldy #0");
oliverschmidtac661242005-03-09 23:31:23 +0000209sendloop2:
oliverschmidtd36173a2005-01-22 02:56:00 +0000210 asm("lda (ptr1),y");
oliverschmidt2fa33232005-01-26 21:33:29 +0000211 asm("sta %v,x", cs8900a_rxtxreg);
oliverschmidtd36173a2005-01-22 02:56:00 +0000212 asm("iny");
213 asm("lda (ptr1),y");
oliverschmidt2fa33232005-01-26 21:33:29 +0000214 asm("sta %v+1,x", cs8900a_rxtxreg);
oliverschmidtd36173a2005-01-22 02:56:00 +0000215 asm("iny");
oliverschmidtac661242005-03-09 23:31:23 +0000216 asm("bne %g", check);
oliverschmidtd36173a2005-01-22 02:56:00 +0000217 asm("inc ptr1+1");
oliverschmidtac661242005-03-09 23:31:23 +0000218check:
oliverschmidtb65645c2005-03-13 21:15:26 +0000219 asm("cpy %v", cnt);
oliverschmidtac661242005-03-09 23:31:23 +0000220 asm("bne %g", sendloop2);
oliverschmidtb65645c2005-03-13 21:15:26 +0000221 asm("dec %v+1", cnt);
oliverschmidtac661242005-03-09 23:31:23 +0000222 asm("bpl %g", sendloop2);
oliverschmidtd36173a2005-01-22 02:56:00 +0000223}
224#pragma optimize(pop)
225/*-----------------------------------------------------------------------------------*/
226#pragma optimize(push, off)
227static void
228skip_frame(void)
229{
oliverschmidt2fa33232005-01-26 21:33:29 +0000230 asm("ldx %v", idx);
231
oliverschmidtd36173a2005-01-22 02:56:00 +0000232 /* PACKETPP = 0x0102;
233 PPDATA = PPDATA | 0x0040; */
234 asm("lda #$02");
oliverschmidt2fa33232005-01-26 21:33:29 +0000235 asm("sta %v,x", cs8900a_packetpp);
oliverschmidtd36173a2005-01-22 02:56:00 +0000236 asm("lda #$01");
oliverschmidt2fa33232005-01-26 21:33:29 +0000237 asm("sta %v+1,x", cs8900a_packetpp);
238 asm("lda %v,x", cs8900a_ppdata);
oliverschmidtd36173a2005-01-22 02:56:00 +0000239 asm("ora #$40");
oliverschmidt2fa33232005-01-26 21:33:29 +0000240 asm("sta %v,x", cs8900a_ppdata);
oliverschmidtd36173a2005-01-22 02:56:00 +0000241}
242#pragma optimize(pop)
243/*-----------------------------------------------------------------------------------*/
244#pragma optimize(push, off)
oliverschmidt2fa33232005-01-26 21:33:29 +0000245u16_t
oliverschmidtd36173a2005-01-22 02:56:00 +0000246cs8900a_poll(void)
247{
oliverschmidt2fa33232005-01-26 21:33:29 +0000248 asm("ldx %v", idx);
oliverschmidtac661242005-03-09 23:31:23 +0000249 asm("beq %g", bailout);
oliverschmidt2fa33232005-01-26 21:33:29 +0000250
oliverschmidtd36173a2005-01-22 02:56:00 +0000251 /* Check receiver event register to see if there are any valid
252 unicast frames avaliable. */
253 /* PACKETPP = 0x0124;
254 if(PPDATA & 0x000d == 0x0000) {
255 return 0;
256 }
257 */
258 asm("lda #$24");
oliverschmidt2fa33232005-01-26 21:33:29 +0000259 asm("sta %v,x", cs8900a_packetpp);
oliverschmidtd36173a2005-01-22 02:56:00 +0000260 asm("lda #$01");
oliverschmidt2fa33232005-01-26 21:33:29 +0000261 asm("sta %v+1,x", cs8900a_packetpp);
262 asm("lda %v+1,x", cs8900a_ppdata);
oliverschmidtd36173a2005-01-22 02:56:00 +0000263 asm("and #$0d");
264 asm("cmp #$00");
oliverschmidtac661242005-03-09 23:31:23 +0000265 asm("bne %g", noreturn);
oliverschmidtd36173a2005-01-22 02:56:00 +0000266 /* No frame ready. */
oliverschmidtac661242005-03-09 23:31:23 +0000267bailout:
oliverschmidtd36173a2005-01-22 02:56:00 +0000268 return 0;
269
oliverschmidtac661242005-03-09 23:31:23 +0000270noreturn:
oliverschmidtd36173a2005-01-22 02:56:00 +0000271 /* Process the incoming frame. */
272
273 /* Read receiver event and discard it. */
oliverschmidt2fa33232005-01-26 21:33:29 +0000274 /* RXTXREG; */
275 asm("lda %v+1,x", cs8900a_rxtxreg);
276 asm("lda %v,x", cs8900a_rxtxreg);
oliverschmidtd36173a2005-01-22 02:56:00 +0000277
278 /* Read frame length. */
oliverschmidt2fa33232005-01-26 21:33:29 +0000279 /* cnt = len = RXTXREG; */
280 asm("lda %v+1,x", cs8900a_rxtxreg);
281 asm("sta %v+1", len);
282 asm("sta %v+1", cnt);
283 asm("lda %v,x", cs8900a_rxtxreg);
284 asm("sta %v", len);
285 asm("sta %v", cnt);
oliverschmidtd36173a2005-01-22 02:56:00 +0000286
oliverschmidt2fa33232005-01-26 21:33:29 +0000287 asm("lsr");
oliverschmidtac661242005-03-09 23:31:23 +0000288 asm("bcc %g", noinc);
oliverschmidt2fa33232005-01-26 21:33:29 +0000289 asm("inc %v", cnt);
oliverschmidtac661242005-03-09 23:31:23 +0000290 asm("bne %g", noinc);
oliverschmidt2fa33232005-01-26 21:33:29 +0000291 asm("inc %v+1", cnt);
oliverschmidtac661242005-03-09 23:31:23 +0000292noinc:
oliverschmidt2fa33232005-01-26 21:33:29 +0000293
294 if(cnt > UIP_BUFSIZE) {
oliverschmidtd36173a2005-01-22 02:56:00 +0000295 skip_frame();
296 return 0;
297 }
oliverschmidt2fa33232005-01-26 21:33:29 +0000298
oliverschmidtd36173a2005-01-22 02:56:00 +0000299 /* Read bytes into uip_buf. */
oliverschmidt2fa33232005-01-26 21:33:29 +0000300 asm("ldx %v", idx);
301
oliverschmidt2fa33232005-01-26 21:33:29 +0000302 asm("lda #<%v", uip_buf);
oliverschmidtd36173a2005-01-22 02:56:00 +0000303 asm("sta ptr1");
oliverschmidt2fa33232005-01-26 21:33:29 +0000304 asm("lda #>%v", uip_buf);
oliverschmidtd36173a2005-01-22 02:56:00 +0000305 asm("sta ptr1+1");
306
oliverschmidtd36173a2005-01-22 02:56:00 +0000307 asm("ldy #0");
oliverschmidtac661242005-03-09 23:31:23 +0000308readloop:
oliverschmidt2fa33232005-01-26 21:33:29 +0000309 asm("lda %v,x", cs8900a_rxtxreg);
oliverschmidtd36173a2005-01-22 02:56:00 +0000310 asm("sta (ptr1),y");
311 asm("iny");
oliverschmidt2fa33232005-01-26 21:33:29 +0000312 asm("lda %v+1,x", cs8900a_rxtxreg);
oliverschmidtd36173a2005-01-22 02:56:00 +0000313 asm("sta (ptr1),y");
314 asm("iny");
oliverschmidtac661242005-03-09 23:31:23 +0000315 asm("bne %g", check);
oliverschmidt2fa33232005-01-26 21:33:29 +0000316 asm("inc ptr1+1");
oliverschmidtac661242005-03-09 23:31:23 +0000317check:
oliverschmidt2fa33232005-01-26 21:33:29 +0000318 asm("cpy %v", cnt);
oliverschmidtac661242005-03-09 23:31:23 +0000319 asm("bne %g", readloop);
oliverschmidt2fa33232005-01-26 21:33:29 +0000320 asm("dec %v+1", cnt);
oliverschmidtac661242005-03-09 23:31:23 +0000321 asm("bpl %g", readloop);
oliverschmidtd36173a2005-01-22 02:56:00 +0000322 return len;
323}
324#pragma optimize(pop)