xref: /freebsd/sys/dev/pms/RefTisa/sat/src/smsathw.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
1*4e1bc9a0SAchim Leubner /*******************************************************************************
2*4e1bc9a0SAchim Leubner *Copyright (c) 2014 PMC-Sierra, Inc.  All rights reserved.
3*4e1bc9a0SAchim Leubner *
4*4e1bc9a0SAchim Leubner *Redistribution and use in source and binary forms, with or without modification, are permitted provided
5*4e1bc9a0SAchim Leubner *that the following conditions are met:
6*4e1bc9a0SAchim Leubner *1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
7*4e1bc9a0SAchim Leubner *following disclaimer.
8*4e1bc9a0SAchim Leubner *2. Redistributions in binary form must reproduce the above copyright notice,
9*4e1bc9a0SAchim Leubner *this list of conditions and the following disclaimer in the documentation and/or other materials provided
10*4e1bc9a0SAchim Leubner *with the distribution.
11*4e1bc9a0SAchim Leubner *
12*4e1bc9a0SAchim Leubner *THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
13*4e1bc9a0SAchim Leubner *WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
14*4e1bc9a0SAchim Leubner *FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
15*4e1bc9a0SAchim Leubner *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
16*4e1bc9a0SAchim Leubner *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
17*4e1bc9a0SAchim Leubner *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18*4e1bc9a0SAchim Leubner *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
19*4e1bc9a0SAchim Leubner *SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
20*4e1bc9a0SAchim Leubner 
21*4e1bc9a0SAchim Leubner ********************************************************************************/
22*4e1bc9a0SAchim Leubner #include <sys/cdefs.h>
23*4e1bc9a0SAchim Leubner #include <dev/pms/config.h>
24*4e1bc9a0SAchim Leubner 
25*4e1bc9a0SAchim Leubner #include <dev/pms/freebsd/driver/common/osenv.h>
26*4e1bc9a0SAchim Leubner #include <dev/pms/freebsd/driver/common/ostypes.h>
27*4e1bc9a0SAchim Leubner #include <dev/pms/freebsd/driver/common/osdebug.h>
28*4e1bc9a0SAchim Leubner 
29*4e1bc9a0SAchim Leubner #include <dev/pms/RefTisa/tisa/api/titypes.h>
30*4e1bc9a0SAchim Leubner 
31*4e1bc9a0SAchim Leubner #include <dev/pms/RefTisa/sallsdk/api/sa.h>
32*4e1bc9a0SAchim Leubner #include <dev/pms/RefTisa/sallsdk/api/saapi.h>
33*4e1bc9a0SAchim Leubner #include <dev/pms/RefTisa/sallsdk/api/saosapi.h>
34*4e1bc9a0SAchim Leubner 
35*4e1bc9a0SAchim Leubner #include <dev/pms/RefTisa/sat/api/sm.h>
36*4e1bc9a0SAchim Leubner #include <dev/pms/RefTisa/sat/api/smapi.h>
37*4e1bc9a0SAchim Leubner #include <dev/pms/RefTisa/sat/api/tdsmapi.h>
38*4e1bc9a0SAchim Leubner 
39*4e1bc9a0SAchim Leubner #include <dev/pms/RefTisa/sat/src/smdefs.h>
40*4e1bc9a0SAchim Leubner #include <dev/pms/RefTisa/sat/src/smproto.h>
41*4e1bc9a0SAchim Leubner #include <dev/pms/RefTisa/sat/src/smtypes.h>
42*4e1bc9a0SAchim Leubner 
43*4e1bc9a0SAchim Leubner /*
44*4e1bc9a0SAchim Leubner  * This table is used to map LL Layer saSATAStart() status to TISA status.
45*4e1bc9a0SAchim Leubner  */
46*4e1bc9a0SAchim Leubner 
47*4e1bc9a0SAchim Leubner 
48*4e1bc9a0SAchim Leubner FORCEINLINE bit32
smsataLLIOStart(smRoot_t * smRoot,smIORequest_t * smIORequest,smDeviceHandle_t * smDeviceHandle,smScsiInitiatorRequest_t * smScsiRequest,smSatIOContext_t * satIOContext)49*4e1bc9a0SAchim Leubner smsataLLIOStart(
50*4e1bc9a0SAchim Leubner                 smRoot_t                  *smRoot,
51*4e1bc9a0SAchim Leubner                 smIORequest_t             *smIORequest,
52*4e1bc9a0SAchim Leubner                 smDeviceHandle_t          *smDeviceHandle,
53*4e1bc9a0SAchim Leubner                 smScsiInitiatorRequest_t  *smScsiRequest,
54*4e1bc9a0SAchim Leubner                 smSatIOContext_t          *satIOContext
55*4e1bc9a0SAchim Leubner                )
56*4e1bc9a0SAchim Leubner {
57*4e1bc9a0SAchim Leubner   smDeviceData_t              *oneDeviceData  = (smDeviceData_t *)smDeviceHandle->smData;
58*4e1bc9a0SAchim Leubner   smIntRoot_t                 *smIntRoot      = (smIntRoot_t *) smRoot->smData;
59*4e1bc9a0SAchim Leubner   smIntContext_t              *smAllShared    = (smIntContext_t *)&(smIntRoot->smAllShared);
60*4e1bc9a0SAchim Leubner   smIORequestBody_t           *smIORequestBody = (smIORequestBody_t *)satIOContext->smRequestBody;
61*4e1bc9a0SAchim Leubner   smDeviceData_t              *pSatDevData   = satIOContext->pSatDevData;
62*4e1bc9a0SAchim Leubner   smSatInternalIo_t           *satIntIo      = satIOContext->satIntIoContext;
63*4e1bc9a0SAchim Leubner   agsaRoot_t                  *agRoot        = smAllShared->agRoot;
64*4e1bc9a0SAchim Leubner   agsaIORequest_t             *agIORequest   = &(smIORequestBody->agIORequest);
65*4e1bc9a0SAchim Leubner   agsaDevHandle_t             *agDevHandle   = oneDeviceData->agDevHandle;
66*4e1bc9a0SAchim Leubner   agsaSATAInitiatorRequest_t  *agSATAReq     = &(smIORequestBody->transport.SATA.agSATARequestBody);
67*4e1bc9a0SAchim Leubner   bit32                       RLERecovery    = agFALSE;
68*4e1bc9a0SAchim Leubner   bit32                       status         = SM_RC_FAILURE;
69*4e1bc9a0SAchim Leubner   bit32                       nQNumber       = 0;
70*4e1bc9a0SAchim Leubner   /*
71*4e1bc9a0SAchim Leubner    * If this is a super I/O request, check for optional settings.
72*4e1bc9a0SAchim Leubner    * Be careful. Use the superRequest pointer for all references
73*4e1bc9a0SAchim Leubner    * in this block of code.
74*4e1bc9a0SAchim Leubner    */
75*4e1bc9a0SAchim Leubner   agSATAReq->option = 0;
76*4e1bc9a0SAchim Leubner   if (satIOContext->superIOFlag)
77*4e1bc9a0SAchim Leubner   {
78*4e1bc9a0SAchim Leubner     smSuperScsiInitiatorRequest_t *superRequest = (smSuperScsiInitiatorRequest_t *) smScsiRequest;
79*4e1bc9a0SAchim Leubner 
80*4e1bc9a0SAchim Leubner     if (superRequest->flags & SM_SCSI_INITIATOR_ENCRYPT)
81*4e1bc9a0SAchim Leubner     {
82*4e1bc9a0SAchim Leubner       /* Copy all of the relevant encrypt information  */
83*4e1bc9a0SAchim Leubner       agSATAReq->option |= AGSA_SATA_ENABLE_ENCRYPTION;
84*4e1bc9a0SAchim Leubner       sm_memcpy(&agSATAReq->encrypt, &superRequest->Encrypt, sizeof(agsaEncrypt_t));
85*4e1bc9a0SAchim Leubner     }
86*4e1bc9a0SAchim Leubner     {
87*4e1bc9a0SAchim Leubner       /* initialize expDataLength */
88*4e1bc9a0SAchim Leubner       if (satIOContext->reqType == AGSA_SATA_PROTOCOL_NON_DATA ||
89*4e1bc9a0SAchim Leubner           satIOContext->reqType == AGSA_SATA_PROTOCOL_SRST_ASSERT ||
90*4e1bc9a0SAchim Leubner           satIOContext->reqType == AGSA_SATA_PROTOCOL_SRST_DEASSERT )
91*4e1bc9a0SAchim Leubner       {
92*4e1bc9a0SAchim Leubner         smIORequestBody->IOType.InitiatorRegIO.expDataLength = 0;
93*4e1bc9a0SAchim Leubner       }
94*4e1bc9a0SAchim Leubner       else
95*4e1bc9a0SAchim Leubner       {
96*4e1bc9a0SAchim Leubner         smIORequestBody->IOType.InitiatorRegIO.expDataLength = smScsiRequest->scsiCmnd.expDataLength;
97*4e1bc9a0SAchim Leubner       }
98*4e1bc9a0SAchim Leubner 
99*4e1bc9a0SAchim Leubner       agSATAReq->dataLength = smIORequestBody->IOType.InitiatorRegIO.expDataLength;
100*4e1bc9a0SAchim Leubner     }
101*4e1bc9a0SAchim Leubner   }
102*4e1bc9a0SAchim Leubner   else
103*4e1bc9a0SAchim Leubner   {
104*4e1bc9a0SAchim Leubner     /* initialize expDataLength */
105*4e1bc9a0SAchim Leubner     if (satIOContext->reqType == AGSA_SATA_PROTOCOL_NON_DATA ||
106*4e1bc9a0SAchim Leubner         satIOContext->reqType == AGSA_SATA_PROTOCOL_SRST_ASSERT ||
107*4e1bc9a0SAchim Leubner         satIOContext->reqType == AGSA_SATA_PROTOCOL_SRST_DEASSERT )
108*4e1bc9a0SAchim Leubner     {
109*4e1bc9a0SAchim Leubner       smIORequestBody->IOType.InitiatorRegIO.expDataLength = 0;
110*4e1bc9a0SAchim Leubner     }
111*4e1bc9a0SAchim Leubner     else
112*4e1bc9a0SAchim Leubner     {
113*4e1bc9a0SAchim Leubner       smIORequestBody->IOType.InitiatorRegIO.expDataLength = smScsiRequest->scsiCmnd.expDataLength;
114*4e1bc9a0SAchim Leubner     }
115*4e1bc9a0SAchim Leubner 
116*4e1bc9a0SAchim Leubner     agSATAReq->dataLength = smIORequestBody->IOType.InitiatorRegIO.expDataLength;
117*4e1bc9a0SAchim Leubner   }
118*4e1bc9a0SAchim Leubner 
119*4e1bc9a0SAchim Leubner   if ( (pSatDevData->satDriveState == SAT_DEV_STATE_IN_RECOVERY) &&
120*4e1bc9a0SAchim Leubner        (satIOContext->pFis->h.command == SAT_READ_LOG_EXT) )
121*4e1bc9a0SAchim Leubner   {
122*4e1bc9a0SAchim Leubner      RLERecovery = agTRUE;
123*4e1bc9a0SAchim Leubner   }
124*4e1bc9a0SAchim Leubner 
125*4e1bc9a0SAchim Leubner   /* check max io, be sure to free */
126*4e1bc9a0SAchim Leubner   if ( (pSatDevData->satDriveState != SAT_DEV_STATE_IN_RECOVERY) ||
127*4e1bc9a0SAchim Leubner        (RLERecovery == agTRUE) )
128*4e1bc9a0SAchim Leubner   {
129*4e1bc9a0SAchim Leubner     if (RLERecovery == agFALSE) /* RLE is not checked against pending IO's */
130*4e1bc9a0SAchim Leubner     {
131*4e1bc9a0SAchim Leubner #ifdef CCFLAG_OPTIMIZE_SAT_LOCK
132*4e1bc9a0SAchim Leubner       bit32 volatile satPendingNCQIO = 0;
133*4e1bc9a0SAchim Leubner       bit32 volatile satPendingNONNCQIO = 0;
134*4e1bc9a0SAchim Leubner       bit32 volatile satPendingIO = 0;
135*4e1bc9a0SAchim Leubner 
136*4e1bc9a0SAchim Leubner       tdsmInterlockedExchange(smRoot, &satPendingNCQIO, pSatDevData->satPendingNCQIO);
137*4e1bc9a0SAchim Leubner       tdsmInterlockedExchange(smRoot, &satPendingNONNCQIO, pSatDevData->satPendingNONNCQIO);
138*4e1bc9a0SAchim Leubner       tdsmInterlockedExchange(smRoot, &satPendingIO, pSatDevData->satPendingIO);
139*4e1bc9a0SAchim Leubner #endif
140*4e1bc9a0SAchim Leubner 
141*4e1bc9a0SAchim Leubner       if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_WRITE) ||
142*4e1bc9a0SAchim Leubner            (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_READ) )
143*4e1bc9a0SAchim Leubner       {
144*4e1bc9a0SAchim Leubner       #ifdef CCFLAG_OPTIMIZE_SAT_LOCK
145*4e1bc9a0SAchim Leubner         if ( satPendingNCQIO >= pSatDevData->satNCQMaxIO ||
146*4e1bc9a0SAchim Leubner              satPendingNONNCQIO != 0)
147*4e1bc9a0SAchim Leubner         {
148*4e1bc9a0SAchim Leubner           SM_DBG1(("smsataLLIOStart: 1st busy did %d!!!\n", pSatDevData->id));
149*4e1bc9a0SAchim Leubner           SM_DBG1(("smsataLLIOStart: 1st busy NCQ. NCQ Pending 0x%x NONNCQ Pending 0x%x All Pending 0x%x!!!\n", satPendingNCQIO,
150*4e1bc9a0SAchim Leubner                     satPendingNONNCQIO, satPendingIO));
151*4e1bc9a0SAchim Leubner           /* free resource */
152*4e1bc9a0SAchim Leubner           smsatFreeIntIoResource( smRoot,
153*4e1bc9a0SAchim Leubner                                   pSatDevData,
154*4e1bc9a0SAchim Leubner                                   satIntIo);
155*4e1bc9a0SAchim Leubner           return SM_RC_DEVICE_BUSY;
156*4e1bc9a0SAchim Leubner         }
157*4e1bc9a0SAchim Leubner       #else
158*4e1bc9a0SAchim Leubner         tdsmSingleThreadedEnter(smRoot, SM_EXTERNAL_IO_LOCK);
159*4e1bc9a0SAchim Leubner         if (pSatDevData->satPendingNCQIO >= pSatDevData->satNCQMaxIO ||
160*4e1bc9a0SAchim Leubner             pSatDevData->satPendingNONNCQIO != 0)
161*4e1bc9a0SAchim Leubner         {
162*4e1bc9a0SAchim Leubner           SM_DBG1(("smsataLLIOStart: 1st busy did %d!!!\n", pSatDevData->id));
163*4e1bc9a0SAchim Leubner           SM_DBG1(("smsataLLIOStart: 1st busy NCQ. NCQ Pending 0x%x NONNCQ Pending 0x%x All Pending 0x%x!!!\n", pSatDevData->satPendingNCQIO,
164*4e1bc9a0SAchim Leubner                     pSatDevData->satPendingNONNCQIO, pSatDevData->satPendingIO));
165*4e1bc9a0SAchim Leubner           tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
166*4e1bc9a0SAchim Leubner           /* free resource */
167*4e1bc9a0SAchim Leubner           smsatFreeIntIoResource( smRoot,
168*4e1bc9a0SAchim Leubner                                   pSatDevData,
169*4e1bc9a0SAchim Leubner                                   satIntIo);
170*4e1bc9a0SAchim Leubner           return SM_RC_DEVICE_BUSY;
171*4e1bc9a0SAchim Leubner         }
172*4e1bc9a0SAchim Leubner         tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
173*4e1bc9a0SAchim Leubner       #endif
174*4e1bc9a0SAchim Leubner 
175*4e1bc9a0SAchim Leubner       }
176*4e1bc9a0SAchim Leubner       else if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_D2H_PKT) ||
177*4e1bc9a0SAchim Leubner                 (satIOContext->reqType == AGSA_SATA_PROTOCOL_H2D_PKT) ||
178*4e1bc9a0SAchim Leubner                 (satIOContext->reqType == AGSA_SATA_PROTOCOL_NON_PKT) )
179*4e1bc9a0SAchim Leubner       {
180*4e1bc9a0SAchim Leubner         sm_memcpy(agSATAReq->scsiCDB, smScsiRequest->scsiCmnd.cdb, 16);
181*4e1bc9a0SAchim Leubner       #ifdef CCFLAG_OPTIMIZE_SAT_LOCK
182*4e1bc9a0SAchim Leubner         if ( satPendingNONNCQIO >= SAT_APAPI_CMDQ_MAX ||
183*4e1bc9a0SAchim Leubner              satPendingNCQIO != 0)
184*4e1bc9a0SAchim Leubner         {
185*4e1bc9a0SAchim Leubner           SM_DBG1(("smsataLLIOStart: ATAPI busy did %d!!!\n", pSatDevData->id));
186*4e1bc9a0SAchim Leubner           SM_DBG1(("smsataLLIOStart: ATAPI busy NON-NCQ. NCQ Pending 0x%x NON-NCQ Pending 0x%x All Pending 0x%x!!!\n", satPendingNCQIO,
187*4e1bc9a0SAchim Leubner                     satPendingNONNCQIO, satPendingIO));
188*4e1bc9a0SAchim Leubner           /* free resource */
189*4e1bc9a0SAchim Leubner           smsatFreeIntIoResource( smRoot,
190*4e1bc9a0SAchim Leubner                                   pSatDevData,
191*4e1bc9a0SAchim Leubner                                   satIntIo);
192*4e1bc9a0SAchim Leubner           return SM_RC_DEVICE_BUSY;
193*4e1bc9a0SAchim Leubner         }
194*4e1bc9a0SAchim Leubner       #else
195*4e1bc9a0SAchim Leubner         tdsmSingleThreadedEnter(smRoot, SM_EXTERNAL_IO_LOCK);
196*4e1bc9a0SAchim Leubner         if ( pSatDevData->satPendingNONNCQIO >= SAT_APAPI_CMDQ_MAX ||
197*4e1bc9a0SAchim Leubner              pSatDevData->satPendingNCQIO != 0)
198*4e1bc9a0SAchim Leubner         {
199*4e1bc9a0SAchim Leubner           SM_DBG1(("smsataLLIOStart: ATAPI busy did %d!!!\n", pSatDevData->id));
200*4e1bc9a0SAchim Leubner           SM_DBG1(("smsataLLIOStart: ATAPI busy NON-NCQ. NCQ Pending 0x%x NON-NCQ Pending 0x%x All Pending 0x%x!!!\n", pSatDevData->satPendingNCQIO,
201*4e1bc9a0SAchim Leubner                     pSatDevData->satPendingNONNCQIO, pSatDevData->satPendingIO));
202*4e1bc9a0SAchim Leubner           tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
203*4e1bc9a0SAchim Leubner           /* free resource */
204*4e1bc9a0SAchim Leubner           smsatFreeIntIoResource( smRoot,
205*4e1bc9a0SAchim Leubner                                   pSatDevData,
206*4e1bc9a0SAchim Leubner                                   satIntIo);
207*4e1bc9a0SAchim Leubner           return SM_RC_DEVICE_BUSY;
208*4e1bc9a0SAchim Leubner         }
209*4e1bc9a0SAchim Leubner         tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
210*4e1bc9a0SAchim Leubner       #endif
211*4e1bc9a0SAchim Leubner 
212*4e1bc9a0SAchim Leubner       }
213*4e1bc9a0SAchim Leubner       else
214*4e1bc9a0SAchim Leubner       {
215*4e1bc9a0SAchim Leubner #ifdef CCFLAG_OPTIMIZE_SAT_LOCK
216*4e1bc9a0SAchim Leubner         if ( satPendingNONNCQIO >= SAT_NONNCQ_MAX ||
217*4e1bc9a0SAchim Leubner              satPendingNCQIO != 0)
218*4e1bc9a0SAchim Leubner         {
219*4e1bc9a0SAchim Leubner           SM_DBG1(("smsataLLIOStart: 2nd busy did %d!!!\n", pSatDevData->id));
220*4e1bc9a0SAchim Leubner           SM_DBG1(("smsataLLIOStart: 2nd busy NCQ. NCQ Pending 0x%x NONNCQ Pending 0x%x All Pending 0x%x!!!\n", satPendingNCQIO,
221*4e1bc9a0SAchim Leubner                     satPendingNONNCQIO, satPendingIO));
222*4e1bc9a0SAchim Leubner           /* free resource */
223*4e1bc9a0SAchim Leubner           smsatFreeIntIoResource( smRoot,
224*4e1bc9a0SAchim Leubner                                   pSatDevData,
225*4e1bc9a0SAchim Leubner                                   satIntIo);
226*4e1bc9a0SAchim Leubner           return SM_RC_DEVICE_BUSY;
227*4e1bc9a0SAchim Leubner         }
228*4e1bc9a0SAchim Leubner #else
229*4e1bc9a0SAchim Leubner         tdsmSingleThreadedEnter(smRoot, SM_EXTERNAL_IO_LOCK);
230*4e1bc9a0SAchim Leubner         if (pSatDevData->satPendingNONNCQIO >= SAT_NONNCQ_MAX ||
231*4e1bc9a0SAchim Leubner             pSatDevData->satPendingNCQIO != 0)
232*4e1bc9a0SAchim Leubner         {
233*4e1bc9a0SAchim Leubner           SM_DBG1(("smsataLLIOStart: 2nd busy did %d!!!\n", pSatDevData->id));
234*4e1bc9a0SAchim Leubner           SM_DBG1(("smsataLLIOStart: 2nd busy NCQ. NCQ Pending 0x%x NONNCQ Pending 0x%x All Pending 0x%x!!!\n", pSatDevData->satPendingNCQIO,
235*4e1bc9a0SAchim Leubner                     pSatDevData->satPendingNONNCQIO, pSatDevData->satPendingIO));
236*4e1bc9a0SAchim Leubner           tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
237*4e1bc9a0SAchim Leubner           /* free resource */
238*4e1bc9a0SAchim Leubner           smsatFreeIntIoResource( smRoot,
239*4e1bc9a0SAchim Leubner                                   pSatDevData,
240*4e1bc9a0SAchim Leubner                                   satIntIo);
241*4e1bc9a0SAchim Leubner           return SM_RC_DEVICE_BUSY;
242*4e1bc9a0SAchim Leubner         }
243*4e1bc9a0SAchim Leubner         tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
244*4e1bc9a0SAchim Leubner #endif
245*4e1bc9a0SAchim Leubner       }
246*4e1bc9a0SAchim Leubner     } /* RLE */
247*4e1bc9a0SAchim Leubner     /* for internal SATA command only */
248*4e1bc9a0SAchim Leubner     if (satIOContext->satOrgIOContext != agNULL)
249*4e1bc9a0SAchim Leubner     {
250*4e1bc9a0SAchim Leubner       /* Initialize tiIORequest */
251*4e1bc9a0SAchim Leubner       smIORequestBody->smIORequest = smIORequest;
252*4e1bc9a0SAchim Leubner       if (smIORequest == agNULL)
253*4e1bc9a0SAchim Leubner       {
254*4e1bc9a0SAchim Leubner         SM_DBG1(("smsataLLIOStart: 1 check!!!\n"));
255*4e1bc9a0SAchim Leubner       }
256*4e1bc9a0SAchim Leubner     }
257*4e1bc9a0SAchim Leubner     /* Initialize tiDevhandle */
258*4e1bc9a0SAchim Leubner     smIORequestBody->smDevHandle = smDeviceHandle;
259*4e1bc9a0SAchim Leubner 
260*4e1bc9a0SAchim Leubner     /* Initializes Scatter Gather and ESGL */
261*4e1bc9a0SAchim Leubner     status = smsatIOPrepareSGL( smRoot,
262*4e1bc9a0SAchim Leubner                                 smIORequestBody,
263*4e1bc9a0SAchim Leubner                                 &smScsiRequest->smSgl1,
264*4e1bc9a0SAchim Leubner                                 smScsiRequest->sglVirtualAddr );
265*4e1bc9a0SAchim Leubner 
266*4e1bc9a0SAchim Leubner     if (status != SM_RC_SUCCESS)
267*4e1bc9a0SAchim Leubner     {
268*4e1bc9a0SAchim Leubner       SM_DBG1(("smsataLLIOStart: can't get SGL!!!\n"));
269*4e1bc9a0SAchim Leubner       /* free resource */
270*4e1bc9a0SAchim Leubner       smsatFreeIntIoResource( smRoot,
271*4e1bc9a0SAchim Leubner                               pSatDevData,
272*4e1bc9a0SAchim Leubner                               satIntIo);
273*4e1bc9a0SAchim Leubner       return status;
274*4e1bc9a0SAchim Leubner     }
275*4e1bc9a0SAchim Leubner 
276*4e1bc9a0SAchim Leubner     /* Initialize LL Layer agIORequest */
277*4e1bc9a0SAchim Leubner     agIORequest->osData = (void *) smIORequestBody;
278*4e1bc9a0SAchim Leubner     agIORequest->sdkData = agNULL; /* SA takes care of this */
279*4e1bc9a0SAchim Leubner 
280*4e1bc9a0SAchim Leubner     smIORequestBody->ioStarted = agTRUE;
281*4e1bc9a0SAchim Leubner     smIORequestBody->ioCompleted = agFALSE;
282*4e1bc9a0SAchim Leubner 
283*4e1bc9a0SAchim Leubner     /* assign tag value for SATA */
284*4e1bc9a0SAchim Leubner     if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_WRITE) ||
285*4e1bc9a0SAchim Leubner          (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_READ) )
286*4e1bc9a0SAchim Leubner     {
287*4e1bc9a0SAchim Leubner       if (agFALSE == smsatTagAlloc(smRoot, pSatDevData, &satIOContext->sataTag))
288*4e1bc9a0SAchim Leubner       {
289*4e1bc9a0SAchim Leubner         SM_DBG1(("smsataLLIOStart: No more NCQ tag!!!\n"));
290*4e1bc9a0SAchim Leubner         smIORequestBody->ioStarted = agFALSE;
291*4e1bc9a0SAchim Leubner         smIORequestBody->ioCompleted = agTRUE;
292*4e1bc9a0SAchim Leubner         return SM_RC_DEVICE_BUSY;
293*4e1bc9a0SAchim Leubner       }
294*4e1bc9a0SAchim Leubner       SM_DBG3(("smsataLLIOStart: ncq tag 0x%x\n",satIOContext->sataTag));
295*4e1bc9a0SAchim Leubner     }
296*4e1bc9a0SAchim Leubner     else
297*4e1bc9a0SAchim Leubner     {
298*4e1bc9a0SAchim Leubner       satIOContext->sataTag = 0xFF;
299*4e1bc9a0SAchim Leubner     }
300*4e1bc9a0SAchim Leubner   }
301*4e1bc9a0SAchim Leubner   else /* AGSA_SATA_PROTOCOL_SRST_ASSERT or AGSA_SATA_PROTOCOL_SRST_DEASSERT
302*4e1bc9a0SAchim Leubner           or SAT_CHECK_POWER_MODE as ABORT */
303*4e1bc9a0SAchim Leubner   {
304*4e1bc9a0SAchim Leubner     agsaSgl_t          *agSgl;
305*4e1bc9a0SAchim Leubner 
306*4e1bc9a0SAchim Leubner     /* for internal SATA command only */
307*4e1bc9a0SAchim Leubner     if (satIOContext->satOrgIOContext != agNULL)
308*4e1bc9a0SAchim Leubner     {
309*4e1bc9a0SAchim Leubner       /* Initialize tiIORequest */
310*4e1bc9a0SAchim Leubner       smIORequestBody->smIORequest = smIORequest;
311*4e1bc9a0SAchim Leubner       if (smIORequest == agNULL)
312*4e1bc9a0SAchim Leubner       {
313*4e1bc9a0SAchim Leubner         SM_DBG1(("smsataLLIOStart: 2 check!!!\n"));
314*4e1bc9a0SAchim Leubner       }
315*4e1bc9a0SAchim Leubner     }
316*4e1bc9a0SAchim Leubner     /* Initialize tiDevhandle */
317*4e1bc9a0SAchim Leubner     smIORequestBody->smDevHandle = smDeviceHandle;
318*4e1bc9a0SAchim Leubner 
319*4e1bc9a0SAchim Leubner 
320*4e1bc9a0SAchim Leubner     smIORequestBody->IOType.InitiatorRegIO.expDataLength = 0;
321*4e1bc9a0SAchim Leubner     /* SGL for SATA request */
322*4e1bc9a0SAchim Leubner     agSgl = &(smIORequestBody->transport.SATA.agSATARequestBody.agSgl);
323*4e1bc9a0SAchim Leubner     agSgl->len = 0;
324*4e1bc9a0SAchim Leubner 
325*4e1bc9a0SAchim Leubner     agSgl->sgUpper = 0;
326*4e1bc9a0SAchim Leubner     agSgl->sgLower = 0;
327*4e1bc9a0SAchim Leubner     agSgl->len = 0;
328*4e1bc9a0SAchim Leubner     SM_CLEAR_ESGL_EXTEND(agSgl->extReserved);
329*4e1bc9a0SAchim Leubner 
330*4e1bc9a0SAchim Leubner     /* Initialize LL Layer agIORequest */
331*4e1bc9a0SAchim Leubner     agIORequest = &(smIORequestBody->agIORequest);
332*4e1bc9a0SAchim Leubner     agIORequest->osData = (void *) smIORequestBody;
333*4e1bc9a0SAchim Leubner     agIORequest->sdkData = agNULL; /* SA takes care of this */
334*4e1bc9a0SAchim Leubner 
335*4e1bc9a0SAchim Leubner     smIORequestBody->ioStarted = agTRUE;
336*4e1bc9a0SAchim Leubner     smIORequestBody->ioCompleted = agFALSE;
337*4e1bc9a0SAchim Leubner 
338*4e1bc9a0SAchim Leubner     /* setting the data length */
339*4e1bc9a0SAchim Leubner     agSATAReq->dataLength = 0;
340*4e1bc9a0SAchim Leubner 
341*4e1bc9a0SAchim Leubner   }
342*4e1bc9a0SAchim Leubner 
343*4e1bc9a0SAchim Leubner 
344*4e1bc9a0SAchim Leubner   smIORequestBody->reTries = 0;
345*4e1bc9a0SAchim Leubner 
346*4e1bc9a0SAchim Leubner #ifdef TD_INTERNAL_DEBUG
347*4e1bc9a0SAchim Leubner   smhexdump("smsataLLIOStart", (bit8 *)satIOContext->pFis, sizeof(agsaFisRegHostToDevice_t));
348*4e1bc9a0SAchim Leubner   smhexdump("smsataLLIOStart LL", (bit8 *)&agSATAReq->fis.fisRegHostToDev,
349*4e1bc9a0SAchim Leubner             sizeof(agsaFisRegHostToDevice_t));
350*4e1bc9a0SAchim Leubner #endif
351*4e1bc9a0SAchim Leubner 
352*4e1bc9a0SAchim Leubner   SM_DBG6(("smsataLLIOStart: agDevHandle %p\n", agDevHandle));
353*4e1bc9a0SAchim Leubner 
354*4e1bc9a0SAchim Leubner   /* to get better IO performance, rotate the OBQ number on main IO path */
355*4e1bc9a0SAchim Leubner   if (smScsiRequest == agNULL)
356*4e1bc9a0SAchim Leubner   {
357*4e1bc9a0SAchim Leubner     nQNumber = 0;
358*4e1bc9a0SAchim Leubner   }
359*4e1bc9a0SAchim Leubner   else
360*4e1bc9a0SAchim Leubner   {
361*4e1bc9a0SAchim Leubner     switch (smScsiRequest->scsiCmnd.cdb[0])
362*4e1bc9a0SAchim Leubner     {
363*4e1bc9a0SAchim Leubner       case SCSIOPC_READ_10:
364*4e1bc9a0SAchim Leubner       case SCSIOPC_WRITE_10:
365*4e1bc9a0SAchim Leubner       case SCSIOPC_READ_6:
366*4e1bc9a0SAchim Leubner       case SCSIOPC_WRITE_6:
367*4e1bc9a0SAchim Leubner       case SCSIOPC_READ_12:
368*4e1bc9a0SAchim Leubner       case SCSIOPC_WRITE_12:
369*4e1bc9a0SAchim Leubner       case SCSIOPC_READ_16:
370*4e1bc9a0SAchim Leubner       case SCSIOPC_WRITE_16:
371*4e1bc9a0SAchim Leubner          nQNumber = tdsmRotateQnumber(smRoot, smDeviceHandle);
372*4e1bc9a0SAchim Leubner          break;
373*4e1bc9a0SAchim Leubner 
374*4e1bc9a0SAchim Leubner       default:
375*4e1bc9a0SAchim Leubner          nQNumber = 0;
376*4e1bc9a0SAchim Leubner          break;
377*4e1bc9a0SAchim Leubner     }
378*4e1bc9a0SAchim Leubner   }
379*4e1bc9a0SAchim Leubner 
380*4e1bc9a0SAchim Leubner   SM_DBG3(("sataLLIOStart: Lock in\n"));
381*4e1bc9a0SAchim Leubner 
382*4e1bc9a0SAchim Leubner #ifdef CCFLAG_OPTIMIZE_SAT_LOCK
383*4e1bc9a0SAchim Leubner   if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_WRITE) ||
384*4e1bc9a0SAchim Leubner        (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_READ) )
385*4e1bc9a0SAchim Leubner   {
386*4e1bc9a0SAchim Leubner      tdsmInterlockedIncrement(smRoot,&pSatDevData->satPendingNCQIO);
387*4e1bc9a0SAchim Leubner   }
388*4e1bc9a0SAchim Leubner   else
389*4e1bc9a0SAchim Leubner   {
390*4e1bc9a0SAchim Leubner      tdsmInterlockedIncrement(smRoot,&pSatDevData->satPendingNONNCQIO);
391*4e1bc9a0SAchim Leubner   }
392*4e1bc9a0SAchim Leubner   tdsmInterlockedIncrement(smRoot,&pSatDevData->satPendingIO);
393*4e1bc9a0SAchim Leubner #else
394*4e1bc9a0SAchim Leubner   tdsmSingleThreadedEnter(smRoot, SM_EXTERNAL_IO_LOCK);
395*4e1bc9a0SAchim Leubner   if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_WRITE) ||
396*4e1bc9a0SAchim Leubner        (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_READ) )
397*4e1bc9a0SAchim Leubner   {
398*4e1bc9a0SAchim Leubner      pSatDevData->satPendingNCQIO++;
399*4e1bc9a0SAchim Leubner   }
400*4e1bc9a0SAchim Leubner   else
401*4e1bc9a0SAchim Leubner   {
402*4e1bc9a0SAchim Leubner      pSatDevData->satPendingNONNCQIO++;
403*4e1bc9a0SAchim Leubner   }
404*4e1bc9a0SAchim Leubner   pSatDevData->satPendingIO++;
405*4e1bc9a0SAchim Leubner 
406*4e1bc9a0SAchim Leubner   SMLIST_INIT_ELEMENT (&satIOContext->satIoContextLink);
407*4e1bc9a0SAchim Leubner   SMLIST_ENQUEUE_AT_TAIL (&satIOContext->satIoContextLink, &pSatDevData->satIoLinkList);
408*4e1bc9a0SAchim Leubner   tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
409*4e1bc9a0SAchim Leubner #endif
410*4e1bc9a0SAchim Leubner   /* post SATA command to low level MPI */
411*4e1bc9a0SAchim Leubner   status = saSATAStart( agRoot,
412*4e1bc9a0SAchim Leubner                         agIORequest,
413*4e1bc9a0SAchim Leubner                         nQNumber,
414*4e1bc9a0SAchim Leubner                         agDevHandle,
415*4e1bc9a0SAchim Leubner                         satIOContext->reqType,
416*4e1bc9a0SAchim Leubner                         agSATAReq,
417*4e1bc9a0SAchim Leubner                         satIOContext->sataTag,
418*4e1bc9a0SAchim Leubner                         smllSATACompleted
419*4e1bc9a0SAchim Leubner                         );
420*4e1bc9a0SAchim Leubner 
421*4e1bc9a0SAchim Leubner   if (status != AGSA_RC_SUCCESS)
422*4e1bc9a0SAchim Leubner   {
423*4e1bc9a0SAchim Leubner     if (status == AGSA_RC_BUSY)
424*4e1bc9a0SAchim Leubner     {
425*4e1bc9a0SAchim Leubner       SM_DBG1(("smsataLLIOStart: saSATAStart busy!!!\n"));
426*4e1bc9a0SAchim Leubner       status = SM_RC_BUSY;
427*4e1bc9a0SAchim Leubner     }
428*4e1bc9a0SAchim Leubner     else
429*4e1bc9a0SAchim Leubner     {
430*4e1bc9a0SAchim Leubner       SM_DBG1(("smsataLLIOStart: saSATAStart failed!!!\n"));
431*4e1bc9a0SAchim Leubner       status = SM_RC_FAILURE;
432*4e1bc9a0SAchim Leubner     }
433*4e1bc9a0SAchim Leubner 
434*4e1bc9a0SAchim Leubner     if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_WRITE) ||
435*4e1bc9a0SAchim Leubner          (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_READ) )
436*4e1bc9a0SAchim Leubner     {
437*4e1bc9a0SAchim Leubner       smsatTagRelease(smRoot, pSatDevData, satIOContext->sataTag);
438*4e1bc9a0SAchim Leubner     }
439*4e1bc9a0SAchim Leubner 
440*4e1bc9a0SAchim Leubner #ifdef CCFLAG_OPTIMIZE_SAT_LOCK
441*4e1bc9a0SAchim Leubner     if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_WRITE) ||
442*4e1bc9a0SAchim Leubner          (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_READ) )
443*4e1bc9a0SAchim Leubner     {
444*4e1bc9a0SAchim Leubner       tdsmInterlockedDecrement(smRoot,&oneDeviceData->satPendingNCQIO);
445*4e1bc9a0SAchim Leubner     }
446*4e1bc9a0SAchim Leubner     else
447*4e1bc9a0SAchim Leubner     {
448*4e1bc9a0SAchim Leubner       tdsmInterlockedDecrement(smRoot,&oneDeviceData->satPendingNONNCQIO);
449*4e1bc9a0SAchim Leubner     }
450*4e1bc9a0SAchim Leubner     tdsmInterlockedDecrement(smRoot,&oneDeviceData->satPendingIO);
451*4e1bc9a0SAchim Leubner #else
452*4e1bc9a0SAchim Leubner     if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_WRITE) ||
453*4e1bc9a0SAchim Leubner          (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_READ) )
454*4e1bc9a0SAchim Leubner     {
455*4e1bc9a0SAchim Leubner       tdsmSingleThreadedEnter(smRoot, SM_EXTERNAL_IO_LOCK);
456*4e1bc9a0SAchim Leubner       oneDeviceData->satPendingNCQIO--;
457*4e1bc9a0SAchim Leubner       oneDeviceData->satPendingIO--;
458*4e1bc9a0SAchim Leubner       SMLIST_DEQUEUE_THIS (&satIOContext->satIoContextLink);
459*4e1bc9a0SAchim Leubner       tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
460*4e1bc9a0SAchim Leubner     }
461*4e1bc9a0SAchim Leubner     else
462*4e1bc9a0SAchim Leubner     {
463*4e1bc9a0SAchim Leubner       tdsmSingleThreadedEnter(smRoot, SM_EXTERNAL_IO_LOCK);
464*4e1bc9a0SAchim Leubner       oneDeviceData->satPendingNONNCQIO--;
465*4e1bc9a0SAchim Leubner       oneDeviceData->satPendingIO--;
466*4e1bc9a0SAchim Leubner       SMLIST_DEQUEUE_THIS (&satIOContext->satIoContextLink);
467*4e1bc9a0SAchim Leubner       tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
468*4e1bc9a0SAchim Leubner     }
469*4e1bc9a0SAchim Leubner #endif /* CCFLAG_OPTIMIZE_SAT_LOCK */
470*4e1bc9a0SAchim Leubner 
471*4e1bc9a0SAchim Leubner     /* Free the ESGL pages associated with this I/O */
472*4e1bc9a0SAchim Leubner     smIORequestBody->ioStarted = agFALSE;
473*4e1bc9a0SAchim Leubner     smIORequestBody->ioCompleted = agTRUE;
474*4e1bc9a0SAchim Leubner     return (status);
475*4e1bc9a0SAchim Leubner   }
476*4e1bc9a0SAchim Leubner 
477*4e1bc9a0SAchim Leubner   return SM_RC_SUCCESS;
478*4e1bc9a0SAchim Leubner }
479*4e1bc9a0SAchim Leubner 
480*4e1bc9a0SAchim Leubner 
481*4e1bc9a0SAchim Leubner osGLOBAL FORCEINLINE bit32
smsatIOPrepareSGL(smRoot_t * smRoot,smIORequestBody_t * smIORequestBody,smSgl_t * smSgl1,void * sglVirtualAddr)482*4e1bc9a0SAchim Leubner smsatIOPrepareSGL(
483*4e1bc9a0SAchim Leubner                   smRoot_t                 *smRoot,
484*4e1bc9a0SAchim Leubner                   smIORequestBody_t        *smIORequestBody,
485*4e1bc9a0SAchim Leubner                   smSgl_t                  *smSgl1,
486*4e1bc9a0SAchim Leubner                   void                     *sglVirtualAddr
487*4e1bc9a0SAchim Leubner                   )
488*4e1bc9a0SAchim Leubner {
489*4e1bc9a0SAchim Leubner   agsaSgl_t          *agSgl;
490*4e1bc9a0SAchim Leubner 
491*4e1bc9a0SAchim Leubner   /* Uppper should be zero-out */
492*4e1bc9a0SAchim Leubner   SM_DBG5(("smsatIOPrepareSGL: start\n"));
493*4e1bc9a0SAchim Leubner 
494*4e1bc9a0SAchim Leubner   SM_DBG5(("smsatIOPrepareSGL: smSgl1->upper %d smSgl1->lower %d smSgl1->len %d\n",
495*4e1bc9a0SAchim Leubner     smSgl1->upper, smSgl1->lower, smSgl1->len));
496*4e1bc9a0SAchim Leubner   SM_DBG5(("smsatIOPrepareSGL: smSgl1->type %d\n", smSgl1->type));
497*4e1bc9a0SAchim Leubner 
498*4e1bc9a0SAchim Leubner   /* SGL for SATA request */
499*4e1bc9a0SAchim Leubner   agSgl = &(smIORequestBody->transport.SATA.agSATARequestBody.agSgl);
500*4e1bc9a0SAchim Leubner   agSgl->len = 0;
501*4e1bc9a0SAchim Leubner 
502*4e1bc9a0SAchim Leubner   if (smSgl1 == agNULL)
503*4e1bc9a0SAchim Leubner   {
504*4e1bc9a0SAchim Leubner     SM_DBG1(("smsatIOPrepareSGL: Error smSgl1 is NULL!!!\n"));
505*4e1bc9a0SAchim Leubner     return tiError;
506*4e1bc9a0SAchim Leubner   }
507*4e1bc9a0SAchim Leubner 
508*4e1bc9a0SAchim Leubner   if (smIORequestBody->IOType.InitiatorRegIO.expDataLength == 0)
509*4e1bc9a0SAchim Leubner   {
510*4e1bc9a0SAchim Leubner     SM_DBG3(("smsatIOPrepareSGL: expDataLength is 0\n"));
511*4e1bc9a0SAchim Leubner     agSgl->sgUpper = 0;
512*4e1bc9a0SAchim Leubner     agSgl->sgLower = 0;
513*4e1bc9a0SAchim Leubner     agSgl->len = 0;
514*4e1bc9a0SAchim Leubner     SM_CLEAR_ESGL_EXTEND(agSgl->extReserved);
515*4e1bc9a0SAchim Leubner     return SM_RC_SUCCESS;
516*4e1bc9a0SAchim Leubner   }
517*4e1bc9a0SAchim Leubner 
518*4e1bc9a0SAchim Leubner   agSgl->sgUpper = smSgl1->upper;
519*4e1bc9a0SAchim Leubner   agSgl->sgLower = smSgl1->lower;
520*4e1bc9a0SAchim Leubner   agSgl->len = smSgl1->len;
521*4e1bc9a0SAchim Leubner   agSgl->extReserved = smSgl1->type;
522*4e1bc9a0SAchim Leubner 
523*4e1bc9a0SAchim Leubner   return SM_RC_SUCCESS;
524*4e1bc9a0SAchim Leubner 
525*4e1bc9a0SAchim Leubner }
526*4e1bc9a0SAchim Leubner 
527*4e1bc9a0SAchim Leubner 
528*4e1bc9a0SAchim Leubner 
529*4e1bc9a0SAchim Leubner 
530