]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/MicroBlaze_Kintex7_EthernetLite/BSP/microblaze_0/libsrc/emaclite_v4_0/src/xemaclite.c
Common scheduler code:
[freertos] / FreeRTOS / Demo / MicroBlaze_Kintex7_EthernetLite / BSP / microblaze_0 / libsrc / emaclite_v4_0 / src / xemaclite.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.c
36 *
37 * Functions in this file are the minimum required functions for the EmacLite
38 * driver. See xemaclite.h for a detailed description of the driver.
39 *
40 * <pre>
41 * MODIFICATION HISTORY:
42 *
43 * Ver   Who  Date     Changes
44 * ----- ---- -------- --------------------------------------------------------
45 * 1.01a ecm  01/31/04 First release
46 * 1.11a mta  03/21/07 Updated to new coding style
47 * 1.11a ecm  05/18/07 Updated the TxBufferAvailable routine to look at both
48 *                     the active and busy bits
49 * 1.13a sv   02/1/08  Updated the TxBufferAvailable routine to return
50 *                     busy status properly
51 * 2.00a ktn  02/16/09 Added support for MDIO
52 * 2.01a ktn  07/20/09 Modified XEmacLite_Send function to use Ping buffers
53 *                     Interrupt enable bit since this alone is used to enable
54 *                     the interrupts for both Ping and Pong Buffers.
55 * 3.00a ktn  10/22/09 Updated driver to use the HAL APIs/macros.
56 *                     The macros have been renamed to remove _m from the name.
57 * 3.01a ktn  07/08/10 The macro XEmacLite_GetReceiveDataLength is changed to
58 *                     a static function.
59 *                     Updated the XEmacLite_GetReceiveDataLength and
60 *                     XEmacLite_Recv functions to support little endian
61 *                     MicroBlaze.
62 * 3.02a sdm  07/22/11 Removed redundant code in XEmacLite_Recv functions for
63 *                     CR617290
64 * 3.04a srt  04/13/13 Removed warnings (CR 705000).
65 *
66 * </pre>
67 ******************************************************************************/
68
69 /***************************** Include Files *********************************/
70
71 #include "xil_io.h"
72 #include "xenv.h"
73 #include "xemaclite.h"
74 #include "xemaclite_i.h"
75
76 /************************** Constant Definitions *****************************/
77
78 /**************************** Type Definitions *******************************/
79
80 /***************** Macros (Inline Functions) Definitions *********************/
81
82
83 /************************** Function Prototypes ******************************/
84
85 static u16 XEmacLite_GetReceiveDataLength(u32 BaseAddress);
86
87 /************************** Variable Definitions *****************************/
88
89 /*****************************************************************************/
90 /**
91 *
92 * Initialize a specific XEmacLite instance/driver.  The initialization entails:
93 * - Initialize fields of the XEmacLite instance structure.
94 *
95 * The driver defaults to polled mode operation.
96 *
97 * @param        InstancePtr is a pointer to the XEmacLite instance.
98 * @param        EmacLiteConfigPtr points to the XEmacLite device configuration
99 *               structure.
100 * @param        EffectiveAddr is the device base address in the virtual memory
101 *               address space. If the address translation is not used then the
102 *               physical address is passed.
103 *               Unexpected errors may occur if the address mapping is changed
104 *               after this function is invoked.
105 *
106 * @return
107 *               - XST_SUCCESS if initialization was successful.
108 *
109 * @note         The initialization of the PHY device is not done in this
110 *               function. The user needs to use XEmacLite_PhyRead and
111 *               XEmacLite_PhyWrite functions to access the PHY device.
112 *
113 ******************************************************************************/
114 int XEmacLite_CfgInitialize(XEmacLite *InstancePtr,
115                                 XEmacLite_Config *EmacLiteConfigPtr,
116                                 u32 EffectiveAddr)
117 {
118
119         /*
120          * Verify that each of the inputs are valid.
121          */
122         Xil_AssertNonvoid(InstancePtr != NULL);
123         Xil_AssertNonvoid(EmacLiteConfigPtr != NULL);
124
125         /*
126          * Zero the provided instance memory.
127          */
128         memset(InstancePtr, 0, sizeof(XEmacLite));
129
130         /*
131          * Set some default values for instance data, don't indicate the device
132          * is ready to use until everything has been initialized successfully.
133          */
134         InstancePtr->EmacLiteConfig.BaseAddress = EffectiveAddr;
135         InstancePtr->EmacLiteConfig.DeviceId = EmacLiteConfigPtr->DeviceId;
136         InstancePtr->EmacLiteConfig.TxPingPong = EmacLiteConfigPtr->TxPingPong;
137         InstancePtr->EmacLiteConfig.RxPingPong = EmacLiteConfigPtr->RxPingPong;
138         InstancePtr->EmacLiteConfig.MdioInclude = EmacLiteConfigPtr->MdioInclude;
139         InstancePtr->EmacLiteConfig.Loopback = EmacLiteConfigPtr->Loopback;
140
141         InstancePtr->NextTxBufferToUse = 0x0;
142         InstancePtr->NextRxBufferToUse = 0x0;
143         InstancePtr->RecvHandler = (XEmacLite_Handler) StubHandler;
144         InstancePtr->SendHandler = (XEmacLite_Handler) StubHandler;
145
146         /*
147          * Clear the TX CSR's in case this is a restart.
148          */
149         XEmacLite_WriteReg(InstancePtr->EmacLiteConfig.BaseAddress,
150                                 XEL_TSR_OFFSET, 0);
151         XEmacLite_WriteReg(InstancePtr->EmacLiteConfig.BaseAddress,
152                                 XEL_BUFFER_OFFSET + XEL_TSR_OFFSET, 0);
153
154         /*
155          * Since there were no failures, indicate the device is ready to use.
156          */
157         InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
158
159         return XST_SUCCESS;
160 }
161
162 /*****************************************************************************/
163 /**
164 *
165 * Send an Ethernet frame. The ByteCount is the total frame size, including
166 * header.
167 *
168 * @param        InstancePtr is a pointer to the XEmacLite instance.
169 * @param        FramePtr is a pointer to frame. For optimal performance, a
170 *               32-bit aligned buffer should be used but it is not required, the
171 *               function will align the data if necessary.
172 * @param        ByteCount is the size, in bytes, of the frame
173 *
174 * @return
175 *               - XST_SUCCESS if data was transmitted.
176 *               - XST_FAILURE if buffer(s) was (were) full and no valid data was
177 *               transmitted.
178 *
179 * @note
180 *
181 * This function call is not blocking in nature, i.e. it will not wait until the
182 * frame is transmitted.
183 *
184 ******************************************************************************/
185 int XEmacLite_Send(XEmacLite *InstancePtr, u8 *FramePtr, unsigned ByteCount)
186 {
187         u32 Register;
188         u32 BaseAddress;
189         u32 EmacBaseAddress;
190         u32 IntrEnableStatus;
191
192         /*
193          * Verify that each of the inputs are valid.
194          */
195         Xil_AssertNonvoid(InstancePtr != NULL);
196
197         /*
198          * Determine the expected TX buffer address.
199          */
200         BaseAddress = XEmacLite_NextTransmitAddr(InstancePtr);
201         EmacBaseAddress = InstancePtr->EmacLiteConfig.BaseAddress;
202
203         /*
204          * Check the Length if it is too large, truncate it.
205          * The maximum Tx packet size is
206          * Ethernet header (14 Bytes) + Maximum MTU (1500 bytes).
207          */
208         if (ByteCount > XEL_MAX_TX_FRAME_SIZE) {
209
210                 ByteCount = XEL_MAX_TX_FRAME_SIZE;
211         }
212
213         /*
214          * Determine if the expected buffer address is empty.
215          */
216         Register = XEmacLite_GetTxStatus(BaseAddress);
217
218         /*
219          * If the expected buffer is available, fill it with the provided data
220          * Align if necessary.
221          */
222         if ((Register & (XEL_TSR_XMIT_BUSY_MASK |
223                         XEL_TSR_XMIT_ACTIVE_MASK)) == 0) {
224
225                 /*
226                  * Switch to next buffer if configured.
227                  */
228                 if (InstancePtr->EmacLiteConfig.TxPingPong != 0) {
229                         InstancePtr->NextTxBufferToUse ^= XEL_BUFFER_OFFSET;
230                 }
231
232                 /*
233                  * Write the frame to the buffer.
234                  */
235                 XEmacLite_AlignedWrite(FramePtr, (u32 *) BaseAddress,
236                                        ByteCount);
237
238
239                 /*
240                  * The frame is in the buffer, now send it.
241                  */
242                 XEmacLite_WriteReg(BaseAddress, XEL_TPLR_OFFSET,
243                                         (ByteCount & (XEL_TPLR_LENGTH_MASK_HI |
244                                         XEL_TPLR_LENGTH_MASK_LO)));
245
246                 /*
247                  * Update the Tx Status Register to indicate that there is a
248                  * frame to send.
249                  * If the interrupt enable bit of Ping buffer(since this
250                  * controls both the buffers) is enabled then set the
251                  * XEL_TSR_XMIT_ACTIVE_MASK flag which is used by the interrupt
252                  * handler to call the callback function provided by the user
253                  * to indicate that the frame has been transmitted.
254                  */
255                 Register = XEmacLite_GetTxStatus(BaseAddress);
256                 Register |= XEL_TSR_XMIT_BUSY_MASK;
257                 IntrEnableStatus = XEmacLite_GetTxStatus(EmacBaseAddress);
258                 if ((IntrEnableStatus & XEL_TSR_XMIT_IE_MASK) != 0) {
259                         Register |= XEL_TSR_XMIT_ACTIVE_MASK;
260                 }
261                 XEmacLite_SetTxStatus(BaseAddress, Register);
262
263                 return XST_SUCCESS;
264         }
265
266         /*
267          * If the expected buffer was full, try the other buffer if configured.
268          */
269         if (InstancePtr->EmacLiteConfig.TxPingPong != 0) {
270
271                 BaseAddress ^= XEL_BUFFER_OFFSET;
272
273                 /*
274                  * Determine if the expected buffer address is empty.
275                  */
276                 Register = XEmacLite_GetTxStatus(BaseAddress);
277
278                 /*
279                  * If the next buffer is available, fill it with the provided
280                  * data.
281                  */
282                 if ((Register & (XEL_TSR_XMIT_BUSY_MASK |
283                                 XEL_TSR_XMIT_ACTIVE_MASK)) == 0) {
284
285                         /*
286                          * Write the frame to the buffer.
287                          */
288                         XEmacLite_AlignedWrite(FramePtr, (u32 *) BaseAddress,
289                                                ByteCount);
290
291                         /*
292                          * The frame is in the buffer, now send it.
293                          */
294                         XEmacLite_WriteReg(BaseAddress, XEL_TPLR_OFFSET,
295                                         (ByteCount & (XEL_TPLR_LENGTH_MASK_HI |
296                                            XEL_TPLR_LENGTH_MASK_LO)));
297
298                         /*
299                          * Update the Tx Status Register to indicate that there
300                          * is a frame to send.
301                          * If the interrupt enable bit of Ping buffer(since this
302                          * controls both the buffers) is enabled then set the
303                          * XEL_TSR_XMIT_ACTIVE_MASK flag which is used by the
304                          * interrupt handler to call the callback function
305                          * provided by the user to indicate that the frame has
306                          * been transmitted.
307                          */
308                         Register = XEmacLite_GetTxStatus(BaseAddress);
309                         Register |= XEL_TSR_XMIT_BUSY_MASK;
310                         IntrEnableStatus =
311                                         XEmacLite_GetTxStatus(EmacBaseAddress);
312                         if ((IntrEnableStatus & XEL_TSR_XMIT_IE_MASK) != 0) {
313                                 Register |= XEL_TSR_XMIT_ACTIVE_MASK;
314                         }
315                         XEmacLite_SetTxStatus(BaseAddress, Register);
316
317                         /*
318                          * Do not switch to next buffer, there is a sync problem
319                          * and the expected buffer should not change.
320                          */
321                         return XST_SUCCESS;
322                 }
323         }
324
325
326         /*
327          * Buffer(s) was(were) full, return failure to allow for polling usage.
328          */
329         return XST_FAILURE;
330 }
331
332 /*****************************************************************************/
333 /**
334 *
335 * Receive a frame. Intended to be called from the interrupt context or
336 * with a wrapper which waits for the receive frame to be available.
337 *
338 * @param        InstancePtr is a pointer to the XEmacLite instance.
339 * @param        FramePtr is a pointer to a buffer where the frame will
340 *               be stored. The buffer must be at least XEL_MAX_FRAME_SIZE bytes.
341 *               For optimal performance, a 32-bit aligned buffer should be used
342 *               but it is not required, the function will align the data if
343 *               necessary.
344 *
345 * @return
346 *
347 * The type/length field of the frame received.  When the type/length field
348 * contains the type, XEL_MAX_FRAME_SIZE bytes will be copied out of the
349 * buffer and it is up to the higher layers to sort out the frame.
350 * Function returns 0 if there is no data waiting in the receive buffer or
351 * the pong buffer if configured.
352 *
353 * @note
354 *
355 * This function call is not blocking in nature, i.e. it will not wait until
356 * a frame arrives.
357 *
358 ******************************************************************************/
359 u16 XEmacLite_Recv(XEmacLite *InstancePtr, u8 *FramePtr)
360 {
361         u16 LengthType;
362         u16 Length;
363         u32 Register;
364         u32 BaseAddress;
365
366         /*
367          * Verify that each of the inputs are valid.
368          */
369
370         Xil_AssertNonvoid(InstancePtr != NULL);
371
372         /*
373          * Determine the expected buffer address.
374          */
375         BaseAddress = XEmacLite_NextReceiveAddr(InstancePtr);
376
377         /*
378          * Verify which buffer has valid data.
379          */
380         Register = XEmacLite_GetRxStatus(BaseAddress);
381
382         if ((Register & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
383
384                 /*
385                  * The driver is in sync, update the next expected buffer if
386                  * configured.
387                  */
388
389                 if (InstancePtr->EmacLiteConfig.RxPingPong != 0) {
390                         InstancePtr->NextRxBufferToUse ^= XEL_BUFFER_OFFSET;
391                 }
392         }
393         else {
394                 /*
395                  * The instance is out of sync, try other buffer if other
396                  * buffer is configured, return 0 otherwise. If the instance is
397                  * out of sync, do not update the 'NextRxBufferToUse' since it
398                  * will correct on subsequent calls.
399                  */
400                 if (InstancePtr->EmacLiteConfig.RxPingPong != 0) {
401                         BaseAddress ^= XEL_BUFFER_OFFSET;
402                 }
403                 else {
404                         return 0;       /* No data was available */
405                 }
406
407                 /*
408                  * Verify that buffer has valid data.
409                  */
410                 Register = XEmacLite_GetRxStatus(BaseAddress);
411                 if ((Register & XEL_RSR_RECV_DONE_MASK) !=
412                                 XEL_RSR_RECV_DONE_MASK) {
413                         return 0;       /* No data was available */
414                 }
415         }
416
417         /*
418          * Get the length of the frame that arrived.
419          */
420         LengthType = XEmacLite_GetReceiveDataLength(BaseAddress);
421
422         /*
423          * Check if length is valid.
424          */
425         if (LengthType > XEL_MAX_FRAME_SIZE) {
426
427
428                 if (LengthType == XEL_ETHER_PROTO_TYPE_IP) {
429
430                         /*
431                          * The packet is a an IP Packet.
432                          */
433 #ifdef __LITTLE_ENDIAN__
434                         Length = (XEmacLite_ReadReg((BaseAddress),
435                                         XEL_HEADER_IP_LENGTH_OFFSET +
436                                         XEL_RXBUFF_OFFSET) &
437                                         (XEL_RPLR_LENGTH_MASK_HI |
438                                         XEL_RPLR_LENGTH_MASK_LO));
439                         Length = (u16) (((Length & 0xFF00) >> 8) | ((Length & 0x00FF) << 8));
440 #else
441                         Length = ((XEmacLite_ReadReg((BaseAddress),
442                                         XEL_HEADER_IP_LENGTH_OFFSET +
443                                         XEL_RXBUFF_OFFSET) >>
444                                         XEL_HEADER_SHIFT) &
445                                         (XEL_RPLR_LENGTH_MASK_HI |
446                                         XEL_RPLR_LENGTH_MASK_LO));
447 #endif
448
449                         Length += XEL_HEADER_SIZE + XEL_FCS_SIZE;
450
451                 } else if (LengthType == XEL_ETHER_PROTO_TYPE_ARP) {
452
453                         /*
454                          * The packet is an ARP Packet.
455                          */
456                         Length = XEL_ARP_PACKET_SIZE + XEL_HEADER_SIZE +
457                                         XEL_FCS_SIZE;
458
459                 } else {
460                         /*
461                          * Field contains type other than IP or ARP, use max
462                          * frame size and let user parse it.
463                          */
464                         Length = XEL_MAX_FRAME_SIZE;
465
466                 }
467         } else {
468
469                 /*
470                  * Use the length in the frame, plus the header and trailer.
471                  */
472                 Length = LengthType + XEL_HEADER_SIZE + XEL_FCS_SIZE;
473         }
474
475         /*
476          * Read from the EmacLite.
477          */
478         XEmacLite_AlignedRead(((u32 *) (BaseAddress + XEL_RXBUFF_OFFSET)),
479                               FramePtr, Length);
480
481         /*
482          * Acknowledge the frame.
483          */
484         Register = XEmacLite_GetRxStatus(BaseAddress);
485         Register &= ~XEL_RSR_RECV_DONE_MASK;
486         XEmacLite_SetRxStatus(BaseAddress, Register);
487
488         return Length;
489 }
490
491 /*****************************************************************************/
492 /**
493 *
494 * Set the MAC address for this device.  The address is a 48-bit value.
495 *
496 * @param        InstancePtr is a pointer to the XEmacLite instance.
497 * @param        AddressPtr is a pointer to a 6-byte MAC address.
498 *               the format of the MAC address is major octet to minor octet
499 *
500 * @return       None.
501 *
502 * @note
503 *
504 *       - TX must be idle and RX should be idle for deterministic results.
505 *       It is recommended that this function should be called after the
506 *       initialization and before transmission of any packets from the device.
507 *       - Function will not return if hardware is absent or not functioning
508 *       properly.
509 *       - The MAC address can be programmed using any of the two transmit
510 *       buffers (if configured).
511 *
512 ******************************************************************************/
513 void XEmacLite_SetMacAddress(XEmacLite *InstancePtr, u8 *AddressPtr)
514 {
515         u32 BaseAddress;
516
517         /*
518          * Verify that each of the inputs are valid.
519          */
520         Xil_AssertVoid(InstancePtr != NULL);
521
522         /*
523          * Determine the expected TX buffer address.
524          */
525         BaseAddress = XEmacLite_NextTransmitAddr(InstancePtr);
526
527         /*
528          * Copy the MAC address to the Transmit buffer.
529          */
530         XEmacLite_AlignedWrite(AddressPtr,
531                                 (u32 *) BaseAddress,
532                                 XEL_MAC_ADDR_SIZE);
533
534         /*
535          * Set the length.
536          */
537         XEmacLite_WriteReg(BaseAddress,
538                                 XEL_TPLR_OFFSET,
539                                 XEL_MAC_ADDR_SIZE);
540
541         /*
542          * Update the MAC address in the EmacLite.
543          */
544         XEmacLite_SetTxStatus(BaseAddress, XEL_TSR_PROG_MAC_ADDR);
545
546
547         /*
548          * Wait for EmacLite to finish with the MAC address update.
549          */
550         while ((XEmacLite_GetTxStatus(BaseAddress) &
551                         XEL_TSR_PROG_MAC_ADDR) != 0);
552
553 }
554
555 /******************************************************************************/
556 /**
557 *
558 * This is a stub for the send and receive callbacks. The stub
559 * is here in case the upper layers forget to set the handlers.
560 *
561 * @param        CallBackRef is a pointer to the upper layer callback reference.
562 *
563 * @return       None.
564 *
565 * @note         None.
566 *
567 ******************************************************************************/
568 void StubHandler(void *CallBackRef)
569 {
570         (void)(CallBackRef);
571         Xil_AssertVoidAlways();
572 }
573
574
575 /****************************************************************************/
576 /**
577 *
578 * Determine if there is a transmit buffer available.
579 *
580 * @param        InstancePtr is the pointer to the instance of the driver to
581 *               be worked on.
582 *
583 * @return
584 *               - TRUE if there is a TX buffer available for data to be written
585 *               - FALSE if Tx Buffer is not available.
586 *
587 * @note         None.
588 *
589 *****************************************************************************/
590 int XEmacLite_TxBufferAvailable(XEmacLite *InstancePtr)
591 {
592
593         u32 Register;
594         int TxPingBusy;
595         int TxPongBusy;
596
597         /*
598          * Verify that each of the inputs are valid.
599          */
600         Xil_AssertNonvoid(InstancePtr != NULL);
601
602         /*
603          * Read the Tx Status and determine if the buffer is available.
604          */
605         Register = XEmacLite_GetTxStatus(InstancePtr->EmacLiteConfig.
606                                                 BaseAddress);
607
608         TxPingBusy = (Register & (XEL_TSR_XMIT_BUSY_MASK |
609                                  XEL_TSR_XMIT_ACTIVE_MASK));
610
611
612         /*
613          * Read the Tx Status of the second buffer register and determine if the
614          * buffer is available.
615          */
616         if (InstancePtr->EmacLiteConfig.TxPingPong != 0) {
617                 Register = XEmacLite_GetTxStatus(InstancePtr->EmacLiteConfig.
618                                                 BaseAddress +
619                                                 XEL_BUFFER_OFFSET);
620
621                 TxPongBusy = (Register & (XEL_TSR_XMIT_BUSY_MASK |
622                                         XEL_TSR_XMIT_ACTIVE_MASK));
623
624                 return (!(TxPingBusy && TxPongBusy));
625         }
626
627         return (!TxPingBusy);
628
629
630 }
631
632 /****************************************************************************/
633 /**
634 *
635 * Flush the Receive buffers. All data will be lost.
636 *
637 * @param        InstancePtr is the pointer to the instance of the driver to
638 *               be worked on.
639 *
640 * @return       None.
641 *
642 * @note         None.
643 *
644 *****************************************************************************/
645 void XEmacLite_FlushReceive(XEmacLite *InstancePtr)
646 {
647
648         u32 Register;
649
650         /*
651          * Verify that each of the inputs are valid.
652          */
653         Xil_AssertVoid(InstancePtr != NULL);
654
655         /*
656          * Read the current buffer register and determine if the buffer is
657          * available.
658          */
659         Register = XEmacLite_GetRxStatus(InstancePtr->EmacLiteConfig.
660                                                 BaseAddress);
661
662         /*
663          * Preserve the IE bit.
664          */
665         Register &= XEL_RSR_RECV_IE_MASK;
666
667         /*
668          * Write out the value to flush the RX buffer.
669          */
670         XEmacLite_SetRxStatus(InstancePtr->EmacLiteConfig.BaseAddress,
671                                 Register);
672
673         /*
674          * If the pong buffer is available, flush it also.
675          */
676         if (InstancePtr->EmacLiteConfig.RxPingPong != 0) {
677                 /*
678                  * Read the current buffer register and determine if the buffer
679                  * is available.
680                  */
681                 Register = XEmacLite_GetRxStatus(InstancePtr->EmacLiteConfig.
682                                                         BaseAddress +
683                                                         XEL_BUFFER_OFFSET);
684
685                 /*
686                  * Preserve the IE bit.
687                  */
688                 Register &= XEL_RSR_RECV_IE_MASK;
689
690                 /*
691                  * Write out the value to flush the RX buffer.
692                  */
693                 XEmacLite_SetRxStatus(InstancePtr->EmacLiteConfig.BaseAddress +
694                                         XEL_BUFFER_OFFSET, Register);
695
696         }
697
698 }
699
700 /******************************************************************************/
701 /**
702 *
703 * Read the specified PHY register.
704 *
705 * @param        InstancePtr is the pointer to the instance of the driver.
706 * @param        PhyAddress is the address of the PHY device. The valid range is
707 *               is from 0 to 31.
708 * @param        RegNum is the register number in the PHY device which
709 *               is to be read. The valid range is is from 0 to 31.
710 * @param        PhyDataPtr is a pointer to the data in which the data read
711 *               from the PHY device is returned.
712 *
713 * @return
714 *               - XST_SUCCESS if the data is read from the PHY.
715 *               - XST_DEVICE_BUSY if MDIO is busy.
716 *
717 * @note         This function waits for the completion of MDIO data transfer.
718 *
719 *****************************************************************************/
720 int XEmacLite_PhyRead(XEmacLite *InstancePtr, u32 PhyAddress, u32 RegNum,
721                         u16 *PhyDataPtr)
722 {
723         u32 PhyAddrReg;
724         u32 MdioCtrlReg;
725
726         /*
727          * Verify that each of the inputs are valid.
728          */
729         Xil_AssertNonvoid(InstancePtr != NULL);
730         Xil_AssertNonvoid(InstancePtr->EmacLiteConfig.MdioInclude == TRUE);
731         Xil_AssertNonvoid(PhyAddress <= 31);
732         Xil_AssertNonvoid(RegNum <= 31);
733         Xil_AssertNonvoid(PhyDataPtr != NULL);
734
735         /*
736          * Verify MDIO master status.
737          */
738         if (XEmacLite_ReadReg(InstancePtr->EmacLiteConfig.BaseAddress,
739                                 XEL_MDIOCNTR_OFFSET) &
740                                 XEL_MDIOCNTR_STATUS_MASK) {
741                 return XST_DEVICE_BUSY;
742         }
743
744         PhyAddrReg = ((((PhyAddress << XEL_MDIO_ADDRESS_SHIFT) &
745                         XEL_MDIO_ADDRESS_MASK) | RegNum) | XEL_MDIO_OP_MASK);
746         XEmacLite_WriteReg(InstancePtr->EmacLiteConfig.BaseAddress,
747                                  XEL_MDIOADDR_OFFSET, PhyAddrReg);
748
749         /*
750          * Enable MDIO and start the transfer.
751          */
752         MdioCtrlReg =
753                 XEmacLite_ReadReg(InstancePtr->EmacLiteConfig.BaseAddress,
754                                         XEL_MDIOCNTR_OFFSET);
755         XEmacLite_WriteReg(InstancePtr->EmacLiteConfig.BaseAddress,
756                                 XEL_MDIOCNTR_OFFSET,
757                                 MdioCtrlReg |
758                                 XEL_MDIOCNTR_STATUS_MASK |
759                                 XEL_MDIOCNTR_ENABLE_MASK);
760
761         /*
762          * Wait till the completion of transfer.
763          */
764         while ((XEmacLite_ReadReg(InstancePtr->EmacLiteConfig.BaseAddress,
765                                 XEL_MDIOCNTR_OFFSET) &
766                                 XEL_MDIOCNTR_STATUS_MASK));
767
768         /*
769          * Read data from MDIO read data register.
770          */
771         *PhyDataPtr = (u16)XEmacLite_ReadReg(InstancePtr->EmacLiteConfig.BaseAddress,
772                                         XEL_MDIORD_OFFSET);
773
774         /*
775          * Disable the MDIO.
776          */
777         MdioCtrlReg =
778                 XEmacLite_ReadReg(InstancePtr->EmacLiteConfig.BaseAddress,
779                                         XEL_MDIOCNTR_OFFSET);
780
781         XEmacLite_WriteReg(InstancePtr->EmacLiteConfig.BaseAddress,
782                                 XEL_MDIOCNTR_OFFSET,
783                                 MdioCtrlReg & ~XEL_MDIOCNTR_ENABLE_MASK);
784
785
786         return XST_SUCCESS;
787 }
788
789 /******************************************************************************/
790 /**
791 *
792 * Write the given data to the specified register in the PHY device.
793 *
794 * @param        InstancePtr is the pointer to the instance of the driver.
795 * @param        PhyAddress is the address of the PHY device. The valid range is
796 *               is from 0 to 31.
797 * @param        RegNum is the register number in the PHY device which
798 *               is to be written. The valid range is is from 0 to 31.
799 * @param        PhyData is the data to be written to the specified register in
800 *               the PHY device.
801 *
802 * @return
803 *               - XST_SUCCESS if the data is written to the PHY.
804 *               - XST_DEVICE_BUSY if MDIO is busy.
805 *
806 * @note         This function waits for the completion of MDIO data transfer.
807 *
808 *******************************************************************************/
809 int XEmacLite_PhyWrite(XEmacLite *InstancePtr, u32 PhyAddress, u32 RegNum,
810                         u16 PhyData)
811 {
812         u32 PhyAddrReg;
813         u32 MdioCtrlReg;
814
815         /*
816          * Verify that each of the inputs are valid.
817          */
818         Xil_AssertNonvoid(InstancePtr != NULL);
819         Xil_AssertNonvoid(InstancePtr->EmacLiteConfig.MdioInclude == TRUE);
820         Xil_AssertNonvoid(PhyAddress <= 31);
821         Xil_AssertNonvoid(RegNum <= 31);
822
823         /*
824          * Verify MDIO master status.
825          */
826         if (XEmacLite_ReadReg(InstancePtr->EmacLiteConfig.BaseAddress,
827                                 XEL_MDIOCNTR_OFFSET) &
828                                 XEL_MDIOCNTR_STATUS_MASK) {
829                 return XST_DEVICE_BUSY;
830         }
831
832
833
834         PhyAddrReg = ((((PhyAddress << XEL_MDIO_ADDRESS_SHIFT) &
835                         XEL_MDIO_ADDRESS_MASK) | RegNum) & ~XEL_MDIO_OP_MASK);
836         XEmacLite_WriteReg(InstancePtr->EmacLiteConfig.BaseAddress,
837                                 XEL_MDIOADDR_OFFSET, PhyAddrReg);
838
839         /*
840          * Write data to MDIO write data register.
841          */
842         XEmacLite_WriteReg(InstancePtr->EmacLiteConfig.BaseAddress,
843                                 XEL_MDIOWR_OFFSET, (u32)PhyData);
844
845         /*
846          * Enable MDIO and start the transfer.
847          */
848         MdioCtrlReg =
849                 XEmacLite_ReadReg(InstancePtr->EmacLiteConfig.BaseAddress,
850                                         XEL_MDIOCNTR_OFFSET);
851         XEmacLite_WriteReg(InstancePtr->EmacLiteConfig.BaseAddress,
852                                 XEL_MDIOCNTR_OFFSET,
853                                 MdioCtrlReg | XEL_MDIOCNTR_STATUS_MASK |
854                                 XEL_MDIOCNTR_ENABLE_MASK);
855
856         /*
857          * Wait till the completion of transfer.
858          */
859         while ((XEmacLite_ReadReg(InstancePtr->EmacLiteConfig.BaseAddress,
860                                 XEL_MDIOCNTR_OFFSET) & XEL_MDIOCNTR_STATUS_MASK));
861
862
863         /*
864          * Disable the MDIO.
865          */
866         MdioCtrlReg =
867                 XEmacLite_ReadReg(InstancePtr->EmacLiteConfig.BaseAddress,
868                                         XEL_MDIOCNTR_OFFSET);
869         XEmacLite_WriteReg(InstancePtr->EmacLiteConfig.BaseAddress,
870                                 XEL_MDIOCNTR_OFFSET,
871                                 MdioCtrlReg & ~XEL_MDIOCNTR_ENABLE_MASK);
872
873
874
875         return XST_SUCCESS;
876 }
877
878
879
880 /****************************************************************************/
881 /**
882 *
883 * Enable Internal loop back functionality.
884 *
885 * @param        InstancePtr is the pointer to the instance of the driver.
886 *
887 * @return       None.
888 *
889 * @note         None.
890 *
891 *****************************************************************************/
892 void XEmacLite_EnableLoopBack(XEmacLite *InstancePtr)
893 {
894         u32 TsrReg;
895
896         /*
897          * Verify that each of the inputs are valid.
898          */
899         Xil_AssertVoid(InstancePtr != NULL);
900         Xil_AssertVoid(InstancePtr->EmacLiteConfig.Loopback == TRUE);
901
902         TsrReg = XEmacLite_ReadReg(InstancePtr->EmacLiteConfig.BaseAddress,
903                                         XEL_TSR_OFFSET);
904         XEmacLite_WriteReg(InstancePtr->EmacLiteConfig.BaseAddress,
905                         XEL_TSR_OFFSET, TsrReg | XEL_TSR_LOOPBACK_MASK);
906 }
907
908 /****************************************************************************/
909 /**
910 *
911 * Disable Internal loop back functionality.
912 *
913 * @param        InstancePtr is the pointer to the instance of the driver.
914 *
915 * @return       None.
916 *
917 * @note         None.
918 *
919 *****************************************************************************/
920 void XEmacLite_DisableLoopBack(XEmacLite *InstancePtr)
921 {
922         u32 TsrReg;
923
924         /*
925          * Verify that each of the inputs are valid.
926          */
927         Xil_AssertVoid(InstancePtr != NULL);
928         Xil_AssertVoid(InstancePtr->EmacLiteConfig.Loopback == TRUE);
929
930         TsrReg = XEmacLite_ReadReg(InstancePtr->EmacLiteConfig.BaseAddress,
931                                         XEL_TSR_OFFSET);
932         XEmacLite_WriteReg(InstancePtr->EmacLiteConfig.BaseAddress,
933                         XEL_TSR_OFFSET, TsrReg & (~XEL_TSR_LOOPBACK_MASK));
934 }
935
936
937 /*****************************************************************************/
938 /**
939 *
940 * Return the length of the data in the Receive Buffer.
941 *
942 * @param        BaseAddress contains the base address of the device.
943 *
944 * @return       The type/length field of the frame received.
945 *
946 * @note         None.
947 *
948 ******************************************************************************/
949 static u16 XEmacLite_GetReceiveDataLength(u32 BaseAddress)
950 {
951         u16 Length;
952
953 #ifdef __LITTLE_ENDIAN__
954         Length = (XEmacLite_ReadReg((BaseAddress),
955                         XEL_HEADER_OFFSET + XEL_RXBUFF_OFFSET) &
956                         (XEL_RPLR_LENGTH_MASK_HI | XEL_RPLR_LENGTH_MASK_LO));
957         Length = (u16) (((Length & 0xFF00) >> 8) | ((Length & 0x00FF) << 8));
958 #else
959         Length = ((XEmacLite_ReadReg((BaseAddress),
960                         XEL_HEADER_OFFSET + XEL_RXBUFF_OFFSET) >>
961                         XEL_HEADER_SHIFT) &
962                         (XEL_RPLR_LENGTH_MASK_HI | XEL_RPLR_LENGTH_MASK_LO));
963 #endif
964
965         return Length;
966 }
967