Cc: Michael D Kinney <michael.d.kin...@intel.com>
Cc: Liming Gao <liming....@intel.com>
Cc: Ruiyu Ni <ruiyu...@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.z...@intel.com>
Reviewed-by: Liming Gao <liming....@intel.com>
Reviewed-by: Michael D Kinney <michael.d.kin...@intel.com>
---
 PcAtChipsetPkg/Library/SerialIoLib/SerialPortLib.c | 287 +++++++++++++++++++++
 1 file changed, 287 insertions(+)

diff --git a/PcAtChipsetPkg/Library/SerialIoLib/SerialPortLib.c 
b/PcAtChipsetPkg/Library/SerialIoLib/SerialPortLib.c
index b364a5c..75324ad 100644
--- a/PcAtChipsetPkg/Library/SerialIoLib/SerialPortLib.c
+++ b/PcAtChipsetPkg/Library/SerialIoLib/SerialPortLib.c
@@ -39,6 +39,13 @@
 #define LSR_TXRDY               0x20
 #define LSR_RXDA                0x01
 #define DLAB                    0x01
+#define MCR_DTRC                0x01
+#define MCR_RTS                 0x02
+#define MCR_LME                 0x10
+#define MSR_CTS                 0x10
+#define MSR_DSR                 0x20
+#define MSR_RI                  0x40
+#define MSR_DCD                 0x80
 
 //---------------------------------------------
 // UART Settings
@@ -219,3 +226,283 @@ 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 |
+                    EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | 
EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE |
+                    EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) != 0) {
+    return RETURN_UNSUPPORTED;
+  }
+
+  //
+  // Read the Modem Control Register.
+  //
+  Mcr = IoRead8 ((UINT16) gUartBase + MCR_OFFSET);
+  Mcr &= (~(MCR_DTRC | MCR_RTS | MCR_LME));
+
+  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;
+  }
+
+  if ((Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) == 
EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) {
+    Mcr |= MCR_LME;
+  }
+
+  //
+  // 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;
+  }
+
+  if ((Mcr & MCR_LME) == MCR_LME) {
+    *Control |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;
+  }
+
+  //
+  // 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;
+}
+
-- 
1.9.5.msysgit.0

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to