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