xref: /FreeRTOS-Plus-TCP-v4.0.0/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_hw.c (revision 2258623ed12f12a8b26f5b0e3d2e418a2def2f06)
1 /*
2  * Copyright (c) 2010-2013 Xilinx, Inc.  All rights reserved.
3  *
4  * Xilinx, Inc.
5  * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
6  * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
7  * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
8  * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
9  * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
10  * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
11  * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
12  * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
13  * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
14  * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
15  * AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  */
18 
19 
20 /* Standard includes. */
21 #include <stdint.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 
25 /* FreeRTOS includes. */
26 #include "FreeRTOS.h"
27 #include "task.h"
28 #include "queue.h"
29 
30 /* FreeRTOS+TCP includes. */
31 #include "FreeRTOS_IP.h"
32 #include "FreeRTOS_Sockets.h"
33 #include "FreeRTOS_IP_Private.h"
34 #include "NetworkBufferManagement.h"
35 #include "NetworkInterface.h"
36 
37 #include "x_emacpsif.h"
38 
39 extern TaskHandle_t xEMACTaskHandle;
40 
41 /*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c
42  *** to run it on a PEEP board
43  ***/
44 
setup_isr(xemacpsif_s * xemacpsif)45 void setup_isr( xemacpsif_s * xemacpsif )
46 {
47     /*
48      * Setup callbacks
49      */
50     XEmacPs * xInstancePtr = &( xemacpsif->emacps );
51 
52     xInstancePtr->SendHandler = emacps_send_handler;
53     xInstancePtr->SendRef = ( void * ) xemacpsif;
54 
55     xInstancePtr->RecvHandler = emacps_recv_handler;
56     xInstancePtr->RecvRef = ( void * ) xemacpsif;
57 
58     xInstancePtr->ErrorHandler = emacps_error_handler;
59     xInstancePtr->ErrorRef = ( void * ) xemacpsif;
60 }
61 
start_emacps(xemacpsif_s * xemacps)62 void start_emacps( xemacpsif_s * xemacps )
63 {
64     /* start the temac */
65     XEmacPs_Start( &xemacps->emacps );
66 }
67 
68 extern struct xtopology_t xXTopology;
69 
70 volatile int error_msg_count = 0;
71 volatile const char * last_err_msg = "";
72 
73 struct xERROR_MSG
74 {
75     void * arg;
76     u8 Direction;
77     u32 ErrorWord;
78 };
79 
80 static struct xERROR_MSG xErrorList[ 8 ];
81 static BaseType_t xErrorHead, xErrorTail;
82 
emacps_error_handler(void * arg,u8 Direction,u32 ErrorWord)83 void emacps_error_handler( void * arg,
84                            u8 Direction,
85                            u32 ErrorWord )
86 {
87     BaseType_t xHigherPriorityTaskWoken = pdFALSE;
88     xemacpsif_s * xemacpsif;
89     BaseType_t xNextHead = xErrorHead;
90 
91     xemacpsif = ( xemacpsif_s * ) ( arg );
92 
93     if( ( Direction != XEMACPS_SEND ) || ( ErrorWord != XEMACPS_TXSR_USEDREAD_MASK ) )
94     {
95         if( ++xNextHead == ( sizeof( xErrorList ) / sizeof( xErrorList[ 0 ] ) ) )
96         {
97             xNextHead = 0;
98         }
99 
100         if( xNextHead != xErrorTail )
101         {
102             xErrorList[ xErrorHead ].arg = arg;
103             xErrorList[ xErrorHead ].Direction = Direction;
104             xErrorList[ xErrorHead ].ErrorWord = ErrorWord;
105 
106             xErrorHead = xNextHead;
107 
108             xemacpsif = ( xemacpsif_s * ) ( arg );
109             xemacpsif->isr_events |= EMAC_IF_ERR_EVENT;
110         }
111 
112         if( xEMACTaskHandle != NULL )
113         {
114             vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
115         }
116     }
117 
118     portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
119 }
120 
121 static void emacps_handle_error( void * arg,
122                                  u8 Direction,
123                                  u32 ErrorWord );
124 
emacps_check_errors(xemacpsif_s * xemacps)125 int emacps_check_errors( xemacpsif_s * xemacps )
126 {
127     int xResult;
128 
129     ( void ) xemacps;
130 
131     if( xErrorHead == xErrorTail )
132     {
133         xResult = 0;
134     }
135     else
136     {
137         xResult = 1;
138         emacps_handle_error(
139             xErrorList[ xErrorTail ].arg,
140             xErrorList[ xErrorTail ].Direction,
141             xErrorList[ xErrorTail ].ErrorWord );
142     }
143 
144     return xResult;
145 }
146 
emacps_handle_error(void * arg,u8 Direction,u32 ErrorWord)147 static void emacps_handle_error( void * arg,
148                                  u8 Direction,
149                                  u32 ErrorWord )
150 {
151     xemacpsif_s * xemacpsif;
152     struct xtopology_t * xtopologyp;
153     XEmacPs * xemacps;
154 
155     xemacpsif = ( xemacpsif_s * ) ( arg );
156 
157     xtopologyp = &xXTopology;
158 
159     xemacps = &xemacpsif->emacps;
160 
161     /* Do not appear to be used. */
162     ( void ) xemacps;
163     ( void ) xtopologyp;
164 
165     last_err_msg = NULL;
166 
167     if( ErrorWord != 0 )
168     {
169         switch( Direction )
170         {
171             case XEMACPS_RECV:
172 
173                 if( ( ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK ) != 0 )
174                 {
175                     last_err_msg = "Receive DMA error";
176                     xNetworkInterfaceInitialise();
177                 }
178 
179                 if( ( ErrorWord & XEMACPS_RXSR_RXOVR_MASK ) != 0 )
180                 {
181                     last_err_msg = "Receive over run";
182                     emacps_recv_handler( arg );
183                 }
184 
185                 if( ( ErrorWord & XEMACPS_RXSR_BUFFNA_MASK ) != 0 )
186                 {
187                     last_err_msg = "Receive buffer not available";
188                     emacps_recv_handler( arg );
189                 }
190 
191                 break;
192 
193             case XEMACPS_SEND:
194 
195                 if( ( ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK ) != 0 )
196                 {
197                     last_err_msg = "Transmit DMA error";
198                     xNetworkInterfaceInitialise();
199                 }
200 
201                 if( ( ErrorWord & XEMACPS_TXSR_URUN_MASK ) != 0 )
202                 {
203                     last_err_msg = "Transmit under run";
204                     HandleTxErrors( xemacpsif );
205                 }
206 
207                 if( ( ErrorWord & XEMACPS_TXSR_BUFEXH_MASK ) != 0 )
208                 {
209                     last_err_msg = "Transmit buffer exhausted";
210                     HandleTxErrors( xemacpsif );
211                 }
212 
213                 if( ( ErrorWord & XEMACPS_TXSR_RXOVR_MASK ) != 0 )
214                 {
215                     last_err_msg = "Transmit retry excessed limits";
216                     HandleTxErrors( xemacpsif );
217                 }
218 
219                 if( ( ErrorWord & XEMACPS_TXSR_FRAMERX_MASK ) != 0 )
220                 {
221                     last_err_msg = "Transmit collision";
222                     emacps_check_tx( xemacpsif );
223                 }
224 
225                 break;
226         }
227     }
228 
229     /* Break on this statement and inspect error_msg if you like */
230     if( last_err_msg != NULL )
231     {
232         error_msg_count++;
233         FreeRTOS_printf( ( "emacps_handle_error: %s\n", last_err_msg ) );
234     }
235 }
236 
HandleTxErrors(xemacpsif_s * xemacpsif)237 void HandleTxErrors( xemacpsif_s * xemacpsif )
238 {
239     u32 netctrlreg;
240 
241     /*taskENTER_CRITICAL() */
242     {
243         netctrlreg = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress,
244                                       XEMACPS_NWCTRL_OFFSET );
245         netctrlreg = netctrlreg & ( ~XEMACPS_NWCTRL_TXEN_MASK );
246         XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress,
247                           XEMACPS_NWCTRL_OFFSET, netctrlreg );
248 
249         clean_dma_txdescs( xemacpsif );
250         netctrlreg = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress,
251                                       XEMACPS_NWCTRL_OFFSET );
252         netctrlreg = netctrlreg | ( XEMACPS_NWCTRL_TXEN_MASK );
253         XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress,
254                           XEMACPS_NWCTRL_OFFSET, netctrlreg );
255     }
256     /*taskEXIT_CRITICAL( ); */
257 }
258