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