1 /******************************************************************************
3 * Copyright (C) 2004 - 2014 Xilinx, Inc. All rights reserved.
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:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
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.
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
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.
31 ******************************************************************************/
32 /*****************************************************************************/
37 * This file contains the minimal, polled functions to send and receive Ethernet
40 * Refer to xemaclite.h for more details.
43 * MODIFICATION HISTORY:
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.
58 ******************************************************************************/
60 /***************************** Include Files *********************************/
62 #include "xil_types.h"
63 #include "xil_assert.h"
64 #include "xemaclite_l.h"
65 #include "xemaclite_i.h"
67 /************************** Constant Definitions *****************************/
69 /**************************** Type Definitions *******************************/
71 /***************** Macros (Inline Functions) Definitions *********************/
73 /************************** Function Prototypes ******************************/
74 void XEmacLite_AlignedWrite(void *SrcPtr, u32 *DestPtr, unsigned ByteCount);
75 void XEmacLite_AlignedRead(u32 *SrcPtr, void *DestPtr, unsigned ByteCount);
77 /************************** Variable Definitions *****************************/
79 /*****************************************************************************/
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.
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
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.
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.
103 ******************************************************************************/
104 void XEmacLite_SendFrame(u32 BaseAddress, u8 *FramePtr, unsigned ByteCount)
109 * Write data to the EmacLite
111 XEmacLite_AlignedWrite(FramePtr, (u32 *) (BaseAddress), ByteCount);
114 * The frame is in the buffer, now send it
116 XEmacLite_WriteReg(BaseAddress, XEL_TPLR_OFFSET,
117 (ByteCount & (XEL_TPLR_LENGTH_MASK_HI |
118 XEL_TPLR_LENGTH_MASK_LO)));
121 Register = XEmacLite_GetTxStatus(BaseAddress);
122 XEmacLite_SetTxStatus(BaseAddress, Register | XEL_TSR_XMIT_BUSY_MASK);
125 * Loop on the status waiting for the transmit to be complete.
127 while (!XEmacLite_IsTxDone(BaseAddress));
132 /*****************************************************************************/
135 * Receive a frame. Wait for a frame to arrive.
137 * @param BaseAddress is the base address of the device
138 * @param FramePtr is a pointer to a buffer where the frame will
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.
149 * This function call is blocking in nature, i.e. it will wait until a
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.
158 ******************************************************************************/
159 u16 XEmacLite_RecvFrame(u32 BaseAddress, u8 *FramePtr)
166 * Wait for a frame to arrive - this is a blocking call
168 while (XEmacLite_IsRxEmpty(BaseAddress));
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.
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));
180 * Check if length is valid
182 if (LengthType > XEL_MAX_FRAME_SIZE) {
184 * Field contain type, use max frame size and
187 Length = XEL_MAX_FRAME_SIZE;
191 * Use the length in the frame, plus the header and trailer
193 Length = LengthType + XEL_HEADER_SIZE + XEL_FCS_SIZE;
197 * Read each byte from the EmacLite
199 XEmacLite_AlignedRead((u32 *) (BaseAddress + XEL_RXBUFF_OFFSET),
203 * Acknowledge the frame
205 Register = XEmacLite_GetRxStatus(BaseAddress);
206 Register &= ~XEL_RSR_RECV_DONE_MASK;
207 XEmacLite_SetRxStatus(BaseAddress, Register);
212 /******************************************************************************/
215 * This function aligns the incoming data and writes it out to a 32-bit
216 * aligned destination address range.
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.
226 ******************************************************************************/
227 void XEmacLite_AlignedWrite(void *SrcPtr, u32 *DestPtr, unsigned ByteCount)
230 unsigned Length = ByteCount;
231 volatile u32 AlignBuffer;
232 volatile u32 *To32Ptr;
234 volatile u16 *To16Ptr;
241 if ((((u32) SrcPtr) & 0x00000003) == 0) {
244 * Word aligned buffer, no correction needed.
246 From32Ptr = (u32 *) SrcPtr;
250 * Output each word destination.
252 *To32Ptr++ = *From32Ptr++;
255 * Adjust length accordingly
261 * Set up to output the remaining data, zero the temp buffer
265 To8Ptr = (u8 *) &AlignBuffer;
266 From8Ptr = (u8 *) From32Ptr;
269 else if ((((u32) SrcPtr) & 0x00000001) != 0) {
271 * Byte aligned buffer, correct.
274 To8Ptr = (u8 *) &AlignBuffer;
275 From8Ptr = (u8 *) SrcPtr;
279 * Copy each byte into the temporary buffer.
281 for (Index = 0; Index < 4; Index++) {
282 *To8Ptr++ = *From8Ptr++;
288 *To32Ptr++ = AlignBuffer;
291 * Reset the temporary buffer pointer and adjust length.
293 To8Ptr = (u8 *) &AlignBuffer;
298 * Set up to output the remaining data, zero the temp buffer
302 To8Ptr = (u8 *) &AlignBuffer;
307 * Half-Word aligned buffer, correct.
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
316 * 'dereferencing type-punned pointer will break strict-aliasing
320 To16Ptr = (u16 *) ((void *) &AlignBuffer);
321 From16Ptr = (u16 *) SrcPtr;
325 * Copy each half word into the temporary buffer.
327 for (Index = 0; Index < 2; Index++) {
328 *To16Ptr++ = *From16Ptr++;
334 *To32Ptr++ = AlignBuffer;
337 * Reset the temporary buffer pointer and adjust length.
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'
348 To16Ptr = (u16 *) ((void *) &AlignBuffer);
353 * Set up to output the remaining data, zero the temp buffer
357 To8Ptr = (u8 *) &AlignBuffer;
358 From8Ptr = (u8 *) From16Ptr;
362 * Output the remaining data, zero the temp buffer first.
364 for (Index = 0; Index < Length; Index++) {
365 *To8Ptr++ = *From8Ptr++;
368 *To32Ptr++ = AlignBuffer;
372 /******************************************************************************/
375 * This function reads from a 32-bit aligned source address range and aligns
376 * the writes to the provided destination pointer alignment.
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.
386 ******************************************************************************/
387 void XEmacLite_AlignedRead(u32 *SrcPtr, void *DestPtr, unsigned ByteCount)
390 unsigned Length = ByteCount;
391 volatile u32 AlignBuffer;
393 volatile u32 *From32Ptr;
395 volatile u16 *From16Ptr;
397 volatile u8 *From8Ptr;
399 From32Ptr = (u32 *) SrcPtr;
401 if ((((u32) DestPtr) & 0x00000003) == 0) {
404 * Word aligned buffer, no correction needed.
406 To32Ptr = (u32 *) DestPtr;
412 *To32Ptr++ = *From32Ptr++;
415 * Adjust length accordingly.
421 * Set up to read the remaining data.
423 To8Ptr = (u8 *) To32Ptr;
426 else if ((((u32) DestPtr) & 0x00000001) != 0) {
428 * Byte aligned buffer, correct.
430 To8Ptr = (u8 *) DestPtr;
434 * Copy each word into the temporary buffer.
436 AlignBuffer = *From32Ptr++;
437 From8Ptr = (u8 *) &AlignBuffer;
440 * Write data to destination.
442 for (Index = 0; Index < 4; Index++) {
443 *To8Ptr++ = *From8Ptr++;
455 * Half-Word aligned buffer, correct.
457 To16Ptr = (u16 *) DestPtr;
461 * Copy each word into the temporary buffer.
463 AlignBuffer = *From32Ptr++;
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'
473 From16Ptr = (u16 *) ((void *) &AlignBuffer);
476 * Write data to destination.
478 for (Index = 0; Index < 2; Index++) {
479 *To16Ptr++ = *From16Ptr++;
489 * Set up to read the remaining data.
491 To8Ptr = (u8 *) To16Ptr;
495 * Read the remaining data.
497 AlignBuffer = *From32Ptr++;
498 From8Ptr = (u8 *) &AlignBuffer;
500 for (Index = 0; Index < Length; Index++) {
501 *To8Ptr++ = *From8Ptr++;