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