xref: /freebsd/sys/dev/pms/RefTisa/sallsdk/spc/mpi.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
14e1bc9a0SAchim Leubner /*******************************************************************************
24e1bc9a0SAchim Leubner **
34e1bc9a0SAchim Leubner *Copyright (c) 2014 PMC-Sierra, Inc.  All rights reserved.
44e1bc9a0SAchim Leubner *
54e1bc9a0SAchim Leubner *Redistribution and use in source and binary forms, with or without modification, are permitted provided
64e1bc9a0SAchim Leubner *that the following conditions are met:
74e1bc9a0SAchim Leubner *1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
84e1bc9a0SAchim Leubner *following disclaimer.
94e1bc9a0SAchim Leubner *2. Redistributions in binary form must reproduce the above copyright notice,
104e1bc9a0SAchim Leubner *this list of conditions and the following disclaimer in the documentation and/or other materials provided
114e1bc9a0SAchim Leubner *with the distribution.
124e1bc9a0SAchim Leubner *
134e1bc9a0SAchim Leubner *THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
144e1bc9a0SAchim Leubner *WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
154e1bc9a0SAchim Leubner *FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
164e1bc9a0SAchim Leubner *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
174e1bc9a0SAchim Leubner *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
184e1bc9a0SAchim Leubner *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
194e1bc9a0SAchim Leubner *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
204e1bc9a0SAchim Leubner *SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
214e1bc9a0SAchim Leubner 
224e1bc9a0SAchim Leubner ********************************************************************************/
234e1bc9a0SAchim Leubner 
244e1bc9a0SAchim Leubner /*******************************************************************************/
254e1bc9a0SAchim Leubner /*! \file mpi.c
264e1bc9a0SAchim Leubner  *  \brief The file is a MPI Libraries to implement the MPI functions
274e1bc9a0SAchim Leubner  *
284e1bc9a0SAchim Leubner  * The file implements the MPI Library functions.
294e1bc9a0SAchim Leubner  *
304e1bc9a0SAchim Leubner  */
314e1bc9a0SAchim Leubner /*******************************************************************************/
324e1bc9a0SAchim Leubner #include <sys/cdefs.h>
334e1bc9a0SAchim Leubner #include <dev/pms/config.h>
344e1bc9a0SAchim Leubner 
354e1bc9a0SAchim Leubner #include <dev/pms/RefTisa/sallsdk/spc/saglobal.h>
364e1bc9a0SAchim Leubner 
374e1bc9a0SAchim Leubner #ifdef SA_ENABLE_TRACE_FUNCTIONS
384e1bc9a0SAchim Leubner #ifdef siTraceFileID
394e1bc9a0SAchim Leubner #undef siTraceFileID
404e1bc9a0SAchim Leubner #endif
414e1bc9a0SAchim Leubner #define siTraceFileID 'A'
424e1bc9a0SAchim Leubner #endif
434e1bc9a0SAchim Leubner 
444e1bc9a0SAchim Leubner #ifdef LOOPBACK_MPI
454e1bc9a0SAchim Leubner extern int loopback;
464e1bc9a0SAchim Leubner #endif
474e1bc9a0SAchim Leubner /*******************************************************************************/
484e1bc9a0SAchim Leubner 
494e1bc9a0SAchim Leubner /*******************************************************************************/
504e1bc9a0SAchim Leubner /*******************************************************************************/
514e1bc9a0SAchim Leubner /* FUNCTIONS                                                                   */
524e1bc9a0SAchim Leubner /*******************************************************************************/
534e1bc9a0SAchim Leubner /*******************************************************************************/
544e1bc9a0SAchim Leubner /** \fn void mpiRequirementsGet(mpiConfig_t* config, mpiMemReq_t* memoryRequirement)
554e1bc9a0SAchim Leubner  *  \brief Retrieves the MPI layer resource requirements
564e1bc9a0SAchim Leubner  *  \param config            MPI configuration for the Host MPI Message Unit
574e1bc9a0SAchim Leubner  *  \param memoryRequirement Returned data structure as defined by mpiMemReq_t
584e1bc9a0SAchim Leubner  *                           that holds the different chunks of memory that are required
594e1bc9a0SAchim Leubner  *
604e1bc9a0SAchim Leubner  * The mpiRequirementsGet() function is used to determine the resource requirements
614e1bc9a0SAchim Leubner  * for the SPC device interface
624e1bc9a0SAchim Leubner  *
634e1bc9a0SAchim Leubner  * Return: None
644e1bc9a0SAchim Leubner  */
654e1bc9a0SAchim Leubner /*******************************************************************************/
mpiRequirementsGet(mpiConfig_t * config,mpiMemReq_t * memoryRequirement)664e1bc9a0SAchim Leubner void mpiRequirementsGet(mpiConfig_t* config, mpiMemReq_t* memoryRequirement)
674e1bc9a0SAchim Leubner {
684e1bc9a0SAchim Leubner   bit32 qIdx, numq;
694e1bc9a0SAchim Leubner   mpiMemReq_t* memoryMap;
704e1bc9a0SAchim Leubner   SA_DBG2(("Entering function:mpiRequirementsGet\n"));
714e1bc9a0SAchim Leubner   SA_ASSERT((NULL != config), "config argument cannot be null");
724e1bc9a0SAchim Leubner 
734e1bc9a0SAchim Leubner   memoryMap = memoryRequirement;
744e1bc9a0SAchim Leubner   memoryMap->count = 0;
754e1bc9a0SAchim Leubner 
764e1bc9a0SAchim Leubner   /* MPI Memory region 0 for MSGU(AAP1) Event Log for fw */
774e1bc9a0SAchim Leubner   memoryMap->region[memoryMap->count].numElements = 1;
784e1bc9a0SAchim Leubner   memoryMap->region[memoryMap->count].elementSize = sizeof(bit8) * config->mainConfig.eventLogSize;
794e1bc9a0SAchim Leubner   memoryMap->region[memoryMap->count].totalLength = sizeof(bit8) * config->mainConfig.eventLogSize;
804e1bc9a0SAchim Leubner   memoryMap->region[memoryMap->count].alignment = 32;
814e1bc9a0SAchim Leubner   memoryMap->region[memoryMap->count].type = AGSA_DMA_MEM;
824e1bc9a0SAchim Leubner   SA_DBG2(("mpiRequirementsGet:eventLogSize region[%d] 0x%X\n",memoryMap->count,memoryMap->region[memoryMap->count].totalLength ));
834e1bc9a0SAchim Leubner   memoryMap->count++;
844e1bc9a0SAchim Leubner 
854e1bc9a0SAchim Leubner   SA_DBG2(("mpiRequirementsGet:eventLogSize region[%d] 0x%X\n",memoryMap->count,memoryMap->region[memoryMap->count].totalLength ));
864e1bc9a0SAchim Leubner   /* MPI Memory region 1 for IOP Event Log for fw */
874e1bc9a0SAchim Leubner   memoryMap->region[memoryMap->count].numElements = 1;
884e1bc9a0SAchim Leubner   memoryMap->region[memoryMap->count].elementSize = sizeof(bit8) * config->mainConfig.IOPeventLogSize;
894e1bc9a0SAchim Leubner   memoryMap->region[memoryMap->count].totalLength = sizeof(bit8) * config->mainConfig.IOPeventLogSize;
904e1bc9a0SAchim Leubner   memoryMap->region[memoryMap->count].alignment = 32;
914e1bc9a0SAchim Leubner   memoryMap->region[memoryMap->count].type = AGSA_DMA_MEM;
924e1bc9a0SAchim Leubner   SA_DBG2(("mpiRequirementsGet:IOPeventLogSize region[%d] 0x%X\n",memoryMap->count,memoryMap->region[memoryMap->count].totalLength ));
934e1bc9a0SAchim Leubner   memoryMap->count++;
944e1bc9a0SAchim Leubner 
954e1bc9a0SAchim Leubner   /* MPI Memory region 2 for consumer Index of inbound queues */
964e1bc9a0SAchim Leubner   memoryMap->region[memoryMap->count].numElements = 1;
974e1bc9a0SAchim Leubner   memoryMap->region[memoryMap->count].elementSize = sizeof(bit32) * config->numInboundQueues;
984e1bc9a0SAchim Leubner   memoryMap->region[memoryMap->count].totalLength = sizeof(bit32) * config->numInboundQueues;
994e1bc9a0SAchim Leubner   memoryMap->region[memoryMap->count].alignment = 4;
1004e1bc9a0SAchim Leubner   memoryMap->region[memoryMap->count].type = AGSA_DMA_MEM;
1014e1bc9a0SAchim Leubner   SA_DBG2(("mpiRequirementsGet:numInboundQueues region[%d] 0x%X\n",memoryMap->count,memoryMap->region[memoryMap->count].totalLength ));
1024e1bc9a0SAchim Leubner   memoryMap->count++;
1034e1bc9a0SAchim Leubner 
1044e1bc9a0SAchim Leubner   /* MPI Memory region 3 for producer Index of outbound queues */
1054e1bc9a0SAchim Leubner   memoryMap->region[memoryMap->count].numElements = 1;
1064e1bc9a0SAchim Leubner   memoryMap->region[memoryMap->count].elementSize = sizeof(bit32) * config->numOutboundQueues;
1074e1bc9a0SAchim Leubner   memoryMap->region[memoryMap->count].totalLength = sizeof(bit32) * config->numOutboundQueues;
1084e1bc9a0SAchim Leubner   memoryMap->region[memoryMap->count].alignment = 4;
1094e1bc9a0SAchim Leubner   memoryMap->region[memoryMap->count].type = AGSA_DMA_MEM;
1104e1bc9a0SAchim Leubner   SA_DBG2(("mpiRequirementsGet:numOutboundQueues region[%d] 0x%X\n",memoryMap->count,memoryMap->region[memoryMap->count].totalLength ));
1114e1bc9a0SAchim Leubner   memoryMap->count++;
1124e1bc9a0SAchim Leubner 
1134e1bc9a0SAchim Leubner   /* MPI Memory regions 4, ... for the inbound queues - depends on configuration */
1144e1bc9a0SAchim Leubner   numq = 0;
1154e1bc9a0SAchim Leubner   for(qIdx = 0; qIdx < config->numInboundQueues; qIdx++)
1164e1bc9a0SAchim Leubner   {
1174e1bc9a0SAchim Leubner     if(0 != config->inboundQueues[qIdx].numElements)
1184e1bc9a0SAchim Leubner     {
1194e1bc9a0SAchim Leubner         bit32 memSize = config->inboundQueues[qIdx].numElements * config->inboundQueues[qIdx].elementSize;
1204e1bc9a0SAchim Leubner         bit32 remainder = memSize & 127;
1214e1bc9a0SAchim Leubner 
1224e1bc9a0SAchim Leubner         /* Calculate the size of this queue padded to 128 bytes */
1234e1bc9a0SAchim Leubner         if (remainder > 0)
1244e1bc9a0SAchim Leubner         {
1254e1bc9a0SAchim Leubner             memSize += (128 - remainder);
1264e1bc9a0SAchim Leubner         }
1274e1bc9a0SAchim Leubner 
1284e1bc9a0SAchim Leubner         if (numq == 0)
1294e1bc9a0SAchim Leubner         {
1304e1bc9a0SAchim Leubner             memoryMap->region[memoryMap->count].numElements = 1;
1314e1bc9a0SAchim Leubner             memoryMap->region[memoryMap->count].elementSize = memSize;
1324e1bc9a0SAchim Leubner             memoryMap->region[memoryMap->count].totalLength = memSize;
1334e1bc9a0SAchim Leubner             memoryMap->region[memoryMap->count].alignment = 128;
1344e1bc9a0SAchim Leubner             memoryMap->region[memoryMap->count].type = AGSA_CACHED_DMA_MEM;
1354e1bc9a0SAchim Leubner         }
1364e1bc9a0SAchim Leubner         else
1374e1bc9a0SAchim Leubner         {
1384e1bc9a0SAchim Leubner             memoryMap->region[memoryMap->count].elementSize += memSize;
1394e1bc9a0SAchim Leubner             memoryMap->region[memoryMap->count].totalLength += memSize;
1404e1bc9a0SAchim Leubner         }
1414e1bc9a0SAchim Leubner 
1424e1bc9a0SAchim Leubner         numq++;
1434e1bc9a0SAchim Leubner 
1444e1bc9a0SAchim Leubner         if ((0 == ((qIdx + 1) % MAX_QUEUE_EACH_MEM)) ||
1454e1bc9a0SAchim Leubner             (qIdx == (bit32)(config->numInboundQueues - 1)))
1464e1bc9a0SAchim Leubner         {
1474e1bc9a0SAchim Leubner             SA_DBG2(("mpiRequirementsGet: (inboundQueues) memoryMap->region[%d].elementSize = %d\n",
1484e1bc9a0SAchim Leubner                      memoryMap->count, memoryMap->region[memoryMap->count].elementSize));
1494e1bc9a0SAchim Leubner             SA_DBG2(("mpiRequirementsGet: (inboundQueues) memoryMap->region[%d].numElements = %d\n",
1504e1bc9a0SAchim Leubner                      memoryMap->count, memoryMap->region[memoryMap->count].numElements));
1514e1bc9a0SAchim Leubner 
1524e1bc9a0SAchim Leubner             memoryMap->count++;
1534e1bc9a0SAchim Leubner             numq = 0;
1544e1bc9a0SAchim Leubner         }
1554e1bc9a0SAchim Leubner     }
1564e1bc9a0SAchim Leubner   }
1574e1bc9a0SAchim Leubner 
1584e1bc9a0SAchim Leubner   /* MPI Memory regions for the outbound queues - depends on configuration */
1594e1bc9a0SAchim Leubner   numq = 0;
1604e1bc9a0SAchim Leubner   for(qIdx = 0; qIdx < config->numOutboundQueues; qIdx++)
1614e1bc9a0SAchim Leubner   {
1624e1bc9a0SAchim Leubner     if(0 != config->outboundQueues[qIdx].numElements)
1634e1bc9a0SAchim Leubner     {
1644e1bc9a0SAchim Leubner         bit32 memSize = config->outboundQueues[qIdx].numElements * config->outboundQueues[qIdx].elementSize;
1654e1bc9a0SAchim Leubner         bit32 remainder = memSize & 127;
1664e1bc9a0SAchim Leubner 
1674e1bc9a0SAchim Leubner         /* Calculate the size of this queue padded to 128 bytes */
1684e1bc9a0SAchim Leubner         if (remainder > 0)
1694e1bc9a0SAchim Leubner         {
1704e1bc9a0SAchim Leubner             memSize += (128 - remainder);
1714e1bc9a0SAchim Leubner         }
1724e1bc9a0SAchim Leubner 
1734e1bc9a0SAchim Leubner         if (numq == 0)
1744e1bc9a0SAchim Leubner         {
1754e1bc9a0SAchim Leubner             memoryMap->region[memoryMap->count].numElements = 1;
1764e1bc9a0SAchim Leubner             memoryMap->region[memoryMap->count].elementSize = memSize;
1774e1bc9a0SAchim Leubner             memoryMap->region[memoryMap->count].totalLength = memSize;
1784e1bc9a0SAchim Leubner             memoryMap->region[memoryMap->count].alignment = 128;
1794e1bc9a0SAchim Leubner             memoryMap->region[memoryMap->count].type = AGSA_CACHED_DMA_MEM;
1804e1bc9a0SAchim Leubner         }
1814e1bc9a0SAchim Leubner         else
1824e1bc9a0SAchim Leubner         {
1834e1bc9a0SAchim Leubner             memoryMap->region[memoryMap->count].elementSize += memSize;
1844e1bc9a0SAchim Leubner             memoryMap->region[memoryMap->count].totalLength += memSize;
1854e1bc9a0SAchim Leubner         }
1864e1bc9a0SAchim Leubner 
1874e1bc9a0SAchim Leubner         numq++;
1884e1bc9a0SAchim Leubner 
1894e1bc9a0SAchim Leubner         if ((0 == ((qIdx + 1) % MAX_QUEUE_EACH_MEM)) ||
1904e1bc9a0SAchim Leubner             (qIdx ==  (bit32)(config->numOutboundQueues - 1)))
1914e1bc9a0SAchim Leubner         {
1924e1bc9a0SAchim Leubner             SA_DBG2(("mpiRequirementsGet: (outboundQueues) memoryMap->region[%d].elementSize = %d\n",
1934e1bc9a0SAchim Leubner                      memoryMap->count, memoryMap->region[memoryMap->count].elementSize));
1944e1bc9a0SAchim Leubner             SA_DBG2(("mpiRequirementsGet: (outboundQueues) memoryMap->region[%d].numElements = %d\n",
1954e1bc9a0SAchim Leubner                      memoryMap->count, memoryMap->region[memoryMap->count].numElements));
1964e1bc9a0SAchim Leubner 
1974e1bc9a0SAchim Leubner 
1984e1bc9a0SAchim Leubner             memoryMap->count++;
1994e1bc9a0SAchim Leubner             numq = 0;
2004e1bc9a0SAchim Leubner         }
2014e1bc9a0SAchim Leubner     }
2024e1bc9a0SAchim Leubner   }
2034e1bc9a0SAchim Leubner 
2044e1bc9a0SAchim Leubner }
2054e1bc9a0SAchim Leubner 
2064e1bc9a0SAchim Leubner /*******************************************************************************/
2074e1bc9a0SAchim Leubner /** \fn mpiMsgFreeGet(mpiICQueue_t *circularQ, bit16 messageSize, void** messagePtr)
2084e1bc9a0SAchim Leubner  *  \brief Retrieves a free message buffer from an inbound queue
2094e1bc9a0SAchim Leubner  *  \param circularQ    Pointer to an inbound circular queue
2104e1bc9a0SAchim Leubner  *  \param messageSize  Requested message size in bytes - only support 64 bytes/element
2114e1bc9a0SAchim Leubner  *  \param messagePtr   Pointer to the free message buffer payload (not including message header) or NULL if no free message buffers are available
2124e1bc9a0SAchim Leubner  *
2134e1bc9a0SAchim Leubner  * This function is used to retrieve a free message buffer for the given inbound queue of at least
2144e1bc9a0SAchim Leubner  * messageSize bytes.
2154e1bc9a0SAchim Leubner  * The caller can use the returned buffer to construct the message and then call mpiMsgProduce()
2164e1bc9a0SAchim Leubner  * to deliver the message to the device message unit or mpiMsgInvalidate() if the message buffer
2174e1bc9a0SAchim Leubner  * is not going to be used
2184e1bc9a0SAchim Leubner  *
2194e1bc9a0SAchim Leubner  * Return:
2204e1bc9a0SAchim Leubner  *         AGSA_RC_SUCCESS if messagePtr contains a valid message buffer pointer
2214e1bc9a0SAchim Leubner  *         AGSA_RC_FAILURE if messageSize larger than the elementSize of queue
2224e1bc9a0SAchim Leubner  *         AGSA_RC_BUSY    if there are not free message buffers (Queue full)
2234e1bc9a0SAchim Leubner  */
2244e1bc9a0SAchim Leubner /*******************************************************************************/
2254e1bc9a0SAchim Leubner GLOBAL FORCEINLINE
2264e1bc9a0SAchim Leubner bit32
mpiMsgFreeGet(mpiICQueue_t * circularQ,bit16 messageSize,void ** messagePtr)2274e1bc9a0SAchim Leubner mpiMsgFreeGet(
2284e1bc9a0SAchim Leubner   mpiICQueue_t *circularQ,
2294e1bc9a0SAchim Leubner   bit16 messageSize,
2304e1bc9a0SAchim Leubner   void** messagePtr
2314e1bc9a0SAchim Leubner   )
2324e1bc9a0SAchim Leubner {
2334e1bc9a0SAchim Leubner   bit32 offset;
2344e1bc9a0SAchim Leubner   agsaRoot_t          *agRoot=circularQ->agRoot;
2354e1bc9a0SAchim Leubner   mpiMsgHeader_t *msgHeader;
2364e1bc9a0SAchim Leubner   bit8 bcCount = 1; /* only support single buffer */
2374e1bc9a0SAchim Leubner 
2384e1bc9a0SAchim Leubner   SA_DBG4(("Entering function:mpiMsgFreeGet\n"));
2394e1bc9a0SAchim Leubner   SA_ASSERT(NULL != circularQ, "circularQ cannot be null");
2404e1bc9a0SAchim Leubner   SA_ASSERT(NULL != messagePtr, "messagePtr argument cannot be null");
2414e1bc9a0SAchim Leubner   SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue is 0");
2424e1bc9a0SAchim Leubner 
2434e1bc9a0SAchim Leubner   /* Checks is the requested message size can be allocated in this queue */
2444e1bc9a0SAchim Leubner   if(messageSize > circularQ->elementSize)
2454e1bc9a0SAchim Leubner   {
2464e1bc9a0SAchim Leubner     SA_DBG1(("mpiMsgFreeGet: Message Size (%d) is larger than Q element size (%d)\n",messageSize,circularQ->elementSize));
2474e1bc9a0SAchim Leubner     return AGSA_RC_FAILURE;
2484e1bc9a0SAchim Leubner   }
2494e1bc9a0SAchim Leubner 
2504e1bc9a0SAchim Leubner   /* Stores the new consumer index */
2514e1bc9a0SAchim Leubner   OSSA_READ_LE_32(circularQ->agRoot, &circularQ->consumerIdx, circularQ->ciPointer, 0);
2524e1bc9a0SAchim Leubner   /* if inbound queue is full, return busy */
2534e1bc9a0SAchim Leubner   /* This queue full logic may only works for bc == 1 ( == ) */
2544e1bc9a0SAchim Leubner   /* ( pi + bc ) % size > ci not fully works for bc > 1 */
2554e1bc9a0SAchim Leubner   /* To do - support bc > 1 case and wrap around case */
2564e1bc9a0SAchim Leubner   if (((circularQ->producerIdx + bcCount) % circularQ->numElements) == circularQ->consumerIdx)
2574e1bc9a0SAchim Leubner   {
2584e1bc9a0SAchim Leubner     *messagePtr = NULL;
2594e1bc9a0SAchim Leubner     smTrace(hpDBG_VERY_LOUD,"Za", (((circularQ->producerIdx & 0xFFF) << 16) |  (circularQ->consumerIdx & 0xFFF) ));
2604e1bc9a0SAchim Leubner     /* TP:Za IQ PI CI */
2614e1bc9a0SAchim Leubner     ossaHwRegRead(agRoot, MSGU_HOST_SCRATCH_PAD_0);
2624e1bc9a0SAchim Leubner     SA_DBG1(("mpiMsgFreeGet: %d + %d == %d AGSA_RC_BUSY\n",circularQ->producerIdx,bcCount,circularQ->consumerIdx));
2634e1bc9a0SAchim Leubner 
2644e1bc9a0SAchim Leubner     return AGSA_RC_BUSY;
2654e1bc9a0SAchim Leubner   }
2664e1bc9a0SAchim Leubner 
2674e1bc9a0SAchim Leubner   smTrace(hpDBG_VERY_LOUD,"Zb", (((circularQ->producerIdx & 0xFFF) << 16) |  (circularQ->consumerIdx & 0xFFF) ));
2684e1bc9a0SAchim Leubner   /* TP:Zb IQ PI CI */
2694e1bc9a0SAchim Leubner 
2704e1bc9a0SAchim Leubner 
2714e1bc9a0SAchim Leubner   /* get memory IOMB buffer address */
2724e1bc9a0SAchim Leubner   offset = circularQ->producerIdx * circularQ->elementSize;
2734e1bc9a0SAchim Leubner   /* increment to next bcCount element */
2744e1bc9a0SAchim Leubner   circularQ->producerIdx = (circularQ->producerIdx + bcCount) % circularQ->numElements;
2754e1bc9a0SAchim Leubner 
2764e1bc9a0SAchim Leubner   /* Adds that distance to the base of the region virtual address plus the message header size*/
2774e1bc9a0SAchim Leubner   msgHeader = (mpiMsgHeader_t*) (((bit8 *)(circularQ->memoryRegion.virtPtr)) + offset);
2784e1bc9a0SAchim Leubner 
2794e1bc9a0SAchim Leubner   SA_DBG3(("mpiMsgFreeGet: msgHeader = %p Offset = 0x%x\n", (void *)msgHeader, offset));
2804e1bc9a0SAchim Leubner 
2814e1bc9a0SAchim Leubner   /* Sets the message buffer in "allocated" state */
2824e1bc9a0SAchim Leubner   /* bc always is 1 for inbound queue */
2834e1bc9a0SAchim Leubner   /* temporarily store it in the native endian format, when the rest of the */
2844e1bc9a0SAchim Leubner   /* header is filled, this would be converted to Little Endian */
2854e1bc9a0SAchim Leubner   msgHeader->Header = (1<<24);
2864e1bc9a0SAchim Leubner   *messagePtr = ((bit8*)msgHeader) + sizeof(mpiMsgHeader_t);
2874e1bc9a0SAchim Leubner 
2884e1bc9a0SAchim Leubner   return AGSA_RC_SUCCESS;
2894e1bc9a0SAchim Leubner }
2904e1bc9a0SAchim Leubner 
2914e1bc9a0SAchim Leubner #ifdef LOOPBACK_MPI
mpiMsgFreeGetOQ(mpiOCQueue_t * circularQ,bit16 messageSize,void ** messagePtr)2924e1bc9a0SAchim Leubner GLOBAL bit32 mpiMsgFreeGetOQ(mpiOCQueue_t *circularQ, bit16 messageSize, void** messagePtr)
2934e1bc9a0SAchim Leubner {
2944e1bc9a0SAchim Leubner   bit32 offset;
2954e1bc9a0SAchim Leubner   mpiMsgHeader_t *msgHeader;
2964e1bc9a0SAchim Leubner   bit8 bcCount = 1; /* only support single buffer */
2974e1bc9a0SAchim Leubner 
2984e1bc9a0SAchim Leubner   SA_DBG4(("Entering function:mpiMsgFreeGet\n"));
2994e1bc9a0SAchim Leubner   SA_ASSERT(NULL != circularQ, "circularQ cannot be null");
3004e1bc9a0SAchim Leubner   SA_ASSERT(NULL != messagePtr, "messagePtr argument cannot be null");
3014e1bc9a0SAchim Leubner   SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue is 0");
3024e1bc9a0SAchim Leubner 
3034e1bc9a0SAchim Leubner   /* Checks is the requested message size can be allocated in this queue */
3044e1bc9a0SAchim Leubner   if(messageSize > circularQ->elementSize)
3054e1bc9a0SAchim Leubner   {
3064e1bc9a0SAchim Leubner     SA_DBG1(("mpiMsgFreeGet: Message Size is not fit in\n"));
3074e1bc9a0SAchim Leubner     return AGSA_RC_FAILURE;
3084e1bc9a0SAchim Leubner   }
3094e1bc9a0SAchim Leubner 
3104e1bc9a0SAchim Leubner   /* Stores the new consumer index */
3114e1bc9a0SAchim Leubner   //OSSA_READ_LE_32(circularQ->agRoot, &circularQ->consumerIdx, circularQ->ciPointer, 0);
3124e1bc9a0SAchim Leubner   /* if inbound queue is full, return busy */
3134e1bc9a0SAchim Leubner   /* This queue full logic may only works for bc == 1 ( == ) */
3144e1bc9a0SAchim Leubner   /* ( pi + bc ) % size > ci not fully works for bc > 1 */
3154e1bc9a0SAchim Leubner   /* To do - support bc > 1 case and wrap around case */
3164e1bc9a0SAchim Leubner   if (((circularQ->producerIdx + bcCount) % circularQ->numElements) == circularQ->consumerIdx)
3174e1bc9a0SAchim Leubner   {
3184e1bc9a0SAchim Leubner     *messagePtr = NULL;
3194e1bc9a0SAchim Leubner     return AGSA_RC_BUSY;
3204e1bc9a0SAchim Leubner   }
3214e1bc9a0SAchim Leubner 
3224e1bc9a0SAchim Leubner   /* get memory IOMB buffer address */
3234e1bc9a0SAchim Leubner   offset = circularQ->producerIdx * circularQ->elementSize;
3244e1bc9a0SAchim Leubner   /* increment to next bcCount element */
3254e1bc9a0SAchim Leubner   circularQ->producerIdx = (circularQ->producerIdx + bcCount) % circularQ->numElements;
3264e1bc9a0SAchim Leubner 
3274e1bc9a0SAchim Leubner   /* Adds that distance to the base of the region virtual address plus the message header size*/
3284e1bc9a0SAchim Leubner   msgHeader = (mpiMsgHeader_t*) (((bit8 *)(circularQ->memoryRegion.virtPtr)) + offset);
3294e1bc9a0SAchim Leubner 
3304e1bc9a0SAchim Leubner   SA_DBG3(("mpiMsgFreeGet: msgHeader = %p Offset = 0x%x\n", (void *)msgHeader, offset));
3314e1bc9a0SAchim Leubner 
3324e1bc9a0SAchim Leubner   /* Sets the message buffer in "allocated" state */
3334e1bc9a0SAchim Leubner   /* bc always is 1 for inbound queue */
3344e1bc9a0SAchim Leubner   /* temporarily store it in the native endian format, when the rest of the */
3354e1bc9a0SAchim Leubner   /* header is filled, this would be converted to Little Endian */
3364e1bc9a0SAchim Leubner   msgHeader->Header = (1<<24);
3374e1bc9a0SAchim Leubner   *messagePtr = ((bit8*)msgHeader) + sizeof(mpiMsgHeader_t);
3384e1bc9a0SAchim Leubner 
3394e1bc9a0SAchim Leubner   return AGSA_RC_SUCCESS;
3404e1bc9a0SAchim Leubner }
3414e1bc9a0SAchim Leubner #endif
3424e1bc9a0SAchim Leubner 
3434e1bc9a0SAchim Leubner /*******************************************************************************/
3444e1bc9a0SAchim Leubner /** \fn mpiMsgProduce(mpiICQueue_t *circularQ, void *messagePtr, mpiMsgCategory_t category, bit16 opCode, bit8 responseQueue)
3454e1bc9a0SAchim Leubner  *  \brief Add a header of IOMB then send to a inbound queue and update the Producer index
3464e1bc9a0SAchim Leubner  *  \param circularQ     Pointer to an inbound queue
3474e1bc9a0SAchim Leubner  *  \param messagePtr    Pointer to the message buffer payload (not including message header))
3484e1bc9a0SAchim Leubner  *  \param category      Message category (ETHERNET, FC, SAS-SATA, SCSI)
3494e1bc9a0SAchim Leubner  *  \param opCode        Message operation code
3504e1bc9a0SAchim Leubner  *  \param responseQueue If the message requires response, this paramater indicates the outbound queue for the response
3514e1bc9a0SAchim Leubner  *
3524e1bc9a0SAchim Leubner  * This function is used to sumit a message buffer, previously obtained from  mpiMsgFreeGet()
3534e1bc9a0SAchim Leubner  * function call, to the given Inbound queue
3544e1bc9a0SAchim Leubner  *
3554e1bc9a0SAchim Leubner  * Return:
3564e1bc9a0SAchim Leubner  *         AGSA_RC_SUCCESS if the message has been posted succesfully
3574e1bc9a0SAchim Leubner  */
3584e1bc9a0SAchim Leubner /*******************************************************************************/
3594e1bc9a0SAchim Leubner #ifdef FAST_IO_TEST
mpiMsgPrepare(mpiICQueue_t * circularQ,void * messagePtr,mpiMsgCategory_t category,bit16 opCode,bit8 responseQueue,bit8 hiPriority)3604e1bc9a0SAchim Leubner GLOBAL bit32 mpiMsgPrepare(
3614e1bc9a0SAchim Leubner                        mpiICQueue_t *circularQ,
3624e1bc9a0SAchim Leubner                        void         *messagePtr,
3634e1bc9a0SAchim Leubner                        mpiMsgCategory_t category,
3644e1bc9a0SAchim Leubner                        bit16        opCode,
3654e1bc9a0SAchim Leubner                        bit8         responseQueue,
3664e1bc9a0SAchim Leubner                        bit8         hiPriority
3674e1bc9a0SAchim Leubner                        )
3684e1bc9a0SAchim Leubner {
3694e1bc9a0SAchim Leubner   mpiMsgHeader_t *msgHeader;
3704e1bc9a0SAchim Leubner   bit32          bc;
3714e1bc9a0SAchim Leubner   bit32          Header = 0;
3724e1bc9a0SAchim Leubner   bit32          hpriority = 0;
3734e1bc9a0SAchim Leubner 
3744e1bc9a0SAchim Leubner   SA_DBG4(("Entering function:mpiMsgProduce\n"));
3754e1bc9a0SAchim Leubner   SA_ASSERT(NULL != circularQ, "circularQ argument cannot be null");
3764e1bc9a0SAchim Leubner   SA_ASSERT(NULL != messagePtr, "messagePtr argument cannot be null");
3774e1bc9a0SAchim Leubner   SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue"
3784e1bc9a0SAchim Leubner             " is 0");
3794e1bc9a0SAchim Leubner   SA_ASSERT(MPI_MAX_OUTBOUND_QUEUES > responseQueue, "oQueue ID is wrong");
3804e1bc9a0SAchim Leubner 
3814e1bc9a0SAchim Leubner   /* Obtains the address of the entire message buffer, including the header */
3824e1bc9a0SAchim Leubner   msgHeader = (mpiMsgHeader_t*)(((bit8*)messagePtr) - sizeof(mpiMsgHeader_t));
3834e1bc9a0SAchim Leubner   /* Read the BC from header, its stored in native endian format when message
3844e1bc9a0SAchim Leubner      was allocated */
3854e1bc9a0SAchim Leubner   /* intially */
3864e1bc9a0SAchim Leubner   bc = (((msgHeader->Header) >> SHIFT24) & BC_MASK);
3874e1bc9a0SAchim Leubner   SA_DBG6(("mpiMsgProduce: msgHeader bc %d\n", bc));
3884e1bc9a0SAchim Leubner   if (circularQ->priority)
3894e1bc9a0SAchim Leubner     hpriority = 1;
3904e1bc9a0SAchim Leubner 
3914e1bc9a0SAchim Leubner   /* Checks the message is in "allocated" state */
3924e1bc9a0SAchim Leubner   SA_ASSERT(0 != bc, "The message buffer is not in \"allocated\" state "
3934e1bc9a0SAchim Leubner                      "(bc == 0)");
3944e1bc9a0SAchim Leubner 
3954e1bc9a0SAchim Leubner   Header = ((V_BIT << SHIFT31) | (hpriority << SHIFT30)  |
3964e1bc9a0SAchim Leubner             ((bc & BC_MASK) << SHIFT24) |
3974e1bc9a0SAchim Leubner             ((responseQueue & OBID_MASK) << SHIFT16) |
3984e1bc9a0SAchim Leubner             ((category  & CAT_MASK) << SHIFT12 ) | (opCode & OPCODE_MASK));
3994e1bc9a0SAchim Leubner 
4004e1bc9a0SAchim Leubner   /* pre flush the IOMB cache line */
4014e1bc9a0SAchim Leubner   ossaCachePreFlush(circularQ->agRoot,
4024e1bc9a0SAchim Leubner                     (void *)circularQ->memoryRegion.appHandle,
4034e1bc9a0SAchim Leubner                     (void *)msgHeader, circularQ->elementSize * bc);
4044e1bc9a0SAchim Leubner   OSSA_WRITE_LE_32(circularQ->agRoot, msgHeader, OSSA_OFFSET_OF(mpiMsgHeader_t,
4054e1bc9a0SAchim Leubner                    Header), Header);
4064e1bc9a0SAchim Leubner   /* flush the IOMB cache line */
4074e1bc9a0SAchim Leubner   ossaCacheFlush(circularQ->agRoot, (void *)circularQ->memoryRegion.appHandle,
4084e1bc9a0SAchim Leubner                  (void *)msgHeader, circularQ->elementSize * bc);
4094e1bc9a0SAchim Leubner 
4104e1bc9a0SAchim Leubner   MPI_DEBUG_TRACE( circularQ->qNumber,
4114e1bc9a0SAchim Leubner                   ((circularQ->producerIdx << 16 ) | circularQ->consumerIdx),
4124e1bc9a0SAchim Leubner                    MPI_DEBUG_TRACE_IBQ,
4134e1bc9a0SAchim Leubner                   (void *)msgHeader,
4144e1bc9a0SAchim Leubner                   circularQ->elementSize);
4154e1bc9a0SAchim Leubner 
4164e1bc9a0SAchim Leubner   ossaLogIomb(circularQ->agRoot,
4174e1bc9a0SAchim Leubner               circularQ->qNumber,
4184e1bc9a0SAchim Leubner               TRUE,
4194e1bc9a0SAchim Leubner               (void *)msgHeader,
4204e1bc9a0SAchim Leubner               circularQ->elementSize);
4214e1bc9a0SAchim Leubner 
4224e1bc9a0SAchim Leubner   return AGSA_RC_SUCCESS;
4234e1bc9a0SAchim Leubner } /* mpiMsgPrepare */
4244e1bc9a0SAchim Leubner 
mpiMsgProduce(mpiICQueue_t * circularQ,void * messagePtr,mpiMsgCategory_t category,bit16 opCode,bit8 responseQueue,bit8 hiPriority)4254e1bc9a0SAchim Leubner GLOBAL bit32 mpiMsgProduce(
4264e1bc9a0SAchim Leubner                        mpiICQueue_t *circularQ,
4274e1bc9a0SAchim Leubner                        void         *messagePtr,
4284e1bc9a0SAchim Leubner                        mpiMsgCategory_t category,
4294e1bc9a0SAchim Leubner                        bit16        opCode,
4304e1bc9a0SAchim Leubner                        bit8         responseQueue,
4314e1bc9a0SAchim Leubner                        bit8         hiPriority
4324e1bc9a0SAchim Leubner                        )
4334e1bc9a0SAchim Leubner {
4344e1bc9a0SAchim Leubner   bit32 ret;
4354e1bc9a0SAchim Leubner 
4364e1bc9a0SAchim Leubner   ret = mpiMsgPrepare(circularQ, messagePtr, category, opCode, responseQueue,
4374e1bc9a0SAchim Leubner                       hiPriority);
4384e1bc9a0SAchim Leubner   if (ret == AGSA_RC_SUCCESS)
4394e1bc9a0SAchim Leubner   {
4404e1bc9a0SAchim Leubner     /* update PI of inbound queue */
4414e1bc9a0SAchim Leubner     ossaHwRegWriteExt(circularQ->agRoot,
4424e1bc9a0SAchim Leubner                       circularQ->PIPCIBar,
4434e1bc9a0SAchim Leubner                       circularQ->PIPCIOffset,
4444e1bc9a0SAchim Leubner                       circularQ->producerIdx);
4454e1bc9a0SAchim Leubner   }
4464e1bc9a0SAchim Leubner   return ret;
4474e1bc9a0SAchim Leubner }
4484e1bc9a0SAchim Leubner 
mpiIBQMsgSend(mpiICQueue_t * circularQ)4494e1bc9a0SAchim Leubner GLOBAL void mpiIBQMsgSend(mpiICQueue_t *circularQ)
4504e1bc9a0SAchim Leubner {
4514e1bc9a0SAchim Leubner   ossaHwRegWriteExt(circularQ->agRoot,
4524e1bc9a0SAchim Leubner                     circularQ->PIPCIBar,
4534e1bc9a0SAchim Leubner                     circularQ->PIPCIOffset,
4544e1bc9a0SAchim Leubner                     circularQ->producerIdx);
4554e1bc9a0SAchim Leubner }
4564e1bc9a0SAchim Leubner #else  /* FAST_IO_TEST */
4574e1bc9a0SAchim Leubner 
4584e1bc9a0SAchim Leubner GLOBAL FORCEINLINE
4594e1bc9a0SAchim Leubner bit32
mpiMsgProduce(mpiICQueue_t * circularQ,void * messagePtr,mpiMsgCategory_t category,bit16 opCode,bit8 responseQueue,bit8 hiPriority)4604e1bc9a0SAchim Leubner mpiMsgProduce(
4614e1bc9a0SAchim Leubner   mpiICQueue_t *circularQ,
4624e1bc9a0SAchim Leubner   void *messagePtr,
4634e1bc9a0SAchim Leubner   mpiMsgCategory_t category,
4644e1bc9a0SAchim Leubner   bit16 opCode,
4654e1bc9a0SAchim Leubner   bit8 responseQueue,
4664e1bc9a0SAchim Leubner   bit8 hiPriority
4674e1bc9a0SAchim Leubner   )
4684e1bc9a0SAchim Leubner {
4694e1bc9a0SAchim Leubner   mpiMsgHeader_t *msgHeader;
4704e1bc9a0SAchim Leubner   bit32          bc;
4714e1bc9a0SAchim Leubner   bit32          Header = 0;
4724e1bc9a0SAchim Leubner   bit32          hpriority = 0;
4734e1bc9a0SAchim Leubner 
4744e1bc9a0SAchim Leubner #ifdef SA_FW_TEST_BUNCH_STARTS
4754e1bc9a0SAchim Leubner #define Need_agRootDefined 1
4764e1bc9a0SAchim Leubner #endif /* SA_FW_TEST_BUNCH_STARTS */
4774e1bc9a0SAchim Leubner 
4784e1bc9a0SAchim Leubner #ifdef SA_ENABLE_TRACE_FUNCTIONS
4794e1bc9a0SAchim Leubner   bit32             i;
4804e1bc9a0SAchim Leubner #define Need_agRootDefined 1
4814e1bc9a0SAchim Leubner #endif /* SA_ENABLE_TRACE_FUNCTIONS */
4824e1bc9a0SAchim Leubner 
4834e1bc9a0SAchim Leubner #ifdef MPI_DEBUG_TRACE_ENABLE
4844e1bc9a0SAchim Leubner #define Need_agRootDefined 1
4854e1bc9a0SAchim Leubner #endif /* MPI_DEBUG_TRACE_ENABLE */
4864e1bc9a0SAchim Leubner 
4874e1bc9a0SAchim Leubner #ifdef Need_agRootDefined
4884e1bc9a0SAchim Leubner   agsaRoot_t   *agRoot=circularQ->agRoot;
4894e1bc9a0SAchim Leubner #ifdef SA_FW_TEST_BUNCH_STARTS
4904e1bc9a0SAchim Leubner    agsaLLRoot_t *saRoot = agNULL;
4914e1bc9a0SAchim Leubner   saRoot = agRoot->sdkData;
4924e1bc9a0SAchim Leubner #endif /* SA_FW_TEST_BUNCH_STARTS */
4934e1bc9a0SAchim Leubner 
4944e1bc9a0SAchim Leubner #undef Need_agRootDefined
4954e1bc9a0SAchim Leubner #endif /* Need_agRootDefined */
4964e1bc9a0SAchim Leubner 
4974e1bc9a0SAchim Leubner   SA_DBG4(("Entering function:mpiMsgProduce\n"));
4984e1bc9a0SAchim Leubner   SA_ASSERT(NULL != circularQ, "circularQ argument cannot be null");
4994e1bc9a0SAchim Leubner   SA_ASSERT(NULL != messagePtr, "messagePtr argument cannot be null");
5004e1bc9a0SAchim Leubner   SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue is 0");
5014e1bc9a0SAchim Leubner   SA_ASSERT(MPI_MAX_OUTBOUND_QUEUES > responseQueue, "oQueue ID is wrong");
5024e1bc9a0SAchim Leubner 
5034e1bc9a0SAchim Leubner   /* REB Start extra trace */
5044e1bc9a0SAchim Leubner   smTraceFuncEnter(hpDBG_VERY_LOUD,"22");
5054e1bc9a0SAchim Leubner   /* REB End extra trace */
5064e1bc9a0SAchim Leubner 
5074e1bc9a0SAchim Leubner   /* Obtains the address of the entire message buffer, including the header */
5084e1bc9a0SAchim Leubner   msgHeader = (mpiMsgHeader_t*)(((bit8*)messagePtr) - sizeof(mpiMsgHeader_t));
5094e1bc9a0SAchim Leubner   /* Read the BC from header, its stored in native endian format when message was allocated */
5104e1bc9a0SAchim Leubner   /* intially */
5114e1bc9a0SAchim Leubner   bc = (((msgHeader->Header) >> SHIFT24) & BC_MASK);
5124e1bc9a0SAchim Leubner   SA_DBG6(("mpiMsgProduce: msgHeader bc %d\n", bc));
5134e1bc9a0SAchim Leubner   if (circularQ->priority)
5144e1bc9a0SAchim Leubner   {
5154e1bc9a0SAchim Leubner     hpriority = 1;
5164e1bc9a0SAchim Leubner   }
5174e1bc9a0SAchim Leubner 
5184e1bc9a0SAchim Leubner   /* Checks the message is in "allocated" state */
5194e1bc9a0SAchim Leubner   SA_ASSERT(0 != bc, "The message buffer is not in \"allocated\" state (bc == 0)");
5204e1bc9a0SAchim Leubner 
5214e1bc9a0SAchim Leubner   Header = ((V_BIT << SHIFT31) |
5224e1bc9a0SAchim Leubner             (hpriority << SHIFT30)  |
5234e1bc9a0SAchim Leubner             ((bc & BC_MASK) << SHIFT24) |
5244e1bc9a0SAchim Leubner             ((responseQueue & OBID_MASK) << SHIFT16) |
5254e1bc9a0SAchim Leubner             ((category  & CAT_MASK) << SHIFT12 ) |
5264e1bc9a0SAchim Leubner             (opCode & OPCODE_MASK));
5274e1bc9a0SAchim Leubner 
5284e1bc9a0SAchim Leubner   /* pre flush the cache line */
5294e1bc9a0SAchim Leubner   ossaCachePreFlush(circularQ->agRoot, (void *)circularQ->memoryRegion.appHandle, (void *)msgHeader, circularQ->elementSize * bc);
5304e1bc9a0SAchim Leubner   OSSA_WRITE_LE_32(circularQ->agRoot, msgHeader, OSSA_OFFSET_OF(mpiMsgHeader_t, Header), Header);
5314e1bc9a0SAchim Leubner   /* flush the cache line for IOMB */
5324e1bc9a0SAchim Leubner   ossaCacheFlush(circularQ->agRoot, (void *)circularQ->memoryRegion.appHandle, (void *)msgHeader, circularQ->elementSize * bc);
5334e1bc9a0SAchim Leubner 
5344e1bc9a0SAchim Leubner   MPI_DEBUG_TRACE( circularQ->qNumber,
5354e1bc9a0SAchim Leubner                   ((circularQ->producerIdx << 16 ) | circularQ->consumerIdx),
5364e1bc9a0SAchim Leubner                   MPI_DEBUG_TRACE_IBQ,
5374e1bc9a0SAchim Leubner                   (void *)msgHeader,
5384e1bc9a0SAchim Leubner                   circularQ->elementSize);
5394e1bc9a0SAchim Leubner 
5404e1bc9a0SAchim Leubner   ossaLogIomb(circularQ->agRoot,
5414e1bc9a0SAchim Leubner               circularQ->qNumber,
5424e1bc9a0SAchim Leubner               TRUE,
5434e1bc9a0SAchim Leubner               (void *)msgHeader,
5444e1bc9a0SAchim Leubner               circularQ->elementSize);
5454e1bc9a0SAchim Leubner 
5464e1bc9a0SAchim Leubner #if defined(SALLSDK_DEBUG)
5474e1bc9a0SAchim Leubner   MPI_IBQ_IOMB_LOG(circularQ->qNumber, (void *)msgHeader, circularQ->elementSize);
5484e1bc9a0SAchim Leubner #endif  /* SALLSDK_DEBUG */
5494e1bc9a0SAchim Leubner   /* REB Start extra trace */
5504e1bc9a0SAchim Leubner #ifdef SA_ENABLE_TRACE_FUNCTIONS
5514e1bc9a0SAchim Leubner   smTrace(hpDBG_IOMB,"M1",circularQ->qNumber);
5524e1bc9a0SAchim Leubner  /* TP:M1 circularQ->qNumber */
5534e1bc9a0SAchim Leubner   for (i=0; i<((bit32)bc*(circularQ->elementSize/4)); i++)
5544e1bc9a0SAchim Leubner   {
5554e1bc9a0SAchim Leubner       /* The -sizeof(mpiMsgHeader_t) is to account for mpiMsgProduce adding the header to the pMessage pointer */
5564e1bc9a0SAchim Leubner       smTrace(hpDBG_IOMB,"MD",*( ((bit32 *)((bit8 *)messagePtr - sizeof(mpiMsgHeader_t))) + i));
5574e1bc9a0SAchim Leubner       /* TP:MD Inbound IOMB Dword */
5584e1bc9a0SAchim Leubner   }
5594e1bc9a0SAchim Leubner #endif /* SA_ENABLE_TRACE_FUNCTIONS */
5604e1bc9a0SAchim Leubner 
5614e1bc9a0SAchim Leubner   /* update PI of inbound queue */
5624e1bc9a0SAchim Leubner 
5634e1bc9a0SAchim Leubner #ifdef SA_FW_TEST_BUNCH_STARTS
5644e1bc9a0SAchim Leubner   if(saRoot->BunchStarts_Enable)
5654e1bc9a0SAchim Leubner   {
5664e1bc9a0SAchim Leubner       if (circularQ->BunchStarts_QPending == 0)
5674e1bc9a0SAchim Leubner       {
5684e1bc9a0SAchim Leubner           // store tick value for 1st deferred IO only
5694e1bc9a0SAchim Leubner           circularQ->BunchStarts_QPendingTick = saRoot->timeTick;
5704e1bc9a0SAchim Leubner       }
5714e1bc9a0SAchim Leubner       // update queue's pending count
5724e1bc9a0SAchim Leubner       circularQ->BunchStarts_QPending++;
5734e1bc9a0SAchim Leubner 
5744e1bc9a0SAchim Leubner       // update global pending count
5754e1bc9a0SAchim Leubner       saRoot->BunchStarts_Pending++;
5764e1bc9a0SAchim Leubner 
5774e1bc9a0SAchim Leubner       SA_DBG1(("mpiMsgProduce: BunchStarts - Global Pending %d\n", saRoot->BunchStarts_Pending));
5784e1bc9a0SAchim Leubner       SA_DBG1(("mpiMsgProduce: BunchStarts - QPending %d, Q-%d\n", circularQ->BunchStarts_QPending, circularQ->qNumber));
5794e1bc9a0SAchim Leubner       smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "22");
5804e1bc9a0SAchim Leubner 
5814e1bc9a0SAchim Leubner       return AGSA_RC_SUCCESS;
5824e1bc9a0SAchim Leubner   }
5834e1bc9a0SAchim Leubner 
5844e1bc9a0SAchim Leubner   saRoot->BunchStarts_Pending     = 0;
5854e1bc9a0SAchim Leubner   circularQ->BunchStarts_QPending = 0;
5864e1bc9a0SAchim Leubner #endif /* SA_FW_TEST_BUNCH_STARTS */
5874e1bc9a0SAchim Leubner   ossaHwRegWriteExt(circularQ->agRoot,
5884e1bc9a0SAchim Leubner                     circularQ->PIPCIBar,
5894e1bc9a0SAchim Leubner                     circularQ->PIPCIOffset,
5904e1bc9a0SAchim Leubner                     circularQ->producerIdx);
5914e1bc9a0SAchim Leubner 
5924e1bc9a0SAchim Leubner   smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "22");
5934e1bc9a0SAchim Leubner 
5944e1bc9a0SAchim Leubner   return AGSA_RC_SUCCESS;
5954e1bc9a0SAchim Leubner } /* mpiMsgProduce */
5964e1bc9a0SAchim Leubner #endif /* FAST_IO_TEST */
5974e1bc9a0SAchim Leubner 
5984e1bc9a0SAchim Leubner #ifdef SA_FW_TEST_BUNCH_STARTS
5994e1bc9a0SAchim Leubner 
mpiMsgProduceBunch(agsaLLRoot_t * saRoot)6004e1bc9a0SAchim Leubner void mpiMsgProduceBunch(  agsaLLRoot_t  *saRoot)
6014e1bc9a0SAchim Leubner {
6024e1bc9a0SAchim Leubner   mpiICQueue_t *circularQ;
6034e1bc9a0SAchim Leubner   bit32 inq;
6044e1bc9a0SAchim Leubner 
6054e1bc9a0SAchim Leubner   for(inq=0; ((inq < saRoot->QueueConfig.numInboundQueues) && saRoot->BunchStarts_Pending); inq++)
6064e1bc9a0SAchim Leubner   {
6074e1bc9a0SAchim Leubner     circularQ= &saRoot->inboundQueue[inq];
6084e1bc9a0SAchim Leubner     /* If any pending IOs present then either process if BunchStarts_Threshold
6094e1bc9a0SAchim Leubner      * IO limit reached or if the timer has popped
6104e1bc9a0SAchim Leubner      */
6114e1bc9a0SAchim Leubner     if (circularQ->BunchStarts_QPending &&
6124e1bc9a0SAchim Leubner         ((circularQ->BunchStarts_QPending >= saRoot->BunchStarts_Threshold) ||
6134e1bc9a0SAchim Leubner          ((saRoot->timeTick - circularQ->BunchStarts_QPendingTick) >= saRoot->BunchStarts_TimeoutTicks))
6144e1bc9a0SAchim Leubner        )
6154e1bc9a0SAchim Leubner     {
6164e1bc9a0SAchim Leubner       if(circularQ->qNumber != inq)
6174e1bc9a0SAchim Leubner       {
6184e1bc9a0SAchim Leubner         SA_DBG1(("mpiMsgProduceBunch:circularQ->qNumber(%d) != inq(%d)\n",circularQ->qNumber, inq));
6194e1bc9a0SAchim Leubner       }
6204e1bc9a0SAchim Leubner 
6214e1bc9a0SAchim Leubner       SA_DBG1(("mpiMsgProduceBunch: IQ=%d, PI=%d\n", inq, circularQ->producerIdx));
6224e1bc9a0SAchim Leubner       SA_DBG1(("mpiMsgProduceBunch: Qpending=%d, TotPending=%d\n", circularQ->BunchStarts_QPending, saRoot->BunchStarts_Pending));
6234e1bc9a0SAchim Leubner 
6244e1bc9a0SAchim Leubner       ossaHwRegWriteExt(circularQ->agRoot,
6254e1bc9a0SAchim Leubner                      circularQ->PIPCIBar,
6264e1bc9a0SAchim Leubner                      circularQ->PIPCIOffset,
6274e1bc9a0SAchim Leubner                      circularQ->producerIdx);
6284e1bc9a0SAchim Leubner 
6294e1bc9a0SAchim Leubner       // update global pending count
6304e1bc9a0SAchim Leubner       saRoot->BunchStarts_Pending -= circularQ->BunchStarts_QPending;
6314e1bc9a0SAchim Leubner 
6324e1bc9a0SAchim Leubner       // clear current queue's pending count after processing
6334e1bc9a0SAchim Leubner       circularQ->BunchStarts_QPending = 0;
6344e1bc9a0SAchim Leubner       circularQ->BunchStarts_QPendingTick = saRoot->timeTick;
6354e1bc9a0SAchim Leubner     }
6364e1bc9a0SAchim Leubner   }
6374e1bc9a0SAchim Leubner }
6384e1bc9a0SAchim Leubner #endif /* SA_FW_TEST_BUNCH_STARTS */
6394e1bc9a0SAchim Leubner 
6404e1bc9a0SAchim Leubner /*******************************************************************************/
6414e1bc9a0SAchim Leubner /** \fn mpiMsgConsume(mpiOCQueue_t *circularQ, void *messagePtr1,
6424e1bc9a0SAchim Leubner  *                mpiMsgCategory_t * pCategory, bit16 * pOpCode, bit8 * pBC)
6434e1bc9a0SAchim Leubner  *  \brief Get a received message
6444e1bc9a0SAchim Leubner  *  \param circularQ   Pointer to a outbound queue
6454e1bc9a0SAchim Leubner  *  \param messagePtr1 Pointer to the returned message buffer or NULL if no valid message
6464e1bc9a0SAchim Leubner  *  \param pCategory   Pointer to Message category (ETHERNET, FC, SAS-SATA, SCSI)
6474e1bc9a0SAchim Leubner  *  \param pOpCode     Pointer to Message operation code
6484e1bc9a0SAchim Leubner  *  \param pBC         Pointer to buffer count
6494e1bc9a0SAchim Leubner  *
6504e1bc9a0SAchim Leubner  * Consume a receive message in the specified outbound queue
6514e1bc9a0SAchim Leubner  *
6524e1bc9a0SAchim Leubner  * Return:
6534e1bc9a0SAchim Leubner  *         AGSA_RC_SUCCESS if the message has been retrieved succesfully
6544e1bc9a0SAchim Leubner  *         AGSA_RC_BUSY    if the circular is empty
6554e1bc9a0SAchim Leubner  */
6564e1bc9a0SAchim Leubner /*******************************************************************************/
6574e1bc9a0SAchim Leubner GLOBAL FORCEINLINE
6584e1bc9a0SAchim Leubner bit32
mpiMsgConsume(mpiOCQueue_t * circularQ,void ** messagePtr1,mpiMsgCategory_t * pCategory,bit16 * pOpCode,bit8 * pBC)6594e1bc9a0SAchim Leubner mpiMsgConsume(
6604e1bc9a0SAchim Leubner   mpiOCQueue_t       *circularQ,
6614e1bc9a0SAchim Leubner   void             ** messagePtr1,
6624e1bc9a0SAchim Leubner   mpiMsgCategory_t   *pCategory,
6634e1bc9a0SAchim Leubner   bit16              *pOpCode,
6644e1bc9a0SAchim Leubner   bit8               *pBC
6654e1bc9a0SAchim Leubner   )
6664e1bc9a0SAchim Leubner {
6674e1bc9a0SAchim Leubner   mpiMsgHeader_t *msgHeader;
6684e1bc9a0SAchim Leubner   bit32          msgHeader_tmp;
6694e1bc9a0SAchim Leubner 
6704e1bc9a0SAchim Leubner   SA_ASSERT(NULL != circularQ, "circularQ argument cannot be null");
6714e1bc9a0SAchim Leubner   SA_ASSERT(NULL != messagePtr1, "messagePtr1 argument cannot be null");
6724e1bc9a0SAchim Leubner   SA_ASSERT(NULL != pCategory, "pCategory argument cannot be null");
6734e1bc9a0SAchim Leubner   SA_ASSERT(NULL != pOpCode, "pOpCode argument cannot be null");
6744e1bc9a0SAchim Leubner   SA_ASSERT(NULL != pBC, "pBC argument cannot be null");
6754e1bc9a0SAchim Leubner   SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue is 0");
6764e1bc9a0SAchim Leubner 
6774e1bc9a0SAchim Leubner   do
6784e1bc9a0SAchim Leubner   {
6794e1bc9a0SAchim Leubner     /* If there are not-yet-delivered messages ... */
6804e1bc9a0SAchim Leubner     if(circularQ->producerIdx != circularQ->consumerIdx)
6814e1bc9a0SAchim Leubner     {
6824e1bc9a0SAchim Leubner       /* Get the pointer to the circular queue buffer element */
6834e1bc9a0SAchim Leubner       msgHeader = (mpiMsgHeader_t*) ((bit8 *)(circularQ->memoryRegion.virtPtr) + circularQ->consumerIdx * circularQ->elementSize);
6844e1bc9a0SAchim Leubner 
6854e1bc9a0SAchim Leubner #ifdef LOOPBACK_MPI
6864e1bc9a0SAchim Leubner       if (!loopback)
6874e1bc9a0SAchim Leubner #endif
6884e1bc9a0SAchim Leubner       /* invalidate the cache line of IOMB */
6894e1bc9a0SAchim Leubner       ossaCacheInvalidate(circularQ->agRoot, (void *)circularQ->memoryRegion.appHandle, (void *)msgHeader, circularQ->elementSize);
6904e1bc9a0SAchim Leubner 
6914e1bc9a0SAchim Leubner 
6924e1bc9a0SAchim Leubner       /* read header */
6934e1bc9a0SAchim Leubner       OSSA_READ_LE_32(circularQ->agRoot, &msgHeader_tmp, msgHeader, 0);
6944e1bc9a0SAchim Leubner 
6954e1bc9a0SAchim Leubner       SA_DBG4(("mpiMsgConsume: process an IOMB, header=0x%x\n", msgHeader_tmp));
6964e1bc9a0SAchim Leubner 
6974e1bc9a0SAchim Leubner       SA_ASSERT(0 != (msgHeader_tmp & HEADER_BC_MASK), "The bc field in the header is 0");
6984e1bc9a0SAchim Leubner #ifdef TEST
6994e1bc9a0SAchim Leubner       /* for debugging */
7004e1bc9a0SAchim Leubner       if (0 == (msgHeader_tmp & HEADER_BC_MASK))
7014e1bc9a0SAchim Leubner       {
7024e1bc9a0SAchim Leubner         SA_DBG1(("mpiMsgConsume: CI=%d PI=%d msgHeader=%p\n", circularQ->consumerIdx, circularQ->producerIdx, (void *)msgHeader));
7034e1bc9a0SAchim Leubner         circularQ->consumerIdx = (circularQ->consumerIdx + 1) % circularQ->numElements;
7044e1bc9a0SAchim Leubner         /* update the CI of outbound queue - skip this blank IOMB, for test only */
7054e1bc9a0SAchim Leubner         ossaHwRegWriteExt(circularQ->agRoot,
7064e1bc9a0SAchim Leubner                           circularQ->CIPCIBar,
7074e1bc9a0SAchim Leubner                           circularQ->CIPCIOffset,
7084e1bc9a0SAchim Leubner                           circularQ->consumerIdx);
7094e1bc9a0SAchim Leubner         return AGSA_RC_FAILURE;
7104e1bc9a0SAchim Leubner       }
7114e1bc9a0SAchim Leubner #endif
7124e1bc9a0SAchim Leubner       /* get message pointer of valid entry */
7134e1bc9a0SAchim Leubner       if (0 != (msgHeader_tmp & HEADER_V_MASK))
7144e1bc9a0SAchim Leubner       {
7154e1bc9a0SAchim Leubner         SA_ASSERT(circularQ->consumerIdx <= circularQ->numElements, "Multi-buffer messages cannot wrap around");
7164e1bc9a0SAchim Leubner 
7174e1bc9a0SAchim Leubner         if (OPC_OUB_SKIP_ENTRY != (msgHeader_tmp & OPCODE_MASK))
7184e1bc9a0SAchim Leubner         {
7194e1bc9a0SAchim Leubner           /* ... return the message payload */
7204e1bc9a0SAchim Leubner           *messagePtr1 = ((bit8*)msgHeader) + sizeof(mpiMsgHeader_t);
7214e1bc9a0SAchim Leubner           *pCategory   = (mpiMsgCategory_t)(msgHeader_tmp >> SHIFT12) & CAT_MASK;
7224e1bc9a0SAchim Leubner           *pOpCode     = (bit16)(msgHeader_tmp & OPCODE_MASK);
7234e1bc9a0SAchim Leubner           *pBC         = (bit8)((msgHeader_tmp >> SHIFT24) & BC_MASK);
7244e1bc9a0SAchim Leubner 
7254e1bc9a0SAchim Leubner           /* invalidate the cache line for IOMB */
7264e1bc9a0SAchim Leubner #ifdef LOOPBACK_MPI
7274e1bc9a0SAchim Leubner           if (!loopback)
7284e1bc9a0SAchim Leubner #endif
7294e1bc9a0SAchim Leubner             ossaCacheInvalidate(circularQ->agRoot, (void *)circularQ->memoryRegion.appHandle, (void *)msgHeader, (*pBC - 1) * circularQ->elementSize);
7304e1bc9a0SAchim Leubner 
7314e1bc9a0SAchim Leubner #if defined(SALLSDK_DEBUG)
7324e1bc9a0SAchim Leubner           SA_DBG3(("mpiMsgConsume: CI=%d PI=%d msgHeader=%p\n", circularQ->consumerIdx, circularQ->producerIdx, (void *)msgHeader));
7334e1bc9a0SAchim Leubner           MPI_OBQ_IOMB_LOG(circularQ->qNumber, (void *)msgHeader, circularQ->elementSize);
7344e1bc9a0SAchim Leubner #endif
7354e1bc9a0SAchim Leubner           return AGSA_RC_SUCCESS;
7364e1bc9a0SAchim Leubner         }
7374e1bc9a0SAchim Leubner         else
7384e1bc9a0SAchim Leubner         {
7394e1bc9a0SAchim Leubner           SA_DBG3(("mpiMsgConsume: SKIP_ENTRIES_IOMB BC=%d\n", (msgHeader_tmp >> SHIFT24) & BC_MASK));
7404e1bc9a0SAchim Leubner           /* Updated comsumerIdx and skip it */
7414e1bc9a0SAchim Leubner           circularQ->consumerIdx = (circularQ->consumerIdx + ((msgHeader_tmp >> SHIFT24) & BC_MASK)) % circularQ->numElements;
7424e1bc9a0SAchim Leubner           /* clean header to 0 */
7434e1bc9a0SAchim Leubner           msgHeader_tmp = 0;
7444e1bc9a0SAchim Leubner           /*ossaSingleThreadedEnter(agRoot, LL_IOREQ_OBQ_LOCK);*/
7454e1bc9a0SAchim Leubner 
7464e1bc9a0SAchim Leubner           OSSA_WRITE_LE_32(circularQ->agRoot, msgHeader, OSSA_OFFSET_OF(mpiMsgHeader_t, Header), msgHeader_tmp);
7474e1bc9a0SAchim Leubner 
7484e1bc9a0SAchim Leubner           /* update the CI of outbound queue */
7494e1bc9a0SAchim Leubner           ossaHwRegWriteExt(circularQ->agRoot,
7504e1bc9a0SAchim Leubner                             circularQ->CIPCIBar,
7514e1bc9a0SAchim Leubner                             circularQ->CIPCIOffset,
7524e1bc9a0SAchim Leubner                             circularQ->consumerIdx);
7534e1bc9a0SAchim Leubner           /* Update the producer index */
7544e1bc9a0SAchim Leubner           OSSA_READ_LE_32(circularQ->agRoot, &circularQ->producerIdx, circularQ->piPointer, 0);
7554e1bc9a0SAchim Leubner           /*ossaSingleThreadedLeave(agRoot, LL_IOREQ_OBQ_LOCK); */
7564e1bc9a0SAchim Leubner         }
7574e1bc9a0SAchim Leubner       }
7584e1bc9a0SAchim Leubner       else
7594e1bc9a0SAchim Leubner       {
7604e1bc9a0SAchim Leubner         /* V bit is not set */
7614e1bc9a0SAchim Leubner #if defined(SALLSDK_DEBUG)
7624e1bc9a0SAchim Leubner         agsaRoot_t *agRoot=circularQ->agRoot;
7634e1bc9a0SAchim Leubner         SA_DBG1(("mpiMsgConsume: V bit not set, PI=%d CI=%d msgHeader=%p\n",  circularQ->producerIdx, circularQ->consumerIdx,(void *)msgHeader));
7644e1bc9a0SAchim Leubner         SA_DBG1(("mpiMsgConsume: V bit not set, 0x%08X Q=%d  \n", msgHeader_tmp, circularQ->qNumber));
7654e1bc9a0SAchim Leubner 
7664e1bc9a0SAchim Leubner         MPI_DEBUG_TRACE(MPI_DEBUG_TRACE_QNUM_ERROR + circularQ->qNumber,
7674e1bc9a0SAchim Leubner                         ((circularQ->producerIdx << 16 ) | circularQ->consumerIdx),
7684e1bc9a0SAchim Leubner                           MPI_DEBUG_TRACE_OBQ,
7694e1bc9a0SAchim Leubner                          (void *)(((bit8*)msgHeader) - sizeof(mpiMsgHeader_t)),
7704e1bc9a0SAchim Leubner                           circularQ->elementSize);
7714e1bc9a0SAchim Leubner 
7724e1bc9a0SAchim Leubner         circularQ->consumerIdx = circularQ->consumerIdx % circularQ->numElements;
7734e1bc9a0SAchim Leubner         circularQ->consumerIdx ++;
7744e1bc9a0SAchim Leubner         OSSA_WRITE_LE_32(circularQ->agRoot, msgHeader, OSSA_OFFSET_OF(mpiMsgHeader_t, Header), msgHeader_tmp);
7754e1bc9a0SAchim Leubner         ossaHwRegWriteExt(agRoot,
7764e1bc9a0SAchim Leubner                           circularQ->CIPCIBar,
7774e1bc9a0SAchim Leubner                           circularQ->CIPCIOffset,
7784e1bc9a0SAchim Leubner                           circularQ->consumerIdx);
7794e1bc9a0SAchim Leubner         MPI_OBQ_IOMB_LOG(circularQ->qNumber, (void *)msgHeader, circularQ->elementSize);
7804e1bc9a0SAchim Leubner #endif
7814e1bc9a0SAchim Leubner         SA_DBG1(("mpiMsgConsume: V bit is not set!!!!! HW CI=%d\n", ossaHwRegReadExt(circularQ->agRoot, circularQ->CIPCIBar, circularQ->CIPCIOffset) ));
7824e1bc9a0SAchim Leubner         SA_ASSERT(0, "V bit is not set");
7834e1bc9a0SAchim Leubner         return AGSA_RC_FAILURE;
7844e1bc9a0SAchim Leubner       }
7854e1bc9a0SAchim Leubner     }
7864e1bc9a0SAchim Leubner     else
7874e1bc9a0SAchim Leubner     {
7884e1bc9a0SAchim Leubner       /* Update the producer index from SPC */
7894e1bc9a0SAchim Leubner       OSSA_READ_LE_32(circularQ->agRoot, &circularQ->producerIdx, circularQ->piPointer, 0);
7904e1bc9a0SAchim Leubner     }
7914e1bc9a0SAchim Leubner   } while(circularQ->producerIdx != circularQ->consumerIdx); /* while we don't have any more not-yet-delivered message */
7924e1bc9a0SAchim Leubner 
7934e1bc9a0SAchim Leubner #ifdef TEST
7944e1bc9a0SAchim Leubner   SA_DBG4(("mpiMsgConsume: Outbound queue is empty.\n"));
7954e1bc9a0SAchim Leubner #endif
7964e1bc9a0SAchim Leubner 
7974e1bc9a0SAchim Leubner   /* report empty */
7984e1bc9a0SAchim Leubner   return AGSA_RC_BUSY;
7994e1bc9a0SAchim Leubner }
8004e1bc9a0SAchim Leubner 
8014e1bc9a0SAchim Leubner /*******************************************************************************/
8024e1bc9a0SAchim Leubner /** \fn mpiMsgFreeSet(mpiOCQueue_t *circularQ, void *messagePtr)
8034e1bc9a0SAchim Leubner  *  \brief Returns a received message to the outbound queue
8044e1bc9a0SAchim Leubner  *  \param circularQ   Pointer to an outbound queue
8054e1bc9a0SAchim Leubner  *  \param messagePtr1 Pointer to the returned message buffer to free
8064e1bc9a0SAchim Leubner  *  \param messagePtr2 Pointer to the returned message buffer to free if bc > 1
8074e1bc9a0SAchim Leubner  *
808*cef367e6SEitan Adler  * Returns consumed and processed message to the specified outbounf queue
8094e1bc9a0SAchim Leubner  *
8104e1bc9a0SAchim Leubner  * Return:
8114e1bc9a0SAchim Leubner  *         AGSA_RC_SUCCESS if the message has been returned succesfully
8124e1bc9a0SAchim Leubner  */
8134e1bc9a0SAchim Leubner /*******************************************************************************/
8144e1bc9a0SAchim Leubner GLOBAL FORCEINLINE
8154e1bc9a0SAchim Leubner bit32
mpiMsgFreeSet(mpiOCQueue_t * circularQ,void * messagePtr1,bit8 bc)8164e1bc9a0SAchim Leubner mpiMsgFreeSet(
8174e1bc9a0SAchim Leubner   mpiOCQueue_t *circularQ,
8184e1bc9a0SAchim Leubner   void *messagePtr1,
8194e1bc9a0SAchim Leubner   bit8 bc
8204e1bc9a0SAchim Leubner   )
8214e1bc9a0SAchim Leubner {
8224e1bc9a0SAchim Leubner   mpiMsgHeader_t     *msgHeader;
8234e1bc9a0SAchim Leubner 
8244e1bc9a0SAchim Leubner   SA_DBG4(("Entering function:mpiMsgFreeSet\n"));
8254e1bc9a0SAchim Leubner   SA_ASSERT(NULL != circularQ, "circularQ argument cannot be null");
8264e1bc9a0SAchim Leubner   SA_ASSERT(NULL != messagePtr1, "messagePtr1 argument cannot be null");
8274e1bc9a0SAchim Leubner   SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue is 0");
8284e1bc9a0SAchim Leubner 
8294e1bc9a0SAchim Leubner   /* Obtains the address of the entire message buffer, including the header */
8304e1bc9a0SAchim Leubner   msgHeader = (mpiMsgHeader_t*)(((bit8*)messagePtr1) - sizeof(mpiMsgHeader_t));
8314e1bc9a0SAchim Leubner 
8324e1bc9a0SAchim Leubner   if ( ((mpiMsgHeader_t*)((bit8*)circularQ->memoryRegion.virtPtr + circularQ->consumerIdx * circularQ->elementSize)) != msgHeader)
8334e1bc9a0SAchim Leubner   {
8344e1bc9a0SAchim Leubner     /* IOMB of CI points mismatch with Message Header - should never happened */
8354e1bc9a0SAchim Leubner     SA_DBG1(("mpiMsgFreeSet: Wrong CI, Q %d ConsumeIdx = %d msgHeader 0x%08x\n",circularQ->qNumber, circularQ->consumerIdx ,msgHeader->Header));
8364e1bc9a0SAchim Leubner     SA_DBG1(("mpiMsgFreeSet: msgHeader %p != %p\n", msgHeader,((mpiMsgHeader_t*)((bit8*)circularQ->memoryRegion.virtPtr + circularQ->consumerIdx * circularQ->elementSize))));
8374e1bc9a0SAchim Leubner 
8384e1bc9a0SAchim Leubner #ifdef LOOPBACK_MPI
8394e1bc9a0SAchim Leubner     if (!loopback)
8404e1bc9a0SAchim Leubner #endif
8414e1bc9a0SAchim Leubner     /* Update the producer index from SPC */
8424e1bc9a0SAchim Leubner     OSSA_READ_LE_32(circularQ->agRoot, &circularQ->producerIdx, circularQ->piPointer, 0);
8434e1bc9a0SAchim Leubner #if defined(SALLSDK_DEBUG)
8444e1bc9a0SAchim Leubner     SA_DBG3(("mpiMsgFreeSet: ProducerIdx = %d\n", circularQ->producerIdx));
8454e1bc9a0SAchim Leubner #endif
8464e1bc9a0SAchim Leubner     return AGSA_RC_SUCCESS;
8474e1bc9a0SAchim Leubner   }
8484e1bc9a0SAchim Leubner 
8494e1bc9a0SAchim Leubner   /* ... free the circular queue buffer elements associated with the message ... */
8504e1bc9a0SAchim Leubner   /*... by incrementing the consumer index (with wrap arround) */
8514e1bc9a0SAchim Leubner   circularQ->consumerIdx = (circularQ->consumerIdx + bc) % circularQ->numElements;
8524e1bc9a0SAchim Leubner 
8534e1bc9a0SAchim Leubner   /* Invalidates this circular queue buffer element */
8544e1bc9a0SAchim Leubner 
8554e1bc9a0SAchim Leubner   msgHeader->Header &= ~HEADER_V_MASK; /* Clear Valid bit to indicate IOMB consumed by host */
8564e1bc9a0SAchim Leubner   SA_ASSERT(circularQ->consumerIdx <= circularQ->numElements, "Multi-buffer messages cannot wrap arround");
8574e1bc9a0SAchim Leubner 
8584e1bc9a0SAchim Leubner   /* update the CI of outbound queue */
8594e1bc9a0SAchim Leubner #ifdef LOOPBACK_MPI
8604e1bc9a0SAchim Leubner   if (!loopback)
8614e1bc9a0SAchim Leubner #endif
8624e1bc9a0SAchim Leubner   {
8634e1bc9a0SAchim Leubner   ossaHwRegWriteExt(circularQ->agRoot,
8644e1bc9a0SAchim Leubner                     circularQ->CIPCIBar,
8654e1bc9a0SAchim Leubner                     circularQ->CIPCIOffset,
8664e1bc9a0SAchim Leubner                     circularQ->consumerIdx);
8674e1bc9a0SAchim Leubner 
8684e1bc9a0SAchim Leubner   /* Update the producer index from SPC */
8694e1bc9a0SAchim Leubner   OSSA_READ_LE_32(circularQ->agRoot, &circularQ->producerIdx, circularQ->piPointer, 0);
8704e1bc9a0SAchim Leubner   }
8714e1bc9a0SAchim Leubner #if defined(SALLSDK_DEBUG)
8724e1bc9a0SAchim Leubner   SA_DBG5(("mpiMsgFreeSet: CI=%d PI=%d\n", circularQ->consumerIdx, circularQ->producerIdx));
8734e1bc9a0SAchim Leubner #endif
8744e1bc9a0SAchim Leubner   return AGSA_RC_SUCCESS;
8754e1bc9a0SAchim Leubner }
8764e1bc9a0SAchim Leubner 
8774e1bc9a0SAchim Leubner #ifdef TEST
mpiRotateQnumber(agsaRoot_t * agRoot)8784e1bc9a0SAchim Leubner GLOBAL bit32 mpiRotateQnumber(agsaRoot_t *agRoot)
8794e1bc9a0SAchim Leubner {
8804e1bc9a0SAchim Leubner   agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
8814e1bc9a0SAchim Leubner   bit32        denom;
8824e1bc9a0SAchim Leubner   bit32        ret = 0;
8834e1bc9a0SAchim Leubner 
8844e1bc9a0SAchim Leubner   /* inbound queue number */
8854e1bc9a0SAchim Leubner   saRoot->IBQnumber++;
8864e1bc9a0SAchim Leubner   denom = saRoot->QueueConfig.numInboundQueues;
8874e1bc9a0SAchim Leubner   if (saRoot->IBQnumber % denom == 0) /* % Qnumber*/
8884e1bc9a0SAchim Leubner   {
8894e1bc9a0SAchim Leubner     saRoot->IBQnumber = 0;
8904e1bc9a0SAchim Leubner   }
8914e1bc9a0SAchim Leubner   SA_DBG3(("mpiRotateQnumber: IBQnumber %d\n", saRoot->IBQnumber));
8924e1bc9a0SAchim Leubner 
8934e1bc9a0SAchim Leubner   /* outbound queue number */
8944e1bc9a0SAchim Leubner   saRoot->OBQnumber++;
8954e1bc9a0SAchim Leubner   denom = saRoot->QueueConfig.numOutboundQueues;
8964e1bc9a0SAchim Leubner   if (saRoot->OBQnumber % denom == 0) /* % Qnumber*/
8974e1bc9a0SAchim Leubner   {
8984e1bc9a0SAchim Leubner     saRoot->OBQnumber = 0;
8994e1bc9a0SAchim Leubner   }
9004e1bc9a0SAchim Leubner   SA_DBG3(("mpiRotateQnumber: OBQnumber %d\n", saRoot->OBQnumber));
9014e1bc9a0SAchim Leubner 
9024e1bc9a0SAchim Leubner   ret = (saRoot->OBQnumber << SHIFT16) | saRoot->IBQnumber;
9034e1bc9a0SAchim Leubner   return ret;
9044e1bc9a0SAchim Leubner }
9054e1bc9a0SAchim Leubner #endif
9064e1bc9a0SAchim Leubner 
9074e1bc9a0SAchim Leubner #ifdef LOOPBACK_MPI
mpiMsgProduceOQ(mpiOCQueue_t * circularQ,void * messagePtr,mpiMsgCategory_t category,bit16 opCode,bit8 responseQueue,bit8 hiPriority)9084e1bc9a0SAchim Leubner GLOBAL bit32 mpiMsgProduceOQ(
9094e1bc9a0SAchim Leubner                        mpiOCQueue_t *circularQ,
9104e1bc9a0SAchim Leubner                        void         *messagePtr,
9114e1bc9a0SAchim Leubner                        mpiMsgCategory_t category,
9124e1bc9a0SAchim Leubner                        bit16        opCode,
9134e1bc9a0SAchim Leubner                        bit8         responseQueue,
9144e1bc9a0SAchim Leubner                        bit8         hiPriority
9154e1bc9a0SAchim Leubner                        )
9164e1bc9a0SAchim Leubner {
9174e1bc9a0SAchim Leubner   mpiMsgHeader_t *msgHeader;
9184e1bc9a0SAchim Leubner   bit32          bc;
9194e1bc9a0SAchim Leubner   bit32          Header = 0;
9204e1bc9a0SAchim Leubner   bit32          hpriority = 0;
9214e1bc9a0SAchim Leubner 
9224e1bc9a0SAchim Leubner   SA_DBG4(("Entering function:mpiMsgProduceOQ\n"));
9234e1bc9a0SAchim Leubner   SA_ASSERT(NULL != circularQ, "circularQ argument cannot be null");
9244e1bc9a0SAchim Leubner   SA_ASSERT(NULL != messagePtr, "messagePtr argument cannot be null");
9254e1bc9a0SAchim Leubner   SA_ASSERT(0 != circularQ->numElements, "The number of elements in this queue"
9264e1bc9a0SAchim Leubner             " is 0");
9274e1bc9a0SAchim Leubner   SA_ASSERT(MPI_MAX_OUTBOUND_QUEUES > responseQueue, "oQueue ID is wrong");
9284e1bc9a0SAchim Leubner 
9294e1bc9a0SAchim Leubner   /* REB Start extra trace */
9304e1bc9a0SAchim Leubner   smTraceFuncEnter(hpDBG_VERY_LOUD, "2I");
9314e1bc9a0SAchim Leubner   /* REB End extra trace */
9324e1bc9a0SAchim Leubner 
9334e1bc9a0SAchim Leubner   /* Obtains the address of the entire message buffer, including the header */
9344e1bc9a0SAchim Leubner   msgHeader = (mpiMsgHeader_t*)(((bit8*)messagePtr) - sizeof(mpiMsgHeader_t));
9354e1bc9a0SAchim Leubner   /* Read the BC from header, its stored in native endian format when message
9364e1bc9a0SAchim Leubner      was allocated */
9374e1bc9a0SAchim Leubner   /* intially */
9384e1bc9a0SAchim Leubner   SA_DBG4(("mpiMsgProduceOQ: msgHeader %p opcode %d pi/ci %d / %d\n", msgHeader, opCode, circularQ->producerIdx, circularQ->consumerIdx));
9394e1bc9a0SAchim Leubner   bc = (((msgHeader->Header) >> SHIFT24) & BC_MASK);
9404e1bc9a0SAchim Leubner   SA_DBG6(("mpiMsgProduceOQ: msgHeader bc %d\n", bc));
9414e1bc9a0SAchim Leubner   if (circularQ->priority)
9424e1bc9a0SAchim Leubner     hpriority = 1;
9434e1bc9a0SAchim Leubner 
9444e1bc9a0SAchim Leubner   /* Checks the message is in "allocated" state */
9454e1bc9a0SAchim Leubner   SA_ASSERT(0 != bc, "The message buffer is not in \"allocated\" state "
9464e1bc9a0SAchim Leubner                      "(bc == 0)");
9474e1bc9a0SAchim Leubner 
9484e1bc9a0SAchim Leubner   Header = ((V_BIT << SHIFT31) | (hpriority << SHIFT30)  |
9494e1bc9a0SAchim Leubner             ((bc & BC_MASK) << SHIFT24) |
9504e1bc9a0SAchim Leubner             ((responseQueue & OBID_MASK) << SHIFT16) |
9514e1bc9a0SAchim Leubner             ((category  & CAT_MASK) << SHIFT12 ) | (opCode & OPCODE_MASK));
9524e1bc9a0SAchim Leubner   /* pre flush the IOMB cache line */
9534e1bc9a0SAchim Leubner   //ossaCachePreFlush(circularQ->agRoot,
9544e1bc9a0SAchim Leubner   //                  (void *)circularQ->memoryRegion.appHandle,
9554e1bc9a0SAchim Leubner   //                  (void *)msgHeader, circularQ->elementSize * bc);
9564e1bc9a0SAchim Leubner   OSSA_WRITE_LE_32(circularQ->agRoot, msgHeader, OSSA_OFFSET_OF(mpiMsgHeader_t,
9574e1bc9a0SAchim Leubner                    Header), Header);
9584e1bc9a0SAchim Leubner 
9594e1bc9a0SAchim Leubner   /* flush the IOMB cache line */
9604e1bc9a0SAchim Leubner   //ossaCacheFlush(circularQ->agRoot, (void *)circularQ->memoryRegion.appHandle,
9614e1bc9a0SAchim Leubner   //               (void *)msgHeader, circularQ->elementSize * bc);
9624e1bc9a0SAchim Leubner 
9634e1bc9a0SAchim Leubner   MPI_DEBUG_TRACE( circularQ->qNumber,
9644e1bc9a0SAchim Leubner                  ((circularQ->producerIdx << 16 ) | circularQ->consumerIdx),
9654e1bc9a0SAchim Leubner                   MPI_DEBUG_TRACE_OBQ,
9664e1bc9a0SAchim Leubner                   (void *)msgHeader,
9674e1bc9a0SAchim Leubner                   circularQ->elementSize);
9684e1bc9a0SAchim Leubner 
9694e1bc9a0SAchim Leubner   ossaLogIomb(circularQ->agRoot,
9704e1bc9a0SAchim Leubner               circularQ->qNumber,
9714e1bc9a0SAchim Leubner               TRUE,
9724e1bc9a0SAchim Leubner               (void *)msgHeader,
9734e1bc9a0SAchim Leubner               circularQ->elementSize);
9744e1bc9a0SAchim Leubner 
9754e1bc9a0SAchim Leubner   smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2I");
9764e1bc9a0SAchim Leubner   return AGSA_RC_SUCCESS;
9774e1bc9a0SAchim Leubner } /* mpiMsgProduceOQ */
9784e1bc9a0SAchim Leubner #endif
9794e1bc9a0SAchim Leubner 
980