xref: /FreeRTOS-Plus-TCP-v3.1.0/source/portable/NetworkInterface/Zynq/x_emacpsif_hw.c (revision a4124602cc584fa0658448c229f48a459a84fbb1)
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 "Zynq/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_SetHandler( &xemacpsif->emacps, XEMACPS_HANDLER_DMASEND,
51                         ( void * ) emacps_send_handler,
52                         ( void * ) xemacpsif );
53 
54     XEmacPs_SetHandler( &xemacpsif->emacps, XEMACPS_HANDLER_DMARECV,
55                         ( void * ) emacps_recv_handler,
56                         ( void * ) xemacpsif );
57 
58     XEmacPs_SetHandler( &xemacpsif->emacps, XEMACPS_HANDLER_ERROR,
59                         ( void * ) emacps_error_handler,
60                         ( void * ) xemacpsif );
61 }
62 
start_emacps(xemacpsif_s * xemacps)63 void start_emacps( xemacpsif_s * xemacps )
64 {
65     /* start the temac */
66     XEmacPs_Start( &xemacps->emacps );
67 }
68 
69 extern struct xtopology_t xXTopology;
70 
71 volatile int error_msg_count = 0;
72 volatile const char * last_err_msg = "";
73 
74 struct xERROR_MSG
75 {
76     void * arg;
77     u8 Direction;
78     u32 ErrorWord;
79 };
80 
81 static struct xERROR_MSG xErrorList[ 8 ];
82 static BaseType_t xErrorHead, xErrorTail;
83 
emacps_error_handler(void * arg,u8 Direction,u32 ErrorWord)84 void emacps_error_handler( void * arg,
85                            u8 Direction,
86                            u32 ErrorWord )
87 {
88     BaseType_t xHigherPriorityTaskWoken = pdFALSE;
89     xemacpsif_s * xemacpsif;
90     BaseType_t xNextHead = xErrorHead;
91 
92     xemacpsif = ( xemacpsif_s * ) ( arg );
93 
94     if( ( Direction != XEMACPS_SEND ) || ( ErrorWord != XEMACPS_TXSR_USEDREAD_MASK ) )
95     {
96         if( ++xNextHead == ( sizeof( xErrorList ) / sizeof( xErrorList[ 0 ] ) ) )
97         {
98             xNextHead = 0;
99         }
100 
101         if( xNextHead != xErrorTail )
102         {
103             xErrorList[ xErrorHead ].arg = arg;
104             xErrorList[ xErrorHead ].Direction = Direction;
105             xErrorList[ xErrorHead ].ErrorWord = ErrorWord;
106 
107             xErrorHead = xNextHead;
108 
109             xemacpsif = ( xemacpsif_s * ) ( arg );
110             xemacpsif->isr_events |= EMAC_IF_ERR_EVENT;
111         }
112 
113         if( xEMACTaskHandle != NULL )
114         {
115             vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
116         }
117     }
118 
119     portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
120 }
121 
122 static void emacps_handle_error( void * arg,
123                                  u8 Direction,
124                                  u32 ErrorWord );
125 
emacps_check_errors(xemacpsif_s * xemacps)126 int emacps_check_errors( xemacpsif_s * xemacps )
127 {
128     int xResult;
129 
130     ( void ) xemacps;
131 
132     if( xErrorHead == xErrorTail )
133     {
134         xResult = 0;
135     }
136     else
137     {
138         xResult = 1;
139         emacps_handle_error(
140             xErrorList[ xErrorTail ].arg,
141             xErrorList[ xErrorTail ].Direction,
142             xErrorList[ xErrorTail ].ErrorWord );
143     }
144 
145     return xResult;
146 }
147 
emacps_handle_error(void * arg,u8 Direction,u32 ErrorWord)148 static void emacps_handle_error( void * arg,
149                                  u8 Direction,
150                                  u32 ErrorWord )
151 {
152     xemacpsif_s * xemacpsif;
153     struct xtopology_t * xtopologyp;
154     XEmacPs * xemacps;
155 
156     xemacpsif = ( xemacpsif_s * ) ( arg );
157 
158     xtopologyp = &xXTopology;
159 
160     xemacps = &xemacpsif->emacps;
161 
162     /* Do not appear to be used. */
163     ( void ) xemacps;
164     ( void ) xtopologyp;
165 
166     last_err_msg = NULL;
167 
168     if( ErrorWord != 0 )
169     {
170         switch( Direction )
171         {
172             case XEMACPS_RECV:
173 
174                 if( ( ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK ) != 0 )
175                 {
176                     last_err_msg = "Receive DMA error";
177                     xNetworkInterfaceInitialise();
178                 }
179 
180                 if( ( ErrorWord & XEMACPS_RXSR_RXOVR_MASK ) != 0 )
181                 {
182                     last_err_msg = "Receive over run";
183                     emacps_recv_handler( arg );
184                 }
185 
186                 if( ( ErrorWord & XEMACPS_RXSR_BUFFNA_MASK ) != 0 )
187                 {
188                     last_err_msg = "Receive buffer not available";
189                     emacps_recv_handler( arg );
190                 }
191 
192                 break;
193 
194             case XEMACPS_SEND:
195 
196                 if( ( ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK ) != 0 )
197                 {
198                     last_err_msg = "Transmit DMA error";
199                     xNetworkInterfaceInitialise();
200                 }
201 
202                 if( ( ErrorWord & XEMACPS_TXSR_URUN_MASK ) != 0 )
203                 {
204                     last_err_msg = "Transmit under run";
205                     HandleTxErrors( xemacpsif );
206                 }
207 
208                 if( ( ErrorWord & XEMACPS_TXSR_BUFEXH_MASK ) != 0 )
209                 {
210                     last_err_msg = "Transmit buffer exhausted";
211                     HandleTxErrors( xemacpsif );
212                 }
213 
214                 if( ( ErrorWord & XEMACPS_TXSR_RXOVR_MASK ) != 0 )
215                 {
216                     last_err_msg = "Transmit retry excessed limits";
217                     HandleTxErrors( xemacpsif );
218                 }
219 
220                 if( ( ErrorWord & XEMACPS_TXSR_FRAMERX_MASK ) != 0 )
221                 {
222                     last_err_msg = "Transmit collision";
223                     emacps_check_tx( xemacpsif );
224                 }
225 
226                 break;
227         }
228     }
229 
230     /* Break on this statement and inspect error_msg if you like */
231     if( last_err_msg != NULL )
232     {
233         error_msg_count++;
234         FreeRTOS_printf( ( "emacps_handle_error: %s\n", last_err_msg ) );
235     }
236 }
237 
HandleTxErrors(xemacpsif_s * xemacpsif)238 void HandleTxErrors( xemacpsif_s * xemacpsif )
239 {
240     u32 netctrlreg;
241 
242     /*taskENTER_CRITICAL() */
243     {
244         netctrlreg = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress,
245                                       XEMACPS_NWCTRL_OFFSET );
246         netctrlreg = netctrlreg & ( ~XEMACPS_NWCTRL_TXEN_MASK );
247         XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress,
248                           XEMACPS_NWCTRL_OFFSET, netctrlreg );
249 
250         clean_dma_txdescs( xemacpsif );
251         netctrlreg = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress,
252                                       XEMACPS_NWCTRL_OFFSET );
253         netctrlreg = netctrlreg | ( XEMACPS_NWCTRL_TXEN_MASK );
254         XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress,
255                           XEMACPS_NWCTRL_OFFSET, netctrlreg );
256     }
257     /*taskEXIT_CRITICAL( ); */
258 }
259