PcAtChipsetPkg SerialIoLib: Implement Get(Set)Control/SetAttributes

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
Reviewed-by: Michael D Kinney <michael.d.kinney@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18964 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Star Zeng 2015-11-26 08:47:15 +00:00 committed by lzeng14
parent 8d9325deb7
commit d63a0df524
1 changed files with 276 additions and 0 deletions

View File

@ -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;
}