xref: /freebsd/sys/dev/pms/RefTisa/sallsdk/spc/sasmp.c (revision b9f654b163bce26de79705e77b872427c9f2afa1)
1 /*******************************************************************************
2 *Copyright (c) 2014 PMC-Sierra, Inc.  All rights reserved.
3 *
4 *Redistribution and use in source and binary forms, with or without modification, are permitted provided
5 *that the following conditions are met:
6 *1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
7 *following disclaimer.
8 *2. Redistributions in binary form must reproduce the above copyright notice,
9 *this list of conditions and the following disclaimer in the documentation and/or other materials provided
10 *with the distribution.
11 *
12 *THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
13 *WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
14 *FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
15 *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
16 *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
17 *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18 *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
19 *SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
20 
21 ********************************************************************************/
22 /*******************************************************************************/
23 /*! \file sasmp.c
24  *  \brief The file implements the functions for SMP request/response
25  *
26  */
27 /*******************************************************************************/
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30 #include <dev/pms/config.h>
31 
32 #include <dev/pms/RefTisa/sallsdk/spc/saglobal.h>
33 #ifdef SA_ENABLE_TRACE_FUNCTIONS
34 #ifdef siTraceFileID
35 #undef siTraceFileID
36 #endif
37 #define siTraceFileID 'N'
38 #endif
39 
40 /******************************************************************************/
41 /*! \brief Start SMP request
42  *
43  *  Start SMP request
44  *
45  *  \param agRoot handles for this instance of SAS/SATA hardware
46  *  \param queueNum
47  *  \param agIORequest
48  *  \param agDevHandle
49  *  \param agRequestType
50  *  \param agRequestBody
51  *  \param agCB
52  * Spc - support    direct mode direct response
53  * SpcV - support   direct mode direct response
54  * SpcV - support indirect mode  direct response
55  * SpcV - support indirect mode indirect response
56  *
57  *  \return If request is started successfully
58  *          - \e AGSA_RC_SUCCESS request is started successfully
59  *          - \e AGSA_RC_BUSY No resource available, try again later
60  */
61 /*******************************************************************************/
62 GLOBAL bit32 saSMPStart(
63   agsaRoot_t            *agRoot,
64   agsaIORequest_t       *agIORequest,
65   bit32                 queueNum,
66   agsaDevHandle_t       *agDevHandle,
67   bit32                 agRequestType,
68   agsaSASRequestBody_t  *agRequestBody,
69   ossaSMPCompletedCB_t  agCB
70   )
71 {
72   bit32                     ret = AGSA_RC_SUCCESS, retVal;
73   agsaLLRoot_t              *saRoot = agNULL;
74   mpiICQueue_t              *circularQ;
75   agsaDeviceDesc_t          *pDevice;
76   agsaPort_t                *pPort;
77   agsaIORequestDesc_t       *pRequest;
78   void                      *pMessage;
79   bit8                      i, inq, outq;
80   bit8                      using_reserved = agFALSE;
81   bit8                      *payload_ptr;
82   agsaSMPFrame_t            *pSMPFrame;
83 
84   SA_DBG4(("saSMPStart: start\n"));
85 
86   smTraceFuncEnter(hpDBG_VERY_LOUD, "9a");
87 
88   /* sanity check */
89   SA_ASSERT((agNULL != agRoot), "");
90   SA_ASSERT((agNULL != agIORequest), "");
91   SA_ASSERT((agNULL != agDevHandle), "");
92   SA_ASSERT((agNULL != agRequestBody), "");
93 
94   /* sanity check */
95   saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
96   SA_ASSERT((agNULL != saRoot), "");
97 
98   if(saRoot == agNULL)
99   {
100     SA_DBG1(("saSMPStart : saRoot is NULL!!\n"));
101     return AGSA_RC_FAILURE;
102   }
103 
104   /* Assign inbound and outbound queue number */
105   inq = (bit8)(queueNum & MPI_IB_NUM_MASK);
106   outq = (bit8)((queueNum & MPI_OB_NUM_MASK) >> MPI_OB_SHIFT);
107   SA_ASSERT((AGSA_MAX_INBOUND_Q > inq), "The IBQ Number is out of range.");
108 
109   /* Find the outgoing port for the device */
110   if (agNULL == agDevHandle->sdkData)
111   {
112     /* Device has been removed */
113     SA_DBG1(("saSMPStart, Device has been removed. agDevHandle=%p\n", agDevHandle));
114     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "9a");
115     return AGSA_RC_FAILURE;
116   }
117 
118   pDevice = (agsaDeviceDesc_t *) (agDevHandle->sdkData);
119 
120   pPort = pDevice->pPort;
121 
122   /* Get request from free IO Requests */
123   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
124   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests)); /**/
125 
126   /* If no LL IO request entry available */
127   if ( agNULL == pRequest )
128   {
129 
130     pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeReservedRequests));
131 
132     if(agNULL != pRequest)
133     {
134       using_reserved = agTRUE;
135       SA_DBG1(("saSMPStart, using saRoot->freeReservedRequests\n"));
136     }
137     else
138     {
139       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
140       SA_DBG1(("saSMPStart, No request from free list Not using saRoot->freeReservedRequests\n"));
141       smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "9a");
142       return AGSA_RC_BUSY;
143     }
144   }
145 
146   /* If free IOMB avaliable */
147   /* Remove the request from free list */
148   if( using_reserved )
149   {
150     saLlistIORemove(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
151   }
152   else
153   {
154     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
155   }
156 
157   /* Add the request to the pendingSMPRequests list of the device */
158   saLlistIOAdd(&(pDevice->pendingIORequests), &(pRequest->linkNode));
159   SA_ASSERT((!pRequest->valid), "The pRequest is in use");
160   pRequest->valid             = agTRUE;
161   ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
162 
163   /* set up pRequest */
164   pRequest->pIORequestContext = agIORequest;
165   pRequest->pDevice           = pDevice;
166   pRequest->pPort             = pPort;
167   pRequest->requestType       = agRequestType;
168   pRequest->startTick         = saRoot->timeTick;
169   pRequest->completionCB      = (ossaSSPCompletedCB_t)agCB;
170 
171   /* Set request to the sdkData of agIORequest */
172   agIORequest->sdkData        = pRequest;
173 
174   /* save tag to IOMap */
175   saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
176   saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
177 
178 #ifdef SA_LL_IBQ_PROTECT
179   ossaSingleThreadedEnter(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
180 #endif /* SA_LL_IBQ_PROTECT */
181 
182   /* If LL IO request entry avaliable */
183   /* Get a free inbound queue entry */
184   circularQ = &saRoot->inboundQueue[inq];
185   retVal    = mpiMsgFreeGet(circularQ, IOMB_SIZE64, &pMessage);
186 
187   if (AGSA_RC_FAILURE == retVal)
188   {
189 #ifdef SA_LL_IBQ_PROTECT
190     ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
191 #endif /* SA_LL_IBQ_PROTECT */
192     /* if not sending return to free list rare */
193     ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
194     saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode));
195     pRequest->valid = agFALSE;
196     saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
197     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
198 
199     SA_DBG1(("saSMPStart, error when get free IOMB\n"));
200     smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "9a");
201     return AGSA_RC_FAILURE;
202   }
203 
204   /* return busy if inbound queue is full */
205   if (AGSA_RC_BUSY == retVal)
206   {
207 #ifdef SA_LL_IBQ_PROTECT
208     ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
209 #endif /* SA_LL_IBQ_PROTECT */
210     /* if not sending return to free list rare */
211     ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
212     saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode));
213     pRequest->valid = agFALSE;
214     saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
215     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
216 
217     SA_DBG1(("saSMPStart, no more IOMB\n"));
218     smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "9a");
219     return AGSA_RC_BUSY;
220   }
221 
222   /* Setup SMP Frame */
223   pSMPFrame = (agsaSMPFrame_t *) &(agRequestBody->smpFrame);
224 
225   SA_DBG2(("saSMPStart:DeviceMapIndex 0x%x portId 0x%x portId 0x%x\n",pDevice->DeviceMapIndex,pPort->portId,pPort->portId));
226 
227 #if defined(SALLSDK_DEBUG)
228 
229   SA_DBG2(("saSMPStart: outFrameBuf  %p\n",pSMPFrame->outFrameBuf));
230 
231   if(pSMPFrame->outFrameBuf )
232   {
233     SA_DBG2(("saSMPStart: outFrameBuf 0  0x%08X\n",*((bit32*)pSMPFrame->outFrameBuf+0) ));
234     SA_DBG2(("saSMPStart: outFrameBuf 1  0x%08X\n",*((bit32*)pSMPFrame->outFrameBuf+1) ));
235     SA_DBG2(("saSMPStart: outFrameBuf 2  0x%08X\n",*((bit32*)pSMPFrame->outFrameBuf+2) ));
236     SA_DBG2(("saSMPStart: outFrameBuf 3  0x%08X\n",*((bit32*)pSMPFrame->outFrameBuf+3) ));
237     SA_DBG2(("saSMPStart: outFrameBuf 4  0x%08X\n",*((bit32*)pSMPFrame->outFrameBuf+4) ));
238     SA_DBG2(("saSMPStart: outFrameBuf 5  0x%08X\n",*((bit32*)pSMPFrame->outFrameBuf+5) ));
239     SA_DBG2(("saSMPStart: outFrameBuf 6  0x%08X\n",*((bit32*)pSMPFrame->outFrameBuf+6) ));
240     SA_DBG2(("saSMPStart: outFrameBuf 7  0x%08X\n",*((bit32*)pSMPFrame->outFrameBuf+7) ));
241     SA_DBG2(("saSMPStart: outFrameBuf 8  0x%08X\n",*((bit32*)pSMPFrame->outFrameBuf+8) ));
242     SA_DBG2(("saSMPStart: outFrameBuf 9  0x%08X\n",*((bit32*)pSMPFrame->outFrameBuf+9) ));
243     SA_DBG2(("saSMPStart: outFrameBuf 11 0x%08X\n",*((bit32*)pSMPFrame->outFrameBuf+10) ));
244     SA_DBG2(("saSMPStart: outFrameBuf 11 0x%08X\n",*((bit32*)pSMPFrame->outFrameBuf+11) ));
245   }
246   SA_DBG2(("saSMPStart: outFrameAddrUpper32 0x%08X\n",pSMPFrame->outFrameAddrUpper32));
247   SA_DBG2(("saSMPStart: outFrameAddrLower32 0x%08X\n",pSMPFrame->outFrameAddrLower32));
248   SA_DBG2(("saSMPStart: outFrameLen         0x%08X\n",pSMPFrame->outFrameLen));
249   SA_DBG2(("saSMPStart: inFrameAddrUpper32  0x%08X\n",pSMPFrame->inFrameAddrUpper32));
250   SA_DBG2(("saSMPStart: inFrameAddrLower32  0x%08X\n",pSMPFrame->inFrameAddrLower32));
251   SA_DBG2(("saSMPStart: inFrameLen          0x%08X\n",pSMPFrame->inFrameLen));
252   SA_DBG2(("saSMPStart: expectedRespLen     0x%08X\n",pSMPFrame->expectedRespLen));
253   SA_DBG2(("saSMPStart: flag                0x%08X\n",pSMPFrame->flag));
254 #endif /* SALLSDK_DEBUG */
255 
256   if(smIS_SPC(agRoot))
257   // if(1)
258   {
259     agsaSMPCmd_t payload;
260     switch ( agRequestType )
261     {
262       case AGSA_SMP_INIT_REQ:
263       {
264         bit32 IR_IP_OV_res_phyId_DPdLen_res = 0;
265         /* Prepare the payload of IOMB */
266         si_memset(&payload, 0, sizeof(agsaSMPCmd_t));
267         OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, tag), pRequest->HTag);
268         OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, deviceId), pDevice->DeviceMapIndex);
269 
270         /* check SMP Response Frame with IR mode */
271         /* check if the SMP Response is indirect mode */
272         if (0 == pSMPFrame->inFrameLen)
273         {
274           /* PHY override not support */
275           /* Direct Response mode */
276           pRequest->IRmode = DIRECT_MODE;
277         }
278         else
279         {
280           /* Indirect Response mode */
281           pRequest->IRmode = INDIRECT_MODE;
282           IR_IP_OV_res_phyId_DPdLen_res = 1;
283           /* check SMP direct payload mode len */
284           if (pSMPFrame->outFrameLen > 32)
285           {
286 #ifdef SA_LL_IBQ_PROTECT
287             ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
288 #endif /* SA_LL_IBQ_PROTECT */
289             /* if not sending return to free list rare */
290             ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
291             saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode));
292             pRequest->valid = agFALSE;
293             saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
294             ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
295             /* can not handle SMP frame length > 32 bytes it if IP=0 and IR=1 */
296             SA_DBG1(("saSMPStart, outFrameLen > 32 bytes error.\n"));
297             smTraceFuncExit(hpDBG_VERY_LOUD, 'e', "9a");
298             return AGSA_RC_FAILURE;
299           }
300         }
301 
302         /* check Direct mode or Indirect mode for IP mode */
303         if ( (pSMPFrame->outFrameBuf &&
304               (pSMPFrame->outFrameLen <= AGSA_MAX_SMPPAYLOAD_VIA_SFO)) ||
305              ((pSMPFrame->outFrameBuf == agNULL) &&
306               (pSMPFrame->outFrameLen == 0) )
307            )
308         {
309           SA_DBG4(("saSMPStart: DIRECT Request SMP\n"));
310 
311           IR_IP_OV_res_phyId_DPdLen_res = (DIRECT_MODE << 1) | IR_IP_OV_res_phyId_DPdLen_res;
312 
313           /* Direct payload length */
314           IR_IP_OV_res_phyId_DPdLen_res |= (((pSMPFrame->outFrameLen) & 0xff) << SHIFT16);
315 
316           /* copy payload - upto 48 bytes */
317           si_memcpy(&(payload.SMPCmd[0]),pSMPFrame->outFrameBuf,pSMPFrame->outFrameLen);
318           for ( i = 0; i < pSMPFrame->outFrameLen / sizeof(bit32)+1; i ++ )
319           {
320             SA_DBG4(("saSMPStart: payload.SMPCmd[%d] %x\n", i, payload.SMPCmd[i]));
321           }
322         }
323         else
324         {
325           SA_DBG4(("saSMPStart: INDIRECT Request SMP\n"));
326           /* use physical address */
327           IR_IP_OV_res_phyId_DPdLen_res = (INDIRECT_MODE << 1) | IR_IP_OV_res_phyId_DPdLen_res;
328 
329           /* Direct payload length = 0 */
330           IR_IP_OV_res_phyId_DPdLen_res = IR_IP_OV_res_phyId_DPdLen_res & 0xff00ffff;
331 
332           /* payload */
333           OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, SMPCmd[4]), (pSMPFrame->outFrameAddrLower32));
334           OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, SMPCmd[5]), (pSMPFrame->outFrameAddrUpper32));
335           OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, SMPCmd[6]), (pSMPFrame->outFrameLen));
336         }
337         /* Write IR_IP_OV_res_phyId_DPdLen_res field in the payload*/
338         OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, IR_IP_OV_res_phyId_DPdLen_res), IR_IP_OV_res_phyId_DPdLen_res);
339 
340         /* check IR bit */
341         if (IR_IP_OV_res_phyId_DPdLen_res & INDIRECT_MODE)
342         {
343           /* setup indirect response frame address */
344           OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, SMPCmd[8]), (pSMPFrame->inFrameAddrLower32));
345           OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, SMPCmd[9]), (pSMPFrame->inFrameAddrUpper32));
346           OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPCmd_t, SMPCmd[10]), (pSMPFrame->inFrameLen));
347         }
348 
349         /* Build IOMB command and send it to SPC */
350         payload_ptr = (bit8 *)&payload;
351         ret = mpiSMPCmd(agRoot, pMessage, OPC_INB_SMP_REQUEST, (agsaSMPCmd_t *)payload_ptr, inq, outq);
352 
353   #ifdef SA_LL_IBQ_PROTECT
354         ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
355   #endif /* SA_LL_IBQ_PROTECT */
356 
357         break;
358       }
359       default:
360       {
361         SA_DBG1(("saSMPStart: SPC unknown agRequestType  %x\n",agRequestType));
362         break;
363       }
364     }
365 
366 #ifdef SALL_API_TEST
367   if (ret == AGSA_RC_SUCCESS)
368     saRoot->LLCounters.IOCounter.numSMPStarted++;
369 #endif
370   }
371   else /* IOMB is different for SPCV SMP */
372   {
373    agsaSMPCmd_V_t vpayload;
374 
375     switch ( agRequestType )
376     {
377       case AGSA_SMP_INIT_REQ:
378       {
379         bit32 IR_IP_OV_res_phyId_DPdLen_res = 0;
380         /* Prepare the payload of IOMB */
381         si_memset(&vpayload, 0, sizeof(agsaSMPCmd_V_t));
382         OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, tag), pRequest->HTag);
383         OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, deviceId), pDevice->DeviceMapIndex);
384 
385         /* Request header must be valid regardless of IP bit */
386         OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,SMPHDR ), *((bit32*)pSMPFrame->outFrameBuf+0) );
387 
388         /* check SMP Response Frame with IR mode */
389         /* check if the SMP Response is indirect mode */
390         // smpFrameFlagDirectResponse smpFrameFlagDirectPayload
391         if ( 0 == pSMPFrame->flag && pSMPFrame->outFrameBuf )
392         {
393           /* PHY override not support */
394           /* Direct Response mode */
395           pRequest->IRmode = DIRECT_MODE;
396           SA_DBG2(("saSMPStart:V DIRECT Request SMP\n"));
397 
398           IR_IP_OV_res_phyId_DPdLen_res = (DIRECT_MODE << 1) | IR_IP_OV_res_phyId_DPdLen_res;
399 
400           /* Direct payload length */
401           IR_IP_OV_res_phyId_DPdLen_res |= (((pSMPFrame->outFrameLen) & 0xff) << SHIFT16);
402           /* Write IR_IP_OV_res_phyId_DPdLen_res field in the payload*/
403           /* fatal error if missing */
404           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, IR_IP_OV_res_phyId_DPdLen_res), IR_IP_OV_res_phyId_DPdLen_res);
405           /* fatal error if missing */
406 
407           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,SMP3_0 ), *((bit32*)pSMPFrame->outFrameBuf+1) );
408           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,SMP7_4 ), *((bit32*)pSMPFrame->outFrameBuf+2) );
409           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,SMP11_8), *((bit32*)pSMPFrame->outFrameBuf+3) );
410 
411           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirL_SMPRF15_12 ),     *((bit32*)pSMPFrame->outFrameBuf+4) );
412           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirH_or_SMPRF19_16 ),  *((bit32*)pSMPFrame->outFrameBuf+5) );
413           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirLen_or_SMPRF23_20 ),*((bit32*)pSMPFrame->outFrameBuf+6) );
414           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,R_or_SMPRF27_24),        *((bit32*)pSMPFrame->outFrameBuf+7) );
415 
416           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,ISRAL_or_SMPRF31_28 ),   *((bit32*)pSMPFrame->outFrameBuf+8) );
417           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,ISRAH_or_SMPRF35_32 ),   *((bit32*)pSMPFrame->outFrameBuf+9) );
418           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,ISRL_or_SMPRF39_36 ),    *((bit32*)pSMPFrame->outFrameBuf+10) );
419           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,R_or_SMPRF43_40 ),       *((bit32*)pSMPFrame->outFrameBuf+11) );
420 
421         }
422         else if (smpFrameFlagIndirectResponse & pSMPFrame->flag && smpFrameFlagIndirectPayload & pSMPFrame->flag) /* */
423         {
424           /* IR IP */
425           SA_DBG2(("saSMPStart:V smpFrameFlagIndirectResponse smpFrameFlagIndirectPayload SMP\n"));
426 
427           pRequest->IRmode = INDIRECT_MODE;
428           IR_IP_OV_res_phyId_DPdLen_res = 3;
429 
430           /* Indirect payload mode */
431           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirL_SMPRF15_12 ), pSMPFrame->outFrameAddrLower32);
432           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirH_or_SMPRF19_16 ), pSMPFrame->outFrameAddrUpper32);
433           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirLen_or_SMPRF23_20 ), pSMPFrame->outFrameLen);
434           /* Indirect Response mode */
435           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, ISRAL_or_SMPRF31_28 ), (pSMPFrame->inFrameAddrLower32));
436           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, ISRAH_or_SMPRF35_32 ), (pSMPFrame->inFrameAddrUpper32));
437           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, ISRL_or_SMPRF39_36 ), (pSMPFrame->inFrameLen));
438         }
439         else if (smpFrameFlagIndirectPayload & pSMPFrame->flag ) /* */
440         {
441           /* IP */
442           SA_DBG2(("saSMPStart:V  smpFrameFlagIndirectPayload SMP\n"));
443           pRequest->IRmode = DIRECT_MODE;
444           IR_IP_OV_res_phyId_DPdLen_res = 2;
445 
446           /* Indirect payload mode */
447           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirL_SMPRF15_12 ), pSMPFrame->outFrameAddrLower32);
448           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirH_or_SMPRF19_16 ), pSMPFrame->outFrameAddrUpper32);
449           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirLen_or_SMPRF23_20 ), pSMPFrame->outFrameLen);
450         }
451         else if (smpFrameFlagIndirectResponse & pSMPFrame->flag ) /* */
452         {
453           /* check IR bit */
454           /* Indirect Response mode */
455           pRequest->IRmode = INDIRECT_MODE;
456           SA_DBG2(("saSMPStart:V smpFrameFlagIndirectResponse SMP\n"));
457           /* use physical address */
458           IR_IP_OV_res_phyId_DPdLen_res = 1;
459           /* Direct payload length */
460           IR_IP_OV_res_phyId_DPdLen_res |= (((pSMPFrame->outFrameLen) & 0xff) << SHIFT16);
461 
462           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,SMP3_0 ), *((bit32*)pSMPFrame->outFrameBuf+1) );
463           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,SMP7_4 ), *((bit32*)pSMPFrame->outFrameBuf+2) );
464           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,SMP11_8), *((bit32*)pSMPFrame->outFrameBuf+3) );
465 
466           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirL_SMPRF15_12 ),     *((bit32*)pSMPFrame->outFrameBuf+4) );
467           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirH_or_SMPRF19_16 ),  *((bit32*)pSMPFrame->outFrameBuf+5) );
468           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,IndirLen_or_SMPRF23_20 ),*((bit32*)pSMPFrame->outFrameBuf+6) );
469           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t,R_or_SMPRF27_24),        *((bit32*)pSMPFrame->outFrameBuf+7) );
470 
471           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, ISRAL_or_SMPRF31_28 ), (pSMPFrame->inFrameAddrLower32));
472           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, ISRAH_or_SMPRF35_32 ), (pSMPFrame->inFrameAddrUpper32));
473           OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, ISRL_or_SMPRF39_36 ), (pSMPFrame->inFrameLen));
474         }
475         IR_IP_OV_res_phyId_DPdLen_res |= (pSMPFrame->flag & 3);
476         /* fatal error if missing */
477         OSSA_WRITE_LE_32(agRoot, &vpayload, OSSA_OFFSET_OF(agsaSMPCmd_V_t, IR_IP_OV_res_phyId_DPdLen_res), IR_IP_OV_res_phyId_DPdLen_res);
478         /* fatal error if missing */
479       }
480       /* Build IOMB command and send it to SPCv */
481       payload_ptr = (bit8 *)&vpayload;
482       ret = mpiSMPCmd(agRoot, pMessage, OPC_INB_SMP_REQUEST, (agsaSMPCmd_t *)payload_ptr, inq, outq);
483 
484 #ifdef SA_LL_IBQ_PROTECT
485       ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
486 #endif /* SA_LL_IBQ_PROTECT */
487 
488       break;
489       default:
490       {
491         SA_DBG1(("saSMPStart: SPCv unknown agRequestType  %x\n",agRequestType));
492         break;
493       }
494     }
495   }
496 
497   smTraceFuncExit(hpDBG_VERY_LOUD, 'f', "9a");
498 
499   /* return */
500   return ret;
501 }
502 
503 /******************************************************************************/
504 /*! \brief Abort SMP request
505  *
506  *  Abort SMP request
507  *
508  *  \param agRoot handles for this instance of SAS/SATA hardware
509  *  \param queueNum
510  *  \param agIORequest
511  *
512  *  \return If request is aborted successfully
513  *          - \e AGSA_RC_SUCCESS request is aborted successfully
514  *          - \e AGSA_RC_FAILURE request is not aborted successfully
515  */
516 /*******************************************************************************/
517 GLOBAL bit32 saSMPAbort(
518   agsaRoot_t           *agRoot,
519   agsaIORequest_t      *agIORequest,
520   bit32                 queueNum,
521   agsaDevHandle_t      *agDevHandle,
522   bit32                 flag,
523   void                 *abortParam,
524   ossaGenericAbortCB_t  agCB
525   )
526 {
527   bit32 ret = AGSA_RC_SUCCESS;
528   agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
529   agsaIORequestDesc_t *pRequest;
530   agsaIORequestDesc_t *pRequestABT = NULL;
531   agsaIORequest_t     *agIOToBeAborted;
532   agsaDeviceDesc_t    *pDevice;
533   agsaSMPAbortCmd_t   payload;
534   bit32               using_reserved = agFALSE;
535 
536   smTraceFuncEnter(hpDBG_VERY_LOUD,"9b");
537 
538   /* sanity check */
539   SA_ASSERT((agNULL != agRoot), "");
540   SA_ASSERT((agNULL != agIORequest), "");
541   SA_ASSERT((agNULL != agDevHandle), "");
542 
543   SA_DBG3(("saSMPAbort: Aborting request %p\n", agIORequest));
544 
545   if( ABORT_SINGLE == (flag & ABORT_MASK) )
546   {
547     agIOToBeAborted = (agsaIORequest_t *)abortParam;
548     /* Get LL IORequest entry for saSMPAbort() */
549     pRequestABT = (agsaIORequestDesc_t *) (agIOToBeAborted->sdkData);
550     if (agNULL == pRequestABT)
551     {
552       /* The IO to Be Abort is no longer exist - can not Abort */
553       SA_DBG1(("saSMPAbort: pRequestABT AGSA_RC_FAILURE\n"));
554       smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "9b");
555       return AGSA_RC_FAILURE;
556     }
557 
558     /* Find the device the request Abort to */
559     pDevice = pRequestABT->pDevice;
560 
561     if (agNULL == pDevice)
562     {
563       /* no deviceID - can not build IOMB */
564       SA_DBG1(("saSMPAbort: pDevice AGSA_RC_FAILURE\n"));
565       smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "9b");
566       return AGSA_RC_FAILURE;
567     }
568   }
569   else
570   {
571     if (ABORT_ALL == (flag & ABORT_MASK))
572     {
573       /* abort All with Device or Port */
574       /* Find the outgoing port for the device */
575       pDevice = (agsaDeviceDesc_t *) (agDevHandle->sdkData);
576       if (agNULL == pDevice)
577       {
578         /* no deviceID - can not build IOMB */
579         SA_DBG1(("saSMPAbort:ABORT_ALL pDevice AGSA_RC_FAILURE\n"));
580         smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "9b");
581         return AGSA_RC_FAILURE;
582       }
583     }
584     else
585     {
586       /* only support 00 and 01 for flag */
587       SA_DBG1(("saSMPAbort:flag  AGSA_RC_FAILURE\n"));
588       smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "9b");
589       return AGSA_RC_FAILURE;
590     }
591   }
592 
593   /* Get LL IORequest entry */
594   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
595   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
596 
597   /* If no LL IO request entry available */
598   if ( agNULL == pRequest )
599   {
600     pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeReservedRequests)); /**/
601     /* If no LL Control request entry available */
602     if(agNULL != pRequest)
603     {
604       using_reserved = agTRUE;
605       SA_DBG1(("saSMPAbort, using saRoot->freeReservedRequests\n"));
606     }
607     else
608     {
609       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
610       SA_DBG1(("saSMPAbort, No request from free list Not using saRoot->freeReservedRequests\n"));
611       smTraceFuncExit(hpDBG_VERY_LOUD, 'e', "9b");
612       return AGSA_RC_BUSY;
613     }
614   }
615 
616   /* If free IOMB avaliable */
617   /* Remove the request from free list */
618   if( using_reserved )
619   {
620     saLlistIORemove(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
621   }
622   else
623   {
624     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
625   }
626 
627   /* Add the request to the pendingSMPRequests list of the device */
628   saLlistIOAdd(&(pDevice->pendingIORequests), &(pRequest->linkNode));
629   SA_ASSERT((!pRequest->valid), "The pRequest is in use");
630   pRequest->valid             = agTRUE;
631   ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
632   /* set up pRequest */
633   pRequest->pIORequestContext = agIORequest;
634   pRequest->requestType       = AGSA_SMP_REQTYPE;
635   pRequest->completionCB = (void*)agCB;
636   pRequest->pDevice           = pDevice;
637   pRequest->startTick         = saRoot->timeTick;
638 
639   /* Set request to the sdkData of agIORequest */
640   agIORequest->sdkData        = pRequest;
641 
642   /* save tag to IOMap */
643   saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
644   saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
645 
646   /* setup payload */
647   OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPAbortCmd_t, tag), pRequest->HTag);
648 
649   if( ABORT_SINGLE == (flag & ABORT_MASK) )
650   {
651     if (agNULL == pRequestABT)
652     {
653       /* remove the request from IOMap */
654       saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
655       saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
656       saRoot->IOMap[pRequest->HTag].agContext = agNULL;
657       /* Delete the request from the pendingSMPRequests */
658       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
659       saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode));
660       /* return the request to free pool */
661       if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
662       {
663         SA_DBG1(("saSMPAbort: saving pRequest (%p) for later use\n", pRequest));
664         saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
665       }
666       else
667       {
668         /* return the request to free pool */
669         saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
670       }
671       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
672       SA_DBG1(("saSMPAbort, agNULL == pRequestABT\n"));
673       /* The IO to Be Abort is no longer exist - can not Abort */
674       smTraceFuncExit(hpDBG_VERY_LOUD, 'f', "9b");
675       return AGSA_RC_FAILURE;
676     }
677     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPAbortCmd_t, HTagAbort), pRequestABT->HTag);
678   }
679   else
680   {
681     /* abort all */
682     OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPAbortCmd_t, HTagAbort), 0);
683   }
684   OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPAbortCmd_t, deviceId), pDevice->DeviceMapIndex);
685   OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPAbortCmd_t, Scp), flag);
686 
687   SA_DBG1(("saSMPAbort, HTag 0x%x HTagABT 0x%x deviceId 0x%x\n", payload.tag, payload.HTagAbort, payload.deviceId));
688 
689   /* build IOMB command and send to SPC */
690   ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_SMP_ABORT, IOMB_SIZE64, queueNum);
691   if (AGSA_RC_SUCCESS != ret)
692   {
693     /* remove the request from IOMap */
694     saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
695     saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
696     saRoot->IOMap[pRequest->HTag].agContext = agNULL;
697     /* Delete the request from the pendingSMPRequests */
698     ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
699     saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode));
700     /* return the request to free pool */
701     if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
702     {
703       SA_DBG1(("saSMPAbort: saving pRequest (%p) for later use\n", pRequest));
704       saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
705     }
706     else
707     {
708       /* return the request to free pool */
709       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
710     }
711     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
712     SA_DBG1(("saSMPAbort, sending IOMB failed\n" ));
713   }
714 #ifdef SALL_API_TEST
715   else
716   {
717     saRoot->LLCounters.IOCounter.numSMPAborted++;
718   }
719 #endif
720 
721   smTraceFuncExit(hpDBG_VERY_LOUD, 'g', "9b");
722 
723   return ret;
724 }
725 
726 
727 
728