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