From d63a0df524617bee32977e932b413ef718e823b9 Mon Sep 17 00:00:00 2001 From: Star Zeng Date: Thu, 26 Nov 2015 08:47:15 +0000 Subject: [PATCH] PcAtChipsetPkg SerialIoLib: Implement Get(Set)Control/SetAttributes Cc: Michael D Kinney Cc: Liming Gao Cc: Ruiyu Ni Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Star Zeng Reviewed-by: Liming Gao Reviewed-by: Michael D Kinney git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18964 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Library/SerialIoLib/SerialPortLib.c | 276 ++++++++++++++++++ 1 file changed, 276 insertions(+) diff --git a/PcAtChipsetPkg/Library/SerialIoLib/SerialPortLib.c b/PcAtChipsetPkg/Library/SerialIoLib/SerialPortLib.c index b364a5c8ab..8656785347 100644 --- a/PcAtChipsetPkg/Library/SerialIoLib/SerialPortLib.c +++ b/PcAtChipsetPkg/Library/SerialIoLib/SerialPortLib.c @@ -39,6 +39,12 @@ #define LSR_TXRDY 0x20 #define LSR_RXDA 0x01 #define DLAB 0x01 +#define MCR_DTRC 0x01 +#define MCR_RTS 0x02 +#define MSR_CTS 0x10 +#define MSR_DSR 0x20 +#define MSR_RI 0x40 +#define MSR_DCD 0x80 //--------------------------------------------- // UART Settings @@ -219,3 +225,273 @@ SerialPortPoll ( return (BOOLEAN) ((Data & LSR_RXDA) != 0); } +/** + Sets the control bits on a serial device. + + @param Control Sets the bits of Control that are settable. + + @retval RETURN_SUCCESS The new control bits were set on the serial device. + @retval RETURN_UNSUPPORTED The serial device does not support this operation. + @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +RETURN_STATUS +EFIAPI +SerialPortSetControl ( + IN UINT32 Control + ) +{ + UINT8 Mcr; + + // + // First determine the parameter is invalid. + // + if ((Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY))) != 0) { + return RETURN_UNSUPPORTED; + } + + // + // Read the Modem Control Register. + // + Mcr = IoRead8 ((UINT16) gUartBase + MCR_OFFSET); + Mcr &= (~(MCR_DTRC | MCR_RTS)); + + if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) == EFI_SERIAL_DATA_TERMINAL_READY) { + Mcr |= MCR_DTRC; + } + + if ((Control & EFI_SERIAL_REQUEST_TO_SEND) == EFI_SERIAL_REQUEST_TO_SEND) { + Mcr |= MCR_RTS; + } + + // + // Write the Modem Control Register. + // + IoWrite8 ((UINT16) gUartBase + MCR_OFFSET, Mcr); + + return RETURN_SUCCESS; +} + +/** + Retrieve the status of the control bits on a serial device. + + @param Control A pointer to return the current control signals from the serial device. + + @retval RETURN_SUCCESS The control bits were read from the serial device. + @retval RETURN_UNSUPPORTED The serial device does not support this operation. + @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +RETURN_STATUS +EFIAPI +SerialPortGetControl ( + OUT UINT32 *Control + ) +{ + UINT8 Msr; + UINT8 Mcr; + UINT8 Lsr; + + *Control = 0; + + // + // Read the Modem Status Register. + // + Msr = IoRead8 ((UINT16) gUartBase + MSR_OFFSET); + + if ((Msr & MSR_CTS) == MSR_CTS) { + *Control |= EFI_SERIAL_CLEAR_TO_SEND; + } + + if ((Msr & MSR_DSR) == MSR_DSR) { + *Control |= EFI_SERIAL_DATA_SET_READY; + } + + if ((Msr & MSR_RI) == MSR_RI) { + *Control |= EFI_SERIAL_RING_INDICATE; + } + + if ((Msr & MSR_DCD) == MSR_DCD) { + *Control |= EFI_SERIAL_CARRIER_DETECT; + } + + // + // Read the Modem Control Register. + // + Mcr = IoRead8 ((UINT16) gUartBase + MCR_OFFSET); + + if ((Mcr & MCR_DTRC) == MCR_DTRC) { + *Control |= EFI_SERIAL_DATA_TERMINAL_READY; + } + + if ((Mcr & MCR_RTS) == MCR_RTS) { + *Control |= EFI_SERIAL_REQUEST_TO_SEND; + } + + // + // Read the Line Status Register. + // + Lsr = IoRead8 ((UINT16) gUartBase + LSR_OFFSET); + + if ((Lsr & LSR_TXRDY) == LSR_TXRDY) { + *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY; + } + + if ((Lsr & LSR_RXDA) == 0) { + *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY; + } + + return RETURN_SUCCESS; +} + +/** + Sets the baud rate, receive FIFO depth, transmit/receice time out, parity, + data bits, and stop bits on a serial device. + + @param BaudRate The requested baud rate. A BaudRate value of 0 will use the + device's default interface speed. + On output, the value actually set. + @param ReveiveFifoDepth The requested depth of the FIFO on the receive side of the + serial interface. A ReceiveFifoDepth value of 0 will use + the device's default FIFO depth. + On output, the value actually set. + @param Timeout The requested time out for a single character in microseconds. + This timeout applies to both the transmit and receive side of the + interface. A Timeout value of 0 will use the device's default time + out value. + On output, the value actually set. + @param Parity The type of parity to use on this serial device. A Parity value of + DefaultParity will use the device's default parity value. + On output, the value actually set. + @param DataBits The number of data bits to use on the serial device. A DataBits + vaule of 0 will use the device's default data bit setting. + On output, the value actually set. + @param StopBits The number of stop bits to use on this serial device. A StopBits + value of DefaultStopBits will use the device's default number of + stop bits. + On output, the value actually set. + + @retval RETURN_SUCCESS The new attributes were set on the serial device. + @retval RETURN_UNSUPPORTED The serial device does not support this operation. + @retval RETURN_INVALID_PARAMETER One or more of the attributes has an unsupported value. + @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +RETURN_STATUS +EFIAPI +SerialPortSetAttributes ( + IN OUT UINT64 *BaudRate, + IN OUT UINT32 *ReceiveFifoDepth, + IN OUT UINT32 *Timeout, + IN OUT EFI_PARITY_TYPE *Parity, + IN OUT UINT8 *DataBits, + IN OUT EFI_STOP_BITS_TYPE *StopBits + ) +{ + UINTN Divisor; + UINT8 OutputData; + UINT8 LcrData; + UINT8 LcrParity; + UINT8 LcrStop; + + // + // Check for default settings and fill in actual values. + // + if (*BaudRate == 0) { + *BaudRate = gBps; + } + + if (*DataBits == 0) { + *DataBits = gData; + } + + if (*Parity == DefaultParity) { + *Parity = NoParity; + } + + if (*StopBits == DefaultStopBits) { + *StopBits = OneStopBit; + } + + if ((*DataBits < 5) || (*DataBits > 8)) { + return RETURN_INVALID_PARAMETER; + } + + if ((*Parity < NoParity) || (*Parity > SpaceParity)) { + return RETURN_INVALID_PARAMETER; + } + + if ((*StopBits < OneStopBit) || (*StopBits > TwoStopBits)) { + return RETURN_INVALID_PARAMETER; + } + + // + // Map 5..8 to 0..3 + // + LcrData = (UINT8) (*DataBits - (UINT8) 5); + + switch (*Parity) { + case NoParity: + LcrParity = 0; + break; + + case EvenParity: + LcrParity = 3; + break; + + case OddParity: + LcrParity = 1; + break; + + case SpaceParity: + LcrParity = 7; + break; + + case MarkParity: + LcrParity = 5; + break; + + default: + break; + } + + switch (*StopBits) { + case OneStopBit: + LcrStop = 0; + break; + + case OneFiveStopBits: + case TwoStopBits: + LcrStop = 1; + break; + + default: + break; + } + + // + // Calculate divisor for baud generator + // + Divisor = 115200 / (UINTN) *BaudRate; + + // + // Set communications format + // + OutputData = (UINT8) ((DLAB << 7) | (gBreakSet << 6) | (LcrParity << 3) | (LcrStop << 2) | LcrData); + IoWrite8 ((UINTN) (gUartBase + LCR_OFFSET), OutputData); + + // + // Configure baud rate + // + IoWrite8 ((UINTN) (gUartBase + BAUD_HIGH_OFFSET), (UINT8) (Divisor >> 8)); + IoWrite8 ((UINTN) (gUartBase + BAUD_LOW_OFFSET), (UINT8) (Divisor & 0xff)); + + // + // Switch back to bank 0 + // + OutputData = (UINT8) ((~DLAB << 7) | (gBreakSet << 6) | (LcrParity << 3) | (LcrStop << 2) | LcrData); + IoWrite8 ((UINTN) (gUartBase + LCR_OFFSET), OutputData); + + return RETURN_SUCCESS; +} + -- 2.39.2