xref: /freebsd/sys/dev/pms/RefTisa/tisa/sassata/sas/ini/itdio.c (revision d3d381b2b194b4d24853e92eecef55f262688d1a)
1 /*******************************************************************************
2 *Copyright (c) 2014 PMC-Sierra, Inc.  All rights reserved.
3 *
4 *Redistribution and use in source and binary forms, with or without modification, are permitted provided
5 *that the following conditions are met:
6 *1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
7 *following disclaimer.
8 *2. Redistributions in binary form must reproduce the above copyright notice,
9 *this list of conditions and the following disclaimer in the documentation and/or other materials provided
10 *with the distribution.
11 *
12 *THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
13 *WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
14 *FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
15 *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
16 *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
17 *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18 *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
19 *SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
20 
21 ********************************************************************************/
22 /*******************************************************************************/
23 /** \file
24  *
25  *
26  * This file contains initiator IO related functions in TD layer
27  *
28  */
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 #include <dev/pms/config.h>
32 
33 #include <dev/pms/freebsd/driver/common/osenv.h>
34 #include <dev/pms/freebsd/driver/common/ostypes.h>
35 #include <dev/pms/freebsd/driver/common/osdebug.h>
36 
37 #include <dev/pms/RefTisa/sallsdk/api/sa.h>
38 #include <dev/pms/RefTisa/sallsdk/api/saapi.h>
39 #include <dev/pms/RefTisa/sallsdk/api/saosapi.h>
40 
41 #include <dev/pms/RefTisa/tisa/api/titypes.h>
42 #include <dev/pms/RefTisa/tisa/api/ostiapi.h>
43 #include <dev/pms/RefTisa/tisa/api/tiapi.h>
44 #include <dev/pms/RefTisa/tisa/api/tiglobal.h>
45 
46 #ifdef FDS_SM
47 #include <dev/pms/RefTisa/sat/api/sm.h>
48 #include <dev/pms/RefTisa/sat/api/smapi.h>
49 #include <dev/pms/RefTisa/sat/api/tdsmapi.h>
50 #endif
51 
52 #ifdef FDS_DM
53 #include <dev/pms/RefTisa/discovery/api/dm.h>
54 #include <dev/pms/RefTisa/discovery/api/dmapi.h>
55 #include <dev/pms/RefTisa/discovery/api/tddmapi.h>
56 #endif
57 
58 #include <dev/pms/RefTisa/tisa/sassata/sas/common/tdtypes.h>
59 #include <dev/pms/freebsd/driver/common/osstring.h>
60 #include <dev/pms/RefTisa/tisa/sassata/common/tdutil.h>
61 
62 #ifdef INITIATOR_DRIVER
63 #include <dev/pms/RefTisa/tisa/sassata/sas/ini/itdtypes.h>
64 #include <dev/pms/RefTisa/tisa/sassata/sas/ini/itddefs.h>
65 #include <dev/pms/RefTisa/tisa/sassata/sas/ini/itdglobl.h>
66 #endif
67 
68 #ifdef TARGET_DRIVER
69 #include <dev/pms/RefTisa/tisa/sassata/sas/tgt/ttdglobl.h>
70 #include <dev/pms/RefTisa/tisa/sassata/sas/tgt/ttdxchg.h>
71 #include <dev/pms/RefTisa/tisa/sassata/sas/tgt/ttdtypes.h>
72 #endif
73 
74 #include <dev/pms/RefTisa/tisa/sassata/common/tdsatypes.h>
75 #include <dev/pms/RefTisa/tisa/sassata/common/tdproto.h>
76 
77 /*****************************************************************************
78 *! \brief  tiINIIOStart
79 *
80 *   Purpose:  This routine is called to initiate a new SCSI request.
81 *
82 *  \param   tiRoot:           Pointer to initiator driver/port instance.
83 *  \param   tiIORequest:      Pointer to the I/O request context for this I/O.
84 *  \param   tiDeviceHandle:   Pointer to device handle for this I/O.
85 *  \param   tiScsiRequest:    Pointer to the SCSI-3 I/O request and SGL list.
86 *  \param   tiRequestBody:    Pointer to the OS Specific module allocated storage
87 *                             to be used by the TD layer for executing this I/O.
88 *  \param   interruptContext: The interrupt context within which this function
89 *                       is called.
90 *  \return:
91 *
92 *  tiSuccess:     I/O request successfully initiated.
93 *  tiBusy:        No resources available, try again later.
94 *  tiIONoDevice:  Invalid device handle.
95 *  tiError:       Other errors that prevent the I/O request to be started.
96 *
97 *
98 *****************************************************************************/
99 osGLOBAL bit32
100 tiINIIOStart(
101              tiRoot_t                  *tiRoot,
102              tiIORequest_t             *tiIORequest,
103              tiDeviceHandle_t          *tiDeviceHandle,
104              tiScsiInitiatorRequest_t  *tiScsiRequest,
105              void                      *tiRequestBody,
106              bit32                     interruptContext
107              )
108 {
109   tdsaRoot_t                *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
110   tdsaContext_t             *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
111   itdsaIni_t                *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni;
112   tdsaDeviceData_t          *oneDeviceData;
113   agsaRoot_t                *agRoot = agNULL;
114   agsaIORequest_t           *agIORequest = agNULL;
115   agsaDevHandle_t           *agDevHandle = agNULL;
116   bit32                     agRequestType;
117   agsaSASRequestBody_t      *agSASRequestBody = agNULL;
118   bit32                     tiStatus = tiError;
119   bit32                     saStatus = AGSA_RC_FAILURE;
120 
121   tdIORequestBody_t         *tdIORequestBody;
122   agsaSSPInitiatorRequest_t *agSSPInitiatorRequest;
123 #ifdef REMOVED
124   /* only for debugging */
125   bit32                      i;
126 #endif
127 
128 #ifdef  SATA_ENABLE
129 #ifndef FDS_SM
130   satIOContext_t            *satIOContext;
131 #endif
132 #endif
133 #ifdef FDS_SM
134   smRoot_t                  *smRoot = &(tdsaAllShared->smRoot);
135   smIORequest_t             *smIORequest;
136   smDeviceHandle_t          *smDeviceHandle;
137   smScsiInitiatorRequest_t  *smSCSIRequest;
138 #endif
139 
140   TDSA_INP_ENTER(tiRoot);
141   TI_DBG6(("tiINIIOStart: start\n"));
142   TI_DBG6(("tiINIIOStart:: ******* tdsaRoot %p tdsaAllShared %p \n", tdsaRoot,tdsaAllShared));
143 
144   oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData;
145 
146   TI_DBG6(("tiINIIOStart: onedevicedata %p\n", oneDeviceData));
147 
148   if(oneDeviceData == agNULL)
149   {
150     TI_DBG1(("tiINIIOStart: tiDeviceHandle=%p DeviceData is NULL\n", tiDeviceHandle ));
151     tiStatus = tiIONoDevice;
152     goto ext;
153   }
154 
155   /* for hotplug */
156   if (oneDeviceData->valid != agTRUE || oneDeviceData->registered != agTRUE ||
157       oneDeviceData->tdPortContext == agNULL )
158   {
159     TI_DBG1(("tiINIIOStart: tiDeviceHandle=%p did %d DeviceData was removed\n", tiDeviceHandle, oneDeviceData->id));
160     TI_DBG6(("tiINIIOStart: device AddrHi 0x%08x AddrLo 0x%08x\n",
161     oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo));
162     // for debugging
163     tdIORequestBody = (tdIORequestBody_t *)tiRequestBody;
164     tdIORequestBody->IOCompletionFunc = itdssIOForDebugging1Completed;
165     TI_DBG6(("tiINIIOStart: IOCompletionFunc %p\n", tdIORequestBody->IOCompletionFunc));
166     tiStatus = tiIONoDevice;
167     goto ext;
168   }
169 #if 1
170   if (tiIORequest->osData == agNULL)
171   {
172     TI_DBG1(("tiINIIOStart: tiIORequest->osData is NULL, wrong\n"));
173   }
174 #endif
175 
176   /* starting IO with SAS device */
177   if (oneDeviceData->DeviceType == TD_SAS_DEVICE)
178   {
179     TI_DBG6(("tiINIIOStart: calling saSSPStart\n"));
180 
181     agRoot = oneDeviceData->agRoot;
182     agDevHandle = oneDeviceData->agDevHandle;
183 
184     /* OS layer has tdlayer data structure pointer in
185        tdIORequestBody_t    tdIOReqBody;
186        in ccb_t in agtiapi.h
187     */
188     tdIORequestBody = (tdIORequestBody_t *)tiRequestBody;
189 
190     /* initialize */
191     osti_memset(tdIORequestBody, 0, sizeof(tdIORequestBody_t));
192 
193     /* let's initialize tdIOrequestBody */
194     /* initialize callback */
195     tdIORequestBody->IOCompletionFunc = itdssIOCompleted;
196 
197     /* initialize tiDevhandle */
198     tdIORequestBody->tiDevHandle = tiDeviceHandle;
199 
200     /* initialize tiIORequest */
201     tdIORequestBody->tiIORequest = tiIORequest;
202 
203     /* save context if we need to abort later */
204     tiIORequest->tdData = tdIORequestBody;
205 
206     /* initialize expDataLength */
207     tdIORequestBody->IOType.InitiatorRegIO.expDataLength
208       = tiScsiRequest->scsiCmnd.expDataLength;
209 
210     tdIORequestBody->IOType.InitiatorRegIO.sglVirtualAddr
211       = tiScsiRequest->sglVirtualAddr;
212 
213     /* initializes "agsaSgl_t   agSgl" of "agsaDifSSPInitiatorRequest_t" */
214     tiStatus = itdssIOPrepareSGL(
215                                  tiRoot,
216                                  tdIORequestBody,
217                                  &tiScsiRequest->agSgl1,
218                                  tiScsiRequest->sglVirtualAddr
219                                  );
220 
221     if (tiStatus != tiSuccess)
222     {
223       TI_DBG1(("tiINIIOStart: can't get SGL\n"));
224       goto ext;
225     }
226 
227 
228     /* initialize agIORequest */
229     agIORequest = &(tdIORequestBody->agIORequest);
230     agIORequest->osData = (void *) tdIORequestBody;
231     agIORequest->sdkData = agNULL; /* LL takes care of this */
232 
233 
234     /*
235       initialize
236       tdIORequestBody_t tdIORequestBody -> agSASRequestBody
237     */
238     agSASRequestBody = &(tdIORequestBody->transport.SAS.agSASRequestBody);
239     agSSPInitiatorRequest = &(agSASRequestBody->sspInitiatorReq);
240 
241     agSSPInitiatorRequest->flag = 0;
242 
243     /* copy cdb bytes */
244     osti_memcpy(agSSPInitiatorRequest->sspCmdIU.cdb, tiScsiRequest->scsiCmnd.cdb, 16);
245 
246     /* copy lun field */
247     osti_memcpy(agSSPInitiatorRequest->sspCmdIU.lun,
248                 tiScsiRequest->scsiCmnd.lun.lun, 8);
249 
250 
251     /* setting the data length */
252     agSSPInitiatorRequest->dataLength  = tiScsiRequest->scsiCmnd.expDataLength;
253     TI_DBG6(("tiINIIOStart: tiScsiRequest->scsiCmnd.expDataLength %d\n", tiScsiRequest->scsiCmnd.expDataLength));
254 
255     agSSPInitiatorRequest->firstBurstSize = 0;
256 
257     /*
258       process taskattribute
259     */
260     if (tiScsiRequest->scsiCmnd.taskAttribute == TASK_SIMPLE)
261     {
262       agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute = (bit8)
263        agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute | TD_TASK_SIMPLE;
264     }
265     else if (tiScsiRequest->scsiCmnd.taskAttribute == TASK_ORDERED)
266     {
267       agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute = (bit8)
268        agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute | TD_TASK_ORDERED;
269     }
270     else if (tiScsiRequest->scsiCmnd.taskAttribute == TASK_HEAD_OF_QUEUE)
271     {
272       agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute = (bit8)
273        agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute | TD_TASK_HEAD_OF_QUEUE;
274     }
275     else if (tiScsiRequest->scsiCmnd.taskAttribute == TASK_ACA)
276     {
277       agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute = (bit8)
278        agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute | TD_TASK_ACA;
279     }
280 
281     if (tiScsiRequest->dataDirection == tiDirectionIn)
282     {
283       agRequestType = AGSA_SSP_INIT_READ;
284       TI_DBG6(("tiINIIOStart: READ\n"));
285     }
286     else if (tiScsiRequest->dataDirection == tiDirectionOut)
287     {
288       agRequestType = AGSA_SSP_INIT_WRITE;
289       TI_DBG6(("tiINIIOStart: WRITE\n"));
290     }
291     else
292     {
293       agRequestType = AGSA_REQ_TYPE_UNKNOWN;
294       TI_DBG1(("tiINIIOStart: unknown data direction\n"));
295     }
296 
297     tdIORequestBody->agRequestType = agRequestType;
298 
299     TI_DBG6(("tiINIIOStart: device AddrHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
300     TI_DBG6(("tiINIIOStart: device AddrLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
301 
302     /* for debugging */
303     if (tdIORequestBody->IOCompletionFunc == agNULL)
304     {
305       TI_DBG1(("tiINIIOStart: Error!!!! IOCompletionFunc is NULL\n"));
306     }
307     saStatus = saSSPStart(agRoot,
308                           agIORequest,
309                           tdsaRotateQnumber(tiRoot, oneDeviceData),
310                           agDevHandle,
311                           agRequestType,
312                           agSASRequestBody,
313                           agNULL,
314                           &ossaSSPCompleted);
315 
316     tdIORequestBody->ioStarted = agTRUE;
317     tdIORequestBody->ioCompleted = agFALSE;
318     tdIORequestBody->reTries = 0;
319 
320     if (saStatus == AGSA_RC_SUCCESS)
321     {
322       Initiator->NumIOsActive++;
323       tiStatus = tiSuccess;
324     }
325     else
326     {
327       tdIORequestBody->ioStarted = agFALSE;
328       tdIORequestBody->ioCompleted = agTRUE;
329       if (saStatus == AGSA_RC_BUSY)
330       {
331         TI_DBG4(("tiINIIOStart: saSSPStart busy\n"));
332         tiStatus = tiBusy;
333       }
334       else
335       {
336         tiStatus = tiError;
337       }
338       goto ext;
339     }
340   }
341 #ifdef FDS_SM
342   else if (oneDeviceData->DeviceType == TD_SATA_DEVICE)
343   {
344     TI_DBG5(("tiINIIOStart: calling satIOStart\n"));
345     TI_DBG5(("tiINIIOStart: onedevicedata did %d\n", oneDeviceData->id));
346     tdIORequestBody = (tdIORequestBody_t *)tiRequestBody;
347     /* initialize */
348     osti_memset(tdIORequestBody, 0, sizeof(tdIORequestBody_t));
349     /* initialize tiDevhandle */
350     tdIORequestBody->tiDevHandle = tiDeviceHandle;
351     tdIORequestBody->superIOFlag = agFALSE;
352 
353     tiIORequest->tdData = tdIORequestBody;
354     tdIORequestBody->tiIORequest = tiIORequest;
355     smIORequest = (smIORequest_t *)&(tdIORequestBody->smIORequest);
356     smIORequest->tdData = tdIORequestBody;
357 
358     smDeviceHandle = (smDeviceHandle_t *)&(oneDeviceData->smDeviceHandle);
359     smDeviceHandle->tdData = oneDeviceData;
360 
361     smSCSIRequest = (smScsiInitiatorRequest_t *)&(tdIORequestBody->SM.smSCSIRequest);
362     osti_memcpy(smSCSIRequest, tiScsiRequest, sizeof(smScsiInitiatorRequest_t));
363 
364     tiStatus = smIOStart(smRoot,
365                          smIORequest,
366                          smDeviceHandle,
367                          smSCSIRequest,
368                          interruptContext);
369     /*
370 osGLOBAL bit32
371 smIOStart(
372           smRoot_t          *smRoot,
373           smIORequest_t         *smIORequest,
374           smDeviceHandle_t      *smDeviceHandle,
375           smScsiInitiatorRequest_t  *smSCSIRequest,
376           bit32             interruptContext
377          )
378 
379 
380     */
381   }
382 #else
383   else if (oneDeviceData->DeviceType == TD_SATA_DEVICE)
384   {
385     TI_DBG5(("tiINIIOStart: calling satIOStart\n"));
386     TI_DBG5(("tiINIIOStart: onedevicedata did %d\n", oneDeviceData->id));
387 
388 #ifdef  SATA_ENABLE
389     tdIORequestBody = (tdIORequestBody_t *)tiRequestBody;
390 
391     /* initialize */
392     osti_memset(tdIORequestBody, 0, sizeof(tdIORequestBody_t));
393 
394     /* initialize tiDevhandle */
395     tdIORequestBody->tiDevHandle = tiDeviceHandle;
396 
397     /* initialize tiIORequest */
398     tdIORequestBody->tiIORequest = tiIORequest;
399     tdIORequestBody->IOCompletionFunc = itdssIOForDebugging2Completed;
400 
401     satIOContext = &(tdIORequestBody->transport.SATA.satIOContext);
402 
403     /*
404      * Need to initialize all the fields within satIOContext except
405      * reqType and satCompleteCB which will be set in sat.c depending on cmd.
406      */
407     tdIORequestBody->transport.SATA.tiSenseData.senseData = agNULL;
408     tdIORequestBody->transport.SATA.tiSenseData.senseLen = 0;
409     satIOContext->pSatDevData   = &oneDeviceData->satDevData;
410     satIOContext->pFis          =
411       &tdIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev;
412     satIOContext->pScsiCmnd     = &tiScsiRequest->scsiCmnd;
413     satIOContext->pSense        = &tdIORequestBody->transport.SATA.sensePayload;
414     satIOContext->pTiSenseData  = &tdIORequestBody->transport.SATA.tiSenseData;
415     satIOContext->pTiSenseData->senseData = satIOContext->pSense;
416     /*    satIOContext->pSense = (scsiRspSense_t *)satIOContext->pTiSenseData->senseData; */
417     satIOContext->tiRequestBody = tiRequestBody;
418     satIOContext->interruptContext = interruptContext;
419     satIOContext->ptiDeviceHandle = tiDeviceHandle;
420     satIOContext->tiScsiXchg = tiScsiRequest;
421     satIOContext->satIntIoContext  = agNULL;
422     satIOContext->satOrgIOContext  = agNULL;
423     /*    satIOContext->tiIORequest      = tiIORequest; */
424 
425     /* save context if we need to abort later */
426     tiIORequest->tdData = tdIORequestBody;
427 
428     /* followings are used only for internal IO */
429     satIOContext->currentLBA = 0;
430     satIOContext->OrgTL = 0;
431 
432     TI_DBG5(("tiINIIOStart: pSatDevData=%p\n", satIOContext->pSatDevData ));
433 
434     tiStatus = satIOStart( tiRoot,
435                            tiIORequest,
436                            tiDeviceHandle,
437                            tiScsiRequest,
438                            satIOContext);
439     goto ext;
440 #endif
441   }
442 #endif /* else of FDS_SM */
443   else
444   {
445 
446     tdIORequestBody = (tdIORequestBody_t *)tiRequestBody;
447     tdIORequestBody->IOCompletionFunc = itdssIOForDebugging3Completed;
448     TI_DBG1(("tiINIIOStart: wrong unspported Device %d\n", oneDeviceData->DeviceType));
449     /*
450       error. unsupported IO
451      */
452   }
453 ext:
454   TDSA_INP_LEAVE(tiRoot);
455   return tiStatus;
456 }
457 
458 #ifdef FAST_IO_TEST
459 osGLOBAL bit32
460 tiINIFastIOSend(void *ioh)
461 {
462   bit32 saStatus, tiStatus;
463 
464   saStatus = saFastSSPSend(ioh);
465   if (saStatus == AGSA_RC_SUCCESS)
466     tiStatus = tiSuccess;
467   else
468     tiStatus = tiError;
469   return tiStatus;
470 }
471 
472 osGLOBAL bit32
473 tiINIFastIOCancel(void *ioh)
474 {
475   bit32 saStatus, tiStatus;
476 
477   saStatus = saFastSSPCancel(ioh);
478   if (saStatus == AGSA_RC_SUCCESS)
479     tiStatus = tiSuccess;
480   else
481     tiStatus = tiError;
482   return tiStatus;
483 }
484 
485 osGLOBAL void*
486 tiINIFastIOPrepare(
487             tiRoot_t          *tiRoot,
488             void              *ioHandle,
489             agsaFastCommand_t *fc)
490 {
491   tdsaDeviceData_t *oneDeviceData;
492   tiDeviceHandle_t *tiDeviceHandle = fc->devHandle;
493   bit32            taskAttribute = fc->taskAttribute;
494   void             *ioh = ioHandle;
495 
496   TDSA_INP_ENTER(tiRoot);
497   TI_DBG6(("tiINIFastIOPrepare: enter\n"));
498 
499   oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData;
500   if(oneDeviceData == agNULL)
501   {
502     TI_DBG1(("tiINIFastIOPrepare: tiDeviceHandle=%p DeviceData is NULL\n",
503              tiDeviceHandle));
504     ioHandle = 0;
505     TD_ASSERT((0), "");
506     goto ext;
507   }
508   TI_DBG6(("tiINIFastIOPrepare: onedevicedata %p\n", oneDeviceData));
509 
510   /* starting IO with SAS device */
511   if (oneDeviceData->DeviceType != TD_SAS_DEVICE)
512   {
513     TI_DBG1(("tiINISuperIOSend: wrong Device %d\n", oneDeviceData->DeviceType));
514     /* error: unsupported IO */
515     ioHandle = 0;
516     TD_ASSERT((0), "");
517     goto ext;
518   }
519 
520   fc->agRoot = oneDeviceData->agRoot;
521   TD_ASSERT((NULL != fc->agRoot), "");
522 
523   fc->devHandle = oneDeviceData->agDevHandle;
524   TD_ASSERT((NULL != fc->devHandle), "");
525   fc->safb->oneDeviceData = oneDeviceData;
526 
527   /*
528     process taskattribute
529   */
530   switch (taskAttribute)
531   {
532     case TASK_SIMPLE:
533       fc->taskAttribute = TD_TASK_SIMPLE;
534       break;
535     case TASK_ORDERED:
536       fc->taskAttribute = TD_TASK_ORDERED;
537       break;
538     case TASK_HEAD_OF_QUEUE:
539       fc->taskAttribute = TD_TASK_HEAD_OF_QUEUE;
540       break;
541     case TASK_ACA:
542       fc->taskAttribute = TD_TASK_ACA;
543       break;
544       /* compile out for "iniload" */
545   }
546 
547 
548   TI_DBG3(("tiINIFastIOPrepare: data direction: %x\n", fc->agRequestType));
549   TI_DBG6(("tiINIFastIOPrepare: device AddrHi/Lo 0x%08x / 0x%08x\n",
550            oneDeviceData->SASAddressID.sasAddressHi,
551            oneDeviceData->SASAddressID.sasAddressLo));
552 
553   fc->queueNum = tdsaRotateQnumber(tiRoot, oneDeviceData);
554 
555   ioHandle = saFastSSPPrepare(ioHandle, fc, ossaFastSSPCompleted, fc->safb);
556   if (!ioHandle)
557   {
558     TI_DBG1(("tiINIFastIOPrepare: saSuperSSPSend error\n"));
559     TD_ASSERT((0), "");
560     //goto ext;
561   }
562 
563 ext:
564   if (ioh && !ioHandle)
565   {
566     saFastSSPCancel(ioh);
567   }
568 
569   TI_DBG6(("tiINIFastIOPrepare: leave\n"));
570 
571   TDSA_INP_LEAVE(tiRoot);
572   return ioHandle;
573 } /* tiINIFastIOPrepare */
574 #endif
575 
576 /*****************************************************************************
577 *
578 *   tiINIIOStartDif
579 *
580 *   Purpose:  This routine is called to initiate a new SCSI request with
581 *             DIF enable.
582 *
583 *   Parameters:
584 *     tiRoot:           Pointer to initiator driver/port instance.
585 *     tiIORequest:      Pointer to the I/O request context for this I/O.
586 *     tiDeviceHandle:   Pointer to device handle for this I/O.
587 *     tiScsiRequest:    Pointer to the SCSI-3 I/O request and SGL list.
588 *     tiRequestBody:    Pointer to the OS Specific module allocated storage
589 *                       to be used by the TD layer for executing this I/O.
590 *     interruptContext: The interrupt context within which this function
591 *                       is called.
592 *     difOption:        DIF option.
593 *
594 *  Return:
595 *
596 *  tiSuccess:     I/O request successfully initiated.
597 *  tiBusy:        No resources available, try again later.
598 *  tiIONoDevice:  Invalid device handle.
599 *  tiError:       Other errors that prevent the I/O request to be started.
600 *
601 *
602 *****************************************************************************/
603 osGLOBAL bit32 tiINIIOStartDif(
604                         tiRoot_t                    *tiRoot,
605                         tiIORequest_t               *tiIORequest,
606                         tiDeviceHandle_t            *tiDeviceHandle,
607                         tiScsiInitiatorRequest_t   *tiScsiRequest,
608                         void                      *tiRequestBody,
609                         bit32                       interruptContext,
610                         tiDif_t                     *difOption
611                         )
612 {
613 
614   /* This function was never used by SAS/SATA. Use tiINISuperIOStart() instead. */
615   return tiBusy;
616 }
617 
618 
619 /*****************************************************************************
620 *
621 *   tiINISuperIOStart
622 *
623 *   Purpose:  This routine is called to initiate a new SCSI request.
624 *
625 *   Parameters:
626 *     tiRoot:           Pointer to initiator driver/port instance.
627 *     tiIORequest:      Pointer to the I/O request context for this I/O.
628 *     tiDeviceHandle:   Pointer to device handle for this I/O.
629 *     tiScsiRequest:    Pointer to the SCSI-3 I/O request and SGL list.
630 *     tiRequestBody:    Pointer to the OS Specific module allocated storage
631 *                       to be used by the TD layer for executing this I/O.
632 *     interruptContext: The interrupt context within which this function
633 *                       is called.
634 *  Return:
635 *
636 *  tiSuccess:     I/O request successfully initiated.
637 *  tiBusy:        No resources available, try again later.
638 *  tiIONoDevice:  Invalid device handle.
639 *  tiError:       Other errors that prevent the I/O request to be started.
640 *
641 *
642 *****************************************************************************/
643 osGLOBAL bit32
644 tiINISuperIOStart(
645              tiRoot_t                       *tiRoot,
646              tiIORequest_t                  *tiIORequest,
647              tiDeviceHandle_t               *tiDeviceHandle,
648              tiSuperScsiInitiatorRequest_t  *tiScsiRequest,
649              void                           *tiRequestBody,
650              bit32                          interruptContext
651              )
652 {
653   tdsaRoot_t                *tdsaRoot = agNULL;
654   tdsaContext_t             *tdsaAllShared = agNULL;
655   itdsaIni_t                *Initiator = agNULL;
656   tdsaDeviceData_t          *oneDeviceData = agNULL;
657   tdIORequestBody_t         *tdIORequestBody = agNULL;
658   agsaSSPInitiatorRequest_t *agSSPInitiatorRequest = agNULL;
659   agsaRoot_t                *agRoot = agNULL;
660   agsaIORequest_t           *agIORequest = agNULL;
661   agsaDevHandle_t           *agDevHandle = agNULL;
662   agsaSASRequestBody_t      *agSASRequestBody = agNULL;
663   bit32                     tiStatus = tiError;
664   bit32                     saStatus = AGSA_RC_FAILURE;
665   bit32                     adjusted_length = 0;
666   bit32                     agRequestType   = 0;
667   agBOOLEAN                 needPlusDataLenAdjustment = agFALSE;
668   agBOOLEAN                 needMinusDataLenAdjustment = agFALSE;
669 
670 #ifdef  SATA_ENABLE
671 #ifndef FDS_SM
672   satIOContext_t            *satIOContext;
673 #endif
674 #endif
675 #ifdef FDS_SM
676   smRoot_t                  *smRoot;
677   smIORequest_t             *smIORequest;
678   smDeviceHandle_t          *smDeviceHandle;
679   smSuperScsiInitiatorRequest_t  *smSuperSCSIRequest;
680 #endif
681 #ifdef CCBUILD_INDIRECT_CDB
682   agsaSSPInitiatorRequestIndirect_t *agSSPInitiatorIndRequest = agNULL;
683 #endif
684   TD_ASSERT(tiRoot , "tiRoot");
685   TD_ASSERT(tiIORequest, "tiIORequest");
686   TD_ASSERT(tiDeviceHandle, "tiDeviceHandle");
687   TD_ASSERT(tiRequestBody, "tiRequestBody");
688   TD_ASSERT(tiRoot->tdData, "tiRoot->tdData");
689   TD_ASSERT(tiDeviceHandle, "tiDeviceHandle");
690 
691   tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
692   TD_ASSERT(tdsaRoot, "tdsaRoot");
693 
694   tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
695   TD_ASSERT(tdsaAllShared, "tdsaAllShared");
696 
697   Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni;
698   TD_ASSERT(Initiator, "Initiator");
699 
700   oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData;
701   TD_ASSERT(oneDeviceData, "oneDeviceData");
702 
703 
704 #ifdef FDS_SM
705   smRoot = &(tdsaAllShared->smRoot);
706   TD_ASSERT(smRoot , "smRoot");
707 #endif
708 
709 
710   TI_DBG6(("tiINISuperIOStart: start\n"));
711   TI_DBG6(("tiINISuperIOStart:: ******* tdsaRoot %p tdsaAllShared %p \n", tdsaRoot,tdsaAllShared));
712 
713   TI_DBG6(("tiINISuperIOStart: onedevicedata %p\n", oneDeviceData));
714 
715   if (oneDeviceData == agNULL)
716   {
717     TI_DBG1(("tiINISuperIOStart: tiDeviceHandle=%p DeviceData is NULL\n", tiDeviceHandle ));
718     return tiIONoDevice;
719   }
720 
721   /* for hotplug */
722   if (oneDeviceData->valid != agTRUE || oneDeviceData->registered != agTRUE ||
723       oneDeviceData->tdPortContext == agNULL )
724   {
725     TI_DBG1(("tiINISuperIOStart: tiDeviceHandle=%p did %d DeviceData was removed\n", tiDeviceHandle, oneDeviceData->id));
726     TI_DBG6(("tiINISuperIOStart: device AddrHi 0x%08x AddrLo 0x%08x\n",
727     oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo));
728     // for debugging
729     tdIORequestBody = (tdIORequestBody_t *)tiRequestBody;
730     tdIORequestBody->IOCompletionFunc = itdssIOForDebugging1Completed;
731     TI_DBG6(("tiINISuperIOStart: IOCompletionFunc %p\n", tdIORequestBody->IOCompletionFunc));
732     return tiIONoDevice;
733   }
734 
735 #ifdef DBG
736   if (tiIORequest->osData == agNULL)
737   {
738     TI_DBG1(("tiINISuperIOStart: tiIORequest->osData is NULL, wrong\n"));
739     return tiError;
740   }
741 #endif
742   /* starting IO with SAS device */
743   if (oneDeviceData->DeviceType == TD_SAS_DEVICE)
744   {
745     TI_DBG3(("tiINISuperIOStart: calling saSSPStart\n"));
746 
747     agRoot = oneDeviceData->agRoot;
748     agDevHandle = oneDeviceData->agDevHandle;
749 
750     /* OS layer has tdlayer data structure pointer in tdIORequestBody_t  tdIOReqBody; in ccb_t in agtiapi.h */
751     tdIORequestBody = (tdIORequestBody_t *)tiRequestBody;
752 
753     /* initialize */
754     /*the tdIORequestBody has been initialized in HwBuildIo routine */
755     /*osti_memset(tdIORequestBody, 0, sizeof(tdIORequestBody_t));*/
756 
757     /* let's initialize tdIOrequestBody */
758     /* initialize callback */
759     tdIORequestBody->IOCompletionFunc = itdssIOCompleted;
760 
761     /* initialize tiDevhandle */
762     tdIORequestBody->tiDevHandle = tiDeviceHandle;
763 
764     /* initialize tiIORequest */
765     tdIORequestBody->tiIORequest = tiIORequest;
766 
767     /* save context if we need to abort later */
768     tiIORequest->tdData = tdIORequestBody;
769 
770     /* initialize expDataLength */
771     tdIORequestBody->IOType.InitiatorRegIO.expDataLength
772       = tiScsiRequest->scsiCmnd.expDataLength;
773 
774     tdIORequestBody->IOType.InitiatorRegIO.sglVirtualAddr
775       = tiScsiRequest->sglVirtualAddr;
776 
777     /* initialize agIORequest */
778     agIORequest = &(tdIORequestBody->agIORequest);
779     agIORequest->osData = (void *) tdIORequestBody;
780 
781     /* initialize tdIORequestBody_t tdIORequestBody -> agSASRequestBody */
782     agSASRequestBody = &(tdIORequestBody->transport.SAS.agSASRequestBody);
783     agSSPInitiatorRequest = &(agSASRequestBody->sspInitiatorReq);
784 
785     agSSPInitiatorRequest->flag = 0;
786     if (tiScsiRequest->flags & TI_SCSI_INITIATOR_ENCRYPT)
787     {
788       TI_DBG3(("tiINISuperIOStart: TI_SCSI_INITIATOR_ENCRYPT\n"));
789 
790       /*  Copy all of the relevant encrypt information */
791       agSSPInitiatorRequest->flag |= AGSA_SAS_ENABLE_ENCRYPTION;
792       TD_ASSERT( sizeof(tiEncrypt_t) == sizeof(agsaEncrypt_t) , "sizeof(tiEncrypt_t) == sizeof(agsaEncrypt_t)");
793       osti_memcpy(&agSSPInitiatorRequest->encrypt, &tiScsiRequest->Encrypt, sizeof(agsaEncrypt_t));
794     }
795 
796     if ((tiScsiRequest->flags & TI_SCSI_INITIATOR_DIF) &&
797          (tiScsiRequest->scsiCmnd.cdb[0] == SCSIOPC_READ_10 ||
798           tiScsiRequest->scsiCmnd.cdb[0] == SCSIOPC_WRITE_10 ||
799           tiScsiRequest->scsiCmnd.cdb[0] == SCSIOPC_WRITE_6 ||
800           tiScsiRequest->scsiCmnd.cdb[0] == SCSIOPC_READ_6 ||
801           tiScsiRequest->scsiCmnd.cdb[0] == SCSIOPC_READ_12 ||
802           tiScsiRequest->scsiCmnd.cdb[0] == SCSIOPC_WRITE_12 ||
803           tiScsiRequest->scsiCmnd.cdb[0] == SCSIOPC_WRITE_16 ||
804           tiScsiRequest->scsiCmnd.cdb[0] == SCSIOPC_READ_16 ))
805     {
806       TI_DBG3(("tiINISuperIOStart: TI_SCSI_INITIATOR_DIF\n"));
807       /* Copy all of the relevant DIF information */
808       agSSPInitiatorRequest->flag |= AGSA_SAS_ENABLE_DIF;
809       osti_memcpy(&agSSPInitiatorRequest->dif, &tiScsiRequest->Dif, sizeof(agsaDif_t));
810 
811       /* Check if need to adjust dataLength. */
812       switch (tiScsiRequest->dataDirection)
813       {
814       case tiDirectionOut: /* Write/Outbound */
815           break;
816 
817       case tiDirectionIn:  /* Read/Inbound */
818           if ((agSSPInitiatorRequest->dif.flags & DIF_ACTION_FLAG_MASK) == DIF_INSERT)
819           {
820               needPlusDataLenAdjustment = agTRUE;
821           }
822           break;
823       }
824 
825       /* Set SGL data len XXX This code needs to support more sector sizes */
826       /* Length adjustment for PCIe DMA only not SAS */
827       if (needPlusDataLenAdjustment == agTRUE)
828       {
829         adjusted_length = tiScsiRequest->scsiCmnd.expDataLength;
830         adjusted_length += (adjusted_length/512) * 8;
831         agSSPInitiatorRequest->dataLength = adjusted_length;
832       }
833       else if (needMinusDataLenAdjustment == agTRUE)
834       {
835         adjusted_length = tiScsiRequest->scsiCmnd.expDataLength;
836         adjusted_length -= (adjusted_length/520) * 8;
837         agSSPInitiatorRequest->dataLength = adjusted_length;
838       }
839       else
840       {
841         /* setting the data length */
842         agSSPInitiatorRequest->dataLength  = tiScsiRequest->scsiCmnd.expDataLength;
843       }
844 
845       /* initializes "agsaSgl_t   agSgl" of "agsaDifSSPInitiatorRequest_t" */
846       tiStatus = itdssIOPrepareSGL(
847                                    tiRoot,
848                                    tdIORequestBody,
849                                    &tiScsiRequest->agSgl1,
850                                    tiScsiRequest->sglVirtualAddr
851                                    );
852       TI_DBG2(("tiINISuperIOStart:TI_SCSI_INITIATOR_DIF needMinusDataLenAdjustment %d needPlusDataLenAdjustment %d difAction %X\n",
853                    needMinusDataLenAdjustment,
854                    needPlusDataLenAdjustment,
855                    agSSPInitiatorRequest->dif.flags & DIF_ACTION_FLAG_MASK));
856 
857     }
858     else
859     {
860       /* setting the data length */
861       agSSPInitiatorRequest->dataLength  = tiScsiRequest->scsiCmnd.expDataLength;
862 
863       /* initializes "agsaSgl_t   agSgl" of "agsaSSPInitiatorRequest_t" */
864       tiStatus = itdssIOPrepareSGL(
865                                    tiRoot,
866                                    tdIORequestBody,
867                                    &tiScsiRequest->agSgl1,
868                                    tiScsiRequest->sglVirtualAddr
869                                    );
870     }
871 
872     if (tiStatus != tiSuccess)
873     {
874       TI_DBG1(("tiINISuperIOStart: can't get SGL\n"));
875       return tiStatus;
876     }
877 
878     TI_DBG6(("tiINISuperIOStart: tiScsiRequest->scsiCmnd.expDataLength %d\n", tiScsiRequest->scsiCmnd.expDataLength));
879 
880     /* process taskattribute */
881     if (tiScsiRequest->scsiCmnd.taskAttribute == TASK_SIMPLE)
882     {
883       agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute = (bit8)
884        agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute | TD_TASK_SIMPLE;
885     }
886     else if (tiScsiRequest->scsiCmnd.taskAttribute == TASK_ORDERED)
887     {
888       agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute = (bit8)
889        agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute | TD_TASK_ORDERED;
890     }
891     else if (tiScsiRequest->scsiCmnd.taskAttribute == TASK_HEAD_OF_QUEUE)
892     {
893       agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute = (bit8)
894        agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute | TD_TASK_HEAD_OF_QUEUE;
895     }
896     else if (tiScsiRequest->scsiCmnd.taskAttribute == TASK_ACA)
897     {
898       agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute = (bit8)
899        agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute | TD_TASK_ACA;
900     }
901 
902     /* copy cdb bytes */
903     osti_memcpy(agSSPInitiatorRequest->sspCmdIU.cdb, tiScsiRequest->scsiCmnd.cdb, 16);
904     /* copy lun field */
905     osti_memcpy(agSSPInitiatorRequest->sspCmdIU.lun, tiScsiRequest->scsiCmnd.lun.lun, 8);
906 #ifdef CCBUILD_INDIRECT_CDB
907     /* check the Indirect CDB flag */
908     if (tiScsiRequest->flags & TI_SCSI_INITIATOR_INDIRECT_CDB)
909     {
910       /* Indirect CDB */
911       if (tiScsiRequest->dataDirection == tiDirectionIn)
912       {
913         agRequestType = AGSA_SSP_INIT_READ_INDIRECT;
914         TI_DBG6(("tiINISuperIOStart: Indirect READ\n"));
915       }
916       else if (tiScsiRequest->dataDirection == tiDirectionOut)
917       {
918         agRequestType = AGSA_SSP_INIT_WRITE_INDIRECT;
919         TI_DBG6(("tiINISuperIOStart: Indirect WRITE\n"));
920       }
921       else
922       {
923         agRequestType = AGSA_REQ_TYPE_UNKNOWN;
924         TI_DBG1(("tiINISuperIOStart: unknown data direction\n"));
925       }
926       agSSPInitiatorIndRequest = &(agSASRequestBody->sspInitiatorReqIndirect);
927       /* copy the constructed SSPIU info to indirect SSPIU buffer */
928       osti_memcpy(tiScsiRequest->IndCDBBuffer, &agSSPInitiatorRequest->sspCmdIU, sizeof(agsaSSPCmdInfoUnit_t));
929       /* initialize the indirect CDB buffer address and length */
930       agSSPInitiatorIndRequest->sspInitiatorReqAddrLower32 = tiScsiRequest->IndCDBLowAddr;
931       agSSPInitiatorIndRequest->sspInitiatorReqAddrUpper32 = tiScsiRequest->IndCDBHighAddr;
932       agSSPInitiatorIndRequest->sspInitiatorReqLen         = sizeof(agsaSSPCmdInfoUnit_t);
933     }
934     else
935 #endif //CCBUILD_INDIRECT_CDB
936     {
937       /* Direct CDB */
938       if (tiScsiRequest->dataDirection == tiDirectionIn)
939       {
940         agRequestType = AGSA_SSP_INIT_READ;
941         TI_DBG6(("tiINISuperIOStart: READ\n"));
942       }
943       else if (tiScsiRequest->dataDirection == tiDirectionOut)
944       {
945         agRequestType = AGSA_SSP_INIT_WRITE;
946         TI_DBG6(("tiINISuperIOStart: WRITE\n"));
947       }
948       else
949       {
950         agRequestType = AGSA_REQ_TYPE_UNKNOWN;
951         TI_DBG1(("tiINISuperIOStart: unknown data direction\n"));
952       }
953     }
954 
955     tdIORequestBody->agRequestType = agRequestType;
956 
957     TI_DBG6(("tiINISuperIOStart: device AddrHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
958     TI_DBG6(("tiINISuperIOStart: device AddrLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
959 
960 #ifdef DBG
961     /* for debugging */
962     if (tdIORequestBody->IOCompletionFunc == agNULL)
963     {
964       TI_DBG1(("tiINISuperIOStart: Error!!!! IOCompletionFunc is NULL\n"));
965       return tiError;
966     }
967 #endif
968     saStatus = saSSPStart(agRoot,
969                           agIORequest,
970                           tdsaRotateQnumber(tiRoot, oneDeviceData),
971                           agDevHandle,
972                           agRequestType,
973                           agSASRequestBody,
974                           agNULL,
975                           &ossaSSPCompleted);
976 
977     if (saStatus == AGSA_RC_SUCCESS)
978     {
979       Initiator->NumIOsActive++;
980       tdIORequestBody->ioStarted = agTRUE;
981       tdIORequestBody->ioCompleted = agFALSE;
982       tiStatus = tiSuccess;
983     }
984     else
985     {
986       tdIORequestBody->ioStarted = agFALSE;
987       tdIORequestBody->ioCompleted = agTRUE;
988       if (saStatus == AGSA_RC_BUSY)
989       {
990         TI_DBG4(("tiINISuperIOStart: saSSPStart busy\n"));
991         tiStatus = tiBusy;
992       }
993       else
994       {
995         tiStatus = tiError;
996       }
997       return tiStatus;
998     }
999   }
1000 #ifdef FDS_SM
1001   else if (oneDeviceData->DeviceType == TD_SATA_DEVICE)
1002   {
1003     TI_DBG5(("tiINISuperIOStart: calling satIOStart\n"));
1004     TI_DBG5(("tiINISuperIOStart: onedevicedata did %d\n", oneDeviceData->id));
1005     TI_DBG5(("tiINISuperIOStart: SATA sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
1006     TI_DBG5(("tiINISuperIOStart: SATA sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
1007 
1008     tdIORequestBody = (tdIORequestBody_t *)tiRequestBody;
1009     /* initialize */
1010     /* the tdIORequestBody has been initialized by Storport in SRB Extension */
1011     /*osti_memset(tdIORequestBody, 0, sizeof(tdIORequestBody_t));*/
1012     /* initialize tiDevhandle */
1013     tdIORequestBody->tiDevHandle = tiDeviceHandle;
1014     tdIORequestBody->superIOFlag = agTRUE;
1015 
1016     tiIORequest->tdData = tdIORequestBody;
1017     tdIORequestBody->tiIORequest = tiIORequest;
1018     smIORequest = (smIORequest_t *)&(tdIORequestBody->smIORequest);
1019     smIORequest->tdData = tdIORequestBody;
1020     smIORequest->smData = &tdIORequestBody->smIORequestBody;
1021 
1022     smDeviceHandle = (smDeviceHandle_t *)&(oneDeviceData->smDeviceHandle);
1023     smDeviceHandle->tdData = oneDeviceData;
1024 
1025     smSuperSCSIRequest = (smSuperScsiInitiatorRequest_t *)&(tdIORequestBody->SM.smSuperSCSIRequest);
1026     osti_memcpy(smSuperSCSIRequest, tiScsiRequest, sizeof(smSuperScsiInitiatorRequest_t));
1027 
1028     tiStatus = smSuperIOStart(smRoot,
1029                               smIORequest,
1030                               smDeviceHandle,
1031                               smSuperSCSIRequest,
1032                               oneDeviceData->SASAddressID.sasAddressHi,
1033                               oneDeviceData->SASAddressID.sasAddressLo,
1034                               interruptContext);
1035 
1036   }
1037 #else
1038   else if (oneDeviceData->DeviceType == TD_SATA_DEVICE)
1039   {
1040 
1041     TI_DBG5(("tiINISuperIOStart: calling satIOStart\n"));
1042     TI_DBG5(("tiINISuperIOStart: onedevicedata did %d\n", oneDeviceData->id));
1043 
1044 #ifdef  SATA_ENABLE
1045     tdIORequestBody = (tdIORequestBody_t *)tiRequestBody;
1046 
1047     /* initialize */
1048     osti_memset(tdIORequestBody, 0, sizeof(tdIORequestBody_t));
1049 
1050     /* initialize tiDevhandle */
1051     tdIORequestBody->tiDevHandle = tiDeviceHandle;
1052 
1053     /* initialize tiIORequest */
1054     tdIORequestBody->tiIORequest = tiIORequest;
1055     tdIORequestBody->IOCompletionFunc = itdssIOForDebugging2Completed;
1056 
1057     satIOContext = &(tdIORequestBody->transport.SATA.satIOContext);
1058 
1059     /*
1060      * Need to initialize all the fields within satIOContext except
1061      * reqType and satCompleteCB which will be set in sat.c depending on cmd.
1062      */
1063     tdIORequestBody->transport.SATA.tiSenseData.senseData = agNULL;
1064     tdIORequestBody->transport.SATA.tiSenseData.senseLen = 0;
1065     satIOContext->pSatDevData   = &oneDeviceData->satDevData;
1066     satIOContext->pFis          =
1067       &tdIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev;
1068     satIOContext->pScsiCmnd     = &tiScsiRequest->scsiCmnd;
1069     satIOContext->pSense        = &tdIORequestBody->transport.SATA.sensePayload;
1070     satIOContext->pTiSenseData  = &tdIORequestBody->transport.SATA.tiSenseData;
1071     satIOContext->pTiSenseData->senseData = satIOContext->pSense;
1072     /*    satIOContext->pSense = (scsiRspSense_t *)satIOContext->pTiSenseData->senseData; */
1073     satIOContext->tiRequestBody = tiRequestBody;
1074     satIOContext->interruptContext = interruptContext;
1075     satIOContext->ptiDeviceHandle = tiDeviceHandle;
1076     /*
1077      This code uses a kludge for the tiScsiXchg. Many subroutines in the SATA code
1078      require a tiScsiInitiatorRequest. Since it would be a lot of work to replicate
1079      those functions for a tiSuperScsiInitiatorRequest, we will use a short cut.
1080      The standard pointer will be passed, but the superIOFlag marks the real type of the structure.
1081     */
1082     satIOContext->tiScsiXchg = tiScsiRequest;
1083     satIOContext->superIOFlag = agTRUE;
1084 
1085     satIOContext->satIntIoContext  = agNULL;
1086     satIOContext->satOrgIOContext  = agNULL;
1087     /*    satIOContext->tiIORequest      = tiIORequest; */
1088 
1089     /* save context if we need to abort later */
1090     tiIORequest->tdData = tdIORequestBody;
1091 
1092     /* followings are used only for internal IO */
1093     satIOContext->currentLBA = 0;
1094     satIOContext->OrgTL = 0;
1095 
1096     TI_DBG5(("tiINISuperIOStart: pSatDevData=%p\n", satIOContext->pSatDevData ));
1097 
1098     tiStatus = satIOStart( tiRoot,
1099                            tiIORequest,
1100                            tiDeviceHandle,
1101                            satIOContext->tiScsiXchg,
1102                            satIOContext);
1103 
1104     return tiStatus;
1105 #endif
1106   }
1107 #endif /* else of FDS_SM */
1108 
1109   else
1110   {
1111 
1112     tdIORequestBody = (tdIORequestBody_t *)tiRequestBody;
1113     tdIORequestBody->IOCompletionFunc = itdssIOForDebugging3Completed;
1114     TI_DBG1(("tiINISuperIOStart: wrong unspported Device %d\n", oneDeviceData->DeviceType));
1115     /*
1116       error. unsupported IO
1117      */
1118   }
1119   return tiStatus;
1120 }
1121 
1122 osGLOBAL bit32
1123 tiINISMPStart(
1124        tiRoot_t                  *tiRoot,
1125        tiIORequest_t             *tiIORequest,
1126        tiDeviceHandle_t          *tiDeviceHandle,
1127        tiSMPFrame_t              *tiSMPFrame,
1128        void                      *tiSMPBody,
1129        bit32                     interruptContext
1130        )
1131 {
1132   tdsaDeviceData_t          *oneDeviceData;
1133   agsaIORequest_t           *agIORequest = agNULL;
1134   tdIORequestBody_t         *tdSMPRequestBody = agNULL;
1135   agsaRoot_t                *agRoot = agNULL;
1136   agsaDevHandle_t           *agDevHandle = agNULL;
1137   agsaSASRequestBody_t      *agRequestBody = agNULL;
1138   agsaSMPFrame_t            *agSMPFrame = agNULL;
1139   bit32                     agRequestType;
1140   bit32                     tiStatus = tiError;
1141   bit32                     saStatus = AGSA_RC_FAILURE;
1142   bit32                     queueNum;
1143   TDSA_INP_ENTER(tiRoot);
1144     TI_DBG6(("tiINISMPStart: start\n"));
1145     oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData;
1146   TI_DBG6(("tiINISMPStart: onedevicedata %p\n", oneDeviceData));
1147     TI_DBG6(("tiINISMPStart: tiDeviceHandle %p\n", tiDeviceHandle));
1148   if (oneDeviceData == agNULL)
1149   {
1150     TI_DBG1(("tiINISMPStart: tiDeviceHandle=%p Expander DeviceData is NULL\n", tiDeviceHandle ));
1151     return tiError;
1152   }
1153   if (tiIORequest->osData == agNULL)
1154   {
1155     TI_DBG1(("tiINISMPStart: tiIORequest->osData is NULL, wrong\n"));
1156     return tiError;
1157   }
1158   agRoot = oneDeviceData->agRoot;
1159   agDevHandle = oneDeviceData->agDevHandle;
1160   tdSMPRequestBody = (tdIORequestBody_t *)tiSMPBody;
1161   tdSMPRequestBody->tiIORequest = tiIORequest;
1162   tiIORequest->tdData = tdSMPRequestBody;
1163   agIORequest = &(tdSMPRequestBody->agIORequest);
1164   agIORequest->osData = (void *) tdSMPRequestBody;
1165   agRequestBody = &(tdSMPRequestBody->transport.SAS.agSASRequestBody);
1166   agSMPFrame = &(agRequestBody->smpFrame);
1167   if (!DEVICE_IS_SMP_TARGET(oneDeviceData))
1168   {
1169     TI_DBG1(("tiINISMPStart: Target Device is not SMP device\n"));
1170     return tiError;
1171   }
1172   if (tiSMPFrame->flag == 0) // define DIRECT SMP at td layer?
1173   {
1174     TI_DBG6(("tiINISMPStart: Direct SMP\n"));
1175     agSMPFrame->outFrameBuf = tiSMPFrame->outFrameBuf;
1176     agSMPFrame->outFrameLen = tiSMPFrame->outFrameLen;
1177     tdhexdump("tiINISMPStart agSMPFrame", (bit8 *)agSMPFrame->outFrameBuf, agSMPFrame->outFrameLen);
1178     agSMPFrame->expectedRespLen = tiSMPFrame->expectedRespLen;
1179     agSMPFrame->inFrameLen = 0;
1180     agSMPFrame->flag = tiSMPFrame->flag;
1181     agRequestType = AGSA_SMP_INIT_REQ;
1182     queueNum = 0;
1183     saStatus = saSMPStart(agRoot,
1184                 agIORequest,
1185                 queueNum,
1186                 agDevHandle,
1187                 agRequestType,
1188                 agRequestBody,
1189                 &ossaSMPCAMCompleted
1190                );
1191     if (saStatus == AGSA_RC_SUCCESS)
1192     {
1193       tiStatus = tiSuccess;
1194     }
1195     else
1196     {
1197       if (saStatus == AGSA_RC_BUSY)
1198       {
1199         TI_DBG1(("tiINISMPStart: saSSPStart busy\n"));
1200         tiStatus = tiBusy;
1201       }
1202       else
1203       {
1204         TI_DBG1(("tiINISMPStart: saSSPStart error\n"));
1205         tiStatus = tiError;
1206       }
1207       return tiStatus;
1208     }
1209   }
1210   else
1211   {
1212     TI_DBG1(("tiINISMPStart: Indirect SMP! Not supported yet\n"));
1213     tiStatus = tiError;
1214   }
1215   return tiStatus;
1216 }
1217 #ifdef TD_INT_COALESCE
1218 osGLOBAL bit32
1219 tiINIIOStartIntCoalesce(
1220              tiRoot_t                  *tiRoot,
1221              tiIORequest_t             *tiIORequest,
1222              tiDeviceHandle_t          *tiDeviceHandle,
1223              tiScsiInitiatorRequest_t *tiScsiRequest,
1224              void                      *tiRequestBody,
1225              bit32                     interruptContext,
1226              tiIntCoalesceContext_t    *tiIntCoalesceCxt
1227              )
1228 {
1229   tdsaRoot_t                *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
1230   tdsaContext_t             *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
1231   itdsaIni_t                *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni;
1232   tdsaDeviceData_t          *oneDeviceData;
1233   agsaRoot_t                *agRoot = agNULL;
1234   agsaIORequest_t           *agIORequest = agNULL;
1235   agsaDevHandle_t           *agDevHandle = agNULL;
1236   bit32                     agRequestType;
1237   agsaSASRequestBody_t      *agSASRequestBody = agNULL;
1238   bit32                     tiStatus = tiError;
1239   bit32                     saStatus = AGSA_RC_FAILURE;
1240 
1241   tdIORequestBody_t         *tdIORequestBody;
1242   agsaSSPInitiatorRequest_t *agSSPInitiatorRequest;
1243   tdsaIntCoalesceContext_t  *tdsaIntCoalCxt;
1244   agsaIntCoalesceContext_t  *agIntCoalCxt;
1245 
1246   TI_DBG1(("tiINIIOStartIntCoalesce: start\n"));
1247   oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData;
1248 
1249   TI_DBG6(("tiINIIOStartIntCoalesce: onedevicedata %p\n", oneDeviceData));
1250 
1251   if(oneDeviceData == agNULL)
1252   {
1253     TI_DBG1(("tiINIIOStartIntCoalesce: tiDeviceHandle=%p DeviceData is NULL\n", tiDeviceHandle ));
1254     return tiIONoDevice;
1255   }
1256 
1257   /* starting IO with SAS device */
1258   if (oneDeviceData->DeviceType == TD_SAS_DEVICE)
1259   {
1260     TI_DBG6(("tiINIIOStartIntCoalesce: calling saSSPStart\n"));
1261 
1262     agRoot = oneDeviceData->agRoot;
1263     agDevHandle = oneDeviceData->agDevHandle;
1264 
1265     /* OS layer has tdlayer data structure pointer in
1266        tdIORequestBody_t    tdIOReqBody;
1267        in ccb_t in agtiapi.h
1268     */
1269     tdIORequestBody = (tdIORequestBody_t *)tiRequestBody;
1270 
1271     /* let's initialize tdIOrequestBody */
1272     /* initialize callback */
1273     tdIORequestBody->IOCompletionFunc = itdssIOCompleted;
1274 
1275     /* initialize tiDevhandle */
1276     tdIORequestBody->tiDevHandle = tiDeviceHandle;
1277 
1278     /* initialize tiIORequest */
1279     tdIORequestBody->tiIORequest = tiIORequest;
1280 
1281     /* save context if we need to abort later */
1282     tiIORequest->tdData = tdIORequestBody;
1283 
1284     /* initialize expDataLength */
1285     tdIORequestBody->IOType.InitiatorRegIO.expDataLength
1286       = tiScsiRequest->scsiCmnd.expDataLength;
1287 
1288     /* initializes "agsaSgl_t   agSgl" of "agsaDifSSPInitiatorRequest_t" */
1289     tiStatus = itdssIOPrepareSGL(
1290                                  tiRoot,
1291                                  tdIORequestBody,
1292                                  &tiScsiRequest->agSgl1,
1293                                  tiScsiRequest->sglVirtualAddr
1294                                  );
1295 
1296     if (tiStatus != tiSuccess)
1297     {
1298       TI_DBG1(("tiINIIOStartIntCoalesce: can't get SGL\n"));
1299       return tiStatus;
1300     }
1301 
1302 
1303     /* initialize agIORequest */
1304     agIORequest = &(tdIORequestBody->agIORequest);
1305     agIORequest->osData = (void *) tdIORequestBody;
1306     agIORequest->sdkData = agNULL; /* LL takes care of this */
1307 
1308 
1309     /*
1310       initialize
1311       tdIORequestBody_t tdIORequestBody -> agSASRequestBody
1312     */
1313     agSASRequestBody = &(tdIORequestBody->transport.SAS.agSASRequestBody);
1314     agSSPInitiatorRequest = &(agSASRequestBody->sspInitiatorReq);
1315 
1316 
1317     /* copy cdb bytes */
1318     osti_memcpy(agSSPInitiatorRequest->sspCmdIU.cdb, tiScsiRequest->scsiCmnd.cdb, 16);
1319 
1320     /* copy lun field */
1321     osti_memcpy(agSSPInitiatorRequest->sspCmdIU.lun,
1322                 tiScsiRequest->scsiCmnd.lun.lun, 8);
1323 
1324     /* setting the data length */
1325     agSSPInitiatorRequest->dataLength  = tiScsiRequest->scsiCmnd.expDataLength;
1326     TI_DBG6(("tiINIIOStartIntCoalesce: tiScsiRequest->scsiCmnd.expDataLength %d\n", tiScsiRequest->scsiCmnd.expDataLength));
1327 
1328     agSSPInitiatorRequest->firstBurstSize = 0;
1329 
1330     if (tiScsiRequest->dataDirection == tiDirectionIn)
1331     {
1332       agRequestType = AGSA_SSP_INIT_READ;
1333       TI_DBG6(("tiINIIOStartIntCoalesce: READ\n"));
1334     }
1335     else if (tiScsiRequest->dataDirection == tiDirectionOut)
1336     {
1337       agRequestType = AGSA_SSP_INIT_WRITE;
1338       TI_DBG6(("tiINIIOStartIntCoalesce: WRITE\n"));
1339     }
1340     else
1341     {
1342       agRequestType = AGSA_REQ_TYPE_UNKNOWN;
1343       TI_DBG1(("tiINIIOStartIntCoalesce: unknown data direction\n"));
1344     }
1345 
1346     tdIORequestBody->agRequestType = agRequestType;
1347 
1348     tdsaIntCoalCxt = (tdsaIntCoalesceContext_t *)tiIntCoalesceCxt->tdData;
1349     agIntCoalCxt = &(tdsaIntCoalCxt->agIntCoalCxt);
1350 
1351 
1352 
1353 #ifdef LL_INT_COALESCE
1354     saStatus = saSSPStartIntCoalesce(agRoot,
1355                                      agIORequest,
1356                                      agIntCoalCxt,
1357                                      agDevHandle,
1358                                      agRequestType,
1359                                      agSASRequestBody,
1360                                      &ossaSSPCompleted);
1361 #endif
1362 
1363     tdIORequestBody->ioStarted = agTRUE;
1364     tdIORequestBody->ioCompleted = agFALSE;
1365 
1366     if (saStatus == AGSA_RC_SUCCESS)
1367     {
1368       Initiator->NumIOsActive++;
1369       tiStatus = tiSuccess;
1370     }
1371     else
1372     {
1373       TI_DBG1(("tiINIIOStartIntCoalesce: saSSPStart failed\n"));
1374       tdIORequestBody->ioStarted = agFALSE;
1375       tdIORequestBody->ioCompleted = agTRUE;
1376       if (saStatus == AGSA_RC_BUSY)
1377       {
1378         tiStatus = tiBusy;
1379       }
1380       else
1381       {
1382         tiStatus = tiError;
1383       }
1384       return tiStatus;
1385     }
1386   }
1387 
1388   else if (oneDeviceData->DeviceType == TD_SATA_DEVICE)
1389   {
1390     /*
1391       satIOStart() -> saSATAStartIntCoalesce()
1392     */
1393     TI_DBG1(("tiINIIOStartIntCoalesce: SATA not supported yet\n"));
1394     return tiStatus;
1395   }
1396   else
1397   {
1398     TI_DBG1(("tiINIIOStartIntCoalesce: wrong unspported Device %d\n", oneDeviceData->DeviceType));
1399     /*
1400       error. unsupported IO
1401      */
1402   }
1403   return tiStatus;
1404 
1405 
1406 }
1407 
1408 osGLOBAL bit32
1409 tiINIIOStartIntCoalesceDif(
1410                            tiRoot_t                  *tiRoot,
1411                            tiIORequest_t             *tiIORequest,
1412                            tiDeviceHandle_t          *tiDeviceHandle,
1413                            tiScsiInitiatorRequest_t *tiScsiRequest,
1414                            void                      *tiRequestBody,
1415                            bit32                     interruptContext,
1416                            tiIntCoalesceContext_t    *tiIntCoalesceCxt,
1417                            tiDif_t                   *difOption
1418                            )
1419 {
1420   tdsaRoot_t                   *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
1421   tdsaContext_t                *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
1422   itdsaIni_t                   *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni;
1423   tdsaDeviceData_t             *oneDeviceData;
1424   agsaRoot_t                   *agRoot = agNULL;
1425   agsaIORequest_t              *agIORequest = agNULL;
1426   agsaDevHandle_t              *agDevHandle = agNULL;
1427   bit32                        agRequestType;
1428   agsaDifSSPRequestBody_t      *agEdcSSPRequestBody = agNULL;
1429   bit32                        tiStatus = tiError;
1430   bit32                        saStatus = AGSA_RC_FAILURE;
1431 
1432   tdIORequestBody_t            *tdIORequestBody;
1433   agsaDifSSPInitiatorRequest_t *agEdcSSPInitiatorRequest;
1434   agsaDif_t                    *agEdc;
1435   bit32                        agUpdateMask = 0;
1436   bit32                        agVerifyMask = 0;
1437   tdsaIntCoalesceContext_t     *tdsaIntCoalCxt;
1438   agsaIntCoalesceContext_t     *agIntCoalCxt;
1439 
1440   TI_DBG1(("tiINIIOStartIntCoalesceDif: start\n"));
1441   oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData;
1442 
1443   TI_DBG6(("tiINIIOStartIntCoalesceDif: onedevicedata %p\n", oneDeviceData));
1444 
1445   if(oneDeviceData == agNULL)
1446   {
1447     TI_DBG1(("tiINIIOStartIntCoalesceDif: tiDeviceHandle=%p DeviceData is NULL\n", tiDeviceHandle ));
1448     return tiIONoDevice;
1449   }
1450 
1451   /* starting IO with SAS device */
1452   if (oneDeviceData->DeviceType == TD_SAS_DEVICE)
1453   {
1454     TI_DBG6(("tiINIIOStartIntCoalesceDif: calling saSSPStart\n"));
1455 
1456     agRoot = oneDeviceData->agRoot;
1457     agDevHandle = oneDeviceData->agDevHandle;
1458 
1459     /* OS layer has tdlayer data structure pointer in
1460        tdIORequestBody_t    tdIOReqBody;
1461        in ccb_t in agtiapi.h
1462     */
1463     tdIORequestBody = (tdIORequestBody_t *)tiRequestBody;
1464 
1465     /* let's initialize tdIOrequestBody */
1466     /* initialize callback */
1467     tdIORequestBody->IOCompletionFunc = itdssIOCompleted;
1468 
1469     /* initialize tiDevhandle */
1470     tdIORequestBody->tiDevHandle = tiDeviceHandle;
1471 
1472     /* initialize tiIORequest */
1473     tdIORequestBody->tiIORequest = tiIORequest;
1474 
1475     /* save context if we need to abort later */
1476     tiIORequest->tdData = tdIORequestBody;
1477 
1478     /* initialize expDataLength */
1479     tdIORequestBody->IOType.InitiatorRegIO.expDataLength
1480       = tiScsiRequest->scsiCmnd.expDataLength;
1481 
1482     /* initializes "agsaSgl_t   agSgl" of "agsaDifSSPInitiatorRequest_t" */
1483     tiStatus = itdssIOPrepareSGL(
1484                                  tiRoot,
1485                                  tdIORequestBody,
1486                                  &tiScsiRequest->agSgl1,
1487                                  tiScsiRequest->sglVirtualAddr
1488                                  );
1489 
1490     if (tiStatus != tiSuccess)
1491     {
1492       TI_DBG1(("tiINIIOStartIntCoalesceDif: can't get SGL\n"));
1493       return tiStatus;
1494     }
1495 
1496 
1497     /* initialize agIORequest */
1498     agIORequest = &(tdIORequestBody->agIORequest);
1499     agIORequest->osData = (void *) tdIORequestBody;
1500     agIORequest->sdkData = agNULL; /* LL takes care of this */
1501 
1502 
1503     /*
1504       initialize
1505       tdIORequestBody_t tdIORequestBody -> agSASRequestBody
1506     */
1507     agEdcSSPRequestBody = &(tdIORequestBody->transport.SAS.agEdcSSPRequestBody);
1508     agEdcSSPInitiatorRequest = &(agEdcSSPRequestBody->edcSSPInitiatorReq);
1509 
1510 
1511     /* copy cdb bytes */
1512     osti_memcpy(agEdcSSPInitiatorRequest->sspCmdIU.cdb, tiScsiRequest->scsiCmnd.cdb, 16);
1513 
1514     /* copy lun field */
1515     osti_memcpy(agEdcSSPInitiatorRequest->sspCmdIU.lun,
1516                 tiScsiRequest->scsiCmnd.lun.lun, 8);
1517 
1518 
1519     /* setting the data length */
1520     agEdcSSPInitiatorRequest->dataLength  = tiScsiRequest->scsiCmnd.expDataLength;
1521     TI_DBG6(("tiINIIOStartIntCoalesceDif: tiScsiRequest->scsiCmnd.expDataLength %d\n", tiScsiRequest->scsiCmnd.expDataLength));
1522 
1523     agEdcSSPInitiatorRequest->firstBurstSize = 0;
1524 
1525 
1526     if (tiScsiRequest->dataDirection == tiDirectionIn)
1527     {
1528       agRequestType = AGSA_SSP_INIT_READ;
1529       TI_DBG1(("tiINIIOStartIntCoalesceDif: READ difAction %X\n",difOption->difAction));
1530     }
1531     else if (tiScsiRequest->dataDirection == tiDirectionOut)
1532     {
1533       agRequestType = AGSA_SSP_INIT_WRITE;
1534       TI_DBG1(("tiINIIOStartIntCoalesceDif: WRITE difAction %X\n",difOption->difAction));
1535     }
1536     else
1537     {
1538       agRequestType = AGSA_REQ_TYPE_UNKNOWN;
1539       TI_DBG1(("tiINIIOStartIntCoalesceDif: unknown data direction\n"));
1540     }
1541 
1542     tdIORequestBody->agRequestType = agRequestType;
1543 
1544     /* process interrupt coalesce context */
1545     tdsaIntCoalCxt = (tdsaIntCoalesceContext_t *)tiIntCoalesceCxt->tdData;
1546     agIntCoalCxt = &(tdsaIntCoalCxt->agIntCoalCxt);
1547 
1548     /* process DIF */
1549 
1550     agEdc = &(agEdcSSPInitiatorRequest->edc);
1551 
1552     osti_memset(agEdc, 0, sizeof(agsaDif_t));
1553 
1554     /* setting edcFlag */
1555     if (difOption->enableBlockCount)
1556     {
1557       /* enables block count; bit5 */
1558       agEdc->edcFlag = agEdc->edcFlag | 0x20; /* 0010 0000 */
1559     }
1560 
1561     if (difOption->enableCrc)
1562     {
1563       /* enables CRC verification; bit6 */
1564       agEdc->edcFlag = agEdc->edcFlag | 0x40; /* 0100 0000 */
1565     }
1566 
1567     if (difOption->enableIOSeed)
1568     {
1569 
1570     }
1571     if (difOption->difAction == DIF_INSERT)
1572     {
1573       /* bit 0 - 2; 000 */
1574       agEdc->edcFlag = agEdc->edcFlag & 0xFFFFFFF8;
1575     }
1576     else if (difOption->difAction == DIF_VERIFY_FORWARD)
1577     {
1578       /* bit 0 - 2; 001 */
1579       agEdc->edcFlag = agEdc->edcFlag | 0x01;
1580     }
1581     else if (difOption->difAction == DIF_VERIFY_DELETE)
1582     {
1583       /* bit 0 - 2; 010 */
1584       agEdc->edcFlag = agEdc->edcFlag | 0x02;
1585     }
1586     else
1587     {
1588       /* DIF_VERIFY_REPLACE */
1589       /* bit 0 - 2; 011 */
1590       agEdc->edcFlag = agEdc->edcFlag | 0x04;
1591     }
1592 
1593     /* set Update Mask; bit 16-21 */
1594     agUpdateMask = (difOption->tagUpdateMask) & 0x3F; /* 0011 1111 */
1595     agUpdateMask = agUpdateMask << 16;
1596     agEdc->edcFlag = agEdc->edcFlag | agUpdateMask;
1597 
1598     /* set Verify Mask bit 24-29 */
1599     agVerifyMask = (difOption->tagVerifyMask) & 0x3F; /* 0011 1111 */
1600     agVerifyMask = agVerifyMask << 24;
1601     agEdc->edcFlag = agEdc->edcFlag | agVerifyMask;
1602 
1603     agEdc->appTag = difOption->udtArray[0];
1604     agEdc->appTag = (agEdc->appTag << 8) | difOption->udtArray[1];
1605 
1606     agEdc->lbaReferenceTag =  difOption->udtArray[2];
1607     agEdc->lbaReferenceTag = (agEdc->lbaReferenceTag << 8) | difOption->udtArray[3];
1608     agEdc->lbaReferenceTag = (agEdc->lbaReferenceTag << 8) | difOption->udtArray[4];
1609     agEdc->lbaReferenceTag = (agEdc->lbaReferenceTag << 8) | difOption->udtArray[5];
1610 
1611     /* currently TISA supports only 512 logical block size */
1612     agEdc->lbSize = 512;
1613 
1614 
1615 #ifdef LL_INT_COALESCE
1616     saStatus = saSSPStartIntCoalesceEdc(agRoot,
1617                                         agIORequest,
1618                                         agIntCoalCxt,
1619                                         agDevHandle,
1620                                         agRequestType,
1621                                         agEdcSSPRequestBody,
1622                                         &ossaSSPCompleted);
1623 #endif
1624 
1625     tdIORequestBody->ioStarted = agTRUE;
1626     tdIORequestBody->ioCompleted = agFALSE;
1627 
1628     if (saStatus == AGSA_RC_SUCCESS)
1629     {
1630       Initiator->NumIOsActive++;
1631       tiStatus = tiSuccess;
1632     }
1633     else
1634     {
1635       TI_DBG1(("tiINIIOStartIntCoalesceDif: saSSPStart failed\n"));
1636       tdIORequestBody->ioStarted = agFALSE;
1637       tdIORequestBody->ioCompleted = agTRUE;
1638       if (saStatus == AGSA_RC_BUSY)
1639       {
1640         tiStatus = tiBusy;
1641       }
1642       else
1643       {
1644         tiStatus = tiError;
1645       }
1646       return tiStatus;
1647     }
1648   }
1649   else if (oneDeviceData->DeviceType == TD_SATA_DEVICE)
1650   {
1651     /*
1652       satIOStart() -> saSATAStartIntCoalesceEdc()
1653     */
1654     TI_DBG1(("tiINIIOStartIntCoalesceDif: SATA not supported yet\n"));
1655     return tiStatus;
1656   }
1657   else
1658   {
1659     TI_DBG1(("tiINIIOStartIntCoalesceDif: wrong unspported Device %d\n", oneDeviceData->DeviceType));
1660     /*
1661       error. unsupported IO
1662      */
1663   }
1664   return tiStatus;
1665 }
1666 
1667 
1668 osGLOBAL bit32
1669 tiINIIntCoalesceInit(
1670                      tiRoot_t                  *tiRoot,
1671                      tiIntCoalesceContext_t    *tiIntCoalesceCxt,
1672                      bit32                     count
1673                      )
1674 {
1675 
1676   tdsaRoot_t                *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
1677   tdsaContext_t             *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
1678   agsaRoot_t                *agRoot = agNULL;
1679   tdsaIntCoalesceContext_t  *tdsaIntCoalCxtHead
1680     = (tdsaIntCoalesceContext_t *)tdsaAllShared->IntCoalesce;
1681   tdsaIntCoalesceContext_t  *tdsaIntCoalCxt;
1682   agsaIntCoalesceContext_t  *agIntCoalCxt;
1683   tdList_t                  *tdsaIntCoalCxtList = agNULL;
1684 
1685   bit32                     tiStatus = tiError;
1686 
1687   TI_DBG1(("tiINIIntCoalesceInit: start\n"));
1688 
1689   tdsaSingleThreadedEnter(tiRoot, TD_INTCOAL_LOCK);
1690   if (TDLIST_NOT_EMPTY(&(tdsaIntCoalCxtHead->FreeLink)))
1691   {
1692     TDLIST_DEQUEUE_FROM_HEAD(&tdsaIntCoalCxtList, &(tdsaIntCoalCxtHead->FreeLink));
1693     tdsaSingleThreadedLeave(tiRoot, TD_INTCOAL_LOCK);
1694     tdsaIntCoalCxt
1695       = TDLIST_OBJECT_BASE(tdsaIntCoalesceContext_t, FreeLink, tdsaIntCoalCxtList);
1696 
1697     TI_DBG1(("tiINIIntCoalesceInit: id %d\n", tdsaIntCoalCxt->id));
1698 
1699     agRoot = &(tdsaAllShared->agRootNonInt);
1700 
1701     agIntCoalCxt = &(tdsaIntCoalCxt->agIntCoalCxt);
1702     tdsaIntCoalCxt->tiIntCoalesceCxt = tiIntCoalesceCxt;
1703     tiIntCoalesceCxt->tdData = tdsaIntCoalCxt;
1704     agIntCoalCxt->osData = tdsaIntCoalCxt;
1705 
1706     tdsaSingleThreadedEnter(tiRoot, TD_INTCOAL_LOCK);
1707     TDLIST_ENQUEUE_AT_TAIL(&(tdsaIntCoalCxt->MainLink), &(tdsaIntCoalCxtHead->MainLink));
1708     tdsaSingleThreadedLeave(tiRoot, TD_INTCOAL_LOCK);
1709 
1710     /*
1711       note: currently asynchronously call is assumed. In other words,
1712       "ossaIntCoalesceInitCB()" -> "ostiInitiatorCoalesceInitCB()" are used
1713     */
1714 #ifdef LL_INT_COALESCE
1715     tiStatus = saIntCoalesceInit(agRoot, agIntCoalCxt, count);
1716 #endif
1717 
1718     TI_DBG6(("tiINIIntCoalesceInit: status %d\n", tiStatus));
1719     return tiStatus;
1720   }
1721   else
1722   {
1723     tdsaSingleThreadedLeave(tiRoot, TD_INTCOAL_LOCK);
1724     TI_DBG1(("tiINIIntCoalesceInit: no more interrupt coalesce context; return fail\n"));
1725     return tiStatus;
1726   }
1727 }
1728 #endif /* TD_INT_COALESCE */
1729 
1730 /*****************************************************************************
1731 *! \brief itdssIOPrepareSGL
1732 *
1733 *  Purpose:  This function is called to translate TISA SGL information to the
1734 *            LL layer SGL.
1735 *
1736 *  \param    tiRoot:         Pointer to initiator driver/port instance.
1737 *  \param    IORequestBody:  TD layer request body for the I/O.
1738 *  \param    tiSgl1:         First TISA SGL info.
1739 *  \param    sglVirtualAddr: The virtual address of the first element in
1740 *                            tiSgl1 when tiSgl1 is used with the type tiSglList.
1741 *
1742 *  \return:
1743 *
1744 *  tiSuccess:     SGL initialized successfully.
1745 *  tiError:       Failed to initialize SGL.
1746 *
1747 *
1748 *****************************************************************************/
1749 osGLOBAL FORCEINLINE bit32
1750 itdssIOPrepareSGL(
1751                   tiRoot_t                 *tiRoot,
1752                   tdIORequestBody_t        *tdIORequestBody,
1753                   tiSgl_t                  *tiSgl1,
1754                   void                     *sglVirtualAddr
1755                   )
1756 {
1757   agsaSgl_t                 *agSgl;
1758 
1759   TI_DBG6(("itdssIOPrepareSGL: start\n"));
1760 
1761   agSgl = &(tdIORequestBody->transport.SAS.agSASRequestBody.sspInitiatorReq.agSgl);
1762 
1763   agSgl->len = 0;
1764 
1765   if (tiSgl1 == agNULL)
1766   {
1767     TI_DBG1(("itdssIOPrepareSGL: Error tiSgl1 is NULL\n"));
1768     return tiError;
1769   }
1770 
1771   if (tdIORequestBody->IOType.InitiatorRegIO.expDataLength == 0)
1772   {
1773     TI_DBG6(("itdssIOPrepareSGL: expDataLength is 0\n"));
1774     agSgl->sgUpper = 0;
1775     agSgl->sgLower = 0;
1776     agSgl->len = 0;
1777     CLEAR_ESGL_EXTEND(agSgl->extReserved);
1778     return tiSuccess;
1779   }
1780 
1781   agSgl->sgUpper = tiSgl1->upper;
1782   agSgl->sgLower = tiSgl1->lower;
1783   agSgl->len = tiSgl1->len;
1784   agSgl->extReserved = tiSgl1->type;
1785 
1786   return tiSuccess;
1787 }
1788 
1789 osGLOBAL bit32
1790 tiNumOfLunIOCTLreq(
1791              tiRoot_t                       *tiRoot,
1792              tiIORequest_t                  *tiIORequest,
1793              tiDeviceHandle_t               *tiDeviceHandle,
1794              void                           *tiRequestBody,
1795              tiIOCTLPayload_t               *agIOCTLPayload,
1796              void                           *agParam1,
1797              void                           *agParam2
1798              )
1799 {
1800   tdsaRoot_t			    *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
1801   tdsaContext_t			    *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
1802   agsaRoot_t			    *agRoot = &(tdsaAllShared->agRootInt);
1803   void					    *respBuffer = agNULL;
1804   void					    *osMemHandle = agNULL;
1805   bit32					    ostiMemoryStatus = 0;
1806   tdsaDeviceData_t		    *oneDeviceData = agNULL;
1807   agsaSSPInitiatorRequest_t *agSSPFrame = agNULL;
1808   bit32					    status = IOCTL_CALL_SUCCESS;
1809   bit32					    agRequestType = 0;
1810   agsaDevHandle_t 		    *agDevHandle = agNULL;
1811   agsaIORequest_t 		    *agIORequest = agNULL;
1812   tdIORequestBody_t		    *tdIORequestBody = agNULL;
1813   agsaSASRequestBody_t	    *agSASRequestBody = agNULL;
1814 
1815   do
1816   {
1817     if((tiIORequest == agNULL) || (tiRequestBody == agNULL))
1818     {
1819       status = IOCTL_CALL_FAIL;
1820       break;
1821     }
1822     tdIORequestBody = (tdIORequestBody_t *)tiRequestBody;
1823 
1824     if(tdIORequestBody == agNULL)
1825     {
1826       status = IOCTL_CALL_FAIL;
1827       break;
1828     }
1829     tdIORequestBody->tiIORequest = tiIORequest;
1830 
1831     /* save context if we need to abort later */
1832     tiIORequest->tdData = tdIORequestBody;
1833 
1834     agIORequest = &(tdIORequestBody->agIORequest);
1835     agIORequest->osData = (void *) tdIORequestBody;
1836     agSASRequestBody = &(tdIORequestBody->transport.SAS.agSASRequestBody);
1837     agSSPFrame = &(agSASRequestBody->sspInitiatorReq);
1838 
1839     ostiMemoryStatus = ostiAllocMemory( tiRoot,
1840     									  &osMemHandle,
1841     									  (void **)&respBuffer,
1842     									  &(agSSPFrame->agSgl.sgUpper),
1843     									  &(agSSPFrame->agSgl.sgLower),
1844     									  8,
1845     									  REPORT_LUN_LEN,
1846     									  agFALSE);
1847     if((ostiMemoryStatus != tiSuccess) && (respBuffer == agNULL  ))
1848     {
1849       status = IOCTL_CALL_FAIL;
1850       break;
1851     }
1852 
1853     osti_memset((void *)respBuffer, 0, REPORT_LUN_LEN);
1854 
1855     	// use FW control place in shared structure to keep the neccesary information
1856     tdsaAllShared->tdFWControlEx.virtAddr = respBuffer;
1857     tdsaAllShared->tdFWControlEx.len = REPORT_LUN_LEN;
1858     tdsaAllShared->tdFWControlEx.param1 = agParam1;
1859     tdsaAllShared->tdFWControlEx.param2 = agParam2;
1860     tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload;
1861     tdsaAllShared->tdFWControlEx.inProgress = 1;
1862     agRequestType = AGSA_SSP_INIT_READ;
1863 
1864     status = IOCTL_CALL_PENDING;
1865     oneDeviceData = (tdsaDeviceData_t *)(tiDeviceHandle->tdData);
1866     agDevHandle = oneDeviceData->agDevHandle;
1867 
1868     agSSPFrame->sspCmdIU.cdb[0] = REPORT_LUN_OPCODE;
1869     agSSPFrame->sspCmdIU.cdb[1] = 0x0;
1870     agSSPFrame->sspCmdIU.cdb[2] = 0x0;
1871     agSSPFrame->sspCmdIU.cdb[3] = 0x0;
1872     agSSPFrame->sspCmdIU.cdb[4] = 0x0;
1873     agSSPFrame->sspCmdIU.cdb[5] = 0x0;
1874     agSSPFrame->sspCmdIU.cdb[6] = 0x0;
1875     agSSPFrame->sspCmdIU.cdb[7] = 0x0;
1876     agSSPFrame->sspCmdIU.cdb[8] = 0x0;
1877     agSSPFrame->sspCmdIU.cdb[9] = REPORT_LUN_LEN;
1878     agSSPFrame->sspCmdIU.cdb[10] = 0x0;
1879     agSSPFrame->sspCmdIU.cdb[11] = 0x0;
1880 
1881     agSSPFrame->dataLength = REPORT_LUN_LEN;
1882     agSSPFrame->agSgl.len =	sizeof(agsaSSPCmdInfoUnit_t);
1883 
1884     status = saSSPStart(agRoot, agIORequest, 0, agDevHandle, agRequestType,agSASRequestBody,agNULL,
1885     										   &ossaSSPIoctlCompleted);
1886     if(status != AGSA_RC_SUCCESS)
1887 	{
1888       ostiFreeMemory(tiRoot,
1889     				 tdsaAllShared->tdFWControlEx.virtAddr,
1890     				 tdsaAllShared->tdFWControlEx.len);
1891       tdsaAllShared->tdFWControlEx.payload = NULL;
1892       tdsaAllShared->tdFWControlEx.inProgress = 0;
1893       status = IOCTL_CALL_FAIL;
1894     }
1895   }while(0);
1896   return status;
1897 }
1898 
1899 
1900