| /** |
| * @file IxNpeMhConfig.c |
| * |
| * @author Intel Corporation |
| * @date 18 Jan 2002 |
| * |
| * @brief This file contains the implementation of the private API for the |
| * Configuration module. |
| * |
| * |
| * @par |
| * IXP400 SW Release version 2.0 |
| * |
| * -- Copyright Notice -- |
| * |
| * @par |
| * Copyright 2001-2005, Intel Corporation. |
| * All rights reserved. |
| * |
| * @par |
| * SPDX-License-Identifier: BSD-3-Clause |
| * @par |
| * -- End of Copyright Notice -- |
| */ |
| |
| /* |
| * Put the system defined include files required. |
| */ |
| |
| |
| /* |
| * Put the user defined include files required. |
| */ |
| |
| #include "IxOsal.h" |
| |
| #include "IxNpeMhMacros_p.h" |
| |
| #include "IxNpeMhConfig_p.h" |
| |
| /* |
| * #defines and macros used in this file. |
| */ |
| #define IX_NPE_MH_MAX_NUM_OF_RETRIES 1000000 /**< Maximum number of |
| * retries before |
| * timeout |
| */ |
| |
| /* |
| * Typedefs whose scope is limited to this file. |
| */ |
| |
| /** |
| * @struct IxNpeMhConfigStats |
| * |
| * @brief This structure is used to maintain statistics for the |
| * Configuration module. |
| */ |
| |
| typedef struct |
| { |
| UINT32 outFifoReads; /**< outFifo reads */ |
| UINT32 inFifoWrites; /**< inFifo writes */ |
| UINT32 maxInFifoFullRetries; /**< max retries if inFIFO full */ |
| UINT32 maxOutFifoEmptyRetries; /**< max retries if outFIFO empty */ |
| } IxNpeMhConfigStats; |
| |
| /* |
| * Variable declarations global to this file only. Externs are followed by |
| * static variables. |
| */ |
| |
| IxNpeMhConfigNpeInfo ixNpeMhConfigNpeInfo[IX_NPEMH_NUM_NPES] = |
| { |
| { |
| 0, |
| IX_NPEMH_NPEA_INT, |
| 0, |
| 0, |
| 0, |
| 0, |
| 0, |
| NULL, |
| false |
| }, |
| { |
| 0, |
| IX_NPEMH_NPEB_INT, |
| 0, |
| 0, |
| 0, |
| 0, |
| 0, |
| NULL, |
| false |
| }, |
| { |
| 0, |
| IX_NPEMH_NPEC_INT, |
| 0, |
| 0, |
| 0, |
| 0, |
| 0, |
| NULL, |
| false |
| } |
| }; |
| |
| PRIVATE IxNpeMhConfigStats ixNpeMhConfigStats[IX_NPEMH_NUM_NPES]; |
| |
| /* |
| * Extern function prototypes. |
| */ |
| |
| /* |
| * Static function prototypes. |
| */ |
| PRIVATE |
| void ixNpeMhConfigIsr (void *parameter); |
| |
| /* |
| * Function definition: ixNpeMhConfigIsr |
| */ |
| |
| PRIVATE |
| void ixNpeMhConfigIsr (void *parameter) |
| { |
| IxNpeMhNpeId npeId = (IxNpeMhNpeId)parameter; |
| UINT32 ofint; |
| volatile UINT32 *statusReg = |
| (UINT32 *)ixNpeMhConfigNpeInfo[npeId].statusRegister; |
| |
| IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering " |
| "ixNpeMhConfigIsr\n"); |
| |
| /* get the OFINT (OutFifo interrupt) bit of the status register */ |
| IX_NPEMH_REGISTER_READ_BITS (statusReg, &ofint, IX_NPEMH_NPE_STAT_OFINT); |
| |
| /* if the OFINT status bit is set */ |
| if (ofint) |
| { |
| /* if there is an ISR registered for this NPE */ |
| if (ixNpeMhConfigNpeInfo[npeId].isr != NULL) |
| { |
| /* invoke the ISR routine */ |
| ixNpeMhConfigNpeInfo[npeId].isr (npeId); |
| } |
| else |
| { |
| /* if we don't service the interrupt the NPE will continue */ |
| /* to trigger the interrupt indefinitely */ |
| IX_NPEMH_ERROR_REPORT ("No ISR registered to service " |
| "interrupt\n"); |
| } |
| } |
| |
| IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting " |
| "ixNpeMhConfigIsr\n"); |
| } |
| |
| /* |
| * Function definition: ixNpeMhConfigInitialize |
| */ |
| |
| void ixNpeMhConfigInitialize ( |
| IxNpeMhNpeInterrupts npeInterrupts) |
| { |
| IxNpeMhNpeId npeId; |
| UINT32 virtualAddr[IX_NPEMH_NUM_NPES]; |
| |
| IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering " |
| "ixNpeMhConfigInitialize\n"); |
| |
| /* Request a mapping for the NPE-A config register address space */ |
| virtualAddr[IX_NPEMH_NPEID_NPEA] = |
| (UINT32) IX_OSAL_MEM_MAP (IX_NPEMH_NPEA_BASE, |
| IX_OSAL_IXP400_NPEA_MAP_SIZE); |
| IX_OSAL_ASSERT (virtualAddr[IX_NPEMH_NPEID_NPEA]); |
| |
| /* Request a mapping for the NPE-B config register address space */ |
| virtualAddr[IX_NPEMH_NPEID_NPEB] = |
| (UINT32) IX_OSAL_MEM_MAP (IX_NPEMH_NPEB_BASE, |
| IX_OSAL_IXP400_NPEB_MAP_SIZE); |
| IX_OSAL_ASSERT (virtualAddr[IX_NPEMH_NPEID_NPEB]); |
| |
| /* Request a mapping for the NPE-C config register address space */ |
| virtualAddr[IX_NPEMH_NPEID_NPEC] = |
| (UINT32) IX_OSAL_MEM_MAP (IX_NPEMH_NPEC_BASE, |
| IX_OSAL_IXP400_NPEC_MAP_SIZE); |
| IX_OSAL_ASSERT (virtualAddr[IX_NPEMH_NPEID_NPEC]); |
| |
| /* for each NPE ... */ |
| for (npeId = 0; npeId < IX_NPEMH_NUM_NPES; npeId++) |
| { |
| /* declare a convenience pointer */ |
| IxNpeMhConfigNpeInfo *npeInfo = &ixNpeMhConfigNpeInfo[npeId]; |
| |
| /* store the virtual addresses of the NPE registers for later use */ |
| npeInfo->virtualRegisterBase = virtualAddr[npeId]; |
| npeInfo->statusRegister = virtualAddr[npeId] + IX_NPEMH_NPESTAT_OFFSET; |
| npeInfo->controlRegister = virtualAddr[npeId] + IX_NPEMH_NPECTL_OFFSET; |
| npeInfo->inFifoRegister = virtualAddr[npeId] + IX_NPEMH_NPEFIFO_OFFSET; |
| npeInfo->outFifoRegister = virtualAddr[npeId] + IX_NPEMH_NPEFIFO_OFFSET; |
| |
| /* for test purposes - to verify the register addresses */ |
| IX_NPEMH_TRACE2 (IX_NPEMH_DEBUG, "NPE %d status register = " |
| "0x%08X\n", npeId, npeInfo->statusRegister); |
| IX_NPEMH_TRACE2 (IX_NPEMH_DEBUG, "NPE %d control register = " |
| "0x%08X\n", npeId, npeInfo->controlRegister); |
| IX_NPEMH_TRACE2 (IX_NPEMH_DEBUG, "NPE %d inFifo register = " |
| "0x%08X\n", npeId, npeInfo->inFifoRegister); |
| IX_NPEMH_TRACE2 (IX_NPEMH_DEBUG, "NPE %d outFifo register = " |
| "0x%08X\n", npeId, npeInfo->outFifoRegister); |
| |
| /* connect our ISR to the NPE interrupt */ |
| (void) ixOsalIrqBind ( |
| npeInfo->interruptId, ixNpeMhConfigIsr, (void *)npeId); |
| |
| /* initialise a mutex for this NPE */ |
| (void) ixOsalMutexInit (&npeInfo->mutex); |
| |
| /* if we should service the NPE's "outFIFO not empty" interrupt */ |
| if (npeInterrupts == IX_NPEMH_NPEINTERRUPTS_YES) |
| { |
| /* enable the NPE's "outFIFO not empty" interrupt */ |
| ixNpeMhConfigNpeInterruptEnable (npeId); |
| } |
| else |
| { |
| /* disable the NPE's "outFIFO not empty" interrupt */ |
| ixNpeMhConfigNpeInterruptDisable (npeId); |
| } |
| } |
| |
| IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting " |
| "ixNpeMhConfigInitialize\n"); |
| } |
| |
| /* |
| * Function definition: ixNpeMhConfigUninit |
| */ |
| |
| void ixNpeMhConfigUninit (void) |
| { |
| IxNpeMhNpeId npeId; |
| |
| IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering " |
| "ixNpeMhConfigUninit\n"); |
| |
| /* for each NPE ... */ |
| for (npeId = 0; npeId < IX_NPEMH_NUM_NPES; npeId++) |
| { |
| /* declare a convenience pointer */ |
| IxNpeMhConfigNpeInfo *npeInfo = &ixNpeMhConfigNpeInfo[npeId]; |
| |
| /* disconnect ISR */ |
| ixOsalIrqUnbind(npeInfo->interruptId); |
| |
| /* destroy mutex associated with this NPE */ |
| ixOsalMutexDestroy(&npeInfo->mutex); |
| |
| IX_OSAL_MEM_UNMAP (npeInfo->virtualRegisterBase); |
| |
| npeInfo->virtualRegisterBase = 0; |
| npeInfo->statusRegister = 0; |
| npeInfo->controlRegister = 0; |
| npeInfo->inFifoRegister = 0; |
| npeInfo->outFifoRegister = 0; |
| } |
| |
| IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting " |
| "ixNpeMhConfigUninit\n"); |
| } |
| |
| /* |
| * Function definition: ixNpeMhConfigIsrRegister |
| */ |
| |
| void ixNpeMhConfigIsrRegister ( |
| IxNpeMhNpeId npeId, |
| IxNpeMhConfigIsr isr) |
| { |
| IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering " |
| "ixNpeMhConfigIsrRegister\n"); |
| |
| /* check if there is already an ISR registered for this NPE */ |
| if (ixNpeMhConfigNpeInfo[npeId].isr != NULL) |
| { |
| IX_NPEMH_TRACE0 (IX_NPEMH_DEBUG, "Over-writing registered NPE ISR\n"); |
| } |
| |
| /* save the ISR routine with the NPE info */ |
| ixNpeMhConfigNpeInfo[npeId].isr = isr; |
| |
| IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting " |
| "ixNpeMhConfigIsrRegister\n"); |
| } |
| |
| /* |
| * Function definition: ixNpeMhConfigNpeInterruptEnable |
| */ |
| |
| BOOL ixNpeMhConfigNpeInterruptEnable ( |
| IxNpeMhNpeId npeId) |
| { |
| UINT32 ofe; |
| volatile UINT32 *controlReg = |
| (UINT32 *)ixNpeMhConfigNpeInfo[npeId].controlRegister; |
| |
| /* get the OFE (OutFifoEnable) bit of the control register */ |
| IX_NPEMH_REGISTER_READ_BITS (controlReg, &ofe, IX_NPEMH_NPE_CTL_OFE); |
| |
| /* if the interrupt is disabled then we must enable it */ |
| if (!ofe) |
| { |
| /* set the OFE (OutFifoEnable) bit of the control register */ |
| /* we must set the OFEWE (OutFifoEnableWriteEnable) at the same */ |
| /* time for the write to have effect */ |
| IX_NPEMH_REGISTER_WRITE_BITS (controlReg, |
| (IX_NPEMH_NPE_CTL_OFE | |
| IX_NPEMH_NPE_CTL_OFEWE), |
| (IX_NPEMH_NPE_CTL_OFE | |
| IX_NPEMH_NPE_CTL_OFEWE)); |
| } |
| |
| /* return the previous state of the interrupt */ |
| return (ofe != 0); |
| } |
| |
| /* |
| * Function definition: ixNpeMhConfigNpeInterruptDisable |
| */ |
| |
| BOOL ixNpeMhConfigNpeInterruptDisable ( |
| IxNpeMhNpeId npeId) |
| { |
| UINT32 ofe; |
| volatile UINT32 *controlReg = |
| (UINT32 *)ixNpeMhConfigNpeInfo[npeId].controlRegister; |
| |
| /* get the OFE (OutFifoEnable) bit of the control register */ |
| IX_NPEMH_REGISTER_READ_BITS (controlReg, &ofe, IX_NPEMH_NPE_CTL_OFE); |
| |
| /* if the interrupt is enabled then we must disable it */ |
| if (ofe) |
| { |
| /* unset the OFE (OutFifoEnable) bit of the control register */ |
| /* we must set the OFEWE (OutFifoEnableWriteEnable) at the same */ |
| /* time for the write to have effect */ |
| IX_NPEMH_REGISTER_WRITE_BITS (controlReg, |
| (0 | |
| IX_NPEMH_NPE_CTL_OFEWE), |
| (IX_NPEMH_NPE_CTL_OFE | |
| IX_NPEMH_NPE_CTL_OFEWE)); |
| } |
| |
| /* return the previous state of the interrupt */ |
| return (ofe != 0); |
| } |
| |
| /* |
| * Function definition: ixNpeMhConfigMessageIdGet |
| */ |
| |
| IxNpeMhMessageId ixNpeMhConfigMessageIdGet ( |
| IxNpeMhMessage message) |
| { |
| /* return the most-significant byte of the first word of the */ |
| /* message */ |
| return ((IxNpeMhMessageId) ((message.data[0] >> 24) & 0xFF)); |
| } |
| |
| /* |
| * Function definition: ixNpeMhConfigNpeIdIsValid |
| */ |
| |
| BOOL ixNpeMhConfigNpeIdIsValid ( |
| IxNpeMhNpeId npeId) |
| { |
| /* check that the npeId parameter is within the range of valid IDs */ |
| return (npeId >= 0 && npeId < IX_NPEMH_NUM_NPES); |
| } |
| |
| /* |
| * Function definition: ixNpeMhConfigLockGet |
| */ |
| |
| void ixNpeMhConfigLockGet ( |
| IxNpeMhNpeId npeId) |
| { |
| IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering " |
| "ixNpeMhConfigLockGet\n"); |
| |
| /* lock the mutex for this NPE */ |
| (void) ixOsalMutexLock (&ixNpeMhConfigNpeInfo[npeId].mutex, |
| IX_OSAL_WAIT_FOREVER); |
| |
| /* disable the NPE's "outFIFO not empty" interrupt */ |
| ixNpeMhConfigNpeInfo[npeId].oldInterruptState = |
| ixNpeMhConfigNpeInterruptDisable (npeId); |
| |
| IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting " |
| "ixNpeMhConfigLockGet\n"); |
| } |
| |
| /* |
| * Function definition: ixNpeMhConfigLockRelease |
| */ |
| |
| void ixNpeMhConfigLockRelease ( |
| IxNpeMhNpeId npeId) |
| { |
| IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering " |
| "ixNpeMhConfigLockRelease\n"); |
| |
| /* if the interrupt was previously enabled */ |
| if (ixNpeMhConfigNpeInfo[npeId].oldInterruptState) |
| { |
| /* enable the NPE's "outFIFO not empty" interrupt */ |
| ixNpeMhConfigNpeInfo[npeId].oldInterruptState = |
| ixNpeMhConfigNpeInterruptEnable (npeId); |
| } |
| |
| /* unlock the mutex for this NPE */ |
| (void) ixOsalMutexUnlock (&ixNpeMhConfigNpeInfo[npeId].mutex); |
| |
| IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting " |
| "ixNpeMhConfigLockRelease\n"); |
| } |
| |
| /* |
| * Function definition: ixNpeMhConfigInFifoWrite |
| */ |
| |
| IX_STATUS ixNpeMhConfigInFifoWrite ( |
| IxNpeMhNpeId npeId, |
| IxNpeMhMessage message) |
| { |
| volatile UINT32 *npeInFifo = |
| (UINT32 *)ixNpeMhConfigNpeInfo[npeId].inFifoRegister; |
| UINT32 retriesCount = 0; |
| |
| /* write the first word of the message to the NPE's inFIFO */ |
| IX_NPEMH_REGISTER_WRITE (npeInFifo, message.data[0]); |
| |
| /* need to wait for room to write second word - see SCR #493, |
| poll for maximum number of retries, if exceed maximum |
| retries, exit from while loop */ |
| while ((IX_NPE_MH_MAX_NUM_OF_RETRIES > retriesCount) |
| && ixNpeMhConfigInFifoIsFull (npeId)) |
| { |
| retriesCount++; |
| } |
| |
| /* Return TIMEOUT status to caller, indicate that NPE Hang / Halt */ |
| if (IX_NPE_MH_MAX_NUM_OF_RETRIES == retriesCount) |
| { |
| return IX_NPEMH_CRITICAL_NPE_ERR; |
| } |
| |
| /* write the second word of the message to the NPE's inFIFO */ |
| IX_NPEMH_REGISTER_WRITE (npeInFifo, message.data[1]); |
| |
| /* record in the stats the maximum number of retries needed */ |
| if (ixNpeMhConfigStats[npeId].maxInFifoFullRetries < retriesCount) |
| { |
| ixNpeMhConfigStats[npeId].maxInFifoFullRetries = retriesCount; |
| } |
| |
| /* update statistical info */ |
| ixNpeMhConfigStats[npeId].inFifoWrites++; |
| |
| return IX_SUCCESS; |
| } |
| |
| /* |
| * Function definition: ixNpeMhConfigOutFifoRead |
| */ |
| |
| IX_STATUS ixNpeMhConfigOutFifoRead ( |
| IxNpeMhNpeId npeId, |
| IxNpeMhMessage *message) |
| { |
| volatile UINT32 *npeOutFifo = |
| (UINT32 *)ixNpeMhConfigNpeInfo[npeId].outFifoRegister; |
| UINT32 retriesCount = 0; |
| |
| /* read the first word of the message from the NPE's outFIFO */ |
| IX_NPEMH_REGISTER_READ (npeOutFifo, &message->data[0]); |
| |
| /* need to wait for NPE to write second word - see SCR #493 |
| poll for maximum number of retries, if exceed maximum |
| retries, exit from while loop */ |
| while ((IX_NPE_MH_MAX_NUM_OF_RETRIES > retriesCount) |
| && ixNpeMhConfigOutFifoIsEmpty (npeId)) |
| { |
| retriesCount++; |
| } |
| |
| /* Return TIMEOUT status to caller, indicate that NPE Hang / Halt */ |
| if (IX_NPE_MH_MAX_NUM_OF_RETRIES == retriesCount) |
| { |
| return IX_NPEMH_CRITICAL_NPE_ERR; |
| } |
| |
| /* read the second word of the message from the NPE's outFIFO */ |
| IX_NPEMH_REGISTER_READ (npeOutFifo, &message->data[1]); |
| |
| /* record in the stats the maximum number of retries needed */ |
| if (ixNpeMhConfigStats[npeId].maxOutFifoEmptyRetries < retriesCount) |
| { |
| ixNpeMhConfigStats[npeId].maxOutFifoEmptyRetries = retriesCount; |
| } |
| |
| /* update statistical info */ |
| ixNpeMhConfigStats[npeId].outFifoReads++; |
| |
| return IX_SUCCESS; |
| } |
| |
| /* |
| * Function definition: ixNpeMhConfigShow |
| */ |
| |
| void ixNpeMhConfigShow ( |
| IxNpeMhNpeId npeId) |
| { |
| /* show the message fifo read counter */ |
| IX_NPEMH_SHOW ("Message FIFO reads", |
| ixNpeMhConfigStats[npeId].outFifoReads); |
| |
| /* show the message fifo write counter */ |
| IX_NPEMH_SHOW ("Message FIFO writes", |
| ixNpeMhConfigStats[npeId].inFifoWrites); |
| |
| /* show the max retries performed when inFIFO full */ |
| IX_NPEMH_SHOW ("Max inFIFO Full retries", |
| ixNpeMhConfigStats[npeId].maxInFifoFullRetries); |
| |
| /* show the max retries performed when outFIFO empty */ |
| IX_NPEMH_SHOW ("Max outFIFO Empty retries", |
| ixNpeMhConfigStats[npeId].maxOutFifoEmptyRetries); |
| |
| /* show the current status of the inFifo */ |
| ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT, |
| "InFifo is %s and %s\n", |
| (ixNpeMhConfigInFifoIsEmpty (npeId) ? |
| (int) "EMPTY" : (int) "NOT EMPTY"), |
| (ixNpeMhConfigInFifoIsFull (npeId) ? |
| (int) "FULL" : (int) "NOT FULL"), |
| 0, 0, 0, 0); |
| |
| /* show the current status of the outFifo */ |
| ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT, |
| "OutFifo is %s and %s\n", |
| (ixNpeMhConfigOutFifoIsEmpty (npeId) ? |
| (int) "EMPTY" : (int) "NOT EMPTY"), |
| (ixNpeMhConfigOutFifoIsFull (npeId) ? |
| (int) "FULL" : (int) "NOT FULL"), |
| 0, 0, 0, 0); |
| } |
| |
| /* |
| * Function definition: ixNpeMhConfigShowReset |
| */ |
| |
| void ixNpeMhConfigShowReset ( |
| IxNpeMhNpeId npeId) |
| { |
| /* reset the message fifo read counter */ |
| ixNpeMhConfigStats[npeId].outFifoReads = 0; |
| |
| /* reset the message fifo write counter */ |
| ixNpeMhConfigStats[npeId].inFifoWrites = 0; |
| |
| /* reset the max inFIFO Full retries counter */ |
| ixNpeMhConfigStats[npeId].maxInFifoFullRetries = 0; |
| |
| /* reset the max outFIFO empty retries counter */ |
| ixNpeMhConfigStats[npeId].maxOutFifoEmptyRetries = 0; |
| } |
| |
| |