]> git.sur5r.net Git - freertos/blob
689c39675ad9711962e8ba6f9a8d6f127656d35a
[freertos] /
1 /******************************************************************************
2 *
3 * Copyright (C) 2004 - 2014 Xilinx, Inc.  All rights reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 *
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
30 *
31 ******************************************************************************/
32 /*****************************************************************************/
33 /**
34 *
35 * @file xemaclite_l.c
36 *
37 * This file contains the minimal, polled functions to send and receive Ethernet
38 * frames.
39 *
40 * Refer to xemaclite.h for more details.
41 *
42 * <pre>
43 * MODIFICATION HISTORY:
44 *
45 * Ver   Who  Date     Changes
46 * ----- ---- -------- -----------------------------------------------
47 * 1.00a ecm  06/01/02 First release
48 * 1.01a ecm  03/31/04 Additional functionality and the _AlignedRead and
49 *                     _AlignedWrite functions.
50 * 1.11a mta  03/21/07 Updated to new coding style
51 * 2.01a ktn  07/20/09 Updated the XEmacLite_AlignedWrite and
52 *                     XEmacLite_AlignedRead functions to use volatile
53 *                     variables so that they are not optimized.
54 * 3.00a ktn  10/22/09 The macros have been renamed to remove _m from the name.
55 *
56 * </pre>
57 *
58 ******************************************************************************/
59
60 /***************************** Include Files *********************************/
61
62 #include "xil_types.h"
63 #include "xil_assert.h"
64 #include "xemaclite_l.h"
65 #include "xemaclite_i.h"
66
67 /************************** Constant Definitions *****************************/
68
69 /**************************** Type Definitions *******************************/
70
71 /***************** Macros (Inline Functions) Definitions *********************/
72
73 /************************** Function Prototypes ******************************/
74 void XEmacLite_AlignedWrite(void *SrcPtr, u32 *DestPtr, unsigned ByteCount);
75 void XEmacLite_AlignedRead(u32 *SrcPtr, void *DestPtr, unsigned ByteCount);
76
77 /************************** Variable Definitions *****************************/
78
79 /*****************************************************************************/
80 /**
81 *
82 * Send an Ethernet frame. The size is the total frame size, including header.
83 * This function blocks waiting for the frame to be transmitted.
84 *
85 * @param        BaseAddress is the base address of the device
86 * @param        FramePtr is a pointer to frame
87 * @param        ByteCount is the size, in bytes, of the frame
88 *
89 * @return       None.
90 *
91 * @note
92 *
93 * This function call is blocking in nature, i.e. it will wait until the
94 * frame is transmitted. This function can hang and not exit if the
95 * hardware is not configured properly.
96 *
97 * If the ping buffer is the destination of the data, the argument should be
98 * DeviceAddress + XEL_TXBUFF_OFFSET.
99 * If the pong buffer is the destination of the data, the argument should be
100 * DeviceAddress + XEL_TXBUFF_OFFSET + XEL_BUFFER_OFFSET.
101 * The function does not take the different buffers into consideration.
102 *
103 ******************************************************************************/
104 void XEmacLite_SendFrame(u32 BaseAddress, u8 *FramePtr, unsigned ByteCount)
105 {
106         u32 Register;
107
108         /*
109          * Write data to the EmacLite
110          */
111         XEmacLite_AlignedWrite(FramePtr, (u32 *) (BaseAddress), ByteCount);
112
113         /*
114          * The frame is in the buffer, now send it
115          */
116         XEmacLite_WriteReg(BaseAddress,  XEL_TPLR_OFFSET,
117                                 (ByteCount & (XEL_TPLR_LENGTH_MASK_HI |
118                                 XEL_TPLR_LENGTH_MASK_LO)));
119
120
121         Register = XEmacLite_GetTxStatus(BaseAddress);
122         XEmacLite_SetTxStatus(BaseAddress, Register | XEL_TSR_XMIT_BUSY_MASK);
123
124         /*
125          * Loop on the status waiting for the transmit to be complete.
126          */
127         while (!XEmacLite_IsTxDone(BaseAddress));
128
129 }
130
131
132 /*****************************************************************************/
133 /**
134 *
135 * Receive a frame. Wait for a frame to arrive.
136 *
137 * @param        BaseAddress is the base address of the device
138 * @param        FramePtr is a pointer to a buffer where the frame will
139 *               be stored.
140 *
141 * @return
142 *
143 * The type/length field of the frame received.  When the type/length field
144 * contains the type , XEL_MAX_FRAME_SIZE bytes will be copied out of the
145 * buffer and it is up to the higher layers to sort out the frame.
146 *
147 * @note
148 *
149 * This function call is blocking in nature, i.e. it will wait until a
150 * frame arrives.
151 *
152 * If the ping buffer is the source of the data, the argument should be
153 * DeviceAddress + XEL_RXBUFF_OFFSET.
154 * If the pong buffer is the source of the data, the argument should be
155 * DeviceAddress + XEL_RXBUFF_OFFSET + XEL_BUFFER_OFFSET.
156 * The function does not take the different buffers into consideration.
157 *
158 ******************************************************************************/
159 u16 XEmacLite_RecvFrame(u32 BaseAddress, u8 *FramePtr)
160 {
161         u16 LengthType;
162         u16 Length;
163         u32 Register;
164
165         /*
166          * Wait for a frame to arrive - this is a blocking call
167          */
168         while (XEmacLite_IsRxEmpty(BaseAddress));
169
170         /*
171          * Get the length of the frame that arrived, only 32-bit reads are
172          * allowed LengthType is in the upper half of the 32-bit word.
173          */
174         Register = XEmacLite_ReadReg(BaseAddress, XEL_RPLR_OFFSET);
175         LengthType = (u16) ((Register >> 16) &
176                             (XEL_RPLR_LENGTH_MASK_HI |
177                              XEL_RPLR_LENGTH_MASK_LO));
178
179         /*
180          * Check if length is valid
181          */
182         if (LengthType > XEL_MAX_FRAME_SIZE) {
183                 /*
184                  * Field contain type, use max frame size and
185                  * let user parse it
186                  */
187                 Length = XEL_MAX_FRAME_SIZE;
188         }
189         else {
190                 /*
191                  * Use the length in the frame, plus the header and trailer
192                  */
193                 Length = LengthType + XEL_HEADER_SIZE + XEL_FCS_SIZE;
194         }
195
196         /*
197          * Read each byte from the EmacLite
198          */
199         XEmacLite_AlignedRead((u32 *) (BaseAddress + XEL_RXBUFF_OFFSET),
200                               FramePtr, Length);
201
202         /*
203          * Acknowledge the frame
204          */
205         Register = XEmacLite_GetRxStatus(BaseAddress);
206         Register &= ~XEL_RSR_RECV_DONE_MASK;
207         XEmacLite_SetRxStatus(BaseAddress, Register);
208
209         return LengthType;
210 }
211
212 /******************************************************************************/
213 /**
214 *
215 * This function aligns the incoming data and writes it out to a 32-bit
216 * aligned destination address range.
217 *
218 * @param        SrcPtr is a pointer to incoming data of any alignment.
219 * @param        DestPtr is a pointer to outgoing data of 32-bit alignment.
220 * @param        ByteCount is the number of bytes to write.
221 *
222 * @return       None.
223 *
224 * @note         None.
225 *
226 ******************************************************************************/
227 void XEmacLite_AlignedWrite(void *SrcPtr, u32 *DestPtr, unsigned ByteCount)
228 {
229         unsigned Index;
230         unsigned Length = ByteCount;
231         volatile u32 AlignBuffer;
232         volatile u32 *To32Ptr;
233         u32 *From32Ptr;
234         volatile u16 *To16Ptr;
235         u16 *From16Ptr;
236         volatile u8 *To8Ptr;
237         u8 *From8Ptr;
238
239         To32Ptr = DestPtr;
240
241         if ((((u32) SrcPtr) & 0x00000003) == 0) {
242
243                 /*
244                  * Word aligned buffer, no correction needed.
245                  */
246                 From32Ptr = (u32 *) SrcPtr;
247
248                 while (Length > 3) {
249                         /*
250                          * Output each word destination.
251                          */
252                         *To32Ptr++ = *From32Ptr++;
253
254                         /*
255                          * Adjust length accordingly
256                          */
257                         Length -= 4;
258                 }
259
260                 /*
261                  * Set up to output the remaining data, zero the temp buffer
262                  first.
263                  */
264                 AlignBuffer = 0;
265                 To8Ptr = (u8 *) &AlignBuffer;
266                 From8Ptr = (u8 *) From32Ptr;
267
268         }
269         else if ((((u32) SrcPtr) & 0x00000001) != 0) {
270                 /*
271                  * Byte aligned buffer, correct.
272                  */
273                 AlignBuffer = 0;
274                 To8Ptr = (u8 *) &AlignBuffer;
275                 From8Ptr = (u8 *) SrcPtr;
276
277                 while (Length > 3) {
278                         /*
279                          * Copy each byte into the temporary buffer.
280                          */
281                         for (Index = 0; Index < 4; Index++) {
282                                 *To8Ptr++ = *From8Ptr++;
283                         }
284
285                         /*
286                          * Output the buffer
287                          */
288                         *To32Ptr++ = AlignBuffer;
289
290                         /*.
291                          * Reset the temporary buffer pointer and adjust length.
292                          */
293                         To8Ptr = (u8 *) &AlignBuffer;
294                         Length -= 4;
295                 }
296
297                 /*
298                  * Set up to output the remaining data, zero the temp buffer
299                  * first.
300                  */
301                 AlignBuffer = 0;
302                 To8Ptr = (u8 *) &AlignBuffer;
303
304         }
305         else {
306                 /*
307                  * Half-Word aligned buffer, correct.
308                  */
309                 AlignBuffer = 0;
310
311                 /*
312                  * This is a funny looking cast. The new gcc, version 3.3.x has
313                  * a strict cast check for 16 bit pointers, aka short pointers.
314                  * The following warning is issued if the initial 'void *' cast
315                  * is  not used:
316                  * 'dereferencing type-punned pointer will break strict-aliasing
317                  * rules'
318                  */
319
320                 To16Ptr = (u16 *) ((void *) &AlignBuffer);
321                 From16Ptr = (u16 *) SrcPtr;
322
323                 while (Length > 3) {
324                         /*
325                          * Copy each half word into the temporary buffer.
326                          */
327                         for (Index = 0; Index < 2; Index++) {
328                                 *To16Ptr++ = *From16Ptr++;
329                         }
330
331                         /*
332                          * Output the buffer.
333                          */
334                         *To32Ptr++ = AlignBuffer;
335
336                         /*
337                          * Reset the temporary buffer pointer and adjust length.
338                          */
339
340                         /*
341                          * This is a funny looking cast. The new gcc, version
342                          * 3.3.x has a strict cast check for 16 bit pointers,
343                          * aka short  pointers. The following warning is issued
344                          * if the initial 'void *' cast is not used:
345                          * 'dereferencing type-punned pointer will break
346                          * strict-aliasing  rules'
347                          */
348                         To16Ptr = (u16 *) ((void *) &AlignBuffer);
349                         Length -= 4;
350                 }
351
352                 /*
353                  * Set up to output the remaining data, zero the temp buffer
354                  * first.
355                  */
356                 AlignBuffer = 0;
357                 To8Ptr = (u8 *) &AlignBuffer;
358                 From8Ptr = (u8 *) From16Ptr;
359         }
360
361         /*
362          * Output the remaining data, zero the temp buffer first.
363          */
364         for (Index = 0; Index < Length; Index++) {
365                 *To8Ptr++ = *From8Ptr++;
366         }
367
368         *To32Ptr++ = AlignBuffer;
369
370 }
371
372 /******************************************************************************/
373 /**
374 *
375 * This function reads from a 32-bit aligned source address range and aligns
376 * the writes to the provided destination pointer alignment.
377 *
378 * @param        SrcPtr is a pointer to incoming data of 32-bit alignment.
379 * @param        DestPtr is a pointer to outgoing data of any alignment.
380 * @param        ByteCount is the number of bytes to read.
381 *
382 * @return       None.
383 *
384 * @note         None.
385 *
386 ******************************************************************************/
387 void XEmacLite_AlignedRead(u32 *SrcPtr, void *DestPtr, unsigned ByteCount)
388 {
389         unsigned Index;
390         unsigned Length = ByteCount;
391         volatile u32 AlignBuffer;
392         u32 *To32Ptr;
393         volatile u32 *From32Ptr;
394         u16 *To16Ptr;
395         volatile u16 *From16Ptr;
396         u8 *To8Ptr;
397         volatile u8 *From8Ptr;
398
399         From32Ptr = (u32 *) SrcPtr;
400
401         if ((((u32) DestPtr) & 0x00000003) == 0) {
402
403                 /*
404                  * Word aligned buffer, no correction needed.
405                  */
406                 To32Ptr = (u32 *) DestPtr;
407
408                 while (Length > 3) {
409                         /*
410                          * Output each word.
411                          */
412                         *To32Ptr++ = *From32Ptr++;
413
414                         /*
415                          * Adjust length accordingly.
416                          */
417                         Length -= 4;
418                 }
419
420                 /*
421                  * Set up to read the remaining data.
422                  */
423                 To8Ptr = (u8 *) To32Ptr;
424
425         }
426         else if ((((u32) DestPtr) & 0x00000001) != 0) {
427                 /*
428                  * Byte aligned buffer, correct.
429                  */
430                 To8Ptr = (u8 *) DestPtr;
431
432                 while (Length > 3) {
433                         /*
434                          * Copy each word into the temporary buffer.
435                          */
436                         AlignBuffer = *From32Ptr++;
437                         From8Ptr = (u8 *) &AlignBuffer;
438
439                         /*
440                          * Write data to destination.
441                          */
442                         for (Index = 0; Index < 4; Index++) {
443                                 *To8Ptr++ = *From8Ptr++;
444                         }
445
446                         /*
447                          * Adjust length
448                          */
449                         Length -= 4;
450                 }
451
452         }
453         else {
454                 /*
455                  * Half-Word aligned buffer, correct.
456                  */
457                 To16Ptr = (u16 *) DestPtr;
458
459                 while (Length > 3) {
460                         /*
461                          * Copy each word into the temporary buffer.
462                          */
463                         AlignBuffer = *From32Ptr++;
464
465                         /*
466                          * This is a funny looking cast. The new gcc, version
467                          * 3.3.x has a strict cast check for 16 bit pointers,
468                          * aka short pointers. The following warning is issued
469                          * if the initial 'void *' cast is not used:
470                          * 'dereferencing type-punned pointer will break
471                          *  strict-aliasing rules'
472                          */
473                         From16Ptr = (u16 *) ((void *) &AlignBuffer);
474
475                         /*
476                          * Write data to destination.
477                          */
478                         for (Index = 0; Index < 2; Index++) {
479                                 *To16Ptr++ = *From16Ptr++;
480                         }
481
482                         /*
483                          * Adjust length.
484                          */
485                         Length -= 4;
486                 }
487
488                 /*
489                  * Set up to read the remaining data.
490                  */
491                 To8Ptr = (u8 *) To16Ptr;
492         }
493
494         /*
495          * Read the remaining data.
496          */
497         AlignBuffer = *From32Ptr++;
498         From8Ptr = (u8 *) &AlignBuffer;
499
500         for (Index = 0; Index < Length; Index++) {
501                 *To8Ptr++ = *From8Ptr++;
502         }
503 }