From 970911e31a856f42f407cb95fa6ae549d14cf095 Mon Sep 17 00:00:00 2001 From: Stefan Baltruweit Date: Tue, 10 Sep 2024 14:11:07 +0200 Subject: [PATCH 01/11] Update Zynq Ultrascale port for V4.x This is basically a merge of the previous port, the Zynq7000 port and the port suggested by Pete Bone . --- .../xilinx_ultrascale/NetworkInterface.c | 441 ++++++++++++++---- .../xilinx_ultrascale/x_emacpsif.h | 16 +- .../xilinx_ultrascale/x_emacpsif_dma.c | 188 ++++++-- .../xilinx_ultrascale/x_emacpsif_hw.c | 22 +- .../xilinx_ultrascale/x_emacpsif_hw.h | 5 +- .../xilinx_ultrascale/x_emacpsif_physpeed.c | 13 +- .../xilinx_ultrascale/x_topology.h | 7 +- 7 files changed, 527 insertions(+), 165 deletions(-) diff --git a/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c b/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c index 6928131e6..a4612b956 100644 --- a/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c +++ b/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c @@ -43,6 +43,7 @@ #include "FreeRTOS_ARP.h" #include "NetworkBufferManagement.h" #include "NetworkInterface.h" +#include "FreeRTOS_Routing.h" /* Xilinx library files. */ #include @@ -114,7 +115,8 @@ * Look for the link to be up every few milliseconds until * xMaxTimeTicks has passed or a link is found. */ -static BaseType_t prvGMACWaitLS( TickType_t xMaxTimeTicks ); +static BaseType_t prvGMACWaitLS( BaseType_t xEMACIndex, + TickType_t xMaxTimeTicks ); /* * A deferred interrupt handler for all MAC/DMA interrupt sources. @@ -123,81 +125,190 @@ static void prvEMACHandlerTask( void * pvParameters ); /*-----------------------------------------------------------*/ +/* FreeRTOS+TCP/multi : + * Each network device has 3 access functions: + * - initialise the device + * - output a network packet + * - return the PHY link-status (LS) + * They can be defined as static because their addresses will be + * stored in struct NetworkInterface_t. */ + +static NetworkInterface_t * pxMyInterfaces[ XPAR_XEMACPS_NUM_INSTANCES ]; + +static BaseType_t xUltrascaleNetworkInterfaceInitialise( NetworkInterface_t * pxInterface ); + +static BaseType_t xUltrascaleNetworkInterfaceOutput( NetworkInterface_t * pxInterface, + NetworkBufferDescriptor_t * const pxBuffer, + BaseType_t bReleaseAfterSend ); + +static BaseType_t xUltrascaleGetPhyLinkStatus( NetworkInterface_t * pxInterface ); + +NetworkInterface_t * pxUltrascale_FillInterfaceDescriptor( BaseType_t xEMACIndex, + NetworkInterface_t * pxInterface ); + +/*-----------------------------------------------------------*/ + /* EMAC data/descriptions. */ -static xemacpsif_s xEMACpsif; -struct xtopology_t xXTopology = +static xemacpsif_s xEMACpsifs[ XPAR_XEMACPS_NUM_INSTANCES ]; + +struct xtopology_t xXTopologies[ XPAR_XEMACPS_NUM_INSTANCES ] = { - .emac_baseaddr = XPAR_XEMACPS_0_BASEADDR, - .emac_type = xemac_type_emacps, - .intc_baseaddr = 0x0, - .intc_emac_intr = 0x0, - .scugic_baseaddr = XPAR_SCUGIC_0_CPU_BASEADDR, - .scugic_emac_intr = XPAR_XEMACPS_3_INTR, + [ 0 ] = + { + .emac_baseaddr = XPAR_XEMACPS_0_BASEADDR, + .emac_type = xemac_type_emacps, + .intc_baseaddr = 0x0, + .intc_emac_intr = 0x0, + .scugic_baseaddr = XPAR_SCUGIC_0_CPU_BASEADDR, + .scugic_emac_intr = XPAR_XEMACPS_0_INTR, + }, + #if ( XPAR_XEMACPS_NUM_INSTANCES > 1 ) + [ 1 ] = + { + .emac_baseaddr = XPAR_XEMACPS_1_BASEADDR, + .emac_type = xemac_type_emacps, + .intc_baseaddr = 0x0, + .intc_emac_intr = 0x0, + .scugic_baseaddr = XPAR_SCUGIC_0_CPU_BASEADDR, + .scugic_emac_intr = XPAR_XEMACPS_1_INTR, + }, + #elif ( XPAR_XEMACPS_NUM_INSTANCES > 2 ) + [ 2 ] = + { + .emac_baseaddr = XPAR_XEMACPS_2_BASEADDR, + .emac_type = xemac_type_emacps, + .intc_baseaddr = 0x0, + .intc_emac_intr = 0x0, + .scugic_baseaddr = XPAR_SCUGIC_0_CPU_BASEADDR, + .scugic_emac_intr = XPAR_XEMACPS_2_INTR, + }, + #elif ( XPAR_XEMACPS_NUM_INSTANCES > 3 ) + [ 3 ] = + { + .emac_baseaddr = XPAR_XEMACPS_3_BASEADDR, + .emac_type = xemac_type_emacps, + .intc_baseaddr = 0x0, + .intc_emac_intr = 0x0, + .scugic_baseaddr = XPAR_SCUGIC_0_CPU_BASEADDR, + .scugic_emac_intr = XPAR_XEMACPS_3_INTR, + }, + #endif /* if ( XPAR_XEMACPS_NUM_INSTANCES > 1 ) */ }; -XEmacPs_Config mac_config = +XEmacPs_Config mac_configs[ XPAR_XEMACPS_NUM_INSTANCES ] = { - .DeviceId = XPAR_PSU_ETHERNET_3_DEVICE_ID, /**< Unique ID of device */ - .BaseAddress = XPAR_PSU_ETHERNET_3_BASEADDR, /**< Physical base address of IPIF registers */ - .IsCacheCoherent = XPAR_PSU_ETHERNET_3_IS_CACHE_COHERENT + [ 0 ] = + { + .DeviceId = XPAR_XEMACPS_0_DEVICE_ID, /**< Unique ID of device */ + .BaseAddress = XPAR_XEMACPS_0_BASEADDR, /**< Physical base address of IPIF registers */ + .IsCacheCoherent = XPAR_XEMACPS_0_IS_CACHE_COHERENT + }, + #if ( XPAR_XEMACPS_NUM_INSTANCES > 1 ) + [ 1 ] = + { + .DeviceId = XPAR_XEMACPS_1_DEVICE_ID, /**< Unique ID of device */ + .BaseAddress = XPAR_XEMACPS_1_BASEADDR, /**< Physical base address of IPIF registers */ + .IsCacheCoherent = XPAR_XEMACPS_1_IS_CACHE_COHERENT + }, + #elif ( XPAR_XEMACPS_NUM_INSTANCES > 2 ) + [ 2 ] = + { + .DeviceId = XPAR_XEMACPS_2_DEVICE_ID, /**< Unique ID of device */ + .BaseAddress = XPAR_XEMACPS_2_BASEADDR, /**< Physical base address of IPIF registers */ + .IsCacheCoherent = XPAR_XEMACPS_2_IS_CACHE_COHERENT + }, + #elif ( XPAR_XEMACPS_NUM_INSTANCES > 3 ) + [ 3 ] = + { + .DeviceId = XPAR_XEMACPS_3_DEVICE_ID, /**< Unique ID of device */ + .BaseAddress = XPAR_XEMACPS_3_BASEADDR, /**< Physical base address of IPIF registers */ + .IsCacheCoherent = XPAR_XEMACPS_3_IS_CACHE_COHERENT + }, + #endif /* if ( XPAR_XEMACPS_NUM_INSTANCES > 1 ) */ }; -/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */ -static uint32_t ulPHYLinkStatus = 0uL; +extern uint32_t phy_detected[ 4 ]; -#if ( ipconfigUSE_LLMNR == 1 ) -static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC }; -#endif +/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */ +static uint32_t ulPHYLinkStates[ XPAR_XEMACPS_NUM_INSTANCES ]; /* 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; +TaskHandle_t xEMACTaskHandles[ XPAR_XEMACPS_NUM_INSTANCES ]; -/* The PHY index where a PHY was found. */ -static u32 ulPHYIndex; +/*-----------------------------------------------------------*/ +/** + * @brief Initialise the interface number 'xIndex' + * @param xIndex: the index of the interface, between 0 + * zero and (XPAR_XEMACPS_NUM_INSTANCES-1) + * @note Although the function is declared public, it should + * not be called directly by an application. + */ +void vInitialiseOnIndex( BaseType_t xIndex ) +{ + if( ( xIndex >= 0 ) && ( xIndex < XPAR_XEMACPS_NUM_INSTANCES ) ) + { + NetworkInterface_t * pxInterface = pxMyInterfaces[ xIndex ]; + + if( pxInterface != NULL ) + { + xUltrascaleNetworkInterfaceInitialise( pxInterface ); + } + } +} /*-----------------------------------------------------------*/ /* The function xNetworkInterfaceInitialise() will be called as * long as it returns the value pdFAIL. - * It will go through several stages as described in 'eEMACState'. + * It will go through several stages as described in 'eEMACStates'. */ typedef enum xEMAC_STATE { - xEMAC_Init, + xEMAC_Init = 0, xEMAC_SetupPHY, xEMAC_WaitPHY, xEMAC_Ready, xEMAC_Fatal, } EMACState_t; -static EMACState_t eEMACState = xEMAC_Init; +static EMACState_t eEMACStates[ XPAR_XEMACPS_NUM_INSTANCES ] = { xEMAC_Init }; -BaseType_t xNetworkInterfaceInitialise( void ) +static BaseType_t xUltrascaleNetworkInterfaceInitialise( NetworkInterface_t * pxInterface ) { uint32_t ulLinkSpeed, ulDMAReg; BaseType_t xStatus, xReturn = pdFAIL; - XEmacPs * pxEMAC_PS = &( xEMACpsif.emacps ); + XEmacPs * pxEMAC_PS; const TickType_t xWaitLinkDelay = pdMS_TO_TICKS( 1000U ); + NetworkEndPoint_t * pxEndPoint; + BaseType_t xEMACIndex = ( BaseType_t ) pxInterface->pvArgument; - switch( eEMACState ) + configASSERT( xEMACIndex >= 0 ); + configASSERT( xEMACIndex < XPAR_XEMACPS_NUM_INSTANCES ); + + pxEMAC_PS = &( xEMACpsifs[ xEMACIndex ].emacps ); + + switch( eEMACStates[ xEMACIndex ] ) { case xEMAC_Init: - ulPHYLinkStatus = 0U; - memset( &xEMACpsif, '\0', sizeof( xEMACpsif ) ); + pxMyInterfaces[ xEMACIndex ] = pxInterface; + + ulPHYLinkStates[ xEMACIndex ] = 0U; + memset( &xEMACpsifs[ xEMACIndex ], '\0', sizeof( xEMACpsifs[ xEMACIndex ] ) ); - xStatus = XEmacPs_CfgInitialize( pxEMAC_PS, &mac_config, mac_config.BaseAddress ); + xStatus = XEmacPs_CfgInitialize( pxEMAC_PS, &( mac_configs[ xEMACIndex ] ), mac_configs[ xEMACIndex ].BaseAddress ); if( xStatus != XST_SUCCESS ) { FreeRTOS_printf( ( "xEMACInit: EmacPs Configuration Failed....\n" ) ); - eEMACState = xEMAC_Fatal; + eEMACStates[ xEMACIndex ] = xEMAC_Fatal; break; } -/* _HT_ : the use of jumbo frames has not been tested sufficiently yet. */ + pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); + configASSERT( pxEndPoint != NULL ); if( pxEMAC_PS->Version > 2 ) { @@ -207,32 +318,86 @@ BaseType_t xNetworkInterfaceInitialise( void ) #endif } - /* Initialize the mac and set the MAC address. */ - XEmacPs_SetMacAddress( pxEMAC_PS, ( void * ) ipLOCAL_MAC_ADDRESS, 1 ); + /* Initialize the mac and set the MAC address at position 1. */ + XEmacPs_SetMacAddress( pxEMAC_PS, ( void * ) pxEndPoint->xMACAddress.ucBytes, 1 ); #if ( ipconfigUSE_LLMNR == 1 ) { - /* Also add LLMNR multicast MAC address. */ - XEmacPs_SetMacAddress( pxEMAC_PS, ( void * ) xLLMNR_MACAddress, 2 ); + #if ( ipconfigUSE_IPv6 == 0 ) + { + /* Also add LLMNR multicast MAC address. */ + XEmacPs_SetMacAddress( pxEMAC_PS, ( void * ) xLLMNR_MacAddress.ucBytes, 2 ); + } + #else + { + XEmacPs_SetHash( pxEMAC_PS, ( void * ) xLLMNR_MacAddressIPv6.ucBytes ); + } + #endif /* if ( ipconfigUSE_IPv6 == 0 ) */ } #endif /* ipconfigUSE_LLMNR == 1 */ + #if ( ipconfigUSE_MDNS == 1 ) + { + #if ( ipconfigUSE_IPv6 == 0 ) + { + XEmacPs_SetHash( pxEMAC_PS, ( void * ) xMDNS_MacAddress.ucBytes ); + } + #else + { + XEmacPs_SetHash( pxEMAC_PS, ( void * ) xMDNS_MACAddressIPv6.ucBytes ); + } + #endif /* if ( ipconfigUSE_IPv6 == 0 ) */ + } + #endif /* ( ipconfigUSE_MDNS == 1 ) */ + + #if ( ipconfigUSE_IPv6 != 0 ) + { + /* set the solicited-node multicast address */ + for( NetworkEndPoint_t * pxEndPointIter = FreeRTOS_FirstEndPoint( pxInterface ); + pxEndPointIter != NULL; + pxEndPointIter = FreeRTOS_NextEndPoint( pxInterface, pxEndPointIter ) ) + { + if( pxEndPointIter->bits.bIPv6 != pdFALSE_UNSIGNED ) + { + unsigned char ucSsolicitedNodeMAC[ 6 ] = { 0x33, 0x33, 0xff, 0, 0, 0 }; + ucSsolicitedNodeMAC[ 3 ] = pxEndPointIter->ipv6_settings.xIPAddress.ucBytes[ 13 ]; + ucSsolicitedNodeMAC[ 4 ] = pxEndPointIter->ipv6_settings.xIPAddress.ucBytes[ 14 ]; + ucSsolicitedNodeMAC[ 5 ] = pxEndPointIter->ipv6_settings.xIPAddress.ucBytes[ 15 ]; + XEmacPs_SetHash( pxEMAC_PS, ( void * ) ucSsolicitedNodeMAC ); + } + } + } + #endif /* if ( ipconfigUSE_IPv6 == 0 ) */ + + /* allow reception of multicast addresses programmed into hash (LLMNR or mDNS) */ + XEmacPs_SetOptions( pxEMAC_PS, XEMACPS_MULTICAST_OPTION ); + + /* TODO: is it needed to add the MAC of the second endpoint? */ + pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ); + + if( pxEndPoint != NULL ) + { + /* If there is a second end-point, store the MAC + * address at position 4.*/ + XEmacPs_SetMacAddress( pxEMAC_PS, ( void * ) pxEndPoint->xMACAddress.ucBytes, 4 ); + } + XEmacPs_SetMdioDivisor( pxEMAC_PS, MDC_DIV_224 ); - ulPHYIndex = ulDetectPHY( pxEMAC_PS ); + phy_detected[ xEMACIndex ] = ulDetectPHY( pxEMAC_PS ); - if( ulPHYIndex == ~0U ) + if( phy_detected[ xEMACIndex ] == ~0U ) { FreeRTOS_printf( ( "xEMACInit: No valid PHY was found\n" ) ); - eEMACState = xEMAC_Fatal; + eEMACStates[ xEMACIndex ] = xEMAC_Fatal; break; } - eEMACState = xEMAC_SetupPHY; + eEMACStates[ xEMACIndex ] = xEMAC_SetupPHY; /* Fall through. */ case xEMAC_SetupPHY: - ulLinkSpeed = Phy_Setup_US( pxEMAC_PS, ulPHYIndex ); + ulLinkSpeed = Phy_Setup_US( pxEMAC_PS, phy_detected[ xEMACIndex ] ); if( ulLinkSpeed == XST_FAILURE ) { @@ -258,38 +423,60 @@ BaseType_t xNetworkInterfaceInitialise( void ) 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 ); - eEMACState = xEMAC_WaitPHY; + setup_isr( &( xEMACpsifs[ xEMACIndex ] ) ); + init_dma( &( xEMACpsifs[ xEMACIndex ] ) ); + start_emacps( &( xEMACpsifs[ xEMACIndex ] ) ); + eEMACStates[ xEMACIndex ] = xEMAC_WaitPHY; /* Fall through. */ case xEMAC_WaitPHY: - prvGMACWaitLS( xWaitLinkDelay ); + prvGMACWaitLS( xEMACIndex, xWaitLinkDelay ); - if( xGetPhyLinkStatus() == pdFALSE ) + if( xGetPhyLinkStatus( pxInterface ) == pdFALSE ) { /* The Link Status is not yet high, Stay in 'xEMAC_WaitPHY'. */ break; } - if( xEMACTaskHandle == NULL ) + if( xEMACTaskHandles[ xEMACIndex ] == NULL ) { /* 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 + * to it. The task's handle is stored in xEMACTaskHandles[] so interrupts can * notify the task when there is something to process. */ - xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, niEMAC_HANDLER_TASK_PRIORITY, &xEMACTaskHandle ); + const char * pcTaskName; + + switch( xEMACIndex ) + { + case 1: + pcTaskName = "EMAC1"; + break; + + case 2: + pcTaskName = "EMAC2"; + break; + + case 3: + pcTaskName = "EMAC3"; + break; + + case 0: + default: + pcTaskName = "EMAC0"; + break; + } - if( xEMACTaskHandle == NULL ) + xTaskCreate( prvEMACHandlerTask, pcTaskName, configEMAC_TASK_STACK_SIZE, ( void * ) xEMACIndex, niEMAC_HANDLER_TASK_PRIORITY, &( xEMACTaskHandles[ xEMACIndex ] ) ); + + if( xEMACTaskHandles[ xEMACIndex ] == NULL ) { - eEMACState = xEMAC_Fatal; + eEMACStates[ xEMACIndex ] = xEMAC_Fatal; break; } } - eEMACState = xEMAC_Ready; + eEMACStates[ xEMACIndex ] = xEMAC_Ready; /* Fall through. */ @@ -307,11 +494,17 @@ BaseType_t xNetworkInterfaceInitialise( void ) return xReturn; } -/*-----------------------------------------------------------*/ -BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxBuffer, - BaseType_t bReleaseAfterSend ) +/*-----------------------------------------------------------*/ +static BaseType_t xUltrascaleNetworkInterfaceOutput( NetworkInterface_t * pxInterface, + NetworkBufferDescriptor_t * const pxBuffer, + BaseType_t bReleaseAfterSend ) { + BaseType_t xEMACIndex = ( BaseType_t ) pxInterface->pvArgument; + + configASSERT( xEMACIndex >= 0 ); + configASSERT( xEMACIndex < XPAR_XEMACPS_NUM_INSTANCES ); + #if ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 ) { ProtocolPacket_t * pxPacket; @@ -320,22 +513,37 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxBuffer, * the protocol checksum to have a value of zero. */ pxPacket = ( ProtocolPacket_t * ) ( pxBuffer->pucEthernetBuffer ); + #if ( ipconfigUSE_IPv6 != 0 ) + ICMPPacket_IPv6_t * pxICMPPacket = ( ICMPPacket_IPv6_t * ) pxBuffer->pucEthernetBuffer; + + if( ( pxPacket->xICMPPacket.xEthernetHeader.usFrameType == ipIPv6_FRAME_TYPE ) && + ( pxICMPPacket->xIPHeader.ucNextHeader == ipPROTOCOL_ICMP_IPv6 ) ) + { + /* The EMAC will calculate the checksum of the IP-header. + * It can only calculate protocol checksums of UDP and TCP, + * so for ICMP and other protocols it must be done manually. */ + usGenerateProtocolChecksum( pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength, pdTRUE ); + } + #endif /* ipconfigUSE_IPv6 */ + if( ( pxPacket->xICMPPacket.xEthernetHeader.usFrameType == ipIPv4_FRAME_TYPE ) && - ( pxPacket->xICMPPacket.xIPHeader.ucProtocol != ipPROTOCOL_UDP ) && - ( pxPacket->xICMPPacket.xIPHeader.ucProtocol != ipPROTOCOL_TCP ) ) + ( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ipPROTOCOL_ICMP ) ) { /* The EMAC will calculate the checksum of the IP-header. * It can only calculate protocol checksums of UDP and TCP, * so for ICMP and other protocols it must be done manually. */ - usGenerateProtocolChecksum( ( uint8_t * ) &( pxPacket->xUDPPacket ), pxBuffer->xDataLength, pdTRUE ); + usGenerateProtocolChecksum( pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength, pdTRUE ); } } #endif /* ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM */ - if( ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) != 0UL ) + if( ( ulPHYLinkStates[ xEMACIndex ] & niBMSR_LINK_STATUS ) != 0UL ) { iptraceNETWORK_INTERFACE_TRANSMIT(); - emacps_send_message( &xEMACpsif, pxBuffer, bReleaseAfterSend ); + + /* emacps_send_message() will take ownership of pxBuffer, and + * make sure it will get release when bReleaseAfterSend is pdTRUE. */ + emacps_send_message( &( xEMACpsifs[ xEMACIndex ] ), pxBuffer, bReleaseAfterSend ); } else if( bReleaseAfterSend != pdFALSE ) { @@ -347,16 +555,18 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxBuffer, } /*-----------------------------------------------------------*/ -static inline unsigned long ulReadMDIO( unsigned ulRegister ) +static inline unsigned long ulReadMDIO( BaseType_t xEMACIndex, + unsigned ulRegister ) { uint16_t usValue; - XEmacPs_PhyRead( &( xEMACpsif.emacps ), ulPHYIndex, ulRegister, &usValue ); + XEmacPs_PhyRead( &( xEMACpsifs[ xEMACIndex ].emacps ), phy_detected[ xEMACIndex ], ulRegister, &usValue ); return usValue; } /*-----------------------------------------------------------*/ -static BaseType_t prvGMACWaitLS( TickType_t xMaxTimeTicks ) +static BaseType_t prvGMACWaitLS( BaseType_t xEMACIndex, + TickType_t xMaxTimeTicks ) { TickType_t xStartTime, xEndTime; const TickType_t xShortDelay = pdMS_TO_TICKS( 20UL ); @@ -374,9 +584,9 @@ static BaseType_t prvGMACWaitLS( TickType_t xMaxTimeTicks ) break; } - ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR ); + ulPHYLinkStates[ xEMACIndex ] = ulReadMDIO( xEMACIndex, PHY_REG_01_BMSR ); - if( ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) != 0uL ) + if( ( ulPHYLinkStates[ xEMACIndex ] & niBMSR_LINK_STATUS ) != 0uL ) { xReturn = pdTRUE; break; @@ -429,11 +639,12 @@ static BaseType_t prvGMACWaitLS( TickType_t xMaxTimeTicks ) #endif /* ( nicUSE_UNCACHED_MEMORY == 0 ) */ /*-----------------------------------------------------------*/ -BaseType_t xGetPhyLinkStatus( void ) +static BaseType_t xUltrascaleGetPhyLinkStatus( NetworkInterface_t * pxInterface ) { BaseType_t xReturn; + BaseType_t xEMACIndex = ( BaseType_t ) pxInterface->pvArgument; - if( ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) == 0uL ) + if( ( ulPHYLinkStates[ xEMACIndex ] & niBMSR_LINK_STATUS ) == 0uL ) { xReturn = pdFALSE; } @@ -444,6 +655,56 @@ BaseType_t xGetPhyLinkStatus( void ) return xReturn; } + +/*-----------------------------------------------------------*/ +#if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 1 ) + +/* Do not call the following function directly. It is there for downward compatibility. + * The function FreeRTOS_IPInit() will call it to initialise the interface and end-point + * objects. See the description in FreeRTOS_Routing.h. */ + NetworkInterface_t * pxFillInterfaceDescriptor( BaseType_t xEMACIndex, + NetworkInterface_t * pxInterface ) + { + pxUltrascale_FillInterfaceDescriptor( xEMACIndex, pxInterface ); + } +#endif + +NetworkInterface_t * pxUltrascale_FillInterfaceDescriptor( BaseType_t xEMACIndex, + NetworkInterface_t * pxInterface ) +{ + static char pcNames[ XPAR_XEMACPS_NUM_INSTANCES ][ 8 ]; + + configASSERT( xEMACIndex >= 0 ); + configASSERT( xEMACIndex < XPAR_XEMACPS_NUM_INSTANCES ); + +/* This function pxZynq_FillInterfaceDescriptor() adds a network-interface. + * Make sure that the object pointed to by 'pxInterface' + * is declared static or global, and that it will remain to exist. */ + + strcpy( pcNames[ xEMACIndex ], "ETH" ); + uint8_t temp = strlen( pcNames[ xEMACIndex ] ); + pcNames[ xEMACIndex ][ temp ] = ( char ) xEMACIndex + '0'; + pcNames[ xEMACIndex ][ temp + 1 ] = '\0'; + + memset( pxInterface, '\0', sizeof( *pxInterface ) ); + pxInterface->pcName = pcNames[ xEMACIndex ]; /* Just for logging, debugging. */ + pxInterface->pvArgument = ( void * ) xEMACIndex; /* Has meaning only for the driver functions. */ + pxInterface->pfInitialise = xUltrascaleNetworkInterfaceInitialise; + pxInterface->pfOutput = xUltrascaleNetworkInterfaceOutput; + pxInterface->pfGetPhyLinkStatus = xUltrascaleGetPhyLinkStatus; + + FreeRTOS_AddNetworkInterface( pxInterface ); + + return pxInterface; +} + +/*-----------------------------------------------------------*/ + +BaseType_t xGetPhyLinkStatus( struct xNetworkInterface * pxInterface ) +{ + return xUltrascaleGetPhyLinkStatus( pxInterface ); +} + /*-----------------------------------------------------------*/ static void prvEMACHandlerTask( void * pvParameters ) @@ -454,8 +715,13 @@ static void prvEMACHandlerTask( void * pvParameters ) uint32_t xStatus; const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL ); - /* Remove compiler warnings about unused parameters. */ - ( void ) pvParameters; + BaseType_t xEMACIndex = ( BaseType_t ) pvParameters; + xemacpsif_s * pxEMAC_PS; + + configASSERT( xEMACIndex >= 0 ); + configASSERT( xEMACIndex < XPAR_XEMACPS_NUM_INSTANCES ); + + pxEMAC_PS = &( xEMACpsifs[ xEMACIndex ] ); /* A possibility to set some additional task properties like calling * portTASK_USES_FLOATING_POINT() */ @@ -463,6 +729,7 @@ static void prvEMACHandlerTask( void * pvParameters ) vTaskSetTimeOutState( &xPhyTime ); xPhyRemTime = pdMS_TO_TICKS( ipconfigPHY_LS_LOW_CHECK_TIME_MS ); + FreeRTOS_printf( ( "prvEMACHandlerTask[ %ld ] started running\n", xEMACIndex ) ); for( ; ; ) { @@ -475,28 +742,28 @@ static void prvEMACHandlerTask( void * pvParameters ) } #endif /* ( ipconfigHAS_PRINTF != 0 ) */ - if( ( xEMACpsif.isr_events & EMAC_IF_ALL_EVENT ) == 0 ) + if( ( pxEMAC_PS->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 ) + if( ( pxEMAC_PS->isr_events & EMAC_IF_RX_EVENT ) != 0 ) { - xEMACpsif.isr_events &= ~EMAC_IF_RX_EVENT; - xResult = emacps_check_rx( &xEMACpsif ); + pxEMAC_PS->isr_events &= ~EMAC_IF_RX_EVENT; + xResult = emacps_check_rx( pxEMAC_PS, pxMyInterfaces[ xEMACIndex ] ); } - if( ( xEMACpsif.isr_events & EMAC_IF_TX_EVENT ) != 0 ) + if( ( pxEMAC_PS->isr_events & EMAC_IF_TX_EVENT ) != 0 ) { - xEMACpsif.isr_events &= ~EMAC_IF_TX_EVENT; - emacps_check_tx( &xEMACpsif ); + pxEMAC_PS->isr_events &= ~EMAC_IF_TX_EVENT; + emacps_check_tx( pxEMAC_PS ); } - if( ( xEMACpsif.isr_events & EMAC_IF_ERR_EVENT ) != 0 ) + if( ( pxEMAC_PS->isr_events & EMAC_IF_ERR_EVENT ) != 0 ) { - xEMACpsif.isr_events &= ~EMAC_IF_ERR_EVENT; - emacps_check_errors( &xEMACpsif ); + pxEMAC_PS->isr_events &= ~EMAC_IF_ERR_EVENT; + emacps_check_errors( pxEMAC_PS ); } if( xResult > 0 ) @@ -507,27 +774,27 @@ static void prvEMACHandlerTask( void * pvParameters ) xPhyRemTime = pdMS_TO_TICKS( ipconfigPHY_LS_HIGH_CHECK_TIME_MS ); xResult = 0; - if( ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) == 0uL ) + if( ( ulPHYLinkStates[ xEMACIndex ] & niBMSR_LINK_STATUS ) == 0uL ) { /* Indicate that the Link Status is high, so that * xNetworkInterfaceOutput() can send packets. */ - ulPHYLinkStatus |= niBMSR_LINK_STATUS; + ulPHYLinkStates[ xEMACIndex ] |= niBMSR_LINK_STATUS; FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS assume 1\n" ) ); } } else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE ) { - xStatus = ulReadMDIO( PHY_REG_01_BMSR ); + xStatus = ulReadMDIO( xEMACIndex, PHY_REG_01_BMSR ); - if( ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) != ( xStatus & niBMSR_LINK_STATUS ) ) + if( ( ulPHYLinkStates[ xEMACIndex ] & niBMSR_LINK_STATUS ) != ( xStatus & niBMSR_LINK_STATUS ) ) { - ulPHYLinkStatus = xStatus; - FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) != 0uL ) ); + ulPHYLinkStates[ xEMACIndex ] = xStatus; + FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStates[ xEMACIndex ] & niBMSR_LINK_STATUS ) != 0uL ) ); } vTaskSetTimeOutState( &xPhyTime ); - if( ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) != 0uL ) + if( ( ulPHYLinkStates[ xEMACIndex ] & niBMSR_LINK_STATUS ) != 0uL ) { xPhyRemTime = pdMS_TO_TICKS( ipconfigPHY_LS_HIGH_CHECK_TIME_MS ); } diff --git a/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif.h b/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif.h index 12522e564..9171f509a 100644 --- a/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif.h +++ b/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif.h @@ -21,6 +21,8 @@ #include + #include "FreeRTOS_Routing.h" + #include "xstatus.h" #include "sleep.h" #include "xparameters.h" @@ -117,7 +119,8 @@ struct xNETWORK_BUFFER; - int emacps_check_rx( xemacpsif_s * xemacpsif ); + int emacps_check_rx( xemacpsif_s * xemacpsif, + NetworkInterface_t * pxInterface ); void emacps_check_tx( xemacpsif_s * xemacpsif ); int emacps_check_errors( xemacpsif_s * xemacps ); void emacps_set_rx_buffers( xemacpsif_s * xemacpsif, @@ -133,8 +136,8 @@ extern XStatus init_dma( xemacpsif_s * xemacpsif ); extern void start_emacps( xemacpsif_s * xemacpsif ); - void EmacEnableIntr( void ); - void EmacDisableIntr( void ); + void EmacEnableIntr( int xEMACIndex ); + void EmacDisableIntr( int xEMACIndex ); XStatus init_axi_dma( xemacpsif_s * xemacpsif ); void process_sent_bds( xemacpsif_s * xemacpsif ); @@ -150,8 +153,13 @@ void clean_dma_txdescs( xemacpsif_s * xemacpsif ); void resetrx_on_no_rxdata( xemacpsif_s * xemacpsif ); +/** + * @brief Initialise the interface number 'xIndex'. Do not call directly. + */ + void vInitialiseOnIndex( BaseType_t xIndex ); + #ifdef __cplusplus -} /* extern "C" */ + } /* extern "C" */ #endif #endif /* __NETIF_XAXIEMACIF_H__ */ diff --git a/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_dma.c b/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_dma.c index 34ec35a46..62c7407d3 100644 --- a/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_dma.c +++ b/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_dma.c @@ -95,28 +95,28 @@ #endif /* Defined in NetworkInterface.c */ -extern TaskHandle_t xEMACTaskHandle; +extern TaskHandle_t xEMACTaskHandles[ XPAR_XEMACPS_NUM_INSTANCES ]; /* * 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 }; +static unsigned char * pxDMA_tx_buffers[ XPAR_XEMACPS_NUM_INSTANCES ][ ipconfigNIC_N_TX_DESC ]; /* * 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 }; +static NetworkBufferDescriptor_t * pxDMA_rx_buffers[ XPAR_XEMACPS_NUM_INSTANCES ][ ipconfigNIC_N_RX_DESC ]; /* * The FreeRTOS+TCP port is using a fixed 'topology', which is declared in * ./portable/NetworkInterface/Zynq/NetworkInterface.c */ -extern struct xtopology_t xXTopology; +extern struct xtopology_t xXTopologies[ XPAR_XEMACPS_NUM_INSTANCES ]; -static SemaphoreHandle_t xTXDescriptorSemaphore = NULL; +static SemaphoreHandle_t xTXDescriptorSemaphore[ XPAR_XEMACPS_NUM_INSTANCES ]; /* * The FreeRTOS+TCP port does not make use of "src/xemacps_bdring.c". @@ -128,13 +128,11 @@ static SemaphoreHandle_t xTXDescriptorSemaphore = NULL; int is_tx_space_available( xemacpsif_s * xemacpsif ) { size_t uxCount; + BaseType_t xEMACIndex = xemacpsif->emacps.Config.DeviceId; - /* Just to prevent compiler warnings about unused parameters. */ - ( void ) xemacpsif; - - if( xTXDescriptorSemaphore != NULL ) + if( xTXDescriptorSemaphore[ xEMACIndex ] != NULL ) { - uxCount = ( ( UBaseType_t ) ipconfigNIC_N_TX_DESC ) - uxSemaphoreGetCount( xTXDescriptorSemaphore ); + uxCount = ( ( UBaseType_t ) ipconfigNIC_N_TX_DESC ) - uxSemaphoreGetCount( xTXDescriptorSemaphore[ xEMACIndex ] ); } else { @@ -148,7 +146,8 @@ 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 ); + BaseType_t xEMACIndex = xemacpsif->emacps.Config.DeviceId; + size_t uxCount = ( ( UBaseType_t ) ipconfigNIC_N_TX_DESC ) - uxSemaphoreGetCount( xTXDescriptorSemaphore[ xEMACIndex ] ); /* uxCount is the number of TX descriptors that are in use by the DMA. */ /* When done, "TXBUF_USED" will be set. */ @@ -161,12 +160,12 @@ void emacps_check_tx( xemacpsif_s * xemacpsif ) } { - void * pvBuffer = pxDMA_tx_buffers[ tail ]; + void * pvBuffer = pxDMA_tx_buffers[ xEMACIndex ][ tail ]; NetworkBufferDescriptor_t * pxBuffer; if( pvBuffer != NULL ) { - pxDMA_tx_buffers[ tail ] = NULL; + pxDMA_tx_buffers[ xEMACIndex ][ tail ] = NULL; pxBuffer = pxPacketBuffer_to_NetworkBuffer( pvBuffer ); if( pxBuffer != NULL ) @@ -192,7 +191,7 @@ void emacps_check_tx( xemacpsif_s * xemacpsif ) uxCount--; /* Tell the counting semaphore that one more TX descriptor is available. */ - xSemaphoreGive( xTXDescriptorSemaphore ); + xSemaphoreGive( xTXDescriptorSemaphore[ xEMACIndex ] ); if( ++tail == ipconfigNIC_N_TX_DESC ) { @@ -207,8 +206,10 @@ void emacps_send_handler( void * arg ) { xemacpsif_s * xemacpsif; BaseType_t xHigherPriorityTaskWoken = pdFALSE; + BaseType_t xEMACIndex; xemacpsif = ( xemacpsif_s * ) arg; + xEMACIndex = xemacpsif->emacps.Config.DeviceId; /* This function is called from an ISR. The Xilinx ISR-handler has already * cleared the TXCOMPL and TXSR_USEDREAD status bits in the XEMACPS_TXSR register. @@ -221,9 +222,9 @@ void emacps_send_handler( void * arg ) xemacpsif->isr_events |= EMAC_IF_TX_EVENT; xemacpsif->txBusy = pdFALSE; - if( xEMACTaskHandle != NULL ) + if( xEMACTaskHandles[ xEMACIndex ] != NULL ) { - vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken ); + vTaskNotifyGiveFromISR( xEMACTaskHandles[ xEMACIndex ], &xHigherPriorityTaskWoken ); } portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); @@ -252,6 +253,7 @@ XStatus emacps_send_message( xemacpsif_s * xemacpsif, int head = xemacpsif->txHead; int iHasSent = 0; uint32_t ulBaseAddress = xemacpsif->emacps.Config.BaseAddress; + BaseType_t xEMACIndex = xemacpsif->emacps.Config.DeviceId; TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 5000U ); /* This driver wants to own all network buffers which are to be transmitted. */ @@ -267,19 +269,19 @@ XStatus emacps_send_message( xemacpsif_s * xemacpsif, break; } - if( xTXDescriptorSemaphore == NULL ) + if( xTXDescriptorSemaphore[ xEMACIndex ] == NULL ) { break; } - if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS ) + if( xSemaphoreTake( xTXDescriptorSemaphore[ xEMACIndex ], xBlockTimeTicks ) != pdPASS ) { FreeRTOS_printf( ( "emacps_send_message: Time-out waiting for TX buffer\n" ) ); break; } /* Pass the pointer (and its ownership) directly to DMA. */ - pxDMA_tx_buffers[ head ] = pxBuffer->pucEthernetBuffer; + pxDMA_tx_buffers[ xEMACIndex ][ head ] = pxBuffer->pucEthernetBuffer; if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 ) { @@ -300,7 +302,7 @@ XStatus emacps_send_message( xemacpsif_s * xemacpsif, } /* Copy the address of the buffer and set the flags. */ - xemacpsif->txSegments[ head ].address = ( uintptr_t ) pxDMA_tx_buffers[ head ]; + xemacpsif->txSegments[ head ].address = ( uintptr_t ) pxDMA_tx_buffers[ xEMACIndex ][ head ]; xemacpsif->txSegments[ head ].flags = ulFlags; iHasSent = pdTRUE; @@ -347,15 +349,16 @@ void emacps_recv_handler( void * arg ) xemacpsif = ( xemacpsif_s * ) arg; xemacpsif->isr_events |= EMAC_IF_RX_EVENT; + BaseType_t xEMACIndex = xemacpsif->emacps.Config.DeviceId; /* The driver has already cleared the FRAMERX, BUFFNA and error bits * in the XEMACPS_RXSR register, * But it forgets to do a read-back. Do so now. */ ( void ) XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXSR_OFFSET ); - if( xEMACTaskHandle != NULL ) + if( xEMACTaskHandles[ xEMACIndex ] != NULL ) { - vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken ); + vTaskNotifyGiveFromISR( xEMACTaskHandles[ xEMACIndex ], &xHigherPriorityTaskWoken ); } portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); @@ -392,12 +395,88 @@ static void prvPassEthMessages( NetworkBufferDescriptor_t * pxDescriptor ) } } -int emacps_check_rx( xemacpsif_s * xemacpsif ) +BaseType_t xMayAcceptPacket( uint8_t * pucEthernetBuffer ) +{ + const ProtocolPacket_t * pxProtPacket = ( const ProtocolPacket_t * ) pucEthernetBuffer; + + switch( pxProtPacket->xTCPPacket.xEthernetHeader.usFrameType ) + { + case ipARP_FRAME_TYPE: + /* Check it later. */ + return pdTRUE; + + case ipIPv6_FRAME_TYPE: + /* Check it later. */ + return pdTRUE; + + case ipIPv4_FRAME_TYPE: + /* Check it here. */ + break; + + default: + /* Refuse the packet. */ + return pdFALSE; + } + + #if ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 ) + { + const IPHeader_t * pxIPHeader = &( pxProtPacket->xTCPPacket.xIPHeader ); + + /* Ensure that the incoming packet is not fragmented (only outgoing packets + * can be fragmented) as these are the only handled IP frames currently. */ + if( ( pxIPHeader->usFragmentOffset & FreeRTOS_ntohs( ipFRAGMENT_OFFSET_BIT_MASK ) ) != 0U ) + { + return pdFALSE; + } + + /* HT: Might want to make the following configurable because + * most IP messages have a standard length of 20 bytes */ + + /* 0x45 means: IPv4 with an IP header of 5 x 4 = 20 bytes + * 0x47 means: IPv4 with an IP header of 7 x 4 = 28 bytes */ + if( ( pxIPHeader->ucVersionHeaderLength < 0x45 ) || ( pxIPHeader->ucVersionHeaderLength > 0x4F ) ) + { + return pdFALSE; + } + + if( pxIPHeader->ucProtocol == ipPROTOCOL_UDP ) + { + uint16_t usSourcePort = FreeRTOS_ntohs( pxProtPacket->xUDPPacket.xUDPHeader.usSourcePort ); + uint16_t usDestinationPort = FreeRTOS_ntohs( pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort ); + + if( ( xPortHasUDPSocket( pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort ) == pdFALSE ) + #if ipconfigUSE_LLMNR == 1 + && ( usDestinationPort != ipLLMNR_PORT ) && + ( usSourcePort != ipLLMNR_PORT ) + #endif + #if ipconfigUSE_NBNS == 1 + && ( usDestinationPort != ipNBNS_PORT ) && + ( usSourcePort != ipNBNS_PORT ) + #endif + #if ipconfigUSE_DNS == 1 + && ( usSourcePort != ipDNS_PORT ) + #endif + ) + { + /* Drop this packet, not for this device. */ + /* FreeRTOS_printf( ( "Drop: UDP port %d -> %d\n", usSourcePort, usDestinationPort ) ); */ + return pdFALSE; + } + } + } + #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */ + return pdTRUE; +} + +int emacps_check_rx( xemacpsif_s * xemacpsif, + NetworkInterface_t * pxInterface ) { NetworkBufferDescriptor_t * pxBuffer, * pxNewBuffer; int rx_bytes; volatile int msgCount = 0; int head = xemacpsif->rxHead; + BaseType_t xEMACIndex = xemacpsif->emacps.Config.DeviceId; + BaseType_t xAccepted; #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) NetworkBufferDescriptor_t * pxFirstDescriptor = NULL; @@ -413,26 +492,40 @@ int emacps_check_rx( xemacpsif_s * xemacpsif ) for( ; ; ) { if( ( ( xemacpsif->rxSegments[ head ].address & XEMACPS_RXBUF_NEW_MASK ) == 0 ) || - ( pxDMA_rx_buffers[ head ] == NULL ) ) + ( pxDMA_rx_buffers[ xEMACIndex ][ head ] == NULL ) ) { break; } - pxNewBuffer = pxGetNetworkBufferWithDescriptor( dmaRX_TX_BUFFER_SIZE, ( TickType_t ) 0 ); + pxBuffer = ( NetworkBufferDescriptor_t * ) pxDMA_rx_buffers[ xEMACIndex ][ head ]; + xAccepted = xMayAcceptPacket( pxBuffer->pucEthernetBuffer ); - if( pxNewBuffer == NULL ) + if( xAccepted == pdFALSE ) { - /* 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 Network Buffer\n" ) ); - pxNewBuffer = ( NetworkBufferDescriptor_t * ) pxDMA_rx_buffers[ head ]; + pxNewBuffer = NULL; } else { - pxBuffer = ( NetworkBufferDescriptor_t * ) pxDMA_rx_buffers[ head ]; + pxNewBuffer = pxGetNetworkBufferWithDescriptor( dmaRX_TX_BUFFER_SIZE, ( 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 Network Buffer\n" ) ); + } + } + + if( pxNewBuffer == NULL ) + { + pxNewBuffer = ( NetworkBufferDescriptor_t * ) pxDMA_rx_buffers[ xEMACIndex ][ head ]; + } + else + { + pxBuffer->pxInterface = pxInterface; + pxBuffer->pxEndPoint = FreeRTOS_MatchingEndpoint( pxInterface, pxBuffer->pucEthernetBuffer ); /* Just avoiding to use or refer to the same buffer again */ - pxDMA_rx_buffers[ head ] = pxNewBuffer; + pxDMA_rx_buffers[ xEMACIndex ][ head ] = pxNewBuffer; /* * Adjust the buffer size to the actual number of bytes received. @@ -531,12 +624,13 @@ int emacps_check_rx( xemacpsif_s * xemacpsif ) void clean_dma_txdescs( xemacpsif_s * xemacpsif ) { int index; + BaseType_t xEMACIndex = xemacpsif->emacps.Config.DeviceId; for( index = 0; index < ipconfigNIC_N_TX_DESC; index++ ) { xemacpsif->txSegments[ index ].address = ( uintptr_t ) NULL; xemacpsif->txSegments[ index ].flags = XEMACPS_TXBUF_USED_MASK; - pxDMA_tx_buffers[ index ] = ( unsigned char * ) NULL; + pxDMA_tx_buffers[ xEMACIndex ][ index ] = ( unsigned char * ) NULL; } xemacpsif->txSegments[ ipconfigNIC_N_TX_DESC - 1 ].flags = @@ -546,11 +640,12 @@ void clean_dma_txdescs( xemacpsif_s * xemacpsif ) XStatus init_dma( xemacpsif_s * xemacpsif ) { NetworkBufferDescriptor_t * pxBuffer; + BaseType_t xEMACIndex = xemacpsif->emacps.Config.DeviceId; int iIndex; UBaseType_t xRxSize; UBaseType_t xTxSize; - struct xtopology_t * xtopologyp = &xXTopology; + struct xtopology_t * xtopologyp = &xXTopologies[ xEMACIndex ]; XEmacPs_BdRing * rxRing; XEmacPs * emac = &( xemacpsif->emacps ); XEmacPs_Bd bdTemplate; @@ -596,10 +691,10 @@ XStatus init_dma( xemacpsif_s * xemacpsif ) return status; } - if( xTXDescriptorSemaphore == NULL ) + if( xTXDescriptorSemaphore[ xEMACIndex ] == NULL ) { - xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ipconfigNIC_N_TX_DESC, ( UBaseType_t ) ipconfigNIC_N_TX_DESC ); - configASSERT( xTXDescriptorSemaphore != NULL ); + xTXDescriptorSemaphore[ xEMACIndex ] = xSemaphoreCreateCounting( ( UBaseType_t ) ipconfigNIC_N_TX_DESC, ( UBaseType_t ) ipconfigNIC_N_TX_DESC ); + configASSERT( xTXDescriptorSemaphore[ xEMACIndex ] != NULL ); } /* @@ -607,7 +702,7 @@ XStatus init_dma( xemacpsif_s * xemacpsif ) */ for( iIndex = 0; iIndex < ipconfigNIC_N_RX_DESC; iIndex++ ) { - pxBuffer = pxDMA_rx_buffers[ iIndex ]; + pxBuffer = pxDMA_rx_buffers[ xEMACIndex ][ iIndex ]; if( pxBuffer == NULL ) { @@ -642,7 +737,7 @@ XStatus init_dma( xemacpsif_s * xemacpsif ) xemacpsif->rxSegments[ iIndex ].reserved = iIndex; #endif - pxDMA_rx_buffers[ iIndex ] = pxBuffer; + pxDMA_rx_buffers[ xEMACIndex ][ iIndex ] = pxBuffer; /* Make sure this memory is not in cache for now. */ if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 ) @@ -728,15 +823,12 @@ XStatus init_dma( xemacpsif_s * xemacpsif ) XEmacPs_SetQueuePtr( emac, ( uintptr_t ) xemacpsif->txSegments, 0, XEMACPS_SEND ); } - XScuGic_Connect( &xInterruptController, - xtopologyp->scugic_emac_intr, - XEmacPs_IntrHandler, - emac ); + XScuGic_Connect( &xInterruptController, xtopologyp->scugic_emac_intr, XEmacPs_IntrHandler, emac ); /* * Enable the interrupt for emacps. */ - EmacEnableIntr(); + EmacEnableIntr( xEMACIndex ); return 0; } @@ -777,12 +869,12 @@ void resetrx_on_no_rxdata( xemacpsif_s * xemacpsif ) xemacpsif->last_rx_frms_cntr = tempcntr; } -void EmacDisableIntr( void ) +void EmacDisableIntr( int xEMACIndex ) { - XScuGic_DisableIntr( INTC_DIST_BASE_ADDR, xXTopology.scugic_emac_intr ); + XScuGic_Disable( &xInterruptController, xXTopologies[ xEMACIndex ].scugic_emac_intr ); } -void EmacEnableIntr( void ) +void EmacEnableIntr( int xEMACIndex ) { - XScuGic_Enable( &xInterruptController, xXTopology.scugic_emac_intr ); + XScuGic_Enable( &xInterruptController, xXTopologies[ xEMACIndex ].scugic_emac_intr ); } diff --git a/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_hw.c b/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_hw.c index 03db01d3b..950ea9ceb 100644 --- a/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_hw.c +++ b/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_hw.c @@ -35,8 +35,9 @@ #include "NetworkInterface.h" #include "x_emacpsif.h" +#include "x_topology.h" -extern TaskHandle_t xEMACTaskHandle; +extern TaskHandle_t xEMACTaskHandles[ XPAR_XEMACPS_NUM_INSTANCES ]; /*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c *** to run it on a PEEP board @@ -65,7 +66,7 @@ void start_emacps( xemacpsif_s * xemacps ) XEmacPs_Start( &xemacps->emacps ); } -extern struct xtopology_t xXTopology; +extern struct xtopology_t xXTopologies[ XPAR_XEMACPS_NUM_INSTANCES ]; volatile int error_msg_count = 0; volatile const char * last_err_msg = ""; @@ -87,8 +88,10 @@ void emacps_error_handler( void * arg, BaseType_t xHigherPriorityTaskWoken = pdFALSE; xemacpsif_s * xemacpsif; BaseType_t xNextHead = xErrorHead; + BaseType_t xEMACIndex; xemacpsif = ( xemacpsif_s * ) ( arg ); + xEMACIndex = xemacpsif->emacps.Config.DeviceId; if( ( Direction != XEMACPS_SEND ) || ( ErrorWord != XEMACPS_TXSR_USEDREAD_MASK ) ) { @@ -109,9 +112,9 @@ void emacps_error_handler( void * arg, xemacpsif->isr_events |= EMAC_IF_ERR_EVENT; } - if( xEMACTaskHandle != NULL ) + if( xEMACTaskHandles[ xEMACIndex ] != NULL ) { - vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken ); + vTaskNotifyGiveFromISR( xEMACTaskHandles[ xEMACIndex ], &xHigherPriorityTaskWoken ); } } @@ -152,9 +155,14 @@ static void emacps_handle_error( void * arg, struct xtopology_t * xtopologyp; XEmacPs * xemacps; + BaseType_t xEMACIndex; + xemacpsif = ( xemacpsif_s * ) ( arg ); - xtopologyp = &xXTopology; + xemacps = &xemacpsif->emacps; + xEMACIndex = xemacps->Config.DeviceId; + + xtopologyp = &xXTopologies[ xEMACIndex ]; xemacps = &xemacpsif->emacps; @@ -173,7 +181,7 @@ static void emacps_handle_error( void * arg, if( ( ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK ) != 0 ) { last_err_msg = "Receive DMA error"; - xNetworkInterfaceInitialise(); + vInitialiseOnIndex( xEMACIndex ); } if( ( ErrorWord & XEMACPS_RXSR_RXOVR_MASK ) != 0 ) @@ -195,7 +203,7 @@ static void emacps_handle_error( void * arg, if( ( ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK ) != 0 ) { last_err_msg = "Transmit DMA error"; - xNetworkInterfaceInitialise(); + vInitialiseOnIndex( xEMACIndex ); } if( ( ErrorWord & XEMACPS_TXSR_URUN_MASK ) != 0 ) diff --git a/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_hw.h b/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_hw.h index 7656579f6..2c525027c 100644 --- a/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_hw.h +++ b/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_hw.h @@ -20,7 +20,6 @@ #define __XEMACPSIF_HW_H_ #include "x_emacpsif.h" -/*#include "lwip/netif.h" */ #ifdef __cplusplus extern "C" { @@ -28,8 +27,6 @@ XEmacPs_Config * lookup_config( unsigned mac_base ); -/*void init_emacps(xemacpsif_s *xemacpsif, struct netif *netif); */ - int emacps_check_errors( xemacpsif_s * xemacps ); /* Defined in x_emacpsif_physpeed.c. */ @@ -37,7 +34,7 @@ #ifdef __cplusplus -} /* extern "C" */ + } /* extern "C" */ #endif #endif /* ifndef __XEMACPSIF_HW_H_ */ diff --git a/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_physpeed.c b/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_physpeed.c index 7960b8d31..f34f165f7 100644 --- a/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_physpeed.c +++ b/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_physpeed.c @@ -54,7 +54,6 @@ #include #include "x_emacpsif.h" -/*#include "lwipopts.h" */ #include "xparameters_ps.h" #include "xparameters.h" @@ -69,6 +68,7 @@ #include "FreeRTOS_IP.h" #include "FreeRTOS_Sockets.h" #include "FreeRTOS_IP_Private.h" +#include "FreeRTOS_Routing.h" #include "NetworkBufferManagement.h" #define phyMIN_PHY_ADDRESS 0 @@ -76,9 +76,8 @@ #define MINIMUM_SLEEP_TIME ( ( TickType_t ) 1 * configTICK_RATE_HZ ) -/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c - *** to run it on a PEEP board - ***/ + +uint32_t phy_detected[ 4 ]; /* Advertisement control register. */ #define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */ @@ -226,8 +225,6 @@ #define GEM_VERSION_ZYNQMP 7 #define GEM_VERSION_VERSAL 0x107 -u32 phymapemac0[ 32 ]; -u32 phymapemac1[ 32 ]; static uint16_t prvAR803x_debug_reg_write( XEmacPs * xemacpsp, uint32_t phy_addr, @@ -912,7 +909,7 @@ static uint32_t ar8035CheckStatus( XEmacPs * xemacpsp, static const char * pcGetPHIName( uint16_t usID ) { const char * pcReturn = ""; - static char pcName[ 16 ]; + static char pcName[ 32 ]; switch( usID ) { @@ -973,8 +970,6 @@ static uint32_t get_IEEE_phy_speed_US( XEmacPs * xemacpsp, case PHY_AR8035_IDENTIFIER: RetStatus = get_AR8035_phy_speed( xemacpsp, phy_addr ); - /* RetStatus = get_Marvell_phy_speed(xemacpsp, phy_addr); */ - /* RetStatus = get_Realtek_phy_speed(xemacpsp, phy_addr); */ prvSET_AR803x_TX_Timing( xemacpsp, phy_addr ); break; diff --git a/source/portable/NetworkInterface/xilinx_ultrascale/x_topology.h b/source/portable/NetworkInterface/xilinx_ultrascale/x_topology.h index 2ed411c79..4fb93cb85 100644 --- a/source/portable/NetworkInterface/xilinx_ultrascale/x_topology.h +++ b/source/portable/NetworkInterface/xilinx_ultrascale/x_topology.h @@ -38,13 +38,8 @@ 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 -} /* extern "C" */ + } /* extern "C" */ #endif #endif /* __XTOPOLOGY_H_ */ From e448ae8d8e595ff9d6013f0f0e627762bb07cb11 Mon Sep 17 00:00:00 2001 From: Stefan Baltruweit Date: Wed, 11 Sep 2024 17:00:59 +0200 Subject: [PATCH 02/11] Use MAC hash table for IPv4 LLMNR This is how it is supposed to be used. Also the set of the multi-cast hash enable bit was missing. --- .../NetworkInterface/xilinx_ultrascale/NetworkInterface.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c b/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c index a4612b956..b3561372b 100644 --- a/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c +++ b/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c @@ -325,8 +325,7 @@ static BaseType_t xUltrascaleNetworkInterfaceInitialise( NetworkInterface_t * px { #if ( ipconfigUSE_IPv6 == 0 ) { - /* Also add LLMNR multicast MAC address. */ - XEmacPs_SetMacAddress( pxEMAC_PS, ( void * ) xLLMNR_MacAddress.ucBytes, 2 ); + XEmacPs_SetHash( pxEMAC_PS, ( void * ) xLLMNR_MacAddress.ucBytes ); } #else { From 9dc75a32fbb962054130d89a0addd5edc3e128ef Mon Sep 17 00:00:00 2001 From: Stefan Baltruweit Date: Thu, 12 Sep 2024 14:10:27 +0200 Subject: [PATCH 03/11] Use XEmacPs_DMABLengthUpdate() API The same effect can be achieved but the code is simpler. --- .../NetworkInterface/xilinx_ultrascale/NetworkInterface.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c b/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c index b3561372b..e9c8fe7a3 100644 --- a/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c +++ b/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c @@ -413,14 +413,8 @@ static BaseType_t xUltrascaleNetworkInterfaceInitialise( NetworkInterface_t * px /* 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 ); /* Enable 16-bytes AHB bursts */ - ulDMAReg = ulDMAReg | XEMACPS_DMACR_INCR16_AHB_BURST; - - /* 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*/ ); + XEmacPs_DMABLengthUpdate( pxEMAC_PS, XEMACPS_16BYTE_BURST ); setup_isr( &( xEMACpsifs[ xEMACIndex ] ) ); init_dma( &( xEMACpsifs[ xEMACIndex ] ) ); From 0dbda17ad246582310a0d7d967cefaf8a2f701ff Mon Sep 17 00:00:00 2001 From: Stefan Baltruweit Date: Wed, 11 Sep 2024 17:50:24 +0200 Subject: [PATCH 04/11] Remove Zynq7000 support from Ultrascale port There are already a lot of differences between Zynq and xilinx_ultrascale port, so there is no need to keep compatibility. --- .../xilinx_ultrascale/NetworkInterface.c | 11 +- .../xilinx_ultrascale/uncached_memory.c | 37 ++---- .../xilinx_ultrascale/x_emacpsif_dma.c | 65 +++------- .../xilinx_ultrascale/x_emacpsif_physpeed.c | 120 +----------------- 4 files changed, 42 insertions(+), 191 deletions(-) diff --git a/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c b/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c index e9c8fe7a3..0067c79e6 100644 --- a/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c +++ b/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c @@ -310,13 +310,10 @@ static BaseType_t xUltrascaleNetworkInterfaceInitialise( NetworkInterface_t * px pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); configASSERT( pxEndPoint != NULL ); - if( pxEMAC_PS->Version > 2 ) - { - #if ( USE_JUMBO_FRAMES == 1 ) - /* Enable jumbo frames for zynqmp */ - XEmacPs_SetOptions( pxEMAC_PS, XEMACPS_JUMBO_ENABLE_OPTION ); - #endif - } + #if ( USE_JUMBO_FRAMES == 1 ) + /* Enable jumbo frames for zynqmp */ + XEmacPs_SetOptions( pxEMAC_PS, XEMACPS_JUMBO_ENABLE_OPTION ); + #endif /* Initialize the mac and set the MAC address at position 1. */ XEmacPs_SetMacAddress( pxEMAC_PS, ( void * ) pxEndPoint->xMACAddress.ucBytes, 1 ); diff --git a/source/portable/NetworkInterface/xilinx_ultrascale/uncached_memory.c b/source/portable/NetworkInterface/xilinx_ultrascale/uncached_memory.c index c9035c7fb..18a0d9d6a 100644 --- a/source/portable/NetworkInterface/xilinx_ultrascale/uncached_memory.c +++ b/source/portable/NetworkInterface/xilinx_ultrascale/uncached_memory.c @@ -70,33 +70,24 @@ #include "uncached_memory.h" -#if ( ipconfigULTRASCALE == 1 ) - #if defined( __aarch64__ ) || defined( ARMA53_32 ) - #ifndef uncMEMORY_SIZE - /* Reserve 2 MB of memory. */ - #define uncMEMORY_SIZE 0x200000U - #endif - #define DDR_MEMORY_END ( XPAR_PSU_DDR_0_S_AXI_HIGHADDR ) - #define uncMEMORY_ATTRIBUTE NORM_NONCACHE | INNER_SHAREABLE - #elif defined( ARMR5 ) - #ifndef uncMEMORY_SIZE - /* Reserve 1 MB of memory. */ - #define uncMEMORY_SIZE 0x100000U - #endif - #define uncMEMORY_SIZE 0x100000U - #define DDR_MEMORY_END ( XPAR_PSU_R5_DDR_0_S_AXI_HIGHADDR ) - #define uncMEMORY_ATTRIBUTE STRONG_ORDERD_SHARED | PRIV_RW_USER_RW - #else /* if defined( __aarch64__ ) || defined( ARMA53_32 ) */ - #error Please define the specific target Zynq Ultrascale+ architecture - #endif /* if defined( __aarch64__ ) || defined( ARMA53_32 ) */ -#else /* if ( ipconfigULTRASCALE == 1 ) */ +#if defined( __aarch64__ ) || defined( ARMA53_32 ) + #ifndef uncMEMORY_SIZE + /* Reserve 2 MB of memory. */ + #define uncMEMORY_SIZE 0x200000U + #endif + #define DDR_MEMORY_END ( XPAR_PSU_DDR_0_S_AXI_HIGHADDR ) + #define uncMEMORY_ATTRIBUTE NORM_NONCACHE | INNER_SHAREABLE +#elif defined( ARMR5 ) #ifndef uncMEMORY_SIZE /* Reserve 1 MB of memory. */ #define uncMEMORY_SIZE 0x100000U #endif - #define DDR_MEMORY_END ( XPAR_PS7_DDR_0_S_AXI_HIGHADDR + 1 ) - #define uncMEMORY_ATTRIBUTE 0x1C02 -#endif /* ( ipconfigULTRASCALE == 1 ) */ + #define uncMEMORY_SIZE 0x100000U + #define DDR_MEMORY_END ( XPAR_PSU_R5_DDR_0_S_AXI_HIGHADDR ) + #define uncMEMORY_ATTRIBUTE STRONG_ORDERD_SHARED | PRIV_RW_USER_RW +#else /* if defined( __aarch64__ ) || defined( ARMA53_32 ) */ + #error Please define the specific target Zynq Ultrascale+ architecture +#endif /* if defined( __aarch64__ ) || defined( ARMA53_32 ) */ /* Make sure that each pointer has an alignment of 4 KB. */ #define uncALIGNMENT_SIZE 0x1000uL diff --git a/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_dma.c b/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_dma.c index 62c7407d3..959ff0ab5 100644 --- a/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_dma.c +++ b/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_dma.c @@ -47,29 +47,12 @@ #include "uncached_memory.h" -#ifndef ipconfigULTRASCALE - #error please define ipconfigULTRASCALE -#endif - -/* Two defines used to set or clear the EMAC interrupt */ -#if ( ipconfigULTRASCALE == 1 ) - /* * XPAR_SCUGIC_0_CPU_BASEADDR 0xF9020000U * XPAR_SCUGIC_0_DIST_BASEADDR 0xF9010000U */ - #define INTC_BASE_ADDR XPAR_SCUGIC_0_CPU_BASEADDR - #define INTC_DIST_BASE_ADDR XPAR_SCUGIC_0_DIST_BASEADDR -#else - -/* - * XPAR_SCUGIC_CPU_BASEADDR (XPS_SCU_PERIPH_BASE + 0x00000100U) - * XPAR_SCUGIC_DIST_BASEADDR (XPS_SCU_PERIPH_BASE + 0x00001000U) - */ - - #define INTC_BASE_ADDR XPAR_SCUGIC_CPU_BASEADDR - #define INTC_DIST_BASE_ADDR XPAR_SCUGIC_DIST_BASEADDR -#endif +#define INTC_BASE_ADDR XPAR_SCUGIC_0_CPU_BASEADDR +#define INTC_DIST_BASE_ADDR XPAR_SCUGIC_0_DIST_BASEADDR #if ( ipconfigPACKET_FILLER_SIZE != 2 ) #error Please define ipconfigPACKET_FILLER_SIZE as the value '2' @@ -90,9 +73,7 @@ #define dmaRX_TX_BUFFER_SIZE 1536 #endif /* ( USE_JUMBO_FRAMES == 1 ) */ -#if ( ipconfigULTRASCALE == 1 ) - extern XScuGic xInterruptController; -#endif +extern XScuGic xInterruptController; /* Defined in NetworkInterface.c */ extern TaskHandle_t xEMACTaskHandles[ XPAR_XEMACPS_NUM_INSTANCES ]; @@ -793,35 +774,25 @@ XStatus init_dma( xemacpsif_s * xemacpsif ) } /* Set terminating BDs for US+ GEM */ - if( xemacpsif->emacps.Version > 2 ) - { - xemacpsif->rxBdTerminator = ( struct xBD_TYPE * ) pucGetUncachedMemory( sizeof( *xemacpsif->rxBdTerminator ) ); - xemacpsif->txBdTerminator = ( struct xBD_TYPE * ) pucGetUncachedMemory( sizeof( *xemacpsif->txBdTerminator ) ); - - XEmacPs_BdClear( xemacpsif->rxBdTerminator ); - XEmacPs_BdSetAddressRx( xemacpsif->rxBdTerminator, ( XEMACPS_RXBUF_NEW_MASK | - XEMACPS_RXBUF_WRAP_MASK ) ); - XEmacPs_Out32( ( emac->Config.BaseAddress + XEMACPS_RXQ1BASE_OFFSET ), - ( UINTPTR ) xemacpsif->rxBdTerminator ); - - XEmacPs_BdClear( xemacpsif->txBdTerminator ); - XEmacPs_BdSetStatus( xemacpsif->txBdTerminator, - ( XEMACPS_TXBUF_USED_MASK | XEMACPS_TXBUF_WRAP_MASK ) ); - XEmacPs_Out32( ( emac->Config.BaseAddress + XEMACPS_TXQBASE_OFFSET ), - ( UINTPTR ) xemacpsif->txBdTerminator ); - } + xemacpsif->rxBdTerminator = ( struct xBD_TYPE * ) pucGetUncachedMemory( sizeof( *xemacpsif->rxBdTerminator ) ); + xemacpsif->txBdTerminator = ( struct xBD_TYPE * ) pucGetUncachedMemory( sizeof( *xemacpsif->txBdTerminator ) ); + + XEmacPs_BdClear( xemacpsif->rxBdTerminator ); + XEmacPs_BdSetAddressRx( xemacpsif->rxBdTerminator, ( XEMACPS_RXBUF_NEW_MASK | + XEMACPS_RXBUF_WRAP_MASK ) ); + XEmacPs_Out32( ( emac->Config.BaseAddress + XEMACPS_RXQ1BASE_OFFSET ), + ( UINTPTR ) xemacpsif->rxBdTerminator ); + + XEmacPs_BdClear( xemacpsif->txBdTerminator ); + XEmacPs_BdSetStatus( xemacpsif->txBdTerminator, + ( XEMACPS_TXBUF_USED_MASK | XEMACPS_TXBUF_WRAP_MASK ) ); + XEmacPs_Out32( ( emac->Config.BaseAddress + XEMACPS_TXQBASE_OFFSET ), + ( UINTPTR ) xemacpsif->txBdTerminator ); /* These variables will be used in XEmacPs_Start (see src/xemacps.c). */ XEmacPs_SetQueuePtr( emac, ( uintptr_t ) xemacpsif->rxSegments, 0, XEMACPS_RECV ); - if( xemacpsif->emacps.Version > 2 ) - { - XEmacPs_SetQueuePtr( emac, ( uintptr_t ) xemacpsif->txSegments, 1, XEMACPS_SEND ); - } - else - { - XEmacPs_SetQueuePtr( emac, ( uintptr_t ) xemacpsif->txSegments, 0, XEMACPS_SEND ); - } + XEmacPs_SetQueuePtr( emac, ( uintptr_t ) xemacpsif->txSegments, 1, XEMACPS_SEND ); XScuGic_Connect( &xInterruptController, xtopologyp->scugic_emac_intr, XEmacPs_IntrHandler, emac ); diff --git a/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_physpeed.c b/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_physpeed.c index f34f165f7..c51aee080 100644 --- a/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_physpeed.c +++ b/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_physpeed.c @@ -178,30 +178,6 @@ uint32_t phy_detected[ 4 ]; #define PHY_TI_CRVAL 0x5048 #define PHY_TI_CFG4RESVDBIT7 0x80 -/* 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_GEM_SRCSEL_EMIO 0x40 -#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 ZYNQ_EMACPS_0_BASEADDR 0xE000B000 -#define ZYNQ_EMACPS_1_BASEADDR 0xE000C000 - -#define ZYNQMP_EMACPS_0_BASEADDR 0xFF0B0000 -#define ZYNQMP_EMACPS_1_BASEADDR 0xFF0C0000 -#define ZYNQMP_EMACPS_2_BASEADDR 0xFF0D0000 -#define ZYNQMP_EMACPS_3_BASEADDR 0xFF0E0000 - #define CRL_APB_GEM0_REF_CTRL 0xFF5E0050 #define CRL_APB_GEM1_REF_CTRL 0xFF5E0054 #define CRL_APB_GEM2_REF_CTRL 0xFF5E0058 @@ -985,10 +961,6 @@ static uint32_t get_IEEE_phy_speed_US( XEmacPs * xemacpsp, static void SetUpSLCRDivisors( u32 mac_baseaddr, s32 speed ) { - volatile u32 slcrBaseAddress; - u32 SlcrDiv0 = 0; - u32 SlcrDiv1 = 0; - u32 SlcrTxClkCntrl; u32 gigeversion; volatile u32 CrlApbBaseAddr; u32 CrlApbDiv0 = 0; @@ -997,92 +969,7 @@ static void SetUpSLCRDivisors( u32 mac_baseaddr, gigeversion = ( ( Xil_In32( mac_baseaddr + 0xFC ) ) >> 16 ) & 0xFFF; - if( gigeversion == 2 ) - { - *( volatile u32 * ) ( SLCR_UNLOCK_ADDR ) = SLCR_UNLOCK_KEY_VALUE; - - if( mac_baseaddr == ZYNQ_EMACPS_0_BASEADDR ) - { - slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR; - } - else - { - slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR; - } - - if( ( *( volatile u32 * ) ( UINTPTR ) ( slcrBaseAddress ) ) & - SLCR_GEM_SRCSEL_EMIO ) - { - return; - } - - if( speed == 1000 ) - { - if( mac_baseaddr == XPAR_XEMACPS_0_BASEADDR ) - { - #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( mac_baseaddr == XPAR_XEMACPS_0_BASEADDR ) - { - #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( mac_baseaddr == XPAR_XEMACPS_0_BASEADDR ) - { - #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 - } - } - - if( ( SlcrDiv0 != 0 ) && ( SlcrDiv1 != 0 ) ) - { - SlcrTxClkCntrl = *( volatile u32 * ) ( UINTPTR ) ( slcrBaseAddress ); - SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK; - SlcrTxClkCntrl |= ( SlcrDiv1 << 20 ); - SlcrTxClkCntrl |= ( SlcrDiv0 << 8 ); - *( volatile u32 * ) ( UINTPTR ) ( slcrBaseAddress ) = SlcrTxClkCntrl; - *( volatile u32 * ) ( SLCR_LOCK_ADDR ) = SLCR_LOCK_KEY_VALUE; - } - else - { - FreeRTOS_printf( ( "Clock Divisors incorrect - Please check\n" ) ); - } - } - else if( gigeversion == GEM_VERSION_ZYNQMP ) + if( gigeversion == GEM_VERSION_ZYNQMP ) { /* Setup divisors in CRL_APB for Zynq Ultrascale+ MPSoC */ if( mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR ) @@ -1309,6 +1196,11 @@ static void SetUpSLCRDivisors( u32 mac_baseaddr, FreeRTOS_printf( ( "Clock Divisors incorrect - Please check\n" ) ); } } + else + { + FreeRTOS_printf( ( "Invalid GEM version %u \n", gigeversion ) ); + return; + } } u32 Phy_Setup_US( XEmacPs * xemacpsp, From 1f71d694c5ffa70b20276b3a5c68250b4056d190 Mon Sep 17 00:00:00 2001 From: Stefan Baltruweit Date: Wed, 11 Sep 2024 17:54:28 +0200 Subject: [PATCH 05/11] Add x_emac_map to xilinx_ultrascale port This map makes sure the correct interrupt id is registered in the interrupt controller. E.g. 'XPAR_XEMACPS_0_BASEADDR' is Canonical for the first interface and can be mapped to any of the GEMs. 'XPAR_XEMACPS_0_INTR' on the other hand is fixed to GEM0. This is why this mapping is needed. --- .../xilinx_ultrascale/NetworkInterface.c | 9 ++- .../xilinx_ultrascale/x_emac_map.h | 80 +++++++++++++++++++ .../xilinx_ultrascale/x_emacpsif_physpeed.c | 1 + 3 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 source/portable/NetworkInterface/xilinx_ultrascale/x_emac_map.h diff --git a/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c b/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c index 0067c79e6..d5342b885 100644 --- a/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c +++ b/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c @@ -50,6 +50,7 @@ #include "x_topology.h" #include "x_emacpsif.h" #include "x_emacpsif_hw.h" +#include "x_emac_map.h" /* Provided memory configured as uncached. */ #include "uncached_memory.h" @@ -160,7 +161,7 @@ struct xtopology_t xXTopologies[ XPAR_XEMACPS_NUM_INSTANCES ] = .intc_baseaddr = 0x0, .intc_emac_intr = 0x0, .scugic_baseaddr = XPAR_SCUGIC_0_CPU_BASEADDR, - .scugic_emac_intr = XPAR_XEMACPS_0_INTR, + .scugic_emac_intr = ZYNQMP_EMACPS_0_IRQ_ID, }, #if ( XPAR_XEMACPS_NUM_INSTANCES > 1 ) [ 1 ] = @@ -170,7 +171,7 @@ struct xtopology_t xXTopologies[ XPAR_XEMACPS_NUM_INSTANCES ] = .intc_baseaddr = 0x0, .intc_emac_intr = 0x0, .scugic_baseaddr = XPAR_SCUGIC_0_CPU_BASEADDR, - .scugic_emac_intr = XPAR_XEMACPS_1_INTR, + .scugic_emac_intr = ZYNQMP_EMACPS_1_IRQ_ID, }, #elif ( XPAR_XEMACPS_NUM_INSTANCES > 2 ) [ 2 ] = @@ -180,7 +181,7 @@ struct xtopology_t xXTopologies[ XPAR_XEMACPS_NUM_INSTANCES ] = .intc_baseaddr = 0x0, .intc_emac_intr = 0x0, .scugic_baseaddr = XPAR_SCUGIC_0_CPU_BASEADDR, - .scugic_emac_intr = XPAR_XEMACPS_2_INTR, + .scugic_emac_intr = ZYNQMP_EMACPS_2_IRQ_ID, }, #elif ( XPAR_XEMACPS_NUM_INSTANCES > 3 ) [ 3 ] = @@ -190,7 +191,7 @@ struct xtopology_t xXTopologies[ XPAR_XEMACPS_NUM_INSTANCES ] = .intc_baseaddr = 0x0, .intc_emac_intr = 0x0, .scugic_baseaddr = XPAR_SCUGIC_0_CPU_BASEADDR, - .scugic_emac_intr = XPAR_XEMACPS_3_INTR, + .scugic_emac_intr = ZYNQMP_EMACPS_3_IRQ_ID, }, #endif /* if ( XPAR_XEMACPS_NUM_INSTANCES > 1 ) */ }; diff --git a/source/portable/NetworkInterface/xilinx_ultrascale/x_emac_map.h b/source/portable/NetworkInterface/xilinx_ultrascale/x_emac_map.h new file mode 100644 index 000000000..78bf9804e --- /dev/null +++ b/source/portable/NetworkInterface/xilinx_ultrascale/x_emac_map.h @@ -0,0 +1,80 @@ +/* + * 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 __XEMACMAP_H_ +#define __XEMACMAP_H_ + +#include "xparameters_ps.h" +#include "xparameters.h" + + +#define ZYNQMP_EMACPS_0_BASEADDR 0xFF0B0000 +#define ZYNQMP_EMACPS_1_BASEADDR 0xFF0C0000 +#define ZYNQMP_EMACPS_2_BASEADDR 0xFF0D0000 +#define ZYNQMP_EMACPS_3_BASEADDR 0xFF0E0000 + +#if XPAR_XEMACPS_0_BASEADDR == ZYNQMP_EMACPS_0_BASEADDR + #define ZYNQMP_EMACPS_0_IRQ_ID XPAR_XEMACPS_0_INTR +#endif +#if XPAR_XEMACPS_0_BASEADDR == ZYNQMP_EMACPS_1_BASEADDR + #define ZYNQMP_EMACPS_0_IRQ_ID XPAR_XEMACPS_1_INTR +#endif +#if XPAR_XEMACPS_0_BASEADDR == ZYNQMP_EMACPS_2_BASEADDR + #define ZYNQMP_EMACPS_0_IRQ_ID XPAR_XEMACPS_2_INTR +#endif +#if XPAR_XEMACPS_0_BASEADDR == ZYNQMP_EMACPS_3_BASEADDR + #define ZYNQMP_EMACPS_0_IRQ_ID XPAR_XEMACPS_3_INTR +#endif +#if XPAR_XEMACPS_1_BASEADDR == ZYNQMP_EMACPS_0_BASEADDR + #define ZYNQMP_EMACPS_1_IRQ_ID XPAR_XEMACPS_0_INTR +#endif +#if XPAR_XEMACPS_1_BASEADDR == ZYNQMP_EMACPS_1_BASEADDR + #define ZYNQMP_EMACPS_1_IRQ_ID XPAR_XEMACPS_1_INTR +#endif +#if XPAR_XEMACPS_1_BASEADDR == ZYNQMP_EMACPS_2_BASEADDR + #define ZYNQMP_EMACPS_1_IRQ_ID XPAR_XEMACPS_2_INTR +#endif +#if XPAR_XEMACPS_1_BASEADDR == ZYNQMP_EMACPS_3_BASEADDR + #define ZYNQMP_EMACPS_1_IRQ_ID XPAR_XEMACPS_3_INTR +#endif +#if XPAR_XEMACPS_2_BASEADDR == ZYNQMP_EMACPS_0_BASEADDR + #define ZYNQMP_EMACPS_2_IRQ_ID XPAR_XEMACPS_0_INTR +#endif +#if XPAR_XEMACPS_2_BASEADDR == ZYNQMP_EMACPS_1_BASEADDR + #define ZYNQMP_EMACPS_2_IRQ_ID XPAR_XEMACPS_1_INTR +#endif +#if XPAR_XEMACPS_2_BASEADDR == ZYNQMP_EMACPS_2_BASEADDR + #define ZYNQMP_EMACPS_2_IRQ_ID XPAR_XEMACPS_2_INTR +#endif +#if XPAR_XEMACPS_2_BASEADDR == ZYNQMP_EMACPS_3_BASEADDR + #define ZYNQMP_EMACPS_2_IRQ_ID XPAR_XEMACPS_3_INTR +#endif +#if XPAR_XEMACPS_3_BASEADDR == ZYNQMP_EMACPS_0_BASEADDR + #define ZYNQMP_EMACPS_3_IRQ_ID XPAR_XEMACPS_0_INTR +#endif +#if XPAR_XEMACPS_3_BASEADDR == ZYNQMP_EMACPS_1_BASEADDR + #define ZYNQMP_EMACPS_3_IRQ_ID XPAR_XEMACPS_1_INTR +#endif +#if XPAR_XEMACPS_3_BASEADDR == ZYNQMP_EMACPS_2_BASEADDR + #define ZYNQMP_EMACPS_3_IRQ_ID XPAR_XEMACPS_2_INTR +#endif +#if XPAR_XEMACPS_3_BASEADDR == ZYNQMP_EMACPS_3_BASEADDR + #define ZYNQMP_EMACPS_3_IRQ_ID XPAR_XEMACPS_3_INTR +#endif + +#endif /* __XEMACMAP_H_ */ diff --git a/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_physpeed.c b/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_physpeed.c index c51aee080..1e46156de 100644 --- a/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_physpeed.c +++ b/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_physpeed.c @@ -54,6 +54,7 @@ #include #include "x_emacpsif.h" +#include "x_emac_map.h" #include "xparameters_ps.h" #include "xparameters.h" From 2eaa1623a7e2eceafb7af1af3d91ff4e1d38cc61 Mon Sep 17 00:00:00 2001 From: Stefan Baltruweit Date: Wed, 11 Sep 2024 17:34:20 +0200 Subject: [PATCH 06/11] Add Micrel PHY support to xilinx_ultrascale port Authored-by: Pete Bone --- .../xilinx_ultrascale/x_emacpsif_physpeed.c | 243 ++++++++++++++++++ 1 file changed, 243 insertions(+) diff --git a/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_physpeed.c b/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_physpeed.c index 1e46156de..820b26078 100644 --- a/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_physpeed.c +++ b/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_physpeed.c @@ -157,6 +157,7 @@ uint32_t phy_detected[ 4 ]; #define PHY_MARVELL_IDENTIFIER 0x0141 #define PHY_TI_IDENTIFIER 0x2000 #define PHY_REALTEK_IDENTIFIER 0x001c +#define PHY_MICREL_IDENTIFIER 0x0022 #define PHY_AR8035_IDENTIFIER 0x004D #define PHY_XILINX_PCS_PMA_ID1 0x0174 #define PHY_XILINX_PCS_PMA_ID2 0x0C00 @@ -659,6 +660,240 @@ static uint32_t get_Realtek_phy_speed( XEmacPs * xemacpsp, return XST_FAILURE; } +#define LPA_IEEE_1000FD 0x0800 +#define LP5_IEEE_100BTXFD 0x0100 +#define LP5_IEEE_10BTFD 0x0040 +#define MICREL_ID_KSZ9021 0x0161 +#define MICREL_ID_KSZ9031 0x0162 +#define MICREL_ID_KSZ9131 0x0164 + + +static int set_Micrel_phy_delays( XEmacPs * EmacPsInstancePtr, + uint32_t PhyAddr ) +{ + int Status; + uint16_t PhyType, PhyData; + + XEmacPs_PhyRead( EmacPsInstancePtr, PhyAddr, 0x3, ( u16 * ) &PhyData ); /* read value */ + PhyType = ( PhyData >> 4 ); + + /* enabling RGMII delays */ + if( PhyType == MICREL_ID_KSZ9131 ) /* KSZ9131 */ + { + FreeRTOS_printf( ( "Detected KSZ9131 Ethernet PHY\n\r" ) ); + /*Ctrl Delay */ + u16 RxCtrlDelay = 7; /* 0..15, default 7 */ + u16 TxCtrlDelay = 7; /* 0..15, default 7 */ + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xD, 0x0002 ); + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xE, 0x0004 ); /* Reg 0x4 */ + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xD, 0x4002 ); + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xE, ( TxCtrlDelay | ( RxCtrlDelay << 4 ) ) ); + /*Data Delay */ + u16 RxDataDelay = 7; /* 0..15, default 7 */ + u16 TxDataDelay = 7; /* 0..15, default 7 */ + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xD, 0x0002 ); + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xE, 0x0005 ); /* Reg 0x5 */ + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xD, 0x4002 ); + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xE, ( RxDataDelay | ( RxDataDelay << 4 ) | ( RxDataDelay << 8 ) | ( RxDataDelay << 12 ) ) ); + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xD, 0x0002 ); + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xE, 0x0006 ); /* Reg 0x6 */ + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xD, 0x4002 ); + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xE, ( TxDataDelay | ( TxDataDelay << 4 ) | ( TxDataDelay << 8 ) | ( TxDataDelay << 12 ) ) ); + /*Clock Delay */ + u16 RxClockDelay = 31; /* 0..31, default 15 */ + u16 TxClockDelay = 31; /* 0..31, default 15 */ + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xD, 0x0002 ); + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xE, 0x0008 ); /* Reg 0x8 RGMII Clock Pad Skew */ + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xD, 0x4002 ); + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xE, ( RxClockDelay | ( TxClockDelay << 5 ) ) ); + } + else if( PhyType == MICREL_ID_KSZ9031 ) /* KSZ9031 */ + { + FreeRTOS_printf( ( "Detected KSZ9031 Ethernet PHY\n\r" ) ); + /*Ctrl Delay */ + u16 RxCtrlDelay = 7; /* 0..15, default 7 */ + u16 TxCtrlDelay = 7; /* 0..15, default 7 */ + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xD, 0x0002 ); + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xE, 0x0004 ); /* Reg 0x4 */ + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xD, 0x4002 ); + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xE, ( TxCtrlDelay | ( RxCtrlDelay << 4 ) ) ); + /*Data Delay */ + u16 RxDataDelay = 7; /* 0..15, default 7 */ + u16 TxDataDelay = 7; /* 0..15, default 7 */ + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xD, 0x0002 ); + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xE, 0x0005 ); /* Reg 0x5 */ + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xD, 0x4002 ); + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xE, ( RxDataDelay | ( RxDataDelay << 4 ) | ( RxDataDelay << 8 ) | ( RxDataDelay << 12 ) ) ); + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xD, 0x0002 ); + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xE, 0x0006 ); /* Reg 0x6 */ + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xD, 0x4002 ); + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xE, ( TxDataDelay | ( TxDataDelay << 4 ) | ( TxDataDelay << 8 ) | ( TxDataDelay << 12 ) ) ); + /*Clock Delay */ + u16 RxClockDelay = 31; /* 0..31, default 15 */ + u16 TxClockDelay = 31; /* 0..31, default 15 */ + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xD, 0x0002 ); + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xE, 0x0008 ); /* Reg 0x8 RGMII Clock Pad Skew */ + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xD, 0x4002 ); + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xE, ( RxClockDelay | ( TxClockDelay << 5 ) ) ); + } + else if( PhyType == MICREL_ID_KSZ9021 ) /* KSZ9021 */ + { + FreeRTOS_printf( ( "Detected KSZ9021 Ethernet PHY\n\r" ) ); + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xB, 0x8104 ); /* write Reg 0x104 */ + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xC, 0xF0F0 ); /* set write data */ + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xB, 0x8105 ); /* write Reg 0x105 */ + XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0xC, 0x0000 ); /* set write data */ + } + + /* Issue a reset to phy */ + Status = XEmacPs_PhyRead( EmacPsInstancePtr, PhyAddr, 0x0, &PhyData ); + PhyData |= 0x8000; + Status = XEmacPs_PhyWrite( EmacPsInstancePtr, PhyAddr, 0x0, PhyData ); + vTaskDelay( 1 ); + Status |= XEmacPs_PhyRead( EmacPsInstancePtr, PhyAddr, 0x0, &PhyData ); + + if( Status != XST_SUCCESS ) + { + return Status; + } + + return PhyType; +} + +static uint32_t get_Micrel_phy_speed( XEmacPs * xemacpsp, + uint32_t phy_addr ) +{ + const char * name_ptr; + uint16_t temp, phy_type; + uint16_t control; + uint16_t status; + uint16_t status_speed; + uint32_t timeout_counter = 0; + + /* Just to prevent compiler warnings about unused variables. */ + ( void ) name_ptr; + + + FreeRTOS_printf( ( "Start Micrel PHY program delay\r\n" ) ); + + if( ( phy_type = set_Micrel_phy_delays( xemacpsp, phy_addr ) ) != XST_FAILURE ) + { + FreeRTOS_printf( ( "Delay Set Okay!\r\n" ) ); + } + else + { + FreeRTOS_printf( ( "Delay Set Error!\r\n" ) ); + } + + switch( phy_type ) + { + case MICREL_ID_KSZ9021: + name_ptr = "KSZ9021"; + break; + + case MICREL_ID_KSZ9031: + name_ptr = "KSZ9031"; + break; + + case MICREL_ID_KSZ9131: + name_ptr = "KSZ9131"; + break; + + default: + name_ptr = "!UNKNOWN!"; + break; + } + + FreeRTOS_printf( ( "Start %s auto-negotiation\r\n", name_ptr ) ); + + 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_PhyRead( xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, &control ); + control |= ( 7 << 12 ); + control |= ( 1 << 11 ); + XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG, control ); + + XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control ); + control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE; + control |= IEEE_STAT_AUTONEGOTIATE_RESTART; + XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control ); + + 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; + } + } + + XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status ); + + FreeRTOS_printf( ( "Waiting for %s to complete Auto-negotiation.\r\n", name_ptr ) ); + + while( !( status & IEEE_STAT_AUTONEGOTIATE_COMPLETE ) ) + { + vTaskDelay( pdMS_TO_TICKS( 1000 ) ); + XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2, &temp ); + timeout_counter++; + + if( timeout_counter == 30 ) + { + FreeRTOS_printf( ( "Auto negotiation error \r\n" ) ); + return XST_FAILURE; + } + + XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status ); + } + + FreeRTOS_printf( ( "%s Completed Auto-negotiation\r\n", name_ptr ) ); + + /* Check for high speed connection first */ + XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_3_REG_OFFSET, &status_speed ); + + if( status_speed & LPA_IEEE_1000FD ) + { + FreeRTOS_printf( ( "Micrel PHY %s speed 1000Mbps\r\n", name_ptr ) ); + return 1000; + } + else /* No high speed so check lows... */ + { + XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &status_speed ); + + if( status_speed & LP5_IEEE_100BTXFD ) + { + FreeRTOS_printf( ( "Micrel PHY %s speed 100Mbps\r\n", name_ptr ) ); + return 100; + } + + if( status_speed & LP5_IEEE_10BTFD ) + { + FreeRTOS_printf( ( "Micrel PHY %s speed 10Mbps\r\n", name_ptr ) ); + return 10; + } + } + + return XST_FAILURE; +} + /* Here is a XEmacPs_PhyRead() that returns the value of a register. */ static uint16_t XEmacPs_PhyRead2( XEmacPs * InstancePtr, u32 PhyAddress, @@ -898,6 +1133,10 @@ static const char * pcGetPHIName( uint16_t usID ) pcReturn = "Realtek RTL8212"; break; + case PHY_MICREL_IDENTIFIER: + pcReturn = "MICREL PHY"; + break; + case PHY_AR8035_IDENTIFIER: pcReturn = "Atheros_ar8035"; break; @@ -945,6 +1184,10 @@ static uint32_t get_IEEE_phy_speed_US( XEmacPs * xemacpsp, RetStatus = get_Marvell_phy_speed( xemacpsp, phy_addr ); break; + case PHY_MICREL_IDENTIFIER: + RetStatus = get_Micrel_phy_speed( xemacpsp, phy_addr ); + break; + case PHY_AR8035_IDENTIFIER: RetStatus = get_AR8035_phy_speed( xemacpsp, phy_addr ); prvSET_AR803x_TX_Timing( xemacpsp, phy_addr ); From 3e6376510a17398574fe6469e069ff6753764cd7 Mon Sep 17 00:00:00 2001 From: Stefan Baltruweit Date: Thu, 12 Sep 2024 13:54:04 +0200 Subject: [PATCH 07/11] Fix Zynq7000 EMAC MAC address setup Set solicited-node addresses independent of LLMNR. For mDNS set IPv4/6 MAC depending on ipconfigUSE_IPv6. --- .../NetworkInterface/Zynq/NetworkInterface.c | 55 +++++++++++-------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/source/portable/NetworkInterface/Zynq/NetworkInterface.c b/source/portable/NetworkInterface/Zynq/NetworkInterface.c index 21ad820ce..7cf063df6 100644 --- a/source/portable/NetworkInterface/Zynq/NetworkInterface.c +++ b/source/portable/NetworkInterface/Zynq/NetworkInterface.c @@ -256,43 +256,52 @@ static BaseType_t xZynqNetworkInterfaceInitialise( NetworkInterface_t * pxInterf #if ( ipconfigUSE_LLMNR == 1 ) { - /* Also add LLMNR multicast MAC address. */ #if ( ipconfigUSE_IPv6 == 0 ) { XEmacPs_SetHash( pxEMAC_PS, ( void * ) xLLMNR_MacAddress.ucBytes ); } #else { - NetworkEndPoint_t * pxEndPoint; - NetworkInterface_t * pxInterface = pxMyInterfaces[ xEMACIndex ]; - - for( pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); - pxEndPoint != NULL; - pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) - { - if( pxEndPoint->bits.bIPv6 != pdFALSE_UNSIGNED ) - { - unsigned char ucMACAddress[ 6 ] = { 0x33, 0x33, 0xff, 0, 0, 0 }; - ucMACAddress[ 3 ] = pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ]; - ucMACAddress[ 4 ] = pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ]; - ucMACAddress[ 5 ] = pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ]; - XEmacPs_SetHash( pxEMAC_PS, ( void * ) ucMACAddress ); - } - } - XEmacPs_SetHash( pxEMAC_PS, ( void * ) xLLMNR_MacAddressIPv6.ucBytes ); } #endif /* if ( ipconfigUSE_IPv6 == 0 ) */ } #endif /* ipconfigUSE_LLMNR == 1 */ - #if ( ( ipconfigUSE_MDNS == 1 ) && ( ipconfigUSE_IPv6 != 0 ) ) - XEmacPs_SetHash( pxEMAC_PS, ( void * ) xMDNS_MacAddress.ucBytes ); - XEmacPs_SetHash( pxEMAC_PS, ( void * ) xMDNS_MacAddressIPv6.ucBytes ); - #endif + #if ( ipconfigUSE_MDNS == 1 ) + { + #if ( ipconfigUSE_IPv6 == 0 ) + { + XEmacPs_SetHash( pxEMAC_PS, ( void * ) xMDNS_MacAddress.ucBytes ); + } + #else + { + XEmacPs_SetHash( pxEMAC_PS, ( void * ) xMDNS_MacAddressIPv6.ucBytes ); + } + #endif /* if ( ipconfigUSE_IPv6 == 0 ) */ + } + #endif /* ( ipconfigUSE_MDNS == 1 ) */ - pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ); + #if ( ipconfigUSE_IPv6 != 0 ) + { + /* set the solicited-node multicast address */ + for( NetworkEndPoint_t * pxEndPointIter = FreeRTOS_FirstEndPoint( pxInterface ); + pxEndPointIter != NULL; + pxEndPointIter = FreeRTOS_NextEndPoint( pxInterface, pxEndPointIter ) ) + { + if( pxEndPointIter->bits.bIPv6 != pdFALSE_UNSIGNED ) + { + unsigned char ucSsolicitedNodeMAC[ 6 ] = { 0x33, 0x33, 0xff, 0, 0, 0 }; + ucSsolicitedNodeMAC[ 3 ] = pxEndPointIter->ipv6_settings.xIPAddress.ucBytes[ 13 ]; + ucSsolicitedNodeMAC[ 4 ] = pxEndPointIter->ipv6_settings.xIPAddress.ucBytes[ 14 ]; + ucSsolicitedNodeMAC[ 5 ] = pxEndPointIter->ipv6_settings.xIPAddress.ucBytes[ 15 ]; + XEmacPs_SetHash( pxEMAC_PS, ( void * ) ucSsolicitedNodeMAC ); + } + } + } + #endif /* if ( ipconfigUSE_IPv6 == 0 ) */ + pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ); if( pxEndPoint != NULL ) { /* If there is a second end-point, store the MAC From 60a7f1c415513629dea59c42dfbaddada0f59dc7 Mon Sep 17 00:00:00 2001 From: Stefan Baltruweit Date: Fri, 27 Sep 2024 11:19:13 +0200 Subject: [PATCH 08/11] Uncrustify --- source/portable/NetworkInterface/Zynq/NetworkInterface.c | 5 +++-- .../portable/NetworkInterface/xilinx_ultrascale/x_emacpsif.h | 2 +- .../NetworkInterface/xilinx_ultrascale/x_emacpsif_hw.h | 2 +- .../portable/NetworkInterface/xilinx_ultrascale/x_topology.h | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/source/portable/NetworkInterface/Zynq/NetworkInterface.c b/source/portable/NetworkInterface/Zynq/NetworkInterface.c index 7cf063df6..1a621f12c 100644 --- a/source/portable/NetworkInterface/Zynq/NetworkInterface.c +++ b/source/portable/NetworkInterface/Zynq/NetworkInterface.c @@ -286,8 +286,8 @@ static BaseType_t xZynqNetworkInterfaceInitialise( NetworkInterface_t * pxInterf { /* set the solicited-node multicast address */ for( NetworkEndPoint_t * pxEndPointIter = FreeRTOS_FirstEndPoint( pxInterface ); - pxEndPointIter != NULL; - pxEndPointIter = FreeRTOS_NextEndPoint( pxInterface, pxEndPointIter ) ) + pxEndPointIter != NULL; + pxEndPointIter = FreeRTOS_NextEndPoint( pxInterface, pxEndPointIter ) ) { if( pxEndPointIter->bits.bIPv6 != pdFALSE_UNSIGNED ) { @@ -302,6 +302,7 @@ static BaseType_t xZynqNetworkInterfaceInitialise( NetworkInterface_t * pxInterf #endif /* if ( ipconfigUSE_IPv6 == 0 ) */ pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ); + if( pxEndPoint != NULL ) { /* If there is a second end-point, store the MAC diff --git a/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif.h b/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif.h index 9171f509a..a2a1c04e9 100644 --- a/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif.h +++ b/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif.h @@ -159,7 +159,7 @@ void vInitialiseOnIndex( BaseType_t xIndex ); #ifdef __cplusplus - } /* extern "C" */ +} /* extern "C" */ #endif #endif /* __NETIF_XAXIEMACIF_H__ */ diff --git a/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_hw.h b/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_hw.h index 2c525027c..8e21b0815 100644 --- a/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_hw.h +++ b/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_hw.h @@ -34,7 +34,7 @@ #ifdef __cplusplus - } /* extern "C" */ +} /* extern "C" */ #endif #endif /* ifndef __XEMACPSIF_HW_H_ */ diff --git a/source/portable/NetworkInterface/xilinx_ultrascale/x_topology.h b/source/portable/NetworkInterface/xilinx_ultrascale/x_topology.h index 4fb93cb85..111582f64 100644 --- a/source/portable/NetworkInterface/xilinx_ultrascale/x_topology.h +++ b/source/portable/NetworkInterface/xilinx_ultrascale/x_topology.h @@ -39,7 +39,7 @@ }; #ifdef __cplusplus - } /* extern "C" */ +} /* extern "C" */ #endif #endif /* __XTOPOLOGY_H_ */ From 5c2e46de1ddd53539a7d97bd5c0b95d5cbc61244 Mon Sep 17 00:00:00 2001 From: Stefan Baltruweit Date: Fri, 27 Sep 2024 11:41:01 +0200 Subject: [PATCH 09/11] Fix CI spelling errors --- .github/.cSpellWords.txt | 2 ++ .../xilinx_ultrascale/x_emacpsif_physpeed.c | 12 ++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/.cSpellWords.txt b/.github/.cSpellWords.txt index ed12e1e9c..319b2239e 100644 --- a/.github/.cSpellWords.txt +++ b/.github/.cSpellWords.txt @@ -247,6 +247,7 @@ DIVIDEBY DIVIDEDBY DLPSTATE DMAARBITRATION +DMAB DMABD DMABMR DMAC @@ -1562,6 +1563,7 @@ x xaxiemacif XCOL xemac +XEMACMAP xemacps XEMACPS xemacpsp diff --git a/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_physpeed.c b/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_physpeed.c index 820b26078..b4292600c 100644 --- a/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_physpeed.c +++ b/source/portable/NetworkInterface/xilinx_ultrascale/x_emacpsif_physpeed.c @@ -660,9 +660,9 @@ static uint32_t get_Realtek_phy_speed( XEmacPs * xemacpsp, return XST_FAILURE; } -#define LPA_IEEE_1000FD 0x0800 -#define LP5_IEEE_100BTXFD 0x0100 -#define LP5_IEEE_10BTFD 0x0040 +#define LPA_IEEE_1000 0x0800 +#define LP5_IEEE_100 0x0100 +#define LP5_IEEE_10 0x0040 #define MICREL_ID_KSZ9021 0x0161 #define MICREL_ID_KSZ9031 0x0162 #define MICREL_ID_KSZ9131 0x0164 @@ -869,7 +869,7 @@ static uint32_t get_Micrel_phy_speed( XEmacPs * xemacpsp, /* Check for high speed connection first */ XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_3_REG_OFFSET, &status_speed ); - if( status_speed & LPA_IEEE_1000FD ) + if( status_speed & LPA_IEEE_1000 ) { FreeRTOS_printf( ( "Micrel PHY %s speed 1000Mbps\r\n", name_ptr ) ); return 1000; @@ -878,13 +878,13 @@ static uint32_t get_Micrel_phy_speed( XEmacPs * xemacpsp, { XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET, &status_speed ); - if( status_speed & LP5_IEEE_100BTXFD ) + if( status_speed & LP5_IEEE_100 ) { FreeRTOS_printf( ( "Micrel PHY %s speed 100Mbps\r\n", name_ptr ) ); return 100; } - if( status_speed & LP5_IEEE_10BTFD ) + if( status_speed & LP5_IEEE_10 ) { FreeRTOS_printf( ( "Micrel PHY %s speed 10Mbps\r\n", name_ptr ) ); return 10; From 5aa836b79c6a03b28966264f877ecd4d6bbdfb95 Mon Sep 17 00:00:00 2001 From: Stefan Baltruweit Date: Tue, 1 Oct 2024 10:45:15 +0200 Subject: [PATCH 10/11] Fix IPv4/6 preprocessor logic in Zynq/Ultrascale port --- .../NetworkInterface/Zynq/NetworkInterface.c | 50 +++++++++++-------- .../xilinx_ultrascale/NetworkInterface.c | 50 +++++++++++-------- 2 files changed, 59 insertions(+), 41 deletions(-) diff --git a/source/portable/NetworkInterface/Zynq/NetworkInterface.c b/source/portable/NetworkInterface/Zynq/NetworkInterface.c index 1a621f12c..8b5913bf1 100644 --- a/source/portable/NetworkInterface/Zynq/NetworkInterface.c +++ b/source/portable/NetworkInterface/Zynq/NetworkInterface.c @@ -254,35 +254,39 @@ static BaseType_t xZynqNetworkInterfaceInitialise( NetworkInterface_t * pxInterf /* Initialize the mac and set the MAC address at position 1. */ XEmacPs_SetMacAddress( pxEMAC_PS, ( void * ) pxEndPoint->xMACAddress.ucBytes, 1 ); - #if ( ipconfigUSE_LLMNR == 1 ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_LLMNR ) ) { - #if ( ipconfigUSE_IPv6 == 0 ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ) { XEmacPs_SetHash( pxEMAC_PS, ( void * ) xLLMNR_MacAddress.ucBytes ); } - #else + #endif /* ( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) */ + + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) { XEmacPs_SetHash( pxEMAC_PS, ( void * ) xLLMNR_MacAddressIPv6.ucBytes ); } - #endif /* if ( ipconfigUSE_IPv6 == 0 ) */ + #endif /* ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) */ } - #endif /* ipconfigUSE_LLMNR == 1 */ + #endif /* ( ipconfigIS_ENABLED( ipconfigUSE_LLMNR ) ) */ - #if ( ipconfigUSE_MDNS == 1 ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_MDNS ) ) { - #if ( ipconfigUSE_IPv6 == 0 ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ) { XEmacPs_SetHash( pxEMAC_PS, ( void * ) xMDNS_MacAddress.ucBytes ); } - #else + #endif /* ( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) */ + + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) { XEmacPs_SetHash( pxEMAC_PS, ( void * ) xMDNS_MacAddressIPv6.ucBytes ); } - #endif /* if ( ipconfigUSE_IPv6 == 0 ) */ + #endif /* ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) */ } - #endif /* ( ipconfigUSE_MDNS == 1 ) */ + #endif /* ( ipconfigIS_ENABLED( ipconfigUSE_MDNS) ) */ - #if ( ipconfigUSE_IPv6 != 0 ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) { /* set the solicited-node multicast address */ for( NetworkEndPoint_t * pxEndPointIter = FreeRTOS_FirstEndPoint( pxInterface ); @@ -299,7 +303,7 @@ static BaseType_t xZynqNetworkInterfaceInitialise( NetworkInterface_t * pxInterf } } } - #endif /* if ( ipconfigUSE_IPv6 == 0 ) */ + #endif /* ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) */ pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ); @@ -388,7 +392,8 @@ static BaseType_t xZynqNetworkInterfaceOutput( NetworkInterface_t * pxInterface, * the protocol checksum to have a value of zero. */ pxPacket = ( ProtocolPacket_t * ) ( pxBuffer->pucEthernetBuffer ); - #if ( ipconfigUSE_IPv6 != 0 ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) + { ICMPPacket_IPv6_t * pxICMPPacket = ( ICMPPacket_IPv6_t * ) pxBuffer->pucEthernetBuffer; if( ( pxPacket->xICMPPacket.xEthernetHeader.usFrameType == ipIPv6_FRAME_TYPE ) && @@ -399,16 +404,21 @@ static BaseType_t xZynqNetworkInterfaceOutput( NetworkInterface_t * pxInterface, * so for ICMP and other protocols it must be done manually. */ usGenerateProtocolChecksum( pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength, pdTRUE ); } - #endif + } + #endif /* ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) */ - if( ( pxPacket->xICMPPacket.xEthernetHeader.usFrameType == ipIPv4_FRAME_TYPE ) && - ( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ipPROTOCOL_ICMP ) ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ) { - /* The EMAC will calculate the checksum of the IP-header. - * It can only calculate protocol checksums of UDP and TCP, - * so for ICMP and other protocols it must be done manually. */ - usGenerateProtocolChecksum( pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength, pdTRUE ); + if( ( pxPacket->xICMPPacket.xEthernetHeader.usFrameType == ipIPv4_FRAME_TYPE ) && + ( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ipPROTOCOL_ICMP ) ) + { + /* The EMAC will calculate the checksum of the IP-header. + * It can only calculate protocol checksums of UDP and TCP, + * so for ICMP and other protocols it must be done manually. */ + usGenerateProtocolChecksum( pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength, pdTRUE ); + } } + #endif /* ( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ) */ } #endif /* ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM */ diff --git a/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c b/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c index d5342b885..ea7b2075e 100644 --- a/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c +++ b/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c @@ -319,35 +319,39 @@ static BaseType_t xUltrascaleNetworkInterfaceInitialise( NetworkInterface_t * px /* Initialize the mac and set the MAC address at position 1. */ XEmacPs_SetMacAddress( pxEMAC_PS, ( void * ) pxEndPoint->xMACAddress.ucBytes, 1 ); - #if ( ipconfigUSE_LLMNR == 1 ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_LLMNR ) ) { - #if ( ipconfigUSE_IPv6 == 0 ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ) { XEmacPs_SetHash( pxEMAC_PS, ( void * ) xLLMNR_MacAddress.ucBytes ); } - #else + #endif /* ( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) */ + + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) { XEmacPs_SetHash( pxEMAC_PS, ( void * ) xLLMNR_MacAddressIPv6.ucBytes ); } - #endif /* if ( ipconfigUSE_IPv6 == 0 ) */ + #endif /* ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) */ } - #endif /* ipconfigUSE_LLMNR == 1 */ + #endif /* ( ipconfigIS_ENABLED( ipconfigUSE_LLMNR ) ) */ - #if ( ipconfigUSE_MDNS == 1 ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_MDNS ) ) { - #if ( ipconfigUSE_IPv6 == 0 ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ) { XEmacPs_SetHash( pxEMAC_PS, ( void * ) xMDNS_MacAddress.ucBytes ); } - #else + #endif /* ( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) */ + + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) { - XEmacPs_SetHash( pxEMAC_PS, ( void * ) xMDNS_MACAddressIPv6.ucBytes ); + XEmacPs_SetHash( pxEMAC_PS, ( void * ) xMDNS_MacAddressIPv6.ucBytes ); } - #endif /* if ( ipconfigUSE_IPv6 == 0 ) */ + #endif /* ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) */ } - #endif /* ( ipconfigUSE_MDNS == 1 ) */ + #endif /* ( ipconfigIS_ENABLED( ipconfigUSE_MDNS) ) */ - #if ( ipconfigUSE_IPv6 != 0 ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) { /* set the solicited-node multicast address */ for( NetworkEndPoint_t * pxEndPointIter = FreeRTOS_FirstEndPoint( pxInterface ); @@ -364,7 +368,7 @@ static BaseType_t xUltrascaleNetworkInterfaceInitialise( NetworkInterface_t * px } } } - #endif /* if ( ipconfigUSE_IPv6 == 0 ) */ + #endif /* ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) */ /* allow reception of multicast addresses programmed into hash (LLMNR or mDNS) */ XEmacPs_SetOptions( pxEMAC_PS, XEMACPS_MULTICAST_OPTION ); @@ -504,7 +508,7 @@ static BaseType_t xUltrascaleNetworkInterfaceOutput( NetworkInterface_t * pxInte * the protocol checksum to have a value of zero. */ pxPacket = ( ProtocolPacket_t * ) ( pxBuffer->pucEthernetBuffer ); - #if ( ipconfigUSE_IPv6 != 0 ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) ICMPPacket_IPv6_t * pxICMPPacket = ( ICMPPacket_IPv6_t * ) pxBuffer->pucEthernetBuffer; if( ( pxPacket->xICMPPacket.xEthernetHeader.usFrameType == ipIPv6_FRAME_TYPE ) && @@ -515,16 +519,20 @@ static BaseType_t xUltrascaleNetworkInterfaceOutput( NetworkInterface_t * pxInte * so for ICMP and other protocols it must be done manually. */ usGenerateProtocolChecksum( pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength, pdTRUE ); } - #endif /* ipconfigUSE_IPv6 */ + #endif /* ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) */ - if( ( pxPacket->xICMPPacket.xEthernetHeader.usFrameType == ipIPv4_FRAME_TYPE ) && - ( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ipPROTOCOL_ICMP ) ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ) { - /* The EMAC will calculate the checksum of the IP-header. - * It can only calculate protocol checksums of UDP and TCP, - * so for ICMP and other protocols it must be done manually. */ - usGenerateProtocolChecksum( pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength, pdTRUE ); + if( ( pxPacket->xICMPPacket.xEthernetHeader.usFrameType == ipIPv4_FRAME_TYPE ) && + ( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ipPROTOCOL_ICMP ) ) + { + /* The EMAC will calculate the checksum of the IP-header. + * It can only calculate protocol checksums of UDP and TCP, + * so for ICMP and other protocols it must be done manually. */ + usGenerateProtocolChecksum( pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength, pdTRUE ); + } } + #endif /* ( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) */ } #endif /* ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM */ From f2cf4b2ccdb763af28f79fc9cf6eade090c661b6 Mon Sep 17 00:00:00 2001 From: StefanBalt <79701944+StefanBalt@users.noreply.github.com> Date: Wed, 2 Oct 2024 11:13:17 +0200 Subject: [PATCH 11/11] Add missing return in xilinx_ultrascale/NetworkInterface.c Co-authored-by: ActoryOu --- .../NetworkInterface/xilinx_ultrascale/NetworkInterface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c b/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c index ea7b2075e..bf97e3e27 100644 --- a/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c +++ b/source/portable/NetworkInterface/xilinx_ultrascale/NetworkInterface.c @@ -664,7 +664,7 @@ static BaseType_t xUltrascaleGetPhyLinkStatus( NetworkInterface_t * pxInterface NetworkInterface_t * pxFillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ) { - pxUltrascale_FillInterfaceDescriptor( xEMACIndex, pxInterface ); + return pxUltrascale_FillInterfaceDescriptor( xEMACIndex, pxInterface ); } #endif