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
42extern int loopback;
43#endif
44
45#ifdef SALLSDK_DEBUG
46LOCAL void siDumpSSPStartIu(
47  agsaDevHandle_t       *agDevHandle,
48  bit32                 agRequestType,
49  agsaSASRequestBody_t  *agRequestBody
50  );
51#endif
52
53#ifdef FAST_IO_TEST
54LOCAL 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
66LOCAL 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
79osLOCAL void*
80siFastSSPReqAlloc(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
105LOCAL void
106siFastSSPReqFree(
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
134LOCAL 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
208ext:
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
222GLOBAL 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
276GLOBAL 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
521ext:
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
531GLOBAL 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/******************************************************************************/
580GLOBAL 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");
1657ext:
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/*******************************************************************************/
1678GLOBAL 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/*******************************************************************************/
1987LOCAL 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