/**************************************************************************** * 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; }
/**************************************************************************** * 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; }