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