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