-/*\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 );
+ }
+ }
+ }
+}
+/*-----------------------------------------------------------*/