2 * @file IxNpeMhConfig.c
4 * @author Intel Corporation
7 * @brief This file contains the implementation of the private API for the
8 * Configuration module.
12 * IXP400 SW Release version 2.0
14 * -- Copyright Notice --
17 * Copyright 2001-2005, Intel Corporation.
18 * All rights reserved.
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions
24 * 1. Redistributions of source code must retain the above copyright
25 * notice, this list of conditions and the following disclaimer.
26 * 2. Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in the
28 * documentation and/or other materials provided with the distribution.
29 * 3. Neither the name of the Intel Corporation nor the names of its contributors
30 * may be used to endorse or promote products derived from this software
31 * without specific prior written permission.
34 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
35 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
38 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * -- End of Copyright Notice --
51 * Put the system defined include files required.
56 * Put the user defined include files required.
61 #include "IxNpeMhMacros_p.h"
63 #include "IxNpeMhConfig_p.h"
66 * #defines and macros used in this file.
68 #define IX_NPE_MH_MAX_NUM_OF_RETRIES 1000000 /**< Maximum number of
74 * Typedefs whose scope is limited to this file.
78 * @struct IxNpeMhConfigStats
80 * @brief This structure is used to maintain statistics for the
81 * Configuration module.
86 UINT32 outFifoReads; /**< outFifo reads */
87 UINT32 inFifoWrites; /**< inFifo writes */
88 UINT32 maxInFifoFullRetries; /**< max retries if inFIFO full */
89 UINT32 maxOutFifoEmptyRetries; /**< max retries if outFIFO empty */
93 * Variable declarations global to this file only. Externs are followed by
97 IxNpeMhConfigNpeInfo ixNpeMhConfigNpeInfo[IX_NPEMH_NUM_NPES] =
134 PRIVATE IxNpeMhConfigStats ixNpeMhConfigStats[IX_NPEMH_NUM_NPES];
137 * Extern function prototypes.
141 * Static function prototypes.
144 void ixNpeMhConfigIsr (void *parameter);
147 * Function definition: ixNpeMhConfigIsr
151 void ixNpeMhConfigIsr (void *parameter)
153 IxNpeMhNpeId npeId = (IxNpeMhNpeId)parameter;
155 volatile UINT32 *statusReg =
156 (UINT32 *)ixNpeMhConfigNpeInfo[npeId].statusRegister;
158 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
159 "ixNpeMhConfigIsr\n");
161 /* get the OFINT (OutFifo interrupt) bit of the status register */
162 IX_NPEMH_REGISTER_READ_BITS (statusReg, &ofint, IX_NPEMH_NPE_STAT_OFINT);
164 /* if the OFINT status bit is set */
167 /* if there is an ISR registered for this NPE */
168 if (ixNpeMhConfigNpeInfo[npeId].isr != NULL)
170 /* invoke the ISR routine */
171 ixNpeMhConfigNpeInfo[npeId].isr (npeId);
175 /* if we don't service the interrupt the NPE will continue */
176 /* to trigger the interrupt indefinitely */
177 IX_NPEMH_ERROR_REPORT ("No ISR registered to service "
182 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
183 "ixNpeMhConfigIsr\n");
187 * Function definition: ixNpeMhConfigInitialize
190 void ixNpeMhConfigInitialize (
191 IxNpeMhNpeInterrupts npeInterrupts)
194 UINT32 virtualAddr[IX_NPEMH_NUM_NPES];
196 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
197 "ixNpeMhConfigInitialize\n");
199 /* Request a mapping for the NPE-A config register address space */
200 virtualAddr[IX_NPEMH_NPEID_NPEA] =
201 (UINT32) IX_OSAL_MEM_MAP (IX_NPEMH_NPEA_BASE,
202 IX_OSAL_IXP400_NPEA_MAP_SIZE);
203 IX_OSAL_ASSERT (virtualAddr[IX_NPEMH_NPEID_NPEA]);
205 /* Request a mapping for the NPE-B config register address space */
206 virtualAddr[IX_NPEMH_NPEID_NPEB] =
207 (UINT32) IX_OSAL_MEM_MAP (IX_NPEMH_NPEB_BASE,
208 IX_OSAL_IXP400_NPEB_MAP_SIZE);
209 IX_OSAL_ASSERT (virtualAddr[IX_NPEMH_NPEID_NPEB]);
211 /* Request a mapping for the NPE-C config register address space */
212 virtualAddr[IX_NPEMH_NPEID_NPEC] =
213 (UINT32) IX_OSAL_MEM_MAP (IX_NPEMH_NPEC_BASE,
214 IX_OSAL_IXP400_NPEC_MAP_SIZE);
215 IX_OSAL_ASSERT (virtualAddr[IX_NPEMH_NPEID_NPEC]);
217 /* for each NPE ... */
218 for (npeId = 0; npeId < IX_NPEMH_NUM_NPES; npeId++)
220 /* declare a convenience pointer */
221 IxNpeMhConfigNpeInfo *npeInfo = &ixNpeMhConfigNpeInfo[npeId];
223 /* store the virtual addresses of the NPE registers for later use */
224 npeInfo->virtualRegisterBase = virtualAddr[npeId];
225 npeInfo->statusRegister = virtualAddr[npeId] + IX_NPEMH_NPESTAT_OFFSET;
226 npeInfo->controlRegister = virtualAddr[npeId] + IX_NPEMH_NPECTL_OFFSET;
227 npeInfo->inFifoRegister = virtualAddr[npeId] + IX_NPEMH_NPEFIFO_OFFSET;
228 npeInfo->outFifoRegister = virtualAddr[npeId] + IX_NPEMH_NPEFIFO_OFFSET;
230 /* for test purposes - to verify the register addresses */
231 IX_NPEMH_TRACE2 (IX_NPEMH_DEBUG, "NPE %d status register = "
232 "0x%08X\n", npeId, npeInfo->statusRegister);
233 IX_NPEMH_TRACE2 (IX_NPEMH_DEBUG, "NPE %d control register = "
234 "0x%08X\n", npeId, npeInfo->controlRegister);
235 IX_NPEMH_TRACE2 (IX_NPEMH_DEBUG, "NPE %d inFifo register = "
236 "0x%08X\n", npeId, npeInfo->inFifoRegister);
237 IX_NPEMH_TRACE2 (IX_NPEMH_DEBUG, "NPE %d outFifo register = "
238 "0x%08X\n", npeId, npeInfo->outFifoRegister);
240 /* connect our ISR to the NPE interrupt */
241 (void) ixOsalIrqBind (
242 npeInfo->interruptId, ixNpeMhConfigIsr, (void *)npeId);
244 /* initialise a mutex for this NPE */
245 (void) ixOsalMutexInit (&npeInfo->mutex);
247 /* if we should service the NPE's "outFIFO not empty" interrupt */
248 if (npeInterrupts == IX_NPEMH_NPEINTERRUPTS_YES)
250 /* enable the NPE's "outFIFO not empty" interrupt */
251 ixNpeMhConfigNpeInterruptEnable (npeId);
255 /* disable the NPE's "outFIFO not empty" interrupt */
256 ixNpeMhConfigNpeInterruptDisable (npeId);
260 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
261 "ixNpeMhConfigInitialize\n");
265 * Function definition: ixNpeMhConfigUninit
268 void ixNpeMhConfigUninit (void)
272 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
273 "ixNpeMhConfigUninit\n");
275 /* for each NPE ... */
276 for (npeId = 0; npeId < IX_NPEMH_NUM_NPES; npeId++)
278 /* declare a convenience pointer */
279 IxNpeMhConfigNpeInfo *npeInfo = &ixNpeMhConfigNpeInfo[npeId];
282 ixOsalIrqUnbind(npeInfo->interruptId);
284 /* destroy mutex associated with this NPE */
285 ixOsalMutexDestroy(&npeInfo->mutex);
287 IX_OSAL_MEM_UNMAP (npeInfo->virtualRegisterBase);
289 npeInfo->virtualRegisterBase = 0;
290 npeInfo->statusRegister = 0;
291 npeInfo->controlRegister = 0;
292 npeInfo->inFifoRegister = 0;
293 npeInfo->outFifoRegister = 0;
296 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
297 "ixNpeMhConfigUninit\n");
301 * Function definition: ixNpeMhConfigIsrRegister
304 void ixNpeMhConfigIsrRegister (
306 IxNpeMhConfigIsr isr)
308 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
309 "ixNpeMhConfigIsrRegister\n");
311 /* check if there is already an ISR registered for this NPE */
312 if (ixNpeMhConfigNpeInfo[npeId].isr != NULL)
314 IX_NPEMH_TRACE0 (IX_NPEMH_DEBUG, "Over-writing registered NPE ISR\n");
317 /* save the ISR routine with the NPE info */
318 ixNpeMhConfigNpeInfo[npeId].isr = isr;
320 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
321 "ixNpeMhConfigIsrRegister\n");
325 * Function definition: ixNpeMhConfigNpeInterruptEnable
328 BOOL ixNpeMhConfigNpeInterruptEnable (
332 volatile UINT32 *controlReg =
333 (UINT32 *)ixNpeMhConfigNpeInfo[npeId].controlRegister;
335 /* get the OFE (OutFifoEnable) bit of the control register */
336 IX_NPEMH_REGISTER_READ_BITS (controlReg, &ofe, IX_NPEMH_NPE_CTL_OFE);
338 /* if the interrupt is disabled then we must enable it */
341 /* set the OFE (OutFifoEnable) bit of the control register */
342 /* we must set the OFEWE (OutFifoEnableWriteEnable) at the same */
343 /* time for the write to have effect */
344 IX_NPEMH_REGISTER_WRITE_BITS (controlReg,
345 (IX_NPEMH_NPE_CTL_OFE |
346 IX_NPEMH_NPE_CTL_OFEWE),
347 (IX_NPEMH_NPE_CTL_OFE |
348 IX_NPEMH_NPE_CTL_OFEWE));
351 /* return the previous state of the interrupt */
356 * Function definition: ixNpeMhConfigNpeInterruptDisable
359 BOOL ixNpeMhConfigNpeInterruptDisable (
363 volatile UINT32 *controlReg =
364 (UINT32 *)ixNpeMhConfigNpeInfo[npeId].controlRegister;
366 /* get the OFE (OutFifoEnable) bit of the control register */
367 IX_NPEMH_REGISTER_READ_BITS (controlReg, &ofe, IX_NPEMH_NPE_CTL_OFE);
369 /* if the interrupt is enabled then we must disable it */
372 /* unset the OFE (OutFifoEnable) bit of the control register */
373 /* we must set the OFEWE (OutFifoEnableWriteEnable) at the same */
374 /* time for the write to have effect */
375 IX_NPEMH_REGISTER_WRITE_BITS (controlReg,
377 IX_NPEMH_NPE_CTL_OFEWE),
378 (IX_NPEMH_NPE_CTL_OFE |
379 IX_NPEMH_NPE_CTL_OFEWE));
382 /* return the previous state of the interrupt */
387 * Function definition: ixNpeMhConfigMessageIdGet
390 IxNpeMhMessageId ixNpeMhConfigMessageIdGet (
391 IxNpeMhMessage message)
393 /* return the most-significant byte of the first word of the */
395 return ((IxNpeMhMessageId) ((message.data[0] >> 24) & 0xFF));
399 * Function definition: ixNpeMhConfigNpeIdIsValid
402 BOOL ixNpeMhConfigNpeIdIsValid (
405 /* check that the npeId parameter is within the range of valid IDs */
406 return (npeId >= 0 && npeId < IX_NPEMH_NUM_NPES);
410 * Function definition: ixNpeMhConfigLockGet
413 void ixNpeMhConfigLockGet (
416 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
417 "ixNpeMhConfigLockGet\n");
419 /* lock the mutex for this NPE */
420 (void) ixOsalMutexLock (&ixNpeMhConfigNpeInfo[npeId].mutex,
421 IX_OSAL_WAIT_FOREVER);
423 /* disable the NPE's "outFIFO not empty" interrupt */
424 ixNpeMhConfigNpeInfo[npeId].oldInterruptState =
425 ixNpeMhConfigNpeInterruptDisable (npeId);
427 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
428 "ixNpeMhConfigLockGet\n");
432 * Function definition: ixNpeMhConfigLockRelease
435 void ixNpeMhConfigLockRelease (
438 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering "
439 "ixNpeMhConfigLockRelease\n");
441 /* if the interrupt was previously enabled */
442 if (ixNpeMhConfigNpeInfo[npeId].oldInterruptState)
444 /* enable the NPE's "outFIFO not empty" interrupt */
445 ixNpeMhConfigNpeInfo[npeId].oldInterruptState =
446 ixNpeMhConfigNpeInterruptEnable (npeId);
449 /* unlock the mutex for this NPE */
450 (void) ixOsalMutexUnlock (&ixNpeMhConfigNpeInfo[npeId].mutex);
452 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting "
453 "ixNpeMhConfigLockRelease\n");
457 * Function definition: ixNpeMhConfigInFifoWrite
460 IX_STATUS ixNpeMhConfigInFifoWrite (
462 IxNpeMhMessage message)
464 volatile UINT32 *npeInFifo =
465 (UINT32 *)ixNpeMhConfigNpeInfo[npeId].inFifoRegister;
466 UINT32 retriesCount = 0;
468 /* write the first word of the message to the NPE's inFIFO */
469 IX_NPEMH_REGISTER_WRITE (npeInFifo, message.data[0]);
471 /* need to wait for room to write second word - see SCR #493,
472 poll for maximum number of retries, if exceed maximum
473 retries, exit from while loop */
474 while ((IX_NPE_MH_MAX_NUM_OF_RETRIES > retriesCount)
475 && ixNpeMhConfigInFifoIsFull (npeId))
480 /* Return TIMEOUT status to caller, indicate that NPE Hang / Halt */
481 if (IX_NPE_MH_MAX_NUM_OF_RETRIES == retriesCount)
483 return IX_NPEMH_CRITICAL_NPE_ERR;
486 /* write the second word of the message to the NPE's inFIFO */
487 IX_NPEMH_REGISTER_WRITE (npeInFifo, message.data[1]);
489 /* record in the stats the maximum number of retries needed */
490 if (ixNpeMhConfigStats[npeId].maxInFifoFullRetries < retriesCount)
492 ixNpeMhConfigStats[npeId].maxInFifoFullRetries = retriesCount;
495 /* update statistical info */
496 ixNpeMhConfigStats[npeId].inFifoWrites++;
502 * Function definition: ixNpeMhConfigOutFifoRead
505 IX_STATUS ixNpeMhConfigOutFifoRead (
507 IxNpeMhMessage *message)
509 volatile UINT32 *npeOutFifo =
510 (UINT32 *)ixNpeMhConfigNpeInfo[npeId].outFifoRegister;
511 UINT32 retriesCount = 0;
513 /* read the first word of the message from the NPE's outFIFO */
514 IX_NPEMH_REGISTER_READ (npeOutFifo, &message->data[0]);
516 /* need to wait for NPE to write second word - see SCR #493
517 poll for maximum number of retries, if exceed maximum
518 retries, exit from while loop */
519 while ((IX_NPE_MH_MAX_NUM_OF_RETRIES > retriesCount)
520 && ixNpeMhConfigOutFifoIsEmpty (npeId))
525 /* Return TIMEOUT status to caller, indicate that NPE Hang / Halt */
526 if (IX_NPE_MH_MAX_NUM_OF_RETRIES == retriesCount)
528 return IX_NPEMH_CRITICAL_NPE_ERR;
531 /* read the second word of the message from the NPE's outFIFO */
532 IX_NPEMH_REGISTER_READ (npeOutFifo, &message->data[1]);
534 /* record in the stats the maximum number of retries needed */
535 if (ixNpeMhConfigStats[npeId].maxOutFifoEmptyRetries < retriesCount)
537 ixNpeMhConfigStats[npeId].maxOutFifoEmptyRetries = retriesCount;
540 /* update statistical info */
541 ixNpeMhConfigStats[npeId].outFifoReads++;
547 * Function definition: ixNpeMhConfigShow
550 void ixNpeMhConfigShow (
553 /* show the message fifo read counter */
554 IX_NPEMH_SHOW ("Message FIFO reads",
555 ixNpeMhConfigStats[npeId].outFifoReads);
557 /* show the message fifo write counter */
558 IX_NPEMH_SHOW ("Message FIFO writes",
559 ixNpeMhConfigStats[npeId].inFifoWrites);
561 /* show the max retries performed when inFIFO full */
562 IX_NPEMH_SHOW ("Max inFIFO Full retries",
563 ixNpeMhConfigStats[npeId].maxInFifoFullRetries);
565 /* show the max retries performed when outFIFO empty */
566 IX_NPEMH_SHOW ("Max outFIFO Empty retries",
567 ixNpeMhConfigStats[npeId].maxOutFifoEmptyRetries);
569 /* show the current status of the inFifo */
570 ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT,
571 "InFifo is %s and %s\n",
572 (ixNpeMhConfigInFifoIsEmpty (npeId) ?
573 (int) "EMPTY" : (int) "NOT EMPTY"),
574 (ixNpeMhConfigInFifoIsFull (npeId) ?
575 (int) "FULL" : (int) "NOT FULL"),
578 /* show the current status of the outFifo */
579 ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT,
580 "OutFifo is %s and %s\n",
581 (ixNpeMhConfigOutFifoIsEmpty (npeId) ?
582 (int) "EMPTY" : (int) "NOT EMPTY"),
583 (ixNpeMhConfigOutFifoIsFull (npeId) ?
584 (int) "FULL" : (int) "NOT FULL"),
589 * Function definition: ixNpeMhConfigShowReset
592 void ixNpeMhConfigShowReset (
595 /* reset the message fifo read counter */
596 ixNpeMhConfigStats[npeId].outFifoReads = 0;
598 /* reset the message fifo write counter */
599 ixNpeMhConfigStats[npeId].inFifoWrites = 0;
601 /* reset the max inFIFO Full retries counter */
602 ixNpeMhConfigStats[npeId].maxInFifoFullRetries = 0;
604 /* reset the max outFIFO empty retries counter */
605 ixNpeMhConfigStats[npeId].maxOutFifoEmptyRetries = 0;