+++ /dev/null
-/**@file\r
-\r
-Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
-SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-Module Name:\r
-\r
- WinNtSerialIo.c\r
-\r
-Abstract:\r
-\r
- Our DriverBinding member functions operate on the handles\r
- created by the NT Bus driver.\r
-\r
- Handle(1) - WinNtIo - DevicePath(1)\r
-\r
- If a serial port is added to the system this driver creates a new handle.\r
- The new handle is required, since the serial device must add an UART device\r
- pathnode.\r
-\r
- Handle(2) - SerialIo - DevicePath(1)\UART\r
-\r
- The driver then adds a gEfiWinNtSerialPortGuid as a protocol to Handle(1).\r
- The instance data for this protocol is the private data used to create\r
- Handle(2).\r
-\r
- Handle(1) - WinNtIo - DevicePath(1) - WinNtSerialPort\r
-\r
- If the driver is unloaded Handle(2) is removed from the system and\r
- gEfiWinNtSerialPortGuid is removed from Handle(1).\r
-\r
- Note: Handle(1) is any handle created by the Win NT Bus driver that is passed\r
- into the DriverBinding member functions of this driver. This driver requires\r
- a Handle(1) to contain a WinNtIo protocol, a DevicePath protocol, and\r
- the TypeGuid in the WinNtIo must be gEfiWinNtSerialPortGuid.\r
-\r
- If Handle(1) contains a gEfiWinNtSerialPortGuid protocol then the driver is\r
- loaded on the device.\r
-\r
-**/\r
-\r
-#include "WinNtSerialIo.h"\r
-\r
-EFI_DRIVER_BINDING_PROTOCOL gWinNtSerialIoDriverBinding = {\r
- WinNtSerialIoDriverBindingSupported,\r
- WinNtSerialIoDriverBindingStart,\r
- WinNtSerialIoDriverBindingStop,\r
- 0xa,\r
- NULL,\r
- NULL\r
-};\r
-\r
-//\r
-// List of supported baud rate\r
-//\r
-UINT64 mBaudRateCurrentSupport[] = {50, 75, 110, 134, 150, 300, 600, 1200, 1800, 2000, 2400, 3600, 4800, 7200, 9600, 19200, 38400, 57600, 115200, SERIAL_PORT_MAX_BAUD_RATE + 1};\r
-\r
-/**\r
- Check the device path node whether it's the Flow Control node or not.\r
-\r
- @param[in] FlowControl The device path node to be checked.\r
- \r
- @retval TRUE It's the Flow Control node.\r
- @retval FALSE It's not.\r
-\r
-**/\r
-BOOLEAN\r
-IsUartFlowControlNode (\r
- IN UART_FLOW_CONTROL_DEVICE_PATH *FlowControl\r
- )\r
-{\r
- return (BOOLEAN) (\r
- (DevicePathType (FlowControl) == MESSAGING_DEVICE_PATH) &&\r
- (DevicePathSubType (FlowControl) == MSG_VENDOR_DP) &&\r
- (CompareGuid (&FlowControl->Guid, &gEfiUartDevicePathGuid))\r
- );\r
-}\r
-\r
-/**\r
- Check the device path node whether it contains Flow Control node or not.\r
-\r
- @param[in] DevicePath The device path to be checked.\r
- \r
- @retval TRUE It contains the Flow Control node.\r
- @retval FALSE It doesn't.\r
-\r
-**/\r
-BOOLEAN\r
-ContainsFlowControl (\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
- )\r
-{\r
- while (!IsDevicePathEnd (DevicePath)) {\r
- if (IsUartFlowControlNode ((UART_FLOW_CONTROL_DEVICE_PATH *) DevicePath)) {\r
- return TRUE;\r
- }\r
- DevicePath = NextDevicePathNode (DevicePath);\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-/**\r
- The user Entry Point for module WinNtSerialIo. The user code starts with this function.\r
-\r
- @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
- @param[in] SystemTable A pointer to the EFI System Table.\r
- \r
- @retval EFI_SUCCESS The entry point is executed successfully.\r
- @retval other Some error occurs when executing this entry point.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-InitializeWinNtSerialIo(\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- //\r
- // Install driver model protocol(s).\r
- //\r
- Status = EfiLibInstallDriverBindingComponentName2 (\r
- ImageHandle,\r
- SystemTable,\r
- &gWinNtSerialIoDriverBinding,\r
- ImageHandle,\r
- &gWinNtSerialIoComponentName,\r
- &gWinNtSerialIoComponentName2\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-WinNtSerialIoDriverBindingSupported (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Handle,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-Arguments:\r
-\r
-Returns:\r
-\r
- None\r
-\r
---*/\r
-// TODO: This - add argument and description to function comment\r
-// TODO: Handle - add argument and description to function comment\r
-// TODO: RemainingDevicePath - add argument and description to function comment\r
-// TODO: EFI_SUCCESS - add return value to function comment\r
-// TODO: EFI_SUCCESS - add return value to function comment\r
-{\r
- EFI_STATUS Status;\r
- EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
- EFI_WIN_NT_IO_PROTOCOL *WinNtIo;\r
- UART_DEVICE_PATH *UartNode;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- UART_FLOW_CONTROL_DEVICE_PATH *FlowControlNode;\r
- EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
- UINTN EntryCount;\r
- UINTN Index;\r
- BOOLEAN RemainingDevicePathContainsFlowControl; \r
-\r
- //\r
- // Check RemainingDevicePath validation\r
- //\r
- if (RemainingDevicePath != NULL) {\r
- //\r
- // Check if RemainingDevicePath is the End of Device Path Node, \r
- // if yes, go on checking other conditions\r
- //\r
- if (!IsDevicePathEnd (RemainingDevicePath)) {\r
- //\r
- // If RemainingDevicePath isn't the End of Device Path Node,\r
- // check its validation\r
- //\r
- Status = EFI_UNSUPPORTED;\r
-\r
- UartNode = (UART_DEVICE_PATH *) RemainingDevicePath;\r
- if (UartNode->Header.Type != MESSAGING_DEVICE_PATH ||\r
- UartNode->Header.SubType != MSG_UART_DP ||\r
- DevicePathNodeLength((EFI_DEVICE_PATH_PROTOCOL *)UartNode) != sizeof(UART_DEVICE_PATH)) {\r
- goto Error;\r
- }\r
- if ( UartNode->BaudRate > SERIAL_PORT_MAX_BAUD_RATE) {\r
- goto Error;\r
- }\r
- if (UartNode->Parity < NoParity || UartNode->Parity > SpaceParity) {\r
- goto Error;\r
- }\r
- if (UartNode->DataBits < 5 || UartNode->DataBits > 8) {\r
- goto Error;\r
- }\r
- if (UartNode->StopBits < OneStopBit || UartNode->StopBits > TwoStopBits) {\r
- goto Error;\r
- }\r
- if ((UartNode->DataBits == 5) && (UartNode->StopBits == TwoStopBits)) {\r
- goto Error;\r
- }\r
- if ((UartNode->DataBits >= 6) && (UartNode->DataBits <= 8) && (UartNode->StopBits == OneFiveStopBits)) {\r
- goto Error;\r
- }\r
-\r
- FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (UartNode);\r
- if (IsUartFlowControlNode (FlowControlNode)) {\r
- //\r
- // If the second node is Flow Control Node,\r
- // return error when it request other than hardware flow control.\r
- //\r
- if ((FlowControlNode->FlowControlMap & ~UART_FLOW_CONTROL_HARDWARE) != 0) {\r
- goto Error;\r
- }\r
- }\r
- }\r
- }\r
-\r
- //\r
- // Open the IO Abstraction(s) needed to perform the supported test\r
- //\r
- Status = gBS->OpenProtocol (\r
- Handle,\r
- &gEfiWinNtIoProtocolGuid,\r
- (VOID **) &WinNtIo,\r
- This->DriverBindingHandle,\r
- Handle,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
- if (Status == EFI_ALREADY_STARTED) {\r
- if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) {\r
- //\r
- // If RemainingDevicePath is NULL or is the End of Device Path Node\r
- //\r
- return EFI_SUCCESS;\r
- }\r
- //\r
- // When the driver has produced device path with flow control node but RemainingDevicePath only contains UART node,\r
- // return unsupported, and vice versa.\r
- //\r
- Status = gBS->OpenProtocolInformation (\r
- Handle,\r
- &gEfiWinNtIoProtocolGuid,\r
- &OpenInfoBuffer,\r
- &EntryCount\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // See if RemainingDevicePath has a Flow Control device path node\r
- //\r
- RemainingDevicePathContainsFlowControl = ContainsFlowControl (RemainingDevicePath);\r
- \r
- for (Index = 0; Index < EntryCount; Index++) {\r
- if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
- Status = gBS->OpenProtocol (\r
- OpenInfoBuffer[Index].ControllerHandle,\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID **) &DevicePath,\r
- This->DriverBindingHandle,\r
- Handle,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- if (RemainingDevicePathContainsFlowControl ^ ContainsFlowControl (DevicePath)) {\r
- Status = EFI_UNSUPPORTED;\r
- }\r
- }\r
- break;\r
- }\r
- }\r
- FreePool (OpenInfoBuffer);\r
- return Status;\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Close the I/O Abstraction(s) used to perform the supported test\r
- //\r
- gBS->CloseProtocol (\r
- Handle,\r
- &gEfiWinNtIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Handle\r
- );\r
-\r
- //\r
- // Open the EFI Device Path protocol needed to perform the supported test\r
- //\r
- Status = gBS->OpenProtocol (\r
- Handle,\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID **) &ParentDevicePath,\r
- This->DriverBindingHandle,\r
- Handle,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
- if (Status == EFI_ALREADY_STARTED) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Close protocol, don't use device path protocol in the Support() function\r
- //\r
- gBS->CloseProtocol (\r
- Handle,\r
- &gEfiDevicePathProtocolGuid,\r
- This->DriverBindingHandle,\r
- Handle\r
- );\r
-\r
- //\r
- // Make sure that the WinNt Thunk Protocol is valid\r
- //\r
- if (WinNtIo->WinNtThunk->Signature != EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) {\r
- Status = EFI_UNSUPPORTED;\r
- goto Error;\r
- }\r
-\r
- //\r
- // Check the GUID to see if this is a handle type the driver supports\r
- //\r
- if (!CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtSerialPortGuid)) {\r
- Status = EFI_UNSUPPORTED;\r
- goto Error;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-\r
-Error:\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-WinNtSerialIoDriverBindingStart (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Handle,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-Arguments:\r
-\r
-Returns:\r
-\r
- None\r
-\r
---*/\r
-// TODO: This - add argument and description to function comment\r
-// TODO: Handle - add argument and description to function comment\r
-// TODO: RemainingDevicePath - add argument and description to function comment\r
-// TODO: EFI_SUCCESS - add return value to function comment\r
-// TODO: EFI_SUCCESS - add return value to function comment\r
-{\r
- EFI_STATUS Status;\r
- EFI_WIN_NT_IO_PROTOCOL *WinNtIo;\r
- WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;\r
- HANDLE NtHandle;\r
- UART_DEVICE_PATH UartNode;\r
- EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
- EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
- UINTN EntryCount;\r
- UINTN Index;\r
- EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
- UART_DEVICE_PATH *Uart;\r
- UINT32 FlowControlMap;\r
- UART_FLOW_CONTROL_DEVICE_PATH *FlowControl;\r
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
- UINT32 Control;\r
-\r
- Private = NULL;\r
- NtHandle = INVALID_HANDLE_VALUE;\r
-\r
- //\r
- // Get the Parent Device Path\r
- //\r
- Status = gBS->OpenProtocol (\r
- Handle,\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID **) &ParentDevicePath,\r
- This->DriverBindingHandle,\r
- Handle,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
- if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Grab the IO abstraction we need to get any work done\r
- //\r
- Status = gBS->OpenProtocol (\r
- Handle,\r
- &gEfiWinNtIoProtocolGuid,\r
- (VOID **) &WinNtIo,\r
- This->DriverBindingHandle,\r
- Handle,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
- if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
- gBS->CloseProtocol (\r
- Handle,\r
- &gEfiDevicePathProtocolGuid,\r
- This->DriverBindingHandle,\r
- Handle\r
- );\r
- return Status;\r
- }\r
-\r
- if (Status == EFI_ALREADY_STARTED) {\r
-\r
- if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) {\r
- //\r
- // If RemainingDevicePath is NULL or is the End of Device Path Node\r
- //\r
- return EFI_SUCCESS;\r
- }\r
-\r
- //\r
- // Make sure a child handle does not already exist. This driver can only\r
- // produce one child per serial port.\r
- //\r
- Status = gBS->OpenProtocolInformation (\r
- Handle,\r
- &gEfiWinNtIoProtocolGuid,\r
- &OpenInfoBuffer,\r
- &EntryCount\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Status = EFI_ALREADY_STARTED;\r
- for (Index = 0; Index < EntryCount; Index++) {\r
- if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
- Status = gBS->OpenProtocol (\r
- OpenInfoBuffer[Index].ControllerHandle,\r
- &gEfiSerialIoProtocolGuid,\r
- (VOID **) &SerialIo,\r
- This->DriverBindingHandle,\r
- Handle,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- Uart = (UART_DEVICE_PATH *) RemainingDevicePath;\r
- Status = SerialIo->SetAttributes (\r
- SerialIo,\r
- Uart->BaudRate,\r
- SerialIo->Mode->ReceiveFifoDepth,\r
- SerialIo->Mode->Timeout,\r
- (EFI_PARITY_TYPE) Uart->Parity,\r
- Uart->DataBits,\r
- (EFI_STOP_BITS_TYPE) Uart->StopBits\r
- );\r
- FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Uart);\r
- if (!EFI_ERROR (Status) && IsUartFlowControlNode (FlowControl)) {\r
- Status = SerialIo->GetControl (SerialIo, &Control);\r
- if (!EFI_ERROR (Status)) {\r
- if (FlowControl->FlowControlMap == UART_FLOW_CONTROL_HARDWARE) {\r
- Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;\r
- } else {\r
- Control &= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;\r
- }\r
- //\r
- // Clear the bits that are not allowed to pass to SetControl\r
- //\r
- Control &= (EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY |\r
- EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE | \r
- EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE);\r
- Status = SerialIo->SetControl (SerialIo, Control);\r
- }\r
- }\r
- }\r
- break;\r
- }\r
- }\r
-\r
- FreePool (OpenInfoBuffer);\r
- return Status;\r
- }\r
-\r
- FlowControl = NULL;\r
- FlowControlMap = 0;\r
- if (RemainingDevicePath == NULL) {\r
- //\r
- // Build the device path by appending the UART node to the ParentDevicePath\r
- // from the WinNtIo handle. The Uart setings are zero here, since\r
- // SetAttribute() will update them to match the default setings.\r
- //\r
- ZeroMem (&UartNode, sizeof (UART_DEVICE_PATH));\r
- UartNode.Header.Type = MESSAGING_DEVICE_PATH;\r
- UartNode.Header.SubType = MSG_UART_DP;\r
- SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) &UartNode, sizeof (UART_DEVICE_PATH));\r
-\r
- } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
- //\r
- // If RemainingDevicePath isn't the End of Device Path Node, \r
- // only scan the specified device by RemainingDevicePath\r
- //\r
- //\r
- // Match the configuration of the RemainingDevicePath. IsHandleSupported()\r
- // already checked to make sure the RemainingDevicePath contains settings\r
- // that we can support.\r
- //\r
- CopyMem (&UartNode, RemainingDevicePath, sizeof (UART_DEVICE_PATH));\r
- FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (RemainingDevicePath);\r
- if (IsUartFlowControlNode (FlowControl)) {\r
- FlowControlMap = FlowControl->FlowControlMap;\r
- } else {\r
- FlowControl = NULL;\r
- }\r
-\r
- } else {\r
- //\r
- // If RemainingDevicePath is the End of Device Path Node,\r
- // skip enumerate any device and return EFI_SUCESSS\r
- // \r
- return EFI_SUCCESS;\r
- }\r
-\r
- //\r
- // Check to see if we can access the hardware device. If it's Open in NT we\r
- // will not get access.\r
- //\r
- NtHandle = WinNtIo->WinNtThunk->CreateFile (\r
- WinNtIo->EnvString,\r
- GENERIC_READ | GENERIC_WRITE,\r
- 0,\r
- NULL,\r
- OPEN_EXISTING,\r
- 0,\r
- NULL\r
- );\r
- if (NtHandle == INVALID_HANDLE_VALUE) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto Error;\r
- }\r
-\r
- //\r
- // Construct Private data\r
- //\r
- Private = AllocatePool (sizeof (WIN_NT_SERIAL_IO_PRIVATE_DATA));\r
- if (Private == NULL) {\r
- goto Error;\r
- }\r
-\r
- //\r
- // This signature must be valid before any member function is called\r
- //\r
- Private->Signature = WIN_NT_SERIAL_IO_PRIVATE_DATA_SIGNATURE;\r
- Private->NtHandle = NtHandle;\r
- Private->ControllerHandle = Handle;\r
- Private->Handle = NULL;\r
- Private->WinNtThunk = WinNtIo->WinNtThunk;\r
- Private->ParentDevicePath = ParentDevicePath;\r
- Private->ControllerNameTable = NULL;\r
-\r
- Private->SoftwareLoopbackEnable = FALSE;\r
- Private->HardwareLoopbackEnable = FALSE;\r
- Private->HardwareFlowControl = (BOOLEAN) (FlowControlMap == UART_FLOW_CONTROL_HARDWARE);\r
- Private->Fifo.First = 0;\r
- Private->Fifo.Last = 0;\r
- Private->Fifo.Surplus = SERIAL_MAX_BUFFER_SIZE;\r
-\r
- CopyMem (&Private->UartDevicePath, &UartNode, sizeof (UART_DEVICE_PATH));\r
-\r
- AddUnicodeString2 (\r
- "eng",\r
- gWinNtSerialIoComponentName.SupportedLanguages,\r
- &Private->ControllerNameTable,\r
- WinNtIo->EnvString,\r
- TRUE\r
- );\r
- AddUnicodeString2 (\r
- "en",\r
- gWinNtSerialIoComponentName2.SupportedLanguages,\r
- &Private->ControllerNameTable,\r
- WinNtIo->EnvString,\r
- FALSE\r
- );\r
-\r
-\r
- Private->SerialIo.Revision = SERIAL_IO_INTERFACE_REVISION;\r
- Private->SerialIo.Reset = WinNtSerialIoReset;\r
- Private->SerialIo.SetAttributes = WinNtSerialIoSetAttributes;\r
- Private->SerialIo.SetControl = WinNtSerialIoSetControl;\r
- Private->SerialIo.GetControl = WinNtSerialIoGetControl;\r
- Private->SerialIo.Write = WinNtSerialIoWrite;\r
- Private->SerialIo.Read = WinNtSerialIoRead;\r
- Private->SerialIo.Mode = &Private->SerialIoMode;\r
-\r
- //\r
- // Build the device path by appending the UART node to the ParentDevicePath\r
- // from the WinNtIo handle. The Uart setings are zero here, since\r
- // SetAttribute() will update them to match the current setings.\r
- //\r
- Private->DevicePath = AppendDevicePathNode (\r
- ParentDevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *) &Private->UartDevicePath\r
- );\r
- //\r
- // Only produce the FlowControl node when remaining device path has it\r
- //\r
- if (FlowControl != NULL) {\r
- TempDevicePath = Private->DevicePath;\r
- if (TempDevicePath != NULL) {\r
- Private->DevicePath = AppendDevicePathNode (\r
- TempDevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *) FlowControl\r
- );\r
- FreePool (TempDevicePath);\r
- }\r
- }\r
- if (Private->DevicePath == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Error;\r
- }\r
-\r
- //\r
- // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.\r
- //\r
- Private->SerialIoMode.ControlMask = SERIAL_CONTROL_MASK;\r
- Private->SerialIoMode.Timeout = SERIAL_TIMEOUT_DEFAULT;\r
- Private->SerialIoMode.BaudRate = Private->UartDevicePath.BaudRate;\r
- Private->SerialIoMode.ReceiveFifoDepth = SERIAL_FIFO_DEFAULT;\r
- Private->SerialIoMode.DataBits = Private->UartDevicePath.DataBits;\r
- Private->SerialIoMode.Parity = Private->UartDevicePath.Parity;\r
- Private->SerialIoMode.StopBits = Private->UartDevicePath.StopBits;\r
-\r
- //\r
- // Issue a reset to initialize the COM port\r
- //\r
- Status = Private->SerialIo.Reset (&Private->SerialIo);\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
-\r
- //\r
- // Create new child handle\r
- //\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &Private->Handle,\r
- &gEfiSerialIoProtocolGuid,\r
- &Private->SerialIo,\r
- &gEfiDevicePathProtocolGuid,\r
- Private->DevicePath,\r
- NULL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
-\r
- //\r
- // Open For Child Device\r
- //\r
- Status = gBS->OpenProtocol (\r
- Handle,\r
- &gEfiWinNtIoProtocolGuid,\r
- (VOID **) &WinNtIo,\r
- This->DriverBindingHandle,\r
- Private->Handle,\r
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-\r
-Error:\r
- //\r
- // Use the Stop() function to free all resources allocated in Start()\r
- //\r
- if (Private != NULL) {\r
- if (Private->Handle != NULL) {\r
- This->Stop (This, Handle, 1, &Private->Handle);\r
- } else {\r
- if (NtHandle != INVALID_HANDLE_VALUE) {\r
- Private->WinNtThunk->CloseHandle (NtHandle);\r
- }\r
-\r
- if (Private->DevicePath != NULL) {\r
- FreePool (Private->DevicePath);\r
- }\r
-\r
- FreeUnicodeStringTable (Private->ControllerNameTable);\r
-\r
- FreePool (Private);\r
- }\r
- }\r
-\r
- This->Stop (This, Handle, 0, NULL);\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-WinNtSerialIoDriverBindingStop (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Handle,\r
- IN UINTN NumberOfChildren,\r
- IN EFI_HANDLE *ChildHandleBuffer\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- TODO: Add function description\r
-\r
-Arguments:\r
-\r
- This - TODO: add argument description\r
- Handle - TODO: add argument description\r
- NumberOfChildren - TODO: add argument description\r
- ChildHandleBuffer - TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_DEVICE_ERROR - TODO: Add description for return value\r
- EFI_SUCCESS - TODO: Add description for return value\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- UINTN Index;\r
- BOOLEAN AllChildrenStopped;\r
- EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
- WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;\r
- EFI_WIN_NT_IO_PROTOCOL *WinNtIo;\r
-\r
- //\r
- // Complete all outstanding transactions to Controller.\r
- // Don't allow any new transaction to Controller to be started.\r
- //\r
-\r
- if (NumberOfChildren == 0) {\r
- //\r
- // Close the bus driver\r
- //\r
- Status = gBS->CloseProtocol (\r
- Handle,\r
- &gEfiWinNtIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Handle\r
- );\r
- Status = gBS->CloseProtocol (\r
- Handle,\r
- &gEfiDevicePathProtocolGuid,\r
- This->DriverBindingHandle,\r
- Handle\r
- );\r
- return Status;\r
- }\r
-\r
- AllChildrenStopped = TRUE;\r
-\r
- for (Index = 0; Index < NumberOfChildren; Index++) {\r
- Status = gBS->OpenProtocol (\r
- ChildHandleBuffer[Index],\r
- &gEfiSerialIoProtocolGuid,\r
- (VOID **) &SerialIo,\r
- This->DriverBindingHandle,\r
- Handle,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (SerialIo);\r
-\r
- ASSERT (Private->Handle == ChildHandleBuffer[Index]);\r
-\r
- Status = gBS->CloseProtocol (\r
- Handle,\r
- &gEfiWinNtIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- ChildHandleBuffer[Index]\r
- );\r
-\r
- Status = gBS->UninstallMultipleProtocolInterfaces (\r
- ChildHandleBuffer[Index],\r
- &gEfiSerialIoProtocolGuid,\r
- &Private->SerialIo,\r
- &gEfiDevicePathProtocolGuid,\r
- Private->DevicePath,\r
- NULL\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- gBS->OpenProtocol (\r
- Handle,\r
- &gEfiWinNtIoProtocolGuid,\r
- (VOID **) &WinNtIo,\r
- This->DriverBindingHandle,\r
- ChildHandleBuffer[Index],\r
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
- );\r
- } else {\r
- Private->WinNtThunk->CloseHandle (Private->NtHandle);\r
-\r
- FreePool (Private->DevicePath);\r
-\r
- FreeUnicodeStringTable (Private->ControllerNameTable);\r
-\r
- FreePool (Private);\r
- }\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- AllChildrenStopped = FALSE;\r
- }\r
- }\r
-\r
- if (!AllChildrenStopped) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-//\r
-// Serial IO Protocol member functions\r
-//\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-WinNtSerialIoReset (\r
- IN EFI_SERIAL_IO_PROTOCOL *This\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- TODO: Add function description\r
-\r
-Arguments:\r
-\r
- This - TODO: add argument description\r
-\r
-Returns:\r
-\r
- TODO: add return values\r
-\r
---*/\r
-{\r
- WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;\r
- EFI_TPL Tpl;\r
-\r
- Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
-\r
- Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);\r
-\r
- Private->WinNtThunk->PurgeComm (\r
- Private->NtHandle,\r
- PURGE_TXCLEAR | PURGE_RXCLEAR\r
- );\r
-\r
- gBS->RestoreTPL (Tpl);\r
-\r
- return This->SetAttributes (\r
- This,\r
- This->Mode->BaudRate,\r
- This->Mode->ReceiveFifoDepth,\r
- This->Mode->Timeout,\r
- (EFI_PARITY_TYPE)This->Mode->Parity,\r
- (UINT8) This->Mode->DataBits,\r
- (EFI_STOP_BITS_TYPE)This->Mode->StopBits\r
- );\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-WinNtSerialIoSetAttributes (\r
- IN EFI_SERIAL_IO_PROTOCOL *This,\r
- IN UINT64 BaudRate,\r
- IN UINT32 ReceiveFifoDepth,\r
- IN UINT32 Timeout,\r
- IN EFI_PARITY_TYPE Parity,\r
- IN UINT8 DataBits,\r
- IN EFI_STOP_BITS_TYPE StopBits\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- This function is used to set the attributes.\r
-\r
-Arguments:\r
-\r
- This - A pointer to the EFI_SERIAL_IO_PROTOCOL structrue.\r
- BaudRate - The Baud rate of the serial device.\r
- ReceiveFifoDepth - The request depth of fifo on receive side.\r
- Timeout - the request timeout for a single charact.\r
- Parity - The type of parity used in serial device.\r
- DataBits - Number of deata bits used in serial device.\r
- StopBits - Number of stop bits used in serial device.\r
-\r
-Returns:\r
- Status code\r
-\r
- None\r
-\r
---*/\r
-// TODO: EFI_SUCCESS - add return value to function comment\r
-// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
-// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
-// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
-// TODO: EFI_SUCCESS - add return value to function comment\r
-// TODO: EFI_DEVICE_ERROR - add return value to function comment\r
-// TODO: EFI_SUCCESS - add return value to function comment\r
-{\r
- EFI_STATUS Status;\r
- UINTN Index; \r
- WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;\r
- COMMTIMEOUTS PortTimeOuts;\r
- DWORD ConvertedTime;\r
- BOOL Result;\r
- UART_DEVICE_PATH *Uart;\r
- EFI_TPL Tpl;\r
-\r
- Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);\r
-\r
- //\r
- // Some of our arguments have defaults if a null value is passed in, and\r
- // we must set the default values if a null argument is passed in.\r
- //\r
- if (BaudRate == 0) {\r
- BaudRate = PcdGet64 (PcdUartDefaultBaudRate);\r
- }\r
-\r
- if (ReceiveFifoDepth == 0) {\r
- ReceiveFifoDepth = SERIAL_FIFO_DEFAULT;\r
- }\r
-\r
- if (Timeout == 0) {\r
- Timeout = SERIAL_TIMEOUT_DEFAULT;\r
- }\r
-\r
- if (Parity == DefaultParity) {\r
- Parity = (EFI_PARITY_TYPE) (PcdGet8 (PcdUartDefaultParity));\r
- }\r
-\r
- if (DataBits == 0) {\r
- DataBits = PcdGet8 (PcdUartDefaultDataBits);\r
- }\r
-\r
- if (StopBits == DefaultStopBits) {\r
- StopBits = (EFI_STOP_BITS_TYPE) PcdGet8 (PcdUartDefaultStopBits);\r
- }\r
-\r
- //\r
- // Make sure all parameters are valid\r
- //\r
- if ((BaudRate > SERIAL_PORT_MAX_BAUD_RATE) || (BaudRate < SERIAL_PORT_MIN_BAUD_RATE)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- //The lower baud rate supported by the serial device will be selected without exceeding the unsupported BaudRate parameter\r
- // \r
- \r
- for (Index = 1; Index < (ARRAY_SIZE (mBaudRateCurrentSupport)); Index++) {\r
- if (BaudRate < mBaudRateCurrentSupport[Index]) {\r
- BaudRate = mBaudRateCurrentSupport[Index-1];\r
- break;\r
- }\r
- }\r
-\r
- if ((ReceiveFifoDepth < 1) || (ReceiveFifoDepth > SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if ((Timeout < SERIAL_PORT_MIN_TIMEOUT) || (Timeout > SERIAL_PORT_MAX_TIMEOUT)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if ((Parity < NoParity) || (Parity > SpaceParity)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if ((StopBits < OneStopBit) || (StopBits > TwoStopBits)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Now we only support DataBits=7,8.\r
- //\r
- if ((DataBits < 7) || (DataBits > 8)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- \r
- //\r
- // Now we only support DataBits=7,8.\r
- // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits.\r
- //\r
- if (StopBits == OneFiveStopBits) {\r
- return EFI_INVALID_PARAMETER;\r
- } \r
- \r
- //\r
- // See if the new attributes already match the current attributes\r
- //\r
- if (Private->UartDevicePath.BaudRate == BaudRate &&\r
- Private->UartDevicePath.DataBits == DataBits &&\r
- Private->UartDevicePath.Parity == Parity &&\r
- Private->UartDevicePath.StopBits == StopBits &&\r
- Private->SerialIoMode.ReceiveFifoDepth == ReceiveFifoDepth &&\r
- Private->SerialIoMode.Timeout == Timeout ) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
-\r
- //\r
- // Get current values from NT\r
- //\r
- ZeroMem (&Private->NtDCB, sizeof (DCB));\r
- Private->NtDCB.DCBlength = sizeof (DCB);\r
-\r
- if (!Private->WinNtThunk->GetCommState (Private->NtHandle, &Private->NtDCB)) {\r
- Private->NtError = Private->WinNtThunk->GetLastError ();\r
- DEBUG ((EFI_D_ERROR, "SerialSetAttributes: GetCommState %d\n", Private->NtError));\r
- gBS->RestoreTPL (Tpl);\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- //\r
- // Map EFI com setting to NT\r
- //\r
- Private->NtDCB.BaudRate = ConvertBaud2Nt (BaudRate);\r
- Private->NtDCB.ByteSize = ConvertData2Nt (DataBits);\r
- Private->NtDCB.Parity = ConvertParity2Nt (Parity);\r
- Private->NtDCB.StopBits = ConvertStop2Nt (StopBits);\r
-\r
- Private->NtDCB.fBinary = TRUE;\r
- Private->NtDCB.fParity = Private->NtDCB.Parity == NOPARITY ? FALSE : TRUE;\r
- Private->NtDCB.fOutxCtsFlow = FALSE;\r
- Private->NtDCB.fOutxDsrFlow = FALSE;\r
- Private->NtDCB.fDtrControl = DTR_CONTROL_ENABLE;\r
- Private->NtDCB.fDsrSensitivity = FALSE;\r
- Private->NtDCB.fOutX = FALSE;\r
- Private->NtDCB.fInX = FALSE;\r
- Private->NtDCB.fRtsControl = RTS_CONTROL_ENABLE;\r
- Private->NtDCB.fNull = FALSE;\r
-\r
- //\r
- // Set new values\r
- //\r
- Result = Private->WinNtThunk->SetCommState (Private->NtHandle, &Private->NtDCB);\r
- if (!Result) {\r
- Private->NtError = Private->WinNtThunk->GetLastError ();\r
- DEBUG ((EFI_D_ERROR, "SerialSetAttributes: SetCommState %d\n", Private->NtError));\r
- gBS->RestoreTPL (Tpl);\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- //\r
- // Set com port read/write timeout values\r
- //\r
- ConvertedTime = ConvertTime2Nt (Timeout);\r
- PortTimeOuts.ReadIntervalTimeout = MAXDWORD;\r
- PortTimeOuts.ReadTotalTimeoutMultiplier = 0;\r
- PortTimeOuts.ReadTotalTimeoutConstant = ConvertedTime;\r
- PortTimeOuts.WriteTotalTimeoutMultiplier = ConvertedTime == 0 ? 1 : ConvertedTime;\r
- PortTimeOuts.WriteTotalTimeoutConstant = 0;\r
-\r
- if (!Private->WinNtThunk->SetCommTimeouts (Private->NtHandle, &PortTimeOuts)) {\r
- Private->NtError = Private->WinNtThunk->GetLastError ();\r
- DEBUG ((EFI_D_ERROR, "SerialSetAttributes: SetCommTimeouts %d\n", Private->NtError));\r
- gBS->RestoreTPL (Tpl);\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- //\r
- // Update mode\r
- //\r
- Private->SerialIoMode.BaudRate = BaudRate;\r
- Private->SerialIoMode.ReceiveFifoDepth = ReceiveFifoDepth;\r
- Private->SerialIoMode.Timeout = Timeout;\r
- Private->SerialIoMode.Parity = Parity;\r
- Private->SerialIoMode.DataBits = DataBits;\r
- Private->SerialIoMode.StopBits = StopBits;\r
-\r
- //\r
- // See if Device Path Node has actually changed\r
- //\r
- if (Private->UartDevicePath.BaudRate == BaudRate &&\r
- Private->UartDevicePath.DataBits == DataBits &&\r
- Private->UartDevicePath.Parity == Parity &&\r
- Private->UartDevicePath.StopBits == StopBits ) {\r
- gBS->RestoreTPL(Tpl);\r
- return EFI_SUCCESS;\r
- }\r
-\r
- //\r
- // Update the device path\r
- //\r
- Private->UartDevicePath.BaudRate = BaudRate;\r
- Private->UartDevicePath.DataBits = DataBits;\r
- Private->UartDevicePath.Parity = (UINT8) Parity;\r
- Private->UartDevicePath.StopBits = (UINT8) StopBits;\r
-\r
- Status = EFI_SUCCESS;\r
- if (Private->Handle != NULL) {\r
- Uart = (UART_DEVICE_PATH *) (\r
- (UINTN) Private->DevicePath\r
- + GetDevicePathSize (Private->ParentDevicePath)\r
- - END_DEVICE_PATH_LENGTH\r
- );\r
- CopyMem (Uart, &Private->UartDevicePath, sizeof (UART_DEVICE_PATH));\r
- Status = gBS->ReinstallProtocolInterface (\r
- Private->Handle,\r
- &gEfiDevicePathProtocolGuid,\r
- Private->DevicePath,\r
- Private->DevicePath\r
- );\r
- }\r
-\r
- gBS->RestoreTPL (Tpl);\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-WinNtSerialIoSetControl (\r
- IN EFI_SERIAL_IO_PROTOCOL *This,\r
- IN UINT32 Control\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- TODO: Add function description\r
-\r
-Arguments:\r
-\r
- This - TODO: add argument description\r
- Control - TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_DEVICE_ERROR - TODO: Add description for return value\r
- EFI_DEVICE_ERROR - TODO: Add description for return value\r
- EFI_SUCCESS - TODO: Add description for return value\r
-\r
---*/\r
-{\r
- WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;\r
- BOOL Result;\r
- DCB Dcb;\r
- EFI_TPL Tpl;\r
- UART_FLOW_CONTROL_DEVICE_PATH *FlowControl;\r
- EFI_STATUS Status;\r
-\r
- //\r
- // first determine the parameter is invalid\r
- //\r
- if (Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY |\r
- EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE | \r
- EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
-\r
- Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);\r
-\r
- Result = Private->WinNtThunk->GetCommState (Private->NtHandle, &Dcb);\r
-\r
- if (!Result) {\r
- Private->NtError = Private->WinNtThunk->GetLastError ();\r
- DEBUG ((EFI_D_ERROR, "SerialSetControl: GetCommState %d\n", Private->NtError));\r
- gBS->RestoreTPL (Tpl);\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- Dcb.fRtsControl = RTS_CONTROL_DISABLE;\r
- Dcb.fDtrControl = DTR_CONTROL_DISABLE;\r
- Private->HardwareFlowControl = FALSE;\r
- Private->SoftwareLoopbackEnable = FALSE;\r
- Private->HardwareLoopbackEnable = FALSE;\r
-\r
- if (Control & EFI_SERIAL_REQUEST_TO_SEND) {\r
- Dcb.fRtsControl = RTS_CONTROL_ENABLE;\r
- }\r
-\r
- if (Control & EFI_SERIAL_DATA_TERMINAL_READY) {\r
- Dcb.fDtrControl = DTR_CONTROL_ENABLE;\r
- }\r
-\r
- if (Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {\r
- Private->HardwareFlowControl = TRUE;\r
- }\r
-\r
- if (Control & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) {\r
- Private->SoftwareLoopbackEnable = TRUE;\r
- }\r
-\r
- if (Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) {\r
- Private->HardwareLoopbackEnable = TRUE;\r
- }\r
-\r
- Result = Private->WinNtThunk->SetCommState (\r
- Private->NtHandle,\r
- &Dcb\r
- );\r
-\r
- if (!Result) {\r
- Private->NtError = Private->WinNtThunk->GetLastError ();\r
- DEBUG ((EFI_D_ERROR, "SerialSetControl: SetCommState %d\n", Private->NtError));\r
- gBS->RestoreTPL (Tpl);\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- Status = EFI_SUCCESS;\r
- if (Private->Handle != NULL) {\r
- FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) (\r
- (UINTN) Private->DevicePath\r
- + GetDevicePathSize (Private->ParentDevicePath)\r
- - END_DEVICE_PATH_LENGTH\r
- + sizeof (UART_DEVICE_PATH)\r
- );\r
- if (IsUartFlowControlNode (FlowControl) &&\r
- ((FlowControl->FlowControlMap == UART_FLOW_CONTROL_HARDWARE) ^ Private->HardwareFlowControl)) {\r
- //\r
- // Flow Control setting is changed, need to reinstall device path protocol\r
- //\r
- FlowControl->FlowControlMap = Private->HardwareFlowControl ? UART_FLOW_CONTROL_HARDWARE : 0;\r
- Status = gBS->ReinstallProtocolInterface (\r
- Private->Handle,\r
- &gEfiDevicePathProtocolGuid,\r
- Private->DevicePath,\r
- Private->DevicePath\r
- );\r
- }\r
- }\r
-\r
- gBS->RestoreTPL (Tpl);\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-WinNtSerialIoGetControl (\r
- IN EFI_SERIAL_IO_PROTOCOL *This,\r
- OUT UINT32 *Control\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- TODO: Add function description\r
-\r
-Arguments:\r
-\r
- This - TODO: add argument description\r
- Control - TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_DEVICE_ERROR - TODO: Add description for return value\r
- EFI_DEVICE_ERROR - TODO: Add description for return value\r
- EFI_DEVICE_ERROR - TODO: Add description for return value\r
- EFI_SUCCESS - TODO: Add description for return value\r
-\r
---*/\r
-{\r
- WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;\r
- DWORD ModemStatus;\r
- DWORD Errors;\r
- UINT32 Bits;\r
- DCB Dcb;\r
- EFI_TPL Tpl;\r
-\r
- Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
-\r
- Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);\r
-\r
- //\r
- // Get modem status\r
- //\r
- if (!Private->WinNtThunk->GetCommModemStatus (Private->NtHandle, &ModemStatus)) {\r
- Private->NtError = Private->WinNtThunk->GetLastError ();\r
- gBS->RestoreTPL (Tpl);\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- Bits = 0;\r
- if (ModemStatus & MS_CTS_ON) {\r
- Bits |= EFI_SERIAL_CLEAR_TO_SEND;\r
- }\r
-\r
- if (ModemStatus & MS_DSR_ON) {\r
- Bits |= EFI_SERIAL_DATA_SET_READY;\r
- }\r
-\r
- if (ModemStatus & MS_RING_ON) {\r
- Bits |= EFI_SERIAL_RING_INDICATE;\r
- }\r
-\r
- if (ModemStatus & MS_RLSD_ON) {\r
- Bits |= EFI_SERIAL_CARRIER_DETECT;\r
- }\r
-\r
- //\r
- // Get ctrl status\r
- //\r
- if (!Private->WinNtThunk->GetCommState (Private->NtHandle, &Dcb)) {\r
- Private->NtError = Private->WinNtThunk->GetLastError ();\r
- DEBUG ((EFI_D_ERROR, "SerialGetControl: GetCommState %d\n", Private->NtError));\r
- gBS->RestoreTPL (Tpl);\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- if (Dcb.fDtrControl == DTR_CONTROL_ENABLE) {\r
- Bits |= EFI_SERIAL_DATA_TERMINAL_READY;\r
- }\r
-\r
- if (Dcb.fRtsControl == RTS_CONTROL_ENABLE) {\r
- Bits |= EFI_SERIAL_REQUEST_TO_SEND;\r
- }\r
-\r
- if (Private->HardwareFlowControl) {\r
- Bits |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;\r
- }\r
-\r
- if (Private->SoftwareLoopbackEnable) {\r
- Bits |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;\r
- }\r
-\r
- if (Private->HardwareLoopbackEnable) {\r
- Bits |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;\r
- }\r
-\r
- //\r
- // Get input buffer status\r
- //\r
- if (!Private->WinNtThunk->ClearCommError (Private->NtHandle, &Errors, &Private->NtComStatus)) {\r
- Private->NtError = Private->WinNtThunk->GetLastError ();\r
- DEBUG ((EFI_D_ERROR, "SerialGetControl: ClearCommError %d\n", Private->NtError));\r
- gBS->RestoreTPL (Tpl);\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- if (Private->NtComStatus.cbInQue == 0) {\r
- Bits |= EFI_SERIAL_INPUT_BUFFER_EMPTY;\r
- }\r
-\r
- *Control = Bits;\r
-\r
- gBS->RestoreTPL (Tpl);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-WinNtSerialIoWrite (\r
- IN EFI_SERIAL_IO_PROTOCOL *This,\r
- IN OUT UINTN *BufferSize,\r
- IN VOID *Buffer\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- TODO: Add function description\r
-\r
-Arguments:\r
-\r
- This - TODO: add argument description\r
- BufferSize - TODO: add argument description\r
- Buffer - TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_DEVICE_ERROR - TODO: Add description for return value\r
- EFI_SUCCESS - TODO: Add description for return value\r
-\r
---*/\r
-{\r
- WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;\r
- UINT8 *ByteBuffer;\r
- UINTN TotalBytesWritten;\r
- DWORD BytesToGo;\r
- DWORD BytesWritten;\r
- BOOL Result;\r
- UINT32 Index;\r
- UINT32 Control;\r
- EFI_TPL Tpl;\r
-\r
- Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
-\r
- Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);\r
-\r
- ByteBuffer = (UINT8 *) Buffer;\r
- TotalBytesWritten = 0;\r
-\r
- if (Private->SoftwareLoopbackEnable || Private->HardwareLoopbackEnable) {\r
- for (Index = 0; Index < *BufferSize; Index++) {\r
- if (IsaSerialFifoAdd (&Private->Fifo, ByteBuffer[Index]) == EFI_SUCCESS) {\r
- TotalBytesWritten++;\r
- } else {\r
- break;\r
- }\r
- }\r
- } else {\r
- BytesToGo = (DWORD) (*BufferSize);\r
-\r
- do {\r
- if (Private->HardwareFlowControl) {\r
- //\r
- // Send RTS\r
- //\r
- WinNtSerialIoGetControl (&Private->SerialIo, &Control);\r
- Control |= EFI_SERIAL_REQUEST_TO_SEND;\r
- WinNtSerialIoSetControl (&Private->SerialIo, Control);\r
- }\r
-\r
- //\r
- // Do the write\r
- //\r
- Result = Private->WinNtThunk->WriteFile (\r
- Private->NtHandle,\r
- &ByteBuffer[TotalBytesWritten],\r
- BytesToGo,\r
- &BytesWritten,\r
- NULL\r
- );\r
-\r
- if (Private->HardwareFlowControl) {\r
- //\r
- // Assert RTS\r
- //\r
- WinNtSerialIoGetControl (&Private->SerialIo, &Control);\r
- Control &= ~ (UINT32) EFI_SERIAL_REQUEST_TO_SEND;\r
- WinNtSerialIoSetControl (&Private->SerialIo, Control);\r
- }\r
-\r
- TotalBytesWritten += BytesWritten;\r
- BytesToGo -= BytesWritten;\r
- if (!Result) {\r
- Private->NtError = Private->WinNtThunk->GetLastError ();\r
- DEBUG ((EFI_D_ERROR, "SerialWrite: FileWrite %d\n", Private->NtError));\r
- *BufferSize = TotalBytesWritten;\r
- gBS->RestoreTPL (Tpl);\r
- return EFI_DEVICE_ERROR;\r
- }\r
- } while (BytesToGo > 0);\r
- }\r
-\r
- *BufferSize = TotalBytesWritten;\r
-\r
- gBS->RestoreTPL (Tpl);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-WinNtSerialIoRead (\r
- IN EFI_SERIAL_IO_PROTOCOL *This,\r
- IN OUT UINTN *BufferSize,\r
- OUT VOID *Buffer\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- TODO: Add function description\r
-\r
-Arguments:\r
-\r
- This - TODO: add argument description\r
- BufferSize - TODO: add argument description\r
- Buffer - TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_DEVICE_ERROR - TODO: Add description for return value\r
-\r
---*/\r
-{\r
- WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;\r
- BOOL Result;\r
- DWORD BytesRead;\r
- EFI_STATUS Status;\r
- UINT32 Index;\r
- UINT8 Data;\r
- UINT32 Control;\r
- EFI_TPL Tpl;\r
-\r
- Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
-\r
- Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);\r
-\r
- //\r
- // Do the read\r
- //\r
- if (Private->SoftwareLoopbackEnable || Private->HardwareLoopbackEnable) {\r
- for (Index = 0, BytesRead = 0; Index < *BufferSize; Index++) {\r
- if (IsaSerialFifoRemove (&Private->Fifo, &Data) == EFI_SUCCESS) {\r
- ((UINT8 *) Buffer)[Index] = Data;\r
- BytesRead++;\r
- } else {\r
- break;\r
- }\r
- }\r
- } else {\r
- if (Private->HardwareFlowControl) {\r
- WinNtSerialIoGetControl (&Private->SerialIo, &Control);\r
- Control |= EFI_SERIAL_DATA_TERMINAL_READY;\r
- WinNtSerialIoSetControl (&Private->SerialIo, Control);\r
- }\r
-\r
- Result = Private->WinNtThunk->ReadFile (\r
- Private->NtHandle,\r
- Buffer,\r
- (DWORD) *BufferSize,\r
- &BytesRead,\r
- NULL\r
- );\r
-\r
- if (Private->HardwareFlowControl) {\r
- WinNtSerialIoGetControl (&Private->SerialIo, &Control);\r
- Control &= ~ (UINT32) EFI_SERIAL_DATA_TERMINAL_READY;\r
- WinNtSerialIoSetControl (&Private->SerialIo, Control);\r
- }\r
-\r
- if (!Result) {\r
- Private->NtError = Private->WinNtThunk->GetLastError ();\r
- gBS->RestoreTPL (Tpl);\r
- return EFI_DEVICE_ERROR;\r
- }\r
- }\r
-\r
- if (BytesRead != *BufferSize) {\r
- Status = EFI_TIMEOUT;\r
- } else {\r
- Status = EFI_SUCCESS;\r
- }\r
-\r
- *BufferSize = (UINTN) BytesRead;\r
-\r
- gBS->RestoreTPL (Tpl);\r
-\r
- return Status;\r
-}\r
-\r
-BOOLEAN\r
-IsaSerialFifoFull (\r
- IN SERIAL_DEV_FIFO *Fifo\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Detect whether specific FIFO is full or not\r
-\r
- Arguments:\r
- Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO\r
-\r
- Returns:\r
- TRUE: the FIFO is full\r
- FALSE: the FIFO is not full\r
-\r
---*/\r
-{\r
- if (Fifo->Surplus == 0) {\r
- return TRUE;\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-BOOLEAN\r
-IsaSerialFifoEmpty (\r
- IN SERIAL_DEV_FIFO *Fifo\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Detect whether specific FIFO is empty or not\r
-\r
- Arguments:\r
- Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO\r
-\r
- Returns:\r
- TRUE: the FIFO is empty\r
- FALSE: the FIFO is not empty\r
-\r
---*/\r
-{\r
- if (Fifo->Surplus == SERIAL_MAX_BUFFER_SIZE) {\r
- return TRUE;\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-EFI_STATUS\r
-IsaSerialFifoAdd (\r
- IN SERIAL_DEV_FIFO *Fifo,\r
- IN UINT8 Data\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Add data to specific FIFO\r
-\r
- Arguments:\r
- Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO\r
- Data UINT8: the data added to FIFO\r
-\r
- Returns:\r
- EFI_SUCCESS: Add data to specific FIFO successfully\r
- EFI_OUT_RESOURCE: Failed to add data because FIFO is already full\r
-\r
---*/\r
-// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
-{\r
- //\r
- // if FIFO full can not add data\r
- //\r
- if (IsaSerialFifoFull (Fifo)) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- //\r
- // FIFO is not full can add data\r
- //\r
- Fifo->Data[Fifo->Last] = Data;\r
- Fifo->Surplus--;\r
- Fifo->Last++;\r
- if (Fifo->Last >= SERIAL_MAX_BUFFER_SIZE) {\r
- Fifo->Last = 0;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-IsaSerialFifoRemove (\r
- IN SERIAL_DEV_FIFO *Fifo,\r
- OUT UINT8 *Data\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Remove data from specific FIFO\r
-\r
- Arguments:\r
- Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO\r
- Data UINT8*: the data removed from FIFO\r
-\r
- Returns:\r
- EFI_SUCCESS: Remove data from specific FIFO successfully\r
- EFI_OUT_RESOURCE: Failed to remove data because FIFO is empty\r
-\r
---*/\r
-// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
-{\r
- //\r
- // if FIFO is empty, no data can remove\r
- //\r
- if (IsaSerialFifoEmpty (Fifo)) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- //\r
- // FIFO is not empty, can remove data\r
- //\r
- *Data = Fifo->Data[Fifo->First];\r
- Fifo->Surplus++;\r
- Fifo->First++;\r
- if (Fifo->First >= SERIAL_MAX_BUFFER_SIZE) {\r
- Fifo->First = 0;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r