xref: /freebsd/sys/dev/pms/RefTisa/sallsdk/spc/sassp.c (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1 /*******************************************************************************
2 **
3 *Copyright (c) 2014 PMC-Sierra, Inc.  All rights reserved.
4 *
5 *Redistribution and use in source and binary forms, with or without modification, are permitted provided
6 *that the following conditions are met:
7 *1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
8 *following disclaimer.
9 *2. Redistributions in binary form must reproduce the above copyright notice,
10 *this list of conditions and the following disclaimer in the documentation and/or other materials provided
11 *with the distribution.
12 *
13 *THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
14 *WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
15 *FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
16 *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
17 *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
18 *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
19 *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
20 *SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
21 
22 ********************************************************************************/
23 /*******************************************************************************/
24 /*! \file sassp.c
25  *  \brief The file implements the functions for SSP request/response
26  *
27  */
28 /*******************************************************************************/
29 #include <sys/cdefs.h>
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 'O'
38 #endif
39 
40 #ifdef LOOPBACK_MPI
41 extern int loopback;
42 #endif
43 
44 #ifdef SALLSDK_DEBUG
45 LOCAL void siDumpSSPStartIu(
46   agsaDevHandle_t       *agDevHandle,
47   bit32                 agRequestType,
48   agsaSASRequestBody_t  *agRequestBody
49   );
50 #endif
51 
52 #ifdef FAST_IO_TEST
53 LOCAL bit32 saGetIBQPI(agsaRoot_t *agRoot,
54                        bit32 queueNum)
55 {
56   bit8         inq;
57   mpiICQueue_t *circularQ;
58   agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
59 
60   inq = INQ(queueNum);
61   circularQ = &saRoot->inboundQueue[inq];
62   return circularQ->producerIdx;
63 }
64 
65 LOCAL void saSetIBQPI(agsaRoot_t *agRoot,
66                       bit32      queueNum,
67                       bit32      pi)
68 {
69   bit8         inq;
70   mpiICQueue_t *circularQ;
71   agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
72 
73   inq = INQ(queueNum);
74   circularQ = &saRoot->inboundQueue[inq];
75   circularQ->producerIdx = pi;
76 }
77 
78 osLOCAL void*
79 siFastSSPReqAlloc(agsaRoot_t *agRoot)
80 {
81   int             idx;
82   agsaLLRoot_t    *saRoot = (agsaLLRoot_t*)(agRoot->sdkData);
83   saFastRequest_t *fr;
84 
85   if (!saRoot->freeFastIdx)
86   {
87     SA_DBG1(("saSuperSSPReqAlloc: no memory ERROR\n"));
88     SA_ASSERT((0), "");
89     return 0;
90   }
91 
92   ossaSingleThreadedEnter(agRoot, LL_FAST_IO_LOCK);
93   saRoot->freeFastIdx--;
94   idx = saRoot->freeFastIdx;
95   ossaSingleThreadedLeave(agRoot, LL_FAST_IO_LOCK);
96 
97   fr = saRoot->freeFastReq[idx];
98   SA_ASSERT((fr), "");
99   fr->valid = 1;
100 
101   return fr;
102 }
103 
104 LOCAL void
105 siFastSSPReqFree(
106              agsaRoot_t *agRoot,
107              void       *freq)
108 {
109   agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
110   saFastRequest_t *fr = (saFastRequest_t*)freq;
111 
112   SA_DBG2(("siFastSSPReqFree: enter\n"));
113   SA_ASSERT((fr->valid), "");
114   if (saRoot->freeFastIdx >= sizeof(saRoot->freeFastReq) /
115                              sizeof(saRoot->freeFastReq[0]))
116   {
117     SA_DBG1(("siFastSSPReqFree: too many handles %d / %d ERROR\n",
118              saRoot->freeFastIdx, (int)(sizeof(saRoot->freeFastReq) /
119              sizeof(saRoot->freeFastReq[0]))));
120     SA_ASSERT((0), "");
121     return;
122   }
123   ossaSingleThreadedEnter(agRoot, LL_FAST_IO_LOCK);
124   /* not need if only one entry */
125   /* saRoot->freeFastReq[saRoot->freeFastIdx] = freq;  */
126   saRoot->freeFastIdx++;
127   ossaSingleThreadedLeave(agRoot, LL_FAST_IO_LOCK);
128 
129   fr->valid = 0;
130   SA_DBG6(("siFastSSPReqFree: leave\n"));
131 }
132 
133 LOCAL bit32 siFastSSPResAlloc(
134   agsaRoot_t             *agRoot,
135   bit32                  queueNum,
136   bit32                  agRequestType,
137   agsaDeviceDesc_t       *pDevice,
138   agsaIORequestDesc_t    **pRequest,
139   void                   **pPayload
140   )
141 {
142   agsaLLRoot_t *saRoot = (agsaLLRoot_t*)(agRoot->sdkData);
143   mpiICQueue_t *circularQ;
144   bit8  inq;
145   bit16 size = IOMB_SIZE64;
146   bit32 ret = AGSA_RC_SUCCESS, retVal;
147 
148   smTraceFuncEnter(hpDBG_VERY_LOUD,"2D");
149 
150   SA_DBG4(("Entering function siFastSSPResAlloc:\n"));
151 
152   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
153   *pRequest = (agsaIORequestDesc_t*)saLlistIOGetHead(&saRoot->freeIORequests);
154 
155   /* If no LL IO request entry available */
156   if (agNULL == *pRequest )
157   {
158     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
159     SA_DBG1(("siFastSSPResAlloc: No request from free list\n" ));
160     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2D");
161     ret = AGSA_RC_BUSY;
162     goto ext;
163   }
164 
165   /* Get IO request from free IORequests */
166   /* Assign inbound and outbound Buffer */
167   inq = INQ(queueNum);
168   SA_ASSERT((AGSA_MAX_INBOUND_Q > inq), "The IBQ Number is out of range.");
169 
170   /* SSP_INI_IO_START_EXT IOMB need at least 80 bytes to support 32 CDB */
171   if (agRequestType & AGSA_SSP_EXT_BIT)
172   {
173     size = IOMB_SIZE96;
174   }
175   /* If LL IO request entry avaliable */
176   /* Get a free inbound queue entry */
177   circularQ = &saRoot->inboundQueue[inq];
178   retVal = mpiMsgFreeGet(circularQ, size, pPayload);
179 
180   /* if message size is too large return failure */
181   if (AGSA_RC_SUCCESS != retVal)
182   {
183     if (AGSA_RC_FAILURE == retVal)
184     {
185       SA_DBG1(("siFastSSPResAlloc: error when get free IOMB\n"));
186       smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2D");
187     }
188 
189     /* return busy if inbound queue is full */
190     if (AGSA_RC_BUSY == retVal)
191     {
192       SA_DBG3(("siFastSSPResAlloc: no more IOMB\n"));
193       smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "2D");
194     }
195     ret = retVal;
196     goto ext;
197   }
198 
199   /* But add it to the pending queue during FastStart */
200   /* If free IOMB avaliable */
201   /* Remove the request from free list */
202   saLlistIORemove(&saRoot->freeIORequests, &(*pRequest)->linkNode);
203 
204   /* Add the request to the pendingIORequests list of the device */
205   saLlistIOAdd(&pDevice->pendingIORequests, &(*pRequest)->linkNode);
206 
207 ext:
208   ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
209 
210   if (AGSA_RC_SUCCESS == ret)
211   {
212     /* save tag and IOrequest pointer to IOMap */
213     saRoot->IOMap[(*pRequest)->HTag].Tag = (*pRequest)->HTag;
214     saRoot->IOMap[(*pRequest)->HTag].IORequest = (void *)*pRequest;
215   }
216 
217   return ret;
218 } /* siFastSSPResAlloc */
219 
220 
221 GLOBAL bit32 saFastSSPCancel(void *ioHandle)
222 {
223   agsaRoot_t      *agRoot;
224   agsaLLRoot_t    *saRoot;
225   saFastRequest_t *fr;
226   bit32            i;
227   agsaIORequestDesc_t *ior;
228 
229   SA_ASSERT((ioHandle), "");
230   fr = (saFastRequest_t*)ioHandle;
231   SA_ASSERT((fr->valid), "");
232   agRoot = (agsaRoot_t*)fr->agRoot;
233   SA_ASSERT((agRoot), "");
234   saRoot = (agsaLLRoot_t*)(agRoot->sdkData);
235   SA_ASSERT((saRoot), "");
236 
237   smTraceFuncEnter(hpDBG_VERY_LOUD,"2E");
238 
239   /* rollback the previously set IBQ PI */
240   for (i = 0; i < fr->inqMax - 1; i++)
241     saSetIBQPI(agRoot, fr->inqList[i], fr->beforePI[fr->inqList[i]]);
242 
243   /* free all the previous Fast IO Requests */
244   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
245   /* at least one entry, no need to check for NULL saLlistIOGetHead() */
246   ior = (agsaIORequestDesc_t*)((char*)saLlistIOGetHead(&fr->requests) -
247                               OSSA_OFFSET_OF(agsaIORequestDesc_t, fastLink));
248   do
249   {
250     agsaDeviceDesc_t *pDevice;
251     void             *tmp;
252 
253     pDevice = ior->pDevice;
254     saLlistIORemove(&pDevice->pendingIORequests, &ior->linkNode);
255     saLlistIOAdd(&saRoot->freeIORequests, &ior->linkNode);
256 
257     tmp = (void*)saLlistGetNext(&fr->requests, &ior->fastLink);
258     if (!tmp)
259     {
260       break; /* end of list */
261     }
262     ior = (agsaIORequestDesc_t*)((char*)tmp -
263                                  OSSA_OFFSET_OF(agsaIORequestDesc_t, fastLink));
264   } while (1);
265 
266   ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
267 
268   /* free the IBQ PI tracking struct */
269   siFastSSPReqFree(agRoot, fr);
270 
271   smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2E");
272   return AGSA_RC_SUCCESS;
273 } /* saFastSSPCancel */
274 
275 GLOBAL void *saFastSSPPrepare(
276                  void                 *ioh,
277                  agsaFastCommand_t    *fc,
278                  ossaSSPCompletedCB_t cb,
279                  void                 *cbArg)
280 {
281   bit32            ret = AGSA_RC_SUCCESS;
282   agsaRoot_t       *agRoot;
283   agsaLLRoot_t     *saRoot;
284   mpiICQueue_t     *circularQ;
285   agsaDeviceDesc_t *pDevice;
286   agsaSgl_t        *pSgl;
287   bit32            Dir = 0;
288   bit8             inq, outq;
289   saFastRequest_t  *fr;
290   void             *pMessage;
291   agsaIORequestDesc_t *pRequest;
292   bit16            opCode;
293   bitptr           offsetTag;
294   bitptr           offsetDeviceId;
295   bitptr           offsetDataLen;
296   bitptr           offsetDir;
297 
298   agRoot = (agsaRoot_t*)fc->agRoot;
299   smTraceFuncEnter(hpDBG_VERY_LOUD,"2G");
300 
301   OSSA_INP_ENTER(agRoot);
302 
303   saRoot = (agsaLLRoot_t*)(agRoot->sdkData);
304   /* sanity check */
305   SA_ASSERT((agNULL != saRoot), "");
306 
307   SA_DBG4(("Entering function saFastSSPPrepare:\n"));
308 
309   fr = (saFastRequest_t*)ioh;
310   if (!fr)
311   {
312     int i;
313     fr = siFastSSPReqAlloc(agRoot);
314     if (!fr)
315     {
316       SA_ASSERT((0), "");
317       goto ext;
318     }
319 
320     saLlistIOInitialize(&fr->requests);
321     for (i = 0; i < AGSA_MAX_INBOUND_Q; i++)
322       fr->beforePI[i] = (bit32)-1;
323 
324     fr->inqMax = 0;
325     fr->agRoot = agRoot;
326     ioh = fr;
327   }
328 
329   /* Find the outgoing port for the device */
330   pDevice = (agsaDeviceDesc_t*)(((agsaDevHandle_t*)fc->devHandle)->sdkData);
331 
332   ret = siFastSSPResAlloc(agRoot, fc->queueNum, fc->agRequestType,
333                           pDevice, &pRequest, &pMessage);
334   if (ret != AGSA_RC_SUCCESS)
335   {
336     SA_ASSERT((0), "");
337     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2G");
338     goto ext;
339   }
340 
341   /* Assign inbound and outbound Buffer */
342   inq = INQ(fc->queueNum);
343   outq = OUQ(fc->queueNum);
344   circularQ = &saRoot->inboundQueue[inq];
345 
346   SA_DBG3(("saFastSSPPrepare: deviceId %d\n", pDevice->DeviceMapIndex));
347 
348   /* set up pRequest */
349   pRequest->valid = agTRUE;
350   pRequest->pDevice = pDevice;
351   pRequest->requestType = fc->agRequestType;
352 
353   pRequest->completionCB = cb;
354   pRequest->pIORequestContext = (agsaIORequest_t*)cbArg;
355 
356   pSgl = fc->agSgl;
357 
358   switch (fc->agRequestType)
359   {
360     /* case AGSA_SSP_INIT_NONDATA: */
361     case AGSA_SSP_INIT_READ:
362     case AGSA_SSP_INIT_WRITE:
363     case AGSA_SSP_INIT_READ_M:
364     case AGSA_SSP_INIT_WRITE_M:
365     {
366       agsaSSPIniIOStartCmd_t *pPayload = (agsaSSPIniIOStartCmd_t *)pMessage;
367       agsaSSPCmdInfoUnit_t   *piu;
368 
369       /* SSPIU less equal 28 bytes */
370       offsetTag = OSSA_OFFSET_OF(agsaSSPIniIOStartCmd_t, tag);
371       offsetDeviceId = OSSA_OFFSET_OF(agsaSSPIniIOStartCmd_t, deviceId);
372       offsetDataLen = OSSA_OFFSET_OF(agsaSSPIniIOStartCmd_t, dataLen);
373       offsetDir = OSSA_OFFSET_OF(agsaSSPIniIOStartCmd_t, dirMTlr);
374 
375       piu = &pPayload->SSPInfoUnit;
376 
377       si_memcpy(piu->lun, fc->lun, sizeof(piu->lun));
378       si_memcpy(piu->cdb, fc->cdb, sizeof(piu->cdb));
379       piu->efb_tp_taskAttribute = fc->taskAttribute;
380       piu->additionalCdbLen = fc->additionalCdbLen;
381 
382       /* Mask DIR for Read/Write command */
383       Dir = fc->agRequestType & AGSA_DIR_MASK;
384 
385       /* set TLR */
386       Dir |= fc->flag & TLR_MASK;
387       if (fc->agRequestType & AGSA_MSG)
388       {
389         /* set M bit */
390         Dir |= AGSA_MSG_BIT;
391       }
392 
393       /* Setup SGL */
394       if (fc->dataLength)
395       {
396         SA_DBG5(("saFastSSPPrepare: agSgl %08x:%08x (%x/%x)\n",
397                  pSgl->sgUpper, pSgl->sgLower, pSgl->len, pSgl->extReserved));
398         /*
399         pPayload->AddrLow0 = pSgl->sgLower;
400         pPayload->AddrHi0 = pSgl->sgUpper;
401         pPayload->Len0 = pSgl->len;
402         pPayload->E0 = pSgl->extReserved;
403         */
404         si_memcpy(&pPayload->AddrLow0, pSgl, sizeof(*pSgl));
405       }
406       else
407       {
408         /* no data transfer */
409         si_memset(&pPayload->AddrLow0, 0, sizeof(*pSgl));
410       }
411 
412       opCode = OPC_INB_SSPINIIOSTART;
413       break;
414     }
415 
416     case AGSA_SSP_INIT_READ_EXT:
417     case AGSA_SSP_INIT_WRITE_EXT:
418     case AGSA_SSP_INIT_READ_EXT_M:
419     case AGSA_SSP_INIT_WRITE_EXT_M:
420     {
421       agsaSSPIniExtIOStartCmd_t *pPayload =
422                                     (agsaSSPIniExtIOStartCmd_t *)pMessage;
423       agsaSSPCmdInfoUnitExt_t   *piu;
424       bit32 sspiul;
425 
426       /* CDB > 16 bytes */
427       offsetTag = OSSA_OFFSET_OF(agsaSSPIniExtIOStartCmd_t, tag);
428       offsetDeviceId = OSSA_OFFSET_OF(agsaSSPIniExtIOStartCmd_t, deviceId);
429       offsetDataLen = OSSA_OFFSET_OF(agsaSSPIniExtIOStartCmd_t, dataLen);
430       offsetDir = OSSA_OFFSET_OF(agsaSSPIniExtIOStartCmd_t, SSPIuLendirMTlr);
431 
432       /* dword (bit7-bit2) ==> bytes (bit7-bit0) */
433       /* setup standard CDB bytes + additional CDB bytes in length field */
434       sspiul = sizeof(agsaSSPCmdInfoUnit_t) + (fc->additionalCdbLen & 0xFC);
435 
436       Dir = sspiul << 16;
437       piu = (agsaSSPCmdInfoUnitExt_t*)pPayload->SSPIu;
438 
439       si_memcpy(piu->lun, fc->lun, sizeof(piu->lun));
440       si_memcpy(piu->cdb, fc->cdb, MIN(sizeof(piu->cdb),
441                                        16 + fc->additionalCdbLen));
442       piu->efb_tp_taskAttribute = fc->taskAttribute;
443       piu->additionalCdbLen = fc->additionalCdbLen;
444 
445       /* Mask DIR for Read/Write command */
446       Dir |= fc->agRequestType & AGSA_DIR_MASK;
447 
448       /* set TLR */
449       Dir |= fc->flag & TLR_MASK;
450       if (fc->agRequestType & AGSA_MSG)
451       {
452         /* set M bit */
453         Dir |= AGSA_MSG_BIT;
454       }
455 
456       /* Setup SGL */
457       if (fc->dataLength)
458       {
459         SA_DBG5(("saSuperSSPSend: Ext mode, agSgl %08x:%08x (%x/%x)\n",
460           pSgl->sgUpper, pSgl->sgLower, pSgl->len, pSgl->extReserved));
461 
462         si_memcpy((&(pPayload->SSPIu[0]) + sspiul), pSgl, sizeof(*pSgl));
463       }
464       else //?
465       {
466         /* no data transfer */
467         //pPayload->dataLen = 0;
468         si_memset((&(pPayload->SSPIu[0]) + sspiul), 0, sizeof(*pSgl));
469       }
470       SA_ASSERT((smIS_SPC(agRoot)), "smIS_SPC");
471       opCode = OPC_INB_SSPINIEXTIOSTART;
472       break;
473     }
474 
475     default:
476     {
477       SA_DBG1(("saSuperSSPSend: Unsupported Request IOMB\n"));
478       ret = AGSA_RC_FAILURE;
479       SA_ASSERT((0), "");
480       smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2G");
481       goto ext;
482     }
483   }
484 
485   OSSA_WRITE_LE_32(agRoot, pMessage, offsetTag, pRequest->HTag);
486   OSSA_WRITE_LE_32(agRoot, pMessage, offsetDeviceId, pDevice->DeviceMapIndex);
487   OSSA_WRITE_LE_32(agRoot, pMessage, offsetDataLen, fc->dataLength);
488   OSSA_WRITE_LE_32(agRoot, pMessage, offsetDir, Dir);
489 
490   if (fr->beforePI[inq] == -1)
491   {
492     /* save the new IBQ' PI */
493     fr->beforePI[inq] = saGetIBQPI(agRoot, inq);
494     fr->inqList[fr->inqMax++] = inq;
495   }
496 
497   /* post the IOMB to SPC */
498   ret = mpiMsgPrepare(circularQ, (void *)pMessage, MPI_CATEGORY_SAS_SATA,
499                       opCode, outq, 0);
500   if (AGSA_RC_SUCCESS != ret)
501   {
502     SA_ASSERT((0), "");
503     ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
504     /* Remove the request from pendingIORequests list */
505     saLlistIORemove(&pDevice->pendingIORequests, &pRequest->linkNode);
506 
507     /* Add the request to the free list of the device */
508     saLlistIOAdd(&saRoot->freeIORequests, &pRequest->linkNode);
509     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
510 
511     SA_DBG1(("saFastSSPPrepare: error when post SSP IOMB\n"));
512     smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "2G");
513     goto ext;
514   }
515 
516   /* Add the request to the pendingFastIORequests list of the device */
517   saLlistIOAdd(&fr->requests, &pRequest->fastLink);
518   smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "2G");
519 
520 ext:
521   if (fr && ret != AGSA_RC_SUCCESS)
522   {
523     saFastSSPCancel(fr);
524     ioh = 0;
525   }
526   OSSA_INP_LEAVE(agRoot);
527   return ioh;
528 } /* saFastSSPPrepare */
529 
530 GLOBAL bit32 saFastSSPSend(void *ioHandle)
531 {
532   bit8            inq;
533   agsaRoot_t      *agRoot;
534   agsaLLRoot_t    *saRoot;
535   saFastRequest_t *fr;
536   bit32           i;
537 
538   SA_ASSERT((ioHandle), "");
539   fr = (saFastRequest_t*)ioHandle;
540   agRoot = (agsaRoot_t*)fr->agRoot;
541   SA_ASSERT((agRoot), "");
542   saRoot = (agsaLLRoot_t*)agRoot->sdkData;
543   SA_ASSERT((saRoot), "");
544 
545   SA_DBG4(("Entering function saFastSSPSend:\n"));
546 
547   for (i = 0; i < fr->inqMax; i++)
548   {
549     inq = INQ(fr->inqList[i]);
550     /* FW interrupt */
551     mpiIBQMsgSend(&saRoot->inboundQueue[inq]);
552   }
553   /* IORequests are freed in siIODone() */
554 
555   siFastSSPReqFree(agRoot, fr);
556   return AGSA_RC_SUCCESS;
557 } /* saFastSSPSend */
558 #endif
559 
560 /******************************************************************************/
561 /*! \brief Start SSP request
562  *
563  *  Start SSP request
564  *
565  *  \param agRoot handles for this instance of SAS/SATA LLL
566  *  \param queueNum
567  *  \param agIORequest
568  *  \param agDevHandle
569  *  \param agRequestType
570  *  \param agRequestBody
571  *  \param agTMRequest valid for task management
572  *  \param agCB
573  *
574  *  \return If request is started successfully
575  *          - \e AGSA_RC_SUCCESS request is started successfully
576  *          - \e AGSA_RC_BUSY request is not started successfully
577  */
578 /******************************************************************************/
579 GLOBAL bit32 saSSPStart(
580   agsaRoot_t            *agRoot,
581   agsaIORequest_t       *agIORequest,
582   bit32                 queueNum,
583   agsaDevHandle_t       *agDevHandle,
584   bit32                 agRequestType,
585   agsaSASRequestBody_t  *agRequestBody,
586   agsaIORequest_t       *agTMRequest,
587   ossaSSPCompletedCB_t  agCB)
588 {
589   agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
590 #ifdef LOOPBACK_MPI
591   mpiOCQueue_t        *circularOQ = agNULL;
592 #endif
593   mpiICQueue_t        *circularQ  = agNULL;
594   agsaDeviceDesc_t    *pDevice    = agNULL;
595   agsaPort_t          *pPort      = agNULL;
596   agsaIORequestDesc_t *pRequest   = agNULL;
597   agsaSgl_t           *pSgl       = agNULL;
598   void                *pMessage   = agNULL;
599   bit32               ret = AGSA_RC_SUCCESS, retVal = 0;
600   bit32               DirDW4 = 0;    /* no data and no AutoGR */
601   bit32               encryptFlags = 0;
602   bit16               size = 0;
603   bit16               opCode = 0;
604   bit8                inq = 0, outq = 0;
605 
606 
607   OSSA_INP_ENTER(agRoot);
608   smTraceFuncEnter(hpDBG_VERY_LOUD,"Sa");
609 
610   /* sanity check */
611   SA_ASSERT((agNULL != agRoot), "");
612   SA_ASSERT((agNULL != agIORequest), "");
613   SA_ASSERT((agNULL != agDevHandle), "");
614   SA_ASSERT((agNULL != agRequestBody), "");
615 
616   DBG_DUMP_SSPSTART_CMDIU(agDevHandle,agRequestType,agRequestBody);
617 
618   /* Find the outgoing port for the device */
619   pDevice = (agsaDeviceDesc_t *) (agDevHandle->sdkData);
620 
621   if(pDevice == agNULL )
622   {
623     SA_ASSERT((pDevice), "pDevice");
624     ret = AGSA_RC_FAILURE;
625     smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Sa");
626     goto ext;
627   }
628 
629   pPort = pDevice->pPort;
630   /* Assign inbound and outbound Buffer */
631   inq = (bit8)(queueNum & MPI_IB_NUM_MASK);
632   outq = (bit8)((queueNum & MPI_OB_NUM_MASK) >> MPI_OB_SHIFT);
633   SA_ASSERT((AGSA_MAX_INBOUND_Q > inq), "The IBQ Number is out of range.");
634 
635   SA_DBG3(("saSSPStart: inq %d outq %d deviceId 0x%x\n", inq,outq,pDevice->DeviceMapIndex));
636 
637   /* Get request from free IORequests */
638   ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
639   pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
640 
641   /* If no LL IO request entry available */
642   if ( agNULL == pRequest )
643   {
644     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
645     SA_DBG1(("saSSPStart, No request from free list\n" ));
646     smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "Sa");
647     ret = AGSA_RC_BUSY;
648     goto ext;
649   }
650   /* If LL IO request entry avaliable */
651   else
652   {
653     /* Remove the request from free list */
654     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
655     /* Add the request to the pendingIORequests list of the device */
656     saLlistIOAdd(&(pDevice->pendingIORequests), &(pRequest->linkNode));
657 
658     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
659 
660     SA_ASSERT((!pRequest->valid), "The pRequest is in use");
661 
662     SA_DBG3(("saSSPStart, request %p\n", pRequest ));
663 
664     /* Decode the flag settings in the standard I/O requests to  decide what size we need. */
665     /* All other requests will be fine with only 64 byte messages. */
666     switch ( agRequestType )
667     {
668     case AGSA_SSP_INIT_READ:
669     case AGSA_SSP_INIT_WRITE:
670     case AGSA_SSP_INIT_NONDATA:
671     case AGSA_SSP_INIT_READ_M:
672     case AGSA_SSP_INIT_WRITE_M:
673         {
674             agsaSSPInitiatorRequest_t *pIRequest = &(agRequestBody->sspInitiatorReq);
675 
676             if ((pIRequest->flag & AGSA_SAS_ENABLE_ENCRYPTION)   ||
677 #ifdef SAFLAG_USE_DIF_ENC_IOMB
678                (pIRequest->flag & AGSA_SAS_USE_DIF_ENC_OPSTART)  ||
679 #endif /* SAFLAG_USE_DIF_ENC_IOMB */
680                 (pIRequest->flag & AGSA_SAS_ENABLE_DIF) )
681             {
682                 opCode = OPC_INB_SSP_DIF_ENC_OPSTART;
683                 size = IOMB_SIZE128;
684             }
685             else
686             {
687                 opCode = OPC_INB_SSPINIIOSTART;
688                 size = IOMB_SIZE64;
689             }
690             break;
691         }
692     case AGSA_SSP_INIT_READ_EXT:
693     case AGSA_SSP_INIT_WRITE_EXT:
694     case AGSA_SSP_INIT_READ_EXT_M:
695     case AGSA_SSP_INIT_WRITE_EXT_M:
696         {
697           agsaSSPInitiatorRequestExt_t *pIRequest = &(agRequestBody->sspInitiatorReqExt);
698 
699           if ((pIRequest->flag & AGSA_SAS_ENABLE_ENCRYPTION)   ||
700               (pIRequest->flag & AGSA_SAS_ENABLE_DIF)          ||
701 #ifdef SAFLAG_USE_DIF_ENC_IOMB
702               (pIRequest->flag & AGSA_SAS_USE_DIF_ENC_OPSTART) ||
703 #endif /* SAFLAG_USE_DIF_ENC_IOMB */
704               (pIRequest->flag & AGSA_SAS_ENABLE_SKIP_MASK))
705           {
706               opCode = OPC_INB_SSP_DIF_ENC_OPSTART;
707               size = IOMB_SIZE128;
708           }
709           else
710           {
711               SA_ASSERT((smIS_SPC(agRoot)), "smIS_SPC");
712               opCode = OPC_INB_SSPINIEXTIOSTART;
713               size = IOMB_SIZE96;
714           }
715           break;
716       }
717       case  AGSA_SSP_INIT_READ_INDIRECT:
718       case  AGSA_SSP_INIT_WRITE_INDIRECT:
719       case  AGSA_SSP_INIT_READ_INDIRECT_M:
720       case  AGSA_SSP_INIT_WRITE_INDIRECT_M:
721           {
722             SA_DBG3(("saSSPStart: agRequestType  0x%X INDIRECT\n", agRequestType));
723             opCode = OPC_INB_SSP_DIF_ENC_OPSTART;
724             size = IOMB_SIZE128;
725             break;
726           }
727       case (AGSA_SSP_REQTYPE | AGSA_SSP_TASK_MGNT):
728       case AGSA_SSP_TASK_MGNT_REQ_M:
729       case AGSA_SSP_TGT_READ_DATA:
730       case AGSA_SSP_TGT_READ_GOOD_RESP:
731       case AGSA_SSP_TGT_WRITE_DATA:
732       case AGSA_SSP_TGT_WRITE_GOOD_RESP:
733       case AGSA_SSP_TGT_CMD_OR_TASK_RSP:
734 
735         SA_DBG3(("saSSPStart: agRequestType  0x%X (was default)\n", agRequestType));
736         opCode = OPC_INB_SSPINIIOSTART;
737         size = IOMB_SIZE64;
738          break;
739     default:
740         SA_DBG1(("saSSPStart: agRequestType UNKNOWN 0x%X\n", agRequestType));
741         /* OpCode is not used in this case, but Linux complains if it is not initialized. */
742         opCode = OPC_INB_SSPINIIOSTART;
743         size = IOMB_SIZE64;
744         break;
745     }
746 
747     /* If free IOMB avaliable,  set up pRequest*/
748     pRequest->valid = agTRUE;
749     pRequest->pIORequestContext = agIORequest;
750     pRequest->pDevice = pDevice;
751     pRequest->requestType = agRequestType;
752     pRequest->pPort = pPort;
753     pRequest->startTick = saRoot->timeTick;
754     pRequest->completionCB = agCB;
755 
756     /* Set request to the sdkData of agIORequest */
757     agIORequest->sdkData = pRequest;
758 
759     /* save tag and IOrequest pointer to IOMap */
760     saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
761     saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
762 
763 #ifdef SA_LL_IBQ_PROTECT
764     ossaSingleThreadedEnter(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
765 #endif /* SA_LL_IBQ_PROTECT */
766 
767     /* Get a free inbound queue entry */
768 #ifdef LOOPBACK_MPI
769     if (loopback)
770     {
771       SA_DBG2(("saSSPStart: did %d ioq %d / %d tag %d\n", pDevice->DeviceMapIndex, inq, outq, pRequest->HTag));
772       circularOQ = &saRoot->outboundQueue[outq];
773       retVal = mpiMsgFreeGetOQ(circularOQ, size, &pMessage);
774     }
775     else
776 #endif /* LOOPBACK_MPI */
777     {
778       circularQ = &saRoot->inboundQueue[inq];
779       retVal = mpiMsgFreeGet(circularQ, size, &pMessage);
780     }
781 
782     /* if message size is too large return failure */
783     if (AGSA_RC_FAILURE == retVal)
784     {
785 #ifdef SA_LL_IBQ_PROTECT
786       ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
787 #endif /* SA_LL_IBQ_PROTECT */
788       /* if not sending return to free list rare */
789       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
790       saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode));
791       pRequest->valid = agFALSE;
792       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
793       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
794 
795       SA_DBG1(("saSSPStart, error when get free IOMB\n"));
796       smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "Sa");
797       ret = AGSA_RC_FAILURE;
798       goto ext;
799     }
800 
801     /* return busy if inbound queue is full */
802     if (AGSA_RC_BUSY == retVal)
803     {
804 #ifdef SA_LL_IBQ_PROTECT
805       ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
806 #endif /* SA_LL_IBQ_PROTECT */
807       /* if not sending return to free list rare */
808       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
809       saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode));
810       pRequest->valid = agFALSE;
811       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
812       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
813 
814       SA_DBG1(("saSSPStart, no more IOMB\n"));
815       smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "Sa");
816       ret = AGSA_RC_BUSY;
817       goto ext;
818     }
819     SA_DBG3(("saSSPStart:agRequestType %X\n" ,agRequestType));
820 
821     switch ( agRequestType )
822     {
823       case AGSA_SSP_INIT_READ:
824       case AGSA_SSP_INIT_WRITE:
825       case AGSA_SSP_INIT_NONDATA:
826       case AGSA_SSP_INIT_READ_EXT:
827       case AGSA_SSP_INIT_WRITE_EXT:
828       case AGSA_SSP_INIT_READ_M:
829       case AGSA_SSP_INIT_WRITE_M:
830       case AGSA_SSP_INIT_READ_EXT_M:
831       case AGSA_SSP_INIT_WRITE_EXT_M:
832       case AGSA_SSP_INIT_READ_INDIRECT:
833       case AGSA_SSP_INIT_WRITE_INDIRECT:
834       case AGSA_SSP_INIT_READ_INDIRECT_M:
835       case AGSA_SSP_INIT_WRITE_INDIRECT_M:
836       {
837         if (!(agRequestType & AGSA_SSP_EXT_BIT))
838         {
839           agsaSSPInitiatorRequest_t     *pIRequest = &(agRequestBody->sspInitiatorReq);
840           agsaSSPIniIOStartCmd_t        *pPayload = (agsaSSPIniIOStartCmd_t *)pMessage;
841           agsaSSPIniEncryptIOStartCmd_t *pEncryptPayload = (agsaSSPIniEncryptIOStartCmd_t *)pMessage;
842 
843           /* Most fields for the SAS IOMB have the same offset regardless of the actual IOMB used. */
844           /* Be careful with the scatter/gather lists, encryption and DIF options. */
845 
846 /*          if( pIRequest->sspCmdIU.cdb[ 0] ==  0x28 || pIRequest->sspCmdIU.cdb[0]== 0x2A)
847           {
848             pRequest->requestBlock = ((pIRequest->sspCmdIU.cdb[2] << 24 ) |
849                             (pIRequest->sspCmdIU.cdb[3] << 16 ) |
850                             (pIRequest->sspCmdIU.cdb[4] <<  8 ) |
851                             (pIRequest->sspCmdIU.cdb[5] ) );
852           }
853 */
854 #ifdef LOOPBACK_MPI
855           if (loopback)
856           {
857           OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPCompletionRsp_t, tag), pRequest->HTag);
858           OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPCompletionRsp_t, status), OSSA_IO_SUCCESS);
859           OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPCompletionRsp_t, param), 0);
860           //OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPCompletionRsp_t, SSPTag), 0);
861           }
862           else
863 #endif /* LOOPBACK_MPI */
864           {
865             /* SSPIU less equal 28 bytes */
866             /* Configure DWORD 1 */
867             OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniIOStartCmd_t, tag), pRequest->HTag);
868             /* Configure DWORD 2 */
869             OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniIOStartCmd_t, deviceId), pDevice->DeviceMapIndex);
870             /* Configure DWORD 3 */
871             OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniIOStartCmd_t, dataLen), pIRequest->dataLength);
872           }
873 
874 #ifdef SA_TESTBASE_EXTRA
875           /* TestBase - Set the host BST entry  */
876           DirDW4 |= ((UINT32)pIRequest->bstIndex) << 16;
877 #endif /*  SA_TESTBASE_EXTRA */
878 
879           if (!(agRequestType & AGSA_SSP_INDIRECT_BIT))
880           {
881             /* Configure DWORD 5-12  */
882             si_memcpy(&pPayload->SSPInfoUnit, &pIRequest->sspCmdIU, sizeof(pPayload->SSPInfoUnit));
883             pPayload->dirMTlr     = 0;
884             /* Mask DIR for Read/Write command */
885             /* Configure DWORD 4 bit 8-9 */
886             DirDW4 |= agRequestType & AGSA_DIR_MASK;
887           }
888           else /* AGSA_SSP_INDIRECT_BIT was set */
889           {
890 
891             agsaSSPInitiatorRequestIndirect_t *pIndRequest = &(agRequestBody->sspInitiatorReqIndirect);
892 
893             /* Configure DWORD 5 */
894             OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,sspiu_0_3_indcdbalL ),pIndRequest->sspInitiatorReqAddrLower32);
895             /* Configure DWORD 6 */
896             OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,sspiu_4_7_indcdbalH ),pIndRequest->sspInitiatorReqAddrUpper32 );
897             /* Configure DWORD 7 */
898             OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,sspiu_8_11 ), 0);
899             /* Configure DWORD 8 */
900             OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,sspiu_12_15 ), 0);
901             /* Configure DWORD 9 */
902             OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,sspiu_16_19 ), 0);
903             /* Configure DWORD 10 */
904             OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,sspiu_19_23), 0);
905             /* Configure DWORD 11 */
906             OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,sspiu_24_27 ), 0);
907             /* Mask DIR for Read/Write command */
908             /* Configure DWORD 4 bit 8-9 */
909             DirDW4 |= agRequestType & AGSA_DIR_MASK;
910             /* Configure DWORD 4 bit 24-31 */
911             DirDW4 |= ((pIndRequest->sspInitiatorReqLen >> 2) & 0xFF) << SHIFT24;
912             /* Configure DWORD 4 bit 4 */
913             DirDW4 |= 1 << SHIFT3;
914           }
915 
916           /* set TLR */
917           DirDW4 |= pIRequest->flag & TLR_MASK;
918           if (agRequestType & AGSA_MSG)
919           {
920             /* set M bit */
921             DirDW4 |= AGSA_MSG_BIT;
922           }
923 
924           /* check for skipmask operation */
925           if (pIRequest->flag & AGSA_SAS_ENABLE_SKIP_MASK)
926           {
927             DirDW4 |= AGSA_SKIP_MASK_BIT;
928             /* agsaSSPInitiatorRequestIndirect_t skip mask in flag is offset 5  */
929             DirDW4 |= (pIRequest->flag & AGSA_SAS_SKIP_MASK_OFFSET) << SHIFT8;
930           }
931 
932 
933          /* Configure DWORDS 12-14 */
934          if( pIRequest->encrypt.enableEncryptionPerLA && pIRequest->dif.enableDIFPerLA)
935          {
936             OSSA_WRITE_LE_32(agRoot, pPayload,                      /* DWORD 12 */
937                              OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,epl_descL ),
938                              pIRequest->encrypt.EncryptionPerLAAddrLo );
939             OSSA_WRITE_LE_32(agRoot, pPayload,                      /* DWORD 13 */
940                              OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,dpl_descL ),
941                              pIRequest->dif.DIFPerLAAddrLo );
942 
943             SA_ASSERT(pIRequest->encrypt.EncryptionPerLAAddrHi == pIRequest->dif.DIFPerLAAddrHi, "EPL DPL hi region must be equal");
944 
945             if( pIRequest->encrypt.EncryptionPerLAAddrHi != pIRequest->dif.DIFPerLAAddrHi )
946             {
947 
948               SA_DBG1(("saSSPStart: EPL DPL hi region must be equal AGSA_RC_FAILURE\n" ));
949               smTraceFuncExit(hpDBG_VERY_LOUD, 'e', "Sa");
950               ret = AGSA_RC_FAILURE;
951               goto ext;
952             }
953 
954             OSSA_WRITE_LE_32(agRoot, pPayload,                      /* DWORD 14 */
955                              OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,edpl_descH ),
956                              pIRequest->encrypt.EncryptionPerLAAddrHi );
957           }
958           else if( pIRequest->encrypt.enableEncryptionPerLA)
959           {
960             OSSA_WRITE_LE_32(agRoot, pPayload,                      /* DWORD 12 */
961                              OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,epl_descL ),
962                              pIRequest->encrypt.EncryptionPerLAAddrLo );
963             OSSA_WRITE_LE_32(agRoot, pPayload,                      /* DWORD 13 */
964                              OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,dpl_descL ),
965                              0);
966             OSSA_WRITE_LE_32(agRoot, pPayload,                      /* DWORD 14 */
967                              OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,edpl_descH ),
968                              pIRequest->encrypt.EncryptionPerLAAddrHi );
969           }
970           else if (pIRequest->dif.enableDIFPerLA) /* configure DIF */
971           {
972             OSSA_WRITE_LE_32(agRoot, pPayload,                      /* DWORD 12 */
973                              OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,epl_descL ),
974                              0);
975             OSSA_WRITE_LE_32(agRoot, pPayload,                      /* DWORD 13 */
976                              OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,dpl_descL ),
977                              pIRequest->dif.DIFPerLAAddrLo );
978             OSSA_WRITE_LE_32(agRoot, pPayload,                      /* DWORD 14 */
979                              OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,edpl_descH ),
980                              pIRequest->dif.DIFPerLAAddrHi);
981           }
982           else /* Not EPL or DPL  */
983           {
984             OSSA_WRITE_LE_32(agRoot, pPayload,                      /* DWORD 12 */
985                              OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,epl_descL ),
986                              0);
987             OSSA_WRITE_LE_32(agRoot, pPayload,                      /* DWORD 13 */
988                              OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,dpl_descL ),
989                              0);
990             OSSA_WRITE_LE_32(agRoot, pPayload,                      /* DWORD 14 */
991                              OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,edpl_descH ),
992                              0);
993           }
994 
995           if (pIRequest->flag & AGSA_SAS_ENABLE_DIF)
996           {
997             bit32 UDTR1_UDTR0_UDT1_UDT0  =  0;
998             bit32 UDT5_UDT4_UDT3_UDT2     = 0;
999             bit32 UDTR5_UDTR4_UDTR3_UDTR2 = 0;
1000 
1001             SA_DBG3(("saSSPStart,DIF enableRefBlockCount ref %d enableRefBlockCount  %d enableCrc  %d enableCrcInversion %d\n",
1002                 pIRequest->dif.flags & DIF_FLAG_BITS_UDTR_REF_BLKCOUNT ? 1 : 0,
1003                 pIRequest->dif.flags & DIF_FLAG_BITS_UDTR_REF_BLKCOUNT ? 1 : 0,
1004                 pIRequest->dif.flags & DIF_FLAG_BITS_CRC_VER           ? 1 : 0,
1005                 pIRequest->dif.flags & DIF_FLAG_BITS_CRC_INV           ? 1 : 0  ));
1006 
1007             SA_DBG3(("saSSPStart,DIF initialIOSeed %X lbSize %X difAction %X\n",
1008                 pIRequest->dif.flags & DIF_FLAG_BITS_CRC_SEED ? 1 : 0,
1009                 (pIRequest->dif.flags & DIF_FLAG_BITS_BLOCKSIZE_MASK) >> DIF_FLAG_BITS_BLOCKSIZE_SHIFT,
1010                 pIRequest->dif.flags & DIF_FLAG_BITS_ACTION  ));
1011 
1012             SA_DBG3(("saSSPStart,DIF udtArray %2X %2X %2X %2X %2X %2X\n",
1013                 pIRequest->dif.udtArray[0],
1014                 pIRequest->dif.udtArray[1],
1015                 pIRequest->dif.udtArray[2],
1016                 pIRequest->dif.udtArray[3],
1017                 pIRequest->dif.udtArray[4],
1018                 pIRequest->dif.udtArray[5]));
1019 
1020             SA_DBG3(("saSSPStart,DIF udrtArray %2X %2X %2X %2X %2X %2X\n",
1021                 pIRequest->dif.udrtArray[0],
1022                 pIRequest->dif.udrtArray[1],
1023                 pIRequest->dif.udrtArray[2],
1024                 pIRequest->dif.udrtArray[3],
1025                 pIRequest->dif.udrtArray[4],
1026                 pIRequest->dif.udrtArray[5]));
1027 
1028             SA_DBG3(("saSSPStart,DIF tagUpdateMask %X tagVerifyMask %X DIFPerLAAddrLo %X DIFPerLAAddrHi %X\n",
1029                 (pIRequest->dif.flags & DIF_FLAG_BITS_UDTVMASK) >> DIF_FLAG_BITS_UDTV_SHIFT,
1030                 (pIRequest->dif.flags & DIF_FLAG_BITS_UDTUPMASK) >> DIF_FLAG_BITS_UDTUPSHIFT,
1031                 pIRequest->dif.DIFPerLAAddrLo,
1032                 pIRequest->dif.DIFPerLAAddrHi));
1033 
1034             DirDW4 |= AGSA_DIF_BIT;
1035 
1036             /* DWORD 15 */
1037             SA_DBG3(("saSSPStart, DW 15 DIF_flags 0x%08X\n", pIRequest->dif.flags ));
1038 
1039             OSSA_WRITE_LE_32(agRoot, pPayload,
1040                                OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, DIF_flags),
1041                                pIRequest->dif.flags);
1042 
1043             /* Populate the UDT and UDTR bytes as necessary. */
1044             if ((pIRequest->dif.flags & DIF_FLAG_BITS_ACTION) != AGSA_DIF_INSERT)
1045             {
1046                 UDTR1_UDTR0_UDT1_UDT0 = (pIRequest->dif.udtArray[1] << SHIFT8 |
1047                                          pIRequest->dif.udtArray[0]);
1048                 UDT5_UDT4_UDT3_UDT2   = (pIRequest->dif.udtArray[5] << SHIFT24 |
1049                                          pIRequest->dif.udtArray[4] << SHIFT16 |
1050                                          pIRequest->dif.udtArray[3] << SHIFT8  |
1051                                          pIRequest->dif.udtArray[2]);
1052             }
1053 
1054             if ((pIRequest->dif.flags & DIF_FLAG_BITS_ACTION) == AGSA_DIF_INSERT ||
1055                 (pIRequest->dif.flags & DIF_FLAG_BITS_ACTION) == AGSA_DIF_VERIFY_REPLACE ||
1056                 (pIRequest->dif.flags & DIF_FLAG_BITS_ACTION) == AGSA_DIF_REPLACE_UDT_REPLACE_CRC)
1057             {
1058                 UDTR1_UDTR0_UDT1_UDT0 |= (pIRequest->dif.udrtArray[1] << SHIFT24 |
1059                                           pIRequest->dif.udrtArray[0] << SHIFT16 );
1060                 UDTR5_UDTR4_UDTR3_UDTR2 = (pIRequest->dif.udrtArray[5] << SHIFT24 |
1061                                            pIRequest->dif.udrtArray[4] << SHIFT16 |
1062                                            pIRequest->dif.udrtArray[3] << SHIFT8  |
1063                                            pIRequest->dif.udrtArray[2]);
1064             }
1065 
1066             /* DWORD 16 is UDT3, UDT2, UDT1 and UDT0 */
1067             OSSA_WRITE_LE_32(agRoot, pPayload,
1068                              OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, udt),
1069                              UDTR1_UDTR0_UDT1_UDT0);
1070 
1071             /* DWORD 17 is UDT5, UDT4, UDT3 and UDT2 */
1072             OSSA_WRITE_LE_32(agRoot, pPayload,
1073                              OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, udtReplacementLo),
1074                              UDT5_UDT4_UDT3_UDT2);
1075 
1076             /* DWORD 18 is UDTR5, UDTR4, UDTR3 and UDTR2 */
1077             OSSA_WRITE_LE_32(agRoot, pPayload,
1078                              OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, udtReplacementHi),
1079                              UDTR5_UDTR4_UDTR3_UDTR2);
1080 
1081             /* DWORD 19 */
1082             /* Get IOS IOSeed enable bit */
1083             if( pIRequest->dif.enableDIFPerLA ||
1084                (pIRequest->dif.flags & DIF_FLAG_BITS_CUST_APP_TAG) )
1085             {
1086                 OSSA_WRITE_LE_32(agRoot, pPayload,
1087                                  OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, DIF_seed),
1088                                 ((pIRequest->dif.DIFPerLARegion0SecCount << SHIFT16) |
1089                                  (pIRequest->dif.flags & DIF_FLAG_BITS_CRC_SEED ? pIRequest->dif.initialIOSeed : 0 )));
1090             }
1091             else
1092             {
1093               if (pIRequest->dif.flags & DIF_FLAG_BITS_CRC_SEED)
1094               {
1095                 OSSA_WRITE_LE_32(agRoot, pPayload,
1096                                  OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, DIF_seed),
1097                                  pIRequest->dif.initialIOSeed );
1098               }
1099               else
1100               {
1101                 OSSA_WRITE_LE_32(agRoot, pPayload,
1102                                  OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, DIF_seed),  0 );
1103               }
1104             }
1105           }
1106 
1107           /* configure encryption */
1108           if (pIRequest->flag & AGSA_SAS_ENABLE_ENCRYPTION)
1109           {
1110 
1111             SA_DBG3(("saSSPStart,ENC dekTable 0x%08X dekIndex 0x%08X\n",
1112                 pIRequest->encrypt.dekInfo.dekTable,
1113                 pIRequest->encrypt.dekInfo.dekIndex));
1114 
1115             SA_DBG3(("saSSPStart,ENC kekIndex 0x%08X sectorSizeIndex 0x%08X cipherMode 0x%08X\n",
1116                 pIRequest->encrypt.kekIndex,
1117                 pIRequest->encrypt.sectorSizeIndex,
1118                 pIRequest->encrypt.cipherMode));
1119 
1120             SA_DBG3(("saSSPStart,ENC keyTag_W0 0x%08X keyTag_W1 0x%08X\n",
1121                 pIRequest->encrypt.keyTag_W0,
1122                 pIRequest->encrypt.keyTag_W1));
1123             SA_DBG3(("saSSPStart,ENC tweakVal_W0 0x%08X tweakVal_W1 0x%08X\n",
1124                 pIRequest->encrypt.tweakVal_W0,
1125                 pIRequest->encrypt.tweakVal_W1));
1126             SA_DBG3(("saSSPStart,ENC tweakVal_W2 0x%08X tweakVal_W3 0x%08X\n",
1127                 pIRequest->encrypt.tweakVal_W2,
1128                 pIRequest->encrypt.tweakVal_W3));
1129 
1130               DirDW4 |= AGSA_ENCRYPT_BIT;
1131 
1132               encryptFlags = 0;
1133 
1134               if (pIRequest->encrypt.keyTagCheck == agTRUE)
1135               {
1136                  encryptFlags |= AGSA_ENCRYPT_KEY_TAG_BIT;
1137               }
1138 
1139               if( pIRequest->encrypt.cipherMode == agsaEncryptCipherModeXTS )
1140               {
1141                 encryptFlags |= AGSA_ENCRYPT_XTS_Mode << SHIFT4;
1142               }
1143 
1144               encryptFlags |= pIRequest->encrypt.dekInfo.dekTable << SHIFT2;
1145 
1146               /* Always use encryption for DIF fields, skip SKPD */
1147 
1148               encryptFlags |= (pIRequest->encrypt.dekInfo.dekIndex & 0xFFFFFF) << SHIFT8;
1149               /* Configure DWORD 20 */
1150               OSSA_WRITE_LE_32(agRoot, pPayload,
1151                                OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, encryptFlagsLo),
1152                                encryptFlags);
1153 
1154               encryptFlags = pIRequest->encrypt.sectorSizeIndex;
1155 
1156               encryptFlags |= (pIRequest->encrypt.kekIndex) << SHIFT5;
1157 
1158               encryptFlags |= (pIRequest->encrypt.EncryptionPerLRegion0SecCount) << SHIFT16;
1159               /* Configure DWORD 21 */
1160               OSSA_WRITE_LE_32(agRoot, pPayload,
1161                                OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, encryptFlagsHi),
1162                                encryptFlags);
1163 
1164               /* Configure DWORD 22 */
1165               OSSA_WRITE_LE_32(agRoot, pPayload,
1166                                OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, keyTag_W0),
1167                                pIRequest->encrypt.keyTag_W0);
1168               /* Configure DWORD 23 */
1169               OSSA_WRITE_LE_32(agRoot, pPayload,
1170                                OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, keyTag_W1),
1171                                pIRequest->encrypt.keyTag_W1);
1172 
1173               /* Configure DWORD 24 */
1174               OSSA_WRITE_LE_32(agRoot, pPayload,
1175                                OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, tweakVal_W0),
1176                                pIRequest->encrypt.tweakVal_W0);
1177               /* Configure DWORD 25 */
1178               OSSA_WRITE_LE_32(agRoot, pPayload,
1179                                OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, tweakVal_W1),
1180                                pIRequest->encrypt.tweakVal_W1);
1181               /* Configure DWORD 26 */
1182               OSSA_WRITE_LE_32(agRoot, pPayload,
1183                                OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, tweakVal_W2),
1184                                pIRequest->encrypt.tweakVal_W2);
1185               /* Configure DWORD 27 */
1186               OSSA_WRITE_LE_32(agRoot, pPayload,
1187                                OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, tweakVal_W3),
1188                                pIRequest->encrypt.tweakVal_W3);
1189           }
1190 
1191           /* Setup SGL */
1192           if (pIRequest->dataLength)
1193           {
1194             pSgl = &(pIRequest->agSgl);
1195 
1196             SA_DBG3(("saSSPStart:opCode %X agSgl %08x:%08x (%x/%x)\n",opCode,
1197                 pSgl->sgUpper, pSgl->sgLower, pSgl->len, pSgl->extReserved));
1198 
1199             /* Get DIF PER LA flag */
1200             DirDW4 |= (pIRequest->dif.enableDIFPerLA ? (1 << SHIFT7) : 0);
1201             DirDW4 |= (pIRequest->encrypt.enableEncryptionPerLA ? ( 1 << SHIFT12 ) : 0);
1202             /* Configure DWORD 4 */
1203             OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniIOStartCmd_t, dirMTlr), DirDW4);
1204 
1205             if (opCode == OPC_INB_SSP_DIF_ENC_OPSTART)
1206             {
1207               /* Configure DWORD 28 */
1208               pEncryptPayload->AddrLow0 = pSgl->sgLower;
1209               /* Configure DWORD 29 */
1210               pEncryptPayload->AddrHi0 = pSgl->sgUpper;
1211               /* Configure DWORD 30 */
1212               pEncryptPayload->Len0 = pSgl->len;
1213               /* Configure DWORD 31 */
1214               pEncryptPayload->E0 = pSgl->extReserved;
1215             }
1216             else
1217             {
1218               pPayload->AddrLow0 = pSgl->sgLower;
1219               pPayload->AddrHi0 = pSgl->sgUpper;
1220               pPayload->Len0 = pSgl->len;
1221               pPayload->E0 = pSgl->extReserved;
1222             }
1223           }
1224           else
1225           {
1226             /* no data transfer */
1227             /* Configure DWORD 4 */
1228             OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniIOStartCmd_t, dirMTlr), DirDW4);
1229 
1230             if (opCode == OPC_INB_SSP_DIF_ENC_OPSTART)
1231             {
1232                   pEncryptPayload = (agsaSSPIniEncryptIOStartCmd_t *) pPayload;
1233 
1234                   pEncryptPayload->AddrLow0 = 0;
1235                   pEncryptPayload->AddrHi0 = 0;
1236                   pEncryptPayload->Len0 = 0;
1237                   pEncryptPayload->E0 = 0;
1238             }
1239             else
1240             {
1241                 pPayload->AddrLow0 = 0;
1242                 pPayload->AddrHi0 = 0;
1243                 pPayload->Len0 = 0;
1244                 pPayload->E0 = 0;
1245             }
1246           }
1247 
1248           /* post the IOMB to SPC */
1249 #ifdef LOOPBACK_MPI
1250           if (loopback)
1251             ret = mpiMsgProduceOQ(circularOQ, (void *)pMessage, MPI_CATEGORY_SAS_SATA, OPC_OUB_SSP_COMP, outq, (bit8)circularQ->priority);
1252           else
1253 #endif /* LOOPBACK_MPI */
1254           ret = mpiMsgProduce(circularQ, (void *)pMessage, MPI_CATEGORY_SAS_SATA, opCode, outq, (bit8)circularQ->priority);
1255           if (AGSA_RC_FAILURE == ret)
1256           {
1257             SA_DBG1(("saSSPStart, error when post SSP IOMB\n"));
1258             ret = AGSA_RC_FAILURE;
1259           }
1260         }
1261         else
1262         {
1263           /* additionalCdbLen is not zero and type is Ext - use EXT mode */
1264           agsaSSPInitiatorRequestExt_t *pIRequest = &(agRequestBody->sspInitiatorReqExt);
1265           agsaSSPIniExtIOStartCmd_t *pPayload = (agsaSSPIniExtIOStartCmd_t *)pMessage;
1266           bit32 sspiul;
1267 
1268           /*
1269            * Most fields for the SAS IOMB have the same offset regardless of the actual IOMB used.
1270            * Be careful with the scatter/gather lists, encryption and DIF options.
1271            */
1272           /* CDB > 16 bytes */
1273           OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniExtIOStartCmd_t, tag), pRequest->HTag);
1274           OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniExtIOStartCmd_t, deviceId), pDevice->DeviceMapIndex);
1275           OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniExtIOStartCmd_t, dataLen), pIRequest->dataLength);
1276           /* dword (bit7-bit2) ==> bytes (bit7-bit0) */
1277           /* setup standard CDB bytes + additional CDB bytes in length field */
1278           sspiul = sizeof(agsaSSPCmdInfoUnit_t) +
1279                     (pIRequest->sspCmdIUExt.additionalCdbLen & 0xFC);
1280           DirDW4 = sspiul << 16;
1281           si_memcpy(&pPayload->SSPIu[0], &pIRequest->sspCmdIUExt, sspiul);
1282           pPayload->SSPIuLendirMTlr = 0;
1283 
1284           /* Mask DIR for Read/Write command */
1285           DirDW4 |= agRequestType & AGSA_DIR_MASK;
1286 
1287           /* set TLR */
1288           DirDW4 |= pIRequest->flag & TLR_MASK;
1289           if (agRequestType & AGSA_MSG)
1290           {
1291             /* set M bit */
1292             DirDW4 |= AGSA_MSG_BIT;
1293           }
1294 
1295           /* check for skipmask operation */
1296           if (pIRequest->flag & AGSA_SAS_ENABLE_SKIP_MASK)
1297           {
1298             SA_ASSERT(0, "Mode not supported");
1299           }
1300 
1301           /* configure DIF */
1302           if (pIRequest->flag & AGSA_SAS_ENABLE_DIF)
1303           {
1304             SA_ASSERT(0, "Mode not supported");
1305           }
1306 
1307           /* configure encryption */
1308           if (pIRequest->flag & AGSA_SAS_ENABLE_ENCRYPTION)
1309           {
1310             SA_ASSERT(0, "Mode not supported");
1311           }
1312           /* Setup SGL */
1313           if (pIRequest->dataLength)
1314           {
1315             pSgl = &(pIRequest->agSgl);
1316 
1317             SA_DBG3(("saSSPStart: Ext mode, agSgl %08x:%08x (%x/%x)\n",
1318               pSgl->sgUpper, pSgl->sgLower, pSgl->len, pSgl->extReserved));
1319 
1320             OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniExtIOStartCmd_t, SSPIuLendirMTlr), DirDW4);
1321 
1322              if (opCode == OPC_INB_SSP_DIF_ENC_OPSTART)
1323             {
1324                 si_memcpy((&((agsaSSPIniEncryptIOStartCmd_t *)(pPayload))->AddrLow0), pSgl, sizeof(agsaSgl_t));
1325             }
1326             else
1327             {
1328                 si_memcpy((&(pPayload->SSPIu[0]) + sspiul), pSgl, sizeof(agsaSgl_t));
1329             }
1330           }
1331           else
1332           {
1333             /* no data transfer */
1334             OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniExtIOStartCmd_t, SSPIuLendirMTlr), DirDW4);
1335             pPayload->dataLen = 0;
1336           }
1337 
1338           /* post the IOMB to SPC */
1339           if (AGSA_RC_FAILURE == mpiMsgProduce(circularQ, (void *)pMessage, MPI_CATEGORY_SAS_SATA, opCode, outq,(bit8)circularQ->priority ))
1340           {
1341             SA_DBG1(("saSSPStart, error when post SSP Ext IOMB\n"));
1342             ret = AGSA_RC_FAILURE;
1343           }
1344         }
1345         break;
1346       }
1347       case AGSA_SSP_TASK_MGNT_REQ:
1348       case AGSA_SSP_TASK_MGNT_REQ_M:
1349       {
1350         agsaIORequestDesc_t *pTMRequestToAbort = agNULL;
1351         agsaSSPIniTMStartCmd_t *pPayload = (agsaSSPIniTMStartCmd_t *)pMessage;
1352 
1353         if (agRequestType & AGSA_MSG)
1354         {
1355           /* set M bit */
1356           DirDW4 = AGSA_MSG_BIT;
1357         }
1358 
1359         /* set DS and ADS bit */
1360         DirDW4 |= (agRequestBody->sspTaskMgntReq.tmOption & 0x3) << 3;
1361 
1362         /* Prepare the SSP TASK Management payload */
1363         OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniTMStartCmd_t, tag), pRequest->HTag);
1364         OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniTMStartCmd_t, deviceId), pDevice->DeviceMapIndex);
1365         OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniTMStartCmd_t, relatedTag), agRequestBody->sspTaskMgntReq.tagOfTaskToBeManaged);
1366         OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniTMStartCmd_t, TMfunction), agRequestBody->sspTaskMgntReq.taskMgntFunction);
1367         OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniTMStartCmd_t, dsAdsMReport), DirDW4);
1368         pPayload->lun[0] = agRequestBody->sspTaskMgntReq.lun[0];
1369         pPayload->lun[1] = agRequestBody->sspTaskMgntReq.lun[1];
1370         pPayload->lun[2] = agRequestBody->sspTaskMgntReq.lun[2];
1371         pPayload->lun[3] = agRequestBody->sspTaskMgntReq.lun[3];
1372         pPayload->lun[4] = agRequestBody->sspTaskMgntReq.lun[4];
1373         pPayload->lun[5] = agRequestBody->sspTaskMgntReq.lun[5];
1374         pPayload->lun[6] = agRequestBody->sspTaskMgntReq.lun[6];
1375         pPayload->lun[7] = agRequestBody->sspTaskMgntReq.lun[7];
1376 
1377         if (agTMRequest)
1378         {
1379           pTMRequestToAbort = (agsaIORequestDesc_t *)agTMRequest->sdkData;
1380           if (pTMRequestToAbort)
1381           {
1382             OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniTMStartCmd_t, relatedTag), pTMRequestToAbort->HTag);
1383           }
1384         }
1385 
1386         SA_DBG1(("saSSPStart, HTAG 0x%x TM function 0x%x Tag-to-be-aborted 0x%x deviceId 0x%x\n",
1387                   pPayload->tag, pPayload->TMfunction, pPayload->relatedTag, pPayload->deviceId));
1388 
1389         siDumpActiveIORequests(agRoot, saRoot->swConfig.maxActiveIOs);
1390 
1391         /* post the IOMB to SPC */
1392         if (AGSA_RC_FAILURE == mpiMsgProduce(circularQ, (void *)pMessage, MPI_CATEGORY_SAS_SATA, OPC_INB_SSPINITMSTART, outq, (bit8)circularQ->priority))
1393         {
1394           SA_DBG1(("saSSPStart, error when post TM IOMB\n"));
1395           ret = AGSA_RC_FAILURE;
1396         }
1397 
1398         break;
1399       }
1400       case AGSA_SSP_TGT_READ_DATA:
1401       case AGSA_SSP_TGT_READ_GOOD_RESP:
1402       case AGSA_SSP_TGT_WRITE_DATA:
1403       case AGSA_SSP_TGT_WRITE_GOOD_RESP:
1404       {
1405         agsaSSPTargetRequest_t *pTRequest = &(agRequestBody->sspTargetReq);
1406         agsaSSPTgtIOStartCmd_t *pPayload = (agsaSSPTgtIOStartCmd_t *)pMessage;
1407         bit32 DirDW5 = 0;
1408         /* Prepare the SSP TGT IO Start payload */
1409         /* Configure DWORD 1 */
1410         OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, tag), pRequest->HTag);
1411         /* Configure DWORD 2 */
1412         OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, deviceId), pDevice->DeviceMapIndex);
1413         /* Configure DWORD 3 */
1414         OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, dataLen), pTRequest->dataLength);
1415         /* Configure DWORD 4 */
1416         OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, dataOffset), pTRequest->offset);
1417 
1418         SA_DBG3(("saSSPStart, sspOption %08X\n", pTRequest->sspOption ));
1419 
1420         /* Mask DIR and AutoGR bits for Read/Write command */
1421         DirDW5 = (agRequestType & (AGSA_DIR_MASK | AGSA_AUTO_MASK)) | (pTRequest->agTag << 16);
1422 
1423         if (pTRequest->sspOption & SSP_OPTION_DIF )
1424         {
1425           bit32 UDTR1_UDTR0_UDT1_UDT0   = 0;
1426           bit32 UDT5_UDT4_UDT3_UDT2     = 0;
1427           bit32 UDTR5_UDTR4_UDTR3_UDTR2 = 0;
1428           SA_DBG3(("saSSPStart,tgt DIF enableRefBlockCount ref %d enableRefBlockCount  %d enableCrc  %d enableCrcInversion %d\n",
1429               pTRequest->dif.flags & DIF_FLAG_BITS_UDTR_REF_BLKCOUNT ? 1 : 0,
1430               pTRequest->dif.flags & DIF_FLAG_BITS_UDTR_REF_BLKCOUNT ? 1 : 0,
1431               pTRequest->dif.flags & DIF_FLAG_BITS_CRC_VER           ? 1 : 0,
1432               pTRequest->dif.flags & DIF_FLAG_BITS_CRC_INV           ? 1 : 0  ));
1433 
1434           SA_DBG3(("saSSPStart,tgt DIF initialIOSeed %X lbSize %X difAction %X\n",
1435               pTRequest->dif.flags & DIF_FLAG_BITS_CRC_SEED ? 1 : 0,
1436               (pTRequest->dif.flags & DIF_FLAG_BITS_BLOCKSIZE_MASK ) >> DIF_FLAG_BITS_BLOCKSIZE_SHIFT,
1437               pTRequest->dif.flags & DIF_FLAG_BITS_ACTION  ));
1438 
1439           SA_DBG3(("saSSPStart,tgt DIF udtArray %2X %2X %2X %2X %2X %2X\n",
1440               pTRequest->dif.udtArray[0],
1441               pTRequest->dif.udtArray[1],
1442               pTRequest->dif.udtArray[2],
1443               pTRequest->dif.udtArray[3],
1444               pTRequest->dif.udtArray[4],
1445               pTRequest->dif.udtArray[5]));
1446 
1447           SA_DBG3(("saSSPStart,tgt DIF udrtArray %2X %2X %2X %2X %2X %2X\n",
1448               pTRequest->dif.udrtArray[0],
1449               pTRequest->dif.udrtArray[1],
1450               pTRequest->dif.udrtArray[2],
1451               pTRequest->dif.udrtArray[3],
1452               pTRequest->dif.udrtArray[4],
1453               pTRequest->dif.udrtArray[5]));
1454 
1455           SA_DBG3(("saSSPStart,tgt DIF tagUpdateMask %X tagVerifyMask %X DIFPerLAAddrLo %X DIFPerLAAddrHi %X\n",
1456               (pTRequest->dif.flags & DIF_FLAG_BITS_UDTVMASK) >> DIF_FLAG_BITS_UDTV_SHIFT,
1457               (pTRequest->dif.flags & DIF_FLAG_BITS_UDTUPMASK) >> DIF_FLAG_BITS_UDTUPSHIFT,
1458               pTRequest->dif.DIFPerLAAddrLo,
1459               pTRequest->dif.DIFPerLAAddrHi));
1460 
1461           DirDW5 |= AGSA_SSP_TGT_BITS_DEE_DIF;
1462 
1463 
1464           SA_DBG3(("saSSPStart,tgt  DW 15 DIF_flags 0x%08X\n", pTRequest->dif.flags ));
1465 
1466           OSSA_WRITE_LE_32(agRoot, pPayload,
1467                              OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, DIF_flags),
1468                              pTRequest->dif.flags);
1469 
1470             /* Populate the UDT and UDTR bytes as necessary. */
1471             if ((pTRequest->dif.flags & DIF_FLAG_BITS_ACTION) != AGSA_DIF_INSERT)
1472             {
1473                 UDTR1_UDTR0_UDT1_UDT0 = (pTRequest->dif.udtArray[1] << SHIFT8 |
1474                                          pTRequest->dif.udtArray[0]);
1475                 UDT5_UDT4_UDT3_UDT2   = (pTRequest->dif.udtArray[5] << SHIFT24 |
1476                                          pTRequest->dif.udtArray[4] << SHIFT16 |
1477                                          pTRequest->dif.udtArray[3] << SHIFT8  |
1478                                          pTRequest->dif.udtArray[2]);
1479             }
1480 
1481             if ((pTRequest->dif.flags & DIF_FLAG_BITS_ACTION) == AGSA_DIF_INSERT ||
1482                 (pTRequest->dif.flags & DIF_FLAG_BITS_ACTION) == AGSA_DIF_VERIFY_REPLACE ||
1483                 (pTRequest->dif.flags & DIF_FLAG_BITS_ACTION) == AGSA_DIF_REPLACE_UDT_REPLACE_CRC)
1484             {
1485                 UDTR1_UDTR0_UDT1_UDT0 |= (pTRequest->dif.udrtArray[1] << SHIFT24 |
1486                                           pTRequest->dif.udrtArray[0] << SHIFT16 );
1487                 UDTR5_UDTR4_UDTR3_UDTR2 = (pTRequest->dif.udrtArray[5] << SHIFT24 |
1488                                            pTRequest->dif.udrtArray[4] << SHIFT16 |
1489                                            pTRequest->dif.udrtArray[3] << SHIFT8  |
1490                                            pTRequest->dif.udrtArray[2]);
1491             }
1492           /* DWORD 8 is UDTR1, UDTR0, UDT1 and UDT0 */
1493           OSSA_WRITE_LE_32(agRoot, pPayload,
1494                            OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, udt),
1495                            UDTR1_UDTR0_UDT1_UDT0);
1496 
1497           /* DWORD 9 is UDT5, UDT4, UDT3 and UDT2 */
1498           OSSA_WRITE_LE_32(agRoot, pPayload,
1499                            OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, udtReplacementLo),
1500                            UDT5_UDT4_UDT3_UDT2);
1501 
1502           /* DWORD 10 is UDTR5, UDTR4, UDTR3 and UDTR2 */
1503           OSSA_WRITE_LE_32(agRoot, pPayload,
1504                            OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, udtReplacementHi),
1505                            UDTR5_UDTR4_UDTR3_UDTR2);
1506           /* DWORD 11 */
1507           /* Get IOS IOSeed enable bit */
1508           if( pTRequest->dif.flags & DIF_FLAG_BITS_CUST_APP_TAG)
1509           {
1510               OSSA_WRITE_LE_32(agRoot, pPayload,
1511                                OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, DIF_seed),
1512                                ((pTRequest->dif.DIFPerLARegion0SecCount << SHIFT16) |
1513                                (pTRequest->dif.flags & DIF_FLAG_BITS_CRC_SEED ? pTRequest->dif.initialIOSeed : 0 )));
1514           }
1515           else
1516           {
1517               /* Get IOS IOSeed enable bit */
1518               if (pTRequest->dif.flags & DIF_FLAG_BITS_CRC_SEED)
1519               {
1520                   OSSA_WRITE_LE_32(agRoot, pPayload,
1521                                    OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, DIF_seed),
1522                                    pTRequest->dif.initialIOSeed );
1523               }
1524               else
1525               {
1526                   OSSA_WRITE_LE_32(agRoot, pPayload,
1527                                    OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, DIF_seed),  0 );
1528               }
1529           }
1530         }
1531 
1532         /* Mask DIR and AutoGR bits for Read/Write command */
1533         if(pTRequest->sspOption & SSP_OPTION_AUTO_GOOD_RESPONSE)
1534         {
1535           DirDW5 |= AGSA_SSP_TGT_BITS_AGR;
1536         }
1537 
1538         /* AN, RTE, RDF bits */
1539         DirDW5 |= (pTRequest->sspOption & SSP_OPTION_BITS) << 2;
1540 
1541         /* ODS */
1542         if(pTRequest->sspOption & SSP_OPTION_ODS)
1543         {
1544           DirDW5 |= AGSA_SSP_TGT_BITS_ODS;
1545         }
1546 
1547         /* Setup SGL */
1548         if (pTRequest->dataLength)
1549         {
1550           pSgl = &(pTRequest->agSgl);
1551 
1552           SA_DBG5(("saSSPStart: agSgl %08x:%08x (%x/%x)\n",
1553           pSgl->sgUpper, pSgl->sgLower, pSgl->len, pSgl->extReserved));
1554 
1555           /* set up dir on the payload */
1556           /* Configure DWORD 5 */
1557           OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, INITagAgrDir), DirDW5);
1558 
1559           pPayload->AddrLow0 = pSgl->sgLower;
1560           pPayload->AddrHi0 = pSgl->sgUpper;
1561           pPayload->Len0 = pSgl->len;
1562           pPayload->E0 = pSgl->extReserved;
1563         }
1564         else
1565         {
1566           /* no data transfer */
1567           /* Configure DWORD 5 */
1568           OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, INITagAgrDir), DirDW5);
1569           pPayload->AddrLow0 = 0;
1570           pPayload->AddrHi0 = 0;
1571           pPayload->Len0 = 0;
1572         }
1573         /* Configure DWORD 6 */
1574         OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t,reserved ), 0);
1575 
1576         /* Build TGT IO START command and send it to SPC */
1577         if (AGSA_RC_FAILURE == mpiMsgProduce(circularQ, (void *)pMessage, MPI_CATEGORY_SAS_SATA, OPC_INB_SSPTGTIOSTART, outq, (bit8)circularQ->priority))
1578         {
1579           SA_DBG1(("saSSPStart, error when post TGT IOMB\n"));
1580           ret = AGSA_RC_FAILURE;
1581         }
1582 
1583         break;
1584       }
1585       case AGSA_SSP_TGT_CMD_OR_TASK_RSP:
1586       {
1587         agsaSSPTargetResponse_t *pTResponse = &(agRequestBody->sspTargetResponse);
1588         agsaSSPTgtRspStartCmd_t *pPayload = (agsaSSPTgtRspStartCmd_t *)pMessage;
1589         bit32 ip, an, ods;
1590 
1591         if (pTResponse->frameBuf && (pTResponse->respBufLength <= AGSA_MAX_SSPPAYLOAD_VIA_SFO))
1592         {
1593           ip = 1;
1594           si_memcpy(pPayload->reserved, pTResponse->frameBuf, pTResponse->respBufLength);
1595         }
1596         else
1597         {
1598           ip = 0;
1599           /* NOTE:
1600            * 1. reserved field must be ZEROED out. FW depends on it
1601            * 2. trusted interface. indirect response buffer must be valid.
1602            */
1603           si_memset(pPayload->reserved, 0, sizeof(pPayload->reserved));
1604           OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtRspStartCmd_t, AddrLow0), pTResponse->respBufLower);
1605           OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtRspStartCmd_t, AddrHi0), pTResponse->respBufUpper);
1606           OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtRspStartCmd_t, Len0), pTResponse->respBufLength);
1607           OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtRspStartCmd_t, E0), 0);
1608         }
1609 
1610         /* TLR setting */
1611         an = (pTResponse->respOption & RESP_OPTION_BITS);
1612         /* ODS */
1613         ods = (pTResponse->respOption & RESP_OPTION_ODS);
1614 
1615         /* Prepare the SSP TGT RESPONSE Start payload */
1616         OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtRspStartCmd_t, tag), pRequest->HTag);
1617         OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtRspStartCmd_t, deviceId), pDevice->DeviceMapIndex);
1618         OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtRspStartCmd_t, RspLen), pTResponse->respBufLength);
1619         OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtRspStartCmd_t, INITag_IP_AN),
1620           (pTResponse->agTag << SHIFT16) | ods | (ip << SHIFT10) | (an << SHIFT2));
1621 
1622         /* Build TGT RESPONSE START command and send it to SPC */
1623         if (AGSA_RC_FAILURE == mpiMsgProduce(circularQ, (void *)pMessage, MPI_CATEGORY_SAS_SATA, OPC_INB_SSPTGTRSPSTART, outq, (bit8)circularQ->priority))
1624         {
1625           SA_DBG1(("saSSPStart, error when post TGT RSP IOMB\n"));
1626           ret = AGSA_RC_FAILURE;
1627         }
1628 
1629         break;
1630       }
1631       default:
1632       {
1633         SA_DBG1(("saSSPStart, Unsupported Request IOMB\n"));
1634         ret = AGSA_RC_FAILURE;
1635         break;
1636       }
1637     }
1638 
1639   } /* LL IOrequest available */
1640 
1641 #ifdef SA_LL_IBQ_PROTECT
1642   ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
1643 #endif /* SA_LL_IBQ_PROTECT */
1644 
1645 #ifdef SALL_API_TEST
1646   if (ret == AGSA_RC_SUCCESS)
1647     saRoot->LLCounters.IOCounter.numSSPStarted++;
1648 #endif /*SALL_API_TEST  */
1649 
1650 #ifdef LOOPBACK_MPI
1651   if (loopback)
1652     saRoot->interruptVecIndexBitMap[0] |= (1 << outq);
1653 #endif /* LOOPBACK_MPI */
1654   /* goto have leave and trace point info */
1655   smTraceFuncExit(hpDBG_VERY_LOUD, 'f', "Sa");
1656 ext:
1657 
1658   OSSA_INP_LEAVE(agRoot);
1659   return ret;
1660 }
1661 
1662 /******************************************************************************/
1663 /*! \brief Abort SSP request
1664  *
1665  *  Abort SSP request
1666  *
1667  *  \param agRoot handles for this instance of SAS/SATA LLL
1668  *  \param queueNum
1669  *  \param agIORequest
1670  *  \param agIOToBeAborted
1671  *
1672  *  \return If request is aborted successfully
1673  *          - \e AGSA_RC_SUCCESS request is aborted successfully
1674  *          - \e AGSA_RC_FAILURE request is not aborted successfully
1675  */
1676 /*******************************************************************************/
1677 GLOBAL bit32 saSSPAbort(
1678   agsaRoot_t        *agRoot,
1679   agsaIORequest_t   *agIORequest,
1680   bit32             queueNum,
1681   agsaDevHandle_t   *agDevHandle,
1682   bit32             flag,
1683   void              *abortParam,
1684   ossaGenericAbortCB_t  agCB
1685   )
1686 {
1687   bit32 ret = AGSA_RC_SUCCESS, retVal;
1688   agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
1689   agsaIORequestDesc_t *pRequest;
1690   agsaIORequestDesc_t *pRequestABT = NULL;
1691   agsaDeviceDesc_t    *pDevice = NULL;
1692   agsaDeviceDesc_t    *pDeviceABT = NULL;
1693   agsaPort_t          *pPort = NULL;
1694   mpiICQueue_t        *circularQ;
1695   void                *pMessage;
1696   agsaSSPAbortCmd_t   *payload;
1697   agsaIORequest_t     *agIOToBeAborted;
1698   bit8                inq, outq;
1699   bit32               using_reserved = agFALSE;
1700   bit32               flag_copy = flag;
1701   smTraceFuncEnter(hpDBG_VERY_LOUD,"Sb");
1702 
1703   /* sanity check */
1704   SA_ASSERT((agNULL != agRoot), "");
1705   SA_ASSERT((agNULL != agIORequest), "");
1706 
1707   SA_DBG2(("saSSPAbort: agIORequest %p agDevHandle %p abortParam %p flag 0x%x\n", agIORequest,agDevHandle,abortParam,flag));
1708 
1709   /* Assign inbound and outbound Buffer */
1710   inq = (bit8)(queueNum & MPI_IB_NUM_MASK);
1711   outq = (bit8)((queueNum & MPI_OB_NUM_MASK) >> MPI_OB_SHIFT);
1712   SA_ASSERT((AGSA_MAX_INBOUND_Q > inq), "The IBQ Number is out of range.");
1713 
1714 #ifdef SA_PRINTOUT_IN_WINDBG
1715 #ifndef DBG
1716         DbgPrint("saSSPAbort flag %d\n", flag );
1717 #endif /* DBG  */
1718 #endif /* SA_PRINTOUT_IN_WINDBG  */
1719 
1720   if( ABORT_SINGLE == (flag & ABORT_MASK) )
1721   {
1722     agIOToBeAborted = (agsaIORequest_t *)abortParam;
1723     /* Get LL IORequest entry for saSSPAbort() */
1724     pRequest = (agsaIORequestDesc_t *) (agIOToBeAborted->sdkData);
1725     if (agNULL == pRequest)
1726     {
1727       /* no pRequest found - can not Abort */
1728       SA_DBG1(("saSSPAbort: ABORT_ALL no pRequest\n"));
1729       smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Sb");
1730       return AGSA_RC_FAILURE;
1731     }
1732     /* Find the device the request sent to */
1733     pDevice = pRequest->pDevice;
1734     /* Get LL IORequest entry for IOToBeAborted */
1735     pRequestABT = (agsaIORequestDesc_t *) (agIOToBeAborted->sdkData);
1736     if (agNULL == pRequestABT)
1737     {
1738       /* The IO to Be Abort is no longer exist */
1739       SA_DBG1(("saSSPAbort: ABORT_ALL no pRequestABT\n"));
1740       smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "Sb");
1741       return AGSA_RC_FAILURE;
1742     }
1743     /* Find the device the request Abort to */
1744     pDeviceABT = pRequestABT->pDevice;
1745 
1746     if (agNULL == pDeviceABT)
1747     {
1748       /* no deviceID - can not build IOMB */
1749       SA_DBG1(("saSSPAbort: ABORT_ALL no pRequestABT->deviceID\n"));
1750       smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "Sb");
1751       return AGSA_RC_FAILURE;
1752     }
1753 
1754     if (agNULL != pDevice)
1755     {
1756       /* Find the port the request was sent to */
1757       pPort = pDevice->pPort;
1758     }
1759     else
1760     {
1761       /* no deviceID - can not build IOMB */
1762       SA_DBG1(("saSSPAbort: ABORT_ALL no deviceID\n"));
1763       smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "Sb");
1764       return AGSA_RC_FAILURE;
1765     }
1766 
1767     /* Get request from free IORequests */
1768     ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1769     pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests)); /**/
1770   }
1771   else
1772   {
1773     if (ABORT_ALL == (flag & ABORT_MASK))
1774     {
1775       /* abort All with Device or Port */
1776       /* Find the outgoing port for the device */
1777       if (agDevHandle == agNULL)
1778       {
1779         /* no deviceID - can not build IOMB */
1780         SA_DBG1(("saSSPAbort: agDevHandle == agNULL!!!\n"));
1781         return AGSA_RC_FAILURE;
1782       }
1783       pDevice = (agsaDeviceDesc_t *) (agDevHandle->sdkData);
1784       if (agNULL == pDevice)
1785       {
1786         /* no deviceID - can not build IOMB */
1787         SA_DBG1(("saSSPAbort: ABORT_ALL agNULL == pDevice\n"));
1788         return AGSA_RC_FAILURE;
1789       }
1790       pPort = pDevice->pPort;
1791       ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1792       pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests)); /**/
1793     }
1794     else
1795     {
1796       /* only support 00, 01 and 02 for flag */
1797       SA_DBG1(("saSSPAbort: ABORT_ALL type not supported 0x%X\n",flag));
1798       smTraceFuncExit(hpDBG_VERY_LOUD, 'e', "Sb");
1799       return AGSA_RC_FAILURE;
1800     }
1801   }
1802 
1803   if ( agNULL == pRequest )
1804   {
1805     pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeReservedRequests));
1806     if(agNULL != pRequest)
1807     {
1808       using_reserved = agTRUE;
1809       SA_DBG2(("saSSPAbort: using saRoot->freeReservedRequests\n"));
1810     }
1811     else
1812     {
1813       ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1814       /* If no LL IO request entry available */
1815       SA_DBG1(("saSSPAbort: No request from free list Not using saRoot->freeReservedRequests\n"));
1816       smTraceFuncExit(hpDBG_VERY_LOUD, 'f', "Sb");
1817       return AGSA_RC_BUSY;
1818     }
1819   }
1820 
1821   /* If free IOMB avaliable */
1822   /* Remove the request from free list */
1823   if( using_reserved )
1824   {
1825     saLlistIORemove(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
1826   }
1827   else
1828   {
1829     saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
1830   }
1831 
1832   /* Add the request to the pendingIORequests list of the device */
1833   pRequest->valid = agTRUE;
1834   saLlistIOAdd(&(pDevice->pendingIORequests), &(pRequest->linkNode));
1835 
1836   ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1837 
1838   /* set up pRequest */
1839   pRequest->pIORequestContext = agIORequest;
1840   pRequest->requestType = AGSA_SSP_REQTYPE;
1841   pRequest->pDevice = pDevice;
1842   pRequest->pPort = pPort;
1843   pRequest->completionCB = (void*)agCB;
1844 /*  pRequest->abortCompletionCB = agCB;*/
1845   pRequest->startTick = saRoot->timeTick;
1846 
1847   /* Set request to the sdkData of agIORequest */
1848   agIORequest->sdkData = pRequest;
1849 
1850   /* save tag and IOrequest pointer to IOMap */
1851   saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
1852   saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
1853 
1854 
1855 #ifdef SA_LL_IBQ_PROTECT
1856   ossaSingleThreadedEnter(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
1857 #endif /* SA_LL_IBQ_PROTECT */
1858 
1859   /* If LL IO request entry avaliable */
1860   /* Get a free inbound queue entry */
1861   circularQ = &saRoot->inboundQueue[inq];
1862   retVal    = mpiMsgFreeGet(circularQ, IOMB_SIZE64, &pMessage);
1863 
1864   /* if message size is too large return failure */
1865   if (AGSA_RC_FAILURE == retVal)
1866   {
1867 #ifdef SA_LL_IBQ_PROTECT
1868     ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
1869 #endif /* SA_LL_IBQ_PROTECT */
1870 
1871     ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1872     saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode));
1873     pRequest->valid = agFALSE;
1874     if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
1875     {
1876       SA_DBG1(("saSSPAbort: saving pRequest (%p) for later use\n", pRequest));
1877       saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
1878     }
1879     else
1880     {
1881       /* return the request to free pool */
1882       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
1883     }
1884     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1885 
1886     SA_DBG1(("saSSPAbort: error when get free IOMB\n"));
1887 
1888     smTraceFuncExit(hpDBG_VERY_LOUD, 'g', "Sb");
1889     return AGSA_RC_FAILURE;
1890   }
1891 
1892   /* return busy if inbound queue is full */
1893   if (AGSA_RC_BUSY == retVal)
1894   {
1895 #ifdef SA_LL_IBQ_PROTECT
1896     ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
1897 #endif /* SA_LL_IBQ_PROTECT */
1898 
1899     ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1900     saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode));
1901     pRequest->valid = agFALSE;
1902     if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
1903     {
1904       SA_DBG1(("saSSPAbort: saving pRequest (%p) for later use\n", pRequest));
1905       saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
1906     }
1907     else
1908     {
1909       /* return the request to free pool */
1910       saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
1911     }
1912     ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1913 
1914     SA_DBG1(("saSSPAbort: no more IOMB\n"));
1915     smTraceFuncExit(hpDBG_VERY_LOUD, 'h', "Sb");
1916     return AGSA_RC_BUSY;
1917   }
1918 
1919   /* setup payload */
1920   payload = (agsaSSPAbortCmd_t*)pMessage;
1921   OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSSPAbortCmd_t, tag), pRequest->HTag);
1922 
1923   if( ABORT_SINGLE == (flag & ABORT_MASK) )
1924   {
1925     if ( agNULL == pDeviceABT )
1926     {
1927       SA_DBG1(("saSSPSAbort: no device\n" ));
1928       smTraceFuncExit(hpDBG_VERY_LOUD, 'i', "Sb");
1929       return AGSA_RC_FAILURE;
1930     }
1931     OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSSPAbortCmd_t, deviceId), pDeviceABT->DeviceMapIndex);
1932     OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSSPAbortCmd_t, HTagAbort), pRequestABT->HTag);
1933   }
1934   else
1935   {
1936     /* abort all */
1937     OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSSPAbortCmd_t, deviceId), pDevice->DeviceMapIndex);
1938     OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSSPAbortCmd_t, HTagAbort), 0);
1939   }
1940 
1941   if(flag & ABORT_TSDK_QUARANTINE)
1942   {
1943     if(smIS_SPCV(agRoot))
1944     {
1945       flag_copy &= ABORT_SCOPE;
1946       flag_copy |= ABORT_QUARANTINE_SPCV;
1947     }
1948   }
1949   OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSSPAbortCmd_t, abortAll), flag_copy);
1950 
1951   SA_DBG1(("saSSPAbort: HTag 0x%x HTagABT 0x%x deviceId 0x%x flag 0x%x\n", payload->tag, payload->HTagAbort, payload->deviceId,flag));
1952 
1953   siCountActiveIORequestsOnDevice( agRoot,   payload->deviceId );
1954 
1955   /* post the IOMB to SPC */
1956   ret = mpiMsgProduce(circularQ, (void *)pMessage, MPI_CATEGORY_SAS_SATA, OPC_INB_SSP_ABORT, outq, (bit8)circularQ->priority);
1957 
1958 #ifdef SA_LL_IBQ_PROTECT
1959   ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
1960 #endif /* SA_LL_IBQ_PROTECT */
1961 
1962 #ifdef SALL_API_TEST
1963   if (AGSA_RC_SUCCESS == ret)
1964   {
1965     saRoot->LLCounters.IOCounter.numSSPAborted++;
1966   }
1967 #endif
1968 
1969   smTraceFuncExit(hpDBG_VERY_LOUD, 'j', "Sb");
1970 
1971   return ret;
1972 }
1973 
1974 
1975 #if defined(SALLSDK_DEBUG)
1976 /******************************************************************************/
1977 /*! \brief
1978  *
1979  *  Dump StartSSP information
1980  *
1981  *  Debug helper routine
1982  *
1983  *  \return -none -
1984  */
1985 /*******************************************************************************/
1986 LOCAL void siDumpSSPStartIu(
1987   agsaDevHandle_t       *agDevHandle,
1988   bit32                 agRequestType,
1989   agsaSASRequestBody_t  *agRequestBody
1990   )
1991  {
1992   switch ( agRequestType )
1993   {
1994     case AGSA_SSP_INIT_READ:
1995     case AGSA_SSP_INIT_WRITE:
1996     {
1997       agsaSSPInitiatorRequest_t *pIRequest = &(agRequestBody->sspInitiatorReq);
1998 
1999       SA_DBG5(("siDumpSSPStartIu: dev=%p - %s - len=%x - attr=%x - CDB:%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
2000         agDevHandle,
2001         (agRequestType==AGSA_SSP_INIT_READ)? "AGSA_SSP_INIT_READ" : "AGSA_SSP_INIT_WRITE",
2002         pIRequest->dataLength,
2003         pIRequest->sspCmdIU.efb_tp_taskAttribute,
2004         pIRequest->sspCmdIU.cdb[0],
2005         pIRequest->sspCmdIU.cdb[1],
2006         pIRequest->sspCmdIU.cdb[2],
2007         pIRequest->sspCmdIU.cdb[3],
2008         pIRequest->sspCmdIU.cdb[4],
2009         pIRequest->sspCmdIU.cdb[5],
2010         pIRequest->sspCmdIU.cdb[6],
2011         pIRequest->sspCmdIU.cdb[7],
2012         pIRequest->sspCmdIU.cdb[8],
2013         pIRequest->sspCmdIU.cdb[9]
2014         ));
2015       break;
2016     }
2017 
2018     case  AGSA_SSP_INIT_READ_EXT:
2019     case  AGSA_SSP_INIT_WRITE_EXT:
2020     {
2021       agsaSSPInitiatorRequestExt_t *pIRequest = &(agRequestBody->sspInitiatorReqExt);
2022 
2023       SA_DBG3(("siDumpSSPStartIu: dev=%p - %s - len=%x - attr=%x - CDB:%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
2024         agDevHandle,
2025         (agRequestType==AGSA_SSP_INIT_READ_EXT)? "AGSA_SSP_INIT_READ_EXT" : "AGSA_SSP_INIT_WRITE_EXT",
2026         pIRequest->dataLength,
2027         pIRequest->sspCmdIUExt.efb_tp_taskAttribute,
2028         pIRequest->sspCmdIUExt.cdb[0],
2029         pIRequest->sspCmdIUExt.cdb[1],
2030         pIRequest->sspCmdIUExt.cdb[2],
2031         pIRequest->sspCmdIUExt.cdb[3],
2032         pIRequest->sspCmdIUExt.cdb[4],
2033         pIRequest->sspCmdIUExt.cdb[5],
2034         pIRequest->sspCmdIUExt.cdb[6],
2035         pIRequest->sspCmdIUExt.cdb[7],
2036         pIRequest->sspCmdIUExt.cdb[8],
2037         pIRequest->sspCmdIUExt.cdb[9]
2038         ));
2039       break;
2040     }
2041 
2042     case  AGSA_SSP_INIT_READ_EXT_M:
2043     case  AGSA_SSP_INIT_WRITE_EXT_M:
2044     {
2045       agsaSSPInitiatorRequestExt_t *pIRequest = &(agRequestBody->sspInitiatorReqExt);
2046 
2047       SA_DBG3(("siDumpSSPStartIu: dev=%p - %s - len=%x - attr=%x - CDB:%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
2048         agDevHandle,
2049         (agRequestType==AGSA_SSP_INIT_READ_EXT_M)? "AGSA_SSP_INIT_READ_EXT_M" : "AGSA_SSP_INIT_WRITE_EXT_M",
2050         pIRequest->dataLength,
2051         pIRequest->sspCmdIUExt.efb_tp_taskAttribute,
2052         pIRequest->sspCmdIUExt.cdb[0],
2053         pIRequest->sspCmdIUExt.cdb[1],
2054         pIRequest->sspCmdIUExt.cdb[2],
2055         pIRequest->sspCmdIUExt.cdb[3],
2056         pIRequest->sspCmdIUExt.cdb[4],
2057         pIRequest->sspCmdIUExt.cdb[5],
2058         pIRequest->sspCmdIUExt.cdb[6],
2059         pIRequest->sspCmdIUExt.cdb[7],
2060         pIRequest->sspCmdIUExt.cdb[8],
2061         pIRequest->sspCmdIUExt.cdb[9]
2062         ));
2063       break;
2064     }
2065 
2066     case  AGSA_SSP_INIT_READ_INDIRECT:
2067     case  AGSA_SSP_INIT_WRITE_INDIRECT:
2068     case  AGSA_SSP_INIT_READ_INDIRECT_M:
2069     case  AGSA_SSP_INIT_WRITE_INDIRECT_M:
2070     {
2071      agsaSSPInitiatorRequestIndirect_t *pIRequest = &(agRequestBody->sspInitiatorReqIndirect);
2072 
2073       SA_DBG3(("siDumpSSPStartIu: dev=%p - %s - len=%x - cdblen=%d CDB:U %08x L %08x\n",
2074         agDevHandle,
2075         (agRequestType==AGSA_SSP_INIT_READ_INDIRECT ||
2076          agRequestType==AGSA_SSP_INIT_READ_INDIRECT_M) ? "AGSA_SSP_INIT_READ_INDIRECT" : "AGSA_SSP_INIT_WRITE_INDIRECT",
2077         pIRequest->dataLength,
2078         pIRequest->sspInitiatorReqLen,
2079         pIRequest->sspInitiatorReqAddrUpper32,
2080         pIRequest->sspInitiatorReqAddrLower32 ));
2081       break;
2082     }
2083 
2084 
2085     case AGSA_SSP_TASK_MGNT_REQ:
2086     {
2087       agsaSSPScsiTaskMgntReq_t  *pTaskCmd =&agRequestBody->sspTaskMgntReq;
2088       /* copy payload */
2089 
2090       SA_DBG5(("siDumpSSPStartIu: dev=%p - %s - Task Function=%x - Tag to managed=%x",
2091         agDevHandle,
2092         "AGSA_SSP_TASK_MGNT_REQ",
2093         pTaskCmd->taskMgntFunction,
2094         pTaskCmd->tagOfTaskToBeManaged
2095         ));
2096       break;
2097     }
2098     case AGSA_SSP_TGT_READ_DATA:
2099     {
2100       agsaSSPTargetRequest_t *pTRequest = &(agRequestBody->sspTargetReq);
2101 
2102       SA_DBG5(("siDumpSSPStartIu: dev=%p - %s - dmaSize=%x dmaOffset=%x\n",
2103                   agDevHandle,
2104                   "AGSA_SSP_TGT_READ_DATA",
2105                   pTRequest->dataLength,
2106                   pTRequest->offset ));
2107       break;
2108     }
2109     case AGSA_SSP_TGT_READ_GOOD_RESP:
2110     {
2111       agsaSSPTargetRequest_t *pTRequest = &(agRequestBody->sspTargetReq);
2112 
2113       SA_DBG5(("siDumpSSPStartIu: dev=%p - %s - dmaSize=%x dmaOffset=%x\n",
2114                   agDevHandle,
2115                   "AGSA_SSP_TGT_READ_GOOD_RESP",
2116                   pTRequest->dataLength,
2117                   pTRequest->offset));
2118       break;
2119     }
2120     case AGSA_SSP_TGT_WRITE_GOOD_RESP:
2121     {
2122       agsaSSPTargetRequest_t  *pTRequest = &(agRequestBody->sspTargetReq);
2123       SA_DBG5(("siDumpSSPStartIu: dev=%p - %s - dmaSize=%x dmaOffset=%x\n",
2124                   agDevHandle,
2125                   "AGSA_SSP_TGT_WRITE_GOOD_RESP",
2126                   pTRequest->dataLength,
2127                   pTRequest->offset ));
2128 
2129       break;
2130     }
2131     case AGSA_SSP_TGT_WRITE_DATA:
2132     {
2133       agsaSSPTargetRequest_t  *pTRequest = &(agRequestBody->sspTargetReq);
2134 
2135       SA_DBG5(("siDumpSSPStartIu: dev=%p - %s - dmaSize=%x dmaOffset=%x\n",
2136         agDevHandle,
2137         "AGSA_SSP_TGT_WRITE_DATA",
2138         pTRequest->dataLength,
2139         pTRequest->offset ));
2140       break;
2141     }
2142     case AGSA_SSP_TGT_CMD_OR_TASK_RSP:
2143     {
2144       agsaSSPTargetResponse_t *pTResponse = &(agRequestBody->sspTargetResponse);
2145 
2146       SA_DBG5(("siDumpSSPStartIu: dev=%p - %s - len=%x PAddr=%08x:%08x  Tag=%x\n",
2147         agDevHandle,
2148         "AGSA_SSP_TGT_CMD_OR_TASK_RSP",
2149         pTResponse->respBufLength,
2150         pTResponse->respBufUpper,
2151         pTResponse->respBufLower,
2152         pTResponse->agTag  ));
2153       break;
2154     }
2155 
2156     default:
2157     {
2158       SA_DBG1(("siDumpSSPStartIu: dev=%p - %s %X\n",
2159         agDevHandle,
2160         "Unknown SSP cmd type",
2161         agRequestType
2162         ));
2163       break;
2164     }
2165   }
2166   return;
2167 }
2168 #endif /* SALLSDK_DEBUG */
2169