summaryrefslogtreecommitdiff
path: root/Platform
diff options
context:
space:
mode:
authorGuo Mang <mang.guo@intel.com>2016-12-23 13:58:51 +0800
committerGuo Mang <mang.guo@intel.com>2016-12-26 19:15:18 +0800
commitf84a4e587ab750e5d6dcf9513a985dfec5190463 (patch)
treedca3b7866c0148df5f8accda7cd4b27465c22322 /Platform
parent13a22b1db0af2d087f646557ee12dad8cd4b2dce (diff)
downloadedk2-platforms-f84a4e587ab750e5d6dcf9513a985dfec5190463.tar.xz
BroxtonPlatformPkg: Add LpssUartSerailDxe
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang <mang.guo@intel.com>
Diffstat (limited to 'Platform')
-rw-r--r--Platform/BroxtonPlatformPkg/Common/Console/LpssUartSerialDxe/ComponentName.c266
-rw-r--r--Platform/BroxtonPlatformPkg/Common/Console/LpssUartSerialDxe/LpssUartSerailDxe.unibin0 -> 2056 bytes
-rw-r--r--Platform/BroxtonPlatformPkg/Common/Console/LpssUartSerialDxe/LpssUartSerialDxe.inf84
-rw-r--r--Platform/BroxtonPlatformPkg/Common/Console/LpssUartSerialDxe/Serial.c1811
-rw-r--r--Platform/BroxtonPlatformPkg/Common/Console/LpssUartSerialDxe/Serial.h853
5 files changed, 3014 insertions, 0 deletions
diff --git a/Platform/BroxtonPlatformPkg/Common/Console/LpssUartSerialDxe/ComponentName.c b/Platform/BroxtonPlatformPkg/Common/Console/LpssUartSerialDxe/ComponentName.c
new file mode 100644
index 0000000000..a685f781de
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Console/LpssUartSerialDxe/ComponentName.c
@@ -0,0 +1,266 @@
+/** @file
+ UEFI Component Name and Name2 protocol for Isa serial driver.
+
+ Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Serial.h"
+
+#define SERIAL_PORT_NAME "LPSS UART Serial Port # "
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gLpssUartSerialComponentName = {
+ IsaSerialComponentNameGetDriverName,
+ IsaSerialComponentNameGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gLpssUartSerialComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) IsaSerialComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) IsaSerialComponentNameGetControllerName,
+ "en"
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mLpssUartSerialDriverNameTable[] = {
+ {
+ "eng;en",
+ L"Lpss Uart Serial Driver"
+ },
+ {
+ NULL,
+ NULL
+ }
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param[in] Language A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param[out] DriverName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+IsaSerialComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mLpssUartSerialDriverNameTable,
+ DriverName,
+ (BOOLEAN) (This == &gLpssUartSerialComponentName)
+ );
+}
+
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param[in] ControllerHandle The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param[in] ChildHandle The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param[in] Language A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param[out] ControllerName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+IsaSerialComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ EFI_STATUS Status;
+ EFI_SERIAL_IO_PROTOCOL *SerialIo;
+ SERIAL_DEV *SerialDevice;
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Make sure this driver is currently managing ControllerHandle
+ //
+ Status = EfiTestManagedDevice (
+ ControllerHandle,
+ gSerialControllerDriver.DriverBindingHandle,
+ &gEfiIsaIoProtocolGuid
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Get the Block I/O Protocol on Controller
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiSerialIoProtocolGuid,
+ (VOID **) &SerialIo,
+ gSerialControllerDriver.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Get the Serial Controller's Device structure
+ //
+ SerialDevice = SERIAL_DEV_FROM_THIS (SerialIo);
+
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ SerialDevice->ControllerNameTable,
+ ControllerName,
+ (BOOLEAN) (This == &gLpssUartSerialComponentName)
+ );
+}
+
+
+/**
+ Add the ISO639-2 and RFC4646 component name both for the Serial IO device
+
+ @param[in] SerialDevice A pointer to the SERIAL_DEV instance.
+ @param[in] IsaIo A pointer to the EFI_ISA_IO_PROTOCOL instance.
+
+**/
+VOID
+AddName (
+ IN SERIAL_DEV *SerialDevice,
+ IN EFI_ISA_IO_PROTOCOL *IsaIo
+ )
+{
+ CHAR16 SerialPortName[sizeof (SERIAL_PORT_NAME)];
+
+ StrCpyS (SerialPortName, sizeof (SerialPortName) / sizeof (CHAR16), L"LPSS UART Serial Port # ");
+ SerialPortName[sizeof (SERIAL_PORT_NAME) - 2] = (CHAR16) (L'0' + (UINT8) IsaIo->ResourceList->Device.UID);
+ AddUnicodeString2 (
+ "eng",
+ gLpssUartSerialComponentName.SupportedLanguages,
+ &SerialDevice->ControllerNameTable,
+ (CHAR16 *) SerialPortName,
+ TRUE
+ );
+ AddUnicodeString2 (
+ "en",
+ gLpssUartSerialComponentName2.SupportedLanguages,
+ &SerialDevice->ControllerNameTable,
+ (CHAR16 *) SerialPortName,
+ FALSE
+ );
+}
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Console/LpssUartSerialDxe/LpssUartSerailDxe.uni b/Platform/BroxtonPlatformPkg/Common/Console/LpssUartSerialDxe/LpssUartSerailDxe.uni
new file mode 100644
index 0000000000..3136ea79b1
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Console/LpssUartSerialDxe/LpssUartSerailDxe.uni
Binary files differ
diff --git a/Platform/BroxtonPlatformPkg/Common/Console/LpssUartSerialDxe/LpssUartSerialDxe.inf b/Platform/BroxtonPlatformPkg/Common/Console/LpssUartSerialDxe/LpssUartSerialDxe.inf
new file mode 100644
index 0000000000..138cf73104
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Console/LpssUartSerialDxe/LpssUartSerialDxe.inf
@@ -0,0 +1,84 @@
+## @file
+# Serial driver for standard UARTS on an ISA bus.
+#
+# Produces the Serial I/O protocol for standard UARTS using ISA I/O. This driver
+# supports the 8250, 16450, 16550 and 16550A UART types.
+#
+# Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = LpssUartSerialDxe
+ MODULE_UNI_FILE = LpssUartSerialDxe.uni
+ FILE_GUID = 93B80003-9FB3-11d4-9A3A-0090273FC14D
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeIsaSerial
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+# DRIVER_BINDING = gSerialControllerDriver
+# COMPONENT_NAME = gIsaSerialComponentName
+# COMPONENT_NAME2 = gIsaSerialComponentName2
+#
+
+[Sources]
+ ComponentName.c
+ Serial.h
+ Serial.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+
+[LibraryClasses]
+ PcdLib
+ ReportStatusCodeLib
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ BaseMemoryLib
+ DevicePathLib
+ UefiLib
+ UefiDriverEntryPoint
+ DebugLib
+ PchSerialIoLib
+ PchSerialIoUartLib
+ MmPciLib
+ IoLib
+
+[Guids]
+ gEfiUartDevicePathGuid ## SOMETIMES_CONSUMES ## GUID
+
+[Protocols]
+ gEfiIsaIoProtocolGuid ## TO_START
+ gEfiDevicePathProtocolGuid ## TO_START
+ gEfiSerialIoProtocolGuid ## BY_START
+ gEfiDevicePathProtocolGuid ## BY_START
+
+[FeaturePcd]
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdIsaBusSerialUseHalfHandshake|FALSE ## CONSUMES
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate|115200 ## CONSUMES
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits|8 ## CONSUMES
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity|1 ## CONSUMES
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits|1 ## CONSUMES
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ IsaSerialDxeExtra.uni
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Console/LpssUartSerialDxe/Serial.c b/Platform/BroxtonPlatformPkg/Common/Console/LpssUartSerialDxe/Serial.c
new file mode 100644
index 0000000000..fa6a2667e9
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Console/LpssUartSerialDxe/Serial.c
@@ -0,0 +1,1811 @@
+/** @file
+ Serial driver for standard UARTS on an ISA bus.
+
+ Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Serial.h"
+
+//
+// ISA Serial Driver Global Variables
+//
+EFI_DRIVER_BINDING_PROTOCOL gSerialControllerDriver = {
+ SerialControllerDriverSupported,
+ SerialControllerDriverStart,
+ SerialControllerDriverStop,
+ 0xa,
+ NULL,
+ NULL
+};
+
+
+SERIAL_DEV gSerialDevTempate = {
+ SERIAL_DEV_SIGNATURE,
+ NULL,
+ { // SerialIo
+ SERIAL_IO_INTERFACE_REVISION,
+ IsaSerialReset,
+ IsaSerialSetAttributes,
+ IsaSerialSetControl,
+ IsaSerialGetControl,
+ IsaSerialWrite,
+ IsaSerialRead,
+ NULL
+ },
+ { // SerialMode
+ SERIAL_PORT_SUPPORT_CONTROL_MASK,
+ SERIAL_PORT_DEFAULT_TIMEOUT,
+ 0,
+ SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH,
+ 0,
+ 0,
+ 0
+ },
+ NULL,
+ NULL,
+ { // UartDevicePath
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_UART_DP,
+ {
+ (UINT8) (sizeof (UART_DEVICE_PATH)),
+ (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8)
+ }
+ },
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ },
+ NULL,
+ 0, //BaseAddress
+ {
+ 0,
+ 0,
+ SERIAL_MAX_BUFFER_SIZE,
+ { 0 }
+ },
+ {
+ 0,
+ 0,
+ SERIAL_MAX_BUFFER_SIZE,
+ { 0 }
+ },
+ FALSE,
+ FALSE,
+ Uart16550A,
+ NULL
+};
+
+
+/**
+ Check the device path node whether it's the Flow Control node or not.
+
+ @param[in] FlowControl The device path node to be checked.
+
+ @retval TRUE It's the Flow Control node.
+ @retval FALSE It's not.
+
+**/
+BOOLEAN
+IsUartFlowControlNode (
+ IN UART_FLOW_CONTROL_DEVICE_PATH *FlowControl
+ )
+{
+ return (BOOLEAN) (
+ (DevicePathType (FlowControl) == MESSAGING_DEVICE_PATH) &&
+ (DevicePathSubType (FlowControl) == MSG_VENDOR_DP) &&
+ (CompareGuid (&FlowControl->Guid, &gEfiUartDevicePathGuid))
+ );
+}
+
+
+/**
+ Check the device path node whether it contains Flow Control node or not.
+
+ @param[in] DevicePath The device path to be checked.
+
+ @retval TRUE It contains the Flow Control node.
+ @retval FALSE It doesn't.
+
+**/
+BOOLEAN
+ContainsFlowControl (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ while (!IsDevicePathEnd (DevicePath)) {
+ if (IsUartFlowControlNode ((UART_FLOW_CONTROL_DEVICE_PATH *) DevicePath)) {
+ return TRUE;
+ }
+ DevicePath = NextDevicePathNode (DevicePath);
+ }
+
+ return FALSE;
+}
+
+
+/**
+ The user Entry Point for module IsaSerial. The user code starts with this function.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeIsaSerial (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install driver model protocol(s).
+ //
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gSerialControllerDriver,
+ ImageHandle,
+ &gLpssUartSerialComponentName,
+ &gLpssUartSerialComponentName2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+
+/**
+ Check to see if this driver supports the given controller
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] Controller The handle of the controller to test.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path.
+
+ @retval EFI_SUCCESS This driver can support the given controller.
+
+**/
+EFI_STATUS
+EFIAPI
+SerialControllerDriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_ISA_IO_PROTOCOL *IsaIo;
+ UART_DEVICE_PATH *UartNode;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UART_FLOW_CONTROL_DEVICE_PATH *FlowControlNode;
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
+ UINTN EntryCount;
+ UINTN Index;
+ BOOLEAN HasFlowControl;
+
+ //
+ // Check RemainingDevicePath validation
+ //
+ if (RemainingDevicePath != NULL) {
+ //
+ // Check if RemainingDevicePath is the End of Device Path Node,
+ // if yes, go on checking other conditions
+ //
+ if (!IsDevicePathEnd (RemainingDevicePath)) {
+ //
+ // If RemainingDevicePath isn't the End of Device Path Node,
+ // check its validation
+ //
+ Status = EFI_UNSUPPORTED;
+
+ UartNode = (UART_DEVICE_PATH *) RemainingDevicePath;
+ if (UartNode->Header.Type != MESSAGING_DEVICE_PATH ||
+ UartNode->Header.SubType != MSG_UART_DP ||
+ sizeof (UART_DEVICE_PATH) != DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) UartNode)
+ ) {
+ goto Error;
+ }
+
+ if (UartNode->BaudRate > SERIAL_PORT_MAX_BAUD_RATE) {
+ goto Error;
+ }
+
+ if (UartNode->Parity < NoParity || UartNode->Parity > SpaceParity) {
+ goto Error;
+ }
+
+ if (UartNode->DataBits < 5 || UartNode->DataBits > 8) {
+ goto Error;
+ }
+
+ if (UartNode->StopBits < OneStopBit || UartNode->StopBits > TwoStopBits) {
+ goto Error;
+ }
+
+ if ((UartNode->DataBits == 5) && (UartNode->StopBits == TwoStopBits)) {
+ goto Error;
+ }
+
+ if ((UartNode->DataBits >= 6) && (UartNode->DataBits <= 8) && (UartNode->StopBits == OneFiveStopBits)) {
+ goto Error;
+ }
+
+ FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (UartNode);
+ if (IsUartFlowControlNode (FlowControlNode)) {
+ //
+ // If the second node is Flow Control Node,
+ // return error when it request other than hardware flow control.
+ //
+ if ((ReadUnaligned32 (&FlowControlNode->FlowControlMap) & ~UART_FLOW_CONTROL_HARDWARE) != 0) {
+ goto Error;
+ }
+ }
+ }
+ }
+
+ //
+ // Open the IO Abstraction(s) needed to perform the supported test
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiIsaIoProtocolGuid,
+ (VOID **) &IsaIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (Status == EFI_ALREADY_STARTED) {
+ if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) {
+ //
+ // If RemainingDevicePath is NULL or is the End of Device Path Node
+ //
+ return EFI_SUCCESS;
+ }
+ //
+ // When the driver has produced device path with flow control node but RemainingDevicePath only contains UART node,
+ // return unsupported, and vice versa.
+ //
+ Status = gBS->OpenProtocolInformation (
+ Controller,
+ &gEfiIsaIoProtocolGuid,
+ &OpenInfoBuffer,
+ &EntryCount
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ for (Index = 0; Index < EntryCount; Index ++) {
+ if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
+ Status = gBS->OpenProtocol (
+ OpenInfoBuffer[Index].ControllerHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &DevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ HasFlowControl = ContainsFlowControl (RemainingDevicePath);
+ if (HasFlowControl ^ ContainsFlowControl (DevicePath)) {
+ Status = EFI_UNSUPPORTED;
+ }
+ }
+ break;
+ }
+ }
+ FreePool (OpenInfoBuffer);
+ return Status;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Close the I/O Abstraction(s) used to perform the supported test
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiIsaIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
+ // Open the EFI Device Path protocol needed to perform the supported test
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (Status == EFI_ALREADY_STARTED) {
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Use the ISA I/O Protocol to see if Controller is standard ISA UART that
+ // can be managed by this driver.
+ //
+ Status = EFI_SUCCESS;
+ if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x501)) {
+ Status = EFI_UNSUPPORTED;
+ goto Error;
+ }
+
+Error:
+ //
+ // Close protocol, don't use device path protocol in the Support() function
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+}
+
+
+/**
+ Start to manage the controller.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] Controller The handle of the controller to test.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path.
+
+ @retval EFI_SUCCESS Driver is started successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+SerialControllerDriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_ISA_IO_PROTOCOL *IsaIo;
+ SERIAL_DEV *SerialDevice;
+ UINTN Index;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
+ UINTN EntryCount;
+ EFI_SERIAL_IO_PROTOCOL *SerialIo;
+ UART_DEVICE_PATH *Uart;
+
+
+ SerialDevice = NULL;
+ //
+ // Get the Parent Device Path
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
+ return Status;
+ }
+ //
+ // Report status code enable the serial
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_P_PC_ENABLE | EFI_PERIPHERAL_SERIAL_PORT,
+ ParentDevicePath
+ );
+
+ //
+ // Grab the IO abstraction we need to get any work done
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiIsaIoProtocolGuid,
+ (VOID **) &IsaIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
+ goto Error;
+ }
+
+ if (Status == EFI_ALREADY_STARTED) {
+
+ if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) {
+ //
+ // If RemainingDevicePath is NULL or is the End of Device Path Node
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Make sure a child handle does not already exist. This driver can only
+ // produce one child per serial port.
+ //
+ Status = gBS->OpenProtocolInformation (
+ Controller,
+ &gEfiIsaIoProtocolGuid,
+ &OpenInfoBuffer,
+ &EntryCount
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = EFI_ALREADY_STARTED;
+ for (Index = 0; Index < EntryCount; Index ++) {
+ if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
+ Status = gBS->OpenProtocol (
+ OpenInfoBuffer[Index].ControllerHandle,
+ &gEfiSerialIoProtocolGuid,
+ (VOID **) &SerialIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ Uart = (UART_DEVICE_PATH *) RemainingDevicePath;
+ }
+ break;
+ }
+ }
+
+ FreePool (OpenInfoBuffer);
+ return Status;
+ }
+
+ if (RemainingDevicePath != NULL) {
+ if (IsDevicePathEnd (RemainingDevicePath)) {
+ //
+ // If RemainingDevicePath is the End of Device Path Node,
+ // skip enumerate any device and return EFI_SUCESSS
+ //
+ return EFI_SUCCESS;
+ }
+ }
+
+ //
+ // Initialize the serial device instance
+ //
+ SerialDevice = AllocateCopyPool (sizeof (SERIAL_DEV), &gSerialDevTempate);
+ if (SerialDevice == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ SerialDevice->SerialIo.Mode = &(SerialDevice->SerialMode);
+ SerialDevice->IsaIo = IsaIo;
+ SerialDevice->ParentDevicePath = ParentDevicePath;
+
+ //
+ // Check if RemainingDevicePath is NULL,
+ // if yes, use the values from the gSerialDevTempate as no remaining device path was
+ // passed in.
+ //
+ if (RemainingDevicePath != NULL) {
+ //
+ // If RemainingDevicePath isn't NULL,
+ // match the configuration of the RemainingDevicePath. IsHandleSupported()
+ // already checked to make sure the RemainingDevicePath contains settings
+ // that we can support.
+ //
+ CopyMem (&SerialDevice->UartDevicePath, RemainingDevicePath, sizeof (UART_DEVICE_PATH));
+ }
+
+ SerialDevice->HardwareFlowControl = UART_FLOW_CONTROL_HARDWARE;
+
+ //
+ // Report status code the serial present
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_P_PC_PRESENCE_DETECT | EFI_PERIPHERAL_SERIAL_PORT,
+ ParentDevicePath
+ );
+
+ //
+ // Build the device path by appending the UART node to the ParentDevicePath.
+ // The Uart setings are zero here, since SetAttribute() will update them to match
+ // the default setings.
+ //
+ SerialDevice->DevicePath = AppendDevicePathNode (
+ ParentDevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &SerialDevice->UartDevicePath
+ );
+
+
+ //
+ // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
+ //
+ SerialDevice->SerialMode.BaudRate = SerialDevice->UartDevicePath.BaudRate;
+ SerialDevice->SerialMode.DataBits = SerialDevice->UartDevicePath.DataBits;
+ SerialDevice->SerialMode.Parity = SerialDevice->UartDevicePath.Parity;
+ SerialDevice->SerialMode.StopBits = SerialDevice->UartDevicePath.StopBits;
+
+ //
+ // Install protocol interfaces for the serial device.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &SerialDevice->Handle,
+ &gEfiDevicePathProtocolGuid,
+ SerialDevice->DevicePath,
+ &gEfiSerialIoProtocolGuid,
+ &SerialDevice->SerialIo,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ //
+ // Open For Child Device
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiIsaIoProtocolGuid,
+ (VOID **) &IsaIo,
+ This->DriverBindingHandle,
+ SerialDevice->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+
+Error:
+ if (EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiIsaIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ if (SerialDevice != NULL) {
+ if (SerialDevice->DevicePath != NULL) {
+ gBS->FreePool (SerialDevice->DevicePath);
+ }
+
+ FreeUnicodeStringTable (SerialDevice->ControllerNameTable);
+ gBS->FreePool (SerialDevice);
+ }
+ }
+
+ return Status;
+}
+
+
+/**
+ Disconnect this driver with the controller, uninstall related protocol instance
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] Controller The handle of the controller to test.
+ @param[in] NumberOfChildren Number of child device.
+ @param[in] ChildHandleBuffer A pointer to the remaining portion of a device path.
+
+ @retval EFI_SUCCESS Operation successfully
+ @retval EFI_DEVICE_ERROR Cannot stop the driver successfully
+
+**/
+EFI_STATUS
+EFIAPI
+SerialControllerDriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ BOOLEAN AllChildrenStopped;
+ EFI_SERIAL_IO_PROTOCOL *SerialIo;
+ SERIAL_DEV *SerialDevice;
+ EFI_ISA_IO_PROTOCOL *IsaIo;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ Status = gBS->HandleProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &DevicePath
+ );
+
+ //
+ // Report the status code disable the serial
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_P_PC_DISABLE | EFI_PERIPHERAL_SERIAL_PORT,
+ DevicePath
+ );
+
+ //
+ // Complete all outstanding transactions to Controller.
+ // Don't allow any new transaction to Controller to be started.
+ //
+ if (NumberOfChildren == 0) {
+ //
+ // Close the bus driver
+ //
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiIsaIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return Status;
+ }
+
+ AllChildrenStopped = TRUE;
+
+ for (Index = 0; Index < NumberOfChildren; Index++) {
+
+ Status = gBS->OpenProtocol (
+ ChildHandleBuffer[Index],
+ &gEfiSerialIoProtocolGuid,
+ (VOID **) &SerialIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+
+ SerialDevice = SERIAL_DEV_FROM_THIS (SerialIo);
+
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiIsaIoProtocolGuid,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index]
+ );
+
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ ChildHandleBuffer[Index],
+ &gEfiDevicePathProtocolGuid,
+ SerialDevice->DevicePath,
+ &gEfiSerialIoProtocolGuid,
+ &SerialDevice->SerialIo,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiIsaIoProtocolGuid,
+ (VOID **) &IsaIo,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index],
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ } else {
+ if (SerialDevice->DevicePath != NULL) {
+ gBS->FreePool (SerialDevice->DevicePath);
+ }
+
+ FreeUnicodeStringTable (SerialDevice->ControllerNameTable);
+ gBS->FreePool (SerialDevice);
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ AllChildrenStopped = FALSE;
+ }
+ }
+
+ if (!AllChildrenStopped) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Detect whether specific FIFO is full or not.
+
+ @param[in] Fifo A pointer to the Data Structure SERIAL_DEV_FIFO.
+
+ @return whether specific FIFO is full or not.
+
+**/
+BOOLEAN
+IsaSerialFifoFull (
+ IN SERIAL_DEV_FIFO *Fifo
+ )
+{
+ if (Fifo->Surplus == 0) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/**
+ Detect whether specific FIFO is empty or not.
+
+ @param[in] Fifo A pointer to the Data Structure SERIAL_DEV_FIFO.
+
+ @return whether specific FIFO is empty or not.
+
+**/
+BOOLEAN
+IsaSerialFifoEmpty (
+ IN SERIAL_DEV_FIFO *Fifo
+ )
+{
+ if (Fifo->Surplus == SERIAL_MAX_BUFFER_SIZE) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/**
+ Add data to specific FIFO.
+
+ @param[in] Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
+ @param[in] Data the data added to FIFO
+
+ @retval EFI_SUCCESS Add data to specific FIFO successfully
+ @retval EFI_OUT_OF_RESOURCE Failed to add data because FIFO is already full
+
+**/
+EFI_STATUS
+IsaSerialFifoAdd (
+ IN SERIAL_DEV_FIFO *Fifo,
+ IN UINT8 Data
+ )
+{
+ //
+ // if FIFO full can not add data
+ //
+ if (IsaSerialFifoFull (Fifo)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // FIFO is not full can add data
+ //
+ Fifo->Data[Fifo->Last] = Data;
+ Fifo->Surplus--;
+ Fifo->Last++;
+ if (Fifo->Last == SERIAL_MAX_BUFFER_SIZE) {
+ Fifo->Last = 0;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Remove data from specific FIFO.
+
+ @param[in] Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
+ @param[in] Data the data removed from FIFO
+
+ @retval EFI_SUCCESS Remove data from specific FIFO successfully
+ @retval EFI_OUT_OF_RESOURCE Failed to remove data because FIFO is empty
+
+**/
+EFI_STATUS
+IsaSerialFifoRemove (
+ IN SERIAL_DEV_FIFO *Fifo,
+ OUT UINT8 *Data
+ )
+{
+ //
+ // if FIFO is empty, no data can remove
+ //
+ if (IsaSerialFifoEmpty (Fifo)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // FIFO is not empty, can remove data
+ //
+ *Data = Fifo->Data[Fifo->First];
+ Fifo->Surplus++;
+ Fifo->First++;
+ if (Fifo->First == SERIAL_MAX_BUFFER_SIZE) {
+ Fifo->First = 0;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Reads and writes all avaliable data.
+
+ @param[in] SerialDevice The device to flush
+
+ @retval EFI_SUCCESS Data was read/written successfully.
+ @retval EFI_OUT_OF_RESOURCE Failed because software receive FIFO is full. Note, when
+ this happens, pending writes are not done.
+
+**/
+EFI_STATUS
+IsaSerialReceiveTransmit (
+ IN SERIAL_DEV *SerialDevice
+ )
+{
+ SERIAL_PORT_LSR Lsr;
+ UINT8 Data;
+ BOOLEAN ReceiveFifoFull;
+ SERIAL_PORT_MSR Msr;
+ SERIAL_PORT_MCR Mcr;
+ UINTN TimeOut;
+
+ Data = 0;
+
+ //
+ // Begin the read or write
+ //
+ if (SerialDevice->SoftwareLoopbackEnable) {
+ do {
+ ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive);
+ if (!IsaSerialFifoEmpty (&SerialDevice->Transmit)) {
+ IsaSerialFifoRemove (&SerialDevice->Transmit, &Data);
+ if (ReceiveFifoFull) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ IsaSerialFifoAdd (&SerialDevice->Receive, Data);
+ }
+ } while (!IsaSerialFifoEmpty (&SerialDevice->Transmit));
+ } else {
+ ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive);
+ //
+ // For full handshake flow control, tell the peer to send data
+ // if receive buffer is available.
+ //
+ if (SerialDevice->HardwareFlowControl &&
+ !FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake)&&
+ !ReceiveFifoFull
+ ) {
+ Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
+ Mcr.Bits.Rts = 1;
+ WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);
+ }
+ do {
+ Lsr.Data = READ_LSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
+
+ //
+ // Flush incomming data to prevent a an overrun during a long write
+ //
+ if ((Lsr.Bits.Dr == 1) && !ReceiveFifoFull) {
+ ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive);
+ if (!ReceiveFifoFull) {
+ if (Lsr.Bits.FIFOe == 1 || Lsr.Bits.Oe == 1 || Lsr.Bits.Pe == 1 || Lsr.Bits.Fe == 1 || Lsr.Bits.Bi == 1) {
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_ERROR_CODE,
+ EFI_P_EC_INPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT,
+ SerialDevice->DevicePath
+ );
+ if (Lsr.Bits.FIFOe == 1 || Lsr.Bits.Pe == 1|| Lsr.Bits.Fe == 1 || Lsr.Bits.Bi == 1) {
+ Data = READ_RBR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
+ continue;
+ }
+ }
+
+ Data = READ_RBR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
+
+ IsaSerialFifoAdd (&SerialDevice->Receive, Data);
+
+ //
+ // For full handshake flow control, if receive buffer full
+ // tell the peer to stop sending data.
+ //
+ if (SerialDevice->HardwareFlowControl &&
+ !FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake) &&
+ IsaSerialFifoFull (&SerialDevice->Receive)
+ ) {
+ Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
+ Mcr.Bits.Rts = 0;
+ WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);
+ }
+
+
+ continue;
+ } else {
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_P_SERIAL_PORT_PC_CLEAR_BUFFER | EFI_PERIPHERAL_SERIAL_PORT,
+ SerialDevice->DevicePath
+ );
+ }
+ }
+ //
+ // Do the write
+ //
+ if (Lsr.Bits.Thre == 1 && !IsaSerialFifoEmpty (&SerialDevice->Transmit)) {
+ //
+ // Make sure the transmit data will not be missed
+ //
+ if (SerialDevice->HardwareFlowControl) {
+ //
+ // For half handshake flow control assert RTS before sending.
+ //
+ if (FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake)) {
+ Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
+ Mcr.Bits.Rts= 0;
+ WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);
+ }
+ //
+ // Wait for CTS
+ //
+ TimeOut = 0;
+ Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
+ while ((Msr.Bits.Dcd == 1) && ((Msr.Bits.Cts == 0) ^ FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake))) {
+ gBS->Stall (TIMEOUT_STALL_INTERVAL);
+ TimeOut++;
+ if (TimeOut > 5) {
+ break;
+ }
+
+ Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
+ }
+
+ if ((Msr.Bits.Dcd == 0) || ((Msr.Bits.Cts == 1) ^ FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake))) {
+ IsaSerialFifoRemove (&SerialDevice->Transmit, &Data);
+ WRITE_THR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Data);
+ }
+
+ //
+ // For half handshake flow control, tell DCE we are done.
+ //
+ if (FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake)) {
+ Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
+ Mcr.Bits.Rts = 1;
+ WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);
+ }
+ } else {
+ IsaSerialFifoRemove (&SerialDevice->Transmit, &Data);
+ WRITE_THR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Data);
+ }
+ }
+ } while (Lsr.Bits.Thre == 1 && !IsaSerialFifoEmpty (&SerialDevice->Transmit));
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Reset serial device.
+
+ @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL
+
+ @retval EFI_SUCCESS Reset successfully
+ @retval EFI_DEVICE_ERROR Failed to reset
+
+**/
+EFI_STATUS
+EFIAPI
+IsaSerialReset (
+ IN EFI_SERIAL_IO_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ SERIAL_DEV *SerialDevice;
+ SERIAL_PORT_LCR Lcr;
+ SERIAL_PORT_IER Ier;
+ SERIAL_PORT_MCR Mcr;
+ SERIAL_PORT_FCR Fcr;
+ EFI_TPL Tpl;
+ UINT32 Control;
+
+ SerialDevice = SERIAL_DEV_FROM_THIS (This);
+
+ //
+ // Report the status code reset the serial
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_P_PC_RESET | EFI_PERIPHERAL_SERIAL_PORT,
+ SerialDevice->DevicePath
+ );
+
+ Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ //
+ // Make sure DLAB is 0.
+ //
+ Lcr.Data = READ_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
+ Lcr.Bits.DLab = 0;
+ WRITE_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Lcr.Data);
+
+ //
+ // Turn off all interrupts
+ //
+ Ier.Data = READ_IER (SerialDevice->IsaIo, SerialDevice->BaseAddress);
+ Ier.Bits.Ravie = 0;
+ Ier.Bits.Theie = 0;
+ Ier.Bits.Rie = 0;
+ Ier.Bits.Mie = 0;
+ WRITE_IER (SerialDevice->IsaIo, SerialDevice->BaseAddress, Ier.Data);
+
+ //
+ // Disable the FIFO.
+ //
+ Fcr.Bits.TrFIFOE = 0;
+ WRITE_FCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Fcr.Data);
+
+ //
+ // Turn off loopback and disable device interrupt.
+ //
+ Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
+ Mcr.Bits.Out1 = 0;
+ Mcr.Bits.Out2 = 0;
+ Mcr.Bits.Lme = 0;
+ WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);
+
+ //
+ // Clear the scratch pad register
+ //
+ WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, 0);
+
+
+ if (EFI_ERROR (Status)) {
+ gBS->RestoreTPL (Tpl);
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Go set the current control bits
+ //
+ Control = 0;
+ if (SerialDevice->HardwareFlowControl) {
+ Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
+ }
+ if (SerialDevice->SoftwareLoopbackEnable) {
+ Control |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;
+ }
+ //
+ // for 16550A enable FIFO, 16550 disable FIFO
+ //
+ Fcr.Bits.TrFIFOE = 1;
+ Fcr.Bits.ResetRF = 1;
+ Fcr.Bits.ResetTF = 1;
+ WRITE_FCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Fcr.Data);
+
+ //
+ // Reset the software FIFO
+ //
+ SerialDevice->Receive.First = 0;
+ SerialDevice->Receive.Last = 0;
+ SerialDevice->Receive.Surplus = SERIAL_MAX_BUFFER_SIZE;
+ SerialDevice->Transmit.First = 0;
+ SerialDevice->Transmit.Last = 0;
+ SerialDevice->Transmit.Surplus = SERIAL_MAX_BUFFER_SIZE;
+
+ gBS->RestoreTPL (Tpl);
+
+ //
+ // Device reset is complete
+ //
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Set new attributes to a serial device.
+
+ @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param[in] BaudRate The baudrate of the serial device
+ @param[in] ReceiveFifoDepth The depth of receive FIFO buffer
+ @param[in] Timeout The request timeout for a single char
+ @param[in] Parity The type of parity used in serial device
+ @param[in] DataBits Number of databits used in serial device
+ @param[in] StopBits Number of stopbits used in serial device
+
+ @retval EFI_SUCCESS The new attributes were set
+ @retval EFI_INVALID_PARAMETERS One or more attributes have an unsupported value
+ @retval EFI_UNSUPPORTED Data Bits can not set to 5 or 6
+ @retval EFI_DEVICE_ERROR The serial device is not functioning correctly (no return)
+
+**/
+EFI_STATUS
+EFIAPI
+IsaSerialSetAttributes (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN UINT64 BaudRate,
+ IN UINT32 ReceiveFifoDepth,
+ IN UINT32 Timeout,
+ IN EFI_PARITY_TYPE Parity,
+ IN UINT8 DataBits,
+ IN EFI_STOP_BITS_TYPE StopBits
+ )
+{
+ EFI_STATUS Status;
+ SERIAL_DEV *SerialDevice;
+ UINT32 Divisor;
+ UINT32 Remained;
+ SERIAL_PORT_LCR Lcr;
+ UART_DEVICE_PATH *Uart;
+ EFI_TPL Tpl;
+
+ SerialDevice = SERIAL_DEV_FROM_THIS (This);
+
+ //
+ // Check for default settings and fill in actual values.
+ //
+ if (BaudRate == 0) {
+ BaudRate = PcdGet64 (PcdUartDefaultBaudRate);
+ }
+
+ if (ReceiveFifoDepth == 0) {
+ ReceiveFifoDepth = SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH;
+ }
+
+ if (Timeout == 0) {
+ Timeout = SERIAL_PORT_DEFAULT_TIMEOUT;
+ }
+
+ if (Parity == DefaultParity) {
+ Parity = (EFI_PARITY_TYPE) PcdGet8 (PcdUartDefaultParity);
+ }
+
+ if (DataBits == 0) {
+ DataBits = PcdGet8 (PcdUartDefaultDataBits);
+ }
+
+ if (StopBits == DefaultStopBits) {
+ StopBits = (EFI_STOP_BITS_TYPE) PcdGet8 (PcdUartDefaultStopBits);
+ }
+ //
+ // 5 and 6 data bits can not be verified on a 16550A UART
+ // Return EFI_INVALID_PARAMETER if an attempt is made to use these settings.
+ //
+ if ((DataBits == 5) || (DataBits == 6)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Make sure all parameters are valid
+ //
+ if ((BaudRate > SERIAL_PORT_MAX_BAUD_RATE) || (BaudRate < SERIAL_PORT_MIN_BAUD_RATE)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BaudRate < 75) {
+ BaudRate = 50;
+ } else if (BaudRate < 110) {
+ BaudRate = 75;
+ } else if (BaudRate < 134) {
+ BaudRate = 110;
+ } else if (BaudRate < 150) {
+ BaudRate = 134;
+ } else if (BaudRate < 300) {
+ BaudRate = 150;
+ } else if (BaudRate < 600) {
+ BaudRate = 300;
+ } else if (BaudRate < 1200) {
+ BaudRate = 600;
+ } else if (BaudRate < 1800) {
+ BaudRate = 1200;
+ } else if (BaudRate < 2000) {
+ BaudRate = 1800;
+ } else if (BaudRate < 2400) {
+ BaudRate = 2000;
+ } else if (BaudRate < 3600) {
+ BaudRate = 2400;
+ } else if (BaudRate < 4800) {
+ BaudRate = 3600;
+ } else if (BaudRate < 7200) {
+ BaudRate = 4800;
+ } else if (BaudRate < 9600) {
+ BaudRate = 7200;
+ } else if (BaudRate < 19200) {
+ BaudRate = 9600;
+ } else if (BaudRate < 38400) {
+ BaudRate = 19200;
+ } else if (BaudRate < 57600) {
+ BaudRate = 38400;
+ } else if (BaudRate < 115200) {
+ BaudRate = 57600;
+ } else if (BaudRate <= SERIAL_PORT_MAX_BAUD_RATE) {
+ BaudRate = 115200;
+ }
+
+ if ((ReceiveFifoDepth < 1) || (ReceiveFifoDepth > SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Timeout < SERIAL_PORT_MIN_TIMEOUT) || (Timeout > SERIAL_PORT_MAX_TIMEOUT)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Parity < NoParity) || (Parity > SpaceParity)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((DataBits < 5) || (DataBits > 8)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((StopBits < OneStopBit) || (StopBits > TwoStopBits)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits
+ //
+ if ((DataBits >= 6) && (DataBits <= 8) && (StopBits == OneFiveStopBits)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Compute divisor use to program the baud rate using a round determination
+ //
+ Divisor = (UINT32) DivU64x32Remainder (
+ SERIAL_PORT_INPUT_CLOCK,
+ ((UINT32) BaudRate * 16),
+ &Remained
+ );
+ if (Remained != 0) {
+ Divisor += 1;
+ }
+
+ if ((Divisor == 0) || ((Divisor & 0xffff0000) != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ //
+ // Compute the actual baud rate that the serial port will be programmed for.
+ //
+ BaudRate = SERIAL_PORT_INPUT_CLOCK / Divisor / 16;
+
+ //
+ // Put serial port on Divisor Latch Mode
+ //
+ Lcr.Data = READ_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
+ Lcr.Bits.DLab = 1;
+ WRITE_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Lcr.Data);
+
+ //
+ // Write the divisor to the serial port
+ //
+ WRITE_DLL (SerialDevice->IsaIo, SerialDevice->BaseAddress, (UINT8) (Divisor & 0xff));
+ WRITE_DLM (SerialDevice->IsaIo, SerialDevice->BaseAddress, (UINT8) ((Divisor >> 8) & 0xff));
+
+ //
+ // Put serial port back in normal mode and set remaining attributes.
+ //
+ Lcr.Bits.DLab = 0;
+
+ switch (Parity) {
+ case NoParity:
+ Lcr.Bits.ParEn = 0;
+ Lcr.Bits.EvenPar = 0;
+ Lcr.Bits.SticPar = 0;
+ break;
+
+ case EvenParity:
+ Lcr.Bits.ParEn = 1;
+ Lcr.Bits.EvenPar = 1;
+ Lcr.Bits.SticPar = 0;
+ break;
+
+ case OddParity:
+ Lcr.Bits.ParEn = 1;
+ Lcr.Bits.EvenPar = 0;
+ Lcr.Bits.SticPar = 0;
+ break;
+
+ case SpaceParity:
+ Lcr.Bits.ParEn = 1;
+ Lcr.Bits.EvenPar = 1;
+ Lcr.Bits.SticPar = 1;
+ break;
+
+ case MarkParity:
+ Lcr.Bits.ParEn = 1;
+ Lcr.Bits.EvenPar = 0;
+ Lcr.Bits.SticPar = 1;
+ break;
+
+ default:
+ break;
+ }
+
+ switch (StopBits) {
+ case OneStopBit:
+ Lcr.Bits.StopB = 0;
+ break;
+
+ case OneFiveStopBits:
+ case TwoStopBits:
+ Lcr.Bits.StopB = 1;
+ break;
+
+ default:
+ break;
+ }
+
+ //
+ // DataBits
+ //
+ Lcr.Bits.SerialDB = (UINT8) ((DataBits - 5) & 0x03);
+ WRITE_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Lcr.Data);
+
+ //
+ // Set the Serial I/O mode
+ //
+ This->Mode->BaudRate = BaudRate;
+ This->Mode->ReceiveFifoDepth = ReceiveFifoDepth;
+ This->Mode->Timeout = Timeout;
+ This->Mode->Parity = Parity;
+ This->Mode->DataBits = DataBits;
+ This->Mode->StopBits = StopBits;
+
+ //
+ // See if Device Path Node has actually changed
+ //
+ if (SerialDevice->UartDevicePath.BaudRate == BaudRate &&
+ SerialDevice->UartDevicePath.DataBits == DataBits &&
+ SerialDevice->UartDevicePath.Parity == Parity &&
+ SerialDevice->UartDevicePath.StopBits == StopBits
+ ) {
+ gBS->RestoreTPL (Tpl);
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Update the device path
+ //
+ SerialDevice->UartDevicePath.BaudRate = BaudRate;
+ SerialDevice->UartDevicePath.DataBits = DataBits;
+ SerialDevice->UartDevicePath.Parity = (UINT8) Parity;
+ SerialDevice->UartDevicePath.StopBits = (UINT8) StopBits;
+
+ Status = EFI_SUCCESS;
+ if (SerialDevice->Handle != NULL) {
+ Uart = (UART_DEVICE_PATH *) (
+ (UINTN) SerialDevice->DevicePath
+ + GetDevicePathSize (SerialDevice->ParentDevicePath)
+ - END_DEVICE_PATH_LENGTH
+ );
+ CopyMem (Uart, &SerialDevice->UartDevicePath, sizeof (UART_DEVICE_PATH));
+ Status = gBS->ReinstallProtocolInterface (
+ SerialDevice->Handle,
+ &gEfiDevicePathProtocolGuid,
+ SerialDevice->DevicePath,
+ SerialDevice->DevicePath
+ );
+ }
+
+ gBS->RestoreTPL (Tpl);
+
+ return Status;
+}
+
+
+/**
+ Set Control Bits.
+
+ @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param[in] Control Control bits that can be settable
+
+ @retval EFI_SUCCESS New Control bits were set successfully
+ @retval EFI_UNSUPPORTED The Control bits wanted to set are not supported
+
+**/
+EFI_STATUS
+EFIAPI
+IsaSerialSetControl (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN UINT32 Control
+ )
+{
+ SERIAL_DEV *SerialDevice;
+ SERIAL_PORT_MCR Mcr;
+ EFI_TPL Tpl;
+ UART_FLOW_CONTROL_DEVICE_PATH *FlowControl;
+ EFI_STATUS Status;
+
+ //
+ // The control bits that can be set are :
+ // EFI_SERIAL_DATA_TERMINAL_READY: 0x0001 // WO
+ // EFI_SERIAL_REQUEST_TO_SEND: 0x0002 // WO
+ // EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE: 0x1000 // RW
+ // EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE: 0x2000 // RW
+ // EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE: 0x4000 // RW
+ //
+ SerialDevice = SERIAL_DEV_FROM_THIS (This);
+
+ //
+ // 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 EFI_UNSUPPORTED;
+ }
+
+ Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
+ Mcr.Bits.DtrC = 0;
+ Mcr.Bits.Rts = 0;
+ Mcr.Bits.Lme = 0;
+ SerialDevice->SoftwareLoopbackEnable = FALSE;
+ SerialDevice->HardwareFlowControl = FALSE;
+
+ if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) == EFI_SERIAL_DATA_TERMINAL_READY) {
+ Mcr.Bits.DtrC = 1;
+ }
+
+ if ((Control & EFI_SERIAL_REQUEST_TO_SEND) == EFI_SERIAL_REQUEST_TO_SEND) {
+ Mcr.Bits.Rts = 1;
+ }
+
+ if ((Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) == EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) {
+ Mcr.Bits.Lme = 1;
+ }
+
+ if ((Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) == EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {
+ SerialDevice->HardwareFlowControl = TRUE;
+ }
+
+ WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);
+
+ if ((Control & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) == EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) {
+ SerialDevice->SoftwareLoopbackEnable = TRUE;
+ }
+
+ Status = EFI_SUCCESS;
+ if (SerialDevice->Handle != NULL) {
+ FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) (
+ (UINTN) SerialDevice->DevicePath
+ + GetDevicePathSize (SerialDevice->ParentDevicePath)
+ - END_DEVICE_PATH_LENGTH
+ + sizeof (UART_DEVICE_PATH)
+ );
+ if (IsUartFlowControlNode (FlowControl) &&
+ ((ReadUnaligned32 (&FlowControl->FlowControlMap) == UART_FLOW_CONTROL_HARDWARE) ^ SerialDevice->HardwareFlowControl)) {
+ //
+ // Flow Control setting is changed, need to reinstall device path protocol
+ //
+ WriteUnaligned32 (&FlowControl->FlowControlMap, SerialDevice->HardwareFlowControl ? UART_FLOW_CONTROL_HARDWARE : 0);
+ Status = gBS->ReinstallProtocolInterface (
+ SerialDevice->Handle,
+ &gEfiDevicePathProtocolGuid,
+ SerialDevice->DevicePath,
+ SerialDevice->DevicePath
+ );
+ }
+ }
+
+ gBS->RestoreTPL (Tpl);
+
+ return Status;
+}
+
+
+/**
+ Get Control Bits.
+
+ @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param[out] Control Control signals of the serial device
+
+ @retval EFI_SUCCESS Get Control signals successfully
+
+**/
+EFI_STATUS
+EFIAPI
+IsaSerialGetControl (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ OUT UINT32 *Control
+ )
+{
+ SERIAL_DEV *SerialDevice;
+ SERIAL_PORT_MSR Msr;
+ SERIAL_PORT_MCR Mcr;
+ EFI_TPL Tpl;
+
+ Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ SerialDevice = SERIAL_DEV_FROM_THIS (This);
+
+ *Control = 0;
+
+ //
+ // Read the Modem Status Register
+ //
+ Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
+
+ if (Msr.Bits.Cts == 1) {
+ *Control |= EFI_SERIAL_CLEAR_TO_SEND;
+ }
+
+ if (Msr.Bits.Dsr == 1) {
+ *Control |= EFI_SERIAL_DATA_SET_READY;
+ }
+
+ if (Msr.Bits.Ri == 1) {
+ *Control |= EFI_SERIAL_RING_INDICATE;
+ }
+
+ if (Msr.Bits.Dcd == 1) {
+ *Control |= EFI_SERIAL_CARRIER_DETECT;
+ }
+ //
+ // Read the Modem Control Register
+ //
+ Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
+
+ if (Mcr.Bits.DtrC == 1) {
+ *Control |= EFI_SERIAL_DATA_TERMINAL_READY;
+ }
+
+ if (Mcr.Bits.Rts == 1) {
+ *Control |= EFI_SERIAL_REQUEST_TO_SEND;
+ }
+
+ if (Mcr.Bits.Lme == 1) {
+ *Control |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;
+ }
+
+ if (SerialDevice->HardwareFlowControl) {
+ *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
+ }
+ //
+ // See if the Transmit FIFO is empty
+ //
+ IsaSerialReceiveTransmit (SerialDevice);
+
+ if (IsaSerialFifoEmpty (&SerialDevice->Transmit)) {
+ *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
+ }
+ //
+ // See if the Receive FIFO is empty.
+ //
+ IsaSerialReceiveTransmit (SerialDevice);
+
+ if (IsaSerialFifoEmpty (&SerialDevice->Receive)) {
+ *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
+ }
+
+ if (SerialDevice->SoftwareLoopbackEnable) {
+ *Control |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;
+ }
+
+ gBS->RestoreTPL (Tpl);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Write the specified number of bytes to serial device.
+
+ @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param[in, out] BufferSize On input the size of Buffer, on output the amount of
+ data actually written
+ @param[in] Buffer The buffer of data to write
+
+ @retval EFI_SUCCESS The data were written successfully
+ @retval EFI_DEVICE_ERROR The device reported an error
+ @retval EFI_TIMEOUT The write operation was stopped due to timeout
+
+**/
+EFI_STATUS
+EFIAPI
+IsaSerialWrite (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ )
+{
+ UINT8 *CharBuffer;
+ EFI_TPL Tpl;
+
+ if (*BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ CharBuffer = (UINT8 *) Buffer;
+
+ PchSerialIoUartOut (Uart2, CharBuffer, *BufferSize);
+
+ gBS->RestoreTPL (Tpl);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Read the specified number of bytes from serial device.
+
+ @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param[in, out] BufferSize On input the size of Buffer, on output the amount of
+ data returned in buffer
+ @param[out] Buffer The buffer to return the data into
+
+ @retval EFI_SUCCESS The data were read successfully
+ @retval EFI_DEVICE_ERROR The device reported an error
+ @retval EFI_TIMEOUT The read operation was stopped due to timeout
+
+**/
+EFI_STATUS
+EFIAPI
+IsaSerialRead (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ SERIAL_DEV *SerialDevice;
+ EFI_TPL Tpl;
+
+ SerialDevice = SERIAL_DEV_FROM_THIS (This);
+
+ if (*BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ *BufferSize = PchSerialIoUartIn(Uart2, Buffer, *BufferSize, FALSE);
+
+ gBS->RestoreTPL (Tpl);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Use scratchpad register to test if this serial port is present.
+
+ @param[in] SerialDevice Pointer to serial device structure
+
+ @return if this serial port is present
+
+**/
+BOOLEAN
+IsaSerialPortPresent (
+ IN SERIAL_DEV *SerialDevice
+ )
+{
+ UINT8 Temp;
+ BOOLEAN Status;
+
+ Status = TRUE;
+
+ //
+ // Save SCR reg
+ //
+ Temp = READ_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
+ WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, 0xAA);
+
+ if (READ_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress) != 0xAA) {
+ Status = FALSE;
+ }
+
+ WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, 0x55);
+
+ if (READ_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress) != 0x55) {
+ Status = FALSE;
+ }
+ //
+ // Restore SCR
+ //
+ WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Temp);
+
+ return Status;
+}
+
+
+/**
+ Use IsaIo protocol to read serial port.
+
+ @param[in] IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance
+ @param[in] BaseAddress Serial port register group base address
+ @param[in] Offset Offset in register group
+
+ @return Data read from serial port
+
+**/
+UINT8
+IsaSerialReadPort (
+ IN EFI_ISA_IO_PROTOCOL *IsaIo,
+ IN UINT16 BaseAddress,
+ IN UINT32 Offset
+ )
+{
+ UINT8 Data;
+
+ //
+ // Use IsaIo to access IO
+ //
+ IsaIo->Io.Read (
+ IsaIo,
+ EfiIsaIoWidthUint8,
+ BaseAddress + Offset,
+ 1,
+ &Data
+ );
+
+ return Data;
+}
+
+
+/**
+ Use IsaIo protocol to write serial port.
+
+ @param[in] IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance
+ @param[in] BaseAddress Serial port register group base address
+ @param[in] Offset Offset in register group
+ @param[in] Data data which is to be written to some serial port register
+
+**/
+VOID
+IsaSerialWritePort (
+ IN EFI_ISA_IO_PROTOCOL *IsaIo,
+ IN UINT16 BaseAddress,
+ IN UINT32 Offset,
+ IN UINT8 Data
+ )
+{
+ //
+ // Use IsaIo to access IO
+ //
+ IsaIo->Io.Write (
+ IsaIo,
+ EfiIsaIoWidthUint8,
+ BaseAddress + Offset,
+ 1,
+ &Data
+ );
+}
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Console/LpssUartSerialDxe/Serial.h b/Platform/BroxtonPlatformPkg/Common/Console/LpssUartSerialDxe/Serial.h
new file mode 100644
index 0000000000..5be600e0d2
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/Console/LpssUartSerialDxe/Serial.h
@@ -0,0 +1,853 @@
+/** @file
+ Include for Serial Driver
+
+ Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SERIAL_H_
+#define _SERIAL_H_
+
+#include <FrameworkDxe.h>
+#include <Protocol/IsaIo.h>
+#include <Protocol/SerialIo.h>
+#include <Protocol/DevicePath.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/PcdLib.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/ScSerialIoUartLib.h>
+#include <Library/PeiDxeSmmMmPciLib.h>
+
+//
+// Driver Binding Externs
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gSerialControllerDriver;
+extern EFI_COMPONENT_NAME_PROTOCOL gLpssUartSerialComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gLpssUartSerialComponentName2;
+
+//
+// Internal Data Structures
+//
+#define SERIAL_DEV_SIGNATURE SIGNATURE_32 ('s', 'e', 'r', 'd')
+#define SERIAL_MAX_BUFFER_SIZE 16
+#define TIMEOUT_STALL_INTERVAL 10
+
+//
+// Name: SERIAL_DEV_FIFO
+// Purpose: To define Receive FIFO and Transmit FIFO
+// Context: Used by serial data transmit and receive
+// Fields:
+// First UINT32: The index of the first data in array Data[]
+// Last UINT32: The index, which you can put a new data into array Data[]
+// Surplus UINT32: Identify how many data you can put into array Data[]
+// Data[] UINT8 : An array, which used to store data
+//
+typedef struct {
+ UINT32 First;
+ UINT32 Last;
+ UINT32 Surplus;
+ UINT8 Data[SERIAL_MAX_BUFFER_SIZE];
+} SERIAL_DEV_FIFO;
+
+typedef enum {
+ Uart8250 = 0,
+ Uart16450 = 1,
+ Uart16550 = 2,
+ Uart16550A= 3
+} EFI_UART_TYPE;
+
+typedef enum {
+ Uart0 = 0,
+ Uart1 = 1,
+ Uart2 = 2,
+ Uart3 = 3
+} EFI_UART_Number;
+
+//
+// Name: SERIAL_DEV
+// Purpose: To provide device specific information
+// Context:
+// Fields:
+// Signature UINTN: The identity of the serial device
+// SerialIo SERIAL_IO_PROTOCOL: Serial I/O protocol interface
+// SerialMode SERIAL_IO_MODE:
+// DevicePath EFI_DEVICE_PATH_PROTOCOL *: Device path of the serial device
+// Handle EFI_HANDLE: The handle instance attached to serial device
+// BaseAddress UINT16: The base address of specific serial device
+// Receive SERIAL_DEV_FIFO: The FIFO used to store data,
+// which is received by UART
+// Transmit SERIAL_DEV_FIFO: The FIFO used to store data,
+// which you want to transmit by UART
+// SoftwareLoopbackEnable BOOLEAN:
+// Type EFI_UART_TYPE: Specify the UART type of certain serial device
+//
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_SERIAL_IO_PROTOCOL SerialIo;
+ EFI_SERIAL_IO_MODE SerialMode;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ UART_DEVICE_PATH UartDevicePath;
+ EFI_ISA_IO_PROTOCOL *IsaIo;
+ UINT16 BaseAddress;
+ SERIAL_DEV_FIFO Receive;
+ SERIAL_DEV_FIFO Transmit;
+ BOOLEAN SoftwareLoopbackEnable;
+ BOOLEAN HardwareFlowControl;
+ EFI_UART_TYPE Type;
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;
+} SERIAL_DEV;
+
+#define SERIAL_DEV_FROM_THIS(a) CR (a, SERIAL_DEV, SerialIo, SERIAL_DEV_SIGNATURE)
+
+//
+// Serial Driver Defaults
+//
+#define SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH 1
+#define SERIAL_PORT_DEFAULT_TIMEOUT 1000000
+#define SERIAL_PORT_SUPPORT_CONTROL_MASK (EFI_SERIAL_CLEAR_TO_SEND | \
+ EFI_SERIAL_DATA_SET_READY | \
+ EFI_SERIAL_RING_INDICATE | \
+ EFI_SERIAL_CARRIER_DETECT | \
+ 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 | \
+ EFI_SERIAL_OUTPUT_BUFFER_EMPTY | \
+ EFI_SERIAL_INPUT_BUFFER_EMPTY)
+
+
+//
+// (24000000/13)MHz input clock
+//
+#define SERIAL_PORT_INPUT_CLOCK 1843200
+
+//
+// 115200 baud with rounding errors
+//
+#define SERIAL_PORT_MAX_BAUD_RATE 115400
+#define SERIAL_PORT_MIN_BAUD_RATE 50
+
+#define SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH 16
+#define SERIAL_PORT_MIN_TIMEOUT 1 // 1 uS
+#define SERIAL_PORT_MAX_TIMEOUT 100000000 // 100 seconds
+//
+// UART Registers
+//
+#define SERIAL_REGISTER_THR 0 // WO Transmit Holding Register
+#define SERIAL_REGISTER_RBR 0 // RO Receive Buffer Register
+#define SERIAL_REGISTER_DLL 0 // R/W Divisor Latch LSB
+#define SERIAL_REGISTER_DLM 1 // R/W Divisor Latch MSB
+#define SERIAL_REGISTER_IER 1 // R/W Interrupt Enable Register
+#define SERIAL_REGISTER_IIR 2 // RO Interrupt Identification Register
+#define SERIAL_REGISTER_FCR 2 // WO FIFO Cotrol Register
+#define SERIAL_REGISTER_LCR 3 // R/W Line Control Register
+#define SERIAL_REGISTER_MCR 4 // R/W Modem Control Register
+#define SERIAL_REGISTER_LSR 5 // R/W Line Status Register
+#define SERIAL_REGISTER_MSR 6 // R/W Modem Status Register
+#define SERIAL_REGISTER_SCR 7 // R/W Scratch Pad Register
+#pragma pack(1)
+//
+// Name: SERIAL_PORT_IER_BITS
+// Purpose: Define each bit in Interrupt Enable Register
+// Context:
+// Fields:
+// Ravie Bit0: Receiver Data Available Interrupt Enable
+// Theie Bit1: Transmistter Holding Register Empty Interrupt Enable
+// Rie Bit2: Receiver Interrupt Enable
+// Mie Bit3: Modem Interrupt Enable
+// Reserved Bit4-Bit7: Reserved
+//
+typedef struct {
+ UINT8 Ravie : 1;
+ UINT8 Theie : 1;
+ UINT8 Rie : 1;
+ UINT8 Mie : 1;
+ UINT8 Reserved : 4;
+} SERIAL_PORT_IER_BITS;
+
+//
+// Name: SERIAL_PORT_IER
+// Purpose:
+// Context:
+// Fields:
+// Bits SERIAL_PORT_IER_BITS: Bits of the IER
+// Data UINT8: the value of the IER
+//
+typedef union {
+ SERIAL_PORT_IER_BITS Bits;
+ UINT8 Data;
+} SERIAL_PORT_IER;
+
+//
+// Name: SERIAL_PORT_FCR_BITS
+// Purpose: Define each bit in FIFO Control Register
+// Context:
+// Fields:
+// TrFIFOE Bit0: Transmit and Receive FIFO Enable
+// ResetRF Bit1: Reset Reciever FIFO
+// ResetTF Bit2: Reset Transmistter FIFO
+// Dms Bit3: DMA Mode Select
+// Reserved Bit4-Bit5: Reserved
+// Rtb Bit6-Bit7: Receive Trigger Bits
+//
+typedef struct {
+ UINT8 TrFIFOE : 1;
+ UINT8 ResetRF : 1;
+ UINT8 ResetTF : 1;
+ UINT8 Dms : 1;
+ UINT8 Reserved : 2;
+ UINT8 Rtb : 2;
+} SERIAL_PORT_FCR_BITS;
+
+//
+// Name: SERIAL_PORT_FCR
+// Purpose:
+// Context:
+// Fields:
+// Bits SERIAL_PORT_FCR_BITS: Bits of the FCR
+// Data UINT8: the value of the FCR
+//
+typedef union {
+ SERIAL_PORT_FCR_BITS Bits;
+ UINT8 Data;
+} SERIAL_PORT_FCR;
+
+//
+// Name: SERIAL_PORT_LCR_BITS
+// Purpose: Define each bit in Line Control Register
+// Context:
+// Fields:
+// SerialDB Bit0-Bit1: Number of Serial Data Bits
+// StopB Bit2: Number of Stop Bits
+// ParEn Bit3: Parity Enable
+// EvenPar Bit4: Even Parity Select
+// SticPar Bit5: Sticky Parity
+// BrCon Bit6: Break Control
+// DLab Bit7: Divisor Latch Access Bit
+//
+typedef struct {
+ UINT8 SerialDB : 2;
+ UINT8 StopB : 1;
+ UINT8 ParEn : 1;
+ UINT8 EvenPar : 1;
+ UINT8 SticPar : 1;
+ UINT8 BrCon : 1;
+ UINT8 DLab : 1;
+} SERIAL_PORT_LCR_BITS;
+
+//
+// Name: SERIAL_PORT_LCR
+// Purpose:
+// Context:
+// Fields:
+// Bits SERIAL_PORT_LCR_BITS: Bits of the LCR
+// Data UINT8: the value of the LCR
+//
+typedef union {
+ SERIAL_PORT_LCR_BITS Bits;
+ UINT8 Data;
+} SERIAL_PORT_LCR;
+
+//
+// Name: SERIAL_PORT_MCR_BITS
+// Purpose: Define each bit in Modem Control Register
+// Context:
+// Fields:
+// DtrC Bit0: Data Terminal Ready Control
+// Rts Bit1: Request To Send Control
+// Out1 Bit2: Output1
+// Out2 Bit3: Output2, used to disable interrupt
+// Lme; Bit4: Loopback Mode Enable
+// Reserved Bit5-Bit7: Reserved
+//
+typedef struct {
+ UINT8 DtrC : 1;
+ UINT8 Rts : 1;
+ UINT8 Out1 : 1;
+ UINT8 Out2 : 1;
+ UINT8 Lme : 1;
+ UINT8 Reserved : 3;
+} SERIAL_PORT_MCR_BITS;
+
+//
+// Name: SERIAL_PORT_MCR
+// Purpose:
+// Context:
+// Fields:
+// Bits SERIAL_PORT_MCR_BITS: Bits of the MCR
+// Data UINT8: the value of the MCR
+//
+typedef union {
+ SERIAL_PORT_MCR_BITS Bits;
+ UINT8 Data;
+} SERIAL_PORT_MCR;
+
+//
+// Name: SERIAL_PORT_LSR_BITS
+// Purpose: Define each bit in Line Status Register
+// Context:
+// Fields:
+// Dr Bit0: Receiver Data Ready Status
+// Oe Bit1: Overrun Error Status
+// Pe Bit2: Parity Error Status
+// Fe Bit3: Framing Error Status
+// Bi Bit4: Break Interrupt Status
+// Thre Bit5: Transmistter Holding Register Status
+// Temt Bit6: Transmitter Empty Status
+// FIFOe Bit7: FIFO Error Status
+//
+typedef struct {
+ UINT8 Dr : 1;
+ UINT8 Oe : 1;
+ UINT8 Pe : 1;
+ UINT8 Fe : 1;
+ UINT8 Bi : 1;
+ UINT8 Thre : 1;
+ UINT8 Temt : 1;
+ UINT8 FIFOe : 1;
+} SERIAL_PORT_LSR_BITS;
+
+//
+// Name: SERIAL_PORT_LSR
+// Purpose:
+// Context:
+// Fields:
+// Bits SERIAL_PORT_LSR_BITS: Bits of the LSR
+// Data UINT8: the value of the LSR
+//
+typedef union {
+ SERIAL_PORT_LSR_BITS Bits;
+ UINT8 Data;
+} SERIAL_PORT_LSR;
+
+//
+// Name: SERIAL_PORT_MSR_BITS
+// Purpose: Define each bit in Modem Status Register
+// Context:
+// Fields:
+// DeltaCTS Bit0: Delta Clear To Send Status
+// DeltaDSR Bit1: Delta Data Set Ready Status
+// TrailingEdgeRI Bit2: Trailing Edge of Ring Indicator Status
+// DeltaDCD Bit3: Delta Data Carrier Detect Status
+// Cts Bit4: Clear To Send Status
+// Dsr Bit5: Data Set Ready Status
+// Ri Bit6: Ring Indicator Status
+// Dcd Bit7: Data Carrier Detect Status
+//
+typedef struct {
+ UINT8 DeltaCTS : 1;
+ UINT8 DeltaDSR : 1;
+ UINT8 TrailingEdgeRI : 1;
+ UINT8 DeltaDCD : 1;
+ UINT8 Cts : 1;
+ UINT8 Dsr : 1;
+ UINT8 Ri : 1;
+ UINT8 Dcd : 1;
+} SERIAL_PORT_MSR_BITS;
+
+//
+// Name: SERIAL_PORT_MSR
+// Purpose:
+// Context:
+// Fields:
+// Bits SERIAL_PORT_MSR_BITS: Bits of the MSR
+// Data UINT8: the value of the MSR
+//
+typedef union {
+ SERIAL_PORT_MSR_BITS Bits;
+ UINT8 Data;
+} SERIAL_PORT_MSR;
+
+#pragma pack()
+//
+// Define serial register I/O macros
+//
+#define READ_RBR(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_RBR)
+#define READ_DLL(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_DLL)
+#define READ_DLM(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_DLM)
+#define READ_IER(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_IER)
+#define READ_IIR(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_IIR)
+#define READ_LCR(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_LCR)
+#define READ_MCR(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_MCR)
+#define READ_LSR(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_LSR)
+#define READ_MSR(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_MSR)
+#define READ_SCR(IO, B) IsaSerialReadPort (IO, B, SERIAL_REGISTER_SCR)
+
+#define WRITE_THR(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_THR, D)
+#define WRITE_DLL(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_DLL, D)
+#define WRITE_DLM(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_DLM, D)
+#define WRITE_IER(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_IER, D)
+#define WRITE_FCR(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_FCR, D)
+#define WRITE_LCR(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_LCR, D)
+#define WRITE_MCR(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_MCR, D)
+#define WRITE_LSR(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_LSR, D)
+#define WRITE_MSR(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_MSR, D)
+#define WRITE_SCR(IO, B, D) IsaSerialWritePort (IO, B, SERIAL_REGISTER_SCR, D)
+
+//
+// Prototypes
+// Driver model protocol interface
+//
+/**
+ Check to see if this driver supports the given controller
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] Controller The handle of the controller to test.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path.
+
+ @retval EFI_SUCCESS This driver can support the given controller
+
+**/
+EFI_STATUS
+EFIAPI
+SerialControllerDriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Start to management the controller passed in
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] Controller The handle of the controller to test.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path.
+
+ @retval EFI_SUCCESS Driver is started successfully
+**/
+EFI_STATUS
+EFIAPI
+SerialControllerDriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Disconnect this driver with the controller, uninstall related protocol instance
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] Controller The handle of the controller to test.
+ @param[in] NumberOfChildren Number of child device.
+ @param[in] ChildHandleBuffer A pointer to the remaining portion of a device path.
+
+ @retval EFI_SUCCESS Operation successfully
+ @retval EFI_DEVICE_ERROR Cannot stop the driver successfully
+
+**/
+EFI_STATUS
+EFIAPI
+SerialControllerDriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+//
+// Serial I/O Protocol Interface
+//
+/**
+ Reset serial device.
+
+ @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL
+
+ @retval EFI_SUCCESS Reset successfully
+ @retval EFI_DEVICE_ERROR Failed to reset
+
+**/
+EFI_STATUS
+EFIAPI
+IsaSerialReset (
+ IN EFI_SERIAL_IO_PROTOCOL *This
+ );
+
+/**
+ Set new attributes to a serial device.
+
+ @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param[in] BaudRate The baudrate of the serial device
+ @param[in] ReceiveFifoDepth The depth of receive FIFO buffer
+ @param[in] Timeout The request timeout for a single char
+ @param[in] Parity The type of parity used in serial device
+ @param[in] DataBits Number of databits used in serial device
+ @param[in] StopBits Number of stopbits used in serial device
+
+ @retval EFI_SUCCESS The new attributes were set
+ @retval EFI_INVALID_PARAMETERS One or more attributes have an unsupported value
+ @retval EFI_UNSUPPORTED Data Bits can not set to 5 or 6
+ @retval EFI_DEVICE_ERROR The serial device is not functioning correctly (no return)
+
+**/
+EFI_STATUS
+EFIAPI
+IsaSerialSetAttributes (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN UINT64 BaudRate,
+ IN UINT32 ReceiveFifoDepth,
+ IN UINT32 Timeout,
+ IN EFI_PARITY_TYPE Parity,
+ IN UINT8 DataBits,
+ IN EFI_STOP_BITS_TYPE StopBits
+ );
+
+/**
+ Set Control Bits.
+
+ @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param[in] Control Control bits that can be settable
+
+ @retval EFI_SUCCESS New Control bits were set successfully
+ @retval EFI_UNSUPPORTED The Control bits wanted to set are not supported
+
+**/
+EFI_STATUS
+EFIAPI
+IsaSerialSetControl (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN UINT32 Control
+ );
+
+/**
+ Get Control Bits.
+
+ @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param[out] Control Control signals of the serial device
+
+ @retval EFI_SUCCESS Get Control signals successfully
+
+**/
+EFI_STATUS
+EFIAPI
+IsaSerialGetControl (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ OUT UINT32 *Control
+ );
+
+/**
+ Write the specified number of bytes to serial device.
+
+ @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param[in, out] BufferSize On input the size of Buffer, on output the amount of
+ data actually written
+ @param[in] Buffer The buffer of data to write
+
+ @retval EFI_SUCCESS The data were written successfully
+ @retval EFI_DEVICE_ERROR The device reported an error
+ @retval EFI_TIMEOUT The write operation was stopped due to timeout
+
+**/
+EFI_STATUS
+EFIAPI
+IsaSerialWrite (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ );
+
+/**
+ Read the specified number of bytes from serial device.
+
+ @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param[in, out] BufferSize On input the size of Buffer, on output the amount of
+ data returned in buffer
+ @param[out] Buffer The buffer to return the data into
+
+ @retval EFI_SUCCESS The data were read successfully
+ @retval EFI_DEVICE_ERROR The device reported an error
+ @retval EFI_TIMEOUT The read operation was stopped due to timeout
+
+**/
+EFI_STATUS
+EFIAPI
+IsaSerialRead (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ );
+
+//
+// Internal Functions
+//
+/**
+ Use scratchpad register to test if this serial port is present.
+
+ @param[in] SerialDevice Pointer to serial device structure
+
+ @return if this serial port is present
+
+**/
+BOOLEAN
+IsaSerialPortPresent (
+ IN SERIAL_DEV *SerialDevice
+ );
+
+/**
+ Detect whether specific FIFO is full or not.
+
+ @param[in] Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
+
+ @return whether specific FIFO is full or not
+
+**/
+BOOLEAN
+IsaSerialFifoFull (
+ IN SERIAL_DEV_FIFO *Fifo
+ );
+
+/**
+ Detect whether specific FIFO is empty or not.
+
+ @param[in] Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
+
+ @return whether specific FIFO is empty or not
+
+**/
+BOOLEAN
+IsaSerialFifoEmpty (
+ IN SERIAL_DEV_FIFO *Fifo
+ );
+
+/**
+ Add data to specific FIFO.
+
+ @param[in] Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
+ @param[in] Data the data added to FIFO
+
+ @retval EFI_SUCCESS Add data to specific FIFO successfully
+ @retval EFI_OUT_OF_RESOURCE Failed to add data because FIFO is already full
+
+**/
+EFI_STATUS
+IsaSerialFifoAdd (
+ IN SERIAL_DEV_FIFO *Fifo,
+ IN UINT8 Data
+ );
+
+/**
+ Remove data from specific FIFO.
+
+ @param[in] Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
+ @param[in] Data the data removed from FIFO
+
+ @retval EFI_SUCCESS Remove data from specific FIFO successfully
+ @retval EFI_OUT_OF_RESOURCE Failed to remove data because FIFO is empty
+
+**/
+EFI_STATUS
+IsaSerialFifoRemove (
+ IN SERIAL_DEV_FIFO *Fifo,
+ OUT UINT8 *Data
+ );
+
+/**
+ Reads and writes all avaliable data.
+
+ @param[in] SerialDevice The device to flush
+
+ @retval EFI_SUCCESS Data was read/written successfully.
+ @retval EFI_OUT_OF_RESOURCE Failed because software receive FIFO is full. Note, when
+ this happens, pending writes are not done.
+
+**/
+EFI_STATUS
+IsaSerialReceiveTransmit (
+ IN SERIAL_DEV *SerialDevice
+ );
+
+/**
+ Use IsaIo protocol to read serial port.
+
+ @param[in] IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance
+ @param[in] BaseAddress Serial port register group base address
+ @param[in] Offset Offset in register group
+
+ @return Data read from serial port
+
+**/
+UINT8
+IsaSerialReadPort (
+ IN EFI_ISA_IO_PROTOCOL *IsaIo,
+ IN UINT16 BaseAddress,
+ IN UINT32 Offset
+ );
+
+/**
+ Use IsaIo protocol to write serial port.
+
+ @param[in] IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance
+ @param[in] BaseAddress Serial port register group base address
+ @param[in] Offset Offset in register group
+ @param[in] Data data which is to be written to some serial port register
+
+**/
+VOID
+IsaSerialWritePort (
+ IN EFI_ISA_IO_PROTOCOL *IsaIo,
+ IN UINT16 BaseAddress,
+ IN UINT32 Offset,
+ IN UINT8 Data
+ );
+
+//
+// EFI Component Name Functions
+//
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param[in] Language A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param[out] DriverName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+IsaSerialComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param[in] ControllerHandle The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param[in] ChildHandle The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param[in] Language A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param[out] ControllerName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+IsaSerialComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+/**
+ Add the component name for the serial io device
+
+ @param[in] SerialDevice A pointer to the SERIAL_DEV instance.
+ @param[in] IsaIo A pointer to the EFI_ISA_IO_PROTOCOL instance.
+
+**/
+VOID
+AddName (
+ IN SERIAL_DEV *SerialDevice,
+ IN EFI_ISA_IO_PROTOCOL *IsaIo
+ );
+
+#endif
+