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