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 "FreeRTOS_Routing.h"
35 #include "NetworkBufferManagement.h"
36 #include "NetworkInterface.h"
37
38 #include "Zynq/x_emacpsif.h"
39
40 extern TaskHandle_t xEMACTaskHandles[ XPAR_XEMACPS_NUM_INSTANCES ];
41
42 /*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c
43 *** to run it on a PEEP board
44 ***/
45
setup_isr(xemacpsif_s * xemacpsif)46 void setup_isr( xemacpsif_s * xemacpsif )
47 {
48 /*
49 * Setup callbacks
50 */
51 XEmacPs_SetHandler( &xemacpsif->emacps, XEMACPS_HANDLER_DMASEND,
52 ( void * ) emacps_send_handler,
53 ( void * ) xemacpsif );
54
55 XEmacPs_SetHandler( &xemacpsif->emacps, XEMACPS_HANDLER_DMARECV,
56 ( void * ) emacps_recv_handler,
57 ( void * ) xemacpsif );
58
59 XEmacPs_SetHandler( &xemacpsif->emacps, XEMACPS_HANDLER_ERROR,
60 ( void * ) emacps_error_handler,
61 ( void * ) xemacpsif );
62 }
63
start_emacps(xemacpsif_s * xemacps)64 void start_emacps( xemacpsif_s * xemacps )
65 {
66 /* start the temac */
67 XEmacPs_Start( &xemacps->emacps );
68 }
69
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 BaseType_t xEMACIndex;
92
93 xemacpsif = ( xemacpsif_s * ) ( arg );
94 xEMACIndex = xemacpsif->emacps.Config.DeviceId;
95
96 if( ( Direction != XEMACPS_SEND ) || ( ErrorWord != XEMACPS_TXSR_USEDREAD_MASK ) )
97 {
98 if( ++xNextHead == ( sizeof( xErrorList ) / sizeof( xErrorList[ 0 ] ) ) )
99 {
100 xNextHead = 0;
101 }
102
103 if( xNextHead != xErrorTail )
104 {
105 xErrorList[ xErrorHead ].arg = arg;
106 xErrorList[ xErrorHead ].Direction = Direction;
107 xErrorList[ xErrorHead ].ErrorWord = ErrorWord;
108
109 xErrorHead = xNextHead;
110
111 xemacpsif = ( xemacpsif_s * ) ( arg );
112 xemacpsif->isr_events |= EMAC_IF_ERR_EVENT;
113 }
114
115 if( xEMACTaskHandles[ xEMACIndex ] != NULL )
116 {
117 vTaskNotifyGiveFromISR( xEMACTaskHandles[ xEMACIndex ], &xHigherPriorityTaskWoken );
118 }
119 }
120
121 portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
122 }
123
124 static void emacps_handle_error( void * arg,
125 u8 Direction,
126 u32 ErrorWord );
127
emacps_check_errors(xemacpsif_s * xemacps)128 int emacps_check_errors( xemacpsif_s * xemacps )
129 {
130 int xResult;
131
132 ( void ) xemacps;
133
134 if( xErrorHead == xErrorTail )
135 {
136 xResult = 0;
137 }
138 else
139 {
140 xResult = 1;
141 emacps_handle_error(
142 xErrorList[ xErrorTail ].arg,
143 xErrorList[ xErrorTail ].Direction,
144 xErrorList[ xErrorTail ].ErrorWord );
145 }
146
147 return xResult;
148 }
149
emacps_handle_error(void * arg,u8 Direction,u32 ErrorWord)150 static void emacps_handle_error( void * arg,
151 u8 Direction,
152 u32 ErrorWord )
153 {
154 xemacpsif_s * xemacpsif;
155 XEmacPs * xemacps;
156 BaseType_t xEMACIndex;
157
158 xemacpsif = ( xemacpsif_s * ) ( arg );
159
160 xemacps = &xemacpsif->emacps;
161 xEMACIndex = xemacps->Config.DeviceId;
162
163 last_err_msg = NULL;
164
165 if( ErrorWord != 0 )
166 {
167 switch( Direction )
168 {
169 case XEMACPS_RECV:
170
171 if( ( ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK ) != 0 )
172 {
173 last_err_msg = "Receive DMA error";
174 vInitialiseOnIndex( xEMACIndex );
175 }
176
177 if( ( ErrorWord & XEMACPS_RXSR_RXOVR_MASK ) != 0 )
178 {
179 last_err_msg = "Receive over run";
180 emacps_recv_handler( arg );
181 }
182
183 if( ( ErrorWord & XEMACPS_RXSR_BUFFNA_MASK ) != 0 )
184 {
185 last_err_msg = "Receive buffer not available";
186 emacps_recv_handler( arg );
187 }
188
189 break;
190
191 case XEMACPS_SEND:
192
193 if( ( ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK ) != 0 )
194 {
195 last_err_msg = "Transmit DMA error";
196 vInitialiseOnIndex( xEMACIndex );
197 }
198
199 if( ( ErrorWord & XEMACPS_TXSR_URUN_MASK ) != 0 )
200 {
201 last_err_msg = "Transmit under run";
202 HandleTxErrors( xemacpsif );
203 }
204
205 if( ( ErrorWord & XEMACPS_TXSR_BUFEXH_MASK ) != 0 )
206 {
207 last_err_msg = "Transmit buffer exhausted";
208 HandleTxErrors( xemacpsif );
209 }
210
211 if( ( ErrorWord & XEMACPS_TXSR_RXOVR_MASK ) != 0 )
212 {
213 last_err_msg = "Transmit retry excessed limits";
214 HandleTxErrors( xemacpsif );
215 }
216
217 if( ( ErrorWord & XEMACPS_TXSR_FRAMERX_MASK ) != 0 )
218 {
219 last_err_msg = "Transmit collision";
220 emacps_check_tx( xemacpsif );
221 }
222
223 break;
224 }
225 }
226
227 /* Break on this statement and inspect error_msg if you like */
228 if( last_err_msg != NULL )
229 {
230 error_msg_count++;
231 FreeRTOS_printf( ( "emacps_handle_error: %s\n", last_err_msg ) );
232 }
233 }
234
HandleTxErrors(xemacpsif_s * xemacpsif)235 void HandleTxErrors( xemacpsif_s * xemacpsif )
236 {
237 u32 netctrlreg;
238
239 /*taskENTER_CRITICAL() */
240 {
241 netctrlreg = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress,
242 XEMACPS_NWCTRL_OFFSET );
243 netctrlreg = netctrlreg & ( ~XEMACPS_NWCTRL_TXEN_MASK );
244 XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress,
245 XEMACPS_NWCTRL_OFFSET, netctrlreg );
246
247 clean_dma_txdescs( xemacpsif );
248 netctrlreg = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress,
249 XEMACPS_NWCTRL_OFFSET );
250 netctrlreg = netctrlreg | ( XEMACPS_NWCTRL_TXEN_MASK );
251 XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress,
252 XEMACPS_NWCTRL_OFFSET, netctrlreg );
253 }
254 /*taskEXIT_CRITICAL( ); */
255 }
256