//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtuEventsGetCancel -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. // // This functions cancels the DtuEventGetWait function if that function was waiting // for an event to happen // DtStatus DtuEventsGetCancel(DtuDeviceData* pDvcData, DtFileObject* pFile) { DtuEvents* pDtuEvents; if (pFile == NULL) return DT_STATUS_INVALID_PARAMETER; DtDbgOut(MAX, EVENTS, "Start"); // We force the Pending event to be signaled. pDtuEvents = DtuEventsGetEventsObject(pDvcData, pFile); if (pDtuEvents == NULL) { DtDbgOut(MAX, EVENTS, "Exit"); return DT_STATUS_NOT_FOUND; } pDtuEvents->m_CancelInProgress = TRUE; #ifdef WINBUILD // Dequeue pending events DtuEventsDequeue(pDvcData, pFile); #endif // Trigger event DtEventSet(&pDtuEvents->m_PendingEvent); // Decrement refcount DtuEventsUnrefEventsObject(pDvcData, pDtuEvents); DtDbgOut(MAX, EVENTS, "Exit"); return DT_STATUS_OK; }
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtaPPBufferReadDataFinished -.-.-.-.-.-.-.-.-.-.-.-.-.-.-. // void DtaPPBufferReadDataFinished(PPBuffer* pPPBuffer) { DtDbgOut(MAX, PP, "Start"); DT_ASSERT(pPPBuffer->m_pDmaChannel->m_DmaDirection == DT_DMA_DIRECTION_FROM_DEVICE); DtaPPBufferRWFinished(pPPBuffer); DtDbgOut(MAX, PP, "Exit"); }
//-.-.-.-.-.-.-.-.-.-.-.-.-.- DtaPPBufferTransferDataStartDma -.-.-.-.-.-.-.-.-.-.-.-.-.-. // static DtStatus DtaPPBufferTransferDataStartDma(PPBuffer* pPPBuffer, UInt BufferToTransfer) { DtStatus Status = DT_STATUS_OK; UInt TransferSize; UInt BufStart; UInt BufStop; UInt TransferSizeNew; UInt8* pLocalAddress; DtDbgOut(MAX, PP, "Start"); if (pPPBuffer->m_pDmaChannel->m_DmaDirection == DT_DMA_DIRECTION_TO_DEVICE) TransferSize = pPPBuffer->m_BufTransferSize[BufferToTransfer]; else TransferSize = pPPBuffer->m_BufSize[BufferToTransfer]; // Transfer buffer pPPBuffer->m_pGetLocAddrFunc(pPPBuffer->m_pGetLocAddrContext, &pLocalAddress, &BufStart, &BufStop, &TransferSizeNew); if (TransferSizeNew != 0) TransferSize = TransferSizeNew; Status = DtaDmaStartKernelBufTransfer(pPPBuffer->m_pDmaChannel, pPPBuffer->m_pBufStart,TransferSize, pPPBuffer->m_BufOffset[BufferToTransfer], pLocalAddress, BufStart, BufStop); DtDbgOut(MAX, PP, "Exit"); return Status; }
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtuDvcReset -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. // // Handler for reset device command // DtStatus DtuDvcReset(DtuDeviceData* pDvcData) { DtStatus Status = DT_STATUS_OK; Int Dummy; Int i=0; if (pDvcData->m_DevInfo.m_TypeNumber>=300 && pDvcData->m_DevInfo.m_TypeNumber<400) { DtDbgOut(ERR, DTU, "Attempt to reset USB3 device with USB2 command"); return DT_STATUS_NOT_SUPPORTED; } // Reset temporariy for all channels for (i=0; i<pDvcData->m_NumNonIpPorts; i++) { DtuNonIpPort* pNonIpPort = &(pDvcData->m_pNonIpPorts[i]); // Clear temporariy buffer pNonIpPort->m_TempBufWrIndex = 0; pNonIpPort->m_TempBufRdIndex = 0; } // Simply send the vendor command to the device Status = DtUsbVendorRequest(&pDvcData->m_Device, NULL, DTU_USB_RESET_DEVICE, 0, 0, DT_USB_HOST_TO_DEVICE, NULL, 0, &Dummy, MAX_USB_REQ_TIMEOUT); DtDbgOut(AVG, DTU, "DTU-%d reset", pDvcData->m_DevInfo.m_TypeNumber); return Status; }
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtaEventsSet -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // // This function adds new events to the pending events. // DtStatus DtaEventsSet( DtaDeviceData* pDvcData, DtFileObject* pFile, UInt EventType, UInt Value1, UInt Value2) { DtStatus Result = DT_STATUS_OK; DtaEvents* pDtaEvents = NULL; DtDbgOut(MAX, EVENTS, "Start"); DtDbgOut(AVG, EVENTS, "EventType: %i, Value1: %i, Value2: %i", EventType, Value1, Value2); if (pFile != NULL) { // Get corresponding events object pDtaEvents = DtaEventsGetEventsObject(pDvcData, pFile); if (pDtaEvents == NULL) Result = DT_STATUS_NOT_FOUND; else { Result = DtaEventsSetEvent(pDtaEvents, EventType, Value1, Value2); #ifdef WINBUILD if (pDtaEvents->m_NumPendingEvents != 0) { // Dequeue pending events pFile = &pDtaEvents->m_File; DtaEventsDequeue(pDvcData, pFile, pDtaEvents); } #endif DtaEventsUnrefEventsObject(pDvcData, pDtaEvents); } } else { // Set event for all file handles DtSpinLockAcquire(&pDvcData->m_EventsSpinlock); pDtaEvents = pDvcData->m_pEvents; while (pDtaEvents != NULL) { // Set event Result = DtaEventsSetEvent(pDtaEvents, EventType, Value1, Value2); #ifdef WINBUILD if (pDtaEvents->m_NumPendingEvents != 0) { // Dequeue pending events pFile = &pDtaEvents->m_File; DtaEventsDequeue(pDvcData, pFile, pDtaEvents); } #endif pDtaEvents = pDtaEvents->m_pNext; } DtSpinLockRelease(&pDvcData->m_EventsSpinlock); } DtDbgOut(MAX, EVENTS, "Exit"); return Result; }
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtuEventsSetEvent -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // static DtStatus DtuEventsSetEvent( DtuEvents* pDtuEvents, UInt EventType, UInt Value1, UInt Value2) { DtuEvent* pDtuEvent; // Skip unregistered events if ((EventType & pDtuEvents->m_EventTypeMask) != 0) { DtSpinLockAcquire(&pDtuEvents->m_Lock); if (EventType == DTU_EVENT_TYPE_IOCONFIG) { UInt i; for (i=0; i<pDtuEvents->m_NumPendingEvents; i++) { if (pDtuEvents->m_PendingEvents[i].m_EventType==DTU_EVENT_TYPE_IOCONFIG && pDtuEvents->m_PendingEvents[i].m_EventValue1==Value1) { // Event is already pending, don't create a duplicate DtSpinLockRelease(&pDtuEvents->m_Lock); return DT_STATUS_OK; } } } // Add new events if (pDtuEvents->m_NumPendingEvents == MAX_PENDING_EVENTS) { // Remove oldest event DtDbgOut(AVG, EVENTS, "Max. number of events. Remove old event"); DtMemMove(&pDtuEvents->m_PendingEvents[0], &pDtuEvents->m_PendingEvents[1], sizeof(DtuEvent) * (MAX_PENDING_EVENTS - 1)); pDtuEvent = &pDtuEvents->m_PendingEvents[MAX_PENDING_EVENTS - 1]; } else { pDtuEvent = &pDtuEvents->m_PendingEvents[pDtuEvents->m_NumPendingEvents]; pDtuEvents->m_NumPendingEvents++; } DtDbgOut(MAX, EVENTS, "New event #%d. Type: %d, Value1: %d, Value2: %d", pDtuEvents->m_NumPendingEvents, EventType, Value1, Value2); pDtuEvent->m_EventType = EventType; pDtuEvent->m_EventValue1 = Value1; pDtuEvent->m_EventValue2 = Value2; // Trigger wait function if it was waiting DtEventSet(&pDtuEvents->m_PendingEvent); DtSpinLockRelease(&pDtuEvents->m_Lock); } return DT_STATUS_OK; }
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- EzUsbLoadFirmware -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // DtStatus EzUsbLoadFirmware( DtuDeviceData* pDvcData, const DtuIntelHexRecord* pMicroCode) { DtStatus Status; Int Dummy = 0; DtuIntelHexRecord* pPtr = NULL; if (pMicroCode == NULL) return DT_STATUS_INVALID_PARAMETER; //.-.-.-.-.-.-.-.-.-.-.-.- Download firmware to internal RAM -.-.-.-.-.-.-.-.-.-.-.-.- // // Before starting the upload, stop the 8051 Status = EzUsbResetProcessor(pDvcData, TRUE); if (!DT_SUCCESS(Status)) { DtDbgOut(ERR, DTU, "Failed to stop the processor (Status=0x%08X)", Status); return Status; } pPtr = (DtuIntelHexRecord*)pMicroCode; while (pPtr->Type == 0) { // Send load command Status = DtUsbVendorRequest(&pDvcData->m_Device, NULL, EZUSB_FX2_LOAD_INTERNAL, pPtr->Address, 0, DT_USB_HOST_TO_DEVICE, pPtr->Data, pPtr->Length, &Dummy, MAX_USB_REQ_TIMEOUT); if (!DT_SUCCESS(Status)) { DtDbgOut(ERR, DTU, "Failed to send load command (Status=0x%08X)", Status); return Status; } pPtr++; } // Restart the 8051 if (Status == DT_STATUS_OK) { Status = EzUsbResetProcessor(pDvcData, FALSE); if (!DT_SUCCESS(Status)) { DtDbgOut(ERR, DTU, "Failed to start the processor (Status=0x%08X)", Status); return Status; } } return DT_STATUS_OK; }
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtaGs296xWriteRegister -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. // DtStatus DtaM235x4WriteRegister(DtaNonIpPort* pNonIpPort, Int Addr, UInt32 Value) { UInt Timeout=100, SpiCmd=0; // Port must has a matrix-API register interface if (!pNonIpPort->m_CapMatrix) return DT_STATUS_NOT_SUPPORTED; // Step 1: write write-command to card SpiCmd = (Value << DT_HD_SPICTRL_DATA_SH) & DT_HD_SPICTRL_DATA_MSK; SpiCmd |= (Addr << DT_HD_SPICTRL_ADDR_SH) & DT_HD_SPICTRL_ADDR_MSK; SpiCmd |= (0<<DT_HD_SPICTRL_AUTOINC_SH) & DT_HD_SPICTRL_AUTOINC_MSK; SpiCmd |= (0<<DT_HD_SPICTRL_READ_SH) & DT_HD_SPICTRL_READ_MSK; SpiCmd |= (1<<DT_HD_SPICTRL_START_SH) & DT_HD_SPICTRL_START_MSK; DtDbgOut(MAX, DTA, "Addr=0x%04X, Value=0x%04X, SpiCmd=0x%08X", Addr, Value, SpiCmd); WRITE_UINT(SpiCmd, pNonIpPort->m_pRxRegs, DT_HD_REG_SPICTRL); // Step 2: wait for done bit SpiCmd = READ_UINT(pNonIpPort->m_pRxRegs, DT_HD_REG_SPICTRL); while ((SpiCmd & DT_HD_SPICTRL_DONE_MSK) == 0) { DtSleep(1); SpiCmd = READ_UINT(pNonIpPort->m_pRxRegs, DT_HD_REG_SPICTRL); Timeout--; if (Timeout <= 0) return DT_STATUS_TIMEOUT; } return DT_STATUS_OK; }
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtaGenlockGetRefState -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // // Return lock status // DtStatus DtaGenlockGetRefState(DtaDeviceData* pDvcData, Int PortIndex, Int *pEnabled, Int *pInLock) { DtStatus Status = DT_STATUS_OK; #ifdef _DEBUG Int GenRefPortIndex = pDvcData->m_Genlock.m_RefPortIndex; #endif Bool InLock = FALSE; Bool Enabled = FALSE; if(pDvcData->m_Genlock.m_GenlArch == GENLOCK_ARCH_2144 || pDvcData->m_Genlock.m_GenlArch == GENLOCK_ARCH_145) { Status = DtaFpgaGenlockGetRefState(pDvcData, PortIndex, &Enabled, &InLock); *pEnabled = Enabled == TRUE ? 1 : 0; *pInLock = InLock == TRUE ? 1 : 0; return Status; } // TODO: Should we also implement this for HDSDI? //if(pDvcData->m_Genlock.m_GenlArch != GENLOCK_ARCH_2152) // return DtaLmh1982GenlockGetRefState(pDvcData, pInLock); DtDbgOut(ERR, GENL, "[%d] GENREF NOT SUPPORTED", GenRefPortIndex); return DT_STATUS_NOT_SUPPORTED; }
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtPropertiesInit -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // DtStatus DtPropertiesInit(DtPropertyData* pPropData) { Int Index; // Default no property store found for our device pPropData->m_pPropertyStore = NULL; // Find the property store for our device for (Index=0; Index<DtPropertyStoreCount; Index++) { if (DtPropertyStores[Index].m_TypeNumber==pPropData->m_TypeNumber && DtPropertyStores[Index].m_SubDvc == pPropData->m_SubDvc) { pPropData->m_pPropertyStore = (void*)&DtPropertyStores[Index]; break; } } // Check if we found a property store for our device if (pPropData->m_pPropertyStore == NULL) { DtDbgOut(ERR, PROP, "PropertyStore not found DTA %d, SubDvc %d", pPropData->m_TypeNumber, pPropData->m_SubDvc); return DT_STATUS_NOT_FOUND; } pPropData->m_PropertyNotFoundCounter = 0; return DtStringAlloc(&pPropData->m_PropertyNotFoundString, 50); }
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtTablesInit -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // DtStatus DtTablesInit(DtPropertyData* pPropData) { Int Index; // Default no table store found for our device pPropData->m_pTableStore = NULL; // Find the table store for our device for (Index=0; Index<DtTableStoreCount; Index++) { if (DtTableStores[Index].m_TypeNumber==pPropData->m_TypeNumber && DtTableStores[Index].m_SubDvc==pPropData->m_SubDvc) { pPropData->m_pTableStore = (void*)&DtTableStores[Index]; break; } } // It's not a fault if no table store is found. Not all cards have tables if (pPropData->m_pTableStore == NULL) DtDbgOut(MIN, TABLE, "Tablestore not found for %s-%d:%d", pPropData->m_TypeName, pPropData->m_TypeNumber, pPropData->m_SubDvc); return DT_STATUS_OK; }
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DriverParametersKeyDelete -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // NTSTATUS DriverParametersKeyDelete( WDFDRIVER Driver, DtString* pKeyName) { NTSTATUS NtStatus; WDFKEY ParametersKey; WDFKEY Key = NULL; DT_ASSERT(KeGetCurrentIrql()<=PASSIVE_LEVEL); // Open the drivers parameters key (under services) NtStatus = WdfDriverOpenParametersRegistryKey(Driver, KEY_WRITE, WDF_NO_OBJECT_ATTRIBUTES, &ParametersKey); if (!NT_SUCCESS(NtStatus)) { DtDbgOut(ERR, SAL, "WdfDriverOpenParametersRegistryKey failed. Error: 0x%x", NtStatus); return NtStatus; } // Open subkey NtStatus = WdfRegistryOpenKey(ParametersKey, pKeyName, KEY_WRITE, WDF_NO_OBJECT_ATTRIBUTES, &Key); if (!NT_SUCCESS(NtStatus)) { if (NtStatus == STATUS_OBJECT_NAME_NOT_FOUND) DtDbgOut(MAX, SAL, "WdfRegistryOpenKey error:'STATUS_OBJECT_NAME_NOT_FOUND'"); else DtDbgOut(ERR, SAL, "WdfRegistryOpenKey failed. Error: 0x%x", NtStatus); } if (NT_SUCCESS(NtStatus)) { // Delete the key NtStatus = WdfRegistryRemoveKey(Key); if (!NT_SUCCESS(NtStatus)) DtDbgOut(ERR, SAL, "WdfRegistryRemoveKey failed. Error: 0x%x", NtStatus); else Key = NULL; } if (Key != NULL) WdfRegistryClose(Key); WdfRegistryClose(ParametersKey); return NtStatus; }
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- EzUsbLoadFirmware -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // DtStatus EzUsbLoadFirmwareFx3( DtuDeviceData* pDvcData, const DtuFx3HexRecord* pMicroCode) { DtStatus Status; Int Dummy = 0; const DtuFx3HexRecord* pPtr = pMicroCode; Bool Cont = TRUE; if (pMicroCode == NULL) return DT_STATUS_INVALID_PARAMETER; DtDbgOut(MAX, DTU, "Loading firmware"); while (Cont) { UInt32 Len = pPtr->Length; UInt32 Addr = pPtr->Address; UInt8* Data = (UInt8*)(pPtr->Data); UInt32 NumToWrite; Cont = (pPtr->Length != 0); do { NumToWrite = Len < FX3_MAX_CHUNK_SIZE ? Len : FX3_MAX_CHUNK_SIZE; // Send load command Status = DtUsbVendorRequest(&pDvcData->m_Device, NULL, EZUSB_FX2_LOAD_INTERNAL, Addr&0xFFFF, Addr>>16, DT_USB_HOST_TO_DEVICE, Data, NumToWrite, &Dummy, MAX_USB_REQ_TIMEOUT); if (!DT_SUCCESS(Status)) { DtDbgOut(ERR, DTU, "Failed to send load command (Status=0x%08X)", Status); return Status; } Len -= NumToWrite; Addr += NumToWrite; Data += NumToWrite; } while (Len > 0); pPtr++; } return DT_STATUS_OK; }
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtaEventsSetEvent -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // static DtStatus DtaEventsSetEvent( DtaEvents* pDtaEvents, UInt EventType, UInt Value1, UInt Value2) { DtStatus Result = DT_STATUS_OK; DtaEvent* pDtaEvent; // Skip unregistered events if ((EventType & pDtaEvents->m_EventTypeMask) != 0) { DtSpinLockAcquire(&pDtaEvents->m_Lock); // Add new events if (pDtaEvents->m_NumPendingEvents == MAX_PENDING_EVENTS) { // Remove oldest event DtDbgOut(AVG, EVENTS, "Max. number of events. Remove old event"); DtMemMove(&pDtaEvents->m_PendingEvents[0], &pDtaEvents->m_PendingEvents[1], sizeof(DtaEvent) * (MAX_PENDING_EVENTS - 1)); pDtaEvent = &pDtaEvents->m_PendingEvents[MAX_PENDING_EVENTS - 1]; } else { pDtaEvent = &pDtaEvents->m_PendingEvents[pDtaEvents->m_NumPendingEvents]; pDtaEvents->m_NumPendingEvents++; } DtDbgOut(MAX, EVENTS, "New event #%d. Type: %d, Value1: %d, Value2: %d", pDtaEvents->m_NumPendingEvents, EventType, Value1, Value2); pDtaEvent->m_EventType = EventType; pDtaEvent->m_EventValue1 = Value1; pDtaEvent->m_EventValue2 = Value2; // Trigger wait function if it was waiting DtEventSet(&pDtaEvents->m_PendingEvent); DtSpinLockRelease(&pDtaEvents->m_Lock); } return Result; }
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtuDemodInit -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // DtStatus DtuDemodInit(DtuDeviceData* pDvcData) { DtStatus Status = DT_STATUS_OK; const DtuDemodFirmwareStore* pDemodFirmware = NULL; pDemodFirmware = DtuGetDemodFirmware(pDvcData->m_DevInfo.m_ProductId, pDvcData->m_DevInfo.m_HardwareRevision); if (pDemodFirmware == NULL) return DT_STATUS_OK; Status = DtuLoadDemodFirmware(pDvcData, pDemodFirmware); if (!DT_SUCCESS(Status)) { DtDbgOut(ERR, DTU, "Failed to upload demodulator firmware (Status=0x%08X)", Status); return Status; } DtDbgOut(AVG, DTU, "Demodulator firmware uploaded successfully"); return Status; }
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtuEventsNumPending -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. // Int DtuEventsNumPending(DtuDeviceData* pDvcData, DtFileObject* pFile) { DtuEvents* pDtuEvents; Int NumPending = 0; DtDbgOut(MAX, EVENTS, "Start"); // We force the Pending event to be signaled. pDtuEvents = DtuEventsGetEventsObject(pDvcData, pFile); if (pDtuEvents != NULL) { NumPending = pDtuEvents->m_NumPendingEvents; // Decrement refcount DtuEventsUnrefEventsObject(pDvcData, pDtuEvents); } DtDbgOut(MAX, EVENTS, "Exit (%d pending events)", NumPending); return NumPending; }
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtuDvcPowerSupplyInit -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // // Initializes the Altera power supply // DtStatus DtuDvcPowerSupplyInit(DtuDeviceData* pDvcData) { DtStatus Status = DT_STATUS_OK; UInt8 I2cBuf[8]; Int TypeNumber = pDvcData->m_DevInfo.m_TypeNumber; if (TypeNumber==215) { // Start 1V2 power supply (ALTERA core voltage) // NOTE: we only start the 1V2 power supply here. Other power supplies are started // later when we init the device hardware. I2cBuf[0] = DTU215_IIC_ADDR_PWR_1V2; I2cBuf[1] = DTU215_IIC_PWR_1V2_CTRL; Status = DtuI2cWrite(pDvcData, NULL, DTU215_IIC_ADDR_PWR_SUPPLY, 2, I2cBuf); // Sleep shortly to allow power-supply to settle DtSleep(200); if (DT_SUCCESS(Status)) DtDbgOut(AVG, DTU, "DTU-%d power supply started", TypeNumber); else DtDbgOut(ERR, DTU, "DTU-%d power supply start ERROR. Error: %xh", TypeNumber, Status); } else if ((TypeNumber==350 || TypeNumber==351) && pDvcData->m_DevInfo.m_UsbSpeed==2) { Status = DtUsbVendorRequest(&pDvcData->m_Device, NULL, DTU_USB3_PNP_CMD, DTU_PNP_CMD_DVC_POWER, DTU_DVC_POWER_ON, DT_USB_HOST_TO_DEVICE, NULL, 0, NULL, MAX_USB_REQ_TIMEOUT); if (DT_SUCCESS(Status)) DtSleep(100); } else if (TypeNumber==315 && pDvcData->m_DevInfo.m_UsbSpeed==2) { // DTU-315 specific: Enable LED (fade PWM mode) Dtu3RegWrite(pDvcData, DTU3_FX3_BLOCK_OFFSET, &FwbFx3.LedCtrl, 1); } return Status; }
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtaEventsRegister -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // DtStatus DtaEventsRegister( DtaDeviceData* pDvcData, DtFileObject* pFile, UInt EventTypeMask) { DtaEvents* pDtaEvents; if (pFile == NULL) return DT_STATUS_INVALID_PARAMETER; DtDbgOut(MAX, EVENTS, "Register event mask 0x%x", EventTypeMask); pDtaEvents = DtaEventsAllocEventsObject(pDvcData, pFile, EventTypeMask); if (pDtaEvents == NULL) return DT_STATUS_OUT_OF_RESOURCES; return DT_STATUS_OK; }
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtaPPBufferRWFinished -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // static void DtaPPBufferRWFinished(PPBuffer* pPPBuffer) { UInt OldState = pPPBuffer->m_BufState; UInt AddState; if (pPPBuffer->m_CurRwBufferId == DTA_PPBUF_PING_ID) AddState = DTA_PPBUF_STAT_PING; else AddState = DTA_PPBUF_STAT_PONG; DT_ASSERT((OldState & AddState) == 0); while (OldState != DtAtomicCompareExchange(&pPPBuffer->m_BufState, OldState, OldState | AddState)) { OldState = pPPBuffer->m_BufState; DT_ASSERT((OldState & AddState) == 0); } DtDbgOut(MAX, PP, "OldState: %xh NewState: %xh", OldState, OldState | AddState); DtaPPBufferSwap(&pPPBuffer->m_CurRwBufferId); }
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtaEventsAllocEventsObject -.-.-.-.-.-.-.-.-.-.-.-.-.-.-. // static DtaEvents* DtaEventsAllocEventsObject( DtaDeviceData* pDvcData, DtFileObject* pFileHandle, UInt EventTypeMask) { DtaEvents* pDtaEvents; pDtaEvents = (DtaEvents*)DtMemAllocPool(DtPoolNonPaged, sizeof(DtaEvents), DTA_TAG); if (pDtaEvents == NULL) { DtDbgOut(ERR, EVENTS, "Out of memory allocating DtaEvents struct"); return NULL; } DtAtomicSet(&pDtaEvents->m_RefCount, 1); pDtaEvents->m_File = *pFileHandle; pDtaEvents->m_EventTypeMask = EventTypeMask; pDtaEvents->m_CancelInProgress = FALSE; pDtaEvents->m_NumPendingEvents = 0; DtEventInit(&pDtaEvents->m_PendingEvent, FALSE); DtSpinLockInit(&pDtaEvents->m_Lock); memset(&pDtaEvents->m_PendingEvents, 0, sizeof(pDtaEvents->m_PendingEvents)); // Insert at start of list DtSpinLockAcquire(&pDvcData->m_EventsSpinlock); pDtaEvents->m_pPrev = NULL; pDtaEvents->m_pNext = NULL; if (pDvcData->m_pEvents != NULL) { pDtaEvents->m_pNext = pDvcData->m_pEvents; pDtaEvents->m_pNext->m_pPrev = pDtaEvents; } pDvcData->m_pEvents = pDtaEvents; DtSpinLockRelease(&pDvcData->m_EventsSpinlock); return pDtaEvents; }
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtuEventsSet -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // // This function adds new events to the pending events. If the Events argument is 0, // this function does nothing. // DtStatus DtuEventsSet( DtuDeviceData* pDvcData, DtFileObject* pFile, UInt EventType, UInt Value1, UInt Value2) { DtStatus Result = DT_STATUS_OK; Int i; DtuEvents* pDtuEvents = NULL; Bool InUse; DtDbgOut(MAX, EVENTS, "Start"); DtDbgOut(AVG, EVENTS, "EventType: %i, Value1: %i, Value2: %i", EventType, Value1, Value2); if (pFile != NULL) { // Get corresponding events object pDtuEvents = DtuEventsGetEventsObject(pDvcData, pFile); if (pDtuEvents == NULL) Result = DT_STATUS_NOT_FOUND; else { Result = DtuEventsSetEvent(pDtuEvents, EventType, Value1, Value2); #ifdef WINBUILD if (pDtuEvents->m_NumPendingEvents != 0) { // Dequeue pending events DtuEventsDequeue(pDvcData, pFile); } #endif DtuEventsUnrefEventsObject(pDvcData, pDtuEvents); } } else { // Set event for all file handles for (i=0; i<MAX_NUM_FILE_HANDLES; i++) { pDtuEvents = &pDvcData->m_Events[i]; // Increment refcount InUse = FALSE; DtSpinLockAcquire(&pDtuEvents->m_Lock); if (pDtuEvents->m_RefCount > 0) { pDtuEvents->m_RefCount++; InUse = TRUE; } DtSpinLockRelease(&pDtuEvents->m_Lock); if (InUse) { // Set event Result = DtuEventsSetEvent(pDtuEvents, EventType, Value1, Value2); #ifdef WINBUILD if (pDtuEvents->m_NumPendingEvents != 0) { // Dequeue pending events pFile = &pDtuEvents->m_File; DtuEventsDequeue(pDvcData, pFile); } #endif // Decrement refcount DtuEventsUnrefEventsObject(pDvcData, pDtuEvents); } } } DtDbgOut(MAX, EVENTS, "Exit"); return Result; }
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtPropertiesFind -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // DtStatus DtPropertiesFind(DtPropertyData* pPropData, const char* pName, Int PortIndex, const DtProperty** ppProperty, Int DtapiMaj, Int DtapiMin, Int DtapiBugfix) { DtStatus Status = DT_STATUS_OK; const DtPropertyStore* pStore = (DtPropertyStore*)pPropData->m_pPropertyStore; const DtPropertyHashSet* pHashSets = (DtPropertyHashSet*)pStore->m_pPropertyHashSets; UInt HashSetCount = pStore->m_PropertyHashSetCount; Int FwVersion = pPropData->m_FirmwareVersion; Int HwRevision = pPropData->m_HardwareRevision; Int FwVariant = pPropData->m_FirmwareVariant; UInt Hash = 0; Int Index; Int FindCount = 0; Bool PropertyNameFound = FALSE; const DtPropertyHashSet* pHashSet = NULL; Int PropertyCount = 0; *ppProperty = NULL; // For devices with no 'EC' VPD resource and no registry key which forces the // hardware revision, treat the hardware revision as 0 if (HwRevision < 0) HwRevision = 0; // Determine the name hash Hash = DtDjb2(pName) % HashSetCount; // Get correct hash set (if it exists) if (DT_SUCCESS(Status)) { pHashSet = &pHashSets[Hash]; PropertyCount = pHashSets[Hash].m_PropertyCount; // Check if a hash set was available for this hash value if (pHashSet == NULL) Status = DT_STATUS_NOT_FOUND; } if (DT_SUCCESS(Status)) { // If the property is not found for a specific fw-variant try a second time // without specifying a specific fw-variant for (FindCount=0; FindCount<2 && *ppProperty==NULL; FindCount++) { if (FindCount == 1) FwVariant = -1; // Get correct property entry within hash set PropertyNameFound = FALSE; // Search all properties for (Index=0; Index<PropertyCount; Index++) { const DtProperty* pProp = &pHashSet->m_pProperties[Index]; // Check the property name was already found if (PropertyNameFound) { // When the property name was found earlier, only accept entries // without a name. We just stop when (another) named entry is found. if (pProp->m_pName != NULL) break; } else { // Compare name to check if we found the first occurrence if (DtAnsiCharArrayIsEqual(pName, pProp->m_pName)) PropertyNameFound = TRUE; } if (PropertyNameFound) { // Check port number and firmware variant if (PortIndex==pProp->m_PortIndex && FwVariant==pProp->m_FwVariant) { // Check minimal firmware version and hardware version if (FwVersion>=pProp->m_MinFw && HwRevision>=pProp->m_MinHw && (pProp->m_MaxHw==-1 || HwRevision<pProp->m_MaxHw)) { Bool DtapiVerOk = FALSE; // -1 means the request came from the driver if (DtapiMaj==-1 && DtapiMin==-1 && DtapiBugfix==-1) DtapiVerOk = TRUE; else if (DtapiMaj > pProp->m_MinDtapiMaj) DtapiVerOk = TRUE; else if (DtapiMaj==pProp->m_MinDtapiMaj) { if (DtapiMin > pProp->m_MinDtapiMin) DtapiVerOk = TRUE; else if (DtapiMin==pProp->m_MinDtapiMin && DtapiBugfix>= pProp->m_MinDtapiBugfix) DtapiVerOk = TRUE; } // Check minimal DTAPI version if (DtapiVerOk) { *ppProperty = pProp; // We can stop here since the parser has ordered each // property by minimal firmware version/hardware version. // This means the first hit is the best one... break; } } } } } } if (!PropertyNameFound) { if (DtAnsiCharArrayStartsWith(pName, "CAP_")) DtDbgOut(AVG, PROP, "PropertyName(Capability) %s is not found at all for" " %s-%d", pName, pPropData->m_TypeName, pPropData->m_TypeNumber); else DtDbgOut(MIN, PROP, "PropertyName %s is not found at all for %s-%d", pName, pPropData->m_TypeName, pPropData->m_TypeNumber); } // Check if the property was found if (*ppProperty == NULL) { Status = DT_STATUS_NOT_FOUND; DtDbgOut(AVG, PROP, "Failed to find property %s for %s-%d, FW %d, HW %d" "VAR %d", pName, pPropData->m_TypeName, pPropData->m_TypeNumber, pPropData->m_FirmwareVersion, pPropData->m_HardwareRevision, pPropData->m_FirmwareVariant); } } return Status; }
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtTableGet -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. // DtStatus DtTableGet( DtPropertyData* pPropData, const char* pTableName, Int PortIndex, UInt MaxNumEntries, UInt* pNumEntries, DtTableEntry* pTableEntry2, UInt OutBufSize) { DtStatus Status = DT_STATUS_OK; const DtTableStore* pStore = (DtTableStore*)pPropData->m_pTableStore; Int HwRevision = pPropData->m_HardwareRevision; Int FwVariant = pPropData->m_FirmwareVariant; Bool TableNameFound = FALSE; Int FindCount = 0; UInt Index; DtTableLink* pTableLinkFound = NULL; // For devices with no 'EC' VPD resource and no registry key which forces the // hardware revision, treat the hardware revision as 0 if (HwRevision < 0) HwRevision = 0; *pNumEntries = 0; if (pPropData->m_pTableStore == NULL) { DtDbgOut(ERR, TABLE, "There are no tables defined at all for DTX-%d", pPropData->m_TypeNumber); return DT_STATUS_NOT_FOUND; } // If the property is not found for a specific fw-variant try a second time // without specifying a specific fw-variant for (FindCount=0; FindCount<2 && pTableLinkFound==NULL; FindCount++) { if (FindCount == 1) FwVariant = -1; TableNameFound = FALSE; // Search all tables for (Index=0; Index<pStore->m_TableLinkCount; Index++) { const DtTableLink* pTableLink = &pStore->m_pTableLink[Index]; // Check if the table name was already found. If so, we stop if // name <> NULL. if (TableNameFound) { // When the table name was found earlier, only accept entries without // a name. We just stop when (another) named entry is found. if (pTableLink->m_pName != NULL) break; } else { // Compare name to check if we found the first occurrence if (DtAnsiCharArrayIsEqual(pTableName, pTableLink->m_pName)) TableNameFound = TRUE; } if (TableNameFound) { // Check port number and firmware variant if (PortIndex==pTableLink->m_PortIndex && FwVariant==pTableLink->m_FwVariant) { // Check minimal firmware version if (pPropData->m_FirmwareVersion >= pTableLink->m_MinFw) { // Check minimal hardware version if (HwRevision >= pTableLink->m_MinHw) { pTableLinkFound = (DtTableLink*)pTableLink; // We can stop here since the parser has ordened each // property by minimal firmware version/hardware version. // This means the first hit is the best one break; } } } } } } if (!TableNameFound) { DtDbgOut(ERR, TABLE, "Table %s is not found at all for DTX-%d", pTableName, pStore->m_TypeNumber); Status = DT_STATUS_NOT_FOUND; } // Check if the table was found if (pTableLinkFound == NULL) { Status = DT_STATUS_NOT_FOUND; DtDbgOut(ERR, TABLE, "Failed to get table %s for DTX-%d:%d, FW %d, HW %d port %i", pTableName, pPropData->m_TypeNumber, pPropData->m_SubDvc, pPropData->m_FirmwareVersion, pPropData->m_HardwareRevision, PortIndex); } if (DT_SUCCESS(Status) && pTableLinkFound!=NULL) { DtDbgOut(MAX, TABLE, "Found table %s for DTX-%d:%d, FW %d, HW %d. #EL:%i #MAX:%i" , pTableName, pPropData->m_TypeNumber, pPropData->m_SubDvc, pPropData->m_FirmwareVersion, pPropData->m_HardwareRevision, pTableLinkFound->m_TableEntryCount, MaxNumEntries); *pNumEntries = pTableLinkFound->m_TableEntryCount; // Check if enough space for the table if (MaxNumEntries < pTableLinkFound->m_TableEntryCount) { if (MaxNumEntries != 0) DtDbgOut(ERR, TABLE, "Max. number of entries to small. Needed:%i, " "Space for:%i", pTableLinkFound->m_TableEntryCount, MaxNumEntries); } else if (OutBufSize < pTableLinkFound->m_TableEntryCount * sizeof(DtTableEntry)) { DtDbgOut(ERR, TABLE, "Buffer smaller than indicated by MaxNumEntries"); Status = DT_STATUS_INVALID_PARAMETER; } else { // Copy table DtMemCopy(pTableEntry2, (void*)pTableLinkFound->m_pTableEntries, pTableLinkFound->m_TableEntryCount * sizeof(DtTableEntry)); } } return Status; }
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtAvGetFrameProps -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // // Returns the AV frame properties for the given video standard // DtStatus DtAvGetFrameProps(Int VidStd, DtAvFrameProps* pProps) { DT_ASSERT(pProps != NULL); switch (VidStd) { case DT_VIDSTD_525I59_94: pProps->m_NumLines = 525; pProps->m_Fps = 30; pProps->m_IsFractional = TRUE; pProps->m_IsInterlaced = TRUE; pProps->m_IsHd = FALSE; pProps->m_Field1Start = 1; pProps->m_Field1End = 262; pProps->m_Field1ActVidStart = 17; pProps->m_Field1ActVidEnd = 260; pProps->m_SwitchingLines[0] = 7; pProps->m_Field2Start = 263; pProps->m_Field2End = 525; pProps->m_Field2ActVidStart = 280; pProps->m_Field2ActVidEnd = 522; pProps->m_SwitchingLines[1] = 270; pProps->m_VancNumS = pProps->m_ActVidNumS = 720*2; pProps->m_HancNumS = 268; pProps->m_SavNumS = 4; pProps->m_EavNumS = 4; pProps->m_SyncPointPixelOff = 16; // Sync point @pixel 16 break; case DT_VIDSTD_525P59_94: case DT_VIDSTD_480P59_94: pProps->m_NumLines = 525; pProps->m_Fps = 60; pProps->m_IsFractional = TRUE; pProps->m_IsInterlaced = FALSE; pProps->m_IsHd = FALSE; pProps->m_Field1Start = 1; pProps->m_Field1End = 525; pProps->m_Field1ActVidStart = 17; pProps->m_Field1ActVidEnd = 496; pProps->m_SwitchingLines[0] = 7; pProps->m_SwitchingLines[1] = -1; pProps->m_Field2Start = 0; pProps->m_Field2End = 0; pProps->m_Field2ActVidStart = 0; pProps->m_Field2ActVidEnd = 0; if (VidStd == DT_VIDSTD_480P59_94) pProps->m_VancNumS = pProps->m_ActVidNumS = 640*2; else pProps->m_VancNumS = pProps->m_ActVidNumS = 720*2; pProps->m_HancNumS = 268; pProps->m_SavNumS = 4; pProps->m_EavNumS = 4; pProps->m_SyncPointPixelOff = 0; break; case DT_VIDSTD_625I50: pProps->m_NumLines = 625; pProps->m_Fps = 25; pProps->m_IsFractional = FALSE; pProps->m_IsInterlaced = TRUE; pProps->m_IsHd = FALSE; pProps->m_Field1Start = 1; pProps->m_Field1End = 312; pProps->m_Field1ActVidStart = 23; pProps->m_Field1ActVidEnd = 310; pProps->m_SwitchingLines[0] = 6; pProps->m_Field2Start = 313; pProps->m_Field2End = 625; pProps->m_Field2ActVidStart = 336; pProps->m_Field2ActVidEnd = 623; pProps->m_SwitchingLines[1] = 319; pProps->m_VancNumS = pProps->m_ActVidNumS = 720*2; pProps->m_HancNumS = 280; pProps->m_SavNumS = 4; pProps->m_EavNumS = 4; pProps->m_SyncPointPixelOff = 12; // Sync point @pixel 12 break; case DT_VIDSTD_625P50: pProps->m_NumLines = 625; pProps->m_Fps = 50; pProps->m_IsFractional = FALSE; pProps->m_IsInterlaced = FALSE; pProps->m_IsHd = FALSE; pProps->m_Field1Start = 1; pProps->m_Field1End = 625; pProps->m_Field1ActVidStart = 23; pProps->m_Field1ActVidEnd = 598; pProps->m_SwitchingLines[0] = 6; pProps->m_SwitchingLines[1] = -1; pProps->m_Field2Start = 0; pProps->m_Field2End = 0; pProps->m_Field2ActVidStart = 0; pProps->m_Field2ActVidEnd = 0; pProps->m_VancNumS = pProps->m_ActVidNumS = 720*2; pProps->m_HancNumS = 280; pProps->m_SavNumS = 4; pProps->m_EavNumS = 4; pProps->m_SyncPointPixelOff = 0; break; case DT_VIDSTD_2160P60: case DT_VIDSTD_2160P60B: case DT_VIDSTD_2160P59_94: case DT_VIDSTD_2160P59_94B: case DT_VIDSTD_2160P50: case DT_VIDSTD_2160P50B: case DT_VIDSTD_1080P60: case DT_VIDSTD_1080P60B: case DT_VIDSTD_1080P59_94: case DT_VIDSTD_1080P59_94B: case DT_VIDSTD_1080P50: case DT_VIDSTD_1080P50B: pProps->m_NumLines = 1125; if (VidStd==DT_VIDSTD_1080P50 || VidStd==DT_VIDSTD_1080P50B || VidStd==DT_VIDSTD_2160P50 || VidStd==DT_VIDSTD_2160P50B) pProps->m_Fps = 50; else pProps->m_Fps = 60; pProps->m_IsFractional = (VidStd==DT_VIDSTD_1080P59_94 || VidStd==DT_VIDSTD_1080P59_94B || VidStd==DT_VIDSTD_2160P59_94 || VidStd==DT_VIDSTD_2160P59_94B); pProps->m_IsInterlaced = FALSE; pProps->m_IsHd = TRUE; pProps->m_Field1Start = 1; pProps->m_Field1End = 1125; pProps->m_Field1ActVidStart = 42; pProps->m_Field1ActVidEnd = 1121; pProps->m_SwitchingLines[0] = 7; pProps->m_SwitchingLines[1] = -1; pProps->m_Field2Start = 0; pProps->m_Field2End = 0; pProps->m_Field2ActVidStart = 0; pProps->m_Field2ActVidEnd = 0; pProps->m_VancNumS = pProps->m_ActVidNumS = 1920*2; if (VidStd==DT_VIDSTD_1080P60 || VidStd==DT_VIDSTD_1080P60B || VidStd==DT_VIDSTD_1080P59_94 || VidStd==DT_VIDSTD_1080P59_94B || VidStd==DT_VIDSTD_2160P60 || VidStd==DT_VIDSTD_2160P60B || VidStd==DT_VIDSTD_2160P59_94 || VidStd==DT_VIDSTD_2160P59_94B) { pProps->m_HancNumS = 268*2; // Set Sync point pProps->m_SyncPointPixelOff = 88; // Sync point @pixel 88 } else if (VidStd==DT_VIDSTD_1080P50 || VidStd==DT_VIDSTD_1080P50B || VidStd==DT_VIDSTD_2160P50 || VidStd==DT_VIDSTD_2160P50B) { pProps->m_HancNumS = 708*2; pProps->m_SyncPointPixelOff = 528; // Sync point @pixel 528 } else DT_ASSERT(1==0); pProps->m_EavNumS = 8*2; pProps->m_SavNumS = 4*2; break; case DT_VIDSTD_2160P30: case DT_VIDSTD_2160P29_97: case DT_VIDSTD_2160P25: case DT_VIDSTD_2160P24: case DT_VIDSTD_2160P23_98: case DT_VIDSTD_1080P30: case DT_VIDSTD_1080P29_97: case DT_VIDSTD_1080P25: case DT_VIDSTD_1080P24: case DT_VIDSTD_1080P23_98: pProps->m_NumLines = 1125; if (VidStd==DT_VIDSTD_1080P30 || VidStd==DT_VIDSTD_1080P29_97 || VidStd==DT_VIDSTD_2160P30 || VidStd==DT_VIDSTD_2160P29_97) pProps->m_Fps = 30; else if (VidStd==DT_VIDSTD_1080P25 || VidStd==DT_VIDSTD_2160P25) pProps->m_Fps = 25; else if (VidStd==DT_VIDSTD_1080P24 || VidStd==DT_VIDSTD_1080P23_98 || VidStd==DT_VIDSTD_2160P24 || VidStd==DT_VIDSTD_2160P23_98) pProps->m_Fps = 24; else DT_ASSERT(1==0); pProps->m_IsFractional = (VidStd==DT_VIDSTD_1080P29_97 || VidStd==DT_VIDSTD_1080P23_98 || VidStd==DT_VIDSTD_2160P29_97 || VidStd==DT_VIDSTD_2160P23_98); pProps->m_IsInterlaced = FALSE; pProps->m_IsHd = TRUE; pProps->m_Field1Start = 1; pProps->m_Field1End = 1125; pProps->m_Field1ActVidStart = 42; pProps->m_Field1ActVidEnd = 1121; pProps->m_SwitchingLines[0] = 7; pProps->m_Field2Start = 0; pProps->m_Field2End = 0; pProps->m_Field2ActVidStart = 0; pProps->m_Field2ActVidEnd = 0; pProps->m_SwitchingLines[1] = -1; pProps->m_VancNumS = pProps->m_ActVidNumS = 1920*2; if (VidStd==DT_VIDSTD_1080P30 || VidStd==DT_VIDSTD_1080P29_97 || VidStd==DT_VIDSTD_2160P30 || VidStd==DT_VIDSTD_2160P29_97) { pProps->m_HancNumS = 268*2; pProps->m_SyncPointPixelOff = 88; // Sync point @pixel 88 } else if (VidStd==DT_VIDSTD_1080P25 || VidStd==DT_VIDSTD_2160P25) { pProps->m_HancNumS = 708*2; pProps->m_SyncPointPixelOff = 528; // Sync point @pixel 528 } else if (VidStd==DT_VIDSTD_1080P24 || VidStd==DT_VIDSTD_1080P23_98 || VidStd==DT_VIDSTD_2160P24 || VidStd==DT_VIDSTD_2160P23_98) { pProps->m_HancNumS = 818*2; pProps->m_SyncPointPixelOff = 638; // Sync point @pixel 638 } else DT_ASSERT(1==0); pProps->m_EavNumS = 8*2; pProps->m_SavNumS = 4*2; break; case DT_VIDSTD_1080I60: case DT_VIDSTD_1080I59_94: case DT_VIDSTD_1080I50: case DT_VIDSTD_1080PSF30: case DT_VIDSTD_1080PSF29_97: case DT_VIDSTD_1080PSF25: case DT_VIDSTD_1080PSF24: case DT_VIDSTD_1080PSF23_98: pProps->m_NumLines = 1125; if (VidStd==DT_VIDSTD_1080I60 || VidStd==DT_VIDSTD_1080I59_94 || VidStd==DT_VIDSTD_1080PSF30 || VidStd==DT_VIDSTD_1080PSF29_97) pProps->m_Fps = 30; else if (VidStd==DT_VIDSTD_1080I50 || VidStd==DT_VIDSTD_1080PSF25) pProps->m_Fps = 25; else if (VidStd==DT_VIDSTD_1080PSF24 || VidStd==DT_VIDSTD_1080PSF23_98) pProps->m_Fps = 24; else DT_ASSERT(1==0); pProps->m_IsFractional = (VidStd==DT_VIDSTD_1080I59_94 || VidStd==DT_VIDSTD_1080PSF29_97 || VidStd==DT_VIDSTD_1080PSF23_98); pProps->m_IsInterlaced = TRUE; pProps->m_IsHd = TRUE; pProps->m_Field1Start = 1; pProps->m_Field1End = 563; pProps->m_Field1ActVidStart = 21; pProps->m_Field1ActVidEnd = 560; pProps->m_SwitchingLines[0] = 7; pProps->m_Field2Start = 564; pProps->m_Field2End = 1125; pProps->m_Field2ActVidStart = 584; pProps->m_Field2ActVidEnd = 1123; pProps->m_SwitchingLines[1] = 569; pProps->m_VancNumS = pProps->m_ActVidNumS = 1920*2; if (VidStd==DT_VIDSTD_1080I60 || VidStd==DT_VIDSTD_1080I59_94 || VidStd==DT_VIDSTD_1080PSF30 || VidStd==DT_VIDSTD_1080PSF29_97) { pProps->m_HancNumS = 268*2; pProps->m_SyncPointPixelOff = 88; // Sync point @pixel 88 } else if (VidStd==DT_VIDSTD_1080I50 || VidStd==DT_VIDSTD_1080PSF25) { pProps->m_HancNumS = 708*2; pProps->m_SyncPointPixelOff = 528; // Sync point @pixel 528 } else if (VidStd==DT_VIDSTD_1080PSF24 || VidStd==DT_VIDSTD_1080PSF23_98) { pProps->m_HancNumS = 818*2; pProps->m_SyncPointPixelOff = 638; // Sync point @pixel 638 } else DT_ASSERT(1==0); pProps->m_EavNumS = 8*2; pProps->m_SavNumS = 4*2; break; case DT_VIDSTD_720P60: case DT_VIDSTD_720P59_94: case DT_VIDSTD_720P50: case DT_VIDSTD_720P30: case DT_VIDSTD_720P29_97: case DT_VIDSTD_720P25: case DT_VIDSTD_720P24: case DT_VIDSTD_720P23_98: pProps->m_NumLines = 750; if (VidStd==DT_VIDSTD_720P60 || VidStd==DT_VIDSTD_720P59_94) pProps->m_Fps = 60; else if (VidStd==DT_VIDSTD_720P50) pProps->m_Fps = 50; else if (VidStd==DT_VIDSTD_720P30 || VidStd==DT_VIDSTD_720P29_97) pProps->m_Fps = 30; else if (VidStd==DT_VIDSTD_720P25) pProps->m_Fps = 25; else if (VidStd==DT_VIDSTD_720P24 || VidStd==DT_VIDSTD_720P23_98) pProps->m_Fps = 24; else DT_ASSERT(1==0); pProps->m_IsFractional = (VidStd==DT_VIDSTD_720P59_94 || VidStd==DT_VIDSTD_720P29_97 || VidStd==DT_VIDSTD_720P23_98); pProps->m_IsInterlaced = FALSE; pProps->m_IsHd = TRUE; pProps->m_Field1Start = 1; pProps->m_Field1End = 750; pProps->m_Field1ActVidStart = 26; pProps->m_Field1ActVidEnd = 745; pProps->m_SwitchingLines[0] = 7; pProps->m_Field2Start = 0; pProps->m_Field2End = 0; pProps->m_Field2ActVidStart = 0; pProps->m_Field2ActVidEnd = 0; pProps->m_SwitchingLines[1] = -1; pProps->m_VancNumS = pProps->m_ActVidNumS = 1280*2; if (VidStd==DT_VIDSTD_720P60 || VidStd==DT_VIDSTD_720P59_94) { pProps->m_HancNumS = 358*2; pProps->m_SyncPointPixelOff = 110; // Sync point @pixel 110 } else if (VidStd==DT_VIDSTD_720P50) { pProps->m_HancNumS = 688*2; pProps->m_SyncPointPixelOff = 440; // Sync point @pixel 440 } else if (VidStd==DT_VIDSTD_720P30 || VidStd==DT_VIDSTD_720P29_97) { pProps->m_HancNumS = 2008*2; pProps->m_SyncPointPixelOff = 1760; // Sync point @pixel 88 } else if (VidStd==DT_VIDSTD_720P25) { pProps->m_HancNumS = 2668*2; pProps->m_SyncPointPixelOff = 2420; // Sync point @pixel 88 } else if (VidStd==DT_VIDSTD_720P24 || VidStd==DT_VIDSTD_720P23_98) { pProps->m_HancNumS = 2833*2; pProps->m_SyncPointPixelOff = 2585; // Sync point @pixel 88 } else DT_ASSERT(1==0); pProps->m_EavNumS = 8*2; pProps->m_SavNumS = 4*2; break; default: DtDbgOut(ERR, AV, "Unknown IO-standard"); return DT_STATUS_INVALID_PARAMETER; } // Store the video video standard pProps->m_VidStd = VidStd; return DT_STATUS_OK; }
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtuEventsGet -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // // Return a pending event. This functions blocks if no events are pending. // DtStatus DtuEventsGet( DtuDeviceData* pDvcData, DtFileObject* pFile, UInt* pEventType, UInt* pValue1, UInt* pValue2, Bool Wait) { DtStatus Result = DT_STATUS_OK; DtuEvents* pDtuEvents; if (pFile==NULL || pEventType==NULL || pValue1==NULL || pValue2==NULL) return DT_STATUS_INVALID_PARAMETER; // Get corresponding events object pDtuEvents = DtuEventsGetEventsObject(pDvcData, pFile); if (pDtuEvents == NULL) Result = DT_STATUS_NOT_FOUND; if (DT_SUCCESS(Result)) { DtEventReset(&pDtuEvents->m_PendingEvent); if (Wait && pDtuEvents->m_NumPendingEvents==0 && !pDtuEvents->m_CancelInProgress) { DtDbgOut(MAX, EVENTS, "Waiting for event"); // Wait for event to be triggered DtEventWait(&pDtuEvents->m_PendingEvent, -1); } // The next request will be rejected by the IoCtl function, so we can reset // the Cancel state here. if (pDtuEvents->m_CancelInProgress) Result = DT_STATUS_CANCELLED; pDtuEvents->m_CancelInProgress = FALSE; DtSpinLockAcquire(&pDtuEvents->m_Lock); // Return pending events if (pDtuEvents->m_NumPendingEvents != 0) { *pEventType = pDtuEvents->m_PendingEvents[0].m_EventType; *pValue1 = pDtuEvents->m_PendingEvents[0].m_EventValue1; *pValue2 = pDtuEvents->m_PendingEvents[0].m_EventValue2; DtDbgOut(MAX, EVENTS, "Event #%d. Type: %d, Value1: %d, Value2: %d", pDtuEvents->m_NumPendingEvents, *pEventType, *pValue1, *pValue2); pDtuEvents->m_NumPendingEvents--; if (pDtuEvents->m_NumPendingEvents != 0) { // Remove the old event DtMemMove(&pDtuEvents->m_PendingEvents[0], &pDtuEvents->m_PendingEvents[1], sizeof(DtuEvent) * pDtuEvents->m_NumPendingEvents); } } else { *pEventType = 0; *pValue1 = 0; *pValue2 = 0; if (Result == DT_STATUS_OK) Result = DT_STATUS_REQUEUE; // No pending events DtDbgOut(MAX, EVENTS, "Event #%d. No event", pDtuEvents->m_NumPendingEvents); } DtSpinLockRelease(&pDtuEvents->m_Lock); // Decrement refcount DtuEventsUnrefEventsObject(pDvcData, pDtuEvents); } return Result; }
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- IoConfigCodesCodeGet -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // DtStatus IoConfigCodeGet( const char* pName, Int *pConfigCode) { DtStatus Status = DT_STATUS_OK; const IoConfigCodeHashSet* pHashSets = IoConfigCodeHashSets; UInt HashSetCount = IoConfigCodesHashCount; UInt Hash = 0; Int Index; Bool ConfigNameFound = FALSE; const IoConfigCodeHashSet* pHashSet = NULL; Int ConfigCount = 0; const IoConfigCode* pConfig = NULL; // Special case empty string if (pName[0] == '\0') { *pConfigCode = -1; return Status; } // Determine the name hash Hash = DtDjb2(pName) % HashSetCount; // Get correct hash set (if exists) if (DT_SUCCESS(Status)) { pHashSet = &pHashSets[Hash]; ConfigCount = pHashSets[Hash].m_ConfigCodeCount; // Check if a hash set was available for this hash value if (pHashSet == NULL) Status = DT_STATUS_NOT_FOUND; } // Get correct config entry within hash set if (DT_SUCCESS(Status)) { // Search all configs for (Index=0; Index<ConfigCount; Index++) { pConfig = &pHashSet->m_pConfigCodes[Index]; // Compare name to check if we found the first occurrence if (DtAnsiCharArrayIsEqual(pName, pConfig->m_pName)) { *pConfigCode = pConfig->m_Value; ConfigNameFound = TRUE; break; } } if (!ConfigNameFound) Status = DT_STATUS_NOT_FOUND; } if (!ConfigNameFound) DtDbgOut(ERR, PROP, "ConfigName %s is not found", pName); else DtDbgOut(MAX, PROP, "Found config code %d for %s", *pConfigCode, pName); return Status; }
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtaHdmiControllerThread -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. // void DtaHdmiControllerThread(DtThread* pThread, void* pContext) { DtStatus Status = DT_STATUS_OK; DtaNonIpPort* pNonIpPort = (DtaNonIpPort*)pContext; DtaHdmi* pHdmi = &pNonIpPort->m_HdmiRx; Bool ConfigForHd = TRUE; DtDbgOut(MAX, HDMI, "Thread begin"); DtaFwbRegWrite(pNonIpPort->m_pFwbRegs, &pHdmi->m_pFwbHdmiAdv7610Ctrl->Control_Reset, 1); DtSleep(5); DtaFwbRegWrite(pNonIpPort->m_pFwbRegs, &pHdmi->m_pFwbHdmiAdv7610Ctrl->Control_Reset, 0); DtSleep(10); // Disable VGA framing DtaFwbRegWrite(pNonIpPort->m_pFwbRegs, &pHdmi->m_pFwbHdmiAdv7610Ctrl->Control_VgaFraming, DTFWB_HDMI_NO_FRAMING); // Disable powerdown bit if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, IO_REG_0C, 0x42); DtSleep(10); if (Status != DT_STATUS_OK) { DtDbgOut(ERR, HDMI, "Failed to disable powerdown bit: 0x%X", Status); DtaFwbRegWrite(pNonIpPort->m_pFwbRegs, &pHdmi->m_pFwbHdmiAdv7610Ctrl->Control_Reset, 1); DtThreadWaitForStop(pThread); return; } // Initialize I2C addresses of other register pages if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, CEC_SLAVE_ADDRESS, ADV7610_I2CADDR_CEC); if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, INFOFRAME_SLAVE_ADDRESS, ADV7610_I2CADDR_INFOFRAME); if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, KSV_SLAVE_ADDRESS, ADV7610_I2CADDR_KSV); if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, EDID_SLAVE_ADDRESS, ADV7610_I2CADDR_EDID); if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, HDMI_SLAVE_ADDRESS, ADV7610_I2CADDR_HDMI); if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, CP_SLAVE_ADDRESS, ADV7610_I2CADDR_CP); if (Status != DT_STATUS_OK) DtDbgOut(ERR, HDMI, "Failed to set slave I2C addresses: 0x%X", Status); // Setting clock frequency to 27Mhz and pixel bus to mode 2 if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, IO_REG_04, 0x60); // color space settings if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, IO_REG_02, 0xF4); // set IO_REG_05 if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, IO_REG_05, 0x2C); // enabling output if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, IO_REG_15, 0xA8); // disable free run mode if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(CP, HDMI_CP_CNTRL_1, 0x00); // disable cable detect reset if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(HDMI, REGISTER_48, 0x40); // enable termination automatic control if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(HDMI, REGISTER_01, 0x01); // enable clock termination on port a if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(HDMI, REGISTER_02, 0xFE); // enable dynamic eq control if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(HDMI, EQ_DYNAMIC_ENABLE, 0x01); // Set bit width for right justified mode on I2S interface //if (Status == DT_STATUS_OK) // Status = ADV7610_WRITE_REG(HDMI, REGISTER_03, 0x10); // Disable "mute if compressed audio is detected" bit if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(HDMI, MUTE_MASK21_16, 0x1F); if (Status != DT_STATUS_OK) DtDbgOut(ERR, HDMI, "Failed to initialize general registers"); // Write EDID data if (Status == DT_STATUS_OK) { Int i; UInt8 Sum = 0; UInt8 Edid[257]; UInt32 Serial; Edid[0] = 0; // Address byte DtMemCopy(Edid+1, EDID_Block, sizeof(EDID_Block)); Serial = (UInt32)pNonIpPort->m_pDvcData->m_DevInfo.m_Serial; DtMemCopy(Edid+1+0x0C, &Serial, sizeof(Serial)); for (i=0; i<127; i++) Sum += Edid[i+1]; Edid[0x80] = (255 - Sum + 1); Status = DtaI2cmWrite(&pHdmi->m_I2c, ADV7610_I2CADDR_EDID, sizeof(Edid), Edid); } if (Status != DT_STATUS_OK) DtDbgOut(ERR, HDMI, "Write EDID failure"); // enable EDID for port a if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(KSV, HDCP_EDID_CONTROLS, 0x01); if (Status == DT_STATUS_OK) Status = DtaHdmiConfigForHd(pHdmi); ConfigForHd = TRUE; // Set interrupt signal duration to '11': Active until cleared // Set signal configuration '10': drives high when active if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, INT1_CONFIGURATION, 0xE2); // Enable cable detect / encrypted signal interrupts if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, HDMI_LVL_INT_MASKB4, 0x05); // Enable Video clock changed, Audio mode changed, new sample rate, // TMDS freq changed interrupts if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, HDMI_EDG_INT_MASKB3, 0x6A); // Enable TMDS-PLL locked, TMDS clock detect, Vertical sync lock, DE regeneration // lock interrupts if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, HDMI_LVL_INT_MASKB3, 0x53); // Enable NEW_AVI_INFO and NEW_AUDIO_INFO interrupts if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, HDMI_LVL_INT_MASKB1, 0x03); if (Status != DT_STATUS_OK) { DtDbgOut(ERR, HDMI, "HDMI initialization failed."); DtaFwbRegWrite(pNonIpPort->m_pFwbRegs, &pHdmi->m_pFwbHdmiAdv7610Ctrl->Control_Reset, 1); DtThreadWaitForStop(pThread); return; } DtDbgOut(AVG, HDMI, "HDMI initialization complete"); while (!pThread->m_StopThread) { UInt8 Value; DtaHdmiStatus NewStatus; Int NewVidStd = DT_VIDSTD_UNKNOWN; DtaHdmiClearStatus(&NewStatus); // Read/clear cable detect / encrypted signal interrupts Status = ADV7610_READ_REG(GENERAL, HDMI_LVL_INT_STATUS4, &Value); if (Status==DT_STATUS_OK && Value!=0) ADV7610_WRITE_REG(GENERAL, HDMI_LVL_INT_CLR4, Value&0x05); Status = ADV7610_READ_REG(GENERAL, HDMI_LVL_RAW_STATUS4, &Value); if (Status == DT_STATUS_OK) { NewStatus.m_CableDet = (Value&0x01)!=0; NewStatus.m_Encrypted = (Value&0x04)!=0; } // Read/clear TMDS-PLL locked, TMDS clock detect, Vertical sync lock, // DE regeneration lock interrupts Status = ADV7610_READ_REG(GENERAL, HDMI_LVL_INT_STATUS3, &Value); if (Status==DT_STATUS_OK && Value!=0) ADV7610_WRITE_REG(GENERAL, HDMI_LVL_INT_CLR3, Value); // Read/clear TMDS freq changed interrupt Status = ADV7610_READ_REG(GENERAL, HDMI_EDG_STATUS3, &Value); if (Status==DT_STATUS_OK && Value!=0) ADV7610_WRITE_REG(GENERAL, HDMI_EDG_INT_CLR3, Value); if (NewStatus.m_CableDet) { Status = ADV7610_READ_REG(HDMI, REGISTER_04, &Value); NewStatus.m_TmdsPllLocked = (Value&0x02)!=0; NewStatus.m_AudioLocked = (Value&0x01)!=0; } // Read/clear new audio info interrupt Status = ADV7610_READ_REG(GENERAL, HDMI_LVL_INT_STATUS1, &Value); if (Status==DT_STATUS_OK && Value!=0) ADV7610_WRITE_REG(GENERAL, HDMI_LVL_INT_CLR1, Value); if (NewStatus.m_TmdsPllLocked) { Status = ADV7610_READ_REG(HDMI, HDMI_COLORSPACE, &Value); NewStatus.m_InpColorspace = Value&0x0F; Status = ADV7610_READ_REG(HDMI, REGISTER_05, &Value); NewStatus.m_PixelRepetition = Value&0x0F; Status = ADV7610_READ_REG(HDMI, LINE_WIDTH1, &Value); NewStatus.m_VertFilterLocked = (Value&0x80)!=0; NewStatus.m_DeRegenFilterLocked = (Value&0x20)!=0; NewStatus.m_VidWidth = (Value&0x01F)<<8; Status = ADV7610_READ_REG(HDMI, LINE_WIDTH2, &Value); NewStatus.m_VidWidth |= Value; Status = ADV7610_READ_REG(HDMI, FIELD0_HEIGHT1, &Value); NewStatus.m_VidHeight1 = (Value&0x01F)<<8; Status = ADV7610_READ_REG(HDMI, FIELD0_HEIGHT2, &Value); NewStatus.m_VidHeight1 |= Value; Status = ADV7610_READ_REG(HDMI, REGISTER_51, &Value); NewStatus.m_TmdsFreq = Value<<8; Status = ADV7610_READ_REG(HDMI, REGISTER_52, &Value); NewStatus.m_TmdsFreq |= Value; Status = ADV7610_READ_REG(HDMI, FIELD1_HEIGHT1, &Value); switch (Value>>6) { case 0: NewStatus.m_BitsPerChannel = 8; break; case 1: NewStatus.m_BitsPerChannel = 10; break; case 2: NewStatus.m_BitsPerChannel = 12; break; case 3: NewStatus.m_BitsPerChannel = 16; break; } NewStatus.m_Interlaced = (Value&0x20)!=0; NewStatus.m_VidHeight2 = (Value&0x01F)<<8; Status = ADV7610_READ_REG(HDMI, FIELD1_HEIGHT2, &Value); NewStatus.m_VidHeight2 |= Value; Status = ADV7610_READ_REG(GENERAL, HDMI_LVL_RAW_STATUS2, &Value); NewStatus.m_AudioChanStatusValid = (Value&0x80)!=0; if (NewStatus.m_AudioChanStatusValid) { UInt8 RegAddr = ADV7610_HDMI_CHANNEL_STATUS_DATA_1; DtaI2cmWriteRead(&pHdmi->m_I2c, ADV7610_I2CADDR_HDMI, 1, &RegAddr, sizeof(NewStatus.m_AudioChannelStatus), NewStatus.m_AudioChannelStatus); } } if (NewStatus.m_AudioLocked) { Status = ADV7610_READ_REG(HDMI, LINE_WIDTH1, &Value); NewStatus.m_AudioChannelMode = (Value>>6)&1; Status = ADV7610_READ_REG(HDMI, PACKETS_DETECTED_2, &Value); if ((Value&0x01) != 0) NewStatus.m_AudioType = 0; else if ((Value&0x02) != 0) NewStatus.m_AudioType = 1; else if ((Value&0x04) != 0) NewStatus.m_AudioType = 2; else if ((Value&0x08) != 0) NewStatus.m_AudioType = 3; }
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtaNonIpTxIoctl -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. // DtStatus DtaNonIpTxIoctl( DtaDeviceData* pDvcData, DtFileObject* pFile, DtIoctlObject* pIoctl) { DtStatus Status = DT_STATUS_OK; char* pCmdStr; // Mnemonic string for Command UInt InReqSize = 0; // Required length of input buffer UInt OutReqSize = 0; // Required length of output buffer Int NonIpPortIndex; // Index in the nonip port struct DtaIoctlNonIpTxCmdInput* pNonIpTxCmdInput = (DtaIoctlNonIpTxCmdInput*)pIoctl->m_pInputBuffer; DtaIoctlNonIpTxCmdOutput* pNonIpTxCmdOutput = (DtaIoctlNonIpTxCmdOutput*)pIoctl->m_pOutputBuffer; // Default require at least the size of the header preceding the data InReqSize = OFFSETOF(DtaIoctlNonIpTxCmdInput, m_Data); OutReqSize = OFFSETOF(DtaIoctlNonIpTxCmdOutput, m_Data); // Check if we can read m_Cmd / m_PortIndex if (pIoctl->m_InputBufferSize < InReqSize) return DT_STATUS_INVALID_PARAMETER; // Validate port index if (!DT_SUCCESS(DtaGetNonIpPortIndex(pDvcData, pNonIpTxCmdInput->m_PortIndex, &NonIpPortIndex))) return DT_STATUS_INVALID_PARAMETER; // Determine final required output/input sizes switch (pNonIpTxCmdInput->m_Cmd) { case DTA_NONIP_TX_CMD_GET_FLAGS: pCmdStr = "DTA_NONIP_TX_CMD_GET_FLAGS"; OutReqSize += sizeof(DtaIoctlNonIpTxCmdGetFlagsOutput); // We expect no additional data in the input buffer InReqSize += 0; break; case DTA_NONIP_TX_CMD_CLEAR_FLAGS: pCmdStr = "DTA_NONIP_TX_CMD_CLEAR_FLAGS"; InReqSize += sizeof(DtaIoctlNonIpTxCmdClearFlagsInput); // We expect no output buffer at all OutReqSize = 0; break; case DTA_NONIP_TX_CMD_SET_FAILSAFE_CFG: pCmdStr = "DTA_NONIP_TX_CMD_SET_FAILSAFE_CFG"; InReqSize += sizeof(DtaIoctlNonIpTxCmdSetFailsafeCfgInput); // We expect no output buffer at all OutReqSize = 0; break; case DTA_NONIP_TX_CMD_SET_FAILSAFE_ALIVE: pCmdStr = "DTA_NONIP_TX_CMD_SET_FAILSAFE_ALIVE"; // We expect no additional data in the input buffer InReqSize += 0; // We expect no output buffer at all OutReqSize = 0; break; case DTA_NONIP_TX_CMD_GET_FAILSAFE_INFO: pCmdStr = "DTA_NONIP_TX_CMD_GET_FAILSAFE_INFO"; OutReqSize += sizeof(DtaIoctlNonIpTxCmdGetFailsafeInfoOutput); // We expect no additional data in the input buffer InReqSize += 0; break; default: pCmdStr = "??UNKNOWN VPDCMD CODE??"; Status = DT_STATUS_NOT_SUPPORTED; } if (DT_SUCCESS(Status)) { // Check buffer sizes if (pIoctl->m_InputBufferSize < InReqSize) { DtDbgOut(ERR, NONIP, "%s: INPUT BUFFER TOO SMALL Size=%d Req=%d", pCmdStr, pIoctl->m_InputBufferSize, InReqSize); return DT_STATUS_INVALID_PARAMETER; } if (pIoctl->m_OutputBufferSize < OutReqSize) { DtDbgOut(ERR, NONIP, "%s: OUTPUT BUFFER TOO SMALL Size=%d Req=%d", pCmdStr, pIoctl->m_OutputBufferSize, OutReqSize); return DT_STATUS_INVALID_PARAMETER; } DtDbgOut(MAX, NONIP, "%s: In=%d (Rq=%d), Out=%d (Rq=%d)", pCmdStr, pIoctl->m_InputBufferSize, InReqSize, pIoctl->m_OutputBufferSize, OutReqSize); } // The bytes written will be updated if needed. Set the default value here. pIoctl->m_OutputBufferBytesWritten = OutReqSize; if (DT_SUCCESS(Status)) { // Execute cmd switch (pNonIpTxCmdInput->m_Cmd) { case DTA_NONIP_TX_CMD_GET_FLAGS: Status = DtaNonIpTxGetFlags(&pDvcData->m_pNonIpPorts[NonIpPortIndex], &pNonIpTxCmdOutput->m_Data.m_GetFlags.m_Status, &pNonIpTxCmdOutput->m_Data.m_GetFlags.m_Latched); break; case DTA_NONIP_TX_CMD_CLEAR_FLAGS: Status = DtaNonIpTxClearFlags(&pDvcData->m_pNonIpPorts[NonIpPortIndex], pNonIpTxCmdInput->m_Data.m_ClearFlags.m_FlagsToClear); break; case DTA_NONIP_TX_CMD_SET_FAILSAFE_CFG: Status = DtaNonIpTxSetFailsafeCfg(&pDvcData->m_pNonIpPorts[NonIpPortIndex], pNonIpTxCmdInput->m_Data.m_SetFailsafeCfg.m_Enable, pNonIpTxCmdInput->m_Data.m_SetFailsafeCfg.m_Timeout); break; case DTA_NONIP_TX_CMD_SET_FAILSAFE_ALIVE: Status = DtaNonIpTxSetFailsafeAlive(&pDvcData->m_pNonIpPorts[NonIpPortIndex]); break; case DTA_NONIP_TX_CMD_GET_FAILSAFE_INFO: Status = DtaNonIpTxGetFailsafeInfo(&pDvcData->m_pNonIpPorts[NonIpPortIndex], &pNonIpTxCmdOutput->m_Data.m_GetFailsafeInfo.m_Enable, &pNonIpTxCmdOutput->m_Data.m_GetFailsafeInfo.m_Timeout, &pNonIpTxCmdOutput->m_Data.m_GetFailsafeInfo.m_Alive); break; default: Status = DT_STATUS_NOT_SUPPORTED; } } // If we failed, no data has te be copied to user space if (!DT_SUCCESS(Status)) { pIoctl->m_OutputBufferBytesWritten = 0; if (Status == DT_STATUS_NOT_SUPPORTED) DtDbgOut(MIN, NONIP, "NonIpTxCmd=0x%x: NOT SUPPORTED", pNonIpTxCmdInput->m_Cmd); else DtDbgOut(MIN, NONIP, "%s: ERROR %xh", pCmdStr, Status); } return Status; }
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- EzUsbInit -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // DtStatus EzUsbInit(DtuDeviceData* pDvcData, Bool* pReEnumerate) { DtStatus Status = DT_STATUS_OK; const DtuIntelHexRecord* pEzUsbFirmware = NULL; DtPropertyData* pPropData = &pDvcData->m_PropData; Bool IsEzUsbFwLoaded=FALSE, IsPldFwLoaded=FALSE; Int FirmwareEndpoint; Int ReadEndpoint; Int WriteEndpoint; // Initialize properties FirmwareEndpoint = DtPropertiesGetInt(pPropData, "USB_END_POINT_FIRMWARE", -1); ReadEndpoint = DtPropertiesGetInt(pPropData, "USB_END_POINT_READ", -1); WriteEndpoint = DtPropertiesGetInt(pPropData, "USB_END_POINT_WRITE", -1); // Check if no property error occurred Status = DtuPropertiesReportDriverErrors(pDvcData); if (!DT_SUCCESS(Status)) return Status; // Check if we need to load firmware. NOTE: there are two conditions to load the // firmware namely: // 1. EzUsb firmware is not loaded yet // 2. PLD firmware is loaded already, which suggest a warm-reboot which we want to // treat as a cold roboot => upload EzUsb firmware, but no re-enumeration *pReEnumerate = FALSE; IsEzUsbFwLoaded = EzUsbIsFirmwareLoaded(pDvcData); IsPldFwLoaded = FALSE; if (IsEzUsbFwLoaded && !(pDvcData->m_DevInfo.m_TypeNumber>=300 && pDvcData->m_DevInfo.m_TypeNumber<400)) IsPldFwLoaded = DtuPldIsFirmwareLoaded(pDvcData); if (!IsEzUsbFwLoaded || IsPldFwLoaded) { if (IsPldFwLoaded) DtDbgOut(MIN, DTU, "PLD FW is already loaded => warm reboot"); else DtDbgOut(MIN, DTU, "No EzUsb firmware loaded => cold reboot"); if (pDvcData->m_DevInfo.m_TypeNumber>=300 && pDvcData->m_DevInfo.m_TypeNumber<400) { // Lookup firmware const DtuFx3HexRecord* pFx3Firmware = Dtu3GetFx3Firmware( pDvcData->m_DevInfo.m_TypeNumber, -1, pDvcData->m_DevInfo.m_HardwareRevision); if (pFx3Firmware == NULL) DtDbgOut(ERR, DTU, "FX3 firmware not found for Typenumber: %d," " HardwareRev: 0x%X", pDvcData->m_DevInfo.m_TypeNumber, pDvcData->m_DevInfo.m_HardwareRevision); if (!DtUsbManufNameEq(&pDvcData->m_Device, "Cypress")) { DtDbgOut(ERR, DTU, "DTU-3XX vid/pid found but wrong manufacturer string"); return DT_STATUS_FAIL; } if (pDvcData->m_DevInfo.m_ProductId == DTU3_PID_UNIT_EEPROM) pDvcData->m_BootState = DTU_BOOTSTATE_FACTORY_COLD; else pDvcData->m_BootState = DTU_BOOTSTATE_COLD; //TODOTM: verify product string is "DTU-351" // Upload firmware for EzUsb chip Status = EzUsbLoadFirmwareFx3(pDvcData, pFx3Firmware); if (!DT_SUCCESS(Status)) { DtDbgOut(ERR, DTU, "Failed to upload FX3 firmware (Status=0x%08X)", Status); return Status; } DtDbgOut(ERR, DTU, "FX3 firmware uploaded"); } else { // Lookup firmware pEzUsbFirmware = DtuGetEzUsbFirmware(pDvcData->m_DevInfo.m_ProductId, -1, pDvcData->m_DevInfo.m_HardwareRevision); if (pEzUsbFirmware == NULL) { DtDbgOut(ERR, DTU, "No EzUsb firmware available for DTU-%d", pDvcData->m_DevInfo.m_TypeNumber); return DT_STATUS_FAIL; } // Upload firmware for EzUsb chip Status = EzUsbLoadFirmware(pDvcData, pEzUsbFirmware); if (!DT_SUCCESS(Status)) { DtDbgOut(ERR, DTU, "Failed to upload FX2 firmware (Status=0x%08X)", Status); return Status; } } *pReEnumerate = !IsPldFwLoaded; // Device will reenumerate, if cold reboot if (!IsPldFwLoaded) return DT_STATUS_OK; // In case of cold reboot we are done (will reenumerate) } // Convert endpoint to pipe numbers if (FirmwareEndpoint != -1) { // Convert endpoint to pipe number pDvcData->m_EzUsb.m_FirmwarePipe = DtUsbGetBulkPipeNumber(&pDvcData->m_Device, DT_USB_HOST_TO_DEVICE, FirmwareEndpoint); DT_ASSERT(pDvcData->m_EzUsb.m_FirmwarePipe != -1); } if (ReadEndpoint != -1) { // Convert endpoint to pipe number pDvcData->m_EzUsb.m_ReadPipe = DtUsbGetBulkPipeNumber(&pDvcData->m_Device, DT_USB_DEVICE_TO_HOST, ReadEndpoint); DT_ASSERT(pDvcData->m_EzUsb.m_ReadPipe != -1); } if (WriteEndpoint != -1) { // Convert endpoint to pipe number pDvcData->m_EzUsb.m_WritePipe = DtUsbGetBulkPipeNumber(&pDvcData->m_Device, DT_USB_HOST_TO_DEVICE, WriteEndpoint); DT_ASSERT(pDvcData->m_EzUsb.m_WritePipe != -1); } return Status; }
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtuLoadDemodFirmware -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // DtStatus DtuLoadDemodFirmware( DtuDeviceData* pDvcData, const DtuDemodFirmwareStore* pDemodFirmware) { DtStatus Status = DT_STATUS_OK; UInt8 Buffer[2]; Int i, j; UInt DvcAddr = pDemodFirmware->m_DemodI2cAddress; DT_ASSERT(pDemodFirmware != NULL); // First do the PRE-upload register writes if (pDemodFirmware->m_pPreUpload != NULL) { const DtuInitRegisterStruct* pInitRegisterData = pDemodFirmware->m_pPreUpload; for (i=0; i<pInitRegisterData->m_RegisterDataCount; i++) { Buffer[0] = pInitRegisterData->m_RegData[i].m_Data[0]; Buffer[1] = pInitRegisterData->m_RegData[i].m_Data[1]; Status = DtuI2cWrite(pDvcData, NULL, DvcAddr, 2, Buffer); if (!DT_SUCCESS(Status)) { DtDbgOut(ERR, DTU, "Error writing I2C pre-upload data. (Status=0x%08X)", Status); return Status; } } } // Upload demodulator firmware if (pDemodFirmware->m_pFirmware != NULL) { const Int MAX_BYTES_TO_TRY = 60; UInt8 AddrHigh; UInt8 AddrLow; Int DataCount; Int BytesToTry; const DtuHexStruct* pFirmware = pDemodFirmware->m_pFirmware; UInt8* pHexData=NULL; // First allocate memory for temporary helper buffer pHexData = DtMemAllocPool(DtPoolNonPaged, 4096, DTU_TAG); if (pHexData == NULL) return DT_STATUS_OUT_OF_MEMORY; for (i=0; i<pFirmware->m_HexBlockCount; i++) { const DtuHexBlockStruct* pHexBlock = &(pFirmware->m_HexBlock[i]); DataCount = pHexBlock->m_DataCount; BytesToTry = 0; while (DataCount > 0) { AddrHigh = (UInt8)((pHexBlock->m_Address + pHexBlock->m_DataCount-DataCount) >> 8); AddrLow = (UInt8)(pHexBlock->m_Address + pHexBlock->m_DataCount-DataCount); // Write high address Buffer[0] = (UInt8)pDemodFirmware->m_AddrRegH; Buffer[1] = AddrHigh; Status = DtuI2cWrite(pDvcData, NULL, DvcAddr, 2, Buffer); if (!DT_SUCCESS(Status)) { DtDbgOut(ERR, DTU, "Error writing I2C high address. (Status=0x%08X)", Status); DtMemFreePool(pHexData, DTU_TAG); return Status; } // Write low address Buffer[0] = (UInt8)pDemodFirmware->m_AddrRegL; Buffer[1] = AddrLow; Status = DtuI2cWrite(pDvcData, NULL, DvcAddr, 2, Buffer); if (!DT_SUCCESS(Status)) { DtDbgOut(ERR, DTU, "Error writing I2C low address. (Status=0x%08X)", Status); DtMemFreePool(pHexData, DTU_TAG); return Status; } // Write data pHexData[0] = (UInt8)pDemodFirmware->m_DataReg; BytesToTry = (DataCount<=MAX_BYTES_TO_TRY ? DataCount : MAX_BYTES_TO_TRY); for (j=0; j<BytesToTry; j++) pHexData[j + 1] = pHexBlock->m_Data[j + pHexBlock->m_DataCount - DataCount]; Status = DtuI2cWrite(pDvcData, NULL, DvcAddr, BytesToTry+1, pHexData); if (!DT_SUCCESS(Status)) { DtDbgOut(ERR, DTU, "Error writing I2C data. (Status=0x%08X)", Status); DtMemFreePool(pHexData, DTU_TAG); return Status; } DataCount -= BytesToTry; } } DtMemFreePool(pHexData, DTU_TAG); } // Do the STOP-upload register writes if (pDemodFirmware->m_pStopUpload != NULL) { const DtuInitRegisterStruct* pInitRegisterData = pDemodFirmware->m_pStopUpload; for (i=0; i<pInitRegisterData->m_RegisterDataCount; i++) { Buffer[0] = pInitRegisterData->m_RegData[i].m_Data[0]; Buffer[1] = pInitRegisterData->m_RegData[i].m_Data[1]; Status = DtuI2cWrite(pDvcData, NULL, DvcAddr, 2, Buffer); if (!DT_SUCCESS(Status)) { DtDbgOut(ERR, DTU, "Error writing I2C stop-upload data. (Status=0x%08X)", Status); return Status; } } } // Wait until AP is running if (pDemodFirmware->m_pFirmware != NULL) { Int TimeOut; Buffer[0] = (UInt8)pDemodFirmware->m_ApStatReg; Status = DtuI2cWrite(pDvcData, NULL, DvcAddr, 1, Buffer); if (!DT_SUCCESS(Status)) { DtDbgOut(ERR, DTU, "Error writing I2C apstat data. (Status=0x%08X)", Status); return Status; } // Wait until ready Buffer[0] = 1; TimeOut = 0; while (Buffer[0]==1 && TimeOut<250) // Wait max. 250ms { DtSleep(10); TimeOut += 10; // Read the app status Status = DtuI2cRead(pDvcData, NULL, DvcAddr, 1, Buffer); if (!DT_SUCCESS(Status)) { DtDbgOut(ERR, DTU, "Error reading I2C apstat data. (Status=0x%08X)", Status); return Status; } } if (Buffer[0] == 1) { DtDbgOut(ERR, DTU, "TIMEOUT! APSTAT = %x.", (Int)(Buffer[0])); } } //Do the post-upload register writes if (pDemodFirmware->m_pPostUpload != NULL) { const DtuInitRegisterStruct* pInitRegisterData = pDemodFirmware->m_pPostUpload; for (i=0; i<pInitRegisterData->m_RegisterDataCount; i++) { Buffer[0] = pInitRegisterData->m_RegData[i].m_Data[0]; Buffer[1] = pInitRegisterData->m_RegData[i].m_Data[1]; Status = DtuI2cWrite(pDvcData, NULL, DvcAddr, 2, Buffer); if (!DT_SUCCESS(Status)) { DtDbgOut(ERR, DTU, "Error writing I2C post-upload data. (Status=0x%08X)", Status); return Status; } } } return Status; }