blob: 2aa0844ddc5dec1bdf8fe03141c19b080056a992 [file] [log] [blame]
adamdunkels45c1f132004-02-16 20:59:49 +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 * Ethernet card for Commodore 64, based on lan91c96 chip
8 * is a device created by IDE64 Project team.
9 * More information: http://ide64.come.to
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote
20 * products derived from this software without specific prior
21 * written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
24 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
oliverschmidt6b786ba2005-03-10 00:53:07 +000035 * $Id: lan91c96.c,v 1.9 2005/03/10 00:53:07 oliverschmidt Exp $
adamdunkels45c1f132004-02-16 20:59:49 +000036 *
37 */
38
adamdunkels0a08fda2004-07-04 18:33:07 +000039#define UIP_ETHADDR0 0x00
40#define UIP_ETHADDR1 0x0d
41#define UIP_ETHADDR2 0x60
42#define UIP_ETHADDR3 0x80
43#define UIP_ETHADDR4 0x3d
44#define UIP_ETHADDR5 0xb9
45
adamdunkels45c1f132004-02-16 20:59:49 +000046#include "lan91c96.h"
47#include "uip.h"
48#include "uip_arp.h"
49
50#include <stdio.h>
51
52// #define DEBUG
53
54#define ETHBASE 0xde10
55
oliverschmidt3c3aed42005-03-10 00:05:46 +000056#define ETHBSR ETHBASE+0x0e /* Bank select register R/W (2B) */
adamdunkels45c1f132004-02-16 20:59:49 +000057
58/* Register bank 0 */
59
oliverschmidt3c3aed42005-03-10 00:05:46 +000060#define ETHTCR ETHBASE /* Transmition control register R/W (2B) */
61#define ETHEPHSR ETHBASE+2 /* EPH status register R/O (2B) */
62#define ETHRCR ETHBASE+4 /* Receive control register R/W (2B) */
63#define ETHECR ETHBASE+6 /* Counter register R/O (2B) */
64#define ETHMIR ETHBASE+8 /* Memory information register R/O (2B) */
65#define ETHMCR ETHBASE+0x0a /* Memory Config. reg. +0 R/W +1 R/O (2B) */
adamdunkels45c1f132004-02-16 20:59:49 +000066
67/* Register bank 1 */
68
oliverschmidt3c3aed42005-03-10 00:05:46 +000069#define ETHCR ETHBASE /* Configuration register R/W (2B) */
70#define ETHBAR ETHBASE+2 /* Base address register R/W (2B) */
71#define ETHIAR ETHBASE+4 /* Individual address register R/W (6B) */
72#define ETHGPR ETHBASE+0x0a /* General address register R/W (2B) */
73#define ETHCTR ETHBASE+0x0c /* Control register R/W (2B) */
adamdunkels45c1f132004-02-16 20:59:49 +000074
75/* Register bank 2 */
76
oliverschmidt3c3aed42005-03-10 00:05:46 +000077#define ETHMMUCR ETHBASE /* MMU command register W/O (1B) */
78#define ETHAUTOTX ETHBASE+1 /* AUTO TX start register R/W (1B) */
79#define ETHPNR ETHBASE+2 /* Packet number register R/W (1B) */
80#define ETHARR ETHBASE+3 /* Allocation result register R/O (1B) */
81#define ETHFIFO ETHBASE+4 /* FIFO ports register R/O (2B) */
82#define ETHPTR ETHBASE+6 /* Pointer register R/W (2B) */
83#define ETHDATA ETHBASE+8 /* Data register R/W (4B) */
84#define ETHIST ETHBASE+0x0c /* Interrupt status register R/O (1B) */
85#define ETHACK ETHBASE+0x0c /* Interrupt acknowledge register W/O (1B) */
86#define ETHMSK ETHBASE+0x0d /* Interrupt mask register R/W (1B) */
adamdunkels45c1f132004-02-16 20:59:49 +000087
88/* Register bank 3 */
89
oliverschmidt3c3aed42005-03-10 00:05:46 +000090#define ETHMT ETHBASE /* Multicast table R/W (8B) */
91#define ETHMGMT ETHBASE+8 /* Management interface R/W (2B) */
92#define ETHREV ETHBASE+0x0a /* Revision register R/W (2B) */
93#define ETHERCV ETHBASE+0x0c /* Early RCV register R/W (2B) */
adamdunkels45c1f132004-02-16 20:59:49 +000094
95#define BANK(num) asm("lda #%b",num); asm("sta %w",ETHBSR);
96
97#ifdef DEBUG
98static void print_packet(u8_t *, u16_t);
99#endif
100
101static u8_t packet_status;
102static u16_t packet_length;
103
adamdunkels45c1f132004-02-16 20:59:49 +0000104
oliverschmidt3c3aed42005-03-10 00:05:46 +0000105/*-----------------------------------------------------------------------------------*/
oliverschmidta8240ea2004-07-18 13:19:47 +0000106#pragma optimize(push, off)
adamdunkels45c1f132004-02-16 20:59:49 +0000107void lan91c96_init(void)
108{
109 /* Check if high byte is 0x33 */
110 asm("lda %w", ETHBSR+1);
111 asm("cmp #$33");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000112 asm("beq %g", L1);
adamdunkels45c1f132004-02-16 20:59:49 +0000113
oliverschmidt3c3aed42005-03-10 00:05:46 +0000114 asm("inc $d021"); /* Error */
adamdunkels45c1f132004-02-16 20:59:49 +0000115
oliverschmidt6b786ba2005-03-10 00:53:07 +0000116L1:
adamdunkels45c1f132004-02-16 20:59:49 +0000117
118 /* Reset ETH card */
119 BANK(0);
oliverschmidt3c3aed42005-03-10 00:05:46 +0000120 asm("lda #%%10000000"); /* Software reset */
adamdunkels45c1f132004-02-16 20:59:49 +0000121 asm("sta %w", ETHRCR+1);
122
123 asm("lda #0");
124 asm("sta %w", ETHRCR);
125 asm("sta %w", ETHRCR+1);
126
127 /* delay */
128 asm("ldx #0");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000129L2:
oliverschmidt3c3aed42005-03-10 00:05:46 +0000130 asm("cmp ($ff,x)"); /* 6 cycles */
131 asm("cmp ($ff,x)"); /* 6 cycles */
132 asm("dex"); /* 2 cycles */
oliverschmidt6b786ba2005-03-10 00:53:07 +0000133 asm("bne %g", L2); /* 3 cycles */
oliverschmidt3c3aed42005-03-10 00:05:46 +0000134 /* 17*256=4352 => 4,4 ms */
adamdunkels45c1f132004-02-16 20:59:49 +0000135
136 /* Enable transmit and receive */
oliverschmidt3c3aed42005-03-10 00:05:46 +0000137 asm("lda #%%10000001"); /* Enable transmit TXENA, PAD_EN */
adamdunkels45c1f132004-02-16 20:59:49 +0000138 asm("sta %w", ETHTCR);
oliverschmidt3c3aed42005-03-10 00:05:46 +0000139 asm("lda #%%00000011"); /* Enable receive, strip CRC ??? */
adamdunkels45c1f132004-02-16 20:59:49 +0000140 asm("sta %w", ETHRCR+1);
141
142 BANK(1);
143 asm("lda %w", ETHCR+1);
oliverschmidt3c3aed42005-03-10 00:05:46 +0000144 asm("ora #%%00010000"); /* No wait (IOCHRDY) */
adamdunkels45c1f132004-02-16 20:59:49 +0000145 asm("sta %w", ETHCR+1);
146
oliverschmidt3c3aed42005-03-10 00:05:46 +0000147 asm("lda #%%00001001"); /* Auto release */
adamdunkels45c1f132004-02-16 20:59:49 +0000148 asm("sta %w", ETHCTR+1);
149
150 /* Set MAC address */
151 asm("lda #%b", (unsigned)UIP_ETHADDR0);
152 asm("sta %w", ETHIAR);
153 asm("lda #%b", (unsigned)UIP_ETHADDR1);
154 asm("sta %w", ETHIAR+1);
155 asm("lda #%b", (unsigned)UIP_ETHADDR2);
156 asm("sta %w", ETHIAR+2);
157 asm("lda #%b", (unsigned)UIP_ETHADDR3);
158 asm("sta %w", ETHIAR+3);
159 asm("lda #%b", (unsigned)UIP_ETHADDR4);
160 asm("sta %w", ETHIAR+4);
161 asm("lda #%b", (unsigned)UIP_ETHADDR5);
162 asm("sta %w", ETHIAR+5);
163
164 BANK(2);
oliverschmidt3c3aed42005-03-10 00:05:46 +0000165 asm("lda #%%00001111"); /* RCV INT, ALLOC INT, TX INT, TX EMPTY */
adamdunkels45c1f132004-02-16 20:59:49 +0000166 asm("sta %w", ETHMSK);
167}
oliverschmidta8240ea2004-07-18 13:19:47 +0000168#pragma optimize(pop)
oliverschmidt3c3aed42005-03-10 00:05:46 +0000169/*-----------------------------------------------------------------------------------*/
oliverschmidta8240ea2004-07-18 13:19:47 +0000170#pragma optimize(push, off)
adamdunkels45c1f132004-02-16 20:59:49 +0000171u16_t lan91c96_poll(void)
adamdunkels45c1f132004-02-16 20:59:49 +0000172{
oliverschmidt3c3aed42005-03-10 00:05:46 +0000173#ifdef DEBUG
174 BANK(0);
175 printf("RAM: %d ", ((*(unsigned int *)(ETHMIR)) & 0xff00));
176 BANK(2);
177#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000178
179 asm("lda %w", ETHIST);
oliverschmidt3c3aed42005-03-10 00:05:46 +0000180 asm("and #%%00000001"); /* RCV INT */
oliverschmidt6b786ba2005-03-10 00:53:07 +0000181 asm("bne %g", L1);
adamdunkels45c1f132004-02-16 20:59:49 +0000182
183 /* No packet available */
184 return 0;
185
oliverschmidt6b786ba2005-03-10 00:53:07 +0000186L1:
adamdunkels45c1f132004-02-16 20:59:49 +0000187
oliverschmidt3c3aed42005-03-10 00:05:46 +0000188#ifdef DEBUG
adamdunkels45c1f132004-02-16 20:59:49 +0000189 printf("RCV: IRQ\n");
oliverschmidt3c3aed42005-03-10 00:05:46 +0000190#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000191
192 asm("lda #0");
193 asm("sta %w", ETHPTR);
oliverschmidt3c3aed42005-03-10 00:05:46 +0000194 asm("lda #%%11100000"); /* RCV,AUTO INCR.,READ */
adamdunkels45c1f132004-02-16 20:59:49 +0000195 asm("sta %w", ETHPTR+1);
196
oliverschmidt3c3aed42005-03-10 00:05:46 +0000197 asm("lda %w", ETHDATA); /* Status word */
adamdunkels45c1f132004-02-16 20:59:49 +0000198 asm("lda %w", ETHDATA);
oliverschmidt6b786ba2005-03-10 00:53:07 +0000199 asm("sta %v", packet_status); /* High byte only */
adamdunkels45c1f132004-02-16 20:59:49 +0000200
oliverschmidt3c3aed42005-03-10 00:05:46 +0000201 asm("lda %w", ETHDATA); /* Total number of bytes */
oliverschmidt6b786ba2005-03-10 00:53:07 +0000202 asm("sta %v", packet_length);
adamdunkels45c1f132004-02-16 20:59:49 +0000203 asm("lda %w", ETHDATA);
oliverschmidt6b786ba2005-03-10 00:53:07 +0000204 asm("sta %v+1", packet_length);
adamdunkels45c1f132004-02-16 20:59:49 +0000205
206 /* Last word contain 'last data byte' and 0x60 */
207 /* or 'fill byte' and 0x40 */
208
oliverschmidt3c3aed42005-03-10 00:05:46 +0000209 packet_length -= 6; /* The packet contains 3 extra words */
adamdunkels45c1f132004-02-16 20:59:49 +0000210
oliverschmidt6b786ba2005-03-10 00:53:07 +0000211 asm("lda %v", packet_status);
adamdunkels45c1f132004-02-16 20:59:49 +0000212 asm("and #$10");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000213 asm("beq %g", L2);
adamdunkels45c1f132004-02-16 20:59:49 +0000214
215 packet_length++;
216
oliverschmidt3c3aed42005-03-10 00:05:46 +0000217#ifdef DEBUG
adamdunkels45c1f132004-02-16 20:59:49 +0000218 printf("RCV: odd number of bytes\n");
oliverschmidt3c3aed42005-03-10 00:05:46 +0000219#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000220
oliverschmidt6b786ba2005-03-10 00:53:07 +0000221L2:
adamdunkels45c1f132004-02-16 20:59:49 +0000222
oliverschmidt3c3aed42005-03-10 00:05:46 +0000223#ifdef DEBUG
oliverschmidt6b786ba2005-03-10 00:53:07 +0000224 printf("RCV: L:%d ST-HIGH:0x%02x ", packet_length, packet_status);
oliverschmidt3c3aed42005-03-10 00:05:46 +0000225#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000226
oliverschmidt3c3aed42005-03-10 00:05:46 +0000227 if(packet_length > UIP_BUFSIZE) {
228
229 /* Remove and release RX packet from FIFO */
adamdunkels45c1f132004-02-16 20:59:49 +0000230 asm("lda #%%10000000");
231 asm("sta %w", ETHMMUCR);
232
oliverschmidt3c3aed42005-03-10 00:05:46 +0000233#ifdef DEBUG
adamdunkels45c1f132004-02-16 20:59:49 +0000234 printf("RCV: UIP_BUFSIZE exceeded - packet dropped!\n");
oliverschmidt3c3aed42005-03-10 00:05:46 +0000235#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000236
237 return 0;
238 }
239
oliverschmidt6b786ba2005-03-10 00:53:07 +0000240 asm("lda #<%v", uip_buf);
adamdunkels45c1f132004-02-16 20:59:49 +0000241 asm("sta ptr1");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000242 asm("lda #>%v", uip_buf);
adamdunkels45c1f132004-02-16 20:59:49 +0000243 asm("sta ptr1+1");
244
245 asm("ldy #0");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000246 asm("ldx %v+1", packet_length);
247 asm("beq %g", RE1); /* packet_length < 256 */
adamdunkels45c1f132004-02-16 20:59:49 +0000248
oliverschmidt6b786ba2005-03-10 00:53:07 +0000249RL1:
adamdunkels45c1f132004-02-16 20:59:49 +0000250 asm("lda %w", ETHDATA);
251 asm("sta (ptr1),y");
252 asm("iny");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000253 asm("bne %g", RL1);
adamdunkels45c1f132004-02-16 20:59:49 +0000254 asm("inc ptr1+1");
255 asm("dex");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000256 asm("bne %g", RL1);
adamdunkels45c1f132004-02-16 20:59:49 +0000257
oliverschmidt6b786ba2005-03-10 00:53:07 +0000258RE1:
adamdunkels45c1f132004-02-16 20:59:49 +0000259 asm("lda %w", ETHDATA);
260 asm("sta (ptr1),y");
261 asm("iny");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000262 asm("cpy %v", packet_length);
263 asm("bne %g", RE1);
adamdunkels45c1f132004-02-16 20:59:49 +0000264
oliverschmidt3c3aed42005-03-10 00:05:46 +0000265 /* Remove and release RX packet from FIFO */
adamdunkels45c1f132004-02-16 20:59:49 +0000266 asm("lda #%%10000000");
267 asm("sta %w", ETHMMUCR);
268
oliverschmidt3c3aed42005-03-10 00:05:46 +0000269#ifdef DEBUG
270 print_packet(uip_buf, packet_length);
271#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000272
273 return packet_length;
274}
oliverschmidta8240ea2004-07-18 13:19:47 +0000275#pragma optimize(pop)
oliverschmidt3c3aed42005-03-10 00:05:46 +0000276/*-----------------------------------------------------------------------------------*/
oliverschmidta8240ea2004-07-18 13:19:47 +0000277#pragma optimize(push, off)
adamdunkels45c1f132004-02-16 20:59:49 +0000278void lan91c96_send(void)
279{
oliverschmidt3c3aed42005-03-10 00:05:46 +0000280 /* First 14+40 (IP and TCP header) is send from uip_buf */
281 /* than data from uip_appdata */
282
283#ifdef DEBUG
adamdunkels45c1f132004-02-16 20:59:49 +0000284 printf("SND: send packet\n");
oliverschmidt3c3aed42005-03-10 00:05:46 +0000285#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000286
oliverschmidt6b786ba2005-03-10 00:53:07 +0000287 asm("lda %v+1", uip_len);
oliverschmidt3c3aed42005-03-10 00:05:46 +0000288 asm("ora #%%00100000"); /* Allocate memory for TX */
adamdunkels45c1f132004-02-16 20:59:49 +0000289 asm("sta %w", ETHMMUCR);
290
oliverschmidt3c3aed42005-03-10 00:05:46 +0000291 asm("ldx #8"); /* Wait... */
oliverschmidt6b786ba2005-03-10 00:53:07 +0000292L1: /* Wait for allocation ready */
adamdunkels45c1f132004-02-16 20:59:49 +0000293 asm("lda %w", ETHIST);
oliverschmidt3c3aed42005-03-10 00:05:46 +0000294 asm("and #%%00001000"); /* ALLOC INT */
oliverschmidt6b786ba2005-03-10 00:53:07 +0000295 asm("bne %g", X1);
adamdunkels45c1f132004-02-16 20:59:49 +0000296 asm("dex");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000297 asm("bne %g", L1);
adamdunkels45c1f132004-02-16 20:59:49 +0000298
oliverschmidt3c3aed42005-03-10 00:05:46 +0000299#ifdef DEBUG
adamdunkels45c1f132004-02-16 20:59:49 +0000300 printf("SND: ERR: memory alloc timeout\n");
oliverschmidt3c3aed42005-03-10 00:05:46 +0000301#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000302
303 return;
304
oliverschmidt6b786ba2005-03-10 00:53:07 +0000305X1:
oliverschmidt3c3aed42005-03-10 00:05:46 +0000306#ifdef DEBUG
adamdunkels45c1f132004-02-16 20:59:49 +0000307 printf("SND: packet memory allocated\n");
oliverschmidt3c3aed42005-03-10 00:05:46 +0000308#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000309
oliverschmidt3c3aed42005-03-10 00:05:46 +0000310 asm("lda #%%00001000"); /* Acknowledge int, is it necessary ??? */
adamdunkels45c1f132004-02-16 20:59:49 +0000311 asm("sta %w", ETHACK);
312
313 asm("lda %w", ETHARR);
oliverschmidt3c3aed42005-03-10 00:05:46 +0000314 asm("sta %w", ETHPNR); /* Set packet address */
adamdunkels45c1f132004-02-16 20:59:49 +0000315
316 asm("lda #0");
317 asm("sta %w", ETHPTR);
oliverschmidt3c3aed42005-03-10 00:05:46 +0000318 asm("lda #%%01000000"); /* AUTO INCR. */
adamdunkels45c1f132004-02-16 20:59:49 +0000319 asm("sta %w", ETHPTR+1);
320
oliverschmidt3c3aed42005-03-10 00:05:46 +0000321#ifdef DEBUG
adamdunkels45c1f132004-02-16 20:59:49 +0000322 printf("SND: L:%d ", uip_len);
oliverschmidt3c3aed42005-03-10 00:05:46 +0000323#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000324
oliverschmidt3c3aed42005-03-10 00:05:46 +0000325 asm("lda #0"); /* Status written by CSMA */
adamdunkels45c1f132004-02-16 20:59:49 +0000326 asm("sta %w", ETHDATA);
327 asm("sta %w", ETHDATA);
328
oliverschmidt6b786ba2005-03-10 00:53:07 +0000329 asm("lda %v", uip_len);
adamdunkels45c1f132004-02-16 20:59:49 +0000330 asm("and #$01");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000331 asm("beq %g", SD1);
adamdunkels45c1f132004-02-16 20:59:49 +0000332
oliverschmidt6b786ba2005-03-10 00:53:07 +0000333 packet_length = uip_len + 5;
334 asm("jmp %g", LC1);
adamdunkels45c1f132004-02-16 20:59:49 +0000335
oliverschmidt6b786ba2005-03-10 00:53:07 +0000336SD1:
adamdunkels45c1f132004-02-16 20:59:49 +0000337
oliverschmidt6b786ba2005-03-10 00:53:07 +0000338 packet_length = uip_len + 6; /* +6 for status word, length and ctl byte */
adamdunkels45c1f132004-02-16 20:59:49 +0000339
oliverschmidt6b786ba2005-03-10 00:53:07 +0000340LC1:
adamdunkels45c1f132004-02-16 20:59:49 +0000341
oliverschmidt3c3aed42005-03-10 00:05:46 +0000342#ifdef DEBUG
343 printf("SND: L:%d ", packet_length);
344#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000345
oliverschmidt6b786ba2005-03-10 00:53:07 +0000346 asm("lda %v", packet_length);
adamdunkels45c1f132004-02-16 20:59:49 +0000347 asm("sta %w", ETHDATA);
oliverschmidt6b786ba2005-03-10 00:53:07 +0000348 asm("lda %v+1", packet_length);
adamdunkels45c1f132004-02-16 20:59:49 +0000349 asm("sta %w", ETHDATA);
350
oliverschmidt3c3aed42005-03-10 00:05:46 +0000351#ifdef DEBUG
352 print_packet(uip_buf, uip_len);
353#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000354
oliverschmidt4affe762005-02-23 22:43:00 +0000355 /* Send 14+40=54 bytes of header */
adamdunkels45c1f132004-02-16 20:59:49 +0000356
oliverschmidt4affe762005-02-23 22:43:00 +0000357 if(uip_len <= UIP_LLH_LEN + UIP_TCPIP_HLEN) {
adamdunkels45c1f132004-02-16 20:59:49 +0000358
oliverschmidt3c3aed42005-03-10 00:05:46 +0000359#ifdef DEBUG
adamdunkels45c1f132004-02-16 20:59:49 +0000360 printf("SND: short packet sent.\n");
oliverschmidt3c3aed42005-03-10 00:05:46 +0000361#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000362
oliverschmidt6b786ba2005-03-10 00:53:07 +0000363 asm("ldx %v", uip_len);
adamdunkels45c1f132004-02-16 20:59:49 +0000364 asm("ldy #0");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000365WL1:
366 asm("lda %v,y", uip_buf);
adamdunkels45c1f132004-02-16 20:59:49 +0000367 asm("sta %w", ETHDATA);
368 asm("iny");
369 asm("dex");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000370 asm("bne %g", WL1);
adamdunkels45c1f132004-02-16 20:59:49 +0000371
372 } else {
373
oliverschmidt4affe762005-02-23 22:43:00 +0000374 asm("ldx #%b", UIP_LLH_LEN + UIP_TCPIP_HLEN);
adamdunkels45c1f132004-02-16 20:59:49 +0000375 asm("ldy #0");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000376WL2:
377 asm("lda %v,y", uip_buf);
adamdunkels45c1f132004-02-16 20:59:49 +0000378 asm("sta %w", ETHDATA);
379 asm("iny");
380 asm("dex");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000381 asm("bne %g", WL2);
adamdunkels45c1f132004-02-16 20:59:49 +0000382
oliverschmidt4affe762005-02-23 22:43:00 +0000383 uip_len -= UIP_LLH_LEN + UIP_TCPIP_HLEN;
adamdunkels45c1f132004-02-16 20:59:49 +0000384
oliverschmidt6b786ba2005-03-10 00:53:07 +0000385 asm("lda %v", uip_appdata); /* uip_appdata is pointer */
adamdunkels45c1f132004-02-16 20:59:49 +0000386 asm("sta ptr1");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000387 asm("lda %v+1", uip_appdata);
adamdunkels45c1f132004-02-16 20:59:49 +0000388 asm("sta ptr1+1");
389
390 asm("ldy #0");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000391 asm("ldx %v+1", uip_len);
392 asm("beq %g", RE1); /* packet_length < 256 */
adamdunkels45c1f132004-02-16 20:59:49 +0000393
oliverschmidt6b786ba2005-03-10 00:53:07 +0000394RL1:
adamdunkels45c1f132004-02-16 20:59:49 +0000395 asm("lda (ptr1),y");
396 asm("sta %w", ETHDATA);
397 asm("iny");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000398 asm("bne %g", RL1);
adamdunkels45c1f132004-02-16 20:59:49 +0000399 asm("inc ptr1+1");
400 asm("dex");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000401 asm("bne %g", RL1);
adamdunkels45c1f132004-02-16 20:59:49 +0000402
oliverschmidt6b786ba2005-03-10 00:53:07 +0000403RE1:
adamdunkels45c1f132004-02-16 20:59:49 +0000404 asm("lda (ptr1),y");
405 asm("sta %w", ETHDATA);
406 asm("iny");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000407 asm("cpy %v", uip_len);
408 asm("bne %g", RE1);
adamdunkels45c1f132004-02-16 20:59:49 +0000409
410 }
411
oliverschmidt6b786ba2005-03-10 00:53:07 +0000412 asm("lda %v", uip_len);
adamdunkels45c1f132004-02-16 20:59:49 +0000413 asm("and #$01");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000414 asm("beq %g", R3);
adamdunkels45c1f132004-02-16 20:59:49 +0000415
416 asm("lda #%%00100000");
oliverschmidt3c3aed42005-03-10 00:05:46 +0000417 asm("sta %w", ETHDATA); /* Control byte */
adamdunkels45c1f132004-02-16 20:59:49 +0000418
oliverschmidt3c3aed42005-03-10 00:05:46 +0000419 asm("lda #%%11000000"); /* ENQUEUE PACKET - transmit packet */
adamdunkels45c1f132004-02-16 20:59:49 +0000420 asm("sta %w", ETHMMUCR);
421
oliverschmidt3c3aed42005-03-10 00:05:46 +0000422#ifdef DEBUG
423 printf("\n## %02x", *(unsigned char *)(ETHIST));
424#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000425
426 return;
427
oliverschmidt6b786ba2005-03-10 00:53:07 +0000428R3:
adamdunkels45c1f132004-02-16 20:59:49 +0000429
430 asm("lda #0");
oliverschmidt3c3aed42005-03-10 00:05:46 +0000431 asm("sta %w", ETHDATA); /* Fill byte */
432 asm("sta %w", ETHDATA); /* Control byte */
adamdunkels45c1f132004-02-16 20:59:49 +0000433
oliverschmidt3c3aed42005-03-10 00:05:46 +0000434 asm("lda #%%11000000"); /* ENQUEUE PACKET - transmit packet */
adamdunkels45c1f132004-02-16 20:59:49 +0000435 asm("sta %w", ETHMMUCR);
436
oliverschmidt3c3aed42005-03-10 00:05:46 +0000437#ifdef DEBUG
438 printf("\n## %02x\n", *(unsigned char *)(ETHIST));
439#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000440 return;
441}
oliverschmidta8240ea2004-07-18 13:19:47 +0000442#pragma optimize(pop)
oliverschmidt3c3aed42005-03-10 00:05:46 +0000443/*-----------------------------------------------------------------------------------*/
adamdunkels45c1f132004-02-16 20:59:49 +0000444#ifdef DEBUG
445static void print_packet(u8_t *buf, u16_t length)
446{
447 int i;
448 int remainder;
449 int lines;
450 u8_t a;
451 int cur;
452 int address=0;
453
oliverschmidt3c3aed42005-03-10 00:05:46 +0000454 printf("\nPacket of length %d \n", length);
adamdunkels45c1f132004-02-16 20:59:49 +0000455
456 lines = length / 8;
457 remainder = length % 8;
458
oliverschmidt3c3aed42005-03-10 00:05:46 +0000459 for(i = 0; i < lines; i++) {
adamdunkels45c1f132004-02-16 20:59:49 +0000460 printf(":%04x ", address=i*8);
461
oliverschmidt3c3aed42005-03-10 00:05:46 +0000462 for(cur = 0; cur < 8; cur++) {
463 a = *(buf++);
adamdunkels45c1f132004-02-16 20:59:49 +0000464 printf("%02x ", a);
465 }
466 printf("\n");
467 }
468
469 printf(":%04x ", address+8);
470
oliverschmidt3c3aed42005-03-10 00:05:46 +0000471 for (i = 0; i < remainder; i++) {
472 a = *(buf++);
adamdunkels45c1f132004-02-16 20:59:49 +0000473 printf("%02x ", a);
474 }
475 printf("\n");
476}
477#endif /* DEBUG */