1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
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
82void uboot_push_packet_len(int len);
83void uboot_push_tx_done(int key, int val);
84
85
86#include "ne2000_base.h"
87
88#if defined(CONFIG_DRIVER_AX88796L)
89
90#include "ax88796.h"
91#else
92
93#include "ne2000.h"
94#endif
95
96static dp83902a_priv_data_t nic;
97
98static bool
99dp83902a_init(void)
100{
101 dp83902a_priv_data_t *dp = &nic;
102 u8* base;
103#if defined(NE2000_BASIC_INIT)
104 int i;
105#endif
106
107 DEBUG_FUNCTION();
108
109 base = dp->base;
110 if (!base)
111 return false;
112
113 DEBUG_LINE();
114
115#if defined(NE2000_BASIC_INIT)
116
117
118 DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE1);
119
120 for (i = 0; i < 6; i++)
121 DP_IN(base, DP_P1_PAR0+i, dp->esa[i]);
122 DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE0);
123
124 printf("NE2000 - %s ESA: %02x:%02x:%02x:%02x:%02x:%02x\n",
125 "eeprom",
126 dp->esa[0],
127 dp->esa[1],
128 dp->esa[2],
129 dp->esa[3],
130 dp->esa[4],
131 dp->esa[5] );
132
133#endif
134 return true;
135}
136
137static void
138dp83902a_stop(void)
139{
140 dp83902a_priv_data_t *dp = &nic;
141 u8 *base = dp->base;
142
143 DEBUG_FUNCTION();
144
145 DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP);
146 DP_OUT(base, DP_ISR, 0xFF);
147 DP_OUT(base, DP_IMR, 0x00);
148
149 dp->running = false;
150}
151
152
153
154
155
156
157
158static void
159dp83902a_start(u8 * enaddr)
160{
161 dp83902a_priv_data_t *dp = &nic;
162 u8 *base = dp->base;
163 int i;
164
165 DEBUG_FUNCTION();
166
167 DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP);
168 DP_OUT(base, DP_DCR, DP_DCR_INIT);
169 DP_OUT(base, DP_RBCH, 0);
170 DP_OUT(base, DP_RBCL, 0);
171 DP_OUT(base, DP_RCR, DP_RCR_MON);
172 DP_OUT(base, DP_TCR, DP_TCR_LOCAL);
173 DP_OUT(base, DP_TPSR, dp->tx_buf1);
174 dp->tx1 = dp->tx2 = 0;
175 dp->tx_next = dp->tx_buf1;
176 dp->tx_started = false;
177 dp->running = true;
178 DP_OUT(base, DP_PSTART, dp->rx_buf_start);
179 DP_OUT(base, DP_BNDRY, dp->rx_buf_end - 1);
180 DP_OUT(base, DP_PSTOP, dp->rx_buf_end);
181 dp->rx_next = dp->rx_buf_start - 1;
182 dp->running = true;
183 DP_OUT(base, DP_ISR, 0xFF);
184 DP_OUT(base, DP_IMR, DP_IMR_All);
185 DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE1 | DP_CR_STOP);
186 DP_OUT(base, DP_P1_CURP, dp->rx_buf_start);
187 dp->running = true;
188 for (i = 0; i < ETHER_ADDR_LEN; i++) {
189
190
191
192 DP_OUT(base, DP_P1_PAR0+i, enaddr[i]);
193 }
194
195 DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
196 DP_OUT(base, DP_TCR, DP_TCR_NORMAL);
197 DP_OUT(base, DP_RCR, DP_RCR_AB);
198 dp->running = true;
199}
200
201
202
203
204
205
206
207static void
208dp83902a_start_xmit(int start_page, int len)
209{
210 dp83902a_priv_data_t *dp = (dp83902a_priv_data_t *) &nic;
211 u8 *base = dp->base;
212
213 DEBUG_FUNCTION();
214
215#if DEBUG & 1
216 printf("Tx pkt %d len %d\n", start_page, len);
217 if (dp->tx_started)
218 printf("TX already started?!?\n");
219#endif
220
221 DP_OUT(base, DP_ISR, (DP_ISR_TxP | DP_ISR_TxE));
222 DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
223 DP_OUT(base, DP_TBCL, len & 0xFF);
224 DP_OUT(base, DP_TBCH, len >> 8);
225 DP_OUT(base, DP_TPSR, start_page);
226 DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_TXPKT | DP_CR_START);
227
228 dp->tx_started = true;
229}
230
231
232
233
234
235static void
236dp83902a_send(u8 *data, int total_len, u32 key)
237{
238 struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic;
239 u8 *base = dp->base;
240 int len, start_page, pkt_len, i, isr;
241#if DEBUG & 4
242 int dx;
243#endif
244
245 DEBUG_FUNCTION();
246
247 len = pkt_len = total_len;
248 if (pkt_len < IEEE_8023_MIN_FRAME)
249 pkt_len = IEEE_8023_MIN_FRAME;
250
251 start_page = dp->tx_next;
252 if (dp->tx_next == dp->tx_buf1) {
253 dp->tx1 = start_page;
254 dp->tx1_len = pkt_len;
255 dp->tx1_key = key;
256 dp->tx_next = dp->tx_buf2;
257 } else {
258 dp->tx2 = start_page;
259 dp->tx2_len = pkt_len;
260 dp->tx2_key = key;
261 dp->tx_next = dp->tx_buf1;
262 }
263
264#if DEBUG & 5
265 printf("TX prep page %d len %d\n", start_page, pkt_len);
266#endif
267
268 DP_OUT(base, DP_ISR, DP_ISR_RDC);
269 {
270
271
272
273
274
275
276 u16 tmp;
277 int len = 1;
278
279 DP_OUT(base, DP_RSAL, 0x100 - len);
280 DP_OUT(base, DP_RSAH, (start_page - 1) & 0xff);
281 DP_OUT(base, DP_RBCL, len);
282 DP_OUT(base, DP_RBCH, 0);
283 DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_RDMA | DP_CR_START);
284 DP_IN_DATA(dp->data, tmp);
285 }
286
287#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_TX_DMA
288
289
290
291
292 CYGACC_CALL_IF_DELAY_US(1);
293#endif
294
295
296 DP_OUT(base, DP_RSAL, 0);
297 DP_OUT(base, DP_RSAH, start_page);
298 DP_OUT(base, DP_RBCL, pkt_len & 0xFF);
299 DP_OUT(base, DP_RBCH, pkt_len >> 8);
300 DP_OUT(base, DP_CR, DP_CR_WDMA | DP_CR_START);
301
302
303#if DEBUG & 4
304 printf(" sg buf %08lx len %08x\n ", (u32)data, len);
305 dx = 0;
306#endif
307 while (len > 0) {
308#if DEBUG & 4
309 printf(" %02x", *data);
310 if (0 == (++dx % 16)) printf("\n ");
311#endif
312
313 DP_OUT_DATA(dp->data, *data++);
314 len--;
315 }
316#if DEBUG & 4
317 printf("\n");
318#endif
319 if (total_len < pkt_len) {
320#if DEBUG & 4
321 printf(" + %d bytes of padding\n", pkt_len - total_len);
322#endif
323
324 for (i = total_len; i < pkt_len;) {
325 i++;
326 DP_OUT_DATA(dp->data, 0);
327 }
328 }
329
330#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_TX_DMA
331
332
333
334
335
336 CYGACC_CALL_IF_DELAY_US(1);
337#endif
338
339
340 do {
341 DP_IN(base, DP_ISR, isr);
342 } while ((isr & DP_ISR_RDC) == 0);
343
344
345 DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
346
347
348 if (!dp->tx_started) {
349 if (start_page == dp->tx1) {
350 dp->tx_int = 1;
351 } else {
352 dp->tx_int = 2;
353 }
354 dp83902a_start_xmit(start_page, pkt_len);
355 }
356}
357
358
359
360
361
362
363
364
365static void
366dp83902a_RxEvent(void)
367{
368 struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic;
369 u8 *base = dp->base;
370 u8 rsr;
371 u8 rcv_hdr[4];
372 int i, len, pkt, cur;
373
374 DEBUG_FUNCTION();
375
376 DP_IN(base, DP_RSR, rsr);
377 while (true) {
378
379 DP_OUT(base, DP_CR, DP_CR_PAGE1 | DP_CR_NODMA | DP_CR_START);
380 DP_IN(base, DP_P1_CURP, cur);
381 DP_OUT(base, DP_P1_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
382 DP_IN(base, DP_BNDRY, pkt);
383
384 pkt += 1;
385 if (pkt == dp->rx_buf_end)
386 pkt = dp->rx_buf_start;
387
388 if (pkt == cur) {
389 break;
390 }
391 DP_OUT(base, DP_RBCL, sizeof(rcv_hdr));
392 DP_OUT(base, DP_RBCH, 0);
393 DP_OUT(base, DP_RSAL, 0);
394 DP_OUT(base, DP_RSAH, pkt);
395 if (dp->rx_next == pkt) {
396 if (cur == dp->rx_buf_start)
397 DP_OUT(base, DP_BNDRY, dp->rx_buf_end - 1);
398 else
399 DP_OUT(base, DP_BNDRY, cur - 1);
400 return;
401 }
402 dp->rx_next = pkt;
403 DP_OUT(base, DP_ISR, DP_ISR_RDC);
404 DP_OUT(base, DP_CR, DP_CR_RDMA | DP_CR_START);
405#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_RX_DMA
406 CYGACC_CALL_IF_DELAY_US(10);
407#endif
408
409
410 for (i = 0; i < sizeof(rcv_hdr);) {
411 DP_IN_DATA(dp->data, rcv_hdr[i++]);
412 }
413
414#if DEBUG & 5
415 printf("rx hdr %02x %02x %02x %02x\n",
416 rcv_hdr[0], rcv_hdr[1], rcv_hdr[2], rcv_hdr[3]);
417#endif
418 len = ((rcv_hdr[3] << 8) | rcv_hdr[2]) - sizeof(rcv_hdr);
419
420
421 uboot_push_packet_len(len);
422
423 if (rcv_hdr[1] == dp->rx_buf_start)
424 DP_OUT(base, DP_BNDRY, dp->rx_buf_end - 1);
425 else
426 DP_OUT(base, DP_BNDRY, rcv_hdr[1] - 1);
427 }
428}
429
430
431
432
433
434
435
436
437static void
438dp83902a_recv(u8 *data, int len)
439{
440 struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic;
441 u8 *base = dp->base;
442 int i, mlen;
443 u8 saved_char = 0;
444 bool saved;
445#if DEBUG & 4
446 int dx;
447#endif
448
449 DEBUG_FUNCTION();
450
451#if DEBUG & 5
452 printf("Rx packet %d length %d\n", dp->rx_next, len);
453#endif
454
455
456 DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
457 DP_OUT(base, DP_RBCL, len & 0xFF);
458 DP_OUT(base, DP_RBCH, len >> 8);
459 DP_OUT(base, DP_RSAL, 4);
460 DP_OUT(base, DP_RSAH, dp->rx_next);
461 DP_OUT(base, DP_ISR, DP_ISR_RDC);
462 DP_OUT(base, DP_CR, DP_CR_RDMA | DP_CR_START);
463#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_RX_DMA
464 CYGACC_CALL_IF_DELAY_US(10);
465#endif
466
467 saved = false;
468 for (i = 0; i < 1; i++) {
469 if (data) {
470 mlen = len;
471#if DEBUG & 4
472 printf(" sg buf %08lx len %08x \n", (u32) data, mlen);
473 dx = 0;
474#endif
475 while (0 < mlen) {
476
477 if (saved) {
478 *data++ = saved_char;
479 mlen--;
480 saved = false;
481 continue;
482 }
483
484 {
485 u8 tmp;
486 DP_IN_DATA(dp->data, tmp);
487#if DEBUG & 4
488 printf(" %02x", tmp);
489 if (0 == (++dx % 16)) printf("\n ");
490#endif
491 *data++ = tmp;;
492 mlen--;
493 }
494 }
495#if DEBUG & 4
496 printf("\n");
497#endif
498 }
499 }
500}
501
502static void
503dp83902a_TxEvent(void)
504{
505 struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic;
506 u8 *base = dp->base;
507 u8 tsr;
508 u32 key;
509
510 DEBUG_FUNCTION();
511
512 DP_IN(base, DP_TSR, tsr);
513 if (dp->tx_int == 1) {
514 key = dp->tx1_key;
515 dp->tx1 = 0;
516 } else {
517 key = dp->tx2_key;
518 dp->tx2 = 0;
519 }
520
521 dp->tx_started = false;
522 if (dp->tx1) {
523 dp83902a_start_xmit(dp->tx1, dp->tx1_len);
524 dp->tx_int = 1;
525 } else if (dp->tx2) {
526 dp83902a_start_xmit(dp->tx2, dp->tx2_len);
527 dp->tx_int = 2;
528 } else {
529 dp->tx_int = 0;
530 }
531
532 uboot_push_tx_done(key, 0);
533}
534
535
536
537
538
539static void
540dp83902a_ClearCounters(void)
541{
542 struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic;
543 u8 *base = dp->base;
544 u8 cnt1, cnt2, cnt3;
545
546 DP_IN(base, DP_FER, cnt1);
547 DP_IN(base, DP_CER, cnt2);
548 DP_IN(base, DP_MISSED, cnt3);
549 DP_OUT(base, DP_ISR, DP_ISR_CNT);
550}
551
552
553
554
555
556static void
557dp83902a_Overflow(void)
558{
559 struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *)&nic;
560 u8 *base = dp->base;
561 u8 isr;
562
563
564 DP_OUT(base, DP_CR, DP_CR_STOP | DP_CR_NODMA);
565 CYGACC_CALL_IF_DELAY_US(1600);
566
567
568 DP_OUT(base, DP_RBCL, 0);
569 DP_OUT(base, DP_RBCH, 0);
570
571
572 DP_OUT(base, DP_TCR, DP_TCR_LOCAL);
573 DP_OUT(base, DP_CR, DP_CR_START | DP_CR_NODMA);
574
575
576
577
578
579
580 dp83902a_RxEvent();
581 DP_OUT(base, DP_ISR, DP_ISR_RxP|DP_ISR_RxE);
582
583
584 DP_OUT(base, DP_ISR, DP_ISR_OFLW);
585 DP_OUT(base, DP_TCR, DP_TCR_NORMAL);
586
587
588
589
590
591 DP_IN(base, DP_ISR, isr);
592 if (dp->tx_started && !(isr & (DP_ISR_TxP|DP_ISR_TxE))) {
593 DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_TXPKT | DP_CR_START);
594 }
595}
596
597static void
598dp83902a_poll(void)
599{
600 struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic;
601 u8 *base = dp->base;
602 u8 isr;
603
604 DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE0 | DP_CR_START);
605 DP_IN(base, DP_ISR, isr);
606 while (0 != isr) {
607
608
609
610
611
612 if (isr & DP_ISR_CNT) {
613 dp83902a_ClearCounters();
614 }
615
616
617
618
619
620 if (isr & DP_ISR_OFLW) {
621 dp83902a_Overflow();
622 } else {
623
624
625
626
627
628 DP_OUT(base, DP_ISR, isr);
629 if (!dp->running) break;
630
631
632
633
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
646
647static u8 *pbuf = NULL;
648
649static int pkey = -1;
650static int initialized = 0;
651
652void uboot_push_packet_len(int len) {
653 PRINTK("pushed len = %d\n", len);
654 if (len >= 2000) {
655 printf("NE2000: packet too big\n");
656 return;
657 }
658 dp83902a_recv(&pbuf[0], len);
659
660
661 NetReceive(&pbuf[0], len);
662}
663
664void uboot_push_tx_done(int key, int val) {
665 PRINTK("pushed key = %d\n", key);
666 pkey = key;
667}
668
669int eth_init(bd_t *bd) {
670 int r;
671 u8 dev_addr[6];
672 char ethaddr[20];
673
674 PRINTK("### eth_init\n");
675
676 if (!pbuf) {
677 pbuf = malloc(2000);
678 if (!pbuf) {
679 printf("Cannot allocate rx buffer\n");
680 return -1;
681 }
682 }
683
684#ifdef CONFIG_DRIVER_NE2000_CCR
685 {
686 vu_char *p = (vu_char *) CONFIG_DRIVER_NE2000_CCR;
687
688 PRINTK("CCR before is %x\n", *p);
689 *p = CONFIG_DRIVER_NE2000_VAL;
690 PRINTK("CCR after is %x\n", *p);
691 }
692#endif
693
694 nic.base = (u8 *) CONFIG_DRIVER_NE2000_BASE;
695
696 r = get_prom(dev_addr, nic.base);
697 if (!r)
698 return -1;
699
700 sprintf (ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X",
701 dev_addr[0], dev_addr[1],
702 dev_addr[2], dev_addr[3],
703 dev_addr[4], dev_addr[5]) ;
704 PRINTK("Set environment from HW MAC addr = \"%s\"\n", ethaddr);
705 setenv ("ethaddr", ethaddr);
706
707 nic.data = nic.base + DP_DATA;
708 nic.tx_buf1 = START_PG;
709 nic.tx_buf2 = START_PG2;
710 nic.rx_buf_start = RX_START;
711 nic.rx_buf_end = RX_END;
712
713 if (dp83902a_init() == false)
714 return -1;
715
716 dp83902a_start(dev_addr);
717 initialized = 1;
718
719 return 0;
720}
721
722void eth_halt() {
723
724 PRINTK("### eth_halt\n");
725 if(initialized)
726 dp83902a_stop();
727 initialized = 0;
728}
729
730int eth_rx() {
731 dp83902a_poll();
732 return 1;
733}
734
735int eth_send(volatile void *packet, int length) {
736 int tmo;
737
738 PRINTK("### eth_send\n");
739
740 pkey = -1;
741
742 dp83902a_send((u8 *) packet, length, 666);
743 tmo = get_timer (0) + TOUT * CONFIG_SYS_HZ;
744 while(1) {
745 dp83902a_poll();
746 if (pkey != -1) {
747 PRINTK("Packet sucesfully sent\n");
748 return 0;
749 }
750 if (get_timer (0) >= tmo) {
751 printf("transmission error (timoeut)\n");
752 return 0;
753 }
754
755 }
756 return 0;
757}
758