]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/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 / STM32Fxx / NetworkInterface.c
index 6fad9216e8aaa5c2f40902cafd5db637f4116d6b..b9278c0429f610119232cbb4283452b56f39d4cb 100644 (file)
-/*\r
- * Some constants, hardware definitions and comments taken from ST's HAL driver\r
- * library, COPYRIGHT(c) 2015 STMicroelectronics.\r
- */\r
-\r
-/*\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 "FreeRTOS_DNS.h"\r
-#include "FreeRTOS_ARP.h"\r
-#include "NetworkBufferManagement.h"\r
-#include "NetworkInterface.h"\r
-#include "phyHandling.h"\r
-\r
-/* ST includes. */\r
-#if defined( STM32F7xx )\r
-       #include "stm32f7xx_hal.h"\r
-#elif defined( STM32F4xx )\r
-       #include "stm32f4xx_hal.h"\r
-#elif defined( STM32F2xx )\r
-       #include "stm32f2xx_hal.h"\r
-#elif !defined( _lint )        /* Lint does not like an #error */\r
-       #error What part?\r
-#endif\r
-\r
-#include "stm32fxx_hal_eth.h"\r
-\r
-/* Interrupt events to process.  Currently only the Rx event is processed\r
-although code for other events is included to allow for possible future\r
-expansion. */\r
-#define EMAC_IF_RX_EVENT        1UL\r
-#define EMAC_IF_TX_EVENT        2UL\r
-#define EMAC_IF_ERR_EVENT       4UL\r
-#define EMAC_IF_ALL_EVENT       ( EMAC_IF_RX_EVENT | EMAC_IF_TX_EVENT | EMAC_IF_ERR_EVENT )\r
-\r
-#define ETH_DMA_ALL_INTS \\r
-       ( ETH_DMA_IT_TST | ETH_DMA_IT_PMT | ETH_DMA_IT_MMC | ETH_DMA_IT_NIS | ETH_DMA_IT_ER | \\r
-         ETH_DMA_IT_FBE | ETH_DMA_IT_RWT | ETH_DMA_IT_RPS | ETH_DMA_IT_RBU | ETH_DMA_IT_R | \\r
-         ETH_DMA_IT_TU | ETH_DMA_IT_RO | ETH_DMA_IT_TJT | ETH_DMA_IT_TPS | ETH_DMA_IT_T )\r
-\r
-#ifndef niEMAC_HANDLER_TASK_PRIORITY\r
-       #define niEMAC_HANDLER_TASK_PRIORITY    configMAX_PRIORITIES - 1\r
-#endif\r
-\r
-#define ipFRAGMENT_OFFSET_BIT_MASK             ( ( uint16_t ) 0x0fff ) /* The bits in the two byte IP header field that make up the fragment offset value. */\r
-\r
-#if( ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 ) || ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 ) )\r
-       #warning Consider enabling checksum offloading\r
-#endif\r
-\r
-#ifndef niDESCRIPTOR_WAIT_TIME_MS\r
-       #define niDESCRIPTOR_WAIT_TIME_MS               250uL\r
-#endif\r
-\r
-/*\r
- * Most users will want a PHY that negotiates about\r
- * the connection properties: speed, dmix and duplex.\r
- * On some rare cases, you want to select what is being\r
- * advertised, properties like MDIX and duplex.\r
- */\r
-\r
-#if !defined( ipconfigETHERNET_AN_ENABLE )\r
-       /* Enable auto-negotiation */\r
-       #define ipconfigETHERNET_AN_ENABLE                              1\r
-#endif\r
-\r
-#if !defined( ipconfigETHERNET_AUTO_CROSS_ENABLE )\r
-       #define ipconfigETHERNET_AUTO_CROSS_ENABLE              1\r
-#endif\r
-\r
-#if( ipconfigETHERNET_AN_ENABLE == 0 )\r
-       /*\r
-        * The following three defines are only used in case there\r
-        * is no auto-negotiation.\r
-        */\r
-       #if !defined( ipconfigETHERNET_CROSSED_LINK )\r
-               #define ipconfigETHERNET_CROSSED_LINK                   1\r
-       #endif\r
-\r
-       #if !defined( ipconfigETHERNET_USE_100MB )\r
-               #define ipconfigETHERNET_USE_100MB                              1\r
-       #endif\r
-\r
-       #if !defined( ipconfigETHERNET_USE_FULL_DUPLEX )\r
-               #define ipconfigETHERNET_USE_FULL_DUPLEX                1\r
-       #endif\r
-#endif /* ipconfigETHERNET_AN_ENABLE == 0 */\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
-/* Two choices must be made: RMII versus MII,\r
-and the index of the PHY in use ( between 0 and 31 ). */\r
-#ifndef ipconfigUSE_RMII\r
-       #ifdef STM32F7xx\r
-               #define ipconfigUSE_RMII        1\r
-       #else\r
-               #define ipconfigUSE_RMII        0\r
-       #endif /* STM32F7xx */\r
-#endif /* ipconfigUSE_RMII */\r
-\r
-#if( ipconfigUSE_RMII != 0 )\r
-       #warning Using RMII, make sure if this is correct\r
-#else\r
-       #warning Using MII, make sure if this is correct\r
-#endif\r
-\r
-typedef enum\r
-{\r
-    eMACInit,   /* Must initialise MAC. */\r
-    eMACPass,   /* Initialisation was successful. */\r
-    eMACFailed, /* Initialisation failed. */\r
-} eMAC_INIT_STATUS_TYPE;\r
-\r
-static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit;\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-/*\r
- * A deferred interrupt handler task that processes\r
- */\r
-static void prvEMACHandlerTask( void *pvParameters );\r
-\r
-/*\r
- * Force a negotiation with the Switch or Router and wait for LS.\r
- */\r
-static void prvEthernetUpdateConfig( BaseType_t xForce );\r
-\r
-/*\r
- * See if there is a new packet and forward it to the IP-task.\r
- */\r
-static BaseType_t prvNetworkInterfaceInput( void );\r
-\r
-#if( ipconfigUSE_LLMNR != 0 )\r
-       /*\r
-        * For LLMNR, an extra MAC-address must be configured to\r
-        * be able to receive the multicast messages.\r
-        */\r
-       static void prvMACAddressConfig(ETH_HandleTypeDef *heth, uint32_t ulIndex, uint8_t *Addr);\r
-#endif\r
-\r
-/*\r
- * Check if a given packet should be accepted.\r
- */\r
-static BaseType_t xMayAcceptPacket( uint8_t *pcBuffer );\r
-\r
-/*\r
- * Initialise the TX descriptors.\r
- */\r
-static void prvDMATxDescListInit( void );\r
-\r
-/*\r
- * Initialise the RX descriptors.\r
- */\r
-static void prvDMARxDescListInit( void );\r
-\r
-/* After packets have been sent, the network\r
-buffers will be released. */\r
-static void vClearTXBuffers( void );\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-/* Bit map of outstanding ETH interrupt events for processing.  Currently only\r
-the Rx interrupt is handled, although code is included for other events to\r
-enable future expansion. */\r
-static volatile uint32_t ulISREvents;\r
-\r
-#if( ipconfigUSE_LLMNR == 1 )\r
-       static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };\r
-#endif\r
-\r
-static EthernetPhy_t xPhyObject;\r
-\r
-/* Ethernet handle. */\r
-static ETH_HandleTypeDef xETH;\r
-\r
-/* xTXDescriptorSemaphore is a counting semaphore with\r
-a maximum count of ETH_TXBUFNB, which is the number of\r
-DMA TX descriptors. */\r
-static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;\r
-\r
-/*\r
- * Note: it is adviced to define both\r
- *\r
- *     #define  ipconfigZERO_COPY_RX_DRIVER   1\r
- *     #define  ipconfigZERO_COPY_TX_DRIVER   1\r
- *\r
- * The method using memcpy is slower and probaly uses more RAM memory.\r
- * The possibility is left in the code just for comparison.\r
- *\r
- * It is adviced to define ETH_TXBUFNB at least 4. Note that no\r
- * TX buffers are allocated in a zero-copy driver.\r
- */\r
-/* MAC buffers: ---------------------------------------------------------*/\r
-\r
-/* Put the DMA descriptors in '.first_data'.\r
-This is important for STM32F7, which has an L1 data cache.\r
-The first 64KB of the SRAM is not cached. */\r
-\r
-/* Ethernet Rx MA Descriptor */\r
-__attribute__ ((aligned (32)))\r
-__attribute__ ((section(".first_data")))\r
-       ETH_DMADescTypeDef  DMARxDscrTab[ ETH_RXBUFNB ];\r
-\r
-#if( ipconfigZERO_COPY_RX_DRIVER == 0 )\r
-       /* Ethernet Receive Buffer */\r
-       __ALIGN_BEGIN uint8_t Rx_Buff[ ETH_RXBUFNB ][ ETH_RX_BUF_SIZE ] __ALIGN_END;\r
-#endif\r
-\r
-/* Ethernet Tx DMA Descriptor */\r
-__attribute__ ((aligned (32)))\r
-__attribute__ ((section(".first_data")))\r
-       ETH_DMADescTypeDef  DMATxDscrTab[ ETH_TXBUFNB ];\r
-\r
-#if( ipconfigZERO_COPY_TX_DRIVER == 0 )\r
-       /* Ethernet Transmit Buffer */\r
-       __ALIGN_BEGIN uint8_t Tx_Buff[ ETH_TXBUFNB ][ ETH_TX_BUF_SIZE ] __ALIGN_END;\r
-#endif\r
-\r
-/* DMATxDescToClear points to the next TX DMA descriptor\r
-that must be cleared by vClearTXBuffers(). */\r
-static __IO ETH_DMADescTypeDef  *DMATxDescToClear;\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
-static TaskHandle_t xEMACTaskHandle = NULL;\r
-\r
-/* For local use only: describe the PHY's properties: */\r
-const PhyProperties_t xPHYProperties =\r
-{\r
-       #if( ipconfigETHERNET_AN_ENABLE != 0 )\r
-               .ucSpeed = PHY_SPEED_AUTO,\r
-               .ucDuplex = PHY_DUPLEX_AUTO,\r
-       #else\r
-               #if( ipconfigETHERNET_USE_100MB != 0 )\r
-                       .ucSpeed = PHY_SPEED_100,\r
-               #else\r
-                       .ucSpeed = PHY_SPEED_10,\r
-               #endif\r
-\r
-               #if( ipconfigETHERNET_USE_FULL_DUPLEX != 0 )\r
-                       .ucDuplex = PHY_DUPLEX_FULL,\r
-               #else\r
-                       .ucDuplex = PHY_DUPLEX_HALF,\r
-               #endif\r
-       #endif\r
-\r
-       #if( ipconfigETHERNET_AN_ENABLE != 0 ) && ( ipconfigETHERNET_AUTO_CROSS_ENABLE != 0 )\r
-               .ucMDI_X = PHY_MDIX_AUTO,\r
-       #elif( ipconfigETHERNET_CROSSED_LINK != 0 )\r
-               .ucMDI_X = PHY_MDIX_CROSSED,\r
-       #else\r
-               .ucMDI_X = PHY_MDIX_DIRECT,\r
-       #endif\r
-};\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef *heth )\r
-{\r
-BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
-\r
-       ( void ) heth;\r
-\r
-       /* Ethernet RX-Complete callback function, elsewhere declared as weak. */\r
-    ulISREvents |= EMAC_IF_RX_EVENT;\r
-       /* Wakeup the prvEMACHandlerTask. */\r
-       if( xEMACTaskHandle != NULL )\r
-       {\r
-               vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );\r
-               portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef *heth )\r
-{\r
-BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
-\r
-       ( void ) heth;\r
-\r
-       /* This call-back is only useful in case packets are being sent\r
-       zero-copy.  Once they're sent, the buffers will be released\r
-       by the function vClearTXBuffers(). */\r
-       ulISREvents |= EMAC_IF_TX_EVENT;\r
-       /* Wakeup the prvEMACHandlerTask. */\r
-       if( xEMACTaskHandle != NULL )\r
-       {\r
-               vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );\r
-               portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static void vClearTXBuffers()\r
-{\r
-__IO ETH_DMADescTypeDef  *txLastDescriptor = xETH.TxDesc;\r
-size_t uxCount = ( ( UBaseType_t ) ETH_TXBUFNB ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );\r
-#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
-       NetworkBufferDescriptor_t *pxNetworkBuffer;\r
-       uint8_t *ucPayLoad;\r
-#endif\r
-\r
-       /* This function is called after a TX-completion interrupt.\r
-       It will release each Network Buffer used in xNetworkInterfaceOutput().\r
-       'uxCount' represents the number of descriptors given to DMA for transmission.\r
-       After sending a packet, the DMA will clear the 'ETH_DMATXDESC_OWN' bit. */\r
-       while( ( uxCount > 0 ) && ( ( DMATxDescToClear->Status & ETH_DMATXDESC_OWN ) == 0 ) )\r
-       {\r
-               if( ( DMATxDescToClear == txLastDescriptor ) && ( uxCount != ETH_TXBUFNB ) )\r
-               {\r
-                       break;\r
-               }\r
-               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
-               {\r
-                       ucPayLoad = ( uint8_t * )DMATxDescToClear->Buffer1Addr;\r
-\r
-                       if( ucPayLoad != NULL )\r
-                       {\r
-                               pxNetworkBuffer = pxPacketBuffer_to_NetworkBuffer( ucPayLoad );\r
-                               if( pxNetworkBuffer != NULL )\r
-                               {\r
-                                       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ) ;\r
-                               }\r
-                               DMATxDescToClear->Buffer1Addr = ( uint32_t )0u;\r
-                       }\r
-               }\r
-               #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
-\r
-               DMATxDescToClear = ( ETH_DMADescTypeDef * )( DMATxDescToClear->Buffer2NextDescAddr );\r
-\r
-               uxCount--;\r
-               /* Tell the counting semaphore that one more TX descriptor is available. */\r
-               xSemaphoreGive( xTXDescriptorSemaphore );\r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-BaseType_t xNetworkInterfaceInitialise( void )\r
-{\r
-HAL_StatusTypeDef hal_eth_init_status;\r
-BaseType_t xResult;\r
-\r
-    if( xMacInitStatus == eMACInit )\r
-       {\r
-               xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ETH_TXBUFNB, ( UBaseType_t ) ETH_TXBUFNB );\r
-               if( xTXDescriptorSemaphore == NULL )\r
-               {\r
-                       xMacInitStatus = eMACFailed;\r
-               }\r
-               else\r
-               {\r
-                       /* Initialise ETH */\r
-\r
-                       xETH.Instance = ETH;\r
-                       xETH.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;\r
-                       xETH.Init.Speed = ETH_SPEED_100M;\r
-                       xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;\r
-                       /* Value of PhyAddress doesn't matter, will be probed for. */\r
-                       xETH.Init.PhyAddress = 0;\r
-\r
-                       xETH.Init.MACAddr = ( uint8_t * ) FreeRTOS_GetMACAddress();\r
-                       xETH.Init.RxMode = ETH_RXINTERRUPT_MODE;\r
-\r
-                       #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )\r
-                       {\r
-                               /* using the ETH_CHECKSUM_BY_HARDWARE option:\r
-                               both the IP and the protocol checksums will be calculated\r
-                               by the peripheral. */\r
-                               xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;\r
-                       }\r
-                       #else\r
-                       {\r
-                               xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE;\r
-                       }\r
-                       #endif\r
-\r
-                       #if( ipconfigUSE_RMII != 0 )\r
-                       {\r
-                               xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;\r
-                       }\r
-                       #else\r
-                       {\r
-                               xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII;\r
-                       }\r
-                       #endif /* ipconfigUSE_RMII */\r
-\r
-                       hal_eth_init_status = HAL_ETH_Init( &xETH );\r
-\r
-                       /* Only for inspection by debugger. */\r
-                       ( void ) hal_eth_init_status;\r
-\r
-                       /* Set the TxDesc and RxDesc pointers. */\r
-                       xETH.TxDesc = DMATxDscrTab;\r
-                       xETH.RxDesc = DMARxDscrTab;\r
-\r
-                       /* Make sure that all unused fields are cleared. */\r
-                       memset( &DMATxDscrTab, '\0', sizeof( DMATxDscrTab ) );\r
-                       memset( &DMARxDscrTab, '\0', sizeof( DMARxDscrTab ) );\r
-\r
-                       /* Initialize Tx Descriptors list: Chain Mode */\r
-                       DMATxDescToClear = DMATxDscrTab;\r
-\r
-                       /* Initialise TX-descriptors. */\r
-                       prvDMATxDescListInit();\r
-\r
-                       /* Initialise RX-descriptors. */\r
-                       prvDMARxDescListInit();\r
-\r
-                       #if( ipconfigUSE_LLMNR != 0 )\r
-                       {\r
-                               /* Program the LLMNR address at index 1. */\r
-                               prvMACAddressConfig( &xETH, ETH_MAC_ADDRESS1, ( uint8_t *) xLLMNR_MACAddress );\r
-                       }\r
-                       #endif\r
-\r
-                       /* Force a negotiation with the Switch or Router and wait for LS. */\r
-                       prvEthernetUpdateConfig( pdTRUE );\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
-                       if( xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, niEMAC_HANDLER_TASK_PRIORITY, &xEMACTaskHandle ) == pdPASS )\r
-                       {\r
-                               /* The xTXDescriptorSemaphore and the task are created successfully. */\r
-                               xMacInitStatus = eMACPass;\r
-                       }\r
-                       else\r
-                       {\r
-                               xMacInitStatus = eMACFailed;\r
-                       }\r
-               }\r
-       } /* if( xEMACTaskHandle == NULL ) */\r
-\r
-       if( xMacInitStatus != eMACPass )\r
-       {\r
-               /* EMAC initialisation failed, return pdFAIL. */\r
-               xResult = pdFAIL;\r
-       }\r
-       else\r
-       {\r
-               if( xPhyObject.ulLinkStatusMask != 0uL )\r
-               {\r
-                       xETH.Instance->DMAIER |= ETH_DMA_ALL_INTS;\r
-                       xResult = pdPASS;\r
-                       FreeRTOS_printf( ( "Link Status is high\n" ) ) ;\r
-               }\r
-               else\r
-               {\r
-                       /* For now pdFAIL will be returned. But prvEMACHandlerTask() is running\r
-                       and it will keep on checking the PHY and set 'ulLinkStatusMask' when necessary. */\r
-                       xResult = pdFAIL;\r
-               }\r
-       }\r
-       /* When returning non-zero, the stack will become active and\r
-    start DHCP (in configured) */\r
-       return xResult;\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static void prvDMATxDescListInit()\r
-{\r
-ETH_DMADescTypeDef *pxDMADescriptor;\r
-BaseType_t xIndex;\r
-\r
-       /* Get the pointer on the first member of the descriptor list */\r
-       pxDMADescriptor = DMATxDscrTab;\r
-\r
-       /* Fill each DMA descriptor with the right values */\r
-       for( xIndex = 0; xIndex < ETH_TXBUFNB; xIndex++, pxDMADescriptor++ )\r
-       {\r
-               /* Set Second Address Chained bit */\r
-               pxDMADescriptor->Status = ETH_DMATXDESC_TCH;\r
-\r
-               #if( ipconfigZERO_COPY_TX_DRIVER == 0 )\r
-               {\r
-                       /* Set Buffer1 address pointer */\r
-                       pxDMADescriptor->Buffer1Addr = ( uint32_t )( Tx_Buff[ xIndex ] );\r
-               }\r
-               #endif\r
-\r
-               if( xETH.Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE )\r
-               {\r
-                       /* Set the DMA Tx descriptors checksum insertion for TCP, UDP, and ICMP */\r
-                       pxDMADescriptor->Status |= ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL;\r
-               }\r
-               else\r
-               {\r
-                       pxDMADescriptor->Status &= ~( ( uint32_t ) ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL );\r
-               }\r
-\r
-               /* Initialize the next descriptor with the Next Descriptor Polling Enable */\r
-               if( xIndex < ETH_TXBUFNB - 1 )\r
-               {\r
-                       /* Set next descriptor address register with next descriptor base address */\r
-                       pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) ( pxDMADescriptor + 1 );\r
-               }\r
-               else\r
-               {\r
-                       /* For last descriptor, set next descriptor address register equal to the first descriptor base address */\r
-                       pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) DMATxDscrTab;\r
-               }\r
-       }\r
-\r
-       /* Set Transmit Descriptor List Address Register */\r
-       xETH.Instance->DMATDLAR = ( uint32_t ) DMATxDscrTab;\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static void prvDMARxDescListInit()\r
-{\r
-ETH_DMADescTypeDef *pxDMADescriptor;\r
-BaseType_t xIndex;\r
-       /*\r
-        * RX-descriptors.\r
-        */\r
-\r
-       /* Get the pointer on the first member of the descriptor list */\r
-       pxDMADescriptor = DMARxDscrTab;\r
-\r
-       /* Fill each DMA descriptor with the right values */\r
-       for( xIndex = 0; xIndex < ETH_RXBUFNB; xIndex++, pxDMADescriptor++ )\r
-       {\r
-\r
-               /* Set Buffer1 size and Second Address Chained bit */\r
-               pxDMADescriptor->ControlBufferSize = ETH_DMARXDESC_RCH | (uint32_t)ETH_RX_BUF_SIZE;  \r
-\r
-               #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
-               {\r
-               /* Set Buffer1 address pointer */\r
-               NetworkBufferDescriptor_t *pxBuffer;\r
-\r
-                       pxBuffer = pxGetNetworkBufferWithDescriptor( ETH_RX_BUF_SIZE, 100ul );\r
-                       /* If the assert below fails, make sure that there are at least 'ETH_RXBUFNB'\r
-                       Network Buffers available during start-up ( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) */\r
-                       configASSERT( pxBuffer != NULL );\r
-                       if( pxBuffer != NULL )\r
-                       {\r
-                               pxDMADescriptor->Buffer1Addr = (uint32_t)pxBuffer->pucEthernetBuffer;\r
-                               pxDMADescriptor->Status = ETH_DMARXDESC_OWN;\r
-                       }\r
-               }\r
-               #else\r
-               {\r
-                       /* Set Buffer1 address pointer */\r
-                       pxDMADescriptor->Buffer1Addr = ( uint32_t )( Rx_Buff[ xIndex ] );\r
-                       /* Set Own bit of the Rx descriptor Status */\r
-                       pxDMADescriptor->Status = ETH_DMARXDESC_OWN;\r
-               }\r
-               #endif\r
-\r
-               /* Initialize the next descriptor with the Next Descriptor Polling Enable */\r
-               if( xIndex < ETH_RXBUFNB - 1 )\r
-               {\r
-                       /* Set next descriptor address register with next descriptor base address */\r
-                       pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t )( pxDMADescriptor + 1 );\r
-               }\r
-               else\r
-               {\r
-                       /* For last descriptor, set next descriptor address register equal to the first descriptor base address */\r
-                       pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) DMARxDscrTab;\r
-               }\r
-\r
-       }\r
-       /* Set Receive Descriptor List Address Register */\r
-       xETH.Instance->DMARDLAR = ( uint32_t ) DMARxDscrTab;\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static void prvMACAddressConfig(ETH_HandleTypeDef *heth, uint32_t ulIndex, uint8_t *Addr)\r
-{\r
-uint32_t ulTempReg;\r
-\r
-       ( void ) heth;\r
-\r
-       /* Calculate the selected MAC address high register. */\r
-       ulTempReg = 0x80000000ul | ( ( uint32_t ) Addr[ 5 ] << 8 ) | ( uint32_t ) Addr[ 4 ];\r
-\r
-       /* Load the selected MAC address high register. */\r
-       ( *(__IO uint32_t *)( ( uint32_t ) ( ETH_MAC_ADDR_HBASE + ulIndex ) ) ) = ulTempReg;\r
-\r
-       /* Calculate the selected MAC address low register. */\r
-       ulTempReg = ( ( uint32_t ) Addr[ 3 ] << 24 ) | ( ( uint32_t ) Addr[ 2 ] << 16 ) | ( ( uint32_t ) Addr[ 1 ] << 8 ) | Addr[ 0 ];\r
-\r
-       /* Load the selected MAC address low register */\r
-       ( *(__IO uint32_t *) ( ( uint32_t ) ( ETH_MAC_ADDR_LBASE + ulIndex ) ) ) = ulTempReg;\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend )\r
-{\r
-BaseType_t xReturn = pdFAIL;\r
-uint32_t ulTransmitSize = 0;\r
-__IO ETH_DMADescTypeDef *pxDmaTxDesc;\r
-/* Do not wait too long for a free TX DMA buffer. */\r
-const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );\r
-\r
-       /* Open a do {} while ( 0 ) loop to be able to call break. */\r
-       do\r
-       {\r
-               if( xCheckLoopback( pxDescriptor, bReleaseAfterSend ) != 0 )\r
-               {\r
-                       /* The packet has been sent back to the IP-task.\r
-                       The IP-task will further handle it.\r
-                       Do not release the descriptor. */\r
-                       bReleaseAfterSend = pdFALSE;\r
-                       break;\r
-               }\r
-               #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )\r
-               {\r
-               ProtocolPacket_t *pxPacket;\r
-\r
-                       /* If the peripheral must calculate the checksum, it wants\r
-                       the protocol checksum to have a value of zero. */\r
-                       pxPacket = ( ProtocolPacket_t * ) ( pxDescriptor->pucEthernetBuffer );\r
-\r
-                       if( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP )\r
-                       {\r
-                               pxPacket->xICMPPacket.xICMPHeader.usChecksum = ( uint16_t )0u;\r
-                       }\r
-               }\r
-               #endif /* ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM */\r
-               if( xPhyObject.ulLinkStatusMask != 0 )\r
-               {\r
-                       if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )\r
-                       {\r
-                               /* Time-out waiting for a free TX descriptor. */\r
-                               break;\r
-                       }\r
-\r
-                       /* This function does the actual transmission of the packet. The packet is\r
-                       contained in 'pxDescriptor' that is passed to the function. */\r
-                       pxDmaTxDesc = xETH.TxDesc;\r
-\r
-                       /* Is this buffer available? */\r
-                       configASSERT ( ( pxDmaTxDesc->Status & ETH_DMATXDESC_OWN ) == 0 );\r
-\r
-                       {\r
-                               /* Is this buffer available? */\r
-                               /* Get bytes in current buffer. */\r
-                               ulTransmitSize = pxDescriptor->xDataLength;\r
-\r
-                               if( ulTransmitSize > ETH_TX_BUF_SIZE )\r
-                               {\r
-                                       ulTransmitSize = ETH_TX_BUF_SIZE;\r
-                               }\r
-\r
-                               #if( ipconfigZERO_COPY_TX_DRIVER == 0 )\r
-                               {\r
-                                       /* Copy the bytes. */\r
-                                       memcpy( ( void * ) pxDmaTxDesc->Buffer1Addr, pxDescriptor->pucEthernetBuffer, ulTransmitSize );\r
-                               }\r
-                               #else\r
-                               {\r
-                                       configASSERT( bReleaseAfterSend != 0 );\r
-\r
-                                       /* Move the buffer. */\r
-                                       pxDmaTxDesc->Buffer1Addr = ( uint32_t )pxDescriptor->pucEthernetBuffer;\r
-                                       /* The Network Buffer has been passed to DMA, no need to release it. */\r
-                                       bReleaseAfterSend = pdFALSE_UNSIGNED;\r
-                               }\r
-                               #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
-\r
-                               /* Ask to set the IPv4 checksum.\r
-                               Also need an Interrupt on Completion so that 'vClearTXBuffers()' will be called.. */\r
-                               #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )\r
-                               {\r
-                                       pxDmaTxDesc->Status |= ETH_DMATXDESC_CIC_TCPUDPICMP_FULL | ETH_DMATXDESC_IC;\r
-                               }\r
-                               #else\r
-                               {\r
-                                       pxDmaTxDesc->Status &= ~( ( uint32_t ) ETH_DMATXDESC_CIC );\r
-                                       pxDmaTxDesc->Status |= ETH_DMATXDESC_IC;\r
-                               }\r
-                               #endif\r
-                               \r
-\r
-                               /* Prepare transmit descriptors to give to DMA. */\r
-\r
-                               /* Set LAST and FIRST segment */\r
-                               pxDmaTxDesc->Status |= ETH_DMATXDESC_FS | ETH_DMATXDESC_LS;\r
-                               /* Set frame size */\r
-                               pxDmaTxDesc->ControlBufferSize = ( ulTransmitSize & ETH_DMATXDESC_TBS1 );\r
-\r
-                               #if( NETWORK_BUFFERS_CACHED     != 0 )\r
-                               {\r
-                               BaseType_t xlength = CACHE_LINE_SIZE * ( ( ulTransmitSize + NETWORK_BUFFER_HEADER_SIZE + CACHE_LINE_SIZE - 1 ) / CACHE_LINE_SIZE );\r
-                               uint32_t *pulBuffer = ( uint32_t )( pxDescriptor->pucEthernetBuffer - NETWORK_BUFFER_HEADER_SIZE );\r
-                                       cache_clean_invalidate_by_addr( pulBuffer, xlength );\r
-                               }\r
-                               #endif\r
-\r
-                               /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */\r
-                               pxDmaTxDesc->Status |= ETH_DMATXDESC_OWN;\r
-\r
-                               /* Point to next descriptor */\r
-                               xETH.TxDesc = ( ETH_DMADescTypeDef * ) ( xETH.TxDesc->Buffer2NextDescAddr );\r
-                               /* Ensure completion of memory access */\r
-                               __DSB();\r
-                               /* Resume DMA transmission*/\r
-                               xETH.Instance->DMATPDR = 0;\r
-                               iptraceNETWORK_INTERFACE_TRANSMIT();\r
-                               xReturn = pdPASS;\r
-                       }\r
-               }\r
-               else\r
-               {\r
-                       /* The PHY has no Link Status, packet shall be dropped. */\r
-               }\r
-       } while( 0 );\r
-       /* The buffer has been sent so can be released. */\r
-       if( bReleaseAfterSend != pdFALSE )\r
-       {\r
-               vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
-       }\r
-\r
-       return xReturn;\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static BaseType_t xMayAcceptPacket( uint8_t *pcBuffer )\r
-{\r
-const ProtocolPacket_t *pxProtPacket = ( const ProtocolPacket_t * )pcBuffer;\r
-\r
-       switch( pxProtPacket->xTCPPacket.xEthernetHeader.usFrameType )\r
-       {\r
-       case ipARP_FRAME_TYPE:\r
-               /* Check it later. */\r
-               return pdTRUE;\r
-       case ipIPv4_FRAME_TYPE:\r
-               /* Check it here. */\r
-               break;\r
-       default:\r
-               /* Refuse the packet. */\r
-               return pdFALSE;\r
-       }\r
-\r
-       #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )\r
-       {\r
-               const IPHeader_t *pxIPHeader = &(pxProtPacket->xTCPPacket.xIPHeader);\r
-               uint32_t ulDestinationIPAddress;\r
-\r
-               /* Ensure that the incoming packet is not fragmented (only outgoing packets\r
-                * can be fragmented) as these are the only handled IP frames currently. */\r
-               if( ( pxIPHeader->usFragmentOffset & FreeRTOS_ntohs( ipFRAGMENT_OFFSET_BIT_MASK ) ) != 0U )\r
-               {\r
-                       return pdFALSE;\r
-               }\r
-               /* HT: Might want to make the following configurable because\r
-                * most IP messages have a standard length of 20 bytes */\r
-\r
-               /* 0x45 means: IPv4 with an IP header of 5 x 4 = 20 bytes\r
-                * 0x47 means: IPv4 with an IP header of 7 x 4 = 28 bytes */\r
-               if( pxIPHeader->ucVersionHeaderLength < 0x45 || pxIPHeader->ucVersionHeaderLength > 0x4F )\r
-               {\r
-                       return pdFALSE;\r
-               }\r
-\r
-               ulDestinationIPAddress = pxIPHeader->ulDestinationIPAddress;\r
-               /* Is the packet for this node? */\r
-               if( ( ulDestinationIPAddress != *ipLOCAL_IP_ADDRESS_POINTER ) &&\r
-                       /* Is it a broadcast address x.x.x.255 ? */\r
-                       ( ( FreeRTOS_ntohl( ulDestinationIPAddress ) & 0xff ) != 0xff ) &&\r
-               #if( ipconfigUSE_LLMNR == 1 )\r
-                       ( ulDestinationIPAddress != ipLLMNR_IP_ADDR ) &&\r
-               #endif\r
-                       ( *ipLOCAL_IP_ADDRESS_POINTER != 0 ) ) {\r
-                       FreeRTOS_printf( ( "Drop IP %lxip\n", FreeRTOS_ntohl( ulDestinationIPAddress ) ) );\r
-                       return pdFALSE;\r
-               }\r
-\r
-               if( pxIPHeader->ucProtocol == ipPROTOCOL_UDP )\r
-               {\r
-               uint16_t usSourcePort = FreeRTOS_ntohs( pxProtPacket->xUDPPacket.xUDPHeader.usSourcePort );\r
-               uint16_t usDestinationPort = FreeRTOS_ntohs( pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort );\r
-\r
-                       if( ( xPortHasUDPSocket( pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort ) == pdFALSE )\r
-                       #if ipconfigUSE_LLMNR == 1\r
-                               && ( usDestinationPort != ipLLMNR_PORT )\r
-                               && ( usSourcePort != ipLLMNR_PORT )\r
-                       #endif\r
-                       #if ipconfigUSE_NBNS == 1\r
-                               && ( usDestinationPort != ipNBNS_PORT )\r
-                               && ( usSourcePort != ipNBNS_PORT )\r
-                       #endif\r
-                       #if ipconfigUSE_DNS == 1\r
-                               && ( usSourcePort != ipDNS_PORT )\r
-                       #endif\r
-                               ) {\r
-                               /* Drop this packet, not for this device. */\r
-                               /* FreeRTOS_printf( ( "Drop: UDP port %d -> %d\n", usSourcePort, usDestinationPort ) ); */\r
-                               return pdFALSE;\r
-                       }\r
-               }\r
-       }\r
-       #endif  /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */\r
-       return pdTRUE;\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static void prvPassEthMessages( NetworkBufferDescriptor_t *pxDescriptor )\r
-{\r
-IPStackEvent_t xRxEvent;\r
-\r
-       xRxEvent.eEventType = eNetworkRxEvent;\r
-       xRxEvent.pvData = ( void * ) pxDescriptor;\r
-\r
-       if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 1000 ) != pdPASS )\r
-       {\r
-               /* The buffer could not be sent to the stack so must be released again.\r
-               This is a deferred handler taskr, not a real interrupt, so it is ok to\r
-               use the task level function here. */\r
-               #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )\r
-               {\r
-                       do\r
-                       {\r
-                               NetworkBufferDescriptor_t *pxNext = pxDescriptor->pxNextBuffer;\r
-                               vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
-                               pxDescriptor = pxNext;\r
-                       } while( pxDescriptor != NULL );\r
-               }\r
-               #else\r
-               {\r
-                       vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
-               }\r
-               #endif  /* ipconfigUSE_LINKED_RX_MESSAGES */\r
-               iptraceETHERNET_RX_EVENT_LOST();\r
-               FreeRTOS_printf( ( "prvPassEthMessages: Can not queue return packet!\n" ) );\r
-       }\r
-       else\r
-       {\r
-               iptraceNETWORK_INTERFACE_RECEIVE();\r
-       }\r
-}\r
-\r
-static BaseType_t prvNetworkInterfaceInput( void )\r
-{\r
-NetworkBufferDescriptor_t *pxCurDescriptor;\r
-NetworkBufferDescriptor_t *pxNewDescriptor = NULL;\r
-#if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )\r
-       NetworkBufferDescriptor_t *pxFirstDescriptor = NULL;\r
-       NetworkBufferDescriptor_t *pxLastDescriptor = NULL;\r
-#endif\r
-BaseType_t xReceivedLength = 0;\r
-__IO ETH_DMADescTypeDef *pxDMARxDescriptor;\r
-const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( niDESCRIPTOR_WAIT_TIME_MS );\r
-uint8_t *pucBuffer;\r
-\r
-       pxDMARxDescriptor = xETH.RxDesc;\r
-\r
-       while( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_OWN ) == 0u )\r
-       {\r
-       BaseType_t xAccepted = pdTRUE;\r
-               /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */\r
-               xReceivedLength = ( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_FL ) >> ETH_DMARXDESC_FRAMELENGTHSHIFT ) - 4;\r
-\r
-               pucBuffer = (uint8_t *) pxDMARxDescriptor->Buffer1Addr;\r
-\r
-               /* Update the ETHERNET DMA global Rx descriptor with next Rx descriptor */\r
-               /* Chained Mode */    \r
-               /* Selects the next DMA Rx descriptor list for next buffer to read */ \r
-               xETH.RxDesc = ( ETH_DMADescTypeDef* )pxDMARxDescriptor->Buffer2NextDescAddr;\r
-\r
-               /* In order to make the code easier and faster, only packets in a single buffer\r
-               will be accepted.  This can be done by making the buffers large enough to\r
-               hold a complete Ethernet packet (1536 bytes).\r
-               Therefore, two sanity checks: */\r
-               configASSERT( xReceivedLength <= ETH_RX_BUF_SIZE );\r
-\r
-               if( ( pxDMARxDescriptor->Status & ( ETH_DMARXDESC_CE | ETH_DMARXDESC_IPV4HCE | ETH_DMARXDESC_FT ) ) != ETH_DMARXDESC_FT )\r
-               {\r
-                       /* Not an Ethernet frame-type or a checmsum error. */\r
-                       xAccepted = pdFALSE;\r
-               }\r
-               else\r
-               {\r
-                       /* See if this packet must be handled. */\r
-                       xAccepted = xMayAcceptPacket( pucBuffer );\r
-               }\r
-\r
-               if( xAccepted != pdFALSE )\r
-               {\r
-                       /* The packet wil be accepted, but check first if a new Network Buffer can\r
-                       be obtained. If not, the packet will still be dropped. */\r
-                       pxNewDescriptor = pxGetNetworkBufferWithDescriptor( ETH_RX_BUF_SIZE, xDescriptorWaitTime );\r
-\r
-                       if( pxNewDescriptor == NULL )\r
-                       {\r
-                               /* A new descriptor can not be allocated now. This packet will be dropped. */\r
-                               xAccepted = pdFALSE;\r
-                       }\r
-               }\r
-               #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
-               {\r
-                       /* Find out which Network Buffer was originally passed to the descriptor. */\r
-                       pxCurDescriptor = pxPacketBuffer_to_NetworkBuffer( pucBuffer );\r
-                       configASSERT( pxCurDescriptor != NULL );\r
-               }\r
-               #else\r
-               {\r
-                       /* In this mode, the two descriptors are the same. */\r
-                       pxCurDescriptor = pxNewDescriptor;\r
-                       if( pxNewDescriptor != NULL )\r
-                       {\r
-                               /* The packet is acepted and a new Network Buffer was created,\r
-                               copy data to the Network Bufffer. */\r
-                               memcpy( pxNewDescriptor->pucEthernetBuffer, pucBuffer, xReceivedLength );\r
-                       }\r
-               }\r
-               #endif\r
-\r
-               if( xAccepted != pdFALSE )\r
-               {\r
-                       pxCurDescriptor->xDataLength = xReceivedLength;\r
-                       #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )\r
-                       {\r
-                               pxCurDescriptor->pxNextBuffer = NULL;\r
-\r
-                               if( pxFirstDescriptor == NULL )\r
-                               {\r
-                                       // Becomes the first message\r
-                                       pxFirstDescriptor = pxCurDescriptor;\r
-                               }\r
-                               else if( pxLastDescriptor != NULL )\r
-                               {\r
-                                       // Add to the tail\r
-                                       pxLastDescriptor->pxNextBuffer = pxCurDescriptor;\r
-                               }\r
-\r
-                               pxLastDescriptor = pxCurDescriptor;\r
-                       }\r
-                       #else\r
-                       {\r
-                               prvPassEthMessages( pxCurDescriptor );\r
-                       }\r
-                       #endif\r
-               }\r
-\r
-               /* Release descriptors to DMA */\r
-               #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
-               {\r
-                       /* Set Buffer1 address pointer */\r
-                       if( pxNewDescriptor != NULL )\r
-                       {\r
-                               pxDMARxDescriptor->Buffer1Addr = (uint32_t)pxNewDescriptor->pucEthernetBuffer;\r
-                       }\r
-                       else\r
-                       {\r
-                               /* The packet was dropped and the same Network\r
-                               Buffer will be used to receive a new packet. */\r
-                       }\r
-               }\r
-               #endif /* ipconfigZERO_COPY_RX_DRIVER */\r
-\r
-               /* Set Buffer1 size and Second Address Chained bit */\r
-               pxDMARxDescriptor->ControlBufferSize = ETH_DMARXDESC_RCH | (uint32_t)ETH_RX_BUF_SIZE;  \r
-               pxDMARxDescriptor->Status = ETH_DMARXDESC_OWN;\r
-\r
-               /* Ensure completion of memory access */\r
-               __DSB();\r
-               /* When Rx Buffer unavailable flag is set clear it and resume\r
-               reception. */\r
-               if( ( xETH.Instance->DMASR & ETH_DMASR_RBUS ) != 0 )\r
-               {\r
-                       /* Clear RBUS ETHERNET DMA flag. */\r
-                       xETH.Instance->DMASR = ETH_DMASR_RBUS;\r
-\r
-                       /* Resume DMA reception. */\r
-                       xETH.Instance->DMARPDR = 0;\r
-               }\r
-               pxDMARxDescriptor = xETH.RxDesc;\r
-       }\r
-\r
-       #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )\r
-       {\r
-               if( pxFirstDescriptor != NULL )\r
-               {\r
-                       prvPassEthMessages( pxFirstDescriptor );\r
-               }\r
-       }\r
-       #endif  /* ipconfigUSE_LINKED_RX_MESSAGES */\r
-\r
-       return ( xReceivedLength > 0 );\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-\r
-BaseType_t xSTM32_PhyRead( BaseType_t xAddress, BaseType_t xRegister, uint32_t *pulValue )\r
-{\r
-uint16_t usPrevAddress = xETH.Init.PhyAddress;\r
-BaseType_t xResult;\r
-HAL_StatusTypeDef xHALResult;\r
-\r
-       xETH.Init.PhyAddress = xAddress;\r
-       xHALResult = HAL_ETH_ReadPHYRegister( &xETH, ( uint16_t )xRegister, pulValue );\r
-       xETH.Init.PhyAddress = usPrevAddress;\r
-\r
-       if( xHALResult == HAL_OK )\r
-       {\r
-               xResult = 0;\r
-       }\r
-       else\r
-       {\r
-               xResult = -1;\r
-       }\r
-       return xResult;\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-BaseType_t xSTM32_PhyWrite( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue )\r
-{\r
-uint16_t usPrevAddress = xETH.Init.PhyAddress;\r
-BaseType_t xResult;\r
-HAL_StatusTypeDef xHALResult;\r
-\r
-       xETH.Init.PhyAddress = xAddress;\r
-       xHALResult = HAL_ETH_WritePHYRegister( &xETH, ( uint16_t )xRegister, ulValue );\r
-       xETH.Init.PhyAddress = usPrevAddress;\r
-\r
-       if( xHALResult == HAL_OK )\r
-       {\r
-               xResult = 0;\r
-       }\r
-       else\r
-       {\r
-               xResult = -1;\r
-       }\r
-       return xResult;\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-void vMACBProbePhy( void )\r
-{\r
-       vPhyInitialise( &xPhyObject, xSTM32_PhyRead, xSTM32_PhyWrite );\r
-       xPhyDiscover( &xPhyObject );\r
-       xPhyConfigure( &xPhyObject, &xPHYProperties );\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static void prvEthernetUpdateConfig( BaseType_t xForce )\r
-{\r
-       FreeRTOS_printf( ( "prvEthernetUpdateConfig: LS mask %02lX Force %d\n",\r
-               xPhyObject.ulLinkStatusMask,\r
-               ( int )xForce ) );\r
-\r
-       if( ( xForce != pdFALSE ) || ( xPhyObject.ulLinkStatusMask != 0 ) )\r
-       {\r
-               /* Restart the auto-negotiation. */\r
-               if( xETH.Init.AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE )\r
-               {\r
-                       xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) );\r
-\r
-                       /* Configure the MAC with the Duplex Mode fixed by the\r
-                       auto-negotiation process. */\r
-                       if( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL )\r
-                       {\r
-                               xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;\r
-                       }\r
-                       else\r
-                       {\r
-                               xETH.Init.DuplexMode = ETH_MODE_HALFDUPLEX;\r
-                       }\r
-\r
-                       /* Configure the MAC with the speed fixed by the\r
-                       auto-negotiation process. */\r
-                       if( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 )\r
-                       {\r
-                               xETH.Init.Speed = ETH_SPEED_10M;\r
-                       }\r
-                       else\r
-                       {\r
-                               xETH.Init.Speed = ETH_SPEED_100M;\r
-                       }\r
-               }\r
-               else /* AutoNegotiation Disable */\r
-               {\r
-                       /* Check parameters */\r
-                       assert_param( IS_ETH_SPEED( xETH.Init.Speed ) );\r
-                       assert_param( IS_ETH_DUPLEX_MODE( xETH.Init.DuplexMode ) );\r
-\r
-                       if( xETH.Init.DuplexMode == ETH_MODE_FULLDUPLEX )\r
-                       {\r
-                               xPhyObject.xPhyPreferences.ucDuplex = PHY_DUPLEX_HALF;\r
-                       }\r
-                       else\r
-                       {\r
-                               xPhyObject.xPhyPreferences.ucDuplex = PHY_DUPLEX_FULL;\r
-                       }\r
-\r
-                       if( xETH.Init.Speed == ETH_SPEED_10M )\r
-                       {\r
-                               xPhyObject.xPhyPreferences.ucSpeed = PHY_SPEED_10;\r
-                       }\r
-                       else\r
-                       {\r
-                               xPhyObject.xPhyPreferences.ucSpeed = PHY_SPEED_100;\r
-                       }\r
-\r
-                       xPhyObject.xPhyPreferences.ucMDI_X = PHY_MDIX_AUTO;\r
-\r
-                       /* Use predefined (fixed) configuration. */\r
-                       xPhyFixedValue( &xPhyObject, xPhyGetMask( &xPhyObject ) );\r
-               }\r
-\r
-               /* ETHERNET MAC Re-Configuration */\r
-               HAL_ETH_ConfigMAC( &xETH, (ETH_MACInitTypeDef *) NULL);\r
-\r
-               /* Restart MAC interface */\r
-               HAL_ETH_Start( &xETH);\r
-       }\r
-       else\r
-       {\r
-               /* Stop MAC interface */\r
-               HAL_ETH_Stop( &xETH );\r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-BaseType_t xGetPhyLinkStatus( void )\r
-{\r
-BaseType_t xReturn;\r
-\r
-       if( xPhyObject.ulLinkStatusMask != 0 )\r
-       {\r
-               xReturn = pdPASS;\r
-       }\r
-       else\r
-       {\r
-               xReturn = pdFAIL;\r
-       }\r
-\r
-       return xReturn;\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-/* Uncomment this in case BufferAllocation_1.c is used. */\r
-\r
-void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )\r
-{\r
-static __attribute__ ((section(".first_data"))) uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * ETH_MAX_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 += ETH_MAX_PACKET_SIZE;\r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static void prvEMACHandlerTask( void *pvParameters )\r
-{\r
-UBaseType_t uxLastMinBufferCount = 0;\r
-#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
-UBaseType_t uxLastMinQueueSpace = 0;\r
-#endif\r
-UBaseType_t uxCurrentCount;\r
-BaseType_t xResult;\r
-const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );\r
-\r
-       /* Remove compiler warnings about unused parameters. */\r
-       ( void ) pvParameters;\r
-\r
-       for( ;; )\r
-       {\r
-               xResult = 0;\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( xTXDescriptorSemaphore != NULL )\r
-               {\r
-               static UBaseType_t uxLowestSemCount = ( UBaseType_t ) ETH_TXBUFNB - 1;\r
-\r
-                       uxCurrentCount = uxSemaphoreGetCount( xTXDescriptorSemaphore );\r
-                       if( uxLowestSemCount > uxCurrentCount )\r
-                       {\r
-                               uxLowestSemCount = uxCurrentCount;\r
-                               FreeRTOS_printf( ( "TX DMA buffers: lowest %lu\n", uxLowestSemCount ) );\r
-                       }\r
-\r
-               }\r
-\r
-               #if( ipconfigCHECK_IP_QUEUE_SPACE != 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( ( ulISREvents & EMAC_IF_ALL_EVENT ) == 0 )\r
-               {\r
-                       /* No events to process now, wait for the next. */\r
-                       ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );\r
-               }\r
-\r
-               if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 )\r
-               {\r
-                       ulISREvents &= ~EMAC_IF_RX_EVENT;\r
-\r
-                       xResult = prvNetworkInterfaceInput();\r
-               }\r
-\r
-               if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )\r
-               {\r
-                       /* Code to release TX buffers if zero-copy is used. */\r
-                       ulISREvents &= ~EMAC_IF_TX_EVENT;\r
-                       /* Check if DMA packets have been delivered. */\r
-                       vClearTXBuffers();\r
-               }\r
-\r
-               if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 )\r
-               {\r
-                       /* Future extension: logging about errors that occurred. */\r
-                       ulISREvents &= ~EMAC_IF_ERR_EVENT;\r
-               }\r
-               if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != 0 )\r
-               {\r
-                       /* Something has changed to a Link Status, need re-check. */\r
-                       prvEthernetUpdateConfig( pdFALSE );\r
-               }\r
-       }\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-void ETH_IRQHandler( void )\r
-{\r
-       HAL_ETH_IRQHandler( &xETH );\r
-}\r
-\r
+/*
+ * Some constants, hardware definitions and comments taken from ST's HAL driver
+ * library, COPYRIGHT(c) 2015 STMicroelectronics.
+ */
+
+/*
+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 "FreeRTOS_DNS.h"
+#include "NetworkBufferManagement.h"
+#include "NetworkInterface.h"
+
+/* ST includes. */
+#include "stm32f4xx_hal.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
+
+/* Interrupt events to process.  Currently only the Rx event is processed
+although code for other events is included to allow for possible future
+expansion. */
+#define EMAC_IF_RX_EVENT        1UL
+#define EMAC_IF_TX_EVENT        2UL
+#define EMAC_IF_ERR_EVENT       4UL
+#define EMAC_IF_ALL_EVENT       ( EMAC_IF_RX_EVENT | EMAC_IF_TX_EVENT | EMAC_IF_ERR_EVENT )
+
+#define ETH_DMA_ALL_INTS \
+       ( ETH_DMA_IT_TST | ETH_DMA_IT_PMT | ETH_DMA_IT_MMC | ETH_DMA_IT_NIS | ETH_DMA_IT_ER | \
+         ETH_DMA_IT_FBE | ETH_DMA_IT_RWT | ETH_DMA_IT_RPS | ETH_DMA_IT_RBU | ETH_DMA_IT_R | \
+         ETH_DMA_IT_TU | ETH_DMA_IT_RO | ETH_DMA_IT_TJT | ETH_DMA_IT_TPS | ETH_DMA_IT_T )
+
+/* Naming and numbering of PHY registers. */
+#define PHY_REG_00_BMCR                        0x00    /* Basic Mode Control Register */
+#define PHY_REG_01_BMSR                        0x01    /* Basic Mode Status Register */
+#define PHY_REG_02_PHYSID1             0x02    /* PHYS ID 1 */
+#define PHY_REG_03_PHYSID2             0x03    /* PHYS ID 2 */
+#define PHY_REG_04_ADVERTISE   0x04    /* Advertisement control reg */
+
+#define PHY_ID_LAN8720         0x0007c0f0
+#define PHY_ID_DP83848I                0x20005C90
+
+#ifndef USE_STM324xG_EVAL
+       #define USE_STM324xG_EVAL       1
+#endif
+
+#if( USE_STM324xG_EVAL == 0 )
+       #define EXPECTED_PHY_ID                 PHY_ID_LAN8720
+       #define PHY_REG_1F_PHYSPCS              0x1F    /* 31 RW PHY Special Control Status */
+       /* Use 3 bits in register 31 */
+       #define PHYSPCS_SPEED_MASK              0x0C
+       #define PHYSPCS_SPEED_10                0x04
+       #define PHYSPCS_SPEED_100               0x08
+       #define PHYSPCS_FULL_DUPLEX             0x10
+#else
+       #define EXPECTED_PHY_ID         PHY_ID_DP83848I
+
+       #define PHY_REG_10_PHY_SR               0x10    /* PHY status register Offset */
+       #define PHY_REG_19_PHYCR                0x19    /* 25 RW PHY Control Register */
+#endif
+
+/* Some defines used internally here to indicate preferences about speed, MDIX
+(wired direct or crossed), and duplex (half or full). */
+#define        PHY_SPEED_10       1
+#define        PHY_SPEED_100      2
+#define        PHY_SPEED_AUTO     (PHY_SPEED_10|PHY_SPEED_100)
+
+#define        PHY_MDIX_DIRECT    1
+#define        PHY_MDIX_CROSSED   2
+#define        PHY_MDIX_AUTO      (PHY_MDIX_CROSSED|PHY_MDIX_DIRECT)
+
+#define        PHY_DUPLEX_HALF    1
+#define        PHY_DUPLEX_FULL    2
+#define        PHY_DUPLEX_AUTO    (PHY_DUPLEX_FULL|PHY_DUPLEX_HALF)
+
+#define PHY_AUTONEGO_COMPLETE    ((uint16_t)0x0020)  /*!< Auto-Negotiation process completed   */
+
+/*
+ * Description of all capabilities that can be advertised to
+ * the peer (usually a switch or router).
+ */
+#define ADVERTISE_CSMA                 0x0001          /* Only selector supported. */
+#define ADVERTISE_10HALF               0x0020          /* Try for 10mbps half-duplex. */
+#define ADVERTISE_10FULL               0x0040          /* Try for 10mbps full-duplex. */
+#define ADVERTISE_100HALF              0x0080          /* Try for 100mbps half-duplex. */
+#define ADVERTISE_100FULL              0x0100          /* Try for 100mbps full-duplex. */
+
+#define ADVERTISE_ALL                  ( ADVERTISE_10HALF | ADVERTISE_10FULL | \
+                                                                 ADVERTISE_100HALF | ADVERTISE_100FULL)
+
+/*
+ * Value for the 'PHY_REG_00_BMCR', the PHY's Basic Mode Control Register
+ */
+#define BMCR_FULLDPLX                  0x0100          /* Full duplex. */
+#define BMCR_ANRESTART                 0x0200          /* Auto negotiation restart. */
+#define BMCR_ANENABLE                  0x1000          /* Enable auto negotiation. */
+#define BMCR_SPEED100                  0x2000          /* Select 100Mbps. */
+#define BMCR_RESET                             0x8000          /* Reset the PHY. */
+
+#define PHYCR_MDIX_EN                  0x8000          /* Enable Auto MDIX. */
+#define PHYCR_MDIX_FORCE               0x4000          /* Force MDIX crossed. */
+
+#define ipFRAGMENT_OFFSET_BIT_MASK             ( ( uint16_t ) 0x0fff ) /* The bits in the two byte IP header field that make up the fragment offset value. */
+
+/*
+ * Most users will want a PHY that negotiates about
+ * the connection properties: speed, dmix and duplex.
+ * On some rare cases, you want to select what is being
+ * advertised, properties like MDIX and duplex.
+ */
+
+#if !defined( ipconfigETHERNET_AN_ENABLE )
+       /* Enable auto-negotiation */
+       #define ipconfigETHERNET_AN_ENABLE                              1
+#endif
+
+#if !defined( ipconfigETHERNET_AUTO_CROSS_ENABLE )
+       #define ipconfigETHERNET_AUTO_CROSS_ENABLE              1
+#endif
+
+#if( ipconfigETHERNET_AN_ENABLE == 0 )
+       /*
+        * The following three defines are only used in case there
+        * is no auto-negotiation.
+        */
+       #if !defined( ipconfigETHERNET_CROSSED_LINK )
+               #define ipconfigETHERNET_CROSSED_LINK                   1
+       #endif
+
+       #if !defined( ipconfigETHERNET_USE_100MB )
+               #define ipconfigETHERNET_USE_100MB                              1
+       #endif
+
+       #if !defined( ipconfigETHERNET_USE_FULL_DUPLEX )
+               #define ipconfigETHERNET_USE_FULL_DUPLEX                1
+       #endif
+#endif /* ipconfigETHERNET_AN_ENABLE == 0 */
+
+/* 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
+
+/*-----------------------------------------------------------*/
+
+/*
+ * A deferred interrupt handler task that processes
+ */
+static void prvEMACHandlerTask( void *pvParameters );
+
+/*
+ * Force a negotiation with the Switch or Router and wait for LS.
+ */
+static void prvEthernetUpdateConfig( BaseType_t xForce );
+
+/*
+ * See if there is a new packet and forward it to the IP-task.
+ */
+static BaseType_t prvNetworkInterfaceInput( void );
+
+#if( ipconfigUSE_LLMNR != 0 )
+       /*
+        * For LLMNR, an extra MAC-address must be configured to
+        * be able to receive the multicast messages.
+        */
+       static void prvMACAddressConfig(ETH_HandleTypeDef *heth, uint32_t ulIndex, uint8_t *Addr);
+#endif
+
+/*
+ * Check if a given packet should be accepted.
+ */
+static BaseType_t xMayAcceptPacket( uint8_t *pcBuffer );
+
+/*
+ * Initialise the TX descriptors.
+ */
+static void prvDMATxDescListInit( void );
+
+/*
+ * Initialise the RX descriptors.
+ */
+static void prvDMARxDescListInit( void );
+
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+       /* After packets have been sent, the network
+       buffers will be released. */
+       static void vClearTXBuffers( void );
+#endif /* ipconfigZERO_COPY_TX_DRIVER */
+
+/*-----------------------------------------------------------*/
+
+typedef struct _PhyProperties_t
+{
+       uint8_t speed;
+       uint8_t mdix;
+       uint8_t duplex;
+       uint8_t spare;
+} PhyProperties_t;
+
+/* Bit map of outstanding ETH interrupt events for processing.  Currently only
+the Rx interrupt is handled, although code is included for other events to
+enable future expansion. */
+static volatile uint32_t ulISREvents;
+
+/* 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
+
+/* Ethernet handle. */
+static ETH_HandleTypeDef xETH;
+
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+       /* xTXDescriptorSemaphore is a counting semaphore with
+       a maximum count of ETH_TXBUFNB, which is the number of
+       DMA TX descriptors. */
+       static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;
+#endif /* ipconfigZERO_COPY_TX_DRIVER */
+
+/*
+ * Note: it is adviced to define both
+ *
+ *     #define  ipconfigZERO_COPY_RX_DRIVER   1
+ *     #define  ipconfigZERO_COPY_TX_DRIVER   1
+ *
+ * The method using memcpy is slower and probaly uses more RAM memory.
+ * The possibility is left in the code just for comparison.
+ *
+ * It is adviced to define ETH_TXBUFNB at least 4. Note that no
+ * TX buffers are allocated in a zero-copy driver.
+ */
+/* MAC buffers: ---------------------------------------------------------*/
+__ALIGN_BEGIN ETH_DMADescTypeDef  DMARxDscrTab[ ETH_RXBUFNB ] __ALIGN_END;/* Ethernet Rx MA Descriptor */
+#if( ipconfigZERO_COPY_RX_DRIVER == 0 )
+       __ALIGN_BEGIN uint8_t Rx_Buff[ ETH_RXBUFNB ][ ETH_RX_BUF_SIZE ] __ALIGN_END; /* Ethernet Receive Buffer */
+#endif
+
+__ALIGN_BEGIN ETH_DMADescTypeDef  DMATxDscrTab[ ETH_TXBUFNB ] __ALIGN_END;/* Ethernet Tx DMA Descriptor */
+#if( ipconfigZERO_COPY_TX_DRIVER == 0 )
+       __ALIGN_BEGIN uint8_t Tx_Buff[ ETH_TXBUFNB ][ ETH_TX_BUF_SIZE ] __ALIGN_END; /* Ethernet Transmit Buffer */
+#endif
+
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+       /* DMATxDescToClear points to the next TX DMA descriptor
+       that must be cleared by vClearTXBuffers(). */
+       static __IO ETH_DMADescTypeDef  *DMATxDescToClear;
+#endif
+
+/* Value to be written into the 'Basic mode Control Register'. */
+static uint32_t ulBCRvalue;
+
+/* Value to be written into the 'Advertisement Control Register'. */
+static uint32_t ulACRValue;
+
+/* 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. */
+static TaskHandle_t xEMACTaskHandle = NULL;
+
+/* For local use only: describe the PHY's properties: */
+const PhyProperties_t xPHYProperties =
+{
+       #if( ipconfigETHERNET_AN_ENABLE != 0 )
+               .speed = PHY_SPEED_AUTO,
+               .duplex = PHY_DUPLEX_AUTO,
+       #else
+               #if( ipconfigETHERNET_USE_100MB != 0 )
+                       .speed = PHY_SPEED_100,
+               #else
+                       .speed = PHY_SPEED_10,
+               #endif
+
+               #if( ipconfigETHERNET_USE_FULL_DUPLEX != 0 )
+                       .duplex = PHY_DUPLEX_FULL,
+               #else
+                       .duplex = PHY_DUPLEX_HALF,
+               #endif
+       #endif
+
+       #if( ipconfigETHERNET_AN_ENABLE != 0 ) && ( ipconfigETHERNET_AUTO_CROSS_ENABLE != 0 )
+               .mdix = PHY_MDIX_AUTO,
+       #elif( ipconfigETHERNET_CROSSED_LINK != 0 )
+               .mdix = PHY_MDIX_CROSSED,
+       #else
+               .mdix = PHY_MDIX_DIRECT,
+       #endif
+};
+
+/*-----------------------------------------------------------*/
+
+void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef *heth )
+{
+BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+
+       /* Ethernet RX-Complete callback function, elsewhere declared as weak. */
+    ulISREvents |= EMAC_IF_RX_EVENT;
+       /* Wakeup the prvEMACHandlerTask. */
+       if( xEMACTaskHandle != NULL )
+       {
+               vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
+               portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
+       }
+}
+/*-----------------------------------------------------------*/
+
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+       void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef *heth )
+       {
+       BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+
+               /* This call-back is only useful in case packets are being sent
+               zero-copy.  Once they're sent, the buffers will be released
+               by the function vClearTXBuffers(). */
+               ulISREvents |= EMAC_IF_TX_EVENT;
+               /* Wakeup the prvEMACHandlerTask. */
+               if( xEMACTaskHandle != NULL )
+               {
+                       vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
+                       portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
+               }
+
+       }
+#endif /* ipconfigZERO_COPY_TX_DRIVER */
+
+/*-----------------------------------------------------------*/
+
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+       static void vClearTXBuffers()
+       {
+       __IO ETH_DMADescTypeDef  *txLastDescriptor = xETH.TxDesc;
+       NetworkBufferDescriptor_t *pxNetworkBuffer;
+       uint8_t *ucPayLoad;
+       size_t uxCount = ( ( UBaseType_t ) ETH_TXBUFNB ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );
+
+               /* This function is called after a TX-completion interrupt.
+               It will release each Network Buffer used in xNetworkInterfaceOutput().
+               'uxCount' represents the number of descriptors given to DMA for transmission.
+               After sending a packet, the DMA will clear the 'ETH_DMATXDESC_OWN' bit. */
+               while( ( uxCount > 0 ) && ( ( DMATxDescToClear->Status & ETH_DMATXDESC_OWN ) == 0 ) )
+               {
+                       if( ( DMATxDescToClear == txLastDescriptor ) && ( uxCount != ETH_TXBUFNB ) )
+                       {
+                               break;
+                       }
+
+                       ucPayLoad = ( uint8_t * )DMATxDescToClear->Buffer1Addr;
+
+                       if( ucPayLoad != NULL )
+                       {
+                               pxNetworkBuffer = pxPacketBuffer_to_NetworkBuffer( ucPayLoad );
+                               if( pxNetworkBuffer != NULL )
+                               {
+                                       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ) ;
+                               }
+                               DMATxDescToClear->Buffer1Addr = ( uint32_t )0u;
+                       }
+
+                       DMATxDescToClear = ( ETH_DMADescTypeDef * )( DMATxDescToClear->Buffer2NextDescAddr );
+
+                       uxCount--;
+                       /* Tell the counting semaphore that one more TX descriptor is available. */
+                       xSemaphoreGive( xTXDescriptorSemaphore );
+               }
+       }
+#endif /* ipconfigZERO_COPY_TX_DRIVER */
+/*-----------------------------------------------------------*/
+
+BaseType_t xNetworkInterfaceInitialise( void )
+{
+HAL_StatusTypeDef hal_eth_init_status;
+BaseType_t xResult;
+
+       if( xEMACTaskHandle == NULL )
+       {
+               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+               {
+                       if( xTXDescriptorSemaphore == NULL )
+                       {
+                               xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ETH_TXBUFNB, ( UBaseType_t ) ETH_TXBUFNB );
+                               configASSERT( xTXDescriptorSemaphore );
+                       }
+               }
+               #endif /* ipconfigZERO_COPY_TX_DRIVER */
+
+               /* Initialise ETH */
+
+               xETH.Instance = ETH;
+               xETH.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
+               xETH.Init.Speed = ETH_SPEED_100M;
+               xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
+               xETH.Init.PhyAddress = 1;
+
+               xETH.Init.MACAddr = ( uint8_t *) ucMACAddress;
+               xETH.Init.RxMode = ETH_RXINTERRUPT_MODE;
+
+               /* using the ETH_CHECKSUM_BY_HARDWARE option:
+               both the IP and the protocol checksums will be calculated
+               by the peripheral. */
+               xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
+
+               xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII;
+               hal_eth_init_status = HAL_ETH_Init( &xETH );
+
+               /* Only for inspection by debugger. */
+               ( void ) hal_eth_init_status;
+
+               /* Set the TxDesc and RxDesc pointers. */
+               xETH.TxDesc = DMATxDscrTab;
+               xETH.RxDesc = DMARxDscrTab;
+
+               /* Make sure that all unused fields are cleared. */
+               memset( &DMATxDscrTab, '\0', sizeof( DMATxDscrTab ) );
+               memset( &DMARxDscrTab, '\0', sizeof( DMARxDscrTab ) );
+
+               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+               {
+                       /* Initialize Tx Descriptors list: Chain Mode */
+                       DMATxDescToClear = DMATxDscrTab;
+               }
+               #endif /* ipconfigZERO_COPY_TX_DRIVER */
+
+               /* Initialise TX-descriptors. */
+               prvDMATxDescListInit();
+
+               /* Initialise RX-descriptors. */
+               prvDMARxDescListInit();
+
+               #if( ipconfigUSE_LLMNR != 0 )
+               {
+                       /* Program the LLMNR address at index 1. */
+                       prvMACAddressConfig( &xETH, ETH_MAC_ADDRESS1, ( uint8_t *) xLLMNR_MACAddress );
+               }
+               #endif
+
+               /* Force a negotiation with the Switch or Router and wait for LS. */
+               prvEthernetUpdateConfig( pdTRUE );
+
+               /* 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 );
+       } /* if( xEMACTaskHandle == NULL ) */
+
+       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
+       {
+               xETH.Instance->DMAIER |= ETH_DMA_ALL_INTS;
+               xResult = pdPASS;
+               FreeRTOS_printf( ( "Link Status is high\n" ) ) ;
+       }
+       else
+       {
+               /* For now pdFAIL will be returned. But prvEMACHandlerTask() is running
+               and it will keep on checking the PHY and set ulPHYLinkStatus when necessary. */
+               xResult = pdFAIL;
+               FreeRTOS_printf( ( "Link Status still low\n" ) ) ;
+       }
+       /* When returning non-zero, the stack will become active and
+    start DHCP (in configured) */
+       return xResult;
+}
+/*-----------------------------------------------------------*/
+
+static void prvDMATxDescListInit()
+{
+ETH_DMADescTypeDef *pxDMADescriptor;
+BaseType_t xIndex;
+
+       /* Get the pointer on the first member of the descriptor list */
+       pxDMADescriptor = DMATxDscrTab;
+
+       /* Fill each DMA descriptor with the right values */
+       for( xIndex = 0; xIndex < ETH_TXBUFNB; xIndex++, pxDMADescriptor++ )
+       {
+               /* Set Second Address Chained bit */
+               pxDMADescriptor->Status = ETH_DMATXDESC_TCH;
+
+               #if( ipconfigZERO_COPY_TX_DRIVER == 0 )
+               {
+                       /* Set Buffer1 address pointer */
+                       pxDMADescriptor->Buffer1Addr = ( uint32_t )( Tx_Buff[ xIndex ] );
+               }
+               #endif
+
+               if( xETH.Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE )
+               {
+                       /* Set the DMA Tx descriptors checksum insertion for TCP, UDP, and ICMP */
+                       pxDMADescriptor->Status |= ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL;
+               }
+
+               /* Initialize the next descriptor with the Next Descriptor Polling Enable */
+               if( xIndex < ETH_TXBUFNB - 1 )
+               {
+                       /* Set next descriptor address register with next descriptor base address */
+                       pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) ( pxDMADescriptor + 1 );
+               }
+               else
+               {
+                       /* For last descriptor, set next descriptor address register equal to the first descriptor base address */
+                       pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) DMATxDscrTab;
+               }
+       }
+
+       /* Set Transmit Descriptor List Address Register */
+       xETH.Instance->DMATDLAR = ( uint32_t ) DMATxDscrTab;
+}
+/*-----------------------------------------------------------*/
+
+static void prvDMARxDescListInit()
+{
+ETH_DMADescTypeDef *pxDMADescriptor;
+BaseType_t xIndex;
+       /*
+        * RX-descriptors.
+        */
+
+       /* Get the pointer on the first member of the descriptor list */
+       pxDMADescriptor = DMARxDscrTab;
+
+       /* Fill each DMA descriptor with the right values */
+       for( xIndex = 0; xIndex < ETH_RXBUFNB; xIndex++, pxDMADescriptor++ )
+       {
+
+               /* Set Buffer1 size and Second Address Chained bit */
+               pxDMADescriptor->ControlBufferSize = ETH_DMARXDESC_RCH | (uint32_t)ETH_RX_BUF_SIZE;  
+
+               #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
+               {
+               /* Set Buffer1 address pointer */
+               NetworkBufferDescriptor_t *pxBuffer;
+
+                       pxBuffer = pxGetNetworkBufferWithDescriptor( ETH_RX_BUF_SIZE, 100ul );
+                       /* If the assert below fails, make sure that there are at least 'ETH_RXBUFNB'
+                       Network Buffers available during start-up ( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) */
+                       configASSERT( pxBuffer != NULL );
+                       if( pxBuffer != NULL )
+                       {
+                               pxDMADescriptor->Buffer1Addr = (uint32_t)pxBuffer->pucEthernetBuffer;
+                               pxDMADescriptor->Status = ETH_DMARXDESC_OWN;
+                       }
+               }
+               #else
+               {
+                       /* Set Buffer1 address pointer */
+                       pxDMADescriptor->Buffer1Addr = ( uint32_t )( Rx_Buff[ xIndex ] );
+                       /* Set Own bit of the Rx descriptor Status */
+                       pxDMADescriptor->Status = ETH_DMARXDESC_OWN;
+               }
+               #endif
+
+               /* Initialize the next descriptor with the Next Descriptor Polling Enable */
+               if( xIndex < ETH_RXBUFNB - 1 )
+               {
+                       /* Set next descriptor address register with next descriptor base address */
+                       pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t )( pxDMADescriptor + 1 );
+               }
+               else
+               {
+                       /* For last descriptor, set next descriptor address register equal to the first descriptor base address */
+                       pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) DMARxDscrTab;
+               }
+
+       }
+       /* Set Receive Descriptor List Address Register */
+       xETH.Instance->DMARDLAR = ( uint32_t ) DMARxDscrTab;
+}
+/*-----------------------------------------------------------*/
+
+static void prvMACAddressConfig(ETH_HandleTypeDef *heth, uint32_t ulIndex, uint8_t *Addr)
+{
+uint32_t ulTempReg;
+
+       /* Calculate the selected MAC address high register. */
+       ulTempReg = 0x80000000ul | ( ( uint32_t ) Addr[ 5 ] << 8 ) | ( uint32_t ) Addr[ 4 ];
+
+       /* Load the selected MAC address high register. */
+       ( *(__IO uint32_t *)( ( uint32_t ) ( ETH_MAC_ADDR_HBASE + ulIndex ) ) ) = ulTempReg;
+
+       /* Calculate the selected MAC address low register. */
+       ulTempReg = ( ( uint32_t ) Addr[ 3 ] << 24 ) | ( ( uint32_t ) Addr[ 2 ] << 16 ) | ( ( uint32_t ) Addr[ 1 ] << 8 ) | Addr[ 0 ];
+
+       /* Load the selected MAC address low register */
+       ( *(__IO uint32_t *) ( ( uint32_t ) ( ETH_MAC_ADDR_LBASE + ulIndex ) ) ) = ulTempReg;
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend )
+{
+BaseType_t xReturn = pdFAIL;
+uint32_t ulTransmitSize = 0;
+__IO ETH_DMADescTypeDef *pxDmaTxDesc;
+/* Do not wait too long for a free TX DMA buffer. */
+const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );
+
+       #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )
+       {
+       ProtocolPacket_t *pxPacket;
+
+               /* If the peripheral must calculate the checksum, it wants
+               the protocol checksum to have a value of zero. */
+               pxPacket = ( ProtocolPacket_t * ) ( pxDescriptor->pucEthernetBuffer );
+
+               if( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ipPROTOCOL_ICMP )
+               {
+                       pxPacket->xICMPPacket.xICMPHeader.usChecksum = ( uint16_t )0u;
+               }
+       }
+       #endif
+
+       /* Open a do {} while ( 0 ) loop to be able to call break. */
+       do
+       {
+               if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
+               {
+                       #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+                       {
+                               if( xTXDescriptorSemaphore == NULL )
+                               {
+                                       break;
+                               }
+                               if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )
+                               {
+                                       /* Time-out waiting for a free TX descriptor. */
+                                       break;
+                               }
+                       }
+                       #endif /* ipconfigZERO_COPY_TX_DRIVER */
+
+                       /* This function does the actual transmission of the packet. The packet is
+                       contained in 'pxDescriptor' that is passed to the function. */
+                       pxDmaTxDesc = xETH.TxDesc;
+
+                       /* Is this buffer available? */
+                       if( ( pxDmaTxDesc->Status & ETH_DMATXDESC_OWN ) == 0 )
+                       {
+                               /* Is this buffer available? */
+                               /* Get bytes in current buffer. */
+                               ulTransmitSize = pxDescriptor->xDataLength;
+
+                               if( ulTransmitSize > ETH_TX_BUF_SIZE )
+                               {
+                                       ulTransmitSize = ETH_TX_BUF_SIZE;
+                               }
+
+                               #if( ipconfigZERO_COPY_TX_DRIVER == 0 )
+                               {
+                                       /* Copy the bytes. */
+                                       memcpy( ( void * ) pxDmaTxDesc->Buffer1Addr, pxDescriptor->pucEthernetBuffer, ulTransmitSize );
+                                       pxDmaTxDesc->Status |= ETH_DMATXDESC_CIC_TCPUDPICMP_FULL;
+                               }
+                               #else
+                               {
+                                       /* Move the buffer. */
+                                       pxDmaTxDesc->Buffer1Addr = ( uint32_t )pxDescriptor->pucEthernetBuffer;
+                                       /* Ask to set the IPv4 checksum.
+                                       Also need an Interrupt on Completion so that 'vClearTXBuffers()' will be called.. */
+                                       pxDmaTxDesc->Status |= ETH_DMATXDESC_CIC_TCPUDPICMP_FULL | ETH_DMATXDESC_IC;
+                                       /* The Network Buffer has been passed to DMA, no need to release it. */
+                                       bReleaseAfterSend = pdFALSE_UNSIGNED;
+                               }
+                               #endif /* ipconfigZERO_COPY_TX_DRIVER */
+
+                               /* Prepare transmit descriptors to give to DMA. */
+
+                               /* Set LAST and FIRST segment */
+                               pxDmaTxDesc->Status |= ETH_DMATXDESC_FS | ETH_DMATXDESC_LS;
+                               /* Set frame size */
+                               pxDmaTxDesc->ControlBufferSize = ( ulTransmitSize & ETH_DMATXDESC_TBS1 );
+                               /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
+                               pxDmaTxDesc->Status |= ETH_DMATXDESC_OWN;
+
+                               /* Point to next descriptor */
+                               xETH.TxDesc = ( ETH_DMADescTypeDef * ) ( xETH.TxDesc->Buffer2NextDescAddr );
+       
+                               /* Resume DMA transmission*/
+                               xETH.Instance->DMATPDR = 0;
+                               iptraceNETWORK_INTERFACE_TRANSMIT();
+                               xReturn = pdPASS;
+                       }
+               }
+               else
+               {
+                       /* The PHY has no Link Status, packet shall be dropped. */
+               }
+       } while( 0 );
+       /* The buffer has been sent so can be released. */
+       if( bReleaseAfterSend != pdFALSE )
+       {
+               vReleaseNetworkBufferAndDescriptor( pxDescriptor );
+       }
+
+       return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+static BaseType_t xMayAcceptPacket( uint8_t *pcBuffer )
+{
+const ProtocolPacket_t *pxProtPacket = ( const ProtocolPacket_t * )pcBuffer;
+
+       switch( pxProtPacket->xTCPPacket.xEthernetHeader.usFrameType )
+       {
+       case ipARP_FRAME_TYPE:
+               /* Check it later. */
+               return pdTRUE;
+       case ipIPv4_FRAME_TYPE:
+               /* Check it here. */
+               break;
+       default:
+               /* Refuse the packet. */
+               return pdFALSE;
+       }
+
+       #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
+       {
+               const IPHeader_t *pxIPHeader = &(pxProtPacket->xTCPPacket.xIPHeader);
+               uint32_t ulDestinationIPAddress;
+
+               /* Ensure that the incoming packet is not fragmented (only outgoing packets
+                * can be fragmented) as these are the only handled IP frames currently. */
+               if( ( pxIPHeader->usFragmentOffset & FreeRTOS_ntohs( ipFRAGMENT_OFFSET_BIT_MASK ) ) != 0U )
+               {
+                       return pdFALSE;
+               }
+               /* HT: Might want to make the following configurable because
+                * most IP messages have a standard length of 20 bytes */
+
+               /* 0x45 means: IPv4 with an IP header of 5 x 4 = 20 bytes
+                * 0x47 means: IPv4 with an IP header of 7 x 4 = 28 bytes */
+               if( pxIPHeader->ucVersionHeaderLength < 0x45 || pxIPHeader->ucVersionHeaderLength > 0x4F )
+               {
+                       return pdFALSE;
+               }
+
+               ulDestinationIPAddress = pxIPHeader->ulDestinationIPAddress;
+               /* Is the packet for this node? */
+               if( ( ulDestinationIPAddress != *ipLOCAL_IP_ADDRESS_POINTER ) &&
+                       /* Is it a broadcast address x.x.x.255 ? */
+                       ( ( FreeRTOS_ntohl( ulDestinationIPAddress ) & 0xff ) != 0xff ) &&
+               #if( ipconfigUSE_LLMNR == 1 )
+                       ( ulDestinationIPAddress != ipLLMNR_IP_ADDR ) &&
+               #endif
+                       ( *ipLOCAL_IP_ADDRESS_POINTER != 0 ) ) {
+                       FreeRTOS_printf( ( "Drop IP %lxip\n", FreeRTOS_ntohl( ulDestinationIPAddress ) ) );
+                       return pdFALSE;
+               }
+
+               if( pxIPHeader->ucProtocol == ipPROTOCOL_UDP )
+               {
+                       uint16_t port = pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort;
+
+                       if( ( xPortHasUDPSocket( port ) == pdFALSE )
+                       #if ipconfigUSE_LLMNR == 1
+                               && ( port != FreeRTOS_ntohs( ipLLMNR_PORT ) )
+                       #endif
+                       #if ipconfigUSE_NBNS == 1
+                               && ( port != FreeRTOS_ntohs( ipNBNS_PORT ) )
+                       #endif
+                       #if ipconfigUSE_DNS == 1
+                               && ( pxProtPacket->xUDPPacket.xUDPHeader.usSourcePort != FreeRTOS_ntohs( ipDNS_PORT ) )
+                       #endif
+                               ) {
+                               /* Drop this packet, not for this device. */
+                               return pdFALSE;
+                       }
+               }
+       }
+       #endif  /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
+       return pdTRUE;
+}
+/*-----------------------------------------------------------*/
+
+static BaseType_t prvNetworkInterfaceInput( void )
+{
+NetworkBufferDescriptor_t *pxCurDescriptor;
+NetworkBufferDescriptor_t *pxNewDescriptor = NULL;
+BaseType_t xReceivedLength, xAccepted;
+__IO ETH_DMADescTypeDef *pxDMARxDescriptor;
+xIPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
+const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );
+uint8_t *pucBuffer;
+
+       pxDMARxDescriptor = xETH.RxDesc;
+
+       if( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_OWN) == 0 )
+       {
+               /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
+               xReceivedLength = ( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_FL ) >> ETH_DMARXDESC_FRAMELENGTHSHIFT ) - 4;
+
+               pucBuffer = (uint8_t *) pxDMARxDescriptor->Buffer1Addr;
+
+               /* Update the ETHERNET DMA global Rx descriptor with next Rx descriptor */
+               /* Chained Mode */    
+               /* Selects the next DMA Rx descriptor list for next buffer to read */ 
+               xETH.RxDesc = ( ETH_DMADescTypeDef* )pxDMARxDescriptor->Buffer2NextDescAddr;
+       }
+       else
+       {
+               xReceivedLength = 0;
+       }
+
+       /* Obtain the size of the packet and put it into the "usReceivedLength" variable. */
+       /* In order to make the code easier and faster, only packets in a single buffer
+       will be accepted.  This can be done by making the buffers large enough to
+       hold a complete Ethernet packet (1536 bytes). */
+       if( xReceivedLength > 0ul && xReceivedLength < ETH_RX_BUF_SIZE ) 
+       {
+               if( ( pxDMARxDescriptor->Status & ( ETH_DMARXDESC_CE | ETH_DMARXDESC_IPV4HCE | ETH_DMARXDESC_FT ) ) != ETH_DMARXDESC_FT )
+               {
+                       /* Not an Ethernet frame-type or a checmsum error. */
+                       xAccepted = pdFALSE;
+               }
+               else
+               {
+                       /* See if this packet must be handled. */
+                       xAccepted = xMayAcceptPacket( pucBuffer );
+               }
+
+               if( xAccepted != pdFALSE )
+               {
+                       /* The packet wil be accepted, but check first if a new Network Buffer can
+                       be obtained. If not, the packet will still be dropped. */
+                       pxNewDescriptor = pxGetNetworkBufferWithDescriptor( ETH_RX_BUF_SIZE, xDescriptorWaitTime );
+
+                       if( pxNewDescriptor == NULL )
+                       {
+                               /* A new descriptor can not be allocated now. This packet will be dropped. */
+                               xAccepted = pdFALSE;
+                       }
+               }
+               #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
+               {
+                       /* Find out which Network Buffer was originally passed to the descriptor. */
+                       pxCurDescriptor = pxPacketBuffer_to_NetworkBuffer( pucBuffer );
+                       configASSERT( pxCurDescriptor != NULL );
+               }
+               #else
+               {
+                       /* In this mode, the two descriptors are the same. */
+                       pxCurDescriptor = pxNewDescriptor;
+                       if( pxNewDescriptor != NULL )
+                       {
+                               /* The packet is acepted and a new Network Buffer was created,
+                               copy data to the Network Bufffer. */
+                               memcpy( pxNewDescriptor->pucEthernetBuffer, pucBuffer, xReceivedLength );
+                       }
+               }
+               #endif
+
+               if( xAccepted != pdFALSE )
+               {
+                       pxCurDescriptor->xDataLength = xReceivedLength;
+                       xRxEvent.pvData = ( void * ) pxCurDescriptor;
+
+                       /* Pass the data to the TCP/IP task for processing. */
+                       if( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime ) == pdFALSE )
+                       {
+                               /* Could not send the descriptor into the TCP/IP stack, it
+                               must be released. */
+                               vReleaseNetworkBufferAndDescriptor( pxCurDescriptor );
+                               iptraceETHERNET_RX_EVENT_LOST();
+                       }
+                       else
+                       {
+                               iptraceNETWORK_INTERFACE_RECEIVE();
+                       }
+               }
+
+               /* Release descriptors to DMA */
+               #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
+               {
+                       /* Set Buffer1 address pointer */
+                       if( pxNewDescriptor != NULL )
+                       {
+                               pxDMARxDescriptor->Buffer1Addr = (uint32_t)pxNewDescriptor->pucEthernetBuffer;
+                       }
+                       else
+                       {
+                               /* The packet was dropped and the same Network
+                               Buffer will be used to receive a new packet. */
+                       }
+               }
+               #endif /* ipconfigZERO_COPY_RX_DRIVER */
+
+               /* Set Buffer1 size and Second Address Chained bit */
+               pxDMARxDescriptor->ControlBufferSize = ETH_DMARXDESC_RCH | (uint32_t)ETH_RX_BUF_SIZE;  
+               pxDMARxDescriptor->Status = ETH_DMARXDESC_OWN;
+
+               /* When Rx Buffer unavailable flag is set clear it and resume
+               reception. */
+               if( ( xETH.Instance->DMASR & ETH_DMASR_RBUS ) != 0 )
+               {
+                       /* Clear RBUS ETHERNET DMA flag. */
+                       xETH.Instance->DMASR = ETH_DMASR_RBUS;
+
+                       /* Resume DMA reception. */
+                       xETH.Instance->DMARPDR = 0;
+               }
+       }
+
+       return ( xReceivedLength > 0 );
+}
+/*-----------------------------------------------------------*/
+
+void vMACBProbePhy( void )
+{
+uint32_t ulConfig, ulAdvertise, ulLower, ulUpper, ulMACPhyID, ulValue;
+TimeOut_t xPhyTime;
+TickType_t xRemTime = 0;
+#if( EXPECTED_PHY_ID == PHY_ID_DP83848I )
+       uint32_t ulPhyControl;
+#endif
+
+       HAL_ETH_ReadPHYRegister(&xETH, PHY_REG_03_PHYSID2, &ulLower);
+       HAL_ETH_ReadPHYRegister(&xETH, PHY_REG_02_PHYSID1, &ulUpper);
+
+       ulMACPhyID = ( ( ulUpper << 16 ) & 0xFFFF0000 ) | ( ulLower & 0xFFF0 );
+
+       /* The expected ID for the 'LAN8720' is 0x0007c0f0. */
+       /* The expected ID for the 'DP83848I' is 0x20005C90. */
+
+       FreeRTOS_printf( ( "PHY ID %lX (%s)\n", ulMACPhyID,
+               ( ulMACPhyID == EXPECTED_PHY_ID ) ? "OK" : "Unknown" ) );
+
+       /* Remove compiler warning if FreeRTOS_printf() is not defined. */
+       ( void ) ulMACPhyID;
+
+    /* Set advertise register. */
+       if( ( xPHYProperties.speed == PHY_SPEED_AUTO ) && ( xPHYProperties.duplex == PHY_DUPLEX_AUTO ) )
+       {
+               ulAdvertise = ADVERTISE_CSMA | ADVERTISE_ALL;
+               /* Reset auto-negotiation capability. */
+       }
+       else
+       {
+               ulAdvertise = ADVERTISE_CSMA;
+
+               if( xPHYProperties.speed == PHY_SPEED_AUTO )
+               {
+                       if( xPHYProperties.duplex == PHY_DUPLEX_FULL )
+                       {
+                               ulAdvertise |= ADVERTISE_10FULL | ADVERTISE_100FULL;
+                       }
+                       else
+                       {
+                               ulAdvertise |= ADVERTISE_10HALF | ADVERTISE_100HALF;
+                       }
+               }
+               else if( xPHYProperties.duplex == PHY_DUPLEX_AUTO )
+               {
+                       if( xPHYProperties.speed == PHY_SPEED_10 )
+                       {
+                               ulAdvertise |= ADVERTISE_10FULL | ADVERTISE_10HALF;
+                       }
+                       else
+                       {
+                               ulAdvertise |= ADVERTISE_100FULL | ADVERTISE_100HALF;
+                       }
+               }
+               else if( xPHYProperties.speed == PHY_SPEED_100 )
+               {
+                       if( xPHYProperties.duplex == PHY_DUPLEX_FULL )
+                       {
+                               ulAdvertise |= ADVERTISE_100FULL;
+                       }
+                       else
+                       {
+                               ulAdvertise |= ADVERTISE_100HALF;
+                       }
+               }
+               else
+               {
+                       if( xPHYProperties.duplex == PHY_DUPLEX_FULL )
+                       {
+                               ulAdvertise |= ADVERTISE_10FULL;
+                       }
+                       else
+                       {
+                               ulAdvertise |= ADVERTISE_10HALF;
+                       }
+               }
+       }
+
+       /* Read Control register. */
+       HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_00_BMCR, &ulConfig );
+
+       HAL_ETH_WritePHYRegister( &xETH, PHY_REG_00_BMCR, ulConfig | BMCR_RESET );
+       xRemTime = ( TickType_t ) pdMS_TO_TICKS( 1000UL );
+       vTaskSetTimeOutState( &xPhyTime );
+
+       for( ; ; )
+       {
+               HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_00_BMCR, &ulValue );
+               if( ( ulValue & BMCR_RESET ) == 0 )
+               {
+                       FreeRTOS_printf( ( "BMCR_RESET ready\n" ) );
+                       break;
+               }
+               if( xTaskCheckForTimeOut( &xPhyTime, &xRemTime ) != pdFALSE )
+               {
+                       FreeRTOS_printf( ( "BMCR_RESET timed out\n" ) );
+                       break;
+               }
+       }
+       HAL_ETH_WritePHYRegister( &xETH, PHY_REG_00_BMCR, ulConfig & ~BMCR_RESET );
+
+       vTaskDelay( pdMS_TO_TICKS( 50ul ) );
+
+    /* Write advertise register. */
+       HAL_ETH_WritePHYRegister( &xETH, PHY_REG_04_ADVERTISE, ulAdvertise );
+
+       /*
+                       AN_EN        AN1         AN0       Forced Mode
+                         0           0           0        10BASE-T, Half-Duplex
+                         0           0           1        10BASE-T, Full-Duplex
+                         0           1           0        100BASE-TX, Half-Duplex
+                         0           1           1        100BASE-TX, Full-Duplex
+                       AN_EN        AN1         AN0       Advertised Mode
+                         1           0           0        10BASE-T, Half/Full-Duplex
+                         1           0           1        100BASE-TX, Half/Full-Duplex
+                         1           1           0        10BASE-T Half-Duplex
+                                                                                          100BASE-TX, Half-Duplex
+                         1           1           1        10BASE-T, Half/Full-Duplex
+                                                                                          100BASE-TX, Half/Full-Duplex
+       */
+
+    /* Read Control register. */
+       HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_00_BMCR, &ulConfig );
+
+       ulConfig &= ~( BMCR_ANRESTART | BMCR_ANENABLE | BMCR_SPEED100 | BMCR_FULLDPLX );
+
+       /* HT 12/9/14: always set AN-restart and AN-enable, even though the choices
+       are limited. */
+       ulConfig |= (BMCR_ANRESTART | BMCR_ANENABLE);
+
+       if( xPHYProperties.speed == PHY_SPEED_100 )
+       {
+               ulConfig |= BMCR_SPEED100;
+       }
+       else if( xPHYProperties.speed == PHY_SPEED_10 )
+       {
+               ulConfig &= ~BMCR_SPEED100;
+       }
+
+       if( xPHYProperties.duplex == PHY_DUPLEX_FULL )
+       {
+               ulConfig |= BMCR_FULLDPLX;
+       }
+       else if( xPHYProperties.duplex == PHY_DUPLEX_HALF )
+       {
+               ulConfig &= ~BMCR_FULLDPLX;
+       }
+
+       #if( EXPECTED_PHY_ID == PHY_ID_LAN8720 )
+       {
+       }
+       #elif( EXPECTED_PHY_ID == PHY_ID_DP83848I )
+       {
+               /* Read PHY Control register. */
+               HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_19_PHYCR, &ulPhyControl );
+
+               /* Clear bits which might get set: */
+               ulPhyControl &= ~( PHYCR_MDIX_EN|PHYCR_MDIX_FORCE );
+
+               if( xPHYProperties.mdix == PHY_MDIX_AUTO )
+               {
+                       ulPhyControl |= PHYCR_MDIX_EN;
+               }
+               else if( xPHYProperties.mdix == PHY_MDIX_CROSSED )
+               {
+                       /* Force direct link = Use crossed RJ45 cable. */
+                       ulPhyControl &= ~PHYCR_MDIX_FORCE;
+               }
+               else
+               {
+                       /* Force crossed link = Use direct RJ45 cable. */
+                       ulPhyControl |= PHYCR_MDIX_FORCE;
+               }
+               /* update PHY Control Register. */
+               HAL_ETH_WritePHYRegister( &xETH, PHY_REG_19_PHYCR, ulPhyControl );
+       }
+       #endif
+       FreeRTOS_printf( ( "+TCP: advertise: %lX config %lX\n", ulAdvertise, ulConfig ) );
+
+       /* Now the two values to global values for later use. */
+       ulBCRvalue = ulConfig;
+       ulACRValue = ulAdvertise;
+}
+/*-----------------------------------------------------------*/
+
+static void prvEthernetUpdateConfig( BaseType_t xForce )
+{
+__IO uint32_t ulTimeout = 0;
+uint32_t ulRegValue = 0;
+
+       FreeRTOS_printf( ( "prvEthernetUpdateConfig: LS %d Force %d\n",
+               ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ,
+               xForce ) );
+
+       if( ( xForce != pdFALSE ) || ( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) )
+       {
+               /* Restart the auto-negotiation. */
+               if( xETH.Init.AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE )
+               {
+                       /* Enable Auto-Negotiation. */
+                       HAL_ETH_WritePHYRegister( &xETH, PHY_REG_00_BMCR, ulBCRvalue | BMCR_ANRESTART );
+                       HAL_ETH_WritePHYRegister( &xETH, PHY_REG_04_ADVERTISE, ulACRValue);
+
+                       /* Wait until the auto-negotiation will be completed */
+                       do
+                       {
+                               ulTimeout++;
+                               HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_01_BMSR, &ulRegValue );
+                       } while( ( ( ulRegValue & PHY_AUTONEGO_COMPLETE) == 0 ) && ( ulTimeout < PHY_READ_TO ) );
+
+                       HAL_ETH_WritePHYRegister( &xETH, PHY_REG_00_BMCR, ulBCRvalue & ~BMCR_ANRESTART );
+
+                       if( ulTimeout < PHY_READ_TO )
+                       {
+                               /* Reset Timeout counter. */
+                               ulTimeout = 0;
+
+                               HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_01_BMSR, &ulRegValue);
+                               if( ( ulRegValue & BMSR_LINK_STATUS ) != 0 )
+                               {
+                                       ulPHYLinkStatus |= BMSR_LINK_STATUS;
+                               }
+                               else
+                               {
+                                       ulPHYLinkStatus &= ~( BMSR_LINK_STATUS );
+                               }
+
+                               #if( EXPECTED_PHY_ID == PHY_ID_LAN8720 )
+                               {
+                               /* 31 RW PHY Special Control Status */
+                               uint32_t ulControlStatus;
+
+                                       HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_1F_PHYSPCS, &ulControlStatus);
+                                       ulRegValue = 0;
+                                       if( ( ulControlStatus & PHYSPCS_FULL_DUPLEX ) != 0 )
+                                       {
+                                               ulRegValue |= PHY_DUPLEX_STATUS;
+                                       }
+                                       if( ( ulControlStatus & PHYSPCS_SPEED_MASK ) == PHYSPCS_SPEED_10 )
+                                       {
+                                               ulRegValue |= PHY_SPEED_STATUS;
+                                       }
+
+                               }
+                               #elif( EXPECTED_PHY_ID == PHY_ID_DP83848I )
+                               {
+                                       /* Read the result of the auto-negotiation. */
+                                       HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_10_PHY_SR, &ulRegValue);
+                               }
+                               #endif
+                               FreeRTOS_printf( ( ">> Autonego ready: %08lx: %s duplex %u mbit %s status\n",
+                                       ulRegValue,
+                                       (ulRegValue & PHY_DUPLEX_STATUS) ? "full" : "half",
+                                       (ulRegValue & PHY_SPEED_STATUS) ? 10 : 100,
+                                       ((ulPHYLinkStatus |= BMSR_LINK_STATUS) != 0) ? "high" : "low" ) );
+
+                               /* Configure the MAC with the Duplex Mode fixed by the
+                               auto-negotiation process. */
+                               if( ( ulRegValue & PHY_DUPLEX_STATUS ) != ( uint32_t ) RESET )
+                               {
+                                       /* Set Ethernet duplex mode to Full-duplex following the
+                                       auto-negotiation. */
+                                       xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
+                               }
+                               else
+                               {
+                                       /* Set Ethernet duplex mode to Half-duplex following the
+                                       auto-negotiation. */
+                                       xETH.Init.DuplexMode = ETH_MODE_HALFDUPLEX;
+                               }
+
+                               /* Configure the MAC with the speed fixed by the
+                               auto-negotiation process. */
+                               if( ( ulRegValue & PHY_SPEED_STATUS) != 0 )
+                               {
+                                       /* Set Ethernet speed to 10M following the
+                                       auto-negotiation. */
+                                       xETH.Init.Speed = ETH_SPEED_10M;
+                               }
+                               else
+                               {
+                                       /* Set Ethernet speed to 100M following the
+                                       auto-negotiation. */
+                                       xETH.Init.Speed = ETH_SPEED_100M;
+                               }
+                       }       /* if( ulTimeout < PHY_READ_TO ) */
+               }
+               else /* AutoNegotiation Disable */
+               {
+               uint16_t usValue;
+
+                       /* Check parameters */
+                       assert_param( IS_ETH_SPEED( xETH.Init.Speed ) );
+                       assert_param( IS_ETH_DUPLEX_MODE( xETH.Init.DuplexMode ) );
+
+                       /* Set MAC Speed and Duplex Mode to PHY */
+                       usValue = ( uint16_t ) ( xETH.Init.DuplexMode >> 3 ) | ( uint16_t ) ( xETH.Init.Speed >> 1 );
+                       HAL_ETH_WritePHYRegister( &xETH, PHY_REG_00_BMCR, usValue );
+               }
+
+               /* ETHERNET MAC Re-Configuration */
+               HAL_ETH_ConfigMAC( &xETH, (ETH_MACInitTypeDef *) NULL);
+
+               /* Restart MAC interface */
+               HAL_ETH_Start( &xETH);
+       }
+       else
+       {
+               /* Stop MAC interface */
+               HAL_ETH_Stop( &xETH );
+       }
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xGetPhyLinkStatus( void )
+{
+BaseType_t xReturn;
+
+       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
+       {
+               xReturn = pdPASS;
+       }
+       else
+       {
+               xReturn = pdFAIL;
+       }
+
+       return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+static void prvEMACHandlerTask( void *pvParameters )
+{
+TimeOut_t xPhyTime;
+TickType_t xPhyRemTime;
+UBaseType_t uxLastMinBufferCount = 0;
+#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
+UBaseType_t uxLastMinQueueSpace = 0;
+#endif
+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;
+
+       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( ipconfigZERO_COPY_TX_DRIVER != 0 )
+               if( xTXDescriptorSemaphore != NULL )
+               {
+               static UBaseType_t uxLowestSemCount = ( UBaseType_t ) ETH_TXBUFNB - 1;
+
+                       uxCurrentCount = uxSemaphoreGetCount( xTXDescriptorSemaphore );
+                       if( uxLowestSemCount > uxCurrentCount )
+                       {
+                               uxLowestSemCount = uxCurrentCount;
+                               FreeRTOS_printf( ( "TX DMA buffers: lowest %lu\n", uxLowestSemCount ) );
+                       }
+
+               }
+               #endif
+               #if( ipconfigCHECK_IP_QUEUE_SPACE != 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( ( ulISREvents & EMAC_IF_ALL_EVENT ) == 0 )
+               {
+                       /* No events to process now, wait for the next. */
+                       ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );
+               }
+
+               if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 )
+               {
+                       ulISREvents &= ~EMAC_IF_RX_EVENT;
+
+                       xResult = prvNetworkInterfaceInput();
+                       if( xResult > 0 )
+                       {
+                               while( prvNetworkInterfaceInput() > 0 )
+                               {
+                               }
+                       }
+               }
+
+               if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )
+               {
+                       /* Code to release TX buffers if zero-copy is used. */
+                       ulISREvents &= ~EMAC_IF_TX_EVENT;
+                       #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+                       {
+                               /* Check if DMA packets have been delivered. */
+                               vClearTXBuffers();
+                       }
+                       #endif
+               }
+
+               if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 )
+               {
+                       /* Future extension: logging about errors that occurred. */
+                       ulISREvents &= ~EMAC_IF_ERR_EVENT;
+               }
+
+               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 )
+               {
+                       HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_01_BMSR, &xStatus );
+                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )
+                       {
+                               ulPHYLinkStatus = xStatus;
+                               FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );
+                               prvEthernetUpdateConfig( pdFALSE );
+                       }
+
+                       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 );
+                       }
+               }
+       }
+}
+/*-----------------------------------------------------------*/
+
+void ETH_IRQHandler( void )
+{
+       HAL_ETH_IRQHandler( &xETH );
+}