BOOLEAN SerialTurnOnBreak( IN PVOID Context ) /*++ Routine Description: This routine will turn on break in the hardware and record the fact the break is on, in the extension variable that holds reasons that transmission is stopped. Arguments: Context - Really a pointer to the device extension. Return Value: This routine always returns FALSE. --*/ { PSERIAL_DEVICE_EXTENSION Extension = Context; UCHAR OldLineControl; if ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) == SERIAL_TRANSMIT_TOGGLE) { SerialSetRTS(Extension); } OldLineControl = READ_LINE_CONTROL(Extension->Controller); OldLineControl |= SERIAL_LCR_BREAK; WRITE_LINE_CONTROL( Extension->Controller, OldLineControl ); Extension->TXHolding |= SERIAL_TX_BREAK; return FALSE; }
VOID SerialSaveDeviceState(IN PSERIAL_DEVICE_EXTENSION PDevExt) /*++ Routine Description: This routine saves the device state of the UART Arguments: PDevExt - Pointer to the device extension for the devobj to save the state for. Return Value: VOID --*/ { PSERIAL_DEVICE_STATE pDevState = &PDevExt->DeviceState; PAGED_CODE(); SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_POWER, "Entering SerialSaveDeviceState\n"); // // Read necessary registers direct // pDevState->IER = READ_INTERRUPT_ENABLE(PDevExt, PDevExt->Controller); pDevState->MCR = READ_MODEM_CONTROL(PDevExt, PDevExt->Controller); pDevState->LCR = READ_LINE_CONTROL(PDevExt, PDevExt->Controller); SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_POWER, "Leaving SerialSaveDeviceState\n"); }
BOOLEAN SerialTurnOffBreak( IN PVOID Context ) /*++ Routine Description: This routine will turn off break in the hardware and record the fact the break is off, in the extension variable that holds reasons that transmission is stopped. Arguments: Context - Really a pointer to the device extension. Return Value: This routine always returns FALSE. --*/ { PSERIAL_DEVICE_EXTENSION Extension = Context; UCHAR OldLineControl; if (Extension->TXHolding & SERIAL_TX_BREAK) { // // We actually have a good reason for testing if transmission // is holding instead of blindly clearing the bit. // // If transmission actually was holding and the result of // clearing the bit is that we should restart transmission // then we will poke the interrupt enable bit, which will // cause an actual interrupt and transmission will then // restart on its own. // // If transmission wasn't holding and we poked the bit // then we would interrupt before a character actually made // it out and we could end up over writing a character in // the transmission hardware. OldLineControl = READ_LINE_CONTROL(Extension->Controller); OldLineControl &= ~SERIAL_LCR_BREAK; WRITE_LINE_CONTROL( Extension->Controller, OldLineControl ); Extension->TXHolding &= ~SERIAL_TX_BREAK; if (!Extension->TXHolding && (Extension->TransmitImmediate || Extension->WriteLength) && Extension->HoldingEmpty) { DISABLE_ALL_INTERRUPTS(Extension->Controller); ENABLE_ALL_INTERRUPTS(Extension->Controller); } else { // // The following routine will lower the rts if we // are doing transmit toggleing and there is no // reason to keep it up. // Extension->CountOfTryingToLowerRTS++; SerialPerhapsLowerRTS(Extension); } } return FALSE; }
// // 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); }