| /* eip207_ice.c |
| * |
| * EIP-207c Input Classification Engine (ICE) interface implementation |
| */ |
| |
| /* -------------------------------------------------------------------------- */ |
| /* */ |
| /* Module : ddk197 */ |
| /* Version : 5.6.1 */ |
| /* Configuration : DDK-197-GPL */ |
| /* */ |
| /* Date : 2022-Dec-16 */ |
| /* */ |
| /* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries. */ |
| /* */ |
| /* This program is free software: you can redistribute it and/or modify */ |
| /* it under the terms of the GNU General Public License as published by */ |
| /* the Free Software Foundation, either version 2 of the License, or */ |
| /* any later version. */ |
| /* */ |
| /* This program is distributed in the hope that it will be useful, */ |
| /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ |
| /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ |
| /* GNU General Public License for more details. */ |
| /* */ |
| /* You should have received a copy of the GNU General Public License */ |
| /* along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
| /* -------------------------------------------------------------------------- */ |
| |
| /*---------------------------------------------------------------------------- |
| * This module implements (provides) the following interface(s): |
| */ |
| |
| // EIP-207c Input Classification Engine (ICE) interface |
| #include "eip207_ice.h" |
| |
| |
| /*---------------------------------------------------------------------------- |
| * This module uses (requires) the following interface(s): |
| */ |
| |
| // Default configuration |
| #include "c_eip207_global.h" |
| |
| // Driver Framework Basic Definitions API |
| #include "basic_defs.h" // uint32_t, bool |
| |
| // EIP-207 Global Control Driver Library Internal interfaces |
| #include "eip207_level0.h" // EIP-207 Level 0 macros |
| |
| // EIP-207 HW interface |
| #include "eip207_hw_interface.h" |
| |
| // Driver Framework Device API |
| #include "device_types.h" // Device_Handle_t |
| #include "device_rw.h" // Read32, Write32 |
| |
| // EIP-207 Firmware Classification API |
| #include "firmware_eip207_api_cs.h" // Classification API: General |
| |
| // EIP-207 Firmware Download API |
| #include "firmware_eip207_api_dwld.h" // Classification API: FW download |
| |
| // EIP-207 Support API |
| #include "eip207_support.h" |
| |
| // EIP97_Interfaces_Get() |
| #include "eip97_global_internal.h" |
| |
| #include "clib.h" // memcmp |
| |
| /*---------------------------------------------------------------------------- |
| * Definitions and macros |
| */ |
| |
| // Allow legacy firmware to be used, which does not have these constants. |
| #ifndef FIRMWARE_EIP207_DWLD_ADMIN_RAM_INPUT_LAST_BYTE_COUNT |
| #define FIRMWARE_EIP207_DWLD_ADMIN_RAM_INPUT_LAST_BYTE_COUNT FIRMWARE_EIP207_DWLD_ADMIN_RAM_LAST_BYTE_COUNT |
| #endif |
| #ifndef FIRMWARE_EIP207_CS_ADMIN_RAM_INPUT_LAST_BYTE_COUNT |
| #define FIRMWARE_EIP207_CS_ADMIN_RAM_INPUT_LAST_BYTE_COUNT FIRMWARE_EIP207_DWLD_ADMIN_RAM_INPUT_LAST_BYTE_COUNT |
| #endif |
| |
| // Number fo words to check when reading firmware back. |
| #define EIP207_FW_CHECK_WORD_COUNT 16 |
| |
| |
| /*---------------------------------------------------------------------------- |
| * EIP207_ICE_Firmware_Load |
| */ |
| EIP207_Global_Error_t |
| EIP207_ICE_Firmware_Load( |
| const Device_Handle_t Device, |
| const unsigned int TimerPrescaler, |
| EIP207_Firmware_t * const PUE_Firmware_p, |
| EIP207_Firmware_t * const FPP_Firmware_p) |
| { |
| unsigned int NofCEs; |
| EIP97_Interfaces_Get(&NofCEs,NULL,NULL,NULL); |
| // Check if the Adapter provides the IPUE firmware image with correct size. |
| if (!PUE_Firmware_p->Image_p || |
| PUE_Firmware_p->ImageWordCount > EIP207_IPUE_PROG_RAM_WORD_COUNT) |
| return EIP207_GLOBAL_ARGUMENT_ERROR; |
| |
| // Check if the Adapter provides the IFPP firmware image with correct size. |
| if (!FPP_Firmware_p->Image_p || |
| FPP_Firmware_p->ImageWordCount > EIP207_IPUE_PROG_RAM_WORD_COUNT) |
| return EIP207_GLOBAL_ARGUMENT_ERROR; |
| |
| |
| // Clear EIP-207c ICE Scratchpad RAM where the the firmware |
| // administration data will be located |
| { |
| unsigned int i, CECount, BlockCount, RequiredRAMByteCount; |
| |
| RequiredRAMByteCount = |
| MAX(FIRMWARE_EIP207_CS_ADMIN_RAM_INPUT_LAST_BYTE_COUNT, |
| FIRMWARE_EIP207_DWLD_ADMIN_RAM_INPUT_LAST_BYTE_COUNT); |
| |
| // Check if the administration RAM required by the EIP-207 firmware |
| // fits into physically available scratchpad RAM |
| if ((EIP207_ICE_SCRATCH_RAM_128B_BLOCK_COUNT * 128) < |
| RequiredRAMByteCount) |
| return EIP207_GLOBAL_ARGUMENT_ERROR; |
| |
| // Calculate how many 128-byte blocks are required for the firmware |
| // administration data |
| BlockCount = (RequiredRAMByteCount + 127) / 128; |
| |
| for (CECount = 0; CECount < NofCEs; CECount++) |
| { |
| // Make ICE Scratchpad RAM accessible and set the timer |
| EIP207_ICE_SCRATCH_CTRL_WR( |
| Device, |
| CECount, |
| true, // Change timer |
| true, // Enable timer |
| (uint16_t)TimerPrescaler, |
| EIP207_ICE_SCRATCH_TIMER_OFLO_BIT, // Timer overflow bit |
| true, // Change access |
| (uint8_t)BlockCount); |
| |
| #ifdef DEBUG |
| // Check if the timer runs |
| { |
| uint32_t Value32; |
| unsigned int i; |
| |
| for (i = 0; i < 10; i++) |
| { |
| Value32 = Device_Read32(Device, |
| EIP207_ICE_REG_TIMER_LO(CECount)); |
| |
| if (Value32 == 0) |
| return EIP207_GLOBAL_INTERNAL_ERROR; |
| } |
| } |
| #endif |
| |
| // Write the ICE Scratchpad RAM with 0 |
| for(i = 0; i < (BlockCount * 32); i++) |
| { |
| Device_Write32(Device, |
| EIP207_ICE_REG_SCRATCH_RAM(CECount) + |
| i * sizeof(uint32_t), |
| 0); |
| #ifdef DEBUG |
| // Perform read-back check |
| { |
| uint32_t Value32 = |
| Device_Read32( |
| Device, |
| EIP207_ICE_REG_SCRATCH_RAM(CECount) + |
| i * sizeof(uint32_t)); |
| |
| if (Value32 != 0) |
| return EIP207_GLOBAL_INTERNAL_ERROR; |
| } |
| #endif |
| } |
| } |
| |
| // Leave the scratchpad RAM accessible for the Host |
| } |
| |
| // Download the firmware |
| { |
| unsigned int CECount; |
| #ifdef DEBUG |
| unsigned int i; |
| #endif |
| for (CECount = 0; CECount < NofCEs; CECount++) |
| { |
| // Reset the Input Flow Post-Processor micro-engine (IFPP) to make its |
| // Program RAM accessible |
| EIP207_ICE_FPP_CTRL_WR(Device, |
| CECount, |
| 0, // No start address for debug mode |
| 1, // Clear ECC correctable error |
| 1, // Clear ECC non-correctable error |
| false, // Debug mode OFF |
| true); // SW Reset ON |
| |
| // Enable access to IFPP Program RAM |
| EIP207_ICE_RAM_CTRL_WR(Device, CECount, false, true); |
| } |
| |
| #ifdef DEBUG |
| // Write the Input Flow post-Processor micro-Engine firmware |
| for(i = 0; i < FPP_Firmware_p->ImageWordCount; i++) |
| { |
| Device_Write32(Device, |
| EIP207_CS_RAM_XS_SPACE_BASE + i * sizeof(uint32_t), |
| FPP_Firmware_p->Image_p[i]); |
| // Perform read-back check |
| { |
| uint32_t Value32 = |
| Device_Read32( |
| Device, |
| EIP207_CS_RAM_XS_SPACE_BASE + i * sizeof(uint32_t)); |
| |
| if (Value32 != FPP_Firmware_p->Image_p[i]) |
| return EIP207_GLOBAL_INTERNAL_ERROR; |
| } |
| } |
| #else |
| Device_Write32Array(Device, |
| EIP207_CS_RAM_XS_SPACE_BASE, |
| FPP_Firmware_p->Image_p, |
| FPP_Firmware_p->ImageWordCount); |
| // Perform read-back check of small subset |
| { |
| static uint32_t ReadBuf[EIP207_FW_CHECK_WORD_COUNT]; |
| Device_Read32Array(Device, |
| EIP207_CS_RAM_XS_SPACE_BASE, |
| ReadBuf, |
| EIP207_FW_CHECK_WORD_COUNT); |
| if (memcmp(ReadBuf, |
| FPP_Firmware_p->Image_p, |
| EIP207_FW_CHECK_WORD_COUNT * sizeof(uint32_t)) != 0) |
| return EIP207_GLOBAL_INTERNAL_ERROR; |
| |
| } |
| #endif |
| |
| for (CECount = 0; CECount < NofCEs; CECount++) |
| { |
| // Disable access to IFPP Program RAM |
| // Enable access to IPUE Program RAM |
| EIP207_ICE_RAM_CTRL_WR(Device, CECount, true, false); |
| |
| // Reset the Input Pull-Up micro-Engine (IPUE) to make its |
| // Program RAM accessible |
| EIP207_ICE_PUE_CTRL_WR(Device, |
| CECount, |
| 0, // No start address for debug mode |
| 1, // Clear ECC correctable error |
| 1, // Clear ECC non-correctable error |
| false, // Debug mode OFF |
| true); // SW Reset ON |
| } |
| |
| #ifdef DEBUG |
| // Write the Input Pull-Up micro-Engine firmware |
| for(i = 0; i < PUE_Firmware_p->ImageWordCount; i++) |
| { |
| Device_Write32(Device, |
| EIP207_CS_RAM_XS_SPACE_BASE + i * sizeof(uint32_t), |
| PUE_Firmware_p->Image_p[i]); |
| // Perform read-back check |
| { |
| uint32_t Value32 = |
| Device_Read32( |
| Device, |
| EIP207_CS_RAM_XS_SPACE_BASE + i * sizeof(uint32_t)); |
| |
| if (Value32 != PUE_Firmware_p->Image_p[i]) |
| return EIP207_GLOBAL_INTERNAL_ERROR; |
| } |
| } |
| #else |
| Device_Write32Array(Device, |
| EIP207_CS_RAM_XS_SPACE_BASE, |
| PUE_Firmware_p->Image_p, |
| PUE_Firmware_p->ImageWordCount); |
| // Perform read-back check of small subset |
| { |
| static uint32_t ReadBuf[EIP207_FW_CHECK_WORD_COUNT]; |
| Device_Read32Array(Device, |
| EIP207_CS_RAM_XS_SPACE_BASE, |
| ReadBuf, |
| EIP207_FW_CHECK_WORD_COUNT); |
| if (memcmp(ReadBuf, |
| PUE_Firmware_p->Image_p, |
| EIP207_FW_CHECK_WORD_COUNT * sizeof(uint32_t)) != 0) |
| return EIP207_GLOBAL_INTERNAL_ERROR; |
| |
| } |
| #endif |
| |
| // Disable access to IPUE Program RAM |
| for (CECount = 0; CECount < NofCEs; CECount++) |
| EIP207_ICE_RAM_CTRL_WR(Device, CECount, false, false); |
| |
| #ifdef EIP207_GLOBAL_FIRMWARE_DOWNLOAD_VERSION_CHECK |
| // Check the firmware version and start all the engines |
| for (CECount = 0; CECount < NofCEs; CECount++) |
| { |
| uint32_t Value32; |
| unsigned int Ma, Mi, Pl, i; |
| bool fUpdated; |
| |
| // Start the IFPP in Debug mode for the firmware version check |
| EIP207_ICE_FPP_CTRL_WR( |
| Device, |
| CECount, |
| FIRMWARE_EIP207_DWLD_IFPP_VERSION_CHECK_DBG_PROG_CNTR, |
| 1, // Clear ECC correctable error |
| 1, // Clear ECC non-correctable error |
| true, // Debug mode ON |
| false); // SW Reset OFF |
| |
| // Wait for the IFPP version update |
| for (i = 0; i < EIP207_FW_VER_CHECK_MAX_NOF_READ_ATTEMPTS; i++) |
| { |
| Value32 = Device_Read32( |
| Device, |
| EIP207_ICE_REG_SCRATCH_RAM(CECount) + |
| FIRMWARE_EIP207_DWLD_ADMIN_RAM_IFPP_CTRL_BYTE_OFFSET); |
| |
| FIRMWARE_EIP207_DWLD_IFPP_VersionUpdated_Read(Value32, |
| &fUpdated); |
| |
| if (fUpdated) |
| break; |
| } |
| |
| if (!fUpdated) |
| return EIP207_GLOBAL_INTERNAL_ERROR; |
| |
| Value32 = Device_Read32( |
| Device, |
| EIP207_ICE_REG_SCRATCH_RAM(CECount) + |
| FIRMWARE_EIP207_DWLD_ADMIN_RAM_IFPP_VERSION_BYTE_OFFSET); |
| |
| FIRMWARE_EIP207_DWLD_Version_Read(Value32, &Ma, &Mi, &Pl); |
| |
| if (FPP_Firmware_p->Major == 0 && |
| FPP_Firmware_p->Minor == 0 && |
| FPP_Firmware_p->PatchLevel == 0) |
| { // Adapter did not provide expected version, return it. |
| FPP_Firmware_p->Major = Ma; |
| FPP_Firmware_p->Minor = Mi; |
| FPP_Firmware_p->PatchLevel = Pl; |
| } |
| else |
| { |
| // Adapter provided expected version, check it. |
| if (FPP_Firmware_p->Major != Ma || |
| FPP_Firmware_p->Minor != Mi || |
| FPP_Firmware_p->PatchLevel != Pl) |
| return EIP207_GLOBAL_INTERNAL_ERROR; |
| } |
| |
| // Start the IPUE in Debug mode for the firmware version check |
| EIP207_ICE_PUE_CTRL_WR( |
| Device, |
| CECount, |
| FIRMWARE_EIP207_DWLD_IPUE_VERSION_CHECK_DBG_PROG_CNTR, |
| 1, // Clear ECC correctable error |
| 1, // Clear ECC non-correctable error |
| true, // Debug mode ON |
| false); // SW Reset OFF |
| |
| // Wait for the IPUE version update |
| for (i = 0; i < EIP207_FW_VER_CHECK_MAX_NOF_READ_ATTEMPTS; i++) |
| { |
| Value32 = Device_Read32( |
| Device, |
| EIP207_ICE_REG_SCRATCH_RAM(CECount) + |
| FIRMWARE_EIP207_DWLD_ADMIN_RAM_IPUE_CTRL_BYTE_OFFSET); |
| |
| FIRMWARE_EIP207_DWLD_IPUE_VersionUpdated_Read(Value32, |
| &fUpdated); |
| |
| if (fUpdated) |
| break; |
| } |
| |
| if (!fUpdated) |
| return EIP207_GLOBAL_INTERNAL_ERROR; |
| |
| Value32 = Device_Read32( |
| Device, |
| EIP207_ICE_REG_SCRATCH_RAM(CECount) + |
| FIRMWARE_EIP207_DWLD_ADMIN_RAM_IPUE_VERSION_BYTE_OFFSET); |
| |
| FIRMWARE_EIP207_DWLD_Version_Read(Value32, &Ma, &Mi, &Pl); |
| |
| if (PUE_Firmware_p->Major == 0 && |
| PUE_Firmware_p->Minor == 0 && |
| PUE_Firmware_p->PatchLevel == 0) |
| { // Adapter did not provide expected version, return it. |
| PUE_Firmware_p->Major = Ma; |
| PUE_Firmware_p->Minor = Mi; |
| PUE_Firmware_p->PatchLevel = Pl; |
| } |
| else |
| { |
| // Adapter provided expected version, check it. |
| if (PUE_Firmware_p->Major != Ma || |
| PUE_Firmware_p->Minor != Mi || |
| PUE_Firmware_p->PatchLevel != Pl) |
| return EIP207_GLOBAL_INTERNAL_ERROR; |
| } |
| } // for |
| #else |
| for (CECount = 0; CECount < NofCEs; CECount++) |
| { |
| // Start the IFPP in Debug mode |
| EIP207_ICE_FPP_CTRL_WR( |
| Device, |
| CECount, |
| FIRMWARE_EIP207_DWLD_IFPP_VERSION_CHECK_DBG_PROG_CNTR, |
| 1, // Clear ECC correctable error |
| 1, // Clear ECC non-correctable error |
| true, // Debug mode ON |
| false); // SW Reset OFF |
| |
| // Start the IPUE in Debug mode |
| EIP207_ICE_PUE_CTRL_WR( |
| Device, |
| CECount, |
| FIRMWARE_EIP207_DWLD_IPUE_VERSION_CHECK_DBG_PROG_CNTR, |
| 1, // Clear ECC correctable error |
| 1, // Clear ECC non-correctable error |
| true, // Debug mode ON |
| false); // SW Reset OFF |
| } // for |
| #endif // EIP207_GLOBAL_FIRMWARE_DOWNLOAD_VERSION_CHECK |
| for (CECount = 0; CECount < NofCEs; CECount++) |
| { |
| uint32_t InputBufferSize = Device_Read32( |
| Device, |
| EIP207_ICE_REG_SCRATCH_RAM(CECount) + |
| 4*33) & MASK_16_BITS; |
| if (InputBufferSize != 0) |
| { |
| if (PUE_Firmware_p->Major > 3 || |
| (PUE_Firmware_p->Major ==3 && |
| PUE_Firmware_p->Minor >=1)) |
| { |
| InputBufferSize -= 2048; |
| } |
| else |
| { |
| InputBufferSize = (InputBufferSize * 3) / 4; |
| } |
| EIP207_ICE_ADAPT_CTRL_WR(Device, CECount, InputBufferSize); |
| } |
| EIP207_ICE_PUTF_CTRL_WR(Device, CECount, 3, false); |
| EIP207_ICE_PPTF_CTRL_WR(Device, CECount, 0, false); |
| } |
| } |
| |
| |
| return EIP207_GLOBAL_NO_ERROR; |
| } |
| |
| |
| /*---------------------------------------------------------------------------- |
| * EIP207_ICE_GlobalStats_Get |
| */ |
| EIP207_Global_Error_t |
| EIP207_ICE_GlobalStats_Get( |
| const Device_Handle_t Device, |
| const unsigned int CE_Number, |
| EIP207_Global_ICE_GlobalStats_t * const ICE_GlobalStats_p) |
| { |
| EIP207_Global_Error_t rv; |
| |
| rv = EIP207_Global_Read64( |
| Device, |
| EIP207_ICE_REG_SCRATCH_RAM(CE_Number) + |
| FIRMWARE_EIP207_CS_ADMIN_RAM_STAT_DROP_LO_BYTE_OFFSET, |
| EIP207_ICE_REG_SCRATCH_RAM(CE_Number) + |
| FIRMWARE_EIP207_CS_ADMIN_RAM_STAT_DROP_HI_BYTE_OFFSET, |
| &ICE_GlobalStats_p->DroppedPacketsCounter); |
| if (rv != EIP207_GLOBAL_NO_ERROR) |
| return rv; |
| |
| rv = EIP207_Global_Read64( |
| Device, |
| EIP207_ICE_REG_SCRATCH_RAM(CE_Number) + |
| FIRMWARE_EIP207_CS_ADMIN_RAM_STAT_IN_OCT_LO_BYTE_OFFSET, |
| EIP207_ICE_REG_SCRATCH_RAM(CE_Number) + |
| FIRMWARE_EIP207_CS_ADMIN_RAM_STAT_IN_OCT_HI_BYTE_OFFSET, |
| &ICE_GlobalStats_p->InboundOctetsCounter); |
| if (rv != EIP207_GLOBAL_NO_ERROR) |
| return rv; |
| |
| rv = EIP207_Global_Read64( |
| Device, |
| EIP207_ICE_REG_SCRATCH_RAM(CE_Number) + |
| FIRMWARE_EIP207_CS_ADMIN_RAM_STAT_OUT_OCT_LO_BYTE_OFFSET, |
| EIP207_ICE_REG_SCRATCH_RAM(CE_Number) + |
| FIRMWARE_EIP207_CS_ADMIN_RAM_STAT_OUT_OCT_HI_BYTE_OFFSET, |
| &ICE_GlobalStats_p->OutboundOctetsCounter); |
| if (rv != EIP207_GLOBAL_NO_ERROR) |
| return rv; |
| |
| ICE_GlobalStats_p->InboundPacketsCounter = |
| Device_Read32(Device, |
| EIP207_ICE_REG_SCRATCH_RAM(CE_Number) + |
| FIRMWARE_EIP207_CS_ADMIN_RAM_STAT_IN_PKT_BYTE_OFFSET); |
| |
| ICE_GlobalStats_p->OutboundPacketCounter = |
| Device_Read32(Device, |
| EIP207_ICE_REG_SCRATCH_RAM(CE_Number) + |
| FIRMWARE_EIP207_CS_ADMIN_RAM_STAT_OUT_PKT_BYTE_OFFSET); |
| |
| return EIP207_GLOBAL_NO_ERROR; |
| } |
| |
| |
| /*---------------------------------------------------------------------------- |
| * EIP207_ICE_ClockCount_Get |
| */ |
| EIP207_Global_Error_t |
| EIP207_ICE_ClockCount_Get( |
| const Device_Handle_t Device, |
| const unsigned int CE_Number, |
| EIP207_Global_Value64_t * const ICE_Clock_p) |
| { |
| return EIP207_Global_Read64( |
| Device, |
| EIP207_ICE_REG_SCRATCH_RAM(CE_Number) + |
| FIRMWARE_EIP207_CS_ADMIN_RAM_TIME_LO_BYTE_OFFSET, |
| EIP207_ICE_REG_SCRATCH_RAM(CE_Number) + |
| FIRMWARE_EIP207_CS_ADMIN_RAM_TIME_HI_BYTE_OFFSET, |
| ICE_Clock_p); |
| } |
| |
| |
| /*----------------------------------------------------------------------------- |
| * EIP207_ICE_Status_Get |
| */ |
| EIP207_Global_Error_t |
| EIP207_ICE_Status_Get( |
| const Device_Handle_t Device, |
| const unsigned int CE_Number, |
| EIP207_Global_CE_Status_t * const ICE_Status_p) |
| { |
| EIP207_ICE_PUE_CTRL_RD_CLEAR(Device, |
| CE_Number, |
| &ICE_Status_p->fPUE_EccCorr, |
| &ICE_Status_p->fPUE_EccDerr); |
| |
| EIP207_ICE_FPP_CTRL_RD_CLEAR(Device, |
| CE_Number, |
| &ICE_Status_p->fFPP_EccCorr, |
| &ICE_Status_p->fFPP_EccDerr); |
| |
| EIP207_ICE_SCRATCH_CTRL_RD(Device, |
| CE_Number, |
| &ICE_Status_p->fTimerOverflow); |
| |
| return EIP207_GLOBAL_NO_ERROR; |
| } |
| |
| |
| /* end of file eip207_ice.c */ |