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