/**
  Mallocs a memory (virtual) using OS Malloc API.

  Mallocs a memory (virtual) using OS Malloc API. The memory allocated
  is for SW usage only.

  @param[in]  size    Size of the memory to be allocated

  @return
  Pointer to the memory allocated. NULL if failed.

  @sa
  bam_osal_mallocmemregion, bam_osal_free
*/
void * bam_osal_malloc(uint32 size)
{
    void *ptr;
#if defined(BAM_MBA)
    ptr = qurt_malloc(size);
#elif defined(BAM_TZOS)
    ptr = tzbsp_malloc(size);
#else
    DALResult res = DALSYS_Malloc(size, &ptr);

    if (res != DAL_SUCCESS)
    {
        return NULL;
    }
#endif
    return ptr;
}
static DALResult _AllocateMemForBitMasks(uint32** pMask, uint32 uNumBits)
{

   uint32 uMemSize = sizeof(uint32) * (ROUND_UP_32(uNumBits)/32);

//LHT add size check because DALSYS_Malloc will assert after
//DALHeap_Malloc fails on request of size zero.
   if (0 < uMemSize)
   {
      if(DAL_SUCCESS != DALSYS_Malloc(uMemSize, (void **)pMask))
      {
         return DAL_ERROR;
      }

      memset(*pMask, 0, uMemSize);
   }
   return DAL_SUCCESS;
}
/*------------------------------------------------------------------------------
User API to Register Work Loop
-------------------------------------------------------------------------------*/
static DALResult
registerWorkLoop( char *pszname,
      uint32 dwStackSize,
      uint32 dwPriority,
      void * ownerRetAddr,
      DALSYSWorkLoopHandle *phWorkLoop,
      DALSYSWorkLoopObj *pObj)
{
   _DALSYSWorkLoopObj *pWorkLoopObj = (_DALSYSWorkLoopObj *)pObj;

   if (!phWorkLoop)
   {
      DALSYS_LOG_ERROR_EVENT("phWorkLoop is NULL- workloop:%s", 
            pszname);
      return DAL_ERROR;
   }
   *phWorkLoop = NULL;

   if(NULL == pWorkLoopObj)
   {
      /*----------------------------------------------------------------------
      User has not passed in WorkLoop object, we need to allocate memory.
      Always get the size form the DALSYS Macros. This is done to support
      static allocation and maintain consistency between sizes of statically
      and dynamically alloced structures.
      ----------------------------------------------------------------------*/

      if(DAL_SUCCESS != DALSYS_Malloc(sizeof(_DALSYSWorkLoopObj), (void**)&pWorkLoopObj))
         return DAL_ERROR;

      memset(pWorkLoopObj,0,sizeof(_DALSYSWorkLoopObj));
      DALSYSCMN_SET_DYNAMIC_ALLOC_BIT(pWorkLoopObj->dwObjInfo);
   }
   else
   {
      /*----------------------------------------------------------------------
      User has allocated memory allocate memory, we dont allocate memory
      ----------------------------------------------------------------------*/
      memset(pWorkLoopObj,0,sizeof(_DALSYSWorkLoopObj));
   }

   /*--------------------------------------------------------------------------
   Initialize the remaining data structure
   --------------------------------------------------------------------------*/
   if(DAL_SUCCESS != DALSYS_SyncCreate(DALSYS_SYNC_ATTR_NO_PREEMPTION,
         &pWorkLoopObj->hSync, NULL))
   {
      goto wl_reg_error_1;
   }

   // allocate memory for thread stack.
   if (DAL_SUCCESS != DALSYS_Malloc(dwStackSize, 
       (void**)&pWorkLoopObj->pStackBuffer ))
   {
      goto wl_reg_error_2;
   }

   DALSYSCMN_SET_OBJECT_ID(pWorkLoopObj->dwObjInfo,DALSYSCMN_WORKLOOP_OBJECT_ID);
   qurt_anysignal_init(&pWorkLoopObj->signal);

   if (!dwPriority || dwPriority > 255)
   {
      dwPriority = DALSYS_WL_DEFAULT_PRIO;
   }
   DALSYSCMN_SET_ATTRIB(pWorkLoopObj->dwObjInfo,(dwPriority<<4));

   // setting debug information
   pWorkLoopObj->ownerThreadId = qurt_thread_get_id();
   pWorkLoopObj->ownerRetAddr = ownerRetAddr;
   pWorkLoopObj->thisVirtualAddr = (DALSYSMemAddr)pWorkLoopObj;

   if (DAL_SUCCESS == DALSYS_WorkLoopThreadCreate( pWorkLoopObj, pszname, dwStackSize, dwPriority ) )
   {
      *phWorkLoop = pWorkLoopObj;
      return DAL_SUCCESS;
   }

   // workloop creation failed - need to cleanup
   qurt_anysignal_destroy(&pWorkLoopObj->signal);

   DALSYS_Free(pWorkLoopObj->pStackBuffer);

wl_reg_error_2:
   DALSYS_DestroyObject( pWorkLoopObj->hSync );

wl_reg_error_1:
   if(DALSYSCMN_IS_OBJ_DYNAMICALLY_ALLOCED(pWorkLoopObj->dwObjInfo))
      DALSYS_Free(pWorkLoopObj); /* If dynamically alloced free memory */
   else /*Statically alloced object, reset all fields to ZERO*/
      memset(pWorkLoopObj,0,sizeof(_DALSYSWorkLoopObj));

   DALSYS_LOG_ERROR_EVENT("failed- pszname:%s", pszname);
   return DAL_ERROR;
}
/*==================================================================================================
  @brief FTM driver open

  This API can be used to open the FTM driver.

  @param DriverHdl:   Input -   handle created in Audio_FTM_Attach
         AccessMode:  Input -   Read/Write/RD_WR
         ShareMode:   Input -   Exclusive or Share
         pClientHdl:  Output -  point to the returned Open handle

  @return return code, AUDIO_FTM_SUCCESS on successful completion, error code otherwise
==================================================================================================*/
AUDIO_FTM_STS_T
audio_ftm_toneplay_open
(
    AUDIO_FTM_DRIVER_HANDLE_T pDriverContext ,  /* Input: driver handle */
    AUD_FTM_ACCESS_MODE_T AccessMode,           /* Input: Access mode */
    AUD_FTM_SHARE_MODE_T  ShareMode,            /* Input: Share mode */
    AUDIO_FTM_CLIENT_HANDLE_T * pClientContext  /* Output: client handle */
)
{
    Aud_FTM_DrvCtxt_T * pDrvCxt = (Aud_FTM_DrvCtxt_T *)pDriverContext;
    Aud_FTM_ClientCtxt_T * pOpenContext = NULL;
    AUDIO_FTM_STS_T  res;
    int16 i;
    uint32 dev_buf_size, fifo_buf_size;

    if (pDrvCxt == NULL)
    {
        DALSYS_Log_Err("%s: failed %d\n",__func__,__LINE__);
        return AUDIO_FTM_ERR_INVALID_PARAM;
    }

    DALSYS_SyncEnter(pDrvCxt->hClientSync);

    if((ShareMode == AUD_FTM_SHAREMODE_EXCLU ) && (DALSYS_atomic_read(&pDrvCxt->dwOpenCount) != 0))
        /* ShareMode = 0: exclusive mode; =FILE_SHARE_READ: read only; =FILE_SHARE_WRITE: write only */
    {
        DALSYS_SyncLeave(pDrvCxt->hClientSync);
        DALSYS_Log_Err("%s: failed %d\n",__func__,__LINE__);
        return AUDIO_FTM_ERROR;
    }

  if(DAL_SUCCESS != DALSYS_Malloc(sizeof(Aud_FTM_ClientCtxt_T), (void **)&pOpenContext))
    {
        DALSYS_Log_Err("%s: failed %d\n",__func__,__LINE__);
        DALSYS_SyncLeave(pDrvCxt->hClientSync);
        return AUDIO_FTM_ERR_MEM_ALLOC_FAIL;
    }

    if (pOpenContext == NULL)
    {
      DALSYS_SyncLeave(pDrvCxt->hClientSync);
        DALSYS_Log_Err("%s: failed %d\n",__func__,__LINE__);
      return AUDIO_FTM_ERR_MEM_ALLOC_FAIL;
    }
  DALSYS_memset(pOpenContext,0,sizeof(Aud_FTM_ClientCtxt_T));

    // Store device settings for future use
    pOpenContext->pDrvCtxt = pDrvCxt;
    pOpenContext->dwAccessCode = AccessMode;
    pOpenContext->dwShareMode = ShareMode;

  pOpenContext->dwClientID=DALSYS_atomic_read(&pDrvCxt->dwOpenCount);

  pDrvCxt->apClientCtxt[pOpenContext->dwClientID]=pOpenContext;

#ifdef MSM8960_ALSA
  pDrvCxt->pDevCtxt->read_write_flag = PCM_OUT;
#endif

  /***** open HW *****/
  DALSYS_Log_Info("%s: open hw\n",__func__);
  pDrvCxt->pDevCtxt->playbackdevice =
  pDrvCxt->pDevCtxt->pDrvCtxt->client_param.device;
  res=audio_ftm_hw_open(pDrvCxt->pDevCtxt);
  if(res != AUDIO_FTM_SUCCESS)
  {
    DALSYS_Log_Err("%s: failed %d\n",__func__,__LINE__);
    DALSYS_SyncLeave(pDrvCxt->hClientSync);
    return AUDIO_FTM_ERROR;
  }

    audio_ftm_hw_iocontrol(pDrvCxt->pDevCtxt, IOCTL_AUDIO_FTM_RX_DEV_BUF_SIZE, NULL, 0, &dev_buf_size, sizeof(dev_buf_size), NULL);
    pDrvCxt->nRx_blk_convey_samples=dev_buf_size/sizeof(int16);

  /********* init circular buf ********/
    fifo_buf_size=dev_buf_size*AUD_FTM_TONE_PLAY_FIFO_FACTOR+4;    // reserve 4 bytes

  DALSYS_Log_Info("%s: init buf\n",__func__);
  aud_ftm_cbuf_init(&(pDrvCxt->fifo_data_buf), fifo_buf_size);

  if(DAL_SUCCESS != DALSYS_Malloc(dev_buf_size*AUD_FTM_TONE_PLAY_FIFO_FACTOR, (void **)&pTmpBuf))  /* buffer for DTMF data producing */
  {
          DALSYS_SyncLeave(pDrvCxt->hClientSync);
      DALSYS_Log_Err(" pTmpBuf allocation fail\n");
      return DAL_ERROR;
    }
  DALSYS_memset(pTmpBuf,0,dev_buf_size*AUD_FTM_TONE_PLAY_FIFO_FACTOR);

  if(DAL_SUCCESS != DALSYS_Malloc(dev_buf_size, (void **)&pAud_ftm_rx_buf))  /* buffer for fetch data from FIFO and pass to low layer driver for consuming */
  {
          DALSYS_SyncLeave(pDrvCxt->hClientSync);
      DALSYS_Log_Err(" pAud_ftm_rx_buf allocation fail\n");
      return DAL_ERROR;
    }
  DALSYS_memset(pAud_ftm_rx_buf,0,dev_buf_size);

  /***** prefill the circular buffer with DTMF data *****/

  for(i=0; i<((dev_buf_size*AUD_FTM_TONE_PLAY_FIFO_FACTOR)/sizeof(int16)); i++)
  {
    *(pTmpBuf+i)=audio_ftm_dtmf_tone_sample_gen(&(pDrvCxt->dtmfGen),pDrvCxt->nDTMF_Gain);
  }
  aud_ftm_cbuf_write (&(pDrvCxt->fifo_data_buf),(uint8 *)pTmpBuf,(int32)(dev_buf_size*AUD_FTM_TONE_PLAY_FIFO_FACTOR));

    // Increase opened device counter
  AddRef(&pDrvCxt->dwOpenCount);
    pDrvCxt->bOpened=TRUE;

    DALSYS_SyncLeave(pDrvCxt->hClientSync);

    *pClientContext=  (AUDIO_FTM_CLIENT_HANDLE_T)pOpenContext;

    return AUDIO_FTM_SUCCESS;
}
AUDIO_FTM_STS_T
audio_ftm_toneplay_attach
(
    void *pParam,                                 /* Input: parameters  */
    AUDIO_FTM_DRIVER_HANDLE_T *pDriverHdl        /* Output: driver handle */
)
{
  /************* Context creation ***********/

  Aud_FTM_DevCtxt_T *pDeviceCtxt;
  Aud_FTM_DrvCtxt_T *pDriverCtxt;

    Aud_FTM_HW_INIT_PARAM_T hw_param;
    int16 freq1,freq2, sampling_freq;

    AUDIO_FTM_STS_T sts;

    if (g_bDriverInitialized)
  {
      DALSYS_Log_Err("%s: error: already initialized\n", __func__);
        return  AUDIO_FTM_ERROR;    //  already inited,
  }

  DALSYS_Log_Info("Attach TonePlay Driver\n");

    /****************** create context object ******************/

  if((DAL_SUCCESS != DALSYS_Malloc(sizeof(Aud_FTM_DevCtxt_T), (void **)&pDeviceCtxt)) ||
        (pDeviceCtxt == NULL))
    {
      DALSYS_Log_Err("Memory allocation fail\n");
        return AUDIO_FTM_ERR_MEM_ALLOC_FAIL;
    }

  DALSYS_memset(pDeviceCtxt,0,sizeof(Aud_FTM_DevCtxt_T));

  if((DAL_SUCCESS != DALSYS_Malloc(sizeof(Aud_FTM_DrvCtxt_T), (void **)&pDriverCtxt)) ||
        (pDriverCtxt == NULL))
    {
      DALSYS_Log_Err("Memory allocation fail\n");
                DALSYS_Free(pDeviceCtxt);
        return AUDIO_FTM_ERR_MEM_ALLOC_FAIL;
    }

  DALSYS_memset(pDriverCtxt,0,sizeof(Aud_FTM_DevCtxt_T));

    DALSYS_atomic_init(&pDriverCtxt->dwOpenCount);
    pDriverCtxt->pDevCtxt=pDeviceCtxt;
    pDeviceCtxt->pDrvCtxt=pDriverCtxt;

  /************* Create Critical Section ***********/

    if(DAL_SUCCESS != DALSYS_SyncCreate(DALSYS_SYNC_ATTR_RESOURCE,
        &(pDriverCtxt->hClientSync),
        NULL))
    {
      DALSYS_Log_Err("hClientSync creation fail\n");
        return AUDIO_FTM_ERROR;
    }

   if(DAL_SUCCESS != DALSYS_EventCreate(DALSYS_EVENT_ATTR_WORKLOOP_EVENT,       //Not used for work loops
                              &(pDriverCtxt->hReq_Data_Event),          //Return event handle
                              NULL))
   {
    DALSYS_Log_Err("%s: failed to create event\n", __func__);
    DALSYS_SyncLeave(pDriverCtxt->hClientSync);
    DALSYS_Free(pDriverCtxt->hClientSync);
    return AUDIO_FTM_ERROR;
   }

    /*************  hardware initialization ***********/

   DALSYS_memcpy((uint8*)&(pDriverCtxt->client_param),
                  (uint8*)pParam, sizeof(AUD_FTM_TONE_PLAY_PARAM_T));

   hw_param.inpath=AUDIO_FTM_IN_INVALID;
   hw_param.outpath=pDriverCtxt->client_param.path.outpath;
   hw_param.rate=AUDIO_FTM_PCM_RATE_8K;
   hw_param.width=AUDIO_FTM_BIT_WIDTH_16;
   hw_param.channel=AUDIO_FTM_CHN_1;
   hw_param.gain=pDriverCtxt->client_param.gain;
     hw_param.bLoopbackCase=FALSE;

   sts=aud_ftm_hw_init(pDeviceCtxt, &hw_param);
   if(sts != AUDIO_FTM_SUCCESS) {
      DALSYS_Log_Err("%s: failed to init hw\n", __func__);
        return AUDIO_FTM_ERROR;
   }

      /* Tone generator init */

    freq1=((AUD_FTM_TONE_PLAY_PARAM_T*)pParam)->dtmf_low;
    freq2=((AUD_FTM_TONE_PLAY_PARAM_T*)pParam)->dtmf_hi;
    sampling_freq=8000;

    audio_ftm_dtmf_tone_init(&(pDriverCtxt->dtmfGen),freq1,freq2,sampling_freq);
    pDriverCtxt->nDTMF_Gain = vol_map[3];

    /***** end of Init *****/

        pDriverCtxt->bOpened=FALSE;
      g_bDriverInitialized=TRUE;
    *pDriverHdl=(AUDIO_FTM_DRIVER_HANDLE_T)pDriverCtxt;

      return AUDIO_FTM_SUCCESS;

}
static DALResult
HWEvent_DeviceInit(DalDeviceHandle *h)
{
      DALClientCtxt * pClientCtxt = (DALClientCtxt *)(h->pClientCtxt);
      HWEventDevCtxt *pDevCtxt;
      DALSYSPropertyVar PropVar;
      uint32 uNumReg,phys_addr,virt_addr=NULL;
      DALResult uFound;

      HWEventRegisterValue *pConfigTable;
      HWEventTableSize *pConfigTableSize;
      uint32 i;

      pDevCtxt=(HWEventDevCtxt *)pClientCtxt->pDALDevCtxt;

      if(DAL_SUCCESS!=DALSYS_GetDALPropertyHandleStr(pClientCtxt->pDALDevCtxt->strDeviceName,
         pDevCtxt->hProp))
      {
         return DAL_ERROR;
      }

      if (DAL_SUCCESS!= DALSYS_GetPropertyValue(pDevCtxt->hProp,
                        "hwevent_config",
                        0,
                        &PropVar ))
      {
         return DAL_ERROR;
      }
      pConfigTable=(HWEventRegisterValue *)PropVar.Val.pStruct;
      pDevCtxt->pConfigTable=pConfigTable;

      if (DAL_SUCCESS!= DALSYS_GetPropertyValue(pDevCtxt->hProp,
                        "hwevent_config_size",
                        0,
                        &PropVar ))
      {
         return DAL_ERROR;
      }
      pConfigTableSize=(HWEventTableSize *)PropVar.Val.pStruct;
      uNumReg=pConfigTableSize->size;
      pDevCtxt->uTableSize=uNumReg;

      if (DAL_SUCCESS!= DALSYS_GetPropertyValue(pDevCtxt->hProp,
                        "hwevent_addr_check",
                        0,
                        &PropVar ))
      {
         return DAL_ERROR;
      }
      pDevCtxt->pAddrRangeTable=(HWEventAddrRange *)PropVar.Val.pStruct;

      if (DAL_SUCCESS!= DALSYS_GetPropertyValue(pDevCtxt->hProp,
                        "hwevent_addr_check_size",
                        0,
                        &PropVar ))
      {
         return DAL_ERROR;
      }

      pConfigTableSize=(HWEventTableSize *)PropVar.Val.pStruct;
      pDevCtxt->uAddrRangeTableSize = pConfigTableSize->size;

     /*allocate memory to store virtual address of registers*/
      if (DAL_SUCCESS!=DALSYS_Malloc(uNumReg*sizeof(HWEventMemMap),
                        (void **)&pDevCtxt->pMemMapTable))
      {
         return DAL_ERROR;
      }
      memset(pDevCtxt->pMemMapTable,0x0,uNumReg*sizeof(HWEventMemMap));

      for(i=0;i<uNumReg;i++)
      {
         phys_addr= HWIO_PAGE_BASE(pConfigTable[i].reg_phys_addr);
         /*end of table*/
         if (phys_addr==NULL)
         {
            break;
         }
         uFound = HWEvent_FindPhysAddrMapping(phys_addr,&virt_addr,pDevCtxt);
         if (uFound==DAL_ERROR)
         {
            if (DAL_SUCCESS!=HWEvent_AddPhysAddrMapping(phys_addr,&virt_addr,pDevCtxt))
            {
               return DAL_ERROR;
            }
         }
      }

   return DAL_SUCCESS;
}
DALResult Clock_InitImage
(
  ClockDrvCtxt *pDrvCtxt
)
{
  DALResult eRes;
  uint32 nMaxPL, nMaxQDSP6Config, nIdx, nSupportedIdx;
  ClockPropertyValueType PropVal = NULL;
  ClockImageConfigType *pImageCfg = NULL;
  ClockSourceInitType* pInitSources = NULL;
  DalDeviceHandle *hTLMM = NULL;
  DalDeviceHandle *hPlatInfo = NULL;
  DalPlatformInfoPlatformInfoType PlatformInfo;
  uint32 *pGPIO = NULL;
  HAL_clk_HWIOBaseType *pHWIOBases = NULL;
  uint32 anSourceIndex;

  /*-----------------------------------------------------------------------*/
  /* Get the CPU Configurations.                                           */
  /*-----------------------------------------------------------------------*/

  if(DAL_SUCCESS != Clock_GetPropertyValue("ClockImageConfig", &PropVal))
  {
    return(DAL_ERROR);
  }

  pImageCfg = (ClockImageConfigType*)PropVal;
  nSupportedIdx = 0;

  if (pImageCfg != NULL)
  {
    /* 
     * Get the number of supported configs on this chipset.
     */
    for (nIdx = 0; nIdx < pImageCfg->pCPUPerfConfig->nTotalConfigs; nIdx++)
    {
      if (Clock_IsBSPSupported(&pImageCfg->pCPUConfig[nIdx].Mux.HWVersion))
      {
        nSupportedIdx++;
      }
    }

    if (nSupportedIdx == 0)
    {
      return(DAL_ERROR);
    }

    Clock_LPASSCtxt.pImageConfig = &Clock_ImageConfig;

    eRes = DALSYS_Malloc(sizeof(ClockCPUConfigType)*nSupportedIdx, (void **)&Clock_LPASSCtxt.pImageConfig->pCPUConfig);

    if (eRes != DAL_SUCCESS) 
    {
      DALSYS_LogEvent (
        DALDEVICEID_CLOCK, DALSYS_LOGEVENT_FATAL_ERROR,
        "Unable to allocate pImageConfig buffer for Q6 clock controller.");
      return eRes;
    }
    memset(Clock_LPASSCtxt.pImageConfig->pCPUConfig, 0, sizeof(ClockCPUConfigType)*nSupportedIdx);

    nSupportedIdx = 0;

    /* 
     * Add each supported configuration into the new CPU configuration array.
     */
    for (nIdx=0; nIdx < pImageCfg->pCPUPerfConfig->nTotalConfigs; nIdx++)
    {
      if (Clock_IsBSPSupported(&pImageCfg->pCPUConfig[nIdx].Mux.HWVersion))
      {
        Clock_LPASSCtxt.pImageConfig->pCPUConfig[nSupportedIdx] = pImageCfg->pCPUConfig[nIdx];
        nSupportedIdx++;
      }
    }
  }
  else
  {
    DALSYS_LogEvent (
      DALDEVICEID_CLOCK, DALSYS_LOGEVENT_FATAL_ERROR,
      "Unable to get QDSP6 Image Configuration information from the BSP!.");
    return(DAL_ERROR);
  }

  /* 
   * Fill in remaining fields from the BSP here.
   */
  Clock_LPASSCtxt.pImageConfig->pCPUPerfConfig = pImageCfg->pCPUPerfConfig;
  Clock_LPASSCtxt.pImageConfig->nTotalSupportedConfigs  = nSupportedIdx;
  Clock_LPASSCtxt.pImageConfig->bGlobalLDOEnable = pImageCfg->bGlobalLDOEnable;
  Clock_LPASSCtxt.pImageConfig->bIsFusionMDM = pImageCfg->bIsFusionMDM;
  Clock_LPASSCtxt.pImageConfig->pIntermediateCPUConfig = pImageCfg->pIntermediateCPUConfig;


  /*-----------------------------------------------------------------------*/
  /* Initialize the Q6SS HWIO Base address.                                */
  /*-----------------------------------------------------------------------*/

  if(Clock_nHWIOBaseLPASS == 0)
  {
    eRes = Clock_GetPropertyValue("ClockLDOBase", &PropVal);

    if (eRes != DAL_SUCCESS)
    {
      return(eRes);
    }

    pHWIOBases = (HAL_clk_HWIOBaseType*)PropVal;

    if (pHWIOBases != NULL)
    {
      Clock_MapHWIORegion(
        pHWIOBases->nPhysAddr, pHWIOBases->nSize, &Clock_nHWIOBaseLPASS);

      /*
       * If we are unable to map a virtual address, assume the physical one.
       */
      if(Clock_nHWIOBaseLPASS == NULL)
      {
        Clock_nHWIOBaseLPASS = pHWIOBases->nPhysAddr;
      }
    }
    else
    {
      /*
       * We were unable to get the base address.
       */
      return(DAL_ERROR);
    }
  }

  /*-----------------------------------------------------------------------*/
  /* Get QDSP6 core/cpu clock ID.                                          */
  /*-----------------------------------------------------------------------*/

  eRes =
    Clock_GetClockId(
      pDrvCtxt, "lpass_q6core",
      (ClockIdType *)&Clock_LPASSCtxt.QDSP6Ctxt.pQDSP6Clock);

  if (eRes != DAL_SUCCESS) 
  {
    DALSYS_LogEvent (
      DALDEVICEID_CLOCK, DALSYS_LOGEVENT_FATAL_ERROR,
      "Unable to get Q6LPASS core clock ID.");
    return eRes;

  }

  /*
   * Increase the reference count on the LPAPLL2 to ensure Q6 clock 
   * switching does not disable the PLL that the bus is currently on. 
   */
  anSourceIndex = pDrvCtxt->anSourceIndex[HAL_CLK_SOURCE_LPAPLL2];
  pDrvCtxt->aSources[anSourceIndex].nReferenceCountSuppressible++;

  pDrvCtxt->pImageCtxt = &Clock_LPASSCtxt;

  /*-----------------------------------------------------------------------*/
  /* Detect initial QDSP6 core clock frequency configuration.              */
  /*-----------------------------------------------------------------------*/

  eRes = Clock_DetectQDSP6Config(pDrvCtxt);

  if (eRes != DAL_SUCCESS) 
  {
    DALSYS_LogEvent (
      DALDEVICEID_CLOCK, DALSYS_LOGEVENT_FATAL_ERROR,
      "Unable to detect Q6LPASS core clock configuration.");
    return eRes;
  }

  if (DAL_SUCCESS != DAL_DeviceAttach(DALDEVICEID_PLATFORMINFO, &hPlatInfo))
  {
    return(DAL_ERROR);
  }

  if(DAL_SUCCESS != DalPlatformInfo_GetPlatformInfo(hPlatInfo,  &PlatformInfo))
  {
    return(DAL_ERROR);
  }

  /*-----------------------------------------------------------------------*/
  /* Initialize the Q6PLL if applicable to this chipset.                   */
  /*-----------------------------------------------------------------------*/

  if(DAL_SUCCESS == Clock_GetPropertyValue("ClockSourcesToInit", &PropVal))
  {
    pInitSources = (ClockSourceInitType*)PropVal;

    if (pInitSources != NULL)
    {
      nIdx = 0;
      while (pInitSources[nIdx].eSource != HAL_CLK_SOURCE_NULL)
      {
        Clock_InitSource(pDrvCtxt,
                         pInitSources[nIdx].eSource,
                         pInitSources[nIdx].nFreqHz);
        nIdx++;
      }
    }
  }

  /*
   * on MSM8994 the LPAPLL2 is already in use.  Update the 
   * settings here. 
   */
  if (DalChipInfo_ChipFamily() == DALCHIPINFO_FAMILY_MSM8994)
  {
    nIdx = pDrvCtxt->anSourceIndex[HAL_CLK_SOURCE_LPAPLL2];
    pDrvCtxt->aSources[nIdx].pActiveFreqConfig = 
      pDrvCtxt->aSources[nIdx].pBSPConfig->pSourceFreqConfig;
  }


  /*-----------------------------------------------------------------------*/
  /* Ensure that the Q6LPASS clock/domain/source reference counts are '1'. */
  /*-----------------------------------------------------------------------*/

  Clock_EnableClock(pDrvCtxt, 
    (ClockIdType)Clock_LPASSCtxt.QDSP6Ctxt.pQDSP6Clock);


  /*-----------------------------------------------------------------------*/
  /* Run QDSP6 at max performance level - if DCVS is enable then we'll     */
  /* go to lower performance level later.                                  */
  /*-----------------------------------------------------------------------*/

  nMaxPL = Clock_LPASSCtxt.pImageConfig->pCPUPerfConfig->nInitPerfLevel;

  /* 
   * Configure the PLL to one less than max for low power initialization.
   */

  nMaxQDSP6Config = Clock_LPASSCtxt.pImageConfig->pCPUPerfConfig->panPerfLevel[nMaxPL];
 

  if (Clock_LPASSCtxt.QDSP6Ctxt.pCPUConfig != 
        &Clock_LPASSCtxt.pImageConfig->pCPUConfig[nMaxQDSP6Config])
  {
    Clock_SetQDSP6Config(
      pDrvCtxt, &Clock_LPASSCtxt.pImageConfig->pCPUConfig[nMaxQDSP6Config]);
  }

  /*-----------------------------------------------------------------------*/
  /*  Check for Fusion, which requires a different input source to the     */
  /*  LPAPLL.                                                              */
  /*-----------------------------------------------------------------------*/

  if ((DalPlatformInfo_IsFusion()) && 
      (PlatformInfo.version == DALPLATFORMINFO_VERSION(1,0)) &&
      (TRUE == Clock_LPASSCtxt.pImageConfig->bIsFusionMDM))
  {
    if(DAL_SUCCESS != Clock_GetPropertyValue("ClockARCGPIO", &PropVal))
    {
      return(DAL_ERROR);
    }

    pGPIO = (uint32*)PropVal;

    if(DAL_SUCCESS != DAL_DeviceAttach(DALDEVICEID_TLMM, &hTLMM))
    {
      return(DAL_ERROR);
    }

    for (nIdx = 0; pGPIO[nIdx] != 0xFFFFFFFF; ++nIdx)
    {
      DalTlmm_ConfigGpio(hTLMM, pGPIO[nIdx], DAL_TLMM_GPIO_ENABLE);
    }

    Clock_InitSwitchPLLSource(pDrvCtxt);
  }

  /*-----------------------------------------------------------------------*/
  /* Initialize the DCVS module.                                           */
  /*-----------------------------------------------------------------------*/

  Clock_InitDCVS(pDrvCtxt);

  /*-----------------------------------------------------------------------*/
  /* Initialize the XO module.                                             */
  /*-----------------------------------------------------------------------*/

  Clock_InitXO(pDrvCtxt);

  /*-----------------------------------------------------------------------*/
  /* Initialize LDO Voltage control for supported chipsets.                */
  /*-----------------------------------------------------------------------*/

  Clock_InitLDOVoltage(pDrvCtxt);

  /*-----------------------------------------------------------------------*/
  /* Now that NPA is initialized, allow Q6 scaling by the power manager.   */
  /*-----------------------------------------------------------------------*/

  Clock_EnableDCVS(pDrvCtxt);

  /*-----------------------------------------------------------------------*/
  /* Initialize the NPA eLDO enable/disable functionality.                 */
  /*-----------------------------------------------------------------------*/

  Clock_InitVdd(pDrvCtxt);

  /*
   * Decrease the reference count on the LPAPLL2 to ensure Q6 clock 
   * switching does not disable the PLL that the bus is currently on. 
   */
  anSourceIndex = pDrvCtxt->anSourceIndex[HAL_CLK_SOURCE_LPAPLL2];
  pDrvCtxt->aSources[anSourceIndex].nReferenceCountSuppressible--;

  /*-----------------------------------------------------------------------*/
  /* Good to go.                                                           */
  /*-----------------------------------------------------------------------*/

  return DAL_SUCCESS;

} /* END Clock_InitImage */
/** @brief Attaches to the device and creates a dal device
           handle.

    @param[in] pszArg       Char string.
    @param[in] DeviceId     Platform device id.
    @param[out] phDalDevice Pointer to pointer to device handle.
    
    @return          DAL_SUCCESS if successful, error otherwise.
  */
DALResult
I2C_DalI2C_Attach
(
   const char       *pszArg,
   DALDEVICEID       DeviceId,
   DalDeviceHandle **phDalDevice
)
{
  DALResult nErr;
  static DalI2cDrvCtxt *pDrvCtxt = NULL;
  uint32         uDrvCtxtSize;
  

  DalI2cClientCtxt *pclientCtxt =  NULL;

  if (NULL == pDrvCtxt) {
     /*
     nErr = DALSYS_GetDALPropertyHandleStr("/dev/buses/i2c", hPropI2C);
     if (nErr != DAL_SUCCESS) {
        return nErr;
     }
     nErr = DALSYS_GetPropertyValue(hPropI2C,"SW_DRV_NUM_DEVICES",0,&prop);
     if (nErr != DAL_SUCCESS) {
        return nErr;
     }
     */

     
     if ( 0 == uNumI2cBuses ) {
         return DAL_ERROR;
     }
     uDrvCtxtSize = sizeof(DalI2cDrvCtxt) + (uNumI2cBuses - 1) *
     sizeof(DalI2cDevCtxt);
     nErr = DALSYS_Malloc(uDrvCtxtSize, (void **)&pDrvCtxt);

     if ( nErr != DAL_SUCCESS ) {
        return nErr;
     }

     if ( NULL == pDrvCtxt ) {
        return DAL_ERROR;
     }
     DALSYS_memset(pDrvCtxt, 0, uDrvCtxtSize);
     pDrvCtxt->I2CDALVtbl.I2C_DriverInit = I2C_DalI2C_DriverInit;
     pDrvCtxt->I2CDALVtbl.I2C_DriverDeInit = I2C_DalI2C_DriverDeInit;
     pDrvCtxt->dwNumDev = uNumI2cBuses;
     pDrvCtxt->dwSizeDevCtxt = sizeof(DalI2cDevCtxt);

  }

  nErr = DALSYS_Malloc(sizeof(DalI2cClientCtxt), (void **)&pclientCtxt);

  *phDalDevice = NULL;

  if ((DAL_SUCCESS == nErr) && (NULL != pclientCtxt)) {
    DALSYS_memset(pclientCtxt,0,sizeof(DalI2cClientCtxt));

    nErr = DALFW_AttachToDevice(DeviceId,(DALDrvCtxt *)pDrvCtxt,
        (DALClientCtxt *)pclientCtxt);
    if (DAL_SUCCESS == nErr)
    {
      I2C_InitInterface(pclientCtxt);
      I2C_DalI2C_AddRef(&(pclientCtxt->DalI2CHandle));
      *phDalDevice = (DalDeviceHandle *)&(pclientCtxt->DalI2CHandle);
    }
  }
  return nErr;
}
/*==================================================================================================

FUNCTION: Uart_interrupt_open

DESCRIPTION:

==================================================================================================*/
UartResult Uart_interrupt_open(UART_CONTEXT* h, void* isr)
{
   uint8* virtual_tcsr_base;
   uint32 tcsr_offset;
   UART_INTERRUPT_CONTEXT* uart_interrupt_context;
   DalDeviceHandle* interrupt_dal = NULL;
   DALResult result;
   DALSYS_PROPERTY_HANDLE_DECLARE(hProp_device);

   UART_LOG_0(INFO, "+Uart_interrupt_open");


   result = DALSYS_Malloc(sizeof(UART_INTERRUPT_CONTEXT), (void **)(&uart_interrupt_context));
   if (result != DAL_SUCCESS)
   {
      UART_LOG_0(ERROR,"DALSYS_Malloc Attach failed");
      return UART_ERROR;
   }
   h->interrupt_context = uart_interrupt_context;
   result = DAL_DeviceAttach(DALDEVICEID_INTERRUPTCONTROLLER, &interrupt_dal);
   if (result != DAL_SUCCESS)
   {
      UART_LOG_0(ERROR,"DALDEVICEID_INTERRUPTCONTROLLER Attach failed");
      return UART_ERROR;
   }

   result = DalDevice_Open(interrupt_dal, DAL_OPEN_SHARED);
   if (result != DAL_SUCCESS)
   {
      UART_LOG_0(ERROR,"DALDEVICEID_INTERRUPTCONTROLLER open failed");
      return UART_ERROR;
   }

   if( DAL_SUCCESS != DALSYS_GetDALPropertyHandleStr(h->port_id,hProp_device))
   {
      UART_LOG_0(ERROR,"DALSYS_GetDALPropertyHandleStr for device failed");
      return UART_ERROR;
   }

   // Get the interrupt specific Properties in to the interrupt context.
   get_dword_property (hProp_device, "Irq",              &uart_interrupt_context->irq_num,0);
   get_dword_property (hProp_device, "UartIntSelOffset", &tcsr_offset,0);
   get_dword_property (hProp_device, "UartIntSelVal",    &uart_interrupt_context->tcsr_mask,0);

   result = DalInterruptController_RegisterISR(interrupt_dal,
                                                         (DALInterruptID)uart_interrupt_context->irq_num,
                                                         (DALISR)isr, h,
                                                         DALINTRCTRL_ENABLE_LEVEL_HIGH_TRIGGER);

   // If the processor uses TCSR for interrupts, configure the UART TCSR registers.
   if (tcsr_offset)
   {
      // Map the TCSR region and get the virtual address of the TCSR REGS base.
      if(dal_hwio && (DalHWIO_MapRegion(dal_hwio,"+TCSR_TCSR_REGS",&virtual_tcsr_base) != DAL_SUCCESS))
      {
         UART_LOG_0(ERROR,"DalHWIO_MapRegion for TCSR failed");
         return UART_ERROR;
      }
      // Close and deattach the HWIO handle as we wont be needing it anymore.
      DalDevice_Close(dal_hwio);
      DAL_DeviceDetach(dal_hwio);

      uart_interrupt_context->uart_tcsr_addr = (uint32*)(virtual_tcsr_base + tcsr_offset);

      //Configure the TCSR register.
      configure_tcsr(h,TRUE);
   }

   UART_LOG_0(INFO, "-Uart_interrupt_open");
   return UART_SUCCESS;
}
DALResult DALSYS_TimerStart(DALSYSEventHandle hEvent, uint32 time) 
{
    _DALSYSEventObj * pEventObj = (_DALSYSEventObj *)hEvent;
   timer_error_type timerRet;
   DALResult dalRet;

   if (!hEvent) return DAL_ERROR_INVALID_HANDLE;

   // allocate and initialize timer object
   if ( !pEventObj->pTimerObj )
   {
      int hEventValue = (int)hEvent; // used to avoid compiler warnings

      dalRet = DALSYS_Malloc(sizeof(timer_type), 
            (void**)&pEventObj->pTimerObj);

      if (DAL_ERROR_RETURNED(dalRet)) return dalRet;

      if(DALSYSCMN_IS_EVENT_NON_DEFERRED(pEventObj->dwObjInfo))
      {
         timerRet = timer_def_osal( pEventObj->pTimerObj, 
               &timer_non_defer_group, 
               TIMER_FUNC1_CB_TYPE, 
               (timer_t1_cb_type)timeoutCB,
               (timer_cb_data_type)hEventValue);
      }
      else
      {
         timerRet = timer_def_osal( pEventObj->pTimerObj, 
               NULL, 
               TIMER_FUNC1_CB_TYPE, 
               (timer_t1_cb_type)timeoutCB,
               (timer_cb_data_type)hEventValue);
      }

      if (TE_SUCCESS != timerRet)
      {
         DALSYS_Free( pEventObj->pTimerObj );
         pEventObj->pTimerObj = NULL;
         return DAL_ERROR_INTERNAL;
      }
   }

   if (time)
   {
      if(DALSYSCMN_IS_EVENT_A_TIMER(pEventObj->dwObjInfo))
      {
         // periodic
         timerRet = timer_set_64(pEventObj->pTimerObj, time, time, T_USEC);
      }
      else
      {
         // one-shot
         timerRet = timer_set_64(pEventObj->pTimerObj, time, 0, T_USEC);
      }

      if (TE_SUCCESS != timerRet) return DAL_ERROR_INTERNAL;
   }
   else
   {
      timer_clr_64( pEventObj->pTimerObj, T_USEC );
   }
   return DAL_SUCCESS;
}
/*==================================================================================================

FUNCTION: tal_clock_open

DESCRIPTION:
   Open a clock handle for the specified UART device. If successful, this function will return a
   clock handle, and may acquire other resources, which must be released by calling
   tal_clock_close().

==================================================================================================*/
TAL_RESULT tal_clock_open(TAL_CLOCK_HANDLE *phandle, uint32 client_id)
{
   DALSYS_PROPERTY_HANDLE_DECLARE(property_handle);
   TAL_CLOCK_HANDLE handle = NULL;
   DalDeviceHandle *clock_dal = NULL;
   char *clock_name = NULL;
   ICBArb_MasterSlaveType uart_arb_master_slave;
   ICBArb_RequestType pnoc_request;
   ICBArb_ErrorType   arb_error;
   DALResult result;

   if (DALSYS_Malloc(sizeof(TAL_CLOCK_CONTEXT), (void **)&handle) != DAL_SUCCESS) { goto error; }

   if (DAL_DeviceAttach(DALDEVICEID_CLOCK, &clock_dal) != DAL_SUCCESS) { goto error; }

   handle->daldev_clock = clock_dal;

   // No open needed for clock

   handle->dal_id = client_id;
   handle->manage_pclk = FALSE;

   // Read this clock's Clock Regime-specific parameters from the UART configuration:
   //
   // UartClockName: This is the name of the core clock.  It must be present.
   //
   // ManagePCLK: In recent chips there are two clock inputs to the UART HW block: the
   //             core clock and the peripheral bus clock.  The peripheral bus clock
   //             operates the bus interface (it must be enabled when reading/writing
   //             registers).  On some builds CLKREGIM manages the peripheral bus clock
   //             for us and turns it on/off along with the core clock.  On other builds
   //             we must manage the peripheral bus clock ourselves.  This property is
   //             used to specify whether we must manage it ourselves.
   //
   // PClockName: This is the name of the peripheral clock (if present)
   //
   // ResetClock: Flag indicating whether the clock block must be reset before
   //             it can be used.
   //
   // ClockFundFreq: The fundamental frequency of the bit clock, to which an
   //                integer divider can be applied. If unspecified, the clock
   //                has an M/N:D divider and the clock frequency can be
   //                specified directly.

   result = DALSYS_GetDALPropertyHandle(handle->dal_id, property_handle);
   if (result != DAL_SUCCESS) { goto error; }

   // Read the name of the UART clock
   result = get_property_string(handle->dal_id, property_handle, "UartClockName", &clock_name, NULL);
   if (result != DAL_SUCCESS || clock_name == 0) { goto error; }

   // Look up the clock ID for the core clock
   result = DalClock_GetClockId(handle->daldev_clock, clock_name, &handle->core_clk_id);
   if (result != DAL_SUCCESS)
   {
      DALSYS_LogEvent(handle->dal_id, DALSYS_LOGEVENT_ERROR, "Core GetClockId( %s ) = %d", clock_name, result);
      goto error;
   }

   handle->periph_clk_id = 0;
   
   get_property_dword(handle->dal_id,property_handle,"ManagePCLK", &handle->manage_pclk,FALSE);

   if (handle->manage_pclk)
   {
      // Read the name of the peripheral clock 
      result = get_property_string(handle->dal_id, property_handle, "PClockName", &clock_name, NULL);

      // Look up the clock ID for the peripheral clock
      if (result == DAL_SUCCESS && clock_name)
      {
         result = DalClock_GetClockId(handle->daldev_clock, clock_name, &handle->periph_clk_id);
         if (result != DAL_SUCCESS)
         {
            DALSYS_LogEvent(handle->dal_id, DALSYS_LOGEVENT_ERROR, "Periph GetClockId(%s) = %d", clock_name, result);
            goto error;
         }
      }
   }

   get_property_dword(handle->dal_id,property_handle,"ResetClock",     &handle->reset_clock,0);
   get_property_dword(handle->dal_id,property_handle,"ClockFundFreq",  &handle->fundamental_frequency,0);
   get_property_dword(handle->dal_id,property_handle,"PnocVoteEnable", &handle->pnoc_enable, 0);

   if(handle->pnoc_enable)
   {
      get_property_dword(handle->dal_id,property_handle,"PnocArbMaster", &handle->pnoc_master,0);
      get_property_dword(handle->dal_id,property_handle,"PnocArbSlave",  &handle->pnoc_slave, 0);
      if(!(handle->pnoc_master)){ goto error;}

      get_property_dword(handle->dal_id,property_handle,"PnocIBval",     &handle->pnoc_ib_val,0);
      get_property_dword(handle->dal_id,property_handle,"PnocABval",     &handle->pnoc_ab_val,0);
      if(!(handle->pnoc_ib_val && handle->pnoc_ab_val)){ goto error;}

      DALSYS_LogEvent(handle->dal_id, DALSYS_LOGEVENT_INFO, "Pnoc vote is enabled:Master %d & SLAVE %d",
                                                     handle->pnoc_master,handle->pnoc_slave);
      
      uart_arb_master_slave.eMaster =  handle->pnoc_master;
      uart_arb_master_slave.eSlave  =  handle->pnoc_slave; 
      
      /* Create a NPA client for the "/node/core/bus/uart/pnocclk" client to make PNOC voting request*/
      handle->npa_pnoc_client = icbarb_create_suppressible_client_ex
                                                           ("/node/core/bus/uart/pnocclk",
                                                            &uart_arb_master_slave,
                                                            UART_ICB_CLIENT_CNT, NULL);
      if (NULL == handle->npa_pnoc_client)
      {
         DALSYS_LogEvent(handle->dal_id, DALSYS_LOGEVENT_ERROR, "tal_clock_open: "
                                                 "Unable to create a pnoc npa client");
         goto error;
      }
      
      pnoc_request.arbType =    ICBARB_REQUEST_TYPE_3;     /* Ib/Ab pair */

      /* Bandwidth in Bytes/second */
      pnoc_request.arbData.type3.uIb = (uint64)  handle->pnoc_ib_val;      
      pnoc_request.arbData.type3.uAb = (uint64)  handle->pnoc_ab_val;    
 
      arb_error = icbarb_issue_request(handle->npa_pnoc_client, &pnoc_request,
                                     UART_PNOC_MSTRSLV_PAIRS_NUM);
   
      if(arb_error != ICBARB_ERROR_SUCCESS)
      {
         DALSYS_LogEvent(handle->dal_id, DALSYS_LOGEVENT_ERROR, "tal_clock_enable: "
                         "pnoc request is failed witht the error: %d",arb_error);     
         goto error;
      }
   }
   else
   {
      handle->pnoc_master = 0;
      handle->pnoc_slave  = 0;
      handle->pnoc_ib_val = 0;
      handle->pnoc_ab_val = 0;
      handle->npa_pnoc_client = NULL;
      DALSYS_LogEvent(handle->dal_id, DALSYS_LOGEVENT_INFO, "Pnoc vote is not enabled");
   }

   *phandle = handle;
   return TAL_SUCCESS;

error:
   if (clock_dal) { DAL_DeviceDetach(clock_dal); }
   if (handle)    { DALSYS_Free(handle); }
   return TAL_ERROR;
}
static DALResult
STMTrace_NewPort( DalDeviceHandle * h, uint32 * uPort, uint32 * uPortDMA)
{
   STMTraceClientCtxt *pClientCtxt = ((DalSTMTraceHandle *)h)->pClientCtxt;
   STMTraceDevCtxt *pDevCtxt = pClientCtxt->pSTMTraceDevCtxt;
   STMPortRange *pMainPortRange;
   STMPortRangeItem * currRange = NULL;
   STMPortRangeItem * prevRange = NULL;
   uint32 uBitPos;
   DALSYSMemInfo memInfo;


   if(NULL != uPortDMA) // DMA'able port requested ?
   {
      pMainPortRange = &pDevCtxt->portRangeDMA;
      if(!pMainPortRange->uNumPorts)
      {
         return DAL_ERROR;
      }
   }
   else
   {
      pMainPortRange = &pDevCtxt->portRange;
   }

   DALSYS_SyncEnter(pDevCtxt->hSync);

   currRange = pDevCtxt->listHead;
   while(NULL != currRange)
   {
      // previously allocated range has a free port?
      if(0 != currRange->uNumFreePorts)
         goto alloc_port;

      prevRange = currRange;
      currRange = currRange->next;
   }

   // carve out a new range from the master range now
   if(DAL_SUCCESS != DALSYS_Malloc(sizeof(STMPortRangeItem),(void **)&currRange))
   {
      DALSYS_SyncLeave(pDevCtxt->hSync);
      return DAL_ERROR;
   }

   memset(currRange, 0, sizeof(STMPortRangeItem));

   if(DAL_SUCCESS != _AllocBit(pMainPortRange->pBitMask,
                                pMainPortRange->uNumPorts/MAX_STM_PORTS_PER_PAGE,
                                &uBitPos))
   {
      DALSYS_Free(currRange);
      DALSYS_SyncLeave(pDevCtxt->hSync);
      return DAL_ERROR;
   }
   currRange->portRange.uBasePort = pMainPortRange->uBasePort + (uBitPos * MAX_STM_PORTS_PER_PAGE);
   currRange->portRange.uNumPorts = MAX_STM_PORTS_PER_PAGE;
   currRange->uNumFreePorts = MAX_STM_PORTS_PER_PAGE;
   currRange->mainPortRange = pMainPortRange;

   if(DAL_SUCCESS != _AllocateMemForBitMasks(&currRange->portRange.pBitMask, MAX_STM_PORTS_PER_PAGE))
   {
      _FreeBit(pMainPortRange->pBitMask, pMainPortRange->uNumPorts/MAX_STM_PORTS_PER_PAGE, uBitPos);
      DALSYS_Free(currRange);
      DALSYS_SyncLeave(pDevCtxt->hSync);
      return DAL_ERROR;
   }

   if(DAL_SUCCESS != DALSYS_MemRegionAlloc(DALSYS_MEM_PROPS_HWIO, DALSYS_MEM_ADDR_NOT_SPECIFIED,
                                           pDevCtxt->uSTMSPBaseAddr +
                                           (currRange->portRange.uBasePort * STM_PORT_SIZE),
                                           4096, &currRange->hMem, NULL))
   {
      _FreeBit(pMainPortRange->pBitMask, pMainPortRange->uNumPorts/MAX_STM_PORTS_PER_PAGE, uBitPos);
      DALSYS_Free(currRange->portRange.pBitMask);
      DALSYS_Free(currRange);
      DALSYS_SyncLeave(pDevCtxt->hSync);
      return DAL_ERROR;
   }

   DALSYS_MemInfo(currRange->hMem, &memInfo);
   currRange->uBaseAddr = memInfo.VirtualAddr;

   if(NULL != prevRange)
   {
      prevRange->next = currRange;
   }
   else
   {
      pDevCtxt->listHead = currRange;
   }

alloc_port:

   if(DAL_SUCCESS != _AllocBit(currRange->portRange.pBitMask, MAX_STM_PORTS_PER_PAGE, &uBitPos))
   {
      DALSYS_SyncLeave(pDevCtxt->hSync);
      return DAL_ERROR;
   }

   *uPort = currRange->uBaseAddr + (STM_PORT_SIZE * uBitPos);
   if(NULL != uPortDMA)
   {
      /* prepare a 32 bit int with 7 bits starting at 17th bit */
      uint32 uPortOffset = ((currRange->portRange.uBasePort+uBitPos)&0x7F)<<17;
      /* first get the physical address of the allocated port */
      *uPortDMA = pDevCtxt->uSTMSPBaseAddr +
                  ((currRange->portRange.uBasePort + uBitPos) * STM_PORT_SIZE);
      /* then set the 7 bits starting at 17th bit pos to 0's */
      *uPortDMA = *uPortDMA &(~(0x7F<<17));
      /* finally set the lower 7 bits of the stimulus port number at the 17th bit pos */
      *uPortDMA |= uPortOffset;
   }
   currRange->uNumFreePorts--;

   DALSYS_SyncLeave(pDevCtxt->hSync);

   return DAL_SUCCESS;
}