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