]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/NetworkInterface.c
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2822 1d2547de-c912-0410...
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-TCP / portable / NetworkInterface / Zynq / NetworkInterface.c
index c8f9653951e567f4a1e5ed6f26f9409ffa8fecec..1c11976cbcec7779ed97ef48964cc7a25bcdd9d9 100644 (file)
-/*
-FreeRTOS+TCP V2.0.11
-Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
- http://aws.amazon.com/freertos
- http://www.FreeRTOS.org
-*/
-
-/* Standard includes. */
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "task.h"
-#include "queue.h"
-#include "semphr.h"
-
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_Sockets.h"
-#include "FreeRTOS_IP_Private.h"
-#include "NetworkBufferManagement.h"
-#include "NetworkInterface.h"
-
-/* Xilinx library files. */
-#include <xemacps.h>
-#include "Zynq/x_topology.h"
-#include "Zynq/x_emacpsif.h"
-#include "Zynq/x_emacpsif_hw.h"
-
-/* Provided memory configured as uncached. */
-#include "uncached_memory.h"
-
-#ifndef        BMSR_LINK_STATUS
-       #define BMSR_LINK_STATUS            0x0004UL
-#endif
-
-#ifndef        PHY_LS_HIGH_CHECK_TIME_MS
-       /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not
-       receiving packets. */
-       #define PHY_LS_HIGH_CHECK_TIME_MS       15000
-#endif
-
-#ifndef        PHY_LS_LOW_CHECK_TIME_MS
-       /* Check if the LinkSStatus in the PHY is still low every second. */
-       #define PHY_LS_LOW_CHECK_TIME_MS        1000
-#endif
-
-/* The size of each buffer when BufferAllocation_1 is used:
-http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html */
-#define niBUFFER_1_PACKET_SIZE         1536
-
-/* Naming and numbering of PHY registers. */
-#define PHY_REG_01_BMSR                        0x01    /* Basic mode status register */
-
-#ifndef iptraceEMAC_TASK_STARTING
-       #define iptraceEMAC_TASK_STARTING()     do { } while( 0 )
-#endif
-
-/* Default the size of the stack used by the EMAC deferred handler task to twice
-the size of the stack used by the idle task - but allow this to be overridden in
-FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */
-#ifndef configEMAC_TASK_STACK_SIZE
-       #define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )
-#endif
-
-/*-----------------------------------------------------------*/
-
-/*
- * Look for the link to be up every few milliseconds until either xMaxTime time
- * has passed or a link is found.
- */
-static BaseType_t prvGMACWaitLS( TickType_t xMaxTime );
-
-/*
- * A deferred interrupt handler for all MAC/DMA interrupt sources.
- */
-static void prvEMACHandlerTask( void *pvParameters );
-
-/*-----------------------------------------------------------*/
-
-/* EMAC data/descriptions. */
-static xemacpsif_s xEMACpsif;
-struct xtopology_t xXTopology =
-{
-       .emac_baseaddr = XPAR_PS7_ETHERNET_0_BASEADDR,
-       .emac_type = xemac_type_emacps,
-       .intc_baseaddr = 0x0,
-       .intc_emac_intr = 0x0,
-       .scugic_baseaddr = XPAR_PS7_SCUGIC_0_BASEADDR,
-       .scugic_emac_intr = 0x36,
-};
-
-XEmacPs_Config mac_config =
-{
-       .DeviceId = XPAR_PS7_ETHERNET_0_DEVICE_ID,      /**< Unique ID  of device */
-       .BaseAddress = XPAR_PS7_ETHERNET_0_BASEADDR /**< Physical base address of IPIF registers */
-};
-
-extern int phy_detected;
-
-/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */
-static uint32_t ulPHYLinkStatus = 0;
-
-#if( ipconfigUSE_LLMNR == 1 )
-       static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };
-#endif
-
-/* ucMACAddress as it appears in main.c */
-extern const uint8_t ucMACAddress[ 6 ];
-
-/* Holds the handle of the task used as a deferred interrupt processor.  The
-handle is used so direct notifications can be sent to the task for all EMAC/DMA
-related interrupts. */
-TaskHandle_t xEMACTaskHandle = NULL;
-
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceInitialise( void )
-{
-uint32_t ulLinkSpeed, ulDMAReg;
-BaseType_t xStatus, xLinkStatus;
-XEmacPs *pxEMAC_PS;
-const TickType_t xWaitLinkDelay = pdMS_TO_TICKS( 7000UL ), xWaitRelinkDelay = pdMS_TO_TICKS( 1000UL );
-
-       /* Guard against the init function being called more than once. */
-       if( xEMACTaskHandle == NULL )
-       {
-               pxEMAC_PS = &( xEMACpsif.emacps );
-               memset( &xEMACpsif, '\0', sizeof( xEMACpsif ) );
-
-               xStatus = XEmacPs_CfgInitialize( pxEMAC_PS, &mac_config, mac_config.BaseAddress);
-               if( xStatus != XST_SUCCESS )
-               {
-                       FreeRTOS_printf( ( "xEMACInit: EmacPs Configuration Failed....\n" ) );
-               }
-
-               /* Initialize the mac and set the MAC address. */
-               XEmacPs_SetMacAddress( pxEMAC_PS, ( void * ) ucMACAddress, 1 );
-
-               #if( ipconfigUSE_LLMNR == 1 )
-               {
-                       /* Also add LLMNR multicast MAC address. */
-                       XEmacPs_SetMacAddress( pxEMAC_PS, ( void * )xLLMNR_MACAddress, 2 );
-               }
-               #endif  /* ipconfigUSE_LLMNR == 1 */
-
-               XEmacPs_SetMdioDivisor( pxEMAC_PS, MDC_DIV_224 );
-               ulLinkSpeed = Phy_Setup( pxEMAC_PS );
-               XEmacPs_SetOperatingSpeed( pxEMAC_PS, ulLinkSpeed);
-
-               /* Setting the operating speed of the MAC needs a delay. */
-               vTaskDelay( pdMS_TO_TICKS( 25UL ) );
-
-               ulDMAReg = XEmacPs_ReadReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET);
-
-               /* DISC_WHEN_NO_AHB: when set, the GEM DMA will automatically discard receive
-               packets from the receiver packet buffer memory when no AHB resource is available. */
-               XEmacPs_WriteReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET,
-                       ulDMAReg | XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK);
-
-               setup_isr( &xEMACpsif );
-               init_dma( &xEMACpsif );
-               start_emacps( &xEMACpsif );
-
-               prvGMACWaitLS( xWaitLinkDelay );
-
-               /* The deferred interrupt handler task is created at the highest
-               possible priority to ensure the interrupt handler can return directly
-               to it.  The task's handle is stored in xEMACTaskHandle so interrupts can
-               notify the task when there is something to process. */
-               xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );
-       }
-       else
-       {
-               /* Initialisation was already performed, just wait for the link. */
-               prvGMACWaitLS( xWaitRelinkDelay );
-       }
-
-       /* Only return pdTRUE when the Link Status of the PHY is high, otherwise the
-       DHCP process and all other communication will fail. */
-       xLinkStatus = xGetPhyLinkStatus();
-
-       return ( xLinkStatus != pdFALSE );
-}
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxBuffer, BaseType_t bReleaseAfterSend )
-{
-       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
-       {
-               iptraceNETWORK_INTERFACE_TRANSMIT();
-               emacps_send_message( &xEMACpsif, pxBuffer, bReleaseAfterSend );
-       }
-       else if( bReleaseAfterSend != pdFALSE )
-       {
-               /* No link. */
-               vReleaseNetworkBufferAndDescriptor( pxBuffer );
-       }
-
-       return pdTRUE;
-}
-/*-----------------------------------------------------------*/
-
-static inline unsigned long ulReadMDIO( unsigned ulRegister )
-{
-uint16_t usValue;
-
-       XEmacPs_PhyRead( &( xEMACpsif.emacps ), phy_detected, ulRegister, &usValue );
-       return usValue;
-}
-/*-----------------------------------------------------------*/
-
-static BaseType_t prvGMACWaitLS( TickType_t xMaxTime )
-{
-TickType_t xStartTime, xEndTime;
-const TickType_t xShortDelay = pdMS_TO_TICKS( 20UL );
-BaseType_t xReturn;
-
-       xStartTime = xTaskGetTickCount();
-
-       for( ;; )
-       {
-               xEndTime = xTaskGetTickCount();
-
-               if( xEndTime - xStartTime > xMaxTime )
-               {
-                       xReturn = pdFALSE;
-                       break;
-               }
-               ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );
-
-               if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
-               {
-                       xReturn = pdTRUE;
-                       break;
-               }
-
-               vTaskDelay( xShortDelay );
-       }
-
-       return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
-{
-static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );
-uint8_t *ucRAMBuffer = ucNetworkPackets;
-uint32_t ul;
-
-       for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )
-       {
-               pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;
-               *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );
-               ucRAMBuffer += niBUFFER_1_PACKET_SIZE;
-       }
-}
-/*-----------------------------------------------------------*/
-
-BaseType_t xGetPhyLinkStatus( void )
-{
-BaseType_t xReturn;
-
-       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )
-       {
-               xReturn = pdFALSE;
-       }
-       else
-       {
-               xReturn = pdTRUE;
-       }
-
-       return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-static void prvEMACHandlerTask( void *pvParameters )
-{
-TimeOut_t xPhyTime;
-TickType_t xPhyRemTime;
-UBaseType_t uxLastMinBufferCount = 0;
-UBaseType_t uxCurrentCount;
-BaseType_t xResult = 0;
-uint32_t xStatus;
-const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
-
-       /* Remove compiler warnings about unused parameters. */
-       ( void ) pvParameters;
-
-       /* A possibility to set some additional task properties like calling
-       portTASK_USES_FLOATING_POINT() */
-       iptraceEMAC_TASK_STARTING();
-
-       vTaskSetTimeOutState( &xPhyTime );
-       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
-
-       for( ;; )
-       {
-               uxCurrentCount = uxGetMinimumFreeNetworkBuffers();
-               if( uxLastMinBufferCount != uxCurrentCount )
-               {
-                       /* The logging produced below may be helpful
-                       while tuning +TCP: see how many buffers are in use. */
-                       uxLastMinBufferCount = uxCurrentCount;
-                       FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
-                               uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );
-               }
-
-               #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
-               {
-               static UBaseType_t uxLastMinQueueSpace = 0;
-
-                       uxCurrentCount = uxGetMinimumIPQueueSpace();
-                       if( uxLastMinQueueSpace != uxCurrentCount )
-                       {
-                               /* The logging produced below may be helpful
-                               while tuning +TCP: see how many buffers are in use. */
-                               uxLastMinQueueSpace = uxCurrentCount;
-                               FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );
-                       }
-               }
-               #endif /* ipconfigCHECK_IP_QUEUE_SPACE */
-
-               if( ( xEMACpsif.isr_events & EMAC_IF_ALL_EVENT ) == 0 )
-               {
-                       /* No events to process now, wait for the next. */
-                       ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );
-               }
-
-               if( ( xEMACpsif.isr_events & EMAC_IF_RX_EVENT ) != 0 )
-               {
-                       xEMACpsif.isr_events &= ~EMAC_IF_RX_EVENT;
-                       xResult = emacps_check_rx( &xEMACpsif );
-               }
-
-               if( ( xEMACpsif.isr_events & EMAC_IF_TX_EVENT ) != 0 )
-               {
-                       xEMACpsif.isr_events &= ~EMAC_IF_TX_EVENT;
-                       emacps_check_tx( &xEMACpsif );
-               }
-
-               if( ( xEMACpsif.isr_events & EMAC_IF_ERR_EVENT ) != 0 )
-               {
-                       xEMACpsif.isr_events &= ~EMAC_IF_ERR_EVENT;
-                       emacps_check_errors( &xEMACpsif );
-               }
-
-               if( xResult > 0 )
-               {
-                       /* A packet was received. No need to check for the PHY status now,
-                       but set a timer to check it later on. */
-                       vTaskSetTimeOutState( &xPhyTime );
-                       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
-                       xResult = 0;
-               }
-               else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE )
-               {
-                       xStatus = ulReadMDIO( PHY_REG_01_BMSR );
-
-                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )
-                       {
-                               ulPHYLinkStatus = xStatus;
-                               FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );
-                       }
-
-                       vTaskSetTimeOutState( &xPhyTime );
-                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
-                       {
-                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
-                       }
-                       else
-                       {
-                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
-                       }
-               }
-       }
-}
-/*-----------------------------------------------------------*/
+/*\r
+FreeRTOS+TCP V2.0.11\r
+Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+this software and associated documentation files (the "Software"), to deal in\r
+the Software without restriction, including without limitation the rights to\r
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+the Software, and to permit persons to whom the Software is furnished to do so,\r
+subject to the following conditions:\r
+\r
+The above copyright notice and this permission notice shall be included in all\r
+copies or substantial portions of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+\r
+ http://aws.amazon.com/freertos\r
+ http://www.FreeRTOS.org\r
+*/\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+#include "NetworkInterface.h"\r
+\r
+/* Xilinx library files. */\r
+#include <xemacps.h>\r
+#include "Zynq/x_topology.h"\r
+#include "Zynq/x_emacpsif.h"\r
+#include "Zynq/x_emacpsif_hw.h"\r
+\r
+/* Provided memory configured as uncached. */\r
+#include "uncached_memory.h"\r
+\r
+#ifndef        BMSR_LINK_STATUS\r
+       #define BMSR_LINK_STATUS            0x0004UL\r
+#endif\r
+\r
+#ifndef        PHY_LS_HIGH_CHECK_TIME_MS\r
+       /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not\r
+       receiving packets. */\r
+       #define PHY_LS_HIGH_CHECK_TIME_MS       15000\r
+#endif\r
+\r
+#ifndef        PHY_LS_LOW_CHECK_TIME_MS\r
+       /* Check if the LinkSStatus in the PHY is still low every second. */\r
+       #define PHY_LS_LOW_CHECK_TIME_MS        1000\r
+#endif\r
+\r
+/* The size of each buffer when BufferAllocation_1 is used:\r
+http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html */\r
+#define niBUFFER_1_PACKET_SIZE         1536\r
+\r
+/* Naming and numbering of PHY registers. */\r
+#define PHY_REG_01_BMSR                        0x01    /* Basic mode status register */\r
+\r
+#ifndef iptraceEMAC_TASK_STARTING\r
+       #define iptraceEMAC_TASK_STARTING()     do { } while( 0 )\r
+#endif\r
+\r
+/* Default the size of the stack used by the EMAC deferred handler task to twice\r
+the size of the stack used by the idle task - but allow this to be overridden in\r
+FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */\r
+#ifndef configEMAC_TASK_STACK_SIZE\r
+       #define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )\r
+#endif\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Look for the link to be up every few milliseconds until either xMaxTime time\r
+ * has passed or a link is found.\r
+ */\r
+static BaseType_t prvGMACWaitLS( TickType_t xMaxTime );\r
+\r
+/*\r
+ * A deferred interrupt handler for all MAC/DMA interrupt sources.\r
+ */\r
+static void prvEMACHandlerTask( void *pvParameters );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* EMAC data/descriptions. */\r
+static xemacpsif_s xEMACpsif;\r
+struct xtopology_t xXTopology =\r
+{\r
+       .emac_baseaddr = XPAR_PS7_ETHERNET_0_BASEADDR,\r
+       .emac_type = xemac_type_emacps,\r
+       .intc_baseaddr = 0x0,\r
+       .intc_emac_intr = 0x0,\r
+       .scugic_baseaddr = XPAR_PS7_SCUGIC_0_BASEADDR,\r
+       .scugic_emac_intr = 0x36,\r
+};\r
+\r
+XEmacPs_Config mac_config =\r
+{\r
+       .DeviceId = XPAR_PS7_ETHERNET_0_DEVICE_ID,      /**< Unique ID  of device */\r
+       .BaseAddress = XPAR_PS7_ETHERNET_0_BASEADDR /**< Physical base address of IPIF registers */\r
+};\r
+\r
+extern int phy_detected;\r
+\r
+/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */\r
+static uint32_t ulPHYLinkStatus = 0;\r
+\r
+#if( ipconfigUSE_LLMNR == 1 )\r
+       static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };\r
+#endif\r
+\r
+/* ucMACAddress as it appears in main.c */\r
+extern const uint8_t ucMACAddress[ 6 ];\r
+\r
+/* Holds the handle of the task used as a deferred interrupt processor.  The\r
+handle is used so direct notifications can be sent to the task for all EMAC/DMA\r
+related interrupts. */\r
+TaskHandle_t xEMACTaskHandle = NULL;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+uint32_t ulLinkSpeed, ulDMAReg;\r
+BaseType_t xStatus, xLinkStatus;\r
+XEmacPs *pxEMAC_PS;\r
+const TickType_t xWaitLinkDelay = pdMS_TO_TICKS( 7000UL ), xWaitRelinkDelay = pdMS_TO_TICKS( 1000UL );\r
+\r
+       /* Guard against the init function being called more than once. */\r
+       if( xEMACTaskHandle == NULL )\r
+       {\r
+               pxEMAC_PS = &( xEMACpsif.emacps );\r
+               memset( &xEMACpsif, '\0', sizeof( xEMACpsif ) );\r
+\r
+               xStatus = XEmacPs_CfgInitialize( pxEMAC_PS, &mac_config, mac_config.BaseAddress);\r
+               if( xStatus != XST_SUCCESS )\r
+               {\r
+                       FreeRTOS_printf( ( "xEMACInit: EmacPs Configuration Failed....\n" ) );\r
+               }\r
+\r
+               /* Initialize the mac and set the MAC address. */\r
+               XEmacPs_SetMacAddress( pxEMAC_PS, ( void * ) ucMACAddress, 1 );\r
+\r
+               #if( ipconfigUSE_LLMNR == 1 )\r
+               {\r
+                       /* Also add LLMNR multicast MAC address. */\r
+                       XEmacPs_SetMacAddress( pxEMAC_PS, ( void * )xLLMNR_MACAddress, 2 );\r
+               }\r
+               #endif  /* ipconfigUSE_LLMNR == 1 */\r
+\r
+               XEmacPs_SetMdioDivisor( pxEMAC_PS, MDC_DIV_224 );\r
+               ulLinkSpeed = Phy_Setup( pxEMAC_PS );\r
+               XEmacPs_SetOperatingSpeed( pxEMAC_PS, ulLinkSpeed);\r
+\r
+               /* Setting the operating speed of the MAC needs a delay. */\r
+               vTaskDelay( pdMS_TO_TICKS( 25UL ) );\r
+\r
+               ulDMAReg = XEmacPs_ReadReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET);\r
+\r
+               /* DISC_WHEN_NO_AHB: when set, the GEM DMA will automatically discard receive\r
+               packets from the receiver packet buffer memory when no AHB resource is available. */\r
+               XEmacPs_WriteReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET,\r
+                       ulDMAReg | XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK);\r
+\r
+               setup_isr( &xEMACpsif );\r
+               init_dma( &xEMACpsif );\r
+               start_emacps( &xEMACpsif );\r
+\r
+               prvGMACWaitLS( xWaitLinkDelay );\r
+\r
+               /* The deferred interrupt handler task is created at the highest\r
+               possible priority to ensure the interrupt handler can return directly\r
+               to it.  The task's handle is stored in xEMACTaskHandle so interrupts can\r
+               notify the task when there is something to process. */\r
+               xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );\r
+       }\r
+       else\r
+       {\r
+               /* Initialisation was already performed, just wait for the link. */\r
+               prvGMACWaitLS( xWaitRelinkDelay );\r
+       }\r
+\r
+       /* Only return pdTRUE when the Link Status of the PHY is high, otherwise the\r
+       DHCP process and all other communication will fail. */\r
+       xLinkStatus = xGetPhyLinkStatus();\r
+\r
+       return ( xLinkStatus != pdFALSE );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxBuffer, BaseType_t bReleaseAfterSend )\r
+{\r
+       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+       {\r
+               iptraceNETWORK_INTERFACE_TRANSMIT();\r
+               emacps_send_message( &xEMACpsif, pxBuffer, bReleaseAfterSend );\r
+       }\r
+       else if( bReleaseAfterSend != pdFALSE )\r
+       {\r
+               /* No link. */\r
+               vReleaseNetworkBufferAndDescriptor( pxBuffer );\r
+       }\r
+\r
+       return pdTRUE;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static inline unsigned long ulReadMDIO( unsigned ulRegister )\r
+{\r
+uint16_t usValue;\r
+\r
+       XEmacPs_PhyRead( &( xEMACpsif.emacps ), phy_detected, ulRegister, &usValue );\r
+       return usValue;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvGMACWaitLS( TickType_t xMaxTime )\r
+{\r
+TickType_t xStartTime, xEndTime;\r
+const TickType_t xShortDelay = pdMS_TO_TICKS( 20UL );\r
+BaseType_t xReturn;\r
+\r
+       xStartTime = xTaskGetTickCount();\r
+\r
+       for( ;; )\r
+       {\r
+               xEndTime = xTaskGetTickCount();\r
+\r
+               if( xEndTime - xStartTime > xMaxTime )\r
+               {\r
+                       xReturn = pdFALSE;\r
+                       break;\r
+               }\r
+               ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );\r
+\r
+               if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+               {\r
+                       xReturn = pdTRUE;\r
+                       break;\r
+               }\r
+\r
+               vTaskDelay( xShortDelay );\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )\r
+{\r
+static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );\r
+uint8_t *ucRAMBuffer = ucNetworkPackets;\r
+uint32_t ul;\r
+\r
+       for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )\r
+       {\r
+               pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;\r
+               *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );\r
+               ucRAMBuffer += niBUFFER_1_PACKET_SIZE;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xGetPhyLinkStatus( void )\r
+{\r
+BaseType_t xReturn;\r
+\r
+       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )\r
+       {\r
+               xReturn = pdFALSE;\r
+       }\r
+       else\r
+       {\r
+               xReturn = pdTRUE;\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvEMACHandlerTask( void *pvParameters )\r
+{\r
+TimeOut_t xPhyTime;\r
+TickType_t xPhyRemTime;\r
+UBaseType_t uxLastMinBufferCount = 0;\r
+UBaseType_t uxCurrentCount;\r
+BaseType_t xResult = 0;\r
+uint32_t xStatus;\r
+const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );\r
+\r
+       /* Remove compiler warnings about unused parameters. */\r
+       ( void ) pvParameters;\r
+\r
+       /* A possibility to set some additional task properties like calling\r
+       portTASK_USES_FLOATING_POINT() */\r
+       iptraceEMAC_TASK_STARTING();\r
+\r
+       vTaskSetTimeOutState( &xPhyTime );\r
+       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+\r
+       for( ;; )\r
+       {\r
+               uxCurrentCount = uxGetMinimumFreeNetworkBuffers();\r
+               if( uxLastMinBufferCount != uxCurrentCount )\r
+               {\r
+                       /* The logging produced below may be helpful\r
+                       while tuning +TCP: see how many buffers are in use. */\r
+                       uxLastMinBufferCount = uxCurrentCount;\r
+                       FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",\r
+                               uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );\r
+               }\r
+\r
+               #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+               {\r
+               static UBaseType_t uxLastMinQueueSpace = 0;\r
+\r
+                       uxCurrentCount = uxGetMinimumIPQueueSpace();\r
+                       if( uxLastMinQueueSpace != uxCurrentCount )\r
+                       {\r
+                               /* The logging produced below may be helpful\r
+                               while tuning +TCP: see how many buffers are in use. */\r
+                               uxLastMinQueueSpace = uxCurrentCount;\r
+                               FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );\r
+                       }\r
+               }\r
+               #endif /* ipconfigCHECK_IP_QUEUE_SPACE */\r
+\r
+               if( ( xEMACpsif.isr_events & EMAC_IF_ALL_EVENT ) == 0 )\r
+               {\r
+                       /* No events to process now, wait for the next. */\r
+                       ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );\r
+               }\r
+\r
+               if( ( xEMACpsif.isr_events & EMAC_IF_RX_EVENT ) != 0 )\r
+               {\r
+                       xEMACpsif.isr_events &= ~EMAC_IF_RX_EVENT;\r
+                       xResult = emacps_check_rx( &xEMACpsif );\r
+               }\r
+\r
+               if( ( xEMACpsif.isr_events & EMAC_IF_TX_EVENT ) != 0 )\r
+               {\r
+                       xEMACpsif.isr_events &= ~EMAC_IF_TX_EVENT;\r
+                       emacps_check_tx( &xEMACpsif );\r
+               }\r
+\r
+               if( ( xEMACpsif.isr_events & EMAC_IF_ERR_EVENT ) != 0 )\r
+               {\r
+                       xEMACpsif.isr_events &= ~EMAC_IF_ERR_EVENT;\r
+                       emacps_check_errors( &xEMACpsif );\r
+               }\r
+\r
+               if( xResult > 0 )\r
+               {\r
+                       /* A packet was received. No need to check for the PHY status now,\r
+                       but set a timer to check it later on. */\r
+                       vTaskSetTimeOutState( &xPhyTime );\r
+                       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+                       xResult = 0;\r
+               }\r
+               else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE )\r
+               {\r
+                       xStatus = ulReadMDIO( PHY_REG_01_BMSR );\r
+\r
+                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )\r
+                       {\r
+                               ulPHYLinkStatus = xStatus;\r
+                               FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );\r
+                       }\r
+\r
+                       vTaskSetTimeOutState( &xPhyTime );\r
+                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+                       {\r
+                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+                       }\r
+                       else\r
+                       {\r
+                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+                       }\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r