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