blob: 880998a222e6854bffbb9f1051b6233bb5110da0 [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 *
oliverschmidt83b83272005-03-29 23:14:39 +000035 * $Id: lan91c96.c,v 1.13 2005/03/29 23:14:39 oliverschmidt Exp $
adamdunkels45c1f132004-02-16 20:59:49 +000036 *
37 */
38
adamdunkels45c1f132004-02-16 20:59:49 +000039#include "lan91c96.h"
40#include "uip.h"
41#include "uip_arp.h"
42
43#include <stdio.h>
44
45// #define DEBUG
46
47#define ETHBASE 0xde10
48
oliverschmidt3c3aed42005-03-10 00:05:46 +000049#define ETHBSR ETHBASE+0x0e /* Bank select register R/W (2B) */
adamdunkels45c1f132004-02-16 20:59:49 +000050
51/* Register bank 0 */
52
oliverschmidt3c3aed42005-03-10 00:05:46 +000053#define ETHTCR ETHBASE /* Transmition control register R/W (2B) */
54#define ETHEPHSR ETHBASE+2 /* EPH status register R/O (2B) */
55#define ETHRCR ETHBASE+4 /* Receive control register R/W (2B) */
56#define ETHECR ETHBASE+6 /* Counter register R/O (2B) */
57#define ETHMIR ETHBASE+8 /* Memory information register R/O (2B) */
58#define ETHMCR ETHBASE+0x0a /* Memory Config. reg. +0 R/W +1 R/O (2B) */
adamdunkels45c1f132004-02-16 20:59:49 +000059
60/* Register bank 1 */
61
oliverschmidt3c3aed42005-03-10 00:05:46 +000062#define ETHCR ETHBASE /* Configuration register R/W (2B) */
63#define ETHBAR ETHBASE+2 /* Base address register R/W (2B) */
64#define ETHIAR ETHBASE+4 /* Individual address register R/W (6B) */
65#define ETHGPR ETHBASE+0x0a /* General address register R/W (2B) */
66#define ETHCTR ETHBASE+0x0c /* Control register R/W (2B) */
adamdunkels45c1f132004-02-16 20:59:49 +000067
68/* Register bank 2 */
69
oliverschmidt3c3aed42005-03-10 00:05:46 +000070#define ETHMMUCR ETHBASE /* MMU command register W/O (1B) */
71#define ETHAUTOTX ETHBASE+1 /* AUTO TX start register R/W (1B) */
72#define ETHPNR ETHBASE+2 /* Packet number register R/W (1B) */
73#define ETHARR ETHBASE+3 /* Allocation result register R/O (1B) */
74#define ETHFIFO ETHBASE+4 /* FIFO ports register R/O (2B) */
75#define ETHPTR ETHBASE+6 /* Pointer register R/W (2B) */
76#define ETHDATA ETHBASE+8 /* Data register R/W (4B) */
77#define ETHIST ETHBASE+0x0c /* Interrupt status register R/O (1B) */
78#define ETHACK ETHBASE+0x0c /* Interrupt acknowledge register W/O (1B) */
79#define ETHMSK ETHBASE+0x0d /* Interrupt mask register R/W (1B) */
adamdunkels45c1f132004-02-16 20:59:49 +000080
81/* Register bank 3 */
82
oliverschmidt3c3aed42005-03-10 00:05:46 +000083#define ETHMT ETHBASE /* Multicast table R/W (8B) */
84#define ETHMGMT ETHBASE+8 /* Management interface R/W (2B) */
85#define ETHREV ETHBASE+0x0a /* Revision register R/W (2B) */
86#define ETHERCV ETHBASE+0x0c /* Early RCV register R/W (2B) */
adamdunkels45c1f132004-02-16 20:59:49 +000087
oliverschmidtff8cd802005-03-13 21:21:15 +000088#define BANK(num) asm("lda #%b", num); asm("sta %w", ETHBSR);
adamdunkels45c1f132004-02-16 20:59:49 +000089
90#ifdef DEBUG
91static void print_packet(u8_t *, u16_t);
92#endif
93
94static u8_t packet_status;
95static u16_t packet_length;
96
adamdunkels45c1f132004-02-16 20:59:49 +000097
oliverschmidt3c3aed42005-03-10 00:05:46 +000098/*-----------------------------------------------------------------------------------*/
oliverschmidta8240ea2004-07-18 13:19:47 +000099#pragma optimize(push, off)
adamdunkels45c1f132004-02-16 20:59:49 +0000100void lan91c96_init(void)
101{
102 /* Check if high byte is 0x33 */
103 asm("lda %w", ETHBSR+1);
104 asm("cmp #$33");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000105 asm("beq %g", L1);
adamdunkels45c1f132004-02-16 20:59:49 +0000106
oliverschmidt3c3aed42005-03-10 00:05:46 +0000107 asm("inc $d021"); /* Error */
adamdunkels45c1f132004-02-16 20:59:49 +0000108
oliverschmidt6b786ba2005-03-10 00:53:07 +0000109L1:
adamdunkels45c1f132004-02-16 20:59:49 +0000110 /* Reset ETH card */
111 BANK(0);
oliverschmidt3c3aed42005-03-10 00:05:46 +0000112 asm("lda #%%10000000"); /* Software reset */
adamdunkels45c1f132004-02-16 20:59:49 +0000113 asm("sta %w", ETHRCR+1);
114
115 asm("lda #0");
116 asm("sta %w", ETHRCR);
117 asm("sta %w", ETHRCR+1);
118
119 /* delay */
oliverschmidtff8cd802005-03-13 21:21:15 +0000120 asm("ldy #0");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000121L2:
oliverschmidt3c3aed42005-03-10 00:05:46 +0000122 asm("cmp ($ff,x)"); /* 6 cycles */
123 asm("cmp ($ff,x)"); /* 6 cycles */
oliverschmidtff8cd802005-03-13 21:21:15 +0000124 asm("dey"); /* 2 cycles */
oliverschmidt6b786ba2005-03-10 00:53:07 +0000125 asm("bne %g", L2); /* 3 cycles */
oliverschmidt3c3aed42005-03-10 00:05:46 +0000126 /* 17*256=4352 => 4,4 ms */
adamdunkels45c1f132004-02-16 20:59:49 +0000127
128 /* Enable transmit and receive */
oliverschmidt3c3aed42005-03-10 00:05:46 +0000129 asm("lda #%%10000001"); /* Enable transmit TXENA, PAD_EN */
adamdunkels45c1f132004-02-16 20:59:49 +0000130 asm("sta %w", ETHTCR);
oliverschmidt3c3aed42005-03-10 00:05:46 +0000131 asm("lda #%%00000011"); /* Enable receive, strip CRC ??? */
adamdunkels45c1f132004-02-16 20:59:49 +0000132 asm("sta %w", ETHRCR+1);
133
134 BANK(1);
135 asm("lda %w", ETHCR+1);
oliverschmidt3c3aed42005-03-10 00:05:46 +0000136 asm("ora #%%00010000"); /* No wait (IOCHRDY) */
adamdunkels45c1f132004-02-16 20:59:49 +0000137 asm("sta %w", ETHCR+1);
138
oliverschmidt3c3aed42005-03-10 00:05:46 +0000139 asm("lda #%%00001001"); /* Auto release */
adamdunkels45c1f132004-02-16 20:59:49 +0000140 asm("sta %w", ETHCTR+1);
141
142 /* Set MAC address */
oliverschmidte245c9c2005-03-14 23:01:36 +0000143 asm("lda %v", uip_ethaddr);
adamdunkels45c1f132004-02-16 20:59:49 +0000144 asm("sta %w", ETHIAR);
oliverschmidte245c9c2005-03-14 23:01:36 +0000145 asm("lda %v+1", uip_ethaddr);
adamdunkels45c1f132004-02-16 20:59:49 +0000146 asm("sta %w", ETHIAR+1);
oliverschmidte245c9c2005-03-14 23:01:36 +0000147 asm("lda %v+2", uip_ethaddr);
adamdunkels45c1f132004-02-16 20:59:49 +0000148 asm("sta %w", ETHIAR+2);
oliverschmidte245c9c2005-03-14 23:01:36 +0000149 asm("lda %v+3", uip_ethaddr);
adamdunkels45c1f132004-02-16 20:59:49 +0000150 asm("sta %w", ETHIAR+3);
oliverschmidte245c9c2005-03-14 23:01:36 +0000151 asm("lda %v+4", uip_ethaddr);
adamdunkels45c1f132004-02-16 20:59:49 +0000152 asm("sta %w", ETHIAR+4);
oliverschmidte245c9c2005-03-14 23:01:36 +0000153 asm("lda %v+5", uip_ethaddr);
adamdunkels45c1f132004-02-16 20:59:49 +0000154 asm("sta %w", ETHIAR+5);
155
156 BANK(2);
oliverschmidt3c3aed42005-03-10 00:05:46 +0000157 asm("lda #%%00001111"); /* RCV INT, ALLOC INT, TX INT, TX EMPTY */
adamdunkels45c1f132004-02-16 20:59:49 +0000158 asm("sta %w", ETHMSK);
159}
oliverschmidta8240ea2004-07-18 13:19:47 +0000160#pragma optimize(pop)
oliverschmidt3c3aed42005-03-10 00:05:46 +0000161/*-----------------------------------------------------------------------------------*/
oliverschmidta8240ea2004-07-18 13:19:47 +0000162#pragma optimize(push, off)
adamdunkels45c1f132004-02-16 20:59:49 +0000163u16_t lan91c96_poll(void)
adamdunkels45c1f132004-02-16 20:59:49 +0000164{
oliverschmidt3c3aed42005-03-10 00:05:46 +0000165#ifdef DEBUG
166 BANK(0);
167 printf("RAM: %d ", ((*(unsigned int *)(ETHMIR)) & 0xff00));
168 BANK(2);
169#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000170
171 asm("lda %w", ETHIST);
oliverschmidt3c3aed42005-03-10 00:05:46 +0000172 asm("and #%%00000001"); /* RCV INT */
oliverschmidt6b786ba2005-03-10 00:53:07 +0000173 asm("bne %g", L1);
adamdunkels45c1f132004-02-16 20:59:49 +0000174
175 /* No packet available */
176 return 0;
177
oliverschmidt6b786ba2005-03-10 00:53:07 +0000178L1:
adamdunkels45c1f132004-02-16 20:59:49 +0000179
oliverschmidt3c3aed42005-03-10 00:05:46 +0000180#ifdef DEBUG
adamdunkels45c1f132004-02-16 20:59:49 +0000181 printf("RCV: IRQ\n");
oliverschmidt3c3aed42005-03-10 00:05:46 +0000182#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000183
184 asm("lda #0");
185 asm("sta %w", ETHPTR);
oliverschmidt3c3aed42005-03-10 00:05:46 +0000186 asm("lda #%%11100000"); /* RCV,AUTO INCR.,READ */
adamdunkels45c1f132004-02-16 20:59:49 +0000187 asm("sta %w", ETHPTR+1);
188
oliverschmidt3c3aed42005-03-10 00:05:46 +0000189 asm("lda %w", ETHDATA); /* Status word */
adamdunkels45c1f132004-02-16 20:59:49 +0000190 asm("lda %w", ETHDATA);
oliverschmidt6b786ba2005-03-10 00:53:07 +0000191 asm("sta %v", packet_status); /* High byte only */
adamdunkels45c1f132004-02-16 20:59:49 +0000192
oliverschmidt3c3aed42005-03-10 00:05:46 +0000193 asm("lda %w", ETHDATA); /* Total number of bytes */
oliverschmidt6b786ba2005-03-10 00:53:07 +0000194 asm("sta %v", packet_length);
adamdunkels45c1f132004-02-16 20:59:49 +0000195 asm("lda %w", ETHDATA);
oliverschmidt6b786ba2005-03-10 00:53:07 +0000196 asm("sta %v+1", packet_length);
adamdunkels45c1f132004-02-16 20:59:49 +0000197
198 /* Last word contain 'last data byte' and 0x60 */
199 /* or 'fill byte' and 0x40 */
200
oliverschmidt3c3aed42005-03-10 00:05:46 +0000201 packet_length -= 6; /* The packet contains 3 extra words */
adamdunkels45c1f132004-02-16 20:59:49 +0000202
oliverschmidt6b786ba2005-03-10 00:53:07 +0000203 asm("lda %v", packet_status);
adamdunkels45c1f132004-02-16 20:59:49 +0000204 asm("and #$10");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000205 asm("beq %g", L2);
adamdunkels45c1f132004-02-16 20:59:49 +0000206
207 packet_length++;
208
oliverschmidt3c3aed42005-03-10 00:05:46 +0000209#ifdef DEBUG
adamdunkels45c1f132004-02-16 20:59:49 +0000210 printf("RCV: odd number of bytes\n");
oliverschmidt3c3aed42005-03-10 00:05:46 +0000211#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000212
oliverschmidt6b786ba2005-03-10 00:53:07 +0000213L2:
adamdunkels45c1f132004-02-16 20:59:49 +0000214
oliverschmidt3c3aed42005-03-10 00:05:46 +0000215#ifdef DEBUG
oliverschmidt6b786ba2005-03-10 00:53:07 +0000216 printf("RCV: L:%d ST-HIGH:0x%02x ", packet_length, packet_status);
oliverschmidt3c3aed42005-03-10 00:05:46 +0000217#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000218
oliverschmidt3c3aed42005-03-10 00:05:46 +0000219 if(packet_length > UIP_BUFSIZE) {
220
221 /* Remove and release RX packet from FIFO */
adamdunkels45c1f132004-02-16 20:59:49 +0000222 asm("lda #%%10000000");
223 asm("sta %w", ETHMMUCR);
224
oliverschmidt3c3aed42005-03-10 00:05:46 +0000225#ifdef DEBUG
adamdunkels45c1f132004-02-16 20:59:49 +0000226 printf("RCV: UIP_BUFSIZE exceeded - packet dropped!\n");
oliverschmidt3c3aed42005-03-10 00:05:46 +0000227#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000228
229 return 0;
230 }
231
oliverschmidt6b786ba2005-03-10 00:53:07 +0000232 asm("lda #<%v", uip_buf);
adamdunkels45c1f132004-02-16 20:59:49 +0000233 asm("sta ptr1");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000234 asm("lda #>%v", uip_buf);
adamdunkels45c1f132004-02-16 20:59:49 +0000235 asm("sta ptr1+1");
236
oliverschmidtff8cd802005-03-13 21:21:15 +0000237 asm("lda %v+1", packet_length);
238 asm("sta tmp1");
239
adamdunkels45c1f132004-02-16 20:59:49 +0000240 asm("ldy #0");
oliverschmidtff8cd802005-03-13 21:21:15 +0000241L3:
adamdunkels45c1f132004-02-16 20:59:49 +0000242 asm("lda %w", ETHDATA);
243 asm("sta (ptr1),y");
244 asm("iny");
oliverschmidtff8cd802005-03-13 21:21:15 +0000245 asm("bne %g", L4);
adamdunkels45c1f132004-02-16 20:59:49 +0000246 asm("inc ptr1+1");
oliverschmidtff8cd802005-03-13 21:21:15 +0000247L4:
oliverschmidt6b786ba2005-03-10 00:53:07 +0000248 asm("cpy %v", packet_length);
oliverschmidtff8cd802005-03-13 21:21:15 +0000249 asm("bne %g", L3);
250 asm("dec tmp1");
251 asm("bpl %g", L3);
adamdunkels45c1f132004-02-16 20:59:49 +0000252
oliverschmidt3c3aed42005-03-10 00:05:46 +0000253 /* Remove and release RX packet from FIFO */
adamdunkels45c1f132004-02-16 20:59:49 +0000254 asm("lda #%%10000000");
255 asm("sta %w", ETHMMUCR);
256
oliverschmidt3c3aed42005-03-10 00:05:46 +0000257#ifdef DEBUG
258 print_packet(uip_buf, packet_length);
259#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000260
261 return packet_length;
262}
oliverschmidta8240ea2004-07-18 13:19:47 +0000263#pragma optimize(pop)
oliverschmidt3c3aed42005-03-10 00:05:46 +0000264/*-----------------------------------------------------------------------------------*/
oliverschmidta8240ea2004-07-18 13:19:47 +0000265#pragma optimize(push, off)
adamdunkels45c1f132004-02-16 20:59:49 +0000266void lan91c96_send(void)
267{
oliverschmidt3c3aed42005-03-10 00:05:46 +0000268 /* First 14+40 (IP and TCP header) is send from uip_buf */
269 /* than data from uip_appdata */
270
271#ifdef DEBUG
adamdunkels45c1f132004-02-16 20:59:49 +0000272 printf("SND: send packet\n");
oliverschmidt3c3aed42005-03-10 00:05:46 +0000273#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000274
oliverschmidt6b786ba2005-03-10 00:53:07 +0000275 asm("lda %v+1", uip_len);
oliverschmidt3c3aed42005-03-10 00:05:46 +0000276 asm("ora #%%00100000"); /* Allocate memory for TX */
adamdunkels45c1f132004-02-16 20:59:49 +0000277 asm("sta %w", ETHMMUCR);
278
oliverschmidtff8cd802005-03-13 21:21:15 +0000279 asm("ldy #8"); /* Wait... */
oliverschmidt6b786ba2005-03-10 00:53:07 +0000280L1: /* Wait for allocation ready */
adamdunkels45c1f132004-02-16 20:59:49 +0000281 asm("lda %w", ETHIST);
oliverschmidt3c3aed42005-03-10 00:05:46 +0000282 asm("and #%%00001000"); /* ALLOC INT */
oliverschmidtff8cd802005-03-13 21:21:15 +0000283 asm("bne %g", L2);
284 asm("dey");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000285 asm("bne %g", L1);
adamdunkels45c1f132004-02-16 20:59:49 +0000286
oliverschmidt3c3aed42005-03-10 00:05:46 +0000287#ifdef DEBUG
adamdunkels45c1f132004-02-16 20:59:49 +0000288 printf("SND: ERR: memory alloc timeout\n");
oliverschmidt3c3aed42005-03-10 00:05:46 +0000289#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000290
291 return;
292
oliverschmidtff8cd802005-03-13 21:21:15 +0000293L2:
294
oliverschmidt3c3aed42005-03-10 00:05:46 +0000295#ifdef DEBUG
adamdunkels45c1f132004-02-16 20:59:49 +0000296 printf("SND: packet memory allocated\n");
oliverschmidt3c3aed42005-03-10 00:05:46 +0000297#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000298
oliverschmidt3c3aed42005-03-10 00:05:46 +0000299 asm("lda #%%00001000"); /* Acknowledge int, is it necessary ??? */
adamdunkels45c1f132004-02-16 20:59:49 +0000300 asm("sta %w", ETHACK);
301
302 asm("lda %w", ETHARR);
oliverschmidt3c3aed42005-03-10 00:05:46 +0000303 asm("sta %w", ETHPNR); /* Set packet address */
adamdunkels45c1f132004-02-16 20:59:49 +0000304
305 asm("lda #0");
306 asm("sta %w", ETHPTR);
oliverschmidt3c3aed42005-03-10 00:05:46 +0000307 asm("lda #%%01000000"); /* AUTO INCR. */
adamdunkels45c1f132004-02-16 20:59:49 +0000308 asm("sta %w", ETHPTR+1);
309
oliverschmidt3c3aed42005-03-10 00:05:46 +0000310#ifdef DEBUG
adamdunkels45c1f132004-02-16 20:59:49 +0000311 printf("SND: L:%d ", uip_len);
oliverschmidt3c3aed42005-03-10 00:05:46 +0000312#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000313
oliverschmidt3c3aed42005-03-10 00:05:46 +0000314 asm("lda #0"); /* Status written by CSMA */
adamdunkels45c1f132004-02-16 20:59:49 +0000315 asm("sta %w", ETHDATA);
316 asm("sta %w", ETHDATA);
317
oliverschmidt6b786ba2005-03-10 00:53:07 +0000318 asm("lda %v", uip_len);
adamdunkels45c1f132004-02-16 20:59:49 +0000319 asm("and #$01");
oliverschmidtff8cd802005-03-13 21:21:15 +0000320 asm("beq %g", L3);
adamdunkels45c1f132004-02-16 20:59:49 +0000321
oliverschmidt6b786ba2005-03-10 00:53:07 +0000322 packet_length = uip_len + 5;
oliverschmidtff8cd802005-03-13 21:21:15 +0000323 asm("jmp %g", L4);
adamdunkels45c1f132004-02-16 20:59:49 +0000324
oliverschmidtff8cd802005-03-13 21:21:15 +0000325L3:
oliverschmidt6b786ba2005-03-10 00:53:07 +0000326 packet_length = uip_len + 6; /* +6 for status word, length and ctl byte */
adamdunkels45c1f132004-02-16 20:59:49 +0000327
oliverschmidtff8cd802005-03-13 21:21:15 +0000328L4:
adamdunkels45c1f132004-02-16 20:59:49 +0000329
oliverschmidt3c3aed42005-03-10 00:05:46 +0000330#ifdef DEBUG
331 printf("SND: L:%d ", packet_length);
332#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000333
oliverschmidt6b786ba2005-03-10 00:53:07 +0000334 asm("lda %v", packet_length);
adamdunkels45c1f132004-02-16 20:59:49 +0000335 asm("sta %w", ETHDATA);
oliverschmidt6b786ba2005-03-10 00:53:07 +0000336 asm("lda %v+1", packet_length);
adamdunkels45c1f132004-02-16 20:59:49 +0000337 asm("sta %w", ETHDATA);
338
oliverschmidt3c3aed42005-03-10 00:05:46 +0000339#ifdef DEBUG
340 print_packet(uip_buf, uip_len);
341#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000342
oliverschmidt4affe762005-02-23 22:43:00 +0000343 /* Send 14+40=54 bytes of header */
adamdunkels45c1f132004-02-16 20:59:49 +0000344
oliverschmidt4affe762005-02-23 22:43:00 +0000345 if(uip_len <= UIP_LLH_LEN + UIP_TCPIP_HLEN) {
adamdunkels45c1f132004-02-16 20:59:49 +0000346
oliverschmidt3c3aed42005-03-10 00:05:46 +0000347#ifdef DEBUG
adamdunkels45c1f132004-02-16 20:59:49 +0000348 printf("SND: short packet sent.\n");
oliverschmidt3c3aed42005-03-10 00:05:46 +0000349#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000350
adamdunkels45c1f132004-02-16 20:59:49 +0000351 asm("ldy #0");
oliverschmidtff8cd802005-03-13 21:21:15 +0000352L5:
oliverschmidt6b786ba2005-03-10 00:53:07 +0000353 asm("lda %v,y", uip_buf);
adamdunkels45c1f132004-02-16 20:59:49 +0000354 asm("sta %w", ETHDATA);
355 asm("iny");
oliverschmidtff8cd802005-03-13 21:21:15 +0000356 asm("cpy %v", uip_len);
357 asm("bne %g", L5);
adamdunkels45c1f132004-02-16 20:59:49 +0000358
359 } else {
360
adamdunkels45c1f132004-02-16 20:59:49 +0000361 asm("ldy #0");
oliverschmidtff8cd802005-03-13 21:21:15 +0000362L6:
oliverschmidt6b786ba2005-03-10 00:53:07 +0000363 asm("lda %v,y", uip_buf);
adamdunkels45c1f132004-02-16 20:59:49 +0000364 asm("sta %w", ETHDATA);
365 asm("iny");
oliverschmidtff8cd802005-03-13 21:21:15 +0000366 asm("cpy #%b", UIP_LLH_LEN + UIP_TCPIP_HLEN);
367 asm("bne %g", L6);
adamdunkels45c1f132004-02-16 20:59:49 +0000368
oliverschmidtc8bfc022005-03-16 22:39:21 +0000369 packet_length = uip_len - (UIP_LLH_LEN + UIP_TCPIP_HLEN);
adamdunkels45c1f132004-02-16 20:59:49 +0000370
oliverschmidt6b786ba2005-03-10 00:53:07 +0000371 asm("lda %v", uip_appdata); /* uip_appdata is pointer */
adamdunkels45c1f132004-02-16 20:59:49 +0000372 asm("sta ptr1");
oliverschmidt6b786ba2005-03-10 00:53:07 +0000373 asm("lda %v+1", uip_appdata);
adamdunkels45c1f132004-02-16 20:59:49 +0000374 asm("sta ptr1+1");
375
376 asm("ldy #0");
oliverschmidtff8cd802005-03-13 21:21:15 +0000377L7:
adamdunkels45c1f132004-02-16 20:59:49 +0000378 asm("lda (ptr1),y");
379 asm("sta %w", ETHDATA);
380 asm("iny");
oliverschmidtff8cd802005-03-13 21:21:15 +0000381 asm("bne %g", L8);
adamdunkels45c1f132004-02-16 20:59:49 +0000382 asm("inc ptr1+1");
oliverschmidtff8cd802005-03-13 21:21:15 +0000383L8:
384 asm("cpy %v", packet_length);
385 asm("bne %g", L7);
386 asm("dec %v+1", packet_length);
387 asm("bpl %g", L7);
adamdunkels45c1f132004-02-16 20:59:49 +0000388 }
389
oliverschmidtff8cd802005-03-13 21:21:15 +0000390 asm("lda %v", packet_length);
adamdunkels45c1f132004-02-16 20:59:49 +0000391 asm("and #$01");
oliverschmidtff8cd802005-03-13 21:21:15 +0000392 asm("beq %g", L9);
adamdunkels45c1f132004-02-16 20:59:49 +0000393
394 asm("lda #%%00100000");
oliverschmidt3c3aed42005-03-10 00:05:46 +0000395 asm("sta %w", ETHDATA); /* Control byte */
adamdunkels45c1f132004-02-16 20:59:49 +0000396
oliverschmidt3c3aed42005-03-10 00:05:46 +0000397 asm("lda #%%11000000"); /* ENQUEUE PACKET - transmit packet */
adamdunkels45c1f132004-02-16 20:59:49 +0000398 asm("sta %w", ETHMMUCR);
399
oliverschmidt3c3aed42005-03-10 00:05:46 +0000400#ifdef DEBUG
401 printf("\n## %02x", *(unsigned char *)(ETHIST));
402#endif
adamdunkels45c1f132004-02-16 20:59:49 +0000403
404 return;
405
oliverschmidtff8cd802005-03-13 21:21:15 +0000406L9:
adamdunkels45c1f132004-02-16 20:59:49 +0000407 asm("lda #0");
oliverschmidt3c3aed42005-03-10 00:05:46 +0000408 asm("sta %w", ETHDATA); /* Fill byte */
409 asm("sta %w", ETHDATA); /* Control byte */
adamdunkels45c1f132004-02-16 20:59:49 +0000410
oliverschmidt3c3aed42005-03-10 00:05:46 +0000411 asm("lda #%%11000000"); /* ENQUEUE PACKET - transmit packet */
adamdunkels45c1f132004-02-16 20:59:49 +0000412 asm("sta %w", ETHMMUCR);
413
oliverschmidt3c3aed42005-03-10 00:05:46 +0000414#ifdef DEBUG
415 printf("\n## %02x\n", *(unsigned char *)(ETHIST));
416#endif
oliverschmidt83b83272005-03-29 23:14:39 +0000417
adamdunkels45c1f132004-02-16 20:59:49 +0000418}
oliverschmidta8240ea2004-07-18 13:19:47 +0000419#pragma optimize(pop)
oliverschmidt3c3aed42005-03-10 00:05:46 +0000420/*-----------------------------------------------------------------------------------*/
adamdunkels45c1f132004-02-16 20:59:49 +0000421#ifdef DEBUG
422static void print_packet(u8_t *buf, u16_t length)
423{
424 int i;
425 int remainder;
426 int lines;
427 u8_t a;
428 int cur;
429 int address=0;
430
oliverschmidt3c3aed42005-03-10 00:05:46 +0000431 printf("\nPacket of length %d \n", length);
adamdunkels45c1f132004-02-16 20:59:49 +0000432
433 lines = length / 8;
434 remainder = length % 8;
435
oliverschmidt3c3aed42005-03-10 00:05:46 +0000436 for(i = 0; i < lines; i++) {
adamdunkels45c1f132004-02-16 20:59:49 +0000437 printf(":%04x ", address=i*8);
438
oliverschmidt3c3aed42005-03-10 00:05:46 +0000439 for(cur = 0; cur < 8; cur++) {
440 a = *(buf++);
adamdunkels45c1f132004-02-16 20:59:49 +0000441 printf("%02x ", a);
442 }
443 printf("\n");
444 }
445
446 printf(":%04x ", address+8);
447
oliverschmidt3c3aed42005-03-10 00:05:46 +0000448 for (i = 0; i < remainder; i++) {
449 a = *(buf++);
adamdunkels45c1f132004-02-16 20:59:49 +0000450 printf("%02x ", a);
451 }
452 printf("\n");
453}
454#endif /* DEBUG */