blob: 28d1c10cc72333fd704d18ef85b304ca630e0008 [file] [log] [blame]
oliverschmidt8871bdd2005-03-13 21:33:57 +00001/*
2 * uIP lan91c96 (smc9194) driver
3 * Based on cs8900a driver, copyrighted (c) 2001, by Adam Dunkels
4 * Copyright (c) 2003, Josef Soucek
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote
16 * products derived from this software without specific prior
17 * written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
20 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
25 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
oliverschmidt356f3662005-05-22 14:04:00 +000031 * $Id: lan91c96.c,v 1.6 2005/05/22 14:04:21 oliverschmidt Exp $
oliverschmidt8871bdd2005-03-13 21:33:57 +000032 *
33 */
34
oliverschmidt8871bdd2005-03-13 21:33:57 +000035#include "lan91c96.h"
36#include "uip.h"
37#include "uip_arp.h"
38
39#include <stdio.h>
40
41#define ETHBASE 0xc080
42
43#define ETHBSR ETHBASE+0x0e /* Bank select register R/W (2B) */
44
45/* Register bank 0 */
46
47#define ETHTCR ETHBASE /* Transmition control register R/W (2B) */
48#define ETHEPHSR ETHBASE+2 /* EPH status register R/O (2B) */
49#define ETHRCR ETHBASE+4 /* Receive control register R/W (2B) */
50#define ETHECR ETHBASE+6 /* Counter register R/O (2B) */
51#define ETHMIR ETHBASE+8 /* Memory information register R/O (2B) */
52#define ETHMCR ETHBASE+0x0a /* Memory Config. reg. +0 R/W +1 R/O (2B) */
53
54/* Register bank 1 */
55
56#define ETHCR ETHBASE /* Configuration register R/W (2B) */
57#define ETHBAR ETHBASE+2 /* Base address register R/W (2B) */
58#define ETHIAR ETHBASE+4 /* Individual address register R/W (6B) */
59#define ETHGPR ETHBASE+0x0a /* General address register R/W (2B) */
60#define ETHCTR ETHBASE+0x0c /* Control register R/W (2B) */
61
62/* Register bank 2 */
63
64#define ETHMMUCR ETHBASE /* MMU command register W/O (1B) */
65#define ETHAUTOTX ETHBASE+1 /* AUTO TX start register R/W (1B) */
66#define ETHPNR ETHBASE+2 /* Packet number register R/W (1B) */
67#define ETHARR ETHBASE+3 /* Allocation result register R/O (1B) */
68#define ETHFIFO ETHBASE+4 /* FIFO ports register R/O (2B) */
69#define ETHPTR ETHBASE+6 /* Pointer register R/W (2B) */
70#define ETHDATA ETHBASE+8 /* Data register R/W (4B) */
71#define ETHIST ETHBASE+0x0c /* Interrupt status register R/O (1B) */
72#define ETHACK ETHBASE+0x0c /* Interrupt acknowledge register W/O (1B) */
73#define ETHMSK ETHBASE+0x0d /* Interrupt mask register R/W (1B) */
74
75/* Register bank 3 */
76
77#define ETHMT ETHBASE /* Multicast table R/W (8B) */
78#define ETHMGMT ETHBASE+8 /* Management interface R/W (2B) */
79#define ETHREV ETHBASE+0x0a /* Revision register R/W (2B) */
80#define ETHERCV ETHBASE+0x0c /* Early RCV register R/W (2B) */
81
82#define BANK(num) asm("lda #%b", num); asm("sta %w,x", ETHBSR);
83
84extern u8_t lanslot;
85
86static u8_t slot_index;
87static u8_t packet_status;
88static u16_t packet_length;
89
90
91/*-----------------------------------------------------------------------------------*/
92#pragma optimize(push, off)
93void lan91c96_init(void)
94{
95 asm("lda %v", lanslot);
oliverschmidt356f3662005-05-22 14:04:00 +000096 asm("beq %g", L1);
oliverschmidt8871bdd2005-03-13 21:33:57 +000097 asm("asl");
98 asm("asl");
99 asm("asl");
100 asm("asl");
oliverschmidt8871bdd2005-03-13 21:33:57 +0000101 asm("tax");
102
oliverschmidt84d84632005-03-31 22:03:41 +0000103 /* Check if high byte is 0x33 */
104 asm("lda %w,x", ETHBSR+1);
105 asm("cmp #$33");
106 asm("bne %g", L1);
107 asm("stx %v", slot_index);
108
oliverschmidt8871bdd2005-03-13 21:33:57 +0000109 /* Reset ETH card */
110 BANK(0);
111 asm("lda #%%10000000"); /* Software reset */
112 asm("sta %w,x", ETHRCR+1);
113
114 asm("lda #0");
115 asm("sta %w,x", ETHRCR);
116 asm("sta %w,x", ETHRCR+1);
117
118 /* Enable transmit and receive */
119 asm("lda #%%10000001"); /* Enable transmit TXENA, PAD_EN */
120 asm("sta %w,x", ETHTCR);
121 asm("lda #%%00000011"); /* Enable receive, strip CRC ??? */
122 asm("sta %w,x", ETHRCR+1);
123
124 BANK(1);
125 asm("lda %w,x", ETHCR+1);
126 asm("ora #%%00010000"); /* No wait (IOCHRDY) */
127 asm("sta %w,x", ETHCR+1);
128
129 asm("lda #%%00001001"); /* Auto release */
130 asm("sta %w,x", ETHCTR+1);
131
132 /* Set MAC address */
oliverschmidt14821d42005-03-14 23:00:34 +0000133 asm("lda %v", uip_ethaddr);
oliverschmidt8871bdd2005-03-13 21:33:57 +0000134 asm("sta %w,x", ETHIAR);
oliverschmidt14821d42005-03-14 23:00:34 +0000135 asm("lda %v+1", uip_ethaddr);
oliverschmidt8871bdd2005-03-13 21:33:57 +0000136 asm("sta %w,x", ETHIAR+1);
oliverschmidt14821d42005-03-14 23:00:34 +0000137 asm("lda %v+2", uip_ethaddr);
oliverschmidt8871bdd2005-03-13 21:33:57 +0000138 asm("sta %w,x", ETHIAR+2);
oliverschmidt14821d42005-03-14 23:00:34 +0000139 asm("lda %v+3", uip_ethaddr);
oliverschmidt8871bdd2005-03-13 21:33:57 +0000140 asm("sta %w,x", ETHIAR+3);
oliverschmidt14821d42005-03-14 23:00:34 +0000141 asm("lda %v+4", uip_ethaddr);
oliverschmidt8871bdd2005-03-13 21:33:57 +0000142 asm("sta %w,x", ETHIAR+4);
oliverschmidt14821d42005-03-14 23:00:34 +0000143 asm("lda %v+5", uip_ethaddr);
oliverschmidt8871bdd2005-03-13 21:33:57 +0000144 asm("sta %w,x", ETHIAR+5);
145
146 BANK(2);
147 asm("lda #%%00000000"); /* No interrupts */
148 asm("sta %w,x", ETHMSK);
oliverschmidt84d84632005-03-31 22:03:41 +0000149L1:
oliverschmidt8871bdd2005-03-13 21:33:57 +0000150}
151#pragma optimize(pop)
152/*-----------------------------------------------------------------------------------*/
153#pragma optimize(push, off)
154u16_t lan91c96_poll(void)
155{
156 asm("ldx %v", slot_index);
157 asm("beq %g", L0);
158
159 asm("lda %w,x", ETHIST);
160 asm("and #%%00000001"); /* RCV INT */
161 asm("bne %g", L1);
162
163 /* No packet available */
164L0:
165 return 0;
166
167L1:
168 asm("lda #0");
169 asm("sta %w,x", ETHPTR);
170 asm("lda #%%11100000"); /* RCV,AUTO INCR.,READ */
171 asm("sta %w,x", ETHPTR+1);
172
173 asm("lda %w,x", ETHDATA); /* Status word */
174 asm("lda %w,x", ETHDATA);
175 asm("sta %v", packet_status); /* High byte only */
176
177 asm("lda %w,x", ETHDATA); /* Total number of bytes */
178 asm("sta %v", packet_length);
179 asm("lda %w,x", ETHDATA);
180 asm("sta %v+1", packet_length);
181
182 /* Last word contain 'last data byte' and 0x60 */
183 /* or 'fill byte' and 0x40 */
184
185 packet_length -= 6; /* The packet contains 3 extra words */
186
187 asm("lda %v", packet_status);
188 asm("and #$10");
189 asm("beq %g", L2);
190
191 packet_length++;
192
193L2:
194 if(packet_length > UIP_BUFSIZE) {
195
196 asm("ldx %v", slot_index);
197
198 /* Remove and release RX packet from FIFO */
199 asm("lda #%%10000000");
200 asm("sta %w,x", ETHMMUCR);
201 return 0;
202 }
203
204 asm("ldx %v", slot_index);
205
206 asm("lda #<%v", uip_buf);
207 asm("sta ptr1");
208 asm("lda #>%v", uip_buf);
209 asm("sta ptr1+1");
210
211 asm("lda %v+1", packet_length);
212 asm("sta tmp1");
213
214 asm("ldy #0");
215L3:
216 asm("lda %w,x", ETHDATA);
217 asm("sta (ptr1),y");
218 asm("iny");
219 asm("bne %g", L4);
220 asm("inc ptr1+1");
221L4:
222 asm("cpy %v", packet_length);
223 asm("bne %g", L3);
224 asm("dec tmp1");
225 asm("bpl %g", L3);
226
227 /* Remove and release RX packet from FIFO */
228 asm("lda #%%10000000");
229 asm("sta %w,x", ETHMMUCR);
230 return packet_length;
231}
232#pragma optimize(pop)
233/*-----------------------------------------------------------------------------------*/
234#pragma optimize(push, off)
235void lan91c96_send(void)
236{
237 /* First 14+40 (IP and TCP header) is send from uip_buf */
238 /* than data from uip_appdata */
239
240 asm("ldx %v", slot_index);
oliverschmidt389e2f22005-04-05 08:18:01 +0000241 asm("beq %g", L0);
oliverschmidt8871bdd2005-03-13 21:33:57 +0000242
243 asm("lda %v+1", uip_len);
244 asm("ora #%%00100000"); /* Allocate memory for TX */
245 asm("sta %w,x", ETHMMUCR);
246
247 asm("ldy #8"); /* Wait... */
248L1: /* Wait for allocation ready */
249 asm("lda %w,x", ETHIST);
250 asm("and #%%00001000"); /* ALLOC INT */
251 asm("bne %g", L2);
252 asm("dey");
253 asm("bne %g", L1);
oliverschmidt389e2f22005-04-05 08:18:01 +0000254L0:
oliverschmidt8871bdd2005-03-13 21:33:57 +0000255 return;
256
257L2:
258 asm("lda #%%00001000"); /* Acknowledge int, is it necessary ??? */
259 asm("sta %w,x", ETHACK);
260
261 asm("lda %w,x", ETHARR);
262 asm("sta %w,x", ETHPNR); /* Set packet address */
263
264 asm("lda #0");
265 asm("sta %w,x", ETHPTR);
266 asm("lda #%%01000000"); /* AUTO INCR. */
267 asm("sta %w,x", ETHPTR+1);
268
269 asm("lda #0"); /* Status written by CSMA */
270 asm("sta %w,x", ETHDATA);
271 asm("sta %w,x", ETHDATA);
272
273 asm("lda %v", uip_len);
274 asm("and #$01");
275 asm("beq %g", L3);
276
277 packet_length = uip_len + 5;
278 asm("jmp %g", L4);
279
280L3:
281 packet_length = uip_len + 6; /* +6 for status word, length and ctl byte */
282
283L4:
284 asm("ldx %v", slot_index);
285
286 asm("lda %v", packet_length);
287 asm("sta %w,x", ETHDATA);
288 asm("lda %v+1", packet_length);
289 asm("sta %w,x", ETHDATA);
290
291 /* Send 14+40=54 bytes of header */
292
293 if(uip_len <= UIP_LLH_LEN + UIP_TCPIP_HLEN) {
294
295 asm("ldx %v", slot_index);
296
297 asm("ldy #0");
298L5:
299 asm("lda %v,y", uip_buf);
300 asm("sta %w,x", ETHDATA);
301 asm("iny");
302 asm("cpy %v", uip_len);
303 asm("bne %g", L5);
304
305 } else {
306
307 asm("ldx %v", slot_index);
308
309 asm("ldy #0");
310L6:
311 asm("lda %v,y", uip_buf);
312 asm("sta %w,x", ETHDATA);
313 asm("iny");
314 asm("cpy #%b", UIP_LLH_LEN + UIP_TCPIP_HLEN);
315 asm("bne %g", L6);
316
oliverschmidte2c08622005-03-16 22:38:54 +0000317 packet_length = uip_len - (UIP_LLH_LEN + UIP_TCPIP_HLEN);
oliverschmidt8871bdd2005-03-13 21:33:57 +0000318
319 asm("ldx %v", slot_index);
320
321 asm("lda %v", uip_appdata); /* uip_appdata is pointer */
322 asm("sta ptr1");
323 asm("lda %v+1", uip_appdata);
324 asm("sta ptr1+1");
325
326 asm("ldy #0");
327L7:
328 asm("lda (ptr1),y");
329 asm("sta %w,x", ETHDATA);
330 asm("iny");
331 asm("bne %g", L8);
332 asm("inc ptr1+1");
333L8:
334 asm("cpy %v", packet_length);
335 asm("bne %g", L7);
336 asm("dec %v+1", packet_length);
337 asm("bpl %g", L7);
338 }
339
340 asm("lda %v", packet_length);
341 asm("and #$01");
342 asm("beq %g", L9);
343
344 asm("lda #%%00100000");
345 asm("sta %w,x", ETHDATA); /* Control byte */
346
347 asm("lda #%%11000000"); /* ENQUEUE PACKET - transmit packet */
348 asm("sta %w,x", ETHMMUCR);
349 return;
350
351L9:
352 asm("lda #0");
353 asm("sta %w,x", ETHDATA); /* Fill byte */
354 asm("sta %w,x", ETHDATA); /* Control byte */
355
356 asm("lda #%%11000000"); /* ENQUEUE PACKET - transmit packet */
357 asm("sta %w,x", ETHMMUCR);
oliverschmidt8871bdd2005-03-13 21:33:57 +0000358}
359#pragma optimize(pop)