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