1285809Sscottl/*******************************************************************************
2285809Sscottl*Copyright (c) 2014 PMC-Sierra, Inc.  All rights reserved.
3285809Sscottl*
4285809Sscottl*Redistribution and use in source and binary forms, with or without modification, are permitted provided
5285809Sscottl*that the following conditions are met:
6285809Sscottl*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
7285809Sscottl*following disclaimer.
8285809Sscottl*2. Redistributions in binary form must reproduce the above copyright notice,
9285809Sscottl*this list of conditions and the following disclaimer in the documentation and/or other materials provided
10285809Sscottl*with the distribution.
11285809Sscottl*
12285809Sscottl*THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
13285809Sscottl*WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
14285809Sscottl*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
15285809Sscottl*FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
16285809Sscottl*NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
17285809Sscottl*BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18285809Sscottl*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
19285809Sscottl*SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
20285809Sscottl
21285809Sscottl********************************************************************************/
22285809Sscottl#include <sys/cdefs.h>
23285809Sscottl__FBSDID("$FreeBSD$");
24285809Sscottl#include <dev/pms/config.h>
25285809Sscottl
26285809Sscottl#include <dev/pms/freebsd/driver/common/osenv.h>
27285809Sscottl#include <dev/pms/freebsd/driver/common/ostypes.h>
28285809Sscottl#include <dev/pms/freebsd/driver/common/osdebug.h>
29285809Sscottl
30285809Sscottl#include <dev/pms/RefTisa/tisa/api/titypes.h>
31285809Sscottl
32285809Sscottl#include <dev/pms/RefTisa/sallsdk/api/sa.h>
33285809Sscottl#include <dev/pms/RefTisa/sallsdk/api/saapi.h>
34285809Sscottl#include <dev/pms/RefTisa/sallsdk/api/saosapi.h>
35285809Sscottl
36285809Sscottl#include <dev/pms/RefTisa/sat/api/sm.h>
37285809Sscottl#include <dev/pms/RefTisa/sat/api/smapi.h>
38285809Sscottl#include <dev/pms/RefTisa/sat/api/tdsmapi.h>
39285809Sscottl
40285809Sscottl#include <dev/pms/RefTisa/sat/src/smdefs.h>
41285809Sscottl#include <dev/pms/RefTisa/sat/src/smproto.h>
42285809Sscottl#include <dev/pms/RefTisa/sat/src/smtypes.h>
43285809Sscottl
44285809Sscottl/*
45285809Sscottl * This table is used to map LL Layer saSATAStart() status to TISA status.
46285809Sscottl */
47285809Sscottl
48285809Sscottl
49285809SscottlFORCEINLINE bit32
50285809SscottlsmsataLLIOStart(
51285809Sscottl                smRoot_t                  *smRoot,
52285809Sscottl                smIORequest_t             *smIORequest,
53285809Sscottl                smDeviceHandle_t          *smDeviceHandle,
54285809Sscottl                smScsiInitiatorRequest_t  *smScsiRequest,
55285809Sscottl                smSatIOContext_t          *satIOContext
56285809Sscottl               )
57285809Sscottl{
58285809Sscottl  smDeviceData_t              *oneDeviceData  = (smDeviceData_t *)smDeviceHandle->smData;
59285809Sscottl  smIntRoot_t                 *smIntRoot      = (smIntRoot_t *) smRoot->smData;
60285809Sscottl  smIntContext_t              *smAllShared    = (smIntContext_t *)&(smIntRoot->smAllShared);
61285809Sscottl  smIORequestBody_t           *smIORequestBody = (smIORequestBody_t *)satIOContext->smRequestBody;
62285809Sscottl  smDeviceData_t              *pSatDevData   = satIOContext->pSatDevData;
63285809Sscottl  smSatInternalIo_t           *satIntIo      = satIOContext->satIntIoContext;
64285809Sscottl  agsaRoot_t                  *agRoot        = smAllShared->agRoot;
65285809Sscottl  agsaIORequest_t             *agIORequest   = &(smIORequestBody->agIORequest);
66285809Sscottl  agsaDevHandle_t             *agDevHandle   = oneDeviceData->agDevHandle;
67285809Sscottl  agsaSATAInitiatorRequest_t  *agSATAReq     = &(smIORequestBody->transport.SATA.agSATARequestBody);
68285809Sscottl  bit32                       RLERecovery    = agFALSE;
69285809Sscottl  bit32                       status         = SM_RC_FAILURE;
70285809Sscottl  bit32                       nQNumber       = 0;
71285809Sscottl  /*
72285809Sscottl   * If this is a super I/O request, check for optional settings.
73285809Sscottl   * Be careful. Use the superRequest pointer for all references
74285809Sscottl   * in this block of code.
75285809Sscottl   */
76285809Sscottl  agSATAReq->option = 0;
77285809Sscottl  if (satIOContext->superIOFlag)
78285809Sscottl  {
79285809Sscottl    smSuperScsiInitiatorRequest_t *superRequest = (smSuperScsiInitiatorRequest_t *) smScsiRequest;
80285809Sscottl
81285809Sscottl    if (superRequest->flags & SM_SCSI_INITIATOR_ENCRYPT)
82285809Sscottl    {
83285809Sscottl      /* Copy all of the relevant encrypt information  */
84285809Sscottl      agSATAReq->option |= AGSA_SATA_ENABLE_ENCRYPTION;
85285809Sscottl      sm_memcpy(&agSATAReq->encrypt, &superRequest->Encrypt, sizeof(agsaEncrypt_t));
86285809Sscottl    }
87285809Sscottl    {
88285809Sscottl      /* initialize expDataLength */
89285809Sscottl      if (satIOContext->reqType == AGSA_SATA_PROTOCOL_NON_DATA ||
90285809Sscottl          satIOContext->reqType == AGSA_SATA_PROTOCOL_SRST_ASSERT ||
91285809Sscottl          satIOContext->reqType == AGSA_SATA_PROTOCOL_SRST_DEASSERT )
92285809Sscottl      {
93285809Sscottl        smIORequestBody->IOType.InitiatorRegIO.expDataLength = 0;
94285809Sscottl      }
95285809Sscottl      else
96285809Sscottl      {
97285809Sscottl        smIORequestBody->IOType.InitiatorRegIO.expDataLength = smScsiRequest->scsiCmnd.expDataLength;
98285809Sscottl      }
99285809Sscottl
100285809Sscottl      agSATAReq->dataLength = smIORequestBody->IOType.InitiatorRegIO.expDataLength;
101285809Sscottl    }
102285809Sscottl  }
103285809Sscottl  else
104285809Sscottl  {
105285809Sscottl    /* initialize expDataLength */
106285809Sscottl    if (satIOContext->reqType == AGSA_SATA_PROTOCOL_NON_DATA ||
107285809Sscottl        satIOContext->reqType == AGSA_SATA_PROTOCOL_SRST_ASSERT ||
108285809Sscottl        satIOContext->reqType == AGSA_SATA_PROTOCOL_SRST_DEASSERT )
109285809Sscottl    {
110285809Sscottl      smIORequestBody->IOType.InitiatorRegIO.expDataLength = 0;
111285809Sscottl    }
112285809Sscottl    else
113285809Sscottl    {
114285809Sscottl      smIORequestBody->IOType.InitiatorRegIO.expDataLength = smScsiRequest->scsiCmnd.expDataLength;
115285809Sscottl    }
116285809Sscottl
117285809Sscottl    agSATAReq->dataLength = smIORequestBody->IOType.InitiatorRegIO.expDataLength;
118285809Sscottl  }
119285809Sscottl
120285809Sscottl  if ( (pSatDevData->satDriveState == SAT_DEV_STATE_IN_RECOVERY) &&
121285809Sscottl       (satIOContext->pFis->h.command == SAT_READ_LOG_EXT) )
122285809Sscottl  {
123285809Sscottl     RLERecovery = agTRUE;
124285809Sscottl  }
125285809Sscottl
126285809Sscottl  /* check max io, be sure to free */
127285809Sscottl  if ( (pSatDevData->satDriveState != SAT_DEV_STATE_IN_RECOVERY) ||
128285809Sscottl       (RLERecovery == agTRUE) )
129285809Sscottl  {
130285809Sscottl    if (RLERecovery == agFALSE) /* RLE is not checked against pending IO's */
131285809Sscottl    {
132285809Sscottl#ifdef CCFLAG_OPTIMIZE_SAT_LOCK
133285809Sscottl      bit32 volatile satPendingNCQIO = 0;
134285809Sscottl      bit32 volatile satPendingNONNCQIO = 0;
135285809Sscottl      bit32 volatile satPendingIO = 0;
136285809Sscottl
137285809Sscottl      tdsmInterlockedExchange(smRoot, &satPendingNCQIO, pSatDevData->satPendingNCQIO);
138285809Sscottl      tdsmInterlockedExchange(smRoot, &satPendingNONNCQIO, pSatDevData->satPendingNONNCQIO);
139285809Sscottl      tdsmInterlockedExchange(smRoot, &satPendingIO, pSatDevData->satPendingIO);
140285809Sscottl#endif
141285809Sscottl
142285809Sscottl      if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_WRITE) ||
143285809Sscottl           (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_READ) )
144285809Sscottl      {
145285809Sscottl      #ifdef CCFLAG_OPTIMIZE_SAT_LOCK
146285809Sscottl        if ( satPendingNCQIO >= pSatDevData->satNCQMaxIO ||
147285809Sscottl             satPendingNONNCQIO != 0)
148285809Sscottl        {
149285809Sscottl          SM_DBG1(("smsataLLIOStart: 1st busy did %d!!!\n", pSatDevData->id));
150285809Sscottl          SM_DBG1(("smsataLLIOStart: 1st busy NCQ. NCQ Pending 0x%x NONNCQ Pending 0x%x All Pending 0x%x!!!\n", satPendingNCQIO,
151285809Sscottl                    satPendingNONNCQIO, satPendingIO));
152285809Sscottl          /* free resource */
153285809Sscottl          smsatFreeIntIoResource( smRoot,
154285809Sscottl                                  pSatDevData,
155285809Sscottl                                  satIntIo);
156285809Sscottl          return SM_RC_DEVICE_BUSY;
157285809Sscottl        }
158285809Sscottl      #else
159285809Sscottl        tdsmSingleThreadedEnter(smRoot, SM_EXTERNAL_IO_LOCK);
160285809Sscottl        if (pSatDevData->satPendingNCQIO >= pSatDevData->satNCQMaxIO ||
161285809Sscottl            pSatDevData->satPendingNONNCQIO != 0)
162285809Sscottl        {
163285809Sscottl          SM_DBG1(("smsataLLIOStart: 1st busy did %d!!!\n", pSatDevData->id));
164285809Sscottl          SM_DBG1(("smsataLLIOStart: 1st busy NCQ. NCQ Pending 0x%x NONNCQ Pending 0x%x All Pending 0x%x!!!\n", pSatDevData->satPendingNCQIO,
165285809Sscottl                    pSatDevData->satPendingNONNCQIO, pSatDevData->satPendingIO));
166285809Sscottl          tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
167285809Sscottl          /* free resource */
168285809Sscottl          smsatFreeIntIoResource( smRoot,
169285809Sscottl                                  pSatDevData,
170285809Sscottl                                  satIntIo);
171285809Sscottl          return SM_RC_DEVICE_BUSY;
172285809Sscottl        }
173285809Sscottl        tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
174285809Sscottl      #endif
175285809Sscottl
176285809Sscottl      }
177285809Sscottl      else if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_D2H_PKT) ||
178285809Sscottl                (satIOContext->reqType == AGSA_SATA_PROTOCOL_H2D_PKT) ||
179285809Sscottl                (satIOContext->reqType == AGSA_SATA_PROTOCOL_NON_PKT) )
180285809Sscottl      {
181285809Sscottl        sm_memcpy(agSATAReq->scsiCDB, smScsiRequest->scsiCmnd.cdb, 16);
182285809Sscottl      #ifdef CCFLAG_OPTIMIZE_SAT_LOCK
183285809Sscottl        if ( satPendingNONNCQIO >= SAT_APAPI_CMDQ_MAX ||
184285809Sscottl             satPendingNCQIO != 0)
185285809Sscottl        {
186285809Sscottl          SM_DBG1(("smsataLLIOStart: ATAPI busy did %d!!!\n", pSatDevData->id));
187285809Sscottl          SM_DBG1(("smsataLLIOStart: ATAPI busy NON-NCQ. NCQ Pending 0x%x NON-NCQ Pending 0x%x All Pending 0x%x!!!\n", satPendingNCQIO,
188285809Sscottl                    satPendingNONNCQIO, satPendingIO));
189285809Sscottl          /* free resource */
190285809Sscottl          smsatFreeIntIoResource( smRoot,
191285809Sscottl                                  pSatDevData,
192285809Sscottl                                  satIntIo);
193285809Sscottl          return SM_RC_DEVICE_BUSY;
194285809Sscottl        }
195285809Sscottl      #else
196285809Sscottl        tdsmSingleThreadedEnter(smRoot, SM_EXTERNAL_IO_LOCK);
197285809Sscottl        if ( pSatDevData->satPendingNONNCQIO >= SAT_APAPI_CMDQ_MAX ||
198285809Sscottl             pSatDevData->satPendingNCQIO != 0)
199285809Sscottl        {
200285809Sscottl          SM_DBG1(("smsataLLIOStart: ATAPI busy did %d!!!\n", pSatDevData->id));
201285809Sscottl          SM_DBG1(("smsataLLIOStart: ATAPI busy NON-NCQ. NCQ Pending 0x%x NON-NCQ Pending 0x%x All Pending 0x%x!!!\n", pSatDevData->satPendingNCQIO,
202285809Sscottl                    pSatDevData->satPendingNONNCQIO, pSatDevData->satPendingIO));
203285809Sscottl          tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
204285809Sscottl          /* free resource */
205285809Sscottl          smsatFreeIntIoResource( smRoot,
206285809Sscottl                                  pSatDevData,
207285809Sscottl                                  satIntIo);
208285809Sscottl          return SM_RC_DEVICE_BUSY;
209285809Sscottl        }
210285809Sscottl        tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
211285809Sscottl      #endif
212285809Sscottl
213285809Sscottl      }
214285809Sscottl      else
215285809Sscottl      {
216285809Sscottl#ifdef CCFLAG_OPTIMIZE_SAT_LOCK
217285809Sscottl        if ( satPendingNONNCQIO >= SAT_NONNCQ_MAX ||
218285809Sscottl             satPendingNCQIO != 0)
219285809Sscottl        {
220285809Sscottl          SM_DBG1(("smsataLLIOStart: 2nd busy did %d!!!\n", pSatDevData->id));
221285809Sscottl          SM_DBG1(("smsataLLIOStart: 2nd busy NCQ. NCQ Pending 0x%x NONNCQ Pending 0x%x All Pending 0x%x!!!\n", satPendingNCQIO,
222285809Sscottl                    satPendingNONNCQIO, satPendingIO));
223285809Sscottl          /* free resource */
224285809Sscottl          smsatFreeIntIoResource( smRoot,
225285809Sscottl                                  pSatDevData,
226285809Sscottl                                  satIntIo);
227285809Sscottl          return SM_RC_DEVICE_BUSY;
228285809Sscottl        }
229285809Sscottl#else
230285809Sscottl        tdsmSingleThreadedEnter(smRoot, SM_EXTERNAL_IO_LOCK);
231285809Sscottl        if (pSatDevData->satPendingNONNCQIO >= SAT_NONNCQ_MAX ||
232285809Sscottl            pSatDevData->satPendingNCQIO != 0)
233285809Sscottl        {
234285809Sscottl          SM_DBG1(("smsataLLIOStart: 2nd busy did %d!!!\n", pSatDevData->id));
235285809Sscottl          SM_DBG1(("smsataLLIOStart: 2nd busy NCQ. NCQ Pending 0x%x NONNCQ Pending 0x%x All Pending 0x%x!!!\n", pSatDevData->satPendingNCQIO,
236285809Sscottl                    pSatDevData->satPendingNONNCQIO, pSatDevData->satPendingIO));
237285809Sscottl          tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
238285809Sscottl          /* free resource */
239285809Sscottl          smsatFreeIntIoResource( smRoot,
240285809Sscottl                                  pSatDevData,
241285809Sscottl                                  satIntIo);
242285809Sscottl          return SM_RC_DEVICE_BUSY;
243285809Sscottl        }
244285809Sscottl        tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
245285809Sscottl#endif
246285809Sscottl      }
247285809Sscottl    } /* RLE */
248285809Sscottl    /* for internal SATA command only */
249285809Sscottl    if (satIOContext->satOrgIOContext != agNULL)
250285809Sscottl    {
251285809Sscottl      /* Initialize tiIORequest */
252285809Sscottl      smIORequestBody->smIORequest = smIORequest;
253285809Sscottl      if (smIORequest == agNULL)
254285809Sscottl      {
255285809Sscottl        SM_DBG1(("smsataLLIOStart: 1 check!!!\n"));
256285809Sscottl      }
257285809Sscottl    }
258285809Sscottl    /* Initialize tiDevhandle */
259285809Sscottl    smIORequestBody->smDevHandle = smDeviceHandle;
260285809Sscottl
261285809Sscottl    /* Initializes Scatter Gather and ESGL */
262285809Sscottl    status = smsatIOPrepareSGL( smRoot,
263285809Sscottl                                smIORequestBody,
264285809Sscottl                                &smScsiRequest->smSgl1,
265285809Sscottl                                smScsiRequest->sglVirtualAddr );
266285809Sscottl
267285809Sscottl    if (status != SM_RC_SUCCESS)
268285809Sscottl    {
269285809Sscottl      SM_DBG1(("smsataLLIOStart: can't get SGL!!!\n"));
270285809Sscottl      /* free resource */
271285809Sscottl      smsatFreeIntIoResource( smRoot,
272285809Sscottl                              pSatDevData,
273285809Sscottl                              satIntIo);
274285809Sscottl      return status;
275285809Sscottl    }
276285809Sscottl
277285809Sscottl    /* Initialize LL Layer agIORequest */
278285809Sscottl    agIORequest->osData = (void *) smIORequestBody;
279285809Sscottl    agIORequest->sdkData = agNULL; /* SA takes care of this */
280285809Sscottl
281285809Sscottl    smIORequestBody->ioStarted = agTRUE;
282285809Sscottl    smIORequestBody->ioCompleted = agFALSE;
283285809Sscottl
284285809Sscottl    /* assign tag value for SATA */
285285809Sscottl    if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_WRITE) ||
286285809Sscottl         (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_READ) )
287285809Sscottl    {
288285809Sscottl      if (agFALSE == smsatTagAlloc(smRoot, pSatDevData, &satIOContext->sataTag))
289285809Sscottl      {
290285809Sscottl        SM_DBG1(("smsataLLIOStart: No more NCQ tag!!!\n"));
291285809Sscottl        smIORequestBody->ioStarted = agFALSE;
292285809Sscottl        smIORequestBody->ioCompleted = agTRUE;
293285809Sscottl        return SM_RC_DEVICE_BUSY;
294285809Sscottl      }
295285809Sscottl      SM_DBG3(("smsataLLIOStart: ncq tag 0x%x\n",satIOContext->sataTag));
296285809Sscottl    }
297285809Sscottl    else
298285809Sscottl    {
299285809Sscottl      satIOContext->sataTag = 0xFF;
300285809Sscottl    }
301285809Sscottl  }
302285809Sscottl  else /* AGSA_SATA_PROTOCOL_SRST_ASSERT or AGSA_SATA_PROTOCOL_SRST_DEASSERT
303285809Sscottl          or SAT_CHECK_POWER_MODE as ABORT */
304285809Sscottl  {
305285809Sscottl    agsaSgl_t          *agSgl;
306285809Sscottl
307285809Sscottl    /* for internal SATA command only */
308285809Sscottl    if (satIOContext->satOrgIOContext != agNULL)
309285809Sscottl    {
310285809Sscottl      /* Initialize tiIORequest */
311285809Sscottl      smIORequestBody->smIORequest = smIORequest;
312285809Sscottl      if (smIORequest == agNULL)
313285809Sscottl      {
314285809Sscottl        SM_DBG1(("smsataLLIOStart: 2 check!!!\n"));
315285809Sscottl      }
316285809Sscottl    }
317285809Sscottl    /* Initialize tiDevhandle */
318285809Sscottl    smIORequestBody->smDevHandle = smDeviceHandle;
319285809Sscottl
320285809Sscottl
321285809Sscottl    smIORequestBody->IOType.InitiatorRegIO.expDataLength = 0;
322285809Sscottl    /* SGL for SATA request */
323285809Sscottl    agSgl = &(smIORequestBody->transport.SATA.agSATARequestBody.agSgl);
324285809Sscottl    agSgl->len = 0;
325285809Sscottl
326285809Sscottl    agSgl->sgUpper = 0;
327285809Sscottl    agSgl->sgLower = 0;
328285809Sscottl    agSgl->len = 0;
329285809Sscottl    SM_CLEAR_ESGL_EXTEND(agSgl->extReserved);
330285809Sscottl
331285809Sscottl    /* Initialize LL Layer agIORequest */
332285809Sscottl    agIORequest = &(smIORequestBody->agIORequest);
333285809Sscottl    agIORequest->osData = (void *) smIORequestBody;
334285809Sscottl    agIORequest->sdkData = agNULL; /* SA takes care of this */
335285809Sscottl
336285809Sscottl    smIORequestBody->ioStarted = agTRUE;
337285809Sscottl    smIORequestBody->ioCompleted = agFALSE;
338285809Sscottl
339285809Sscottl    /* setting the data length */
340285809Sscottl    agSATAReq->dataLength = 0;
341285809Sscottl
342285809Sscottl  }
343285809Sscottl
344285809Sscottl
345285809Sscottl  smIORequestBody->reTries = 0;
346285809Sscottl
347285809Sscottl#ifdef TD_INTERNAL_DEBUG
348285809Sscottl  smhexdump("smsataLLIOStart", (bit8 *)satIOContext->pFis, sizeof(agsaFisRegHostToDevice_t));
349285809Sscottl  smhexdump("smsataLLIOStart LL", (bit8 *)&agSATAReq->fis.fisRegHostToDev,
350285809Sscottl            sizeof(agsaFisRegHostToDevice_t));
351285809Sscottl#endif
352285809Sscottl
353285809Sscottl  SM_DBG6(("smsataLLIOStart: agDevHandle %p\n", agDevHandle));
354285809Sscottl
355285809Sscottl  /* to get better IO performance, rotate the OBQ number on main IO path */
356285809Sscottl  if (smScsiRequest == agNULL)
357285809Sscottl  {
358285809Sscottl    nQNumber = 0;
359285809Sscottl  }
360285809Sscottl  else
361285809Sscottl  {
362285809Sscottl    switch (smScsiRequest->scsiCmnd.cdb[0])
363285809Sscottl    {
364285809Sscottl      case SCSIOPC_READ_10:
365285809Sscottl      case SCSIOPC_WRITE_10:
366285809Sscottl      case SCSIOPC_READ_6:
367285809Sscottl      case SCSIOPC_WRITE_6:
368285809Sscottl      case SCSIOPC_READ_12:
369285809Sscottl      case SCSIOPC_WRITE_12:
370285809Sscottl      case SCSIOPC_READ_16:
371285809Sscottl      case SCSIOPC_WRITE_16:
372285809Sscottl         nQNumber = tdsmRotateQnumber(smRoot, smDeviceHandle);
373285809Sscottl         break;
374285809Sscottl
375285809Sscottl      default:
376285809Sscottl         nQNumber = 0;
377285809Sscottl         break;
378285809Sscottl    }
379285809Sscottl  }
380285809Sscottl
381285809Sscottl  SM_DBG3(("sataLLIOStart: Lock in\n"));
382285809Sscottl
383285809Sscottl#ifdef CCFLAG_OPTIMIZE_SAT_LOCK
384285809Sscottl  if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_WRITE) ||
385285809Sscottl       (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_READ) )
386285809Sscottl  {
387285809Sscottl     tdsmInterlockedIncrement(smRoot,&pSatDevData->satPendingNCQIO);
388285809Sscottl  }
389285809Sscottl  else
390285809Sscottl  {
391285809Sscottl     tdsmInterlockedIncrement(smRoot,&pSatDevData->satPendingNONNCQIO);
392285809Sscottl  }
393285809Sscottl  tdsmInterlockedIncrement(smRoot,&pSatDevData->satPendingIO);
394285809Sscottl#else
395285809Sscottl  tdsmSingleThreadedEnter(smRoot, SM_EXTERNAL_IO_LOCK);
396285809Sscottl  if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_WRITE) ||
397285809Sscottl       (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_READ) )
398285809Sscottl  {
399285809Sscottl     pSatDevData->satPendingNCQIO++;
400285809Sscottl  }
401285809Sscottl  else
402285809Sscottl  {
403285809Sscottl     pSatDevData->satPendingNONNCQIO++;
404285809Sscottl  }
405285809Sscottl  pSatDevData->satPendingIO++;
406285809Sscottl
407285809Sscottl  SMLIST_INIT_ELEMENT (&satIOContext->satIoContextLink);
408285809Sscottl  SMLIST_ENQUEUE_AT_TAIL (&satIOContext->satIoContextLink, &pSatDevData->satIoLinkList);
409285809Sscottl  tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
410285809Sscottl#endif
411285809Sscottl  /* post SATA command to low level MPI */
412285809Sscottl  status = saSATAStart( agRoot,
413285809Sscottl                        agIORequest,
414285809Sscottl                        nQNumber,
415285809Sscottl                        agDevHandle,
416285809Sscottl                        satIOContext->reqType,
417285809Sscottl                        agSATAReq,
418285809Sscottl                        satIOContext->sataTag,
419285809Sscottl                        smllSATACompleted
420285809Sscottl                        );
421285809Sscottl
422285809Sscottl  if (status != AGSA_RC_SUCCESS)
423285809Sscottl  {
424285809Sscottl    if (status == AGSA_RC_BUSY)
425285809Sscottl    {
426285809Sscottl      SM_DBG1(("smsataLLIOStart: saSATAStart busy!!!\n"));
427285809Sscottl      status = SM_RC_BUSY;
428285809Sscottl    }
429285809Sscottl    else
430285809Sscottl    {
431285809Sscottl      SM_DBG1(("smsataLLIOStart: saSATAStart failed!!!\n"));
432285809Sscottl      status = SM_RC_FAILURE;
433285809Sscottl    }
434285809Sscottl
435285809Sscottl    if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_WRITE) ||
436285809Sscottl         (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_READ) )
437285809Sscottl    {
438285809Sscottl      smsatTagRelease(smRoot, pSatDevData, satIOContext->sataTag);
439285809Sscottl    }
440285809Sscottl
441285809Sscottl#ifdef CCFLAG_OPTIMIZE_SAT_LOCK
442285809Sscottl    if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_WRITE) ||
443285809Sscottl         (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_READ) )
444285809Sscottl    {
445285809Sscottl      tdsmInterlockedDecrement(smRoot,&oneDeviceData->satPendingNCQIO);
446285809Sscottl    }
447285809Sscottl    else
448285809Sscottl    {
449285809Sscottl      tdsmInterlockedDecrement(smRoot,&oneDeviceData->satPendingNONNCQIO);
450285809Sscottl    }
451285809Sscottl    tdsmInterlockedDecrement(smRoot,&oneDeviceData->satPendingIO);
452285809Sscottl#else
453285809Sscottl    if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_WRITE) ||
454285809Sscottl         (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_READ) )
455285809Sscottl    {
456285809Sscottl      tdsmSingleThreadedEnter(smRoot, SM_EXTERNAL_IO_LOCK);
457285809Sscottl      oneDeviceData->satPendingNCQIO--;
458285809Sscottl      oneDeviceData->satPendingIO--;
459285809Sscottl      SMLIST_DEQUEUE_THIS (&satIOContext->satIoContextLink);
460285809Sscottl      tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
461285809Sscottl    }
462285809Sscottl    else
463285809Sscottl    {
464285809Sscottl      tdsmSingleThreadedEnter(smRoot, SM_EXTERNAL_IO_LOCK);
465285809Sscottl      oneDeviceData->satPendingNONNCQIO--;
466285809Sscottl      oneDeviceData->satPendingIO--;
467285809Sscottl      SMLIST_DEQUEUE_THIS (&satIOContext->satIoContextLink);
468285809Sscottl      tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
469285809Sscottl    }
470285809Sscottl#endif /* CCFLAG_OPTIMIZE_SAT_LOCK */
471285809Sscottl
472285809Sscottl    /* Free the ESGL pages associated with this I/O */
473285809Sscottl    smIORequestBody->ioStarted = agFALSE;
474285809Sscottl    smIORequestBody->ioCompleted = agTRUE;
475285809Sscottl    return (status);
476285809Sscottl  }
477285809Sscottl
478285809Sscottl  return SM_RC_SUCCESS;
479285809Sscottl}
480285809Sscottl
481285809Sscottl
482285809SscottlosGLOBAL FORCEINLINE bit32
483285809SscottlsmsatIOPrepareSGL(
484285809Sscottl                  smRoot_t                 *smRoot,
485285809Sscottl                  smIORequestBody_t        *smIORequestBody,
486285809Sscottl                  smSgl_t                  *smSgl1,
487285809Sscottl                  void                     *sglVirtualAddr
488285809Sscottl                  )
489285809Sscottl{
490285809Sscottl  agsaSgl_t          *agSgl;
491285809Sscottl
492285809Sscottl  /* Uppper should be zero-out */
493285809Sscottl  SM_DBG5(("smsatIOPrepareSGL: start\n"));
494285809Sscottl
495285809Sscottl  SM_DBG5(("smsatIOPrepareSGL: smSgl1->upper %d smSgl1->lower %d smSgl1->len %d\n",
496285809Sscottl    smSgl1->upper, smSgl1->lower, smSgl1->len));
497285809Sscottl  SM_DBG5(("smsatIOPrepareSGL: smSgl1->type %d\n", smSgl1->type));
498285809Sscottl
499285809Sscottl  /* SGL for SATA request */
500285809Sscottl  agSgl = &(smIORequestBody->transport.SATA.agSATARequestBody.agSgl);
501285809Sscottl  agSgl->len = 0;
502285809Sscottl
503285809Sscottl  if (smSgl1 == agNULL)
504285809Sscottl  {
505285809Sscottl    SM_DBG1(("smsatIOPrepareSGL: Error smSgl1 is NULL!!!\n"));
506285809Sscottl    return tiError;
507285809Sscottl  }
508285809Sscottl
509285809Sscottl  if (smIORequestBody->IOType.InitiatorRegIO.expDataLength == 0)
510285809Sscottl  {
511285809Sscottl    SM_DBG3(("smsatIOPrepareSGL: expDataLength is 0\n"));
512285809Sscottl    agSgl->sgUpper = 0;
513285809Sscottl    agSgl->sgLower = 0;
514285809Sscottl    agSgl->len = 0;
515285809Sscottl    SM_CLEAR_ESGL_EXTEND(agSgl->extReserved);
516285809Sscottl    return SM_RC_SUCCESS;
517285809Sscottl  }
518285809Sscottl
519285809Sscottl  agSgl->sgUpper = smSgl1->upper;
520285809Sscottl  agSgl->sgLower = smSgl1->lower;
521285809Sscottl  agSgl->len = smSgl1->len;
522285809Sscottl  agSgl->extReserved = smSgl1->type;
523285809Sscottl
524285809Sscottl  return SM_RC_SUCCESS;
525285809Sscottl
526285809Sscottl}
527285809Sscottl
528285809Sscottl
529285809Sscottl
530285809Sscottl
531