1285242Sachim/*******************************************************************************
2285242Sachim**
3285242Sachim*Copyright (c) 2014 PMC-Sierra, Inc.  All rights reserved.
4285242Sachim*
5285242Sachim*Redistribution and use in source and binary forms, with or without modification, are permitted provided
6285242Sachim*that the following conditions are met:
7285242Sachim*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
8285242Sachim*following disclaimer.
9285242Sachim*2. Redistributions in binary form must reproduce the above copyright notice,
10285242Sachim*this list of conditions and the following disclaimer in the documentation and/or other materials provided
11285242Sachim*with the distribution.
12285242Sachim*
13285242Sachim*THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
14285242Sachim*WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
15285242Sachim*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
16285242Sachim*FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
17285242Sachim*NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
18285242Sachim*BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
19285242Sachim*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
20285242Sachim*SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
21285242Sachim
22285242Sachim********************************************************************************/
23285242Sachim/*******************************************************************************/
24285242Sachim/*! \file sassp.c
25285242Sachim *  \brief The file implements the functions for SSP request/response
26285242Sachim *
27285242Sachim */
28285242Sachim/*******************************************************************************/
29285242Sachim#include <sys/cdefs.h>
30285242Sachim__FBSDID("$FreeBSD$");
31285242Sachim#include <dev/pms/config.h>
32285242Sachim
33285242Sachim#include <dev/pms/RefTisa/sallsdk/spc/saglobal.h>
34285242Sachim#ifdef SA_ENABLE_TRACE_FUNCTIONS
35285242Sachim#ifdef siTraceFileID
36285242Sachim#undef siTraceFileID
37285242Sachim#endif
38285242Sachim#define siTraceFileID 'O'
39285242Sachim#endif
40285242Sachim
41285242Sachim#ifdef LOOPBACK_MPI
42285242Sachimextern int loopback;
43285242Sachim#endif
44285242Sachim
45285242Sachim#ifdef SALLSDK_DEBUG
46285242SachimLOCAL void siDumpSSPStartIu(
47285242Sachim  agsaDevHandle_t       *agDevHandle,
48285242Sachim  bit32                 agRequestType,
49285242Sachim  agsaSASRequestBody_t  *agRequestBody
50285242Sachim  );
51285242Sachim#endif
52285242Sachim
53285242Sachim#ifdef FAST_IO_TEST
54285242SachimLOCAL bit32 saGetIBQPI(agsaRoot_t *agRoot,
55285242Sachim                       bit32 queueNum)
56285242Sachim{
57285242Sachim  bit8         inq;
58285242Sachim  mpiICQueue_t *circularQ;
59285242Sachim  agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
60285242Sachim
61285242Sachim  inq = INQ(queueNum);
62285242Sachim  circularQ = &saRoot->inboundQueue[inq];
63285242Sachim  return circularQ->producerIdx;
64285242Sachim}
65285242Sachim
66285242SachimLOCAL void saSetIBQPI(agsaRoot_t *agRoot,
67285242Sachim                      bit32      queueNum,
68285242Sachim                      bit32      pi)
69285242Sachim{
70285242Sachim  bit8         inq;
71285242Sachim  mpiICQueue_t *circularQ;
72285242Sachim  agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
73285242Sachim
74285242Sachim  inq = INQ(queueNum);
75285242Sachim  circularQ = &saRoot->inboundQueue[inq];
76285242Sachim  circularQ->producerIdx = pi;
77285242Sachim}
78285242Sachim
79285242SachimosLOCAL void*
80285242SachimsiFastSSPReqAlloc(agsaRoot_t *agRoot)
81285242Sachim{
82285242Sachim  int             idx;
83285242Sachim  agsaLLRoot_t    *saRoot = (agsaLLRoot_t*)(agRoot->sdkData);
84285242Sachim  saFastRequest_t *fr;
85285242Sachim
86285242Sachim  if (!saRoot->freeFastIdx)
87285242Sachim  {
88285242Sachim    SA_DBG1(("saSuperSSPReqAlloc: no memory ERROR\n"));
89285242Sachim    SA_ASSERT((0), "");
90285242Sachim    return 0;
91285242Sachim  }
92285242Sachim
93285242Sachim  ossaSingleThreadedEnter(agRoot, LL_FAST_IO_LOCK);
94285242Sachim  saRoot->freeFastIdx--;
95285242Sachim  idx = saRoot->freeFastIdx;
96285242Sachim  ossaSingleThreadedLeave(agRoot, LL_FAST_IO_LOCK);
97285242Sachim
98285242Sachim  fr = saRoot->freeFastReq[idx];
99285242Sachim  SA_ASSERT((fr), "");
100285242Sachim  fr->valid = 1;
101285242Sachim
102285242Sachim  return fr;
103285242Sachim}
104285242Sachim
105285242SachimLOCAL void
106285242SachimsiFastSSPReqFree(
107285242Sachim             agsaRoot_t *agRoot,
108285242Sachim             void       *freq)
109285242Sachim{
110285242Sachim  agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
111285242Sachim  saFastRequest_t *fr = (saFastRequest_t*)freq;
112285242Sachim
113285242Sachim  SA_DBG2(("siFastSSPReqFree: enter\n"));
114285242Sachim  SA_ASSERT((fr->valid), "");
115285242Sachim  if (saRoot->freeFastIdx >= sizeof(saRoot->freeFastReq) /
116285242Sachim                             sizeof(saRoot->freeFastReq[0]))
117285242Sachim  {
118285242Sachim    SA_DBG1(("siFastSSPReqFree: too many handles %d / %d ERROR\n",
119285242Sachim             saRoot->freeFastIdx, (int)(sizeof(saRoot->freeFastReq) /
120285242Sachim             sizeof(saRoot->freeFastReq[0]))));
121285242Sachim    SA_ASSERT((0), "");
122285242Sachim    return;
123285242Sachim  }
124285242Sachim  ossaSingleThreadedEnter(agRoot, LL_FAST_IO_LOCK);
125285242Sachim  /* not need if only one entry */
126285242Sachim  /* saRoot->freeFastReq[saRoot->freeFastIdx] = freq;  */
127285242Sachim  saRoot->freeFastIdx++;
128285242Sachim  ossaSingleThreadedLeave(agRoot, LL_FAST_IO_LOCK);
129285242Sachim
130285242Sachim  fr->valid = 0;
131285242Sachim  SA_DBG6(("siFastSSPReqFree: leave\n"));
132285242Sachim}
133285242Sachim
134285242SachimLOCAL bit32 siFastSSPResAlloc(
135285242Sachim  agsaRoot_t             *agRoot,
136285242Sachim  bit32                  queueNum,
137285242Sachim  bit32                  agRequestType,
138285242Sachim  agsaDeviceDesc_t       *pDevice,
139285242Sachim  agsaIORequestDesc_t    **pRequest,
140285242Sachim  void                   **pPayload
141285242Sachim  )
142285242Sachim{
143285242Sachim  agsaLLRoot_t *saRoot = (agsaLLRoot_t*)(agRoot->sdkData);
144285242Sachim  mpiICQueue_t *circularQ;
145285242Sachim  bit8  inq;
146285242Sachim  bit16 size = IOMB_SIZE64;
147285242Sachim  bit32 ret = AGSA_RC_SUCCESS, retVal;
148285242Sachim
149285242Sachim  smTraceFuncEnter(hpDBG_VERY_LOUD,"2D");
150285242Sachim
151285242Sachim  SA_DBG4(("Entering function siFastSSPResAlloc:\n"));
152285242Sachim
153285242Sachim  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
154285242Sachim  *pRequest = (agsaIORequestDesc_t*)saLlistIOGetHead(&saRoot->freeIORequests);
155285242Sachim
156285242Sachim  /* If no LL IO request entry available */
157285242Sachim  if (agNULL == *pRequest )
158285242Sachim  {
159285242Sachim    ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
160285242Sachim    SA_DBG1(("siFastSSPResAlloc: No request from free list\n" ));
161285242Sachim    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2D");
162285242Sachim    ret = AGSA_RC_BUSY;
163285242Sachim    goto ext;
164285242Sachim  }
165285242Sachim
166285242Sachim  /* Get IO request from free IORequests */
167285242Sachim  /* Assign inbound and outbound Buffer */
168285242Sachim  inq = INQ(queueNum);
169285242Sachim  SA_ASSERT((AGSA_MAX_INBOUND_Q > inq), "The IBQ Number is out of range.");
170285242Sachim
171285242Sachim  /* SSP_INI_IO_START_EXT IOMB need at least 80 bytes to support 32 CDB */
172285242Sachim  if (agRequestType & AGSA_SSP_EXT_BIT)
173285242Sachim  {
174285242Sachim    size = IOMB_SIZE96;
175285242Sachim  }
176285242Sachim  /* If LL IO request entry avaliable */
177285242Sachim  /* Get a free inbound queue entry */
178285242Sachim  circularQ = &saRoot->inboundQueue[inq];
179285242Sachim  retVal = mpiMsgFreeGet(circularQ, size, pPayload);
180285242Sachim
181285242Sachim  /* if message size is too large return failure */
182285242Sachim  if (AGSA_RC_SUCCESS != retVal)
183285242Sachim  {
184285242Sachim    if (AGSA_RC_FAILURE == retVal)
185285242Sachim    {
186285242Sachim      SA_DBG1(("siFastSSPResAlloc: error when get free IOMB\n"));
187285242Sachim      smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2D");
188285242Sachim    }
189285242Sachim
190285242Sachim    /* return busy if inbound queue is full */
191285242Sachim    if (AGSA_RC_BUSY == retVal)
192285242Sachim    {
193285242Sachim      SA_DBG3(("siFastSSPResAlloc: no more IOMB\n"));
194285242Sachim      smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "2D");
195285242Sachim    }
196285242Sachim    ret = retVal;
197285242Sachim    goto ext;
198285242Sachim  }
199285242Sachim
200285242Sachim  /* But add it to the pending queue during FastStart */
201285242Sachim  /* If free IOMB avaliable */
202285242Sachim  /* Remove the request from free list */
203285242Sachim  saLlistIORemove(&saRoot->freeIORequests, &(*pRequest)->linkNode);
204285242Sachim
205285242Sachim  /* Add the request to the pendingIORequests list of the device */
206285242Sachim  saLlistIOAdd(&pDevice->pendingIORequests, &(*pRequest)->linkNode);
207285242Sachim
208285242Sachimext:
209285242Sachim  ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
210285242Sachim
211285242Sachim  if (AGSA_RC_SUCCESS == ret)
212285242Sachim  {
213285242Sachim    /* save tag and IOrequest pointer to IOMap */
214285242Sachim    saRoot->IOMap[(*pRequest)->HTag].Tag = (*pRequest)->HTag;
215285242Sachim    saRoot->IOMap[(*pRequest)->HTag].IORequest = (void *)*pRequest;
216285242Sachim  }
217285242Sachim
218285242Sachim  return ret;
219285242Sachim} /* siFastSSPResAlloc */
220285242Sachim
221285242Sachim
222285242SachimGLOBAL bit32 saFastSSPCancel(void *ioHandle)
223285242Sachim{
224285242Sachim  agsaRoot_t      *agRoot;
225285242Sachim  agsaLLRoot_t    *saRoot;
226285242Sachim  saFastRequest_t *fr;
227285242Sachim  bit32            i;
228285242Sachim  agsaIORequestDesc_t *ior;
229285242Sachim
230285242Sachim  SA_ASSERT((ioHandle), "");
231285242Sachim  fr = (saFastRequest_t*)ioHandle;
232285242Sachim  SA_ASSERT((fr->valid), "");
233285242Sachim  agRoot = (agsaRoot_t*)fr->agRoot;
234285242Sachim  SA_ASSERT((agRoot), "");
235285242Sachim  saRoot = (agsaLLRoot_t*)(agRoot->sdkData);
236285242Sachim  SA_ASSERT((saRoot), "");
237285242Sachim
238285242Sachim  smTraceFuncEnter(hpDBG_VERY_LOUD,"2E");
239285242Sachim
240285242Sachim  /* rollback the previously set IBQ PI */
241285242Sachim  for (i = 0; i < fr->inqMax - 1; i++)
242285242Sachim    saSetIBQPI(agRoot, fr->inqList[i], fr->beforePI[fr->inqList[i]]);
243285242Sachim
244285242Sachim  /* free all the previous Fast IO Requests */
245285242Sachim  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
246285242Sachim  /* at least one entry, no need to check for NULL saLlistIOGetHead() */
247285242Sachim  ior = (agsaIORequestDesc_t*)((char*)saLlistIOGetHead(&fr->requests) -
248285242Sachim                              OSSA_OFFSET_OF(agsaIORequestDesc_t, fastLink));
249285242Sachim  do
250285242Sachim  {
251285242Sachim    agsaDeviceDesc_t *pDevice;
252285242Sachim    void             *tmp;
253285242Sachim
254285242Sachim    pDevice = ior->pDevice;
255285242Sachim    saLlistIORemove(&pDevice->pendingIORequests, &ior->linkNode);
256285242Sachim    saLlistIOAdd(&saRoot->freeIORequests, &ior->linkNode);
257285242Sachim
258285242Sachim    tmp = (void*)saLlistGetNext(&fr->requests, &ior->fastLink);
259285242Sachim    if (!tmp)
260285242Sachim    {
261285242Sachim      break; /* end of list */
262285242Sachim    }
263285242Sachim    ior = (agsaIORequestDesc_t*)((char*)tmp -
264285242Sachim                                 OSSA_OFFSET_OF(agsaIORequestDesc_t, fastLink));
265285242Sachim  } while (1);
266285242Sachim
267285242Sachim  ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
268285242Sachim
269285242Sachim  /* free the IBQ PI tracking struct */
270285242Sachim  siFastSSPReqFree(agRoot, fr);
271285242Sachim
272285242Sachim  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2E");
273285242Sachim  return AGSA_RC_SUCCESS;
274285242Sachim} /* saFastSSPCancel */
275285242Sachim
276285242SachimGLOBAL void *saFastSSPPrepare(
277285242Sachim                 void                 *ioh,
278285242Sachim                 agsaFastCommand_t    *fc,
279285242Sachim                 ossaSSPCompletedCB_t cb,
280285242Sachim                 void                 *cbArg)
281285242Sachim{
282285242Sachim  bit32            ret = AGSA_RC_SUCCESS;
283285242Sachim  agsaRoot_t       *agRoot;
284285242Sachim  agsaLLRoot_t     *saRoot;
285285242Sachim  mpiICQueue_t     *circularQ;
286285242Sachim  agsaDeviceDesc_t *pDevice;
287285242Sachim  agsaSgl_t        *pSgl;
288285242Sachim  bit32            Dir = 0;
289285242Sachim  bit8             inq, outq;
290285242Sachim  saFastRequest_t  *fr;
291285242Sachim  void             *pMessage;
292285242Sachim  agsaIORequestDesc_t *pRequest;
293285242Sachim  bit16            opCode;
294285242Sachim  bitptr           offsetTag;
295285242Sachim  bitptr           offsetDeviceId;
296285242Sachim  bitptr           offsetDataLen;
297285242Sachim  bitptr           offsetDir;
298285242Sachim
299285242Sachim  agRoot = (agsaRoot_t*)fc->agRoot;
300285242Sachim  smTraceFuncEnter(hpDBG_VERY_LOUD,"2G");
301285242Sachim
302285242Sachim  OSSA_INP_ENTER(agRoot);
303285242Sachim
304285242Sachim  saRoot = (agsaLLRoot_t*)(agRoot->sdkData);
305285242Sachim  /* sanity check */
306285242Sachim  SA_ASSERT((agNULL != saRoot), "");
307285242Sachim
308285242Sachim  SA_DBG4(("Entering function saFastSSPPrepare:\n"));
309285242Sachim
310285242Sachim  fr = (saFastRequest_t*)ioh;
311285242Sachim  if (!fr)
312285242Sachim  {
313285242Sachim    int i;
314285242Sachim    fr = siFastSSPReqAlloc(agRoot);
315285242Sachim    if (!fr)
316285242Sachim    {
317285242Sachim      SA_ASSERT((0), "");
318285242Sachim      goto ext;
319285242Sachim    }
320285242Sachim
321285242Sachim    saLlistIOInitialize(&fr->requests);
322285242Sachim    for (i = 0; i < AGSA_MAX_INBOUND_Q; i++)
323285242Sachim      fr->beforePI[i] = (bit32)-1;
324285242Sachim
325285242Sachim    fr->inqMax = 0;
326285242Sachim    fr->agRoot = agRoot;
327285242Sachim    ioh = fr;
328285242Sachim  }
329285242Sachim
330285242Sachim  /* Find the outgoing port for the device */
331285242Sachim  pDevice = (agsaDeviceDesc_t*)(((agsaDevHandle_t*)fc->devHandle)->sdkData);
332285242Sachim
333285242Sachim  ret = siFastSSPResAlloc(agRoot, fc->queueNum, fc->agRequestType,
334285242Sachim                          pDevice, &pRequest, &pMessage);
335285242Sachim  if (ret != AGSA_RC_SUCCESS)
336285242Sachim  {
337285242Sachim    SA_ASSERT((0), "");
338285242Sachim    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2G");
339285242Sachim    goto ext;
340285242Sachim  }
341285242Sachim
342285242Sachim  /* Assign inbound and outbound Buffer */
343285242Sachim  inq = INQ(fc->queueNum);
344285242Sachim  outq = OUQ(fc->queueNum);
345285242Sachim  circularQ = &saRoot->inboundQueue[inq];
346285242Sachim
347285242Sachim  SA_DBG3(("saFastSSPPrepare: deviceId %d\n", pDevice->DeviceMapIndex));
348285242Sachim
349285242Sachim  /* set up pRequest */
350285242Sachim  pRequest->valid = agTRUE;
351285242Sachim  pRequest->pDevice = pDevice;
352285242Sachim  pRequest->requestType = fc->agRequestType;
353285242Sachim
354285242Sachim  pRequest->completionCB = cb;
355285242Sachim  pRequest->pIORequestContext = (agsaIORequest_t*)cbArg;
356285242Sachim
357285242Sachim  pSgl = fc->agSgl;
358285242Sachim
359285242Sachim  switch (fc->agRequestType)
360285242Sachim  {
361285242Sachim    /* case AGSA_SSP_INIT_NONDATA: */
362285242Sachim    case AGSA_SSP_INIT_READ:
363285242Sachim    case AGSA_SSP_INIT_WRITE:
364285242Sachim    case AGSA_SSP_INIT_READ_M:
365285242Sachim    case AGSA_SSP_INIT_WRITE_M:
366285242Sachim    {
367285242Sachim      agsaSSPIniIOStartCmd_t *pPayload = (agsaSSPIniIOStartCmd_t *)pMessage;
368285242Sachim      agsaSSPCmdInfoUnit_t   *piu;
369285242Sachim
370285242Sachim      /* SSPIU less equal 28 bytes */
371285242Sachim      offsetTag = OSSA_OFFSET_OF(agsaSSPIniIOStartCmd_t, tag);
372285242Sachim      offsetDeviceId = OSSA_OFFSET_OF(agsaSSPIniIOStartCmd_t, deviceId);
373285242Sachim      offsetDataLen = OSSA_OFFSET_OF(agsaSSPIniIOStartCmd_t, dataLen);
374285242Sachim      offsetDir = OSSA_OFFSET_OF(agsaSSPIniIOStartCmd_t, dirMTlr);
375285242Sachim
376285242Sachim      piu = &pPayload->SSPInfoUnit;
377285242Sachim
378285242Sachim      si_memcpy(piu->lun, fc->lun, sizeof(piu->lun));
379285242Sachim      si_memcpy(piu->cdb, fc->cdb, sizeof(piu->cdb));
380285242Sachim      piu->efb_tp_taskAttribute = fc->taskAttribute;
381285242Sachim      piu->additionalCdbLen = fc->additionalCdbLen;
382285242Sachim
383285242Sachim      /* Mask DIR for Read/Write command */
384285242Sachim      Dir = fc->agRequestType & AGSA_DIR_MASK;
385285242Sachim
386285242Sachim      /* set TLR */
387285242Sachim      Dir |= fc->flag & TLR_MASK;
388285242Sachim      if (fc->agRequestType & AGSA_MSG)
389285242Sachim      {
390285242Sachim        /* set M bit */
391285242Sachim        Dir |= AGSA_MSG_BIT;
392285242Sachim      }
393285242Sachim
394285242Sachim      /* Setup SGL */
395285242Sachim      if (fc->dataLength)
396285242Sachim      {
397285242Sachim        SA_DBG5(("saFastSSPPrepare: agSgl %08x:%08x (%x/%x)\n",
398285242Sachim                 pSgl->sgUpper, pSgl->sgLower, pSgl->len, pSgl->extReserved));
399285242Sachim        /*
400285242Sachim        pPayload->AddrLow0 = pSgl->sgLower;
401285242Sachim        pPayload->AddrHi0 = pSgl->sgUpper;
402285242Sachim        pPayload->Len0 = pSgl->len;
403285242Sachim        pPayload->E0 = pSgl->extReserved;
404285242Sachim        */
405285242Sachim        si_memcpy(&pPayload->AddrLow0, pSgl, sizeof(*pSgl));
406285242Sachim      }
407285242Sachim      else
408285242Sachim      {
409285242Sachim        /* no data transfer */
410285242Sachim        si_memset(&pPayload->AddrLow0, 0, sizeof(*pSgl));
411285242Sachim      }
412285242Sachim
413285242Sachim      opCode = OPC_INB_SSPINIIOSTART;
414285242Sachim      break;
415285242Sachim    }
416285242Sachim
417285242Sachim    case AGSA_SSP_INIT_READ_EXT:
418285242Sachim    case AGSA_SSP_INIT_WRITE_EXT:
419285242Sachim    case AGSA_SSP_INIT_READ_EXT_M:
420285242Sachim    case AGSA_SSP_INIT_WRITE_EXT_M:
421285242Sachim    {
422285242Sachim      agsaSSPIniExtIOStartCmd_t *pPayload =
423285242Sachim                                    (agsaSSPIniExtIOStartCmd_t *)pMessage;
424285242Sachim      agsaSSPCmdInfoUnitExt_t   *piu;
425285242Sachim      bit32 sspiul;
426285242Sachim
427285242Sachim      /* CDB > 16 bytes */
428285242Sachim      offsetTag = OSSA_OFFSET_OF(agsaSSPIniExtIOStartCmd_t, tag);
429285242Sachim      offsetDeviceId = OSSA_OFFSET_OF(agsaSSPIniExtIOStartCmd_t, deviceId);
430285242Sachim      offsetDataLen = OSSA_OFFSET_OF(agsaSSPIniExtIOStartCmd_t, dataLen);
431285242Sachim      offsetDir = OSSA_OFFSET_OF(agsaSSPIniExtIOStartCmd_t, SSPIuLendirMTlr);
432285242Sachim
433285242Sachim      /* dword (bit7-bit2) ==> bytes (bit7-bit0) */
434285242Sachim      /* setup standard CDB bytes + additional CDB bytes in length field */
435285242Sachim      sspiul = sizeof(agsaSSPCmdInfoUnit_t) + (fc->additionalCdbLen & 0xFC);
436285242Sachim
437285242Sachim      Dir = sspiul << 16;
438285242Sachim      piu = (agsaSSPCmdInfoUnitExt_t*)pPayload->SSPIu;
439285242Sachim
440285242Sachim      si_memcpy(piu->lun, fc->lun, sizeof(piu->lun));
441285242Sachim      si_memcpy(piu->cdb, fc->cdb, MIN(sizeof(piu->cdb),
442285242Sachim                                       16 + fc->additionalCdbLen));
443285242Sachim      piu->efb_tp_taskAttribute = fc->taskAttribute;
444285242Sachim      piu->additionalCdbLen = fc->additionalCdbLen;
445285242Sachim
446285242Sachim      /* Mask DIR for Read/Write command */
447285242Sachim      Dir |= fc->agRequestType & AGSA_DIR_MASK;
448285242Sachim
449285242Sachim      /* set TLR */
450285242Sachim      Dir |= fc->flag & TLR_MASK;
451285242Sachim      if (fc->agRequestType & AGSA_MSG)
452285242Sachim      {
453285242Sachim        /* set M bit */
454285242Sachim        Dir |= AGSA_MSG_BIT;
455285242Sachim      }
456285242Sachim
457285242Sachim      /* Setup SGL */
458285242Sachim      if (fc->dataLength)
459285242Sachim      {
460285242Sachim        SA_DBG5(("saSuperSSPSend: Ext mode, agSgl %08x:%08x (%x/%x)\n",
461285242Sachim          pSgl->sgUpper, pSgl->sgLower, pSgl->len, pSgl->extReserved));
462285242Sachim
463285242Sachim        si_memcpy((&(pPayload->SSPIu[0]) + sspiul), pSgl, sizeof(*pSgl));
464285242Sachim      }
465285242Sachim      else //?
466285242Sachim      {
467285242Sachim        /* no data transfer */
468285242Sachim        //pPayload->dataLen = 0;
469285242Sachim        si_memset((&(pPayload->SSPIu[0]) + sspiul), 0, sizeof(*pSgl));
470285242Sachim      }
471285242Sachim      SA_ASSERT((smIS_SPC(agRoot)), "smIS_SPC");
472285242Sachim      opCode = OPC_INB_SSPINIEXTIOSTART;
473285242Sachim      break;
474285242Sachim    }
475285242Sachim
476285242Sachim    default:
477285242Sachim    {
478285242Sachim      SA_DBG1(("saSuperSSPSend: Unsupported Request IOMB\n"));
479285242Sachim      ret = AGSA_RC_FAILURE;
480285242Sachim      SA_ASSERT((0), "");
481285242Sachim      smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2G");
482285242Sachim      goto ext;
483285242Sachim    }
484285242Sachim  }
485285242Sachim
486285242Sachim  OSSA_WRITE_LE_32(agRoot, pMessage, offsetTag, pRequest->HTag);
487285242Sachim  OSSA_WRITE_LE_32(agRoot, pMessage, offsetDeviceId, pDevice->DeviceMapIndex);
488285242Sachim  OSSA_WRITE_LE_32(agRoot, pMessage, offsetDataLen, fc->dataLength);
489285242Sachim  OSSA_WRITE_LE_32(agRoot, pMessage, offsetDir, Dir);
490285242Sachim
491285242Sachim  if (fr->beforePI[inq] == -1)
492285242Sachim  {
493285242Sachim    /* save the new IBQ' PI */
494285242Sachim    fr->beforePI[inq] = saGetIBQPI(agRoot, inq);
495285242Sachim    fr->inqList[fr->inqMax++] = inq;
496285242Sachim  }
497285242Sachim
498285242Sachim  /* post the IOMB to SPC */
499285242Sachim  ret = mpiMsgPrepare(circularQ, (void *)pMessage, MPI_CATEGORY_SAS_SATA,
500285242Sachim                      opCode, outq, 0);
501285242Sachim  if (AGSA_RC_SUCCESS != ret)
502285242Sachim  {
503285242Sachim    SA_ASSERT((0), "");
504285242Sachim    ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
505285242Sachim    /* Remove the request from pendingIORequests list */
506285242Sachim    saLlistIORemove(&pDevice->pendingIORequests, &pRequest->linkNode);
507285242Sachim
508285242Sachim    /* Add the request to the free list of the device */
509285242Sachim    saLlistIOAdd(&saRoot->freeIORequests, &pRequest->linkNode);
510285242Sachim    ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
511285242Sachim
512285242Sachim    SA_DBG1(("saFastSSPPrepare: error when post SSP IOMB\n"));
513285242Sachim    smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "2G");
514285242Sachim    goto ext;
515285242Sachim  }
516285242Sachim
517285242Sachim  /* Add the request to the pendingFastIORequests list of the device */
518285242Sachim  saLlistIOAdd(&fr->requests, &pRequest->fastLink);
519285242Sachim  smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "2G");
520285242Sachim
521285242Sachimext:
522285242Sachim  if (fr && ret != AGSA_RC_SUCCESS)
523285242Sachim  {
524285242Sachim    saFastSSPCancel(fr);
525285242Sachim    ioh = 0;
526285242Sachim  }
527285242Sachim  OSSA_INP_LEAVE(agRoot);
528285242Sachim  return ioh;
529285242Sachim} /* saFastSSPPrepare */
530285242Sachim
531285242SachimGLOBAL bit32 saFastSSPSend(void *ioHandle)
532285242Sachim{
533285242Sachim  bit8            inq;
534285242Sachim  agsaRoot_t      *agRoot;
535285242Sachim  agsaLLRoot_t    *saRoot;
536285242Sachim  saFastRequest_t *fr;
537285242Sachim  bit32           i;
538285242Sachim
539285242Sachim  SA_ASSERT((ioHandle), "");
540285242Sachim  fr = (saFastRequest_t*)ioHandle;
541285242Sachim  agRoot = (agsaRoot_t*)fr->agRoot;
542285242Sachim  SA_ASSERT((agRoot), "");
543285242Sachim  saRoot = (agsaLLRoot_t*)agRoot->sdkData;
544285242Sachim  SA_ASSERT((saRoot), "");
545285242Sachim
546285242Sachim  SA_DBG4(("Entering function saFastSSPSend:\n"));
547285242Sachim
548285242Sachim  for (i = 0; i < fr->inqMax; i++)
549285242Sachim  {
550285242Sachim    inq = INQ(fr->inqList[i]);
551285242Sachim    /* FW interrupt */
552285242Sachim    mpiIBQMsgSend(&saRoot->inboundQueue[inq]);
553285242Sachim  }
554285242Sachim  /* IORequests are freed in siIODone() */
555285242Sachim
556285242Sachim  siFastSSPReqFree(agRoot, fr);
557285242Sachim  return AGSA_RC_SUCCESS;
558285242Sachim} /* saFastSSPSend */
559285242Sachim#endif
560285242Sachim
561285242Sachim/******************************************************************************/
562285242Sachim/*! \brief Start SSP request
563285242Sachim *
564285242Sachim *  Start SSP request
565285242Sachim *
566285242Sachim *  \param agRoot handles for this instance of SAS/SATA LLL
567285242Sachim *  \param queueNum
568285242Sachim *  \param agIORequest
569285242Sachim *  \param agDevHandle
570285242Sachim *  \param agRequestType
571285242Sachim *  \param agRequestBody
572285242Sachim *  \param agTMRequest valid for task management
573285242Sachim *  \param agCB
574285242Sachim *
575285242Sachim *  \return If request is started successfully
576285242Sachim *          - \e AGSA_RC_SUCCESS request is started successfully
577285242Sachim *          - \e AGSA_RC_BUSY request is not started successfully
578285242Sachim */
579285242Sachim/******************************************************************************/
580285242SachimGLOBAL bit32 saSSPStart(
581285242Sachim  agsaRoot_t            *agRoot,
582285242Sachim  agsaIORequest_t       *agIORequest,
583285242Sachim  bit32                 queueNum,
584285242Sachim  agsaDevHandle_t       *agDevHandle,
585285242Sachim  bit32                 agRequestType,
586285242Sachim  agsaSASRequestBody_t  *agRequestBody,
587285242Sachim  agsaIORequest_t       *agTMRequest,
588285242Sachim  ossaSSPCompletedCB_t  agCB)
589285242Sachim{
590285242Sachim  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
591285242Sachim#ifdef LOOPBACK_MPI
592285242Sachim  mpiOCQueue_t        *circularOQ = agNULL;
593285242Sachim#endif
594285242Sachim  mpiICQueue_t        *circularQ  = agNULL;
595285242Sachim  agsaDeviceDesc_t    *pDevice    = agNULL;
596285242Sachim  agsaPort_t          *pPort      = agNULL;
597285242Sachim  agsaIORequestDesc_t *pRequest   = agNULL;
598285242Sachim  agsaSgl_t           *pSgl       = agNULL;
599285242Sachim  void                *pMessage   = agNULL;
600285242Sachim  bit32               ret = AGSA_RC_SUCCESS, retVal = 0;
601285242Sachim  bit32               DirDW4 = 0;    /* no data and no AutoGR */
602285242Sachim  bit32               encryptFlags = 0;
603285242Sachim  bit16               size = 0;
604285242Sachim  bit16               opCode = 0;
605285242Sachim  bit8                inq = 0, outq = 0;
606285242Sachim
607285242Sachim
608285242Sachim  OSSA_INP_ENTER(agRoot);
609285242Sachim  smTraceFuncEnter(hpDBG_VERY_LOUD,"Sa");
610285242Sachim
611285242Sachim  /* sanity check */
612285242Sachim  SA_ASSERT((agNULL != agRoot), "");
613285242Sachim  SA_ASSERT((agNULL != agIORequest), "");
614285242Sachim  SA_ASSERT((agNULL != agDevHandle), "");
615285242Sachim  SA_ASSERT((agNULL != agRequestBody), "");
616285242Sachim
617285242Sachim  DBG_DUMP_SSPSTART_CMDIU(agDevHandle,agRequestType,agRequestBody);
618285242Sachim
619285242Sachim  /* Find the outgoing port for the device */
620285242Sachim  pDevice = (agsaDeviceDesc_t *) (agDevHandle->sdkData);
621285242Sachim
622285242Sachim  if(pDevice == agNULL )
623285242Sachim  {
624285242Sachim    SA_ASSERT((pDevice), "pDevice");
625285242Sachim    ret = AGSA_RC_FAILURE;
626285242Sachim    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Sa");
627285242Sachim    goto ext;
628285242Sachim  }
629285242Sachim
630285242Sachim  pPort = pDevice->pPort;
631285242Sachim  /* Assign inbound and outbound Buffer */
632285242Sachim  inq = (bit8)(queueNum & MPI_IB_NUM_MASK);
633285242Sachim  outq = (bit8)((queueNum & MPI_OB_NUM_MASK) >> MPI_OB_SHIFT);
634285242Sachim  SA_ASSERT((AGSA_MAX_INBOUND_Q > inq), "The IBQ Number is out of range.");
635285242Sachim
636285242Sachim  SA_DBG3(("saSSPStart: inq %d outq %d deviceId 0x%x\n", inq,outq,pDevice->DeviceMapIndex));
637285242Sachim
638285242Sachim  /* Get request from free IORequests */
639285242Sachim  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
640285242Sachim  pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
641285242Sachim
642285242Sachim  /* If no LL IO request entry available */
643285242Sachim  if ( agNULL == pRequest )
644285242Sachim  {
645285242Sachim    ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
646285242Sachim    SA_DBG1(("saSSPStart, No request from free list\n" ));
647285242Sachim    smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "Sa");
648285242Sachim    ret = AGSA_RC_BUSY;
649285242Sachim    goto ext;
650285242Sachim  }
651285242Sachim  /* If LL IO request entry avaliable */
652285242Sachim  else
653285242Sachim  {
654285242Sachim    /* Remove the request from free list */
655285242Sachim    saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
656285242Sachim    /* Add the request to the pendingIORequests list of the device */
657285242Sachim    saLlistIOAdd(&(pDevice->pendingIORequests), &(pRequest->linkNode));
658285242Sachim
659285242Sachim    ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
660285242Sachim
661285242Sachim    SA_ASSERT((!pRequest->valid), "The pRequest is in use");
662285242Sachim
663285242Sachim    SA_DBG3(("saSSPStart, request %p\n", pRequest ));
664285242Sachim
665285242Sachim    /* Decode the flag settings in the standard I/O requests to  decide what size we need. */
666285242Sachim    /* All other requests will be fine with only 64 byte messages. */
667285242Sachim    switch ( agRequestType )
668285242Sachim    {
669285242Sachim    case AGSA_SSP_INIT_READ:
670285242Sachim    case AGSA_SSP_INIT_WRITE:
671285242Sachim    case AGSA_SSP_INIT_NONDATA:
672285242Sachim    case AGSA_SSP_INIT_READ_M:
673285242Sachim    case AGSA_SSP_INIT_WRITE_M:
674285242Sachim        {
675285242Sachim            agsaSSPInitiatorRequest_t *pIRequest = &(agRequestBody->sspInitiatorReq);
676285242Sachim
677285242Sachim            if ((pIRequest->flag & AGSA_SAS_ENABLE_ENCRYPTION)   ||
678285242Sachim#ifdef SAFLAG_USE_DIF_ENC_IOMB
679285242Sachim               (pIRequest->flag & AGSA_SAS_USE_DIF_ENC_OPSTART)  ||
680285242Sachim#endif /* SAFLAG_USE_DIF_ENC_IOMB */
681285242Sachim                (pIRequest->flag & AGSA_SAS_ENABLE_DIF) )
682285242Sachim            {
683285242Sachim                opCode = OPC_INB_SSP_DIF_ENC_OPSTART;
684285242Sachim                size = IOMB_SIZE128;
685285242Sachim            }
686285242Sachim            else
687285242Sachim            {
688285242Sachim                opCode = OPC_INB_SSPINIIOSTART;
689285242Sachim                size = IOMB_SIZE64;
690285242Sachim            }
691285242Sachim            break;
692285242Sachim        }
693285242Sachim    case AGSA_SSP_INIT_READ_EXT:
694285242Sachim    case AGSA_SSP_INIT_WRITE_EXT:
695285242Sachim    case AGSA_SSP_INIT_READ_EXT_M:
696285242Sachim    case AGSA_SSP_INIT_WRITE_EXT_M:
697285242Sachim        {
698285242Sachim          agsaSSPInitiatorRequestExt_t *pIRequest = &(agRequestBody->sspInitiatorReqExt);
699285242Sachim
700285242Sachim          if ((pIRequest->flag & AGSA_SAS_ENABLE_ENCRYPTION)   ||
701285242Sachim              (pIRequest->flag & AGSA_SAS_ENABLE_DIF)          ||
702285242Sachim#ifdef SAFLAG_USE_DIF_ENC_IOMB
703285242Sachim              (pIRequest->flag & AGSA_SAS_USE_DIF_ENC_OPSTART) ||
704285242Sachim#endif /* SAFLAG_USE_DIF_ENC_IOMB */
705285242Sachim              (pIRequest->flag & AGSA_SAS_ENABLE_SKIP_MASK))
706285242Sachim          {
707285242Sachim              opCode = OPC_INB_SSP_DIF_ENC_OPSTART;
708285242Sachim              size = IOMB_SIZE128;
709285242Sachim          }
710285242Sachim          else
711285242Sachim          {
712285242Sachim              SA_ASSERT((smIS_SPC(agRoot)), "smIS_SPC");
713285242Sachim              opCode = OPC_INB_SSPINIEXTIOSTART;
714285242Sachim              size = IOMB_SIZE96;
715285242Sachim          }
716285242Sachim          break;
717285242Sachim      }
718285242Sachim      case  AGSA_SSP_INIT_READ_INDIRECT:
719285242Sachim      case  AGSA_SSP_INIT_WRITE_INDIRECT:
720285242Sachim      case  AGSA_SSP_INIT_READ_INDIRECT_M:
721285242Sachim      case  AGSA_SSP_INIT_WRITE_INDIRECT_M:
722285242Sachim          {
723285242Sachim            SA_DBG3(("saSSPStart: agRequestType  0x%X INDIRECT\n", agRequestType));
724285242Sachim            opCode = OPC_INB_SSP_DIF_ENC_OPSTART;
725285242Sachim            size = IOMB_SIZE128;
726285242Sachim            break;
727285242Sachim          }
728285242Sachim      case (AGSA_SSP_REQTYPE | AGSA_SSP_TASK_MGNT):
729285242Sachim      case AGSA_SSP_TASK_MGNT_REQ_M:
730285242Sachim      case AGSA_SSP_TGT_READ_DATA:
731285242Sachim      case AGSA_SSP_TGT_READ_GOOD_RESP:
732285242Sachim      case AGSA_SSP_TGT_WRITE_DATA:
733285242Sachim      case AGSA_SSP_TGT_WRITE_GOOD_RESP:
734285242Sachim      case AGSA_SSP_TGT_CMD_OR_TASK_RSP:
735285242Sachim
736285242Sachim        SA_DBG3(("saSSPStart: agRequestType  0x%X (was default)\n", agRequestType));
737285242Sachim        opCode = OPC_INB_SSPINIIOSTART;
738285242Sachim        size = IOMB_SIZE64;
739285242Sachim         break;
740285242Sachim    default:
741285242Sachim        SA_DBG1(("saSSPStart: agRequestType UNKNOWN 0x%X\n", agRequestType));
742285242Sachim        /* OpCode is not used in this case, but Linux complains if it is not initialized. */
743285242Sachim        opCode = OPC_INB_SSPINIIOSTART;
744285242Sachim        size = IOMB_SIZE64;
745285242Sachim        break;
746285242Sachim    }
747285242Sachim
748285242Sachim    /* If free IOMB avaliable,  set up pRequest*/
749285242Sachim    pRequest->valid = agTRUE;
750285242Sachim    pRequest->pIORequestContext = agIORequest;
751285242Sachim    pRequest->pDevice = pDevice;
752285242Sachim    pRequest->requestType = agRequestType;
753285242Sachim    pRequest->pPort = pPort;
754285242Sachim    pRequest->startTick = saRoot->timeTick;
755285242Sachim    pRequest->completionCB = agCB;
756285242Sachim
757285242Sachim    /* Set request to the sdkData of agIORequest */
758285242Sachim    agIORequest->sdkData = pRequest;
759285242Sachim
760285242Sachim    /* save tag and IOrequest pointer to IOMap */
761285242Sachim    saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
762285242Sachim    saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
763285242Sachim
764285242Sachim#ifdef SA_LL_IBQ_PROTECT
765285242Sachim    ossaSingleThreadedEnter(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
766285242Sachim#endif /* SA_LL_IBQ_PROTECT */
767285242Sachim
768285242Sachim    /* Get a free inbound queue entry */
769285242Sachim#ifdef LOOPBACK_MPI
770285242Sachim    if (loopback)
771285242Sachim    {
772285242Sachim      SA_DBG2(("saSSPStart: did %d ioq %d / %d tag %d\n", pDevice->DeviceMapIndex, inq, outq, pRequest->HTag));
773285242Sachim      circularOQ = &saRoot->outboundQueue[outq];
774285242Sachim      retVal = mpiMsgFreeGetOQ(circularOQ, size, &pMessage);
775285242Sachim    }
776285242Sachim    else
777285242Sachim#endif /* LOOPBACK_MPI */
778285242Sachim    {
779285242Sachim      circularQ = &saRoot->inboundQueue[inq];
780285242Sachim      retVal = mpiMsgFreeGet(circularQ, size, &pMessage);
781285242Sachim    }
782285242Sachim
783285242Sachim    /* if message size is too large return failure */
784285242Sachim    if (AGSA_RC_FAILURE == retVal)
785285242Sachim    {
786285242Sachim#ifdef SA_LL_IBQ_PROTECT
787285242Sachim      ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
788285242Sachim#endif /* SA_LL_IBQ_PROTECT */
789285242Sachim      /* if not sending return to free list rare */
790285242Sachim      ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
791285242Sachim      saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode));
792285242Sachim      pRequest->valid = agFALSE;
793285242Sachim      saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
794285242Sachim      ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
795285242Sachim
796285242Sachim      SA_DBG1(("saSSPStart, error when get free IOMB\n"));
797285242Sachim      smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "Sa");
798285242Sachim      ret = AGSA_RC_FAILURE;
799285242Sachim      goto ext;
800285242Sachim    }
801285242Sachim
802285242Sachim    /* return busy if inbound queue is full */
803285242Sachim    if (AGSA_RC_BUSY == retVal)
804285242Sachim    {
805285242Sachim#ifdef SA_LL_IBQ_PROTECT
806285242Sachim      ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
807285242Sachim#endif /* SA_LL_IBQ_PROTECT */
808285242Sachim      /* if not sending return to free list rare */
809285242Sachim      ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
810285242Sachim      saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode));
811285242Sachim      pRequest->valid = agFALSE;
812285242Sachim      saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
813285242Sachim      ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
814285242Sachim
815285242Sachim      SA_DBG1(("saSSPStart, no more IOMB\n"));
816285242Sachim      smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "Sa");
817285242Sachim      ret = AGSA_RC_BUSY;
818285242Sachim      goto ext;
819285242Sachim    }
820285242Sachim    SA_DBG3(("saSSPStart:agRequestType %X\n" ,agRequestType));
821285242Sachim
822285242Sachim    switch ( agRequestType )
823285242Sachim    {
824285242Sachim      case AGSA_SSP_INIT_READ:
825285242Sachim      case AGSA_SSP_INIT_WRITE:
826285242Sachim      case AGSA_SSP_INIT_NONDATA:
827285242Sachim      case AGSA_SSP_INIT_READ_EXT:
828285242Sachim      case AGSA_SSP_INIT_WRITE_EXT:
829285242Sachim      case AGSA_SSP_INIT_READ_M:
830285242Sachim      case AGSA_SSP_INIT_WRITE_M:
831285242Sachim      case AGSA_SSP_INIT_READ_EXT_M:
832285242Sachim      case AGSA_SSP_INIT_WRITE_EXT_M:
833285242Sachim      case AGSA_SSP_INIT_READ_INDIRECT:
834285242Sachim      case AGSA_SSP_INIT_WRITE_INDIRECT:
835285242Sachim      case AGSA_SSP_INIT_READ_INDIRECT_M:
836285242Sachim      case AGSA_SSP_INIT_WRITE_INDIRECT_M:
837285242Sachim      {
838285242Sachim        if (!(agRequestType & AGSA_SSP_EXT_BIT))
839285242Sachim        {
840285242Sachim          agsaSSPInitiatorRequest_t     *pIRequest = &(agRequestBody->sspInitiatorReq);
841285242Sachim          agsaSSPIniIOStartCmd_t        *pPayload = (agsaSSPIniIOStartCmd_t *)pMessage;
842285242Sachim          agsaSSPIniEncryptIOStartCmd_t *pEncryptPayload = (agsaSSPIniEncryptIOStartCmd_t *)pMessage;
843285242Sachim
844285242Sachim          /* Most fields for the SAS IOMB have the same offset regardless of the actual IOMB used. */
845285242Sachim          /* Be careful with the scatter/gather lists, encryption and DIF options. */
846285242Sachim
847285242Sachim/*          if( pIRequest->sspCmdIU.cdb[ 0] ==  0x28 || pIRequest->sspCmdIU.cdb[0]== 0x2A)
848285242Sachim          {
849285242Sachim            pRequest->requestBlock = ((pIRequest->sspCmdIU.cdb[2] << 24 ) |
850285242Sachim                            (pIRequest->sspCmdIU.cdb[3] << 16 ) |
851285242Sachim                            (pIRequest->sspCmdIU.cdb[4] <<  8 ) |
852285242Sachim                            (pIRequest->sspCmdIU.cdb[5] ) );
853285242Sachim          }
854285242Sachim*/
855285242Sachim#ifdef LOOPBACK_MPI
856285242Sachim          if (loopback)
857285242Sachim          {
858285242Sachim          OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPCompletionRsp_t, tag), pRequest->HTag);
859285242Sachim          OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPCompletionRsp_t, status), OSSA_IO_SUCCESS);
860285242Sachim          OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPCompletionRsp_t, param), 0);
861285242Sachim          //OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPCompletionRsp_t, SSPTag), 0);
862285242Sachim          }
863285242Sachim          else
864285242Sachim#endif /* LOOPBACK_MPI */
865285242Sachim          {
866285242Sachim            /* SSPIU less equal 28 bytes */
867285242Sachim            /* Configure DWORD 1 */
868285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniIOStartCmd_t, tag), pRequest->HTag);
869285242Sachim            /* Configure DWORD 2 */
870285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniIOStartCmd_t, deviceId), pDevice->DeviceMapIndex);
871285242Sachim            /* Configure DWORD 3 */
872285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniIOStartCmd_t, dataLen), pIRequest->dataLength);
873285242Sachim          }
874285242Sachim
875285242Sachim#ifdef SA_TESTBASE_EXTRA
876285242Sachim          /* TestBase - Set the host BST entry  */
877285242Sachim          DirDW4 |= ((UINT32)pIRequest->bstIndex) << 16;
878285242Sachim#endif /*  SA_TESTBASE_EXTRA */
879285242Sachim
880285242Sachim          if (!(agRequestType & AGSA_SSP_INDIRECT_BIT))
881285242Sachim          {
882285242Sachim            /* Configure DWORD 5-12  */
883285242Sachim            si_memcpy(&pPayload->SSPInfoUnit, &pIRequest->sspCmdIU, sizeof(pPayload->SSPInfoUnit));
884285242Sachim            pPayload->dirMTlr     = 0;
885285242Sachim            /* Mask DIR for Read/Write command */
886285242Sachim            /* Configure DWORD 4 bit 8-9 */
887285242Sachim            DirDW4 |= agRequestType & AGSA_DIR_MASK;
888285242Sachim          }
889285242Sachim          else /* AGSA_SSP_INDIRECT_BIT was set */
890285242Sachim          {
891285242Sachim
892285242Sachim            agsaSSPInitiatorRequestIndirect_t *pIndRequest = &(agRequestBody->sspInitiatorReqIndirect);
893285242Sachim
894285242Sachim            /* Configure DWORD 5 */
895285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,sspiu_0_3_indcdbalL ),pIndRequest->sspInitiatorReqAddrLower32);
896285242Sachim            /* Configure DWORD 6 */
897285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,sspiu_4_7_indcdbalH ),pIndRequest->sspInitiatorReqAddrUpper32 );
898285242Sachim            /* Configure DWORD 7 */
899285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,sspiu_8_11 ), 0);
900285242Sachim            /* Configure DWORD 8 */
901285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,sspiu_12_15 ), 0);
902285242Sachim            /* Configure DWORD 9 */
903285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,sspiu_16_19 ), 0);
904285242Sachim            /* Configure DWORD 10 */
905285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,sspiu_19_23), 0);
906285242Sachim            /* Configure DWORD 11 */
907285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,sspiu_24_27 ), 0);
908285242Sachim            /* Mask DIR for Read/Write command */
909285242Sachim            /* Configure DWORD 4 bit 8-9 */
910285242Sachim            DirDW4 |= agRequestType & AGSA_DIR_MASK;
911285242Sachim            /* Configure DWORD 4 bit 24-31 */
912285242Sachim            DirDW4 |= ((pIndRequest->sspInitiatorReqLen >> 2) & 0xFF) << SHIFT24;
913285242Sachim            /* Configure DWORD 4 bit 4 */
914285242Sachim            DirDW4 |= 1 << SHIFT3;
915285242Sachim          }
916285242Sachim
917285242Sachim          /* set TLR */
918285242Sachim          DirDW4 |= pIRequest->flag & TLR_MASK;
919285242Sachim          if (agRequestType & AGSA_MSG)
920285242Sachim          {
921285242Sachim            /* set M bit */
922285242Sachim            DirDW4 |= AGSA_MSG_BIT;
923285242Sachim          }
924285242Sachim
925285242Sachim          /* check for skipmask operation */
926285242Sachim          if (pIRequest->flag & AGSA_SAS_ENABLE_SKIP_MASK)
927285242Sachim          {
928285242Sachim            DirDW4 |= AGSA_SKIP_MASK_BIT;
929285242Sachim            /* agsaSSPInitiatorRequestIndirect_t skip mask in flag is offset 5  */
930285242Sachim            DirDW4 |= (pIRequest->flag & AGSA_SAS_SKIP_MASK_OFFSET) << SHIFT8;
931285242Sachim          }
932285242Sachim
933285242Sachim
934285242Sachim         /* Configure DWORDS 12-14 */
935285242Sachim         if( pIRequest->encrypt.enableEncryptionPerLA && pIRequest->dif.enableDIFPerLA)
936285242Sachim         {
937285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload,                      /* DWORD 12 */
938285242Sachim                             OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,epl_descL ),
939285242Sachim                             pIRequest->encrypt.EncryptionPerLAAddrLo );
940285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload,                      /* DWORD 13 */
941285242Sachim                             OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,dpl_descL ),
942285242Sachim                             pIRequest->dif.DIFPerLAAddrLo );
943285242Sachim
944285242Sachim            SA_ASSERT(pIRequest->encrypt.EncryptionPerLAAddrHi == pIRequest->dif.DIFPerLAAddrHi, "EPL DPL hi region must be equal");
945285242Sachim
946285242Sachim            if( pIRequest->encrypt.EncryptionPerLAAddrHi != pIRequest->dif.DIFPerLAAddrHi )
947285242Sachim            {
948285242Sachim
949285242Sachim              SA_DBG1(("saSSPStart: EPL DPL hi region must be equal AGSA_RC_FAILURE\n" ));
950285242Sachim              smTraceFuncExit(hpDBG_VERY_LOUD, 'e', "Sa");
951285242Sachim              ret = AGSA_RC_FAILURE;
952285242Sachim              goto ext;
953285242Sachim            }
954285242Sachim
955285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload,                      /* DWORD 14 */
956285242Sachim                             OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,edpl_descH ),
957285242Sachim                             pIRequest->encrypt.EncryptionPerLAAddrHi );
958285242Sachim          }
959285242Sachim          else if( pIRequest->encrypt.enableEncryptionPerLA)
960285242Sachim          {
961285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload,                      /* DWORD 12 */
962285242Sachim                             OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,epl_descL ),
963285242Sachim                             pIRequest->encrypt.EncryptionPerLAAddrLo );
964285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload,                      /* DWORD 13 */
965285242Sachim                             OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,dpl_descL ),
966285242Sachim                             0);
967285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload,                      /* DWORD 14 */
968285242Sachim                             OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,edpl_descH ),
969285242Sachim                             pIRequest->encrypt.EncryptionPerLAAddrHi );
970285242Sachim          }
971285242Sachim          else if (pIRequest->dif.enableDIFPerLA) /* configure DIF */
972285242Sachim          {
973285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload,                      /* DWORD 12 */
974285242Sachim                             OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,epl_descL ),
975285242Sachim                             0);
976285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload,                      /* DWORD 13 */
977285242Sachim                             OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,dpl_descL ),
978285242Sachim                             pIRequest->dif.DIFPerLAAddrLo );
979285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload,                      /* DWORD 14 */
980285242Sachim                             OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,edpl_descH ),
981285242Sachim                             pIRequest->dif.DIFPerLAAddrHi);
982285242Sachim          }
983285242Sachim          else /* Not EPL or DPL  */
984285242Sachim          {
985285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload,                      /* DWORD 12 */
986285242Sachim                             OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,epl_descL ),
987285242Sachim                             0);
988285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload,                      /* DWORD 13 */
989285242Sachim                             OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,dpl_descL ),
990285242Sachim                             0);
991285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload,                      /* DWORD 14 */
992285242Sachim                             OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t,edpl_descH ),
993285242Sachim                             0);
994285242Sachim          }
995285242Sachim
996285242Sachim          if (pIRequest->flag & AGSA_SAS_ENABLE_DIF)
997285242Sachim          {
998285242Sachim            bit32 UDTR1_UDTR0_UDT1_UDT0  =  0;
999285242Sachim            bit32 UDT5_UDT4_UDT3_UDT2     = 0;
1000285242Sachim            bit32 UDTR5_UDTR4_UDTR3_UDTR2 = 0;
1001285242Sachim
1002285242Sachim            SA_DBG3(("saSSPStart,DIF enableRefBlockCount ref %d enableRefBlockCount  %d enableCrc  %d enableCrcInversion %d\n",
1003285242Sachim                pIRequest->dif.flags & DIF_FLAG_BITS_UDTR_REF_BLKCOUNT ? 1 : 0,
1004285242Sachim                pIRequest->dif.flags & DIF_FLAG_BITS_UDTR_REF_BLKCOUNT ? 1 : 0,
1005285242Sachim                pIRequest->dif.flags & DIF_FLAG_BITS_CRC_VER           ? 1 : 0,
1006285242Sachim                pIRequest->dif.flags & DIF_FLAG_BITS_CRC_INV           ? 1 : 0  ));
1007285242Sachim
1008285242Sachim            SA_DBG3(("saSSPStart,DIF initialIOSeed %X lbSize %X difAction %X\n",
1009285242Sachim                pIRequest->dif.flags & DIF_FLAG_BITS_CRC_SEED ? 1 : 0,
1010285242Sachim                (pIRequest->dif.flags & DIF_FLAG_BITS_BLOCKSIZE_MASK) >> DIF_FLAG_BITS_BLOCKSIZE_SHIFT,
1011285242Sachim                pIRequest->dif.flags & DIF_FLAG_BITS_ACTION  ));
1012285242Sachim
1013285242Sachim            SA_DBG3(("saSSPStart,DIF udtArray %2X %2X %2X %2X %2X %2X\n",
1014285242Sachim                pIRequest->dif.udtArray[0],
1015285242Sachim                pIRequest->dif.udtArray[1],
1016285242Sachim                pIRequest->dif.udtArray[2],
1017285242Sachim                pIRequest->dif.udtArray[3],
1018285242Sachim                pIRequest->dif.udtArray[4],
1019285242Sachim                pIRequest->dif.udtArray[5]));
1020285242Sachim
1021285242Sachim            SA_DBG3(("saSSPStart,DIF udrtArray %2X %2X %2X %2X %2X %2X\n",
1022285242Sachim                pIRequest->dif.udrtArray[0],
1023285242Sachim                pIRequest->dif.udrtArray[1],
1024285242Sachim                pIRequest->dif.udrtArray[2],
1025285242Sachim                pIRequest->dif.udrtArray[3],
1026285242Sachim                pIRequest->dif.udrtArray[4],
1027285242Sachim                pIRequest->dif.udrtArray[5]));
1028285242Sachim
1029285242Sachim            SA_DBG3(("saSSPStart,DIF tagUpdateMask %X tagVerifyMask %X DIFPerLAAddrLo %X DIFPerLAAddrHi %X\n",
1030285242Sachim                (pIRequest->dif.flags & DIF_FLAG_BITS_UDTVMASK) >> DIF_FLAG_BITS_UDTV_SHIFT,
1031285242Sachim                (pIRequest->dif.flags & DIF_FLAG_BITS_UDTUPMASK) >> DIF_FLAG_BITS_UDTUPSHIFT,
1032285242Sachim                pIRequest->dif.DIFPerLAAddrLo,
1033285242Sachim                pIRequest->dif.DIFPerLAAddrHi));
1034285242Sachim
1035285242Sachim            DirDW4 |= AGSA_DIF_BIT;
1036285242Sachim
1037285242Sachim            /* DWORD 15 */
1038285242Sachim            SA_DBG3(("saSSPStart, DW 15 DIF_flags 0x%08X\n", pIRequest->dif.flags ));
1039285242Sachim
1040285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload,
1041285242Sachim                               OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, DIF_flags),
1042285242Sachim                               pIRequest->dif.flags);
1043285242Sachim
1044285242Sachim            /* Populate the UDT and UDTR bytes as necessary. */
1045285242Sachim            if ((pIRequest->dif.flags & DIF_FLAG_BITS_ACTION) != AGSA_DIF_INSERT)
1046285242Sachim            {
1047285242Sachim                UDTR1_UDTR0_UDT1_UDT0 = (pIRequest->dif.udtArray[1] << SHIFT8 |
1048285242Sachim                                         pIRequest->dif.udtArray[0]);
1049285242Sachim                UDT5_UDT4_UDT3_UDT2   = (pIRequest->dif.udtArray[5] << SHIFT24 |
1050285242Sachim                                         pIRequest->dif.udtArray[4] << SHIFT16 |
1051285242Sachim                                         pIRequest->dif.udtArray[3] << SHIFT8  |
1052285242Sachim                                         pIRequest->dif.udtArray[2]);
1053285242Sachim            }
1054285242Sachim
1055285242Sachim            if ((pIRequest->dif.flags & DIF_FLAG_BITS_ACTION) == AGSA_DIF_INSERT ||
1056285242Sachim                (pIRequest->dif.flags & DIF_FLAG_BITS_ACTION) == AGSA_DIF_VERIFY_REPLACE ||
1057285242Sachim                (pIRequest->dif.flags & DIF_FLAG_BITS_ACTION) == AGSA_DIF_REPLACE_UDT_REPLACE_CRC)
1058285242Sachim            {
1059285242Sachim                UDTR1_UDTR0_UDT1_UDT0 |= (pIRequest->dif.udrtArray[1] << SHIFT24 |
1060285242Sachim                                          pIRequest->dif.udrtArray[0] << SHIFT16 );
1061285242Sachim                UDTR5_UDTR4_UDTR3_UDTR2 = (pIRequest->dif.udrtArray[5] << SHIFT24 |
1062285242Sachim                                           pIRequest->dif.udrtArray[4] << SHIFT16 |
1063285242Sachim                                           pIRequest->dif.udrtArray[3] << SHIFT8  |
1064285242Sachim                                           pIRequest->dif.udrtArray[2]);
1065285242Sachim            }
1066285242Sachim
1067285242Sachim            /* DWORD 16 is UDT3, UDT2, UDT1 and UDT0 */
1068285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload,
1069285242Sachim                             OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, udt),
1070285242Sachim                             UDTR1_UDTR0_UDT1_UDT0);
1071285242Sachim
1072285242Sachim            /* DWORD 17 is UDT5, UDT4, UDT3 and UDT2 */
1073285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload,
1074285242Sachim                             OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, udtReplacementLo),
1075285242Sachim                             UDT5_UDT4_UDT3_UDT2);
1076285242Sachim
1077285242Sachim            /* DWORD 18 is UDTR5, UDTR4, UDTR3 and UDTR2 */
1078285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload,
1079285242Sachim                             OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, udtReplacementHi),
1080285242Sachim                             UDTR5_UDTR4_UDTR3_UDTR2);
1081285242Sachim
1082285242Sachim            /* DWORD 19 */
1083285242Sachim            /* Get IOS IOSeed enable bit */
1084285242Sachim            if( pIRequest->dif.enableDIFPerLA ||
1085285242Sachim               (pIRequest->dif.flags & DIF_FLAG_BITS_CUST_APP_TAG) )
1086285242Sachim            {
1087285242Sachim                OSSA_WRITE_LE_32(agRoot, pPayload,
1088285242Sachim                                 OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, DIF_seed),
1089285242Sachim                                ((pIRequest->dif.DIFPerLARegion0SecCount << SHIFT16) |
1090285242Sachim                                 (pIRequest->dif.flags & DIF_FLAG_BITS_CRC_SEED ? pIRequest->dif.initialIOSeed : 0 )));
1091285242Sachim            }
1092285242Sachim            else
1093285242Sachim            {
1094285242Sachim              if (pIRequest->dif.flags & DIF_FLAG_BITS_CRC_SEED)
1095285242Sachim              {
1096285242Sachim                OSSA_WRITE_LE_32(agRoot, pPayload,
1097285242Sachim                                 OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, DIF_seed),
1098285242Sachim                                 pIRequest->dif.initialIOSeed );
1099285242Sachim              }
1100285242Sachim              else
1101285242Sachim              {
1102285242Sachim                OSSA_WRITE_LE_32(agRoot, pPayload,
1103285242Sachim                                 OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, DIF_seed),  0 );
1104285242Sachim              }
1105285242Sachim            }
1106285242Sachim          }
1107285242Sachim
1108285242Sachim          /* configure encryption */
1109285242Sachim          if (pIRequest->flag & AGSA_SAS_ENABLE_ENCRYPTION)
1110285242Sachim          {
1111285242Sachim
1112285242Sachim            SA_DBG3(("saSSPStart,ENC dekTable 0x%08X dekIndex 0x%08X\n",
1113285242Sachim                pIRequest->encrypt.dekInfo.dekTable,
1114285242Sachim                pIRequest->encrypt.dekInfo.dekIndex));
1115285242Sachim
1116285242Sachim            SA_DBG3(("saSSPStart,ENC kekIndex 0x%08X sectorSizeIndex 0x%08X cipherMode 0x%08X\n",
1117285242Sachim                pIRequest->encrypt.kekIndex,
1118285242Sachim                pIRequest->encrypt.sectorSizeIndex,
1119285242Sachim                pIRequest->encrypt.cipherMode));
1120285242Sachim
1121285242Sachim            SA_DBG3(("saSSPStart,ENC keyTag_W0 0x%08X keyTag_W1 0x%08X\n",
1122285242Sachim                pIRequest->encrypt.keyTag_W0,
1123285242Sachim                pIRequest->encrypt.keyTag_W1));
1124285242Sachim            SA_DBG3(("saSSPStart,ENC tweakVal_W0 0x%08X tweakVal_W1 0x%08X\n",
1125285242Sachim                pIRequest->encrypt.tweakVal_W0,
1126285242Sachim                pIRequest->encrypt.tweakVal_W1));
1127285242Sachim            SA_DBG3(("saSSPStart,ENC tweakVal_W2 0x%08X tweakVal_W3 0x%08X\n",
1128285242Sachim                pIRequest->encrypt.tweakVal_W2,
1129285242Sachim                pIRequest->encrypt.tweakVal_W3));
1130285242Sachim
1131285242Sachim              DirDW4 |= AGSA_ENCRYPT_BIT;
1132285242Sachim
1133285242Sachim              encryptFlags = 0;
1134285242Sachim
1135285242Sachim              if (pIRequest->encrypt.keyTagCheck == agTRUE)
1136285242Sachim              {
1137285242Sachim                 encryptFlags |= AGSA_ENCRYPT_KEY_TAG_BIT;
1138285242Sachim              }
1139285242Sachim
1140285242Sachim              if( pIRequest->encrypt.cipherMode == agsaEncryptCipherModeXTS )
1141285242Sachim              {
1142285242Sachim                encryptFlags |= AGSA_ENCRYPT_XTS_Mode << SHIFT4;
1143285242Sachim              }
1144285242Sachim
1145285242Sachim              encryptFlags |= pIRequest->encrypt.dekInfo.dekTable << SHIFT2;
1146285242Sachim
1147285242Sachim              /* Always use encryption for DIF fields, skip SKPD */
1148285242Sachim
1149285242Sachim              encryptFlags |= (pIRequest->encrypt.dekInfo.dekIndex & 0xFFFFFF) << SHIFT8;
1150285242Sachim              /* Configure DWORD 20 */
1151285242Sachim              OSSA_WRITE_LE_32(agRoot, pPayload,
1152285242Sachim                               OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, encryptFlagsLo),
1153285242Sachim                               encryptFlags);
1154285242Sachim
1155285242Sachim              encryptFlags = pIRequest->encrypt.sectorSizeIndex;
1156285242Sachim
1157285242Sachim              encryptFlags |= (pIRequest->encrypt.kekIndex) << SHIFT5;
1158285242Sachim
1159285242Sachim              encryptFlags |= (pIRequest->encrypt.EncryptionPerLRegion0SecCount) << SHIFT16;
1160285242Sachim              /* Configure DWORD 21 */
1161285242Sachim              OSSA_WRITE_LE_32(agRoot, pPayload,
1162285242Sachim                               OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, encryptFlagsHi),
1163285242Sachim                               encryptFlags);
1164285242Sachim
1165285242Sachim              /* Configure DWORD 22 */
1166285242Sachim              OSSA_WRITE_LE_32(agRoot, pPayload,
1167285242Sachim                               OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, keyTag_W0),
1168285242Sachim                               pIRequest->encrypt.keyTag_W0);
1169285242Sachim              /* Configure DWORD 23 */
1170285242Sachim              OSSA_WRITE_LE_32(agRoot, pPayload,
1171285242Sachim                               OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, keyTag_W1),
1172285242Sachim                               pIRequest->encrypt.keyTag_W1);
1173285242Sachim
1174285242Sachim              /* Configure DWORD 24 */
1175285242Sachim              OSSA_WRITE_LE_32(agRoot, pPayload,
1176285242Sachim                               OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, tweakVal_W0),
1177285242Sachim                               pIRequest->encrypt.tweakVal_W0);
1178285242Sachim              /* Configure DWORD 25 */
1179285242Sachim              OSSA_WRITE_LE_32(agRoot, pPayload,
1180285242Sachim                               OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, tweakVal_W1),
1181285242Sachim                               pIRequest->encrypt.tweakVal_W1);
1182285242Sachim              /* Configure DWORD 26 */
1183285242Sachim              OSSA_WRITE_LE_32(agRoot, pPayload,
1184285242Sachim                               OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, tweakVal_W2),
1185285242Sachim                               pIRequest->encrypt.tweakVal_W2);
1186285242Sachim              /* Configure DWORD 27 */
1187285242Sachim              OSSA_WRITE_LE_32(agRoot, pPayload,
1188285242Sachim                               OSSA_OFFSET_OF(agsaSSPIniEncryptIOStartCmd_t, tweakVal_W3),
1189285242Sachim                               pIRequest->encrypt.tweakVal_W3);
1190285242Sachim          }
1191285242Sachim
1192285242Sachim          /* Setup SGL */
1193285242Sachim          if (pIRequest->dataLength)
1194285242Sachim          {
1195285242Sachim            pSgl = &(pIRequest->agSgl);
1196285242Sachim
1197285242Sachim            SA_DBG3(("saSSPStart:opCode %X agSgl %08x:%08x (%x/%x)\n",opCode,
1198285242Sachim                pSgl->sgUpper, pSgl->sgLower, pSgl->len, pSgl->extReserved));
1199285242Sachim
1200285242Sachim            /* Get DIF PER LA flag */
1201285242Sachim            DirDW4 |= (pIRequest->dif.enableDIFPerLA ? (1 << SHIFT7) : 0);
1202285242Sachim            DirDW4 |= (pIRequest->encrypt.enableEncryptionPerLA ? ( 1 << SHIFT12 ) : 0);
1203285242Sachim            /* Configure DWORD 4 */
1204285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniIOStartCmd_t, dirMTlr), DirDW4);
1205285242Sachim
1206285242Sachim            if (opCode == OPC_INB_SSP_DIF_ENC_OPSTART)
1207285242Sachim            {
1208285242Sachim              /* Configure DWORD 28 */
1209285242Sachim              pEncryptPayload->AddrLow0 = pSgl->sgLower;
1210285242Sachim              /* Configure DWORD 29 */
1211285242Sachim              pEncryptPayload->AddrHi0 = pSgl->sgUpper;
1212285242Sachim              /* Configure DWORD 30 */
1213285242Sachim              pEncryptPayload->Len0 = pSgl->len;
1214285242Sachim              /* Configure DWORD 31 */
1215285242Sachim              pEncryptPayload->E0 = pSgl->extReserved;
1216285242Sachim            }
1217285242Sachim            else
1218285242Sachim            {
1219285242Sachim              pPayload->AddrLow0 = pSgl->sgLower;
1220285242Sachim              pPayload->AddrHi0 = pSgl->sgUpper;
1221285242Sachim              pPayload->Len0 = pSgl->len;
1222285242Sachim              pPayload->E0 = pSgl->extReserved;
1223285242Sachim            }
1224285242Sachim          }
1225285242Sachim          else
1226285242Sachim          {
1227285242Sachim            /* no data transfer */
1228285242Sachim            /* Configure DWORD 4 */
1229285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniIOStartCmd_t, dirMTlr), DirDW4);
1230285242Sachim
1231285242Sachim            if (opCode == OPC_INB_SSP_DIF_ENC_OPSTART)
1232285242Sachim            {
1233285242Sachim                  pEncryptPayload = (agsaSSPIniEncryptIOStartCmd_t *) pPayload;
1234285242Sachim
1235285242Sachim                  pEncryptPayload->AddrLow0 = 0;
1236285242Sachim                  pEncryptPayload->AddrHi0 = 0;
1237285242Sachim                  pEncryptPayload->Len0 = 0;
1238285242Sachim                  pEncryptPayload->E0 = 0;
1239285242Sachim            }
1240285242Sachim            else
1241285242Sachim            {
1242285242Sachim                pPayload->AddrLow0 = 0;
1243285242Sachim                pPayload->AddrHi0 = 0;
1244285242Sachim                pPayload->Len0 = 0;
1245285242Sachim                pPayload->E0 = 0;
1246285242Sachim            }
1247285242Sachim          }
1248285242Sachim
1249285242Sachim          /* post the IOMB to SPC */
1250285242Sachim#ifdef LOOPBACK_MPI
1251285242Sachim          if (loopback)
1252285242Sachim            ret = mpiMsgProduceOQ(circularOQ, (void *)pMessage, MPI_CATEGORY_SAS_SATA, OPC_OUB_SSP_COMP, outq, (bit8)circularQ->priority);
1253285242Sachim          else
1254285242Sachim#endif /* LOOPBACK_MPI */
1255285242Sachim          ret = mpiMsgProduce(circularQ, (void *)pMessage, MPI_CATEGORY_SAS_SATA, opCode, outq, (bit8)circularQ->priority);
1256285242Sachim          if (AGSA_RC_FAILURE == ret)
1257285242Sachim          {
1258285242Sachim            SA_DBG1(("saSSPStart, error when post SSP IOMB\n"));
1259285242Sachim            ret = AGSA_RC_FAILURE;
1260285242Sachim          }
1261285242Sachim        }
1262285242Sachim        else
1263285242Sachim        {
1264285242Sachim          /* additionalCdbLen is not zero and type is Ext - use EXT mode */
1265285242Sachim          agsaSSPInitiatorRequestExt_t *pIRequest = &(agRequestBody->sspInitiatorReqExt);
1266285242Sachim          agsaSSPIniExtIOStartCmd_t *pPayload = (agsaSSPIniExtIOStartCmd_t *)pMessage;
1267285242Sachim          bit32 sspiul;
1268285242Sachim
1269285242Sachim          /*
1270285242Sachim           * Most fields for the SAS IOMB have the same offset regardless of the actual IOMB used.
1271285242Sachim           * Be careful with the scatter/gather lists, encryption and DIF options.
1272285242Sachim           */
1273285242Sachim          /* CDB > 16 bytes */
1274285242Sachim          OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniExtIOStartCmd_t, tag), pRequest->HTag);
1275285242Sachim          OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniExtIOStartCmd_t, deviceId), pDevice->DeviceMapIndex);
1276285242Sachim          OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniExtIOStartCmd_t, dataLen), pIRequest->dataLength);
1277285242Sachim          /* dword (bit7-bit2) ==> bytes (bit7-bit0) */
1278285242Sachim          /* setup standard CDB bytes + additional CDB bytes in length field */
1279285242Sachim          sspiul = sizeof(agsaSSPCmdInfoUnit_t) +
1280285242Sachim                    (pIRequest->sspCmdIUExt.additionalCdbLen & 0xFC);
1281285242Sachim          DirDW4 = sspiul << 16;
1282285242Sachim          si_memcpy(&pPayload->SSPIu[0], &pIRequest->sspCmdIUExt, sspiul);
1283285242Sachim          pPayload->SSPIuLendirMTlr = 0;
1284285242Sachim
1285285242Sachim          /* Mask DIR for Read/Write command */
1286285242Sachim          DirDW4 |= agRequestType & AGSA_DIR_MASK;
1287285242Sachim
1288285242Sachim          /* set TLR */
1289285242Sachim          DirDW4 |= pIRequest->flag & TLR_MASK;
1290285242Sachim          if (agRequestType & AGSA_MSG)
1291285242Sachim          {
1292285242Sachim            /* set M bit */
1293285242Sachim            DirDW4 |= AGSA_MSG_BIT;
1294285242Sachim          }
1295285242Sachim
1296285242Sachim          /* check for skipmask operation */
1297285242Sachim          if (pIRequest->flag & AGSA_SAS_ENABLE_SKIP_MASK)
1298285242Sachim          {
1299285242Sachim            SA_ASSERT(0, "Mode not supported");
1300285242Sachim          }
1301285242Sachim
1302285242Sachim          /* configure DIF */
1303285242Sachim          if (pIRequest->flag & AGSA_SAS_ENABLE_DIF)
1304285242Sachim          {
1305285242Sachim            SA_ASSERT(0, "Mode not supported");
1306285242Sachim          }
1307285242Sachim
1308285242Sachim          /* configure encryption */
1309285242Sachim          if (pIRequest->flag & AGSA_SAS_ENABLE_ENCRYPTION)
1310285242Sachim          {
1311285242Sachim            SA_ASSERT(0, "Mode not supported");
1312285242Sachim          }
1313285242Sachim          /* Setup SGL */
1314285242Sachim          if (pIRequest->dataLength)
1315285242Sachim          {
1316285242Sachim            pSgl = &(pIRequest->agSgl);
1317285242Sachim
1318285242Sachim            SA_DBG3(("saSSPStart: Ext mode, agSgl %08x:%08x (%x/%x)\n",
1319285242Sachim              pSgl->sgUpper, pSgl->sgLower, pSgl->len, pSgl->extReserved));
1320285242Sachim
1321285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniExtIOStartCmd_t, SSPIuLendirMTlr), DirDW4);
1322285242Sachim
1323285242Sachim             if (opCode == OPC_INB_SSP_DIF_ENC_OPSTART)
1324285242Sachim            {
1325285242Sachim                si_memcpy((&((agsaSSPIniEncryptIOStartCmd_t *)(pPayload))->AddrLow0), pSgl, sizeof(agsaSgl_t));
1326285242Sachim            }
1327285242Sachim            else
1328285242Sachim            {
1329285242Sachim                si_memcpy((&(pPayload->SSPIu[0]) + sspiul), pSgl, sizeof(agsaSgl_t));
1330285242Sachim            }
1331285242Sachim          }
1332285242Sachim          else
1333285242Sachim          {
1334285242Sachim            /* no data transfer */
1335285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniExtIOStartCmd_t, SSPIuLendirMTlr), DirDW4);
1336285242Sachim            pPayload->dataLen = 0;
1337285242Sachim          }
1338285242Sachim
1339285242Sachim          /* post the IOMB to SPC */
1340285242Sachim          if (AGSA_RC_FAILURE == mpiMsgProduce(circularQ, (void *)pMessage, MPI_CATEGORY_SAS_SATA, opCode, outq,(bit8)circularQ->priority ))
1341285242Sachim          {
1342285242Sachim            SA_DBG1(("saSSPStart, error when post SSP Ext IOMB\n"));
1343285242Sachim            ret = AGSA_RC_FAILURE;
1344285242Sachim          }
1345285242Sachim        }
1346285242Sachim        break;
1347285242Sachim      }
1348285242Sachim      case AGSA_SSP_TASK_MGNT_REQ:
1349285242Sachim      case AGSA_SSP_TASK_MGNT_REQ_M:
1350285242Sachim      {
1351285242Sachim        agsaIORequestDesc_t *pTMRequestToAbort = agNULL;
1352285242Sachim        agsaSSPIniTMStartCmd_t *pPayload = (agsaSSPIniTMStartCmd_t *)pMessage;
1353285242Sachim
1354285242Sachim        if (agRequestType & AGSA_MSG)
1355285242Sachim        {
1356285242Sachim          /* set M bit */
1357285242Sachim          DirDW4 = AGSA_MSG_BIT;
1358285242Sachim        }
1359285242Sachim
1360285242Sachim        /* set DS and ADS bit */
1361285242Sachim        DirDW4 |= (agRequestBody->sspTaskMgntReq.tmOption & 0x3) << 3;
1362285242Sachim
1363285242Sachim        /* Prepare the SSP TASK Management payload */
1364285242Sachim        OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniTMStartCmd_t, tag), pRequest->HTag);
1365285242Sachim        OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniTMStartCmd_t, deviceId), pDevice->DeviceMapIndex);
1366285242Sachim        OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniTMStartCmd_t, relatedTag), agRequestBody->sspTaskMgntReq.tagOfTaskToBeManaged);
1367285242Sachim        OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniTMStartCmd_t, TMfunction), agRequestBody->sspTaskMgntReq.taskMgntFunction);
1368285242Sachim        OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniTMStartCmd_t, dsAdsMReport), DirDW4);
1369285242Sachim        pPayload->lun[0] = agRequestBody->sspTaskMgntReq.lun[0];
1370285242Sachim        pPayload->lun[1] = agRequestBody->sspTaskMgntReq.lun[1];
1371285242Sachim        pPayload->lun[2] = agRequestBody->sspTaskMgntReq.lun[2];
1372285242Sachim        pPayload->lun[3] = agRequestBody->sspTaskMgntReq.lun[3];
1373285242Sachim        pPayload->lun[4] = agRequestBody->sspTaskMgntReq.lun[4];
1374285242Sachim        pPayload->lun[5] = agRequestBody->sspTaskMgntReq.lun[5];
1375285242Sachim        pPayload->lun[6] = agRequestBody->sspTaskMgntReq.lun[6];
1376285242Sachim        pPayload->lun[7] = agRequestBody->sspTaskMgntReq.lun[7];
1377285242Sachim
1378285242Sachim        if (agTMRequest)
1379285242Sachim        {
1380285242Sachim          pTMRequestToAbort = (agsaIORequestDesc_t *)agTMRequest->sdkData;
1381285242Sachim          if (pTMRequestToAbort)
1382285242Sachim          {
1383285242Sachim            OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPIniTMStartCmd_t, relatedTag), pTMRequestToAbort->HTag);
1384285242Sachim          }
1385285242Sachim        }
1386285242Sachim
1387285242Sachim        SA_DBG1(("saSSPStart, HTAG 0x%x TM function 0x%x Tag-to-be-aborted 0x%x deviceId 0x%x\n",
1388285242Sachim                  pPayload->tag, pPayload->TMfunction, pPayload->relatedTag, pPayload->deviceId));
1389285242Sachim
1390285242Sachim        siDumpActiveIORequests(agRoot, saRoot->swConfig.maxActiveIOs);
1391285242Sachim
1392285242Sachim        /* post the IOMB to SPC */
1393285242Sachim        if (AGSA_RC_FAILURE == mpiMsgProduce(circularQ, (void *)pMessage, MPI_CATEGORY_SAS_SATA, OPC_INB_SSPINITMSTART, outq, (bit8)circularQ->priority))
1394285242Sachim        {
1395285242Sachim          SA_DBG1(("saSSPStart, error when post TM IOMB\n"));
1396285242Sachim          ret = AGSA_RC_FAILURE;
1397285242Sachim        }
1398285242Sachim
1399285242Sachim        break;
1400285242Sachim      }
1401285242Sachim      case AGSA_SSP_TGT_READ_DATA:
1402285242Sachim      case AGSA_SSP_TGT_READ_GOOD_RESP:
1403285242Sachim      case AGSA_SSP_TGT_WRITE_DATA:
1404285242Sachim      case AGSA_SSP_TGT_WRITE_GOOD_RESP:
1405285242Sachim      {
1406285242Sachim        agsaSSPTargetRequest_t *pTRequest = &(agRequestBody->sspTargetReq);
1407285242Sachim        agsaSSPTgtIOStartCmd_t *pPayload = (agsaSSPTgtIOStartCmd_t *)pMessage;
1408285242Sachim        bit32 DirDW5 = 0;
1409285242Sachim        /* Prepare the SSP TGT IO Start payload */
1410285242Sachim        /* Configure DWORD 1 */
1411285242Sachim        OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, tag), pRequest->HTag);
1412285242Sachim        /* Configure DWORD 2 */
1413285242Sachim        OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, deviceId), pDevice->DeviceMapIndex);
1414285242Sachim        /* Configure DWORD 3 */
1415285242Sachim        OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, dataLen), pTRequest->dataLength);
1416285242Sachim        /* Configure DWORD 4 */
1417285242Sachim        OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, dataOffset), pTRequest->offset);
1418285242Sachim
1419285242Sachim        SA_DBG3(("saSSPStart, sspOption %08X\n", pTRequest->sspOption ));
1420285242Sachim
1421285242Sachim        /* Mask DIR and AutoGR bits for Read/Write command */
1422285242Sachim        DirDW5 = (agRequestType & (AGSA_DIR_MASK | AGSA_AUTO_MASK)) | (pTRequest->agTag << 16);
1423285242Sachim
1424285242Sachim        if (pTRequest->sspOption & SSP_OPTION_DIF )
1425285242Sachim        {
1426285242Sachim          bit32 UDTR1_UDTR0_UDT1_UDT0   = 0;
1427285242Sachim          bit32 UDT5_UDT4_UDT3_UDT2     = 0;
1428285242Sachim          bit32 UDTR5_UDTR4_UDTR3_UDTR2 = 0;
1429285242Sachim          SA_DBG3(("saSSPStart,tgt DIF enableRefBlockCount ref %d enableRefBlockCount  %d enableCrc  %d enableCrcInversion %d\n",
1430285242Sachim              pTRequest->dif.flags & DIF_FLAG_BITS_UDTR_REF_BLKCOUNT ? 1 : 0,
1431285242Sachim              pTRequest->dif.flags & DIF_FLAG_BITS_UDTR_REF_BLKCOUNT ? 1 : 0,
1432285242Sachim              pTRequest->dif.flags & DIF_FLAG_BITS_CRC_VER           ? 1 : 0,
1433285242Sachim              pTRequest->dif.flags & DIF_FLAG_BITS_CRC_INV           ? 1 : 0  ));
1434285242Sachim
1435285242Sachim          SA_DBG3(("saSSPStart,tgt DIF initialIOSeed %X lbSize %X difAction %X\n",
1436285242Sachim              pTRequest->dif.flags & DIF_FLAG_BITS_CRC_SEED ? 1 : 0,
1437285242Sachim              (pTRequest->dif.flags & DIF_FLAG_BITS_BLOCKSIZE_MASK ) >> DIF_FLAG_BITS_BLOCKSIZE_SHIFT,
1438285242Sachim              pTRequest->dif.flags & DIF_FLAG_BITS_ACTION  ));
1439285242Sachim
1440285242Sachim          SA_DBG3(("saSSPStart,tgt DIF udtArray %2X %2X %2X %2X %2X %2X\n",
1441285242Sachim              pTRequest->dif.udtArray[0],
1442285242Sachim              pTRequest->dif.udtArray[1],
1443285242Sachim              pTRequest->dif.udtArray[2],
1444285242Sachim              pTRequest->dif.udtArray[3],
1445285242Sachim              pTRequest->dif.udtArray[4],
1446285242Sachim              pTRequest->dif.udtArray[5]));
1447285242Sachim
1448285242Sachim          SA_DBG3(("saSSPStart,tgt DIF udrtArray %2X %2X %2X %2X %2X %2X\n",
1449285242Sachim              pTRequest->dif.udrtArray[0],
1450285242Sachim              pTRequest->dif.udrtArray[1],
1451285242Sachim              pTRequest->dif.udrtArray[2],
1452285242Sachim              pTRequest->dif.udrtArray[3],
1453285242Sachim              pTRequest->dif.udrtArray[4],
1454285242Sachim              pTRequest->dif.udrtArray[5]));
1455285242Sachim
1456285242Sachim          SA_DBG3(("saSSPStart,tgt DIF tagUpdateMask %X tagVerifyMask %X DIFPerLAAddrLo %X DIFPerLAAddrHi %X\n",
1457285242Sachim              (pTRequest->dif.flags & DIF_FLAG_BITS_UDTVMASK) >> DIF_FLAG_BITS_UDTV_SHIFT,
1458285242Sachim              (pTRequest->dif.flags & DIF_FLAG_BITS_UDTUPMASK) >> DIF_FLAG_BITS_UDTUPSHIFT,
1459285242Sachim              pTRequest->dif.DIFPerLAAddrLo,
1460285242Sachim              pTRequest->dif.DIFPerLAAddrHi));
1461285242Sachim
1462285242Sachim          DirDW5 |= AGSA_SSP_TGT_BITS_DEE_DIF;
1463285242Sachim
1464285242Sachim
1465285242Sachim          SA_DBG3(("saSSPStart,tgt  DW 15 DIF_flags 0x%08X\n", pTRequest->dif.flags ));
1466285242Sachim
1467285242Sachim          OSSA_WRITE_LE_32(agRoot, pPayload,
1468285242Sachim                             OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, DIF_flags),
1469285242Sachim                             pTRequest->dif.flags);
1470285242Sachim
1471285242Sachim            /* Populate the UDT and UDTR bytes as necessary. */
1472285242Sachim            if ((pTRequest->dif.flags & DIF_FLAG_BITS_ACTION) != AGSA_DIF_INSERT)
1473285242Sachim            {
1474285242Sachim                UDTR1_UDTR0_UDT1_UDT0 = (pTRequest->dif.udtArray[1] << SHIFT8 |
1475285242Sachim                                         pTRequest->dif.udtArray[0]);
1476285242Sachim                UDT5_UDT4_UDT3_UDT2   = (pTRequest->dif.udtArray[5] << SHIFT24 |
1477285242Sachim                                         pTRequest->dif.udtArray[4] << SHIFT16 |
1478285242Sachim                                         pTRequest->dif.udtArray[3] << SHIFT8  |
1479285242Sachim                                         pTRequest->dif.udtArray[2]);
1480285242Sachim            }
1481285242Sachim
1482285242Sachim            if ((pTRequest->dif.flags & DIF_FLAG_BITS_ACTION) == AGSA_DIF_INSERT ||
1483285242Sachim                (pTRequest->dif.flags & DIF_FLAG_BITS_ACTION) == AGSA_DIF_VERIFY_REPLACE ||
1484285242Sachim                (pTRequest->dif.flags & DIF_FLAG_BITS_ACTION) == AGSA_DIF_REPLACE_UDT_REPLACE_CRC)
1485285242Sachim            {
1486285242Sachim                UDTR1_UDTR0_UDT1_UDT0 |= (pTRequest->dif.udrtArray[1] << SHIFT24 |
1487285242Sachim                                          pTRequest->dif.udrtArray[0] << SHIFT16 );
1488285242Sachim                UDTR5_UDTR4_UDTR3_UDTR2 = (pTRequest->dif.udrtArray[5] << SHIFT24 |
1489285242Sachim                                           pTRequest->dif.udrtArray[4] << SHIFT16 |
1490285242Sachim                                           pTRequest->dif.udrtArray[3] << SHIFT8  |
1491285242Sachim                                           pTRequest->dif.udrtArray[2]);
1492285242Sachim            }
1493285242Sachim          /* DWORD 8 is UDTR1, UDTR0, UDT1 and UDT0 */
1494285242Sachim          OSSA_WRITE_LE_32(agRoot, pPayload,
1495285242Sachim                           OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, udt),
1496285242Sachim                           UDTR1_UDTR0_UDT1_UDT0);
1497285242Sachim
1498285242Sachim          /* DWORD 9 is UDT5, UDT4, UDT3 and UDT2 */
1499285242Sachim          OSSA_WRITE_LE_32(agRoot, pPayload,
1500285242Sachim                           OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, udtReplacementLo),
1501285242Sachim                           UDT5_UDT4_UDT3_UDT2);
1502285242Sachim
1503285242Sachim          /* DWORD 10 is UDTR5, UDTR4, UDTR3 and UDTR2 */
1504285242Sachim          OSSA_WRITE_LE_32(agRoot, pPayload,
1505285242Sachim                           OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, udtReplacementHi),
1506285242Sachim                           UDTR5_UDTR4_UDTR3_UDTR2);
1507285242Sachim          /* DWORD 11 */
1508285242Sachim          /* Get IOS IOSeed enable bit */
1509285242Sachim          if( pTRequest->dif.flags & DIF_FLAG_BITS_CUST_APP_TAG)
1510285242Sachim          {
1511285242Sachim              OSSA_WRITE_LE_32(agRoot, pPayload,
1512285242Sachim                               OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, DIF_seed),
1513285242Sachim                               ((pTRequest->dif.DIFPerLARegion0SecCount << SHIFT16) |
1514285242Sachim                               (pTRequest->dif.flags & DIF_FLAG_BITS_CRC_SEED ? pTRequest->dif.initialIOSeed : 0 )));
1515285242Sachim          }
1516285242Sachim          else
1517285242Sachim          {
1518285242Sachim              /* Get IOS IOSeed enable bit */
1519285242Sachim              if (pTRequest->dif.flags & DIF_FLAG_BITS_CRC_SEED)
1520285242Sachim              {
1521285242Sachim                  OSSA_WRITE_LE_32(agRoot, pPayload,
1522285242Sachim                                   OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, DIF_seed),
1523285242Sachim                                   pTRequest->dif.initialIOSeed );
1524285242Sachim              }
1525285242Sachim              else
1526285242Sachim              {
1527285242Sachim                  OSSA_WRITE_LE_32(agRoot, pPayload,
1528285242Sachim                                   OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, DIF_seed),  0 );
1529285242Sachim              }
1530285242Sachim          }
1531285242Sachim        }
1532285242Sachim
1533285242Sachim        /* Mask DIR and AutoGR bits for Read/Write command */
1534285242Sachim        if(pTRequest->sspOption & SSP_OPTION_AUTO_GOOD_RESPONSE)
1535285242Sachim        {
1536285242Sachim          DirDW5 |= AGSA_SSP_TGT_BITS_AGR;
1537285242Sachim        }
1538285242Sachim
1539285242Sachim        /* AN, RTE, RDF bits */
1540285242Sachim        DirDW5 |= (pTRequest->sspOption & SSP_OPTION_BITS) << 2;
1541285242Sachim
1542285242Sachim        /* ODS */
1543285242Sachim        if(pTRequest->sspOption & SSP_OPTION_ODS)
1544285242Sachim        {
1545285242Sachim          DirDW5 |= AGSA_SSP_TGT_BITS_ODS;
1546285242Sachim        }
1547285242Sachim
1548285242Sachim        /* Setup SGL */
1549285242Sachim        if (pTRequest->dataLength)
1550285242Sachim        {
1551285242Sachim          pSgl = &(pTRequest->agSgl);
1552285242Sachim
1553285242Sachim          SA_DBG5(("saSSPStart: agSgl %08x:%08x (%x/%x)\n",
1554285242Sachim          pSgl->sgUpper, pSgl->sgLower, pSgl->len, pSgl->extReserved));
1555285242Sachim
1556285242Sachim          /* set up dir on the payload */
1557285242Sachim          /* Configure DWORD 5 */
1558285242Sachim          OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, INITagAgrDir), DirDW5);
1559285242Sachim
1560285242Sachim          pPayload->AddrLow0 = pSgl->sgLower;
1561285242Sachim          pPayload->AddrHi0 = pSgl->sgUpper;
1562285242Sachim          pPayload->Len0 = pSgl->len;
1563285242Sachim          pPayload->E0 = pSgl->extReserved;
1564285242Sachim        }
1565285242Sachim        else
1566285242Sachim        {
1567285242Sachim          /* no data transfer */
1568285242Sachim          /* Configure DWORD 5 */
1569285242Sachim          OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t, INITagAgrDir), DirDW5);
1570285242Sachim          pPayload->AddrLow0 = 0;
1571285242Sachim          pPayload->AddrHi0 = 0;
1572285242Sachim          pPayload->Len0 = 0;
1573285242Sachim        }
1574285242Sachim        /* Configure DWORD 6 */
1575285242Sachim        OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtIOStartCmd_t,reserved ), 0);
1576285242Sachim
1577285242Sachim        /* Build TGT IO START command and send it to SPC */
1578285242Sachim        if (AGSA_RC_FAILURE == mpiMsgProduce(circularQ, (void *)pMessage, MPI_CATEGORY_SAS_SATA, OPC_INB_SSPTGTIOSTART, outq, (bit8)circularQ->priority))
1579285242Sachim        {
1580285242Sachim          SA_DBG1(("saSSPStart, error when post TGT IOMB\n"));
1581285242Sachim          ret = AGSA_RC_FAILURE;
1582285242Sachim        }
1583285242Sachim
1584285242Sachim        break;
1585285242Sachim      }
1586285242Sachim      case AGSA_SSP_TGT_CMD_OR_TASK_RSP:
1587285242Sachim      {
1588285242Sachim        agsaSSPTargetResponse_t *pTResponse = &(agRequestBody->sspTargetResponse);
1589285242Sachim        agsaSSPTgtRspStartCmd_t *pPayload = (agsaSSPTgtRspStartCmd_t *)pMessage;
1590285242Sachim        bit32 ip, an, ods;
1591285242Sachim
1592285242Sachim        if (pTResponse->frameBuf && (pTResponse->respBufLength <= AGSA_MAX_SSPPAYLOAD_VIA_SFO))
1593285242Sachim        {
1594285242Sachim          ip = 1;
1595285242Sachim          si_memcpy(pPayload->reserved, pTResponse->frameBuf, pTResponse->respBufLength);
1596285242Sachim        }
1597285242Sachim        else
1598285242Sachim        {
1599285242Sachim          ip = 0;
1600285242Sachim          /* NOTE:
1601285242Sachim           * 1. reserved field must be ZEROED out. FW depends on it
1602285242Sachim           * 2. trusted interface. indirect response buffer must be valid.
1603285242Sachim           */
1604285242Sachim          si_memset(pPayload->reserved, 0, sizeof(pPayload->reserved));
1605285242Sachim          OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtRspStartCmd_t, AddrLow0), pTResponse->respBufLower);
1606285242Sachim          OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtRspStartCmd_t, AddrHi0), pTResponse->respBufUpper);
1607285242Sachim          OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtRspStartCmd_t, Len0), pTResponse->respBufLength);
1608285242Sachim          OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtRspStartCmd_t, E0), 0);
1609285242Sachim        }
1610285242Sachim
1611285242Sachim        /* TLR setting */
1612285242Sachim        an = (pTResponse->respOption & RESP_OPTION_BITS);
1613285242Sachim        /* ODS */
1614285242Sachim        ods = (pTResponse->respOption & RESP_OPTION_ODS);
1615285242Sachim
1616285242Sachim        /* Prepare the SSP TGT RESPONSE Start payload */
1617285242Sachim        OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtRspStartCmd_t, tag), pRequest->HTag);
1618285242Sachim        OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtRspStartCmd_t, deviceId), pDevice->DeviceMapIndex);
1619285242Sachim        OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtRspStartCmd_t, RspLen), pTResponse->respBufLength);
1620285242Sachim        OSSA_WRITE_LE_32(agRoot, pPayload, OSSA_OFFSET_OF(agsaSSPTgtRspStartCmd_t, INITag_IP_AN),
1621285242Sachim          (pTResponse->agTag << SHIFT16) | ods | (ip << SHIFT10) | (an << SHIFT2));
1622285242Sachim
1623285242Sachim        /* Build TGT RESPONSE START command and send it to SPC */
1624285242Sachim        if (AGSA_RC_FAILURE == mpiMsgProduce(circularQ, (void *)pMessage, MPI_CATEGORY_SAS_SATA, OPC_INB_SSPTGTRSPSTART, outq, (bit8)circularQ->priority))
1625285242Sachim        {
1626285242Sachim          SA_DBG1(("saSSPStart, error when post TGT RSP IOMB\n"));
1627285242Sachim          ret = AGSA_RC_FAILURE;
1628285242Sachim        }
1629285242Sachim
1630285242Sachim        break;
1631285242Sachim      }
1632285242Sachim      default:
1633285242Sachim      {
1634285242Sachim        SA_DBG1(("saSSPStart, Unsupported Request IOMB\n"));
1635285242Sachim        ret = AGSA_RC_FAILURE;
1636285242Sachim        break;
1637285242Sachim      }
1638285242Sachim    }
1639285242Sachim
1640285242Sachim  } /* LL IOrequest available */
1641285242Sachim
1642285242Sachim#ifdef SA_LL_IBQ_PROTECT
1643285242Sachim  ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
1644285242Sachim#endif /* SA_LL_IBQ_PROTECT */
1645285242Sachim
1646285242Sachim#ifdef SALL_API_TEST
1647285242Sachim  if (ret == AGSA_RC_SUCCESS)
1648285242Sachim    saRoot->LLCounters.IOCounter.numSSPStarted++;
1649285242Sachim#endif /*SALL_API_TEST  */
1650285242Sachim
1651285242Sachim#ifdef LOOPBACK_MPI
1652285242Sachim  if (loopback)
1653285242Sachim    saRoot->interruptVecIndexBitMap[0] |= (1 << outq);
1654285242Sachim#endif /* LOOPBACK_MPI */
1655285242Sachim  /* goto have leave and trace point info */
1656285242Sachim  smTraceFuncExit(hpDBG_VERY_LOUD, 'f', "Sa");
1657285242Sachimext:
1658285242Sachim
1659285242Sachim  OSSA_INP_LEAVE(agRoot);
1660285242Sachim  return ret;
1661285242Sachim}
1662285242Sachim
1663285242Sachim/******************************************************************************/
1664285242Sachim/*! \brief Abort SSP request
1665285242Sachim *
1666285242Sachim *  Abort SSP request
1667285242Sachim *
1668285242Sachim *  \param agRoot handles for this instance of SAS/SATA LLL
1669285242Sachim *  \param queueNum
1670285242Sachim *  \param agIORequest
1671285242Sachim *  \param agIOToBeAborted
1672285242Sachim *
1673285242Sachim *  \return If request is aborted successfully
1674285242Sachim *          - \e AGSA_RC_SUCCESS request is aborted successfully
1675285242Sachim *          - \e AGSA_RC_FAILURE request is not aborted successfully
1676285242Sachim */
1677285242Sachim/*******************************************************************************/
1678285242SachimGLOBAL bit32 saSSPAbort(
1679285242Sachim  agsaRoot_t        *agRoot,
1680285242Sachim  agsaIORequest_t   *agIORequest,
1681285242Sachim  bit32             queueNum,
1682285242Sachim  agsaDevHandle_t   *agDevHandle,
1683285242Sachim  bit32             flag,
1684285242Sachim  void              *abortParam,
1685285242Sachim  ossaGenericAbortCB_t  agCB
1686285242Sachim  )
1687285242Sachim{
1688285242Sachim  bit32 ret = AGSA_RC_SUCCESS, retVal;
1689285242Sachim  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
1690285242Sachim  agsaIORequestDesc_t *pRequest;
1691285242Sachim  agsaIORequestDesc_t *pRequestABT = NULL;
1692285242Sachim  agsaDeviceDesc_t    *pDevice = NULL;
1693285242Sachim  agsaDeviceDesc_t    *pDeviceABT = NULL;
1694285242Sachim  agsaPort_t          *pPort = NULL;
1695285242Sachim  mpiICQueue_t        *circularQ;
1696285242Sachim  void                *pMessage;
1697285242Sachim  agsaSSPAbortCmd_t   *payload;
1698285242Sachim  agsaIORequest_t     *agIOToBeAborted;
1699285242Sachim  bit8                inq, outq;
1700285242Sachim  bit32               using_reserved = agFALSE;
1701285242Sachim  bit32               flag_copy = flag;
1702285242Sachim  smTraceFuncEnter(hpDBG_VERY_LOUD,"Sb");
1703285242Sachim
1704285242Sachim  /* sanity check */
1705285242Sachim  SA_ASSERT((agNULL != agRoot), "");
1706285242Sachim  SA_ASSERT((agNULL != agIORequest), "");
1707285242Sachim
1708285242Sachim  SA_DBG2(("saSSPAbort: agIORequest %p agDevHandle %p abortParam %p flag 0x%x\n", agIORequest,agDevHandle,abortParam,flag));
1709285242Sachim
1710285242Sachim  /* Assign inbound and outbound Buffer */
1711285242Sachim  inq = (bit8)(queueNum & MPI_IB_NUM_MASK);
1712285242Sachim  outq = (bit8)((queueNum & MPI_OB_NUM_MASK) >> MPI_OB_SHIFT);
1713285242Sachim  SA_ASSERT((AGSA_MAX_INBOUND_Q > inq), "The IBQ Number is out of range.");
1714285242Sachim
1715285242Sachim#ifdef SA_PRINTOUT_IN_WINDBG
1716285242Sachim#ifndef DBG
1717285242Sachim        DbgPrint("saSSPAbort flag %d\n", flag );
1718285242Sachim#endif /* DBG  */
1719285242Sachim#endif /* SA_PRINTOUT_IN_WINDBG  */
1720285242Sachim
1721285242Sachim  if( ABORT_SINGLE == (flag & ABORT_MASK) )
1722285242Sachim  {
1723285242Sachim    agIOToBeAborted = (agsaIORequest_t *)abortParam;
1724285242Sachim    /* Get LL IORequest entry for saSSPAbort() */
1725285242Sachim    pRequest = (agsaIORequestDesc_t *) (agIOToBeAborted->sdkData);
1726285242Sachim    if (agNULL == pRequest)
1727285242Sachim    {
1728285242Sachim      /* no pRequest found - can not Abort */
1729285242Sachim      SA_DBG1(("saSSPAbort: ABORT_ALL no pRequest\n"));
1730285242Sachim      smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Sb");
1731285242Sachim      return AGSA_RC_FAILURE;
1732285242Sachim    }
1733285242Sachim    /* Find the device the request sent to */
1734285242Sachim    pDevice = pRequest->pDevice;
1735285242Sachim    /* Get LL IORequest entry for IOToBeAborted */
1736285242Sachim    pRequestABT = (agsaIORequestDesc_t *) (agIOToBeAborted->sdkData);
1737285242Sachim    if (agNULL == pRequestABT)
1738285242Sachim    {
1739285242Sachim      /* The IO to Be Abort is no longer exist */
1740285242Sachim      SA_DBG1(("saSSPAbort: ABORT_ALL no pRequestABT\n"));
1741285242Sachim      smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "Sb");
1742285242Sachim      return AGSA_RC_FAILURE;
1743285242Sachim    }
1744285242Sachim    /* Find the device the request Abort to */
1745285242Sachim    pDeviceABT = pRequestABT->pDevice;
1746285242Sachim
1747285242Sachim    if (agNULL == pDeviceABT)
1748285242Sachim    {
1749285242Sachim      /* no deviceID - can not build IOMB */
1750285242Sachim      SA_DBG1(("saSSPAbort: ABORT_ALL no pRequestABT->deviceID\n"));
1751285242Sachim      smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "Sb");
1752285242Sachim      return AGSA_RC_FAILURE;
1753285242Sachim    }
1754285242Sachim
1755285242Sachim    if (agNULL != pDevice)
1756285242Sachim    {
1757285242Sachim      /* Find the port the request was sent to */
1758285242Sachim      pPort = pDevice->pPort;
1759285242Sachim    }
1760285242Sachim    else
1761285242Sachim    {
1762285242Sachim      /* no deviceID - can not build IOMB */
1763285242Sachim      SA_DBG1(("saSSPAbort: ABORT_ALL no deviceID\n"));
1764285242Sachim      smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "Sb");
1765285242Sachim      return AGSA_RC_FAILURE;
1766285242Sachim    }
1767285242Sachim
1768285242Sachim    /* Get request from free IORequests */
1769285242Sachim    ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1770285242Sachim    pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests)); /**/
1771285242Sachim  }
1772285242Sachim  else
1773285242Sachim  {
1774285242Sachim    if (ABORT_ALL == (flag & ABORT_MASK))
1775285242Sachim    {
1776285242Sachim      /* abort All with Device or Port */
1777285242Sachim      /* Find the outgoing port for the device */
1778285242Sachim      if (agDevHandle == agNULL)
1779285242Sachim      {
1780285242Sachim        /* no deviceID - can not build IOMB */
1781285242Sachim        SA_DBG1(("saSSPAbort: agDevHandle == agNULL!!!\n"));
1782285242Sachim        return AGSA_RC_FAILURE;
1783285242Sachim      }
1784285242Sachim      pDevice = (agsaDeviceDesc_t *) (agDevHandle->sdkData);
1785285242Sachim      if (agNULL == pDevice)
1786285242Sachim      {
1787285242Sachim        /* no deviceID - can not build IOMB */
1788285242Sachim        SA_DBG1(("saSSPAbort: ABORT_ALL agNULL == pDevice\n"));
1789285242Sachim        return AGSA_RC_FAILURE;
1790285242Sachim      }
1791285242Sachim      pPort = pDevice->pPort;
1792285242Sachim      ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1793285242Sachim      pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests)); /**/
1794285242Sachim    }
1795285242Sachim    else
1796285242Sachim    {
1797285242Sachim      /* only support 00, 01 and 02 for flag */
1798285242Sachim      SA_DBG1(("saSSPAbort: ABORT_ALL type not supported 0x%X\n",flag));
1799285242Sachim      smTraceFuncExit(hpDBG_VERY_LOUD, 'e', "Sb");
1800285242Sachim      return AGSA_RC_FAILURE;
1801285242Sachim    }
1802285242Sachim  }
1803285242Sachim
1804285242Sachim  if ( agNULL == pRequest )
1805285242Sachim  {
1806285242Sachim    pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeReservedRequests));
1807285242Sachim    if(agNULL != pRequest)
1808285242Sachim    {
1809285242Sachim      using_reserved = agTRUE;
1810285242Sachim      SA_DBG2(("saSSPAbort: using saRoot->freeReservedRequests\n"));
1811285242Sachim    }
1812285242Sachim    else
1813285242Sachim    {
1814285242Sachim      ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1815285242Sachim      /* If no LL IO request entry available */
1816285242Sachim      SA_DBG1(("saSSPAbort: No request from free list Not using saRoot->freeReservedRequests\n"));
1817285242Sachim      smTraceFuncExit(hpDBG_VERY_LOUD, 'f', "Sb");
1818285242Sachim      return AGSA_RC_BUSY;
1819285242Sachim    }
1820285242Sachim  }
1821285242Sachim
1822285242Sachim  /* If free IOMB avaliable */
1823285242Sachim  /* Remove the request from free list */
1824285242Sachim  if( using_reserved )
1825285242Sachim  {
1826285242Sachim    saLlistIORemove(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
1827285242Sachim  }
1828285242Sachim  else
1829285242Sachim  {
1830285242Sachim    saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
1831285242Sachim  }
1832285242Sachim
1833285242Sachim  /* Add the request to the pendingIORequests list of the device */
1834285242Sachim  pRequest->valid = agTRUE;
1835285242Sachim  saLlistIOAdd(&(pDevice->pendingIORequests), &(pRequest->linkNode));
1836285242Sachim
1837285242Sachim  ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1838285242Sachim
1839285242Sachim  /* set up pRequest */
1840285242Sachim  pRequest->pIORequestContext = agIORequest;
1841285242Sachim  pRequest->requestType = AGSA_SSP_REQTYPE;
1842285242Sachim  pRequest->pDevice = pDevice;
1843285242Sachim  pRequest->pPort = pPort;
1844285242Sachim  pRequest->completionCB = (void*)agCB;
1845285242Sachim/*  pRequest->abortCompletionCB = agCB;*/
1846285242Sachim  pRequest->startTick = saRoot->timeTick;
1847285242Sachim
1848285242Sachim  /* Set request to the sdkData of agIORequest */
1849285242Sachim  agIORequest->sdkData = pRequest;
1850285242Sachim
1851285242Sachim  /* save tag and IOrequest pointer to IOMap */
1852285242Sachim  saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
1853285242Sachim  saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
1854285242Sachim
1855285242Sachim
1856285242Sachim#ifdef SA_LL_IBQ_PROTECT
1857285242Sachim  ossaSingleThreadedEnter(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
1858285242Sachim#endif /* SA_LL_IBQ_PROTECT */
1859285242Sachim
1860285242Sachim  /* If LL IO request entry avaliable */
1861285242Sachim  /* Get a free inbound queue entry */
1862285242Sachim  circularQ = &saRoot->inboundQueue[inq];
1863285242Sachim  retVal    = mpiMsgFreeGet(circularQ, IOMB_SIZE64, &pMessage);
1864285242Sachim
1865285242Sachim  /* if message size is too large return failure */
1866285242Sachim  if (AGSA_RC_FAILURE == retVal)
1867285242Sachim  {
1868285242Sachim#ifdef SA_LL_IBQ_PROTECT
1869285242Sachim    ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
1870285242Sachim#endif /* SA_LL_IBQ_PROTECT */
1871285242Sachim
1872285242Sachim    ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1873285242Sachim    saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode));
1874285242Sachim    pRequest->valid = agFALSE;
1875285242Sachim    if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
1876285242Sachim    {
1877285242Sachim      SA_DBG1(("saSSPAbort: saving pRequest (%p) for later use\n", pRequest));
1878285242Sachim      saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
1879285242Sachim    }
1880285242Sachim    else
1881285242Sachim    {
1882285242Sachim      /* return the request to free pool */
1883285242Sachim      saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
1884285242Sachim    }
1885285242Sachim    ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1886285242Sachim
1887285242Sachim    SA_DBG1(("saSSPAbort: error when get free IOMB\n"));
1888285242Sachim
1889285242Sachim    smTraceFuncExit(hpDBG_VERY_LOUD, 'g', "Sb");
1890285242Sachim    return AGSA_RC_FAILURE;
1891285242Sachim  }
1892285242Sachim
1893285242Sachim  /* return busy if inbound queue is full */
1894285242Sachim  if (AGSA_RC_BUSY == retVal)
1895285242Sachim  {
1896285242Sachim#ifdef SA_LL_IBQ_PROTECT
1897285242Sachim    ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
1898285242Sachim#endif /* SA_LL_IBQ_PROTECT */
1899285242Sachim
1900285242Sachim    ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1901285242Sachim    saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode));
1902285242Sachim    pRequest->valid = agFALSE;
1903285242Sachim    if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
1904285242Sachim    {
1905285242Sachim      SA_DBG1(("saSSPAbort: saving pRequest (%p) for later use\n", pRequest));
1906285242Sachim      saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
1907285242Sachim    }
1908285242Sachim    else
1909285242Sachim    {
1910285242Sachim      /* return the request to free pool */
1911285242Sachim      saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
1912285242Sachim    }
1913285242Sachim    ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
1914285242Sachim
1915285242Sachim    SA_DBG1(("saSSPAbort: no more IOMB\n"));
1916285242Sachim    smTraceFuncExit(hpDBG_VERY_LOUD, 'h', "Sb");
1917285242Sachim    return AGSA_RC_BUSY;
1918285242Sachim  }
1919285242Sachim
1920285242Sachim  /* setup payload */
1921285242Sachim  payload = (agsaSSPAbortCmd_t*)pMessage;
1922285242Sachim  OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSSPAbortCmd_t, tag), pRequest->HTag);
1923285242Sachim
1924285242Sachim  if( ABORT_SINGLE == (flag & ABORT_MASK) )
1925285242Sachim  {
1926285242Sachim    if ( agNULL == pDeviceABT )
1927285242Sachim    {
1928285242Sachim      SA_DBG1(("saSSPSAbort: no device\n" ));
1929285242Sachim      smTraceFuncExit(hpDBG_VERY_LOUD, 'i', "Sb");
1930285242Sachim      return AGSA_RC_FAILURE;
1931285242Sachim    }
1932285242Sachim    OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSSPAbortCmd_t, deviceId), pDeviceABT->DeviceMapIndex);
1933285242Sachim    OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSSPAbortCmd_t, HTagAbort), pRequestABT->HTag);
1934285242Sachim  }
1935285242Sachim  else
1936285242Sachim  {
1937285242Sachim    /* abort all */
1938285242Sachim    OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSSPAbortCmd_t, deviceId), pDevice->DeviceMapIndex);
1939285242Sachim    OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSSPAbortCmd_t, HTagAbort), 0);
1940285242Sachim  }
1941285242Sachim
1942285242Sachim  if(flag & ABORT_TSDK_QUARANTINE)
1943285242Sachim  {
1944285242Sachim    if(smIS_SPCV(agRoot))
1945285242Sachim    {
1946285242Sachim      flag_copy &= ABORT_SCOPE;
1947285242Sachim      flag_copy |= ABORT_QUARANTINE_SPCV;
1948285242Sachim    }
1949285242Sachim  }
1950285242Sachim  OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSSPAbortCmd_t, abortAll), flag_copy);
1951285242Sachim
1952285242Sachim  SA_DBG1(("saSSPAbort: HTag 0x%x HTagABT 0x%x deviceId 0x%x flag 0x%x\n", payload->tag, payload->HTagAbort, payload->deviceId,flag));
1953285242Sachim
1954285242Sachim  siCountActiveIORequestsOnDevice( agRoot,   payload->deviceId );
1955285242Sachim
1956285242Sachim  /* post the IOMB to SPC */
1957285242Sachim  ret = mpiMsgProduce(circularQ, (void *)pMessage, MPI_CATEGORY_SAS_SATA, OPC_INB_SSP_ABORT, outq, (bit8)circularQ->priority);
1958285242Sachim
1959285242Sachim#ifdef SA_LL_IBQ_PROTECT
1960285242Sachim  ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
1961285242Sachim#endif /* SA_LL_IBQ_PROTECT */
1962285242Sachim
1963285242Sachim#ifdef SALL_API_TEST
1964285242Sachim  if (AGSA_RC_SUCCESS == ret)
1965285242Sachim  {
1966285242Sachim    saRoot->LLCounters.IOCounter.numSSPAborted++;
1967285242Sachim  }
1968285242Sachim#endif
1969285242Sachim
1970285242Sachim  smTraceFuncExit(hpDBG_VERY_LOUD, 'j', "Sb");
1971285242Sachim
1972285242Sachim  return ret;
1973285242Sachim}
1974285242Sachim
1975285242Sachim
1976285242Sachim#if defined(SALLSDK_DEBUG)
1977285242Sachim/******************************************************************************/
1978285242Sachim/*! \brief
1979285242Sachim *
1980285242Sachim *  Dump StartSSP information
1981285242Sachim *
1982285242Sachim *  Debug helper routine
1983285242Sachim *
1984285242Sachim *  \return -none -
1985285242Sachim */
1986285242Sachim/*******************************************************************************/
1987285242SachimLOCAL void siDumpSSPStartIu(
1988285242Sachim  agsaDevHandle_t       *agDevHandle,
1989285242Sachim  bit32                 agRequestType,
1990285242Sachim  agsaSASRequestBody_t  *agRequestBody
1991285242Sachim  )
1992285242Sachim {
1993285242Sachim  switch ( agRequestType )
1994285242Sachim  {
1995285242Sachim    case AGSA_SSP_INIT_READ:
1996285242Sachim    case AGSA_SSP_INIT_WRITE:
1997285242Sachim    {
1998285242Sachim      agsaSSPInitiatorRequest_t *pIRequest = &(agRequestBody->sspInitiatorReq);
1999285242Sachim
2000285242Sachim      SA_DBG5(("siDumpSSPStartIu: dev=%p - %s - len=%x - attr=%x - CDB:%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
2001285242Sachim        agDevHandle,
2002285242Sachim        (agRequestType==AGSA_SSP_INIT_READ)? "AGSA_SSP_INIT_READ" : "AGSA_SSP_INIT_WRITE",
2003285242Sachim        pIRequest->dataLength,
2004285242Sachim        pIRequest->sspCmdIU.efb_tp_taskAttribute,
2005285242Sachim        pIRequest->sspCmdIU.cdb[0],
2006285242Sachim        pIRequest->sspCmdIU.cdb[1],
2007285242Sachim        pIRequest->sspCmdIU.cdb[2],
2008285242Sachim        pIRequest->sspCmdIU.cdb[3],
2009285242Sachim        pIRequest->sspCmdIU.cdb[4],
2010285242Sachim        pIRequest->sspCmdIU.cdb[5],
2011285242Sachim        pIRequest->sspCmdIU.cdb[6],
2012285242Sachim        pIRequest->sspCmdIU.cdb[7],
2013285242Sachim        pIRequest->sspCmdIU.cdb[8],
2014285242Sachim        pIRequest->sspCmdIU.cdb[9]
2015285242Sachim        ));
2016285242Sachim      break;
2017285242Sachim    }
2018285242Sachim
2019285242Sachim    case  AGSA_SSP_INIT_READ_EXT:
2020285242Sachim    case  AGSA_SSP_INIT_WRITE_EXT:
2021285242Sachim    {
2022285242Sachim      agsaSSPInitiatorRequestExt_t *pIRequest = &(agRequestBody->sspInitiatorReqExt);
2023285242Sachim
2024285242Sachim      SA_DBG3(("siDumpSSPStartIu: dev=%p - %s - len=%x - attr=%x - CDB:%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
2025285242Sachim        agDevHandle,
2026285242Sachim        (agRequestType==AGSA_SSP_INIT_READ_EXT)? "AGSA_SSP_INIT_READ_EXT" : "AGSA_SSP_INIT_WRITE_EXT",
2027285242Sachim        pIRequest->dataLength,
2028285242Sachim        pIRequest->sspCmdIUExt.efb_tp_taskAttribute,
2029285242Sachim        pIRequest->sspCmdIUExt.cdb[0],
2030285242Sachim        pIRequest->sspCmdIUExt.cdb[1],
2031285242Sachim        pIRequest->sspCmdIUExt.cdb[2],
2032285242Sachim        pIRequest->sspCmdIUExt.cdb[3],
2033285242Sachim        pIRequest->sspCmdIUExt.cdb[4],
2034285242Sachim        pIRequest->sspCmdIUExt.cdb[5],
2035285242Sachim        pIRequest->sspCmdIUExt.cdb[6],
2036285242Sachim        pIRequest->sspCmdIUExt.cdb[7],
2037285242Sachim        pIRequest->sspCmdIUExt.cdb[8],
2038285242Sachim        pIRequest->sspCmdIUExt.cdb[9]
2039285242Sachim        ));
2040285242Sachim      break;
2041285242Sachim    }
2042285242Sachim
2043285242Sachim    case  AGSA_SSP_INIT_READ_EXT_M:
2044285242Sachim    case  AGSA_SSP_INIT_WRITE_EXT_M:
2045285242Sachim    {
2046285242Sachim      agsaSSPInitiatorRequestExt_t *pIRequest = &(agRequestBody->sspInitiatorReqExt);
2047285242Sachim
2048285242Sachim      SA_DBG3(("siDumpSSPStartIu: dev=%p - %s - len=%x - attr=%x - CDB:%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
2049285242Sachim        agDevHandle,
2050285242Sachim        (agRequestType==AGSA_SSP_INIT_READ_EXT_M)? "AGSA_SSP_INIT_READ_EXT_M" : "AGSA_SSP_INIT_WRITE_EXT_M",
2051285242Sachim        pIRequest->dataLength,
2052285242Sachim        pIRequest->sspCmdIUExt.efb_tp_taskAttribute,
2053285242Sachim        pIRequest->sspCmdIUExt.cdb[0],
2054285242Sachim        pIRequest->sspCmdIUExt.cdb[1],
2055285242Sachim        pIRequest->sspCmdIUExt.cdb[2],
2056285242Sachim        pIRequest->sspCmdIUExt.cdb[3],
2057285242Sachim        pIRequest->sspCmdIUExt.cdb[4],
2058285242Sachim        pIRequest->sspCmdIUExt.cdb[5],
2059285242Sachim        pIRequest->sspCmdIUExt.cdb[6],
2060285242Sachim        pIRequest->sspCmdIUExt.cdb[7],
2061285242Sachim        pIRequest->sspCmdIUExt.cdb[8],
2062285242Sachim        pIRequest->sspCmdIUExt.cdb[9]
2063285242Sachim        ));
2064285242Sachim      break;
2065285242Sachim    }
2066285242Sachim
2067285242Sachim    case  AGSA_SSP_INIT_READ_INDIRECT:
2068285242Sachim    case  AGSA_SSP_INIT_WRITE_INDIRECT:
2069285242Sachim    case  AGSA_SSP_INIT_READ_INDIRECT_M:
2070285242Sachim    case  AGSA_SSP_INIT_WRITE_INDIRECT_M:
2071285242Sachim    {
2072285242Sachim     agsaSSPInitiatorRequestIndirect_t *pIRequest = &(agRequestBody->sspInitiatorReqIndirect);
2073285242Sachim
2074285242Sachim      SA_DBG3(("siDumpSSPStartIu: dev=%p - %s - len=%x - cdblen=%d CDB:U %08x L %08x\n",
2075285242Sachim        agDevHandle,
2076285242Sachim        (agRequestType==AGSA_SSP_INIT_READ_INDIRECT ||
2077285242Sachim         agRequestType==AGSA_SSP_INIT_READ_INDIRECT_M) ? "AGSA_SSP_INIT_READ_INDIRECT" : "AGSA_SSP_INIT_WRITE_INDIRECT",
2078285242Sachim        pIRequest->dataLength,
2079285242Sachim        pIRequest->sspInitiatorReqLen,
2080285242Sachim        pIRequest->sspInitiatorReqAddrUpper32,
2081285242Sachim        pIRequest->sspInitiatorReqAddrLower32 ));
2082285242Sachim      break;
2083285242Sachim    }
2084285242Sachim
2085285242Sachim
2086285242Sachim    case AGSA_SSP_TASK_MGNT_REQ:
2087285242Sachim    {
2088285242Sachim      agsaSSPScsiTaskMgntReq_t  *pTaskCmd =&agRequestBody->sspTaskMgntReq;
2089285242Sachim      /* copy payload */
2090285242Sachim
2091285242Sachim      SA_DBG5(("siDumpSSPStartIu: dev=%p - %s - Task Function=%x - Tag to managed=%x",
2092285242Sachim        agDevHandle,
2093285242Sachim        "AGSA_SSP_TASK_MGNT_REQ",
2094285242Sachim        pTaskCmd->taskMgntFunction,
2095285242Sachim        pTaskCmd->tagOfTaskToBeManaged
2096285242Sachim        ));
2097285242Sachim      break;
2098285242Sachim    }
2099285242Sachim    case AGSA_SSP_TGT_READ_DATA:
2100285242Sachim    {
2101285242Sachim      agsaSSPTargetRequest_t *pTRequest = &(agRequestBody->sspTargetReq);
2102285242Sachim
2103285242Sachim      SA_DBG5(("siDumpSSPStartIu: dev=%p - %s - dmaSize=%x dmaOffset=%x\n",
2104285242Sachim                  agDevHandle,
2105285242Sachim                  "AGSA_SSP_TGT_READ_DATA",
2106285242Sachim                  pTRequest->dataLength,
2107285242Sachim                  pTRequest->offset ));
2108285242Sachim      break;
2109285242Sachim    }
2110285242Sachim    case AGSA_SSP_TGT_READ_GOOD_RESP:
2111285242Sachim    {
2112285242Sachim      agsaSSPTargetRequest_t *pTRequest = &(agRequestBody->sspTargetReq);
2113285242Sachim
2114285242Sachim      SA_DBG5(("siDumpSSPStartIu: dev=%p - %s - dmaSize=%x dmaOffset=%x\n",
2115285242Sachim                  agDevHandle,
2116285242Sachim                  "AGSA_SSP_TGT_READ_GOOD_RESP",
2117285242Sachim                  pTRequest->dataLength,
2118285242Sachim                  pTRequest->offset));
2119285242Sachim      break;
2120285242Sachim    }
2121285242Sachim    case AGSA_SSP_TGT_WRITE_GOOD_RESP:
2122285242Sachim    {
2123285242Sachim      agsaSSPTargetRequest_t  *pTRequest = &(agRequestBody->sspTargetReq);
2124285242Sachim      SA_DBG5(("siDumpSSPStartIu: dev=%p - %s - dmaSize=%x dmaOffset=%x\n",
2125285242Sachim                  agDevHandle,
2126285242Sachim                  "AGSA_SSP_TGT_WRITE_GOOD_RESP",
2127285242Sachim                  pTRequest->dataLength,
2128285242Sachim                  pTRequest->offset ));
2129285242Sachim
2130285242Sachim      break;
2131285242Sachim    }
2132285242Sachim    case AGSA_SSP_TGT_WRITE_DATA:
2133285242Sachim    {
2134285242Sachim      agsaSSPTargetRequest_t  *pTRequest = &(agRequestBody->sspTargetReq);
2135285242Sachim
2136285242Sachim      SA_DBG5(("siDumpSSPStartIu: dev=%p - %s - dmaSize=%x dmaOffset=%x\n",
2137285242Sachim        agDevHandle,
2138285242Sachim        "AGSA_SSP_TGT_WRITE_DATA",
2139285242Sachim        pTRequest->dataLength,
2140285242Sachim        pTRequest->offset ));
2141285242Sachim      break;
2142285242Sachim    }
2143285242Sachim    case AGSA_SSP_TGT_CMD_OR_TASK_RSP:
2144285242Sachim    {
2145285242Sachim      agsaSSPTargetResponse_t *pTResponse = &(agRequestBody->sspTargetResponse);
2146285242Sachim
2147285242Sachim      SA_DBG5(("siDumpSSPStartIu: dev=%p - %s - len=%x PAddr=%08x:%08x  Tag=%x\n",
2148285242Sachim        agDevHandle,
2149285242Sachim        "AGSA_SSP_TGT_CMD_OR_TASK_RSP",
2150285242Sachim        pTResponse->respBufLength,
2151285242Sachim        pTResponse->respBufUpper,
2152285242Sachim        pTResponse->respBufLower,
2153285242Sachim        pTResponse->agTag  ));
2154285242Sachim      break;
2155285242Sachim    }
2156285242Sachim
2157285242Sachim    default:
2158285242Sachim    {
2159285242Sachim      SA_DBG1(("siDumpSSPStartIu: dev=%p - %s %X\n",
2160285242Sachim        agDevHandle,
2161285242Sachim        "Unknown SSP cmd type",
2162285242Sachim        agRequestType
2163285242Sachim        ));
2164285242Sachim      break;
2165285242Sachim    }
2166285242Sachim  }
2167285242Sachim  return;
2168285242Sachim}
2169285242Sachim#endif /* SALLSDK_DEBUG */
2170