📄 if_dm9000.c
字号:
435 {
436 struct eth_drv_sc *sc;
437 struct dm9000 *priv;
438 int i;
439 unsigned id;
440 unsigned short u16tab[64];
441
442 sc = (struct eth_drv_sc *)ndp->device_instance;
443 priv = (struct dm9000 *)sc->driver_private;
444
445 priv->sc = sc;
446
447 #ifdef CYG_HAL_DM9000_PRESENT
448 if (!CYG_HAL_DM9000_PRESENT())
449 return 0;
450 #endif
451
452 id = getreg(priv, DM_VIDL);
453 id |= getreg(priv, DM_VIDH) << 8;
454 id |= getreg(priv, DM_PIDL) << 16;
455 id |= getreg(priv, DM_PIDH) << 24;
456
457 if (id != 0x90000A46)
458 return 0;
459
460 for (i = 0; i < 64; i++)
461 u16tab[i] = eeprom_read(priv, i);
462
463 u16tab[3] &= ~0xc;
464 u16tab[3] |= 4;
465 u16tab[6] &= 0xfe00;
466 u16tab[6] |= 6;
467
468 #if 0
469 eeprom_write(priv, 6, u16tab[6]);
470 eeprom_write(priv, 3, u16tab[3]);
471 #endif
472
473 eeprom_reload(priv);
474
475 do {
476 for (i = 0; i < 64; i++)
477 u16tab[i] = eeprom_read(priv, i);
478 } while ((u16tab[0] | u16tab[1] | u16tab[2]) == 0);
479
480 priv->mac_address[0] = u16tab[0];
481 priv->mac_address[1] = u16tab[0] >> 8;
482 priv->mac_address[2] = u16tab[1];
483 priv->mac_address[3] = u16tab[1] >> 8;
484 priv->mac_address[4] = u16tab[2];
485 priv->mac_address[5] = u16tab[2] >> 8;
486
487 if (!initialize_nic(priv))
488 return 0;
489
490 // Initialize upper level driver
491 (sc->funs->eth_drv->init)(sc, &(priv->mac_address[0]) );
492 return 1;
493 }
494
495 // ------------------------------------------------------------------------
496 //
497 // API Function : dm9000_start
498 //
499 // ------------------------------------------------------------------------
500 static void
501 dm9000_start( struct eth_drv_sc *sc, unsigned char *enaddr, int flags )
502 {
503 struct dm9000 *priv = (struct dm9000 *)sc->driver_private;
504
505 // turn on receiver
506 putreg(priv, DM_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
507
508 // unmask interrupt
509 putreg(priv, DM_IMR, IMR_PAR | IMR_PTM | IMR_PRM);
510
511 priv->active = 1;
512 }
513
514 // ------------------------------------------------------------------------
515 //
516 // API Function : dm9000_stop
517 //
518 // ------------------------------------------------------------------------
519 static void
520 dm9000_stop( struct eth_drv_sc *sc )
521 {
522 struct dm9000 *priv = (struct dm9000 *)sc->driver_private;
523
524 // turn on receiver
525 putreg(priv, DM_RCR, 0);
526
527 // mask interrupts
528 putreg(priv, DM_IMR, IMR_PAR);
529
530 priv->active = 0;
531 }
532
533
534 // ------------------------------------------------------------------------
535 //
536 // API Function : dm9000_recv
537 //
538 // ------------------------------------------------------------------------
539 static void
540 dm9000_recv( struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len )
541 {
542 struct dm9000 *priv = (struct dm9000 *)sc->driver_private;
543 struct eth_drv_sg *sg = sg_list;
544 cyg_uint8 tmpbuf[4];
545 char *p;
546 int len, total_len, nread, n, leftover;
547
548 total_len = priv->rxlen;
549 nread = leftover = 0;
550
551 // diag_printf("dm9000_recv: total_len=%d\n", total_len);
552
553 do {
554 p = (char *)sg->buf;
555 len = sg->len;
556
557 // diag_printf("recv: buf=%p len=%d to_read=%d, leftover=%d\n", p, len, total_len - nread, leftover);
558
559 if ((nread + len) > total_len)
560 len = total_len - nread;
561
562 if (leftover) {
563 if (leftover <= len) {
564 memcpy(p, tmpbuf + (sizeof(tmpbuf) - leftover), leftover);
565 p += leftover;
566 len -= leftover;
567 nread += leftover;
568 leftover = 0;
569 } else {
570 memcpy(p, tmpbuf + (sizeof(tmpbuf) - leftover), len);
571 leftover -= len;
572 p += len;
573 nread += len;
574 len = 0;
575 }
576 }
577
578 while (len >= sizeof(tmpbuf)) {
579 n = priv->read_data(priv, p);
580 nread += n;
581 len -= n;
582 p += n;
583 }
584
585 while (len > 0) {
586 n = priv->read_data(priv, tmpbuf);
587 if (n <= len) {
588 memcpy(p, tmpbuf, n);
589 len -= n;
590 nread += n;
591 p += n;
592 } else {
593 memcpy(p, tmpbuf, len);
594 nread += len;
595 leftover = n - len;
596 len = 0;
597 }
598 }
599
600 ++sg;
601 } while (nread < total_len);
602
603 #if 0
604 // dump packet
605 for (sg = sg_list; sg < (sg_list + sg_len); sg++) {
606 diag_printf("\n");
607 diag_dump_buf(sg->buf, sg->len);
608 }
609 #endif
610 }
611
612 // ------------------------------------------------------------------------
613 //
614 // API Function : dm9000_can_send
615 //
616 // ------------------------------------------------------------------------
617 static int
618 dm9000_can_send(struct eth_drv_sc *sc)
619 {
620 struct dm9000 *priv = (struct dm9000 *)sc->driver_private;
621
622 if (!priv->active || priv->txbusy || priv->reset_pending)
623 return 0;
624
625 return 1;
626 }
627
628
629 // ------------------------------------------------------------------------
630 //
631 // API Function : dm9000_send
632 //
633 // ------------------------------------------------------------------------
634 static void
635 dm9000_send(struct eth_drv_sc *sc,
636 struct eth_drv_sg *sg_list, int sg_len,
637 int total_len, unsigned long key)
638 {
639 struct dm9000 *priv = (struct dm9000 *)sc->driver_private;
640 struct eth_drv_sg *sg = sg_list;
641 cyg_uint8 tmpbuf[4];
642 int i, len, extra, n, save_len;
643 char *p;
644
645 if (0) {
646 diag_printf("dm9000_send: NCR[%02x] NSR[%02x] TPL[%02x]\n",
647 getreg(priv, DM_NCR), getreg(priv, DM_NSR),
648 getreg(priv, DM_TRPAL) | (getreg(priv, DM_TRPAH) << 8)
649 );
650 }
651
652 priv->txbusy = 1;
653
654 save_len = total_len;
655 extra = 0;
656
657 HAL_WRITE_UINT8(priv->io_addr, DM_MWCMD);
658
659 while (total_len > 0) {
660 len = sg->len;
661 if (len > total_len)
662 len = total_len;
663 p = (char *)sg->buf;
664
665 if (extra) {
666 n = sizeof(tmpbuf) - extra;
667 memcpy(tmpbuf + extra, p, n);
668 p += n;
669 len -= n;
670 for (i = 0; i < sizeof(tmpbuf) && total_len > 0; i += n) {
671 n = priv->write_data(priv, tmpbuf + i);
672 total_len -= n;
673 }
674 extra = 0;
675 }
676
677 while (len >= sizeof(tmpbuf) && total_len > 0) {
678 n = priv->write_data(priv, p);
679 len -= n;
680 total_len -= n;
681 p += n;
682 }
683
684 if (len > 0 && total_len > 0) {
685 extra = len;
686 memcpy(tmpbuf, p, extra);
687
688 if ((total_len - extra) <= 0) {
689 // go ahead and write it now
690 for (i = 0; total_len > 0; i += n, total_len -= n) {
691 n = priv->write_data(priv, tmpbuf + i);
692 total_len = 0;
693 }
694 break;
695 }
696 }
697 sg++;
698 }
699
700 priv->txkey = key;
701
702 putreg(priv, DM_TXPLL, save_len);
703 putreg(priv, DM_TXPLH, save_len >> 8);
704
705 putreg(priv, DM_TCR, TCR_TXREQ);
706
707 return;
708 }
709
710 // ------------------------------------------------------------------------
711 //
712 // API Function : dm9000_poll
713 //
714 // ------------------------------------------------------------------------
715 static void
716 dm9000_poll(struct eth_drv_sc *sc)
717 {
718 struct dm9000 *priv = (struct dm9000 *)sc->driver_private;
719 cyg_uint8 status, rxstat, rx1;
720 cyg_uint16 pkt_stat, pkt_len;
721 int i;
722
723 // mask interrupts
724 putreg(priv, DM_IMR, IMR_PAR);
725
726 // get and clear staus
727 status = getreg(priv, DM_ISR);
728 putreg(priv, DM_ISR, status);
729
730 // check for rx done
731 if (1 /*status & ISR_PRS*/) {
732
733 rx1 = getreg(priv, DM_MRCMDX);
734 HAL_READ_UINT8(priv->io_data, rxstat);
735
736 // check for packet ready
737 if (rxstat == 1) {
738 cyg_uint16 u16[2];
739 cyg_uint8 *cp;
740
741 HAL_WRITE_UINT8(priv->io_addr, DM_MRCMD);
742 for (i = 0, cp = (cyg_uint8 *)u16; i < 4; )
743 i += priv->read_data(priv, cp + i);
744
745 u16[0] = CYG_LE16_TO_CPU(u16[0]);
746 u16[1] = CYG_LE16_TO_CPU(u16[1]);
747
748 #if (CYG_BYTEORDER == CYG_MSBFIRST)
749 pkt_stat = u16[0];
750 pkt_len = u16[1];
751 #else
752 pkt_stat = u16[1];
753 pkt_len = u16[0];
754 #endif
755
756 #ifdef DEBUG
757 diag_printf("pkt_stat=%04x pkt_len=%04x\n", pkt_stat, pkt_len);
758 #endif
759
760 if (pkt_len < 0x40) {
761 diag_printf("packet too short: %d (0x%04x)\n", pkt_len, pkt_len);
762 i = 0;
763 while (i < pkt_len)
764 i += priv->read_data(priv, cp);
765 } else if (pkt_len > 1536) {
766 priv->reset_pending = 1;
767 diag_printf("packet too long: %d (0x%04x)\n", pkt_len, pkt_len);
768 } else if (pkt_stat & 0xbf00) {
769 diag_printf("bad packet status: 0x%04x\n", pkt_stat);
770 i = 0;
771 while (i < pkt_len)
772 i += priv->read_data(priv, cp);
773 } else {
774 // receive packet
775 priv->rxlen = pkt_len;
776 (sc->funs->eth_drv->recv)(sc, pkt_len);
777 }
778
779 } else if (rxstat > 1) {
780 // this should never happen.
781 diag_printf("unknown rxstat byte: %d\n", rxstat);
782 priv->reset_pending = 1;
783 }
784 }
785
786
787 // check transmit status
788 if (status & ISR_PTS) {
789 cyg_uint8 txstat;
790
791 txstat = getreg(priv, DM_NSR);
792
793 if (txstat & (NSR_TX1END | NSR_TX2END)) {
794 if (txstat & NSR_TX1END)
795 txstat = getreg(priv, DM_TSRI);
796 else
797 txstat = getreg(priv, DM_TSRII);
798
799 if (txstat & TSR_COL) {
800 // collision
801 }
802
803 if (getreg(priv, DM_TRPAL) & 3) {
804 // NIC bug detected. Need to reset.
805 priv->reset_pending = 1;
806 diag_printf("NIC collision bug detected!\n");
807 }
808
809 (sc->funs->eth_drv->tx_done)(sc, priv->txkey, 0);
810 priv->txbusy = 0;
811 }
812 }
813
814 if (priv->reset_pending && !priv->txbusy) {
815 initialize_nic(priv);
816
817 // turn on receiver
818 putreg(priv, DM_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
819
820 priv->reset_pending = 0;
821 }
822
823 // unmask interrupts
824 putreg(priv, DM_IMR, IMR_PAR | IMR_PTM | IMR_PRM);
825 }
826
827
828 // ------------------------------------------------------------------------
829 //
830 // API Function : dm9000_deliver
831 //
832 // ------------------------------------------------------------------------
833 static void
834 dm9000_deliver(struct eth_drv_sc *sc)
835 {
836 dm9000_poll(sc);
837 }
838
839 // ------------------------------------------------------------------------
840 //
841 // API Function : dm9000_int_vector
842 //
843 // ------------------------------------------------------------------------
844 static int
845 dm9000_int_vector(struct eth_drv_sc *sc)
846 {
847 struct dm9000 *priv;
848 priv = (struct dm9000 *)sc->driver_private;
849
850 return -1;
851 }
852
853
854 // ------------------------------------------------------------------------
855 //
856 // API Function : dm9000_ioctl
857 //
858 // ------------------------------------------------------------------------
859 static int
860 dm9000_ioctl(struct eth_drv_sc *sc, unsigned long key,
861 void *data, int data_length)
862 {
863 return -1;
864 }
865
866 // ------------------------------------------------------------------------
867 // EOF if_dm9000.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -