/* DTS open  function. 
 * On open the transport device should initialize itself.
 * Parameters:
 *  pContext:Cookie that should be passed back to the caller along 
 *  with the callback.
 *
 * Return Value: SUCCESS  Completed successfully.
 *     FAILURE_XXX  Request was rejected due XXX Reason.
 *
 */
wpt_status WDTS_openTransport( void *pContext)
{
  void *pDTDriverContext; 
  WDI_DS_ClientDataType *pClientData;
  WDI_Status sWdiStatus = WDI_STATUS_SUCCESS;
  WDTS_ClientCallbacks WDTSCb;

  pClientData = (WDI_DS_ClientDataType*) wpalMemoryAllocate(sizeof(WDI_DS_ClientDataType));
  if (!pClientData){
    return eWLAN_PAL_STATUS_E_NOMEM;
  }

  pClientData->suspend = 0;
  WDI_DS_AssignDatapathContext(pContext, (void*)pClientData);

  pDTDriverContext = gTransportDriver.open(); 
  if( NULL == pDTDriverContext )
  {
     DTI_TRACE( DTI_TRACE_LEVEL_ERROR, " %s fail from transport open", __func__);
     return eWLAN_PAL_STATUS_E_FAILURE;
  }
  WDT_AssignTransportDriverContext(pContext, pDTDriverContext);

  WDTSCb.rxFrameReadyCB = WDTS_RxPacket;
  WDTSCb.txCompleteCB = WDTS_TxPacketComplete;
  WDTSCb.lowResourceCB = WDTS_OOResourceNotification;
  WDTSCb.receiveMbMsgCB = WDTS_MbReceiveMsg;
  WDTSCb.receiveLogCompleteCB = WDTS_LogRxDone;
  gTransportDriver.register_client(pDTDriverContext, WDTSCb, (void*)pClientData);

  /* Create a memory pool for Mgmt BDheaders.*/
  sWdiStatus = WDI_DS_MemPoolCreate(&pClientData->mgmtMemPool, WDI_DS_MAX_CHUNK_SIZE, 
                                                     WDI_DS_HI_PRI_RES_NUM);
  if (WDI_STATUS_SUCCESS != sWdiStatus){
    return eWLAN_PAL_STATUS_E_NOMEM;
  }

  /* Create a memory pool for Data BDheaders.*/
  sWdiStatus = WDI_DS_MemPoolCreate(&pClientData->dataMemPool, WDI_DS_MAX_CHUNK_SIZE, 
                                                      WDI_DS_LO_PRI_RES_NUM);
  if (WDI_STATUS_SUCCESS != sWdiStatus){
    return eWLAN_PAL_STATUS_E_NOMEM;
  }

  wpalMemoryZero(&gDsTrafficStats, sizeof(gDsTrafficStats));

  WDI_DS_LoggingMbCreate(&pClientData->loggingMbContext, sizeof(tLoggingMailBox));
  if (WDI_STATUS_SUCCESS != sWdiStatus)
    return eWLAN_PAL_STATUS_E_NOMEM;

  return eWLAN_PAL_STATUS_SUCCESS;

}
/* DTS Tx Complete function. 
 * This function should be invoked by the DAL Dataservice to notify tx completion to DXE/SDIO.
 * Parameters:
 * pContext:Cookie that should be passed back to the caller along with the callback.
 * ucTxResReq:TX resource number required by TL
 * Return Value: SUCCESS  Completed successfully.
 *     FAILURE_XXX  Request was rejected due XXX Reason.
 *
 */
wpt_status WDTS_CompleteTx(void *pContext, wpt_uint32 ucTxResReq)
{
  void *pDTDriverContext = WDT_GetTransportDriverContext(pContext);
  
  // Notify completion to  Transport Driver. 
  return gTransportDriver.txComplete(pDTDriverContext, ucTxResReq);
}
/* DTS start  function. 
 * On start the transport device should start running.
 * Parameters:
 * pContext:Cookie that should be passed back to the caller along 
 * with the callback.
 *
 * Return Value: SUCCESS  Completed successfully.
 *     FAILURE_XXX  Request was rejected due XXX Reason.
 *
 */
wpt_status WDTS_startTransport( void *pContext)
{
  void *pDTDriverContext = WDT_GetTransportDriverContext(pContext);
  gTransportDriver.start(pDTDriverContext); 
  return eWLAN_PAL_STATUS_SUCCESS;

}
void WDTS_MbReceiveMsg(void *pContext)
{
  tpLoggingMailBox pLoggingMb;
  WDI_DS_LoggingSessionType *pLoggingSession;
  wpt_int8 i, noMem = 0;
  wpt_uint32 totalLen = 0;

  pLoggingMb = (tpLoggingMailBox)WDI_DS_GetLoggingMbAddr(pContext);
  pLoggingSession = (WDI_DS_LoggingSessionType *)
                       WDI_DS_GetLoggingSession(pContext);

  for(i = 0; i < MAX_NUM_OF_BUFFER; i++)
  {
     pLoggingSession->logBuffAddress[i] = pLoggingMb->logBuffAddress[i];
     if (!noMem && (pLoggingMb->logBuffLength[i] <= MAX_LOG_BUFFER_LENGTH))
     {
        pLoggingSession->logBuffLength[i] = gTransportDriver.setupLogTransfer(
                                               pLoggingMb->logBuffAddress[i],
                                               pLoggingMb->logBuffLength[i]);
     }
     else
     {
        pLoggingSession->logBuffLength[i] = 0;
        continue;
     }

     totalLen += pLoggingSession->logBuffLength[i];

     if (pLoggingSession->logBuffLength[i] < pLoggingMb->logBuffLength[i])
     {
        noMem = 1;
     }
  }

  pLoggingSession->done = pLoggingMb->done;
  pLoggingSession->logType = pLoggingMb->logType;
  // Done using Mailbox, zero out the memory.
  wpalMemoryZero(pLoggingMb, sizeof(tLoggingMailBox));

  if (totalLen)
  {
     if (gTransportDriver.startLogTransfer() == eWLAN_PAL_STATUS_SUCCESS)
        return;
  }

  // Send Done event to upper layers, since we wont be getting any from DXE
}
/* DTS Stop function. 
 * Stop Transport driver, ie DXE, SDIO
 * Parameters:
 * pContext:Cookie that should be passed back to the caller along with the callback.
 * Return Value: SUCCESS  Completed successfully.
 *     FAILURE_XXX  Request was rejected due XXX Reason.
 *
 */
wpt_status WDTS_Stop(void *pContext)
{
  void *pDTDriverContext = WDT_GetTransportDriverContext(pContext);
  wpt_status status = eWLAN_PAL_STATUS_SUCCESS;

  status =  gTransportDriver.stop(pDTDriverContext);

  return status;
}
/* DTS Stop function. 
 * Stop Transport driver, ie DXE, SDIO
 * Parameters:
 * pContext:Cookie that should be passed back to the caller along with the callback.
 * Return Value: SUCCESS  Completed successfully.
 *     FAILURE_XXX  Request was rejected due XXX Reason.
 *
 */
wpt_status WDTS_Stop(void *pContext)
{
  void *pDTDriverContext = WDT_GetTransportDriverContext(pContext);
  wpt_status status = eWLAN_PAL_STATUS_SUCCESS;

  status =  gTransportDriver.stop(pDTDriverContext);

  wpalMemoryZero(&gDsTrafficStats, sizeof(gDsTrafficStats));

  return status;
}
/* DTS open  function. 
 * On open the transport device should initialize itself.
 * Parameters:
 *  pContext:Cookie that should be passed back to the caller along 
 *  with the callback.
 *
 * Return Value: SUCCESS  Completed successfully.
 *     FAILURE_XXX  Request was rejected due XXX Reason.
 *
 */
wpt_status WDTS_openTransport( void *pContext)
{
  void *pDTDriverContext; 
  WDI_DS_ClientDataType *pClientData;
  WDI_Status sWdiStatus = WDI_STATUS_SUCCESS;

  pClientData = (WDI_DS_ClientDataType*) wpalMemoryAllocate(sizeof(WDI_DS_ClientDataType));
  if (!pClientData){
    return eWLAN_PAL_STATUS_E_NOMEM;
  }

  pClientData->suspend = 0;
  WDI_DS_AssignDatapathContext(pContext, (void*)pClientData);

  pDTDriverContext = gTransportDriver.open(); 
  if( NULL == pDTDriverContext )
  {
     DTI_TRACE( DTI_TRACE_LEVEL_ERROR, " %s fail from transport open", __FUNCTION__);
     return eWLAN_PAL_STATUS_E_FAILURE;
  }
  WDT_AssignTransportDriverContext(pContext, pDTDriverContext);
  gTransportDriver.register_client(pDTDriverContext, WDTS_RxPacket, WDTS_TxPacketComplete, 
    WDTS_OOResourceNotification, (void*)pClientData);

  /* Create a memory pool for Mgmt BDheaders.*/
  sWdiStatus = WDI_DS_MemPoolCreate(&pClientData->mgmtMemPool, WDI_DS_MAX_CHUNK_SIZE, 
                                                     WDI_DS_HI_PRI_RES_NUM);
  if (WDI_STATUS_SUCCESS != sWdiStatus){
    return eWLAN_PAL_STATUS_E_NOMEM;
  }

  /* Create a memory pool for Data BDheaders.*/
  sWdiStatus = WDI_DS_MemPoolCreate(&pClientData->dataMemPool, WDI_DS_MAX_CHUNK_SIZE, 
                                                      WDI_DS_LO_PRI_RES_NUM);
  if (WDI_STATUS_SUCCESS != sWdiStatus){
    return eWLAN_PAL_STATUS_E_NOMEM;
  }

  return eWLAN_PAL_STATUS_SUCCESS;

}
/* DTS Tx packet function. 
 * This function should be invoked by the DAL Dataservice to schedule transmit frame through DXE/SDIO.
 * Parameters:
 * pContext:Cookie that should be passed back to the caller along with the callback.
 * pFrame:Refernce to PAL frame.
 * Return Value: SUCCESS  Completed successfully.
 *     FAILURE_XXX  Request was rejected due XXX Reason.
 *
 */
wpt_status WDTS_TxPacket(void *pContext, wpt_packet *pFrame)
{
  void *pDTDriverContext = WDT_GetTransportDriverContext(pContext);
  WDI_DS_TxMetaInfoType     *pTxMetadata;
  WDTS_ChannelType channel = WDTS_CHANNEL_TX_LOW_PRI;
  wpt_status status = eWLAN_PAL_STATUS_SUCCESS;

  // extract metadata from PAL packet
  pTxMetadata = WDI_DS_ExtractTxMetaData(pFrame);

  //Log the TX Stats
  if(gDsTrafficStats.running && pTxMetadata->staIdx < HAL_NUM_STA)
  {
     if(pTxMetadata->frmType & WDI_MAC_DATA_FRAME)
     {
        gDsTrafficStats.txStats[pTxMetadata->staIdx].txBytesPushed +=
           pTxMetadata->fPktlen;
        gDsTrafficStats.txStats[pTxMetadata->staIdx].txPacketsPushed += 1;
      }
  }

  // assign MDPU to correct channel??
  channel =  (pTxMetadata->frmType & WDI_MAC_DATA_FRAME)? 
    /* EAPOL frame uses TX_HIGH_PRIORITY DXE channel
       To make sure EAPOL (for second session) is pushed even if TX_LO channel
       already reached to low resource condition
       This can happen especially in MCC, high data traffic TX in first session
     */
#ifdef FEATURE_WLAN_TDLS
     /* I utilizes TDLS mgmt frame always sent at BD_RATE2. (See limProcessTdls.c)
        Assumption here is data frame sent by WDA_TxPacket() <- HalTxFrame/HalTxFrameWithComplete()
        should take managment path. As of today, only TDLS feature has special data frame
        which needs to be treated as mgmt.
      */
      (((pTxMetadata->isEapol) || (pTxMetadata->txFlags & WDI_USE_BD_RATE2_FOR_MANAGEMENT_FRAME))? WDTS_CHANNEL_TX_HIGH_PRI : WDTS_CHANNEL_TX_LOW_PRI) : WDTS_CHANNEL_TX_HIGH_PRI;
#else
      ((pTxMetadata->isEapol) ? WDTS_CHANNEL_TX_HIGH_PRI : WDTS_CHANNEL_TX_LOW_PRI) : WDTS_CHANNEL_TX_HIGH_PRI;
#endif
  // Send packet to  Transport Driver. 
  status =  gTransportDriver.xmit(pDTDriverContext, pFrame, channel);
#ifdef DEBUG_ROAM_DELAY
   //Hack we need to send the frame type, so we are using bufflen as frametype
   vos_record_roam_event(e_DXE_FIRST_XMIT_TIME, (void *)pFrame, pTxMetadata->frmType);
   //Should we use the below check to avoid funciton calls
   /*
   if(gRoamDelayMetaInfo.dxe_monitor_tx)
   {
   }
   */
#endif
  return status;
}
/* DTS Set power state function. 
 * This function should be invoked by the DAL to notify the WLAN device power state.
 * Parameters:
 * pContext:Cookie that should be passed back to the caller along with the callback.
 * powerState:Power state of the WLAN device.
 * Return Value: SUCCESS  Set successfully in DXE control blk.
 *     FAILURE_XXX  Request was rejected due XXX Reason.
 *
 */
wpt_status WDTS_SetPowerState(void *pContext, WDTS_PowerStateType  powerState,
                              WDTS_SetPowerStateCbType cback)
{
   void *pDTDriverContext = WDT_GetTransportDriverContext(pContext);
   wpt_status status = eWLAN_PAL_STATUS_SUCCESS;

   if( cback )
   {
      //save the cback & cookie
      gSetPowerStateCbInfo.pUserData = pContext;
      gSetPowerStateCbInfo.cback = cback;
      status = gTransportDriver.setPowerState(pDTDriverContext, powerState,
                                            WDTS_SetPowerStateCb);
   }
   else
   {
      status = gTransportDriver.setPowerState(pDTDriverContext, powerState,
                                               NULL);
   }

   return status;
}
/* DTS Stop function. 
 * Stop Transport driver, ie DXE, SDIO
 * Parameters:
 * pContext:Cookie that should be passed back to the caller along with the callback.
 * Return Value: SUCCESS  Completed successfully.
 *     FAILURE_XXX  Request was rejected due XXX Reason.
 *
 */
wpt_status WDTS_Close(void *pContext)
{
  void *pDTDriverContext = WDT_GetTransportDriverContext(pContext);
  WDI_DS_ClientDataType *pClientData = WDI_DS_GetDatapathContext(pContext);
  wpt_status status = eWLAN_PAL_STATUS_SUCCESS;

  /*Destroy the mem pool for mgmt BD headers*/
  WDI_DS_MemPoolDestroy(&pClientData->mgmtMemPool);
  
  /*Destroy the mem pool for mgmt BD headers*/
  WDI_DS_MemPoolDestroy(&pClientData->dataMemPool);
  
  status =  gTransportDriver.close(pDTDriverContext);

  wpalMemoryFree(pClientData);

  return status;
}
/* DTS Tx packet function. 
 * This function should be invoked by the DAL Dataservice to schedule transmit frame through DXE/SDIO.
 * Parameters:
 * pContext:Cookie that should be passed back to the caller along with the callback.
 * pFrame:Refernce to PAL frame.
 * Return Value: SUCCESS  Completed successfully.
 *     FAILURE_XXX  Request was rejected due XXX Reason.
 *
 */
wpt_status WDTS_TxPacket(void *pContext, wpt_packet *pFrame)
{
  void *pDTDriverContext = WDT_GetTransportDriverContext(pContext);
  WDI_DS_TxMetaInfoType     *pTxMetadata;
  WDTS_ChannelType channel = WDTS_CHANNEL_TX_LOW_PRI;
  wpt_status status = eWLAN_PAL_STATUS_SUCCESS;

  // extract metadata from PAL packet
  pTxMetadata = WDI_DS_ExtractTxMetaData(pFrame);

  // assign MDPU to correct channel??
  channel =  (pTxMetadata->frmType & WDI_MAC_DATA_FRAME)? 
      WDTS_CHANNEL_TX_LOW_PRI : WDTS_CHANNEL_TX_HIGH_PRI;
  
  // Send packet to  Transport Driver. 
  status =  gTransportDriver.xmit(pDTDriverContext, pFrame, channel);
  return status;
}
/* Get free TX data descriptor number from DXE
 * Parameters:
 * pContext: Cookie that should be passed back to the caller along with the callback.
 * Return Value: number of free descriptors for TX data channel
 *
 */
wpt_uint32 WDTS_GetFreeTxDataResNumber(void *pContext)
{
  return 
     gTransportDriver.getFreeTxDataResNumber(WDT_GetTransportDriverContext(pContext));
}
/* DTS Transport Channel Debug
 * Display DXE Channel debugging information
 * User may request to display DXE channel snapshot
 * Or if host driver detects any abnormal stcuk may display
 * Parameters:
 *  displaySnapshot : Display DXE snapshot option
 *  enableStallDetect : Enable stall detect feature
                        This feature will take effect to data performance
                        Not integrate till fully verification
 * Return Value: NONE
 *
 */
void WDTS_ChannelDebug(wpt_boolean displaySnapshot, wpt_boolean toggleStallDetect)
{
   gTransportDriver.channelDebug(displaySnapshot, toggleStallDetect);
   return;
}
/* DTS Transport Channel Debug
 * Display DXE Channel debugging information
 * User may request to display DXE channel snapshot
 * Or if host driver detects any abnormal stcuk may display
 * Parameters:
 *  displaySnapshot : Display DXE snapshot option
 *  enableStallDetect : Enable stall detect feature
                        This feature will take effect to data performance
                        Not integrate till fully verification
 * Return Value: NONE
 *
 */
void WDTS_ChannelDebug(wpt_boolean displaySnapshot, wpt_uint8 debugFlags)
{
   gTransportDriver.channelDebug(displaySnapshot, debugFlags);
   return;
}