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