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