The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/pms/RefTisa/sallsdk/spc/mpi.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*******************************************************************************
    2 **
    3 *Copyright (c) 2014 PMC-Sierra, Inc.  All rights reserved. 
    4 *
    5 *Redistribution and use in source and binary forms, with or without modification, are permitted provided 
    6 *that the following conditions are met: 
    7 *1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
    8 *following disclaimer. 
    9 *2. Redistributions in binary form must reproduce the above copyright notice, 
   10 *this list of conditions and the following disclaimer in the documentation and/or other materials provided
   11 *with the distribution. 
   12 *
   13 *THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED 
   14 *WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   15 *FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   16 *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
   17 *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
   18 *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
   19 *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
   20 *SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
   21 
   22 ********************************************************************************/
   23 
   24 /*******************************************************************************/
   25 /*! \file mpi.c
   26  *  \brief The file is a MPI Libraries to implement the MPI functions
   27  *
   28  * The file implements the MPI Library functions.
   29  *
   30  */
   31 /*******************************************************************************/
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD$");
   34 #include <dev/pms/config.h>
   35 
   36 #include <dev/pms/RefTisa/sallsdk/spc/saglobal.h>
   37 
   38 #ifdef SA_ENABLE_TRACE_FUNCTIONS
   39 #ifdef siTraceFileID
   40 #undef siTraceFileID
   41 #endif
   42 #define siTraceFileID 'A'
   43 #endif
   44 
   45 #ifdef LOOPBACK_MPI
   46 extern int loopback;
   47 #endif
   48 /*******************************************************************************/
   49 
   50 /*******************************************************************************/
   51 /*******************************************************************************/
   52 /* FUNCTIONS                                                                   */
   53 /*******************************************************************************/
   54 /*******************************************************************************/
   55 /** \fn void mpiRequirementsGet(mpiConfig_t* config, mpiMemReq_t* memoryRequirement)
   56  *  \brief Retrieves the MPI layer resource requirements
   57  *  \param config            MPI configuration for the Host MPI Message Unit
   58  *  \param memoryRequirement Returned data structure as defined by mpiMemReq_t
   59  *                           that holds the different chunks of memory that are required
   60  *
   61  * The mpiRequirementsGet() function is used to determine the resource requirements
   62  * for the SPC device interface
   63  *
   64  * Return: None
   65  */
   66 /*******************************************************************************/
   67 void mpiRequirementsGet(mpiConfig_t* config, mpiMemReq_t* memoryRequirement)
   68 {
   69   bit32 qIdx, numq;
   70   mpiMemReq_t* memoryMap;
   71   SA_DBG2(("Entering function:mpiRequirementsGet\n"));
   72   SA_ASSERT((NULL != config), "config argument cannot be null");
   73 
   74   memoryMap = memoryRequirement;
   75   memoryMap->count = 0;
   76 
   77   /* MPI Memory region 0 for MSGU(AAP1) Event Log for fw */
   78   memoryMap->region[memoryMap->count].numElements = 1;
   79   memoryMap->region[memoryMap->count].elementSize = sizeof(bit8) * config->mainConfig.eventLogSize;
   80   memoryMap->region[memoryMap->count].totalLength = sizeof(bit8) * config->mainConfig.eventLogSize;
   81   memoryMap->region[memoryMap->count].alignment = 32;
   82   memoryMap->region[memoryMap->count].type = AGSA_DMA_MEM;
   83   SA_DBG2(("mpiRequirementsGet:eventLogSize region[%d] 0x%X\n",memoryMap->count,memoryMap->region[memoryMap->count].totalLength ));
   84   memoryMap->count++;
   85 
   86   SA_DBG2(("mpiRequirementsGet:eventLogSize region[%d] 0x%X\n",memoryMap->count,memoryMap->region[memoryMap->count].totalLength ));
   87   /* MPI Memory region 1 for IOP Event Log for fw */
   88   memoryMap->region[memoryMap->count].numElements = 1;
   89   memoryMap->region[memoryMap->count].elementSize = sizeof(bit8) * config->mainConfig.IOPeventLogSize;
   90   memoryMap->region[memoryMap->count].totalLength = sizeof(bit8) * config->mainConfig.IOPeventLogSize;
   91   memoryMap->region[memoryMap->count].alignment = 32;
   92   memoryMap->region[memoryMap->count].type = AGSA_DMA_MEM;
   93   SA_DBG2(("mpiRequirementsGet:IOPeventLogSize region[%d] 0x%X\n",memoryMap->count,memoryMap->region[memoryMap->count].totalLength ));
   94   memoryMap->count++;
   95 
   96   /* MPI Memory region 2 for consumer Index of inbound queues */
   97   memoryMap->region[memoryMap->count].numElements = 1;
   98   memoryMap->region[memoryMap->count].elementSize = sizeof(bit32) * config->numInboundQueues;
   99   memoryMap->region[memoryMap->count].totalLength = sizeof(bit32) * config->numInboundQueues;
  100   memoryMap->region[memoryMap->count].alignment = 4;
  101   memoryMap->region[memoryMap->count].type = AGSA_DMA_MEM;
  102   SA_DBG2(("mpiRequirementsGet:numInboundQueues region[%d] 0x%X\n",memoryMap->count,memoryMap->region[memoryMap->count].totalLength ));
  103   memoryMap->count++;
  104 
  105   /* MPI Memory region 3 for producer Index of outbound queues */
  106   memoryMap->region[memoryMap->count].numElements = 1;
  107   memoryMap->region[memoryMap->count].elementSize = sizeof(bit32) * config->numOutboundQueues;
  108   memoryMap->region[memoryMap->count].totalLength = sizeof(bit32) * config->numOutboundQueues;
  109   memoryMap->region[memoryMap->count].alignment = 4;
  110   memoryMap->region[memoryMap->count].type = AGSA_DMA_MEM;
  111   SA_DBG2(("mpiRequirementsGet:numOutboundQueues region[%d] 0x%X\n",memoryMap->count,memoryMap->region[memoryMap->count].totalLength ));
  112   memoryMap->count++;
  113 
  114   /* MPI Memory regions 4, ... for the inbound queues - depends on configuration */
  115   numq = 0;
  116   for(qIdx = 0; qIdx < config->numInboundQueues; qIdx++)
  117   {
  118     if(0 != config->inboundQueues[qIdx].numElements)
  119     {
  120         bit32 memSize = config->inboundQueues[qIdx].numElements * config->inboundQueues[qIdx].elementSize;
  121         bit32 remainder = memSize & 127;
  122 
  123         /* Calculate the size of this queue padded to 128 bytes */
  124         if (remainder > 0)
  125         {
  126             memSize += (128 - remainder);
  127         }
  128 
  129         if (numq == 0)
  130         {
  131             memoryMap->region[memoryMap->count].numElements = 1;
  132             memoryMap->region[memoryMap->count].elementSize = memSize;
  133             memoryMap->region[memoryMap->count].totalLength = memSize;
  134             memoryMap->region[memoryMap->count].alignment = 128;
  135             memoryMap->region[memoryMap->count].type = AGSA_CACHED_DMA_MEM;
  136         }
  137         else
  138         {
  139             memoryMap->region[memoryMap->count].elementSize += memSize;
  140             memoryMap->region[memoryMap->count].totalLength += memSize;
  141         }
  142 
  143         numq++;
  144 
  145         if ((0 == ((qIdx + 1) % MAX_QUEUE_EACH_MEM)) ||
  146             (qIdx == (bit32)(config->numInboundQueues - 1)))
  147         {
  148             SA_DBG2(("mpiRequirementsGet: (inboundQueues) memoryMap->region[%d].elementSize = %d\n",
  149                      memoryMap->count, memoryMap->region[memoryMap->count].elementSize));
  150             SA_DBG2(("mpiRequirementsGet: (inboundQueues) memoryMap->region[%d].numElements = %d\n",
  151                      memoryMap->count, memoryMap->region[memoryMap->count].numElements));
  152 
  153             memoryMap->count++;
  154             numq = 0;
  155         }
  156     }
  157   }
  158 
  159   /* MPI Memory regions for the outbound queues - depends on configuration */
  160   numq = 0;
  161   for(qIdx = 0; qIdx < config->numOutboundQueues; qIdx++)
  162   {
  163     if(0 != config->outboundQueues[qIdx].numElements)
  164     {
  165         bit32 memSize = config->outboundQueues[qIdx].numElements * config->outboundQueues[qIdx].elementSize;
  166         bit32 remainder = memSize & 127;
  167 
  168         /* Calculate the size of this queue padded to 128 bytes */
  169         if (remainder > 0)
  170         {
  171             memSize += (128 - remainder);
  172         }
  173 
  174         if (numq == 0)
  175         {
  176             memoryMap->region[memoryMap->count].numElements = 1;
  177             memoryMap->region[memoryMap->count].elementSize = memSize;
  178             memoryMap->region[memoryMap->count].totalLength = memSize;
  179             memoryMap->region[memoryMap->count].alignment = 128;
  180             memoryMap->region[memoryMap->count].type = AGSA_CACHED_DMA_MEM;
  181         }
  182         else
  183         {
  184             memoryMap->region[memoryMap->count].elementSize += memSize;
  185             memoryMap->region[memoryMap->count].totalLength += memSize;
  186         }
  187 
  188         numq++;
  189 
  190         if ((0 == ((qIdx + 1) % MAX_QUEUE_EACH_MEM)) ||
  191             (qIdx ==  (bit32)(config->numOutboundQueues - 1)))
  192         {
  193             SA_DBG2(("mpiRequirementsGet: (outboundQueues) memoryMap->region[%d].elementSize = %d\n",
  194                      memoryMap->count, memoryMap->region[memoryMap->count].elementSize));
  195             SA_DBG2(("mpiRequirementsGet: (outboundQueues) memoryMap->region[%d].numElements = %d\n",
  196                      memoryMap->count, memoryMap->region[memoryMap->count].numElements));
  197 
  198 
  199             memoryMap->count++;
  200             numq = 0;
  201         }
  202     }
  203   }
  204 
  205 }
  206 
  207 /*******************************************************************************/
  208 /** \fn mpiMsgFreeGet(mpiICQueue_t *circularQ, bit16 messageSize, void** messagePtr)
  209  *  \brief Retrieves a free message buffer from an inbound queue
  210  *  \param circularQ    Pointer to an inbound circular queue
  211  *  \param messageSize  Requested message size in bytes - only support 64 bytes/element
  212  *  \param messagePtr   Pointer to the free message buffer payload (not including message header) or NULL if no free message buffers are available
  213  *
  214  * This function is used to retrieve a free message buffer for the given inbound queue of at least
  215  * messageSize bytes.
  216  * The caller can use the returned buffer to construct the message and then call mpiMsgProduce()
  217  * to deliver the message to the device message unit or mpiMsgInvalidate() if the message buffer
  218  * is not going to be used
  219  *
  220  * Return:
  221  *         AGSA_RC_SUCCESS if messagePtr contains a valid message buffer pointer
  222  *         AGSA_RC_FAILURE if messageSize larger than the elementSize of queue
  223  *         AGSA_RC_BUSY    if there are not free message buffers (Queue full)
  224  */
  225 /*******************************************************************************/
  226 GLOBAL FORCEINLINE
  227 bit32
  228 mpiMsgFreeGet(
  229   mpiICQueue_t *circularQ,
  230   bit16 messageSize,
  231   void** messagePtr
  232   )
  233 {
  234   bit32 offset;
  235   agsaRoot_t          *agRoot=circularQ->agRoot;
  236   mpiMsgHeader_t *msgHeader;
  237   bit8 bcCount = 1; /* only support single buffer */
  238 
  239   SA_DBG4(("Entering function:mpiMsgFreeGet\n"));
  240   SA_ASSERT(NULL != circularQ, "circularQ cannot be null");
  241   SA_ASSERT(NULL != messagePtr, "messagePtr argument cannot be null");
  242   SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue is 0");
  243 
  244   /* Checks is the requested message size can be allocated in this queue */
  245   if(messageSize > circularQ->elementSize)
  246   {
  247     SA_DBG1(("mpiMsgFreeGet: Message Size (%d) is larger than Q element size (%d)\n",messageSize,circularQ->elementSize));
  248     return AGSA_RC_FAILURE;
  249   }
  250 
  251   /* Stores the new consumer index */
  252   OSSA_READ_LE_32(circularQ->agRoot, &circularQ->consumerIdx, circularQ->ciPointer, 0);
  253   /* if inbound queue is full, return busy */
  254   /* This queue full logic may only works for bc == 1 ( == ) */
  255   /* ( pi + bc ) % size > ci not fully works for bc > 1 */
  256   /* To do - support bc > 1 case and wrap around case */
  257   if (((circularQ->producerIdx + bcCount) % circularQ->numElements) == circularQ->consumerIdx)
  258   {
  259     *messagePtr = NULL;
  260     smTrace(hpDBG_VERY_LOUD,"Za", (((circularQ->producerIdx & 0xFFF) << 16) |  (circularQ->consumerIdx & 0xFFF) ));
  261     /* TP:Za IQ PI CI */
  262     ossaHwRegRead(agRoot, MSGU_HOST_SCRATCH_PAD_0);
  263     SA_DBG1(("mpiMsgFreeGet: %d + %d == %d AGSA_RC_BUSY\n",circularQ->producerIdx,bcCount,circularQ->consumerIdx));
  264 
  265     return AGSA_RC_BUSY;
  266   }
  267 
  268   smTrace(hpDBG_VERY_LOUD,"Zb", (((circularQ->producerIdx & 0xFFF) << 16) |  (circularQ->consumerIdx & 0xFFF) ));
  269   /* TP:Zb IQ PI CI */
  270 
  271 
  272   /* get memory IOMB buffer address */
  273   offset = circularQ->producerIdx * circularQ->elementSize;
  274   /* increment to next bcCount element */
  275   circularQ->producerIdx = (circularQ->producerIdx + bcCount) % circularQ->numElements;
  276 
  277   /* Adds that distance to the base of the region virtual address plus the message header size*/
  278   msgHeader = (mpiMsgHeader_t*) (((bit8 *)(circularQ->memoryRegion.virtPtr)) + offset);
  279 
  280   SA_DBG3(("mpiMsgFreeGet: msgHeader = %p Offset = 0x%x\n", (void *)msgHeader, offset));
  281 
  282   /* Sets the message buffer in "allocated" state */
  283   /* bc always is 1 for inbound queue */
  284   /* temporarily store it in the native endian format, when the rest of the */
  285   /* header is filled, this would be converted to Little Endian */
  286   msgHeader->Header = (1<<24);
  287   *messagePtr = ((bit8*)msgHeader) + sizeof(mpiMsgHeader_t);
  288 
  289   return AGSA_RC_SUCCESS;
  290 }
  291 
  292 #ifdef LOOPBACK_MPI
  293 GLOBAL bit32 mpiMsgFreeGetOQ(mpiOCQueue_t *circularQ, bit16 messageSize, void** messagePtr)
  294 {
  295   bit32 offset;
  296   mpiMsgHeader_t *msgHeader;
  297   bit8 bcCount = 1; /* only support single buffer */
  298 
  299   SA_DBG4(("Entering function:mpiMsgFreeGet\n"));
  300   SA_ASSERT(NULL != circularQ, "circularQ cannot be null");
  301   SA_ASSERT(NULL != messagePtr, "messagePtr argument cannot be null");
  302   SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue is 0");
  303 
  304   /* Checks is the requested message size can be allocated in this queue */
  305   if(messageSize > circularQ->elementSize)
  306   {
  307     SA_DBG1(("mpiMsgFreeGet: Message Size is not fit in\n"));
  308     return AGSA_RC_FAILURE;
  309   }
  310 
  311   /* Stores the new consumer index */
  312   //OSSA_READ_LE_32(circularQ->agRoot, &circularQ->consumerIdx, circularQ->ciPointer, 0);
  313   /* if inbound queue is full, return busy */
  314   /* This queue full logic may only works for bc == 1 ( == ) */
  315   /* ( pi + bc ) % size > ci not fully works for bc > 1 */
  316   /* To do - support bc > 1 case and wrap around case */
  317   if (((circularQ->producerIdx + bcCount) % circularQ->numElements) == circularQ->consumerIdx)
  318   {
  319     *messagePtr = NULL;
  320     return AGSA_RC_BUSY;
  321   }
  322 
  323   /* get memory IOMB buffer address */
  324   offset = circularQ->producerIdx * circularQ->elementSize;
  325   /* increment to next bcCount element */
  326   circularQ->producerIdx = (circularQ->producerIdx + bcCount) % circularQ->numElements;
  327 
  328   /* Adds that distance to the base of the region virtual address plus the message header size*/
  329   msgHeader = (mpiMsgHeader_t*) (((bit8 *)(circularQ->memoryRegion.virtPtr)) + offset);
  330 
  331   SA_DBG3(("mpiMsgFreeGet: msgHeader = %p Offset = 0x%x\n", (void *)msgHeader, offset));
  332 
  333   /* Sets the message buffer in "allocated" state */
  334   /* bc always is 1 for inbound queue */
  335   /* temporarily store it in the native endian format, when the rest of the */
  336   /* header is filled, this would be converted to Little Endian */
  337   msgHeader->Header = (1<<24);
  338   *messagePtr = ((bit8*)msgHeader) + sizeof(mpiMsgHeader_t);
  339 
  340   return AGSA_RC_SUCCESS;
  341 }
  342 #endif
  343 
  344 /*******************************************************************************/
  345 /** \fn mpiMsgProduce(mpiICQueue_t *circularQ, void *messagePtr, mpiMsgCategory_t category, bit16 opCode, bit8 responseQueue)
  346  *  \brief Add a header of IOMB then send to a inbound queue and update the Producer index
  347  *  \param circularQ     Pointer to an inbound queue
  348  *  \param messagePtr    Pointer to the message buffer payload (not including message header))
  349  *  \param category      Message category (ETHERNET, FC, SAS-SATA, SCSI)
  350  *  \param opCode        Message operation code
  351  *  \param responseQueue If the message requires response, this paramater indicates the outbound queue for the response
  352  *
  353  * This function is used to sumit a message buffer, previously obtained from  mpiMsgFreeGet()
  354  * function call, to the given Inbound queue
  355  *
  356  * Return:
  357  *         AGSA_RC_SUCCESS if the message has been posted succesfully
  358  */
  359 /*******************************************************************************/
  360 #ifdef FAST_IO_TEST
  361 GLOBAL bit32 mpiMsgPrepare(
  362                        mpiICQueue_t *circularQ,
  363                        void         *messagePtr,
  364                        mpiMsgCategory_t category,
  365                        bit16        opCode,
  366                        bit8         responseQueue,
  367                        bit8         hiPriority
  368                        )
  369 {
  370   mpiMsgHeader_t *msgHeader;
  371   bit32          bc;
  372   bit32          Header = 0;
  373   bit32          hpriority = 0;
  374 
  375   SA_DBG4(("Entering function:mpiMsgProduce\n"));
  376   SA_ASSERT(NULL != circularQ, "circularQ argument cannot be null");
  377   SA_ASSERT(NULL != messagePtr, "messagePtr argument cannot be null");
  378   SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue"
  379             " is 0");
  380   SA_ASSERT(MPI_MAX_OUTBOUND_QUEUES > responseQueue, "oQueue ID is wrong");
  381 
  382   /* Obtains the address of the entire message buffer, including the header */
  383   msgHeader = (mpiMsgHeader_t*)(((bit8*)messagePtr) - sizeof(mpiMsgHeader_t));
  384   /* Read the BC from header, its stored in native endian format when message
  385      was allocated */
  386   /* intially */
  387   bc = (((msgHeader->Header) >> SHIFT24) & BC_MASK);
  388   SA_DBG6(("mpiMsgProduce: msgHeader bc %d\n", bc));
  389   if (circularQ->priority)
  390     hpriority = 1;
  391 
  392   /* Checks the message is in "allocated" state */
  393   SA_ASSERT(0 != bc, "The message buffer is not in \"allocated\" state "
  394                      "(bc == 0)");
  395 
  396   Header = ((V_BIT << SHIFT31) | (hpriority << SHIFT30)  |
  397             ((bc & BC_MASK) << SHIFT24) |
  398             ((responseQueue & OBID_MASK) << SHIFT16) |
  399             ((category  & CAT_MASK) << SHIFT12 ) | (opCode & OPCODE_MASK));
  400 
  401   /* pre flush the IOMB cache line */
  402   ossaCachePreFlush(circularQ->agRoot,
  403                     (void *)circularQ->memoryRegion.appHandle,
  404                     (void *)msgHeader, circularQ->elementSize * bc);
  405   OSSA_WRITE_LE_32(circularQ->agRoot, msgHeader, OSSA_OFFSET_OF(mpiMsgHeader_t,
  406                    Header), Header);
  407   /* flush the IOMB cache line */
  408   ossaCacheFlush(circularQ->agRoot, (void *)circularQ->memoryRegion.appHandle,
  409                  (void *)msgHeader, circularQ->elementSize * bc);
  410 
  411   MPI_DEBUG_TRACE( circularQ->qNumber,
  412                   ((circularQ->producerIdx << 16 ) | circularQ->consumerIdx),
  413                    MPI_DEBUG_TRACE_IBQ,
  414                   (void *)msgHeader,
  415                   circularQ->elementSize);
  416 
  417   ossaLogIomb(circularQ->agRoot,
  418               circularQ->qNumber,
  419               TRUE,
  420               (void *)msgHeader,
  421               circularQ->elementSize);
  422 
  423   return AGSA_RC_SUCCESS;
  424 } /* mpiMsgPrepare */
  425 
  426 GLOBAL bit32 mpiMsgProduce(
  427                        mpiICQueue_t *circularQ,
  428                        void         *messagePtr,
  429                        mpiMsgCategory_t category,
  430                        bit16        opCode,
  431                        bit8         responseQueue,
  432                        bit8         hiPriority
  433                        )
  434 {
  435   bit32 ret;
  436 
  437   ret = mpiMsgPrepare(circularQ, messagePtr, category, opCode, responseQueue,
  438                       hiPriority);
  439   if (ret == AGSA_RC_SUCCESS)
  440   {
  441     /* update PI of inbound queue */
  442     ossaHwRegWriteExt(circularQ->agRoot,
  443                       circularQ->PIPCIBar,
  444                       circularQ->PIPCIOffset,
  445                       circularQ->producerIdx);
  446   }
  447   return ret;
  448 }
  449 
  450 GLOBAL void mpiIBQMsgSend(mpiICQueue_t *circularQ)
  451 {
  452   ossaHwRegWriteExt(circularQ->agRoot,
  453                     circularQ->PIPCIBar,
  454                     circularQ->PIPCIOffset,
  455                     circularQ->producerIdx);
  456 }
  457 #else  /* FAST_IO_TEST */
  458 
  459 GLOBAL FORCEINLINE
  460 bit32
  461 mpiMsgProduce(
  462   mpiICQueue_t *circularQ,
  463   void *messagePtr,
  464   mpiMsgCategory_t category,
  465   bit16 opCode,
  466   bit8 responseQueue,
  467   bit8 hiPriority
  468   )
  469 {
  470   mpiMsgHeader_t *msgHeader;
  471   bit32          bc;
  472   bit32          Header = 0;
  473   bit32          hpriority = 0;
  474 
  475 #ifdef SA_FW_TEST_BUNCH_STARTS
  476 #define Need_agRootDefined 1
  477 #endif /* SA_FW_TEST_BUNCH_STARTS */
  478 
  479 #ifdef SA_ENABLE_TRACE_FUNCTIONS
  480   bit32             i;
  481 #define Need_agRootDefined 1
  482 #endif /* SA_ENABLE_TRACE_FUNCTIONS */
  483 
  484 #ifdef MPI_DEBUG_TRACE_ENABLE
  485 #define Need_agRootDefined 1
  486 #endif /* MPI_DEBUG_TRACE_ENABLE */
  487 
  488 #ifdef Need_agRootDefined
  489   agsaRoot_t   *agRoot=circularQ->agRoot;
  490 #ifdef SA_FW_TEST_BUNCH_STARTS
  491    agsaLLRoot_t *saRoot = agNULL;
  492   saRoot = agRoot->sdkData;
  493 #endif /* SA_FW_TEST_BUNCH_STARTS */
  494 
  495 #undef Need_agRootDefined
  496 #endif /* Need_agRootDefined */
  497 
  498   SA_DBG4(("Entering function:mpiMsgProduce\n"));
  499   SA_ASSERT(NULL != circularQ, "circularQ argument cannot be null");
  500   SA_ASSERT(NULL != messagePtr, "messagePtr argument cannot be null");
  501   SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue is 0");
  502   SA_ASSERT(MPI_MAX_OUTBOUND_QUEUES > responseQueue, "oQueue ID is wrong");
  503 
  504   /* REB Start extra trace */
  505   smTraceFuncEnter(hpDBG_VERY_LOUD,"22");
  506   /* REB End extra trace */
  507 
  508   /* Obtains the address of the entire message buffer, including the header */
  509   msgHeader = (mpiMsgHeader_t*)(((bit8*)messagePtr) - sizeof(mpiMsgHeader_t));
  510   /* Read the BC from header, its stored in native endian format when message was allocated */
  511   /* intially */
  512   bc = (((msgHeader->Header) >> SHIFT24) & BC_MASK);
  513   SA_DBG6(("mpiMsgProduce: msgHeader bc %d\n", bc));
  514   if (circularQ->priority)
  515   {
  516     hpriority = 1;
  517   }
  518 
  519   /* Checks the message is in "allocated" state */
  520   SA_ASSERT(0 != bc, "The message buffer is not in \"allocated\" state (bc == 0)");
  521 
  522   Header = ((V_BIT << SHIFT31) |
  523             (hpriority << SHIFT30)  |
  524             ((bc & BC_MASK) << SHIFT24) |
  525             ((responseQueue & OBID_MASK) << SHIFT16) |
  526             ((category  & CAT_MASK) << SHIFT12 ) |
  527             (opCode & OPCODE_MASK));
  528 
  529   /* pre flush the cache line */
  530   ossaCachePreFlush(circularQ->agRoot, (void *)circularQ->memoryRegion.appHandle, (void *)msgHeader, circularQ->elementSize * bc);
  531   OSSA_WRITE_LE_32(circularQ->agRoot, msgHeader, OSSA_OFFSET_OF(mpiMsgHeader_t, Header), Header);
  532   /* flush the cache line for IOMB */
  533   ossaCacheFlush(circularQ->agRoot, (void *)circularQ->memoryRegion.appHandle, (void *)msgHeader, circularQ->elementSize * bc);
  534 
  535   MPI_DEBUG_TRACE( circularQ->qNumber,
  536                   ((circularQ->producerIdx << 16 ) | circularQ->consumerIdx),
  537                   MPI_DEBUG_TRACE_IBQ,
  538                   (void *)msgHeader,
  539                   circularQ->elementSize);
  540 
  541   ossaLogIomb(circularQ->agRoot,
  542               circularQ->qNumber,
  543               TRUE,
  544               (void *)msgHeader,
  545               circularQ->elementSize);
  546 
  547 #if defined(SALLSDK_DEBUG)
  548   MPI_IBQ_IOMB_LOG(circularQ->qNumber, (void *)msgHeader, circularQ->elementSize);
  549 #endif  /* SALLSDK_DEBUG */
  550   /* REB Start extra trace */
  551 #ifdef SA_ENABLE_TRACE_FUNCTIONS
  552   smTrace(hpDBG_IOMB,"M1",circularQ->qNumber);
  553  /* TP:M1 circularQ->qNumber */
  554   for (i=0; i<((bit32)bc*(circularQ->elementSize/4)); i++)
  555   {
  556       /* The -sizeof(mpiMsgHeader_t) is to account for mpiMsgProduce adding the header to the pMessage pointer */
  557       smTrace(hpDBG_IOMB,"MD",*( ((bit32 *)((bit8 *)messagePtr - sizeof(mpiMsgHeader_t))) + i));
  558       /* TP:MD Inbound IOMB Dword */
  559   }
  560 #endif /* SA_ENABLE_TRACE_FUNCTIONS */
  561 
  562   /* update PI of inbound queue */
  563 
  564 #ifdef SA_FW_TEST_BUNCH_STARTS
  565   if(saRoot->BunchStarts_Enable)
  566   {
  567       if (circularQ->BunchStarts_QPending == 0)
  568       {
  569           // store tick value for 1st deferred IO only 
  570           circularQ->BunchStarts_QPendingTick = saRoot->timeTick;
  571       }
  572       // update queue's pending count
  573       circularQ->BunchStarts_QPending++;
  574 
  575       // update global pending count
  576       saRoot->BunchStarts_Pending++;
  577 
  578       SA_DBG1(("mpiMsgProduce: BunchStarts - Global Pending %d\n", saRoot->BunchStarts_Pending));
  579       SA_DBG1(("mpiMsgProduce: BunchStarts - QPending %d, Q-%d\n", circularQ->BunchStarts_QPending, circularQ->qNumber));
  580       smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "22");
  581 
  582       return AGSA_RC_SUCCESS;
  583   }
  584 
  585   saRoot->BunchStarts_Pending     = 0;
  586   circularQ->BunchStarts_QPending = 0;
  587 #endif /* SA_FW_TEST_BUNCH_STARTS */
  588   ossaHwRegWriteExt(circularQ->agRoot,
  589                     circularQ->PIPCIBar,
  590                     circularQ->PIPCIOffset,
  591                     circularQ->producerIdx);
  592 
  593   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "22");
  594 
  595   return AGSA_RC_SUCCESS;
  596 } /* mpiMsgProduce */
  597 #endif /* FAST_IO_TEST */
  598 
  599 #ifdef SA_FW_TEST_BUNCH_STARTS
  600 
  601 void mpiMsgProduceBunch(  agsaLLRoot_t  *saRoot)
  602 {
  603   mpiICQueue_t *circularQ;
  604   bit32 inq;
  605 
  606   for(inq=0; ((inq < saRoot->QueueConfig.numInboundQueues) && saRoot->BunchStarts_Pending); inq++)
  607   {
  608     circularQ= &saRoot->inboundQueue[inq];
  609     /* If any pending IOs present then either process if BunchStarts_Threshold
  610      * IO limit reached or if the timer has popped
  611      */
  612     if (circularQ->BunchStarts_QPending &&
  613         ((circularQ->BunchStarts_QPending >= saRoot->BunchStarts_Threshold) || 
  614          ((saRoot->timeTick - circularQ->BunchStarts_QPendingTick) >= saRoot->BunchStarts_TimeoutTicks))
  615        )
  616     {
  617       if(circularQ->qNumber != inq)
  618       {
  619         SA_DBG1(("mpiMsgProduceBunch:circularQ->qNumber(%d) != inq(%d)\n",circularQ->qNumber, inq));
  620       }
  621 
  622       SA_DBG1(("mpiMsgProduceBunch: IQ=%d, PI=%d\n", inq, circularQ->producerIdx));
  623       SA_DBG1(("mpiMsgProduceBunch: Qpending=%d, TotPending=%d\n", circularQ->BunchStarts_QPending, saRoot->BunchStarts_Pending));
  624 
  625       ossaHwRegWriteExt(circularQ->agRoot,
  626                      circularQ->PIPCIBar,
  627                      circularQ->PIPCIOffset,
  628                      circularQ->producerIdx);
  629 
  630       // update global pending count
  631       saRoot->BunchStarts_Pending -= circularQ->BunchStarts_QPending;
  632 
  633       // clear current queue's pending count after processing
  634       circularQ->BunchStarts_QPending = 0;
  635       circularQ->BunchStarts_QPendingTick = saRoot->timeTick;
  636     }
  637   }
  638 }
  639 #endif /* SA_FW_TEST_BUNCH_STARTS */
  640 
  641 /*******************************************************************************/
  642 /** \fn mpiMsgConsume(mpiOCQueue_t *circularQ, void *messagePtr1,
  643  *                mpiMsgCategory_t * pCategory, bit16 * pOpCode, bit8 * pBC)
  644  *  \brief Get a received message
  645  *  \param circularQ   Pointer to a outbound queue
  646  *  \param messagePtr1 Pointer to the returned message buffer or NULL if no valid message
  647  *  \param pCategory   Pointer to Message category (ETHERNET, FC, SAS-SATA, SCSI)
  648  *  \param pOpCode     Pointer to Message operation code
  649  *  \param pBC         Pointer to buffer count
  650  *
  651  * Consume a receive message in the specified outbound queue
  652  *
  653  * Return:
  654  *         AGSA_RC_SUCCESS if the message has been retrieved succesfully
  655  *         AGSA_RC_BUSY    if the circular is empty
  656  */
  657 /*******************************************************************************/
  658 GLOBAL FORCEINLINE
  659 bit32
  660 mpiMsgConsume(
  661   mpiOCQueue_t       *circularQ,
  662   void             ** messagePtr1,
  663   mpiMsgCategory_t   *pCategory,
  664   bit16              *pOpCode,
  665   bit8               *pBC
  666   )
  667 {
  668   mpiMsgHeader_t *msgHeader;
  669   bit32          msgHeader_tmp;
  670 
  671   SA_ASSERT(NULL != circularQ, "circularQ argument cannot be null");
  672   SA_ASSERT(NULL != messagePtr1, "messagePtr1 argument cannot be null");
  673   SA_ASSERT(NULL != pCategory, "pCategory argument cannot be null");
  674   SA_ASSERT(NULL != pOpCode, "pOpCode argument cannot be null");
  675   SA_ASSERT(NULL != pBC, "pBC argument cannot be null");
  676   SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue is 0");
  677 
  678   do
  679   {
  680     /* If there are not-yet-delivered messages ... */
  681     if(circularQ->producerIdx != circularQ->consumerIdx)
  682     {
  683       /* Get the pointer to the circular queue buffer element */
  684       msgHeader = (mpiMsgHeader_t*) ((bit8 *)(circularQ->memoryRegion.virtPtr) + circularQ->consumerIdx * circularQ->elementSize);
  685 
  686 #ifdef LOOPBACK_MPI
  687       if (!loopback)
  688 #endif
  689       /* invalidate the cache line of IOMB */
  690       ossaCacheInvalidate(circularQ->agRoot, (void *)circularQ->memoryRegion.appHandle, (void *)msgHeader, circularQ->elementSize);
  691 
  692 
  693       /* read header */
  694       OSSA_READ_LE_32(circularQ->agRoot, &msgHeader_tmp, msgHeader, 0);
  695 
  696       SA_DBG4(("mpiMsgConsume: process an IOMB, header=0x%x\n", msgHeader_tmp));
  697 
  698       SA_ASSERT(0 != (msgHeader_tmp & HEADER_BC_MASK), "The bc field in the header is 0");
  699 #ifdef TEST
  700       /* for debugging */
  701       if (0 == (msgHeader_tmp & HEADER_BC_MASK))
  702       {
  703         SA_DBG1(("mpiMsgConsume: CI=%d PI=%d msgHeader=%p\n", circularQ->consumerIdx, circularQ->producerIdx, (void *)msgHeader));
  704         circularQ->consumerIdx = (circularQ->consumerIdx + 1) % circularQ->numElements;
  705         /* update the CI of outbound queue - skip this blank IOMB, for test only */
  706         ossaHwRegWriteExt(circularQ->agRoot,
  707                           circularQ->CIPCIBar,
  708                           circularQ->CIPCIOffset,
  709                           circularQ->consumerIdx);
  710         return AGSA_RC_FAILURE;
  711       }
  712 #endif
  713       /* get message pointer of valid entry */
  714       if (0 != (msgHeader_tmp & HEADER_V_MASK))
  715       {
  716         SA_ASSERT(circularQ->consumerIdx <= circularQ->numElements, "Multi-buffer messages cannot wrap around");
  717 
  718         if (OPC_OUB_SKIP_ENTRY != (msgHeader_tmp & OPCODE_MASK))
  719         {
  720           /* ... return the message payload */
  721           *messagePtr1 = ((bit8*)msgHeader) + sizeof(mpiMsgHeader_t);
  722           *pCategory   = (mpiMsgCategory_t)(msgHeader_tmp >> SHIFT12) & CAT_MASK;
  723           *pOpCode     = (bit16)(msgHeader_tmp & OPCODE_MASK);
  724           *pBC         = (bit8)((msgHeader_tmp >> SHIFT24) & BC_MASK);
  725 
  726           /* invalidate the cache line for IOMB */
  727 #ifdef LOOPBACK_MPI
  728           if (!loopback)
  729 #endif
  730             ossaCacheInvalidate(circularQ->agRoot, (void *)circularQ->memoryRegion.appHandle, (void *)msgHeader, (*pBC - 1) * circularQ->elementSize);
  731 
  732 #if defined(SALLSDK_DEBUG)
  733           SA_DBG3(("mpiMsgConsume: CI=%d PI=%d msgHeader=%p\n", circularQ->consumerIdx, circularQ->producerIdx, (void *)msgHeader));
  734           MPI_OBQ_IOMB_LOG(circularQ->qNumber, (void *)msgHeader, circularQ->elementSize);
  735 #endif
  736           return AGSA_RC_SUCCESS;
  737         }
  738         else
  739         {
  740           SA_DBG3(("mpiMsgConsume: SKIP_ENTRIES_IOMB BC=%d\n", (msgHeader_tmp >> SHIFT24) & BC_MASK));
  741           /* Updated comsumerIdx and skip it */
  742           circularQ->consumerIdx = (circularQ->consumerIdx + ((msgHeader_tmp >> SHIFT24) & BC_MASK)) % circularQ->numElements;
  743           /* clean header to 0 */
  744           msgHeader_tmp = 0;
  745           /*ossaSingleThreadedEnter(agRoot, LL_IOREQ_OBQ_LOCK);*/
  746 
  747           OSSA_WRITE_LE_32(circularQ->agRoot, msgHeader, OSSA_OFFSET_OF(mpiMsgHeader_t, Header), msgHeader_tmp);
  748 
  749           /* update the CI of outbound queue */
  750           ossaHwRegWriteExt(circularQ->agRoot,
  751                             circularQ->CIPCIBar,
  752                             circularQ->CIPCIOffset,
  753                             circularQ->consumerIdx);
  754           /* Update the producer index */
  755           OSSA_READ_LE_32(circularQ->agRoot, &circularQ->producerIdx, circularQ->piPointer, 0);
  756           /*ossaSingleThreadedLeave(agRoot, LL_IOREQ_OBQ_LOCK); */
  757         }
  758       }
  759       else
  760       {
  761         /* V bit is not set */
  762 #if defined(SALLSDK_DEBUG)
  763         agsaRoot_t *agRoot=circularQ->agRoot;
  764         SA_DBG1(("mpiMsgConsume: V bit not set, PI=%d CI=%d msgHeader=%p\n",  circularQ->producerIdx, circularQ->consumerIdx,(void *)msgHeader));
  765         SA_DBG1(("mpiMsgConsume: V bit not set, 0x%08X Q=%d  \n", msgHeader_tmp, circularQ->qNumber));
  766 
  767         MPI_DEBUG_TRACE(MPI_DEBUG_TRACE_QNUM_ERROR + circularQ->qNumber,
  768                         ((circularQ->producerIdx << 16 ) | circularQ->consumerIdx),
  769                           MPI_DEBUG_TRACE_OBQ,
  770                          (void *)(((bit8*)msgHeader) - sizeof(mpiMsgHeader_t)),
  771                           circularQ->elementSize);
  772 
  773         circularQ->consumerIdx = circularQ->consumerIdx % circularQ->numElements;
  774         circularQ->consumerIdx ++;
  775         OSSA_WRITE_LE_32(circularQ->agRoot, msgHeader, OSSA_OFFSET_OF(mpiMsgHeader_t, Header), msgHeader_tmp);
  776         ossaHwRegWriteExt(agRoot,
  777                           circularQ->CIPCIBar,
  778                           circularQ->CIPCIOffset,
  779                           circularQ->consumerIdx);
  780         MPI_OBQ_IOMB_LOG(circularQ->qNumber, (void *)msgHeader, circularQ->elementSize);
  781 #endif
  782         SA_DBG1(("mpiMsgConsume: V bit is not set!!!!! HW CI=%d\n", ossaHwRegReadExt(circularQ->agRoot, circularQ->CIPCIBar, circularQ->CIPCIOffset) ));
  783         SA_ASSERT(0, "V bit is not set");
  784         return AGSA_RC_FAILURE;
  785       }
  786     }
  787     else
  788     {
  789       /* Update the producer index from SPC */
  790       OSSA_READ_LE_32(circularQ->agRoot, &circularQ->producerIdx, circularQ->piPointer, 0);
  791     }
  792   } while(circularQ->producerIdx != circularQ->consumerIdx); /* while we don't have any more not-yet-delivered message */
  793 
  794 #ifdef TEST
  795   SA_DBG4(("mpiMsgConsume: Outbound queue is empty.\n"));
  796 #endif
  797 
  798   /* report empty */
  799   return AGSA_RC_BUSY;
  800 }
  801 
  802 /*******************************************************************************/
  803 /** \fn mpiMsgFreeSet(mpiOCQueue_t *circularQ, void *messagePtr)
  804  *  \brief Returns a received message to the outbound queue
  805  *  \param circularQ   Pointer to an outbound queue
  806  *  \param messagePtr1 Pointer to the returned message buffer to free
  807  *  \param messagePtr2 Pointer to the returned message buffer to free if bc > 1
  808  *
  809  * Returns consumed and processed message to the specified outbounf queue
  810  *
  811  * Return:
  812  *         AGSA_RC_SUCCESS if the message has been returned succesfully
  813  */
  814 /*******************************************************************************/
  815 GLOBAL FORCEINLINE
  816 bit32
  817 mpiMsgFreeSet(
  818   mpiOCQueue_t *circularQ,
  819   void *messagePtr1,
  820   bit8 bc
  821   )
  822 {
  823   mpiMsgHeader_t     *msgHeader;
  824 
  825   SA_DBG4(("Entering function:mpiMsgFreeSet\n"));
  826   SA_ASSERT(NULL != circularQ, "circularQ argument cannot be null");
  827   SA_ASSERT(NULL != messagePtr1, "messagePtr1 argument cannot be null");
  828   SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue is 0");
  829 
  830   /* Obtains the address of the entire message buffer, including the header */
  831   msgHeader = (mpiMsgHeader_t*)(((bit8*)messagePtr1) - sizeof(mpiMsgHeader_t));
  832 
  833   if ( ((mpiMsgHeader_t*)((bit8*)circularQ->memoryRegion.virtPtr + circularQ->consumerIdx * circularQ->elementSize)) != msgHeader)
  834   {
  835     /* IOMB of CI points mismatch with Message Header - should never happened */
  836     SA_DBG1(("mpiMsgFreeSet: Wrong CI, Q %d ConsumeIdx = %d msgHeader 0x%08x\n",circularQ->qNumber, circularQ->consumerIdx ,msgHeader->Header));
  837     SA_DBG1(("mpiMsgFreeSet: msgHeader %p != %p\n", msgHeader,((mpiMsgHeader_t*)((bit8*)circularQ->memoryRegion.virtPtr + circularQ->consumerIdx * circularQ->elementSize))));
  838 
  839 #ifdef LOOPBACK_MPI
  840     if (!loopback)
  841 #endif
  842     /* Update the producer index from SPC */
  843     OSSA_READ_LE_32(circularQ->agRoot, &circularQ->producerIdx, circularQ->piPointer, 0);
  844 #if defined(SALLSDK_DEBUG)
  845     SA_DBG3(("mpiMsgFreeSet: ProducerIdx = %d\n", circularQ->producerIdx));
  846 #endif
  847     return AGSA_RC_SUCCESS;
  848   }
  849 
  850   /* ... free the circular queue buffer elements associated with the message ... */
  851   /*... by incrementing the consumer index (with wrap arround) */
  852   circularQ->consumerIdx = (circularQ->consumerIdx + bc) % circularQ->numElements;
  853 
  854   /* Invalidates this circular queue buffer element */
  855 
  856   msgHeader->Header &= ~HEADER_V_MASK; /* Clear Valid bit to indicate IOMB consumed by host */
  857   SA_ASSERT(circularQ->consumerIdx <= circularQ->numElements, "Multi-buffer messages cannot wrap arround");
  858 
  859   /* update the CI of outbound queue */
  860 #ifdef LOOPBACK_MPI
  861   if (!loopback)
  862 #endif
  863   {
  864   ossaHwRegWriteExt(circularQ->agRoot,
  865                     circularQ->CIPCIBar,
  866                     circularQ->CIPCIOffset,
  867                     circularQ->consumerIdx);
  868 
  869   /* Update the producer index from SPC */
  870   OSSA_READ_LE_32(circularQ->agRoot, &circularQ->producerIdx, circularQ->piPointer, 0);
  871   }
  872 #if defined(SALLSDK_DEBUG)
  873   SA_DBG5(("mpiMsgFreeSet: CI=%d PI=%d\n", circularQ->consumerIdx, circularQ->producerIdx));
  874 #endif
  875   return AGSA_RC_SUCCESS;
  876 }
  877 
  878 #ifdef TEST
  879 GLOBAL bit32 mpiRotateQnumber(agsaRoot_t *agRoot)
  880 {
  881   agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
  882   bit32        denom;
  883   bit32        ret = 0;
  884 
  885   /* inbound queue number */
  886   saRoot->IBQnumber++;
  887   denom = saRoot->QueueConfig.numInboundQueues;
  888   if (saRoot->IBQnumber % denom == 0) /* % Qnumber*/
  889   {
  890     saRoot->IBQnumber = 0;
  891   }
  892   SA_DBG3(("mpiRotateQnumber: IBQnumber %d\n", saRoot->IBQnumber));
  893 
  894   /* outbound queue number */
  895   saRoot->OBQnumber++;
  896   denom = saRoot->QueueConfig.numOutboundQueues;
  897   if (saRoot->OBQnumber % denom == 0) /* % Qnumber*/
  898   {
  899     saRoot->OBQnumber = 0;
  900   }
  901   SA_DBG3(("mpiRotateQnumber: OBQnumber %d\n", saRoot->OBQnumber));
  902 
  903   ret = (saRoot->OBQnumber << SHIFT16) | saRoot->IBQnumber;
  904   return ret;
  905 }
  906 #endif
  907 
  908 #ifdef LOOPBACK_MPI
  909 GLOBAL bit32 mpiMsgProduceOQ(
  910                        mpiOCQueue_t *circularQ,
  911                        void         *messagePtr,
  912                        mpiMsgCategory_t category,
  913                        bit16        opCode,
  914                        bit8         responseQueue,
  915                        bit8         hiPriority
  916                        )
  917 {
  918   mpiMsgHeader_t *msgHeader;
  919   bit32          bc;
  920   bit32          Header = 0;
  921   bit32          hpriority = 0;
  922 
  923   SA_DBG4(("Entering function:mpiMsgProduceOQ\n"));
  924   SA_ASSERT(NULL != circularQ, "circularQ argument cannot be null");
  925   SA_ASSERT(NULL != messagePtr, "messagePtr argument cannot be null");
  926   SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue"
  927             " is 0");
  928   SA_ASSERT(MPI_MAX_OUTBOUND_QUEUES > responseQueue, "oQueue ID is wrong");
  929 
  930   /* REB Start extra trace */
  931   smTraceFuncEnter(hpDBG_VERY_LOUD, "2I");
  932   /* REB End extra trace */
  933 
  934   /* Obtains the address of the entire message buffer, including the header */
  935   msgHeader = (mpiMsgHeader_t*)(((bit8*)messagePtr) - sizeof(mpiMsgHeader_t));
  936   /* Read the BC from header, its stored in native endian format when message
  937      was allocated */
  938   /* intially */
  939   SA_DBG4(("mpiMsgProduceOQ: msgHeader %p opcode %d pi/ci %d / %d\n", msgHeader, opCode, circularQ->producerIdx, circularQ->consumerIdx));
  940   bc = (((msgHeader->Header) >> SHIFT24) & BC_MASK);
  941   SA_DBG6(("mpiMsgProduceOQ: msgHeader bc %d\n", bc));
  942   if (circularQ->priority)
  943     hpriority = 1;
  944 
  945   /* Checks the message is in "allocated" state */
  946   SA_ASSERT(0 != bc, "The message buffer is not in \"allocated\" state "
  947                      "(bc == 0)");
  948 
  949   Header = ((V_BIT << SHIFT31) | (hpriority << SHIFT30)  |
  950             ((bc & BC_MASK) << SHIFT24) |
  951             ((responseQueue & OBID_MASK) << SHIFT16) |
  952             ((category  & CAT_MASK) << SHIFT12 ) | (opCode & OPCODE_MASK));
  953   /* pre flush the IOMB cache line */
  954   //ossaCachePreFlush(circularQ->agRoot,
  955   //                  (void *)circularQ->memoryRegion.appHandle,
  956   //                  (void *)msgHeader, circularQ->elementSize * bc);
  957   OSSA_WRITE_LE_32(circularQ->agRoot, msgHeader, OSSA_OFFSET_OF(mpiMsgHeader_t,
  958                    Header), Header);
  959 
  960   /* flush the IOMB cache line */
  961   //ossaCacheFlush(circularQ->agRoot, (void *)circularQ->memoryRegion.appHandle,
  962   //               (void *)msgHeader, circularQ->elementSize * bc);
  963 
  964   MPI_DEBUG_TRACE( circularQ->qNumber,
  965                  ((circularQ->producerIdx << 16 ) | circularQ->consumerIdx),
  966                   MPI_DEBUG_TRACE_OBQ,
  967                   (void *)msgHeader,
  968                   circularQ->elementSize);
  969 
  970   ossaLogIomb(circularQ->agRoot,
  971               circularQ->qNumber,
  972               TRUE,
  973               (void *)msgHeader,
  974               circularQ->elementSize);
  975 
  976   smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2I");
  977   return AGSA_RC_SUCCESS;
  978 } /* mpiMsgProduceOQ */
  979 #endif
  980 

Cache object: 4401aff08c2415a4d8605ae68154b9d2


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.