BOOLEAN SerialSetBaud( IN PVOID Context ) /*++ Routine Description: This routine is used to set the buad rate of the device. Arguments: Context - Pointer to a structure that contains a pointer to the device extension and what should be the current baud rate. Return Value: This routine always returns FALSE. --*/ { PSERIAL_DEVICE_EXTENSION Extension = ((PSERIAL_IOCTL_SYNC)Context)->Extension; USHORT Appropriate = (USHORT)(((PSERIAL_IOCTL_SYNC)Context)->Data); WRITE_DIVISOR_LATCH( Extension->Controller, Appropriate ); return FALSE; }
/////////////////////////////////////////////////////////////////////////////// // Does : Initializes the device. // Parameters : port - Port of a 8250 // baudrate - Baudrate to init 8250 to // dataBits - Number of data bits (5..8) // stopBits - Number of stop bits (1..2) // parity - 0 == NONE, 1 == ODD, 2 == EVEN // Returns : Status of the operation. // Postcondition : Ready to start interrupt processing when returning // STATUS_SUCCESS. /////////////////////////////////////////////////////////////////////////////// NTSTATUS Hw8250Init(PUCHAR port, ULONG baudRate, ULONG dataBits, ULONG stopBits, ULONG parity) { NTSTATUS result = STATUS_SUCCESS; ULONG divisor; UCHAR dataFormat; // disable all interrupts WRITE_INTERRUPT_ENABLE(port, 0x00); // set up baudrate divisor = Hw8550InternalGetDivisor(baudRate); WRITE_LINE_CONTROL(port, LCR_DLAB); WRITE_DIVISOR_LATCH(port, divisor); // set up data bits (defaults to 8 data bits) switch(dataBits) { case 5: dataFormat = LCR_DATA_5; break; case 6: dataFormat = LCR_DATA_6; break; case 7: dataFormat = LCR_DATA_7; break; case 8: default: dataFormat = LCR_DATA_8; break; } // set up stop bits (defaults to 1 stop bit) if(stopBits == 2) { dataFormat |= LCR_STOP_2; } else { dataFormat |= LCR_STOP_1; } // set up parity (defaults to none) switch(parity) { case 4: dataFormat |= LCR_PARITY_SPACE; break; case 3: dataFormat |= LCR_PARITY_MARK; break; case 2: dataFormat |= LCR_PARITY_EVEN; break; case 1: dataFormat |= LCR_PARITY_ODD; break; case 0: default: dataFormat |= LCR_PARITY_NONE; break; } WRITE_LINE_CONTROL(port, dataFormat); WRITE_MODEM_CONTROL(port, MCR_GPO1 | MCR_RTS | MCR_DTR); return result; } // end Hw8250Init
// // 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); }