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: stable/11/sys/dev/pms/RefTisa/tisa/sassata/sas/ini/itdio.c 345507 2019-03-25 17:04:14Z dab $");
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*****************************************************************************/
99osGLOBAL bit32
100tiINIIOStart(
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    /*
370osGLOBAL bit32
371smIOStart(
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  }
453ext:
454  TDSA_INP_LEAVE(tiRoot);
455  return tiStatus;
456}
457
458#ifdef FAST_IO_TEST
459osGLOBAL bit32
460tiINIFastIOSend(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
472osGLOBAL bit32
473tiINIFastIOCancel(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
485osGLOBAL void*
486tiINIFastIOPrepare(
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
563ext:
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*****************************************************************************/
603osGLOBAL 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*****************************************************************************/
643osGLOBAL bit32
644tiINISuperIOStart(
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
1122osGLOBAL bit32
1123tiINISMPStart(
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
1218osGLOBAL bit32
1219tiINIIOStartIntCoalesce(
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
1408osGLOBAL bit32
1409tiINIIOStartIntCoalesceDif(
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
1668osGLOBAL bit32
1669tiINIIntCoalesceInit(
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*****************************************************************************/
1749osGLOBAL FORCEINLINE bit32
1750itdssIOPrepareSGL(
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
1789osGLOBAL bit32
1790tiNumOfLunIOCTLreq(
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    tdIORequestBody->tiIORequest = tiIORequest;
1824
1825    /* save context if we need to abort later */
1826    tiIORequest->tdData = tdIORequestBody;
1827
1828    agIORequest = &(tdIORequestBody->agIORequest);
1829    agIORequest->osData = (void *) tdIORequestBody;
1830    agSASRequestBody = &(tdIORequestBody->transport.SAS.agSASRequestBody);
1831    agSSPFrame = &(agSASRequestBody->sspInitiatorReq);
1832
1833    ostiMemoryStatus = ostiAllocMemory( tiRoot,
1834    									  &osMemHandle,
1835    									  (void **)&respBuffer,
1836    									  &(agSSPFrame->agSgl.sgUpper),
1837    									  &(agSSPFrame->agSgl.sgLower),
1838    									  8,
1839    									  REPORT_LUN_LEN,
1840    									  agFALSE);
1841    if((ostiMemoryStatus != tiSuccess) && (respBuffer == agNULL  ))
1842    {
1843      status = IOCTL_CALL_FAIL;
1844      break;
1845    }
1846
1847    osti_memset((void *)respBuffer, 0, REPORT_LUN_LEN);
1848
1849    	// use FW control place in shared structure to keep the neccesary information
1850    tdsaAllShared->tdFWControlEx.virtAddr = respBuffer;
1851    tdsaAllShared->tdFWControlEx.len = REPORT_LUN_LEN;
1852    tdsaAllShared->tdFWControlEx.param1 = agParam1;
1853    tdsaAllShared->tdFWControlEx.param2 = agParam2;
1854    tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload;
1855    tdsaAllShared->tdFWControlEx.inProgress = 1;
1856    agRequestType = AGSA_SSP_INIT_READ;
1857
1858    status = IOCTL_CALL_PENDING;
1859    oneDeviceData = (tdsaDeviceData_t *)(tiDeviceHandle->tdData);
1860    agDevHandle = oneDeviceData->agDevHandle;
1861
1862    agSSPFrame->sspCmdIU.cdb[0] = REPORT_LUN_OPCODE;
1863    agSSPFrame->sspCmdIU.cdb[1] = 0x0;
1864    agSSPFrame->sspCmdIU.cdb[2] = 0x0;
1865    agSSPFrame->sspCmdIU.cdb[3] = 0x0;
1866    agSSPFrame->sspCmdIU.cdb[4] = 0x0;
1867    agSSPFrame->sspCmdIU.cdb[5] = 0x0;
1868    agSSPFrame->sspCmdIU.cdb[6] = 0x0;
1869    agSSPFrame->sspCmdIU.cdb[7] = 0x0;
1870    agSSPFrame->sspCmdIU.cdb[8] = 0x0;
1871    agSSPFrame->sspCmdIU.cdb[9] = REPORT_LUN_LEN;
1872    agSSPFrame->sspCmdIU.cdb[10] = 0x0;
1873    agSSPFrame->sspCmdIU.cdb[11] = 0x0;
1874
1875    agSSPFrame->dataLength = REPORT_LUN_LEN;
1876    agSSPFrame->agSgl.len =	sizeof(agsaSSPCmdInfoUnit_t);
1877    agSSPFrame->agSgl.extReserved = 0;
1878    CLEAR_ESGL_EXTEND(agSSPFrame->agSgl.extReserved);
1879
1880    status = saSSPStart(agRoot, agIORequest, 0, agDevHandle, agRequestType,agSASRequestBody,agNULL,
1881    										   &ossaSSPIoctlCompleted);
1882    if(status != AGSA_RC_SUCCESS)
1883	{
1884      ostiFreeMemory(tiRoot,
1885    				 tdsaAllShared->tdFWControlEx.virtAddr,
1886    				 tdsaAllShared->tdFWControlEx.len);
1887      tdsaAllShared->tdFWControlEx.payload = NULL;
1888      tdsaAllShared->tdFWControlEx.inProgress = 0;
1889      status = IOCTL_CALL_FAIL;
1890    }
1891  }while(0);
1892  return status;
1893}
1894
1895
1896