16ae81428485020dd371eaefa5b97b24f21efe117klu/**@file
25f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
38f2a5f8012e3a6de30f5b12ce3a218efae9eaeddhhtianCopyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
48f2a5f8012e3a6de30f5b12ce3a218efae9eaeddhhtianThis program and the accompanying materials
55f44f5b9bb21baefa954c0c36b5e86957ee68b86kluare licensed and made available under the terms and conditions of the BSD License
65f44f5b9bb21baefa954c0c36b5e86957ee68b86kluwhich accompanies this distribution.  The full text of the license may be found at
75f44f5b9bb21baefa954c0c36b5e86957ee68b86kluhttp://opensource.org/licenses/bsd-license.php
85f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
95f44f5b9bb21baefa954c0c36b5e86957ee68b86kluTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
105f44f5b9bb21baefa954c0c36b5e86957ee68b86kluWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
115f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
125f44f5b9bb21baefa954c0c36b5e86957ee68b86kluModule Name:
135f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
145f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  WinNtSerialIo.c
155f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
165f44f5b9bb21baefa954c0c36b5e86957ee68b86kluAbstract:
175f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
185f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Our DriverBinding member functions operate on the handles
195f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  created by the NT Bus driver.
205f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
215f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Handle(1) - WinNtIo - DevicePath(1)
225f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
235f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  If a serial port is added to the system this driver creates a new handle.
245f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  The new handle is required, since the serial device must add an UART device
255f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  pathnode.
265f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
275f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Handle(2) - SerialIo - DevicePath(1)\UART
285f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
295f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  The driver then adds a gEfiWinNtSerialPortGuid as a protocol to Handle(1).
305f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  The instance data for this protocol is the private data used to create
315f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Handle(2).
325f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
335f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Handle(1) - WinNtIo - DevicePath(1) - WinNtSerialPort
345f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
355f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  If the driver is unloaded Handle(2) is removed from the system and
365f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  gEfiWinNtSerialPortGuid is removed from Handle(1).
375f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
385f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Note: Handle(1) is any handle created by the Win NT Bus driver that is passed
395f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  into the DriverBinding member functions of this driver. This driver requires
405f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  a Handle(1) to contain a WinNtIo protocol, a DevicePath protocol, and
415f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  the TypeGuid in the WinNtIo must be gEfiWinNtSerialPortGuid.
425f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
435f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  If Handle(1) contains a gEfiWinNtSerialPortGuid protocol then the driver is
445f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  loaded on the device.
455f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
466ae81428485020dd371eaefa5b97b24f21efe117klu**/
475f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
485f44f5b9bb21baefa954c0c36b5e86957ee68b86klu#include "WinNtSerialIo.h"
495f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
505f44f5b9bb21baefa954c0c36b5e86957ee68b86kluEFI_DRIVER_BINDING_PROTOCOL gWinNtSerialIoDriverBinding = {
515f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  WinNtSerialIoDriverBindingSupported,
525f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  WinNtSerialIoDriverBindingStart,
535f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  WinNtSerialIoDriverBindingStop,
545f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  0xa,
555f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  NULL,
565f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  NULL
575f44f5b9bb21baefa954c0c36b5e86957ee68b86klu};
585f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
5982408a47c9a982ceea9290dfe2d38ece14d8c867xli//
6082408a47c9a982ceea9290dfe2d38ece14d8c867xli// List of supported baud rate
6182408a47c9a982ceea9290dfe2d38ece14d8c867xli//
6282408a47c9a982ceea9290dfe2d38ece14d8c867xliUINT64 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};
6382408a47c9a982ceea9290dfe2d38ece14d8c867xli
645f44f5b9bb21baefa954c0c36b5e86957ee68b86klu/**
65ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  Check the device path node whether it's the Flow Control node or not.
66ff72001b5b0e581e53614015d93abd1107bee25bniruiyu
67ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  @param[in] FlowControl    The device path node to be checked.
68ff72001b5b0e581e53614015d93abd1107bee25bniruiyu
69ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  @retval TRUE              It's the Flow Control node.
70ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  @retval FALSE             It's not.
71ff72001b5b0e581e53614015d93abd1107bee25bniruiyu
72ff72001b5b0e581e53614015d93abd1107bee25bniruiyu**/
73ff72001b5b0e581e53614015d93abd1107bee25bniruiyuBOOLEAN
74ff72001b5b0e581e53614015d93abd1107bee25bniruiyuIsUartFlowControlNode (
75ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  IN UART_FLOW_CONTROL_DEVICE_PATH *FlowControl
76ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  )
77ff72001b5b0e581e53614015d93abd1107bee25bniruiyu{
78ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  return (BOOLEAN) (
79ff72001b5b0e581e53614015d93abd1107bee25bniruiyu           (DevicePathType (FlowControl) == MESSAGING_DEVICE_PATH) &&
80ff72001b5b0e581e53614015d93abd1107bee25bniruiyu           (DevicePathSubType (FlowControl) == MSG_VENDOR_DP) &&
81ff72001b5b0e581e53614015d93abd1107bee25bniruiyu           (CompareGuid (&FlowControl->Guid, &gEfiUartDevicePathGuid))
82ff72001b5b0e581e53614015d93abd1107bee25bniruiyu           );
83ff72001b5b0e581e53614015d93abd1107bee25bniruiyu}
84ff72001b5b0e581e53614015d93abd1107bee25bniruiyu
85ff72001b5b0e581e53614015d93abd1107bee25bniruiyu/**
86ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  Check the device path node whether it contains Flow Control node or not.
87ff72001b5b0e581e53614015d93abd1107bee25bniruiyu
88ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  @param[in] DevicePath     The device path to be checked.
89ff72001b5b0e581e53614015d93abd1107bee25bniruiyu
90ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  @retval TRUE              It contains the Flow Control node.
91ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  @retval FALSE             It doesn't.
92ff72001b5b0e581e53614015d93abd1107bee25bniruiyu
93ff72001b5b0e581e53614015d93abd1107bee25bniruiyu**/
94ff72001b5b0e581e53614015d93abd1107bee25bniruiyuBOOLEAN
95ff72001b5b0e581e53614015d93abd1107bee25bniruiyuContainsFlowControl (
96ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  IN EFI_DEVICE_PATH_PROTOCOL      *DevicePath
97ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  )
98ff72001b5b0e581e53614015d93abd1107bee25bniruiyu{
99ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  while (!IsDevicePathEnd (DevicePath)) {
100ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    if (IsUartFlowControlNode ((UART_FLOW_CONTROL_DEVICE_PATH *) DevicePath)) {
101ff72001b5b0e581e53614015d93abd1107bee25bniruiyu      return TRUE;
102ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    }
103ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    DevicePath = NextDevicePathNode (DevicePath);
104ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  }
105ff72001b5b0e581e53614015d93abd1107bee25bniruiyu
106ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  return FALSE;
107ff72001b5b0e581e53614015d93abd1107bee25bniruiyu}
108ff72001b5b0e581e53614015d93abd1107bee25bniruiyu
109ff72001b5b0e581e53614015d93abd1107bee25bniruiyu/**
1105f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  The user Entry Point for module WinNtSerialIo. The user code starts with this function.
1115f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
1125f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  @param[in] ImageHandle    The firmware allocated handle for the EFI image.
1135f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  @param[in] SystemTable    A pointer to the EFI System Table.
1145f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
1155f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  @retval EFI_SUCCESS       The entry point is executed successfully.
1165f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  @retval other             Some error occurs when executing this entry point.
1175f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
1185f44f5b9bb21baefa954c0c36b5e86957ee68b86klu**/
1195f44f5b9bb21baefa954c0c36b5e86957ee68b86kluEFI_STATUS
1205f44f5b9bb21baefa954c0c36b5e86957ee68b86kluEFIAPI
1215f44f5b9bb21baefa954c0c36b5e86957ee68b86kluInitializeWinNtSerialIo(
1225f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN EFI_HANDLE           ImageHandle,
1235f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN EFI_SYSTEM_TABLE     *SystemTable
1245f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  )
1255f44f5b9bb21baefa954c0c36b5e86957ee68b86klu{
1265f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_STATUS              Status;
1275f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
1285f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
1295f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // Install driver model protocol(s).
1305f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
13104369cd8fc2523bd45dccb1f615f97c950ed3c63qhuang  Status = EfiLibInstallDriverBindingComponentName2 (
1325f44f5b9bb21baefa954c0c36b5e86957ee68b86klu             ImageHandle,
1335f44f5b9bb21baefa954c0c36b5e86957ee68b86klu             SystemTable,
1345f44f5b9bb21baefa954c0c36b5e86957ee68b86klu             &gWinNtSerialIoDriverBinding,
1355f44f5b9bb21baefa954c0c36b5e86957ee68b86klu             ImageHandle,
1365f44f5b9bb21baefa954c0c36b5e86957ee68b86klu             &gWinNtSerialIoComponentName,
13704369cd8fc2523bd45dccb1f615f97c950ed3c63qhuang             &gWinNtSerialIoComponentName2
1385f44f5b9bb21baefa954c0c36b5e86957ee68b86klu             );
1395f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  ASSERT_EFI_ERROR (Status);
1405f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
1415f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
1425f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  return Status;
1435f44f5b9bb21baefa954c0c36b5e86957ee68b86klu}
1445f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
1455f44f5b9bb21baefa954c0c36b5e86957ee68b86kluEFI_STATUS
1465f44f5b9bb21baefa954c0c36b5e86957ee68b86kluEFIAPI
1475f44f5b9bb21baefa954c0c36b5e86957ee68b86kluWinNtSerialIoDriverBindingSupported (
1485f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
1495f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN  EFI_HANDLE                    Handle,
1505f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN  EFI_DEVICE_PATH_PROTOCOL      *RemainingDevicePath
1515f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  )
1525f44f5b9bb21baefa954c0c36b5e86957ee68b86klu/*++
1535f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
1545f44f5b9bb21baefa954c0c36b5e86957ee68b86kluRoutine Description:
1555f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
1565f44f5b9bb21baefa954c0c36b5e86957ee68b86kluArguments:
1575f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
1585f44f5b9bb21baefa954c0c36b5e86957ee68b86kluReturns:
1595f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
1605f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  None
1615f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
1625f44f5b9bb21baefa954c0c36b5e86957ee68b86klu--*/
1635f44f5b9bb21baefa954c0c36b5e86957ee68b86klu// TODO:    This - add argument and description to function comment
1645f44f5b9bb21baefa954c0c36b5e86957ee68b86klu// TODO:    Handle - add argument and description to function comment
1655f44f5b9bb21baefa954c0c36b5e86957ee68b86klu// TODO:    RemainingDevicePath - add argument and description to function comment
1665f44f5b9bb21baefa954c0c36b5e86957ee68b86klu// TODO:    EFI_SUCCESS - add return value to function comment
1675f44f5b9bb21baefa954c0c36b5e86957ee68b86klu// TODO:    EFI_SUCCESS - add return value to function comment
1685f44f5b9bb21baefa954c0c36b5e86957ee68b86klu{
169ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  EFI_STATUS                          Status;
170ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  EFI_DEVICE_PATH_PROTOCOL            *ParentDevicePath;
171ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  EFI_WIN_NT_IO_PROTOCOL              *WinNtIo;
172ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  UART_DEVICE_PATH                    *UartNode;
173ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  EFI_DEVICE_PATH_PROTOCOL            *DevicePath;
174ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  UART_FLOW_CONTROL_DEVICE_PATH       *FlowControlNode;
175ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
176ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  UINTN                               EntryCount;
177ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  UINTN                               Index;
178e74c3676e651f79d27afa986c5837eb1e103fe84mdkinney  BOOLEAN                             RemainingDevicePathContainsFlowControl;
1795f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
1805f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
181f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff  // Check RemainingDevicePath validation
182f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff  //
183f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff  if (RemainingDevicePath != NULL) {
184f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    //
185f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    // Check if RemainingDevicePath is the End of Device Path Node,
186f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    // if yes, go on checking other conditions
187f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    //
188f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    if (!IsDevicePathEnd (RemainingDevicePath)) {
189f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff      //
190f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff      // If RemainingDevicePath isn't the End of Device Path Node,
191f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff      // check its validation
192f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff      //
193f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff      Status = EFI_UNSUPPORTED;
194f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff
195f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff      UartNode  = (UART_DEVICE_PATH *) RemainingDevicePath;
196f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff      if (UartNode->Header.Type != MESSAGING_DEVICE_PATH ||
197f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff          UartNode->Header.SubType != MSG_UART_DP ||
198f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff          DevicePathNodeLength((EFI_DEVICE_PATH_PROTOCOL *)UartNode) != sizeof(UART_DEVICE_PATH)) {
199f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff        goto Error;
200f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff      }
201f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff      if ( UartNode->BaudRate > SERIAL_PORT_MAX_BAUD_RATE) {
202f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff        goto Error;
203f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff      }
204f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff      if (UartNode->Parity < NoParity || UartNode->Parity > SpaceParity) {
205f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff        goto Error;
206f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff      }
207f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff      if (UartNode->DataBits < 5 || UartNode->DataBits > 8) {
208f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff        goto Error;
209f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff      }
210f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff      if (UartNode->StopBits < OneStopBit || UartNode->StopBits > TwoStopBits) {
211f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff        goto Error;
212f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff      }
213f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff      if ((UartNode->DataBits == 5) && (UartNode->StopBits == TwoStopBits)) {
214f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff        goto Error;
215f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff      }
216f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff      if ((UartNode->DataBits >= 6) && (UartNode->DataBits <= 8) && (UartNode->StopBits == OneFiveStopBits)) {
217f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff        goto Error;
218f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff      }
219ff72001b5b0e581e53614015d93abd1107bee25bniruiyu
220ff72001b5b0e581e53614015d93abd1107bee25bniruiyu      FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (UartNode);
221ff72001b5b0e581e53614015d93abd1107bee25bniruiyu      if (IsUartFlowControlNode (FlowControlNode)) {
222ff72001b5b0e581e53614015d93abd1107bee25bniruiyu        //
223ff72001b5b0e581e53614015d93abd1107bee25bniruiyu        // If the second node is Flow Control Node,
224ff72001b5b0e581e53614015d93abd1107bee25bniruiyu        //   return error when it request other than hardware flow control.
225ff72001b5b0e581e53614015d93abd1107bee25bniruiyu        //
226ff72001b5b0e581e53614015d93abd1107bee25bniruiyu        if ((FlowControlNode->FlowControlMap & ~UART_FLOW_CONTROL_HARDWARE) != 0) {
227ff72001b5b0e581e53614015d93abd1107bee25bniruiyu          goto Error;
228ff72001b5b0e581e53614015d93abd1107bee25bniruiyu        }
229ff72001b5b0e581e53614015d93abd1107bee25bniruiyu      }
230f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    }
231f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff  }
232f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff
233f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff  //
2345f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // Open the IO Abstraction(s) needed to perform the supported test
2355f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
2365f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Status = gBS->OpenProtocol (
2375f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  Handle,
238f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff                  &gEfiWinNtIoProtocolGuid,
239f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff                  (VOID **) &WinNtIo,
2405f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  This->DriverBindingHandle,
2415f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  Handle,
2425f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  EFI_OPEN_PROTOCOL_BY_DRIVER
2435f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  );
2445f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Status == EFI_ALREADY_STARTED) {
245ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) {
246ff72001b5b0e581e53614015d93abd1107bee25bniruiyu      //
247ff72001b5b0e581e53614015d93abd1107bee25bniruiyu      // If RemainingDevicePath is NULL or is the End of Device Path Node
248ff72001b5b0e581e53614015d93abd1107bee25bniruiyu      //
249ff72001b5b0e581e53614015d93abd1107bee25bniruiyu      return EFI_SUCCESS;
250ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    }
251ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    //
252ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    // When the driver has produced device path with flow control node but RemainingDevicePath only contains UART node,
253ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    //   return unsupported, and vice versa.
254ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    //
255ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    Status = gBS->OpenProtocolInformation (
256ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                    Handle,
257ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                    &gEfiWinNtIoProtocolGuid,
258ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                    &OpenInfoBuffer,
259ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                    &EntryCount
260ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                    );
261ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    if (EFI_ERROR (Status)) {
262ff72001b5b0e581e53614015d93abd1107bee25bniruiyu      return Status;
263ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    }
264ff72001b5b0e581e53614015d93abd1107bee25bniruiyu
265e74c3676e651f79d27afa986c5837eb1e103fe84mdkinney    //
266e74c3676e651f79d27afa986c5837eb1e103fe84mdkinney    // See if RemainingDevicePath has a Flow Control device path node
267e74c3676e651f79d27afa986c5837eb1e103fe84mdkinney    //
268e74c3676e651f79d27afa986c5837eb1e103fe84mdkinney    RemainingDevicePathContainsFlowControl = ContainsFlowControl (RemainingDevicePath);
269e74c3676e651f79d27afa986c5837eb1e103fe84mdkinney
270ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    for (Index = 0; Index < EntryCount; Index++) {
271ff72001b5b0e581e53614015d93abd1107bee25bniruiyu      if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
272ff72001b5b0e581e53614015d93abd1107bee25bniruiyu        Status = gBS->OpenProtocol (
273ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                        OpenInfoBuffer[Index].ControllerHandle,
274ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                        &gEfiDevicePathProtocolGuid,
275ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                        (VOID **) &DevicePath,
276ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                        This->DriverBindingHandle,
277ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                        Handle,
278ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                        EFI_OPEN_PROTOCOL_GET_PROTOCOL
279ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                        );
280e74c3676e651f79d27afa986c5837eb1e103fe84mdkinney        if (!EFI_ERROR (Status)) {
281e74c3676e651f79d27afa986c5837eb1e103fe84mdkinney          if (RemainingDevicePathContainsFlowControl ^ ContainsFlowControl (DevicePath)) {
282e74c3676e651f79d27afa986c5837eb1e103fe84mdkinney            Status = EFI_UNSUPPORTED;
283e74c3676e651f79d27afa986c5837eb1e103fe84mdkinney          }
284ff72001b5b0e581e53614015d93abd1107bee25bniruiyu        }
285ff72001b5b0e581e53614015d93abd1107bee25bniruiyu        break;
286ff72001b5b0e581e53614015d93abd1107bee25bniruiyu      }
287ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    }
288ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    FreePool (OpenInfoBuffer);
289ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    return Status;
2905f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
2915f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
2925f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (EFI_ERROR (Status)) {
2935f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    return Status;
2945f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
2955f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
296f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff  //
297af4a63857cd189964cc2c6b53b54483efaba78a3vanjeff  // Close the I/O Abstraction(s) used to perform the supported test
298f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff  //
2995f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  gBS->CloseProtocol (
3005f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        Handle,
301f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff        &gEfiWinNtIoProtocolGuid,
3025f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        This->DriverBindingHandle,
3035f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        Handle
3045f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        );
3055f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
306f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff  //
307f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff  // Open the EFI Device Path protocol needed to perform the supported test
308f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff  //
3095f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Status = gBS->OpenProtocol (
3105f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  Handle,
311f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff                  &gEfiDevicePathProtocolGuid,
312f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff                  (VOID **) &ParentDevicePath,
3135f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  This->DriverBindingHandle,
3145f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  Handle,
3155f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  EFI_OPEN_PROTOCOL_BY_DRIVER
3165f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  );
3175f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Status == EFI_ALREADY_STARTED) {
3185f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    return EFI_SUCCESS;
3195f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
3205f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
3215f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (EFI_ERROR (Status)) {
3225f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    return Status;
3235f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
3245f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
3255f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
326f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff  // Close protocol, don't use device path protocol in the Support() function
327f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff  //
328f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff  gBS->CloseProtocol (
329f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff        Handle,
330f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff        &gEfiDevicePathProtocolGuid,
331f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff        This->DriverBindingHandle,
332f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff        Handle
333f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff        );
334f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff
335f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff  //
3365f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // Make sure that the WinNt Thunk Protocol is valid
3375f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
3385f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (WinNtIo->WinNtThunk->Signature != EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) {
3395f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Status = EFI_UNSUPPORTED;
3405f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    goto Error;
3415f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
3425f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
3435f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
3445f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // Check the GUID to see if this is a handle type the driver supports
3455f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
3465f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (!CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtSerialPortGuid)) {
3475f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Status = EFI_UNSUPPORTED;
3485f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    goto Error;
3495f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
3505f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
351f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff  return EFI_SUCCESS;
3525f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
3535f44f5b9bb21baefa954c0c36b5e86957ee68b86kluError:
3545f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  return Status;
3555f44f5b9bb21baefa954c0c36b5e86957ee68b86klu}
3565f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
3575f44f5b9bb21baefa954c0c36b5e86957ee68b86kluEFI_STATUS
3585f44f5b9bb21baefa954c0c36b5e86957ee68b86kluEFIAPI
3595f44f5b9bb21baefa954c0c36b5e86957ee68b86kluWinNtSerialIoDriverBindingStart (
3605f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
3615f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN  EFI_HANDLE                    Handle,
3625f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN  EFI_DEVICE_PATH_PROTOCOL      *RemainingDevicePath
3635f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  )
3645f44f5b9bb21baefa954c0c36b5e86957ee68b86klu/*++
3655f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
3665f44f5b9bb21baefa954c0c36b5e86957ee68b86kluRoutine Description:
3675f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
3685f44f5b9bb21baefa954c0c36b5e86957ee68b86kluArguments:
3695f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
3705f44f5b9bb21baefa954c0c36b5e86957ee68b86kluReturns:
3715f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
3725f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  None
3735f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
3745f44f5b9bb21baefa954c0c36b5e86957ee68b86klu--*/
3755f44f5b9bb21baefa954c0c36b5e86957ee68b86klu// TODO:    This - add argument and description to function comment
3765f44f5b9bb21baefa954c0c36b5e86957ee68b86klu// TODO:    Handle - add argument and description to function comment
3775f44f5b9bb21baefa954c0c36b5e86957ee68b86klu// TODO:    RemainingDevicePath - add argument and description to function comment
3785f44f5b9bb21baefa954c0c36b5e86957ee68b86klu// TODO:    EFI_SUCCESS - add return value to function comment
3795f44f5b9bb21baefa954c0c36b5e86957ee68b86klu// TODO:    EFI_SUCCESS - add return value to function comment
3805f44f5b9bb21baefa954c0c36b5e86957ee68b86klu{
3815f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_STATUS                          Status;
3825f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_WIN_NT_IO_PROTOCOL              *WinNtIo;
3835f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  WIN_NT_SERIAL_IO_PRIVATE_DATA       *Private;
3845f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  HANDLE                              NtHandle;
385ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  UART_DEVICE_PATH                    UartNode;
3865f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_DEVICE_PATH_PROTOCOL            *ParentDevicePath;
3875f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
3885f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  UINTN                               EntryCount;
3895f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  UINTN                               Index;
3905f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_SERIAL_IO_PROTOCOL              *SerialIo;
391ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  UART_DEVICE_PATH                    *Uart;
392ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  UINT32                              FlowControlMap;
393ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  UART_FLOW_CONTROL_DEVICE_PATH       *FlowControl;
394ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  EFI_DEVICE_PATH_PROTOCOL            *TempDevicePath;
395ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  UINT32                              Control;
3965f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
3975f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private   = NULL;
3985f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  NtHandle  = INVALID_HANDLE_VALUE;
3995f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
4005f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
401ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  // Get the Parent Device Path
4025f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
4035f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Status = gBS->OpenProtocol (
4045f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  Handle,
4055f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  &gEfiDevicePathProtocolGuid,
4066394182967f63d4a97a1c882861d9958657112bbqwang                  (VOID **) &ParentDevicePath,
4075f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  This->DriverBindingHandle,
4085f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  Handle,
4095f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  EFI_OPEN_PROTOCOL_BY_DRIVER
4105f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  );
4115f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
4125f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    return Status;
4135f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
4145f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
4155f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
4165f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // Grab the IO abstraction we need to get any work done
4175f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
4185f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Status = gBS->OpenProtocol (
4195f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  Handle,
4205f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  &gEfiWinNtIoProtocolGuid,
4216394182967f63d4a97a1c882861d9958657112bbqwang                  (VOID **) &WinNtIo,
4225f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  This->DriverBindingHandle,
4235f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  Handle,
4245f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  EFI_OPEN_PROTOCOL_BY_DRIVER
4255f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  );
4265f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
4275f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    gBS->CloseProtocol (
4285f44f5b9bb21baefa954c0c36b5e86957ee68b86klu          Handle,
4295f44f5b9bb21baefa954c0c36b5e86957ee68b86klu          &gEfiDevicePathProtocolGuid,
4305f44f5b9bb21baefa954c0c36b5e86957ee68b86klu          This->DriverBindingHandle,
4315f44f5b9bb21baefa954c0c36b5e86957ee68b86klu          Handle
4325f44f5b9bb21baefa954c0c36b5e86957ee68b86klu          );
4335f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    return Status;
4345f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
4355f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
4365f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Status == EFI_ALREADY_STARTED) {
4375f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
438f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) {
439f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff      //
440f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff      // If RemainingDevicePath is NULL or is the End of Device Path Node
441f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff      //
4425f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      return EFI_SUCCESS;
4435f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    }
4445f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
4455f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    //
4465f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    // Make sure a child handle does not already exist.  This driver can only
4475f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    // produce one child per serial port.
4485f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    //
4495f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Status = gBS->OpenProtocolInformation (
4505f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                    Handle,
4515f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                    &gEfiWinNtIoProtocolGuid,
4525f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                    &OpenInfoBuffer,
4535f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                    &EntryCount
4545f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                    );
4555f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    if (EFI_ERROR (Status)) {
4565f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      return Status;
4575f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    }
4585f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
4595f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Status = EFI_ALREADY_STARTED;
4605f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    for (Index = 0; Index < EntryCount; Index++) {
461ff72001b5b0e581e53614015d93abd1107bee25bniruiyu      if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
4625f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        Status = gBS->OpenProtocol (
4635f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                        OpenInfoBuffer[Index].ControllerHandle,
4645f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                        &gEfiSerialIoProtocolGuid,
4656394182967f63d4a97a1c882861d9958657112bbqwang                        (VOID **) &SerialIo,
4665f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                        This->DriverBindingHandle,
4675f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                        Handle,
4685f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                        EFI_OPEN_PROTOCOL_GET_PROTOCOL
4695f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                        );
4705f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        if (!EFI_ERROR (Status)) {
471ff72001b5b0e581e53614015d93abd1107bee25bniruiyu          Uart   = (UART_DEVICE_PATH *) RemainingDevicePath;
4725f44f5b9bb21baefa954c0c36b5e86957ee68b86klu          Status = SerialIo->SetAttributes (
473ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                               SerialIo,
474ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                               Uart->BaudRate,
475ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                               SerialIo->Mode->ReceiveFifoDepth,
476ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                               SerialIo->Mode->Timeout,
477ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                               (EFI_PARITY_TYPE) Uart->Parity,
478ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                               Uart->DataBits,
479ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                               (EFI_STOP_BITS_TYPE) Uart->StopBits
480ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                               );
481ff72001b5b0e581e53614015d93abd1107bee25bniruiyu          FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Uart);
482ff72001b5b0e581e53614015d93abd1107bee25bniruiyu          if (!EFI_ERROR (Status) && IsUartFlowControlNode (FlowControl)) {
483ff72001b5b0e581e53614015d93abd1107bee25bniruiyu            Status = SerialIo->GetControl (SerialIo, &Control);
484ff72001b5b0e581e53614015d93abd1107bee25bniruiyu            if (!EFI_ERROR (Status)) {
485ff72001b5b0e581e53614015d93abd1107bee25bniruiyu              if (FlowControl->FlowControlMap == UART_FLOW_CONTROL_HARDWARE) {
486ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
487ff72001b5b0e581e53614015d93abd1107bee25bniruiyu              } else {
488ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                Control &= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
489ff72001b5b0e581e53614015d93abd1107bee25bniruiyu              }
490ff72001b5b0e581e53614015d93abd1107bee25bniruiyu              //
491ff72001b5b0e581e53614015d93abd1107bee25bniruiyu              // Clear the bits that are not allowed to pass to SetControl
492ff72001b5b0e581e53614015d93abd1107bee25bniruiyu              //
493ff72001b5b0e581e53614015d93abd1107bee25bniruiyu              Control &= (EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY |
494ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                          EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE |
495ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                          EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE);
496ff72001b5b0e581e53614015d93abd1107bee25bniruiyu              Status = SerialIo->SetControl (SerialIo, Control);
497ff72001b5b0e581e53614015d93abd1107bee25bniruiyu            }
498ff72001b5b0e581e53614015d93abd1107bee25bniruiyu          }
4995f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        }
5005f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        break;
5015f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      }
5025f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    }
5039be29006683dd5fa6c02059691735715d28070c7vanjeff
5045f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    FreePool (OpenInfoBuffer);
5059be29006683dd5fa6c02059691735715d28070c7vanjeff    return Status;
506f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff  }
507f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff
508ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  FlowControl    = NULL;
509ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  FlowControlMap = 0;
510f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff  if (RemainingDevicePath == NULL) {
511f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    //
512f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    // Build the device path by appending the UART node to the ParentDevicePath
513f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    // from the WinNtIo handle. The Uart setings are zero here, since
514f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    // SetAttribute() will update them to match the default setings.
515f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    //
516ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    ZeroMem (&UartNode, sizeof (UART_DEVICE_PATH));
517ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    UartNode.Header.Type     = MESSAGING_DEVICE_PATH;
518ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    UartNode.Header.SubType  = MSG_UART_DP;
519ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) &UartNode, sizeof (UART_DEVICE_PATH));
520f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff
521f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff  } else if (!IsDevicePathEnd (RemainingDevicePath)) {
522f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    //
523f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    // If RemainingDevicePath isn't the End of Device Path Node,
524f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    // only scan the specified device by RemainingDevicePath
525f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    //
526f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    //
527f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    // Match the configuration of the RemainingDevicePath. IsHandleSupported()
528f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    // already checked to make sure the RemainingDevicePath contains settings
529f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    // that we can support.
530f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    //
531ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    CopyMem (&UartNode, RemainingDevicePath, sizeof (UART_DEVICE_PATH));
532ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (RemainingDevicePath);
533ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    if (IsUartFlowControlNode (FlowControl)) {
534ff72001b5b0e581e53614015d93abd1107bee25bniruiyu      FlowControlMap = FlowControl->FlowControlMap;
535ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    } else {
536ff72001b5b0e581e53614015d93abd1107bee25bniruiyu      FlowControl    = NULL;
537ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    }
538f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff
539f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff  } else {
540f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    //
541f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    // If RemainingDevicePath is the End of Device Path Node,
542f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    // skip enumerate any device and return EFI_SUCESSS
543f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    //
544f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff    return EFI_SUCCESS;
5455f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
5465f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
5475f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
5485f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // Check to see if we can access the hardware device. If it's Open in NT we
5495f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // will not get access.
5505f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
5515f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  NtHandle = WinNtIo->WinNtThunk->CreateFile (
5525f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                                    WinNtIo->EnvString,
5535f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                                    GENERIC_READ | GENERIC_WRITE,
5545f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                                    0,
5555f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                                    NULL,
5565f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                                    OPEN_EXISTING,
5575f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                                    0,
5585f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                                    NULL
5595f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                                    );
5605f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (NtHandle == INVALID_HANDLE_VALUE) {
5615f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Status = EFI_DEVICE_ERROR;
5625f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    goto Error;
5635f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
5645f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
5655f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
5665f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // Construct Private data
5675f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
5685f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private = AllocatePool (sizeof (WIN_NT_SERIAL_IO_PRIVATE_DATA));
5695f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Private == NULL) {
5705f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    goto Error;
5715f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
5725f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
5735f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
5745f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // This signature must be valid before any member function is called
5755f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
5765f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->Signature              = WIN_NT_SERIAL_IO_PRIVATE_DATA_SIGNATURE;
5775f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->NtHandle               = NtHandle;
5785f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->ControllerHandle       = Handle;
5795f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->Handle                 = NULL;
5805f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->WinNtThunk             = WinNtIo->WinNtThunk;
5815f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->ParentDevicePath       = ParentDevicePath;
5825f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->ControllerNameTable    = NULL;
5835f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
5845f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->SoftwareLoopbackEnable = FALSE;
5855f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->HardwareLoopbackEnable = FALSE;
586ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  Private->HardwareFlowControl    = (BOOLEAN) (FlowControlMap == UART_FLOW_CONTROL_HARDWARE);
5875f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->Fifo.First             = 0;
5885f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->Fifo.Last              = 0;
5895f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->Fifo.Surplus           = SERIAL_MAX_BUFFER_SIZE;
5905f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
591ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  CopyMem (&Private->UartDevicePath, &UartNode, sizeof (UART_DEVICE_PATH));
592f22911b49e8be58d364f9e21f5af6bd3f0513cf7vanjeff
59304369cd8fc2523bd45dccb1f615f97c950ed3c63qhuang  AddUnicodeString2 (
5945f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    "eng",
5955f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    gWinNtSerialIoComponentName.SupportedLanguages,
5965f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    &Private->ControllerNameTable,
59704369cd8fc2523bd45dccb1f615f97c950ed3c63qhuang    WinNtIo->EnvString,
59804369cd8fc2523bd45dccb1f615f97c950ed3c63qhuang    TRUE
5995f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    );
60004369cd8fc2523bd45dccb1f615f97c950ed3c63qhuang  AddUnicodeString2 (
60104369cd8fc2523bd45dccb1f615f97c950ed3c63qhuang    "en",
60204369cd8fc2523bd45dccb1f615f97c950ed3c63qhuang    gWinNtSerialIoComponentName2.SupportedLanguages,
60304369cd8fc2523bd45dccb1f615f97c950ed3c63qhuang    &Private->ControllerNameTable,
60404369cd8fc2523bd45dccb1f615f97c950ed3c63qhuang    WinNtIo->EnvString,
60504369cd8fc2523bd45dccb1f615f97c950ed3c63qhuang    FALSE
60604369cd8fc2523bd45dccb1f615f97c950ed3c63qhuang    );
60704369cd8fc2523bd45dccb1f615f97c950ed3c63qhuang
6085f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
6095f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->SerialIo.Revision      = SERIAL_IO_INTERFACE_REVISION;
6105f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->SerialIo.Reset         = WinNtSerialIoReset;
6115f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->SerialIo.SetAttributes = WinNtSerialIoSetAttributes;
6125f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->SerialIo.SetControl    = WinNtSerialIoSetControl;
6135f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->SerialIo.GetControl    = WinNtSerialIoGetControl;
6145f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->SerialIo.Write         = WinNtSerialIoWrite;
6155f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->SerialIo.Read          = WinNtSerialIoRead;
6165f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->SerialIo.Mode          = &Private->SerialIoMode;
6175f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
6185f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
6195f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // Build the device path by appending the UART node to the ParentDevicePath
6205f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // from the WinNtIo handle. The Uart setings are zero here, since
6215f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // SetAttribute() will update them to match the current setings.
6225f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
6235f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->DevicePath = AppendDevicePathNode (
6245f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                          ParentDevicePath,
6255f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                          (EFI_DEVICE_PATH_PROTOCOL *) &Private->UartDevicePath
6265f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                          );
627ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  //
628ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  // Only produce the FlowControl node when remaining device path has it
629ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  //
630ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  if (FlowControl != NULL) {
631ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    TempDevicePath = Private->DevicePath;
632ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    if (TempDevicePath != NULL) {
633ff72001b5b0e581e53614015d93abd1107bee25bniruiyu      Private->DevicePath = AppendDevicePathNode (
634ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                              TempDevicePath,
635ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                              (EFI_DEVICE_PATH_PROTOCOL *) FlowControl
636ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                              );
637ff72001b5b0e581e53614015d93abd1107bee25bniruiyu      FreePool (TempDevicePath);
638ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    }
639ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  }
6405f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Private->DevicePath == NULL) {
6415f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Status = EFI_OUT_OF_RESOURCES;
6425f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    goto Error;
6435f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
6445f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
6455f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
6465f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
6475f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
6485f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->SerialIoMode.ControlMask       = SERIAL_CONTROL_MASK;
6495f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->SerialIoMode.Timeout           = SERIAL_TIMEOUT_DEFAULT;
6505f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->SerialIoMode.BaudRate          = Private->UartDevicePath.BaudRate;
6515f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->SerialIoMode.ReceiveFifoDepth  = SERIAL_FIFO_DEFAULT;
6525f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->SerialIoMode.DataBits          = Private->UartDevicePath.DataBits;
6535f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->SerialIoMode.Parity            = Private->UartDevicePath.Parity;
6545f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->SerialIoMode.StopBits          = Private->UartDevicePath.StopBits;
6555f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
6565f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
6575f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // Issue a reset to initialize the COM port
6585f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
6595f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Status = Private->SerialIo.Reset (&Private->SerialIo);
6605f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (EFI_ERROR (Status)) {
6615f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    goto Error;
6625f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
6635f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
6645f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
6655f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // Create new child handle
6665f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
6675f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Status = gBS->InstallMultipleProtocolInterfaces (
6685f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  &Private->Handle,
6695f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  &gEfiSerialIoProtocolGuid,
6705f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  &Private->SerialIo,
6715f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  &gEfiDevicePathProtocolGuid,
6725f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  Private->DevicePath,
6735f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  NULL
6745f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  );
6755f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (EFI_ERROR (Status)) {
6765f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    goto Error;
6775f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
6785f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
6795f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
6805f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // Open For Child Device
6815f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
6825f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Status = gBS->OpenProtocol (
6835f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  Handle,
6845f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  &gEfiWinNtIoProtocolGuid,
6856394182967f63d4a97a1c882861d9958657112bbqwang                  (VOID **) &WinNtIo,
6865f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  This->DriverBindingHandle,
6875f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  Private->Handle,
6885f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
6895f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                  );
6905f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (EFI_ERROR (Status)) {
6915f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    goto Error;
6925f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
6935f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
6945f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  return EFI_SUCCESS;
6955f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
6965f44f5b9bb21baefa954c0c36b5e86957ee68b86kluError:
6975f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
6985f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // Use the Stop() function to free all resources allocated in Start()
6995f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
7005f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Private != NULL) {
7015f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    if (Private->Handle != NULL) {
7025f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      This->Stop (This, Handle, 1, &Private->Handle);
7035f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    } else {
7045f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      if (NtHandle != INVALID_HANDLE_VALUE) {
7055f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        Private->WinNtThunk->CloseHandle (NtHandle);
7065f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      }
7075f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
7085f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      if (Private->DevicePath != NULL) {
7095f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        FreePool (Private->DevicePath);
7105f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      }
7115f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
7125f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      FreeUnicodeStringTable (Private->ControllerNameTable);
7135f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
7145f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      FreePool (Private);
7155f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    }
7165f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
7175f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
7185f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  This->Stop (This, Handle, 0, NULL);
7195f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
7205f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  return Status;
7215f44f5b9bb21baefa954c0c36b5e86957ee68b86klu}
7225f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
7235f44f5b9bb21baefa954c0c36b5e86957ee68b86kluEFI_STATUS
7245f44f5b9bb21baefa954c0c36b5e86957ee68b86kluEFIAPI
7255f44f5b9bb21baefa954c0c36b5e86957ee68b86kluWinNtSerialIoDriverBindingStop (
7265f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
7275f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN  EFI_HANDLE                    Handle,
7285f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN  UINTN                         NumberOfChildren,
7295f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN  EFI_HANDLE                    *ChildHandleBuffer
7305f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  )
7315f44f5b9bb21baefa954c0c36b5e86957ee68b86klu/*++
7325f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
7335f44f5b9bb21baefa954c0c36b5e86957ee68b86kluRoutine Description:
7345f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
7355f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  TODO: Add function description
7365f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
7375f44f5b9bb21baefa954c0c36b5e86957ee68b86kluArguments:
7385f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
7395f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  This              - TODO: add argument description
7405f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Handle            - TODO: add argument description
7415f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  NumberOfChildren  - TODO: add argument description
7425f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  ChildHandleBuffer - TODO: add argument description
7435f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
7445f44f5b9bb21baefa954c0c36b5e86957ee68b86kluReturns:
7455f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
7465f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_DEVICE_ERROR - TODO: Add description for return value
7475f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_SUCCESS - TODO: Add description for return value
7485f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
7495f44f5b9bb21baefa954c0c36b5e86957ee68b86klu--*/
7505f44f5b9bb21baefa954c0c36b5e86957ee68b86klu{
7515f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_STATUS                    Status;
7525f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  UINTN                         Index;
7535f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  BOOLEAN                       AllChildrenStopped;
7545f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_SERIAL_IO_PROTOCOL        *SerialIo;
7555f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;
7565f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_WIN_NT_IO_PROTOCOL        *WinNtIo;
7575f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
7585f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
7595f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // Complete all outstanding transactions to Controller.
7605f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // Don't allow any new transaction to Controller to be started.
7615f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
7625f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
7635f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (NumberOfChildren == 0) {
7645f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    //
7655f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    // Close the bus driver
7665f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    //
7675f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Status = gBS->CloseProtocol (
7685f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                    Handle,
7695f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                    &gEfiWinNtIoProtocolGuid,
7705f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                    This->DriverBindingHandle,
7715f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                    Handle
7725f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                    );
7735f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Status = gBS->CloseProtocol (
7745f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                    Handle,
7755f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                    &gEfiDevicePathProtocolGuid,
7765f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                    This->DriverBindingHandle,
7775f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                    Handle
7785f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                    );
7795f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    return Status;
7805f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
7815f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
7825f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  AllChildrenStopped = TRUE;
7835f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
7845f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  for (Index = 0; Index < NumberOfChildren; Index++) {
7855f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Status = gBS->OpenProtocol (
7865f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                    ChildHandleBuffer[Index],
7875f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                    &gEfiSerialIoProtocolGuid,
7886394182967f63d4a97a1c882861d9958657112bbqwang                    (VOID **) &SerialIo,
7895f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                    This->DriverBindingHandle,
7905f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                    Handle,
7915f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
7925f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                    );
7935f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    if (!EFI_ERROR (Status)) {
7945f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (SerialIo);
7955f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
7965f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      ASSERT (Private->Handle == ChildHandleBuffer[Index]);
7975f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
7985f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      Status = gBS->CloseProtocol (
7995f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                      Handle,
8005f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                      &gEfiWinNtIoProtocolGuid,
8015f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                      This->DriverBindingHandle,
8025f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                      ChildHandleBuffer[Index]
8035f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                      );
8045f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
8055f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      Status = gBS->UninstallMultipleProtocolInterfaces (
8065f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                      ChildHandleBuffer[Index],
8075f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                      &gEfiSerialIoProtocolGuid,
8085f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                      &Private->SerialIo,
8095f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                      &gEfiDevicePathProtocolGuid,
8105f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                      Private->DevicePath,
8115f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                      NULL
8125f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                      );
8135f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
8145f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      if (EFI_ERROR (Status)) {
8155f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        gBS->OpenProtocol (
8165f44f5b9bb21baefa954c0c36b5e86957ee68b86klu              Handle,
8175f44f5b9bb21baefa954c0c36b5e86957ee68b86klu              &gEfiWinNtIoProtocolGuid,
8185f44f5b9bb21baefa954c0c36b5e86957ee68b86klu              (VOID **) &WinNtIo,
8195f44f5b9bb21baefa954c0c36b5e86957ee68b86klu              This->DriverBindingHandle,
8205f44f5b9bb21baefa954c0c36b5e86957ee68b86klu              ChildHandleBuffer[Index],
8215f44f5b9bb21baefa954c0c36b5e86957ee68b86klu              EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
8225f44f5b9bb21baefa954c0c36b5e86957ee68b86klu              );
8235f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      } else {
8245f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        Private->WinNtThunk->CloseHandle (Private->NtHandle);
8255f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
8265f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        FreePool (Private->DevicePath);
8275f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
8285f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        FreeUnicodeStringTable (Private->ControllerNameTable);
8295f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
8305f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        FreePool (Private);
8315f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      }
8325f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    }
8335f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
8345f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    if (EFI_ERROR (Status)) {
8355f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      AllChildrenStopped = FALSE;
8365f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    }
8375f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
8385f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
8395f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (!AllChildrenStopped) {
8405f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    return EFI_DEVICE_ERROR;
8415f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
8425f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
8435f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  return EFI_SUCCESS;
8445f44f5b9bb21baefa954c0c36b5e86957ee68b86klu}
8455f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
8465f44f5b9bb21baefa954c0c36b5e86957ee68b86klu//
8475f44f5b9bb21baefa954c0c36b5e86957ee68b86klu// Serial IO Protocol member functions
8485f44f5b9bb21baefa954c0c36b5e86957ee68b86klu//
8495f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
8505f44f5b9bb21baefa954c0c36b5e86957ee68b86kluEFI_STATUS
8515f44f5b9bb21baefa954c0c36b5e86957ee68b86kluEFIAPI
8525f44f5b9bb21baefa954c0c36b5e86957ee68b86kluWinNtSerialIoReset (
8535f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN EFI_SERIAL_IO_PROTOCOL *This
8545f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  )
8555f44f5b9bb21baefa954c0c36b5e86957ee68b86klu/*++
8565f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
8575f44f5b9bb21baefa954c0c36b5e86957ee68b86kluRoutine Description:
8585f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
8595f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  TODO: Add function description
8605f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
8615f44f5b9bb21baefa954c0c36b5e86957ee68b86kluArguments:
8625f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
8635f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  This  - TODO: add argument description
8645f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
8655f44f5b9bb21baefa954c0c36b5e86957ee68b86kluReturns:
8665f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
8675f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  TODO: add return values
8685f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
8695f44f5b9bb21baefa954c0c36b5e86957ee68b86klu--*/
8705f44f5b9bb21baefa954c0c36b5e86957ee68b86klu{
8715f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;
8725f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_TPL                       Tpl;
8735f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
8745f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Tpl     = gBS->RaiseTPL (TPL_NOTIFY);
8755f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
8765f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);
8775f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
8785f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->WinNtThunk->PurgeComm (
8795f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                        Private->NtHandle,
8805f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                        PURGE_TXCLEAR | PURGE_RXCLEAR
8815f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                        );
8825f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
8835f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  gBS->RestoreTPL (Tpl);
8845f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
8855f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  return This->SetAttributes (
8865f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                This,
8875f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                This->Mode->BaudRate,
8885f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                This->Mode->ReceiveFifoDepth,
8895f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                This->Mode->Timeout,
890a00ec39b52224a40bf9a0a813b69cb43e14407a8mdkinney                (EFI_PARITY_TYPE)This->Mode->Parity,
8915f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                (UINT8) This->Mode->DataBits,
892a00ec39b52224a40bf9a0a813b69cb43e14407a8mdkinney                (EFI_STOP_BITS_TYPE)This->Mode->StopBits
8935f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                );
8945f44f5b9bb21baefa954c0c36b5e86957ee68b86klu}
8955f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
8965f44f5b9bb21baefa954c0c36b5e86957ee68b86kluEFI_STATUS
8975f44f5b9bb21baefa954c0c36b5e86957ee68b86kluEFIAPI
8985f44f5b9bb21baefa954c0c36b5e86957ee68b86kluWinNtSerialIoSetAttributes (
8995f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN EFI_SERIAL_IO_PROTOCOL *This,
9005f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN UINT64                 BaudRate,
9015f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN UINT32                 ReceiveFifoDepth,
9025f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN UINT32                 Timeout,
9035f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN EFI_PARITY_TYPE        Parity,
9045f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN UINT8                  DataBits,
9055f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN EFI_STOP_BITS_TYPE     StopBits
9065f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  )
9075f44f5b9bb21baefa954c0c36b5e86957ee68b86klu/*++
9085f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
9095f44f5b9bb21baefa954c0c36b5e86957ee68b86kluRoutine Description:
9105f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
9115f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  This function is used to set the attributes.
9125f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
9135f44f5b9bb21baefa954c0c36b5e86957ee68b86kluArguments:
9145f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
9155f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  This              - A pointer to the EFI_SERIAL_IO_PROTOCOL structrue.
9165f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  BaudRate          - The Baud rate of the serial device.
9175f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  ReceiveFifoDepth  - The request depth of fifo on receive side.
9185f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Timeout           - the request timeout for a single charact.
9195f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Parity            - The type of parity used in serial device.
9205f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  DataBits          - Number of deata bits used in serial device.
9215f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  StopBits          - Number of stop bits used in serial device.
9225f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
9235f44f5b9bb21baefa954c0c36b5e86957ee68b86kluReturns:
9245f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Status code
9255f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
9265f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  None
9275f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
9285f44f5b9bb21baefa954c0c36b5e86957ee68b86klu--*/
9295f44f5b9bb21baefa954c0c36b5e86957ee68b86klu// TODO:    EFI_SUCCESS - add return value to function comment
9305f44f5b9bb21baefa954c0c36b5e86957ee68b86klu// TODO:    EFI_DEVICE_ERROR - add return value to function comment
9315f44f5b9bb21baefa954c0c36b5e86957ee68b86klu// TODO:    EFI_DEVICE_ERROR - add return value to function comment
9325f44f5b9bb21baefa954c0c36b5e86957ee68b86klu// TODO:    EFI_DEVICE_ERROR - add return value to function comment
9335f44f5b9bb21baefa954c0c36b5e86957ee68b86klu// TODO:    EFI_SUCCESS - add return value to function comment
9345f44f5b9bb21baefa954c0c36b5e86957ee68b86klu// TODO:    EFI_DEVICE_ERROR - add return value to function comment
9355f44f5b9bb21baefa954c0c36b5e86957ee68b86klu// TODO:    EFI_SUCCESS - add return value to function comment
9365f44f5b9bb21baefa954c0c36b5e86957ee68b86klu{
9375f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_STATUS                    Status;
93882408a47c9a982ceea9290dfe2d38ece14d8c867xli  UINTN                         Index;
9395f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;
9405f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  COMMTIMEOUTS                  PortTimeOuts;
9415f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  DWORD                         ConvertedTime;
9425f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  BOOL                          Result;
943ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  UART_DEVICE_PATH              *Uart;
9445f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_TPL                       Tpl;
9455f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
9465f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);
9475f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
9485f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
9495f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //  Some of our arguments have defaults if a null value is passed in, and
9505f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //   we must set the default values if a null argument is passed in.
9515f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
9525f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (BaudRate == 0) {
953f7c58a94cf72eb00f0931c89d935a164abaadf50mdkinney    BaudRate = PcdGet64 (PcdUartDefaultBaudRate);
9545f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
9555f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
9565f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (ReceiveFifoDepth == 0) {
9575f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    ReceiveFifoDepth = SERIAL_FIFO_DEFAULT;
9585f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
9595f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
9605f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Timeout == 0) {
9615f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Timeout = SERIAL_TIMEOUT_DEFAULT;
9625f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
9635f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
9645f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Parity == DefaultParity) {
965f7c58a94cf72eb00f0931c89d935a164abaadf50mdkinney    Parity = (EFI_PARITY_TYPE) (PcdGet8 (PcdUartDefaultParity));
9665f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
9675f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
9685f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (DataBits == 0) {
969f7c58a94cf72eb00f0931c89d935a164abaadf50mdkinney    DataBits = PcdGet8 (PcdUartDefaultDataBits);
9705f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
9715f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
9725f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (StopBits == DefaultStopBits) {
973f7c58a94cf72eb00f0931c89d935a164abaadf50mdkinney    StopBits = (EFI_STOP_BITS_TYPE) PcdGet8 (PcdUartDefaultStopBits);
9745f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
97582408a47c9a982ceea9290dfe2d38ece14d8c867xli
97682408a47c9a982ceea9290dfe2d38ece14d8c867xli  //
97782408a47c9a982ceea9290dfe2d38ece14d8c867xli  // Make sure all parameters are valid
97882408a47c9a982ceea9290dfe2d38ece14d8c867xli  //
97982408a47c9a982ceea9290dfe2d38ece14d8c867xli  if ((BaudRate > SERIAL_PORT_MAX_BAUD_RATE) || (BaudRate < SERIAL_PORT_MIN_BAUD_RATE)) {
98082408a47c9a982ceea9290dfe2d38ece14d8c867xli    return EFI_INVALID_PARAMETER;
98182408a47c9a982ceea9290dfe2d38ece14d8c867xli  }
98282408a47c9a982ceea9290dfe2d38ece14d8c867xli
98382408a47c9a982ceea9290dfe2d38ece14d8c867xli  //
98482408a47c9a982ceea9290dfe2d38ece14d8c867xli  //The lower baud rate supported by the serial device will be selected without exceeding the unsupported BaudRate parameter
98582408a47c9a982ceea9290dfe2d38ece14d8c867xli  //
98682408a47c9a982ceea9290dfe2d38ece14d8c867xli
98782408a47c9a982ceea9290dfe2d38ece14d8c867xli  for (Index = 1; Index < (sizeof (mBaudRateCurrentSupport) / sizeof (mBaudRateCurrentSupport[0])); Index++) {
98882408a47c9a982ceea9290dfe2d38ece14d8c867xli    if (BaudRate < mBaudRateCurrentSupport[Index]) {
98982408a47c9a982ceea9290dfe2d38ece14d8c867xli      BaudRate = mBaudRateCurrentSupport[Index-1];
99082408a47c9a982ceea9290dfe2d38ece14d8c867xli      break;
99182408a47c9a982ceea9290dfe2d38ece14d8c867xli      }
99282408a47c9a982ceea9290dfe2d38ece14d8c867xli  }
993ff72001b5b0e581e53614015d93abd1107bee25bniruiyu
99482408a47c9a982ceea9290dfe2d38ece14d8c867xli  if ((ReceiveFifoDepth < 1) || (ReceiveFifoDepth > SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH)) {
99582408a47c9a982ceea9290dfe2d38ece14d8c867xli    return EFI_INVALID_PARAMETER;
99682408a47c9a982ceea9290dfe2d38ece14d8c867xli  }
99782408a47c9a982ceea9290dfe2d38ece14d8c867xli
99882408a47c9a982ceea9290dfe2d38ece14d8c867xli  if ((Timeout < SERIAL_PORT_MIN_TIMEOUT) || (Timeout > SERIAL_PORT_MAX_TIMEOUT)) {
99982408a47c9a982ceea9290dfe2d38ece14d8c867xli    return EFI_INVALID_PARAMETER;
100082408a47c9a982ceea9290dfe2d38ece14d8c867xli  }
100182408a47c9a982ceea9290dfe2d38ece14d8c867xli
100282408a47c9a982ceea9290dfe2d38ece14d8c867xli  if ((Parity < NoParity) || (Parity > SpaceParity)) {
100382408a47c9a982ceea9290dfe2d38ece14d8c867xli    return EFI_INVALID_PARAMETER;
100482408a47c9a982ceea9290dfe2d38ece14d8c867xli  }
100582408a47c9a982ceea9290dfe2d38ece14d8c867xli
100682408a47c9a982ceea9290dfe2d38ece14d8c867xli  if ((StopBits < OneStopBit) || (StopBits > TwoStopBits)) {
100782408a47c9a982ceea9290dfe2d38ece14d8c867xli    return EFI_INVALID_PARAMETER;
100882408a47c9a982ceea9290dfe2d38ece14d8c867xli  }
100982408a47c9a982ceea9290dfe2d38ece14d8c867xli
101082408a47c9a982ceea9290dfe2d38ece14d8c867xli  //
101182408a47c9a982ceea9290dfe2d38ece14d8c867xli  // Now we only support DataBits=7,8.
101282408a47c9a982ceea9290dfe2d38ece14d8c867xli  //
101382408a47c9a982ceea9290dfe2d38ece14d8c867xli  if ((DataBits < 7) || (DataBits > 8)) {
101482408a47c9a982ceea9290dfe2d38ece14d8c867xli    return EFI_INVALID_PARAMETER;
101582408a47c9a982ceea9290dfe2d38ece14d8c867xli  }
101682408a47c9a982ceea9290dfe2d38ece14d8c867xli
101782408a47c9a982ceea9290dfe2d38ece14d8c867xli  //
101882408a47c9a982ceea9290dfe2d38ece14d8c867xli  // Now we only support DataBits=7,8.
101982408a47c9a982ceea9290dfe2d38ece14d8c867xli  // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits.
102082408a47c9a982ceea9290dfe2d38ece14d8c867xli  //
102182408a47c9a982ceea9290dfe2d38ece14d8c867xli  if (StopBits == OneFiveStopBits) {
102282408a47c9a982ceea9290dfe2d38ece14d8c867xli    return EFI_INVALID_PARAMETER;
102382408a47c9a982ceea9290dfe2d38ece14d8c867xli  }
102482408a47c9a982ceea9290dfe2d38ece14d8c867xli
10255f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
10265f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // See if the new attributes already match the current attributes
10275f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
10285f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Private->UartDevicePath.BaudRate       == BaudRate         &&
10295f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      Private->UartDevicePath.DataBits       == DataBits         &&
10305f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      Private->UartDevicePath.Parity         == Parity           &&
10315f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      Private->UartDevicePath.StopBits       == StopBits         &&
10325f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      Private->SerialIoMode.ReceiveFifoDepth == ReceiveFifoDepth &&
10335f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      Private->SerialIoMode.Timeout          == Timeout             ) {
10345f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    return EFI_SUCCESS;
10355f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
10365f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
103782408a47c9a982ceea9290dfe2d38ece14d8c867xli  Tpl     = gBS->RaiseTPL (TPL_NOTIFY);
103882408a47c9a982ceea9290dfe2d38ece14d8c867xli
10395f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
10405f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //  Get current values from NT
10415f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
10425f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  ZeroMem (&Private->NtDCB, sizeof (DCB));
10435f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->NtDCB.DCBlength = sizeof (DCB);
10445f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
10455f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (!Private->WinNtThunk->GetCommState (Private->NtHandle, &Private->NtDCB)) {
10465f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Private->NtError = Private->WinNtThunk->GetLastError ();
10475f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    DEBUG ((EFI_D_ERROR, "SerialSetAttributes: GetCommState %d\n", Private->NtError));
10485f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    gBS->RestoreTPL (Tpl);
10495f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    return EFI_DEVICE_ERROR;
10505f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
10515f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
10525f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
10535f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // Map EFI com setting to NT
10545f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
10555f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->NtDCB.BaudRate         = ConvertBaud2Nt (BaudRate);
10565f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->NtDCB.ByteSize         = ConvertData2Nt (DataBits);
10575f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->NtDCB.Parity           = ConvertParity2Nt (Parity);
10585f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->NtDCB.StopBits         = ConvertStop2Nt (StopBits);
10595f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
10605f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->NtDCB.fBinary          = TRUE;
10615f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->NtDCB.fParity          = Private->NtDCB.Parity == NOPARITY ? FALSE : TRUE;
10625f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->NtDCB.fOutxCtsFlow     = FALSE;
10635f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->NtDCB.fOutxDsrFlow     = FALSE;
10645f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->NtDCB.fDtrControl      = DTR_CONTROL_ENABLE;
10655f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->NtDCB.fDsrSensitivity  = FALSE;
10665f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->NtDCB.fOutX            = FALSE;
10675f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->NtDCB.fInX             = FALSE;
10685f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->NtDCB.fRtsControl      = RTS_CONTROL_ENABLE;
10695f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->NtDCB.fNull            = FALSE;
10705f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
10715f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
10725f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //  Set new values
10735f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
10745f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Result = Private->WinNtThunk->SetCommState (Private->NtHandle, &Private->NtDCB);
10755f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (!Result) {
10765f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Private->NtError = Private->WinNtThunk->GetLastError ();
10775f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    DEBUG ((EFI_D_ERROR, "SerialSetAttributes: SetCommState %d\n", Private->NtError));
10785f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    gBS->RestoreTPL (Tpl);
10795f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    return EFI_DEVICE_ERROR;
10805f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
10815f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
10825f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
10835f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //  Set com port read/write timeout values
10845f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
10855f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  ConvertedTime = ConvertTime2Nt (Timeout);
10865f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  PortTimeOuts.ReadIntervalTimeout = MAXDWORD;
10875f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  PortTimeOuts.ReadTotalTimeoutMultiplier = 0;
10885f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  PortTimeOuts.ReadTotalTimeoutConstant = ConvertedTime;
10895f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  PortTimeOuts.WriteTotalTimeoutMultiplier = ConvertedTime == 0 ? 1 : ConvertedTime;
10905f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  PortTimeOuts.WriteTotalTimeoutConstant = 0;
10915f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
10925f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (!Private->WinNtThunk->SetCommTimeouts (Private->NtHandle, &PortTimeOuts)) {
10935f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Private->NtError = Private->WinNtThunk->GetLastError ();
10945f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    DEBUG ((EFI_D_ERROR, "SerialSetAttributes: SetCommTimeouts %d\n", Private->NtError));
10955f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    gBS->RestoreTPL (Tpl);
10965f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    return EFI_DEVICE_ERROR;
10975f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
10985f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
10995f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
11005f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //  Update mode
11015f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
11025f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->SerialIoMode.BaudRate          = BaudRate;
11035f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->SerialIoMode.ReceiveFifoDepth  = ReceiveFifoDepth;
11045f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->SerialIoMode.Timeout           = Timeout;
11055f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->SerialIoMode.Parity            = Parity;
11065f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->SerialIoMode.DataBits          = DataBits;
11075f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->SerialIoMode.StopBits          = StopBits;
11085f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
11095f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
11105f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // See if Device Path Node has actually changed
11115f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
11125f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Private->UartDevicePath.BaudRate     == BaudRate &&
11135f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      Private->UartDevicePath.DataBits     == DataBits &&
11145f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      Private->UartDevicePath.Parity       == Parity   &&
11155f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      Private->UartDevicePath.StopBits     == StopBits    ) {
11165f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    gBS->RestoreTPL(Tpl);
11175f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    return EFI_SUCCESS;
11185f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
11195f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
11205f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
11215f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // Update the device path
11225f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
11235f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->UartDevicePath.BaudRate  = BaudRate;
11245f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->UartDevicePath.DataBits  = DataBits;
11255f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->UartDevicePath.Parity    = (UINT8) Parity;
11265f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->UartDevicePath.StopBits  = (UINT8) StopBits;
11275f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
1128ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  Status = EFI_SUCCESS;
11295f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Private->Handle != NULL) {
1130ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    Uart = (UART_DEVICE_PATH *) (
1131ff72001b5b0e581e53614015d93abd1107bee25bniruiyu             (UINTN) Private->DevicePath
1132ff72001b5b0e581e53614015d93abd1107bee25bniruiyu             + GetDevicePathSize (Private->ParentDevicePath)
1133ff72001b5b0e581e53614015d93abd1107bee25bniruiyu             - END_DEVICE_PATH_LENGTH
1134ff72001b5b0e581e53614015d93abd1107bee25bniruiyu             );
1135ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    CopyMem (Uart, &Private->UartDevicePath, sizeof (UART_DEVICE_PATH));
11365f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Status = gBS->ReinstallProtocolInterface (
11375f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                    Private->Handle,
11385f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                    &gEfiDevicePathProtocolGuid,
11395f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                    Private->DevicePath,
1140ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                    Private->DevicePath
11415f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                    );
11425f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
11435f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
11445f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  gBS->RestoreTPL (Tpl);
11455f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
1146ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  return Status;
11475f44f5b9bb21baefa954c0c36b5e86957ee68b86klu}
11485f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
11495f44f5b9bb21baefa954c0c36b5e86957ee68b86kluEFI_STATUS
11505f44f5b9bb21baefa954c0c36b5e86957ee68b86kluEFIAPI
11515f44f5b9bb21baefa954c0c36b5e86957ee68b86kluWinNtSerialIoSetControl (
11525f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN EFI_SERIAL_IO_PROTOCOL *This,
11535f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN UINT32                 Control
11545f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  )
11555f44f5b9bb21baefa954c0c36b5e86957ee68b86klu/*++
11565f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
11575f44f5b9bb21baefa954c0c36b5e86957ee68b86kluRoutine Description:
11585f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
11595f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  TODO: Add function description
11605f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
11615f44f5b9bb21baefa954c0c36b5e86957ee68b86kluArguments:
11625f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
11635f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  This    - TODO: add argument description
11645f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Control - TODO: add argument description
11655f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
11665f44f5b9bb21baefa954c0c36b5e86957ee68b86kluReturns:
11675f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
11685f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_DEVICE_ERROR - TODO: Add description for return value
11695f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_DEVICE_ERROR - TODO: Add description for return value
11705f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_SUCCESS - TODO: Add description for return value
11715f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
11725f44f5b9bb21baefa954c0c36b5e86957ee68b86klu--*/
11735f44f5b9bb21baefa954c0c36b5e86957ee68b86klu{
11745f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;
11755f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  BOOL                          Result;
11765f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  DCB                           Dcb;
11775f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_TPL                       Tpl;
1178ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  UART_FLOW_CONTROL_DEVICE_PATH *FlowControl;
1179ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  EFI_STATUS                    Status;
11805f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
118182408a47c9a982ceea9290dfe2d38ece14d8c867xli  //
118282408a47c9a982ceea9290dfe2d38ece14d8c867xli  // first determine the parameter is invalid
118382408a47c9a982ceea9290dfe2d38ece14d8c867xli  //
118482408a47c9a982ceea9290dfe2d38ece14d8c867xli  if (Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY |
118582408a47c9a982ceea9290dfe2d38ece14d8c867xli                   EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE |
118682408a47c9a982ceea9290dfe2d38ece14d8c867xli                   EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) {
118782408a47c9a982ceea9290dfe2d38ece14d8c867xli    return EFI_UNSUPPORTED;
118882408a47c9a982ceea9290dfe2d38ece14d8c867xli  }
118982408a47c9a982ceea9290dfe2d38ece14d8c867xli
11905f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Tpl     = gBS->RaiseTPL (TPL_NOTIFY);
11915f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
11925f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);
11935f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
11945f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Result  = Private->WinNtThunk->GetCommState (Private->NtHandle, &Dcb);
11955f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
11965f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (!Result) {
11975f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Private->NtError = Private->WinNtThunk->GetLastError ();
11985f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    DEBUG ((EFI_D_ERROR, "SerialSetControl: GetCommState %d\n", Private->NtError));
11995f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    gBS->RestoreTPL (Tpl);
12005f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    return EFI_DEVICE_ERROR;
12015f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
12025f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
12035f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Dcb.fRtsControl                 = RTS_CONTROL_DISABLE;
12045f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Dcb.fDtrControl                 = DTR_CONTROL_DISABLE;
12055f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->HardwareFlowControl    = FALSE;
12065f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->SoftwareLoopbackEnable = FALSE;
12075f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private->HardwareLoopbackEnable = FALSE;
12085f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
12095f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Control & EFI_SERIAL_REQUEST_TO_SEND) {
12105f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Dcb.fRtsControl = RTS_CONTROL_ENABLE;
12115f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
12125f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
12135f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Control & EFI_SERIAL_DATA_TERMINAL_READY) {
12145f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Dcb.fDtrControl = DTR_CONTROL_ENABLE;
12155f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
12165f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
12175f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {
12185f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Private->HardwareFlowControl = TRUE;
12195f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
12205f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
12215f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Control & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) {
12225f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Private->SoftwareLoopbackEnable = TRUE;
12235f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
12245f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
12255f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) {
12265f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Private->HardwareLoopbackEnable = TRUE;
12275f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
12285f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
12295f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Result = Private->WinNtThunk->SetCommState (
12305f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                                  Private->NtHandle,
12315f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                                  &Dcb
12325f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                                  );
12335f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
12345f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (!Result) {
12355f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Private->NtError = Private->WinNtThunk->GetLastError ();
12365f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    DEBUG ((EFI_D_ERROR, "SerialSetControl: SetCommState %d\n", Private->NtError));
12375f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    gBS->RestoreTPL (Tpl);
12385f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    return EFI_DEVICE_ERROR;
12395f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
12405f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
1241ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  Status = EFI_SUCCESS;
1242ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  if (Private->Handle != NULL) {
1243ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) (
1244ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                    (UINTN) Private->DevicePath
1245ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                    + GetDevicePathSize (Private->ParentDevicePath)
1246ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                    - END_DEVICE_PATH_LENGTH
1247ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                    + sizeof (UART_DEVICE_PATH)
1248ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                    );
1249ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    if (IsUartFlowControlNode (FlowControl) &&
1250ff72001b5b0e581e53614015d93abd1107bee25bniruiyu        ((FlowControl->FlowControlMap == UART_FLOW_CONTROL_HARDWARE) ^ Private->HardwareFlowControl)) {
1251ff72001b5b0e581e53614015d93abd1107bee25bniruiyu      //
1252ff72001b5b0e581e53614015d93abd1107bee25bniruiyu      // Flow Control setting is changed, need to reinstall device path protocol
1253ff72001b5b0e581e53614015d93abd1107bee25bniruiyu      //
1254ff72001b5b0e581e53614015d93abd1107bee25bniruiyu      FlowControl->FlowControlMap = Private->HardwareFlowControl ? UART_FLOW_CONTROL_HARDWARE : 0;
1255ff72001b5b0e581e53614015d93abd1107bee25bniruiyu      Status = gBS->ReinstallProtocolInterface (
1256ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                      Private->Handle,
1257ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                      &gEfiDevicePathProtocolGuid,
1258ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                      Private->DevicePath,
1259ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                      Private->DevicePath
1260ff72001b5b0e581e53614015d93abd1107bee25bniruiyu                      );
1261ff72001b5b0e581e53614015d93abd1107bee25bniruiyu    }
1262ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  }
1263ff72001b5b0e581e53614015d93abd1107bee25bniruiyu
12645f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  gBS->RestoreTPL (Tpl);
12655f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
1266ff72001b5b0e581e53614015d93abd1107bee25bniruiyu  return Status;
12675f44f5b9bb21baefa954c0c36b5e86957ee68b86klu}
12685f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
12695f44f5b9bb21baefa954c0c36b5e86957ee68b86kluEFI_STATUS
12705f44f5b9bb21baefa954c0c36b5e86957ee68b86kluEFIAPI
12715f44f5b9bb21baefa954c0c36b5e86957ee68b86kluWinNtSerialIoGetControl (
12725f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN  EFI_SERIAL_IO_PROTOCOL  *This,
12735f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  OUT UINT32                  *Control
12745f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  )
12755f44f5b9bb21baefa954c0c36b5e86957ee68b86klu/*++
12765f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
12775f44f5b9bb21baefa954c0c36b5e86957ee68b86kluRoutine Description:
12785f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
12795f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  TODO: Add function description
12805f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
12815f44f5b9bb21baefa954c0c36b5e86957ee68b86kluArguments:
12825f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
12835f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  This    - TODO: add argument description
12845f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Control - TODO: add argument description
12855f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
12865f44f5b9bb21baefa954c0c36b5e86957ee68b86kluReturns:
12875f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
12885f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_DEVICE_ERROR - TODO: Add description for return value
12895f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_DEVICE_ERROR - TODO: Add description for return value
12905f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_DEVICE_ERROR - TODO: Add description for return value
12915f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_SUCCESS - TODO: Add description for return value
12925f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
12935f44f5b9bb21baefa954c0c36b5e86957ee68b86klu--*/
12945f44f5b9bb21baefa954c0c36b5e86957ee68b86klu{
12955f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;
12965f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  DWORD                         ModemStatus;
12975f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  DWORD                         Errors;
12985f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  UINT32                        Bits;
12995f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  DCB                           Dcb;
13005f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_TPL                       Tpl;
13015f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
13025f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Tpl     = gBS->RaiseTPL (TPL_NOTIFY);
13035f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
13045f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);
13055f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
13065f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
13075f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //  Get modem status
13085f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
13095f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (!Private->WinNtThunk->GetCommModemStatus (Private->NtHandle, &ModemStatus)) {
13105f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Private->NtError = Private->WinNtThunk->GetLastError ();
13115f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    gBS->RestoreTPL (Tpl);
13125f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    return EFI_DEVICE_ERROR;
13135f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
13145f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
13155f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Bits = 0;
13165f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (ModemStatus & MS_CTS_ON) {
13175f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Bits |= EFI_SERIAL_CLEAR_TO_SEND;
13185f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
13195f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
13205f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (ModemStatus & MS_DSR_ON) {
13215f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Bits |= EFI_SERIAL_DATA_SET_READY;
13225f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
13235f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
13245f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (ModemStatus & MS_RING_ON) {
13255f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Bits |= EFI_SERIAL_RING_INDICATE;
13265f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
13275f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
13285f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (ModemStatus & MS_RLSD_ON) {
13295f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Bits |= EFI_SERIAL_CARRIER_DETECT;
13305f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
13315f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
13325f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
13335f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // Get ctrl status
13345f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
13355f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (!Private->WinNtThunk->GetCommState (Private->NtHandle, &Dcb)) {
13365f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Private->NtError = Private->WinNtThunk->GetLastError ();
13375f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    DEBUG ((EFI_D_ERROR, "SerialGetControl: GetCommState %d\n", Private->NtError));
13385f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    gBS->RestoreTPL (Tpl);
13395f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    return EFI_DEVICE_ERROR;
13405f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
13415f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
13425f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Dcb.fDtrControl == DTR_CONTROL_ENABLE) {
13435f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Bits |= EFI_SERIAL_DATA_TERMINAL_READY;
13445f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
13455f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
13465f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Dcb.fRtsControl == RTS_CONTROL_ENABLE) {
13475f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Bits |= EFI_SERIAL_REQUEST_TO_SEND;
13485f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
13495f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
13505f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Private->HardwareFlowControl) {
13515f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Bits |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
13525f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
13535f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
13545f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Private->SoftwareLoopbackEnable) {
13555f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Bits |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;
13565f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
13575f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
13585f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Private->HardwareLoopbackEnable) {
13595f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Bits |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;
13605f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
13615f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
13625f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
13635f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //  Get input buffer status
13645f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
13655f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (!Private->WinNtThunk->ClearCommError (Private->NtHandle, &Errors, &Private->NtComStatus)) {
13665f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Private->NtError = Private->WinNtThunk->GetLastError ();
13675f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    DEBUG ((EFI_D_ERROR, "SerialGetControl: ClearCommError %d\n", Private->NtError));
13685f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    gBS->RestoreTPL (Tpl);
13695f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    return EFI_DEVICE_ERROR;
13705f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
13715f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
13725f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Private->NtComStatus.cbInQue == 0) {
13735f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Bits |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
13745f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
13755f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
13765f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  *Control = Bits;
13775f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
13785f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  gBS->RestoreTPL (Tpl);
13795f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
13805f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  return EFI_SUCCESS;
13815f44f5b9bb21baefa954c0c36b5e86957ee68b86klu}
13825f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
13835f44f5b9bb21baefa954c0c36b5e86957ee68b86kluEFI_STATUS
13845f44f5b9bb21baefa954c0c36b5e86957ee68b86kluEFIAPI
13855f44f5b9bb21baefa954c0c36b5e86957ee68b86kluWinNtSerialIoWrite (
13865f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN EFI_SERIAL_IO_PROTOCOL   *This,
13875f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN OUT UINTN                *BufferSize,
13885f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN VOID                     *Buffer
13895f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  )
13905f44f5b9bb21baefa954c0c36b5e86957ee68b86klu/*++
13915f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
13925f44f5b9bb21baefa954c0c36b5e86957ee68b86kluRoutine Description:
13935f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
13945f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  TODO: Add function description
13955f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
13965f44f5b9bb21baefa954c0c36b5e86957ee68b86kluArguments:
13975f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
13985f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  This        - TODO: add argument description
13995f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  BufferSize  - TODO: add argument description
14005f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Buffer      - TODO: add argument description
14015f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
14025f44f5b9bb21baefa954c0c36b5e86957ee68b86kluReturns:
14035f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
14045f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_DEVICE_ERROR - TODO: Add description for return value
14055f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_SUCCESS - TODO: Add description for return value
14065f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
14075f44f5b9bb21baefa954c0c36b5e86957ee68b86klu--*/
14085f44f5b9bb21baefa954c0c36b5e86957ee68b86klu{
14095f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;
14105f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  UINT8                         *ByteBuffer;
14115f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  UINTN                         TotalBytesWritten;
14125f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  DWORD                         BytesToGo;
14135f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  DWORD                         BytesWritten;
14145f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  BOOL                          Result;
14155f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  UINT32                        Index;
14165f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  UINT32                        Control;
14175f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_TPL                       Tpl;
14185f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
14195f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Tpl               = gBS->RaiseTPL (TPL_NOTIFY);
14205f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
14215f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private           = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);
14225f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
14235f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  ByteBuffer        = (UINT8 *) Buffer;
14245f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  TotalBytesWritten = 0;
14255f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
14265f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Private->SoftwareLoopbackEnable || Private->HardwareLoopbackEnable) {
14275f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    for (Index = 0; Index < *BufferSize; Index++) {
14285f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      if (IsaSerialFifoAdd (&Private->Fifo, ByteBuffer[Index]) == EFI_SUCCESS) {
14295f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        TotalBytesWritten++;
14305f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      } else {
14315f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        break;
14325f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      }
14335f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    }
14345f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  } else {
14355f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    BytesToGo = (DWORD) (*BufferSize);
14365f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
14375f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    do {
14385f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      if (Private->HardwareFlowControl) {
14395f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        //
14405f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        // Send RTS
14415f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        //
14425f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        WinNtSerialIoGetControl (&Private->SerialIo, &Control);
14435f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        Control |= EFI_SERIAL_REQUEST_TO_SEND;
14445f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        WinNtSerialIoSetControl (&Private->SerialIo, Control);
14455f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      }
14465f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
14475f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      //
14485f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      //  Do the write
14495f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      //
14505f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      Result = Private->WinNtThunk->WriteFile (
14515f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                                      Private->NtHandle,
14525f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                                      &ByteBuffer[TotalBytesWritten],
14535f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                                      BytesToGo,
14545f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                                      &BytesWritten,
14555f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                                      NULL
14565f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                                      );
14575f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
14585f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      if (Private->HardwareFlowControl) {
14595f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        //
14605f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        // Assert RTS
14615f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        //
14625f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        WinNtSerialIoGetControl (&Private->SerialIo, &Control);
14635f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        Control &= ~ (UINT32) EFI_SERIAL_REQUEST_TO_SEND;
14645f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        WinNtSerialIoSetControl (&Private->SerialIo, Control);
14655f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      }
14665f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
14675f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      TotalBytesWritten += BytesWritten;
14685f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      BytesToGo -= BytesWritten;
14695f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      if (!Result) {
14705f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        Private->NtError = Private->WinNtThunk->GetLastError ();
14715f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        DEBUG ((EFI_D_ERROR, "SerialWrite: FileWrite %d\n", Private->NtError));
14725f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        *BufferSize = TotalBytesWritten;
14735f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        gBS->RestoreTPL (Tpl);
14745f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        return EFI_DEVICE_ERROR;
14755f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      }
14765f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    } while (BytesToGo > 0);
14775f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
14785f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
14795f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  *BufferSize = TotalBytesWritten;
14805f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
14815f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  gBS->RestoreTPL (Tpl);
14825f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
14835f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  return EFI_SUCCESS;
14845f44f5b9bb21baefa954c0c36b5e86957ee68b86klu}
14855f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
14865f44f5b9bb21baefa954c0c36b5e86957ee68b86kluEFI_STATUS
14875f44f5b9bb21baefa954c0c36b5e86957ee68b86kluEFIAPI
14885f44f5b9bb21baefa954c0c36b5e86957ee68b86kluWinNtSerialIoRead (
14895f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN  EFI_SERIAL_IO_PROTOCOL  *This,
14905f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN  OUT UINTN               *BufferSize,
14915f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  OUT VOID                    *Buffer
14925f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  )
14935f44f5b9bb21baefa954c0c36b5e86957ee68b86klu/*++
14945f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
14955f44f5b9bb21baefa954c0c36b5e86957ee68b86kluRoutine Description:
14965f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
14975f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  TODO: Add function description
14985f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
14995f44f5b9bb21baefa954c0c36b5e86957ee68b86kluArguments:
15005f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
15015f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  This        - TODO: add argument description
15025f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  BufferSize  - TODO: add argument description
15035f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Buffer      - TODO: add argument description
15045f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
15055f44f5b9bb21baefa954c0c36b5e86957ee68b86kluReturns:
15065f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
15075f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_DEVICE_ERROR - TODO: Add description for return value
15085f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
15095f44f5b9bb21baefa954c0c36b5e86957ee68b86klu--*/
15105f44f5b9bb21baefa954c0c36b5e86957ee68b86klu{
15115f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;
15125f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  BOOL                          Result;
15135f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  DWORD                         BytesRead;
15145f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_STATUS                    Status;
15155f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  UINT32                        Index;
15165f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  UINT8                         Data;
15175f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  UINT32                        Control;
15185f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  EFI_TPL                       Tpl;
15195f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
15205f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Tpl     = gBS->RaiseTPL (TPL_NOTIFY);
15215f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
15225f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);
15235f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
15245f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
15255f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //  Do the read
15265f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
15275f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Private->SoftwareLoopbackEnable || Private->HardwareLoopbackEnable) {
15285f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    for (Index = 0, BytesRead = 0; Index < *BufferSize; Index++) {
15295f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      if (IsaSerialFifoRemove (&Private->Fifo, &Data) == EFI_SUCCESS) {
15305f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        ((UINT8 *) Buffer)[Index] = Data;
15315f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        BytesRead++;
15325f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      } else {
15335f44f5b9bb21baefa954c0c36b5e86957ee68b86klu        break;
15345f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      }
15355f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    }
15365f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  } else {
15375f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    if (Private->HardwareFlowControl) {
15385f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      WinNtSerialIoGetControl (&Private->SerialIo, &Control);
15395f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      Control |= EFI_SERIAL_DATA_TERMINAL_READY;
15405f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      WinNtSerialIoSetControl (&Private->SerialIo, Control);
15415f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    }
15425f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
15435f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Result = Private->WinNtThunk->ReadFile (
15445f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                                    Private->NtHandle,
15455f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                                    Buffer,
15465f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                                    (DWORD) *BufferSize,
15475f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                                    &BytesRead,
15485f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                                    NULL
15495f44f5b9bb21baefa954c0c36b5e86957ee68b86klu                                    );
15505f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
15515f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    if (Private->HardwareFlowControl) {
15525f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      WinNtSerialIoGetControl (&Private->SerialIo, &Control);
15535f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      Control &= ~ (UINT32) EFI_SERIAL_DATA_TERMINAL_READY;
15545f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      WinNtSerialIoSetControl (&Private->SerialIo, Control);
15555f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    }
15565f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
15575f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    if (!Result) {
15585f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      Private->NtError = Private->WinNtThunk->GetLastError ();
15595f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      gBS->RestoreTPL (Tpl);
15605f44f5b9bb21baefa954c0c36b5e86957ee68b86klu      return EFI_DEVICE_ERROR;
15615f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    }
15625f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
15635f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
15645f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (BytesRead != *BufferSize) {
15655f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Status = EFI_TIMEOUT;
15665f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  } else {
15675f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Status = EFI_SUCCESS;
15685f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
15695f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
15705f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  *BufferSize = (UINTN) BytesRead;
15715f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
15725f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  gBS->RestoreTPL (Tpl);
15735f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
15745f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  return Status;
15755f44f5b9bb21baefa954c0c36b5e86957ee68b86klu}
15765f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
15775f44f5b9bb21baefa954c0c36b5e86957ee68b86kluBOOLEAN
15785f44f5b9bb21baefa954c0c36b5e86957ee68b86kluIsaSerialFifoFull (
15795f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN SERIAL_DEV_FIFO *Fifo
15805f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  )
15815f44f5b9bb21baefa954c0c36b5e86957ee68b86klu/*++
15825f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
15835f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Routine Description:
15845f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Detect whether specific FIFO is full or not
15855f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
15865f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Arguments:
15875f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Fifo  SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
15885f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
15895f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Returns:
15905f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  TRUE:  the FIFO is full
15915f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  FALSE: the FIFO is not full
15925f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
15935f44f5b9bb21baefa954c0c36b5e86957ee68b86klu--*/
15945f44f5b9bb21baefa954c0c36b5e86957ee68b86klu{
15955f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Fifo->Surplus == 0) {
15965f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    return TRUE;
15975f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
15985f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
15995f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  return FALSE;
16005f44f5b9bb21baefa954c0c36b5e86957ee68b86klu}
16015f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
16025f44f5b9bb21baefa954c0c36b5e86957ee68b86kluBOOLEAN
16035f44f5b9bb21baefa954c0c36b5e86957ee68b86kluIsaSerialFifoEmpty (
16045f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN SERIAL_DEV_FIFO *Fifo
16055f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  )
16065f44f5b9bb21baefa954c0c36b5e86957ee68b86klu/*++
16075f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
16085f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Routine Description:
16095f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Detect whether specific FIFO is empty or not
16105f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
16115f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Arguments:
16125f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Fifo  SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
16135f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
16145f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Returns:
16155f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    TRUE:  the FIFO is empty
16165f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    FALSE: the FIFO is not empty
16175f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
16185f44f5b9bb21baefa954c0c36b5e86957ee68b86klu--*/
16195f44f5b9bb21baefa954c0c36b5e86957ee68b86klu{
16205f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Fifo->Surplus == SERIAL_MAX_BUFFER_SIZE) {
16215f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    return TRUE;
16225f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
16235f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
16245f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  return FALSE;
16255f44f5b9bb21baefa954c0c36b5e86957ee68b86klu}
16265f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
16275f44f5b9bb21baefa954c0c36b5e86957ee68b86kluEFI_STATUS
16285f44f5b9bb21baefa954c0c36b5e86957ee68b86kluIsaSerialFifoAdd (
16295f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN SERIAL_DEV_FIFO *Fifo,
16305f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN UINT8           Data
16315f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  )
16325f44f5b9bb21baefa954c0c36b5e86957ee68b86klu/*++
16335f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
16345f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Routine Description:
16355f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Add data to specific FIFO
16365f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
16375f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Arguments:
16385f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Fifo  SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
16395f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Data  UINT8: the data added to FIFO
16405f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
16415f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Returns:
16425f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    EFI_SUCCESS:  Add data to specific FIFO successfully
16435f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    EFI_OUT_RESOURCE: Failed to add data because FIFO is already full
16445f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
16455f44f5b9bb21baefa954c0c36b5e86957ee68b86klu--*/
16465f44f5b9bb21baefa954c0c36b5e86957ee68b86klu// TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment
16475f44f5b9bb21baefa954c0c36b5e86957ee68b86klu{
16485f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
16495f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // if FIFO full can not add data
16505f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
16515f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (IsaSerialFifoFull (Fifo)) {
16525f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    return EFI_OUT_OF_RESOURCES;
16535f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
16545f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
16555f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
16565f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // FIFO is not full can add data
16575f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
16585f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Fifo->Data[Fifo->Last] = Data;
16595f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Fifo->Surplus--;
16605f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Fifo->Last++;
16615f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Fifo->Last >= SERIAL_MAX_BUFFER_SIZE) {
16625f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Fifo->Last = 0;
16635f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
16645f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
16655f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  return EFI_SUCCESS;
16665f44f5b9bb21baefa954c0c36b5e86957ee68b86klu}
16675f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
16685f44f5b9bb21baefa954c0c36b5e86957ee68b86kluEFI_STATUS
16695f44f5b9bb21baefa954c0c36b5e86957ee68b86kluIsaSerialFifoRemove (
16705f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  IN  SERIAL_DEV_FIFO *Fifo,
16715f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  OUT UINT8           *Data
16725f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  )
16735f44f5b9bb21baefa954c0c36b5e86957ee68b86klu/*++
16745f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
16755f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Routine Description:
16765f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Remove data from specific FIFO
16775f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
16785f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Arguments:
16795f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Fifo  SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
16805f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Data  UINT8*: the data removed from FIFO
16815f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
16825f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Returns:
16835f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    EFI_SUCCESS:  Remove data from specific FIFO successfully
16845f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    EFI_OUT_RESOURCE: Failed to remove data because FIFO is empty
16855f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
16865f44f5b9bb21baefa954c0c36b5e86957ee68b86klu--*/
16875f44f5b9bb21baefa954c0c36b5e86957ee68b86klu// TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment
16885f44f5b9bb21baefa954c0c36b5e86957ee68b86klu{
16895f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
16905f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // if FIFO is empty, no data can remove
16915f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
16925f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (IsaSerialFifoEmpty (Fifo)) {
16935f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    return EFI_OUT_OF_RESOURCES;
16945f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
16955f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
16965f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
16975f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  // FIFO is not empty, can remove data
16985f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  //
16995f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  *Data = Fifo->Data[Fifo->First];
17005f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Fifo->Surplus++;
17015f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  Fifo->First++;
17025f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  if (Fifo->First >= SERIAL_MAX_BUFFER_SIZE) {
17035f44f5b9bb21baefa954c0c36b5e86957ee68b86klu    Fifo->First = 0;
17045f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  }
17055f44f5b9bb21baefa954c0c36b5e86957ee68b86klu
17065f44f5b9bb21baefa954c0c36b5e86957ee68b86klu  return EFI_SUCCESS;
17075f44f5b9bb21baefa954c0c36b5e86957ee68b86klu}
1708