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