//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtaUartIntDpc -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // void DtaUartIntDpc(DtDpcArgs* pArgs) { DtaUartPort* pUart = (DtaUartPort*)pArgs->m_pContext; UInt32 IntReason = pArgs->m_Data1.m_UInt32_1; // Check for TX interrupt if ((IntReason&DTA_UART_INT_TX_EMPTY)!=0 || (IntReason&DTA_UART_INT_TX_HALFEMPTY)!=0) DtEventSet(&pUart->m_TxEvent); // Check for RX interrupt if ((IntReason&DTA_UART_INT_RX_IDLE)!=0 || (IntReason&DTA_UART_INT_RX_HALFFULL)!=0) DtEventSet(&pUart->m_RxEvent); }
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- 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; }
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- 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; }
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- 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; }
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtuShBufferIoctl -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // DtStatus DtuShBufferIoctl( DtuDeviceData* pDvcData, DtFileObject* pFile, DtIoctlObject* pIoctl) { DtStatus Status = DT_STATUS_OK; char* pIoctlStr; // Mnemonic string for Command UInt InReqSize = 0; // Required length of input buffer UInt OutReqSize = 0; // Required length of output buffer Int Index; DtuShBuffer* pShBuffer = NULL; DtuIoctlShBufCmdInput* pShBufCmdInput = (DtuIoctlShBufCmdInput*)pIoctl->m_pInputBuffer; InReqSize = OFFSETOF(DtuIoctlShBufCmdInput, m_Data); // Check if we can read m_Cmd if (pIoctl->m_InputBufferSize < OFFSETOF(DtuIoctlShBufCmdInput, m_Data)) return DT_STATUS_INVALID_PARAMETER; switch (pShBufCmdInput->m_Cmd) { case DTU_SH_BUF_CMD_INIT: pIoctlStr = "DTU_SH_BUF_CMD_INIT"; InReqSize += sizeof(DtuIoctlShBufCmdInitInput); // We expect an output buffer size, but will be checked later OutReqSize = 0; break; case DTU_SH_BUF_CMD_CLOSE: pIoctlStr = "DTU_HP_BUF_CMD_CLOSE"; // We expect no output buffer OutReqSize = 0; break; default: pIoctlStr = "??UNKNOWN VPDCMD CODE??"; Status = DT_STATUS_NOT_SUPPORTED; } if (DT_SUCCESS(Status)) { // Check buffer sizes if (pIoctl->m_InputBufferSize < InReqSize) { DtDbgOut(ERR, SHBUF, "%s: INPUT BUFFER TOO SMALL Size=%d Req=%d", pIoctlStr, pIoctl->m_InputBufferSize, InReqSize); return DT_STATUS_INVALID_PARAMETER; } if (pIoctl->m_OutputBufferSize < OutReqSize) { DtDbgOut(ERR, SHBUF, "%s: OUTPUT BUFFER TOO SMALL Size=%d Req=%d", pIoctlStr, pIoctl->m_OutputBufferSize, OutReqSize); return DT_STATUS_INVALID_PARAMETER; } DtDbgOut(MAX, SHBUF, "%s: In=%d (Rq=%d), Out=%d (Rq=%d)", pIoctlStr, pIoctl->m_InputBufferSize, InReqSize, pIoctl->m_OutputBufferSize, OutReqSize); } if (pShBufCmdInput->m_BufferIndex != 0) { DtDbgOut(ERR, SHBUF, "%s: OUTPUT BUFFER TOO SMALL Size=%d Req=%d", pIoctlStr, pIoctl->m_OutputBufferSize, OutReqSize); return DT_STATUS_INVALID_PARAMETER; } // The bytes written will be updated if needed. Set the default value here. pIoctl->m_OutputBufferBytesWritten = OutReqSize; // Lookup the shared buffer structure // Check if the PortIndex is from the NonIpPort Status = DtuGetNonIpPortIndex(pDvcData, pShBufCmdInput->m_PortIndex, &Index); if (!DT_SUCCESS(Status)) return DT_STATUS_NOT_FOUND; pShBuffer = &pDvcData->m_pNonIpPorts[Index].m_SharedBuffer; if (DT_SUCCESS(Status)) { switch (pShBufCmdInput->m_Cmd) { case DTU_SH_BUF_CMD_INIT: { char* pBuffer; UInt Size; DtPageList* pPageList = NULL; #if defined(WINBUILD) DtPageList PageList; PMDL pMdl; NTSTATUS NtStatus; // Retrieve MDL and virtual buffer from request object NtStatus = WdfRequestRetrieveOutputWdmMdl(pIoctl->m_WdfRequest, &pMdl); if (NtStatus != STATUS_SUCCESS) { DtDbgOut(ERR, SHBUF, "WdfRequestRetrieveOutputWdmMdl error: %08x", NtStatus); Status = DT_STATUS_OUT_OF_RESOURCES; } if (DT_SUCCESS(Status)) { pBuffer = MmGetMdlVirtualAddress(pMdl); if (pBuffer == NULL) { DtDbgOut(ERR, SHBUF, "DTU_SH_BUF_CMD_INIT: DT_STATUS_OUT_OF_MEMORY"); Status = DT_STATUS_OUT_OF_MEMORY; } Size = MmGetMdlByteCount(pMdl); // Build pagelist object for user space buffer pPageList = &PageList; pPageList->m_BufType = DT_BUFTYPE_USER; pPageList->m_OwnedByOs = TRUE; pPageList->m_pMdl = pMdl; pPageList->m_pVirtualKernel = NULL; } #else // LINBUILD Size = (UInt)pShBufCmdInput->m_Data.m_Init.m_BufferSize; #if defined(LIN32) pBuffer = (char*)(UInt32)pShBufCmdInput->m_Data.m_Init.m_BufferAddr; #else pBuffer = (char*)(UInt64)pShBufCmdInput->m_Data.m_Init.m_BufferAddr; #endif #endif if (DT_SUCCESS(Status)) { Status = DtuShBufferInit(pShBufCmdInput, pFile, pPageList, pBuffer, Size, DT_BUFTYPE_USER, pShBuffer); if (!DT_SUCCESS(Status)) DtDbgOut(ERR, SHBUF, "DtuShBufferInit failed"); } } break; case DTU_SH_BUF_CMD_CLOSE: if (pDvcData->m_pNonIpPorts!=NULL && pDvcData->m_pNonIpPorts[0].m_State==DTU3_STATE_READ351) { pDvcData->m_pNonIpPorts[0].m_NextState = DTU3_STATE_DET_VIDSTD; DtEventSet(&pDvcData->m_pNonIpPorts[0].m_StateChanged); DtEventWait(&pDvcData->m_pNonIpPorts[0].m_StateChangeCmpl, -1); } else if (pDvcData->m_pNonIpPorts!=NULL && pDvcData->m_pNonIpPorts[0].m_State==DTU3_STATE_WRITE315) { pDvcData->m_pNonIpPorts[0].m_NextState = DTU3_STATE_IDLE; DtEventSet(&pDvcData->m_pNonIpPorts[0].m_StateChanged); DtEventWait(&pDvcData->m_pNonIpPorts[0].m_StateChangeCmpl, -1); } Status = DtuShBufferClose(pShBuffer); 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, SHBUF, "ShBufCmd=0x%x: NOT SUPPORTED", pShBufCmdInput->m_Cmd); } return Status; }