]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/NetworkInterface.c
Update version number in readiness for V10.3.0 release. Sync SVN with reviewed releas...
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-TCP / portable / NetworkInterface / Zynq / NetworkInterface.c
index 1c11976cbcec7779ed97ef48964cc7a25bcdd9d9..c8f9653951e567f4a1e5ed6f26f9409ffa8fecec 100644 (file)
-/*\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
+/*
+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 );
+                       }
+               }
+       }
+}
+/*-----------------------------------------------------------*/