1 /*******************************************************************************
2 *Copyright (c) 2014 PMC-Sierra, Inc. All rights reserved.
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
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.
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
21 ********************************************************************************/
22 /*******************************************************************************/
24 * \brief The file implements the functions for SMP request/response
27 /*******************************************************************************/
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30 #include <dev/pms/config.h>
32 #include <dev/pms/RefTisa/sallsdk/spc/saglobal.h>
33 #ifdef SA_ENABLE_TRACE_FUNCTIONS
37 #define siTraceFileID 'N'
40 /******************************************************************************/
41 /*! \brief Start SMP request
45 * \param agRoot handles for this instance of SAS/SATA hardware
49 * \param agRequestType
50 * \param agRequestBody
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
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
61 /*******************************************************************************/
62 GLOBAL bit32 saSMPStart(
64 agsaIORequest_t *agIORequest,
66 agsaDevHandle_t *agDevHandle,
68 agsaSASRequestBody_t *agRequestBody,
69 ossaSMPCompletedCB_t agCB
72 bit32 ret = AGSA_RC_SUCCESS, retVal;
73 agsaLLRoot_t *saRoot = agNULL;
74 mpiICQueue_t *circularQ;
75 agsaDeviceDesc_t *pDevice;
77 agsaIORequestDesc_t *pRequest;
80 bit8 using_reserved = agFALSE;
82 agsaSMPFrame_t *pSMPFrame;
84 SA_DBG4(("saSMPStart: start\n"));
86 smTraceFuncEnter(hpDBG_VERY_LOUD, "9a");
89 SA_ASSERT((agNULL != agRoot), "");
90 SA_ASSERT((agNULL != agIORequest), "");
91 SA_ASSERT((agNULL != agDevHandle), "");
92 SA_ASSERT((agNULL != agRequestBody), "");
95 saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
96 SA_ASSERT((agNULL != saRoot), "");
100 SA_DBG1(("saSMPStart : saRoot is NULL!!\n"));
101 return AGSA_RC_FAILURE;
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.");
109 /* Find the outgoing port for the device */
110 if (agNULL == agDevHandle->sdkData)
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;
118 pDevice = (agsaDeviceDesc_t *) (agDevHandle->sdkData);
120 pPort = pDevice->pPort;
122 /* Get request from free IO Requests */
123 ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
124 pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests)); /**/
126 /* If no LL IO request entry available */
127 if ( agNULL == pRequest )
130 pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeReservedRequests));
132 if(agNULL != pRequest)
134 using_reserved = agTRUE;
135 SA_DBG1(("saSMPStart, using saRoot->freeReservedRequests\n"));
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");
146 /* If free IOMB avaliable */
147 /* Remove the request from free list */
150 saLlistIORemove(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
154 saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
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);
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;
171 /* Set request to the sdkData of agIORequest */
172 agIORequest->sdkData = pRequest;
174 /* save tag to IOMap */
175 saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
176 saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
178 #ifdef SA_LL_IBQ_PROTECT
179 ossaSingleThreadedEnter(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
180 #endif /* SA_LL_IBQ_PROTECT */
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);
187 if (AGSA_RC_FAILURE == retVal)
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);
199 SA_DBG1(("saSMPStart, error when get free IOMB\n"));
200 smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "9a");
201 return AGSA_RC_FAILURE;
204 /* return busy if inbound queue is full */
205 if (AGSA_RC_BUSY == retVal)
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);
217 SA_DBG1(("saSMPStart, no more IOMB\n"));
218 smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "9a");
222 /* Setup SMP Frame */
223 pSMPFrame = (agsaSMPFrame_t *) &(agRequestBody->smpFrame);
225 SA_DBG2(("saSMPStart:DeviceMapIndex 0x%x portId 0x%x portId 0x%x\n",pDevice->DeviceMapIndex,pPort->portId,pPort->portId));
227 #if defined(SALLSDK_DEBUG)
229 SA_DBG2(("saSMPStart: outFrameBuf %p\n",pSMPFrame->outFrameBuf));
231 if(pSMPFrame->outFrameBuf )
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) ));
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 */
259 agsaSMPCmd_t payload;
260 switch ( agRequestType )
262 case AGSA_SMP_INIT_REQ:
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);
270 /* check SMP Response Frame with IR mode */
271 /* check if the SMP Response is indirect mode */
272 if (0 == pSMPFrame->inFrameLen)
274 /* PHY override not support */
275 /* Direct Response mode */
276 pRequest->IRmode = DIRECT_MODE;
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)
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;
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) )
309 SA_DBG4(("saSMPStart: DIRECT Request SMP\n"));
311 IR_IP_OV_res_phyId_DPdLen_res = (DIRECT_MODE << 1) | IR_IP_OV_res_phyId_DPdLen_res;
313 /* Direct payload length */
314 IR_IP_OV_res_phyId_DPdLen_res |= (((pSMPFrame->outFrameLen) & 0xff) << SHIFT16);
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 ++ )
320 SA_DBG4(("saSMPStart: payload.SMPCmd[%d] %x\n", i, payload.SMPCmd[i]));
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;
329 /* Direct payload length = 0 */
330 IR_IP_OV_res_phyId_DPdLen_res = IR_IP_OV_res_phyId_DPdLen_res & 0xff00ffff;
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));
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);
341 if (IR_IP_OV_res_phyId_DPdLen_res & INDIRECT_MODE)
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));
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);
353 #ifdef SA_LL_IBQ_PROTECT
354 ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
355 #endif /* SA_LL_IBQ_PROTECT */
361 SA_DBG1(("saSMPStart: SPC unknown agRequestType %x\n",agRequestType));
367 if (ret == AGSA_RC_SUCCESS)
368 saRoot->LLCounters.IOCounter.numSMPStarted++;
371 else /* IOMB is different for SPCV SMP */
373 agsaSMPCmd_V_t vpayload;
375 switch ( agRequestType )
377 case AGSA_SMP_INIT_REQ:
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);
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) );
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 )
393 /* PHY override not support */
394 /* Direct Response mode */
395 pRequest->IRmode = DIRECT_MODE;
396 SA_DBG2(("saSMPStart:V DIRECT Request SMP\n"));
398 IR_IP_OV_res_phyId_DPdLen_res = (DIRECT_MODE << 1) | IR_IP_OV_res_phyId_DPdLen_res;
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 */
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) );
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) );
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) );
422 else if (smpFrameFlagIndirectResponse & pSMPFrame->flag && smpFrameFlagIndirectPayload & pSMPFrame->flag) /* */
425 SA_DBG2(("saSMPStart:V smpFrameFlagIndirectResponse smpFrameFlagIndirectPayload SMP\n"));
427 pRequest->IRmode = INDIRECT_MODE;
428 IR_IP_OV_res_phyId_DPdLen_res = 3;
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));
439 else if (smpFrameFlagIndirectPayload & pSMPFrame->flag ) /* */
442 SA_DBG2(("saSMPStart:V smpFrameFlagIndirectPayload SMP\n"));
443 pRequest->IRmode = DIRECT_MODE;
444 IR_IP_OV_res_phyId_DPdLen_res = 2;
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);
451 else if (smpFrameFlagIndirectResponse & pSMPFrame->flag ) /* */
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);
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) );
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) );
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));
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 */
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);
484 #ifdef SA_LL_IBQ_PROTECT
485 ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
486 #endif /* SA_LL_IBQ_PROTECT */
491 SA_DBG1(("saSMPStart: SPCv unknown agRequestType %x\n",agRequestType));
497 smTraceFuncExit(hpDBG_VERY_LOUD, 'f', "9a");
503 /******************************************************************************/
504 /*! \brief Abort SMP request
508 * \param agRoot handles for this instance of SAS/SATA hardware
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
516 /*******************************************************************************/
517 GLOBAL bit32 saSMPAbort(
519 agsaIORequest_t *agIORequest,
521 agsaDevHandle_t *agDevHandle,
524 ossaGenericAbortCB_t agCB
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;
536 smTraceFuncEnter(hpDBG_VERY_LOUD,"9b");
539 SA_ASSERT((agNULL != agRoot), "");
540 SA_ASSERT((agNULL != agIORequest), "");
541 SA_ASSERT((agNULL != agDevHandle), "");
543 SA_DBG3(("saSMPAbort: Aborting request %p\n", agIORequest));
545 if( ABORT_SINGLE == (flag & ABORT_MASK) )
547 agIOToBeAborted = (agsaIORequest_t *)abortParam;
548 /* Get LL IORequest entry for saSMPAbort() */
549 pRequestABT = (agsaIORequestDesc_t *) (agIOToBeAborted->sdkData);
550 if (agNULL == pRequestABT)
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;
558 /* Find the device the request Abort to */
559 pDevice = pRequestABT->pDevice;
561 if (agNULL == pDevice)
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;
571 if (ABORT_ALL == (flag & ABORT_MASK))
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)
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;
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;
593 /* Get LL IORequest entry */
594 ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
595 pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
597 /* If no LL IO request entry available */
598 if ( agNULL == pRequest )
600 pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeReservedRequests)); /**/
601 /* If no LL Control request entry available */
602 if(agNULL != pRequest)
604 using_reserved = agTRUE;
605 SA_DBG1(("saSMPAbort, using saRoot->freeReservedRequests\n"));
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");
616 /* If free IOMB avaliable */
617 /* Remove the request from free list */
620 saLlistIORemove(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
624 saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
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;
639 /* Set request to the sdkData of agIORequest */
640 agIORequest->sdkData = pRequest;
642 /* save tag to IOMap */
643 saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
644 saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
647 OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPAbortCmd_t, tag), pRequest->HTag);
649 if( ABORT_SINGLE == (flag & ABORT_MASK) )
651 if (agNULL == pRequestABT)
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)
663 SA_DBG1(("saSMPAbort: saving pRequest (%p) for later use\n", pRequest));
664 saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
668 /* return the request to free pool */
669 saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
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;
677 OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPAbortCmd_t, HTagAbort), pRequestABT->HTag);
682 OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSMPAbortCmd_t, HTagAbort), 0);
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);
687 SA_DBG1(("saSMPAbort, HTag 0x%x HTagABT 0x%x deviceId 0x%x\n", payload.tag, payload.HTagAbort, payload.deviceId));
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)
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)
703 SA_DBG1(("saSMPAbort: saving pRequest (%p) for later use\n", pRequest));
704 saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
708 /* return the request to free pool */
709 saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
711 ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
712 SA_DBG1(("saSMPAbort, sending IOMB failed\n" ));
717 saRoot->LLCounters.IOCounter.numSMPAborted++;
721 smTraceFuncExit(hpDBG_VERY_LOUD, 'g', "9b");