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_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