xref: /rk3399_rockchip-uboot/drivers/net/ne2000.c (revision e0a6140dd381e1eed1ada2291166ef2616d8822b)
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 }
852