xref: /freebsd/sys/dev/pms/RefTisa/sallsdk/spc/mpi.c (revision 4e1bc9a039df516be13abb902ab76677fef81b1d)
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