4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Serial driver for standard UARTS on an ISA bus.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncCopyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncThis program and the accompanying materials
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncare licensed and made available under the terms and conditions of the BSD License
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncwhich accompanies this distribution. The full text of the license may be found at
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynchttp://opensource.org/licenses/bsd-license.php
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include "Serial.h"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync// ISA Serial Driver Global Variables
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_DRIVER_BINDING_PROTOCOL gSerialControllerDriver = {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialControllerDriverSupported,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialControllerDriverStart,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialControllerDriverStop,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0xa,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync};
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncSERIAL_DEV gSerialDevTempate = {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_DEV_SIGNATURE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync { // SerialIo
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_IO_INTERFACE_REVISION,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsaSerialReset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsaSerialSetAttributes,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsaSerialSetControl,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsaSerialGetControl,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsaSerialWrite,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsaSerialRead,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync },
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync { // SerialMode
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_PORT_SUPPORT_CONTROL_MASK,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_PORT_DEFAULT_TIMEOUT,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixedPcdGet8 (PcdUartDefaultParity), // Parity
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync },
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync { // UartDevicePath
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MESSAGING_DEVICE_PATH,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MSG_UART_DP,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT8) (sizeof (UART_DEVICE_PATH)),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync },
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixedPcdGet64 (PcdUartDefaultBaudRate),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixedPcdGet8 (PcdUartDefaultDataBits),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixedPcdGet8 (PcdUartDefaultParity),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FixedPcdGet8 (PcdUartDefaultStopBits)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync },
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0, //BaseAddress
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_MAX_BUFFER_SIZE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync { 0 }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync },
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_MAX_BUFFER_SIZE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync { 0 }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync },
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FALSE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FALSE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Uart16550A,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync};
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Check the device path node whether it's the Flow Control node or not.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] FlowControl The device path node to be checked.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval TRUE It's the Flow Control node.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval FALSE It's not.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncBOOLEAN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIsUartFlowControlNode (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UART_FLOW_CONTROL_DEVICE_PATH *FlowControl
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return (BOOLEAN) (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (DevicePathType (FlowControl) == MESSAGING_DEVICE_PATH) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (DevicePathSubType (FlowControl) == MSG_VENDOR_DP) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (CompareGuid (&FlowControl->Guid, &gEfiUartDevicePathGuid))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Check the device path node whether it contains Flow Control node or not.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] DevicePath The device path to be checked.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval TRUE It contains the Flow Control node.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval FALSE It doesn't.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncBOOLEAN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncContainsFlowControl (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (!IsDevicePathEnd (DevicePath)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IsUartFlowControlNode ((UART_FLOW_CONTROL_DEVICE_PATH *) DevicePath)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DevicePath = NextDevicePathNode (DevicePath);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The user Entry Point for module IsaSerial. The user code starts with this function.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] ImageHandle The firmware allocated handle for the EFI image.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] SystemTable A pointer to the EFI System Table.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The entry point is executed successfully.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval other Some error occurs when executing this entry point.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncInitializeIsaSerial (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_HANDLE ImageHandle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_SYSTEM_TABLE *SystemTable
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Install driver model protocol(s).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EfiLibInstallDriverBindingComponentName2 (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageHandle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SystemTable,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gSerialControllerDriver,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImageHandle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gIsaSerialComponentName,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gIsaSerialComponentName2
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT_EFI_ERROR (Status);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Check to see if this driver supports the given controller
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Controller The handle of the controller to test.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param RemainingDevicePath A pointer to the remaining portion of a device path.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return EFI_SUCCESS This driver can support the given controller
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncSerialControllerDriverSupported (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_DRIVER_BINDING_PROTOCOL *This,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_HANDLE Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_ISA_IO_PROTOCOL *IsaIo;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UART_DEVICE_PATH *UartNode;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_DEVICE_PATH_PROTOCOL *DevicePath;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UART_FLOW_CONTROL_DEVICE_PATH *FlowControlNode;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN EntryCount;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Index;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN HasFlowControl;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check RemainingDevicePath validation
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RemainingDevicePath != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check if RemainingDevicePath is the End of Device Path Node,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // if yes, go on checking other conditions
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!IsDevicePathEnd (RemainingDevicePath)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If RemainingDevicePath isn't the End of Device Path Node,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // check its validation
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_UNSUPPORTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UartNode = (UART_DEVICE_PATH *) RemainingDevicePath;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (UartNode->Header.Type != MESSAGING_DEVICE_PATH ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UartNode->Header.SubType != MSG_UART_DP ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof (UART_DEVICE_PATH) != DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) UartNode)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Error;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (UartNode->BaudRate > SERIAL_PORT_MAX_BAUD_RATE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Error;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (UartNode->Parity < NoParity || UartNode->Parity > SpaceParity) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Error;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (UartNode->DataBits < 5 || UartNode->DataBits > 8) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Error;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (UartNode->StopBits < OneStopBit || UartNode->StopBits > TwoStopBits) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Error;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((UartNode->DataBits == 5) && (UartNode->StopBits == TwoStopBits)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Error;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((UartNode->DataBits >= 6) && (UartNode->DataBits <= 8) && (UartNode->StopBits == OneFiveStopBits)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Error;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (UartNode);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IsUartFlowControlNode (FlowControlNode)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the second node is Flow Control Node,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // return error when it request other than hardware flow control.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((ReadUnaligned32 (&FlowControlNode->FlowControlMap) & ~UART_FLOW_CONTROL_HARDWARE) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Error;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Open the IO Abstraction(s) needed to perform the supported test
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->OpenProtocol (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiIsaIoProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (VOID **) &IsaIo,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->DriverBindingHandle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_OPEN_PROTOCOL_BY_DRIVER
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Status == EFI_ALREADY_STARTED) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If RemainingDevicePath is NULL or is the End of Device Path Node
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // When the driver has produced device path with flow control node but RemainingDevicePath only contains UART node,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // return unsupported, and vice versa.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->OpenProtocolInformation (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiIsaIoProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &OpenInfoBuffer,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &EntryCount
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < EntryCount; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->OpenProtocol (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OpenInfoBuffer[Index].ControllerHandle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiDevicePathProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (VOID **) &DevicePath,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->DriverBindingHandle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_OPEN_PROTOCOL_GET_PROTOCOL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HasFlowControl = ContainsFlowControl (RemainingDevicePath);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (HasFlowControl ^ ContainsFlowControl (DevicePath)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_UNSUPPORTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (OpenInfoBuffer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Close the I/O Abstraction(s) used to perform the supported test
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->CloseProtocol (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiIsaIoProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->DriverBindingHandle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Open the EFI Device Path protocol needed to perform the supported test
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->OpenProtocol (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiDevicePathProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (VOID **) &ParentDevicePath,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->DriverBindingHandle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_OPEN_PROTOCOL_BY_DRIVER
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Status == EFI_ALREADY_STARTED) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use the ISA I/O Protocol to see if Controller is standard ISA UART that
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // can be managed by this driver.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x501)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_UNSUPPORTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Error;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncError:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Close protocol, don't use device path protocol in the Support() function
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->CloseProtocol (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiDevicePathProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->DriverBindingHandle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Start to management the controller passed in
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Controller The handle of the controller to test.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param RemainingDevicePath A pointer to the remaining portion of a device path.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return EFI_SUCCESS Driver is started successfully
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncSerialControllerDriverStart (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_DRIVER_BINDING_PROTOCOL *This,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_HANDLE Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_ISA_IO_PROTOCOL *IsaIo;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_DEV *SerialDevice;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Index;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN EntryCount;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_SERIAL_IO_PROTOCOL *SerialIo;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UART_DEVICE_PATH *Uart;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 FlowControlMap;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UART_FLOW_CONTROL_DEVICE_PATH *FlowControl;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Control;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get the Parent Device Path
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->OpenProtocol (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiDevicePathProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (VOID **) &ParentDevicePath,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->DriverBindingHandle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_OPEN_PROTOCOL_BY_DRIVER
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Report status code enable the serial
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync REPORT_STATUS_CODE_WITH_DEVICE_PATH (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_PROGRESS_CODE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_P_PC_ENABLE | EFI_PERIPHERAL_SERIAL_PORT,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ParentDevicePath
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Grab the IO abstraction we need to get any work done
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->OpenProtocol (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiIsaIoProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (VOID **) &IsaIo,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->DriverBindingHandle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_OPEN_PROTOCOL_BY_DRIVER
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Error;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Status == EFI_ALREADY_STARTED) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If RemainingDevicePath is NULL or is the End of Device Path Node
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Make sure a child handle does not already exist. This driver can only
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // produce one child per serial port.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->OpenProtocolInformation (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiIsaIoProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &OpenInfoBuffer,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &EntryCount
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_ALREADY_STARTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < EntryCount; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->OpenProtocol (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OpenInfoBuffer[Index].ControllerHandle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiSerialIoProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (VOID **) &SerialIo,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->DriverBindingHandle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_OPEN_PROTOCOL_GET_PROTOCOL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Uart = (UART_DEVICE_PATH *) RemainingDevicePath;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = SerialIo->SetAttributes (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialIo,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Uart->BaudRate,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialIo->Mode->ReceiveFifoDepth,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialIo->Mode->Timeout,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_PARITY_TYPE) Uart->Parity,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Uart->DataBits,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_STOP_BITS_TYPE) Uart->StopBits
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Uart);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!EFI_ERROR (Status) && IsUartFlowControlNode (FlowControl)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = SerialIo->GetControl (SerialIo, &Control);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ReadUnaligned32 (&FlowControl->FlowControlMap) == UART_FLOW_CONTROL_HARDWARE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Control &= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Clear the bits that are not allowed to pass to SetControl
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Control &= (EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY |
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE |
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = SerialIo->SetControl (SerialIo, Control);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (OpenInfoBuffer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RemainingDevicePath != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IsDevicePathEnd (RemainingDevicePath)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If RemainingDevicePath is the End of Device Path Node,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // skip enumerate any device and return EFI_SUCESSS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Initialize the serial device instance
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice = AllocateCopyPool (sizeof (SERIAL_DEV), &gSerialDevTempate);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (SerialDevice == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Error;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->SerialIo.Mode = &(SerialDevice->SerialMode);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->IsaIo = IsaIo;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->ParentDevicePath = ParentDevicePath;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FlowControl = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FlowControlMap = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check if RemainingDevicePath is NULL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // if yes, use the values from the gSerialDevTempate as no remaining device path was
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // passed in.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RemainingDevicePath != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If RemainingDevicePath isn't NULL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // match the configuration of the RemainingDevicePath. IsHandleSupported()
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // already checked to make sure the RemainingDevicePath contains settings
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // that we can support.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (&SerialDevice->UartDevicePath, RemainingDevicePath, sizeof (UART_DEVICE_PATH));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (RemainingDevicePath);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IsUartFlowControlNode (FlowControl)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FlowControlMap = ReadUnaligned32 (&FlowControl->FlowControlMap);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FlowControl = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AddName (SerialDevice, IsaIo);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; SerialDevice->IsaIo->ResourceList->ResourceItem[Index].Type != EfiIsaAcpiResourceEndOfList; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (SerialDevice->IsaIo->ResourceList->ResourceItem[Index].Type == EfiIsaAcpiResourceIo) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->BaseAddress = (UINT16) SerialDevice->IsaIo->ResourceList->ResourceItem[Index].StartRange;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->HardwareFlowControl = (BOOLEAN) (FlowControlMap == UART_FLOW_CONTROL_HARDWARE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Report status code the serial present
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync REPORT_STATUS_CODE_WITH_DEVICE_PATH (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_PROGRESS_CODE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_P_PC_PRESENCE_DETECT | EFI_PERIPHERAL_SERIAL_PORT,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ParentDevicePath
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!IsaSerialPortPresent (SerialDevice)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_DEVICE_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync REPORT_STATUS_CODE_WITH_DEVICE_PATH (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_ERROR_CODE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_P_EC_NOT_DETECTED | EFI_PERIPHERAL_SERIAL_PORT,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ParentDevicePath
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Error;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Build the device path by appending the UART node to the ParentDevicePath.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The Uart setings are zero here, since SetAttribute() will update them to match
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the default setings.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->DevicePath = AppendDevicePathNode (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ParentDevicePath,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_DEVICE_PATH_PROTOCOL *) &SerialDevice->UartDevicePath
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Only produce the Flow Control node when remaining device path has it
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (FlowControl != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TempDevicePath = SerialDevice->DevicePath;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TempDevicePath != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->DevicePath = AppendDevicePathNode (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TempDevicePath,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_DEVICE_PATH_PROTOCOL *) FlowControl
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (TempDevicePath);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (SerialDevice->DevicePath == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Error;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->SerialMode.BaudRate = SerialDevice->UartDevicePath.BaudRate;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->SerialMode.DataBits = SerialDevice->UartDevicePath.DataBits;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->SerialMode.Parity = SerialDevice->UartDevicePath.Parity;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->SerialMode.StopBits = SerialDevice->UartDevicePath.StopBits;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Issue a reset to initialize the COM port
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = SerialDevice->SerialIo.Reset (&SerialDevice->SerialIo);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync REPORT_STATUS_CODE_WITH_DEVICE_PATH (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_ERROR_CODE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_P_EC_CONTROLLER_ERROR | EFI_PERIPHERAL_SERIAL_PORT,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ParentDevicePath
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Error;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Install protocol interfaces for the serial device.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->InstallMultipleProtocolInterfaces (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &SerialDevice->Handle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiDevicePathProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->DevicePath,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiSerialIoProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &SerialDevice->SerialIo,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Error;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Open For Child Device
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->OpenProtocol (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiIsaIoProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (VOID **) &IsaIo,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->DriverBindingHandle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->Handle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncError:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->CloseProtocol (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiDevicePathProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->DriverBindingHandle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->CloseProtocol (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiIsaIoProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->DriverBindingHandle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (SerialDevice != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (SerialDevice->DevicePath != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->FreePool (SerialDevice->DevicePath);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeUnicodeStringTable (SerialDevice->ControllerNameTable);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->FreePool (SerialDevice);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Disconnect this driver with the controller, uninstall related protocol instance
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Controller The handle of the controller to test.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param NumberOfChildren Number of child device.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ChildHandleBuffer A pointer to the remaining portion of a device path.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS Operation successfully
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_DEVICE_ERROR Cannot stop the driver successfully
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncSerialControllerDriverStop (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_DRIVER_BINDING_PROTOCOL *This,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_HANDLE Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN NumberOfChildren,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_HANDLE *ChildHandleBuffer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Index;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN AllChildrenStopped;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_SERIAL_IO_PROTOCOL *SerialIo;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_DEV *SerialDevice;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_ISA_IO_PROTOCOL *IsaIo;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_DEVICE_PATH_PROTOCOL *DevicePath;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->HandleProtocol (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiDevicePathProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (VOID **) &DevicePath
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Report the status code disable the serial
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync REPORT_STATUS_CODE_WITH_DEVICE_PATH (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_PROGRESS_CODE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_P_PC_DISABLE | EFI_PERIPHERAL_SERIAL_PORT,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DevicePath
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Complete all outstanding transactions to Controller.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Don't allow any new transaction to Controller to be started.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NumberOfChildren == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Close the bus driver
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->CloseProtocol (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiIsaIoProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->DriverBindingHandle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->CloseProtocol (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiDevicePathProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->DriverBindingHandle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AllChildrenStopped = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < NumberOfChildren; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->OpenProtocol (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ChildHandleBuffer[Index],
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiSerialIoProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (VOID **) &SerialIo,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->DriverBindingHandle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_OPEN_PROTOCOL_GET_PROTOCOL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice = SERIAL_DEV_FROM_THIS (SerialIo);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->CloseProtocol (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiIsaIoProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->DriverBindingHandle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ChildHandleBuffer[Index]
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->UninstallMultipleProtocolInterfaces (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ChildHandleBuffer[Index],
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiDevicePathProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->DevicePath,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiSerialIoProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &SerialDevice->SerialIo,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->OpenProtocol (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiIsaIoProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (VOID **) &IsaIo,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->DriverBindingHandle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ChildHandleBuffer[Index],
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (SerialDevice->DevicePath != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->FreePool (SerialDevice->DevicePath);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreeUnicodeStringTable (SerialDevice->ControllerNameTable);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->FreePool (SerialDevice);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AllChildrenStopped = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!AllChildrenStopped) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_DEVICE_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Detect whether specific FIFO is full or not.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return whether specific FIFO is full or not
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncBOOLEAN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIsaSerialFifoFull (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN SERIAL_DEV_FIFO *Fifo
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Fifo->Surplus == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Detect whether specific FIFO is empty or not.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return whether specific FIFO is empty or not
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncBOOLEAN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIsaSerialFifoEmpty (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN SERIAL_DEV_FIFO *Fifo
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Fifo->Surplus == SERIAL_MAX_BUFFER_SIZE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Add data to specific FIFO.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Data the data added to FIFO
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS Add data to specific FIFO successfully
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCE Failed to add data because FIFO is already full
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIsaSerialFifoAdd (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN SERIAL_DEV_FIFO *Fifo,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 Data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // if FIFO full can not add data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IsaSerialFifoFull (Fifo)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // FIFO is not full can add data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fifo->Data[Fifo->Last] = Data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fifo->Surplus--;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fifo->Last++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Fifo->Last == SERIAL_MAX_BUFFER_SIZE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fifo->Last = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Remove data from specific FIFO.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Data the data removed from FIFO
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS Remove data from specific FIFO successfully
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCE Failed to remove data because FIFO is empty
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIsaSerialFifoRemove (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN SERIAL_DEV_FIFO *Fifo,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OUT UINT8 *Data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // if FIFO is empty, no data can remove
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IsaSerialFifoEmpty (Fifo)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // FIFO is not empty, can remove data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Data = Fifo->Data[Fifo->First];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fifo->Surplus++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fifo->First++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Fifo->First == SERIAL_MAX_BUFFER_SIZE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fifo->First = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Reads and writes all avaliable data.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param SerialDevice The device to flush
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS Data was read/written successfully.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCE Failed because software receive FIFO is full. Note, when
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync this happens, pending writes are not done.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIsaSerialReceiveTransmit (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN SERIAL_DEV *SerialDevice
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_PORT_LSR Lsr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 Data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN ReceiveFifoFull;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_PORT_MSR Msr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_PORT_MCR Mcr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN TimeOut;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Data = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Begin the read or write
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (SerialDevice->SoftwareLoopbackEnable) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync do {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!IsaSerialFifoEmpty (&SerialDevice->Transmit)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsaSerialFifoRemove (&SerialDevice->Transmit, &Data);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ReceiveFifoFull) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsaSerialFifoAdd (&SerialDevice->Receive, Data);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } while (!IsaSerialFifoEmpty (&SerialDevice->Transmit));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // For full handshake flow control, tell the peer to send data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // if receive buffer is available.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (SerialDevice->HardwareFlowControl &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync !FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake)&&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync !ReceiveFifoFull
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mcr.Bits.Rts = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync do {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lsr.Data = READ_LSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Flush incomming data to prevent a an overrun during a long write
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Lsr.Bits.Dr == 1) && !ReceiveFifoFull) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!ReceiveFifoFull) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Lsr.Bits.FIFOe == 1 || Lsr.Bits.Oe == 1 || Lsr.Bits.Pe == 1 || Lsr.Bits.Fe == 1 || Lsr.Bits.Bi == 1) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync REPORT_STATUS_CODE_WITH_DEVICE_PATH (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_ERROR_CODE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_P_EC_INPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->DevicePath
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Lsr.Bits.FIFOe == 1 || Lsr.Bits.Pe == 1|| Lsr.Bits.Fe == 1 || Lsr.Bits.Bi == 1) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Data = READ_RBR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync continue;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Data = READ_RBR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsaSerialFifoAdd (&SerialDevice->Receive, Data);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // For full handshake flow control, if receive buffer full
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // tell the peer to stop sending data.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (SerialDevice->HardwareFlowControl &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync !FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsaSerialFifoFull (&SerialDevice->Receive)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mcr.Bits.Rts = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync continue;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync REPORT_STATUS_CODE_WITH_DEVICE_PATH (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_PROGRESS_CODE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_P_SERIAL_PORT_PC_CLEAR_BUFFER | EFI_PERIPHERAL_SERIAL_PORT,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->DevicePath
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Do the write
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Lsr.Bits.Thre == 1 && !IsaSerialFifoEmpty (&SerialDevice->Transmit)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Make sure the transmit data will not be missed
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (SerialDevice->HardwareFlowControl) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // For half handshake flow control assert RTS before sending.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mcr.Bits.Rts= 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Wait for CTS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TimeOut = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while ((Msr.Bits.Dcd == 1) && ((Msr.Bits.Cts == 0) ^ FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake))) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->Stall (TIMEOUT_STALL_INTERVAL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TimeOut++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TimeOut > 5) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Msr.Bits.Dcd == 0) || ((Msr.Bits.Cts == 1) ^ FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake))) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsaSerialFifoRemove (&SerialDevice->Transmit, &Data);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WRITE_THR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Data);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // For half handshake flow control, tell DCE we are done.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mcr.Bits.Rts = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsaSerialFifoRemove (&SerialDevice->Transmit, &Data);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WRITE_THR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Data);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } while (Lsr.Bits.Thre == 1 && !IsaSerialFifoEmpty (&SerialDevice->Transmit));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync// Interface Functions
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Reset serial device.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param This Pointer to EFI_SERIAL_IO_PROTOCOL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS Reset successfully
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_DEVICE_ERROR Failed to reset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIsaSerialReset (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_SERIAL_IO_PROTOCOL *This
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_DEV *SerialDevice;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_PORT_LCR Lcr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_PORT_IER Ier;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_PORT_MCR Mcr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_PORT_FCR Fcr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_TPL Tpl;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Control;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice = SERIAL_DEV_FROM_THIS (This);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Report the status code reset the serial
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync REPORT_STATUS_CODE_WITH_DEVICE_PATH (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_PROGRESS_CODE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_P_PC_RESET | EFI_PERIPHERAL_SERIAL_PORT,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->DevicePath
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tpl = gBS->RaiseTPL (TPL_NOTIFY);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Make sure DLAB is 0.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lcr.Data = READ_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lcr.Bits.DLab = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WRITE_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Lcr.Data);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Turn off all interrupts
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ier.Data = READ_IER (SerialDevice->IsaIo, SerialDevice->BaseAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ier.Bits.Ravie = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ier.Bits.Theie = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ier.Bits.Rie = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ier.Bits.Mie = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WRITE_IER (SerialDevice->IsaIo, SerialDevice->BaseAddress, Ier.Data);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Disable the FIFO.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fcr.Bits.TrFIFOE = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WRITE_FCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Fcr.Data);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Turn off loopback and disable device interrupt.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mcr.Bits.Out1 = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mcr.Bits.Out2 = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mcr.Bits.Lme = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Clear the scratch pad register
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Go set the current attributes
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = This->SetAttributes (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->Mode->BaudRate,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->Mode->ReceiveFifoDepth,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->Mode->Timeout,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_PARITY_TYPE) This->Mode->Parity,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT8) This->Mode->DataBits,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_STOP_BITS_TYPE) This->Mode->StopBits
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->RestoreTPL (Tpl);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_DEVICE_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Go set the current control bits
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Control = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (SerialDevice->HardwareFlowControl) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (SerialDevice->SoftwareLoopbackEnable) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Control |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = This->SetControl (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Control
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->RestoreTPL (Tpl);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_DEVICE_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // for 16550A enable FIFO, 16550 disable FIFO
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fcr.Bits.TrFIFOE = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fcr.Bits.ResetRF = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fcr.Bits.ResetTF = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WRITE_FCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Fcr.Data);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Reset the software FIFO
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->Receive.First = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->Receive.Last = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->Receive.Surplus = SERIAL_MAX_BUFFER_SIZE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->Transmit.First = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->Transmit.Last = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->Transmit.Surplus = SERIAL_MAX_BUFFER_SIZE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->RestoreTPL (Tpl);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Device reset is complete
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Set new attributes to a serial device.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param This Pointer to EFI_SERIAL_IO_PROTOCOL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param BaudRate The baudrate of the serial device
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ReceiveFifoDepth The depth of receive FIFO buffer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Timeout The request timeout for a single char
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Parity The type of parity used in serial device
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param DataBits Number of databits used in serial device
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param StopBits Number of stopbits used in serial device
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The new attributes were set
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_INVALID_PARAMETERS One or more attributes have an unsupported value
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_UNSUPPORTED Data Bits can not set to 5 or 6
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_DEVICE_ERROR The serial device is not functioning correctly (no return)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIsaSerialSetAttributes (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_SERIAL_IO_PROTOCOL *This,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT64 BaudRate,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 ReceiveFifoDepth,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 Timeout,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_PARITY_TYPE Parity,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 DataBits,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_STOP_BITS_TYPE StopBits
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_DEV *SerialDevice;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Divisor;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Remained;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_PORT_LCR Lcr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UART_DEVICE_PATH *Uart;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_TPL Tpl;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice = SERIAL_DEV_FROM_THIS (This);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check for default settings and fill in actual values.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (BaudRate == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BaudRate = PcdGet64 (PcdUartDefaultBaudRate);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ReceiveFifoDepth == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ReceiveFifoDepth = SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Timeout == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Timeout = SERIAL_PORT_DEFAULT_TIMEOUT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Parity == DefaultParity) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Parity = (EFI_PARITY_TYPE)PcdGet8 (PcdUartDefaultParity);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DataBits == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataBits = PcdGet8 (PcdUartDefaultDataBits);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (StopBits == DefaultStopBits) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync StopBits = (EFI_STOP_BITS_TYPE) PcdGet8 (PcdUartDefaultStopBits);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 5 and 6 data bits can not be verified on a 16550A UART
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Return EFI_INVALID_PARAMETER if an attempt is made to use these settings.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((DataBits == 5) || (DataBits == 6)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Make sure all parameters are valid
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((BaudRate > SERIAL_PORT_MAX_BAUD_RATE) || (BaudRate < SERIAL_PORT_MIN_BAUD_RATE)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 50,75,110,134,150,300,600,1200,1800,2000,2400,3600,4800,7200,9600,19200,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 38400,57600,115200
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (BaudRate < 75) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BaudRate = 50;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (BaudRate < 110) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BaudRate = 75;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (BaudRate < 134) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BaudRate = 110;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (BaudRate < 150) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BaudRate = 134;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (BaudRate < 300) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BaudRate = 150;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (BaudRate < 600) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BaudRate = 300;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (BaudRate < 1200) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BaudRate = 600;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (BaudRate < 1800) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BaudRate = 1200;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (BaudRate < 2000) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BaudRate = 1800;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (BaudRate < 2400) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BaudRate = 2000;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (BaudRate < 3600) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BaudRate = 2400;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (BaudRate < 4800) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BaudRate = 3600;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (BaudRate < 7200) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BaudRate = 4800;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (BaudRate < 9600) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BaudRate = 7200;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (BaudRate < 19200) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BaudRate = 9600;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (BaudRate < 38400) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BaudRate = 19200;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (BaudRate < 57600) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BaudRate = 38400;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (BaudRate < 115200) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BaudRate = 57600;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (BaudRate <= SERIAL_PORT_MAX_BAUD_RATE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BaudRate = 115200;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((ReceiveFifoDepth < 1) || (ReceiveFifoDepth > SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Timeout < SERIAL_PORT_MIN_TIMEOUT) || (Timeout > SERIAL_PORT_MAX_TIMEOUT)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Parity < NoParity) || (Parity > SpaceParity)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((DataBits < 5) || (DataBits > 8)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((StopBits < OneStopBit) || (StopBits > TwoStopBits)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((DataBits >= 6) && (DataBits <= 8) && (StopBits == OneFiveStopBits)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Compute divisor use to program the baud rate using a round determination
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Divisor = (UINT32) DivU64x32Remainder (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_PORT_INPUT_CLOCK,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ((UINT32) BaudRate * 16),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Remained
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Remained != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Divisor += 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Divisor == 0) || ((Divisor & 0xffff0000) != 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tpl = gBS->RaiseTPL (TPL_NOTIFY);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Compute the actual baud rate that the serial port will be programmed for.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BaudRate = SERIAL_PORT_INPUT_CLOCK / Divisor / 16;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Put serial port on Divisor Latch Mode
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lcr.Data = READ_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lcr.Bits.DLab = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WRITE_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Lcr.Data);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Write the divisor to the serial port
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WRITE_DLL (SerialDevice->IsaIo, SerialDevice->BaseAddress, (UINT8) (Divisor & 0xff));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WRITE_DLM (SerialDevice->IsaIo, SerialDevice->BaseAddress, (UINT8) ((Divisor >> 8) & 0xff));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Put serial port back in normal mode and set remaining attributes.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lcr.Bits.DLab = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (Parity) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case NoParity:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lcr.Bits.ParEn = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lcr.Bits.EvenPar = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lcr.Bits.SticPar = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case EvenParity:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lcr.Bits.ParEn = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lcr.Bits.EvenPar = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lcr.Bits.SticPar = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case OddParity:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lcr.Bits.ParEn = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lcr.Bits.EvenPar = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lcr.Bits.SticPar = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case SpaceParity:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lcr.Bits.ParEn = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lcr.Bits.EvenPar = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lcr.Bits.SticPar = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case MarkParity:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lcr.Bits.ParEn = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lcr.Bits.EvenPar = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lcr.Bits.SticPar = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (StopBits) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case OneStopBit:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lcr.Bits.StopB = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case OneFiveStopBits:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case TwoStopBits:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lcr.Bits.StopB = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DataBits
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Lcr.Bits.SerialDB = (UINT8) ((DataBits - 5) & 0x03);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WRITE_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Lcr.Data);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Set the Serial I/O mode
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->Mode->BaudRate = BaudRate;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->Mode->ReceiveFifoDepth = ReceiveFifoDepth;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->Mode->Timeout = Timeout;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->Mode->Parity = Parity;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->Mode->DataBits = DataBits;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->Mode->StopBits = StopBits;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // See if Device Path Node has actually changed
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (SerialDevice->UartDevicePath.BaudRate == BaudRate &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->UartDevicePath.DataBits == DataBits &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->UartDevicePath.Parity == Parity &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->UartDevicePath.StopBits == StopBits
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->RestoreTPL (Tpl);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update the device path
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->UartDevicePath.BaudRate = BaudRate;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->UartDevicePath.DataBits = DataBits;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->UartDevicePath.Parity = (UINT8) Parity;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->UartDevicePath.StopBits = (UINT8) StopBits;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (SerialDevice->Handle != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Uart = (UART_DEVICE_PATH *) (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINTN) SerialDevice->DevicePath
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync + GetDevicePathSize (SerialDevice->ParentDevicePath)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync - END_DEVICE_PATH_LENGTH
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (Uart, &SerialDevice->UartDevicePath, sizeof (UART_DEVICE_PATH));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->ReinstallProtocolInterface (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->Handle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiDevicePathProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->DevicePath,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->DevicePath
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->RestoreTPL (Tpl);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Set Control Bits.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param This Pointer to EFI_SERIAL_IO_PROTOCOL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Control Control bits that can be settable
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS New Control bits were set successfully
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_UNSUPPORTED The Control bits wanted to set are not supported
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIsaSerialSetControl (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_SERIAL_IO_PROTOCOL *This,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 Control
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_DEV *SerialDevice;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_PORT_MCR Mcr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_TPL Tpl;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UART_FLOW_CONTROL_DEVICE_PATH *FlowControl;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The control bits that can be set are :
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // EFI_SERIAL_DATA_TERMINAL_READY: 0x0001 // WO
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // EFI_SERIAL_REQUEST_TO_SEND: 0x0002 // WO
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE: 0x1000 // RW
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE: 0x2000 // RW
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE: 0x4000 // RW
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice = SERIAL_DEV_FROM_THIS (This);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // first determine the parameter is invalid
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY |
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE |
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_UNSUPPORTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tpl = gBS->RaiseTPL (TPL_NOTIFY);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mcr.Bits.DtrC = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mcr.Bits.Rts = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mcr.Bits.Lme = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->SoftwareLoopbackEnable = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->HardwareFlowControl = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) == EFI_SERIAL_DATA_TERMINAL_READY) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mcr.Bits.DtrC = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Control & EFI_SERIAL_REQUEST_TO_SEND) == EFI_SERIAL_REQUEST_TO_SEND) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mcr.Bits.Rts = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) == EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mcr.Bits.Lme = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) == EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->HardwareFlowControl = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Control & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) == EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->SoftwareLoopbackEnable = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (SerialDevice->Handle != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINTN) SerialDevice->DevicePath
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync + GetDevicePathSize (SerialDevice->ParentDevicePath)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync - END_DEVICE_PATH_LENGTH
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync + sizeof (UART_DEVICE_PATH)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IsUartFlowControlNode (FlowControl) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ((ReadUnaligned32 (&FlowControl->FlowControlMap) == UART_FLOW_CONTROL_HARDWARE) ^ SerialDevice->HardwareFlowControl)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Flow Control setting is changed, need to reinstall device path protocol
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WriteUnaligned32 (&FlowControl->FlowControlMap, SerialDevice->HardwareFlowControl ? UART_FLOW_CONTROL_HARDWARE : 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->ReinstallProtocolInterface (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->Handle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &gEfiDevicePathProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->DevicePath,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->DevicePath
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->RestoreTPL (Tpl);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Get ControlBits.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param This Pointer to EFI_SERIAL_IO_PROTOCOL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Control Control signals of the serial device
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS Get Control signals successfully
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIsaSerialGetControl (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_SERIAL_IO_PROTOCOL *This,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OUT UINT32 *Control
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_DEV *SerialDevice;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_PORT_MSR Msr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_PORT_MCR Mcr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_TPL Tpl;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tpl = gBS->RaiseTPL (TPL_NOTIFY);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice = SERIAL_DEV_FROM_THIS (This);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Control = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Read the Modem Status Register
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Msr.Bits.Cts == 1) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Control |= EFI_SERIAL_CLEAR_TO_SEND;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Msr.Bits.Dsr == 1) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Control |= EFI_SERIAL_DATA_SET_READY;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Msr.Bits.Ri == 1) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Control |= EFI_SERIAL_RING_INDICATE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Msr.Bits.Dcd == 1) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Control |= EFI_SERIAL_CARRIER_DETECT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Read the Modem Control Register
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Mcr.Bits.DtrC == 1) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Control |= EFI_SERIAL_DATA_TERMINAL_READY;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Mcr.Bits.Rts == 1) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Control |= EFI_SERIAL_REQUEST_TO_SEND;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Mcr.Bits.Lme == 1) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Control |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (SerialDevice->HardwareFlowControl) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // See if the Transmit FIFO is empty
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsaSerialReceiveTransmit (SerialDevice);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IsaSerialFifoEmpty (&SerialDevice->Transmit)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // See if the Receive FIFO is empty.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsaSerialReceiveTransmit (SerialDevice);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IsaSerialFifoEmpty (&SerialDevice->Receive)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (SerialDevice->SoftwareLoopbackEnable) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Control |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->RestoreTPL (Tpl);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Write the specified number of bytes to serial device.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param This Pointer to EFI_SERIAL_IO_PROTOCOL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param BufferSize On input the size of Buffer, on output the amount of
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync data actually written
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Buffer The buffer of data to write
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The data were written successfully
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_DEVICE_ERROR The device reported an error
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_TIMEOUT The write operation was stopped due to timeout
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIsaSerialWrite (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_SERIAL_IO_PROTOCOL *This,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT UINTN *BufferSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Buffer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_DEV *SerialDevice;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *CharBuffer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Index;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Elapsed;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN ActualWrite;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_TPL Tpl;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Timeout;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN BitsPerCharacter;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice = SERIAL_DEV_FROM_THIS (This);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Elapsed = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ActualWrite = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*BufferSize == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Buffer == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync REPORT_STATUS_CODE_WITH_DEVICE_PATH (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_ERROR_CODE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_P_EC_OUTPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->DevicePath
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_DEVICE_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tpl = gBS->RaiseTPL (TPL_NOTIFY);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CharBuffer = (UINT8 *) Buffer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Compute the number of bits in a single character. This is a start bit,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // followed by the number of data bits, followed by the number of stop bits.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The number of stop bits is specified by an enumeration that includes
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // support for 1.5 stop bits. Treat 1.5 stop bits as 2 stop bits.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BitsPerCharacter =
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 1 +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->Mode->DataBits +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ((This->Mode->StopBits == TwoStopBits) ? 2 : This->Mode->StopBits);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Compute the timeout in microseconds to wait for a single byte to be
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // transmitted. The Mode structure contans a Timeout field that is the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // maximum time to transmit or receive a character. However, many UARTs
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // have a FIFO for transmits, so the time required to add one new character
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // to the transmit FIFO may be the time required to flush a full FIFO. If
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the Timeout in the Mode structure is smaller than the time required to
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // flush a full FIFO at the current baud rate, then use a timeout value that
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // is required to flush a full transmit FIFO.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Timeout = MAX (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->Mode->Timeout,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINTN)DivU64x64Remainder (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BitsPerCharacter * (SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH + 1) * 1000000,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This->Mode->BaudRate,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < *BufferSize; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsaSerialFifoAdd (&SerialDevice->Transmit, CharBuffer[Index]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (IsaSerialReceiveTransmit (SerialDevice) != EFI_SUCCESS || !IsaSerialFifoEmpty (&SerialDevice->Transmit)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Unsuccessful write so check if timeout has expired, if not,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // stall for a bit, increment time elapsed, and try again
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Elapsed >= Timeout) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *BufferSize = ActualWrite;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->RestoreTPL (Tpl);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_TIMEOUT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->Stall (TIMEOUT_STALL_INTERVAL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Elapsed += TIMEOUT_STALL_INTERVAL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ActualWrite++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Successful write so reset timeout
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Elapsed = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->RestoreTPL (Tpl);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Read the specified number of bytes from serial device.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param This Pointer to EFI_SERIAL_IO_PROTOCOL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param BufferSize On input the size of Buffer, on output the amount of
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync data returned in buffer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Buffer The buffer to return the data into
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The data were read successfully
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_DEVICE_ERROR The device reported an error
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_TIMEOUT The read operation was stopped due to timeout
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIsaSerialRead (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_SERIAL_IO_PROTOCOL *This,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT UINTN *BufferSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OUT VOID *Buffer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SERIAL_DEV *SerialDevice;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Index;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *CharBuffer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Elapsed;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_TPL Tpl;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice = SERIAL_DEV_FROM_THIS (This);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Elapsed = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*BufferSize == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Buffer == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_DEVICE_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tpl = gBS->RaiseTPL (TPL_NOTIFY);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IsaSerialReceiveTransmit (SerialDevice);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *BufferSize = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync REPORT_STATUS_CODE_WITH_DEVICE_PATH (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_ERROR_CODE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_P_EC_INPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SerialDevice->DevicePath
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->RestoreTPL (Tpl);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_DEVICE_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CharBuffer = (UINT8 *) Buffer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < *BufferSize; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (IsaSerialFifoRemove (&SerialDevice->Receive, &(CharBuffer[Index])) != EFI_SUCCESS) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Unsuccessful read so check if timeout has expired, if not,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // stall for a bit, increment time elapsed, and try again
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Need this time out to get conspliter to work.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Elapsed >= This->Mode->Timeout) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *BufferSize = Index;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->RestoreTPL (Tpl);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_TIMEOUT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->Stall (TIMEOUT_STALL_INTERVAL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Elapsed += TIMEOUT_STALL_INTERVAL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IsaSerialReceiveTransmit (SerialDevice);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Status == EFI_DEVICE_ERROR) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *BufferSize = Index;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->RestoreTPL (Tpl);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_DEVICE_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Successful read so reset timeout
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Elapsed = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsaSerialReceiveTransmit (SerialDevice);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->RestoreTPL (Tpl);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Use scratchpad register to test if this serial port is present.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param SerialDevice Pointer to serial device structure
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return if this serial port is present
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncBOOLEAN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIsaSerialPortPresent (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN SERIAL_DEV *SerialDevice
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 Temp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Save SCR reg
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Temp = READ_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, 0xAA);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (READ_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress) != 0xAA) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, 0x55);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (READ_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress) != 0x55) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Restore SCR
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Temp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Use IsaIo protocol to read serial port.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param BaseAddress Serial port register group base address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Offset Offset in register group
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return Data read from serial port
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUINT8
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIsaSerialReadPort (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_ISA_IO_PROTOCOL *IsaIo,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT16 BaseAddress,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 Offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 Data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use IsaIo to access IO
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsaIo->Io.Read (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsaIo,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EfiIsaIoWidthUint8,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BaseAddress + Offset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 1,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Use IsaIo protocol to write serial port.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param BaseAddress Serial port register group base address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Offset Offset in register group
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Data data which is to be written to some serial port register
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIsaSerialWritePort (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_ISA_IO_PROTOCOL *IsaIo,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT16 BaseAddress,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 Offset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 Data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use IsaIo to access IO
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsaIo->Io.Write (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsaIo,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EfiIsaIoWidthUint8,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BaseAddress + Offset,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 1,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync