]> git.sur5r.net Git - freertos/commitdiff
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2822 1d2547de-c912-0410...
authorrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Fri, 7 Feb 2020 21:49:55 +0000 (21:49 +0000)
committerrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Fri, 7 Feb 2020 21:49:55 +0000 (21:49 +0000)
36 files changed:
FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/Compiler/CompilerName/ReadMe.txt [new file with mode: 0644]
FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/Compiler/CompilerName/pack_struct_end.h [new file with mode: 0644]
FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/Compiler/CompilerName/pack_struct_start.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/NetworkInterface.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/component/gmac.h
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/ethernet_phy.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/ethernet_phy.h
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/gmac.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/gmac.h
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/instance/gmac.h
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC17xx/NetworkInterface.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC18xx/NetworkInterface.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/NetworkInterface.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/m480_eth.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/m480_eth.h
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/RX/NetworkInterface.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/RX/ether_callback.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/SH2A/NetworkInterface.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/FaultInjection.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/NetworkInterface.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/NetworkInterface.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif.h
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_dma.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_hw.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_hw.h
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_topology.h
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/board_family/NetworkInterface.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ksz8851snl/NetworkInterface.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/mw300_rd/NetworkInterface.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/pic32mzef/BufferAllocation_2.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/pic32mzef/NetworkInterface_eth.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/pic32mzef/NetworkInterface_wifi.c
FreeRTOS/History.txt
FreeRTOS/Source/include/task.h
Upgrading to FreeRTOS V10.3.0.url [new file with mode: 0644]

diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/Compiler/CompilerName/ReadMe.txt b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/Compiler/CompilerName/ReadMe.txt
new file mode 100644 (file)
index 0000000..17aca57
--- /dev/null
@@ -0,0 +1,3 @@
+Update pack_struct_start.h and pack_struct_end.h for your architecure.
+These files define the specifiers needed by your compiler to properly pack struct data 
+need by FreeRTOS+TCP.
\ No newline at end of file
diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/Compiler/CompilerName/pack_struct_end.h b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/Compiler/CompilerName/pack_struct_end.h
new file mode 100644 (file)
index 0000000..cdbad17
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+FreeRTOS+TCP V2.0.11
+Copyright (C) 2018 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
+*/
+
+/*****************************************************************************
+ *
+ * See the following URL for an explanation of this file:
+ * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
+ *
+ *****************************************************************************/
+; /* FIX ME. Update for the compiler specifier needed at end of a struct declartion to pack the struct. */
\ No newline at end of file
diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/Compiler/CompilerName/pack_struct_start.h b/FreeRTOS-Labs/Source/FreeRTOS-Plus-TCP/portable/Compiler/CompilerName/pack_struct_start.h
new file mode 100644 (file)
index 0000000..7fe533a
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+FreeRTOS+TCP V2.0.11
+Copyright (C) 2018 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
+*/
+
+/*****************************************************************************
+ *
+ * See the following URL for an explanation of this file:
+ * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
+ *
+ *****************************************************************************/
+/* FIX ME. Update for the compiler specifier needed at the start of a struct declartion to pack the struct. */
\ No newline at end of file
index 3528269bdb908c29673e1a7e78ce9df880a03342..83c96a07c078c448f34e6d632b0537eeaa342b70 100644 (file)
-/*
-FreeRTOS+TCP V2.0.11
-Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
- http://aws.amazon.com/freertos
- http://www.FreeRTOS.org
-*/
-
-/* Standard includes. */
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "task.h"
-#include "queue.h"
-#include "semphr.h"
-
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_Sockets.h"
-#include "FreeRTOS_IP_Private.h"
-#include "NetworkBufferManagement.h"
-#include "NetworkInterface.h"
-
-/* Some files from the Atmel Software Framework */
-/*_RB_ The SAM4E portable layer has three different header files called gmac.h! */
-#include "instance/gmac.h"
-#include <sysclk.h>
-#include <ethernet_phy.h>
-
-#ifndef        BMSR_LINK_STATUS
-       #define BMSR_LINK_STATUS            0x0004  //!< Link status
-#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 ETHERNET_CONF_PHY_ADDR  BOARD_GMAC_PHY_ADDR
-
-#define HZ_PER_MHZ                             ( 1000000UL )
-
-#ifndef        EMAC_MAX_BLOCK_TIME_MS
-       #define EMAC_MAX_BLOCK_TIME_MS  100ul
-#endif
-
-#if !defined( GMAC_USES_TX_CALLBACK ) || ( GMAC_USES_TX_CALLBACK != 1 )
-       #error Please define GMAC_USES_TX_CALLBACK as 1
-#endif
-
-/* Default the size of the stack used by the EMAC deferred handler task to 4x
-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 ( 4 * configMINIMAL_STACK_SIZE )
-#endif
-
-/*-----------------------------------------------------------*/
-
-/*
- * Wait a fixed time for the link status to indicate the network is up.
- */
-static BaseType_t xGMACWaitLS( TickType_t xMaxTime );
-
-#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 1 ) && ( ipconfigHAS_TX_CRC_OFFLOADING == 0 )
-       void vGMACGenerateChecksum( uint8_t *apBuffer );
-#endif
-
-/*
- * Called from the ASF GMAC driver.
- */
-static void prvRxCallback( uint32_t ulStatus );
-static void prvTxCallback( uint32_t ulStatus, uint8_t *puc_buffer );
-
-/*
- * A deferred interrupt handler task that processes GMAC interrupts.
- */
-static void prvEMACHandlerTask( void *pvParameters );
-
-/*
- * Initialise the ASF GMAC driver.
- */
-static BaseType_t prvGMACInit( void );
-
-/*
- * Try to obtain an Rx packet from the hardware.
- */
-static uint32_t prvEMACRxPoll( void );
-
-/*-----------------------------------------------------------*/
-
-/* 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;
-static volatile BaseType_t xGMACSwitchRequired;
-
-/* ethernet_phy_addr: the address of the PHY in use.
-Atmel was a bit ambiguous about it so the address will be stored
-in this variable, see ethernet_phy.c */
-extern int ethernet_phy_addr;
-
-/* LLMNR multicast address. */
-static const uint8_t llmnr_mac_address[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };
-
-/* The GMAC object as defined by the ASF drivers. */
-static gmac_device_t gs_gmac_dev;
-
-/* MAC address to use. */
-extern const uint8_t ucMACAddress[ 6 ];
-
-/* Holds the handle of the task used as a deferred interrupt processor.  The
-handle is used so direct notifications can be sent to the task for all EMAC/DMA
-related interrupts. */
-TaskHandle_t xEMACTaskHandle = NULL;
-
-static QueueHandle_t xTxBufferQueue;
-int tx_release_count[ 4 ];
-
-/* xTXDescriptorSemaphore is a counting semaphore with
-a maximum count of GMAC_TX_BUFFERS, which is the number of
-DMA TX descriptors. */
-static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;
-
-/*-----------------------------------------------------------*/
-
-/*
- * GMAC interrupt handler.
- */
-void GMAC_Handler(void)
-{
-       xGMACSwitchRequired = pdFALSE;
-
-       /* gmac_handler() may call prvRxCallback() which may change
-       the value of xGMACSwitchRequired. */
-       gmac_handler( &gs_gmac_dev );
-
-       if( xGMACSwitchRequired != pdFALSE )
-       {
-               portEND_SWITCHING_ISR( xGMACSwitchRequired );
-       }
-}
-/*-----------------------------------------------------------*/
-
-static void prvRxCallback( uint32_t ulStatus )
-{
-       if( ( ( ulStatus & GMAC_RSR_REC ) != 0 ) && ( xEMACTaskHandle != NULL ) )
-       {
-               /* let the prvEMACHandlerTask know that there was an RX event. */
-               ulISREvents |= EMAC_IF_RX_EVENT;
-               /* Only an RX interrupt can wakeup prvEMACHandlerTask. */
-               vTaskNotifyGiveFromISR( xEMACTaskHandle, ( BaseType_t * ) &xGMACSwitchRequired );
-       }
-}
-/*-----------------------------------------------------------*/
-
-static void prvTxCallback( uint32_t ulStatus, uint8_t *puc_buffer )
-{
-       if( ( xTxBufferQueue != NULL ) && ( xEMACTaskHandle != NULL ) )
-       {
-               /* let the prvEMACHandlerTask know that there was an RX event. */
-               ulISREvents |= EMAC_IF_TX_EVENT;
-
-               vTaskNotifyGiveFromISR( xEMACTaskHandle, ( BaseType_t * ) &xGMACSwitchRequired );
-               xQueueSendFromISR( xTxBufferQueue, &puc_buffer, ( BaseType_t * ) &xGMACSwitchRequired );
-               tx_release_count[ 2 ]++;
-       }
-}
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceInitialise( void )
-{
-const TickType_t x5_Seconds = 5000UL;
-
-       if( xEMACTaskHandle == NULL )
-       {
-               prvGMACInit();
-
-               /* Wait at most 5 seconds for a Link Status in the PHY. */
-               xGMACWaitLS( pdMS_TO_TICKS( x5_Seconds ) );
-
-               /* The handler task is created at the highest possible priority to
-               ensure the interrupt handler can return directly to it. */
-               xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );
-               configASSERT( xEMACTaskHandle );
-       }
-
-       if( xTxBufferQueue == NULL )
-       {
-               xTxBufferQueue = xQueueCreate( GMAC_TX_BUFFERS, sizeof( void * ) );
-               configASSERT( xTxBufferQueue );
-       }
-
-       if( xTXDescriptorSemaphore == NULL )
-       {
-               xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) GMAC_TX_BUFFERS, ( UBaseType_t ) GMAC_TX_BUFFERS );
-               configASSERT( xTXDescriptorSemaphore );
-       }
-       /* When returning non-zero, the stack will become active and
-    start DHCP (in configured) */
-       return ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0;
-}
-/*-----------------------------------------------------------*/
-
-BaseType_t xGetPhyLinkStatus( void )
-{
-BaseType_t xResult;
-
-       /* This function returns true if the Link Status in the PHY is high. */
-       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
-       {
-               xResult = pdTRUE;
-       }
-       else
-       {
-               xResult = pdFALSE;
-       }
-
-       return xResult;
-}
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend )
-{
-/* Do not wait too long for a free TX DMA buffer. */
-const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );
-
-       do {
-               if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )
-               {
-                       /* Do not attempt to send packets as long as the Link Status is low. */
-                       break;
-               }
-               if( xTXDescriptorSemaphore == NULL )
-               {
-                       /* Semaphore has not been created yet? */
-                       break;
-               }
-               if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )
-               {
-                       /* Time-out waiting for a free TX descriptor. */
-                       tx_release_count[ 3 ]++;
-                       break;
-               }
-               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
-               {
-                       /* Confirm that the pxDescriptor may be kept by the driver. */
-                       configASSERT( bReleaseAfterSend != pdFALSE );
-               }
-               #endif /* ipconfigZERO_COPY_TX_DRIVER */
-
-               gmac_dev_write( &gs_gmac_dev, (void *)pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength, prvTxCallback );
-
-               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
-               {
-                       /* Confirm that the pxDescriptor may be kept by the driver. */
-                       bReleaseAfterSend = pdFALSE;
-               }
-               #endif /* ipconfigZERO_COPY_TX_DRIVER */
-               /* Not interested in a call-back after TX. */
-               iptraceNETWORK_INTERFACE_TRANSMIT();
-       } while( 0 );
-
-       if( bReleaseAfterSend != pdFALSE )
-       {
-               vReleaseNetworkBufferAndDescriptor( pxDescriptor );
-       }
-       return pdTRUE;
-}
-/*-----------------------------------------------------------*/
-
-static BaseType_t prvGMACInit( void )
-{
-uint32_t ncfgr;
-
-       gmac_options_t gmac_option;
-
-       memset( &gmac_option, '\0', sizeof( gmac_option ) );
-       gmac_option.uc_copy_all_frame = 0;
-       gmac_option.uc_no_boardcast = 0;
-       memcpy( gmac_option.uc_mac_addr, ucMACAddress, sizeof( gmac_option.uc_mac_addr ) );
-
-       gs_gmac_dev.p_hw = GMAC;
-       gmac_dev_init( GMAC, &gs_gmac_dev, &gmac_option );
-
-       NVIC_SetPriority( GMAC_IRQn, configMAC_INTERRUPT_PRIORITY );
-       NVIC_EnableIRQ( GMAC_IRQn );
-
-       /* Contact the Ethernet PHY and store it's address in 'ethernet_phy_addr' */
-       ethernet_phy_init( GMAC, ETHERNET_CONF_PHY_ADDR, sysclk_get_cpu_hz() );
-
-       ethernet_phy_auto_negotiate( GMAC, ethernet_phy_addr );
-       ethernet_phy_set_link( GMAC, ethernet_phy_addr, 1 );
-
-       /* The GMAC driver will call a hook prvRxCallback(), which
-       in turn will wake-up the task by calling vTaskNotifyGiveFromISR() */
-       gmac_dev_set_rx_callback( &gs_gmac_dev, prvRxCallback );
-       gmac_set_address( GMAC, 1, (uint8_t*)llmnr_mac_address );
-
-       ncfgr = GMAC_NCFGR_SPD | GMAC_NCFGR_FD;
-
-       GMAC->GMAC_NCFGR = ( GMAC->GMAC_NCFGR & ~( GMAC_NCFGR_SPD | GMAC_NCFGR_FD ) ) | ncfgr;
-
-       return 1;
-}
-/*-----------------------------------------------------------*/
-
-static inline unsigned long ulReadMDIO( unsigned /*short*/ usAddress )
-{
-uint32_t ulValue, ulReturn;
-int rc;
-
-       gmac_enable_management( GMAC, 1 );
-       rc = gmac_phy_read( GMAC, ethernet_phy_addr, usAddress, &ulValue );
-       gmac_enable_management( GMAC, 0 );
-       if( rc == GMAC_OK )
-       {
-               ulReturn = ulValue;
-       }
-       else
-       {
-               ulReturn = 0UL;
-       }
-
-       return ulReturn;
-}
-/*-----------------------------------------------------------*/
-
-static BaseType_t xGMACWaitLS( TickType_t xMaxTime )
-{
-TickType_t xStartTime = xTaskGetTickCount();
-TickType_t xEndTime;
-BaseType_t xReturn;
-const TickType_t xShortTime = pdMS_TO_TICKS( 100UL );
-
-       for( ;; )
-       {
-               xEndTime = xTaskGetTickCount();
-
-               if( ( xEndTime - xStartTime ) > xMaxTime )
-               {
-                       /* Wated more than xMaxTime, return. */
-                       xReturn = pdFALSE;
-                       break;
-               }
-
-               /* Check the link status again. */
-               ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );
-
-               if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
-               {
-                       /* Link is up - return. */
-                       xReturn = pdTRUE;
-                       break;
-               }
-
-               /* Link is down - wait in the Blocked state for a short while (to allow
-               other tasks to execute) before checking again. */
-               vTaskDelay( xShortTime );
-       }
-
-       FreeRTOS_printf( ( "xGMACWaitLS: %ld (PHY %d) freq %lu Mz\n",
-               xReturn,
-               ethernet_phy_addr,
-               sysclk_get_cpu_hz() / HZ_PER_MHZ ) );
-
-       return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-//#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 1 ) && ( ipconfigHAS_TX_CRC_OFFLOADING == 0 )
-
-       void vGMACGenerateChecksum( uint8_t *apBuffer )
-       {
-       ProtocolPacket_t *xProtPacket = (ProtocolPacket_t *)apBuffer;
-
-               if ( xProtPacket->xTCPPacket.xEthernetHeader.usFrameType == ipIPv4_FRAME_TYPE )
-               {
-                       IPHeader_t *pxIPHeader = &(xProtPacket->xTCPPacket.xIPHeader);
-
-                       /* Calculate the IP header checksum. */
-                       pxIPHeader->usHeaderChecksum = 0x00;
-                       pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );
-                       pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum );
-
-                       /* Calculate the TCP checksum for an outgoing packet. */
-                       usGenerateProtocolChecksum( ( uint8_t * ) apBuffer, pdTRUE );
-               }
-       }
-
-//#endif
-/*-----------------------------------------------------------*/
-
-static uint32_t prvEMACRxPoll( void )
-{
-unsigned char *pucUseBuffer;
-uint32_t ulReceiveCount, ulResult, ulReturnValue = 0;
-static NetworkBufferDescriptor_t *pxNextNetworkBufferDescriptor = NULL;
-const UBaseType_t xMinDescriptorsToLeave = 2UL;
-const TickType_t xBlockTime = pdMS_TO_TICKS( 100UL );
-static IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
-
-       for( ;; )
-       {
-               /* If pxNextNetworkBufferDescriptor was not left pointing at a valid
-               descriptor then allocate one now. */
-               if( ( pxNextNetworkBufferDescriptor == NULL ) && ( uxGetNumberOfFreeNetworkBuffers() > xMinDescriptorsToLeave ) )
-               {
-                       pxNextNetworkBufferDescriptor = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, xBlockTime );
-               }
-
-               if( pxNextNetworkBufferDescriptor != NULL )
-               {
-                       /* Point pucUseBuffer to the buffer pointed to by the descriptor. */
-                       pucUseBuffer = ( unsigned char* ) ( pxNextNetworkBufferDescriptor->pucEthernetBuffer - ipconfigPACKET_FILLER_SIZE );
-               }
-               else
-               {
-                       /* As long as pxNextNetworkBufferDescriptor is NULL, the incoming
-                       messages will be flushed and ignored. */
-                       pucUseBuffer = NULL;
-               }
-
-               /* Read the next packet from the hardware into pucUseBuffer. */
-               ulResult = gmac_dev_read( &gs_gmac_dev, pucUseBuffer, ipTOTAL_ETHERNET_FRAME_SIZE, &ulReceiveCount );
-
-               if( ( ulResult != GMAC_OK ) || ( ulReceiveCount == 0 ) )
-               {
-                       /* No data from the hardware. */
-                       break;
-               }
-
-               if( pxNextNetworkBufferDescriptor == NULL )
-               {
-                       /* Data was read from the hardware, but no descriptor was available
-                       for it, so it will be dropped. */
-                       iptraceETHERNET_RX_EVENT_LOST();
-                       continue;
-               }
-
-               iptraceNETWORK_INTERFACE_RECEIVE();
-               pxNextNetworkBufferDescriptor->xDataLength = ( size_t ) ulReceiveCount;
-               xRxEvent.pvData = ( void * ) pxNextNetworkBufferDescriptor;
-
-               /* Send the descriptor to the IP task for processing. */
-               if( xSendEventStructToIPTask( &xRxEvent, xBlockTime ) != pdTRUE )
-               {
-                       /* The buffer could not be sent to the stack so must be released
-                       again. */
-                       vReleaseNetworkBufferAndDescriptor( pxNextNetworkBufferDescriptor );
-                       iptraceETHERNET_RX_EVENT_LOST();
-                       FreeRTOS_printf( ( "prvEMACRxPoll: Can not queue return packet!\n" ) );
-               }
-
-               /* Now the buffer has either been passed to the IP-task,
-               or it has been released in the code above. */
-               pxNextNetworkBufferDescriptor = NULL;
-               ulReturnValue++;
-       }
-
-       return ulReturnValue;
-}
-/*-----------------------------------------------------------*/
-
-static void prvEMACHandlerTask( void *pvParameters )
-{
-TimeOut_t xPhyTime;
-TickType_t xPhyRemTime;
-UBaseType_t uxLastMinBufferCount = 0, uxCount;
-UBaseType_t uxCurrentCount;
-#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
-       UBaseType_t uxLastMinQueueSpace;
-#endif
-#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
-       NetworkBufferDescriptor_t *pxBuffer;
-#endif
-uint8_t *pucBuffer;
-BaseType_t xResult = 0;
-uint32_t xStatus;
-const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( EMAC_MAX_BLOCK_TIME_MS );
-
-       /* Remove compiler warnings about unused parameters. */
-       ( void ) pvParameters;
-
-       configASSERT( xEMACTaskHandle );
-
-       vTaskSetTimeOutState( &xPhyTime );
-       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
-
-       for( ;; )
-       {
-               uxCurrentCount = uxGetMinimumFreeNetworkBuffers();
-               if( uxLastMinBufferCount != uxCurrentCount )
-               {
-                       /* The logging produced below may be helpful
-                       while tuning +TCP: see how many buffers are in use. */
-                       uxLastMinBufferCount = uxCurrentCount;
-                       FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
-                               uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );
-               }
-
-               #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
-               {
-                       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;
-
-                       /* Wait for the EMAC interrupt to indicate that another packet has been
-                       received. */
-                       xResult = prvEMACRxPoll();
-               }
-
-               if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )
-               {
-                       /* Future extension: code to release TX buffers if zero-copy is used. */
-                       ulISREvents &= ~EMAC_IF_TX_EVENT;
-                       while( xQueueReceive( xTxBufferQueue, &pucBuffer, 0 ) != pdFALSE )
-                       {
-                               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
-                               {
-                                       pxBuffer = pxPacketBuffer_to_NetworkBuffer( pucBuffer );
-                                       if( pxBuffer != NULL )
-                                       {
-                                               vReleaseNetworkBufferAndDescriptor( pxBuffer );
-                                               tx_release_count[ 0 ]++;
-                                       }
-                                       else
-                                       {
-                                               tx_release_count[ 1 ]++;
-                                       }
-                               }
-                               #else
-                               {
-                                       tx_release_count[ 0 ]++;
-                               }
-                               #endif
-                               uxCount = uxQueueMessagesWaiting( ( QueueHandle_t ) xTXDescriptorSemaphore );
-                               if( uxCount < GMAC_TX_BUFFERS )
-                               {
-                                       /* Tell the counting semaphore that one more TX descriptor is available. */
-                                       xSemaphoreGive( xTXDescriptorSemaphore );
-                               }
-                       }
-               }
-
-               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 )
-               {
-                       /* Check the link status again. */
-                       xStatus = ulReadMDIO( PHY_REG_01_BMSR );
-
-                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )
-                       {
-                               ulPHYLinkStatus = xStatus;
-                               FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );
-                       }
-
-                       vTaskSetTimeOutState( &xPhyTime );
-                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
-                       {
-                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
-                       }
-                       else
-                       {
-                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
-                       }
-               }
-       }
-}
-/*-----------------------------------------------------------*/
+/*\r
+FreeRTOS+TCP V2.0.11\r
+Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+this software and associated documentation files (the "Software"), to deal in\r
+the Software without restriction, including without limitation the rights to\r
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+the Software, and to permit persons to whom the Software is furnished to do so,\r
+subject to the following conditions:\r
+\r
+The above copyright notice and this permission notice shall be included in all\r
+copies or substantial portions of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+\r
+ http://aws.amazon.com/freertos\r
+ http://www.FreeRTOS.org\r
+*/\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+#include "NetworkInterface.h"\r
+\r
+/* Some files from the Atmel Software Framework */\r
+/*_RB_ The SAM4E portable layer has three different header files called gmac.h! */\r
+#include "instance/gmac.h"\r
+#include <sysclk.h>\r
+#include <ethernet_phy.h>\r
+\r
+#ifndef        BMSR_LINK_STATUS\r
+       #define BMSR_LINK_STATUS            0x0004  //!< Link status\r
+#endif\r
+\r
+#ifndef        PHY_LS_HIGH_CHECK_TIME_MS\r
+       /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not\r
+       receiving packets. */\r
+       #define PHY_LS_HIGH_CHECK_TIME_MS       15000\r
+#endif\r
+\r
+#ifndef        PHY_LS_LOW_CHECK_TIME_MS\r
+       /* Check if the LinkSStatus in the PHY is still low every second. */\r
+       #define PHY_LS_LOW_CHECK_TIME_MS        1000\r
+#endif\r
+\r
+/* 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 ETHERNET_CONF_PHY_ADDR  BOARD_GMAC_PHY_ADDR\r
+\r
+#define HZ_PER_MHZ                             ( 1000000UL )\r
+\r
+#ifndef        EMAC_MAX_BLOCK_TIME_MS\r
+       #define EMAC_MAX_BLOCK_TIME_MS  100ul\r
+#endif\r
+\r
+#if !defined( GMAC_USES_TX_CALLBACK ) || ( GMAC_USES_TX_CALLBACK != 1 )\r
+       #error Please define GMAC_USES_TX_CALLBACK as 1\r
+#endif\r
+\r
+/* Default the size of the stack used by the EMAC deferred handler task to 4x\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 ( 4 * configMINIMAL_STACK_SIZE )\r
+#endif\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Wait a fixed time for the link status to indicate the network is up.\r
+ */\r
+static BaseType_t xGMACWaitLS( TickType_t xMaxTime );\r
+\r
+#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 1 ) && ( ipconfigHAS_TX_CRC_OFFLOADING == 0 )\r
+       void vGMACGenerateChecksum( uint8_t *apBuffer );\r
+#endif\r
+\r
+/*\r
+ * Called from the ASF GMAC driver.\r
+ */\r
+static void prvRxCallback( uint32_t ulStatus );\r
+static void prvTxCallback( uint32_t ulStatus, uint8_t *puc_buffer );\r
+\r
+/*\r
+ * A deferred interrupt handler task that processes GMAC interrupts.\r
+ */\r
+static void prvEMACHandlerTask( void *pvParameters );\r
+\r
+/*\r
+ * Initialise the ASF GMAC driver.\r
+ */\r
+static BaseType_t prvGMACInit( void );\r
+\r
+/*\r
+ * Try to obtain an Rx packet from the hardware.\r
+ */\r
+static uint32_t prvEMACRxPoll( 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
+/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */\r
+static uint32_t ulPHYLinkStatus = 0;\r
+static volatile BaseType_t xGMACSwitchRequired;\r
+\r
+/* ethernet_phy_addr: the address of the PHY in use.\r
+Atmel was a bit ambiguous about it so the address will be stored\r
+in this variable, see ethernet_phy.c */\r
+extern int ethernet_phy_addr;\r
+\r
+/* LLMNR multicast address. */\r
+static const uint8_t llmnr_mac_address[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };\r
+\r
+/* The GMAC object as defined by the ASF drivers. */\r
+static gmac_device_t gs_gmac_dev;\r
+\r
+/* MAC address to use. */\r
+extern const uint8_t ucMACAddress[ 6 ];\r
+\r
+/* Holds the handle of the task used as a deferred interrupt processor.  The\r
+handle is used so direct notifications can be sent to the task for all EMAC/DMA\r
+related interrupts. */\r
+TaskHandle_t xEMACTaskHandle = NULL;\r
+\r
+static QueueHandle_t xTxBufferQueue;\r
+int tx_release_count[ 4 ];\r
+\r
+/* xTXDescriptorSemaphore is a counting semaphore with\r
+a maximum count of GMAC_TX_BUFFERS, which is the number of\r
+DMA TX descriptors. */\r
+static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * GMAC interrupt handler.\r
+ */\r
+void GMAC_Handler(void)\r
+{\r
+       xGMACSwitchRequired = pdFALSE;\r
+\r
+       /* gmac_handler() may call prvRxCallback() which may change\r
+       the value of xGMACSwitchRequired. */\r
+       gmac_handler( &gs_gmac_dev );\r
+\r
+       if( xGMACSwitchRequired != pdFALSE )\r
+       {\r
+               portEND_SWITCHING_ISR( xGMACSwitchRequired );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvRxCallback( uint32_t ulStatus )\r
+{\r
+       if( ( ( ulStatus & GMAC_RSR_REC ) != 0 ) && ( xEMACTaskHandle != NULL ) )\r
+       {\r
+               /* let the prvEMACHandlerTask know that there was an RX event. */\r
+               ulISREvents |= EMAC_IF_RX_EVENT;\r
+               /* Only an RX interrupt can wakeup prvEMACHandlerTask. */\r
+               vTaskNotifyGiveFromISR( xEMACTaskHandle, ( BaseType_t * ) &xGMACSwitchRequired );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvTxCallback( uint32_t ulStatus, uint8_t *puc_buffer )\r
+{\r
+       if( ( xTxBufferQueue != NULL ) && ( xEMACTaskHandle != NULL ) )\r
+       {\r
+               /* let the prvEMACHandlerTask know that there was an RX event. */\r
+               ulISREvents |= EMAC_IF_TX_EVENT;\r
+\r
+               vTaskNotifyGiveFromISR( xEMACTaskHandle, ( BaseType_t * ) &xGMACSwitchRequired );\r
+               xQueueSendFromISR( xTxBufferQueue, &puc_buffer, ( BaseType_t * ) &xGMACSwitchRequired );\r
+               tx_release_count[ 2 ]++;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+const TickType_t x5_Seconds = 5000UL;\r
+\r
+       if( xEMACTaskHandle == NULL )\r
+       {\r
+               prvGMACInit();\r
+\r
+               /* Wait at most 5 seconds for a Link Status in the PHY. */\r
+               xGMACWaitLS( pdMS_TO_TICKS( x5_Seconds ) );\r
+\r
+               /* The handler task is created at the highest possible priority to\r
+               ensure the interrupt handler can return directly to it. */\r
+               xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );\r
+               configASSERT( xEMACTaskHandle );\r
+       }\r
+\r
+       if( xTxBufferQueue == NULL )\r
+       {\r
+               xTxBufferQueue = xQueueCreate( GMAC_TX_BUFFERS, sizeof( void * ) );\r
+               configASSERT( xTxBufferQueue );\r
+       }\r
+\r
+       if( xTXDescriptorSemaphore == NULL )\r
+       {\r
+               xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) GMAC_TX_BUFFERS, ( UBaseType_t ) GMAC_TX_BUFFERS );\r
+               configASSERT( xTXDescriptorSemaphore );\r
+       }\r
+       /* When returning non-zero, the stack will become active and\r
+    start DHCP (in configured) */\r
+       return ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xGetPhyLinkStatus( void )\r
+{\r
+BaseType_t xResult;\r
+\r
+       /* This function returns true if the Link Status in the PHY is high. */\r
+       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+       {\r
+               xResult = pdTRUE;\r
+       }\r
+       else\r
+       {\r
+               xResult = pdFALSE;\r
+       }\r
+\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend )\r
+{\r
+/* Do not wait too long for a free TX DMA buffer. */\r
+const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );\r
+\r
+       do {\r
+               if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )\r
+               {\r
+                       /* Do not attempt to send packets as long as the Link Status is low. */\r
+                       break;\r
+               }\r
+               if( xTXDescriptorSemaphore == NULL )\r
+               {\r
+                       /* Semaphore has not been created yet? */\r
+                       break;\r
+               }\r
+               if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )\r
+               {\r
+                       /* Time-out waiting for a free TX descriptor. */\r
+                       tx_release_count[ 3 ]++;\r
+                       break;\r
+               }\r
+               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+               {\r
+                       /* Confirm that the pxDescriptor may be kept by the driver. */\r
+                       configASSERT( bReleaseAfterSend != pdFALSE );\r
+               }\r
+               #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+\r
+               gmac_dev_write( &gs_gmac_dev, (void *)pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength, prvTxCallback );\r
+\r
+               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+               {\r
+                       /* Confirm that the pxDescriptor may be kept by the driver. */\r
+                       bReleaseAfterSend = pdFALSE;\r
+               }\r
+               #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+               /* Not interested in a call-back after TX. */\r
+               iptraceNETWORK_INTERFACE_TRANSMIT();\r
+       } while( 0 );\r
+\r
+       if( bReleaseAfterSend != pdFALSE )\r
+       {\r
+               vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
+       }\r
+       return pdTRUE;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvGMACInit( void )\r
+{\r
+uint32_t ncfgr;\r
+\r
+       gmac_options_t gmac_option;\r
+\r
+       memset( &gmac_option, '\0', sizeof( gmac_option ) );\r
+       gmac_option.uc_copy_all_frame = 0;\r
+       gmac_option.uc_no_boardcast = 0;\r
+       memcpy( gmac_option.uc_mac_addr, ucMACAddress, sizeof( gmac_option.uc_mac_addr ) );\r
+\r
+       gs_gmac_dev.p_hw = GMAC;\r
+       gmac_dev_init( GMAC, &gs_gmac_dev, &gmac_option );\r
+\r
+       NVIC_SetPriority( GMAC_IRQn, configMAC_INTERRUPT_PRIORITY );\r
+       NVIC_EnableIRQ( GMAC_IRQn );\r
+\r
+       /* Contact the Ethernet PHY and store it's address in 'ethernet_phy_addr' */\r
+       ethernet_phy_init( GMAC, ETHERNET_CONF_PHY_ADDR, sysclk_get_cpu_hz() );\r
+\r
+       ethernet_phy_auto_negotiate( GMAC, ethernet_phy_addr );\r
+       ethernet_phy_set_link( GMAC, ethernet_phy_addr, 1 );\r
+\r
+       /* The GMAC driver will call a hook prvRxCallback(), which\r
+       in turn will wake-up the task by calling vTaskNotifyGiveFromISR() */\r
+       gmac_dev_set_rx_callback( &gs_gmac_dev, prvRxCallback );\r
+       gmac_set_address( GMAC, 1, (uint8_t*)llmnr_mac_address );\r
+\r
+       ncfgr = GMAC_NCFGR_SPD | GMAC_NCFGR_FD;\r
+\r
+       GMAC->GMAC_NCFGR = ( GMAC->GMAC_NCFGR & ~( GMAC_NCFGR_SPD | GMAC_NCFGR_FD ) ) | ncfgr;\r
+\r
+       return 1;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static inline unsigned long ulReadMDIO( unsigned /*short*/ usAddress )\r
+{\r
+uint32_t ulValue, ulReturn;\r
+int rc;\r
+\r
+       gmac_enable_management( GMAC, 1 );\r
+       rc = gmac_phy_read( GMAC, ethernet_phy_addr, usAddress, &ulValue );\r
+       gmac_enable_management( GMAC, 0 );\r
+       if( rc == GMAC_OK )\r
+       {\r
+               ulReturn = ulValue;\r
+       }\r
+       else\r
+       {\r
+               ulReturn = 0UL;\r
+       }\r
+\r
+       return ulReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t xGMACWaitLS( TickType_t xMaxTime )\r
+{\r
+TickType_t xStartTime = xTaskGetTickCount();\r
+TickType_t xEndTime;\r
+BaseType_t xReturn;\r
+const TickType_t xShortTime = pdMS_TO_TICKS( 100UL );\r
+\r
+       for( ;; )\r
+       {\r
+               xEndTime = xTaskGetTickCount();\r
+\r
+               if( ( xEndTime - xStartTime ) > xMaxTime )\r
+               {\r
+                       /* Wated more than xMaxTime, return. */\r
+                       xReturn = pdFALSE;\r
+                       break;\r
+               }\r
+\r
+               /* Check the link status again. */\r
+               ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );\r
+\r
+               if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+               {\r
+                       /* Link is up - return. */\r
+                       xReturn = pdTRUE;\r
+                       break;\r
+               }\r
+\r
+               /* Link is down - wait in the Blocked state for a short while (to allow\r
+               other tasks to execute) before checking again. */\r
+               vTaskDelay( xShortTime );\r
+       }\r
+\r
+       FreeRTOS_printf( ( "xGMACWaitLS: %ld (PHY %d) freq %lu Mz\n",\r
+               xReturn,\r
+               ethernet_phy_addr,\r
+               sysclk_get_cpu_hz() / HZ_PER_MHZ ) );\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+//#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 1 ) && ( ipconfigHAS_TX_CRC_OFFLOADING == 0 )\r
+\r
+       void vGMACGenerateChecksum( uint8_t *apBuffer )\r
+       {\r
+       ProtocolPacket_t *xProtPacket = (ProtocolPacket_t *)apBuffer;\r
+\r
+               if ( xProtPacket->xTCPPacket.xEthernetHeader.usFrameType == ipIPv4_FRAME_TYPE )\r
+               {\r
+                       IPHeader_t *pxIPHeader = &(xProtPacket->xTCPPacket.xIPHeader);\r
+\r
+                       /* Calculate the IP header checksum. */\r
+                       pxIPHeader->usHeaderChecksum = 0x00;\r
+                       pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );\r
+                       pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum );\r
+\r
+                       /* Calculate the TCP checksum for an outgoing packet. */\r
+                       usGenerateProtocolChecksum( ( uint8_t * ) apBuffer, pdTRUE );\r
+               }\r
+       }\r
+\r
+//#endif\r
+/*-----------------------------------------------------------*/\r
+\r
+static uint32_t prvEMACRxPoll( void )\r
+{\r
+unsigned char *pucUseBuffer;\r
+uint32_t ulReceiveCount, ulResult, ulReturnValue = 0;\r
+static NetworkBufferDescriptor_t *pxNextNetworkBufferDescriptor = NULL;\r
+const UBaseType_t xMinDescriptorsToLeave = 2UL;\r
+const TickType_t xBlockTime = pdMS_TO_TICKS( 100UL );\r
+static IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
+\r
+       for( ;; )\r
+       {\r
+               /* If pxNextNetworkBufferDescriptor was not left pointing at a valid\r
+               descriptor then allocate one now. */\r
+               if( ( pxNextNetworkBufferDescriptor == NULL ) && ( uxGetNumberOfFreeNetworkBuffers() > xMinDescriptorsToLeave ) )\r
+               {\r
+                       pxNextNetworkBufferDescriptor = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, xBlockTime );\r
+               }\r
+\r
+               if( pxNextNetworkBufferDescriptor != NULL )\r
+               {\r
+                       /* Point pucUseBuffer to the buffer pointed to by the descriptor. */\r
+                       pucUseBuffer = ( unsigned char* ) ( pxNextNetworkBufferDescriptor->pucEthernetBuffer - ipconfigPACKET_FILLER_SIZE );\r
+               }\r
+               else\r
+               {\r
+                       /* As long as pxNextNetworkBufferDescriptor is NULL, the incoming\r
+                       messages will be flushed and ignored. */\r
+                       pucUseBuffer = NULL;\r
+               }\r
+\r
+               /* Read the next packet from the hardware into pucUseBuffer. */\r
+               ulResult = gmac_dev_read( &gs_gmac_dev, pucUseBuffer, ipTOTAL_ETHERNET_FRAME_SIZE, &ulReceiveCount );\r
+\r
+               if( ( ulResult != GMAC_OK ) || ( ulReceiveCount == 0 ) )\r
+               {\r
+                       /* No data from the hardware. */\r
+                       break;\r
+               }\r
+\r
+               if( pxNextNetworkBufferDescriptor == NULL )\r
+               {\r
+                       /* Data was read from the hardware, but no descriptor was available\r
+                       for it, so it will be dropped. */\r
+                       iptraceETHERNET_RX_EVENT_LOST();\r
+                       continue;\r
+               }\r
+\r
+               iptraceNETWORK_INTERFACE_RECEIVE();\r
+               pxNextNetworkBufferDescriptor->xDataLength = ( size_t ) ulReceiveCount;\r
+               xRxEvent.pvData = ( void * ) pxNextNetworkBufferDescriptor;\r
+\r
+               /* Send the descriptor to the IP task for processing. */\r
+               if( xSendEventStructToIPTask( &xRxEvent, xBlockTime ) != pdTRUE )\r
+               {\r
+                       /* The buffer could not be sent to the stack so must be released\r
+                       again. */\r
+                       vReleaseNetworkBufferAndDescriptor( pxNextNetworkBufferDescriptor );\r
+                       iptraceETHERNET_RX_EVENT_LOST();\r
+                       FreeRTOS_printf( ( "prvEMACRxPoll: Can not queue return packet!\n" ) );\r
+               }\r
+\r
+               /* Now the buffer has either been passed to the IP-task,\r
+               or it has been released in the code above. */\r
+               pxNextNetworkBufferDescriptor = NULL;\r
+               ulReturnValue++;\r
+       }\r
+\r
+       return ulReturnValue;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvEMACHandlerTask( void *pvParameters )\r
+{\r
+TimeOut_t xPhyTime;\r
+TickType_t xPhyRemTime;\r
+UBaseType_t uxLastMinBufferCount = 0, uxCount;\r
+UBaseType_t uxCurrentCount;\r
+#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+       UBaseType_t uxLastMinQueueSpace;\r
+#endif\r
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+       NetworkBufferDescriptor_t *pxBuffer;\r
+#endif\r
+uint8_t *pucBuffer;\r
+BaseType_t xResult = 0;\r
+uint32_t xStatus;\r
+const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( EMAC_MAX_BLOCK_TIME_MS );\r
+\r
+       /* Remove compiler warnings about unused parameters. */\r
+       ( void ) pvParameters;\r
+\r
+       configASSERT( xEMACTaskHandle );\r
+\r
+       vTaskSetTimeOutState( &xPhyTime );\r
+       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+\r
+       for( ;; )\r
+       {\r
+               uxCurrentCount = uxGetMinimumFreeNetworkBuffers();\r
+               if( uxLastMinBufferCount != uxCurrentCount )\r
+               {\r
+                       /* The logging produced below may be helpful\r
+                       while tuning +TCP: see how many buffers are in use. */\r
+                       uxLastMinBufferCount = uxCurrentCount;\r
+                       FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",\r
+                               uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );\r
+               }\r
+\r
+               #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+               {\r
+                       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
+                       /* Wait for the EMAC interrupt to indicate that another packet has been\r
+                       received. */\r
+                       xResult = prvEMACRxPoll();\r
+               }\r
+\r
+               if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )\r
+               {\r
+                       /* Future extension: code to release TX buffers if zero-copy is used. */\r
+                       ulISREvents &= ~EMAC_IF_TX_EVENT;\r
+                       while( xQueueReceive( xTxBufferQueue, &pucBuffer, 0 ) != pdFALSE )\r
+                       {\r
+                               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+                               {\r
+                                       pxBuffer = pxPacketBuffer_to_NetworkBuffer( pucBuffer );\r
+                                       if( pxBuffer != NULL )\r
+                                       {\r
+                                               vReleaseNetworkBufferAndDescriptor( pxBuffer );\r
+                                               tx_release_count[ 0 ]++;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               tx_release_count[ 1 ]++;\r
+                                       }\r
+                               }\r
+                               #else\r
+                               {\r
+                                       tx_release_count[ 0 ]++;\r
+                               }\r
+                               #endif\r
+                               uxCount = uxQueueMessagesWaiting( ( QueueHandle_t ) xTXDescriptorSemaphore );\r
+                               if( uxCount < GMAC_TX_BUFFERS )\r
+                               {\r
+                                       /* Tell the counting semaphore that one more TX descriptor is available. */\r
+                                       xSemaphoreGive( xTXDescriptorSemaphore );\r
+                               }\r
+                       }\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
+\r
+               if( xResult > 0 )\r
+               {\r
+                       /* A packet was received. No need to check for the PHY status now,\r
+                       but set a timer to check it later on. */\r
+                       vTaskSetTimeOutState( &xPhyTime );\r
+                       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+                       xResult = 0;\r
+               }\r
+               else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE )\r
+               {\r
+                       /* Check the link status again. */\r
+                       xStatus = ulReadMDIO( PHY_REG_01_BMSR );\r
+\r
+                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )\r
+                       {\r
+                               ulPHYLinkStatus = xStatus;\r
+                               FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );\r
+                       }\r
+\r
+                       vTaskSetTimeOutState( &xPhyTime );\r
+                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+                       {\r
+                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+                       }\r
+                       else\r
+                       {\r
+                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+                       }\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
index ae40ac9601b254782c5209f7532cf82b1fe3325a..6eb069f55a123cee6f67703371b31f3ec5ffce6f 100644 (file)
-/**
- * \file
- *
- * Copyright (c) 2012 Atmel Corporation. All rights reserved.
- *
- * \asf_license_start
- *
- * \page License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *
- * 3. The name of Atmel may not be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * 4. This software may only be redistributed and used in connection with an
- *    Atmel microcontroller product.
- *
- * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
- * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * \asf_license_stop
- *
- */
-
-#ifndef _SAM4E_GMAC_COMPONENT_
-#define _SAM4E_GMAC_COMPONENT_
-
-/* ============================================================================= */
-/**  SOFTWARE API DEFINITION FOR Gigabit Ethernet MAC */
-/* ============================================================================= */
-/** \addtogroup SAM4E_GMAC Gigabit Ethernet MAC */
-/*@{*/
-
-#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))
-/** \brief GmacSa hardware registers */
-typedef struct {
-  RwReg   GMAC_SAB;        /**< \brief (GmacSa Offset: 0x0) Specific Address 1 Bottom [31:0] Register */
-  RwReg   GMAC_SAT;        /**< \brief (GmacSa Offset: 0x4) Specific Address 1 Top [47:32] Register */
-} GmacSa;
-/** \brief Gmac hardware registers */
-#define GMACSA_NUMBER 4
-typedef struct {
-  RwReg   GMAC_NCR;        /**< \brief (Gmac Offset: 0x000) Network Control Register */
-  RwReg   GMAC_NCFGR;      /**< \brief (Gmac Offset: 0x004) Network Configuration Register */
-  RoReg   GMAC_NSR;        /**< \brief (Gmac Offset: 0x008) Network Status Register */
-  RwReg   GMAC_UR;         /**< \brief (Gmac Offset: 0x00C) User Register */
-  RwReg   GMAC_DCFGR;      /**< \brief (Gmac Offset: 0x010) DMA Configuration Register */
-  RwReg   GMAC_TSR;        /**< \brief (Gmac Offset: 0x014) Transmit Status Register */
-  RwReg   GMAC_RBQB;       /**< \brief (Gmac Offset: 0x018) Receive Buffer Queue Base Address */
-  RwReg   GMAC_TBQB;       /**< \brief (Gmac Offset: 0x01C) Transmit Buffer Queue Base Address */
-  RwReg   GMAC_RSR;        /**< \brief (Gmac Offset: 0x020) Receive Status Register */
-  RoReg   GMAC_ISR;        /**< \brief (Gmac Offset: 0x024) Interrupt Status Register */
-  WoReg   GMAC_IER;        /**< \brief (Gmac Offset: 0x028) Interrupt Enable Register */
-  WoReg   GMAC_IDR;        /**< \brief (Gmac Offset: 0x02C) Interrupt Disable Register */
-  RoReg   GMAC_IMR;        /**< \brief (Gmac Offset: 0x030) Interrupt Mask Register */
-  RwReg   GMAC_MAN;        /**< \brief (Gmac Offset: 0x034) PHY Maintenance Register */
-  RoReg   GMAC_RPQ;        /**< \brief (Gmac Offset: 0x038) Received Pause Quantum Register */
-  RwReg   GMAC_TPQ;        /**< \brief (Gmac Offset: 0x03C) Transmit Pause Quantum Register */
-  RwReg   GMAC_TPSF;       /**< \brief (Gmac Offset: 0x040) TX Partial Store and Forward Register */
-  RwReg   GMAC_RPSF;       /**< \brief (Gmac Offset: 0x044) RX Partial Store and Forward Register */
-  RoReg   Reserved1[14];
-  RwReg   GMAC_HRB;        /**< \brief (Gmac Offset: 0x080) Hash Register Bottom [31:0] */
-  RwReg   GMAC_HRT;        /**< \brief (Gmac Offset: 0x084) Hash Register Top [63:32] */
-  GmacSa  GMAC_SA[GMACSA_NUMBER]; /**< \brief (Gmac Offset: 0x088) 1 .. 4 */
-  RwReg   GMAC_TIDM[4];    /**< \brief (Gmac Offset: 0x0A8) Type ID Match 1 Register */
-  RwReg   GMAC_WOL;        /**< \brief (Gmac Offset: 0x0B8) Wake on LAN Register */
-  RwReg   GMAC_IPGS;       /**< \brief (Gmac Offset: 0x0BC) IPG Stretch Register */
-  RwReg   GMAC_SVLAN;      /**< \brief (Gmac Offset: 0x0C0) Stacked VLAN Register */
-  RwReg   GMAC_TPFCP;      /**< \brief (Gmac Offset: 0x0C4) Transmit PFC Pause Register */
-  RwReg   GMAC_SAMB1;      /**< \brief (Gmac Offset: 0x0C8) Specific Address 1 Mask Bottom [31:0] Register */
-  RwReg   GMAC_SAMT1;      /**< \brief (Gmac Offset: 0x0CC) Specific Address 1 Mask Top [47:32] Register */
-  RoReg   Reserved2[12];
-  RoReg   GMAC_OTLO;       /**< \brief (Gmac Offset: 0x100) Octets Transmitted [31:0] Register */
-  RoReg   GMAC_OTHI;       /**< \brief (Gmac Offset: 0x104) Octets Transmitted [47:32] Register */
-  RoReg   GMAC_FT;         /**< \brief (Gmac Offset: 0x108) Frames Transmitted Register */
-  RoReg   GMAC_BCFT;       /**< \brief (Gmac Offset: 0x10C) Broadcast Frames Transmitted Register */
-  RoReg   GMAC_MFT;        /**< \brief (Gmac Offset: 0x110) Multicast Frames Transmitted Register */
-  RoReg   GMAC_PFT;        /**< \brief (Gmac Offset: 0x114) Pause Frames Transmitted Register */
-  RoReg   GMAC_BFT64;      /**< \brief (Gmac Offset: 0x118) 64 Byte Frames Transmitted Register */
-  RoReg   GMAC_TBFT127;    /**< \brief (Gmac Offset: 0x11C) 65 to 127 Byte Frames Transmitted Register */
-  RoReg   GMAC_TBFT255;    /**< \brief (Gmac Offset: 0x120) 128 to 255 Byte Frames Transmitted Register */
-  RoReg   GMAC_TBFT511;    /**< \brief (Gmac Offset: 0x124) 256 to 511 Byte Frames Transmitted Register */
-  RoReg   GMAC_TBFT1023;   /**< \brief (Gmac Offset: 0x128) 512 to 1023 Byte Frames Transmitted Register */
-  RoReg   GMAC_TBFT1518;   /**< \brief (Gmac Offset: 0x12C) 1024 to 1518 Byte Frames Transmitted Register */
-  RoReg   GMAC_GTBFT1518;  /**< \brief (Gmac Offset: 0x130) Greater Than 1518 Byte Frames Transmitted Register */
-  RoReg   GMAC_TUR;        /**< \brief (Gmac Offset: 0x134) Transmit Under Runs Register */
-  RoReg   GMAC_SCF;        /**< \brief (Gmac Offset: 0x138) Single Collision Frames Register */
-  RoReg   GMAC_MCF;        /**< \brief (Gmac Offset: 0x13C) Multiple Collision Frames Register */
-  RoReg   GMAC_EC;         /**< \brief (Gmac Offset: 0x140) Excessive Collisions Register */
-  RoReg   GMAC_LC;         /**< \brief (Gmac Offset: 0x144) Late Collisions Register */
-  RoReg   GMAC_DTF;        /**< \brief (Gmac Offset: 0x148) Deferred Transmission Frames Register */
-  RoReg   GMAC_CSE;        /**< \brief (Gmac Offset: 0x14C) Carrier Sense Errors Register */
-  RoReg   GMAC_ORLO;       /**< \brief (Gmac Offset: 0x150) Octets Received [31:0] Received */
-  RoReg   GMAC_ORHI;       /**< \brief (Gmac Offset: 0x154) Octets Received [47:32] Received */
-  RoReg   GMAC_FR;         /**< \brief (Gmac Offset: 0x158) Frames Received Register */
-  RoReg   GMAC_BCFR;       /**< \brief (Gmac Offset: 0x15C) Broadcast Frames Received Register */
-  RoReg   GMAC_MFR;        /**< \brief (Gmac Offset: 0x160) Multicast Frames Received Register */
-  RoReg   GMAC_PFR;        /**< \brief (Gmac Offset: 0x164) Pause Frames Received Register */
-  RoReg   GMAC_BFR64;      /**< \brief (Gmac Offset: 0x168) 64 Byte Frames Received Register */
-  RoReg   GMAC_TBFR127;    /**< \brief (Gmac Offset: 0x16C) 65 to 127 Byte Frames Received Register */
-  RoReg   GMAC_TBFR255;    /**< \brief (Gmac Offset: 0x170) 128 to 255 Byte Frames Received Register */
-  RoReg   GMAC_TBFR511;    /**< \brief (Gmac Offset: 0x174) 256 to 511Byte Frames Received Register */
-  RoReg   GMAC_TBFR1023;   /**< \brief (Gmac Offset: 0x178) 512 to 1023 Byte Frames Received Register */
-  RoReg   GMAC_TBFR1518;   /**< \brief (Gmac Offset: 0x17C) 1024 to 1518 Byte Frames Received Register */
-  RoReg   GMAC_TMXBFR;     /**< \brief (Gmac Offset: 0x180) 1519 to Maximum Byte Frames Received Register */
-  RoReg   GMAC_UFR;        /**< \brief (Gmac Offset: 0x184) Undersize Frames Received Register */
-  RoReg   GMAC_OFR;        /**< \brief (Gmac Offset: 0x188) Oversize Frames Received Register */
-  RoReg   GMAC_JR;         /**< \brief (Gmac Offset: 0x18C) Jabbers Received Register */
-  RoReg   GMAC_FCSE;       /**< \brief (Gmac Offset: 0x190) Frame Check Sequence Errors Register */
-  RoReg   GMAC_LFFE;       /**< \brief (Gmac Offset: 0x194) Length Field Frame Errors Register */
-  RoReg   GMAC_RSE;        /**< \brief (Gmac Offset: 0x198) Receive Symbol Errors Register */
-  RoReg   GMAC_AE;         /**< \brief (Gmac Offset: 0x19C) Alignment Errors Register */
-  RoReg   GMAC_RRE;        /**< \brief (Gmac Offset: 0x1A0) Receive Resource Errors Register */
-  RoReg   GMAC_ROE;        /**< \brief (Gmac Offset: 0x1A4) Receive Overrun Register */
-  RoReg   GMAC_IHCE;       /**< \brief (Gmac Offset: 0x1A8) IP Header Checksum Errors Register */
-  RoReg   GMAC_TCE;        /**< \brief (Gmac Offset: 0x1AC) TCP Checksum Errors Register */
-  RoReg   GMAC_UCE;        /**< \brief (Gmac Offset: 0x1B0) UDP Checksum Errors Register */
-  RoReg   Reserved3[5];
-  RwReg   GMAC_TSSS;       /**< \brief (Gmac Offset: 0x1C8) 1588 Timer Sync Strobe Seconds Register */
-  RwReg   GMAC_TSSN;       /**< \brief (Gmac Offset: 0x1CC) 1588 Timer Sync Strobe Nanoseconds Register */
-  RwReg   GMAC_TS;         /**< \brief (Gmac Offset: 0x1D0) 1588 Timer Seconds Register */
-  RwReg   GMAC_TN;         /**< \brief (Gmac Offset: 0x1D4) 1588 Timer Nanoseconds Register */
-  WoReg   GMAC_TA;         /**< \brief (Gmac Offset: 0x1D8) 1588 Timer Adjust Register */
-  RwReg   GMAC_TI;         /**< \brief (Gmac Offset: 0x1DC) 1588 Timer Increment Register */
-  RoReg   GMAC_EFTS;       /**< \brief (Gmac Offset: 0x1E0) PTP Event Frame Transmitted Seconds */
-  RoReg   GMAC_EFTN;       /**< \brief (Gmac Offset: 0x1E4) PTP Event Frame Transmitted Nanoseconds */
-  RoReg   GMAC_EFRS;       /**< \brief (Gmac Offset: 0x1E8) PTP Event Frame Received Seconds */
-  RoReg   GMAC_EFRN;       /**< \brief (Gmac Offset: 0x1EC) PTP Event Frame Received Nanoseconds */
-  RoReg   GMAC_PEFTS;      /**< \brief (Gmac Offset: 0x1F0) PTP Peer Event Frame Transmitted Seconds */
-  RoReg   GMAC_PEFTN;      /**< \brief (Gmac Offset: 0x1F4) PTP Peer Event Frame Transmitted Nanoseconds */
-  RoReg   GMAC_PEFRS;      /**< \brief (Gmac Offset: 0x1F8) PTP Peer Event Frame Received Seconds */
-  RoReg   GMAC_PEFRN;      /**< \brief (Gmac Offset: 0x1FC) PTP Peer Event Frame Received Nanoseconds */
-  RoReg   Reserved4[128];
-  RoReg   GMAC_ISRPQ[7];   /**< \brief (Gmac Offset: 0x400) Interrupt Status Register Priority Queue */
-  RoReg   Reserved5[9];
-  RwReg   GMAC_TBQBAPQ[7]; /**< \brief (Gmac Offset: 0x440) Transmit Buffer Queue Base Address Priority Queue */
-  RoReg   Reserved6[9];
-  RwReg   GMAC_RBQBAPQ[7]; /**< \brief (Gmac Offset: 0x480) Receive Buffer Queue Base Address Priority Queue */
-  RoReg   Reserved7[1];
-  RwReg   GMAC_RBSRPQ[7];  /**< \brief (Gmac Offset: 0x4A0) Receive Buffer Size Register Priority Queue */
-  RoReg   Reserved8[17];
-  RwReg   GMAC_ST1RPQ[16]; /**< \brief (Gmac Offset: 0x500) Screening Type1 Register Priority Queue */
-  RwReg   GMAC_ST2RPQ[16]; /**< \brief (Gmac Offset: 0x540) Screening Type2 Register Priority Queue */
-  RoReg   Reserved9[32];
-  WoReg   GMAC_IERPQ[7];   /**< \brief (Gmac Offset: 0x600) Interrupt Enable Register Priority Queue */
-  RoReg   Reserved10[1];
-  WoReg   GMAC_IDRPQ[7];   /**< \brief (Gmac Offset: 0x620) Interrupt Disable Register Priority Queue */
-  RoReg   Reserved11[1];
-  RwReg   GMAC_IMRPQ[7];   /**< \brief (Gmac Offset: 0x640) Interrupt Mask Register Priority Queue */
-} Gmac;
-#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
-/* -------- GMAC_NCR : (GMAC Offset: 0x000) Network Control Register -------- */
-#define GMAC_NCR_LB (0x1u << 0) /**< \brief (GMAC_NCR) Loop Back */
-#define GMAC_NCR_LBL (0x1u << 1) /**< \brief (GMAC_NCR) Loop Back Local */
-#define GMAC_NCR_RXEN (0x1u << 2) /**< \brief (GMAC_NCR) Receive Enable */
-#define GMAC_NCR_TXEN (0x1u << 3) /**< \brief (GMAC_NCR) Transmit Enable */
-#define GMAC_NCR_MPE (0x1u << 4) /**< \brief (GMAC_NCR) Management Port Enable */
-#define GMAC_NCR_CLRSTAT (0x1u << 5) /**< \brief (GMAC_NCR) Clear Statistics Registers */
-#define GMAC_NCR_INCSTAT (0x1u << 6) /**< \brief (GMAC_NCR) Increment Statistics Registers */
-#define GMAC_NCR_WESTAT (0x1u << 7) /**< \brief (GMAC_NCR) Write Enable for Statistics Registers */
-#define GMAC_NCR_BP (0x1u << 8) /**< \brief (GMAC_NCR) Back pressure */
-#define GMAC_NCR_TSTART (0x1u << 9) /**< \brief (GMAC_NCR) Start Transmission */
-#define GMAC_NCR_THALT (0x1u << 10) /**< \brief (GMAC_NCR) Transmit Halt */
-#define GMAC_NCR_TXPF (0x1u << 11) /**< \brief (GMAC_NCR) Transmit Pause Frame */
-#define GMAC_NCR_TXZQPF (0x1u << 12) /**< \brief (GMAC_NCR) Transmit Zero Quantum Pause Frame */
-#define GMAC_NCR_RDS (0x1u << 14) /**< \brief (GMAC_NCR) Read Snapshot */
-#define GMAC_NCR_SRTSM (0x1u << 15) /**< \brief (GMAC_NCR) Store Receive Time Stamp to Memory */
-#define GMAC_NCR_ENPBPR (0x1u << 16) /**< \brief (GMAC_NCR) Enable PFC Priority-based Pause Reception */
-#define GMAC_NCR_TXPBPF (0x1u << 17) /**< \brief (GMAC_NCR) Transmit PFC Priority-based Pause Frame */
-#define GMAC_NCR_FNP (0x1u << 18) /**< \brief (GMAC_NCR) Flush Next Packet */
-/* -------- GMAC_NCFGR : (GMAC Offset: 0x004) Network Configuration Register -------- */
-#define GMAC_NCFGR_SPD (0x1u << 0) /**< \brief (GMAC_NCFGR) Speed */
-#define GMAC_NCFGR_FD (0x1u << 1) /**< \brief (GMAC_NCFGR) Full Duplex */
-#define GMAC_NCFGR_DNVLAN (0x1u << 2) /**< \brief (GMAC_NCFGR) Discard Non-VLAN FRAMES */
-#define GMAC_NCFGR_JFRAME (0x1u << 3) /**< \brief (GMAC_NCFGR) Jumbo Frame Size */
-#define GMAC_NCFGR_CAF (0x1u << 4) /**< \brief (GMAC_NCFGR) Copy All Frames */
-#define GMAC_NCFGR_NBC (0x1u << 5) /**< \brief (GMAC_NCFGR) No Broadcast */
-#define GMAC_NCFGR_MTIHEN (0x1u << 6) /**< \brief (GMAC_NCFGR) Multicast Hash Enable */
-#define GMAC_NCFGR_UNIHEN (0x1u << 7) /**< \brief (GMAC_NCFGR) Unicast Hash Enable */
-#define GMAC_NCFGR_MAXFS (0x1u << 8) /**< \brief (GMAC_NCFGR) 1536 Maximum Frame Size */
-#define GMAC_NCFGR_GBE (0x1u << 10) /**< \brief (GMAC_NCFGR) Gigabit Mode Enable */
-#define GMAC_NCFGR_PIS (0x1u << 11) /**< \brief (GMAC_NCFGR) Physical Interface Select */
-#define GMAC_NCFGR_RTY (0x1u << 12) /**< \brief (GMAC_NCFGR) Retry Test */
-#define GMAC_NCFGR_PEN (0x1u << 13) /**< \brief (GMAC_NCFGR) Pause Enable */
-#define GMAC_NCFGR_RXBUFO_Pos 14
-#define GMAC_NCFGR_RXBUFO_Msk (0x3u << GMAC_NCFGR_RXBUFO_Pos) /**< \brief (GMAC_NCFGR) Receive Buffer Offset */
-#define GMAC_NCFGR_RXBUFO(value) ((GMAC_NCFGR_RXBUFO_Msk & ((value) << GMAC_NCFGR_RXBUFO_Pos)))
-#define GMAC_NCFGR_LFERD (0x1u << 16) /**< \brief (GMAC_NCFGR) Length Field Error Frame Discard */
-#define GMAC_NCFGR_RFCS (0x1u << 17) /**< \brief (GMAC_NCFGR) Remove FCS */
-#define GMAC_NCFGR_CLK_Pos 18
-#define GMAC_NCFGR_CLK_Msk (0x7u << GMAC_NCFGR_CLK_Pos) /**< \brief (GMAC_NCFGR) MDC CLock Division */
-#define   GMAC_NCFGR_CLK_MCK_8 (0x0u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 8 (MCK up to 20 MHz) */
-#define   GMAC_NCFGR_CLK_MCK_16 (0x1u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 16 (MCK up to 40 MHz) */
-#define   GMAC_NCFGR_CLK_MCK_32 (0x2u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 32 (MCK up to 80 MHz) */
-#define   GMAC_NCFGR_CLK_MCK_48 (0x3u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 48 (MCK up to 120MHz) */
-#define   GMAC_NCFGR_CLK_MCK_64 (0x4u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 64 (MCK up to 160 MHz) */
-#define   GMAC_NCFGR_CLK_MCK_96 (0x5u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 96 (MCK up to 240 MHz) */
-#define   GMAC_NCFGR_CLK_MCK_128 (0x6u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 128 (MCK up to 320 MHz) */
-#define   GMAC_NCFGR_CLK_MCK_224 (0x7u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 224 (MCK up to 540 MHz) */
-#define GMAC_NCFGR_DBW_Pos 21
-#define GMAC_NCFGR_DBW_Msk (0x3u << GMAC_NCFGR_DBW_Pos) /**< \brief (GMAC_NCFGR) Data Bus Width */
-#define   GMAC_NCFGR_DBW_DBW32 (0x0u << 21) /**< \brief (GMAC_NCFGR) 32-bit data bus width */
-#define   GMAC_NCFGR_DBW_DBW64 (0x1u << 21) /**< \brief (GMAC_NCFGR) 64-bit data bus width */
-#define GMAC_NCFGR_DCPF (0x1u << 23) /**< \brief (GMAC_NCFGR) Disable Copy of Pause Frames */
-#define GMAC_NCFGR_RXCOEN (0x1u << 24) /**< \brief (GMAC_NCFGR) Receive Checksum Offload Enable */
-#define GMAC_NCFGR_EFRHD (0x1u << 25) /**< \brief (GMAC_NCFGR) Enable Frames Received in Half Duplex */
-#define GMAC_NCFGR_IRXFCS (0x1u << 26) /**< \brief (GMAC_NCFGR) Ignore RX FCS */
-#define GMAC_NCFGR_IPGSEN (0x1u << 28) /**< \brief (GMAC_NCFGR) IP Stretch Enable */
-#define GMAC_NCFGR_RXBP (0x1u << 29) /**< \brief (GMAC_NCFGR) Receive Bad Preamble */
-#define GMAC_NCFGR_IRXER (0x1u << 30) /**< \brief (GMAC_NCFGR) Ignore IPG rx_er */
-/* -------- GMAC_NSR : (GMAC Offset: 0x008) Network Status Register -------- */
-#define GMAC_NSR_MDIO (0x1u << 1) /**< \brief (GMAC_NSR) MDIO Input Status */
-#define GMAC_NSR_IDLE (0x1u << 2) /**< \brief (GMAC_NSR) PHY Management Logic Idle */
-/* -------- GMAC_UR : (GMAC Offset: 0x00C) User Register -------- */
-#define GMAC_UR_RGMII (0x1u << 0) /**< \brief (GMAC_UR) RGMII Mode */
-#define GMAC_UR_HDFC (0x1u << 6) /**< \brief (GMAC_UR) Half Duplex Flow Control */
-#define GMAC_UR_BPDG (0x1u << 7) /**< \brief (GMAC_UR) BPDG Bypass Deglitchers */
-/* -------- GMAC_DCFGR : (GMAC Offset: 0x010) DMA Configuration Register -------- */
-#define GMAC_DCFGR_FBLDO_Pos 0
-#define GMAC_DCFGR_FBLDO_Msk (0x1fu << GMAC_DCFGR_FBLDO_Pos) /**< \brief (GMAC_DCFGR) Fixed Burst Length for DMA Data Operations: */
-#define   GMAC_DCFGR_FBLDO_SINGLE (0x1u << 0) /**< \brief (GMAC_DCFGR) 00001: Always use SINGLE AHB bursts */
-#define   GMAC_DCFGR_FBLDO_INCR4 (0x4u << 0) /**< \brief (GMAC_DCFGR) 001xx: Attempt to use INCR4 AHB bursts (Default) */
-#define   GMAC_DCFGR_FBLDO_INCR8 (0x8u << 0) /**< \brief (GMAC_DCFGR) 01xxx: Attempt to use INCR8 AHB bursts */
-#define   GMAC_DCFGR_FBLDO_INCR16 (0x10u << 0) /**< \brief (GMAC_DCFGR) 1xxxx: Attempt to use INCR16 AHB bursts */
-#define GMAC_DCFGR_ESMA (0x1u << 6) /**< \brief (GMAC_DCFGR) Endian Swap Mode Enable for Management Descriptor Accesses */
-#define GMAC_DCFGR_ESPA (0x1u << 7) /**< \brief (GMAC_DCFGR) Endian Swap Mode Enable for Packet Data Accesses */
-#define GMAC_DCFGR_RXBMS_Pos 8
-#define GMAC_DCFGR_RXBMS_Msk (0x3u << GMAC_DCFGR_RXBMS_Pos) /**< \brief (GMAC_DCFGR) Receiver Packet Buffer Memory Size Select */
-#define   GMAC_DCFGR_RXBMS_EIGHTH (0x0u << 8) /**< \brief (GMAC_DCFGR) 1 Kbyte Memory Size */
-#define   GMAC_DCFGR_RXBMS_QUARTER (0x1u << 8) /**< \brief (GMAC_DCFGR) 2 Kbytes Memory Size */
-#define   GMAC_DCFGR_RXBMS_HALF (0x2u << 8) /**< \brief (GMAC_DCFGR) 4 Kbytes Memory Size */
-#define   GMAC_DCFGR_RXBMS_FULL (0x3u << 8) /**< \brief (GMAC_DCFGR) 8 Kbytes Memory Size */
-#define GMAC_DCFGR_TXPBMS (0x1u << 10) /**< \brief (GMAC_DCFGR) Transmitter Packet Buffer Memory Size Select */
-#define GMAC_DCFGR_TXCOEN (0x1u << 11) /**< \brief (GMAC_DCFGR) Transmitter Checksum Generation Offload Enable */
-#define GMAC_DCFGR_DRBS_Pos 16
-#define GMAC_DCFGR_DRBS_Msk (0xffu << GMAC_DCFGR_DRBS_Pos) /**< \brief (GMAC_DCFGR) DMA Receive Buffer Size */
-#define GMAC_DCFGR_DRBS(value) ((GMAC_DCFGR_DRBS_Msk & ((value) << GMAC_DCFGR_DRBS_Pos)))
-#define GMAC_DCFGR_DDRP (0x1u << 24) /**< \brief (GMAC_DCFGR) DMA Discard Receive Packets */
-/* -------- GMAC_TSR : (GMAC Offset: 0x014) Transmit Status Register -------- */
-#define GMAC_TSR_UBR (0x1u << 0) /**< \brief (GMAC_TSR) Used Bit Read */
-#define GMAC_TSR_COL (0x1u << 1) /**< \brief (GMAC_TSR) Collision Occurred */
-#define GMAC_TSR_RLE (0x1u << 2) /**< \brief (GMAC_TSR) Retry Limit Exceeded */
-#define GMAC_TSR_TXGO (0x1u << 3) /**< \brief (GMAC_TSR) Transmit Go */
-#define GMAC_TSR_TFC (0x1u << 4) /**< \brief (GMAC_TSR) Transmit Frame Corruption due to AHB error */
-#define GMAC_TSR_TXCOMP (0x1u << 5) /**< \brief (GMAC_TSR) Transmit Complete */
-#define GMAC_TSR_UND (0x1u << 6) /**< \brief (GMAC_TSR) Transmit Under Run */
-#define GMAC_TSR_LCO (0x1u << 7) /**< \brief (GMAC_TSR) Late Collision Occurred */
-#define GMAC_TSR_HRESP (0x1u << 8) /**< \brief (GMAC_TSR) HRESP Not OK */
-/* -------- GMAC_RBQB : (GMAC Offset: 0x018) Receive Buffer Queue Base Address -------- */
-#define GMAC_RBQB_ADDR_Pos 2
-#define GMAC_RBQB_ADDR_Msk (0x3fffffffu << GMAC_RBQB_ADDR_Pos) /**< \brief (GMAC_RBQB) Receive buffer queue base address */
-#define GMAC_RBQB_ADDR(value) ((GMAC_RBQB_ADDR_Msk & ((value) << GMAC_RBQB_ADDR_Pos)))
-/* -------- GMAC_TBQB : (GMAC Offset: 0x01C) Transmit Buffer Queue Base Address -------- */
-#define GMAC_TBQB_ADDR_Pos 2
-#define GMAC_TBQB_ADDR_Msk (0x3fffffffu << GMAC_TBQB_ADDR_Pos) /**< \brief (GMAC_TBQB) Transmit Buffer Queue Base Address */
-#define GMAC_TBQB_ADDR(value) ((GMAC_TBQB_ADDR_Msk & ((value) << GMAC_TBQB_ADDR_Pos)))
-/* -------- GMAC_RSR : (GMAC Offset: 0x020) Receive Status Register -------- */
-#define GMAC_RSR_BNA (0x1u << 0) /**< \brief (GMAC_RSR) Buffer Not Available */
-#define GMAC_RSR_REC (0x1u << 1) /**< \brief (GMAC_RSR) Frame Received */
-#define GMAC_RSR_RXOVR (0x1u << 2) /**< \brief (GMAC_RSR) Receive Overrun */
-#define GMAC_RSR_HNO (0x1u << 3) /**< \brief (GMAC_RSR) HRESP Not OK */
-/* -------- GMAC_ISR : (GMAC Offset: 0x024) Interrupt Status Register -------- */
-#define GMAC_ISR_MFS (0x1u << 0) /**< \brief (GMAC_ISR) Management Frame Sent */
-#define GMAC_ISR_RCOMP (0x1u << 1) /**< \brief (GMAC_ISR) Receive Complete */
-#define GMAC_ISR_RXUBR (0x1u << 2) /**< \brief (GMAC_ISR) RX Used Bit Read */
-#define GMAC_ISR_TXUBR (0x1u << 3) /**< \brief (GMAC_ISR) TX Used Bit Read */
-#define GMAC_ISR_TUR (0x1u << 4) /**< \brief (GMAC_ISR) Transmit Under Run */
-#define GMAC_ISR_RLEX (0x1u << 5) /**< \brief (GMAC_ISR) Retry Limit Exceeded or Late Collision */
-#define GMAC_ISR_TFC (0x1u << 6) /**< \brief (GMAC_ISR) Transmit Frame Corruption due to AHB error */
-#define GMAC_ISR_TCOMP (0x1u << 7) /**< \brief (GMAC_ISR) Transmit Complete */
-#define GMAC_ISR_ROVR (0x1u << 10) /**< \brief (GMAC_ISR) Receive Overrun */
-#define GMAC_ISR_HRESP (0x1u << 11) /**< \brief (GMAC_ISR) HRESP Not OK */
-#define GMAC_ISR_PFNZ (0x1u << 12) /**< \brief (GMAC_ISR) Pause Frame with Non-zero Pause Quantum Received */
-#define GMAC_ISR_PTZ (0x1u << 13) /**< \brief (GMAC_ISR) Pause Time Zero */
-#define GMAC_ISR_PFTR (0x1u << 14) /**< \brief (GMAC_ISR) Pause Frame Transmitted */
-#define GMAC_ISR_EXINT (0x1u << 15) /**< \brief (GMAC_ISR) External Interrupt */
-#define GMAC_ISR_DRQFR (0x1u << 18) /**< \brief (GMAC_ISR) PTP Delay Request Frame Received */
-#define GMAC_ISR_SFR (0x1u << 19) /**< \brief (GMAC_ISR) PTP Sync Frame Received */
-#define GMAC_ISR_DRQFT (0x1u << 20) /**< \brief (GMAC_ISR) PTP Delay Request Frame Transmitted */
-#define GMAC_ISR_SFT (0x1u << 21) /**< \brief (GMAC_ISR) PTP Sync Frame Transmitted */
-#define GMAC_ISR_PDRQFR (0x1u << 22) /**< \brief (GMAC_ISR) PDelay Request Frame Received */
-#define GMAC_ISR_PDRSFR (0x1u << 23) /**< \brief (GMAC_ISR) PDelay Response Frame Received */
-#define GMAC_ISR_PDRQFT (0x1u << 24) /**< \brief (GMAC_ISR) PDelay Request Frame Transmitted */
-#define GMAC_ISR_PDRSFT (0x1u << 25) /**< \brief (GMAC_ISR) PDelay Response Frame Transmitted */
-#define GMAC_ISR_SRI (0x1u << 26) /**< \brief (GMAC_ISR) TSU Seconds Register Increment */
-#define GMAC_ISR_WOL (0x1u << 28) /**< \brief (GMAC_ISR) Wake On LAN */
-/* -------- GMAC_IER : (GMAC Offset: 0x028) Interrupt Enable Register -------- */
-#define GMAC_IER_MFS (0x1u << 0) /**< \brief (GMAC_IER) Management Frame Sent */
-#define GMAC_IER_RCOMP (0x1u << 1) /**< \brief (GMAC_IER) Receive Complete */
-#define GMAC_IER_RXUBR (0x1u << 2) /**< \brief (GMAC_IER) RX Used Bit Read */
-#define GMAC_IER_TXUBR (0x1u << 3) /**< \brief (GMAC_IER) TX Used Bit Read */
-#define GMAC_IER_TUR (0x1u << 4) /**< \brief (GMAC_IER) Transmit Under Run */
-#define GMAC_IER_RLEX (0x1u << 5) /**< \brief (GMAC_IER) Retry Limit Exceeded or Late Collision */
-#define GMAC_IER_TFC (0x1u << 6) /**< \brief (GMAC_IER) Transmit Frame Corruption due to AHB error */
-#define GMAC_IER_TCOMP (0x1u << 7) /**< \brief (GMAC_IER) Transmit Complete */
-#define GMAC_IER_ROVR (0x1u << 10) /**< \brief (GMAC_IER) Receive Overrun */
-#define GMAC_IER_HRESP (0x1u << 11) /**< \brief (GMAC_IER) HRESP Not OK */
-#define GMAC_IER_PFNZ (0x1u << 12) /**< \brief (GMAC_IER) Pause Frame with Non-zero Pause Quantum Received */
-#define GMAC_IER_PTZ (0x1u << 13) /**< \brief (GMAC_IER) Pause Time Zero */
-#define GMAC_IER_PFTR (0x1u << 14) /**< \brief (GMAC_IER) Pause Frame Transmitted */
-#define GMAC_IER_EXINT (0x1u << 15) /**< \brief (GMAC_IER) External Interrupt */
-#define GMAC_IER_DRQFR (0x1u << 18) /**< \brief (GMAC_IER) PTP Delay Request Frame Received */
-#define GMAC_IER_SFR (0x1u << 19) /**< \brief (GMAC_IER) PTP Sync Frame Received */
-#define GMAC_IER_DRQFT (0x1u << 20) /**< \brief (GMAC_IER) PTP Delay Request Frame Transmitted */
-#define GMAC_IER_SFT (0x1u << 21) /**< \brief (GMAC_IER) PTP Sync Frame Transmitted */
-#define GMAC_IER_PDRQFR (0x1u << 22) /**< \brief (GMAC_IER) PDelay Request Frame Received */
-#define GMAC_IER_PDRSFR (0x1u << 23) /**< \brief (GMAC_IER) PDelay Response Frame Received */
-#define GMAC_IER_PDRQFT (0x1u << 24) /**< \brief (GMAC_IER) PDelay Request Frame Transmitted */
-#define GMAC_IER_PDRSFT (0x1u << 25) /**< \brief (GMAC_IER) PDelay Response Frame Transmitted */
-#define GMAC_IER_SRI (0x1u << 26) /**< \brief (GMAC_IER) TSU Seconds Register Increment */
-#define GMAC_IER_WOL (0x1u << 28) /**< \brief (GMAC_IER) Wake On LAN */
-/* -------- GMAC_IDR : (GMAC Offset: 0x02C) Interrupt Disable Register -------- */
-#define GMAC_IDR_MFS (0x1u << 0) /**< \brief (GMAC_IDR) Management Frame Sent */
-#define GMAC_IDR_RCOMP (0x1u << 1) /**< \brief (GMAC_IDR) Receive Complete */
-#define GMAC_IDR_RXUBR (0x1u << 2) /**< \brief (GMAC_IDR) RX Used Bit Read */
-#define GMAC_IDR_TXUBR (0x1u << 3) /**< \brief (GMAC_IDR) TX Used Bit Read */
-#define GMAC_IDR_TUR (0x1u << 4) /**< \brief (GMAC_IDR) Transmit Under Run */
-#define GMAC_IDR_RLEX (0x1u << 5) /**< \brief (GMAC_IDR) Retry Limit Exceeded or Late Collision */
-#define GMAC_IDR_TFC (0x1u << 6) /**< \brief (GMAC_IDR) Transmit Frame Corruption due to AHB error */
-#define GMAC_IDR_TCOMP (0x1u << 7) /**< \brief (GMAC_IDR) Transmit Complete */
-#define GMAC_IDR_ROVR (0x1u << 10) /**< \brief (GMAC_IDR) Receive Overrun */
-#define GMAC_IDR_HRESP (0x1u << 11) /**< \brief (GMAC_IDR) HRESP Not OK */
-#define GMAC_IDR_PFNZ (0x1u << 12) /**< \brief (GMAC_IDR) Pause Frame with Non-zero Pause Quantum Received */
-#define GMAC_IDR_PTZ (0x1u << 13) /**< \brief (GMAC_IDR) Pause Time Zero */
-#define GMAC_IDR_PFTR (0x1u << 14) /**< \brief (GMAC_IDR) Pause Frame Transmitted */
-#define GMAC_IDR_EXINT (0x1u << 15) /**< \brief (GMAC_IDR) External Interrupt */
-#define GMAC_IDR_DRQFR (0x1u << 18) /**< \brief (GMAC_IDR) PTP Delay Request Frame Received */
-#define GMAC_IDR_SFR (0x1u << 19) /**< \brief (GMAC_IDR) PTP Sync Frame Received */
-#define GMAC_IDR_DRQFT (0x1u << 20) /**< \brief (GMAC_IDR) PTP Delay Request Frame Transmitted */
-#define GMAC_IDR_SFT (0x1u << 21) /**< \brief (GMAC_IDR) PTP Sync Frame Transmitted */
-#define GMAC_IDR_PDRQFR (0x1u << 22) /**< \brief (GMAC_IDR) PDelay Request Frame Received */
-#define GMAC_IDR_PDRSFR (0x1u << 23) /**< \brief (GMAC_IDR) PDelay Response Frame Received */
-#define GMAC_IDR_PDRQFT (0x1u << 24) /**< \brief (GMAC_IDR) PDelay Request Frame Transmitted */
-#define GMAC_IDR_PDRSFT (0x1u << 25) /**< \brief (GMAC_IDR) PDelay Response Frame Transmitted */
-#define GMAC_IDR_SRI (0x1u << 26) /**< \brief (GMAC_IDR) TSU Seconds Register Increment */
-#define GMAC_IDR_WOL (0x1u << 28) /**< \brief (GMAC_IDR) Wake On LAN */
-/* -------- GMAC_IMR : (GMAC Offset: 0x030) Interrupt Mask Register -------- */
-#define GMAC_IMR_MFS (0x1u << 0) /**< \brief (GMAC_IMR) Management Frame Sent */
-#define GMAC_IMR_RCOMP (0x1u << 1) /**< \brief (GMAC_IMR) Receive Complete */
-#define GMAC_IMR_RXUBR (0x1u << 2) /**< \brief (GMAC_IMR) RX Used Bit Read */
-#define GMAC_IMR_TXUBR (0x1u << 3) /**< \brief (GMAC_IMR) TX Used Bit Read */
-#define GMAC_IMR_TUR (0x1u << 4) /**< \brief (GMAC_IMR) Transmit Under Run */
-#define GMAC_IMR_RLEX (0x1u << 5) /**< \brief (GMAC_IMR) Retry Limit Exceeded or Late Collision */
-#define GMAC_IMR_TFC (0x1u << 6) /**< \brief (GMAC_IMR) Transmit Frame Corruption due to AHB error */
-#define GMAC_IMR_TCOMP (0x1u << 7) /**< \brief (GMAC_IMR) Transmit Complete */
-#define GMAC_IMR_ROVR (0x1u << 10) /**< \brief (GMAC_IMR) Receive Overrun */
-#define GMAC_IMR_HRESP (0x1u << 11) /**< \brief (GMAC_IMR) HRESP Not OK */
-#define GMAC_IMR_PFNZ (0x1u << 12) /**< \brief (GMAC_IMR) Pause Frame with Non-zero Pause Quantum Received */
-#define GMAC_IMR_PTZ (0x1u << 13) /**< \brief (GMAC_IMR) Pause Time Zero */
-#define GMAC_IMR_PFTR (0x1u << 14) /**< \brief (GMAC_IMR) Pause Frame Transmitted */
-#define GMAC_IMR_EXINT (0x1u << 15) /**< \brief (GMAC_IMR) External Interrupt */
-#define GMAC_IMR_DRQFR (0x1u << 18) /**< \brief (GMAC_IMR) PTP Delay Request Frame Received */
-#define GMAC_IMR_SFR (0x1u << 19) /**< \brief (GMAC_IMR) PTP Sync Frame Received */
-#define GMAC_IMR_DRQFT (0x1u << 20) /**< \brief (GMAC_IMR) PTP Delay Request Frame Transmitted */
-#define GMAC_IMR_SFT (0x1u << 21) /**< \brief (GMAC_IMR) PTP Sync Frame Transmitted */
-#define GMAC_IMR_PDRQFR (0x1u << 22) /**< \brief (GMAC_IMR) PDelay Request Frame Received */
-#define GMAC_IMR_PDRSFR (0x1u << 23) /**< \brief (GMAC_IMR) PDelay Response Frame Received */
-#define GMAC_IMR_PDRQFT (0x1u << 24) /**< \brief (GMAC_IMR) PDelay Request Frame Transmitted */
-#define GMAC_IMR_PDRSFT (0x1u << 25) /**< \brief (GMAC_IMR) PDelay Response Frame Transmitted */
-/* -------- GMAC_MAN : (GMAC Offset: 0x034) PHY Maintenance Register -------- */
-#define GMAC_MAN_DATA_Pos 0
-#define GMAC_MAN_DATA_Msk (0xffffu << GMAC_MAN_DATA_Pos) /**< \brief (GMAC_MAN) PHY Data */
-#define GMAC_MAN_DATA(value) ((GMAC_MAN_DATA_Msk & ((value) << GMAC_MAN_DATA_Pos)))
-#define GMAC_MAN_WTN_Pos 16
-#define GMAC_MAN_WTN_Msk (0x3u << GMAC_MAN_WTN_Pos) /**< \brief (GMAC_MAN) Write Ten */
-#define GMAC_MAN_WTN(value) ((GMAC_MAN_WTN_Msk & ((value) << GMAC_MAN_WTN_Pos)))
-#define GMAC_MAN_REGA_Pos 18
-#define GMAC_MAN_REGA_Msk (0x1fu << GMAC_MAN_REGA_Pos) /**< \brief (GMAC_MAN) Register Address */
-#define GMAC_MAN_REGA(value) ((GMAC_MAN_REGA_Msk & ((value) << GMAC_MAN_REGA_Pos)))
-#define GMAC_MAN_PHYA_Pos 23
-#define GMAC_MAN_PHYA_Msk (0x1fu << GMAC_MAN_PHYA_Pos) /**< \brief (GMAC_MAN) PHY Address */
-#define GMAC_MAN_PHYA(value) ((GMAC_MAN_PHYA_Msk & ((value) << GMAC_MAN_PHYA_Pos)))
-#define GMAC_MAN_OP_Pos 28
-#define GMAC_MAN_OP_Msk (0x3u << GMAC_MAN_OP_Pos) /**< \brief (GMAC_MAN) Operation */
-#define GMAC_MAN_OP(value) ((GMAC_MAN_OP_Msk & ((value) << GMAC_MAN_OP_Pos)))
-#define GMAC_MAN_CLTTO (0x1u << 30) /**< \brief (GMAC_MAN) Clause 22 Operation */
-#define GMAC_MAN_WZO (0x1u << 31) /**< \brief (GMAC_MAN) Write ZERO */
-/* -------- GMAC_RPQ : (GMAC Offset: 0x038) Received Pause Quantum Register -------- */
-#define GMAC_RPQ_RPQ_Pos 0
-#define GMAC_RPQ_RPQ_Msk (0xffffu << GMAC_RPQ_RPQ_Pos) /**< \brief (GMAC_RPQ) Received Pause Quantum */
-/* -------- GMAC_TPQ : (GMAC Offset: 0x03C) Transmit Pause Quantum Register -------- */
-#define GMAC_TPQ_TPQ_Pos 0
-#define GMAC_TPQ_TPQ_Msk (0xffffu << GMAC_TPQ_TPQ_Pos) /**< \brief (GMAC_TPQ) Transmit Pause Quantum */
-#define GMAC_TPQ_TPQ(value) ((GMAC_TPQ_TPQ_Msk & ((value) << GMAC_TPQ_TPQ_Pos)))
-/* -------- GMAC_TPSF : (GMAC Offset: 0x040) TX Partial Store and Forward Register -------- */
-#define GMAC_TPSF_TPB1ADR_Pos 0
-#define GMAC_TPSF_TPB1ADR_Msk (0xfffu << GMAC_TPSF_TPB1ADR_Pos) /**< \brief (GMAC_TPSF) tx_pbuf_addr-1:0 */
-#define GMAC_TPSF_TPB1ADR(value) ((GMAC_TPSF_TPB1ADR_Msk & ((value) << GMAC_TPSF_TPB1ADR_Pos)))
-#define GMAC_TPSF_ENTXP (0x1u << 31) /**< \brief (GMAC_TPSF) Enable TX Partial Store and Forward Operation */
-/* -------- GMAC_RPSF : (GMAC Offset: 0x044) RX Partial Store and Forward Register -------- */
-#define GMAC_RPSF_RPB1ADR_Pos 0
-#define GMAC_RPSF_RPB1ADR_Msk (0xfffu << GMAC_RPSF_RPB1ADR_Pos) /**< \brief (GMAC_RPSF) rx_pbuf_addr-1:0 */
-#define GMAC_RPSF_RPB1ADR(value) ((GMAC_RPSF_RPB1ADR_Msk & ((value) << GMAC_RPSF_RPB1ADR_Pos)))
-#define GMAC_RPSF_ENRXP (0x1u << 31) /**< \brief (GMAC_RPSF) Enable RX Partial Store and Forward Operation */
-/* -------- GMAC_HRB : (GMAC Offset: 0x080) Hash Register Bottom [31:0] -------- */
-#define GMAC_HRB_ADDR_Pos 0
-#define GMAC_HRB_ADDR_Msk (0xffffffffu << GMAC_HRB_ADDR_Pos) /**< \brief (GMAC_HRB) Hash Address */
-#define GMAC_HRB_ADDR(value) ((GMAC_HRB_ADDR_Msk & ((value) << GMAC_HRB_ADDR_Pos)))
-/* -------- GMAC_HRT : (GMAC Offset: 0x084) Hash Register Top [63:32] -------- */
-#define GMAC_HRT_ADDR_Pos 0
-#define GMAC_HRT_ADDR_Msk (0xffffffffu << GMAC_HRT_ADDR_Pos) /**< \brief (GMAC_HRT) Hash Address */
-#define GMAC_HRT_ADDR(value) ((GMAC_HRT_ADDR_Msk & ((value) << GMAC_HRT_ADDR_Pos)))
-/* -------- GMAC_SAB1 : (GMAC Offset: 0x088) Specific Address 1 Bottom [31:0] Register -------- */
-#define GMAC_SAB1_ADDR_Pos 0
-#define GMAC_SAB1_ADDR_Msk (0xffffffffu << GMAC_SAB1_ADDR_Pos) /**< \brief (GMAC_SAB1) Specific Address 1 */
-#define GMAC_SAB1_ADDR(value) ((GMAC_SAB1_ADDR_Msk & ((value) << GMAC_SAB1_ADDR_Pos)))
-/* -------- GMAC_SAT1 : (GMAC Offset: 0x08C) Specific Address 1 Top [47:32] Register -------- */
-#define GMAC_SAT1_ADDR_Pos 0
-#define GMAC_SAT1_ADDR_Msk (0xffffu << GMAC_SAT1_ADDR_Pos) /**< \brief (GMAC_SAT1) Specific Address 1 */
-#define GMAC_SAT1_ADDR(value) ((GMAC_SAT1_ADDR_Msk & ((value) << GMAC_SAT1_ADDR_Pos)))
-/* -------- GMAC_SAB2 : (GMAC Offset: 0x090) Specific Address 2 Bottom [31:0] Register -------- */
-#define GMAC_SAB2_ADDR_Pos 0
-#define GMAC_SAB2_ADDR_Msk (0xffffffffu << GMAC_SAB2_ADDR_Pos) /**< \brief (GMAC_SAB2) Specific Address 2 */
-#define GMAC_SAB2_ADDR(value) ((GMAC_SAB2_ADDR_Msk & ((value) << GMAC_SAB2_ADDR_Pos)))
-/* -------- GMAC_SAT2 : (GMAC Offset: 0x094) Specific Address 2 Top [47:32] Register -------- */
-#define GMAC_SAT2_ADDR_Pos 0
-#define GMAC_SAT2_ADDR_Msk (0xffffu << GMAC_SAT2_ADDR_Pos) /**< \brief (GMAC_SAT2) Specific Address 2 */
-#define GMAC_SAT2_ADDR(value) ((GMAC_SAT2_ADDR_Msk & ((value) << GMAC_SAT2_ADDR_Pos)))
-/* -------- GMAC_SAB3 : (GMAC Offset: 0x098) Specific Address 3 Bottom [31:0] Register -------- */
-#define GMAC_SAB3_ADDR_Pos 0
-#define GMAC_SAB3_ADDR_Msk (0xffffffffu << GMAC_SAB3_ADDR_Pos) /**< \brief (GMAC_SAB3) Specific Address 3 */
-#define GMAC_SAB3_ADDR(value) ((GMAC_SAB3_ADDR_Msk & ((value) << GMAC_SAB3_ADDR_Pos)))
-/* -------- GMAC_SAT3 : (GMAC Offset: 0x09C) Specific Address 3 Top [47:32] Register -------- */
-#define GMAC_SAT3_ADDR_Pos 0
-#define GMAC_SAT3_ADDR_Msk (0xffffu << GMAC_SAT3_ADDR_Pos) /**< \brief (GMAC_SAT3) Specific Address 3 */
-#define GMAC_SAT3_ADDR(value) ((GMAC_SAT3_ADDR_Msk & ((value) << GMAC_SAT3_ADDR_Pos)))
-/* -------- GMAC_SAB4 : (GMAC Offset: 0x0A0) Specific Address 4 Bottom [31:0] Register -------- */
-#define GMAC_SAB4_ADDR_Pos 0
-#define GMAC_SAB4_ADDR_Msk (0xffffffffu << GMAC_SAB4_ADDR_Pos) /**< \brief (GMAC_SAB4) Specific Address 4 */
-#define GMAC_SAB4_ADDR(value) ((GMAC_SAB4_ADDR_Msk & ((value) << GMAC_SAB4_ADDR_Pos)))
-/* -------- GMAC_SAT4 : (GMAC Offset: 0x0A4) Specific Address 4 Top [47:32] Register -------- */
-#define GMAC_SAT4_ADDR_Pos 0
-#define GMAC_SAT4_ADDR_Msk (0xffffu << GMAC_SAT4_ADDR_Pos) /**< \brief (GMAC_SAT4) Specific Address 4 */
-#define GMAC_SAT4_ADDR(value) ((GMAC_SAT4_ADDR_Msk & ((value) << GMAC_SAT4_ADDR_Pos)))
-/* -------- GMAC_TIDM[4] : (GMAC Offset: 0x0A8) Type ID Match 1 Register -------- */
-#define GMAC_TIDM_TID_Pos 0
-#define GMAC_TIDM_TID_Msk (0xffffu << GMAC_TIDM_TID_Pos) /**< \brief (GMAC_TIDM[4]) Type ID Match 1 */
-#define GMAC_TIDM_TID(value) ((GMAC_TIDM_TID_Msk & ((value) << GMAC_TIDM_TID_Pos)))
-/* -------- GMAC_WOL : (GMAC Offset: 0x0B8) Wake on LAN Register -------- */
-#define GMAC_WOL_IP_Pos 0
-#define GMAC_WOL_IP_Msk (0xffffu << GMAC_WOL_IP_Pos) /**< \brief (GMAC_WOL) ARP Request IP Address */
-#define GMAC_WOL_IP(value) ((GMAC_WOL_IP_Msk & ((value) << GMAC_WOL_IP_Pos)))
-#define GMAC_WOL_MAG (0x1u << 16) /**< \brief (GMAC_WOL) Magic Packet Event Enable */
-#define GMAC_WOL_ARP (0x1u << 17) /**< \brief (GMAC_WOL) ARP Request IP Address */
-#define GMAC_WOL_SA1 (0x1u << 18) /**< \brief (GMAC_WOL) Specific Address Register 1 Event Enable */
-#define GMAC_WOL_MTI (0x1u << 19) /**< \brief (GMAC_WOL) Multicast Hash Event Enable */
-/* -------- GMAC_IPGS : (GMAC Offset: 0x0BC) IPG Stretch Register -------- */
-#define GMAC_IPGS_FL_Pos 0
-#define GMAC_IPGS_FL_Msk (0xffffu << GMAC_IPGS_FL_Pos) /**< \brief (GMAC_IPGS) Frame Length */
-#define GMAC_IPGS_FL(value) ((GMAC_IPGS_FL_Msk & ((value) << GMAC_IPGS_FL_Pos)))
-/* -------- GMAC_SVLAN : (GMAC Offset: 0x0C0) Stacked VLAN Register -------- */
-#define GMAC_SVLAN_VLAN_TYPE_Pos 0
-#define GMAC_SVLAN_VLAN_TYPE_Msk (0xffffu << GMAC_SVLAN_VLAN_TYPE_Pos) /**< \brief (GMAC_SVLAN) User Defined VLAN_TYPE Field */
-#define GMAC_SVLAN_VLAN_TYPE(value) ((GMAC_SVLAN_VLAN_TYPE_Msk & ((value) << GMAC_SVLAN_VLAN_TYPE_Pos)))
-#define GMAC_SVLAN_ESVLAN (0x1u << 31) /**< \brief (GMAC_SVLAN) Enable Stacked VLAN Processing Mode */
-/* -------- GMAC_TPFCP : (GMAC Offset: 0x0C4) Transmit PFC Pause Register -------- */
-#define GMAC_TPFCP_PEV_Pos 0
-#define GMAC_TPFCP_PEV_Msk (0xffu << GMAC_TPFCP_PEV_Pos) /**< \brief (GMAC_TPFCP) Priority Enable Vector */
-#define GMAC_TPFCP_PEV(value) ((GMAC_TPFCP_PEV_Msk & ((value) << GMAC_TPFCP_PEV_Pos)))
-#define GMAC_TPFCP_PQ_Pos 8
-#define GMAC_TPFCP_PQ_Msk (0xffu << GMAC_TPFCP_PQ_Pos) /**< \brief (GMAC_TPFCP) Pause Quantum */
-#define GMAC_TPFCP_PQ(value) ((GMAC_TPFCP_PQ_Msk & ((value) << GMAC_TPFCP_PQ_Pos)))
-/* -------- GMAC_SAMB1 : (GMAC Offset: 0x0C8) Specific Address 1 Mask Bottom [31:0] Register -------- */
-#define GMAC_SAMB1_ADDR_Pos 0
-#define GMAC_SAMB1_ADDR_Msk (0xffffffffu << GMAC_SAMB1_ADDR_Pos) /**< \brief (GMAC_SAMB1) Specific Address 1 Mask */
-#define GMAC_SAMB1_ADDR(value) ((GMAC_SAMB1_ADDR_Msk & ((value) << GMAC_SAMB1_ADDR_Pos)))
-/* -------- GMAC_SAMT1 : (GMAC Offset: 0x0CC) Specific Address 1 Mask Top [47:32] Register -------- */
-#define GMAC_SAMT1_ADDR_Pos 0
-#define GMAC_SAMT1_ADDR_Msk (0xffffu << GMAC_SAMT1_ADDR_Pos) /**< \brief (GMAC_SAMT1) Specific Address 1 Mask */
-#define GMAC_SAMT1_ADDR(value) ((GMAC_SAMT1_ADDR_Msk & ((value) << GMAC_SAMT1_ADDR_Pos)))
-/* -------- GMAC_OTLO : (GMAC Offset: 0x100) Octets Transmitted [31:0] Register -------- */
-#define GMAC_OTLO_TXO_Pos 0
-#define GMAC_OTLO_TXO_Msk (0xffffffffu << GMAC_OTLO_TXO_Pos) /**< \brief (GMAC_OTLO) Transmitted Octets */
-/* -------- GMAC_OTHI : (GMAC Offset: 0x104) Octets Transmitted [47:32] Register -------- */
-#define GMAC_OTHI_TXO_Pos 0
-#define GMAC_OTHI_TXO_Msk (0xffffu << GMAC_OTHI_TXO_Pos) /**< \brief (GMAC_OTHI) Transmitted Octets */
-/* -------- GMAC_FT : (GMAC Offset: 0x108) Frames Transmitted Register -------- */
-#define GMAC_FT_FTX_Pos 0
-#define GMAC_FT_FTX_Msk (0xffffffffu << GMAC_FT_FTX_Pos) /**< \brief (GMAC_FT) Frames Transmitted without Error */
-/* -------- GMAC_BCFT : (GMAC Offset: 0x10C) Broadcast Frames Transmitted Register -------- */
-#define GMAC_BCFT_BFTX_Pos 0
-#define GMAC_BCFT_BFTX_Msk (0xffffffffu << GMAC_BCFT_BFTX_Pos) /**< \brief (GMAC_BCFT) Broadcast Frames Transmitted without Error */
-/* -------- GMAC_MFT : (GMAC Offset: 0x110) Multicast Frames Transmitted Register -------- */
-#define GMAC_MFT_MFTX_Pos 0
-#define GMAC_MFT_MFTX_Msk (0xffffffffu << GMAC_MFT_MFTX_Pos) /**< \brief (GMAC_MFT) Multicast Frames Transmitted without Error */
-/* -------- GMAC_PFT : (GMAC Offset: 0x114) Pause Frames Transmitted Register -------- */
-#define GMAC_PFT_PFTX_Pos 0
-#define GMAC_PFT_PFTX_Msk (0xffffu << GMAC_PFT_PFTX_Pos) /**< \brief (GMAC_PFT) Pause Frames Transmitted Register */
-/* -------- GMAC_BFT64 : (GMAC Offset: 0x118) 64 Byte Frames Transmitted Register -------- */
-#define GMAC_BFT64_NFTX_Pos 0
-#define GMAC_BFT64_NFTX_Msk (0xffffffffu << GMAC_BFT64_NFTX_Pos) /**< \brief (GMAC_BFT64) 64 Byte Frames Transmitted without Error */
-/* -------- GMAC_TBFT127 : (GMAC Offset: 0x11C) 65 to 127 Byte Frames Transmitted Register -------- */
-#define GMAC_TBFT127_NFTX_Pos 0
-#define GMAC_TBFT127_NFTX_Msk (0xffffffffu << GMAC_TBFT127_NFTX_Pos) /**< \brief (GMAC_TBFT127) 65 to 127 Byte Frames Transmitted without Error */
-/* -------- GMAC_TBFT255 : (GMAC Offset: 0x120) 128 to 255 Byte Frames Transmitted Register -------- */
-#define GMAC_TBFT255_NFTX_Pos 0
-#define GMAC_TBFT255_NFTX_Msk (0xffffffffu << GMAC_TBFT255_NFTX_Pos) /**< \brief (GMAC_TBFT255) 128 to 255 Byte Frames Transmitted without Error */
-/* -------- GMAC_TBFT511 : (GMAC Offset: 0x124) 256 to 511 Byte Frames Transmitted Register -------- */
-#define GMAC_TBFT511_NFTX_Pos 0
-#define GMAC_TBFT511_NFTX_Msk (0xffffffffu << GMAC_TBFT511_NFTX_Pos) /**< \brief (GMAC_TBFT511) 256 to 511 Byte Frames Transmitted without Error */
-/* -------- GMAC_TBFT1023 : (GMAC Offset: 0x128) 512 to 1023 Byte Frames Transmitted Register -------- */
-#define GMAC_TBFT1023_NFTX_Pos 0
-#define GMAC_TBFT1023_NFTX_Msk (0xffffffffu << GMAC_TBFT1023_NFTX_Pos) /**< \brief (GMAC_TBFT1023) 512 to 1023 Byte Frames Transmitted without Error */
-/* -------- GMAC_TBFT1518 : (GMAC Offset: 0x12C) 1024 to 1518 Byte Frames Transmitted Register -------- */
-#define GMAC_TBFT1518_NFTX_Pos 0
-#define GMAC_TBFT1518_NFTX_Msk (0xffffffffu << GMAC_TBFT1518_NFTX_Pos) /**< \brief (GMAC_TBFT1518) 1024 to 1518 Byte Frames Transmitted without Error */
-/* -------- GMAC_GTBFT1518 : (GMAC Offset: 0x130) Greater Than 1518 Byte Frames Transmitted Register -------- */
-#define GMAC_GTBFT1518_NFTX_Pos 0
-#define GMAC_GTBFT1518_NFTX_Msk (0xffffffffu << GMAC_GTBFT1518_NFTX_Pos) /**< \brief (GMAC_GTBFT1518) Greater than 1518 Byte Frames Transmitted without Error */
-/* -------- GMAC_TUR : (GMAC Offset: 0x134) Transmit Under Runs Register -------- */
-#define GMAC_TUR_TXUNR_Pos 0
-#define GMAC_TUR_TXUNR_Msk (0x3ffu << GMAC_TUR_TXUNR_Pos) /**< \brief (GMAC_TUR) Transmit Under Runs */
-/* -------- GMAC_SCF : (GMAC Offset: 0x138) Single Collision Frames Register -------- */
-#define GMAC_SCF_SCOL_Pos 0
-#define GMAC_SCF_SCOL_Msk (0x3ffffu << GMAC_SCF_SCOL_Pos) /**< \brief (GMAC_SCF) Single Collision */
-/* -------- GMAC_MCF : (GMAC Offset: 0x13C) Multiple Collision Frames Register -------- */
-#define GMAC_MCF_MCOL_Pos 0
-#define GMAC_MCF_MCOL_Msk (0x3ffffu << GMAC_MCF_MCOL_Pos) /**< \brief (GMAC_MCF) Multiple Collision */
-/* -------- GMAC_EC : (GMAC Offset: 0x140) Excessive Collisions Register -------- */
-#define GMAC_EC_XCOL_Pos 0
-#define GMAC_EC_XCOL_Msk (0x3ffu << GMAC_EC_XCOL_Pos) /**< \brief (GMAC_EC) Excessive Collisions */
-/* -------- GMAC_LC : (GMAC Offset: 0x144) Late Collisions Register -------- */
-#define GMAC_LC_LCOL_Pos 0
-#define GMAC_LC_LCOL_Msk (0x3ffu << GMAC_LC_LCOL_Pos) /**< \brief (GMAC_LC) Late Collisions */
-/* -------- GMAC_DTF : (GMAC Offset: 0x148) Deferred Transmission Frames Register -------- */
-#define GMAC_DTF_DEFT_Pos 0
-#define GMAC_DTF_DEFT_Msk (0x3ffffu << GMAC_DTF_DEFT_Pos) /**< \brief (GMAC_DTF) Deferred Transmission */
-/* -------- GMAC_CSE : (GMAC Offset: 0x14C) Carrier Sense Errors Register -------- */
-#define GMAC_CSE_CSR_Pos 0
-#define GMAC_CSE_CSR_Msk (0x3ffu << GMAC_CSE_CSR_Pos) /**< \brief (GMAC_CSE) Carrier Sense Error */
-/* -------- GMAC_ORLO : (GMAC Offset: 0x150) Octets Received [31:0] Received -------- */
-#define GMAC_ORLO_RXO_Pos 0
-#define GMAC_ORLO_RXO_Msk (0xffffffffu << GMAC_ORLO_RXO_Pos) /**< \brief (GMAC_ORLO) Received Octets */
-/* -------- GMAC_ORHI : (GMAC Offset: 0x154) Octets Received [47:32] Received -------- */
-#define GMAC_ORHI_RXO_Pos 0
-#define GMAC_ORHI_RXO_Msk (0xffffu << GMAC_ORHI_RXO_Pos) /**< \brief (GMAC_ORHI) Received Octets */
-/* -------- GMAC_FR : (GMAC Offset: 0x158) Frames Received Register -------- */
-#define GMAC_FR_FRX_Pos 0
-#define GMAC_FR_FRX_Msk (0xffffffffu << GMAC_FR_FRX_Pos) /**< \brief (GMAC_FR) Frames Received without Error */
-/* -------- GMAC_BCFR : (GMAC Offset: 0x15C) Broadcast Frames Received Register -------- */
-#define GMAC_BCFR_BFRX_Pos 0
-#define GMAC_BCFR_BFRX_Msk (0xffffffffu << GMAC_BCFR_BFRX_Pos) /**< \brief (GMAC_BCFR) Broadcast Frames Received without Error */
-/* -------- GMAC_MFR : (GMAC Offset: 0x160) Multicast Frames Received Register -------- */
-#define GMAC_MFR_MFRX_Pos 0
-#define GMAC_MFR_MFRX_Msk (0xffffffffu << GMAC_MFR_MFRX_Pos) /**< \brief (GMAC_MFR) Multicast Frames Received without Error */
-/* -------- GMAC_PFR : (GMAC Offset: 0x164) Pause Frames Received Register -------- */
-#define GMAC_PFR_PFRX_Pos 0
-#define GMAC_PFR_PFRX_Msk (0xffffu << GMAC_PFR_PFRX_Pos) /**< \brief (GMAC_PFR) Pause Frames Received Register */
-/* -------- GMAC_BFR64 : (GMAC Offset: 0x168) 64 Byte Frames Received Register -------- */
-#define GMAC_BFR64_NFRX_Pos 0
-#define GMAC_BFR64_NFRX_Msk (0xffffffffu << GMAC_BFR64_NFRX_Pos) /**< \brief (GMAC_BFR64) 64 Byte Frames Received without Error */
-/* -------- GMAC_TBFR127 : (GMAC Offset: 0x16C) 65 to 127 Byte Frames Received Register -------- */
-#define GMAC_TBFR127_NFRX_Pos 0
-#define GMAC_TBFR127_NFRX_Msk (0xffffffffu << GMAC_TBFR127_NFRX_Pos) /**< \brief (GMAC_TBFR127) 65 to 127 Byte Frames Received without Error */
-/* -------- GMAC_TBFR255 : (GMAC Offset: 0x170) 128 to 255 Byte Frames Received Register -------- */
-#define GMAC_TBFR255_NFRX_Pos 0
-#define GMAC_TBFR255_NFRX_Msk (0xffffffffu << GMAC_TBFR255_NFRX_Pos) /**< \brief (GMAC_TBFR255) 128 to 255 Byte Frames Received without Error */
-/* -------- GMAC_TBFR511 : (GMAC Offset: 0x174) 256 to 511Byte Frames Received Register -------- */
-#define GMAC_TBFR511_NFRX_Pos 0
-#define GMAC_TBFR511_NFRX_Msk (0xffffffffu << GMAC_TBFR511_NFRX_Pos) /**< \brief (GMAC_TBFR511) 256 to 511 Byte Frames Received without Error */
-/* -------- GMAC_TBFR1023 : (GMAC Offset: 0x178) 512 to 1023 Byte Frames Received Register -------- */
-#define GMAC_TBFR1023_NFRX_Pos 0
-#define GMAC_TBFR1023_NFRX_Msk (0xffffffffu << GMAC_TBFR1023_NFRX_Pos) /**< \brief (GMAC_TBFR1023) 512 to 1023 Byte Frames Received without Error */
-/* -------- GMAC_TBFR1518 : (GMAC Offset: 0x17C) 1024 to 1518 Byte Frames Received Register -------- */
-#define GMAC_TBFR1518_NFRX_Pos 0
-#define GMAC_TBFR1518_NFRX_Msk (0xffffffffu << GMAC_TBFR1518_NFRX_Pos) /**< \brief (GMAC_TBFR1518) 1024 to 1518 Byte Frames Received without Error */
-/* -------- GMAC_TMXBFR : (GMAC Offset: 0x180) 1519 to Maximum Byte Frames Received Register -------- */
-#define GMAC_TMXBFR_NFRX_Pos 0
-#define GMAC_TMXBFR_NFRX_Msk (0xffffffffu << GMAC_TMXBFR_NFRX_Pos) /**< \brief (GMAC_TMXBFR) 1519 to Maximum Byte Frames Received without Error */
-/* -------- GMAC_UFR : (GMAC Offset: 0x184) Undersize Frames Received Register -------- */
-#define GMAC_UFR_UFRX_Pos 0
-#define GMAC_UFR_UFRX_Msk (0x3ffu << GMAC_UFR_UFRX_Pos) /**< \brief (GMAC_UFR) Undersize Frames Received */
-/* -------- GMAC_OFR : (GMAC Offset: 0x188) Oversize Frames Received Register -------- */
-#define GMAC_OFR_OFRX_Pos 0
-#define GMAC_OFR_OFRX_Msk (0x3ffu << GMAC_OFR_OFRX_Pos) /**< \brief (GMAC_OFR) Oversized Frames Received */
-/* -------- GMAC_JR : (GMAC Offset: 0x18C) Jabbers Received Register -------- */
-#define GMAC_JR_JRX_Pos 0
-#define GMAC_JR_JRX_Msk (0x3ffu << GMAC_JR_JRX_Pos) /**< \brief (GMAC_JR) Jabbers Received */
-/* -------- GMAC_FCSE : (GMAC Offset: 0x190) Frame Check Sequence Errors Register -------- */
-#define GMAC_FCSE_FCKR_Pos 0
-#define GMAC_FCSE_FCKR_Msk (0x3ffu << GMAC_FCSE_FCKR_Pos) /**< \brief (GMAC_FCSE) Frame Check Sequence Errors */
-/* -------- GMAC_LFFE : (GMAC Offset: 0x194) Length Field Frame Errors Register -------- */
-#define GMAC_LFFE_LFER_Pos 0
-#define GMAC_LFFE_LFER_Msk (0x3ffu << GMAC_LFFE_LFER_Pos) /**< \brief (GMAC_LFFE) Length Field Frame Errors */
-/* -------- GMAC_RSE : (GMAC Offset: 0x198) Receive Symbol Errors Register -------- */
-#define GMAC_RSE_RXSE_Pos 0
-#define GMAC_RSE_RXSE_Msk (0x3ffu << GMAC_RSE_RXSE_Pos) /**< \brief (GMAC_RSE) Receive Symbol Errors */
-/* -------- GMAC_AE : (GMAC Offset: 0x19C) Alignment Errors Register -------- */
-#define GMAC_AE_AER_Pos 0
-#define GMAC_AE_AER_Msk (0x3ffu << GMAC_AE_AER_Pos) /**< \brief (GMAC_AE) Alignment Errors */
-/* -------- GMAC_RRE : (GMAC Offset: 0x1A0) Receive Resource Errors Register -------- */
-#define GMAC_RRE_RXRER_Pos 0
-#define GMAC_RRE_RXRER_Msk (0x3ffffu << GMAC_RRE_RXRER_Pos) /**< \brief (GMAC_RRE) Receive Resource Errors */
-/* -------- GMAC_ROE : (GMAC Offset: 0x1A4) Receive Overrun Register -------- */
-#define GMAC_ROE_RXOVR_Pos 0
-#define GMAC_ROE_RXOVR_Msk (0x3ffu << GMAC_ROE_RXOVR_Pos) /**< \brief (GMAC_ROE) Receive Overruns */
-/* -------- GMAC_IHCE : (GMAC Offset: 0x1A8) IP Header Checksum Errors Register -------- */
-#define GMAC_IHCE_HCKER_Pos 0
-#define GMAC_IHCE_HCKER_Msk (0xffu << GMAC_IHCE_HCKER_Pos) /**< \brief (GMAC_IHCE) IP Header Checksum Errors */
-/* -------- GMAC_TCE : (GMAC Offset: 0x1AC) TCP Checksum Errors Register -------- */
-#define GMAC_TCE_TCKER_Pos 0
-#define GMAC_TCE_TCKER_Msk (0xffu << GMAC_TCE_TCKER_Pos) /**< \brief (GMAC_TCE) TCP Checksum Errors */
-/* -------- GMAC_UCE : (GMAC Offset: 0x1B0) UDP Checksum Errors Register -------- */
-#define GMAC_UCE_UCKER_Pos 0
-#define GMAC_UCE_UCKER_Msk (0xffu << GMAC_UCE_UCKER_Pos) /**< \brief (GMAC_UCE) UDP Checksum Errors */
-/* -------- GMAC_TSSS : (GMAC Offset: 0x1C8) 1588 Timer Sync Strobe Seconds Register -------- */
-#define GMAC_TSSS_VTS_Pos 0
-#define GMAC_TSSS_VTS_Msk (0xffffffffu << GMAC_TSSS_VTS_Pos) /**< \brief (GMAC_TSSS) Value of Timer Seconds Register Capture */
-#define GMAC_TSSS_VTS(value) ((GMAC_TSSS_VTS_Msk & ((value) << GMAC_TSSS_VTS_Pos)))
-/* -------- GMAC_TSSN : (GMAC Offset: 0x1CC) 1588 Timer Sync Strobe Nanoseconds Register -------- */
-#define GMAC_TSSN_VTN_Pos 0
-#define GMAC_TSSN_VTN_Msk (0x3fffffffu << GMAC_TSSN_VTN_Pos) /**< \brief (GMAC_TSSN) Value Timer Nanoseconds Register Capture */
-#define GMAC_TSSN_VTN(value) ((GMAC_TSSN_VTN_Msk & ((value) << GMAC_TSSN_VTN_Pos)))
-/* -------- GMAC_TS : (GMAC Offset: 0x1D0) 1588 Timer Seconds Register -------- */
-#define GMAC_TS_TCS_Pos 0
-#define GMAC_TS_TCS_Msk (0xffffffffu << GMAC_TS_TCS_Pos) /**< \brief (GMAC_TS) Timer Count in Seconds */
-#define GMAC_TS_TCS(value) ((GMAC_TS_TCS_Msk & ((value) << GMAC_TS_TCS_Pos)))
-/* -------- GMAC_TN : (GMAC Offset: 0x1D4) 1588 Timer Nanoseconds Register -------- */
-#define GMAC_TN_TNS_Pos 0
-#define GMAC_TN_TNS_Msk (0x3fffffffu << GMAC_TN_TNS_Pos) /**< \brief (GMAC_TN) Timer Count in Nanoseconds */
-#define GMAC_TN_TNS(value) ((GMAC_TN_TNS_Msk & ((value) << GMAC_TN_TNS_Pos)))
-/* -------- GMAC_TA : (GMAC Offset: 0x1D8) 1588 Timer Adjust Register -------- */
-#define GMAC_TA_ITDT_Pos 0
-#define GMAC_TA_ITDT_Msk (0x3fffffffu << GMAC_TA_ITDT_Pos) /**< \brief (GMAC_TA) Increment/Decrement */
-#define GMAC_TA_ITDT(value) ((GMAC_TA_ITDT_Msk & ((value) << GMAC_TA_ITDT_Pos)))
-#define GMAC_TA_ADJ (0x1u << 31) /**< \brief (GMAC_TA) Adjust 1588 Timer */
-/* -------- GMAC_TI : (GMAC Offset: 0x1DC) 1588 Timer Increment Register -------- */
-#define GMAC_TI_CNS_Pos 0
-#define GMAC_TI_CNS_Msk (0xffu << GMAC_TI_CNS_Pos) /**< \brief (GMAC_TI) Count Nanoseconds */
-#define GMAC_TI_CNS(value) ((GMAC_TI_CNS_Msk & ((value) << GMAC_TI_CNS_Pos)))
-#define GMAC_TI_ACNS_Pos 8
-#define GMAC_TI_ACNS_Msk (0xffu << GMAC_TI_ACNS_Pos) /**< \brief (GMAC_TI) Alternative Count Nanoseconds */
-#define GMAC_TI_ACNS(value) ((GMAC_TI_ACNS_Msk & ((value) << GMAC_TI_ACNS_Pos)))
-#define GMAC_TI_NIT_Pos 16
-#define GMAC_TI_NIT_Msk (0xffu << GMAC_TI_NIT_Pos) /**< \brief (GMAC_TI) Number of Increments */
-#define GMAC_TI_NIT(value) ((GMAC_TI_NIT_Msk & ((value) << GMAC_TI_NIT_Pos)))
-/* -------- GMAC_EFTS : (GMAC Offset: 0x1E0) PTP Event Frame Transmitted Seconds -------- */
-#define GMAC_EFTS_RUD_Pos 0
-#define GMAC_EFTS_RUD_Msk (0xffffffffu << GMAC_EFTS_RUD_Pos) /**< \brief (GMAC_EFTS) Register Update */
-/* -------- GMAC_EFTN : (GMAC Offset: 0x1E4) PTP Event Frame Transmitted Nanoseconds -------- */
-#define GMAC_EFTN_RUD_Pos 0
-#define GMAC_EFTN_RUD_Msk (0x3fffffffu << GMAC_EFTN_RUD_Pos) /**< \brief (GMAC_EFTN) Register Update */
-/* -------- GMAC_EFRS : (GMAC Offset: 0x1E8) PTP Event Frame Received Seconds -------- */
-#define GMAC_EFRS_RUD_Pos 0
-#define GMAC_EFRS_RUD_Msk (0xffffffffu << GMAC_EFRS_RUD_Pos) /**< \brief (GMAC_EFRS) Register Update */
-/* -------- GMAC_EFRN : (GMAC Offset: 0x1EC) PTP Event Frame Received Nanoseconds -------- */
-#define GMAC_EFRN_RUD_Pos 0
-#define GMAC_EFRN_RUD_Msk (0x3fffffffu << GMAC_EFRN_RUD_Pos) /**< \brief (GMAC_EFRN) Register Update */
-/* -------- GMAC_PEFTS : (GMAC Offset: 0x1F0) PTP Peer Event Frame Transmitted Seconds -------- */
-#define GMAC_PEFTS_RUD_Pos 0
-#define GMAC_PEFTS_RUD_Msk (0xffffffffu << GMAC_PEFTS_RUD_Pos) /**< \brief (GMAC_PEFTS) Register Update */
-/* -------- GMAC_PEFTN : (GMAC Offset: 0x1F4) PTP Peer Event Frame Transmitted Nanoseconds -------- */
-#define GMAC_PEFTN_RUD_Pos 0
-#define GMAC_PEFTN_RUD_Msk (0x3fffffffu << GMAC_PEFTN_RUD_Pos) /**< \brief (GMAC_PEFTN) Register Update */
-/* -------- GMAC_PEFRS : (GMAC Offset: 0x1F8) PTP Peer Event Frame Received Seconds -------- */
-#define GMAC_PEFRS_RUD_Pos 0
-#define GMAC_PEFRS_RUD_Msk (0xffffffffu << GMAC_PEFRS_RUD_Pos) /**< \brief (GMAC_PEFRS) Register Update */
-/* -------- GMAC_PEFRN : (GMAC Offset: 0x1FC) PTP Peer Event Frame Received Nanoseconds -------- */
-#define GMAC_PEFRN_RUD_Pos 0
-#define GMAC_PEFRN_RUD_Msk (0x3fffffffu << GMAC_PEFRN_RUD_Pos) /**< \brief (GMAC_PEFRN) Register Update */
-/* -------- GMAC_ISRPQ[7] : (GMAC Offset: 0x400) Interrupt Status Register Priority Queue -------- */
-#define GMAC_ISRPQ_RCOMP (0x1u << 1) /**< \brief (GMAC_ISRPQ[7]) Receive Complete */
-#define GMAC_ISRPQ_RXUBR (0x1u << 2) /**< \brief (GMAC_ISRPQ[7]) RX Used Bit Read */
-#define GMAC_ISRPQ_RLEX (0x1u << 5) /**< \brief (GMAC_ISRPQ[7]) Retry Limit Exceeded or Late Collision */
-#define GMAC_ISRPQ_TFC (0x1u << 6) /**< \brief (GMAC_ISRPQ[7]) Transmit Frame Corruption due to AHB error */
-#define GMAC_ISRPQ_TCOMP (0x1u << 7) /**< \brief (GMAC_ISRPQ[7]) Transmit Complete */
-#define GMAC_ISRPQ_ROVR (0x1u << 10) /**< \brief (GMAC_ISRPQ[7]) Receive Overrun */
-#define GMAC_ISRPQ_HRESP (0x1u << 11) /**< \brief (GMAC_ISRPQ[7]) HRESP Not OK */
-/* -------- GMAC_TBQBAPQ[7] : (GMAC Offset: 0x440) Transmit Buffer Queue Base Address Priority Queue -------- */
-#define GMAC_TBQBAPQ_TXBQBA_Pos 2
-#define GMAC_TBQBAPQ_TXBQBA_Msk (0x3fu << GMAC_TBQBAPQ_TXBQBA_Pos) /**< \brief (GMAC_TBQBAPQ[7]) Transmit Buffer Queue Base Address */
-#define GMAC_TBQBAPQ_TXBQBA(value) ((GMAC_TBQBAPQ_TXBQBA_Msk & ((value) << GMAC_TBQBAPQ_TXBQBA_Pos)))
-/* -------- GMAC_RBQBAPQ[7] : (GMAC Offset: 0x480) Receive Buffer Queue Base Address Priority Queue -------- */
-#define GMAC_RBQBAPQ_RXBQBA_Pos 2
-#define GMAC_RBQBAPQ_RXBQBA_Msk (0x3fu << GMAC_RBQBAPQ_RXBQBA_Pos) /**< \brief (GMAC_RBQBAPQ[7]) Receive Buffer Queue Base Address */
-#define GMAC_RBQBAPQ_RXBQBA(value) ((GMAC_RBQBAPQ_RXBQBA_Msk & ((value) << GMAC_RBQBAPQ_RXBQBA_Pos)))
-/* -------- GMAC_RBSRPQ[7] : (GMAC Offset: 0x4A0) Receive Buffer Size Register Priority Queue -------- */
-#define GMAC_RBSRPQ_RBS_Pos 0
-#define GMAC_RBSRPQ_RBS_Msk (0xffffu << GMAC_RBSRPQ_RBS_Pos) /**< \brief (GMAC_RBSRPQ[7]) Receive Buffer Size */
-#define GMAC_RBSRPQ_RBS(value) ((GMAC_RBSRPQ_RBS_Msk & ((value) << GMAC_RBSRPQ_RBS_Pos)))
-/* -------- GMAC_ST1RPQ[16] : (GMAC Offset: 0x500) Screening Type1 Register Priority Queue -------- */
-#define GMAC_ST1RPQ_QNB_Pos 0
-#define GMAC_ST1RPQ_QNB_Msk (0xfu << GMAC_ST1RPQ_QNB_Pos) /**< \brief (GMAC_ST1RPQ[16]) Que Number (0->7) */
-#define GMAC_ST1RPQ_QNB(value) ((GMAC_ST1RPQ_QNB_Msk & ((value) << GMAC_ST1RPQ_QNB_Pos)))
-#define GMAC_ST1RPQ_DSTCM_Pos 4
-#define GMAC_ST1RPQ_DSTCM_Msk (0xffu << GMAC_ST1RPQ_DSTCM_Pos) /**< \brief (GMAC_ST1RPQ[16]) Differentiated Services or Traffic Class Match */
-#define GMAC_ST1RPQ_DSTCM(value) ((GMAC_ST1RPQ_DSTCM_Msk & ((value) << GMAC_ST1RPQ_DSTCM_Pos)))
-#define GMAC_ST1RPQ_UDPM_Pos 12
-#define GMAC_ST1RPQ_UDPM_Msk (0xffffu << GMAC_ST1RPQ_UDPM_Pos) /**< \brief (GMAC_ST1RPQ[16]) UDP Port Match */
-#define GMAC_ST1RPQ_UDPM(value) ((GMAC_ST1RPQ_UDPM_Msk & ((value) << GMAC_ST1RPQ_UDPM_Pos)))
-#define GMAC_ST1RPQ_DSTCE (0x1u << 28) /**< \brief (GMAC_ST1RPQ[16]) Differentiated Services or Traffic Class Match Enable */
-#define GMAC_ST1RPQ_UDPE (0x1u << 29) /**< \brief (GMAC_ST1RPQ[16]) UDP Port Match Enable */
-/* -------- GMAC_ST2RPQ[16] : (GMAC Offset: 0x540) Screening Type2 Register Priority Queue -------- */
-#define GMAC_ST2RPQ_QNB_Pos 0
-#define GMAC_ST2RPQ_QNB_Msk (0xfu << GMAC_ST2RPQ_QNB_Pos) /**< \brief (GMAC_ST2RPQ[16]) Que Number (0->7) */
-#define GMAC_ST2RPQ_QNB(value) ((GMAC_ST2RPQ_QNB_Msk & ((value) << GMAC_ST2RPQ_QNB_Pos)))
-#define GMAC_ST2RPQ_VLANP_Pos 4
-#define GMAC_ST2RPQ_VLANP_Msk (0xfu << GMAC_ST2RPQ_VLANP_Pos) /**< \brief (GMAC_ST2RPQ[16]) VLAN Priority */
-#define GMAC_ST2RPQ_VLANP(value) ((GMAC_ST2RPQ_VLANP_Msk & ((value) << GMAC_ST2RPQ_VLANP_Pos)))
-#define GMAC_ST2RPQ_VLANE (0x1u << 8) /**< \brief (GMAC_ST2RPQ[16]) VLAN Enable */
-/* -------- GMAC_IERPQ[7] : (GMAC Offset: 0x600) Interrupt Enable Register Priority Queue -------- */
-#define GMAC_IERPQ_RCOMP (0x1u << 1) /**< \brief (GMAC_IERPQ[7]) Receive Complete */
-#define GMAC_IERPQ_RXUBR (0x1u << 2) /**< \brief (GMAC_IERPQ[7]) RX Used Bit Read */
-#define GMAC_IERPQ_RLEX (0x1u << 5) /**< \brief (GMAC_IERPQ[7]) Retry Limit Exceeded or Late Collision */
-#define GMAC_IERPQ_TFC (0x1u << 6) /**< \brief (GMAC_IERPQ[7]) Transmit Frame Corruption due to AHB error */
-#define GMAC_IERPQ_TCOMP (0x1u << 7) /**< \brief (GMAC_IERPQ[7]) Transmit Complete */
-#define GMAC_IERPQ_ROVR (0x1u << 10) /**< \brief (GMAC_IERPQ[7]) Receive Overrun */
-#define GMAC_IERPQ_HRESP (0x1u << 11) /**< \brief (GMAC_IERPQ[7]) HRESP Not OK */
-/* -------- GMAC_IDRPQ[7] : (GMAC Offset: 0x620) Interrupt Disable Register Priority Queue -------- */
-#define GMAC_IDRPQ_RCOMP (0x1u << 1) /**< \brief (GMAC_IDRPQ[7]) Receive Complete */
-#define GMAC_IDRPQ_RXUBR (0x1u << 2) /**< \brief (GMAC_IDRPQ[7]) RX Used Bit Read */
-#define GMAC_IDRPQ_RLEX (0x1u << 5) /**< \brief (GMAC_IDRPQ[7]) Retry Limit Exceeded or Late Collision */
-#define GMAC_IDRPQ_TFC (0x1u << 6) /**< \brief (GMAC_IDRPQ[7]) Transmit Frame Corruption due to AHB error */
-#define GMAC_IDRPQ_TCOMP (0x1u << 7) /**< \brief (GMAC_IDRPQ[7]) Transmit Complete */
-#define GMAC_IDRPQ_ROVR (0x1u << 10) /**< \brief (GMAC_IDRPQ[7]) Receive Overrun */
-#define GMAC_IDRPQ_HRESP (0x1u << 11) /**< \brief (GMAC_IDRPQ[7]) HRESP Not OK */
-/* -------- GMAC_IMRPQ[7] : (GMAC Offset: 0x640) Interrupt Mask Register Priority Queue -------- */
-#define GMAC_IMRPQ_RCOMP (0x1u << 1) /**< \brief (GMAC_IMRPQ[7]) Receive Complete */
-#define GMAC_IMRPQ_RXUBR (0x1u << 2) /**< \brief (GMAC_IMRPQ[7]) RX Used Bit Read */
-#define GMAC_IMRPQ_RLEX (0x1u << 5) /**< \brief (GMAC_IMRPQ[7]) Retry Limit Exceeded or Late Collision */
-#define GMAC_IMRPQ_AHB (0x1u << 6) /**< \brief (GMAC_IMRPQ[7]) AHB Error */
-#define GMAC_IMRPQ_TCOMP (0x1u << 7) /**< \brief (GMAC_IMRPQ[7]) Transmit Complete */
-#define GMAC_IMRPQ_ROVR (0x1u << 10) /**< \brief (GMAC_IMRPQ[7]) Receive Overrun */
-#define GMAC_IMRPQ_HRESP (0x1u << 11) /**< \brief (GMAC_IMRPQ[7]) HRESP Not OK */
-
-/*@}*/
-
-
-#endif /* _SAM4E_GMAC_COMPONENT_ */
+/**\r
+ * \file\r
+ *\r
+ * Copyright (c) 2012 Atmel Corporation. All rights reserved.\r
+ *\r
+ * \asf_license_start\r
+ *\r
+ * \page License\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ *    this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ *    this list of conditions and the following disclaimer in the documentation\r
+ *    and/or other materials provided with the distribution.\r
+ *\r
+ * 3. The name of Atmel may not be used to endorse or promote products derived\r
+ *    from this software without specific prior written permission.\r
+ *\r
+ * 4. This software may only be redistributed and used in connection with an\r
+ *    Atmel microcontroller product.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * \asf_license_stop\r
+ *\r
+ */\r
+\r
+#ifndef _SAM4E_GMAC_COMPONENT_\r
+#define _SAM4E_GMAC_COMPONENT_\r
+\r
+/* ============================================================================= */\r
+/**  SOFTWARE API DEFINITION FOR Gigabit Ethernet MAC */\r
+/* ============================================================================= */\r
+/** \addtogroup SAM4E_GMAC Gigabit Ethernet MAC */\r
+/*@{*/\r
+\r
+#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))\r
+/** \brief GmacSa hardware registers */\r
+typedef struct {\r
+  RwReg   GMAC_SAB;        /**< \brief (GmacSa Offset: 0x0) Specific Address 1 Bottom [31:0] Register */\r
+  RwReg   GMAC_SAT;        /**< \brief (GmacSa Offset: 0x4) Specific Address 1 Top [47:32] Register */\r
+} GmacSa;\r
+/** \brief Gmac hardware registers */\r
+#define GMACSA_NUMBER 4\r
+typedef struct {\r
+  RwReg   GMAC_NCR;        /**< \brief (Gmac Offset: 0x000) Network Control Register */\r
+  RwReg   GMAC_NCFGR;      /**< \brief (Gmac Offset: 0x004) Network Configuration Register */\r
+  RoReg   GMAC_NSR;        /**< \brief (Gmac Offset: 0x008) Network Status Register */\r
+  RwReg   GMAC_UR;         /**< \brief (Gmac Offset: 0x00C) User Register */\r
+  RwReg   GMAC_DCFGR;      /**< \brief (Gmac Offset: 0x010) DMA Configuration Register */\r
+  RwReg   GMAC_TSR;        /**< \brief (Gmac Offset: 0x014) Transmit Status Register */\r
+  RwReg   GMAC_RBQB;       /**< \brief (Gmac Offset: 0x018) Receive Buffer Queue Base Address */\r
+  RwReg   GMAC_TBQB;       /**< \brief (Gmac Offset: 0x01C) Transmit Buffer Queue Base Address */\r
+  RwReg   GMAC_RSR;        /**< \brief (Gmac Offset: 0x020) Receive Status Register */\r
+  RoReg   GMAC_ISR;        /**< \brief (Gmac Offset: 0x024) Interrupt Status Register */\r
+  WoReg   GMAC_IER;        /**< \brief (Gmac Offset: 0x028) Interrupt Enable Register */\r
+  WoReg   GMAC_IDR;        /**< \brief (Gmac Offset: 0x02C) Interrupt Disable Register */\r
+  RoReg   GMAC_IMR;        /**< \brief (Gmac Offset: 0x030) Interrupt Mask Register */\r
+  RwReg   GMAC_MAN;        /**< \brief (Gmac Offset: 0x034) PHY Maintenance Register */\r
+  RoReg   GMAC_RPQ;        /**< \brief (Gmac Offset: 0x038) Received Pause Quantum Register */\r
+  RwReg   GMAC_TPQ;        /**< \brief (Gmac Offset: 0x03C) Transmit Pause Quantum Register */\r
+  RwReg   GMAC_TPSF;       /**< \brief (Gmac Offset: 0x040) TX Partial Store and Forward Register */\r
+  RwReg   GMAC_RPSF;       /**< \brief (Gmac Offset: 0x044) RX Partial Store and Forward Register */\r
+  RoReg   Reserved1[14];\r
+  RwReg   GMAC_HRB;        /**< \brief (Gmac Offset: 0x080) Hash Register Bottom [31:0] */\r
+  RwReg   GMAC_HRT;        /**< \brief (Gmac Offset: 0x084) Hash Register Top [63:32] */\r
+  GmacSa  GMAC_SA[GMACSA_NUMBER]; /**< \brief (Gmac Offset: 0x088) 1 .. 4 */\r
+  RwReg   GMAC_TIDM[4];    /**< \brief (Gmac Offset: 0x0A8) Type ID Match 1 Register */\r
+  RwReg   GMAC_WOL;        /**< \brief (Gmac Offset: 0x0B8) Wake on LAN Register */\r
+  RwReg   GMAC_IPGS;       /**< \brief (Gmac Offset: 0x0BC) IPG Stretch Register */\r
+  RwReg   GMAC_SVLAN;      /**< \brief (Gmac Offset: 0x0C0) Stacked VLAN Register */\r
+  RwReg   GMAC_TPFCP;      /**< \brief (Gmac Offset: 0x0C4) Transmit PFC Pause Register */\r
+  RwReg   GMAC_SAMB1;      /**< \brief (Gmac Offset: 0x0C8) Specific Address 1 Mask Bottom [31:0] Register */\r
+  RwReg   GMAC_SAMT1;      /**< \brief (Gmac Offset: 0x0CC) Specific Address 1 Mask Top [47:32] Register */\r
+  RoReg   Reserved2[12];\r
+  RoReg   GMAC_OTLO;       /**< \brief (Gmac Offset: 0x100) Octets Transmitted [31:0] Register */\r
+  RoReg   GMAC_OTHI;       /**< \brief (Gmac Offset: 0x104) Octets Transmitted [47:32] Register */\r
+  RoReg   GMAC_FT;         /**< \brief (Gmac Offset: 0x108) Frames Transmitted Register */\r
+  RoReg   GMAC_BCFT;       /**< \brief (Gmac Offset: 0x10C) Broadcast Frames Transmitted Register */\r
+  RoReg   GMAC_MFT;        /**< \brief (Gmac Offset: 0x110) Multicast Frames Transmitted Register */\r
+  RoReg   GMAC_PFT;        /**< \brief (Gmac Offset: 0x114) Pause Frames Transmitted Register */\r
+  RoReg   GMAC_BFT64;      /**< \brief (Gmac Offset: 0x118) 64 Byte Frames Transmitted Register */\r
+  RoReg   GMAC_TBFT127;    /**< \brief (Gmac Offset: 0x11C) 65 to 127 Byte Frames Transmitted Register */\r
+  RoReg   GMAC_TBFT255;    /**< \brief (Gmac Offset: 0x120) 128 to 255 Byte Frames Transmitted Register */\r
+  RoReg   GMAC_TBFT511;    /**< \brief (Gmac Offset: 0x124) 256 to 511 Byte Frames Transmitted Register */\r
+  RoReg   GMAC_TBFT1023;   /**< \brief (Gmac Offset: 0x128) 512 to 1023 Byte Frames Transmitted Register */\r
+  RoReg   GMAC_TBFT1518;   /**< \brief (Gmac Offset: 0x12C) 1024 to 1518 Byte Frames Transmitted Register */\r
+  RoReg   GMAC_GTBFT1518;  /**< \brief (Gmac Offset: 0x130) Greater Than 1518 Byte Frames Transmitted Register */\r
+  RoReg   GMAC_TUR;        /**< \brief (Gmac Offset: 0x134) Transmit Under Runs Register */\r
+  RoReg   GMAC_SCF;        /**< \brief (Gmac Offset: 0x138) Single Collision Frames Register */\r
+  RoReg   GMAC_MCF;        /**< \brief (Gmac Offset: 0x13C) Multiple Collision Frames Register */\r
+  RoReg   GMAC_EC;         /**< \brief (Gmac Offset: 0x140) Excessive Collisions Register */\r
+  RoReg   GMAC_LC;         /**< \brief (Gmac Offset: 0x144) Late Collisions Register */\r
+  RoReg   GMAC_DTF;        /**< \brief (Gmac Offset: 0x148) Deferred Transmission Frames Register */\r
+  RoReg   GMAC_CSE;        /**< \brief (Gmac Offset: 0x14C) Carrier Sense Errors Register */\r
+  RoReg   GMAC_ORLO;       /**< \brief (Gmac Offset: 0x150) Octets Received [31:0] Received */\r
+  RoReg   GMAC_ORHI;       /**< \brief (Gmac Offset: 0x154) Octets Received [47:32] Received */\r
+  RoReg   GMAC_FR;         /**< \brief (Gmac Offset: 0x158) Frames Received Register */\r
+  RoReg   GMAC_BCFR;       /**< \brief (Gmac Offset: 0x15C) Broadcast Frames Received Register */\r
+  RoReg   GMAC_MFR;        /**< \brief (Gmac Offset: 0x160) Multicast Frames Received Register */\r
+  RoReg   GMAC_PFR;        /**< \brief (Gmac Offset: 0x164) Pause Frames Received Register */\r
+  RoReg   GMAC_BFR64;      /**< \brief (Gmac Offset: 0x168) 64 Byte Frames Received Register */\r
+  RoReg   GMAC_TBFR127;    /**< \brief (Gmac Offset: 0x16C) 65 to 127 Byte Frames Received Register */\r
+  RoReg   GMAC_TBFR255;    /**< \brief (Gmac Offset: 0x170) 128 to 255 Byte Frames Received Register */\r
+  RoReg   GMAC_TBFR511;    /**< \brief (Gmac Offset: 0x174) 256 to 511Byte Frames Received Register */\r
+  RoReg   GMAC_TBFR1023;   /**< \brief (Gmac Offset: 0x178) 512 to 1023 Byte Frames Received Register */\r
+  RoReg   GMAC_TBFR1518;   /**< \brief (Gmac Offset: 0x17C) 1024 to 1518 Byte Frames Received Register */\r
+  RoReg   GMAC_TMXBFR;     /**< \brief (Gmac Offset: 0x180) 1519 to Maximum Byte Frames Received Register */\r
+  RoReg   GMAC_UFR;        /**< \brief (Gmac Offset: 0x184) Undersize Frames Received Register */\r
+  RoReg   GMAC_OFR;        /**< \brief (Gmac Offset: 0x188) Oversize Frames Received Register */\r
+  RoReg   GMAC_JR;         /**< \brief (Gmac Offset: 0x18C) Jabbers Received Register */\r
+  RoReg   GMAC_FCSE;       /**< \brief (Gmac Offset: 0x190) Frame Check Sequence Errors Register */\r
+  RoReg   GMAC_LFFE;       /**< \brief (Gmac Offset: 0x194) Length Field Frame Errors Register */\r
+  RoReg   GMAC_RSE;        /**< \brief (Gmac Offset: 0x198) Receive Symbol Errors Register */\r
+  RoReg   GMAC_AE;         /**< \brief (Gmac Offset: 0x19C) Alignment Errors Register */\r
+  RoReg   GMAC_RRE;        /**< \brief (Gmac Offset: 0x1A0) Receive Resource Errors Register */\r
+  RoReg   GMAC_ROE;        /**< \brief (Gmac Offset: 0x1A4) Receive Overrun Register */\r
+  RoReg   GMAC_IHCE;       /**< \brief (Gmac Offset: 0x1A8) IP Header Checksum Errors Register */\r
+  RoReg   GMAC_TCE;        /**< \brief (Gmac Offset: 0x1AC) TCP Checksum Errors Register */\r
+  RoReg   GMAC_UCE;        /**< \brief (Gmac Offset: 0x1B0) UDP Checksum Errors Register */\r
+  RoReg   Reserved3[5];\r
+  RwReg   GMAC_TSSS;       /**< \brief (Gmac Offset: 0x1C8) 1588 Timer Sync Strobe Seconds Register */\r
+  RwReg   GMAC_TSSN;       /**< \brief (Gmac Offset: 0x1CC) 1588 Timer Sync Strobe Nanoseconds Register */\r
+  RwReg   GMAC_TS;         /**< \brief (Gmac Offset: 0x1D0) 1588 Timer Seconds Register */\r
+  RwReg   GMAC_TN;         /**< \brief (Gmac Offset: 0x1D4) 1588 Timer Nanoseconds Register */\r
+  WoReg   GMAC_TA;         /**< \brief (Gmac Offset: 0x1D8) 1588 Timer Adjust Register */\r
+  RwReg   GMAC_TI;         /**< \brief (Gmac Offset: 0x1DC) 1588 Timer Increment Register */\r
+  RoReg   GMAC_EFTS;       /**< \brief (Gmac Offset: 0x1E0) PTP Event Frame Transmitted Seconds */\r
+  RoReg   GMAC_EFTN;       /**< \brief (Gmac Offset: 0x1E4) PTP Event Frame Transmitted Nanoseconds */\r
+  RoReg   GMAC_EFRS;       /**< \brief (Gmac Offset: 0x1E8) PTP Event Frame Received Seconds */\r
+  RoReg   GMAC_EFRN;       /**< \brief (Gmac Offset: 0x1EC) PTP Event Frame Received Nanoseconds */\r
+  RoReg   GMAC_PEFTS;      /**< \brief (Gmac Offset: 0x1F0) PTP Peer Event Frame Transmitted Seconds */\r
+  RoReg   GMAC_PEFTN;      /**< \brief (Gmac Offset: 0x1F4) PTP Peer Event Frame Transmitted Nanoseconds */\r
+  RoReg   GMAC_PEFRS;      /**< \brief (Gmac Offset: 0x1F8) PTP Peer Event Frame Received Seconds */\r
+  RoReg   GMAC_PEFRN;      /**< \brief (Gmac Offset: 0x1FC) PTP Peer Event Frame Received Nanoseconds */\r
+  RoReg   Reserved4[128];\r
+  RoReg   GMAC_ISRPQ[7];   /**< \brief (Gmac Offset: 0x400) Interrupt Status Register Priority Queue */\r
+  RoReg   Reserved5[9];\r
+  RwReg   GMAC_TBQBAPQ[7]; /**< \brief (Gmac Offset: 0x440) Transmit Buffer Queue Base Address Priority Queue */\r
+  RoReg   Reserved6[9];\r
+  RwReg   GMAC_RBQBAPQ[7]; /**< \brief (Gmac Offset: 0x480) Receive Buffer Queue Base Address Priority Queue */\r
+  RoReg   Reserved7[1];\r
+  RwReg   GMAC_RBSRPQ[7];  /**< \brief (Gmac Offset: 0x4A0) Receive Buffer Size Register Priority Queue */\r
+  RoReg   Reserved8[17];\r
+  RwReg   GMAC_ST1RPQ[16]; /**< \brief (Gmac Offset: 0x500) Screening Type1 Register Priority Queue */\r
+  RwReg   GMAC_ST2RPQ[16]; /**< \brief (Gmac Offset: 0x540) Screening Type2 Register Priority Queue */\r
+  RoReg   Reserved9[32];\r
+  WoReg   GMAC_IERPQ[7];   /**< \brief (Gmac Offset: 0x600) Interrupt Enable Register Priority Queue */\r
+  RoReg   Reserved10[1];\r
+  WoReg   GMAC_IDRPQ[7];   /**< \brief (Gmac Offset: 0x620) Interrupt Disable Register Priority Queue */\r
+  RoReg   Reserved11[1];\r
+  RwReg   GMAC_IMRPQ[7];   /**< \brief (Gmac Offset: 0x640) Interrupt Mask Register Priority Queue */\r
+} Gmac;\r
+#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */\r
+/* -------- GMAC_NCR : (GMAC Offset: 0x000) Network Control Register -------- */\r
+#define GMAC_NCR_LB (0x1u << 0) /**< \brief (GMAC_NCR) Loop Back */\r
+#define GMAC_NCR_LBL (0x1u << 1) /**< \brief (GMAC_NCR) Loop Back Local */\r
+#define GMAC_NCR_RXEN (0x1u << 2) /**< \brief (GMAC_NCR) Receive Enable */\r
+#define GMAC_NCR_TXEN (0x1u << 3) /**< \brief (GMAC_NCR) Transmit Enable */\r
+#define GMAC_NCR_MPE (0x1u << 4) /**< \brief (GMAC_NCR) Management Port Enable */\r
+#define GMAC_NCR_CLRSTAT (0x1u << 5) /**< \brief (GMAC_NCR) Clear Statistics Registers */\r
+#define GMAC_NCR_INCSTAT (0x1u << 6) /**< \brief (GMAC_NCR) Increment Statistics Registers */\r
+#define GMAC_NCR_WESTAT (0x1u << 7) /**< \brief (GMAC_NCR) Write Enable for Statistics Registers */\r
+#define GMAC_NCR_BP (0x1u << 8) /**< \brief (GMAC_NCR) Back pressure */\r
+#define GMAC_NCR_TSTART (0x1u << 9) /**< \brief (GMAC_NCR) Start Transmission */\r
+#define GMAC_NCR_THALT (0x1u << 10) /**< \brief (GMAC_NCR) Transmit Halt */\r
+#define GMAC_NCR_TXPF (0x1u << 11) /**< \brief (GMAC_NCR) Transmit Pause Frame */\r
+#define GMAC_NCR_TXZQPF (0x1u << 12) /**< \brief (GMAC_NCR) Transmit Zero Quantum Pause Frame */\r
+#define GMAC_NCR_RDS (0x1u << 14) /**< \brief (GMAC_NCR) Read Snapshot */\r
+#define GMAC_NCR_SRTSM (0x1u << 15) /**< \brief (GMAC_NCR) Store Receive Time Stamp to Memory */\r
+#define GMAC_NCR_ENPBPR (0x1u << 16) /**< \brief (GMAC_NCR) Enable PFC Priority-based Pause Reception */\r
+#define GMAC_NCR_TXPBPF (0x1u << 17) /**< \brief (GMAC_NCR) Transmit PFC Priority-based Pause Frame */\r
+#define GMAC_NCR_FNP (0x1u << 18) /**< \brief (GMAC_NCR) Flush Next Packet */\r
+/* -------- GMAC_NCFGR : (GMAC Offset: 0x004) Network Configuration Register -------- */\r
+#define GMAC_NCFGR_SPD (0x1u << 0) /**< \brief (GMAC_NCFGR) Speed */\r
+#define GMAC_NCFGR_FD (0x1u << 1) /**< \brief (GMAC_NCFGR) Full Duplex */\r
+#define GMAC_NCFGR_DNVLAN (0x1u << 2) /**< \brief (GMAC_NCFGR) Discard Non-VLAN FRAMES */\r
+#define GMAC_NCFGR_JFRAME (0x1u << 3) /**< \brief (GMAC_NCFGR) Jumbo Frame Size */\r
+#define GMAC_NCFGR_CAF (0x1u << 4) /**< \brief (GMAC_NCFGR) Copy All Frames */\r
+#define GMAC_NCFGR_NBC (0x1u << 5) /**< \brief (GMAC_NCFGR) No Broadcast */\r
+#define GMAC_NCFGR_MTIHEN (0x1u << 6) /**< \brief (GMAC_NCFGR) Multicast Hash Enable */\r
+#define GMAC_NCFGR_UNIHEN (0x1u << 7) /**< \brief (GMAC_NCFGR) Unicast Hash Enable */\r
+#define GMAC_NCFGR_MAXFS (0x1u << 8) /**< \brief (GMAC_NCFGR) 1536 Maximum Frame Size */\r
+#define GMAC_NCFGR_GBE (0x1u << 10) /**< \brief (GMAC_NCFGR) Gigabit Mode Enable */\r
+#define GMAC_NCFGR_PIS (0x1u << 11) /**< \brief (GMAC_NCFGR) Physical Interface Select */\r
+#define GMAC_NCFGR_RTY (0x1u << 12) /**< \brief (GMAC_NCFGR) Retry Test */\r
+#define GMAC_NCFGR_PEN (0x1u << 13) /**< \brief (GMAC_NCFGR) Pause Enable */\r
+#define GMAC_NCFGR_RXBUFO_Pos 14\r
+#define GMAC_NCFGR_RXBUFO_Msk (0x3u << GMAC_NCFGR_RXBUFO_Pos) /**< \brief (GMAC_NCFGR) Receive Buffer Offset */\r
+#define GMAC_NCFGR_RXBUFO(value) ((GMAC_NCFGR_RXBUFO_Msk & ((value) << GMAC_NCFGR_RXBUFO_Pos)))\r
+#define GMAC_NCFGR_LFERD (0x1u << 16) /**< \brief (GMAC_NCFGR) Length Field Error Frame Discard */\r
+#define GMAC_NCFGR_RFCS (0x1u << 17) /**< \brief (GMAC_NCFGR) Remove FCS */\r
+#define GMAC_NCFGR_CLK_Pos 18\r
+#define GMAC_NCFGR_CLK_Msk (0x7u << GMAC_NCFGR_CLK_Pos) /**< \brief (GMAC_NCFGR) MDC CLock Division */\r
+#define   GMAC_NCFGR_CLK_MCK_8 (0x0u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 8 (MCK up to 20 MHz) */\r
+#define   GMAC_NCFGR_CLK_MCK_16 (0x1u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 16 (MCK up to 40 MHz) */\r
+#define   GMAC_NCFGR_CLK_MCK_32 (0x2u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 32 (MCK up to 80 MHz) */\r
+#define   GMAC_NCFGR_CLK_MCK_48 (0x3u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 48 (MCK up to 120MHz) */\r
+#define   GMAC_NCFGR_CLK_MCK_64 (0x4u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 64 (MCK up to 160 MHz) */\r
+#define   GMAC_NCFGR_CLK_MCK_96 (0x5u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 96 (MCK up to 240 MHz) */\r
+#define   GMAC_NCFGR_CLK_MCK_128 (0x6u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 128 (MCK up to 320 MHz) */\r
+#define   GMAC_NCFGR_CLK_MCK_224 (0x7u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 224 (MCK up to 540 MHz) */\r
+#define GMAC_NCFGR_DBW_Pos 21\r
+#define GMAC_NCFGR_DBW_Msk (0x3u << GMAC_NCFGR_DBW_Pos) /**< \brief (GMAC_NCFGR) Data Bus Width */\r
+#define   GMAC_NCFGR_DBW_DBW32 (0x0u << 21) /**< \brief (GMAC_NCFGR) 32-bit data bus width */\r
+#define   GMAC_NCFGR_DBW_DBW64 (0x1u << 21) /**< \brief (GMAC_NCFGR) 64-bit data bus width */\r
+#define GMAC_NCFGR_DCPF (0x1u << 23) /**< \brief (GMAC_NCFGR) Disable Copy of Pause Frames */\r
+#define GMAC_NCFGR_RXCOEN (0x1u << 24) /**< \brief (GMAC_NCFGR) Receive Checksum Offload Enable */\r
+#define GMAC_NCFGR_EFRHD (0x1u << 25) /**< \brief (GMAC_NCFGR) Enable Frames Received in Half Duplex */\r
+#define GMAC_NCFGR_IRXFCS (0x1u << 26) /**< \brief (GMAC_NCFGR) Ignore RX FCS */\r
+#define GMAC_NCFGR_IPGSEN (0x1u << 28) /**< \brief (GMAC_NCFGR) IP Stretch Enable */\r
+#define GMAC_NCFGR_RXBP (0x1u << 29) /**< \brief (GMAC_NCFGR) Receive Bad Preamble */\r
+#define GMAC_NCFGR_IRXER (0x1u << 30) /**< \brief (GMAC_NCFGR) Ignore IPG rx_er */\r
+/* -------- GMAC_NSR : (GMAC Offset: 0x008) Network Status Register -------- */\r
+#define GMAC_NSR_MDIO (0x1u << 1) /**< \brief (GMAC_NSR) MDIO Input Status */\r
+#define GMAC_NSR_IDLE (0x1u << 2) /**< \brief (GMAC_NSR) PHY Management Logic Idle */\r
+/* -------- GMAC_UR : (GMAC Offset: 0x00C) User Register -------- */\r
+#define GMAC_UR_RGMII (0x1u << 0) /**< \brief (GMAC_UR) RGMII Mode */\r
+#define GMAC_UR_HDFC (0x1u << 6) /**< \brief (GMAC_UR) Half Duplex Flow Control */\r
+#define GMAC_UR_BPDG (0x1u << 7) /**< \brief (GMAC_UR) BPDG Bypass Deglitchers */\r
+/* -------- GMAC_DCFGR : (GMAC Offset: 0x010) DMA Configuration Register -------- */\r
+#define GMAC_DCFGR_FBLDO_Pos 0\r
+#define GMAC_DCFGR_FBLDO_Msk (0x1fu << GMAC_DCFGR_FBLDO_Pos) /**< \brief (GMAC_DCFGR) Fixed Burst Length for DMA Data Operations: */\r
+#define   GMAC_DCFGR_FBLDO_SINGLE (0x1u << 0) /**< \brief (GMAC_DCFGR) 00001: Always use SINGLE AHB bursts */\r
+#define   GMAC_DCFGR_FBLDO_INCR4 (0x4u << 0) /**< \brief (GMAC_DCFGR) 001xx: Attempt to use INCR4 AHB bursts (Default) */\r
+#define   GMAC_DCFGR_FBLDO_INCR8 (0x8u << 0) /**< \brief (GMAC_DCFGR) 01xxx: Attempt to use INCR8 AHB bursts */\r
+#define   GMAC_DCFGR_FBLDO_INCR16 (0x10u << 0) /**< \brief (GMAC_DCFGR) 1xxxx: Attempt to use INCR16 AHB bursts */\r
+#define GMAC_DCFGR_ESMA (0x1u << 6) /**< \brief (GMAC_DCFGR) Endian Swap Mode Enable for Management Descriptor Accesses */\r
+#define GMAC_DCFGR_ESPA (0x1u << 7) /**< \brief (GMAC_DCFGR) Endian Swap Mode Enable for Packet Data Accesses */\r
+#define GMAC_DCFGR_RXBMS_Pos 8\r
+#define GMAC_DCFGR_RXBMS_Msk (0x3u << GMAC_DCFGR_RXBMS_Pos) /**< \brief (GMAC_DCFGR) Receiver Packet Buffer Memory Size Select */\r
+#define   GMAC_DCFGR_RXBMS_EIGHTH (0x0u << 8) /**< \brief (GMAC_DCFGR) 1 Kbyte Memory Size */\r
+#define   GMAC_DCFGR_RXBMS_QUARTER (0x1u << 8) /**< \brief (GMAC_DCFGR) 2 Kbytes Memory Size */\r
+#define   GMAC_DCFGR_RXBMS_HALF (0x2u << 8) /**< \brief (GMAC_DCFGR) 4 Kbytes Memory Size */\r
+#define   GMAC_DCFGR_RXBMS_FULL (0x3u << 8) /**< \brief (GMAC_DCFGR) 8 Kbytes Memory Size */\r
+#define GMAC_DCFGR_TXPBMS (0x1u << 10) /**< \brief (GMAC_DCFGR) Transmitter Packet Buffer Memory Size Select */\r
+#define GMAC_DCFGR_TXCOEN (0x1u << 11) /**< \brief (GMAC_DCFGR) Transmitter Checksum Generation Offload Enable */\r
+#define GMAC_DCFGR_DRBS_Pos 16\r
+#define GMAC_DCFGR_DRBS_Msk (0xffu << GMAC_DCFGR_DRBS_Pos) /**< \brief (GMAC_DCFGR) DMA Receive Buffer Size */\r
+#define GMAC_DCFGR_DRBS(value) ((GMAC_DCFGR_DRBS_Msk & ((value) << GMAC_DCFGR_DRBS_Pos)))\r
+#define GMAC_DCFGR_DDRP (0x1u << 24) /**< \brief (GMAC_DCFGR) DMA Discard Receive Packets */\r
+/* -------- GMAC_TSR : (GMAC Offset: 0x014) Transmit Status Register -------- */\r
+#define GMAC_TSR_UBR (0x1u << 0) /**< \brief (GMAC_TSR) Used Bit Read */\r
+#define GMAC_TSR_COL (0x1u << 1) /**< \brief (GMAC_TSR) Collision Occurred */\r
+#define GMAC_TSR_RLE (0x1u << 2) /**< \brief (GMAC_TSR) Retry Limit Exceeded */\r
+#define GMAC_TSR_TXGO (0x1u << 3) /**< \brief (GMAC_TSR) Transmit Go */\r
+#define GMAC_TSR_TFC (0x1u << 4) /**< \brief (GMAC_TSR) Transmit Frame Corruption due to AHB error */\r
+#define GMAC_TSR_TXCOMP (0x1u << 5) /**< \brief (GMAC_TSR) Transmit Complete */\r
+#define GMAC_TSR_UND (0x1u << 6) /**< \brief (GMAC_TSR) Transmit Under Run */\r
+#define GMAC_TSR_LCO (0x1u << 7) /**< \brief (GMAC_TSR) Late Collision Occurred */\r
+#define GMAC_TSR_HRESP (0x1u << 8) /**< \brief (GMAC_TSR) HRESP Not OK */\r
+/* -------- GMAC_RBQB : (GMAC Offset: 0x018) Receive Buffer Queue Base Address -------- */\r
+#define GMAC_RBQB_ADDR_Pos 2\r
+#define GMAC_RBQB_ADDR_Msk (0x3fffffffu << GMAC_RBQB_ADDR_Pos) /**< \brief (GMAC_RBQB) Receive buffer queue base address */\r
+#define GMAC_RBQB_ADDR(value) ((GMAC_RBQB_ADDR_Msk & ((value) << GMAC_RBQB_ADDR_Pos)))\r
+/* -------- GMAC_TBQB : (GMAC Offset: 0x01C) Transmit Buffer Queue Base Address -------- */\r
+#define GMAC_TBQB_ADDR_Pos 2\r
+#define GMAC_TBQB_ADDR_Msk (0x3fffffffu << GMAC_TBQB_ADDR_Pos) /**< \brief (GMAC_TBQB) Transmit Buffer Queue Base Address */\r
+#define GMAC_TBQB_ADDR(value) ((GMAC_TBQB_ADDR_Msk & ((value) << GMAC_TBQB_ADDR_Pos)))\r
+/* -------- GMAC_RSR : (GMAC Offset: 0x020) Receive Status Register -------- */\r
+#define GMAC_RSR_BNA (0x1u << 0) /**< \brief (GMAC_RSR) Buffer Not Available */\r
+#define GMAC_RSR_REC (0x1u << 1) /**< \brief (GMAC_RSR) Frame Received */\r
+#define GMAC_RSR_RXOVR (0x1u << 2) /**< \brief (GMAC_RSR) Receive Overrun */\r
+#define GMAC_RSR_HNO (0x1u << 3) /**< \brief (GMAC_RSR) HRESP Not OK */\r
+/* -------- GMAC_ISR : (GMAC Offset: 0x024) Interrupt Status Register -------- */\r
+#define GMAC_ISR_MFS (0x1u << 0) /**< \brief (GMAC_ISR) Management Frame Sent */\r
+#define GMAC_ISR_RCOMP (0x1u << 1) /**< \brief (GMAC_ISR) Receive Complete */\r
+#define GMAC_ISR_RXUBR (0x1u << 2) /**< \brief (GMAC_ISR) RX Used Bit Read */\r
+#define GMAC_ISR_TXUBR (0x1u << 3) /**< \brief (GMAC_ISR) TX Used Bit Read */\r
+#define GMAC_ISR_TUR (0x1u << 4) /**< \brief (GMAC_ISR) Transmit Under Run */\r
+#define GMAC_ISR_RLEX (0x1u << 5) /**< \brief (GMAC_ISR) Retry Limit Exceeded or Late Collision */\r
+#define GMAC_ISR_TFC (0x1u << 6) /**< \brief (GMAC_ISR) Transmit Frame Corruption due to AHB error */\r
+#define GMAC_ISR_TCOMP (0x1u << 7) /**< \brief (GMAC_ISR) Transmit Complete */\r
+#define GMAC_ISR_ROVR (0x1u << 10) /**< \brief (GMAC_ISR) Receive Overrun */\r
+#define GMAC_ISR_HRESP (0x1u << 11) /**< \brief (GMAC_ISR) HRESP Not OK */\r
+#define GMAC_ISR_PFNZ (0x1u << 12) /**< \brief (GMAC_ISR) Pause Frame with Non-zero Pause Quantum Received */\r
+#define GMAC_ISR_PTZ (0x1u << 13) /**< \brief (GMAC_ISR) Pause Time Zero */\r
+#define GMAC_ISR_PFTR (0x1u << 14) /**< \brief (GMAC_ISR) Pause Frame Transmitted */\r
+#define GMAC_ISR_EXINT (0x1u << 15) /**< \brief (GMAC_ISR) External Interrupt */\r
+#define GMAC_ISR_DRQFR (0x1u << 18) /**< \brief (GMAC_ISR) PTP Delay Request Frame Received */\r
+#define GMAC_ISR_SFR (0x1u << 19) /**< \brief (GMAC_ISR) PTP Sync Frame Received */\r
+#define GMAC_ISR_DRQFT (0x1u << 20) /**< \brief (GMAC_ISR) PTP Delay Request Frame Transmitted */\r
+#define GMAC_ISR_SFT (0x1u << 21) /**< \brief (GMAC_ISR) PTP Sync Frame Transmitted */\r
+#define GMAC_ISR_PDRQFR (0x1u << 22) /**< \brief (GMAC_ISR) PDelay Request Frame Received */\r
+#define GMAC_ISR_PDRSFR (0x1u << 23) /**< \brief (GMAC_ISR) PDelay Response Frame Received */\r
+#define GMAC_ISR_PDRQFT (0x1u << 24) /**< \brief (GMAC_ISR) PDelay Request Frame Transmitted */\r
+#define GMAC_ISR_PDRSFT (0x1u << 25) /**< \brief (GMAC_ISR) PDelay Response Frame Transmitted */\r
+#define GMAC_ISR_SRI (0x1u << 26) /**< \brief (GMAC_ISR) TSU Seconds Register Increment */\r
+#define GMAC_ISR_WOL (0x1u << 28) /**< \brief (GMAC_ISR) Wake On LAN */\r
+/* -------- GMAC_IER : (GMAC Offset: 0x028) Interrupt Enable Register -------- */\r
+#define GMAC_IER_MFS (0x1u << 0) /**< \brief (GMAC_IER) Management Frame Sent */\r
+#define GMAC_IER_RCOMP (0x1u << 1) /**< \brief (GMAC_IER) Receive Complete */\r
+#define GMAC_IER_RXUBR (0x1u << 2) /**< \brief (GMAC_IER) RX Used Bit Read */\r
+#define GMAC_IER_TXUBR (0x1u << 3) /**< \brief (GMAC_IER) TX Used Bit Read */\r
+#define GMAC_IER_TUR (0x1u << 4) /**< \brief (GMAC_IER) Transmit Under Run */\r
+#define GMAC_IER_RLEX (0x1u << 5) /**< \brief (GMAC_IER) Retry Limit Exceeded or Late Collision */\r
+#define GMAC_IER_TFC (0x1u << 6) /**< \brief (GMAC_IER) Transmit Frame Corruption due to AHB error */\r
+#define GMAC_IER_TCOMP (0x1u << 7) /**< \brief (GMAC_IER) Transmit Complete */\r
+#define GMAC_IER_ROVR (0x1u << 10) /**< \brief (GMAC_IER) Receive Overrun */\r
+#define GMAC_IER_HRESP (0x1u << 11) /**< \brief (GMAC_IER) HRESP Not OK */\r
+#define GMAC_IER_PFNZ (0x1u << 12) /**< \brief (GMAC_IER) Pause Frame with Non-zero Pause Quantum Received */\r
+#define GMAC_IER_PTZ (0x1u << 13) /**< \brief (GMAC_IER) Pause Time Zero */\r
+#define GMAC_IER_PFTR (0x1u << 14) /**< \brief (GMAC_IER) Pause Frame Transmitted */\r
+#define GMAC_IER_EXINT (0x1u << 15) /**< \brief (GMAC_IER) External Interrupt */\r
+#define GMAC_IER_DRQFR (0x1u << 18) /**< \brief (GMAC_IER) PTP Delay Request Frame Received */\r
+#define GMAC_IER_SFR (0x1u << 19) /**< \brief (GMAC_IER) PTP Sync Frame Received */\r
+#define GMAC_IER_DRQFT (0x1u << 20) /**< \brief (GMAC_IER) PTP Delay Request Frame Transmitted */\r
+#define GMAC_IER_SFT (0x1u << 21) /**< \brief (GMAC_IER) PTP Sync Frame Transmitted */\r
+#define GMAC_IER_PDRQFR (0x1u << 22) /**< \brief (GMAC_IER) PDelay Request Frame Received */\r
+#define GMAC_IER_PDRSFR (0x1u << 23) /**< \brief (GMAC_IER) PDelay Response Frame Received */\r
+#define GMAC_IER_PDRQFT (0x1u << 24) /**< \brief (GMAC_IER) PDelay Request Frame Transmitted */\r
+#define GMAC_IER_PDRSFT (0x1u << 25) /**< \brief (GMAC_IER) PDelay Response Frame Transmitted */\r
+#define GMAC_IER_SRI (0x1u << 26) /**< \brief (GMAC_IER) TSU Seconds Register Increment */\r
+#define GMAC_IER_WOL (0x1u << 28) /**< \brief (GMAC_IER) Wake On LAN */\r
+/* -------- GMAC_IDR : (GMAC Offset: 0x02C) Interrupt Disable Register -------- */\r
+#define GMAC_IDR_MFS (0x1u << 0) /**< \brief (GMAC_IDR) Management Frame Sent */\r
+#define GMAC_IDR_RCOMP (0x1u << 1) /**< \brief (GMAC_IDR) Receive Complete */\r
+#define GMAC_IDR_RXUBR (0x1u << 2) /**< \brief (GMAC_IDR) RX Used Bit Read */\r
+#define GMAC_IDR_TXUBR (0x1u << 3) /**< \brief (GMAC_IDR) TX Used Bit Read */\r
+#define GMAC_IDR_TUR (0x1u << 4) /**< \brief (GMAC_IDR) Transmit Under Run */\r
+#define GMAC_IDR_RLEX (0x1u << 5) /**< \brief (GMAC_IDR) Retry Limit Exceeded or Late Collision */\r
+#define GMAC_IDR_TFC (0x1u << 6) /**< \brief (GMAC_IDR) Transmit Frame Corruption due to AHB error */\r
+#define GMAC_IDR_TCOMP (0x1u << 7) /**< \brief (GMAC_IDR) Transmit Complete */\r
+#define GMAC_IDR_ROVR (0x1u << 10) /**< \brief (GMAC_IDR) Receive Overrun */\r
+#define GMAC_IDR_HRESP (0x1u << 11) /**< \brief (GMAC_IDR) HRESP Not OK */\r
+#define GMAC_IDR_PFNZ (0x1u << 12) /**< \brief (GMAC_IDR) Pause Frame with Non-zero Pause Quantum Received */\r
+#define GMAC_IDR_PTZ (0x1u << 13) /**< \brief (GMAC_IDR) Pause Time Zero */\r
+#define GMAC_IDR_PFTR (0x1u << 14) /**< \brief (GMAC_IDR) Pause Frame Transmitted */\r
+#define GMAC_IDR_EXINT (0x1u << 15) /**< \brief (GMAC_IDR) External Interrupt */\r
+#define GMAC_IDR_DRQFR (0x1u << 18) /**< \brief (GMAC_IDR) PTP Delay Request Frame Received */\r
+#define GMAC_IDR_SFR (0x1u << 19) /**< \brief (GMAC_IDR) PTP Sync Frame Received */\r
+#define GMAC_IDR_DRQFT (0x1u << 20) /**< \brief (GMAC_IDR) PTP Delay Request Frame Transmitted */\r
+#define GMAC_IDR_SFT (0x1u << 21) /**< \brief (GMAC_IDR) PTP Sync Frame Transmitted */\r
+#define GMAC_IDR_PDRQFR (0x1u << 22) /**< \brief (GMAC_IDR) PDelay Request Frame Received */\r
+#define GMAC_IDR_PDRSFR (0x1u << 23) /**< \brief (GMAC_IDR) PDelay Response Frame Received */\r
+#define GMAC_IDR_PDRQFT (0x1u << 24) /**< \brief (GMAC_IDR) PDelay Request Frame Transmitted */\r
+#define GMAC_IDR_PDRSFT (0x1u << 25) /**< \brief (GMAC_IDR) PDelay Response Frame Transmitted */\r
+#define GMAC_IDR_SRI (0x1u << 26) /**< \brief (GMAC_IDR) TSU Seconds Register Increment */\r
+#define GMAC_IDR_WOL (0x1u << 28) /**< \brief (GMAC_IDR) Wake On LAN */\r
+/* -------- GMAC_IMR : (GMAC Offset: 0x030) Interrupt Mask Register -------- */\r
+#define GMAC_IMR_MFS (0x1u << 0) /**< \brief (GMAC_IMR) Management Frame Sent */\r
+#define GMAC_IMR_RCOMP (0x1u << 1) /**< \brief (GMAC_IMR) Receive Complete */\r
+#define GMAC_IMR_RXUBR (0x1u << 2) /**< \brief (GMAC_IMR) RX Used Bit Read */\r
+#define GMAC_IMR_TXUBR (0x1u << 3) /**< \brief (GMAC_IMR) TX Used Bit Read */\r
+#define GMAC_IMR_TUR (0x1u << 4) /**< \brief (GMAC_IMR) Transmit Under Run */\r
+#define GMAC_IMR_RLEX (0x1u << 5) /**< \brief (GMAC_IMR) Retry Limit Exceeded or Late Collision */\r
+#define GMAC_IMR_TFC (0x1u << 6) /**< \brief (GMAC_IMR) Transmit Frame Corruption due to AHB error */\r
+#define GMAC_IMR_TCOMP (0x1u << 7) /**< \brief (GMAC_IMR) Transmit Complete */\r
+#define GMAC_IMR_ROVR (0x1u << 10) /**< \brief (GMAC_IMR) Receive Overrun */\r
+#define GMAC_IMR_HRESP (0x1u << 11) /**< \brief (GMAC_IMR) HRESP Not OK */\r
+#define GMAC_IMR_PFNZ (0x1u << 12) /**< \brief (GMAC_IMR) Pause Frame with Non-zero Pause Quantum Received */\r
+#define GMAC_IMR_PTZ (0x1u << 13) /**< \brief (GMAC_IMR) Pause Time Zero */\r
+#define GMAC_IMR_PFTR (0x1u << 14) /**< \brief (GMAC_IMR) Pause Frame Transmitted */\r
+#define GMAC_IMR_EXINT (0x1u << 15) /**< \brief (GMAC_IMR) External Interrupt */\r
+#define GMAC_IMR_DRQFR (0x1u << 18) /**< \brief (GMAC_IMR) PTP Delay Request Frame Received */\r
+#define GMAC_IMR_SFR (0x1u << 19) /**< \brief (GMAC_IMR) PTP Sync Frame Received */\r
+#define GMAC_IMR_DRQFT (0x1u << 20) /**< \brief (GMAC_IMR) PTP Delay Request Frame Transmitted */\r
+#define GMAC_IMR_SFT (0x1u << 21) /**< \brief (GMAC_IMR) PTP Sync Frame Transmitted */\r
+#define GMAC_IMR_PDRQFR (0x1u << 22) /**< \brief (GMAC_IMR) PDelay Request Frame Received */\r
+#define GMAC_IMR_PDRSFR (0x1u << 23) /**< \brief (GMAC_IMR) PDelay Response Frame Received */\r
+#define GMAC_IMR_PDRQFT (0x1u << 24) /**< \brief (GMAC_IMR) PDelay Request Frame Transmitted */\r
+#define GMAC_IMR_PDRSFT (0x1u << 25) /**< \brief (GMAC_IMR) PDelay Response Frame Transmitted */\r
+/* -------- GMAC_MAN : (GMAC Offset: 0x034) PHY Maintenance Register -------- */\r
+#define GMAC_MAN_DATA_Pos 0\r
+#define GMAC_MAN_DATA_Msk (0xffffu << GMAC_MAN_DATA_Pos) /**< \brief (GMAC_MAN) PHY Data */\r
+#define GMAC_MAN_DATA(value) ((GMAC_MAN_DATA_Msk & ((value) << GMAC_MAN_DATA_Pos)))\r
+#define GMAC_MAN_WTN_Pos 16\r
+#define GMAC_MAN_WTN_Msk (0x3u << GMAC_MAN_WTN_Pos) /**< \brief (GMAC_MAN) Write Ten */\r
+#define GMAC_MAN_WTN(value) ((GMAC_MAN_WTN_Msk & ((value) << GMAC_MAN_WTN_Pos)))\r
+#define GMAC_MAN_REGA_Pos 18\r
+#define GMAC_MAN_REGA_Msk (0x1fu << GMAC_MAN_REGA_Pos) /**< \brief (GMAC_MAN) Register Address */\r
+#define GMAC_MAN_REGA(value) ((GMAC_MAN_REGA_Msk & ((value) << GMAC_MAN_REGA_Pos)))\r
+#define GMAC_MAN_PHYA_Pos 23\r
+#define GMAC_MAN_PHYA_Msk (0x1fu << GMAC_MAN_PHYA_Pos) /**< \brief (GMAC_MAN) PHY Address */\r
+#define GMAC_MAN_PHYA(value) ((GMAC_MAN_PHYA_Msk & ((value) << GMAC_MAN_PHYA_Pos)))\r
+#define GMAC_MAN_OP_Pos 28\r
+#define GMAC_MAN_OP_Msk (0x3u << GMAC_MAN_OP_Pos) /**< \brief (GMAC_MAN) Operation */\r
+#define GMAC_MAN_OP(value) ((GMAC_MAN_OP_Msk & ((value) << GMAC_MAN_OP_Pos)))\r
+#define GMAC_MAN_CLTTO (0x1u << 30) /**< \brief (GMAC_MAN) Clause 22 Operation */\r
+#define GMAC_MAN_WZO (0x1u << 31) /**< \brief (GMAC_MAN) Write ZERO */\r
+/* -------- GMAC_RPQ : (GMAC Offset: 0x038) Received Pause Quantum Register -------- */\r
+#define GMAC_RPQ_RPQ_Pos 0\r
+#define GMAC_RPQ_RPQ_Msk (0xffffu << GMAC_RPQ_RPQ_Pos) /**< \brief (GMAC_RPQ) Received Pause Quantum */\r
+/* -------- GMAC_TPQ : (GMAC Offset: 0x03C) Transmit Pause Quantum Register -------- */\r
+#define GMAC_TPQ_TPQ_Pos 0\r
+#define GMAC_TPQ_TPQ_Msk (0xffffu << GMAC_TPQ_TPQ_Pos) /**< \brief (GMAC_TPQ) Transmit Pause Quantum */\r
+#define GMAC_TPQ_TPQ(value) ((GMAC_TPQ_TPQ_Msk & ((value) << GMAC_TPQ_TPQ_Pos)))\r
+/* -------- GMAC_TPSF : (GMAC Offset: 0x040) TX Partial Store and Forward Register -------- */\r
+#define GMAC_TPSF_TPB1ADR_Pos 0\r
+#define GMAC_TPSF_TPB1ADR_Msk (0xfffu << GMAC_TPSF_TPB1ADR_Pos) /**< \brief (GMAC_TPSF) tx_pbuf_addr-1:0 */\r
+#define GMAC_TPSF_TPB1ADR(value) ((GMAC_TPSF_TPB1ADR_Msk & ((value) << GMAC_TPSF_TPB1ADR_Pos)))\r
+#define GMAC_TPSF_ENTXP (0x1u << 31) /**< \brief (GMAC_TPSF) Enable TX Partial Store and Forward Operation */\r
+/* -------- GMAC_RPSF : (GMAC Offset: 0x044) RX Partial Store and Forward Register -------- */\r
+#define GMAC_RPSF_RPB1ADR_Pos 0\r
+#define GMAC_RPSF_RPB1ADR_Msk (0xfffu << GMAC_RPSF_RPB1ADR_Pos) /**< \brief (GMAC_RPSF) rx_pbuf_addr-1:0 */\r
+#define GMAC_RPSF_RPB1ADR(value) ((GMAC_RPSF_RPB1ADR_Msk & ((value) << GMAC_RPSF_RPB1ADR_Pos)))\r
+#define GMAC_RPSF_ENRXP (0x1u << 31) /**< \brief (GMAC_RPSF) Enable RX Partial Store and Forward Operation */\r
+/* -------- GMAC_HRB : (GMAC Offset: 0x080) Hash Register Bottom [31:0] -------- */\r
+#define GMAC_HRB_ADDR_Pos 0\r
+#define GMAC_HRB_ADDR_Msk (0xffffffffu << GMAC_HRB_ADDR_Pos) /**< \brief (GMAC_HRB) Hash Address */\r
+#define GMAC_HRB_ADDR(value) ((GMAC_HRB_ADDR_Msk & ((value) << GMAC_HRB_ADDR_Pos)))\r
+/* -------- GMAC_HRT : (GMAC Offset: 0x084) Hash Register Top [63:32] -------- */\r
+#define GMAC_HRT_ADDR_Pos 0\r
+#define GMAC_HRT_ADDR_Msk (0xffffffffu << GMAC_HRT_ADDR_Pos) /**< \brief (GMAC_HRT) Hash Address */\r
+#define GMAC_HRT_ADDR(value) ((GMAC_HRT_ADDR_Msk & ((value) << GMAC_HRT_ADDR_Pos)))\r
+/* -------- GMAC_SAB1 : (GMAC Offset: 0x088) Specific Address 1 Bottom [31:0] Register -------- */\r
+#define GMAC_SAB1_ADDR_Pos 0\r
+#define GMAC_SAB1_ADDR_Msk (0xffffffffu << GMAC_SAB1_ADDR_Pos) /**< \brief (GMAC_SAB1) Specific Address 1 */\r
+#define GMAC_SAB1_ADDR(value) ((GMAC_SAB1_ADDR_Msk & ((value) << GMAC_SAB1_ADDR_Pos)))\r
+/* -------- GMAC_SAT1 : (GMAC Offset: 0x08C) Specific Address 1 Top [47:32] Register -------- */\r
+#define GMAC_SAT1_ADDR_Pos 0\r
+#define GMAC_SAT1_ADDR_Msk (0xffffu << GMAC_SAT1_ADDR_Pos) /**< \brief (GMAC_SAT1) Specific Address 1 */\r
+#define GMAC_SAT1_ADDR(value) ((GMAC_SAT1_ADDR_Msk & ((value) << GMAC_SAT1_ADDR_Pos)))\r
+/* -------- GMAC_SAB2 : (GMAC Offset: 0x090) Specific Address 2 Bottom [31:0] Register -------- */\r
+#define GMAC_SAB2_ADDR_Pos 0\r
+#define GMAC_SAB2_ADDR_Msk (0xffffffffu << GMAC_SAB2_ADDR_Pos) /**< \brief (GMAC_SAB2) Specific Address 2 */\r
+#define GMAC_SAB2_ADDR(value) ((GMAC_SAB2_ADDR_Msk & ((value) << GMAC_SAB2_ADDR_Pos)))\r
+/* -------- GMAC_SAT2 : (GMAC Offset: 0x094) Specific Address 2 Top [47:32] Register -------- */\r
+#define GMAC_SAT2_ADDR_Pos 0\r
+#define GMAC_SAT2_ADDR_Msk (0xffffu << GMAC_SAT2_ADDR_Pos) /**< \brief (GMAC_SAT2) Specific Address 2 */\r
+#define GMAC_SAT2_ADDR(value) ((GMAC_SAT2_ADDR_Msk & ((value) << GMAC_SAT2_ADDR_Pos)))\r
+/* -------- GMAC_SAB3 : (GMAC Offset: 0x098) Specific Address 3 Bottom [31:0] Register -------- */\r
+#define GMAC_SAB3_ADDR_Pos 0\r
+#define GMAC_SAB3_ADDR_Msk (0xffffffffu << GMAC_SAB3_ADDR_Pos) /**< \brief (GMAC_SAB3) Specific Address 3 */\r
+#define GMAC_SAB3_ADDR(value) ((GMAC_SAB3_ADDR_Msk & ((value) << GMAC_SAB3_ADDR_Pos)))\r
+/* -------- GMAC_SAT3 : (GMAC Offset: 0x09C) Specific Address 3 Top [47:32] Register -------- */\r
+#define GMAC_SAT3_ADDR_Pos 0\r
+#define GMAC_SAT3_ADDR_Msk (0xffffu << GMAC_SAT3_ADDR_Pos) /**< \brief (GMAC_SAT3) Specific Address 3 */\r
+#define GMAC_SAT3_ADDR(value) ((GMAC_SAT3_ADDR_Msk & ((value) << GMAC_SAT3_ADDR_Pos)))\r
+/* -------- GMAC_SAB4 : (GMAC Offset: 0x0A0) Specific Address 4 Bottom [31:0] Register -------- */\r
+#define GMAC_SAB4_ADDR_Pos 0\r
+#define GMAC_SAB4_ADDR_Msk (0xffffffffu << GMAC_SAB4_ADDR_Pos) /**< \brief (GMAC_SAB4) Specific Address 4 */\r
+#define GMAC_SAB4_ADDR(value) ((GMAC_SAB4_ADDR_Msk & ((value) << GMAC_SAB4_ADDR_Pos)))\r
+/* -------- GMAC_SAT4 : (GMAC Offset: 0x0A4) Specific Address 4 Top [47:32] Register -------- */\r
+#define GMAC_SAT4_ADDR_Pos 0\r
+#define GMAC_SAT4_ADDR_Msk (0xffffu << GMAC_SAT4_ADDR_Pos) /**< \brief (GMAC_SAT4) Specific Address 4 */\r
+#define GMAC_SAT4_ADDR(value) ((GMAC_SAT4_ADDR_Msk & ((value) << GMAC_SAT4_ADDR_Pos)))\r
+/* -------- GMAC_TIDM[4] : (GMAC Offset: 0x0A8) Type ID Match 1 Register -------- */\r
+#define GMAC_TIDM_TID_Pos 0\r
+#define GMAC_TIDM_TID_Msk (0xffffu << GMAC_TIDM_TID_Pos) /**< \brief (GMAC_TIDM[4]) Type ID Match 1 */\r
+#define GMAC_TIDM_TID(value) ((GMAC_TIDM_TID_Msk & ((value) << GMAC_TIDM_TID_Pos)))\r
+/* -------- GMAC_WOL : (GMAC Offset: 0x0B8) Wake on LAN Register -------- */\r
+#define GMAC_WOL_IP_Pos 0\r
+#define GMAC_WOL_IP_Msk (0xffffu << GMAC_WOL_IP_Pos) /**< \brief (GMAC_WOL) ARP Request IP Address */\r
+#define GMAC_WOL_IP(value) ((GMAC_WOL_IP_Msk & ((value) << GMAC_WOL_IP_Pos)))\r
+#define GMAC_WOL_MAG (0x1u << 16) /**< \brief (GMAC_WOL) Magic Packet Event Enable */\r
+#define GMAC_WOL_ARP (0x1u << 17) /**< \brief (GMAC_WOL) ARP Request IP Address */\r
+#define GMAC_WOL_SA1 (0x1u << 18) /**< \brief (GMAC_WOL) Specific Address Register 1 Event Enable */\r
+#define GMAC_WOL_MTI (0x1u << 19) /**< \brief (GMAC_WOL) Multicast Hash Event Enable */\r
+/* -------- GMAC_IPGS : (GMAC Offset: 0x0BC) IPG Stretch Register -------- */\r
+#define GMAC_IPGS_FL_Pos 0\r
+#define GMAC_IPGS_FL_Msk (0xffffu << GMAC_IPGS_FL_Pos) /**< \brief (GMAC_IPGS) Frame Length */\r
+#define GMAC_IPGS_FL(value) ((GMAC_IPGS_FL_Msk & ((value) << GMAC_IPGS_FL_Pos)))\r
+/* -------- GMAC_SVLAN : (GMAC Offset: 0x0C0) Stacked VLAN Register -------- */\r
+#define GMAC_SVLAN_VLAN_TYPE_Pos 0\r
+#define GMAC_SVLAN_VLAN_TYPE_Msk (0xffffu << GMAC_SVLAN_VLAN_TYPE_Pos) /**< \brief (GMAC_SVLAN) User Defined VLAN_TYPE Field */\r
+#define GMAC_SVLAN_VLAN_TYPE(value) ((GMAC_SVLAN_VLAN_TYPE_Msk & ((value) << GMAC_SVLAN_VLAN_TYPE_Pos)))\r
+#define GMAC_SVLAN_ESVLAN (0x1u << 31) /**< \brief (GMAC_SVLAN) Enable Stacked VLAN Processing Mode */\r
+/* -------- GMAC_TPFCP : (GMAC Offset: 0x0C4) Transmit PFC Pause Register -------- */\r
+#define GMAC_TPFCP_PEV_Pos 0\r
+#define GMAC_TPFCP_PEV_Msk (0xffu << GMAC_TPFCP_PEV_Pos) /**< \brief (GMAC_TPFCP) Priority Enable Vector */\r
+#define GMAC_TPFCP_PEV(value) ((GMAC_TPFCP_PEV_Msk & ((value) << GMAC_TPFCP_PEV_Pos)))\r
+#define GMAC_TPFCP_PQ_Pos 8\r
+#define GMAC_TPFCP_PQ_Msk (0xffu << GMAC_TPFCP_PQ_Pos) /**< \brief (GMAC_TPFCP) Pause Quantum */\r
+#define GMAC_TPFCP_PQ(value) ((GMAC_TPFCP_PQ_Msk & ((value) << GMAC_TPFCP_PQ_Pos)))\r
+/* -------- GMAC_SAMB1 : (GMAC Offset: 0x0C8) Specific Address 1 Mask Bottom [31:0] Register -------- */\r
+#define GMAC_SAMB1_ADDR_Pos 0\r
+#define GMAC_SAMB1_ADDR_Msk (0xffffffffu << GMAC_SAMB1_ADDR_Pos) /**< \brief (GMAC_SAMB1) Specific Address 1 Mask */\r
+#define GMAC_SAMB1_ADDR(value) ((GMAC_SAMB1_ADDR_Msk & ((value) << GMAC_SAMB1_ADDR_Pos)))\r
+/* -------- GMAC_SAMT1 : (GMAC Offset: 0x0CC) Specific Address 1 Mask Top [47:32] Register -------- */\r
+#define GMAC_SAMT1_ADDR_Pos 0\r
+#define GMAC_SAMT1_ADDR_Msk (0xffffu << GMAC_SAMT1_ADDR_Pos) /**< \brief (GMAC_SAMT1) Specific Address 1 Mask */\r
+#define GMAC_SAMT1_ADDR(value) ((GMAC_SAMT1_ADDR_Msk & ((value) << GMAC_SAMT1_ADDR_Pos)))\r
+/* -------- GMAC_OTLO : (GMAC Offset: 0x100) Octets Transmitted [31:0] Register -------- */\r
+#define GMAC_OTLO_TXO_Pos 0\r
+#define GMAC_OTLO_TXO_Msk (0xffffffffu << GMAC_OTLO_TXO_Pos) /**< \brief (GMAC_OTLO) Transmitted Octets */\r
+/* -------- GMAC_OTHI : (GMAC Offset: 0x104) Octets Transmitted [47:32] Register -------- */\r
+#define GMAC_OTHI_TXO_Pos 0\r
+#define GMAC_OTHI_TXO_Msk (0xffffu << GMAC_OTHI_TXO_Pos) /**< \brief (GMAC_OTHI) Transmitted Octets */\r
+/* -------- GMAC_FT : (GMAC Offset: 0x108) Frames Transmitted Register -------- */\r
+#define GMAC_FT_FTX_Pos 0\r
+#define GMAC_FT_FTX_Msk (0xffffffffu << GMAC_FT_FTX_Pos) /**< \brief (GMAC_FT) Frames Transmitted without Error */\r
+/* -------- GMAC_BCFT : (GMAC Offset: 0x10C) Broadcast Frames Transmitted Register -------- */\r
+#define GMAC_BCFT_BFTX_Pos 0\r
+#define GMAC_BCFT_BFTX_Msk (0xffffffffu << GMAC_BCFT_BFTX_Pos) /**< \brief (GMAC_BCFT) Broadcast Frames Transmitted without Error */\r
+/* -------- GMAC_MFT : (GMAC Offset: 0x110) Multicast Frames Transmitted Register -------- */\r
+#define GMAC_MFT_MFTX_Pos 0\r
+#define GMAC_MFT_MFTX_Msk (0xffffffffu << GMAC_MFT_MFTX_Pos) /**< \brief (GMAC_MFT) Multicast Frames Transmitted without Error */\r
+/* -------- GMAC_PFT : (GMAC Offset: 0x114) Pause Frames Transmitted Register -------- */\r
+#define GMAC_PFT_PFTX_Pos 0\r
+#define GMAC_PFT_PFTX_Msk (0xffffu << GMAC_PFT_PFTX_Pos) /**< \brief (GMAC_PFT) Pause Frames Transmitted Register */\r
+/* -------- GMAC_BFT64 : (GMAC Offset: 0x118) 64 Byte Frames Transmitted Register -------- */\r
+#define GMAC_BFT64_NFTX_Pos 0\r
+#define GMAC_BFT64_NFTX_Msk (0xffffffffu << GMAC_BFT64_NFTX_Pos) /**< \brief (GMAC_BFT64) 64 Byte Frames Transmitted without Error */\r
+/* -------- GMAC_TBFT127 : (GMAC Offset: 0x11C) 65 to 127 Byte Frames Transmitted Register -------- */\r
+#define GMAC_TBFT127_NFTX_Pos 0\r
+#define GMAC_TBFT127_NFTX_Msk (0xffffffffu << GMAC_TBFT127_NFTX_Pos) /**< \brief (GMAC_TBFT127) 65 to 127 Byte Frames Transmitted without Error */\r
+/* -------- GMAC_TBFT255 : (GMAC Offset: 0x120) 128 to 255 Byte Frames Transmitted Register -------- */\r
+#define GMAC_TBFT255_NFTX_Pos 0\r
+#define GMAC_TBFT255_NFTX_Msk (0xffffffffu << GMAC_TBFT255_NFTX_Pos) /**< \brief (GMAC_TBFT255) 128 to 255 Byte Frames Transmitted without Error */\r
+/* -------- GMAC_TBFT511 : (GMAC Offset: 0x124) 256 to 511 Byte Frames Transmitted Register -------- */\r
+#define GMAC_TBFT511_NFTX_Pos 0\r
+#define GMAC_TBFT511_NFTX_Msk (0xffffffffu << GMAC_TBFT511_NFTX_Pos) /**< \brief (GMAC_TBFT511) 256 to 511 Byte Frames Transmitted without Error */\r
+/* -------- GMAC_TBFT1023 : (GMAC Offset: 0x128) 512 to 1023 Byte Frames Transmitted Register -------- */\r
+#define GMAC_TBFT1023_NFTX_Pos 0\r
+#define GMAC_TBFT1023_NFTX_Msk (0xffffffffu << GMAC_TBFT1023_NFTX_Pos) /**< \brief (GMAC_TBFT1023) 512 to 1023 Byte Frames Transmitted without Error */\r
+/* -------- GMAC_TBFT1518 : (GMAC Offset: 0x12C) 1024 to 1518 Byte Frames Transmitted Register -------- */\r
+#define GMAC_TBFT1518_NFTX_Pos 0\r
+#define GMAC_TBFT1518_NFTX_Msk (0xffffffffu << GMAC_TBFT1518_NFTX_Pos) /**< \brief (GMAC_TBFT1518) 1024 to 1518 Byte Frames Transmitted without Error */\r
+/* -------- GMAC_GTBFT1518 : (GMAC Offset: 0x130) Greater Than 1518 Byte Frames Transmitted Register -------- */\r
+#define GMAC_GTBFT1518_NFTX_Pos 0\r
+#define GMAC_GTBFT1518_NFTX_Msk (0xffffffffu << GMAC_GTBFT1518_NFTX_Pos) /**< \brief (GMAC_GTBFT1518) Greater than 1518 Byte Frames Transmitted without Error */\r
+/* -------- GMAC_TUR : (GMAC Offset: 0x134) Transmit Under Runs Register -------- */\r
+#define GMAC_TUR_TXUNR_Pos 0\r
+#define GMAC_TUR_TXUNR_Msk (0x3ffu << GMAC_TUR_TXUNR_Pos) /**< \brief (GMAC_TUR) Transmit Under Runs */\r
+/* -------- GMAC_SCF : (GMAC Offset: 0x138) Single Collision Frames Register -------- */\r
+#define GMAC_SCF_SCOL_Pos 0\r
+#define GMAC_SCF_SCOL_Msk (0x3ffffu << GMAC_SCF_SCOL_Pos) /**< \brief (GMAC_SCF) Single Collision */\r
+/* -------- GMAC_MCF : (GMAC Offset: 0x13C) Multiple Collision Frames Register -------- */\r
+#define GMAC_MCF_MCOL_Pos 0\r
+#define GMAC_MCF_MCOL_Msk (0x3ffffu << GMAC_MCF_MCOL_Pos) /**< \brief (GMAC_MCF) Multiple Collision */\r
+/* -------- GMAC_EC : (GMAC Offset: 0x140) Excessive Collisions Register -------- */\r
+#define GMAC_EC_XCOL_Pos 0\r
+#define GMAC_EC_XCOL_Msk (0x3ffu << GMAC_EC_XCOL_Pos) /**< \brief (GMAC_EC) Excessive Collisions */\r
+/* -------- GMAC_LC : (GMAC Offset: 0x144) Late Collisions Register -------- */\r
+#define GMAC_LC_LCOL_Pos 0\r
+#define GMAC_LC_LCOL_Msk (0x3ffu << GMAC_LC_LCOL_Pos) /**< \brief (GMAC_LC) Late Collisions */\r
+/* -------- GMAC_DTF : (GMAC Offset: 0x148) Deferred Transmission Frames Register -------- */\r
+#define GMAC_DTF_DEFT_Pos 0\r
+#define GMAC_DTF_DEFT_Msk (0x3ffffu << GMAC_DTF_DEFT_Pos) /**< \brief (GMAC_DTF) Deferred Transmission */\r
+/* -------- GMAC_CSE : (GMAC Offset: 0x14C) Carrier Sense Errors Register -------- */\r
+#define GMAC_CSE_CSR_Pos 0\r
+#define GMAC_CSE_CSR_Msk (0x3ffu << GMAC_CSE_CSR_Pos) /**< \brief (GMAC_CSE) Carrier Sense Error */\r
+/* -------- GMAC_ORLO : (GMAC Offset: 0x150) Octets Received [31:0] Received -------- */\r
+#define GMAC_ORLO_RXO_Pos 0\r
+#define GMAC_ORLO_RXO_Msk (0xffffffffu << GMAC_ORLO_RXO_Pos) /**< \brief (GMAC_ORLO) Received Octets */\r
+/* -------- GMAC_ORHI : (GMAC Offset: 0x154) Octets Received [47:32] Received -------- */\r
+#define GMAC_ORHI_RXO_Pos 0\r
+#define GMAC_ORHI_RXO_Msk (0xffffu << GMAC_ORHI_RXO_Pos) /**< \brief (GMAC_ORHI) Received Octets */\r
+/* -------- GMAC_FR : (GMAC Offset: 0x158) Frames Received Register -------- */\r
+#define GMAC_FR_FRX_Pos 0\r
+#define GMAC_FR_FRX_Msk (0xffffffffu << GMAC_FR_FRX_Pos) /**< \brief (GMAC_FR) Frames Received without Error */\r
+/* -------- GMAC_BCFR : (GMAC Offset: 0x15C) Broadcast Frames Received Register -------- */\r
+#define GMAC_BCFR_BFRX_Pos 0\r
+#define GMAC_BCFR_BFRX_Msk (0xffffffffu << GMAC_BCFR_BFRX_Pos) /**< \brief (GMAC_BCFR) Broadcast Frames Received without Error */\r
+/* -------- GMAC_MFR : (GMAC Offset: 0x160) Multicast Frames Received Register -------- */\r
+#define GMAC_MFR_MFRX_Pos 0\r
+#define GMAC_MFR_MFRX_Msk (0xffffffffu << GMAC_MFR_MFRX_Pos) /**< \brief (GMAC_MFR) Multicast Frames Received without Error */\r
+/* -------- GMAC_PFR : (GMAC Offset: 0x164) Pause Frames Received Register -------- */\r
+#define GMAC_PFR_PFRX_Pos 0\r
+#define GMAC_PFR_PFRX_Msk (0xffffu << GMAC_PFR_PFRX_Pos) /**< \brief (GMAC_PFR) Pause Frames Received Register */\r
+/* -------- GMAC_BFR64 : (GMAC Offset: 0x168) 64 Byte Frames Received Register -------- */\r
+#define GMAC_BFR64_NFRX_Pos 0\r
+#define GMAC_BFR64_NFRX_Msk (0xffffffffu << GMAC_BFR64_NFRX_Pos) /**< \brief (GMAC_BFR64) 64 Byte Frames Received without Error */\r
+/* -------- GMAC_TBFR127 : (GMAC Offset: 0x16C) 65 to 127 Byte Frames Received Register -------- */\r
+#define GMAC_TBFR127_NFRX_Pos 0\r
+#define GMAC_TBFR127_NFRX_Msk (0xffffffffu << GMAC_TBFR127_NFRX_Pos) /**< \brief (GMAC_TBFR127) 65 to 127 Byte Frames Received without Error */\r
+/* -------- GMAC_TBFR255 : (GMAC Offset: 0x170) 128 to 255 Byte Frames Received Register -------- */\r
+#define GMAC_TBFR255_NFRX_Pos 0\r
+#define GMAC_TBFR255_NFRX_Msk (0xffffffffu << GMAC_TBFR255_NFRX_Pos) /**< \brief (GMAC_TBFR255) 128 to 255 Byte Frames Received without Error */\r
+/* -------- GMAC_TBFR511 : (GMAC Offset: 0x174) 256 to 511Byte Frames Received Register -------- */\r
+#define GMAC_TBFR511_NFRX_Pos 0\r
+#define GMAC_TBFR511_NFRX_Msk (0xffffffffu << GMAC_TBFR511_NFRX_Pos) /**< \brief (GMAC_TBFR511) 256 to 511 Byte Frames Received without Error */\r
+/* -------- GMAC_TBFR1023 : (GMAC Offset: 0x178) 512 to 1023 Byte Frames Received Register -------- */\r
+#define GMAC_TBFR1023_NFRX_Pos 0\r
+#define GMAC_TBFR1023_NFRX_Msk (0xffffffffu << GMAC_TBFR1023_NFRX_Pos) /**< \brief (GMAC_TBFR1023) 512 to 1023 Byte Frames Received without Error */\r
+/* -------- GMAC_TBFR1518 : (GMAC Offset: 0x17C) 1024 to 1518 Byte Frames Received Register -------- */\r
+#define GMAC_TBFR1518_NFRX_Pos 0\r
+#define GMAC_TBFR1518_NFRX_Msk (0xffffffffu << GMAC_TBFR1518_NFRX_Pos) /**< \brief (GMAC_TBFR1518) 1024 to 1518 Byte Frames Received without Error */\r
+/* -------- GMAC_TMXBFR : (GMAC Offset: 0x180) 1519 to Maximum Byte Frames Received Register -------- */\r
+#define GMAC_TMXBFR_NFRX_Pos 0\r
+#define GMAC_TMXBFR_NFRX_Msk (0xffffffffu << GMAC_TMXBFR_NFRX_Pos) /**< \brief (GMAC_TMXBFR) 1519 to Maximum Byte Frames Received without Error */\r
+/* -------- GMAC_UFR : (GMAC Offset: 0x184) Undersize Frames Received Register -------- */\r
+#define GMAC_UFR_UFRX_Pos 0\r
+#define GMAC_UFR_UFRX_Msk (0x3ffu << GMAC_UFR_UFRX_Pos) /**< \brief (GMAC_UFR) Undersize Frames Received */\r
+/* -------- GMAC_OFR : (GMAC Offset: 0x188) Oversize Frames Received Register -------- */\r
+#define GMAC_OFR_OFRX_Pos 0\r
+#define GMAC_OFR_OFRX_Msk (0x3ffu << GMAC_OFR_OFRX_Pos) /**< \brief (GMAC_OFR) Oversized Frames Received */\r
+/* -------- GMAC_JR : (GMAC Offset: 0x18C) Jabbers Received Register -------- */\r
+#define GMAC_JR_JRX_Pos 0\r
+#define GMAC_JR_JRX_Msk (0x3ffu << GMAC_JR_JRX_Pos) /**< \brief (GMAC_JR) Jabbers Received */\r
+/* -------- GMAC_FCSE : (GMAC Offset: 0x190) Frame Check Sequence Errors Register -------- */\r
+#define GMAC_FCSE_FCKR_Pos 0\r
+#define GMAC_FCSE_FCKR_Msk (0x3ffu << GMAC_FCSE_FCKR_Pos) /**< \brief (GMAC_FCSE) Frame Check Sequence Errors */\r
+/* -------- GMAC_LFFE : (GMAC Offset: 0x194) Length Field Frame Errors Register -------- */\r
+#define GMAC_LFFE_LFER_Pos 0\r
+#define GMAC_LFFE_LFER_Msk (0x3ffu << GMAC_LFFE_LFER_Pos) /**< \brief (GMAC_LFFE) Length Field Frame Errors */\r
+/* -------- GMAC_RSE : (GMAC Offset: 0x198) Receive Symbol Errors Register -------- */\r
+#define GMAC_RSE_RXSE_Pos 0\r
+#define GMAC_RSE_RXSE_Msk (0x3ffu << GMAC_RSE_RXSE_Pos) /**< \brief (GMAC_RSE) Receive Symbol Errors */\r
+/* -------- GMAC_AE : (GMAC Offset: 0x19C) Alignment Errors Register -------- */\r
+#define GMAC_AE_AER_Pos 0\r
+#define GMAC_AE_AER_Msk (0x3ffu << GMAC_AE_AER_Pos) /**< \brief (GMAC_AE) Alignment Errors */\r
+/* -------- GMAC_RRE : (GMAC Offset: 0x1A0) Receive Resource Errors Register -------- */\r
+#define GMAC_RRE_RXRER_Pos 0\r
+#define GMAC_RRE_RXRER_Msk (0x3ffffu << GMAC_RRE_RXRER_Pos) /**< \brief (GMAC_RRE) Receive Resource Errors */\r
+/* -------- GMAC_ROE : (GMAC Offset: 0x1A4) Receive Overrun Register -------- */\r
+#define GMAC_ROE_RXOVR_Pos 0\r
+#define GMAC_ROE_RXOVR_Msk (0x3ffu << GMAC_ROE_RXOVR_Pos) /**< \brief (GMAC_ROE) Receive Overruns */\r
+/* -------- GMAC_IHCE : (GMAC Offset: 0x1A8) IP Header Checksum Errors Register -------- */\r
+#define GMAC_IHCE_HCKER_Pos 0\r
+#define GMAC_IHCE_HCKER_Msk (0xffu << GMAC_IHCE_HCKER_Pos) /**< \brief (GMAC_IHCE) IP Header Checksum Errors */\r
+/* -------- GMAC_TCE : (GMAC Offset: 0x1AC) TCP Checksum Errors Register -------- */\r
+#define GMAC_TCE_TCKER_Pos 0\r
+#define GMAC_TCE_TCKER_Msk (0xffu << GMAC_TCE_TCKER_Pos) /**< \brief (GMAC_TCE) TCP Checksum Errors */\r
+/* -------- GMAC_UCE : (GMAC Offset: 0x1B0) UDP Checksum Errors Register -------- */\r
+#define GMAC_UCE_UCKER_Pos 0\r
+#define GMAC_UCE_UCKER_Msk (0xffu << GMAC_UCE_UCKER_Pos) /**< \brief (GMAC_UCE) UDP Checksum Errors */\r
+/* -------- GMAC_TSSS : (GMAC Offset: 0x1C8) 1588 Timer Sync Strobe Seconds Register -------- */\r
+#define GMAC_TSSS_VTS_Pos 0\r
+#define GMAC_TSSS_VTS_Msk (0xffffffffu << GMAC_TSSS_VTS_Pos) /**< \brief (GMAC_TSSS) Value of Timer Seconds Register Capture */\r
+#define GMAC_TSSS_VTS(value) ((GMAC_TSSS_VTS_Msk & ((value) << GMAC_TSSS_VTS_Pos)))\r
+/* -------- GMAC_TSSN : (GMAC Offset: 0x1CC) 1588 Timer Sync Strobe Nanoseconds Register -------- */\r
+#define GMAC_TSSN_VTN_Pos 0\r
+#define GMAC_TSSN_VTN_Msk (0x3fffffffu << GMAC_TSSN_VTN_Pos) /**< \brief (GMAC_TSSN) Value Timer Nanoseconds Register Capture */\r
+#define GMAC_TSSN_VTN(value) ((GMAC_TSSN_VTN_Msk & ((value) << GMAC_TSSN_VTN_Pos)))\r
+/* -------- GMAC_TS : (GMAC Offset: 0x1D0) 1588 Timer Seconds Register -------- */\r
+#define GMAC_TS_TCS_Pos 0\r
+#define GMAC_TS_TCS_Msk (0xffffffffu << GMAC_TS_TCS_Pos) /**< \brief (GMAC_TS) Timer Count in Seconds */\r
+#define GMAC_TS_TCS(value) ((GMAC_TS_TCS_Msk & ((value) << GMAC_TS_TCS_Pos)))\r
+/* -------- GMAC_TN : (GMAC Offset: 0x1D4) 1588 Timer Nanoseconds Register -------- */\r
+#define GMAC_TN_TNS_Pos 0\r
+#define GMAC_TN_TNS_Msk (0x3fffffffu << GMAC_TN_TNS_Pos) /**< \brief (GMAC_TN) Timer Count in Nanoseconds */\r
+#define GMAC_TN_TNS(value) ((GMAC_TN_TNS_Msk & ((value) << GMAC_TN_TNS_Pos)))\r
+/* -------- GMAC_TA : (GMAC Offset: 0x1D8) 1588 Timer Adjust Register -------- */\r
+#define GMAC_TA_ITDT_Pos 0\r
+#define GMAC_TA_ITDT_Msk (0x3fffffffu << GMAC_TA_ITDT_Pos) /**< \brief (GMAC_TA) Increment/Decrement */\r
+#define GMAC_TA_ITDT(value) ((GMAC_TA_ITDT_Msk & ((value) << GMAC_TA_ITDT_Pos)))\r
+#define GMAC_TA_ADJ (0x1u << 31) /**< \brief (GMAC_TA) Adjust 1588 Timer */\r
+/* -------- GMAC_TI : (GMAC Offset: 0x1DC) 1588 Timer Increment Register -------- */\r
+#define GMAC_TI_CNS_Pos 0\r
+#define GMAC_TI_CNS_Msk (0xffu << GMAC_TI_CNS_Pos) /**< \brief (GMAC_TI) Count Nanoseconds */\r
+#define GMAC_TI_CNS(value) ((GMAC_TI_CNS_Msk & ((value) << GMAC_TI_CNS_Pos)))\r
+#define GMAC_TI_ACNS_Pos 8\r
+#define GMAC_TI_ACNS_Msk (0xffu << GMAC_TI_ACNS_Pos) /**< \brief (GMAC_TI) Alternative Count Nanoseconds */\r
+#define GMAC_TI_ACNS(value) ((GMAC_TI_ACNS_Msk & ((value) << GMAC_TI_ACNS_Pos)))\r
+#define GMAC_TI_NIT_Pos 16\r
+#define GMAC_TI_NIT_Msk (0xffu << GMAC_TI_NIT_Pos) /**< \brief (GMAC_TI) Number of Increments */\r
+#define GMAC_TI_NIT(value) ((GMAC_TI_NIT_Msk & ((value) << GMAC_TI_NIT_Pos)))\r
+/* -------- GMAC_EFTS : (GMAC Offset: 0x1E0) PTP Event Frame Transmitted Seconds -------- */\r
+#define GMAC_EFTS_RUD_Pos 0\r
+#define GMAC_EFTS_RUD_Msk (0xffffffffu << GMAC_EFTS_RUD_Pos) /**< \brief (GMAC_EFTS) Register Update */\r
+/* -------- GMAC_EFTN : (GMAC Offset: 0x1E4) PTP Event Frame Transmitted Nanoseconds -------- */\r
+#define GMAC_EFTN_RUD_Pos 0\r
+#define GMAC_EFTN_RUD_Msk (0x3fffffffu << GMAC_EFTN_RUD_Pos) /**< \brief (GMAC_EFTN) Register Update */\r
+/* -------- GMAC_EFRS : (GMAC Offset: 0x1E8) PTP Event Frame Received Seconds -------- */\r
+#define GMAC_EFRS_RUD_Pos 0\r
+#define GMAC_EFRS_RUD_Msk (0xffffffffu << GMAC_EFRS_RUD_Pos) /**< \brief (GMAC_EFRS) Register Update */\r
+/* -------- GMAC_EFRN : (GMAC Offset: 0x1EC) PTP Event Frame Received Nanoseconds -------- */\r
+#define GMAC_EFRN_RUD_Pos 0\r
+#define GMAC_EFRN_RUD_Msk (0x3fffffffu << GMAC_EFRN_RUD_Pos) /**< \brief (GMAC_EFRN) Register Update */\r
+/* -------- GMAC_PEFTS : (GMAC Offset: 0x1F0) PTP Peer Event Frame Transmitted Seconds -------- */\r
+#define GMAC_PEFTS_RUD_Pos 0\r
+#define GMAC_PEFTS_RUD_Msk (0xffffffffu << GMAC_PEFTS_RUD_Pos) /**< \brief (GMAC_PEFTS) Register Update */\r
+/* -------- GMAC_PEFTN : (GMAC Offset: 0x1F4) PTP Peer Event Frame Transmitted Nanoseconds -------- */\r
+#define GMAC_PEFTN_RUD_Pos 0\r
+#define GMAC_PEFTN_RUD_Msk (0x3fffffffu << GMAC_PEFTN_RUD_Pos) /**< \brief (GMAC_PEFTN) Register Update */\r
+/* -------- GMAC_PEFRS : (GMAC Offset: 0x1F8) PTP Peer Event Frame Received Seconds -------- */\r
+#define GMAC_PEFRS_RUD_Pos 0\r
+#define GMAC_PEFRS_RUD_Msk (0xffffffffu << GMAC_PEFRS_RUD_Pos) /**< \brief (GMAC_PEFRS) Register Update */\r
+/* -------- GMAC_PEFRN : (GMAC Offset: 0x1FC) PTP Peer Event Frame Received Nanoseconds -------- */\r
+#define GMAC_PEFRN_RUD_Pos 0\r
+#define GMAC_PEFRN_RUD_Msk (0x3fffffffu << GMAC_PEFRN_RUD_Pos) /**< \brief (GMAC_PEFRN) Register Update */\r
+/* -------- GMAC_ISRPQ[7] : (GMAC Offset: 0x400) Interrupt Status Register Priority Queue -------- */\r
+#define GMAC_ISRPQ_RCOMP (0x1u << 1) /**< \brief (GMAC_ISRPQ[7]) Receive Complete */\r
+#define GMAC_ISRPQ_RXUBR (0x1u << 2) /**< \brief (GMAC_ISRPQ[7]) RX Used Bit Read */\r
+#define GMAC_ISRPQ_RLEX (0x1u << 5) /**< \brief (GMAC_ISRPQ[7]) Retry Limit Exceeded or Late Collision */\r
+#define GMAC_ISRPQ_TFC (0x1u << 6) /**< \brief (GMAC_ISRPQ[7]) Transmit Frame Corruption due to AHB error */\r
+#define GMAC_ISRPQ_TCOMP (0x1u << 7) /**< \brief (GMAC_ISRPQ[7]) Transmit Complete */\r
+#define GMAC_ISRPQ_ROVR (0x1u << 10) /**< \brief (GMAC_ISRPQ[7]) Receive Overrun */\r
+#define GMAC_ISRPQ_HRESP (0x1u << 11) /**< \brief (GMAC_ISRPQ[7]) HRESP Not OK */\r
+/* -------- GMAC_TBQBAPQ[7] : (GMAC Offset: 0x440) Transmit Buffer Queue Base Address Priority Queue -------- */\r
+#define GMAC_TBQBAPQ_TXBQBA_Pos 2\r
+#define GMAC_TBQBAPQ_TXBQBA_Msk (0x3fu << GMAC_TBQBAPQ_TXBQBA_Pos) /**< \brief (GMAC_TBQBAPQ[7]) Transmit Buffer Queue Base Address */\r
+#define GMAC_TBQBAPQ_TXBQBA(value) ((GMAC_TBQBAPQ_TXBQBA_Msk & ((value) << GMAC_TBQBAPQ_TXBQBA_Pos)))\r
+/* -------- GMAC_RBQBAPQ[7] : (GMAC Offset: 0x480) Receive Buffer Queue Base Address Priority Queue -------- */\r
+#define GMAC_RBQBAPQ_RXBQBA_Pos 2\r
+#define GMAC_RBQBAPQ_RXBQBA_Msk (0x3fu << GMAC_RBQBAPQ_RXBQBA_Pos) /**< \brief (GMAC_RBQBAPQ[7]) Receive Buffer Queue Base Address */\r
+#define GMAC_RBQBAPQ_RXBQBA(value) ((GMAC_RBQBAPQ_RXBQBA_Msk & ((value) << GMAC_RBQBAPQ_RXBQBA_Pos)))\r
+/* -------- GMAC_RBSRPQ[7] : (GMAC Offset: 0x4A0) Receive Buffer Size Register Priority Queue -------- */\r
+#define GMAC_RBSRPQ_RBS_Pos 0\r
+#define GMAC_RBSRPQ_RBS_Msk (0xffffu << GMAC_RBSRPQ_RBS_Pos) /**< \brief (GMAC_RBSRPQ[7]) Receive Buffer Size */\r
+#define GMAC_RBSRPQ_RBS(value) ((GMAC_RBSRPQ_RBS_Msk & ((value) << GMAC_RBSRPQ_RBS_Pos)))\r
+/* -------- GMAC_ST1RPQ[16] : (GMAC Offset: 0x500) Screening Type1 Register Priority Queue -------- */\r
+#define GMAC_ST1RPQ_QNB_Pos 0\r
+#define GMAC_ST1RPQ_QNB_Msk (0xfu << GMAC_ST1RPQ_QNB_Pos) /**< \brief (GMAC_ST1RPQ[16]) Que Number (0->7) */\r
+#define GMAC_ST1RPQ_QNB(value) ((GMAC_ST1RPQ_QNB_Msk & ((value) << GMAC_ST1RPQ_QNB_Pos)))\r
+#define GMAC_ST1RPQ_DSTCM_Pos 4\r
+#define GMAC_ST1RPQ_DSTCM_Msk (0xffu << GMAC_ST1RPQ_DSTCM_Pos) /**< \brief (GMAC_ST1RPQ[16]) Differentiated Services or Traffic Class Match */\r
+#define GMAC_ST1RPQ_DSTCM(value) ((GMAC_ST1RPQ_DSTCM_Msk & ((value) << GMAC_ST1RPQ_DSTCM_Pos)))\r
+#define GMAC_ST1RPQ_UDPM_Pos 12\r
+#define GMAC_ST1RPQ_UDPM_Msk (0xffffu << GMAC_ST1RPQ_UDPM_Pos) /**< \brief (GMAC_ST1RPQ[16]) UDP Port Match */\r
+#define GMAC_ST1RPQ_UDPM(value) ((GMAC_ST1RPQ_UDPM_Msk & ((value) << GMAC_ST1RPQ_UDPM_Pos)))\r
+#define GMAC_ST1RPQ_DSTCE (0x1u << 28) /**< \brief (GMAC_ST1RPQ[16]) Differentiated Services or Traffic Class Match Enable */\r
+#define GMAC_ST1RPQ_UDPE (0x1u << 29) /**< \brief (GMAC_ST1RPQ[16]) UDP Port Match Enable */\r
+/* -------- GMAC_ST2RPQ[16] : (GMAC Offset: 0x540) Screening Type2 Register Priority Queue -------- */\r
+#define GMAC_ST2RPQ_QNB_Pos 0\r
+#define GMAC_ST2RPQ_QNB_Msk (0xfu << GMAC_ST2RPQ_QNB_Pos) /**< \brief (GMAC_ST2RPQ[16]) Que Number (0->7) */\r
+#define GMAC_ST2RPQ_QNB(value) ((GMAC_ST2RPQ_QNB_Msk & ((value) << GMAC_ST2RPQ_QNB_Pos)))\r
+#define GMAC_ST2RPQ_VLANP_Pos 4\r
+#define GMAC_ST2RPQ_VLANP_Msk (0xfu << GMAC_ST2RPQ_VLANP_Pos) /**< \brief (GMAC_ST2RPQ[16]) VLAN Priority */\r
+#define GMAC_ST2RPQ_VLANP(value) ((GMAC_ST2RPQ_VLANP_Msk & ((value) << GMAC_ST2RPQ_VLANP_Pos)))\r
+#define GMAC_ST2RPQ_VLANE (0x1u << 8) /**< \brief (GMAC_ST2RPQ[16]) VLAN Enable */\r
+/* -------- GMAC_IERPQ[7] : (GMAC Offset: 0x600) Interrupt Enable Register Priority Queue -------- */\r
+#define GMAC_IERPQ_RCOMP (0x1u << 1) /**< \brief (GMAC_IERPQ[7]) Receive Complete */\r
+#define GMAC_IERPQ_RXUBR (0x1u << 2) /**< \brief (GMAC_IERPQ[7]) RX Used Bit Read */\r
+#define GMAC_IERPQ_RLEX (0x1u << 5) /**< \brief (GMAC_IERPQ[7]) Retry Limit Exceeded or Late Collision */\r
+#define GMAC_IERPQ_TFC (0x1u << 6) /**< \brief (GMAC_IERPQ[7]) Transmit Frame Corruption due to AHB error */\r
+#define GMAC_IERPQ_TCOMP (0x1u << 7) /**< \brief (GMAC_IERPQ[7]) Transmit Complete */\r
+#define GMAC_IERPQ_ROVR (0x1u << 10) /**< \brief (GMAC_IERPQ[7]) Receive Overrun */\r
+#define GMAC_IERPQ_HRESP (0x1u << 11) /**< \brief (GMAC_IERPQ[7]) HRESP Not OK */\r
+/* -------- GMAC_IDRPQ[7] : (GMAC Offset: 0x620) Interrupt Disable Register Priority Queue -------- */\r
+#define GMAC_IDRPQ_RCOMP (0x1u << 1) /**< \brief (GMAC_IDRPQ[7]) Receive Complete */\r
+#define GMAC_IDRPQ_RXUBR (0x1u << 2) /**< \brief (GMAC_IDRPQ[7]) RX Used Bit Read */\r
+#define GMAC_IDRPQ_RLEX (0x1u << 5) /**< \brief (GMAC_IDRPQ[7]) Retry Limit Exceeded or Late Collision */\r
+#define GMAC_IDRPQ_TFC (0x1u << 6) /**< \brief (GMAC_IDRPQ[7]) Transmit Frame Corruption due to AHB error */\r
+#define GMAC_IDRPQ_TCOMP (0x1u << 7) /**< \brief (GMAC_IDRPQ[7]) Transmit Complete */\r
+#define GMAC_IDRPQ_ROVR (0x1u << 10) /**< \brief (GMAC_IDRPQ[7]) Receive Overrun */\r
+#define GMAC_IDRPQ_HRESP (0x1u << 11) /**< \brief (GMAC_IDRPQ[7]) HRESP Not OK */\r
+/* -------- GMAC_IMRPQ[7] : (GMAC Offset: 0x640) Interrupt Mask Register Priority Queue -------- */\r
+#define GMAC_IMRPQ_RCOMP (0x1u << 1) /**< \brief (GMAC_IMRPQ[7]) Receive Complete */\r
+#define GMAC_IMRPQ_RXUBR (0x1u << 2) /**< \brief (GMAC_IMRPQ[7]) RX Used Bit Read */\r
+#define GMAC_IMRPQ_RLEX (0x1u << 5) /**< \brief (GMAC_IMRPQ[7]) Retry Limit Exceeded or Late Collision */\r
+#define GMAC_IMRPQ_AHB (0x1u << 6) /**< \brief (GMAC_IMRPQ[7]) AHB Error */\r
+#define GMAC_IMRPQ_TCOMP (0x1u << 7) /**< \brief (GMAC_IMRPQ[7]) Transmit Complete */\r
+#define GMAC_IMRPQ_ROVR (0x1u << 10) /**< \brief (GMAC_IMRPQ[7]) Receive Overrun */\r
+#define GMAC_IMRPQ_HRESP (0x1u << 11) /**< \brief (GMAC_IMRPQ[7]) HRESP Not OK */\r
+\r
+/*@}*/\r
+\r
+\r
+#endif /* _SAM4E_GMAC_COMPONENT_ */\r
index fc72c6ad9a87fe2649a33f9c346e3c65302ca6a2..fe9e2960ff80b754834c4c51ae7b1a3ac322b158 100644 (file)
- /**
- * \file
- *
- * \brief API driver for KSZ8051MNL PHY component.
- *
- * Copyright (c) 2013 Atmel Corporation. All rights reserved.
- *
- * \asf_license_start
- *
- * \page License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *
- * 3. The name of Atmel may not be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * 4. This software may only be redistributed and used in connection with an
- *    Atmel microcontroller product.
- *
- * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
- * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * \asf_license_stop
- *
- */
-
-/* Standard includes. */
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "FreeRTOSIPConfig.h"
-
-#include "ethernet_phy.h"
-#include "instance/gmac.h"
-
-/// @cond 0
-/**INDENT-OFF**/
-#ifdef __cplusplus
-extern "C" {
-#endif
-/**INDENT-ON**/
-/// @endcond
-
-/**
- * \defgroup ksz8051mnl_ethernet_phy_group PHY component (KSZ8051MNL)
- *
- * Driver for the ksz8051mnl component. This driver provides access to the main
- * features of the PHY.
- *
- * \section dependencies Dependencies
- * This driver depends on the following modules:
- * - \ref gmac_group Ethernet Media Access Controller (GMAC) module.
- *
- * @{
- */
-
-SPhyProps phyProps;
-
-/* Max PHY number */
-#define ETH_PHY_MAX_ADDR   31
-
-/* Ethernet PHY operation max retry count */
-#define ETH_PHY_RETRY_MAX 1000000
-
-/* Ethernet PHY operation timeout */
-#define ETH_PHY_TIMEOUT 10
-
-/**
- * \brief Find a valid PHY Address ( from addrStart to 31 ).
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_phy_addr PHY address.
- * \param uc_start_addr Start address of the PHY to be searched.
- *
- * \return 0xFF when no valid PHY address is found.
- */
-int ethernet_phy_addr = 0;
-static uint8_t ethernet_phy_find_valid(Gmac *p_gmac, uint8_t uc_phy_addr,
-               uint8_t uc_start_addr)
-{
-       uint32_t ul_value = 0;
-       uint8_t uc_cnt;
-       uint8_t uc_phy_address = uc_phy_addr;
-
-       gmac_enable_management(p_gmac, true);
-/*
-#define GMII_OUI_MSB            0x0022
-#define GMII_OUI_LSB            0x05
-
-PHYID1 = 0x0022
-PHYID2 = 0x1550
-0001_0101_0101_0000 = 0x1550 <= mask should be 0xFFF0
-*/
-       /* Check the current PHY address */
-       gmac_phy_read(p_gmac, uc_phy_addr, GMII_PHYID1, &ul_value);
-
-       /* Find another one */
-       if (ul_value != GMII_OUI_MSB) {
-               ethernet_phy_addr = 0xFF;
-               for (uc_cnt = uc_start_addr; uc_cnt <= ETH_PHY_MAX_ADDR; uc_cnt++) {
-                       uc_phy_address = (uc_phy_address + 1) & 0x1F;
-                       ul_value = 0;
-                       gmac_phy_read(p_gmac, uc_phy_address, GMII_PHYID1, &ul_value);
-                       if (ul_value == GMII_OUI_MSB) {
-                               ethernet_phy_addr = uc_phy_address;
-                               break;
-                       }
-               }
-       }
-
-       gmac_enable_management(p_gmac, false);
-
-       if (ethernet_phy_addr != 0xFF) {
-               gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_value);
-       }
-       return ethernet_phy_addr;
-}
-
-
-/**
- * \brief Perform a HW initialization to the PHY and set up clocks.
- *
- * This should be called only once to initialize the PHY pre-settings.
- * The PHY address is the reset status of CRS, RXD[3:0] (the emacPins' pullups).
- * The COL pin is used to select MII mode on reset (pulled up for Reduced MII).
- * The RXDV pin is used to select test mode on reset (pulled up for test mode).
- * The above pins should be predefined for corresponding settings in resetPins.
- * The GMAC peripheral pins are configured after the reset is done.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_phy_addr PHY address.
- * \param ul_mck GMAC MCK.
- *
- * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
- */
-uint8_t ethernet_phy_init(Gmac *p_gmac, uint8_t uc_phy_addr, uint32_t mck)
-{
-       uint8_t uc_rc = GMAC_TIMEOUT;
-       uint8_t uc_phy;
-
-       ethernet_phy_reset(GMAC,uc_phy_addr);
-
-       /* Configure GMAC runtime clock */
-       uc_rc = gmac_set_mdc_clock(p_gmac, mck);
-       if (uc_rc != GMAC_OK) {
-               return 0;
-       }
-
-       /* Check PHY Address */
-       uc_phy = ethernet_phy_find_valid(p_gmac, uc_phy_addr, 0);
-       if (uc_phy == 0xFF) {
-               return 0;
-       }
-       if (uc_phy != uc_phy_addr) {
-               ethernet_phy_reset(p_gmac, uc_phy_addr);
-       }
-       phy_props.phy_chn = uc_phy;
-       return uc_phy;
-}
-
-
-/**
- * \brief Get the Link & speed settings, and automatically set up the GMAC with the
- * settings.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_phy_addr PHY address.
- * \param uc_apply_setting_flag Set to 0 to not apply the PHY configurations, else to apply.
- *
- * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
- */
-uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr,
-               uint8_t uc_apply_setting_flag)
-{
-       uint32_t ul_stat1;
-       uint32_t ul_stat2;
-       uint8_t uc_phy_address, uc_speed = true, uc_fd = true;
-       uint8_t uc_rc = GMAC_TIMEOUT;
-
-       gmac_enable_management(p_gmac, true);
-
-       uc_phy_address = uc_phy_addr;
-
-       uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_stat1);
-       if (uc_rc != GMAC_OK) {
-               /* Disable PHY management and start the GMAC transfer */
-               gmac_enable_management(p_gmac, false);
-
-               return uc_rc;
-       }
-       if ((ul_stat1 & GMII_LINK_STATUS) == 0) {
-               /* Disable PHY management and start the GMAC transfer */
-               gmac_enable_management(p_gmac, false);
-
-               return GMAC_INVALID;
-       }
-
-       if (uc_apply_setting_flag == 0) {
-               /* Disable PHY management and start the GMAC transfer */
-               gmac_enable_management(p_gmac, false);
-
-               return uc_rc;
-       }
-
-       /* Read advertisement */
-       uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_ANAR, &ul_stat2);
-phy_props.phy_stat1 = ul_stat1;
-phy_props.phy_stat2 = ul_stat2;
-       if (uc_rc != GMAC_OK) {
-               /* Disable PHY management and start the GMAC transfer */
-               gmac_enable_management(p_gmac, false);
-
-               return uc_rc;
-       }
-
-       if ((ul_stat1 & GMII_100BASE_TX_FD) && (ul_stat2 & GMII_100TX_FDX)) {
-               /* Set GMAC for 100BaseTX and Full Duplex */
-               uc_speed = true;
-               uc_fd = true;
-       } else
-       if ((ul_stat1 & GMII_100BASE_T4_HD) && (ul_stat2 & GMII_100TX_HDX)) {
-               /* Set MII for 100BaseTX and Half Duplex */
-               uc_speed = true;
-               uc_fd = false;
-       } else
-       if ((ul_stat1 & GMII_10BASE_T_FD) && (ul_stat2 & GMII_10_FDX)) {
-               /* Set MII for 10BaseT and Full Duplex */
-               uc_speed = false;
-               uc_fd = true;
-       } else
-       if ((ul_stat1 & GMII_10BASE_T_HD) && (ul_stat2 & GMII_10_HDX)) {
-               /* Set MII for 10BaseT and Half Duplex */
-               uc_speed = false;
-               uc_fd = false;
-       }
-
-       gmac_set_speed(p_gmac, uc_speed);
-       gmac_enable_full_duplex(p_gmac, uc_fd);
-
-       /* Start the GMAC transfers */
-       gmac_enable_management(p_gmac, false);
-       return uc_rc;
-}
-
-PhyProps_t phy_props;
-
-/**
- * \brief Issue an auto negotiation of the PHY.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_phy_addr PHY address.
- *
- * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
- */
-uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr)
-{
-       uint32_t ul_retry_max = ETH_PHY_RETRY_MAX;
-       uint32_t ul_value;
-       uint32_t ul_phy_anar;
-       uint32_t ul_retry_count = 0;
-       uint8_t uc_speed = 0;
-       uint8_t uc_fd=0;
-       uint8_t uc_rc = GMAC_TIMEOUT;
-
-       gmac_enable_management(p_gmac, true);
-
-       /* Set up control register */
-       uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);
-       if (uc_rc != GMAC_OK) {
-               gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -1;
-               return uc_rc;
-       }
-
-       ul_value &= ~(uint32_t)GMII_AUTONEG; /* Remove auto-negotiation enable */
-       ul_value &= ~(uint32_t)(GMII_LOOPBACK | GMII_POWER_DOWN);
-       ul_value |= (uint32_t)GMII_ISOLATE; /* Electrically isolate PHY */
-       uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
-       if (uc_rc != GMAC_OK) {
-               gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -2;
-               return uc_rc;
-       }
-
-       /*
-        * Set the Auto_negotiation Advertisement Register.
-        * MII advertising for Next page.
-        * 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3.
-        */
-       ul_phy_anar = GMII_100TX_FDX | GMII_100TX_HDX | GMII_10_FDX | GMII_10_HDX |
-                       GMII_AN_IEEE_802_3;
-       uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_ANAR, ul_phy_anar);
-       if (uc_rc != GMAC_OK) {
-               gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -3;
-               return uc_rc;
-       }
-
-       /* Read & modify control register */
-       uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);
-       if (uc_rc != GMAC_OK) {
-               gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -4;
-               return uc_rc;
-       }
-
-       ul_value |= GMII_SPEED_SELECT | GMII_AUTONEG | GMII_DUPLEX_MODE;
-       uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
-       if (uc_rc != GMAC_OK) {
-               gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -5;
-               return uc_rc;
-       }
-
-       /* Restart auto negotiation */
-       ul_value |= (uint32_t)GMII_RESTART_AUTONEG;
-       ul_value &= ~(uint32_t)GMII_ISOLATE;
-       uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
-       if (uc_rc != GMAC_OK) {
-               gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -6;
-               return uc_rc;
-       }
-
-       /* Check if auto negotiation is completed */
-       while (1) {
-               uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMSR, &ul_value);
-               if (uc_rc != GMAC_OK) {
-                       gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -7;
-                       return uc_rc;
-               }
-               /* Done successfully */
-               if (ul_value & GMII_AUTONEG_COMP) {
-                       break;
-               }
-
-               /* Timeout check */
-               if (ul_retry_max) {
-                       if (++ul_retry_count >= ul_retry_max) {
-                               gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -8;
-                               return GMAC_TIMEOUT;
-                       }
-               }
-       }
-
-       /* Get the auto negotiate link partner base page */
-       uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_PCR1, &phy_props.phy_params);
-       if (uc_rc != GMAC_OK) {
-               gmac_enable_management(p_gmac, false);
-phy_props.phy_result = -9;
-               return uc_rc;
-       }
-
-
-       /* Set up the GMAC link speed */
-       if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_FDX) {
-               /* Set MII for 100BaseTX and Full Duplex */
-               uc_speed = true;
-               uc_fd = true;
-       } else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_FDX) {
-               /* Set MII for 10BaseT and Full Duplex */
-               uc_speed = false;
-               uc_fd = true;
-       } else if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_HDX) {
-               /* Set MII for 100BaseTX and half Duplex */
-               uc_speed = true;
-               uc_fd = false;
-       } else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_HDX) {
-               /* Set MII for 10BaseT and half Duplex */
-               uc_speed = false;
-               uc_fd = false;
-       }
-
-       gmac_set_speed(p_gmac, uc_speed);
-       gmac_enable_full_duplex(p_gmac, uc_fd);
-
-       /* Select Media Independent Interface type */
-       gmac_select_mii_mode(p_gmac, ETH_PHY_MODE);
-
-       gmac_enable_transmit(GMAC, true);
-       gmac_enable_receive(GMAC, true);
-
-       gmac_enable_management(p_gmac, false);
-phy_props.phy_result = 1;
-       return uc_rc;
-}
-
-/**
- * \brief Issue a SW reset to reset all registers of the PHY.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_phy_addr PHY address.
- *
- * \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
- */
-uint8_t ethernet_phy_reset(Gmac *p_gmac, uint8_t uc_phy_addr)
-{
-       uint32_t ul_bmcr = GMII_RESET;
-       uint8_t uc_phy_address = uc_phy_addr;
-       uint32_t ul_timeout = ETH_PHY_TIMEOUT;
-       uint8_t uc_rc = GMAC_TIMEOUT;
-
-       gmac_enable_management(p_gmac, true);
-
-       ul_bmcr = GMII_RESET;
-       gmac_phy_write(p_gmac, uc_phy_address, GMII_BMCR, ul_bmcr);
-
-       do {
-               gmac_phy_read(p_gmac, uc_phy_address, GMII_BMCR, &ul_bmcr);
-               ul_timeout--;
-       } while ((ul_bmcr & GMII_RESET) && ul_timeout);
-
-       gmac_enable_management(p_gmac, false);
-
-       if (!ul_timeout) {
-               uc_rc = GMAC_OK;
-       }
-
-       return (uc_rc);
-}
-
-/// @cond 0
-/**INDENT-OFF**/
-#ifdef __cplusplus
-}
-#endif
-/**INDENT-ON**/
-/// @endcond
-
-/**
- * \}
- */
+ /**\r
+ * \file\r
+ *\r
+ * \brief API driver for KSZ8051MNL PHY component.\r
+ *\r
+ * Copyright (c) 2013 Atmel Corporation. All rights reserved.\r
+ *\r
+ * \asf_license_start\r
+ *\r
+ * \page License\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ *    this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ *    this list of conditions and the following disclaimer in the documentation\r
+ *    and/or other materials provided with the distribution.\r
+ *\r
+ * 3. The name of Atmel may not be used to endorse or promote products derived\r
+ *    from this software without specific prior written permission.\r
+ *\r
+ * 4. This software may only be redistributed and used in connection with an\r
+ *    Atmel microcontroller product.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * \asf_license_stop\r
+ *\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 "FreeRTOSIPConfig.h"\r
+\r
+#include "ethernet_phy.h"\r
+#include "instance/gmac.h"\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
+\r
+/**\r
+ * \defgroup ksz8051mnl_ethernet_phy_group PHY component (KSZ8051MNL)\r
+ *\r
+ * Driver for the ksz8051mnl component. This driver provides access to the main\r
+ * features of the PHY.\r
+ *\r
+ * \section dependencies Dependencies\r
+ * This driver depends on the following modules:\r
+ * - \ref gmac_group Ethernet Media Access Controller (GMAC) module.\r
+ *\r
+ * @{\r
+ */\r
+\r
+SPhyProps phyProps;\r
+\r
+/* Max PHY number */\r
+#define ETH_PHY_MAX_ADDR   31\r
+\r
+/* Ethernet PHY operation max retry count */\r
+#define ETH_PHY_RETRY_MAX 1000000\r
+\r
+/* Ethernet PHY operation timeout */\r
+#define ETH_PHY_TIMEOUT 10\r
+\r
+/**\r
+ * \brief Find a valid PHY Address ( from addrStart to 31 ).\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ * \param uc_start_addr Start address of the PHY to be searched.\r
+ *\r
+ * \return 0xFF when no valid PHY address is found.\r
+ */\r
+int ethernet_phy_addr = 0;\r
+static uint8_t ethernet_phy_find_valid(Gmac *p_gmac, uint8_t uc_phy_addr,\r
+               uint8_t uc_start_addr)\r
+{\r
+       uint32_t ul_value = 0;\r
+       uint8_t uc_cnt;\r
+       uint8_t uc_phy_address = uc_phy_addr;\r
+\r
+       gmac_enable_management(p_gmac, true);\r
+/*\r
+#define GMII_OUI_MSB            0x0022\r
+#define GMII_OUI_LSB            0x05\r
+\r
+PHYID1 = 0x0022\r
+PHYID2 = 0x1550\r
+0001_0101_0101_0000 = 0x1550 <= mask should be 0xFFF0\r
+*/\r
+       /* Check the current PHY address */\r
+       gmac_phy_read(p_gmac, uc_phy_addr, GMII_PHYID1, &ul_value);\r
+\r
+       /* Find another one */\r
+       if (ul_value != GMII_OUI_MSB) {\r
+               ethernet_phy_addr = 0xFF;\r
+               for (uc_cnt = uc_start_addr; uc_cnt <= ETH_PHY_MAX_ADDR; uc_cnt++) {\r
+                       uc_phy_address = (uc_phy_address + 1) & 0x1F;\r
+                       ul_value = 0;\r
+                       gmac_phy_read(p_gmac, uc_phy_address, GMII_PHYID1, &ul_value);\r
+                       if (ul_value == GMII_OUI_MSB) {\r
+                               ethernet_phy_addr = uc_phy_address;\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+\r
+       gmac_enable_management(p_gmac, false);\r
+\r
+       if (ethernet_phy_addr != 0xFF) {\r
+               gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_value);\r
+       }\r
+       return ethernet_phy_addr;\r
+}\r
+\r
+\r
+/**\r
+ * \brief Perform a HW initialization to the PHY and set up clocks.\r
+ *\r
+ * This should be called only once to initialize the PHY pre-settings.\r
+ * The PHY address is the reset status of CRS, RXD[3:0] (the emacPins' pullups).\r
+ * The COL pin is used to select MII mode on reset (pulled up for Reduced MII).\r
+ * The RXDV pin is used to select test mode on reset (pulled up for test mode).\r
+ * The above pins should be predefined for corresponding settings in resetPins.\r
+ * The GMAC peripheral pins are configured after the reset is done.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ * \param ul_mck GMAC MCK.\r
+ *\r
+ * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_init(Gmac *p_gmac, uint8_t uc_phy_addr, uint32_t mck)\r
+{\r
+       uint8_t uc_rc = GMAC_TIMEOUT;\r
+       uint8_t uc_phy;\r
+\r
+       ethernet_phy_reset(GMAC,uc_phy_addr);\r
+\r
+       /* Configure GMAC runtime clock */\r
+       uc_rc = gmac_set_mdc_clock(p_gmac, mck);\r
+       if (uc_rc != GMAC_OK) {\r
+               return 0;\r
+       }\r
+\r
+       /* Check PHY Address */\r
+       uc_phy = ethernet_phy_find_valid(p_gmac, uc_phy_addr, 0);\r
+       if (uc_phy == 0xFF) {\r
+               return 0;\r
+       }\r
+       if (uc_phy != uc_phy_addr) {\r
+               ethernet_phy_reset(p_gmac, uc_phy_addr);\r
+       }\r
+       phy_props.phy_chn = uc_phy;\r
+       return uc_phy;\r
+}\r
+\r
+\r
+/**\r
+ * \brief Get the Link & speed settings, and automatically set up the GMAC with the\r
+ * settings.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ * \param uc_apply_setting_flag Set to 0 to not apply the PHY configurations, else to apply.\r
+ *\r
+ * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr,\r
+               uint8_t uc_apply_setting_flag)\r
+{\r
+       uint32_t ul_stat1;\r
+       uint32_t ul_stat2;\r
+       uint8_t uc_phy_address, uc_speed = true, uc_fd = true;\r
+       uint8_t uc_rc = GMAC_TIMEOUT;\r
+\r
+       gmac_enable_management(p_gmac, true);\r
+\r
+       uc_phy_address = uc_phy_addr;\r
+\r
+       uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_stat1);\r
+       if (uc_rc != GMAC_OK) {\r
+               /* Disable PHY management and start the GMAC transfer */\r
+               gmac_enable_management(p_gmac, false);\r
+\r
+               return uc_rc;\r
+       }\r
+       if ((ul_stat1 & GMII_LINK_STATUS) == 0) {\r
+               /* Disable PHY management and start the GMAC transfer */\r
+               gmac_enable_management(p_gmac, false);\r
+\r
+               return GMAC_INVALID;\r
+       }\r
+\r
+       if (uc_apply_setting_flag == 0) {\r
+               /* Disable PHY management and start the GMAC transfer */\r
+               gmac_enable_management(p_gmac, false);\r
+\r
+               return uc_rc;\r
+       }\r
+\r
+       /* Read advertisement */\r
+       uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_ANAR, &ul_stat2);\r
+phy_props.phy_stat1 = ul_stat1;\r
+phy_props.phy_stat2 = ul_stat2;\r
+       if (uc_rc != GMAC_OK) {\r
+               /* Disable PHY management and start the GMAC transfer */\r
+               gmac_enable_management(p_gmac, false);\r
+\r
+               return uc_rc;\r
+       }\r
+\r
+       if ((ul_stat1 & GMII_100BASE_TX_FD) && (ul_stat2 & GMII_100TX_FDX)) {\r
+               /* Set GMAC for 100BaseTX and Full Duplex */\r
+               uc_speed = true;\r
+               uc_fd = true;\r
+       } else\r
+       if ((ul_stat1 & GMII_100BASE_T4_HD) && (ul_stat2 & GMII_100TX_HDX)) {\r
+               /* Set MII for 100BaseTX and Half Duplex */\r
+               uc_speed = true;\r
+               uc_fd = false;\r
+       } else\r
+       if ((ul_stat1 & GMII_10BASE_T_FD) && (ul_stat2 & GMII_10_FDX)) {\r
+               /* Set MII for 10BaseT and Full Duplex */\r
+               uc_speed = false;\r
+               uc_fd = true;\r
+       } else\r
+       if ((ul_stat1 & GMII_10BASE_T_HD) && (ul_stat2 & GMII_10_HDX)) {\r
+               /* Set MII for 10BaseT and Half Duplex */\r
+               uc_speed = false;\r
+               uc_fd = false;\r
+       }\r
+\r
+       gmac_set_speed(p_gmac, uc_speed);\r
+       gmac_enable_full_duplex(p_gmac, uc_fd);\r
+\r
+       /* Start the GMAC transfers */\r
+       gmac_enable_management(p_gmac, false);\r
+       return uc_rc;\r
+}\r
+\r
+PhyProps_t phy_props;\r
+\r
+/**\r
+ * \brief Issue an auto negotiation of the PHY.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ *\r
+ * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr)\r
+{\r
+       uint32_t ul_retry_max = ETH_PHY_RETRY_MAX;\r
+       uint32_t ul_value;\r
+       uint32_t ul_phy_anar;\r
+       uint32_t ul_retry_count = 0;\r
+       uint8_t uc_speed = 0;\r
+       uint8_t uc_fd=0;\r
+       uint8_t uc_rc = GMAC_TIMEOUT;\r
+\r
+       gmac_enable_management(p_gmac, true);\r
+\r
+       /* Set up control register */\r
+       uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);\r
+       if (uc_rc != GMAC_OK) {\r
+               gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -1;\r
+               return uc_rc;\r
+       }\r
+\r
+       ul_value &= ~(uint32_t)GMII_AUTONEG; /* Remove auto-negotiation enable */\r
+       ul_value &= ~(uint32_t)(GMII_LOOPBACK | GMII_POWER_DOWN);\r
+       ul_value |= (uint32_t)GMII_ISOLATE; /* Electrically isolate PHY */\r
+       uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);\r
+       if (uc_rc != GMAC_OK) {\r
+               gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -2;\r
+               return uc_rc;\r
+       }\r
+\r
+       /*\r
+        * Set the Auto_negotiation Advertisement Register.\r
+        * MII advertising for Next page.\r
+        * 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3.\r
+        */\r
+       ul_phy_anar = GMII_100TX_FDX | GMII_100TX_HDX | GMII_10_FDX | GMII_10_HDX |\r
+                       GMII_AN_IEEE_802_3;\r
+       uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_ANAR, ul_phy_anar);\r
+       if (uc_rc != GMAC_OK) {\r
+               gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -3;\r
+               return uc_rc;\r
+       }\r
+\r
+       /* Read & modify control register */\r
+       uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);\r
+       if (uc_rc != GMAC_OK) {\r
+               gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -4;\r
+               return uc_rc;\r
+       }\r
+\r
+       ul_value |= GMII_SPEED_SELECT | GMII_AUTONEG | GMII_DUPLEX_MODE;\r
+       uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);\r
+       if (uc_rc != GMAC_OK) {\r
+               gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -5;\r
+               return uc_rc;\r
+       }\r
+\r
+       /* Restart auto negotiation */\r
+       ul_value |= (uint32_t)GMII_RESTART_AUTONEG;\r
+       ul_value &= ~(uint32_t)GMII_ISOLATE;\r
+       uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);\r
+       if (uc_rc != GMAC_OK) {\r
+               gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -6;\r
+               return uc_rc;\r
+       }\r
+\r
+       /* Check if auto negotiation is completed */\r
+       while (1) {\r
+               uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMSR, &ul_value);\r
+               if (uc_rc != GMAC_OK) {\r
+                       gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -7;\r
+                       return uc_rc;\r
+               }\r
+               /* Done successfully */\r
+               if (ul_value & GMII_AUTONEG_COMP) {\r
+                       break;\r
+               }\r
+\r
+               /* Timeout check */\r
+               if (ul_retry_max) {\r
+                       if (++ul_retry_count >= ul_retry_max) {\r
+                               gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -8;\r
+                               return GMAC_TIMEOUT;\r
+                       }\r
+               }\r
+       }\r
+\r
+       /* Get the auto negotiate link partner base page */\r
+       uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_PCR1, &phy_props.phy_params);\r
+       if (uc_rc != GMAC_OK) {\r
+               gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -9;\r
+               return uc_rc;\r
+       }\r
+\r
+\r
+       /* Set up the GMAC link speed */\r
+       if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_FDX) {\r
+               /* Set MII for 100BaseTX and Full Duplex */\r
+               uc_speed = true;\r
+               uc_fd = true;\r
+       } else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_FDX) {\r
+               /* Set MII for 10BaseT and Full Duplex */\r
+               uc_speed = false;\r
+               uc_fd = true;\r
+       } else if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_HDX) {\r
+               /* Set MII for 100BaseTX and half Duplex */\r
+               uc_speed = true;\r
+               uc_fd = false;\r
+       } else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_HDX) {\r
+               /* Set MII for 10BaseT and half Duplex */\r
+               uc_speed = false;\r
+               uc_fd = false;\r
+       }\r
+\r
+       gmac_set_speed(p_gmac, uc_speed);\r
+       gmac_enable_full_duplex(p_gmac, uc_fd);\r
+\r
+       /* Select Media Independent Interface type */\r
+       gmac_select_mii_mode(p_gmac, ETH_PHY_MODE);\r
+\r
+       gmac_enable_transmit(GMAC, true);\r
+       gmac_enable_receive(GMAC, true);\r
+\r
+       gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = 1;\r
+       return uc_rc;\r
+}\r
+\r
+/**\r
+ * \brief Issue a SW reset to reset all registers of the PHY.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ *\r
+ * \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_reset(Gmac *p_gmac, uint8_t uc_phy_addr)\r
+{\r
+       uint32_t ul_bmcr = GMII_RESET;\r
+       uint8_t uc_phy_address = uc_phy_addr;\r
+       uint32_t ul_timeout = ETH_PHY_TIMEOUT;\r
+       uint8_t uc_rc = GMAC_TIMEOUT;\r
+\r
+       gmac_enable_management(p_gmac, true);\r
+\r
+       ul_bmcr = GMII_RESET;\r
+       gmac_phy_write(p_gmac, uc_phy_address, GMII_BMCR, ul_bmcr);\r
+\r
+       do {\r
+               gmac_phy_read(p_gmac, uc_phy_address, GMII_BMCR, &ul_bmcr);\r
+               ul_timeout--;\r
+       } while ((ul_bmcr & GMII_RESET) && ul_timeout);\r
+\r
+       gmac_enable_management(p_gmac, false);\r
+\r
+       if (!ul_timeout) {\r
+               uc_rc = GMAC_OK;\r
+       }\r
+\r
+       return (uc_rc);\r
+}\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
+\r
+/**\r
+ * \}\r
+ */\r
index 6729df0fe280f7d1c2ff2102c1a825139deab11d..8ea5fa0c720aac048405c24158e80f3e5814cf43 100644 (file)
-/**
- * \file
- *
- * \brief KSZ8051MNL (Ethernet PHY) driver for SAM.
- *
- * Copyright (c) 2013 Atmel Corporation. All rights reserved.
- *
- * \asf_license_start
- *
- * \page License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *
- * 3. The name of Atmel may not be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * 4. This software may only be redistributed and used in connection with an
- *    Atmel microcontroller product.
- *
- * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
- * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * \asf_license_stop
- *
- */
-
-#ifndef ETHERNET_PHY_H_INCLUDED
-#define ETHERNET_PHY_H_INCLUDED
-
-#include "compiler.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// IEEE defined Registers
-#define GMII_BMCR        0x00   // Basic Control
-#define GMII_BMSR        0x01   // Basic Status
-#define GMII_PHYID1      0x02   // PHY Idendifier 1
-#define GMII_PHYID2      0x03   // PHY Idendifier 2
-#define GMII_ANAR        0x04   // Auto_Negotiation Advertisement
-#define GMII_ANLPAR      0x05   // Auto_negotiation Link Partner Ability
-#define GMII_ANER        0x06   // Auto-negotiation Expansion
-#define GMII_ANNPR       0x07   // Auto-negotiation Next Page
-#define GMII_ANLPNPAR    0x08   // Link Partner Next Page Ability
-//#define GMII_1000BTCR    9   // 1000Base-T Control  // Reserved
-//#define GMII_1000BTSR   10   // 1000Base-T Status   // Reserved
-#define GMII_AFECR1        0x11   // AFE Control 1
-//#define GMII_ERDWR      12   // Extend Register - Data Write Register
-//#define GMII_ERDRR      13   // Extend Register - Data Read Register
-//14    reserved
-#define GMII_RXERCR        0x15   // RXER Counter
-
-       #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_REG_05_LPA             0x05 // Link partner ability reg
-       #define PHY_REG_06_ANER            0x06 //      6       RW              Auto-Negotiation Expansion Register
-       #define PHY_REG_07_ANNPTR          0x07 //      7       RW              Auto-Negotiation Next Page TX
-       #define PHY_REG_08_RESERVED0       0x08 // 0x08..0x0Fh  8-15    RW              RESERVED
-
-       #define PHY_REG_10_PHYSTS     0x10      // 16   RO              PHY Status Register
-       #define PHY_REG_11_MICR       0x11      // 17   RW              MII Interrupt Control Register
-       #define PHY_REG_12_MISR       0x12      // 18   RO              MII Interrupt Status Register
-       #define PHY_REG_13_RESERVED1  0x13      // 19   RW              RESERVED
-       #define PHY_REG_14_FCSCR      0x14      // 20   RO              False Carrier Sense Counter Register
-       #define PHY_REG_15_RECR       0x15      // 21   RO              Receive Error Counter Register
-       #define PHY_REG_16_PCSR       0x16      // 22   RW              PCS Sub-Layer Configuration and Status Register
-       #define PHY_REG_17_RBR        0x17      // 23   RW              RMII and Bypass Register
-       #define PHY_REG_18_LEDCR      0x18      // 24   RW              LED Direct Control Register
-       #define PHY_REG_19_PHYCR      0x19      // 25   RW              PHY Control Register
-       #define PHY_REG_1A_10BTSCR    0x1A      // 26   RW              10Base-T Status/Control Register
-       #define PHY_REG_1B_CDCTRL1    0x1B      // 27   RW              CD Test Control Register and BIST Extensions Register
-       #define PHY_REG_1B_INT_CTRL   0x1B      // 27   RW              KSZ8041NL interrupt control
-       #define PHY_REG_1C_RESERVED2  0x1C      // 28   RW              RESERVED
-       #define PHY_REG_1D_EDCR       0x1D      // 29   RW              Energy Detect Control Register
-       #define PHY_REG_1E_RESERVED3  0x1E      //
-       #define PHY_REG_1F_RESERVED4  0x1F      // 30-31        RW              RESERVED
-
-       #define PHY_REG_1E_PHYCR_1    0x1E      //
-       #define PHY_REG_1F_PHYCR_2    0x1F      //
-
-       #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)
-
-       typedef struct _SPhyProps {
-               unsigned char speed;
-               unsigned char mdix;
-               unsigned char duplex;
-               unsigned char spare;
-       } SPhyProps;
-
-       const char *phyPrintable (const SPhyProps *apProps);
-
-       extern SPhyProps phyProps;
-
-#define GMII_OMSOR        0x16   // Operation Mode Strap Override
-#define GMII_OMSSR       0x17   // Operation Mode Strap Status
-#define GMII_ECR      0x18   // Expanded Control
-//#define GMII_DPPSR      19   // Digital PMA/PCS Status
-//20    reserved
-//#define GMII_RXERCR     21   // RXER Counter Register
-//22-26 reserved
-#define GMII_ICSR        0x1B   // Interrupt Control/Status
-//#define GMII_DDC1R       28   // Digital Debug Control 1 Register
-#define GMII_LCSR        0x1D   // LinkMD Control/Status
-
-//29-30 reserved
-#define GMII_PCR1       0x1E   // PHY Control 1
-#define GMII_PCR2       0x1F   // PHY Control 2
-
-/*
-//Extend Registers
-#define GMII_CCR        256  // Common Control Register
-#define GMII_SSR        257  // Strap Status Register
-#define GMII_OMSOR      258  // Operation Mode Strap Override Register
-#define GMII_OMSSR      259  // Operation Mode Strap Status Register
-#define GMII_RCCPSR     260  // RGMII Clock and Control Pad Skew Register
-#define GMII_RRDPSR     261  // RGMII RX Data Pad Skew Register
-#define GMII_ATR        263  // Analog Test Register
-*/
-
-
-// Bit definitions: GMII_BMCR 0x00 Basic Control
-#define GMII_RESET             (1 << 15) // 1= Software Reset; 0=Normal Operation
-#define GMII_LOOPBACK          (1 << 14) // 1=loopback Enabled; 0=Normal Operation
-#define GMII_SPEED_SELECT      (1 << 13) // 1=100Mbps; 0=10Mbps
-#define GMII_AUTONEG           (1 << 12) // Auto-negotiation Enable
-#define GMII_POWER_DOWN        (1 << 11) // 1=Power down 0=Normal operation
-#define GMII_ISOLATE           (1 << 10) // 1 = Isolates 0 = Normal operation
-#define GMII_RESTART_AUTONEG   (1 << 9)  // 1 = Restart auto-negotiation 0 = Normal operation
-#define GMII_DUPLEX_MODE       (1 << 8)  // 1 = Full duplex operation 0 = Normal operation
-#define GMII_COLLISION_TEST    (1 << 7)  // 1 = Enable COL test; 0 = Disable COL test
-//#define GMII_SPEED_SELECT_MSB  (1 << 6)  // Reserved
-//      Reserved                6 to 0   // Read as 0, ignore on write
-
-// Bit definitions: GMII_BMSR 0x01 Basic Status
-#define GMII_100BASE_T4        (1 << 15) // 100BASE-T4 Capable
-#define GMII_100BASE_TX_FD     (1 << 14) // 100BASE-TX Full Duplex Capable
-#define GMII_100BASE_T4_HD     (1 << 13) // 100BASE-TX Half Duplex Capable
-#define GMII_10BASE_T_FD       (1 << 12) // 10BASE-T Full Duplex Capable
-#define GMII_10BASE_T_HD       (1 << 11) // 10BASE-T Half Duplex Capable
-//      Reserved                10 to79  // Read as 0, ignore on write
-//#define GMII_EXTEND_STATUS     (1 << 8)  // 1 = Extend Status Information In Reg 15
-//      Reserved                7
-#define GMII_MF_PREAMB_SUPPR   (1 << 6)  // MII Frame Preamble Suppression
-#define GMII_AUTONEG_COMP      (1 << 5)  // Auto-negotiation Complete
-#define GMII_REMOTE_FAULT      (1 << 4)  // Remote Fault
-#define GMII_AUTONEG_ABILITY   (1 << 3)  // Auto Configuration Ability
-#define GMII_LINK_STATUS       (1 << 2)  // Link Status
-#define GMII_JABBER_DETECT     (1 << 1)  // Jabber Detect
-#define GMII_EXTEND_CAPAB      (1 << 0)  // Extended Capability
-
-
-// Bit definitions: GMII_PHYID1 0x02 PHY Idendifier 1
-// Bit definitions: GMII_PHYID2 0x03 PHY Idendifier 2
-#define GMII_LSB_MASK           0x3F
-#define GMII_OUI_MSB            0x0022
-#define GMII_OUI_LSB            0x05
-
-
-// Bit definitions: GMII_ANAR   0x04 Auto_Negotiation Advertisement
-// Bit definitions: GMII_ANLPAR 0x05 Auto_negotiation Link Partner Ability
-#define GMII_NP               (1 << 15) // Next page Indication
-//      Reserved               7
-#define GMII_RF               (1 << 13) // Remote Fault
-//      Reserved               12       // Write as 0, ignore on read
-#define GMII_PAUSE_MASK       (3 << 11) // 0,0 = No Pause 1,0 = Asymmetric Pause(link partner)
-                                        // 0,1 = Symmetric Pause 1,1 = Symmetric&Asymmetric Pause(local device)
-#define GMII_100T4               (1 << 9)  // 100BASE-T4 Support
-#define GMII_100TX_FDX           (1 << 8)  // 100BASE-TX Full Duplex Support
-#define GMII_100TX_HDX           (1 << 7)  // 100BASE-TX Support
-#define GMII_10_FDX           (1 << 6)  // 10BASE-T Full Duplex Support
-#define GMII_10_HDX           (1 << 5)  // 10BASE-T Support
-//      Selector                 4 to 0   // Protocol Selection Bits
-#define GMII_AN_IEEE_802_3      0x0001    // [00001] = IEEE 802.3
-
-
-// Bit definitions: GMII_ANER 0x06 Auto-negotiation Expansion
-//      Reserved                15 to 5  // Read as 0, ignore on write
-#define GMII_PDF              (1 << 4) // Local Device Parallel Detection Fault
-#define GMII_LP_NP_ABLE       (1 << 3) // Link Partner Next Page Able
-#define GMII_NP_ABLE          (1 << 2) // Local Device Next Page Able
-#define GMII_PAGE_RX          (1 << 1) // New Page Received
-#define GMII_LP_AN_ABLE       (1 << 0) // Link Partner Auto-negotiation Able
-
-/**
- * \brief Perform a HW initialization to the PHY and set up clocks.
- *
- * This should be called only once to initialize the PHY pre-settings.
- * The PHY address is the reset status of CRS, RXD[3:0] (the GmacPins' pullups).
- * The COL pin is used to select MII mode on reset (pulled up for Reduced MII).
- * The RXDV pin is used to select test mode on reset (pulled up for test mode).
- * The above pins should be predefined for corresponding settings in resetPins.
- * The GMAC peripheral pins are configured after the reset is done.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_phy_addr PHY address.
- * \param ul_mck GMAC MCK.
- *
- * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
- */
-uint8_t ethernet_phy_init(Gmac *p_gmac, uint8_t uc_phy_addr, uint32_t ul_mck);
-
-
-/**
- * \brief Get the Link & speed settings, and automatically set up the GMAC with the
- * settings.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_phy_addr PHY address.
- * \param uc_apply_setting_flag Set to 0 to not apply the PHY configurations, else to apply.
- *
- * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
- */
-uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr,
-               uint8_t uc_apply_setting_flag);
-
-
-/**
- * \brief Issue an auto negotiation of the PHY.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_phy_addr PHY address.
- *
- * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
- */
-uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr);
-
-/**
- * \brief Issue a SW reset to reset all registers of the PHY.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_phy_addr PHY address.
- *
- * \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
- */
-uint8_t ethernet_phy_reset(Gmac *p_gmac, uint8_t uc_phy_addr);
-
-typedef struct xPHY_PROPS {
-       signed char phy_result;
-       uint32_t phy_params;
-       uint32_t phy_stat1;
-       uint32_t phy_stat2;
-       unsigned char phy_chn;
-} PhyProps_t;
-extern PhyProps_t phy_props;
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* #ifndef ETHERNET_PHY_H_INCLUDED */
-
+/**\r
+ * \file\r
+ *\r
+ * \brief KSZ8051MNL (Ethernet PHY) driver for SAM.\r
+ *\r
+ * Copyright (c) 2013 Atmel Corporation. All rights reserved.\r
+ *\r
+ * \asf_license_start\r
+ *\r
+ * \page License\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ *    this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ *    this list of conditions and the following disclaimer in the documentation\r
+ *    and/or other materials provided with the distribution.\r
+ *\r
+ * 3. The name of Atmel may not be used to endorse or promote products derived\r
+ *    from this software without specific prior written permission.\r
+ *\r
+ * 4. This software may only be redistributed and used in connection with an\r
+ *    Atmel microcontroller product.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * \asf_license_stop\r
+ *\r
+ */\r
+\r
+#ifndef ETHERNET_PHY_H_INCLUDED\r
+#define ETHERNET_PHY_H_INCLUDED\r
+\r
+#include "compiler.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+// IEEE defined Registers\r
+#define GMII_BMCR        0x00   // Basic Control\r
+#define GMII_BMSR        0x01   // Basic Status\r
+#define GMII_PHYID1      0x02   // PHY Idendifier 1\r
+#define GMII_PHYID2      0x03   // PHY Idendifier 2\r
+#define GMII_ANAR        0x04   // Auto_Negotiation Advertisement\r
+#define GMII_ANLPAR      0x05   // Auto_negotiation Link Partner Ability\r
+#define GMII_ANER        0x06   // Auto-negotiation Expansion\r
+#define GMII_ANNPR       0x07   // Auto-negotiation Next Page\r
+#define GMII_ANLPNPAR    0x08   // Link Partner Next Page Ability\r
+//#define GMII_1000BTCR    9   // 1000Base-T Control  // Reserved\r
+//#define GMII_1000BTSR   10   // 1000Base-T Status   // Reserved\r
+#define GMII_AFECR1        0x11   // AFE Control 1\r
+//#define GMII_ERDWR      12   // Extend Register - Data Write Register\r
+//#define GMII_ERDRR      13   // Extend Register - Data Read Register\r
+//14    reserved\r
+#define GMII_RXERCR        0x15   // RXER Counter\r
+\r
+       #define PHY_REG_01_BMSR            0x01 // Basic mode status register\r
+       #define PHY_REG_02_PHYSID1         0x02 // PHYS ID 1\r
+       #define PHY_REG_03_PHYSID2         0x03 // PHYS ID 2\r
+       #define PHY_REG_04_ADVERTISE       0x04 // Advertisement control reg\r
+       #define PHY_REG_05_LPA             0x05 // Link partner ability reg\r
+       #define PHY_REG_06_ANER            0x06 //      6       RW              Auto-Negotiation Expansion Register\r
+       #define PHY_REG_07_ANNPTR          0x07 //      7       RW              Auto-Negotiation Next Page TX\r
+       #define PHY_REG_08_RESERVED0       0x08 // 0x08..0x0Fh  8-15    RW              RESERVED\r
+\r
+       #define PHY_REG_10_PHYSTS     0x10      // 16   RO              PHY Status Register\r
+       #define PHY_REG_11_MICR       0x11      // 17   RW              MII Interrupt Control Register\r
+       #define PHY_REG_12_MISR       0x12      // 18   RO              MII Interrupt Status Register\r
+       #define PHY_REG_13_RESERVED1  0x13      // 19   RW              RESERVED\r
+       #define PHY_REG_14_FCSCR      0x14      // 20   RO              False Carrier Sense Counter Register\r
+       #define PHY_REG_15_RECR       0x15      // 21   RO              Receive Error Counter Register\r
+       #define PHY_REG_16_PCSR       0x16      // 22   RW              PCS Sub-Layer Configuration and Status Register\r
+       #define PHY_REG_17_RBR        0x17      // 23   RW              RMII and Bypass Register\r
+       #define PHY_REG_18_LEDCR      0x18      // 24   RW              LED Direct Control Register\r
+       #define PHY_REG_19_PHYCR      0x19      // 25   RW              PHY Control Register\r
+       #define PHY_REG_1A_10BTSCR    0x1A      // 26   RW              10Base-T Status/Control Register\r
+       #define PHY_REG_1B_CDCTRL1    0x1B      // 27   RW              CD Test Control Register and BIST Extensions Register\r
+       #define PHY_REG_1B_INT_CTRL   0x1B      // 27   RW              KSZ8041NL interrupt control\r
+       #define PHY_REG_1C_RESERVED2  0x1C      // 28   RW              RESERVED\r
+       #define PHY_REG_1D_EDCR       0x1D      // 29   RW              Energy Detect Control Register\r
+       #define PHY_REG_1E_RESERVED3  0x1E      //\r
+       #define PHY_REG_1F_RESERVED4  0x1F      // 30-31        RW              RESERVED\r
+\r
+       #define PHY_REG_1E_PHYCR_1    0x1E      //\r
+       #define PHY_REG_1F_PHYCR_2    0x1F      //\r
+\r
+       #define PHY_SPEED_10       1\r
+       #define PHY_SPEED_100      2\r
+       #define PHY_SPEED_AUTO     (PHY_SPEED_10|PHY_SPEED_100)\r
+\r
+       #define PHY_MDIX_DIRECT    1\r
+       #define PHY_MDIX_CROSSED   2\r
+       #define PHY_MDIX_AUTO      (PHY_MDIX_CROSSED|PHY_MDIX_DIRECT)\r
+\r
+       #define PHY_DUPLEX_HALF    1\r
+       #define PHY_DUPLEX_FULL    2\r
+       #define PHY_DUPLEX_AUTO    (PHY_DUPLEX_FULL|PHY_DUPLEX_HALF)\r
+\r
+       typedef struct _SPhyProps {\r
+               unsigned char speed;\r
+               unsigned char mdix;\r
+               unsigned char duplex;\r
+               unsigned char spare;\r
+       } SPhyProps;\r
+\r
+       const char *phyPrintable (const SPhyProps *apProps);\r
+\r
+       extern SPhyProps phyProps;\r
+\r
+#define GMII_OMSOR        0x16   // Operation Mode Strap Override\r
+#define GMII_OMSSR       0x17   // Operation Mode Strap Status\r
+#define GMII_ECR      0x18   // Expanded Control\r
+//#define GMII_DPPSR      19   // Digital PMA/PCS Status\r
+//20    reserved\r
+//#define GMII_RXERCR     21   // RXER Counter Register\r
+//22-26 reserved\r
+#define GMII_ICSR        0x1B   // Interrupt Control/Status\r
+//#define GMII_DDC1R       28   // Digital Debug Control 1 Register\r
+#define GMII_LCSR        0x1D   // LinkMD Control/Status\r
+\r
+//29-30 reserved\r
+#define GMII_PCR1       0x1E   // PHY Control 1\r
+#define GMII_PCR2       0x1F   // PHY Control 2\r
+\r
+/*\r
+//Extend Registers\r
+#define GMII_CCR        256  // Common Control Register\r
+#define GMII_SSR        257  // Strap Status Register\r
+#define GMII_OMSOR      258  // Operation Mode Strap Override Register\r
+#define GMII_OMSSR      259  // Operation Mode Strap Status Register\r
+#define GMII_RCCPSR     260  // RGMII Clock and Control Pad Skew Register\r
+#define GMII_RRDPSR     261  // RGMII RX Data Pad Skew Register\r
+#define GMII_ATR        263  // Analog Test Register\r
+*/\r
+\r
+\r
+// Bit definitions: GMII_BMCR 0x00 Basic Control\r
+#define GMII_RESET             (1 << 15) // 1= Software Reset; 0=Normal Operation\r
+#define GMII_LOOPBACK          (1 << 14) // 1=loopback Enabled; 0=Normal Operation\r
+#define GMII_SPEED_SELECT      (1 << 13) // 1=100Mbps; 0=10Mbps\r
+#define GMII_AUTONEG           (1 << 12) // Auto-negotiation Enable\r
+#define GMII_POWER_DOWN        (1 << 11) // 1=Power down 0=Normal operation\r
+#define GMII_ISOLATE           (1 << 10) // 1 = Isolates 0 = Normal operation\r
+#define GMII_RESTART_AUTONEG   (1 << 9)  // 1 = Restart auto-negotiation 0 = Normal operation\r
+#define GMII_DUPLEX_MODE       (1 << 8)  // 1 = Full duplex operation 0 = Normal operation\r
+#define GMII_COLLISION_TEST    (1 << 7)  // 1 = Enable COL test; 0 = Disable COL test\r
+//#define GMII_SPEED_SELECT_MSB  (1 << 6)  // Reserved\r
+//      Reserved                6 to 0   // Read as 0, ignore on write\r
+\r
+// Bit definitions: GMII_BMSR 0x01 Basic Status\r
+#define GMII_100BASE_T4        (1 << 15) // 100BASE-T4 Capable\r
+#define GMII_100BASE_TX_FD     (1 << 14) // 100BASE-TX Full Duplex Capable\r
+#define GMII_100BASE_T4_HD     (1 << 13) // 100BASE-TX Half Duplex Capable\r
+#define GMII_10BASE_T_FD       (1 << 12) // 10BASE-T Full Duplex Capable\r
+#define GMII_10BASE_T_HD       (1 << 11) // 10BASE-T Half Duplex Capable\r
+//      Reserved                10 to79  // Read as 0, ignore on write\r
+//#define GMII_EXTEND_STATUS     (1 << 8)  // 1 = Extend Status Information In Reg 15\r
+//      Reserved                7\r
+#define GMII_MF_PREAMB_SUPPR   (1 << 6)  // MII Frame Preamble Suppression\r
+#define GMII_AUTONEG_COMP      (1 << 5)  // Auto-negotiation Complete\r
+#define GMII_REMOTE_FAULT      (1 << 4)  // Remote Fault\r
+#define GMII_AUTONEG_ABILITY   (1 << 3)  // Auto Configuration Ability\r
+#define GMII_LINK_STATUS       (1 << 2)  // Link Status\r
+#define GMII_JABBER_DETECT     (1 << 1)  // Jabber Detect\r
+#define GMII_EXTEND_CAPAB      (1 << 0)  // Extended Capability\r
+\r
+\r
+// Bit definitions: GMII_PHYID1 0x02 PHY Idendifier 1\r
+// Bit definitions: GMII_PHYID2 0x03 PHY Idendifier 2\r
+#define GMII_LSB_MASK           0x3F\r
+#define GMII_OUI_MSB            0x0022\r
+#define GMII_OUI_LSB            0x05\r
+\r
+\r
+// Bit definitions: GMII_ANAR   0x04 Auto_Negotiation Advertisement\r
+// Bit definitions: GMII_ANLPAR 0x05 Auto_negotiation Link Partner Ability\r
+#define GMII_NP               (1 << 15) // Next page Indication\r
+//      Reserved               7\r
+#define GMII_RF               (1 << 13) // Remote Fault\r
+//      Reserved               12       // Write as 0, ignore on read\r
+#define GMII_PAUSE_MASK       (3 << 11) // 0,0 = No Pause 1,0 = Asymmetric Pause(link partner)\r
+                                        // 0,1 = Symmetric Pause 1,1 = Symmetric&Asymmetric Pause(local device)\r
+#define GMII_100T4               (1 << 9)  // 100BASE-T4 Support\r
+#define GMII_100TX_FDX           (1 << 8)  // 100BASE-TX Full Duplex Support\r
+#define GMII_100TX_HDX           (1 << 7)  // 100BASE-TX Support\r
+#define GMII_10_FDX           (1 << 6)  // 10BASE-T Full Duplex Support\r
+#define GMII_10_HDX           (1 << 5)  // 10BASE-T Support\r
+//      Selector                 4 to 0   // Protocol Selection Bits\r
+#define GMII_AN_IEEE_802_3      0x0001    // [00001] = IEEE 802.3\r
+\r
+\r
+// Bit definitions: GMII_ANER 0x06 Auto-negotiation Expansion\r
+//      Reserved                15 to 5  // Read as 0, ignore on write\r
+#define GMII_PDF              (1 << 4) // Local Device Parallel Detection Fault\r
+#define GMII_LP_NP_ABLE       (1 << 3) // Link Partner Next Page Able\r
+#define GMII_NP_ABLE          (1 << 2) // Local Device Next Page Able\r
+#define GMII_PAGE_RX          (1 << 1) // New Page Received\r
+#define GMII_LP_AN_ABLE       (1 << 0) // Link Partner Auto-negotiation Able\r
+\r
+/**\r
+ * \brief Perform a HW initialization to the PHY and set up clocks.\r
+ *\r
+ * This should be called only once to initialize the PHY pre-settings.\r
+ * The PHY address is the reset status of CRS, RXD[3:0] (the GmacPins' pullups).\r
+ * The COL pin is used to select MII mode on reset (pulled up for Reduced MII).\r
+ * The RXDV pin is used to select test mode on reset (pulled up for test mode).\r
+ * The above pins should be predefined for corresponding settings in resetPins.\r
+ * The GMAC peripheral pins are configured after the reset is done.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ * \param ul_mck GMAC MCK.\r
+ *\r
+ * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_init(Gmac *p_gmac, uint8_t uc_phy_addr, uint32_t ul_mck);\r
+\r
+\r
+/**\r
+ * \brief Get the Link & speed settings, and automatically set up the GMAC with the\r
+ * settings.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ * \param uc_apply_setting_flag Set to 0 to not apply the PHY configurations, else to apply.\r
+ *\r
+ * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr,\r
+               uint8_t uc_apply_setting_flag);\r
+\r
+\r
+/**\r
+ * \brief Issue an auto negotiation of the PHY.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ *\r
+ * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr);\r
+\r
+/**\r
+ * \brief Issue a SW reset to reset all registers of the PHY.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ *\r
+ * \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_reset(Gmac *p_gmac, uint8_t uc_phy_addr);\r
+\r
+typedef struct xPHY_PROPS {\r
+       signed char phy_result;\r
+       uint32_t phy_params;\r
+       uint32_t phy_stat1;\r
+       uint32_t phy_stat2;\r
+       unsigned char phy_chn;\r
+} PhyProps_t;\r
+extern PhyProps_t phy_props;\r
+\r
+#ifdef __cplusplus\r
+} /* extern "C" */\r
+#endif\r
+\r
+#endif /* #ifndef ETHERNET_PHY_H_INCLUDED */\r
+\r
index e4a3ba988a3dc745b6eaf9a01ba7b2ca259f8dd5..948f9a661be10d631f958fb6fff813e81fb12ee4 100644 (file)
- /**
- * \file
- *
- * \brief GMAC (Ethernet MAC) driver for SAM.
- *
- * Copyright (c) 2013 Atmel Corporation. All rights reserved.
- *
- * \asf_license_start
- *
- * \page License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *
- * 3. The name of Atmel may not be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * 4. This software may only be redistributed and used in connection with an
- *    Atmel microcontroller product.
- *
- * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
- * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * \asf_license_stop
- *
- */
-
-/* Standard includes. */
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "task.h"
-
-#include "FreeRTOSIPConfig.h"
-
-#include "compiler.h"
-#include "instance/gmac.h"
-#include "ethernet_phy.h"
-
-/// @cond 0
-/**INDENT-OFF**/
-#ifdef __cplusplus
-extern "C" {
-#endif
-/**INDENT-ON**/
-/// @endcond
-
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(x)  (int)( sizeof(x) / sizeof(x)[0] )
-#endif
-/**
- * \defgroup gmac_group Ethernet Media Access Controller
- *
- * See \ref gmac_quickstart.
- *
- * Driver for the GMAC (Ethernet Media Access Controller).
- * This file contains basic functions for the GMAC, with support for all modes, settings
- * and clock speeds.
- *
- * \section dependencies Dependencies
- * This driver does not depend on other modules.
- *
- * @{
- */
-
-/** TX descriptor lists */
-COMPILER_ALIGNED(8)
-static gmac_tx_descriptor_t gs_tx_desc[ GMAC_TX_BUFFERS ];
-#if( GMAC_USES_TX_CALLBACK != 0 )
-/** TX callback lists */
-static gmac_dev_tx_cb_t gs_tx_callback[ GMAC_TX_BUFFERS ];
-#endif
-/** RX descriptors lists */
-COMPILER_ALIGNED(8)
-static gmac_rx_descriptor_t gs_rx_desc[ GMAC_RX_BUFFERS ];
-
-#if( ipconfigZERO_COPY_TX_DRIVER == 0 )
-       /** Send Buffer. Section 3.6 of AMBA 2.0 spec states that burst should not cross the
-        * 1K Boundaries. Receive buffer manager write operations are burst of 2 words => 3 lsb bits
-        * of the address shall be set to 0.
-        */
-       COMPILER_ALIGNED(8)
-       static uint8_t gs_uc_tx_buffer[ GMAC_TX_BUFFERS * GMAC_TX_UNITSIZE ];
-#endif /* ipconfigZERO_COPY_TX_DRIVER */
-
-/** Receive Buffer */
-COMPILER_ALIGNED(8)
-static uint8_t gs_uc_rx_buffer[ GMAC_RX_BUFFERS * GMAC_RX_UNITSIZE ];
-
-/**
- * GMAC device memory management struct.
- */
-typedef struct gmac_dev_mem {
-       /* Pointer to allocated buffer for RX. The address should be 8-byte aligned
-       and the size should be GMAC_RX_UNITSIZE * wRxSize. */
-       uint8_t *p_rx_buffer;
-       /* Pointer to allocated RX descriptor list. */
-       gmac_rx_descriptor_t *p_rx_dscr;
-       /* RX size, in number of registered units (RX descriptors). */
-       /* Increased size from 16- to 32-bits, because it's more efficient */
-       uint32_t us_rx_size;
-       /* Pointer to allocated buffer for TX. The address should be 8-byte aligned
-       and the size should be GMAC_TX_UNITSIZE * wTxSize. */
-       uint8_t *p_tx_buffer;
-       /* Pointer to allocated TX descriptor list. */
-       gmac_tx_descriptor_t *p_tx_dscr;
-       /* TX size, in number of registered units (TX descriptors). */
-       uint32_t us_tx_size;
-} gmac_dev_mem_t;
-
-/** Return count in buffer */
-#define CIRC_CNT( head, tail, size )           ( ( ( head ) - ( tail ) ) % ( size ) )
-
-/*
- * Return space available, from 0 to size-1.
- * Always leave one free char as a completely full buffer that has (head == tail),
- * which is the same as empty.
- */
-#define CIRC_SPACE( head, tail, size )         CIRC_CNT( ( tail ), ( ( head ) + 1 ), ( size ) )
-
-/** Circular buffer is empty ? */
-#define CIRC_EMPTY( head, tail )                       ( head == tail )
-/** Clear circular buffer */
-#define CIRC_CLEAR( head, tail )                       do { ( head ) = 0; ( tail ) = 0; } while( 0 )
-
-/** Increment head or tail */
-static __inline void circ_inc32( int32_t *lHeadOrTail, uint32_t ulSize )
-{
-       ( *lHeadOrTail ) ++;
-    if( ( *lHeadOrTail ) >= ( int32_t )ulSize )
-       {
-               ( *lHeadOrTail ) = 0;
-       }
-}
-
-/**
- * \brief Wait PHY operation to be completed.
- *
- * \param p_gmac HW controller address.
- * \param ul_retry The retry times, 0 to wait forever until completeness.
- *
- * Return GMAC_OK if the operation is completed successfully.
- */
-static uint8_t gmac_wait_phy(Gmac* p_gmac, const uint32_t ul_retry)
-{
-       volatile uint32_t ul_retry_count = 0;
-       const uint32_t xPHYPollDelay = pdMS_TO_TICKS( 1ul );
-
-       while (!gmac_is_phy_idle(p_gmac)) {
-               if (ul_retry == 0) {
-                       continue;
-               }
-
-               ul_retry_count++;
-
-               if (ul_retry_count >= ul_retry) {
-                       return GMAC_TIMEOUT;
-               }
-
-               /* Block the task to allow other tasks to execute while the PHY
-               is not connected. */
-               vTaskDelay( xPHYPollDelay );
-       }
-       return GMAC_OK;
-}
-
-/**
- * \brief Disable transfer, reset registers and descriptor lists.
- *
- * \param p_dev Pointer to GMAC driver instance.
- *
- */
-static void gmac_reset_tx_mem(gmac_device_t* p_dev)
-{
-       Gmac *p_hw = p_dev->p_hw;
-       uint8_t *p_tx_buff = p_dev->p_tx_buffer;
-       gmac_tx_descriptor_t *p_td = p_dev->p_tx_dscr;
-
-       uint32_t ul_index;
-       uint32_t ul_address;
-
-       /* Disable TX */
-       gmac_enable_transmit(p_hw, 0);
-
-       /* Set up the TX descriptors */
-       CIRC_CLEAR(p_dev->l_tx_head, p_dev->l_tx_tail);
-       for( ul_index = 0; ul_index < p_dev->ul_tx_list_size; ul_index++ )
-       {
-               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
-               {
-                       ul_address = (uint32_t) 0u;
-               }
-               #else
-               {
-                       ul_address = (uint32_t) (&(p_tx_buff[ul_index * GMAC_TX_UNITSIZE]));
-               }
-               #endif /* ipconfigZERO_COPY_TX_DRIVER */
-               p_td[ul_index].addr = ul_address;
-               p_td[ul_index].status.val = GMAC_TXD_USED;
-       }
-       p_td[p_dev->ul_tx_list_size - 1].status.val =
-                       GMAC_TXD_USED | GMAC_TXD_WRAP;
-
-       /* Set transmit buffer queue */
-       gmac_set_tx_queue(p_hw, (uint32_t) p_td);
-}
-
-/**
- * \brief Disable receiver, reset registers and descriptor list.
- *
- * \param p_drv Pointer to GMAC Driver instance.
- */
-static void gmac_reset_rx_mem(gmac_device_t* p_dev)
-{
-       Gmac *p_hw = p_dev->p_hw;
-       uint8_t *p_rx_buff = p_dev->p_rx_buffer;
-       gmac_rx_descriptor_t *pRd = p_dev->p_rx_dscr;
-
-       uint32_t ul_index;
-       uint32_t ul_address;
-
-       /* Disable RX */
-       gmac_enable_receive(p_hw, 0);
-
-       /* Set up the RX descriptors */
-       p_dev->ul_rx_idx = 0;
-       for( ul_index = 0; ul_index < p_dev->ul_rx_list_size; ul_index++ )
-       {
-               ul_address = (uint32_t) (&(p_rx_buff[ul_index * GMAC_RX_UNITSIZE]));
-               pRd[ul_index].addr.val = ul_address & GMAC_RXD_ADDR_MASK;
-               pRd[ul_index].status.val = 0;
-       }
-       pRd[p_dev->ul_rx_list_size - 1].addr.val |= GMAC_RXD_WRAP;
-
-       /* Set receive buffer queue */
-       gmac_set_rx_queue(p_hw, (uint32_t) pRd);
-}
-
-
-/**
- * \brief Initialize the allocated buffer lists for GMAC driver to transfer data.
- * Must be invoked after gmac_dev_init() but before RX/TX starts.
- *
- * \note If input address is not 8-byte aligned, the address is automatically
- *       adjusted and the list size is reduced by one.
- *
- * \param p_gmac Pointer to GMAC instance.
- * \param p_gmac_dev Pointer to GMAC device instance.
- * \param p_dev_mm Pointer to the GMAC memory management control block.
- * \param p_tx_cb Pointer to allocated TX callback list.
- *
- * \return GMAC_OK or GMAC_PARAM.
- */
-static uint8_t gmac_init_mem(Gmac* p_gmac, gmac_device_t* p_gmac_dev,
-               gmac_dev_mem_t* p_dev_mm
-#if( GMAC_USES_TX_CALLBACK != 0 )
-               , gmac_dev_tx_cb_t* p_tx_cb
-#endif
-               )
-{
-       if (p_dev_mm->us_rx_size <= 1 || p_dev_mm->us_tx_size <= 1
-#if( GMAC_USES_TX_CALLBACK != 0 )
-               || p_tx_cb == NULL
-#endif
-               ) {
-               return GMAC_PARAM;
-       }
-
-       /* Assign RX buffers */
-       if (((uint32_t) p_dev_mm->p_rx_buffer & 0x7)
-                       || ((uint32_t) p_dev_mm->p_rx_dscr & 0x7)) {
-               p_dev_mm->us_rx_size--;
-       }
-       p_gmac_dev->p_rx_buffer =
-                       (uint8_t *) ((uint32_t) p_dev_mm->p_rx_buffer & 0xFFFFFFF8);
-       p_gmac_dev->p_rx_dscr =
-                       (gmac_rx_descriptor_t *) ((uint32_t) p_dev_mm->p_rx_dscr
-                       & 0xFFFFFFF8);
-       p_gmac_dev->ul_rx_list_size = p_dev_mm->us_rx_size;
-
-       /* Assign TX buffers */
-       if (((uint32_t) p_dev_mm->p_tx_buffer & 0x7)
-                       || ((uint32_t) p_dev_mm->p_tx_dscr & 0x7)) {
-               p_dev_mm->us_tx_size--;
-       }
-       p_gmac_dev->p_tx_buffer =
-                       (uint8_t *) ((uint32_t) p_dev_mm->p_tx_buffer & 0xFFFFFFF8);
-       p_gmac_dev->p_tx_dscr =
-                       (gmac_tx_descriptor_t *) ((uint32_t) p_dev_mm->p_tx_dscr
-                       & 0xFFFFFFF8);
-       p_gmac_dev->ul_tx_list_size = p_dev_mm->us_tx_size;
-#if( GMAC_USES_TX_CALLBACK != 0 )
-       p_gmac_dev->func_tx_cb_list = p_tx_cb;
-#endif
-       /* Reset TX & RX */
-       gmac_reset_rx_mem(p_gmac_dev);
-       gmac_reset_tx_mem(p_gmac_dev);
-
-       /* Enable Rx and Tx, plus the statistics register */
-       gmac_enable_transmit(p_gmac, true);
-       gmac_enable_receive(p_gmac, true);
-       gmac_enable_statistics_write(p_gmac, true);
-
-       /* Set up the interrupts for transmission and errors */
-       gmac_enable_interrupt(p_gmac,
-                       GMAC_IER_RXUBR | /* Enable receive used bit read interrupt. */
-                       GMAC_IER_TUR   | /* Enable transmit underrun interrupt. */
-                       GMAC_IER_RLEX  | /* Enable retry limit  exceeded interrupt. */
-                       GMAC_IER_TFC   | /* Enable transmit buffers exhausted in mid-frame interrupt. */
-                       GMAC_IER_TCOMP | /* Enable transmit complete interrupt. */
-                       GMAC_IER_ROVR  | /* Enable receive overrun interrupt. */
-                       GMAC_IER_HRESP | /* Enable Hresp not OK interrupt. */
-                       GMAC_IER_PFNZ  | /* Enable pause frame received interrupt. */
-                       GMAC_IER_PTZ);   /* Enable pause time zero interrupt. */
-
-       return GMAC_OK;
-}
-
-/**
- * \brief Read the PHY register.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_phy_address PHY address.
- * \param uc_address Register address.
- * \param p_value Pointer to a 32-bit location to store read data.
- *
- * \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
- */
-uint8_t gmac_phy_read(Gmac* p_gmac, uint8_t uc_phy_address, uint8_t uc_address,
-               uint32_t* p_value)
-{
-       gmac_maintain_phy(p_gmac, uc_phy_address, uc_address, 1, 0);
-
-       if (gmac_wait_phy(p_gmac, MAC_PHY_RETRY_MAX) == GMAC_TIMEOUT) {
-               return GMAC_TIMEOUT;
-       }
-       *p_value = gmac_get_phy_data(p_gmac);
-       return GMAC_OK;
-}
-
-/**
- * \brief Write the PHY register.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_phy_address PHY Address.
- * \param uc_address Register Address.
- * \param ul_value Data to write, actually 16-bit data.
- *
- * \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
- */
-uint8_t gmac_phy_write(Gmac* p_gmac, uint8_t uc_phy_address,
-               uint8_t uc_address, uint32_t ul_value)
-{
-       gmac_maintain_phy(p_gmac, uc_phy_address, uc_address, 0, ul_value);
-
-       if (gmac_wait_phy(p_gmac, MAC_PHY_RETRY_MAX) == GMAC_TIMEOUT) {
-               return GMAC_TIMEOUT;
-       }
-       return GMAC_OK;
-}
-
-/**
- * \brief Initialize the GMAC driver.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param p_gmac_dev Pointer to the GMAC device instance.
- * \param p_opt GMAC configure options.
- */
-void gmac_dev_init(Gmac* p_gmac, gmac_device_t* p_gmac_dev,
-               gmac_options_t* p_opt)
-{
-       gmac_dev_mem_t gmac_dev_mm;
-
-       /* Disable TX & RX and more */
-       gmac_network_control(p_gmac, 0);
-       gmac_disable_interrupt(p_gmac, ~0u);
-
-
-       gmac_clear_statistics(p_gmac);
-
-       /* Clear all status bits in the receive status register. */
-       gmac_clear_rx_status(p_gmac, GMAC_RSR_RXOVR | GMAC_RSR_REC | GMAC_RSR_BNA);
-
-       /* Clear all status bits in the transmit status register */
-       gmac_clear_tx_status(p_gmac, GMAC_TSR_UBR | GMAC_TSR_COL | GMAC_TSR_RLE
-                       | GMAC_TSR_TFC | GMAC_TSR_TXCOMP | GMAC_TSR_UND);
-
-       /* Clear interrupts */
-       gmac_get_interrupt_status(p_gmac);
-#if !defined(ETHERNET_CONF_DATA_OFFSET)
-       /*  Receive Buffer Offset
-        * Indicates the number of bytes by which the received data
-        * is offset from the start of the receive buffer
-        * which can be handy for alignment reasons */
-       /* Note: FreeRTOS+TCP wants to have this offset set to 2 bytes */
-       #error ETHERNET_CONF_DATA_OFFSET not defined, assuming 0
-#endif
-       /* Enable the copy of data into the buffers
-          ignore broadcasts, and not copy FCS. */
-
-       gmac_set_configure(p_gmac,
-                       ( gmac_get_configure(p_gmac) & ~GMAC_NCFGR_RXBUFO_Msk ) |
-                       GMAC_NCFGR_RFCS |   /*  Remove FCS, frame check sequence (last 4 bytes) */
-                       GMAC_NCFGR_PEN |    /* Pause Enable */
-                       GMAC_NCFGR_RXBUFO( ETHERNET_CONF_DATA_OFFSET ) |
-                       GMAC_RXD_RXCOEN );
-
-       /*
-        * GMAC_DCFGR_TXCOEN: (GMAC_DCFGR) Transmitter Checksum Generation Offload Enable.
-        * Note: tha SAM4E does have RX checksum offloading
-        * but TX checksum offloading has NOT been implemented.
-        */
-
-       gmac_set_dma(p_gmac,
-                       gmac_get_dma(p_gmac) | GMAC_DCFGR_TXCOEN );
-
-       gmac_enable_copy_all(p_gmac, p_opt->uc_copy_all_frame);
-       gmac_disable_broadcast(p_gmac, p_opt->uc_no_boardcast);
-
-       /* Fill in GMAC device memory management */
-       gmac_dev_mm.p_rx_buffer = gs_uc_rx_buffer;
-       gmac_dev_mm.p_rx_dscr = gs_rx_desc;
-       gmac_dev_mm.us_rx_size = GMAC_RX_BUFFERS;
-
-       #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
-       {
-               gmac_dev_mm.p_tx_buffer = NULL;
-       }
-       #else
-       {
-               gmac_dev_mm.p_tx_buffer = gs_uc_tx_buffer;
-       }
-       #endif
-       gmac_dev_mm.p_tx_dscr = gs_tx_desc;
-       gmac_dev_mm.us_tx_size = GMAC_TX_BUFFERS;
-
-       gmac_init_mem(p_gmac, p_gmac_dev, &gmac_dev_mm
-#if( GMAC_USES_TX_CALLBACK != 0 )
-               , gs_tx_callback
-#endif
-               );
-
-       gmac_set_address(p_gmac, 0, p_opt->uc_mac_addr);
-}
-
-/**
- * \brief Frames can be read from the GMAC in multiple sections.
- *
- * Returns > 0 if a complete frame is available
- * It also it cleans up incomplete older frames
- */
-
-static uint32_t gmac_dev_poll(gmac_device_t* p_gmac_dev)
-{
-       uint32_t ulReturn = 0;
-       int32_t ulIndex = p_gmac_dev->ul_rx_idx;
-       gmac_rx_descriptor_t *pxHead = &p_gmac_dev->p_rx_dscr[ulIndex];
-
-       /* Discard any incomplete frames */
-       while ((pxHead->addr.val & GMAC_RXD_OWNERSHIP) &&
-                       (pxHead->status.val & GMAC_RXD_SOF) == 0) {
-               pxHead->addr.val &= ~(GMAC_RXD_OWNERSHIP);
-               circ_inc32 (&ulIndex, p_gmac_dev->ul_rx_list_size);
-               pxHead = &p_gmac_dev->p_rx_dscr[ulIndex];
-               p_gmac_dev->ul_rx_idx = ulIndex;
-               #if( GMAC_STATS != 0 )
-               {
-                       gmacStats.incompCount++;
-               }
-               #endif
-       }
-
-       while ((pxHead->addr.val & GMAC_RXD_OWNERSHIP) != 0) {
-               if ((pxHead->status.val & GMAC_RXD_EOF) != 0) {
-                       /* Here a complete frame has been seen with SOF and EOF */
-                       ulReturn = pxHead->status.bm.len;
-                       break;
-               }
-               circ_inc32 (&ulIndex, p_gmac_dev->ul_rx_list_size);
-               pxHead = &p_gmac_dev->p_rx_dscr[ulIndex];
-               if ((pxHead->addr.val & GMAC_RXD_OWNERSHIP) == 0) {
-                       /* CPU is not the owner (yet) */
-                       break;
-               }
-               if ((pxHead->status.val & GMAC_RXD_SOF) != 0) {
-                       /* Strange, we found a new Start Of Frame
-                        * discard previous segments */
-                       int32_t ulPrev = p_gmac_dev->ul_rx_idx;
-                       pxHead = &p_gmac_dev->p_rx_dscr[ulPrev];
-                       do {
-                               pxHead->addr.val &= ~(GMAC_RXD_OWNERSHIP);
-                               circ_inc32 (&ulPrev, p_gmac_dev->ul_rx_list_size);
-                               pxHead = &p_gmac_dev->p_rx_dscr[ulPrev];
-                               #if( GMAC_STATS != 0 )
-                               {
-                                       gmacStats.truncCount++;
-                               }
-                               #endif
-                       } while (ulPrev != ulIndex);
-                       p_gmac_dev->ul_rx_idx = ulIndex;
-               }
-       }
-       return ulReturn;
-}
-
-/**
- * \brief Frames can be read from the GMAC in multiple sections.
- * Read ul_frame_size bytes from the GMAC receive buffers to pcTo.
- * p_rcv_size is the size of the entire frame.  Generally gmac_read
- * will be repeatedly called until the sum of all the ul_frame_size equals
- * the value of p_rcv_size.
- *
- * \param p_gmac_dev Pointer to the GMAC device instance.
- * \param p_frame Address of the frame buffer.
- * \param ul_frame_size  Length of the frame.
- * \param p_rcv_size   Received frame size.
- *
- * \return GMAC_OK if receiving frame successfully, otherwise failed.
- */
-uint32_t gmac_dev_read(gmac_device_t* p_gmac_dev, uint8_t* p_frame,
-               uint32_t ul_frame_size, uint32_t* p_rcv_size)
-{
-       int32_t nextIdx;        /* A copy of the Rx-index 'ul_rx_idx' */
-       int32_t bytesLeft = gmac_dev_poll (p_gmac_dev);
-       gmac_rx_descriptor_t *pxHead;
-
-       if (bytesLeft == 0 )
-       {
-               return GMAC_RX_NULL;
-       }
-
-       /* gmac_dev_poll has confirmed that there is a complete frame at
-        * the current position 'ul_rx_idx'
-        */
-       nextIdx = p_gmac_dev->ul_rx_idx;
-
-       /* Read +2 bytes because buffers are aligned at -2 bytes */
-       bytesLeft = min( bytesLeft + 2, ( int32_t )ul_frame_size );
-
-       /* The frame will be copied in 1 or 2 memcpy's */
-       if( ( p_frame != NULL ) && ( bytesLeft != 0 ) )
-       {
-       const uint8_t *source;
-       int32_t left;
-       int32_t toCopy;
-
-               source = p_gmac_dev->p_rx_buffer + nextIdx * GMAC_RX_UNITSIZE;
-               left = bytesLeft;
-               toCopy = ( p_gmac_dev->ul_rx_list_size - nextIdx ) * GMAC_RX_UNITSIZE;
-               if(toCopy > left )
-               {
-                       toCopy = left;
-               }
-               memcpy (p_frame, source, toCopy);
-               left -= toCopy;
-
-               if( left != 0ul )
-               {
-                       memcpy (p_frame + toCopy, (void*)p_gmac_dev->p_rx_buffer, left);
-               }
-       }
-
-       do
-       {
-               pxHead = &p_gmac_dev->p_rx_dscr[nextIdx];
-               pxHead->addr.val &= ~(GMAC_RXD_OWNERSHIP);
-               circ_inc32 (&nextIdx, p_gmac_dev->ul_rx_list_size);
-       } while ((pxHead->status.val & GMAC_RXD_EOF) == 0);
-
-       p_gmac_dev->ul_rx_idx = nextIdx;
-
-       *p_rcv_size = bytesLeft;
-
-       return GMAC_OK;
-}
-
-
-extern void vGMACGenerateChecksum( uint8_t *apBuffer );
-
-/**
- * \brief Send ulLength bytes from pcFrom. This copies the buffer to one of the
- * GMAC Tx buffers, and then indicates to the GMAC that the buffer is ready.
- * If lEndOfFrame is true then the data being copied is the end of the frame
- * and the frame can be transmitted.
- *
- * \param p_gmac_dev Pointer to the GMAC device instance.
- * \param p_buffer       Pointer to the data buffer.
- * \param ul_size    Length of the frame.
- * \param func_tx_cb  Transmit callback function.
- *
- * \return Length sent.
- */
-uint32_t gmac_dev_write(gmac_device_t* p_gmac_dev, void *p_buffer,
-               uint32_t ul_size, gmac_dev_tx_cb_t func_tx_cb)
-{
-
-       volatile gmac_tx_descriptor_t *p_tx_td;
-#if( GMAC_USES_TX_CALLBACK != 0 )
-       volatile gmac_dev_tx_cb_t *p_func_tx_cb;
-#endif
-
-       Gmac *p_hw = p_gmac_dev->p_hw;
-
-#if( GMAC_USES_TX_CALLBACK == 0 )
-       ( void )func_tx_cb;
-#endif
-
-       /* Check parameter */
-       if (ul_size > GMAC_TX_UNITSIZE) {
-               return GMAC_PARAM;
-       }
-
-       /* Pointers to the current transmit descriptor */
-       p_tx_td = &p_gmac_dev->p_tx_dscr[p_gmac_dev->l_tx_head];
-
-       /* If no free TxTd, buffer can't be sent, schedule the wakeup callback */
-//     if (CIRC_SPACE(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail,
-//                                     p_gmac_dev->ul_tx_list_size) == 0)
-       {
-               if ((p_tx_td->status.val & GMAC_TXD_USED) == 0)
-                       return GMAC_TX_BUSY;
-       }
-#if( GMAC_USES_TX_CALLBACK != 0 )
-       /* Pointers to the current Tx callback */
-       p_func_tx_cb = &p_gmac_dev->func_tx_cb_list[p_gmac_dev->l_tx_head];
-#endif
-
-       /* Set up/copy data to transmission buffer */
-       if (p_buffer && ul_size) {
-               /* Driver manages the ring buffer */
-               /* Calculating the checksum here is faster than calculating it from the GMAC buffer
-                * because withing p_buffer, it is well aligned */
-               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
-               {
-                       /* Zero-copy... */
-                       p_tx_td->addr = ( uint32_t ) p_buffer;
-               }
-               #else
-               {
-                       /* Or Memcopy... */
-                       memcpy((void *)p_tx_td->addr, p_buffer, ul_size);
-               }
-               #endif /* ipconfigZERO_COPY_TX_DRIVER */
-               vGMACGenerateChecksum( ( uint8_t * ) p_tx_td->addr );
-       }
-
-#if( GMAC_USES_TX_CALLBACK != 0 )
-       /* Tx callback */
-       *p_func_tx_cb = func_tx_cb;
-#endif
-
-       /* Update transmit descriptor status */
-
-       /* The buffer size defined is the length of ethernet frame,
-          so it's always the last buffer of the frame. */
-       if( p_gmac_dev->l_tx_head == ( int32_t )( p_gmac_dev->ul_tx_list_size - 1 ) )
-       {
-               /* No need to 'and' with GMAC_TXD_LEN_MASK because ul_size has been checked */
-               p_tx_td->status.val =
-                       ul_size | GMAC_TXD_LAST | GMAC_TXD_WRAP;
-       } else {
-               p_tx_td->status.val =
-                       ul_size | GMAC_TXD_LAST;
-       }
-
-       circ_inc32( &p_gmac_dev->l_tx_head, p_gmac_dev->ul_tx_list_size );
-
-       /* Now start to transmit if it is still not done */
-       gmac_start_transmission(p_hw);
-
-       return GMAC_OK;
-}
-
-/**
- * \brief Get current load of transmit.
- *
- * \param p_gmac_dev Pointer to the GMAC device instance.
- *
- * \return Current load of transmit.
- */
-#if( GMAC_USES_TX_CALLBACK != 0 )
-/* Without defining GMAC_USES_TX_CALLBACK, l_tx_tail won't be updated */
-uint32_t gmac_dev_get_tx_load(gmac_device_t* p_gmac_dev)
-{
-       uint16_t us_head = p_gmac_dev->l_tx_head;
-       uint16_t us_tail = p_gmac_dev->l_tx_tail;
-       return CIRC_CNT(us_head, us_tail, p_gmac_dev->ul_tx_list_size);
-}
-#endif
-
-/**
- * \brief Register/Clear RX callback. Callback will be invoked after the next received
- * frame.
- *
- * When gmac_dev_read() returns GMAC_RX_NULL, the application task calls
- * gmac_dev_set_rx_callback() to register func_rx_cb() callback and enters suspend state.
- * The callback is in charge to resume the task once a new frame has been
- * received. The next time gmac_dev_read() is called, it will be successful.
- *
- * This function is usually invoked from the RX callback itself with NULL
- * callback, to unregister. Once the callback has resumed the application task,
- * there is no need to invoke the callback again.
- *
- * \param p_gmac_dev Pointer to the GMAC device instance.
- * \param func_tx_cb  Receive callback function.
- */
-void gmac_dev_set_rx_callback(gmac_device_t* p_gmac_dev,
-               gmac_dev_rx_cb_t func_rx_cb)
-{
-       Gmac *p_hw = p_gmac_dev->p_hw;
-
-       if (func_rx_cb == NULL) {
-               gmac_disable_interrupt(p_hw, GMAC_IDR_RCOMP);
-               p_gmac_dev->func_rx_cb = NULL;
-       } else {
-               p_gmac_dev->func_rx_cb = func_rx_cb;
-               gmac_enable_interrupt(p_hw, GMAC_IER_RCOMP);
-       }
-}
-
-/**
- *  \brief Register/Clear TX wakeup callback.
- *
- * When gmac_dev_write() returns GMAC_TX_BUSY (all transmit descriptor busy), the application
- * task calls gmac_dev_set_tx_wakeup_callback() to register func_wakeup() callback and
- * enters suspend state. The callback is in charge to resume the task once
- * several transmit descriptors have been released. The next time gmac_dev_write() will be called,
- * it shall be successful.
- *
- * This function is usually invoked with NULL callback from the TX wakeup
- * callback itself, to unregister. Once the callback has resumed the
- * application task, there is no need to invoke the callback again.
- *
- * \param p_gmac_dev   Pointer to GMAC device instance.
- * \param func_wakeup    Pointer to wakeup callback function.
- * \param uc_threshold Number of free transmit descriptor before wakeup callback invoked.
- *
- * \return GMAC_OK, GMAC_PARAM on parameter error.
- */
-#if( GMAC_USES_WAKEUP_CALLBACK )
-uint8_t gmac_dev_set_tx_wakeup_callback(gmac_device_t* p_gmac_dev,
-               gmac_dev_wakeup_cb_t func_wakeup_cb, uint8_t uc_threshold)
-{
-       if (func_wakeup_cb == NULL) {
-               p_gmac_dev->func_wakeup_cb = NULL;
-       } else {
-               if (uc_threshold <= p_gmac_dev->ul_tx_list_size) {
-                       p_gmac_dev->func_wakeup_cb = func_wakeup_cb;
-                       p_gmac_dev->uc_wakeup_threshold = uc_threshold;
-               } else {
-                       return GMAC_PARAM;
-               }
-       }
-
-       return GMAC_OK;
-}
-#endif /* GMAC_USES_WAKEUP_CALLBACK */
-
-/**
- * \brief Reset TX & RX queue & statistics.
- *
- * \param p_gmac_dev   Pointer to GMAC device instance.
- */
-void gmac_dev_reset(gmac_device_t* p_gmac_dev)
-{
-       Gmac *p_hw = p_gmac_dev->p_hw;
-
-       gmac_reset_rx_mem(p_gmac_dev);
-       gmac_reset_tx_mem(p_gmac_dev);
-       gmac_network_control(p_hw, GMAC_NCR_TXEN | GMAC_NCR_RXEN
-                       | GMAC_NCR_WESTAT | GMAC_NCR_CLRSTAT);
-}
-
-void gmac_dev_halt(Gmac* p_gmac);
-
-void gmac_dev_halt(Gmac* p_gmac)
-{
-       gmac_network_control(p_gmac, GMAC_NCR_WESTAT | GMAC_NCR_CLRSTAT);
-       gmac_disable_interrupt(p_gmac, ~0u);
-}
-
-
-/**
- * \brief GMAC Interrupt handler.
- *
- * \param p_gmac_dev   Pointer to GMAC device instance.
- */
-
-#if( GMAC_STATS != 0 )
-       extern int logPrintf( const char *pcFormat, ... );
-
-       void gmac_show_irq_counts ()
-       {
-               int index;
-               for (index = 0; index < ARRAY_SIZE(intPairs); index++) {
-                       if (gmacStats.intStatus[intPairs[index].index]) {
-                               logPrintf("%s : %6u\n", intPairs[index].name, gmacStats.intStatus[intPairs[index].index]);
-                       }
-               }
-       }
-#endif
-
-void gmac_handler(gmac_device_t* p_gmac_dev)
-{
-       Gmac *p_hw = p_gmac_dev->p_hw;
-
-#if( GMAC_USES_TX_CALLBACK != 0 )
-       gmac_tx_descriptor_t *p_tx_td;
-       gmac_dev_tx_cb_t *p_tx_cb = NULL;
-       uint32_t ul_tx_status_flag;
-#endif
-#if( GMAC_STATS != 0 )
-       int index;
-#endif
-
-       /* volatile */ uint32_t ul_isr;
-       /* volatile */ uint32_t ul_rsr;
-       /* volatile */ uint32_t ul_tsr;
-
-       ul_isr = gmac_get_interrupt_status(p_hw);
-       ul_rsr = gmac_get_rx_status(p_hw);
-       ul_tsr = gmac_get_tx_status(p_hw);
-
-/*     Why clear bits that are ignored anyway ? */
-/*     ul_isr &= ~(gmac_get_interrupt_mask(p_hw) | 0xF8030300); */
-       #if( GMAC_STATS != 0 )
-       {
-               for (index = 0; index < ARRAY_SIZE(intPairs); index++) {
-                       if (ul_isr & intPairs[index].mask)
-                               gmacStats.intStatus[intPairs[index].index]++;
-               }
-       }
-       #endif /* GMAC_STATS != 0 */
-
-       /* RX packet */
-       if ((ul_isr & GMAC_ISR_RCOMP) || (ul_rsr & (GMAC_RSR_REC|GMAC_RSR_RXOVR|GMAC_RSR_BNA))) {
-               /* Clear status */
-               gmac_clear_rx_status(p_hw, ul_rsr);
-
-               if (ul_isr & GMAC_ISR_RCOMP)
-                       ul_rsr |= GMAC_RSR_REC;
-               /* Invoke callbacks which can be useful to wake op a task */
-               if (p_gmac_dev->func_rx_cb) {
-                       p_gmac_dev->func_rx_cb(ul_rsr);
-               }
-       }
-
-       /* TX packet */
-       if ((ul_isr & GMAC_ISR_TCOMP) || (ul_tsr & (GMAC_TSR_TXCOMP|GMAC_TSR_COL|GMAC_TSR_RLE|GMAC_TSR_UND))) {
-
-#if( GMAC_USES_TX_CALLBACK != 0 )
-               ul_tx_status_flag = GMAC_TSR_TXCOMP;
-#endif
-               /* A frame transmitted */
-
-               /* Check RLE */
-               if (ul_tsr & GMAC_TSR_RLE) {
-                       /* Status RLE & Number of discarded buffers */
-#if( GMAC_USES_TX_CALLBACK != 0 )
-                       ul_tx_status_flag = GMAC_TSR_RLE | CIRC_CNT(p_gmac_dev->l_tx_head,
-                                       p_gmac_dev->l_tx_tail, p_gmac_dev->ul_tx_list_size);
-                       p_tx_cb = &p_gmac_dev->func_tx_cb_list[p_gmac_dev->l_tx_tail];
-#endif
-                       gmac_reset_tx_mem(p_gmac_dev);
-                       gmac_enable_transmit(p_hw, 1);
-               }
-               /* Clear status */
-               gmac_clear_tx_status(p_hw, ul_tsr);
-
-#if( GMAC_USES_TX_CALLBACK != 0 )
-               if (!CIRC_EMPTY(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail)) {
-                       /* Check the buffers */
-                       do {
-                               p_tx_td = &p_gmac_dev->p_tx_dscr[p_gmac_dev->l_tx_tail];
-                               p_tx_cb = &p_gmac_dev->func_tx_cb_list[p_gmac_dev->l_tx_tail];
-                               /* Any error? Exit if buffer has not been sent yet */
-                               if ((p_tx_td->status.val & GMAC_TXD_USED) == 0) {
-                                       break;
-                               }
-
-                               /* Notify upper layer that a packet has been sent */
-                               if (*p_tx_cb) {
-                                       (*p_tx_cb) (ul_tx_status_flag, (void*)p_tx_td->addr);
-                                       #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
-                                       {
-                                               p_tx_td->addr = 0ul;
-                                       }
-                                       #endif /* ipconfigZERO_COPY_TX_DRIVER */
-                               }
-
-                               circ_inc32(&p_gmac_dev->l_tx_tail, p_gmac_dev->ul_tx_list_size);
-                       } while (CIRC_CNT(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail,
-                                                       p_gmac_dev->ul_tx_list_size));
-               }
-
-               if (ul_tsr & GMAC_TSR_RLE) {
-                       /* Notify upper layer RLE */
-                       if (*p_tx_cb) {
-                               (*p_tx_cb) (ul_tx_status_flag, NULL);
-                       }
-               }
-#endif /* GMAC_USES_TX_CALLBACK */
-
-#if( GMAC_USES_WAKEUP_CALLBACK )
-               /* If a wakeup has been scheduled, notify upper layer that it can
-                  send other packets, and the sending will be successful. */
-               if ((CIRC_SPACE(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail,
-                               p_gmac_dev->ul_tx_list_size) >= p_gmac_dev->uc_wakeup_threshold)
-                               && p_gmac_dev->func_wakeup_cb) {
-                       p_gmac_dev->func_wakeup_cb();
-               }
-#endif
-       }
-}
-
-//@}
-
-/// @cond 0
-/**INDENT-OFF**/
-#ifdef __cplusplus
-}
-#endif
-/**INDENT-ON**/
-/// @endcond
+ /**\r
+ * \file\r
+ *\r
+ * \brief GMAC (Ethernet MAC) driver for SAM.\r
+ *\r
+ * Copyright (c) 2013 Atmel Corporation. All rights reserved.\r
+ *\r
+ * \asf_license_start\r
+ *\r
+ * \page License\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ *    this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ *    this list of conditions and the following disclaimer in the documentation\r
+ *    and/or other materials provided with the distribution.\r
+ *\r
+ * 3. The name of Atmel may not be used to endorse or promote products derived\r
+ *    from this software without specific prior written permission.\r
+ *\r
+ * 4. This software may only be redistributed and used in connection with an\r
+ *    Atmel microcontroller product.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * \asf_license_stop\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+\r
+#include "FreeRTOSIPConfig.h"\r
+\r
+#include "compiler.h"\r
+#include "instance/gmac.h"\r
+#include "ethernet_phy.h"\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
+\r
+#ifndef ARRAY_SIZE\r
+#define ARRAY_SIZE(x)  (int)( sizeof(x) / sizeof(x)[0] )\r
+#endif\r
+/**\r
+ * \defgroup gmac_group Ethernet Media Access Controller\r
+ *\r
+ * See \ref gmac_quickstart.\r
+ *\r
+ * Driver for the GMAC (Ethernet Media Access Controller).\r
+ * This file contains basic functions for the GMAC, with support for all modes, settings\r
+ * and clock speeds.\r
+ *\r
+ * \section dependencies Dependencies\r
+ * This driver does not depend on other modules.\r
+ *\r
+ * @{\r
+ */\r
+\r
+/** TX descriptor lists */\r
+COMPILER_ALIGNED(8)\r
+static gmac_tx_descriptor_t gs_tx_desc[ GMAC_TX_BUFFERS ];\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+/** TX callback lists */\r
+static gmac_dev_tx_cb_t gs_tx_callback[ GMAC_TX_BUFFERS ];\r
+#endif\r
+/** RX descriptors lists */\r
+COMPILER_ALIGNED(8)\r
+static gmac_rx_descriptor_t gs_rx_desc[ GMAC_RX_BUFFERS ];\r
+\r
+#if( ipconfigZERO_COPY_TX_DRIVER == 0 )\r
+       /** Send Buffer. Section 3.6 of AMBA 2.0 spec states that burst should not cross the\r
+        * 1K Boundaries. Receive buffer manager write operations are burst of 2 words => 3 lsb bits\r
+        * of the address shall be set to 0.\r
+        */\r
+       COMPILER_ALIGNED(8)\r
+       static uint8_t gs_uc_tx_buffer[ GMAC_TX_BUFFERS * GMAC_TX_UNITSIZE ];\r
+#endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+\r
+/** Receive Buffer */\r
+COMPILER_ALIGNED(8)\r
+static uint8_t gs_uc_rx_buffer[ GMAC_RX_BUFFERS * GMAC_RX_UNITSIZE ];\r
+\r
+/**\r
+ * GMAC device memory management struct.\r
+ */\r
+typedef struct gmac_dev_mem {\r
+       /* Pointer to allocated buffer for RX. The address should be 8-byte aligned\r
+       and the size should be GMAC_RX_UNITSIZE * wRxSize. */\r
+       uint8_t *p_rx_buffer;\r
+       /* Pointer to allocated RX descriptor list. */\r
+       gmac_rx_descriptor_t *p_rx_dscr;\r
+       /* RX size, in number of registered units (RX descriptors). */\r
+       /* Increased size from 16- to 32-bits, because it's more efficient */\r
+       uint32_t us_rx_size;\r
+       /* Pointer to allocated buffer for TX. The address should be 8-byte aligned\r
+       and the size should be GMAC_TX_UNITSIZE * wTxSize. */\r
+       uint8_t *p_tx_buffer;\r
+       /* Pointer to allocated TX descriptor list. */\r
+       gmac_tx_descriptor_t *p_tx_dscr;\r
+       /* TX size, in number of registered units (TX descriptors). */\r
+       uint32_t us_tx_size;\r
+} gmac_dev_mem_t;\r
+\r
+/** Return count in buffer */\r
+#define CIRC_CNT( head, tail, size )           ( ( ( head ) - ( tail ) ) % ( size ) )\r
+\r
+/*\r
+ * Return space available, from 0 to size-1.\r
+ * Always leave one free char as a completely full buffer that has (head == tail),\r
+ * which is the same as empty.\r
+ */\r
+#define CIRC_SPACE( head, tail, size )         CIRC_CNT( ( tail ), ( ( head ) + 1 ), ( size ) )\r
+\r
+/** Circular buffer is empty ? */\r
+#define CIRC_EMPTY( head, tail )                       ( head == tail )\r
+/** Clear circular buffer */\r
+#define CIRC_CLEAR( head, tail )                       do { ( head ) = 0; ( tail ) = 0; } while( 0 )\r
+\r
+/** Increment head or tail */\r
+static __inline void circ_inc32( int32_t *lHeadOrTail, uint32_t ulSize )\r
+{\r
+       ( *lHeadOrTail ) ++;\r
+    if( ( *lHeadOrTail ) >= ( int32_t )ulSize )\r
+       {\r
+               ( *lHeadOrTail ) = 0;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Wait PHY operation to be completed.\r
+ *\r
+ * \param p_gmac HW controller address.\r
+ * \param ul_retry The retry times, 0 to wait forever until completeness.\r
+ *\r
+ * Return GMAC_OK if the operation is completed successfully.\r
+ */\r
+static uint8_t gmac_wait_phy(Gmac* p_gmac, const uint32_t ul_retry)\r
+{\r
+       volatile uint32_t ul_retry_count = 0;\r
+       const uint32_t xPHYPollDelay = pdMS_TO_TICKS( 1ul );\r
+\r
+       while (!gmac_is_phy_idle(p_gmac)) {\r
+               if (ul_retry == 0) {\r
+                       continue;\r
+               }\r
+\r
+               ul_retry_count++;\r
+\r
+               if (ul_retry_count >= ul_retry) {\r
+                       return GMAC_TIMEOUT;\r
+               }\r
+\r
+               /* Block the task to allow other tasks to execute while the PHY\r
+               is not connected. */\r
+               vTaskDelay( xPHYPollDelay );\r
+       }\r
+       return GMAC_OK;\r
+}\r
+\r
+/**\r
+ * \brief Disable transfer, reset registers and descriptor lists.\r
+ *\r
+ * \param p_dev Pointer to GMAC driver instance.\r
+ *\r
+ */\r
+static void gmac_reset_tx_mem(gmac_device_t* p_dev)\r
+{\r
+       Gmac *p_hw = p_dev->p_hw;\r
+       uint8_t *p_tx_buff = p_dev->p_tx_buffer;\r
+       gmac_tx_descriptor_t *p_td = p_dev->p_tx_dscr;\r
+\r
+       uint32_t ul_index;\r
+       uint32_t ul_address;\r
+\r
+       /* Disable TX */\r
+       gmac_enable_transmit(p_hw, 0);\r
+\r
+       /* Set up the TX descriptors */\r
+       CIRC_CLEAR(p_dev->l_tx_head, p_dev->l_tx_tail);\r
+       for( ul_index = 0; ul_index < p_dev->ul_tx_list_size; ul_index++ )\r
+       {\r
+               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+               {\r
+                       ul_address = (uint32_t) 0u;\r
+               }\r
+               #else\r
+               {\r
+                       ul_address = (uint32_t) (&(p_tx_buff[ul_index * GMAC_TX_UNITSIZE]));\r
+               }\r
+               #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+               p_td[ul_index].addr = ul_address;\r
+               p_td[ul_index].status.val = GMAC_TXD_USED;\r
+       }\r
+       p_td[p_dev->ul_tx_list_size - 1].status.val =\r
+                       GMAC_TXD_USED | GMAC_TXD_WRAP;\r
+\r
+       /* Set transmit buffer queue */\r
+       gmac_set_tx_queue(p_hw, (uint32_t) p_td);\r
+}\r
+\r
+/**\r
+ * \brief Disable receiver, reset registers and descriptor list.\r
+ *\r
+ * \param p_drv Pointer to GMAC Driver instance.\r
+ */\r
+static void gmac_reset_rx_mem(gmac_device_t* p_dev)\r
+{\r
+       Gmac *p_hw = p_dev->p_hw;\r
+       uint8_t *p_rx_buff = p_dev->p_rx_buffer;\r
+       gmac_rx_descriptor_t *pRd = p_dev->p_rx_dscr;\r
+\r
+       uint32_t ul_index;\r
+       uint32_t ul_address;\r
+\r
+       /* Disable RX */\r
+       gmac_enable_receive(p_hw, 0);\r
+\r
+       /* Set up the RX descriptors */\r
+       p_dev->ul_rx_idx = 0;\r
+       for( ul_index = 0; ul_index < p_dev->ul_rx_list_size; ul_index++ )\r
+       {\r
+               ul_address = (uint32_t) (&(p_rx_buff[ul_index * GMAC_RX_UNITSIZE]));\r
+               pRd[ul_index].addr.val = ul_address & GMAC_RXD_ADDR_MASK;\r
+               pRd[ul_index].status.val = 0;\r
+       }\r
+       pRd[p_dev->ul_rx_list_size - 1].addr.val |= GMAC_RXD_WRAP;\r
+\r
+       /* Set receive buffer queue */\r
+       gmac_set_rx_queue(p_hw, (uint32_t) pRd);\r
+}\r
+\r
+\r
+/**\r
+ * \brief Initialize the allocated buffer lists for GMAC driver to transfer data.\r
+ * Must be invoked after gmac_dev_init() but before RX/TX starts.\r
+ *\r
+ * \note If input address is not 8-byte aligned, the address is automatically\r
+ *       adjusted and the list size is reduced by one.\r
+ *\r
+ * \param p_gmac Pointer to GMAC instance.\r
+ * \param p_gmac_dev Pointer to GMAC device instance.\r
+ * \param p_dev_mm Pointer to the GMAC memory management control block.\r
+ * \param p_tx_cb Pointer to allocated TX callback list.\r
+ *\r
+ * \return GMAC_OK or GMAC_PARAM.\r
+ */\r
+static uint8_t gmac_init_mem(Gmac* p_gmac, gmac_device_t* p_gmac_dev,\r
+               gmac_dev_mem_t* p_dev_mm\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+               , gmac_dev_tx_cb_t* p_tx_cb\r
+#endif\r
+               )\r
+{\r
+       if (p_dev_mm->us_rx_size <= 1 || p_dev_mm->us_tx_size <= 1\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+               || p_tx_cb == NULL\r
+#endif\r
+               ) {\r
+               return GMAC_PARAM;\r
+       }\r
+\r
+       /* Assign RX buffers */\r
+       if (((uint32_t) p_dev_mm->p_rx_buffer & 0x7)\r
+                       || ((uint32_t) p_dev_mm->p_rx_dscr & 0x7)) {\r
+               p_dev_mm->us_rx_size--;\r
+       }\r
+       p_gmac_dev->p_rx_buffer =\r
+                       (uint8_t *) ((uint32_t) p_dev_mm->p_rx_buffer & 0xFFFFFFF8);\r
+       p_gmac_dev->p_rx_dscr =\r
+                       (gmac_rx_descriptor_t *) ((uint32_t) p_dev_mm->p_rx_dscr\r
+                       & 0xFFFFFFF8);\r
+       p_gmac_dev->ul_rx_list_size = p_dev_mm->us_rx_size;\r
+\r
+       /* Assign TX buffers */\r
+       if (((uint32_t) p_dev_mm->p_tx_buffer & 0x7)\r
+                       || ((uint32_t) p_dev_mm->p_tx_dscr & 0x7)) {\r
+               p_dev_mm->us_tx_size--;\r
+       }\r
+       p_gmac_dev->p_tx_buffer =\r
+                       (uint8_t *) ((uint32_t) p_dev_mm->p_tx_buffer & 0xFFFFFFF8);\r
+       p_gmac_dev->p_tx_dscr =\r
+                       (gmac_tx_descriptor_t *) ((uint32_t) p_dev_mm->p_tx_dscr\r
+                       & 0xFFFFFFF8);\r
+       p_gmac_dev->ul_tx_list_size = p_dev_mm->us_tx_size;\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+       p_gmac_dev->func_tx_cb_list = p_tx_cb;\r
+#endif\r
+       /* Reset TX & RX */\r
+       gmac_reset_rx_mem(p_gmac_dev);\r
+       gmac_reset_tx_mem(p_gmac_dev);\r
+\r
+       /* Enable Rx and Tx, plus the statistics register */\r
+       gmac_enable_transmit(p_gmac, true);\r
+       gmac_enable_receive(p_gmac, true);\r
+       gmac_enable_statistics_write(p_gmac, true);\r
+\r
+       /* Set up the interrupts for transmission and errors */\r
+       gmac_enable_interrupt(p_gmac,\r
+                       GMAC_IER_RXUBR | /* Enable receive used bit read interrupt. */\r
+                       GMAC_IER_TUR   | /* Enable transmit underrun interrupt. */\r
+                       GMAC_IER_RLEX  | /* Enable retry limit  exceeded interrupt. */\r
+                       GMAC_IER_TFC   | /* Enable transmit buffers exhausted in mid-frame interrupt. */\r
+                       GMAC_IER_TCOMP | /* Enable transmit complete interrupt. */\r
+                       GMAC_IER_ROVR  | /* Enable receive overrun interrupt. */\r
+                       GMAC_IER_HRESP | /* Enable Hresp not OK interrupt. */\r
+                       GMAC_IER_PFNZ  | /* Enable pause frame received interrupt. */\r
+                       GMAC_IER_PTZ);   /* Enable pause time zero interrupt. */\r
+\r
+       return GMAC_OK;\r
+}\r
+\r
+/**\r
+ * \brief Read the PHY register.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_address PHY address.\r
+ * \param uc_address Register address.\r
+ * \param p_value Pointer to a 32-bit location to store read data.\r
+ *\r
+ * \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t gmac_phy_read(Gmac* p_gmac, uint8_t uc_phy_address, uint8_t uc_address,\r
+               uint32_t* p_value)\r
+{\r
+       gmac_maintain_phy(p_gmac, uc_phy_address, uc_address, 1, 0);\r
+\r
+       if (gmac_wait_phy(p_gmac, MAC_PHY_RETRY_MAX) == GMAC_TIMEOUT) {\r
+               return GMAC_TIMEOUT;\r
+       }\r
+       *p_value = gmac_get_phy_data(p_gmac);\r
+       return GMAC_OK;\r
+}\r
+\r
+/**\r
+ * \brief Write the PHY register.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_address PHY Address.\r
+ * \param uc_address Register Address.\r
+ * \param ul_value Data to write, actually 16-bit data.\r
+ *\r
+ * \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t gmac_phy_write(Gmac* p_gmac, uint8_t uc_phy_address,\r
+               uint8_t uc_address, uint32_t ul_value)\r
+{\r
+       gmac_maintain_phy(p_gmac, uc_phy_address, uc_address, 0, ul_value);\r
+\r
+       if (gmac_wait_phy(p_gmac, MAC_PHY_RETRY_MAX) == GMAC_TIMEOUT) {\r
+               return GMAC_TIMEOUT;\r
+       }\r
+       return GMAC_OK;\r
+}\r
+\r
+/**\r
+ * \brief Initialize the GMAC driver.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param p_gmac_dev Pointer to the GMAC device instance.\r
+ * \param p_opt GMAC configure options.\r
+ */\r
+void gmac_dev_init(Gmac* p_gmac, gmac_device_t* p_gmac_dev,\r
+               gmac_options_t* p_opt)\r
+{\r
+       gmac_dev_mem_t gmac_dev_mm;\r
+\r
+       /* Disable TX & RX and more */\r
+       gmac_network_control(p_gmac, 0);\r
+       gmac_disable_interrupt(p_gmac, ~0u);\r
+\r
+\r
+       gmac_clear_statistics(p_gmac);\r
+\r
+       /* Clear all status bits in the receive status register. */\r
+       gmac_clear_rx_status(p_gmac, GMAC_RSR_RXOVR | GMAC_RSR_REC | GMAC_RSR_BNA);\r
+\r
+       /* Clear all status bits in the transmit status register */\r
+       gmac_clear_tx_status(p_gmac, GMAC_TSR_UBR | GMAC_TSR_COL | GMAC_TSR_RLE\r
+                       | GMAC_TSR_TFC | GMAC_TSR_TXCOMP | GMAC_TSR_UND);\r
+\r
+       /* Clear interrupts */\r
+       gmac_get_interrupt_status(p_gmac);\r
+#if !defined(ETHERNET_CONF_DATA_OFFSET)\r
+       /*  Receive Buffer Offset\r
+        * Indicates the number of bytes by which the received data\r
+        * is offset from the start of the receive buffer\r
+        * which can be handy for alignment reasons */\r
+       /* Note: FreeRTOS+TCP wants to have this offset set to 2 bytes */\r
+       #error ETHERNET_CONF_DATA_OFFSET not defined, assuming 0\r
+#endif\r
+       /* Enable the copy of data into the buffers\r
+          ignore broadcasts, and not copy FCS. */\r
+\r
+       gmac_set_configure(p_gmac,\r
+                       ( gmac_get_configure(p_gmac) & ~GMAC_NCFGR_RXBUFO_Msk ) |\r
+                       GMAC_NCFGR_RFCS |   /*  Remove FCS, frame check sequence (last 4 bytes) */\r
+                       GMAC_NCFGR_PEN |    /* Pause Enable */\r
+                       GMAC_NCFGR_RXBUFO( ETHERNET_CONF_DATA_OFFSET ) |\r
+                       GMAC_RXD_RXCOEN );\r
+\r
+       /*\r
+        * GMAC_DCFGR_TXCOEN: (GMAC_DCFGR) Transmitter Checksum Generation Offload Enable.\r
+        * Note: tha SAM4E does have RX checksum offloading\r
+        * but TX checksum offloading has NOT been implemented.\r
+        */\r
+\r
+       gmac_set_dma(p_gmac,\r
+                       gmac_get_dma(p_gmac) | GMAC_DCFGR_TXCOEN );\r
+\r
+       gmac_enable_copy_all(p_gmac, p_opt->uc_copy_all_frame);\r
+       gmac_disable_broadcast(p_gmac, p_opt->uc_no_boardcast);\r
+\r
+       /* Fill in GMAC device memory management */\r
+       gmac_dev_mm.p_rx_buffer = gs_uc_rx_buffer;\r
+       gmac_dev_mm.p_rx_dscr = gs_rx_desc;\r
+       gmac_dev_mm.us_rx_size = GMAC_RX_BUFFERS;\r
+\r
+       #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+       {\r
+               gmac_dev_mm.p_tx_buffer = NULL;\r
+       }\r
+       #else\r
+       {\r
+               gmac_dev_mm.p_tx_buffer = gs_uc_tx_buffer;\r
+       }\r
+       #endif\r
+       gmac_dev_mm.p_tx_dscr = gs_tx_desc;\r
+       gmac_dev_mm.us_tx_size = GMAC_TX_BUFFERS;\r
+\r
+       gmac_init_mem(p_gmac, p_gmac_dev, &gmac_dev_mm\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+               , gs_tx_callback\r
+#endif\r
+               );\r
+\r
+       gmac_set_address(p_gmac, 0, p_opt->uc_mac_addr);\r
+}\r
+\r
+/**\r
+ * \brief Frames can be read from the GMAC in multiple sections.\r
+ *\r
+ * Returns > 0 if a complete frame is available\r
+ * It also it cleans up incomplete older frames\r
+ */\r
+\r
+static uint32_t gmac_dev_poll(gmac_device_t* p_gmac_dev)\r
+{\r
+       uint32_t ulReturn = 0;\r
+       int32_t ulIndex = p_gmac_dev->ul_rx_idx;\r
+       gmac_rx_descriptor_t *pxHead = &p_gmac_dev->p_rx_dscr[ulIndex];\r
+\r
+       /* Discard any incomplete frames */\r
+       while ((pxHead->addr.val & GMAC_RXD_OWNERSHIP) &&\r
+                       (pxHead->status.val & GMAC_RXD_SOF) == 0) {\r
+               pxHead->addr.val &= ~(GMAC_RXD_OWNERSHIP);\r
+               circ_inc32 (&ulIndex, p_gmac_dev->ul_rx_list_size);\r
+               pxHead = &p_gmac_dev->p_rx_dscr[ulIndex];\r
+               p_gmac_dev->ul_rx_idx = ulIndex;\r
+               #if( GMAC_STATS != 0 )\r
+               {\r
+                       gmacStats.incompCount++;\r
+               }\r
+               #endif\r
+       }\r
+\r
+       while ((pxHead->addr.val & GMAC_RXD_OWNERSHIP) != 0) {\r
+               if ((pxHead->status.val & GMAC_RXD_EOF) != 0) {\r
+                       /* Here a complete frame has been seen with SOF and EOF */\r
+                       ulReturn = pxHead->status.bm.len;\r
+                       break;\r
+               }\r
+               circ_inc32 (&ulIndex, p_gmac_dev->ul_rx_list_size);\r
+               pxHead = &p_gmac_dev->p_rx_dscr[ulIndex];\r
+               if ((pxHead->addr.val & GMAC_RXD_OWNERSHIP) == 0) {\r
+                       /* CPU is not the owner (yet) */\r
+                       break;\r
+               }\r
+               if ((pxHead->status.val & GMAC_RXD_SOF) != 0) {\r
+                       /* Strange, we found a new Start Of Frame\r
+                        * discard previous segments */\r
+                       int32_t ulPrev = p_gmac_dev->ul_rx_idx;\r
+                       pxHead = &p_gmac_dev->p_rx_dscr[ulPrev];\r
+                       do {\r
+                               pxHead->addr.val &= ~(GMAC_RXD_OWNERSHIP);\r
+                               circ_inc32 (&ulPrev, p_gmac_dev->ul_rx_list_size);\r
+                               pxHead = &p_gmac_dev->p_rx_dscr[ulPrev];\r
+                               #if( GMAC_STATS != 0 )\r
+                               {\r
+                                       gmacStats.truncCount++;\r
+                               }\r
+                               #endif\r
+                       } while (ulPrev != ulIndex);\r
+                       p_gmac_dev->ul_rx_idx = ulIndex;\r
+               }\r
+       }\r
+       return ulReturn;\r
+}\r
+\r
+/**\r
+ * \brief Frames can be read from the GMAC in multiple sections.\r
+ * Read ul_frame_size bytes from the GMAC receive buffers to pcTo.\r
+ * p_rcv_size is the size of the entire frame.  Generally gmac_read\r
+ * will be repeatedly called until the sum of all the ul_frame_size equals\r
+ * the value of p_rcv_size.\r
+ *\r
+ * \param p_gmac_dev Pointer to the GMAC device instance.\r
+ * \param p_frame Address of the frame buffer.\r
+ * \param ul_frame_size  Length of the frame.\r
+ * \param p_rcv_size   Received frame size.\r
+ *\r
+ * \return GMAC_OK if receiving frame successfully, otherwise failed.\r
+ */\r
+uint32_t gmac_dev_read(gmac_device_t* p_gmac_dev, uint8_t* p_frame,\r
+               uint32_t ul_frame_size, uint32_t* p_rcv_size)\r
+{\r
+       int32_t nextIdx;        /* A copy of the Rx-index 'ul_rx_idx' */\r
+       int32_t bytesLeft = gmac_dev_poll (p_gmac_dev);\r
+       gmac_rx_descriptor_t *pxHead;\r
+\r
+       if (bytesLeft == 0 )\r
+       {\r
+               return GMAC_RX_NULL;\r
+       }\r
+\r
+       /* gmac_dev_poll has confirmed that there is a complete frame at\r
+        * the current position 'ul_rx_idx'\r
+        */\r
+       nextIdx = p_gmac_dev->ul_rx_idx;\r
+\r
+       /* Read +2 bytes because buffers are aligned at -2 bytes */\r
+       bytesLeft = min( bytesLeft + 2, ( int32_t )ul_frame_size );\r
+\r
+       /* The frame will be copied in 1 or 2 memcpy's */\r
+       if( ( p_frame != NULL ) && ( bytesLeft != 0 ) )\r
+       {\r
+       const uint8_t *source;\r
+       int32_t left;\r
+       int32_t toCopy;\r
+\r
+               source = p_gmac_dev->p_rx_buffer + nextIdx * GMAC_RX_UNITSIZE;\r
+               left = bytesLeft;\r
+               toCopy = ( p_gmac_dev->ul_rx_list_size - nextIdx ) * GMAC_RX_UNITSIZE;\r
+               if(toCopy > left )\r
+               {\r
+                       toCopy = left;\r
+               }\r
+               memcpy (p_frame, source, toCopy);\r
+               left -= toCopy;\r
+\r
+               if( left != 0ul )\r
+               {\r
+                       memcpy (p_frame + toCopy, (void*)p_gmac_dev->p_rx_buffer, left);\r
+               }\r
+       }\r
+\r
+       do\r
+       {\r
+               pxHead = &p_gmac_dev->p_rx_dscr[nextIdx];\r
+               pxHead->addr.val &= ~(GMAC_RXD_OWNERSHIP);\r
+               circ_inc32 (&nextIdx, p_gmac_dev->ul_rx_list_size);\r
+       } while ((pxHead->status.val & GMAC_RXD_EOF) == 0);\r
+\r
+       p_gmac_dev->ul_rx_idx = nextIdx;\r
+\r
+       *p_rcv_size = bytesLeft;\r
+\r
+       return GMAC_OK;\r
+}\r
+\r
+\r
+extern void vGMACGenerateChecksum( uint8_t *apBuffer );\r
+\r
+/**\r
+ * \brief Send ulLength bytes from pcFrom. This copies the buffer to one of the\r
+ * GMAC Tx buffers, and then indicates to the GMAC that the buffer is ready.\r
+ * If lEndOfFrame is true then the data being copied is the end of the frame\r
+ * and the frame can be transmitted.\r
+ *\r
+ * \param p_gmac_dev Pointer to the GMAC device instance.\r
+ * \param p_buffer       Pointer to the data buffer.\r
+ * \param ul_size    Length of the frame.\r
+ * \param func_tx_cb  Transmit callback function.\r
+ *\r
+ * \return Length sent.\r
+ */\r
+uint32_t gmac_dev_write(gmac_device_t* p_gmac_dev, void *p_buffer,\r
+               uint32_t ul_size, gmac_dev_tx_cb_t func_tx_cb)\r
+{\r
+\r
+       volatile gmac_tx_descriptor_t *p_tx_td;\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+       volatile gmac_dev_tx_cb_t *p_func_tx_cb;\r
+#endif\r
+\r
+       Gmac *p_hw = p_gmac_dev->p_hw;\r
+\r
+#if( GMAC_USES_TX_CALLBACK == 0 )\r
+       ( void )func_tx_cb;\r
+#endif\r
+\r
+       /* Check parameter */\r
+       if (ul_size > GMAC_TX_UNITSIZE) {\r
+               return GMAC_PARAM;\r
+       }\r
+\r
+       /* Pointers to the current transmit descriptor */\r
+       p_tx_td = &p_gmac_dev->p_tx_dscr[p_gmac_dev->l_tx_head];\r
+\r
+       /* If no free TxTd, buffer can't be sent, schedule the wakeup callback */\r
+//     if (CIRC_SPACE(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail,\r
+//                                     p_gmac_dev->ul_tx_list_size) == 0)\r
+       {\r
+               if ((p_tx_td->status.val & GMAC_TXD_USED) == 0)\r
+                       return GMAC_TX_BUSY;\r
+       }\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+       /* Pointers to the current Tx callback */\r
+       p_func_tx_cb = &p_gmac_dev->func_tx_cb_list[p_gmac_dev->l_tx_head];\r
+#endif\r
+\r
+       /* Set up/copy data to transmission buffer */\r
+       if (p_buffer && ul_size) {\r
+               /* Driver manages the ring buffer */\r
+               /* Calculating the checksum here is faster than calculating it from the GMAC buffer\r
+                * because withing p_buffer, it is well aligned */\r
+               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+               {\r
+                       /* Zero-copy... */\r
+                       p_tx_td->addr = ( uint32_t ) p_buffer;\r
+               }\r
+               #else\r
+               {\r
+                       /* Or Memcopy... */\r
+                       memcpy((void *)p_tx_td->addr, p_buffer, ul_size);\r
+               }\r
+               #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+               vGMACGenerateChecksum( ( uint8_t * ) p_tx_td->addr );\r
+       }\r
+\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+       /* Tx callback */\r
+       *p_func_tx_cb = func_tx_cb;\r
+#endif\r
+\r
+       /* Update transmit descriptor status */\r
+\r
+       /* The buffer size defined is the length of ethernet frame,\r
+          so it's always the last buffer of the frame. */\r
+       if( p_gmac_dev->l_tx_head == ( int32_t )( p_gmac_dev->ul_tx_list_size - 1 ) )\r
+       {\r
+               /* No need to 'and' with GMAC_TXD_LEN_MASK because ul_size has been checked */\r
+               p_tx_td->status.val =\r
+                       ul_size | GMAC_TXD_LAST | GMAC_TXD_WRAP;\r
+       } else {\r
+               p_tx_td->status.val =\r
+                       ul_size | GMAC_TXD_LAST;\r
+       }\r
+\r
+       circ_inc32( &p_gmac_dev->l_tx_head, p_gmac_dev->ul_tx_list_size );\r
+\r
+       /* Now start to transmit if it is still not done */\r
+       gmac_start_transmission(p_hw);\r
+\r
+       return GMAC_OK;\r
+}\r
+\r
+/**\r
+ * \brief Get current load of transmit.\r
+ *\r
+ * \param p_gmac_dev Pointer to the GMAC device instance.\r
+ *\r
+ * \return Current load of transmit.\r
+ */\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+/* Without defining GMAC_USES_TX_CALLBACK, l_tx_tail won't be updated */\r
+uint32_t gmac_dev_get_tx_load(gmac_device_t* p_gmac_dev)\r
+{\r
+       uint16_t us_head = p_gmac_dev->l_tx_head;\r
+       uint16_t us_tail = p_gmac_dev->l_tx_tail;\r
+       return CIRC_CNT(us_head, us_tail, p_gmac_dev->ul_tx_list_size);\r
+}\r
+#endif\r
+\r
+/**\r
+ * \brief Register/Clear RX callback. Callback will be invoked after the next received\r
+ * frame.\r
+ *\r
+ * When gmac_dev_read() returns GMAC_RX_NULL, the application task calls\r
+ * gmac_dev_set_rx_callback() to register func_rx_cb() callback and enters suspend state.\r
+ * The callback is in charge to resume the task once a new frame has been\r
+ * received. The next time gmac_dev_read() is called, it will be successful.\r
+ *\r
+ * This function is usually invoked from the RX callback itself with NULL\r
+ * callback, to unregister. Once the callback has resumed the application task,\r
+ * there is no need to invoke the callback again.\r
+ *\r
+ * \param p_gmac_dev Pointer to the GMAC device instance.\r
+ * \param func_tx_cb  Receive callback function.\r
+ */\r
+void gmac_dev_set_rx_callback(gmac_device_t* p_gmac_dev,\r
+               gmac_dev_rx_cb_t func_rx_cb)\r
+{\r
+       Gmac *p_hw = p_gmac_dev->p_hw;\r
+\r
+       if (func_rx_cb == NULL) {\r
+               gmac_disable_interrupt(p_hw, GMAC_IDR_RCOMP);\r
+               p_gmac_dev->func_rx_cb = NULL;\r
+       } else {\r
+               p_gmac_dev->func_rx_cb = func_rx_cb;\r
+               gmac_enable_interrupt(p_hw, GMAC_IER_RCOMP);\r
+       }\r
+}\r
+\r
+/**\r
+ *  \brief Register/Clear TX wakeup callback.\r
+ *\r
+ * When gmac_dev_write() returns GMAC_TX_BUSY (all transmit descriptor busy), the application\r
+ * task calls gmac_dev_set_tx_wakeup_callback() to register func_wakeup() callback and\r
+ * enters suspend state. The callback is in charge to resume the task once\r
+ * several transmit descriptors have been released. The next time gmac_dev_write() will be called,\r
+ * it shall be successful.\r
+ *\r
+ * This function is usually invoked with NULL callback from the TX wakeup\r
+ * callback itself, to unregister. Once the callback has resumed the\r
+ * application task, there is no need to invoke the callback again.\r
+ *\r
+ * \param p_gmac_dev   Pointer to GMAC device instance.\r
+ * \param func_wakeup    Pointer to wakeup callback function.\r
+ * \param uc_threshold Number of free transmit descriptor before wakeup callback invoked.\r
+ *\r
+ * \return GMAC_OK, GMAC_PARAM on parameter error.\r
+ */\r
+#if( GMAC_USES_WAKEUP_CALLBACK )\r
+uint8_t gmac_dev_set_tx_wakeup_callback(gmac_device_t* p_gmac_dev,\r
+               gmac_dev_wakeup_cb_t func_wakeup_cb, uint8_t uc_threshold)\r
+{\r
+       if (func_wakeup_cb == NULL) {\r
+               p_gmac_dev->func_wakeup_cb = NULL;\r
+       } else {\r
+               if (uc_threshold <= p_gmac_dev->ul_tx_list_size) {\r
+                       p_gmac_dev->func_wakeup_cb = func_wakeup_cb;\r
+                       p_gmac_dev->uc_wakeup_threshold = uc_threshold;\r
+               } else {\r
+                       return GMAC_PARAM;\r
+               }\r
+       }\r
+\r
+       return GMAC_OK;\r
+}\r
+#endif /* GMAC_USES_WAKEUP_CALLBACK */\r
+\r
+/**\r
+ * \brief Reset TX & RX queue & statistics.\r
+ *\r
+ * \param p_gmac_dev   Pointer to GMAC device instance.\r
+ */\r
+void gmac_dev_reset(gmac_device_t* p_gmac_dev)\r
+{\r
+       Gmac *p_hw = p_gmac_dev->p_hw;\r
+\r
+       gmac_reset_rx_mem(p_gmac_dev);\r
+       gmac_reset_tx_mem(p_gmac_dev);\r
+       gmac_network_control(p_hw, GMAC_NCR_TXEN | GMAC_NCR_RXEN\r
+                       | GMAC_NCR_WESTAT | GMAC_NCR_CLRSTAT);\r
+}\r
+\r
+void gmac_dev_halt(Gmac* p_gmac);\r
+\r
+void gmac_dev_halt(Gmac* p_gmac)\r
+{\r
+       gmac_network_control(p_gmac, GMAC_NCR_WESTAT | GMAC_NCR_CLRSTAT);\r
+       gmac_disable_interrupt(p_gmac, ~0u);\r
+}\r
+\r
+\r
+/**\r
+ * \brief GMAC Interrupt handler.\r
+ *\r
+ * \param p_gmac_dev   Pointer to GMAC device instance.\r
+ */\r
+\r
+#if( GMAC_STATS != 0 )\r
+       extern int logPrintf( const char *pcFormat, ... );\r
+\r
+       void gmac_show_irq_counts ()\r
+       {\r
+               int index;\r
+               for (index = 0; index < ARRAY_SIZE(intPairs); index++) {\r
+                       if (gmacStats.intStatus[intPairs[index].index]) {\r
+                               logPrintf("%s : %6u\n", intPairs[index].name, gmacStats.intStatus[intPairs[index].index]);\r
+                       }\r
+               }\r
+       }\r
+#endif\r
+\r
+void gmac_handler(gmac_device_t* p_gmac_dev)\r
+{\r
+       Gmac *p_hw = p_gmac_dev->p_hw;\r
+\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+       gmac_tx_descriptor_t *p_tx_td;\r
+       gmac_dev_tx_cb_t *p_tx_cb = NULL;\r
+       uint32_t ul_tx_status_flag;\r
+#endif\r
+#if( GMAC_STATS != 0 )\r
+       int index;\r
+#endif\r
+\r
+       /* volatile */ uint32_t ul_isr;\r
+       /* volatile */ uint32_t ul_rsr;\r
+       /* volatile */ uint32_t ul_tsr;\r
+\r
+       ul_isr = gmac_get_interrupt_status(p_hw);\r
+       ul_rsr = gmac_get_rx_status(p_hw);\r
+       ul_tsr = gmac_get_tx_status(p_hw);\r
+\r
+/*     Why clear bits that are ignored anyway ? */\r
+/*     ul_isr &= ~(gmac_get_interrupt_mask(p_hw) | 0xF8030300); */\r
+       #if( GMAC_STATS != 0 )\r
+       {\r
+               for (index = 0; index < ARRAY_SIZE(intPairs); index++) {\r
+                       if (ul_isr & intPairs[index].mask)\r
+                               gmacStats.intStatus[intPairs[index].index]++;\r
+               }\r
+       }\r
+       #endif /* GMAC_STATS != 0 */\r
+\r
+       /* RX packet */\r
+       if ((ul_isr & GMAC_ISR_RCOMP) || (ul_rsr & (GMAC_RSR_REC|GMAC_RSR_RXOVR|GMAC_RSR_BNA))) {\r
+               /* Clear status */\r
+               gmac_clear_rx_status(p_hw, ul_rsr);\r
+\r
+               if (ul_isr & GMAC_ISR_RCOMP)\r
+                       ul_rsr |= GMAC_RSR_REC;\r
+               /* Invoke callbacks which can be useful to wake op a task */\r
+               if (p_gmac_dev->func_rx_cb) {\r
+                       p_gmac_dev->func_rx_cb(ul_rsr);\r
+               }\r
+       }\r
+\r
+       /* TX packet */\r
+       if ((ul_isr & GMAC_ISR_TCOMP) || (ul_tsr & (GMAC_TSR_TXCOMP|GMAC_TSR_COL|GMAC_TSR_RLE|GMAC_TSR_UND))) {\r
+\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+               ul_tx_status_flag = GMAC_TSR_TXCOMP;\r
+#endif\r
+               /* A frame transmitted */\r
+\r
+               /* Check RLE */\r
+               if (ul_tsr & GMAC_TSR_RLE) {\r
+                       /* Status RLE & Number of discarded buffers */\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+                       ul_tx_status_flag = GMAC_TSR_RLE | CIRC_CNT(p_gmac_dev->l_tx_head,\r
+                                       p_gmac_dev->l_tx_tail, p_gmac_dev->ul_tx_list_size);\r
+                       p_tx_cb = &p_gmac_dev->func_tx_cb_list[p_gmac_dev->l_tx_tail];\r
+#endif\r
+                       gmac_reset_tx_mem(p_gmac_dev);\r
+                       gmac_enable_transmit(p_hw, 1);\r
+               }\r
+               /* Clear status */\r
+               gmac_clear_tx_status(p_hw, ul_tsr);\r
+\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+               if (!CIRC_EMPTY(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail)) {\r
+                       /* Check the buffers */\r
+                       do {\r
+                               p_tx_td = &p_gmac_dev->p_tx_dscr[p_gmac_dev->l_tx_tail];\r
+                               p_tx_cb = &p_gmac_dev->func_tx_cb_list[p_gmac_dev->l_tx_tail];\r
+                               /* Any error? Exit if buffer has not been sent yet */\r
+                               if ((p_tx_td->status.val & GMAC_TXD_USED) == 0) {\r
+                                       break;\r
+                               }\r
+\r
+                               /* Notify upper layer that a packet has been sent */\r
+                               if (*p_tx_cb) {\r
+                                       (*p_tx_cb) (ul_tx_status_flag, (void*)p_tx_td->addr);\r
+                                       #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+                                       {\r
+                                               p_tx_td->addr = 0ul;\r
+                                       }\r
+                                       #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+                               }\r
+\r
+                               circ_inc32(&p_gmac_dev->l_tx_tail, p_gmac_dev->ul_tx_list_size);\r
+                       } while (CIRC_CNT(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail,\r
+                                                       p_gmac_dev->ul_tx_list_size));\r
+               }\r
+\r
+               if (ul_tsr & GMAC_TSR_RLE) {\r
+                       /* Notify upper layer RLE */\r
+                       if (*p_tx_cb) {\r
+                               (*p_tx_cb) (ul_tx_status_flag, NULL);\r
+                       }\r
+               }\r
+#endif /* GMAC_USES_TX_CALLBACK */\r
+\r
+#if( GMAC_USES_WAKEUP_CALLBACK )\r
+               /* If a wakeup has been scheduled, notify upper layer that it can\r
+                  send other packets, and the sending will be successful. */\r
+               if ((CIRC_SPACE(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail,\r
+                               p_gmac_dev->ul_tx_list_size) >= p_gmac_dev->uc_wakeup_threshold)\r
+                               && p_gmac_dev->func_wakeup_cb) {\r
+                       p_gmac_dev->func_wakeup_cb();\r
+               }\r
+#endif\r
+       }\r
+}\r
+\r
+//@}\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
index d741a2a0a96c038ce58f56578a18868a39b5c8f2..fca3ece332a456b2d3c3b40a8a6bc7c2965b7fb4 100644 (file)
- /**
- * \file
- *
- * \brief GMAC (Ethernet MAC) driver for SAM.
- *
- * Copyright (c) 2013 Atmel Corporation. All rights reserved.
- *
- * \asf_license_start
- *
- * \page License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *
- * 3. The name of Atmel may not be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * 4. This software may only be redistributed and used in connection with an
- *    Atmel microcontroller product.
- *
- * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
- * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * \asf_license_stop
- *
- */
-
-#ifndef GMAC_H_INCLUDED
-#define GMAC_H_INCLUDED
-
-#include "compiler.h"
-
-/// @cond 0
-/**INDENT-OFF**/
-#ifdef __cplusplus
-extern "C" {
-#endif
-/**INDENT-ON**/
-/// @endcond
-
-/** The buffer addresses written into the descriptors must be aligned, so the
-    last few bits are zero.  These bits have special meaning for the GMAC
-    peripheral and cannot be used as part of the address. */
-#define GMAC_RXD_ADDR_MASK      0xFFFFFFFC
-#define GMAC_RXD_WRAP         (1ul << 1)  /**< Wrap bit */
-#define GMAC_RXD_OWNERSHIP    (1ul << 0)  /**< Ownership bit */
-
-#define GMAC_RXD_BROADCAST    (1ul << 31) /**< Broadcast detected */
-#define GMAC_RXD_MULTIHASH    (1ul << 30) /**< Multicast hash match */
-#define GMAC_RXD_UNIHASH      (1ul << 29) /**< Unicast hash match */
-#define GMAC_RXD_ADDR_FOUND      (1ul << 27) /**< Specific address match found */
-#define GMAC_RXD_ADDR        (3ul << 25) /**< Address match */
-#define GMAC_RXD_RXCOEN        (1ul << 24) /**< RXCOEN related function */
-#define GMAC_RXD_TYPE         (3ul << 22) /**< Type ID match */
-#define GMAC_RXD_VLAN         (1ul << 21) /**< VLAN tag detected */
-#define GMAC_RXD_PRIORITY     (1ul << 20) /**< Priority tag detected */
-#define GMAC_RXD_PRIORITY_MASK  (3ul << 17) /**< VLAN priority */
-#define GMAC_RXD_CFI          (1ul << 16) /**< Concatenation Format Indicator only if bit 21 is set */
-#define GMAC_RXD_EOF          (1ul << 15) /**< End of frame */
-#define GMAC_RXD_SOF          (1ul << 14) /**< Start of frame */
-#define GMAC_RXD_FCS          (1ul << 13) /**< Frame check sequence */
-#define GMAC_RXD_OFFSET_MASK                /**< Receive buffer offset */
-#define GMAC_RXD_LEN_MASK       (0xFFF)     /**< Length of frame including FCS (if selected) */
-#define GMAC_RXD_LENJUMBO_MASK  (0x3FFF)    /**< Jumbo frame length */
-
-#define GMAC_TXD_USED         (1ul << 31) /**< Frame is transmitted */
-#define GMAC_TXD_WRAP         (1ul << 30) /**< Last descriptor */
-#define GMAC_TXD_ERROR        (1ul << 29) /**< Retry limit exceeded, error */
-#define GMAC_TXD_UNDERRUN     (1ul << 28) /**< Transmit underrun */
-#define GMAC_TXD_EXHAUSTED    (1ul << 27) /**< Buffer exhausted */
-#define GMAC_TXD_LATE    (1ul << 26) /**< Late collision,transmit  error  */
-#define GMAC_TXD_CHECKSUM_ERROR   (7ul << 20) /**< Checksum error */
-#define GMAC_TXD_NOCRC        (1ul << 16) /**< No CRC */
-#define GMAC_TXD_LAST         (1ul << 15) /**< Last buffer in frame */
-#define GMAC_TXD_LEN_MASK       (0x1FFF)     /**< Length of buffer */
-
-/** The MAC can support frame lengths up to 1536 bytes */
-#define GMAC_FRAME_LENTGH_MAX       1536
-
-#define GMAC_RX_UNITSIZE            128     /**< Fixed size for RX buffer  */
-#define GMAC_TX_UNITSIZE            1518    /**< Size for ETH frame length */
-
-/** GMAC clock speed */
-#define GMAC_MCK_SPEED_240MHZ        (240*1000*1000)
-#define GMAC_MCK_SPEED_160MHZ        (160*1000*1000)
-#define GMAC_MCK_SPEED_120MHZ        (120*1000*1000)
-#define GMAC_MCK_SPEED_80MHZ          (80*1000*1000)
-#define GMAC_MCK_SPEED_40MHZ          (40*1000*1000)
-#define GMAC_MCK_SPEED_20MHZ          (20*1000*1000)
-
-/** GMAC maintain code default value*/
-#define GMAC_MAN_CODE_VALUE    (10)
-
-/** GMAC maintain start of frame default value*/
-#define GMAC_MAN_SOF_VALUE     (1)
-
-/** GMAC maintain read/write*/
-#define GMAC_MAN_RW_TYPE       (2)
-
-/** GMAC maintain read only*/
-#define GMAC_MAN_READ_ONLY     (1)
-
-/** GMAC address length */
-#define GMAC_ADDR_LENGTH       (6)
-
-
-#define GMAC_DUPLEX_HALF 0
-#define GMAC_DUPLEX_FULL 1
-
-#define GMAC_SPEED_10M      0
-#define GMAC_SPEED_100M     1
-
-/**
- * \brief Return codes for GMAC APIs.
- */
-typedef enum {
-       GMAC_OK = 0,         /** 0  Operation OK */
-       GMAC_TIMEOUT = 1,    /** 1  GMAC operation timeout */
-       GMAC_TX_BUSY,        /** 2  TX in progress */
-       GMAC_RX_NULL,        /** 3  No data received */
-       GMAC_SIZE_TOO_SMALL, /** 4  Buffer size not enough */
-       GMAC_PARAM,          /** 5  Parameter error, TX packet invalid or RX size too small */
-       GMAC_INVALID = 0xFF, /* Invalid */
-} gmac_status_t;
-
-/**
- * \brief Media Independent Interface (MII) type.
- */
-typedef enum {
-       GMAC_PHY_MII = 0,         /** MII mode */
-       GMAC_PHY_RMII = 1,    /** Reduced MII mode */
-       GMAC_PHY_INVALID = 0xFF, /* Invalid mode*/
-} gmac_mii_mode_t;
-
-/** Receive buffer descriptor struct */
-COMPILER_PACK_SET(8)
-typedef struct gmac_rx_descriptor {
-       union gmac_rx_addr {
-               uint32_t val;
-               struct gmac_rx_addr_bm {
-                       uint32_t b_ownership:1, /**< User clear, GMAC sets this to 1 once it has successfully written a frame to memory */
-                       b_wrap:1,   /**< Marks last descriptor in receive buffer */
-                       addr_dw:30; /**< Address in number of DW */
-               } bm;
-       } addr; /**< Address, Wrap & Ownership */
-       union gmac_rx_status {
-               uint32_t val;
-               struct gmac_rx_status_bm {
-                       uint32_t len:13,       /**  0..12  Length of frame including FCS */
-                       b_fcs:1,               /**  13     Receive buffer offset,  bits 13:12 of frame length for jumbo frame */
-                       b_sof:1,               /**  14     Start of frame */
-                       b_eof:1,               /**  15     End of frame */
-                       b_cfi:1,               /**  16     Concatenation Format Indicator */
-                       vlan_priority:3,       /**  17..19 VLAN priority (if VLAN detected) */
-                       b_priority_detected:1, /**  20     Priority tag detected */
-                       b_vlan_detected:1,     /**  21     VLAN tag detected */
-                       b_type_id_match:2,     /**  22..23 Type ID match */
-                       b_checksumoffload:1,   /**  24     Checksum offload specific function */
-                       b_addrmatch:2,         /**  25..26 Address register match */
-                       b_ext_addr_match:1,    /**  27     External address match found */
-                       reserved:1,            /**  28     */
-                       b_uni_hash_match:1,    /**  29     Unicast hash match */
-                       b_multi_hash_match:1,  /**  30     Multicast hash match */
-                       b_boardcast_detect:1;  /**  31     Global broadcast address detected */
-               } bm;
-       } status;
-} gmac_rx_descriptor_t;
-
-/** Transmit buffer descriptor struct */
-COMPILER_PACK_SET(8)
-typedef struct gmac_tx_descriptor {
-       uint32_t addr;
-       union gmac_tx_status {
-               uint32_t val;
-               struct gmac_tx_status_bm {
-                       uint32_t len:14,     /**  0..13 Length of buffer */
-                       reserved:1,          /** 14            */
-                       b_last_buffer:1,     /** 15     Last buffer (in the current frame) */
-                       b_no_crc:1,          /** 16     No CRC */
-                       reserved1:3,         /** 17..19        */
-                       b_checksumoffload:3, /** 20..22 Transmit checksum generation offload errors */
-                       reserved2:3,         /** 23..25        */
-                       b_lco:1,             /** 26     Late collision, transmit error detected */
-                       b_exhausted:1,       /** 27     Buffer exhausted in mid frame */
-                       b_underrun:1,        /** 28     Transmit underrun */
-                       b_error:1,           /** 29     Retry limit exceeded, error detected */
-                       b_wrap:1,            /** 30     Marks last descriptor in TD list */
-                       b_used:1;            /** 31     User clear, GMAC sets this to 1 once a frame has been successfully transmitted */
-               } bm;
-       } status;
-} gmac_tx_descriptor_t;
-
-COMPILER_PACK_RESET()
-
-/**
- * \brief Input parameters when initializing the gmac module mode.
- */
-typedef struct gmac_options {
-       /*  Enable/Disable CopyAllFrame */
-       uint8_t uc_copy_all_frame;
-       /* Enable/Disable NoBroadCast */
-       uint8_t uc_no_boardcast;
-       /* MAC address */
-       uint8_t uc_mac_addr[GMAC_ADDR_LENGTH];
-} gmac_options_t;
-
-/** RX callback */
-typedef void (*gmac_dev_tx_cb_t) (uint32_t ul_status);
-/** Wakeup callback */
-typedef void (*gmac_dev_wakeup_cb_t) (void);
-
-/**
- * GMAC driver structure.
- */
-typedef struct gmac_device {
-
-       /** Pointer to HW register base */
-       Gmac *p_hw;
-       /**
-        * Pointer to allocated TX buffer.
-        * Section 3.6 of AMBA 2.0 spec states that burst should not cross
-        * 1K Boundaries.
-        * Receive buffer manager writes are burst of 2 words => 3 lsb bits
-        * of the address shall be set to 0.
-        */
-       uint8_t *p_tx_buffer;
-       /** Pointer to allocated RX buffer */
-       uint8_t *p_rx_buffer;
-       /** Pointer to Rx TDs (must be 8-byte aligned) */
-       gmac_rx_descriptor_t *p_rx_dscr;
-       /** Pointer to Tx TDs (must be 8-byte aligned) */
-       gmac_tx_descriptor_t *p_tx_dscr;
-       /** Optional callback to be invoked once a frame has been received */
-       gmac_dev_tx_cb_t func_rx_cb;
-#if( GMAC_USES_WAKEUP_CALLBACK )
-       /** Optional callback to be invoked once several TDs have been released */
-       gmac_dev_wakeup_cb_t func_wakeup_cb;
-#endif
-#if( GMAC_USES_TX_CALLBACK != 0 )
-       /** Optional callback list to be invoked once TD has been processed */
-       gmac_dev_tx_cb_t *func_tx_cb_list;
-#endif
-       /** RX TD list size */
-       uint32_t ul_rx_list_size;
-       /** RX index for current processing TD */
-       uint32_t ul_rx_idx;
-       /** TX TD list size */
-       uint32_t ul_tx_list_size;
-       /** Circular buffer head pointer by upper layer (buffer to be sent) */
-       int32_t l_tx_head;
-       /** Circular buffer tail pointer incremented by handlers (buffer sent) */
-       int32_t l_tx_tail;
-
-       /** Number of free TD before wakeup callback is invoked */
-       uint32_t uc_wakeup_threshold;
-} gmac_device_t;
-
-/**
- * \brief Write network control value.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param ul_ncr   Network control value.
- */
-static inline void gmac_network_control(Gmac* p_gmac, uint32_t ul_ncr)
-{
-       p_gmac->GMAC_NCR = ul_ncr;
-}
-
-/**
- * \brief Get network control value.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- */
-
-static inline uint32_t gmac_get_network_control(Gmac* p_gmac)
-{
-       return p_gmac->GMAC_NCR;
-}
-
-/**
- * \brief Enable/Disable GMAC receive.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable GMAC receiver, else to enable it.
- */
-static inline void gmac_enable_receive(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCR |= GMAC_NCR_RXEN;
-       } else {
-               p_gmac->GMAC_NCR &= ~GMAC_NCR_RXEN;
-       }
-}
-
-/**
- * \brief Enable/Disable GMAC transmit.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable GMAC transmit, else to enable it.
- */
-static inline void gmac_enable_transmit(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCR |= GMAC_NCR_TXEN;
-       } else {
-               p_gmac->GMAC_NCR &= ~GMAC_NCR_TXEN;
-       }
-}
-
-/**
- * \brief Enable/Disable GMAC management.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable GMAC management, else to enable it.
- */
-static inline void gmac_enable_management(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCR |= GMAC_NCR_MPE;
-       } else {
-               p_gmac->GMAC_NCR &= ~GMAC_NCR_MPE;
-       }
-}
-
-/**
- * \brief Clear all statistics registers.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- */
-static inline void gmac_clear_statistics(Gmac* p_gmac)
-{
-       p_gmac->GMAC_NCR |= GMAC_NCR_CLRSTAT;
-}
-
-/**
- * \brief Increase all statistics registers.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- */
-static inline void gmac_increase_statistics(Gmac* p_gmac)
-{
-       p_gmac->GMAC_NCR |= GMAC_NCR_INCSTAT;
-}
-
-/**
- * \brief Enable/Disable statistics registers writing.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable the statistics registers writing, else to enable it.
- */
-static inline void gmac_enable_statistics_write(Gmac* p_gmac,
-               uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCR |= GMAC_NCR_WESTAT;
-       } else {
-               p_gmac->GMAC_NCR &= ~GMAC_NCR_WESTAT;
-       }
-}
-
-/**
- * \brief In half-duplex mode, forces collisions on all received frames.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable the back pressure, else to enable it.
- */
-static inline void gmac_enable_back_pressure(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCR |= GMAC_NCR_BP;
-       } else {
-               p_gmac->GMAC_NCR &= ~GMAC_NCR_BP;
-       }
-}
-
-/**
- * \brief Start transmission.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- */
-static inline void gmac_start_transmission(Gmac* p_gmac)
-{
-       p_gmac->GMAC_NCR |= GMAC_NCR_TSTART;
-}
-
-/**
- * \brief Halt transmission.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- */
-static inline void gmac_halt_transmission(Gmac* p_gmac)
-{
-       p_gmac->GMAC_NCR |= GMAC_NCR_THALT;
-}
-
-/**
- * \brief Transmit pause frame.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- */
-static inline void gmac_tx_pause_frame(Gmac* p_gmac)
-{
-       p_gmac->GMAC_NCR |= GMAC_NCR_TXPF;
-}
-
-/**
- * \brief Transmit zero quantum pause frame.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- */
-static inline void gmac_tx_pause_zero_quantum_frame(Gmac* p_gmac)
-{
-       p_gmac->GMAC_NCR |= GMAC_NCR_TXZQPF;
-}
-
-/**
- * \brief Read snapshot.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- */
-static inline void gmac_read_snapshot(Gmac* p_gmac)
-{
-       p_gmac->GMAC_NCR |= GMAC_NCR_RDS;
-}
-
-/**
- * \brief Store receivetime stamp to memory.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to normal operation, else to enable the store.
- */
-static inline void gmac_store_rx_time_stamp(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCR |= GMAC_NCR_SRTSM;
-       } else {
-               p_gmac->GMAC_NCR &= ~GMAC_NCR_SRTSM;
-       }
-}
-
-/**
- * \brief Enable PFC priority-based pause reception.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   1 to set the reception, 0 to disable.
- */
-static inline void gmac_enable_pfc_pause_frame(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCR |= GMAC_NCR_ENPBPR;
-       } else {
-               p_gmac->GMAC_NCR &= ~GMAC_NCR_ENPBPR;
-       }
-}
-
-/**
- * \brief Transmit PFC priority-based pause reception.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- */
-static inline void gmac_transmit_pfc_pause_frame(Gmac* p_gmac)
-{
-               p_gmac->GMAC_NCR |= GMAC_NCR_TXPBPF;
-}
-
-/**
- * \brief Flush next packet.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- */
-static inline void gmac_flush_next_packet(Gmac* p_gmac)
-{
-               p_gmac->GMAC_NCR |= GMAC_NCR_FNP;
-}
-
-/**
- * \brief Set up network configuration register.
- *
- * \param p_gmac   Pointer to the GMAC instance.
-  * \param ul_cfg   Network configuration value.
- */
-static inline void gmac_set_configure(Gmac* p_gmac, uint32_t ul_cfg)
-{
-       p_gmac->GMAC_NCFGR = ul_cfg;
-}
-
-/**
- * \brief Get network configuration.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- *
- * \return Network configuration.
- */
-static inline uint32_t gmac_get_configure(Gmac* p_gmac)
-{
-       return p_gmac->GMAC_NCFGR;
-}
-
-
-/* Get and set DMA Configuration Register */
-static inline void gmac_set_dma(Gmac* p_gmac, uint32_t ul_cfg)
-{
-       p_gmac->GMAC_DCFGR = ul_cfg;
-}
-
-static inline uint32_t gmac_get_dma(Gmac* p_gmac)
-{
-       return p_gmac->GMAC_DCFGR;
-}
-
-/**
- * \brief Set speed.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_speed 1 to indicate 100Mbps, 0 to 10Mbps.
- */
-static inline void gmac_set_speed(Gmac* p_gmac, uint8_t uc_speed)
-{
-       if (uc_speed) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_SPD;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_SPD;
-       }
-}
-
-/**
- * \brief Enable/Disable Full-Duplex mode.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable the Full-Duplex mode, else to enable it.
- */
-static inline void gmac_enable_full_duplex(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_FD;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_FD;
-       }
-}
-
-/**
- * \brief Enable/Disable Copy(Receive) All Valid Frames.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable copying all valid frames, else to enable it.
- */
-static inline void gmac_enable_copy_all(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_CAF;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_CAF;
-       }
-}
-
-/**
- * \brief Enable/Disable jumbo frames (up to 10240 bytes).
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable the jumbo frames, else to enable it.
- */
-static inline void gmac_enable_jumbo_frames(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_JFRAME;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_JFRAME;
-       }
-}
-
-/**
- * \brief Disable/Enable broadcast receiving.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   1 to disable the broadcast, else to enable it.
- */
-static inline void gmac_disable_broadcast(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_NBC;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_NBC;
-       }
-}
-
-/**
- * \brief Enable/Disable multicast hash.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable the multicast hash, else to enable it.
- */
-static inline void gmac_enable_multicast_hash(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_UNIHEN;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_UNIHEN;
-       }
-}
-
-/**
- * \brief Enable/Disable big frames (over 1518, up to 1536).
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable big frames else to enable it.
- */
-static inline void gmac_enable_big_frame(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_MAXFS;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_MAXFS;
-       }
-}
-
-/**
- * \brief Set MDC clock divider.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param ul_mck   GMAC MCK.
- *
- * \return GMAC_OK if successfully.
- */
-static inline uint8_t gmac_set_mdc_clock(Gmac* p_gmac, uint32_t ul_mck)
-{
-       uint32_t ul_clk;
-       
-       if (ul_mck > GMAC_MCK_SPEED_240MHZ) {
-               return GMAC_INVALID;
-       } else if (ul_mck > GMAC_MCK_SPEED_160MHZ) {
-               ul_clk = GMAC_NCFGR_CLK_MCK_96;
-       } else if (ul_mck > GMAC_MCK_SPEED_120MHZ) {
-               ul_clk = GMAC_NCFGR_CLK_MCK_64;
-       } else if (ul_mck > GMAC_MCK_SPEED_80MHZ) {
-               ul_clk = GMAC_NCFGR_CLK_MCK_48;
-       } else if (ul_mck > GMAC_MCK_SPEED_40MHZ) {
-               ul_clk = GMAC_NCFGR_CLK_MCK_32;
-       } else if (ul_mck > GMAC_MCK_SPEED_20MHZ) {
-               ul_clk = GMAC_NCFGR_CLK_MCK_16;
-       } else {
-               ul_clk = GMAC_NCFGR_CLK_MCK_8;
-       }
-       ;
-       p_gmac->GMAC_NCFGR = (p_gmac->GMAC_NCFGR & ~GMAC_NCFGR_CLK_Msk) | ul_clk;
-       return GMAC_OK;
-}
-
-/**
- * \brief Enable/Disable retry test.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable the GMAC receiver, else to enable it.
- */
-static inline void gmac_enable_retry_test(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RTY;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RTY;
-       }
-}
-
-/**
- * \brief Enable/Disable pause (when a valid pause frame is received).
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable pause frame, else to enable it.
- */
-static inline void gmac_enable_pause_frame(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_PEN;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_PEN;
-       }
-}
-
-/**
- * \brief Set receive buffer offset to 0 ~ 3.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- */
-static inline void gmac_set_rx_buffer_offset(Gmac* p_gmac, uint8_t uc_offset)
-{
-       p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RXBUFO_Msk;
-       p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RXBUFO(uc_offset);
-}
-
-/**
- * \brief Enable/Disable receive length field checking.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable receive length field checking, else to enable it.
- */
-static inline void gmac_enable_rx_length_check(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_LFERD;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_LFERD;
-       }
-}
-
-/**
- * \brief Enable/Disable discarding FCS field of received frames.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable discarding FCS field of received frames, else to enable it.
- */
-static inline void gmac_enable_discard_fcs(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RFCS;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RFCS;
-       }
-}
-
-
-/**
- * \brief Enable/Disable frames to be received in half-duplex mode
- * while transmitting.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable the received in half-duplex mode, else to enable it.
- */
-static inline void gmac_enable_efrhd(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_EFRHD;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_EFRHD;
-       }
-}
-
-/**
- * \brief Enable/Disable ignore RX FCS.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable ignore RX FCS, else to enable it.
- */
-static inline void gmac_enable_ignore_rx_fcs(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_IRXFCS;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_IRXFCS;
-       }
-}
-
-/**
- * \brief Get Network Status.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- *
- * \return Network status.
- */
-static inline uint32_t gmac_get_status(Gmac* p_gmac)
-{
-       return p_gmac->GMAC_NSR;
-}
-
-/**
- * \brief Get MDIO IN pin status.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- *
- * \return MDIO IN pin status.
- */
-static inline uint8_t gmac_get_MDIO(Gmac* p_gmac)
-{
-       return ((p_gmac->GMAC_NSR & GMAC_NSR_MDIO) > 0);
-}
-
-/**
- * \brief Check if PHY is idle.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- *
- * \return  1 if PHY is idle.
- */
-static inline uint8_t gmac_is_phy_idle(Gmac* p_gmac)
-{
-       return ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) > 0);
-}
-
-/**
- * \brief Return transmit status.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- *
- * \return  Transmit status.
- */
-static inline uint32_t gmac_get_tx_status(Gmac* p_gmac)
-{
-       return p_gmac->GMAC_TSR;
-}
-
-/**
- * \brief Clear transmit status.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param ul_status   Transmit status.
- */
-static inline void gmac_clear_tx_status(Gmac* p_gmac, uint32_t ul_status)
-{
-       p_gmac->GMAC_TSR = ul_status;
-}
-
-/**
- * \brief Return receive status.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- */
-static inline uint32_t gmac_get_rx_status(Gmac* p_gmac)
-{
-       return p_gmac->GMAC_RSR;
-}
-
-/**
- * \brief Clear receive status.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param ul_status   Receive status.
- */
-static inline void gmac_clear_rx_status(Gmac* p_gmac, uint32_t ul_status)
-{
-       p_gmac->GMAC_RSR = ul_status;
-}
-
-/**
- * \brief Set Rx Queue.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param ul_addr   Rx queue address.
- */
-static inline void gmac_set_rx_queue(Gmac* p_gmac, uint32_t ul_addr)
-{
-       p_gmac->GMAC_RBQB = GMAC_RBQB_ADDR_Msk & ul_addr;
-}
-
-/**
- * \brief Get Rx Queue Address.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- *
- * \return  Rx queue address.
- */
-static inline uint32_t gmac_get_rx_queue(Gmac* p_gmac)
-{
-       return p_gmac->GMAC_RBQB;
-}
-
-/**
- * \brief Set Tx Queue.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param ul_addr  Tx queue address.
- */
-static inline void gmac_set_tx_queue(Gmac* p_gmac, uint32_t ul_addr)
-{
-       p_gmac->GMAC_TBQB = GMAC_TBQB_ADDR_Msk & ul_addr;
-}
-
-/**
- * \brief Get Tx Queue.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- *
- * \return  Rx queue address.
- */
-static inline uint32_t gmac_get_tx_queue(Gmac* p_gmac)
-{
-       return p_gmac->GMAC_TBQB;
-}
-
-/**
- * \brief Enable interrupt(s).
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param ul_source   Interrupt source(s) to be enabled.
- */
-static inline void gmac_enable_interrupt(Gmac* p_gmac, uint32_t ul_source)
-{
-       p_gmac->GMAC_IER = ul_source;
-}
-
-/**
- * \brief Disable interrupt(s).
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param ul_source   Interrupt source(s) to be disabled.
- */
-static inline void gmac_disable_interrupt(Gmac* p_gmac, uint32_t ul_source)
-{
-       p_gmac->GMAC_IDR = ul_source;
-}
-
-/**
- * \brief Return interrupt status.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- *
- * \return Interrupt status.
- */
-static inline uint32_t gmac_get_interrupt_status(Gmac* p_gmac)
-{
-       return p_gmac->GMAC_ISR;
-}
-
-/**
- * \brief Return interrupt mask.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- *
- * \return Interrupt mask.
- */
-static inline uint32_t gmac_get_interrupt_mask(Gmac* p_gmac)
-{
-       return p_gmac->GMAC_IMR;
-}
-
-/**
- * \brief Execute PHY maintenance command.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_phy_addr   PHY address.
- * \param uc_reg_addr   Register address.
- * \param uc_rw   1 to Read, 0 to write.
- * \param us_data   Data to be performed, write only.
- */
-static inline void gmac_maintain_phy(Gmac* p_gmac,
-               uint8_t uc_phy_addr, uint8_t uc_reg_addr, uint8_t uc_rw,
-               uint16_t us_data)
-{
-       /* Wait until bus idle */
-       while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);
-       /* Write maintain register */
-       p_gmac->GMAC_MAN = GMAC_MAN_WTN(GMAC_MAN_CODE_VALUE)
-                       | GMAC_MAN_CLTTO 
-                       | GMAC_MAN_PHYA(uc_phy_addr)
-                       | GMAC_MAN_REGA(uc_reg_addr)
-                       | GMAC_MAN_OP((uc_rw ? GMAC_MAN_RW_TYPE : GMAC_MAN_READ_ONLY))
-                       | GMAC_MAN_DATA(us_data);
-}
-
-/**
- * \brief Get PHY maintenance data returned.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- *
- * \return Get PHY data.
- */
-static inline uint16_t gmac_get_phy_data(Gmac* p_gmac)
-{
-       /* Wait until bus idle */
-       while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);
-       /* Return data */
-       return (uint16_t) (p_gmac->GMAC_MAN & GMAC_MAN_DATA_Msk);
-}
-
-/**
- * \brief Set Hash.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param ul_hash_top   Hash top.
- * \param ul_hash_bottom   Hash bottom.
- */
-static inline void gmac_set_hash(Gmac* p_gmac, uint32_t ul_hash_top,
-               uint32_t ul_hash_bottom)
-{
-       p_gmac->GMAC_HRB = ul_hash_bottom;
-       p_gmac->GMAC_HRT = ul_hash_top;
-}
-
-/**
- * \brief Set 64 bits Hash.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param ull_hash   64 bits hash value.
- */
-static inline void gmac_set_hash64(Gmac* p_gmac, uint64_t ull_hash)
-{
-       p_gmac->GMAC_HRB = (uint32_t) ull_hash;
-       p_gmac->GMAC_HRT = (uint32_t) (ull_hash >> 32);
-}
-
-/**
- * \brief Set MAC Address.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_index  GMAC specific address register index.
- * \param p_mac_addr  GMAC address.
- */
-static inline void gmac_set_address(Gmac* p_gmac, uint8_t uc_index,
-               uint8_t* p_mac_addr)
-{
-       p_gmac->GMAC_SA[uc_index].GMAC_SAB = (p_mac_addr[3] << 24)
-                       | (p_mac_addr[2] << 16)
-                       | (p_mac_addr[1] << 8)
-                       | (p_mac_addr[0]);
-       p_gmac->GMAC_SA[uc_index].GMAC_SAT = (p_mac_addr[5] << 8)
-                       | (p_mac_addr[4]);
-}
-
-/**
- * \brief Set MAC Address via 2 dword.
-  *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_index  GMAC specific address register index.
- * \param ul_mac_top  GMAC top address.
- * \param ul_mac_bottom  GMAC bottom address.
- */
-static inline void gmac_set_address32(Gmac* p_gmac, uint8_t uc_index,
-               uint32_t ul_mac_top, uint32_t ul_mac_bottom)
-{
-       p_gmac->GMAC_SA[uc_index].GMAC_SAB = ul_mac_bottom;
-       p_gmac->GMAC_SA[uc_index].GMAC_SAT = ul_mac_top;
-}
-
-/**
- * \brief Set MAC Address via int64.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_index  GMAC specific address register index.
- * \param ull_mac  64-bit GMAC address.
- */
-static inline void gmac_set_address64(Gmac* p_gmac, uint8_t uc_index,
-               uint64_t ull_mac)
-{
-       p_gmac->GMAC_SA[uc_index].GMAC_SAB = (uint32_t) ull_mac;
-       p_gmac->GMAC_SA[uc_index].GMAC_SAT = (uint32_t) (ull_mac >> 32);
-}
-
-/**
- * \brief Select media independent interface mode.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param mode   Media independent interface mode.
- */
-static inline void gmac_select_mii_mode(Gmac* p_gmac, gmac_mii_mode_t mode)
-{
-       switch (mode) {
-               case GMAC_PHY_MII:
-               case GMAC_PHY_RMII:
-                       p_gmac->GMAC_UR |= GMAC_UR_RMIIMII;
-               break;
-
-               default:
-                       p_gmac->GMAC_UR &= ~GMAC_UR_RMIIMII;
-               break;
-       }
-}
-
-uint8_t gmac_phy_read(Gmac* p_gmac, uint8_t uc_phy_address, uint8_t uc_address,
-               uint32_t* p_value);
-uint8_t gmac_phy_write(Gmac* p_gmac, uint8_t uc_phy_address,
-               uint8_t uc_address, uint32_t ul_value);
-void gmac_dev_init(Gmac* p_gmac, gmac_device_t* p_gmac_dev,
-               gmac_options_t* p_opt);
-uint32_t gmac_dev_read(gmac_device_t* p_gmac_dev, uint8_t* p_frame,
-               uint32_t ul_frame_size, uint32_t* p_rcv_size);
-uint32_t gmac_dev_write(gmac_device_t* p_gmac_dev, void *p_buffer,
-               uint32_t ul_size, gmac_dev_tx_cb_t func_tx_cb);
-uint32_t gmac_dev_get_tx_load(gmac_device_t* p_gmac_dev);
-void gmac_dev_set_rx_callback(gmac_device_t* p_gmac_dev,
-               gmac_dev_tx_cb_t func_rx_cb);
-uint8_t gmac_dev_set_tx_wakeup_callback(gmac_device_t* p_gmac_dev,
-               gmac_dev_wakeup_cb_t func_wakeup, uint8_t uc_threshold);
-void gmac_dev_reset(gmac_device_t* p_gmac_dev);
-void gmac_handler(gmac_device_t* p_gmac_dev);
-
-/// @cond 0
-/**INDENT-OFF**/
-#ifdef __cplusplus
-}
-#endif
-/**INDENT-ON**/
-/// @endcond
-
-/**
- * \page gmac_quickstart Quickstart guide for GMAC driver.
- *
- * This is the quickstart guide for the \ref gmac_group "Ethernet MAC",
- * with step-by-step instructions on how to configure and use the driver in a
- * selection of use cases.
- *
- * The use cases contain several code fragments. The code fragments in the
- * steps for setup can be copied into a custom initialization function, while
- * the steps for usage can be copied into, e.g., the main application function.
- *
- * \section gmac_basic_use_case Basic use case
- * In the basic use case, the GMAC driver are configured for:
- * - PHY component KSZ8051MNL is used
- * - GMAC uses MII mode
- * - The number of receive buffer is 16
- * - The number of transfer buffer is 8
- * - MAC address is set to 00-04-25-1c-a0-02
- * - IP address is set to 192.168.0.2
- * - IP address is set to 192.168.0.2
- * - Gateway is set to 192.168.0.1
- * - Network mask is 255.255.255.0
- * - PHY operation max retry count is 1000000
- * - GMAC is configured to not support copy all frame and support broadcast
- * - The data will be read from the ethernet
- *
- * \section gmac_basic_use_case_setup Setup steps
- *
- * \subsection gmac_basic_use_case_setup_prereq Prerequisites
- * -# \ref sysclk_group "System Clock Management (sysclock)"
- * -# \ref pmc_group "Power Management Controller (pmc)"
- * -# \ref ksz8051mnl_ethernet_phy_group "PHY component (KSZ8051MNL)"
- *
- * \subsection gmac_basic_use_case_setup_code Example code
- * Content of conf_eth.h
- * \code
- * #define GMAC_RX_BUFFERS                               16
- * #define GMAC_TX_BUFFERS                               8
- * #define MAC_PHY_RETRY_MAX                             1000000
- * #define ETHERNET_CONF_ETHADDR0                        0x00
- * #define ETHERNET_CONF_ETHADDR0                        0x00
- * #define ETHERNET_CONF_ETHADDR1                        0x04
- * #define ETHERNET_CONF_ETHADDR2                        0x25
- * #define ETHERNET_CONF_ETHADDR3                        0x1C
- * #define ETHERNET_CONF_ETHADDR4                        0xA0
- * #define ETHERNET_CONF_ETHADDR5                        0x02
- * #define ETHERNET_CONF_IPADDR0                         192
- * #define ETHERNET_CONF_IPADDR1                         168
- * #define ETHERNET_CONF_IPADDR2                         0
- * #define ETHERNET_CONF_IPADDR3                         2
- * #define ETHERNET_CONF_GATEWAY_ADDR0                   192
- * #define ETHERNET_CONF_GATEWAY_ADDR1                   168
- * #define ETHERNET_CONF_GATEWAY_ADDR2                   0
- * #define ETHERNET_CONF_GATEWAY_ADDR3                   1
- * #define ETHERNET_CONF_NET_MASK0                       255
- * #define ETHERNET_CONF_NET_MASK1                       255
- * #define ETHERNET_CONF_NET_MASK2                       255
- * #define ETHERNET_CONF_NET_MASK3                       0
- * #define ETH_PHY_MODE                                  ETH_PHY_MODE
- * \endcode
- *
- * A specific gmac device and the receive data buffer must be defined; another ul_frm_size should be defined
- * to trace the actual size of the data received.
- * \code
- * static gmac_device_t gs_gmac_dev;
- * static volatile uint8_t gs_uc_eth_buffer[GMAC_FRAME_LENTGH_MAX];
- *
- * uint32_t ul_frm_size;
- * \endcode
- *
- * Add to application C-file:
- * \code
- *   void gmac_init(void)
- *   {
- *       sysclk_init();
- *
- *       board_init();
- *
- *       pmc_enable_periph_clk(ID_GMAC);
- *
- *       gmac_option.uc_copy_all_frame = 0;
- *       gmac_option.uc_no_boardcast = 0;
- *       memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));
- *       gs_gmac_dev.p_hw = GMAC;
- *
- *       gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option);
- *
- *       NVIC_EnableIRQ(GMAC_IRQn);
- *
- *       ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz());
- * 
- *       ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR);
- *
- *       ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1);
- * \endcode
- *
- * \subsection gmac_basic_use_case_setup_flow Workflow
- * - Ensure that conf_eth.h is present and contains the
- * following configuration symbol. This configuration file is used
- * by the driver and should not be included by the application.
- * -# Define the receiving buffer size used in the internal GMAC driver.
- * The buffer size used for RX is GMAC_RX_BUFFERS * 128.
- * If it was supposed receiving a large number of frame, the
- * GMAC_RX_BUFFERS should be set higher. E.g., the application wants to accept
- * a ping echo test of 2048, the GMAC_RX_BUFFERS should be set at least 
- * (2048/128)=16, and as there are additional frames coming, a preferred
- * number is 24 depending on a normal Ethernet throughput.
- *   - \code
- *        #define GMAC_RX_BUFFERS                               16
- *   \endcode
- * -# Define the transmitting buffer size used in the internal GMAC driver.
- * The buffer size used for TX is GMAC_TX_BUFFERS * 1518.
- *   - \code
- *        #define GMAC_TX_BUFFERS                               8
- *   \endcode
- * -# Define maximum retry time for a PHY read/write operation.
- *   - \code
- *        #define MAC_PHY_RETRY_MAX                             1000000
- *   \endcode
- * -# Define the MAC address. 00:04:25:1C:A0:02 is the address reserved
- * for ATMEL, application should always change this address to its' own.
- *   - \code
- *        #define ETHERNET_CONF_ETHADDR0                        0x00
- *        #define ETHERNET_CONF_ETHADDR1                        0x04
- *        #define ETHERNET_CONF_ETHADDR2                        0x25
- *        #define ETHERNET_CONF_ETHADDR3                        0x1C
- *        #define ETHERNET_CONF_ETHADDR4                        0xA0
- *        #define ETHERNET_CONF_ETHADDR5                        0x02
- *   \endcode
- * -# Define the IP address configration used in the application. When DHCP
- *  is enabled, this configuration is not effected.
- *   - \code
- *        #define ETHERNET_CONF_IPADDR0                         192
- *        #define ETHERNET_CONF_IPADDR1                         168
- *        #define ETHERNET_CONF_IPADDR2                         0
- *        #define ETHERNET_CONF_IPADDR3                         2
- *        #define ETHERNET_CONF_GATEWAY_ADDR0                   192
- *        #define ETHERNET_CONF_GATEWAY_ADDR1                   168
- *        #define ETHERNET_CONF_GATEWAY_ADDR2                   0
- *        #define ETHERNET_CONF_GATEWAY_ADDR3                   1
- *        #define ETHERNET_CONF_NET_MASK0                       255
- *        #define ETHERNET_CONF_NET_MASK1                       255
- *        #define ETHERNET_CONF_NET_MASK2                       255
- *        #define ETHERNET_CONF_NET_MASK3                       0
- *   \endcode
- * -# Configure the PHY maintainance interface.
- *   - \code
- *        #define ETH_PHY_MODE                                  GMAC_PHY_MII
- *   \endcode
- * -# Enable the system clock:
- *   - \code sysclk_init(); \endcode
- * -# Enable PIO configurations for GMAC:
- *   - \code board_init(); \endcode
- * -# Enable PMC clock for GMAC:
- *   - \code pmc_enable_periph_clk(ID_GMAC); \endcode
- * -# Set the GMAC options; it's set to copy all frame and support broadcast:
- *   - \code
- *         gmac_option.uc_copy_all_frame = 0;
- *         gmac_option.uc_no_boardcast = 0;
- *         memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));
- *         gs_gmac_dev.p_hw = GMAC;
- * \endcode
- * -# Initialize GMAC device with the filled option:
- *   - \code
- *         gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option);
- * \endcode
- * -# Enable the interrupt service for GMAC:
- *   - \code
- *         NVIC_EnableIRQ(GMAC_IRQn);
- * \endcode
- * -# Initialize the PHY component:
- *   - \code
- *         ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz());
- * \endcode
-  * -# The link will be established based on auto negotiation.
- *   - \code
- *         ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR);
- * \endcode
- * -# Establish the ethernet link; the network can be worked from now on:
- *   - \code
- *         ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1);
- * \endcode
- *
- * \section gmac_basic_use_case_usage Usage steps
- * \subsection gmac_basic_use_case_usage_code Example code
- * Add to, e.g., main loop in application C-file:
- * \code
- *    gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size));
- * \endcode
- *
- * \subsection gmac_basic_use_case_usage_flow Workflow
- * -# Start reading the data from the ethernet:
- *   - \code gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size)); \endcode
- */
-
-#      define GMAC_STATS 0
-
-#if( GMAC_STATS != 0 )
-
-       /* Here below some code to study the types and
-       frequencies of  GMAC interrupts. */
-       #define GMAC_IDX_RXUBR 0
-       #define GMAC_IDX_TUR   1
-       #define GMAC_IDX_RLEX  2
-       #define GMAC_IDX_TFC   3
-       #define GMAC_IDX_RCOMP 4
-       #define GMAC_IDX_TCOMP 5
-       #define GMAC_IDX_ROVR  6
-       #define GMAC_IDX_HRESP 7
-       #define GMAC_IDX_PFNZ  8
-       #define GMAC_IDX_PTZ   9
-
-       struct SGmacStats {
-               unsigned recvCount;
-               unsigned rovrCount;
-               unsigned bnaCount;
-               unsigned sendCount;
-               unsigned sovrCount;
-               unsigned incompCount;
-               unsigned truncCount;
-
-               unsigned intStatus[10];
-       };
-       extern struct SGmacStats gmacStats;
-
-       struct SIntPair {
-               const char *name;
-               unsigned mask;
-               int index;
-       };
-
-       #define MK_PAIR( NAME )   #NAME, GMAC_IER_##NAME, GMAC_IDX_##NAME
-       static const struct SIntPair intPairs[] = {
-               { MK_PAIR( RXUBR ) }, /* Enable receive used bit read interrupt. */
-               { MK_PAIR( TUR   ) }, /* Enable transmit underrun interrupt. */
-               { MK_PAIR( RLEX  ) }, /* Enable retry limit  exceeded interrupt. */
-               { MK_PAIR( TFC   ) }, /* Enable transmit buffers exhausted in mid-frame interrupt. */
-               { MK_PAIR( RCOMP ) }, /* Receive complete */
-               { MK_PAIR( TCOMP ) }, /* Enable transmit complete interrupt. */
-               { MK_PAIR( ROVR  ) }, /* Enable receive overrun interrupt. */
-               { MK_PAIR( HRESP ) }, /* Enable Hresp not OK interrupt. */
-               { MK_PAIR( PFNZ  ) }, /* Enable pause frame received interrupt. */
-               { MK_PAIR( PTZ   ) }  /* Enable pause time zero interrupt. */
-       };
-
-       void gmac_show_irq_counts ();
-
-#endif
-
-#endif /* GMAC_H_INCLUDED */
+ /**\r
+ * \file\r
+ *\r
+ * \brief GMAC (Ethernet MAC) driver for SAM.\r
+ *\r
+ * Copyright (c) 2013 Atmel Corporation. All rights reserved.\r
+ *\r
+ * \asf_license_start\r
+ *\r
+ * \page License\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ *    this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ *    this list of conditions and the following disclaimer in the documentation\r
+ *    and/or other materials provided with the distribution.\r
+ *\r
+ * 3. The name of Atmel may not be used to endorse or promote products derived\r
+ *    from this software without specific prior written permission.\r
+ *\r
+ * 4. This software may only be redistributed and used in connection with an\r
+ *    Atmel microcontroller product.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * \asf_license_stop\r
+ *\r
+ */\r
+\r
+#ifndef GMAC_H_INCLUDED\r
+#define GMAC_H_INCLUDED\r
+\r
+#include "compiler.h"\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
+\r
+/** The buffer addresses written into the descriptors must be aligned, so the\r
+    last few bits are zero.  These bits have special meaning for the GMAC\r
+    peripheral and cannot be used as part of the address. */\r
+#define GMAC_RXD_ADDR_MASK      0xFFFFFFFC\r
+#define GMAC_RXD_WRAP         (1ul << 1)  /**< Wrap bit */\r
+#define GMAC_RXD_OWNERSHIP    (1ul << 0)  /**< Ownership bit */\r
+\r
+#define GMAC_RXD_BROADCAST    (1ul << 31) /**< Broadcast detected */\r
+#define GMAC_RXD_MULTIHASH    (1ul << 30) /**< Multicast hash match */\r
+#define GMAC_RXD_UNIHASH      (1ul << 29) /**< Unicast hash match */\r
+#define GMAC_RXD_ADDR_FOUND      (1ul << 27) /**< Specific address match found */\r
+#define GMAC_RXD_ADDR        (3ul << 25) /**< Address match */\r
+#define GMAC_RXD_RXCOEN        (1ul << 24) /**< RXCOEN related function */\r
+#define GMAC_RXD_TYPE         (3ul << 22) /**< Type ID match */\r
+#define GMAC_RXD_VLAN         (1ul << 21) /**< VLAN tag detected */\r
+#define GMAC_RXD_PRIORITY     (1ul << 20) /**< Priority tag detected */\r
+#define GMAC_RXD_PRIORITY_MASK  (3ul << 17) /**< VLAN priority */\r
+#define GMAC_RXD_CFI          (1ul << 16) /**< Concatenation Format Indicator only if bit 21 is set */\r
+#define GMAC_RXD_EOF          (1ul << 15) /**< End of frame */\r
+#define GMAC_RXD_SOF          (1ul << 14) /**< Start of frame */\r
+#define GMAC_RXD_FCS          (1ul << 13) /**< Frame check sequence */\r
+#define GMAC_RXD_OFFSET_MASK                /**< Receive buffer offset */\r
+#define GMAC_RXD_LEN_MASK       (0xFFF)     /**< Length of frame including FCS (if selected) */\r
+#define GMAC_RXD_LENJUMBO_MASK  (0x3FFF)    /**< Jumbo frame length */\r
+\r
+#define GMAC_TXD_USED         (1ul << 31) /**< Frame is transmitted */\r
+#define GMAC_TXD_WRAP         (1ul << 30) /**< Last descriptor */\r
+#define GMAC_TXD_ERROR        (1ul << 29) /**< Retry limit exceeded, error */\r
+#define GMAC_TXD_UNDERRUN     (1ul << 28) /**< Transmit underrun */\r
+#define GMAC_TXD_EXHAUSTED    (1ul << 27) /**< Buffer exhausted */\r
+#define GMAC_TXD_LATE    (1ul << 26) /**< Late collision,transmit  error  */\r
+#define GMAC_TXD_CHECKSUM_ERROR   (7ul << 20) /**< Checksum error */\r
+#define GMAC_TXD_NOCRC        (1ul << 16) /**< No CRC */\r
+#define GMAC_TXD_LAST         (1ul << 15) /**< Last buffer in frame */\r
+#define GMAC_TXD_LEN_MASK       (0x1FFF)     /**< Length of buffer */\r
+\r
+/** The MAC can support frame lengths up to 1536 bytes */\r
+#define GMAC_FRAME_LENTGH_MAX       1536\r
+\r
+#define GMAC_RX_UNITSIZE            128     /**< Fixed size for RX buffer  */\r
+#define GMAC_TX_UNITSIZE            1518    /**< Size for ETH frame length */\r
+\r
+/** GMAC clock speed */\r
+#define GMAC_MCK_SPEED_240MHZ        (240*1000*1000)\r
+#define GMAC_MCK_SPEED_160MHZ        (160*1000*1000)\r
+#define GMAC_MCK_SPEED_120MHZ        (120*1000*1000)\r
+#define GMAC_MCK_SPEED_80MHZ          (80*1000*1000)\r
+#define GMAC_MCK_SPEED_40MHZ          (40*1000*1000)\r
+#define GMAC_MCK_SPEED_20MHZ          (20*1000*1000)\r
+\r
+/** GMAC maintain code default value*/\r
+#define GMAC_MAN_CODE_VALUE    (10)\r
+\r
+/** GMAC maintain start of frame default value*/\r
+#define GMAC_MAN_SOF_VALUE     (1)\r
+\r
+/** GMAC maintain read/write*/\r
+#define GMAC_MAN_RW_TYPE       (2)\r
+\r
+/** GMAC maintain read only*/\r
+#define GMAC_MAN_READ_ONLY     (1)\r
+\r
+/** GMAC address length */\r
+#define GMAC_ADDR_LENGTH       (6)\r
+\r
+\r
+#define GMAC_DUPLEX_HALF 0\r
+#define GMAC_DUPLEX_FULL 1\r
+\r
+#define GMAC_SPEED_10M      0\r
+#define GMAC_SPEED_100M     1\r
+\r
+/**\r
+ * \brief Return codes for GMAC APIs.\r
+ */\r
+typedef enum {\r
+       GMAC_OK = 0,         /** 0  Operation OK */\r
+       GMAC_TIMEOUT = 1,    /** 1  GMAC operation timeout */\r
+       GMAC_TX_BUSY,        /** 2  TX in progress */\r
+       GMAC_RX_NULL,        /** 3  No data received */\r
+       GMAC_SIZE_TOO_SMALL, /** 4  Buffer size not enough */\r
+       GMAC_PARAM,          /** 5  Parameter error, TX packet invalid or RX size too small */\r
+       GMAC_INVALID = 0xFF, /* Invalid */\r
+} gmac_status_t;\r
+\r
+/**\r
+ * \brief Media Independent Interface (MII) type.\r
+ */\r
+typedef enum {\r
+       GMAC_PHY_MII = 0,         /** MII mode */\r
+       GMAC_PHY_RMII = 1,    /** Reduced MII mode */\r
+       GMAC_PHY_INVALID = 0xFF, /* Invalid mode*/\r
+} gmac_mii_mode_t;\r
+\r
+/** Receive buffer descriptor struct */\r
+COMPILER_PACK_SET(8)\r
+typedef struct gmac_rx_descriptor {\r
+       union gmac_rx_addr {\r
+               uint32_t val;\r
+               struct gmac_rx_addr_bm {\r
+                       uint32_t b_ownership:1, /**< User clear, GMAC sets this to 1 once it has successfully written a frame to memory */\r
+                       b_wrap:1,   /**< Marks last descriptor in receive buffer */\r
+                       addr_dw:30; /**< Address in number of DW */\r
+               } bm;\r
+       } addr; /**< Address, Wrap & Ownership */\r
+       union gmac_rx_status {\r
+               uint32_t val;\r
+               struct gmac_rx_status_bm {\r
+                       uint32_t len:13,       /**  0..12  Length of frame including FCS */\r
+                       b_fcs:1,               /**  13     Receive buffer offset,  bits 13:12 of frame length for jumbo frame */\r
+                       b_sof:1,               /**  14     Start of frame */\r
+                       b_eof:1,               /**  15     End of frame */\r
+                       b_cfi:1,               /**  16     Concatenation Format Indicator */\r
+                       vlan_priority:3,       /**  17..19 VLAN priority (if VLAN detected) */\r
+                       b_priority_detected:1, /**  20     Priority tag detected */\r
+                       b_vlan_detected:1,     /**  21     VLAN tag detected */\r
+                       b_type_id_match:2,     /**  22..23 Type ID match */\r
+                       b_checksumoffload:1,   /**  24     Checksum offload specific function */\r
+                       b_addrmatch:2,         /**  25..26 Address register match */\r
+                       b_ext_addr_match:1,    /**  27     External address match found */\r
+                       reserved:1,            /**  28     */\r
+                       b_uni_hash_match:1,    /**  29     Unicast hash match */\r
+                       b_multi_hash_match:1,  /**  30     Multicast hash match */\r
+                       b_boardcast_detect:1;  /**  31     Global broadcast address detected */\r
+               } bm;\r
+       } status;\r
+} gmac_rx_descriptor_t;\r
+\r
+/** Transmit buffer descriptor struct */\r
+COMPILER_PACK_SET(8)\r
+typedef struct gmac_tx_descriptor {\r
+       uint32_t addr;\r
+       union gmac_tx_status {\r
+               uint32_t val;\r
+               struct gmac_tx_status_bm {\r
+                       uint32_t len:14,     /**  0..13 Length of buffer */\r
+                       reserved:1,          /** 14            */\r
+                       b_last_buffer:1,     /** 15     Last buffer (in the current frame) */\r
+                       b_no_crc:1,          /** 16     No CRC */\r
+                       reserved1:3,         /** 17..19        */\r
+                       b_checksumoffload:3, /** 20..22 Transmit checksum generation offload errors */\r
+                       reserved2:3,         /** 23..25        */\r
+                       b_lco:1,             /** 26     Late collision, transmit error detected */\r
+                       b_exhausted:1,       /** 27     Buffer exhausted in mid frame */\r
+                       b_underrun:1,        /** 28     Transmit underrun */\r
+                       b_error:1,           /** 29     Retry limit exceeded, error detected */\r
+                       b_wrap:1,            /** 30     Marks last descriptor in TD list */\r
+                       b_used:1;            /** 31     User clear, GMAC sets this to 1 once a frame has been successfully transmitted */\r
+               } bm;\r
+       } status;\r
+} gmac_tx_descriptor_t;\r
+\r
+COMPILER_PACK_RESET()\r
+\r
+/**\r
+ * \brief Input parameters when initializing the gmac module mode.\r
+ */\r
+typedef struct gmac_options {\r
+       /*  Enable/Disable CopyAllFrame */\r
+       uint8_t uc_copy_all_frame;\r
+       /* Enable/Disable NoBroadCast */\r
+       uint8_t uc_no_boardcast;\r
+       /* MAC address */\r
+       uint8_t uc_mac_addr[GMAC_ADDR_LENGTH];\r
+} gmac_options_t;\r
+\r
+/** RX callback */\r
+typedef void (*gmac_dev_tx_cb_t) (uint32_t ul_status);\r
+/** Wakeup callback */\r
+typedef void (*gmac_dev_wakeup_cb_t) (void);\r
+\r
+/**\r
+ * GMAC driver structure.\r
+ */\r
+typedef struct gmac_device {\r
+\r
+       /** Pointer to HW register base */\r
+       Gmac *p_hw;\r
+       /**\r
+        * Pointer to allocated TX buffer.\r
+        * Section 3.6 of AMBA 2.0 spec states that burst should not cross\r
+        * 1K Boundaries.\r
+        * Receive buffer manager writes are burst of 2 words => 3 lsb bits\r
+        * of the address shall be set to 0.\r
+        */\r
+       uint8_t *p_tx_buffer;\r
+       /** Pointer to allocated RX buffer */\r
+       uint8_t *p_rx_buffer;\r
+       /** Pointer to Rx TDs (must be 8-byte aligned) */\r
+       gmac_rx_descriptor_t *p_rx_dscr;\r
+       /** Pointer to Tx TDs (must be 8-byte aligned) */\r
+       gmac_tx_descriptor_t *p_tx_dscr;\r
+       /** Optional callback to be invoked once a frame has been received */\r
+       gmac_dev_tx_cb_t func_rx_cb;\r
+#if( GMAC_USES_WAKEUP_CALLBACK )\r
+       /** Optional callback to be invoked once several TDs have been released */\r
+       gmac_dev_wakeup_cb_t func_wakeup_cb;\r
+#endif\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+       /** Optional callback list to be invoked once TD has been processed */\r
+       gmac_dev_tx_cb_t *func_tx_cb_list;\r
+#endif\r
+       /** RX TD list size */\r
+       uint32_t ul_rx_list_size;\r
+       /** RX index for current processing TD */\r
+       uint32_t ul_rx_idx;\r
+       /** TX TD list size */\r
+       uint32_t ul_tx_list_size;\r
+       /** Circular buffer head pointer by upper layer (buffer to be sent) */\r
+       int32_t l_tx_head;\r
+       /** Circular buffer tail pointer incremented by handlers (buffer sent) */\r
+       int32_t l_tx_tail;\r
+\r
+       /** Number of free TD before wakeup callback is invoked */\r
+       uint32_t uc_wakeup_threshold;\r
+} gmac_device_t;\r
+\r
+/**\r
+ * \brief Write network control value.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_ncr   Network control value.\r
+ */\r
+static inline void gmac_network_control(Gmac* p_gmac, uint32_t ul_ncr)\r
+{\r
+       p_gmac->GMAC_NCR = ul_ncr;\r
+}\r
+\r
+/**\r
+ * \brief Get network control value.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+\r
+static inline uint32_t gmac_get_network_control(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_NCR;\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable GMAC receive.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable GMAC receiver, else to enable it.\r
+ */\r
+static inline void gmac_enable_receive(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_RXEN;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_RXEN;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable GMAC transmit.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable GMAC transmit, else to enable it.\r
+ */\r
+static inline void gmac_enable_transmit(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_TXEN;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_TXEN;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable GMAC management.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable GMAC management, else to enable it.\r
+ */\r
+static inline void gmac_enable_management(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_MPE;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_MPE;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Clear all statistics registers.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_clear_statistics(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_CLRSTAT;\r
+}\r
+\r
+/**\r
+ * \brief Increase all statistics registers.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_increase_statistics(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_INCSTAT;\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable statistics registers writing.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the statistics registers writing, else to enable it.\r
+ */\r
+static inline void gmac_enable_statistics_write(Gmac* p_gmac,\r
+               uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_WESTAT;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_WESTAT;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief In half-duplex mode, forces collisions on all received frames.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the back pressure, else to enable it.\r
+ */\r
+static inline void gmac_enable_back_pressure(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_BP;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_BP;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Start transmission.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_start_transmission(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_TSTART;\r
+}\r
+\r
+/**\r
+ * \brief Halt transmission.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_halt_transmission(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_THALT;\r
+}\r
+\r
+/**\r
+ * \brief Transmit pause frame.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_tx_pause_frame(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_TXPF;\r
+}\r
+\r
+/**\r
+ * \brief Transmit zero quantum pause frame.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_tx_pause_zero_quantum_frame(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_TXZQPF;\r
+}\r
+\r
+/**\r
+ * \brief Read snapshot.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_read_snapshot(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_RDS;\r
+}\r
+\r
+/**\r
+ * \brief Store receivetime stamp to memory.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to normal operation, else to enable the store.\r
+ */\r
+static inline void gmac_store_rx_time_stamp(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_SRTSM;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_SRTSM;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable PFC priority-based pause reception.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   1 to set the reception, 0 to disable.\r
+ */\r
+static inline void gmac_enable_pfc_pause_frame(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_ENPBPR;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_ENPBPR;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Transmit PFC priority-based pause reception.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_transmit_pfc_pause_frame(Gmac* p_gmac)\r
+{\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_TXPBPF;\r
+}\r
+\r
+/**\r
+ * \brief Flush next packet.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_flush_next_packet(Gmac* p_gmac)\r
+{\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_FNP;\r
+}\r
+\r
+/**\r
+ * \brief Set up network configuration register.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+  * \param ul_cfg   Network configuration value.\r
+ */\r
+static inline void gmac_set_configure(Gmac* p_gmac, uint32_t ul_cfg)\r
+{\r
+       p_gmac->GMAC_NCFGR = ul_cfg;\r
+}\r
+\r
+/**\r
+ * \brief Get network configuration.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return Network configuration.\r
+ */\r
+static inline uint32_t gmac_get_configure(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_NCFGR;\r
+}\r
+\r
+\r
+/* Get and set DMA Configuration Register */\r
+static inline void gmac_set_dma(Gmac* p_gmac, uint32_t ul_cfg)\r
+{\r
+       p_gmac->GMAC_DCFGR = ul_cfg;\r
+}\r
+\r
+static inline uint32_t gmac_get_dma(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_DCFGR;\r
+}\r
+\r
+/**\r
+ * \brief Set speed.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_speed 1 to indicate 100Mbps, 0 to 10Mbps.\r
+ */\r
+static inline void gmac_set_speed(Gmac* p_gmac, uint8_t uc_speed)\r
+{\r
+       if (uc_speed) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_SPD;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_SPD;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable Full-Duplex mode.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the Full-Duplex mode, else to enable it.\r
+ */\r
+static inline void gmac_enable_full_duplex(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_FD;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_FD;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable Copy(Receive) All Valid Frames.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable copying all valid frames, else to enable it.\r
+ */\r
+static inline void gmac_enable_copy_all(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_CAF;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_CAF;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable jumbo frames (up to 10240 bytes).\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the jumbo frames, else to enable it.\r
+ */\r
+static inline void gmac_enable_jumbo_frames(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_JFRAME;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_JFRAME;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Disable/Enable broadcast receiving.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   1 to disable the broadcast, else to enable it.\r
+ */\r
+static inline void gmac_disable_broadcast(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_NBC;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_NBC;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable multicast hash.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the multicast hash, else to enable it.\r
+ */\r
+static inline void gmac_enable_multicast_hash(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_UNIHEN;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_UNIHEN;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable big frames (over 1518, up to 1536).\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable big frames else to enable it.\r
+ */\r
+static inline void gmac_enable_big_frame(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_MAXFS;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_MAXFS;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Set MDC clock divider.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_mck   GMAC MCK.\r
+ *\r
+ * \return GMAC_OK if successfully.\r
+ */\r
+static inline uint8_t gmac_set_mdc_clock(Gmac* p_gmac, uint32_t ul_mck)\r
+{\r
+       uint32_t ul_clk;\r
+       \r
+       if (ul_mck > GMAC_MCK_SPEED_240MHZ) {\r
+               return GMAC_INVALID;\r
+       } else if (ul_mck > GMAC_MCK_SPEED_160MHZ) {\r
+               ul_clk = GMAC_NCFGR_CLK_MCK_96;\r
+       } else if (ul_mck > GMAC_MCK_SPEED_120MHZ) {\r
+               ul_clk = GMAC_NCFGR_CLK_MCK_64;\r
+       } else if (ul_mck > GMAC_MCK_SPEED_80MHZ) {\r
+               ul_clk = GMAC_NCFGR_CLK_MCK_48;\r
+       } else if (ul_mck > GMAC_MCK_SPEED_40MHZ) {\r
+               ul_clk = GMAC_NCFGR_CLK_MCK_32;\r
+       } else if (ul_mck > GMAC_MCK_SPEED_20MHZ) {\r
+               ul_clk = GMAC_NCFGR_CLK_MCK_16;\r
+       } else {\r
+               ul_clk = GMAC_NCFGR_CLK_MCK_8;\r
+       }\r
+       ;\r
+       p_gmac->GMAC_NCFGR = (p_gmac->GMAC_NCFGR & ~GMAC_NCFGR_CLK_Msk) | ul_clk;\r
+       return GMAC_OK;\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable retry test.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the GMAC receiver, else to enable it.\r
+ */\r
+static inline void gmac_enable_retry_test(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RTY;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RTY;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable pause (when a valid pause frame is received).\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable pause frame, else to enable it.\r
+ */\r
+static inline void gmac_enable_pause_frame(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_PEN;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_PEN;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Set receive buffer offset to 0 ~ 3.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_set_rx_buffer_offset(Gmac* p_gmac, uint8_t uc_offset)\r
+{\r
+       p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RXBUFO_Msk;\r
+       p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RXBUFO(uc_offset);\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable receive length field checking.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable receive length field checking, else to enable it.\r
+ */\r
+static inline void gmac_enable_rx_length_check(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_LFERD;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_LFERD;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable discarding FCS field of received frames.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable discarding FCS field of received frames, else to enable it.\r
+ */\r
+static inline void gmac_enable_discard_fcs(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RFCS;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RFCS;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * \brief Enable/Disable frames to be received in half-duplex mode\r
+ * while transmitting.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the received in half-duplex mode, else to enable it.\r
+ */\r
+static inline void gmac_enable_efrhd(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_EFRHD;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_EFRHD;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable ignore RX FCS.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable ignore RX FCS, else to enable it.\r
+ */\r
+static inline void gmac_enable_ignore_rx_fcs(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_IRXFCS;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_IRXFCS;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Get Network Status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return Network status.\r
+ */\r
+static inline uint32_t gmac_get_status(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_NSR;\r
+}\r
+\r
+/**\r
+ * \brief Get MDIO IN pin status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return MDIO IN pin status.\r
+ */\r
+static inline uint8_t gmac_get_MDIO(Gmac* p_gmac)\r
+{\r
+       return ((p_gmac->GMAC_NSR & GMAC_NSR_MDIO) > 0);\r
+}\r
+\r
+/**\r
+ * \brief Check if PHY is idle.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return  1 if PHY is idle.\r
+ */\r
+static inline uint8_t gmac_is_phy_idle(Gmac* p_gmac)\r
+{\r
+       return ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) > 0);\r
+}\r
+\r
+/**\r
+ * \brief Return transmit status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return  Transmit status.\r
+ */\r
+static inline uint32_t gmac_get_tx_status(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_TSR;\r
+}\r
+\r
+/**\r
+ * \brief Clear transmit status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_status   Transmit status.\r
+ */\r
+static inline void gmac_clear_tx_status(Gmac* p_gmac, uint32_t ul_status)\r
+{\r
+       p_gmac->GMAC_TSR = ul_status;\r
+}\r
+\r
+/**\r
+ * \brief Return receive status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline uint32_t gmac_get_rx_status(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_RSR;\r
+}\r
+\r
+/**\r
+ * \brief Clear receive status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_status   Receive status.\r
+ */\r
+static inline void gmac_clear_rx_status(Gmac* p_gmac, uint32_t ul_status)\r
+{\r
+       p_gmac->GMAC_RSR = ul_status;\r
+}\r
+\r
+/**\r
+ * \brief Set Rx Queue.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_addr   Rx queue address.\r
+ */\r
+static inline void gmac_set_rx_queue(Gmac* p_gmac, uint32_t ul_addr)\r
+{\r
+       p_gmac->GMAC_RBQB = GMAC_RBQB_ADDR_Msk & ul_addr;\r
+}\r
+\r
+/**\r
+ * \brief Get Rx Queue Address.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return  Rx queue address.\r
+ */\r
+static inline uint32_t gmac_get_rx_queue(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_RBQB;\r
+}\r
+\r
+/**\r
+ * \brief Set Tx Queue.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_addr  Tx queue address.\r
+ */\r
+static inline void gmac_set_tx_queue(Gmac* p_gmac, uint32_t ul_addr)\r
+{\r
+       p_gmac->GMAC_TBQB = GMAC_TBQB_ADDR_Msk & ul_addr;\r
+}\r
+\r
+/**\r
+ * \brief Get Tx Queue.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return  Rx queue address.\r
+ */\r
+static inline uint32_t gmac_get_tx_queue(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_TBQB;\r
+}\r
+\r
+/**\r
+ * \brief Enable interrupt(s).\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_source   Interrupt source(s) to be enabled.\r
+ */\r
+static inline void gmac_enable_interrupt(Gmac* p_gmac, uint32_t ul_source)\r
+{\r
+       p_gmac->GMAC_IER = ul_source;\r
+}\r
+\r
+/**\r
+ * \brief Disable interrupt(s).\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_source   Interrupt source(s) to be disabled.\r
+ */\r
+static inline void gmac_disable_interrupt(Gmac* p_gmac, uint32_t ul_source)\r
+{\r
+       p_gmac->GMAC_IDR = ul_source;\r
+}\r
+\r
+/**\r
+ * \brief Return interrupt status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return Interrupt status.\r
+ */\r
+static inline uint32_t gmac_get_interrupt_status(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_ISR;\r
+}\r
+\r
+/**\r
+ * \brief Return interrupt mask.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return Interrupt mask.\r
+ */\r
+static inline uint32_t gmac_get_interrupt_mask(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_IMR;\r
+}\r
+\r
+/**\r
+ * \brief Execute PHY maintenance command.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr   PHY address.\r
+ * \param uc_reg_addr   Register address.\r
+ * \param uc_rw   1 to Read, 0 to write.\r
+ * \param us_data   Data to be performed, write only.\r
+ */\r
+static inline void gmac_maintain_phy(Gmac* p_gmac,\r
+               uint8_t uc_phy_addr, uint8_t uc_reg_addr, uint8_t uc_rw,\r
+               uint16_t us_data)\r
+{\r
+       /* Wait until bus idle */\r
+       while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);\r
+       /* Write maintain register */\r
+       p_gmac->GMAC_MAN = GMAC_MAN_WTN(GMAC_MAN_CODE_VALUE)\r
+                       | GMAC_MAN_CLTTO \r
+                       | GMAC_MAN_PHYA(uc_phy_addr)\r
+                       | GMAC_MAN_REGA(uc_reg_addr)\r
+                       | GMAC_MAN_OP((uc_rw ? GMAC_MAN_RW_TYPE : GMAC_MAN_READ_ONLY))\r
+                       | GMAC_MAN_DATA(us_data);\r
+}\r
+\r
+/**\r
+ * \brief Get PHY maintenance data returned.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return Get PHY data.\r
+ */\r
+static inline uint16_t gmac_get_phy_data(Gmac* p_gmac)\r
+{\r
+       /* Wait until bus idle */\r
+       while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);\r
+       /* Return data */\r
+       return (uint16_t) (p_gmac->GMAC_MAN & GMAC_MAN_DATA_Msk);\r
+}\r
+\r
+/**\r
+ * \brief Set Hash.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_hash_top   Hash top.\r
+ * \param ul_hash_bottom   Hash bottom.\r
+ */\r
+static inline void gmac_set_hash(Gmac* p_gmac, uint32_t ul_hash_top,\r
+               uint32_t ul_hash_bottom)\r
+{\r
+       p_gmac->GMAC_HRB = ul_hash_bottom;\r
+       p_gmac->GMAC_HRT = ul_hash_top;\r
+}\r
+\r
+/**\r
+ * \brief Set 64 bits Hash.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ull_hash   64 bits hash value.\r
+ */\r
+static inline void gmac_set_hash64(Gmac* p_gmac, uint64_t ull_hash)\r
+{\r
+       p_gmac->GMAC_HRB = (uint32_t) ull_hash;\r
+       p_gmac->GMAC_HRT = (uint32_t) (ull_hash >> 32);\r
+}\r
+\r
+/**\r
+ * \brief Set MAC Address.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_index  GMAC specific address register index.\r
+ * \param p_mac_addr  GMAC address.\r
+ */\r
+static inline void gmac_set_address(Gmac* p_gmac, uint8_t uc_index,\r
+               uint8_t* p_mac_addr)\r
+{\r
+       p_gmac->GMAC_SA[uc_index].GMAC_SAB = (p_mac_addr[3] << 24)\r
+                       | (p_mac_addr[2] << 16)\r
+                       | (p_mac_addr[1] << 8)\r
+                       | (p_mac_addr[0]);\r
+       p_gmac->GMAC_SA[uc_index].GMAC_SAT = (p_mac_addr[5] << 8)\r
+                       | (p_mac_addr[4]);\r
+}\r
+\r
+/**\r
+ * \brief Set MAC Address via 2 dword.\r
+  *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_index  GMAC specific address register index.\r
+ * \param ul_mac_top  GMAC top address.\r
+ * \param ul_mac_bottom  GMAC bottom address.\r
+ */\r
+static inline void gmac_set_address32(Gmac* p_gmac, uint8_t uc_index,\r
+               uint32_t ul_mac_top, uint32_t ul_mac_bottom)\r
+{\r
+       p_gmac->GMAC_SA[uc_index].GMAC_SAB = ul_mac_bottom;\r
+       p_gmac->GMAC_SA[uc_index].GMAC_SAT = ul_mac_top;\r
+}\r
+\r
+/**\r
+ * \brief Set MAC Address via int64.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_index  GMAC specific address register index.\r
+ * \param ull_mac  64-bit GMAC address.\r
+ */\r
+static inline void gmac_set_address64(Gmac* p_gmac, uint8_t uc_index,\r
+               uint64_t ull_mac)\r
+{\r
+       p_gmac->GMAC_SA[uc_index].GMAC_SAB = (uint32_t) ull_mac;\r
+       p_gmac->GMAC_SA[uc_index].GMAC_SAT = (uint32_t) (ull_mac >> 32);\r
+}\r
+\r
+/**\r
+ * \brief Select media independent interface mode.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param mode   Media independent interface mode.\r
+ */\r
+static inline void gmac_select_mii_mode(Gmac* p_gmac, gmac_mii_mode_t mode)\r
+{\r
+       switch (mode) {\r
+               case GMAC_PHY_MII:\r
+               case GMAC_PHY_RMII:\r
+                       p_gmac->GMAC_UR |= GMAC_UR_RMIIMII;\r
+               break;\r
+\r
+               default:\r
+                       p_gmac->GMAC_UR &= ~GMAC_UR_RMIIMII;\r
+               break;\r
+       }\r
+}\r
+\r
+uint8_t gmac_phy_read(Gmac* p_gmac, uint8_t uc_phy_address, uint8_t uc_address,\r
+               uint32_t* p_value);\r
+uint8_t gmac_phy_write(Gmac* p_gmac, uint8_t uc_phy_address,\r
+               uint8_t uc_address, uint32_t ul_value);\r
+void gmac_dev_init(Gmac* p_gmac, gmac_device_t* p_gmac_dev,\r
+               gmac_options_t* p_opt);\r
+uint32_t gmac_dev_read(gmac_device_t* p_gmac_dev, uint8_t* p_frame,\r
+               uint32_t ul_frame_size, uint32_t* p_rcv_size);\r
+uint32_t gmac_dev_write(gmac_device_t* p_gmac_dev, void *p_buffer,\r
+               uint32_t ul_size, gmac_dev_tx_cb_t func_tx_cb);\r
+uint32_t gmac_dev_get_tx_load(gmac_device_t* p_gmac_dev);\r
+void gmac_dev_set_rx_callback(gmac_device_t* p_gmac_dev,\r
+               gmac_dev_tx_cb_t func_rx_cb);\r
+uint8_t gmac_dev_set_tx_wakeup_callback(gmac_device_t* p_gmac_dev,\r
+               gmac_dev_wakeup_cb_t func_wakeup, uint8_t uc_threshold);\r
+void gmac_dev_reset(gmac_device_t* p_gmac_dev);\r
+void gmac_handler(gmac_device_t* p_gmac_dev);\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
+\r
+/**\r
+ * \page gmac_quickstart Quickstart guide for GMAC driver.\r
+ *\r
+ * This is the quickstart guide for the \ref gmac_group "Ethernet MAC",\r
+ * with step-by-step instructions on how to configure and use the driver in a\r
+ * selection of use cases.\r
+ *\r
+ * The use cases contain several code fragments. The code fragments in the\r
+ * steps for setup can be copied into a custom initialization function, while\r
+ * the steps for usage can be copied into, e.g., the main application function.\r
+ *\r
+ * \section gmac_basic_use_case Basic use case\r
+ * In the basic use case, the GMAC driver are configured for:\r
+ * - PHY component KSZ8051MNL is used\r
+ * - GMAC uses MII mode\r
+ * - The number of receive buffer is 16\r
+ * - The number of transfer buffer is 8\r
+ * - MAC address is set to 00-04-25-1c-a0-02\r
+ * - IP address is set to 192.168.0.2\r
+ * - IP address is set to 192.168.0.2\r
+ * - Gateway is set to 192.168.0.1\r
+ * - Network mask is 255.255.255.0\r
+ * - PHY operation max retry count is 1000000\r
+ * - GMAC is configured to not support copy all frame and support broadcast\r
+ * - The data will be read from the ethernet\r
+ *\r
+ * \section gmac_basic_use_case_setup Setup steps\r
+ *\r
+ * \subsection gmac_basic_use_case_setup_prereq Prerequisites\r
+ * -# \ref sysclk_group "System Clock Management (sysclock)"\r
+ * -# \ref pmc_group "Power Management Controller (pmc)"\r
+ * -# \ref ksz8051mnl_ethernet_phy_group "PHY component (KSZ8051MNL)"\r
+ *\r
+ * \subsection gmac_basic_use_case_setup_code Example code\r
+ * Content of conf_eth.h\r
+ * \code\r
+ * #define GMAC_RX_BUFFERS                               16\r
+ * #define GMAC_TX_BUFFERS                               8\r
+ * #define MAC_PHY_RETRY_MAX                             1000000\r
+ * #define ETHERNET_CONF_ETHADDR0                        0x00\r
+ * #define ETHERNET_CONF_ETHADDR0                        0x00\r
+ * #define ETHERNET_CONF_ETHADDR1                        0x04\r
+ * #define ETHERNET_CONF_ETHADDR2                        0x25\r
+ * #define ETHERNET_CONF_ETHADDR3                        0x1C\r
+ * #define ETHERNET_CONF_ETHADDR4                        0xA0\r
+ * #define ETHERNET_CONF_ETHADDR5                        0x02\r
+ * #define ETHERNET_CONF_IPADDR0                         192\r
+ * #define ETHERNET_CONF_IPADDR1                         168\r
+ * #define ETHERNET_CONF_IPADDR2                         0\r
+ * #define ETHERNET_CONF_IPADDR3                         2\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR0                   192\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR1                   168\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR2                   0\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR3                   1\r
+ * #define ETHERNET_CONF_NET_MASK0                       255\r
+ * #define ETHERNET_CONF_NET_MASK1                       255\r
+ * #define ETHERNET_CONF_NET_MASK2                       255\r
+ * #define ETHERNET_CONF_NET_MASK3                       0\r
+ * #define ETH_PHY_MODE                                  ETH_PHY_MODE\r
+ * \endcode\r
+ *\r
+ * A specific gmac device and the receive data buffer must be defined; another ul_frm_size should be defined\r
+ * to trace the actual size of the data received.\r
+ * \code\r
+ * static gmac_device_t gs_gmac_dev;\r
+ * static volatile uint8_t gs_uc_eth_buffer[GMAC_FRAME_LENTGH_MAX];\r
+ *\r
+ * uint32_t ul_frm_size;\r
+ * \endcode\r
+ *\r
+ * Add to application C-file:\r
+ * \code\r
+ *   void gmac_init(void)\r
+ *   {\r
+ *       sysclk_init();\r
+ *\r
+ *       board_init();\r
+ *\r
+ *       pmc_enable_periph_clk(ID_GMAC);\r
+ *\r
+ *       gmac_option.uc_copy_all_frame = 0;\r
+ *       gmac_option.uc_no_boardcast = 0;\r
+ *       memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));\r
+ *       gs_gmac_dev.p_hw = GMAC;\r
+ *\r
+ *       gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option);\r
+ *\r
+ *       NVIC_EnableIRQ(GMAC_IRQn);\r
+ *\r
+ *       ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz());\r
+ * \r
+ *       ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR);\r
+ *\r
+ *       ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1);\r
+ * \endcode\r
+ *\r
+ * \subsection gmac_basic_use_case_setup_flow Workflow\r
+ * - Ensure that conf_eth.h is present and contains the\r
+ * following configuration symbol. This configuration file is used\r
+ * by the driver and should not be included by the application.\r
+ * -# Define the receiving buffer size used in the internal GMAC driver.\r
+ * The buffer size used for RX is GMAC_RX_BUFFERS * 128.\r
+ * If it was supposed receiving a large number of frame, the\r
+ * GMAC_RX_BUFFERS should be set higher. E.g., the application wants to accept\r
+ * a ping echo test of 2048, the GMAC_RX_BUFFERS should be set at least \r
+ * (2048/128)=16, and as there are additional frames coming, a preferred\r
+ * number is 24 depending on a normal Ethernet throughput.\r
+ *   - \code\r
+ *        #define GMAC_RX_BUFFERS                               16\r
+ *   \endcode\r
+ * -# Define the transmitting buffer size used in the internal GMAC driver.\r
+ * The buffer size used for TX is GMAC_TX_BUFFERS * 1518.\r
+ *   - \code\r
+ *        #define GMAC_TX_BUFFERS                               8\r
+ *   \endcode\r
+ * -# Define maximum retry time for a PHY read/write operation.\r
+ *   - \code\r
+ *        #define MAC_PHY_RETRY_MAX                             1000000\r
+ *   \endcode\r
+ * -# Define the MAC address. 00:04:25:1C:A0:02 is the address reserved\r
+ * for ATMEL, application should always change this address to its' own.\r
+ *   - \code\r
+ *        #define ETHERNET_CONF_ETHADDR0                        0x00\r
+ *        #define ETHERNET_CONF_ETHADDR1                        0x04\r
+ *        #define ETHERNET_CONF_ETHADDR2                        0x25\r
+ *        #define ETHERNET_CONF_ETHADDR3                        0x1C\r
+ *        #define ETHERNET_CONF_ETHADDR4                        0xA0\r
+ *        #define ETHERNET_CONF_ETHADDR5                        0x02\r
+ *   \endcode\r
+ * -# Define the IP address configration used in the application. When DHCP\r
+ *  is enabled, this configuration is not effected.\r
+ *   - \code\r
+ *        #define ETHERNET_CONF_IPADDR0                         192\r
+ *        #define ETHERNET_CONF_IPADDR1                         168\r
+ *        #define ETHERNET_CONF_IPADDR2                         0\r
+ *        #define ETHERNET_CONF_IPADDR3                         2\r
+ *        #define ETHERNET_CONF_GATEWAY_ADDR0                   192\r
+ *        #define ETHERNET_CONF_GATEWAY_ADDR1                   168\r
+ *        #define ETHERNET_CONF_GATEWAY_ADDR2                   0\r
+ *        #define ETHERNET_CONF_GATEWAY_ADDR3                   1\r
+ *        #define ETHERNET_CONF_NET_MASK0                       255\r
+ *        #define ETHERNET_CONF_NET_MASK1                       255\r
+ *        #define ETHERNET_CONF_NET_MASK2                       255\r
+ *        #define ETHERNET_CONF_NET_MASK3                       0\r
+ *   \endcode\r
+ * -# Configure the PHY maintainance interface.\r
+ *   - \code\r
+ *        #define ETH_PHY_MODE                                  GMAC_PHY_MII\r
+ *   \endcode\r
+ * -# Enable the system clock:\r
+ *   - \code sysclk_init(); \endcode\r
+ * -# Enable PIO configurations for GMAC:\r
+ *   - \code board_init(); \endcode\r
+ * -# Enable PMC clock for GMAC:\r
+ *   - \code pmc_enable_periph_clk(ID_GMAC); \endcode\r
+ * -# Set the GMAC options; it's set to copy all frame and support broadcast:\r
+ *   - \code\r
+ *         gmac_option.uc_copy_all_frame = 0;\r
+ *         gmac_option.uc_no_boardcast = 0;\r
+ *         memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));\r
+ *         gs_gmac_dev.p_hw = GMAC;\r
+ * \endcode\r
+ * -# Initialize GMAC device with the filled option:\r
+ *   - \code\r
+ *         gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option);\r
+ * \endcode\r
+ * -# Enable the interrupt service for GMAC:\r
+ *   - \code\r
+ *         NVIC_EnableIRQ(GMAC_IRQn);\r
+ * \endcode\r
+ * -# Initialize the PHY component:\r
+ *   - \code\r
+ *         ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz());\r
+ * \endcode\r
+  * -# The link will be established based on auto negotiation.\r
+ *   - \code\r
+ *         ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR);\r
+ * \endcode\r
+ * -# Establish the ethernet link; the network can be worked from now on:\r
+ *   - \code\r
+ *         ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1);\r
+ * \endcode\r
+ *\r
+ * \section gmac_basic_use_case_usage Usage steps\r
+ * \subsection gmac_basic_use_case_usage_code Example code\r
+ * Add to, e.g., main loop in application C-file:\r
+ * \code\r
+ *    gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size));\r
+ * \endcode\r
+ *\r
+ * \subsection gmac_basic_use_case_usage_flow Workflow\r
+ * -# Start reading the data from the ethernet:\r
+ *   - \code gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size)); \endcode\r
+ */\r
+\r
+#      define GMAC_STATS 0\r
+\r
+#if( GMAC_STATS != 0 )\r
+\r
+       /* Here below some code to study the types and\r
+       frequencies of  GMAC interrupts. */\r
+       #define GMAC_IDX_RXUBR 0\r
+       #define GMAC_IDX_TUR   1\r
+       #define GMAC_IDX_RLEX  2\r
+       #define GMAC_IDX_TFC   3\r
+       #define GMAC_IDX_RCOMP 4\r
+       #define GMAC_IDX_TCOMP 5\r
+       #define GMAC_IDX_ROVR  6\r
+       #define GMAC_IDX_HRESP 7\r
+       #define GMAC_IDX_PFNZ  8\r
+       #define GMAC_IDX_PTZ   9\r
+\r
+       struct SGmacStats {\r
+               unsigned recvCount;\r
+               unsigned rovrCount;\r
+               unsigned bnaCount;\r
+               unsigned sendCount;\r
+               unsigned sovrCount;\r
+               unsigned incompCount;\r
+               unsigned truncCount;\r
+\r
+               unsigned intStatus[10];\r
+       };\r
+       extern struct SGmacStats gmacStats;\r
+\r
+       struct SIntPair {\r
+               const char *name;\r
+               unsigned mask;\r
+               int index;\r
+       };\r
+\r
+       #define MK_PAIR( NAME )   #NAME, GMAC_IER_##NAME, GMAC_IDX_##NAME\r
+       static const struct SIntPair intPairs[] = {\r
+               { MK_PAIR( RXUBR ) }, /* Enable receive used bit read interrupt. */\r
+               { MK_PAIR( TUR   ) }, /* Enable transmit underrun interrupt. */\r
+               { MK_PAIR( RLEX  ) }, /* Enable retry limit  exceeded interrupt. */\r
+               { MK_PAIR( TFC   ) }, /* Enable transmit buffers exhausted in mid-frame interrupt. */\r
+               { MK_PAIR( RCOMP ) }, /* Receive complete */\r
+               { MK_PAIR( TCOMP ) }, /* Enable transmit complete interrupt. */\r
+               { MK_PAIR( ROVR  ) }, /* Enable receive overrun interrupt. */\r
+               { MK_PAIR( HRESP ) }, /* Enable Hresp not OK interrupt. */\r
+               { MK_PAIR( PFNZ  ) }, /* Enable pause frame received interrupt. */\r
+               { MK_PAIR( PTZ   ) }  /* Enable pause time zero interrupt. */\r
+       };\r
+\r
+       void gmac_show_irq_counts ();\r
+\r
+#endif\r
+\r
+#endif /* GMAC_H_INCLUDED */\r
index dd29dfe7896eb4524a1e749c24f6f70c5e443ac8..24d806d949c3da4c490b6868cd76ed9e35cec586 100644 (file)
- /**
- * \file
- *
- * \brief GMAC (Ethernet MAC) driver for SAM.
- *
- * Copyright (c) 2013 Atmel Corporation. All rights reserved.
- *
- * \asf_license_start
- *
- * \page License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *
- * 3. The name of Atmel may not be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * 4. This software may only be redistributed and used in connection with an
- *    Atmel microcontroller product.
- *
- * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
- * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * \asf_license_stop
- *
- */
-
-#ifndef GMAC_H_INCLUDED
-#define GMAC_H_INCLUDED
-
-#include "compiler.h"
-#include "component/gmac.h"
-
-/// @cond 0
-/**INDENT-OFF**/
-#ifdef __cplusplus
-extern "C" {
-#endif
-/**INDENT-ON**/
-/// @endcond
-
-/** The buffer addresses written into the descriptors must be aligned, so the
-    last few bits are zero.  These bits have special meaning for the GMAC
-    peripheral and cannot be used as part of the address. */
-#define GMAC_RXD_ADDR_MASK      0xFFFFFFFC
-#define GMAC_RXD_WRAP         (1ul << 1)  /**< Wrap bit */
-#define GMAC_RXD_OWNERSHIP    (1ul << 0)  /**< Ownership bit */
-
-#define GMAC_RXD_BROADCAST    (1ul << 31) /**< Broadcast detected */
-#define GMAC_RXD_MULTIHASH    (1ul << 30) /**< Multicast hash match */
-#define GMAC_RXD_UNIHASH      (1ul << 29) /**< Unicast hash match */
-#define GMAC_RXD_ADDR_FOUND      (1ul << 27) /**< Specific address match found */
-#define GMAC_RXD_ADDR        (3ul << 25) /**< Address match */
-#define GMAC_RXD_RXCOEN        (1ul << 24) /**< RXCOEN related function */
-#define GMAC_RXD_TYPE         (3ul << 22) /**< Type ID match */
-#define GMAC_RXD_VLAN         (1ul << 21) /**< VLAN tag detected */
-#define GMAC_RXD_PRIORITY     (1ul << 20) /**< Priority tag detected */
-#define GMAC_RXD_PRIORITY_MASK  (3ul << 17) /**< VLAN priority */
-#define GMAC_RXD_CFI          (1ul << 16) /**< Concatenation Format Indicator only if bit 21 is set */
-#define GMAC_RXD_EOF          (1ul << 15) /**< End of frame */
-#define GMAC_RXD_SOF          (1ul << 14) /**< Start of frame */
-#define GMAC_RXD_FCS          (1ul << 13) /**< Frame check sequence */
-#define GMAC_RXD_OFFSET_MASK                /**< Receive buffer offset */
-#define GMAC_RXD_LEN_MASK       (0xFFF)     /**< Length of frame including FCS (if selected) */
-#define GMAC_RXD_LENJUMBO_MASK  (0x3FFF)    /**< Jumbo frame length */
-
-#define GMAC_TXD_USED         (1ul << 31) /**< Frame is transmitted */
-#define GMAC_TXD_WRAP         (1ul << 30) /**< Last descriptor */
-#define GMAC_TXD_ERROR        (1ul << 29) /**< Retry limit exceeded, error */
-#define GMAC_TXD_UNDERRUN     (1ul << 28) /**< Transmit underrun */
-#define GMAC_TXD_EXHAUSTED    (1ul << 27) /**< Buffer exhausted */
-#define GMAC_TXD_LATE    (1ul << 26) /**< Late collision,transmit  error  */
-#define GMAC_TXD_CHECKSUM_ERROR   (7ul << 20) /**< Checksum error */
-#define GMAC_TXD_NOCRC        (1ul << 16) /**< No CRC */
-#define GMAC_TXD_LAST         (1ul << 15) /**< Last buffer in frame */
-#define GMAC_TXD_LEN_MASK       (0x1FFF)     /**< Length of buffer */
-
-/** The MAC can support frame lengths up to 1536 bytes */
-#define GMAC_FRAME_LENTGH_MAX       1536
-
-#define GMAC_RX_UNITSIZE            128     /**< Fixed size for RX buffer  */
-#define GMAC_TX_UNITSIZE            1518    /**< Size for ETH frame length */
-
-/** GMAC clock speed */
-#define GMAC_MCK_SPEED_240MHZ        (240*1000*1000)
-#define GMAC_MCK_SPEED_160MHZ        (160*1000*1000)
-#define GMAC_MCK_SPEED_120MHZ        (120*1000*1000)
-#define GMAC_MCK_SPEED_80MHZ          (80*1000*1000)
-#define GMAC_MCK_SPEED_40MHZ          (40*1000*1000)
-#define GMAC_MCK_SPEED_20MHZ          (20*1000*1000)
-
-/** GMAC maintain code default value*/
-#define GMAC_MAN_CODE_VALUE    (10)
-
-/** GMAC maintain start of frame default value*/
-#define GMAC_MAN_SOF_VALUE     (1)
-
-/** GMAC maintain read/write*/
-#define GMAC_MAN_RW_TYPE       (2)
-
-/** GMAC maintain read only*/
-#define GMAC_MAN_READ_ONLY     (1)
-
-/** GMAC address length */
-#define GMAC_ADDR_LENGTH       (6)
-
-
-#define GMAC_DUPLEX_HALF 0
-#define GMAC_DUPLEX_FULL 1
-
-#define GMAC_SPEED_10M      0
-#define GMAC_SPEED_100M     1
-
-/**
- * \brief Return codes for GMAC APIs.
- */
-typedef enum {
-       GMAC_OK = 0,         /** 0  Operation OK */
-       GMAC_TIMEOUT = 1,    /** 1  GMAC operation timeout */
-       GMAC_TX_BUSY,        /** 2  TX in progress */
-       GMAC_RX_NULL,        /** 3  No data received */
-       GMAC_SIZE_TOO_SMALL, /** 4  Buffer size not enough */
-       GMAC_PARAM,          /** 5  Parameter error, TX packet invalid or RX size too small */
-       GMAC_INVALID = 0xFF, /* Invalid */
-} gmac_status_t;
-
-/**
- * \brief Media Independent Interface (MII) type.
- */
-typedef enum {
-       GMAC_PHY_MII = 0,         /** MII mode */
-       GMAC_PHY_RMII = 1,    /** Reduced MII mode */
-       GMAC_PHY_INVALID = 0xFF, /* Invalid mode*/
-} gmac_mii_mode_t;
-
-/** Receive buffer descriptor struct */
-COMPILER_PACK_SET(8)
-typedef struct gmac_rx_descriptor {
-       union gmac_rx_addr {
-               uint32_t val;
-               struct gmac_rx_addr_bm {
-                       uint32_t b_ownership:1, /**< User clear, GMAC sets this to 1 once it has successfully written a frame to memory */
-                       b_wrap:1,   /**< Marks last descriptor in receive buffer */
-                       addr_dw:30; /**< Address in number of DW */
-               } bm;
-       } addr; /**< Address, Wrap & Ownership */
-       union gmac_rx_status {
-               uint32_t val;
-               struct gmac_rx_status_bm {
-                       uint32_t len:13,       /**  0..12  Length of frame including FCS */
-                       b_fcs:1,               /**  13     Receive buffer offset,  bits 13:12 of frame length for jumbo frame */
-                       b_sof:1,               /**  14     Start of frame */
-                       b_eof:1,               /**  15     End of frame */
-                       b_cfi:1,               /**  16     Concatenation Format Indicator */
-                       vlan_priority:3,       /**  17..19 VLAN priority (if VLAN detected) */
-                       b_priority_detected:1, /**  20     Priority tag detected */
-                       b_vlan_detected:1,     /**  21     VLAN tag detected */
-                       b_type_id_match:2,     /**  22..23 Type ID match */
-                       b_checksumoffload:1,   /**  24     Checksum offload specific function */
-                       b_addrmatch:2,         /**  25..26 Address register match */
-                       b_ext_addr_match:1,    /**  27     External address match found */
-                       reserved:1,            /**  28     */
-                       b_uni_hash_match:1,    /**  29     Unicast hash match */
-                       b_multi_hash_match:1,  /**  30     Multicast hash match */
-                       b_boardcast_detect:1;  /**  31     Global broadcast address detected */
-               } bm;
-       } status;
-} gmac_rx_descriptor_t;
-
-/** Transmit buffer descriptor struct */
-COMPILER_PACK_SET(8)
-typedef struct gmac_tx_descriptor {
-       uint32_t addr;
-       union gmac_tx_status {
-               uint32_t val;
-               struct gmac_tx_status_bm {
-                       uint32_t len:14,     /**  0..13 Length of buffer */
-                       reserved:1,          /** 14            */
-                       b_last_buffer:1,     /** 15     Last buffer (in the current frame) */
-                       b_no_crc:1,          /** 16     No CRC */
-                       reserved1:3,         /** 17..19        */
-                       b_checksumoffload:3, /** 20..22 Transmit checksum generation offload errors */
-                       reserved2:3,         /** 23..25        */
-                       b_lco:1,             /** 26     Late collision, transmit error detected */
-                       b_exhausted:1,       /** 27     Buffer exhausted in mid frame */
-                       b_underrun:1,        /** 28     Transmit underrun */
-                       b_error:1,           /** 29     Retry limit exceeded, error detected */
-                       b_wrap:1,            /** 30     Marks last descriptor in TD list */
-                       b_used:1;            /** 31     User clear, GMAC sets this to 1 once a frame has been successfully transmitted */
-               } bm;
-       } status;
-} gmac_tx_descriptor_t;
-
-COMPILER_PACK_RESET()
-
-/**
- * \brief Input parameters when initializing the gmac module mode.
- */
-typedef struct gmac_options {
-       /*  Enable/Disable CopyAllFrame */
-       uint8_t uc_copy_all_frame;
-       /* Enable/Disable NoBroadCast */
-       uint8_t uc_no_boardcast;
-       /* MAC address */
-       uint8_t uc_mac_addr[GMAC_ADDR_LENGTH];
-} gmac_options_t;
-
-/** TX callback */
-typedef void (*gmac_dev_tx_cb_t) (uint32_t ul_status, uint8_t *puc_buffer);
-/** RX callback */
-typedef void (*gmac_dev_rx_cb_t) (uint32_t ul_status);
-/** Wakeup callback */
-typedef void (*gmac_dev_wakeup_cb_t) (void);
-
-/**
- * GMAC driver structure.
- */
-typedef struct gmac_device {
-
-       /** Pointer to HW register base */
-       Gmac *p_hw;
-       /**
-        * Pointer to allocated TX buffer.
-        * Section 3.6 of AMBA 2.0 spec states that burst should not cross
-        * 1K Boundaries.
-        * Receive buffer manager writes are burst of 2 words => 3 lsb bits
-        * of the address shall be set to 0.
-        */
-       uint8_t *p_tx_buffer;
-       /** Pointer to allocated RX buffer */
-       uint8_t *p_rx_buffer;
-       /** Pointer to Rx TDs (must be 8-byte aligned) */
-       gmac_rx_descriptor_t *p_rx_dscr;
-       /** Pointer to Tx TDs (must be 8-byte aligned) */
-       gmac_tx_descriptor_t *p_tx_dscr;
-       /** Optional callback to be invoked once a frame has been received */
-       gmac_dev_rx_cb_t func_rx_cb;
-#if( GMAC_USES_WAKEUP_CALLBACK )
-       /** Optional callback to be invoked once several TDs have been released */
-       gmac_dev_wakeup_cb_t func_wakeup_cb;
-#endif
-#if( GMAC_USES_TX_CALLBACK != 0 )
-       /** Optional callback list to be invoked once TD has been processed */
-       gmac_dev_tx_cb_t *func_tx_cb_list;
-#endif
-       /** RX TD list size */
-       uint32_t ul_rx_list_size;
-       /** RX index for current processing TD */
-       uint32_t ul_rx_idx;
-       /** TX TD list size */
-       uint32_t ul_tx_list_size;
-       /** Circular buffer head pointer by upper layer (buffer to be sent) */
-       int32_t l_tx_head;
-       /** Circular buffer tail pointer incremented by handlers (buffer sent) */
-       int32_t l_tx_tail;
-
-       /** Number of free TD before wakeup callback is invoked */
-       uint32_t uc_wakeup_threshold;
-} gmac_device_t;
-
-/**
- * \brief Write network control value.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param ul_ncr   Network control value.
- */
-static inline void gmac_network_control(Gmac* p_gmac, uint32_t ul_ncr)
-{
-       p_gmac->GMAC_NCR = ul_ncr;
-}
-
-/**
- * \brief Get network control value.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- */
-
-static inline uint32_t gmac_get_network_control(Gmac* p_gmac)
-{
-       return p_gmac->GMAC_NCR;
-}
-
-/**
- * \brief Enable/Disable GMAC receive.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable GMAC receiver, else to enable it.
- */
-static inline void gmac_enable_receive(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCR |= GMAC_NCR_RXEN;
-       } else {
-               p_gmac->GMAC_NCR &= ~GMAC_NCR_RXEN;
-       }
-}
-
-/**
- * \brief Enable/Disable GMAC transmit.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable GMAC transmit, else to enable it.
- */
-static inline void gmac_enable_transmit(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCR |= GMAC_NCR_TXEN;
-       } else {
-               p_gmac->GMAC_NCR &= ~GMAC_NCR_TXEN;
-       }
-}
-
-/**
- * \brief Enable/Disable GMAC management.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable GMAC management, else to enable it.
- */
-static inline void gmac_enable_management(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCR |= GMAC_NCR_MPE;
-       } else {
-               p_gmac->GMAC_NCR &= ~GMAC_NCR_MPE;
-       }
-}
-
-/**
- * \brief Clear all statistics registers.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- */
-static inline void gmac_clear_statistics(Gmac* p_gmac)
-{
-       p_gmac->GMAC_NCR |= GMAC_NCR_CLRSTAT;
-}
-
-/**
- * \brief Increase all statistics registers.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- */
-static inline void gmac_increase_statistics(Gmac* p_gmac)
-{
-       p_gmac->GMAC_NCR |= GMAC_NCR_INCSTAT;
-}
-
-/**
- * \brief Enable/Disable statistics registers writing.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable the statistics registers writing, else to enable it.
- */
-static inline void gmac_enable_statistics_write(Gmac* p_gmac,
-               uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCR |= GMAC_NCR_WESTAT;
-       } else {
-               p_gmac->GMAC_NCR &= ~GMAC_NCR_WESTAT;
-       }
-}
-
-/**
- * \brief In half-duplex mode, forces collisions on all received frames.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable the back pressure, else to enable it.
- */
-static inline void gmac_enable_back_pressure(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCR |= GMAC_NCR_BP;
-       } else {
-               p_gmac->GMAC_NCR &= ~GMAC_NCR_BP;
-       }
-}
-
-/**
- * \brief Start transmission.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- */
-static inline void gmac_start_transmission(Gmac* p_gmac)
-{
-       p_gmac->GMAC_NCR |= GMAC_NCR_TSTART;
-}
-
-/**
- * \brief Halt transmission.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- */
-static inline void gmac_halt_transmission(Gmac* p_gmac)
-{
-       p_gmac->GMAC_NCR |= GMAC_NCR_THALT;
-}
-
-/**
- * \brief Transmit pause frame.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- */
-static inline void gmac_tx_pause_frame(Gmac* p_gmac)
-{
-       p_gmac->GMAC_NCR |= GMAC_NCR_TXPF;
-}
-
-/**
- * \brief Transmit zero quantum pause frame.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- */
-static inline void gmac_tx_pause_zero_quantum_frame(Gmac* p_gmac)
-{
-       p_gmac->GMAC_NCR |= GMAC_NCR_TXZQPF;
-}
-
-/**
- * \brief Read snapshot.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- */
-static inline void gmac_read_snapshot(Gmac* p_gmac)
-{
-       p_gmac->GMAC_NCR |= GMAC_NCR_RDS;
-}
-
-/**
- * \brief Store receivetime stamp to memory.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to normal operation, else to enable the store.
- */
-static inline void gmac_store_rx_time_stamp(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCR |= GMAC_NCR_SRTSM;
-       } else {
-               p_gmac->GMAC_NCR &= ~GMAC_NCR_SRTSM;
-       }
-}
-
-/**
- * \brief Enable PFC priority-based pause reception.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   1 to set the reception, 0 to disable.
- */
-static inline void gmac_enable_pfc_pause_frame(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCR |= GMAC_NCR_ENPBPR;
-       } else {
-               p_gmac->GMAC_NCR &= ~GMAC_NCR_ENPBPR;
-       }
-}
-
-/**
- * \brief Transmit PFC priority-based pause reception.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- */
-static inline void gmac_transmit_pfc_pause_frame(Gmac* p_gmac)
-{
-               p_gmac->GMAC_NCR |= GMAC_NCR_TXPBPF;
-}
-
-/**
- * \brief Flush next packet.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- */
-static inline void gmac_flush_next_packet(Gmac* p_gmac)
-{
-               p_gmac->GMAC_NCR |= GMAC_NCR_FNP;
-}
-
-/**
- * \brief Set up network configuration register.
- *
- * \param p_gmac   Pointer to the GMAC instance.
-  * \param ul_cfg   Network configuration value.
- */
-static inline void gmac_set_configure(Gmac* p_gmac, uint32_t ul_cfg)
-{
-       p_gmac->GMAC_NCFGR = ul_cfg;
-}
-
-/**
- * \brief Get network configuration.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- *
- * \return Network configuration.
- */
-static inline uint32_t gmac_get_configure(Gmac* p_gmac)
-{
-       return p_gmac->GMAC_NCFGR;
-}
-
-
-/* Get and set DMA Configuration Register */
-static inline void gmac_set_dma(Gmac* p_gmac, uint32_t ul_cfg)
-{
-       p_gmac->GMAC_DCFGR = ul_cfg;
-}
-
-static inline uint32_t gmac_get_dma(Gmac* p_gmac)
-{
-       return p_gmac->GMAC_DCFGR;
-}
-
-/**
- * \brief Set speed.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_speed 1 to indicate 100Mbps, 0 to 10Mbps.
- */
-static inline void gmac_set_speed(Gmac* p_gmac, uint8_t uc_speed)
-{
-       if (uc_speed) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_SPD;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_SPD;
-       }
-}
-
-/**
- * \brief Enable/Disable Full-Duplex mode.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable the Full-Duplex mode, else to enable it.
- */
-static inline void gmac_enable_full_duplex(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_FD;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_FD;
-       }
-}
-
-/**
- * \brief Enable/Disable Copy(Receive) All Valid Frames.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable copying all valid frames, else to enable it.
- */
-static inline void gmac_enable_copy_all(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_CAF;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_CAF;
-       }
-}
-
-/**
- * \brief Enable/Disable jumbo frames (up to 10240 bytes).
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable the jumbo frames, else to enable it.
- */
-static inline void gmac_enable_jumbo_frames(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_JFRAME;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_JFRAME;
-       }
-}
-
-/**
- * \brief Disable/Enable broadcast receiving.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   1 to disable the broadcast, else to enable it.
- */
-static inline void gmac_disable_broadcast(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_NBC;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_NBC;
-       }
-}
-
-/**
- * \brief Enable/Disable multicast hash.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable the multicast hash, else to enable it.
- */
-static inline void gmac_enable_multicast_hash(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_UNIHEN;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_UNIHEN;
-       }
-}
-
-/**
- * \brief Enable/Disable big frames (over 1518, up to 1536).
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable big frames else to enable it.
- */
-static inline void gmac_enable_big_frame(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_MAXFS;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_MAXFS;
-       }
-}
-
-/**
- * \brief Set MDC clock divider.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param ul_mck   GMAC MCK.
- *
- * \return GMAC_OK if successfully.
- */
-static inline uint8_t gmac_set_mdc_clock(Gmac* p_gmac, uint32_t ul_mck)
-{
-       uint32_t ul_clk;
-
-       if (ul_mck > GMAC_MCK_SPEED_240MHZ) {
-               return GMAC_INVALID;
-       } else if (ul_mck > GMAC_MCK_SPEED_160MHZ) {
-               ul_clk = GMAC_NCFGR_CLK_MCK_96;
-       } else if (ul_mck > GMAC_MCK_SPEED_120MHZ) {
-               ul_clk = GMAC_NCFGR_CLK_MCK_64;
-       } else if (ul_mck > GMAC_MCK_SPEED_80MHZ) {
-               ul_clk = GMAC_NCFGR_CLK_MCK_48;
-       } else if (ul_mck > GMAC_MCK_SPEED_40MHZ) {
-               ul_clk = GMAC_NCFGR_CLK_MCK_32;
-       } else if (ul_mck > GMAC_MCK_SPEED_20MHZ) {
-               ul_clk = GMAC_NCFGR_CLK_MCK_16;
-       } else {
-               ul_clk = GMAC_NCFGR_CLK_MCK_8;
-       }
-       ;
-       p_gmac->GMAC_NCFGR = (p_gmac->GMAC_NCFGR & ~GMAC_NCFGR_CLK_Msk) | ul_clk;
-       return GMAC_OK;
-}
-
-/**
- * \brief Enable/Disable retry test.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable the GMAC receiver, else to enable it.
- */
-static inline void gmac_enable_retry_test(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RTY;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RTY;
-       }
-}
-
-/**
- * \brief Enable/Disable pause (when a valid pause frame is received).
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable pause frame, else to enable it.
- */
-static inline void gmac_enable_pause_frame(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_PEN;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_PEN;
-       }
-}
-
-/**
- * \brief Set receive buffer offset to 0 ~ 3.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- */
-static inline void gmac_set_rx_buffer_offset(Gmac* p_gmac, uint8_t uc_offset)
-{
-       p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RXBUFO_Msk;
-       p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RXBUFO(uc_offset);
-}
-
-/**
- * \brief Enable/Disable receive length field checking.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable receive length field checking, else to enable it.
- */
-static inline void gmac_enable_rx_length_check(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_LFERD;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_LFERD;
-       }
-}
-
-/**
- * \brief Enable/Disable discarding FCS field of received frames.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable discarding FCS field of received frames, else to enable it.
- */
-static inline void gmac_enable_discard_fcs(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RFCS;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RFCS;
-       }
-}
-
-
-/**
- * \brief Enable/Disable frames to be received in half-duplex mode
- * while transmitting.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable the received in half-duplex mode, else to enable it.
- */
-static inline void gmac_enable_efrhd(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_EFRHD;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_EFRHD;
-       }
-}
-
-/**
- * \brief Enable/Disable ignore RX FCS.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_enable   0 to disable ignore RX FCS, else to enable it.
- */
-static inline void gmac_enable_ignore_rx_fcs(Gmac* p_gmac, uint8_t uc_enable)
-{
-       if (uc_enable) {
-               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_IRXFCS;
-       } else {
-               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_IRXFCS;
-       }
-}
-
-/**
- * \brief Get Network Status.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- *
- * \return Network status.
- */
-static inline uint32_t gmac_get_status(Gmac* p_gmac)
-{
-       return p_gmac->GMAC_NSR;
-}
-
-/**
- * \brief Get MDIO IN pin status.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- *
- * \return MDIO IN pin status.
- */
-static inline uint8_t gmac_get_MDIO(Gmac* p_gmac)
-{
-       return ((p_gmac->GMAC_NSR & GMAC_NSR_MDIO) > 0);
-}
-
-/**
- * \brief Check if PHY is idle.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- *
- * \return  1 if PHY is idle.
- */
-static inline uint8_t gmac_is_phy_idle(Gmac* p_gmac)
-{
-       return ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) > 0);
-}
-
-/**
- * \brief Return transmit status.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- *
- * \return  Transmit status.
- */
-static inline uint32_t gmac_get_tx_status(Gmac* p_gmac)
-{
-       return p_gmac->GMAC_TSR;
-}
-
-/**
- * \brief Clear transmit status.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param ul_status   Transmit status.
- */
-static inline void gmac_clear_tx_status(Gmac* p_gmac, uint32_t ul_status)
-{
-       p_gmac->GMAC_TSR = ul_status;
-}
-
-/**
- * \brief Return receive status.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- */
-static inline uint32_t gmac_get_rx_status(Gmac* p_gmac)
-{
-       return p_gmac->GMAC_RSR;
-}
-
-/**
- * \brief Clear receive status.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param ul_status   Receive status.
- */
-static inline void gmac_clear_rx_status(Gmac* p_gmac, uint32_t ul_status)
-{
-       p_gmac->GMAC_RSR = ul_status;
-}
-
-/**
- * \brief Set Rx Queue.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param ul_addr   Rx queue address.
- */
-static inline void gmac_set_rx_queue(Gmac* p_gmac, uint32_t ul_addr)
-{
-       p_gmac->GMAC_RBQB = GMAC_RBQB_ADDR_Msk & ul_addr;
-}
-
-/**
- * \brief Get Rx Queue Address.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- *
- * \return  Rx queue address.
- */
-static inline uint32_t gmac_get_rx_queue(Gmac* p_gmac)
-{
-       return p_gmac->GMAC_RBQB;
-}
-
-/**
- * \brief Set Tx Queue.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param ul_addr  Tx queue address.
- */
-static inline void gmac_set_tx_queue(Gmac* p_gmac, uint32_t ul_addr)
-{
-       p_gmac->GMAC_TBQB = GMAC_TBQB_ADDR_Msk & ul_addr;
-}
-
-/**
- * \brief Get Tx Queue.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- *
- * \return  Rx queue address.
- */
-static inline uint32_t gmac_get_tx_queue(Gmac* p_gmac)
-{
-       return p_gmac->GMAC_TBQB;
-}
-
-/**
- * \brief Enable interrupt(s).
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param ul_source   Interrupt source(s) to be enabled.
- */
-static inline void gmac_enable_interrupt(Gmac* p_gmac, uint32_t ul_source)
-{
-       p_gmac->GMAC_IER = ul_source;
-}
-
-/**
- * \brief Disable interrupt(s).
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param ul_source   Interrupt source(s) to be disabled.
- */
-static inline void gmac_disable_interrupt(Gmac* p_gmac, uint32_t ul_source)
-{
-       p_gmac->GMAC_IDR = ul_source;
-}
-
-/**
- * \brief Return interrupt status.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- *
- * \return Interrupt status.
- */
-static inline uint32_t gmac_get_interrupt_status(Gmac* p_gmac)
-{
-       return p_gmac->GMAC_ISR;
-}
-
-/**
- * \brief Return interrupt mask.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- *
- * \return Interrupt mask.
- */
-static inline uint32_t gmac_get_interrupt_mask(Gmac* p_gmac)
-{
-       return p_gmac->GMAC_IMR;
-}
-
-/**
- * \brief Execute PHY maintenance command.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_phy_addr   PHY address.
- * \param uc_reg_addr   Register address.
- * \param uc_rw   1 to Read, 0 to write.
- * \param us_data   Data to be performed, write only.
- */
-static inline void gmac_maintain_phy(Gmac* p_gmac,
-               uint8_t uc_phy_addr, uint8_t uc_reg_addr, uint8_t uc_rw,
-               uint16_t us_data)
-{
-       /* Wait until bus idle */
-       while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);
-       /* Write maintain register */
-       p_gmac->GMAC_MAN = GMAC_MAN_WTN(GMAC_MAN_CODE_VALUE)
-                       | GMAC_MAN_CLTTO
-                       | GMAC_MAN_PHYA(uc_phy_addr)
-                       | GMAC_MAN_REGA(uc_reg_addr)
-                       | GMAC_MAN_OP((uc_rw ? GMAC_MAN_RW_TYPE : GMAC_MAN_READ_ONLY))
-                       | GMAC_MAN_DATA(us_data);
-}
-
-/**
- * \brief Get PHY maintenance data returned.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- *
- * \return Get PHY data.
- */
-static inline uint16_t gmac_get_phy_data(Gmac* p_gmac)
-{
-       /* Wait until bus idle */
-       while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);
-       /* Return data */
-       return (uint16_t) (p_gmac->GMAC_MAN & GMAC_MAN_DATA_Msk);
-}
-
-/**
- * \brief Set Hash.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param ul_hash_top   Hash top.
- * \param ul_hash_bottom   Hash bottom.
- */
-static inline void gmac_set_hash(Gmac* p_gmac, uint32_t ul_hash_top,
-               uint32_t ul_hash_bottom)
-{
-       p_gmac->GMAC_HRB = ul_hash_bottom;
-       p_gmac->GMAC_HRT = ul_hash_top;
-}
-
-/**
- * \brief Set 64 bits Hash.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param ull_hash   64 bits hash value.
- */
-static inline void gmac_set_hash64(Gmac* p_gmac, uint64_t ull_hash)
-{
-       p_gmac->GMAC_HRB = (uint32_t) ull_hash;
-       p_gmac->GMAC_HRT = (uint32_t) (ull_hash >> 32);
-}
-
-/**
- * \brief Set MAC Address.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_index  GMAC specific address register index.
- * \param p_mac_addr  GMAC address.
- */
-static inline void gmac_set_address(Gmac* p_gmac, uint8_t uc_index,
-               uint8_t* p_mac_addr)
-{
-       p_gmac->GMAC_SA[uc_index].GMAC_SAB = (p_mac_addr[3] << 24)
-                       | (p_mac_addr[2] << 16)
-                       | (p_mac_addr[1] << 8)
-                       | (p_mac_addr[0]);
-       p_gmac->GMAC_SA[uc_index].GMAC_SAT = (p_mac_addr[5] << 8)
-                       | (p_mac_addr[4]);
-}
-
-/**
- * \brief Set MAC Address via 2 dword.
-  *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_index  GMAC specific address register index.
- * \param ul_mac_top  GMAC top address.
- * \param ul_mac_bottom  GMAC bottom address.
- */
-static inline void gmac_set_address32(Gmac* p_gmac, uint8_t uc_index,
-               uint32_t ul_mac_top, uint32_t ul_mac_bottom)
-{
-       p_gmac->GMAC_SA[uc_index].GMAC_SAB = ul_mac_bottom;
-       p_gmac->GMAC_SA[uc_index].GMAC_SAT = ul_mac_top;
-}
-
-/**
- * \brief Set MAC Address via int64.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param uc_index  GMAC specific address register index.
- * \param ull_mac  64-bit GMAC address.
- */
-static inline void gmac_set_address64(Gmac* p_gmac, uint8_t uc_index,
-               uint64_t ull_mac)
-{
-       p_gmac->GMAC_SA[uc_index].GMAC_SAB = (uint32_t) ull_mac;
-       p_gmac->GMAC_SA[uc_index].GMAC_SAT = (uint32_t) (ull_mac >> 32);
-}
-
-/**
- * \brief Select media independent interface mode.
- *
- * \param p_gmac   Pointer to the GMAC instance.
- * \param mode   Media independent interface mode.
- */
-static inline void gmac_select_mii_mode(Gmac* p_gmac, gmac_mii_mode_t mode)
-{
-       switch (mode) {
-               case GMAC_PHY_MII:
-               case GMAC_PHY_RMII:
-                       p_gmac->GMAC_UR |= GMAC_UR_RMIIMII;
-               break;
-
-               default:
-                       p_gmac->GMAC_UR &= ~GMAC_UR_RMIIMII;
-               break;
-       }
-}
-
-uint8_t gmac_phy_read(Gmac* p_gmac, uint8_t uc_phy_address, uint8_t uc_address,
-               uint32_t* p_value);
-uint8_t gmac_phy_write(Gmac* p_gmac, uint8_t uc_phy_address,
-               uint8_t uc_address, uint32_t ul_value);
-void gmac_dev_init(Gmac* p_gmac, gmac_device_t* p_gmac_dev,
-               gmac_options_t* p_opt);
-uint32_t gmac_dev_read(gmac_device_t* p_gmac_dev, uint8_t* p_frame,
-               uint32_t ul_frame_size, uint32_t* p_rcv_size);
-uint32_t gmac_dev_write(gmac_device_t* p_gmac_dev, void *p_buffer,
-               uint32_t ul_size, gmac_dev_tx_cb_t func_tx_cb);
-uint32_t gmac_dev_get_tx_load(gmac_device_t* p_gmac_dev);
-void gmac_dev_set_rx_callback(gmac_device_t* p_gmac_dev,
-               gmac_dev_rx_cb_t func_rx_cb);
-uint8_t gmac_dev_set_tx_wakeup_callback(gmac_device_t* p_gmac_dev,
-               gmac_dev_wakeup_cb_t func_wakeup, uint8_t uc_threshold);
-void gmac_dev_reset(gmac_device_t* p_gmac_dev);
-void gmac_handler(gmac_device_t* p_gmac_dev);
-
-/// @cond 0
-/**INDENT-OFF**/
-#ifdef __cplusplus
-}
-#endif
-/**INDENT-ON**/
-/// @endcond
-
-/**
- * \page gmac_quickstart Quickstart guide for GMAC driver.
- *
- * This is the quickstart guide for the \ref gmac_group "Ethernet MAC",
- * with step-by-step instructions on how to configure and use the driver in a
- * selection of use cases.
- *
- * The use cases contain several code fragments. The code fragments in the
- * steps for setup can be copied into a custom initialization function, while
- * the steps for usage can be copied into, e.g., the main application function.
- *
- * \section gmac_basic_use_case Basic use case
- * In the basic use case, the GMAC driver are configured for:
- * - PHY component KSZ8051MNL is used
- * - GMAC uses MII mode
- * - The number of receive buffer is 16
- * - The number of transfer buffer is 8
- * - MAC address is set to 00-04-25-1c-a0-02
- * - IP address is set to 192.168.0.2
- * - IP address is set to 192.168.0.2
- * - Gateway is set to 192.168.0.1
- * - Network mask is 255.255.255.0
- * - PHY operation max retry count is 1000000
- * - GMAC is configured to not support copy all frame and support broadcast
- * - The data will be read from the ethernet
- *
- * \section gmac_basic_use_case_setup Setup steps
- *
- * \subsection gmac_basic_use_case_setup_prereq Prerequisites
- * -# \ref sysclk_group "System Clock Management (sysclock)"
- * -# \ref pmc_group "Power Management Controller (pmc)"
- * -# \ref ksz8051mnl_ethernet_phy_group "PHY component (KSZ8051MNL)"
- *
- * \subsection gmac_basic_use_case_setup_code Example code
- * Content of conf_eth.h
- * \code
- * #define GMAC_RX_BUFFERS                               16
- * #define GMAC_TX_BUFFERS                               8
- * #define MAC_PHY_RETRY_MAX                             1000000
- * #define ETHERNET_CONF_ETHADDR0                        0x00
- * #define ETHERNET_CONF_ETHADDR0                        0x00
- * #define ETHERNET_CONF_ETHADDR1                        0x04
- * #define ETHERNET_CONF_ETHADDR2                        0x25
- * #define ETHERNET_CONF_ETHADDR3                        0x1C
- * #define ETHERNET_CONF_ETHADDR4                        0xA0
- * #define ETHERNET_CONF_ETHADDR5                        0x02
- * #define ETHERNET_CONF_IPADDR0                         192
- * #define ETHERNET_CONF_IPADDR1                         168
- * #define ETHERNET_CONF_IPADDR2                         0
- * #define ETHERNET_CONF_IPADDR3                         2
- * #define ETHERNET_CONF_GATEWAY_ADDR0                   192
- * #define ETHERNET_CONF_GATEWAY_ADDR1                   168
- * #define ETHERNET_CONF_GATEWAY_ADDR2                   0
- * #define ETHERNET_CONF_GATEWAY_ADDR3                   1
- * #define ETHERNET_CONF_NET_MASK0                       255
- * #define ETHERNET_CONF_NET_MASK1                       255
- * #define ETHERNET_CONF_NET_MASK2                       255
- * #define ETHERNET_CONF_NET_MASK3                       0
- * #define ETH_PHY_MODE                                  ETH_PHY_MODE
- * \endcode
- *
- * A specific gmac device and the receive data buffer must be defined; another ul_frm_size should be defined
- * to trace the actual size of the data received.
- * \code
- * static gmac_device_t gs_gmac_dev;
- * static volatile uint8_t gs_uc_eth_buffer[GMAC_FRAME_LENTGH_MAX];
- *
- * uint32_t ul_frm_size;
- * \endcode
- *
- * Add to application C-file:
- * \code
- *   void gmac_init(void)
- *   {
- *       sysclk_init();
- *
- *       board_init();
- *
- *       pmc_enable_periph_clk(ID_GMAC);
- *
- *       gmac_option.uc_copy_all_frame = 0;
- *       gmac_option.uc_no_boardcast = 0;
- *       memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));
- *       gs_gmac_dev.p_hw = GMAC;
- *
- *       gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option);
- *
- *       NVIC_EnableIRQ(GMAC_IRQn);
- *
- *       ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz());
- *
- *       ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR);
- *
- *       ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1);
- * \endcode
- *
- * \subsection gmac_basic_use_case_setup_flow Workflow
- * - Ensure that conf_eth.h is present and contains the
- * following configuration symbol. This configuration file is used
- * by the driver and should not be included by the application.
- * -# Define the receiving buffer size used in the internal GMAC driver.
- * The buffer size used for RX is GMAC_RX_BUFFERS * 128.
- * If it was supposed receiving a large number of frame, the
- * GMAC_RX_BUFFERS should be set higher. E.g., the application wants to accept
- * a ping echo test of 2048, the GMAC_RX_BUFFERS should be set at least
- * (2048/128)=16, and as there are additional frames coming, a preferred
- * number is 24 depending on a normal Ethernet throughput.
- *   - \code
- *        #define GMAC_RX_BUFFERS                               16
- *   \endcode
- * -# Define the transmitting buffer size used in the internal GMAC driver.
- * The buffer size used for TX is GMAC_TX_BUFFERS * 1518.
- *   - \code
- *        #define GMAC_TX_BUFFERS                               8
- *   \endcode
- * -# Define maximum retry time for a PHY read/write operation.
- *   - \code
- *        #define MAC_PHY_RETRY_MAX                             1000000
- *   \endcode
- * -# Define the MAC address. 00:04:25:1C:A0:02 is the address reserved
- * for ATMEL, application should always change this address to its' own.
- *   - \code
- *        #define ETHERNET_CONF_ETHADDR0                        0x00
- *        #define ETHERNET_CONF_ETHADDR1                        0x04
- *        #define ETHERNET_CONF_ETHADDR2                        0x25
- *        #define ETHERNET_CONF_ETHADDR3                        0x1C
- *        #define ETHERNET_CONF_ETHADDR4                        0xA0
- *        #define ETHERNET_CONF_ETHADDR5                        0x02
- *   \endcode
- * -# Define the IP address configration used in the application. When DHCP
- *  is enabled, this configuration is not effected.
- *   - \code
- *        #define ETHERNET_CONF_IPADDR0                         192
- *        #define ETHERNET_CONF_IPADDR1                         168
- *        #define ETHERNET_CONF_IPADDR2                         0
- *        #define ETHERNET_CONF_IPADDR3                         2
- *        #define ETHERNET_CONF_GATEWAY_ADDR0                   192
- *        #define ETHERNET_CONF_GATEWAY_ADDR1                   168
- *        #define ETHERNET_CONF_GATEWAY_ADDR2                   0
- *        #define ETHERNET_CONF_GATEWAY_ADDR3                   1
- *        #define ETHERNET_CONF_NET_MASK0                       255
- *        #define ETHERNET_CONF_NET_MASK1                       255
- *        #define ETHERNET_CONF_NET_MASK2                       255
- *        #define ETHERNET_CONF_NET_MASK3                       0
- *   \endcode
- * -# Configure the PHY maintainance interface.
- *   - \code
- *        #define ETH_PHY_MODE                                  GMAC_PHY_MII
- *   \endcode
- * -# Enable the system clock:
- *   - \code sysclk_init(); \endcode
- * -# Enable PIO configurations for GMAC:
- *   - \code board_init(); \endcode
- * -# Enable PMC clock for GMAC:
- *   - \code pmc_enable_periph_clk(ID_GMAC); \endcode
- * -# Set the GMAC options; it's set to copy all frame and support broadcast:
- *   - \code
- *         gmac_option.uc_copy_all_frame = 0;
- *         gmac_option.uc_no_boardcast = 0;
- *         memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));
- *         gs_gmac_dev.p_hw = GMAC;
- * \endcode
- * -# Initialize GMAC device with the filled option:
- *   - \code
- *         gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option);
- * \endcode
- * -# Enable the interrupt service for GMAC:
- *   - \code
- *         NVIC_EnableIRQ(GMAC_IRQn);
- * \endcode
- * -# Initialize the PHY component:
- *   - \code
- *         ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz());
- * \endcode
-  * -# The link will be established based on auto negotiation.
- *   - \code
- *         ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR);
- * \endcode
- * -# Establish the ethernet link; the network can be worked from now on:
- *   - \code
- *         ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1);
- * \endcode
- *
- * \section gmac_basic_use_case_usage Usage steps
- * \subsection gmac_basic_use_case_usage_code Example code
- * Add to, e.g., main loop in application C-file:
- * \code
- *    gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size));
- * \endcode
- *
- * \subsection gmac_basic_use_case_usage_flow Workflow
- * -# Start reading the data from the ethernet:
- *   - \code gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size)); \endcode
- */
-
-#      define GMAC_STATS 0
-
-#if( GMAC_STATS != 0 )
-
-       /* Here below some code to study the types and
-       frequencies of  GMAC interrupts. */
-       #define GMAC_IDX_RXUBR 0
-       #define GMAC_IDX_TUR   1
-       #define GMAC_IDX_RLEX  2
-       #define GMAC_IDX_TFC   3
-       #define GMAC_IDX_RCOMP 4
-       #define GMAC_IDX_TCOMP 5
-       #define GMAC_IDX_ROVR  6
-       #define GMAC_IDX_HRESP 7
-       #define GMAC_IDX_PFNZ  8
-       #define GMAC_IDX_PTZ   9
-
-       struct SGmacStats {
-               unsigned recvCount;
-               unsigned rovrCount;
-               unsigned bnaCount;
-               unsigned sendCount;
-               unsigned sovrCount;
-               unsigned incompCount;
-               unsigned truncCount;
-
-               unsigned intStatus[10];
-       };
-       extern struct SGmacStats gmacStats;
-
-       struct SIntPair {
-               const char *name;
-               unsigned mask;
-               int index;
-       };
-
-       #define MK_PAIR( NAME )   #NAME, GMAC_IER_##NAME, GMAC_IDX_##NAME
-       static const struct SIntPair intPairs[] = {
-               { MK_PAIR( RXUBR ) }, /* Enable receive used bit read interrupt. */
-               { MK_PAIR( TUR   ) }, /* Enable transmit underrun interrupt. */
-               { MK_PAIR( RLEX  ) }, /* Enable retry limit  exceeded interrupt. */
-               { MK_PAIR( TFC   ) }, /* Enable transmit buffers exhausted in mid-frame interrupt. */
-               { MK_PAIR( RCOMP ) }, /* Receive complete */
-               { MK_PAIR( TCOMP ) }, /* Enable transmit complete interrupt. */
-               { MK_PAIR( ROVR  ) }, /* Enable receive overrun interrupt. */
-               { MK_PAIR( HRESP ) }, /* Enable Hresp not OK interrupt. */
-               { MK_PAIR( PFNZ  ) }, /* Enable pause frame received interrupt. */
-               { MK_PAIR( PTZ   ) }  /* Enable pause time zero interrupt. */
-       };
-
-       void gmac_show_irq_counts ();
-
-#endif
-
-#endif /* GMAC_H_INCLUDED */
+ /**\r
+ * \file\r
+ *\r
+ * \brief GMAC (Ethernet MAC) driver for SAM.\r
+ *\r
+ * Copyright (c) 2013 Atmel Corporation. All rights reserved.\r
+ *\r
+ * \asf_license_start\r
+ *\r
+ * \page License\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ *    this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ *    this list of conditions and the following disclaimer in the documentation\r
+ *    and/or other materials provided with the distribution.\r
+ *\r
+ * 3. The name of Atmel may not be used to endorse or promote products derived\r
+ *    from this software without specific prior written permission.\r
+ *\r
+ * 4. This software may only be redistributed and used in connection with an\r
+ *    Atmel microcontroller product.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * \asf_license_stop\r
+ *\r
+ */\r
+\r
+#ifndef GMAC_H_INCLUDED\r
+#define GMAC_H_INCLUDED\r
+\r
+#include "compiler.h"\r
+#include "component/gmac.h"\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
+\r
+/** The buffer addresses written into the descriptors must be aligned, so the\r
+    last few bits are zero.  These bits have special meaning for the GMAC\r
+    peripheral and cannot be used as part of the address. */\r
+#define GMAC_RXD_ADDR_MASK      0xFFFFFFFC\r
+#define GMAC_RXD_WRAP         (1ul << 1)  /**< Wrap bit */\r
+#define GMAC_RXD_OWNERSHIP    (1ul << 0)  /**< Ownership bit */\r
+\r
+#define GMAC_RXD_BROADCAST    (1ul << 31) /**< Broadcast detected */\r
+#define GMAC_RXD_MULTIHASH    (1ul << 30) /**< Multicast hash match */\r
+#define GMAC_RXD_UNIHASH      (1ul << 29) /**< Unicast hash match */\r
+#define GMAC_RXD_ADDR_FOUND      (1ul << 27) /**< Specific address match found */\r
+#define GMAC_RXD_ADDR        (3ul << 25) /**< Address match */\r
+#define GMAC_RXD_RXCOEN        (1ul << 24) /**< RXCOEN related function */\r
+#define GMAC_RXD_TYPE         (3ul << 22) /**< Type ID match */\r
+#define GMAC_RXD_VLAN         (1ul << 21) /**< VLAN tag detected */\r
+#define GMAC_RXD_PRIORITY     (1ul << 20) /**< Priority tag detected */\r
+#define GMAC_RXD_PRIORITY_MASK  (3ul << 17) /**< VLAN priority */\r
+#define GMAC_RXD_CFI          (1ul << 16) /**< Concatenation Format Indicator only if bit 21 is set */\r
+#define GMAC_RXD_EOF          (1ul << 15) /**< End of frame */\r
+#define GMAC_RXD_SOF          (1ul << 14) /**< Start of frame */\r
+#define GMAC_RXD_FCS          (1ul << 13) /**< Frame check sequence */\r
+#define GMAC_RXD_OFFSET_MASK                /**< Receive buffer offset */\r
+#define GMAC_RXD_LEN_MASK       (0xFFF)     /**< Length of frame including FCS (if selected) */\r
+#define GMAC_RXD_LENJUMBO_MASK  (0x3FFF)    /**< Jumbo frame length */\r
+\r
+#define GMAC_TXD_USED         (1ul << 31) /**< Frame is transmitted */\r
+#define GMAC_TXD_WRAP         (1ul << 30) /**< Last descriptor */\r
+#define GMAC_TXD_ERROR        (1ul << 29) /**< Retry limit exceeded, error */\r
+#define GMAC_TXD_UNDERRUN     (1ul << 28) /**< Transmit underrun */\r
+#define GMAC_TXD_EXHAUSTED    (1ul << 27) /**< Buffer exhausted */\r
+#define GMAC_TXD_LATE    (1ul << 26) /**< Late collision,transmit  error  */\r
+#define GMAC_TXD_CHECKSUM_ERROR   (7ul << 20) /**< Checksum error */\r
+#define GMAC_TXD_NOCRC        (1ul << 16) /**< No CRC */\r
+#define GMAC_TXD_LAST         (1ul << 15) /**< Last buffer in frame */\r
+#define GMAC_TXD_LEN_MASK       (0x1FFF)     /**< Length of buffer */\r
+\r
+/** The MAC can support frame lengths up to 1536 bytes */\r
+#define GMAC_FRAME_LENTGH_MAX       1536\r
+\r
+#define GMAC_RX_UNITSIZE            128     /**< Fixed size for RX buffer  */\r
+#define GMAC_TX_UNITSIZE            1518    /**< Size for ETH frame length */\r
+\r
+/** GMAC clock speed */\r
+#define GMAC_MCK_SPEED_240MHZ        (240*1000*1000)\r
+#define GMAC_MCK_SPEED_160MHZ        (160*1000*1000)\r
+#define GMAC_MCK_SPEED_120MHZ        (120*1000*1000)\r
+#define GMAC_MCK_SPEED_80MHZ          (80*1000*1000)\r
+#define GMAC_MCK_SPEED_40MHZ          (40*1000*1000)\r
+#define GMAC_MCK_SPEED_20MHZ          (20*1000*1000)\r
+\r
+/** GMAC maintain code default value*/\r
+#define GMAC_MAN_CODE_VALUE    (10)\r
+\r
+/** GMAC maintain start of frame default value*/\r
+#define GMAC_MAN_SOF_VALUE     (1)\r
+\r
+/** GMAC maintain read/write*/\r
+#define GMAC_MAN_RW_TYPE       (2)\r
+\r
+/** GMAC maintain read only*/\r
+#define GMAC_MAN_READ_ONLY     (1)\r
+\r
+/** GMAC address length */\r
+#define GMAC_ADDR_LENGTH       (6)\r
+\r
+\r
+#define GMAC_DUPLEX_HALF 0\r
+#define GMAC_DUPLEX_FULL 1\r
+\r
+#define GMAC_SPEED_10M      0\r
+#define GMAC_SPEED_100M     1\r
+\r
+/**\r
+ * \brief Return codes for GMAC APIs.\r
+ */\r
+typedef enum {\r
+       GMAC_OK = 0,         /** 0  Operation OK */\r
+       GMAC_TIMEOUT = 1,    /** 1  GMAC operation timeout */\r
+       GMAC_TX_BUSY,        /** 2  TX in progress */\r
+       GMAC_RX_NULL,        /** 3  No data received */\r
+       GMAC_SIZE_TOO_SMALL, /** 4  Buffer size not enough */\r
+       GMAC_PARAM,          /** 5  Parameter error, TX packet invalid or RX size too small */\r
+       GMAC_INVALID = 0xFF, /* Invalid */\r
+} gmac_status_t;\r
+\r
+/**\r
+ * \brief Media Independent Interface (MII) type.\r
+ */\r
+typedef enum {\r
+       GMAC_PHY_MII = 0,         /** MII mode */\r
+       GMAC_PHY_RMII = 1,    /** Reduced MII mode */\r
+       GMAC_PHY_INVALID = 0xFF, /* Invalid mode*/\r
+} gmac_mii_mode_t;\r
+\r
+/** Receive buffer descriptor struct */\r
+COMPILER_PACK_SET(8)\r
+typedef struct gmac_rx_descriptor {\r
+       union gmac_rx_addr {\r
+               uint32_t val;\r
+               struct gmac_rx_addr_bm {\r
+                       uint32_t b_ownership:1, /**< User clear, GMAC sets this to 1 once it has successfully written a frame to memory */\r
+                       b_wrap:1,   /**< Marks last descriptor in receive buffer */\r
+                       addr_dw:30; /**< Address in number of DW */\r
+               } bm;\r
+       } addr; /**< Address, Wrap & Ownership */\r
+       union gmac_rx_status {\r
+               uint32_t val;\r
+               struct gmac_rx_status_bm {\r
+                       uint32_t len:13,       /**  0..12  Length of frame including FCS */\r
+                       b_fcs:1,               /**  13     Receive buffer offset,  bits 13:12 of frame length for jumbo frame */\r
+                       b_sof:1,               /**  14     Start of frame */\r
+                       b_eof:1,               /**  15     End of frame */\r
+                       b_cfi:1,               /**  16     Concatenation Format Indicator */\r
+                       vlan_priority:3,       /**  17..19 VLAN priority (if VLAN detected) */\r
+                       b_priority_detected:1, /**  20     Priority tag detected */\r
+                       b_vlan_detected:1,     /**  21     VLAN tag detected */\r
+                       b_type_id_match:2,     /**  22..23 Type ID match */\r
+                       b_checksumoffload:1,   /**  24     Checksum offload specific function */\r
+                       b_addrmatch:2,         /**  25..26 Address register match */\r
+                       b_ext_addr_match:1,    /**  27     External address match found */\r
+                       reserved:1,            /**  28     */\r
+                       b_uni_hash_match:1,    /**  29     Unicast hash match */\r
+                       b_multi_hash_match:1,  /**  30     Multicast hash match */\r
+                       b_boardcast_detect:1;  /**  31     Global broadcast address detected */\r
+               } bm;\r
+       } status;\r
+} gmac_rx_descriptor_t;\r
+\r
+/** Transmit buffer descriptor struct */\r
+COMPILER_PACK_SET(8)\r
+typedef struct gmac_tx_descriptor {\r
+       uint32_t addr;\r
+       union gmac_tx_status {\r
+               uint32_t val;\r
+               struct gmac_tx_status_bm {\r
+                       uint32_t len:14,     /**  0..13 Length of buffer */\r
+                       reserved:1,          /** 14            */\r
+                       b_last_buffer:1,     /** 15     Last buffer (in the current frame) */\r
+                       b_no_crc:1,          /** 16     No CRC */\r
+                       reserved1:3,         /** 17..19        */\r
+                       b_checksumoffload:3, /** 20..22 Transmit checksum generation offload errors */\r
+                       reserved2:3,         /** 23..25        */\r
+                       b_lco:1,             /** 26     Late collision, transmit error detected */\r
+                       b_exhausted:1,       /** 27     Buffer exhausted in mid frame */\r
+                       b_underrun:1,        /** 28     Transmit underrun */\r
+                       b_error:1,           /** 29     Retry limit exceeded, error detected */\r
+                       b_wrap:1,            /** 30     Marks last descriptor in TD list */\r
+                       b_used:1;            /** 31     User clear, GMAC sets this to 1 once a frame has been successfully transmitted */\r
+               } bm;\r
+       } status;\r
+} gmac_tx_descriptor_t;\r
+\r
+COMPILER_PACK_RESET()\r
+\r
+/**\r
+ * \brief Input parameters when initializing the gmac module mode.\r
+ */\r
+typedef struct gmac_options {\r
+       /*  Enable/Disable CopyAllFrame */\r
+       uint8_t uc_copy_all_frame;\r
+       /* Enable/Disable NoBroadCast */\r
+       uint8_t uc_no_boardcast;\r
+       /* MAC address */\r
+       uint8_t uc_mac_addr[GMAC_ADDR_LENGTH];\r
+} gmac_options_t;\r
+\r
+/** TX callback */\r
+typedef void (*gmac_dev_tx_cb_t) (uint32_t ul_status, uint8_t *puc_buffer);\r
+/** RX callback */\r
+typedef void (*gmac_dev_rx_cb_t) (uint32_t ul_status);\r
+/** Wakeup callback */\r
+typedef void (*gmac_dev_wakeup_cb_t) (void);\r
+\r
+/**\r
+ * GMAC driver structure.\r
+ */\r
+typedef struct gmac_device {\r
+\r
+       /** Pointer to HW register base */\r
+       Gmac *p_hw;\r
+       /**\r
+        * Pointer to allocated TX buffer.\r
+        * Section 3.6 of AMBA 2.0 spec states that burst should not cross\r
+        * 1K Boundaries.\r
+        * Receive buffer manager writes are burst of 2 words => 3 lsb bits\r
+        * of the address shall be set to 0.\r
+        */\r
+       uint8_t *p_tx_buffer;\r
+       /** Pointer to allocated RX buffer */\r
+       uint8_t *p_rx_buffer;\r
+       /** Pointer to Rx TDs (must be 8-byte aligned) */\r
+       gmac_rx_descriptor_t *p_rx_dscr;\r
+       /** Pointer to Tx TDs (must be 8-byte aligned) */\r
+       gmac_tx_descriptor_t *p_tx_dscr;\r
+       /** Optional callback to be invoked once a frame has been received */\r
+       gmac_dev_rx_cb_t func_rx_cb;\r
+#if( GMAC_USES_WAKEUP_CALLBACK )\r
+       /** Optional callback to be invoked once several TDs have been released */\r
+       gmac_dev_wakeup_cb_t func_wakeup_cb;\r
+#endif\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+       /** Optional callback list to be invoked once TD has been processed */\r
+       gmac_dev_tx_cb_t *func_tx_cb_list;\r
+#endif\r
+       /** RX TD list size */\r
+       uint32_t ul_rx_list_size;\r
+       /** RX index for current processing TD */\r
+       uint32_t ul_rx_idx;\r
+       /** TX TD list size */\r
+       uint32_t ul_tx_list_size;\r
+       /** Circular buffer head pointer by upper layer (buffer to be sent) */\r
+       int32_t l_tx_head;\r
+       /** Circular buffer tail pointer incremented by handlers (buffer sent) */\r
+       int32_t l_tx_tail;\r
+\r
+       /** Number of free TD before wakeup callback is invoked */\r
+       uint32_t uc_wakeup_threshold;\r
+} gmac_device_t;\r
+\r
+/**\r
+ * \brief Write network control value.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_ncr   Network control value.\r
+ */\r
+static inline void gmac_network_control(Gmac* p_gmac, uint32_t ul_ncr)\r
+{\r
+       p_gmac->GMAC_NCR = ul_ncr;\r
+}\r
+\r
+/**\r
+ * \brief Get network control value.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+\r
+static inline uint32_t gmac_get_network_control(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_NCR;\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable GMAC receive.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable GMAC receiver, else to enable it.\r
+ */\r
+static inline void gmac_enable_receive(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_RXEN;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_RXEN;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable GMAC transmit.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable GMAC transmit, else to enable it.\r
+ */\r
+static inline void gmac_enable_transmit(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_TXEN;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_TXEN;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable GMAC management.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable GMAC management, else to enable it.\r
+ */\r
+static inline void gmac_enable_management(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_MPE;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_MPE;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Clear all statistics registers.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_clear_statistics(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_CLRSTAT;\r
+}\r
+\r
+/**\r
+ * \brief Increase all statistics registers.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_increase_statistics(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_INCSTAT;\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable statistics registers writing.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the statistics registers writing, else to enable it.\r
+ */\r
+static inline void gmac_enable_statistics_write(Gmac* p_gmac,\r
+               uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_WESTAT;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_WESTAT;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief In half-duplex mode, forces collisions on all received frames.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the back pressure, else to enable it.\r
+ */\r
+static inline void gmac_enable_back_pressure(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_BP;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_BP;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Start transmission.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_start_transmission(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_TSTART;\r
+}\r
+\r
+/**\r
+ * \brief Halt transmission.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_halt_transmission(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_THALT;\r
+}\r
+\r
+/**\r
+ * \brief Transmit pause frame.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_tx_pause_frame(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_TXPF;\r
+}\r
+\r
+/**\r
+ * \brief Transmit zero quantum pause frame.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_tx_pause_zero_quantum_frame(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_TXZQPF;\r
+}\r
+\r
+/**\r
+ * \brief Read snapshot.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_read_snapshot(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_RDS;\r
+}\r
+\r
+/**\r
+ * \brief Store receivetime stamp to memory.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to normal operation, else to enable the store.\r
+ */\r
+static inline void gmac_store_rx_time_stamp(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_SRTSM;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_SRTSM;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable PFC priority-based pause reception.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   1 to set the reception, 0 to disable.\r
+ */\r
+static inline void gmac_enable_pfc_pause_frame(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_ENPBPR;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_ENPBPR;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Transmit PFC priority-based pause reception.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_transmit_pfc_pause_frame(Gmac* p_gmac)\r
+{\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_TXPBPF;\r
+}\r
+\r
+/**\r
+ * \brief Flush next packet.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_flush_next_packet(Gmac* p_gmac)\r
+{\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_FNP;\r
+}\r
+\r
+/**\r
+ * \brief Set up network configuration register.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+  * \param ul_cfg   Network configuration value.\r
+ */\r
+static inline void gmac_set_configure(Gmac* p_gmac, uint32_t ul_cfg)\r
+{\r
+       p_gmac->GMAC_NCFGR = ul_cfg;\r
+}\r
+\r
+/**\r
+ * \brief Get network configuration.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return Network configuration.\r
+ */\r
+static inline uint32_t gmac_get_configure(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_NCFGR;\r
+}\r
+\r
+\r
+/* Get and set DMA Configuration Register */\r
+static inline void gmac_set_dma(Gmac* p_gmac, uint32_t ul_cfg)\r
+{\r
+       p_gmac->GMAC_DCFGR = ul_cfg;\r
+}\r
+\r
+static inline uint32_t gmac_get_dma(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_DCFGR;\r
+}\r
+\r
+/**\r
+ * \brief Set speed.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_speed 1 to indicate 100Mbps, 0 to 10Mbps.\r
+ */\r
+static inline void gmac_set_speed(Gmac* p_gmac, uint8_t uc_speed)\r
+{\r
+       if (uc_speed) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_SPD;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_SPD;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable Full-Duplex mode.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the Full-Duplex mode, else to enable it.\r
+ */\r
+static inline void gmac_enable_full_duplex(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_FD;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_FD;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable Copy(Receive) All Valid Frames.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable copying all valid frames, else to enable it.\r
+ */\r
+static inline void gmac_enable_copy_all(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_CAF;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_CAF;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable jumbo frames (up to 10240 bytes).\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the jumbo frames, else to enable it.\r
+ */\r
+static inline void gmac_enable_jumbo_frames(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_JFRAME;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_JFRAME;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Disable/Enable broadcast receiving.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   1 to disable the broadcast, else to enable it.\r
+ */\r
+static inline void gmac_disable_broadcast(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_NBC;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_NBC;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable multicast hash.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the multicast hash, else to enable it.\r
+ */\r
+static inline void gmac_enable_multicast_hash(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_UNIHEN;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_UNIHEN;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable big frames (over 1518, up to 1536).\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable big frames else to enable it.\r
+ */\r
+static inline void gmac_enable_big_frame(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_MAXFS;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_MAXFS;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Set MDC clock divider.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_mck   GMAC MCK.\r
+ *\r
+ * \return GMAC_OK if successfully.\r
+ */\r
+static inline uint8_t gmac_set_mdc_clock(Gmac* p_gmac, uint32_t ul_mck)\r
+{\r
+       uint32_t ul_clk;\r
+\r
+       if (ul_mck > GMAC_MCK_SPEED_240MHZ) {\r
+               return GMAC_INVALID;\r
+       } else if (ul_mck > GMAC_MCK_SPEED_160MHZ) {\r
+               ul_clk = GMAC_NCFGR_CLK_MCK_96;\r
+       } else if (ul_mck > GMAC_MCK_SPEED_120MHZ) {\r
+               ul_clk = GMAC_NCFGR_CLK_MCK_64;\r
+       } else if (ul_mck > GMAC_MCK_SPEED_80MHZ) {\r
+               ul_clk = GMAC_NCFGR_CLK_MCK_48;\r
+       } else if (ul_mck > GMAC_MCK_SPEED_40MHZ) {\r
+               ul_clk = GMAC_NCFGR_CLK_MCK_32;\r
+       } else if (ul_mck > GMAC_MCK_SPEED_20MHZ) {\r
+               ul_clk = GMAC_NCFGR_CLK_MCK_16;\r
+       } else {\r
+               ul_clk = GMAC_NCFGR_CLK_MCK_8;\r
+       }\r
+       ;\r
+       p_gmac->GMAC_NCFGR = (p_gmac->GMAC_NCFGR & ~GMAC_NCFGR_CLK_Msk) | ul_clk;\r
+       return GMAC_OK;\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable retry test.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the GMAC receiver, else to enable it.\r
+ */\r
+static inline void gmac_enable_retry_test(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RTY;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RTY;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable pause (when a valid pause frame is received).\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable pause frame, else to enable it.\r
+ */\r
+static inline void gmac_enable_pause_frame(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_PEN;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_PEN;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Set receive buffer offset to 0 ~ 3.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_set_rx_buffer_offset(Gmac* p_gmac, uint8_t uc_offset)\r
+{\r
+       p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RXBUFO_Msk;\r
+       p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RXBUFO(uc_offset);\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable receive length field checking.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable receive length field checking, else to enable it.\r
+ */\r
+static inline void gmac_enable_rx_length_check(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_LFERD;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_LFERD;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable discarding FCS field of received frames.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable discarding FCS field of received frames, else to enable it.\r
+ */\r
+static inline void gmac_enable_discard_fcs(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RFCS;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RFCS;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * \brief Enable/Disable frames to be received in half-duplex mode\r
+ * while transmitting.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the received in half-duplex mode, else to enable it.\r
+ */\r
+static inline void gmac_enable_efrhd(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_EFRHD;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_EFRHD;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable ignore RX FCS.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable ignore RX FCS, else to enable it.\r
+ */\r
+static inline void gmac_enable_ignore_rx_fcs(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_IRXFCS;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_IRXFCS;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Get Network Status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return Network status.\r
+ */\r
+static inline uint32_t gmac_get_status(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_NSR;\r
+}\r
+\r
+/**\r
+ * \brief Get MDIO IN pin status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return MDIO IN pin status.\r
+ */\r
+static inline uint8_t gmac_get_MDIO(Gmac* p_gmac)\r
+{\r
+       return ((p_gmac->GMAC_NSR & GMAC_NSR_MDIO) > 0);\r
+}\r
+\r
+/**\r
+ * \brief Check if PHY is idle.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return  1 if PHY is idle.\r
+ */\r
+static inline uint8_t gmac_is_phy_idle(Gmac* p_gmac)\r
+{\r
+       return ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) > 0);\r
+}\r
+\r
+/**\r
+ * \brief Return transmit status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return  Transmit status.\r
+ */\r
+static inline uint32_t gmac_get_tx_status(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_TSR;\r
+}\r
+\r
+/**\r
+ * \brief Clear transmit status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_status   Transmit status.\r
+ */\r
+static inline void gmac_clear_tx_status(Gmac* p_gmac, uint32_t ul_status)\r
+{\r
+       p_gmac->GMAC_TSR = ul_status;\r
+}\r
+\r
+/**\r
+ * \brief Return receive status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline uint32_t gmac_get_rx_status(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_RSR;\r
+}\r
+\r
+/**\r
+ * \brief Clear receive status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_status   Receive status.\r
+ */\r
+static inline void gmac_clear_rx_status(Gmac* p_gmac, uint32_t ul_status)\r
+{\r
+       p_gmac->GMAC_RSR = ul_status;\r
+}\r
+\r
+/**\r
+ * \brief Set Rx Queue.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_addr   Rx queue address.\r
+ */\r
+static inline void gmac_set_rx_queue(Gmac* p_gmac, uint32_t ul_addr)\r
+{\r
+       p_gmac->GMAC_RBQB = GMAC_RBQB_ADDR_Msk & ul_addr;\r
+}\r
+\r
+/**\r
+ * \brief Get Rx Queue Address.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return  Rx queue address.\r
+ */\r
+static inline uint32_t gmac_get_rx_queue(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_RBQB;\r
+}\r
+\r
+/**\r
+ * \brief Set Tx Queue.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_addr  Tx queue address.\r
+ */\r
+static inline void gmac_set_tx_queue(Gmac* p_gmac, uint32_t ul_addr)\r
+{\r
+       p_gmac->GMAC_TBQB = GMAC_TBQB_ADDR_Msk & ul_addr;\r
+}\r
+\r
+/**\r
+ * \brief Get Tx Queue.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return  Rx queue address.\r
+ */\r
+static inline uint32_t gmac_get_tx_queue(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_TBQB;\r
+}\r
+\r
+/**\r
+ * \brief Enable interrupt(s).\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_source   Interrupt source(s) to be enabled.\r
+ */\r
+static inline void gmac_enable_interrupt(Gmac* p_gmac, uint32_t ul_source)\r
+{\r
+       p_gmac->GMAC_IER = ul_source;\r
+}\r
+\r
+/**\r
+ * \brief Disable interrupt(s).\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_source   Interrupt source(s) to be disabled.\r
+ */\r
+static inline void gmac_disable_interrupt(Gmac* p_gmac, uint32_t ul_source)\r
+{\r
+       p_gmac->GMAC_IDR = ul_source;\r
+}\r
+\r
+/**\r
+ * \brief Return interrupt status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return Interrupt status.\r
+ */\r
+static inline uint32_t gmac_get_interrupt_status(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_ISR;\r
+}\r
+\r
+/**\r
+ * \brief Return interrupt mask.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return Interrupt mask.\r
+ */\r
+static inline uint32_t gmac_get_interrupt_mask(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_IMR;\r
+}\r
+\r
+/**\r
+ * \brief Execute PHY maintenance command.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr   PHY address.\r
+ * \param uc_reg_addr   Register address.\r
+ * \param uc_rw   1 to Read, 0 to write.\r
+ * \param us_data   Data to be performed, write only.\r
+ */\r
+static inline void gmac_maintain_phy(Gmac* p_gmac,\r
+               uint8_t uc_phy_addr, uint8_t uc_reg_addr, uint8_t uc_rw,\r
+               uint16_t us_data)\r
+{\r
+       /* Wait until bus idle */\r
+       while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);\r
+       /* Write maintain register */\r
+       p_gmac->GMAC_MAN = GMAC_MAN_WTN(GMAC_MAN_CODE_VALUE)\r
+                       | GMAC_MAN_CLTTO\r
+                       | GMAC_MAN_PHYA(uc_phy_addr)\r
+                       | GMAC_MAN_REGA(uc_reg_addr)\r
+                       | GMAC_MAN_OP((uc_rw ? GMAC_MAN_RW_TYPE : GMAC_MAN_READ_ONLY))\r
+                       | GMAC_MAN_DATA(us_data);\r
+}\r
+\r
+/**\r
+ * \brief Get PHY maintenance data returned.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return Get PHY data.\r
+ */\r
+static inline uint16_t gmac_get_phy_data(Gmac* p_gmac)\r
+{\r
+       /* Wait until bus idle */\r
+       while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);\r
+       /* Return data */\r
+       return (uint16_t) (p_gmac->GMAC_MAN & GMAC_MAN_DATA_Msk);\r
+}\r
+\r
+/**\r
+ * \brief Set Hash.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_hash_top   Hash top.\r
+ * \param ul_hash_bottom   Hash bottom.\r
+ */\r
+static inline void gmac_set_hash(Gmac* p_gmac, uint32_t ul_hash_top,\r
+               uint32_t ul_hash_bottom)\r
+{\r
+       p_gmac->GMAC_HRB = ul_hash_bottom;\r
+       p_gmac->GMAC_HRT = ul_hash_top;\r
+}\r
+\r
+/**\r
+ * \brief Set 64 bits Hash.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ull_hash   64 bits hash value.\r
+ */\r
+static inline void gmac_set_hash64(Gmac* p_gmac, uint64_t ull_hash)\r
+{\r
+       p_gmac->GMAC_HRB = (uint32_t) ull_hash;\r
+       p_gmac->GMAC_HRT = (uint32_t) (ull_hash >> 32);\r
+}\r
+\r
+/**\r
+ * \brief Set MAC Address.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_index  GMAC specific address register index.\r
+ * \param p_mac_addr  GMAC address.\r
+ */\r
+static inline void gmac_set_address(Gmac* p_gmac, uint8_t uc_index,\r
+               uint8_t* p_mac_addr)\r
+{\r
+       p_gmac->GMAC_SA[uc_index].GMAC_SAB = (p_mac_addr[3] << 24)\r
+                       | (p_mac_addr[2] << 16)\r
+                       | (p_mac_addr[1] << 8)\r
+                       | (p_mac_addr[0]);\r
+       p_gmac->GMAC_SA[uc_index].GMAC_SAT = (p_mac_addr[5] << 8)\r
+                       | (p_mac_addr[4]);\r
+}\r
+\r
+/**\r
+ * \brief Set MAC Address via 2 dword.\r
+  *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_index  GMAC specific address register index.\r
+ * \param ul_mac_top  GMAC top address.\r
+ * \param ul_mac_bottom  GMAC bottom address.\r
+ */\r
+static inline void gmac_set_address32(Gmac* p_gmac, uint8_t uc_index,\r
+               uint32_t ul_mac_top, uint32_t ul_mac_bottom)\r
+{\r
+       p_gmac->GMAC_SA[uc_index].GMAC_SAB = ul_mac_bottom;\r
+       p_gmac->GMAC_SA[uc_index].GMAC_SAT = ul_mac_top;\r
+}\r
+\r
+/**\r
+ * \brief Set MAC Address via int64.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_index  GMAC specific address register index.\r
+ * \param ull_mac  64-bit GMAC address.\r
+ */\r
+static inline void gmac_set_address64(Gmac* p_gmac, uint8_t uc_index,\r
+               uint64_t ull_mac)\r
+{\r
+       p_gmac->GMAC_SA[uc_index].GMAC_SAB = (uint32_t) ull_mac;\r
+       p_gmac->GMAC_SA[uc_index].GMAC_SAT = (uint32_t) (ull_mac >> 32);\r
+}\r
+\r
+/**\r
+ * \brief Select media independent interface mode.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param mode   Media independent interface mode.\r
+ */\r
+static inline void gmac_select_mii_mode(Gmac* p_gmac, gmac_mii_mode_t mode)\r
+{\r
+       switch (mode) {\r
+               case GMAC_PHY_MII:\r
+               case GMAC_PHY_RMII:\r
+                       p_gmac->GMAC_UR |= GMAC_UR_RMIIMII;\r
+               break;\r
+\r
+               default:\r
+                       p_gmac->GMAC_UR &= ~GMAC_UR_RMIIMII;\r
+               break;\r
+       }\r
+}\r
+\r
+uint8_t gmac_phy_read(Gmac* p_gmac, uint8_t uc_phy_address, uint8_t uc_address,\r
+               uint32_t* p_value);\r
+uint8_t gmac_phy_write(Gmac* p_gmac, uint8_t uc_phy_address,\r
+               uint8_t uc_address, uint32_t ul_value);\r
+void gmac_dev_init(Gmac* p_gmac, gmac_device_t* p_gmac_dev,\r
+               gmac_options_t* p_opt);\r
+uint32_t gmac_dev_read(gmac_device_t* p_gmac_dev, uint8_t* p_frame,\r
+               uint32_t ul_frame_size, uint32_t* p_rcv_size);\r
+uint32_t gmac_dev_write(gmac_device_t* p_gmac_dev, void *p_buffer,\r
+               uint32_t ul_size, gmac_dev_tx_cb_t func_tx_cb);\r
+uint32_t gmac_dev_get_tx_load(gmac_device_t* p_gmac_dev);\r
+void gmac_dev_set_rx_callback(gmac_device_t* p_gmac_dev,\r
+               gmac_dev_rx_cb_t func_rx_cb);\r
+uint8_t gmac_dev_set_tx_wakeup_callback(gmac_device_t* p_gmac_dev,\r
+               gmac_dev_wakeup_cb_t func_wakeup, uint8_t uc_threshold);\r
+void gmac_dev_reset(gmac_device_t* p_gmac_dev);\r
+void gmac_handler(gmac_device_t* p_gmac_dev);\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
+\r
+/**\r
+ * \page gmac_quickstart Quickstart guide for GMAC driver.\r
+ *\r
+ * This is the quickstart guide for the \ref gmac_group "Ethernet MAC",\r
+ * with step-by-step instructions on how to configure and use the driver in a\r
+ * selection of use cases.\r
+ *\r
+ * The use cases contain several code fragments. The code fragments in the\r
+ * steps for setup can be copied into a custom initialization function, while\r
+ * the steps for usage can be copied into, e.g., the main application function.\r
+ *\r
+ * \section gmac_basic_use_case Basic use case\r
+ * In the basic use case, the GMAC driver are configured for:\r
+ * - PHY component KSZ8051MNL is used\r
+ * - GMAC uses MII mode\r
+ * - The number of receive buffer is 16\r
+ * - The number of transfer buffer is 8\r
+ * - MAC address is set to 00-04-25-1c-a0-02\r
+ * - IP address is set to 192.168.0.2\r
+ * - IP address is set to 192.168.0.2\r
+ * - Gateway is set to 192.168.0.1\r
+ * - Network mask is 255.255.255.0\r
+ * - PHY operation max retry count is 1000000\r
+ * - GMAC is configured to not support copy all frame and support broadcast\r
+ * - The data will be read from the ethernet\r
+ *\r
+ * \section gmac_basic_use_case_setup Setup steps\r
+ *\r
+ * \subsection gmac_basic_use_case_setup_prereq Prerequisites\r
+ * -# \ref sysclk_group "System Clock Management (sysclock)"\r
+ * -# \ref pmc_group "Power Management Controller (pmc)"\r
+ * -# \ref ksz8051mnl_ethernet_phy_group "PHY component (KSZ8051MNL)"\r
+ *\r
+ * \subsection gmac_basic_use_case_setup_code Example code\r
+ * Content of conf_eth.h\r
+ * \code\r
+ * #define GMAC_RX_BUFFERS                               16\r
+ * #define GMAC_TX_BUFFERS                               8\r
+ * #define MAC_PHY_RETRY_MAX                             1000000\r
+ * #define ETHERNET_CONF_ETHADDR0                        0x00\r
+ * #define ETHERNET_CONF_ETHADDR0                        0x00\r
+ * #define ETHERNET_CONF_ETHADDR1                        0x04\r
+ * #define ETHERNET_CONF_ETHADDR2                        0x25\r
+ * #define ETHERNET_CONF_ETHADDR3                        0x1C\r
+ * #define ETHERNET_CONF_ETHADDR4                        0xA0\r
+ * #define ETHERNET_CONF_ETHADDR5                        0x02\r
+ * #define ETHERNET_CONF_IPADDR0                         192\r
+ * #define ETHERNET_CONF_IPADDR1                         168\r
+ * #define ETHERNET_CONF_IPADDR2                         0\r
+ * #define ETHERNET_CONF_IPADDR3                         2\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR0                   192\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR1                   168\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR2                   0\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR3                   1\r
+ * #define ETHERNET_CONF_NET_MASK0                       255\r
+ * #define ETHERNET_CONF_NET_MASK1                       255\r
+ * #define ETHERNET_CONF_NET_MASK2                       255\r
+ * #define ETHERNET_CONF_NET_MASK3                       0\r
+ * #define ETH_PHY_MODE                                  ETH_PHY_MODE\r
+ * \endcode\r
+ *\r
+ * A specific gmac device and the receive data buffer must be defined; another ul_frm_size should be defined\r
+ * to trace the actual size of the data received.\r
+ * \code\r
+ * static gmac_device_t gs_gmac_dev;\r
+ * static volatile uint8_t gs_uc_eth_buffer[GMAC_FRAME_LENTGH_MAX];\r
+ *\r
+ * uint32_t ul_frm_size;\r
+ * \endcode\r
+ *\r
+ * Add to application C-file:\r
+ * \code\r
+ *   void gmac_init(void)\r
+ *   {\r
+ *       sysclk_init();\r
+ *\r
+ *       board_init();\r
+ *\r
+ *       pmc_enable_periph_clk(ID_GMAC);\r
+ *\r
+ *       gmac_option.uc_copy_all_frame = 0;\r
+ *       gmac_option.uc_no_boardcast = 0;\r
+ *       memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));\r
+ *       gs_gmac_dev.p_hw = GMAC;\r
+ *\r
+ *       gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option);\r
+ *\r
+ *       NVIC_EnableIRQ(GMAC_IRQn);\r
+ *\r
+ *       ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz());\r
+ *\r
+ *       ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR);\r
+ *\r
+ *       ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1);\r
+ * \endcode\r
+ *\r
+ * \subsection gmac_basic_use_case_setup_flow Workflow\r
+ * - Ensure that conf_eth.h is present and contains the\r
+ * following configuration symbol. This configuration file is used\r
+ * by the driver and should not be included by the application.\r
+ * -# Define the receiving buffer size used in the internal GMAC driver.\r
+ * The buffer size used for RX is GMAC_RX_BUFFERS * 128.\r
+ * If it was supposed receiving a large number of frame, the\r
+ * GMAC_RX_BUFFERS should be set higher. E.g., the application wants to accept\r
+ * a ping echo test of 2048, the GMAC_RX_BUFFERS should be set at least\r
+ * (2048/128)=16, and as there are additional frames coming, a preferred\r
+ * number is 24 depending on a normal Ethernet throughput.\r
+ *   - \code\r
+ *        #define GMAC_RX_BUFFERS                               16\r
+ *   \endcode\r
+ * -# Define the transmitting buffer size used in the internal GMAC driver.\r
+ * The buffer size used for TX is GMAC_TX_BUFFERS * 1518.\r
+ *   - \code\r
+ *        #define GMAC_TX_BUFFERS                               8\r
+ *   \endcode\r
+ * -# Define maximum retry time for a PHY read/write operation.\r
+ *   - \code\r
+ *        #define MAC_PHY_RETRY_MAX                             1000000\r
+ *   \endcode\r
+ * -# Define the MAC address. 00:04:25:1C:A0:02 is the address reserved\r
+ * for ATMEL, application should always change this address to its' own.\r
+ *   - \code\r
+ *        #define ETHERNET_CONF_ETHADDR0                        0x00\r
+ *        #define ETHERNET_CONF_ETHADDR1                        0x04\r
+ *        #define ETHERNET_CONF_ETHADDR2                        0x25\r
+ *        #define ETHERNET_CONF_ETHADDR3                        0x1C\r
+ *        #define ETHERNET_CONF_ETHADDR4                        0xA0\r
+ *        #define ETHERNET_CONF_ETHADDR5                        0x02\r
+ *   \endcode\r
+ * -# Define the IP address configration used in the application. When DHCP\r
+ *  is enabled, this configuration is not effected.\r
+ *   - \code\r
+ *        #define ETHERNET_CONF_IPADDR0                         192\r
+ *        #define ETHERNET_CONF_IPADDR1                         168\r
+ *        #define ETHERNET_CONF_IPADDR2                         0\r
+ *        #define ETHERNET_CONF_IPADDR3                         2\r
+ *        #define ETHERNET_CONF_GATEWAY_ADDR0                   192\r
+ *        #define ETHERNET_CONF_GATEWAY_ADDR1                   168\r
+ *        #define ETHERNET_CONF_GATEWAY_ADDR2                   0\r
+ *        #define ETHERNET_CONF_GATEWAY_ADDR3                   1\r
+ *        #define ETHERNET_CONF_NET_MASK0                       255\r
+ *        #define ETHERNET_CONF_NET_MASK1                       255\r
+ *        #define ETHERNET_CONF_NET_MASK2                       255\r
+ *        #define ETHERNET_CONF_NET_MASK3                       0\r
+ *   \endcode\r
+ * -# Configure the PHY maintainance interface.\r
+ *   - \code\r
+ *        #define ETH_PHY_MODE                                  GMAC_PHY_MII\r
+ *   \endcode\r
+ * -# Enable the system clock:\r
+ *   - \code sysclk_init(); \endcode\r
+ * -# Enable PIO configurations for GMAC:\r
+ *   - \code board_init(); \endcode\r
+ * -# Enable PMC clock for GMAC:\r
+ *   - \code pmc_enable_periph_clk(ID_GMAC); \endcode\r
+ * -# Set the GMAC options; it's set to copy all frame and support broadcast:\r
+ *   - \code\r
+ *         gmac_option.uc_copy_all_frame = 0;\r
+ *         gmac_option.uc_no_boardcast = 0;\r
+ *         memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));\r
+ *         gs_gmac_dev.p_hw = GMAC;\r
+ * \endcode\r
+ * -# Initialize GMAC device with the filled option:\r
+ *   - \code\r
+ *         gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option);\r
+ * \endcode\r
+ * -# Enable the interrupt service for GMAC:\r
+ *   - \code\r
+ *         NVIC_EnableIRQ(GMAC_IRQn);\r
+ * \endcode\r
+ * -# Initialize the PHY component:\r
+ *   - \code\r
+ *         ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz());\r
+ * \endcode\r
+  * -# The link will be established based on auto negotiation.\r
+ *   - \code\r
+ *         ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR);\r
+ * \endcode\r
+ * -# Establish the ethernet link; the network can be worked from now on:\r
+ *   - \code\r
+ *         ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1);\r
+ * \endcode\r
+ *\r
+ * \section gmac_basic_use_case_usage Usage steps\r
+ * \subsection gmac_basic_use_case_usage_code Example code\r
+ * Add to, e.g., main loop in application C-file:\r
+ * \code\r
+ *    gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size));\r
+ * \endcode\r
+ *\r
+ * \subsection gmac_basic_use_case_usage_flow Workflow\r
+ * -# Start reading the data from the ethernet:\r
+ *   - \code gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size)); \endcode\r
+ */\r
+\r
+#      define GMAC_STATS 0\r
+\r
+#if( GMAC_STATS != 0 )\r
+\r
+       /* Here below some code to study the types and\r
+       frequencies of  GMAC interrupts. */\r
+       #define GMAC_IDX_RXUBR 0\r
+       #define GMAC_IDX_TUR   1\r
+       #define GMAC_IDX_RLEX  2\r
+       #define GMAC_IDX_TFC   3\r
+       #define GMAC_IDX_RCOMP 4\r
+       #define GMAC_IDX_TCOMP 5\r
+       #define GMAC_IDX_ROVR  6\r
+       #define GMAC_IDX_HRESP 7\r
+       #define GMAC_IDX_PFNZ  8\r
+       #define GMAC_IDX_PTZ   9\r
+\r
+       struct SGmacStats {\r
+               unsigned recvCount;\r
+               unsigned rovrCount;\r
+               unsigned bnaCount;\r
+               unsigned sendCount;\r
+               unsigned sovrCount;\r
+               unsigned incompCount;\r
+               unsigned truncCount;\r
+\r
+               unsigned intStatus[10];\r
+       };\r
+       extern struct SGmacStats gmacStats;\r
+\r
+       struct SIntPair {\r
+               const char *name;\r
+               unsigned mask;\r
+               int index;\r
+       };\r
+\r
+       #define MK_PAIR( NAME )   #NAME, GMAC_IER_##NAME, GMAC_IDX_##NAME\r
+       static const struct SIntPair intPairs[] = {\r
+               { MK_PAIR( RXUBR ) }, /* Enable receive used bit read interrupt. */\r
+               { MK_PAIR( TUR   ) }, /* Enable transmit underrun interrupt. */\r
+               { MK_PAIR( RLEX  ) }, /* Enable retry limit  exceeded interrupt. */\r
+               { MK_PAIR( TFC   ) }, /* Enable transmit buffers exhausted in mid-frame interrupt. */\r
+               { MK_PAIR( RCOMP ) }, /* Receive complete */\r
+               { MK_PAIR( TCOMP ) }, /* Enable transmit complete interrupt. */\r
+               { MK_PAIR( ROVR  ) }, /* Enable receive overrun interrupt. */\r
+               { MK_PAIR( HRESP ) }, /* Enable Hresp not OK interrupt. */\r
+               { MK_PAIR( PFNZ  ) }, /* Enable pause frame received interrupt. */\r
+               { MK_PAIR( PTZ   ) }  /* Enable pause time zero interrupt. */\r
+       };\r
+\r
+       void gmac_show_irq_counts ();\r
+\r
+#endif\r
+\r
+#endif /* GMAC_H_INCLUDED */\r
index 7cee711cd3dc89132c114b5554820808640bd1f4..e0d04e45472b3eba6fb5de15bae301774ce725e0 100644 (file)
-/*
-FreeRTOS+TCP V2.0.11
-Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
- http://aws.amazon.com/freertos
- http://www.FreeRTOS.org
-*/
-
-/* Standard includes. */
-#include <stdint.h>
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "task.h"
-#include "queue.h"
-#include "semphr.h"
-
-/* Hardware abstraction. */
-#include "FreeRTOS_IO.h"
-
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_UDP_IP.h"
-#include "FreeRTOS_Sockets.h"
-#include "NetworkBufferManagement.h"
-
-/* Driver includes. */
-#include "lpc17xx_emac.h"
-#include "lpc17xx_pinsel.h"
-
-/* Demo includes. */
-#include "NetworkInterface.h"
-
-#if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 1
-       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
-#else
-       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
-#endif
-
-/* When a packet is ready to be sent, if it cannot be sent immediately then the
-task performing the transmit will block for niTX_BUFFER_FREE_WAIT
-milliseconds.  It will do this a maximum of niMAX_TX_ATTEMPTS before giving
-up. */
-#define niTX_BUFFER_FREE_WAIT  ( pdMS_TO_TICKS( 2UL ) )
-#define niMAX_TX_ATTEMPTS              ( 5 )
-
-/* The length of the queue used to send interrupt status words from the
-interrupt handler to the deferred handler task. */
-#define niINTERRUPT_QUEUE_LENGTH       ( 10 )
-
-/*-----------------------------------------------------------*/
-
-/*
- * A deferred interrupt handler task that processes
- */
-static void prvEMACHandlerTask( void *pvParameters );
-
-/*-----------------------------------------------------------*/
-
-/* The queue used to communicate Ethernet events with the IP task. */
-extern QueueHandle_t xNetworkEventQueue;
-
-/* The semaphore used to wake the deferred interrupt handler task when an Rx
-interrupt is received. */
-static SemaphoreHandle_t xEMACRxEventSemaphore = NULL;
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceInitialise( void )
-{
-EMAC_CFG_Type Emac_Config;
-PINSEL_CFG_Type xPinConfig;
-BaseType_t xStatus, xReturn;
-extern uint8_t ucMACAddress[ 6 ];
-
-       /* Enable Ethernet Pins */
-       boardCONFIGURE_ENET_PINS( xPinConfig );
-
-       Emac_Config.Mode = EMAC_MODE_AUTO;
-       Emac_Config.pbEMAC_Addr = ucMACAddress;
-       xStatus = EMAC_Init( &Emac_Config );
-
-       LPC_EMAC->IntEnable &= ~( EMAC_INT_TX_DONE );
-
-       if( xStatus != ERROR )
-       {
-               vSemaphoreCreateBinary( xEMACRxEventSemaphore );
-               configASSERT( xEMACRxEventSemaphore );
-
-               /* The handler task is created at the highest possible priority to
-               ensure the interrupt handler can return directly to it. */
-               xTaskCreate( prvEMACHandlerTask, "EMAC", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );
-
-               /* Enable the interrupt and set its priority to the minimum
-               interrupt priority.  */
-               NVIC_SetPriority( ENET_IRQn, configMAC_INTERRUPT_PRIORITY );
-               NVIC_EnableIRQ( ENET_IRQn );
-
-               xReturn = pdPASS;
-       }
-       else
-       {
-               xReturn = pdFAIL;
-       }
-
-       configASSERT( xStatus != ERROR );
-
-       return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer )
-{
-BaseType_t xReturn = pdFAIL;
-int32_t x;
-extern void EMAC_StartTransmitNextBuffer( uint32_t ulLength );
-extern void EMAC_SetNextPacketToSend( uint8_t * pucBuffer );
-
-
-       /* Attempt to obtain access to a Tx buffer. */
-       for( x = 0; x < niMAX_TX_ATTEMPTS; x++ )
-       {
-               if( EMAC_CheckTransmitIndex() == TRUE )
-               {
-                       /* Will the data fit in the Tx buffer? */
-                       if( pxNetworkBuffer->xDataLength < EMAC_ETH_MAX_FLEN ) /*_RB_ The size needs to come from FreeRTOSIPConfig.h. */
-                       {
-                               /* Assign the buffer to the Tx descriptor that is now known to
-                               be free. */
-                               EMAC_SetNextPacketToSend( pxNetworkBuffer->pucBuffer );
-
-                               /* The EMAC now owns the buffer. */
-                               pxNetworkBuffer->pucBuffer = NULL;
-
-                               /* Initiate the Tx. */
-                               EMAC_StartTransmitNextBuffer( pxNetworkBuffer->xDataLength );
-                               iptraceNETWORK_INTERFACE_TRANSMIT();
-
-                               /* The Tx has been initiated. */
-                               xReturn = pdPASS;
-                       }
-                       break;
-               }
-               else
-               {
-                       vTaskDelay( niTX_BUFFER_FREE_WAIT );
-               }
-       }
-
-       /* Finished with the network buffer. */
-       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
-
-       return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-void ENET_IRQHandler( void )
-{
-uint32_t ulInterruptCause;
-
-       while( ( ulInterruptCause = LPC_EMAC->IntStatus ) != 0 )
-       {
-               /* Clear the interrupt. */
-               LPC_EMAC->IntClear = ulInterruptCause;
-
-               /* Clear fatal error conditions.  NOTE:  The driver does not clear all
-               errors, only those actually experienced.  For future reference, range
-               errors are not actually errors so can be ignored. */
-               if( ( ulInterruptCause & EMAC_INT_TX_UNDERRUN ) != 0U )
-               {
-                       LPC_EMAC->Command |= EMAC_CR_TX_RES;
-               }
-
-               /* Unblock the deferred interrupt handler task if the event was an
-               Rx. */
-               if( ( ulInterruptCause & EMAC_INT_RX_DONE ) != 0UL )
-               {
-                       xSemaphoreGiveFromISR( xEMACRxEventSemaphore, NULL );
-               }
-       }
-
-       /* ulInterruptCause is used for convenience here.  A context switch is
-       wanted, but coding portEND_SWITCHING_ISR( 1 ) would likely result in a
-       compiler warning. */
-       portEND_SWITCHING_ISR( ulInterruptCause );
-}
-/*-----------------------------------------------------------*/
-
-static void prvEMACHandlerTask( void *pvParameters )
-{
-size_t xDataLength;
-const uint16_t usCRCLength = 4;
-NetworkBufferDescriptor_t *pxNetworkBuffer;
-IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
-
-/* This is not included in the header file for some reason. */
-extern uint8_t *EMAC_NextPacketToRead( void );
-
-       ( void ) pvParameters;
-       configASSERT( xEMACRxEventSemaphore );
-
-       for( ;; )
-       {
-               /* Wait for the EMAC interrupt to indicate that another packet has been
-               received.  The while() loop is only needed if INCLUDE_vTaskSuspend is
-               set to 0 in FreeRTOSConfig.h. */
-               while( xSemaphoreTake( xEMACRxEventSemaphore, portMAX_DELAY ) == pdFALSE );
-
-               /* At least one packet has been received. */
-               while( EMAC_CheckReceiveIndex() != FALSE )
-               {
-                       /* Obtain the length, minus the CRC.  The CRC is four bytes
-                       but the length is already minus 1. */
-                       xDataLength = ( size_t ) EMAC_GetReceiveDataSize() - ( usCRCLength - 1U );
-
-                       if( xDataLength > 0U )
-                       {
-                               /* Obtain a network buffer to pass this data into the
-                               stack.  No storage is required as the network buffer
-                               will point directly to the buffer that already holds
-                               the     received data. */
-                               pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( 0, ( TickType_t ) 0 );
-
-                               if( pxNetworkBuffer != NULL )
-                               {
-                                       pxNetworkBuffer->pucBuffer = EMAC_NextPacketToRead();
-                                       pxNetworkBuffer->xDataLength = xDataLength;
-                                       xRxEvent.pvData = ( void * ) pxNetworkBuffer;
-
-                                       /* Data was received and stored.  Send a message to the IP
-                                       task to let it know. */
-                                       if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )
-                                       {
-                                               vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
-                                               iptraceETHERNET_RX_EVENT_LOST();
-                                       }
-                               }
-                               else
-                               {
-                                       iptraceETHERNET_RX_EVENT_LOST();
-                               }
-
-                               iptraceNETWORK_INTERFACE_RECEIVE();
-                       }
-
-                       /* Release the frame. */
-                       EMAC_UpdateRxConsumeIndex();
-               }
-       }
-}
-/*-----------------------------------------------------------*/
-
+/*\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
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* Hardware abstraction. */\r
+#include "FreeRTOS_IO.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_UDP_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+/* Driver includes. */\r
+#include "lpc17xx_emac.h"\r
+#include "lpc17xx_pinsel.h"\r
+\r
+/* Demo includes. */\r
+#include "NetworkInterface.h"\r
+\r
+#if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 1\r
+       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer\r
+#else\r
+       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )\r
+#endif\r
+\r
+/* When a packet is ready to be sent, if it cannot be sent immediately then the\r
+task performing the transmit will block for niTX_BUFFER_FREE_WAIT\r
+milliseconds.  It will do this a maximum of niMAX_TX_ATTEMPTS before giving\r
+up. */\r
+#define niTX_BUFFER_FREE_WAIT  ( pdMS_TO_TICKS( 2UL ) )\r
+#define niMAX_TX_ATTEMPTS              ( 5 )\r
+\r
+/* The length of the queue used to send interrupt status words from the\r
+interrupt handler to the deferred handler task. */\r
+#define niINTERRUPT_QUEUE_LENGTH       ( 10 )\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * A deferred interrupt handler task that processes\r
+ */\r
+static void prvEMACHandlerTask( void *pvParameters );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* The queue used to communicate Ethernet events with the IP task. */\r
+extern QueueHandle_t xNetworkEventQueue;\r
+\r
+/* The semaphore used to wake the deferred interrupt handler task when an Rx\r
+interrupt is received. */\r
+static SemaphoreHandle_t xEMACRxEventSemaphore = NULL;\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+EMAC_CFG_Type Emac_Config;\r
+PINSEL_CFG_Type xPinConfig;\r
+BaseType_t xStatus, xReturn;\r
+extern uint8_t ucMACAddress[ 6 ];\r
+\r
+       /* Enable Ethernet Pins */\r
+       boardCONFIGURE_ENET_PINS( xPinConfig );\r
+\r
+       Emac_Config.Mode = EMAC_MODE_AUTO;\r
+       Emac_Config.pbEMAC_Addr = ucMACAddress;\r
+       xStatus = EMAC_Init( &Emac_Config );\r
+\r
+       LPC_EMAC->IntEnable &= ~( EMAC_INT_TX_DONE );\r
+\r
+       if( xStatus != ERROR )\r
+       {\r
+               vSemaphoreCreateBinary( xEMACRxEventSemaphore );\r
+               configASSERT( xEMACRxEventSemaphore );\r
+\r
+               /* The handler task is created at the highest possible priority to\r
+               ensure the interrupt handler can return directly to it. */\r
+               xTaskCreate( prvEMACHandlerTask, "EMAC", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );\r
+\r
+               /* Enable the interrupt and set its priority to the minimum\r
+               interrupt priority.  */\r
+               NVIC_SetPriority( ENET_IRQn, configMAC_INTERRUPT_PRIORITY );\r
+               NVIC_EnableIRQ( ENET_IRQn );\r
+\r
+               xReturn = pdPASS;\r
+       }\r
+       else\r
+       {\r
+               xReturn = pdFAIL;\r
+       }\r
+\r
+       configASSERT( xStatus != ERROR );\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer )\r
+{\r
+BaseType_t xReturn = pdFAIL;\r
+int32_t x;\r
+extern void EMAC_StartTransmitNextBuffer( uint32_t ulLength );\r
+extern void EMAC_SetNextPacketToSend( uint8_t * pucBuffer );\r
+\r
+\r
+       /* Attempt to obtain access to a Tx buffer. */\r
+       for( x = 0; x < niMAX_TX_ATTEMPTS; x++ )\r
+       {\r
+               if( EMAC_CheckTransmitIndex() == TRUE )\r
+               {\r
+                       /* Will the data fit in the Tx buffer? */\r
+                       if( pxNetworkBuffer->xDataLength < EMAC_ETH_MAX_FLEN ) /*_RB_ The size needs to come from FreeRTOSIPConfig.h. */\r
+                       {\r
+                               /* Assign the buffer to the Tx descriptor that is now known to\r
+                               be free. */\r
+                               EMAC_SetNextPacketToSend( pxNetworkBuffer->pucBuffer );\r
+\r
+                               /* The EMAC now owns the buffer. */\r
+                               pxNetworkBuffer->pucBuffer = NULL;\r
+\r
+                               /* Initiate the Tx. */\r
+                               EMAC_StartTransmitNextBuffer( pxNetworkBuffer->xDataLength );\r
+                               iptraceNETWORK_INTERFACE_TRANSMIT();\r
+\r
+                               /* The Tx has been initiated. */\r
+                               xReturn = pdPASS;\r
+                       }\r
+                       break;\r
+               }\r
+               else\r
+               {\r
+                       vTaskDelay( niTX_BUFFER_FREE_WAIT );\r
+               }\r
+       }\r
+\r
+       /* Finished with the network buffer. */\r
+       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void ENET_IRQHandler( void )\r
+{\r
+uint32_t ulInterruptCause;\r
+\r
+       while( ( ulInterruptCause = LPC_EMAC->IntStatus ) != 0 )\r
+       {\r
+               /* Clear the interrupt. */\r
+               LPC_EMAC->IntClear = ulInterruptCause;\r
+\r
+               /* Clear fatal error conditions.  NOTE:  The driver does not clear all\r
+               errors, only those actually experienced.  For future reference, range\r
+               errors are not actually errors so can be ignored. */\r
+               if( ( ulInterruptCause & EMAC_INT_TX_UNDERRUN ) != 0U )\r
+               {\r
+                       LPC_EMAC->Command |= EMAC_CR_TX_RES;\r
+               }\r
+\r
+               /* Unblock the deferred interrupt handler task if the event was an\r
+               Rx. */\r
+               if( ( ulInterruptCause & EMAC_INT_RX_DONE ) != 0UL )\r
+               {\r
+                       xSemaphoreGiveFromISR( xEMACRxEventSemaphore, NULL );\r
+               }\r
+       }\r
+\r
+       /* ulInterruptCause is used for convenience here.  A context switch is\r
+       wanted, but coding portEND_SWITCHING_ISR( 1 ) would likely result in a\r
+       compiler warning. */\r
+       portEND_SWITCHING_ISR( ulInterruptCause );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvEMACHandlerTask( void *pvParameters )\r
+{\r
+size_t xDataLength;\r
+const uint16_t usCRCLength = 4;\r
+NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
+\r
+/* This is not included in the header file for some reason. */\r
+extern uint8_t *EMAC_NextPacketToRead( void );\r
+\r
+       ( void ) pvParameters;\r
+       configASSERT( xEMACRxEventSemaphore );\r
+\r
+       for( ;; )\r
+       {\r
+               /* Wait for the EMAC interrupt to indicate that another packet has been\r
+               received.  The while() loop is only needed if INCLUDE_vTaskSuspend is\r
+               set to 0 in FreeRTOSConfig.h. */\r
+               while( xSemaphoreTake( xEMACRxEventSemaphore, portMAX_DELAY ) == pdFALSE );\r
+\r
+               /* At least one packet has been received. */\r
+               while( EMAC_CheckReceiveIndex() != FALSE )\r
+               {\r
+                       /* Obtain the length, minus the CRC.  The CRC is four bytes\r
+                       but the length is already minus 1. */\r
+                       xDataLength = ( size_t ) EMAC_GetReceiveDataSize() - ( usCRCLength - 1U );\r
+\r
+                       if( xDataLength > 0U )\r
+                       {\r
+                               /* Obtain a network buffer to pass this data into the\r
+                               stack.  No storage is required as the network buffer\r
+                               will point directly to the buffer that already holds\r
+                               the     received data. */\r
+                               pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( 0, ( TickType_t ) 0 );\r
+\r
+                               if( pxNetworkBuffer != NULL )\r
+                               {\r
+                                       pxNetworkBuffer->pucBuffer = EMAC_NextPacketToRead();\r
+                                       pxNetworkBuffer->xDataLength = xDataLength;\r
+                                       xRxEvent.pvData = ( void * ) pxNetworkBuffer;\r
+\r
+                                       /* Data was received and stored.  Send a message to the IP\r
+                                       task to let it know. */\r
+                                       if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )\r
+                                       {\r
+                                               vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+                                               iptraceETHERNET_RX_EVENT_LOST();\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       iptraceETHERNET_RX_EVENT_LOST();\r
+                               }\r
+\r
+                               iptraceNETWORK_INTERFACE_RECEIVE();\r
+                       }\r
+\r
+                       /* Release the frame. */\r
+                       EMAC_UpdateRxConsumeIndex();\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
index 0b1f74d075554b9580f7ca5f489e263c0fff85a9..ac01d41af47d865905094c6edafdaad777c99609 100644 (file)
-/*
-FreeRTOS+TCP V2.0.11
-Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
- http://aws.amazon.com/freertos
- http://www.FreeRTOS.org
-*/
-
-/* Standard includes. */
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "task.h"
-#include "queue.h"
-#include "semphr.h"
-
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_Sockets.h"
-#include "FreeRTOS_IP_Private.h"
-#include "NetworkBufferManagement.h"
-#include "NetworkInterface.h"
-
-/* LPCOpen includes. */
-#include "chip.h"
-#include "lpc_phy.h"
-
-/* The size of the stack allocated to the task that handles Rx packets. */
-#define nwRX_TASK_STACK_SIZE   140
-
-#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
-
-#ifndef configUSE_RMII
-       #define configUSE_RMII 1
-#endif
-
-#ifndef configNUM_RX_DESCRIPTORS
-       #error please define configNUM_RX_DESCRIPTORS in your FreeRTOSIPConfig.h
-#endif
-
-#ifndef configNUM_TX_DESCRIPTORS
-       #error please define configNUM_TX_DESCRIPTORS in your FreeRTOSIPConfig.h
-#endif
-
-#ifndef NETWORK_IRQHandler
-       #error NETWORK_IRQHandler must be defined to the name of the function that is installed in the interrupt vector table to handle Ethernet interrupts.
-#endif
-
-#if !defined( MAC_FF_HMC )
-       /* Hash for multicast. */
-       #define MAC_FF_HMC     ( 1UL << 2UL )
-#endif
-
-#ifndef iptraceEMAC_TASK_STARTING
-       #define iptraceEMAC_TASK_STARTING()     do { } while( 0 )
-#endif
-
-/* Define the bits of .STATUS that indicate a reception error. */
-#define nwRX_STATUS_ERROR_BITS \
-       ( RDES_CE  /* CRC Error */                        | \
-         RDES_RE  /* Receive Error */                    | \
-         RDES_DE  /* Descriptor Error */                 | \
-         RDES_RWT /* Receive Watchdog Timeout */         | \
-         RDES_LC  /* Late Collision */                   | \
-         RDES_OE  /* Overflow Error */                   | \
-         RDES_SAF /* Source Address Filter Fail */       | \
-         RDES_AFM /* Destination Address Filter Fail */  | \
-         RDES_LE  /* Length Error */                     )
-
-/* Define the EMAC status bits that should trigger an interrupt. */
-#define nwDMA_INTERRUPT_MASK \
-       ( DMA_IE_TIE  /* Transmit interrupt enable */         | \
-         DMA_IE_TSE  /* Transmit stopped enable */           | \
-         DMA_IE_OVE  /* Overflow interrupt enable */         | \
-         DMA_IE_RIE  /* Receive interrupt enable */          | \
-         DMA_IE_NIE  /* Normal interrupt summary enable */   | \
-         DMA_IE_AIE  /* Abnormal interrupt summary enable */ | \
-         DMA_IE_RUE  /* Receive buffer unavailable enable */ | \
-         DMA_IE_UNE  /* Underflow interrupt enable. */       | \
-         DMA_IE_TJE  /* Transmit jabber timeout enable */    | \
-         DMA_IE_RSE  /* Received stopped enable */           | \
-         DMA_IE_RWE  /* Receive watchdog timeout enable */   | \
-         DMA_IE_FBE )/* Fatal bus error enable */
-
-/* Interrupt events to process.  Currently only the RX/TX events are 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 )
-
- /* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
- driver will filter incoming packets and only pass the stack those packets it
- considers need processing. */
- #if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
-       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
- #else
-       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
- #endif
-
-#if( ipconfigZERO_COPY_RX_DRIVER == 0 ) || ( ipconfigZERO_COPY_TX_DRIVER == 0 )
-       #warning It is adviced to enable both macros
-#endif
-
-#ifndef configPLACE_IN_SECTION_RAM
-       #define configPLACE_IN_SECTION_RAM
-/*
-       #define configPLACE_IN_SECTION_RAM      __attribute__ ((section(".ramfunc")))
-*/
-#endif
-
-/*-----------------------------------------------------------*/
-
-/*
- * Delay function passed into the library.  The implementation uses FreeRTOS
- * calls so the scheduler must be started before the driver can be used.
- */
-static void prvDelay( uint32_t ulMilliSeconds );
-
-/*
- * Initialises the Tx and Rx descriptors respectively.
- */
-static void prvSetupTxDescriptors( void );
-static void prvSetupRxDescriptors( void );
-
-/*
- * A task that processes received frames.
- */
-static void prvEMACHandlerTask( void *pvParameters );
-
-/*
- * Sets up the MAC with the results of an auto-negotiation.
- */
-static BaseType_t prvSetLinkSpeed( void );
-
-/*
- * Generates a CRC for a MAC address that is then used to generate a hash index.
- */
-static uint32_t prvGenerateCRC32( const uint8_t *ucAddress );
-
-/*
- * Generates a hash index when setting a filter to permit a MAC address.
- */
-static uint32_t prvGetHashIndex( const uint8_t *ucAddress );
-
-/*
- * Update the hash table to allow a MAC address.
- */
-static void prvAddMACAddress( const uint8_t* ucMacAddress );
-
-/*
- * Sometimes the DMA will report received data as being longer than the actual
- * received from length.  This function checks the reported length and corrects
- * if if necessary.
- */
-static void prvRemoveTrailingBytes( NetworkBufferDescriptor_t *pxDescriptor );
-
-/*-----------------------------------------------------------*/
-
-/* Bit map of outstanding ETH interrupt events for processing.  Currently only
-the Rx and Tx 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;
-
-/* Tx descriptors and index. */
-static ENET_ENHTXDESC_T xDMATxDescriptors[ configNUM_TX_DESCRIPTORS ];
-
-/* ulNextFreeTxDescriptor is declared volatile, because it is accessed from
-to different tasks. */
-static volatile uint32_t ulNextFreeTxDescriptor;
-static uint32_t ulTxDescriptorToClear;
-
-/* Rx descriptors and index. */
-static ENET_ENHRXDESC_T xDMARxDescriptors[ configNUM_RX_DESCRIPTORS ];
-static uint32_t ulNextRxDescriptorToProcess;
-
-/* Must be defined externally - the demo applications define this in main.c. */
-extern uint8_t ucMACAddress[ 6 ];
-
-/* The handle of the task that processes Rx packets.  The handle is required so
-the task can be notified when new packets arrive. */
-static TaskHandle_t xRxHanderTask = NULL;
-
-#if( ipconfigUSE_LLMNR == 1 )
-       static const uint8_t xLLMNR_MACAddress[] = { '\x01', '\x00', '\x5E', '\x00', '\x00', '\xFC' };
-#endif /* ipconfigUSE_LLMNR == 1 */
-
-/* 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;
-
-/*-----------------------------------------------------------*/
-
-
-BaseType_t xNetworkInterfaceInitialise( void )
-{
-BaseType_t xReturn = pdPASS;
-
-       /* The interrupt will be turned on when a link is established. */
-       NVIC_DisableIRQ( ETHERNET_IRQn );
-
-       /* Disable receive and transmit DMA processes. */
-       LPC_ETHERNET->DMA_OP_MODE &= ~( DMA_OM_ST | DMA_OM_SR );
-
-       /* Disable packet reception. */
-       LPC_ETHERNET->MAC_CONFIG &= ~( MAC_CFG_RE | MAC_CFG_TE );
-
-       /* Call the LPCOpen function to initialise the hardware. */
-       Chip_ENET_Init( LPC_ETHERNET );
-
-       /* Save MAC address. */
-       Chip_ENET_SetADDR( LPC_ETHERNET, ucMACAddress );
-
-       /* Clear all MAC address hash entries. */
-       LPC_ETHERNET->MAC_HASHTABLE_HIGH = 0;
-       LPC_ETHERNET->MAC_HASHTABLE_LOW = 0;
-
-       #if( ipconfigUSE_LLMNR == 1 )
-       {
-               prvAddMACAddress( xLLMNR_MACAddress );
-       }
-       #endif /* ipconfigUSE_LLMNR == 1 */
-
-       /* Promiscuous flag (PR) and Receive All flag (RA) set to zero.  The
-       registers MAC_HASHTABLE_[LOW|HIGH] will be loaded to allow certain
-       multi-cast addresses. */
-       LPC_ETHERNET->MAC_FRAME_FILTER = MAC_FF_HMC;
-
-       #if( configUSE_RMII == 1 )
-       {
-               if( lpc_phy_init( pdTRUE, prvDelay ) != SUCCESS )
-               {
-                       xReturn = pdFAIL;
-               }
-       }
-       #else
-       {
-               #warning This path has not been tested.
-               if( lpc_phy_init( pdFALSE, prvDelay ) != SUCCESS )
-               {
-                       xReturn = pdFAIL;
-               }
-       }
-       #endif
-
-       if( xReturn == pdPASS )
-       {
-               /* Guard against the task being created more than once and the
-               descriptors being initialised more than once. */
-               if( xRxHanderTask == NULL )
-               {
-                       xReturn = xTaskCreate( prvEMACHandlerTask, "EMAC", nwRX_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xRxHanderTask );
-                       configASSERT( xReturn );
-               }
-
-               if( xTXDescriptorSemaphore == NULL )
-               {
-                       /* Create a counting semaphore, with a value of 'configNUM_TX_DESCRIPTORS'
-                       and a maximum of 'configNUM_TX_DESCRIPTORS'. */
-                       xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) configNUM_TX_DESCRIPTORS, ( UBaseType_t ) configNUM_TX_DESCRIPTORS );
-                       configASSERT( xTXDescriptorSemaphore );
-               }
-
-               /* Enable MAC interrupts. */
-               LPC_ETHERNET->DMA_INT_EN = nwDMA_INTERRUPT_MASK;
-       }
-
-       if( xReturn != pdFAIL )
-       {
-               /* Auto-negotiate was already started.  Wait for it to complete. */
-               xReturn = prvSetLinkSpeed();
-
-               if( xReturn == pdPASS )
-               {
-                       /* Initialise the descriptors. */
-                       prvSetupTxDescriptors();
-                       prvSetupRxDescriptors();
-
-                       /* Clear all interrupts. */
-                       LPC_ETHERNET->DMA_STAT = DMA_ST_ALL;
-
-                       /* Enable receive and transmit DMA processes. */
-                       LPC_ETHERNET->DMA_OP_MODE |= DMA_OM_ST | DMA_OM_SR;
-
-                       /* Set Receiver / Transmitter Enable. */
-                       LPC_ETHERNET->MAC_CONFIG |= MAC_CFG_RE | MAC_CFG_TE;
-
-                       /* Start receive polling. */
-                       LPC_ETHERNET->DMA_REC_POLL_DEMAND = 1;
-
-                       /* Enable interrupts in the NVIC. */
-                       NVIC_SetPriority( ETHERNET_IRQn, configMAC_INTERRUPT_PRIORITY );
-                       NVIC_EnableIRQ( ETHERNET_IRQn );
-               }
-       }
-
-       return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-#define niBUFFER_1_PACKET_SIZE         1536
-
-static __attribute__ ((section("._ramAHB32"))) uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );
-
-void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
-{
-
-uint8_t *ucRAMBuffer = ucNetworkPackets;
-uint32_t ul;
-
-       for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )
-       {
-               pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;
-               *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );
-               ucRAMBuffer += niBUFFER_1_PACKET_SIZE;
-       }
-}
-/*-----------------------------------------------------------*/
-
-configPLACE_IN_SECTION_RAM
-static void vClearTXBuffers()
-{
-uint32_t ulLastDescriptor = ulNextFreeTxDescriptor;
-size_t uxCount = ( ( size_t ) configNUM_TX_DESCRIPTORS ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );
-#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
-       NetworkBufferDescriptor_t *pxNetworkBuffer;
-       uint8_t *ucPayLoad;
-#endif
-
-       /* 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 'TDES_OWN' bit. */
-       while( ( uxCount > ( size_t ) 0u ) && ( ( xDMATxDescriptors[ ulTxDescriptorToClear ].CTRLSTAT & TDES_OWN ) == 0 ) )
-       {
-               if( ( ulTxDescriptorToClear == ulLastDescriptor ) && ( uxCount != ( size_t ) configNUM_TX_DESCRIPTORS ) )
-               {
-                       break;
-               }
-
-
-               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
-               {
-                       ucPayLoad = ( uint8_t * )xDMATxDescriptors[ ulTxDescriptorToClear ].B1ADD;
-                       if( ucPayLoad != NULL )
-                       {
-                               /* B1ADD points to a pucEthernetBuffer of a Network Buffer descriptor. */
-                               pxNetworkBuffer = pxPacketBuffer_to_NetworkBuffer( ucPayLoad );
-
-                               configASSERT( pxNetworkBuffer != NULL );
-
-                               vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ) ;
-                               xDMATxDescriptors[ ulTxDescriptorToClear ].B1ADD = ( uint32_t )0u;
-                       }
-               }
-               #endif /* ipconfigZERO_COPY_TX_DRIVER */
-
-               /* Move onto the next descriptor, wrapping if necessary. */
-               ulTxDescriptorToClear++;
-               if( ulTxDescriptorToClear >= configNUM_TX_DESCRIPTORS )
-               {
-                       ulTxDescriptorToClear = 0;
-               }
-
-               uxCount--;
-               /* Tell the counting semaphore that one more TX descriptor is available. */
-               xSemaphoreGive( xTXDescriptorSemaphore );
-       }
-}
-
-/*-----------------------------------------------------------*/
-
-configPLACE_IN_SECTION_RAM
-BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend )
-{
-BaseType_t xReturn = pdFAIL;
-const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50 );
-
-       /* Attempt to obtain access to a Tx descriptor. */
-       do
-       {
-               if( xTXDescriptorSemaphore == NULL )
-               {
-                       break;
-               }
-               if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )
-               {
-                       /* Time-out waiting for a free TX descriptor. */
-                       break;
-               }
-
-               /* If the descriptor is still owned by the DMA it can't be used. */
-               if( ( xDMATxDescriptors[ ulNextFreeTxDescriptor ].CTRLSTAT & TDES_OWN ) != 0 )
-               {
-                       /* The semaphore was taken, the TX DMA-descriptor is still not available.
-                       Actually that should not occur, the 'TDES_OWN' was already confirmed low in vClearTXBuffers(). */
-                       xSemaphoreGive( xTXDescriptorSemaphore );
-               }
-               else
-               {
-                       #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
-                       {
-                               /* bReleaseAfterSend should always be set when using the zero
-                               copy driver. */
-                               configASSERT( bReleaseAfterSend != pdFALSE );
-
-                               /* The DMA's descriptor to point directly to the data in the
-                               network buffer descriptor.  The data is not copied. */
-                               xDMATxDescriptors[ ulNextFreeTxDescriptor ].B1ADD = ( uint32_t ) pxDescriptor->pucEthernetBuffer;
-
-                               /* The DMA descriptor will 'own' this Network Buffer,
-                               until it has been sent.  So don't release it now. */
-                               bReleaseAfterSend = false;
-                       }
-                       #else
-                       {
-                               /* The data is copied from the network buffer descriptor into
-                               the DMA's descriptor. */
-                               memcpy( ( void * ) xDMATxDescriptors[ ulNextFreeTxDescriptor ].B1ADD, ( void * ) pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength );
-                       }
-                       #endif
-
-                       xDMATxDescriptors[ ulNextFreeTxDescriptor ].BSIZE = ( uint32_t ) TDES_ENH_BS1( pxDescriptor->xDataLength );
-
-                       /* This descriptor is given back to the DMA. */
-                       xDMATxDescriptors[ ulNextFreeTxDescriptor ].CTRLSTAT |= TDES_OWN;
-
-                       /* Ensure the DMA is polling Tx descriptors. */
-                       LPC_ETHERNET->DMA_TRANS_POLL_DEMAND = 1;
-
-            iptraceNETWORK_INTERFACE_TRANSMIT();
-
-                       /* Move onto the next descriptor, wrapping if necessary. */
-                       ulNextFreeTxDescriptor++;
-                       if( ulNextFreeTxDescriptor >= configNUM_TX_DESCRIPTORS )
-                       {
-                               ulNextFreeTxDescriptor = 0;
-                       }
-
-                       /* The Tx has been initiated. */
-                       xReturn = pdPASS;
-               }
-       } while( 0 );
-
-       /* The buffer has been sent so can be released. */
-       if( bReleaseAfterSend != pdFALSE )
-       {
-               vReleaseNetworkBufferAndDescriptor( pxDescriptor );
-       }
-
-       return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-static void prvDelay( uint32_t ulMilliSeconds )
-{
-       /* Ensure the scheduler was started before attempting to use the scheduler to
-       create a delay. */
-       configASSERT( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING );
-
-       vTaskDelay( pdMS_TO_TICKS( ulMilliSeconds ) );
-}
-/*-----------------------------------------------------------*/
-
-static void prvSetupTxDescriptors( void )
-{
-BaseType_t x;
-
-       /* Start with Tx descriptors clear. */
-       memset( ( void * ) xDMATxDescriptors, 0, sizeof( xDMATxDescriptors ) );
-
-       /* Index to the next Tx descriptor to use. */
-       ulNextFreeTxDescriptor = 0ul;
-
-       /* Index to the next Tx descriptor to clear ( after transmission ). */
-       ulTxDescriptorToClear = 0ul;
-
-       for( x = 0; x < configNUM_TX_DESCRIPTORS; x++ )
-       {
-               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
-               {
-                       /* Nothing to do, B1ADD will be set when data is ready to transmit.
-                       Currently the memset above will have set it to NULL. */
-               }
-               #else
-               {
-                       /* Allocate a buffer to the Tx descriptor.  This is the most basic
-                       way of creating a driver as the data is then copied into the
-                       buffer. */
-                       xDMATxDescriptors[ x ].B1ADD = ( uint32_t ) pvPortMalloc( ipTOTAL_ETHERNET_FRAME_SIZE );
-
-                       /* Use an assert to check the allocation as +TCP applications will
-                       often not use a malloc() failed hook as the TCP stack will recover
-                       from allocation failures. */
-                       configASSERT( xDMATxDescriptors[ x ].B1ADD );
-               }
-               #endif
-
-               /* Buffers hold an entire frame so all buffers are both the start and
-               end of a frame. */
-               /* TDES_ENH_TCH     Second Address Chained. */
-               /* TDES_ENH_CIC(n)  Checksum Insertion Control, tried but it does not work for the LPC18xx... */
-               /* TDES_ENH_FS      First Segment. */
-               /* TDES_ENH_LS      Last Segment. */
-               /* TDES_ENH_IC      Interrupt on Completion. */
-               xDMATxDescriptors[ x ].CTRLSTAT = TDES_ENH_TCH | TDES_ENH_CIC( 3 ) | TDES_ENH_FS | TDES_ENH_LS | TDES_ENH_IC;
-               xDMATxDescriptors[ x ].B2ADD = ( uint32_t ) &xDMATxDescriptors[ x + 1 ];
-       }
-
-       xDMATxDescriptors[ configNUM_TX_DESCRIPTORS - 1 ].CTRLSTAT |= TDES_ENH_TER;
-       xDMATxDescriptors[ configNUM_TX_DESCRIPTORS - 1 ].B2ADD = ( uint32_t ) &xDMATxDescriptors[ 0 ];
-
-       /* Point the DMA to the base of the descriptor list. */
-       LPC_ETHERNET->DMA_TRANS_DES_ADDR = ( uint32_t ) xDMATxDescriptors;
-}
-/*-----------------------------------------------------------*/
-
-static void prvSetupRxDescriptors( void )
-{
-BaseType_t x;
-#if( ipconfigZERO_COPY_RX_DRIVER != 0 )
-       NetworkBufferDescriptor_t *pxNetworkBuffer;
-#endif
-
-       /* Index to the next Rx descriptor to use. */
-       ulNextRxDescriptorToProcess = 0;
-
-       /* Clear RX descriptor list. */
-       memset( ( void * )  xDMARxDescriptors, 0, sizeof( xDMARxDescriptors ) );
-
-       for( x = 0; x < configNUM_RX_DESCRIPTORS; x++ )
-       {
-               /* Allocate a buffer of the largest     possible frame size as it is not
-               known what size received frames will be. */
-
-               #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
-               {
-                       pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, 0 );
-
-                       /* During start-up there should be enough Network Buffers available,
-                       so it is safe to use configASSERT().
-                       In case this assert fails, please check: configNUM_RX_DESCRIPTORS,
-                       ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, and in case BufferAllocation_2.c
-                       is included, check the amount of available heap. */
-                       configASSERT( pxNetworkBuffer != NULL );
-
-                       /* Pass the actual buffer to DMA. */
-                       xDMARxDescriptors[ x ].B1ADD = ( uint32_t ) pxNetworkBuffer->pucEthernetBuffer;
-               }
-               #else
-               {
-                       /* All DMA descriptors are populated with permanent memory blocks.
-                       Their contents will be copy to Network Buffers. */
-                       xDMARxDescriptors[ x ].B1ADD = ( uint32_t ) pvPortMalloc( ipTOTAL_ETHERNET_FRAME_SIZE );
-               }
-               #endif /* ipconfigZERO_COPY_RX_DRIVER */
-
-               /* Use an assert to check the allocation as +TCP applications will often
-               not use a malloc failed hook as the TCP stack will recover from
-               allocation failures. */
-               configASSERT( xDMARxDescriptors[ x ].B1ADD );
-
-               xDMARxDescriptors[ x ].B2ADD = ( uint32_t ) &( xDMARxDescriptors[ x + 1 ] );
-               xDMARxDescriptors[ x ].CTRL = ( uint32_t ) RDES_ENH_BS1( ipTOTAL_ETHERNET_FRAME_SIZE ) | RDES_ENH_RCH;
-
-               /* The descriptor is available for use by the DMA. */
-               xDMARxDescriptors[ x ].STATUS = RDES_OWN;
-       }
-
-       /* RDES_ENH_RER  Receive End of Ring. */
-       xDMARxDescriptors[ ( configNUM_RX_DESCRIPTORS - 1 ) ].CTRL |= RDES_ENH_RER;
-       xDMARxDescriptors[ configNUM_RX_DESCRIPTORS - 1 ].B2ADD = ( uint32_t ) &( xDMARxDescriptors[ 0 ] );
-
-       /* Point the DMA to the base of the descriptor list. */
-       LPC_ETHERNET->DMA_REC_DES_ADDR = ( uint32_t ) xDMARxDescriptors;
-}
-/*-----------------------------------------------------------*/
-configPLACE_IN_SECTION_RAM
-static void prvRemoveTrailingBytes( NetworkBufferDescriptor_t *pxDescriptor )
-{
-size_t xExpectedLength;
-IPPacket_t *pxIPPacket;
-
-       pxIPPacket = ( IPPacket_t * ) pxDescriptor->pucEthernetBuffer;
-       /* Look at the actual length of the packet, translate it to a host-endial notation. */
-       xExpectedLength = sizeof( EthernetHeader_t ) + ( size_t ) FreeRTOS_htons( pxIPPacket->xIPHeader.usLength );
-
-       if( xExpectedLength == ( pxDescriptor->xDataLength + 4 ) )
-       {
-               pxDescriptor->xDataLength -= 4;
-       }
-       else
-       {
-               if( pxDescriptor->xDataLength > xExpectedLength )
-               {
-                       pxDescriptor->xDataLength = ( size_t ) xExpectedLength;
-               }
-       }
-}
-/*-----------------------------------------------------------*/
-configPLACE_IN_SECTION_RAM
-BaseType_t xGetPhyLinkStatus( void )
-{
-BaseType_t xReturn;
-
-       if( ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) == 0 )
-       {
-               xReturn = pdFALSE;
-       }
-       else
-       {
-               xReturn = pdTRUE;
-       }
-
-       return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-uint32_t ulDataAvailable;
-
-configPLACE_IN_SECTION_RAM
-static BaseType_t prvNetworkInterfaceInput()
-{
-BaseType_t xResult = pdFALSE;
-uint32_t ulStatus;
-eFrameProcessingResult_t eResult;
-const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );
-const UBaseType_t uxMinimumBuffersRemaining = 3UL;
-uint16_t usLength;
-NetworkBufferDescriptor_t *pxDescriptor;
-#if( ipconfigZERO_COPY_RX_DRIVER != 0 )
-       NetworkBufferDescriptor_t *pxNewDescriptor;
-#endif /* ipconfigZERO_COPY_RX_DRIVER */
-#if( ipconfigUSE_LINKED_RX_MESSAGES == 0 )
-       IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
-#endif
-
-       /* Process each descriptor that is not still in use by the DMA. */
-       ulStatus = xDMARxDescriptors[ ulNextRxDescriptorToProcess ].STATUS;
-       if( ( ulStatus & RDES_OWN ) == 0 )
-       {
-               /* Check packet for errors */
-               if( ( ulStatus & nwRX_STATUS_ERROR_BITS ) != 0 )
-               {
-                       /* There is some reception error. */
-                       intCount[ 3 ]++;
-                       /* Clear error bits. */
-                       ulStatus &= ~( ( uint32_t )nwRX_STATUS_ERROR_BITS );
-               }
-               else
-               {
-                       xResult++;
-
-                       eResult = ipCONSIDER_FRAME_FOR_PROCESSING( ( const uint8_t * const ) ( xDMARxDescriptors[ ulNextRxDescriptorToProcess ].B1ADD ) );
-                       if( eResult == eProcessBuffer )
-                       {
-                               if( ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) == 0 )
-                               {
-                                       ulPHYLinkStatus |= PHY_LINK_CONNECTED;
-                                       FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d (message received)\n", ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) != 0 ) );
-                               }
-
-                       #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
-                               if( uxGetNumberOfFreeNetworkBuffers() > uxMinimumBuffersRemaining )
-                               {
-                                       pxNewDescriptor = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, xDescriptorWaitTime );
-                               }
-                               else
-                               {
-                                       /* Too risky to allocate a new Network Buffer. */
-                                       pxNewDescriptor = NULL;
-                               }
-                               if( pxNewDescriptor != NULL )
-                       #else
-                               if( uxGetNumberOfFreeNetworkBuffers() > uxMinimumBuffersRemaining )
-                       #endif /* ipconfigZERO_COPY_RX_DRIVER */
-                               {
-                       #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
-                               const uint8_t *pucBuffer;
-                       #endif
-
-                                       /* Get the actual length. */
-                                       usLength = RDES_FLMSK( ulStatus );
-
-                                       #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
-                                       {
-                                               /* Replace the character buffer 'B1ADD'. */
-                                               pucBuffer = ( const uint8_t * const ) ( xDMARxDescriptors[ ulNextRxDescriptorToProcess ].B1ADD );
-                                               xDMARxDescriptors[ ulNextRxDescriptorToProcess ].B1ADD = ( uint32_t ) pxNewDescriptor->pucEthernetBuffer;
-
-                                               /* 'B1ADD' contained the address of a 'pucEthernetBuffer' that
-                                               belongs to a Network Buffer.  Find the original Network Buffer. */
-                                               pxDescriptor = pxPacketBuffer_to_NetworkBuffer( pucBuffer );
-                                               /* This zero-copy driver makes sure that every 'xDMARxDescriptors' contains
-                                               a reference to a Network Buffer at any time.
-                                               In case it runs out of Network Buffers, a DMA buffer won't be replaced,
-                                               and the received messages is dropped. */
-                                               configASSERT( pxDescriptor != NULL );
-                                       }
-                                       #else
-                                       {
-                                               /* Create a buffer of exactly the required length. */
-                                               pxDescriptor = pxGetNetworkBufferWithDescriptor( usLength, xDescriptorWaitTime );
-                                       }
-                                       #endif /* ipconfigZERO_COPY_RX_DRIVER */
-
-                                       if( pxDescriptor != NULL )
-                                       {
-                                               pxDescriptor->xDataLength = ( size_t ) usLength;
-                                               #if( ipconfigZERO_COPY_RX_DRIVER == 0 )
-                                               {
-                                                       /* Copy the data into the allocated buffer. */
-                                                       memcpy( ( void * ) pxDescriptor->pucEthernetBuffer, ( void * ) xDMARxDescriptors[ ulNextRxDescriptorToProcess ].B1ADD, usLength );
-                                               }
-                                               #endif /* ipconfigZERO_COPY_RX_DRIVER */
-                                               /* It is possible that more data was copied than
-                                               actually makes up the frame.  If this is the case
-                                               adjust the length to remove any trailing bytes. */
-                                               prvRemoveTrailingBytes( pxDescriptor );
-
-                                               /* Pass the data to the TCP/IP task for processing. */
-                                               xRxEvent.pvData = ( void * ) pxDescriptor;
-                                               if( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime ) == pdFALSE )
-                                               {
-                                                       /* Could not send the descriptor into the TCP/IP
-                                                       stack, it must be released. */
-                                                       vReleaseNetworkBufferAndDescriptor( pxDescriptor );
-                                               }
-                                               else
-                                               {
-                                                       iptraceNETWORK_INTERFACE_RECEIVE();
-
-                                                       /* The data that was available at the top of this
-                                                       loop has been sent, so is no longer available. */
-                                                       ulDataAvailable = pdFALSE;
-                                               }
-                                       }
-                               }
-                       }
-                       else
-                       {
-                               /* The packet is discarded as uninteresting. */
-                               ulDataAvailable = pdFALSE;
-                       }
-                       /* Got here because received data was sent to the IP task or the
-                       data contained an error and was discarded.  Give the descriptor
-                       back to the DMA. */
-                       xDMARxDescriptors[ ulNextRxDescriptorToProcess ].STATUS = ulStatus | RDES_OWN;
-
-                       /* Move onto the next descriptor. */
-                       ulNextRxDescriptorToProcess++;
-                       if( ulNextRxDescriptorToProcess >= configNUM_RX_DESCRIPTORS )
-                       {
-                               ulNextRxDescriptorToProcess = 0;
-                       }
-
-                       ulStatus = xDMARxDescriptors[ ulNextRxDescriptorToProcess ].STATUS;
-               } /* if( ( ulStatus & nwRX_STATUS_ERROR_BITS ) != 0 ) */
-       } /* if( ( ulStatus & RDES_OWN ) == 0 ) */
-
-       /* Restart receive polling. */
-       LPC_ETHERNET->DMA_REC_POLL_DEMAND = 1;
-
-       return xResult;
-}
-/*-----------------------------------------------------------*/
-
-configPLACE_IN_SECTION_RAM
-void NETWORK_IRQHandler( void )
-{
-BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-uint32_t ulDMAStatus;
-const uint32_t ulRxInterruptMask =
-       DMA_ST_RI |             /* Receive interrupt */
-       DMA_ST_RU;              /* Receive buffer unavailable */
-const uint32_t ulTxInterruptMask =
-       DMA_ST_TI |             /* Transmit interrupt */
-       DMA_ST_TPS;             /* Transmit process stopped */
-
-       configASSERT( xRxHanderTask );
-
-       /* Get pending interrupts. */
-       ulDMAStatus = LPC_ETHERNET->DMA_STAT;
-
-       /* RX group interrupt(s). */
-       if( ( ulDMAStatus & ulRxInterruptMask ) != 0x00 )
-       {
-               /* Remember that an RX event has happened. */
-               ulISREvents |= EMAC_IF_RX_EVENT;
-               vTaskNotifyGiveFromISR( xRxHanderTask, &xHigherPriorityTaskWoken );
-               intCount[ 0 ]++;
-       }
-
-       /* TX group interrupt(s). */
-       if( ( ulDMAStatus & ulTxInterruptMask ) != 0x00 )
-       {
-               /* Remember that a TX event has happened. */
-               ulISREvents |= EMAC_IF_TX_EVENT;
-               vTaskNotifyGiveFromISR( xRxHanderTask, &xHigherPriorityTaskWoken );
-               intCount[ 1 ]++;
-       }
-
-       /* Test for 'Abnormal interrupt summary'. */
-       if( ( ulDMAStatus & DMA_ST_AIE ) != 0x00 )
-       {
-               /* The trace macro must be written such that it can be called from
-               an interrupt. */
-               iptraceETHERNET_RX_EVENT_LOST();
-       }
-
-       /* Clear pending interrupts */
-       LPC_ETHERNET->DMA_STAT = ulDMAStatus;
-
-       /* Context switch needed? */
-       portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
-}
-/*-----------------------------------------------------------*/
-
-static BaseType_t prvSetLinkSpeed( void )
-{
-BaseType_t xReturn = pdFAIL;
-TickType_t xTimeOnEntering;
-uint32_t ulPhyStatus;
-const TickType_t xAutoNegotiateDelay = pdMS_TO_TICKS( 5000UL );
-
-       /* Ensure polling does not starve lower priority tasks by temporarily
-       setting the priority of this task to that of the idle task. */
-       vTaskPrioritySet( NULL, tskIDLE_PRIORITY );
-
-       xTimeOnEntering = xTaskGetTickCount();
-       do
-       {
-               ulPhyStatus = lpcPHYStsPoll();
-               if( ( ulPhyStatus & PHY_LINK_CONNECTED ) != 0x00 )
-               {
-                       /* Set interface speed and duplex. */
-                       if( ( ulPhyStatus & PHY_LINK_SPEED100 ) != 0x00 )
-                       {
-                               Chip_ENET_SetSpeed( LPC_ETHERNET, 1 );
-                       }
-                       else
-                       {
-                               Chip_ENET_SetSpeed( LPC_ETHERNET, 0 );
-                       }
-
-                       if( ( ulPhyStatus & PHY_LINK_FULLDUPLX ) != 0x00 )
-                       {
-                               Chip_ENET_SetDuplex( LPC_ETHERNET, true );
-                       }
-                       else
-                       {
-                               Chip_ENET_SetDuplex( LPC_ETHERNET, false );
-                       }
-
-                       xReturn = pdPASS;
-                       break;
-               }
-       } while( ( xTaskGetTickCount() - xTimeOnEntering ) < xAutoNegotiateDelay );
-
-       /* Reset the priority of this task back to its original value. */
-       vTaskPrioritySet( NULL, ipconfigIP_TASK_PRIORITY );
-
-       return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-static uint32_t prvGenerateCRC32( const uint8_t *ucAddress )
-{
-unsigned int j;
-const uint32_t Polynomial = 0xEDB88320;
-uint32_t crc = ~0ul;
-const uint8_t *pucCurrent = ( const uint8_t * ) ucAddress;
-const uint8_t *pucLast = pucCurrent + 6;
-
-    /* Calculate  normal CRC32 */
-    while( pucCurrent < pucLast )
-    {
-        crc ^= *( pucCurrent++ );
-        for( j = 0; j < 8; j++ )
-        {
-            if( ( crc & 1 ) != 0 )
-            {
-                crc = (crc >> 1) ^ Polynomial;
-            }
-            else
-            {
-                crc >>= 1;
-            }
-        }
-    }
-    return ~crc;
-}
-/*-----------------------------------------------------------*/
-
-static uint32_t prvGetHashIndex( const uint8_t *ucAddress )
-{
-uint32_t ulCrc = prvGenerateCRC32( ucAddress );
-uint32_t ulIndex = 0ul;
-BaseType_t xCount = 6;
-
-    /* Take the lowest 6 bits of the CRC32 and reverse them */
-    while( xCount-- )
-    {
-        ulIndex <<= 1;
-        ulIndex |= ( ulCrc & 1 );
-        ulCrc >>= 1;
-    }
-
-    /* This is the has value of 'ucAddress' */
-    return ulIndex;
-}
-/*-----------------------------------------------------------*/
-
-static void prvAddMACAddress( const uint8_t* ucMacAddress )
-{
-BaseType_t xIndex;
-
-    xIndex = prvGetHashIndex( ucMacAddress );
-    if( xIndex >= 32 )
-    {
-        LPC_ETHERNET->MAC_HASHTABLE_HIGH |= ( 1u << ( xIndex - 32 ) );
-    }
-    else
-    {
-        LPC_ETHERNET->MAC_HASHTABLE_LOW |= ( 1u << xIndex );
-    }
-}
-/*-----------------------------------------------------------*/
-
-configPLACE_IN_SECTION_RAM
-static void prvEMACHandlerTask( void *pvParameters )
-{
-TimeOut_t xPhyTime;
-TickType_t xPhyRemTime;
-UBaseType_t uxLastMinBufferCount = 0;
-UBaseType_t uxCurrentCount;
-BaseType_t xResult = 0;
-uint32_t ulStatus;
-const TickType_t xBlockTime = pdMS_TO_TICKS( 5000ul );
-
-       /* Remove compiler warning about unused parameter. */
-       ( void ) pvParameters;
-
-       /* A possibility to set some additional task properties. */
-       iptraceEMAC_TASK_STARTING();
-
-       vTaskSetTimeOutState( &xPhyTime );
-       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
-
-       for( ;; )
-       {
-               uxCurrentCount = uxGetMinimumFreeNetworkBuffers();
-               if( uxLastMinBufferCount != uxCurrentCount )
-               {
-                       /* The logging produced below may be helpful
-                       while tuning +TCP: see how many buffers are in use. */
-                       uxLastMinBufferCount = uxCurrentCount;
-                       FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
-                               uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );
-               }
-
-               #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
-               {
-               static UBaseType_t uxLastMinQueueSpace = 0;
-
-                       uxCurrentCount = uxGetMinimumIPQueueSpace();
-                       if( uxLastMinQueueSpace != uxCurrentCount )
-                       {
-                               /* The logging produced below may be helpful
-                               while tuning +TCP: see how many buffers are in use. */
-                               uxLastMinQueueSpace = uxCurrentCount;
-                               FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );
-                       }
-               }
-               #endif /* ipconfigCHECK_IP_QUEUE_SPACE */
-
-               ulTaskNotifyTake( pdTRUE, xBlockTime );
-
-               xResult = ( BaseType_t ) 0;
-
-               if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )
-               {
-                       /* Code to release TX buffers if zero-copy is used. */
-                       ulISREvents &= ~EMAC_IF_TX_EVENT;
-                       {
-                               /* Check if DMA packets have been delivered. */
-                               vClearTXBuffers();
-                       }
-               }
-
-               if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 )
-               {
-                       ulISREvents &= ~EMAC_IF_RX_EVENT;
-
-                       xResult = prvNetworkInterfaceInput();
-                       if( xResult > 0 )
-                       {
-                               while( prvNetworkInterfaceInput() > 0 )
-                               {
-                               }
-                       }
-               }
-
-               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 )
-               {
-                       ulStatus = lpcPHYStsPoll();
-
-                       if( ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) != ( ulStatus & PHY_LINK_CONNECTED ) )
-                       {
-                               ulPHYLinkStatus = ulStatus;
-                               FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d (polled PHY)\n", ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) != 0 ) );
-                       }
-
-                       vTaskSetTimeOutState( &xPhyTime );
-                       if( ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) != 0 )
-                       {
-                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
-                       }
-                       else
-                       {
-                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
-                       }
-               }
-       }
-}
-/*-----------------------------------------------------------*/
+/*\r
+FreeRTOS+TCP V2.0.11\r
+Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+this software and associated documentation files (the "Software"), to deal in\r
+the Software without restriction, including without limitation the rights to\r
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+the Software, and to permit persons to whom the Software is furnished to do so,\r
+subject to the following conditions:\r
+\r
+The above copyright notice and this permission notice shall be included in all\r
+copies or substantial portions of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+\r
+ http://aws.amazon.com/freertos\r
+ http://www.FreeRTOS.org\r
+*/\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+#include "NetworkInterface.h"\r
+\r
+/* LPCOpen includes. */\r
+#include "chip.h"\r
+#include "lpc_phy.h"\r
+\r
+/* The size of the stack allocated to the task that handles Rx packets. */\r
+#define nwRX_TASK_STACK_SIZE   140\r
+\r
+#ifndef        PHY_LS_HIGH_CHECK_TIME_MS\r
+       /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not\r
+       receiving packets. */\r
+       #define PHY_LS_HIGH_CHECK_TIME_MS       15000\r
+#endif\r
+\r
+#ifndef        PHY_LS_LOW_CHECK_TIME_MS\r
+       /* Check if the LinkSStatus in the PHY is still low every second. */\r
+       #define PHY_LS_LOW_CHECK_TIME_MS        1000\r
+#endif\r
+\r
+#ifndef configUSE_RMII\r
+       #define configUSE_RMII 1\r
+#endif\r
+\r
+#ifndef configNUM_RX_DESCRIPTORS\r
+       #error please define configNUM_RX_DESCRIPTORS in your FreeRTOSIPConfig.h\r
+#endif\r
+\r
+#ifndef configNUM_TX_DESCRIPTORS\r
+       #error please define configNUM_TX_DESCRIPTORS in your FreeRTOSIPConfig.h\r
+#endif\r
+\r
+#ifndef NETWORK_IRQHandler\r
+       #error NETWORK_IRQHandler must be defined to the name of the function that is installed in the interrupt vector table to handle Ethernet interrupts.\r
+#endif\r
+\r
+#if !defined( MAC_FF_HMC )\r
+       /* Hash for multicast. */\r
+       #define MAC_FF_HMC     ( 1UL << 2UL )\r
+#endif\r
+\r
+#ifndef iptraceEMAC_TASK_STARTING\r
+       #define iptraceEMAC_TASK_STARTING()     do { } while( 0 )\r
+#endif\r
+\r
+/* Define the bits of .STATUS that indicate a reception error. */\r
+#define nwRX_STATUS_ERROR_BITS \\r
+       ( RDES_CE  /* CRC Error */                        | \\r
+         RDES_RE  /* Receive Error */                    | \\r
+         RDES_DE  /* Descriptor Error */                 | \\r
+         RDES_RWT /* Receive Watchdog Timeout */         | \\r
+         RDES_LC  /* Late Collision */                   | \\r
+         RDES_OE  /* Overflow Error */                   | \\r
+         RDES_SAF /* Source Address Filter Fail */       | \\r
+         RDES_AFM /* Destination Address Filter Fail */  | \\r
+         RDES_LE  /* Length Error */                     )\r
+\r
+/* Define the EMAC status bits that should trigger an interrupt. */\r
+#define nwDMA_INTERRUPT_MASK \\r
+       ( DMA_IE_TIE  /* Transmit interrupt enable */         | \\r
+         DMA_IE_TSE  /* Transmit stopped enable */           | \\r
+         DMA_IE_OVE  /* Overflow interrupt enable */         | \\r
+         DMA_IE_RIE  /* Receive interrupt enable */          | \\r
+         DMA_IE_NIE  /* Normal interrupt summary enable */   | \\r
+         DMA_IE_AIE  /* Abnormal interrupt summary enable */ | \\r
+         DMA_IE_RUE  /* Receive buffer unavailable enable */ | \\r
+         DMA_IE_UNE  /* Underflow interrupt enable. */       | \\r
+         DMA_IE_TJE  /* Transmit jabber timeout enable */    | \\r
+         DMA_IE_RSE  /* Received stopped enable */           | \\r
+         DMA_IE_RWE  /* Receive watchdog timeout enable */   | \\r
+         DMA_IE_FBE )/* Fatal bus error enable */\r
+\r
+/* Interrupt events to process.  Currently only the RX/TX events are 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
+ /* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet\r
+ driver will filter incoming packets and only pass the stack those packets it\r
+ considers need processing. */\r
+ #if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )\r
+       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer\r
+ #else\r
+       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )\r
+ #endif\r
+\r
+#if( ipconfigZERO_COPY_RX_DRIVER == 0 ) || ( ipconfigZERO_COPY_TX_DRIVER == 0 )\r
+       #warning It is adviced to enable both macros\r
+#endif\r
+\r
+#ifndef configPLACE_IN_SECTION_RAM\r
+       #define configPLACE_IN_SECTION_RAM\r
+/*\r
+       #define configPLACE_IN_SECTION_RAM      __attribute__ ((section(".ramfunc")))\r
+*/\r
+#endif\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Delay function passed into the library.  The implementation uses FreeRTOS\r
+ * calls so the scheduler must be started before the driver can be used.\r
+ */\r
+static void prvDelay( uint32_t ulMilliSeconds );\r
+\r
+/*\r
+ * Initialises the Tx and Rx descriptors respectively.\r
+ */\r
+static void prvSetupTxDescriptors( void );\r
+static void prvSetupRxDescriptors( void );\r
+\r
+/*\r
+ * A task that processes received frames.\r
+ */\r
+static void prvEMACHandlerTask( void *pvParameters );\r
+\r
+/*\r
+ * Sets up the MAC with the results of an auto-negotiation.\r
+ */\r
+static BaseType_t prvSetLinkSpeed( void );\r
+\r
+/*\r
+ * Generates a CRC for a MAC address that is then used to generate a hash index.\r
+ */\r
+static uint32_t prvGenerateCRC32( const uint8_t *ucAddress );\r
+\r
+/*\r
+ * Generates a hash index when setting a filter to permit a MAC address.\r
+ */\r
+static uint32_t prvGetHashIndex( const uint8_t *ucAddress );\r
+\r
+/*\r
+ * Update the hash table to allow a MAC address.\r
+ */\r
+static void prvAddMACAddress( const uint8_t* ucMacAddress );\r
+\r
+/*\r
+ * Sometimes the DMA will report received data as being longer than the actual\r
+ * received from length.  This function checks the reported length and corrects\r
+ * if if necessary.\r
+ */\r
+static void prvRemoveTrailingBytes( NetworkBufferDescriptor_t *pxDescriptor );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Bit map of outstanding ETH interrupt events for processing.  Currently only\r
+the Rx and Tx interrupt is handled, although code is included for other events\r
+to enable future expansion. */\r
+static volatile uint32_t ulISREvents;\r
+\r
+/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */\r
+static uint32_t ulPHYLinkStatus = 0;\r
+\r
+/* Tx descriptors and index. */\r
+static ENET_ENHTXDESC_T xDMATxDescriptors[ configNUM_TX_DESCRIPTORS ];\r
+\r
+/* ulNextFreeTxDescriptor is declared volatile, because it is accessed from\r
+to different tasks. */\r
+static volatile uint32_t ulNextFreeTxDescriptor;\r
+static uint32_t ulTxDescriptorToClear;\r
+\r
+/* Rx descriptors and index. */\r
+static ENET_ENHRXDESC_T xDMARxDescriptors[ configNUM_RX_DESCRIPTORS ];\r
+static uint32_t ulNextRxDescriptorToProcess;\r
+\r
+/* Must be defined externally - the demo applications define this in main.c. */\r
+extern uint8_t ucMACAddress[ 6 ];\r
+\r
+/* The handle of the task that processes Rx packets.  The handle is required so\r
+the task can be notified when new packets arrive. */\r
+static TaskHandle_t xRxHanderTask = NULL;\r
+\r
+#if( ipconfigUSE_LLMNR == 1 )\r
+       static const uint8_t xLLMNR_MACAddress[] = { '\x01', '\x00', '\x5E', '\x00', '\x00', '\xFC' };\r
+#endif /* ipconfigUSE_LLMNR == 1 */\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
+\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+BaseType_t xReturn = pdPASS;\r
+\r
+       /* The interrupt will be turned on when a link is established. */\r
+       NVIC_DisableIRQ( ETHERNET_IRQn );\r
+\r
+       /* Disable receive and transmit DMA processes. */\r
+       LPC_ETHERNET->DMA_OP_MODE &= ~( DMA_OM_ST | DMA_OM_SR );\r
+\r
+       /* Disable packet reception. */\r
+       LPC_ETHERNET->MAC_CONFIG &= ~( MAC_CFG_RE | MAC_CFG_TE );\r
+\r
+       /* Call the LPCOpen function to initialise the hardware. */\r
+       Chip_ENET_Init( LPC_ETHERNET );\r
+\r
+       /* Save MAC address. */\r
+       Chip_ENET_SetADDR( LPC_ETHERNET, ucMACAddress );\r
+\r
+       /* Clear all MAC address hash entries. */\r
+       LPC_ETHERNET->MAC_HASHTABLE_HIGH = 0;\r
+       LPC_ETHERNET->MAC_HASHTABLE_LOW = 0;\r
+\r
+       #if( ipconfigUSE_LLMNR == 1 )\r
+       {\r
+               prvAddMACAddress( xLLMNR_MACAddress );\r
+       }\r
+       #endif /* ipconfigUSE_LLMNR == 1 */\r
+\r
+       /* Promiscuous flag (PR) and Receive All flag (RA) set to zero.  The\r
+       registers MAC_HASHTABLE_[LOW|HIGH] will be loaded to allow certain\r
+       multi-cast addresses. */\r
+       LPC_ETHERNET->MAC_FRAME_FILTER = MAC_FF_HMC;\r
+\r
+       #if( configUSE_RMII == 1 )\r
+       {\r
+               if( lpc_phy_init( pdTRUE, prvDelay ) != SUCCESS )\r
+               {\r
+                       xReturn = pdFAIL;\r
+               }\r
+       }\r
+       #else\r
+       {\r
+               #warning This path has not been tested.\r
+               if( lpc_phy_init( pdFALSE, prvDelay ) != SUCCESS )\r
+               {\r
+                       xReturn = pdFAIL;\r
+               }\r
+       }\r
+       #endif\r
+\r
+       if( xReturn == pdPASS )\r
+       {\r
+               /* Guard against the task being created more than once and the\r
+               descriptors being initialised more than once. */\r
+               if( xRxHanderTask == NULL )\r
+               {\r
+                       xReturn = xTaskCreate( prvEMACHandlerTask, "EMAC", nwRX_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xRxHanderTask );\r
+                       configASSERT( xReturn );\r
+               }\r
+\r
+               if( xTXDescriptorSemaphore == NULL )\r
+               {\r
+                       /* Create a counting semaphore, with a value of 'configNUM_TX_DESCRIPTORS'\r
+                       and a maximum of 'configNUM_TX_DESCRIPTORS'. */\r
+                       xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) configNUM_TX_DESCRIPTORS, ( UBaseType_t ) configNUM_TX_DESCRIPTORS );\r
+                       configASSERT( xTXDescriptorSemaphore );\r
+               }\r
+\r
+               /* Enable MAC interrupts. */\r
+               LPC_ETHERNET->DMA_INT_EN = nwDMA_INTERRUPT_MASK;\r
+       }\r
+\r
+       if( xReturn != pdFAIL )\r
+       {\r
+               /* Auto-negotiate was already started.  Wait for it to complete. */\r
+               xReturn = prvSetLinkSpeed();\r
+\r
+               if( xReturn == pdPASS )\r
+               {\r
+                       /* Initialise the descriptors. */\r
+                       prvSetupTxDescriptors();\r
+                       prvSetupRxDescriptors();\r
+\r
+                       /* Clear all interrupts. */\r
+                       LPC_ETHERNET->DMA_STAT = DMA_ST_ALL;\r
+\r
+                       /* Enable receive and transmit DMA processes. */\r
+                       LPC_ETHERNET->DMA_OP_MODE |= DMA_OM_ST | DMA_OM_SR;\r
+\r
+                       /* Set Receiver / Transmitter Enable. */\r
+                       LPC_ETHERNET->MAC_CONFIG |= MAC_CFG_RE | MAC_CFG_TE;\r
+\r
+                       /* Start receive polling. */\r
+                       LPC_ETHERNET->DMA_REC_POLL_DEMAND = 1;\r
+\r
+                       /* Enable interrupts in the NVIC. */\r
+                       NVIC_SetPriority( ETHERNET_IRQn, configMAC_INTERRUPT_PRIORITY );\r
+                       NVIC_EnableIRQ( ETHERNET_IRQn );\r
+               }\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#define niBUFFER_1_PACKET_SIZE         1536\r
+\r
+static __attribute__ ((section("._ramAHB32"))) uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );\r
+\r
+void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )\r
+{\r
+\r
+uint8_t *ucRAMBuffer = ucNetworkPackets;\r
+uint32_t ul;\r
+\r
+       for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )\r
+       {\r
+               pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;\r
+               *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );\r
+               ucRAMBuffer += niBUFFER_1_PACKET_SIZE;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+configPLACE_IN_SECTION_RAM\r
+static void vClearTXBuffers()\r
+{\r
+uint32_t ulLastDescriptor = ulNextFreeTxDescriptor;\r
+size_t uxCount = ( ( size_t ) configNUM_TX_DESCRIPTORS ) - 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 'TDES_OWN' bit. */\r
+       while( ( uxCount > ( size_t ) 0u ) && ( ( xDMATxDescriptors[ ulTxDescriptorToClear ].CTRLSTAT & TDES_OWN ) == 0 ) )\r
+       {\r
+               if( ( ulTxDescriptorToClear == ulLastDescriptor ) && ( uxCount != ( size_t ) configNUM_TX_DESCRIPTORS ) )\r
+               {\r
+                       break;\r
+               }\r
+\r
+\r
+               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+               {\r
+                       ucPayLoad = ( uint8_t * )xDMATxDescriptors[ ulTxDescriptorToClear ].B1ADD;\r
+                       if( ucPayLoad != NULL )\r
+                       {\r
+                               /* B1ADD points to a pucEthernetBuffer of a Network Buffer descriptor. */\r
+                               pxNetworkBuffer = pxPacketBuffer_to_NetworkBuffer( ucPayLoad );\r
+\r
+                               configASSERT( pxNetworkBuffer != NULL );\r
+\r
+                               vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ) ;\r
+                               xDMATxDescriptors[ ulTxDescriptorToClear ].B1ADD = ( uint32_t )0u;\r
+                       }\r
+               }\r
+               #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+\r
+               /* Move onto the next descriptor, wrapping if necessary. */\r
+               ulTxDescriptorToClear++;\r
+               if( ulTxDescriptorToClear >= configNUM_TX_DESCRIPTORS )\r
+               {\r
+                       ulTxDescriptorToClear = 0;\r
+               }\r
+\r
+               uxCount--;\r
+               /* Tell the counting semaphore that one more TX descriptor is available. */\r
+               xSemaphoreGive( xTXDescriptorSemaphore );\r
+       }\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+configPLACE_IN_SECTION_RAM\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend )\r
+{\r
+BaseType_t xReturn = pdFAIL;\r
+const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50 );\r
+\r
+       /* Attempt to obtain access to a Tx descriptor. */\r
+       do\r
+       {\r
+               if( xTXDescriptorSemaphore == NULL )\r
+               {\r
+                       break;\r
+               }\r
+               if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )\r
+               {\r
+                       /* Time-out waiting for a free TX descriptor. */\r
+                       break;\r
+               }\r
+\r
+               /* If the descriptor is still owned by the DMA it can't be used. */\r
+               if( ( xDMATxDescriptors[ ulNextFreeTxDescriptor ].CTRLSTAT & TDES_OWN ) != 0 )\r
+               {\r
+                       /* The semaphore was taken, the TX DMA-descriptor is still not available.\r
+                       Actually that should not occur, the 'TDES_OWN' was already confirmed low in vClearTXBuffers(). */\r
+                       xSemaphoreGive( xTXDescriptorSemaphore );\r
+               }\r
+               else\r
+               {\r
+                       #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+                       {\r
+                               /* bReleaseAfterSend should always be set when using the zero\r
+                               copy driver. */\r
+                               configASSERT( bReleaseAfterSend != pdFALSE );\r
+\r
+                               /* The DMA's descriptor to point directly to the data in the\r
+                               network buffer descriptor.  The data is not copied. */\r
+                               xDMATxDescriptors[ ulNextFreeTxDescriptor ].B1ADD = ( uint32_t ) pxDescriptor->pucEthernetBuffer;\r
+\r
+                               /* The DMA descriptor will 'own' this Network Buffer,\r
+                               until it has been sent.  So don't release it now. */\r
+                               bReleaseAfterSend = false;\r
+                       }\r
+                       #else\r
+                       {\r
+                               /* The data is copied from the network buffer descriptor into\r
+                               the DMA's descriptor. */\r
+                               memcpy( ( void * ) xDMATxDescriptors[ ulNextFreeTxDescriptor ].B1ADD, ( void * ) pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength );\r
+                       }\r
+                       #endif\r
+\r
+                       xDMATxDescriptors[ ulNextFreeTxDescriptor ].BSIZE = ( uint32_t ) TDES_ENH_BS1( pxDescriptor->xDataLength );\r
+\r
+                       /* This descriptor is given back to the DMA. */\r
+                       xDMATxDescriptors[ ulNextFreeTxDescriptor ].CTRLSTAT |= TDES_OWN;\r
+\r
+                       /* Ensure the DMA is polling Tx descriptors. */\r
+                       LPC_ETHERNET->DMA_TRANS_POLL_DEMAND = 1;\r
+\r
+            iptraceNETWORK_INTERFACE_TRANSMIT();\r
+\r
+                       /* Move onto the next descriptor, wrapping if necessary. */\r
+                       ulNextFreeTxDescriptor++;\r
+                       if( ulNextFreeTxDescriptor >= configNUM_TX_DESCRIPTORS )\r
+                       {\r
+                               ulNextFreeTxDescriptor = 0;\r
+                       }\r
+\r
+                       /* The Tx has been initiated. */\r
+                       xReturn = pdPASS;\r
+               }\r
+       } while( 0 );\r
+\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 void prvDelay( uint32_t ulMilliSeconds )\r
+{\r
+       /* Ensure the scheduler was started before attempting to use the scheduler to\r
+       create a delay. */\r
+       configASSERT( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING );\r
+\r
+       vTaskDelay( pdMS_TO_TICKS( ulMilliSeconds ) );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSetupTxDescriptors( void )\r
+{\r
+BaseType_t x;\r
+\r
+       /* Start with Tx descriptors clear. */\r
+       memset( ( void * ) xDMATxDescriptors, 0, sizeof( xDMATxDescriptors ) );\r
+\r
+       /* Index to the next Tx descriptor to use. */\r
+       ulNextFreeTxDescriptor = 0ul;\r
+\r
+       /* Index to the next Tx descriptor to clear ( after transmission ). */\r
+       ulTxDescriptorToClear = 0ul;\r
+\r
+       for( x = 0; x < configNUM_TX_DESCRIPTORS; x++ )\r
+       {\r
+               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+               {\r
+                       /* Nothing to do, B1ADD will be set when data is ready to transmit.\r
+                       Currently the memset above will have set it to NULL. */\r
+               }\r
+               #else\r
+               {\r
+                       /* Allocate a buffer to the Tx descriptor.  This is the most basic\r
+                       way of creating a driver as the data is then copied into the\r
+                       buffer. */\r
+                       xDMATxDescriptors[ x ].B1ADD = ( uint32_t ) pvPortMalloc( ipTOTAL_ETHERNET_FRAME_SIZE );\r
+\r
+                       /* Use an assert to check the allocation as +TCP applications will\r
+                       often not use a malloc() failed hook as the TCP stack will recover\r
+                       from allocation failures. */\r
+                       configASSERT( xDMATxDescriptors[ x ].B1ADD );\r
+               }\r
+               #endif\r
+\r
+               /* Buffers hold an entire frame so all buffers are both the start and\r
+               end of a frame. */\r
+               /* TDES_ENH_TCH     Second Address Chained. */\r
+               /* TDES_ENH_CIC(n)  Checksum Insertion Control, tried but it does not work for the LPC18xx... */\r
+               /* TDES_ENH_FS      First Segment. */\r
+               /* TDES_ENH_LS      Last Segment. */\r
+               /* TDES_ENH_IC      Interrupt on Completion. */\r
+               xDMATxDescriptors[ x ].CTRLSTAT = TDES_ENH_TCH | TDES_ENH_CIC( 3 ) | TDES_ENH_FS | TDES_ENH_LS | TDES_ENH_IC;\r
+               xDMATxDescriptors[ x ].B2ADD = ( uint32_t ) &xDMATxDescriptors[ x + 1 ];\r
+       }\r
+\r
+       xDMATxDescriptors[ configNUM_TX_DESCRIPTORS - 1 ].CTRLSTAT |= TDES_ENH_TER;\r
+       xDMATxDescriptors[ configNUM_TX_DESCRIPTORS - 1 ].B2ADD = ( uint32_t ) &xDMATxDescriptors[ 0 ];\r
+\r
+       /* Point the DMA to the base of the descriptor list. */\r
+       LPC_ETHERNET->DMA_TRANS_DES_ADDR = ( uint32_t ) xDMATxDescriptors;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSetupRxDescriptors( void )\r
+{\r
+BaseType_t x;\r
+#if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+       NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+#endif\r
+\r
+       /* Index to the next Rx descriptor to use. */\r
+       ulNextRxDescriptorToProcess = 0;\r
+\r
+       /* Clear RX descriptor list. */\r
+       memset( ( void * )  xDMARxDescriptors, 0, sizeof( xDMARxDescriptors ) );\r
+\r
+       for( x = 0; x < configNUM_RX_DESCRIPTORS; x++ )\r
+       {\r
+               /* Allocate a buffer of the largest     possible frame size as it is not\r
+               known what size received frames will be. */\r
+\r
+               #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+               {\r
+                       pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, 0 );\r
+\r
+                       /* During start-up there should be enough Network Buffers available,\r
+                       so it is safe to use configASSERT().\r
+                       In case this assert fails, please check: configNUM_RX_DESCRIPTORS,\r
+                       ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, and in case BufferAllocation_2.c\r
+                       is included, check the amount of available heap. */\r
+                       configASSERT( pxNetworkBuffer != NULL );\r
+\r
+                       /* Pass the actual buffer to DMA. */\r
+                       xDMARxDescriptors[ x ].B1ADD = ( uint32_t ) pxNetworkBuffer->pucEthernetBuffer;\r
+               }\r
+               #else\r
+               {\r
+                       /* All DMA descriptors are populated with permanent memory blocks.\r
+                       Their contents will be copy to Network Buffers. */\r
+                       xDMARxDescriptors[ x ].B1ADD = ( uint32_t ) pvPortMalloc( ipTOTAL_ETHERNET_FRAME_SIZE );\r
+               }\r
+               #endif /* ipconfigZERO_COPY_RX_DRIVER */\r
+\r
+               /* Use an assert to check the allocation as +TCP applications will often\r
+               not use a malloc failed hook as the TCP stack will recover from\r
+               allocation failures. */\r
+               configASSERT( xDMARxDescriptors[ x ].B1ADD );\r
+\r
+               xDMARxDescriptors[ x ].B2ADD = ( uint32_t ) &( xDMARxDescriptors[ x + 1 ] );\r
+               xDMARxDescriptors[ x ].CTRL = ( uint32_t ) RDES_ENH_BS1( ipTOTAL_ETHERNET_FRAME_SIZE ) | RDES_ENH_RCH;\r
+\r
+               /* The descriptor is available for use by the DMA. */\r
+               xDMARxDescriptors[ x ].STATUS = RDES_OWN;\r
+       }\r
+\r
+       /* RDES_ENH_RER  Receive End of Ring. */\r
+       xDMARxDescriptors[ ( configNUM_RX_DESCRIPTORS - 1 ) ].CTRL |= RDES_ENH_RER;\r
+       xDMARxDescriptors[ configNUM_RX_DESCRIPTORS - 1 ].B2ADD = ( uint32_t ) &( xDMARxDescriptors[ 0 ] );\r
+\r
+       /* Point the DMA to the base of the descriptor list. */\r
+       LPC_ETHERNET->DMA_REC_DES_ADDR = ( uint32_t ) xDMARxDescriptors;\r
+}\r
+/*-----------------------------------------------------------*/\r
+configPLACE_IN_SECTION_RAM\r
+static void prvRemoveTrailingBytes( NetworkBufferDescriptor_t *pxDescriptor )\r
+{\r
+size_t xExpectedLength;\r
+IPPacket_t *pxIPPacket;\r
+\r
+       pxIPPacket = ( IPPacket_t * ) pxDescriptor->pucEthernetBuffer;\r
+       /* Look at the actual length of the packet, translate it to a host-endial notation. */\r
+       xExpectedLength = sizeof( EthernetHeader_t ) + ( size_t ) FreeRTOS_htons( pxIPPacket->xIPHeader.usLength );\r
+\r
+       if( xExpectedLength == ( pxDescriptor->xDataLength + 4 ) )\r
+       {\r
+               pxDescriptor->xDataLength -= 4;\r
+       }\r
+       else\r
+       {\r
+               if( pxDescriptor->xDataLength > xExpectedLength )\r
+               {\r
+                       pxDescriptor->xDataLength = ( size_t ) xExpectedLength;\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+configPLACE_IN_SECTION_RAM\r
+BaseType_t xGetPhyLinkStatus( void )\r
+{\r
+BaseType_t xReturn;\r
+\r
+       if( ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) == 0 )\r
+       {\r
+               xReturn = pdFALSE;\r
+       }\r
+       else\r
+       {\r
+               xReturn = pdTRUE;\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+uint32_t ulDataAvailable;\r
+\r
+configPLACE_IN_SECTION_RAM\r
+static BaseType_t prvNetworkInterfaceInput()\r
+{\r
+BaseType_t xResult = pdFALSE;\r
+uint32_t ulStatus;\r
+eFrameProcessingResult_t eResult;\r
+const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );\r
+const UBaseType_t uxMinimumBuffersRemaining = 3UL;\r
+uint16_t usLength;\r
+NetworkBufferDescriptor_t *pxDescriptor;\r
+#if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+       NetworkBufferDescriptor_t *pxNewDescriptor;\r
+#endif /* ipconfigZERO_COPY_RX_DRIVER */\r
+#if( ipconfigUSE_LINKED_RX_MESSAGES == 0 )\r
+       IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
+#endif\r
+\r
+       /* Process each descriptor that is not still in use by the DMA. */\r
+       ulStatus = xDMARxDescriptors[ ulNextRxDescriptorToProcess ].STATUS;\r
+       if( ( ulStatus & RDES_OWN ) == 0 )\r
+       {\r
+               /* Check packet for errors */\r
+               if( ( ulStatus & nwRX_STATUS_ERROR_BITS ) != 0 )\r
+               {\r
+                       /* There is some reception error. */\r
+                       intCount[ 3 ]++;\r
+                       /* Clear error bits. */\r
+                       ulStatus &= ~( ( uint32_t )nwRX_STATUS_ERROR_BITS );\r
+               }\r
+               else\r
+               {\r
+                       xResult++;\r
+\r
+                       eResult = ipCONSIDER_FRAME_FOR_PROCESSING( ( const uint8_t * const ) ( xDMARxDescriptors[ ulNextRxDescriptorToProcess ].B1ADD ) );\r
+                       if( eResult == eProcessBuffer )\r
+                       {\r
+                               if( ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) == 0 )\r
+                               {\r
+                                       ulPHYLinkStatus |= PHY_LINK_CONNECTED;\r
+                                       FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d (message received)\n", ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) != 0 ) );\r
+                               }\r
+\r
+                       #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+                               if( uxGetNumberOfFreeNetworkBuffers() > uxMinimumBuffersRemaining )\r
+                               {\r
+                                       pxNewDescriptor = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, xDescriptorWaitTime );\r
+                               }\r
+                               else\r
+                               {\r
+                                       /* Too risky to allocate a new Network Buffer. */\r
+                                       pxNewDescriptor = NULL;\r
+                               }\r
+                               if( pxNewDescriptor != NULL )\r
+                       #else\r
+                               if( uxGetNumberOfFreeNetworkBuffers() > uxMinimumBuffersRemaining )\r
+                       #endif /* ipconfigZERO_COPY_RX_DRIVER */\r
+                               {\r
+                       #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+                               const uint8_t *pucBuffer;\r
+                       #endif\r
+\r
+                                       /* Get the actual length. */\r
+                                       usLength = RDES_FLMSK( ulStatus );\r
+\r
+                                       #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+                                       {\r
+                                               /* Replace the character buffer 'B1ADD'. */\r
+                                               pucBuffer = ( const uint8_t * const ) ( xDMARxDescriptors[ ulNextRxDescriptorToProcess ].B1ADD );\r
+                                               xDMARxDescriptors[ ulNextRxDescriptorToProcess ].B1ADD = ( uint32_t ) pxNewDescriptor->pucEthernetBuffer;\r
+\r
+                                               /* 'B1ADD' contained the address of a 'pucEthernetBuffer' that\r
+                                               belongs to a Network Buffer.  Find the original Network Buffer. */\r
+                                               pxDescriptor = pxPacketBuffer_to_NetworkBuffer( pucBuffer );\r
+                                               /* This zero-copy driver makes sure that every 'xDMARxDescriptors' contains\r
+                                               a reference to a Network Buffer at any time.\r
+                                               In case it runs out of Network Buffers, a DMA buffer won't be replaced,\r
+                                               and the received messages is dropped. */\r
+                                               configASSERT( pxDescriptor != NULL );\r
+                                       }\r
+                                       #else\r
+                                       {\r
+                                               /* Create a buffer of exactly the required length. */\r
+                                               pxDescriptor = pxGetNetworkBufferWithDescriptor( usLength, xDescriptorWaitTime );\r
+                                       }\r
+                                       #endif /* ipconfigZERO_COPY_RX_DRIVER */\r
+\r
+                                       if( pxDescriptor != NULL )\r
+                                       {\r
+                                               pxDescriptor->xDataLength = ( size_t ) usLength;\r
+                                               #if( ipconfigZERO_COPY_RX_DRIVER == 0 )\r
+                                               {\r
+                                                       /* Copy the data into the allocated buffer. */\r
+                                                       memcpy( ( void * ) pxDescriptor->pucEthernetBuffer, ( void * ) xDMARxDescriptors[ ulNextRxDescriptorToProcess ].B1ADD, usLength );\r
+                                               }\r
+                                               #endif /* ipconfigZERO_COPY_RX_DRIVER */\r
+                                               /* It is possible that more data was copied than\r
+                                               actually makes up the frame.  If this is the case\r
+                                               adjust the length to remove any trailing bytes. */\r
+                                               prvRemoveTrailingBytes( pxDescriptor );\r
+\r
+                                               /* Pass the data to the TCP/IP task for processing. */\r
+                                               xRxEvent.pvData = ( void * ) pxDescriptor;\r
+                                               if( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime ) == pdFALSE )\r
+                                               {\r
+                                                       /* Could not send the descriptor into the TCP/IP\r
+                                                       stack, it must be released. */\r
+                                                       vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       iptraceNETWORK_INTERFACE_RECEIVE();\r
+\r
+                                                       /* The data that was available at the top of this\r
+                                                       loop has been sent, so is no longer available. */\r
+                                                       ulDataAvailable = pdFALSE;\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               /* The packet is discarded as uninteresting. */\r
+                               ulDataAvailable = pdFALSE;\r
+                       }\r
+                       /* Got here because received data was sent to the IP task or the\r
+                       data contained an error and was discarded.  Give the descriptor\r
+                       back to the DMA. */\r
+                       xDMARxDescriptors[ ulNextRxDescriptorToProcess ].STATUS = ulStatus | RDES_OWN;\r
+\r
+                       /* Move onto the next descriptor. */\r
+                       ulNextRxDescriptorToProcess++;\r
+                       if( ulNextRxDescriptorToProcess >= configNUM_RX_DESCRIPTORS )\r
+                       {\r
+                               ulNextRxDescriptorToProcess = 0;\r
+                       }\r
+\r
+                       ulStatus = xDMARxDescriptors[ ulNextRxDescriptorToProcess ].STATUS;\r
+               } /* if( ( ulStatus & nwRX_STATUS_ERROR_BITS ) != 0 ) */\r
+       } /* if( ( ulStatus & RDES_OWN ) == 0 ) */\r
+\r
+       /* Restart receive polling. */\r
+       LPC_ETHERNET->DMA_REC_POLL_DEMAND = 1;\r
+\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+configPLACE_IN_SECTION_RAM\r
+void NETWORK_IRQHandler( void )\r
+{\r
+BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
+uint32_t ulDMAStatus;\r
+const uint32_t ulRxInterruptMask =\r
+       DMA_ST_RI |             /* Receive interrupt */\r
+       DMA_ST_RU;              /* Receive buffer unavailable */\r
+const uint32_t ulTxInterruptMask =\r
+       DMA_ST_TI |             /* Transmit interrupt */\r
+       DMA_ST_TPS;             /* Transmit process stopped */\r
+\r
+       configASSERT( xRxHanderTask );\r
+\r
+       /* Get pending interrupts. */\r
+       ulDMAStatus = LPC_ETHERNET->DMA_STAT;\r
+\r
+       /* RX group interrupt(s). */\r
+       if( ( ulDMAStatus & ulRxInterruptMask ) != 0x00 )\r
+       {\r
+               /* Remember that an RX event has happened. */\r
+               ulISREvents |= EMAC_IF_RX_EVENT;\r
+               vTaskNotifyGiveFromISR( xRxHanderTask, &xHigherPriorityTaskWoken );\r
+               intCount[ 0 ]++;\r
+       }\r
+\r
+       /* TX group interrupt(s). */\r
+       if( ( ulDMAStatus & ulTxInterruptMask ) != 0x00 )\r
+       {\r
+               /* Remember that a TX event has happened. */\r
+               ulISREvents |= EMAC_IF_TX_EVENT;\r
+               vTaskNotifyGiveFromISR( xRxHanderTask, &xHigherPriorityTaskWoken );\r
+               intCount[ 1 ]++;\r
+       }\r
+\r
+       /* Test for 'Abnormal interrupt summary'. */\r
+       if( ( ulDMAStatus & DMA_ST_AIE ) != 0x00 )\r
+       {\r
+               /* The trace macro must be written such that it can be called from\r
+               an interrupt. */\r
+               iptraceETHERNET_RX_EVENT_LOST();\r
+       }\r
+\r
+       /* Clear pending interrupts */\r
+       LPC_ETHERNET->DMA_STAT = ulDMAStatus;\r
+\r
+       /* Context switch needed? */\r
+       portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvSetLinkSpeed( void )\r
+{\r
+BaseType_t xReturn = pdFAIL;\r
+TickType_t xTimeOnEntering;\r
+uint32_t ulPhyStatus;\r
+const TickType_t xAutoNegotiateDelay = pdMS_TO_TICKS( 5000UL );\r
+\r
+       /* Ensure polling does not starve lower priority tasks by temporarily\r
+       setting the priority of this task to that of the idle task. */\r
+       vTaskPrioritySet( NULL, tskIDLE_PRIORITY );\r
+\r
+       xTimeOnEntering = xTaskGetTickCount();\r
+       do\r
+       {\r
+               ulPhyStatus = lpcPHYStsPoll();\r
+               if( ( ulPhyStatus & PHY_LINK_CONNECTED ) != 0x00 )\r
+               {\r
+                       /* Set interface speed and duplex. */\r
+                       if( ( ulPhyStatus & PHY_LINK_SPEED100 ) != 0x00 )\r
+                       {\r
+                               Chip_ENET_SetSpeed( LPC_ETHERNET, 1 );\r
+                       }\r
+                       else\r
+                       {\r
+                               Chip_ENET_SetSpeed( LPC_ETHERNET, 0 );\r
+                       }\r
+\r
+                       if( ( ulPhyStatus & PHY_LINK_FULLDUPLX ) != 0x00 )\r
+                       {\r
+                               Chip_ENET_SetDuplex( LPC_ETHERNET, true );\r
+                       }\r
+                       else\r
+                       {\r
+                               Chip_ENET_SetDuplex( LPC_ETHERNET, false );\r
+                       }\r
+\r
+                       xReturn = pdPASS;\r
+                       break;\r
+               }\r
+       } while( ( xTaskGetTickCount() - xTimeOnEntering ) < xAutoNegotiateDelay );\r
+\r
+       /* Reset the priority of this task back to its original value. */\r
+       vTaskPrioritySet( NULL, ipconfigIP_TASK_PRIORITY );\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static uint32_t prvGenerateCRC32( const uint8_t *ucAddress )\r
+{\r
+unsigned int j;\r
+const uint32_t Polynomial = 0xEDB88320;\r
+uint32_t crc = ~0ul;\r
+const uint8_t *pucCurrent = ( const uint8_t * ) ucAddress;\r
+const uint8_t *pucLast = pucCurrent + 6;\r
+\r
+    /* Calculate  normal CRC32 */\r
+    while( pucCurrent < pucLast )\r
+    {\r
+        crc ^= *( pucCurrent++ );\r
+        for( j = 0; j < 8; j++ )\r
+        {\r
+            if( ( crc & 1 ) != 0 )\r
+            {\r
+                crc = (crc >> 1) ^ Polynomial;\r
+            }\r
+            else\r
+            {\r
+                crc >>= 1;\r
+            }\r
+        }\r
+    }\r
+    return ~crc;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static uint32_t prvGetHashIndex( const uint8_t *ucAddress )\r
+{\r
+uint32_t ulCrc = prvGenerateCRC32( ucAddress );\r
+uint32_t ulIndex = 0ul;\r
+BaseType_t xCount = 6;\r
+\r
+    /* Take the lowest 6 bits of the CRC32 and reverse them */\r
+    while( xCount-- )\r
+    {\r
+        ulIndex <<= 1;\r
+        ulIndex |= ( ulCrc & 1 );\r
+        ulCrc >>= 1;\r
+    }\r
+\r
+    /* This is the has value of 'ucAddress' */\r
+    return ulIndex;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvAddMACAddress( const uint8_t* ucMacAddress )\r
+{\r
+BaseType_t xIndex;\r
+\r
+    xIndex = prvGetHashIndex( ucMacAddress );\r
+    if( xIndex >= 32 )\r
+    {\r
+        LPC_ETHERNET->MAC_HASHTABLE_HIGH |= ( 1u << ( xIndex - 32 ) );\r
+    }\r
+    else\r
+    {\r
+        LPC_ETHERNET->MAC_HASHTABLE_LOW |= ( 1u << xIndex );\r
+    }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+configPLACE_IN_SECTION_RAM\r
+static void prvEMACHandlerTask( void *pvParameters )\r
+{\r
+TimeOut_t xPhyTime;\r
+TickType_t xPhyRemTime;\r
+UBaseType_t uxLastMinBufferCount = 0;\r
+UBaseType_t uxCurrentCount;\r
+BaseType_t xResult = 0;\r
+uint32_t ulStatus;\r
+const TickType_t xBlockTime = pdMS_TO_TICKS( 5000ul );\r
+\r
+       /* Remove compiler warning about unused parameter. */\r
+       ( void ) pvParameters;\r
+\r
+       /* A possibility to set some additional task properties. */\r
+       iptraceEMAC_TASK_STARTING();\r
+\r
+       vTaskSetTimeOutState( &xPhyTime );\r
+       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+\r
+       for( ;; )\r
+       {\r
+               uxCurrentCount = uxGetMinimumFreeNetworkBuffers();\r
+               if( uxLastMinBufferCount != uxCurrentCount )\r
+               {\r
+                       /* The logging produced below may be helpful\r
+                       while tuning +TCP: see how many buffers are in use. */\r
+                       uxLastMinBufferCount = uxCurrentCount;\r
+                       FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",\r
+                               uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );\r
+               }\r
+\r
+               #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+               {\r
+               static UBaseType_t uxLastMinQueueSpace = 0;\r
+\r
+                       uxCurrentCount = uxGetMinimumIPQueueSpace();\r
+                       if( uxLastMinQueueSpace != uxCurrentCount )\r
+                       {\r
+                               /* The logging produced below may be helpful\r
+                               while tuning +TCP: see how many buffers are in use. */\r
+                               uxLastMinQueueSpace = uxCurrentCount;\r
+                               FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );\r
+                       }\r
+               }\r
+               #endif /* ipconfigCHECK_IP_QUEUE_SPACE */\r
+\r
+               ulTaskNotifyTake( pdTRUE, xBlockTime );\r
+\r
+               xResult = ( BaseType_t ) 0;\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
+                       {\r
+                               /* Check if DMA packets have been delivered. */\r
+                               vClearTXBuffers();\r
+                       }\r
+               }\r
+\r
+               if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 )\r
+               {\r
+                       ulISREvents &= ~EMAC_IF_RX_EVENT;\r
+\r
+                       xResult = prvNetworkInterfaceInput();\r
+                       if( xResult > 0 )\r
+                       {\r
+                               while( prvNetworkInterfaceInput() > 0 )\r
+                               {\r
+                               }\r
+                       }\r
+               }\r
+\r
+               if( xResult > 0 )\r
+               {\r
+                       /* A packet was received. No need to check for the PHY status now,\r
+                       but set a timer to check it later on. */\r
+                       vTaskSetTimeOutState( &xPhyTime );\r
+                       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+                       xResult = 0;\r
+               }\r
+               else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE )\r
+               {\r
+                       ulStatus = lpcPHYStsPoll();\r
+\r
+                       if( ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) != ( ulStatus & PHY_LINK_CONNECTED ) )\r
+                       {\r
+                               ulPHYLinkStatus = ulStatus;\r
+                               FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d (polled PHY)\n", ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) != 0 ) );\r
+                       }\r
+\r
+                       vTaskSetTimeOutState( &xPhyTime );\r
+                       if( ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) != 0 )\r
+                       {\r
+                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+                       }\r
+                       else\r
+                       {\r
+                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+                       }\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
index 6b926c8119141b8cbf3658884f137921bea87923..e759141cc34537942c595efe1fb5c12d58e4bdf1 100644 (file)
-/*
-FreeRTOS+TCP V2.0.11
-Copyright (C) 2018 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
-*/
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "list.h"
-#include "queue.h"
-#include "semphr.h"
-#include "task.h"
-
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_Sockets.h"
-#include "FreeRTOS_IP_Private.h"
-#include "NetworkBufferManagement.h"
-#include "NetworkInterface.h"
-
-
-#include "m480_eth.h"
-
-/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
-driver will filter incoming packets and only pass the stack those packets it
-considers need processing. */
-#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
-#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
-#else
-#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
-#endif
-
-/* Default the size of the stack used by the EMAC deferred handler task to twice
-the size of the stack used by the idle task - but allow this to be overridden in
-FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */
-#ifndef configEMAC_TASK_STACK_SIZE
-    #define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )
-#endif
-
-
-static SemaphoreHandle_t xTXMutex = NULL;
-
-/* The handle of the task that processes Rx packets.  The handle is required so
-the task can be notified when new packets arrive. */
-static TaskHandle_t xRxHanderTask = NULL;
-static TimerHandle_t xPhyHandlerTask = NULL;
-/*
- * A task that processes received frames.
- */
-static void prvEMACHandlerTask( void *pvParameters );
-static void prvPhyTmrCallback( TimerHandle_t xTimer );
-
-/* The size of each buffer when BufferAllocation_1 is used:
-http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html */
-
-#define niBUFFER_1_PACKET_SIZE        1536
-#ifdef __ICCARM__
-#pragma data_alignment=4
-static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ]
-#else
-static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ((aligned(4)));
-#endif
-
-BaseType_t xNetworkInterfaceInitialise( void )
-{
-    uint8_t hwaddr[6];
-    BaseType_t xReturn = pdPASS;
-
-    /* Init ETH */
-    numaker_mac_address(hwaddr);
-    FreeRTOS_UpdateMACAddress(hwaddr);
-    FreeRTOS_printf( ("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", hwaddr[0], hwaddr[1],hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5]) );
-    /* Enable clock & set EMAC configuration         */
-    /* Enable MAC and DMA transmission and reception */
-    if( numaker_eth_init(hwaddr) < 0)
-    {
-        xReturn = pdFAIL;
-    } else {
-        xReturn = pdPASS;
-        /* Guard against the task being created more than once and the
-        descriptors being initialized more than once. */
-        /* Timer task to monitor PHY Link status */
-        if( xPhyHandlerTask == NULL )
-        {
-            xPhyHandlerTask = xTimerCreate( "TimerPhy",  pdMS_TO_TICKS( 1000 ), pdTRUE, 0, prvPhyTmrCallback );
-            configASSERT(xPhyHandlerTask);
-            xReturn = xTimerStart( xPhyHandlerTask, 0 ) ;
-            configASSERT( xReturn );
-        }
-        /* Rx task */
-        if( xRxHanderTask == NULL )
-        {
-            xReturn = xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xRxHanderTask );
-            configASSERT( xReturn );
-        }
-        
-        if( xTXMutex == NULL )
-        {
-            xTXMutex = xSemaphoreCreateMutex();
-            configASSERT( xTXMutex );
-        }        
-    }
-
-        NVIC_SetPriority( EMAC_RX_IRQn, configMAC_INTERRUPT_PRIORITY );
-        NVIC_SetPriority( EMAC_TX_IRQn, configMAC_INTERRUPT_PRIORITY );
-
-        numaker_eth_enable_interrupts();
-
-        FreeRTOS_printf( ("ETH-RX priority:%d\n",NVIC_GetPriority( EMAC_RX_IRQn)) );
-
-    return xReturn;
-}
-
-BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend )
-{
-    uint8_t *buffer=NULL;
-//    FreeRTOS_printf(("<-- dataLength=%d\n",pxDescriptor->xDataLength));
-    if( pxDescriptor->xDataLength >= PACKET_BUFFER_SIZE )
-    {
-        FreeRTOS_printf(("TX buffer length %d over %d\n", pxDescriptor->xDataLength, PACKET_BUFFER_SIZE));
-        return pdFALSE;
-    }
-    
-    buffer = numaker_eth_get_tx_buf();
-    if( buffer == NULL )
-    {
-        NU_DEBUGF(("Eth TX slots are busy\n"));
-        return pdFALSE;
-    }    
-    
-    /* Get exclusive access */
-    xSemaphoreTake(xTXMutex, portMAX_DELAY);
-    NU_DEBUGF(("%s ... buffer=0x%x\r\n",__FUNCTION__, buffer));   
-    //SendData: pt = pxDescriptor->pucBuffer, length = pxDescriptor->xDataLength
-    memcpy(buffer, pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength);
-    numaker_eth_trigger_tx(pxDescriptor->xDataLength, NULL);
-    /* Call the standard trace macro to log the send event. */
-    iptraceNETWORK_INTERFACE_TRANSMIT();
-
-    if( xReleaseAfterSend != pdFALSE )
-    {
-        /* It is assumed SendData() copies the data out of the FreeRTOS+TCP Ethernet
-        buffer.  The Ethernet buffer is therefore no longer needed, and must be
-        freed for re-use. */
-        vReleaseNetworkBufferAndDescriptor( pxDescriptor );
-    }
-
-    xSemaphoreGive(xTXMutex);
-    
-    return pdTRUE;
-}
-
-
-void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
-{
-
-    uint8_t *ucRAMBuffer = ucNetworkPackets;
-    uint32_t ul;
-
-    for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )
-    {
-        pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;
-        *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );
-        ucRAMBuffer += niBUFFER_1_PACKET_SIZE;
-    }
-}
-
-
-BaseType_t xGetPhyLinkStatus( void )
-{
-    BaseType_t xReturn;
-
-    if( numaker_eth_link_ok() )
-    {
-        xReturn = pdPASS;
-    }
-    else
-    {
-        xReturn = pdFAIL;
-    }
-
-    return xReturn;
-}
-
-static void prvPhyTmrCallback( TimerHandle_t xTimer )
-{
-    IPStackEvent_t xRxEvent;
-    static BaseType_t lastLink = pdFAIL;
-    BaseType_t currLink = xGetPhyLinkStatus();
-    if( currLink != lastLink )
-    {
-        FreeRTOS_printf(("PHY Link %s\n", (currLink) ? "Up" : "Down"));
-        if( !currLink )
-        {
-            xRxEvent.eEventType = eNetworkDownEvent;
-            xSendEventStructToIPTask( &xRxEvent, 0 );
-        }
-        lastLink = currLink;
-    }
-
-}    
-
-    
-static void prvEMACHandlerTask( void *pvParameters )
-{
-    TimeOut_t xPhyTime;
-    TickType_t xPhyRemTime;
-    UBaseType_t uxLastMinBufferCount = 0;
-    UBaseType_t uxCurrentCount;
-    BaseType_t xResult = 0;
-    uint32_t ulStatus;
-    uint16_t dataLength = 0;
-    uint8_t *buffer = NULL;
-    NetworkBufferDescriptor_t *pxBufferDescriptor = NULL;
-    IPStackEvent_t xRxEvent;
-    const TickType_t xBlockTime = pdMS_TO_TICKS( 5000ul );
-    
-    /* Remove compiler warnings about unused parameters. */
-    ( void ) pvParameters;
-    /* A possibility to set some additional task properties. */
-    
-    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 ) );
-        }
-        
-        /* No events to process now, wait for the next. */
-        ulTaskNotifyTake( pdFALSE, portMAX_DELAY ); 
-        while(1)
-        {    
-            /* get received frame */
-            if ( numaker_eth_get_rx_buf(&dataLength, &buffer) != 0) {
-            /* The event was lost because a network buffer was not available.
-            Call the standard trace macro to log the occurrence. */
-                iptraceETHERNET_RX_EVENT_LOST();
-                break;
-            }        
-
-            /* Allocate a network buffer descriptor that points to a buffer
-            large enough to hold the received frame.  As this is the simple
-            rather than efficient example the received data will just be copied
-            into this buffer. */
-
-            pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( PACKET_BUFFER_SIZE, 0 );
-
-            if( pxBufferDescriptor != NULL )
-            {        
-                memcpy( pxBufferDescriptor->pucEthernetBuffer, buffer, dataLength );
-//                          FreeRTOS_printf(("--> dataLength=%d\n",dataLength));
-                pxBufferDescriptor->xDataLength = dataLength;            
-            } else {
-                numaker_eth_rx_next();
-                iptraceETHERNET_RX_EVENT_LOST();
-                break;
-            }
-            /* The event about to be sent to the TCP/IP is an Rx event. */
-            xRxEvent.eEventType = eNetworkRxEvent;
-
-            /* pvData is used to point to the network buffer descriptor that
-                now references the received data. */
-            xRxEvent.pvData = ( void * ) pxBufferDescriptor;
-
-            /* Send the data to the TCP/IP stack. */
-            if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )
-            {
-                /* The buffer could not be sent to the IP task so the buffer
-                 must be released. */
-                vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );
-
-                /* Make a call to the standard trace macro to log the
-                        occurrence. */
-
-                iptraceETHERNET_RX_EVENT_LOST();
-            } else
-            {
-                /* The message was successfully sent to the TCP/IP stack.
-                Call the standard trace macro to log the occurrence. */
-                iptraceNETWORK_INTERFACE_RECEIVE();
-            } 
-                numaker_eth_rx_next();
-        }    
-        numaker_eth_trigger_rx();
-    }
-}
-
-void xNetworkCallback(char event)
-{
-    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-    switch (event)
-    {
-      case 'R': //For RX event
-    /* Wakeup the prvEMACHandlerTask. */
-        if( xRxHanderTask != NULL )
-        {
-            vTaskNotifyGiveFromISR( xRxHanderTask, &xHigherPriorityTaskWoken );
-            portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
-        }
-        break;
-      case 'T': //For TX event
-        // ack of tx done, no-op in this stage
-        break;
-      default:
-        break;
-    }
-}
+/*\r
+FreeRTOS+TCP V2.0.11\r
+Copyright (C) 2018 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
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "list.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+#include "task.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+#include "NetworkInterface.h"\r
+\r
+\r
+#include "m480_eth.h"\r
+\r
+/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet\r
+driver will filter incoming packets and only pass the stack those packets it\r
+considers need processing. */\r
+#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )\r
+#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer\r
+#else\r
+#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )\r
+#endif\r
+\r
+/* Default the size of the stack used by the EMAC deferred handler task to twice\r
+the size of the stack used by the idle task - but allow this to be overridden in\r
+FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */\r
+#ifndef configEMAC_TASK_STACK_SIZE\r
+    #define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )\r
+#endif\r
+\r
+\r
+static SemaphoreHandle_t xTXMutex = NULL;\r
+\r
+/* The handle of the task that processes Rx packets.  The handle is required so\r
+the task can be notified when new packets arrive. */\r
+static TaskHandle_t xRxHanderTask = NULL;\r
+static TimerHandle_t xPhyHandlerTask = NULL;\r
+/*\r
+ * A task that processes received frames.\r
+ */\r
+static void prvEMACHandlerTask( void *pvParameters );\r
+static void prvPhyTmrCallback( TimerHandle_t xTimer );\r
+\r
+/* The size of each buffer when BufferAllocation_1 is used:\r
+http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html */\r
+\r
+#define niBUFFER_1_PACKET_SIZE        1536\r
+#ifdef __ICCARM__\r
+#pragma data_alignment=4\r
+static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ]\r
+#else\r
+static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ((aligned(4)));\r
+#endif\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+    uint8_t hwaddr[6];\r
+    BaseType_t xReturn = pdPASS;\r
+\r
+    /* Init ETH */\r
+    numaker_mac_address(hwaddr);\r
+    FreeRTOS_UpdateMACAddress(hwaddr);\r
+    FreeRTOS_printf( ("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", hwaddr[0], hwaddr[1],hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5]) );\r
+    /* Enable clock & set EMAC configuration         */\r
+    /* Enable MAC and DMA transmission and reception */\r
+    if( numaker_eth_init(hwaddr) < 0)\r
+    {\r
+        xReturn = pdFAIL;\r
+    } else {\r
+        xReturn = pdPASS;\r
+        /* Guard against the task being created more than once and the\r
+        descriptors being initialized more than once. */\r
+        /* Timer task to monitor PHY Link status */\r
+        if( xPhyHandlerTask == NULL )\r
+        {\r
+            xPhyHandlerTask = xTimerCreate( "TimerPhy",  pdMS_TO_TICKS( 1000 ), pdTRUE, 0, prvPhyTmrCallback );\r
+            configASSERT(xPhyHandlerTask);\r
+            xReturn = xTimerStart( xPhyHandlerTask, 0 ) ;\r
+            configASSERT( xReturn );\r
+        }\r
+        /* Rx task */\r
+        if( xRxHanderTask == NULL )\r
+        {\r
+            xReturn = xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xRxHanderTask );\r
+            configASSERT( xReturn );\r
+        }\r
+        \r
+        if( xTXMutex == NULL )\r
+        {\r
+            xTXMutex = xSemaphoreCreateMutex();\r
+            configASSERT( xTXMutex );\r
+        }        \r
+    }\r
+\r
+        NVIC_SetPriority( EMAC_RX_IRQn, configMAC_INTERRUPT_PRIORITY );\r
+        NVIC_SetPriority( EMAC_TX_IRQn, configMAC_INTERRUPT_PRIORITY );\r
+\r
+        numaker_eth_enable_interrupts();\r
+\r
+        FreeRTOS_printf( ("ETH-RX priority:%d\n",NVIC_GetPriority( EMAC_RX_IRQn)) );\r
+\r
+    return xReturn;\r
+}\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend )\r
+{\r
+    uint8_t *buffer=NULL;\r
+//    FreeRTOS_printf(("<-- dataLength=%d\n",pxDescriptor->xDataLength));\r
+    if( pxDescriptor->xDataLength >= PACKET_BUFFER_SIZE )\r
+    {\r
+        FreeRTOS_printf(("TX buffer length %d over %d\n", pxDescriptor->xDataLength, PACKET_BUFFER_SIZE));\r
+        return pdFALSE;\r
+    }\r
+    \r
+    buffer = numaker_eth_get_tx_buf();\r
+    if( buffer == NULL )\r
+    {\r
+        NU_DEBUGF(("Eth TX slots are busy\n"));\r
+        return pdFALSE;\r
+    }    \r
+    \r
+    /* Get exclusive access */\r
+    xSemaphoreTake(xTXMutex, portMAX_DELAY);\r
+    NU_DEBUGF(("%s ... buffer=0x%x\r\n",__FUNCTION__, buffer));   \r
+    //SendData: pt = pxDescriptor->pucBuffer, length = pxDescriptor->xDataLength\r
+    memcpy(buffer, pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength);\r
+    numaker_eth_trigger_tx(pxDescriptor->xDataLength, NULL);\r
+    /* Call the standard trace macro to log the send event. */\r
+    iptraceNETWORK_INTERFACE_TRANSMIT();\r
+\r
+    if( xReleaseAfterSend != pdFALSE )\r
+    {\r
+        /* It is assumed SendData() copies the data out of the FreeRTOS+TCP Ethernet\r
+        buffer.  The Ethernet buffer is therefore no longer needed, and must be\r
+        freed for re-use. */\r
+        vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
+    }\r
+\r
+    xSemaphoreGive(xTXMutex);\r
+    \r
+    return pdTRUE;\r
+}\r
+\r
+\r
+void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )\r
+{\r
+\r
+    uint8_t *ucRAMBuffer = ucNetworkPackets;\r
+    uint32_t ul;\r
+\r
+    for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )\r
+    {\r
+        pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;\r
+        *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );\r
+        ucRAMBuffer += niBUFFER_1_PACKET_SIZE;\r
+    }\r
+}\r
+\r
+\r
+BaseType_t xGetPhyLinkStatus( void )\r
+{\r
+    BaseType_t xReturn;\r
+\r
+    if( numaker_eth_link_ok() )\r
+    {\r
+        xReturn = pdPASS;\r
+    }\r
+    else\r
+    {\r
+        xReturn = pdFAIL;\r
+    }\r
+\r
+    return xReturn;\r
+}\r
+\r
+static void prvPhyTmrCallback( TimerHandle_t xTimer )\r
+{\r
+    IPStackEvent_t xRxEvent;\r
+    static BaseType_t lastLink = pdFAIL;\r
+    BaseType_t currLink = xGetPhyLinkStatus();\r
+    if( currLink != lastLink )\r
+    {\r
+        FreeRTOS_printf(("PHY Link %s\n", (currLink) ? "Up" : "Down"));\r
+        if( !currLink )\r
+        {\r
+            xRxEvent.eEventType = eNetworkDownEvent;\r
+            xSendEventStructToIPTask( &xRxEvent, 0 );\r
+        }\r
+        lastLink = currLink;\r
+    }\r
+\r
+}    \r
+\r
+    \r
+static void prvEMACHandlerTask( void *pvParameters )\r
+{\r
+    TimeOut_t xPhyTime;\r
+    TickType_t xPhyRemTime;\r
+    UBaseType_t uxLastMinBufferCount = 0;\r
+    UBaseType_t uxCurrentCount;\r
+    BaseType_t xResult = 0;\r
+    uint32_t ulStatus;\r
+    uint16_t dataLength = 0;\r
+    uint8_t *buffer = NULL;\r
+    NetworkBufferDescriptor_t *pxBufferDescriptor = NULL;\r
+    IPStackEvent_t xRxEvent;\r
+    const TickType_t xBlockTime = pdMS_TO_TICKS( 5000ul );\r
+    \r
+    /* Remove compiler warnings about unused parameters. */\r
+    ( void ) pvParameters;\r
+    /* A possibility to set some additional task properties. */\r
+    \r
+    for( ;; )\r
+    {\r
+        uxCurrentCount = uxGetMinimumFreeNetworkBuffers();\r
+        if( uxLastMinBufferCount != uxCurrentCount )\r
+        {\r
+            /* The logging produced below may be helpful\r
+            while tuning +TCP: see how many buffers are in use. */\r
+            uxLastMinBufferCount = uxCurrentCount;\r
+            FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",\r
+                uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );\r
+        }\r
+        \r
+        /* No events to process now, wait for the next. */\r
+        ulTaskNotifyTake( pdFALSE, portMAX_DELAY ); \r
+        while(1)\r
+        {    \r
+            /* get received frame */\r
+            if ( numaker_eth_get_rx_buf(&dataLength, &buffer) != 0) {\r
+            /* The event was lost because a network buffer was not available.\r
+            Call the standard trace macro to log the occurrence. */\r
+                iptraceETHERNET_RX_EVENT_LOST();\r
+                break;\r
+            }        \r
+\r
+            /* Allocate a network buffer descriptor that points to a buffer\r
+            large enough to hold the received frame.  As this is the simple\r
+            rather than efficient example the received data will just be copied\r
+            into this buffer. */\r
+\r
+            pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( PACKET_BUFFER_SIZE, 0 );\r
+\r
+            if( pxBufferDescriptor != NULL )\r
+            {        \r
+                memcpy( pxBufferDescriptor->pucEthernetBuffer, buffer, dataLength );\r
+//                          FreeRTOS_printf(("--> dataLength=%d\n",dataLength));\r
+                pxBufferDescriptor->xDataLength = dataLength;            \r
+            } else {\r
+                numaker_eth_rx_next();\r
+                iptraceETHERNET_RX_EVENT_LOST();\r
+                break;\r
+            }\r
+            /* The event about to be sent to the TCP/IP is an Rx event. */\r
+            xRxEvent.eEventType = eNetworkRxEvent;\r
+\r
+            /* pvData is used to point to the network buffer descriptor that\r
+                now references the received data. */\r
+            xRxEvent.pvData = ( void * ) pxBufferDescriptor;\r
+\r
+            /* Send the data to the TCP/IP stack. */\r
+            if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )\r
+            {\r
+                /* The buffer could not be sent to the IP task so the buffer\r
+                 must be released. */\r
+                vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );\r
+\r
+                /* Make a call to the standard trace macro to log the\r
+                        occurrence. */\r
+\r
+                iptraceETHERNET_RX_EVENT_LOST();\r
+            } else\r
+            {\r
+                /* The message was successfully sent to the TCP/IP stack.\r
+                Call the standard trace macro to log the occurrence. */\r
+                iptraceNETWORK_INTERFACE_RECEIVE();\r
+            } \r
+                numaker_eth_rx_next();\r
+        }    \r
+        numaker_eth_trigger_rx();\r
+    }\r
+}\r
+\r
+void xNetworkCallback(char event)\r
+{\r
+    BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
+    switch (event)\r
+    {\r
+      case 'R': //For RX event\r
+    /* Wakeup the prvEMACHandlerTask. */\r
+        if( xRxHanderTask != NULL )\r
+        {\r
+            vTaskNotifyGiveFromISR( xRxHanderTask, &xHigherPriorityTaskWoken );\r
+            portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
+        }\r
+        break;\r
+      case 'T': //For TX event\r
+        // ack of tx done, no-op in this stage\r
+        break;\r
+      default:\r
+        break;\r
+    }\r
+}\r
index cf862da3ea7c9c110ca546ac52c565682435332b..2d45661d003606d220e0bfba536b36a7ebd73a29 100644 (file)
-/**************************************************************************//**
- * @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *   1. Redistributions of source code must retain the above copyright notice,
- *      this list of conditions and the following disclaimer.
- *   2. Redistributions in binary form must reproduce the above copyright notice,
- *      this list of conditions and the following disclaimer in the documentation
- *      and/or other materials provided with the distribution.
- *   3. Neither the name of Nuvoton Technology Corp. nor the names of its contributors
- *      may be used to endorse or promote products derived from this software
- *      without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*****************************************************************************/
-#include "FreeRTOS.h"
-#include "list.h"
-#include "FreeRTOS_IP.h"
-
-#include "m480_eth.h"
-
-#define ETH_TRIGGER_RX()    do{EMAC->RXST = 0;}while(0)
-#define ETH_TRIGGER_TX()    do{EMAC->TXST = 0;}while(0)
-#define ETH_ENABLE_TX()     do{EMAC->CTL |= EMAC_CTL_TXON;}while(0)
-#define ETH_ENABLE_RX()     do{EMAC->CTL |= EMAC_CTL_RXON;}while(0)
-#define ETH_DISABLE_TX()    do{EMAC->CTL &= ~EMAC_CTL_TXON;}while(0)
-#define ETH_DISABLE_RX()    do{EMAC->CTL &= ~EMAC_CTL_RXON;}while(0)
-    
-
-struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));
-struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));
-#ifdef __ICCARM__
-#pragma data_alignment=4
-struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM];
-struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM];
-uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
-uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
-#else
-struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));
-struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));
-uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE]  __attribute__ ((aligned(4)));
-uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE]  __attribute__ ((aligned(4)));
-#endif
-struct eth_descriptor volatile *cur_tx_desc_ptr, *cur_rx_desc_ptr, *fin_tx_desc_ptr;
-
-
-// PTP source clock is 84MHz (Real chip using PLL). Each tick is 11.90ns
-// Assume we want to set each tick to 100ns.
-// Increase register = (100 * 2^31) / (10^9) = 214.71 =~ 215 = 0xD7
-// Addend register = 2^32 * tick_freq / (84MHz), where tick_freq = (2^31 / 215) MHz
-// From above equation, addend register = 2^63 / (84M * 215) ~= 510707200 = 0x1E70C600
-
-
-
-static void mdio_write(uint8_t addr, uint8_t reg, uint16_t val)
-{
-
-    EMAC->MIIMDAT = val;
-    EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_WRITE_Msk | EMAC_MIIMCTL_MDCON_Msk;
-
-    while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);
-
-}
-
-
-static uint16_t mdio_read(uint8_t addr, uint8_t reg)
-{
-    EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk;
-    while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);
-
-    return(EMAC->MIIMDAT);
-}
-
-static int reset_phy(void)
-{
-
-    uint16_t reg;
-    uint32_t delayCnt;
-
-
-    mdio_write(CONFIG_PHY_ADDR, MII_BMCR, BMCR_RESET);
-
-    delayCnt = 2000;
-    while(delayCnt-- > 0) {
-        if((mdio_read(CONFIG_PHY_ADDR, MII_BMCR) & BMCR_RESET) == 0)
-            break;
-
-    }
-
-    if(delayCnt == 0) {
-        NU_DEBUGF(("Reset phy failed\n"));
-        return(-1);
-    }
-
-    mdio_write(CONFIG_PHY_ADDR, MII_ADVERTISE, ADVERTISE_CSMA |
-               ADVERTISE_10HALF |
-               ADVERTISE_10FULL |
-               ADVERTISE_100HALF |
-               ADVERTISE_100FULL);
-
-    reg = mdio_read(CONFIG_PHY_ADDR, MII_BMCR);
-    mdio_write(CONFIG_PHY_ADDR, MII_BMCR, reg | BMCR_ANRESTART);
-
-    delayCnt = 200000;
-    while(delayCnt-- > 0) {
-        if((mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS))
-                == (BMSR_ANEGCOMPLETE | BMSR_LSTATUS))
-            break;
-    }
-
-    if(delayCnt == 0) {
-        NU_DEBUGF(("AN failed. Set to 100 FULL\n"));
-        EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
-        return(-1);
-    } else {
-        reg = mdio_read(CONFIG_PHY_ADDR, MII_LPA);
-
-        if(reg & ADVERTISE_100FULL) {
-            NU_DEBUGF(("100 full\n"));
-            EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
-        } else if(reg & ADVERTISE_100HALF) {
-            NU_DEBUGF(("100 half\n"));
-            EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_FUDUP_Msk) | EMAC_CTL_OPMODE_Msk;
-        } else if(reg & ADVERTISE_10FULL) {
-            NU_DEBUGF(("10 full\n"));
-            EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_OPMODE_Msk) | EMAC_CTL_FUDUP_Msk;
-        } else {
-            NU_DEBUGF(("10 half\n"));
-            EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
-        }
-    }
-       FreeRTOS_printf(("PHY ID 1:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID1)));
-       FreeRTOS_printf(("PHY ID 2:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID2)));
-
-    return(0);
-}
-
-
-static void init_tx_desc(void)
-{
-    uint32_t i;
-
-
-    cur_tx_desc_ptr = fin_tx_desc_ptr = &tx_desc[0];
-
-    for(i = 0; i < TX_DESCRIPTOR_NUM; i++) {
-        tx_desc[i].status1 = TXFD_PADEN | TXFD_CRCAPP | TXFD_INTEN;
-        tx_desc[i].buf = &tx_buf[i][0];
-        tx_desc[i].status2 = 0;
-        tx_desc[i].next = &tx_desc[(i + 1) % TX_DESCRIPTOR_NUM];
-
-    }
-    EMAC->TXDSA = (unsigned int)&tx_desc[0];
-    return;
-}
-
-static void init_rx_desc(void)
-{
-    uint32_t i;
-
-
-    cur_rx_desc_ptr = &rx_desc[0];
-
-    for(i = 0; i < RX_DESCRIPTOR_NUM; i++) {
-        rx_desc[i].status1 = OWNERSHIP_EMAC;
-        rx_desc[i].buf = &rx_buf[i][0];
-        rx_desc[i].status2 = 0;
-        rx_desc[i].next = &rx_desc[(i + 1) % TX_DESCRIPTOR_NUM];
-    }
-    EMAC->RXDSA = (unsigned int)&rx_desc[0];
-    return;
-}
-
-void numaker_set_mac_addr(uint8_t *addr)
-{
-
-    EMAC->CAM0M = (addr[0] << 24) |
-                  (addr[1] << 16) |
-                  (addr[2] << 8) |
-                  addr[3];
-
-    EMAC->CAM0L = (addr[4] << 24) |
-                  (addr[5] << 16);
-
-
-}
-
-static void __eth_clk_pin_init()
-{
-    /* Unlock protected registers */
-    SYS_UnlockReg();
-
-    /* Enable IP clock */
-    CLK_EnableModuleClock(EMAC_MODULE);
-    
-    // Configure MDC clock rate to HCLK / (127 + 1) = 1.25 MHz if system is running at 160 MH
-    CLK_SetModuleClock(EMAC_MODULE, 0, CLK_CLKDIV3_EMAC(127));
-    
-    /* Update System Core Clock */
-    SystemCoreClockUpdate();
-    
-    /*---------------------------------------------------------------------------------------------------------*/
-    /* Init I/O Multi-function                                                                                 */
-    /*---------------------------------------------------------------------------------------------------------*/
-    // Configure RMII pins
-    SYS->GPA_MFPL &= ~(SYS_GPA_MFPL_PA6MFP_Msk | SYS_GPA_MFPL_PA7MFP_Msk);
-    SYS->GPA_MFPL |= SYS_GPA_MFPL_PA6MFP_EMAC_RMII_RXERR | SYS_GPA_MFPL_PA7MFP_EMAC_RMII_CRSDV;
-    SYS->GPC_MFPL &= ~(SYS_GPC_MFPL_PC6MFP_Msk | SYS_GPC_MFPL_PC7MFP_Msk);
-    SYS->GPC_MFPL |= SYS_GPC_MFPL_PC6MFP_EMAC_RMII_RXD1 | SYS_GPC_MFPL_PC7MFP_EMAC_RMII_RXD0;
-    SYS->GPC_MFPH &= ~SYS_GPC_MFPH_PC8MFP_Msk;
-    SYS->GPC_MFPH |= SYS_GPC_MFPH_PC8MFP_EMAC_RMII_REFCLK;
-    SYS->GPE_MFPH &= ~(SYS_GPE_MFPH_PE8MFP_Msk | SYS_GPE_MFPH_PE9MFP_Msk | SYS_GPE_MFPH_PE10MFP_Msk |
-                       SYS_GPE_MFPH_PE11MFP_Msk | SYS_GPE_MFPH_PE12MFP_Msk);
-    SYS->GPE_MFPH |= SYS_GPE_MFPH_PE8MFP_EMAC_RMII_MDC |
-                    SYS_GPE_MFPH_PE9MFP_EMAC_RMII_MDIO |
-                    SYS_GPE_MFPH_PE10MFP_EMAC_RMII_TXD0 |
-                    SYS_GPE_MFPH_PE11MFP_EMAC_RMII_TXD1 |
-                    SYS_GPE_MFPH_PE12MFP_EMAC_RMII_TXEN;
-
-    // Enable high slew rate on all RMII TX output pins
-    PE->SLEWCTL = (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN10_Pos) |
-                  (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN11_Pos) |
-                  (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN12_Pos);
-
-
-    /* Lock protected registers */
-    SYS_LockReg();
-
-
-}
-
-int numaker_eth_init(uint8_t *mac_addr)
-{
-    int ret = 0;
-    // init CLK & pins
-    __eth_clk_pin_init();
-  
-    // Reset MAC
-    EMAC->CTL = EMAC_CTL_RST_Msk;
-    while(EMAC->CTL & EMAC_CTL_RST_Msk) {}
-
-    init_tx_desc();
-    init_rx_desc();
-
-    numaker_set_mac_addr(mac_addr);  // need to reconfigure hardware address 'cos we just RESET emc...
-
-
-    /* Configure the MAC interrupt enable register. */
-    EMAC->INTEN = EMAC_INTEN_RXIEN_Msk |
-                  EMAC_INTEN_TXIEN_Msk |
-                  EMAC_INTEN_RXGDIEN_Msk |
-                  EMAC_INTEN_TXCPIEN_Msk |
-                  EMAC_INTEN_RXBEIEN_Msk |
-                  EMAC_INTEN_TXBEIEN_Msk |
-                  EMAC_INTEN_RDUIEN_Msk |
-                  EMAC_INTEN_TSALMIEN_Msk |
-                  EMAC_INTEN_WOLIEN_Msk;
-
-    /* Configure the MAC control register. */
-    EMAC->CTL = EMAC_CTL_STRIPCRC_Msk | EMAC_CTL_RMIIEN_Msk;
-
-    /* Accept packets for us and all broadcast and multicast packets */
-    EMAC->CAMCTL =  EMAC_CAMCTL_CMPEN_Msk |
-                    EMAC_CAMCTL_AMP_Msk |
-                    EMAC_CAMCTL_ABP_Msk;
-    EMAC->CAMEN = 1;    // Enable CAM entry 0    
-
-    ret= reset_phy();                    
-                    
-    EMAC_ENABLE_RX();
-    EMAC_ENABLE_TX();
-    return ret;
-}
-
-
-
-void  ETH_halt(void)
-{
-
-    EMAC->CTL &= ~(EMAC_CTL_RXON_Msk | EMAC_CTL_TXON_Msk);
-}
-
-unsigned int m_status;
-
-void EMAC_RX_IRQHandler(void)
-{
-//    NU_DEBUGF(("%s ... \r\n", __FUNCTION__));
-    m_status = EMAC->INTSTS & 0xFFFF;
-    EMAC->INTSTS = m_status;
-    if (m_status & EMAC_INTSTS_RXBEIF_Msk) {
-        // Shouldn't goes here, unless descriptor corrupted
-               NU_DEBUGF(("RX descriptor corrupted \r\n"));
-               //return;
-    }
-    // FIX ME: for rx-event, to ack rx_isr into event queue
-        xNetworkCallback('R');
-}
-
-
-void numaker_eth_trigger_rx(void)
-{
-    ETH_TRIGGER_RX();
-}
-
-int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf)
-{
-    unsigned int cur_entry, status;
-
-    cur_entry = EMAC->CRXDSA;
-    if ((cur_entry == (uint32_t)cur_rx_desc_ptr) && (!(m_status & EMAC_INTSTS_RDUIF_Msk)))  // cur_entry may equal to cur_rx_desc_ptr if RDU occures
-            return -1;
-    status = cur_rx_desc_ptr->status1;
-
-    if(status & OWNERSHIP_EMAC)
-            return -1;
-
-    if (status & RXFD_RXGD) {
-        *buf = cur_rx_desc_ptr->buf;
-        *len = status & 0xFFFF;
-    }
-    return 0;
-}    
-
-void numaker_eth_rx_next(void)
-{
-    cur_rx_desc_ptr->status1 = OWNERSHIP_EMAC;
-    cur_rx_desc_ptr = cur_rx_desc_ptr->next;    
-}    
-
-void EMAC_TX_IRQHandler(void)
-{
-    unsigned int cur_entry, status;
-
-    status = EMAC->INTSTS & 0xFFFF0000;
-    EMAC->INTSTS = status;
-    if(status & EMAC_INTSTS_TXBEIF_Msk) {
-        // Shouldn't goes here, unless descriptor corrupted
-        return;
-    }
-
-    cur_entry = EMAC->CTXDSA;
-
-    while (cur_entry != (uint32_t)fin_tx_desc_ptr) {
-
-        fin_tx_desc_ptr = fin_tx_desc_ptr->next;
-    }
-    // FIX ME: for tx-event, no-op at this stage
-    xNetworkCallback('T');
-}
-
-uint8_t *numaker_eth_get_tx_buf(void)
-{
-    if(cur_tx_desc_ptr->status1 & OWNERSHIP_EMAC)
-        return(NULL);
-    else
-        return(cur_tx_desc_ptr->buf);
-}
-
-void numaker_eth_trigger_tx(uint16_t length, void *p)
-{
-    struct eth_descriptor volatile *desc;
-    cur_tx_desc_ptr->status2 = (unsigned int)length;
-    desc = cur_tx_desc_ptr->next;    // in case TX is transmitting and overwrite next pointer before we can update cur_tx_desc_ptr
-    cur_tx_desc_ptr->status1 |= OWNERSHIP_EMAC;
-    cur_tx_desc_ptr = desc;
-
-    ETH_TRIGGER_TX();
-
-}
-
-int numaker_eth_link_ok(void)
-{
-    /* first, a dummy read to latch */
-    mdio_read(CONFIG_PHY_ADDR, MII_BMSR);
-    if(mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & BMSR_LSTATUS)
-      return 1;
-    return 0;  
-}
-
-//void numaker_eth_set_cb(eth_callback_t eth_cb, void *userData)
-//{
-//    nu_eth_txrx_cb =  eth_cb;
-//    nu_userData = userData;
-//}
-
-// Provide ethernet devices with a semi-unique MAC address
-void numaker_mac_address(uint8_t *mac)
-{
-    uint32_t uID1;
-    // Fetch word 0
-    uint32_t word0 = *(uint32_t *)0x7F804; // 2KB Data Flash at 0x7F800
-    // Fetch word 1
-    // we only want bottom 16 bits of word1 (MAC bits 32-47)
-    // and bit 9 forced to 1, bit 8 forced to 0
-    // Locally administered MAC, reduced conflicts
-    // http://en.wikipedia.org/wiki/MAC_address
-    uint32_t word1 = *(uint32_t *)0x7F800; // 2KB Data Flash at 0x7F800
-
-    if( word0 == 0xFFFFFFFF )          // Not burn any mac address at 1st 2 words of Data Flash
-    {
-        // with a semi-unique MAC address from the UUID
-        /* Enable FMC ISP function */
-        SYS_UnlockReg();
-        FMC_Open();
-        // = FMC_ReadUID(0);
-        uID1 = FMC_ReadUID(1);
-        word1 = (uID1 & 0x003FFFFF) | ((uID1 & 0x030000) << 6) >> 8;
-        word0 = ((FMC_ReadUID(0) >> 4) << 20) | ((uID1 & 0xFF)<<12) | (FMC_ReadUID(2) & 0xFFF);
-        /* Disable FMC ISP function */
-        FMC_Close();
-        /* Lock protected registers */
-        SYS_LockReg();
-    }
-
-    word1 |= 0x00000200;
-    word1 &= 0x0000FEFF;
-
-    mac[0] = (word1 & 0x0000ff00) >> 8;    
-    mac[1] = (word1 & 0x000000ff);
-    mac[2] = (word0 & 0xff000000) >> 24;
-    mac[3] = (word0 & 0x00ff0000) >> 16;
-    mac[4] = (word0 & 0x0000ff00) >> 8;
-    mac[5] = (word0 & 0x000000ff);
-    
-    NU_DEBUGF(("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", mac[0], mac[1],mac[2],mac[3],mac[4],mac[5]));
-}
-
-void numaker_eth_enable_interrupts(void) {
-  EMAC->INTEN |= EMAC_INTEN_RXIEN_Msk |
-                   EMAC_INTEN_TXIEN_Msk ;
-  NVIC_EnableIRQ(EMAC_RX_IRQn);
-  NVIC_EnableIRQ(EMAC_TX_IRQn);
-}
-
-void numaker_eth_disable_interrupts(void) {
-  NVIC_DisableIRQ(EMAC_RX_IRQn);
-  NVIC_DisableIRQ(EMAC_TX_IRQn);
-}
+/**************************************************************************//**\r
+ * @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.\r
+ * \r
+ * Redistribution and use in source and binary forms, with or without modification,\r
+ * are permitted provided that the following conditions are met:\r
+ *   1. Redistributions of source code must retain the above copyright notice,\r
+ *      this list of conditions and the following disclaimer.\r
+ *   2. Redistributions in binary form must reproduce the above copyright notice,\r
+ *      this list of conditions and the following disclaimer in the documentation\r
+ *      and/or other materials provided with the distribution.\r
+ *   3. Neither the name of Nuvoton Technology Corp. nor the names of its contributors\r
+ *      may be used to endorse or promote products derived from this software\r
+ *      without specific prior written permission.\r
+ * \r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\r
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\r
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\r
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+*****************************************************************************/\r
+#include "FreeRTOS.h"\r
+#include "list.h"\r
+#include "FreeRTOS_IP.h"\r
+\r
+#include "m480_eth.h"\r
+\r
+#define ETH_TRIGGER_RX()    do{EMAC->RXST = 0;}while(0)\r
+#define ETH_TRIGGER_TX()    do{EMAC->TXST = 0;}while(0)\r
+#define ETH_ENABLE_TX()     do{EMAC->CTL |= EMAC_CTL_TXON;}while(0)\r
+#define ETH_ENABLE_RX()     do{EMAC->CTL |= EMAC_CTL_RXON;}while(0)\r
+#define ETH_DISABLE_TX()    do{EMAC->CTL &= ~EMAC_CTL_TXON;}while(0)\r
+#define ETH_DISABLE_RX()    do{EMAC->CTL &= ~EMAC_CTL_RXON;}while(0)\r
+    \r
+\r
+struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));\r
+struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));\r
+#ifdef __ICCARM__\r
+#pragma data_alignment=4\r
+struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM];\r
+struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM];\r
+uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];\r
+uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];\r
+#else\r
+struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));\r
+struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));\r
+uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE]  __attribute__ ((aligned(4)));\r
+uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE]  __attribute__ ((aligned(4)));\r
+#endif\r
+struct eth_descriptor volatile *cur_tx_desc_ptr, *cur_rx_desc_ptr, *fin_tx_desc_ptr;\r
+\r
+\r
+// PTP source clock is 84MHz (Real chip using PLL). Each tick is 11.90ns\r
+// Assume we want to set each tick to 100ns.\r
+// Increase register = (100 * 2^31) / (10^9) = 214.71 =~ 215 = 0xD7\r
+// Addend register = 2^32 * tick_freq / (84MHz), where tick_freq = (2^31 / 215) MHz\r
+// From above equation, addend register = 2^63 / (84M * 215) ~= 510707200 = 0x1E70C600\r
+\r
+\r
+\r
+static void mdio_write(uint8_t addr, uint8_t reg, uint16_t val)\r
+{\r
+\r
+    EMAC->MIIMDAT = val;\r
+    EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_WRITE_Msk | EMAC_MIIMCTL_MDCON_Msk;\r
+\r
+    while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);\r
+\r
+}\r
+\r
+\r
+static uint16_t mdio_read(uint8_t addr, uint8_t reg)\r
+{\r
+    EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk;\r
+    while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);\r
+\r
+    return(EMAC->MIIMDAT);\r
+}\r
+\r
+static int reset_phy(void)\r
+{\r
+\r
+    uint16_t reg;\r
+    uint32_t delayCnt;\r
+\r
+\r
+    mdio_write(CONFIG_PHY_ADDR, MII_BMCR, BMCR_RESET);\r
+\r
+    delayCnt = 2000;\r
+    while(delayCnt-- > 0) {\r
+        if((mdio_read(CONFIG_PHY_ADDR, MII_BMCR) & BMCR_RESET) == 0)\r
+            break;\r
+\r
+    }\r
+\r
+    if(delayCnt == 0) {\r
+        NU_DEBUGF(("Reset phy failed\n"));\r
+        return(-1);\r
+    }\r
+\r
+    mdio_write(CONFIG_PHY_ADDR, MII_ADVERTISE, ADVERTISE_CSMA |\r
+               ADVERTISE_10HALF |\r
+               ADVERTISE_10FULL |\r
+               ADVERTISE_100HALF |\r
+               ADVERTISE_100FULL);\r
+\r
+    reg = mdio_read(CONFIG_PHY_ADDR, MII_BMCR);\r
+    mdio_write(CONFIG_PHY_ADDR, MII_BMCR, reg | BMCR_ANRESTART);\r
+\r
+    delayCnt = 200000;\r
+    while(delayCnt-- > 0) {\r
+        if((mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS))\r
+                == (BMSR_ANEGCOMPLETE | BMSR_LSTATUS))\r
+            break;\r
+    }\r
+\r
+    if(delayCnt == 0) {\r
+        NU_DEBUGF(("AN failed. Set to 100 FULL\n"));\r
+        EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);\r
+        return(-1);\r
+    } else {\r
+        reg = mdio_read(CONFIG_PHY_ADDR, MII_LPA);\r
+\r
+        if(reg & ADVERTISE_100FULL) {\r
+            NU_DEBUGF(("100 full\n"));\r
+            EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);\r
+        } else if(reg & ADVERTISE_100HALF) {\r
+            NU_DEBUGF(("100 half\n"));\r
+            EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_FUDUP_Msk) | EMAC_CTL_OPMODE_Msk;\r
+        } else if(reg & ADVERTISE_10FULL) {\r
+            NU_DEBUGF(("10 full\n"));\r
+            EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_OPMODE_Msk) | EMAC_CTL_FUDUP_Msk;\r
+        } else {\r
+            NU_DEBUGF(("10 half\n"));\r
+            EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);\r
+        }\r
+    }\r
+       FreeRTOS_printf(("PHY ID 1:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID1)));\r
+       FreeRTOS_printf(("PHY ID 2:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID2)));\r
+\r
+    return(0);\r
+}\r
+\r
+\r
+static void init_tx_desc(void)\r
+{\r
+    uint32_t i;\r
+\r
+\r
+    cur_tx_desc_ptr = fin_tx_desc_ptr = &tx_desc[0];\r
+\r
+    for(i = 0; i < TX_DESCRIPTOR_NUM; i++) {\r
+        tx_desc[i].status1 = TXFD_PADEN | TXFD_CRCAPP | TXFD_INTEN;\r
+        tx_desc[i].buf = &tx_buf[i][0];\r
+        tx_desc[i].status2 = 0;\r
+        tx_desc[i].next = &tx_desc[(i + 1) % TX_DESCRIPTOR_NUM];\r
+\r
+    }\r
+    EMAC->TXDSA = (unsigned int)&tx_desc[0];\r
+    return;\r
+}\r
+\r
+static void init_rx_desc(void)\r
+{\r
+    uint32_t i;\r
+\r
+\r
+    cur_rx_desc_ptr = &rx_desc[0];\r
+\r
+    for(i = 0; i < RX_DESCRIPTOR_NUM; i++) {\r
+        rx_desc[i].status1 = OWNERSHIP_EMAC;\r
+        rx_desc[i].buf = &rx_buf[i][0];\r
+        rx_desc[i].status2 = 0;\r
+        rx_desc[i].next = &rx_desc[(i + 1) % TX_DESCRIPTOR_NUM];\r
+    }\r
+    EMAC->RXDSA = (unsigned int)&rx_desc[0];\r
+    return;\r
+}\r
+\r
+void numaker_set_mac_addr(uint8_t *addr)\r
+{\r
+\r
+    EMAC->CAM0M = (addr[0] << 24) |\r
+                  (addr[1] << 16) |\r
+                  (addr[2] << 8) |\r
+                  addr[3];\r
+\r
+    EMAC->CAM0L = (addr[4] << 24) |\r
+                  (addr[5] << 16);\r
+\r
+\r
+}\r
+\r
+static void __eth_clk_pin_init()\r
+{\r
+    /* Unlock protected registers */\r
+    SYS_UnlockReg();\r
+\r
+    /* Enable IP clock */\r
+    CLK_EnableModuleClock(EMAC_MODULE);\r
+    \r
+    // Configure MDC clock rate to HCLK / (127 + 1) = 1.25 MHz if system is running at 160 MH\r
+    CLK_SetModuleClock(EMAC_MODULE, 0, CLK_CLKDIV3_EMAC(127));\r
+    \r
+    /* Update System Core Clock */\r
+    SystemCoreClockUpdate();\r
+    \r
+    /*---------------------------------------------------------------------------------------------------------*/\r
+    /* Init I/O Multi-function                                                                                 */\r
+    /*---------------------------------------------------------------------------------------------------------*/\r
+    // Configure RMII pins\r
+    SYS->GPA_MFPL &= ~(SYS_GPA_MFPL_PA6MFP_Msk | SYS_GPA_MFPL_PA7MFP_Msk);\r
+    SYS->GPA_MFPL |= SYS_GPA_MFPL_PA6MFP_EMAC_RMII_RXERR | SYS_GPA_MFPL_PA7MFP_EMAC_RMII_CRSDV;\r
+    SYS->GPC_MFPL &= ~(SYS_GPC_MFPL_PC6MFP_Msk | SYS_GPC_MFPL_PC7MFP_Msk);\r
+    SYS->GPC_MFPL |= SYS_GPC_MFPL_PC6MFP_EMAC_RMII_RXD1 | SYS_GPC_MFPL_PC7MFP_EMAC_RMII_RXD0;\r
+    SYS->GPC_MFPH &= ~SYS_GPC_MFPH_PC8MFP_Msk;\r
+    SYS->GPC_MFPH |= SYS_GPC_MFPH_PC8MFP_EMAC_RMII_REFCLK;\r
+    SYS->GPE_MFPH &= ~(SYS_GPE_MFPH_PE8MFP_Msk | SYS_GPE_MFPH_PE9MFP_Msk | SYS_GPE_MFPH_PE10MFP_Msk |\r
+                       SYS_GPE_MFPH_PE11MFP_Msk | SYS_GPE_MFPH_PE12MFP_Msk);\r
+    SYS->GPE_MFPH |= SYS_GPE_MFPH_PE8MFP_EMAC_RMII_MDC |\r
+                    SYS_GPE_MFPH_PE9MFP_EMAC_RMII_MDIO |\r
+                    SYS_GPE_MFPH_PE10MFP_EMAC_RMII_TXD0 |\r
+                    SYS_GPE_MFPH_PE11MFP_EMAC_RMII_TXD1 |\r
+                    SYS_GPE_MFPH_PE12MFP_EMAC_RMII_TXEN;\r
+\r
+    // Enable high slew rate on all RMII TX output pins\r
+    PE->SLEWCTL = (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN10_Pos) |\r
+                  (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN11_Pos) |\r
+                  (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN12_Pos);\r
+\r
+\r
+    /* Lock protected registers */\r
+    SYS_LockReg();\r
+\r
+\r
+}\r
+\r
+int numaker_eth_init(uint8_t *mac_addr)\r
+{\r
+    int ret = 0;\r
+    // init CLK & pins\r
+    __eth_clk_pin_init();\r
+  \r
+    // Reset MAC\r
+    EMAC->CTL = EMAC_CTL_RST_Msk;\r
+    while(EMAC->CTL & EMAC_CTL_RST_Msk) {}\r
+\r
+    init_tx_desc();\r
+    init_rx_desc();\r
+\r
+    numaker_set_mac_addr(mac_addr);  // need to reconfigure hardware address 'cos we just RESET emc...\r
+\r
+\r
+    /* Configure the MAC interrupt enable register. */\r
+    EMAC->INTEN = EMAC_INTEN_RXIEN_Msk |\r
+                  EMAC_INTEN_TXIEN_Msk |\r
+                  EMAC_INTEN_RXGDIEN_Msk |\r
+                  EMAC_INTEN_TXCPIEN_Msk |\r
+                  EMAC_INTEN_RXBEIEN_Msk |\r
+                  EMAC_INTEN_TXBEIEN_Msk |\r
+                  EMAC_INTEN_RDUIEN_Msk |\r
+                  EMAC_INTEN_TSALMIEN_Msk |\r
+                  EMAC_INTEN_WOLIEN_Msk;\r
+\r
+    /* Configure the MAC control register. */\r
+    EMAC->CTL = EMAC_CTL_STRIPCRC_Msk | EMAC_CTL_RMIIEN_Msk;\r
+\r
+    /* Accept packets for us and all broadcast and multicast packets */\r
+    EMAC->CAMCTL =  EMAC_CAMCTL_CMPEN_Msk |\r
+                    EMAC_CAMCTL_AMP_Msk |\r
+                    EMAC_CAMCTL_ABP_Msk;\r
+    EMAC->CAMEN = 1;    // Enable CAM entry 0    \r
+\r
+    ret= reset_phy();                    \r
+                    \r
+    EMAC_ENABLE_RX();\r
+    EMAC_ENABLE_TX();\r
+    return ret;\r
+}\r
+\r
+\r
+\r
+void  ETH_halt(void)\r
+{\r
+\r
+    EMAC->CTL &= ~(EMAC_CTL_RXON_Msk | EMAC_CTL_TXON_Msk);\r
+}\r
+\r
+unsigned int m_status;\r
+\r
+void EMAC_RX_IRQHandler(void)\r
+{\r
+//    NU_DEBUGF(("%s ... \r\n", __FUNCTION__));\r
+    m_status = EMAC->INTSTS & 0xFFFF;\r
+    EMAC->INTSTS = m_status;\r
+    if (m_status & EMAC_INTSTS_RXBEIF_Msk) {\r
+        // Shouldn't goes here, unless descriptor corrupted\r
+               NU_DEBUGF(("RX descriptor corrupted \r\n"));\r
+               //return;\r
+    }\r
+    // FIX ME: for rx-event, to ack rx_isr into event queue\r
+        xNetworkCallback('R');\r
+}\r
+\r
+\r
+void numaker_eth_trigger_rx(void)\r
+{\r
+    ETH_TRIGGER_RX();\r
+}\r
+\r
+int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf)\r
+{\r
+    unsigned int cur_entry, status;\r
+\r
+    cur_entry = EMAC->CRXDSA;\r
+    if ((cur_entry == (uint32_t)cur_rx_desc_ptr) && (!(m_status & EMAC_INTSTS_RDUIF_Msk)))  // cur_entry may equal to cur_rx_desc_ptr if RDU occures\r
+            return -1;\r
+    status = cur_rx_desc_ptr->status1;\r
+\r
+    if(status & OWNERSHIP_EMAC)\r
+            return -1;\r
+\r
+    if (status & RXFD_RXGD) {\r
+        *buf = cur_rx_desc_ptr->buf;\r
+        *len = status & 0xFFFF;\r
+    }\r
+    return 0;\r
+}    \r
+\r
+void numaker_eth_rx_next(void)\r
+{\r
+    cur_rx_desc_ptr->status1 = OWNERSHIP_EMAC;\r
+    cur_rx_desc_ptr = cur_rx_desc_ptr->next;    \r
+}    \r
+\r
+void EMAC_TX_IRQHandler(void)\r
+{\r
+    unsigned int cur_entry, status;\r
+\r
+    status = EMAC->INTSTS & 0xFFFF0000;\r
+    EMAC->INTSTS = status;\r
+    if(status & EMAC_INTSTS_TXBEIF_Msk) {\r
+        // Shouldn't goes here, unless descriptor corrupted\r
+        return;\r
+    }\r
+\r
+    cur_entry = EMAC->CTXDSA;\r
+\r
+    while (cur_entry != (uint32_t)fin_tx_desc_ptr) {\r
+\r
+        fin_tx_desc_ptr = fin_tx_desc_ptr->next;\r
+    }\r
+    // FIX ME: for tx-event, no-op at this stage\r
+    xNetworkCallback('T');\r
+}\r
+\r
+uint8_t *numaker_eth_get_tx_buf(void)\r
+{\r
+    if(cur_tx_desc_ptr->status1 & OWNERSHIP_EMAC)\r
+        return(NULL);\r
+    else\r
+        return(cur_tx_desc_ptr->buf);\r
+}\r
+\r
+void numaker_eth_trigger_tx(uint16_t length, void *p)\r
+{\r
+    struct eth_descriptor volatile *desc;\r
+    cur_tx_desc_ptr->status2 = (unsigned int)length;\r
+    desc = cur_tx_desc_ptr->next;    // in case TX is transmitting and overwrite next pointer before we can update cur_tx_desc_ptr\r
+    cur_tx_desc_ptr->status1 |= OWNERSHIP_EMAC;\r
+    cur_tx_desc_ptr = desc;\r
+\r
+    ETH_TRIGGER_TX();\r
+\r
+}\r
+\r
+int numaker_eth_link_ok(void)\r
+{\r
+    /* first, a dummy read to latch */\r
+    mdio_read(CONFIG_PHY_ADDR, MII_BMSR);\r
+    if(mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & BMSR_LSTATUS)\r
+      return 1;\r
+    return 0;  \r
+}\r
+\r
+//void numaker_eth_set_cb(eth_callback_t eth_cb, void *userData)\r
+//{\r
+//    nu_eth_txrx_cb =  eth_cb;\r
+//    nu_userData = userData;\r
+//}\r
+\r
+// Provide ethernet devices with a semi-unique MAC address\r
+void numaker_mac_address(uint8_t *mac)\r
+{\r
+    uint32_t uID1;\r
+    // Fetch word 0\r
+    uint32_t word0 = *(uint32_t *)0x7F804; // 2KB Data Flash at 0x7F800\r
+    // Fetch word 1\r
+    // we only want bottom 16 bits of word1 (MAC bits 32-47)\r
+    // and bit 9 forced to 1, bit 8 forced to 0\r
+    // Locally administered MAC, reduced conflicts\r
+    // http://en.wikipedia.org/wiki/MAC_address\r
+    uint32_t word1 = *(uint32_t *)0x7F800; // 2KB Data Flash at 0x7F800\r
+\r
+    if( word0 == 0xFFFFFFFF )          // Not burn any mac address at 1st 2 words of Data Flash\r
+    {\r
+        // with a semi-unique MAC address from the UUID\r
+        /* Enable FMC ISP function */\r
+        SYS_UnlockReg();\r
+        FMC_Open();\r
+        // = FMC_ReadUID(0);\r
+        uID1 = FMC_ReadUID(1);\r
+        word1 = (uID1 & 0x003FFFFF) | ((uID1 & 0x030000) << 6) >> 8;\r
+        word0 = ((FMC_ReadUID(0) >> 4) << 20) | ((uID1 & 0xFF)<<12) | (FMC_ReadUID(2) & 0xFFF);\r
+        /* Disable FMC ISP function */\r
+        FMC_Close();\r
+        /* Lock protected registers */\r
+        SYS_LockReg();\r
+    }\r
+\r
+    word1 |= 0x00000200;\r
+    word1 &= 0x0000FEFF;\r
+\r
+    mac[0] = (word1 & 0x0000ff00) >> 8;    \r
+    mac[1] = (word1 & 0x000000ff);\r
+    mac[2] = (word0 & 0xff000000) >> 24;\r
+    mac[3] = (word0 & 0x00ff0000) >> 16;\r
+    mac[4] = (word0 & 0x0000ff00) >> 8;\r
+    mac[5] = (word0 & 0x000000ff);\r
+    \r
+    NU_DEBUGF(("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", mac[0], mac[1],mac[2],mac[3],mac[4],mac[5]));\r
+}\r
+\r
+void numaker_eth_enable_interrupts(void) {\r
+  EMAC->INTEN |= EMAC_INTEN_RXIEN_Msk |\r
+                   EMAC_INTEN_TXIEN_Msk ;\r
+  NVIC_EnableIRQ(EMAC_RX_IRQn);\r
+  NVIC_EnableIRQ(EMAC_TX_IRQn);\r
+}\r
+\r
+void numaker_eth_disable_interrupts(void) {\r
+  NVIC_DisableIRQ(EMAC_RX_IRQn);\r
+  NVIC_DisableIRQ(EMAC_TX_IRQn);\r
+}\r
index 3d370bca7f8b38531f04522768ec56b68068beb3..4e4d98d6d673ca50e83406ef5f304636524e49ae 100644 (file)
-/**************************************************************************//**
- * @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *   1. Redistributions of source code must retain the above copyright notice,
- *      this list of conditions and the following disclaimer.
- *   2. Redistributions in binary form must reproduce the above copyright notice,
- *      this list of conditions and the following disclaimer in the documentation
- *      and/or other materials provided with the distribution.
- *   3. Neither the name of Nuvoton Technology Corp. nor the names of its contributors
- *      may be used to endorse or promote products derived from this software
- *      without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*****************************************************************************/
-#include "M480.h"
-#ifndef  _M480_ETH_
-#define  _M480_ETH_
-
-/* Generic MII registers. */
-
-#define MII_BMCR            0x00        /* Basic mode control register */
-#define MII_BMSR            0x01        /* Basic mode status register  */
-#define MII_PHYSID1         0x02        /* PHYS ID 1                   */
-#define MII_PHYSID2         0x03        /* PHYS ID 2                   */
-#define MII_ADVERTISE       0x04        /* Advertisement control reg   */
-#define MII_LPA             0x05        /* Link partner ability reg    */
-#define MII_EXPANSION       0x06        /* Expansion register          */
-#define MII_DCOUNTER        0x12        /* Disconnect counter          */
-#define MII_FCSCOUNTER      0x13        /* False carrier counter       */
-#define MII_NWAYTEST        0x14        /* N-way auto-neg test reg     */
-#define MII_RERRCOUNTER     0x15        /* Receive error counter       */
-#define MII_SREVISION       0x16        /* Silicon revision            */
-#define MII_RESV1           0x17        /* Reserved...                 */
-#define MII_LBRERROR        0x18        /* Lpback, rx, bypass error    */
-#define MII_PHYADDR         0x19        /* PHY address                 */
-#define MII_RESV2           0x1a        /* Reserved...                 */
-#define MII_TPISTATUS       0x1b        /* TPI status for 10mbps       */
-#define MII_NCONFIG         0x1c        /* Network interface config    */
-
-/* Basic mode control register. */
-#define BMCR_RESV               0x007f  /* Unused...                   */
-#define BMCR_CTST               0x0080  /* Collision test              */
-#define BMCR_FULLDPLX           0x0100  /* Full duplex                 */
-#define BMCR_ANRESTART          0x0200  /* Auto negotiation restart    */
-#define BMCR_ISOLATE            0x0400  /* Disconnect DP83840 from MII */
-#define BMCR_PDOWN              0x0800  /* Powerdown the DP83840       */
-#define BMCR_ANENABLE           0x1000  /* Enable auto negotiation     */
-#define BMCR_SPEED100           0x2000  /* Select 100Mbps              */
-#define BMCR_LOOPBACK           0x4000  /* TXD loopback bits           */
-#define BMCR_RESET              0x8000  /* Reset the DP83840           */
-
-/* Basic mode status register. */
-#define BMSR_ERCAP              0x0001  /* Ext-reg capability          */
-#define BMSR_JCD                0x0002  /* Jabber detected             */
-#define BMSR_LSTATUS            0x0004  /* Link status                 */
-#define BMSR_ANEGCAPABLE        0x0008  /* Able to do auto-negotiation */
-#define BMSR_RFAULT             0x0010  /* Remote fault detected       */
-#define BMSR_ANEGCOMPLETE       0x0020  /* Auto-negotiation complete   */
-#define BMSR_RESV               0x07c0  /* Unused...                   */
-#define BMSR_10HALF             0x0800  /* Can do 10mbps, half-duplex  */
-#define BMSR_10FULL             0x1000  /* Can do 10mbps, full-duplex  */
-#define BMSR_100HALF            0x2000  /* Can do 100mbps, half-duplex */
-#define BMSR_100FULL            0x4000  /* Can do 100mbps, full-duplex */
-#define BMSR_100BASE4           0x8000  /* Can do 100mbps, 4k packets  */
-
-/* Advertisement control register. */
-#define ADVERTISE_SLCT          0x001f  /* Selector bits               */
-#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_100BASE4      0x0200  /* Try for 100mbps 4k packets  */
-#define ADVERTISE_RESV          0x1c00  /* Unused...                   */
-#define ADVERTISE_RFAULT        0x2000  /* Say we can detect faults    */
-#define ADVERTISE_LPACK         0x4000  /* Ack link partners response  */
-#define ADVERTISE_NPAGE         0x8000  /* Next page bit               */
-
-#define RX_DESCRIPTOR_NUM       4 //8    // Max Number of Rx Frame Descriptors
-#define TX_DESCRIPTOR_NUM       2 //4    // Max number of Tx Frame Descriptors
-
-#define PACKET_BUFFER_SIZE      1520
-
-#define CONFIG_PHY_ADDR     1
-
-
-// Frame Descriptor's Owner bit
-#define OWNERSHIP_EMAC 0x80000000  // 1 = EMAC
-//#define OWNERSHIP_CPU 0x7fffffff  // 0 = CPU
-
-
-
-// Rx Frame Descriptor Status
-#define RXFD_RXGD    0x00100000  // Receiving Good Packet Received
-#define RXFD_RTSAS   0x00800000  // RX Time Stamp Available 
-
-
-// Tx Frame Descriptor's Control bits
-#define TXFD_TTSEN    0x08    // Tx Time Stamp Enable
-#define TXFD_INTEN    0x04    // Interrupt Enable
-#define TXFD_CRCAPP   0x02    // Append CRC
-#define TXFD_PADEN    0x01    // Padding Enable
-
-// Tx Frame Descriptor Status
-#define TXFD_TXCP    0x00080000  // Transmission Completion
-#define TXFD_TTSAS   0x08000000  // TX Time Stamp Available
-
-// Tx/Rx buffer descriptor structure
-struct eth_descriptor;
-struct eth_descriptor {
-    uint32_t  status1;
-    uint8_t *buf;
-    uint32_t  status2;
-    struct eth_descriptor *next;
-#ifdef TIME_STAMPING
-    uint32_t backup1;
-    uint32_t backup2;
-    uint32_t reserved1;
-    uint32_t reserved2;
-#endif
-};
-
-#ifdef TIME_STAMPING
-
-#define ETH_TS_ENABLE() do{EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;}while(0)
-#define ETH_TS_START() do{EMAC->TSCTL |= (EMAC_TSCTL_TSMODE_Msk | EMAC_TSCTL_TSIEN_Msk);}while(0)
-s32_t ETH_settime(u32_t sec, u32_t nsec);
-s32_t ETH_gettime(u32_t *sec, u32_t *nsec);
-s32_t ETH_updatetime(u32_t neg, u32_t sec, u32_t nsec);
-s32_t ETH_adjtimex(int ppm);
-void ETH_setinc(void);
-
-#endif
-
-#ifdef NU_TRACE
-#define NU_DEBUGF(x) { printf x; }
-#else
-#define NU_DEBUGF(x)
-#endif
-
-void numaker_set_mac_addr(uint8_t *addr);
-int numaker_eth_init(uint8_t *mac_addr);
-uint8_t *numaker_eth_get_tx_buf(void);
-void numaker_eth_trigger_tx(uint16_t length, void *p);
-int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf);
-void numaker_eth_rx_next(void);
-void numaker_eth_trigger_rx(void);
-int numaker_eth_link_ok(void);
-void numaker_mac_address(uint8_t *mac);
-void numaker_eth_enable_interrupts(void);
-void numaker_eth_disable_interrupts(void);
-
-#endif  /* _M480_ETH_ */
+/**************************************************************************//**\r
+ * @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.\r
+ * \r
+ * Redistribution and use in source and binary forms, with or without modification,\r
+ * are permitted provided that the following conditions are met:\r
+ *   1. Redistributions of source code must retain the above copyright notice,\r
+ *      this list of conditions and the following disclaimer.\r
+ *   2. Redistributions in binary form must reproduce the above copyright notice,\r
+ *      this list of conditions and the following disclaimer in the documentation\r
+ *      and/or other materials provided with the distribution.\r
+ *   3. Neither the name of Nuvoton Technology Corp. nor the names of its contributors\r
+ *      may be used to endorse or promote products derived from this software\r
+ *      without specific prior written permission.\r
+ * \r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\r
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\r
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\r
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+*****************************************************************************/\r
+#include "M480.h"\r
+#ifndef  _M480_ETH_\r
+#define  _M480_ETH_\r
+\r
+/* Generic MII registers. */\r
+\r
+#define MII_BMCR            0x00        /* Basic mode control register */\r
+#define MII_BMSR            0x01        /* Basic mode status register  */\r
+#define MII_PHYSID1         0x02        /* PHYS ID 1                   */\r
+#define MII_PHYSID2         0x03        /* PHYS ID 2                   */\r
+#define MII_ADVERTISE       0x04        /* Advertisement control reg   */\r
+#define MII_LPA             0x05        /* Link partner ability reg    */\r
+#define MII_EXPANSION       0x06        /* Expansion register          */\r
+#define MII_DCOUNTER        0x12        /* Disconnect counter          */\r
+#define MII_FCSCOUNTER      0x13        /* False carrier counter       */\r
+#define MII_NWAYTEST        0x14        /* N-way auto-neg test reg     */\r
+#define MII_RERRCOUNTER     0x15        /* Receive error counter       */\r
+#define MII_SREVISION       0x16        /* Silicon revision            */\r
+#define MII_RESV1           0x17        /* Reserved...                 */\r
+#define MII_LBRERROR        0x18        /* Lpback, rx, bypass error    */\r
+#define MII_PHYADDR         0x19        /* PHY address                 */\r
+#define MII_RESV2           0x1a        /* Reserved...                 */\r
+#define MII_TPISTATUS       0x1b        /* TPI status for 10mbps       */\r
+#define MII_NCONFIG         0x1c        /* Network interface config    */\r
+\r
+/* Basic mode control register. */\r
+#define BMCR_RESV               0x007f  /* Unused...                   */\r
+#define BMCR_CTST               0x0080  /* Collision test              */\r
+#define BMCR_FULLDPLX           0x0100  /* Full duplex                 */\r
+#define BMCR_ANRESTART          0x0200  /* Auto negotiation restart    */\r
+#define BMCR_ISOLATE            0x0400  /* Disconnect DP83840 from MII */\r
+#define BMCR_PDOWN              0x0800  /* Powerdown the DP83840       */\r
+#define BMCR_ANENABLE           0x1000  /* Enable auto negotiation     */\r
+#define BMCR_SPEED100           0x2000  /* Select 100Mbps              */\r
+#define BMCR_LOOPBACK           0x4000  /* TXD loopback bits           */\r
+#define BMCR_RESET              0x8000  /* Reset the DP83840           */\r
+\r
+/* Basic mode status register. */\r
+#define BMSR_ERCAP              0x0001  /* Ext-reg capability          */\r
+#define BMSR_JCD                0x0002  /* Jabber detected             */\r
+#define BMSR_LSTATUS            0x0004  /* Link status                 */\r
+#define BMSR_ANEGCAPABLE        0x0008  /* Able to do auto-negotiation */\r
+#define BMSR_RFAULT             0x0010  /* Remote fault detected       */\r
+#define BMSR_ANEGCOMPLETE       0x0020  /* Auto-negotiation complete   */\r
+#define BMSR_RESV               0x07c0  /* Unused...                   */\r
+#define BMSR_10HALF             0x0800  /* Can do 10mbps, half-duplex  */\r
+#define BMSR_10FULL             0x1000  /* Can do 10mbps, full-duplex  */\r
+#define BMSR_100HALF            0x2000  /* Can do 100mbps, half-duplex */\r
+#define BMSR_100FULL            0x4000  /* Can do 100mbps, full-duplex */\r
+#define BMSR_100BASE4           0x8000  /* Can do 100mbps, 4k packets  */\r
+\r
+/* Advertisement control register. */\r
+#define ADVERTISE_SLCT          0x001f  /* Selector bits               */\r
+#define ADVERTISE_CSMA          0x0001  /* Only selector supported     */\r
+#define ADVERTISE_10HALF        0x0020  /* Try for 10mbps half-duplex  */\r
+#define ADVERTISE_10FULL        0x0040  /* Try for 10mbps full-duplex  */\r
+#define ADVERTISE_100HALF       0x0080  /* Try for 100mbps half-duplex */\r
+#define ADVERTISE_100FULL       0x0100  /* Try for 100mbps full-duplex */\r
+#define ADVERTISE_100BASE4      0x0200  /* Try for 100mbps 4k packets  */\r
+#define ADVERTISE_RESV          0x1c00  /* Unused...                   */\r
+#define ADVERTISE_RFAULT        0x2000  /* Say we can detect faults    */\r
+#define ADVERTISE_LPACK         0x4000  /* Ack link partners response  */\r
+#define ADVERTISE_NPAGE         0x8000  /* Next page bit               */\r
+\r
+#define RX_DESCRIPTOR_NUM       4 //8    // Max Number of Rx Frame Descriptors\r
+#define TX_DESCRIPTOR_NUM       2 //4    // Max number of Tx Frame Descriptors\r
+\r
+#define PACKET_BUFFER_SIZE      1520\r
+\r
+#define CONFIG_PHY_ADDR     1\r
+\r
+\r
+// Frame Descriptor's Owner bit\r
+#define OWNERSHIP_EMAC 0x80000000  // 1 = EMAC\r
+//#define OWNERSHIP_CPU 0x7fffffff  // 0 = CPU\r
+\r
+\r
+\r
+// Rx Frame Descriptor Status\r
+#define RXFD_RXGD    0x00100000  // Receiving Good Packet Received\r
+#define RXFD_RTSAS   0x00800000  // RX Time Stamp Available \r
+\r
+\r
+// Tx Frame Descriptor's Control bits\r
+#define TXFD_TTSEN    0x08    // Tx Time Stamp Enable\r
+#define TXFD_INTEN    0x04    // Interrupt Enable\r
+#define TXFD_CRCAPP   0x02    // Append CRC\r
+#define TXFD_PADEN    0x01    // Padding Enable\r
+\r
+// Tx Frame Descriptor Status\r
+#define TXFD_TXCP    0x00080000  // Transmission Completion\r
+#define TXFD_TTSAS   0x08000000  // TX Time Stamp Available\r
+\r
+// Tx/Rx buffer descriptor structure\r
+struct eth_descriptor;\r
+struct eth_descriptor {\r
+    uint32_t  status1;\r
+    uint8_t *buf;\r
+    uint32_t  status2;\r
+    struct eth_descriptor *next;\r
+#ifdef TIME_STAMPING\r
+    uint32_t backup1;\r
+    uint32_t backup2;\r
+    uint32_t reserved1;\r
+    uint32_t reserved2;\r
+#endif\r
+};\r
+\r
+#ifdef TIME_STAMPING\r
+\r
+#define ETH_TS_ENABLE() do{EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;}while(0)\r
+#define ETH_TS_START() do{EMAC->TSCTL |= (EMAC_TSCTL_TSMODE_Msk | EMAC_TSCTL_TSIEN_Msk);}while(0)\r
+s32_t ETH_settime(u32_t sec, u32_t nsec);\r
+s32_t ETH_gettime(u32_t *sec, u32_t *nsec);\r
+s32_t ETH_updatetime(u32_t neg, u32_t sec, u32_t nsec);\r
+s32_t ETH_adjtimex(int ppm);\r
+void ETH_setinc(void);\r
+\r
+#endif\r
+\r
+#ifdef NU_TRACE\r
+#define NU_DEBUGF(x) { printf x; }\r
+#else\r
+#define NU_DEBUGF(x)\r
+#endif\r
+\r
+void numaker_set_mac_addr(uint8_t *addr);\r
+int numaker_eth_init(uint8_t *mac_addr);\r
+uint8_t *numaker_eth_get_tx_buf(void);\r
+void numaker_eth_trigger_tx(uint16_t length, void *p);\r
+int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf);\r
+void numaker_eth_rx_next(void);\r
+void numaker_eth_trigger_rx(void);\r
+int numaker_eth_link_ok(void);\r
+void numaker_mac_address(uint8_t *mac);\r
+void numaker_eth_enable_interrupts(void);\r
+void numaker_eth_disable_interrupts(void);\r
+\r
+#endif  /* _M480_ETH_ */\r
index 139979cce5a5e64f610be7af6f81d5bb9180e00e..ebcbfbec99c0ebda19cecd6a948cabea81daa600 100644 (file)
-/***********************************************************************************************************************
-* DISCLAIMER
-* This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products. No
-* other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all
-* applicable laws, including copyright laws.
-* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
-* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. TO THE MAXIMUM
-* EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES
-* SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS
-* SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-* Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability of
-* this software. By using this software, you agree to the additional terms and conditions found by accessing the
-* following link:
-* http://www.renesas.com/disclaimer
-*
-* Copyright (C) 2018 Renesas Electronics Corporation. All rights reserved.
-***********************************************************************************************************************/
-
-/***********************************************************************************************************************
-* File Name    : NetworkInterface.c
-* Device(s)    : RX
-* Description  : Interfaces FreeRTOS TCP/IP stack to RX Ethernet driver.
-***********************************************************************************************************************/
-
-/***********************************************************************************************************************
-* History : DD.MM.YYYY Version  Description
-*         : 07.03.2018 0.1     Development
-***********************************************************************************************************************/
-
-/***********************************************************************************************************************
-*  Includes   <System Includes> , "Project Includes"
-***********************************************************************************************************************/
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "task.h"
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_IP_Private.h"
-/*#include "FreeRTOS_DNS.h" */
-#include "NetworkBufferManagement.h"
-#include "NetworkInterface.h"
-
-#include "r_ether_rx_if.h"
-#include "r_pinset.h"
-
-/***********************************************************************************************************************
- * Macro definitions
- **********************************************************************************************************************/
-#define ETHER_BUFSIZE_MIN    60
-
-#if defined( BSP_MCU_RX65N ) || defined( BSP_MCU_RX64M ) || defined( BSP_MCU_RX71M )
-    #if ETHER_CFG_MODE_SEL == 0
-        #define R_ETHER_PinSet_CHANNEL_0()    R_ETHER_PinSet_ETHERC0_MII()
-    #elif ETHER_CFG_MODE_SEL == 1
-        #define R_ETHER_PinSet_CHANNEL_0()    R_ETHER_PinSet_ETHERC0_RMII()
-    #endif
-#elif defined( BSP_MCU_RX63N )
-    #if ETHER_CFG_MODE_SEL == 0
-        #define R_ETHER_PinSet_CHANNEL_0()    R_ETHER_PinSet_ETHERC_MII()
-    #elif ETHER_CFG_MODE_SEL == 1
-        #define R_ETHER_PinSet_CHANNEL_0()    R_ETHER_PinSet_ETHERC_RMII()
-    #endif
-#endif /* if defined( BSP_MCU_RX65N ) || defined( BSP_MCU_RX64M ) || defined( BSP_MCU_RX71M ) */
-
-#ifndef PHY_LS_HIGH_CHECK_TIME_MS
-
-/* Check if the LinkSStatus in the PHY is still high after 2 seconds of not
- * receiving packets. */
-    #define PHY_LS_HIGH_CHECK_TIME_MS    2000
-#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
-
-/***********************************************************************************************************************
- * Private global variables and functions
- **********************************************************************************************************************/
-typedef enum
-{
-    eMACInit,   /* Must initialise MAC. */
-    eMACPass,   /* Initialisation was successful. */
-    eMACFailed, /* Initialisation failed. */
-} eMAC_INIT_STATUS_TYPE;
-
-static TaskHandle_t ether_receive_check_task_handle = 0;
-static TaskHandle_t ether_link_check_task_handle = 0;
-static TaskHandle_t xTaskToNotify = NULL;
-static BaseType_t xPHYLinkStatus;
-static BaseType_t xReportedStatus;
-static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit;
-
-static int16_t SendData( uint8_t * pucBuffer,
-                         size_t length );
-static int InitializeNetwork( void );
-static void prvEMACDeferredInterruptHandlerTask( void * pvParameters );
-static void clear_all_ether_rx_discriptors( uint32_t event );
-
-int32_t callback_ether_regist( void );
-void EINT_Trig_isr( void * );
-void get_random_number( uint8_t * data,
-                        uint32_t len );
-
-void prvLinkStatusChange( BaseType_t xStatus );
-#if ( ipconfigHAS_PRINTF != 0 )
-    static void prvMonitorResources( void );
-#endif
-
-/***********************************************************************************************************************
- * Function Name: xNetworkInterfaceInitialise ()
- * Description  : Initialization of Ethernet driver.
- * Arguments    : none
- * Return Value : pdPASS, pdFAIL
- **********************************************************************************************************************/
-BaseType_t xNetworkInterfaceInitialise( void )
-{
-    BaseType_t xReturn;
-
-    if( xMacInitStatus == eMACInit )
-    {
-        /*
-         * Perform the hardware specific network initialization here using the Ethernet driver library to initialize the
-         * Ethernet hardware, initialize DMA descriptors, and perform a PHY auto-negotiation to obtain a network link.
-         *
-         * InitialiseNetwork() uses Ethernet peripheral driver library function, and returns 0 if the initialization fails.
-         */
-        if( InitializeNetwork() == pdFALSE )
-        {
-            xMacInitStatus = eMACFailed;
-        }
-        else
-        {
-            /* Indicate that the MAC initialisation succeeded. */
-            xMacInitStatus = eMACPass;
-        }
-
-        FreeRTOS_printf( ( "InitializeNetwork returns %s\n", ( xMacInitStatus == eMACPass ) ? "OK" : " Fail" ) );
-    }
-
-    if( xMacInitStatus == eMACPass )
-    {
-        xReturn = xPHYLinkStatus;
-    }
-    else
-    {
-        xReturn = pdFAIL;
-    }
-
-    FreeRTOS_printf( ( "xNetworkInterfaceInitialise returns %d\n", xReturn ) );
-
-    return xReturn;
-} /* End of function xNetworkInterfaceInitialise() */
-
-
-/***********************************************************************************************************************
- * Function Name: xNetworkInterfaceOutput ()
- * Description  : Simple network output interface.
- * Arguments    : pxDescriptor, xReleaseAfterSend
- * Return Value : pdTRUE, pdFALSE
- **********************************************************************************************************************/
-BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,
-                                    BaseType_t xReleaseAfterSend )
-{
-    BaseType_t xReturn = pdFALSE;
-
-    /* Simple network interfaces (as opposed to more efficient zero copy network
-     * interfaces) just use Ethernet peripheral driver library functions to copy
-     * data from the FreeRTOS+TCP buffer into the peripheral driver's own buffer.
-     * This example assumes SendData() is a peripheral driver library function that
-     * takes a pointer to the start of the data to be sent and the length of the
-     * data to be sent as two separate parameters.  The start of the data is located
-     * by pxDescriptor->pucEthernetBuffer.  The length of the data is located
-     * by pxDescriptor->xDataLength. */
-    if( xPHYLinkStatus != 0 )
-    {
-        if( SendData( pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength ) >= 0 )
-        {
-            xReturn = pdTRUE;
-            /* Call the standard trace macro to log the send event. */
-            iptraceNETWORK_INTERFACE_TRANSMIT();
-        }
-    }
-    else
-    {
-        /* As the PHY Link Status is low, it makes no sense trying to deliver a packet. */
-    }
-
-    if( xReleaseAfterSend != pdFALSE )
-    {
-        /* It is assumed SendData() copies the data out of the FreeRTOS+TCP Ethernet
-         * buffer.  The Ethernet buffer is therefore no longer needed, and must be
-         * freed for re-use. */
-        vReleaseNetworkBufferAndDescriptor( pxDescriptor );
-    }
-
-    return xReturn;
-} /* End of function xNetworkInterfaceOutput() */
-
-
-#if ( ipconfigHAS_PRINTF != 0 )
-    static void prvMonitorResources()
-    {
-        static UBaseType_t uxLastMinBufferCount = 0u;
-        static UBaseType_t uxCurrentBufferCount = 0u;
-        static size_t uxMinLastSize = 0uL;
-        static size_t uxCurLastSize = 0uL;
-        size_t uxMinSize;
-        size_t uxCurSize;
-
-        uxCurrentBufferCount = uxGetMinimumFreeNetworkBuffers();
-
-        if( uxLastMinBufferCount != uxCurrentBufferCount )
-        {
-            /* The logging produced below may be helpful
-             * while tuning +TCP: see how many buffers are in use. */
-            uxLastMinBufferCount = uxCurrentBufferCount;
-            FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
-                               uxGetNumberOfFreeNetworkBuffers(), uxCurrentBufferCount ) );
-        }
-
-        uxMinSize = xPortGetMinimumEverFreeHeapSize();
-        uxCurSize = xPortGetFreeHeapSize();
-
-        if( uxMinLastSize != uxMinSize )
-        {
-            uxCurLastSize = uxCurSize;
-            uxMinLastSize = uxMinSize;
-            FreeRTOS_printf( ( "Heap: current %lu lowest %lu\n", uxCurSize, uxMinSize ) );
-        }
-
-        #if ( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
-            {
-                static UBaseType_t uxLastMinQueueSpace = 0;
-                UBaseType_t uxCurrentCount = 0u;
-
-                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 */
-    }
-#endif /* ( ipconfigHAS_PRINTF != 0 ) */
-
-/***********************************************************************************************************************
- * Function Name: prvEMACDeferredInterruptHandlerTask ()
- * Description  : The deferred interrupt handler is a standard RTOS task.
- * Arguments    : pvParameters
- * Return Value : none
- **********************************************************************************************************************/
-static void prvEMACDeferredInterruptHandlerTask( void * pvParameters )
-{
-    NetworkBufferDescriptor_t * pxBufferDescriptor;
-    int32_t xBytesReceived = 0;
-
-    /* Avoid compiler warning about unreferenced parameter. */
-    ( void ) pvParameters;
-
-    /* Used to indicate that xSendEventStructToIPTask() is being called because
-     * of an Ethernet receive event. */
-    IPStackEvent_t xRxEvent;
-
-    uint8_t * buffer_pointer;
-
-    /* Some variables related to monitoring the PHY. */
-    TimeOut_t xPhyTime;
-    TickType_t xPhyRemTime;
-    const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
-
-    vTaskSetTimeOutState( &xPhyTime );
-    xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
-
-    FreeRTOS_printf( ( "Deferred Interrupt Handler Task started\n" ) );
-    xTaskToNotify = ether_receive_check_task_handle;
-
-    for( ; ; )
-    {
-        #if ( ipconfigHAS_PRINTF != 0 )
-            {
-                prvMonitorResources();
-            }
-        #endif /* ipconfigHAS_PRINTF != 0 ) */
-
-        /* Wait for the Ethernet MAC interrupt to indicate that another packet
-         * has been received.  */
-        if( xBytesReceived <= 0 )
-        {
-            ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );
-        }
-
-        /* See how much data was received.  */
-        xBytesReceived = R_ETHER_Read_ZC2( ETHER_CHANNEL_0, ( void ** ) &buffer_pointer );
-
-        if( xBytesReceived < 0 )
-        {
-            /* This is an error. Logged. */
-            FreeRTOS_printf( ( "R_ETHER_Read_ZC2: rc = %d\n", xBytesReceived ) );
-        }
-        else if( xBytesReceived > 0 )
-        {
-            /* Allocate a network buffer descriptor that points to a buffer
-             * large enough to hold the received frame.  As this is the simple
-             * rather than efficient example the received data will just be copied
-             * into this buffer. */
-            pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( ( size_t ) xBytesReceived, 0 );
-
-            if( pxBufferDescriptor != NULL )
-            {
-                /* pxBufferDescriptor->pucEthernetBuffer now points to an Ethernet
-                 * buffer large enough to hold the received data.  Copy the
-                 * received data into pcNetworkBuffer->pucEthernetBuffer.  Here it
-                 * is assumed ReceiveData() is a peripheral driver function that
-                 * copies the received data into a buffer passed in as the function's
-                 * parameter.  Remember! While is is a simple robust technique -
-                 * it is not efficient.  An example that uses a zero copy technique
-                 * is provided further down this page. */
-                memcpy( pxBufferDescriptor->pucEthernetBuffer, buffer_pointer, ( size_t ) xBytesReceived );
-                /*ReceiveData( pxBufferDescriptor->pucEthernetBuffer ); */
-
-                /* Set the actual packet length, in case a larger buffer was returned. */
-                pxBufferDescriptor->xDataLength = ( size_t ) xBytesReceived;
-
-                R_ETHER_Read_ZC2_BufRelease( ETHER_CHANNEL_0 );
-
-                /* See if the data contained in the received Ethernet frame needs
-                * to be processed.  NOTE! It is preferable to do this in
-                * the interrupt service routine itself, which would remove the need
-                * to unblock this task for packets that don't need processing. */
-                if( eConsiderFrameForProcessing( pxBufferDescriptor->pucEthernetBuffer ) == eProcessBuffer )
-                {
-                    /* The event about to be sent to the TCP/IP is an Rx event. */
-                    xRxEvent.eEventType = eNetworkRxEvent;
-
-                    /* pvData is used to point to the network buffer descriptor that
-                     * now references the received data. */
-                    xRxEvent.pvData = ( void * ) pxBufferDescriptor;
-
-                    /* Send the data to the TCP/IP stack. */
-                    if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )
-                    {
-                        /* The buffer could not be sent to the IP task so the buffer must be released. */
-                        vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );
-
-                        /* Make a call to the standard trace macro to log the occurrence. */
-                        iptraceETHERNET_RX_EVENT_LOST();
-                        clear_all_ether_rx_discriptors( 0 );
-                    }
-                    else
-                    {
-                        /* The message was successfully sent to the TCP/IP stack.
-                        * Call the standard trace macro to log the occurrence. */
-                        iptraceNETWORK_INTERFACE_RECEIVE();
-                        R_NOP();
-                    }
-                }
-                else
-                {
-                    /* The Ethernet frame can be dropped, but the Ethernet buffer must be released. */
-                    vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );
-                }
-            }
-            else
-            {
-                /* The event was lost because a network buffer was not available.
-                 * Call the standard trace macro to log the occurrence. */
-                iptraceETHERNET_RX_EVENT_LOST();
-                clear_all_ether_rx_discriptors( 1 );
-                FreeRTOS_printf( ( "R_ETHER_Read_ZC2: Cleared descriptors\n" ) );
-            }
-        }
-
-        if( xBytesReceived > 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 );
-
-            /* Indicate that the Link Status is high, so that
-             * xNetworkInterfaceOutput() can send packets. */
-            if( xPHYLinkStatus == 0 )
-            {
-                xPHYLinkStatus = 1;
-                FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS assume %d\n", xPHYLinkStatus ) );
-            }
-        }
-        else if( ( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE ) || ( FreeRTOS_IsNetworkUp() == pdFALSE ) )
-        {
-            R_ETHER_LinkProcess( 0 );
-
-            if( xPHYLinkStatus != xReportedStatus )
-            {
-                xPHYLinkStatus = xReportedStatus;
-                FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", xPHYLinkStatus ) );
-            }
-
-            vTaskSetTimeOutState( &xPhyTime );
-
-            if( xPHYLinkStatus != 0 )
-            {
-                xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
-            }
-            else
-            {
-                xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
-            }
-        }
-    }
-} /* End of function prvEMACDeferredInterruptHandlerTask() */
-
-
-/***********************************************************************************************************************
- * Function Name: vNetworkInterfaceAllocateRAMToBuffers ()
- * Description  : .
- * Arguments    : pxNetworkBuffers
- * Return Value : none
- **********************************************************************************************************************/
-void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
-{
-    uint32_t ul;
-    uint8_t * buffer_address;
-
-    R_EXTERN_SEC( B_ETHERNET_BUFFERS_1 )
-
-    buffer_address = R_SECTOP( B_ETHERNET_BUFFERS_1 );
-
-    for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )
-    {
-        pxNetworkBuffers[ ul ].pucEthernetBuffer = ( buffer_address + ( ETHER_CFG_BUFSIZE * ul ) );
-    }
-} /* End of function vNetworkInterfaceAllocateRAMToBuffers() */
-
-
-/***********************************************************************************************************************
- * Function Name: prvLinkStatusChange ()
- * Description  : Function will be called when the Link Status of the phy has changed ( see ether_callback.c )
- * Arguments    : xStatus : true when statyus has become high
- * Return Value : void
- **********************************************************************************************************************/
-void prvLinkStatusChange( BaseType_t xStatus )
-{
-    if( xReportedStatus != xStatus )
-    {
-        FreeRTOS_printf( ( "prvLinkStatusChange( %d )\n", xStatus ) );
-        xReportedStatus = xStatus;
-    }
-}
-
-/***********************************************************************************************************************
- * Function Name: InitializeNetwork ()
- * Description  :
- * Arguments    : none
- * Return Value : pdTRUE, pdFALSE
- **********************************************************************************************************************/
-static int InitializeNetwork( void )
-{
-    ether_return_t eth_ret;
-    BaseType_t return_code = pdFALSE;
-    ether_param_t param;
-    uint8_t myethaddr[ 6 ] =
-    {
-        configMAC_ADDR0,
-        configMAC_ADDR1,
-        configMAC_ADDR2,
-        configMAC_ADDR3,
-        configMAC_ADDR4,
-        configMAC_ADDR5
-    }; /*XXX Fix me */
-
-    R_ETHER_PinSet_CHANNEL_0();
-    R_ETHER_Initial();
-    callback_ether_regist();
-
-    param.channel = ETHER_CHANNEL_0;
-    eth_ret = R_ETHER_Control( CONTROL_POWER_ON, param ); /* PHY mode settings, module stop cancellation */
-
-    if( ETHER_SUCCESS != eth_ret )
-    {
-        return pdFALSE;
-    }
-
-    eth_ret = R_ETHER_Open_ZC2( ETHER_CHANNEL_0, myethaddr, ETHER_FLAG_OFF );
-
-    if( ETHER_SUCCESS != eth_ret )
-    {
-        return pdFALSE;
-    }
-
-    return_code = xTaskCreate( prvEMACDeferredInterruptHandlerTask,
-                               "ETHER_RECEIVE_CHECK_TASK",
-                               512u,
-                               0,
-                               configMAX_PRIORITIES - 1,
-                               &ether_receive_check_task_handle );
-
-    if( pdFALSE == return_code )
-    {
-        return pdFALSE;
-    }
-
-    return pdTRUE;
-} /* End of function InitializeNetwork() */
-
-
-/***********************************************************************************************************************
- * Function Name: SendData ()
- * Description  :
- * Arguments    : pucBuffer, length
- * Return Value : 0 success, negative fail
- **********************************************************************************************************************/
-static int16_t SendData( uint8_t * pucBuffer,
-                         size_t length ) /*TODO complete stub function */
-{
-    ether_return_t ret;
-    uint8_t * pwrite_buffer;
-    uint16_t write_buf_size;
-
-    /* (1) Retrieve the transmit buffer location controlled by the  descriptor. */
-    ret = R_ETHER_Write_ZC2_GetBuf( ETHER_CHANNEL_0, ( void ** ) &pwrite_buffer, &write_buf_size );
-
-    if( ETHER_SUCCESS == ret )
-    {
-        if( write_buf_size >= length )
-        {
-            memcpy( pwrite_buffer, pucBuffer, length );
-        }
-
-        if( length < ETHER_BUFSIZE_MIN )                                             /*under minimum*/
-        {
-            memset( ( pwrite_buffer + length ), 0, ( ETHER_BUFSIZE_MIN - length ) ); /*padding*/
-            length = ETHER_BUFSIZE_MIN;                                              /*resize*/
-        }
-
-        ret = R_ETHER_Write_ZC2_SetBuf( ETHER_CHANNEL_0, ( uint16_t ) length );
-        ret = R_ETHER_CheckWrite( ETHER_CHANNEL_0 );
-    }
-
-    if( ETHER_SUCCESS != ret )
-    {
-        return -5; /* XXX return meaningful value */
-    }
-    else
-    {
-        return 0;
-    }
-} /* End of function SendData() */
-
-
-/***********************************************************************************************************************
-* Function Name: EINT_Trig_isr
-* Description  : Standard frame received interrupt handler
-* Arguments    : ectrl - EDMAC and ETHERC control structure
-* Return Value : None
-* Note         : This callback function is executed when EINT0 interrupt occurred.
-***********************************************************************************************************************/
-void EINT_Trig_isr( void * ectrl )
-{
-    ether_cb_arg_t * pdecode;
-    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-
-    pdecode = ( ether_cb_arg_t * ) ectrl;
-
-    if( pdecode->status_eesr & 0x00040000 ) /* EDMAC FR (Frame Receive Event) interrupt */
-    {
-        if( xTaskToNotify != NULL )
-        {
-            vTaskNotifyGiveFromISR( ether_receive_check_task_handle, &xHigherPriorityTaskWoken );
-        }
-
-        /* If xHigherPriorityTaskWoken is now set to pdTRUE then a context switch
-         * should be performed to ensure the interrupt returns directly to the highest
-         * priority task.  The macro used for this purpose is dependent on the port in
-         * use and may be called portEND_SWITCHING_ISR(). */
-        portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
-        /*TODO complete interrupt handler for other events. */
-    }
-} /* End of function EINT_Trig_isr() */
-
-
-static void clear_all_ether_rx_discriptors( uint32_t event )
-{
-    int32_t xBytesReceived;
-    uint8_t * buffer_pointer;
-
-    /* Avoid compiler warning about unreferenced parameter. */
-    ( void ) event;
-
-    while( 1 )
-    {
-        /* See how much data was received.  */
-        xBytesReceived = R_ETHER_Read_ZC2( ETHER_CHANNEL_0, ( void ** ) &buffer_pointer );
-
-        if( 0 > xBytesReceived )
-        {
-            /* This is an error. Ignored. */
-        }
-        else if( 0 < xBytesReceived )
-        {
-            R_ETHER_Read_ZC2_BufRelease( ETHER_CHANNEL_0 );
-            iptraceETHERNET_RX_EVENT_LOST();
-        }
-        else
-        {
-            break;
-        }
-    }
-}
-
-/***********************************************************************************************************************
- * End of file "NetworkInterface.c"
- **********************************************************************************************************************/
+/***********************************************************************************************************************\r
+* DISCLAIMER\r
+* This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products. No\r
+* other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all\r
+* applicable laws, including copyright laws.\r
+* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING\r
+* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY,\r
+* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. TO THE MAXIMUM\r
+* EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES\r
+* SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS\r
+* SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\r
+* Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability of\r
+* this software. By using this software, you agree to the additional terms and conditions found by accessing the\r
+* following link:\r
+* http://www.renesas.com/disclaimer\r
+*\r
+* Copyright (C) 2018 Renesas Electronics Corporation. All rights reserved.\r
+***********************************************************************************************************************/\r
+\r
+/***********************************************************************************************************************\r
+* File Name    : NetworkInterface.c\r
+* Device(s)    : RX\r
+* Description  : Interfaces FreeRTOS TCP/IP stack to RX Ethernet driver.\r
+***********************************************************************************************************************/\r
+\r
+/***********************************************************************************************************************\r
+* History : DD.MM.YYYY Version  Description\r
+*         : 07.03.2018 0.1     Development\r
+***********************************************************************************************************************/\r
+\r
+/***********************************************************************************************************************\r
+*  Includes   <System Includes> , "Project Includes"\r
+***********************************************************************************************************************/\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+/*#include "FreeRTOS_DNS.h" */\r
+#include "NetworkBufferManagement.h"\r
+#include "NetworkInterface.h"\r
+\r
+#include "r_ether_rx_if.h"\r
+#include "r_pinset.h"\r
+\r
+/***********************************************************************************************************************\r
+ * Macro definitions\r
+ **********************************************************************************************************************/\r
+#define ETHER_BUFSIZE_MIN    60\r
+\r
+#if defined( BSP_MCU_RX65N ) || defined( BSP_MCU_RX64M ) || defined( BSP_MCU_RX71M )\r
+    #if ETHER_CFG_MODE_SEL == 0\r
+        #define R_ETHER_PinSet_CHANNEL_0()    R_ETHER_PinSet_ETHERC0_MII()\r
+    #elif ETHER_CFG_MODE_SEL == 1\r
+        #define R_ETHER_PinSet_CHANNEL_0()    R_ETHER_PinSet_ETHERC0_RMII()\r
+    #endif\r
+#elif defined( BSP_MCU_RX63N )\r
+    #if ETHER_CFG_MODE_SEL == 0\r
+        #define R_ETHER_PinSet_CHANNEL_0()    R_ETHER_PinSet_ETHERC_MII()\r
+    #elif ETHER_CFG_MODE_SEL == 1\r
+        #define R_ETHER_PinSet_CHANNEL_0()    R_ETHER_PinSet_ETHERC_RMII()\r
+    #endif\r
+#endif /* if defined( BSP_MCU_RX65N ) || defined( BSP_MCU_RX64M ) || defined( BSP_MCU_RX71M ) */\r
+\r
+#ifndef PHY_LS_HIGH_CHECK_TIME_MS\r
+\r
+/* Check if the LinkSStatus in the PHY is still high after 2 seconds of not\r
+ * receiving packets. */\r
+    #define PHY_LS_HIGH_CHECK_TIME_MS    2000\r
+#endif\r
+\r
+#ifndef PHY_LS_LOW_CHECK_TIME_MS\r
+    /* Check if the LinkSStatus in the PHY is still low every second. */\r
+    #define PHY_LS_LOW_CHECK_TIME_MS    1000\r
+#endif\r
+\r
+/***********************************************************************************************************************\r
+ * Private global variables and functions\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 TaskHandle_t ether_receive_check_task_handle = 0;\r
+static TaskHandle_t ether_link_check_task_handle = 0;\r
+static TaskHandle_t xTaskToNotify = NULL;\r
+static BaseType_t xPHYLinkStatus;\r
+static BaseType_t xReportedStatus;\r
+static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit;\r
+\r
+static int16_t SendData( uint8_t * pucBuffer,\r
+                         size_t length );\r
+static int InitializeNetwork( void );\r
+static void prvEMACDeferredInterruptHandlerTask( void * pvParameters );\r
+static void clear_all_ether_rx_discriptors( uint32_t event );\r
+\r
+int32_t callback_ether_regist( void );\r
+void EINT_Trig_isr( void * );\r
+void get_random_number( uint8_t * data,\r
+                        uint32_t len );\r
+\r
+void prvLinkStatusChange( BaseType_t xStatus );\r
+#if ( ipconfigHAS_PRINTF != 0 )\r
+    static void prvMonitorResources( void );\r
+#endif\r
+\r
+/***********************************************************************************************************************\r
+ * Function Name: xNetworkInterfaceInitialise ()\r
+ * Description  : Initialization of Ethernet driver.\r
+ * Arguments    : none\r
+ * Return Value : pdPASS, pdFAIL\r
+ **********************************************************************************************************************/\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+    BaseType_t xReturn;\r
+\r
+    if( xMacInitStatus == eMACInit )\r
+    {\r
+        /*\r
+         * Perform the hardware specific network initialization here using the Ethernet driver library to initialize the\r
+         * Ethernet hardware, initialize DMA descriptors, and perform a PHY auto-negotiation to obtain a network link.\r
+         *\r
+         * InitialiseNetwork() uses Ethernet peripheral driver library function, and returns 0 if the initialization fails.\r
+         */\r
+        if( InitializeNetwork() == pdFALSE )\r
+        {\r
+            xMacInitStatus = eMACFailed;\r
+        }\r
+        else\r
+        {\r
+            /* Indicate that the MAC initialisation succeeded. */\r
+            xMacInitStatus = eMACPass;\r
+        }\r
+\r
+        FreeRTOS_printf( ( "InitializeNetwork returns %s\n", ( xMacInitStatus == eMACPass ) ? "OK" : " Fail" ) );\r
+    }\r
+\r
+    if( xMacInitStatus == eMACPass )\r
+    {\r
+        xReturn = xPHYLinkStatus;\r
+    }\r
+    else\r
+    {\r
+        xReturn = pdFAIL;\r
+    }\r
+\r
+    FreeRTOS_printf( ( "xNetworkInterfaceInitialise returns %d\n", xReturn ) );\r
+\r
+    return xReturn;\r
+} /* End of function xNetworkInterfaceInitialise() */\r
+\r
+\r
+/***********************************************************************************************************************\r
+ * Function Name: xNetworkInterfaceOutput ()\r
+ * Description  : Simple network output interface.\r
+ * Arguments    : pxDescriptor, xReleaseAfterSend\r
+ * Return Value : pdTRUE, pdFALSE\r
+ **********************************************************************************************************************/\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,\r
+                                    BaseType_t xReleaseAfterSend )\r
+{\r
+    BaseType_t xReturn = pdFALSE;\r
+\r
+    /* Simple network interfaces (as opposed to more efficient zero copy network\r
+     * interfaces) just use Ethernet peripheral driver library functions to copy\r
+     * data from the FreeRTOS+TCP buffer into the peripheral driver's own buffer.\r
+     * This example assumes SendData() is a peripheral driver library function that\r
+     * takes a pointer to the start of the data to be sent and the length of the\r
+     * data to be sent as two separate parameters.  The start of the data is located\r
+     * by pxDescriptor->pucEthernetBuffer.  The length of the data is located\r
+     * by pxDescriptor->xDataLength. */\r
+    if( xPHYLinkStatus != 0 )\r
+    {\r
+        if( SendData( pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength ) >= 0 )\r
+        {\r
+            xReturn = pdTRUE;\r
+            /* Call the standard trace macro to log the send event. */\r
+            iptraceNETWORK_INTERFACE_TRANSMIT();\r
+        }\r
+    }\r
+    else\r
+    {\r
+        /* As the PHY Link Status is low, it makes no sense trying to deliver a packet. */\r
+    }\r
+\r
+    if( xReleaseAfterSend != pdFALSE )\r
+    {\r
+        /* It is assumed SendData() copies the data out of the FreeRTOS+TCP Ethernet\r
+         * buffer.  The Ethernet buffer is therefore no longer needed, and must be\r
+         * freed for re-use. */\r
+        vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
+    }\r
+\r
+    return xReturn;\r
+} /* End of function xNetworkInterfaceOutput() */\r
+\r
+\r
+#if ( ipconfigHAS_PRINTF != 0 )\r
+    static void prvMonitorResources()\r
+    {\r
+        static UBaseType_t uxLastMinBufferCount = 0u;\r
+        static UBaseType_t uxCurrentBufferCount = 0u;\r
+        static size_t uxMinLastSize = 0uL;\r
+        static size_t uxCurLastSize = 0uL;\r
+        size_t uxMinSize;\r
+        size_t uxCurSize;\r
+\r
+        uxCurrentBufferCount = uxGetMinimumFreeNetworkBuffers();\r
+\r
+        if( uxLastMinBufferCount != uxCurrentBufferCount )\r
+        {\r
+            /* The logging produced below may be helpful\r
+             * while tuning +TCP: see how many buffers are in use. */\r
+            uxLastMinBufferCount = uxCurrentBufferCount;\r
+            FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",\r
+                               uxGetNumberOfFreeNetworkBuffers(), uxCurrentBufferCount ) );\r
+        }\r
+\r
+        uxMinSize = xPortGetMinimumEverFreeHeapSize();\r
+        uxCurSize = xPortGetFreeHeapSize();\r
+\r
+        if( uxMinLastSize != uxMinSize )\r
+        {\r
+            uxCurLastSize = uxCurSize;\r
+            uxMinLastSize = uxMinSize;\r
+            FreeRTOS_printf( ( "Heap: current %lu lowest %lu\n", uxCurSize, uxMinSize ) );\r
+        }\r
+\r
+        #if ( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+            {\r
+                static UBaseType_t uxLastMinQueueSpace = 0;\r
+                UBaseType_t uxCurrentCount = 0u;\r
+\r
+                uxCurrentCount = uxGetMinimumIPQueueSpace();\r
+\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
+#endif /* ( ipconfigHAS_PRINTF != 0 ) */\r
+\r
+/***********************************************************************************************************************\r
+ * Function Name: prvEMACDeferredInterruptHandlerTask ()\r
+ * Description  : The deferred interrupt handler is a standard RTOS task.\r
+ * Arguments    : pvParameters\r
+ * Return Value : none\r
+ **********************************************************************************************************************/\r
+static void prvEMACDeferredInterruptHandlerTask( void * pvParameters )\r
+{\r
+    NetworkBufferDescriptor_t * pxBufferDescriptor;\r
+    int32_t xBytesReceived = 0;\r
+\r
+    /* Avoid compiler warning about unreferenced parameter. */\r
+    ( void ) pvParameters;\r
+\r
+    /* Used to indicate that xSendEventStructToIPTask() is being called because\r
+     * of an Ethernet receive event. */\r
+    IPStackEvent_t xRxEvent;\r
+\r
+    uint8_t * buffer_pointer;\r
+\r
+    /* Some variables related to monitoring the PHY. */\r
+    TimeOut_t xPhyTime;\r
+    TickType_t xPhyRemTime;\r
+    const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );\r
+\r
+    vTaskSetTimeOutState( &xPhyTime );\r
+    xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+\r
+    FreeRTOS_printf( ( "Deferred Interrupt Handler Task started\n" ) );\r
+    xTaskToNotify = ether_receive_check_task_handle;\r
+\r
+    for( ; ; )\r
+    {\r
+        #if ( ipconfigHAS_PRINTF != 0 )\r
+            {\r
+                prvMonitorResources();\r
+            }\r
+        #endif /* ipconfigHAS_PRINTF != 0 ) */\r
+\r
+        /* Wait for the Ethernet MAC interrupt to indicate that another packet\r
+         * has been received.  */\r
+        if( xBytesReceived <= 0 )\r
+        {\r
+            ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );\r
+        }\r
+\r
+        /* See how much data was received.  */\r
+        xBytesReceived = R_ETHER_Read_ZC2( ETHER_CHANNEL_0, ( void ** ) &buffer_pointer );\r
+\r
+        if( xBytesReceived < 0 )\r
+        {\r
+            /* This is an error. Logged. */\r
+            FreeRTOS_printf( ( "R_ETHER_Read_ZC2: rc = %d\n", xBytesReceived ) );\r
+        }\r
+        else if( xBytesReceived > 0 )\r
+        {\r
+            /* Allocate a network buffer descriptor that points to a buffer\r
+             * large enough to hold the received frame.  As this is the simple\r
+             * rather than efficient example the received data will just be copied\r
+             * into this buffer. */\r
+            pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( ( size_t ) xBytesReceived, 0 );\r
+\r
+            if( pxBufferDescriptor != NULL )\r
+            {\r
+                /* pxBufferDescriptor->pucEthernetBuffer now points to an Ethernet\r
+                 * buffer large enough to hold the received data.  Copy the\r
+                 * received data into pcNetworkBuffer->pucEthernetBuffer.  Here it\r
+                 * is assumed ReceiveData() is a peripheral driver function that\r
+                 * copies the received data into a buffer passed in as the function's\r
+                 * parameter.  Remember! While is is a simple robust technique -\r
+                 * it is not efficient.  An example that uses a zero copy technique\r
+                 * is provided further down this page. */\r
+                memcpy( pxBufferDescriptor->pucEthernetBuffer, buffer_pointer, ( size_t ) xBytesReceived );\r
+                /*ReceiveData( pxBufferDescriptor->pucEthernetBuffer ); */\r
+\r
+                /* Set the actual packet length, in case a larger buffer was returned. */\r
+                pxBufferDescriptor->xDataLength = ( size_t ) xBytesReceived;\r
+\r
+                R_ETHER_Read_ZC2_BufRelease( ETHER_CHANNEL_0 );\r
+\r
+                /* See if the data contained in the received Ethernet frame needs\r
+                * to be processed.  NOTE! It is preferable to do this in\r
+                * the interrupt service routine itself, which would remove the need\r
+                * to unblock this task for packets that don't need processing. */\r
+                if( eConsiderFrameForProcessing( pxBufferDescriptor->pucEthernetBuffer ) == eProcessBuffer )\r
+                {\r
+                    /* The event about to be sent to the TCP/IP is an Rx event. */\r
+                    xRxEvent.eEventType = eNetworkRxEvent;\r
+\r
+                    /* pvData is used to point to the network buffer descriptor that\r
+                     * now references the received data. */\r
+                    xRxEvent.pvData = ( void * ) pxBufferDescriptor;\r
+\r
+                    /* Send the data to the TCP/IP stack. */\r
+                    if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )\r
+                    {\r
+                        /* The buffer could not be sent to the IP task so the buffer must be released. */\r
+                        vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );\r
+\r
+                        /* Make a call to the standard trace macro to log the occurrence. */\r
+                        iptraceETHERNET_RX_EVENT_LOST();\r
+                        clear_all_ether_rx_discriptors( 0 );\r
+                    }\r
+                    else\r
+                    {\r
+                        /* The message was successfully sent to the TCP/IP stack.\r
+                        * Call the standard trace macro to log the occurrence. */\r
+                        iptraceNETWORK_INTERFACE_RECEIVE();\r
+                        R_NOP();\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    /* The Ethernet frame can be dropped, but the Ethernet buffer must be released. */\r
+                    vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );\r
+                }\r
+            }\r
+            else\r
+            {\r
+                /* The event was lost because a network buffer was not available.\r
+                 * Call the standard trace macro to log the occurrence. */\r
+                iptraceETHERNET_RX_EVENT_LOST();\r
+                clear_all_ether_rx_discriptors( 1 );\r
+                FreeRTOS_printf( ( "R_ETHER_Read_ZC2: Cleared descriptors\n" ) );\r
+            }\r
+        }\r
+\r
+        if( xBytesReceived > 0 )\r
+        {\r
+            /* A packet was received. No need to check for the PHY status now,\r
+             * but set a timer to check it later on. */\r
+            vTaskSetTimeOutState( &xPhyTime );\r
+            xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+\r
+            /* Indicate that the Link Status is high, so that\r
+             * xNetworkInterfaceOutput() can send packets. */\r
+            if( xPHYLinkStatus == 0 )\r
+            {\r
+                xPHYLinkStatus = 1;\r
+                FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS assume %d\n", xPHYLinkStatus ) );\r
+            }\r
+        }\r
+        else if( ( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE ) || ( FreeRTOS_IsNetworkUp() == pdFALSE ) )\r
+        {\r
+            R_ETHER_LinkProcess( 0 );\r
+\r
+            if( xPHYLinkStatus != xReportedStatus )\r
+            {\r
+                xPHYLinkStatus = xReportedStatus;\r
+                FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", xPHYLinkStatus ) );\r
+            }\r
+\r
+            vTaskSetTimeOutState( &xPhyTime );\r
+\r
+            if( xPHYLinkStatus != 0 )\r
+            {\r
+                xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+            }\r
+            else\r
+            {\r
+                xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+            }\r
+        }\r
+    }\r
+} /* End of function prvEMACDeferredInterruptHandlerTask() */\r
+\r
+\r
+/***********************************************************************************************************************\r
+ * Function Name: vNetworkInterfaceAllocateRAMToBuffers ()\r
+ * Description  : .\r
+ * Arguments    : pxNetworkBuffers\r
+ * Return Value : none\r
+ **********************************************************************************************************************/\r
+void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )\r
+{\r
+    uint32_t ul;\r
+    uint8_t * buffer_address;\r
+\r
+    R_EXTERN_SEC( B_ETHERNET_BUFFERS_1 )\r
+\r
+    buffer_address = R_SECTOP( B_ETHERNET_BUFFERS_1 );\r
+\r
+    for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )\r
+    {\r
+        pxNetworkBuffers[ ul ].pucEthernetBuffer = ( buffer_address + ( ETHER_CFG_BUFSIZE * ul ) );\r
+    }\r
+} /* End of function vNetworkInterfaceAllocateRAMToBuffers() */\r
+\r
+\r
+/***********************************************************************************************************************\r
+ * Function Name: prvLinkStatusChange ()\r
+ * Description  : Function will be called when the Link Status of the phy has changed ( see ether_callback.c )\r
+ * Arguments    : xStatus : true when statyus has become high\r
+ * Return Value : void\r
+ **********************************************************************************************************************/\r
+void prvLinkStatusChange( BaseType_t xStatus )\r
+{\r
+    if( xReportedStatus != xStatus )\r
+    {\r
+        FreeRTOS_printf( ( "prvLinkStatusChange( %d )\n", xStatus ) );\r
+        xReportedStatus = xStatus;\r
+    }\r
+}\r
+\r
+/***********************************************************************************************************************\r
+ * Function Name: InitializeNetwork ()\r
+ * Description  :\r
+ * Arguments    : none\r
+ * Return Value : pdTRUE, pdFALSE\r
+ **********************************************************************************************************************/\r
+static int InitializeNetwork( void )\r
+{\r
+    ether_return_t eth_ret;\r
+    BaseType_t return_code = pdFALSE;\r
+    ether_param_t param;\r
+    uint8_t myethaddr[ 6 ] =\r
+    {\r
+        configMAC_ADDR0,\r
+        configMAC_ADDR1,\r
+        configMAC_ADDR2,\r
+        configMAC_ADDR3,\r
+        configMAC_ADDR4,\r
+        configMAC_ADDR5\r
+    }; /*XXX Fix me */\r
+\r
+    R_ETHER_PinSet_CHANNEL_0();\r
+    R_ETHER_Initial();\r
+    callback_ether_regist();\r
+\r
+    param.channel = ETHER_CHANNEL_0;\r
+    eth_ret = R_ETHER_Control( CONTROL_POWER_ON, param ); /* PHY mode settings, module stop cancellation */\r
+\r
+    if( ETHER_SUCCESS != eth_ret )\r
+    {\r
+        return pdFALSE;\r
+    }\r
+\r
+    eth_ret = R_ETHER_Open_ZC2( ETHER_CHANNEL_0, myethaddr, ETHER_FLAG_OFF );\r
+\r
+    if( ETHER_SUCCESS != eth_ret )\r
+    {\r
+        return pdFALSE;\r
+    }\r
+\r
+    return_code = xTaskCreate( prvEMACDeferredInterruptHandlerTask,\r
+                               "ETHER_RECEIVE_CHECK_TASK",\r
+                               512u,\r
+                               0,\r
+                               configMAX_PRIORITIES - 1,\r
+                               &ether_receive_check_task_handle );\r
+\r
+    if( pdFALSE == return_code )\r
+    {\r
+        return pdFALSE;\r
+    }\r
+\r
+    return pdTRUE;\r
+} /* End of function InitializeNetwork() */\r
+\r
+\r
+/***********************************************************************************************************************\r
+ * Function Name: SendData ()\r
+ * Description  :\r
+ * Arguments    : pucBuffer, length\r
+ * Return Value : 0 success, negative fail\r
+ **********************************************************************************************************************/\r
+static int16_t SendData( uint8_t * pucBuffer,\r
+                         size_t length ) /*TODO complete stub function */\r
+{\r
+    ether_return_t ret;\r
+    uint8_t * pwrite_buffer;\r
+    uint16_t write_buf_size;\r
+\r
+    /* (1) Retrieve the transmit buffer location controlled by the  descriptor. */\r
+    ret = R_ETHER_Write_ZC2_GetBuf( ETHER_CHANNEL_0, ( void ** ) &pwrite_buffer, &write_buf_size );\r
+\r
+    if( ETHER_SUCCESS == ret )\r
+    {\r
+        if( write_buf_size >= length )\r
+        {\r
+            memcpy( pwrite_buffer, pucBuffer, length );\r
+        }\r
+\r
+        if( length < ETHER_BUFSIZE_MIN )                                             /*under minimum*/\r
+        {\r
+            memset( ( pwrite_buffer + length ), 0, ( ETHER_BUFSIZE_MIN - length ) ); /*padding*/\r
+            length = ETHER_BUFSIZE_MIN;                                              /*resize*/\r
+        }\r
+\r
+        ret = R_ETHER_Write_ZC2_SetBuf( ETHER_CHANNEL_0, ( uint16_t ) length );\r
+        ret = R_ETHER_CheckWrite( ETHER_CHANNEL_0 );\r
+    }\r
+\r
+    if( ETHER_SUCCESS != ret )\r
+    {\r
+        return -5; /* XXX return meaningful value */\r
+    }\r
+    else\r
+    {\r
+        return 0;\r
+    }\r
+} /* End of function SendData() */\r
+\r
+\r
+/***********************************************************************************************************************\r
+* Function Name: EINT_Trig_isr\r
+* Description  : Standard frame received interrupt handler\r
+* Arguments    : ectrl - EDMAC and ETHERC control structure\r
+* Return Value : None\r
+* Note         : This callback function is executed when EINT0 interrupt occurred.\r
+***********************************************************************************************************************/\r
+void EINT_Trig_isr( void * ectrl )\r
+{\r
+    ether_cb_arg_t * pdecode;\r
+    BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
+\r
+    pdecode = ( ether_cb_arg_t * ) ectrl;\r
+\r
+    if( pdecode->status_eesr & 0x00040000 ) /* EDMAC FR (Frame Receive Event) interrupt */\r
+    {\r
+        if( xTaskToNotify != NULL )\r
+        {\r
+            vTaskNotifyGiveFromISR( ether_receive_check_task_handle, &xHigherPriorityTaskWoken );\r
+        }\r
+\r
+        /* If xHigherPriorityTaskWoken is now set to pdTRUE then a context switch\r
+         * should be performed to ensure the interrupt returns directly to the highest\r
+         * priority task.  The macro used for this purpose is dependent on the port in\r
+         * use and may be called portEND_SWITCHING_ISR(). */\r
+        portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
+        /*TODO complete interrupt handler for other events. */\r
+    }\r
+} /* End of function EINT_Trig_isr() */\r
+\r
+\r
+static void clear_all_ether_rx_discriptors( uint32_t event )\r
+{\r
+    int32_t xBytesReceived;\r
+    uint8_t * buffer_pointer;\r
+\r
+    /* Avoid compiler warning about unreferenced parameter. */\r
+    ( void ) event;\r
+\r
+    while( 1 )\r
+    {\r
+        /* See how much data was received.  */\r
+        xBytesReceived = R_ETHER_Read_ZC2( ETHER_CHANNEL_0, ( void ** ) &buffer_pointer );\r
+\r
+        if( 0 > xBytesReceived )\r
+        {\r
+            /* This is an error. Ignored. */\r
+        }\r
+        else if( 0 < xBytesReceived )\r
+        {\r
+            R_ETHER_Read_ZC2_BufRelease( ETHER_CHANNEL_0 );\r
+            iptraceETHERNET_RX_EVENT_LOST();\r
+        }\r
+        else\r
+        {\r
+            break;\r
+        }\r
+    }\r
+}\r
+\r
+/***********************************************************************************************************************\r
+ * End of file "NetworkInterface.c"\r
+ **********************************************************************************************************************/\r
index 8cb38ce30dc101192b42dcda21f49983ca681376..c42d8a20b36f2f3ed064caa059f540b1ae4b6d97 100644 (file)
-/***********************************************************************************************************************
-* DISCLAIMER
-* This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products. No
-* other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all
-* applicable laws, including copyright laws.
-* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
-* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. TO THE MAXIMUM
-* EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES
-* SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS
-* SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-* Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability of
-* this software. By using this software, you agree to the additional terms and conditions found by accessing the
-* following link:
-* http://www.renesas.com/disclaimer
-*
-* Copyright (C) 2015 Renesas Electronics Corporation. All rights reserved.
-***********************************************************************************************************************/
-/***********************************************************************************************************************
-* File Name    : ether_callback.c
-* Version      : ----
-* Description  : This module solves all the world's problems
-***********************************************************************************************************************/
-/**********************************************************************************************************************
-* History : DD.MM.YYYY Version  Description
-*         : 05.01.2015 ----     Clean up source code.
-***********************************************************************************************************************/
-
-/***********************************************************************************************************************
-Includes   <System Includes> , "Project Includes"
-***********************************************************************************************************************/
-#include "r_ether_rx_if.h"
-
-/***********************************************************************************************************************
-Private global variables and functions
-***********************************************************************************************************************/
-int32_t callback_ether_regist(void);
-void callback_ether(void * pparam);
-static void callback_wakeon_lan(uint32_t channel);
-static void callback_link_on(uint32_t channel);
-static void callback_link_off(uint32_t channel);
-
-volatile uint8_t  pause_enable = ETHER_FLAG_OFF;
-volatile uint8_t  magic_packet_detect[ETHER_CHANNEL_MAX];
-volatile uint8_t  link_detect[ETHER_CHANNEL_MAX];
-
-void EINT_Trig_isr(void *);
-
-/*
- * When that Link Status changes, the following function will be called:
- */
-void prvLinkStatusChange( BaseType_t xStatus );
-
-/***********************************************************************************************************************
-* Function Name: callback_ether
-* Description  : Regist of callback function
-* Arguments    : -
-* Return Value : 0: success, -1:failed
-***********************************************************************************************************************/
-int32_t callback_ether_regist(void)
-{
-    ether_param_t   param;
-    ether_cb_t      cb_func;
-
-    int32_t         ret;
-
-    /* Set the callback function (LAN cable connect/disconnect event) */
-    cb_func.pcb_func     = &callback_ether;
-    param.ether_callback = cb_func;
-    ret = R_ETHER_Control(CONTROL_SET_CALLBACK, param);
-    if (ETHER_SUCCESS != ret)
-    {
-        return -1;
-    }
-
-    /* Set the callback function (Ether interrupt event) */
-    cb_func.pcb_int_hnd     = &EINT_Trig_isr;
-    param.ether_callback = cb_func;
-    ret = R_ETHER_Control(CONTROL_SET_INT_HANDLER, param);
-    if (ETHER_SUCCESS != ret)
-    {
-        return -1;
-    }
-    return 0;
-} /* End of function callback_ether_regist() */
-
-/***********************************************************************************************************************
-* Function Name: callback_ether
-* Description  : Sample of the callback function
-* Arguments    : pparam -
-*
-* Return Value : none
-***********************************************************************************************************************/
-void callback_ether(void * pparam)
-{
-    ether_cb_arg_t    * pdecode;
-    uint32_t            channel;
-
-    pdecode = (ether_cb_arg_t *)pparam;
-    channel = pdecode->channel;                             /* Get Ethernet channel number */
-
-    switch (pdecode->event_id)
-    {
-        /* Callback function that notifies user to have detected magic packet. */
-        case ETHER_CB_EVENT_ID_WAKEON_LAN:
-            callback_wakeon_lan(channel);
-            break;
-
-        /* Callback function that notifies user to have become Link up. */
-        case ETHER_CB_EVENT_ID_LINK_ON:
-            callback_link_on(channel);
-            break;
-
-        /* Callback function that notifies user to have become Link down. */
-        case ETHER_CB_EVENT_ID_LINK_OFF:
-            callback_link_off(channel);
-            break;
-
-        default:
-            break;
-    }
-} /* End of function callback_ether() */
-
-/***********************************************************************************************************************
-* Function Name: callback_wakeon_lan
-* Description  :
-* Arguments    : channel -
-*                    Ethernet channel number
-* Return Value : none
-***********************************************************************************************************************/
-static void callback_wakeon_lan(uint32_t channel)
-{
-    if (ETHER_CHANNEL_MAX > channel)
-    {
-        magic_packet_detect[channel] = 1;
-
-        /* Please add necessary processing when magic packet is detected.  */
-    }
-} /* End of function callback_wakeon_lan() */
-
-/***********************************************************************************************************************
-* Function Name: callback_link_on
-* Description  :
-* Arguments    : channel -
-*                    Ethernet channel number
-* Return Value : none
-***********************************************************************************************************************/
-static void callback_link_on(uint32_t channel)
-{
-    if (ETHER_CHANNEL_MAX > channel)
-    {
-        link_detect[channel] = ETHER_FLAG_ON_LINK_ON;
-
-        /* Please add necessary processing when becoming Link up. */
-               prvLinkStatusChange( 1 );
-    }
-} /* End of function callback_link_on() */
-
-/***********************************************************************************************************************
-* Function Name: callback_link_off
-* Description  :
-* Arguments    : channel -
-*                    Ethernet channel number
-* Return Value : none
-***********************************************************************************************************************/
-static void callback_link_off(uint32_t channel)
-{
-    if (ETHER_CHANNEL_MAX > channel)
-    {
-        link_detect[channel] = ETHER_FLAG_ON_LINK_OFF;
-
-        /* Please add necessary processing when becoming Link down. */
-               prvLinkStatusChange( 0 );
-    }
-} /* End of function ether_cb_link_off() */
-
-/* End of File */
+/***********************************************************************************************************************\r
+* DISCLAIMER\r
+* This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products. No\r
+* other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all\r
+* applicable laws, including copyright laws.\r
+* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING\r
+* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY,\r
+* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. TO THE MAXIMUM\r
+* EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES\r
+* SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS\r
+* SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\r
+* Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability of\r
+* this software. By using this software, you agree to the additional terms and conditions found by accessing the\r
+* following link:\r
+* http://www.renesas.com/disclaimer\r
+*\r
+* Copyright (C) 2015 Renesas Electronics Corporation. All rights reserved.\r
+***********************************************************************************************************************/\r
+/***********************************************************************************************************************\r
+* File Name    : ether_callback.c\r
+* Version      : ----\r
+* Description  : This module solves all the world's problems\r
+***********************************************************************************************************************/\r
+/**********************************************************************************************************************\r
+* History : DD.MM.YYYY Version  Description\r
+*         : 05.01.2015 ----     Clean up source code.\r
+***********************************************************************************************************************/\r
+\r
+/***********************************************************************************************************************\r
+Includes   <System Includes> , "Project Includes"\r
+***********************************************************************************************************************/\r
+#include "r_ether_rx_if.h"\r
+\r
+/***********************************************************************************************************************\r
+Private global variables and functions\r
+***********************************************************************************************************************/\r
+int32_t callback_ether_regist(void);\r
+void callback_ether(void * pparam);\r
+static void callback_wakeon_lan(uint32_t channel);\r
+static void callback_link_on(uint32_t channel);\r
+static void callback_link_off(uint32_t channel);\r
+\r
+volatile uint8_t  pause_enable = ETHER_FLAG_OFF;\r
+volatile uint8_t  magic_packet_detect[ETHER_CHANNEL_MAX];\r
+volatile uint8_t  link_detect[ETHER_CHANNEL_MAX];\r
+\r
+void EINT_Trig_isr(void *);\r
+\r
+/*\r
+ * When that Link Status changes, the following function will be called:\r
+ */\r
+void prvLinkStatusChange( BaseType_t xStatus );\r
+\r
+/***********************************************************************************************************************\r
+* Function Name: callback_ether\r
+* Description  : Regist of callback function\r
+* Arguments    : -\r
+* Return Value : 0: success, -1:failed\r
+***********************************************************************************************************************/\r
+int32_t callback_ether_regist(void)\r
+{\r
+    ether_param_t   param;\r
+    ether_cb_t      cb_func;\r
+\r
+    int32_t         ret;\r
+\r
+    /* Set the callback function (LAN cable connect/disconnect event) */\r
+    cb_func.pcb_func     = &callback_ether;\r
+    param.ether_callback = cb_func;\r
+    ret = R_ETHER_Control(CONTROL_SET_CALLBACK, param);\r
+    if (ETHER_SUCCESS != ret)\r
+    {\r
+        return -1;\r
+    }\r
+\r
+    /* Set the callback function (Ether interrupt event) */\r
+    cb_func.pcb_int_hnd     = &EINT_Trig_isr;\r
+    param.ether_callback = cb_func;\r
+    ret = R_ETHER_Control(CONTROL_SET_INT_HANDLER, param);\r
+    if (ETHER_SUCCESS != ret)\r
+    {\r
+        return -1;\r
+    }\r
+    return 0;\r
+} /* End of function callback_ether_regist() */\r
+\r
+/***********************************************************************************************************************\r
+* Function Name: callback_ether\r
+* Description  : Sample of the callback function\r
+* Arguments    : pparam -\r
+*\r
+* Return Value : none\r
+***********************************************************************************************************************/\r
+void callback_ether(void * pparam)\r
+{\r
+    ether_cb_arg_t    * pdecode;\r
+    uint32_t            channel;\r
+\r
+    pdecode = (ether_cb_arg_t *)pparam;\r
+    channel = pdecode->channel;                             /* Get Ethernet channel number */\r
+\r
+    switch (pdecode->event_id)\r
+    {\r
+        /* Callback function that notifies user to have detected magic packet. */\r
+        case ETHER_CB_EVENT_ID_WAKEON_LAN:\r
+            callback_wakeon_lan(channel);\r
+            break;\r
+\r
+        /* Callback function that notifies user to have become Link up. */\r
+        case ETHER_CB_EVENT_ID_LINK_ON:\r
+            callback_link_on(channel);\r
+            break;\r
+\r
+        /* Callback function that notifies user to have become Link down. */\r
+        case ETHER_CB_EVENT_ID_LINK_OFF:\r
+            callback_link_off(channel);\r
+            break;\r
+\r
+        default:\r
+            break;\r
+    }\r
+} /* End of function callback_ether() */\r
+\r
+/***********************************************************************************************************************\r
+* Function Name: callback_wakeon_lan\r
+* Description  :\r
+* Arguments    : channel -\r
+*                    Ethernet channel number\r
+* Return Value : none\r
+***********************************************************************************************************************/\r
+static void callback_wakeon_lan(uint32_t channel)\r
+{\r
+    if (ETHER_CHANNEL_MAX > channel)\r
+    {\r
+        magic_packet_detect[channel] = 1;\r
+\r
+        /* Please add necessary processing when magic packet is detected.  */\r
+    }\r
+} /* End of function callback_wakeon_lan() */\r
+\r
+/***********************************************************************************************************************\r
+* Function Name: callback_link_on\r
+* Description  :\r
+* Arguments    : channel -\r
+*                    Ethernet channel number\r
+* Return Value : none\r
+***********************************************************************************************************************/\r
+static void callback_link_on(uint32_t channel)\r
+{\r
+    if (ETHER_CHANNEL_MAX > channel)\r
+    {\r
+        link_detect[channel] = ETHER_FLAG_ON_LINK_ON;\r
+\r
+        /* Please add necessary processing when becoming Link up. */\r
+               prvLinkStatusChange( 1 );\r
+    }\r
+} /* End of function callback_link_on() */\r
+\r
+/***********************************************************************************************************************\r
+* Function Name: callback_link_off\r
+* Description  :\r
+* Arguments    : channel -\r
+*                    Ethernet channel number\r
+* Return Value : none\r
+***********************************************************************************************************************/\r
+static void callback_link_off(uint32_t channel)\r
+{\r
+    if (ETHER_CHANNEL_MAX > channel)\r
+    {\r
+        link_detect[channel] = ETHER_FLAG_ON_LINK_OFF;\r
+\r
+        /* Please add necessary processing when becoming Link down. */\r
+               prvLinkStatusChange( 0 );\r
+    }\r
+} /* End of function ether_cb_link_off() */\r
+\r
+/* End of File */\r
index adc603c52552f015c4db990eab7d1074876522dc..44d19f3a9a0b2b4fb899147b9633893df1ce6f0c 100644 (file)
-/*
-FreeRTOS+TCP V2.0.11
-Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
- http://aws.amazon.com/freertos
- http://www.FreeRTOS.org
-*/
-
-/* Standard includes. */
-#include <stdint.h>
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "task.h"
-#include "queue.h"
-#include "semphr.h"
-
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_UDP_IP.h"
-#include "FreeRTOS_Sockets.h"
-#include "NetworkBufferManagement.h"
-
-/* Hardware includes. */
-#include "hwEthernet.h"
-
-/* Demo includes. */
-#include "NetworkInterface.h"
-
-#if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 1
-       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
-#else
-       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
-#endif
-
-/* When a packet is ready to be sent, if it cannot be sent immediately then the
-task performing the transmit will block for niTX_BUFFER_FREE_WAIT
-milliseconds.  It will do this a maximum of niMAX_TX_ATTEMPTS before giving
-up. */
-#define niTX_BUFFER_FREE_WAIT  ( ( TickType_t ) 2UL / portTICK_PERIOD_MS )
-#define niMAX_TX_ATTEMPTS              ( 5 )
-
-/* The length of the queue used to send interrupt status words from the
-interrupt handler to the deferred handler task. */
-#define niINTERRUPT_QUEUE_LENGTH       ( 10 )
-
-/*-----------------------------------------------------------*/
-
-/*
- * A deferred interrupt handler task that processes
- */
-extern void vEMACHandlerTask( void *pvParameters );
-
-/*-----------------------------------------------------------*/
-
-/* The queue used to communicate Ethernet events with the IP task. */
-extern QueueHandle_t xNetworkEventQueue;
-
-/* The semaphore used to wake the deferred interrupt handler task when an Rx
-interrupt is received. */
-SemaphoreHandle_t xEMACRxEventSemaphore = NULL;
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceInitialise( void )
-{
-BaseType_t xStatus, xReturn;
-extern uint8_t ucMACAddress[ 6 ];
-
-       /* Initialise the MAC. */
-       vInitEmac();
-
-       while( lEMACWaitForLink() != pdPASS )
-    {
-        vTaskDelay( 20 );
-    }
-
-       vSemaphoreCreateBinary( xEMACRxEventSemaphore );
-       configASSERT( xEMACRxEventSemaphore );
-
-       /* The handler task is created at the highest possible priority to
-       ensure the interrupt handler can return directly to it. */
-       xTaskCreate( vEMACHandlerTask, "EMAC", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );
-       xReturn = pdPASS;
-
-       return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer )
-{
-extern void vEMACCopyWrite( uint8_t * pucBuffer, uint16_t usLength );
-
-       vEMACCopyWrite( pxNetworkBuffer->pucBuffer, pxNetworkBuffer->xDataLength );
-
-       /* Finished with the network buffer. */
-       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
-
-       return pdTRUE;
-}
-/*-----------------------------------------------------------*/
-
-
+/*\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
+\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_UDP_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+/* Hardware includes. */\r
+#include "hwEthernet.h"\r
+\r
+/* Demo includes. */\r
+#include "NetworkInterface.h"\r
+\r
+#if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 1\r
+       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer\r
+#else\r
+       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )\r
+#endif\r
+\r
+/* When a packet is ready to be sent, if it cannot be sent immediately then the\r
+task performing the transmit will block for niTX_BUFFER_FREE_WAIT\r
+milliseconds.  It will do this a maximum of niMAX_TX_ATTEMPTS before giving\r
+up. */\r
+#define niTX_BUFFER_FREE_WAIT  ( ( TickType_t ) 2UL / portTICK_PERIOD_MS )\r
+#define niMAX_TX_ATTEMPTS              ( 5 )\r
+\r
+/* The length of the queue used to send interrupt status words from the\r
+interrupt handler to the deferred handler task. */\r
+#define niINTERRUPT_QUEUE_LENGTH       ( 10 )\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * A deferred interrupt handler task that processes\r
+ */\r
+extern void vEMACHandlerTask( void *pvParameters );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* The queue used to communicate Ethernet events with the IP task. */\r
+extern QueueHandle_t xNetworkEventQueue;\r
+\r
+/* The semaphore used to wake the deferred interrupt handler task when an Rx\r
+interrupt is received. */\r
+SemaphoreHandle_t xEMACRxEventSemaphore = NULL;\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+BaseType_t xStatus, xReturn;\r
+extern uint8_t ucMACAddress[ 6 ];\r
+\r
+       /* Initialise the MAC. */\r
+       vInitEmac();\r
+\r
+       while( lEMACWaitForLink() != pdPASS )\r
+    {\r
+        vTaskDelay( 20 );\r
+    }\r
+\r
+       vSemaphoreCreateBinary( xEMACRxEventSemaphore );\r
+       configASSERT( xEMACRxEventSemaphore );\r
+\r
+       /* The handler task is created at the highest possible priority to\r
+       ensure the interrupt handler can return directly to it. */\r
+       xTaskCreate( vEMACHandlerTask, "EMAC", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );\r
+       xReturn = pdPASS;\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer )\r
+{\r
+extern void vEMACCopyWrite( uint8_t * pucBuffer, uint16_t usLength );\r
+\r
+       vEMACCopyWrite( pxNetworkBuffer->pucBuffer, pxNetworkBuffer->xDataLength );\r
+\r
+       /* Finished with the network buffer. */\r
+       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+\r
+       return pdTRUE;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+\r
index 8e64a40cc4e36aac7b85c4cc2fbf49797eaa96da..502fbd661dc5f43a0e678af100ecfc4ef1f446bf 100644 (file)
-#define xBUFFER_CACHE_SIZE                     10
-#define xMAX_FAULT_INJECTION_RATE      15
-#define xMIN_FAULT_INJECTION_RATE      3
-#define xNUM_FAULT_TYPES                       1
-
-static NetworkBufferDescriptor_t *xNetworkBufferCache[ xBUFFER_CACHE_SIZE ] = { 0 };
-
-#define xFAULT_LOG_SIZE 2048
-uint32_t ulInjectedFault[ xFAULT_LOG_SIZE ];
-uint32_t ulFaultLogIndex = 0;
-
-static BaseType_t prvCachePacket( NetworkBufferDescriptor_t *pxNetworkBufferIn )
-{
-BaseType_t x, xReturn = pdFALSE;
-
-       for( x = 0; x < xBUFFER_CACHE_SIZE; x++ )
-       {
-               if( xNetworkBufferCache[ x ] == NULL )
-               {
-                       xNetworkBufferCache[ x ] = pxNetworkBufferIn;
-                       xReturn = pdTRUE;
-                       break;
-               }
-       }
-
-       return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-static NetworkBufferDescriptor_t *prvGetCachedPacket( void )
-{
-BaseType_t x;
-NetworkBufferDescriptor_t *pxReturn = NULL;
-
-       for( x = ( xBUFFER_CACHE_SIZE - 1 ); x >= 0; x-- )
-       {
-               if( xNetworkBufferCache[ x ] != NULL )
-               {
-                       pxReturn = xNetworkBufferCache[ x ];
-                       xNetworkBufferCache[ x ] = NULL;
-                       break;
-               }
-       }
-
-       return pxReturn;
-}
-/*-----------------------------------------------------------*/
-
-static NetworkBufferDescriptor_t *prvDuplicatePacket( NetworkBufferDescriptor_t * pxOriginalPacket, const uint8_t *pucPacketData )
-{
-NetworkBufferDescriptor_t *pxReturn;
-
-       /* Obtain a new descriptor. */
-       pxReturn = pxGetNetworkBufferWithDescriptor( pxOriginalPacket->xDataLength, 0 );
-
-       if( pxReturn != NULL )
-       {
-               /* Copy in the packet data. */
-               pxReturn->xDataLength = pxOriginalPacket->xDataLength;
-               memcpy( pxReturn->pucEthernetBuffer, pucPacketData, pxOriginalPacket->xDataLength );
-       }
-
-       return pxReturn;
-}
-/*-----------------------------------------------------------*/
-
-static NetworkBufferDescriptor_t *prvRxFaultInjection( NetworkBufferDescriptor_t *pxNetworkBufferIn, const uint8_t *pucPacketData )
-{
-static uint32_t ulCallCount = 0, ulNextFaultCallCount = 0;
-NetworkBufferDescriptor_t *pxReturn = pxNetworkBufferIn;
-IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
-uint32_t ulFault;
-
-return pxNetworkBufferIn;
-
-       ulCallCount++;
-
-       if( ulCallCount > ulNextFaultCallCount )
-       {
-               xApplicationGetRandomNumber( &( ulNextFaultCallCount ) );
-               ulNextFaultCallCount = ulNextFaultCallCount % xMAX_FAULT_INJECTION_RATE;
-               if( ulNextFaultCallCount < xMIN_FAULT_INJECTION_RATE )
-               {
-                       ulNextFaultCallCount = xMIN_FAULT_INJECTION_RATE;
-               }
-
-               ulCallCount = 0;
-
-               xApplicationGetRandomNumber( &( ulFault ) );
-               ulFault = ulFault % xNUM_FAULT_TYPES;
-
-               if( ulFaultLogIndex < xFAULT_LOG_SIZE )
-               {
-                       ulInjectedFault[ ulFaultLogIndex ] = ulFault;
-                       ulFaultLogIndex++;
-               }
-
-               switch( ulFault )
-               {
-                       case 0:
-                               /* Just drop the packet. */
-                               vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
-                               pxReturn = NULL;
-                               break;
-
-                       case 1:
-                               /* Store the packet in the cache for later. */
-                               if( prvCachePacket( pxNetworkBufferIn ) == pdTRUE )
-                               {
-                                       /* The packet may get sent later, it is not being sent
-                                       now. */
-                                       pxReturn = NULL;
-                               }
-                               break;
-
-                       case 2:
-                               /* Send a cached packet. */
-                               pxReturn = prvGetCachedPacket();
-                               if( pxReturn != NULL )
-                               {
-                                       /* A cached packet was obtained so drop the original
-                                       packet. */
-                                       vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
-                               }
-                               else
-                               {
-                                       /* Could not obtain a packet from the cache so just return
-                                       the packet that was passed in. */
-                                       pxReturn = pxNetworkBufferIn;
-                               }
-                               break;
-
-                       case 4:
-
-                               /* Send a duplicate of the packet right away. */
-                               pxReturn = prvDuplicatePacket( pxNetworkBufferIn, pucPacketData );
-
-                               /* Send the original packet to the stack. */
-                               xRxEvent.pvData = ( void * ) pxNetworkBufferIn;
-                               if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )
-                               {
-                                       vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
-                               }
-                               break;
-
-                       case 5:
-
-                               /* Send both a cached packet and the current packet. */
-                               xRxEvent.pvData = ( void * ) prvGetCachedPacket();
-                               if( xRxEvent.pvData != NULL )
-                               {
-                                       if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )
-                                       {
-                                               vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
-                                       }
-                               }
-                               break;
-
-                       case 6:
-                       case 7:
-                       case 8:
-                               /* Store the packet in the cache for later. */
-                               if( prvCachePacket( pxNetworkBufferIn ) == pdTRUE )
-                               {
-                                       /* The packet may get sent later, it is not being sent
-                                       now. */
-                                       pxReturn = NULL;
-                               }
-                               break;
-               }
-       }
-
-       return pxReturn;
-}
-/*-----------------------------------------------------------*/
+#define xBUFFER_CACHE_SIZE                     10\r
+#define xMAX_FAULT_INJECTION_RATE      15\r
+#define xMIN_FAULT_INJECTION_RATE      3\r
+#define xNUM_FAULT_TYPES                       1\r
+\r
+static NetworkBufferDescriptor_t *xNetworkBufferCache[ xBUFFER_CACHE_SIZE ] = { 0 };\r
+\r
+#define xFAULT_LOG_SIZE 2048\r
+uint32_t ulInjectedFault[ xFAULT_LOG_SIZE ];\r
+uint32_t ulFaultLogIndex = 0;\r
+\r
+static BaseType_t prvCachePacket( NetworkBufferDescriptor_t *pxNetworkBufferIn )\r
+{\r
+BaseType_t x, xReturn = pdFALSE;\r
+\r
+       for( x = 0; x < xBUFFER_CACHE_SIZE; x++ )\r
+       {\r
+               if( xNetworkBufferCache[ x ] == NULL )\r
+               {\r
+                       xNetworkBufferCache[ x ] = pxNetworkBufferIn;\r
+                       xReturn = pdTRUE;\r
+                       break;\r
+               }\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static NetworkBufferDescriptor_t *prvGetCachedPacket( void )\r
+{\r
+BaseType_t x;\r
+NetworkBufferDescriptor_t *pxReturn = NULL;\r
+\r
+       for( x = ( xBUFFER_CACHE_SIZE - 1 ); x >= 0; x-- )\r
+       {\r
+               if( xNetworkBufferCache[ x ] != NULL )\r
+               {\r
+                       pxReturn = xNetworkBufferCache[ x ];\r
+                       xNetworkBufferCache[ x ] = NULL;\r
+                       break;\r
+               }\r
+       }\r
+\r
+       return pxReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static NetworkBufferDescriptor_t *prvDuplicatePacket( NetworkBufferDescriptor_t * pxOriginalPacket, const uint8_t *pucPacketData )\r
+{\r
+NetworkBufferDescriptor_t *pxReturn;\r
+\r
+       /* Obtain a new descriptor. */\r
+       pxReturn = pxGetNetworkBufferWithDescriptor( pxOriginalPacket->xDataLength, 0 );\r
+\r
+       if( pxReturn != NULL )\r
+       {\r
+               /* Copy in the packet data. */\r
+               pxReturn->xDataLength = pxOriginalPacket->xDataLength;\r
+               memcpy( pxReturn->pucEthernetBuffer, pucPacketData, pxOriginalPacket->xDataLength );\r
+       }\r
+\r
+       return pxReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static NetworkBufferDescriptor_t *prvRxFaultInjection( NetworkBufferDescriptor_t *pxNetworkBufferIn, const uint8_t *pucPacketData )\r
+{\r
+static uint32_t ulCallCount = 0, ulNextFaultCallCount = 0;\r
+NetworkBufferDescriptor_t *pxReturn = pxNetworkBufferIn;\r
+IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
+uint32_t ulFault;\r
+\r
+return pxNetworkBufferIn;\r
+\r
+       ulCallCount++;\r
+\r
+       if( ulCallCount > ulNextFaultCallCount )\r
+       {\r
+               xApplicationGetRandomNumber( &( ulNextFaultCallCount ) );\r
+               ulNextFaultCallCount = ulNextFaultCallCount % xMAX_FAULT_INJECTION_RATE;\r
+               if( ulNextFaultCallCount < xMIN_FAULT_INJECTION_RATE )\r
+               {\r
+                       ulNextFaultCallCount = xMIN_FAULT_INJECTION_RATE;\r
+               }\r
+\r
+               ulCallCount = 0;\r
+\r
+               xApplicationGetRandomNumber( &( ulFault ) );\r
+               ulFault = ulFault % xNUM_FAULT_TYPES;\r
+\r
+               if( ulFaultLogIndex < xFAULT_LOG_SIZE )\r
+               {\r
+                       ulInjectedFault[ ulFaultLogIndex ] = ulFault;\r
+                       ulFaultLogIndex++;\r
+               }\r
+\r
+               switch( ulFault )\r
+               {\r
+                       case 0:\r
+                               /* Just drop the packet. */\r
+                               vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );\r
+                               pxReturn = NULL;\r
+                               break;\r
+\r
+                       case 1:\r
+                               /* Store the packet in the cache for later. */\r
+                               if( prvCachePacket( pxNetworkBufferIn ) == pdTRUE )\r
+                               {\r
+                                       /* The packet may get sent later, it is not being sent\r
+                                       now. */\r
+                                       pxReturn = NULL;\r
+                               }\r
+                               break;\r
+\r
+                       case 2:\r
+                               /* Send a cached packet. */\r
+                               pxReturn = prvGetCachedPacket();\r
+                               if( pxReturn != NULL )\r
+                               {\r
+                                       /* A cached packet was obtained so drop the original\r
+                                       packet. */\r
+                                       vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );\r
+                               }\r
+                               else\r
+                               {\r
+                                       /* Could not obtain a packet from the cache so just return\r
+                                       the packet that was passed in. */\r
+                                       pxReturn = pxNetworkBufferIn;\r
+                               }\r
+                               break;\r
+\r
+                       case 4:\r
+\r
+                               /* Send a duplicate of the packet right away. */\r
+                               pxReturn = prvDuplicatePacket( pxNetworkBufferIn, pucPacketData );\r
+\r
+                               /* Send the original packet to the stack. */\r
+                               xRxEvent.pvData = ( void * ) pxNetworkBufferIn;\r
+                               if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )\r
+                               {\r
+                                       vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );\r
+                               }\r
+                               break;\r
+\r
+                       case 5:\r
+\r
+                               /* Send both a cached packet and the current packet. */\r
+                               xRxEvent.pvData = ( void * ) prvGetCachedPacket();\r
+                               if( xRxEvent.pvData != NULL )\r
+                               {\r
+                                       if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )\r
+                                       {\r
+                                               vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );\r
+                                       }\r
+                               }\r
+                               break;\r
+\r
+                       case 6:\r
+                       case 7:\r
+                       case 8:\r
+                               /* Store the packet in the cache for later. */\r
+                               if( prvCachePacket( pxNetworkBufferIn ) == pdTRUE )\r
+                               {\r
+                                       /* The packet may get sent later, it is not being sent\r
+                                       now. */\r
+                                       pxReturn = NULL;\r
+                               }\r
+                               break;\r
+               }\r
+       }\r
+\r
+       return pxReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
index c4a12515b0891a151d7a5063428e77157ac80cf5..474629e4632d4a552efa3e2afe016bd053b53068 100644 (file)
-/*
-FreeRTOS+TCP V2.0.11
-Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
- http://aws.amazon.com/freertos
- http://www.FreeRTOS.org
-*/
-
-/* WinPCap includes. */
-#define HAVE_REMOTE
-#include "pcap.h"
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "task.h"
-#include "semphr.h"
-
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_IP_Private.h"
-#include "NetworkBufferManagement.h"
-
-/* Thread-safe circular buffers are being used to pass data to and from the PCAP
-access functions. */
-#include "Win32-Extensions.h"
-#include "FreeRTOS_Stream_Buffer.h"
-
-/* Sizes of the thread safe circular buffers used to pass data to and from the
-WinPCAP Windows threads. */
-#define xSEND_BUFFER_SIZE  32768
-#define xRECV_BUFFER_SIZE  32768
-
-/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
-driver will filter incoming packets and only pass the stack those packets it
-considers need processing. */
-#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
-       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
-#else
-       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
-#endif
-
-/* Used to insert test code only. */
-#define niDISRUPT_PACKETS      0
-
-/*-----------------------------------------------------------*/
-
-/*
- * Windows threads that are outside of the control of the FreeRTOS simulator are
- * used to interface with the WinPCAP libraries.
- */
-DWORD WINAPI prvWinPcapRecvThread( void *pvParam );
-DWORD WINAPI prvWinPcapSendThread( void *pvParam );
-
-/*
- * Print out a numbered list of network interfaces that are available on the
- * host computer.
- */
-static pcap_if_t * prvPrintAvailableNetworkInterfaces( void );
-
-/*
- * Open the network interface.  The number of the interface to be opened is set
- * by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.
- */
-static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces );
-static int prvOpenInterface( const char *pucName );
-
-/*
- * Configure the capture filter to allow blocking reads, and to filter out
- * packets that are not of interest to this demo.
- */
-static void prvConfigureCaptureBehaviour( void );
-
-/*
- * A function that simulates Ethernet interrupts by periodically polling the
- * WinPCap interface for new data.
- */
-static void prvInterruptSimulatorTask( void *pvParameters );
-
-/*
- * Create the buffers that are used to pass data between the FreeRTOS simulator
- * and the Win32 threads that manage WinPCAP.
- */
-static void prvCreateThreadSafeBuffers( void );
-
-/*
- * Utility function used to format print messages only.
- */
-static const char *prvRemoveSpaces( char *pcBuffer, int aBuflen, const char *pcMessage );
-
-/*-----------------------------------------------------------*/
-
-/* Required by the WinPCap library. */
-static char cErrorBuffer[ PCAP_ERRBUF_SIZE ];
-
-/* An event used to wake up the Win32 thread that sends data through the WinPCAP
-library. */
-static void *pvSendEvent = NULL;
-
-/* _HT_ made the PCAP interface number configurable through the program's
-parameters in order to test in different machines. */
-static BaseType_t xConfigNetworkInterfaceToUse = configNETWORK_INTERFACE_TO_USE;
-
-/* Handles to the Windows threads that handle the PCAP IO. */
-static HANDLE vWinPcapRecvThreadHandle = NULL;
-static HANDLE vWinPcapSendThreadHandle = NULL;;
-
-/* The interface being used by WinPCap. */
-static pcap_t *pxOpenedInterfaceHandle = NULL;
-
-/* Circular buffers used by the PCAP Win32 threads. */
-static StreamBuffer_t *xSendBuffer = NULL;
-static StreamBuffer_t *xRecvBuffer = NULL;
-
-/* The MAC address initially set to the constants defined in FreeRTOSConfig.h. */
-extern uint8_t ucMACAddress[ 6 ];
-
-/* Logs the number of WinPCAP send failures, for viewing in the debugger only. */
-static volatile uint32_t ulWinPCAPSendFailures = 0;
-
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceInitialise( void )
-{
-BaseType_t xReturn = pdFALSE;
-pcap_if_t *pxAllNetworkInterfaces;
-
-       /* Query the computer the simulation is being executed on to find the
-       network interfaces it has installed. */
-       pxAllNetworkInterfaces = prvPrintAvailableNetworkInterfaces();
-
-       /* Open the network interface.  The number of the interface to be opened is
-       set by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.
-       Calling this function will set the pxOpenedInterfaceHandle variable.  If,
-       after calling this function, pxOpenedInterfaceHandle is equal to NULL, then
-       the interface could not be opened. */
-       if( pxAllNetworkInterfaces != NULL )
-       {
-               prvOpenSelectedNetworkInterface( pxAllNetworkInterfaces );
-       }
-
-       if( pxOpenedInterfaceHandle != NULL )
-       {
-               xReturn = pdPASS;
-       }
-
-       return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-static void prvCreateThreadSafeBuffers( void )
-{
-       /* The buffer used to pass data to be transmitted from a FreeRTOS task to
-       the Win32 thread that sends via the WinPCAP library. */
-       if( xSendBuffer == NULL)
-       {
-               xSendBuffer = ( StreamBuffer_t * ) malloc( sizeof( *xSendBuffer ) - sizeof( xSendBuffer->ucArray ) + xSEND_BUFFER_SIZE + 1 );
-               configASSERT( xSendBuffer );
-               memset( xSendBuffer, '\0', sizeof( *xSendBuffer ) - sizeof( xSendBuffer->ucArray ) );
-               xSendBuffer->LENGTH = xSEND_BUFFER_SIZE + 1;
-       }
-
-       /* The buffer used to pass received data from the Win32 thread that receives
-       via the WinPCAP library to the FreeRTOS task. */
-       if( xRecvBuffer == NULL)
-       {
-               xRecvBuffer = ( StreamBuffer_t * ) malloc( sizeof( *xRecvBuffer ) - sizeof( xRecvBuffer->ucArray ) + xRECV_BUFFER_SIZE + 1 );
-               configASSERT( xRecvBuffer );
-               memset( xRecvBuffer, '\0', sizeof( *xRecvBuffer ) - sizeof( xRecvBuffer->ucArray ) );
-               xRecvBuffer->LENGTH = xRECV_BUFFER_SIZE + 1;
-       }
-}
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t bReleaseAfterSend )
-{
-size_t xSpace;
-
-       iptraceNETWORK_INTERFACE_TRANSMIT();
-       configASSERT( xIsCallingFromIPTask() == pdTRUE );
-
-       /* Both the length of the data being sent and the actual data being sent
-       are placed in the thread safe buffer used to pass data between the FreeRTOS
-       tasks and the Win32 thread that sends data via the WinPCAP library.  Drop
-       the packet if there is insufficient space in the buffer to hold both. */
-       xSpace = uxStreamBufferGetSpace( xSendBuffer );
-
-       if( ( pxNetworkBuffer->xDataLength <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) &&
-               ( xSpace >= ( pxNetworkBuffer->xDataLength + sizeof( pxNetworkBuffer->xDataLength ) ) ) )
-       {
-               /* First write in the length of the data, then write in the data
-               itself. */
-               uxStreamBufferAdd( xSendBuffer, 0, ( const uint8_t * ) &( pxNetworkBuffer->xDataLength ), sizeof( pxNetworkBuffer->xDataLength ) );
-               uxStreamBufferAdd( xSendBuffer, 0, ( const uint8_t * ) pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength );
-       }
-       else
-       {
-               FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: send buffers full to store %lu\n", pxNetworkBuffer->xDataLength ) );
-       }
-
-       /* Kick the Tx task in either case in case it doesn't know the buffer is
-       full. */
-       SetEvent( pvSendEvent );
-
-       /* The buffer has been sent so can be released. */
-       if( bReleaseAfterSend != pdFALSE )
-       {
-               vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
-       }
-
-       return pdPASS;
-}
-/*-----------------------------------------------------------*/
-
-static pcap_if_t * prvPrintAvailableNetworkInterfaces( void )
-{
-pcap_if_t * pxAllNetworkInterfaces = NULL, *xInterface;
-int32_t lInterfaceNumber = 1;
-char cBuffer[ 512 ];
-static BaseType_t xInvalidInterfaceDetected = pdFALSE;
-
-       if( xInvalidInterfaceDetected == pdFALSE )
-       {
-               if( pcap_findalldevs_ex( PCAP_SRC_IF_STRING, NULL, &pxAllNetworkInterfaces, cErrorBuffer ) == -1 )
-               {
-                       printf( "Could not obtain a list of network interfaces\n%s\n", cErrorBuffer );
-                       pxAllNetworkInterfaces = NULL;
-               }
-               else
-               {
-                       printf( "\r\n\r\nThe following network interfaces are available:\r\n\r\n" );
-               }
-
-               if( pxAllNetworkInterfaces != NULL )
-               {
-                       /* Print out the list of network interfaces.  The first in the list
-                       is interface '1', not interface '0'. */
-                       for( xInterface = pxAllNetworkInterfaces; xInterface != NULL; xInterface = xInterface->next )
-                       {
-                               /* The descriptions of the devices can be full of spaces, clean them
-                               a little.  printf() can only be used here because the network is not
-                               up yet - so no other network tasks will be running. */
-                               printf( "Interface %d - %s\n", lInterfaceNumber, prvRemoveSpaces( cBuffer, sizeof( cBuffer ), xInterface->name ) );
-                               printf( "              (%s)\n", prvRemoveSpaces(cBuffer, sizeof( cBuffer ), xInterface->description ? xInterface->description : "No description" ) );
-                               printf( "\n" );
-                               lInterfaceNumber++;
-                       }
-               }
-
-               if( lInterfaceNumber == 1 )
-               {
-                       /* The interface number was never incremented, so the above for() loop
-                       did not execute meaning no interfaces were found. */
-                       printf( " \nNo network interfaces were found.\n" );
-                       pxAllNetworkInterfaces = NULL;
-               }
-
-               printf( "\r\nThe interface that will be opened is set by " );
-               printf( "\"configNETWORK_INTERFACE_TO_USE\", which\r\nshould be defined in FreeRTOSConfig.h\r\n" );
-
-               if( ( xConfigNetworkInterfaceToUse < 1L ) || ( xConfigNetworkInterfaceToUse >= lInterfaceNumber ) )
-               {
-                       printf( "\r\nERROR:  configNETWORK_INTERFACE_TO_USE is set to %d, which is an invalid value.\r\n", xConfigNetworkInterfaceToUse );
-                       printf( "Please set configNETWORK_INTERFACE_TO_USE to one of the interface numbers listed above,\r\n" );
-                       printf( "then re-compile and re-start the application.  Only Ethernet (as opposed to WiFi)\r\n" );
-                       printf( "interfaces are supported.\r\n\r\nHALTING\r\n\r\n\r\n" );
-                       xInvalidInterfaceDetected = pdTRUE;
-
-                       if( pxAllNetworkInterfaces != NULL )
-                       {
-                               /* Free the device list, as no devices are going to be opened. */
-                               pcap_freealldevs( pxAllNetworkInterfaces );
-                               pxAllNetworkInterfaces = NULL;
-                       }
-               }
-               else
-               {
-                       printf( "Attempting to open interface number %d.\n", xConfigNetworkInterfaceToUse );
-               }
-       }
-
-       return pxAllNetworkInterfaces;
-}
-/*-----------------------------------------------------------*/
-
-static int prvOpenInterface( const char *pucName )
-{
-static char pucInterfaceName[ 256 ];
-
-       if( pucName != NULL )
-       {
-               strncpy( pucInterfaceName, pucName, sizeof( pucInterfaceName ) );
-       }
-
-       pxOpenedInterfaceHandle = pcap_open(    pucInterfaceName,               /* The name of the selected interface. */
-                                                                                       ipTOTAL_ETHERNET_FRAME_SIZE, /* The size of the packet to capture. */
-                                                                                       PCAP_OPENFLAG_PROMISCUOUS,      /* Open in promiscuous mode as the MAC and
-                                                                                                                                               IP address is going to be "simulated", and
-                                                                                                                                               not be the real MAC and IP address.  This allows
-                                                                                                                                               traffic to the simulated IP address to be routed
-                                                                                                                                               to uIP, and traffic to the real IP address to be
-                                                                                                                                               routed to the Windows TCP/IP stack. */
-                                                                                       100,
-                                                                                       NULL,                                   /* No authentication is required as this is
-                                                                                                                                               not a remote capture session. */
-                                                                                       cErrorBuffer
-                                                                          );
-
-       if ( pxOpenedInterfaceHandle == NULL )
-       {
-               printf( "\n%s is not supported by WinPcap and cannot be opened\n", pucInterfaceName );
-               return 1;
-       }
-       else
-       {
-               /* Configure the capture filter to allow blocking reads, and to filter
-               out packets that are not of interest to this demo. */
-               prvConfigureCaptureBehaviour();
-       }
-       return 0;
-}
-/*-----------------------------------------------------------*/
-
-static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces )
-{
-pcap_if_t *pxInterface;
-int32_t x;
-
-       /* Walk the list of devices until the selected device is located. */
-       pxInterface = pxAllNetworkInterfaces;
-       for( x = 0L; x < ( xConfigNetworkInterfaceToUse - 1L ); x++ )
-       {
-               pxInterface = pxInterface->next;
-       }
-
-       /* Open the selected interface. */
-       if( prvOpenInterface( pxInterface->name ) == 0 )
-       {
-               printf( "Successfully opened interface number %d.\n", x + 1 );
-       }
-       else
-       {
-               printf( "Failed to open interface number %d.\n", x + 1 );
-       }
-
-       /* The device list is no longer required. */
-       pcap_freealldevs( pxAllNetworkInterfaces );
-}
-/*-----------------------------------------------------------*/
-
-static void prvConfigureCaptureBehaviour( void )
-{
-struct bpf_program xFilterCode;
-uint32_t ulNetMask;
-
-       /* Set up a filter so only the packets of interest are passed to the IP
-       stack.  cErrorBuffer is used for convenience to create the string.  Don't
-       confuse this with an error message. */
-       sprintf( cErrorBuffer, "broadcast or multicast or ether host %x:%x:%x:%x:%x:%x",
-               ucMACAddress[0], ucMACAddress[1], ucMACAddress[2], ucMACAddress[3], ucMACAddress[4], ucMACAddress[5] );
-
-       ulNetMask = ( configNET_MASK3 << 24UL ) | ( configNET_MASK2 << 16UL ) | ( configNET_MASK1 << 8L ) | configNET_MASK0;
-
-       if( pcap_compile( pxOpenedInterfaceHandle, &xFilterCode, cErrorBuffer, 1, ulNetMask ) < 0 )
-       {
-               printf( "\nThe packet filter string is invalid\n" );
-       }
-       else
-       {
-               if( pcap_setfilter( pxOpenedInterfaceHandle, &xFilterCode ) < 0 )
-               {
-                       printf( "\nAn error occurred setting the packet filter.\n" );
-               }
-               /* When pcap_compile() succeeds, it allocates memory for the memory pointed to by the bpf_program struct 
-               parameter.pcap_freecode() will free that memory. */
-               pcap_freecode( &xFilterCode );
-       }
-
-       /* Create the buffers used to pass packets between the FreeRTOS simulator
-       and the Win32 threads that are handling WinPCAP. */
-       prvCreateThreadSafeBuffers();
-
-       if( pvSendEvent == NULL )
-       {
-               /* Create event used to signal the Win32 WinPCAP Tx thread. */
-               pvSendEvent = CreateEvent( NULL, FALSE, TRUE, NULL );
-
-               /* Create the Win32 thread that handles WinPCAP Rx. */
-               vWinPcapRecvThreadHandle = CreateThread(
-                       NULL,   /* Pointer to thread security attributes. */
-                       0,              /* Initial thread stack size, in bytes. */
-                       prvWinPcapRecvThread,   /* Pointer to thread function. */
-                       NULL,   /* Argument for new thread. */
-                       0,              /* Creation flags. */
-                       NULL );
-
-               /* Use the cores that are not used by the FreeRTOS tasks. */
-               SetThreadAffinityMask( vWinPcapRecvThreadHandle, ~0x01u );
-
-               /* Create the Win32 thread that handlers WinPCAP Tx. */
-               vWinPcapSendThreadHandle = CreateThread(
-                       NULL,   /* Pointer to thread security attributes. */
-                       0,              /* initial thread stack size, in bytes. */
-                       prvWinPcapSendThread,   /* Pointer to thread function. */
-                       NULL,   /* Argument for new thread. */
-                       0,              /* Creation flags. */
-                       NULL );
-
-               /* Use the cores that are not used by the FreeRTOS tasks. */
-               SetThreadAffinityMask( vWinPcapSendThreadHandle, ~0x01u );
-
-               /* Create a task that simulates an interrupt in a real system.  This will
-               block waiting for packets, then send a message to the IP task when data
-               is available. */
-               xTaskCreate( prvInterruptSimulatorTask, "MAC_ISR", configMINIMAL_STACK_SIZE, NULL, configMAC_ISR_SIMULATOR_PRIORITY, NULL );
-       }
-}
-/*-----------------------------------------------------------*/
-
-/* WinPCAP function. */
-void pcap_callback( u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data )
-{
-       (void)user;
-
-       /* THIS IS CALLED FROM A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS
-       OR TO PRINT OUT MESSAGES HERE. */
-
-       /* Pass data to the FreeRTOS simulator on a thread safe circular buffer. */
-       if( ( pkt_header->caplen <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) &&
-               ( uxStreamBufferGetSpace( xRecvBuffer ) >= ( ( ( size_t ) pkt_header->caplen ) + sizeof( *pkt_header ) ) ) )
-       {
-               uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t* ) pkt_header, sizeof( *pkt_header ) );
-               uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t* ) pkt_data, ( size_t ) pkt_header->caplen );
-       }
-}
-/*-----------------------------------------------------------*/
-
-DWORD WINAPI prvWinPcapRecvThread ( void *pvParam )
-{
-       ( void ) pvParam;
-
-       /* THIS IS A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS OR TO PRINT
-       OUT MESSAGES HERE. */
-
-       for( ;; )
-       {
-               pcap_dispatch( pxOpenedInterfaceHandle, 1, pcap_callback, ( u_char * ) "mydata" );
-       }
-}
-/*-----------------------------------------------------------*/
-
-DWORD WINAPI prvWinPcapSendThread( void *pvParam )
-{
-size_t xLength;
-uint8_t ucBuffer[ ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ];
-static char cErrorMessage[ 1024 ];
-const DWORD xMaxMSToWait = 1000;
-
-       /* THIS IS A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS OR TO PRINT
-       OUT MESSAGES HERE. */
-
-       /* Remove compiler warnings about unused parameters. */
-       ( void ) pvParam;
-
-       for( ;; )
-       {
-               /* Wait until notified of something to send. */
-               WaitForSingleObject( pvSendEvent, xMaxMSToWait );
-
-               /* Is there more than the length value stored in the circular buffer
-               used to pass data from the FreeRTOS simulator into this Win32 thread? */
-               while( uxStreamBufferGetSize( xSendBuffer ) > sizeof( xLength ) )
-               {
-                       uxStreamBufferGet( xSendBuffer, 0, ( uint8_t * ) &xLength, sizeof( xLength ), pdFALSE );
-                       uxStreamBufferGet( xSendBuffer, 0, ( uint8_t* ) ucBuffer, xLength, pdFALSE );
-                       if( pcap_sendpacket( pxOpenedInterfaceHandle, ucBuffer, xLength  ) != 0 )
-                       {
-                               ulWinPCAPSendFailures++;
-                       }
-               }
-       }
-}
-/*-----------------------------------------------------------*/
-
-static void prvInterruptSimulatorTask( void *pvParameters )
-{
-struct pcap_pkthdr xHeader;
-static struct pcap_pkthdr *pxHeader;
-const uint8_t *pucPacketData;
-uint8_t ucRecvBuffer[ ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ];
-NetworkBufferDescriptor_t *pxNetworkBuffer;
-IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
-eFrameProcessingResult_t eResult;
-
-       /* Remove compiler warnings about unused parameters. */
-       ( void ) pvParameters;
-
-       for( ;; )
-       {
-               /* Does the circular buffer used to pass data from the Win32 thread that
-               handles WinPCAP Rx into the FreeRTOS simulator contain another packet? */
-               if( uxStreamBufferGetSize( xRecvBuffer ) > sizeof( xHeader ) )
-               {
-                       /* Get the next packet. */
-                       uxStreamBufferGet( xRecvBuffer, 0, (uint8_t*)&xHeader, sizeof( xHeader ), pdFALSE );
-                       uxStreamBufferGet( xRecvBuffer, 0, (uint8_t*)ucRecvBuffer, ( size_t ) xHeader.len, pdFALSE );
-                       pucPacketData = ucRecvBuffer;
-                       pxHeader = &xHeader;
-
-                       iptraceNETWORK_INTERFACE_RECEIVE();
-
-                       /* Check for minimal size. */
-                       if( pxHeader->len >= sizeof( EthernetHeader_t ) )
-                       {
-                               eResult = ipCONSIDER_FRAME_FOR_PROCESSING( pucPacketData );
-                       }
-                       else
-                       {
-                               eResult = eReleaseBuffer;
-                       }
-
-                       if( eResult == eProcessBuffer )
-                       {
-                               /* Will the data fit into the frame buffer? */
-                               if( pxHeader->len <= ipTOTAL_ETHERNET_FRAME_SIZE )
-                               {
-                                       /* Obtain a buffer into which the data can be placed.  This
-                                       is only an interrupt simulator, not a real interrupt, so it
-                                       is ok to call the task level function here, but note that
-                                       some buffer implementations cannot be called from a real
-                                       interrupt. */
-                                       pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( pxHeader->len, 0 );
-
-                                       if( pxNetworkBuffer != NULL )
-                                       {
-                                               memcpy( pxNetworkBuffer->pucEthernetBuffer, pucPacketData, pxHeader->len );
-                                               pxNetworkBuffer->xDataLength = ( size_t ) pxHeader->len;
-
-                                               #if( niDISRUPT_PACKETS == 1 )
-                                               {
-                                                       pxNetworkBuffer = vRxFaultInjection( pxNetworkBuffer, pucPacketData );
-                                               }
-                                               #endif /* niDISRUPT_PACKETS */
-
-                                               if( pxNetworkBuffer != NULL )
-                                               {
-                                                       xRxEvent.pvData = ( void * ) pxNetworkBuffer;
-
-                                                       /* Data was received and stored.  Send a message to
-                                                       the IP task to let it know. */
-                                                       if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )
-                                                       {
-                                                               /* The buffer could not be sent to the stack so
-                                                               must be released again.  This is only an
-                                                               interrupt simulator, not a real interrupt, so it
-                                                               is ok to use the task level function here, but
-                                                               note no all buffer implementations will allow
-                                                               this function to be executed from a real
-                                                               interrupt. */
-                                                               vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
-                                                               iptraceETHERNET_RX_EVENT_LOST();
-                                                       }
-                                               }
-                                               else
-                                               {
-                                                       /* The packet was already released or stored inside
-                                                       vRxFaultInjection().  Don't release it here. */
-                                               }
-                                       }
-                                       else
-                                       {
-                                               iptraceETHERNET_RX_EVENT_LOST();
-                                       }
-                               }
-                               else
-                               {
-                                       /* Log that a packet was dropped because it would have
-                                       overflowed the buffer, but there may be more buffers to
-                                       process. */
-                               }
-                       }
-               }
-               else
-               {
-                       /* There is no real way of simulating an interrupt.  Make sure
-                       other tasks can run. */
-                       vTaskDelay( configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY );
-               }
-       }
-}
-/*-----------------------------------------------------------*/
-
-static const char *prvRemoveSpaces( char *pcBuffer, int aBuflen, const char *pcMessage )
-{
-       char *pcTarget = pcBuffer;
-
-       /* Utility function used to formap messages being printed only. */
-       while( ( *pcMessage != 0 ) && ( pcTarget < ( pcBuffer + aBuflen - 1 ) ) )
-       {
-               *( pcTarget++ ) = *pcMessage;
-
-               if( isspace( *pcMessage ) != pdFALSE )
-               {
-                       while( isspace( *pcMessage ) != pdFALSE )
-                       {
-                               pcMessage++;
-                       }
-               }
-               else
-               {
-                       pcMessage++;
-               }
-       }
-
-       *pcTarget = '\0';
-
-       return pcBuffer;
-}
+/*\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
+/* WinPCap includes. */\r
+#define HAVE_REMOTE\r
+#include "pcap.h"\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+/* Thread-safe circular buffers are being used to pass data to and from the PCAP\r
+access functions. */\r
+#include "Win32-Extensions.h"\r
+#include "FreeRTOS_Stream_Buffer.h"\r
+\r
+/* Sizes of the thread safe circular buffers used to pass data to and from the\r
+WinPCAP Windows threads. */\r
+#define xSEND_BUFFER_SIZE  32768\r
+#define xRECV_BUFFER_SIZE  32768\r
+\r
+/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet\r
+driver will filter incoming packets and only pass the stack those packets it\r
+considers need processing. */\r
+#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )\r
+       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer\r
+#else\r
+       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )\r
+#endif\r
+\r
+/* Used to insert test code only. */\r
+#define niDISRUPT_PACKETS      0\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Windows threads that are outside of the control of the FreeRTOS simulator are\r
+ * used to interface with the WinPCAP libraries.\r
+ */\r
+DWORD WINAPI prvWinPcapRecvThread( void *pvParam );\r
+DWORD WINAPI prvWinPcapSendThread( void *pvParam );\r
+\r
+/*\r
+ * Print out a numbered list of network interfaces that are available on the\r
+ * host computer.\r
+ */\r
+static pcap_if_t * prvPrintAvailableNetworkInterfaces( void );\r
+\r
+/*\r
+ * Open the network interface.  The number of the interface to be opened is set\r
+ * by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.\r
+ */\r
+static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces );\r
+static int prvOpenInterface( const char *pucName );\r
+\r
+/*\r
+ * Configure the capture filter to allow blocking reads, and to filter out\r
+ * packets that are not of interest to this demo.\r
+ */\r
+static void prvConfigureCaptureBehaviour( void );\r
+\r
+/*\r
+ * A function that simulates Ethernet interrupts by periodically polling the\r
+ * WinPCap interface for new data.\r
+ */\r
+static void prvInterruptSimulatorTask( void *pvParameters );\r
+\r
+/*\r
+ * Create the buffers that are used to pass data between the FreeRTOS simulator\r
+ * and the Win32 threads that manage WinPCAP.\r
+ */\r
+static void prvCreateThreadSafeBuffers( void );\r
+\r
+/*\r
+ * Utility function used to format print messages only.\r
+ */\r
+static const char *prvRemoveSpaces( char *pcBuffer, int aBuflen, const char *pcMessage );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Required by the WinPCap library. */\r
+static char cErrorBuffer[ PCAP_ERRBUF_SIZE ];\r
+\r
+/* An event used to wake up the Win32 thread that sends data through the WinPCAP\r
+library. */\r
+static void *pvSendEvent = NULL;\r
+\r
+/* _HT_ made the PCAP interface number configurable through the program's\r
+parameters in order to test in different machines. */\r
+static BaseType_t xConfigNetworkInterfaceToUse = configNETWORK_INTERFACE_TO_USE;\r
+\r
+/* Handles to the Windows threads that handle the PCAP IO. */\r
+static HANDLE vWinPcapRecvThreadHandle = NULL;\r
+static HANDLE vWinPcapSendThreadHandle = NULL;;\r
+\r
+/* The interface being used by WinPCap. */\r
+static pcap_t *pxOpenedInterfaceHandle = NULL;\r
+\r
+/* Circular buffers used by the PCAP Win32 threads. */\r
+static StreamBuffer_t *xSendBuffer = NULL;\r
+static StreamBuffer_t *xRecvBuffer = NULL;\r
+\r
+/* The MAC address initially set to the constants defined in FreeRTOSConfig.h. */\r
+extern uint8_t ucMACAddress[ 6 ];\r
+\r
+/* Logs the number of WinPCAP send failures, for viewing in the debugger only. */\r
+static volatile uint32_t ulWinPCAPSendFailures = 0;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+BaseType_t xReturn = pdFALSE;\r
+pcap_if_t *pxAllNetworkInterfaces;\r
+\r
+       /* Query the computer the simulation is being executed on to find the\r
+       network interfaces it has installed. */\r
+       pxAllNetworkInterfaces = prvPrintAvailableNetworkInterfaces();\r
+\r
+       /* Open the network interface.  The number of the interface to be opened is\r
+       set by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.\r
+       Calling this function will set the pxOpenedInterfaceHandle variable.  If,\r
+       after calling this function, pxOpenedInterfaceHandle is equal to NULL, then\r
+       the interface could not be opened. */\r
+       if( pxAllNetworkInterfaces != NULL )\r
+       {\r
+               prvOpenSelectedNetworkInterface( pxAllNetworkInterfaces );\r
+       }\r
+\r
+       if( pxOpenedInterfaceHandle != NULL )\r
+       {\r
+               xReturn = pdPASS;\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvCreateThreadSafeBuffers( void )\r
+{\r
+       /* The buffer used to pass data to be transmitted from a FreeRTOS task to\r
+       the Win32 thread that sends via the WinPCAP library. */\r
+       if( xSendBuffer == NULL)\r
+       {\r
+               xSendBuffer = ( StreamBuffer_t * ) malloc( sizeof( *xSendBuffer ) - sizeof( xSendBuffer->ucArray ) + xSEND_BUFFER_SIZE + 1 );\r
+               configASSERT( xSendBuffer );\r
+               memset( xSendBuffer, '\0', sizeof( *xSendBuffer ) - sizeof( xSendBuffer->ucArray ) );\r
+               xSendBuffer->LENGTH = xSEND_BUFFER_SIZE + 1;\r
+       }\r
+\r
+       /* The buffer used to pass received data from the Win32 thread that receives\r
+       via the WinPCAP library to the FreeRTOS task. */\r
+       if( xRecvBuffer == NULL)\r
+       {\r
+               xRecvBuffer = ( StreamBuffer_t * ) malloc( sizeof( *xRecvBuffer ) - sizeof( xRecvBuffer->ucArray ) + xRECV_BUFFER_SIZE + 1 );\r
+               configASSERT( xRecvBuffer );\r
+               memset( xRecvBuffer, '\0', sizeof( *xRecvBuffer ) - sizeof( xRecvBuffer->ucArray ) );\r
+               xRecvBuffer->LENGTH = xRECV_BUFFER_SIZE + 1;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t bReleaseAfterSend )\r
+{\r
+size_t xSpace;\r
+\r
+       iptraceNETWORK_INTERFACE_TRANSMIT();\r
+       configASSERT( xIsCallingFromIPTask() == pdTRUE );\r
+\r
+       /* Both the length of the data being sent and the actual data being sent\r
+       are placed in the thread safe buffer used to pass data between the FreeRTOS\r
+       tasks and the Win32 thread that sends data via the WinPCAP library.  Drop\r
+       the packet if there is insufficient space in the buffer to hold both. */\r
+       xSpace = uxStreamBufferGetSpace( xSendBuffer );\r
+\r
+       if( ( pxNetworkBuffer->xDataLength <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) &&\r
+               ( xSpace >= ( pxNetworkBuffer->xDataLength + sizeof( pxNetworkBuffer->xDataLength ) ) ) )\r
+       {\r
+               /* First write in the length of the data, then write in the data\r
+               itself. */\r
+               uxStreamBufferAdd( xSendBuffer, 0, ( const uint8_t * ) &( pxNetworkBuffer->xDataLength ), sizeof( pxNetworkBuffer->xDataLength ) );\r
+               uxStreamBufferAdd( xSendBuffer, 0, ( const uint8_t * ) pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength );\r
+       }\r
+       else\r
+       {\r
+               FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: send buffers full to store %lu\n", pxNetworkBuffer->xDataLength ) );\r
+       }\r
+\r
+       /* Kick the Tx task in either case in case it doesn't know the buffer is\r
+       full. */\r
+       SetEvent( pvSendEvent );\r
+\r
+       /* The buffer has been sent so can be released. */\r
+       if( bReleaseAfterSend != pdFALSE )\r
+       {\r
+               vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+       }\r
+\r
+       return pdPASS;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static pcap_if_t * prvPrintAvailableNetworkInterfaces( void )\r
+{\r
+pcap_if_t * pxAllNetworkInterfaces = NULL, *xInterface;\r
+int32_t lInterfaceNumber = 1;\r
+char cBuffer[ 512 ];\r
+static BaseType_t xInvalidInterfaceDetected = pdFALSE;\r
+\r
+       if( xInvalidInterfaceDetected == pdFALSE )\r
+       {\r
+               if( pcap_findalldevs_ex( PCAP_SRC_IF_STRING, NULL, &pxAllNetworkInterfaces, cErrorBuffer ) == -1 )\r
+               {\r
+                       printf( "Could not obtain a list of network interfaces\n%s\n", cErrorBuffer );\r
+                       pxAllNetworkInterfaces = NULL;\r
+               }\r
+               else\r
+               {\r
+                       printf( "\r\n\r\nThe following network interfaces are available:\r\n\r\n" );\r
+               }\r
+\r
+               if( pxAllNetworkInterfaces != NULL )\r
+               {\r
+                       /* Print out the list of network interfaces.  The first in the list\r
+                       is interface '1', not interface '0'. */\r
+                       for( xInterface = pxAllNetworkInterfaces; xInterface != NULL; xInterface = xInterface->next )\r
+                       {\r
+                               /* The descriptions of the devices can be full of spaces, clean them\r
+                               a little.  printf() can only be used here because the network is not\r
+                               up yet - so no other network tasks will be running. */\r
+                               printf( "Interface %d - %s\n", lInterfaceNumber, prvRemoveSpaces( cBuffer, sizeof( cBuffer ), xInterface->name ) );\r
+                               printf( "              (%s)\n", prvRemoveSpaces(cBuffer, sizeof( cBuffer ), xInterface->description ? xInterface->description : "No description" ) );\r
+                               printf( "\n" );\r
+                               lInterfaceNumber++;\r
+                       }\r
+               }\r
+\r
+               if( lInterfaceNumber == 1 )\r
+               {\r
+                       /* The interface number was never incremented, so the above for() loop\r
+                       did not execute meaning no interfaces were found. */\r
+                       printf( " \nNo network interfaces were found.\n" );\r
+                       pxAllNetworkInterfaces = NULL;\r
+               }\r
+\r
+               printf( "\r\nThe interface that will be opened is set by " );\r
+               printf( "\"configNETWORK_INTERFACE_TO_USE\", which\r\nshould be defined in FreeRTOSConfig.h\r\n" );\r
+\r
+               if( ( xConfigNetworkInterfaceToUse < 1L ) || ( xConfigNetworkInterfaceToUse >= lInterfaceNumber ) )\r
+               {\r
+                       printf( "\r\nERROR:  configNETWORK_INTERFACE_TO_USE is set to %d, which is an invalid value.\r\n", xConfigNetworkInterfaceToUse );\r
+                       printf( "Please set configNETWORK_INTERFACE_TO_USE to one of the interface numbers listed above,\r\n" );\r
+                       printf( "then re-compile and re-start the application.  Only Ethernet (as opposed to WiFi)\r\n" );\r
+                       printf( "interfaces are supported.\r\n\r\nHALTING\r\n\r\n\r\n" );\r
+                       xInvalidInterfaceDetected = pdTRUE;\r
+\r
+                       if( pxAllNetworkInterfaces != NULL )\r
+                       {\r
+                               /* Free the device list, as no devices are going to be opened. */\r
+                               pcap_freealldevs( pxAllNetworkInterfaces );\r
+                               pxAllNetworkInterfaces = NULL;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       printf( "Attempting to open interface number %d.\n", xConfigNetworkInterfaceToUse );\r
+               }\r
+       }\r
+\r
+       return pxAllNetworkInterfaces;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static int prvOpenInterface( const char *pucName )\r
+{\r
+static char pucInterfaceName[ 256 ];\r
+\r
+       if( pucName != NULL )\r
+       {\r
+               strncpy( pucInterfaceName, pucName, sizeof( pucInterfaceName ) );\r
+       }\r
+\r
+       pxOpenedInterfaceHandle = pcap_open(    pucInterfaceName,               /* The name of the selected interface. */\r
+                                                                                       ipTOTAL_ETHERNET_FRAME_SIZE, /* The size of the packet to capture. */\r
+                                                                                       PCAP_OPENFLAG_PROMISCUOUS,      /* Open in promiscuous mode as the MAC and\r
+                                                                                                                                               IP address is going to be "simulated", and\r
+                                                                                                                                               not be the real MAC and IP address.  This allows\r
+                                                                                                                                               traffic to the simulated IP address to be routed\r
+                                                                                                                                               to uIP, and traffic to the real IP address to be\r
+                                                                                                                                               routed to the Windows TCP/IP stack. */\r
+                                                                                       100,\r
+                                                                                       NULL,                                   /* No authentication is required as this is\r
+                                                                                                                                               not a remote capture session. */\r
+                                                                                       cErrorBuffer\r
+                                                                          );\r
+\r
+       if ( pxOpenedInterfaceHandle == NULL )\r
+       {\r
+               printf( "\n%s is not supported by WinPcap and cannot be opened\n", pucInterfaceName );\r
+               return 1;\r
+       }\r
+       else\r
+       {\r
+               /* Configure the capture filter to allow blocking reads, and to filter\r
+               out packets that are not of interest to this demo. */\r
+               prvConfigureCaptureBehaviour();\r
+       }\r
+       return 0;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces )\r
+{\r
+pcap_if_t *pxInterface;\r
+int32_t x;\r
+\r
+       /* Walk the list of devices until the selected device is located. */\r
+       pxInterface = pxAllNetworkInterfaces;\r
+       for( x = 0L; x < ( xConfigNetworkInterfaceToUse - 1L ); x++ )\r
+       {\r
+               pxInterface = pxInterface->next;\r
+       }\r
+\r
+       /* Open the selected interface. */\r
+       if( prvOpenInterface( pxInterface->name ) == 0 )\r
+       {\r
+               printf( "Successfully opened interface number %d.\n", x + 1 );\r
+       }\r
+       else\r
+       {\r
+               printf( "Failed to open interface number %d.\n", x + 1 );\r
+       }\r
+\r
+       /* The device list is no longer required. */\r
+       pcap_freealldevs( pxAllNetworkInterfaces );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvConfigureCaptureBehaviour( void )\r
+{\r
+struct bpf_program xFilterCode;\r
+uint32_t ulNetMask;\r
+\r
+       /* Set up a filter so only the packets of interest are passed to the IP\r
+       stack.  cErrorBuffer is used for convenience to create the string.  Don't\r
+       confuse this with an error message. */\r
+       sprintf( cErrorBuffer, "broadcast or multicast or ether host %x:%x:%x:%x:%x:%x",\r
+               ucMACAddress[0], ucMACAddress[1], ucMACAddress[2], ucMACAddress[3], ucMACAddress[4], ucMACAddress[5] );\r
+\r
+       ulNetMask = ( configNET_MASK3 << 24UL ) | ( configNET_MASK2 << 16UL ) | ( configNET_MASK1 << 8L ) | configNET_MASK0;\r
+\r
+       if( pcap_compile( pxOpenedInterfaceHandle, &xFilterCode, cErrorBuffer, 1, ulNetMask ) < 0 )\r
+       {\r
+               printf( "\nThe packet filter string is invalid\n" );\r
+       }\r
+       else\r
+       {\r
+               if( pcap_setfilter( pxOpenedInterfaceHandle, &xFilterCode ) < 0 )\r
+               {\r
+                       printf( "\nAn error occurred setting the packet filter.\n" );\r
+               }\r
+               /* When pcap_compile() succeeds, it allocates memory for the memory pointed to by the bpf_program struct \r
+               parameter.pcap_freecode() will free that memory. */\r
+               pcap_freecode( &xFilterCode );\r
+       }\r
+\r
+       /* Create the buffers used to pass packets between the FreeRTOS simulator\r
+       and the Win32 threads that are handling WinPCAP. */\r
+       prvCreateThreadSafeBuffers();\r
+\r
+       if( pvSendEvent == NULL )\r
+       {\r
+               /* Create event used to signal the Win32 WinPCAP Tx thread. */\r
+               pvSendEvent = CreateEvent( NULL, FALSE, TRUE, NULL );\r
+\r
+               /* Create the Win32 thread that handles WinPCAP Rx. */\r
+               vWinPcapRecvThreadHandle = CreateThread(\r
+                       NULL,   /* Pointer to thread security attributes. */\r
+                       0,              /* Initial thread stack size, in bytes. */\r
+                       prvWinPcapRecvThread,   /* Pointer to thread function. */\r
+                       NULL,   /* Argument for new thread. */\r
+                       0,              /* Creation flags. */\r
+                       NULL );\r
+\r
+               /* Use the cores that are not used by the FreeRTOS tasks. */\r
+               SetThreadAffinityMask( vWinPcapRecvThreadHandle, ~0x01u );\r
+\r
+               /* Create the Win32 thread that handlers WinPCAP Tx. */\r
+               vWinPcapSendThreadHandle = CreateThread(\r
+                       NULL,   /* Pointer to thread security attributes. */\r
+                       0,              /* initial thread stack size, in bytes. */\r
+                       prvWinPcapSendThread,   /* Pointer to thread function. */\r
+                       NULL,   /* Argument for new thread. */\r
+                       0,              /* Creation flags. */\r
+                       NULL );\r
+\r
+               /* Use the cores that are not used by the FreeRTOS tasks. */\r
+               SetThreadAffinityMask( vWinPcapSendThreadHandle, ~0x01u );\r
+\r
+               /* Create a task that simulates an interrupt in a real system.  This will\r
+               block waiting for packets, then send a message to the IP task when data\r
+               is available. */\r
+               xTaskCreate( prvInterruptSimulatorTask, "MAC_ISR", configMINIMAL_STACK_SIZE, NULL, configMAC_ISR_SIMULATOR_PRIORITY, NULL );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* WinPCAP function. */\r
+void pcap_callback( u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data )\r
+{\r
+       (void)user;\r
+\r
+       /* THIS IS CALLED FROM A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS\r
+       OR TO PRINT OUT MESSAGES HERE. */\r
+\r
+       /* Pass data to the FreeRTOS simulator on a thread safe circular buffer. */\r
+       if( ( pkt_header->caplen <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) &&\r
+               ( uxStreamBufferGetSpace( xRecvBuffer ) >= ( ( ( size_t ) pkt_header->caplen ) + sizeof( *pkt_header ) ) ) )\r
+       {\r
+               uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t* ) pkt_header, sizeof( *pkt_header ) );\r
+               uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t* ) pkt_data, ( size_t ) pkt_header->caplen );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+DWORD WINAPI prvWinPcapRecvThread ( void *pvParam )\r
+{\r
+       ( void ) pvParam;\r
+\r
+       /* THIS IS A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS OR TO PRINT\r
+       OUT MESSAGES HERE. */\r
+\r
+       for( ;; )\r
+       {\r
+               pcap_dispatch( pxOpenedInterfaceHandle, 1, pcap_callback, ( u_char * ) "mydata" );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+DWORD WINAPI prvWinPcapSendThread( void *pvParam )\r
+{\r
+size_t xLength;\r
+uint8_t ucBuffer[ ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ];\r
+static char cErrorMessage[ 1024 ];\r
+const DWORD xMaxMSToWait = 1000;\r
+\r
+       /* THIS IS A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS OR TO PRINT\r
+       OUT MESSAGES HERE. */\r
+\r
+       /* Remove compiler warnings about unused parameters. */\r
+       ( void ) pvParam;\r
+\r
+       for( ;; )\r
+       {\r
+               /* Wait until notified of something to send. */\r
+               WaitForSingleObject( pvSendEvent, xMaxMSToWait );\r
+\r
+               /* Is there more than the length value stored in the circular buffer\r
+               used to pass data from the FreeRTOS simulator into this Win32 thread? */\r
+               while( uxStreamBufferGetSize( xSendBuffer ) > sizeof( xLength ) )\r
+               {\r
+                       uxStreamBufferGet( xSendBuffer, 0, ( uint8_t * ) &xLength, sizeof( xLength ), pdFALSE );\r
+                       uxStreamBufferGet( xSendBuffer, 0, ( uint8_t* ) ucBuffer, xLength, pdFALSE );\r
+                       if( pcap_sendpacket( pxOpenedInterfaceHandle, ucBuffer, xLength  ) != 0 )\r
+                       {\r
+                               ulWinPCAPSendFailures++;\r
+                       }\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvInterruptSimulatorTask( void *pvParameters )\r
+{\r
+struct pcap_pkthdr xHeader;\r
+static struct pcap_pkthdr *pxHeader;\r
+const uint8_t *pucPacketData;\r
+uint8_t ucRecvBuffer[ ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ];\r
+NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
+eFrameProcessingResult_t eResult;\r
+\r
+       /* Remove compiler warnings about unused parameters. */\r
+       ( void ) pvParameters;\r
+\r
+       for( ;; )\r
+       {\r
+               /* Does the circular buffer used to pass data from the Win32 thread that\r
+               handles WinPCAP Rx into the FreeRTOS simulator contain another packet? */\r
+               if( uxStreamBufferGetSize( xRecvBuffer ) > sizeof( xHeader ) )\r
+               {\r
+                       /* Get the next packet. */\r
+                       uxStreamBufferGet( xRecvBuffer, 0, (uint8_t*)&xHeader, sizeof( xHeader ), pdFALSE );\r
+                       uxStreamBufferGet( xRecvBuffer, 0, (uint8_t*)ucRecvBuffer, ( size_t ) xHeader.len, pdFALSE );\r
+                       pucPacketData = ucRecvBuffer;\r
+                       pxHeader = &xHeader;\r
+\r
+                       iptraceNETWORK_INTERFACE_RECEIVE();\r
+\r
+                       /* Check for minimal size. */\r
+                       if( pxHeader->len >= sizeof( EthernetHeader_t ) )\r
+                       {\r
+                               eResult = ipCONSIDER_FRAME_FOR_PROCESSING( pucPacketData );\r
+                       }\r
+                       else\r
+                       {\r
+                               eResult = eReleaseBuffer;\r
+                       }\r
+\r
+                       if( eResult == eProcessBuffer )\r
+                       {\r
+                               /* Will the data fit into the frame buffer? */\r
+                               if( pxHeader->len <= ipTOTAL_ETHERNET_FRAME_SIZE )\r
+                               {\r
+                                       /* Obtain a buffer into which the data can be placed.  This\r
+                                       is only an interrupt simulator, not a real interrupt, so it\r
+                                       is ok to call the task level function here, but note that\r
+                                       some buffer implementations cannot be called from a real\r
+                                       interrupt. */\r
+                                       pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( pxHeader->len, 0 );\r
+\r
+                                       if( pxNetworkBuffer != NULL )\r
+                                       {\r
+                                               memcpy( pxNetworkBuffer->pucEthernetBuffer, pucPacketData, pxHeader->len );\r
+                                               pxNetworkBuffer->xDataLength = ( size_t ) pxHeader->len;\r
+\r
+                                               #if( niDISRUPT_PACKETS == 1 )\r
+                                               {\r
+                                                       pxNetworkBuffer = vRxFaultInjection( pxNetworkBuffer, pucPacketData );\r
+                                               }\r
+                                               #endif /* niDISRUPT_PACKETS */\r
+\r
+                                               if( pxNetworkBuffer != NULL )\r
+                                               {\r
+                                                       xRxEvent.pvData = ( void * ) pxNetworkBuffer;\r
+\r
+                                                       /* Data was received and stored.  Send a message to\r
+                                                       the IP task to let it know. */\r
+                                                       if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )\r
+                                                       {\r
+                                                               /* The buffer could not be sent to the stack so\r
+                                                               must be released again.  This is only an\r
+                                                               interrupt simulator, not a real interrupt, so it\r
+                                                               is ok to use the task level function here, but\r
+                                                               note no all buffer implementations will allow\r
+                                                               this function to be executed from a real\r
+                                                               interrupt. */\r
+                                                               vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+                                                               iptraceETHERNET_RX_EVENT_LOST();\r
+                                                       }\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       /* The packet was already released or stored inside\r
+                                                       vRxFaultInjection().  Don't release it here. */\r
+                                               }\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               iptraceETHERNET_RX_EVENT_LOST();\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       /* Log that a packet was dropped because it would have\r
+                                       overflowed the buffer, but there may be more buffers to\r
+                                       process. */\r
+                               }\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       /* There is no real way of simulating an interrupt.  Make sure\r
+                       other tasks can run. */\r
+                       vTaskDelay( configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY );\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static const char *prvRemoveSpaces( char *pcBuffer, int aBuflen, const char *pcMessage )\r
+{\r
+       char *pcTarget = pcBuffer;\r
+\r
+       /* Utility function used to formap messages being printed only. */\r
+       while( ( *pcMessage != 0 ) && ( pcTarget < ( pcBuffer + aBuflen - 1 ) ) )\r
+       {\r
+               *( pcTarget++ ) = *pcMessage;\r
+\r
+               if( isspace( *pcMessage ) != pdFALSE )\r
+               {\r
+                       while( isspace( *pcMessage ) != pdFALSE )\r
+                       {\r
+                               pcMessage++;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       pcMessage++;\r
+               }\r
+       }\r
+\r
+       *pcTarget = '\0';\r
+\r
+       return pcBuffer;\r
+}\r
index c8f9653951e567f4a1e5ed6f26f9409ffa8fecec..1c11976cbcec7779ed97ef48964cc7a25bcdd9d9 100644 (file)
-/*
-FreeRTOS+TCP V2.0.11
-Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
- http://aws.amazon.com/freertos
- http://www.FreeRTOS.org
-*/
-
-/* Standard includes. */
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "task.h"
-#include "queue.h"
-#include "semphr.h"
-
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_Sockets.h"
-#include "FreeRTOS_IP_Private.h"
-#include "NetworkBufferManagement.h"
-#include "NetworkInterface.h"
-
-/* Xilinx library files. */
-#include <xemacps.h>
-#include "Zynq/x_topology.h"
-#include "Zynq/x_emacpsif.h"
-#include "Zynq/x_emacpsif_hw.h"
-
-/* Provided memory configured as uncached. */
-#include "uncached_memory.h"
-
-#ifndef        BMSR_LINK_STATUS
-       #define BMSR_LINK_STATUS            0x0004UL
-#endif
-
-#ifndef        PHY_LS_HIGH_CHECK_TIME_MS
-       /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not
-       receiving packets. */
-       #define PHY_LS_HIGH_CHECK_TIME_MS       15000
-#endif
-
-#ifndef        PHY_LS_LOW_CHECK_TIME_MS
-       /* Check if the LinkSStatus in the PHY is still low every second. */
-       #define PHY_LS_LOW_CHECK_TIME_MS        1000
-#endif
-
-/* The size of each buffer when BufferAllocation_1 is used:
-http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html */
-#define niBUFFER_1_PACKET_SIZE         1536
-
-/* Naming and numbering of PHY registers. */
-#define PHY_REG_01_BMSR                        0x01    /* Basic mode status register */
-
-#ifndef iptraceEMAC_TASK_STARTING
-       #define iptraceEMAC_TASK_STARTING()     do { } while( 0 )
-#endif
-
-/* Default the size of the stack used by the EMAC deferred handler task to twice
-the size of the stack used by the idle task - but allow this to be overridden in
-FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */
-#ifndef configEMAC_TASK_STACK_SIZE
-       #define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )
-#endif
-
-/*-----------------------------------------------------------*/
-
-/*
- * Look for the link to be up every few milliseconds until either xMaxTime time
- * has passed or a link is found.
- */
-static BaseType_t prvGMACWaitLS( TickType_t xMaxTime );
-
-/*
- * A deferred interrupt handler for all MAC/DMA interrupt sources.
- */
-static void prvEMACHandlerTask( void *pvParameters );
-
-/*-----------------------------------------------------------*/
-
-/* EMAC data/descriptions. */
-static xemacpsif_s xEMACpsif;
-struct xtopology_t xXTopology =
-{
-       .emac_baseaddr = XPAR_PS7_ETHERNET_0_BASEADDR,
-       .emac_type = xemac_type_emacps,
-       .intc_baseaddr = 0x0,
-       .intc_emac_intr = 0x0,
-       .scugic_baseaddr = XPAR_PS7_SCUGIC_0_BASEADDR,
-       .scugic_emac_intr = 0x36,
-};
-
-XEmacPs_Config mac_config =
-{
-       .DeviceId = XPAR_PS7_ETHERNET_0_DEVICE_ID,      /**< Unique ID  of device */
-       .BaseAddress = XPAR_PS7_ETHERNET_0_BASEADDR /**< Physical base address of IPIF registers */
-};
-
-extern int phy_detected;
-
-/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */
-static uint32_t ulPHYLinkStatus = 0;
-
-#if( ipconfigUSE_LLMNR == 1 )
-       static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };
-#endif
-
-/* ucMACAddress as it appears in main.c */
-extern const uint8_t ucMACAddress[ 6 ];
-
-/* Holds the handle of the task used as a deferred interrupt processor.  The
-handle is used so direct notifications can be sent to the task for all EMAC/DMA
-related interrupts. */
-TaskHandle_t xEMACTaskHandle = NULL;
-
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceInitialise( void )
-{
-uint32_t ulLinkSpeed, ulDMAReg;
-BaseType_t xStatus, xLinkStatus;
-XEmacPs *pxEMAC_PS;
-const TickType_t xWaitLinkDelay = pdMS_TO_TICKS( 7000UL ), xWaitRelinkDelay = pdMS_TO_TICKS( 1000UL );
-
-       /* Guard against the init function being called more than once. */
-       if( xEMACTaskHandle == NULL )
-       {
-               pxEMAC_PS = &( xEMACpsif.emacps );
-               memset( &xEMACpsif, '\0', sizeof( xEMACpsif ) );
-
-               xStatus = XEmacPs_CfgInitialize( pxEMAC_PS, &mac_config, mac_config.BaseAddress);
-               if( xStatus != XST_SUCCESS )
-               {
-                       FreeRTOS_printf( ( "xEMACInit: EmacPs Configuration Failed....\n" ) );
-               }
-
-               /* Initialize the mac and set the MAC address. */
-               XEmacPs_SetMacAddress( pxEMAC_PS, ( void * ) ucMACAddress, 1 );
-
-               #if( ipconfigUSE_LLMNR == 1 )
-               {
-                       /* Also add LLMNR multicast MAC address. */
-                       XEmacPs_SetMacAddress( pxEMAC_PS, ( void * )xLLMNR_MACAddress, 2 );
-               }
-               #endif  /* ipconfigUSE_LLMNR == 1 */
-
-               XEmacPs_SetMdioDivisor( pxEMAC_PS, MDC_DIV_224 );
-               ulLinkSpeed = Phy_Setup( pxEMAC_PS );
-               XEmacPs_SetOperatingSpeed( pxEMAC_PS, ulLinkSpeed);
-
-               /* Setting the operating speed of the MAC needs a delay. */
-               vTaskDelay( pdMS_TO_TICKS( 25UL ) );
-
-               ulDMAReg = XEmacPs_ReadReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET);
-
-               /* DISC_WHEN_NO_AHB: when set, the GEM DMA will automatically discard receive
-               packets from the receiver packet buffer memory when no AHB resource is available. */
-               XEmacPs_WriteReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET,
-                       ulDMAReg | XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK);
-
-               setup_isr( &xEMACpsif );
-               init_dma( &xEMACpsif );
-               start_emacps( &xEMACpsif );
-
-               prvGMACWaitLS( xWaitLinkDelay );
-
-               /* The deferred interrupt handler task is created at the highest
-               possible priority to ensure the interrupt handler can return directly
-               to it.  The task's handle is stored in xEMACTaskHandle so interrupts can
-               notify the task when there is something to process. */
-               xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );
-       }
-       else
-       {
-               /* Initialisation was already performed, just wait for the link. */
-               prvGMACWaitLS( xWaitRelinkDelay );
-       }
-
-       /* Only return pdTRUE when the Link Status of the PHY is high, otherwise the
-       DHCP process and all other communication will fail. */
-       xLinkStatus = xGetPhyLinkStatus();
-
-       return ( xLinkStatus != pdFALSE );
-}
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxBuffer, BaseType_t bReleaseAfterSend )
-{
-       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
-       {
-               iptraceNETWORK_INTERFACE_TRANSMIT();
-               emacps_send_message( &xEMACpsif, pxBuffer, bReleaseAfterSend );
-       }
-       else if( bReleaseAfterSend != pdFALSE )
-       {
-               /* No link. */
-               vReleaseNetworkBufferAndDescriptor( pxBuffer );
-       }
-
-       return pdTRUE;
-}
-/*-----------------------------------------------------------*/
-
-static inline unsigned long ulReadMDIO( unsigned ulRegister )
-{
-uint16_t usValue;
-
-       XEmacPs_PhyRead( &( xEMACpsif.emacps ), phy_detected, ulRegister, &usValue );
-       return usValue;
-}
-/*-----------------------------------------------------------*/
-
-static BaseType_t prvGMACWaitLS( TickType_t xMaxTime )
-{
-TickType_t xStartTime, xEndTime;
-const TickType_t xShortDelay = pdMS_TO_TICKS( 20UL );
-BaseType_t xReturn;
-
-       xStartTime = xTaskGetTickCount();
-
-       for( ;; )
-       {
-               xEndTime = xTaskGetTickCount();
-
-               if( xEndTime - xStartTime > xMaxTime )
-               {
-                       xReturn = pdFALSE;
-                       break;
-               }
-               ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );
-
-               if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
-               {
-                       xReturn = pdTRUE;
-                       break;
-               }
-
-               vTaskDelay( xShortDelay );
-       }
-
-       return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
-{
-static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );
-uint8_t *ucRAMBuffer = ucNetworkPackets;
-uint32_t ul;
-
-       for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )
-       {
-               pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;
-               *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );
-               ucRAMBuffer += niBUFFER_1_PACKET_SIZE;
-       }
-}
-/*-----------------------------------------------------------*/
-
-BaseType_t xGetPhyLinkStatus( void )
-{
-BaseType_t xReturn;
-
-       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )
-       {
-               xReturn = pdFALSE;
-       }
-       else
-       {
-               xReturn = pdTRUE;
-       }
-
-       return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-static void prvEMACHandlerTask( void *pvParameters )
-{
-TimeOut_t xPhyTime;
-TickType_t xPhyRemTime;
-UBaseType_t uxLastMinBufferCount = 0;
-UBaseType_t uxCurrentCount;
-BaseType_t xResult = 0;
-uint32_t xStatus;
-const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
-
-       /* Remove compiler warnings about unused parameters. */
-       ( void ) pvParameters;
-
-       /* A possibility to set some additional task properties like calling
-       portTASK_USES_FLOATING_POINT() */
-       iptraceEMAC_TASK_STARTING();
-
-       vTaskSetTimeOutState( &xPhyTime );
-       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
-
-       for( ;; )
-       {
-               uxCurrentCount = uxGetMinimumFreeNetworkBuffers();
-               if( uxLastMinBufferCount != uxCurrentCount )
-               {
-                       /* The logging produced below may be helpful
-                       while tuning +TCP: see how many buffers are in use. */
-                       uxLastMinBufferCount = uxCurrentCount;
-                       FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
-                               uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );
-               }
-
-               #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
-               {
-               static UBaseType_t uxLastMinQueueSpace = 0;
-
-                       uxCurrentCount = uxGetMinimumIPQueueSpace();
-                       if( uxLastMinQueueSpace != uxCurrentCount )
-                       {
-                               /* The logging produced below may be helpful
-                               while tuning +TCP: see how many buffers are in use. */
-                               uxLastMinQueueSpace = uxCurrentCount;
-                               FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );
-                       }
-               }
-               #endif /* ipconfigCHECK_IP_QUEUE_SPACE */
-
-               if( ( xEMACpsif.isr_events & EMAC_IF_ALL_EVENT ) == 0 )
-               {
-                       /* No events to process now, wait for the next. */
-                       ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );
-               }
-
-               if( ( xEMACpsif.isr_events & EMAC_IF_RX_EVENT ) != 0 )
-               {
-                       xEMACpsif.isr_events &= ~EMAC_IF_RX_EVENT;
-                       xResult = emacps_check_rx( &xEMACpsif );
-               }
-
-               if( ( xEMACpsif.isr_events & EMAC_IF_TX_EVENT ) != 0 )
-               {
-                       xEMACpsif.isr_events &= ~EMAC_IF_TX_EVENT;
-                       emacps_check_tx( &xEMACpsif );
-               }
-
-               if( ( xEMACpsif.isr_events & EMAC_IF_ERR_EVENT ) != 0 )
-               {
-                       xEMACpsif.isr_events &= ~EMAC_IF_ERR_EVENT;
-                       emacps_check_errors( &xEMACpsif );
-               }
-
-               if( xResult > 0 )
-               {
-                       /* A packet was received. No need to check for the PHY status now,
-                       but set a timer to check it later on. */
-                       vTaskSetTimeOutState( &xPhyTime );
-                       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
-                       xResult = 0;
-               }
-               else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE )
-               {
-                       xStatus = ulReadMDIO( PHY_REG_01_BMSR );
-
-                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )
-                       {
-                               ulPHYLinkStatus = xStatus;
-                               FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );
-                       }
-
-                       vTaskSetTimeOutState( &xPhyTime );
-                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
-                       {
-                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
-                       }
-                       else
-                       {
-                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
-                       }
-               }
-       }
-}
-/*-----------------------------------------------------------*/
+/*\r
+FreeRTOS+TCP V2.0.11\r
+Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+this software and associated documentation files (the "Software"), to deal in\r
+the Software without restriction, including without limitation the rights to\r
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+the Software, and to permit persons to whom the Software is furnished to do so,\r
+subject to the following conditions:\r
+\r
+The above copyright notice and this permission notice shall be included in all\r
+copies or substantial portions of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+\r
+ http://aws.amazon.com/freertos\r
+ http://www.FreeRTOS.org\r
+*/\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+#include "NetworkInterface.h"\r
+\r
+/* Xilinx library files. */\r
+#include <xemacps.h>\r
+#include "Zynq/x_topology.h"\r
+#include "Zynq/x_emacpsif.h"\r
+#include "Zynq/x_emacpsif_hw.h"\r
+\r
+/* Provided memory configured as uncached. */\r
+#include "uncached_memory.h"\r
+\r
+#ifndef        BMSR_LINK_STATUS\r
+       #define BMSR_LINK_STATUS            0x0004UL\r
+#endif\r
+\r
+#ifndef        PHY_LS_HIGH_CHECK_TIME_MS\r
+       /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not\r
+       receiving packets. */\r
+       #define PHY_LS_HIGH_CHECK_TIME_MS       15000\r
+#endif\r
+\r
+#ifndef        PHY_LS_LOW_CHECK_TIME_MS\r
+       /* Check if the LinkSStatus in the PHY is still low every second. */\r
+       #define PHY_LS_LOW_CHECK_TIME_MS        1000\r
+#endif\r
+\r
+/* The size of each buffer when BufferAllocation_1 is used:\r
+http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html */\r
+#define niBUFFER_1_PACKET_SIZE         1536\r
+\r
+/* Naming and numbering of PHY registers. */\r
+#define PHY_REG_01_BMSR                        0x01    /* Basic mode status register */\r
+\r
+#ifndef iptraceEMAC_TASK_STARTING\r
+       #define iptraceEMAC_TASK_STARTING()     do { } while( 0 )\r
+#endif\r
+\r
+/* Default the size of the stack used by the EMAC deferred handler task to twice\r
+the size of the stack used by the idle task - but allow this to be overridden in\r
+FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */\r
+#ifndef configEMAC_TASK_STACK_SIZE\r
+       #define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )\r
+#endif\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Look for the link to be up every few milliseconds until either xMaxTime time\r
+ * has passed or a link is found.\r
+ */\r
+static BaseType_t prvGMACWaitLS( TickType_t xMaxTime );\r
+\r
+/*\r
+ * A deferred interrupt handler for all MAC/DMA interrupt sources.\r
+ */\r
+static void prvEMACHandlerTask( void *pvParameters );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* EMAC data/descriptions. */\r
+static xemacpsif_s xEMACpsif;\r
+struct xtopology_t xXTopology =\r
+{\r
+       .emac_baseaddr = XPAR_PS7_ETHERNET_0_BASEADDR,\r
+       .emac_type = xemac_type_emacps,\r
+       .intc_baseaddr = 0x0,\r
+       .intc_emac_intr = 0x0,\r
+       .scugic_baseaddr = XPAR_PS7_SCUGIC_0_BASEADDR,\r
+       .scugic_emac_intr = 0x36,\r
+};\r
+\r
+XEmacPs_Config mac_config =\r
+{\r
+       .DeviceId = XPAR_PS7_ETHERNET_0_DEVICE_ID,      /**< Unique ID  of device */\r
+       .BaseAddress = XPAR_PS7_ETHERNET_0_BASEADDR /**< Physical base address of IPIF registers */\r
+};\r
+\r
+extern int phy_detected;\r
+\r
+/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */\r
+static uint32_t ulPHYLinkStatus = 0;\r
+\r
+#if( ipconfigUSE_LLMNR == 1 )\r
+       static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };\r
+#endif\r
+\r
+/* ucMACAddress as it appears in main.c */\r
+extern const uint8_t ucMACAddress[ 6 ];\r
+\r
+/* Holds the handle of the task used as a deferred interrupt processor.  The\r
+handle is used so direct notifications can be sent to the task for all EMAC/DMA\r
+related interrupts. */\r
+TaskHandle_t xEMACTaskHandle = NULL;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+uint32_t ulLinkSpeed, ulDMAReg;\r
+BaseType_t xStatus, xLinkStatus;\r
+XEmacPs *pxEMAC_PS;\r
+const TickType_t xWaitLinkDelay = pdMS_TO_TICKS( 7000UL ), xWaitRelinkDelay = pdMS_TO_TICKS( 1000UL );\r
+\r
+       /* Guard against the init function being called more than once. */\r
+       if( xEMACTaskHandle == NULL )\r
+       {\r
+               pxEMAC_PS = &( xEMACpsif.emacps );\r
+               memset( &xEMACpsif, '\0', sizeof( xEMACpsif ) );\r
+\r
+               xStatus = XEmacPs_CfgInitialize( pxEMAC_PS, &mac_config, mac_config.BaseAddress);\r
+               if( xStatus != XST_SUCCESS )\r
+               {\r
+                       FreeRTOS_printf( ( "xEMACInit: EmacPs Configuration Failed....\n" ) );\r
+               }\r
+\r
+               /* Initialize the mac and set the MAC address. */\r
+               XEmacPs_SetMacAddress( pxEMAC_PS, ( void * ) ucMACAddress, 1 );\r
+\r
+               #if( ipconfigUSE_LLMNR == 1 )\r
+               {\r
+                       /* Also add LLMNR multicast MAC address. */\r
+                       XEmacPs_SetMacAddress( pxEMAC_PS, ( void * )xLLMNR_MACAddress, 2 );\r
+               }\r
+               #endif  /* ipconfigUSE_LLMNR == 1 */\r
+\r
+               XEmacPs_SetMdioDivisor( pxEMAC_PS, MDC_DIV_224 );\r
+               ulLinkSpeed = Phy_Setup( pxEMAC_PS );\r
+               XEmacPs_SetOperatingSpeed( pxEMAC_PS, ulLinkSpeed);\r
+\r
+               /* Setting the operating speed of the MAC needs a delay. */\r
+               vTaskDelay( pdMS_TO_TICKS( 25UL ) );\r
+\r
+               ulDMAReg = XEmacPs_ReadReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET);\r
+\r
+               /* DISC_WHEN_NO_AHB: when set, the GEM DMA will automatically discard receive\r
+               packets from the receiver packet buffer memory when no AHB resource is available. */\r
+               XEmacPs_WriteReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET,\r
+                       ulDMAReg | XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK);\r
+\r
+               setup_isr( &xEMACpsif );\r
+               init_dma( &xEMACpsif );\r
+               start_emacps( &xEMACpsif );\r
+\r
+               prvGMACWaitLS( xWaitLinkDelay );\r
+\r
+               /* The deferred interrupt handler task is created at the highest\r
+               possible priority to ensure the interrupt handler can return directly\r
+               to it.  The task's handle is stored in xEMACTaskHandle so interrupts can\r
+               notify the task when there is something to process. */\r
+               xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );\r
+       }\r
+       else\r
+       {\r
+               /* Initialisation was already performed, just wait for the link. */\r
+               prvGMACWaitLS( xWaitRelinkDelay );\r
+       }\r
+\r
+       /* Only return pdTRUE when the Link Status of the PHY is high, otherwise the\r
+       DHCP process and all other communication will fail. */\r
+       xLinkStatus = xGetPhyLinkStatus();\r
+\r
+       return ( xLinkStatus != pdFALSE );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxBuffer, BaseType_t bReleaseAfterSend )\r
+{\r
+       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+       {\r
+               iptraceNETWORK_INTERFACE_TRANSMIT();\r
+               emacps_send_message( &xEMACpsif, pxBuffer, bReleaseAfterSend );\r
+       }\r
+       else if( bReleaseAfterSend != pdFALSE )\r
+       {\r
+               /* No link. */\r
+               vReleaseNetworkBufferAndDescriptor( pxBuffer );\r
+       }\r
+\r
+       return pdTRUE;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static inline unsigned long ulReadMDIO( unsigned ulRegister )\r
+{\r
+uint16_t usValue;\r
+\r
+       XEmacPs_PhyRead( &( xEMACpsif.emacps ), phy_detected, ulRegister, &usValue );\r
+       return usValue;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvGMACWaitLS( TickType_t xMaxTime )\r
+{\r
+TickType_t xStartTime, xEndTime;\r
+const TickType_t xShortDelay = pdMS_TO_TICKS( 20UL );\r
+BaseType_t xReturn;\r
+\r
+       xStartTime = xTaskGetTickCount();\r
+\r
+       for( ;; )\r
+       {\r
+               xEndTime = xTaskGetTickCount();\r
+\r
+               if( xEndTime - xStartTime > xMaxTime )\r
+               {\r
+                       xReturn = pdFALSE;\r
+                       break;\r
+               }\r
+               ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );\r
+\r
+               if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+               {\r
+                       xReturn = pdTRUE;\r
+                       break;\r
+               }\r
+\r
+               vTaskDelay( xShortDelay );\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )\r
+{\r
+static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );\r
+uint8_t *ucRAMBuffer = ucNetworkPackets;\r
+uint32_t ul;\r
+\r
+       for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )\r
+       {\r
+               pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;\r
+               *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );\r
+               ucRAMBuffer += niBUFFER_1_PACKET_SIZE;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xGetPhyLinkStatus( void )\r
+{\r
+BaseType_t xReturn;\r
+\r
+       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )\r
+       {\r
+               xReturn = pdFALSE;\r
+       }\r
+       else\r
+       {\r
+               xReturn = pdTRUE;\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvEMACHandlerTask( void *pvParameters )\r
+{\r
+TimeOut_t xPhyTime;\r
+TickType_t xPhyRemTime;\r
+UBaseType_t uxLastMinBufferCount = 0;\r
+UBaseType_t uxCurrentCount;\r
+BaseType_t xResult = 0;\r
+uint32_t xStatus;\r
+const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );\r
+\r
+       /* Remove compiler warnings about unused parameters. */\r
+       ( void ) pvParameters;\r
+\r
+       /* A possibility to set some additional task properties like calling\r
+       portTASK_USES_FLOATING_POINT() */\r
+       iptraceEMAC_TASK_STARTING();\r
+\r
+       vTaskSetTimeOutState( &xPhyTime );\r
+       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+\r
+       for( ;; )\r
+       {\r
+               uxCurrentCount = uxGetMinimumFreeNetworkBuffers();\r
+               if( uxLastMinBufferCount != uxCurrentCount )\r
+               {\r
+                       /* The logging produced below may be helpful\r
+                       while tuning +TCP: see how many buffers are in use. */\r
+                       uxLastMinBufferCount = uxCurrentCount;\r
+                       FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",\r
+                               uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );\r
+               }\r
+\r
+               #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+               {\r
+               static UBaseType_t uxLastMinQueueSpace = 0;\r
+\r
+                       uxCurrentCount = uxGetMinimumIPQueueSpace();\r
+                       if( uxLastMinQueueSpace != uxCurrentCount )\r
+                       {\r
+                               /* The logging produced below may be helpful\r
+                               while tuning +TCP: see how many buffers are in use. */\r
+                               uxLastMinQueueSpace = uxCurrentCount;\r
+                               FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );\r
+                       }\r
+               }\r
+               #endif /* ipconfigCHECK_IP_QUEUE_SPACE */\r
+\r
+               if( ( xEMACpsif.isr_events & EMAC_IF_ALL_EVENT ) == 0 )\r
+               {\r
+                       /* No events to process now, wait for the next. */\r
+                       ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );\r
+               }\r
+\r
+               if( ( xEMACpsif.isr_events & EMAC_IF_RX_EVENT ) != 0 )\r
+               {\r
+                       xEMACpsif.isr_events &= ~EMAC_IF_RX_EVENT;\r
+                       xResult = emacps_check_rx( &xEMACpsif );\r
+               }\r
+\r
+               if( ( xEMACpsif.isr_events & EMAC_IF_TX_EVENT ) != 0 )\r
+               {\r
+                       xEMACpsif.isr_events &= ~EMAC_IF_TX_EVENT;\r
+                       emacps_check_tx( &xEMACpsif );\r
+               }\r
+\r
+               if( ( xEMACpsif.isr_events & EMAC_IF_ERR_EVENT ) != 0 )\r
+               {\r
+                       xEMACpsif.isr_events &= ~EMAC_IF_ERR_EVENT;\r
+                       emacps_check_errors( &xEMACpsif );\r
+               }\r
+\r
+               if( xResult > 0 )\r
+               {\r
+                       /* A packet was received. No need to check for the PHY status now,\r
+                       but set a timer to check it later on. */\r
+                       vTaskSetTimeOutState( &xPhyTime );\r
+                       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+                       xResult = 0;\r
+               }\r
+               else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE )\r
+               {\r
+                       xStatus = ulReadMDIO( PHY_REG_01_BMSR );\r
+\r
+                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )\r
+                       {\r
+                               ulPHYLinkStatus = xStatus;\r
+                               FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );\r
+                       }\r
+\r
+                       vTaskSetTimeOutState( &xPhyTime );\r
+                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+                       {\r
+                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+                       }\r
+                       else\r
+                       {\r
+                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+                       }\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
index 2f1b0df2041aaf60a6fab860bf08700b0991a503..823dee0d30a79dbae2ff7c2bfd7f3a9136e17861 100644 (file)
-/*
- * Copyright (c) 2010-2013 Xilinx, Inc.  All rights reserved.
- *
- * Xilinx, Inc.
- * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
- * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
- * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
- * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
- * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
- * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
- * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
- * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
- * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
- * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-#ifndef __NETIF_XEMACPSIF_H__
-#define __NETIF_XEMACPSIF_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdint.h>
-
-#include "xstatus.h"
-#include "sleep.h"
-#include "xparameters.h"
-#include "xparameters_ps.h"    /* defines XPAR values */
-#include "xil_types.h"
-#include "xil_assert.h"
-#include "xil_io.h"
-#include "xil_exception.h"
-#include "xpseudo_asm.h"
-#include "xil_cache.h"
-#include "xil_printf.h"
-#include "xuartps.h"
-#include "xscugic.h"
-#include "xemacps.h"           /* defines XEmacPs API */
-
-//#include "netif/xpqueue.h"
-//#include "xlwipconfig.h"
-
-void   xemacpsif_setmac(uint32_t index, uint8_t *addr);
-uint8_t*       xemacpsif_getmac(uint32_t index);
-//int  xemacpsif_init(struct netif *netif);
-//int  xemacpsif_input(struct netif *netif);
-#ifdef NOTNOW_BHILL
-unsigned get_IEEE_phy_speed(XLlTemac *xlltemacp);
-#endif
-
-/* xaxiemacif_hw.c */
-void   xemacps_error_handler(XEmacPs * Temac);
-
-struct xBD_TYPE {
-       uint32_t address;
-       uint32_t flags;
-};
-
-/*
- * Missing declaration in 'src/xemacps_hw.h' :
- * When set, the GEM DMA will automatically
- * discard receive packets from the receiver packet
- * buffer memory when no AHB resource is
- * available.
- * When low, then received packets will remain to be
- * stored in the SRAM based packet buffer until
- * AHB buffer resource next becomes available.
- */
-#define XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK            0x01000000
-
-#define EMAC_IF_RX_EVENT       1
-#define EMAC_IF_TX_EVENT       2
-#define EMAC_IF_ERR_EVENT      4
-#define EMAC_IF_ALL_EVENT      7
-
-/* structure within each netif, encapsulating all information required for
- * using a particular temac instance
- */
-typedef struct {
-       XEmacPs emacps;
-
-       /* pointers to memory holding buffer descriptors (used only with SDMA) */
-       struct xBD_TYPE *rxSegments;
-       struct xBD_TYPE *txSegments;
-
-       unsigned char *tx_space;
-       unsigned uTxUnitSize;
-
-       char *remain_mem;
-       unsigned remain_siz;
-
-       volatile int rxHead, rxTail;
-       volatile int txHead, txTail;
-
-       volatile int txBusy;
-
-       volatile uint32_t isr_events;
-
-       unsigned int last_rx_frms_cntr;
-
-} xemacpsif_s;
-
-//extern xemacpsif_s xemacpsif;
-
-int    is_tx_space_available(xemacpsif_s *emac);
-
-/* xaxiemacif_dma.c */
-
-struct xNETWORK_BUFFER;
-
-int emacps_check_rx( xemacpsif_s *xemacpsif );
-void emacps_check_tx( xemacpsif_s *xemacpsif );
-int emacps_check_errors( xemacpsif_s *xemacps );
-void emacps_set_rx_buffers( xemacpsif_s *xemacpsif, u32 ulCount );
-
-extern XStatus emacps_send_message(xemacpsif_s *xemacpsif, struct xNETWORK_BUFFER *pxBuffer, int iReleaseAfterSend );
-extern unsigned Phy_Setup( XEmacPs *xemacpsp );
-extern void setup_isr( xemacpsif_s *xemacpsif );
-extern XStatus init_dma( xemacpsif_s *xemacpsif );
-extern void start_emacps( xemacpsif_s *xemacpsif );
-
-void EmacEnableIntr(void);
-void EmacDisableIntr(void);
-
-XStatus init_axi_dma(xemacpsif_s *xemacpsif);
-void process_sent_bds( xemacpsif_s *xemacpsif );
-
-void emacps_send_handler(void *arg);
-void emacps_recv_handler(void *arg);
-void emacps_error_handler(void *arg,u8 Direction, u32 ErrorWord);
-void HandleTxErrors(xemacpsif_s *xemacpsif);
-XEmacPs_Config *xemacps_lookup_config(unsigned mac_base);
-
-void clean_dma_txdescs(xemacpsif_s *xemacpsif);
-void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __NETIF_XAXIEMACIF_H__ */
+/*\r
+ * Copyright (c) 2010-2013 Xilinx, Inc.  All rights reserved.\r
+ *\r
+ * Xilinx, Inc.\r
+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A\r
+ * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS\r
+ * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR\r
+ * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION\r
+ * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE\r
+ * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.\r
+ * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO\r
+ * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO\r
+ * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE\r
+ * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY\r
+ * AND FITNESS FOR A PARTICULAR PURPOSE.\r
+ *\r
+ */\r
+\r
+#ifndef __NETIF_XEMACPSIF_H__\r
+#define __NETIF_XEMACPSIF_H__\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#include <stdint.h>\r
+\r
+#include "xstatus.h"\r
+#include "sleep.h"\r
+#include "xparameters.h"\r
+#include "xparameters_ps.h"    /* defines XPAR values */\r
+#include "xil_types.h"\r
+#include "xil_assert.h"\r
+#include "xil_io.h"\r
+#include "xil_exception.h"\r
+#include "xpseudo_asm.h"\r
+#include "xil_cache.h"\r
+#include "xil_printf.h"\r
+#include "xuartps.h"\r
+#include "xscugic.h"\r
+#include "xemacps.h"           /* defines XEmacPs API */\r
+\r
+//#include "netif/xpqueue.h"\r
+//#include "xlwipconfig.h"\r
+\r
+void   xemacpsif_setmac(uint32_t index, uint8_t *addr);\r
+uint8_t*       xemacpsif_getmac(uint32_t index);\r
+//int  xemacpsif_init(struct netif *netif);\r
+//int  xemacpsif_input(struct netif *netif);\r
+#ifdef NOTNOW_BHILL\r
+unsigned get_IEEE_phy_speed(XLlTemac *xlltemacp);\r
+#endif\r
+\r
+/* xaxiemacif_hw.c */\r
+void   xemacps_error_handler(XEmacPs * Temac);\r
+\r
+struct xBD_TYPE {\r
+       uint32_t address;\r
+       uint32_t flags;\r
+};\r
+\r
+/*\r
+ * Missing declaration in 'src/xemacps_hw.h' :\r
+ * When set, the GEM DMA will automatically\r
+ * discard receive packets from the receiver packet\r
+ * buffer memory when no AHB resource is\r
+ * available.\r
+ * When low, then received packets will remain to be\r
+ * stored in the SRAM based packet buffer until\r
+ * AHB buffer resource next becomes available.\r
+ */\r
+#define XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK            0x01000000\r
+\r
+#define EMAC_IF_RX_EVENT       1\r
+#define EMAC_IF_TX_EVENT       2\r
+#define EMAC_IF_ERR_EVENT      4\r
+#define EMAC_IF_ALL_EVENT      7\r
+\r
+/* structure within each netif, encapsulating all information required for\r
+ * using a particular temac instance\r
+ */\r
+typedef struct {\r
+       XEmacPs emacps;\r
+\r
+       /* pointers to memory holding buffer descriptors (used only with SDMA) */\r
+       struct xBD_TYPE *rxSegments;\r
+       struct xBD_TYPE *txSegments;\r
+\r
+       unsigned char *tx_space;\r
+       unsigned uTxUnitSize;\r
+\r
+       char *remain_mem;\r
+       unsigned remain_siz;\r
+\r
+       volatile int rxHead, rxTail;\r
+       volatile int txHead, txTail;\r
+\r
+       volatile int txBusy;\r
+\r
+       volatile uint32_t isr_events;\r
+\r
+       unsigned int last_rx_frms_cntr;\r
+\r
+} xemacpsif_s;\r
+\r
+//extern xemacpsif_s xemacpsif;\r
+\r
+int    is_tx_space_available(xemacpsif_s *emac);\r
+\r
+/* xaxiemacif_dma.c */\r
+\r
+struct xNETWORK_BUFFER;\r
+\r
+int emacps_check_rx( xemacpsif_s *xemacpsif );\r
+void emacps_check_tx( xemacpsif_s *xemacpsif );\r
+int emacps_check_errors( xemacpsif_s *xemacps );\r
+void emacps_set_rx_buffers( xemacpsif_s *xemacpsif, u32 ulCount );\r
+\r
+extern XStatus emacps_send_message(xemacpsif_s *xemacpsif, struct xNETWORK_BUFFER *pxBuffer, int iReleaseAfterSend );\r
+extern unsigned Phy_Setup( XEmacPs *xemacpsp );\r
+extern void setup_isr( xemacpsif_s *xemacpsif );\r
+extern XStatus init_dma( xemacpsif_s *xemacpsif );\r
+extern void start_emacps( xemacpsif_s *xemacpsif );\r
+\r
+void EmacEnableIntr(void);\r
+void EmacDisableIntr(void);\r
+\r
+XStatus init_axi_dma(xemacpsif_s *xemacpsif);\r
+void process_sent_bds( xemacpsif_s *xemacpsif );\r
+\r
+void emacps_send_handler(void *arg);\r
+void emacps_recv_handler(void *arg);\r
+void emacps_error_handler(void *arg,u8 Direction, u32 ErrorWord);\r
+void HandleTxErrors(xemacpsif_s *xemacpsif);\r
+XEmacPs_Config *xemacps_lookup_config(unsigned mac_base);\r
+\r
+void clean_dma_txdescs(xemacpsif_s *xemacpsif);\r
+void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif /* __NETIF_XAXIEMACIF_H__ */\r
index 13a62852d4de046ef505ce189a59e6f49d0879cd..fc09d218335022fd0750a72d6ceb635138ca90e7 100644 (file)
-/*
-FreeRTOS+TCP V2.0.11
-Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
- http://aws.amazon.com/freertos
- http://www.FreeRTOS.org
-*/
-
-#include "Zynq/x_emacpsif.h"
-#include "Zynq/x_topology.h"
-#include "xstatus.h"
-
-#include "xparameters.h"
-#include "xparameters_ps.h"
-#include "xil_exception.h"
-#include "xil_mmu.h"
-
-#include "FreeRTOS.h"
-#include "task.h"
-#include "timers.h"
-#include "semphr.h"
-
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_Sockets.h"
-#include "FreeRTOS_IP_Private.h"
-#include "NetworkBufferManagement.h"
-
-#include "uncached_memory.h"
-
-/* Two defines used to set or clear the EMAC interrupt */
-#define INTC_BASE_ADDR         XPAR_SCUGIC_CPU_BASEADDR
-#define INTC_DIST_BASE_ADDR    XPAR_SCUGIC_DIST_BASEADDR
-
-
-
-#if( ipconfigPACKET_FILLER_SIZE != 2 )
-       #error Please define ipconfigPACKET_FILLER_SIZE as the value '2'
-#endif
-#define TX_OFFSET                              ipconfigPACKET_FILLER_SIZE
-
-#define RX_BUFFER_ALIGNMENT    14
-
-/* Defined in NetworkInterface.c */
-extern TaskHandle_t xEMACTaskHandle;
-
-/*
-       pxDMA_tx_buffers: these are character arrays, each one is big enough to hold 1 MTU.
-       The actual TX buffers are located in uncached RAM.
-*/
-static unsigned char *pxDMA_tx_buffers[ ipconfigNIC_N_TX_DESC ] = { NULL };
-
-/*
-       pxDMA_rx_buffers: these are pointers to 'NetworkBufferDescriptor_t'.
-       Once a message has been received by the EMAC, the descriptor can be passed
-       immediately to the IP-task.
-*/
-static NetworkBufferDescriptor_t *pxDMA_rx_buffers[ ipconfigNIC_N_RX_DESC ] = { NULL };
-
-/*
-       The FreeRTOS+TCP port is using a fixed 'topology', which is declared in
-       ./portable/NetworkInterface/Zynq/NetworkInterface.c
-*/
-extern struct xtopology_t xXTopology;
-
-static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;
-
-/*
-       The FreeRTOS+TCP port does not make use of "src/xemacps_bdring.c".
-       In stead 'struct xemacpsif_s' has a "head" and a "tail" index.
-       "head" is the next index to be written, used.
-       "tail" is the next index to be read, freed.
-*/
-
-int is_tx_space_available( xemacpsif_s *xemacpsif )
-{
-size_t uxCount;
-
-       if( xTXDescriptorSemaphore != NULL )
-       {
-               uxCount = ( ( UBaseType_t ) ipconfigNIC_N_TX_DESC ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );
-       }
-       else
-       {
-               uxCount = ( UBaseType_t ) 0u;
-       }
-
-       return uxCount;
-}
-
-void emacps_check_tx( xemacpsif_s *xemacpsif )
-{
-int tail = xemacpsif->txTail;
-int head = xemacpsif->txHead;
-size_t uxCount = ( ( UBaseType_t ) ipconfigNIC_N_TX_DESC ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );
-
-       /* uxCount is the number of TX descriptors that are in use by the DMA. */
-       /* When done, "TXBUF_USED" will be set. */
-
-       while( ( uxCount > 0 ) && ( ( xemacpsif->txSegments[ tail ].flags & XEMACPS_TXBUF_USED_MASK ) != 0 ) )
-       {
-               if( ( tail == head ) && ( uxCount != ipconfigNIC_N_TX_DESC ) )
-               {
-                       break;
-               }
-#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
-#warning ipconfigZERO_COPY_TX_DRIVER is defined
-               {
-               void *pvBuffer = pxDMA_tx_buffers[ tail ];
-               NetworkBufferDescriptor_t *pxBuffer;
-
-                       if( pvBuffer != NULL )
-                       {
-                               pxDMA_tx_buffers[ tail ] = NULL;
-                               pxBuffer = pxPacketBuffer_to_NetworkBuffer( pvBuffer );
-                               if( pxBuffer != NULL )
-                               {
-                                       vReleaseNetworkBufferAndDescriptor( pxBuffer );
-                               }
-                               else
-                               {
-                                       FreeRTOS_printf( ( "emacps_check_tx: Can not find network buffer\n" ) );
-                               }
-                       }
-               }
-#endif
-               /* Clear all but the "used" and "wrap" bits. */
-               if( tail < ipconfigNIC_N_TX_DESC - 1 )
-               {
-                       xemacpsif->txSegments[ tail ].flags = XEMACPS_TXBUF_USED_MASK;
-               }
-               else
-               {
-                       xemacpsif->txSegments[ tail ].flags = XEMACPS_TXBUF_USED_MASK | XEMACPS_TXBUF_WRAP_MASK;
-               }
-               uxCount--;
-               /* Tell the counting semaphore that one more TX descriptor is available. */
-               xSemaphoreGive( xTXDescriptorSemaphore );
-               if( ++tail == ipconfigNIC_N_TX_DESC )
-               {
-                       tail = 0;
-               }
-               xemacpsif->txTail = tail;
-       }
-
-       return;
-}
-
-void emacps_send_handler(void *arg)
-{
-xemacpsif_s   *xemacpsif;
-BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-
-       xemacpsif = (xemacpsif_s *)(arg);
-
-       /* In this port for FreeRTOS+TCP, the EMAC interrupts will only set a bit in
-       "isr_events". The task in NetworkInterface will wake-up and do the necessary work.
-       */
-       xemacpsif->isr_events |= EMAC_IF_TX_EVENT;
-       xemacpsif->txBusy = pdFALSE;
-
-       if( xEMACTaskHandle != NULL )
-       {
-               vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
-       }
-
-       portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
-}
-
-static BaseType_t xValidLength( BaseType_t xLength )
-{
-BaseType_t xReturn;
-
-       if( ( xLength >= ( BaseType_t ) sizeof( struct xARP_PACKET ) ) && ( ( ( uint32_t ) xLength ) <= ipTOTAL_ETHERNET_FRAME_SIZE ) )
-       {
-               xReturn = pdTRUE;
-       }
-       else
-       {
-               xReturn =  pdFALSE;
-       }
-
-       return xReturn;
-}
-
-XStatus emacps_send_message(xemacpsif_s *xemacpsif, NetworkBufferDescriptor_t *pxBuffer, int iReleaseAfterSend )
-{
-int head = xemacpsif->txHead;
-int iHasSent = 0;
-uint32_t ulBaseAddress = xemacpsif->emacps.Config.BaseAddress;
-TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 5000u );
-
-       #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
-       {
-               /* This driver wants to own all network buffers which are to be transmitted. */
-               configASSERT( iReleaseAfterSend != pdFALSE );
-       }
-       #endif
-
-       /* Open a do {} while ( 0 ) loop to be able to call break. */
-       do
-       {
-       uint32_t ulFlags = 0;
-
-               if( xValidLength( pxBuffer->xDataLength ) != pdTRUE )
-               {
-                       break;
-               }
-
-               if( xTXDescriptorSemaphore == NULL )
-               {
-                       break;
-               }
-
-               if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )
-               {
-                       FreeRTOS_printf( ( "emacps_send_message: Time-out waiting for TX buffer\n" ) );
-                       break;
-               }
-
-#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
-               /* Pass the pointer (and its ownership) directly to DMA. */
-               pxDMA_tx_buffers[ head ] = pxBuffer->pucEthernetBuffer;
-               if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 )
-               {
-                       Xil_DCacheFlushRange( ( unsigned )pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength );
-               }
-               /* Buffer has been transferred, do not release it. */
-               iReleaseAfterSend = pdFALSE;
-#else
-               if( pxDMA_tx_buffers[ head ] == NULL )
-               {
-                       FreeRTOS_printf( ( "emacps_send_message: pxDMA_tx_buffers[ %d ] == NULL\n", head ) );
-                       break;
-               }
-               /* Copy the message to unbuffered space in RAM. */
-               memcpy( pxDMA_tx_buffers[ head ], pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength );
-#endif
-               /* Packets will be sent one-by-one, so for each packet
-               the TXBUF_LAST bit will be set. */
-               ulFlags |= XEMACPS_TXBUF_LAST_MASK;
-               ulFlags |= ( pxBuffer->xDataLength & XEMACPS_TXBUF_LEN_MASK );
-               if( head == ( ipconfigNIC_N_TX_DESC - 1 ) )
-               {
-                       ulFlags |= XEMACPS_TXBUF_WRAP_MASK;
-               }
-
-               /* Copy the address of the buffer and set the flags. */
-               xemacpsif->txSegments[ head ].address = ( uint32_t )pxDMA_tx_buffers[ head ];
-               xemacpsif->txSegments[ head ].flags = ulFlags;
-
-               iHasSent = pdTRUE;
-               if( ++head == ipconfigNIC_N_TX_DESC )
-               {
-                       head = 0;
-               }
-               /* Update the TX-head index. These variable are declared volatile so they will be
-               accessed as little as possible. */
-               xemacpsif->txHead = head;
-       } while( pdFALSE );
-
-       if( iReleaseAfterSend != pdFALSE )
-       {
-               vReleaseNetworkBufferAndDescriptor( pxBuffer );
-               pxBuffer = NULL;
-       }
-
-       /* Data Synchronization Barrier */
-       dsb();
-
-       if( iHasSent != pdFALSE )
-       {
-               /* Make STARTTX high */
-               uint32_t ulValue = XEmacPs_ReadReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET);
-               /* Start transmit */
-               xemacpsif->txBusy = pdTRUE;
-               XEmacPs_WriteReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET, ( ulValue | XEMACPS_NWCTRL_STARTTX_MASK ) );
-       }
-       dsb();
-
-       return 0;
-}
-
-void emacps_recv_handler(void *arg)
-{
-       xemacpsif_s *xemacpsif;
-       BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-
-       xemacpsif = (xemacpsif_s *)(arg);
-       xemacpsif->isr_events |= EMAC_IF_RX_EVENT;
-
-       if( xEMACTaskHandle != NULL )
-       {
-               vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
-       }
-
-       portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
-}
-
-static NetworkBufferDescriptor_t *ethMsg = NULL;
-static NetworkBufferDescriptor_t *ethLast = NULL;
-
-static void passEthMessages( void )
-{
-IPStackEvent_t xRxEvent;
-
-       xRxEvent.eEventType = eNetworkRxEvent;
-       xRxEvent.pvData = ( void * ) ethMsg;
-
-       if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 1000 ) != pdPASS )
-       {
-               /* The buffer could not be sent to the stack so must be released again.
-               This is a deferred handler taskr, not a real interrupt, so it is ok to
-               use the task level function here. */
-               do
-               {
-                       NetworkBufferDescriptor_t *xNext = ethMsg->pxNextBuffer;
-                       vReleaseNetworkBufferAndDescriptor( ethMsg );
-                       ethMsg = xNext;
-               } while( ethMsg != NULL );
-
-               iptraceETHERNET_RX_EVENT_LOST();
-               FreeRTOS_printf( ( "passEthMessages: Can not queue return packet!\n" ) );
-       }
-
-       ethMsg = ethLast = NULL;
-}
-
-int emacps_check_rx( xemacpsif_s *xemacpsif )
-{
-NetworkBufferDescriptor_t *pxBuffer, *pxNewBuffer;
-int rx_bytes;
-volatile int msgCount = 0;
-int head = xemacpsif->rxHead;
-
-       /* There seems to be an issue (SI# 692601), see comments below. */
-       resetrx_on_no_rxdata(xemacpsif);
-
-       /* This FreeRTOS+TCP driver shall be compiled with the option
-       "ipconfigUSE_LINKED_RX_MESSAGES" enabled.  It allows the driver to send a
-       chain of RX messages within one message to the IP-task. */
-       for( ;; )
-       {
-               if( ( ( xemacpsif->rxSegments[ head ].address & XEMACPS_RXBUF_NEW_MASK ) == 0 ) ||
-                       ( pxDMA_rx_buffers[ head ] == NULL ) )
-               {
-                       break;
-               }
-
-               pxNewBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT, ( TickType_t ) 0 );
-               if( pxNewBuffer == NULL )
-               {
-                       /* A packet has been received, but there is no replacement for this Network Buffer.
-                       The packet will be dropped, and it Network Buffer will stay in place. */
-                       FreeRTOS_printf( ("emacps_check_rx: unable to allocate a Netwrok Buffer\n" ) );
-                       pxNewBuffer = ( NetworkBufferDescriptor_t * )pxDMA_rx_buffers[ head ];
-               }
-               else
-               {
-                       pxBuffer = ( NetworkBufferDescriptor_t * )pxDMA_rx_buffers[ head ];
-
-                       /* Just avoiding to use or refer to the same buffer again */
-                       pxDMA_rx_buffers[ head ] = pxNewBuffer;
-
-                       /*
-                        * Adjust the buffer size to the actual number of bytes received.
-                        */
-                       rx_bytes = xemacpsif->rxSegments[ head ].flags & XEMACPS_RXBUF_LEN_MASK;
-
-                       pxBuffer->xDataLength = rx_bytes;
-
-                       if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 )
-                       {
-                               Xil_DCacheInvalidateRange( ( ( uint32_t )pxBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE, (unsigned)rx_bytes );
-                       }
-
-                       /* store it in the receive queue, where it'll be processed by a
-                       different handler. */
-                       iptraceNETWORK_INTERFACE_RECEIVE();
-                       pxBuffer->pxNextBuffer = NULL;
-
-                       if( ethMsg == NULL )
-                       {
-                               // Becomes the first message
-                               ethMsg = pxBuffer;
-                       }
-                       else if( ethLast != NULL )
-                       {
-                               // Add to the tail
-                               ethLast->pxNextBuffer = pxBuffer;
-                       }
-
-                       ethLast = pxBuffer;
-                       msgCount++;
-               }
-               {
-                       if( ucIsCachedMemory( pxNewBuffer->pucEthernetBuffer ) != 0 )
-                       {
-                               Xil_DCacheInvalidateRange( ( ( uint32_t )pxNewBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE, (unsigned)ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT);
-                       }
-                       {
-                               uint32_t addr = ( ( uint32_t )pxNewBuffer->pucEthernetBuffer ) & XEMACPS_RXBUF_ADD_MASK;
-                               if( head == ( ipconfigNIC_N_RX_DESC - 1 ) )
-                               {
-                                       addr |= XEMACPS_RXBUF_WRAP_MASK;
-                               }
-                               /* Clearing 'XEMACPS_RXBUF_NEW_MASK'       0x00000001 *< Used bit.. */
-                               xemacpsif->rxSegments[ head ].address = addr;
-                               xemacpsif->rxSegments[ head ].flags = 0;
-                       }
-               }
-
-               if( ++head == ipconfigNIC_N_RX_DESC )
-               {
-                       head = 0;
-               }
-               xemacpsif->rxHead = head;
-       }
-
-       if( ethMsg != NULL )
-       {
-               passEthMessages( );
-       }
-
-       return msgCount;
-}
-
-void clean_dma_txdescs(xemacpsif_s *xemacpsif)
-{
-int index;
-unsigned char *ucTxBuffer;
-
-       /* Clear all TX descriptors and assign uncached memory to each descriptor.
-       "tx_space" points to the first available TX buffer. */
-       ucTxBuffer = xemacpsif->tx_space;
-
-       for( index = 0; index < ipconfigNIC_N_TX_DESC; index++ )
-       {
-               xemacpsif->txSegments[ index ].address = ( uint32_t )ucTxBuffer;
-               xemacpsif->txSegments[ index ].flags = XEMACPS_TXBUF_USED_MASK;
-#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
-               pxDMA_tx_buffers[ index ] = ( void* )NULL;
-#else
-               pxDMA_tx_buffers[ index ] = ( void* )( ucTxBuffer + TX_OFFSET );
-#endif
-               ucTxBuffer += xemacpsif->uTxUnitSize;
-       }
-       xemacpsif->txSegments[ ipconfigNIC_N_TX_DESC - 1 ].flags =
-               XEMACPS_TXBUF_USED_MASK | XEMACPS_TXBUF_WRAP_MASK;
-}
-
-XStatus init_dma(xemacpsif_s *xemacpsif)
-{
-       NetworkBufferDescriptor_t *pxBuffer;
-
-       int iIndex;
-       UBaseType_t xRxSize;
-       UBaseType_t xTxSize;
-       struct xtopology_t *xtopologyp = &xXTopology;
-
-       xRxSize = ipconfigNIC_N_RX_DESC * sizeof( xemacpsif->rxSegments[ 0 ] );
-
-       xTxSize = ipconfigNIC_N_TX_DESC * sizeof( xemacpsif->txSegments[ 0 ] );
-
-       /* Also round-up to 4KB */
-       xemacpsif->uTxUnitSize = ( ipTOTAL_ETHERNET_FRAME_SIZE + 0x1000ul ) & ~0xffful;
-       /*
-        * We allocate 65536 bytes for RX BDs which can accommodate a
-        * maximum of 8192 BDs which is much more than any application
-        * will ever need.
-        */
-       xemacpsif->rxSegments = ( struct xBD_TYPE * )( pucGetUncachedMemory ( xRxSize )  );
-       xemacpsif->txSegments = ( struct xBD_TYPE * )( pucGetUncachedMemory ( xTxSize ) );
-       xemacpsif->tx_space   = ( unsigned char *   )( pucGetUncachedMemory ( ipconfigNIC_N_TX_DESC * xemacpsif->uTxUnitSize ) );
-
-       /* These variables will be used in XEmacPs_Start (see src/xemacps.c). */
-       xemacpsif->emacps.RxBdRing.BaseBdAddr = ( uint32_t ) xemacpsif->rxSegments;
-       xemacpsif->emacps.TxBdRing.BaseBdAddr = ( uint32_t ) xemacpsif->txSegments;
-
-       if( xTXDescriptorSemaphore == NULL )
-       {
-               xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ipconfigNIC_N_TX_DESC, ( UBaseType_t ) ipconfigNIC_N_TX_DESC );
-               configASSERT( xTXDescriptorSemaphore );
-       }
-       /*
-        * Allocate RX descriptors, 1 RxBD at a time.
-        */
-       for( iIndex = 0; iIndex < ipconfigNIC_N_RX_DESC; iIndex++ )
-       {
-               pxBuffer = pxDMA_rx_buffers[ iIndex ];
-               if( pxBuffer == NULL )
-               {
-                       pxBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT, ( TickType_t ) 0 );
-                       if( pxBuffer == NULL )
-                       {
-                               FreeRTOS_printf( ("Unable to allocate a network buffer in recv_handler\n" ) );
-                               return -1;
-                       }
-               }
-
-               xemacpsif->rxSegments[ iIndex ].flags = 0;
-               xemacpsif->rxSegments[ iIndex ].address = ( ( uint32_t )pxBuffer->pucEthernetBuffer ) & XEMACPS_RXBUF_ADD_MASK;
-
-               pxDMA_rx_buffers[ iIndex ] = pxBuffer;
-               /* Make sure this memory is not in cache for now. */
-               if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 )
-               {
-                       Xil_DCacheInvalidateRange( ( ( uint32_t )pxBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE,
-                               (unsigned)ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT);
-               }
-       }
-
-       xemacpsif->rxSegments[ ipconfigNIC_N_RX_DESC - 1 ].address |= XEMACPS_RXBUF_WRAP_MASK;
-
-       memset( xemacpsif->tx_space, '\0', ipconfigNIC_N_TX_DESC * xemacpsif->uTxUnitSize );
-
-       clean_dma_txdescs( xemacpsif );
-
-       {
-               uint32_t value;
-               value = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_DMACR_OFFSET );
-
-               // 1xxxx: Attempt to use INCR16 AHB bursts
-               value = ( value & ~( XEMACPS_DMACR_BLENGTH_MASK ) ) | XEMACPS_DMACR_INCR16_AHB_BURST;
-#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )
-               value |= XEMACPS_DMACR_TCPCKSUM_MASK;
-#else
-#warning Are you sure the EMAC should not calculate outgoing checksums?
-               value &= ~XEMACPS_DMACR_TCPCKSUM_MASK;
-#endif
-               XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_DMACR_OFFSET, value );
-       }
-       {
-               uint32_t value;
-               value = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCFG_OFFSET );
-
-               /* Network buffers are 32-bit aligned + 2 bytes (because ipconfigPACKET_FILLER_SIZE = 2 ).
-               Now tell the EMAC that received messages should be stored at "address + 2". */
-               value = ( value & ~XEMACPS_NWCFG_RXOFFS_MASK ) | 0x8000;
-
-#if( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM != 0 )
-               value |= XEMACPS_NWCFG_RXCHKSUMEN_MASK;
-#else
-#warning Are you sure the EMAC should not calculate incoming checksums?
-               value &= ~XEMACPS_NWCFG_RXCHKSUMEN_MASK;
-#endif
-               XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCFG_OFFSET, value );
-       }
-
-       /*
-        * Connect the device driver handler that will be called when an
-        * interrupt for the device occurs, the handler defined above performs
-        * the specific interrupt processing for the device.
-        */
-       XScuGic_RegisterHandler(INTC_BASE_ADDR, xtopologyp->scugic_emac_intr,
-               (Xil_ExceptionHandler)XEmacPs_IntrHandler,
-               (void *)&xemacpsif->emacps);
-       /*
-        * Enable the interrupt for emacps.
-        */
-       EmacEnableIntr( );
-
-       return 0;
-}
-
-/*
- * resetrx_on_no_rxdata():
- *
- * It is called at regular intervals through the API xemacpsif_resetrx_on_no_rxdata
- * called by the user.
- * The EmacPs has a HW bug (SI# 692601) on the Rx path for heavy Rx traffic.
- * Under heavy Rx traffic because of the HW bug there are times when the Rx path
- * becomes unresponsive. The workaround for it is to check for the Rx path for
- * traffic (by reading the stats registers regularly). If the stats register
- * does not increment for sometime (proving no Rx traffic), the function resets
- * the Rx data path.
- *
- */
-
-void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif)
-{
-       unsigned long regctrl;
-       unsigned long tempcntr;
-
-       tempcntr = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXCNT_OFFSET );
-       if ( ( tempcntr == 0 ) && ( xemacpsif->last_rx_frms_cntr == 0 ) )
-       {
-               regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
-                               XEMACPS_NWCTRL_OFFSET);
-               regctrl &= (~XEMACPS_NWCTRL_RXEN_MASK);
-               XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
-                               XEMACPS_NWCTRL_OFFSET, regctrl);
-               regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET);
-               regctrl |= (XEMACPS_NWCTRL_RXEN_MASK);
-               XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, regctrl);
-       }
-       xemacpsif->last_rx_frms_cntr = tempcntr;
-}
-
-void EmacDisableIntr(void)
-{
-       XScuGic_DisableIntr(INTC_DIST_BASE_ADDR, xXTopology.scugic_emac_intr);
-}
-
-void EmacEnableIntr(void)
-{
-       XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, xXTopology.scugic_emac_intr);
-}
-
+/*\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
+#include "Zynq/x_emacpsif.h"\r
+#include "Zynq/x_topology.h"\r
+#include "xstatus.h"\r
+\r
+#include "xparameters.h"\r
+#include "xparameters_ps.h"\r
+#include "xil_exception.h"\r
+#include "xil_mmu.h"\r
+\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "timers.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+#include "uncached_memory.h"\r
+\r
+/* Two defines used to set or clear the EMAC interrupt */\r
+#define INTC_BASE_ADDR         XPAR_SCUGIC_CPU_BASEADDR\r
+#define INTC_DIST_BASE_ADDR    XPAR_SCUGIC_DIST_BASEADDR\r
+\r
+\r
+\r
+#if( ipconfigPACKET_FILLER_SIZE != 2 )\r
+       #error Please define ipconfigPACKET_FILLER_SIZE as the value '2'\r
+#endif\r
+#define TX_OFFSET                              ipconfigPACKET_FILLER_SIZE\r
+\r
+#define RX_BUFFER_ALIGNMENT    14\r
+\r
+/* Defined in NetworkInterface.c */\r
+extern TaskHandle_t xEMACTaskHandle;\r
+\r
+/*\r
+       pxDMA_tx_buffers: these are character arrays, each one is big enough to hold 1 MTU.\r
+       The actual TX buffers are located in uncached RAM.\r
+*/\r
+static unsigned char *pxDMA_tx_buffers[ ipconfigNIC_N_TX_DESC ] = { NULL };\r
+\r
+/*\r
+       pxDMA_rx_buffers: these are pointers to 'NetworkBufferDescriptor_t'.\r
+       Once a message has been received by the EMAC, the descriptor can be passed\r
+       immediately to the IP-task.\r
+*/\r
+static NetworkBufferDescriptor_t *pxDMA_rx_buffers[ ipconfigNIC_N_RX_DESC ] = { NULL };\r
+\r
+/*\r
+       The FreeRTOS+TCP port is using a fixed 'topology', which is declared in\r
+       ./portable/NetworkInterface/Zynq/NetworkInterface.c\r
+*/\r
+extern struct xtopology_t xXTopology;\r
+\r
+static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;\r
+\r
+/*\r
+       The FreeRTOS+TCP port does not make use of "src/xemacps_bdring.c".\r
+       In stead 'struct xemacpsif_s' has a "head" and a "tail" index.\r
+       "head" is the next index to be written, used.\r
+       "tail" is the next index to be read, freed.\r
+*/\r
+\r
+int is_tx_space_available( xemacpsif_s *xemacpsif )\r
+{\r
+size_t uxCount;\r
+\r
+       if( xTXDescriptorSemaphore != NULL )\r
+       {\r
+               uxCount = ( ( UBaseType_t ) ipconfigNIC_N_TX_DESC ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );\r
+       }\r
+       else\r
+       {\r
+               uxCount = ( UBaseType_t ) 0u;\r
+       }\r
+\r
+       return uxCount;\r
+}\r
+\r
+void emacps_check_tx( xemacpsif_s *xemacpsif )\r
+{\r
+int tail = xemacpsif->txTail;\r
+int head = xemacpsif->txHead;\r
+size_t uxCount = ( ( UBaseType_t ) ipconfigNIC_N_TX_DESC ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );\r
+\r
+       /* uxCount is the number of TX descriptors that are in use by the DMA. */\r
+       /* When done, "TXBUF_USED" will be set. */\r
+\r
+       while( ( uxCount > 0 ) && ( ( xemacpsif->txSegments[ tail ].flags & XEMACPS_TXBUF_USED_MASK ) != 0 ) )\r
+       {\r
+               if( ( tail == head ) && ( uxCount != ipconfigNIC_N_TX_DESC ) )\r
+               {\r
+                       break;\r
+               }\r
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+#warning ipconfigZERO_COPY_TX_DRIVER is defined\r
+               {\r
+               void *pvBuffer = pxDMA_tx_buffers[ tail ];\r
+               NetworkBufferDescriptor_t *pxBuffer;\r
+\r
+                       if( pvBuffer != NULL )\r
+                       {\r
+                               pxDMA_tx_buffers[ tail ] = NULL;\r
+                               pxBuffer = pxPacketBuffer_to_NetworkBuffer( pvBuffer );\r
+                               if( pxBuffer != NULL )\r
+                               {\r
+                                       vReleaseNetworkBufferAndDescriptor( pxBuffer );\r
+                               }\r
+                               else\r
+                               {\r
+                                       FreeRTOS_printf( ( "emacps_check_tx: Can not find network buffer\n" ) );\r
+                               }\r
+                       }\r
+               }\r
+#endif\r
+               /* Clear all but the "used" and "wrap" bits. */\r
+               if( tail < ipconfigNIC_N_TX_DESC - 1 )\r
+               {\r
+                       xemacpsif->txSegments[ tail ].flags = XEMACPS_TXBUF_USED_MASK;\r
+               }\r
+               else\r
+               {\r
+                       xemacpsif->txSegments[ tail ].flags = XEMACPS_TXBUF_USED_MASK | XEMACPS_TXBUF_WRAP_MASK;\r
+               }\r
+               uxCount--;\r
+               /* Tell the counting semaphore that one more TX descriptor is available. */\r
+               xSemaphoreGive( xTXDescriptorSemaphore );\r
+               if( ++tail == ipconfigNIC_N_TX_DESC )\r
+               {\r
+                       tail = 0;\r
+               }\r
+               xemacpsif->txTail = tail;\r
+       }\r
+\r
+       return;\r
+}\r
+\r
+void emacps_send_handler(void *arg)\r
+{\r
+xemacpsif_s   *xemacpsif;\r
+BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
+\r
+       xemacpsif = (xemacpsif_s *)(arg);\r
+\r
+       /* In this port for FreeRTOS+TCP, the EMAC interrupts will only set a bit in\r
+       "isr_events". The task in NetworkInterface will wake-up and do the necessary work.\r
+       */\r
+       xemacpsif->isr_events |= EMAC_IF_TX_EVENT;\r
+       xemacpsif->txBusy = pdFALSE;\r
+\r
+       if( xEMACTaskHandle != NULL )\r
+       {\r
+               vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );\r
+       }\r
+\r
+       portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
+}\r
+\r
+static BaseType_t xValidLength( BaseType_t xLength )\r
+{\r
+BaseType_t xReturn;\r
+\r
+       if( ( xLength >= ( BaseType_t ) sizeof( struct xARP_PACKET ) ) && ( ( ( uint32_t ) xLength ) <= ipTOTAL_ETHERNET_FRAME_SIZE ) )\r
+       {\r
+               xReturn = pdTRUE;\r
+       }\r
+       else\r
+       {\r
+               xReturn =  pdFALSE;\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+\r
+XStatus emacps_send_message(xemacpsif_s *xemacpsif, NetworkBufferDescriptor_t *pxBuffer, int iReleaseAfterSend )\r
+{\r
+int head = xemacpsif->txHead;\r
+int iHasSent = 0;\r
+uint32_t ulBaseAddress = xemacpsif->emacps.Config.BaseAddress;\r
+TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 5000u );\r
+\r
+       #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+       {\r
+               /* This driver wants to own all network buffers which are to be transmitted. */\r
+               configASSERT( iReleaseAfterSend != pdFALSE );\r
+       }\r
+       #endif\r
+\r
+       /* Open a do {} while ( 0 ) loop to be able to call break. */\r
+       do\r
+       {\r
+       uint32_t ulFlags = 0;\r
+\r
+               if( xValidLength( pxBuffer->xDataLength ) != pdTRUE )\r
+               {\r
+                       break;\r
+               }\r
+\r
+               if( xTXDescriptorSemaphore == NULL )\r
+               {\r
+                       break;\r
+               }\r
+\r
+               if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )\r
+               {\r
+                       FreeRTOS_printf( ( "emacps_send_message: Time-out waiting for TX buffer\n" ) );\r
+                       break;\r
+               }\r
+\r
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+               /* Pass the pointer (and its ownership) directly to DMA. */\r
+               pxDMA_tx_buffers[ head ] = pxBuffer->pucEthernetBuffer;\r
+               if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 )\r
+               {\r
+                       Xil_DCacheFlushRange( ( unsigned )pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength );\r
+               }\r
+               /* Buffer has been transferred, do not release it. */\r
+               iReleaseAfterSend = pdFALSE;\r
+#else\r
+               if( pxDMA_tx_buffers[ head ] == NULL )\r
+               {\r
+                       FreeRTOS_printf( ( "emacps_send_message: pxDMA_tx_buffers[ %d ] == NULL\n", head ) );\r
+                       break;\r
+               }\r
+               /* Copy the message to unbuffered space in RAM. */\r
+               memcpy( pxDMA_tx_buffers[ head ], pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength );\r
+#endif\r
+               /* Packets will be sent one-by-one, so for each packet\r
+               the TXBUF_LAST bit will be set. */\r
+               ulFlags |= XEMACPS_TXBUF_LAST_MASK;\r
+               ulFlags |= ( pxBuffer->xDataLength & XEMACPS_TXBUF_LEN_MASK );\r
+               if( head == ( ipconfigNIC_N_TX_DESC - 1 ) )\r
+               {\r
+                       ulFlags |= XEMACPS_TXBUF_WRAP_MASK;\r
+               }\r
+\r
+               /* Copy the address of the buffer and set the flags. */\r
+               xemacpsif->txSegments[ head ].address = ( uint32_t )pxDMA_tx_buffers[ head ];\r
+               xemacpsif->txSegments[ head ].flags = ulFlags;\r
+\r
+               iHasSent = pdTRUE;\r
+               if( ++head == ipconfigNIC_N_TX_DESC )\r
+               {\r
+                       head = 0;\r
+               }\r
+               /* Update the TX-head index. These variable are declared volatile so they will be\r
+               accessed as little as possible. */\r
+               xemacpsif->txHead = head;\r
+       } while( pdFALSE );\r
+\r
+       if( iReleaseAfterSend != pdFALSE )\r
+       {\r
+               vReleaseNetworkBufferAndDescriptor( pxBuffer );\r
+               pxBuffer = NULL;\r
+       }\r
+\r
+       /* Data Synchronization Barrier */\r
+       dsb();\r
+\r
+       if( iHasSent != pdFALSE )\r
+       {\r
+               /* Make STARTTX high */\r
+               uint32_t ulValue = XEmacPs_ReadReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET);\r
+               /* Start transmit */\r
+               xemacpsif->txBusy = pdTRUE;\r
+               XEmacPs_WriteReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET, ( ulValue | XEMACPS_NWCTRL_STARTTX_MASK ) );\r
+       }\r
+       dsb();\r
+\r
+       return 0;\r
+}\r
+\r
+void emacps_recv_handler(void *arg)\r
+{\r
+       xemacpsif_s *xemacpsif;\r
+       BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
+\r
+       xemacpsif = (xemacpsif_s *)(arg);\r
+       xemacpsif->isr_events |= EMAC_IF_RX_EVENT;\r
+\r
+       if( xEMACTaskHandle != NULL )\r
+       {\r
+               vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );\r
+       }\r
+\r
+       portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
+}\r
+\r
+static NetworkBufferDescriptor_t *ethMsg = NULL;\r
+static NetworkBufferDescriptor_t *ethLast = NULL;\r
+\r
+static void passEthMessages( void )\r
+{\r
+IPStackEvent_t xRxEvent;\r
+\r
+       xRxEvent.eEventType = eNetworkRxEvent;\r
+       xRxEvent.pvData = ( void * ) ethMsg;\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
+               do\r
+               {\r
+                       NetworkBufferDescriptor_t *xNext = ethMsg->pxNextBuffer;\r
+                       vReleaseNetworkBufferAndDescriptor( ethMsg );\r
+                       ethMsg = xNext;\r
+               } while( ethMsg != NULL );\r
+\r
+               iptraceETHERNET_RX_EVENT_LOST();\r
+               FreeRTOS_printf( ( "passEthMessages: Can not queue return packet!\n" ) );\r
+       }\r
+\r
+       ethMsg = ethLast = NULL;\r
+}\r
+\r
+int emacps_check_rx( xemacpsif_s *xemacpsif )\r
+{\r
+NetworkBufferDescriptor_t *pxBuffer, *pxNewBuffer;\r
+int rx_bytes;\r
+volatile int msgCount = 0;\r
+int head = xemacpsif->rxHead;\r
+\r
+       /* There seems to be an issue (SI# 692601), see comments below. */\r
+       resetrx_on_no_rxdata(xemacpsif);\r
+\r
+       /* This FreeRTOS+TCP driver shall be compiled with the option\r
+       "ipconfigUSE_LINKED_RX_MESSAGES" enabled.  It allows the driver to send a\r
+       chain of RX messages within one message to the IP-task. */\r
+       for( ;; )\r
+       {\r
+               if( ( ( xemacpsif->rxSegments[ head ].address & XEMACPS_RXBUF_NEW_MASK ) == 0 ) ||\r
+                       ( pxDMA_rx_buffers[ head ] == NULL ) )\r
+               {\r
+                       break;\r
+               }\r
+\r
+               pxNewBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT, ( TickType_t ) 0 );\r
+               if( pxNewBuffer == NULL )\r
+               {\r
+                       /* A packet has been received, but there is no replacement for this Network Buffer.\r
+                       The packet will be dropped, and it Network Buffer will stay in place. */\r
+                       FreeRTOS_printf( ("emacps_check_rx: unable to allocate a Netwrok Buffer\n" ) );\r
+                       pxNewBuffer = ( NetworkBufferDescriptor_t * )pxDMA_rx_buffers[ head ];\r
+               }\r
+               else\r
+               {\r
+                       pxBuffer = ( NetworkBufferDescriptor_t * )pxDMA_rx_buffers[ head ];\r
+\r
+                       /* Just avoiding to use or refer to the same buffer again */\r
+                       pxDMA_rx_buffers[ head ] = pxNewBuffer;\r
+\r
+                       /*\r
+                        * Adjust the buffer size to the actual number of bytes received.\r
+                        */\r
+                       rx_bytes = xemacpsif->rxSegments[ head ].flags & XEMACPS_RXBUF_LEN_MASK;\r
+\r
+                       pxBuffer->xDataLength = rx_bytes;\r
+\r
+                       if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 )\r
+                       {\r
+                               Xil_DCacheInvalidateRange( ( ( uint32_t )pxBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE, (unsigned)rx_bytes );\r
+                       }\r
+\r
+                       /* store it in the receive queue, where it'll be processed by a\r
+                       different handler. */\r
+                       iptraceNETWORK_INTERFACE_RECEIVE();\r
+                       pxBuffer->pxNextBuffer = NULL;\r
+\r
+                       if( ethMsg == NULL )\r
+                       {\r
+                               // Becomes the first message\r
+                               ethMsg = pxBuffer;\r
+                       }\r
+                       else if( ethLast != NULL )\r
+                       {\r
+                               // Add to the tail\r
+                               ethLast->pxNextBuffer = pxBuffer;\r
+                       }\r
+\r
+                       ethLast = pxBuffer;\r
+                       msgCount++;\r
+               }\r
+               {\r
+                       if( ucIsCachedMemory( pxNewBuffer->pucEthernetBuffer ) != 0 )\r
+                       {\r
+                               Xil_DCacheInvalidateRange( ( ( uint32_t )pxNewBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE, (unsigned)ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT);\r
+                       }\r
+                       {\r
+                               uint32_t addr = ( ( uint32_t )pxNewBuffer->pucEthernetBuffer ) & XEMACPS_RXBUF_ADD_MASK;\r
+                               if( head == ( ipconfigNIC_N_RX_DESC - 1 ) )\r
+                               {\r
+                                       addr |= XEMACPS_RXBUF_WRAP_MASK;\r
+                               }\r
+                               /* Clearing 'XEMACPS_RXBUF_NEW_MASK'       0x00000001 *< Used bit.. */\r
+                               xemacpsif->rxSegments[ head ].address = addr;\r
+                               xemacpsif->rxSegments[ head ].flags = 0;\r
+                       }\r
+               }\r
+\r
+               if( ++head == ipconfigNIC_N_RX_DESC )\r
+               {\r
+                       head = 0;\r
+               }\r
+               xemacpsif->rxHead = head;\r
+       }\r
+\r
+       if( ethMsg != NULL )\r
+       {\r
+               passEthMessages( );\r
+       }\r
+\r
+       return msgCount;\r
+}\r
+\r
+void clean_dma_txdescs(xemacpsif_s *xemacpsif)\r
+{\r
+int index;\r
+unsigned char *ucTxBuffer;\r
+\r
+       /* Clear all TX descriptors and assign uncached memory to each descriptor.\r
+       "tx_space" points to the first available TX buffer. */\r
+       ucTxBuffer = xemacpsif->tx_space;\r
+\r
+       for( index = 0; index < ipconfigNIC_N_TX_DESC; index++ )\r
+       {\r
+               xemacpsif->txSegments[ index ].address = ( uint32_t )ucTxBuffer;\r
+               xemacpsif->txSegments[ index ].flags = XEMACPS_TXBUF_USED_MASK;\r
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+               pxDMA_tx_buffers[ index ] = ( void* )NULL;\r
+#else\r
+               pxDMA_tx_buffers[ index ] = ( void* )( ucTxBuffer + TX_OFFSET );\r
+#endif\r
+               ucTxBuffer += xemacpsif->uTxUnitSize;\r
+       }\r
+       xemacpsif->txSegments[ ipconfigNIC_N_TX_DESC - 1 ].flags =\r
+               XEMACPS_TXBUF_USED_MASK | XEMACPS_TXBUF_WRAP_MASK;\r
+}\r
+\r
+XStatus init_dma(xemacpsif_s *xemacpsif)\r
+{\r
+       NetworkBufferDescriptor_t *pxBuffer;\r
+\r
+       int iIndex;\r
+       UBaseType_t xRxSize;\r
+       UBaseType_t xTxSize;\r
+       struct xtopology_t *xtopologyp = &xXTopology;\r
+\r
+       xRxSize = ipconfigNIC_N_RX_DESC * sizeof( xemacpsif->rxSegments[ 0 ] );\r
+\r
+       xTxSize = ipconfigNIC_N_TX_DESC * sizeof( xemacpsif->txSegments[ 0 ] );\r
+\r
+       /* Also round-up to 4KB */\r
+       xemacpsif->uTxUnitSize = ( ipTOTAL_ETHERNET_FRAME_SIZE + 0x1000ul ) & ~0xffful;\r
+       /*\r
+        * We allocate 65536 bytes for RX BDs which can accommodate a\r
+        * maximum of 8192 BDs which is much more than any application\r
+        * will ever need.\r
+        */\r
+       xemacpsif->rxSegments = ( struct xBD_TYPE * )( pucGetUncachedMemory ( xRxSize )  );\r
+       xemacpsif->txSegments = ( struct xBD_TYPE * )( pucGetUncachedMemory ( xTxSize ) );\r
+       xemacpsif->tx_space   = ( unsigned char *   )( pucGetUncachedMemory ( ipconfigNIC_N_TX_DESC * xemacpsif->uTxUnitSize ) );\r
+\r
+       /* These variables will be used in XEmacPs_Start (see src/xemacps.c). */\r
+       xemacpsif->emacps.RxBdRing.BaseBdAddr = ( uint32_t ) xemacpsif->rxSegments;\r
+       xemacpsif->emacps.TxBdRing.BaseBdAddr = ( uint32_t ) xemacpsif->txSegments;\r
+\r
+       if( xTXDescriptorSemaphore == NULL )\r
+       {\r
+               xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ipconfigNIC_N_TX_DESC, ( UBaseType_t ) ipconfigNIC_N_TX_DESC );\r
+               configASSERT( xTXDescriptorSemaphore );\r
+       }\r
+       /*\r
+        * Allocate RX descriptors, 1 RxBD at a time.\r
+        */\r
+       for( iIndex = 0; iIndex < ipconfigNIC_N_RX_DESC; iIndex++ )\r
+       {\r
+               pxBuffer = pxDMA_rx_buffers[ iIndex ];\r
+               if( pxBuffer == NULL )\r
+               {\r
+                       pxBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT, ( TickType_t ) 0 );\r
+                       if( pxBuffer == NULL )\r
+                       {\r
+                               FreeRTOS_printf( ("Unable to allocate a network buffer in recv_handler\n" ) );\r
+                               return -1;\r
+                       }\r
+               }\r
+\r
+               xemacpsif->rxSegments[ iIndex ].flags = 0;\r
+               xemacpsif->rxSegments[ iIndex ].address = ( ( uint32_t )pxBuffer->pucEthernetBuffer ) & XEMACPS_RXBUF_ADD_MASK;\r
+\r
+               pxDMA_rx_buffers[ iIndex ] = pxBuffer;\r
+               /* Make sure this memory is not in cache for now. */\r
+               if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 )\r
+               {\r
+                       Xil_DCacheInvalidateRange( ( ( uint32_t )pxBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE,\r
+                               (unsigned)ipTOTAL_ETHERNET_FRAME_SIZE + RX_BUFFER_ALIGNMENT);\r
+               }\r
+       }\r
+\r
+       xemacpsif->rxSegments[ ipconfigNIC_N_RX_DESC - 1 ].address |= XEMACPS_RXBUF_WRAP_MASK;\r
+\r
+       memset( xemacpsif->tx_space, '\0', ipconfigNIC_N_TX_DESC * xemacpsif->uTxUnitSize );\r
+\r
+       clean_dma_txdescs( xemacpsif );\r
+\r
+       {\r
+               uint32_t value;\r
+               value = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_DMACR_OFFSET );\r
+\r
+               // 1xxxx: Attempt to use INCR16 AHB bursts\r
+               value = ( value & ~( XEMACPS_DMACR_BLENGTH_MASK ) ) | XEMACPS_DMACR_INCR16_AHB_BURST;\r
+#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )\r
+               value |= XEMACPS_DMACR_TCPCKSUM_MASK;\r
+#else\r
+#warning Are you sure the EMAC should not calculate outgoing checksums?\r
+               value &= ~XEMACPS_DMACR_TCPCKSUM_MASK;\r
+#endif\r
+               XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_DMACR_OFFSET, value );\r
+       }\r
+       {\r
+               uint32_t value;\r
+               value = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCFG_OFFSET );\r
+\r
+               /* Network buffers are 32-bit aligned + 2 bytes (because ipconfigPACKET_FILLER_SIZE = 2 ).\r
+               Now tell the EMAC that received messages should be stored at "address + 2". */\r
+               value = ( value & ~XEMACPS_NWCFG_RXOFFS_MASK ) | 0x8000;\r
+\r
+#if( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM != 0 )\r
+               value |= XEMACPS_NWCFG_RXCHKSUMEN_MASK;\r
+#else\r
+#warning Are you sure the EMAC should not calculate incoming checksums?\r
+               value &= ~XEMACPS_NWCFG_RXCHKSUMEN_MASK;\r
+#endif\r
+               XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCFG_OFFSET, value );\r
+       }\r
+\r
+       /*\r
+        * Connect the device driver handler that will be called when an\r
+        * interrupt for the device occurs, the handler defined above performs\r
+        * the specific interrupt processing for the device.\r
+        */\r
+       XScuGic_RegisterHandler(INTC_BASE_ADDR, xtopologyp->scugic_emac_intr,\r
+               (Xil_ExceptionHandler)XEmacPs_IntrHandler,\r
+               (void *)&xemacpsif->emacps);\r
+       /*\r
+        * Enable the interrupt for emacps.\r
+        */\r
+       EmacEnableIntr( );\r
+\r
+       return 0;\r
+}\r
+\r
+/*\r
+ * resetrx_on_no_rxdata():\r
+ *\r
+ * It is called at regular intervals through the API xemacpsif_resetrx_on_no_rxdata\r
+ * called by the user.\r
+ * The EmacPs has a HW bug (SI# 692601) on the Rx path for heavy Rx traffic.\r
+ * Under heavy Rx traffic because of the HW bug there are times when the Rx path\r
+ * becomes unresponsive. The workaround for it is to check for the Rx path for\r
+ * traffic (by reading the stats registers regularly). If the stats register\r
+ * does not increment for sometime (proving no Rx traffic), the function resets\r
+ * the Rx data path.\r
+ *\r
+ */\r
+\r
+void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif)\r
+{\r
+       unsigned long regctrl;\r
+       unsigned long tempcntr;\r
+\r
+       tempcntr = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXCNT_OFFSET );\r
+       if ( ( tempcntr == 0 ) && ( xemacpsif->last_rx_frms_cntr == 0 ) )\r
+       {\r
+               regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,\r
+                               XEMACPS_NWCTRL_OFFSET);\r
+               regctrl &= (~XEMACPS_NWCTRL_RXEN_MASK);\r
+               XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,\r
+                               XEMACPS_NWCTRL_OFFSET, regctrl);\r
+               regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET);\r
+               regctrl |= (XEMACPS_NWCTRL_RXEN_MASK);\r
+               XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, regctrl);\r
+       }\r
+       xemacpsif->last_rx_frms_cntr = tempcntr;\r
+}\r
+\r
+void EmacDisableIntr(void)\r
+{\r
+       XScuGic_DisableIntr(INTC_DIST_BASE_ADDR, xXTopology.scugic_emac_intr);\r
+}\r
+\r
+void EmacEnableIntr(void)\r
+{\r
+       XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, xXTopology.scugic_emac_intr);\r
+}\r
+\r
index be00f4f9c8493dff2363d357744bf39b07fc1ed0..e9443cda8e17151e4a2381a2113c29fa31eea298 100644 (file)
-/*
- * Copyright (c) 2010-2013 Xilinx, Inc.  All rights reserved.
- *
- * Xilinx, Inc.
- * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
- * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
- * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
- * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
- * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
- * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
- * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
- * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
- * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
- * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-
-/* Standard includes. */
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "Zynq/x_emacpsif.h"
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "task.h"
-#include "queue.h"
-
-///* FreeRTOS+TCP includes. */
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_Sockets.h"
-#include "FreeRTOS_IP_Private.h"
-#include "NetworkBufferManagement.h"
-
-extern TaskHandle_t xEMACTaskHandle;
-
-/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c
- *** to run it on a PEEP board
- ***/
-
-unsigned int link_speed = 100;
-
-void setup_isr( xemacpsif_s *xemacpsif )
-{
-       /*
-        * Setup callbacks
-        */
-       XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMASEND,
-               (void *) emacps_send_handler,
-               (void *) xemacpsif);
-
-       XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMARECV,
-               (void *) emacps_recv_handler,
-               (void *) xemacpsif);
-
-       XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_ERROR,
-               (void *) emacps_error_handler,
-               (void *) xemacpsif);
-}
-
-void start_emacps (xemacpsif_s *xemacps)
-{
-       /* start the temac */
-       XEmacPs_Start(&xemacps->emacps);
-}
-
-extern struct xtopology_t xXTopology;
-
-volatile int error_msg_count = 0;
-volatile const char *last_err_msg = "";
-
-struct xERROR_MSG {
-       void *arg;
-       u8 Direction;
-       u32 ErrorWord;
-};
-
-static struct xERROR_MSG xErrorList[ 8 ];
-static BaseType_t xErrorHead, xErrorTail;
-
-void emacps_error_handler(void *arg, u8 Direction, u32 ErrorWord)
-{
-       BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-       xemacpsif_s *xemacpsif;
-       BaseType_t xNextHead = xErrorHead;
-
-       xemacpsif = (xemacpsif_s *)(arg);
-
-       if( ( Direction != XEMACPS_SEND ) || (ErrorWord != XEMACPS_TXSR_USEDREAD_MASK ) )
-       {
-               if( ++xNextHead == ( sizeof( xErrorList ) / sizeof( xErrorList[ 0 ] ) ) )
-                       xNextHead = 0;
-               if( xNextHead != xErrorTail )
-               {
-
-                       xErrorList[ xErrorHead ].arg = arg;
-                       xErrorList[ xErrorHead ].Direction = Direction;
-                       xErrorList[ xErrorHead ].ErrorWord = ErrorWord;
-
-                       xErrorHead = xNextHead;
-
-                       xemacpsif = (xemacpsif_s *)(arg);
-                       xemacpsif->isr_events |= EMAC_IF_ERR_EVENT;
-               }
-
-               if( xEMACTaskHandle != NULL )
-               {
-                       vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
-               }
-
-       }
-
-       portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
-}
-
-static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord);
-
-int emacps_check_errors( xemacpsif_s *xemacps )
-{
-int xResult;
-
-       ( void ) xemacps;
-
-       if( xErrorHead == xErrorTail )
-       {
-               xResult = 0;
-       }
-       else
-       {
-               xResult = 1;
-               emacps_handle_error(
-                       xErrorList[ xErrorTail ].arg,
-                       xErrorList[ xErrorTail ].Direction,
-                       xErrorList[ xErrorTail ].ErrorWord );
-       }
-
-       return xResult;
-}
-
-BaseType_t xNetworkInterfaceInitialise( void );
-
-static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord)
-{
-       xemacpsif_s   *xemacpsif;
-       struct xtopology_t *xtopologyp;
-       XEmacPs *xemacps;
-
-       xemacpsif = (xemacpsif_s *)(arg);
-
-       xtopologyp = &xXTopology;
-
-       xemacps = &xemacpsif->emacps;
-
-       /* Do not appear to be used. */
-       ( void ) xemacps;
-       ( void ) xtopologyp;
-
-       last_err_msg = NULL;
-
-       if( ErrorWord != 0 )
-       {
-               switch (Direction) {
-               case XEMACPS_RECV:
-                       if( ( ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK ) != 0 )
-                       {
-                               last_err_msg = "Receive DMA error";
-                               xNetworkInterfaceInitialise( );
-                       }
-                       if( ( ErrorWord & XEMACPS_RXSR_RXOVR_MASK ) != 0 )
-                       {
-                               last_err_msg = "Receive over run";
-                               emacps_recv_handler(arg);
-                       }
-                       if( ( ErrorWord & XEMACPS_RXSR_BUFFNA_MASK ) != 0 )
-                       {
-                               last_err_msg = "Receive buffer not available";
-                               emacps_recv_handler(arg);
-                       }
-                       break;
-               case XEMACPS_SEND:
-                       if( ( ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK ) != 0 )
-                       {
-                               last_err_msg = "Transmit DMA error";
-                               xNetworkInterfaceInitialise( );
-                       }
-                       if( ( ErrorWord & XEMACPS_TXSR_URUN_MASK ) != 0 )
-                       {
-                               last_err_msg = "Transmit under run";
-                               HandleTxErrors( xemacpsif );
-                       }
-                       if( ( ErrorWord & XEMACPS_TXSR_BUFEXH_MASK ) != 0 )
-                       {
-                               last_err_msg = "Transmit buffer exhausted";
-                               HandleTxErrors( xemacpsif );
-                       }
-                       if( ( ErrorWord & XEMACPS_TXSR_RXOVR_MASK ) != 0 )
-                       {
-                               last_err_msg = "Transmit retry excessed limits";
-                               HandleTxErrors( xemacpsif );
-                       }
-                       if( ( ErrorWord & XEMACPS_TXSR_FRAMERX_MASK ) != 0 )
-                       {
-                               last_err_msg = "Transmit collision";
-                               emacps_check_tx( xemacpsif );
-                       }
-                       break;
-               }
-       }
-       // Break on this statement and inspect error_msg if you like
-       if( last_err_msg != NULL )
-       {
-               error_msg_count++;
-               FreeRTOS_printf( ( "emacps_handle_error: %s\n", last_err_msg ) );
-       }
-}
-
-extern XEmacPs_Config mac_config;
-
-void HandleTxErrors(xemacpsif_s *xemacpsif)
-{
-       u32 netctrlreg;
-
-       //taskENTER_CRITICAL()
-       {
-               netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
-                                                                                                       XEMACPS_NWCTRL_OFFSET);
-               netctrlreg = netctrlreg & (~XEMACPS_NWCTRL_TXEN_MASK);
-               XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
-                                                                               XEMACPS_NWCTRL_OFFSET, netctrlreg);
-
-               clean_dma_txdescs( xemacpsif );
-               netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
-                                                                                                               XEMACPS_NWCTRL_OFFSET);
-               netctrlreg = netctrlreg | (XEMACPS_NWCTRL_TXEN_MASK);
-               XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
-                                                                                       XEMACPS_NWCTRL_OFFSET, netctrlreg);
-       }
-       //taskEXIT_CRITICAL( );
-}
+/*\r
+ * Copyright (c) 2010-2013 Xilinx, Inc.  All rights reserved.\r
+ *\r
+ * Xilinx, Inc.\r
+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A\r
+ * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS\r
+ * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR\r
+ * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION\r
+ * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE\r
+ * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.\r
+ * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO\r
+ * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO\r
+ * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE\r
+ * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY\r
+ * AND FITNESS FOR A PARTICULAR PURPOSE.\r
+ *\r
+ */\r
+\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+#include "Zynq/x_emacpsif.h"\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+\r
+///* FreeRTOS+TCP includes. */\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+extern TaskHandle_t xEMACTaskHandle;\r
+\r
+/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c\r
+ *** to run it on a PEEP board\r
+ ***/\r
+\r
+unsigned int link_speed = 100;\r
+\r
+void setup_isr( xemacpsif_s *xemacpsif )\r
+{\r
+       /*\r
+        * Setup callbacks\r
+        */\r
+       XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMASEND,\r
+               (void *) emacps_send_handler,\r
+               (void *) xemacpsif);\r
+\r
+       XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMARECV,\r
+               (void *) emacps_recv_handler,\r
+               (void *) xemacpsif);\r
+\r
+       XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_ERROR,\r
+               (void *) emacps_error_handler,\r
+               (void *) xemacpsif);\r
+}\r
+\r
+void start_emacps (xemacpsif_s *xemacps)\r
+{\r
+       /* start the temac */\r
+       XEmacPs_Start(&xemacps->emacps);\r
+}\r
+\r
+extern struct xtopology_t xXTopology;\r
+\r
+volatile int error_msg_count = 0;\r
+volatile const char *last_err_msg = "";\r
+\r
+struct xERROR_MSG {\r
+       void *arg;\r
+       u8 Direction;\r
+       u32 ErrorWord;\r
+};\r
+\r
+static struct xERROR_MSG xErrorList[ 8 ];\r
+static BaseType_t xErrorHead, xErrorTail;\r
+\r
+void emacps_error_handler(void *arg, u8 Direction, u32 ErrorWord)\r
+{\r
+       BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
+       xemacpsif_s *xemacpsif;\r
+       BaseType_t xNextHead = xErrorHead;\r
+\r
+       xemacpsif = (xemacpsif_s *)(arg);\r
+\r
+       if( ( Direction != XEMACPS_SEND ) || (ErrorWord != XEMACPS_TXSR_USEDREAD_MASK ) )\r
+       {\r
+               if( ++xNextHead == ( sizeof( xErrorList ) / sizeof( xErrorList[ 0 ] ) ) )\r
+                       xNextHead = 0;\r
+               if( xNextHead != xErrorTail )\r
+               {\r
+\r
+                       xErrorList[ xErrorHead ].arg = arg;\r
+                       xErrorList[ xErrorHead ].Direction = Direction;\r
+                       xErrorList[ xErrorHead ].ErrorWord = ErrorWord;\r
+\r
+                       xErrorHead = xNextHead;\r
+\r
+                       xemacpsif = (xemacpsif_s *)(arg);\r
+                       xemacpsif->isr_events |= EMAC_IF_ERR_EVENT;\r
+               }\r
+\r
+               if( xEMACTaskHandle != NULL )\r
+               {\r
+                       vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );\r
+               }\r
+\r
+       }\r
+\r
+       portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
+}\r
+\r
+static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord);\r
+\r
+int emacps_check_errors( xemacpsif_s *xemacps )\r
+{\r
+int xResult;\r
+\r
+       ( void ) xemacps;\r
+\r
+       if( xErrorHead == xErrorTail )\r
+       {\r
+               xResult = 0;\r
+       }\r
+       else\r
+       {\r
+               xResult = 1;\r
+               emacps_handle_error(\r
+                       xErrorList[ xErrorTail ].arg,\r
+                       xErrorList[ xErrorTail ].Direction,\r
+                       xErrorList[ xErrorTail ].ErrorWord );\r
+       }\r
+\r
+       return xResult;\r
+}\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void );\r
+\r
+static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord)\r
+{\r
+       xemacpsif_s   *xemacpsif;\r
+       struct xtopology_t *xtopologyp;\r
+       XEmacPs *xemacps;\r
+\r
+       xemacpsif = (xemacpsif_s *)(arg);\r
+\r
+       xtopologyp = &xXTopology;\r
+\r
+       xemacps = &xemacpsif->emacps;\r
+\r
+       /* Do not appear to be used. */\r
+       ( void ) xemacps;\r
+       ( void ) xtopologyp;\r
+\r
+       last_err_msg = NULL;\r
+\r
+       if( ErrorWord != 0 )\r
+       {\r
+               switch (Direction) {\r
+               case XEMACPS_RECV:\r
+                       if( ( ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK ) != 0 )\r
+                       {\r
+                               last_err_msg = "Receive DMA error";\r
+                               xNetworkInterfaceInitialise( );\r
+                       }\r
+                       if( ( ErrorWord & XEMACPS_RXSR_RXOVR_MASK ) != 0 )\r
+                       {\r
+                               last_err_msg = "Receive over run";\r
+                               emacps_recv_handler(arg);\r
+                       }\r
+                       if( ( ErrorWord & XEMACPS_RXSR_BUFFNA_MASK ) != 0 )\r
+                       {\r
+                               last_err_msg = "Receive buffer not available";\r
+                               emacps_recv_handler(arg);\r
+                       }\r
+                       break;\r
+               case XEMACPS_SEND:\r
+                       if( ( ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK ) != 0 )\r
+                       {\r
+                               last_err_msg = "Transmit DMA error";\r
+                               xNetworkInterfaceInitialise( );\r
+                       }\r
+                       if( ( ErrorWord & XEMACPS_TXSR_URUN_MASK ) != 0 )\r
+                       {\r
+                               last_err_msg = "Transmit under run";\r
+                               HandleTxErrors( xemacpsif );\r
+                       }\r
+                       if( ( ErrorWord & XEMACPS_TXSR_BUFEXH_MASK ) != 0 )\r
+                       {\r
+                               last_err_msg = "Transmit buffer exhausted";\r
+                               HandleTxErrors( xemacpsif );\r
+                       }\r
+                       if( ( ErrorWord & XEMACPS_TXSR_RXOVR_MASK ) != 0 )\r
+                       {\r
+                               last_err_msg = "Transmit retry excessed limits";\r
+                               HandleTxErrors( xemacpsif );\r
+                       }\r
+                       if( ( ErrorWord & XEMACPS_TXSR_FRAMERX_MASK ) != 0 )\r
+                       {\r
+                               last_err_msg = "Transmit collision";\r
+                               emacps_check_tx( xemacpsif );\r
+                       }\r
+                       break;\r
+               }\r
+       }\r
+       // Break on this statement and inspect error_msg if you like\r
+       if( last_err_msg != NULL )\r
+       {\r
+               error_msg_count++;\r
+               FreeRTOS_printf( ( "emacps_handle_error: %s\n", last_err_msg ) );\r
+       }\r
+}\r
+\r
+extern XEmacPs_Config mac_config;\r
+\r
+void HandleTxErrors(xemacpsif_s *xemacpsif)\r
+{\r
+       u32 netctrlreg;\r
+\r
+       //taskENTER_CRITICAL()\r
+       {\r
+               netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,\r
+                                                                                                       XEMACPS_NWCTRL_OFFSET);\r
+               netctrlreg = netctrlreg & (~XEMACPS_NWCTRL_TXEN_MASK);\r
+               XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,\r
+                                                                               XEMACPS_NWCTRL_OFFSET, netctrlreg);\r
+\r
+               clean_dma_txdescs( xemacpsif );\r
+               netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,\r
+                                                                                                               XEMACPS_NWCTRL_OFFSET);\r
+               netctrlreg = netctrlreg | (XEMACPS_NWCTRL_TXEN_MASK);\r
+               XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,\r
+                                                                                       XEMACPS_NWCTRL_OFFSET, netctrlreg);\r
+       }\r
+       //taskEXIT_CRITICAL( );\r
+}\r
index 7b0e4fd3647a357643707edbf47ffbfe0a11036c..f3c424a4b5497a2bae86a91f8bee0e3292319edf 100644 (file)
@@ -1,39 +1,39 @@
-/*
- * Copyright (c) 2010-2013 Xilinx, Inc.  All rights reserved.
- *
- * Xilinx, Inc.
- * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
- * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
- * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
- * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
- * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
- * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
- * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
- * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
- * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
- * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-#ifndef __XEMACPSIF_HW_H_
-#define __XEMACPSIF_HW_H_
-
-#include "Zynq/x_emacpsif.h"
-//#include "lwip/netif.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-XEmacPs_Config * lookup_config(unsigned mac_base);
-
-//void init_emacps(xemacpsif_s *xemacpsif, struct netif *netif);
-
-int emacps_check_errors( xemacpsif_s *xemacps );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+/*\r
+ * Copyright (c) 2010-2013 Xilinx, Inc.  All rights reserved.\r
+ *\r
+ * Xilinx, Inc.\r
+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A\r
+ * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS\r
+ * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR\r
+ * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION\r
+ * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE\r
+ * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.\r
+ * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO\r
+ * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO\r
+ * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE\r
+ * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY\r
+ * AND FITNESS FOR A PARTICULAR PURPOSE.\r
+ *\r
+ */\r
+\r
+#ifndef __XEMACPSIF_HW_H_\r
+#define __XEMACPSIF_HW_H_\r
+\r
+#include "Zynq/x_emacpsif.h"\r
+//#include "lwip/netif.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+XEmacPs_Config * lookup_config(unsigned mac_base);\r
+\r
+//void init_emacps(xemacpsif_s *xemacpsif, struct netif *netif);\r
+\r
+int emacps_check_errors( xemacpsif_s *xemacps );\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
index 742ff8b96665c9797e7fc4d6625c0728d48d7e30..12b8c60c8b9da9b4ccf0fe20cb0ef6fc31352b14 100644 (file)
-/*
- * Copyright (c) 2007-2008, Advanced Micro Devices, Inc.
- *               All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *    * Redistributions of source code must retain the above copyright
- *      notice, this list of conditions and the following disclaimer.
- *    * Redistributions in binary form must reproduce the above copyright
- *      notice, this list of conditions and the following disclaimer in
- *      the documentation and/or other materials provided with the
- *      distribution.
- *    * Neither the name of Advanced Micro Devices, Inc. nor the names
- *      of its contributors may be used to endorse or promote products
- *      derived from this software without specific prior written
- *      permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * Some portions copyright (c) 2010-2013 Xilinx, Inc.  All rights reserved.
- *
- * Xilinx, Inc.
- * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
- * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
- * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
- * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
- * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
- * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
- * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
- * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
- * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
- * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-/* Standard includes. */
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "Zynq/x_emacpsif.h"
-//#include "lwipopts.h"
-#include "xparameters_ps.h"
-#include "xparameters.h"
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "task.h"
-#include "queue.h"
-#include "semphr.h"
-
-///* FreeRTOS+TCP includes. */
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_Sockets.h"
-#include "FreeRTOS_IP_Private.h"
-#include "NetworkBufferManagement.h"
-
-int phy_detected = 0;
-
-/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c
- *** to run it on a PEEP board
- ***/
-
-/* Advertisement control register. */
-#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_100_AND_10   (ADVERTISE_10FULL | ADVERTISE_100FULL | \
-                                                               ADVERTISE_10HALF | ADVERTISE_100HALF)
-#define ADVERTISE_100                  (ADVERTISE_100FULL | ADVERTISE_100HALF)
-#define ADVERTISE_10                   (ADVERTISE_10FULL | ADVERTISE_10HALF)
-
-#define ADVERTISE_1000                 0x0300
-
-
-//#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 IEEE_CONTROL_REG_OFFSET                                0
-#define IEEE_STATUS_REG_OFFSET                         1
-#define IEEE_AUTONEGO_ADVERTISE_REG                    4
-#define IEEE_PARTNER_ABILITIES_1_REG_OFFSET    5
-#define IEEE_1000_ADVERTISE_REG_OFFSET         9
-#define IEEE_PARTNER_ABILITIES_3_REG_OFFSET    10
-#define IEEE_COPPER_SPECIFIC_CONTROL_REG       16
-#define IEEE_SPECIFIC_STATUS_REG                       17
-#define IEEE_COPPER_SPECIFIC_STATUS_REG_2      19
-#define IEEE_CONTROL_REG_MAC                           21
-#define IEEE_PAGE_ADDRESS_REGISTER                     22
-
-
-#define IEEE_CTRL_1GBPS_LINKSPEED_MASK         0x2040
-#define IEEE_CTRL_LINKSPEED_MASK                       0x0040
-#define IEEE_CTRL_LINKSPEED_1000M                      0x0040
-#define IEEE_CTRL_LINKSPEED_100M                       0x2000
-#define IEEE_CTRL_LINKSPEED_10M                                0x0000
-#define IEEE_CTRL_RESET_MASK                           0x8000
-#define IEEE_CTRL_AUTONEGOTIATE_ENABLE         0x1000
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
-#define IEEE_CTRL_RESET                         0x9140
-#define IEEE_CTRL_ISOLATE_DISABLE               0xFBFF
-#endif
-#define IEEE_STAT_AUTONEGOTIATE_CAPABLE                0x0008
-#define IEEE_STAT_AUTONEGOTIATE_COMPLETE       0x0020
-#define IEEE_STAT_AUTONEGOTIATE_RESTART                0x0200
-#define IEEE_STAT_1GBPS_EXTENSIONS                     0x0100
-#define IEEE_AN1_ABILITY_MASK                          0x1FE0
-#define IEEE_AN3_ABILITY_MASK_1GBPS                    0x0C00
-#define IEEE_AN1_ABILITY_MASK_100MBPS          0x0380
-#define IEEE_AN1_ABILITY_MASK_10MBPS           0x0060
-#define IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK     0x0030
-
-#define IEEE_ASYMMETRIC_PAUSE_MASK                     0x0800
-#define IEEE_PAUSE_MASK                                                0x0400
-#define IEEE_AUTONEG_ERROR_MASK                                0x8000
-
-#define PHY_DETECT_REG  1
-#define PHY_DETECT_MASK 0x1808
-
-#define XEMACPS_GMII2RGMII_SPEED1000_FD                0x140
-#define XEMACPS_GMII2RGMII_SPEED100_FD         0x2100
-#define XEMACPS_GMII2RGMII_SPEED10_FD          0x100
-#define XEMACPS_GMII2RGMII_REG_NUM                     0x10
-
-/* Frequency setting */
-#define SLCR_LOCK_ADDR                 (XPS_SYS_CTRL_BASEADDR + 0x4)
-#define SLCR_UNLOCK_ADDR               (XPS_SYS_CTRL_BASEADDR + 0x8)
-#define SLCR_GEM0_CLK_CTRL_ADDR        (XPS_SYS_CTRL_BASEADDR + 0x140)
-#define SLCR_GEM1_CLK_CTRL_ADDR        (XPS_SYS_CTRL_BASEADDR + 0x144)
-#ifdef PEEP
-#define SLCR_GEM_10M_CLK_CTRL_VALUE            0x00103031
-#define SLCR_GEM_100M_CLK_CTRL_VALUE   0x00103001
-#define SLCR_GEM_1G_CLK_CTRL_VALUE             0x00103011
-#endif
-#define SLCR_LOCK_KEY_VALUE                    0x767B
-#define SLCR_UNLOCK_KEY_VALUE                  0xDF0D
-#define SLCR_ADDR_GEM_RST_CTRL                 (XPS_SYS_CTRL_BASEADDR + 0x214)
-#define EMACPS_SLCR_DIV_MASK                   0xFC0FC0FF
-
-#define EMAC0_BASE_ADDRESS                             0xE000B000
-#define EMAC1_BASE_ADDRESS                             0xE000C000
-
-static int detect_phy(XEmacPs *xemacpsp)
-{
-       u16 phy_reg;
-       u32 phy_addr;
-
-       for (phy_addr = 31; phy_addr > 0; phy_addr--) {
-               XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_DETECT_REG,
-                                                       &phy_reg);
-
-               if ((phy_reg != 0xFFFF) &&
-                       ((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
-                       /* Found a valid PHY address */
-                       FreeRTOS_printf( ("XEmacPs detect_phy: PHY detected at address %d.\r\n",
-                                                                                                                                       phy_addr));
-                       FreeRTOS_printf( ("XEmacPs detect_phy: PHY detected.\n" ) );
-                       phy_detected = phy_addr;
-                       return phy_addr;
-               }
-       }
-
-       FreeRTOS_printf( ("XEmacPs detect_phy: No PHY detected.  Assuming a PHY at address 0\n" ) );
-
-        /* default to zero */
-       return 0;
-}
-
-#ifdef PEEP
-unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)
-{
-
-       u16 control;
-       u16 status;
-       u16 partner_capabilities;
-       u16 partner_capabilities_1000;
-       u16 phylinkspeed;
-       u32 phy_addr = detect_phy(xemacpsp);
-
-       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
-                                                                                                                       ADVERTISE_1000);
-       /* Advertise PHY speed of 100 and 10 Mbps */
-       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
-                                                                                                       ADVERTISE_100_AND_10);
-
-       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,
-                                                                                                                               &control);
-       control |= (IEEE_CTRL_AUTONEGOTIATE_ENABLE |
-                                       IEEE_STAT_AUTONEGOTIATE_RESTART);
-
-       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
-
-       /* Read PHY control and status registers is successful. */
-       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
-       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
-
-       if ((control & IEEE_CTRL_AUTONEGOTIATE_ENABLE) && (status &
-                                       IEEE_STAT_AUTONEGOTIATE_CAPABLE)) {
-
-               while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
-                       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,
-                                                                                                                               &status);
-               }
-
-               XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET,
-                                                                                                                       &partner_capabilities);
-
-               if (status & IEEE_STAT_1GBPS_EXTENSIONS) {
-                       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_3_REG_OFFSET,
-                                                                                                               &partner_capabilities_1000);
-                       if (partner_capabilities_1000 & IEEE_AN3_ABILITY_MASK_1GBPS)
-                               return 1000;
-               }
-
-               if (partner_capabilities & IEEE_AN1_ABILITY_MASK_100MBPS)
-                       return 100;
-               if (partner_capabilities & IEEE_AN1_ABILITY_MASK_10MBPS)
-                       return 10;
-
-               xil_printf("%s: unknown PHY link speed, setting TEMAC speed to be 10 Mbps\r\n",
-                               __FUNCTION__);
-               return 10;
-
-       } else {
-
-               /* Update TEMAC speed accordingly */
-               if (status & IEEE_STAT_1GBPS_EXTENSIONS) {
-                       /* Get commanded link speed */
-                       phylinkspeed = control & IEEE_CTRL_1GBPS_LINKSPEED_MASK;
-
-                       switch (phylinkspeed) {
-                               case (IEEE_CTRL_LINKSPEED_1000M):
-                                       return 1000;
-                               case (IEEE_CTRL_LINKSPEED_100M):
-                                       return 100;
-                               case (IEEE_CTRL_LINKSPEED_10M):
-                                       return 10;
-                               default:
-                                       xil_printf("%s: unknown PHY link speed (%d), setting TEMAC speed to be 10 Mbps\r\n",
-                                                       __FUNCTION__, phylinkspeed);
-                                       return 10;
-                       }
-
-               } else {
-
-                       return (control & IEEE_CTRL_LINKSPEED_MASK) ? 100 : 10;
-
-               }
-       }
-}
-
-#else /* Zynq */
-unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)
-{
-       u16 temp;
-       u16 control;
-       u16 status;
-       u16 partner_capabilities;
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
-       u32 phy_addr = XPAR_PCSPMA_SGMII_PHYADDR;
-#else
-       u32 phy_addr = detect_phy(xemacpsp);
-#endif
-       xil_printf("Start PHY autonegotiation \r\n");
-
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
-#else
-       XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
-       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
-       control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
-       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);
-
-       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
-
-       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
-       control |= IEEE_ASYMMETRIC_PAUSE_MASK;
-       control |= IEEE_PAUSE_MASK;
-       control |= ADVERTISE_100;
-       control |= ADVERTISE_10;
-       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
-
-       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
-                                                                                                                                       &control);
-       control |= ADVERTISE_1000;
-       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
-                                                                                                                                       control);
-
-       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
-       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
-                                                                                                                               &control);
-       control |= (7 << 12);   /* max number of gigabit attempts */
-       control |= (1 << 11);   /* enable downshift */
-       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
-                                                                                                                               control);
-#endif
-       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
-       control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
-       control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
-    control &= IEEE_CTRL_ISOLATE_DISABLE;
-#endif
-
-       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
-
-
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
-#else
-       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
-       control |= IEEE_CTRL_RESET_MASK;
-       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
-
-       while (1) {
-               XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
-               if (control & IEEE_CTRL_RESET_MASK)
-                       continue;
-               else
-                       break;
-       }
-#endif
-       xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
-
-       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
-       while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
-               sleep(1);
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
-#else
-               XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2,
-                                                                                                                                       &temp);
-               if (temp & IEEE_AUTONEG_ERROR_MASK) {
-                       xil_printf("Auto negotiation error \r\n");
-               }
-#endif
-               XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,
-                                                                                                                               &status);
-               }
-
-       xil_printf("autonegotiation complete \r\n");
-
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
-#else
-       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_SPECIFIC_STATUS_REG, &partner_capabilities);
-#endif
-
-#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
-       xil_printf("Waiting for Link to be up; Polling for SGMII core Reg \r\n");
-       XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);
-       while(!(temp & 0x8000)) {
-               XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);
-       }
-       if((temp & 0x0C00) == 0x0800) {
-               XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
-               return 1000;
-       }
-       else if((temp & 0x0C00) == 0x0400) {
-               XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
-               return 100;
-       }
-       else if((temp & 0x0C00) == 0x0000) {
-               XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
-               return 10;
-       } else {
-               xil_printf("get_IEEE_phy_speed(): Invalid speed bit value, Deafulting to Speed = 10 Mbps\r\n");
-               XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
-               XEmacPs_PhyWrite(xemacpsp, phy_addr, 0, 0x0100);
-               return 10;
-       }
-#else
-       if ( ((partner_capabilities >> 14) & 3) == 2)/* 1000Mbps */
-               return 1000;
-       else if ( ((partner_capabilities >> 14) & 3) == 1)/* 100Mbps */
-               return 100;
-       else                                    /* 10Mbps */
-               return 10;
-#endif
-}
-#endif
-
-unsigned configure_IEEE_phy_speed(XEmacPs *xemacpsp, unsigned speed)
-{
-       u16 control;
-       u32 phy_addr = detect_phy(xemacpsp);
-
-       XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
-       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
-       control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
-       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);
-
-       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
-
-       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
-       control |= IEEE_ASYMMETRIC_PAUSE_MASK;
-       control |= IEEE_PAUSE_MASK;
-       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
-
-       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
-       control &= ~IEEE_CTRL_LINKSPEED_1000M;
-       control &= ~IEEE_CTRL_LINKSPEED_100M;
-       control &= ~IEEE_CTRL_LINKSPEED_10M;
-
-       if (speed == 1000) {
-               control |= IEEE_CTRL_LINKSPEED_1000M;
-       }
-
-       else if (speed == 100) {
-               control |= IEEE_CTRL_LINKSPEED_100M;
-               /* Dont advertise PHY speed of 1000 Mbps */
-               XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, 0);
-               /* Dont advertise PHY speed of 10 Mbps */
-               XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
-                                                                                                                               ADVERTISE_100);
-       }
-
-       else if (speed == 10) {
-               control |= IEEE_CTRL_LINKSPEED_10M;
-               /* Dont advertise PHY speed of 1000 Mbps */
-               XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
-                                                                                                                                                       0);
-               /* Dont advertise PHY speed of 100 Mbps */
-               XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
-                                                                                                                               ADVERTISE_10);
-       }
-
-       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,
-                                                                                       control | IEEE_CTRL_RESET_MASK);
-       {
-               volatile int wait;
-               for (wait=0; wait < 100000; wait++);
-       }
-       return 0;
-}
-
-static void SetUpSLCRDivisors(int mac_baseaddr, int speed)
-{
-       volatile u32 slcrBaseAddress;
-#ifndef PEEP
-       u32 SlcrDiv0;
-       u32 SlcrDiv1=0;
-       u32 SlcrTxClkCntrl;
-#endif
-
-       *(volatile unsigned int *)(SLCR_UNLOCK_ADDR) = SLCR_UNLOCK_KEY_VALUE;
-
-       if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {
-               slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR;
-       } else {
-               slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR;
-       }
-#ifdef PEEP
-       if (speed == 1000) {
-               *(volatile unsigned int *)(slcrBaseAddress) =
-                                                                                       SLCR_GEM_1G_CLK_CTRL_VALUE;
-       } else if (speed == 100) {
-               *(volatile unsigned int *)(slcrBaseAddress) =
-                                                                                       SLCR_GEM_100M_CLK_CTRL_VALUE;
-       } else {
-               *(volatile unsigned int *)(slcrBaseAddress) =
-                                                                                       SLCR_GEM_10M_CLK_CTRL_VALUE;
-       }
-#else
-       if (speed == 1000) {
-               if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {
-#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0
-                       SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
-                       SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;
-#endif
-               } else {
-#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0
-                       SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
-                       SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;
-#endif
-               }
-       } else if (speed == 100) {
-               if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {
-#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0
-                       SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
-                       SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;
-#endif
-               } else {
-#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0
-                       SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
-                       SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;
-#endif
-               }
-       } else {
-               if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {
-#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0
-                       SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
-                       SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;
-#endif
-               } else {
-#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0
-                       SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
-                       SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;
-#endif
-               }
-       }
-       SlcrTxClkCntrl = *(volatile unsigned int *)(slcrBaseAddress);
-       SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK;
-       SlcrTxClkCntrl |= (SlcrDiv1 << 20);
-       SlcrTxClkCntrl |= (SlcrDiv0 << 8);
-       *(volatile unsigned int *)(slcrBaseAddress) = SlcrTxClkCntrl;
-#endif
-       *(volatile unsigned int *)(SLCR_LOCK_ADDR) = SLCR_LOCK_KEY_VALUE;
-       return;
-}
-
-
-unsigned link_speed;
-unsigned Phy_Setup (XEmacPs *xemacpsp)
-{
-       unsigned long conv_present = 0;
-       unsigned long convspeeddupsetting = 0;
-       unsigned long convphyaddr = 0;
-
-#ifdef XPAR_GMII2RGMIICON_0N_ETH0_ADDR
-       convphyaddr = XPAR_GMII2RGMIICON_0N_ETH0_ADDR;
-       conv_present = 1;
-#else
-#ifdef XPAR_GMII2RGMIICON_0N_ETH1_ADDR
-       convphyaddr = XPAR_GMII2RGMIICON_0N_ETH1_ADDR;
-       conv_present = 1;
-#endif
-#endif
-
-#ifdef  ipconfigNIC_LINKSPEED_AUTODETECT
-       link_speed = get_IEEE_phy_speed(xemacpsp);
-       if (link_speed == 1000) {
-               SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
-               convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
-       } else if (link_speed == 100) {
-               SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
-               convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
-       } else {
-               SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
-               convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
-       }
-#elif  defined(ipconfigNIC_LINKSPEED1000)
-       SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
-       link_speed = 1000;
-       configure_IEEE_phy_speed(xemacpsp, link_speed);
-       convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
-       sleep(1);
-#elif  defined(ipconfigNIC_LINKSPEED100)
-       SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
-       link_speed = 100;
-       configure_IEEE_phy_speed(xemacpsp, link_speed);
-       convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
-       sleep(1);
-#elif  defined(ipconfigNIC_LINKSPEED10)
-       SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
-       link_speed = 10;
-       configure_IEEE_phy_speed(xemacpsp, link_speed);
-       convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
-       sleep(1);
-#endif
-       if (conv_present) {
-               XEmacPs_PhyWrite(xemacpsp, convphyaddr,
-               XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting);
-       }
-
-       xil_printf("link speed: %d\r\n", link_speed);
-       return link_speed;
-}
-
+/*\r
+ * Copyright (c) 2007-2008, Advanced Micro Devices, Inc.\r
+ *               All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ *    * Redistributions of source code must retain the above copyright\r
+ *      notice, this list of conditions and the following disclaimer.\r
+ *    * Redistributions in binary form must reproduce the above copyright\r
+ *      notice, this list of conditions and the following disclaimer in\r
+ *      the documentation and/or other materials provided with the\r
+ *      distribution.\r
+ *    * Neither the name of Advanced Micro Devices, Inc. nor the names\r
+ *      of its contributors may be used to endorse or promote products\r
+ *      derived from this software without specific prior written\r
+ *      permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\r
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+/*\r
+ * Some portions copyright (c) 2010-2013 Xilinx, Inc.  All rights reserved.\r
+ *\r
+ * Xilinx, Inc.\r
+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A\r
+ * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS\r
+ * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR\r
+ * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION\r
+ * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE\r
+ * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.\r
+ * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO\r
+ * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO\r
+ * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE\r
+ * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY\r
+ * AND FITNESS FOR A PARTICULAR PURPOSE.\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+#include "Zynq/x_emacpsif.h"\r
+//#include "lwipopts.h"\r
+#include "xparameters_ps.h"\r
+#include "xparameters.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
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+int phy_detected = 0;\r
+\r
+/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c\r
+ *** to run it on a PEEP board\r
+ ***/\r
+\r
+/* Advertisement control register. */\r
+#define ADVERTISE_10HALF               0x0020  /* Try for 10mbps half-duplex  */\r
+#define ADVERTISE_10FULL               0x0040  /* Try for 10mbps full-duplex  */\r
+#define ADVERTISE_100HALF              0x0080  /* Try for 100mbps half-duplex */\r
+#define ADVERTISE_100FULL              0x0100  /* Try for 100mbps full-duplex */\r
+\r
+#define ADVERTISE_100_AND_10   (ADVERTISE_10FULL | ADVERTISE_100FULL | \\r
+                                                               ADVERTISE_10HALF | ADVERTISE_100HALF)\r
+#define ADVERTISE_100                  (ADVERTISE_100FULL | ADVERTISE_100HALF)\r
+#define ADVERTISE_10                   (ADVERTISE_10FULL | ADVERTISE_10HALF)\r
+\r
+#define ADVERTISE_1000                 0x0300\r
+\r
+\r
+//#define PHY_REG_00_BMCR            0x00 // Basic mode control register\r
+//#define PHY_REG_01_BMSR            0x01 // Basic mode status register\r
+//#define PHY_REG_02_PHYSID1         0x02 // PHYS ID 1\r
+//#define PHY_REG_03_PHYSID2         0x03 // PHYS ID 2\r
+//#define PHY_REG_04_ADVERTISE       0x04 // Advertisement control reg\r
+\r
+#define IEEE_CONTROL_REG_OFFSET                                0\r
+#define IEEE_STATUS_REG_OFFSET                         1\r
+#define IEEE_AUTONEGO_ADVERTISE_REG                    4\r
+#define IEEE_PARTNER_ABILITIES_1_REG_OFFSET    5\r
+#define IEEE_1000_ADVERTISE_REG_OFFSET         9\r
+#define IEEE_PARTNER_ABILITIES_3_REG_OFFSET    10\r
+#define IEEE_COPPER_SPECIFIC_CONTROL_REG       16\r
+#define IEEE_SPECIFIC_STATUS_REG                       17\r
+#define IEEE_COPPER_SPECIFIC_STATUS_REG_2      19\r
+#define IEEE_CONTROL_REG_MAC                           21\r
+#define IEEE_PAGE_ADDRESS_REGISTER                     22\r
+\r
+\r
+#define IEEE_CTRL_1GBPS_LINKSPEED_MASK         0x2040\r
+#define IEEE_CTRL_LINKSPEED_MASK                       0x0040\r
+#define IEEE_CTRL_LINKSPEED_1000M                      0x0040\r
+#define IEEE_CTRL_LINKSPEED_100M                       0x2000\r
+#define IEEE_CTRL_LINKSPEED_10M                                0x0000\r
+#define IEEE_CTRL_RESET_MASK                           0x8000\r
+#define IEEE_CTRL_AUTONEGOTIATE_ENABLE         0x1000\r
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
+#define IEEE_CTRL_RESET                         0x9140\r
+#define IEEE_CTRL_ISOLATE_DISABLE               0xFBFF\r
+#endif\r
+#define IEEE_STAT_AUTONEGOTIATE_CAPABLE                0x0008\r
+#define IEEE_STAT_AUTONEGOTIATE_COMPLETE       0x0020\r
+#define IEEE_STAT_AUTONEGOTIATE_RESTART                0x0200\r
+#define IEEE_STAT_1GBPS_EXTENSIONS                     0x0100\r
+#define IEEE_AN1_ABILITY_MASK                          0x1FE0\r
+#define IEEE_AN3_ABILITY_MASK_1GBPS                    0x0C00\r
+#define IEEE_AN1_ABILITY_MASK_100MBPS          0x0380\r
+#define IEEE_AN1_ABILITY_MASK_10MBPS           0x0060\r
+#define IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK     0x0030\r
+\r
+#define IEEE_ASYMMETRIC_PAUSE_MASK                     0x0800\r
+#define IEEE_PAUSE_MASK                                                0x0400\r
+#define IEEE_AUTONEG_ERROR_MASK                                0x8000\r
+\r
+#define PHY_DETECT_REG  1\r
+#define PHY_DETECT_MASK 0x1808\r
+\r
+#define XEMACPS_GMII2RGMII_SPEED1000_FD                0x140\r
+#define XEMACPS_GMII2RGMII_SPEED100_FD         0x2100\r
+#define XEMACPS_GMII2RGMII_SPEED10_FD          0x100\r
+#define XEMACPS_GMII2RGMII_REG_NUM                     0x10\r
+\r
+/* Frequency setting */\r
+#define SLCR_LOCK_ADDR                 (XPS_SYS_CTRL_BASEADDR + 0x4)\r
+#define SLCR_UNLOCK_ADDR               (XPS_SYS_CTRL_BASEADDR + 0x8)\r
+#define SLCR_GEM0_CLK_CTRL_ADDR        (XPS_SYS_CTRL_BASEADDR + 0x140)\r
+#define SLCR_GEM1_CLK_CTRL_ADDR        (XPS_SYS_CTRL_BASEADDR + 0x144)\r
+#ifdef PEEP\r
+#define SLCR_GEM_10M_CLK_CTRL_VALUE            0x00103031\r
+#define SLCR_GEM_100M_CLK_CTRL_VALUE   0x00103001\r
+#define SLCR_GEM_1G_CLK_CTRL_VALUE             0x00103011\r
+#endif\r
+#define SLCR_LOCK_KEY_VALUE                    0x767B\r
+#define SLCR_UNLOCK_KEY_VALUE                  0xDF0D\r
+#define SLCR_ADDR_GEM_RST_CTRL                 (XPS_SYS_CTRL_BASEADDR + 0x214)\r
+#define EMACPS_SLCR_DIV_MASK                   0xFC0FC0FF\r
+\r
+#define EMAC0_BASE_ADDRESS                             0xE000B000\r
+#define EMAC1_BASE_ADDRESS                             0xE000C000\r
+\r
+static int detect_phy(XEmacPs *xemacpsp)\r
+{\r
+       u16 phy_reg;\r
+       u32 phy_addr;\r
+\r
+       for (phy_addr = 31; phy_addr > 0; phy_addr--) {\r
+               XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_DETECT_REG,\r
+                                                       &phy_reg);\r
+\r
+               if ((phy_reg != 0xFFFF) &&\r
+                       ((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {\r
+                       /* Found a valid PHY address */\r
+                       FreeRTOS_printf( ("XEmacPs detect_phy: PHY detected at address %d.\r\n",\r
+                                                                                                                                       phy_addr));\r
+                       FreeRTOS_printf( ("XEmacPs detect_phy: PHY detected.\n" ) );\r
+                       phy_detected = phy_addr;\r
+                       return phy_addr;\r
+               }\r
+       }\r
+\r
+       FreeRTOS_printf( ("XEmacPs detect_phy: No PHY detected.  Assuming a PHY at address 0\n" ) );\r
+\r
+        /* default to zero */\r
+       return 0;\r
+}\r
+\r
+#ifdef PEEP\r
+unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)\r
+{\r
+\r
+       u16 control;\r
+       u16 status;\r
+       u16 partner_capabilities;\r
+       u16 partner_capabilities_1000;\r
+       u16 phylinkspeed;\r
+       u32 phy_addr = detect_phy(xemacpsp);\r
+\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,\r
+                                                                                                                       ADVERTISE_1000);\r
+       /* Advertise PHY speed of 100 and 10 Mbps */\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,\r
+                                                                                                       ADVERTISE_100_AND_10);\r
+\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,\r
+                                                                                                                               &control);\r
+       control |= (IEEE_CTRL_AUTONEGOTIATE_ENABLE |\r
+                                       IEEE_STAT_AUTONEGOTIATE_RESTART);\r
+\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);\r
+\r
+       /* Read PHY control and status registers is successful. */\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);\r
+\r
+       if ((control & IEEE_CTRL_AUTONEGOTIATE_ENABLE) && (status &\r
+                                       IEEE_STAT_AUTONEGOTIATE_CAPABLE)) {\r
+\r
+               while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {\r
+                       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,\r
+                                                                                                                               &status);\r
+               }\r
+\r
+               XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET,\r
+                                                                                                                       &partner_capabilities);\r
+\r
+               if (status & IEEE_STAT_1GBPS_EXTENSIONS) {\r
+                       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_3_REG_OFFSET,\r
+                                                                                                               &partner_capabilities_1000);\r
+                       if (partner_capabilities_1000 & IEEE_AN3_ABILITY_MASK_1GBPS)\r
+                               return 1000;\r
+               }\r
+\r
+               if (partner_capabilities & IEEE_AN1_ABILITY_MASK_100MBPS)\r
+                       return 100;\r
+               if (partner_capabilities & IEEE_AN1_ABILITY_MASK_10MBPS)\r
+                       return 10;\r
+\r
+               xil_printf("%s: unknown PHY link speed, setting TEMAC speed to be 10 Mbps\r\n",\r
+                               __FUNCTION__);\r
+               return 10;\r
+\r
+       } else {\r
+\r
+               /* Update TEMAC speed accordingly */\r
+               if (status & IEEE_STAT_1GBPS_EXTENSIONS) {\r
+                       /* Get commanded link speed */\r
+                       phylinkspeed = control & IEEE_CTRL_1GBPS_LINKSPEED_MASK;\r
+\r
+                       switch (phylinkspeed) {\r
+                               case (IEEE_CTRL_LINKSPEED_1000M):\r
+                                       return 1000;\r
+                               case (IEEE_CTRL_LINKSPEED_100M):\r
+                                       return 100;\r
+                               case (IEEE_CTRL_LINKSPEED_10M):\r
+                                       return 10;\r
+                               default:\r
+                                       xil_printf("%s: unknown PHY link speed (%d), setting TEMAC speed to be 10 Mbps\r\n",\r
+                                                       __FUNCTION__, phylinkspeed);\r
+                                       return 10;\r
+                       }\r
+\r
+               } else {\r
+\r
+                       return (control & IEEE_CTRL_LINKSPEED_MASK) ? 100 : 10;\r
+\r
+               }\r
+       }\r
+}\r
+\r
+#else /* Zynq */\r
+unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)\r
+{\r
+       u16 temp;\r
+       u16 control;\r
+       u16 status;\r
+       u16 partner_capabilities;\r
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
+       u32 phy_addr = XPAR_PCSPMA_SGMII_PHYADDR;\r
+#else\r
+       u32 phy_addr = detect_phy(xemacpsp);\r
+#endif\r
+       xil_printf("Start PHY autonegotiation \r\n");\r
+\r
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
+#else\r
+       XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);\r
+       control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);\r
+\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);\r
+\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);\r
+       control |= IEEE_ASYMMETRIC_PAUSE_MASK;\r
+       control |= IEEE_PAUSE_MASK;\r
+       control |= ADVERTISE_100;\r
+       control |= ADVERTISE_10;\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);\r
+\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,\r
+                                                                                                                                       &control);\r
+       control |= ADVERTISE_1000;\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,\r
+                                                                                                                                       control);\r
+\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,\r
+                                                                                                                               &control);\r
+       control |= (7 << 12);   /* max number of gigabit attempts */\r
+       control |= (1 << 11);   /* enable downshift */\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,\r
+                                                                                                                               control);\r
+#endif\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
+       control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;\r
+       control |= IEEE_STAT_AUTONEGOTIATE_RESTART;\r
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
+    control &= IEEE_CTRL_ISOLATE_DISABLE;\r
+#endif\r
+\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);\r
+\r
+\r
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
+#else\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
+       control |= IEEE_CTRL_RESET_MASK;\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);\r
+\r
+       while (1) {\r
+               XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
+               if (control & IEEE_CTRL_RESET_MASK)\r
+                       continue;\r
+               else\r
+                       break;\r
+       }\r
+#endif\r
+       xil_printf("Waiting for PHY to complete autonegotiation.\r\n");\r
+\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);\r
+       while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {\r
+               sleep(1);\r
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
+#else\r
+               XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2,\r
+                                                                                                                                       &temp);\r
+               if (temp & IEEE_AUTONEG_ERROR_MASK) {\r
+                       xil_printf("Auto negotiation error \r\n");\r
+               }\r
+#endif\r
+               XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,\r
+                                                                                                                               &status);\r
+               }\r
+\r
+       xil_printf("autonegotiation complete \r\n");\r
+\r
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
+#else\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_SPECIFIC_STATUS_REG, &partner_capabilities);\r
+#endif\r
+\r
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
+       xil_printf("Waiting for Link to be up; Polling for SGMII core Reg \r\n");\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);\r
+       while(!(temp & 0x8000)) {\r
+               XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);\r
+       }\r
+       if((temp & 0x0C00) == 0x0800) {\r
+               XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);\r
+               return 1000;\r
+       }\r
+       else if((temp & 0x0C00) == 0x0400) {\r
+               XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);\r
+               return 100;\r
+       }\r
+       else if((temp & 0x0C00) == 0x0000) {\r
+               XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);\r
+               return 10;\r
+       } else {\r
+               xil_printf("get_IEEE_phy_speed(): Invalid speed bit value, Deafulting to Speed = 10 Mbps\r\n");\r
+               XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);\r
+               XEmacPs_PhyWrite(xemacpsp, phy_addr, 0, 0x0100);\r
+               return 10;\r
+       }\r
+#else\r
+       if ( ((partner_capabilities >> 14) & 3) == 2)/* 1000Mbps */\r
+               return 1000;\r
+       else if ( ((partner_capabilities >> 14) & 3) == 1)/* 100Mbps */\r
+               return 100;\r
+       else                                    /* 10Mbps */\r
+               return 10;\r
+#endif\r
+}\r
+#endif\r
+\r
+unsigned configure_IEEE_phy_speed(XEmacPs *xemacpsp, unsigned speed)\r
+{\r
+       u16 control;\r
+       u32 phy_addr = detect_phy(xemacpsp);\r
+\r
+       XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);\r
+       control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);\r
+\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);\r
+\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);\r
+       control |= IEEE_ASYMMETRIC_PAUSE_MASK;\r
+       control |= IEEE_PAUSE_MASK;\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);\r
+\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
+       control &= ~IEEE_CTRL_LINKSPEED_1000M;\r
+       control &= ~IEEE_CTRL_LINKSPEED_100M;\r
+       control &= ~IEEE_CTRL_LINKSPEED_10M;\r
+\r
+       if (speed == 1000) {\r
+               control |= IEEE_CTRL_LINKSPEED_1000M;\r
+       }\r
+\r
+       else if (speed == 100) {\r
+               control |= IEEE_CTRL_LINKSPEED_100M;\r
+               /* Dont advertise PHY speed of 1000 Mbps */\r
+               XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, 0);\r
+               /* Dont advertise PHY speed of 10 Mbps */\r
+               XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,\r
+                                                                                                                               ADVERTISE_100);\r
+       }\r
+\r
+       else if (speed == 10) {\r
+               control |= IEEE_CTRL_LINKSPEED_10M;\r
+               /* Dont advertise PHY speed of 1000 Mbps */\r
+               XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,\r
+                                                                                                                                                       0);\r
+               /* Dont advertise PHY speed of 100 Mbps */\r
+               XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,\r
+                                                                                                                               ADVERTISE_10);\r
+       }\r
+\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,\r
+                                                                                       control | IEEE_CTRL_RESET_MASK);\r
+       {\r
+               volatile int wait;\r
+               for (wait=0; wait < 100000; wait++);\r
+       }\r
+       return 0;\r
+}\r
+\r
+static void SetUpSLCRDivisors(int mac_baseaddr, int speed)\r
+{\r
+       volatile u32 slcrBaseAddress;\r
+#ifndef PEEP\r
+       u32 SlcrDiv0;\r
+       u32 SlcrDiv1=0;\r
+       u32 SlcrTxClkCntrl;\r
+#endif\r
+\r
+       *(volatile unsigned int *)(SLCR_UNLOCK_ADDR) = SLCR_UNLOCK_KEY_VALUE;\r
+\r
+       if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {\r
+               slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR;\r
+       } else {\r
+               slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR;\r
+       }\r
+#ifdef PEEP\r
+       if (speed == 1000) {\r
+               *(volatile unsigned int *)(slcrBaseAddress) =\r
+                                                                                       SLCR_GEM_1G_CLK_CTRL_VALUE;\r
+       } else if (speed == 100) {\r
+               *(volatile unsigned int *)(slcrBaseAddress) =\r
+                                                                                       SLCR_GEM_100M_CLK_CTRL_VALUE;\r
+       } else {\r
+               *(volatile unsigned int *)(slcrBaseAddress) =\r
+                                                                                       SLCR_GEM_10M_CLK_CTRL_VALUE;\r
+       }\r
+#else\r
+       if (speed == 1000) {\r
+               if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {\r
+#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0\r
+                       SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;\r
+                       SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;\r
+#endif\r
+               } else {\r
+#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0\r
+                       SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;\r
+                       SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;\r
+#endif\r
+               }\r
+       } else if (speed == 100) {\r
+               if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {\r
+#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0\r
+                       SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;\r
+                       SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;\r
+#endif\r
+               } else {\r
+#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0\r
+                       SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;\r
+                       SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;\r
+#endif\r
+               }\r
+       } else {\r
+               if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {\r
+#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0\r
+                       SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;\r
+                       SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;\r
+#endif\r
+               } else {\r
+#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0\r
+                       SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;\r
+                       SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;\r
+#endif\r
+               }\r
+       }\r
+       SlcrTxClkCntrl = *(volatile unsigned int *)(slcrBaseAddress);\r
+       SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK;\r
+       SlcrTxClkCntrl |= (SlcrDiv1 << 20);\r
+       SlcrTxClkCntrl |= (SlcrDiv0 << 8);\r
+       *(volatile unsigned int *)(slcrBaseAddress) = SlcrTxClkCntrl;\r
+#endif\r
+       *(volatile unsigned int *)(SLCR_LOCK_ADDR) = SLCR_LOCK_KEY_VALUE;\r
+       return;\r
+}\r
+\r
+\r
+unsigned link_speed;\r
+unsigned Phy_Setup (XEmacPs *xemacpsp)\r
+{\r
+       unsigned long conv_present = 0;\r
+       unsigned long convspeeddupsetting = 0;\r
+       unsigned long convphyaddr = 0;\r
+\r
+#ifdef XPAR_GMII2RGMIICON_0N_ETH0_ADDR\r
+       convphyaddr = XPAR_GMII2RGMIICON_0N_ETH0_ADDR;\r
+       conv_present = 1;\r
+#else\r
+#ifdef XPAR_GMII2RGMIICON_0N_ETH1_ADDR\r
+       convphyaddr = XPAR_GMII2RGMIICON_0N_ETH1_ADDR;\r
+       conv_present = 1;\r
+#endif\r
+#endif\r
+\r
+#ifdef  ipconfigNIC_LINKSPEED_AUTODETECT\r
+       link_speed = get_IEEE_phy_speed(xemacpsp);\r
+       if (link_speed == 1000) {\r
+               SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);\r
+               convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;\r
+       } else if (link_speed == 100) {\r
+               SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);\r
+               convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;\r
+       } else {\r
+               SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);\r
+               convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;\r
+       }\r
+#elif  defined(ipconfigNIC_LINKSPEED1000)\r
+       SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);\r
+       link_speed = 1000;\r
+       configure_IEEE_phy_speed(xemacpsp, link_speed);\r
+       convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;\r
+       sleep(1);\r
+#elif  defined(ipconfigNIC_LINKSPEED100)\r
+       SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);\r
+       link_speed = 100;\r
+       configure_IEEE_phy_speed(xemacpsp, link_speed);\r
+       convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;\r
+       sleep(1);\r
+#elif  defined(ipconfigNIC_LINKSPEED10)\r
+       SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);\r
+       link_speed = 10;\r
+       configure_IEEE_phy_speed(xemacpsp, link_speed);\r
+       convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;\r
+       sleep(1);\r
+#endif\r
+       if (conv_present) {\r
+               XEmacPs_PhyWrite(xemacpsp, convphyaddr,\r
+               XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting);\r
+       }\r
+\r
+       xil_printf("link speed: %d\r\n", link_speed);\r
+       return link_speed;\r
+}\r
+\r
index 1d8fede15ff871dd778076161852b95bfa3be390..bb51783469e2c1e453c19df2795462f68bf69ce0 100644 (file)
@@ -1,46 +1,46 @@
-/*
- * Copyright (c) 2007-2013 Xilinx, Inc.  All rights reserved.
- *
- * Xilinx, Inc.
- * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
- * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
- * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
- * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
- * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
- * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
- * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
- * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
- * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
- * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-#ifndef __XTOPOLOGY_H_
-#define __XTOPOLOGY_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-enum xemac_types { xemac_type_unknown = -1, xemac_type_xps_emaclite, xemac_type_xps_ll_temac, xemac_type_axi_ethernet, xemac_type_emacps };
-
-struct xtopology_t {
-       unsigned emac_baseaddr;
-       enum xemac_types emac_type;
-       unsigned intc_baseaddr;
-       unsigned intc_emac_intr;        /* valid only for xemac_type_xps_emaclite */
-       unsigned scugic_baseaddr; /* valid only for Zynq */
-       unsigned scugic_emac_intr; /* valid only for GEM */
-};
-
-extern int x_topology_n_emacs;
-extern struct xtopology_t x_topology[];
-
-int x_topology_find_index(unsigned base);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+/*\r
+ * Copyright (c) 2007-2013 Xilinx, Inc.  All rights reserved.\r
+ *\r
+ * Xilinx, Inc.\r
+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A\r
+ * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS\r
+ * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR\r
+ * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION\r
+ * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE\r
+ * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.\r
+ * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO\r
+ * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO\r
+ * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE\r
+ * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY\r
+ * AND FITNESS FOR A PARTICULAR PURPOSE.\r
+ *\r
+ */\r
+\r
+#ifndef __XTOPOLOGY_H_\r
+#define __XTOPOLOGY_H_\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+enum xemac_types { xemac_type_unknown = -1, xemac_type_xps_emaclite, xemac_type_xps_ll_temac, xemac_type_axi_ethernet, xemac_type_emacps };\r
+\r
+struct xtopology_t {\r
+       unsigned emac_baseaddr;\r
+       enum xemac_types emac_type;\r
+       unsigned intc_baseaddr;\r
+       unsigned intc_emac_intr;        /* valid only for xemac_type_xps_emaclite */\r
+       unsigned scugic_baseaddr; /* valid only for Zynq */\r
+       unsigned scugic_emac_intr; /* valid only for GEM */\r
+};\r
+\r
+extern int x_topology_n_emacs;\r
+extern struct xtopology_t x_topology[];\r
+\r
+int x_topology_find_index(unsigned base);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
index 4692c12c4a5d3c04f6e88828e0aa01de491f3417..aa0a646b4b7307d026b834c66d84b53b2a787b80 100644 (file)
@@ -1,63 +1,63 @@
-/*
-FreeRTOS+TCP V2.0.11
-Copyright (C) 2018 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
-*/
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "list.h"
-
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_IP.h"
-
-/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
-driver will filter incoming packets and only pass the stack those packets it
-considers need processing. */
-#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
-#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
-#else
-#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
-#endif
-
-BaseType_t xNetworkInterfaceInitialise( void )
-{
-    /* FIX ME. */
-    return pdFALSE;
-}
-
-BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t xReleaseAfterSend )
-{
-    /* FIX ME. */
-    return pdFALSE;
-}
-
-void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
-{
-    /* FIX ME. */
-}
-
-BaseType_t xGetPhyLinkStatus( void )
-{
-    /* FIX ME. */
-    return pdFALSE;
+/*\r
+FreeRTOS+TCP V2.0.11\r
+Copyright (C) 2018 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
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "list.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+\r
+/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet\r
+driver will filter incoming packets and only pass the stack those packets it\r
+considers need processing. */\r
+#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )\r
+#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer\r
+#else\r
+#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )\r
+#endif\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+    /* FIX ME. */\r
+    return pdFALSE;\r
+}\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t xReleaseAfterSend )\r
+{\r
+    /* FIX ME. */\r
+    return pdFALSE;\r
+}\r
+\r
+void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )\r
+{\r
+    /* FIX ME. */\r
+}\r
+\r
+BaseType_t xGetPhyLinkStatus( void )\r
+{\r
+    /* FIX ME. */\r
+    return pdFALSE;\r
 }
\ No newline at end of file
index e4ae1168f6ef0a1e52e8f47f03e44ac3938d7f62..544e5ba095497386218b939f7dbc2d1ba1ee632c 100644 (file)
-/*
-FreeRTOS+TCP V2.0.11
-Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
- http://aws.amazon.com/freertos
- http://www.FreeRTOS.org
-*/
-
-/* Standard includes. */
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "task.h"
-#include "queue.h"
-#include "semphr.h"
-
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_Sockets.h"
-#include "FreeRTOS_IP_Private.h"
-#include "NetworkBufferManagement.h"
-#include "NetworkInterface.h"
-
-#include "sam4e_xplained_pro.h"
-#include "hr_gettime.h"
-#include "conf_eth.h"
-#include "ksz8851snl.h"
-#include "ksz8851snl_reg.h"
-
-/* Some files from the Atmel Software Framework */
-#include <sysclk.h>
-#include <pdc/pdc.h>
-#include <spi/spi.h>
-
-/*
-       Sending a packet:
-
-               1) Called by UP-task, add buffer to the TX-list:
-                       xNetworkInterfaceOutput()
-                               tx_buffers[ us_tx_head ] = pxNetworkBuffer;
-                               tx_busy[ us_tx_head ] = pdTRUE;
-                               us_tx_head++;
-
-               2) Called by EMAC-Task: start SPI transfer
-                       ksz8851snl_update()
-                       if( ul_spi_pdc_status == SPI_PDC_IDLE )
-                       {
-                               if( ( tx_busy[ us_tx_tail ] != pdFALSE ) &&
-                                       ( us_pending_frame == 0 ) &&
-                                       ( ul_had_intn_interrupt == 0 ) )
-                               {
-                                       // disable all interrupts.
-                                       ksz8851_reg_write( REG_INT_MASK, 0 );
-                                       Bring KSZ8851SNL_CSN_GPIO low
-                                       ksz8851_fifo_write( pxNetworkBuffer->pucEthernetBuffer, xLength, xLength );
-                                       ul_spi_pdc_status = SPI_PDC_TX_START;
-                                       tx_cur_buffer = pxNetworkBuffer;
-                               }
-                       }
-               3) Wait for SPI RXBUFF interrupt
-                       SPI_Handler()
-                               if( ul_spi_pdc_status == SPI_PDC_TX_START )
-                               {
-                                       if( SPI_Status & SPI_SR_RXBUFF )
-                                       {
-                                               ul_spi_pdc_status = SPI_PDC_TX_COMPLETE;
-                                       }
-                               }
-
-               4) Called by EMAC-Task: finish SPI transfer
-                       ksz8851snl_update()
-                               if( ul_spi_pdc_status == SPI_PDC_TX_COMPLETE )
-                               {
-                                       ul_spi_pdc_status = SPI_PDC_IDLE;
-                                       Bring KSZ8851SNL_CSN_GPIO high
-                                       // TX step12: disable TXQ write access.
-                                       ksz8851_reg_clrbits( REG_RXQ_CMD, RXQ_START );
-                                       // TX step12.1: enqueue frame in TXQ.
-                                       ksz8851_reg_setbits( REG_TXQ_CMD, TXQ_ENQUEUE );
-
-                                       // RX step13: enable INT_RX flag.
-                                       ksz8851_reg_write( REG_INT_MASK, INT_RX );
-
-                                       // Buffer sent, free the corresponding buffer and mark descriptor as owned by software.
-                                       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
-
-                                       tx_buffers[ us_tx_tail ] = NULL;
-                                       tx_busy[ us_tx_tail ] = pdFALSE;
-                                       us_tx_tail++
-                               }
-
-       Receiving a packet:
-
-               1) Wait for a INTN interrupt
-                       INTN_Handler()
-                               ul_had_intn_interrupt = 1
-                               vTaskNotifyGiveFromISR();       // Wake up the EMAC task
-
-               2) Called by EMAC-Task: check for new fragments and start SPI transfer
-                       ksz8851snl_update()
-                               if( ul_spi_pdc_status == SPI_PDC_IDLE )
-                               {
-                                       if( ( ul_had_intn_interrupt != 0 ) || ( us_pending_frame > 0 ) )
-                                       {
-                                               if( us_pending_frame == 0 )
-                                               {
-                                                       us_pending_frame = ksz8851_reg_read(REG_RX_FRAME_CNT_THRES) >> 8;
-                                                       if( us_pending_frame == 0 )
-                                                       {
-                                                               break;
-                                                       }
-                                               }
-                                               // RX step2: disable all interrupts.
-                                               ksz8851_reg_write( REG_INT_MASK, 0 );
-                                               Check if there is a valid packet: REG_RX_FHR_STATUS
-                                               Read the length of the next fragment: REG_RX_FHR_BYTE_CNT
-                                               ul_spi_pdc_status = SPI_PDC_RX_START;
-                                               gpio_set_pin_low(KSZ8851SNL_CSN_GPIO);
-                                               // Start SPI data transfer
-                                               ksz8851_fifo_read( pxNetworkBuffer->pucEthernetBuffer, xReadLength );
-                                       }
-                               }
-
-               3) Wait for SPI RXBUFF interrupt
-                       SPI_Handler()
-                       if( ul_spi_pdc_status == SPI_PDC_RX_START:
-                       {
-                               if( ( ulCurrentSPIStatus & SPI_SR_RXBUFF ) != 0 )
-                               {
-                                       // Transfer complete, disable SPI RXBUFF interrupt.
-                                       spi_disable_interrupt( KSZ8851SNL_SPI, SPI_IDR_RXBUFF );
-
-                                       ul_spi_pdc_status = SPI_PDC_RX_COMPLETE;
-                               }
-                       }
-               }
-
-               4) Finish SPI transfer
-                       ksz8851snl_update()
-                               if( ul_spi_pdc_status == SPI_PDC_RX_COMPLETE )
-                               {
-                                       ul_spi_pdc_status = SPI_PDC_IDLE;
-                                       Bring KSZ8851SNL_CSN_GPIO high
-                                       // RX step21: end RXQ read access.
-                                       ksz8851_reg_clrbits(REG_RXQ_CMD, RXQ_START);
-                                       // RX step22-23: update frame count to be read.
-                                       us_pending_frame--
-                                       // RX step24: enable INT_RX flag if transfer complete.
-                                       if( us_pending_frame == 0 )
-                                       {
-                                               // Allow more RX interrupts.
-                                               ksz8851_reg_write( REG_INT_MASK, INT_RX );
-                                       }
-
-                                       // Mark descriptor ready to be read.
-                                       rx_ready[ rxHead ] = pdTRUE;
-                                       rxHead++
-                               }
-*/
-
-#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_REG_05_LPA             0x05 // Link partner ability reg
-#define        PHY_REG_06_ANER            0x06 //      6       RW              Auto-Negotiation Expansion Register
-#define        PHY_REG_07_ANNPTR          0x07 //      7       RW              Auto-Negotiation Next Page TX
-#define        PHY_REG_08_RESERVED0       0x08 // 0x08..0x0Fh  8-15    RW              RESERVED
-
-#define BMSR_LINK_STATUS            0x0004  //!< Link status
-
-#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 ETHERNET_CONF_PHY_ADDR BOARD_GMAC_PHY_ADDR
-
-#ifdef ipconfigHAS_TX_CRC_OFFLOADING
-       #undef ipconfigHAS_TX_CRC_OFFLOADING
-#endif
-/* Override this define because the KSZ8851 is programmed to set all outgoing CRC's */
-#define        ipconfigHAS_TX_CRC_OFFLOADING   1
-
-#ifndef        EMAC_MAX_BLOCK_TIME_MS
-       #define EMAC_MAX_BLOCK_TIME_MS  100ul
-#endif
-
-/* Default the size of the stack used by the EMAC deferred handler task to 4x
-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 ( 6 * configMINIMAL_STACK_SIZE )
-#endif
-
-#define SPI_PDC_IDLE                   0
-#define SPI_PDC_RX_START               1
-#define SPI_PDC_TX_ERROR               2
-#define SPI_PDC_RX_COMPLETE            3
-#define SPI_PDC_TX_START               4
-#define SPI_PDC_RX_ERROR               5
-#define SPI_PDC_TX_COMPLETE            6
-
-/**
- * ksz8851snl driver structure.
- */
-typedef struct {
-       /** Set to 1 when owner is software (ready to read), 0 for Micrel. */
-       uint32_t rx_ready[MICREL_RX_BUFFERS];
-       /** Set to 1 when owner is Micrel, 0 for software. */
-       uint32_t tx_busy[MICREL_TX_BUFFERS];
-       /** RX NetworkBufferDescriptor_t pointer list */
-       NetworkBufferDescriptor_t *rx_buffers[MICREL_RX_BUFFERS];
-       /** TX NetworkBufferDescriptor_t pointer list */
-       NetworkBufferDescriptor_t *tx_buffers[MICREL_TX_BUFFERS];
-       NetworkBufferDescriptor_t *tx_cur_buffer;
-
-       /** Circular buffer head pointer for packet received. */
-       uint32_t us_rx_head;
-       /** Circular buffer tail pointer for packet to be read. */
-       uint32_t us_rx_tail;
-       /** Circular buffer head pointer by upper layer (buffer to be sent). */
-       uint32_t us_tx_head;
-       /** Circular buffer tail pointer incremented by handlers (buffer sent). */
-       uint32_t us_tx_tail;
-
-       uint32_t ul_total_tx;
-       uint32_t ul_total_rx;
-       uint32_t tx_space;
-
-       /** Still experimental: hash table to allow certain multicast addresses. */
-       uint16_t pusHashTable[ 4 ];
-
-       /* ul_spi_pdc_status has "SPI_PDC_xxx" values. */
-       volatile uint32_t ul_spi_pdc_status;
-
-       /* ul_had_intn_interrupt becomes true within the INTN interrupt. */
-       volatile uint32_t ul_had_intn_interrupt;
-
-       uint16_t us_pending_frame;
-} xKSZ8851_Device_t;
-
-/* SPI PDC register base.
-Declared in ASF\sam\components\ksz8851snl\ksz8851snl.c */
-extern Pdc *g_p_spi_pdc;
-
-/* Temporary buffer for PDC reception.
-declared in ASF\sam\components\ksz8851snl\ksz8851snl.c */
-extern uint8_t tmpbuf[1536];
-
-COMPILER_ALIGNED(8)
-static xKSZ8851_Device_t xMicrelDevice;
-
-static TaskHandle_t xTransmitHandle;
-
-/*-----------------------------------------------------------*/
-
-/*
- * Wait a fixed time for the link status to indicate the network is up.
- */
-static BaseType_t xGMACWaitLS( TickType_t xMaxTime );
-
-/*
- * A deferred interrupt handler task that processes GMAC interrupts.
- */
-static void prvEMACHandlerTask( void *pvParameters );
-
-/*
- * Try to obtain an Rx packet from the hardware.
- */
-static uint32_t prvEMACRxPoll( void );
-
-static inline unsigned long ulReadMDIO( unsigned uAddress );
-
-static void ksz8851snl_low_level_init( void );
-
-static NetworkBufferDescriptor_t *ksz8851snl_low_level_input( void );
-
-/*-----------------------------------------------------------*/
-
-/* 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;
-static volatile BaseType_t xGMACSwitchRequired;
-
-static void ksz8851snl_update( void );
-
-static void ksz8851snl_rx_init( void );
-
-static void ksz8851snl_tx_init( void );
-
-/* Holds the handle of the task used as a deferred interrupt processor.  The
-handle is used so direct notifications can be sent to the task for all EMAC/DMA
-related interrupts. */
-TaskHandle_t xEMACTaskHandle = NULL;
-
-
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceInitialise( void )
-{
-const TickType_t x5_Seconds = 5000UL;
-
-       if( xEMACTaskHandle == NULL )
-       {
-               ksz8851snl_low_level_init();
-
-               /* Wait at most 5 seconds for a Link Status in the PHY. */
-               xGMACWaitLS( pdMS_TO_TICKS( x5_Seconds ) );
-
-               /* The handler task is created at the highest possible priority to
-               ensure the interrupt handler can return directly to it. */
-               xTaskCreate( prvEMACHandlerTask, "KSZ8851", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );
-               configASSERT( xEMACTaskHandle );
-       }
-
-       /* When returning non-zero, the stack will become active and
-    start DHCP (in configured) */
-       ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );
-
-       return ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0;
-}
-/*-----------------------------------------------------------*/
-
-BaseType_t xGetPhyLinkStatus( void )
-{
-BaseType_t xResult;
-
-       /* This function returns true if the Link Status in the PHY is high. */
-       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
-       {
-               xResult = pdTRUE;
-       }
-       else
-       {
-               xResult = pdFALSE;
-       }
-
-       return xResult;
-}
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t bReleaseAfterSend )
-{
-BaseType_t xResult = pdFALSE;
-int txHead = xMicrelDevice.us_tx_head;
-
-       /* Make sure the next descriptor is free. */
-       if( xMicrelDevice.tx_busy[ txHead ] != pdFALSE )
-       {
-               /* All TX buffers busy. */
-       }
-       else if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )
-       {
-               /* Output: LS low. */
-       }
-       else
-       {
-               /* Pass the packet. */
-               xMicrelDevice.tx_buffers[ txHead ] = pxNetworkBuffer;
-               /* The descriptor is now owned by Micrel. */
-               xMicrelDevice.tx_busy[ txHead ] = pdTRUE;
-
-               /* Move the head pointer. */
-               if( ++txHead == MICREL_TX_BUFFERS )
-               {
-                       txHead = 0;
-               }
-               xMicrelDevice.us_tx_head = txHead;
-               if( xEMACTaskHandle != NULL )
-               {
-                       xTaskNotifyGive( xEMACTaskHandle );
-               }
-
-       #if( ipconfigZERO_COPY_TX_DRIVER != 1 )
-               #warning Please ipconfigZERO_COPY_TX_DRIVER as 1
-       #endif
-               configASSERT( bReleaseAfterSend != pdFALSE );
-               xResult = pdTRUE;
-       }
-       if( ( xResult == pdFALSE ) && ( bReleaseAfterSend  != pdFALSE ) )
-       {
-               vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
-       }
-       return xResult;
-}
-/*-----------------------------------------------------------*/
-
-/* This Micrel has numbered it's PHY registers in a different way.
-Translate the register index. */
-static int ks8851_phy_reg( int reg )
-{
-       switch (reg) {
-       case PHY_REG_00_BMCR:
-               return REG_PHY_CNTL;    // P1MBCR;
-       case PHY_REG_01_BMSR:
-               return REG_PHY_STATUS;
-       case PHY_REG_02_PHYSID1:
-               return REG_PHY_ID_LOW;
-       case PHY_REG_03_PHYSID2:
-               return REG_PHY_ID_HIGH;
-       case PHY_REG_04_ADVERTISE:
-               return REG_PHY_AUTO_NEGOTIATION;
-       case PHY_REG_05_LPA:
-               return REG_PHY_REMOTE_CAPABILITY;
-       }
-
-       return 0x0;
-}
-/*-----------------------------------------------------------*/
-
-static inline unsigned long ulReadMDIO( unsigned uAddress )
-{
-uint16_t usPHYStatus;
-int ks8851_reg = ks8851_phy_reg( uAddress );
-
-       if( ks8851_reg != 0 )
-       {
-               usPHYStatus = ksz8851_reg_read( ks8851_reg );
-       }
-       else
-       {
-               /* Other addresses not yet implemented. */
-               usPHYStatus = 0;
-       }
-       return usPHYStatus;
-}
-/*-----------------------------------------------------------*/
-
-static BaseType_t xGMACWaitLS( TickType_t xMaxTime )
-{
-TickType_t xStartTime = xTaskGetTickCount();
-TickType_t xEndTime;
-BaseType_t xReturn;
-const TickType_t xShortTime = pdMS_TO_TICKS( 100UL );
-const uint32_t ulHz_Per_MHz = 1000000UL;
-
-       for( ;; )
-       {
-               xEndTime = xTaskGetTickCount();
-
-               if( ( xEndTime - xStartTime ) > xMaxTime )
-               {
-                       /* Wated more than xMaxTime, return. */
-                       xReturn = pdFALSE;
-                       break;
-               }
-
-               /* Check the link status again. */
-               ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );
-
-               if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
-               {
-                       /* Link is up - return. */
-                       xReturn = pdTRUE;
-                       break;
-               }
-
-               /* Link is down - wait in the Blocked state for a short while (to allow
-               other tasks to execute) before checking again. */
-               vTaskDelay( xShortTime );
-       }
-
-       FreeRTOS_printf( ( "xGMACWaitLS: %ld freq %lu Mz\n",
-               xReturn,
-               sysclk_get_cpu_hz() / ulHz_Per_MHz ) );
-
-       return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-static void vPioSetPinHigh(uint32_t ul_pin)
-{
-       Pio *p_pio = (Pio *)((uint32_t)PIOA + (PIO_DELTA * (ul_pin >> 5)));
-       // Value to be driven on the I/O line: 1.
-       p_pio->PIO_SODR = 1 << (ul_pin & 0x1F);
-}
-
-/**
- * \brief Handler for SPI interrupt.
- */
-void SPI_Handler(void)
-{
-BaseType_t xDoWakeup = pdFALSE;
-BaseType_t xKSZTaskWoken = pdFALSE;
-uint32_t ulCurrentSPIStatus;
-uint32_t ulEnabledSPIStatus;
-
-       ulCurrentSPIStatus = spi_read_status( KSZ8851SNL_SPI );
-       ulEnabledSPIStatus = spi_read_interrupt_mask( KSZ8851SNL_SPI );
-       ulCurrentSPIStatus &= ulEnabledSPIStatus;
-       spi_disable_interrupt( KSZ8851SNL_SPI, ulCurrentSPIStatus );
-
-
-       switch( xMicrelDevice.ul_spi_pdc_status )
-       {
-               case SPI_PDC_RX_START:
-               {
-                       if( ( ulCurrentSPIStatus & SPI_SR_OVRES ) != 0 )
-                       {
-                               pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
-                               xMicrelDevice.ul_spi_pdc_status = SPI_PDC_RX_ERROR;
-                               xDoWakeup = pdTRUE;
-                       }
-                       else
-                       {
-                               if( ( ulCurrentSPIStatus & SPI_SR_RXBUFF ) != 0 )
-                               {
-                                       xMicrelDevice.ul_spi_pdc_status = SPI_PDC_RX_COMPLETE;
-                                       xDoWakeup = pdTRUE;
-                               }
-                       }
-               }
-               break;
-
-               case SPI_PDC_TX_START:
-               {
-                       /* Middle of TX. */
-                       if( ( ulCurrentSPIStatus & SPI_SR_OVRES ) != 0 )
-                       {
-                               pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
-                               xMicrelDevice.ul_spi_pdc_status = SPI_PDC_TX_ERROR;
-                               xDoWakeup = pdTRUE;
-                       }
-                       else
-                       {
-                               if( ( ulCurrentSPIStatus & SPI_SR_ENDRX ) != 0 )
-                               {
-                                       /* Enable RX complete interrupt. */
-                                       spi_enable_interrupt( KSZ8851SNL_SPI, SPI_IER_RXBUFF );
-                               }
-                               /* End of TX. */
-                               if( ( ulCurrentSPIStatus & SPI_END_OF_TX ) != 0 )
-                               {
-                                       xMicrelDevice.ul_spi_pdc_status = SPI_PDC_TX_COMPLETE;
-                                       xDoWakeup = pdTRUE;
-                               }
-                       }
-               }
-               break;
-       }       /* switch( xMicrelDevice.ul_spi_pdc_status ) */
-
-       if( xDoWakeup != pdFALSE )
-       {
-               if( xEMACTaskHandle != NULL )
-               {
-                       vTaskNotifyGiveFromISR( xEMACTaskHandle, ( BaseType_t * ) &xKSZTaskWoken );
-               }
-       }
-       else
-       {
-       }
-       portEND_SWITCHING_ISR( xKSZTaskWoken );
-}
-/*-----------------------------------------------------------*/
-
-static void INTN_Handler(uint32_t id, uint32_t mask)
-{
-BaseType_t xKSZTaskWoken = pdFALSE;
-
-       if( ( id == INTN_ID ) &&
-               ( mask == INTN_PIN_MSK ) )
-       {
-               /* Clear the PIO interrupt flags. */
-               pio_get_interrupt_status( INTN_PIO );
-
-               /* Set the INTN flag. */
-               xMicrelDevice.ul_had_intn_interrupt++;
-               if( xEMACTaskHandle != NULL )
-               {
-                       vTaskNotifyGiveFromISR( xEMACTaskHandle, &( xKSZTaskWoken ) );
-               }
-       }
-       portEND_SWITCHING_ISR( xKSZTaskWoken );
-}
-/*-----------------------------------------------------------*/
-
-/**
- * \brief Populate the RX descriptor ring buffers with pbufs.
- *
- * \param p_ksz8851snl_dev Pointer to driver data structure.
- */
-static void ksz8851snl_rx_populate_queue( void )
-{
-       uint32_t ul_index = 0;
-       NetworkBufferDescriptor_t *pxNetworkBuffer;
-
-       /* Set up the RX descriptors */
-       for (ul_index = 0; ul_index < MICREL_RX_BUFFERS; ul_index++) {
-               if( xMicrelDevice.rx_buffers[ ul_index ] == NULL )
-               {
-                       /* Allocate a new NetworkBufferDescriptor_t with the maximum size. */
-                       pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( ipconfigNETWORK_MTU + 36, 100 );
-                       if( pxNetworkBuffer == NULL )
-                       {
-                               FreeRTOS_printf( ( "ksz8851snl_rx_populate_queue: NetworkBufferDescriptor_t allocation failure\n" ) );
-                               configASSERT( 1 == 2 );
-                       }
-
-                       /* Make sure lwIP is well configured so one NetworkBufferDescriptor_t can contain the maximum packet size. */
-                       //LWIP_ASSERT("ksz8851snl_rx_populate_queue: NetworkBufferDescriptor_t size too small!", pbuf_clen(pxNetworkBuffer) <= 1);
-
-                       /* Save NetworkBufferDescriptor_t pointer to be sent to lwIP upper layer. */
-                       xMicrelDevice.rx_buffers[ ul_index ] = pxNetworkBuffer;
-                       /* Pass it to Micrel for reception. */
-                       xMicrelDevice.rx_ready[ ul_index ] = pdFALSE;
-               }
-       }
-}
-
-unsigned tx_space, wait_tx_space, tx_status, fhr_status;
-unsigned rx_debug = 0;
-/**
- * \brief Update Micrel state machine and perform required actions.
- *
- * \param netif the lwIP network interface structure for this ethernetif.
- */
-static void ksz8851snl_update()
-{
-       uint16_t txmir = 0;
-
-/* Check for free PDC. */
-       switch( xMicrelDevice.ul_spi_pdc_status )
-       {
-       case SPI_PDC_TX_ERROR:
-               {
-               uint32_t ulValue;
-       //              /* TX step11: end TX transfer. */
-                       gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );
-
-                       vTaskDelay( 2 ); gpio_set_pin_low( KSZ8851SNL_CSN_GPIO );
-                       vTaskDelay( 1 ); gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );
-                       vTaskDelay( 1 );
-
-                       /* Disable asynchronous transfer mode. */
-                       xMicrelDevice.ul_spi_pdc_status = SPI_PDC_IDLE;
-
-                       /* TX step12: disable TXQ write access. */
-                       ksz8851_reg_clrbits( REG_RXQ_CMD, RXQ_START );
-
-                       ulValue = ksz8851snl_reset_tx();
-
-                       xMicrelDevice.tx_space = ksz8851_reg_read( REG_TX_MEM_INFO ) & TX_MEM_AVAILABLE_MASK;
-
-                       FreeRTOS_printf( ("SPI_PDC_TX_ERROR %02X\n", ulValue ) );
-               }
-               break;
-
-       case SPI_PDC_RX_ERROR:
-               {
-               uint32_t ulValue;
-                       /* TX step11: end TX transfer. */
-                       gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );
-
-                       vTaskDelay( 2 ); gpio_set_pin_low( KSZ8851SNL_CSN_GPIO );
-                       vTaskDelay( 1 ); gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );
-                       vTaskDelay( 1 );
-
-                       /* Disable asynchronous transfer mode. */
-                       xMicrelDevice.ul_spi_pdc_status = SPI_PDC_IDLE;
-
-                       /* TX step12: disable TXQ write access. */
-                       ksz8851_reg_clrbits( REG_RXQ_CMD, RXQ_START );
-
-                       //ulValue = ksz8851snl_reset_rx();
-                       ulValue = ksz8851snl_reinit();
-
-                       xGMACWaitLS( pdMS_TO_TICKS( 5000UL ) );
-
-                       FreeRTOS_printf( ("SPI_PDC_RX_ERROR %02X\n", ulValue ) );
-               }
-               break;
-       }
-       switch( xMicrelDevice.ul_spi_pdc_status )
-       {
-               case SPI_PDC_IDLE:
-               {
-               int txTail = xMicrelDevice.us_tx_tail;
-
-                       /*
-                        * ========================== Handle RX ==========================
-                        */
-                       if( ( xMicrelDevice.ul_had_intn_interrupt != 0 ) || ( xMicrelDevice.us_pending_frame > 0 ) )
-                       {
-                       int rxHead = xMicrelDevice.us_rx_head;
-                       NetworkBufferDescriptor_t *pxNetworkBuffer;
-#warning try
-                               xMicrelDevice.ul_had_intn_interrupt = 0;
-
-                               if( xMicrelDevice.us_pending_frame == 0 )
-                               {
-                               uint16_t int_status;
-                                       /* RX step1: read interrupt status for INT_RX flag. */
-                                       int_status = ksz8851_reg_read( REG_INT_STATUS );
-
-
-                                       /* RX step2: disable all interrupts. */
-                                       ksz8851_reg_write( REG_INT_MASK, 0 );
-
-                                       /* RX step3: clear INT_RX flag. */
-                                       ksz8851_reg_setbits( REG_INT_STATUS, INT_RX );
-
-                                       /* RX step4-5: check for received frames. */
-                                       xMicrelDevice.us_pending_frame = ksz8851_reg_read(REG_RX_FRAME_CNT_THRES) >> 8;
-                                       if( xMicrelDevice.us_pending_frame == 0 )
-                                       {
-                                               /* RX step24: enable INT_RX flag. */
-                                               ksz8851_reg_write(REG_INT_MASK, INT_RX);
-                                               return;
-                                       }
-                               }
-#warning try
-                               xMicrelDevice.ul_had_intn_interrupt = 0;
-
-                               /* Now xMicrelDevice.us_pending_frame != 0 */
-
-                               /* Don't break Micrel state machine, wait for a free descriptor first! */
-                               if( xMicrelDevice.rx_ready[ rxHead ] != pdFALSE )
-                               {
-                                       FreeRTOS_printf( ( "ksz8851snl_update: out of free descriptor! [tail=%u head=%u]\n",
-                                                       xMicrelDevice.us_rx_tail, rxHead ) );
-                                       return;
-                               }
-                               pxNetworkBuffer = xMicrelDevice.rx_buffers[ rxHead ];
-
-                               if( pxNetworkBuffer == NULL )
-                               {
-                                       ksz8851snl_rx_populate_queue();
-                                       FreeRTOS_printf( ( "ksz8851snl_update: no buffer set [head=%u]\n", rxHead ) );
-                                       return;
-                               }
-
-                               /* RX step6: get RX packet status. */
-                               fhr_status = ksz8851_reg_read( REG_RX_FHR_STATUS );
-                               if( ( ( fhr_status & RX_VALID ) == 0 ) || ( ( fhr_status & RX_ERRORS ) != 0 ) )
-                               {
-                                       ksz8851_reg_setbits(REG_RXQ_CMD, RXQ_CMD_FREE_PACKET);
-                                       FreeRTOS_printf( ( "ksz8851snl_update: RX packet error!\n" ) );
-
-                                       /* RX step4-5: check for received frames. */
-                                       xMicrelDevice.us_pending_frame = ksz8851_reg_read(REG_RX_FRAME_CNT_THRES) >> 8;
-                                       if( xMicrelDevice.us_pending_frame == 0 )
-                                       {
-                                               /* RX step24: enable INT_RX flag. */
-                                               ksz8851_reg_write(REG_INT_MASK, INT_RX);
-                                       }
-                                       ulISREvents |= EMAC_IF_ERR_EVENT;
-                               }
-                               else
-                               {
-                               size_t xLength;
-                                       /* RX step7: read frame length. */
-                                       xLength = ksz8851_reg_read(REG_RX_FHR_BYTE_CNT) & RX_BYTE_CNT_MASK;
-
-                                       /* RX step8: Drop packet if len is invalid or no descriptor available. */
-                                       if( xLength == 0 )
-                                       {
-                                               ksz8851_reg_setbits( REG_RXQ_CMD, RXQ_CMD_FREE_PACKET );
-                                               FreeRTOS_printf( ( "ksz8851snl_update: RX bad len!\n" ) );
-                                               ulISREvents |= EMAC_IF_ERR_EVENT;
-                                       }
-                                       else
-                                       {
-                                       size_t xReadLength = xLength;
-
-                                               xMicrelDevice.ul_total_rx++;
-                                               /* RX step9: reset RX frame pointer. */
-                                               ksz8851_reg_clrbits(REG_RX_ADDR_PTR, ADDR_PTR_MASK);
-
-                                               /* RX step10: start RXQ read access. */
-                                               ksz8851_reg_setbits(REG_RXQ_CMD, RXQ_START);
-                                               /* RX step11-17: start asynchronous FIFO read operation. */
-                                               xMicrelDevice.ul_spi_pdc_status = SPI_PDC_RX_START;
-                                               gpio_set_pin_low( KSZ8851SNL_CSN_GPIO );
-                                               if( ( xReadLength & ( sizeof( size_t ) - 1 ) ) != 0 )
-                                               {
-                                                       xReadLength = ( xReadLength | ( sizeof( size_t ) - 1 ) ) + 1;
-                                               }
-
-                                               /* Pass the buffer minus 2 bytes, see ksz8851snl.c: RXQ_TWOBYTE_OFFSET. */
-                                               ksz8851_fifo_read( pxNetworkBuffer->pucEthernetBuffer - 2, xReadLength );
-                                               /* Remove CRC and update buffer length. */
-                                               xLength -= 4;
-                                               pxNetworkBuffer->xDataLength = xLength;
-                                               /* Wait for SPI interrupt to set status 'SPI_PDC_RX_COMPLETE'. */
-                                       }
-                               }
-                               break;
-                       } /* ul_had_intn_interrupt || us_pending_frame */
-                       /*
-                        * ========================== Handle TX ==========================
-                        */
-
-                       /* Fetch next packet to be sent. */
-                       if( ( xMicrelDevice.tx_busy[ txTail ] != pdFALSE ) &&
-                               ( xMicrelDevice.us_pending_frame == 0 ) &&
-                               ( xMicrelDevice.ul_had_intn_interrupt == 0 ) )
-                       {
-                       NetworkBufferDescriptor_t *pxNetworkBuffer = xMicrelDevice.tx_buffers[ txTail ];
-                       size_t xLength = pxNetworkBuffer->xDataLength;
-                       int iIndex = xLength;
-
-                               xLength = 4 * ( ( xLength + 3 ) / 4 );
-                               while( iIndex < ( int ) xLength )
-                               {
-                                       pxNetworkBuffer->pucEthernetBuffer[ iIndex ] = '\0';
-                                       iIndex++;
-                               }
-                               pxNetworkBuffer->xDataLength = xLength;
-
-                               /* TX step1: check if TXQ memory size is available for transmit. */
-                               txmir = ksz8851_reg_read( REG_TX_MEM_INFO );
-                               txmir = txmir & TX_MEM_AVAILABLE_MASK;
-
-                               if( txmir < ( xLength + 8 ) )
-                               {
-                                       if( wait_tx_space == pdFALSE )
-                                       {
-                                               tx_status = ksz8851_reg_read( REG_TX_STATUS );
-                                               fhr_status = ksz8851_reg_read( REG_RX_FHR_STATUS );
-                                               wait_tx_space = pdTRUE;
-                                       }
-                                       //return;
-                                       rx_debug = 1;
-                                       tx_space = txmir;
-                               }
-                               else
-                               {
-                                       tx_space = txmir;
-
-                                       /* TX step2: disable all interrupts. */
-                                       ksz8851_reg_write( REG_INT_MASK, 0 );
-
-                                       xMicrelDevice.tx_space -= xLength;
-
-                                       /* TX step3: enable TXQ write access. */
-                                       ksz8851_reg_setbits( REG_RXQ_CMD, RXQ_START );
-                                       /* TX step4-8: perform FIFO write operation. */
-                                       xMicrelDevice.ul_spi_pdc_status = SPI_PDC_TX_START;
-                                       xMicrelDevice.tx_cur_buffer = pxNetworkBuffer;
-                                       /* Bring SPI SS low. */
-                                       gpio_set_pin_low( KSZ8851SNL_CSN_GPIO );
-                                       xMicrelDevice.ul_total_tx++;
-
-                                       ksz8851_fifo_write( pxNetworkBuffer->pucEthernetBuffer, xLength, xLength );
-                               }
-                       }
-               }
-               break;  /* SPI_PDC_IDLE */
-
-       case SPI_PDC_RX_COMPLETE:
-               {
-               int rxHead = xMicrelDevice.us_rx_head;
-                       /* RX step18-19: pad with dummy data to keep dword alignment. */
-                       /* Packet lengths will be rounded up to a multiple of "sizeof size_t". */
-//                     xLength = xMicrelDevice.rx_buffers[ rxHead ]->xDataLength & 3;
-//                     if( xLength != 0 )
-//                     {
-//                             ksz8851_fifo_dummy( 4 - xLength );
-//                     }
-
-                       /* RX step20: end RX transfer. */
-                       gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );
-
-                       /* Disable asynchronous transfer mode. */
-                       xMicrelDevice.ul_spi_pdc_status = SPI_PDC_IDLE;
-
-                       /* RX step21: end RXQ read access. */
-                       ksz8851_reg_clrbits(REG_RXQ_CMD, RXQ_START);
-
-                       /* RX step22-23: update frame count to be read. */
-                       xMicrelDevice.us_pending_frame -= 1;
-
-                       /* RX step24: enable INT_RX flag if transfer complete. */
-                       if( xMicrelDevice.us_pending_frame == 0 )
-                       {
-                               ksz8851_reg_write(REG_INT_MASK, INT_RX);
-                       }
-
-                       /* Mark descriptor ready to be read. */
-                       xMicrelDevice.rx_ready[ rxHead ] = pdTRUE;
-                       if( ++rxHead == MICREL_RX_BUFFERS )
-                       {
-                               rxHead = 0;
-                       }
-                       xMicrelDevice.us_rx_head = rxHead;
-                       if( rx_debug != 0 )
-                       {
-                       uint32_t txmir;
-                               rx_debug = 0;
-                               txmir = ksz8851_reg_read( REG_TX_MEM_INFO );
-                               txmir = txmir & TX_MEM_AVAILABLE_MASK;
-                       }
-                       /* Tell prvEMACHandlerTask that RX packets are available. */
-                       ulISREvents |= EMAC_IF_RX_EVENT;
-               }       /* case SPI_PDC_RX_COMPLETE */
-               break;
-
-       case SPI_PDC_TX_COMPLETE:
-               {
-               int txTail = xMicrelDevice.us_tx_tail;
-               NetworkBufferDescriptor_t *pxNetworkBuffer = xMicrelDevice.tx_buffers[ txTail ];
-
-               size_t xLength;
-                       /* TX step9-10: pad with dummy data to keep dword alignment. */
-                       /* Not necessary: length is already a multiple of 4. */
-                       xLength = pxNetworkBuffer->xDataLength & 3;
-                       if( xLength != 0 )
-                       {
-//                             ksz8851_fifo_dummy( 4 - xLength );
-                       }
-
-//                     /* TX step11: end TX transfer. */
-                       gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );
-
-                       /* Disable asynchronous transfer mode. */
-                       xMicrelDevice.ul_spi_pdc_status = SPI_PDC_IDLE;
-
-                       /* TX step12: disable TXQ write access. */
-                       ksz8851_reg_clrbits( REG_RXQ_CMD, RXQ_START );
-
-                       xMicrelDevice.tx_space = ksz8851_reg_read( REG_TX_MEM_INFO ) & TX_MEM_AVAILABLE_MASK;
-
-                       /* TX step12.1: enqueue frame in TXQ. */
-                       ksz8851_reg_setbits( REG_TXQ_CMD, TXQ_ENQUEUE );
-
-                       /* RX step13: enable INT_RX flag. */
-//                     ksz8851_reg_write( REG_INT_MASK, INT_RX );
-                       /* Buffer sent, free the corresponding buffer and mark descriptor as owned by software. */
-                       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
-
-                       xMicrelDevice.tx_buffers[ txTail ] = NULL;
-                       xMicrelDevice.tx_busy[ txTail ] = pdFALSE;
-                       if( ++txTail == MICREL_TX_BUFFERS )
-                       {
-                               txTail = 0;
-                       }
-
-                       xMicrelDevice.us_tx_tail = txTail;
-                       /* Experiment. */
-                       //xMicrelDevice.ul_had_intn_interrupt = 1;
-                       if( xTransmitHandle != NULL )
-                       {
-                               xTaskNotifyGive( xTransmitHandle );
-                       }
-#warning moved downward
-                       /* RX step13: enable INT_RX flag. */
-                       ksz8851_reg_write( REG_INT_MASK, INT_RX );
-                       /* Prevent the EMAC task from sleeping a single time. */
-                       ulISREvents |= EMAC_IF_TX_EVENT;
-               }       /* case SPI_PDC_TX_COMPLETE */
-               break;
-       }       /* switch( xMicrelDevice.ul_spi_pdc_status ) */
-}
-
-/**
- * \brief Set up the RX descriptor ring buffers.
- *
- * This function sets up the descriptor list used for RX packets.
- *
- */
-static void ksz8851snl_rx_init()
-{
-       uint32_t ul_index = 0;
-
-       /* Init pointer index. */
-       xMicrelDevice.us_rx_head = 0;
-       xMicrelDevice.us_rx_tail = 0;
-
-       /* Set up the RX descriptors. */
-       for (ul_index = 0; ul_index < MICREL_RX_BUFFERS; ul_index++) {
-               xMicrelDevice.rx_buffers[ul_index] = NULL;
-               xMicrelDevice.rx_ready[ul_index] = pdFALSE;
-       }
-
-       /* Build RX buffer and descriptors. */
-       ksz8851snl_rx_populate_queue();
-}
-
-/**
- * \brief Set up the TX descriptor ring buffers.
- *
- * This function sets up the descriptor list used for TX packets.
- *
- */
-static void ksz8851snl_tx_init()
-{
-       uint32_t ul_index = 0;
-
-       /* Init TX index pointer. */
-       xMicrelDevice.us_tx_head = 0;
-       xMicrelDevice.us_tx_tail = 0;
-
-       /* Set up the TX descriptors */
-       for( ul_index = 0; ul_index < MICREL_TX_BUFFERS; ul_index++ )
-       {
-               xMicrelDevice.tx_busy[ul_index] = pdFALSE;
-       }
-       xMicrelDevice.tx_space = 6144;
-}
-
-/**
- * \brief Initialize ksz8851snl ethernet controller.
- *
- * \note Called from ethernetif_init().
- *
- * \param netif the lwIP network interface structure for this ethernetif.
- */
-static void ksz8851snl_low_level_init( void )
-{
-       ksz8851snl_rx_init();
-       ksz8851snl_tx_init();
-
-       /* Enable NVIC interrupts. */
-       NVIC_SetPriority(SPI_IRQn, INT_PRIORITY_SPI);
-       NVIC_EnableIRQ(SPI_IRQn);
-
-       /* Initialize SPI link. */
-       if( ksz8851snl_init() < 0 )
-       {
-               FreeRTOS_printf( ( "ksz8851snl_low_level_init: failed to initialize the Micrel driver!\n" ) );
-               configASSERT(0 == 1);
-       }
-       memset( xMicrelDevice.pusHashTable, 255, sizeof( xMicrelDevice.pusHashTable ) );
-       ksz8851_reg_write( REG_MAC_HASH_0, FreeRTOS_htons( xMicrelDevice.pusHashTable[ 0 ] ) );
-       ksz8851_reg_write( REG_MAC_HASH_2, FreeRTOS_htons( xMicrelDevice.pusHashTable[ 1 ] ) );
-       ksz8851_reg_write( REG_MAC_HASH_4, FreeRTOS_htons( xMicrelDevice.pusHashTable[ 2 ] ) );
-       ksz8851_reg_write( REG_MAC_HASH_6, FreeRTOS_htons( xMicrelDevice.pusHashTable[ 3 ] ) );
-
-       /* Initialize interrupt line INTN. */
-       configure_intn( INTN_Handler );
-}
-
-/**
- * \brief Use pre-allocated pbuf as DMA source and return the incoming packet.
- *
- * \param netif the lwIP network interface structure for this ethernetif.
- *
- * \return a pbuf filled with the received packet (including MAC header).
- * 0 on memory error.
- */
-static NetworkBufferDescriptor_t *ksz8851snl_low_level_input( void )
-{
-NetworkBufferDescriptor_t *pxNetworkBuffer = NULL;
-int rxTail = xMicrelDevice.us_rx_tail;
-
-       /* Check that descriptor is owned by software (ie packet received). */
-       if( xMicrelDevice.rx_ready[ rxTail ] != pdFALSE )
-       {
-
-               /* Fetch pre-allocated buffer */
-               pxNetworkBuffer = xMicrelDevice.rx_buffers[ rxTail ];
-
-               /* Remove this pbuf from its descriptor. */
-               xMicrelDevice.rx_buffers[ rxTail ] = NULL;
-
-               /* Clears rx_ready and sets rx_buffers. */
-               ksz8851snl_rx_populate_queue();
-
-               if( ++rxTail == MICREL_RX_BUFFERS )
-               {
-                       rxTail = 0;
-               }
-               xMicrelDevice.us_rx_tail = rxTail;
-       }
-
-       return pxNetworkBuffer;
-}
-/*-----------------------------------------------------------*/
-
-static uint32_t prvEMACRxPoll( void )
-{
-NetworkBufferDescriptor_t *pxNetworkBuffer;
-IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
-uint32_t ulReturnValue = 0;
-
-       for( ;; )
-       {
-       /* Only for logging. */
-       int rxTail = xMicrelDevice.us_rx_tail;
-       EthernetHeader_t *pxEthernetHeader;
-
-       pxNetworkBuffer = ksz8851snl_low_level_input();
-       
-               if( pxNetworkBuffer == NULL )
-               {
-                       break;
-               }
-               pxEthernetHeader = ( EthernetHeader_t * ) ( pxNetworkBuffer->pucEthernetBuffer );
-
-               if( ( pxEthernetHeader->usFrameType != ipIPv4_FRAME_TYPE ) &&
-                       ( pxEthernetHeader->usFrameType != ipARP_FRAME_TYPE     ) )
-               {
-                       FreeRTOS_printf( ( "Frame type %02X received\n", pxEthernetHeader->usFrameType ) );
-               }
-               ulReturnValue++;
-
-               xRxEvent.pvData = ( void * )pxNetworkBuffer;
-               /* Send the descriptor to the IP task for processing. */
-               if( xSendEventStructToIPTask( &xRxEvent, 100UL ) != pdTRUE )
-               {
-                       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
-                       iptraceETHERNET_RX_EVENT_LOST();
-                       FreeRTOS_printf( ( "prvEMACRxPoll: Can not queue return packet!\n" ) );
-               }
-       }
-
-       return ulReturnValue;
-}
-/*-----------------------------------------------------------*/
-
-static void prvEMACHandlerTask( void *pvParameters )
-{
-TimeOut_t xPhyTime;
-TickType_t xPhyRemTime;
-TickType_t xLoggingTime;
-UBaseType_t uxLastMinBufferCount = 0;
-UBaseType_t uxCurrentCount;
-BaseType_t xResult = 0;
-uint32_t xStatus;
-const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( EMAC_MAX_BLOCK_TIME_MS );
-#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
-       UBaseType_t uxLastMinQueueSpace = 0;
-#endif
-
-       /* Remove compiler warnings about unused parameters. */
-       ( void ) pvParameters;
-
-       configASSERT( xEMACTaskHandle );
-
-       vTaskSetTimeOutState( &xPhyTime );
-       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
-       xLoggingTime = xTaskGetTickCount();
-
-       for( ;; )
-       {
-               uxCurrentCount = uxGetMinimumFreeNetworkBuffers();
-               if( uxLastMinBufferCount != uxCurrentCount )
-               {
-                       /* The logging produced below may be helpful
-                       while tuning +TCP: see how many buffers are in use. */
-                       uxLastMinBufferCount = uxCurrentCount;
-                       FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
-                               uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );
-               }
-
-               #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
-               {
-                       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 */
-
-               /* Run the state-machine of the ksz8851 driver. */
-               ksz8851snl_update();
-
-               if( ( ulISREvents & EMAC_IF_ALL_EVENT ) == 0 )
-               {
-                       /* No events to process now, wait for the next. */
-                       ulTaskNotifyTake( pdTRUE, ulMaxBlockTime );
-               }
-
-               if( ( xTaskGetTickCount() - xLoggingTime ) > 10000 )
-               {
-                       xLoggingTime += 10000;
-                       FreeRTOS_printf( ( "Now Tx/Rx %7d /%7d\n",
-                               xMicrelDevice.ul_total_tx, xMicrelDevice.ul_total_rx ) );
-               }
-
-               if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 )
-               {
-                       ulISREvents &= ~EMAC_IF_RX_EVENT;
-
-                       /* Wait for the EMAC interrupt to indicate that another packet has been
-                       received. */
-                       xResult = prvEMACRxPoll();
-               }
-
-               if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )
-               {
-                       /* Future extension: code to release TX buffers if zero-copy is used. */
-                       ulISREvents &= ~EMAC_IF_TX_EVENT;
-               }
-
-               if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 )
-               {
-                       /* Future extension: logging about errors that occurred. */
-                       ulISREvents &= ~EMAC_IF_ERR_EVENT;
-               }
-
-               if( xResult > 0 )
-               {
-                       /* As long as packets are being received, assume that
-                       the Link Status is high. */
-                       ulPHYLinkStatus |= BMSR_LINK_STATUS;
-                       /* 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 ) &&
-                       ( xMicrelDevice.ul_spi_pdc_status == SPI_PDC_IDLE ) )
-               {
-                       /* Check the link status again. */
-                       xStatus = ulReadMDIO( PHY_REG_01_BMSR );
-
-                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )
-                       {
-                               ulPHYLinkStatus = xStatus;
-                               FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );
-                       }
-
-                       vTaskSetTimeOutState( &xPhyTime );
-                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
-                       {
-                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
-                       }
-                       else
-                       {
-                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
-                       }
-               }
-       }
-}
-/*-----------------------------------------------------------*/
+/*\r
+FreeRTOS+TCP V2.0.11\r
+Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+this software and associated documentation files (the "Software"), to deal in\r
+the Software without restriction, including without limitation the rights to\r
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+the Software, and to permit persons to whom the Software is furnished to do so,\r
+subject to the following conditions:\r
+\r
+The above copyright notice and this permission notice shall be included in all\r
+copies or substantial portions of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+\r
+ http://aws.amazon.com/freertos\r
+ http://www.FreeRTOS.org\r
+*/\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <stdarg.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+#include "NetworkInterface.h"\r
+\r
+#include "sam4e_xplained_pro.h"\r
+#include "hr_gettime.h"\r
+#include "conf_eth.h"\r
+#include "ksz8851snl.h"\r
+#include "ksz8851snl_reg.h"\r
+\r
+/* Some files from the Atmel Software Framework */\r
+#include <sysclk.h>\r
+#include <pdc/pdc.h>\r
+#include <spi/spi.h>\r
+\r
+/*\r
+       Sending a packet:\r
+\r
+               1) Called by UP-task, add buffer to the TX-list:\r
+                       xNetworkInterfaceOutput()\r
+                               tx_buffers[ us_tx_head ] = pxNetworkBuffer;\r
+                               tx_busy[ us_tx_head ] = pdTRUE;\r
+                               us_tx_head++;\r
+\r
+               2) Called by EMAC-Task: start SPI transfer\r
+                       ksz8851snl_update()\r
+                       if( ul_spi_pdc_status == SPI_PDC_IDLE )\r
+                       {\r
+                               if( ( tx_busy[ us_tx_tail ] != pdFALSE ) &&\r
+                                       ( us_pending_frame == 0 ) &&\r
+                                       ( ul_had_intn_interrupt == 0 ) )\r
+                               {\r
+                                       // disable all interrupts.\r
+                                       ksz8851_reg_write( REG_INT_MASK, 0 );\r
+                                       Bring KSZ8851SNL_CSN_GPIO low\r
+                                       ksz8851_fifo_write( pxNetworkBuffer->pucEthernetBuffer, xLength, xLength );\r
+                                       ul_spi_pdc_status = SPI_PDC_TX_START;\r
+                                       tx_cur_buffer = pxNetworkBuffer;\r
+                               }\r
+                       }\r
+               3) Wait for SPI RXBUFF interrupt\r
+                       SPI_Handler()\r
+                               if( ul_spi_pdc_status == SPI_PDC_TX_START )\r
+                               {\r
+                                       if( SPI_Status & SPI_SR_RXBUFF )\r
+                                       {\r
+                                               ul_spi_pdc_status = SPI_PDC_TX_COMPLETE;\r
+                                       }\r
+                               }\r
+\r
+               4) Called by EMAC-Task: finish SPI transfer\r
+                       ksz8851snl_update()\r
+                               if( ul_spi_pdc_status == SPI_PDC_TX_COMPLETE )\r
+                               {\r
+                                       ul_spi_pdc_status = SPI_PDC_IDLE;\r
+                                       Bring KSZ8851SNL_CSN_GPIO high\r
+                                       // TX step12: disable TXQ write access.\r
+                                       ksz8851_reg_clrbits( REG_RXQ_CMD, RXQ_START );\r
+                                       // TX step12.1: enqueue frame in TXQ.\r
+                                       ksz8851_reg_setbits( REG_TXQ_CMD, TXQ_ENQUEUE );\r
+\r
+                                       // RX step13: enable INT_RX flag.\r
+                                       ksz8851_reg_write( REG_INT_MASK, INT_RX );\r
+\r
+                                       // Buffer sent, free the corresponding buffer and mark descriptor as owned by software.\r
+                                       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+\r
+                                       tx_buffers[ us_tx_tail ] = NULL;\r
+                                       tx_busy[ us_tx_tail ] = pdFALSE;\r
+                                       us_tx_tail++\r
+                               }\r
+\r
+       Receiving a packet:\r
+\r
+               1) Wait for a INTN interrupt\r
+                       INTN_Handler()\r
+                               ul_had_intn_interrupt = 1\r
+                               vTaskNotifyGiveFromISR();       // Wake up the EMAC task\r
+\r
+               2) Called by EMAC-Task: check for new fragments and start SPI transfer\r
+                       ksz8851snl_update()\r
+                               if( ul_spi_pdc_status == SPI_PDC_IDLE )\r
+                               {\r
+                                       if( ( ul_had_intn_interrupt != 0 ) || ( us_pending_frame > 0 ) )\r
+                                       {\r
+                                               if( us_pending_frame == 0 )\r
+                                               {\r
+                                                       us_pending_frame = ksz8851_reg_read(REG_RX_FRAME_CNT_THRES) >> 8;\r
+                                                       if( us_pending_frame == 0 )\r
+                                                       {\r
+                                                               break;\r
+                                                       }\r
+                                               }\r
+                                               // RX step2: disable all interrupts.\r
+                                               ksz8851_reg_write( REG_INT_MASK, 0 );\r
+                                               Check if there is a valid packet: REG_RX_FHR_STATUS\r
+                                               Read the length of the next fragment: REG_RX_FHR_BYTE_CNT\r
+                                               ul_spi_pdc_status = SPI_PDC_RX_START;\r
+                                               gpio_set_pin_low(KSZ8851SNL_CSN_GPIO);\r
+                                               // Start SPI data transfer\r
+                                               ksz8851_fifo_read( pxNetworkBuffer->pucEthernetBuffer, xReadLength );\r
+                                       }\r
+                               }\r
+\r
+               3) Wait for SPI RXBUFF interrupt\r
+                       SPI_Handler()\r
+                       if( ul_spi_pdc_status == SPI_PDC_RX_START:\r
+                       {\r
+                               if( ( ulCurrentSPIStatus & SPI_SR_RXBUFF ) != 0 )\r
+                               {\r
+                                       // Transfer complete, disable SPI RXBUFF interrupt.\r
+                                       spi_disable_interrupt( KSZ8851SNL_SPI, SPI_IDR_RXBUFF );\r
+\r
+                                       ul_spi_pdc_status = SPI_PDC_RX_COMPLETE;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               4) Finish SPI transfer\r
+                       ksz8851snl_update()\r
+                               if( ul_spi_pdc_status == SPI_PDC_RX_COMPLETE )\r
+                               {\r
+                                       ul_spi_pdc_status = SPI_PDC_IDLE;\r
+                                       Bring KSZ8851SNL_CSN_GPIO high\r
+                                       // RX step21: end RXQ read access.\r
+                                       ksz8851_reg_clrbits(REG_RXQ_CMD, RXQ_START);\r
+                                       // RX step22-23: update frame count to be read.\r
+                                       us_pending_frame--\r
+                                       // RX step24: enable INT_RX flag if transfer complete.\r
+                                       if( us_pending_frame == 0 )\r
+                                       {\r
+                                               // Allow more RX interrupts.\r
+                                               ksz8851_reg_write( REG_INT_MASK, INT_RX );\r
+                                       }\r
+\r
+                                       // Mark descriptor ready to be read.\r
+                                       rx_ready[ rxHead ] = pdTRUE;\r
+                                       rxHead++\r
+                               }\r
+*/\r
+\r
+#define PHY_REG_00_BMCR            0x00 // Basic mode control register\r
+#define PHY_REG_01_BMSR            0x01 // Basic mode status register\r
+#define PHY_REG_02_PHYSID1         0x02 // PHYS ID 1\r
+#define PHY_REG_03_PHYSID2         0x03 // PHYS ID 2\r
+#define PHY_REG_04_ADVERTISE       0x04 // Advertisement control reg\r
+#define PHY_REG_05_LPA             0x05 // Link partner ability reg\r
+#define        PHY_REG_06_ANER            0x06 //      6       RW              Auto-Negotiation Expansion Register\r
+#define        PHY_REG_07_ANNPTR          0x07 //      7       RW              Auto-Negotiation Next Page TX\r
+#define        PHY_REG_08_RESERVED0       0x08 // 0x08..0x0Fh  8-15    RW              RESERVED\r
+\r
+#define BMSR_LINK_STATUS            0x0004  //!< Link status\r
+\r
+#ifndef        PHY_LS_HIGH_CHECK_TIME_MS\r
+       /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not\r
+       receiving packets. */\r
+       #define PHY_LS_HIGH_CHECK_TIME_MS       15000\r
+#endif\r
+\r
+#ifndef        PHY_LS_LOW_CHECK_TIME_MS\r
+       /* Check if the LinkSStatus in the PHY is still low every second. */\r
+       #define PHY_LS_LOW_CHECK_TIME_MS        1000\r
+#endif\r
+\r
+/* 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 ETHERNET_CONF_PHY_ADDR BOARD_GMAC_PHY_ADDR\r
+\r
+#ifdef ipconfigHAS_TX_CRC_OFFLOADING\r
+       #undef ipconfigHAS_TX_CRC_OFFLOADING\r
+#endif\r
+/* Override this define because the KSZ8851 is programmed to set all outgoing CRC's */\r
+#define        ipconfigHAS_TX_CRC_OFFLOADING   1\r
+\r
+#ifndef        EMAC_MAX_BLOCK_TIME_MS\r
+       #define EMAC_MAX_BLOCK_TIME_MS  100ul\r
+#endif\r
+\r
+/* Default the size of the stack used by the EMAC deferred handler task to 4x\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 ( 6 * configMINIMAL_STACK_SIZE )\r
+#endif\r
+\r
+#define SPI_PDC_IDLE                   0\r
+#define SPI_PDC_RX_START               1\r
+#define SPI_PDC_TX_ERROR               2\r
+#define SPI_PDC_RX_COMPLETE            3\r
+#define SPI_PDC_TX_START               4\r
+#define SPI_PDC_RX_ERROR               5\r
+#define SPI_PDC_TX_COMPLETE            6\r
+\r
+/**\r
+ * ksz8851snl driver structure.\r
+ */\r
+typedef struct {\r
+       /** Set to 1 when owner is software (ready to read), 0 for Micrel. */\r
+       uint32_t rx_ready[MICREL_RX_BUFFERS];\r
+       /** Set to 1 when owner is Micrel, 0 for software. */\r
+       uint32_t tx_busy[MICREL_TX_BUFFERS];\r
+       /** RX NetworkBufferDescriptor_t pointer list */\r
+       NetworkBufferDescriptor_t *rx_buffers[MICREL_RX_BUFFERS];\r
+       /** TX NetworkBufferDescriptor_t pointer list */\r
+       NetworkBufferDescriptor_t *tx_buffers[MICREL_TX_BUFFERS];\r
+       NetworkBufferDescriptor_t *tx_cur_buffer;\r
+\r
+       /** Circular buffer head pointer for packet received. */\r
+       uint32_t us_rx_head;\r
+       /** Circular buffer tail pointer for packet to be read. */\r
+       uint32_t us_rx_tail;\r
+       /** Circular buffer head pointer by upper layer (buffer to be sent). */\r
+       uint32_t us_tx_head;\r
+       /** Circular buffer tail pointer incremented by handlers (buffer sent). */\r
+       uint32_t us_tx_tail;\r
+\r
+       uint32_t ul_total_tx;\r
+       uint32_t ul_total_rx;\r
+       uint32_t tx_space;\r
+\r
+       /** Still experimental: hash table to allow certain multicast addresses. */\r
+       uint16_t pusHashTable[ 4 ];\r
+\r
+       /* ul_spi_pdc_status has "SPI_PDC_xxx" values. */\r
+       volatile uint32_t ul_spi_pdc_status;\r
+\r
+       /* ul_had_intn_interrupt becomes true within the INTN interrupt. */\r
+       volatile uint32_t ul_had_intn_interrupt;\r
+\r
+       uint16_t us_pending_frame;\r
+} xKSZ8851_Device_t;\r
+\r
+/* SPI PDC register base.\r
+Declared in ASF\sam\components\ksz8851snl\ksz8851snl.c */\r
+extern Pdc *g_p_spi_pdc;\r
+\r
+/* Temporary buffer for PDC reception.\r
+declared in ASF\sam\components\ksz8851snl\ksz8851snl.c */\r
+extern uint8_t tmpbuf[1536];\r
+\r
+COMPILER_ALIGNED(8)\r
+static xKSZ8851_Device_t xMicrelDevice;\r
+\r
+static TaskHandle_t xTransmitHandle;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Wait a fixed time for the link status to indicate the network is up.\r
+ */\r
+static BaseType_t xGMACWaitLS( TickType_t xMaxTime );\r
+\r
+/*\r
+ * A deferred interrupt handler task that processes GMAC interrupts.\r
+ */\r
+static void prvEMACHandlerTask( void *pvParameters );\r
+\r
+/*\r
+ * Try to obtain an Rx packet from the hardware.\r
+ */\r
+static uint32_t prvEMACRxPoll( void );\r
+\r
+static inline unsigned long ulReadMDIO( unsigned uAddress );\r
+\r
+static void ksz8851snl_low_level_init( void );\r
+\r
+static NetworkBufferDescriptor_t *ksz8851snl_low_level_input( 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
+/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */\r
+static uint32_t ulPHYLinkStatus = 0;\r
+static volatile BaseType_t xGMACSwitchRequired;\r
+\r
+static void ksz8851snl_update( void );\r
+\r
+static void ksz8851snl_rx_init( void );\r
+\r
+static void ksz8851snl_tx_init( void );\r
+\r
+/* Holds the handle of the task used as a deferred interrupt processor.  The\r
+handle is used so direct notifications can be sent to the task for all EMAC/DMA\r
+related interrupts. */\r
+TaskHandle_t xEMACTaskHandle = NULL;\r
+\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+const TickType_t x5_Seconds = 5000UL;\r
+\r
+       if( xEMACTaskHandle == NULL )\r
+       {\r
+               ksz8851snl_low_level_init();\r
+\r
+               /* Wait at most 5 seconds for a Link Status in the PHY. */\r
+               xGMACWaitLS( pdMS_TO_TICKS( x5_Seconds ) );\r
+\r
+               /* The handler task is created at the highest possible priority to\r
+               ensure the interrupt handler can return directly to it. */\r
+               xTaskCreate( prvEMACHandlerTask, "KSZ8851", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );\r
+               configASSERT( xEMACTaskHandle );\r
+       }\r
+\r
+       /* When returning non-zero, the stack will become active and\r
+    start DHCP (in configured) */\r
+       ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );\r
+\r
+       return ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xGetPhyLinkStatus( void )\r
+{\r
+BaseType_t xResult;\r
+\r
+       /* This function returns true if the Link Status in the PHY is high. */\r
+       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+       {\r
+               xResult = pdTRUE;\r
+       }\r
+       else\r
+       {\r
+               xResult = pdFALSE;\r
+       }\r
+\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t bReleaseAfterSend )\r
+{\r
+BaseType_t xResult = pdFALSE;\r
+int txHead = xMicrelDevice.us_tx_head;\r
+\r
+       /* Make sure the next descriptor is free. */\r
+       if( xMicrelDevice.tx_busy[ txHead ] != pdFALSE )\r
+       {\r
+               /* All TX buffers busy. */\r
+       }\r
+       else if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )\r
+       {\r
+               /* Output: LS low. */\r
+       }\r
+       else\r
+       {\r
+               /* Pass the packet. */\r
+               xMicrelDevice.tx_buffers[ txHead ] = pxNetworkBuffer;\r
+               /* The descriptor is now owned by Micrel. */\r
+               xMicrelDevice.tx_busy[ txHead ] = pdTRUE;\r
+\r
+               /* Move the head pointer. */\r
+               if( ++txHead == MICREL_TX_BUFFERS )\r
+               {\r
+                       txHead = 0;\r
+               }\r
+               xMicrelDevice.us_tx_head = txHead;\r
+               if( xEMACTaskHandle != NULL )\r
+               {\r
+                       xTaskNotifyGive( xEMACTaskHandle );\r
+               }\r
+\r
+       #if( ipconfigZERO_COPY_TX_DRIVER != 1 )\r
+               #warning Please ipconfigZERO_COPY_TX_DRIVER as 1\r
+       #endif\r
+               configASSERT( bReleaseAfterSend != pdFALSE );\r
+               xResult = pdTRUE;\r
+       }\r
+       if( ( xResult == pdFALSE ) && ( bReleaseAfterSend  != pdFALSE ) )\r
+       {\r
+               vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+       }\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* This Micrel has numbered it's PHY registers in a different way.\r
+Translate the register index. */\r
+static int ks8851_phy_reg( int reg )\r
+{\r
+       switch (reg) {\r
+       case PHY_REG_00_BMCR:\r
+               return REG_PHY_CNTL;    // P1MBCR;\r
+       case PHY_REG_01_BMSR:\r
+               return REG_PHY_STATUS;\r
+       case PHY_REG_02_PHYSID1:\r
+               return REG_PHY_ID_LOW;\r
+       case PHY_REG_03_PHYSID2:\r
+               return REG_PHY_ID_HIGH;\r
+       case PHY_REG_04_ADVERTISE:\r
+               return REG_PHY_AUTO_NEGOTIATION;\r
+       case PHY_REG_05_LPA:\r
+               return REG_PHY_REMOTE_CAPABILITY;\r
+       }\r
+\r
+       return 0x0;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static inline unsigned long ulReadMDIO( unsigned uAddress )\r
+{\r
+uint16_t usPHYStatus;\r
+int ks8851_reg = ks8851_phy_reg( uAddress );\r
+\r
+       if( ks8851_reg != 0 )\r
+       {\r
+               usPHYStatus = ksz8851_reg_read( ks8851_reg );\r
+       }\r
+       else\r
+       {\r
+               /* Other addresses not yet implemented. */\r
+               usPHYStatus = 0;\r
+       }\r
+       return usPHYStatus;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t xGMACWaitLS( TickType_t xMaxTime )\r
+{\r
+TickType_t xStartTime = xTaskGetTickCount();\r
+TickType_t xEndTime;\r
+BaseType_t xReturn;\r
+const TickType_t xShortTime = pdMS_TO_TICKS( 100UL );\r
+const uint32_t ulHz_Per_MHz = 1000000UL;\r
+\r
+       for( ;; )\r
+       {\r
+               xEndTime = xTaskGetTickCount();\r
+\r
+               if( ( xEndTime - xStartTime ) > xMaxTime )\r
+               {\r
+                       /* Wated more than xMaxTime, return. */\r
+                       xReturn = pdFALSE;\r
+                       break;\r
+               }\r
+\r
+               /* Check the link status again. */\r
+               ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );\r
+\r
+               if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+               {\r
+                       /* Link is up - return. */\r
+                       xReturn = pdTRUE;\r
+                       break;\r
+               }\r
+\r
+               /* Link is down - wait in the Blocked state for a short while (to allow\r
+               other tasks to execute) before checking again. */\r
+               vTaskDelay( xShortTime );\r
+       }\r
+\r
+       FreeRTOS_printf( ( "xGMACWaitLS: %ld freq %lu Mz\n",\r
+               xReturn,\r
+               sysclk_get_cpu_hz() / ulHz_Per_MHz ) );\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void vPioSetPinHigh(uint32_t ul_pin)\r
+{\r
+       Pio *p_pio = (Pio *)((uint32_t)PIOA + (PIO_DELTA * (ul_pin >> 5)));\r
+       // Value to be driven on the I/O line: 1.\r
+       p_pio->PIO_SODR = 1 << (ul_pin & 0x1F);\r
+}\r
+\r
+/**\r
+ * \brief Handler for SPI interrupt.\r
+ */\r
+void SPI_Handler(void)\r
+{\r
+BaseType_t xDoWakeup = pdFALSE;\r
+BaseType_t xKSZTaskWoken = pdFALSE;\r
+uint32_t ulCurrentSPIStatus;\r
+uint32_t ulEnabledSPIStatus;\r
+\r
+       ulCurrentSPIStatus = spi_read_status( KSZ8851SNL_SPI );\r
+       ulEnabledSPIStatus = spi_read_interrupt_mask( KSZ8851SNL_SPI );\r
+       ulCurrentSPIStatus &= ulEnabledSPIStatus;\r
+       spi_disable_interrupt( KSZ8851SNL_SPI, ulCurrentSPIStatus );\r
+\r
+\r
+       switch( xMicrelDevice.ul_spi_pdc_status )\r
+       {\r
+               case SPI_PDC_RX_START:\r
+               {\r
+                       if( ( ulCurrentSPIStatus & SPI_SR_OVRES ) != 0 )\r
+                       {\r
+                               pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);\r
+                               xMicrelDevice.ul_spi_pdc_status = SPI_PDC_RX_ERROR;\r
+                               xDoWakeup = pdTRUE;\r
+                       }\r
+                       else\r
+                       {\r
+                               if( ( ulCurrentSPIStatus & SPI_SR_RXBUFF ) != 0 )\r
+                               {\r
+                                       xMicrelDevice.ul_spi_pdc_status = SPI_PDC_RX_COMPLETE;\r
+                                       xDoWakeup = pdTRUE;\r
+                               }\r
+                       }\r
+               }\r
+               break;\r
+\r
+               case SPI_PDC_TX_START:\r
+               {\r
+                       /* Middle of TX. */\r
+                       if( ( ulCurrentSPIStatus & SPI_SR_OVRES ) != 0 )\r
+                       {\r
+                               pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);\r
+                               xMicrelDevice.ul_spi_pdc_status = SPI_PDC_TX_ERROR;\r
+                               xDoWakeup = pdTRUE;\r
+                       }\r
+                       else\r
+                       {\r
+                               if( ( ulCurrentSPIStatus & SPI_SR_ENDRX ) != 0 )\r
+                               {\r
+                                       /* Enable RX complete interrupt. */\r
+                                       spi_enable_interrupt( KSZ8851SNL_SPI, SPI_IER_RXBUFF );\r
+                               }\r
+                               /* End of TX. */\r
+                               if( ( ulCurrentSPIStatus & SPI_END_OF_TX ) != 0 )\r
+                               {\r
+                                       xMicrelDevice.ul_spi_pdc_status = SPI_PDC_TX_COMPLETE;\r
+                                       xDoWakeup = pdTRUE;\r
+                               }\r
+                       }\r
+               }\r
+               break;\r
+       }       /* switch( xMicrelDevice.ul_spi_pdc_status ) */\r
+\r
+       if( xDoWakeup != pdFALSE )\r
+       {\r
+               if( xEMACTaskHandle != NULL )\r
+               {\r
+                       vTaskNotifyGiveFromISR( xEMACTaskHandle, ( BaseType_t * ) &xKSZTaskWoken );\r
+               }\r
+       }\r
+       else\r
+       {\r
+       }\r
+       portEND_SWITCHING_ISR( xKSZTaskWoken );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void INTN_Handler(uint32_t id, uint32_t mask)\r
+{\r
+BaseType_t xKSZTaskWoken = pdFALSE;\r
+\r
+       if( ( id == INTN_ID ) &&\r
+               ( mask == INTN_PIN_MSK ) )\r
+       {\r
+               /* Clear the PIO interrupt flags. */\r
+               pio_get_interrupt_status( INTN_PIO );\r
+\r
+               /* Set the INTN flag. */\r
+               xMicrelDevice.ul_had_intn_interrupt++;\r
+               if( xEMACTaskHandle != NULL )\r
+               {\r
+                       vTaskNotifyGiveFromISR( xEMACTaskHandle, &( xKSZTaskWoken ) );\r
+               }\r
+       }\r
+       portEND_SWITCHING_ISR( xKSZTaskWoken );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/**\r
+ * \brief Populate the RX descriptor ring buffers with pbufs.\r
+ *\r
+ * \param p_ksz8851snl_dev Pointer to driver data structure.\r
+ */\r
+static void ksz8851snl_rx_populate_queue( void )\r
+{\r
+       uint32_t ul_index = 0;\r
+       NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+\r
+       /* Set up the RX descriptors */\r
+       for (ul_index = 0; ul_index < MICREL_RX_BUFFERS; ul_index++) {\r
+               if( xMicrelDevice.rx_buffers[ ul_index ] == NULL )\r
+               {\r
+                       /* Allocate a new NetworkBufferDescriptor_t with the maximum size. */\r
+                       pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( ipconfigNETWORK_MTU + 36, 100 );\r
+                       if( pxNetworkBuffer == NULL )\r
+                       {\r
+                               FreeRTOS_printf( ( "ksz8851snl_rx_populate_queue: NetworkBufferDescriptor_t allocation failure\n" ) );\r
+                               configASSERT( 1 == 2 );\r
+                       }\r
+\r
+                       /* Make sure lwIP is well configured so one NetworkBufferDescriptor_t can contain the maximum packet size. */\r
+                       //LWIP_ASSERT("ksz8851snl_rx_populate_queue: NetworkBufferDescriptor_t size too small!", pbuf_clen(pxNetworkBuffer) <= 1);\r
+\r
+                       /* Save NetworkBufferDescriptor_t pointer to be sent to lwIP upper layer. */\r
+                       xMicrelDevice.rx_buffers[ ul_index ] = pxNetworkBuffer;\r
+                       /* Pass it to Micrel for reception. */\r
+                       xMicrelDevice.rx_ready[ ul_index ] = pdFALSE;\r
+               }\r
+       }\r
+}\r
+\r
+unsigned tx_space, wait_tx_space, tx_status, fhr_status;\r
+unsigned rx_debug = 0;\r
+/**\r
+ * \brief Update Micrel state machine and perform required actions.\r
+ *\r
+ * \param netif the lwIP network interface structure for this ethernetif.\r
+ */\r
+static void ksz8851snl_update()\r
+{\r
+       uint16_t txmir = 0;\r
+\r
+/* Check for free PDC. */\r
+       switch( xMicrelDevice.ul_spi_pdc_status )\r
+       {\r
+       case SPI_PDC_TX_ERROR:\r
+               {\r
+               uint32_t ulValue;\r
+       //              /* TX step11: end TX transfer. */\r
+                       gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );\r
+\r
+                       vTaskDelay( 2 ); gpio_set_pin_low( KSZ8851SNL_CSN_GPIO );\r
+                       vTaskDelay( 1 ); gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );\r
+                       vTaskDelay( 1 );\r
+\r
+                       /* Disable asynchronous transfer mode. */\r
+                       xMicrelDevice.ul_spi_pdc_status = SPI_PDC_IDLE;\r
+\r
+                       /* TX step12: disable TXQ write access. */\r
+                       ksz8851_reg_clrbits( REG_RXQ_CMD, RXQ_START );\r
+\r
+                       ulValue = ksz8851snl_reset_tx();\r
+\r
+                       xMicrelDevice.tx_space = ksz8851_reg_read( REG_TX_MEM_INFO ) & TX_MEM_AVAILABLE_MASK;\r
+\r
+                       FreeRTOS_printf( ("SPI_PDC_TX_ERROR %02X\n", ulValue ) );\r
+               }\r
+               break;\r
+\r
+       case SPI_PDC_RX_ERROR:\r
+               {\r
+               uint32_t ulValue;\r
+                       /* TX step11: end TX transfer. */\r
+                       gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );\r
+\r
+                       vTaskDelay( 2 ); gpio_set_pin_low( KSZ8851SNL_CSN_GPIO );\r
+                       vTaskDelay( 1 ); gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );\r
+                       vTaskDelay( 1 );\r
+\r
+                       /* Disable asynchronous transfer mode. */\r
+                       xMicrelDevice.ul_spi_pdc_status = SPI_PDC_IDLE;\r
+\r
+                       /* TX step12: disable TXQ write access. */\r
+                       ksz8851_reg_clrbits( REG_RXQ_CMD, RXQ_START );\r
+\r
+                       //ulValue = ksz8851snl_reset_rx();\r
+                       ulValue = ksz8851snl_reinit();\r
+\r
+                       xGMACWaitLS( pdMS_TO_TICKS( 5000UL ) );\r
+\r
+                       FreeRTOS_printf( ("SPI_PDC_RX_ERROR %02X\n", ulValue ) );\r
+               }\r
+               break;\r
+       }\r
+       switch( xMicrelDevice.ul_spi_pdc_status )\r
+       {\r
+               case SPI_PDC_IDLE:\r
+               {\r
+               int txTail = xMicrelDevice.us_tx_tail;\r
+\r
+                       /*\r
+                        * ========================== Handle RX ==========================\r
+                        */\r
+                       if( ( xMicrelDevice.ul_had_intn_interrupt != 0 ) || ( xMicrelDevice.us_pending_frame > 0 ) )\r
+                       {\r
+                       int rxHead = xMicrelDevice.us_rx_head;\r
+                       NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+#warning try\r
+                               xMicrelDevice.ul_had_intn_interrupt = 0;\r
+\r
+                               if( xMicrelDevice.us_pending_frame == 0 )\r
+                               {\r
+                               uint16_t int_status;\r
+                                       /* RX step1: read interrupt status for INT_RX flag. */\r
+                                       int_status = ksz8851_reg_read( REG_INT_STATUS );\r
+\r
+\r
+                                       /* RX step2: disable all interrupts. */\r
+                                       ksz8851_reg_write( REG_INT_MASK, 0 );\r
+\r
+                                       /* RX step3: clear INT_RX flag. */\r
+                                       ksz8851_reg_setbits( REG_INT_STATUS, INT_RX );\r
+\r
+                                       /* RX step4-5: check for received frames. */\r
+                                       xMicrelDevice.us_pending_frame = ksz8851_reg_read(REG_RX_FRAME_CNT_THRES) >> 8;\r
+                                       if( xMicrelDevice.us_pending_frame == 0 )\r
+                                       {\r
+                                               /* RX step24: enable INT_RX flag. */\r
+                                               ksz8851_reg_write(REG_INT_MASK, INT_RX);\r
+                                               return;\r
+                                       }\r
+                               }\r
+#warning try\r
+                               xMicrelDevice.ul_had_intn_interrupt = 0;\r
+\r
+                               /* Now xMicrelDevice.us_pending_frame != 0 */\r
+\r
+                               /* Don't break Micrel state machine, wait for a free descriptor first! */\r
+                               if( xMicrelDevice.rx_ready[ rxHead ] != pdFALSE )\r
+                               {\r
+                                       FreeRTOS_printf( ( "ksz8851snl_update: out of free descriptor! [tail=%u head=%u]\n",\r
+                                                       xMicrelDevice.us_rx_tail, rxHead ) );\r
+                                       return;\r
+                               }\r
+                               pxNetworkBuffer = xMicrelDevice.rx_buffers[ rxHead ];\r
+\r
+                               if( pxNetworkBuffer == NULL )\r
+                               {\r
+                                       ksz8851snl_rx_populate_queue();\r
+                                       FreeRTOS_printf( ( "ksz8851snl_update: no buffer set [head=%u]\n", rxHead ) );\r
+                                       return;\r
+                               }\r
+\r
+                               /* RX step6: get RX packet status. */\r
+                               fhr_status = ksz8851_reg_read( REG_RX_FHR_STATUS );\r
+                               if( ( ( fhr_status & RX_VALID ) == 0 ) || ( ( fhr_status & RX_ERRORS ) != 0 ) )\r
+                               {\r
+                                       ksz8851_reg_setbits(REG_RXQ_CMD, RXQ_CMD_FREE_PACKET);\r
+                                       FreeRTOS_printf( ( "ksz8851snl_update: RX packet error!\n" ) );\r
+\r
+                                       /* RX step4-5: check for received frames. */\r
+                                       xMicrelDevice.us_pending_frame = ksz8851_reg_read(REG_RX_FRAME_CNT_THRES) >> 8;\r
+                                       if( xMicrelDevice.us_pending_frame == 0 )\r
+                                       {\r
+                                               /* RX step24: enable INT_RX flag. */\r
+                                               ksz8851_reg_write(REG_INT_MASK, INT_RX);\r
+                                       }\r
+                                       ulISREvents |= EMAC_IF_ERR_EVENT;\r
+                               }\r
+                               else\r
+                               {\r
+                               size_t xLength;\r
+                                       /* RX step7: read frame length. */\r
+                                       xLength = ksz8851_reg_read(REG_RX_FHR_BYTE_CNT) & RX_BYTE_CNT_MASK;\r
+\r
+                                       /* RX step8: Drop packet if len is invalid or no descriptor available. */\r
+                                       if( xLength == 0 )\r
+                                       {\r
+                                               ksz8851_reg_setbits( REG_RXQ_CMD, RXQ_CMD_FREE_PACKET );\r
+                                               FreeRTOS_printf( ( "ksz8851snl_update: RX bad len!\n" ) );\r
+                                               ulISREvents |= EMAC_IF_ERR_EVENT;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                       size_t xReadLength = xLength;\r
+\r
+                                               xMicrelDevice.ul_total_rx++;\r
+                                               /* RX step9: reset RX frame pointer. */\r
+                                               ksz8851_reg_clrbits(REG_RX_ADDR_PTR, ADDR_PTR_MASK);\r
+\r
+                                               /* RX step10: start RXQ read access. */\r
+                                               ksz8851_reg_setbits(REG_RXQ_CMD, RXQ_START);\r
+                                               /* RX step11-17: start asynchronous FIFO read operation. */\r
+                                               xMicrelDevice.ul_spi_pdc_status = SPI_PDC_RX_START;\r
+                                               gpio_set_pin_low( KSZ8851SNL_CSN_GPIO );\r
+                                               if( ( xReadLength & ( sizeof( size_t ) - 1 ) ) != 0 )\r
+                                               {\r
+                                                       xReadLength = ( xReadLength | ( sizeof( size_t ) - 1 ) ) + 1;\r
+                                               }\r
+\r
+                                               /* Pass the buffer minus 2 bytes, see ksz8851snl.c: RXQ_TWOBYTE_OFFSET. */\r
+                                               ksz8851_fifo_read( pxNetworkBuffer->pucEthernetBuffer - 2, xReadLength );\r
+                                               /* Remove CRC and update buffer length. */\r
+                                               xLength -= 4;\r
+                                               pxNetworkBuffer->xDataLength = xLength;\r
+                                               /* Wait for SPI interrupt to set status 'SPI_PDC_RX_COMPLETE'. */\r
+                                       }\r
+                               }\r
+                               break;\r
+                       } /* ul_had_intn_interrupt || us_pending_frame */\r
+                       /*\r
+                        * ========================== Handle TX ==========================\r
+                        */\r
+\r
+                       /* Fetch next packet to be sent. */\r
+                       if( ( xMicrelDevice.tx_busy[ txTail ] != pdFALSE ) &&\r
+                               ( xMicrelDevice.us_pending_frame == 0 ) &&\r
+                               ( xMicrelDevice.ul_had_intn_interrupt == 0 ) )\r
+                       {\r
+                       NetworkBufferDescriptor_t *pxNetworkBuffer = xMicrelDevice.tx_buffers[ txTail ];\r
+                       size_t xLength = pxNetworkBuffer->xDataLength;\r
+                       int iIndex = xLength;\r
+\r
+                               xLength = 4 * ( ( xLength + 3 ) / 4 );\r
+                               while( iIndex < ( int ) xLength )\r
+                               {\r
+                                       pxNetworkBuffer->pucEthernetBuffer[ iIndex ] = '\0';\r
+                                       iIndex++;\r
+                               }\r
+                               pxNetworkBuffer->xDataLength = xLength;\r
+\r
+                               /* TX step1: check if TXQ memory size is available for transmit. */\r
+                               txmir = ksz8851_reg_read( REG_TX_MEM_INFO );\r
+                               txmir = txmir & TX_MEM_AVAILABLE_MASK;\r
+\r
+                               if( txmir < ( xLength + 8 ) )\r
+                               {\r
+                                       if( wait_tx_space == pdFALSE )\r
+                                       {\r
+                                               tx_status = ksz8851_reg_read( REG_TX_STATUS );\r
+                                               fhr_status = ksz8851_reg_read( REG_RX_FHR_STATUS );\r
+                                               wait_tx_space = pdTRUE;\r
+                                       }\r
+                                       //return;\r
+                                       rx_debug = 1;\r
+                                       tx_space = txmir;\r
+                               }\r
+                               else\r
+                               {\r
+                                       tx_space = txmir;\r
+\r
+                                       /* TX step2: disable all interrupts. */\r
+                                       ksz8851_reg_write( REG_INT_MASK, 0 );\r
+\r
+                                       xMicrelDevice.tx_space -= xLength;\r
+\r
+                                       /* TX step3: enable TXQ write access. */\r
+                                       ksz8851_reg_setbits( REG_RXQ_CMD, RXQ_START );\r
+                                       /* TX step4-8: perform FIFO write operation. */\r
+                                       xMicrelDevice.ul_spi_pdc_status = SPI_PDC_TX_START;\r
+                                       xMicrelDevice.tx_cur_buffer = pxNetworkBuffer;\r
+                                       /* Bring SPI SS low. */\r
+                                       gpio_set_pin_low( KSZ8851SNL_CSN_GPIO );\r
+                                       xMicrelDevice.ul_total_tx++;\r
+\r
+                                       ksz8851_fifo_write( pxNetworkBuffer->pucEthernetBuffer, xLength, xLength );\r
+                               }\r
+                       }\r
+               }\r
+               break;  /* SPI_PDC_IDLE */\r
+\r
+       case SPI_PDC_RX_COMPLETE:\r
+               {\r
+               int rxHead = xMicrelDevice.us_rx_head;\r
+                       /* RX step18-19: pad with dummy data to keep dword alignment. */\r
+                       /* Packet lengths will be rounded up to a multiple of "sizeof size_t". */\r
+//                     xLength = xMicrelDevice.rx_buffers[ rxHead ]->xDataLength & 3;\r
+//                     if( xLength != 0 )\r
+//                     {\r
+//                             ksz8851_fifo_dummy( 4 - xLength );\r
+//                     }\r
+\r
+                       /* RX step20: end RX transfer. */\r
+                       gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );\r
+\r
+                       /* Disable asynchronous transfer mode. */\r
+                       xMicrelDevice.ul_spi_pdc_status = SPI_PDC_IDLE;\r
+\r
+                       /* RX step21: end RXQ read access. */\r
+                       ksz8851_reg_clrbits(REG_RXQ_CMD, RXQ_START);\r
+\r
+                       /* RX step22-23: update frame count to be read. */\r
+                       xMicrelDevice.us_pending_frame -= 1;\r
+\r
+                       /* RX step24: enable INT_RX flag if transfer complete. */\r
+                       if( xMicrelDevice.us_pending_frame == 0 )\r
+                       {\r
+                               ksz8851_reg_write(REG_INT_MASK, INT_RX);\r
+                       }\r
+\r
+                       /* Mark descriptor ready to be read. */\r
+                       xMicrelDevice.rx_ready[ rxHead ] = pdTRUE;\r
+                       if( ++rxHead == MICREL_RX_BUFFERS )\r
+                       {\r
+                               rxHead = 0;\r
+                       }\r
+                       xMicrelDevice.us_rx_head = rxHead;\r
+                       if( rx_debug != 0 )\r
+                       {\r
+                       uint32_t txmir;\r
+                               rx_debug = 0;\r
+                               txmir = ksz8851_reg_read( REG_TX_MEM_INFO );\r
+                               txmir = txmir & TX_MEM_AVAILABLE_MASK;\r
+                       }\r
+                       /* Tell prvEMACHandlerTask that RX packets are available. */\r
+                       ulISREvents |= EMAC_IF_RX_EVENT;\r
+               }       /* case SPI_PDC_RX_COMPLETE */\r
+               break;\r
+\r
+       case SPI_PDC_TX_COMPLETE:\r
+               {\r
+               int txTail = xMicrelDevice.us_tx_tail;\r
+               NetworkBufferDescriptor_t *pxNetworkBuffer = xMicrelDevice.tx_buffers[ txTail ];\r
+\r
+               size_t xLength;\r
+                       /* TX step9-10: pad with dummy data to keep dword alignment. */\r
+                       /* Not necessary: length is already a multiple of 4. */\r
+                       xLength = pxNetworkBuffer->xDataLength & 3;\r
+                       if( xLength != 0 )\r
+                       {\r
+//                             ksz8851_fifo_dummy( 4 - xLength );\r
+                       }\r
+\r
+//                     /* TX step11: end TX transfer. */\r
+                       gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );\r
+\r
+                       /* Disable asynchronous transfer mode. */\r
+                       xMicrelDevice.ul_spi_pdc_status = SPI_PDC_IDLE;\r
+\r
+                       /* TX step12: disable TXQ write access. */\r
+                       ksz8851_reg_clrbits( REG_RXQ_CMD, RXQ_START );\r
+\r
+                       xMicrelDevice.tx_space = ksz8851_reg_read( REG_TX_MEM_INFO ) & TX_MEM_AVAILABLE_MASK;\r
+\r
+                       /* TX step12.1: enqueue frame in TXQ. */\r
+                       ksz8851_reg_setbits( REG_TXQ_CMD, TXQ_ENQUEUE );\r
+\r
+                       /* RX step13: enable INT_RX flag. */\r
+//                     ksz8851_reg_write( REG_INT_MASK, INT_RX );\r
+                       /* Buffer sent, free the corresponding buffer and mark descriptor as owned by software. */\r
+                       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+\r
+                       xMicrelDevice.tx_buffers[ txTail ] = NULL;\r
+                       xMicrelDevice.tx_busy[ txTail ] = pdFALSE;\r
+                       if( ++txTail == MICREL_TX_BUFFERS )\r
+                       {\r
+                               txTail = 0;\r
+                       }\r
+\r
+                       xMicrelDevice.us_tx_tail = txTail;\r
+                       /* Experiment. */\r
+                       //xMicrelDevice.ul_had_intn_interrupt = 1;\r
+                       if( xTransmitHandle != NULL )\r
+                       {\r
+                               xTaskNotifyGive( xTransmitHandle );\r
+                       }\r
+#warning moved downward\r
+                       /* RX step13: enable INT_RX flag. */\r
+                       ksz8851_reg_write( REG_INT_MASK, INT_RX );\r
+                       /* Prevent the EMAC task from sleeping a single time. */\r
+                       ulISREvents |= EMAC_IF_TX_EVENT;\r
+               }       /* case SPI_PDC_TX_COMPLETE */\r
+               break;\r
+       }       /* switch( xMicrelDevice.ul_spi_pdc_status ) */\r
+}\r
+\r
+/**\r
+ * \brief Set up the RX descriptor ring buffers.\r
+ *\r
+ * This function sets up the descriptor list used for RX packets.\r
+ *\r
+ */\r
+static void ksz8851snl_rx_init()\r
+{\r
+       uint32_t ul_index = 0;\r
+\r
+       /* Init pointer index. */\r
+       xMicrelDevice.us_rx_head = 0;\r
+       xMicrelDevice.us_rx_tail = 0;\r
+\r
+       /* Set up the RX descriptors. */\r
+       for (ul_index = 0; ul_index < MICREL_RX_BUFFERS; ul_index++) {\r
+               xMicrelDevice.rx_buffers[ul_index] = NULL;\r
+               xMicrelDevice.rx_ready[ul_index] = pdFALSE;\r
+       }\r
+\r
+       /* Build RX buffer and descriptors. */\r
+       ksz8851snl_rx_populate_queue();\r
+}\r
+\r
+/**\r
+ * \brief Set up the TX descriptor ring buffers.\r
+ *\r
+ * This function sets up the descriptor list used for TX packets.\r
+ *\r
+ */\r
+static void ksz8851snl_tx_init()\r
+{\r
+       uint32_t ul_index = 0;\r
+\r
+       /* Init TX index pointer. */\r
+       xMicrelDevice.us_tx_head = 0;\r
+       xMicrelDevice.us_tx_tail = 0;\r
+\r
+       /* Set up the TX descriptors */\r
+       for( ul_index = 0; ul_index < MICREL_TX_BUFFERS; ul_index++ )\r
+       {\r
+               xMicrelDevice.tx_busy[ul_index] = pdFALSE;\r
+       }\r
+       xMicrelDevice.tx_space = 6144;\r
+}\r
+\r
+/**\r
+ * \brief Initialize ksz8851snl ethernet controller.\r
+ *\r
+ * \note Called from ethernetif_init().\r
+ *\r
+ * \param netif the lwIP network interface structure for this ethernetif.\r
+ */\r
+static void ksz8851snl_low_level_init( void )\r
+{\r
+       ksz8851snl_rx_init();\r
+       ksz8851snl_tx_init();\r
+\r
+       /* Enable NVIC interrupts. */\r
+       NVIC_SetPriority(SPI_IRQn, INT_PRIORITY_SPI);\r
+       NVIC_EnableIRQ(SPI_IRQn);\r
+\r
+       /* Initialize SPI link. */\r
+       if( ksz8851snl_init() < 0 )\r
+       {\r
+               FreeRTOS_printf( ( "ksz8851snl_low_level_init: failed to initialize the Micrel driver!\n" ) );\r
+               configASSERT(0 == 1);\r
+       }\r
+       memset( xMicrelDevice.pusHashTable, 255, sizeof( xMicrelDevice.pusHashTable ) );\r
+       ksz8851_reg_write( REG_MAC_HASH_0, FreeRTOS_htons( xMicrelDevice.pusHashTable[ 0 ] ) );\r
+       ksz8851_reg_write( REG_MAC_HASH_2, FreeRTOS_htons( xMicrelDevice.pusHashTable[ 1 ] ) );\r
+       ksz8851_reg_write( REG_MAC_HASH_4, FreeRTOS_htons( xMicrelDevice.pusHashTable[ 2 ] ) );\r
+       ksz8851_reg_write( REG_MAC_HASH_6, FreeRTOS_htons( xMicrelDevice.pusHashTable[ 3 ] ) );\r
+\r
+       /* Initialize interrupt line INTN. */\r
+       configure_intn( INTN_Handler );\r
+}\r
+\r
+/**\r
+ * \brief Use pre-allocated pbuf as DMA source and return the incoming packet.\r
+ *\r
+ * \param netif the lwIP network interface structure for this ethernetif.\r
+ *\r
+ * \return a pbuf filled with the received packet (including MAC header).\r
+ * 0 on memory error.\r
+ */\r
+static NetworkBufferDescriptor_t *ksz8851snl_low_level_input( void )\r
+{\r
+NetworkBufferDescriptor_t *pxNetworkBuffer = NULL;\r
+int rxTail = xMicrelDevice.us_rx_tail;\r
+\r
+       /* Check that descriptor is owned by software (ie packet received). */\r
+       if( xMicrelDevice.rx_ready[ rxTail ] != pdFALSE )\r
+       {\r
+\r
+               /* Fetch pre-allocated buffer */\r
+               pxNetworkBuffer = xMicrelDevice.rx_buffers[ rxTail ];\r
+\r
+               /* Remove this pbuf from its descriptor. */\r
+               xMicrelDevice.rx_buffers[ rxTail ] = NULL;\r
+\r
+               /* Clears rx_ready and sets rx_buffers. */\r
+               ksz8851snl_rx_populate_queue();\r
+\r
+               if( ++rxTail == MICREL_RX_BUFFERS )\r
+               {\r
+                       rxTail = 0;\r
+               }\r
+               xMicrelDevice.us_rx_tail = rxTail;\r
+       }\r
+\r
+       return pxNetworkBuffer;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static uint32_t prvEMACRxPoll( void )\r
+{\r
+NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
+uint32_t ulReturnValue = 0;\r
+\r
+       for( ;; )\r
+       {\r
+       /* Only for logging. */\r
+       int rxTail = xMicrelDevice.us_rx_tail;\r
+       EthernetHeader_t *pxEthernetHeader;\r
+\r
+       pxNetworkBuffer = ksz8851snl_low_level_input();\r
+       \r
+               if( pxNetworkBuffer == NULL )\r
+               {\r
+                       break;\r
+               }\r
+               pxEthernetHeader = ( EthernetHeader_t * ) ( pxNetworkBuffer->pucEthernetBuffer );\r
+\r
+               if( ( pxEthernetHeader->usFrameType != ipIPv4_FRAME_TYPE ) &&\r
+                       ( pxEthernetHeader->usFrameType != ipARP_FRAME_TYPE     ) )\r
+               {\r
+                       FreeRTOS_printf( ( "Frame type %02X received\n", pxEthernetHeader->usFrameType ) );\r
+               }\r
+               ulReturnValue++;\r
+\r
+               xRxEvent.pvData = ( void * )pxNetworkBuffer;\r
+               /* Send the descriptor to the IP task for processing. */\r
+               if( xSendEventStructToIPTask( &xRxEvent, 100UL ) != pdTRUE )\r
+               {\r
+                       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+                       iptraceETHERNET_RX_EVENT_LOST();\r
+                       FreeRTOS_printf( ( "prvEMACRxPoll: Can not queue return packet!\n" ) );\r
+               }\r
+       }\r
+\r
+       return ulReturnValue;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvEMACHandlerTask( void *pvParameters )\r
+{\r
+TimeOut_t xPhyTime;\r
+TickType_t xPhyRemTime;\r
+TickType_t xLoggingTime;\r
+UBaseType_t uxLastMinBufferCount = 0;\r
+UBaseType_t uxCurrentCount;\r
+BaseType_t xResult = 0;\r
+uint32_t xStatus;\r
+const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( EMAC_MAX_BLOCK_TIME_MS );\r
+#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+       UBaseType_t uxLastMinQueueSpace = 0;\r
+#endif\r
+\r
+       /* Remove compiler warnings about unused parameters. */\r
+       ( void ) pvParameters;\r
+\r
+       configASSERT( xEMACTaskHandle );\r
+\r
+       vTaskSetTimeOutState( &xPhyTime );\r
+       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+       xLoggingTime = xTaskGetTickCount();\r
+\r
+       for( ;; )\r
+       {\r
+               uxCurrentCount = uxGetMinimumFreeNetworkBuffers();\r
+               if( uxLastMinBufferCount != uxCurrentCount )\r
+               {\r
+                       /* The logging produced below may be helpful\r
+                       while tuning +TCP: see how many buffers are in use. */\r
+                       uxLastMinBufferCount = uxCurrentCount;\r
+                       FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",\r
+                               uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );\r
+               }\r
+\r
+               #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+               {\r
+                       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
+               /* Run the state-machine of the ksz8851 driver. */\r
+               ksz8851snl_update();\r
+\r
+               if( ( ulISREvents & EMAC_IF_ALL_EVENT ) == 0 )\r
+               {\r
+                       /* No events to process now, wait for the next. */\r
+                       ulTaskNotifyTake( pdTRUE, ulMaxBlockTime );\r
+               }\r
+\r
+               if( ( xTaskGetTickCount() - xLoggingTime ) > 10000 )\r
+               {\r
+                       xLoggingTime += 10000;\r
+                       FreeRTOS_printf( ( "Now Tx/Rx %7d /%7d\n",\r
+                               xMicrelDevice.ul_total_tx, xMicrelDevice.ul_total_rx ) );\r
+               }\r
+\r
+               if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 )\r
+               {\r
+                       ulISREvents &= ~EMAC_IF_RX_EVENT;\r
+\r
+                       /* Wait for the EMAC interrupt to indicate that another packet has been\r
+                       received. */\r
+                       xResult = prvEMACRxPoll();\r
+               }\r
+\r
+               if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )\r
+               {\r
+                       /* Future extension: code to release TX buffers if zero-copy is used. */\r
+                       ulISREvents &= ~EMAC_IF_TX_EVENT;\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
+\r
+               if( xResult > 0 )\r
+               {\r
+                       /* As long as packets are being received, assume that\r
+                       the Link Status is high. */\r
+                       ulPHYLinkStatus |= BMSR_LINK_STATUS;\r
+                       /* A packet was received. No need to check for the PHY status now,\r
+                       but set a timer to check it later on. */\r
+                       vTaskSetTimeOutState( &xPhyTime );\r
+                       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+                       xResult = 0;\r
+               }\r
+               else if( ( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE ) &&\r
+                       ( xMicrelDevice.ul_spi_pdc_status == SPI_PDC_IDLE ) )\r
+               {\r
+                       /* Check the link status again. */\r
+                       xStatus = ulReadMDIO( PHY_REG_01_BMSR );\r
+\r
+                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )\r
+                       {\r
+                               ulPHYLinkStatus = xStatus;\r
+                               FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );\r
+                       }\r
+\r
+                       vTaskSetTimeOutState( &xPhyTime );\r
+                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+                       {\r
+                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+                       }\r
+                       else\r
+                       {\r
+                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+                       }\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
index df5bd7cfe50fe6b96e7eb797d937716c1e433cbb..87161fd3925dab4dbfc1e3a053100e645a336010 100644 (file)
-/*
-FreeRTOS+TCP V2.0.11
-Copyright (C) 2018 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
-*/
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "list.h"
-
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_IP.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"
-
-#include "wifi-decl.h"
-#include "wmerrno.h"
-#include "wifi.h"
-
-#include <wmlog.h>
-
-#define net_e(...)                             \
-    wmlog_e("freertos_tcp", ##__VA_ARGS__)
-#define net_w(...)                             \
-    wmlog_w("freertos_tcp", ##__VA_ARGS__)
-#define net_d(...)                             \
-    wmlog("freertos_tcp", ##__VA_ARGS__)
-
-#if 0 //this is lwip structure.
-#define MAX_INTERFACES_SUPPORTED 3
-static struct netif *netif_arr[MAX_INTERFACES_SUPPORTED];
-#endif
-
-/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
-driver will filter incoming packets and only pass the stack those packets it
-considers need processing. */
-#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
-#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
-#else
-#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
-#endif
-
-#define IP_ADDR_ANY         ((ip_addr_t *)&ip_addr_any)
-#define IP_ADDR_BROADCAST   ((ip_addr_t *)&ip_addr_broadcast)
-
-/** 255.255.255.255 */
-#define IPADDR_NONE         ((u32_t)0xffffffffUL)
-/** 127.0.0.1 */
-#define IPADDR_LOOPBACK     ((u32_t)0x7f000001UL)
-/** 0.0.0.0 */
-#define IPADDR_ANY          ((u32_t)0x00000000UL)
-/** 255.255.255.255 */
-#define IPADDR_BROADCAST    ((u32_t)0xffffffffUL)
-
-/** 255.255.255.255 */
-#define INADDR_NONE         IPADDR_NONE
-/** 127.0.0.1 */
-#define INADDR_LOOPBACK     IPADDR_LOOPBACK
-/** 0.0.0.0 */
-#define INADDR_ANY          IPADDR_ANY
-/** 255.255.255.255 */
-#define INADDR_BROADCAST    IPADDR_BROADCAST
-
-enum if_state_t {
-    INTERFACE_DOWN = 0,
-    INTERFACE_UP,
-};
-struct ip_addr {
-  u32_t addr;
-};
-
-#define MLAN_BSS_TYPE_STA 0
-
-extern uint8_t outbuf[2048];
-extern bool mlan_is_amsdu(const t_u8 *rcvdata);
-extern t_u8 *mlan_get_payload(const t_u8 *rcvdata, t_u16 *payload_len, int *interface);
-extern int wrapper_wlan_handle_amsdu_rx_packet(const t_u8 *rcvdata, const t_u16 datalen);
-extern int wrapper_wlan_handle_rx_packet(const t_u16 datalen, const t_u8 *rcvdata,  NetworkBufferDescriptor_t *pxNetworkBuffer);
-static volatile  uint32_t xInterfaceState = INTERFACE_DOWN;
-
-static int process_data_packet(const t_u8 *databuf, const t_u16 datalen)
-{
-    int interface = BSS_TYPE_STA;
-    t_u8 *payload = NULL;
-    t_u16 payload_len = 0;
-    const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );
-
-    NetworkBufferDescriptor_t *pxNetworkBuffer;
-    IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
-
-    payload = (t_u8 *)mlan_get_payload(databuf, &payload_len, &interface);
-
-    if( eConsiderFrameForProcessing( payload ) != eProcessBuffer ) {
-       net_d("Dropping packet\r\n");
-       return WM_SUCCESS;
-    }
-
-    pxNetworkBuffer = pxGetNetworkBufferWithDescriptor(/*payload_len*/datalen, xDescriptorWaitTime);
-
-    if (pxNetworkBuffer != NULL) {
-       /* Set the packet size, in case a larger buffer was returned. */
-       pxNetworkBuffer->xDataLength = payload_len;
-
-       /* Copy the packet data. */
-       memcpy(pxNetworkBuffer->pucEthernetBuffer, payload, payload_len);
-
-       xRxEvent.pvData = (void *) pxNetworkBuffer;
-       if ( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime) == pdFAIL ) {
-               wmprintf("Failed to enqueue packet to network stack %p, len %d", payload, payload_len);
-               vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);
-               return WM_FAIL;
-       }
-    }
-    return WM_SUCCESS;
-}
-
-/* Callback function called from the wifi module */
-void handle_data_packet(const t_u8 interface, const t_u8 *rcvdata,
-                        const t_u16 datalen)
-{
-    if (interface == BSS_TYPE_STA)
-       process_data_packet(rcvdata, datalen);
-}
-
-BaseType_t xNetworkInterfaceInitialise( void )
-{
-    uint8_t ret;
-    mac_addr_t mac_addr;
-
-       ret = wifi_get_device_mac_addr(&mac_addr);
-       if (ret != WM_SUCCESS) {
-               net_d("Failed to get mac address");
-       }
-
-       FreeRTOS_UpdateMACAddress(mac_addr.mac);
-
-    return ( xInterfaceState == INTERFACE_UP && ret == WM_SUCCESS ) ? pdTRUE : pdFALSE;
-}
-
-void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
-{
-    /* FIX ME. */
-}
-
-BaseType_t xGetPhyLinkStatus( void )
-{
-    /* FIX ME. */
-    return pdFALSE;
-}
-void vNetworkNotifyIFDown()
-{
-    IPStackEvent_t xRxEvent = { eNetworkDownEvent, NULL };
-    xInterfaceState = INTERFACE_DOWN;
-    if( xSendEventStructToIPTask( &xRxEvent, 0 ) != pdPASS ) {
-       /* Could not send the message, so it is still pending. */
-        net_e("Could not send network down event");
-    }
-    else {
-       /* Message was sent so it is not pending. */
-        net_d("Sent network down event");
-    }
-}
-
-void vNetworkNotifyIFUp()
-{
-    xInterfaceState = INTERFACE_UP;
-}
-
-BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t *const pxNetworkBuffer, BaseType_t xReleaseAfterSend )
-{
-    uint8_t pkt_len;
-
-    if (pxNetworkBuffer == NULL ||
-       pxNetworkBuffer->pucEthernetBuffer == NULL ||
-       pxNetworkBuffer->xDataLength == 0) {
-           net_d("Incorrect params");
-            return pdFALSE;
-    }
-    memset(outbuf, 0x00, sizeof(outbuf));
-    pkt_len = 22 + 4; /* sizeof(TxPD) + INTF_HEADER_LEN */
-    memcpy((u8_t *) outbuf + pkt_len, (u8_t *) pxNetworkBuffer->pucEthernetBuffer,
-               pxNetworkBuffer->xDataLength);
-    int ret = wifi_low_level_output(BSS_TYPE_STA, outbuf + pkt_len, pxNetworkBuffer->xDataLength);
-    if (ret != WM_SUCCESS) {
-       net_e("Failed output %p, length %d, error %d \r\n", pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength, ret);
-    }
-
-    if (xReleaseAfterSend != pdFALSE) {
-        vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);
-    }
-
-    return ret == WM_SUCCESS ? pdTRUE : pdFALSE;
-}
+/*\r
+FreeRTOS+TCP V2.0.11\r
+Copyright (C) 2018 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
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "list.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\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 "NetworkBufferManagement.h"\r
+#include "NetworkInterface.h"\r
+\r
+#include "wifi-decl.h"\r
+#include "wmerrno.h"\r
+#include "wifi.h"\r
+\r
+#include <wmlog.h>\r
+\r
+#define net_e(...)                             \\r
+    wmlog_e("freertos_tcp", ##__VA_ARGS__)\r
+#define net_w(...)                             \\r
+    wmlog_w("freertos_tcp", ##__VA_ARGS__)\r
+#define net_d(...)                             \\r
+    wmlog("freertos_tcp", ##__VA_ARGS__)\r
+\r
+#if 0 //this is lwip structure.\r
+#define MAX_INTERFACES_SUPPORTED 3\r
+static struct netif *netif_arr[MAX_INTERFACES_SUPPORTED];\r
+#endif\r
+\r
+/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet\r
+driver will filter incoming packets and only pass the stack those packets it\r
+considers need processing. */\r
+#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )\r
+#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer\r
+#else\r
+#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )\r
+#endif\r
+\r
+#define IP_ADDR_ANY         ((ip_addr_t *)&ip_addr_any)\r
+#define IP_ADDR_BROADCAST   ((ip_addr_t *)&ip_addr_broadcast)\r
+\r
+/** 255.255.255.255 */\r
+#define IPADDR_NONE         ((u32_t)0xffffffffUL)\r
+/** 127.0.0.1 */\r
+#define IPADDR_LOOPBACK     ((u32_t)0x7f000001UL)\r
+/** 0.0.0.0 */\r
+#define IPADDR_ANY          ((u32_t)0x00000000UL)\r
+/** 255.255.255.255 */\r
+#define IPADDR_BROADCAST    ((u32_t)0xffffffffUL)\r
+\r
+/** 255.255.255.255 */\r
+#define INADDR_NONE         IPADDR_NONE\r
+/** 127.0.0.1 */\r
+#define INADDR_LOOPBACK     IPADDR_LOOPBACK\r
+/** 0.0.0.0 */\r
+#define INADDR_ANY          IPADDR_ANY\r
+/** 255.255.255.255 */\r
+#define INADDR_BROADCAST    IPADDR_BROADCAST\r
+\r
+enum if_state_t {\r
+    INTERFACE_DOWN = 0,\r
+    INTERFACE_UP,\r
+};\r
+struct ip_addr {\r
+  u32_t addr;\r
+};\r
+\r
+#define MLAN_BSS_TYPE_STA 0\r
+\r
+extern uint8_t outbuf[2048];\r
+extern bool mlan_is_amsdu(const t_u8 *rcvdata);\r
+extern t_u8 *mlan_get_payload(const t_u8 *rcvdata, t_u16 *payload_len, int *interface);\r
+extern int wrapper_wlan_handle_amsdu_rx_packet(const t_u8 *rcvdata, const t_u16 datalen);\r
+extern int wrapper_wlan_handle_rx_packet(const t_u16 datalen, const t_u8 *rcvdata,  NetworkBufferDescriptor_t *pxNetworkBuffer);\r
+static volatile  uint32_t xInterfaceState = INTERFACE_DOWN;\r
+\r
+static int process_data_packet(const t_u8 *databuf, const t_u16 datalen)\r
+{\r
+    int interface = BSS_TYPE_STA;\r
+    t_u8 *payload = NULL;\r
+    t_u16 payload_len = 0;\r
+    const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );\r
+\r
+    NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+    IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
+\r
+    payload = (t_u8 *)mlan_get_payload(databuf, &payload_len, &interface);\r
+\r
+    if( eConsiderFrameForProcessing( payload ) != eProcessBuffer ) {\r
+       net_d("Dropping packet\r\n");\r
+       return WM_SUCCESS;\r
+    }\r
+\r
+    pxNetworkBuffer = pxGetNetworkBufferWithDescriptor(/*payload_len*/datalen, xDescriptorWaitTime);\r
+\r
+    if (pxNetworkBuffer != NULL) {\r
+       /* Set the packet size, in case a larger buffer was returned. */\r
+       pxNetworkBuffer->xDataLength = payload_len;\r
+\r
+       /* Copy the packet data. */\r
+       memcpy(pxNetworkBuffer->pucEthernetBuffer, payload, payload_len);\r
+\r
+       xRxEvent.pvData = (void *) pxNetworkBuffer;\r
+       if ( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime) == pdFAIL ) {\r
+               wmprintf("Failed to enqueue packet to network stack %p, len %d", payload, payload_len);\r
+               vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);\r
+               return WM_FAIL;\r
+       }\r
+    }\r
+    return WM_SUCCESS;\r
+}\r
+\r
+/* Callback function called from the wifi module */\r
+void handle_data_packet(const t_u8 interface, const t_u8 *rcvdata,\r
+                        const t_u16 datalen)\r
+{\r
+    if (interface == BSS_TYPE_STA)\r
+       process_data_packet(rcvdata, datalen);\r
+}\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+    uint8_t ret;\r
+    mac_addr_t mac_addr;\r
+\r
+       ret = wifi_get_device_mac_addr(&mac_addr);\r
+       if (ret != WM_SUCCESS) {\r
+               net_d("Failed to get mac address");\r
+       }\r
+\r
+       FreeRTOS_UpdateMACAddress(mac_addr.mac);\r
+\r
+    return ( xInterfaceState == INTERFACE_UP && ret == WM_SUCCESS ) ? pdTRUE : pdFALSE;\r
+}\r
+\r
+void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )\r
+{\r
+    /* FIX ME. */\r
+}\r
+\r
+BaseType_t xGetPhyLinkStatus( void )\r
+{\r
+    /* FIX ME. */\r
+    return pdFALSE;\r
+}\r
+void vNetworkNotifyIFDown()\r
+{\r
+    IPStackEvent_t xRxEvent = { eNetworkDownEvent, NULL };\r
+    xInterfaceState = INTERFACE_DOWN;\r
+    if( xSendEventStructToIPTask( &xRxEvent, 0 ) != pdPASS ) {\r
+       /* Could not send the message, so it is still pending. */\r
+        net_e("Could not send network down event");\r
+    }\r
+    else {\r
+       /* Message was sent so it is not pending. */\r
+        net_d("Sent network down event");\r
+    }\r
+}\r
+\r
+void vNetworkNotifyIFUp()\r
+{\r
+    xInterfaceState = INTERFACE_UP;\r
+}\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t *const pxNetworkBuffer, BaseType_t xReleaseAfterSend )\r
+{\r
+    uint8_t pkt_len;\r
+\r
+    if (pxNetworkBuffer == NULL ||\r
+       pxNetworkBuffer->pucEthernetBuffer == NULL ||\r
+       pxNetworkBuffer->xDataLength == 0) {\r
+           net_d("Incorrect params");\r
+            return pdFALSE;\r
+    }\r
+    memset(outbuf, 0x00, sizeof(outbuf));\r
+    pkt_len = 22 + 4; /* sizeof(TxPD) + INTF_HEADER_LEN */\r
+    memcpy((u8_t *) outbuf + pkt_len, (u8_t *) pxNetworkBuffer->pucEthernetBuffer,\r
+               pxNetworkBuffer->xDataLength);\r
+    int ret = wifi_low_level_output(BSS_TYPE_STA, outbuf + pkt_len, pxNetworkBuffer->xDataLength);\r
+    if (ret != WM_SUCCESS) {\r
+       net_e("Failed output %p, length %d, error %d \r\n", pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength, ret);\r
+    }\r
+\r
+    if (xReleaseAfterSend != pdFALSE) {\r
+        vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);\r
+    }\r
+\r
+    return ret == WM_SUCCESS ? pdTRUE : pdFALSE;\r
+}\r
index f00ae1fe8297ad4f59a02fd20f769a4420e22952..531e878eafc8e2837e6364281d242bafa746d401 100644 (file)
-/*
- * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.
- * Authors include Hein Tibosch and Richard Barry
- *
- *******************************************************************************
- ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
- ***                                                                         ***
- ***                                                                         ***
- ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***
- ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***
- ***   download):                                                            ***
- ***                                                                         ***
- ***   FreeRTOS+TCP is functional and has been used in commercial products   ***
- ***   for some time.  Be aware however that we are still refining its       ***
- ***   design, the source code does not yet quite conform to the strict      ***
- ***   coding and style standards mandated by Real Time Engineers ltd., and  ***
- ***   the documentation and testing is not necessarily complete.            ***
- ***                                                                         ***
- ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***
- ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***
- ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***
- ***   under a license other than that described below.                      ***
- ***                                                                         ***
- ***                                                                         ***
- ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***
- *******************************************************************************
- *
- * FreeRTOS+TCP can be used under two different free open source licenses.  The
- * license that applies is dependent on the processor on which FreeRTOS+TCP is
- * executed, as follows:
- *
- * If FreeRTOS+TCP is executed on one of the processors listed under the Special
- * License Arrangements heading of the FreeRTOS+TCP license information web
- * page, then it can be used under the terms of the FreeRTOS Open Source
- * License.  If FreeRTOS+TCP is used on any other processor, then it can be used
- * under the terms of the GNU General Public License V2.  Links to the relevant
- * licenses follow:
- *
- * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license
- * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license
- * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt
- *
- * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot
- * use FreeRTOS+TCP unless you agree that you use the software 'as is'.
- * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied
- * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
- * implied, expressed, or statutory.
- *
- * 1 tab == 4 spaces!
- *
- * http://www.FreeRTOS.org
- * http://www.FreeRTOS.org/plus
- * http://www.FreeRTOS.org/labs
- *
- */
-
-/******************************************************************************
-*
-* See the following web page for essential buffer allocation scheme usage and
-* configuration details:
-* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html
-*
-******************************************************************************/
-
-/* THIS FILE SHOULD NOT BE USED IF THE PROJECT INCLUDES A MEMORY ALLOCATOR
- * THAT WILL FRAGMENT THE HEAP MEMORY.  For example, heap_2 must not be used,
- * heap_4 can be used. */
-
-/* Standard includes. */
-#include <stdint.h>
-
-/* FreeRTOS includes. */
-#include "FreeRTOS.h"
-#include "task.h"
-#include "semphr.h"
-
-/* FreeRTOS+TCP includes. */
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_UDP_IP.h"
-#include "FreeRTOS_IP_Private.h"
-#include "NetworkInterface.h"
-#include "NetworkBufferManagement.h"
-
-#include "tcpip/tcpip.h"
-#include "tcpip/src/tcpip_private.h"
-
-#include "NetworkConfig.h"
-
-/* The obtained network buffer must be large enough to hold a packet that might
- * replace the packet that was requested to be sent. */
-#if ipconfigUSE_TCP == 1
-    #define baMINIMAL_BUFFER_SIZE    sizeof( TCPPacket_t )
-#else
-    #define baMINIMAL_BUFFER_SIZE    sizeof( ARPPacket_t )
-#endif /* ipconfigUSE_TCP == 1 */
-
-/*_RB_ This is too complex not to have an explanation. */
-#if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES )
-    #define ASSERT_CONCAT_( a, b )    a ## b
-    #define ASSERT_CONCAT( a, b )     ASSERT_CONCAT_( a, b )
-    #define STATIC_ASSERT( e ) \
-    ; enum { ASSERT_CONCAT( assert_line_, __LINE__ ) = 1 / ( !!( e ) ) }
-
-    STATIC_ASSERT( ipconfigETHERNET_MINIMUM_PACKET_BYTES <= baMINIMAL_BUFFER_SIZE );
-#endif
-
-/* A list of free (available) NetworkBufferDescriptor_t structures. */
-static List_t xFreeBuffersList;
-
-/* Some statistics about the use of buffers. */
-static size_t uxMinimumFreeNetworkBuffers;
-
-/* Declares the pool of NetworkBufferDescriptor_t structures that are available
- * to the system.  All the network buffers referenced from xFreeBuffersList exist
- * in this array.  The array is not accessed directly except during initialisation,
- * when the xFreeBuffersList is filled (as all the buffers are free when the system
- * is booted). */
-static NetworkBufferDescriptor_t xNetworkBufferDescriptors[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ];
-
-/* This constant is defined as false to let FreeRTOS_TCP_IP.c know that the
- * network buffers have a variable size: resizing may be necessary */
-const BaseType_t xBufferAllocFixedSize = pdFALSE;
-
-/* The semaphore used to obtain network buffers. */
-static SemaphoreHandle_t xNetworkBufferSemaphore = NULL;
-
-/*-----------------------------------------------------------*/
-
-#ifdef PIC32_USE_ETHERNET
-
-    /* PIC32 specific stuff */
-    /* */
-
-    /* MAC packet acknowledgment, once MAC is done with it */
-        static bool PIC32_MacPacketAcknowledge( TCPIP_MAC_PACKET * pPkt,
-                                                const void * param );
-
-    /* allocates a MAC packet that holds a data buffer that can be used by both: */
-    /*  - the FreeRTOSIP (NetworkBufferDescriptor_t->pucEthernetBuffer) */
-    /*  - the Harmony MAC driver: TCPIP_MAC_PACKET->pDSeg->segLoad */
-    /* from the beginning of the buffer: */
-    /*      - 4 bytes pointer to the network descriptor (FreeRTOS) */
-    /*      - 4 bytes pointer to the MAC packet (pic32_NetworkInterface.c) */
-    /*      - 2 bytes offset from the MAC packet (Harmony MAC driver: segLoadOffset) */
-    /* */
-    /* NOTE: segLoadLen should NOT include: */
-    /*          - the TCPIP_MAC_FRAME_OFFSET (== ipBUFFER_PADDING which should be == 10!) */
-    /*          - the sizeof(TCPIP_MAC_ETHERNET_HEADER) */
-    /*       These are added by the MAC packet allocation! */
-    /* */
-    static uint8_t * PIC32_PktAlloc( uint16_t pktLen,
-                                     uint16_t segLoadLen,
-                                     TCPIP_MAC_PACKET_ACK_FUNC ackF,
-                                     TCPIP_MAC_PACKET ** pPtrPkt )
-    {
-        uint8_t * pBuff = 0;
-
-        /* allocate standard packet */
-        TCPIP_MAC_PACKET * pPkt = TCPIP_PKT_PacketAlloc( pktLen, segLoadLen, 0 );
-
-        /* set the MAC packet pointer in the packet */
-        if( pPkt != 0 )
-        {
-            pBuff = pPkt->pDSeg->segLoad;
-            TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pBuff - PIC32_BUFFER_PKT_PTR_OSSET );
-            configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 );
-            *ppkt = pPkt; /* store the packet it comes from */
-            pPkt->ackFunc = ackF;
-            pPkt->ackParam = 0;
-        }
-
-        if( pPtrPkt != 0 )
-        {
-            *pPtrPkt = pPkt;
-        }
-
-        return pBuff;
-    }
-
-
-
-    /* standard PIC32 MAC allocation function for a MAC packet */
-    /* this packet saves room for the FreeRTOS network descriptor */
-    /* at the beginning of the data buffer */
-    /* see NetworkBufferAllocate */
-    /* Note: flags parameter is ignored since that's used in the Harmony stack only */
-    TCPIP_MAC_PACKET * PIC32_MacPacketAllocate( uint16_t pktLen,
-                                                uint16_t segLoadLen,
-                                                TCPIP_MAC_PACKET_FLAGS flags )
-    {
-        TCPIP_MAC_PACKET * pPkt;
-
-        PIC32_PktAlloc( pktLen, segLoadLen, 0, &pPkt );
-
-        return pPkt;
-    }
-
-    /* standard PIC32 MAC packet acknowledgment */
-    /* function called once MAC is done with it */
-    static bool PIC32_MacPacketAcknowledge( TCPIP_MAC_PACKET * pPkt,
-                                            const void * param )
-    {
-        configASSERT( ( pPkt != 0 ) );
-
-        TCPIP_PKT_PacketFree( pPkt );
-
-        return false;
-    }
-
-    /* associates the current MAC packet with a network descriptor */
-    /* mainly for RX packet */
-    void PIC32_MacAssociate( TCPIP_MAC_PACKET * pRxPkt,
-                             NetworkBufferDescriptor_t * pxBufferDescriptor,
-                             size_t pktLength )
-    {
-        uint8_t * pPktBuff = pRxPkt->pDSeg->segLoad;
-
-        pxBufferDescriptor->pucEthernetBuffer = pPktBuff;
-        pxBufferDescriptor->xDataLength = pktLength;
-
-        /* make sure this is a properly allocated packet */
-        TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pPktBuff - PIC32_BUFFER_PKT_PTR_OSSET );
-        configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 );
-
-        if( *ppkt != pRxPkt )
-        {
-            configASSERT( false );
-        }
-
-        /* set the proper descriptor info */
-        NetworkBufferDescriptor_t ** ppDcpt = ( NetworkBufferDescriptor_t ** ) ( pPktBuff - ipBUFFER_PADDING );
-        configASSERT( ( ( uint32_t ) ppDcpt & ( sizeof( uint32_t ) - 1 ) ) == 0 );
-        *ppDcpt = pxBufferDescriptor;
-    }
-
-    /* debug functionality */
-    void PIC32_MacPacketOrphan( TCPIP_MAC_PACKET * pPkt )
-    {
-        TCPIP_PKT_PacketFree( pPkt );
-        configASSERT( false );
-    }
-
-    /* FreeRTOS allocation functions */
-
-    /* allocates a buffer that can be used by both: */
-    /*  - the FreeRTOSIP (NetworkBufferDescriptor_t->pucEthernetBuffer) */
-    /*  - the Harmony MAC driver: TCPIP_MAC_PACKET */
-    /*  See PIC32_PktAlloc for details */
-    /* */
-    /* NOTE: reqLength should NOT include the ipBUFFER_PADDING (which should be == 10!) */
-    /*       or the sizeof(TCPIP_MAC_ETHERNET_HEADER) */
-    /*       These are added by the MAC packet allocation! */
-    /* */
-    uint8_t * NetworkBufferAllocate( size_t reqLength )
-    {
-        return PIC32_PktAlloc( sizeof( TCPIP_MAC_PACKET ), reqLength, PIC32_MacPacketAcknowledge, 0 );
-    }
-
-    /* deallocates a network buffer previously allocated */
-    /* with NetworkBufferAllocate */
-    void NetworkBufferFree( uint8_t * pNetworkBuffer )
-    {
-        if( pNetworkBuffer != 0 )
-        {
-            TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pNetworkBuffer - PIC32_BUFFER_PKT_PTR_OSSET );
-            configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 );
-            TCPIP_MAC_PACKET * pPkt = *ppkt;
-            configASSERT( ( pPkt != 0 ) );
-
-            if( pPkt->ackFunc != 0 )
-            {
-                ( *pPkt->ackFunc )( pPkt, pPkt->ackParam );
-            }
-            else
-            { /* ??? */
-                PIC32_MacPacketOrphan( pPkt );
-            }
-        }
-    }
-
-#endif /* #ifdef PIC32_USE_ETHERNET */
-
-/*-----------------------------------------------------------*/
-
-BaseType_t xNetworkBuffersInitialise( void )
-{
-    BaseType_t xReturn, x;
-
-    /* Only initialise the buffers and their associated kernel objects if they
-     * have not been initialised before. */
-    if( xNetworkBufferSemaphore == NULL )
-    {
-        xNetworkBufferSemaphore = xSemaphoreCreateCounting( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS );
-        configASSERT( xNetworkBufferSemaphore );
-
-        if( xNetworkBufferSemaphore != NULL )
-        {
-            #if ( configQUEUE_REGISTRY_SIZE > 0 )
-                {
-                    vQueueAddToRegistry( xNetworkBufferSemaphore, "NetBufSem" );
-                }
-            #endif /* configQUEUE_REGISTRY_SIZE */
-
-            /* If the trace recorder code is included name the semaphore for viewing
-             * in FreeRTOS+Trace.  */
-            #if ( ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 )
-                {
-                    extern QueueHandle_t xNetworkEventQueue;
-                    vTraceSetQueueName( xNetworkEventQueue, "IPStackEvent" );
-                    vTraceSetQueueName( xNetworkBufferSemaphore, "NetworkBufferCount" );
-                }
-            #endif /*  ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 */
-
-            vListInitialise( &xFreeBuffersList );
-
-            /* Initialise all the network buffers.  No storage is allocated to
-             * the buffers yet. */
-            for( x = 0; x < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; x++ )
-            {
-                /* Initialise and set the owner of the buffer list items. */
-                xNetworkBufferDescriptors[ x ].pucEthernetBuffer = NULL;
-                vListInitialiseItem( &( xNetworkBufferDescriptors[ x ].xBufferListItem ) );
-                listSET_LIST_ITEM_OWNER( &( xNetworkBufferDescriptors[ x ].xBufferListItem ), &xNetworkBufferDescriptors[ x ] );
-
-                /* Currently, all buffers are available for use. */
-                vListInsert( &xFreeBuffersList, &( xNetworkBufferDescriptors[ x ].xBufferListItem ) );
-            }
-
-            uxMinimumFreeNetworkBuffers = ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS;
-        }
-    }
-
-    if( xNetworkBufferSemaphore == NULL )
-    {
-        xReturn = pdFAIL;
-    }
-    else
-    {
-        xReturn = pdPASS;
-    }
-
-    return xReturn;
-}
-/*-----------------------------------------------------------*/
-
-uint8_t * pucGetNetworkBuffer( size_t * pxRequestedSizeBytes )
-{
-    uint8_t * pucEthernetBuffer;
-    size_t xSize = *pxRequestedSizeBytes;
-
-    if( xSize < baMINIMAL_BUFFER_SIZE )
-    {
-        /* Buffers must be at least large enough to hold a TCP-packet with
-         * headers, or an ARP packet, in case TCP is not included. */
-        xSize = baMINIMAL_BUFFER_SIZE;
-    }
-
-    /* Round up xSize to the nearest multiple of N bytes,
-     * where N equals 'sizeof( size_t )'. */
-    if( ( xSize & ( sizeof( size_t ) - 1u ) ) != 0u )
-    {
-        xSize = ( xSize | ( sizeof( size_t ) - 1u ) ) + 1u;
-    }
-
-    *pxRequestedSizeBytes = xSize;
-
-    /* Allocate a buffer large enough to store the requested Ethernet frame size
-     * and a pointer to a network buffer structure (hence the addition of
-     * ipBUFFER_PADDING bytes). */
-
-    #ifdef PIC32_USE_ETHERNET
-        pucEthernetBuffer = NetworkBufferAllocate( xSize - sizeof( TCPIP_MAC_ETHERNET_HEADER ) );
-    #else
-        pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xSize + ipBUFFER_PADDING );
-    #endif /* #ifdef PIC32_USE_ETHERNET */
-
-    configASSERT( pucEthernetBuffer );
-
-    if( pucEthernetBuffer != NULL )
-    {
-        /* Enough space is left at the start of the buffer to place a pointer to
-         * the network buffer structure that references this Ethernet buffer.
-         * Return a pointer to the start of the Ethernet buffer itself. */
-               #ifndef PIC32_USE_ETHERNET
-               pucEthernetBuffer += ipBUFFER_PADDING;
-               #endif /* #ifndef PIC32_USE_ETHERNET */
-    }
-
-    return pucEthernetBuffer;
-}
-/*-----------------------------------------------------------*/
-
-void vReleaseNetworkBuffer( uint8_t * pucEthernetBuffer )
-{
-    /* There is space before the Ethernet buffer in which a pointer to the
-     * network buffer that references this Ethernet buffer is stored.  Remove the
-     * space before freeing the buffer. */
-    #ifdef PIC32_USE_ETHERNET
-        NetworkBufferFree( pucEthernetBuffer );
-    #else
-        if( pucEthernetBuffer != NULL )
-        {
-            pucEthernetBuffer -= ipBUFFER_PADDING;
-            vPortFree( ( void * ) pucEthernetBuffer );
-        }
-    #endif /* #ifdef PIC32_USE_ETHERNET */
-}
-/*-----------------------------------------------------------*/
-
-NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes,
-                                                              TickType_t xBlockTimeTicks )
-{
-    NetworkBufferDescriptor_t * pxReturn = NULL;
-    size_t uxCount;
-
-    if( ( xRequestedSizeBytes != 0u ) && ( xRequestedSizeBytes < ( size_t ) baMINIMAL_BUFFER_SIZE ) )
-    {
-        /* ARP packets can replace application packets, so the storage must be
-         * at least large enough to hold an ARP. */
-        xRequestedSizeBytes = baMINIMAL_BUFFER_SIZE;
-    }
-
-       #ifdef PIC32_USE_ETHERNET
-       if( xRequestedSizeBytes != 0u )
-    {
-       #endif /* #ifdef PIC32_USE_ETHERNET */
-       xRequestedSizeBytes += 2u;
-
-       if( ( xRequestedSizeBytes & ( sizeof( size_t ) - 1u ) ) != 0u )
-       {
-               xRequestedSizeBytes = ( xRequestedSizeBytes | ( sizeof( size_t ) - 1u ) ) + 1u;
-       }
-       #ifdef PIC32_USE_ETHERNET
-    }
-       #endif /* #ifdef PIC32_USE_ETHERNET */
-
-    /* If there is a semaphore available, there is a network buffer available. */
-    if( xSemaphoreTake( xNetworkBufferSemaphore, xBlockTimeTicks ) == pdPASS )
-    {
-        /* Protect the structure as it is accessed from tasks and interrupts. */
-        taskENTER_CRITICAL();
-        {
-            pxReturn = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );
-            uxListRemove( &( pxReturn->xBufferListItem ) );
-        }
-        taskEXIT_CRITICAL();
-
-        /* Reading UBaseType_t, no critical section needed. */
-        uxCount = listCURRENT_LIST_LENGTH( &xFreeBuffersList );
-
-        if( uxMinimumFreeNetworkBuffers > uxCount )
-        {
-            uxMinimumFreeNetworkBuffers = uxCount;
-        }
-
-        /* Allocate storage of exactly the requested size to the buffer. */
-        configASSERT( pxReturn->pucEthernetBuffer == NULL );
-
-        if( xRequestedSizeBytes > 0 )
-        {
-            /* Extra space is obtained so a pointer to the network buffer can
-             * be stored at the beginning of the buffer. */
-
-            #ifdef PIC32_USE_ETHERNET
-                pxReturn->pucEthernetBuffer = NetworkBufferAllocate( xRequestedSizeBytes - sizeof( TCPIP_MAC_ETHERNET_HEADER ) );
-            #else
-                pxReturn->pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xRequestedSizeBytes + ipBUFFER_PADDING );
-            #endif /* #ifdef PIC32_USE_ETHERNET */
-
-            if( pxReturn->pucEthernetBuffer == NULL )
-            {
-                /* The attempt to allocate storage for the buffer payload failed,
-                 * so the network buffer structure cannot be used and must be
-                 * released. */
-                vReleaseNetworkBufferAndDescriptor( pxReturn );
-                pxReturn = NULL;
-            }
-            else
-            {
-                /* Store a pointer to the network buffer structure in the
-                 * buffer storage area, then move the buffer pointer on past the
-                 * stored pointer so the pointer value is not overwritten by the
-                 * application when the buffer is used. */
-                #ifdef PIC32_USE_ETHERNET
-                    *( ( NetworkBufferDescriptor_t ** ) ( pxReturn->pucEthernetBuffer - ipBUFFER_PADDING ) ) = pxReturn;
-                #else
-                    *( ( NetworkBufferDescriptor_t ** ) ( pxReturn->pucEthernetBuffer ) ) = pxReturn;
-                    pxReturn->pucEthernetBuffer += ipBUFFER_PADDING;
-                #endif /* #ifdef PIC32_USE_ETHERNET */
-
-                /* Store the actual size of the allocated buffer, which may be
-                 * greater than the original requested size. */
-                pxReturn->xDataLength = xRequestedSizeBytes;
-
-                #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
-                    {
-                        /* make sure the buffer is not linked */
-                        pxReturn->pxNextBuffer = NULL;
-                    }
-                #endif /* ipconfigUSE_LINKED_RX_MESSAGES */
-            }
-        }
-        else
-        {
-            /* A descriptor is being returned without an associated buffer being
-             * allocated. */
-        }
-    }
-
-    if( pxReturn == NULL )
-    {
-        iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER();
-    }
-    else
-    {
-        iptraceNETWORK_BUFFER_OBTAINED( pxReturn );
-    }
-
-    return pxReturn;
-}
-/*-----------------------------------------------------------*/
-
-void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer )
-{
-    BaseType_t xListItemAlreadyInFreeList;
-
-    /* Ensure the buffer is returned to the list of free buffers before the
-    * counting semaphore is 'given' to say a buffer is available.  Release the
-    * storage allocated to the buffer payload.  THIS FILE SHOULD NOT BE USED
-    * IF THE PROJECT INCLUDES A MEMORY ALLOCATOR THAT WILL FRAGMENT THE HEAP
-    * MEMORY.  For example, heap_2 must not be used, heap_4 can be used. */
-    vReleaseNetworkBuffer( pxNetworkBuffer->pucEthernetBuffer );
-    pxNetworkBuffer->pucEthernetBuffer = NULL;
-
-    taskENTER_CRITICAL();
-    {
-        xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
-
-        if( xListItemAlreadyInFreeList == pdFALSE )
-        {
-            vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
-        }
-    }
-    taskEXIT_CRITICAL();
-
-    /*
-     * Update the network state machine, unless the program fails to release its 'xNetworkBufferSemaphore'.
-     * The program should only try to release its semaphore if 'xListItemAlreadyInFreeList' is false.
-     */
-    if( xListItemAlreadyInFreeList == pdFALSE )
-    {
-        if ( xSemaphoreGive( xNetworkBufferSemaphore ) == pdTRUE )
-        {
-            iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
-        }
-    }
-    else
-    {
-        iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
-    }
-}
-/*-----------------------------------------------------------*/
-
-/*
- * Returns the number of free network buffers
- */
-UBaseType_t uxGetNumberOfFreeNetworkBuffers( void )
-{
-    return listCURRENT_LIST_LENGTH( &xFreeBuffersList );
-}
-/*-----------------------------------------------------------*/
-
-UBaseType_t uxGetMinimumFreeNetworkBuffers( void )
-{
-    return uxMinimumFreeNetworkBuffers;
-}
-/*-----------------------------------------------------------*/
-
-NetworkBufferDescriptor_t * pxResizeNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * pxNetworkBuffer,
-                                                                 size_t xNewSizeBytes )
-{
-    size_t xOriginalLength;
-    uint8_t * pucBuffer;
-
-    #ifdef PIC32_USE_ETHERNET
-        xOriginalLength = pxNetworkBuffer->xDataLength;
-    #else
-        xOriginalLength = pxNetworkBuffer->xDataLength + ipBUFFER_PADDING;
-               xNewSizeBytes = xNewSizeBytes + ipBUFFER_PADDING;
-    #endif /* #ifdef PIC32_USE_ETHERNET */
-       
-    pucBuffer = pucGetNetworkBuffer( &( xNewSizeBytes ) );
-
-    if( pucBuffer == NULL )
-    {
-        /* In case the allocation fails, return NULL. */
-        pxNetworkBuffer = NULL;
-    }
-    else
-    {
-        pxNetworkBuffer->xDataLength = xNewSizeBytes;
-        if( xNewSizeBytes > xOriginalLength )
-        {
-            xNewSizeBytes = xOriginalLength;
-        }
-
-        #ifdef PIC32_USE_ETHERNET
-            memcpy( pucBuffer, pxNetworkBuffer->pucEthernetBuffer, xNewSizeBytes );
-            *( ( NetworkBufferDescriptor_t ** ) ( pucBuffer - ipBUFFER_PADDING ) ) = pxNetworkBuffer;
-        #else
-            memcpy( pucBuffer - ipBUFFER_PADDING, pxNetworkBuffer->pucEthernetBuffer - ipBUFFER_PADDING, xNewSizeBytes );
-        #endif /* #ifdef PIC32_USE_ETHERNET */
-
-        vReleaseNetworkBuffer( pxNetworkBuffer->pucEthernetBuffer );
-        pxNetworkBuffer->pucEthernetBuffer = pucBuffer;
-    }
-
-    return pxNetworkBuffer;
-}
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/******************************************************************************\r
+*\r
+* See the following web page for essential buffer allocation scheme usage and\r
+* configuration details:\r
+* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html\r
+*\r
+******************************************************************************/\r
+\r
+/* THIS FILE SHOULD NOT BE USED IF THE PROJECT INCLUDES A MEMORY ALLOCATOR\r
+ * THAT WILL FRAGMENT THE HEAP MEMORY.  For example, heap_2 must not be used,\r
+ * heap_4 can be used. */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_UDP_IP.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkInterface.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+#include "tcpip/tcpip.h"\r
+#include "tcpip/src/tcpip_private.h"\r
+\r
+#include "NetworkConfig.h"\r
+\r
+/* The obtained network buffer must be large enough to hold a packet that might\r
+ * replace the packet that was requested to be sent. */\r
+#if ipconfigUSE_TCP == 1\r
+    #define baMINIMAL_BUFFER_SIZE    sizeof( TCPPacket_t )\r
+#else\r
+    #define baMINIMAL_BUFFER_SIZE    sizeof( ARPPacket_t )\r
+#endif /* ipconfigUSE_TCP == 1 */\r
+\r
+/*_RB_ This is too complex not to have an explanation. */\r
+#if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES )\r
+    #define ASSERT_CONCAT_( a, b )    a ## b\r
+    #define ASSERT_CONCAT( a, b )     ASSERT_CONCAT_( a, b )\r
+    #define STATIC_ASSERT( e ) \\r
+    ; enum { ASSERT_CONCAT( assert_line_, __LINE__ ) = 1 / ( !!( e ) ) }\r
+\r
+    STATIC_ASSERT( ipconfigETHERNET_MINIMUM_PACKET_BYTES <= baMINIMAL_BUFFER_SIZE );\r
+#endif\r
+\r
+/* A list of free (available) NetworkBufferDescriptor_t structures. */\r
+static List_t xFreeBuffersList;\r
+\r
+/* Some statistics about the use of buffers. */\r
+static size_t uxMinimumFreeNetworkBuffers;\r
+\r
+/* Declares the pool of NetworkBufferDescriptor_t structures that are available\r
+ * to the system.  All the network buffers referenced from xFreeBuffersList exist\r
+ * in this array.  The array is not accessed directly except during initialisation,\r
+ * when the xFreeBuffersList is filled (as all the buffers are free when the system\r
+ * is booted). */\r
+static NetworkBufferDescriptor_t xNetworkBufferDescriptors[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ];\r
+\r
+/* This constant is defined as false to let FreeRTOS_TCP_IP.c know that the\r
+ * network buffers have a variable size: resizing may be necessary */\r
+const BaseType_t xBufferAllocFixedSize = pdFALSE;\r
+\r
+/* The semaphore used to obtain network buffers. */\r
+static SemaphoreHandle_t xNetworkBufferSemaphore = NULL;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+#ifdef PIC32_USE_ETHERNET\r
+\r
+    /* PIC32 specific stuff */\r
+    /* */\r
+\r
+    /* MAC packet acknowledgment, once MAC is done with it */\r
+        static bool PIC32_MacPacketAcknowledge( TCPIP_MAC_PACKET * pPkt,\r
+                                                const void * param );\r
+\r
+    /* allocates a MAC packet that holds a data buffer that can be used by both: */\r
+    /*  - the FreeRTOSIP (NetworkBufferDescriptor_t->pucEthernetBuffer) */\r
+    /*  - the Harmony MAC driver: TCPIP_MAC_PACKET->pDSeg->segLoad */\r
+    /* from the beginning of the buffer: */\r
+    /*      - 4 bytes pointer to the network descriptor (FreeRTOS) */\r
+    /*      - 4 bytes pointer to the MAC packet (pic32_NetworkInterface.c) */\r
+    /*      - 2 bytes offset from the MAC packet (Harmony MAC driver: segLoadOffset) */\r
+    /* */\r
+    /* NOTE: segLoadLen should NOT include: */\r
+    /*          - the TCPIP_MAC_FRAME_OFFSET (== ipBUFFER_PADDING which should be == 10!) */\r
+    /*          - the sizeof(TCPIP_MAC_ETHERNET_HEADER) */\r
+    /*       These are added by the MAC packet allocation! */\r
+    /* */\r
+    static uint8_t * PIC32_PktAlloc( uint16_t pktLen,\r
+                                     uint16_t segLoadLen,\r
+                                     TCPIP_MAC_PACKET_ACK_FUNC ackF,\r
+                                     TCPIP_MAC_PACKET ** pPtrPkt )\r
+    {\r
+        uint8_t * pBuff = 0;\r
+\r
+        /* allocate standard packet */\r
+        TCPIP_MAC_PACKET * pPkt = TCPIP_PKT_PacketAlloc( pktLen, segLoadLen, 0 );\r
+\r
+        /* set the MAC packet pointer in the packet */\r
+        if( pPkt != 0 )\r
+        {\r
+            pBuff = pPkt->pDSeg->segLoad;\r
+            TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pBuff - PIC32_BUFFER_PKT_PTR_OSSET );\r
+            configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 );\r
+            *ppkt = pPkt; /* store the packet it comes from */\r
+            pPkt->ackFunc = ackF;\r
+            pPkt->ackParam = 0;\r
+        }\r
+\r
+        if( pPtrPkt != 0 )\r
+        {\r
+            *pPtrPkt = pPkt;\r
+        }\r
+\r
+        return pBuff;\r
+    }\r
+\r
+\r
+\r
+    /* standard PIC32 MAC allocation function for a MAC packet */\r
+    /* this packet saves room for the FreeRTOS network descriptor */\r
+    /* at the beginning of the data buffer */\r
+    /* see NetworkBufferAllocate */\r
+    /* Note: flags parameter is ignored since that's used in the Harmony stack only */\r
+    TCPIP_MAC_PACKET * PIC32_MacPacketAllocate( uint16_t pktLen,\r
+                                                uint16_t segLoadLen,\r
+                                                TCPIP_MAC_PACKET_FLAGS flags )\r
+    {\r
+        TCPIP_MAC_PACKET * pPkt;\r
+\r
+        PIC32_PktAlloc( pktLen, segLoadLen, 0, &pPkt );\r
+\r
+        return pPkt;\r
+    }\r
+\r
+    /* standard PIC32 MAC packet acknowledgment */\r
+    /* function called once MAC is done with it */\r
+    static bool PIC32_MacPacketAcknowledge( TCPIP_MAC_PACKET * pPkt,\r
+                                            const void * param )\r
+    {\r
+        configASSERT( ( pPkt != 0 ) );\r
+\r
+        TCPIP_PKT_PacketFree( pPkt );\r
+\r
+        return false;\r
+    }\r
+\r
+    /* associates the current MAC packet with a network descriptor */\r
+    /* mainly for RX packet */\r
+    void PIC32_MacAssociate( TCPIP_MAC_PACKET * pRxPkt,\r
+                             NetworkBufferDescriptor_t * pxBufferDescriptor,\r
+                             size_t pktLength )\r
+    {\r
+        uint8_t * pPktBuff = pRxPkt->pDSeg->segLoad;\r
+\r
+        pxBufferDescriptor->pucEthernetBuffer = pPktBuff;\r
+        pxBufferDescriptor->xDataLength = pktLength;\r
+\r
+        /* make sure this is a properly allocated packet */\r
+        TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pPktBuff - PIC32_BUFFER_PKT_PTR_OSSET );\r
+        configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 );\r
+\r
+        if( *ppkt != pRxPkt )\r
+        {\r
+            configASSERT( false );\r
+        }\r
+\r
+        /* set the proper descriptor info */\r
+        NetworkBufferDescriptor_t ** ppDcpt = ( NetworkBufferDescriptor_t ** ) ( pPktBuff - ipBUFFER_PADDING );\r
+        configASSERT( ( ( uint32_t ) ppDcpt & ( sizeof( uint32_t ) - 1 ) ) == 0 );\r
+        *ppDcpt = pxBufferDescriptor;\r
+    }\r
+\r
+    /* debug functionality */\r
+    void PIC32_MacPacketOrphan( TCPIP_MAC_PACKET * pPkt )\r
+    {\r
+        TCPIP_PKT_PacketFree( pPkt );\r
+        configASSERT( false );\r
+    }\r
+\r
+    /* FreeRTOS allocation functions */\r
+\r
+    /* allocates a buffer that can be used by both: */\r
+    /*  - the FreeRTOSIP (NetworkBufferDescriptor_t->pucEthernetBuffer) */\r
+    /*  - the Harmony MAC driver: TCPIP_MAC_PACKET */\r
+    /*  See PIC32_PktAlloc for details */\r
+    /* */\r
+    /* NOTE: reqLength should NOT include the ipBUFFER_PADDING (which should be == 10!) */\r
+    /*       or the sizeof(TCPIP_MAC_ETHERNET_HEADER) */\r
+    /*       These are added by the MAC packet allocation! */\r
+    /* */\r
+    uint8_t * NetworkBufferAllocate( size_t reqLength )\r
+    {\r
+        return PIC32_PktAlloc( sizeof( TCPIP_MAC_PACKET ), reqLength, PIC32_MacPacketAcknowledge, 0 );\r
+    }\r
+\r
+    /* deallocates a network buffer previously allocated */\r
+    /* with NetworkBufferAllocate */\r
+    void NetworkBufferFree( uint8_t * pNetworkBuffer )\r
+    {\r
+        if( pNetworkBuffer != 0 )\r
+        {\r
+            TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pNetworkBuffer - PIC32_BUFFER_PKT_PTR_OSSET );\r
+            configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 );\r
+            TCPIP_MAC_PACKET * pPkt = *ppkt;\r
+            configASSERT( ( pPkt != 0 ) );\r
+\r
+            if( pPkt->ackFunc != 0 )\r
+            {\r
+                ( *pPkt->ackFunc )( pPkt, pPkt->ackParam );\r
+            }\r
+            else\r
+            { /* ??? */\r
+                PIC32_MacPacketOrphan( pPkt );\r
+            }\r
+        }\r
+    }\r
+\r
+#endif /* #ifdef PIC32_USE_ETHERNET */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkBuffersInitialise( void )\r
+{\r
+    BaseType_t xReturn, x;\r
+\r
+    /* Only initialise the buffers and their associated kernel objects if they\r
+     * have not been initialised before. */\r
+    if( xNetworkBufferSemaphore == NULL )\r
+    {\r
+        xNetworkBufferSemaphore = xSemaphoreCreateCounting( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS );\r
+        configASSERT( xNetworkBufferSemaphore );\r
+\r
+        if( xNetworkBufferSemaphore != NULL )\r
+        {\r
+            #if ( configQUEUE_REGISTRY_SIZE > 0 )\r
+                {\r
+                    vQueueAddToRegistry( xNetworkBufferSemaphore, "NetBufSem" );\r
+                }\r
+            #endif /* configQUEUE_REGISTRY_SIZE */\r
+\r
+            /* If the trace recorder code is included name the semaphore for viewing\r
+             * in FreeRTOS+Trace.  */\r
+            #if ( ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 )\r
+                {\r
+                    extern QueueHandle_t xNetworkEventQueue;\r
+                    vTraceSetQueueName( xNetworkEventQueue, "IPStackEvent" );\r
+                    vTraceSetQueueName( xNetworkBufferSemaphore, "NetworkBufferCount" );\r
+                }\r
+            #endif /*  ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 */\r
+\r
+            vListInitialise( &xFreeBuffersList );\r
+\r
+            /* Initialise all the network buffers.  No storage is allocated to\r
+             * the buffers yet. */\r
+            for( x = 0; x < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; x++ )\r
+            {\r
+                /* Initialise and set the owner of the buffer list items. */\r
+                xNetworkBufferDescriptors[ x ].pucEthernetBuffer = NULL;\r
+                vListInitialiseItem( &( xNetworkBufferDescriptors[ x ].xBufferListItem ) );\r
+                listSET_LIST_ITEM_OWNER( &( xNetworkBufferDescriptors[ x ].xBufferListItem ), &xNetworkBufferDescriptors[ x ] );\r
+\r
+                /* Currently, all buffers are available for use. */\r
+                vListInsert( &xFreeBuffersList, &( xNetworkBufferDescriptors[ x ].xBufferListItem ) );\r
+            }\r
+\r
+            uxMinimumFreeNetworkBuffers = ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS;\r
+        }\r
+    }\r
+\r
+    if( xNetworkBufferSemaphore == NULL )\r
+    {\r
+        xReturn = pdFAIL;\r
+    }\r
+    else\r
+    {\r
+        xReturn = pdPASS;\r
+    }\r
+\r
+    return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+uint8_t * pucGetNetworkBuffer( size_t * pxRequestedSizeBytes )\r
+{\r
+    uint8_t * pucEthernetBuffer;\r
+    size_t xSize = *pxRequestedSizeBytes;\r
+\r
+    if( xSize < baMINIMAL_BUFFER_SIZE )\r
+    {\r
+        /* Buffers must be at least large enough to hold a TCP-packet with\r
+         * headers, or an ARP packet, in case TCP is not included. */\r
+        xSize = baMINIMAL_BUFFER_SIZE;\r
+    }\r
+\r
+    /* Round up xSize to the nearest multiple of N bytes,\r
+     * where N equals 'sizeof( size_t )'. */\r
+    if( ( xSize & ( sizeof( size_t ) - 1u ) ) != 0u )\r
+    {\r
+        xSize = ( xSize | ( sizeof( size_t ) - 1u ) ) + 1u;\r
+    }\r
+\r
+    *pxRequestedSizeBytes = xSize;\r
+\r
+    /* Allocate a buffer large enough to store the requested Ethernet frame size\r
+     * and a pointer to a network buffer structure (hence the addition of\r
+     * ipBUFFER_PADDING bytes). */\r
+\r
+    #ifdef PIC32_USE_ETHERNET\r
+        pucEthernetBuffer = NetworkBufferAllocate( xSize - sizeof( TCPIP_MAC_ETHERNET_HEADER ) );\r
+    #else\r
+        pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xSize + ipBUFFER_PADDING );\r
+    #endif /* #ifdef PIC32_USE_ETHERNET */\r
+\r
+    configASSERT( pucEthernetBuffer );\r
+\r
+    if( pucEthernetBuffer != NULL )\r
+    {\r
+        /* Enough space is left at the start of the buffer to place a pointer to\r
+         * the network buffer structure that references this Ethernet buffer.\r
+         * Return a pointer to the start of the Ethernet buffer itself. */\r
+               #ifndef PIC32_USE_ETHERNET\r
+               pucEthernetBuffer += ipBUFFER_PADDING;\r
+               #endif /* #ifndef PIC32_USE_ETHERNET */\r
+    }\r
+\r
+    return pucEthernetBuffer;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vReleaseNetworkBuffer( uint8_t * pucEthernetBuffer )\r
+{\r
+    /* There is space before the Ethernet buffer in which a pointer to the\r
+     * network buffer that references this Ethernet buffer is stored.  Remove the\r
+     * space before freeing the buffer. */\r
+    #ifdef PIC32_USE_ETHERNET\r
+        NetworkBufferFree( pucEthernetBuffer );\r
+    #else\r
+        if( pucEthernetBuffer != NULL )\r
+        {\r
+            pucEthernetBuffer -= ipBUFFER_PADDING;\r
+            vPortFree( ( void * ) pucEthernetBuffer );\r
+        }\r
+    #endif /* #ifdef PIC32_USE_ETHERNET */\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes,\r
+                                                              TickType_t xBlockTimeTicks )\r
+{\r
+    NetworkBufferDescriptor_t * pxReturn = NULL;\r
+    size_t uxCount;\r
+\r
+    if( ( xRequestedSizeBytes != 0u ) && ( xRequestedSizeBytes < ( size_t ) baMINIMAL_BUFFER_SIZE ) )\r
+    {\r
+        /* ARP packets can replace application packets, so the storage must be\r
+         * at least large enough to hold an ARP. */\r
+        xRequestedSizeBytes = baMINIMAL_BUFFER_SIZE;\r
+    }\r
+\r
+       #ifdef PIC32_USE_ETHERNET\r
+       if( xRequestedSizeBytes != 0u )\r
+    {\r
+       #endif /* #ifdef PIC32_USE_ETHERNET */\r
+       xRequestedSizeBytes += 2u;\r
+\r
+       if( ( xRequestedSizeBytes & ( sizeof( size_t ) - 1u ) ) != 0u )\r
+       {\r
+               xRequestedSizeBytes = ( xRequestedSizeBytes | ( sizeof( size_t ) - 1u ) ) + 1u;\r
+       }\r
+       #ifdef PIC32_USE_ETHERNET\r
+    }\r
+       #endif /* #ifdef PIC32_USE_ETHERNET */\r
+\r
+    /* If there is a semaphore available, there is a network buffer available. */\r
+    if( xSemaphoreTake( xNetworkBufferSemaphore, xBlockTimeTicks ) == pdPASS )\r
+    {\r
+        /* Protect the structure as it is accessed from tasks and interrupts. */\r
+        taskENTER_CRITICAL();\r
+        {\r
+            pxReturn = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );\r
+            uxListRemove( &( pxReturn->xBufferListItem ) );\r
+        }\r
+        taskEXIT_CRITICAL();\r
+\r
+        /* Reading UBaseType_t, no critical section needed. */\r
+        uxCount = listCURRENT_LIST_LENGTH( &xFreeBuffersList );\r
+\r
+        if( uxMinimumFreeNetworkBuffers > uxCount )\r
+        {\r
+            uxMinimumFreeNetworkBuffers = uxCount;\r
+        }\r
+\r
+        /* Allocate storage of exactly the requested size to the buffer. */\r
+        configASSERT( pxReturn->pucEthernetBuffer == NULL );\r
+\r
+        if( xRequestedSizeBytes > 0 )\r
+        {\r
+            /* Extra space is obtained so a pointer to the network buffer can\r
+             * be stored at the beginning of the buffer. */\r
+\r
+            #ifdef PIC32_USE_ETHERNET\r
+                pxReturn->pucEthernetBuffer = NetworkBufferAllocate( xRequestedSizeBytes - sizeof( TCPIP_MAC_ETHERNET_HEADER ) );\r
+            #else\r
+                pxReturn->pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xRequestedSizeBytes + ipBUFFER_PADDING );\r
+            #endif /* #ifdef PIC32_USE_ETHERNET */\r
+\r
+            if( pxReturn->pucEthernetBuffer == NULL )\r
+            {\r
+                /* The attempt to allocate storage for the buffer payload failed,\r
+                 * so the network buffer structure cannot be used and must be\r
+                 * released. */\r
+                vReleaseNetworkBufferAndDescriptor( pxReturn );\r
+                pxReturn = NULL;\r
+            }\r
+            else\r
+            {\r
+                /* Store a pointer to the network buffer structure in the\r
+                 * buffer storage area, then move the buffer pointer on past the\r
+                 * stored pointer so the pointer value is not overwritten by the\r
+                 * application when the buffer is used. */\r
+                #ifdef PIC32_USE_ETHERNET\r
+                    *( ( NetworkBufferDescriptor_t ** ) ( pxReturn->pucEthernetBuffer - ipBUFFER_PADDING ) ) = pxReturn;\r
+                #else\r
+                    *( ( NetworkBufferDescriptor_t ** ) ( pxReturn->pucEthernetBuffer ) ) = pxReturn;\r
+                    pxReturn->pucEthernetBuffer += ipBUFFER_PADDING;\r
+                #endif /* #ifdef PIC32_USE_ETHERNET */\r
+\r
+                /* Store the actual size of the allocated buffer, which may be\r
+                 * greater than the original requested size. */\r
+                pxReturn->xDataLength = xRequestedSizeBytes;\r
+\r
+                #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 )\r
+                    {\r
+                        /* make sure the buffer is not linked */\r
+                        pxReturn->pxNextBuffer = NULL;\r
+                    }\r
+                #endif /* ipconfigUSE_LINKED_RX_MESSAGES */\r
+            }\r
+        }\r
+        else\r
+        {\r
+            /* A descriptor is being returned without an associated buffer being\r
+             * allocated. */\r
+        }\r
+    }\r
+\r
+    if( pxReturn == NULL )\r
+    {\r
+        iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER();\r
+    }\r
+    else\r
+    {\r
+        iptraceNETWORK_BUFFER_OBTAINED( pxReturn );\r
+    }\r
+\r
+    return pxReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer )\r
+{\r
+    BaseType_t xListItemAlreadyInFreeList;\r
+\r
+    /* Ensure the buffer is returned to the list of free buffers before the\r
+    * counting semaphore is 'given' to say a buffer is available.  Release the\r
+    * storage allocated to the buffer payload.  THIS FILE SHOULD NOT BE USED\r
+    * IF THE PROJECT INCLUDES A MEMORY ALLOCATOR THAT WILL FRAGMENT THE HEAP\r
+    * MEMORY.  For example, heap_2 must not be used, heap_4 can be used. */\r
+    vReleaseNetworkBuffer( pxNetworkBuffer->pucEthernetBuffer );\r
+    pxNetworkBuffer->pucEthernetBuffer = NULL;\r
+\r
+    taskENTER_CRITICAL();\r
+    {\r
+        xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );\r
+\r
+        if( xListItemAlreadyInFreeList == pdFALSE )\r
+        {\r
+            vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );\r
+        }\r
+    }\r
+    taskEXIT_CRITICAL();\r
+\r
+    /*\r
+     * Update the network state machine, unless the program fails to release its 'xNetworkBufferSemaphore'.\r
+     * The program should only try to release its semaphore if 'xListItemAlreadyInFreeList' is false.\r
+     */\r
+    if( xListItemAlreadyInFreeList == pdFALSE )\r
+    {\r
+        if ( xSemaphoreGive( xNetworkBufferSemaphore ) == pdTRUE )\r
+        {\r
+            iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );\r
+        }\r
+    }\r
+    else\r
+    {\r
+        iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );\r
+    }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Returns the number of free network buffers\r
+ */\r
+UBaseType_t uxGetNumberOfFreeNetworkBuffers( void )\r
+{\r
+    return listCURRENT_LIST_LENGTH( &xFreeBuffersList );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+UBaseType_t uxGetMinimumFreeNetworkBuffers( void )\r
+{\r
+    return uxMinimumFreeNetworkBuffers;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+NetworkBufferDescriptor_t * pxResizeNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * pxNetworkBuffer,\r
+                                                                 size_t xNewSizeBytes )\r
+{\r
+    size_t xOriginalLength;\r
+    uint8_t * pucBuffer;\r
+\r
+    #ifdef PIC32_USE_ETHERNET\r
+        xOriginalLength = pxNetworkBuffer->xDataLength;\r
+    #else\r
+        xOriginalLength = pxNetworkBuffer->xDataLength + ipBUFFER_PADDING;\r
+               xNewSizeBytes = xNewSizeBytes + ipBUFFER_PADDING;\r
+    #endif /* #ifdef PIC32_USE_ETHERNET */\r
+       \r
+    pucBuffer = pucGetNetworkBuffer( &( xNewSizeBytes ) );\r
+\r
+    if( pucBuffer == NULL )\r
+    {\r
+        /* In case the allocation fails, return NULL. */\r
+        pxNetworkBuffer = NULL;\r
+    }\r
+    else\r
+    {\r
+        pxNetworkBuffer->xDataLength = xNewSizeBytes;\r
+        if( xNewSizeBytes > xOriginalLength )\r
+        {\r
+            xNewSizeBytes = xOriginalLength;\r
+        }\r
+\r
+        #ifdef PIC32_USE_ETHERNET\r
+            memcpy( pucBuffer, pxNetworkBuffer->pucEthernetBuffer, xNewSizeBytes );\r
+            *( ( NetworkBufferDescriptor_t ** ) ( pucBuffer - ipBUFFER_PADDING ) ) = pxNetworkBuffer;\r
+        #else\r
+            memcpy( pucBuffer - ipBUFFER_PADDING, pxNetworkBuffer->pucEthernetBuffer - ipBUFFER_PADDING, xNewSizeBytes );\r
+        #endif /* #ifdef PIC32_USE_ETHERNET */\r
+\r
+        vReleaseNetworkBuffer( pxNetworkBuffer->pucEthernetBuffer );\r
+        pxNetworkBuffer->pucEthernetBuffer = pucBuffer;\r
+    }\r
+\r
+    return pxNetworkBuffer;\r
+}\r
index 5fe4438bd2709660bf3d6dbe772b9b4601e3b685..1b7584c44cb74813ccc21306360783ed9193ee6d 100644 (file)
-/*******************************************************************************
-*  Network Interface file
-*
-*  Summary:
-*   Network Interface file for FreeRTOS-Plus-TCP stack
-*
-*  Description:
-*   - Interfaces PIC32 to the FreeRTOS TCP/IP stack
-*******************************************************************************/
-
-/*******************************************************************************
-*  File Name:  pic32_NetworkInterface.c
-*  Copyright 2017 Microchip Technology Incorporated and its subsidiaries.
-*
-*  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
-*******************************************************************************/
-#include <sys/kmem.h>
-
-#include "FreeRTOS.h"
-#include "semphr.h"
-#include "event_groups.h"
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_IP_Private.h"
-
-#include "NetworkInterface.h"
-#include "NetworkBufferManagement.h"
-
-
-#include "NetworkInterface.h"
-#include "NetworkConfig.h"
-
-#include "peripheral/eth/plib_eth.h"
-
-#include "system_config.h"
-#include "system/console/sys_console.h"
-#include "system/debug/sys_debug.h"
-#include "system/command/sys_command.h"
-
-#include "driver/ethmac/drv_ethmac.h"
-#include "driver/miim/drv_miim.h"
-
-#include "tcpip/tcpip.h"
-#include "tcpip/src/tcpip_private.h"
-#include "tcpip/src/link_list.h"
-
-#ifdef PIC32_USE_ETHERNET
-
-    /* local definitions and data */
-
-    /* debug messages */
-    #if ( PIC32_MAC_DEBUG_MESSAGES != 0 )
-        #define PIC32_MAC_DbgPrint( format, ... )    SYS_CONSOLE_PRINT( format, ## __VA_ARGS__ )
-    #else
-        #define PIC32_MAC_DbgPrint( format, ... )
-    #endif /* (PIC32_MAC_DEBUG_MESSAGES != 0) */
-
-    typedef enum
-    {
-        PIC32_MAC_EVENT_INIT_NONE = 0x000,      /* no event/invalid */
-
-        PIC32_MAC_EVENT_INIT_DONE = 0x001,      /* initialization done event */
-        PIC32_MAC_EVENT_TIMEOUT = 0x002,        /* periodic timeout event */
-        PIC32_MAC_EVENT_IF_PENDING = 0x004,     /* an interface event signal: RX, TX, errors. etc. */
-    } PIC32_MAC_EVENT_TYPE;
-
-    typedef enum
-    {
-        eMACInit,                               /* Must initialise MAC. */
-        eMACPass,                               /* Initialisation was successful. */
-        eMACFailed,                             /* Initialisation failed. */
-    } eMAC_INIT_STATUS_TYPE;
-
-    static TCPIP_STACK_HEAP_HANDLE macHeapHandle;
-
-    static const TCPIP_MAC_OBJECT * macObject; /* the one and only MAC object; */
-
-    static SYS_MODULE_OBJ macObjHandle;        /* the MAC object instance, obtained at initialization */
-    static TCPIP_MAC_HANDLE macCliHandle;      /* client handle */
-    static volatile SYS_STATUS macObjStatus;   /* current MAC status */
-
-    static TaskHandle_t macTaskHandle;
-
-    static TimerHandle_t macTmrHandle;
-
-    static bool macLinkStatus;              /* true if link is ON */
-
-    static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit;
-
-    /* local prototypes */
-    static bool StartInitMac( void );
-    static void StartInitCleanup( void );
-
-    static void SetMacCtrl( TCPIP_MAC_MODULE_CTRL * pMacCtrl );
-
-    static bool MacSyncFunction( void * synchHandle,
-                                 TCPIP_MAC_SYNCH_REQUEST req );
-
-    /* the PIC32 MAC task function */
-    static void MacHandlerTask( void * params );
-
-    /* MAC interrupt event function */
-    static void MAC_EventFunction( TCPIP_MAC_EVENT event,
-                                   const void * eventParam );
-
-    /* timer callback for link maintenance, etc; */
-    static void MacTmrCallback( TimerHandle_t xTimer );
-
-    /* MAC RX packets functions */
-    static void MacRxPackets( void );
-    static void MacProcessRxPacket( TCPIP_MAC_PACKET * pRxPkt );
-
-
-    /* memory allocation mapping to FreeRTOS */
-    static void * _malloc( size_t nBytes )
-    {
-        return pvPortMalloc( nBytes );
-    }
-
-    /*-----------------------------------------------------------*/
-
-    static void * _calloc( size_t nElems,
-                           size_t elemSize )
-    {
-        size_t nBytes = nElems * elemSize;
-
-        void * ptr = pvPortMalloc( nBytes );
-
-        if( ptr != 0 )
-        {
-            memset( ptr, 0, nBytes );
-        }
-
-        return ptr;
-    }
-
-    /*-----------------------------------------------------------*/
-
-    static void _free( void * pBuff )
-    {
-        vPortFree( pBuff );
-    }
-
-    /* extern references */
-    /* */
-    /* use the configuration data from the system_init.c */
-    extern const TCPIP_NETWORK_CONFIG TCPIP_HOSTS_CONFIGURATION[];
-
-    /* BufferAllocation_2.c:: packet allocation function */
-    extern TCPIP_MAC_PACKET * PIC32_MacPacketAllocate( uint16_t pktLen,
-                                                       uint16_t segLoadLen,
-                                                       TCPIP_MAC_PACKET_FLAGS flags );
-
-    extern void PIC32_MacAssociate( TCPIP_MAC_PACKET * pRxPkt,
-                                    NetworkBufferDescriptor_t * pxBufferDescriptor,
-                                    size_t pktLength );
-    extern void PIC32_MacPacketOrphan( TCPIP_MAC_PACKET * pPkt );
-
-    /* cannot use the system_init.c::tcpipHeapConfig because FreeRTOS does not have a calloc function! */
-    /* we build it here! */
-
-    /* make sure we're running with external heap! Redirect to FreeRTOS. */
-    #if !defined( TCPIP_STACK_USE_EXTERNAL_HEAP ) || defined( TCPIP_STACK_USE_INTERNAL_HEAP ) || defined( TCPIP_STACK_USE_INTERNAL_HEAP_POOL )
-        #error "TCPIP_STACK_USE_EXTERNAL_HEAP should be defined for this project!"
-    #endif
-
-    static const TCPIP_STACK_HEAP_EXTERNAL_CONFIG tcpipHeapConfig =
-    {
-        .heapType   = TCPIP_STACK_HEAP_TYPE_EXTERNAL_HEAP,
-        .heapFlags  = TCPIP_STACK_HEAP_FLAG_ALLOC_UNCACHED | TCPIP_STACK_HEAP_FLAG_NO_MTHREAD_SYNC,
-        .heapUsage  = TCPIP_STACK_HEAP_USE_DEFAULT,
-        .malloc_fnc = _malloc,
-        .calloc_fnc = _calloc,
-        .free_fnc   = _free,
-    };
-
-    #if ( PIC32_MAC_DEBUG_COMMANDS != 0 )
-        static int _Command_MacInfo( SYS_CMD_DEVICE_NODE * pCmdIO,
-                                     int argc,
-                                     char ** argv );
-        static int _Command_NetInfo( SYS_CMD_DEVICE_NODE * pCmdIO,
-                                     int argc,
-                                     char ** argv );
-        static int _Command_Version( SYS_CMD_DEVICE_NODE * pCmdIO,
-                                     int argc,
-                                     char ** argv );
-
-        static const SYS_CMD_DESCRIPTOR macCmdTbl[] =
-        {
-            { "macinfo", _Command_MacInfo, ": Check MAC statistics" },
-            { "netinfo", _Command_NetInfo, ": Net info" },
-            { "version", _Command_Version, ": Version info" },
-        };
-    #endif /* (PIC32_MAC_DEBUG_COMMANDS != 0) */
-
-
-    /* FreeRTOS implementation functions */
-    BaseType_t xNetworkInterfaceInitialise( void )
-    {
-    BaseType_t xResult;
-
-        if( xMacInitStatus == eMACInit )
-        {
-                       /* This is the first time this function is called. */
-            if( StartInitMac() != false )
-            {
-                /* Indicate that the MAC initialisation succeeded. */
-                xMacInitStatus = eMACPass;
-            }
-            else
-            {
-                xMacInitStatus = eMACFailed;
-            }
-        }
-
-        if( xMacInitStatus == eMACPass )
-        {
-            xResult = xGetPhyLinkStatus();
-        }
-        else
-        {
-            xResult = pdFAIL;
-        }
-
-       PIC32_MAC_DbgPrint( "xNetworkInterfaceInitialise: %d %d\r\n", ( int ) xMacInitStatus, ( int ) xResult );
-
-        return xResult;
-    }
-
-
-    /*-----------------------------------------------------------*/
-
-    BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,
-                                        BaseType_t xReleaseAfterSend )
-    {
-        TCPIP_MAC_RES macRes;
-        TCPIP_MAC_PACKET * pTxPkt;
-
-        BaseType_t retRes = pdFALSE;
-
-
-        if( ( pxDescriptor != 0 ) && ( pxDescriptor->pucEthernetBuffer != 0 ) && ( pxDescriptor->xDataLength != 0 ) )
-        {
-            TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pxDescriptor->pucEthernetBuffer - PIC32_BUFFER_PKT_PTR_OSSET );
-            configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 );
-            pTxPkt = *ppkt;
-            configASSERT( pTxPkt != 0 );
-
-            /* prepare the packet for transmission */
-            /* set the correct data length: */
-            configASSERT( pTxPkt->pDSeg->segSize >= pTxPkt->pDSeg->segLen );
-            pTxPkt->pDSeg->segLen = pxDescriptor->xDataLength;
-            pTxPkt->next = 0; /* unlink it */
-            macRes = ( macObject->TCPIP_MAC_PacketTx )( macCliHandle, pTxPkt );
-
-            if( macRes >= 0 )
-            {
-                retRes = pdTRUE;
-                pxDescriptor->pucEthernetBuffer = 0; /* it will be released by the MAC driver once it's transmitted */
-                iptraceNETWORK_INTERFACE_TRANSMIT();
-            }
-
-            /* else same error occurred; this normally should not happen! But the buffer is left in there so it shold be freed! */
-
-            /* The buffer has been sent so can be released. */
-            if( xReleaseAfterSend != pdFALSE )
-            {
-                vReleaseNetworkBufferAndDescriptor( pxDescriptor );
-            }
-        }
-
-        return retRes;
-    }
-
-
-    /************************************* Section: helper functions ************************************************** */
-    /* */
-
-    void PIC32_GetMACAddress( uint8_t macAdd[ 6 ] )
-    {
-        #if defined( __PIC32MZ__ ) || defined( __PIC32MX__ )
-            PLIB_ETH_MACGetAddress( ETH_ID_0, macAdd );
-        #else
-        #error "MAC Address: not supported architecture!"
-        #endif
-    }
-
-
-    /*-----------------------------------------------------------*/
-
-    const void * const PIC32_GetMacConfigData( void )
-    {
-        #if defined( __PIC32MZ__ ) || defined( __PIC32MX__ )
-            extern const TCPIP_MODULE_MAC_PIC32INT_CONFIG tcpipMACPIC32INTInitData;
-
-            return &tcpipMACPIC32INTInitData;
-        #else
-        #error "MAC Address: not supported architecture!"
-        #endif
-    }
-
-    /************************************* Section: worker code ************************************************** */
-    /* */
-
-
-    static bool StartInitMac( void )
-    {
-        TCPIP_MAC_MODULE_CTRL macCtrl;
-        SYS_MODULE_INIT moduleInit;
-        EventBits_t evBits;
-
-
-        /* perform some initialization of all variables so that we can cleanup what failed */
-        /* if something failed, the routine will be called again and again by FreeRTOS! */
-        macHeapHandle = 0;
-        macObjHandle = 0;
-        macCliHandle = 0;
-        macTmrHandle = 0;
-        macTaskHandle = 0;
-        macObject = TCPIP_HOSTS_CONFIGURATION[ 0 ].pMacObject; /* the MAC object we use */
-        macObjStatus = SYS_STATUS_UNINITIALIZED;
-        macLinkStatus = false;
-
-        int netUpFail = 0;
-
-        while( true )
-        {
-            /* start the allocator */
-            macHeapHandle = TCPIP_HEAP_Create( ( const TCPIP_STACK_HEAP_CONFIG * ) &tcpipHeapConfig, 0 );
-
-            if( macHeapHandle == 0 )
-            {
-                netUpFail = 1;
-                break;
-            }
-
-            if( TCPIP_PKT_Initialize( macHeapHandle, 0, 0 ) == false )
-            {
-                netUpFail = 2;
-                break;
-            }
-
-            moduleInit.sys.powerState = SYS_MODULE_POWER_RUN_FULL;
-
-            /* Initialize the MAC. MAC address is defined to 0x000000000000 in
-             * FreeRTOSConfig.h and therefore it will be initialized to the
-             * factory programmed MAC address. */
-            SetMacCtrl( &macCtrl );
-            /* Set the mac address in the FreeRTOS+TCP stack. */
-            FreeRTOS_UpdateMACAddress( macCtrl.ifPhyAddress.v );
-
-            TCPIP_MAC_INIT macInit =
-            {
-                .moduleInit = { moduleInit.value },
-                .macControl = &macCtrl,
-                .moduleData = PIC32_GetMacConfigData(),
-            };
-
-            macObjHandle = ( macObject->TCPIP_MAC_Initialize )( TCPIP_MODULE_MAC_PIC32INT, &macInit.moduleInit );
-
-            if( macObjHandle == SYS_MODULE_OBJ_INVALID )
-            {
-                macObjHandle = 0;
-                netUpFail = 4;
-                break;
-            }
-
-            /* open the MAC */
-            macCliHandle = ( macObject->TCPIP_MAC_Open )( TCPIP_MODULE_MAC_PIC32INT, DRV_IO_INTENT_READWRITE );
-
-            if( macCliHandle == DRV_HANDLE_INVALID )
-            {
-                macCliHandle = 0;
-                netUpFail = 5;
-                break;
-            }
-
-            if( !( macObject->TCPIP_MAC_EventMaskSet )( macCliHandle, ( TCPIP_MAC_EV_RX_DONE | TCPIP_MAC_EV_TX_DONE | TCPIP_MAC_EV_RXTX_ERRORS ), true ) )
-            {
-                netUpFail = 6;
-                break;
-            }
-
-            /* completed the MAC initialization */
-            /* continue the initialization */
-            macTmrHandle = xTimerCreate( PIC32_MAC_TIMER_NAME, PIC32_MAC_TIMER_PERIOD, pdTRUE, 0, MacTmrCallback );
-
-            if( ( macTmrHandle == 0 ) || ( xTimerStart( macTmrHandle, 0 ) != pdPASS ) )
-            {
-                netUpFail = 8;
-                break;
-            }
-
-            /* spawn the PIC32 MAC task function */
-            /* and wait for its event signal */
-            macObjStatus = SYS_STATUS_BUSY;
-
-            if( xTaskCreate( MacHandlerTask, PIC32_MAC_TASK_NAME, PIC32_MAC_TASK_STACK_SIZE, xTaskGetCurrentTaskHandle(), PIC32_MAC_TASK_PRI, &macTaskHandle ) != pdPASS )
-            { /* failed */
-                netUpFail = 9;
-                break;
-            }
-
-            xTaskNotifyWait( PIC32_MAC_EVENT_INIT_DONE, PIC32_MAC_EVENT_INIT_DONE, &evBits, PIC32_MAC_INIT_TIMEOUT );
-
-            if( ( evBits & PIC32_MAC_EVENT_INIT_DONE ) == 0 )
-            { /* timed out */
-                netUpFail = 10;
-                break;
-            }
-
-            if( macObjStatus != SYS_STATUS_READY )
-            { /* failed somehow ??? */
-                netUpFail = 11;
-                break;
-            }
-
-            netUpFail = 0;
-            break;
-        }
-
-        if( netUpFail == 0 )
-        {
-            PIC32_MAC_DbgPrint( " MAC Init success!\r\n" );
-
-            #if ( PIC32_MAC_DEBUG_COMMANDS != 0 )
-                /* create command group */
-                if( !SYS_CMD_ADDGRP( macCmdTbl, sizeof( macCmdTbl ) / sizeof( *macCmdTbl ), "mac", ": mac commands" ) )
-                {
-                    PIC32_MAC_DbgPrint( "Failed to create MAC Commands\r\n" );
-                }
-            #endif /* (PIC32_MAC_DEBUG_COMMANDS != 0) */
-
-            return true;
-        }
-        else
-        {
-            StartInitCleanup();
-            PIC32_MAC_DbgPrint( "MAC Init failed: %d!\r\n", netUpFail );
-
-            return false;
-        }
-    }
-
-    /*-----------------------------------------------------------*/
-
-    static void StartInitCleanup( void )
-    {
-        if( macHeapHandle != 0 )
-        {
-            TCPIP_HEAP_Delete( macHeapHandle );
-            macHeapHandle = 0;
-        }
-
-        if( macObjHandle != 0 )
-        {
-            ( macObject->TCPIP_MAC_Deinitialize )( macObjHandle );
-            macObjHandle = 0;
-        }
-
-        if( macTmrHandle != 0 )
-        {
-            xTimerDelete( macTmrHandle, portMAX_DELAY );
-            macTmrHandle = 0;
-        }
-
-        if( macTaskHandle != 0 )
-        {
-            vTaskDelete( macTaskHandle );
-            macTaskHandle = 0;
-        }
-    }
-
-    /*-----------------------------------------------------------*/
-
-    static void SetMacCtrl( TCPIP_MAC_MODULE_CTRL * pMacCtrl )
-    {
-        TCPIP_MAC_ADDR macAdd;
-        uint8_t unsetMACAddr[ 6 ] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };     /* not set MAC address */
-
-        pMacCtrl->nIfs = 1;
-
-        pMacCtrl->mallocF = TCPIP_HEAP_MallocOutline;
-        pMacCtrl->callocF = TCPIP_HEAP_CallocOutline;
-        pMacCtrl->freeF = TCPIP_HEAP_FreeOutline;
-        pMacCtrl->memH = macHeapHandle;
-
-
-        pMacCtrl->pktAllocF = PIC32_MacPacketAllocate;
-        pMacCtrl->pktFreeF = ( TCPIP_MAC_PKT_FreeF ) _TCPIP_PKT_FREE_FNC;
-        pMacCtrl->pktAckF = ( TCPIP_MAC_PKT_AckF ) _TCPIP_PKT_ACK_FNC;
-
-        pMacCtrl->synchF = MacSyncFunction;
-
-        pMacCtrl->eventF = MAC_EventFunction;
-        pMacCtrl->eventParam = 0;
-
-        pMacCtrl->moduleId = TCPIP_MODULE_MAC_PIC32INT;
-        pMacCtrl->netIx = 0;
-        pMacCtrl->macAction = TCPIP_MAC_ACTION_INIT;
-        pMacCtrl->powerMode = TCPIP_MAC_POWER_FULL;
-
-        macAdd.v[ 0 ] = configMAC_ADDR0;
-        macAdd.v[ 1 ] = configMAC_ADDR1;
-        macAdd.v[ 2 ] = configMAC_ADDR2;
-        macAdd.v[ 3 ] = configMAC_ADDR3;
-        macAdd.v[ 4 ] = configMAC_ADDR4;
-        macAdd.v[ 5 ] = configMAC_ADDR5;
-
-        if( memcmp( macAdd.v, unsetMACAddr, sizeof( unsetMACAddr ) ) == 0 )
-        { /* if unspecified we use the factory pre-programmed address */
-            PIC32_GetMACAddress( pMacCtrl->ifPhyAddress.v );
-        }
-        else
-        { /* use the config suggested one */
-            memcpy( pMacCtrl->ifPhyAddress.v, macAdd.v, sizeof( macAdd ) );
-        }
-    }
-
-    /*-----------------------------------------------------------*/
-
-    static bool MacSyncFunction( void * synchHandle,
-                                 TCPIP_MAC_SYNCH_REQUEST req )
-    {
-        switch( req )
-        {
-            case TCPIP_MAC_SYNCH_REQUEST_OBJ_CREATE:
-                vSemaphoreCreateBinary( *( SemaphoreHandle_t * ) synchHandle );
-
-                return ( *( SemaphoreHandle_t * ) synchHandle == NULL ) ? false : true;
-
-            case TCPIP_MAC_SYNCH_REQUEST_OBJ_DELETE:
-                vSemaphoreDelete( *( SemaphoreHandle_t * ) synchHandle );
-                *( SemaphoreHandle_t * ) synchHandle = NULL;
-
-                return true;
-
-            case TCPIP_MAC_SYNCH_REQUEST_OBJ_LOCK:
-
-                return ( xSemaphoreTake( *( SemaphoreHandle_t * ) synchHandle, portMAX_DELAY ) == pdTRUE ) ? true : false;
-
-            case TCPIP_MAC_SYNCH_REQUEST_OBJ_UNLOCK:
-
-                return ( xSemaphoreGive( *( SemaphoreHandle_t * ) synchHandle ) == pdTRUE ) ? true : false;
-
-            case TCPIP_MAC_SYNCH_REQUEST_CRIT_ENTER:
-                vTaskSuspendAll();
-
-                return true;
-
-            case TCPIP_MAC_SYNCH_REQUEST_CRIT_LEAVE:
-                xTaskResumeAll();
-
-                return true;
-
-            default:
-
-                return false;
-        }
-    }
-
-
-    /*-----------------------------------------------------------*/
-
-    static void MacHandlerTask( void * params )
-    {
-        EventBits_t evBits;
-
-        /* perform the MAC initialization */
-        while( macObjStatus == SYS_STATUS_BUSY )
-        {
-            /* process the underlying MAC module tasks */
-            ( macObject->TCPIP_MAC_Tasks )( macObjHandle );
-
-            SYS_STATUS macStatus = ( macObject->TCPIP_MAC_Status )( macObjHandle );
-
-            if( macStatus == SYS_STATUS_BUSY )
-            { /* still pending */
-                vTaskDelay( PIC32_MAC_TASK_INIT_PENDING_DELAY );
-            }
-            else
-            { /* completed ...somehow */
-                macObjStatus = macStatus;
-
-                xTaskNotify( ( TaskHandle_t ) params, PIC32_MAC_EVENT_INIT_DONE, eSetBits );
-
-                if( macStatus != SYS_STATUS_READY )
-                { /* failed miserably */
-                    vTaskDelete( 0 );
-                }
-
-                /* done, up and running */
-            }
-        }
-
-        while( true )
-        {
-            xTaskNotifyWait( PIC32_MAC_EVENT_TIMEOUT | PIC32_MAC_EVENT_IF_PENDING, PIC32_MAC_EVENT_TIMEOUT | PIC32_MAC_EVENT_IF_PENDING, &evBits, portMAX_DELAY );
-
-            if( ( evBits & PIC32_MAC_EVENT_TIMEOUT ) != 0 )
-            {                                                                       /* timeout occurred... */
-                ( macObject->TCPIP_MAC_Tasks )( macObjHandle );
-                bool linkCurr = ( macObject->TCPIP_MAC_LinkCheck )( macCliHandle ); /* check link status */
-
-                if( macLinkStatus != linkCurr )
-                { /* link status changed; some event could ve fired here if needed */
-                    PIC32_MAC_DbgPrint( " MAC link: %s!\r\n", linkCurr ? "ON" : "OFF" );
-                    macLinkStatus = linkCurr;
-                }
-            }
-
-            if( ( evBits & PIC32_MAC_EVENT_IF_PENDING ) != 0 )
-            { /* IF events signal */
-                TCPIP_MAC_EVENT activeEvents = ( macObject->TCPIP_MAC_EventPendingGet )( macCliHandle );
-
-                if( activeEvents != TCPIP_MAC_EV_NONE )
-                {
-                    /* acknowledge the events */
-                    ( macObject->TCPIP_MAC_EventAcknowledge )( macCliHandle, activeEvents );
-
-                    /* check for RX */
-                    if( ( activeEvents & ( TCPIP_MAC_EV_RX_DONE | TCPIP_MAC_EV_RX_OVFLOW | TCPIP_MAC_EV_RX_BUFNA ) ) != 0 )
-                    { /* RX packets available */
-                        MacRxPackets();
-                    }
-
-                    /* call the driver process function; */
-                    /* PIC32 driver requests it through TCPIP_MAC_ParametersGet() which is bypassed here! */
-                    ( macObject->TCPIP_MAC_Process )( macCliHandle );
-                }
-            }
-
-            /* do what you have to do and then wait for another event... */
-        }
-    }
-
-    /*-----------------------------------------------------------*/
-
-    static void MacTmrCallback( TimerHandle_t xTimer )
-    {
-        xTaskNotify( macTaskHandle, PIC32_MAC_EVENT_TIMEOUT, eSetBits );
-    }
-
-    /* MAC interrupt event function */
-    /* MAC signals an event, probably from within ISR */
-    /* we care just for RX related events */
-    static void MAC_EventFunction( TCPIP_MAC_EVENT event,
-                                   const void * eventParam )
-    {
-        BaseType_t xHigherPriorityTaskWoken;
-
-        if( ( event & ( TCPIP_MAC_EV_RX_DONE | TCPIP_MAC_EV_TX_DONE | TCPIP_MAC_EV_RXTX_ERRORS ) ) != 0 )
-        {
-            xHigherPriorityTaskWoken = pdFALSE;
-            xTaskNotifyFromISR( macTaskHandle, PIC32_MAC_EVENT_IF_PENDING, eSetBits, &xHigherPriorityTaskWoken );
-
-            if( xHigherPriorityTaskWoken )
-            {
-                portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
-            }
-        }
-    }
-
-    /*-----------------------------------------------------------*/
-
-    BaseType_t xGetPhyLinkStatus( void )
-    {
-        return macLinkStatus == true ? pdPASS : pdFAIL;
-    }
-
-
-    /* receive packets from the MAC driver */
-    static void MacRxPackets( void )
-    {
-        TCPIP_MAC_PACKET * pRxPkt;
-
-        /* get all the new MAC packets */
-        while( ( pRxPkt = ( macObject->TCPIP_MAC_PacketRx )( macCliHandle, 0, 0 ) ) != 0 )
-        {
-            MacProcessRxPacket( pRxPkt );
-        }
-    }
-
-    /*-----------------------------------------------------------*/
-
-    static void MacProcessRxPacket( TCPIP_MAC_PACKET * pRxPkt )
-    {
-        bool pktSuccess, pktLost;
-        size_t pktLength;
-        TCPIP_MAC_DATA_SEGMENT * pSeg;
-        uint8_t * pPktBuff;
-        NetworkBufferDescriptor_t * pxBufferDescriptor;
-        IPStackEvent_t xRxEvent;
-
-        pxBufferDescriptor = 0;
-        pktSuccess = pktLost = false;
-
-        while( true )
-        {
-            pktLength = 0;
-            int nSegs = 0;
-            pSeg = pRxPkt->pDSeg;
-            pPktBuff = pSeg->segLoad;
-
-            /* calculate the packet size */
-            do
-            {
-                pktLength += pSeg->segLen;
-                pSeg = pSeg->next;
-                nSegs++;
-            } while( pSeg != 0 );
-
-            if( nSegs > 1 )
-            { /* no support in FreeRTOS for multi segment packets! */
-                break;
-            }
-
-            /* sizeof(TCPIP_MAC_ETHERNET_HEADER) is subtracted by the driver */
-            /* but FreeRTOS needs the whole frame! */
-            pktLength += sizeof( TCPIP_MAC_ETHERNET_HEADER );
-
-            if( eConsiderFrameForProcessing( pPktBuff ) != eProcessBuffer )
-            {
-                break;
-            }
-
-            /* get the network descriptor (no data buffer) to hold this packet */
-            pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( 0, 0 );
-
-            if( pxBufferDescriptor == 0 )
-            {
-                pktLost = true;
-                break;
-            }
-
-            PIC32_MacAssociate( pRxPkt, pxBufferDescriptor, pktLength );
-
-            xRxEvent.eEventType = eNetworkRxEvent;
-            xRxEvent.pvData = ( void * ) pxBufferDescriptor;
-
-            /* Send the data to the TCP/IP stack */
-            if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )
-            { /* failed */
-                pktLost = true;
-            }
-            else
-            { /* success */
-                pktSuccess = true;
-                iptraceNETWORK_INTERFACE_RECEIVE();
-            }
-
-            break;
-        }
-
-        if( !pktSuccess )
-        { /* smth went wrong; nothing sent to the */
-            if( pxBufferDescriptor != 0 )
-            {
-                pxBufferDescriptor->pucEthernetBuffer = 0;
-                vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );
-            }
-
-            if( pktLost )
-            {
-                iptraceETHERNET_RX_EVENT_LOST();
-            }
-
-            /* acknowledge the packet to the MAC driver */
-            if( pRxPkt->ackFunc )
-            {
-                ( *pRxPkt->ackFunc )( pRxPkt, pRxPkt->ackParam );
-            }
-            else
-            {
-                PIC32_MacPacketOrphan( pRxPkt );
-            }
-        }
-    }
-
-    #if ( PIC32_MAC_DEBUG_COMMANDS != 0 )
-        /* */
-        static int _Command_MacInfo( SYS_CMD_DEVICE_NODE * pCmdIO,
-                                     int argc,
-                                     char ** argv )
-        {
-            TCPIP_MAC_RES macRes;
-            TCPIP_MAC_RX_STATISTICS rxStatistics;
-            TCPIP_MAC_TX_STATISTICS txStatistics;
-            TCPIP_MAC_STATISTICS_REG_ENTRY regEntries[ 8 ];
-            TCPIP_MAC_STATISTICS_REG_ENTRY * pRegEntry;
-            int jx, hwEntries;
-            char entryName[ sizeof( pRegEntry->registerName ) + 1 ];
-
-            const void * cmdIoParam = pCmdIO->cmdIoParam;
-
-            if( argc != 1 )
-            {
-                ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "Usage: macinfo \r\n" );
-                ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "Ex: macinfo \r\n" );
-
-                return false;
-            }
-
-            ( *pCmdIO->pCmdApi->print )( cmdIoParam, "Interface: %s driver statistics\r\n", macObject->macName );
-            macRes = ( macObject->TCPIP_MAC_StatisticsGet )( macCliHandle, &rxStatistics, &txStatistics );
-
-            if( macRes == TCPIP_MAC_RES_OK )
-            {
-                ( *pCmdIO->pCmdApi->print )( cmdIoParam, "\tnRxOkPackets: %d, nRxPendBuffers: %d, nRxSchedBuffers: %d, ",
-                                             rxStatistics.nRxOkPackets, rxStatistics.nRxPendBuffers, rxStatistics.nRxSchedBuffers );
-                ( *pCmdIO->pCmdApi->print )( cmdIoParam, "nRxErrorPackets: %d, nRxFragmentErrors: %d\r\n", rxStatistics.nRxErrorPackets, rxStatistics.nRxFragmentErrors );
-                ( *pCmdIO->pCmdApi->print )( cmdIoParam, "\tnTxOkPackets: %d, nTxPendBuffers: %d, nTxErrorPackets: %d, nTxQueueFull: %d\r\n",
-                                             txStatistics.nTxOkPackets, txStatistics.nTxPendBuffers, txStatistics.nTxErrorPackets, txStatistics.nTxQueueFull );
-            }
-            else
-            {
-                ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "\tnot supported\r\n" );
-            }
-
-            ( *pCmdIO->pCmdApi->print )( cmdIoParam, "Interface: %s hardware statistics\r\n", macObject->macName );
-            macRes = ( macObject->TCPIP_MAC_RegisterStatisticsGet )( macCliHandle, regEntries, sizeof( regEntries ) / sizeof( *regEntries ), &hwEntries );
-
-            if( macRes == TCPIP_MAC_RES_OK )
-            {
-                entryName[ sizeof( entryName ) - 1 ] = 0;
-
-                for( jx = 0, pRegEntry = regEntries; jx < hwEntries && jx < sizeof( regEntries ) / sizeof( *regEntries ); jx++, pRegEntry++ )
-                {
-                    strncpy( entryName, pRegEntry->registerName, sizeof( entryName ) - 1 );
-                    ( *pCmdIO->pCmdApi->print )( cmdIoParam, "\t%s: 0x%8x\r\n", entryName, pRegEntry->registerValue );
-                }
-            }
-            else
-            {
-                ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "\tnot supported\r\n" );
-            }
-
-            return true;
-        }
-
-        /*-----------------------------------------------------------*/
-
-        static int _Command_NetInfo( SYS_CMD_DEVICE_NODE * pCmdIO,
-                                     int argc,
-                                     char ** argv )
-        {
-            const void * cmdIoParam = pCmdIO->cmdIoParam;
-
-            union
-            {
-                uint32_t ul;
-                uint8_t b[ 4 ];
-            }
-            sUl;
-
-            sUl.ul = FreeRTOS_GetIPAddress();
-
-            bool linkUp = FreeRTOS_IsNetworkUp() == pdTRUE;
-
-            ( *pCmdIO->pCmdApi->print )( cmdIoParam, "IP address: %d.%d.%d.%d\r\n", sUl.b[ 0 ], sUl.b[ 1 ], sUl.b[ 2 ], sUl.b[ 3 ] );
-            ( *pCmdIO->pCmdApi->print )( cmdIoParam, "Link is: %s\r\n", linkUp ? "Up" : "Down" );
-
-            return true;
-        }
-
-#include "aws_application_version.h"
-
-static int _Command_Version(SYS_CMD_DEVICE_NODE* pCmdIO, int argc, char** argv)
-{
-    configPRINTF( ( "App version - maj: %d, min: %d, build: %d\r\n",  xAppFirmwareVersion.u.x.ucMajor, xAppFirmwareVersion.u.x.ucMinor, xAppFirmwareVersion.u.x.usBuild) );
-    return 0;
-}
-
-    #endif /* (PIC32_MAC_DEBUG_COMMANDS != 0) */
-#endif /* #ifdef PIC32_USE_ETHERNET */
+/*******************************************************************************\r
+*  Network Interface file\r
+*\r
+*  Summary:\r
+*   Network Interface file for FreeRTOS-Plus-TCP stack\r
+*\r
+*  Description:\r
+*   - Interfaces PIC32 to the FreeRTOS TCP/IP stack\r
+*******************************************************************************/\r
+\r
+/*******************************************************************************\r
+*  File Name:  pic32_NetworkInterface.c\r
+*  Copyright 2017 Microchip Technology Incorporated and its subsidiaries.\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\r
+*  of the Software, and to permit persons to whom the Software is furnished to do\r
+*  so, subject to the following conditions:\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,\r
+*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+*  SOFTWARE\r
+*******************************************************************************/\r
+#include <sys/kmem.h>\r
+\r
+#include "FreeRTOS.h"\r
+#include "semphr.h"\r
+#include "event_groups.h"\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+\r
+#include "NetworkInterface.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+\r
+#include "NetworkInterface.h"\r
+#include "NetworkConfig.h"\r
+\r
+#include "peripheral/eth/plib_eth.h"\r
+\r
+#include "system_config.h"\r
+#include "system/console/sys_console.h"\r
+#include "system/debug/sys_debug.h"\r
+#include "system/command/sys_command.h"\r
+\r
+#include "driver/ethmac/drv_ethmac.h"\r
+#include "driver/miim/drv_miim.h"\r
+\r
+#include "tcpip/tcpip.h"\r
+#include "tcpip/src/tcpip_private.h"\r
+#include "tcpip/src/link_list.h"\r
+\r
+#ifdef PIC32_USE_ETHERNET\r
+\r
+    /* local definitions and data */\r
+\r
+    /* debug messages */\r
+    #if ( PIC32_MAC_DEBUG_MESSAGES != 0 )\r
+        #define PIC32_MAC_DbgPrint( format, ... )    SYS_CONSOLE_PRINT( format, ## __VA_ARGS__ )\r
+    #else\r
+        #define PIC32_MAC_DbgPrint( format, ... )\r
+    #endif /* (PIC32_MAC_DEBUG_MESSAGES != 0) */\r
+\r
+    typedef enum\r
+    {\r
+        PIC32_MAC_EVENT_INIT_NONE = 0x000,      /* no event/invalid */\r
+\r
+        PIC32_MAC_EVENT_INIT_DONE = 0x001,      /* initialization done event */\r
+        PIC32_MAC_EVENT_TIMEOUT = 0x002,        /* periodic timeout event */\r
+        PIC32_MAC_EVENT_IF_PENDING = 0x004,     /* an interface event signal: RX, TX, errors. etc. */\r
+    } PIC32_MAC_EVENT_TYPE;\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 TCPIP_STACK_HEAP_HANDLE macHeapHandle;\r
+\r
+    static const TCPIP_MAC_OBJECT * macObject; /* the one and only MAC object; */\r
+\r
+    static SYS_MODULE_OBJ macObjHandle;        /* the MAC object instance, obtained at initialization */\r
+    static TCPIP_MAC_HANDLE macCliHandle;      /* client handle */\r
+    static volatile SYS_STATUS macObjStatus;   /* current MAC status */\r
+\r
+    static TaskHandle_t macTaskHandle;\r
+\r
+    static TimerHandle_t macTmrHandle;\r
+\r
+    static bool macLinkStatus;              /* true if link is ON */\r
+\r
+    static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit;\r
+\r
+    /* local prototypes */\r
+    static bool StartInitMac( void );\r
+    static void StartInitCleanup( void );\r
+\r
+    static void SetMacCtrl( TCPIP_MAC_MODULE_CTRL * pMacCtrl );\r
+\r
+    static bool MacSyncFunction( void * synchHandle,\r
+                                 TCPIP_MAC_SYNCH_REQUEST req );\r
+\r
+    /* the PIC32 MAC task function */\r
+    static void MacHandlerTask( void * params );\r
+\r
+    /* MAC interrupt event function */\r
+    static void MAC_EventFunction( TCPIP_MAC_EVENT event,\r
+                                   const void * eventParam );\r
+\r
+    /* timer callback for link maintenance, etc; */\r
+    static void MacTmrCallback( TimerHandle_t xTimer );\r
+\r
+    /* MAC RX packets functions */\r
+    static void MacRxPackets( void );\r
+    static void MacProcessRxPacket( TCPIP_MAC_PACKET * pRxPkt );\r
+\r
+\r
+    /* memory allocation mapping to FreeRTOS */\r
+    static void * _malloc( size_t nBytes )\r
+    {\r
+        return pvPortMalloc( nBytes );\r
+    }\r
+\r
+    /*-----------------------------------------------------------*/\r
+\r
+    static void * _calloc( size_t nElems,\r
+                           size_t elemSize )\r
+    {\r
+        size_t nBytes = nElems * elemSize;\r
+\r
+        void * ptr = pvPortMalloc( nBytes );\r
+\r
+        if( ptr != 0 )\r
+        {\r
+            memset( ptr, 0, nBytes );\r
+        }\r
+\r
+        return ptr;\r
+    }\r
+\r
+    /*-----------------------------------------------------------*/\r
+\r
+    static void _free( void * pBuff )\r
+    {\r
+        vPortFree( pBuff );\r
+    }\r
+\r
+    /* extern references */\r
+    /* */\r
+    /* use the configuration data from the system_init.c */\r
+    extern const TCPIP_NETWORK_CONFIG TCPIP_HOSTS_CONFIGURATION[];\r
+\r
+    /* BufferAllocation_2.c:: packet allocation function */\r
+    extern TCPIP_MAC_PACKET * PIC32_MacPacketAllocate( uint16_t pktLen,\r
+                                                       uint16_t segLoadLen,\r
+                                                       TCPIP_MAC_PACKET_FLAGS flags );\r
+\r
+    extern void PIC32_MacAssociate( TCPIP_MAC_PACKET * pRxPkt,\r
+                                    NetworkBufferDescriptor_t * pxBufferDescriptor,\r
+                                    size_t pktLength );\r
+    extern void PIC32_MacPacketOrphan( TCPIP_MAC_PACKET * pPkt );\r
+\r
+    /* cannot use the system_init.c::tcpipHeapConfig because FreeRTOS does not have a calloc function! */\r
+    /* we build it here! */\r
+\r
+    /* make sure we're running with external heap! Redirect to FreeRTOS. */\r
+    #if !defined( TCPIP_STACK_USE_EXTERNAL_HEAP ) || defined( TCPIP_STACK_USE_INTERNAL_HEAP ) || defined( TCPIP_STACK_USE_INTERNAL_HEAP_POOL )\r
+        #error "TCPIP_STACK_USE_EXTERNAL_HEAP should be defined for this project!"\r
+    #endif\r
+\r
+    static const TCPIP_STACK_HEAP_EXTERNAL_CONFIG tcpipHeapConfig =\r
+    {\r
+        .heapType   = TCPIP_STACK_HEAP_TYPE_EXTERNAL_HEAP,\r
+        .heapFlags  = TCPIP_STACK_HEAP_FLAG_ALLOC_UNCACHED | TCPIP_STACK_HEAP_FLAG_NO_MTHREAD_SYNC,\r
+        .heapUsage  = TCPIP_STACK_HEAP_USE_DEFAULT,\r
+        .malloc_fnc = _malloc,\r
+        .calloc_fnc = _calloc,\r
+        .free_fnc   = _free,\r
+    };\r
+\r
+    #if ( PIC32_MAC_DEBUG_COMMANDS != 0 )\r
+        static int _Command_MacInfo( SYS_CMD_DEVICE_NODE * pCmdIO,\r
+                                     int argc,\r
+                                     char ** argv );\r
+        static int _Command_NetInfo( SYS_CMD_DEVICE_NODE * pCmdIO,\r
+                                     int argc,\r
+                                     char ** argv );\r
+        static int _Command_Version( SYS_CMD_DEVICE_NODE * pCmdIO,\r
+                                     int argc,\r
+                                     char ** argv );\r
+\r
+        static const SYS_CMD_DESCRIPTOR macCmdTbl[] =\r
+        {\r
+            { "macinfo", _Command_MacInfo, ": Check MAC statistics" },\r
+            { "netinfo", _Command_NetInfo, ": Net info" },\r
+            { "version", _Command_Version, ": Version info" },\r
+        };\r
+    #endif /* (PIC32_MAC_DEBUG_COMMANDS != 0) */\r
+\r
+\r
+    /* FreeRTOS implementation functions */\r
+    BaseType_t xNetworkInterfaceInitialise( void )\r
+    {\r
+    BaseType_t xResult;\r
+\r
+        if( xMacInitStatus == eMACInit )\r
+        {\r
+                       /* This is the first time this function is called. */\r
+            if( StartInitMac() != false )\r
+            {\r
+                /* Indicate that the MAC initialisation succeeded. */\r
+                xMacInitStatus = eMACPass;\r
+            }\r
+            else\r
+            {\r
+                xMacInitStatus = eMACFailed;\r
+            }\r
+        }\r
+\r
+        if( xMacInitStatus == eMACPass )\r
+        {\r
+            xResult = xGetPhyLinkStatus();\r
+        }\r
+        else\r
+        {\r
+            xResult = pdFAIL;\r
+        }\r
+\r
+       PIC32_MAC_DbgPrint( "xNetworkInterfaceInitialise: %d %d\r\n", ( int ) xMacInitStatus, ( int ) xResult );\r
+\r
+        return xResult;\r
+    }\r
+\r
+\r
+    /*-----------------------------------------------------------*/\r
+\r
+    BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,\r
+                                        BaseType_t xReleaseAfterSend )\r
+    {\r
+        TCPIP_MAC_RES macRes;\r
+        TCPIP_MAC_PACKET * pTxPkt;\r
+\r
+        BaseType_t retRes = pdFALSE;\r
+\r
+\r
+        if( ( pxDescriptor != 0 ) && ( pxDescriptor->pucEthernetBuffer != 0 ) && ( pxDescriptor->xDataLength != 0 ) )\r
+        {\r
+            TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pxDescriptor->pucEthernetBuffer - PIC32_BUFFER_PKT_PTR_OSSET );\r
+            configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 );\r
+            pTxPkt = *ppkt;\r
+            configASSERT( pTxPkt != 0 );\r
+\r
+            /* prepare the packet for transmission */\r
+            /* set the correct data length: */\r
+            configASSERT( pTxPkt->pDSeg->segSize >= pTxPkt->pDSeg->segLen );\r
+            pTxPkt->pDSeg->segLen = pxDescriptor->xDataLength;\r
+            pTxPkt->next = 0; /* unlink it */\r
+            macRes = ( macObject->TCPIP_MAC_PacketTx )( macCliHandle, pTxPkt );\r
+\r
+            if( macRes >= 0 )\r
+            {\r
+                retRes = pdTRUE;\r
+                pxDescriptor->pucEthernetBuffer = 0; /* it will be released by the MAC driver once it's transmitted */\r
+                iptraceNETWORK_INTERFACE_TRANSMIT();\r
+            }\r
+\r
+            /* else same error occurred; this normally should not happen! But the buffer is left in there so it shold be freed! */\r
+\r
+            /* The buffer has been sent so can be released. */\r
+            if( xReleaseAfterSend != pdFALSE )\r
+            {\r
+                vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
+            }\r
+        }\r
+\r
+        return retRes;\r
+    }\r
+\r
+\r
+    /************************************* Section: helper functions ************************************************** */\r
+    /* */\r
+\r
+    void PIC32_GetMACAddress( uint8_t macAdd[ 6 ] )\r
+    {\r
+        #if defined( __PIC32MZ__ ) || defined( __PIC32MX__ )\r
+            PLIB_ETH_MACGetAddress( ETH_ID_0, macAdd );\r
+        #else\r
+        #error "MAC Address: not supported architecture!"\r
+        #endif\r
+    }\r
+\r
+\r
+    /*-----------------------------------------------------------*/\r
+\r
+    const void * const PIC32_GetMacConfigData( void )\r
+    {\r
+        #if defined( __PIC32MZ__ ) || defined( __PIC32MX__ )\r
+            extern const TCPIP_MODULE_MAC_PIC32INT_CONFIG tcpipMACPIC32INTInitData;\r
+\r
+            return &tcpipMACPIC32INTInitData;\r
+        #else\r
+        #error "MAC Address: not supported architecture!"\r
+        #endif\r
+    }\r
+\r
+    /************************************* Section: worker code ************************************************** */\r
+    /* */\r
+\r
+\r
+    static bool StartInitMac( void )\r
+    {\r
+        TCPIP_MAC_MODULE_CTRL macCtrl;\r
+        SYS_MODULE_INIT moduleInit;\r
+        EventBits_t evBits;\r
+\r
+\r
+        /* perform some initialization of all variables so that we can cleanup what failed */\r
+        /* if something failed, the routine will be called again and again by FreeRTOS! */\r
+        macHeapHandle = 0;\r
+        macObjHandle = 0;\r
+        macCliHandle = 0;\r
+        macTmrHandle = 0;\r
+        macTaskHandle = 0;\r
+        macObject = TCPIP_HOSTS_CONFIGURATION[ 0 ].pMacObject; /* the MAC object we use */\r
+        macObjStatus = SYS_STATUS_UNINITIALIZED;\r
+        macLinkStatus = false;\r
+\r
+        int netUpFail = 0;\r
+\r
+        while( true )\r
+        {\r
+            /* start the allocator */\r
+            macHeapHandle = TCPIP_HEAP_Create( ( const TCPIP_STACK_HEAP_CONFIG * ) &tcpipHeapConfig, 0 );\r
+\r
+            if( macHeapHandle == 0 )\r
+            {\r
+                netUpFail = 1;\r
+                break;\r
+            }\r
+\r
+            if( TCPIP_PKT_Initialize( macHeapHandle, 0, 0 ) == false )\r
+            {\r
+                netUpFail = 2;\r
+                break;\r
+            }\r
+\r
+            moduleInit.sys.powerState = SYS_MODULE_POWER_RUN_FULL;\r
+\r
+            /* Initialize the MAC. MAC address is defined to 0x000000000000 in\r
+             * FreeRTOSConfig.h and therefore it will be initialized to the\r
+             * factory programmed MAC address. */\r
+            SetMacCtrl( &macCtrl );\r
+            /* Set the mac address in the FreeRTOS+TCP stack. */\r
+            FreeRTOS_UpdateMACAddress( macCtrl.ifPhyAddress.v );\r
+\r
+            TCPIP_MAC_INIT macInit =\r
+            {\r
+                .moduleInit = { moduleInit.value },\r
+                .macControl = &macCtrl,\r
+                .moduleData = PIC32_GetMacConfigData(),\r
+            };\r
+\r
+            macObjHandle = ( macObject->TCPIP_MAC_Initialize )( TCPIP_MODULE_MAC_PIC32INT, &macInit.moduleInit );\r
+\r
+            if( macObjHandle == SYS_MODULE_OBJ_INVALID )\r
+            {\r
+                macObjHandle = 0;\r
+                netUpFail = 4;\r
+                break;\r
+            }\r
+\r
+            /* open the MAC */\r
+            macCliHandle = ( macObject->TCPIP_MAC_Open )( TCPIP_MODULE_MAC_PIC32INT, DRV_IO_INTENT_READWRITE );\r
+\r
+            if( macCliHandle == DRV_HANDLE_INVALID )\r
+            {\r
+                macCliHandle = 0;\r
+                netUpFail = 5;\r
+                break;\r
+            }\r
+\r
+            if( !( macObject->TCPIP_MAC_EventMaskSet )( macCliHandle, ( TCPIP_MAC_EV_RX_DONE | TCPIP_MAC_EV_TX_DONE | TCPIP_MAC_EV_RXTX_ERRORS ), true ) )\r
+            {\r
+                netUpFail = 6;\r
+                break;\r
+            }\r
+\r
+            /* completed the MAC initialization */\r
+            /* continue the initialization */\r
+            macTmrHandle = xTimerCreate( PIC32_MAC_TIMER_NAME, PIC32_MAC_TIMER_PERIOD, pdTRUE, 0, MacTmrCallback );\r
+\r
+            if( ( macTmrHandle == 0 ) || ( xTimerStart( macTmrHandle, 0 ) != pdPASS ) )\r
+            {\r
+                netUpFail = 8;\r
+                break;\r
+            }\r
+\r
+            /* spawn the PIC32 MAC task function */\r
+            /* and wait for its event signal */\r
+            macObjStatus = SYS_STATUS_BUSY;\r
+\r
+            if( xTaskCreate( MacHandlerTask, PIC32_MAC_TASK_NAME, PIC32_MAC_TASK_STACK_SIZE, xTaskGetCurrentTaskHandle(), PIC32_MAC_TASK_PRI, &macTaskHandle ) != pdPASS )\r
+            { /* failed */\r
+                netUpFail = 9;\r
+                break;\r
+            }\r
+\r
+            xTaskNotifyWait( PIC32_MAC_EVENT_INIT_DONE, PIC32_MAC_EVENT_INIT_DONE, &evBits, PIC32_MAC_INIT_TIMEOUT );\r
+\r
+            if( ( evBits & PIC32_MAC_EVENT_INIT_DONE ) == 0 )\r
+            { /* timed out */\r
+                netUpFail = 10;\r
+                break;\r
+            }\r
+\r
+            if( macObjStatus != SYS_STATUS_READY )\r
+            { /* failed somehow ??? */\r
+                netUpFail = 11;\r
+                break;\r
+            }\r
+\r
+            netUpFail = 0;\r
+            break;\r
+        }\r
+\r
+        if( netUpFail == 0 )\r
+        {\r
+            PIC32_MAC_DbgPrint( " MAC Init success!\r\n" );\r
+\r
+            #if ( PIC32_MAC_DEBUG_COMMANDS != 0 )\r
+                /* create command group */\r
+                if( !SYS_CMD_ADDGRP( macCmdTbl, sizeof( macCmdTbl ) / sizeof( *macCmdTbl ), "mac", ": mac commands" ) )\r
+                {\r
+                    PIC32_MAC_DbgPrint( "Failed to create MAC Commands\r\n" );\r
+                }\r
+            #endif /* (PIC32_MAC_DEBUG_COMMANDS != 0) */\r
+\r
+            return true;\r
+        }\r
+        else\r
+        {\r
+            StartInitCleanup();\r
+            PIC32_MAC_DbgPrint( "MAC Init failed: %d!\r\n", netUpFail );\r
+\r
+            return false;\r
+        }\r
+    }\r
+\r
+    /*-----------------------------------------------------------*/\r
+\r
+    static void StartInitCleanup( void )\r
+    {\r
+        if( macHeapHandle != 0 )\r
+        {\r
+            TCPIP_HEAP_Delete( macHeapHandle );\r
+            macHeapHandle = 0;\r
+        }\r
+\r
+        if( macObjHandle != 0 )\r
+        {\r
+            ( macObject->TCPIP_MAC_Deinitialize )( macObjHandle );\r
+            macObjHandle = 0;\r
+        }\r
+\r
+        if( macTmrHandle != 0 )\r
+        {\r
+            xTimerDelete( macTmrHandle, portMAX_DELAY );\r
+            macTmrHandle = 0;\r
+        }\r
+\r
+        if( macTaskHandle != 0 )\r
+        {\r
+            vTaskDelete( macTaskHandle );\r
+            macTaskHandle = 0;\r
+        }\r
+    }\r
+\r
+    /*-----------------------------------------------------------*/\r
+\r
+    static void SetMacCtrl( TCPIP_MAC_MODULE_CTRL * pMacCtrl )\r
+    {\r
+        TCPIP_MAC_ADDR macAdd;\r
+        uint8_t unsetMACAddr[ 6 ] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };     /* not set MAC address */\r
+\r
+        pMacCtrl->nIfs = 1;\r
+\r
+        pMacCtrl->mallocF = TCPIP_HEAP_MallocOutline;\r
+        pMacCtrl->callocF = TCPIP_HEAP_CallocOutline;\r
+        pMacCtrl->freeF = TCPIP_HEAP_FreeOutline;\r
+        pMacCtrl->memH = macHeapHandle;\r
+\r
+\r
+        pMacCtrl->pktAllocF = PIC32_MacPacketAllocate;\r
+        pMacCtrl->pktFreeF = ( TCPIP_MAC_PKT_FreeF ) _TCPIP_PKT_FREE_FNC;\r
+        pMacCtrl->pktAckF = ( TCPIP_MAC_PKT_AckF ) _TCPIP_PKT_ACK_FNC;\r
+\r
+        pMacCtrl->synchF = MacSyncFunction;\r
+\r
+        pMacCtrl->eventF = MAC_EventFunction;\r
+        pMacCtrl->eventParam = 0;\r
+\r
+        pMacCtrl->moduleId = TCPIP_MODULE_MAC_PIC32INT;\r
+        pMacCtrl->netIx = 0;\r
+        pMacCtrl->macAction = TCPIP_MAC_ACTION_INIT;\r
+        pMacCtrl->powerMode = TCPIP_MAC_POWER_FULL;\r
+\r
+        macAdd.v[ 0 ] = configMAC_ADDR0;\r
+        macAdd.v[ 1 ] = configMAC_ADDR1;\r
+        macAdd.v[ 2 ] = configMAC_ADDR2;\r
+        macAdd.v[ 3 ] = configMAC_ADDR3;\r
+        macAdd.v[ 4 ] = configMAC_ADDR4;\r
+        macAdd.v[ 5 ] = configMAC_ADDR5;\r
+\r
+        if( memcmp( macAdd.v, unsetMACAddr, sizeof( unsetMACAddr ) ) == 0 )\r
+        { /* if unspecified we use the factory pre-programmed address */\r
+            PIC32_GetMACAddress( pMacCtrl->ifPhyAddress.v );\r
+        }\r
+        else\r
+        { /* use the config suggested one */\r
+            memcpy( pMacCtrl->ifPhyAddress.v, macAdd.v, sizeof( macAdd ) );\r
+        }\r
+    }\r
+\r
+    /*-----------------------------------------------------------*/\r
+\r
+    static bool MacSyncFunction( void * synchHandle,\r
+                                 TCPIP_MAC_SYNCH_REQUEST req )\r
+    {\r
+        switch( req )\r
+        {\r
+            case TCPIP_MAC_SYNCH_REQUEST_OBJ_CREATE:\r
+                vSemaphoreCreateBinary( *( SemaphoreHandle_t * ) synchHandle );\r
+\r
+                return ( *( SemaphoreHandle_t * ) synchHandle == NULL ) ? false : true;\r
+\r
+            case TCPIP_MAC_SYNCH_REQUEST_OBJ_DELETE:\r
+                vSemaphoreDelete( *( SemaphoreHandle_t * ) synchHandle );\r
+                *( SemaphoreHandle_t * ) synchHandle = NULL;\r
+\r
+                return true;\r
+\r
+            case TCPIP_MAC_SYNCH_REQUEST_OBJ_LOCK:\r
+\r
+                return ( xSemaphoreTake( *( SemaphoreHandle_t * ) synchHandle, portMAX_DELAY ) == pdTRUE ) ? true : false;\r
+\r
+            case TCPIP_MAC_SYNCH_REQUEST_OBJ_UNLOCK:\r
+\r
+                return ( xSemaphoreGive( *( SemaphoreHandle_t * ) synchHandle ) == pdTRUE ) ? true : false;\r
+\r
+            case TCPIP_MAC_SYNCH_REQUEST_CRIT_ENTER:\r
+                vTaskSuspendAll();\r
+\r
+                return true;\r
+\r
+            case TCPIP_MAC_SYNCH_REQUEST_CRIT_LEAVE:\r
+                xTaskResumeAll();\r
+\r
+                return true;\r
+\r
+            default:\r
+\r
+                return false;\r
+        }\r
+    }\r
+\r
+\r
+    /*-----------------------------------------------------------*/\r
+\r
+    static void MacHandlerTask( void * params )\r
+    {\r
+        EventBits_t evBits;\r
+\r
+        /* perform the MAC initialization */\r
+        while( macObjStatus == SYS_STATUS_BUSY )\r
+        {\r
+            /* process the underlying MAC module tasks */\r
+            ( macObject->TCPIP_MAC_Tasks )( macObjHandle );\r
+\r
+            SYS_STATUS macStatus = ( macObject->TCPIP_MAC_Status )( macObjHandle );\r
+\r
+            if( macStatus == SYS_STATUS_BUSY )\r
+            { /* still pending */\r
+                vTaskDelay( PIC32_MAC_TASK_INIT_PENDING_DELAY );\r
+            }\r
+            else\r
+            { /* completed ...somehow */\r
+                macObjStatus = macStatus;\r
+\r
+                xTaskNotify( ( TaskHandle_t ) params, PIC32_MAC_EVENT_INIT_DONE, eSetBits );\r
+\r
+                if( macStatus != SYS_STATUS_READY )\r
+                { /* failed miserably */\r
+                    vTaskDelete( 0 );\r
+                }\r
+\r
+                /* done, up and running */\r
+            }\r
+        }\r
+\r
+        while( true )\r
+        {\r
+            xTaskNotifyWait( PIC32_MAC_EVENT_TIMEOUT | PIC32_MAC_EVENT_IF_PENDING, PIC32_MAC_EVENT_TIMEOUT | PIC32_MAC_EVENT_IF_PENDING, &evBits, portMAX_DELAY );\r
+\r
+            if( ( evBits & PIC32_MAC_EVENT_TIMEOUT ) != 0 )\r
+            {                                                                       /* timeout occurred... */\r
+                ( macObject->TCPIP_MAC_Tasks )( macObjHandle );\r
+                bool linkCurr = ( macObject->TCPIP_MAC_LinkCheck )( macCliHandle ); /* check link status */\r
+\r
+                if( macLinkStatus != linkCurr )\r
+                { /* link status changed; some event could ve fired here if needed */\r
+                    PIC32_MAC_DbgPrint( " MAC link: %s!\r\n", linkCurr ? "ON" : "OFF" );\r
+                    macLinkStatus = linkCurr;\r
+                }\r
+            }\r
+\r
+            if( ( evBits & PIC32_MAC_EVENT_IF_PENDING ) != 0 )\r
+            { /* IF events signal */\r
+                TCPIP_MAC_EVENT activeEvents = ( macObject->TCPIP_MAC_EventPendingGet )( macCliHandle );\r
+\r
+                if( activeEvents != TCPIP_MAC_EV_NONE )\r
+                {\r
+                    /* acknowledge the events */\r
+                    ( macObject->TCPIP_MAC_EventAcknowledge )( macCliHandle, activeEvents );\r
+\r
+                    /* check for RX */\r
+                    if( ( activeEvents & ( TCPIP_MAC_EV_RX_DONE | TCPIP_MAC_EV_RX_OVFLOW | TCPIP_MAC_EV_RX_BUFNA ) ) != 0 )\r
+                    { /* RX packets available */\r
+                        MacRxPackets();\r
+                    }\r
+\r
+                    /* call the driver process function; */\r
+                    /* PIC32 driver requests it through TCPIP_MAC_ParametersGet() which is bypassed here! */\r
+                    ( macObject->TCPIP_MAC_Process )( macCliHandle );\r
+                }\r
+            }\r
+\r
+            /* do what you have to do and then wait for another event... */\r
+        }\r
+    }\r
+\r
+    /*-----------------------------------------------------------*/\r
+\r
+    static void MacTmrCallback( TimerHandle_t xTimer )\r
+    {\r
+        xTaskNotify( macTaskHandle, PIC32_MAC_EVENT_TIMEOUT, eSetBits );\r
+    }\r
+\r
+    /* MAC interrupt event function */\r
+    /* MAC signals an event, probably from within ISR */\r
+    /* we care just for RX related events */\r
+    static void MAC_EventFunction( TCPIP_MAC_EVENT event,\r
+                                   const void * eventParam )\r
+    {\r
+        BaseType_t xHigherPriorityTaskWoken;\r
+\r
+        if( ( event & ( TCPIP_MAC_EV_RX_DONE | TCPIP_MAC_EV_TX_DONE | TCPIP_MAC_EV_RXTX_ERRORS ) ) != 0 )\r
+        {\r
+            xHigherPriorityTaskWoken = pdFALSE;\r
+            xTaskNotifyFromISR( macTaskHandle, PIC32_MAC_EVENT_IF_PENDING, eSetBits, &xHigherPriorityTaskWoken );\r
+\r
+            if( xHigherPriorityTaskWoken )\r
+            {\r
+                portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );\r
+            }\r
+        }\r
+    }\r
+\r
+    /*-----------------------------------------------------------*/\r
+\r
+    BaseType_t xGetPhyLinkStatus( void )\r
+    {\r
+        return macLinkStatus == true ? pdPASS : pdFAIL;\r
+    }\r
+\r
+\r
+    /* receive packets from the MAC driver */\r
+    static void MacRxPackets( void )\r
+    {\r
+        TCPIP_MAC_PACKET * pRxPkt;\r
+\r
+        /* get all the new MAC packets */\r
+        while( ( pRxPkt = ( macObject->TCPIP_MAC_PacketRx )( macCliHandle, 0, 0 ) ) != 0 )\r
+        {\r
+            MacProcessRxPacket( pRxPkt );\r
+        }\r
+    }\r
+\r
+    /*-----------------------------------------------------------*/\r
+\r
+    static void MacProcessRxPacket( TCPIP_MAC_PACKET * pRxPkt )\r
+    {\r
+        bool pktSuccess, pktLost;\r
+        size_t pktLength;\r
+        TCPIP_MAC_DATA_SEGMENT * pSeg;\r
+        uint8_t * pPktBuff;\r
+        NetworkBufferDescriptor_t * pxBufferDescriptor;\r
+        IPStackEvent_t xRxEvent;\r
+\r
+        pxBufferDescriptor = 0;\r
+        pktSuccess = pktLost = false;\r
+\r
+        while( true )\r
+        {\r
+            pktLength = 0;\r
+            int nSegs = 0;\r
+            pSeg = pRxPkt->pDSeg;\r
+            pPktBuff = pSeg->segLoad;\r
+\r
+            /* calculate the packet size */\r
+            do\r
+            {\r
+                pktLength += pSeg->segLen;\r
+                pSeg = pSeg->next;\r
+                nSegs++;\r
+            } while( pSeg != 0 );\r
+\r
+            if( nSegs > 1 )\r
+            { /* no support in FreeRTOS for multi segment packets! */\r
+                break;\r
+            }\r
+\r
+            /* sizeof(TCPIP_MAC_ETHERNET_HEADER) is subtracted by the driver */\r
+            /* but FreeRTOS needs the whole frame! */\r
+            pktLength += sizeof( TCPIP_MAC_ETHERNET_HEADER );\r
+\r
+            if( eConsiderFrameForProcessing( pPktBuff ) != eProcessBuffer )\r
+            {\r
+                break;\r
+            }\r
+\r
+            /* get the network descriptor (no data buffer) to hold this packet */\r
+            pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( 0, 0 );\r
+\r
+            if( pxBufferDescriptor == 0 )\r
+            {\r
+                pktLost = true;\r
+                break;\r
+            }\r
+\r
+            PIC32_MacAssociate( pRxPkt, pxBufferDescriptor, pktLength );\r
+\r
+            xRxEvent.eEventType = eNetworkRxEvent;\r
+            xRxEvent.pvData = ( void * ) pxBufferDescriptor;\r
+\r
+            /* Send the data to the TCP/IP stack */\r
+            if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )\r
+            { /* failed */\r
+                pktLost = true;\r
+            }\r
+            else\r
+            { /* success */\r
+                pktSuccess = true;\r
+                iptraceNETWORK_INTERFACE_RECEIVE();\r
+            }\r
+\r
+            break;\r
+        }\r
+\r
+        if( !pktSuccess )\r
+        { /* smth went wrong; nothing sent to the */\r
+            if( pxBufferDescriptor != 0 )\r
+            {\r
+                pxBufferDescriptor->pucEthernetBuffer = 0;\r
+                vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );\r
+            }\r
+\r
+            if( pktLost )\r
+            {\r
+                iptraceETHERNET_RX_EVENT_LOST();\r
+            }\r
+\r
+            /* acknowledge the packet to the MAC driver */\r
+            if( pRxPkt->ackFunc )\r
+            {\r
+                ( *pRxPkt->ackFunc )( pRxPkt, pRxPkt->ackParam );\r
+            }\r
+            else\r
+            {\r
+                PIC32_MacPacketOrphan( pRxPkt );\r
+            }\r
+        }\r
+    }\r
+\r
+    #if ( PIC32_MAC_DEBUG_COMMANDS != 0 )\r
+        /* */\r
+        static int _Command_MacInfo( SYS_CMD_DEVICE_NODE * pCmdIO,\r
+                                     int argc,\r
+                                     char ** argv )\r
+        {\r
+            TCPIP_MAC_RES macRes;\r
+            TCPIP_MAC_RX_STATISTICS rxStatistics;\r
+            TCPIP_MAC_TX_STATISTICS txStatistics;\r
+            TCPIP_MAC_STATISTICS_REG_ENTRY regEntries[ 8 ];\r
+            TCPIP_MAC_STATISTICS_REG_ENTRY * pRegEntry;\r
+            int jx, hwEntries;\r
+            char entryName[ sizeof( pRegEntry->registerName ) + 1 ];\r
+\r
+            const void * cmdIoParam = pCmdIO->cmdIoParam;\r
+\r
+            if( argc != 1 )\r
+            {\r
+                ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "Usage: macinfo \r\n" );\r
+                ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "Ex: macinfo \r\n" );\r
+\r
+                return false;\r
+            }\r
+\r
+            ( *pCmdIO->pCmdApi->print )( cmdIoParam, "Interface: %s driver statistics\r\n", macObject->macName );\r
+            macRes = ( macObject->TCPIP_MAC_StatisticsGet )( macCliHandle, &rxStatistics, &txStatistics );\r
+\r
+            if( macRes == TCPIP_MAC_RES_OK )\r
+            {\r
+                ( *pCmdIO->pCmdApi->print )( cmdIoParam, "\tnRxOkPackets: %d, nRxPendBuffers: %d, nRxSchedBuffers: %d, ",\r
+                                             rxStatistics.nRxOkPackets, rxStatistics.nRxPendBuffers, rxStatistics.nRxSchedBuffers );\r
+                ( *pCmdIO->pCmdApi->print )( cmdIoParam, "nRxErrorPackets: %d, nRxFragmentErrors: %d\r\n", rxStatistics.nRxErrorPackets, rxStatistics.nRxFragmentErrors );\r
+                ( *pCmdIO->pCmdApi->print )( cmdIoParam, "\tnTxOkPackets: %d, nTxPendBuffers: %d, nTxErrorPackets: %d, nTxQueueFull: %d\r\n",\r
+                                             txStatistics.nTxOkPackets, txStatistics.nTxPendBuffers, txStatistics.nTxErrorPackets, txStatistics.nTxQueueFull );\r
+            }\r
+            else\r
+            {\r
+                ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "\tnot supported\r\n" );\r
+            }\r
+\r
+            ( *pCmdIO->pCmdApi->print )( cmdIoParam, "Interface: %s hardware statistics\r\n", macObject->macName );\r
+            macRes = ( macObject->TCPIP_MAC_RegisterStatisticsGet )( macCliHandle, regEntries, sizeof( regEntries ) / sizeof( *regEntries ), &hwEntries );\r
+\r
+            if( macRes == TCPIP_MAC_RES_OK )\r
+            {\r
+                entryName[ sizeof( entryName ) - 1 ] = 0;\r
+\r
+                for( jx = 0, pRegEntry = regEntries; jx < hwEntries && jx < sizeof( regEntries ) / sizeof( *regEntries ); jx++, pRegEntry++ )\r
+                {\r
+                    strncpy( entryName, pRegEntry->registerName, sizeof( entryName ) - 1 );\r
+                    ( *pCmdIO->pCmdApi->print )( cmdIoParam, "\t%s: 0x%8x\r\n", entryName, pRegEntry->registerValue );\r
+                }\r
+            }\r
+            else\r
+            {\r
+                ( *pCmdIO->pCmdApi->msg )( cmdIoParam, "\tnot supported\r\n" );\r
+            }\r
+\r
+            return true;\r
+        }\r
+\r
+        /*-----------------------------------------------------------*/\r
+\r
+        static int _Command_NetInfo( SYS_CMD_DEVICE_NODE * pCmdIO,\r
+                                     int argc,\r
+                                     char ** argv )\r
+        {\r
+            const void * cmdIoParam = pCmdIO->cmdIoParam;\r
+\r
+            union\r
+            {\r
+                uint32_t ul;\r
+                uint8_t b[ 4 ];\r
+            }\r
+            sUl;\r
+\r
+            sUl.ul = FreeRTOS_GetIPAddress();\r
+\r
+            bool linkUp = FreeRTOS_IsNetworkUp() == pdTRUE;\r
+\r
+            ( *pCmdIO->pCmdApi->print )( cmdIoParam, "IP address: %d.%d.%d.%d\r\n", sUl.b[ 0 ], sUl.b[ 1 ], sUl.b[ 2 ], sUl.b[ 3 ] );\r
+            ( *pCmdIO->pCmdApi->print )( cmdIoParam, "Link is: %s\r\n", linkUp ? "Up" : "Down" );\r
+\r
+            return true;\r
+        }\r
+\r
+#include "aws_application_version.h"\r
+\r
+static int _Command_Version(SYS_CMD_DEVICE_NODE* pCmdIO, int argc, char** argv)\r
+{\r
+    configPRINTF( ( "App version - maj: %d, min: %d, build: %d\r\n",  xAppFirmwareVersion.u.x.ucMajor, xAppFirmwareVersion.u.x.ucMinor, xAppFirmwareVersion.u.x.usBuild) );\r
+    return 0;\r
+}\r
+\r
+    #endif /* (PIC32_MAC_DEBUG_COMMANDS != 0) */\r
+#endif /* #ifdef PIC32_USE_ETHERNET */\r
index fc8335ebea9ee842ffcd0c523eb92beb5f6bee72..a24cfe8ad7e575f44aa11b55e02047ae5023e77f 100644 (file)
-/*******************************************************************************
-*  Network Interface file
-*
-*  Summary:
-*   Network Interface file for FreeRTOS-Plus-TCP stack
-*
-*  Description:
-*   - Interfaces PIC32 to the FreeRTOS TCP/IP stack
-*******************************************************************************/
-
-/*******************************************************************************
-*  File Name:  pic32_NetworkInterface.c
-*  Copyright 2017 Microchip Technology Incorporated and its subsidiaries.
-*
-*  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
-*******************************************************************************/
-#ifndef PIC32_USE_ETHERNET
-#include <sys/kmem.h>
-
-#include "FreeRTOS.h"
-#include "semphr.h"
-#include "event_groups.h"
-#include "FreeRTOS_IP.h"
-#include "FreeRTOS_IP_Private.h"
-
-#include "NetworkInterface.h"
-#include "NetworkBufferManagement.h"
-#include "peripheral/eth/plib_eth.h"
-
-#include "system_config.h"
-#include "system/console/sys_console.h"
-#include "system/debug/sys_debug.h"
-#include "system/command/sys_command.h"
-
-#include "driver/ethmac/drv_ethmac.h"
-#include "driver/miim/drv_miim.h"
-#include "m2m_types.h"
-
-#include "tcpip/tcpip.h"
-#include "tcpip/src/tcpip_private.h"
-#include "tcpip/src/link_list.h"
-#include "wilc1000_task.h"
-
-#include "NetworkConfig.h"
-
-
-    #include "iot_wifi.h"
-
-    /* local definitions and data */
-
-
-    /* FreeRTOS implementation functions */
-    BaseType_t xNetworkInterfaceInitialise( void )
-    {
-        WIFINetworkParams_t xNetworkParams;
-
-        xNetworkParams.pcSSID = clientcredentialWIFI_SSID;
-        xNetworkParams.ucSSIDLength = sizeof( clientcredentialWIFI_SSID );
-        xNetworkParams.pcPassword = clientcredentialWIFI_PASSWORD;
-        xNetworkParams.ucPasswordLength = sizeof( clientcredentialWIFI_PASSWORD );
-        xNetworkParams.xSecurity = clientcredentialWIFI_SECURITY;
-        xNetworkParams.cChannel = M2M_WIFI_CH_ALL; /* Scan all channels (255) */
-
-        /*Turn  WiFi ON */
-        if( WIFI_On() != eWiFiSuccess )
-        {
-            return pdFAIL;
-        }
-
-        /* Connect to the AP */
-        if( WIFI_ConnectAP( &xNetworkParams ) != eWiFiSuccess )
-        {
-            return pdFAIL;
-        }
-
-        return pdPASS;
-    }
-
-
-    /*-----------------------------------------------------------*/
-
-    BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,
-                                        BaseType_t xReleaseAfterSend )
-    {
-        BaseType_t retRes = pdFALSE;
-
-        if( ( pxDescriptor != 0 ) && ( pxDescriptor->pucEthernetBuffer != 0 ) && ( pxDescriptor->xDataLength != 0 ) )
-        {
-            /* There you go */
-            if( WDRV_EXT_DataSend( pxDescriptor->xDataLength, pxDescriptor->pucEthernetBuffer ) == 0 )
-            {
-                retRes = pdTRUE;
-            }
-
-            /* The buffer has been sent so can be released. */
-            if( xReleaseAfterSend != pdFALSE )
-            {
-                vReleaseNetworkBufferAndDescriptor( pxDescriptor );
-            }
-        }
-
-        return retRes;
-    }
-
-
-    /************************************* Section: helper functions ************************************************** */
-    /* */
-
-
-
-    /************************************* Section: worker code ************************************************** */
-    /* */
-
-    void xNetworkFrameReceived( uint32_t len,
-                                uint8_t const * const frame )
-    {
-        bool pktSuccess, pktLost;
-        NetworkBufferDescriptor_t * pxNetworkBuffer = NULL;
-        IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
-
-        pktSuccess = pktLost = false;
-
-        while( true )
-        {
-            if( eConsiderFrameForProcessing( frame ) != eProcessBuffer )
-            {
-                break;
-            }
-
-            /* get the network descriptor (no data buffer) to hold this packet */
-            pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( len, 0 );
-
-            if( pxNetworkBuffer == NULL )
-            {
-                pktLost = true;
-                break;
-            }
-
-            /* Set the actual packet length, in case a larger buffer was 
-            returned. */
-            pxNetworkBuffer->xDataLength = len;
-            
-            /* Copy the packet. */
-            memcpy( pxNetworkBuffer->pucEthernetBuffer, frame, len );
-
-            /* Send the data to the TCP/IP stack. */
-            xRxEvent.pvData = ( void * ) pxNetworkBuffer;
-
-            if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )
-            { /* failed */
-                pktLost = true;
-            }
-            else
-            { /* success */
-                pktSuccess = true;
-                iptraceNETWORK_INTERFACE_RECEIVE();
-            }
-
-            break;
-        }
-
-        if( !pktSuccess )
-        { /* smth went wrong; nothing sent to the */
-            if( pxNetworkBuffer != NULL )
-            {
-                pxNetworkBuffer->pucEthernetBuffer = 0;
-                vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
-            }
-
-            if( pktLost )
-            {
-                iptraceETHERNET_RX_EVENT_LOST();
-            }
-        }
-    }
-
-#endif /* #ifndef PIC32_USE_ETHERNET */
+/*******************************************************************************\r
+*  Network Interface file\r
+*\r
+*  Summary:\r
+*   Network Interface file for FreeRTOS-Plus-TCP stack\r
+*\r
+*  Description:\r
+*   - Interfaces PIC32 to the FreeRTOS TCP/IP stack\r
+*******************************************************************************/\r
+\r
+/*******************************************************************************\r
+*  File Name:  pic32_NetworkInterface.c\r
+*  Copyright 2017 Microchip Technology Incorporated and its subsidiaries.\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\r
+*  of the Software, and to permit persons to whom the Software is furnished to do\r
+*  so, subject to the following conditions:\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,\r
+*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+*  SOFTWARE\r
+*******************************************************************************/\r
+#ifndef PIC32_USE_ETHERNET\r
+#include <sys/kmem.h>\r
+\r
+#include "FreeRTOS.h"\r
+#include "semphr.h"\r
+#include "event_groups.h"\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+\r
+#include "NetworkInterface.h"\r
+#include "NetworkBufferManagement.h"\r
+#include "peripheral/eth/plib_eth.h"\r
+\r
+#include "system_config.h"\r
+#include "system/console/sys_console.h"\r
+#include "system/debug/sys_debug.h"\r
+#include "system/command/sys_command.h"\r
+\r
+#include "driver/ethmac/drv_ethmac.h"\r
+#include "driver/miim/drv_miim.h"\r
+#include "m2m_types.h"\r
+\r
+#include "tcpip/tcpip.h"\r
+#include "tcpip/src/tcpip_private.h"\r
+#include "tcpip/src/link_list.h"\r
+#include "wilc1000_task.h"\r
+\r
+#include "NetworkConfig.h"\r
+\r
+\r
+    #include "iot_wifi.h"\r
+\r
+    /* local definitions and data */\r
+\r
+\r
+    /* FreeRTOS implementation functions */\r
+    BaseType_t xNetworkInterfaceInitialise( void )\r
+    {\r
+        WIFINetworkParams_t xNetworkParams;\r
+\r
+        xNetworkParams.pcSSID = clientcredentialWIFI_SSID;\r
+        xNetworkParams.ucSSIDLength = sizeof( clientcredentialWIFI_SSID );\r
+        xNetworkParams.pcPassword = clientcredentialWIFI_PASSWORD;\r
+        xNetworkParams.ucPasswordLength = sizeof( clientcredentialWIFI_PASSWORD );\r
+        xNetworkParams.xSecurity = clientcredentialWIFI_SECURITY;\r
+        xNetworkParams.cChannel = M2M_WIFI_CH_ALL; /* Scan all channels (255) */\r
+\r
+        /*Turn  WiFi ON */\r
+        if( WIFI_On() != eWiFiSuccess )\r
+        {\r
+            return pdFAIL;\r
+        }\r
+\r
+        /* Connect to the AP */\r
+        if( WIFI_ConnectAP( &xNetworkParams ) != eWiFiSuccess )\r
+        {\r
+            return pdFAIL;\r
+        }\r
+\r
+        return pdPASS;\r
+    }\r
+\r
+\r
+    /*-----------------------------------------------------------*/\r
+\r
+    BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,\r
+                                        BaseType_t xReleaseAfterSend )\r
+    {\r
+        BaseType_t retRes = pdFALSE;\r
+\r
+        if( ( pxDescriptor != 0 ) && ( pxDescriptor->pucEthernetBuffer != 0 ) && ( pxDescriptor->xDataLength != 0 ) )\r
+        {\r
+            /* There you go */\r
+            if( WDRV_EXT_DataSend( pxDescriptor->xDataLength, pxDescriptor->pucEthernetBuffer ) == 0 )\r
+            {\r
+                retRes = pdTRUE;\r
+            }\r
+\r
+            /* The buffer has been sent so can be released. */\r
+            if( xReleaseAfterSend != pdFALSE )\r
+            {\r
+                vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
+            }\r
+        }\r
+\r
+        return retRes;\r
+    }\r
+\r
+\r
+    /************************************* Section: helper functions ************************************************** */\r
+    /* */\r
+\r
+\r
+\r
+    /************************************* Section: worker code ************************************************** */\r
+    /* */\r
+\r
+    void xNetworkFrameReceived( uint32_t len,\r
+                                uint8_t const * const frame )\r
+    {\r
+        bool pktSuccess, pktLost;\r
+        NetworkBufferDescriptor_t * pxNetworkBuffer = NULL;\r
+        IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
+\r
+        pktSuccess = pktLost = false;\r
+\r
+        while( true )\r
+        {\r
+            if( eConsiderFrameForProcessing( frame ) != eProcessBuffer )\r
+            {\r
+                break;\r
+            }\r
+\r
+            /* get the network descriptor (no data buffer) to hold this packet */\r
+            pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( len, 0 );\r
+\r
+            if( pxNetworkBuffer == NULL )\r
+            {\r
+                pktLost = true;\r
+                break;\r
+            }\r
+\r
+            /* Set the actual packet length, in case a larger buffer was \r
+            returned. */\r
+            pxNetworkBuffer->xDataLength = len;\r
+            \r
+            /* Copy the packet. */\r
+            memcpy( pxNetworkBuffer->pucEthernetBuffer, frame, len );\r
+\r
+            /* Send the data to the TCP/IP stack. */\r
+            xRxEvent.pvData = ( void * ) pxNetworkBuffer;\r
+\r
+            if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )\r
+            { /* failed */\r
+                pktLost = true;\r
+            }\r
+            else\r
+            { /* success */\r
+                pktSuccess = true;\r
+                iptraceNETWORK_INTERFACE_RECEIVE();\r
+            }\r
+\r
+            break;\r
+        }\r
+\r
+        if( !pktSuccess )\r
+        { /* smth went wrong; nothing sent to the */\r
+            if( pxNetworkBuffer != NULL )\r
+            {\r
+                pxNetworkBuffer->pucEthernetBuffer = 0;\r
+                vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+            }\r
+\r
+            if( pktLost )\r
+            {\r
+                iptraceETHERNET_RX_EVENT_LOST();\r
+            }\r
+        }\r
+    }\r
+\r
+#endif /* #ifndef PIC32_USE_ETHERNET */\r
index 566db43d7373d05b00beef86cefef15f532a022b..f7a54557516a1408b50f4e9b3c44e0726b2cd67c 100644 (file)
@@ -1,6 +1,6 @@
 Documentation and download available at http://www.FreeRTOS.org/\r
 \r
-Changes between FreeRTOS V10.2.1 and FreeRTOS V10.3.0 released TBD\r
+Changes between FreeRTOS V10.2.1 and FreeRTOS V10.3.0 released February 7 2020\r
 \r
        See http://www.FreeRTOS.org/FreeRTOS-V10.3.x.html\r
 \r
index 286c5f221252c431a73f0b3ef6474a3d073e8119..b861483d042010b97b35f553becae8edd3804f50 100644 (file)
@@ -43,10 +43,10 @@ extern "C" {
  * MACROS AND DEFINITIONS\r
  *----------------------------------------------------------*/\r
 \r
-#define tskKERNEL_VERSION_NUMBER "V10.2.1"\r
+#define tskKERNEL_VERSION_NUMBER "V10.3.0"\r
 #define tskKERNEL_VERSION_MAJOR 10\r
-#define tskKERNEL_VERSION_MINOR 2\r
-#define tskKERNEL_VERSION_BUILD 1\r
+#define tskKERNEL_VERSION_MINOR 3\r
+#define tskKERNEL_VERSION_BUILD 0\r
 \r
 /* MPU region parameters passed in ulParameters\r
  * of MemoryRegion_t struct. */\r
diff --git a/Upgrading to FreeRTOS V10.3.0.url b/Upgrading to FreeRTOS V10.3.0.url
new file mode 100644 (file)
index 0000000..a30f018
--- /dev/null
@@ -0,0 +1,5 @@
+[{000214A0-0000-0000-C000-000000000046}]\r
+Prop3=19,11\r
+[InternetShortcut]\r
+IDList=\r
+URL=https://www.freertos.org/FreeRTOS-V10.3.x.html\r