/*******************************************************************************
*Copyright (c) 2014 PMC-Sierra, Inc.  All rights reserved. 
*
*Redistribution and use in source and binary forms, with or without modification, are permitted provided 
*that the following conditions are met: 
*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
*following disclaimer. 
*2. Redistributions in binary form must reproduce the above copyright notice, 
*this list of conditions and the following disclaimer in the documentation and/or other materials provided
*with the distribution. 
*
*THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED 
*WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
*FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
*NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
*BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
*SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE

********************************************************************************/
/*******************************************************************************/
/** \file
 *
 *
 *
 * This file contains CB functions used by lower layer in SAS/SATA TD layer
 *
 */
#include <sys/cdefs.h>
#include <dev/pms/config.h>

#include <dev/pms/freebsd/driver/common/osenv.h>
#include <dev/pms/freebsd/driver/common/ostypes.h>
#include <dev/pms/freebsd/driver/common/osdebug.h>

#include <dev/pms/RefTisa/sallsdk/api/sa.h>
#include <dev/pms/RefTisa/sallsdk/api/saapi.h>
#include <dev/pms/RefTisa/sallsdk/api/saosapi.h>

#include <dev/pms/RefTisa/tisa/api/titypes.h>
#include <dev/pms/RefTisa/tisa/api/ostiapi.h>
#include <dev/pms/RefTisa/tisa/api/tiapi.h>
#include <dev/pms/RefTisa/tisa/api/tiglobal.h>

#ifdef FDS_SM
#include <dev/pms/RefTisa/sat/api/sm.h>
#include <dev/pms/RefTisa/sat/api/smapi.h>
#include <dev/pms/RefTisa/sat/api/tdsmapi.h>
#endif

#ifdef FDS_DM
#include <dev/pms/RefTisa/discovery/api/dm.h>
#include <dev/pms/RefTisa/discovery/api/dmapi.h>
#include <dev/pms/RefTisa/discovery/api/tddmapi.h>
#endif

#include <dev/pms/RefTisa/tisa/sassata/sas/common/tdtypes.h>
#include <dev/pms/freebsd/driver/common/osstring.h>
#include <dev/pms/RefTisa/tisa/sassata/common/tdutil.h>

#ifdef INITIATOR_DRIVER
#include <dev/pms/RefTisa/tisa/sassata/sas/ini/itdtypes.h>
#include <dev/pms/RefTisa/tisa/sassata/sas/ini/itddefs.h>
#include <dev/pms/RefTisa/tisa/sassata/sas/ini/itdglobl.h>
#endif

#ifdef TARGET_DRIVER
#include <dev/pms/RefTisa/tisa/sassata/sas/tgt/ttdglobl.h>
#include <dev/pms/RefTisa/tisa/sassata/sas/tgt/ttdxchg.h>
#include <dev/pms/RefTisa/tisa/sassata/sas/tgt/ttdtypes.h>
#endif

#include <dev/pms/RefTisa/tisa/sassata/common/tdsatypes.h>
#include <dev/pms/RefTisa/tisa/sassata/common/tdproto.h>

#ifdef ECHO_TESTING
/* temporary to test saEchoCommand() */
extern bit8 gEcho;
#endif

#if defined(SALLSDK_DEBUG)
extern bit32 gLLDebugLevel;
#endif


#include <dev/pms/RefTisa/sallsdk/spc/mpidebug.h>

#ifdef SA_ENABLE_TRACE_FUNCTIONS

#ifdef siTraceFileID
#undef siTraceFileID
#endif
#define siTraceFileID 'R'
#endif
/*
  functions that are common to SAS and SATA
*/

FORCEINLINE
void ossaCacheInvalidate(
                         agsaRoot_t  *agRoot,
                         void        *osMemHandle,
                         void        *virtPtr,
                         bit32       length
                         )
{
  tdsaRootOsData_t     *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t             *tiRoot = (tiRoot_t *)osData->tiRoot;

  TI_DBG6(("ossaCacheInvalidate: start\n"));
  ostiCacheInvalidate(tiRoot, osMemHandle, virtPtr, length);
  return;
}

FORCEINLINE
void ossaCacheFlush(
               agsaRoot_t  *agRoot,
               void        *osMemHandle,
               void        *virtPtr,
               bit32       length
               )
{
  tdsaRootOsData_t     *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t             *tiRoot = (tiRoot_t *)osData->tiRoot;

  TI_DBG6(("ossaCacheFlush: start\n"));
  ostiCacheFlush(tiRoot, osMemHandle, virtPtr, length);
  return;
}

FORCEINLINE
void ossaCachePreFlush(
                  agsaRoot_t  *agRoot,
                  void        *osMemHandle,
                  void        *virtPtr,
                  bit32       length
                   )

{
  tdsaRootOsData_t     *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t             *tiRoot = (tiRoot_t *)osData->tiRoot;

  TI_DBG6(("ossaCachePreFlush: start\n"));
  ostiCachePreFlush(tiRoot, osMemHandle, virtPtr, length);
  return;
}

/*****************************************************************************
*! \brief ossaDeviceHandleAccept
*
*  Purpose:  This function is called by lower layer to inform TD layer of
*            a new SAS device arrival. Used only at the target
*
*
*  \param   agRoot         Pointer to chip/driver Instance.
*  \param   agDevHandle    Pointer to the device handle of the device
*  \param   agDevInfo      Pointer to the device info structure
*  \param   agPortContext  Pointer to a port context
*
*  \return:
*          OSSA_RC_REJECT  A device is accpeted
*          OSSA_RC_ACCEPT  A device is rejected
*
*  \note -  For details, refer to SAS/SATA Low-Level API Specification
*
*****************************************************************************/
osGLOBAL bit32 ossaDeviceHandleAccept(
                       agsaRoot_t          *agRoot,
                       agsaDevHandle_t     *agDevHandle,
                       agsaSASDeviceInfo_t *agDevInfo,
                       agsaPortContext_t   *agPortContext,
                       bit32               *hostAssignedDeviceId
                       )
{
#ifdef TARGET_DRIVER
  tdsaRootOsData_t     *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t             *tiRoot = (tiRoot_t *)osData->tiRoot;
  tdsaRoot_t           *tdsaRoot      = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t        *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;

  tdsaPortContext_t    *onePortContext = agNULL;
  tiPortalContext_t    *tiPortalContext = agNULL;
  tdsaDeviceData_t     *oneDeviceData = agNULL;
  tiDeviceHandle_t     *tiDeviceHandle = agNULL;
  tdsaSASSubID_t       agSASSubID;
  bit32                option;
  bit32                param;
  /*
    at target only
    by default TD layer accpets all devices
  */
  /*
    at this point,
    by LINK_UP event tdsaPortContext should have been created
  */
  smTraceFuncEnter(hpDBG_VERY_LOUD, "Y0");
  TI_DBG1(("ossaDeviceHandleAccept: start hostAssignedDeviceId 0x%X\n",*hostAssignedDeviceId));


  if (agPortContext == agNULL)
  {
    TI_DBG1(("ossaDeviceHandleAccept: NULL agsaPortContext; wrong\n"));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Y0");
    return OSSA_RC_REJECT;
  }


  onePortContext = (tdsaPortContext_t *)agPortContext->osData;

  if (onePortContext == agNULL)
  {
    TI_DBG1(("ossaDeviceHandleAccept: NULL oneportcontext; wrong\n"));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "Y0");
    return OSSA_RC_REJECT;
  }

  tiPortalContext = (tiPortalContext_t *)onePortContext->tiPortalContext;

  if (tiPortalContext == agNULL)
  {
    TI_DBG1(("ossaDeviceHandleAccept: NULL tiPortalContext; wrong\n"));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "Y0");
    return OSSA_RC_REJECT;
  }

  /*
    add the device to device list
    cf) OSSA_DISCOVER_FOUND_DEVICE
  */
  TI_DBG4(("ossaDeviceHandleAccept: sasAddressHi 0x%08x\n", SA_DEVINFO_GET_SAS_ADDRESSHI(&agDevInfo->commonDevInfo)));
  TI_DBG4(("ossaDeviceHandleAccept: sasAddressLo 0x%08x\n", SA_DEVINFO_GET_SAS_ADDRESSLO(&agDevInfo->commonDevInfo)));
  TI_DBG4(("ossaDeviceHandleAccept: device type  0x%x\n", DEVINFO_GET_DEVICETTYPE(&agDevInfo->commonDevInfo)));
  TI_DBG4(("ossaDeviceHandleAccept: phys %d\n", agDevInfo->numOfPhys));
  TI_DBG4(("ossaDeviceHandleAccept: pid %d\n", onePortContext->id));

  if (DEVINFO_GET_DEVICETTYPE(&agDevInfo->commonDevInfo) == SAS_END_DEVICE)
  {
    TI_DBG4(("ossaDeviceHandleAccept: SAS_END_DEVICE\n"));
  }
  else if (DEVINFO_GET_DEVICETTYPE(&agDevInfo->commonDevInfo) == SAS_EDGE_EXPANDER_DEVICE)
  {
    TI_DBG4(("ossaDeviceHandleAccept: SAS_EDGE_EXPANDER_DEVICE\n"));
  }
  else /* SAS_FANOUT_EXPANDER_DEVICE */
  {
    TI_DBG4(("ossaDeviceHandleAccept: SAS_FANOUT_EXPANDER_DEVICE\n"));
  }
  agSASSubID.sasAddressHi = SA_DEVINFO_GET_SAS_ADDRESSHI(&agDevInfo->commonDevInfo);
  agSASSubID.sasAddressLo = SA_DEVINFO_GET_SAS_ADDRESSLO(&agDevInfo->commonDevInfo);
  agSASSubID.initiator_ssp_stp_smp = agDevInfo->initiator_ssp_stp_smp;
  agSASSubID.target_ssp_stp_smp = agDevInfo->target_ssp_stp_smp;


  tdssAddSASToSharedcontext(
                            onePortContext,
                            agRoot,
                            agDevHandle,
                            &agSASSubID,
                            agTRUE,
                            0xFF,
                            TD_OPERATION_TARGET
                            );

  /* at this point devicedata for new device exists */
  oneDeviceData = (tdsaDeviceData_t *)agDevHandle->osData;

  if (oneDeviceData == agNULL)
  {
    TI_DBG1(("ossaDeviceHandleAccept: NULL oneDeviceData; wrong\n"));
    return OSSA_RC_REJECT;
  }

  oneDeviceData->registered = agTRUE;

  tiDeviceHandle = &(oneDeviceData->tiDeviceHandle);

  if (tiDeviceHandle == agNULL)
  {
    TI_DBG1(("ossaDeviceHandleAccept: NULL tiDeviceHandle; wrong\n"));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "Y0");
    return OSSA_RC_REJECT;
  }

  /* setting MCN in agsaDeviceInfo_t*/
  agDevInfo->commonDevInfo.flag = agDevInfo->commonDevInfo.flag | (tdsaAllShared->MCN << 16);
  /* increment RegisteredDevNums */
  onePortContext->RegisteredDevNums++;

  *hostAssignedDeviceId |= 0xBEEF0000;

  TI_DBG1(("ossaDeviceHandleAccept: Now hostAssignedDeviceId 0x%X\n", *hostAssignedDeviceId));


  /* no login in SAS */
  /*
    osGLOBAL bit32 ostiTargetEvent (
                        tiRoot_t          *tiRoot,
                        tiPortalContext_t *portalContext,
                        tiDeviceHandle_t  *tiDeviceHandle,
                        tiTgtEventType_t  eventType,
                        bit32             eventStatus,
                        void              *parm
                        );
  */

  ostiTargetEvent(
                  tiRoot,
                  tiPortalContext,
                  tiDeviceHandle,
                  tiTgtEventTypeDeviceChange,
                  tiDeviceArrival,
                  agNULL
                  );
  /* set MCN and initiator role bit using saSetDeviceInfo */
  option = 24; /* setting MCN and initiator role 1 1000b*/
  param = (1 << 18) | (tdsaAllShared->MCN << 24);
  TI_DBG1(("ossaDeviceHandleAccept: option 0x%x param 0x%x MCN 0x%x\n", option, param, tdsaAllShared->MCN));
  saSetDeviceInfo(agRoot, agNULL, 0, agDevHandle, option, param, ossaSetDeviceInfoCB);
  smTraceFuncExit(hpDBG_VERY_LOUD, 'e', "Y0");
  return OSSA_RC_ACCEPT;
#endif

#ifdef INITIATOR_DRIVER
  /* this function is not used in case of Initiator */
  return OSSA_RC_ACCEPT;
#endif
}

#ifdef INITIATOR_DRIVER
/*****************************************************************************
*! \brief ossaDiscoverSasCB
*
*  Purpose:  This function is called by lower layer to inform TD layer of
*            SAS discovery results
*
*
*  \param   agRoot         Pointer to chip/driver Instance.
*  \param   agPortContext  Pointer to the port context of TD and Lower layer
*  \param   event          event type
*  \param   pParm1         Pointer to data associated with event
*  \param   pParm2         Pointer to data associated with event
*
*  \return: none
*
*  \note -  For details, refer to SAS/SATA Low-Level API Specification
*
*****************************************************************************/
osGLOBAL void ossaDiscoverSasCB(agsaRoot_t        *agRoot,
                  agsaPortContext_t *agPortContext,
                  bit32             event,
                  void              *pParm1,
                  void              *pParm2
                  )
{
  tdsaRootOsData_t     *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t             *tiRoot = (tiRoot_t *)osData->tiRoot;
  tdsaContext_t        *tdsaAllShared = (tdsaContext_t *)osData->tdsaAllShared;

  tdsaPortContext_t    *onePortContext = agNULL;
  tdsaDeviceData_t     *oneDeviceData = agNULL;

  agsaDevHandle_t      *agDevHandle = agNULL;
  agsaSASDeviceInfo_t  *agDeviceInfo = agNULL;
  tiPortalContext_t    *tiPortalContext = agNULL;
  tdList_t             *DeviceListList;
  tdsaSASSubID_t       agSASSubID;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"Y1");
  TI_DBG2(("ossaDiscoverSasCB: start\n"));

  if (agPortContext == agNULL)
  {
    TI_DBG1(("ossaDiscoverSasCB: NULL agsaPortContext; wrong\n"));
    return;
  }

  onePortContext = (tdsaPortContext_t *)agPortContext->osData;
  tiPortalContext = (tiPortalContext_t *)onePortContext->tiPortalContext;

  switch ( event )
  {
  case OSSA_DISCOVER_STARTED:
  {
    TI_DBG3(("ossaDiscoverSasCB: STARTED pid %d\n", onePortContext->id));
    /*
      invalidate all devices in current device list
    */
    DeviceListList = tdsaAllShared->MainDeviceList.flink;
    while (DeviceListList != &(tdsaAllShared->MainDeviceList))
    {
      oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
      TI_DBG3(("ossaDiscoverSasCB: loop did %d\n", oneDeviceData->id));
      TI_DBG3(("ossaDiscoverSasCB: loop sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
      TI_DBG6(("ossaDiscoverSasCB: loop sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
      if (oneDeviceData->tdPortContext == onePortContext)
      {
        TI_DBG3(("ossaDiscoverSasCB: did %d is invalidated \n", oneDeviceData->id));
        /* temporary solution: only for sata direct attached */
      }
      DeviceListList = DeviceListList->flink;
    }
    onePortContext->DiscoveryState = ITD_DSTATE_STARTED;
    break;
  }

  case OSSA_DISCOVER_FOUND_DEVICE:
  {
    TI_DBG4(("ossaDiscoverSasCB: $$$$$ FOUND_DEVICE pid %d\n", onePortContext->id));
    agDevHandle = (agsaDevHandle_t *)pParm1;
    agDeviceInfo = (agsaSASDeviceInfo_t *)pParm2;
    TI_DBG5(("ossaDiscoverSasCB: sasAddressHi 0x%08x\n", SA_DEVINFO_GET_SAS_ADDRESSHI(&agDeviceInfo->commonDevInfo)));
    TI_DBG5(("ossaDiscoverSasCB: sasAddressLo 0x%08x\n", SA_DEVINFO_GET_SAS_ADDRESSLO(&agDeviceInfo->commonDevInfo)));
    TI_DBG5(("ossaDiscoverSasCB: device type  0x%x\n", DEVINFO_GET_DEVICETTYPE(&agDeviceInfo->commonDevInfo)));

    TI_DBG6(("ossaDiscoverSasCB: phys %d\n", agDeviceInfo->numOfPhys));
    TI_DBG4(("ossaDiscoverSasCB: pid %d\n", onePortContext->id));


    /* Add only target devices; do not add expander device */
    if (DEVINFO_GET_DEVICETTYPE(&agDeviceInfo->commonDevInfo) == SAS_END_DEVICE)
    {
      agSASSubID.sasAddressHi = SA_DEVINFO_GET_SAS_ADDRESSHI(&agDeviceInfo->commonDevInfo);
      agSASSubID.sasAddressLo = SA_DEVINFO_GET_SAS_ADDRESSLO(&agDeviceInfo->commonDevInfo);
      agSASSubID.initiator_ssp_stp_smp = agDeviceInfo->initiator_ssp_stp_smp;
      agSASSubID.target_ssp_stp_smp = agDeviceInfo->target_ssp_stp_smp;

      TI_DBG2(("ossaDiscoverSasCB: adding ....\n"));

      tdssAddSASToSharedcontext(
                                onePortContext,
                                agRoot,
                                agDevHandle,
                                &agSASSubID,
                                agTRUE,
                                agDeviceInfo->phyIdentifier, 
                                TD_OPERATION_INITIATOR
                                );
      ostiInitiatorEvent(
                         tiRoot,
                         tiPortalContext,
                         agNULL,
                         tiIntrEventTypeDeviceChange,
                         tiDeviceArrival,
                         agNULL
                         );
    }
    else
    {
      TI_DBG5(("ossaDiscoverSasCB: $$$$$ not end device. not adding....\n"));
    }


    break;
  }

  case OSSA_DISCOVER_REMOVED_DEVICE:
  {
    TI_DBG3(("ossaDiscoverSasCB: REMOVED_DEVICE\n"));
    agDevHandle = (agsaDevHandle_t *)pParm1;
    agDeviceInfo = (agsaSASDeviceInfo_t *)pParm2;
    oneDeviceData = (tdsaDeviceData_t *) agDevHandle->osData;

    TI_DBG6(("ossaDiscoverSasCB: sasAddressHi 0x%08x\n",
             SA_DEVINFO_GET_SAS_ADDRESSHI(&agDeviceInfo->commonDevInfo)));
    TI_DBG6(("ossaDiscoverSasCB: sasAddressLo 0x%08x\n",
             SA_DEVINFO_GET_SAS_ADDRESSLO(&agDeviceInfo->commonDevInfo)));
    TI_DBG6(("ossaDiscoverSasCB: phys %d\n", agDeviceInfo->numOfPhys));
    TI_DBG6(("ossaDiscoverSasCB: onePortContext->id %d\n", onePortContext->id));

    if (oneDeviceData == agNULL)
    {
      TI_DBG1(("ossaDiscoverSasCB: Wrong. DevHandle->osData is NULL but is being removed\n"));
    }
    else
    {
      tdssRemoveSASFromSharedcontext(onePortContext,
                                     oneDeviceData,
                                     agRoot);
      agDevHandle->osData = agNULL;
      ostiInitiatorEvent(
                         tiRoot,
                         tiPortalContext,
                         agNULL,
                         tiIntrEventTypeDeviceChange,
                         tiDeviceRemoval,
                         agNULL
                         );
    }

    break;
  }
  case OSSA_DISCOVER_COMPLETE:
  {
    TI_DBG2(("ossaDiscoverSasCB: SAS COMPLETE pid %d\n", onePortContext->id));
    /*
      note:
      SAS discovery must be called before SATA discovery
      "onePortContext->DiscoveryState = ITD_DSTATE_COMPLETED" is
      in ossaDiscoverSataCB not in ossaDiscoverSasCB when SATA_ENABLE
    */
#ifndef SATA_ENABLE
    onePortContext->DiscoveryState = ITD_DSTATE_COMPLETED;
    TI_DBG6(("ossaDiscoverSasCB: COMPLETE pid %d\n", onePortContext->id));
#endif

#ifdef SATA_ENABLE
    TI_DBG2(("ossaDiscoverSasCB: calling SATA discovery\n"));

    /* Continue with SATA discovery */
    saDiscover(agRoot, agPortContext, AG_SA_DISCOVERY_TYPE_SATA,
               onePortContext->discoveryOptions);

#else /* SATA not enable */

#ifdef TD_INTERNAL_DEBUG /* for debugging */
    /* dump device list */
    DeviceListList = tdsaAllShared->MainPortContextList.flink;

    while (DeviceListList != &(tdsaAllShared->MainPortContextList))
    {
      oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
      TI_DBG2(("ossaDiscoverSasCB: did %d valid %d\n", oneDeviceData->id, oneDeviceData->valid));
      TI_DBG2(("ossaDiscoverSasCB: device AddrHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
      TI_DBG2(("ossaDiscoverSasCB: device AddrLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
      DeviceListList = DeviceListList->flink;
    }
#endif

    /* letting OS layer know discovery has been successfully complete */
    ostiInitiatorEvent(
                       tiRoot,
                       tiPortalContext,
                       agNULL,
                       tiIntrEventTypeDiscovery,
                       tiDiscOK,
                       agNULL
                       );
#endif  /* SATA_ENABLE */

    break;
  }
  case OSSA_DISCOVER_ABORT:
  {
    TI_DBG3(("ossaDiscoverSasCB: ABORT\n"));
    /* letting OS layer know discovery has not been successfully complete */
    ostiInitiatorEvent(
                       tiRoot,
                       tiPortalContext,
                       agNULL,
                       tiIntrEventTypeDiscovery,
                       tiDiscFailed,
                       agNULL
                       );
    break;
  }
  case OSSA_DISCOVER_ABORT_ERROR_1:
  {
    TI_DBG3(("ossaDiscoverSasCB: ERROR 1\n"));
    /* letting OS layer know discovery has not been successfully complete */
    ostiInitiatorEvent(
                       tiRoot,
                       tiPortalContext,
                       agNULL,
                       tiIntrEventTypeDiscovery,
                       tiDiscFailed,
                       agNULL
                       );
    break;
  }

  case OSSA_DISCOVER_ABORT_ERROR_2:
  {
    TI_DBG3(("ossaDiscoverSasCB: ERROR 2\n"));
    /* letting OS layer know discovery has not been successfully complete */
    ostiInitiatorEvent(
                       tiRoot,
                       tiPortalContext,
                       agNULL,
                       tiIntrEventTypeDiscovery,
                       tiDiscFailed,
                       agNULL
                       );
    break;
  }

  case OSSA_DISCOVER_ABORT_ERROR_3:
  {
    TI_DBG3(("ossaDiscoverSasCB: ERROR 3\n"));
    /* letting OS layer know discovery has not been successfully complete */
    ostiInitiatorEvent(
                       tiRoot,
                       tiPortalContext,
                       agNULL,
                       tiIntrEventTypeDiscovery,
                       tiDiscFailed,
                       agNULL
                       );
    break;
  }
  case OSSA_DISCOVER_ABORT_ERROR_4:
  {
    TI_DBG3(("ossaDiscoverSasCB: ERROR 4\n"));
    /* letting OS layer know discovery has not been successfully complete */
    ostiInitiatorEvent(
                       tiRoot,
                       tiPortalContext,
                       agNULL,
                       tiIntrEventTypeDiscovery,
                       tiDiscFailed,
                       agNULL
                       );
        break;
  }
  case OSSA_DISCOVER_ABORT_ERROR_5:
  {
    TI_DBG3(("ossaDiscoverSasCB: ERROR 5\n"));
    /* letting OS layer know discovery has not been successfully complete */
    ostiInitiatorEvent(
                       tiRoot,
                       tiPortalContext,
                       agNULL,
                       tiIntrEventTypeDiscovery,
                       tiDiscFailed,
                       agNULL
                       );
    break;
  }
  case OSSA_DISCOVER_ABORT_ERROR_6:
  {
    TI_DBG3(("ossaDiscoverSasCB: ERROR 6\n"));
    /* letting OS layer know discovery has not been successfully complete */
    ostiInitiatorEvent(
                       tiRoot,
                       tiPortalContext,
                       agNULL,
                       tiIntrEventTypeDiscovery,
                       tiDiscFailed,
                       agNULL
                       );
    break;
  }
  case OSSA_DISCOVER_ABORT_ERROR_7:
  {
    TI_DBG3(("ossaDiscoverSasCB: ERROR 7\n"));
    /* letting OS layer know discovery has not been successfully complete */
    ostiInitiatorEvent(
                       tiRoot,
                       tiPortalContext,
                       agNULL,
                       tiIntrEventTypeDiscovery,
                       tiDiscFailed,
                       agNULL
                       );
    break;
  }
  case OSSA_DISCOVER_ABORT_ERROR_8:
  {
    TI_DBG3(("ossaDiscoverSasCB: ERROR 8\n"));
    /* letting OS layer know discovery has not been successfully complete */
    ostiInitiatorEvent(
                       tiRoot,
                       tiPortalContext,
                       agNULL,
                       tiIntrEventTypeDiscovery,
                       tiDiscFailed,
                       agNULL
                       );
    break;
  }
  case OSSA_DISCOVER_ABORT_ERROR_9:
  {
    TI_DBG3(("ossaDiscoverSasCB: ERROR 9\n"));
    /* letting OS layer know discovery has not been successfully complete */
    ostiInitiatorEvent(
                       tiRoot,
                       tiPortalContext,
                       agNULL,
                       tiIntrEventTypeDiscovery,
                       tiDiscFailed,
                       agNULL
                       );
    break;
  }
  default:
    TI_DBG3(("ossaDiscoverSasCB: ERROR default event 0x%x\n", event));
    /* letting OS layer know discovery has not been successfully complete */
    ostiInitiatorEvent(
                       tiRoot,
                       tiPortalContext,
                       agNULL,
                       tiIntrEventTypeDiscovery,
                       tiDiscFailed,
                       agNULL
                       );
    break;
  } /* end of switch */
  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Y1");
  return;
}
#endif // #ifdef INITIATOR_DRIVER

osGLOBAL void ossaLogTrace0(
               agsaRoot_t           *agRoot,
               bit32               traceCode
               )
{
  return;
}

osGLOBAL void ossaLogTrace1(
               agsaRoot_t           *agRoot,
               bit32               traceCode,
               bit32               value1
               )
{
  return;
}

osGLOBAL void ossaLogTrace2(
               agsaRoot_t           *agRoot,
               bit32               traceCode,
               bit32               value1,
               bit32               value2
               )
{
  return;
}

osGLOBAL void ossaLogTrace3(
               agsaRoot_t           *agRoot,
               bit32               traceCode,
               bit32               value1,
               bit32               value2,
               bit32               value3
               )
{
  return;
}


osGLOBAL void
ossaLogTrace4(
               agsaRoot_t           *agRoot,
               bit32               traceCode,
               bit32               value1,
               bit32               value2,
               bit32               value3,
               bit32               value4
               )
{
  return;
}


/*****************************************************************************
*! \brief ossaHwCB
*
*  Purpose:  This function is called by lower layer to inform TD layer of
*            HW related results
*
*  \param   agRoot         Pointer to chip/driver Instance.
*  \param   agPortContext  Pointer to the port context of TD and Lower layer
*  \param   event          event type
*  \param   eventParm1     event-specific parameter
*  \param   eventParm2     event-specific parameter
*  \param   eventParm3     event-specific parameter of pointer type
*
*  \return: none
*
*  \note -  For details, refer to SAS/SATA Low-Level API Specification
*
*****************************************************************************/
osGLOBAL void ossaHwCB(
         agsaRoot_t        *agRoot,
         agsaPortContext_t *agPortContext,
         bit32             event,
         bit32             eventParm1,
         void              *eventParm2,
         void              *eventParm3
         )
{
  tdsaRootOsData_t    *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t            *tiRoot = (tiRoot_t *)osData->tiRoot;
  tdsaContext_t       *tdsaAllShared = (tdsaContext_t *)osData->tdsaAllShared;
  tdList_t            *PortContextList = agNULL;
  tdsaPortContext_t   *onePortContext = agNULL;
  agsaDevHandle_t     *agDevHandle = agNULL;
  agsaSASIdentify_t   *IDframe = agNULL;
  int                 i = 0;
#ifdef INITIATOR_DRIVER
  tdsaSASSubID_t      agSASSubID;
#endif
  bit32               PhyID;
  bit32               PhyStatus;
  bit32               LinkRate;
  bit32               PortState;
  bit32               HwAckSatus = AGSA_RC_SUCCESS;

// #ifdef INITIATOR_DRIVER
#ifdef INITIATOR_DRIVER
  agsaFisRegDeviceToHost_t *RegD2H = agNULL;
  tdsaDeviceData_t         *oneDeviceData = agNULL;
  tdList_t                 *DeviceListList;
#endif
#ifdef REMOVED
  bit32                    found = agFALSE;
#endif
  agsaHWEventEncrypt_t     *pEncryptCBData;
  agsaEncryptInfo_t        *pEncryptInfo;
  agsaHWEventMode_t        *pModeEvent;
  tiEncryptPort_t          encryptEventData;
  tiEncryptInfo_t          encryptInfo;
  bit32                    *pModePage;
  bit32                    securityMode;
  bit32                    cipherMode;
  bit32                    encryptStatus;
  bit32                    securitySetModeStatus;
  bit32                    securityModeStatus;

// #endif /* INITIATOR_DRIVER */
  agsaPhyErrCountersPage_t *agPhyErrCountersPage;
  agsaEventSource_t        eventSource;

#ifdef FDS_DM
  dmRoot_t                 *dmRoot = &(tdsaAllShared->dmRoot);
  dmPortContext_t          *dmPortContext = agNULL;
  bit32                    status = DM_RC_FAILURE;
  dmPortInfo_t             dmPortInfo;
//  bit32                    discStatus = dmDiscInProgress;
#endif

  smTraceFuncEnter(hpDBG_VERY_LOUD,"Y2");

  TI_DBG2(("ossaHwCB: agPortContext %p event 0x%x eventParm1 0x%x eventParm2 %p eventParm3 %p\n",
                      agPortContext,event,eventParm1,eventParm2,eventParm3 ));

  switch ( event )
  {
  case OSSA_HW_EVENT_SAS_PHY_UP:
  {
    PhyID = TD_GET_PHY_ID(eventParm1);
    LinkRate = TD_GET_LINK_RATE(eventParm1);
    PortState = TD_GET_PORT_STATE(eventParm1);
    agDevHandle = agNULL;
    IDframe = (agsaSASIdentify_t *)eventParm3;


    TI_DBG2(("ossaHwCB: Phy%d SAS link Up\n", PhyID));

    if (agPortContext == agNULL)
    {
      TI_DBG1(("ossaHwCB: agPortContext null, wrong\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Y2");
      return;
    }
    if (agDevHandle == agNULL)
    {
      TI_DBG3(("ossaHwCB: agDevHandle null by design change\n"));
    }

    if (IDframe == agNULL)
    {
      TI_DBG1(("ossaHwCB: IDframe null, wrong\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "Y2");
      return;
    }
    /* debugging only */
    if (LinkRate == 0x01)
    {
      TI_DBG1(("ossaHwCB: SAS Link Rate is 1.5 Gbps PhyID %d\n",PhyID));
    }
    if (LinkRate == 0x02)
    {
      TI_DBG1(("ossaHwCB: SAS Link Rate is 3.0 Gbps PhyID %d\n",PhyID));
    }
    if (LinkRate == 0x04)
    {
      TI_DBG1(("ossaHwCB: SAS Link Rate is 6.0 Gbps PhyID %d\n",PhyID));
    }
    if (LinkRate == 0x08)
    {
      TI_DBG1(("ossaHwCB: SAS Link Rate is 12.0 Gbps PhyID %d\n",PhyID));
    }

    if (PortState == OSSA_PORT_INVALID)
    {
      TI_DBG1(("ossaHwCB: Wrong port state with SAS link up\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "Y2");
      return;
    }

    if ( agPortContext->osData == agNULL)
    {/* if */
      TI_DBG6 (("ossaHwCB: PhyID %d tdsaAllShared %p\n", PhyID, tdsaAllShared));
      if (tdsaAllShared->Ports[PhyID].tiPortalContext == agNULL)
      {
        TI_DBG6(("ossaHwCB: NULL portalcontext\n"));
      }
      else
      {
        TI_DBG6(("ossaHwCB: NOT NULL portalcontext\n"));
      }

      if (IDframe == agNULL)
      {
        TI_DBG1(("ossaHwCB: IDFrame is NULL; SATA !!!!\n"));
      }
      else
      {
        TI_DBG3(("ossaHwCB: IDframe->sasAddressHi 0x%08x \n",
                 SA_IDFRM_GET_SAS_ADDRESSHI(IDframe)));
        TI_DBG3(("ossaHwCB: IDframe->sasAddressLo 0x%08x \n",
                 SA_IDFRM_GET_SAS_ADDRESSLO(IDframe)));

      }
      /*
        setting tdsaPortContext fields
        take the head from the FreeLink of tdsaPortContext_t
        then modify it
        then put it in MainLink of tdsaPortContext_t
      */
      tdsaSingleThreadedEnter(tiRoot, TD_PORT_LOCK);
      if (TDLIST_NOT_EMPTY(&(tdsaAllShared->FreePortContextList)))
      {
        TDLIST_DEQUEUE_FROM_HEAD(&PortContextList, &(tdsaAllShared->FreePortContextList));
        tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
        onePortContext = TDLIST_OBJECT_BASE(tdsaPortContext_t, FreeLink, PortContextList);
        TI_DBG2(("ossaHwCB: pid %d\n", onePortContext->id));
        TI_DBG6(("ossaHwCB: onePortContext %p\n", onePortContext));
        if (onePortContext == agNULL)
        {
          TI_DBG1(("ossaHwCB: onePortContext is NULL in allocation, wrong!\n"));
          return;
        }

        /* sets fields of tdsaportcontext */
#ifdef INITIATOR_DRIVER
        onePortContext->DiscoveryState = ITD_DSTATE_NOT_STARTED;
        onePortContext->discoveryOptions = AG_SA_DISCOVERY_OPTION_FULL_START;
#endif
        onePortContext->PhyIDList[PhyID] = agTRUE;
        if (IDframe == agNULL)
        {
          onePortContext->sasRemoteAddressHi = 0xFFFFFFFF;
          onePortContext->sasRemoteAddressLo = 0xFFFFFFFF;
          onePortContext->directAttatchedSAS = agTRUE;
        }
        else
        {
          onePortContext->sasRemoteAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(IDframe);
          onePortContext->sasRemoteAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(IDframe);
          /* Create ID frame and storing ID frame */
          osti_memcpy(&onePortContext->sasIDframe, IDframe, sizeof(agsaSASIdentify_t));
          tdhexdump("ossaHWCB: sasIDframe", (bit8 *)(&onePortContext->sasIDframe), sizeof(agsaSASIdentify_t));
          if (SA_IDFRM_GET_DEVICETTYPE(IDframe) == SAS_END_DEVICE)
          {
            onePortContext->directAttatchedSAS = agTRUE;
          }
#ifdef FDS_DM
          if (SA_IDFRM_GET_DEVICETTYPE(IDframe) == SAS_EDGE_EXPANDER_DEVICE ||
              SA_IDFRM_GET_DEVICETTYPE(IDframe) == SAS_FANOUT_EXPANDER_DEVICE
             )
          {
            onePortContext->UseDM = agTRUE;
          }
#endif
        }

        onePortContext->sasLocalAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&tdsaAllShared->Ports[PhyID].SASID);
        onePortContext->sasLocalAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&tdsaAllShared->Ports[PhyID].SASID);
        onePortContext->tiPortalContext = tdsaAllShared->Ports[PhyID].tiPortalContext;
        onePortContext->agRoot = agRoot;
        onePortContext->agPortContext = agPortContext;
        tdsaAllShared->Ports[PhyID].portContext = onePortContext;
        agPortContext->osData = onePortContext;
        onePortContext->valid = agTRUE;
        if (LinkRate == 0x01)
        {
          onePortContext->LinkRate = SAS_CONNECTION_RATE_1_5G;
        }
        else if (LinkRate == 0x02)
        {
          onePortContext->LinkRate = SAS_CONNECTION_RATE_3_0G;
        }
        else if (LinkRate == 0x04)
        {
          onePortContext->LinkRate = SAS_CONNECTION_RATE_6_0G;
        }
        else /* (LinkRate == 0x08) */
        {
          onePortContext->LinkRate = SAS_CONNECTION_RATE_12_0G;
        }

        tdsaSingleThreadedEnter(tiRoot, TD_PORT_LOCK);
        TDLIST_ENQUEUE_AT_TAIL(&(onePortContext->MainLink), &(tdsaAllShared->MainPortContextList));
        tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
#ifdef FDS_DM
        dmPortContext = &(onePortContext->dmPortContext);
        dmPortContext->tdData = onePortContext;
        /* set up dmPortInfo_t */
        PORTINFO_PUT_SAS_REMOTE_ADDRESSLO(&dmPortInfo, onePortContext->sasRemoteAddressLo);
        PORTINFO_PUT_SAS_REMOTE_ADDRESSHI(&dmPortInfo, onePortContext->sasRemoteAddressHi);
        PORTINFO_PUT_SAS_LOCAL_ADDRESSLO(&dmPortInfo, onePortContext->sasLocalAddressLo);
        PORTINFO_PUT_SAS_LOCAL_ADDRESSHI(&dmPortInfo, onePortContext->sasLocalAddressHi);

        TI_DBG2(("ossaHwCB: phy %d hi 0x%x lo 0x%x\n", PhyID,
                 SA_IDFRM_GET_SAS_ADDRESSHI(&(tdsaAllShared->Ports[PhyID].SASID)),
                 SA_IDFRM_GET_SAS_ADDRESSLO(&(tdsaAllShared->Ports[PhyID].SASID))));
        TI_DBG2(("ossaHwCB: LocalAddrHi 0x%08x LocaAddrLo 0x%08x\n", onePortContext->sasLocalAddressHi, onePortContext->sasLocalAddressLo));

        dmPortInfo.flag = onePortContext->LinkRate;

        if (onePortContext->UseDM == agTRUE)
        {
          TI_DBG1(("ossaHwCB: calling dmCreatePort\n"));
          status = dmCreatePort(dmRoot, dmPortContext, &dmPortInfo);
          if (status != DM_RC_SUCCESS)
          {
            TI_DBG1(("ossaHwCB: dmCreatePort failed!!! 0x%x\n", status));
          }
        }
#endif

      }
      else
      {
        tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
        TI_DBG1(("\nossaHwCB: Attention!!! no more free PortContext.\n"));
      }
#ifdef TD_INTERNAL_DEBUG     /* for debugging only */

      print_tdlist_flink(&(tdsaPortContext->FreeLink), 1, 1);
      print_tdlist_flink(&(tdsaPortContext->MainLink), 1, 2);
      print_tdlist_flink(&(tdsaDeviceData->FreeLink), 2, 1);
      print_tdlist_flink(&(tdsaDeviceData->MainLink), 2, 2);
#endif

#ifdef TD_INTERNAL_DEBUG      /* for debugging */
      PortContextList = tdsaPortContext->MainLink.flink;
      while (PortContextList != &(tdsaPortContext->MainLink))
      {
        twoPortContext = TDLIST_OBJECT_BASE(tdsaPortContext_t, MainLink, PortContextList);
        TI_DBG6(("ossaHwCB: in while portContext ID %d\n", twoPortContext->id));
        TI_DBG6(("ossaHwCB: in while PortContext %p\n", twoPortContext));
        PortContextList = PortContextList->flink;
      }
#endif
      /* add agDevHandle */
      if (SA_IDFRM_GET_DEVICETTYPE(IDframe) != SAS_NO_DEVICE)
      {
#ifdef INITIATOR_DRIVER
        agSASSubID.sasAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(IDframe);
        agSASSubID.sasAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(IDframe);
        agSASSubID.initiator_ssp_stp_smp = IDframe->initiator_ssp_stp_smp;
        agSASSubID.target_ssp_stp_smp = IDframe->target_ssp_stp_smp;
#endif

        TI_DBG2(("ossaHwCB: adding ....\n"));
        /* uses only SASIDframe not agsaSASDeviceInfo_t */
#ifdef INITIATOR_DRIVER
        tdssAddSASToSharedcontext(
                                  onePortContext,
                                  agRoot,
                                  agDevHandle, /* agNULL */
                                  &agSASSubID,
                                  agTRUE,
                                  (bit8)PhyID,
                                  TD_OPERATION_INITIATOR
                                  );
#endif

#ifdef FDS_DM
        if (SA_IDFRM_GET_DEVICETTYPE(IDframe) == SAS_END_DEVICE &&
            SA_IDFRM_IS_SSP_TARGET(IDframe) )
        {
          TI_DBG2(("ossaHwCB: NOTIFY_ENABLE_SPINUP PhyID %d \n", PhyID));
         
          for (i=0;i<TD_MAX_NUM_NOTIFY_SPINUP;i++)
          {
            saLocalPhyControl(agRoot, agNULL, 0, PhyID, AGSA_PHY_NOTIFY_ENABLE_SPINUP, agNULL);
          }
        }

        /* update MCN */
        tdsaUpdateMCN(dmRoot, onePortContext);
#endif

#ifdef TARGET_DRIVER
        TI_DBG1(("ossaHwCB: target, link up PhyID 0x%x\n",PhyID));

        /* notifying link up */
        ostiPortEvent (
                       tiRoot,
                       tiPortLinkUp,
                       tiSuccess,
                       (void *)tdsaAllShared->Ports[PhyID].tiPortalContext
                       );
#endif
      }
      else
      {
        TI_DBG5(("ossaHwCB: $$$$$ not end device. not adding....\n"));
      }

      saPortControl(agRoot, /* AGSA_PORT_SET_PORT_RECOVERY_TIME */
                    agNULL,
                    0,
                    agPortContext,
                    AGSA_PORT_SET_PORT_RECOVERY_TIME,
                    tdsaAllShared->portTMO, //PORT_RECOVERY_TIMEOUT
                    0
                    );
      /* setting SAS PORT RESET TMO and SATA PORT RESET TMO*/
      if (tIsSPCV12G(agRoot))
      {
        saPortControl(agRoot, /* AGSA_PORT_SET_PORT_RESET_TIME */
                      agNULL,
                      0,
                      agPortContext,
                      AGSA_PORT_SET_PORT_RESET_TIME,
                      SAS_12G_PORT_RESET_TMO, // 800 ms
                      0
                      );
      }
      else
      {
        saPortControl(agRoot, /* AGSA_PORT_SET_PORT_RESET_TIME */
                      agNULL,
                      0,
                      agPortContext,
                      AGSA_PORT_SET_PORT_RESET_TIME,
                      SAS_PORT_RESET_TMO, // 300 ms
                      0
                      );
      }
    }
    else
    {
      /*
        an existing portcontext
        to be tested
      */

      TI_DBG2(("ossaHwCB: SAS existing portcontext returned\n"));

      onePortContext  = (tdsaPortContext_t *)agPortContext->osData;
      if (onePortContext == agNULL)
      {
        TI_DBG1(("ossaHwCB: onePortContext is NULL, wrong!\n"));
        return;
      }
      if (onePortContext->valid == agFALSE)
      {
        /* port has been invalidated; needs to be allocated */
        TI_DBG2(("ossaHwCB: SAS allocating port context\n"));

        tdsaSingleThreadedEnter(tiRoot, TD_PORT_LOCK);
        if (TDLIST_NOT_EMPTY(&(tdsaAllShared->FreePortContextList)))
        {
          TDLIST_DEQUEUE_FROM_HEAD(&PortContextList, &(tdsaAllShared->FreePortContextList));
          tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
          onePortContext = TDLIST_OBJECT_BASE(tdsaPortContext_t, FreeLink, PortContextList);
          TI_DBG2(("ossaHwCB: allocating pid %d\n", onePortContext->id));
          TI_DBG6(("ossaHwCB: allocating onePortContext %p\n", onePortContext));
          if (onePortContext == agNULL)
          {
            TI_DBG1(("ossaHwCB: onePortContext is NULL in allocation, wrong!\n"));
            return;
          }
          /* sets fields of tdsaportcontext */
#ifdef INITIATOR_DRIVER
          onePortContext->DiscoveryState = ITD_DSTATE_NOT_STARTED;
          onePortContext->discoveryOptions = AG_SA_DISCOVERY_OPTION_FULL_START;
#endif
          onePortContext->PhyIDList[PhyID] = agTRUE;
          if (IDframe == agNULL)
          {
            onePortContext->sasRemoteAddressHi = 0xFFFFFFFF;
            onePortContext->sasRemoteAddressLo = 0xFFFFFFFF;
            onePortContext->directAttatchedSAS = agTRUE;
          }
          else
          {
            onePortContext->sasRemoteAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(IDframe);
            onePortContext->sasRemoteAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(IDframe);
            /* Create ID frame and storing ID frame */
            osti_memcpy(&onePortContext->sasIDframe, IDframe, sizeof(agsaSASIdentify_t));
            tdhexdump("ossaHWCB: sasIDframe", (bit8 *)(&onePortContext->sasIDframe), sizeof(agsaSASIdentify_t));
            if (SA_IDFRM_GET_DEVICETTYPE(IDframe) == SAS_END_DEVICE)
            {
              onePortContext->directAttatchedSAS = agTRUE;
            }
          }

          onePortContext->sasLocalAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&tdsaAllShared->Ports[PhyID].SASID);
          onePortContext->sasLocalAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&tdsaAllShared->Ports[PhyID].SASID);
          onePortContext->tiPortalContext = tdsaAllShared->Ports[PhyID].tiPortalContext;
          onePortContext->agRoot = agRoot;
          onePortContext->agPortContext = agPortContext;
          tdsaAllShared->Ports[PhyID].portContext = onePortContext;
          agPortContext->osData = onePortContext;
          onePortContext->valid = agTRUE;
          if (LinkRate == 0x01)
          {
            onePortContext->LinkRate = SAS_CONNECTION_RATE_1_5G;
          }
          else if (LinkRate == 0x02)
          {
            onePortContext->LinkRate = SAS_CONNECTION_RATE_3_0G;
          }
          else if (LinkRate == 0x04)
          {
            onePortContext->LinkRate = SAS_CONNECTION_RATE_6_0G;
          }
          else /* (LinkRate == 0x08) */
          {
            onePortContext->LinkRate = SAS_CONNECTION_RATE_12_0G;
          }
          tdsaSingleThreadedEnter(tiRoot, TD_PORT_LOCK);
          TDLIST_ENQUEUE_AT_TAIL(&(onePortContext->MainLink), &(tdsaAllShared->MainPortContextList));
          tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
        }
        else
        {
          tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
          TI_DBG1(("\nossaHwCB: Attention!!! no more free PortContext.\n"));
          smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "Y2");
          return;
        }
      } /* invalidated port */
      else
      {
        /* already alloacated */
        TI_DBG2(("ossaHwCB: SAS already allocated port context\n"));
        if (TDLIST_EMPTY(&(tdsaAllShared->MainPortContextList)))
        {
          TI_DBG1(("ossaHwCB: wrong!!!  null tdsaPortContext list\n"));
          smTraceFuncExit(hpDBG_VERY_LOUD, 'e', "Y2");
          return;
        }
        if (onePortContext == agNULL)
        {
          TI_DBG1(("ossaHwCB: wrong !!! No corressponding tdsaPortContext\n"));
          smTraceFuncExit(hpDBG_VERY_LOUD, 'f', "Y2");
          return;
        }

        TI_DBG2(("ossaHwCB: existing pid %d\n", onePortContext->id));
        if (tdsaAllShared->Ports[PhyID].portContext == agNULL)
        {
          TI_DBG1(("ossaHwCB: existing allshared pid is NULL\n"));
        }
        else
        {
          TI_DBG2(("ossaHwCB: existing allshared pid %d\n", tdsaAllShared->Ports[PhyID].portContext->id));
        }
        /* updates PhyID belong to a port */
        onePortContext->PhyIDList[PhyID] = agTRUE;
#ifdef FDS_DM
        if (SA_IDFRM_GET_DEVICETTYPE(IDframe) == SAS_END_DEVICE &&
            SA_IDFRM_IS_SSP_TARGET(IDframe) )
        {
          TI_DBG2(("ossaHwCB: NOTIFY_ENABLE_SPINUP PhyID %d \n", PhyID));
          
          for (i=0;i<TD_MAX_NUM_NOTIFY_SPINUP;i++)
          {
            saLocalPhyControl(agRoot, agNULL, 0, PhyID, AGSA_PHY_NOTIFY_ENABLE_SPINUP, agNULL);
          }
        }

        /* update MCN */
        tdsaUpdateMCN(dmRoot, onePortContext);
#endif
      }
      onePortContext->SeenLinkUp = agTRUE;
    } /* else, old portcontext */

    break;
  }
#ifdef INITIATOR_DRIVER
  case OSSA_HW_EVENT_SATA_PHY_UP:
  {
    PhyID = TD_GET_PHY_ID(eventParm1);
    LinkRate = TD_GET_LINK_RATE(eventParm1);
    PortState = TD_GET_PORT_STATE(eventParm1);
    agDevHandle = agNULL;
    RegD2H = ( agsaFisRegDeviceToHost_t *)eventParm3;

    TI_DBG2(("ossaHwCB: Phy%d SATA link Up\n", PhyID));

    if (agDevHandle == agNULL)
    {
      TI_DBG3(("ossaHwCB: agDevHandle null by design change\n"));
    }

    if (RegD2H == agNULL)
    {
      TI_DBG1(("ossaHwCB: RegD2H null, wrong\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'g', "Y2");
      return;
    }


    TI_DBG2(("ossaHwCB: agDevHandle %p\n", agDevHandle));
    tdhexdump("ossaHWCB RegD2H", (bit8 *)RegD2H, sizeof(agsaFisRegDeviceToHost_t));
    TI_DBG2(("ossaHwCB: Sector Count %d\n", RegD2H->d.sectorCount));
    TI_DBG2(("ossaHwCB: LBA LOW %d\n", RegD2H->d.lbaLow));
    TI_DBG2(("ossaHwCB: LBA MID  %d\n", RegD2H->d.lbaMid));
    TI_DBG2(("ossaHwCB: LBA HIGH  %d\n", RegD2H->d.lbaHigh));
    TI_DBG2(("ossaHwCB: DEVICE  %d\n", RegD2H->d.device));

    /* debugging only */
    if (LinkRate == 0x01)
    {
      TI_DBG1(("ossaHwCB: SATA Link Rate is 1.5 Gbps PhyID %d\n",PhyID));
    }
    if (LinkRate == 0x02)
    {
      TI_DBG1(("ossaHwCB: SATA Link Rate is 3.0 Gbps PhyID %d\n",PhyID));
    }
    if (LinkRate == 0x04)
    {
      TI_DBG1(("ossaHwCB: SATA Link Rate is 6.0 Gbps PhyID %d\n",PhyID));
    }
    if (LinkRate == 0x08)
    {
      TI_DBG1(("ossaHwCB: SATA Link Rate is 12.0 Gbps PhyID %d\n",PhyID));
    }

    if (PortState == OSSA_PORT_INVALID)
    {
      TI_DBG1(("ossaHwCB: Wrong port state with SATA link up\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'h', "Y2");
      return;
    }

    if ( agPortContext->osData == agNULL)
    {/* if */
      TI_DBG6 (("ossaHwCB: PhyID %d tdsaAllShared %p\n", PhyID, tdsaAllShared));
      tdsaSingleThreadedEnter(tiRoot, TD_PORT_LOCK);
      if (TDLIST_NOT_EMPTY(&(tdsaAllShared->FreePortContextList)))
      {
        TDLIST_DEQUEUE_FROM_HEAD(&PortContextList, &(tdsaAllShared->FreePortContextList));
        tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
        onePortContext = TDLIST_OBJECT_BASE(tdsaPortContext_t, FreeLink, PortContextList);
        TI_DBG2(("ossaHwCB: pid %d\n", onePortContext->id));
        TI_DBG6(("ossaHwCB: onePortContext %p\n", onePortContext));
        if (onePortContext == agNULL)
        {
          TI_DBG1(("ossaHwCB: onePortContext is NULL in allocation, wrong!\n"));
          return;
        }

        /* sets fields of tdsaportcontext */
        onePortContext->DiscoveryState = ITD_DSTATE_NOT_STARTED;
        onePortContext->discoveryOptions = AG_SA_DISCOVERY_OPTION_FULL_START;
        onePortContext->PhyIDList[PhyID] = agTRUE;
        /* NO sas address for SATA */
        onePortContext->sasRemoteAddressHi = 0xFFFFFFFF;
        onePortContext->sasRemoteAddressLo = 0xFFFFFFFF;
        /* copying the signature */
        onePortContext->remoteSignature[0] = RegD2H->d.sectorCount;
        onePortContext->remoteSignature[1] = RegD2H->d.lbaLow;
        onePortContext->remoteSignature[2] = RegD2H->d.lbaMid;
        onePortContext->remoteSignature[3] = RegD2H->d.lbaHigh;
        onePortContext->remoteSignature[4] = RegD2H->d.device;

        onePortContext->sasLocalAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&tdsaAllShared->Ports[PhyID].SASID);
        onePortContext->sasLocalAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&tdsaAllShared->Ports[PhyID].SASID);
        onePortContext->tiPortalContext = tdsaAllShared->Ports[PhyID].tiPortalContext;
        onePortContext->agRoot = agRoot;
        onePortContext->agPortContext = agPortContext;
        tdsaAllShared->Ports[PhyID].portContext = onePortContext;
        agPortContext->osData = onePortContext;
        onePortContext->nativeSATAMode = agTRUE;
        onePortContext->valid = agTRUE;
        if (LinkRate == 0x01)
        {
          onePortContext->LinkRate = SAS_CONNECTION_RATE_1_5G;
        }
        else if (LinkRate == 0x02)
        {
          onePortContext->LinkRate = SAS_CONNECTION_RATE_3_0G;
        }
        else if (LinkRate == 0x04)
        {
          onePortContext->LinkRate = SAS_CONNECTION_RATE_6_0G;
        }
        else /* (LinkRate == 0x08) */
        {
          onePortContext->LinkRate = SAS_CONNECTION_RATE_12_0G;
        }

        tdsaSingleThreadedEnter(tiRoot, TD_PORT_LOCK);
        TDLIST_ENQUEUE_AT_TAIL(&(onePortContext->MainLink), &(tdsaAllShared->MainPortContextList));
        tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
      }
      else
      {
        tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
        TI_DBG1(("\nossaHwCB: Attention!!! no more free PortContext.\n"));
        smTraceFuncExit(hpDBG_VERY_LOUD, 'i', "Y2");
        return;
      }
#ifdef SATA_ENABLE
      /* tdssAddSATAToSharedcontext() sends identify device data to find out the uniqueness of
         target. In identify device data CB fn (satAddSATAIDDevCB()),
         tiPortLinkUp and tiPortDiscoveryReady happen
      */
      tdssAddSATAToSharedcontext(
                                  onePortContext,
                                  agRoot,
                                  agDevHandle, /* agNULL */
                                  agNULL,
                                  agTRUE,
                                  (bit8)PhyID
                                  );
#endif
      /* setting SAS PORT RESET TMO and SATA PORT RESET TMO*/
      saPortControl(agRoot, /* AGSA_PORT_SET_PORT_RESET_TIME */
                    agNULL,
                    0,
                    agPortContext,
                    AGSA_PORT_SET_PORT_RESET_TIME,
                    0,
                    SATA_PORT_RESET_TMO // 8000 ms
                    );

    }
    else
    {
      /*
        an existing portcontext
        to be tested
      */

      TI_DBG1(("ossaHwCB: SATA existing portcontext returned. need testing\n"));
      onePortContext  = (tdsaPortContext_t *)agPortContext->osData;
      /* for debugging only */
      if (onePortContext->valid == agFALSE)
      {
        /* port has been invalidated; needs to be allocated */
        TI_DBG2(("ossaHwCB: SATA allocating port context\n"));
      }
      else
      {
        /* already alloacated */
        TI_DBG1(("ossaHwCB: Wrong!!! SATA already allocated port context\n"));
        smTraceFuncExit(hpDBG_VERY_LOUD, 'j', "Y2");
        return;
      }

      tdsaSingleThreadedEnter(tiRoot, TD_PORT_LOCK);
      if (TDLIST_NOT_EMPTY(&(tdsaAllShared->FreePortContextList)))
      {
        TDLIST_DEQUEUE_FROM_HEAD(&PortContextList, &(tdsaAllShared->FreePortContextList));
        tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
        onePortContext = TDLIST_OBJECT_BASE(tdsaPortContext_t, FreeLink, PortContextList);
        TI_DBG2(("ossaHwCB: pid %d\n", onePortContext->id));
        TI_DBG6(("ossaHwCB: onePortContext %p\n", onePortContext));
        if (onePortContext == agNULL)
        {
          TI_DBG1(("ossaHwCB: onePortContext is NULL in allocation, wrong!\n"));
          return;
        }

        /* sets fields of tdsaportcontext */
        onePortContext->DiscoveryState = ITD_DSTATE_NOT_STARTED;
        onePortContext->discoveryOptions = AG_SA_DISCOVERY_OPTION_FULL_START;
        onePortContext->PhyIDList[PhyID] = agTRUE;
        /* NO sas address for SATA */
        onePortContext->sasRemoteAddressHi = 0xFFFFFFFF;
        onePortContext->sasRemoteAddressLo = 0xFFFFFFFF;
        /* copying the signature */
        onePortContext->remoteSignature[0] = RegD2H->d.sectorCount;
        onePortContext->remoteSignature[1] = RegD2H->d.lbaLow;
        onePortContext->remoteSignature[2] = RegD2H->d.lbaMid;
        onePortContext->remoteSignature[3] = RegD2H->d.lbaHigh;
        onePortContext->remoteSignature[4] = RegD2H->d.device;

        onePortContext->sasLocalAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(&tdsaAllShared->Ports[PhyID].SASID);
        onePortContext->sasLocalAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(&tdsaAllShared->Ports[PhyID].SASID);
        onePortContext->tiPortalContext = tdsaAllShared->Ports[PhyID].tiPortalContext;
        onePortContext->agRoot = agRoot;
        onePortContext->agPortContext = agPortContext;
        tdsaAllShared->Ports[PhyID].portContext = onePortContext;
        agPortContext->osData = onePortContext;
        onePortContext->nativeSATAMode = agTRUE;
        onePortContext->valid = agTRUE;
        if (LinkRate == 0x01)
        {
          onePortContext->LinkRate = SAS_CONNECTION_RATE_1_5G;
        }
        else if (LinkRate == 0x02)
        {
          onePortContext->LinkRate = SAS_CONNECTION_RATE_3_0G;
        }
        else if (LinkRate == 0x04)
        {
          onePortContext->LinkRate = SAS_CONNECTION_RATE_6_0G;
        }
        else /* (LinkRate == 0x08) */
        {
          onePortContext->LinkRate = SAS_CONNECTION_RATE_12_0G;
        }

        tdsaSingleThreadedEnter(tiRoot, TD_PORT_LOCK);
        TDLIST_ENQUEUE_AT_TAIL(&(onePortContext->MainLink), &(tdsaAllShared->MainPortContextList));
        tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
      }
      else
      {
        tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
        TI_DBG1(("\nossaHwCB: Attention!!! no more free PortContext.\n"));
        smTraceFuncExit(hpDBG_VERY_LOUD, 'k', "Y2");
        return;
      }


      /*hotplug */
#ifdef SATA_ENABLE
      tdssAddSATAToSharedcontext(
                                  onePortContext,
                                  agRoot,
                                  agDevHandle, /* agNULL */
                                  agNULL,
                                  agTRUE,
                                  (bit8)PhyID
                                  );
#endif
    /* end hotplug */
    }

    break;
  }
#endif
  case OSSA_HW_EVENT_SATA_SPINUP_HOLD:
  {
    PhyID = TD_GET_PHY_ID(eventParm1);

    TI_DBG2(("ossaHwCB: spinup hold PhyID %d\n", PhyID));
    break;
  }

  case OSSA_HW_EVENT_PHY_DOWN:
  {
    bit32 AllPhyDown = agTRUE;

    /* 4/15/08 spec */
    PhyID = TD_GET_PHY_ID(eventParm1);
    LinkRate = TD_GET_LINK_RATE(eventParm1);
    PortState = TD_GET_PORT_STATE(eventParm1);


    TI_DBG2(("ossaHwCB: Phy%d link Down\n", PhyID));

    if (agPortContext == agNULL)
    {
      TI_DBG1(("ossaHwCB: agPortContext null, wrong\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'l', "Y2");
      return;
    }

    if ( agPortContext->osData == agNULL)
    { /* if */
      /* PortContext must exit at this point */
      TI_DBG1(("ossaHwCB: NULL portalcontext. Error. Can't be NULL\n"));
    }
    else
    {
      TI_DBG3(("ossaHwCB: NOT NULL portalcontext\n"));
      onePortContext  = (tdsaPortContext_t *)agPortContext->osData;
      if (onePortContext == agNULL)
      {
        TI_DBG1(("ossaHwCB: wrong !!! No corressponding tdsaPortContext\n"));
        smTraceFuncExit(hpDBG_VERY_LOUD, 'm', "Y2");
        return;
      }
      onePortContext->PhyIDList[PhyID] = agFALSE;
      for(i=0;i<TD_MAX_NUM_PHYS;i++)
      {
        if (onePortContext->PhyIDList[i] == agTRUE)
        {
          TI_DBG3(("ossaHwCB: Phy %d is still up\n", i));
          AllPhyDown = agFALSE;
          break;
        }
      }

      /* last phy belong to the portcontext */
      if (AllPhyDown == agTRUE)
      {
#ifdef NOT_YET  
        TI_DBG1(("ossaHwCB: calling tiPortLinkDown\n"));
        ostiPortEvent (
                       tiRoot,
                       tiPortLinkDown,
                       tiSuccess,
                       (void *)onePortContext->tiPortalContext
                       );
#endif
      }

      if (PortState == OSSA_PORT_VALID)
      {
        /* do nothing */
        /* no ack for every phy down */
#ifdef FDS_DM
        /* update MCN for all devices belong to this port */
        tdsaUpdateMCN(dmRoot, onePortContext);
#endif
      }
      else if (PortState == OSSA_PORT_LOSTCOMM)
      {
        /*
         1. Mark the port as invalid and stop the io for that port and its device
         No ack here. Otherwise, port will be released by FW.
        */
        TI_DBG2(("ossaHwCB: phy Down and OSSA_PORT_LOSTCOMM\n"));
        /* save eventSource related information in tdsaAllShared */
        tdsaAllShared->eventSource[PhyID].EventValid =  agTRUE;
        tdsaAllShared->eventSource[PhyID].Source.agPortContext =  agPortContext;
        tdsaAllShared->eventSource[PhyID].Source.event =  OSSA_HW_EVENT_PHY_DOWN;
        /* phy ID */
        tdsaAllShared->eventSource[PhyID].Source.param =  PhyID;
        /* phy ID */
        onePortContext->eventPhyID = PhyID;
        /* to stop IO's */
        onePortContext->valid = agFALSE;
        break;
      }
      else if (PortState == OSSA_PORT_IN_RESET)
      {
        TI_DBG2(("ossaHwCB: phy Down and OSSA_PORT_IN_RESET\n"));
        /* save eventSource related information in tdsaAllShared */
        tdsaAllShared->eventSource[PhyID].EventValid =  agTRUE;
        tdsaAllShared->eventSource[PhyID].Source.agPortContext =  agPortContext;
        tdsaAllShared->eventSource[PhyID].Source.event =  OSSA_HW_EVENT_PHY_DOWN;
        /* phy ID */
        tdsaAllShared->eventSource[PhyID].Source.param =  PhyID;
        /* phy ID */
        onePortContext->eventPhyID = PhyID;
        /* to stop IO's */
        onePortContext->valid = agFALSE;
        break;
      }
      else if (PortState == OSSA_PORT_INVALID)
      {
        TI_DBG1(("ossaHwCB: Last phy Down and port invalid OSSA_PORT_INVALID\n"));
        /*
          invalidate port
          then, saHwEventAck() in ossaDeregisterDeviceHandleCB()
        */

        /* save eventSource related information in tdsaAllShared */
        tdsaAllShared->eventSource[PhyID].EventValid =  agTRUE;
        tdsaAllShared->eventSource[PhyID].Source.agPortContext =  agPortContext;
        tdsaAllShared->eventSource[PhyID].Source.event =  OSSA_HW_EVENT_PHY_DOWN;
        /* phy ID */
        tdsaAllShared->eventSource[PhyID].Source.param =  PhyID;
        /* phy ID */
        onePortContext->eventPhyID = PhyID;

        onePortContext->valid = agFALSE;

        TI_DBG2(("ossaHwCB: pid %d\n", onePortContext->id));
#ifdef INITIATOR_DRIVER
        /* notifying link down (all links belonging to a port are down) */
        ostiPortEvent(
                      tiRoot,
                      tiPortStopped,
                      tiSuccess,
                      (void *)onePortContext->tiPortalContext
                      );
#endif

#ifdef TARGET_DRIVER
        ostiPortEvent(
                      tiRoot,
                      tiPortLinkDown,
                      tiSuccess,
                      (void *)onePortContext->tiPortalContext
                      );

#endif

#ifdef INITIATOR_DRIVER
        tdssReportRemovals(agRoot,
                         onePortContext,
                         agFALSE
                        );
#endif
#ifdef TARGET_DRIVER
        ttdssReportRemovals(agRoot,
                            onePortContext,
                            agFALSE
                           );

#endif

        /* find a PhyID and reset for portContext in tdssSASShared */
        for(i=0;i<TD_MAX_NUM_PHYS;i++)
        {
          if (onePortContext->PhyIDList[i] == agTRUE)
          {
            tdsaAllShared->Ports[i].portContext = agNULL;
          }
        }
    /* portcontext is removed from MainLink to FreeLink in tdssReportRemovals or
       ossaDeregisterDeviceHandleCB
     */
      }/* OSSA_PORT_INVALID */
      else
      {
        /* other newly defined port state */
        /* do nothing */
        TI_DBG2(("ossaHwCB: portstate 0x%x\n", PortState));
      }
    } /* big else */
    break;
  }
  case OSSA_HW_EVENT_PHY_START_STATUS:
  {
    PhyID = TD_GET_PHY_ID(eventParm1);
    PhyStatus =  TD_GET_PHY_STATUS(eventParm1);

    TI_DBG6(("ossaHwCB: OSSA_HW_EVENT_PHY_START_STATUS\n"));
    if (PhyStatus == 0x00)
    {
      TI_DBG6(("ossaHwCB: OSSA_HW_EVENT_PHY_START_STATUS, SUCCESS\n"));
    }
    else if (PhyStatus == 0x01)
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_PHY_START_STATUS, INVALID_PHY\n"));
    }
    else if (PhyStatus == 0x02)
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_PHY_START_STATUS, PHY_NOT_DISABLED\n"));
    }
    else
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_PHY_START_STATUS, OTHER_FAILURE %d\n", PhyStatus));
    }
    break;
  }
  case OSSA_HW_EVENT_PHY_STOP_STATUS:
  {
    agsaContext_t     *agContext;
    PhyID = TD_GET_PHY_ID(eventParm1);
    PhyStatus =  TD_GET_PHY_STATUS(eventParm1);
    PortState = TD_GET_PORT_STATE(eventParm1);

    TI_DBG2(("ossaHwCB: OSSA_HW_EVENT_PHY_STOP_STATUS\n"));
    if (PhyStatus == 0x00)
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_PHY_STOP_STATUS, SUCCESS\n"));
      agContext = (agsaContext_t *)eventParm2;
      onePortContext  = (tdsaPortContext_t *)agContext->osData;
      if (onePortContext == agNULL)
      {
        TI_DBG1(("ossaHwCB: onePortContext is null, wrong!!!\n"));
        return;
      }
      onePortContext->PhyIDList[PhyID] = agFALSE;
      if (PortState == OSSA_PORT_INVALID) /* invalid port */
      {
        TI_DBG1(("ossaHwCB: OSSA_PORT_INVALID\n"));
        tdsaAllShared->eventSource[PhyID].EventValid =  NO_ACK;
        onePortContext->eventPhyID = PhyID;
        onePortContext->valid = agFALSE;

        TI_DBG2(("ossaHwCB: pid %d\n", onePortContext->id));
#ifdef INITIATOR_DRIVER
        /* notifying link down (all links belonging to a port are down) */
        ostiPortEvent(
                      tiRoot,
                      tiPortStopped,
                      tiSuccess,
                      (void *)onePortContext->tiPortalContext
                      );
#endif

#ifdef TARGET_DRIVER
        ostiPortEvent(
                      tiRoot,
                      tiPortLinkDown,
                      tiSuccess,
                      (void *)onePortContext->tiPortalContext
                      );

#endif

#ifdef INITIATOR_DRIVER
        tdssReportRemovals(agRoot,
                           onePortContext,
                           agFALSE
                          );
#endif
#ifdef TARGET_DRIVER
        ttdssReportRemovals(agRoot,
                            onePortContext,
                            agFALSE
                           );

#endif

        /* find a PhyID and reset for portContext in tdssSASShared */
        for(i=0;i<TD_MAX_NUM_PHYS;i++)
        {
          if (onePortContext->PhyIDList[i] == agTRUE)
          {
            tdsaAllShared->Ports[i].portContext = agNULL;
          }
        }
    /* portcontext is removed from MainLink to FreeLink in tdssReportRemovals or
       ossaDeregisterDeviceHandleCB
     */
      } /* invalid port */
    }
    else if (PhyStatus == 0x01)
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_PHY_STOP_STATUS, INVALID_PHY\n"));
    }
    else if (PhyStatus == 0x02)
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_PHY_STOP_STATUS, DEVICES_ATTACHED\n"));
    }
    else if (PhyStatus == 0x03)
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_PHY_STOP_STATUS, OTHER_FAILURE\n"));
    }
    else if (PhyStatus == 0x04)
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_PHY_STOP_STATUS, PHY_NOT_DISABLED\n"));
    }
    else
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_PHY_STOP_STATUS, Unknown %d\n", PhyStatus));
    }
    break;
  }

  case OSSA_HW_EVENT_RESET_START:
  {
    bit32 new_status = TD_GET_RESET_STATUS(eventParm1);
    TI_DBG2(("ossaHwCB: RESET_START, status %d\n", new_status));
    if (new_status == OSSA_SUCCESS)
    {
      tdsaAllShared->flags.resetInProgress = agTRUE;
      TI_DBG2(("ossaHwCB: RESET_START, SUCCESS\n"));
    }
    else if (new_status == OSSA_FAILURE)
    {
      TI_DBG1(("ossaHwCB: RESET_START, FAILURE\n"));
    }
    else
    {
      TI_DBG1(("ossaHwCB: RESET_START, PENDING\n"));
    }
    break;
  }

  case OSSA_HW_EVENT_RESET_COMPLETE:
  {
    bit32 new_status = TD_GET_RESET_STATUS(eventParm1);
#ifdef SOFT_RESET_TEST
    DbgPrint("Reset Complete\n");
#endif
    TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_RESET_COMPLETE, status %d\n", new_status));
    if (new_status == OSSA_SUCCESS)
    {
      /* remove all portcontext and devices */
#ifdef INITIATOR_DRIVER
      tdssRemoveSASSATAFromSharedcontextByReset(agRoot);
#endif
      tdsaAllShared->flags.resetInProgress = agFALSE;
      /*
        a callback notifying reset completion
      */
      ostiPortEvent(
                    tiRoot,
                    tiPortResetComplete,
                    tiSuccess,
                    agNULL
                    );
    }
    else
    {
      /*
        a callback notifying reset completion
      */
      tdsaAllShared->flags.resetInProgress = agFALSE;
      ostiPortEvent(
                    tiRoot,
                    tiPortResetComplete,
                    tiError,
                    agNULL
                    );

    }
    break;
  }

  case OSSA_HW_EVENT_PHY_ERR_INBOUND_CRC:
  {
    PhyID = TD_GET_PHY_ID(eventParm1);
    PortState = TD_GET_PORT_STATE(eventParm1);
    agPhyErrCountersPage = (agsaPhyErrCountersPage_t *)eventParm2;

    TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_PHY_ERR_INBOUND_CRC from PhyID %d; to be tested\n", PhyID));

    if (PortState == OSSA_PORT_INVALID)
    {
      TI_DBG1(("ossaHwCB: Wrong port state with OSSA_HW_EVENT_PHY_ERR_INBOUND_CRC\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'n', "Y2");
      return;
    }

    if (agPhyErrCountersPage != agNULL)
    {
      TI_DBG2(("ossaHwCB: OSSA_HW_EVENT_PHY_ERR_INBOUND_CRC from PhyID %d\n", PhyID));
      TI_DBG1(("ossaHwCB: iDw %d rDE %d cV %d lS %d rP %d iCRC %d\n",
                        agPhyErrCountersPage->invalidDword,
                        agPhyErrCountersPage->runningDisparityError,
                        agPhyErrCountersPage->codeViolation,
                        agPhyErrCountersPage->lossOfDwordSynch,
                        agPhyErrCountersPage->phyResetProblem,
                        agPhyErrCountersPage->inboundCRCError ));
    }
    else
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_PHY_ERR_INBOUND_CRC: Error!!!  eventParm2 is NULL\n"));
    }

    /* saHwEventAck() */
    eventSource.agPortContext = agPortContext;
    eventSource.event = OSSA_HW_EVENT_PHY_ERR_INBOUND_CRC;
    /* phy ID */
    eventSource.param = PhyID;
    HwAckSatus = saHwEventAck(
                              agRoot,
                              agNULL, /* agContext */
                              0,
                              &eventSource, /* agsaEventSource_t */
                              0,
                              0
                              );
    if ( HwAckSatus != AGSA_RC_SUCCESS)
    {
      TI_DBG1(("ossaHwCB: failing in saHwEventAck; status %d\n", HwAckSatus));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'o', "Y2");
      return;
    }
    break;
  }
#ifdef REMOVED
  case OSSA_HW_EVENT_PORT_INVALID:
  {
    TI_DBG1(("ossaHwCB: PORT_INVALID\n"));

    if ( agPortContext == agNULL)
    {
      TI_DBG1(("ossaHwCB: agPortContext is NULL, wrong.\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'p', "Y2");
      return;
    }
    if ( agPortContext->osData != agNULL)
    {
      TI_DBG1(("ossaHwCB: NOT NULL osDATA\n"));
      /*
        put the old portcontext back to free list
      */
      onePortContext = (tdsaPortContext_t *)agPortContext->osData;
      TI_DBG1(("ossaHwCB: pid %d\n", onePortContext->id));

#ifdef INITIATOR_DRIVER
      /* notifying link down (all links belonging to a port are down) */
      ostiPortEvent (
                     tiRoot,
                     tiPortStopped,
                     tiSuccess,
                     (void *)onePortContext->tiPortalContext

                     );
#endif /* INITIATOR_DRIVER */
#ifdef TARGET_DRIVER
        ostiPortEvent(
                      tiRoot,
                      tiPortLinkDown,
                      tiSuccess,
                      (void *)onePortContext->tiPortalContext
                      );

#endif /*TARGET_DRIVER  */

      /* find the device belonging to the port and remove it from the device list */
      //tdssRemoveSASSATAFromSharedcontext(agRoot, tdsaDeviceData, onePortContext);


#ifdef INITIATOR_DRIVER
      /* reset the fields of portcontext */
      onePortContext->DiscoveryState = ITD_DSTATE_NOT_STARTED;
      tdssReportRemovals(agRoot,
                         onePortContext,
                         agFALSE
                        );

      onePortContext->discoveryOptions = AG_SA_DISCOVERY_OPTION_FULL_START;
      onePortContext->DiscoveryRdyGiven = agFALSE;
      onePortContext->SeenLinkUp = agFALSE;

#endif /* INITIATOR_DRIVER */



      /* for hotplug */

      /* find a PhyID and reset for portContext in tdssSASShared */
      for(i=0;i<TD_MAX_NUM_PHYS;i++)
      {
        if (onePortContext->PhyIDList[i] == agTRUE)
        {
          tdsaAllShared->Ports[i].portContext = agNULL;
        }
      }

      /* reset PhyIDList in portcontext */
      for(i=0;i<TD_MAX_NUM_PHYS;i++)
      {
        onePortContext->PhyIDList[i] = agFALSE;
      }

//      onePortContext->tiPortalContext = agNULL;
//      onePortContext->agRoot = agNULL;
      onePortContext->agPortContext = agNULL;
      onePortContext->valid = agFALSE;

      TI_DBG4(("ossaHwCB: pid %d count %d\n", onePortContext->id, onePortContext->Count));

      /* resets the number of devices in onePortContext */
      onePortContext->Count = 0;
      onePortContext->discovery.pendingSMP = 0;
      onePortContext->discovery.SeenBC = agFALSE;


      /*
        put all devices belonging to the onePortContext
        back to the free link
      */

      tdsaSingleThreadedEnter(tiRoot, TD_PORT_LOCK);
      TDLIST_DEQUEUE_THIS(&(onePortContext->MainLink));
      TDLIST_ENQUEUE_AT_TAIL(&(onePortContext->FreeLink), &(tdsaPortContext->FreeLink));
      tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
    }
    else
    {
      TI_DBG1(("ossaHwCB: NULL osDATA: wrong\n"));
    }
    TI_DBG6(("ossaHwCB: PORT_INVALID end\n"));
    break;
  }
#endif /* REMOVED */

  case OSSA_HW_EVENT_BROADCAST_CHANGE:
  {
    PhyID = TD_GET_PHY_ID(eventParm1);
    PortState = TD_GET_PORT_STATE(eventParm1);
    TI_DBG1(("ossaHwCB: BROADCAST_CHANGE from PhyID %d\n", PhyID));

    if (PortState == OSSA_PORT_INVALID)
    {
      TI_DBG1(("ossaHwCB: Wrong port state with  BROADCAST_CHANGE\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'q', "Y2");
      return;
    }
    /* saHwEventAck() */
    eventSource.agPortContext = agPortContext;
    eventSource.event = OSSA_HW_EVENT_BROADCAST_CHANGE;
    /* phy ID */
    eventSource.param = PhyID;
    HwAckSatus = saHwEventAck(
                              agRoot,
                              agNULL, /* agContext */
                              0,
                              &eventSource, /* agsaEventSource_t */
                              0,
                              0
                              );
    TI_DBG4(("ossaHwCB: calling saHwEventAck\n"));

    if ( HwAckSatus != AGSA_RC_SUCCESS)
    {
      TI_DBG1(("ossaHwCB: failing in saHwEventAck; status %d\n", HwAckSatus));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'r', "Y2");
      return;
    }
    if (tIsSPC12SATA(agRoot))
    {
      TI_DBG1(("ossaHwCB: BROADCAST_CHANGE received for SATA Controller\n"));
      break;
    }
    /*
     * incremental discovery is to be tested and debugged further
     */

     /* just for testing discovery abort */
#ifdef FDS_DM_NO
    if (agPortContext == agNULL)
    {
      /* this case happens when broadcase is received first before the link up */
      TI_DBG2(("ossaHwCB: agPortContext is NULL. Do nothing.\n"));
    }
    else if ( agPortContext->osData != agNULL)
    {
      dmRoot = &(tdsaAllShared->dmRoot);
      onePortContext = (tdsaPortContext_t *)agPortContext->osData;
      dmPortContext = &(onePortContext->dmPortContext);

      dmQueryDiscovery(dmRoot, dmPortContext);
//      dmDiscover(dmRoot, dmPortContext, DM_DISCOVERY_OPTION_ABORT);

#if 1
      if (onePortContext->DMDiscoveryState == dmDiscInProgress)
      {
        dmDiscover(dmRoot, dmPortContext, DM_DISCOVERY_OPTION_ABORT);
      }
#endif /* 1 */

      TI_DBG2(("ossaHwCB: portcontext pid %d\n", onePortContext->id));
      if (onePortContext->DMDiscoveryState == dmDiscCompleted ||
          onePortContext->DMDiscoveryState == dmDiscAborted ||
          onePortContext->DMDiscoveryState == dmDiscAbortInvalid )
      {
        TI_DBG1(("ossaHwCB: BROADCAST_CHANGE; calling dmNotifyBC and does incremental discovery\n"));
        dmNotifyBC(dmRoot, dmPortContext, OSSA_HW_EVENT_BROADCAST_CHANGE);
        dmDiscover(dmRoot, dmPortContext, DM_DISCOVERY_OPTION_INCREMENTAL_START);

      }
      else
      {
        TI_DBG2(("ossaHwCB: pid %d BROADCAST_CHANGE; updating SeenBC. calling dmNotifyBC\n", onePortContext->id));
        dmNotifyBC(dmRoot, dmPortContext, OSSA_HW_EVENT_BROADCAST_CHANGE);
      }
    }
    else
    {
      TI_DBG1(("ossaHwCB: BROADCAST_CHANGE NULL osDATA wrong !!! \n"));
    }


#endif /* FDS_DM_NO */

#ifdef FDS_DM
    if (agPortContext == agNULL)
    {
      /* this case happens when broadcase is received first before the link up */
      TI_DBG2(("ossaHwCB: agPortContext is NULL. Do nothing.\n"));
    }
    else if ( agPortContext->osData != agNULL)
    {
      dmRoot = &(tdsaAllShared->dmRoot);
      onePortContext = (tdsaPortContext_t *)agPortContext->osData;
      dmPortContext = &(onePortContext->dmPortContext);

      dmQueryDiscovery(dmRoot, dmPortContext);

      TI_DBG2(("ossaHwCB: portcontext pid %d\n", onePortContext->id));
      if (onePortContext->DMDiscoveryState == dmDiscCompleted ||
          onePortContext->DMDiscoveryState == dmDiscAborted ||
          onePortContext->DMDiscoveryState == dmDiscAbortInvalid )
      {
        TI_DBG1(("ossaHwCB: BROADCAST_CHANGE; calling dmNotifyBC and does incremental discovery, pid %d\n", onePortContext->id));
        onePortContext->DiscoveryState = ITD_DSTATE_STARTED;
        dmNotifyBC(dmRoot, dmPortContext, OSSA_HW_EVENT_BROADCAST_CHANGE);
        dmDiscover(dmRoot, dmPortContext, DM_DISCOVERY_OPTION_INCREMENTAL_START);

      }
      else if (onePortContext->DMDiscoveryState == dmDiscFailed )
      {
        TI_DBG1(("ossaHwCB: dmDiscFailed; pid %d BROADCAST_CHANGE; updating SeenBC. calling dmNotifyBC\n", onePortContext->id));
        onePortContext->DiscFailNSeenBC = agTRUE;
        dmNotifyBC(dmRoot, dmPortContext, OSSA_HW_EVENT_BROADCAST_CHANGE);
      }
      else
      {
        TI_DBG2(("ossaHwCB: pid %d BROADCAST_CHANGE; updating SeenBC. calling dmNotifyBC\n", onePortContext->id));
        dmNotifyBC(dmRoot, dmPortContext, OSSA_HW_EVENT_BROADCAST_CHANGE);
      }
    }
    else
    {
      TI_DBG1(("ossaHwCB: BROADCAST_CHANGE NULL osDATA wrong !!! \n"));
    }
#endif /* FDS_DM */

#ifdef FDS_DM_WORKED
    if (agPortContext == agNULL)
    {
      /* this case happens when broadcase is received first before the link up */
      TI_DBG2(("ossaHwCB: agPortContext is NULL. Do nothing.\n"));
    }
    else if ( agPortContext->osData != agNULL)
    {
      onePortContext = (tdsaPortContext_t *)agPortContext->osData;
      TI_DBG2(("ossaHwCB: calling dmNotifyBC\n"));
      dmRoot = &(tdsaAllShared->dmRoot);
      dmPortContext = &(onePortContext->dmPortContext);
      dmNotifyBC(dmRoot, dmPortContext, OSSA_HW_EVENT_BROADCAST_CHANGE);
    }
#endif /* FDS_DM_WORKED */

#ifndef FDS_DM
#ifdef INITIATOR_DRIVER
    if (agPortContext == agNULL)
    {
      /* this case happens when broadcase is received first before the link up */
      TI_DBG2(("ossaHwCB: agPortContext is NULL. Do nothing.\n"));
    }
    else if ( agPortContext->osData != agNULL)
    {
      onePortContext = (tdsaPortContext_t *)agPortContext->osData;
      TI_DBG2(("ossaHwCB: portcontext pid %d\n", onePortContext->id));
      if (onePortContext->DiscoveryState == ITD_DSTATE_COMPLETED)
      {
        TI_DBG1(("ossaHwCB: BROADCAST_CHANGE; does incremental discovery\n"));
        onePortContext->DiscoveryState = ITD_DSTATE_NOT_STARTED;
        onePortContext->discoveryOptions = AG_SA_DISCOVERY_OPTION_INCREMENTAL_START;
        /* processed broadcast change */
        onePortContext->discovery.SeenBC = agFALSE;
#ifdef TD_DISCOVER
        if (tdsaAllShared->ResetInDiscovery != 0 &&
            onePortContext->discovery.ResetTriggerred == agTRUE)
        {
          TI_DBG2(("ossaHwCB: tdsaBCTimer\n"));
          tdsaBCTimer(tiRoot, onePortContext);
        }
        else
        {
          tdsaDiscover(
                     tiRoot,
                     onePortContext,
                     TDSA_DISCOVERY_TYPE_SAS,
                     TDSA_DISCOVERY_OPTION_INCREMENTAL_START
                    );
        }
#else
        saDiscover(agRoot,
                   agPortContext,
                   AG_SA_DISCOVERY_TYPE_SAS,
                   onePortContext->discoveryOptions);
#endif
      }
      else
      {
        TI_DBG2(("ossaHwCB: pid %d BROADCAST_CHANGE; updating SeenBC. Do nothing.\n", onePortContext->id));
        onePortContext->discovery.SeenBC = agTRUE;
      }
    }
    else
    {
      TI_DBG1(("ossaHwCB: BROADCAST_CHANGE NULL osDATA wrong !!! \n"));
    }
#endif
#endif /* ifndef FDS_DM */

    break;
  }

  case OSSA_HW_EVENT_PORT_RECOVERY_TIMER_TMO:
  {
    PhyID = TD_GET_PHY_ID(eventParm1);
    PortState = TD_GET_PORT_STATE(eventParm1);

    /*
      1. tear town the portcontext just like link down last phy down
      2. ack
      port state must be invalid
    */

    TI_DBG2(("ossaHwCB: OSSA_HW_EVENT_PORT_RECOVERY_TIMER_TMO\n"));

    if (PortState == OSSA_PORT_VALID)
    {
      TI_DBG1(("ossaHwCB: Wrong port state\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 's', "Y2");
      return;
    }

    TD_ASSERT(agPortContext, "agPortContext");
    if ( agPortContext->osData == agNULL)
    { /* if */
      /* PortContext must exit at this point */
      TI_DBG1(("ossaHwCB: NULL portalcontext. Error. Can't be NULL\n"));
    }
    else
    {
      onePortContext  = (tdsaPortContext_t *)agPortContext->osData;
      onePortContext->valid = agFALSE;

      TI_DBG1(("ossaHwCB: tiPortStopped pid %d\n", onePortContext->id));
#ifdef INITIATOR_DRIVER
      /* notifying link down (all links belonging to a port are down) */
      ostiPortEvent(
                    tiRoot,
                    tiPortStopped,
                    tiSuccess,
                    (void *)onePortContext->tiPortalContext
                    );
#endif

#ifdef TARGET_DRIVER
        ostiPortEvent(
                      tiRoot,
                      tiPortLinkDown,
                      tiSuccess,
                      (void *)onePortContext->tiPortalContext
                      );

#endif

#ifdef INITIATOR_DRIVER
      tdssReportRemovals(agRoot,
                         onePortContext,
                         agFALSE
                         );
#endif
#ifdef TARGET_DRIVER
      ttdssReportRemovals(agRoot,
                          onePortContext,
                          agFALSE
                         );

#endif
      /* find a PhyID and reset for portContext in tdssSASShared */
      for(i=0;i<TD_MAX_NUM_PHYS;i++)
      {
        if (onePortContext->PhyIDList[i] == agTRUE)
        {
          tdsaAllShared->Ports[i].portContext = agNULL;
        }
      }
      /* portcontext is removed from MainLink to FreeLink in tdssReportRemovals or
         ossaDeregisterDeviceHandleCB
       */
    }

    break;
  }

  case OSSA_HW_EVENT_PORT_RESET_TIMER_TMO:
  {
    /*
       clean up
    */
    PhyID = TD_GET_PHY_ID(eventParm1);
    PortState = TD_GET_PORT_STATE(eventParm1);

    TI_DBG2(("ossaHwCB: OSSA_HW_EVENT_PORT_RESET_TIMER_TMO\n"));

    if (PortState == OSSA_PORT_VALID)
    {
      TI_DBG1(("ossaHwCB: Wrong port state\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 't', "Y2");
      return;
    }

    if (agPortContext == agNULL)
    {
      TI_DBG1(("ossaHwCB: agPortContext is NULL, error\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'u', "Y2");
      return;
    }

    if ( agPortContext->osData == agNULL)
    { /* if */
      /* PortContext must exit at this point */
      TI_DBG1(("ossaHwCB: NULL portalcontext. Error. Can't be NULL\n"));
    }
    else
    {
      onePortContext  = (tdsaPortContext_t *)agPortContext->osData;
      onePortContext->valid = agFALSE;

      TI_DBG1(("ossaHwCB: pid %d tiPortStopped\n", onePortContext->id));

#ifdef INITIATOR_DRIVER
      /* notifying link down (all links belonging to a port are down) */
      ostiPortEvent(
                    tiRoot,
                    tiPortStopped,
                    tiSuccess,
                    (void *)onePortContext->tiPortalContext
                    );
#endif

#ifdef TARGET_DRIVER
        ostiPortEvent(
                      tiRoot,
                      tiPortLinkDown,
                      tiSuccess,
                      (void *)onePortContext->tiPortalContext
                      );

#endif

#ifdef INITIATOR_DRIVER
      tdssReportRemovals(agRoot,
                         onePortContext,
                         agFALSE
                         );
#endif
#ifdef TARGET_DRIVER
      ttdssReportRemovals(agRoot,
                          onePortContext,
                          agFALSE
                         );

#endif
      /* find a PhyID and reset for portContext in tdssSASShared */
      for(i=0;i<TD_MAX_NUM_PHYS;i++)
      {
        if (onePortContext->PhyIDList[i] == agTRUE)
        {
          tdsaAllShared->Ports[i].portContext = agNULL;
        }
      }
      /* portcontext is removed from MainLink to FreeLink in tdssReportRemovals or
         ossaDeregisterDeviceHandleCB
       */
    }

    break;
  }

  case OSSA_HW_EVENT_PORT_RESET_COMPLETE:
  {
#ifdef INITIATOR_DRIVER
    tiIORequest_t *currentTaskTag = agNULL;
#endif

#ifdef REMOVED
    smRoot_t  *smRoot = &(tdsaAllShared->smRoot);
#endif

    PhyID = TD_GET_PHY_ID(eventParm1);
    PortState = TD_GET_PORT_STATE(eventParm1);
    IDframe = (agsaSASIdentify_t *)eventParm3;

    /* completes for Lun Reset and Target reset for directly attached SATA */
    /* completes for Target reset for directly attached SAS */

    TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_PORT_RESET_COMPLETE, phyID %d\n", PhyID));

    /* error check */
    if (PortState == OSSA_PORT_INVALID)
    {
      TI_DBG1(("ossaHwCB: Wrong port state\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'v', "Y2");
      return;
    }

    if (agPortContext == agNULL)
    {
      TI_DBG1(("ossaHwCB: agPortContext null, wrong\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'w', "Y2");
      return;
    }
    if ( agPortContext->osData == agNULL)
    {
      TI_DBG1(("ossaHwCB: agPortContext->osData null, wrong\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'x', "Y2");
      return;
    }

    /* find a corresponding portcontext */
    onePortContext  = (tdsaPortContext_t *)agPortContext->osData;

    if (onePortContext == agNULL)
    {
      TI_DBG1(("ossaHwCB: oneportContext is NULL; wrong??????\n"));
    }
    else
    {
      TI_DBG1(("ossaHwCB: oneportContext %p pid %d\n", onePortContext, onePortContext->id));
      onePortContext->valid = agTRUE;
#ifdef INITIATOR_DRIVER
#ifdef REMOVED
      if (tdsaAllShared->ResetInDiscovery != 0)
      {
        DeviceListList = tdsaAllShared->MainDeviceList.flink;
        while (DeviceListList != &(tdsaAllShared->MainDeviceList))
        {
          oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
          if (oneDeviceData->tdPortContext != onePortContext)
          {
            DeviceListList = DeviceListList->flink;
          }
          else
          {
            found = agTRUE;
            break;
          }
        } /* while */
        if (found == agTRUE)
        {
          /* applied to only SATA devices */
          if (DEVICE_IS_SATA_DEVICE(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData))
          {
          #ifdef FDS_SM
            tdIDStart(tiRoot, agRoot, smRoot, oneDeviceData, onePortContext);
          #else
            tdssRetrySATAID(tiRoot, oneDeviceData);
          #endif
          }
        }
        else
        {
          TI_DBG1(("ossaHwCB: no onedevicedata found!\n"));
        }
      }
#endif
      /* completed TM */
      DeviceListList = tdsaAllShared->MainDeviceList.flink;
      while (DeviceListList != &(tdsaAllShared->MainDeviceList))
      {
        oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList);
        if ( oneDeviceData == agNULL)
        {
          TI_DBG1(("ossaHwCB: oneDeviceData is NULL!!!\n"));
          return;
        }

        if ( (oneDeviceData->tdPortContext == onePortContext) &&
             (oneDeviceData->directlyAttached == agTRUE) &&
             (oneDeviceData->phyID == PhyID) )
        {
          TI_DBG1(("ossaHwCB: found the onePortContext and oneDeviceData!!\n"));

          currentTaskTag = (tiIORequest_t *)oneDeviceData->agDeviceResetContext.osData;
          if (currentTaskTag != agNULL )
          {
            /* applied to only SATA devices */
            if (DEVICE_IS_SATA_DEVICE(oneDeviceData))
            {
               tdIORequestBody_t  *SMTMtdIORequestBody = agNULL;
               SMTMtdIORequestBody = (tdIORequestBody_t *)currentTaskTag->tdData;
               if (SMTMtdIORequestBody != agNULL)
               {
                 /* free the SMTMtdIORequestBody memory allocated in tiINITaskManagement function */
                 ostiFreeMemory(
                       tiRoot,
                       SMTMtdIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                       sizeof(tdIORequestBody_t)
                      );
               }
               else
               {
                 TI_DBG1(("ossaHwCB: SATA device but SMTMtdIORequestBody is NULL!!!\n"));
               }
            }
            /* set device state to DS_OPERATIONAL */
            saSetDeviceState(agRoot,
                            agNULL,
                            tdsaRotateQnumber(tiRoot, oneDeviceData),
                            oneDeviceData->agDevHandle,
                            SA_DS_OPERATIONAL
                            );
            /* notify OS layer to complete the TMF IO */
            ostiInitiatorEvent(tiRoot,
                              agNULL,
                              agNULL,
                              tiIntrEventTypeTaskManagement,
                              tiTMOK,
                              currentTaskTag
                              );

          }
          else
          {
            TI_DBG1(("ossaHwCB: currentTaskTag is NULL!!!\n"));
          }

          break;
        }
        else
        {
          DeviceListList = DeviceListList->flink;
        }
      }
#endif
    }
    break;
  }
  case OSSA_HW_EVENT_BROADCAST_ASYNCH_EVENT:
  {
    PhyID = TD_GET_PHY_ID(eventParm1);
    PortState = TD_GET_PORT_STATE(eventParm1);

    TI_DBG2(("ossaHwCB: OSSA_HW_EVENT_BROADCAST_ASYNCH_EVENT\n"));
    if (tIsSPC12SATA(agRoot))
    {
      TI_DBG1(("ossaHwCB: BROADCAST_ASYNCH_EVENT received for SATA Controller\n"));
      break;
    }
    if (agPortContext == agNULL)
    {
      TI_DBG1(("ossaHwCB: Error!!! agPortContext is NULL %d\n", PhyID));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'y', "Y2");
      return;
    }
    onePortContext = (tdsaPortContext_t *)agPortContext->osData;
    if (onePortContext == agNULL)
    {
      TI_DBG1(("ossaHwCB: Error!!! onePortContext is NULL %d\n", PhyID));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'z', "Y2");
      return;
    }

    if (onePortContext->tiPortalContext != agNULL)
    {
#if 0 
      ostiInitiatorEvent(
                         tiRoot,
                         onePortContext->tiPortalContext,
                         agNULL,
                         tiIntrEventTypeDeviceChange,
                         OSSA_HW_EVENT_BROADCAST_ASYNCH_EVENT,
                         agNULL
                         );
#endif
    }
    else
    {
      TI_DBG1(("ossaHwCB: Error!!! onePortContext->tiPortalContext is NULL\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'A', "Y2");
      return;
    }

    break;
   }

  case OSSA_HW_EVENT_PORT_RECOVER:
  {

    PhyID = TD_GET_PHY_ID(eventParm1);
    if (agPortContext == agNULL)
    {
      TI_DBG1(("ossaHwCB: Error!!! agPortContext is NULL %d\n", PhyID));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'B', "Y2");
      return;
    }

    LinkRate = TD_GET_LINK_RATE(eventParm1);
    PortState = TD_GET_PORT_STATE(eventParm1);
    agDevHandle = agNULL;
    IDframe = (agsaSASIdentify_t *)eventParm3;

    /*
      1. this is like link up
      2. handle the phyID
      3. no trigger discovery (broadcast change will do this later)
      port state must be valid
    */

    TI_DBG2(("ossaHwCB: OSSA_HW_EVENT_PORT_RECOVER, phyID %d\n", PhyID));

    if (PortState == OSSA_PORT_INVALID)
    {
      TI_DBG1(("ossaHwCB: Wrong port state\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'C', "Y2");
      return;
    }
    if ( agPortContext->osData == agNULL)
    { /* if */
      /* PortContext must exit at this point */
      TI_DBG1(("ossaHwCB: NULL portalcontext. Error. Can't be NULL\n"));
    }
    else
    {
      onePortContext  = (tdsaPortContext_t *)agPortContext->osData;
      TI_DBG2(("ossaHwCB: pid %d\n", onePortContext->id));
      onePortContext->PhyIDList[PhyID] = agTRUE;
      onePortContext->valid = agTRUE;
      tdsaAllShared->Ports[PhyID].portContext = onePortContext;
      onePortContext->tiPortalContext = tdsaAllShared->Ports[PhyID].tiPortalContext;
      onePortContext->PortRecoverPhyID = PhyID;
      if (LinkRate == 0x01)
      {
        onePortContext->LinkRate = SAS_CONNECTION_RATE_1_5G;
      }
      else if (LinkRate == 0x02)
      {
        onePortContext->LinkRate = SAS_CONNECTION_RATE_3_0G;
      }
      else if (LinkRate == 0x04)
      {
        onePortContext->LinkRate = SAS_CONNECTION_RATE_6_0G;
      }
      else /* (LinkRate == 0x08) */
      {
        onePortContext->LinkRate = SAS_CONNECTION_RATE_12_0G;
      }

      if (SA_IDFRM_GET_DEVICETTYPE(&onePortContext->sasIDframe) == SAS_END_DEVICE &&
          SA_IDFRM_IS_SSP_TARGET(&onePortContext->sasIDframe) )
      {
        TI_DBG2(("ossaHwCB: OSSA_HW_EVENT_PORT_RECOVER, sending spinup on phyID %d\n", PhyID));
        for (i=0;i<TD_MAX_NUM_NOTIFY_SPINUP;i++)
        {
          saLocalPhyControl(agRoot, agNULL, 0, PhyID, AGSA_PHY_NOTIFY_ENABLE_SPINUP, agNULL);
        }
      }

      /* transient period between link up and link down/port recovery */
      if (onePortContext->Transient == agTRUE && onePortContext->RegisteredDevNums == 0)
      {
        TI_DBG2(("ossaHwCB: OSSA_HW_EVENT_PORT_RECOVER transient period"));
        if (SA_IDFRM_GET_DEVICETTYPE(IDframe) != SAS_NO_DEVICE)
        {
#ifdef INITIATOR_DRIVER
          agSASSubID.sasAddressHi = SA_IDFRM_GET_SAS_ADDRESSHI(IDframe);
          agSASSubID.sasAddressLo = SA_IDFRM_GET_SAS_ADDRESSLO(IDframe);
          agSASSubID.initiator_ssp_stp_smp = IDframe->initiator_ssp_stp_smp;
          agSASSubID.target_ssp_stp_smp = IDframe->target_ssp_stp_smp;
          tdssAddSASToSharedcontext(
                                    onePortContext,
                                    agRoot,
                                    agDevHandle, /* agNULL */
                                    &agSASSubID,
                                    agTRUE,
                                    (bit8)PhyID,
                                    TD_OPERATION_INITIATOR
                                    );
#endif
        }
        onePortContext->Transient = agFALSE;
      }




    }
    break;
  }

  case OSSA_HW_EVENT_BROADCAST_SES:
  {
    PhyID = TD_GET_PHY_ID(eventParm1);
    PortState = TD_GET_PORT_STATE(eventParm1);

    TI_DBG2(("ossaHwCB: BROADCAST_SES  from PhyID %d; to be tested\n", PhyID));
    if (tIsSPC12SATA(agRoot))
    {
      TI_DBG1(("ossaHwCB: BROADCAST_SES received for SATA Controller\n"));
      break;
    }
    if (PortState == OSSA_PORT_INVALID)
    {
      TI_DBG1(("ossaHwCB: Wrong port state with  BROADCAST_SES\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'D', "Y2");
      return;
    }

    /*
       let os layer read payload
    */
    break;
  }
  case OSSA_HW_EVENT_BROADCAST_EXP:
  {
    PhyID = TD_GET_PHY_ID(eventParm1);
    PortState = TD_GET_PORT_STATE(eventParm1);

    TI_DBG2(("ossaHwCB: BROADCAST_EXP from PhyID %d; to be tested\n", PhyID));
    if (tIsSPC12SATA(agRoot))
    {
      TI_DBG1(("ossaHwCB: BROADCAST_EXP received for SATA Controller\n"));
      break;
    }

    if (PortState == OSSA_PORT_INVALID)
    {
      TI_DBG1(("ossaHwCB: Wrong port state with  BROADCAST_EXP\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'E', "Y2");
      return;
    }
    /* to-do:
       let os layer read payload
    */
    break;
  }

  case OSSA_HW_EVENT_HARD_RESET_RECEIVED:
  {
    PhyID = TD_GET_PHY_ID(eventParm1);
    PortState = TD_GET_PORT_STATE(eventParm1);

    TI_DBG2(("ossaHwCB: HARD_RESET_RECEIVED from PhyID %d\n", PhyID));

    if (PortState == OSSA_PORT_VALID && tiIS_SPC(agRoot))
    {
      TI_DBG1(("ossaHwCB: calling saPortControl and OSSA_PORT_VALID\n"));
      saPortControl(agRoot, agNULL, 0, agPortContext, AGSA_PORT_HARD_RESET, 0,0);
    }
    else if (PortState == OSSA_PORT_3RDPARTY_RESET && (tIsSPCV12or6G(agRoot))  )
    {
      TI_DBG1(("ossaHwCB: calling saPortControl and OSSA_PORT_3RDPARTY_RESET\n"));
      saPortControl(agRoot, agNULL, 0, agPortContext, AGSA_PORT_HARD_RESET, 0,0);
    }
    else /* PortState == OSSA_PORT_INVALID */
    {
      TI_DBG1(("ossaHwCB: Error. Port state is invalid\n"));
#ifdef REMOVED
      TI_DBG1(("ossaHwCB: calling saLocalPhyControl on phyID %d\n", PhyID));
      saLocalPhyControl(agRoot, agNULL, 0, PhyID, AGSA_PHY_LINK_RESET, agNULL);
#endif
    }

    break;
  }

  case OSSA_HW_EVENT_MALFUNCTION:
  {
#ifdef TD_DEBUG_ENABLE
    agsaFatalErrorInfo_t  *FatalError = (agsaFatalErrorInfo_t *)eventParm2;
#endif
    TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_MALFUNCTION \n"));
    TI_DBG1(("ossaHwCB: errorInfo0 %8X errorInfo1 %8X\n", FatalError->errorInfo0, FatalError->errorInfo1));
    TI_DBG1(("ossaHwCB: errorInfo2 %8X errorInfo3 %8X\n", FatalError->errorInfo2, FatalError->errorInfo3));
    TI_DBG1(("ossaHwCB: regDumpBusBaseNum0 %8X regDumpOffset0 %8X regDumpLen0 %8X\n", FatalError->regDumpBusBaseNum0, FatalError->regDumpOffset0, FatalError->regDumpLen0));
    TI_DBG1(("ossaHwCB: regDumpBusBaseNum1 %8X regDumpOffset1 %8X regDumpLen1 %8X\n", FatalError->regDumpBusBaseNum1, FatalError->regDumpOffset1, FatalError->regDumpLen1));


    if (eventParm1 == agTRUE)
    {
      TI_DBG1(("ossaHwCB: fatal error\n"));
      /* port panic */
      ostiPortEvent (
                     tiRoot,
                     tiPortPanic,
                     0,
                     agNULL
                     );
    }
    else
    {
      TI_DBG1(("ossaHwCB: non-fatal error \n"));
    }
    break;
  }

  case OSSA_HW_EVENT_ID_FRAME_TIMEOUT:
  {
    PhyID = TD_GET_PHY_ID(eventParm1);
    PortState = TD_GET_PORT_STATE(eventParm1);

    TI_DBG2(("ossaHwCB: OSSA_HW_EVENT_ID_FRAME_TIMEOUT from PhyID %d\n", PhyID));

    if (PortState == OSSA_PORT_INVALID)
    {
      TI_DBG1(("ossaHwCB: Wrong port state with  OSSA_HW_EVENT_ID_FRAME_TIMEOUT\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'F', "Y2");
      return;
    }
    break;
  }

  case OSSA_HW_EVENT_PHY_ERR_INVALID_DWORD:
  {
    PhyID = TD_GET_PHY_ID(eventParm1);
    PortState = TD_GET_PORT_STATE(eventParm1);
    agPhyErrCountersPage = (agsaPhyErrCountersPage_t *)eventParm2;
    TI_DBG2(("ossaHwCB: OSSA_HW_EVENT_PHY_ERR_INVALID_DWORD\n"));

    if (PortState == OSSA_PORT_INVALID)
    {
      TI_DBG1(("ossaHwCB: Wrong port state with  OSSA_HW_EVENT_PHY_ERR_INVALID_DWORD\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'G', "Y2");
      return;
    }

    if (agPhyErrCountersPage != agNULL)
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_PHY_ERR_INVALID_DWORD from PhyID %d\n", PhyID));
      TI_DBG1(("ossaHwCB: invalidDword %d\n", agPhyErrCountersPage->invalidDword));
    }
    else
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_PHY_ERR_INVALID_DWORD: Error!!!  eventParm2 is NULL\n"));
    }

    /* saHwEventAck() */
    eventSource.agPortContext = agPortContext;
    eventSource.event = OSSA_HW_EVENT_PHY_ERR_INVALID_DWORD;
    /* phy ID */
    eventSource.param = PhyID;
    HwAckSatus = saHwEventAck(
                              agRoot,
                              agNULL, /* agContext */
                              0,
                              &eventSource, /* agsaEventSource_t */
                              0,
                              0
                              );
    if ( HwAckSatus != AGSA_RC_SUCCESS)
    {
      TI_DBG1(("ossaHwCB: failing in saHwEventAck; status %d\n", HwAckSatus));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'H', "Y2");
      return;
    }

    break;
  }

  case OSSA_HW_EVENT_PHY_ERR_DISPARITY_ERROR:
  {
    PhyID = TD_GET_PHY_ID(eventParm1);
    PortState = TD_GET_PORT_STATE(eventParm1);
    agPhyErrCountersPage = (agsaPhyErrCountersPage_t *)eventParm2;
    TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_PHY_ERR_DISPARITY_ERROR\n"));

    if (PortState == OSSA_PORT_INVALID)
    {
      TI_DBG1(("ossaHwCB: Wrong port state with  OSSA_HW_EVENT_PHY_ERR_DISPARITY_ERROR\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'I', "Y2");
      return;
    }

    if (agPhyErrCountersPage != agNULL)
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_PHY_ERR_DISPARITY_ERROR from PhyID %d\n", PhyID));
      TI_DBG1(("ossaHwCB: runningDisparityError %d\n", agPhyErrCountersPage->runningDisparityError));
    }
    else
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_PHY_ERR_DISPARITY_ERROR: Error!!!  eventParm2 is NULL\n"));
    }

    /* saHwEventAck() */
    eventSource.agPortContext = agPortContext;
    eventSource.event = OSSA_HW_EVENT_PHY_ERR_DISPARITY_ERROR;
    /* phy ID */
    eventSource.param = PhyID;
    HwAckSatus = saHwEventAck(
                              agRoot,
                              agNULL, /* agContext */
                              0,
                              &eventSource, /* agsaEventSource_t */
                              0,
                              0
                              );
    if ( HwAckSatus != AGSA_RC_SUCCESS)
    {
      TI_DBG1(("ossaHwCB: failing in saHwEventAck; status %d\n", HwAckSatus));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'J', "Y2");
      return;
    }

    break;
  }

  case OSSA_HW_EVENT_PHY_ERR_CODE_VIOLATION:
  {
    PhyID = TD_GET_PHY_ID(eventParm1);
    PortState = TD_GET_PORT_STATE(eventParm1);
    agPhyErrCountersPage = (agsaPhyErrCountersPage_t *)eventParm2;
    TI_DBG2(("ossaHwCB: OSSA_HW_EVENT_PHY_ERR_CODE_VIOLATION\n"));

    if (PortState == OSSA_PORT_INVALID)
    {
      TI_DBG1(("ossaHwCB: Wrong port state with  OSSA_HW_EVENT_PHY_ERR_CODE_VIOLATION\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'K', "Y2");
      return;
    }

    if (agPhyErrCountersPage != agNULL)
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_PHY_ERR_CODE_VIOLATION from PhyID %d\n", PhyID));
      TI_DBG1(("ossaHwCB: codeViolation %d\n", agPhyErrCountersPage->codeViolation));
    }
    else
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_PHY_ERR_CODE_VIOLATION: Error!!!  eventParm2 is NULL\n"));
    }

    /* saHwEventAck() */
    eventSource.agPortContext = agPortContext;
    eventSource.event = OSSA_HW_EVENT_PHY_ERR_CODE_VIOLATION;
    /* phy ID */
    eventSource.param = PhyID;
    HwAckSatus = saHwEventAck(
                              agRoot,
                              agNULL, /* agContext */
                              0,
                              &eventSource, /* agsaEventSource_t */
                              0,
                              0
                              );
    if ( HwAckSatus != AGSA_RC_SUCCESS)
    {
      TI_DBG1(("ossaHwCB: failing in saHwEventAck; status %d\n", HwAckSatus));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'L', "Y2");
      return;
    }

    break;
  }

#ifdef REMOVED
  case OSSA_HW_EVENT_LINK_ERR_CODE_VIOLATION1:
  {
    PhyID = eventParm1 & 0xFF;
    agPhyErrCountersPage = (agsaPhyErrCountersPage_t *)eventParm2;

    if (agPhyErrCountersPage != agNULL)
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_LINK_ERR_CODE_VIOLATION1 from PhyID %d\n", PhyID));
      TI_DBG1(("ossaHwCB: invalidDword %d\n", agPhyErrCountersPage->invalidDword));
      TI_DBG1(("ossaHwCB: runningDisparityError %d\n", agPhyErrCountersPage->runningDisparityError));
      TI_DBG1(("ossaHwCB: codeViolation %d\n", agPhyErrCountersPage->codeViolation));
      TI_DBG1(("ossaHwCB: lostOfDwordSynch %d\n", agPhyErrCountersPage->lossOfDwordSynch));
      TI_DBG1(("ossaHwCB: phyResetProblem %d\n", agPhyErrCountersPage->phyResetProblem));
      TI_DBG1(("ossaHwCB: inboundCRCError %d\n", agPhyErrCountersPage->inboundCRCError));
    }
    else
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_LINK_ERR_CODE_VIOLATION1: Error!!!  eventParm2 is NULL\n"));
    }
    break;
  }
#endif /* REMOVED */

  case OSSA_HW_EVENT_PHY_ERR_LOSS_OF_DWORD_SYNCH:
  {
    PhyID = TD_GET_PHY_ID(eventParm1);
    PortState = TD_GET_PORT_STATE(eventParm1);
    agPhyErrCountersPage = (agsaPhyErrCountersPage_t *)eventParm2;
    TI_DBG2(("ossaHwCB: OSSA_HW_EVENT_PHY_ERR_LOSS_OF_DWORD_SYNCH\n"));

    if (PortState == OSSA_PORT_INVALID)
    {
      TI_DBG1(("ossaHwCB: Wrong port state with  OSSA_HW_EVENT_PHY_ERR_LOSS_OF_DWORD_SYNCH\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'M', "Y2");
      return;
    }

    if (agPhyErrCountersPage != agNULL)
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_PHY_ERR_LOSS_OF_DWORD_SYNCH from PhyID %d\n", PhyID));
      TI_DBG1(("ossaHwCB: lostOfDwordSynch %d\n", agPhyErrCountersPage->lossOfDwordSynch));
    }
    else
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_PHY_ERR_LOSS_OF_DWORD_SYNCH: Error!!!  eventParm2 is NULL\n"));
    }

    /* saHwEventAck() */
    eventSource.agPortContext = agPortContext;
    eventSource.event = OSSA_HW_EVENT_PHY_ERR_LOSS_OF_DWORD_SYNCH;
    /* phy ID */
    eventSource.param = PhyID;
    HwAckSatus = saHwEventAck(
                              agRoot,
                              agNULL, /* agContext */
                              0,
                              &eventSource, /* agsaEventSource_t */
                              0,
                              0
                              );
    if ( HwAckSatus != AGSA_RC_SUCCESS)
    {
      TI_DBG1(("ossaHwCB: failing in saHwEventAck; status %d\n", HwAckSatus));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'N', "Y2");
      return;
    }

    break;
  }

  case OSSA_HW_EVENT_PHY_ERR_PHY_RESET_FAILED:
  {
    PhyID = TD_GET_PHY_ID(eventParm1);
    PortState = TD_GET_PORT_STATE(eventParm1);
    agPhyErrCountersPage = (agsaPhyErrCountersPage_t *)eventParm2;

    TI_DBG2(("ossaHwCB: OSSA_HW_EVENT_PHY_ERR_PHY_RESET_FAILED\n"));

    if (PortState == OSSA_PORT_INVALID)
    {
      TI_DBG1(("ossaHwCB: Wrong port state with  OSSA_HW_EVENT_PHY_ERR_PHY_RESET_FAILED\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'O', "Y2");
      return;
    }

    if (agPhyErrCountersPage != agNULL)
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_PHY_ERR_PHY_RESET_FAILED from PhyID %d\n", PhyID));
      TI_DBG1(("ossaHwCB: phyResetProblem %d\n", agPhyErrCountersPage->phyResetProblem));
    }
    else
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_PHY_ERR_PHY_RESET_FAILED: Error!!!  eventParm2 is NULL\n"));
    }

    /* saHwEventAck() */
    eventSource.agPortContext = agPortContext;
    eventSource.event = OSSA_HW_EVENT_PHY_ERR_PHY_RESET_FAILED;
    /* phy ID */
    eventSource.param = PhyID;
    HwAckSatus = saHwEventAck(
                              agRoot,
                              agNULL, /* agContext */
                              0,
                              &eventSource, /* agsaEventSource_t */
                              0,
                              0
                              );
    if ( HwAckSatus != AGSA_RC_SUCCESS)
    {
      TI_DBG1(("ossaHwCB: failing in saHwEventAck; status %d\n", HwAckSatus));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'P', "Y2");
      return;
    }

    break;
  }

// #ifdef INITIATOR_DRIVER
  case OSSA_HW_EVENT_ENCRYPTION:
  {
    pEncryptCBData = (agsaHWEventEncrypt_t *) eventParm2;
    TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_ENCRYPTION: encryptOperation 0x%x\n",pEncryptCBData->encryptOperation));
    TI_DBG1(("ossaHwCB: event 0x%x eventParm1 0x%x eventParm2 %p eventParm3 %p\n",event,eventParm1,eventParm2,eventParm3));

    /*
     * All events and status need to be translated from
     * SAS specific values to TISA specific values. This
     * is effectively a NOP, but the OS layer won't want to
     * look for SAS values.
     */
    if (pEncryptCBData->encryptOperation == OSSA_HW_ENCRYPT_KEK_UPDATE_AND_STORE)
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_ENCRYPT_KEK_UPDATE_AND_STORE\n"));
      encryptEventData.encryptEvent = tiEncryptKekStore;
    }
    else if (pEncryptCBData->encryptOperation == OSSA_HW_ENCRYPT_KEK_UPDATE)
    {
      TI_DBG1(("ossaHwCB:OSSA_HW_ENCRYPT_KEK_UPDATE \n"));
      encryptEventData.encryptEvent = tiEncryptKekAdd;
    }
    else if (pEncryptCBData->encryptOperation == OSSA_HW_ENCRYPT_KEK_INVALIDTE)
    {
      TI_DBG1(("ossaHwCB:OSSA_HW_ENCRYPT_KEK_INVALIDTE \n"));
      /* none */
    }
    else if (pEncryptCBData->encryptOperation == OSSA_HW_ENCRYPT_DEK_UPDATE)
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_ENCRYPT_DEK_UPDATE\n"));
      encryptEventData.encryptEvent = tiEncryptDekAdd;
    }
    else if (pEncryptCBData->encryptOperation == OSSA_HW_ENCRYPT_DEK_INVALIDTE)
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_ENCRYPT_DEK_INVALIDTE\n"));
      encryptEventData.encryptEvent = tiEncryptDekInvalidate;
    }
    else if (pEncryptCBData->encryptOperation == OSSA_HW_ENCRYPT_OPERATOR_MANAGEMENT)
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_ENCRYPT_OPERATOR_MANAGEMENT\n"));
      encryptEventData.encryptEvent = tiEncryptOperatorManagement;
    }
    else if (pEncryptCBData->encryptOperation == OSSA_HW_ENCRYPT_TEST_EXECUTE)
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_ENCRYPT_TEST_EXECUTE\n"));
      encryptEventData.encryptEvent = tiEncryptSelfTest;
      encryptEventData.subEvent = pEncryptCBData->eq;
    }
    else
    {
      TI_DBG1(("ossaHwCB: unknown encryptOperation 0x%x\n",pEncryptCBData->encryptOperation));
    }

    if (pEncryptCBData->status != OSSA_SUCCESS)
    {
      encryptStatus = tiError;

      /* prints out status and error qualifier */
      TI_DBG1(("ossaHwCB: encrypt response status 0x%x error qualifier 0x%x\n", pEncryptCBData->status, pEncryptCBData->eq));
    }
    else
    {
      encryptStatus = tiSuccess;
    }

    if (pEncryptCBData->encryptOperation == OSSA_HW_ENCRYPT_KEK_UPDATE_AND_STORE ||
        pEncryptCBData->encryptOperation == OSSA_HW_ENCRYPT_KEK_UPDATE )
    {
      /* returning new KEK index */
      encryptEventData.pData = pEncryptCBData->handle;
    }
    else
    {
      /* returning current KEK index or DEK index */
      encryptEventData.pData = pEncryptCBData->param;
    }

    ostiPortEvent(tiRoot,
                  tiEncryptOperation,
                  encryptStatus,
                  &encryptEventData);
    break;
  }
  case OSSA_HW_EVENT_SECURITY_MODE:
  {
    securitySetModeStatus = eventParm1;
    pEncryptInfo = (agsaEncryptInfo_t *) eventParm2;

    TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_SECURITY_MODE\n"));
    if (securitySetModeStatus == OSSA_SUCCESS)
    {
      securityModeStatus = tiSuccess;
    }
    else
    {
      securityModeStatus = tiError;
    }

    encryptEventData.encryptEvent = tiEncryptSetMode;
    /* process status to fill in subevent */
    /* See PM 4.26.12.6 */
    TI_DBG1(("ossaHwCB: pEncryptInfo->status 0x%x\n", pEncryptInfo->status));
    if ( pEncryptInfo->status == OSSA_SUCCESS)
    {
      encryptEventData.subEvent = tiNVRAMSuccess;
    }
    else if (pEncryptInfo->status == 0x24)
    {
      encryptEventData.subEvent = tiNVRAMNotFound;
    }
    else if (pEncryptInfo->status == 0x05 || pEncryptInfo->status == 0x20 || pEncryptInfo->status == 0x21)
    {
      encryptEventData.subEvent = tiNVRAMAccessTimeout;
    }
    else
    {
      encryptEventData.subEvent = tiNVRAMWriteFail;
    }

    encryptEventData.pData = agNULL;
    ostiPortEvent(tiRoot,
                  tiEncryptOperation,
                  securityModeStatus,
                  &encryptEventData);

    break;
  }
  case OSSA_HW_EVENT_MODE:
  {
    pModeEvent = (agsaHWEventMode_t *) eventParm2;
    pModePage = (bit32 *) pModeEvent->modePage;

    TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_MODE modePageOperation 0x%x status 0x%x modePageLen 0x%x\n",
              pModeEvent->modePageOperation, pModeEvent->status, pModeEvent->modePageLen));

    if (pModeEvent->modePageOperation == agsaModePageSet)
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_MODE page code 0x%x error qualifier 0x%x\n", (eventParm1 & 0xFF), (eventParm1 >> 16)));
      ostiPortEvent(tiRoot,
                    tiModePageOperation,
                    pModeEvent->status,
                    eventParm2);
    }
    else if (pModeEvent->modePageOperation == agsaModePageGet)
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_MODE error qualifier 0x%x\n", eventParm1));
      switch ((*pModePage) & 0xFF)
      {
      case AGSA_ENCRYPTION_GENERAL_CONFIG_PAGE:
        TI_DBG1(("ossaHwCB: AGSA_ENCRYPTION_GENERAL_CONFIG_PAGE 0x%x %p\n", pModeEvent->status,eventParm2));
        TI_DBG1(("ossaHwCB:modePageOperation 0x%x status 0x%x modePageLen 0x%x modePage %p context %p\n",
                      pModeEvent->modePageOperation,
                      pModeEvent->status,
                      pModeEvent->modePageLen,
                      pModeEvent->modePage,
                      pModeEvent->context));
        ostiPortEvent(tiRoot,
                      tiModePageOperation,
                      pModeEvent->status,
                      eventParm2);
        break;
      case AGSA_ENCRYPTION_DEK_CONFIG_PAGE:
        TI_DBG1(("ossaHwCB: AGSA_ENCRYPTION_DEK_CONFIG_PAGE 0x%x %p\n", pModeEvent->status,eventParm2));
        ostiPortEvent(tiRoot,
                      tiModePageOperation,
                      pModeEvent->status,
                      eventParm2);
        break;
      case AGSA_ENCRYPTION_HMAC_CONFIG_PAGE:
        TI_DBG1(("ossaHwCB: AGSA_ENCRYPTION_HMAC_CONFIG_PAGE 0x%x %p\n", pModeEvent->status,eventParm2));
        ostiPortEvent(tiRoot,
                      tiModePageOperation,
                      pModeEvent->status,
                      eventParm2);
        break;
      case AGSA_ENCRYPTION_CONTROL_PARM_PAGE:
        TI_DBG1(("ossaHwCB: AGSA_ENCRYPTION_CONTROL_PARM_PAGE 0x%x %p\n", pModeEvent->status,eventParm2));
        /*
         * This page is directly related to tiCOMEncryptGetInfo() and
         * will be translated into a tiEncrytOperation for the OS layer.
         */

        /* Fill out tiEncryptInfo_t */
        securityMode = *pModePage & 0x0F00 >> 8;
        cipherMode = *pModePage & 0xF000 >> 12;

        if (securityMode == agsaEncryptSMA)
        {
          encryptInfo.securityCipherMode = TI_ENCRYPT_SEC_MODE_A;
        }
        else if (securityMode == agsaEncryptSMB)
        {
          encryptInfo.securityCipherMode = TI_ENCRYPT_SEC_MODE_B;
        }
        else
        {
          encryptInfo.securityCipherMode = TI_ENCRYPT_SEC_MODE_FACT_INIT;
        }

        if (cipherMode == agsaEncryptCipherModeECB)
        {
          encryptInfo.securityCipherMode |= TI_ENCRYPT_ATTRIB_CIPHER_ECB;
        }

        if (cipherMode == agsaEncryptCipherModeXTS)
        {
          encryptInfo.securityCipherMode |= TI_ENCRYPT_ATTRIB_CIPHER_XTS;
        }

        /* How will subEvents be tracked? */
        encryptInfo.status = 0;

        encryptInfo.sectorSize[0] = 512;  /* DIF is allowed on 512 BPS SATA drives */
        encryptInfo.sectorSize[1] = 520;
        encryptInfo.sectorSize[2] = 528;
        encryptInfo.sectorSize[3] = 4104;
        encryptInfo.sectorSize[4] = 4168;
        encryptInfo.sectorSize[5] = 4232;

        encryptEventData.encryptEvent = tiEncryptGetInfo;
        encryptEventData.subEvent = 0;
        encryptEventData.pData = &encryptInfo;

        ostiPortEvent(tiRoot,
                    tiEncryptOperation,
                    pModeEvent->status,
                    &encryptEventData);
        break;
      case AGSA_SAS_PROTOCOL_TIMER_CONFIG_PAGE:
        TI_DBG1(("ossaHwCB: AGSA_SAS_PROTOCOL_TIMER_CONFIG_PAGE 0x%x %p\n", pModeEvent->status,eventParm2));

#ifdef IOCTL_INTERRUPT_TIME_CONFIG
         ostiPortEvent(tiRoot,
                    tiModePageOperation,
                    pModeEvent->status,
                    eventParm2
                 );
#endif /* IOCTL_INTERRUPT_TIME_CONFIG */

        /*ostiPortEvent(tiRoot,
                    tiModePageOperation,
                    pModeEvent->status,
                    &encryptEventData);*/
        break;
      case AGSA_INTERRUPT_CONFIGURATION_PAGE:
        TI_DBG1(("ossaHwCB: AGSA_INTERRUPT_CONFIGURATION_PAGE 0x%x %p\n", pModeEvent->status,eventParm2));

#ifdef IOCTL_INTERRUPT_TIME_CONFIG
        ostiPortEvent(tiRoot,
                    tiModePageOperation,
                    pModeEvent->status,
                    eventParm2
                    );
#endif /* IOCTL_INTERRUPT_TIME_CONFIG */

        break;
      default:
        TI_DBG1(("ossaHwCB: Unknown Mode Event %x\n", *pModePage));
         break;
      }

    }
    else
    {
      TI_DBG1(("ossaHwCB: Unknown modePageOperation %x\n", pModeEvent->modePageOperation));
    }
    break;
  }

// #endif  /* INITIATOR_DRIVER */

#ifdef REMOVED
  case OSSA_HW_EVENT_PHY_UNRECOVERABLE_ERROR:
  {
    PhyID = TD_GET_PHY_ID(eventParm1);
    PortState = TD_GET_PORT_STATE(eventParm1);

    TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_PHY_UNRECOVERABLE_ERROR\n"));

    if (PortState == OSSA_PORT_INVALID)
    {
      TI_DBG1(("ossaHwCB: INVALID port state\n"));
    }
    else
    {
      TI_DBG1(("ossaHwCB: VALID port state\n"));
    }
    break;
  }
#endif /* REMOVED */
    case OSSA_HW_EVENT_OPEN_RETRY_BACKOFF_THR_ADJUSTED:
    {
      TI_DBG1(("ossaHwCB: OSSA_HW_EVENT_OPEN_RETRY_BACKOFF_THR_ADJUSTED\n"));
      break;
    }

    default:
    {
      TI_DBG1(("ossaHwCB: default error (0x%X)!!!!!\n",event));
      break;
    }
  }

  smTraceFuncExit(hpDBG_VERY_LOUD, 'R', "Y2");
  return;
}

osGLOBAL void ossaPortControlCB(
                  agsaRoot_t          *agRoot,
                  agsaContext_t       *agContext,
                  agsaPortContext_t   *agPortContext,
                  bit32               portOperation,
                  bit32               status)
{
  tdsaRootOsData_t    *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t            *tiRoot = (tiRoot_t *)osData->tiRoot;
  tdsaPortContext_t   *onePortContext = agNULL;

  TI_DBG6(("ossaPortControlCB: start\n"));

  smTraceFuncEnter(hpDBG_VERY_LOUD,"Y3");
  if (portOperation == AGSA_PORT_SET_SMP_PHY_WIDTH)
  {
    TI_DBG1(("ossaPortControlCB: portOperation AGSA_PORT_SET_SMP_PHY_WIDTH\n"));
  }
  else if (portOperation == AGSA_PORT_SET_PORT_RECOVERY_TIME)
  {
    TI_DBG1(("ossaPortControlCB: portOperation AGSA_PORT_SET_PORT_RECOVERY_TIME\n"));
  }
  else if (portOperation == AGSA_PORT_IO_ABORT)
  {
    TI_DBG1(("ossaPortControlCB: portOperation AGSA_PORT_IO_ABORT\n"));
    /* code is here because disocvery failed
       deregister all targets. Then, later call discovery if broacast is seen in ossaDeregisterDeviceHandleCB.
    */
    onePortContext = (tdsaPortContext_t *)agPortContext->osData;
    if (onePortContext == agNULL)
    {
      TI_DBG1(("ossaPortControlCB: onePortContext is NULL\n"));
      return;
    }
    /* qqqqq deregister all devices */
   tdsaDeregisterDevicesInPort(tiRoot, onePortContext);

  }
  else if (portOperation == AGSA_PORT_SET_PORT_RESET_TIME)
  {
    TI_DBG1(("ossaPortControlCB: portOperation AGSA_PORT_SET_PORT_RESET_TIME\n"));
  }
  else if (portOperation == AGSA_PORT_HARD_RESET)
  {
    TI_DBG1(("ossaPortControlCB: portOperation AGSA_PORT_HARD_RESET\n"));
  }
  else if (portOperation == AGSA_PORT_CLEAN_UP)
  {
    TI_DBG1(("ossaPortControlCB: portOperation AGSA_PORT_CLEAN_UP\n"));
  }
  else if (portOperation == AGSA_STOP_PORT_RECOVERY_TIMER)
  {
    TI_DBG1(("ossaPortControlCB: portOperation AGSA_STOP_PORT_RECOVERY_TIMER\n"));
  }
  else
  {
    TI_DBG1(("ossaPortControlCB: undefined portOperation %d\n", portOperation));
  }

  TI_DBG1(("ossaPortControlCB: status %d\n", status));

  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Y3");
  return;
}

/*****************************************************************************
*! \brief  ossaHwRegRead
*
*  Purpose: This routine is called to read a 32-bit value from the PCI
*           registers of the controller
*
*  \param  agRoot:       Pointer to chip/driver Instance.
*  \param  regOffset:    Byte offset to chip register from which to read a 32-bit
*                        value.
*
*  \return:             32-bit value.
*
*  \note - The scope is shared target and initiator.
*
*****************************************************************************/
FORCEINLINE
bit32
ossaHwRegRead(agsaRoot_t *agRoot,
              bit32      regOffset
              )
{
  tdsaRootOsData_t *osData = (tdsaRootOsData_t *) (agRoot->osData);
  bit32 return_value;


  return_value =  ostiChipReadBit32 (
                             osData->tiRoot,
                             regOffset
                             );
  if( agNULL != agRoot->sdkData )
  {
    smTrace(hpDBG_REGISTERS,"RR",regOffset);
    /* TP:RR regOffset */
    smTrace(hpDBG_REGISTERS,"RV",return_value);
    /* TP:RV value read */
  }

  return(return_value);

}

/*****************************************************************************
*! \brief  ossaHwRegWrite
*
*  Purpose: This routine is called to write a 32-bit value to the PCI
*           registers of the controller.
*
*  \param   agRoot:     Pointer to chip/driver Instance.
*  \param   regOffset:  Byte offset to chip register to which chipIOValue is
*                       written.
*  \param   regValue:   32-bit value to write at chipIOOffset in host byte order.
*
*  \return:             None.
*
*  \note - The scope is shared target and initiator.
*
*****************************************************************************/
FORCEINLINE
void
ossaHwRegWrite(agsaRoot_t *agRoot,
               bit32      regOffset,
               bit32      regValue
               )
{

  tdsaRootOsData_t *osData = (tdsaRootOsData_t *) (agRoot->osData);
  if( agNULL != agRoot->sdkData )
  {
    smTrace(hpDBG_REGISTERS,"RW",regOffset);
    /* TP:RW regOffset */
    smTrace(hpDBG_REGISTERS,"VW",regValue);
    /* TP:VW value written */
  }

  ostiChipWriteBit32 (
                      osData->tiRoot,
                      regOffset,
                      regValue
                      );
  return;
}

/*****************************************************************************
*! \brief  ossaHwRegReadExt
*
*  Purpose: This routine is called to read a 32-bit value from a bus-specific
*           mapped registers of the controller
*
*  \param  agRoot:       Pointer to chip/driver Instance.
*  \param  regOffset:    Byte offset to chip register from which to read a 32-bit
*                        value.
*
*  \return:             32-bit value.
*
*  \note - The scope is shared target and initiator.
*
*****************************************************************************/
FORCEINLINE
bit32
ossaHwRegReadExt(
                 agsaRoot_t  *agRoot,
                 bit32       busBaseNumber,
                 bit32       regOffset
                 )
{
  tdsaRootOsData_t *osData = (tdsaRootOsData_t *) (agRoot->osData);

  bit32 return_value;

  return_value = ostiChipReadBit32Ext(
                               osData->tiRoot,
                               busBaseNumber,
                               regOffset
                               );

  /* TI_DBG4(("#_R: 0x%x:0x%x=0x%x\n",busBaseNumber,regOffset,return_value)); */

  if( agNULL != agRoot->sdkData )
  {
    smTrace(hpDBG_REGISTERS,"EB",busBaseNumber);
    /* TP:EB EX read busBaseNumber */
    smTrace(hpDBG_REGISTERS,"EO",regOffset);
    /* TP:EO regOffset */
    smTrace(hpDBG_REGISTERS,"ER",return_value);
    /* TP:ER value read */
  }
  return(return_value);
}

void ossaPCI_TRIGGER(agsaRoot_t  *agRoot )
{
  tdsaRootOsData_t *osData = (tdsaRootOsData_t *) (agRoot->osData);
  ostiPCI_TRIGGER(osData->tiRoot);

}



/*****************************************************************************
*! \brief  ossaHwRegWriteExt
*
*  Purpose: This routine is called to write a 32-bit value to a bus specific
*           mapped registers of the controller.
*
*  \param   agRoot:     Pointer to chip/driver Instance.
*  \param   regOffset:  Byte offset to chip register to which chipIOValue is
*                       written.
*  \param   regValue:   32-bit value to write at chipIOOffset in host byte order.
*
*  \return:             None.
*
*  \note - The scope is shared target and initiator.
*
*****************************************************************************/
FORCEINLINE
void
ossaHwRegWriteExt(
                  agsaRoot_t  *agRoot,
                  bit32       busBaseNumber,
                  bit32       regOffset,
                  bit32       regValue
                  )
{
  tdsaRootOsData_t *osData = (tdsaRootOsData_t *) (agRoot->osData);
  ostiChipWriteBit32Ext(
                        osData->tiRoot,
                        busBaseNumber,
                        regOffset,
                        regValue
                        );

  /*  TI_DBG4(("#_W: 0x%x:0x%x=0x%x\n",busBaseNumber,regOffset,regValue)); */

  if( agNULL != agRoot->sdkData )
  {
    smTrace(hpDBG_REGISTERS,"Eb",busBaseNumber);
    /* TP:Eb Ex Write busBaseNumber */
    smTrace(hpDBG_REGISTERS,"Eo",regOffset);
    /* TP:Eo regOffset */
    smTrace(hpDBG_REGISTERS,"Ew",regValue);
    /* TP:Ew value written  regValue*/
  }
  return;
}


osGLOBAL bit32 ossaHwRegReadConfig32(
              agsaRoot_t  *agRoot,
              bit32       regOffset
              )
{
  tdsaRootOsData_t *osData = (tdsaRootOsData_t *) (agRoot->osData);
  bit32 to_ret;
  to_ret= ostiChipConfigReadBit32( osData->tiRoot, regOffset);
  TI_DBG4(("ossaHwRegReadConfig32: regOffset 0x%x returns 0x%x\n",regOffset,to_ret));
  return(to_ret);
}




#ifdef TD_INT_COALESCE
void
ossaIntCoalesceInitCB(
                      agsaRoot_t                *agRoot,
                      agsaIntCoalesceContext_t    *agIntCoContext,
                      bit32                   status
                      )
{
  tdsaRootOsData_t          *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t                  *tiRoot = (tiRoot_t *)osData->tiRoot;
  tdsaContext_t             *tdsaAllShared = (tdsaContext_t *)osData->tdsaAllShared;
  tiIntCoalesceContext_t    *tiIntCoalesceCxt;
  tdsaIntCoalesceContext_t  *tdsaIntCoalCxt;
  tdsaIntCoalesceContext_t  *tdsaIntCoalCxtHead
    = (tdsaIntCoalesceContext_t *)tdsaAllShared->IntCoalesce;
  bit32                     tiStatus;

  TI_DBG2(("ossaIntCoalesceInitCB: start\n"));

  tdsaIntCoalCxt = (tdsaIntCoalesceContext_t *)agIntCoContext->osData;
  tiIntCoalesceCxt = tdsaIntCoalCxt->tiIntCoalesceCxt;
  switch (status)
  {
  case AGSA_RC_SUCCESS:
    tiStatus = tiSuccess;
    break;
  case AGSA_RC_BUSY:
    tiStatus = tiBusy;
    break;
  case AGSA_RC_FAILURE:
    tiStatus = tiError;
    break;
  default:
    TI_DBG1(("ossaIntCoalesceInitCB: unknown status %d\n", status));
    tiStatus = tiError;
    break;
  }

  TI_DBG2(("ossaIntCoalesceInitCB: status %d\n", tiStatus));

  /* enqueue tdsaIntCoalCxt to freelink */
  tdsaIntCoalCxt->tiIntCoalesceCxt = agNULL;
  TI_DBG2(("ossaIntCoalesceInitCB: id %d\n", tdsaIntCoalCxt->id));

  tdsaSingleThreadedEnter(tiRoot, TD_INTCOAL_LOCK);
  TDLIST_DEQUEUE_THIS(&(tdsaIntCoalCxt->MainLink));
  TDLIST_ENQUEUE_AT_TAIL(&(tdsaIntCoalCxt->FreeLink), &(tdsaIntCoalCxtHead->FreeLink));
  tdsaSingleThreadedLeave(tiRoot, TD_INTCOAL_LOCK);

#ifdef OS_INT_COALESCE
  ostiInitiatorIntCoalesceInitCB(tiRoot,
                                 tiIntCoalesceCxt,
                                 tiStatus);
#endif

  TI_DBG2(("ossaIntCoalesceInitCB: return end\n"));

  return;
}
#endif /* TD_INT_COALESCE */

/*****************************************************************************/
/*! \brief ossaSingleThreadedEnter
 *
 *
 * Purpose: This routine is called to ensure that only a single thread of
 *          the given port instance executes code in the region protected by
 *          this function.
 *
 *
 *  \param   agRoot:       Pointer to chip/driver Instance.
 *  \param   syncLockId    to be explained.
 *
 *
 *  \return None.
 *
 *  \note - The scope is shared target and initiator.
 *
 */
/*****************************************************************************/
FORCEINLINE
void ossaSingleThreadedEnter(
     agsaRoot_t *agRoot,
     bit32  syncLockId
     )
{
  tdsaRootOsData_t *pOsData = agNULL;
  tiRoot_t  *ptiRoot = agNULL;
  tdsaContext_t *tdsaAllShared = agNULL;

  TD_ASSERT(agRoot, "agRoot");
  pOsData = (tdsaRootOsData_t *) (agRoot->osData);
  TD_ASSERT(pOsData, "pOsData");
  ptiRoot = pOsData->tiRoot;
  TD_ASSERT(ptiRoot, "ptiRoot");

  tdsaAllShared = (tdsaContext_t *)pOsData->tdsaAllShared;
  TD_ASSERT(tdsaAllShared, "tdsaAllShared");

  ostiSingleThreadedEnter(ptiRoot, syncLockId + tdsaAllShared->MaxNumOSLocks);
  return;
}

/*****************************************************************************/
/*! \brief ossaSingleThreadedLeave
 *
 *
 *  Purpose: This routine is called to leave a critical region of code
 *           previously protected by a call to osSingleThreadedEnter()
 *
 *
 *  \param   agRoot:       Pointer to chip/driver Instance.
 *  \param   syncLockId    to be explained.
 *
 *
 *  \return None.
 *
 *  \note - The scope is shared target and initiator.
 *
 */
/*****************************************************************************/
FORCEINLINE
void ossaSingleThreadedLeave(
     agsaRoot_t *agRoot,
     bit32  syncLockId
     )
{
  tdsaRootOsData_t *pOsData = agNULL;
  tiRoot_t  *ptiRoot = agNULL;
  tdsaContext_t *tdsaAllShared = agNULL;

  TD_ASSERT(agRoot, "agRoot");
  pOsData = (tdsaRootOsData_t *) (agRoot->osData);
  TD_ASSERT(pOsData, "pOsData");
  ptiRoot = pOsData->tiRoot;
  TD_ASSERT(ptiRoot, "ptiRoot");

  tdsaAllShared = (tdsaContext_t *)pOsData->tdsaAllShared;
  TD_ASSERT(tdsaAllShared, "tdsaAllShared");

  ostiSingleThreadedLeave(ptiRoot, syncLockId + tdsaAllShared->MaxNumOSLocks);
  return;
}

#ifdef PERF_COUNT
osGLOBAL void ossaEnter(agsaRoot_t *agRoot, int io)
{
  ostiEnter(((tdsaRootOsData_t*)(agRoot->osData))->tiRoot, 0, io);
  return;
}

osGLOBAL void ossaLeave(agsaRoot_t *agRoot, int io)
{
  ostiLeave(((tdsaRootOsData_t*)(agRoot->osData))->tiRoot, 0, io);
  return;
}
#endif


osGLOBAL void
ossaSSPIoctlCompleted(
                        agsaRoot_t                        *agRoot,
                        agsaIORequest_t           *agIORequest,
                        bit32                             agIOStatus,
                        bit32                             agIOInfoLen,
                        void                              *agParam,
                        bit16                             sspTag,
                        bit32                             agOtherInfo
                   )
{
  tdsaRootOsData_t                              *osData           = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t                                              *tiRoot           = (tiRoot_t *)osData->tiRoot;
  tdIORequestBody_t                             *tdIORequestBody  = (tdIORequestBody_t *)agIORequest->osData;
  agsaSASRequestBody_t                  *agSASRequestBody = agNULL;
  agsaSSPInitiatorRequest_t             *agSSPFrame       = agNULL;
  bit8                          scsiOpcode        = 0;

  agSASRequestBody = &(tdIORequestBody->transport.SAS.agSASRequestBody);
  agSSPFrame = &(agSASRequestBody->sspInitiatorReq);
  scsiOpcode = agSSPFrame->sspCmdIU.cdb[0];

  TI_DBG2(("ossaSSPIoctlCompleted: start\n"));

  if (agIOStatus == OSSA_SUCCESS)
  {
    TI_DBG2(("ossaSSPIoctlCompleted: Success status\n"));
  }
  else
  {
    TI_DBG1(("ossaSSPIoctlCompleted: Status 0x%x\n", agIOStatus));
  }
  switch(scsiOpcode)
  {
  case REPORT_LUN_OPCODE:
    ostiNumOfLUNIOCTLRsp(tiRoot, agIOStatus);
        break;

  default:
        TI_DBG1(("ossaSSPIoctlCompleted: Unsupported SCSI command Response  0x%x\n",scsiOpcode));
        break;
  }
  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Yi");
  return;

}

osGLOBAL void
ossaSMPIoctlCompleted(
                 agsaRoot_t            *agRoot,
                 agsaIORequest_t       *agIORequest,
                 bit32                 agIOStatus,
                 bit32                 agIOInfoLen,
                 agsaFrameHandle_t     agFrameHandle
                 )
{
        tdsaRootOsData_t        *osData = (tdsaRootOsData_t *)agRoot->osData;
        tiRoot_t                        *tiRoot = (tiRoot_t *)osData->tiRoot;
        TI_DBG2(("ossaSMPIoctlCompleted: start\n"));

        if (agIOStatus == OSSA_SUCCESS)
        {
          TI_DBG2(("ossaSMPIoctlCompleted: Success status\n"));
        }
        else
        {
          TI_DBG1(("ossaSMPIoctlCompleted: Status 0x%x\n", agIOStatus));
        }

        ostiSendSMPIOCTLRsp(tiRoot, agIOStatus);
        smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Yi");
        return;

}


/*****************************************************************************/
/*! \brief ossaSMPCompleted
 *
 *
 *  Purpose: This routine is called by lower layer to indicate the completion of
 *           SMP request
 *
 *  \param   agRoot:       Pointer to chip/driver Instance.
 *  \param   agIORequest   Pointer to SMP request handle
 *  \param   agIOStatus    Status
 *  \param   agFrameHeader:Pointer to SMP frame header.
 *  \param   agIOInfoLen   IO information length assoicated with the IO
 *  \param   agFrameHandle A Handle used to refer to the response frame
 *
 *
 *  \return None.
 *
 *  \note - The scope is shared target and initiator.
 *          For details, refer to SAS/SATA Low-Level API Specification
 */
/*****************************************************************************/
osGLOBAL void ossaSMPCompleted(
                 agsaRoot_t            *agRoot,
                 agsaIORequest_t       *agIORequest,
                 bit32                 agIOStatus,
                 bit32                 agIOInfoLen,
                 agsaFrameHandle_t     agFrameHandle
                 )
{
#ifdef PASSTHROUGH
  tdsaRootOsData_t         *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t                 *tiRoot = (tiRoot_t *)osData->tiRoot;
  tdPassthroughCmndBody_t  *tdPTCmndBody  = (tdPassthroughCmndBody_t *)agIORequest->osData;
  bit32                    tiStatus = tiPassthroughError;
  bit8                     SMPframe[agIOInfoLen + sizeof(agsaSMPFrameHeader_t)];
  bit8                     SMPpayload[agIOInfoLen];

  TI_DBG2(("ossaSMPCompleted: start and passthrough\n"));
#else /* not PASSTHROUGH */

  tdssSMPRequestBody_t *pSMPRequestBody = (tdssSMPRequestBody_t *) agIORequest->osData;
  TI_DBG4(("ossaSMPCompleted: start\n"));
#endif /* end not PASSTHROUGH */

  TDSA_OUT_ENTER((tiRoot_t *)((tdsaRootOsData_t *)agRoot->osData)->tiRoot);
  smTraceFuncEnter(hpDBG_VERY_LOUD,"Y4");

#ifdef PASSTHROUGH
  if (tdPTCmndBody == agNULL)
  {
    TI_DBG1(("ossaSMPCompleted: tdPTCmndBody is NULL \n"));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Y4");
    goto ext;
  }

  if (tdPTCmndBody->EventCB == agNULL)
  {
    TI_DBG1(("ossaSMPCompleted: tdPTCmndBody->EventCB is NULL \n"));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "Y4");
    goto ext;
  }

  if (agIOStatus == OSSA_IO_SUCCESS)
  {
    tiStatus = tiPassthroughSuccess;
  }
  else if (agIOStatus == OSSA_IO_ABORTED)
  {
    tiStatus = tiPassthroughAborted;
  }
  else
  {
    tiStatus = tiPassthroughError;
  }

  osti_memset(SMPpayload, 0, agIOInfoLen);
  osti_memset(SMPframe, 0, agIOInfoLen + sizeof(agsaSMPFrameHeader_t));

  /* combine the header and payload */
  saFrameReadBlock(agRoot, agFrameHandle, 0, &SMPpayload, agIOInfoLen);
  osti_memcpy(SMPframe, agFrameHeader, sizeof(agsaSMPFrameHeader_t));
  osti_memcpy(SMPframe+sizeof(agsaSMPFrameHeader_t), SMPpayload, agIOInfoLen);

  tdPTCmndBody->EventCB(tiRoot,
                        tdPTCmndBody->tiPassthroughRequest,
                        tiStatus,
                        SMPframe,
                        agIOInfoLen + sizeof(agsaSMPFrameHeader_t)
                        );


#else /* not PASSTHROUGH */

  /*
    At initiator, passing SMP to TD layer, itdssSMPCompleted(), which does nothing.
    At target, passing SMP to TD layer, ttdsaSMPCompleted()
  */
  /*
     how to use agFrameHandle, when saFrameReadBlock() is used
  */

  /* SPC can't be SMP target */

  TI_DBG4(("ossaSMPCompleted: start\n"));

  if (pSMPRequestBody == agNULL)
  {
    TI_DBG1(("ossaSMPCompleted: pSMPRequestBody is NULL \n"));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "Y4");
    goto ext;
  }

  if (pSMPRequestBody->SMPCompletionFunc == agNULL)
  {
    TI_DBG1(("ossaSMPCompleted: pSMPRequestBody->SMPCompletionFunc is NULL \n"));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "Y4");
    goto ext;
  }
#ifdef TD_INTERNAL_DEBUG /* debugging */
  TI_DBG4(("ossaSMPCompleted: agIOrequest %p\n", agIORequest->osData));
  TI_DBG4(("ossaSMPCompleted: sizeof(tdIORequestBody_t) %d 0x%x\n", sizeof(tdIORequestBody_t),
           sizeof(tdIORequestBody_t)));
  TI_DBG4(("ossaSMPCompleted: SMPRequestbody %p\n", pSMPRequestBody));
  TI_DBG4(("ossaSMPCompleted: calling callback fn\n"));
  TI_DBG4(("ossaSMPCompleted: callback fn %p\n",pSMPRequestBody->SMPCompletionFunc));
#endif /* TD_INTERNAL_DEBUG */
  /*
    if initiator, calling itdssSMPCompleted() in itdcb.c
    if target,    calling ttdsaSMPCompleted() in ttdsmp.c
  */
  pSMPRequestBody->SMPCompletionFunc(
                                     agRoot,
                                     agIORequest,
                                     agIOStatus,
                                     agIOInfoLen,
                                     agFrameHandle
                                     );

#endif /* Not PASSTHROUGH */

  smTraceFuncExit(hpDBG_VERY_LOUD, 'e', "Y4");
ext:
  TDSA_OUT_LEAVE((tiRoot_t *)((tdsaRootOsData_t *)agRoot->osData)->tiRoot);
  return;
}

osGLOBAL void
ossaSMPReqReceived(
                   agsaRoot_t           *agRoot,
                   agsaDevHandle_t      *agDevHandle,
                   agsaFrameHandle_t    agFrameHandle,
                   bit32                agIOInfoLen,
                   bit32                phyId
                   )
{
  smTraceFuncEnter(hpDBG_VERY_LOUD,"Y5");
  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Y5");
  return;
}

/*****************************************************************************/
/*! \brief ossaSMPCAMCompleted
 *
 *
 *  Purpose: This routine is called by lower layer to indicate the completion of
 *           SMP request
 *
 *  \param   agRoot:       Pointer to chip/driver Instance.
 *  \param   agIORequest   Pointer to SMP request handle
 *  \param   agIOStatus    Status
 *  \param   agIOInfoLen   IO information length assoicated with the IO
 *  \param   agFrameHandle A Handle used to refer to the response frame
 *
 *
 *  \return None.
 *
 *  \note - The scope is shared target and initiator.
 *          For details, refer to SAS/SATA Low-Level API Specification
 */
/*****************************************************************************/
osGLOBAL void ossaSMPCAMCompleted(
                 agsaRoot_t            *agRoot,
                 agsaIORequest_t       *agIORequest,
                 bit32                 agIOStatus,
                 bit32                 agIOInfoLen,
                 agsaFrameHandle_t     agFrameHandle
                 )
{
  tdsaRootOsData_t    *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t            *tiRoot = (tiRoot_t *)osData->tiRoot;
  tdIORequestBody_t   *tdSMPRequestBody  = agNULL;
  bit32                context = osData->IntContext;
  tiSMPStatus_t        status;
  bit32               PhysUpper32;
  bit32               PhysLower32;
  bit32               memAllocStatus;
  void                *osMemHandle;
  bit32               *SMPpayload;
  TI_DBG2(("ossaSMPCAMCompleted: start\n"));
  TI_DBG2(("ossaSMPCAMCompleted: agIOInfoLen %d\n", agIOInfoLen));
  if (!agIORequest->osData)
  {
    TD_ASSERT((0), "ossaSMPCAMCompleted agIORequest->osData");
    goto ext;
  }
  tdSMPRequestBody = (tdIORequestBody_t *)agIORequest->osData;
  if (tdSMPRequestBody->tiIORequest->osData == agNULL)
  {
    TI_DBG1(("ossaSMPCAMCompleted: tdIORequestBody->tiIORequest->osData is null, wrong\n"));
    goto ext;
  }
  /* allocating agIORequest for SMP Payload itself */
  memAllocStatus = ostiAllocMemory(
                                   tiRoot,
                                   &osMemHandle,
                                   (void **)&SMPpayload,
                                   &PhysUpper32,
                                   &PhysLower32,
                                   8,
                                   agIOInfoLen,
                                   agTRUE
                                   );
  if (memAllocStatus != tiSuccess)
  {
    /* let os process IO */
    TI_DBG1(("ossaSMPCAMCompleted: ostiAllocMemory failed...\n"));
    goto ext;
  }
  if (SMPpayload == agNULL)
  {
    TI_DBG1(("ossaSMPCAMCompleted: ostiAllocMemory returned NULL SMPpayload\n"));
    goto ext;
  }
  if (agIOStatus == OSSA_IO_SUCCESS)
  {
    TI_DBG1(("ossaSMPCAMCompleted: Success status\n"));
    osti_memset(SMPpayload, 0, agIOInfoLen);
    TI_DBG1(("ossaSMPCAMCompleted: after memset\n"));
    saFrameReadBlock(agRoot, agFrameHandle, 0, SMPpayload, agIOInfoLen);
    TI_DBG1(("ossaSMPCAMCompleted: after read \n"));
    status = tiSMPSuccess;
  }
  else if (agIOStatus == OSSA_IO_ABORTED)
  {
    TI_DBG1(("ossaSMPCAMCompleted: SMP Aborted status\n"));
    status = tiSMPAborted;
    TI_DBG1(("ossaSMPCAMCompleted: failed status=%d\n", status));
    //failed to send smp command, we need to free the memory
    ostiFreeMemory(
                  tiRoot,
                  osMemHandle,
                  agIOInfoLen
                  );
  }
  else
  {
    TI_DBG1(("ossaSMPCAMCompleted: SMP failed status\n"));
    status = tiSMPFailed;
    TI_DBG1(("ossaSMPCAMCompleted: failed status=%d\n", status));
    //failed to send smp command, we need to free the memory
    ostiFreeMemory(
                  tiRoot,
                  osMemHandle,
                  agIOInfoLen
                  );
  }
  ostiInitiatorSMPCompleted(tiRoot,
                            tdSMPRequestBody->tiIORequest,
                            status,
                            agIOInfoLen,
                            SMPpayload,
                            context
                            );
  ext:
  TDSA_OUT_LEAVE((tiRoot_t*)((tdsaRootOsData_t*)agRoot->osData)->tiRoot);
  return;
}
#ifdef REMOVED
#ifdef TARGET_DRIVER
/*****************************************************************************/
/*! \brief ossaSMPReqReceived
 *
 *
 *  Purpose: This routine is called by lower layer to indicate the reception of
 *           SMP request
 *
 *  \param   agRoot:       Pointer to chip/driver Instance.
 *  \param   agDevHandle   Pointer to the device handle of the device
 *  \param   agFrameHandle A Handle used to refer to the response frame
 *
 *
 *  \return None.
 *
 *  \note - The scope is target only
 *          For details, refer to SAS/SATA Low-Level API Specification
 */
/*****************************************************************************/
osGLOBAL void ossaSMPReqReceived(
                   agsaRoot_t           *agRoot,
                   agsaDevHandle_t      *agDevHandle,
                   agsaFrameHandle_t    agFrameHandle,
                   bit32                 agFrameLength,
                   bit32                phyId
                   )
{
  bit8                   smpHeader[4];
  agsaSMPFrameHeader_t   *agFrameHeader;
#ifdef PASSTHROUGH
  /* call the registered function(parameter in tiTGTPassthroughCmndRegister() by target */
  tdsaRootOsData_t       *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t               *tiRoot = (tiRoot_t *)osData->tiRoot;
  ttdsaTgt_t             *Target = (ttdsaTgt_t *)osData->ttdsaTgt;

  bit8                   SMPframe[agIOInfoLen + sizeof(agsaSMPFrameHeader_t)];
  bit8                   SMPpayload[agIOInfoLen];

  TI_DBG2(("ossaSMPReqReceived: start and passthrough\n"));
  osti_memset(SMPpayload, 0, agIOInfoLen);
  osti_memset(SMPframe, 0, agIOInfoLen + sizeof(agsaSMPFrameHeader_t));
  /* combine smp header and payload */
  saFrameReadBlock(agRoot, agFrameHandle, 0, &SMPpayload, agIOInfoLen);
  osti_memcpy(SMPframe, agFrameHeader, sizeof(agsaSMPFrameHeader_t));
  osti_memcpy(SMPframe+sizeof(agsaSMPFrameHeader_t), SMPpayload, agIOInfoLen);

  Target->PasthroughCB(
                       tiRoot,
                       tiSASATA,
                       tiSMP,
                       tiSMPResponse,
                       SMPframe,
                       agIOInfoLen + sizeof(agsaSMPFrameHeader_t),
                       phyId
                       );

#else

  /*
    agDevHandle_t->osData points to tdssDeviceData_t
   */
  tdsaDeviceData_t *pDeviceData = (tdsaDeviceData_t *) agDevHandle->osData;

    saFrameReadBlock(agRoot, agFrameHandle, 0, smpHeader, 4);
    agFrameHeader = (agsaSMPFrameHeader_t *)smpHeader;
  TI_DBG4(("ossaSMPReqReceived: start\n"));

  /* tdtypes.h, calling  ttdsaSMPReqReceived in ttdsmp.c */
  pDeviceData->pJumpTable->pSMPReqReceived (
                                            agRoot,
                                            agDevHandle,
                                            agFrameHeader,
                                            agFrameHandle,
                                            agFrameLength,
                                            phyId
                                            );
#endif
  return;
}
#endif
#endif

/*****************************************************************************/
/*! \brief ossaSSPCompleted
 *
 *
 *  Purpose: This routine is called by lower layer to indicate the completion of
 *           SSP request
 *
 *  \param   agRoot:       Pointer to chip/driver Instance.
 *  \param   agIORequest   Pointer to SMP request handle
 *  \param   agIOStatus    Status
 *  \param   agIOInfoLen   IO information length assoicated with the IO
 *  \param   agFrameHandle A Handle used to refer to the response frame
 *
 *
 *  \return None.
 *
 *  \note - The scope is shared target and initiator.
 *          For details, refer to SAS/SATA Low-Level API Specification
 */
/*****************************************************************************/
FORCEINLINE
void ossaSSPCompleted(
                 agsaRoot_t          *agRoot,
                 agsaIORequest_t     *agIORequest,
                 bit32               agIOStatus,
                 bit32               agIOInfoLen,
                 void                *agParam,
                 bit16               sspTag,
                 bit32               agOtherInfo
                )
{
  tdIORequestBody_t  *pIORequestBody;
#ifdef TD_DEBUG_ENABLE
  tiDeviceHandle_t   *tiDeviceHandle = agNULL;
  tdsaDeviceData_t   *oneDeviceData = agNULL;
#endif

  TDSA_OUT_ENTER((tiRoot_t*)((tdsaRootOsData_t*)agRoot->osData)->tiRoot);
  smTraceFuncEnter(hpDBG_VERY_LOUD,"2L");

  if(!agIORequest->osData)
  {
    TD_ASSERT((0), "ossaSSPCompleted agIORequest->osData");
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2L");
    goto ext;
  }
  pIORequestBody = (tdIORequestBody_t *)agIORequest->osData;


  TI_DBG4(("ossaSSPCompleted: start\n"));

  if (pIORequestBody == agNULL)
  {
    TI_DBG1(("ossaSSPCompleted: pIORequestBody is NULL \n"));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2L");
    goto ext;
  }
  if (pIORequestBody->IOCompletionFunc == agNULL)
  {
#ifdef TD_DEBUG_ENABLE
    tiDeviceHandle = pIORequestBody->tiDevHandle;
    oneDeviceData  = (tdsaDeviceData_t *)tiDeviceHandle->tdData;
#endif
    TI_DBG1(("ossaSSPCompleted: IOCompletionFunc is NULL \n"));
    TI_DBG1(("ossaSSPCompleted: did %d \n", oneDeviceData->id));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "2L");
    goto ext;
  }

   /*
     if initiator, calling itdssIOCompleted() in itdcb.c
     if initiator, calling itdssTaskCompleted in itdcb.c
     if target,    calling ttdsaIOCompleted() in ttdio.c
   */
  pIORequestBody->IOCompletionFunc(
                                   agRoot,
                                   agIORequest,
                                   agIOStatus,
                                   agIOInfoLen,
                                   agParam,
                                   agOtherInfo
                                   );
  smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "2L");
ext:
  TDSA_OUT_LEAVE((tiRoot_t*)((tdsaRootOsData_t*)agRoot->osData)->tiRoot);
  return;
}

#ifdef FAST_IO_TEST
GLOBAL void ossaFastSSPCompleted(
                 agsaRoot_t          *agRoot,
                 agsaIORequest_t     *cbArg,
                 bit32               agIOStatus,
                 bit32               agIOInfoLen,
                 void                *agParam,
                 bit16               sspTag,
                 bit32               agOtherInfo
                )
{
  agsaFastCBBuf_t    *safb = (agsaFastCBBuf_t*)cbArg;
  tdsaRootOsData_t *osData = (tdsaRootOsData_t*)agRoot->osData;
  tiRoot_t         *tiRoot = (tiRoot_t*)osData->tiRoot;
  bit32            scsi_status;
  bit32            data_status;
  bit32            respLen;
  bit8             respData[128];
  bit32            senseLen;
  agsaSSPResponseInfoUnit_t agSSPRespIU;

  TDSA_OUT_ENTER((tiRoot_t*)((tdsaRootOsData_t*)agRoot->osData)->tiRoot);
  smTraceFuncEnter(hpDBG_VERY_LOUD,"Y6");

  TI_DBG4(("ossaSSPCompleted: start\n"));

  if (safb->cb == agNULL || safb->cbArg == agNULL)
  {
    TI_DBG1(("ossaFastSSPCompleted: pIORequestBody is NULL \n"));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Y6");
    TD_ASSERT((0), "");
    goto ext;
  }

  switch (agIOStatus)
  {
    case OSSA_IO_SUCCESS:

      /* ~ itdssIOSuccessHandler */
      if ((agIOInfoLen < sizeof(agsaSSPResponseInfoUnit_t)))
      {
        ((ostiFastSSPCb_t)safb->cb)(tiRoot, safb->cbArg, OSSA_IO_SUCCESS, 0);
        break;
      }

      /* reads agsaSSPResponseInfoUnit_t */
      saFrameReadBlock(agRoot, agParam, 0, &agSSPRespIU,
                       sizeof(agsaSSPResponseInfoUnit_t));

      data_status = SA_SSPRESP_GET_DATAPRES(&agSSPRespIU);
      scsi_status = agSSPRespIU.status;

      TI_DBG1(("itdssIOSuccessHandler: scsi_status %d\n", scsi_status));

      /* endianess is invovled here */
      senseLen = SA_SSPRESP_GET_SENSEDATALEN(&agSSPRespIU);
      respLen = SA_SSPRESP_GET_RESPONSEDATALEN(&agSSPRespIU);
      TI_DBG2(("itdssIOSuccessHandler: scsi status=0x%x, senselen=0x%x resplen "
               "0x%x\n", scsi_status, senseLen, respLen));

      if (agIOInfoLen < sizeof(agsaSSPResponseInfoUnit_t) + senseLen + respLen)
      {
        ((ostiFastSSPCb_t)safb->cb)(tiRoot, safb->cbArg, tiIOFailed,
                                     tiDetailOtherError);
        break;
      }

      /* reads response data */
      saFrameReadBlock(agRoot, agParam, sizeof(agsaSSPResponseInfoUnit_t),
                       respData, respLen);
      /* reads sense data */
      saFrameReadBlock(agRoot, agParam, sizeof(agsaSSPResponseInfoUnit_t)
                       + respLen, safb->pSenseData, senseLen);

      if (data_status == 0)
      {
        /* NO_DATA */
        TI_DBG2(("ossaFastSSPCompleted: no data\n"));
        ((ostiFastSSPCb_t)safb->cb)(tiRoot, safb->cbArg, tiIOSuccess,
                                     scsi_status);
        break;
      }

      if (data_status == 1)
      {
        /* RESPONSE_DATA */
        TI_DBG1(("ossaFastSSPCompleted: response data \n"));
        ((ostiFastSSPCb_t)safb->cb)(tiRoot, safb->cbArg, tiIOSuccess, 0);
        break;
      }

      if (data_status == 2)
      {
        tiSenseData_t senseData;

        /* SENSE_DATA */
        TI_DBG2(("itdssIOSuccessHandler: sense data \n"));

        senseData.senseData = safb->pSenseData;
        senseData.senseLen = MIN(*(safb->senseLen), senseLen);

        /* when ASC = 0x04 - Log Unit Not Ready,
           and ASCQ = 0x11 - Enable Spinup Required:
           call saLocalPhyControl to notify spinup */
        if (((char*)safb->pSenseData)[12] == 0x04 &&
            ((char*)safb->pSenseData)[13] == 0x11)
        {
          int i;

          TI_DBG2(("ossaFastSSPCompleted: sending notfify spinup\n"));

          if (((tdsaDeviceData_t*)safb->oneDeviceData)->directlyAttached ==
               agTRUE)
          {
            for (i = 0; i < TD_MAX_NUM_NOTIFY_SPINUP; i++)
            {
              saLocalPhyControl(agRoot, agNULL, 0,
                                ((tdsaDeviceData_t*)safb->oneDeviceData)->phyID,
                                AGSA_PHY_NOTIFY_ENABLE_SPINUP,
                                agNULL);
            }
          }
        }

        if (*(safb->senseLen) > senseData.senseLen)
          *(safb->senseLen) = senseData.senseLen;
//       memcpy((void *)safb->pSenseData, senseData.senseData, safb->senseLen);

        ((ostiFastSSPCb_t)safb->cb)(tiRoot, safb->cbArg, tiIOSuccess,
                                     scsi_status);
        break;
      }

      if (data_status == 3)
      {
        /* RESERVED */
        TI_DBG1(("ossaFastSSPCompleted: reserved wrong!!!\n"));

        ((ostiFastSSPCb_t)safb->cb)(tiRoot, safb->cbArg, tiIOFailed,
                                     scsi_status);
        break;
      }
      break;
#ifdef REMOVED
    case OSSA_IO_OVERFLOW:
      ((ostiFastSSPCb_t)safb->cb)(tiRoot, safb->cbArg, tiIOOverRun,
                                   agIOInfoLen);
      break;
#endif /* REMOVED */
    case OSSA_IO_UNDERFLOW:
      ((ostiFastSSPCb_t)safb->cb)(tiRoot, safb->cbArg, tiIOUnderRun,
                                   agIOInfoLen);
      break;

    case OSSA_IO_ABORTED:
      ((ostiFastSSPCb_t)safb->cb)(tiRoot, safb->cbArg, tiIOFailed,
                                   tiDetailAborted);
      break;
    case OSSA_IO_ABORT_RESET:
      ((ostiFastSSPCb_t)safb->cb)(tiRoot, safb->cbArg, tiIOFailed,
                                   tiDetailAbortReset);
      break;
    case OSSA_IO_NO_DEVICE:
      ((ostiFastSSPCb_t)safb->cb)(tiRoot, safb->cbArg, tiIOFailed,
                                   tiDetailNoLogin);
      break;
    case OSSA_IO_DS_NON_OPERATIONAL:
    {

      tdsaDeviceData_t *oneDeviceData;

      oneDeviceData = (tdsaDeviceData_t*)safb->oneDeviceData;
      if (oneDeviceData->valid == agTRUE &&
          oneDeviceData->registered == agTRUE &&
          oneDeviceData->tdPortContext != agNULL)
      {
        saSetDeviceState(oneDeviceData->agRoot, agNULL, tdsaRotateQnumber(tiRoot, oneDeviceData),
                         oneDeviceData->agDevHandle, SA_DS_OPERATIONAL);
      }
      /* fall through */
    }

    default:
      ((ostiFastSSPCb_t)safb->cb)(tiRoot, safb->cbArg, tiIOFailed,
                                   tiDetailOtherError);
      break;
  }

  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "Y6");

ext:
  TDSA_OUT_LEAVE((tiRoot_t*)((tdsaRootOsData_t*)agRoot->osData)->tiRoot);
  return;
} /* ossaFastSSPCompleted */
#endif

/*****************************************************************************/
/*! \brief ossaSSPReqReceived
 *
 *
 *  Purpose: This routine is called by lower layer to indicate the reception of
 *           SMP request
 *
 *  \param   agRoot:         Pointer to chip/driver Instance.
 *  \param   agDevHandle     Pointer to the device handle of the device
 *  \param   agFrameHandle   A Handle used to refer to the response frame
 *  \param   agInitiatorTag  the initiator tag
 *  \param   agFrameType     SSP frame type
 *
 *  \return none.
 *
 *  \note - The scope is target only
 *          For details, refer to SAS/SATA Low-Level API Specification
 */
/*****************************************************************************/
osGLOBAL void ossaSSPReqReceived(
                   agsaRoot_t           *agRoot,
                   agsaDevHandle_t      *agDevHandle,
                   agsaFrameHandle_t    agFrameHandle,
                   bit16                agInitiatorTag,
                   bit32                parameter,
                   bit32                agFrameLen
                   )
{
  /*
    at target only
    uses jumptable, not callback
  */
  /*
    agDevHandle_t->osData points to tdssDeviceData_t
  */
  tdsaDeviceData_t *pDeviceData = (tdsaDeviceData_t *) agDevHandle->osData;
  smTraceFuncEnter(hpDBG_VERY_LOUD,"Y7");

  /* tdtypes.h, calling  ttdsaSSPReqReceived() in ttdio.c */
  pDeviceData->pJumpTable->pSSPReqReceived (
                                            agRoot,
                                            agDevHandle,
                                            agFrameHandle,
                                            agInitiatorTag,
                                            parameter,
                                            agFrameLen
                                            );
  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Y7");
  return;
}
/*****************************************************************************/
/*! \brief ossaStallThread
 *
 *
 *  Purpose: This routine is called to stall this thread for a number of
 *           microseconds.
 *
 *
 *  \param  agRoot:       Pointer to chip/driver Instance.
 *  \param   microseconds: Micro second to stall.
 *
 *
 *  \return None.
 *
 *  \note - The scope is shared target and initiator.
 *
 */
/*****************************************************************************/
osGLOBAL void ossaStallThread(agsaRoot_t *agRoot,
                bit32 microseconds
                )
{
  tdsaRootOsData_t *pOsData = (tdsaRootOsData_t *) (agRoot->osData);

  ostiStallThread (
                   pOsData->tiRoot,
                   microseconds
                   );
  return;
}


/*****************************************************************************
*! \brief  ossaSSPEvent
*
*   This routine is called to notify the OS Layer of an event associated with
*   SAS port or SAS device
*
*  \param   agRoot:         Handles for this instance of SAS/SATA hardware
*  \param   agIORequest     Pointer to IO request
*  \param   event:          event type
*  \param   agIOInfoLen:    not in use
*  \param   agFrameHandle:  not in use
*
*  \return: none
*
*****************************************************************************/
/* in case of CMD ACK_NAK timeout, send query task */
osGLOBAL void ossaSSPEvent(
             agsaRoot_t           *agRoot,
             agsaIORequest_t      *agIORequest,
             agsaPortContext_t    *agPortContext,
             agsaDevHandle_t      *agDevHandle,
             bit32                event,
             bit16                sspTag,
             bit32                agIOInfoLen,
             void                 *agParam
             )
{
#ifdef INITIATOR_DRIVER
  tdsaRootOsData_t            *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t                    *tiRoot = (tiRoot_t *)osData->tiRoot;
  /*  bit32                       intContext = osData->IntContext; */
  void                        *osMemHandle;
  tdIORequestBody_t           *TMtdIORequestBody;
  bit32                       PhysUpper32;
  bit32                       PhysLower32;
  bit32                       memAllocStatus;
  bit32                       agRequestType;
  agsaIORequest_t             *agTMIORequest = agNULL;  /* task management itself */
  agsaSASRequestBody_t        *agSASRequestBody = agNULL;
  agsaSSPScsiTaskMgntReq_t    *agSSPTaskMgntRequest;
  bit32                       saStatus;
  bit32                       agIORequestType;  /* type of IO recevied */
  tiIORequest_t               *taskTag;                 /* being task managed one */
  tdIORequestBody_t           *tdIORequestBody;
#endif

#ifdef REMOVED
  tiDeviceHandle_t            *tiDeviceHandle;
  tdsaDeviceData_t            *oneDeviceData = agNULL;
  tdIORequestBody_t           *tdAbortIORequestBody;
#endif
  agsaDifDetails_t            agDifDetails;
  bit8                        framePayload[256];
#ifdef REMOVED
  bit16                       frameOffset = 0;
#endif
  bit16                       frameLen = 0;

  TI_DBG6(("ossaSSPEvent: start\n"));
  smTraceFuncEnter(hpDBG_VERY_LOUD,"Y9");



  if (event == OSSA_IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT ||
      event == OSSA_IO_XFER_ERROR_BREAK ||
      event == OSSA_IO_XFER_ERROR_PHY_NOT_READY
      )
  {

    /* IO being task managed(the original IO) depending on event */
#ifdef INITIATOR_DRIVER
    tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData;
    taskTag         = tdIORequestBody->tiIORequest;
#endif
#ifdef REMOVED
    tiDeviceHandle  = tdIORequestBody->tiDevHandle;
    oneDeviceData   = (tdsaDeviceData_t *)tiDeviceHandle->tdData;
#endif

#ifdef INITIATOR_DRIVER
    agIORequestType = tdIORequestBody->agRequestType;

    /* error checking; only command is expected here */
    if (agIORequestType == AGSA_REQ_TYPE_UNKNOWN)
    {
      TI_DBG1(("ossaSSPEvent: incorrect frame 0x%x. Should be command\n", agIORequestType));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Y9");
      return;
    }

    /* Allocate memory for query task management */
    memAllocStatus = ostiAllocMemory(
                                     tiRoot,
                                     &osMemHandle,
                                     (void **)&TMtdIORequestBody,
                                     &PhysUpper32,
                                     &PhysLower32,
                                     8,
                                     sizeof(tdIORequestBody_t),
                                     agTRUE
                                     );

    if (memAllocStatus != tiSuccess)
    {
      /* let os process IO */
      TI_DBG1(("ossaSSPEvent: ostiAllocMemory failed...\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "Y9");
      return;
    }

    if (TMtdIORequestBody == agNULL)
    {
      /* let os process IO */
      TI_DBG1(("ossaSSPEvent: ostiAllocMemory returned NULL TMIORequestBody\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "Y9");
      return;
    }

    /* setup task management structure */
    TMtdIORequestBody->IOType.InitiatorTMIO.osMemHandle = osMemHandle;
    /* TD generates Query Task not OS layer */
    TMtdIORequestBody->IOType.InitiatorTMIO.CurrentTaskTag = agNULL;
    TMtdIORequestBody->IOType.InitiatorTMIO.TaskTag = taskTag;

    /* initialize callback function */
    TMtdIORequestBody->IOCompletionFunc = itdssQueryTaskCompleted;

    /* initialize tiDevhandle */
    TMtdIORequestBody->tiDevHandle = tdIORequestBody->tiDevHandle;


    /* initialize agIORequest */
    agTMIORequest = &(TMtdIORequestBody->agIORequest);
    agTMIORequest->osData = (void *) TMtdIORequestBody;
    agTMIORequest->sdkData = agNULL; /* LL takes care of this */

    /* request type */
    agRequestType = AGSA_SSP_TASK_MGNT_REQ;
    TMtdIORequestBody->agRequestType = AGSA_SSP_TASK_MGNT_REQ;

    /*
      initialize
      tdIORequestBody_t tdIORequestBody -> agSASRequestBody
    */
    agSASRequestBody = &(TMtdIORequestBody->transport.SAS.agSASRequestBody);
    agSSPTaskMgntRequest = &(agSASRequestBody->sspTaskMgntReq);

    /* fill up LUN field */
    osti_memset(agSSPTaskMgntRequest->lun, 0, 8);

    /* sets taskMgntFunction field */
    agSSPTaskMgntRequest->taskMgntFunction = AGSA_QUERY_TASK;
    /* debugging */
    if (TMtdIORequestBody->IOCompletionFunc == agNULL)
    {
      TI_DBG1(("ossaSSPEvent: Error !!! IOCompletionFunc is NULL\n"));
    }
    /* send query task management */
    saStatus = saSSPStart(agRoot,
                          agTMIORequest,
                          0,
                          agDevHandle,
                          agRequestType,
                          agSASRequestBody,
                          agIORequest,
                          &ossaSSPCompleted);

    if (saStatus != AGSA_RC_SUCCESS)
    {
      /* free up allocated memory */
      ostiFreeMemory(
                     tiRoot,
                     TMtdIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
      TI_DBG1(("ossaSSPEvent: saSSPStart failed\n"));
      return;
    }
#endif
  }
#ifdef REMOVED
  else if (event == OSSA_IO_ABORTED)
  {
    TI_DBG2(("ossaSSPEvent: OSSA_IO_ABORTED\n"));
    /* clean up TD layer's IORequestBody */
    tdAbortIORequestBody = (tdIORequestBody_t *)agIORequest->osData;
    ostiFreeMemory(
                   tiRoot,
                   tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                   sizeof(tdIORequestBody_t)
                   );

  }
  else if (event == OSSA_IO_NOT_VALID)
  {
    TI_DBG1(("ossaSSPEvent: OSSA_IO_NOT_VALID\n"));
    tdAbortIORequestBody = (tdIORequestBody_t *)agIORequest->osData;
    ostiFreeMemory(
                   tiRoot,
                   tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                   sizeof(tdIORequestBody_t)
                   );


  }
#endif
  else if (event == OSSA_IO_XFER_CMD_FRAME_ISSUED)
  {
    TI_DBG2(("ossaSSPEvent: OSSA_IO_XFER_CMD_FRAME_ISSUED\n"));
  }
  else if (event == OSSA_IO_XFER_ERROR_OFFSET_MISMATCH)
  {
    TI_DBG1(("ossaSSPEvent: OSSA_IO_XFER_ERROR_OFFSET_MISMATCH\n"));
  }
  else if (event == OSSA_IO_OVERFLOW)
  {
    TI_DBG1(("ossaSSPEvent: OSSA_IO_OVERFLOW\n"));
    /*
    ??? can't call; missing agIOInfoLen
    ostiInitiatorIOCompleted (
                              tiRoot,
                              tdIORequestBody->tiIORequest,
                              tiIOOverRun,
                              agIOInfoLen,
                              agNULL,
                              intContext
                              );

    */

  }
  else if (event == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED)
  {
    TI_DBG1(("ossaSSPEvent: OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED\n"));
  }
  else if (event == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO)
  {
    TI_DBG1(("ossaSSPEvent: OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO\n"));
  }
  else if (event == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST)
  {
    TI_DBG1(("ossaSSPEvent: OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST\n"));
  }
  else if (event == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE)
  {
    TI_DBG1(("ossaSSPEvent: OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE\n"));
  }
  else if (event == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED)
  {
    TI_DBG1(("ossaSSPEvent: OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED\n"));
  }
  else if (event == OSSA_IO_XFR_ERROR_DEK_KEY_TAG_MISMATCH)
  {
    TI_DBG1(("ossaSSPEvent: OSSA_IO_XFR_ERROR_DEK_KEY_TAG_MISMATCH\n"));
  }
  else if (event == OSSA_IO_XFER_ERROR_XFER_RDY_OVERRUN)
  {
    TI_DBG1(("ossaSSPEvent: OSSA_IO_XFER_ERROR_XFER_RDY_OVERRUN\n"));
  }
  else if (event == OSSA_IO_XFR_ERROR_DIF_MISMATCH                 ||
           event == OSSA_IO_XFR_ERROR_DIF_APPLICATION_TAG_MISMATCH ||
           event == OSSA_IO_XFR_ERROR_DIF_REFERENCE_TAG_MISMATCH   ||
           event == OSSA_IO_XFR_ERROR_DIF_CRC_MISMATCH                 )
  {
    TI_DBG1(("ossaSSPEvent: DIF related, event 0x%x\n", event));
    /* process DIF detail information */
    TI_DBG2(("ossaSSPEvent: agIOInfoLen %d\n", agIOInfoLen));
    if (agParam == agNULL)
    {
      TI_DBG2(("ossaSSPEvent: agParam is NULL!!!\n"));
      return;
    }
    if (agIOInfoLen < sizeof(agsaDifDetails_t))
    {
      TI_DBG2(("ossaSSPEvent: wrong agIOInfoLen!!! agIOInfoLen %d sizeof(agsaDifDetails_t) %d\n", agIOInfoLen, (int)sizeof(agsaDifDetails_t)));
      return;
    }
    /* reads agsaDifDetails_t */
    saFrameReadBlock(agRoot, agParam, 0, &agDifDetails, sizeof(agsaDifDetails_t));
#ifdef REMOVED
    frameOffset = (agDifDetails.ErrBoffsetEDataLen & 0xFFFF);
#endif
    frameLen = (bit16)((agDifDetails.ErrBoffsetEDataLen & 0xFFFF0000) >> 16);

    TI_DBG2(("ossaSSPEvent: UpperLBA 0x%08x LowerLBA 0x%08x\n", agDifDetails.UpperLBA, agDifDetails.LowerLBA));
    TI_DBG2(("ossaSSPEvent: SASAddrHI 0x%08x SASAddrLO 0x%08x\n",
             TD_GET_SAS_ADDRESSHI(agDifDetails.sasAddressHi), TD_GET_SAS_ADDRESSLO(agDifDetails.sasAddressLo)));
    TI_DBG2(("ossaSSPEvent: DIF error mask 0x%x Device ID 0x%x\n",
             (agDifDetails.DIFErrDevID) & 0xFF, (agDifDetails.DIFErrDevID & 0xFFFF0000) >> 16));
    if (frameLen != 0 && frameLen <= 256)
    {
      saFrameReadBlock(agRoot, agParam, sizeof(agsaDifDetails_t), framePayload, frameLen);
      tdhexdump("ossaSSPEvent frame", framePayload, frameLen);
    }
  }
  else
  {
    TI_DBG1(("ossaSSPEvent: other event 0x%x\n", event));
  }

  smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "Y9");
  return;
}

#ifdef FDS_SM
osGLOBAL void ossaSATAIDAbortCB(
               agsaRoot_t               *agRoot,
               agsaIORequest_t          *agIORequest,
               bit32                    flag,
               bit32                    status)
{
  tdsaRootOsData_t        *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t                *tiRoot = (tiRoot_t *)osData->tiRoot;
  tdIORequestBody_t       *tdAbortIORequestBody;

  TI_DBG1(("ossaSATAIDAbortCB: start flag %d status %d\n", flag, status));

  tdAbortIORequestBody = (tdIORequestBody_t *)agIORequest->osData;

  /*
   triggered by tdIDStartTimerCB
  */
  ostiFreeMemory(
                 tiRoot,
                 tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                 sizeof(tdIORequestBody_t)
                );
  return;
}
#endif

#ifdef INITIATOR_DRIVER
osGLOBAL void ossaSSPAbortCB(
               agsaRoot_t               *agRoot,
               agsaIORequest_t          *agIORequest,
               bit32                    flag,
               bit32                    status)
{
  tdsaRootOsData_t        *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t                *tiRoot = (tiRoot_t *)osData->tiRoot;
  tdIORequestBody_t       *tdAbortIORequestBody = agNULL;
  tdsaDeviceData_t        *oneDeviceData        = agNULL;
  tiDeviceHandle_t        *tiDeviceHandle       = agNULL;
  tiIORequest_t           *taskTag              = agNULL;

  TI_DBG2(("ossaSSPAbortCB: start\n"));
  smTraceFuncEnter(hpDBG_VERY_LOUD,"Ya");

  tdAbortIORequestBody = (tdIORequestBody_t *)agIORequest->osData;
  if (tdAbortIORequestBody == agNULL)
  {
    TI_DBG1(("ossaSSPAbortCB: tdAbortIORequestBody is NULL warning!!!!\n"));
    return;
  }

  if (flag == 2)
  {
    /* abort per port */
    TI_DBG1(("ossaSSPAbortCB: abort per port\n"));
  }
  else if (flag == 1)
  {
    TI_DBG2(("ossaSSPAbortCB: abort all\n"));

    tiDeviceHandle = (tiDeviceHandle_t *)tdAbortIORequestBody->tiDevHandle;
    if (tiDeviceHandle == agNULL)
    {
      TI_DBG1(("ossaSSPAbortCB: tiDeviceHandle is NULL warning!!!!\n"));
      ostiFreeMemory(
               tiRoot,
               tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
               sizeof(tdIORequestBody_t)
               );
      return;
    }

    oneDeviceData  = (tdsaDeviceData_t *)tiDeviceHandle->tdData;
    if (oneDeviceData == agNULL)
    {
      TI_DBG1(("ossaSSPAbortCB: oneDeviceData is NULL warning!!!!\n"));
      ostiFreeMemory(
               tiRoot,
               tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
               sizeof(tdIORequestBody_t)
               );
      return;
    }

    if (status == OSSA_IO_SUCCESS)
    {
      TI_DBG2(("ossaSSPAbortCB: OSSA_IO_SUCCESS\n"));
      /* clean up TD layer's IORequestBody */
      if (oneDeviceData->OSAbortAll == agTRUE)
      {
        oneDeviceData->OSAbortAll = agFALSE;
        ostiInitiatorEvent( tiRoot,
                            agNULL,
                            tiDeviceHandle,
                            tiIntrEventTypeLocalAbort,
                            tiAbortOK,
                            agNULL);
      }
      else
      {
        TI_DBG2(("ossaSSPAbortCB: calling saDeregisterDeviceHandle\n"));
        saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData));
      }
      TI_DBG2(("ossaSSPAbortCB: did %d\n", oneDeviceData->id));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );

    }
    else if (status == OSSA_IO_NOT_VALID)
    {
      TI_DBG1(("ossaSSPAbortCB: OSSA_IO_NOT_VALID\n"));
      /* clean up TD layer's IORequestBody */
      if (oneDeviceData->OSAbortAll == agTRUE)
      {
        oneDeviceData->OSAbortAll = agFALSE;
        ostiInitiatorEvent( tiRoot,
                            agNULL,
                            tiDeviceHandle,
                            tiIntrEventTypeLocalAbort,
                            tiAbortFailed,
                            agNULL );
      }
      else
      {
        TI_DBG2(("ossaSSPAbortCB: calling saDeregisterDeviceHandle\n"));
        saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData));
      }
      TI_DBG2(("ossaSSPAbortCB: did %d\n", oneDeviceData->id));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
    else if (status == OSSA_IO_NO_DEVICE)
    {
      TI_DBG1(("ossaSSPAbortCB: OSSA_IO_NO_DEVICE\n"));
      /* clean up TD layer's IORequestBody */
      if (oneDeviceData->OSAbortAll == agTRUE)
      {
        oneDeviceData->OSAbortAll = agFALSE;
        ostiInitiatorEvent( tiRoot,
                            agNULL,
                            tiDeviceHandle,
                            tiIntrEventTypeLocalAbort,
                            tiAbortInProgress,
                            agNULL );
      }
      else
      {
        TI_DBG2(("ossaSSPAbortCB: calling saDeregisterDeviceHandle\n"));
        saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData));
      }
      TI_DBG2(("ossaSSPAbortCB: did %d\n", oneDeviceData->id));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
    else if (status == OSSA_IO_ABORT_IN_PROGRESS)
    {
      TI_DBG1(("ossaSSPAbortCB: OSSA_IO_ABORT_IN_PROGRESS\n"));
      /* clean up TD layer's IORequestBody */
      if (oneDeviceData->OSAbortAll == agTRUE)
      {
        oneDeviceData->OSAbortAll = agFALSE;
        ostiInitiatorEvent( tiRoot,
                            agNULL,
                            tiDeviceHandle,
                            tiIntrEventTypeLocalAbort,
                            tiAbortInProgress,
                            agNULL );
      }
      else
      {
        TI_DBG2(("ossaSSPAbortCB: calling saDeregisterDeviceHandle\n"));
        saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData));
      }
      TI_DBG2(("ossaSSPAbortCB: did %d\n", oneDeviceData->id));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
#ifdef REMOVED
    else if (status == OSSA_IO_ABORT_DELAYED)
    {
      TI_DBG1(("ossaSSPAbortCB: OSSA_IO_ABORT_DELAYED\n"));
      /* clean up TD layer's IORequestBody */
      if (oneDeviceData->OSAbortAll == agTRUE)
      {
        oneDeviceData->OSAbortAll = agFALSE;
        ostiInitiatorEvent( tiRoot,
                            agNULL,
                            tiDeviceHandle,
                            tiIntrEventTypeLocalAbort,
                            tiAbortDelayed,
                            agNULL );
      }
      else
      {
        TI_DBG2(("ossaSSPAbortCB: calling saDeregisterDeviceHandle\n"));
        saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData));
      }
      TI_DBG2(("ossaSSPAbortCB: did %d\n", oneDeviceData->id));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
#endif
    else
    {
      TI_DBG1(("ossaSSPAbortCB: other status %d\n", status));
      /* clean up TD layer's IORequestBody */
      if (oneDeviceData->OSAbortAll == agTRUE)
      {
        oneDeviceData->OSAbortAll = agFALSE;
        ostiInitiatorEvent( tiRoot,
                            agNULL,
                            tiDeviceHandle,
                            tiIntrEventTypeLocalAbort,
                            tiAbortInProgress,
                            agNULL );
      }
      else
      {
        TI_DBG2(("ossaSSPAbortCB: calling saDeregisterDeviceHandle\n"));
        saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData));
      }
      TI_DBG2(("ossaSSPAbortCB: did %d\n", oneDeviceData->id));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
  }
  else if (flag == 0)
  {
    TI_DBG2(("ossaSSPAbortCB: abort one\n"));
    taskTag = tdAbortIORequestBody->tiIOToBeAbortedRequest;

    if ( taskTag == agNULL)
    {
      TI_DBG1(("ossaSSPAbortCB: taskTag is NULL; triggered by itdssQueryTaskCompleted\n"));
    }
    if (status == OSSA_IO_SUCCESS)
    {
      TI_DBG2(("ossaSSPAbortCB: OSSA_IO_SUCCESS\n"));
      if (taskTag != agNULL)
      {
        ostiInitiatorEvent( tiRoot,
                            agNULL,
                            agNULL,
                            tiIntrEventTypeLocalAbort,
                            tiAbortOK,
                            taskTag );
      }
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );

    }
    else if (status == OSSA_IO_NOT_VALID)
    {
      TI_DBG1(("ossaSSPAbortCB: OSSA_IO_NOT_VALID\n"));

      if (taskTag != agNULL)
      {
        ostiInitiatorEvent( tiRoot,
                            agNULL,
                            agNULL,
                            tiIntrEventTypeLocalAbort,
                            tiAbortFailed,
                            taskTag );
      }
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
    else if (status == OSSA_IO_NO_DEVICE)
    {
      TI_DBG1(("ossaSSPAbortCB: OSSA_IO_NO_DEVICE\n"));

      if (taskTag != agNULL)
      {
        ostiInitiatorEvent( tiRoot,
                            agNULL,
                            agNULL,
                            tiIntrEventTypeLocalAbort,
                            tiAbortInProgress,
                            taskTag );
      }
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
    else if (status == OSSA_IO_ABORT_IN_PROGRESS)
    {
      TI_DBG1(("ossaSSPAbortCB: OSSA_IO_ABORT_IN_PROGRESS\n"));

      if (taskTag != agNULL)
      {
        ostiInitiatorEvent( tiRoot,
                            agNULL,
                            agNULL,
                            tiIntrEventTypeLocalAbort,
                            tiAbortInProgress,
                            taskTag );
      }
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
#ifdef REMOVED
    else if (status == OSSA_IO_ABORT_DELAYED)
    {
      TI_DBG1(("ossaSSPAbortCB: OSSA_IO_ABORT_DELAYED\n"));

      if (taskTag != agNULL)
      {
        ostiInitiatorEvent( tiRoot,
                            agNULL,
                            agNULL,
                            tiIntrEventTypeLocalAbort,
                            tiAbortDelayed,
                            taskTag );
      }
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
#endif
    else
    {
      TI_DBG1(("ossaSSPAbortCB: other status %d\n", status));

      if (taskTag != agNULL)
      {
        ostiInitiatorEvent( tiRoot,
                            agNULL,
                            agNULL,
                            tiIntrEventTypeLocalAbort,
                            tiAbortFailed,
                            taskTag );
      }
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
  }
  else
  {
    TI_DBG1(("ossaSSPAbortCB: wrong flag %d\n", flag));
  }
  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Ya");
  return;

}
#endif


#ifdef TARGET_DRIVER
osGLOBAL void ossaSSPAbortCB(
               agsaRoot_t       *agRoot,
               agsaIORequest_t  *agIORequest,
               bit32            flag,
               bit32            status)
{
  tdsaRootOsData_t        *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t                *tiRoot = (tiRoot_t *)osData->tiRoot;
  tdIORequestBody_t       *tdAbortIORequestBody;
  tdsaDeviceData_t        *oneDeviceData;
  tiDeviceHandle_t        *tiDeviceHandle;

  TI_DBG3(("ossaSSPAbortCB: start\n"));
  tdAbortIORequestBody = (tdIORequestBody_t *)agIORequest->osData;

  if (flag == 2)
  {
    /* abort per port */
    TI_DBG2(("ossaSSPAbortCB: abort per port\n"));
  }
  else if (flag == 1)
  {
    TI_DBG2(("ossaSSPAbortCB: abort all\n"));
    tiDeviceHandle = (tiDeviceHandle_t *)tdAbortIORequestBody->tiDevHandle;
    oneDeviceData  = (tdsaDeviceData_t *)tiDeviceHandle->tdData;
    if (status == OSSA_IO_SUCCESS)
    {
      TI_DBG2(("ossaSSPAbortCB: OSSA_IO_SUCCESS\n"));
      /* clean up TD layer's IORequestBody */
      TI_DBG3(("ossaSSPAbortCB: calling saDeregisterDeviceHandle\n"));
      saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData));
      TI_DBG2(("ossaSSPAbortCB: did %d\n", oneDeviceData->id));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );

    }
    else if (status == OSSA_IO_NOT_VALID)
    {
      TI_DBG1(("ossaSSPAbortCB: OSSA_IO_NOT_VALID\n"));
      /* clean up TD layer's IORequestBody */
      TI_DBG2(("ossaSSPAbortCB: calling saDeregisterDeviceHandle\n"));
      saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData));
      TI_DBG2(("ossaSSPAbortCB: did %d\n", oneDeviceData->id));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
    else if (status == OSSA_IO_NO_DEVICE)
    {
      TI_DBG1(("ossaSSPAbortCB: OSSA_IO_NO_DEVICE\n"));
      /* clean up TD layer's IORequestBody */
      TI_DBG2(("ossaSSPAbortCB: calling saDeregisterDeviceHandle\n"));
      saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData));
      TI_DBG2(("ossaSSPAbortCB: did %d\n", oneDeviceData->id));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
    else if (status == OSSA_IO_ABORT_IN_PROGRESS)
    {
      TI_DBG1(("ossaSSPAbortCB: OSSA_IO_ABORT_IN_PROGRESS\n"));
      /* clean up TD layer's IORequestBody */
      TI_DBG2(("ossaSSPAbortCB: calling saDeregisterDeviceHandle\n"));
      saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData));
      TI_DBG2(("ossaSSPAbortCB: did %d\n", oneDeviceData->id));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
#ifdef REMOVED
    else if (status == OSSA_IO_ABORT_DELAYED)
    {
      TI_DBG1(("ossaSSPAbortCB: OSSA_IO_ABORT_DELAYED\n"));
      /* clean up TD layer's IORequestBody */
      TI_DBG2(("ossaSSPAbortCB: calling saDeregisterDeviceHandle\n"));
      saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData));
      TI_DBG2(("ossaSSPAbortCB: did %d\n", oneDeviceData->id));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
#endif
    else
    {
      TI_DBG1(("ossaSSPAbortCB: other status %d\n", status));
      /* clean up TD layer's IORequestBody */
      TI_DBG2(("ossaSSPAbortCB: calling saDeregisterDeviceHandle\n"));
      saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData));
      TI_DBG1(("ossaSSPAbortCB: did %d\n", oneDeviceData->id));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
  }
  else if (flag == 0)
  {
    TI_DBG2(("ossaSSPAbortCB: abort one\n"));
    if (status == OSSA_IO_SUCCESS)
    {
      TI_DBG2(("ossaSSPAbortCB: OSSA_IO_SUCCESS\n"));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );

    }
    else if (status == OSSA_IO_NOT_VALID)
    {
      TI_DBG1(("ossaSSPAbortCB: OSSA_IO_NOT_VALID\n"));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
    else if (status == OSSA_IO_NO_DEVICE)
    {
      TI_DBG1(("ossaSSPAbortCB: OSSA_IO_NO_DEVICE\n"));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
    else if (status == OSSA_IO_ABORT_IN_PROGRESS)
    {
      TI_DBG1(("ossaSSPAbortCB: OSSA_IO_ABORT_IN_PROGRESS\n"));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
#ifdef REMOVED
    else if (status == OSSA_IO_ABORT_DELAYED)
    {
      TI_DBG1(("ossaSSPAbortCB: OSSA_IO_ABORT_DELAYED\n"));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
#endif
    else
    {
      TI_DBG1(("ossaSSPAbortCB: other status %d\n", status));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
  }
  else
  {
    TI_DBG1(("ossaSSPAbortCB: wrong flag %d\n", flag));
  }

  return;

}
#endif


/*****************************************************************************/
/*! \brief ossaLocalPhyControlCB
 *
 *
 *  Purpose: This routine is called by lower layer to indicate the status of
 *           phy operations
 *
 *  \param   agRoot:       Pointer to chip/driver Instance.
 *  \param   phyId         Phy id
 *  \param   phyOperation  Operation to be done on the phy
 *  \param   status        Phy operation specific completion status
 *  \param   parm          Additional parameter, phy operation and status specific
 *
 *
 *  \return None.
 *
 */
/*****************************************************************************/
osGLOBAL void ossaLocalPhyControlCB(
                      agsaRoot_t  *agRoot,
                      agsaContext_t *agContext,
                      bit32       phyId,
                      bit32       phyOperation,
                      bit32       status,
                      void        *parm
                      )
{
#ifdef REMVOED
  agsaPhyErrCounters_t    *agPhyErrCounters;
#endif
#ifdef INITIATOR_DRIVER
  tdsaRootOsData_t         *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t                 *tiRoot = (tiRoot_t *)osData->tiRoot;
  tiIORequest_t            *currentTaskTag;
  tdsaDeviceData_t         *TargetDeviceData;
  satDeviceData_t          *pSatDevData;
  agsaDevHandle_t          *agDevHandle = agNULL;
  agsaContext_t            *agContextDevice;
#endif

  smTraceFuncEnter(hpDBG_VERY_LOUD,"Yb");
  TI_DBG3(("ossaLocalPhyControlCB: start phyID %d\n", phyId));
  TI_DBG3(("ossaLocalPhyControlCB: phyOperation %d status 0x%x\n", phyOperation, status));
  switch (phyOperation)
  {
  case AGSA_PHY_LINK_RESET: /* fall through */
  case AGSA_PHY_HARD_RESET:
    if (phyOperation == AGSA_PHY_LINK_RESET)
    {
      TI_DBG1(("ossaLocalPhyControlCB: AGSA_PHY_LINK_RESET, status 0x%x\n", status));
    }
    else
    {
      TI_DBG1(("ossaLocalPhyControlCB: AGSA_PHY_HARD_RESET, status 0x%x\n", status));
    }
#ifdef INITIATOR_DRIVER
    if (agContext != agNULL)
    {
      currentTaskTag = (tiIORequest_t *)agContext->osData;
      if (status == OSSA_SUCCESS)
      {
        if (currentTaskTag != agNULL)
        {
          TI_DBG2(("ossaLocalPhyControlCB: callback to OS layer with success\n"));
          TargetDeviceData = (tdsaDeviceData_t *)currentTaskTag->tdData;
          pSatDevData = (satDeviceData_t *)&(TargetDeviceData->satDevData);
          agDevHandle = TargetDeviceData->agDevHandle;
          TI_DBG2(("ossaLocalPhyControlCB: satPendingIO %d satNCQMaxIO %d\n", pSatDevData->satPendingIO, pSatDevData->satNCQMaxIO ));
          TI_DBG2(("ossaLocalPhyControlCB: satPendingNCQIO %d satPendingNONNCQIO %d\n", pSatDevData->satPendingNCQIO, pSatDevData->satPendingNONNCQIO));
          pSatDevData->satDriveState = SAT_DEV_STATE_NORMAL;

          if (TargetDeviceData->TRflag == agTRUE)
          {
            saSetDeviceState(agRoot, agNULL, tdsaRotateQnumber(tiRoot, TargetDeviceData), agDevHandle, SA_DS_OPERATIONAL);
            TargetDeviceData->TRflag = agFALSE;
            ostiInitiatorEvent(tiRoot,
                               TargetDeviceData->tdPortContext->tiPortalContext,
                               &(TargetDeviceData->tiDeviceHandle),
                               tiIntrEventTypeTransportRecovery,
                               tiRecOK,
                               agNULL
                              );
          }
          else
          {
            agDevHandle = TargetDeviceData->agDevHandle;
            if (agDevHandle == agNULL)
            {
              TI_DBG1(("ossaLocalPhyControlCB: wrong, agDevHandle is NULL\n"));
            }
            /* move this to OSSA_HW_EVENT_PORT_RESET_COMPLETE in ossaHwCB() */
            agContextDevice = &(TargetDeviceData->agDeviceResetContext);
            agContextDevice->osData = currentTaskTag;

#ifdef REMOVED
            ostiInitiatorEvent( tiRoot,
                                NULL,
                                NULL,
                                tiIntrEventTypeTaskManagement,
                                tiTMOK,
                                currentTaskTag );
#endif
          }
        }
      }
      else
      {
        if (currentTaskTag != agNULL)
        {
          TI_DBG1(("ossaLocalPhyControlCB: callback to OS layer with failure\n"));
          TargetDeviceData = (tdsaDeviceData_t *)currentTaskTag->tdData;
          pSatDevData = (satDeviceData_t *)&(TargetDeviceData->satDevData);
          TI_DBG1(("ossaLocalPhyControlCB: satPendingIO %d satNCQMaxIO %d\n", pSatDevData->satPendingIO, pSatDevData->satNCQMaxIO ));
          TI_DBG1(("ossaLocalPhyControlCB: satPendingNCQIO %d satPendingNONNCQIO %d\n", pSatDevData->satPendingNCQIO, pSatDevData->satPendingNONNCQIO));
          if (TargetDeviceData->TRflag == agTRUE)
          {
            TargetDeviceData->TRflag = agFALSE;
            ostiInitiatorEvent(tiRoot,
                               TargetDeviceData->tdPortContext->tiPortalContext,
                               &(TargetDeviceData->tiDeviceHandle),
                               tiIntrEventTypeTransportRecovery,
                               tiRecFailed ,
                               agNULL
                              );
          }
          else
          {
            ostiInitiatorEvent( tiRoot,
                                NULL,
                                NULL,
                                tiIntrEventTypeTaskManagement,
                                tiTMFailed,
                                currentTaskTag );
          }
        }
      }
    }
#endif
    break;
#ifdef REMOVED
  case AGSA_PHY_GET_ERROR_COUNTS:

    TI_DBG2(("ossaLocalPhyControlCB: AGSA_PHY_GET_ERROR_COUNTS, status 0x%x\n", status));
    if(parm !=agNULL )
    {
      agPhyErrCounters = (agsaPhyErrCounters_t *)parm;
      TI_DBG2(("ossaLocalPhyControlCB: invalidDword %d\n", agPhyErrCounters->invalidDword));
      TI_DBG2(("ossaLocalPhyControlCB: runningDisparityError %d\n", agPhyErrCounters->runningDisparityError));
      TI_DBG2(("ossaLocalPhyControlCB: lostOfDwordSynch %d\n", agPhyErrCounters->lossOfDwordSynch));
      TI_DBG2(("ossaLocalPhyControlCB: phyResetProblem %d\n", agPhyErrCounters->phyResetProblem));
      TI_DBG2(("ossaLocalPhyControlCB: elasticityBufferOverflow %d\n", agPhyErrCounters->elasticityBufferOverflow));
      TI_DBG2(("ossaLocalPhyControlCB: receivedErrorPrimitive %d\n", agPhyErrCounters->receivedErrorPrimitive));
    }
    break;
  case AGSA_PHY_CLEAR_ERROR_COUNTS:
    TI_DBG2(("ossaLocalPhyControlCB: AGSA_PHY_CLEAR_ERROR_COUNTS, status 0x%x\n", status));
    break;
#endif
  case AGSA_PHY_NOTIFY_ENABLE_SPINUP:
    TI_DBG2(("ossaLocalPhyControlCB: AGSA_PHY_NOTIFY_ENABLE_SPINUP, status 0x%x\n", status));
    break;
  case AGSA_PHY_BROADCAST_ASYNCH_EVENT:
    TI_DBG2(("ossaLocalPhyControlCB: AGSA_PHY_BROADCAST_ASYNCH_EVENT, status 0x%x\n", status));
    if (tIsSPC12SATA(agRoot))
    {
      TI_DBG1(("ossaLocalPhyControlCB: BROADCAST_ASYNCH_EVENT received for SATA Controller\n"));
      break;
    }
    break;
  case AGSA_PHY_COMINIT_OOB :
    TI_DBG2(("ossaLocalPhyControlCB: AGSA_PHY_COMINIT_OOB, status 0x%x\n", status));
    break;
  default:
    TI_DBG1(("ossaLocalPhyControlCB: UNKNOWN default case. phyOperation %d status 0x%x\n", phyOperation, status));
    break;
  }
  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Yb");
  return;
}

GLOBAL void   ossaGetPhyProfileCB(
                      agsaRoot_t    *agRoot,
                      agsaContext_t *agContext,
                      bit32         status,
                      bit32         ppc,
                      bit32         phyID,
                      void          *parm )
{

  tdsaRootOsData_t  *osData        = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t          *tiRoot        = (tiRoot_t *)osData->tiRoot;
  tdsaRoot_t        *tdsaRoot      = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t     *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
#ifdef CCFLAGS_PHYCONTROL_COUNTS
  agsaPhyAnalogSettingsPage_t *analog;
#endif /* CCFLAGS_PHYCONTROL_COUNTS   */
  tdPhyCount_t      *PhyBlob = agNULL;

  agsaPhyBWCountersPage_t       *agBWCounters;
  agsaPhyErrCountersPage_t      *agPhyErrCounters;
  TI_DBG1(("ossaGetPhyProfileCB: agContext %p parm %p\n", agContext, parm));
/*
  if(  tdsaAllShared->tdFWControlEx.inProgress )
  {
    tdsaAllShared->tdFWControlEx.inProgress = 0;
    PhyBlob = (tdPhyCount_t  *)tdsaAllShared->tdFWControlEx.usrAddr;
  }
*/
  switch(ppc)
  {
    case  AGSA_SAS_PHY_BW_COUNTERS_PAGE:
      TI_DBG1(("ossaGetPhyProfileCB: AGSA_SAS_PHY_BW_COUNTERS_PAGE, status 0x%x phyID %d\n", status, phyID));
      if(parm !=agNULL )
      {
        agBWCounters = (agsaPhyBWCountersPage_t *)parm;
        TI_DBG1(("ossaGetPhyProfileCB: RX %d TX %d\n", agBWCounters->RXBWCounter,agBWCounters->TXBWCounter));
        if(PhyBlob !=agNULL )
        {
          PhyBlob->InvalidDword = 0;
          PhyBlob->runningDisparityError = 0;
          PhyBlob->codeViolation = 0;
          PhyBlob->phyResetProblem = 0;
          PhyBlob->inboundCRCError = 0;
          PhyBlob->BW_rx = agBWCounters->RXBWCounter;
          PhyBlob->BW_tx = agBWCounters->TXBWCounter;
        }

      }
      break;
    case AGSA_SAS_PHY_ERR_COUNTERS_PAGE:
      if(  tdsaAllShared->tdFWControlEx.inProgress )
      {
  	  tdsaAllShared->tdFWControlEx.inProgress = 0;
  	  PhyBlob = (tdPhyCount_t  *)tdsaAllShared->tdFWControlEx.usrAddr;
      }
      TI_DBG1(("ossaGetPhyProfileCB: AGSA_SAS_PHY_ERR_COUNTERS_PAGE, status 0x%x phyID %d\n", status, phyID));
      if(parm !=agNULL )
      {
        agPhyErrCounters = (agsaPhyErrCountersPage_t *)parm;
        if(PhyBlob !=agNULL )
        {

          PhyBlob->InvalidDword          = agPhyErrCounters->invalidDword;
          PhyBlob->runningDisparityError = agPhyErrCounters->runningDisparityError;
          PhyBlob->LossOfSyncDW          = agPhyErrCounters->lossOfDwordSynch;
          PhyBlob->codeViolation         = agPhyErrCounters->codeViolation;
          PhyBlob->phyResetProblem       = agPhyErrCounters->phyResetProblem;
          PhyBlob->inboundCRCError       = agPhyErrCounters->inboundCRCError;
          PhyBlob->BW_rx = 0;
          PhyBlob->BW_tx = 0;

          TI_DBG2(("ossaGetPhyProfileCB: invalidDword          %d\n", agPhyErrCounters->invalidDword));
          TI_DBG2(("ossaGetPhyProfileCB: runningDisparityError %d\n", agPhyErrCounters->runningDisparityError));
          TI_DBG2(("ossaGetPhyProfileCB: lostOfDwordSynch      %d\n", agPhyErrCounters->lossOfDwordSynch));
          TI_DBG2(("ossaGetPhyProfileCB: phyResetProblem       %d\n", agPhyErrCounters->phyResetProblem));
          TI_DBG2(("ossaGetPhyProfileCB: inboundCRCError       %d\n", agPhyErrCounters->inboundCRCError));
        }
      }
      break;
    case AGSA_SAS_PHY_ERR_COUNTERS_CLR_PAGE:
      TI_DBG1(("ossaGetPhyProfileCB: AGSA_SAS_PHY_ERR_COUNTERS_CLR_PAGE status 0x%x phyID %d\n", status, phyID));
      break;
    case AGSA_SAS_PHY_ANALOG_SETTINGS_PAGE:
      TI_DBG1(("ossaGetPhyProfileCB:AGSA_SAS_PHY_ANALOG_SETTINGS_PAGE status 0x%x phyID %d\n", status, phyID));
#ifdef CCFLAGS_PHYCONTROL_COUNTS
      if(parm !=agNULL )
      {
        analog = (agsaPhyAnalogSettingsPage_t *)parm;
        TI_DBG1(("ossaGetPhyProfileCB: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
          analog->Dword0, analog->Dword1, analog->Dword2, analog->Dword3, analog->Dword4,
          analog->Dword5, analog->Dword6, analog->Dword7, analog->Dword8, analog->Dword9));
        tdsaAllShared->analog[phyID].spaRegister0 = analog->Dword0;
        tdsaAllShared->analog[phyID].spaRegister1 = analog->Dword1;
        tdsaAllShared->analog[phyID].spaRegister2 = analog->Dword2;
        tdsaAllShared->analog[phyID].spaRegister3 = analog->Dword3;
        tdsaAllShared->analog[phyID].spaRegister4 = analog->Dword4;
        saSetPhyProfile( agRoot,agContext,tdsaRotateQnumber(tiRoot, agNULL), AGSA_SAS_PHY_ANALOG_SETTINGS_PAGE,sizeof(agsaPhyAnalogSetupRegisters_t),&tdsaAllShared->analog[phyID],phyID);
      }
#endif /* CCFLAGS_PHYCONTROL_COUNTS   */
     break;
    case AGSA_SAS_PHY_OPEN_REJECT_RETRY_BACKOFF_THRESHOLD_PAGE:
    {
      TI_DBG1(("ossaGetPhyProfileCB:AGSA_SAS_PHY_OPEN_REJECT_RETRY_BACKOFF_THRESHOLD_PAGE status 0x%x phyID %d\n", status, phyID));
      if( parm !=agNULL )
      {
#ifdef TD_DEBUG_ENABLE
        agsaSASPhyOpenRejectRetryBackOffThresholdPage_t *Backoff =
          (agsaSASPhyOpenRejectRetryBackOffThresholdPage_t *)parm;
#endif
        TI_DBG2(("ossaGetPhyProfileCB: DW0 0x%X DW1 0x%X DW2 0x%X DW3 0x%X\n",
                 Backoff->Dword0,Backoff->Dword1,
                 Backoff->Dword2,Backoff->Dword3));
       }
      break;
    }

    case AGSA_SAS_PHY_GENERAL_STATUS_PAGE:
    {
      agsaSASPhyGeneralStatusPage_t * GenStatus = NULL;

      TI_DBG1(("ossaGetPhyProfileCB: AGSA_SAS_PHY_GENERAL_STATUS_PAGE status 0x%x phyID %d\n",
               status, phyID));
      if( parm !=agNULL )
      {
          GenStatus=
          (agsaSASPhyGeneralStatusPage_t *)parm;
        TI_DBG2(("ossaGetPhyProfileCB: "
                 "AGSA_SAS_PHY_GENERAL_STATUS_PAGE status %d DW0 0x%x DW1 0x%x\n",
                 status, GenStatus->Dword0, GenStatus->Dword1));
      }
      ostiGetPhyGeneralStatusRsp(tiRoot, GenStatus, phyID);
//      break;
      return ;
    }

    default:
      TI_DBG1(("ossaGetPhyProfileCB: UNKNOWN default case. phyOperation %d status 0x%x\n", ppc, status));
      break;

  }

  ostiGetPhyProfileIOCTLRsp(tiRoot, status);

}


GLOBAL void ossaSetPhyProfileCB(
                     agsaRoot_t    *agRoot,
                     agsaContext_t *agContext,
                     bit32         status,
                     bit32         ppc,
                     bit32         phyID,
                     void          *parm )
{
  TI_DBG1(("ossaSetPhyProfileCB:agContext %p status 0x%x ppc %d phyID %d parm %p\n",agContext, status, ppc, phyID,parm));
}


/*****************************************************************************/
/*! \brief ossaGetDeviceHandlesCB
 *
 *
 *  Purpose: This routine is called by lower layer to corresponding to
 *           saGetDeviceHandles()
 *
 *  \param   agRoot:       Pointer to chip/driver Instance.
 *  \param   agContext:    Context of the get device handle request originally passed into
 *                         saGetDeviceHandles().
 *  \param   agPortContext:Pointer to this instance of a port context
 *  \param   agDev:        Array containing pointers to the device handles

 *  \param   validDevs     Number of valid device handles
 *
 *
 *  \return None.
 *
 *  \note - The scope is shared target and initiator.
 *          For details, refer to SAS/SATA Low-Level API Specification
 */
/*****************************************************************************/
osGLOBAL void ossaGetDeviceHandlesCB(
                       agsaRoot_t           *agRoot,
                       agsaContext_t        *agContext,
                       agsaPortContext_t    *agPortContext,
                       agsaDevHandle_t      *agDev[],
                       bit32                validDevs
                       )
{
  TI_DBG2(("ossaGetDeviceHandlesCB: start\n"));
  TI_DBG2(("ossaGetDeviceHandlesCB: validDevs %d\n", validDevs));
  smTraceFuncEnter(hpDBG_VERY_LOUD,"Yc");
#ifdef TO_DO
  for (i = 0 ; i < validDevs ; i++)
  {
    agDev[i];
  }
#endif
  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Yc");
  return;
}

/*****************************************************************************/
/*! \brief ossaGetDeviceInfoCB
 *
 *
 *  Purpose: This routine is called by lower layer to corresponding to
 *           saGetDeviceInfo()
 *
 *  \param   agRoot:       Pointer to chip/driver Instance.
 *  \param   agDevHandle:  Handle of the device
 *  \param   status:       status
 *  \param   agInfo:       Pointer to the structure that describes device information
 *
 *
 *  \return None.
 *
 *  \note - The scope is shared target and initiator.
 *          For details, refer to SAS/SATA Low-Level API Specification
 */
/*****************************************************************************/
osGLOBAL void ossaGetDeviceInfoCB(
                    agsaRoot_t        *agRoot,
                    agsaContext_t     *agContext,
                    agsaDevHandle_t   *agDevHandle,
                    bit32             status,
                    void              *agInfo
                    )
{
  
#ifdef TD_DEBUG_ENABLE
  agsaDeviceInfo_t       *agDeviceInfo;
  agsaSASDeviceInfo_t    *agSASDeviceInfo;
  agsaSATADeviceInfo_t   *agSATADeviceInfo;
#endif
  smTraceFuncEnter(hpDBG_VERY_LOUD,"Yd");

  TI_DBG1(("ossaGetDeviceInfoCB: start agContext %p\n",agContext));
  switch (status)
  {
  case OSSA_DEV_INFO_INVALID_HANDLE:
    TI_DBG1(("ossaGetDeviceInfoCB: OSSA_DEV_INFO_INVALID_HANDLE\n"));
    /*ostiGetDeviceInfoIOCTLRsp(tiRoot, status, agNULL);*/
    break;
  case OSSA_DEV_INFO_NO_EXTENDED_INFO:
#ifdef TD_DEBUG_ENABLE
    agDeviceInfo = (agsaDeviceInfo_t *)agInfo;
#endif
    TI_DBG1(("ossaGetDeviceInfoCB: OSSA_DEV_INFO_NO_EXTENDED_INFO\n"));
    TI_DBG1(("ossaGetDeviceInfoCB: sasAddressHi 0x%08x\n", SA_DEVINFO_GET_SAS_ADDRESSHI(agDeviceInfo)));
    TI_DBG1(("ossaGetDeviceInfoCB: sasAddressLo 0x%08x\n", SA_DEVINFO_GET_SAS_ADDRESSLO(agDeviceInfo)));
    TI_DBG1(("ossaGetDeviceInfoCB: devType_S_Rate 0x%08x\n", agDeviceInfo->devType_S_Rate));
    TI_DBG1(("ossaGetDeviceInfoCB: firstBurstSize 0x%08x\n", agDeviceInfo->firstBurstSize));

    /*ostiPortEvent (tiRoot, tiGetDevInfo, tiSuccess,(void *)agContext );*/
    /*ostiGetDeviceInfoIOCTLRsp(tiRoot, status, agDeviceInfo);*/
    break;
  case OSSA_DEV_INFO_SAS_EXTENDED_INFO:
#ifdef TD_DEBUG_ENABLE
    agSASDeviceInfo = (agsaSASDeviceInfo_t *)agInfo;
#endif
    TI_DBG2(("ossaGetDeviceInfoCB: OSSA_DEV_INFO_SAS_EXTENDED_INFO\n"));
    TI_DBG2(("ossaGetDeviceInfoCB: sasAddressHi 0x%08x\n", SA_DEVINFO_GET_SAS_ADDRESSHI(&agSASDeviceInfo->commonDevInfo)));
    TI_DBG2(("ossaGetDeviceInfoCB: sasAddressLo 0x%08x\n", SA_DEVINFO_GET_SAS_ADDRESSLO(&agSASDeviceInfo->commonDevInfo)));
    TI_DBG2(("ossaGetDeviceInfoCB: initiator_ssp_stp_smp %d\n", agSASDeviceInfo->initiator_ssp_stp_smp));
    TI_DBG2(("ossaGetDeviceInfoCB: target_ssp_stp_smp %d\n", agSASDeviceInfo->target_ssp_stp_smp));
    TI_DBG2(("ossaGetDeviceInfoCB: numOfPhys %d\n", agSASDeviceInfo->numOfPhys));
    TI_DBG2(("ossaGetDeviceInfoCB: phyIdentifier %d\n", agSASDeviceInfo->phyIdentifier));

    break;
  case OSSA_DEV_INFO_SATA_EXTENDED_INFO:
#ifdef TD_DEBUG_ENABLE
    agSATADeviceInfo = (agsaSATADeviceInfo_t *)agInfo;
#endif
    TI_DBG2(("ossaGetDeviceInfoCB: OSSA_DEV_INFO_SATA_EXTENDED_INFO\n"));
    TI_DBG2(("ossaGetDeviceInfoCB: sasAddressHi 0x%08x\n", SA_DEVINFO_GET_SAS_ADDRESSHI(&agSATADeviceInfo->commonDevInfo)));
    TI_DBG2(("ossaGetDeviceInfoCB: sasAddressLo 0x%08x\n", SA_DEVINFO_GET_SAS_ADDRESSLO(&agSATADeviceInfo->commonDevInfo)));
    TI_DBG2(("ossaGetDeviceInfoCB: connection %d\n", agSATADeviceInfo->connection));
    TI_DBG2(("ossaGetDeviceInfoCB: portMultiplierField %d\n", agSATADeviceInfo->portMultiplierField));
    TI_DBG2(("ossaGetDeviceInfoCB: stpPhyIdentifier %d\n", agSATADeviceInfo->stpPhyIdentifier));
#ifdef TD_DEBUG_ENABLE
    tdhexdump("ossaGetDeviceInfoCB: signature", (bit8 *)agSATADeviceInfo->signature, 8);
#endif
     break;
  default:
    TI_DBG2(("ossaGetDeviceInfoCB: error default case, status is %d\n", status));
    break;
  }
  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Yd");
  return;
}

/*****************************************************************************/
/*! \brief ossaDeviceRegistrationCB
 *
 *
 *  Purpose: This routine is called by lower layer to corresponding to
 *           saRegisterNewDevice()
 *
 *  \param   agRoot:       Pointer to chip/driver Instance.
 *  \param   agContext:    Context of the get device handle request originally
 *                         passed into saRegisterNewDevice().
 *  \param   status:       status
 *  \param   agDevHandle:  Pointer to the assigned device handle for the
 *                         registered device.
 *
 *
 *  \return None.
 *
 */
/*****************************************************************************/
osGLOBAL void ossaDeviceRegistrationCB(
                         agsaRoot_t        *agRoot,
                         agsaContext_t     *agContext,
                         bit32             status,
                         agsaDevHandle_t   *agDevHandle,
                         bit32             deviceID
                         )
{
#ifdef INITIATOR_DRIVER
  tdsaRootOsData_t     *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t             *tiRoot = (tiRoot_t *)osData->tiRoot;
  tdsaRoot_t           *tdsaRoot      = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t        *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  bit32                Indenom = tdsaAllShared->QueueConfig.numInboundQueues;
  bit32                Outdenom = tdsaAllShared->QueueConfig.numOutboundQueues;
  tdsaDeviceData_t     *oneDeviceData = (tdsaDeviceData_t *)agContext->osData;
  tdsaPortContext_t    *onePortContext = oneDeviceData->tdPortContext;
  tiPortalContext_t    *tiPortalContext = onePortContext->tiPortalContext;
#ifdef FDS_DM
  dmRoot_t             *dmRoot = &(tdsaAllShared->dmRoot);
  dmPortContext_t      *dmPortContext = &(onePortContext->dmPortContext);
  dmDeviceInfo_t       dmDeviceInfo;
  bit32                DMstatus = DM_RC_FAILURE;
  bit16                ext = 0;
  bit32                expanderType = 1;
#endif

#if defined(FDS_DM) && !defined(FDS_SM)
  bit32                IDstatus;
#endif

#ifdef FDS_SM
  smRoot_t             *smRoot = &(tdsaAllShared->smRoot);
  bit32                SMstatus = SM_RC_FAILURE;
#endif
  smTraceFuncEnter(hpDBG_VERY_LOUD,"Ye");
  TI_DBG3(("ossaDeviceRegistrationCB: start status 0x%x\n",status));
  TI_DBG3(("ossaDeviceRegistrationCB: device AddrHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
  TI_DBG3(("ossaDeviceRegistrationCB: device AddrLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
  TI_DBG3(("ossaDeviceRegistrationCB: did 0x%x\n", oneDeviceData->id));
  TI_DBG3(("ossaDeviceRegistrationCB: deviceID 0x%x\n", deviceID));
  TI_DBG3(("ossaDeviceRegistrationCB: agDevHandle %p %p %p\n",agDevHandle,agDevHandle->osData,agDevHandle->sdkData ));

  /* transient period caused by tdssReportRemovals(), device was in the middle
    of registration but port is invalidated
  */
  if (oneDeviceData->valid == agFALSE && oneDeviceData->valid2 == agFALSE
      && oneDeviceData->DeviceType == TD_DEFAULT_DEVICE)
  {
    if (status == OSSA_SUCCESS)
    {
      TI_DBG2(("ossaDeviceRegistrationCB: transient, calling saDeregisterDeviceHandle, did %d\n", oneDeviceData->id));
      oneDeviceData->agDevHandle = agDevHandle;
      agDevHandle->osData = oneDeviceData;
      if (DEVICE_IS_SATA_DEVICE(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData))
      {
        if (oneDeviceData->satDevData.IDDeviceValid == agFALSE)
        {
          saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, 0);
        }
        else
        {
          saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData));
        }
      }
      else
      {
        saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData));
      }
    }
    else if (status == OSSA_FAILURE_PORT_NOT_VALID_STATE || status == OSSA_ERR_PORT_STATE_NOT_VALID)
    {
      /* do nothing */
      TI_DBG2(("ossaDeviceRegistrationCB: transient, do nothing did %d\n", oneDeviceData->id));
    }
    return;
  }

  if (agDevHandle == agNULL)
  {
    TI_DBG3(("ossaDeviceRegistrationCB: agDevHandle is NULL\n"));
  }
  else
  {
    TI_DBG3(("ossaDeviceRegistrationCB: agDevHandle is NOT NULL\n"));
  }

  switch (status)
  {
  case OSSA_SUCCESS:
    TI_DBG3(("ossaDeviceRegistrationCB: success\n"));
    TI_DBG2(("ossaDeviceRegistrationCB: Success did %d FW did 0x%x\n", oneDeviceData->id, deviceID));
    TI_DBG2(("ossaDeviceRegistrationCB: Success pid %d\n", onePortContext->id));
    if (agDevHandle == agNULL)
    {
      TI_DBG1(("ossaDeviceRegistrationCB: agDevHandle is NULL, wrong!\n"));
      return;
    }
    oneDeviceData->agDevHandle = agDevHandle;
    agDevHandle->osData = oneDeviceData;
    oneDeviceData->registered = agTRUE;
    oneDeviceData->InQID = oneDeviceData->id % Indenom;
    oneDeviceData->OutQID = oneDeviceData->id % Outdenom;
    onePortContext->RegisteredDevNums++;

    TI_DBG3(("ossaDeviceRegistrationCB: direct %d STP target %d target_ssp_stp_smp %d\n", oneDeviceData->directlyAttached, DEVICE_IS_STP_TARGET(oneDeviceData), oneDeviceData->target_ssp_stp_smp));
    TI_DBG3(("ossaDeviceRegistrationCB: pid %d registeredNumDevice %d\n", onePortContext->id, onePortContext->RegisteredDevNums));
    TI_DBG3(("ossaDeviceRegistrationCB: pid %d Count %d\n", onePortContext->id, onePortContext->Count));

#ifdef FDS_DM
    /* if device is an expander, register it to DM */
    if (onePortContext->valid == agTRUE)
    {
      if (DEVICE_IS_SMP_TARGET(oneDeviceData))
      {
        TI_DBG1(("ossaDeviceRegistrationCB: calling dmRegisterDevice\n"));
        TI_DBG1(("ossaDeviceRegistrationCB: device AddrHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi));
        TI_DBG1(("ossaDeviceRegistrationCB: device AddrLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo));
        /* set up dmDeviceInfo */
        osti_memset(&dmDeviceInfo, 0, sizeof(dmDeviceInfo_t));
        DEVINFO_PUT_SAS_ADDRESSLO(&dmDeviceInfo, oneDeviceData->SASAddressID.sasAddressLo);
        DEVINFO_PUT_SAS_ADDRESSHI(&dmDeviceInfo, oneDeviceData->SASAddressID.sasAddressHi);
        dmDeviceInfo.initiator_ssp_stp_smp = oneDeviceData->initiator_ssp_stp_smp;
        dmDeviceInfo.target_ssp_stp_smp = oneDeviceData->target_ssp_stp_smp;
        dmDeviceInfo.devType_S_Rate = oneDeviceData->agDeviceInfo.devType_S_Rate;
        if (oneDeviceData->directlyAttached == agTRUE)
        {
          /* setting SMP bit */
          ext = (bit16)(ext | 0x100);
          expanderType = SA_IDFRM_GET_DEVICETTYPE(&onePortContext->sasIDframe);
          ext = (bit16)( ext | (expanderType << 9));
          /* setting MCN field to 0xF */
          ext = (bit16)(ext | (bit16)(0xF << 11));
          TI_DBG1(("ossaDeviceRegistrationCB: directlyAttached ext 0x%x\n", ext));
          dmDeviceInfo.ext = ext;
        }
        DMstatus = dmRegisterDevice(dmRoot, dmPortContext, &dmDeviceInfo, oneDeviceData->agDevHandle);
        if (DMstatus != DM_RC_SUCCESS)
        {
          TI_DBG1(("ossaDeviceRegistrationCB: dmRegisterDevice failed!!! 0x%x\n", DMstatus));
        }
      }
    }
#endif /* FDS_DM */
#ifdef FDS_SM
    /* if device is SATA, register it to SM */
    if (onePortContext->valid == agTRUE)
    {
      if (DEVICE_IS_SATA_DEVICE(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData))
      {
        TI_DBG1(("ossaDeviceRegistrationCB: calling smRegisterDevice\n"));
        if (oneDeviceData->directlyAttached == agTRUE)
        {
          SMstatus = smRegisterDevice(smRoot,
                                      agDevHandle,
                                      &(oneDeviceData->smDeviceHandle),
                                      agNULL,
                                      (bit32)oneDeviceData->phyID,
                                      oneDeviceData->satDevData.satDeviceType);
        }
        else
        {
          if (oneDeviceData->ExpDevice == agNULL)
          {
            TI_DBG1(("ossaDeviceRegistrationCB: oneDeviceData->ExpDevice NULL!!!\n"));
            return;
          }
          if (oneDeviceData->ExpDevice->agDevHandle == agNULL)
          {
            TI_DBG1(("ossaDeviceRegistrationCB: oneDeviceData->ExpDevice->agDevHandle NULL!!!\n"));
          }
          SMstatus = smRegisterDevice(smRoot,
                                      agDevHandle,
                                      &(oneDeviceData->smDeviceHandle),
                                      oneDeviceData->ExpDevice->agDevHandle,
                                      (bit32)oneDeviceData->phyID,
                                      oneDeviceData->satDevData.satDeviceType);
        }
        if (SMstatus != SM_RC_SUCCESS)
        {
          TI_DBG1(("ossaDeviceRegistrationCB: smRegisterDevice failed!!! 0x%x\n", DMstatus));
        }
      }
    }
#endif /* FDS_SM */
    /* special case for directly attached targets */
    if (oneDeviceData->directlyAttached == agTRUE)
    {
      TI_DBG3(("ossaDeviceRegistrationCB: directly attached did %d\n", oneDeviceData->id));
      if (oneDeviceData->DeviceType == TD_SAS_DEVICE)
      {
        TI_DBG3(("ossaDeviceRegistrationCB: SAS target\n"));
        if (onePortContext->valid == agTRUE)
        {
          if (onePortContext->PortRecoverPhyID != 0xFF)
          {
            oneDeviceData->phyID = (bit8)onePortContext->PortRecoverPhyID;
            onePortContext->PortRecoverPhyID = 0xFF;
            TI_DBG3(("ossaDeviceRegistrationCB: PortRecoverPhyID %d\n", oneDeviceData->phyID));
          }
          /* link up and discovery ready event */
          if (onePortContext->DiscoveryRdyGiven == agFALSE)
          {
            TI_DBG2(("ossaDeviceRegistrationCB: link up and discovery ready\n"));
            TI_DBG3(("ossaDeviceRegistrationCB: phyID %d pid %d\n", oneDeviceData->phyID, onePortContext->id));
            TI_DBG3(("ossaDeviceRegistrationCB: tiPortalContext %p\n", tdsaAllShared->Ports[oneDeviceData->phyID].tiPortalContext));
            TI_DBG3(("ossaDeviceRegistrationCB: onePortContext->tiPortalContext %p\n", onePortContext->tiPortalContext));
            onePortContext->DiscoveryRdyGiven = agTRUE;
            if (onePortContext->DiscoveryState != ITD_DSTATE_NOT_STARTED)
            {
              TI_DBG1(("ossaDeviceRegistrationCB: wrong discovery state 0x%x\n", onePortContext->DiscoveryState));
            }
            /* notifying link up */
            ostiPortEvent (
                           tiRoot,
                           tiPortLinkUp,
                           tiSuccess,
                           (void *)onePortContext->tiPortalContext
                           );
#ifdef INITIATOR_DRIVER
            /* triggers discovery */
            ostiPortEvent(
                          tiRoot,
                          tiPortDiscoveryReady,
                          tiSuccess,
                          (void *)onePortContext->tiPortalContext
                          );
#endif
          }
        }
        else
        {
          TI_DBG2(("ossaDeviceRegistrationCB: abort call\n"));
          /* abort all followed by deregistration of sas target */
          tdsaAbortAll(tiRoot, agRoot, oneDeviceData);
        }
      }
      else
      {
        TI_DBG2(("ossaDeviceRegistrationCB: SATA target\n"));
        if (onePortContext->valid == agTRUE)
        {
          if (oneDeviceData->satDevData.IDDeviceValid == agFALSE)
          {
#ifdef FDS_SM
            /* send identify device data */
            tdIDStart(tiRoot, agRoot, smRoot, oneDeviceData, onePortContext);

#else
            /* send identify device data */
            tdssSubAddSATAToSharedcontext(tiRoot, oneDeviceData);
#endif
          }
        }
        else
        {
          TI_DBG2(("ossaDeviceRegistrationCB: abort call\n"));
          /* abort all followed by deregistration of sas target */
          tdsaAbortAll(tiRoot, agRoot, oneDeviceData);
        }
      }
    }
    else /* behind the expander */
    {
#if defined(FDS_DM) && defined(FDS_SM)
      /* send ID to SATA targets
         needs go allocate tdIORequestBody_t for smIORequest
      */

      if ( (DEVICE_IS_SATA_DEVICE(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData))
          &&
          oneDeviceData->satDevData.IDDeviceValid == agFALSE)
      {
        tdIDStart(tiRoot, agRoot, smRoot, oneDeviceData, onePortContext);
      }

#elif defined(FDS_DM) /* worked with DM */
      if ( (DEVICE_IS_SATA_DEVICE(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData))
          &&
          oneDeviceData->satDevData.IDDeviceValid == agFALSE)
      {
         IDstatus = tdsaDiscoveryStartIDDev(tiRoot,
                                         agNULL,
                                         &(oneDeviceData->tiDeviceHandle),
                                         agNULL,
                                         oneDeviceData);

        if (IDstatus != tiSuccess)
        {
          /* identify device data is not valid */
          TI_DBG1(("ossaDeviceRegistrationCB: fail or busy %d\n", IDstatus));
          oneDeviceData->satDevData.IDDeviceValid = agFALSE;
        }
      }
#endif


   }
    /* after discovery is finished */
    if (onePortContext->DiscoveryState == ITD_DSTATE_COMPLETED)
    {
      TI_DBG2(("ossaDeviceRegistrationCB: calling new device arrival\n"));
      if (DEVICE_IS_SSP_TARGET(oneDeviceData))
      {
        /* in case registration is finished after discovery is finished */
#ifdef AGTIAPI_CTL
        if (tdsaAllShared->SASConnectTimeLimit)
          tdsaCTLSet(tiRoot, onePortContext, tiIntrEventTypeDeviceChange,
                     tiDeviceArrival);
        else
#endif
          ostiInitiatorEvent(
                             tiRoot,
                             tiPortalContext,
                             agNULL,
                             tiIntrEventTypeDeviceChange,
                             tiDeviceArrival,
                             agNULL
                             );
      }
      else if ( (DEVICE_IS_SATA_DEVICE(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData))
                &&
                oneDeviceData->satDevData.IDDeviceValid == agTRUE )
      {
        /* in case registration is finished after discovery is finished */
        ostiInitiatorEvent(
                           tiRoot,
                           tiPortalContext,
                           agNULL,
                           tiIntrEventTypeDeviceChange,
                           tiDeviceArrival,
                           agNULL
                           );
      }
    }
    break;
  case OSSA_FAILURE_OUT_OF_RESOURCE: /* fall through */
  case OSSA_ERR_DEVICE_HANDLE_UNAVAILABLE:
    TI_DBG1(("ossaDeviceRegistrationCB: OSSA_FAILURE_OUT_OF_RESOURCE or OSSA_ERR_DEVICE_HANDLE_UNAVAILABLE\n"));
    oneDeviceData->registered = agFALSE;
    break;
  case OSSA_FAILURE_DEVICE_ALREADY_REGISTERED: /* fall through */
  case OSSA_ERR_DEVICE_ALREADY_REGISTERED:
    /* do nothing */
    TI_DBG1(("ossaDeviceRegistrationCB: OSSA_FAILURE_DEVICE_ALREADY_REGISTERED or OSSA_ERR_DEVICE_ALREADY_REGISTERED\n"));
    break;
  case OSSA_FAILURE_INVALID_PHY_ID: /* fall through */
  case OSSA_ERR_PHY_ID_INVALID:
    TI_DBG1(("ossaDeviceRegistrationCB: OSSA_FAILURE_INVALID_PHY_ID or OSSA_ERR_PHY_ID_INVALID\n"));
    oneDeviceData->registered = agFALSE;
    break;
  case OSSA_FAILURE_PHY_ID_ALREADY_REGISTERED: /* fall through */
  case OSSA_ERR_PHY_ID_ALREADY_REGISTERED:
    /* do nothing */
    TI_DBG1(("ossaDeviceRegistrationCB: OSSA_FAILURE_PHY_ID_ALREADY_REGISTERED or OSSA_ERR_PHY_ID_ALREADY_REGISTERED\n"));
    break;
  case OSSA_FAILURE_PORT_ID_OUT_OF_RANGE: /* fall through */
  case OSSA_ERR_PORT_INVALID:
    TI_DBG1(("ossaDeviceRegistrationCB: OSSA_FAILURE_PORT_ID_OUT_OF_RANGE or OSSA_ERR_PORT_INVALID\n"));
    oneDeviceData->registered = agFALSE;
    break;
  case OSSA_FAILURE_PORT_NOT_VALID_STATE: /* fall through */
  case OSSA_ERR_PORT_STATE_NOT_VALID:
    TI_DBG1(("ossaDeviceRegistrationCB: OSSA_FAILURE_PORT_NOT_VALID_STATE or OSSA_ERR_PORT_STATE_NOT_VALID\n"));
    TI_DBG2(("ossaDeviceRegistrationCB: did %d pid %d\n", oneDeviceData->id, onePortContext->id));
    oneDeviceData->registered = agFALSE;
    /* transient period between link up and link down/port recovery */
    onePortContext->Transient = agTRUE;
    if (onePortContext->valid == agTRUE && (oneDeviceData->valid == agTRUE || oneDeviceData->valid2 == agTRUE))
    {
      TI_DBG1(("ossaDeviceRegistrationCB: retries regisration\n"));
#ifdef REMOVED
      //temp; setting MCN to tdsaAllShared->MCN
      oneDeviceData->agDeviceInfo.flag = oneDeviceData->agDeviceInfo.flag | (tdsaAllShared->MCN << 16);
      //end temp
#endif
      saRegisterNewDevice( /* ossaDeviceRegistrationCB */
                          agRoot,
                          &oneDeviceData->agContext,
                          0,
                          &oneDeviceData->agDeviceInfo,
                          onePortContext->agPortContext,
                          0
                         );
    }
    else if (oneDeviceData->directlyAttached == agTRUE && DEVICE_IS_SATA_DEVICE(oneDeviceData))
    {
      TI_DBG1(("ossaDeviceRegistrationCB: directly attached SATA, put back into free list\n"));
      tdsaDeviceDataReInit(tiRoot, oneDeviceData);
      tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK);
      TDLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->FreeLink), &(tdsaAllShared->FreeDeviceList));
      tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
    }
    break;
  case OSSA_FAILURE_DEVICE_TYPE_NOT_VALID: /* fall through */
  case OSSA_ERR_DEVICE_TYPE_NOT_VALID:
    TI_DBG1(("ossaDeviceRegistrationCB: OSSA_FAILURE_DEVICE_TYPE_NOT_VALID or OSSA_ERR_DEVICE_TYPE_NOT_VALID\n"));
    oneDeviceData->registered = agFALSE;
    break;
  default:
    TI_DBG1(("ossaDeviceRegistrationCB: wrong. default status is %d\n", status));
    break;


    }
  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Ye");
  return;
#endif
}

/*****************************************************************************/
/*! \brief ossaDeregisterDeviceHandleCB
 *
 *
 *  Purpose: This routine is called by lower layer to corresponding to
 *           saDeregisterDeviceHandle()
 *
 *  \param   agRoot:       Pointer to chip/driver Instance.
 *  \param   agDevHandle:  Pointer to the assigned device handle for the
 *                         registered device.
 *  \param   status:       status
 *
 *
 *  \return None.
 *
 */
/*****************************************************************************/
osGLOBAL void ossaDeregisterDeviceHandleCB(
                             agsaRoot_t          *agRoot,
                             agsaContext_t       *agContext,
                             agsaDevHandle_t     *agDevHandle,
                             bit32               status
                             )
{
  tdsaRootOsData_t     *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t             *tiRoot = (tiRoot_t *)osData->tiRoot;
  tdsaRoot_t           *tdsaRoot      = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t        *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  tdsaDeviceData_t     *oneDeviceData = agNULL;
  tdsaPortContext_t    *onePortContext = agNULL;
  agsaEventSource_t    *eventSource;
  bit32                HwAckSatus;
  bit32                PhyID;
#ifdef FDS_DM
  dmRoot_t             *dmRoot = &(tdsaAllShared->dmRoot);
  dmPortContext_t      *dmPortContext = agNULL;
  dmPortInfo_t         dmPortInfo;
  bit32                DMstatus = DM_RC_FAILURE;
#endif
#ifdef FDS_SM
  smRoot_t             *smRoot = &(tdsaAllShared->smRoot);
#endif

  TI_DBG3(("ossaDeregisterDeviceHandleCB: start\n"));
  smTraceFuncEnter(hpDBG_VERY_LOUD,"Yf");

  if (status == OSSA_ERR_DEVICE_HANDLE_INVALID)
  {
    /* there is no device handle to process */
    TI_DBG2(("ossaDeregisterDeviceHandleCB: OSSA_ERR_DEVICE_HANDLE_INVALID\n"));
    return;
  }

  oneDeviceData = (tdsaDeviceData_t *)agDevHandle->osData;
  onePortContext = oneDeviceData->tdPortContext;
#ifdef FDS_DM
  dmPortContext = &(onePortContext->dmPortContext);
#endif

  if (oneDeviceData->valid == agFALSE && oneDeviceData->valid2 == agFALSE &&
      oneDeviceData->DeviceType == TD_DEFAULT_DEVICE && onePortContext->valid == agTRUE)
  {
    TI_DBG2(("ossaDeregisterDeviceHandleCB: transient did %d\n", oneDeviceData->id));
    return;
  }

  if (onePortContext != agNULL)
  {
    TI_DBG2(("ossaDeregisterDeviceHandleCB: pid %d registeredNumDevice %d\n", onePortContext->id, onePortContext->RegisteredDevNums));
  }

  switch (status)
  {
  case OSSA_SUCCESS:
    TI_DBG3(("ossaDeregisterDeviceHandleCB: Success\n"));
    if (onePortContext == agNULL)
    {
      TI_DBG1(("ossaDeregisterDeviceHandleCB: onePortContext is NULL, wrong!\n"));
      return;
    }
    /* port is going down */
    if (onePortContext->valid == agFALSE)
    {
      if (!(oneDeviceData->valid == agFALSE && oneDeviceData->valid2 == agFALSE && oneDeviceData->DeviceType == TD_DEFAULT_DEVICE))
      {
        /* remove oneDevice from MainLink */
        TI_DBG2(("ossaDeregisterDeviceHandleCB: delete from MainLink\n"));
#ifdef FDS_SM
        if (DEVICE_IS_SATA_DEVICE(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData))
        {
          TI_DBG1(("ossaDeregisterDeviceHandleCB: did %d calling smDeregisterDevice\n", oneDeviceData->id));
          smDeregisterDevice(smRoot, oneDeviceData->agDevHandle, &(oneDeviceData->smDeviceHandle));
        }
#endif
        tdsaDeviceDataReInit(tiRoot, oneDeviceData);
        osti_memset(&(oneDeviceData->satDevData.satIdentifyData), 0xFF, sizeof(agsaSATAIdentifyData_t));

        tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK);
        TDLIST_DEQUEUE_THIS(&(oneDeviceData->MainLink));
        TDLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->FreeLink), &(tdsaAllShared->FreeDeviceList));
        tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
      }
      /* for portcontext */
      PhyID = onePortContext->eventPhyID;
      TI_DBG3(("ossaDeregisterDeviceHandleCB: PhyID %d\n", PhyID));
      onePortContext->RegisteredDevNums--;
      /*
        check if valid in tdsaAllShared and the last registered device in a portcontext;
        if so, call saHwEventAck()
       */
      if (tdsaAllShared->eventSource[PhyID].EventValid == agTRUE &&
          onePortContext->RegisteredDevNums == 0 &&
          PhyID != 0xFF
          )
      {
        TI_DBG2(("ossaDeregisterDeviceHandleCB: calling saHwEventAck\n"));
        eventSource = &(tdsaAllShared->eventSource[PhyID].Source);
        HwAckSatus = saHwEventAck(
                                  agRoot,
                                  agNULL, /* agContext */
                                  0,
                                  eventSource, /* agsaEventSource_t */
                                  0,
                                  0
                                  );
        if ( HwAckSatus != AGSA_RC_SUCCESS)
        {
          TI_DBG1(("ossaDeregisterDeviceHandleCB: failing in saHwEventAck; status %d\n", HwAckSatus));
        }

        /* toggle */
        tdsaAllShared->eventSource[PhyID].EventValid = agFALSE;

#ifdef FDS_DM
        if (onePortContext->UseDM == agTRUE)
        {
          TI_DBG1(("ossaDeregisterDeviceHandleCB: calling dmDestroyPort\n"));
          /* setup dmPortInfo */
          PORTINFO_PUT_SAS_REMOTE_ADDRESSLO(&dmPortInfo, onePortContext->sasRemoteAddressLo);
          PORTINFO_PUT_SAS_REMOTE_ADDRESSHI(&dmPortInfo, onePortContext->sasRemoteAddressHi);
          PORTINFO_PUT_SAS_LOCAL_ADDRESSLO(&dmPortInfo, onePortContext->sasLocalAddressLo);
          PORTINFO_PUT_SAS_LOCAL_ADDRESSHI(&dmPortInfo, onePortContext->sasLocalAddressHi);
          DMstatus = dmDestroyPort(dmRoot, dmPortContext, &dmPortInfo);
          if (DMstatus != DM_RC_SUCCESS)
          {
             TI_DBG1(("ossaDeregisterDeviceHandleCB: dmDestroyPort failed!!! 0x%x\n", DMstatus));
          }
        }
#endif
        tdsaPortContextReInit(tiRoot, onePortContext);
        /*
          put all devices belonging to the onePortContext
          back to the free link
        */

        tdsaSingleThreadedEnter(tiRoot, TD_PORT_LOCK);
        TDLIST_DEQUEUE_THIS(&(onePortContext->MainLink));
        TDLIST_ENQUEUE_AT_TAIL(&(onePortContext->FreeLink), &(tdsaAllShared->FreePortContextList));
        tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
      }
      else if (tdsaAllShared->eventSource[PhyID].EventValid == NO_ACK &&
               onePortContext->RegisteredDevNums == 0
              )
      {
        TI_DBG2(("ossaDeregisterDeviceHandleCB: NO ACK case\n"));
#ifdef FDS_DM
        if (onePortContext->UseDM == agTRUE)
        {
          TI_DBG1(("ossaDeregisterDeviceHandleCB: calling dmDestroyPort\n"));
          /* setup dmPortInfo */
          PORTINFO_PUT_SAS_REMOTE_ADDRESSLO(&dmPortInfo, onePortContext->sasRemoteAddressLo);
          PORTINFO_PUT_SAS_REMOTE_ADDRESSHI(&dmPortInfo, onePortContext->sasRemoteAddressHi);
          PORTINFO_PUT_SAS_LOCAL_ADDRESSLO(&dmPortInfo, onePortContext->sasLocalAddressLo);
          PORTINFO_PUT_SAS_LOCAL_ADDRESSHI(&dmPortInfo, onePortContext->sasLocalAddressHi);
          DMstatus = dmDestroyPort(dmRoot, dmPortContext, &dmPortInfo);
          if (DMstatus != DM_RC_SUCCESS)
          {
            TI_DBG1(("ossaDeregisterDeviceHandleCB: dmDestroyPort failed!!! 0x%x\n", DMstatus));
          }
        }
#endif
        tdsaPortContextReInit(tiRoot, onePortContext);
        /*
          put all devices belonging to the onePortContext
          back to the free link
        */

        tdsaSingleThreadedEnter(tiRoot, TD_PORT_LOCK);
        TDLIST_DEQUEUE_THIS(&(onePortContext->MainLink));
        TDLIST_ENQUEUE_AT_TAIL(&(onePortContext->FreeLink), &(tdsaAllShared->FreePortContextList));
        tdsaSingleThreadedLeave(tiRoot, TD_PORT_LOCK);
      }
      else
      {
        if (PhyID < TD_MAX_NUM_PHYS)
        {
          TI_DBG3(("ossaDeregisterDeviceHandleCB: pid %d eventvalid %d registeredNumDevice %d\n", onePortContext->id, tdsaAllShared->eventSource[PhyID].EventValid , onePortContext->RegisteredDevNums));
        }
        else
        {
          TI_DBG3(("ossaDeregisterDeviceHandleCB: pid %d registeredNumDevice %d wrong phyid %d\n", onePortContext->id, onePortContext->RegisteredDevNums, PhyID));
        }
      }
    }
    else
    {
      PhyID = onePortContext->eventPhyID;
      TI_DBG3(("ossaDeregisterDeviceHandleCB: PhyID %d\n", PhyID));
      onePortContext->RegisteredDevNums--;
#ifdef FDS_SM
      oneDeviceData->satDevData.IDDeviceValid = agFALSE;
      if (DEVICE_IS_SATA_DEVICE(oneDeviceData) || DEVICE_IS_STP_TARGET(oneDeviceData))
      {
        smDeregisterDevice(smRoot, oneDeviceData->agDevHandle, &(oneDeviceData->smDeviceHandle));
      }
#endif
      /*
        check if valid in tdsaAllShared and the last registered device in a portcontext;
        if so, call saHwEventAck()
      */
      if (tdsaAllShared->eventSource[PhyID].EventValid == agTRUE &&
          onePortContext->RegisteredDevNums == 0 &&
          PhyID != 0xFF
          )
      {
        TI_DBG2(("ossaDeregisterDeviceHandleCB: calling saHwEventAck\n"));
        eventSource = &(tdsaAllShared->eventSource[PhyID].Source);
        HwAckSatus = saHwEventAck(
                                  agRoot,
                                  agNULL, /* agContext */
                                  0,
                                  eventSource, /* agsaEventSource_t */
                                  0,
                                  0
                                  );
        if ( HwAckSatus != AGSA_RC_SUCCESS)
        {
          TI_DBG1(("ossaDeregisterDeviceHandleCB: failing in saHwEventAck; status %d\n", HwAckSatus));
        }

        /* toggle */
        tdsaAllShared->eventSource[PhyID].EventValid = agFALSE;
      }
#ifdef INITIATOR_DRIVER
      else if (onePortContext->RegisteredDevNums == 1)
      {
        TI_DBG1(("ossaDeregisterDeviceHandleCB: all devices have been deregistered except directly attached EXP\n"));
        /* qqqqq If broadcast has been seen, call incremental discovery*/
        if (onePortContext->DiscFailNSeenBC == agTRUE)
        {
          TI_DBG1(("ossaDeregisterDeviceHandleCB: calling dmDiscover, incremental, pid %d\n", onePortContext->id));
          dmDiscover(dmRoot, dmPortContext, DM_DISCOVERY_OPTION_INCREMENTAL_START);
          onePortContext->DiscFailNSeenBC = agFALSE;
        }
        else
        {
          TI_DBG1(("ossaDeregisterDeviceHandleCB: not calling dmDiscover\n"));
          /* qqqqq needs to change discovery state to onePortContext->DMDiscoveryState == dmDiscCompleted
             in dmQueryDiscovery
             change the discovery state from dmDiscFailed to dmDiscCompleted
          */
          dmResetFailedDiscovery(dmRoot, dmPortContext);

        }
      }
#endif
      else
      {
        if (PhyID < TD_MAX_NUM_PHYS)
        {
          TI_DBG3(("ossaDeregisterDeviceHandleCB: pid %d eventvalid %d registeredNumDevice %d\n", onePortContext->id, tdsaAllShared->eventSource[PhyID].EventValid , onePortContext->RegisteredDevNums));
        }
        else
        {
          TI_DBG3(("ossaDeregisterDeviceHandleCB: pid %d registeredNumDevice %d wrong phyid %d\n", onePortContext->id, onePortContext->RegisteredDevNums, PhyID));
        }
      }
    }
    break;
  case OSSA_INVALID_HANDLE:
    TI_DBG1(("ossaDeregisterDeviceHandleCB: OSSA_INVALID_HANDLE\n"));
    break;
#ifdef REMOVED
  case OSSA_FAILURE_DEVICE_DIRECT_ATTACH:
    TI_DBG1(("ossaDeregisterDeviceHandleCB: OSSA_FAILURE_DEVICE_DIRECT_ATTACH\n"));
    break;
#endif
  case OSSA_ERR_DEVICE_HANDLE_INVALID:
    TI_DBG1(("ossaDeregisterDeviceHandleCB: OSSA_ERR_DEVICE_HANDLE_INVALID\n"));
    break;
  case OSSA_ERR_DEVICE_BUSY:
    TI_DBG1(("ossaDeregisterDeviceHandleCB: OSSA_ERR_DEVICE_BUSY\n"));
    break;
  default:
    TI_DBG1(("ossaDeregisterDeviceHandleCB: unknown status 0x%x\n", status));
    break;
  }

  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Yf");
  return;
}

/*****************************************************************************/
/*! \brief ossaDeviceHandleRemovedEvent
 *
 *
 *  Purpose: This routine is called by lower layer to notify the device removal
 *
 *
 *  \param   agRoot:       Pointer to chip/driver Instance.
 *  \param   agDevHandle:  Pointer to the assigned device handle for the
 *                         registered device.
 *  \param   agPortContext:Pointer to this instance of port context.
 *
 *
 *  \return None.
 *
 */
/*****************************************************************************/
osGLOBAL void ossaDeviceHandleRemovedEvent (
                                agsaRoot_t        *agRoot,
                                agsaDevHandle_t   *agDevHandle,
                                agsaPortContext_t *agPortContext
                                )
{
#ifdef NOT_YET
  tdsaRootOsData_t  *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t          *tiRoot = (tiRoot_t *)osData->tiRoot;
#endif
  tdsaPortContext_t *onePortContext = agNULL;
  tdsaDeviceData_t  *oneDeviceData = (tdsaDeviceData_t *)agDevHandle->osData;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"Yg");
  TI_DBG2(("ossaDeviceHandleRemovedEvent: start\n"));
  if (oneDeviceData == agNULL)
  {
    TI_DBG1(("ossaDeviceHandleRemovedEvent: Wrong! oneDeviceData is NULL\n"));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Yg");
    return;
  }
  TI_DBG2(("ossaDeviceHandleRemovedEvent: did %d\n", oneDeviceData->id));
  oneDeviceData->registered = agFALSE;
  onePortContext  = (tdsaPortContext_t *)agPortContext->osData;
  if (onePortContext == agNULL)
  {
    TI_DBG1(("ossaDeviceHandleRemovedEvent: Wrong! onePortContext is NULL\n"));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "Yg");
    return;
  }
  TI_DBG2(("ossaDeviceHandleRemovedEvent: pid %d\n", onePortContext->id));
  onePortContext->RegisteredDevNums--;
#ifdef NOT_YET
  ostiInitiatorEvent(
                     tiRoot,
                     onePortContext->tiPortalContext,
                     agNULL,
                     tiIntrEventTypeDeviceChange,
                     tiDeviceRemoval,
                     agNULL
                     );
#endif

  smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "Yg");
  return;
}

#ifdef SPC_ENABLE_PROFILE
/*****************************************************************************/
/*! \brief ossaFwProfileCB
 *
 *
 *  Purpose: This routine is called by lower layer to corresponding to
 *           saFwProfile()
 *
 *  \param   agRoot:       Pointer to chip/driver Instance.
 *  \param   agContext:    Context of the operation originally passed
 *                         into saFwProfile()
 *  \param   status:       status
 *
 *
 *  \return None.
 *
 */
/*****************************************************************************/
osGLOBAL void ossaFwProfileCB(
                    agsaRoot_t          *agRoot,
                    agsaContext_t       *agContext,
                    bit32                status,
                    bit32                len)
{
  tdsaRootOsData_t    *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t            *tiRoot = (tiRoot_t *)osData->tiRoot;

  TI_DBG2(("ossaFwProfileCB: start\n"));

  switch (status)
  {
    case AGSA_RC_SUCCESS:
    {
      TI_DBG2(("ossaFwProfileCB: SUCCESS\n"));
      break;
    }
    case AGSA_RC_FAILURE:
    {
      TI_DBG1(("ossaFwProfileCB: FAIL\n"));
      break;
    }
    default:
    {
      TI_DBG1(("ossaFwProfileCB: !!! default, status %d\n", status));
      break;
    }
  }

  ostiFWProfileIOCTLRsp(tiRoot, status, len);
  return;
}
#endif
/*****************************************************************************/
/*! \brief ossaFwFlashUpdateCB
 *
 *
 *  Purpose: This routine is called by lower layer to corresponding to
 *           saFwFlashUpdate()
 *
 *  \param   agRoot:       Pointer to chip/driver Instance.
 *  \param   agContext:    Context of the operation originally passed
 *                         into saFwFlashUpdate()
 *  \param   status:       status
 *
 *
 *  \return None.
 *
 */
/*****************************************************************************/
osGLOBAL void ossaFwFlashUpdateCB(
                    agsaRoot_t          *agRoot,
                    agsaContext_t       *agContext,
                    bit32               status
                    )
{
  tdsaRootOsData_t    *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t            *tiRoot = (tiRoot_t *)osData->tiRoot;

  TI_DBG2(("ossaFwFlashUpdateCB: start\n"));

  smTraceFuncEnter(hpDBG_VERY_LOUD,"Yh");
  switch (status)
  {
  case OSSA_FLASH_UPDATE_COMPLETE_PENDING_REBOOT:
  {
    TI_DBG2(("ossaFwFlashUpdateCB: OSSA_FLASH_UPDATE_COMPLETE_PENDING_REBOOT\n"));
    break;
  }
  case OSSA_FLASH_UPDATE_IN_PROGRESS:
  {
    TI_DBG2(("ossaFwFlashUpdateCB: OSSA_FLASH_UPDATE_IN_PROGRESS\n"));
    break;
  }
  case OSSA_FLASH_UPDATE_HDR_ERR:
  {
    TI_DBG1(("ossaFwFlashUpdateCB: OSSA_FLASH_UPDATE_HDR_ERR\n"));
    break;
  }
  case OSSA_FLASH_UPDATE_OFFSET_ERR:
  {
    TI_DBG1(("ossaFwFlashUpdateCB: OSSA_FLASH_UPDATE_OFFSET_ERR\n"));
    break;
  }
  case OSSA_FLASH_UPDATE_CRC_ERR:
  {
    TI_DBG1(("ossaFwFlashUpdateCB: OSSA_FLASH_UPDATE_CRC_ERR\n"));
    break;
  }
  case OSSA_FLASH_UPDATE_LENGTH_ERR:
  {
    TI_DBG1(("ossaFwFlashUpdateCB: OSSA_FLASH_UPDATE_LENGTH_ERR\n"));
    break;
  }
  case OSSA_FLASH_UPDATE_HW_ERR:
  {
    TI_DBG1(("ossaFwFlashUpdateCB: OSSA_FLASH_UPDATE_HW_ERR\n"));
    break;
  }
  case OSSA_FLASH_UPDATE_DNLD_NOT_SUPPORTED:
  {
    TI_DBG1(("ossaFwFlashUpdateCB: OSSA_FLASH_UPDATE_DNLD_NOT_SUPPORTED\n"));
    break;
  }
  case OSSA_FLASH_UPDATE_DISABLED:
  {
    TI_DBG1(("ossaFwFlashUpdateCB: OSSA_FLASH_UPDATE_DISABLED\n"));
    break;
  }
  case OSSA_FLASH_FWDNLD_DEVICE_UNSUPPORT:
  {
    TI_DBG1(("ossaFwFlashUpdateCB: OSSA_FLASH_FWDNLD_DEVICE_UNSUPPORT\n"));
    break;
  }
  case OSSA_MPI_ERR_IO_RESOURCE_UNAVAILABLE:
  {
    TI_DBG1(("ossaFwFlashUpdateCB: OSSA_MPI_ERR_IO_RESOURCE_UNAVAILABLE\n"));
    break;
  }
  case OSSA_FLASH_UPDATE_HMAC_ERR:
  {
    TI_DBG1(("ossaFwFlashUpdateCB: OSSA_FLASH_UPDATE_HMAC_ERR\n"));
    break;
  }

  default:
  {
    TI_DBG1(("ossaFwFlashUpdateCB: !!! default, status 0x%X\n", status));
    break;
  }
  }

  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Yh");
  ostiCOMMgntIOCTLRsp(tiRoot, status);
  return;

}


GLOBAL void   ossaFlashExtExecuteCB(
                      agsaRoot_t               *agRoot,
                      agsaContext_t            *agContext,
                      bit32                    status,
                      bit32                    command,
                      agsaFlashExtResponse_t  *agFlashExtRsp)
{
    TI_DBG1(("ossaFlashExtExecuteCB: command  0x%X status 0x%X\n",command, status));

}



/*****************************************************************************/
/*! \brief ossaGetNVMDResponseCB
 *
 *
 *  Purpose: This routine is called by lower layer to corresponding to
 *           saGetNVMDCommand()
 *
 *  \param   agRoot:           Pointer to chip/driver Instance.
 *  \param   agContext:        Context of the operation originally passed
 *                             into saGetVPDCommand()
 *  \param   status:           status
 *  \param   indirectPayload:  The value passed in agsaNVMDData_t when
 *                             calling saGetNVMDCommand()
 *  \param   agInfoLen:        the length of VPD information
 *  \param   agFrameHandle:    handler of VPD information
 *
 *
 *  \return None.
 *
 */
/*****************************************************************************/
osGLOBAL void ossaGetNVMDResponseCB(
                      agsaRoot_t                    *agRoot,
                      agsaContext_t                 *agContext,
                      bit32                         status,
                      bit8                          indirectPayload,
                      bit32                         agInfoLen,
                      agsaFrameHandle_t             agFrameHandle
)
{
  tdsaRootOsData_t    *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t            *tiRoot = (tiRoot_t *)osData->tiRoot;
  TI_DBG2(("ossaGetNVMDResponseCB: start\n"));
  TI_DBG2(("ossaGetNVMDResponseCB: agInfoLen %d\n", agInfoLen));
  smTraceFuncEnter(hpDBG_VERY_LOUD,"Yi");

  if (status == OSSA_SUCCESS)
  {
    TI_DBG2(("ossaGetNVMDResponseCB: Success status\n"));
    if (indirectPayload == 0 && agInfoLen != 0)
    {
      TI_DBG2(("ossaGetNVMDResponseCB: direct\n"));
      tdhexdump("ossaGetNVMDResponseCB", (bit8 *)agFrameHandle, agInfoLen);
    }
  }
  else
  {
    TI_DBG1(("ossaGetNVMDResponseCB: Status 0x%x\n", status));
  }

  if (indirectPayload == 0)
  {
    TI_DBG2(("ossaGetNVMDResponseCB: direct\n"));
  }
  else
  {
    TI_DBG2(("ossaGetNVMDResponseCB: indirect\n"));
  }

  ostiGetNVMDIOCTLRsp(tiRoot, status);
  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Yi");
  return;
}


/*****************************************************************************/
/*! \brief ossaSetNVMDResponseCB
 *
 *
 *  Purpose: This routine is called by lower layer to corresponding to
 *           saSetNVMDCommand()
 *
 *  \param   agRoot:       Pointer to chip/driver Instance.
 *  \param   agContext:    Context of the operation originally passed
 *                         into saSetVPDCommand()
 *  \param   status:       status
 *
 *
 *  \return None.
 *
 */
/*****************************************************************************/
osGLOBAL void ossaSetNVMDResponseCB(
                      agsaRoot_t            *agRoot,
                      agsaContext_t         *agContext,
                      bit32                 status
                      )
{
  tdsaRootOsData_t    *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t            *tiRoot = (tiRoot_t *)osData->tiRoot;
  TI_DBG2(("ossaSetNVMDResponseCB: start\n"));
  smTraceFuncEnter(hpDBG_VERY_LOUD,"Yj");
  if (status == OSSA_SUCCESS)
  {
    TI_DBG2(("ossaSetNVMDResponseCB: success\n"));
  }
  else
  {
    TI_DBG1(("ossaSetNVMDResponseCB: fail or undefined staus %d\n", status));
  }
  ostiSetNVMDIOCTLRsp(tiRoot, status);
  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Yj");
  return;
}


#ifdef REMOVED
/*****************************************************************************/
/*! \brief ossaGetVPDResponseCB
 *
 *
 *  Purpose: This routine is called by lower layer to corresponding to
 *           saGetVPDCommand()
 *
 *  \param   agRoot:       Pointer to chip/driver Instance.
 *  \param   agContext:    Context of the operation originally passed
 *                         into saGetVPDCommand()
 *  \param   status:       status
 *  \param   agInfoLen:    the length of VPD information
 *  \param   agFrameHandle:handler of VPD information
 *
 *
 *  \return None.
 *
 */
/*****************************************************************************/
osGLOBAL void ossaGetVPDResponseCB(
                     agsaRoot_t         *agRoot,
                     agsaContext_t      *agContext,
                     bit32              status,
                     bit8               indirectMode,
                     bit32              agInfoLen,
                     agsaFrameHandle_t  agFrameHandle
                     )
{
  bit8 VPDData[48];

  TI_DBG2(("ossaGetVPDResponseCB: start\n"));

  smTraceFuncEnter(hpDBG_VERY_LOUD,"Yk");
  if (status == OSSA_SUCCESS)
  {
    TI_DBG2(("ossaGetVPDResponseCB: agInfoLen %d\n", agInfoLen));
    osti_memset(VPDData, 0, 48);
    /* We can read only in case of Direct */
    saFrameReadBlock(agRoot, agFrameHandle, 0, VPDData, agInfoLen);
    tdhexdump("ossaGetVPDResponseCB", (bit8 *)VPDData, agInfoLen);
    /*
      callback osti....
    */
  }
  else
  {
    TI_DBG1(("ossaGetVPDResponseCB: fail or undefined staus %d\n", status));
  }
  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Yk");
  return;
}


/*****************************************************************************/
/*! \brief ossaSetVPDResponseCB
 *
 *
 *  Purpose: This routine is called by lower layer to corresponding to
 *           saSetVPDCommand()
 *
 *  \param   agRoot:       Pointer to chip/driver Instance.
 *  \param   agContext:    Context of the operation originally passed
 *                         into saSetVPDCommand()
 *  \param   status:       status
 *
 *
 *  \return None.
 *
 */
/*****************************************************************************/
osGLOBAL void ossaSetVPDResponseCB(
                     agsaRoot_t         *agRoot,
                     agsaContext_t      *agContext,
                     bit32              status
                     )
{
  tdsaRootOsData_t    *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t            *tiRoot = (tiRoot_t *)osData->tiRoot;

  TI_DBG2(("ossaSetVPDResponseCB: start\n"));
  smTraceFuncEnter(hpDBG_VERY_LOUD,"Yl");

  if (status == OSSA_SUCCESS)
  {
    TI_DBG2(("ossaSetVPDResponseCB: success\n"));
    ostiCOMMgntVPDSetIOCTLRsp(tiRoot, 0);
    /*
      callback osti.....
    */

#ifdef VPD_TESTING
    /* temporary to test saSetVPDCommand() and saGetVPDCommand */
    tdsaVPDGet(tiRoot);
#endif

  }
  else
  {
    TI_DBG1(("ossaSetVPDResponseCB: fail or undefined staus %d\n", status));
  }
  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Yl");
  return;
}
#endif

/*****************************************************************************/
/*! \brief ossaEchoCB
 *
 *
 *  Purpose: This routine is called by lower layer to corresponding to
 *           saEchoCommand()
 *
 *  \param   agRoot:        Pointer to chip/driver Instance.
 *  \param   agContext:     Context of the operation originally passed
 *                          into saEchoCommand()
 *  \param   echoPayload:   Pointer to the echo payload
 *
 *
 *  \return None.
 *
 */
/*****************************************************************************/
osGLOBAL void ossaEchoCB(
            agsaRoot_t      *agRoot,
            agsaContext_t   *agContext,
            void            *echoPayload
          )
{
#ifdef ECHO_TESTING
  tdsaRootOsData_t    *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t            *tiRoot = (tiRoot_t *)osData->tiRoot;
  bit8                payload[56];
#endif

  TI_DBG2(("ossaEchoCB: start\n"));
  smTraceFuncEnter(hpDBG_VERY_LOUD,"Ym");

  /* dumping received echo payload is 56 bytes */
  tdhexdump("ossaEchoCB: echoPayload", (bit8 *)(echoPayload), 56);

#ifdef ECHO_TESTING
  /* temporary to test saEchoCommand() */

  /* new echo payload */
  osti_memset(payload,0, sizeof(payload));

  payload[0] = gEcho;
  payload[55] = gEcho;

  TI_DBG2(("ossaEchoCB: gEcho %d\n", gEcho));

  saEchoCommand(agRoot, agNULL, tdsaRotateQnumber(tiRoot, agNULL), (void *)&payload);

  if (gEcho == 0xFF)
  {
    gEcho = 0;
  }
  else
  {
    gEcho++;
  }
#endif

  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Ym");
  return;
}

/*****************************************************************************/
/*! \brief ossaGpioResponseCB
 *
 *
 *  Purpose: This routine is called by lower layer to corresponding to
 *           saGpioEventSetup(), saGpioPinSetup(), saGpioRead(), or
 *           saGpioWrite()
 *
 *  \param   agRoot:              Pointer to chip/driver Instance.
 *  \param   agContext:           Context of the operation originally passed
 *                                in.
 *  \param   status:              GPIO operation completion status
 *  \param   gpioReadValue:       a bit map containing the corresponding
 *                                value for each GPIO pin.
 *  \param   gpioPinSetupInfo:    Pointer to agsaGpioPinSetupInfo_t structure
 *                                describing the GPIO pin setup
 *  \param   gpioEventSetupInfo   Pointer to agsaGpioEventSetupInfo_t structure
 *                                describing the GPIO event setups
 *
 *
 *  \return None.
 *
 */
/*****************************************************************************/
osGLOBAL void ossaGpioResponseCB(
                   agsaRoot_t               *agRoot,
                   agsaContext_t            *agContext,
                   bit32                    status,
                   bit32                    gpioReadValue,
                   agsaGpioPinSetupInfo_t   *gpioPinSetupInfo,
                   agsaGpioEventSetupInfo_t *gpioEventSetupInfo
                   )
{
  TI_DBG2(("ossaGpioResponseCB: start\n"));
  smTraceFuncEnter(hpDBG_VERY_LOUD,"Yn");
  if (status == OSSA_SUCCESS)
  {
    TI_DBG2(("ossaGpioResponseCB: Success\n"));
    /* printing gpioReadValue, agsaGpioPinSetupInfo_t and agsaGpioEventSetupInfo_t */
    TI_DBG2(("ossaGpioResponseCB: gpioReadValue 0x%x\n", gpioReadValue));
    TI_DBG2(("ossaGpioResponseCB: PinSetupInfo gpioInputEnabled 0x%x\n", gpioPinSetupInfo->gpioInputEnabled));
    TI_DBG2(("ossaGpioResponseCB: PinSetupInfo gpioTypePart1 0x%x\n", gpioPinSetupInfo->gpioTypePart1));
    TI_DBG2(("ossaGpioResponseCB: PinSetupInfo gpioTypePart2 0x%x\n", gpioPinSetupInfo->gpioTypePart2));
    TI_DBG2(("ossaGpioResponseCB: EventSetupInfo gpioEventLevel 0x%x\n", gpioEventSetupInfo->gpioEventLevel));
    TI_DBG2(("ossaGpioResponseCB: EventSetupInfo gpioEventRisingEdge 0x%x\n", gpioEventSetupInfo->gpioEventRisingEdge));
    TI_DBG2(("ossaGpioResponseCB: EventSetupInfo gpioEventFallingEdge 0x%x\n", gpioEventSetupInfo->gpioEventFallingEdge));
  }
  else
  {
    TI_DBG1(("ossaGpioResponseCB: Failure\n"));
  }
  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Yn");
  return;
}

/*****************************************************************************/
/*! \brief ossaGpioEvent
 *
 *
 *  Purpose: This routine is called by lower layer to corresponding to
 *           saGpioEventSetup(), saGpioPinSetup(), saGpioRead(), or
 *           saGpioWrite()
 *
 *  \param   agRoot:              Pointer to chip/driver Instance.
 *  \param   gpioEvent:           a bit map that indicates which GPIO
 *                                input pins have generated the event.
 *
 *
 *  \return None.
 *
 */
/*****************************************************************************/
osGLOBAL void ossaGpioEvent(
              agsaRoot_t    *agRoot,
              bit32         gpioEvent
              )
{
  TI_DBG2(("ossaGpioEvent: start\n"));
  TI_DBG2(("ossaGpioEvent: gpioEvent 0x%x\n", gpioEvent));
  smTraceFuncEnter(hpDBG_VERY_LOUD,"Yo");
  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Yo");
  return;
}


/*****************************************************************************/
/*! \brief ossaSASDiagExecuteCB
 *
 *
 *  Purpose: This routine is called by lower layer to corresponding to
 *           saSASDiagExecute()
 *
 *  \param   agRoot:              Pointer to chip/driver Instance.
 *  \param   agContext:           Context of the operation originally passed
 *                                in.
 *  \param   status:              Diagnostic operation completion status
 *  \param   command:             SAS diagnostic command field in agsaSASDiagExecute_t
 *                                structure passed in saSASDiagExecute().
 *  \param   reportData:          Report Diagnostic Data
 *
 *
 *  \return None.
 *
 */
/*****************************************************************************/
osGLOBAL void ossaSASDiagExecuteCB(
                      agsaRoot_t      *agRoot,
                      agsaContext_t   *agContext,
                      bit32           status,
                      bit32           command,
                      bit32           reportData)
{
  smTraceFuncEnter(hpDBG_VERY_LOUD,"Yq");
  TI_DBG2(("ossaSASDiagExecuteCB: start\n"));
  TI_DBG2(("ossaSASDiagExecuteCB: status %d\n", status));
  TI_DBG2(("ossaSASDiagExecuteCB: command %d\n", command));
  TI_DBG2(("ossaSASDiagExecuteCB: reportData %d\n", reportData));

  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Yq");
  return;

}


/*****************************************************************************/
/*! \brief ossaSASDiagStartEndCB
 *
 *
 *  Purpose: This routine is called by lower layer to corresponding to
 *           saSASDiagExecute()
 *
 *  \param   agRoot:              Pointer to chip/driver Instance.
 *  \param   agContext:           Context of the operation originally passed
 *                                in.
 *  \param   status:              Diagnostic operation completion status
 *
 *
 *  \return None.
 *
 */
/*****************************************************************************/
osGLOBAL void ossaSASDiagStartEndCB(
                      agsaRoot_t        *agRoot,
                      agsaContext_t     *agContext,
                      bit32             status)
{
  TI_DBG2(("ossaSASDiagStartEndCB: start\n"));
  TI_DBG2(("ossaSASDiagStartEndCB: status %d\n", status));
  smTraceFuncEnter(hpDBG_VERY_LOUD,"Yr");
  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Yr");
  return;
}

/*****************************************************************************/
/*! \brief ossaReconfigSASParamsCB
 *
 *
 *  Purpose: This routine is called by lower layer to corresponding to
 *           saReconfigSASParams()
 *
 *  \param   agRoot:              Pointer to chip/driver Instance.
 *  \param   agContext:           Context of the operation originally passed
 *                                in saReconfigSASParams().
 *  \param   status:              saReconfigSASParams() completion status
 *  \param   agSASConfig:         Pointer to the data structure agsaSASReconfig_t
 *
 *
 *  \return None.
 *
 */
/*****************************************************************************/
osGLOBAL void   ossaReconfigSASParamsCB(
                        agsaRoot_t        *agRoot,
                        agsaContext_t     *agContext,
                        bit32             status,
                        agsaSASReconfig_t *agSASConfig)
{
  TI_DBG2(("ossaReconfigSASParamsCB: status %d\n", status));
  return;
}

GLOBAL void ossaPCIeDiagExecuteCB(
            agsaRoot_t             *agRoot,
            agsaContext_t         *agContext,
            bit32                  status,
            bit32                  command,
            agsaPCIeDiagResponse_t *resp )
{
  TI_DBG2(("ossaPCIeDiagExecuteCB: status %d\n", status));
  TI_DBG2(("ossaPCIeDiagExecuteCB: ERR_BLKH 0x%X\n",resp->ERR_BLKH ));
  TI_DBG2(("ossaPCIeDiagExecuteCB: ERR_BLKL 0x%X\n",resp->ERR_BLKL ));
  TI_DBG2(("ossaPCIeDiagExecuteCB: DWord8 0x%X\n",resp->DWord8 ));
  TI_DBG2(("ossaPCIeDiagExecuteCB: DWord9 0x%X\n",resp->DWord9 ));
  TI_DBG2(("ossaPCIeDiagExecuteCB: DWord10 0x%X\n",resp->DWord10 ));
  TI_DBG2(("ossaPCIeDiagExecuteCB: DWord11 0x%X\n",resp->DWord11 ));
  TI_DBG2(("ossaPCIeDiagExecuteCB: DIF_ERR 0x%X\n",resp->DIF_ERR ));

  return;
}


#ifndef BIOS
GLOBAL void ossaSGpioCB(
                    agsaRoot_t              *agRoot,
                    agsaContext_t           *agContext, 
                    agsaSGpioReqResponse_t  *pSgpioResponse
                    )
{
  tdsaRootOsData_t  *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t          *tiRoot = (tiRoot_t *)osData->tiRoot;
	
  TI_DBG2(("ossaSGpioCB:  smpFrameType: 0x%02x \n", pSgpioResponse->smpFrameType));
 // printf("SS:ossaSGpioCB:  smpFrameType: 0x%02x \n", pSgpioResponse->smpFrameType);
  TI_DBG2(("ossaSGpioCB:  function: 0x%02x \n", pSgpioResponse->function));
  TI_DBG2(("ossaSGpioCB:  functionResult: 0x%02x \n", pSgpioResponse->functionResult));
  //printf("SS:ossaSGpioCB:  functionResult: 0x%02x \n", pSgpioResponse->functionResult);
  
  tdhexdump("ossaSGpioCB Response", (bit8 *)pSgpioResponse, sizeof(agsaSGpioReqResponse_t));
  ostiSgpioIoctlRsp(tiRoot, pSgpioResponse);	
}

#endif /* BIOS */

/*****************************************************************************/
/*! \brief ossaLogDebugString
 *
 *
 *  Purpose: This routine is called by lower layer to log.
 *
 *  \param   agRoot:              Pointer to chip/driver Instance.
 *  \param   level:               Detail of information desired.
 *  \param   string:              Pointer to the character string.
 *  \param   ptr1:                First pointer value.
 *  \param   ptr2:                Second pointer value.
 *  \param   value1:              First 32-bit value related to the specific information.
 *  \param   value2:              Second 32-bit value related to the specific information.
 *
 *  \return None.
 *
 */
/*****************************************************************************/
GLOBAL void ossaLogDebugString(
                         agsaRoot_t   *agRoot,
                         bit32        level,
                         char         *string,
                         void         *ptr1,
                         void         *ptr2,
                         bit32        value1,
                         bit32        value2
                         )
{
#if defined(SALLSDK_DEBUG)
  TIDEBUG_MSG(gLLDebugLevel, level, ("%s %p %p %d %d\n", string, ptr1, ptr2, value1, value2));
#endif
  return;
}

/*****************************************************************************/
/*! \brief ossaHwEventAckCB
 *
 *
 *  Purpose: This routine is called by lower layer to corresponding to
 *           saHwEventAck(()
 *
 *  \param   agRoot:              Pointer to chip/driver Instance.
 *  \param   agContext:           Context of the operation originally passed
 *                                in.
 *  \param   status:              Status
 *
 *
 *  \return None.
 *
 */
/*****************************************************************************/
GLOBAL void ossaHwEventAckCB(
                             agsaRoot_t         *agRoot,
                             agsaContext_t      *agContext,
                             bit32              status
                             )
{
  TI_DBG3(("ossaHwEventAckCB: start\n"));
  smTraceFuncEnter(hpDBG_VERY_LOUD,"Ys");
  if (status == tiSuccess)
  {
    TI_DBG3(("ossaHwEventAckCB: SUCCESS status\n"));
  }
  else
  {
    TI_DBG1(("ossaHwEventAckCB: FAIL status 0x%X\n", status));
    TI_DBG1(("ossaHwEventAckCB: invalid event status bit0 %d\n", status & 0x01));
    TI_DBG1(("ossaHwEventAckCB: invalid phyid status bit1 %d\n", (status & 0x02) >> 1 ));
    TI_DBG1(("ossaHwEventAckCB: invalid portcontext status bit2 %d\n", (status & 0x04) >> 2));
    TI_DBG1(("ossaHwEventAckCB: invalid param0 status bit3 %d\n", (status & 0x08) >> 3));
  }

  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Ys");
  return;
}

/*****************************************************************************/
/*! \brief ossaGetTimeStampCB
 *
 *
 *  Purpose: This routine is called by lower layer to corresponding to
 *           saGetTimeStamp()
 *
 *  \param   agRoot:              Pointer to chip/driver Instance.
 *  \param   agContext:           Context of the operation originally passed
 *                                in.
 *  \param   timeStampLower:      The controller lower 32-bit of internal time
 *                                stamp associated with event log.
 *  \param   timeStampUpper:      The controller upper 32-bit of internal time
 *                                stamp associated with event log.
 *
 *
 *  \return None.
 *
 */
/*****************************************************************************/
GLOBAL void ossaGetTimeStampCB(
                         agsaRoot_t    *agRoot,
                         agsaContext_t *agContext,
                         bit32         timeStampLower,
                         bit32         timeStampUpper
                         )
{
  smTraceFuncEnter(hpDBG_VERY_LOUD,"Yt");
  TI_DBG4(("ossaGetTimeStampCB: start\n"));
  TI_DBG4(("ossaGetTimeStampCB: timeStampUpper 0x%x timeStampLower 0x%x\n", timeStampUpper, timeStampLower));
  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Yt");
  return;
}


/*****************************************************************************/
/*! \brief ossaSMPAbortCB
 *
 *
 *  Purpose: This routine is called by lower layer to corresponding to
 *           saSMPAbort()
 *
 *  \param   agRoot:              Pointer to chip/driver Instance.
 *  \param   agIORequest:         This is the agIORequest parameter passed in
 *                                saSMPAbort()
 *  \param   status:              Status of abort
 *
 *  \return None.
 *
 */
/*****************************************************************************/
GLOBAL void ossaSMPAbortCB(
                           agsaRoot_t           *agRoot,
                           agsaIORequest_t      *agIORequest,
                           bit32                flag,
                           bit32                status)
{
  tdsaRootOsData_t        *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t                *tiRoot = (tiRoot_t *)osData->tiRoot;
  tdIORequestBody_t       *tdAbortIORequestBody = agNULL;
  tdsaDeviceData_t        *oneDeviceData        = agNULL;
  tiDeviceHandle_t        *tiDeviceHandle       = agNULL;

  TI_DBG4(("ossaSMPAbortCB: start\n"));
  TI_DBG4(("ossaSMPAbortCB: flag %d\n", flag));
  TI_DBG4(("ossaSMPAbortCB: status %d\n", status));
  smTraceFuncEnter(hpDBG_VERY_LOUD,"Yu");

  tdAbortIORequestBody = (tdIORequestBody_t *)agIORequest->osData;
  if (tdAbortIORequestBody == agNULL)
  {
    TI_DBG1(("ossaSMPAbortCB: tdAbortIORequestBody is NULL warning!!!!\n"));
    return;
  }

  if (flag == 2)
  {
    /* abort per port */
    TI_DBG2(("ossaSMPAbortCB: abort per port\n"));
  }
  else if (flag == 1)
  {
    TI_DBG2(("ossaSMPAbortCB: abort all\n"));

    tiDeviceHandle = (tiDeviceHandle_t *)tdAbortIORequestBody->tiDevHandle;
    if (tiDeviceHandle == agNULL)
    {
      TI_DBG1(("ossaSMPAbortCB: tiDeviceHandle is NULL warning!!!!\n"));
      ostiFreeMemory(
               tiRoot,
               tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
               sizeof(tdIORequestBody_t)
               );
      return;
    }

    oneDeviceData  = (tdsaDeviceData_t *)tiDeviceHandle->tdData;
    if (oneDeviceData == agNULL)
    {
      TI_DBG1(("ossaSMPAbortCB: oneDeviceData is NULL warning!!!!\n"));
      ostiFreeMemory(
               tiRoot,
               tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
               sizeof(tdIORequestBody_t)
               );
      return;
    }

    if (status == OSSA_IO_SUCCESS)
    {
      TI_DBG2(("ossaSMPAbortCB: OSSA_IO_SUCCESS\n"));
      /* clean up TD layer's IORequestBody */
      TI_DBG3(("ossaSMPAbortCB: calling saDeregisterDeviceHandle\n"));
      saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData));
      TI_DBG2(("ossaSMPAbortCB: did %d\n", oneDeviceData->id));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );

    }
    else if (status == OSSA_IO_NOT_VALID)
    {
      TI_DBG1(("ossaSMPAbortCB: OSSA_IO_NOT_VALID\n"));
      /* clean up TD layer's IORequestBody */
      TI_DBG1(("ossaSMPAbortCB: calling saDeregisterDeviceHandle\n"));
      saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData));
      TI_DBG1(("ossaSMPAbortCB: did %d\n", oneDeviceData->id));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
    else if (status == OSSA_IO_NO_DEVICE)
    {
      TI_DBG1(("ossaSMPAbortCB: OSSA_IO_NO_DEVICE\n"));
      /* clean up TD layer's IORequestBody */
      TI_DBG1(("ossaSMPAbortCB: calling saDeregisterDeviceHandle\n"));
      saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData));
      TI_DBG1(("ossaSMPAbortCB: did %d\n", oneDeviceData->id));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
    else if (status == OSSA_IO_ABORT_IN_PROGRESS)
    {
      TI_DBG1(("ossaSMPAbortCB: OSSA_IO_ABORT_IN_PROGRESS\n"));
      /* clean up TD layer's IORequestBody */
      TI_DBG1(("ossaSMPAbortCB: calling saDeregisterDeviceHandle\n"));
      saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData));
      TI_DBG1(("ossaSMPAbortCB: did %d\n", oneDeviceData->id));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
#ifdef REMOVED
    else if (status == OSSA_IO_ABORT_DELAYED)
    {
      TI_DBG1(("ossaSMPAbortCB: OSSA_IO_ABORT_DELAYED\n"));
      /* clean up TD layer's IORequestBody */
      TI_DBG1(("ossaSMPAbortCB: calling saDeregisterDeviceHandle\n"));
      saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData));
      TI_DBG1(("ossaSMPAbortCB: did %d\n", oneDeviceData->id));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
#endif
    else
    {
      TI_DBG1(("ossaSMPAbortCB: other status %d\n", status));
      /* clean up TD layer's IORequestBody */
      TI_DBG1(("ossaSMPAbortCB: calling saDeregisterDeviceHandle\n"));
      saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData));
      TI_DBG1(("ossaSMPAbortCB: did %d\n", oneDeviceData->id));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
  }
  else if (flag == 0)
  {
    TI_DBG2(("ossaSMPAbortCB: abort one\n"));
    if (status == OSSA_IO_SUCCESS)
    {
      TI_DBG2(("ossaSMPAbortCB: OSSA_IO_SUCCESS\n"));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );

    }
    else if (status == OSSA_IO_NOT_VALID)
    {
      TI_DBG1(("ossaSMPAbortCB: OSSA_IO_NOT_VALID\n"));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
    else if (status == OSSA_IO_NO_DEVICE)
    {
      TI_DBG1(("ossaSMPAbortCB: OSSA_IO_NO_DEVICE\n"));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
    else if (status == OSSA_IO_ABORT_IN_PROGRESS)
    {
      TI_DBG1(("ossaSMPAbortCB: OSSA_IO_ABORT_IN_PROGRESS\n"));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
#ifdef REMOVED
    else if (status == OSSA_IO_ABORT_DELAYED)
    {
      TI_DBG1(("ossaSMPAbortCB: OSSA_IO_ABORT_DELAYED\n"));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
#endif
    else
    {
      TI_DBG1(("ossaSMPAbortCB: other status %d\n", status));
      ostiFreeMemory(
                     tiRoot,
                     tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                     sizeof(tdIORequestBody_t)
                     );
    }
  }
  else
  {
    TI_DBG1(("ossaSMPAbortCB: wrong flag %d\n", flag));
  }


  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Yu");
  return;
}

/*****************************************************************************/
/*! \brief ossaGeneralEvent
 *
 *
 *  Purpose: This is the event notification for debugging purposes sent to
 *           inform the OS layer of some general error related to a specific
 *           inbound operation.
 *
 *  \param   agRoot:              Pointer to chip/driver Instance.
 *  \param   status:              Status associated with this event
 *  \param   msg:                 Pointer to controller specific command
 *                                massage that caused the error
 *
 *  \return None.
 *
 */
/*****************************************************************************/
GLOBAL void ossaGeneralEvent(
                             agsaRoot_t    *agRoot,
                             bit32         status,
                             agsaContext_t *agContext,
                             bit32         *msg)
{
  tdsaRootOsData_t    *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t            *tiRoot = (tiRoot_t *)osData->tiRoot;

  TI_DBG1(("ossaGeneralEvent: start\n"));
  TI_DBG1(("ossaGeneralEvent: status %d\n", status));

  if(msg)
  {
    TI_DBG1(("ossaGeneralEvent: *msg %X\n", *msg));
  }

  smTraceFuncEnter(hpDBG_VERY_LOUD,"Yv");
  ostiGenEventIOCTLRsp(tiRoot, status);
  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Yv");
  return;
}

GLOBAL void   ossaGetForensicDataCB (
        agsaRoot_t         *agRoot,
        agsaContext_t      *agContext,
        bit32              status,
        agsaForensicData_t *forensicData)
{
  tdsaRootOsData_t    *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t            *tiRoot = (tiRoot_t *)osData->tiRoot;

  ostiGetForensicDataIOCTLRsp(tiRoot, status, forensicData);
  return;
}


#ifdef INITIATOR_DRIVER

GLOBAL void ossaGetIOErrorStatsCB (
                      agsaRoot_t               *agRoot,
                      agsaContext_t            *agContext,
                      bit32                     status,
                      agsaIOErrorEventStats_t  *stats)

{
  tdsaRootOsData_t    *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t            *tiRoot = (tiRoot_t *)osData->tiRoot;

  ostiGetIoErrorStatsIOCTLRsp(tiRoot, status, stats);
}
#else
GLOBAL void ossaGetIOErrorStatsCB (
                      agsaRoot_t               *agRoot,
                      agsaContext_t            *agContext,
                      bit32                     status,
                      agsaIOErrorEventStats_t  *stats)

{

}

#endif

GLOBAL void ossaGetIOEventStatsCB (
                      agsaRoot_t               *agRoot,
                      agsaContext_t            *agContext,
                      bit32                     status,
                      agsaIOErrorEventStats_t  *stats)

{
  tdsaRootOsData_t    *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t            *tiRoot = (tiRoot_t *)osData->tiRoot;

  ostiGetIoEventStatsIOCTLRsp(tiRoot, status, stats);
}


/*****************************************************************************/
/*! \brief ossaGetRegisterDumpCB
 *
 *
 *  Purpose: ossaGetRegisterDumpCB() is the response callback function
 *           called by the LL Layer to indicate a response to
 *           saGetRegisterDump()
 *
 *  \param   agRoot:              Pointer to chip/driver Instance.
 *  \param   agContext:           Context of the operation originally
 *                                passed into saGetRegisterDump()
 *  \param   status:              status
 *
 *  \return None.
 *
 */
/*****************************************************************************/
GLOBAL void ossaGetRegisterDumpCB(
                                  agsaRoot_t    *agRoot,
                                  agsaContext_t *agContext,
                                  bit32         status
)
{
  tdsaRootOsData_t    *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t            *tiRoot = (tiRoot_t *)osData->tiRoot;

  TI_DBG4(("ossaGetRegisterDumpCB: start\n"));
  TI_DBG4(("ossaGetRegisterDumpCB: status %d\n", status));
  smTraceFuncEnter(hpDBG_VERY_LOUD,"Yw");

  ostiRegDumpIOCTLRsp(tiRoot, status);
  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Yw");
  return;
}

/*****************************************************************************/
/*! \brief ossaSetDeviceStateCB
 *
 *
 *  Purpose: ossaSetDeviceStateCB() is the response callback function
 *           called by the LL Layer to indicate a response to
 *           saSetDeviceState()
 *
 *  \param   agRoot:              Pointer to chip/driver Instance.
 *  \param   agContext:           Context of the operation originally
 *                                passed into saGetRegisterDump()
 *  \param   agDevHandle          Pointer to the device handle of the device
 *  \param   status:              status
 *  \param   newDeviceState:      newly set device status
 *  \param   previousDeviceState: old device status
 *
 *  \return None.
 *
 */
/*****************************************************************************/
GLOBAL void ossaSetDeviceStateCB(
                                 agsaRoot_t         *agRoot,
                                 agsaContext_t      *agContext,
                                 agsaDevHandle_t    *agDevHandle,
                                 bit32              status,
                                 bit32              newDeviceState,
                                 bit32              previousDeviceState
                                 )
{
  tdsaDeviceData_t            *oneDeviceData = agNULL;

  TI_DBG2(("ossaSetDeviceStateCB: start\n"));
  TI_DBG2(("ossaSetDeviceStateCB: status %d\n", status));
  TI_DBG2(("ossaSetDeviceStateCB: newDeviceState %d\n", newDeviceState));
  TI_DBG2(("ossaSetDeviceStateCB: previousDeviceState %d\n", previousDeviceState));

  if (agDevHandle == agNULL)
  {
    TI_DBG4(("ossaSetDeviceStateCB: agDevHandle is NULL\n"));
    return;
  }

  oneDeviceData = (tdsaDeviceData_t *)agDevHandle->osData;

  if (oneDeviceData == agNULL)
  {
    TI_DBG1(("ossaSetDeviceStateCB: wrong; oneDeviceData is NULL\n"));
  }
  else
  {
    TI_DBG2(("ossaSetDeviceStateCB: did %d\n", oneDeviceData->id));
  }

  return;
}

/*****************************************************************************/
/*! \brief ossaGetDeviceStateCB
 *
 *
 *  Purpose: ossaGetDeviceStateCB() is the response callback function
 *           called by the LL Layer to indicate a response to
 *           saGetDeviceState()
 *
 *  \param   agRoot:              Pointer to chip/driver Instance.
 *  \param   agContext:           Context of the operation originally
 *                                passed into saGetRegisterDump()
 *  \param   agDevHandle          Pointer to the device handle of the device
 *  \param   status:              status
 *  \param   deviceState:         device status
 *
 *  \return None.
 *
 */
/*****************************************************************************/
GLOBAL void ossaGetDeviceStateCB(
                                 agsaRoot_t         *agRoot,
                                 agsaContext_t      *agContext,
                                 agsaDevHandle_t    *agDevHandle,
                                 bit32              status,
                                 bit32              deviceState
                                 )
{
  TI_DBG4(("ossaGetDeviceStateCB: start\n"));
  TI_DBG4(("ossaGetDeviceStateCB: status %d\n", status));
  TI_DBG4(("ossaGetDeviceStateCB: deviceState %d\n", deviceState));

  return;
}

#ifdef INITIATOR_DRIVER
/*****************************************************************************/
/*! \brief ossaIniSetDeviceInfoCB
 *
 *
 *  Purpose: ossaIniSetDeviceInfoCB() is the response callback function
 *           called by the LL Layer to indicate a response to
 *           saSetDeviceInfo()
 *
 *  \param   agRoot:              Pointer to chip/driver Instance.
 *  \param   agContext:           Context of the operation originally
 *                                passed into saSetDeviceInfo()
 *  \param   agDevHandle          Pointer to the device handle of the device
 *  \param   status:              status
 *  \param   option:              option parameter passed in saSetDeviceInfo()
 *  \param   param:               param parameter passed in saSetDeviceInfo()
 *
 *  \return None.
 *
 */
/*****************************************************************************/
osGLOBAL void
ossaIniSetDeviceInfoCB(
                        agsaRoot_t        *agRoot,
                        agsaContext_t     *agContext,
                        agsaDevHandle_t   *agDevHandle,
                        bit32             status,
                        bit32             option,
                        bit32             param
                      )
{
  tdsaRootOsData_t       *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t               *tiRoot = (tiRoot_t *)osData->tiRoot;
  tdsaRoot_t             *tdsaRoot      = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t          *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  itdsaIni_t             *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni;
  bit32                  intContext = osData->IntContext;
  tdIORequestBody_t      *tdIORequestBody = agNULL;
  agsaIORequest_t        *agIORequest = agNULL;
  bit32                  saStatus = AGSA_RC_FAILURE;
  bit8                   devType_S_Rate;
  tdsaDeviceData_t       *oneDeviceData = agNULL;

  TI_DBG4(("ossaIniSetDeviceInfoCB: start\n"));
  TI_DBG4(("ossaIniSetDeviceInfoCB: status 0x%x\n", status));
  TI_DBG4(("ossaIniSetDeviceInfoCB: option 0x%x\n", option));
  TI_DBG4(("ossaIniSetDeviceInfoCB: param 0x%x\n", param));

  if (status != OSSA_SUCCESS)
  {
    TI_DBG1(("ossaIniSetDeviceInfoCB: status %d\n", status));
    TI_DBG1(("ossaIniSetDeviceInfoCB: option 0x%x\n", option));
    TI_DBG1(("ossaIniSetDeviceInfoCB: param 0x%x\n", param));
    if (option == 32) /* set connection rate */
    {
      TI_DBG1(("ossaIniSetDeviceInfoCB: IO failure\n"));
      agIORequest = (agsaIORequest_t *)agContext->osData;
      tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData;
      ostiInitiatorIOCompleted(
                               tiRoot,
                               tdIORequestBody->tiIORequest,
                               tiIOFailed,
                               tiDetailOtherError,
                               agNULL,
                               intContext
                               );
    }
  }
  if (agDevHandle == agNULL)
  {
    TI_DBG4(("ossaIniSetDeviceInfoCB: agDevHandle is NULL\n"));
    return;
  }
  oneDeviceData = (tdsaDeviceData_t *)agDevHandle->osData;
  if (oneDeviceData == agNULL)
  {
    TI_DBG1(("ossaIniSetDeviceInfoCB: wrong; oneDeviceData is NULL\n"));
    return;
  }
  else
  {
    TI_DBG4(("ossaIniSetDeviceInfoCB: did %d\n", oneDeviceData->id));
  }

  /* retry IOs */
  if (option == 32) /* set connection rate */
  {
    TI_DBG1(("ossaIniSetDeviceInfoCB: set connection rate option\n"));
    agIORequest = (agsaIORequest_t *)agContext->osData;
    tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData;
    devType_S_Rate = oneDeviceData->agDeviceInfo.devType_S_Rate;
    devType_S_Rate = (devType_S_Rate & 0xF0) | (param >> 28);
    oneDeviceData->agDeviceInfo.devType_S_Rate =  devType_S_Rate;
    TI_DBG1(("ossaIniSetDeviceInfoCB: new rate is 0x%x\n", DEVINFO_GET_LINKRATE(&oneDeviceData->agDeviceInfo)));
    if (oneDeviceData->valid == agTRUE && oneDeviceData->registered == agTRUE &&
        oneDeviceData->tdPortContext != agNULL )
    {
      saStatus = saSSPStart(agRoot,
                            agIORequest,
                            tdsaRotateQnumber(tiRoot, oneDeviceData),
                            agDevHandle,
                            tdIORequestBody->agRequestType,
                            &(tdIORequestBody->transport.SAS.agSASRequestBody),
                            agNULL,
                            &ossaSSPCompleted);
      if (saStatus == AGSA_RC_SUCCESS)
      {
        TI_DBG1(("ossaIniSetDeviceInfoCB: retried\n"));
        Initiator->NumIOsActive++;
        tdIORequestBody->ioStarted = agTRUE;
        tdIORequestBody->ioCompleted = agFALSE;
        return;
      }
      else
      {
        TI_DBG1(("ossaIniSetDeviceInfoCB: retry failed\n"));
        tdIORequestBody->ioStarted = agFALSE;
        tdIORequestBody->ioCompleted = agTRUE;
        ostiInitiatorIOCompleted(
                                 tiRoot,
                                 tdIORequestBody->tiIORequest,
                                 tiIOFailed,
                                 tiDetailOtherError,
                                 agNULL,
                                 intContext
                                 );
       }
    }
  }
  return;
}
#endif
/*****************************************************************************/
/*! \brief ossaSetDeviceInfoCB
 *
 *
 *  Purpose: ossaSetDeviceInfoCB() is the response callback function
 *           called by the LL Layer to indicate a response to
 *           saSetDeviceInfo()
 *
 *  \param   agRoot:              Pointer to chip/driver Instance.
 *  \param   agContext:           Context of the operation originally
 *                                passed into saSetDeviceInfo()
 *  \param   agDevHandle          Pointer to the device handle of the device
 *  \param   status:              status
 *  \param   option:              option parameter passed in saSetDeviceInfo()
 *  \param   param:               param parameter passed in saSetDeviceInfo()
 *
 *  \return None.
 *
 */
/*****************************************************************************/
GLOBAL void ossaSetDeviceInfoCB(
                                 agsaRoot_t         *agRoot,
                                 agsaContext_t      *agContext,
                                 agsaDevHandle_t    *agDevHandle,
                                 bit32              status,
                                 bit32              option,
                                 bit32              param
                                )
{
  tdsaDeviceData_t       *oneDeviceData = agNULL;

  TI_DBG4(("ossaSetDeviceInfoCB: start\n"));
  TI_DBG4(("ossaSetDeviceInfoCB: status 0x%x\n", status));
  TI_DBG4(("ossaSetDeviceInfoCB: option 0x%x\n", option));
  TI_DBG4(("ossaSetDeviceInfoCB: param 0x%x\n", param));

  if (status != OSSA_SUCCESS)
  {
    TI_DBG1(("ossaSetDeviceInfoCB: status %d\n", status));
    TI_DBG1(("ossaSetDeviceInfoCB: option 0x%x\n", option));
    TI_DBG1(("ossaSetDeviceInfoCB: param 0x%x\n", param));
  }

  if (agDevHandle == agNULL)
  {
    TI_DBG4(("ossaSetDeviceInfoCB: agDevHandle is NULL\n"));
    return;
  }

  oneDeviceData = (tdsaDeviceData_t *)agDevHandle->osData;

  if (oneDeviceData == agNULL)
  {
    TI_DBG1(("ossaSetDeviceInfoCB: wrong; oneDeviceData is NULL\n"));
  }
  else
  {
    TI_DBG4(("ossaSetDeviceInfoCB: did %d\n", oneDeviceData->id));
  }

  return;
}

/*****************************************************************************/
/*! \brief ossaGetDFEDataCB
 *
 *
 *  Purpose: ossaGetDFEDataCB() is the response callback function
 *           called by the LL Layer to indicate a response to
 *           saGetDFEData()
 *
 *  \param   agRoot:              Pointer to chip/driver Instance.
 *  \param   agContext:           Context of the operation originally
 *                                passed into saGetDFEData()
 *  \param   status:              status
 *  \param   agInfoLen:           length in bytes of DFE data captured and transferred
 *
 *  \return None.
 *
 */
/*****************************************************************************/
GLOBAL void ossaGetDFEDataCB(
                             agsaRoot_t     *agRoot,
                             agsaContext_t  *agContext,
                             bit32   status,
                             bit32   agInfoLen)
{
  TI_DBG1(("ossaGetDFEDataCB: start\n"));
  TI_DBG1(("ossaGetDFEDataCB: status 0x%x agInfoLen 0x%x\n", status, agInfoLen));
  return;
}

/*****************************************************************************/
/*! \brief ossaVhistCaptureCB
 *
 *
 *  Purpose: ossaVhistCaptureCB() is the response callback function
 *           called by the LL Layer to indicate a response to
 *           saGetDFEData()
 *
 *  \param   agRoot:              Pointer to chip/driver Instance.
 *  \param   agContext:           Context of the operation originally
 *                                passed into ()
 *  \param   status:              status
 *  \param   len:           length in bytes of Vis data captured and transferred
 *
 *  \return None.
 *
 */
/*****************************************************************************/

void ossaVhistCaptureCB(
        agsaRoot_t    *agRoot,
        agsaContext_t *agContext,
        bit32         status,
        bit32         len)
{
  TI_DBG1(("ossaVhistCaptureCB: start\n"));
  TI_DBG1(("ossaVhistCaptureCB: status 0x%x agInfoLen 0x%x\n", status,len ));
  return;
}

GLOBAL void ossaOperatorManagementCB(
                  agsaRoot_t    *agRoot,
                  agsaContext_t *agContext,
                  bit32          status,
                  bit32          eq
                  )
{
  tdsaRootOsData_t    *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t            *tiRoot = (tiRoot_t *)osData->tiRoot;
  tiEncryptPort_t      encryptEventData;

  TI_DBG1(("ossaOperatorManagementCB: status 0x%x eq 0x%x\n", status, eq));

  osti_memset(&encryptEventData, 0, sizeof(tiEncryptPort_t));
  encryptEventData.encryptEvent = tiEncryptOperatorManagement;
  encryptEventData.subEvent = eq;
  encryptEventData.pData = agNULL;

  ostiPortEvent(tiRoot,
              tiEncryptOperation,
              status,
              &encryptEventData);
}

GLOBAL void ossaEncryptSelftestExecuteCB (
                        agsaRoot_t    *agRoot,
                        agsaContext_t *agContext,
                        bit32          status,
                        bit32          type,
                        bit32          length,
                        void          *TestResult
                        )
{
  tdsaRootOsData_t    *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t            *tiRoot = (tiRoot_t *)osData->tiRoot;
  tiEncryptPort_t      encryptEventData;

  TI_DBG1(("ossaEncryptSelftestExecuteCB: status 0x%x type 0x%x length 0x%x\n", status, type, length));

  osti_memset(&encryptEventData, 0, sizeof(tiEncryptPort_t));
  encryptEventData.encryptEvent = tiEncryptSelfTest;
  encryptEventData.subEvent = type;
  encryptEventData.pData = (void*)TestResult;

  ostiPortEvent(tiRoot,
              tiEncryptOperation,
              status,
              &encryptEventData);
}

GLOBAL void ossaGetOperatorCB(
               agsaRoot_t    *agRoot,
               agsaContext_t *agContext,
               bit32          status,
               bit32          option,
               bit32          num,
               bit32          role,
               agsaID_t      *id
               )
{

  tdsaRootOsData_t    *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t            *tiRoot = (tiRoot_t *)osData->tiRoot;
  tiEncryptPort_t      encryptEventData;

  TI_DBG1(("ossaGetOperatorCB: status 0x%x option 0x%x num 0x%x role 0x%x\n",
                status, option, num, role));
  TI_DBG1(("ossaGetOperatorCB: agContext %p id %p\n",agContext,id));
  osti_memset(&encryptEventData, 0, sizeof(tiEncryptPort_t));
  encryptEventData.encryptEvent = tiEncryptGetOperator;
  encryptEventData.subEvent = option;
  encryptEventData.pData = agNULL;

  switch(status)
  {
    case OSSA_IO_SUCCESS:
      TI_DBG1(("ossaGetOperatorCB: OSSA_IO_SUCCESS option 0x%x\n", option));
      if(option == 1)
      {
        TI_DBG2(("ossaGetOperatorCB: 0x%02x 0x%02x 0x%02x 0x%02x\n",id->ID[0], id->ID[1], id->ID[2], id->ID[3]));
        TI_DBG2(("ossaGetOperatorCB: 0x%02x 0x%02x 0x%02x 0x%02x\n",id->ID[4], id->ID[5], id->ID[6], id->ID[7]));
        TI_DBG2(("ossaGetOperatorCB: 0x%02x 0x%02x 0x%02x 0x%02x\n",id->ID[8], id->ID[9], id->ID[10],id->ID[11]));
        TI_DBG2(("ossaGetOperatorCB: 0x%02x 0x%02x 0x%02x 0x%02x\n",id->ID[12],id->ID[13],id->ID[14],id->ID[15]));
        TI_DBG2(("ossaGetOperatorCB: 0x%02x 0x%02x 0x%02x 0x%02x\n",id->ID[16],id->ID[17],id->ID[18],id->ID[19]));
        TI_DBG2(("ossaGetOperatorCB: 0x%02x 0x%02x 0x%02x 0x%02x\n",id->ID[20],id->ID[21],id->ID[22],id->ID[23]));
        TI_DBG2(("ossaGetOperatorCB: 0x%02x 0x%02x 0x%02x 0x%02x\n",id->ID[24],id->ID[25],id->ID[26],id->ID[27]));
        TI_DBG2(("ossaGetOperatorCB: 0x%02x 0x%02x 0x%02x\n",       id->ID[28],id->ID[29],id->ID[30]));
      }else if(option == 2)
      {
        TI_DBG1(("ossaGetOperatorCB: number operators 0x%02x\n", num ));
      }

      encryptEventData.pData = id;
      break;
    case OSSA_MPI_ENC_ERR_UNSUPPORTED_OPTION:
      TI_DBG1(("ossaGetOperatorCB: OSSA_MPI_ENC_ERR_UNSUPPORTED_OPTION 0x%x\n",option));
      break;
    case OSSA_MPI_ENC_ERR_ID_TRANSFER_FAILURE:
      TI_DBG1(("ossaGetOperatorCB: OSSA_MPI_ENC_ERR_ID_TRANSFER_FAILURE 0x%x\n",option));
      break;
    default:
      TI_DBG1(("ossaGetOperatorCB: Unknown status 0x%x\n",status));
  }
  ostiPortEvent(tiRoot,
              tiEncryptOperation,
              status,
              &encryptEventData);

}

GLOBAL void ossaSetOperatorCB(
              agsaRoot_t    *agRoot,
              agsaContext_t *agContext,
              bit32          status,
              bit32          eq
              )
{
  tdsaRootOsData_t    *osData = (tdsaRootOsData_t *)agRoot->osData;
  tiRoot_t            *tiRoot = (tiRoot_t *)osData->tiRoot;
  tiEncryptPort_t      encryptEventData;

  TI_DBG1(("ossaSetOperatorCB: agContext %p status 0x%x eq 0x%x\n",agContext, status, eq));

  osti_memset(&encryptEventData, 0, sizeof(tiEncryptPort_t));
  encryptEventData.encryptEvent = tiEncryptSetOperator;
  encryptEventData.subEvent = 0;
  switch(status)
  {
    case OSSA_IO_SUCCESS:
      TI_DBG1(("ossaSetOperatorCB: OSSA_IO_SUCCESS\n"));
      encryptEventData.pData = agNULL;
      break;
    case OSSA_MPI_ENC_ERR_CONTROLLER_NOT_IDLE:
      TI_DBG1(("ossaSetOperatorCB: OSSA_MPI_ENC_ERR_CONTROLLER_NOT_IDLE\n"));
      break;
    case OSSA_MPI_ENC_OPERATOR_AUTH_FAILURE:
      TI_DBG1(("ossaSetOperatorCB: OSSA_MPI_ENC_OPERATOR_AUTH_FAILURE error qualifier 0x%x\n",eq));
      break;
    case OSSA_MPI_ENC_OPERATOR_OPERATOR_ALREADY_LOGGED_IN:
      TI_DBG1(("ossaSetOperatorCB: OSSA_MPI_ENC_OPERATOR_OPERATOR_ALREADY_LOGGED_IN\n"));
      break;
    case OSSA_MPI_ENC_OPERATOR_ILLEGAL_PARAMETER:
      TI_DBG1(("ossaSetOperatorCB: OSSA_MPI_ENC_OPERATOR_ILLEGAL_PARAMETER\n"));
      break;
    case OSSA_MPI_ENC_ERR_UNSUPPORTED_OPTION:
      TI_DBG1(("ossaSetOperatorCB: OSSA_MPI_ENC_ERR_UNSUPPORTED_OPTION\n"));
      break;
    case OSSA_MPI_ENC_ERR_ID_TRANSFER_FAILURE:
      TI_DBG1(("ossaSetOperatorCB: OSSA_MPI_ENC_ERR_ID_TRANSFER_FAILURE\n"));
      break;
    default:
      TI_DBG1(("ossaGetOperatorCB: Unknown status 0x%x\n",status));
  }
  ostiPortEvent(tiRoot,
              tiEncryptOperation,
              status,
              &encryptEventData);
}

GLOBAL void ossaDIFEncryptionOffloadStartCB(
                             agsaRoot_t     *agRoot,
                             agsaContext_t  *agContext,
                             bit32   status,
                             agsaOffloadDifDetails_t *agsaOffloadDifDetails)
{
  TI_DBG1(("ossaDIFEncryptionOffloadStartCB: start\n"));
  TI_DBG1(("ossaDIFEncryptionOffloadStartCB: status 0x%x agsaOffloadDifDetails=%p\n", status, agsaOffloadDifDetails));
  return;
}

GLOBAL bit32 ossaTimeStamp( agsaRoot_t     *agRoot )
{
  tdsaRootOsData_t    *osData= agNULL;
  tiRoot_t            *tiRoot= agNULL;
  if(agRoot)
  {
    osData = (tdsaRootOsData_t *)agRoot->osData;
  }
  if(osData)
  {
    tiRoot = (tiRoot_t *)osData->tiRoot;
  }
  return(ostiTimeStamp(tiRoot));
} 

GLOBAL bit64 ossaTimeStamp64( agsaRoot_t     *agRoot)
{
  tdsaRootOsData_t    *osData= agNULL;
  tiRoot_t            *tiRoot= agNULL;
  if(agRoot)
  {
    osData = (tdsaRootOsData_t *)agRoot->osData;
  }
  if(osData)
  {
    tiRoot = (tiRoot_t *)osData->tiRoot;
  }
  return(ostiTimeStamp64(tiRoot));
} 

#ifdef FDS_SM
osGLOBAL void
tdIDStartTimer(tiRoot_t                 *tiRoot,
                  smIORequest_t            *smIORequest,
                  tdsaDeviceData_t         *oneDeviceData
                  )
{
  tdsaRoot_t                  *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t               *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  itdsaIni_t                  *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni;

  TI_DBG1(("tdIDStartTimer: start\n"));

  tdsaSingleThreadedEnter(tiRoot, TD_TIMER_LOCK);
  if (oneDeviceData->tdIDTimer.timerRunning == agTRUE)
  {
    tdsaSingleThreadedLeave(tiRoot, TD_TIMER_LOCK);
    tdsaKillTimer(
                  tiRoot,
                  &oneDeviceData->tdIDTimer
                  );
  }
  else
  {
    tdsaSingleThreadedLeave(tiRoot, TD_TIMER_LOCK);
  }

  tdsaSetTimerRequest(
                      tiRoot,
                      &oneDeviceData->tdIDTimer,
                      SATA_ID_DEVICE_DATA_TIMER_VALUE/Initiator->OperatingOption.UsecsPerTick,
                      tdIDStartTimerCB,
                      smIORequest,
                      oneDeviceData,
                      agNULL
                     );

  tdsaAddTimer(
               tiRoot,
               &Initiator->timerlist,
               &oneDeviceData->tdIDTimer
              );
  TI_DBG1(("tdIDStartTimer: end\n"));
  return;
}

osGLOBAL void
tdIDStartTimerCB(
                  tiRoot_t    * tiRoot,
                  void        * timerData1,
                  void        * timerData2,
                  void        * timerData3
                )
{
  tdsaRoot_t         *tdsaRoot      = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t      *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  smIORequest_t      *smIORequest;
  tdsaDeviceData_t   *oneDeviceData;
  smRoot_t           *smRoot;
  tdIORequestBody_t  *tdIORequestBody;
  smDeviceHandle_t   *smDeviceHandle;
  tdsaPortContext_t  *onePortContext;
#ifdef REMOVED
  agsaRoot_t         *agRoot;
  bit32               IDstatus;
//#endif
//#ifdef REMOVED
  agsaIORequest_t    *agAbortIORequest = agNULL;
  tdIORequestBody_t  *tdAbortIORequestBody = agNULL;
  bit32               PhysUpper32;
  bit32               PhysLower32;
  bit32               memAllocStatus;
  void               *osMemHandle;
#endif // REMOVED
#ifdef  TD_DEBUG_ENABLE
  bit32               status = AGSA_RC_FAILURE;
#endif

  TI_DBG1(("tdIDStartTimerCB start\n"));
  smIORequest = (smIORequest_t *)timerData1;
  oneDeviceData = (tdsaDeviceData_t *)timerData2;
  smRoot = &(tdsaAllShared->smRoot);
#ifdef REMOVED
  agRoot = oneDeviceData->agRoot;
#endif // REMOVED

  if (smIORequest == agNULL)
  {
    TI_DBG1(("tdIDStartTimerCB: smIORequest == agNULL !!!!!!\n"));
    return;
  }

  if (oneDeviceData == agNULL)
  {
    TI_DBG1(("tdIDStartTimerCB: oneDeviceData == agNULL !!!!!!\n"));
    return;
  }

  if (oneDeviceData->satDevData.IDPending == agFALSE || oneDeviceData->satDevData.IDDeviceValid == agTRUE)
  {
     /*the Identify Device command already normally completed, just return*/
     return;
  }

  tdIORequestBody = (tdIORequestBody_t *)smIORequest->tdData;
  smDeviceHandle = (smDeviceHandle_t *)&(oneDeviceData->smDeviceHandle);
  onePortContext = oneDeviceData->tdPortContext;
  if (tdIORequestBody == agNULL)
  {
    TI_DBG1(("tdIDStartTimerCB: tdIORequestBody == agNULL !!!!!!\n"));
    return;
  }

  if (smDeviceHandle == agNULL)
  {
    TI_DBG1(("tdIDStartTimerCB: smDeviceHandle == agNULL !!!!!!\n"));
    return;
  }

  if (onePortContext == agNULL)
  {
    TI_DBG1(("tdIDStartTimerCB: onePortContext == agNULL !!!!!!\n"));
    return;
  }

  TI_DBG1(("tdIDStartTimerCB: did %d\n", oneDeviceData->id));
  /*
   1. smIOabort()
   2. in tdsmIDCompletedCB(), retry
  */
  if (oneDeviceData->valid == agFALSE)
  {
    TI_DBG1(("tdIDStartTimerCB: invalid device\n"));
    return;
  }
#ifdef  TD_DEBUG_ENABLE
  status = smIOAbort( smRoot, smIORequest );
#else
  smIOAbort( smRoot, smIORequest );
#endif

#ifdef REMOVED
  /* allocating agIORequest for abort itself */
  memAllocStatus = ostiAllocMemory(
                                   tiRoot,
                                   &osMemHandle,
                                   (void **)&tdAbortIORequestBody,
                                   &PhysUpper32,
                                   &PhysLower32,
                                   8,
                                   sizeof(tdIORequestBody_t),
                                   agTRUE
                                   );
  if (memAllocStatus != tiSuccess)
  {
    /* let os process IO */
    TI_DBG1(("tdIDStartTimerCB: ostiAllocMemory failed...; can't retry ID data \n"));
    return;
  }
  if (tdAbortIORequestBody == agNULL)
  {
    /* let os process IO */
    TI_DBG1(("tdIDStartTimerCB: ostiAllocMemory returned NULL tdAbortIORequestBody; can't retry ID data\n"));
    return;
  }
  /* setup task management structure */
  tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle = osMemHandle;
  /* setting callback but not used later */
  tdAbortIORequestBody->IOCompletionFunc = agNULL;
  //tdAbortIORequestBody->IOCompletionFunc = itdssIOAbortedHandler;
  tdAbortIORequestBody->tiDevHandle = (tiDeviceHandle_t *)&(oneDeviceData->tiDeviceHandle);
  /* initialize agIORequest */
  agAbortIORequest = &(tdAbortIORequestBody->agIORequest);
  agAbortIORequest->osData = (void *) tdAbortIORequestBody;
  agAbortIORequest->sdkData = agNULL; /* LL takes care of this */
//#endif
//#ifdef REMOVED
  status = saSATAAbort(agRoot,
                       agAbortIORequest,
                       0,
                       oneDeviceData->agDevHandle,
                       1, /* abort all */
                       agNULL,
                       ossaSATAIDAbortCB
                       );
  status = saSATAAbort(agRoot,
                       agAbortIORequest,
                       0,
                       oneDeviceData->agDevHandle,
                       0, /* abort one */
                       agIORequest,
                       ossaSATAIDAbortCB
                       );
//#endif
//#ifdef REMOVED
  if (status != AGSA_RC_SUCCESS)
  {
    TI_DBG1(("tdIDStartTimerCB: saSATAAbort failed; can't retry ID data\n"));
  }
  if (oneDeviceData->satDevData.IDDeviceValid == agTRUE)
  {
    TI_DBG1(("tdIDStartTimerCB: IDDeviceValid is valid, no need to retry\n"));
    return;
  }
  if (tdIORequestBody->reTries <= SM_RETRIES)
  {
    tdIORequestBody->tiIORequest = agNULL; /* not in use */
    tdIORequestBody->pid = onePortContext->id;
    smIORequest->tdData = tdIORequestBody;
    smIORequest->smData = &tdIORequestBody->smIORequestBody;
    smDeviceHandle->tdData = oneDeviceData;
    IDstatus = smIDStart(smRoot, smIORequest, smDeviceHandle );
    if (IDstatus == SM_RC_SUCCESS)
    {
      TI_DBG1(("tdIDStartTimerCB: being retried!!!\n"));
      tdIORequestBody->reTries++;
      tdIORequestBody->ioCompleted = agFALSE;
      tdIORequestBody->ioStarted = agTRUE;
      tdIDStartTimer(tiRoot, smIORequest, oneDeviceData);
    }
    else
    {
      /* identify device data is not valid */
      TI_DBG1(("tdIDStartTimerCB: smIDStart fail or busy %d!!!\n", IDstatus));
      tdIORequestBody->reTries = 0;
      tdIORequestBody->ioCompleted = agTRUE;
      tdIORequestBody->ioStarted = agFALSE;
      ostiFreeMemory( tiRoot,
                      tdIORequestBody->osMemHandle,
                      sizeof(tdIORequestBody_t)
                    );
      oneDeviceData->satDevData.IDDeviceValid = agFALSE;
      smReportRemoval(tiRoot, agRoot, oneDeviceData, onePortContext);
      return;
    }
  }
  else
  {
    /* give up */
    TI_DBG1(("tdIDStartTimerCB: retries are over!!!\n"));
    if (oneDeviceData->tdIDTimer.timerRunning == agTRUE)
    {
      tdsaKillTimer( tiRoot, &oneDeviceData->tdIDTimer );
    }
    tdIORequestBody->reTries = 0;
    tdIORequestBody->ioCompleted = agTRUE;
    tdIORequestBody->ioStarted = agFALSE;
    ostiFreeMemory(
                   tiRoot,
                   tdIORequestBody->osMemHandle,
                   sizeof(tdIORequestBody_t)
            );
    oneDeviceData->satDevData.IDDeviceValid = agFALSE;

    if (oneDeviceData->SMNumOfID <= 0) /* does SMP HARD RESET only upto one time */
    {
      TI_DBG1(("tdIDStartTimerCB: fail; sending HARD_RESET\n"));
      oneDeviceData->SMNumOfID++;
      if (oneDeviceData->directlyAttached == agTRUE)
      {
        saLocalPhyControl(agRoot, agNULL, 0, oneDeviceData->phyID, AGSA_PHY_HARD_RESET, agNULL);
      }
      else
      {
        tdsaPhyControlSend(tiRoot,
                           oneDeviceData,
                           SMP_PHY_CONTROL_HARD_RESET,
                           agNULL);
      }
    }
    else
    {
      /* given up after one time of SMP HARD RESET; */
      TI_DBG1(("tdIDStartTimerCB: fail; but giving up sending HARD_RESET!!!\n"));
      if (oneDeviceData->directlyAttached == agTRUE)
      {
        smReportRemovalDirect(tiRoot, agRoot, oneDeviceData);
      }
      else
      {
        smReportRemoval(tiRoot, agRoot, oneDeviceData, onePortContext);
      }
    }
  }
#endif // REMOVED

  TI_DBG1(("tdIDStartTimerCB: end, smIOAbort status %d\n", status));
  return;
}
#endif // FDS_SM


#if defined(FDS_DM) && defined(FDS_SM)
//start here
GLOBAL void
tdIDStart(
           tiRoot_t             *tiRoot,
           agsaRoot_t           *agRoot,
           smRoot_t             *smRoot,
           tdsaDeviceData_t     *oneDeviceData,
           tdsaPortContext_t    *onePortContext
          )
{
  tdsaRoot_t           *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
  tdsaContext_t        *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
  bit32                SMstatus = SM_RC_FAILURE;
  tdIORequestBody_t    *tdIORequestBody;
  smIORequest_t        *smIORequest;
  smDeviceHandle_t     *smDeviceHandle;
  bit32                PhysUpper32;
  bit32                PhysLower32;
  bit32                memAllocStatus;
  void                 *osMemHandle;


  TI_DBG1(("tdIDStart: start, did %d\n",oneDeviceData->id));
 
  if ( (DEVICE_IS_SATA_DEVICE(oneDeviceData)|| DEVICE_IS_STP_TARGET(oneDeviceData))
      &&
      oneDeviceData->satDevData.IDDeviceValid == agFALSE
      &&
      oneDeviceData->satDevData.IDPending == agFALSE
      )
  {
    TI_DBG2(("tdIDStart: in loop, did %d\n", oneDeviceData->id));
    /* allocating tdIORequestBody */
    memAllocStatus = ostiAllocMemory(
                                      tiRoot,
                                      &osMemHandle,
                                      (void **)&tdIORequestBody,
                                      &PhysUpper32,
                                      &PhysLower32,
                                      8,
                                      sizeof(tdIORequestBody_t),
                                      agTRUE
                                    );
    if (memAllocStatus != tiSuccess || tdIORequestBody == agNULL)
    {
      /* let os process IO */
      TI_DBG1(("tdIDStart: ostiAllocMemory failed... or ostiAllocMemory returned NULL tdIORequestBody!!!\n"));
      oneDeviceData->satDevData.IDDeviceValid = agFALSE;
      if (oneDeviceData->directlyAttached == agTRUE)
      {
        /* notifying link up */
        ostiPortEvent(
                       tiRoot,
                       tiPortLinkUp,
                       tiSuccess,
                       (void *)onePortContext->tiPortalContext
                     );
#ifdef INITIATOR_DRIVER
        /* triggers discovery */
        ostiPortEvent(
                       tiRoot,
                       tiPortDiscoveryReady,
                       tiSuccess,
                       (void *) onePortContext->tiPortalContext
                     );
#endif
      }
    }
    else
    {
      /* initialize */
      osti_memset(tdIORequestBody, 0, sizeof(tdIORequestBody_t));

      tdIORequestBody->osMemHandle = osMemHandle;
      TI_DBG2(("tdIDStart: tdIORequestBody %p  tdIORequestBody->osMemHandle %p\n", tdIORequestBody, tdIORequestBody->osMemHandle));

      /* not in use */
      tdIORequestBody->IOCompletionFunc = agNULL;
      tdIORequestBody->tiDevHandle = agNULL;

      tdIORequestBody->tiIORequest = agNULL; /* not in use */
      tdIORequestBody->pid = onePortContext->id;
      tdIORequestBody->reTries = 0;
      smIORequest = (smIORequest_t *)&(tdIORequestBody->smIORequest);
      smIORequest->tdData = tdIORequestBody;
      smIORequest->smData = &tdIORequestBody->smIORequestBody;

      smDeviceHandle = (smDeviceHandle_t *)&(oneDeviceData->smDeviceHandle);
      smDeviceHandle->tdData = oneDeviceData;

      TI_DBG2(("tdIDStart: smIORequest %p\n", smIORequest));

      SMstatus = smIDStart(smRoot,
                           smIORequest,
                           &(oneDeviceData->smDeviceHandle)
                           );

      if (SMstatus == SM_RC_SUCCESS)
      {
        if (oneDeviceData->directlyAttached == agTRUE)
        {
          TI_DBG2(("tdIDStart: successfully sent identify device data\n"));

          /* Add the devicedata to the mainlink */
          tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK);
          TDLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->MainLink), &(tdsaAllShared->MainDeviceList));
          tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
          TI_DBG6(("tdIDStart: one case did %d \n", oneDeviceData->id));
        }
        oneDeviceData->satDevData.IDPending = agTRUE;
        /* start a timer */
        tdIDStartTimer(tiRoot, smIORequest, oneDeviceData);
      }
      else
      {
        /* failed to send  */
        TI_DBG1(("tdIDStart: smIDStart fail or busy %d\n", SMstatus));

        /* free up allocated memory */
        ostiFreeMemory(
                   tiRoot,
                   tdIORequestBody->IOType.InitiatorTMIO.osMemHandle,
                   sizeof(tdIORequestBody_t)
                   );

        oneDeviceData->satDevData.IDDeviceValid = agFALSE;
        if (oneDeviceData->directlyAttached == agTRUE)
        {
          TI_DBG1(("tdIDStart: failed in sending identify device data\n"));
          /* put onedevicedata back to free list */
          tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK);
          TDLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->FreeLink), &(tdsaAllShared->FreeDeviceList));
          tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK);
          /* notifying link up */
          ostiPortEvent(
                         tiRoot,
                         tiPortLinkUp,
                         tiSuccess,
                         (void *)onePortContext->tiPortalContext
                       );
#ifdef INITIATOR_DRIVER
          /* triggers discovery */
          ostiPortEvent(
                         tiRoot,
                         tiPortDiscoveryReady,
                         tiSuccess,
                         (void *) onePortContext->tiPortalContext
                       );
#endif
        }
        else
        {
          smReportRemoval(tiRoot, agRoot, oneDeviceData, onePortContext);
        }
      }
    }
  }
  TI_DBG1(("tdIDStart: exit\n"));
  return;
}

#endif

#ifdef SALLSDK_OS_IOMB_LOG_ENABLE
GLOBAL void ossaLogIomb(agsaRoot_t  *agRoot,
                        bit32        queueNum,
                        agBOOLEAN      isInbound,
                        void        *pMsg,
                        bit32        msgLength)
{
  return;
}
#endif /* SALLSDK_OS_IOMB_LOG_ENABLE */

#ifndef SATA_ENABLE
/*
 * These callback routines are defined in ossasat.c which are included in the
 * compilation if SATA_ENABLED is defined.
 */

/*****************************************************************************
*! \brief ossaDiscoverSataCB
*
*  Purpose:  This function is called by lower layer to inform TD layer of
*            STP/SATA discovery results
*
*
*  \param   agRoot         Pointer to chip/driver Instance.
*  \param   agPortContext  Pointer to the port context of TD and Lower layer
*  \param   event          event type
*  \param   pParm1         Pointer to data associated with event
*  \param   pParm2         Pointer to data associated with event
*
*  \return: none
*
*  \note -  For details, refer to SAS/SATA Low-Level API Specification
*
*****************************************************************************/

osGLOBAL void ossaDiscoverSataCB( agsaRoot_t        *agRoot,
                    agsaPortContext_t *agPortContext,
                    bit32             event,
                    void              *pParm1,
                    void              *pParm2
                    )
{
  return;
}


/*****************************************************************************
*! \brief  ossaSATACompleted
*
*   This routine is called to complete a SATA request previously issued to the
*    LL Layer in saSATAStart()
*
*  \param   agRoot:      Handles for this instance of SAS/SATA hardware
*  \param   agIORequest: Pointer to the LL I/O request context for this I/O.
*  \param   agIOStatus:  Status of completed I/O.
*  \param   agFirstDword:Pointer to the four bytes of FIS.
*  \param   agIOInfoLen: Length in bytes of overrun/underrun residual or FIS
*                        length.
*  \param   agParam:     Additional info based on status.
*
*  \return: none
*
*****************************************************************************/
GLOBAL void ossaSATACompleted(
                  agsaRoot_t        *agRoot,
                  agsaIORequest_t   *agIORequest,
                  bit32             agIOStatus,
                  void              *agFirstDword,
                  bit32             agIOInfoLen,
                  void              *agParam
                  )
{
  return;
}


/*****************************************************************************
*! \brief  ossaSATAEvent
*
*   This routine is called to notify the OS Layer of an event associated with
*   SATA port or SATA device
*
*  \param   agRoot:        Handles for this instance of SAS/SATA hardware
*  \param   agIORequest:   Pointer to the LL I/O request context for this I/O.
*  \param   agPortContext  Pointer to the port context of TD and Lower layer
*  \param   agDevHandle:   Pointer to a device handle
*  \param   event:         event type
*
*  \return: none
*
*****************************************************************************/
osGLOBAL void ossaSATAEvent(
                        agsaRoot_t        *agRoot,
                        agsaIORequest_t   *agIORequest,
                        agsaPortContext_t *agPortContext,
                        agsaDevHandle_t   *agDevHandle,
                        bit32             event,
                        bit32             agIOInfoLen,
                        void              *agParam
                        )
{
  return;
}


/*****************************************************************************
*! \brief  ossaSATADeviceResetCB
*
*   This routine is called to complete a SATA device reset request previously
*   issued to the LL Layer in saSATADeviceReset().
*
*  \param agRoot:      Handles for this instance of SAS/SATA hardware
*  \param agDevHandle: Pointer to a device handle
*  \param resetStatus: Reset status:
*                      OSSA_SUCCESS: The reset operation completed successfully.
*                      OSSA_FAILURE: The reset operation failed.
*  \param resetparm:  Pointer to the Device-To-Host FIS received from the device.
*
*  \return: none
*
*****************************************************************************/
osGLOBAL void ossaSATADeviceResetCB(
                      agsaRoot_t        *agRoot,
                      agsaDevHandle_t   *agDevHandle,
                      bit32             resetStatus,
                      void              *resetparm)
{

  return;

}

/*****************************************************************************
*! \brief ossaDiscoverSasCB
*
*  Purpose:  This function is called by lower layer to inform TD layer of
*            SAS discovery results
*
*
*  \param   agRoot         Pointer to chip/driver Instance.
*  \param   agPortContext  Pointer to the port context of TD and Lower layer
*  \param   event          event type
*  \param   pParm1         Pointer to data associated with event
*  \param   pParm2         Pointer to data associated with event
*
*  \return: none
*
*  \note -  For details, refer to SAS/SATA Low-Level API Specification
*
*****************************************************************************/
osGLOBAL void ossaDiscoverSasCB(agsaRoot_t        *agRoot,
                  agsaPortContext_t *agPortContext,
                  bit32             event,
                  void              *pParm1,
                  void              *pParm2
                  )
{
  return;
}
#endif