Changeset a19b915 in rtems
- Timestamp:
- 12/11/13 10:35:10 (10 years ago)
- Branches:
- 4.11, 5, master
- Children:
- 14e1c677
- Parents:
- 6eb1733
- git-author:
- Sebastian Huber <sebastian.huber@…> (12/11/13 10:35:10)
- git-committer:
- Sebastian Huber <sebastian.huber@…> (12/16/13 14:15:42)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
c/src/lib/libbsp/m68k/genmcf548x/network/network.c
r6eb1733 ra19b915 37 37 * 38 38 */ 39 39 40 #include <rtems.h> 40 41 #include <rtems/error.h> … … 60 61 #include <mcf548x/mcdma_glue.h> 61 62 62 #define ETH_PROMISCOUS_MODE 1 /* FIXME: remove me */63 64 63 /* 65 64 * Number of interfaces supported by this driver … … 68 67 69 68 #define FEC_WATCHDOG_TIMEOUT 5 /* check media every 5 seconds */ 70 /*71 * buffer descriptor handling72 */73 74 #define SET_BD_STATUS(bd, stat) { \75 (bd)->statCtrl = stat; \76 }77 #define SET_BD_LENGTH(bd, len) { \78 (bd)->length = len; \79 }80 #define SET_BD_BUFFER(bd, buf) { \81 (bd)->dataPointer= (uint32_t)(buf); \82 }83 #define GET_BD_STATUS(bd) ((bd)->statCtrl)84 #define GET_BD_LENGTH(bd) ((bd)->length)85 #define GET_BD_BUFFER(bd) ((void *)((bd)->dataPointer))86 69 87 70 #define DMA_BD_RX_NUM 32 /* Number of receive buffer descriptors */ 88 71 #define DMA_BD_TX_NUM 32 /* Number of transmit buffer descriptors */ 72 73 #define FEC_EVENT RTEMS_EVENT_0 89 74 90 75 /* … … 133 118 /(MCF548X_FEC1_IRQ_VECTOR \ 134 119 -MCF548X_FEC0_IRQ_VECTOR)) 135 136 #define FEC_RECV_TASK_NO 4137 #define FEC_XMIT_TASK_NO 5138 120 139 121 #define MCDMA_FEC_RX_CHAN(chan) (0 + NIFACES*(chan)) … … 150 132 +(chan)*(MCF548X_FEC1_TX_INITIATOR \ 151 133 -MCF548X_FEC0_TX_INITIATOR)) 152 153 /*154 * RTEMS event used by interrupt handler to signal daemons.155 * This must *not* be the same event used by the TCP/IP task synchronization.156 */157 #define INTERRUPT_EVENT RTEMS_EVENT_1158 #define FATAL_INT_EVENT RTEMS_EVENT_3159 160 /*161 * RTEMS event used to start transmit daemon.162 * This must not be the same as INTERRUPT_EVENT.163 */164 #define START_TRANSMIT_EVENT RTEMS_EVENT_2165 134 166 135 /* BD and parameters are stored in SRAM(refer to sdma.h) */ … … 199 168 MCF548X_FEC_EIMR_XFUN | MCF548X_FEC_EIMR_XFERR | MCF548X_FEC_EIMR_RFERR) 200 169 170 typedef enum { 171 FEC_STATE_RESTART_0, 172 FEC_STATE_RESTART_1, 173 FEC_STATE_NORMAL, 174 } fec_state; 175 201 176 /* 202 177 * Device data … … 207 182 struct mbuf **txMbuf; 208 183 int chan; 184 fec_state state; 209 185 int acceptBroadcast; 210 186 int rxBdCount; 211 187 int txBdCount; 212 int txBdHead;213 int txBdTail;214 int txBdActiveCount;215 188 MCD_bufDescFec *rxBd; 216 189 MCD_bufDescFec *txBd; … … 233 206 unsigned long rxNonOctet; 234 207 unsigned long rxBadCRC; 235 unsigned long rx Overrun;208 unsigned long rxFIFOError; 236 209 unsigned long rxCollision; 237 210 … … 240 213 unsigned long txLateCollision; 241 214 unsigned long txUnderrun; 215 unsigned long txFIFOError; 242 216 unsigned long txMisaligned; 243 217 unsigned long rxNotFirst; … … 247 221 static struct mcf548x_enet_struct enet_driver[NIFACES]; 248 222 249 extern int taskTable; 250 static void mcf548x_fec_restart(struct mcf548x_enet_struct *sc); 251 252 253 254 /* 255 * Function: mcf548x_fec_rx_bd_init 256 * 257 * Description: Initialize the receive buffer descriptor ring. 258 * 259 * Returns: void 260 * 261 * Notes: Space for the buffers of rx BDs is allocated by the rx deamon 262 * 263 */ 264 static void mcf548x_fec_rx_bd_init(struct mcf548x_enet_struct *sc) { 265 int rxBdIndex; 266 struct mbuf *m; 267 struct ifnet *ifp = &sc->arpcom.ac_if; 268 269 /* 270 * Fill RX buffer descriptor ring. 271 */ 272 for( rxBdIndex = 0; rxBdIndex < sc->rxBdCount; rxBdIndex++ ) { 273 MGETHDR (m, M_WAIT, MT_DATA); 274 MCLGET (m, M_WAIT); 275 276 m->m_pkthdr.rcvif = ifp; 277 sc->rxMbuf[rxBdIndex] = m; 278 rtems_cache_invalidate_multiple_data_lines(mtod(m,const void *), 279 ETHER_MAX_LEN); 280 SET_BD_BUFFER(sc->rxBd+rxBdIndex,mtod(m, void *)); 281 SET_BD_LENGTH(sc->rxBd+rxBdIndex,ETHER_MAX_LEN); 282 SET_BD_STATUS(sc->rxBd+rxBdIndex, 283 MCF548X_FEC_RBD_EMPTY 284 | MCF548X_FEC_RBD_INT 285 | ((rxBdIndex == sc->rxBdCount-1) 286 ? MCF548X_FEC_RBD_WRAP 287 : 0)); 288 } 289 } 290 291 /* 292 * Function: mcf548x_fec_rx_bd_cleanup 293 * 294 * Description: put all mbufs pending in rx BDs back to buffer pool 295 * 296 * Returns: void 297 * 298 */ 299 static void mcf548x_fec_rx_bd_cleanup(struct mcf548x_enet_struct *sc) { 300 int rxBdIndex; 301 struct mbuf *m,*n; 302 303 /* 304 * Drain RX buffer descriptor ring. 305 */ 306 for( rxBdIndex = 0; rxBdIndex < sc->rxBdCount; rxBdIndex++ ) { 307 n = sc->rxMbuf[rxBdIndex]; 308 while (n != NULL) { 309 m = n; 310 MFREE(m,n); 311 } 312 } 223 static void mcf548x_fec_restart(struct mcf548x_enet_struct *sc, rtems_id otherDaemon); 224 225 static void fec_send_event(rtems_id task) 226 { 227 rtems_bsdnet_event_send(task, FEC_EVENT); 228 } 229 230 static void fec_wait_for_event(void) 231 { 232 rtems_event_set out; 233 rtems_bsdnet_event_receive( 234 FEC_EVENT, 235 RTEMS_EVENT_ANY | RTEMS_WAIT, 236 RTEMS_NO_TIMEOUT, 237 &out 238 ); 239 } 240 241 static void mcf548x_fec_request_restart(struct mcf548x_enet_struct *sc) 242 { 243 sc->state = FEC_STATE_RESTART_0; 244 fec_send_event(sc->txDaemonTid); 245 fec_send_event(sc->rxDaemonTid); 313 246 } 314 247 … … 350 283 * as a shift-register with as many ex-ores as the radixes 351 284 * in the polynomium. This suggests that we represent the 352 * polynomiumm its elfas a 32-bit constant.285 * polynomiumm itsc as a 32-bit constant. 353 286 */ 354 287 for(byte = 0; byte < 6; byte++) … … 540 473 * 541 474 */ 542 static intmcf548x_fec_reset(struct mcf548x_enet_struct *sc) {475 static void mcf548x_fec_reset(struct mcf548x_enet_struct *sc) { 543 476 volatile int delay; 544 477 int chan = sc->chan; … … 567 500 */ 568 501 for (delay = 0;delay < 16*4;delay++) {}; 569 570 return true;571 502 } 572 503 … … 648 579 */ 649 580 MCF548X_FEC_ECR(chan) &= ~(MCF548X_FEC_ECR_ETHER_EN); 650 651 /* 652 * cleanup all buffers 653 */ 654 mcf548x_fec_rx_bd_cleanup(sc); 655 656 } 581 } 657 582 658 583 /* … … 683 608 } 684 609 if (ievent & MCF548X_FEC_EIR_XFERR) { 685 sc->tx Underrun++;610 sc->txFIFOError++; 686 611 } 687 612 if (ievent & MCF548X_FEC_EIR_RFERR) { 688 sc->rx Overrun++;613 sc->rxFIFOError++; 689 614 } 690 615 /* … … 693 618 if (ievent & (MCF548X_FEC_EIR_RFERR | MCF548X_FEC_EIR_XFERR)) { 694 619 MCF548X_FEC_EIMR(chan) &=~(MCF548X_FEC_EIMR_RFERR | MCF548X_FEC_EIMR_XFERR); 695 rtems_bsdnet_event_send(sc->rxDaemonTid, FATAL_INT_EVENT); 620 printk("fifo\n"); 621 mcf548x_fec_request_restart(sc); 696 622 } 697 623 } … … 709 635 mcdma_glue_irq_disable(sc->rxDmaChan);/*Disable receive ints*/ 710 636 sc->rxInterrupts++; /* Rx int has occurred */ 711 rtems_bsdnet_event_send(sc->rxDaemonTid, INTERRUPT_EVENT);637 fec_send_event(sc->rxDaemonTid); 712 638 } 713 639 } … … 729 655 sc->txInterrupts++; /* Tx int has occurred */ 730 656 731 rtems_bsdnet_event_send(sc->txDaemonTid, INTERRUPT_EVENT); 732 } 733 } 734 735 736 737 738 739 /* 740 * Function: mcf548x_fec_retire_tbd 741 * 742 * Description: Soak up buffer descriptors that have been sent. 743 * 744 * Returns: void 745 * 746 * Notes: 747 * 748 */ 749 static void mcf548x_fec_retire_tbd(struct mcf548x_enet_struct *sc, 750 bool force) 751 { 752 struct mbuf *n; 753 /* 754 * Clear already transmitted BDs first. Will not work calling same 755 * from fecExceptionHandler(TFINT). 756 */ 757 758 while ((sc->txBdActiveCount > 0) && 759 (force || 760 ((MCF548X_FEC_TBD_READY & GET_BD_STATUS(sc->txBd+sc->txBdTail)) 761 == 0x0))) { 762 if (sc->txMbuf[sc->txBdTail] != NULL) { 763 /* 764 * NOTE: txMbuf can be NULL, if mbuf has been split into different BDs 765 */ 766 MFREE (sc->txMbuf[sc->txBdTail],n); 767 sc->txMbuf[sc->txBdTail] = NULL; 768 } 769 sc->txBdActiveCount--; 770 if(++sc->txBdTail >= sc->txBdCount) { 771 sc->txBdTail = 0; 772 } 773 } 774 } 775 776 777 static void mcf548x_fec_sendpacket(struct ifnet *ifp,struct mbuf *m) { 778 struct mcf548x_enet_struct *sc = ifp->if_softc; 779 struct mbuf *l = NULL; 780 int nAdded; 781 uint32_t status; 782 rtems_event_set events; 783 MCD_bufDescFec *thisBd; 784 MCD_bufDescFec *firstBd = NULL; 785 void *data_ptr; 786 size_t data_len; 787 788 /* 789 * Free up buffer descriptors 790 */ 791 mcf548x_fec_retire_tbd(sc,false); 792 793 /* 794 * Set up the transmit buffer descriptors. 795 * No need to pad out short packets since the 796 * hardware takes care of that automatically. 797 * No need to copy the packet to a contiguous buffer 798 * since the hardware is capable of scatter/gather DMA. 799 */ 800 nAdded = 0; 801 802 for(;;) { 803 804 /* 805 * Wait for buffer descriptor to become available. 806 */ 807 if((sc->txBdActiveCount + nAdded) == sc->txBdCount) { 808 809 /* 810 * Clear old events 811 */ 812 MCDMA_CLR_PENDING(sc->txDmaChan); 813 /* 814 * Wait for buffer descriptor to become available. 815 * Note that the buffer descriptors are checked 816 * *before* * entering the wait loop -- this catches 817 * the possibility that a buffer descriptor became 818 * available between the `if' above, and the clearing 819 * of the event register. 820 * This is to catch the case where the transmitter 821 * stops in the middle of a frame -- and only the 822 * last buffer descriptor in a frame can generate 823 * an interrupt. 824 */ 825 mcf548x_fec_retire_tbd(sc,false); 826 827 while((sc->txBdActiveCount + nAdded) == sc->txBdCount) { 828 mcdma_glue_irq_enable(sc->txDmaChan); 829 rtems_bsdnet_event_receive(INTERRUPT_EVENT, 830 RTEMS_WAIT | RTEMS_EVENT_ANY, 831 RTEMS_NO_TIMEOUT, &events); 832 mcf548x_fec_retire_tbd(sc,false); 833 } 834 } 835 836 if(m->m_len == 0) { 837 /* 838 * Just toss empty mbufs 839 */ 840 struct mbuf *n; 841 MFREE(m, n); 842 m = n; 843 if(l != NULL) { 844 l->m_next = m; 845 } 846 } 847 else { 848 /* 849 * Flush the buffer for this descriptor 850 */ 851 rtems_cache_flush_multiple_data_lines((const void *)mtod(m, void *), 852 m->m_len); 853 /* 854 * Fill in the buffer descriptor, 855 * set "end of frame" bit in status, 856 * if last mbuf in chain 857 */ 858 thisBd = sc->txBd + sc->txBdHead; 859 /* 860 * FIXME: do not send interrupt after every frame 861 * doing this every quarter of BDs is much more efficent 862 */ 863 status = (((m->m_next == NULL) 864 ? MCF548X_FEC_TBD_LAST | MCF548X_FEC_TBD_INT 865 : 0) 866 | ((sc->txBdHead == sc->txBdCount-1) 867 ? MCF548X_FEC_TBD_WRAP 868 :0 )); 869 /* 870 * Don't set the READY flag till the 871 * whole packet has been readied. 872 */ 873 if (firstBd != NULL) { 874 status |= MCF548X_FEC_TBD_READY; 875 } 876 else { 877 firstBd = thisBd; 878 } 879 880 data_ptr = mtod(m, void *); 881 data_len = m->m_len; 882 sc->txMbuf[sc->txBdHead] = m; 883 /* go to next part in chain */ 884 l = m; 885 m = m->m_next; 886 887 SET_BD_BUFFER(thisBd, data_ptr); 888 SET_BD_LENGTH(thisBd, data_len); 889 SET_BD_STATUS(thisBd, status); 890 891 nAdded++; 892 if(++(sc->txBdHead) == sc->txBdCount) { 893 sc->txBdHead = 0; 894 } 895 } 896 /* 897 * Set the transmit buffer status. 898 * Break out of the loop if this mbuf is the last in the frame. 899 */ 900 if(m == NULL) { 901 if(nAdded) { 902 SET_BD_STATUS(firstBd, 903 GET_BD_STATUS(firstBd) | MCF548X_FEC_TBD_READY); 904 MCD_continDma(sc->txDmaChan); 905 sc->txBdActiveCount += nAdded; 906 } 907 break; 908 } 909 } /* end of for(;;) */ 910 } 911 912 913 /* 914 * Driver transmit daemon 915 */ 916 void mcf548x_fec_txDaemon(void *arg) 917 { 918 struct mcf548x_enet_struct *sc = (struct mcf548x_enet_struct *)arg; 919 struct ifnet *ifp = &sc->arpcom.ac_if; 920 struct mbuf *m; 921 rtems_event_set events; 922 923 for(;;) { 924 /* 925 * Wait for packet 926 */ 927 mcdma_glue_irq_enable(sc->txDmaChan); 928 rtems_bsdnet_event_receive(START_TRANSMIT_EVENT|INTERRUPT_EVENT, 929 RTEMS_EVENT_ANY | RTEMS_WAIT, 930 RTEMS_NO_TIMEOUT, 931 &events); 932 933 /* 934 * Send packets till queue is empty 935 */ 936 for(;;) 937 { 938 939 /* 940 * Get the next mbuf chain to transmit. 941 */ 942 IF_DEQUEUE(&ifp->if_snd, m); 943 944 if (!m) 945 break; 946 947 mcf548x_fec_sendpacket(ifp, m); 948 949 } 950 951 ifp->if_flags &= ~IFF_OACTIVE; 952 953 } 954 955 } 956 957 958 /* 959 * reader task 960 */ 961 static void mcf548x_fec_rxDaemon(void *arg){ 962 struct mcf548x_enet_struct *sc = (struct mcf548x_enet_struct *)arg; 963 struct ifnet *ifp = &sc->arpcom.ac_if; 964 struct mbuf *m; 965 struct ether_header *eh; 966 int rxBdIndex; 967 uint32_t status; 968 size_t size; 969 rtems_event_set events; 970 size_t len = 1; 971 MCD_bufDescFec *bd; 972 973 /* 974 * Input packet handling loop 975 */ 976 rxBdIndex = 0; 977 978 for (;;) { 979 /* 980 * Clear old events 981 */ 982 MCDMA_CLR_PENDING(sc->rxDmaChan); 983 /* 984 * Get the first BD pointer and its length. 985 */ 986 bd = sc->rxBd + rxBdIndex; 987 status = GET_BD_STATUS( bd ); 988 len = GET_BD_LENGTH( bd ); 989 990 /* 991 * Loop through BDs until we find an empty one. This indicates that 992 * the DMA is still using it. 993 */ 994 while( !(status & MCF548X_FEC_RBD_EMPTY) ) { 995 996 /* 997 * Remember the data pointer from this transfer. 998 */ 999 GET_BD_BUFFER(bd); 1000 m = sc->rxMbuf[rxBdIndex]; 1001 m->m_len = m->m_pkthdr.len = (len 1002 - sizeof(uint32_t) 1003 - sizeof(struct ether_header)); 1004 eh = mtod(m, struct ether_header *); 1005 m->m_data += sizeof(struct ether_header); 1006 ether_input(ifp, eh, m); 1007 1008 /* 1009 * Done w/ the BD. Clean it. 1010 */ 1011 sc->rxMbuf[rxBdIndex] = NULL; 1012 1013 /* 1014 * Add a new buffer to the ring. 1015 */ 1016 MGETHDR (m, M_WAIT, MT_DATA); 1017 MCLGET (m, M_WAIT); 1018 m->m_pkthdr.rcvif = ifp; 1019 size = ETHER_MAX_LEN; 1020 1021 sc->rxMbuf[rxBdIndex] = m; 1022 rtems_cache_invalidate_multiple_data_lines(mtod(m,const void *), 1023 size); 1024 1025 SET_BD_BUFFER(bd,mtod(m, void *)); 1026 SET_BD_LENGTH(bd,size); 1027 SET_BD_STATUS(bd, 1028 MCF548X_FEC_RBD_EMPTY 1029 |MCF548X_FEC_RBD_INT 1030 |((rxBdIndex == sc->rxBdCount-1) 1031 ? MCF548X_FEC_RBD_WRAP 1032 : 0) 1033 ); 1034 1035 /* 1036 * advance to next BD 1037 */ 1038 if (++rxBdIndex >= sc->rxBdCount) { 1039 rxBdIndex = 0; 1040 } 1041 /* 1042 * Get next BD pointer and its length. 1043 */ 1044 bd = sc->rxBd + rxBdIndex; 1045 status = GET_BD_STATUS( bd ); 1046 len = GET_BD_LENGTH( bd ); 1047 } 1048 /* 1049 * Unmask RXF (Full frame received) event 1050 */ 1051 mcdma_glue_irq_enable(sc->rxDmaChan); 1052 1053 rtems_bsdnet_event_receive (INTERRUPT_EVENT | FATAL_INT_EVENT, 1054 RTEMS_WAIT | RTEMS_EVENT_ANY, 1055 RTEMS_NO_TIMEOUT, &events); 1056 if (events & FATAL_INT_EVENT) { 1057 /* 1058 * fatal interrupt ocurred, so reinit fec and restart mcdma tasks 1059 */ 1060 mcf548x_fec_restart(sc); 1061 rxBdIndex = 0; 1062 } 1063 } 1064 } 1065 657 fec_send_event(sc->txDaemonTid); 658 } 659 } 1066 660 1067 661 /* … … 1137 731 * Set transmit fifo watermark register (X_WMRK), default = 64 1138 732 */ 1139 MCF548X_FEC_FECTFAR(chan) = MCF548X_FEC_FECTFAR_ALARM( 256); /* 256 bytes */1140 MCF548X_FEC_FECTFWR(chan) = MCF548X_FEC_FECTFWR_X_WMRK_64; 733 MCF548X_FEC_FECTFAR(chan) = MCF548X_FEC_FECTFAR_ALARM(128); 734 MCF548X_FEC_FECTFWR(chan) = MCF548X_FEC_FECTFWR_X_WMRK_64; /* 64 bytes */ 1141 735 1142 736 /* … … 1169 763 ifp->if_flags |= IFF_OACTIVE; 1170 764 1171 rtems_bsdnet_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT); 1172 1173 } 1174 1175 1176 /* 1177 * start the DMA channel 1178 */ 1179 static void mcf548x_fec_startDMA(struct mcf548x_enet_struct *sc) 765 fec_send_event(sc->txDaemonTid); 766 767 } 768 769 static void fec_start_dma_and_controller(struct mcf548x_enet_struct *sc) 1180 770 { 1181 771 int chan = sc->chan; … … 1232 822 rtems_panic("FEC: cannot start tx DMA"); 1233 823 } 1234 } 824 825 /* 826 * Enable FEC-Lite controller 827 */ 828 MCF548X_FEC_ECR(chan) |= MCF548X_FEC_ECR_ETHER_EN; 829 } 830 831 static void mcf548x_fec_restart(struct mcf548x_enet_struct *sc, rtems_id otherDaemon) 832 { 833 if (sc->state == FEC_STATE_RESTART_1) { 834 mcf548x_fec_initialize_hardware(sc); 835 fec_start_dma_and_controller(sc); 836 sc->state = FEC_STATE_NORMAL; 837 } else { 838 sc->state = FEC_STATE_RESTART_1; 839 } 840 841 fec_send_event(otherDaemon); 842 while (sc->state != FEC_STATE_NORMAL) { 843 fec_wait_for_event(); 844 } 845 } 846 847 static void fec_reset_bd_and_discard_tx_frames( 848 int bdCount, 849 MCD_bufDescFec *bdRing, 850 struct mbuf **mbufs 851 ) 852 { 853 int bdIndex = 0; 854 855 for (bdIndex = 0; bdIndex < bdCount; ++bdIndex) { 856 bool bdIsLast = bdIndex == bdCount - 1; 857 struct mbuf *m = mbufs[bdIndex]; 858 859 bdRing[bdIndex].statCtrl = bdIsLast ? MCF548X_FEC_TBD_WRAP : 0; 860 861 if (m != NULL) { 862 mbufs[bdIndex] = NULL; 863 m_free(m); 864 } 865 } 866 } 867 868 static void fec_reset_tx_dma( 869 int dmaChan, 870 int bdCount, 871 MCD_bufDescFec *bdRing, 872 struct mbuf **mbufs, 873 struct mbuf *m 874 ) 875 { 876 if (m != NULL) { 877 m_freem(m); 878 } 879 880 MCD_killDma(dmaChan); 881 882 fec_reset_bd_and_discard_tx_frames(bdCount, bdRing, mbufs); 883 } 884 885 static struct mbuf *fec_next_fragment( 886 struct ifnet *ifp, 887 struct mbuf *m, 888 bool *isFirst 889 ) 890 { 891 struct mbuf *n = NULL; 892 893 *isFirst = false; 894 895 while (true) { 896 if (m == NULL) { 897 IF_DEQUEUE(&ifp->if_snd, m); 898 899 if (m != NULL) { 900 *isFirst = true; 901 } else { 902 ifp->if_flags &= ~IFF_OACTIVE; 903 904 return NULL; 905 } 906 } 907 908 if (m->m_len > 0) { 909 break; 910 } else { 911 m = m_free(m); 912 } 913 } 914 915 n = m->m_next; 916 while (n != NULL && n->m_len <= 0) { 917 n = m_free(n); 918 } 919 m->m_next = n; 920 921 return m; 922 } 923 924 static bool fec_transmit( 925 struct ifnet *ifp, 926 int dmaChan, 927 int bdCount, 928 MCD_bufDescFec *bdRing, 929 struct mbuf **mbufs, 930 int *bdIndexPtr, 931 struct mbuf **mPtr, 932 MCD_bufDescFec **firstPtr 933 ) 934 { 935 bool bdShortage = false; 936 int bdIndex = *bdIndexPtr; 937 struct mbuf *m = *mPtr; 938 MCD_bufDescFec *first = *firstPtr; 939 940 while (true) { 941 MCD_bufDescFec *bd = &bdRing[bdIndex]; 942 943 MCDMA_CLR_PENDING(dmaChan); 944 if ((bd->statCtrl & MCF548X_FEC_TBD_READY) == 0) { 945 struct mbuf *done = mbufs[bdIndex]; 946 bool isFirst = false; 947 948 if (done != NULL) { 949 m_free(done); 950 mbufs[bdIndex] = NULL; 951 } 952 953 m = fec_next_fragment(ifp, m, &isFirst); 954 if (m != NULL) { 955 bool bdIsLast = bdIndex == bdCount - 1; 956 u16 status = bdIsLast ? MCF548X_FEC_TBD_WRAP : 0; 957 958 bd->length = (u16) m->m_len; 959 bd->dataPointer = mtod(m, u32); 960 961 mbufs[bdIndex] = m; 962 963 rtems_cache_flush_multiple_data_lines(mtod(m, void *), m->m_len); 964 965 if (isFirst) { 966 first = bd; 967 } else { 968 status |= MCF548X_FEC_TBD_READY; 969 } 970 971 if (m->m_next != NULL) { 972 bd->statCtrl = status; 973 } else { 974 bd->statCtrl = status | MCF548X_FEC_TBD_INT | MCF548X_FEC_TBD_LAST; 975 first->statCtrl |= MCF548X_FEC_TBD_READY; 976 MCD_continDma(dmaChan); 977 } 978 979 m = m->m_next; 980 } else { 981 break; 982 } 983 } else { 984 bdShortage = true; 985 break; 986 } 987 988 if (bdIndex < bdCount - 1) { 989 ++bdIndex; 990 } else { 991 bdIndex = 0; 992 } 993 } 994 995 *bdIndexPtr = bdIndex; 996 *mPtr = m; 997 *firstPtr = first; 998 999 return bdShortage; 1000 } 1001 1002 static MCD_bufDescFec *fec_init_tx_dma( 1003 MCD_bufDescFec *bdRing, 1004 int bdCount 1005 ) 1006 { 1007 int bdIndex; 1008 1009 for (bdIndex = 0; bdIndex < bdCount; ++bdIndex) { 1010 bool bdIsLast = bdIndex == bdCount - 1; 1011 1012 bdRing[bdIndex].dataPointer = 0; 1013 bdRing[bdIndex].length = 0; 1014 bdRing[bdIndex].statCtrl = bdIsLast ? MCF548X_FEC_RBD_WRAP : 0; 1015 } 1016 1017 return bdRing; 1018 } 1019 1020 static void mcf548x_fec_txDaemon(void *arg) 1021 { 1022 struct mcf548x_enet_struct *sc = arg; 1023 struct ifnet *ifp = &sc->arpcom.ac_if; 1024 int dmaChan = sc->txDmaChan; 1025 int bdIndex = 0; 1026 int bdCount = sc->txBdCount; 1027 struct mbuf **mbufs = &sc->txMbuf[0]; 1028 struct mbuf *m = NULL; 1029 MCD_bufDescFec *bdRing = fec_init_tx_dma(sc->txBd, bdCount); 1030 MCD_bufDescFec *first = NULL; 1031 bool bdShortage = false; 1032 1033 memset(mbufs, 0, bdCount * sizeof(*mbufs)); 1034 1035 while (true) { 1036 if (bdShortage) { 1037 mcdma_glue_irq_enable(dmaChan); 1038 } 1039 fec_wait_for_event(); 1040 1041 if (sc->state != FEC_STATE_NORMAL) { 1042 fec_reset_tx_dma(dmaChan, bdCount, bdRing, mbufs, m); 1043 mcf548x_fec_restart(sc, sc->rxDaemonTid); 1044 bdIndex = 0; 1045 m = NULL; 1046 first = NULL; 1047 } 1048 1049 bdShortage = fec_transmit( 1050 ifp, 1051 dmaChan, 1052 bdCount, 1053 bdRing, 1054 mbufs, 1055 &bdIndex, 1056 &m, 1057 &first 1058 ); 1059 } 1060 } 1061 1062 static struct mbuf *fec_add_mbuf( 1063 int how, 1064 struct ifnet *ifp, 1065 MCD_bufDescFec *bd, 1066 bool bdIsLast 1067 ) 1068 { 1069 struct mbuf *m; 1070 1071 MGETHDR(m, how, MT_DATA); 1072 if (m != NULL) { 1073 MCLGET(m, how); 1074 if ((m->m_flags & M_EXT) != 0) { 1075 m->m_pkthdr.rcvif = ifp; 1076 1077 rtems_cache_invalidate_multiple_data_lines(mtod(m, void *), ETHER_MAX_LEN); 1078 1079 bd->dataPointer = mtod(m, u32); 1080 bd->length = ETHER_MAX_LEN; 1081 bd->statCtrl = MCF548X_FEC_RBD_EMPTY 1082 | MCF548X_FEC_RBD_INT 1083 | (bdIsLast ? MCF548X_FEC_RBD_WRAP : 0); 1084 } else { 1085 m_free(m); 1086 } 1087 } 1088 1089 return m; 1090 } 1091 1092 static MCD_bufDescFec *fec_init_rx_dma( 1093 MCD_bufDescFec *bdRing, 1094 struct ifnet *ifp, 1095 int bdCount, 1096 struct mbuf **mbufs 1097 ) 1098 { 1099 int bdIndex; 1100 1101 for (bdIndex = 0; bdIndex < bdCount; ++bdIndex) { 1102 bool bdIsLast = bdIndex == bdCount - 1; 1103 1104 mbufs[bdIndex] = fec_add_mbuf(M_WAIT, ifp, &bdRing[bdIndex], bdIsLast); 1105 } 1106 1107 return bdRing; 1108 } 1109 1110 static void fec_reset_rx_dma( 1111 int dmaChan, 1112 int bdCount, 1113 MCD_bufDescFec *bdRing 1114 ) 1115 { 1116 int bdIndex; 1117 1118 MCD_killDma(dmaChan); 1119 1120 for (bdIndex = 0; bdIndex < bdCount - 1; ++bdIndex) { 1121 bdRing[bdIndex].length = ETHER_MAX_LEN; 1122 bdRing[bdIndex].statCtrl = MCF548X_FEC_RBD_EMPTY | MCF548X_FEC_RBD_INT; 1123 } 1124 1125 bdRing[bdIndex].length = ETHER_MAX_LEN; 1126 bdRing[bdIndex].statCtrl = MCF548X_FEC_RBD_EMPTY | MCF548X_FEC_RBD_INT | MCF548X_FEC_RBD_WRAP; 1127 } 1128 1129 static int fec_ether_input( 1130 struct ifnet *ifp, 1131 int dmaChan, 1132 int bdIndex, 1133 int bdCount, 1134 MCD_bufDescFec *bdRing, 1135 struct mbuf **mbufs 1136 ) 1137 { 1138 while (true) { 1139 bool bdIsLast = bdIndex == bdCount - 1; 1140 MCD_bufDescFec *bd = &bdRing[bdIndex]; 1141 struct mbuf *m = mbufs[bdIndex]; 1142 struct mbuf *n; 1143 u16 status; 1144 1145 MCDMA_CLR_PENDING(dmaChan); 1146 status = bd->statCtrl; 1147 1148 if ((status & MCF548X_FEC_RBD_EMPTY) != 0) { 1149 break; 1150 } 1151 1152 n = fec_add_mbuf(0, ifp, bd, bdIsLast); 1153 if (n != NULL) { 1154 int len = bd->length - ETHER_HDR_LEN - ETHER_CRC_LEN; 1155 struct ether_header *eh = mtod(m, struct ether_header *); 1156 1157 m->m_len = len; 1158 m->m_pkthdr.len = len; 1159 m->m_data = mtod(m, char *) + ETHER_HDR_LEN; 1160 1161 ether_input(ifp, eh, m); 1162 } else { 1163 n = m; 1164 } 1165 1166 mbufs[bdIndex] = n; 1167 1168 if (bdIndex < bdCount - 1) { 1169 ++bdIndex; 1170 } else { 1171 bdIndex = 0; 1172 } 1173 } 1174 1175 return bdIndex; 1176 } 1177 1178 static void mcf548x_fec_rxDaemon(void *arg) 1179 { 1180 struct mcf548x_enet_struct *sc = arg; 1181 struct ifnet *ifp = &sc->arpcom.ac_if; 1182 int dmaChan = sc->rxDmaChan; 1183 int bdIndex = 0; 1184 int bdCount = sc->rxBdCount; 1185 struct mbuf **mbufs = &sc->rxMbuf[0]; 1186 MCD_bufDescFec *bdRing = fec_init_rx_dma(sc->rxBd, ifp, bdCount, mbufs); 1187 1188 while (true) { 1189 mcdma_glue_irq_enable(dmaChan); 1190 fec_wait_for_event(); 1191 1192 bdIndex = fec_ether_input(ifp, dmaChan, bdIndex, bdCount, bdRing, mbufs); 1193 1194 if (sc->state != FEC_STATE_NORMAL) { 1195 fec_reset_rx_dma(dmaChan, bdCount, bdRing); 1196 mcf548x_fec_restart(sc, sc->txDaemonTid); 1197 bdIndex = 0; 1198 } 1199 } 1200 } 1201 1235 1202 /* 1236 1203 * Initialize and start the device … … 1293 1260 1294 1261 MCF548X_FEC_EIMR(chan) = FEC_INTR_MASK_USED; 1295 mcf548x_fec_rx_bd_init(sc);1296 1297 /*1298 * reset and Set up mcf548x FEC hardware1299 */1300 mcf548x_fec_initialize_hardware(sc);1301 1262 1302 1263 /* … … 1309 1270 sc->rxDaemonTid = rtems_bsdnet_newproc(rxTaskName, 4096, 1310 1271 mcf548x_fec_rxDaemon, sc); 1311 /* 1312 * Clear SmartDMA task interrupt pending bits. 1313 */ 1314 MCDMA_CLR_PENDING(sc->rxDmaChan ); 1315 MCDMA_CLR_PENDING(sc->txDmaChan ); 1316 1317 /* 1318 * start the DMA channels 1319 */ 1320 mcf548x_fec_startDMA(sc); 1321 /* 1322 * Enable FEC-Lite controller 1323 */ 1324 MCF548X_FEC_ECR(chan) |= MCF548X_FEC_ECR_ETHER_EN; 1325 1326 1327 } 1272 } 1273 1274 mcf548x_fec_request_restart(sc); 1328 1275 1329 1276 /* … … 1348 1295 static void enet_stats (struct mcf548x_enet_struct *sc) 1349 1296 { 1350 printf (" Rx Interrupts:%-8lu", sc->rxInterrupts); 1351 printf (" Not First:%-8lu", sc->rxNotFirst); 1352 printf (" Not Last:%-8lu\n", sc->rxNotLast); 1353 printf (" Giant:%-8lu", sc->rxGiant); 1354 printf (" Non-octet:%-8lu\n", sc->rxNonOctet); 1355 printf (" Bad CRC:%-8lu", sc->rxBadCRC); 1356 printf (" Overrun:%-8lu", sc->rxOverrun); 1357 printf (" Collision:%-8lu\n", sc->rxCollision); 1358 1359 printf (" Tx Interrupts:%-8lu", sc->txInterrupts); 1360 printf (" Deferred:%-8lu", sc->txDeferred); 1361 printf (" Late Collision:%-8lu\n", sc->txLateCollision); 1362 printf (" Retransmit Limit:%-8lu", sc->txRetryLimit); 1363 printf (" Underrun:%-8lu", sc->txUnderrun); 1364 printf (" Misaligned:%-8lu\n", sc->txMisaligned); 1365 1366 } 1367 1368 /* 1369 * restart the driver, reinit the fec 1370 * this function is responsible to reinitialize the FEC in case a fatal 1371 * error has ocurred. This is needed, wen a RxFIFO Overrun or a TxFIFO underrun 1372 * has ocurred. In these cases, the FEC is automatically disabled, and 1373 * both FIFOs must be reset and the BestComm tasks must be restarted 1374 * 1375 * Note: the daemon tasks will continue to run 1376 * (in fact this function will be called in the context of the rx daemon task) 1377 */ 1378 #define NEW_DMA_SETUP 1379 1380 static void mcf548x_fec_restart(struct mcf548x_enet_struct *sc) 1381 { 1382 int chan = sc->chan; 1383 /* 1384 * FIXME: bring Tx Daemon into idle state 1385 */ 1386 #ifdef NEW_DMA_SETUP 1387 /* 1388 * cleanup remaining receive mbufs 1389 */ 1390 mcf548x_fec_rx_bd_cleanup(sc); 1391 #endif 1392 /* 1393 * Stop DMA tasks 1394 */ 1395 MCD_killDma (sc->rxDmaChan); 1396 MCD_killDma (sc->txDmaChan); 1397 /* 1398 * FIXME: wait, until Tx Daemon is in idle state 1399 */ 1400 1401 /* 1402 * Disable transmit / receive interrupts 1403 */ 1404 mcdma_glue_irq_disable(sc->txDmaChan); 1405 mcdma_glue_irq_disable(sc->rxDmaChan); 1406 #ifdef NEW_DMA_SETUP 1407 /* 1408 * recycle pending tx buffers 1409 * FIXME: try to extract pending Tx buffers 1410 */ 1411 mcf548x_fec_retire_tbd(sc,true); 1412 #endif 1413 /* 1414 * re-initialize the FEC hardware 1415 */ 1416 mcf548x_fec_initialize_hardware(sc); 1417 1418 #ifdef NEW_DMA_SETUP 1419 1420 /* 1421 * reinit receive mbufs 1422 */ 1423 mcf548x_fec_rx_bd_init(sc); 1424 #endif 1425 /* 1426 * Clear SmartDMA task interrupt pending bits. 1427 */ 1428 MCDMA_CLR_PENDING( sc->rxDmaChan ); 1429 1430 /* 1431 * start the DMA channels again 1432 */ 1433 mcf548x_fec_startDMA(sc); 1434 /* 1435 * reenable rx/tx interrupts 1436 */ 1437 mcdma_glue_irq_enable(sc->rxDmaChan); 1438 mcdma_glue_irq_enable(sc->txDmaChan); 1439 /* 1440 * (re-)init fec hardware 1441 */ 1442 mcf548x_fec_initialize_hardware(sc); 1443 /* 1444 * reenable fec FIFO error interrupts 1445 */ 1446 MCF548X_FEC_EIMR(chan) = FEC_INTR_MASK_USED; 1447 /* 1448 * Enable FEC-Lite controller 1449 */ 1450 MCF548X_FEC_ECR(chan) |= MCF548X_FEC_ECR_ETHER_EN; 1297 printf (" Rx Interrupts:%-8lu", sc->rxInterrupts); 1298 printf (" Rx Not First:%-8lu", sc->rxNotFirst); 1299 printf (" Rx Not Last:%-8lu\n", sc->rxNotLast); 1300 printf (" Rx Giant:%-8lu", sc->rxGiant); 1301 printf (" Rx Non-octet:%-8lu", sc->rxNonOctet); 1302 printf (" Rx Bad CRC:%-8lu\n", sc->rxBadCRC); 1303 printf (" Rx FIFO Error:%-8lu", sc->rxFIFOError); 1304 printf (" Rx Collision:%-8lu", sc->rxCollision); 1305 1306 printf (" Tx Interrupts:%-8lu\n", sc->txInterrupts); 1307 printf (" Tx Deferred:%-8lu", sc->txDeferred); 1308 printf (" Tx Late Collision:%-8lu", sc->txLateCollision); 1309 printf (" Tx Retransmit Limit:%-8lu\n", sc->txRetryLimit); 1310 printf (" Tx Underrun:%-8lu", sc->txUnderrun); 1311 printf (" Tx FIFO Error:%-8lu", sc->txFIFOError); 1312 printf (" Tx Misaligned:%-8lu\n", sc->txMisaligned); 1313 1451 1314 } 1452 1315
Note: See TracChangeset
for help on using the changeset viewer.