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