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