/****************************************************************************
 *  Init the bridge from the driver
 ****************************************************************************/
DIBSTATUS DibDriverTargetInit(struct DibDriverContext *pContext)
{
   struct IoctlInit pReq;

   if((pContext->DriverTargetCtx.BridgeFd = open(DEVICE_FILE_NAME, O_RDWR)) < 0) 
   {
      DIB_DEBUG(PORT_ERR, (CRB "Could not open device %s" CRA, DEVICE_FILE_NAME));
      return DIBSTATUS_ERROR;
   }

   /* this will create and initialise bridge */
   pReq.BoardHdl   = pContext->BoardHdl;
   pReq.ChipSelect = pContext->DibChip;

#if (USE_DRAGONFLY == 1)
   if((pContext->DibChip == DIB_VOYAGER) || (pContext->DibChip == DIB_NAUTILUS))
   {
     pReq.Config[0]  = pContext->DragonflyRegisters.JedecAddr;
     pReq.Config[1]  = pContext->DragonflyRegisters.JedecValue;
     pReq.Config[2]  = pContext->DragonflyRegisters.MacMbxSize;
     pReq.Config[3]  = pContext->DragonflyRegisters.MacMbxStart;
     pReq.Config[4]  = pContext->DragonflyRegisters.MacMbxEnd;
     pReq.Config[5]  = pContext->DragonflyRegisters.HostMbxSize;
     pReq.Config[6]  = pContext->DragonflyRegisters.HostMbxStart;
     pReq.Config[7]  = pContext->DragonflyRegisters.HostMbxEnd;
     pReq.Config[8]  = pContext->DragonflyRegisters.HostMbxRdPtrReg;
     pReq.Config[9]  = pContext->DragonflyRegisters.HostMbxWrPtrReg;
     pReq.Config[10] = pContext->DragonflyRegisters.MacMbxRdPtrReg;
     pReq.Config[11] = pContext->DragonflyRegisters.MacMbxWrPtrReg;
   }
   else
#endif
   DibZeroMemory(pReq.Config, sizeof(pReq.Config));

   if(ioctl(pContext->DriverTargetCtx.BridgeFd, REQUEST_BRIDGE_MODULE_INIT, &pReq) != DIBSTATUS_SUCCESS)
   {
      DIB_DEBUG(PORT_ERR, (CRB "Could initialise Bridge %s" CRA, DEVICE_FILE_NAME));

      /* close open device and free allocated memory*/
      close(pContext->DriverTargetCtx.BridgeFd);
      return DIBSTATUS_ERROR;
   }

   DibAllocateEvent(&pContext->DriverTargetCtx.IrqReadDone);
   DibInitNotificationEvent(&pContext->DriverTargetCtx.IrqReadDone);

   DibAllocateLock(&pContext->DriverTargetCtx.IrqLock);
   DibInitLock(&pContext->DriverTargetCtx.IrqLock);

   DIB_DEBUG(PORT_LOG, (CRB "Launching interrupt thread" CRA));

   pthread_create(&pContext->DriverTargetCtx.IrqThread, NULL, IntDriverTargetIrqRead, (void *)pContext);

   DibWaitForEvent(&pContext->DriverTargetCtx.IrqReadDone, 0);
   return DIBSTATUS_SUCCESS;
}
/****************************************************************************
* Write Data to the chip
* ----------------------------------------------------------------------
* Parameters:
* -----------
* struct DibBridgeContext *pContext
* uint16_t      Addr:          Address to write
* uint8_t       ByteMode:      Transfer Mode
*                 0: 16 bits wide register write
*                 1: 8 bits wide FIFO write
* uint32_t       Cnt:      Number of Bytes
* uint8_t      *pBuf:      Data Buffer
* ----------------------------------------------------------------------
* Return Code:
* -----------
*           DIBSTATUS_SUCCESS
*           DIBSTATUS_ERROR
****************************************************************************/
DIBSTATUS DibBridgeTargetWrite(struct DibBridgeContext *pContext, uint32_t FmtAddr, uint8_t ByteMode, uint32_t Cnt, uint8_t *pBuf)
{
   DIBSTATUS rc = DIBSTATUS_SUCCESS;
   SDIO_CMD sdiocmd;

   /* In word Mode the write count has to be even */
   if((ByteMode == DIBBRIDGE_BIT_MODE_16) && (Cnt & 1)) 
   {
      DIB_DEBUG(PORT_LOG, (CRB "-E- DibBridgeTargetWrite: Odd byte count" CRA));
      return DIBSTATUS_INVALID_PARAMETER;
   }

   /* Get semaphore to avoid concurrent access */
   DibAcquireLock(&pContext->DibTargetAccessLock);

   /* For 32 bit architectures, we need to write high 16 bytes before transfer */
   if(DibBridgeGetArch(pContext) == DIBBRIDGE_BIT_MODE_32)
   {
      /* Use CMD52 to configure address for 32 bits platforms. Note, cmd53 is not working here */
      sdiocmd.cmd    = SDIO_CMD_52;     
      sdiocmd.addr   = 0x10000 | ((FmtAddr>>16) & 0xFFFF);
      sdiocmd.fct    = 1;
      sdiocmd.buffer = &ByteMode;
      sdiocmd.rw      = SDIO_CMD_WRITE; 
      SdioCmd52(pContext,&sdiocmd);
   }
/*-----------------------------------------------------------------------
|  Release the Device Driver
|  ressources are freed on IOCTL module shutdown
|   here we only mark the device as closed !
-----------------------------------------------------------------------*/
static int32_t DibBridgeTargetModuleRelease(struct inode *inode, struct file *file)
{
   struct DibBridgeContext *pContext = (struct DibBridgeContext *) file->private_data;

   /* Only opened device can be closed */
   if(pContext == NULL) 
      return DIBSTATUS_ERROR;

   DIB_DEBUG(PORT_LOG, (CRB "dibbridge device release" CRA));

   flush_scheduled_work();

   /* Free previously allocated context in reverse order */
   /* Deinit bridge should have been called previously by shutdown ioctl */
   /*DibBridgeDeinit(pContext);*/

   if (running == eDIB_TRUE) {
       DibBridgeDeinit(pContext);
       running = eDIB_FALSE;
       printk("Bridge Deinit\n");
   }

   /* Free allocated struct */
   IntBridgeTargetModuleFreeStruct(pContext);

   file->private_data = NULL;

   module_put(THIS_MODULE);

   return DIBSTATUS_SUCCESS;
}
void DibBridgeDeinitMsgQueue(struct DibBridgeContext *pContext)
{
   /** msg queue lock and event are freed uppon close */
   DibDeAllocateLock(&pContext->MsgQueueLock);
   DibDeAllocateEvent(&pContext->MsgQueueEvent);
   DIB_DEBUG(PORT_LOG, (CRB "DibBridgeDeinitMsgQueue!" CRA));
}
DIBSTATUS DibDriverGetMonitoringDabAudio(struct DibDriverContext * pContext, ELEM_HDL ItemHdl, union DibDataMonit * pDataMonit, uint8_t ClearMonit)
{
    struct DibDabMonitoring             * pDabMonit = (struct DibDabMonitoring *) pDataMonit;
    struct DibDriverDabAudioServiceCtx  * pService;
    FILTER_HDL                          FilterHdl  = pContext->ItemInfo[ItemHdl].ParentFilter;

    DIB_ASSERT(pDabMonit);
    DIB_ASSERT(ItemHdl < DIB_MAX_NB_ITEMS);
    DIB_ASSERT(pContext->FilterInfo[FilterHdl].TypeFilter == eDAB);
    DIB_ASSERT(((ClearMonit == eDIB_TRUE) || (ClearMonit == eDIB_FALSE)));

    DIB_DEBUG(SOFT_IF_LOG, (CRB "DibDriverGetMonitoringDabAudio" CRA));

#if (LOG_APPLICATION_TO_DRIVER_CALLS_TO_FILE == 1)
    {
        DibLogToFile_Time(gLogFile, gLogFileStartTimeSec, gLogFileStartTimeMsec);
        DibLogToFile_Mesg(gLogFile, CRB "DibDriverGetMonitoringDabAudio" CRA);
    }
#endif

    DibDriverTargetDisableIrqProcessing(pContext);

    pService = pContext->ItemInfo[ItemHdl].ItemCtx.pDabAudioService;

    if(pDabMonit)
    {
        /*** Initialize DAB Monitoring structure ***/
        DibZeroMemory(pDabMonit, sizeof(struct DibDabMonitoring));

        pDabMonit->NbPid                    = 0;
        pDabMonit->ChannelIndex             = pContext->FilterInfo[pContext->ItemInfo[ItemHdl].ParentFilter].ParentChannel;
        pDabMonit->FilterIndex              = FilterHdl;
        pDabMonit->FilterType               = pContext->FilterInfo[FilterHdl].TypeFilter;
        if(pService)
        {
            pDabMonit->CountinuityError         = pService->DabMonitoring.CountinuityError;
            pDabMonit->Error                    = pService->DabMonitoring.Error;
            pDabMonit->TotalPackets             = pService->DabMonitoring.TotalPackets;
            pDabMonit->CorrPackets              = pService->DabMonitoring.CorrectedPackets;
            /* Protected access to shared ressource, clear error and cc counts */
            if(ClearMonit == eDIB_TRUE)
                DibZeroMemory(&pService->DabMonitoring, sizeof(pService->DabMonitoring));
        }
    }
    DibDriverTargetEnableIrqProcessing(pContext);

    /* Send Message to clear internal monitoring info is sent separatly to avoid dead locks */
    if((pService) && (ClearMonit == eDIB_TRUE))
        DibDriverClearMonit(pContext, ItemHdl);

    return DIBSTATUS_SUCCESS;
}
/**
 * Called from bridge context to send a message comming from the driver to the firmware.
 * Messages sent directly from the bridge to the firmware are directly sent using 
 * DibBridgeSendMsgSpec.
 * @param[in] pContext: The bridge context structure
 * @param[in] Data: The buffer to send.
 * @param[in] len: The length in bytes of the message.
 * @return: DIBSTATUS_XXX
 */
DIBSTATUS DibBridgeSendMsg(struct DibBridgeContext *pContext, uint32_t *Data, uint32_t len)
{
   DIBSTATUS ret = DIBSTATUS_ERROR;

   DibBridgeTargetDisableIRQ(pContext);

   DIB_DEBUG(MAILBOX_LOG, (CRB "MSG OUT sent" CRA));

   ret = DibBridgeSendMsgSpec(pContext, Data, len);

   DibBridgeTargetEnableIrq(pContext);

   return ret;
}
void DibB2DFwdEvents(struct DibBridgeContext *pContext, enum DibEvent Event, union DibEventConfig * pEventConfig)
{
   struct DibDriverEventInfoUp eventInfo;

   DIB_ASSERT(pContext);
   DIB_ASSERT(pContext->BridgeTargetCtx.pDriverContext);
   
   eventInfo.EventType = Event;
   DibMoveMemory((char *)&(eventInfo.EventConfig), pEventConfig, sizeof(union DibEventConfig));
   
   DibDriverPostEvent(pContext->BridgeTargetCtx.pDriverContext, &eventInfo);
   
   DIB_DEBUG(PACKET_LOG, (CRB "DibB2DFwdEvents Event %d" CRA, Event));
}
/*******************************************************************************
 *  Send Raw Data from the bridge to the driver
 ******************************************************************************/
void DibB2DFwdRawData(struct DibBridgeContext *pContext, uint32_t Size, ELEM_HDL ItemIndex, uint8_t FirstFrag, uint8_t LastFrag)
{
   struct DibDriverDataInfoUp dataInfo;

   DIB_ASSERT(pContext);
   DIB_ASSERT(pContext->BridgeTargetCtx.pDriverContext);

   dataInfo.Length    = Size;
   dataInfo.ItemIndex = ItemIndex;
   dataInfo.Flags     = (FirstFrag << 1) | LastFrag;

   DibDriverRawDataRead(pContext->BridgeTargetCtx.pDriverContext, dataInfo);
  
   DIB_DEBUG(PACKET_LOG, (CRB "DibB2DFwdRawData Length %d" CRA, Size));
}
/****************************************************************************
 * Take appropriate action upon a interruption sent by the chip
 ****************************************************************************/
static DIBDMA IntBridgeFireflyProcessMacIrq(struct DibBridgeContext *pContext, uint8_t RiscId)
{
   uint16_t RxData[128];
   uint8_t  RxCnt;

   DIB_DEBUG(IRQ_LOG, (CRB "IRQ: RISC %c" CRA, 'A' + RiscId));

   RxCnt = DibBridgeFireflyReceiveMsg(pContext, RxData, RiscId);

   if(RxCnt != 0) 
   {
      return DibBridgeFireflyMsgHandler(pContext, RxData, RxCnt);
   }

   return DIB_NO_DMA;
}
/*-----------------------------------------------------------------------
|  Read from bridge
-----------------------------------------------------------------------*/
int32_t DibBridgeTargetModuleReadMsg(struct DibBridgeContext *pContext, uint8_t *Buffer)
{
   int32_t ret = -1; 
   DIBSTATUS rc;
   uint16_t Type, Size;

   if(pContext) 
   {
      /* retrieve a msg from the MsgQueue */
      DIB_ASSERT(Buffer);
      rc = DibBridgeGetBufFromMsgQueue(pContext, &Type, &Size, Buffer + sizeof(Type));

      if(rc == DIBSTATUS_ERROR) 
      {
         DIB_DEBUG(PORT_LOG, (CRB "MsgQueue deinitialized" CRA));
   	if (running == eDIB_TRUE) {
       		DibBridgeDeinit(pContext);
       		running = eDIB_FALSE;
       		printk("Bridge Deinit\n");
   		}
         return -1;
      }


      if(Buffer)
      {
         /* Remove flagged Type, it is not needed */
         Type &= UPMESSAGE_MASK_TYPE;

         /* copy msg Type to user Buffer */
         ret = copy_to_user(Buffer, &Type, sizeof(Type));
      }

      if (ret) 
      {
         printk(CRB "Will not complete read, device not open" CRA);
         return -1;
      }

      return Size + sizeof(Type);
   }
   else 
   {
      printk(CRB "Will not complete read, device not open" CRA);
      return -1;
   }
}
DIBSTATUS DibDriverGetMonitoringTdmb(struct DibDriverContext * pContext, ELEM_HDL ItemHdl, union DibDataMonit * pDataMonit, uint8_t ClearMonit)
{
    struct DibDabMonitoring *pDabMonit = (struct DibDabMonitoring *) pDataMonit;
    FILTER_HDL                FilterHdl  = pContext->ItemInfo[ItemHdl].ParentFilter;
    struct DibDriverFilter   *pFilter    = &pContext->FilterInfo[FilterHdl];

    DIB_ASSERT(pDabMonit);
    DIB_ASSERT(ItemHdl < DIB_MAX_NB_ITEMS);
    DIB_ASSERT(pContext->FilterInfo[FilterHdl].TypeFilter == eTDMB);
    DIB_ASSERT(((ClearMonit == eDIB_TRUE) || (ClearMonit == eDIB_FALSE)));

    DIB_DEBUG(SOFT_IF_LOG, (CRB "DibDriverGetTdmbMonitoring %d %u" CRA, FilterHdl, pFilter->DvbTMonitoring.TotalPackets));

    DibDriverTargetDisableIrqProcessing(pContext);

    /* Set external DVB-T/TDMB monitoring info */
    pDabMonit->FilterIndex              = FilterHdl;
    pDabMonit->FilterType               = pContext->FilterInfo[FilterHdl].TypeFilter;
    pDabMonit->NbPid                    = pFilter->NbActivePids;
    pDabMonit->ChannelIndex             = pFilter->ParentChannel;
    /* checker of the bridge activated */
    if(pFilter->DvbTMonitoring.CheckTotalPackets)
        pDabMonit->TotalPackets             = pFilter->DvbTMonitoring.CheckTotalPackets;
    else
        pDabMonit->TotalPackets             = pFilter->DvbTMonitoring.TotalPackets;

    pDabMonit->CountinuityError         = pFilter->DvbTMonitoring.CheckCcFailCnt;
    pDabMonit->Error                    = pFilter->DvbTMonitoring.ErrCnt;

    if(ClearMonit == eDIB_TRUE)
    {
        /* Clear Driver monitoring info */
        DibZeroMemory(&pFilter->DvbTMonitoring, sizeof(struct DvbTMonit));
    }

    DibDriverTargetEnableIrqProcessing(pContext);

    if(ClearMonit == eDIB_TRUE)
    {
        /* Clear Firmware and Bridge monitoring info */
        DibDriverClearMonit(pContext, ItemHdl);
    }

    return DIBSTATUS_SUCCESS;
}
/****************************************************************************
* Write Data to the chip
* ----------------------------------------------------------------------
* Parameters:
* -----------
* struct DibBridgeContext *pContext
* uint16_t      Addr:          Address to write
* uint8_t       ByteMode:      Transfer Mode
*                 0: 16 bits wide register write
*                 1: 8 bits wide FIFO write
* uint32_t       Cnt:      Number of Bytes
* uint8_t      *pBuf:      Data Buffer
* ----------------------------------------------------------------------
* Return Code:
* -----------
*           DIBSTATUS_SUCCESS
*           DIBSTATUS_ERROR
****************************************************************************/
DIBSTATUS DibBridgeTargetWrite(struct DibBridgeContext *pContext, uint32_t Addr, uint8_t ByteMode, uint32_t Cnt, uint8_t *pBuf)
{
   DIBSTATUS rc = DIBSTATUS_SUCCESS;

   /* In word Mode the write count has to be even */
   if((ByteMode == DIBBRIDGE_BIT_MODE_16) && (Cnt & 1)) 
   {
      DIB_DEBUG(PORT_LOG, (CRB "-E- DibBridgeTargetWrite: Odd byte count" CRA));
      return DIBSTATUS_INVALID_PARAMETER;
   }

   /* Get semaphore to avoid concurrent access */
   DibAcquireLock(&pContext->DibTargetAccessLock);

   /**************************************************************/
   /********* 16 bits Architecture Dibcom Chips: *****************/
   /**************************************************************/
   /********* Dib7070, Dib7078, Dib9080, Dib9090 *****************/
   /**************************************************************/
   if(DibBridgeGetArch(pContext) == DIBBRIDGE_BIT_MODE_16)
   {
      /* write address on the bus */
      SramWrite(pContext,DIB16_ADDR_MSB, Addr >> 8);
      SramWrite(pContext,DIB16_ADDR_LSB, Addr & 0xff);

      /* write the data on the bus */
      if(ByteMode == DIBBRIDGE_BIT_MODE_8)
      {
         while(Cnt)
         {
           Cnt--;
           SramWrite(pContext,DIB16_DATA_LSB, *(pBuf++));
         }
      }
      else
      {
         Cnt >>= 1;        /* number of WORDS */
         while(Cnt)
         {
            Cnt--;
            SramWrite(pContext,DIB16_DATA_MSB, *(pBuf++));
            SramWrite(pContext,DIB16_DATA_LSB, *(pBuf++));
         }
      }
    }
/****************************************************************************
 * DeInit the bridge from the driver
 ****************************************************************************/
DIBSTATUS DibDriverTargetDeinit(struct DibDriverContext * pContext)
{
   /* this will destroy bridge thread and then destroy driver thread and trigger IrqRead event */
   ioctl(pContext->DriverTargetCtx.BridgeFd, REQUEST_BRIDGE_MODULE_SHUTDOWN, NULL);

   DibWaitForEvent(&pContext->DriverTargetCtx.IrqReadDone, 0);

   /** Free thread internal information */
   pthread_join(pContext->DriverTargetCtx.IrqThread, NULL);

   close(pContext->DriverTargetCtx.BridgeFd);

   DIB_DEBUG(PORT_LOG, (CRB "Stopped reading thread" CRA));

   DibDeAllocateEvent(&pContext->DriverTargetCtx.IrqReadDone);
   DibDeAllocateLock(&pContext->DriverTargetCtx.IrqLock);

   return DIBSTATUS_SUCCESS;
}
DIBSTATUS DibDriverGetMonitoringDabPacket(struct DibDriverContext * pContext, ELEM_HDL ItemHdl, union DibDataMonit * pDataMonit, uint8_t ClearMonit)
{
    struct DibDabPacketMonitoring * pMonit = (struct DibDabPacketMonitoring *) pDataMonit;
    FILTER_HDL                FilterHdl  = pContext->ItemInfo[ItemHdl].ParentFilter;
    struct DibDriverDabPacketServiceCtx  * pService;

    DIB_ASSERT(pMonit);
    DIB_ASSERT(ItemHdl < DIB_MAX_NB_ITEMS);
    DIB_ASSERT(pContext->FilterInfo[FilterHdl].TypeFilter == eDABPACKET);
    DIB_ASSERT(((ClearMonit == eDIB_TRUE) || (ClearMonit == eDIB_FALSE)));


    DibDriverTargetDisableIrqProcessing(pContext);

    pService = pContext->ItemInfo[ItemHdl].ItemCtx.pDabPacketService;

    if(pMonit)
    {
        /*** Initialize DAB Monitoring structure ***/
        DibZeroMemory(pMonit, sizeof(struct DibDabPacketMonitoring));

        pMonit->ChannelIndex             = pContext->FilterInfo[pContext->ItemInfo[ItemHdl].ParentFilter].ParentChannel;
        pMonit->FilterIndex              = FilterHdl;
        if(pService)
        {
            pMonit->MscPacketGood         = pService->DabPacketMonitoring.MscPacketGood;
            pMonit->MscPacketsError       = pService->DabPacketMonitoring.MscPacketsError;
            pMonit->DataGroupGood         = pService->DabPacketMonitoring.DataGroupGood;
            pMonit->DataGroupError        = pService->DabPacketMonitoring.DataGroupError;
            /* Protected access to shared ressource, clear error */
            if(ClearMonit == eDIB_TRUE)
                DibZeroMemory(&pService->DabPacketMonitoring, sizeof(pService->DabPacketMonitoring));
        }
    }
    DibDriverTargetEnableIrqProcessing(pContext);

    /* Send Message to clear internal monitoring info is sent separatly to avoid dead locks */
    if((pService) && (ClearMonit == eDIB_TRUE))
        DibDriverClearMonit(pContext, ItemHdl);

    DIB_DEBUG(SOFT_IF_LOG, (CRB "DibDriverGetDabPacketMonitoring %d" CRA, pMonit->FilterIndex));
    return DIBSTATUS_SUCCESS;
}
DIBSTATUS DibDriverDragonflyAddItemMpeIFec(struct DibDriverContext *pContext, union DibFilters *pFilterDesc, FILTER_HDL FilterHdl, uint32_t ItemHdl, struct MsgCreateItem * msg)
{
   struct DibDriverMpeIFecServiceCtx *pMpeIFecService;
   struct DibDriverItem              *pItem;

   msg->Param.Mpeifec.Pid                 = pFilterDesc->MpeIFec.Pid;
   msg->Param.Mpeifec.MaxBurstDuration    = pFilterDesc->MpeIFec.MaxBurstDuration;
   msg->Param.Mpeifec.Prefetch            = pFilterDesc->MpeIFec.Prefetch;
   msg->Param.Mpeifec.B                   = pFilterDesc->MpeIFec.EncodParal;
   msg->Param.Mpeifec.C                   = pFilterDesc->MpeIFec.NbAdstColumns;
   msg->Param.Mpeifec.S                   = pFilterDesc->MpeIFec.SpreadingFactor;
   msg->Param.Mpeifec.R                   = pFilterDesc->MpeIFec.MaxIFecSect;
   msg->Param.Mpeifec.D                   = pFilterDesc->MpeIFec.SendingDelay;

   pMpeIFecService = (struct DibDriverMpeIFecServiceCtx *) DibMemAlloc(sizeof(struct DibDriverMpeIFecServiceCtx));
   pItem = &pContext->ItemInfo[ItemHdl];
   pItem->ItemCtx.pMpeIFecService = pMpeIFecService;

   if(pMpeIFecService == NULL)
   {
      DIB_DEBUG(SOFT_IF_ERR, (CRB "IntDriverAddPid: no memory for MPE-IFEC service" CRA));
      return DIBSTATUS_ERROR;
   }

   pMpeIFecService->RsNumRows               = pFilterDesc->MpeIFec.NbRows;
   pMpeIFecService->Pid                     = pFilterDesc->MpeIFec.Pid;
   pMpeIFecService->OnlyIfPrioritaryChannel = pContext->ChannelInfo[pContext->FilterInfo[FilterHdl].ParentChannel].IsDataChannel;
   pMpeIFecService->MaxBurstDuration        = pFilterDesc->MpeIFec.MaxBurstDuration;

   /* TBD_IF */

   DibZeroMemory(&pMpeIFecService->DvbSHMonitoring, sizeof(struct DvbSHMonit));

   pContext->FilterInfo[FilterHdl].NbActivePids++;

   return DIBSTATUS_SUCCESS;
}
/* ------------------------------------------------------------------------ */
void DibBridgeForwardData(struct DibBridgeContext *pContext, uint8_t *pBuf, uint32_t Size, ELEM_HDL Item)
{
   enum DibDataMode DataMode = pContext->FilterInfo[pContext->ItSvc[Item].FilterParent].DataMode;

   DIB_ASSERT((DataMode == eIP) || (DataMode == eCLBACK));
   DIB_ASSERT(pBuf);
   
#if (DIB_CHECK_RTP_DATA == 1)
   DibBridgeCheckRtpData(pContext, pBuf, Size, Item);
   DibBridgeForwardCheckStats(pContext, Item);
#endif

#if (DIB_CHECK_IP_DATA == 1)
   DibBridgeCheckIpData(pContext, pBuf, Size, Item);
   DibBridgeForwardCheckStats(pContext, Item);
#endif /* DIB_CHECK_IP_DATA */

   if(DataMode == eIP)
   {
      if (pContext->IpCallback.DataMpe != NULL)
      {
         pContext->IpCallback.DataMpe(pContext, Item, pBuf, Size);
      }
   }
   else
   {
      DIB_ASSERT(pContext->DataInfoUp[pContext->NextFreeWrBuff].pBuff == NULL);
      pContext->DataInfoUp[pContext->NextFreeWrBuff].pBuff = pBuf; 
      pContext->DataInfoUp[pContext->NextFreeWrBuff].FilterIndex = pContext->ItSvc[Item].FilterParent; 
      
      pContext->NextFreeWrBuff = (pContext->NextFreeWrBuff + 1)%(MAX_Q_BUFF); 
      
      DIB_DEBUG(RAWTS_LOG, (CRB "Add Raw Buffer in Queue (NextFreeWrBuff= %d)" CRA, pContext->NextFreeWrBuff));
      
      DibB2DFwdRawData(pContext, Size, Item, 0, 0);
   }
}
/**
 * Get MpeIFec Data monitoring
 * @param[in] pContext: driver context
 * @param[in] ItemHdl: filter item handler.
 * @param[out] pDVBMonit: DVB-SH monitoring information of the corresponding item
 * @param[in] ClearMonit: Reset internal monitoring information after retreiving them.
 */
DIBSTATUS DibDriverGetMonitoringMpeIFec(struct DibDriverContext *pContext, ELEM_HDL ItemHdl, union DibDataMonit *pDataMonit, uint8_t ClearMonit)
{
   struct DibDvbSHMonitoring         *pDvbSHMonit = (struct DibDvbSHMonitoring *) pDataMonit;
   struct DibDriverMpeIFecServiceCtx *pMpeIFecService;     /* Points to MPE service context if target MPE. pMpeService_CONTEXT*/
   FILTER_HDL                         FilterHdl  = pContext->ItemInfo[ItemHdl].ParentFilter;

   DIB_ASSERT(pDvbSHMonit);
   DIB_ASSERT(ItemHdl < DIB_MAX_NB_ITEMS);
   DIB_ASSERT(pContext->FilterInfo[FilterHdl].TypeFilter == eMPEIFEC);
   DIB_ASSERT(((ClearMonit == eDIB_TRUE) || (ClearMonit == eDIB_FALSE)));
   
   DIB_DEBUG(SOFT_IF_LOG, (CRB "DibDriverGetDVBSHMonitoring" CRA));

#if (LOG_APPLICATION_TO_DRIVER_CALLS_TO_FILE == 1)
   {
      DibLogToFile_Time(gLogFile, gLogFileStartTimeSec, gLogFileStartTimeMsec);
      DibLogToFile_Mesg(gLogFile, CRB "DibDriverGetDVBSHMonitoring" CRA);
   }
#endif

   DibDriverTargetDisableIrqProcessing(pContext);

   pMpeIFecService = pContext->ItemInfo[ItemHdl].ItemCtx.pMpeIFecService;

   if(pMpeIFecService)
   {
      if(pDvbSHMonit)
      {
         /*** Initialize DVBH Monitoring structure ***/
         DibZeroMemory(pDvbSHMonit, sizeof(struct DibDvbSHMonitoring));

         pDvbSHMonit->Pid                    = pContext->ItemInfo[ItemHdl].Config.MpeIFec.Pid;
         pDvbSHMonit->ChannelIndex           = pContext->FilterInfo[pContext->ItemInfo[ItemHdl].ParentFilter].ParentChannel;
         pDvbSHMonit->FilterIndex            = FilterHdl;

         pDvbSHMonit->NbRows                 = pContext->ItemInfo[ItemHdl].Config.MpeIFec.NbRows;
         pDvbSHMonit->EncodParal             = pContext->ItemInfo[ItemHdl].Config.MpeIFec.EncodParal;
         pDvbSHMonit->SpreadingFactor        = pContext->ItemInfo[ItemHdl].Config.MpeIFec.SpreadingFactor;
         pDvbSHMonit->SendingDelay           = pContext->ItemInfo[ItemHdl].Config.MpeIFec.SendingDelay;
         pDvbSHMonit->NbAdstColumns          = pContext->ItemInfo[ItemHdl].Config.MpeIFec.NbAdstColumns;
         pDvbSHMonit->MaxIFecSect            = pContext->ItemInfo[ItemHdl].Config.MpeIFec.MaxIFecSect;

         pDvbSHMonit->AdstTotalTables        = pMpeIFecService->DvbSHMonitoring.AdstTotalTables;    
         pDvbSHMonit->AdstTablesLost         = pMpeIFecService->DvbSHMonitoring.AdstTablesLost;     
         pDvbSHMonit->AdstTablesCorrected    = pMpeIFecService->DvbSHMonitoring.AdstTablesCorrected;
         pDvbSHMonit->AdstTablesFailed       = pMpeIFecService->DvbSHMonitoring.AdstTablesFailed;   
         pDvbSHMonit->AdstTablesGood         = pMpeIFecService->DvbSHMonitoring.AdstTablesGood;

         pDvbSHMonit->AdtTotalTables         = pMpeIFecService->DvbSHMonitoring.AdtTotalTables;     
         pDvbSHMonit->AdtTablesCorrected     = pMpeIFecService->DvbSHMonitoring.AdtTablesCorrected; 
         pDvbSHMonit->AdtTablesFailed        = pMpeIFecService->DvbSHMonitoring.AdtTablesFailed;    
         pDvbSHMonit->AdtTablesGood          = pMpeIFecService->DvbSHMonitoring.AdtTablesGood;      

         pDvbSHMonit->DeltaTStream           = pMpeIFecService->DvbSHMonitoring.DeltaTStream;
         pDvbSHMonit->DeltaTDetected         = pMpeIFecService->DvbSHMonitoring.DeltaTDetected;
         pDvbSHMonit->BurstStream            = pMpeIFecService->DvbSHMonitoring.BurstStream;
         pDvbSHMonit->BurstDetected          = pMpeIFecService->DvbSHMonitoring.BurstDetected;
         pDvbSHMonit->PowerUpTime            = pMpeIFecService->DvbSHMonitoring.PowerUpTime; 

         pDvbSHMonit->CountinuityError       = pMpeIFecService->DvbSHMonitoring.CcFailCnt;
         pDvbSHMonit->Error                  = pMpeIFecService->DvbSHMonitoring.ErrCnt;
      }

      /* Protected access to shared ressource, clear error and cc counts */
      if(ClearMonit)
         DibZeroMemory(&pMpeIFecService->DvbSHMonitoring, sizeof(pMpeIFecService->DvbSHMonitoring));
   }

   DibDriverTargetEnableIrqProcessing(pContext);

   /* Send Message to clear internal monitoring info is sent separatly to avoid dead locks */
   if((pMpeIFecService) && (ClearMonit == eDIB_TRUE))
      DibDriverClearMonit(pContext, ItemHdl);

   return DIBSTATUS_SUCCESS;
}
/****************************************************************************
 * Firmware send mpe i-fec frame information.
 ****************************************************************************/
void DibDriverDragonflyProcessMsgMonitorMpeIFec(struct DibDriverContext *pContext, uint32_t * Data)
{
   struct MsgMpeIfecMonitor Msg;
   int32_t  BurstTimeMes;
   uint8_t  ItemHdl;
   struct DibDriverMpeIFecServiceCtx * pMpeIFec;

   MsgMpeIfecMonitorUnpack(&pContext->RxSerialBuf, &Msg);

   BurstTimeMes = Msg.BurstEndDate - Msg.BurstStartDate;
   ItemHdl = Msg.ItemHdl;

   DIB_ASSERT(Data);

#if (DEBUG_MODE == DEBUG_PRINT)

   DIB_DEBUG(MSG_LOG,(CRB "ItemIndex = %d" CRA, ItemHdl));
   switch(Msg.FrameStatus)
   {
   case 0:
      DIB_DEBUG(MSG_LOG,(CRB "FrameStatus     = DEF_FRAME_EMPTY" CRA));   break;
   case 1:
      DIB_DEBUG(MSG_LOG,(CRB "FrameStatus     = DEF_FRAME_INCOMPLETE" CRA));   break;
   case 2:
      DIB_DEBUG(MSG_LOG,(CRB "FrameStatus     = DEF_FRAME_FAILED" CRA));   break;
   case 3:
      DIB_DEBUG(MSG_LOG,(CRB "FrameStatus     = DEF_FRAME_COMPLETE" CRA));   break;
   case 4:
      DIB_DEBUG(MSG_LOG,(CRB "FrameStatus     = DEF_FRAME_FAULTY" CRA));   break;
   case 5:     
      DIB_DEBUG(MSG_LOG,(CRB "FrameStatus     = DEF_FRAME_RECOVERED" CRA));   break;
   case 6:     
      DIB_DEBUG(MSG_LOG,(CRB "FrameStatus     = DEF_FRAME_MISSED" CRA));   break;
   default:
      break;
   }
#endif

   /* Item has been removed since last call*/
   if(ItemHdl == DIB_UNSET)
      return;

   DIB_ASSERT(ItemHdl < DIB_MAX_NB_ITEMS);

   pMpeIFec = pContext->ItemInfo[ItemHdl].ItemCtx.pMpeIFecService;

   if(BurstTimeMes < 0)
      BurstTimeMes += 1 << 16;

   /* mpemnt */
   if(pMpeIFec != NULL)
   {
/*      DIB_DEBUG(MPE_MNT_LOG,(CRB "PID (%4d) Rows (%4d) B/S/D/C/R %2d / %2d / %2d / %3d / %2d  " CRA, */
      DIB_DEBUG(MPE_MNT_LOG,(CRB "PID (%4d) Rows (%4d) Burst (%d) Table (%d)" CRA, pMpeIFec->Pid, pMpeIFec->RsNumRows, Msg.BurstIndex, Msg.TableIndex));

      pMpeIFec->DvbSHMonitoring.AdtTotalTables     = Msg.NbADTTables;
      pMpeIFec->DvbSHMonitoring.AdtTablesCorrected = Msg.NbADTTablesCorrected;
      pMpeIFec->DvbSHMonitoring.AdtTablesFailed    = Msg.NbADTTablesFailed;
      pMpeIFec->DvbSHMonitoring.AdtTablesGood      = Msg.NbADTTablesGood;

      DIB_DEBUG(MPE_MNT_LOG, (CRB " ADT INFO : T/G/C/F: %d / %d / %d / %d " CRA, Msg.NbADTTables, Msg.NbADTTablesGood, Msg.NbADTTablesCorrected, Msg.NbADTTablesFailed));
      
      /** ADST (ie. burst) monitoring */
      pMpeIFec->DvbSHMonitoring.AdstTotalTables    = Msg.NbADSTTables         ;
      pMpeIFec->DvbSHMonitoring.AdstTablesLost     = Msg.NbADSTTablesLost     ;
      pMpeIFec->DvbSHMonitoring.AdstTablesCorrected= Msg.NbADSTTablesCorrected;
      pMpeIFec->DvbSHMonitoring.AdstTablesFailed   = Msg.NbADSTTablesFailed   ;
      pMpeIFec->DvbSHMonitoring.AdstTablesGood     = Msg.NbADSTTablesGood     ;

      pMpeIFec->DvbSHMonitoring.DeltaTStream       = Msg.DeltatMax * 10;
      pMpeIFec->DvbSHMonitoring.DeltaTDetected     = Msg.FrameDuration / 10;
      pMpeIFec->DvbSHMonitoring.BurstStream        = (Msg.DeltatMax - Msg.DeltatMin) * 10;
      pMpeIFec->DvbSHMonitoring.BurstDetected      = BurstTimeMes / 10;
      pMpeIFec->DvbSHMonitoring.PowerUpTime        = Msg.PowerUpDuration;

      DIB_DEBUG(MPE_MNT_LOG, (CRB " ADST INFO : T/G/C/F/L: %d / %d / %d / %d / %d " CRA, Msg.NbADSTTables, Msg.NbADSTTablesGood, Msg.NbADSTTablesCorrected, Msg.NbADSTTablesFailed, Msg.NbADSTTablesLost));
   }
}
/****************************************************************************
* Setup chip memory controller
****************************************************************************/
static DIBSTATUS DibBridgeFireflySetupDma(struct DibBridgeContext *pContext, struct DibBridgeDmaCtx *pDmaCtx)
{
   union Dwd l;
   DIBSTATUS ret = DIBSTATUS_ERROR;
   uint8_t CfgBlk[14];
   uint32_t ChipAddr = pDmaCtx->ChipAddr;

   DIB_ASSERT(pDmaCtx->DmaLen > 0);

   /* Set Len of transfer at Len */
   pDmaCtx->DmaSize = pDmaCtx->DmaLen;

   /** Overwrite ChipAddr to set the HostIf Interface register instead of the real chip.
    * The pDmaCtx->ChipAddr is set to REG_RAMIF_DATA. 
    * The Byte Enabled flag will be set on the address by the DibBridgeSetHostIfMode function
    * if the ByteMode passed to DibBridgeTargetDma, DibBridgeTargetWrite or DibBridgeTargetRead
    * is DIBBRIDGE_BIT_MODE_8. The DibBridgeSetHostIfMode function will also disable autoincrement
    * is destination address is REG_RAMIF_DATA, and enable it otherwise. */

   pDmaCtx->Mode = DIBBRIDGE_BIT_MODE_8;

   /* address formatting: use byte mode */
   pDmaCtx->FmtChipAddr = REG_RAMIF_DATA | 0x2000;

   /* Firefly previous porting compatibility */
   pDmaCtx->ChipAddr = REG_RAMIF_DATA | 0x2000;

   /* Odd start address at chip external space is not supported */
   if((ChipAddr & 1) && (ChipAddr & (1L << 23))) 
   {
      DIB_DEBUG(DMA_ERR, (CRB "Forbidden: odd start at ext mem" CRA));
      return DIBSTATUS_ERROR;
   }

   ret = DibBridgeWriteReg16(pContext, REG_RAMIF_IRAMCFG, 1);
   if(ret != DIBSTATUS_SUCCESS)
      return ret;

   CfgBlk[0] = 0;
   CfgBlk[1] = 1;

   l.l = ChipAddr;
   CfgBlk[3] = l.b.hl;
   CfgBlk[4] = l.b.lh;
   CfgBlk[5] = l.b.ll;
   
   l.l = pDmaCtx->ChipBaseMax;
   CfgBlk[7] = l.b.hl;
   CfgBlk[8] = l.b.lh;
   CfgBlk[9] = l.b.ll;
   
   l.l = pDmaCtx->ChipBaseMin;
   CfgBlk[11] = l.b.hl;
   CfgBlk[12] = l.b.lh;
   CfgBlk[13] = l.b.ll;

   
   ret = DibBridgeTargetWrite(pContext, REG_RAMIF_MODE | 0x1000, DIBBRIDGE_BIT_MODE_16, 14, &CfgBlk[0]);
   if(ret != DIBSTATUS_SUCCESS)
      return ret;

   if(pDmaCtx->Dir == DIBBRIDGE_DMA_READ) 
   {
      ret = DibBridgeWriteReg16(pContext, REG_RAMIF_MODE, (1L << 15) | 1);
      if(ret != DIBSTATUS_SUCCESS)
         return ret;
   }
   return DIBSTATUS_SUCCESS;
}
/**
 * Host Dma transfer is now finished, so we can process the information to upper layer
 * and eventually acknowledge the firmware.
 * @param[in] pContext; the bridge context structure.
 */
DIBSTATUS DibBridgeProcessDmaCommon(struct DibBridgeContext *pContext, struct DibBridgeDmaCtx * pDmaCtx)
{
   DIBSTATUS Status = DIBSTATUS_SUCCESS;
   ELEM_HDL ItemHdl = pDmaCtx->DmaFlags.ItemHdl; /**< This is an ItemHandler */
   DIB_ASSERT(ItemHdl < DIB_MAX_NB_ITEMS);
   DIB_ASSERT(pDmaCtx->DmaFlags.Type <= FORMAT_MSCPACKET);

   if(pDmaCtx->DmaFlags.Prefetch == 0)
   {
      switch (pDmaCtx->DmaFlags.Type) 
      {
         case FORMAT_SIPSI:
            DibBridgeSiPsiDone(pContext, pDmaCtx);
            break;

         case FORMAT_CMMB_RSM:
            DIB_ASSERT(pContext->ItSvc[ItemHdl].FilterParent != DIB_UNSET);
            DibBridgeCmmbRsmDone(pContext, pContext->FilterInfo[pContext->ItSvc[ItemHdl].FilterParent].DataMode, pDmaCtx);
            break;

         case FORMAT_PES_VIDEO:
         case FORMAT_PES_AUDIO:
         case FORMAT_PES_OTHER:
         case FORMAT_PCR:
         case FORMAT_RAWTS:
         case FORMAT_MSCPACKET:
         case FORMAT_MSCPLUS:
         case FORMAT_FIG:
         case FORMAT_MSC:
            /* check item cause the bridge can be still not informed that a new item is created whearas a block is ready!! */
            DIB_ASSERT(pContext->ItSvc[ItemHdl].FilterParent != DIB_UNSET);
            DibBridgeOtherDataDone(pContext, pContext->FilterInfo[pContext->ItSvc[ItemHdl].FilterParent].DataMode, pDmaCtx);
            break;

         case FORMAT_MPE:
         case FORMAT_MPE_CORR:
         case FORMAT_LAST_FRG:
         case FORMAT_FRG:
            DIB_ASSERT(pContext->ItSvc[ItemHdl].FilterParent != DIB_UNSET);
            DibBridgeMpeDataDone(pContext, pDmaCtx);
            break;

         case FORMAT_SH_FRG_DATA:
         case FORMAT_SH_FRG_IFEC:
         case FORMAT_SH_PATTERN_DATA:
         case FORMAT_SH_PATTERN_IFEC:
         case FORMAT_SH_FILL_DATA:
         case FORMAT_SH_FILL_IFEC:
         case FORMAT_SH_ALLOC:     
            /*DibBridgeShDataDone(pContext, pDmaCtx);*/
            break;

         case FORMAT_FLUSH_SVC:
            /* only forward Data to the IP Stack if it is not prefecth Data */
            break;

         case FORMAT_SLICE_REQ:
            if(pContext->DibChip == DIB_FIREFLY)
               DibBridgeSendAck(pContext, &pDmaCtx->DmaFlags, 0);
            break;

         case FORMAT_SLICE_DONE:
            Status = DibBridgeSliceDone(pContext, pDmaCtx);
            break;

#if (DEMOD_TRACE == 1)
         case FORMAT_DTRACE:
            DibB2DFwdDemodTrace(pContext, DTRACE_BUFF_SIZE, pContext->DemodTraceBuf);
            break;
#endif

#if (SUPPORT_CAV == 1)
         case FORMAT_CAV1:
            IntBridgeCav1Done(pContext, pDmaCtx);
            break;

         case FORMAT_CAV2:
            IntBridgeCav2Done(pContext, pDmaCtx);
            break;
#endif

         default:
            DIB_DEBUG(MAILBOX_ERR, (CRB "Oops! Unknown DMA action %d!" CRA, pDmaCtx->DmaFlags.Type));
            return DIBSTATUS_ERROR;
      }
   }

   /** We clear DmaCtx to indicate that it is cleaned */
   memset(pDmaCtx, 0, sizeof(struct DibBridgeDmaCtx));      /* DMA is done now */

   return Status;
}
Example #21
0
/****************************************************************************
* Write Data to the chip
* ----------------------------------------------------------------------
* Parameters:
* -----------
* struct DibBridgeContext *pContext
* uint16_t      Addr:          Address to write
* uint8_t       ByteMode:      Transfer Mode
*                 0: 16 bits wide register write
*                 1: 8 bits wide FIFO write
* uint32_t       Cnt:      Number of Bytes
* uint8_t      *pBuf:      Data Buffer
* ----------------------------------------------------------------------
* Return Code:
* -----------
*           DIBSTATUS_SUCCESS
*           DIBSTATUS_ERROR
****************************************************************************/
DIBSTATUS DibBridgeTargetWrite(struct DibBridgeContext *pContext, uint32_t Addr, uint8_t ByteMode, uint32_t Cnt, uint8_t *pBuf)
{
   DIBSTATUS rc = DIBSTATUS_SUCCESS;
   uint32_t   status, nb_lack, device_address, curk;
   uint32_t  new_addr;
   uint32_t   k, n;

   /* In word Mode the write count has to be even */
   if((ByteMode == DIBBRIDGE_BIT_MODE_16) && (Cnt & 1)) 
   {
      DIB_DEBUG(PORT_LOG, (CRB "-E- DibBridgeTargetWrite: Odd byte count" CRA));
      return DIBSTATUS_INVALID_PARAMETER;
   }

   /* Get semaphore to avoid concurrent access */
   DibAcquireLock(&pContext->DibTargetAccessLock);

   /* Add here the Code */
   device_address =  DEVICE_ADDRESS;
   status         = 0;
   nb_lack        = Cnt;
   new_addr       = Addr;
   curk           = 0;

   /**************************************************************/
   /********* 16 bits Architecture Dibcom Chips: *****************/
   /**************************************************************/
   /********* Dib7070, Dib7078, Dib9080, Dib9090 *****************/
   /**************************************************************/
   if(DibBridgeGetArch(pContext) == DIBBRIDGE_BIT_MODE_16)
   {

     while(nb_lack != 0)
     {
        pContext->BridgeTargetCtx.DataBuffer[0] = (new_addr>>8) & 0xFF;
        pContext->BridgeTargetCtx.DataBuffer[1] = (new_addr   ) & 0xFF;
  
        if(nb_lack>I2C_MAX_RDWR_SIZE)
        {
           n = I2C_MAX_RDWR_SIZE;
        }
        else
        {
           n = nb_lack;
        }
  
          nb_lack -= n; 
  
        pContext->BridgeTargetCtx.DataBuffer[0] |= 0x10;
  
        if(ByteMode == DIBBRIDGE_BIT_MODE_8) 
        {
             pContext->BridgeTargetCtx.DataBuffer[0] |= 0x20;
        }
  
        for(k=0 ; k<n ; k++)
          {
           pContext->BridgeTargetCtx.DataBuffer[k+2] = pBuf[k+curk];
        }
        curk += n;
    
        status |= I2CWrite(device_address, pContext->BridgeTargetCtx.DataBuffer, 2+n, ByteMode );
     }
    
   }
   /**************************************************************/
   /********* 32 bits Architecture Dibcom Chips: *****************/
   /**************************************************************/
   /******************* Dib29098, Dib10098 ***********************/
   /**************************************************************/
   else if(DibBridgeGetArch(pContext) == DIBBRIDGE_BIT_MODE_32)
void DibBridgeOtherDataDone(struct DibBridgeContext * pContext, enum DibDataMode DataMode, struct DibBridgeDmaCtx * pDmaCtx)
{
   uint8_t rc;

#if DIB_CHECK_RAWTS_DATA == 1
   if(pDmaCtx->DmaFlags.Type == FORMAT_RAWTS)
   {
      DibBridgeCheckRawTsData(pContext, pDmaCtx->pHostAddr, pDmaCtx->DmaLen, pDmaCtx->DmaFlags.ItemHdl);
      DibBridgeForwardCheckStats(pContext, pDmaCtx->DmaFlags.ItemHdl);
   }
#endif
#if DIB_CHECK_MSC_DATA
   if(pDmaCtx->DmaFlags.Type == FORMAT_MSC)
   {
      DibBridgeMscDone(pContext, pDmaCtx, pDmaCtx->DmaFlags.ItemHdl);
      DibBridgeForwardCheckStats(pContext, pDmaCtx->DmaFlags.ItemHdl);
   }
#endif

   if(DataMode == eCLBACK)
   {
     if(pContext->DataInfoUp[pContext->NextFreeWrBuff].pBuff != NULL)
     {
       DIB_DEBUG(RAWTS_ERR, (CRB "DataInfoUp Overflow: Free Buffer" CRA));
       DibBridgeDesallocateRawBuffer(pContext, pDmaCtx->pHostAddr, pDmaCtx->DmaLen);
     }
     else
     {
        pContext->DataInfoUp[pContext->NextFreeWrBuff].pBuff = pDmaCtx->pHostAddr;
        pContext->DataInfoUp[pContext->NextFreeWrBuff].FilterIndex = pContext->ItSvc[pDmaCtx->DmaFlags.ItemHdl].FilterParent; 

        pContext->NextFreeWrBuff = (pContext->NextFreeWrBuff + 1)%(MAX_Q_BUFF);

        DIB_DEBUG(RAWTS_LOG, (CRB "NextFreeWrBuff : %d" CRA, pContext->NextFreeWrBuff));
        DibB2DFwdRawData(pContext, pDmaCtx->DmaLen, pDmaCtx->DmaFlags.ItemHdl, pDmaCtx->DmaFlags.FirstFrag, pDmaCtx->DmaFlags.LastFrag);
     }
   }
   else
   {
      switch(pDmaCtx->DmaFlags.Type)
      {
       case FORMAT_RAWTS:
          rc = DibBridgeNotifyRawbufferWrite(pContext,pDmaCtx->pHostAddr,pDmaCtx->DmaLen, pDmaCtx->DmaFlags.ItemHdl);
          DIB_ASSERT(rc == DIBSTATUS_SUCCESS);
          break;
       case FORMAT_FIG:
          DibBridgeFigDone(pContext, pDmaCtx);
          break;
       case FORMAT_MSC:
          DibBridgeMscDone(pContext, pDmaCtx, pDmaCtx->DmaFlags.ItemHdl);
          break;
      case FORMAT_MSCPACKET:
          break;
      case FORMAT_MSCPLUS:
          DibBridgeMscPlusDone(pContext, pDmaCtx, pDmaCtx->DmaFlags.ItemHdl);
          break;
      case FORMAT_PES_VIDEO:
      case FORMAT_PES_AUDIO:
      case FORMAT_PES_OTHER:
          DibBridgePesDone(pContext, pDmaCtx);
          break;
      case FORMAT_PCR:
          DibBridgePcrDone(pContext, pDmaCtx);
          break;
       default:
          DIB_DEBUG(RAWTS_ERR, (CRB "IntBridgeOtherDataDone : FORMAT %d not managed" CRA, pDmaCtx->DmaFlags.Type));
         break;
      }
   }
}
/**
 * Handler for IN_MSG_DATA message.
 * Parses and processes the most prioritary messages, and passes the others
 * to the upper layer. Start host DMA transfert if needed.
 * @param[in] min: Field Info 1 of IN_DATA_MSG. Most of the time it is a lower limit in a circular buffer of the firmware
 * @param[in] max: Field Info 2 of IN_DATA_MSG. Most of the time it is a higher limit in a circular buffer of the firmware
 * @param[in] add: Field Info 3 of IN_DATA_MSG. Most of the time it is the add in the firmware, src of the dma transfert
 * @param[in] len: Field Info 4 of IN_DATA_MSG. Most of the time it is the len in lines (256 bytes) or bytes to transfert
 * @param[in] flags: the flags (svc, type, first_frag, last_frag, prefetch..) needed when the dma transfert is finished.
 * @return: the DMA state: no DMA (DIB_NO_DMA), done (DIB_DMA_DONE) or pending (DIB_DMA_PENDING).
 */
DIBDMA DibBridgeLowDataMsgHandlerCommon(struct DibBridgeContext *pContext, uint32_t min, uint32_t max, uint32_t add, uint32_t len, struct DibBridgeDmaFlags *pFlags)
{
   DIBDMA   DmaStat;

   DIB_ASSERT((pFlags->LastFrag == eDIB_TRUE) || (pFlags->LastFrag == eDIB_FALSE));

   /* Data notification */
   DmaStat = DIB_NO_DMA;

   DIB_DEBUG(MAILBOX_LOG, (CRB "MSG IN DATA:  Type=%d item=%d min=0x%08x max=0x%08x add=0x%08x len=%d" CRA, pFlags->Type, pFlags->ItemHdl, min, max, add, len));

   /* Sanity checks */
   DIB_ASSERT(pFlags->ItemHdl < DIB_MAX_NB_ITEMS);
   if(pFlags->ItemHdl >= DIB_MAX_NB_ITEMS) 
   {
      DIB_DEBUG(MAILBOX_ERR, (CRB "DMA transfer request illegal Item number %d!" CRA, pFlags->ItemHdl));
      return DIB_NO_DMA;
   }

   DIB_ASSERT(pFlags->NbRows <= 4);

   switch (pFlags->Type) 
   {
      /* -------------------------------------------------------------------------------- */
      case FORMAT_FLUSH_SVC:
         DibBridgeFlushService(pContext, pFlags->ItemHdl, (uint8_t) min, (uint8_t) max, pFlags->Prefetch);
         break;

      case FORMAT_SLICE_REQ:
         if (pContext->SliceBuf == NULL) 
         {
            /*** FEC slice Buffer allocation*/
            pContext->SliceBuf = DibBridgeTargetAllocBuf(HBM_SLICE_SIZE);

            if(pContext->SliceBuf == 0) 
            {
               union DibEventConfig EventConfig;
               EventConfig.DataLostEvent.ItemHdl = pFlags->ItemHdl;
               DIB_DEBUG(PORT_ERR, (CRB "Unable to allocate slice Buffer" CRA));

               /* signal error to firmware flush cor Buffer*/
               DibBridgeSendAck(pContext, pFlags, 1);
               DibB2DFwdEvents(pContext, eDATA_LOST, &EventConfig);
               break;
            }
         }
         DmaStat = DibBridgeAssembleSlice(pContext, min, max, add, len, pFlags);

         break;

         /* -------------------------------------------------------------------------------- */
      case FORMAT_SLICE_DONE:
         DmaStat = DibBridgeGetSlice(pContext, min, max, add, len, pFlags);

         break;

         /* -------------------------------------------------------------------------------- */
      case FORMAT_SIPSI:
         DmaStat = DibBridgeGetSipsi(pContext, min, max, add, len, pFlags);
         break;

         /* -------------------------------------------------------------------------------- */
      case FORMAT_RAWTS:
      case FORMAT_FIG:
      case FORMAT_MSCPACKET:
      case FORMAT_MSCPLUS:
      case FORMAT_MSC:
      case FORMAT_PES_VIDEO:
      case FORMAT_PES_AUDIO:
      case FORMAT_PES_OTHER:
      case FORMAT_PCR:
      case FORMAT_CAV1:
      case FORMAT_CAV2:
      case FORMAT_CMMB_RSM:
         DmaStat = DibBridgeGetRawData(pContext, min, max, add, len, pFlags);
         break;

      case FORMAT_SH_FRG_DATA:
      case FORMAT_SH_FRG_IFEC:
         DmaStat = DibBridgeGetShFragment(pContext, min, max, 0, add, len, pFlags, 1);
         /*DibMSleep(1);*/
         break;

      case FORMAT_SH_PATTERN_DATA:
      case FORMAT_SH_PATTERN_IFEC:
         pContext->DmaCtx.DmaFlags = *pFlags;
         pContext->DmaCtx.DmaLen   = len;
         DmaStat = DibBridgeFillShPattern(pContext, min, max, add, len, pFlags);
         break;

      case FORMAT_SH_FILL_DATA:
      case FORMAT_SH_FILL_IFEC:
         pContext->DmaCtx.DmaFlags = *pFlags;
         pContext->DmaCtx.DmaLen   = len;
         DmaStat = DibBridgeFillShData(pContext, min, max, add, len, pFlags);
         break;

      case FORMAT_SH_ALLOC:
         pContext->DmaCtx.DmaFlags = *pFlags;
         pContext->DmaCtx.DmaLen   = len;
         DmaStat = DibBridgeAllocMemory(pContext, min, max, add, len, pFlags);
         break;
         
         /* -------------------------------------------------------------------------------- */
      case FORMAT_MPE:
      case FORMAT_FRG:
      case FORMAT_LAST_FRG:
         DmaStat = DibBridgeGetFragment(pContext, min, max, add, len, pFlags);
         break;

      case FORMAT_MPE_CORR:
         /** As no dma is required only set the pFlags and Size and complete dma */
         pContext->DmaCtx.DmaFlags = *pFlags;
         pContext->DmaCtx.DmaLen   = len;
         /** ProcessDmaDone after this function */
         DmaStat = DIB_DMA_DONE;
         break;

         /* -------------------------------------------------------------------------------- */
      default:
         DIB_DEBUG(MAILBOX_ERR, (CRB "Low: Received unknown Type for Data message: %d" CRA, pFlags->Type));
         break;
   }

   return DmaStat;      /* Tells do we have a pending DMA or not */
}
/****************************************************************************
 * Warn the BridgeGetMsgQueue function that the MsgQueue is terminating.
 * Then the MsgQueue will be DeInited on close sys call.
 ****************************************************************************/
void DibBridgeTerminateMsgQueue(struct DibBridgeContext *pContext)
{
   pContext->MsgQueueInitialized = 0;
   DibSetEvent(&pContext->MsgQueueEvent);
   DIB_DEBUG(PORT_LOG, (CRB "DibBridgeTerminateMsgQueue!" CRA));
}
DIBSTATUS DibBridgeAddBufferToMessageQueue(struct DibBridgeContext *pContext, uint16_t Type, uint32_t Nb, uint8_t *pBuf)
{
   struct DibBridgeMsgQueue * pMsg;
   uint8_t *pQueueAddr;
   uint32_t MsgQueueFree;
   uint32_t MsgSize;
   uint32_t OldHead;
   uint32_t WasEmpty;

   /* No init done */
   if(!pContext->MsgQueueInitialized) 
   {
      DIB_DEBUG(PORT_ERR, (CRB "can't add msg to msg queue : no init done !" CRA));
      return DIBSTATUS_ERROR;
   }

   DIB_ASSERT(pBuf);
   DIB_ASSERT(Nb <= UPMESSAGE_MAX_SIZE);
   DIB_ASSERT(Nb <= 0xFFFF);   /* as typecasted in unt16_t */

   /** safely access to MsgQueue */
   DibAcquireLock(&pContext->MsgQueueLock);

   DIB_ASSERT(pContext->MsgQueueHead < UPMESSAGE_MAILBOX_SIZE);
   DIB_ASSERT(pContext->MsgQueueTail < UPMESSAGE_MAILBOX_SIZE);

   DIB_ASSERT((pContext->MsgQueueHead & 3) == 0);
   DIB_ASSERT((pContext->MsgQueueTail & 3) == 0);

   MsgQueueFree = (pContext->MsgQueueTail - pContext->MsgQueueHead + UPMESSAGE_MAILBOX_SIZE - 1) % (UPMESSAGE_MAILBOX_SIZE);
   WasEmpty = (pContext->MsgQueueTail == pContext->MsgQueueHead) ? 1 : 0 ;

   /** the message contain the buffer. be carefull with message size. */
   MsgSize = DIB_BRIDGE_MESSAGE_SIZE(Nb);

   DIB_DEBUG(PORT_LOG, (CRB "IntBridgeAddBufferToMessageQueue: MsgQueueFree=%d, MsgSize=%d" CRA,MsgQueueFree, MsgSize));

   DIB_ASSERT((MsgSize & 3) == 0);

   /** The number of free bytes must stay stricktly greater than 0 after adding the message to avoid pointer beeing equal */
   if( MsgSize >= MsgQueueFree ) 
   {
      DIB_DEBUG(PORT_ERR, (CRB "QUEUE FULL (free bytes = %d), discard msg %d of size %d %d" CRA, MsgQueueFree, Type, MsgSize, Nb));
      DibReleaseLock(&pContext->MsgQueueLock);
      return DIBSTATUS_RESOURCES;
   }

   /** If we have a non prio message, check that we still have UPMESSAGE_MAILBOX_MIN_SIZE for our priority messages */
   if(((MsgQueueFree - MsgSize) < UPMESSAGE_MAILBOX_MIN_SIZE) && (Type != UPMESSAGE_TYPE_MSG))
   {
      DIB_DEBUG(PORT_ERR, (CRB "QUEUE CRITICAL SIZE (free bytes = %d), discard msg %d of size %d %d" CRA, MsgQueueFree, Type, MsgSize, Nb));
      DibReleaseLock(&pContext->MsgQueueLock);
      return DIBSTATUS_RESOURCES;
   }

   pQueueAddr = ((uint8_t *)pContext->MsgQueue + pContext->MsgQueueHead);

   /** we always have the place to put at least the message header into the circular buffer */
   pMsg       = (struct DibBridgeMsgQueue *)pQueueAddr;
   pMsg->Size = (uint16_t) Nb;
   pMsg->Type = Type;
   pQueueAddr += sizeof(struct DibBridgeMsgQueue);
   pContext->MsgQueueHead += sizeof(struct DibBridgeMsgQueue);

   /** wrap if needed after message header copy */
   if(pContext->MsgQueueHead >= UPMESSAGE_MAILBOX_SIZE)
   {
      pQueueAddr = (uint8_t *)pContext->MsgQueue;
      pContext->MsgQueueHead = 0;
   }

   /** check if a wrap is needed during buffer copy */
   if(Nb > 0)
   {
      /** get the number of free byte until the end of the buffer */
      MsgQueueFree = UPMESSAGE_MAILBOX_SIZE - pContext->MsgQueueHead;

      DIB_ASSERT(MsgQueueFree >= 4);

      if(Nb > MsgQueueFree)
      {
         /** copy the first part */
         DibMoveMemory(pQueueAddr, pBuf, MsgQueueFree);

         /** copy the second part */
         pQueueAddr = (uint8_t *)pContext->MsgQueue;
         DibMoveMemory(pQueueAddr, pBuf + MsgQueueFree, Nb - MsgQueueFree);
      }
      else
      {
         /** copy the buffer in one block */
         DibMoveMemory(pQueueAddr, pBuf, Nb);
      }
   }

   /** move MsgQueueHead with MsgSize, not Nb! */
   OldHead = pContext->MsgQueueHead;
   pContext->MsgQueueHead = (pContext->MsgQueueHead + MsgSize - sizeof(struct DibBridgeMsgQueue)) % (UPMESSAGE_MAILBOX_SIZE);

   DIB_ASSERT(pContext->MsgQueueHead != pContext->MsgQueueTail);

   DIB_DEBUG(RAWTS_LOG, (CRB "IntBridgeAddBufferToMessageQueue Add Msg (Size: %d Type: %d)" CRA, Nb, Type));    

   /** warn the user if queue was empty */
   if(WasEmpty)
   {
      DibSetEvent(&pContext->MsgQueueEvent);
   }

   DibReleaseLock(&pContext->MsgQueueLock);

   return DIBSTATUS_SUCCESS;
}
/****************************************************************************
* Receive msg from the bridge
****************************************************************************/
void *IntDriverTargetIrqRead(void *arg)
{
    /* Dirty change to fix alignment issue */
    /* Previously msg was aligned on a 16 bit boundary and then used as a 32 bit
     * pointer, so 32 bits access => alignment issue
     * Now msg is aligned on 32 bit boundary */

   uint8_t  *msg;
   uint16_t *Type;
   uint8_t  *read_buffer2 = DibMemAlloc(4096+sizeof(*Type));
   uint8_t  *read_buffer = &read_buffer2[sizeof(*Type)];

   struct DibDriverDataInfoUp dataUp;
   struct DibDriverEventInfoUp EventUp;
   struct DibDriverContext   *pContext = (struct DibDriverContext *) arg;

   /* Signal task started */
   DibSetEvent(&pContext->DriverTargetCtx.IrqReadDone);

   while(1) 
   {
      /* read on the char device for SIPSI/MSG/TS */
      ssize_t bytes_read = ioctl(pContext->DriverTargetCtx.BridgeFd, REQUEST_READ_MSG, read_buffer);

      /* Extract the Buffer Type (sipsi/msg/ts and get the msg */
      Type        = (uint16_t *) read_buffer;
      msg         = read_buffer + sizeof(*Type);
      bytes_read -= sizeof(*Type);

      /* Process the msg */
      DIB_DEBUG(PORT_LOG, (CRB "Low Speed IRQ: %d, Size= %d" CRA, msg[0], (uint32_t)bytes_read));

      if(bytes_read > 0) 
      {
         /** acquired driver lock */
         DibDriverTargetDisableIrqProcessing(pContext);

         switch (*Type) 
         {
         case UPMESSAGE_TYPE_MSG:
            DibDriverProcessMessage(pContext, bytes_read, (uint16_t *) msg);
            break;

         case UPMESSAGE_TYPE_SIPSI:
            DibDriverProcessSiPsiBuffer(pContext, bytes_read, msg);
            break;

         case UPMESSAGE_TYPE_DATA:
            DibMoveMemory((char *)&dataUp, msg, sizeof(struct DibDriverDataInfoUp));
            DIB_DEBUG(PACKET_LOG, (CRB "ioctl bytes_read %d Size : %d item : %d" CRA, (int32_t)bytes_read, dataUp.Length, dataUp.ItemIndex));
            DibDriverRawDataRead(pContext, dataUp);
            break;

         case UPMESSAGE_TYPE_EVENT:
            DibMoveMemory((char *)&EventUp, msg, sizeof(struct DibDriverEventInfoUp));
            DIB_DEBUG(CALLBACK_ERR, (CRB "Event up %d Filter : %d" CRA, EventUp.EventType, EventUp.EventConfig.DataLostEvent.ItemHdl));
            DibDriverPostEvent(pContext, &EventUp);
            break;
            
#if (DEMOD_TRACE == 1)
         case UPMESSAGE_TYPE_DTRACE:
            {
               /* Insert your DTRACE logger here */
               uint16_t y;
               uint16_t *rb;

               y  = 0;
               rb = (uint16_t *)msg;

               fprintf(stderr, "\E[H\E[2J");
               while(y < (DTRACE_BUFF_SIZE / 2)) 
               {
                  if(!(y & 0x07)) 
                     fprintf(stderr, "%04X: ", y);

                  y++;
                  fprintf(stderr, CRB "%04X%s", *rb, (y & 0x07) ? " " : "" CRA);
                  rb++;
               }

               if(y & 0x07) 
                  fprintf(stderr, CRB "" CRA);
            }
            break;
#endif

         default:
            DIB_DEBUG(PORT_ERR, (CRB "Low Speed IRQ unknow message %d" CRA, msg[0]));
            break;
         }

         /** release driver lock */
         DibDriverTargetEnableIrqProcessing(pContext);
      }
      else 
      {
         break;
/**
 * Handler for IN_MSG_DATA message.
 * Parses and processes the most prioritary messages, and passes the others
 * to the upper layer. Start host DMA transfert if needed.
 * @param[in] min: Field Info 1 of IN_DATA_MSG. Most of the time it is a lower limit in a circular buffer of the firmware
 * @param[in] max: Field Info 2 of IN_DATA_MSG. Most of the time it is a higher limit in a circular buffer of the firmware
 * @param[in] add: Field Info 3 of IN_DATA_MSG. Most of the time it is the add in the firmware, src of the dma transfert
 * @param[in] len: Field Info 4 of IN_DATA_MSG. Most of the time it is the len in lines (256 bytes) or bytes to transfert
 * @param[in] flags: the flags (svc, type, first_frag, last_frag, prefetch..) needed when the dma transfert is finished.
 * @return: the DMA state: no DMA (DIB_NO_DMA), done (DIB_DMA_DONE) or pending (DIB_DMA_PENDING).
 */
DIBDMA DibBridgeHighDataMsgHandlerCommon(struct DibBridgeContext *pContext, uint32_t min, uint32_t max, uint32_t add, uint32_t len, struct DibBridgeDmaFlags *pFlags)
{
   DIBDMA   DmaStat;

   DIB_ASSERT((pFlags->LastFrag == eDIB_TRUE) || (pFlags->LastFrag == eDIB_FALSE));

   /* Data notification */
   DmaStat = DIB_NO_DMA;

   /* Sanity checks */
   DIB_ASSERT(pFlags->ItemHdl < DIB_MAX_NB_ITEMS);
   if(pFlags->ItemHdl >= DIB_MAX_NB_ITEMS) 
   {
      DIB_DEBUG(MAILBOX_ERR, (CRB "DMA transfer request illegal Item number %d!" CRA, pFlags->ItemHdl));
      return DIB_NO_DMA;
   }

   DIB_ASSERT(pFlags->NbRows <= 4);

   switch (pFlags->Type) 
   {
      /* -------------------------------------------------------------------------------- */
      case FORMAT_SLICE_REQ:
      case FORMAT_SLICE_DONE:
      case FORMAT_SIPSI:
      case FORMAT_FIG:
      case FORMAT_MSC:
      case FORMAT_RAWTS:
      case FORMAT_MPE_CORR:
      case FORMAT_MSCPACKET:
      case FORMAT_MSCPLUS:
         DmaStat = IntBridgeDeferDataMsg(pContext, min, max, add, len, pFlags);
         break;

         /* -------------------------------------------------------------------------------- */
      case FORMAT_MPE:
      case FORMAT_FRG:
      case FORMAT_LAST_FRG:
      case FORMAT_FLUSH_SVC:
      case FORMAT_PES_VIDEO:
      case FORMAT_PES_AUDIO:
      case FORMAT_PES_OTHER:
      case FORMAT_PCR:
      case FORMAT_SH_FRG_DATA:
      case FORMAT_SH_FRG_IFEC:
      case FORMAT_SH_PATTERN_DATA:
      case FORMAT_SH_PATTERN_IFEC:
      case FORMAT_SH_FILL_DATA:
      case FORMAT_SH_FILL_IFEC:
      case FORMAT_SH_ALLOC:
      case FORMAT_CMMB_RSM:
      case FORMAT_CAV1:
      case FORMAT_CAV2:
         DmaStat = DibBridgeLowDataMsgHandlerCommon(pContext, min, max, add, len, pFlags);
         break;

         /* -------------------------------------------------------------------------------- */
      default:
         DIB_DEBUG(MAILBOX_ERR, (CRB "High: Received unknown Type for Data message: %d" CRA, pFlags->Type));
         break;
   }

   return DmaStat;      /* Tells do we have a pending DMA or not */
}
int32_t DibBridgeTargetModuleIoctl(struct inode *inode, struct file *file, uint32_t ioctl_num, LINUX_PTR_CAST ioctl_param)
#endif
{
   int32_t                  status   = DIBSTATUS_SUCCESS;
   struct DibBridgeContext *pContext = (struct DibBridgeContext *) file->private_data;
   struct IoctlHead        *req      = pContext->BridgeTargetCtx.IoctlReq;

   DIB_ASSERT(pContext);

   switch (ioctl_num) 
   {
   case REQUEST_BRIDGE_POSTINIT:
      if(DibBridgePostInit(pContext, ioctl_param) != DIBSTATUS_SUCCESS)
         return DIBSTATUS_INVALID_PARAMETER;
      break;

   case REQUEST_BRIDGE_MODULE_INIT:
      {
         struct IoctlInit Init;

         if(copy_from_user(&Init, (struct IoctlInit *) ioctl_param, sizeof(struct IoctlInit)))
         {
            DIB_DEBUG(PORT_ERR, (CRB "%s: copy_from_user failed" CRA, __func__));
            return DIBSTATUS_INVALID_PARAMETER;
         }

         running = eDIB_TRUE;

         /* Initialize bridge (common & target). TODO: Retreive the board handler from the file name */
         return DibBridgeInit(pContext, Init.BoardHdl, Init.ChipSelect, Init.Config, DebugMask);
      }
      break;

   case REQUEST_BRIDGE_MODULE_SHUTDOWN:
      if(DibBridgeDeinit(pContext) != DIBSTATUS_SUCCESS){ 
         return DIBSTATUS_INVALID_PARAMETER;
      }
      running = eDIB_FALSE;
      break;

   case REQUEST_REG_DOWN:
      DibAcquireLock(&pContext->BridgeTargetCtx.IoctlLock);
      if(copy_from_user(req, (struct IoctlHead *) ioctl_param, offsetof(struct IoctlHead, Buffer)))
      {
         DIB_DEBUG(PORT_ERR, (CRB "%s: copy_from_user failed" CRA, __func__));
         DibReleaseLock(&pContext->BridgeTargetCtx.IoctlLock);
         return DIBSTATUS_INVALID_PARAMETER;
      }
      if(copy_from_user(req->Buffer, ((struct IoctlHead *) ioctl_param)->Buffer, req->Nb))
      {
         DIB_DEBUG(PORT_ERR, (CRB "%s: copy_from_user failed" CRA, __func__));
         DibReleaseLock(&pContext->BridgeTargetCtx.IoctlLock);
         return DIBSTATUS_INVALID_PARAMETER;
      }
      status = DibBridgeWrite(pContext, req->param.address, req->param.Mode, req->Buffer, req->Nb);
      DibReleaseLock(&pContext->BridgeTargetCtx.IoctlLock);
   break;

   case REQUEST_REG_UP:
      DibAcquireLock(&pContext->BridgeTargetCtx.IoctlLock);
      if(copy_from_user(req, (struct IoctlHead *) ioctl_param, offsetof(struct IoctlHead, Buffer)))
      {
         DIB_DEBUG(PORT_ERR, (CRB "%s: copy_from_user failed" CRA, __func__));
         DibReleaseLock(&pContext->BridgeTargetCtx.IoctlLock);
         return DIBSTATUS_INVALID_PARAMETER;
      }
      if(copy_from_user(req->Buffer, ((struct IoctlHead *) ioctl_param)->Buffer, req->Nb))
      {
         DIB_DEBUG(PORT_ERR, (CRB "%s: copy_from_user failed" CRA, __func__));
         DibReleaseLock(&pContext->BridgeTargetCtx.IoctlLock);
         return DIBSTATUS_INVALID_PARAMETER;
      }
      status = DibBridgeRead(pContext, req->param.address, req->param.Mode, req->Buffer, req->Nb);

      if(copy_to_user((struct IoctlHead *) ioctl_param, req, offsetof(struct IoctlHead, Buffer)))
      {
         printk(KERN_WARNING CRB "problem copy_to_user" CRA);
         DibReleaseLock(&pContext->BridgeTargetCtx.IoctlLock);
         return DIBSTATUS_INVALID_PARAMETER;
      }
      if(copy_to_user(((struct IoctlHead *) ioctl_param)->Buffer, req->Buffer, req->Nb))
      {
         printk(KERN_WARNING CRB "problem copy_to_user 2" CRA);
         DibReleaseLock(&pContext->BridgeTargetCtx.IoctlLock);
         return DIBSTATUS_INVALID_PARAMETER;
      }
      DibReleaseLock(&pContext->BridgeTargetCtx.IoctlLock);
      break;

   case REQUEST_TRANSERT_BUF:
      DibAcquireLock(&pContext->BridgeTargetCtx.IoctlLock);
      {
         uint8_t *pBlock, *pHostAddr;
         struct DibBridgeDmaCtx BridgeDma;
         if(copy_from_user(req, (struct IoctlHead *) ioctl_param, offsetof(struct IoctlHead, Buffer))) 
         {
            DIB_DEBUG(PORT_ERR, (CRB "%s: copy_from_user failed" CRA, __func__));
            DibReleaseLock(&pContext->BridgeTargetCtx.IoctlLock);
            return DIBSTATUS_INVALID_PARAMETER;
         }
         if(copy_from_user(req->Buffer, ((struct IoctlHead *) ioctl_param)->Buffer, req->Nb))
         {
            DIB_DEBUG(PORT_ERR, (CRB "%s: copy_from_user failed" CRA, __func__));
            DibReleaseLock(&pContext->BridgeTargetCtx.IoctlLock);
            return DIBSTATUS_INVALID_PARAMETER;
         }

         memcpy(&BridgeDma, req->Buffer, sizeof(struct DibBridgeDmaCtx) - sizeof(struct DibBridgeDmaFlags));
         memset(&BridgeDma.DmaFlags, 0, sizeof(struct DibBridgeDmaFlags));

         /*pBlock = DibMemAlloc(BridgeDma.DmaLen);*/
         pBlock = DibBridgeTargetAllocBuf(BridgeDma.DmaLen);
         
         printk(CRB "Request Dma Transfert dir=%d mode=%d chip=%08x host=%p kernel=%p len=%d" CRA,
            BridgeDma.Dir, BridgeDma.Mode, BridgeDma.ChipAddr,BridgeDma.pHostAddr,pBlock,BridgeDma.DmaLen);

         /* save user host buffer and use the kernel one to do the dma transfer */
         pHostAddr = BridgeDma.pHostAddr;
         BridgeDma.pHostAddr = pBlock;

         if(BridgeDma.Dir == DIBBRIDGE_DMA_WRITE)
         {
            if(copy_from_user(pBlock, pHostAddr, BridgeDma.DmaLen)) 
            {
               DIB_DEBUG(PORT_ERR, (CRB "%s: copy_from_user failed" CRA,__func__));
               DibReleaseLock(&pContext->BridgeTargetCtx.IoctlLock);
               return DIBSTATUS_INVALID_PARAMETER;
            }
         }

         status = DibBridgeTransfertBuf(pContext, &BridgeDma);

         if(BridgeDma.Dir == DIBBRIDGE_DMA_READ)
         {
            if(copy_to_user(pHostAddr, pBlock, BridgeDma.DmaLen)) 
            {
               DIB_DEBUG(PORT_ERR, (CRB "%s: copy_to_user failed" CRA, __func__));
               DibReleaseLock(&pContext->BridgeTargetCtx.IoctlLock);
               return DIBSTATUS_INVALID_PARAMETER;
            }
         }

         /*DibMemFree(pBlock,BridgeDma.DmaLen);*/
         DibBridgeTargetFreeBuf(pBlock,BridgeDma.DmaLen);
      }
      DibReleaseLock(&pContext->BridgeTargetCtx.IoctlLock);
      break;

   case REQUEST_MSG_DOWN:
      DibAcquireLock(&pContext->BridgeTargetCtx.IoctlLock);
      if(copy_from_user(req, (struct IoctlHead *) ioctl_param, offsetof(struct IoctlHead, Buffer)))
      {
         DIB_DEBUG(PORT_ERR, (CRB "%s: copy_from_user failed" CRA, __func__));
         DibReleaseLock(&pContext->BridgeTargetCtx.IoctlLock);
         return DIBSTATUS_INVALID_PARAMETER;
      }
      if(copy_from_user(req->Buffer, ((struct IoctlHead *) ioctl_param)->Buffer, req->Nb))
      {
         DIB_DEBUG(PORT_ERR, (CRB "%s: copy_from_user failed" CRA, __func__));
         DibReleaseLock(&pContext->BridgeTargetCtx.IoctlLock);
         return DIBSTATUS_INVALID_PARAMETER;
      }
      status = DibBridgeSendMsg(pContext, (uint32_t *) req->Buffer, req->Nb);
      DibReleaseLock(&pContext->BridgeTargetCtx.IoctlLock);
      break;

   case REQUEST_READ_MSG:
      status = DibBridgeTargetModuleReadMsg(pContext, (uint8_t *)ioctl_param);
      break;

   case REQUEST_DATAPATH_INFO:
      {
         struct IoctlSvcInfo DataInfo;
         union DibInformBridge SetBridgeInfo;

         if(copy_from_user(&DataInfo, (struct IoctlSvcInfo *) ioctl_param, sizeof(struct IoctlSvcInfo)))
         {
            DIB_DEBUG(PORT_ERR, (CRB "%s: copy_from_user failed" CRA, __func__));
            return DIBSTATUS_INVALID_PARAMETER;
         }

         SetBridgeInfo.SetService.Svc = DataInfo.svc;
         SetBridgeInfo.SetService.ItemHdl = DataInfo.item;
         SetBridgeInfo.SetService.FilterHdl = DataInfo.filter;
         SetBridgeInfo.SetService.StreamId = DataInfo.StreamId;
         SetBridgeInfo.SetService.DataType = DataInfo.DataType;
         SetBridgeInfo.SetService.DataMode = DataInfo.DataMode;

         status = DibBridgeSetInfo(pContext, eSET_SERVICE, &SetBridgeInfo);
      }
      break;
      
   case REQUEST_READ_DATA:
   {
      struct IoctlReadData ReadData;
      uint32_t ReadSize;
      uint8_t * ReadBuf;
      int32_t ret;
      FILTER_HDL FiltHdl;
      if(copy_from_user(&ReadData, (struct IoctlReadData *)ioctl_param, sizeof(struct IoctlReadData)))
      {
         DIB_DEBUG(PORT_ERR, (CRB "%s: copy_from_user failed" CRA, __func__));
         return DIBSTATUS_INVALID_PARAMETER;
      }
      ReadSize = (uint32_t)(ReadData.SizeBuffer);
      FiltHdl = ReadData.FilterHdl;
      
      if(ReadData.Mode == eDIB_TRUE)
      {
         /** Resynchronise FilterHdl from user and from bridge queue */
         if(DibBridgeGetRawBufferFull(pContext, &ReadBuf, &FiltHdl) != DIBSTATUS_SUCCESS)
         {
            printk(CRB "Read Data: not able to read a buffer from the wanted filter" CRA);
            return DIBSTATUS_ERROR;
         }

         /* copy msg Type to user Buffer */
         if(ReadSize > 0) 
         {
            ret = copy_to_user(ReadData.HostBuffer, ReadBuf, ReadSize);
   
            /* check if success */
            if(ret) 
            {
               DIB_DEBUG(PORT_ERR, (CRB "%s: copy_to_user failed" CRA, __func__));
               status = DIBSTATUS_ERROR;
            }else{
               
               status = DIBSTATUS_SUCCESS;
            }
         }
          /* for mpe processing, the buffer is freed later, after having forwarded the data */
         if(pContext->FilterInfo[FiltHdl].DataType != eMPEFEC)
         {
            DibBridgeNotifyRawbufferRead(pContext, ReadBuf, ReadSize);
         }
         
      }else{
         if(DibBridgeGetRawBufferFull(pContext, &ReadBuf, &FiltHdl) != DIBSTATUS_SUCCESS)
         {
            printk(CRB "Read Data: not able to read a buffer" CRA);
            return DIBSTATUS_ERROR;
         }

         /* for mpe processing, the buffer is freed later, after having forwarded the data */
         if(pContext->FilterInfo[FiltHdl].DataType != eMPEFEC)
         {
            /** flush the buffer correctly */
            DibBridgeNotifyRawbufferRead(pContext, ReadBuf, ReadSize);
         }

         status = DIBSTATUS_SUCCESS;            
      }
   }
      break;

   default:
      DIB_DEBUG(PORT_ERR, (CRB "DIbBridgeModuleIoctl: unknown Type %d" CRA, ioctl_num));

      status = DIBSTATUS_INVALID_PARAMETER;
      break;
   }

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
   return (long)status;
#else
   return status;
#endif
}
/**
 * Retrieve a msg from the Bridge 2 Driver msg queue, and copy it to the input buffer using a specific target copy function;
 */
DIBSTATUS DibBridgeGetBufFromMsgQueue(struct DibBridgeContext *pContext, uint16_t *pType, uint16_t *pSize, uint8_t *pBuf)
{
   struct DibBridgeMsgQueue *pMsg;
   uint32_t  MsgQueueAvail,  MsgSize;
   uint16_t  Nb;
   uint8_t  *pQueueAddr;
   DIBSTATUS rc = DIBSTATUS_ERROR;

   /** proper initialisation */
   *pSize = 0;

check_msg:

   /** safely access to the queue */
   DibAcquireLock(&pContext->MsgQueueLock);

   DIB_ASSERT(pContext->MsgQueueHead < UPMESSAGE_MAILBOX_SIZE);
   DIB_ASSERT(pContext->MsgQueueTail < UPMESSAGE_MAILBOX_SIZE);

   DIB_ASSERT((pContext->MsgQueueHead & 3) == 0);
   DIB_ASSERT((pContext->MsgQueueTail & 3) == 0);

   /** Check if message queue is empty. Warning: Bridge can be exiting, and several events can have been sent
    *  by the low level thread. If queue is empty, check first for message queue terminaison, otherwise wait for an event. */
   if(pContext->MsgQueueHead == pContext->MsgQueueTail) 
   {
      DibReleaseLock(&pContext->MsgQueueLock);

      /* Check for bridge terminaison */
      if(!pContext->MsgQueueInitialized) 
      {
         DIB_DEBUG(PORT_ERR, (CRB "DibBridgeGetBufFromMsgQueue: msg queue closed, exiting driver!" CRA));

         DibBridgeDeinitMsgQueue(pContext);

         return DIBSTATUS_ERROR;
      }

      /** wait for a message event */
      DIB_DEBUG(PORT_LOG, (CRB "DibBridgeGetBufFromMsgQueue: WaitForEvent...!" CRA));
      rc = DibWaitForEvent(&pContext->MsgQueueEvent, -1);
      DIB_DEBUG(PORT_LOG, (CRB "DibBridgeGetBufFromMsgQueue: ...WakeUp!" CRA));
      if(rc != DIBSTATUS_SUCCESS)
      {
         /* this should never occur, even when exiting sdk */
         DIB_DEBUG(PORT_ERR, (CRB "DibWaitForEvent failed !" CRA));
         return rc;
      }

      goto check_msg;
   }
   else
   {
      pQueueAddr = ((uint8_t *)pContext->MsgQueue + pContext->MsgQueueTail);

      DIB_DEBUG(PORT_LOG, (CRB "DibBridgeGetBufFromMsgQueue: ...Read one message!" CRA));
      /** extract message header */
      pMsg = (struct DibBridgeMsgQueue *)pQueueAddr;
      *pType = pMsg->Type;
      *pSize = Nb = pMsg->Size;
      MsgSize = DIB_BRIDGE_MESSAGE_SIZE(Nb);
      pQueueAddr += sizeof(struct DibBridgeMsgQueue);
      pContext->MsgQueueTail += sizeof(struct DibBridgeMsgQueue);

      /** wrap if needed after message header copy */
      if(pContext->MsgQueueTail >= UPMESSAGE_MAILBOX_SIZE)
      {
         pQueueAddr = (uint8_t *)pContext->MsgQueue;
         pContext->MsgQueueTail = 0;
      }

      /** check if a wrap is needed during buffer copy */
      if(Nb > 0)
      {
         /** get the number of free byte until the end of the buffer */
         MsgQueueAvail = UPMESSAGE_MAILBOX_SIZE - pContext->MsgQueueTail;

         DIB_ASSERT(MsgQueueAvail >= 4);

         if(Nb > MsgQueueAvail)
         {
            /** copy the first part */
            DibBridgeTargetCopyToUser(pBuf, pQueueAddr, MsgQueueAvail);

            /** copy the second part */
            pQueueAddr = (uint8_t *)pContext->MsgQueue;
            DibBridgeTargetCopyToUser(pBuf + MsgQueueAvail, pQueueAddr, Nb - MsgQueueAvail);
         }
         else
         {
            /** copy the whole block */
            DibBridgeTargetCopyToUser(pBuf, pQueueAddr, Nb);
         }
      }

      pContext->MsgQueueTail = (pContext->MsgQueueTail + MsgSize - sizeof(struct DibBridgeMsgQueue)) % (UPMESSAGE_MAILBOX_SIZE);

      /* Type if flagged with last bit set to 1 if queue becomes empty */
      if(pContext->MsgQueueHead == pContext->MsgQueueTail) *pType |= UPMESSAGE_BIT_EMPTY;

      DibReleaseLock(&pContext->MsgQueueLock);
   }

   return DIBSTATUS_SUCCESS;
}