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
saGetIBQPI(agsaRoot_t * agRoot,bit32 queueNum)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
saSetIBQPI(agsaRoot_t * agRoot,bit32 queueNum,bit32 pi)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*
siFastSSPReqAlloc(agsaRoot_t * agRoot)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
siFastSSPReqFree(agsaRoot_t * agRoot,void * freq)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
siFastSSPResAlloc(agsaRoot_t * agRoot,bit32 queueNum,bit32 agRequestType,agsaDeviceDesc_t * pDevice,agsaIORequestDesc_t ** pRequest,void ** pPayload)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
saFastSSPCancel(void * ioHandle)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
saFastSSPPrepare(void * ioh,agsaFastCommand_t * fc,ossaSSPCompletedCB_t cb,void * cbArg)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
saFastSSPSend(void * ioHandle)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 /******************************************************************************/
saSSPStart(agsaRoot_t * agRoot,agsaIORequest_t * agIORequest,bit32 queueNum,agsaDevHandle_t * agDevHandle,bit32 agRequestType,agsaSASRequestBody_t * agRequestBody,agsaIORequest_t * agTMRequest,ossaSSPCompletedCB_t agCB)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 /*******************************************************************************/
saSSPAbort(agsaRoot_t * agRoot,agsaIORequest_t * agIORequest,bit32 queueNum,agsaDevHandle_t * agDevHandle,bit32 flag,void * abortParam,ossaGenericAbortCB_t agCB)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 /*******************************************************************************/
siDumpSSPStartIu(agsaDevHandle_t * agDevHandle,bit32 agRequestType,agsaSASRequestBody_t * agRequestBody)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