blob: f0cd2b62eb3e8132910dbf8533846543c80756b5 [file] [log] [blame]
Nobuhiro Iwamatsu702c85b2008-09-30 15:02:53 +09001/*
2Ported to U-Boot by Christian Pellegrin <chri@ascensit.com>
3
4Based on sources from the Linux kernel (pcnet_cs.c, 8390.h) and
5eCOS(if_dp83902a.c, if_dp83902a.h). Both of these 2 wonderful world
6are GPL, so this is, of course, GPL.
7
8==========================================================================
9
10dev/if_dp83902a.c
11
12Ethernet device driver for NS DP83902a ethernet controller
13
14==========================================================================
15####ECOSGPLCOPYRIGHTBEGIN####
16-------------------------------------------
17This file is part of eCos, the Embedded Configurable Operating System.
18Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
19
20eCos is free software; you can redistribute it and/or modify it under
21the terms of the GNU General Public License as published by the Free
22Software Foundation; either version 2 or (at your option) any later version.
23
24eCos is distributed in the hope that it will be useful, but WITHOUT ANY
25WARRANTY; without even the implied warranty of MERCHANTABILITY or
26FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
27for more details.
28
29You should have received a copy of the GNU General Public License along
30with eCos; if not, write to the Free Software Foundation, Inc.,
3159 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
32
33As a special exception, if other files instantiate templates or use macros
34or inline functions from this file, or you compile this file and link it
35with other works to produce a work based on this file, this file does not
36by itself cause the resulting work to be covered by the GNU General Public
37License. However the source code for this file must still be made available
38in accordance with section (3) of the GNU General Public License.
39
40This exception does not invalidate any other reasons why a work based on
41this file might be covered by the GNU General Public License.
42
43Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
44at http://sources.redhat.com/ecos/ecos-license/
45-------------------------------------------
46####ECOSGPLCOPYRIGHTEND####
47####BSDCOPYRIGHTBEGIN####
48
49-------------------------------------------
50
51Portions of this software may have been derived from OpenBSD or other sources,
52and are covered by the appropriate copyright disclaimers included herein.
53
54-------------------------------------------
55
56####BSDCOPYRIGHTEND####
57==========================================================================
58#####DESCRIPTIONBEGIN####
59
60Author(s): gthomas
61Contributors: gthomas, jskov, rsandifo
62Date: 2001-06-13
63Purpose:
64Description:
65
66FIXME: Will fail if pinged with large packets (1520 bytes)
67Add promisc config
68Add SNMP
69
70####DESCRIPTIONEND####
71
72==========================================================================
73*/
74
75#include <common.h>
76#include <command.h>
77#include <net.h>
78#include <malloc.h>
79
Nobuhiro Iwamatsu702c85b2008-09-30 15:02:53 +090080/* forward definition of function used for the uboot interface */
81void uboot_push_packet_len(int len);
82void uboot_push_tx_done(int key, int val);
83
84/* NE2000 base header file */
85#include "ne2000_base.h"
86
87#if defined(CONFIG_DRIVER_AX88796L)
88/* AX88796L support */
89#include "ax88796.h"
90#else
91/* Basic NE2000 chip support */
92#include "ne2000.h"
93#endif
94
95static dp83902a_priv_data_t nic; /* just one instance of the card supported */
96
97static bool
98dp83902a_init(void)
99{
100 dp83902a_priv_data_t *dp = &nic;
101 u8* base;
102#if defined(NE2000_BASIC_INIT)
103 int i;
104#endif
105
106 DEBUG_FUNCTION();
107
108 base = dp->base;
109 if (!base)
110 return false; /* No device found */
111
112 DEBUG_LINE();
113
114#if defined(NE2000_BASIC_INIT)
115 /* AX88796L doesn't need */
116 /* Prepare ESA */
117 DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE1); /* Select page 1 */
118 /* Use the address from the serial EEPROM */
119 for (i = 0; i < 6; i++)
120 DP_IN(base, DP_P1_PAR0+i, dp->esa[i]);
121 DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE0); /* Select page 0 */
122
123 printf("NE2000 - %s ESA: %02x:%02x:%02x:%02x:%02x:%02x\n",
124 "eeprom",
125 dp->esa[0],
126 dp->esa[1],
127 dp->esa[2],
128 dp->esa[3],
129 dp->esa[4],
130 dp->esa[5] );
131
132#endif /* NE2000_BASIC_INIT */
133 return true;
134}
135
136static void
137dp83902a_stop(void)
138{
139 dp83902a_priv_data_t *dp = &nic;
140 u8 *base = dp->base;
141
142 DEBUG_FUNCTION();
143
144 DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP); /* Brutal */
145 DP_OUT(base, DP_ISR, 0xFF); /* Clear any pending interrupts */
146 DP_OUT(base, DP_IMR, 0x00); /* Disable all interrupts */
147
148 dp->running = false;
149}
150
151/*
152 * This function is called to "start up" the interface. It may be called
153 * multiple times, even when the hardware is already running. It will be
154 * called whenever something "hardware oriented" changes and should leave
155 * the hardware ready to send/receive packets.
156 */
157static void
158dp83902a_start(u8 * enaddr)
159{
160 dp83902a_priv_data_t *dp = &nic;
161 u8 *base = dp->base;
162 int i;
163
164 DEBUG_FUNCTION();
165
166 DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP); /* Brutal */
167 DP_OUT(base, DP_DCR, DP_DCR_INIT);
168 DP_OUT(base, DP_RBCH, 0); /* Remote byte count */
169 DP_OUT(base, DP_RBCL, 0);
170 DP_OUT(base, DP_RCR, DP_RCR_MON); /* Accept no packets */
171 DP_OUT(base, DP_TCR, DP_TCR_LOCAL); /* Transmitter [virtually] off */
172 DP_OUT(base, DP_TPSR, dp->tx_buf1); /* Transmitter start page */
173 dp->tx1 = dp->tx2 = 0;
174 dp->tx_next = dp->tx_buf1;
175 dp->tx_started = false;
176 dp->running = true;
177 DP_OUT(base, DP_PSTART, dp->rx_buf_start); /* Receive ring start page */
178 DP_OUT(base, DP_BNDRY, dp->rx_buf_end - 1); /* Receive ring boundary */
179 DP_OUT(base, DP_PSTOP, dp->rx_buf_end); /* Receive ring end page */
180 dp->rx_next = dp->rx_buf_start - 1;
181 dp->running = true;
182 DP_OUT(base, DP_ISR, 0xFF); /* Clear any pending interrupts */
183 DP_OUT(base, DP_IMR, DP_IMR_All); /* Enable all interrupts */
184 DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE1 | DP_CR_STOP); /* Select page 1 */
185 DP_OUT(base, DP_P1_CURP, dp->rx_buf_start); /* Current page - next free page for Rx */
186 dp->running = true;
187 for (i = 0; i < ETHER_ADDR_LEN; i++) {
188 /* FIXME */
189 /*((vu_short*)( base + ((DP_P1_PAR0 + i) * 2) +
190 * 0x1400)) = enaddr[i];*/
191 DP_OUT(base, DP_P1_PAR0+i, enaddr[i]);
192 }
193 /* Enable and start device */
194 DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
195 DP_OUT(base, DP_TCR, DP_TCR_NORMAL); /* Normal transmit operations */
196 DP_OUT(base, DP_RCR, DP_RCR_AB); /* Accept broadcast, no errors, no multicast */
197 dp->running = true;
198}
199
200/*
201 * This routine is called to start the transmitter. It is split out from the
202 * data handling routine so it may be called either when data becomes first
203 * available or when an Tx interrupt occurs
204 */
205
206static void
207dp83902a_start_xmit(int start_page, int len)
208{
209 dp83902a_priv_data_t *dp = (dp83902a_priv_data_t *) &nic;
210 u8 *base = dp->base;
211
212 DEBUG_FUNCTION();
213
214#if DEBUG & 1
215 printf("Tx pkt %d len %d\n", start_page, len);
216 if (dp->tx_started)
217 printf("TX already started?!?\n");
218#endif
219
220 DP_OUT(base, DP_ISR, (DP_ISR_TxP | DP_ISR_TxE));
221 DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
222 DP_OUT(base, DP_TBCL, len & 0xFF);
223 DP_OUT(base, DP_TBCH, len >> 8);
224 DP_OUT(base, DP_TPSR, start_page);
225 DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_TXPKT | DP_CR_START);
226
227 dp->tx_started = true;
228}
229
230/*
231 * This routine is called to send data to the hardware. It is known a-priori
232 * that there is free buffer space (dp->tx_next).
233 */
234static void
235dp83902a_send(u8 *data, int total_len, u32 key)
236{
237 struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic;
238 u8 *base = dp->base;
239 int len, start_page, pkt_len, i, isr;
240#if DEBUG & 4
241 int dx;
242#endif
243
244 DEBUG_FUNCTION();
245
246 len = pkt_len = total_len;
247 if (pkt_len < IEEE_8023_MIN_FRAME)
248 pkt_len = IEEE_8023_MIN_FRAME;
249
250 start_page = dp->tx_next;
251 if (dp->tx_next == dp->tx_buf1) {
252 dp->tx1 = start_page;
253 dp->tx1_len = pkt_len;
254 dp->tx1_key = key;
255 dp->tx_next = dp->tx_buf2;
256 } else {
257 dp->tx2 = start_page;
258 dp->tx2_len = pkt_len;
259 dp->tx2_key = key;
260 dp->tx_next = dp->tx_buf1;
261 }
262
263#if DEBUG & 5
264 printf("TX prep page %d len %d\n", start_page, pkt_len);
265#endif
266
267 DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */
268 {
269 /*
270 * Dummy read. The manual sez something slightly different,
271 * but the code is extended a bit to do what Hitachi's monitor
272 * does (i.e., also read data).
273 */
274
275 u16 tmp;
276 int len = 1;
277
278 DP_OUT(base, DP_RSAL, 0x100 - len);
279 DP_OUT(base, DP_RSAH, (start_page - 1) & 0xff);
280 DP_OUT(base, DP_RBCL, len);
281 DP_OUT(base, DP_RBCH, 0);
282 DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_RDMA | DP_CR_START);
283 DP_IN_DATA(dp->data, tmp);
284 }
285
286#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_TX_DMA
287 /*
288 * Stall for a bit before continuing to work around random data
289 * corruption problems on some platforms.
290 */
291 CYGACC_CALL_IF_DELAY_US(1);
292#endif
293
294 /* Send data to device buffer(s) */
295 DP_OUT(base, DP_RSAL, 0);
296 DP_OUT(base, DP_RSAH, start_page);
297 DP_OUT(base, DP_RBCL, pkt_len & 0xFF);
298 DP_OUT(base, DP_RBCH, pkt_len >> 8);
299 DP_OUT(base, DP_CR, DP_CR_WDMA | DP_CR_START);
300
301 /* Put data into buffer */
302#if DEBUG & 4
303 printf(" sg buf %08lx len %08x\n ", (u32)data, len);
304 dx = 0;
305#endif
306 while (len > 0) {
307#if DEBUG & 4
308 printf(" %02x", *data);
309 if (0 == (++dx % 16)) printf("\n ");
310#endif
311
312 DP_OUT_DATA(dp->data, *data++);
313 len--;
314 }
315#if DEBUG & 4
316 printf("\n");
317#endif
318 if (total_len < pkt_len) {
319#if DEBUG & 4
320 printf(" + %d bytes of padding\n", pkt_len - total_len);
321#endif
322 /* Padding to 802.3 length was required */
323 for (i = total_len; i < pkt_len;) {
324 i++;
325 DP_OUT_DATA(dp->data, 0);
326 }
327 }
328
329#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_TX_DMA
330 /*
331 * After last data write, delay for a bit before accessing the
332 * device again, or we may get random data corruption in the last
333 * datum (on some platforms).
334 */
335 CYGACC_CALL_IF_DELAY_US(1);
336#endif
337
338 /* Wait for DMA to complete */
339 do {
340 DP_IN(base, DP_ISR, isr);
341 } while ((isr & DP_ISR_RDC) == 0);
342
343 /* Then disable DMA */
344 DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
345
346 /* Start transmit if not already going */
347 if (!dp->tx_started) {
348 if (start_page == dp->tx1) {
349 dp->tx_int = 1; /* Expecting interrupt from BUF1 */
350 } else {
351 dp->tx_int = 2; /* Expecting interrupt from BUF2 */
352 }
353 dp83902a_start_xmit(start_page, pkt_len);
354 }
355}
356
357/*
358 * This function is called when a packet has been received. It's job is
359 * to prepare to unload the packet from the hardware. Once the length of
360 * the packet is known, the upper layer of the driver can be told. When
361 * the upper layer is ready to unload the packet, the internal function
362 * 'dp83902a_recv' will be called to actually fetch it from the hardware.
363 */
364static void
365dp83902a_RxEvent(void)
366{
367 struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic;
368 u8 *base = dp->base;
369 u8 rsr;
370 u8 rcv_hdr[4];
371 int i, len, pkt, cur;
372
373 DEBUG_FUNCTION();
374
375 DP_IN(base, DP_RSR, rsr);
376 while (true) {
377 /* Read incoming packet header */
378 DP_OUT(base, DP_CR, DP_CR_PAGE1 | DP_CR_NODMA | DP_CR_START);
379 DP_IN(base, DP_P1_CURP, cur);
380 DP_OUT(base, DP_P1_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
381 DP_IN(base, DP_BNDRY, pkt);
382
383 pkt += 1;
384 if (pkt == dp->rx_buf_end)
385 pkt = dp->rx_buf_start;
386
387 if (pkt == cur) {
388 break;
389 }
390 DP_OUT(base, DP_RBCL, sizeof(rcv_hdr));
391 DP_OUT(base, DP_RBCH, 0);
392 DP_OUT(base, DP_RSAL, 0);
393 DP_OUT(base, DP_RSAH, pkt);
394 if (dp->rx_next == pkt) {
395 if (cur == dp->rx_buf_start)
396 DP_OUT(base, DP_BNDRY, dp->rx_buf_end - 1);
397 else
398 DP_OUT(base, DP_BNDRY, cur - 1); /* Update pointer */
399 return;
400 }
401 dp->rx_next = pkt;
402 DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */
403 DP_OUT(base, DP_CR, DP_CR_RDMA | DP_CR_START);
404#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_RX_DMA
405 CYGACC_CALL_IF_DELAY_US(10);
406#endif
407
408 /* read header (get data size)*/
409 for (i = 0; i < sizeof(rcv_hdr);) {
410 DP_IN_DATA(dp->data, rcv_hdr[i++]);
411 }
412
413#if DEBUG & 5
414 printf("rx hdr %02x %02x %02x %02x\n",
415 rcv_hdr[0], rcv_hdr[1], rcv_hdr[2], rcv_hdr[3]);
416#endif
417 len = ((rcv_hdr[3] << 8) | rcv_hdr[2]) - sizeof(rcv_hdr);
418
419 /* data read */
420 uboot_push_packet_len(len);
421
422 if (rcv_hdr[1] == dp->rx_buf_start)
423 DP_OUT(base, DP_BNDRY, dp->rx_buf_end - 1);
424 else
425 DP_OUT(base, DP_BNDRY, rcv_hdr[1] - 1); /* Update pointer */
426 }
427}
428
429/*
430 * This function is called as a result of the "eth_drv_recv()" call above.
431 * It's job is to actually fetch data for a packet from the hardware once
432 * memory buffers have been allocated for the packet. Note that the buffers
433 * may come in pieces, using a scatter-gather list. This allows for more
434 * efficient processing in the upper layers of the stack.
435 */
436static void
437dp83902a_recv(u8 *data, int len)
438{
439 struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic;
440 u8 *base = dp->base;
441 int i, mlen;
442 u8 saved_char = 0;
443 bool saved;
444#if DEBUG & 4
445 int dx;
446#endif
447
448 DEBUG_FUNCTION();
449
450#if DEBUG & 5
451 printf("Rx packet %d length %d\n", dp->rx_next, len);
452#endif
453
454 /* Read incoming packet data */
455 DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
456 DP_OUT(base, DP_RBCL, len & 0xFF);
457 DP_OUT(base, DP_RBCH, len >> 8);
458 DP_OUT(base, DP_RSAL, 4); /* Past header */
459 DP_OUT(base, DP_RSAH, dp->rx_next);
460 DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */
461 DP_OUT(base, DP_CR, DP_CR_RDMA | DP_CR_START);
462#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_RX_DMA
463 CYGACC_CALL_IF_DELAY_US(10);
464#endif
465
466 saved = false;
467 for (i = 0; i < 1; i++) {
468 if (data) {
469 mlen = len;
470#if DEBUG & 4
471 printf(" sg buf %08lx len %08x \n", (u32) data, mlen);
472 dx = 0;
473#endif
474 while (0 < mlen) {
475 /* Saved byte from previous loop? */
476 if (saved) {
477 *data++ = saved_char;
478 mlen--;
479 saved = false;
480 continue;
481 }
482
483 {
484 u8 tmp;
485 DP_IN_DATA(dp->data, tmp);
486#if DEBUG & 4
487 printf(" %02x", tmp);
488 if (0 == (++dx % 16)) printf("\n ");
489#endif
490 *data++ = tmp;;
491 mlen--;
492 }
493 }
494#if DEBUG & 4
495 printf("\n");
496#endif
497 }
498 }
499}
500
501static void
502dp83902a_TxEvent(void)
503{
504 struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic;
505 u8 *base = dp->base;
506 u8 tsr;
507 u32 key;
508
509 DEBUG_FUNCTION();
510
511 DP_IN(base, DP_TSR, tsr);
512 if (dp->tx_int == 1) {
513 key = dp->tx1_key;
514 dp->tx1 = 0;
515 } else {
516 key = dp->tx2_key;
517 dp->tx2 = 0;
518 }
519 /* Start next packet if one is ready */
520 dp->tx_started = false;
521 if (dp->tx1) {
522 dp83902a_start_xmit(dp->tx1, dp->tx1_len);
523 dp->tx_int = 1;
524 } else if (dp->tx2) {
525 dp83902a_start_xmit(dp->tx2, dp->tx2_len);
526 dp->tx_int = 2;
527 } else {
528 dp->tx_int = 0;
529 }
530 /* Tell higher level we sent this packet */
531 uboot_push_tx_done(key, 0);
532}
533
534/*
535 * Read the tally counters to clear them. Called in response to a CNT
536 * interrupt.
537 */
538static void
539dp83902a_ClearCounters(void)
540{
541 struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic;
542 u8 *base = dp->base;
543 u8 cnt1, cnt2, cnt3;
544
545 DP_IN(base, DP_FER, cnt1);
546 DP_IN(base, DP_CER, cnt2);
547 DP_IN(base, DP_MISSED, cnt3);
548 DP_OUT(base, DP_ISR, DP_ISR_CNT);
549}
550
551/*
552 * Deal with an overflow condition. This code follows the procedure set
553 * out in section 7.0 of the datasheet.
554 */
555static void
556dp83902a_Overflow(void)
557{
558 struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *)&nic;
559 u8 *base = dp->base;
560 u8 isr;
561
562 /* Issue a stop command and wait 1.6ms for it to complete. */
563 DP_OUT(base, DP_CR, DP_CR_STOP | DP_CR_NODMA);
564 CYGACC_CALL_IF_DELAY_US(1600);
565
566 /* Clear the remote byte counter registers. */
567 DP_OUT(base, DP_RBCL, 0);
568 DP_OUT(base, DP_RBCH, 0);
569
570 /* Enter loopback mode while we clear the buffer. */
571 DP_OUT(base, DP_TCR, DP_TCR_LOCAL);
572 DP_OUT(base, DP_CR, DP_CR_START | DP_CR_NODMA);
573
574 /*
575 * Read in as many packets as we can and acknowledge any and receive
576 * interrupts. Since the buffer has overflowed, a receive event of
577 * some kind will have occured.
578 */
579 dp83902a_RxEvent();
580 DP_OUT(base, DP_ISR, DP_ISR_RxP|DP_ISR_RxE);
581
582 /* Clear the overflow condition and leave loopback mode. */
583 DP_OUT(base, DP_ISR, DP_ISR_OFLW);
584 DP_OUT(base, DP_TCR, DP_TCR_NORMAL);
585
586 /*
587 * If a transmit command was issued, but no transmit event has occured,
588 * restart it here.
589 */
590 DP_IN(base, DP_ISR, isr);
591 if (dp->tx_started && !(isr & (DP_ISR_TxP|DP_ISR_TxE))) {
592 DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_TXPKT | DP_CR_START);
593 }
594}
595
596static void
597dp83902a_poll(void)
598{
599 struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic;
600 u8 *base = dp->base;
601 u8 isr;
602
603 DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE0 | DP_CR_START);
604 DP_IN(base, DP_ISR, isr);
605 while (0 != isr) {
606 /*
607 * The CNT interrupt triggers when the MSB of one of the error
608 * counters is set. We don't much care about these counters, but
609 * we should read their values to reset them.
610 */
611 if (isr & DP_ISR_CNT) {
612 dp83902a_ClearCounters();
613 }
614 /*
615 * Check for overflow. It's a special case, since there's a
616 * particular procedure that must be followed to get back into
617 * a running state.a
618 */
619 if (isr & DP_ISR_OFLW) {
620 dp83902a_Overflow();
621 } else {
622 /*
623 * Other kinds of interrupts can be acknowledged simply by
624 * clearing the relevant bits of the ISR. Do that now, then
625 * handle the interrupts we care about.
626 */
627 DP_OUT(base, DP_ISR, isr); /* Clear set bits */
628 if (!dp->running) break; /* Is this necessary? */
629 /*
630 * Check for tx_started on TX event since these may happen
631 * spuriously it seems.
632 */
633 if (isr & (DP_ISR_TxP|DP_ISR_TxE) && dp->tx_started) {
634 dp83902a_TxEvent();
635 }
636 if (isr & (DP_ISR_RxP|DP_ISR_RxE)) {
637 dp83902a_RxEvent();
638 }
639 }
640 DP_IN(base, DP_ISR, isr);
641 }
642}
643
644
645/* U-boot specific routines */
646static u8 *pbuf = NULL;
647
648static int pkey = -1;
649static int initialized = 0;
650
651void uboot_push_packet_len(int len) {
652 PRINTK("pushed len = %d\n", len);
653 if (len >= 2000) {
654 printf("NE2000: packet too big\n");
655 return;
656 }
657 dp83902a_recv(&pbuf[0], len);
658
659 /*Just pass it to the upper layer*/
660 NetReceive(&pbuf[0], len);
661}
662
663void uboot_push_tx_done(int key, int val) {
664 PRINTK("pushed key = %d\n", key);
665 pkey = key;
666}
667
668int eth_init(bd_t *bd) {
669 int r;
670 u8 dev_addr[6];
671 char ethaddr[20];
672
673 PRINTK("### eth_init\n");
674
675 if (!pbuf) {
676 pbuf = malloc(2000);
677 if (!pbuf) {
678 printf("Cannot allocate rx buffer\n");
679 return -1;
680 }
681 }
682
683#ifdef CONFIG_DRIVER_NE2000_CCR
684 {
685 vu_char *p = (vu_char *) CONFIG_DRIVER_NE2000_CCR;
686
687 PRINTK("CCR before is %x\n", *p);
688 *p = CONFIG_DRIVER_NE2000_VAL;
689 PRINTK("CCR after is %x\n", *p);
690 }
691#endif
692
693 nic.base = (u8 *) CONFIG_DRIVER_NE2000_BASE;
694
695 r = get_prom(dev_addr, nic.base);
696 if (!r)
697 return -1;
698
699 sprintf (ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X",
700 dev_addr[0], dev_addr[1],
701 dev_addr[2], dev_addr[3],
702 dev_addr[4], dev_addr[5]) ;
703 PRINTK("Set environment from HW MAC addr = \"%s\"\n", ethaddr);
704 setenv ("ethaddr", ethaddr);
705
706 nic.data = nic.base + DP_DATA;
707 nic.tx_buf1 = START_PG;
708 nic.tx_buf2 = START_PG2;
709 nic.rx_buf_start = RX_START;
710 nic.rx_buf_end = RX_END;
711
712 if (dp83902a_init() == false)
713 return -1;
714
715 dp83902a_start(dev_addr);
716 initialized = 1;
717
718 return 0;
719}
720
721void eth_halt() {
722
723 PRINTK("### eth_halt\n");
724 if(initialized)
725 dp83902a_stop();
726 initialized = 0;
727}
728
729int eth_rx() {
730 dp83902a_poll();
731 return 1;
732}
733
734int eth_send(volatile void *packet, int length) {
735 int tmo;
736
737 PRINTK("### eth_send\n");
738
739 pkey = -1;
740
741 dp83902a_send((u8 *) packet, length, 666);
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200742 tmo = get_timer (0) + TOUT * CONFIG_SYS_HZ;
Nobuhiro Iwamatsu702c85b2008-09-30 15:02:53 +0900743 while(1) {
744 dp83902a_poll();
745 if (pkey != -1) {
746 PRINTK("Packet sucesfully sent\n");
747 return 0;
748 }
749 if (get_timer (0) >= tmo) {
750 printf("transmission error (timoeut)\n");
751 return 0;
752 }
753
754 }
755 return 0;
756}