// // Internal Function: UartCtlSetFifoControl // VOID UartCtlSetFifoControl( _In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength ) { NTSTATUS status = STATUS_UNSUCCESSFUL; PUART_DEVICE_EXTENSION pDevExt = UartGetDeviceExtension(Device); UCHAR fifoControlRegister = 0; UCHAR fifoControlRegisterSaved = 0; PUCHAR pFifoControl = NULL; UNREFERENCED_PARAMETER(OutputBufferLength); UNREFERENCED_PARAMETER(InputBufferLength); FuncEntry(TRACE_FLAG_CONTROL); status = WdfRequestRetrieveInputBuffer(Request, sizeof(UCHAR), (PVOID*)(& pFifoControl), NULL); if (!NT_SUCCESS(status)) { TraceMessage( TRACE_LEVEL_ERROR, TRACE_FLAG_CONTROL, "Failed to retrieve input buffer for WDFREQUEST %p - " "%!STATUS!", Request, status); } if (NT_SUCCESS(status)) { // This value is not verified. This is as specified in the documentation. fifoControlRegister = *pFifoControl; // Save the value of the FCR to be written, with the reset bits unset. fifoControlRegisterSaved = fifoControlRegister & (~(SERIAL_FCR_RCVR_RESET | SERIAL_FCR_TXMT_RESET)); // Acquires the interrupt lock and writes the FCR. WdfInterruptAcquireLock(pDevExt->WdfInterrupt); WRITE_FIFO_CONTROL(pDevExt, pDevExt->Controller, fifoControlRegister); pDevExt->FifoControl = fifoControlRegisterSaved; WdfInterruptReleaseLock(pDevExt->WdfInterrupt); } TraceMessage(TRACE_LEVEL_INFORMATION, TRACE_FLAG_CONTROL, "WdfRequestComplete( %!HANDLE! => %!STATUS! )", Request, status); WdfRequestComplete(Request, status); FuncExit(TRACE_FLAG_CONTROL); }
/*++ Routine Description: DPC callback for ISR. Please note that on a multiprocessor system, you could have more than one DPCs running simulataneously on multiple processors. So if you are accesing any global resources make sure to synchrnonize the accesses with a spinlock. Arguments: Interupt - Handle to WDFINTERRUPT Object for this device. Device - WDFDEVICE object passed to InterruptCreate Return Value: --*/ VOID PCIEEvtInterruptDpc(IN WDFINTERRUPT Interrupt,IN WDFDEVICE Device) { NTSTATUS Status; PDEVICE_EXTENSION pDevExt; BOOLEAN fTxInterrupt = FALSE; BOOLEAN fRxInterrupt = FALSE; UNREFERENCED_PARAMETER(Device); pDevExt = PCIEGetDeviceContext(WdfInterruptGetDevice(Interrupt)); do { // // Acquire this device's InterruptSpinLock. // WdfInterruptAcquireLock( Interrupt ); WdfInterruptReleaseLock( Interrupt ); }while (FALSE); return; }
// // Internal Function: UartCtlClearStats // VOID UartCtlClearStats( _In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength ) { NTSTATUS status = STATUS_SUCCESS; PUART_DEVICE_EXTENSION pDevExt = UartGetDeviceExtension(Device); UNREFERENCED_PARAMETER(OutputBufferLength); UNREFERENCED_PARAMETER(InputBufferLength); FuncEntry(TRACE_FLAG_CONTROL); WdfInterruptAcquireLock(pDevExt->WdfInterrupt); RtlZeroMemory(&pDevExt->PerfStats, sizeof(SERIALPERF_STATS)); WdfInterruptReleaseLock(pDevExt->WdfInterrupt); TraceMessage(TRACE_LEVEL_INFORMATION, TRACE_FLAG_CONTROL, "WdfRequestComplete( %!HANDLE! => %!STATUS! )", Request, status); WdfRequestComplete(Request, status); FuncExit(TRACE_FLAG_CONTROL); }
BOOLEAN DeviceInterrupt_EvtAttachDetachInterruptIsr ( _In_ WDFINTERRUPT Interrupt, _In_ ULONG MessageID ) /*++ Routine Description: 'EvtInterruptIsr' handler for the attach/detach interrupt object. http://msdn.microsoft.com/en-us/library/windows/hardware/ff541735(v=vs.85).aspx Arguments: Interrupt - Associated interrupt object. MessageID - Message IDs for MSI Return Value: BOOLEAN --*/ { PCONTROLLER_CONTEXT ControllerContext; UNREFERENCED_PARAMETER(MessageID); TraceEntry(); ControllerContext = DeviceGetControllerContext(WdfInterruptGetDevice(Interrupt)); WdfInterruptAcquireLock(ControllerContext->DeviceInterrupt); // // This is an ActiveBoth interrupt used for attach/detach. State is determined // by counting interrupts. Previous state was attached, so this is a detach. // if (!ControllerContext->Attached) { ControllerContext->Attached = TRUE; ControllerContext->GotAttachOrDetach = TRUE; (void) WdfInterruptQueueDpcForIsr(Interrupt); } else { ControllerContext->Attached = FALSE; ControllerContext->GotAttachOrDetach = TRUE; (void) WdfInterruptQueueDpcForIsr(Interrupt); } WdfInterruptReleaseLock(ControllerContext->DeviceInterrupt); TraceExit(); return TRUE; }
// // Internal Function: UartCtlGetModemControl // VOID UartCtlGetModemControl( _In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength ) { NTSTATUS status; PUART_DEVICE_EXTENSION pDevExt = UartGetDeviceExtension(Device); PULONG pBuffer; UNREFERENCED_PARAMETER(OutputBufferLength); UNREFERENCED_PARAMETER(InputBufferLength); FuncEntry(TRACE_FLAG_CONTROL); status = WdfRequestRetrieveOutputBuffer(Request, sizeof(ULONG), (PVOID*)(&pBuffer), NULL); if (!NT_SUCCESS(status)) { TraceMessage( TRACE_LEVEL_ERROR, TRACE_FLAG_CONTROL, "Failed to retrieve output buffer for WDFREQUEST %p - " "%!STATUS!", Request, status); } if (NT_SUCCESS(status)) { // Acquires the interrupt lock and reads the modem control register. WdfInterruptAcquireLock(pDevExt->WdfInterrupt); *pBuffer = READ_MODEM_CONTROL(pDevExt, pDevExt->Controller); WdfInterruptReleaseLock(pDevExt->WdfInterrupt); WdfRequestSetInformation(Request, sizeof(ULONG)); } TraceMessage(TRACE_LEVEL_INFORMATION, TRACE_FLAG_CONTROL, "WdfRequestComplete( %!HANDLE! => %!STATUS! )", Request, status); WdfRequestComplete(Request, status); FuncExit(TRACE_FLAG_CONTROL); }
// // Internal Function: UartCtlGetBaudRate // VOID UartCtlGetBaudRate( _In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength ) { NTSTATUS status = STATUS_UNSUCCESSFUL; PUART_DEVICE_EXTENSION pDevExt = UartGetDeviceExtension(Device); PSERIAL_BAUD_RATE pBaudRate = NULL; UNREFERENCED_PARAMETER(OutputBufferLength); UNREFERENCED_PARAMETER(InputBufferLength); FuncEntry(TRACE_FLAG_CONTROL); status = WdfRequestRetrieveOutputBuffer(Request, sizeof(SERIAL_BAUD_RATE), (PVOID*)(& pBaudRate), NULL); if (!NT_SUCCESS(status)) { TraceMessage( TRACE_LEVEL_ERROR, TRACE_FLAG_CONTROL, "Failed to retrieve output buffer for WDFREQUEST %p - " "%!STATUS!", Request, status); } if (NT_SUCCESS(status)) { // Acquires the interrupt lock and retrieves the current baud rate. WdfInterruptAcquireLock(pDevExt->WdfInterrupt); pBaudRate->BaudRate = pDevExt->CurrentBaud; WdfInterruptReleaseLock(pDevExt->WdfInterrupt); WdfRequestSetInformation(Request, sizeof(SERIAL_BAUD_RATE)); } TraceMessage(TRACE_LEVEL_INFORMATION, TRACE_FLAG_CONTROL, "WdfRequestComplete( %!HANDLE! => %!STATUS! )", Request, status); WdfRequestComplete(Request, status); FuncExit(TRACE_FLAG_CONTROL); }
// // Internal Function: UartCtlGetStats // VOID UartCtlGetStats( _In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength ) { NTSTATUS status; PUART_DEVICE_EXTENSION pDevExt = UartGetDeviceExtension(Device); PSERIALPERF_STATS pStats = NULL; UNREFERENCED_PARAMETER(OutputBufferLength); UNREFERENCED_PARAMETER(InputBufferLength); FuncEntry(TRACE_FLAG_CONTROL); status = WdfRequestRetrieveOutputBuffer(Request, sizeof(SERIALPERF_STATS), (PVOID*)(& pStats), NULL); if (!NT_SUCCESS(status)) { TraceMessage( TRACE_LEVEL_ERROR, TRACE_FLAG_CONTROL, "Failed to retrieve output buffer for WDFREQUEST %p - " "%!STATUS!", Request, status); } if (NT_SUCCESS(status)) { WdfInterruptAcquireLock(pDevExt->WdfInterrupt); *pStats = pDevExt->PerfStats; WdfInterruptReleaseLock(pDevExt->WdfInterrupt); WdfRequestSetInformation(Request, sizeof(SERIALPERF_STATS)); } TraceMessage(TRACE_LEVEL_INFORMATION, TRACE_FLAG_CONTROL, "WdfRequestComplete( %!HANDLE! => %!STATUS! )", Request, status); WdfRequestComplete(Request, status); FuncExit(TRACE_FLAG_CONTROL); }
// // Internal Function: UartCtlClrRts // VOID UartCtlClrRts( _In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength ) { PUART_DEVICE_EXTENSION pDevExt = UartGetDeviceExtension(Device); UCHAR regModemControl; NTSTATUS status = STATUS_SUCCESS; UNREFERENCED_PARAMETER(OutputBufferLength); UNREFERENCED_PARAMETER(InputBufferLength); FuncEntry(TRACE_FLAG_CONTROL); if (((pDevExt->HandFlow.FlowReplace & SERIAL_RTS_MASK) == SERIAL_RTS_HANDSHAKE) || ((pDevExt->HandFlow.FlowReplace & SERIAL_RTS_MASK) == SERIAL_TRANSMIT_TOGGLE)) { status = STATUS_INVALID_PARAMETER; TraceMessage( TRACE_LEVEL_ERROR, TRACE_FLAG_CONTROL, "RTS cannot be cleared when automatic RTS flow control or " "transmit toggling is used - %!STATUS!", status); } if (NT_SUCCESS(status)) { // Acquires the interrupt lock and sets the MCR. WdfInterruptAcquireLock(pDevExt->WdfInterrupt); regModemControl = READ_MODEM_CONTROL(pDevExt, pDevExt->Controller); regModemControl &= ~SERIAL_MCR_RTS; WRITE_MODEM_CONTROL(pDevExt, pDevExt->Controller, regModemControl); WdfInterruptReleaseLock(pDevExt->WdfInterrupt); } TraceMessage(TRACE_LEVEL_INFORMATION, TRACE_FLAG_CONTROL, "WdfRequestComplete( %!HANDLE! => %!STATUS! )", Request, status); WdfRequestComplete(Request, status); FuncExit(TRACE_FLAG_CONTROL); }
// // Internal Function: UartCtlSetDtr // VOID UartCtlSetDtr( _In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength ) { PUART_DEVICE_EXTENSION pDevExt = UartGetDeviceExtension(Device); UCHAR regModemControl; NTSTATUS status = STATUS_SUCCESS; UNREFERENCED_PARAMETER(OutputBufferLength); UNREFERENCED_PARAMETER(InputBufferLength); FuncEntry(TRACE_FLAG_CONTROL); if ((pDevExt->HandFlow.ControlHandShake & SERIAL_DTR_MASK) == SERIAL_DTR_HANDSHAKE) { status = STATUS_INVALID_PARAMETER; TraceMessage( TRACE_LEVEL_ERROR, TRACE_FLAG_CONTROL, "DTR cannot be set when automatic DTR flow control is used - " "%!STATUS!", status); } if (NT_SUCCESS(status)) { // Acquires the interrupt lock and sets the MCR. WdfInterruptAcquireLock(pDevExt->WdfInterrupt); regModemControl = READ_MODEM_CONTROL(pDevExt, pDevExt->Controller); regModemControl |= SERIAL_MCR_DTR; WRITE_MODEM_CONTROL(pDevExt, pDevExt->Controller, regModemControl); WdfInterruptReleaseLock(pDevExt->WdfInterrupt); } TraceMessage(TRACE_LEVEL_INFORMATION, TRACE_FLAG_CONTROL, "WdfRequestComplete( %!HANDLE! => %!STATUS! )", Request, status); WdfRequestComplete(Request, status); FuncExit(TRACE_FLAG_CONTROL); }
_Use_decl_annotations_ VOID PLxEvtInterruptDpc( WDFINTERRUPT Interrupt, WDFOBJECT Device ) /*++ Routine Description: DPC callback for ISR. Please note that on a multiprocessor system, you could have more than one DPCs running simulataneously on multiple processors. So if you are accesing any global resources make sure to synchrnonize the accesses with a spinlock. Arguments: Interupt - Handle to WDFINTERRUPT Object for this device. Device - WDFDEVICE object passed to InterruptCreate Return Value: --*/ { NTSTATUS status; WDFDMATRANSACTION dmaTransaction; PDEVICE_EXTENSION devExt; BOOLEAN writeInterrupt = FALSE; BOOLEAN readInterrupt = FALSE; UNREFERENCED_PARAMETER(Device); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_DPC, "--> EvtInterruptDpc"); devExt = PLxGetDeviceContext(WdfInterruptGetDevice(Interrupt)); // // Acquire this device's InterruptSpinLock. // WdfInterruptAcquireLock( Interrupt ); if ((devExt->IntCsr.bits.DmaChan0IntActive) && (devExt->Dma0Csr.bits.Done)) { // // If Dma0 channel 0 (write) is interrupting and the // Done bit is set in the Dma0 CSR, // we're interrupting because a WRITE is complete. // Clear the done bit and channel interrupting bit from // our copies... // devExt->IntCsr.bits.DmaChan0IntActive = FALSE; devExt->Dma0Csr.uchar = 0; writeInterrupt = TRUE; } if ((devExt->IntCsr.bits.DmaChan1IntActive) && (devExt->Dma1Csr.bits.Done)) { // // If DMA channel 1 is interrupting and the // DONE bit is set in the DMA1 control/status // register, we're interrupting because a READ // is complete. // Clear the done bit and channel interrupting bit from // our copies... // devExt->IntCsr.bits.DmaChan1IntActive = FALSE; devExt->Dma0Csr.uchar = 0; readInterrupt = TRUE; } // // Release our interrupt spinlock // WdfInterruptReleaseLock( Interrupt ); // // Did a Write DMA complete? // if (writeInterrupt) { BOOLEAN transactionComplete; // // Get the current Write DmaTransaction. // dmaTransaction = devExt->WriteDmaTransaction; // // Indicate this DMA operation has completed: // This may drive the transfer on the next packet if // there is still data to be transfered in the request. // transactionComplete = WdfDmaTransactionDmaCompleted( dmaTransaction, &status ); if (transactionComplete) { // // Complete this DmaTransaction. // TraceEvents(TRACE_LEVEL_INFORMATION, DBG_DPC, "Completing Write request in the DpcForIsr"); PLxWriteRequestComplete( dmaTransaction, status ); } } // // Did a Read DMA complete? // if (readInterrupt) { BOOLEAN transactionComplete; PDMA_TRANSFER_ELEMENT dteVA; size_t length; // // Get the current Read DmaTransaction. // dmaTransaction = devExt->ReadDmaTransaction; // // Only on Read-side -- // Use "DMA Clear-Count Mode" to get complemetary // transferred byte count. // length = WdfDmaTransactionGetCurrentDmaTransferLength( dmaTransaction ); dteVA = (PDMA_TRANSFER_ELEMENT) devExt->ReadCommonBufferBase; while(dteVA->DescPtr.LastElement == FALSE) { length -= dteVA->TransferSize; dteVA++; } length -= dteVA->TransferSize; // // Indicate this DMA operation has completed: // This may drive the transfer on the next packet if // there is still data to be transfered in the request. // transactionComplete = WdfDmaTransactionDmaCompletedWithLength( dmaTransaction, length, &status ); if (transactionComplete) { // // Complete this DmaTransaction. // TraceEvents(TRACE_LEVEL_INFORMATION, DBG_DPC, "Completing Read request in the DpcForIsr"); PLxReadRequestComplete( dmaTransaction, status ); } } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_DPC, "<-- EvtInterruptDpc"); return; }
//----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- VOID HSACEvtIoDeviceControl( __in WDFQUEUE Queue, __in WDFREQUEST Request, __in size_t OutputBufferLength, __in size_t InputBufferLength, __in ULONG IoControlCode ) /*++ Routine Description: This event is called when the framework receives IRP_MJ_DEVICE_CONTROL requests from the system. Arguments: Queue - Handle to the framework queue object that is associated with the I/O request. Request - Handle to a framework request object. OutputBufferLength - length of the request output buffer, if an output buffer is available. InputBufferLength - length of the request input buffer, if an input buffer is available. IoControlCode - the driver-defined or system-defined I/O control code (IOCTL) that is associated with the request. Return Value: VOID --*/ { PDEVICE_EXTENSION devExt; size_t length = 0; NTSTATUS status = STATUS_SUCCESS; PVOID pInputBuffer = NULL; PVOID pOutputBuffer = NULL; ULONG a1 = 0,a2 = 0; ULONG readIndex = 0, readNum = 0; UNREFERENCED_PARAMETER( InputBufferLength ); UNREFERENCED_PARAMETER( OutputBufferLength ); // // Get the device extension. // devExt = HSACGetDeviceContext(WdfIoQueueGetDevice( Queue )); #if (DBG != 0) TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, "HSACEvtIoDeviceControl InputBufferLength: 0x%x, OutputBufferLength: 0x%x\n", InputBufferLength, OutputBufferLength); #endif // // Handle this request specific code. // switch (IoControlCode) { case IOCTL_GET_REGISTER: { #if (DBG != 0) TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, "IOCTL_GET_REGISTER-->require length: 0x%x\n", sizeof(ULONG)); #endif status = WdfRequestRetrieveInputBuffer(Request, 0, &pInputBuffer, &length); if( !NT_SUCCESS(status)) { #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveInputBuffer failed 0x%x\n", status); #endif break; } status = WdfRequestRetrieveOutputBuffer(Request, 0, &pOutputBuffer, &length); if( !NT_SUCCESS(status)) { #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveOutputBuffer failed 0x%x\n", status); #endif break; } readIndex = *(PULONG)pInputBuffer; readNum = *((PULONG)pInputBuffer + 1); #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "readIndex: %d, readNum: %d\n", readIndex, readNum); #endif if (readNum == 0) { length = 0; break; } //if (readNum > 1) //{ if (readIndex + readNum > (sizeof(HSAC_REGS)/sizeof(unsigned int) )) { readNum = (sizeof(HSAC_REGS)/sizeof(unsigned int) ) - readIndex; } WdfInterruptAcquireLock( devExt->Interrupt ); READ_REGISTER_BUFFER_ULONG(((PULONG) devExt->Regs) + readIndex, (PULONG)pOutputBuffer, readNum); WdfInterruptReleaseLock( devExt->Interrupt ); //} //else //{ // *(PULONG)pOutputBuffer = READ_REGISTER_ULONG( ((PULONG) devExt->Regs) + readIndex ); //} length = readNum; break; } case IOCTL_GET_SINGLE_REGISTER: { #if (DBG != 0) TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, "IOCTL_GET_REGISTER-->require length: 0x%x\n", sizeof(ULONG)); #endif status = WdfRequestRetrieveInputBuffer(Request, 0, &pInputBuffer, &length); if( !NT_SUCCESS(status)) { #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveInputBuffer failed 0x%x\n", status); #endif break; } status = WdfRequestRetrieveOutputBuffer(Request, 0, &pOutputBuffer, &length); if( !NT_SUCCESS(status)) { #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveOutputBuffer failed 0x%x\n", status); #endif break; } readIndex = *(PULONG)pInputBuffer; #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "readIndex: %d\n", readIndex); #endif WdfInterruptAcquireLock( devExt->Interrupt ); *(PULONG)pOutputBuffer = READ_REGISTER_ULONG( ((PULONG) devExt->Regs) + readIndex ); WdfInterruptReleaseLock( devExt->Interrupt ); length = sizeof(ULONG); break; } case IOCTL_SET_REGISTER: { status = WdfRequestRetrieveInputBuffer(Request, 0, &pInputBuffer, &length); if( !NT_SUCCESS(status)) { #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveInputBuffer failed 0x%x\n", status); #endif break; } WdfInterruptAcquireLock( devExt->Interrupt ); WRITE_REGISTER_ULONG( ((PULONG) devExt->Regs) + (*(PULONG)pInputBuffer), *((PULONG)pInputBuffer + 1) ); WdfInterruptReleaseLock( devExt->Interrupt ); // //a1 = *(PULONG)pInputBuffer; // //a2 = *((PULONG)pInputBuffer + 1); // //#if (DBG != 0) // TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, // "IOCTL_SET_REGISTER-->offset:0x%x, value:0x%x\n", a1, a2); //#endif // // //a2 = READ_REGISTER_ULONG( ((PULONG) devExt->Regs) + (*(PULONG)pInputBuffer) ); // //#if (DBG != 0) // TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, // "IOCTL_SET_REGISTER-->offset:0x%x, value:0x%x\n", a1, a2); //#endif length = 0; break; } case IOCTL_GET_SRAM: { #if (DBG != 0) TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, "IOCTL_GET_SRAM-->require length: 0x%x\n", sizeof(ULONG)); #endif status = WdfRequestRetrieveInputBuffer(Request, 0, &pInputBuffer, &length); if( !NT_SUCCESS(status)) { #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveInputBuffer failed 0x%x\n", status); #endif break; } status = WdfRequestRetrieveOutputBuffer(Request, 0, &pOutputBuffer, &length); if( !NT_SUCCESS(status)) { #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveOutputBuffer failed 0x%x\n", status); #endif break; } readIndex = *(PULONG)pInputBuffer; readNum = *((PULONG)pInputBuffer + 1); if (readNum == 0) { length = 0; break; } //if (readNum > 1) //{ if (readIndex + readNum > (devExt->SRAMLength/sizeof(ULONG) )) { readNum = (devExt->SRAMLength/sizeof(ULONG) ) - readIndex; } #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "readIndex: %d, readNum: %d\n", readIndex, readNum); #endif WdfInterruptAcquireLock( devExt->Interrupt ); READ_REGISTER_BUFFER_ULONG(((PULONG) devExt->SRAMBase) + readIndex, (PULONG)pOutputBuffer, readNum); WdfInterruptReleaseLock( devExt->Interrupt ); //} //else //{ // *(PULONG)pOutputBuffer = READ_REGISTER_ULONG( ((PULONG) devExt->Regs) + readIndex ); //} length = readNum; break; } case IOCTL_SET_SRAM: { status = WdfRequestRetrieveInputBuffer(Request, 0, &pInputBuffer, &length); if( !NT_SUCCESS(status)) { #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveInputBuffer failed 0x%x\n", status); #endif break; } readIndex = *(PULONG)pInputBuffer; readNum = *((PULONG)pInputBuffer + 1); if (readNum == 0) { length = 0; break; } //if (readNum > 1) //{ if (readIndex + readNum > (devExt->SRAMLength/sizeof(ULONG) )) { readNum = (devExt->SRAMLength/sizeof(ULONG) ) - readIndex; } #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "readIndex: %d, readNum: %d\n", readIndex, readNum); #endif WdfInterruptAcquireLock( devExt->Interrupt ); WRITE_REGISTER_BUFFER_ULONG( ((PULONG) devExt->SRAMBase) + readIndex, (PULONG)pInputBuffer + 2, readNum); WdfInterruptReleaseLock( devExt->Interrupt ); // //a1 = *(PULONG)pInputBuffer; // //a2 = *((PULONG)pInputBuffer + 1); // //#if (DBG != 0) // TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, // "IOCTL_SET_REGISTER-->offset:0x%x, value:0x%x\n", a1, a2); //#endif // // //a2 = READ_REGISTER_ULONG( ((PULONG) devExt->Regs) + (*(PULONG)pInputBuffer) ); // //#if (DBG != 0) // TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, // "IOCTL_SET_REGISTER-->offset:0x%x, value:0x%x\n", a1, a2); //#endif length = readNum; break; } case IOCTL_MAP_DMA_BUF_ADDR: { ULONG_PTR address = 0; status = WdfRequestRetrieveInputBuffer(Request, 0, &pInputBuffer, &length); if( !NT_SUCCESS(status)) { #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveInputBuffer failed 0x%x\n", status); #endif break; } status = WdfRequestRetrieveOutputBuffer(Request, 0, &pOutputBuffer, &length); if( !NT_SUCCESS(status)) { #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveOutputBuffer failed 0x%x\n", status); #endif break; } if (devExt->MapFlag == 1) { HSACUnmapUserAddress(devExt); devExt->MapFlag = 0; } HSACMapUserAddress( devExt ); devExt->MapFlag = 1; #if (CACHE_MODE == MULTI_DISCRETE_CACHE) if (*(PULONG)pInputBuffer == 0) { length = devExt->readCommonBufferNum * sizeof(PVOID); RtlCopyMemory(pOutputBuffer, devExt->pReadUserAddress, length); } else if (*(PULONG)pInputBuffer == 1) { length = devExt->writeCommonBufferNum * sizeof(PVOID); RtlCopyMemory(pOutputBuffer, devExt->pWriteUserAddress, length); } else { status = STATUS_INVALID_DEVICE_REQUEST; } #else if (*(PULONG)pInputBuffer == 0) { address = (ULONG_PTR)devExt->ReadUserAddress0; } else if (*(PULONG)pInputBuffer == 1) { address = (ULONG_PTR)devExt->WriteUserAddress0; } else { status = STATUS_INVALID_DEVICE_REQUEST; } #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "UserAddress: 0x%I64x", address); #endif RtlCopyMemory(pOutputBuffer, &address, sizeof(PVOID)); #endif break; } case IOCTL_UNMAP_DMA_BUF_ADDR: { if (devExt->MapFlag == 1) { HSACUnmapUserAddress(devExt); devExt->MapFlag = 0; } break; } case IOCTL_SET_DMA_PROFILE: { status = WdfRequestRetrieveInputBuffer(Request, 0, &pInputBuffer, &length); if( !NT_SUCCESS(status)) { #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveInputBuffer failed 0x%x\n", status); #endif break; } devExt->dmaProfile = (WDF_DMA_PROFILE)(*(PULONG)pInputBuffer); #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "dmaProfile: %d\n", devExt->dmaProfile); #endif length = 0; break; } case IOCTL_DIRECT_DMA_READ: { // ULONG dma1Ctl = 0; // status = WdfRequestRetrieveInputBuffer(Request, 0, &pInputBuffer, &length); // devExt->ReadSize = *(PULONG)pInputBuffer; // //#if (DBG != 0) // TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, // "devExt->ReadSize: %d\n", devExt->ReadSize); //#endif // // WdfInterruptAcquireLock( devExt->Interrupt ); // // WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->DMA1_ADDR32, // devExt->ReadCommonBufferBaseLA.LowPart); // WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->DMA1_ADDR64, // devExt->ReadCommonBufferBaseLA.HighPart ); // // WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->DMA1_SIZE, devExt->ReadSize); // devExt->ReadSize = 0; // // dma1Ctl = DMA_CTRL_START; // //WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->DMA1_CTRL, dma1Ctl); // // WdfInterruptReleaseLock( devExt->Interrupt ); break; } case IOCTL_DIRECT_DMA_WRITE: { //ULONG dma0Ctl = 0; //status = WdfRequestRetrieveInputBuffer(Request, 0, &pInputBuffer, &length); //devExt->WriteSize = *(PULONG)pInputBuffer; //WdfInterruptAcquireLock( devExt->Interrupt ); //WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->DMA0_ADDR32, // devExt->WriteCommonBufferBaseLA.LowPart ); //WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->DMA0_ADDR64, // devExt->WriteCommonBufferBaseLA.HighPart ); //WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->DMA0_SIZE, devExt->WriteSize); //dma0Ctl = DMA_CTRL_START; //WRITE_REGISTER_ULONG( (PULONG) &devExt->Regs->DMA0_CTRL, dma0Ctl); //WdfInterruptReleaseLock( devExt->Interrupt ); break; } case IOCTL_RESET: // code == 0x801 { status = WdfRequestRetrieveOutputBuffer(Request, 0, &pOutputBuffer, &length); if( !NT_SUCCESS(status)) { #if (DBG != 0) TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveOutputBuffer failed 0x%x\n", status); #endif break; } //*(PULONG) buffer = 0x0004000A; //status = STATUS_SUCCESS; length = sizeof(ULONG); break; } default: status = STATUS_INVALID_DEVICE_REQUEST; break; } WdfRequestCompleteWithInformation(Request, status, length); }
VOID DeviceInterrupt_EvtInterruptDpc ( _In_ WDFINTERRUPT Interrupt, _In_ WDFOBJECT AssociatedObject ) /*++ Routine Description: 'EvtInterruptDpc' handler for the device interrupt object. http://msdn.microsoft.com/en-us/library/windows/hardware/ff541721(v=vs.85).aspx Arguments: Interrupt - Associated interrupt object. AssociatedObject - FDO Object --*/ { WDFDEVICE WdfDevice; PDEVICE_INTERRUPT_CONTEXT InterruptContext; PCONTROLLER_CONTEXT ControllerContext; BOOLEAN Attached; BOOLEAN GotAttachOrDetach; CONTROLLER_EVENT ControllerEvent; UNREFERENCED_PARAMETER(Interrupt); TraceEntry(); WdfDevice = (WDFDEVICE) AssociatedObject; ControllerContext = DeviceGetControllerContext(WdfDevice); WdfSpinLockAcquire(ControllerContext->DpcLock); WdfInterruptAcquireLock(ControllerContext->DeviceInterrupt); Attached = ControllerContext->Attached; GotAttachOrDetach = ControllerContext->GotAttachOrDetach; ControllerContext->GotAttachOrDetach = FALSE; WdfInterruptReleaseLock(ControllerContext->DeviceInterrupt); // // Handle attach/detach events // if (GotAttachOrDetach) { if (Attached && ControllerContext->WasAttached) { // // We must have gotten at least one detach. Need to reset the state. // ControllerContext->RemoteWakeupRequested = FALSE; ControllerContext->Suspended = FALSE; UfxDeviceNotifyDetach(ControllerContext->UfxDevice); } if (Attached) { ControllerContext->RemoteWakeupRequested = FALSE; ControllerContext->Suspended = FALSE; UfxDeviceNotifyAttach(ControllerContext->UfxDevice); } } ControllerContext->WasAttached = Attached; InterruptContext = DeviceInterruptGetContext(ControllerContext->DeviceInterrupt); // // #### TODO: Insert code to read and dispatch events from the controller #### // // The sample will assume an endpoint event of EndpointEventTransferComplete ControllerEvent.Type = EventTypeEndpoint; ControllerEvent.u.EndpointEvent = EndpointEventTransferComplete; // // Handle events from the controller // switch (ControllerEvent.Type) { case EventTypeDevice: HandleDeviceEvent(WdfDevice, ControllerEvent.u.DeviceEvent); break; case EventTypeEndpoint: HandleEndpointEvent(WdfDevice, ControllerEvent.u.EndpointEvent); break; } WdfSpinLockRelease(ControllerContext->DpcLock); TraceExit(); }
// // Internal Function: UartCtlSetBaudRate // VOID UartCtlSetBaudRate( _In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength ) { NTSTATUS status = STATUS_UNSUCCESSFUL; PUART_DEVICE_EXTENSION pDevExt = UartGetDeviceExtension(Device); PSERIAL_BAUD_RATE pBaudRate = NULL; USHORT DivisorLatchRegs = 0; UNREFERENCED_PARAMETER(OutputBufferLength); UNREFERENCED_PARAMETER(InputBufferLength); FuncEntry(TRACE_FLAG_CONTROL); status = WdfRequestRetrieveInputBuffer(Request, sizeof(SERIAL_BAUD_RATE), (PVOID*)(& pBaudRate), NULL); if (!NT_SUCCESS(status)) { TraceMessage( TRACE_LEVEL_ERROR, TRACE_FLAG_CONTROL, "Failed to retrieve input buffer for WDFREQUEST %p - " "%!STATUS!", Request, status); } if (NT_SUCCESS(status)) { status = UartRegConvertAndValidateBaud( pBaudRate->BaudRate, &DivisorLatchRegs); if (!NT_SUCCESS(status)) { TraceMessage( TRACE_LEVEL_ERROR, TRACE_FLAG_CONTROL, "Failed to convert and validate baudrate %lu - " "%!STATUS!", pBaudRate->BaudRate, status); } } if (NT_SUCCESS(status)) { // Acquires the interrupt lock and writes the Divisor Latch. WdfInterruptAcquireLock(pDevExt->WdfInterrupt); pDevExt->CurrentBaud = pBaudRate->BaudRate; WRITE_DIVISOR_LATCH(pDevExt, pDevExt->Controller, DivisorLatchRegs); WdfInterruptReleaseLock(pDevExt->WdfInterrupt); } TraceMessage(TRACE_LEVEL_INFORMATION, TRACE_FLAG_CONTROL, "WdfRequestComplete( %!HANDLE! => %!STATUS! )", Request, status); WdfRequestComplete(Request, status); FuncExit(TRACE_FLAG_CONTROL); }
// // Internal Function: UartCtlGetLineControl // VOID UartCtlGetLineControl( _In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength ) { NTSTATUS status = STATUS_UNSUCCESSFUL; PUART_DEVICE_EXTENSION pDevExt = UartGetDeviceExtension(Device); UCHAR lineControlRegister = 0; PSERIAL_LINE_CONTROL pLineControl = NULL; UNREFERENCED_PARAMETER(OutputBufferLength); UNREFERENCED_PARAMETER(InputBufferLength); FuncEntry(TRACE_FLAG_CONTROL); status = WdfRequestRetrieveOutputBuffer(Request, sizeof(SERIAL_LINE_CONTROL), (PVOID*)(& pLineControl), NULL); if (!NT_SUCCESS(status)) { TraceMessage( TRACE_LEVEL_ERROR, TRACE_FLAG_CONTROL, "Failed to retrieve output buffer for WDFREQUEST %p - " "%!STATUS!", Request, status); } if (NT_SUCCESS(status)) { // Acquires the interrupt lock and reads the LCR. WdfInterruptAcquireLock(pDevExt->WdfInterrupt); lineControlRegister = READ_LINE_CONTROL(pDevExt, pDevExt->Controller); WdfInterruptReleaseLock(pDevExt->WdfInterrupt); status = UartRegLCRToStruct(lineControlRegister, pLineControl); if (!NT_SUCCESS(status)) { TraceMessage( TRACE_LEVEL_ERROR, TRACE_FLAG_CONTROL, "Failed to calculate SERIAL_LINE_CONTROL from LCR %c - " "%!STATUS!", lineControlRegister, status); } } if (NT_SUCCESS(status)) { WdfRequestSetInformation(Request, sizeof(SERIAL_LINE_CONTROL)); } TraceMessage(TRACE_LEVEL_INFORMATION, TRACE_FLAG_CONTROL, "WdfRequestComplete( %!HANDLE! => %!STATUS! )", Request, status); WdfRequestComplete(Request, status); FuncExit(TRACE_FLAG_CONTROL); }
// // Internal Function: UartCtlSetLineControl // VOID UartCtlSetLineControl( _In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength ) { NTSTATUS status = STATUS_UNSUCCESSFUL; PUART_DEVICE_EXTENSION pDevExt = UartGetDeviceExtension(Device); UCHAR lineControlRegister = 0; PSERIAL_LINE_CONTROL pLineControl = NULL; UNREFERENCED_PARAMETER(OutputBufferLength); UNREFERENCED_PARAMETER(InputBufferLength); FuncEntry(TRACE_FLAG_CONTROL); status = WdfRequestRetrieveInputBuffer(Request, sizeof(SERIAL_LINE_CONTROL), (PVOID*)(& pLineControl), NULL); if (!NT_SUCCESS(status)) { TraceMessage( TRACE_LEVEL_ERROR, TRACE_FLAG_CONTROL, "Failed to retrieve input buffer for WDFREQUEST %p - " "%!STATUS!", Request, status); } if (NT_SUCCESS(status)) { status = UartRegStructToLCR(pLineControl, &lineControlRegister); if (!NT_SUCCESS(status)) { TraceMessage( TRACE_LEVEL_ERROR, TRACE_FLAG_CONTROL, "Failed to calculate LCR from SERIAL_LINE_CONTROL %p - " "%!STATUS!", pLineControl, status); } } if (NT_SUCCESS(status)) { WdfInterruptAcquireLock(pDevExt->WdfInterrupt); // Set line control, save break setting lineControlRegister = lineControlRegister | (READ_LINE_CONTROL(pDevExt, pDevExt->Controller) & SERIAL_LCR_BREAK); WRITE_LINE_CONTROL(pDevExt, pDevExt->Controller, lineControlRegister); WdfInterruptReleaseLock(pDevExt->WdfInterrupt); } TraceMessage(TRACE_LEVEL_INFORMATION, TRACE_FLAG_CONTROL, "WdfRequestComplete( %!HANDLE! => %!STATUS! )", Request, status); WdfRequestComplete(Request, status); FuncExit(TRACE_FLAG_CONTROL); }
// // Internal Function: UartCtlSetHandflow // VOID UartCtlSetHandflow( _In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength ) { NTSTATUS status = STATUS_UNSUCCESSFUL; PUART_DEVICE_EXTENSION pDevExt = UartGetDeviceExtension(Device); PSERIAL_HANDFLOW pHandFlow = NULL; UNREFERENCED_PARAMETER(OutputBufferLength); UNREFERENCED_PARAMETER(InputBufferLength); FuncEntry(TRACE_FLAG_CONTROL); status = WdfRequestRetrieveInputBuffer(Request, sizeof(SERIAL_HANDFLOW), (PVOID*)(& pHandFlow), NULL); if (!NT_SUCCESS(status)) { TraceMessage( TRACE_LEVEL_ERROR, TRACE_FLAG_CONTROL, "Failed to retrieve input buffer for WDFREQUEST %p - " "%!STATUS!", Request, status); } if (NT_SUCCESS(status)) { // // Make sure there are no invalid bits set in // the control and handshake // if ((pHandFlow->ControlHandShake & SERIAL_CONTROL_INVALID) || (pHandFlow->FlowReplace & SERIAL_FLOW_INVALID)) { status = STATUS_INVALID_PARAMETER; TraceMessage( TRACE_LEVEL_ERROR, TRACE_FLAG_CONTROL, "Invalid bit in SERIAL_HANDFLOW %p - " "%!STATUS!", pHandFlow, status); } } if (NT_SUCCESS(status)) { // // Software flow control and in-band signaling // have not been implemented in this sample. // if ((pHandFlow->ControlHandShake & SERIAL_DSR_SENSITIVITY) || (pHandFlow->ControlHandShake & SERIAL_ERROR_ABORT) || (pHandFlow->ControlHandShake & SERIAL_DCD_HANDSHAKE) || (pHandFlow->FlowReplace & SERIAL_AUTO_TRANSMIT) || (pHandFlow->FlowReplace & SERIAL_AUTO_RECEIVE) || (pHandFlow->FlowReplace & SERIAL_ERROR_CHAR) || (pHandFlow->FlowReplace & SERIAL_NULL_STRIPPING) || (pHandFlow->FlowReplace & SERIAL_BREAK_CHAR) || (pHandFlow->FlowReplace & SERIAL_XOFF_CONTINUE) || ((pHandFlow->FlowReplace & SERIAL_RTS_MASK) == SERIAL_TRANSMIT_TOGGLE)) { status = STATUS_NOT_IMPLEMENTED; TraceMessage( TRACE_LEVEL_WARNING, TRACE_FLAG_CONTROL, "Specified SERIAL_HANDFLOW %p has not been implemented - " "%!STATUS!", pHandFlow, status); } } if (NT_SUCCESS(status)) { // // Make sure the DTR mode is valid // if ((pHandFlow->ControlHandShake & SERIAL_DTR_MASK) == SERIAL_DTR_MASK) { status = STATUS_INVALID_PARAMETER; TraceMessage( TRACE_LEVEL_ERROR, TRACE_FLAG_CONTROL, "Cannot set handflow with invalid DTR mode %lu - " "%!STATUS!", pHandFlow->ControlHandShake, status); } } if (NT_SUCCESS(status)) { WdfSpinLockAcquire(pDevExt->ReceiveBufferSpinLock); WdfInterruptAcquireLock(pDevExt->WdfInterrupt); BOOLEAN newFlowControl; BOOLEAN prevFlowControl = UsingRXFlowControl(pDevExt); pDevExt->HandFlow = *pHandFlow; newFlowControl = UsingRXFlowControl(pDevExt); WdfInterruptReleaseLock(pDevExt->WdfInterrupt); // Empty software FIFO before changing flow control if (newFlowControl != prevFlowControl) { if (!newFlowControl) { if (pDevExt->FIFOBufferBytes > 0) { // If switching from flow control to no flow control, // read bytes from the software FIFO to ring buffer before // asserting flow control lines. // Shouldn't have a cached buffer and bytes in the software FIFO NT_ASSERT(!HasCachedReceiveBuffer(pDevExt)); // Using a new status variable so the IOCTL doesn't fail if // the driver can't read the software FIFO to SerCx ring buffer, which // may happen after the file has closed. NTSTATUS fifoStatus = SerCxRetrieveReceiveBuffer(Device, SERIAL_SOFTWARE_FIFO_SIZE, &pDevExt->PIOReceiveBuffer); // Read bytes from software FIFO and return the buffer if (NT_SUCCESS(fifoStatus)) { // Read the software FIFO bytes into the ring buffer. // This function won't return the buffer. UartReceiveBytesFromSoftwareFIFO(pDevExt); // The software FIFO has been read out and should be empty now. NT_ASSERT(pDevExt->FIFOBufferBytes == 0); fifoStatus = SerCxProgressReceive( Device, pDevExt->ReceiveProgress, SerCxStatusSuccess); if (!NT_SUCCESS(fifoStatus)) { TraceMessage( TRACE_LEVEL_ERROR, TRACE_FLAG_CONTROL, "%!FUNC! Failed to return buffer - %!STATUS!", fifoStatus); NT_ASSERTMSG("SerCxProgressReceive shouldn't fail", NT_SUCCESS(fifoStatus)); } pDevExt->PerfStats.ReceivedCount += pDevExt->ReceiveProgress; pDevExt->ReceiveProgress = 0; pDevExt->PIOReceiveBuffer.Buffer = NULL; } else { TraceMessage( TRACE_LEVEL_WARNING, TRACE_FLAG_CONTROL, "SerCxRetrieveReceiveBuffer failed - %!STATUS!", fifoStatus); } } } else { // If switching from no flow control to flow control, // the software FIFO should already be empty. NT_ASSERT(pDevExt->FIFOBufferBytes == 0); } } WdfInterruptAcquireLock(pDevExt->WdfInterrupt); // If software FIFO empty, re-assert flow control // Automatic flow control MUST be re-enabled here if it's being used. if (pDevExt->FIFOBufferBytes == 0) { UartFlowReceiveAvailable(Device); } WdfInterruptReleaseLock(pDevExt->WdfInterrupt); WdfSpinLockRelease(pDevExt->ReceiveBufferSpinLock); } TraceMessage(TRACE_LEVEL_INFORMATION, TRACE_FLAG_CONTROL, "WdfRequestComplete( %!HANDLE! => %!STATUS! )", Request, status); WdfRequestComplete(Request, status); FuncExit(TRACE_FLAG_CONTROL); }