1 /*******************************************************************************
2 *Copyright (c) 2014 PMC-Sierra, Inc. All rights reserved.
4 *Redistribution and use in source and binary forms, with or without modification, are permitted provided
5 *that the following conditions are met:
6 *1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
8 *2. Redistributions in binary form must reproduce the above copyright notice,
9 *this list of conditions and the following disclaimer in the documentation and/or other materials provided
10 *with the distribution.
12 *THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
13 *WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
14 *FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
15 *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
16 *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
17 *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18 *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
19 *SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
21 ********************************************************************************/
22 #include <sys/cdefs.h>
23 __FBSDID("$FreeBSD$");
24 #include <dev/pms/config.h>
26 #include <dev/pms/freebsd/driver/common/osenv.h>
27 #include <dev/pms/freebsd/driver/common/ostypes.h>
28 #include <dev/pms/freebsd/driver/common/osdebug.h>
30 #include <dev/pms/RefTisa/tisa/api/titypes.h>
32 #include <dev/pms/RefTisa/sallsdk/api/sa.h>
33 #include <dev/pms/RefTisa/sallsdk/api/saapi.h>
34 #include <dev/pms/RefTisa/sallsdk/api/saosapi.h>
36 #include <dev/pms/RefTisa/sat/api/sm.h>
37 #include <dev/pms/RefTisa/sat/api/smapi.h>
38 #include <dev/pms/RefTisa/sat/api/tdsmapi.h>
40 #include <dev/pms/RefTisa/sat/src/smdefs.h>
41 #include <dev/pms/RefTisa/sat/src/smproto.h>
42 #include <dev/pms/RefTisa/sat/src/smtypes.h>
45 * This table is used to map LL Layer saSATAStart() status to TISA status.
52 smIORequest_t *smIORequest,
53 smDeviceHandle_t *smDeviceHandle,
54 smScsiInitiatorRequest_t *smScsiRequest,
55 smSatIOContext_t *satIOContext
58 smDeviceData_t *oneDeviceData = (smDeviceData_t *)smDeviceHandle->smData;
59 smIntRoot_t *smIntRoot = (smIntRoot_t *) smRoot->smData;
60 smIntContext_t *smAllShared = (smIntContext_t *)&(smIntRoot->smAllShared);
61 smIORequestBody_t *smIORequestBody = (smIORequestBody_t *)satIOContext->smRequestBody;
62 smDeviceData_t *pSatDevData = satIOContext->pSatDevData;
63 smSatInternalIo_t *satIntIo = satIOContext->satIntIoContext;
64 agsaRoot_t *agRoot = smAllShared->agRoot;
65 agsaIORequest_t *agIORequest = &(smIORequestBody->agIORequest);
66 agsaDevHandle_t *agDevHandle = oneDeviceData->agDevHandle;
67 agsaSATAInitiatorRequest_t *agSATAReq = &(smIORequestBody->transport.SATA.agSATARequestBody);
68 bit32 RLERecovery = agFALSE;
69 bit32 status = SM_RC_FAILURE;
72 * If this is a super I/O request, check for optional settings.
73 * Be careful. Use the superRequest pointer for all references
74 * in this block of code.
76 agSATAReq->option = 0;
77 if (satIOContext->superIOFlag)
79 smSuperScsiInitiatorRequest_t *superRequest = (smSuperScsiInitiatorRequest_t *) smScsiRequest;
81 if (superRequest->flags & SM_SCSI_INITIATOR_ENCRYPT)
83 /* Copy all of the relevant encrypt information */
84 agSATAReq->option |= AGSA_SATA_ENABLE_ENCRYPTION;
85 sm_memcpy(&agSATAReq->encrypt, &superRequest->Encrypt, sizeof(agsaEncrypt_t));
88 /* initialize expDataLength */
89 if (satIOContext->reqType == AGSA_SATA_PROTOCOL_NON_DATA ||
90 satIOContext->reqType == AGSA_SATA_PROTOCOL_SRST_ASSERT ||
91 satIOContext->reqType == AGSA_SATA_PROTOCOL_SRST_DEASSERT )
93 smIORequestBody->IOType.InitiatorRegIO.expDataLength = 0;
97 smIORequestBody->IOType.InitiatorRegIO.expDataLength = smScsiRequest->scsiCmnd.expDataLength;
100 agSATAReq->dataLength = smIORequestBody->IOType.InitiatorRegIO.expDataLength;
105 /* initialize expDataLength */
106 if (satIOContext->reqType == AGSA_SATA_PROTOCOL_NON_DATA ||
107 satIOContext->reqType == AGSA_SATA_PROTOCOL_SRST_ASSERT ||
108 satIOContext->reqType == AGSA_SATA_PROTOCOL_SRST_DEASSERT )
110 smIORequestBody->IOType.InitiatorRegIO.expDataLength = 0;
114 smIORequestBody->IOType.InitiatorRegIO.expDataLength = smScsiRequest->scsiCmnd.expDataLength;
117 agSATAReq->dataLength = smIORequestBody->IOType.InitiatorRegIO.expDataLength;
120 if ( (pSatDevData->satDriveState == SAT_DEV_STATE_IN_RECOVERY) &&
121 (satIOContext->pFis->h.command == SAT_READ_LOG_EXT) )
123 RLERecovery = agTRUE;
126 /* check max io, be sure to free */
127 if ( (pSatDevData->satDriveState != SAT_DEV_STATE_IN_RECOVERY) ||
128 (RLERecovery == agTRUE) )
130 if (RLERecovery == agFALSE) /* RLE is not checked against pending IO's */
132 #ifdef CCFLAG_OPTIMIZE_SAT_LOCK
133 bit32 volatile satPendingNCQIO = 0;
134 bit32 volatile satPendingNONNCQIO = 0;
135 bit32 volatile satPendingIO = 0;
137 tdsmInterlockedExchange(smRoot, &satPendingNCQIO, pSatDevData->satPendingNCQIO);
138 tdsmInterlockedExchange(smRoot, &satPendingNONNCQIO, pSatDevData->satPendingNONNCQIO);
139 tdsmInterlockedExchange(smRoot, &satPendingIO, pSatDevData->satPendingIO);
142 if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_WRITE) ||
143 (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_READ) )
145 #ifdef CCFLAG_OPTIMIZE_SAT_LOCK
146 if ( satPendingNCQIO >= pSatDevData->satNCQMaxIO ||
147 satPendingNONNCQIO != 0)
149 SM_DBG1(("smsataLLIOStart: 1st busy did %d!!!\n", pSatDevData->id));
150 SM_DBG1(("smsataLLIOStart: 1st busy NCQ. NCQ Pending 0x%x NONNCQ Pending 0x%x All Pending 0x%x!!!\n", satPendingNCQIO,
151 satPendingNONNCQIO, satPendingIO));
153 smsatFreeIntIoResource( smRoot,
156 return SM_RC_DEVICE_BUSY;
159 tdsmSingleThreadedEnter(smRoot, SM_EXTERNAL_IO_LOCK);
160 if (pSatDevData->satPendingNCQIO >= pSatDevData->satNCQMaxIO ||
161 pSatDevData->satPendingNONNCQIO != 0)
163 SM_DBG1(("smsataLLIOStart: 1st busy did %d!!!\n", pSatDevData->id));
164 SM_DBG1(("smsataLLIOStart: 1st busy NCQ. NCQ Pending 0x%x NONNCQ Pending 0x%x All Pending 0x%x!!!\n", pSatDevData->satPendingNCQIO,
165 pSatDevData->satPendingNONNCQIO, pSatDevData->satPendingIO));
166 tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
168 smsatFreeIntIoResource( smRoot,
171 return SM_RC_DEVICE_BUSY;
173 tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
177 else if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_D2H_PKT) ||
178 (satIOContext->reqType == AGSA_SATA_PROTOCOL_H2D_PKT) ||
179 (satIOContext->reqType == AGSA_SATA_PROTOCOL_NON_PKT) )
181 sm_memcpy(agSATAReq->scsiCDB, smScsiRequest->scsiCmnd.cdb, 16);
182 #ifdef CCFLAG_OPTIMIZE_SAT_LOCK
183 if ( satPendingNONNCQIO >= SAT_APAPI_CMDQ_MAX ||
184 satPendingNCQIO != 0)
186 SM_DBG1(("smsataLLIOStart: ATAPI busy did %d!!!\n", pSatDevData->id));
187 SM_DBG1(("smsataLLIOStart: ATAPI busy NON-NCQ. NCQ Pending 0x%x NON-NCQ Pending 0x%x All Pending 0x%x!!!\n", satPendingNCQIO,
188 satPendingNONNCQIO, satPendingIO));
190 smsatFreeIntIoResource( smRoot,
193 return SM_RC_DEVICE_BUSY;
196 tdsmSingleThreadedEnter(smRoot, SM_EXTERNAL_IO_LOCK);
197 if ( pSatDevData->satPendingNONNCQIO >= SAT_APAPI_CMDQ_MAX ||
198 pSatDevData->satPendingNCQIO != 0)
200 SM_DBG1(("smsataLLIOStart: ATAPI busy did %d!!!\n", pSatDevData->id));
201 SM_DBG1(("smsataLLIOStart: ATAPI busy NON-NCQ. NCQ Pending 0x%x NON-NCQ Pending 0x%x All Pending 0x%x!!!\n", pSatDevData->satPendingNCQIO,
202 pSatDevData->satPendingNONNCQIO, pSatDevData->satPendingIO));
203 tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
205 smsatFreeIntIoResource( smRoot,
208 return SM_RC_DEVICE_BUSY;
210 tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
216 #ifdef CCFLAG_OPTIMIZE_SAT_LOCK
217 if ( satPendingNONNCQIO >= SAT_NONNCQ_MAX ||
218 satPendingNCQIO != 0)
220 SM_DBG1(("smsataLLIOStart: 2nd busy did %d!!!\n", pSatDevData->id));
221 SM_DBG1(("smsataLLIOStart: 2nd busy NCQ. NCQ Pending 0x%x NONNCQ Pending 0x%x All Pending 0x%x!!!\n", satPendingNCQIO,
222 satPendingNONNCQIO, satPendingIO));
224 smsatFreeIntIoResource( smRoot,
227 return SM_RC_DEVICE_BUSY;
230 tdsmSingleThreadedEnter(smRoot, SM_EXTERNAL_IO_LOCK);
231 if (pSatDevData->satPendingNONNCQIO >= SAT_NONNCQ_MAX ||
232 pSatDevData->satPendingNCQIO != 0)
234 SM_DBG1(("smsataLLIOStart: 2nd busy did %d!!!\n", pSatDevData->id));
235 SM_DBG1(("smsataLLIOStart: 2nd busy NCQ. NCQ Pending 0x%x NONNCQ Pending 0x%x All Pending 0x%x!!!\n", pSatDevData->satPendingNCQIO,
236 pSatDevData->satPendingNONNCQIO, pSatDevData->satPendingIO));
237 tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
239 smsatFreeIntIoResource( smRoot,
242 return SM_RC_DEVICE_BUSY;
244 tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
248 /* for internal SATA command only */
249 if (satIOContext->satOrgIOContext != agNULL)
251 /* Initialize tiIORequest */
252 smIORequestBody->smIORequest = smIORequest;
253 if (smIORequest == agNULL)
255 SM_DBG1(("smsataLLIOStart: 1 check!!!\n"));
258 /* Initialize tiDevhandle */
259 smIORequestBody->smDevHandle = smDeviceHandle;
261 /* Initializes Scatter Gather and ESGL */
262 status = smsatIOPrepareSGL( smRoot,
264 &smScsiRequest->smSgl1,
265 smScsiRequest->sglVirtualAddr );
267 if (status != SM_RC_SUCCESS)
269 SM_DBG1(("smsataLLIOStart: can't get SGL!!!\n"));
271 smsatFreeIntIoResource( smRoot,
277 /* Initialize LL Layer agIORequest */
278 agIORequest->osData = (void *) smIORequestBody;
279 agIORequest->sdkData = agNULL; /* SA takes care of this */
281 smIORequestBody->ioStarted = agTRUE;
282 smIORequestBody->ioCompleted = agFALSE;
284 /* assign tag value for SATA */
285 if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_WRITE) ||
286 (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_READ) )
288 if (agFALSE == smsatTagAlloc(smRoot, pSatDevData, &satIOContext->sataTag))
290 SM_DBG1(("smsataLLIOStart: No more NCQ tag!!!\n"));
291 smIORequestBody->ioStarted = agFALSE;
292 smIORequestBody->ioCompleted = agTRUE;
293 return SM_RC_DEVICE_BUSY;
295 SM_DBG3(("smsataLLIOStart: ncq tag 0x%x\n",satIOContext->sataTag));
299 satIOContext->sataTag = 0xFF;
302 else /* AGSA_SATA_PROTOCOL_SRST_ASSERT or AGSA_SATA_PROTOCOL_SRST_DEASSERT
303 or SAT_CHECK_POWER_MODE as ABORT */
307 /* for internal SATA command only */
308 if (satIOContext->satOrgIOContext != agNULL)
310 /* Initialize tiIORequest */
311 smIORequestBody->smIORequest = smIORequest;
312 if (smIORequest == agNULL)
314 SM_DBG1(("smsataLLIOStart: 2 check!!!\n"));
317 /* Initialize tiDevhandle */
318 smIORequestBody->smDevHandle = smDeviceHandle;
321 smIORequestBody->IOType.InitiatorRegIO.expDataLength = 0;
322 /* SGL for SATA request */
323 agSgl = &(smIORequestBody->transport.SATA.agSATARequestBody.agSgl);
329 SM_CLEAR_ESGL_EXTEND(agSgl->extReserved);
331 /* Initialize LL Layer agIORequest */
332 agIORequest = &(smIORequestBody->agIORequest);
333 agIORequest->osData = (void *) smIORequestBody;
334 agIORequest->sdkData = agNULL; /* SA takes care of this */
336 smIORequestBody->ioStarted = agTRUE;
337 smIORequestBody->ioCompleted = agFALSE;
339 /* setting the data length */
340 agSATAReq->dataLength = 0;
345 smIORequestBody->reTries = 0;
347 #ifdef TD_INTERNAL_DEBUG
348 smhexdump("smsataLLIOStart", (bit8 *)satIOContext->pFis, sizeof(agsaFisRegHostToDevice_t));
349 smhexdump("smsataLLIOStart LL", (bit8 *)&agSATAReq->fis.fisRegHostToDev,
350 sizeof(agsaFisRegHostToDevice_t));
353 SM_DBG6(("smsataLLIOStart: agDevHandle %p\n", agDevHandle));
355 /* to get better IO performance, rotate the OBQ number on main IO path */
356 if (smScsiRequest == agNULL)
362 switch (smScsiRequest->scsiCmnd.cdb[0])
364 case SCSIOPC_READ_10:
365 case SCSIOPC_WRITE_10:
367 case SCSIOPC_WRITE_6:
368 case SCSIOPC_READ_12:
369 case SCSIOPC_WRITE_12:
370 case SCSIOPC_READ_16:
371 case SCSIOPC_WRITE_16:
372 nQNumber = tdsmRotateQnumber(smRoot, smDeviceHandle);
381 SM_DBG3(("sataLLIOStart: Lock in\n"));
383 #ifdef CCFLAG_OPTIMIZE_SAT_LOCK
384 if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_WRITE) ||
385 (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_READ) )
387 tdsmInterlockedIncrement(smRoot,&pSatDevData->satPendingNCQIO);
391 tdsmInterlockedIncrement(smRoot,&pSatDevData->satPendingNONNCQIO);
393 tdsmInterlockedIncrement(smRoot,&pSatDevData->satPendingIO);
395 tdsmSingleThreadedEnter(smRoot, SM_EXTERNAL_IO_LOCK);
396 if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_WRITE) ||
397 (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_READ) )
399 pSatDevData->satPendingNCQIO++;
403 pSatDevData->satPendingNONNCQIO++;
405 pSatDevData->satPendingIO++;
407 SMLIST_INIT_ELEMENT (&satIOContext->satIoContextLink);
408 SMLIST_ENQUEUE_AT_TAIL (&satIOContext->satIoContextLink, &pSatDevData->satIoLinkList);
409 tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
411 /* post SATA command to low level MPI */
412 status = saSATAStart( agRoot,
416 satIOContext->reqType,
418 satIOContext->sataTag,
422 if (status != AGSA_RC_SUCCESS)
424 if (status == AGSA_RC_BUSY)
426 SM_DBG1(("smsataLLIOStart: saSATAStart busy!!!\n"));
431 SM_DBG1(("smsataLLIOStart: saSATAStart failed!!!\n"));
432 status = SM_RC_FAILURE;
435 if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_WRITE) ||
436 (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_READ) )
438 smsatTagRelease(smRoot, pSatDevData, satIOContext->sataTag);
441 #ifdef CCFLAG_OPTIMIZE_SAT_LOCK
442 if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_WRITE) ||
443 (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_READ) )
445 tdsmInterlockedDecrement(smRoot,&oneDeviceData->satPendingNCQIO);
449 tdsmInterlockedDecrement(smRoot,&oneDeviceData->satPendingNONNCQIO);
451 tdsmInterlockedDecrement(smRoot,&oneDeviceData->satPendingIO);
453 if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_WRITE) ||
454 (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_READ) )
456 tdsmSingleThreadedEnter(smRoot, SM_EXTERNAL_IO_LOCK);
457 oneDeviceData->satPendingNCQIO--;
458 oneDeviceData->satPendingIO--;
459 SMLIST_DEQUEUE_THIS (&satIOContext->satIoContextLink);
460 tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
464 tdsmSingleThreadedEnter(smRoot, SM_EXTERNAL_IO_LOCK);
465 oneDeviceData->satPendingNONNCQIO--;
466 oneDeviceData->satPendingIO--;
467 SMLIST_DEQUEUE_THIS (&satIOContext->satIoContextLink);
468 tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK);
470 #endif /* CCFLAG_OPTIMIZE_SAT_LOCK */
472 /* Free the ESGL pages associated with this I/O */
473 smIORequestBody->ioStarted = agFALSE;
474 smIORequestBody->ioCompleted = agTRUE;
478 return SM_RC_SUCCESS;
482 osGLOBAL FORCEINLINE bit32
485 smIORequestBody_t *smIORequestBody,
492 /* Uppper should be zero-out */
493 SM_DBG5(("smsatIOPrepareSGL: start\n"));
495 SM_DBG5(("smsatIOPrepareSGL: smSgl1->upper %d smSgl1->lower %d smSgl1->len %d\n",
496 smSgl1->upper, smSgl1->lower, smSgl1->len));
497 SM_DBG5(("smsatIOPrepareSGL: smSgl1->type %d\n", smSgl1->type));
499 /* SGL for SATA request */
500 agSgl = &(smIORequestBody->transport.SATA.agSATARequestBody.agSgl);
503 if (smSgl1 == agNULL)
505 SM_DBG1(("smsatIOPrepareSGL: Error smSgl1 is NULL!!!\n"));
509 if (smIORequestBody->IOType.InitiatorRegIO.expDataLength == 0)
511 SM_DBG3(("smsatIOPrepareSGL: expDataLength is 0\n"));
515 SM_CLEAR_ESGL_EXTEND(agSgl->extReserved);
516 return SM_RC_SUCCESS;
519 agSgl->sgUpper = smSgl1->upper;
520 agSgl->sgLower = smSgl1->lower;
521 agSgl->len = smSgl1->len;
522 agSgl->extReserved = smSgl1->type;
524 return SM_RC_SUCCESS;