]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Nt32SerialIo driver was changed to produce the flow control device path node when...
authorniruiyu <niruiyu@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 9 Apr 2010 08:38:23 +0000 (08:38 +0000)
committerniruiyu <niruiyu@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 9 Apr 2010 08:38:23 +0000 (08:38 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10352 6f19259b-4bc3-4df7-8a09-765794883524

Nt32Pkg/WinNtSerialIoDxe/WinNtSerialIo.c
Nt32Pkg/WinNtSerialIoDxe/WinNtSerialIo.h
Nt32Pkg/WinNtSerialIoDxe/WinNtSerialIoDxe.inf

index b2c9089572528df9a1dc090924da6739d59f39ba..44bc510d7c9cd4ca277aec7cc6dc643549acb3ce 100644 (file)
@@ -61,6 +61,51 @@ EFI_DRIVER_BINDING_PROTOCOL gWinNtSerialIoDriverBinding = {
 //\r
 UINT64 mBaudRateCurrentSupport[] = {50, 75, 110, 134, 150, 300, 600, 1200, 1800, 2000, 2400, 3600, 4800, 7200, 9600, 19200, 38400, 57600, 115200, SERIAL_PORT_MAX_BAUD_RATE + 1};\r
 \r
+/**\r
+  Check the device path node whether it's the Flow Control node or not.\r
+\r
+  @param[in] FlowControl    The device path node to be checked.\r
+  \r
+  @retval TRUE              It's the Flow Control node.\r
+  @retval FALSE             It's not.\r
+\r
+**/\r
+BOOLEAN\r
+IsUartFlowControlNode (\r
+  IN UART_FLOW_CONTROL_DEVICE_PATH *FlowControl\r
+  )\r
+{\r
+  return (BOOLEAN) (\r
+           (DevicePathType (FlowControl) == MESSAGING_DEVICE_PATH) &&\r
+           (DevicePathSubType (FlowControl) == MSG_VENDOR_DP) &&\r
+           (CompareGuid (&FlowControl->Guid, &gEfiUartDevicePathGuid))\r
+           );\r
+}\r
+\r
+/**\r
+  Check the device path node whether it contains Flow Control node or not.\r
+\r
+  @param[in] DevicePath     The device path to be checked.\r
+  \r
+  @retval TRUE              It contains the Flow Control node.\r
+  @retval FALSE             It doesn't.\r
+\r
+**/\r
+BOOLEAN\r
+ContainsFlowControl (\r
+  IN EFI_DEVICE_PATH_PROTOCOL      *DevicePath\r
+  )\r
+{\r
+  while (!IsDevicePathEnd (DevicePath)) {\r
+    if (IsUartFlowControlNode ((UART_FLOW_CONTROL_DEVICE_PATH *) DevicePath)) {\r
+      return TRUE;\r
+    }\r
+    DevicePath = NextDevicePathNode (DevicePath);\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
 /**\r
   The user Entry Point for module WinNtSerialIo. The user code starts with this function.\r
 \r
@@ -121,10 +166,15 @@ Returns:
 // TODO:    EFI_SUCCESS - add return value to function comment\r
 // TODO:    EFI_SUCCESS - add return value to function comment\r
 {\r
-  EFI_STATUS                Status;\r
-  EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;\r
-  EFI_WIN_NT_IO_PROTOCOL    *WinNtIo;\r
-  UART_DEVICE_PATH          *UartNode;\r
+  EFI_STATUS                          Status;\r
+  EFI_DEVICE_PATH_PROTOCOL            *ParentDevicePath;\r
+  EFI_WIN_NT_IO_PROTOCOL              *WinNtIo;\r
+  UART_DEVICE_PATH                    *UartNode;\r
+  EFI_DEVICE_PATH_PROTOCOL            *DevicePath;\r
+  UART_FLOW_CONTROL_DEVICE_PATH       *FlowControlNode;\r
+  EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
+  UINTN                               EntryCount;\r
+  UINTN                               Index;\r
 \r
   //\r
   // Check RemainingDevicePath validation\r
@@ -165,6 +215,17 @@ Returns:
       if ((UartNode->DataBits >= 6) && (UartNode->DataBits <= 8) && (UartNode->StopBits == OneFiveStopBits)) {\r
         goto Error;\r
       }\r
+\r
+      FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (UartNode);\r
+      if (IsUartFlowControlNode (FlowControlNode)) {\r
+        //\r
+        // If the second node is Flow Control Node,\r
+        //   return error when it request other than hardware flow control.\r
+        //\r
+        if ((FlowControlNode->FlowControlMap & ~UART_FLOW_CONTROL_HARDWARE) != 0) {\r
+          goto Error;\r
+        }\r
+      }\r
     }\r
   }\r
 \r
@@ -180,7 +241,45 @@ Returns:
                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
                   );\r
   if (Status == EFI_ALREADY_STARTED) {\r
-    return EFI_SUCCESS;\r
+    if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) {\r
+      //\r
+      // If RemainingDevicePath is NULL or is the End of Device Path Node\r
+      //\r
+      return EFI_SUCCESS;\r
+    }\r
+    //\r
+    // When the driver has produced device path with flow control node but RemainingDevicePath only contains UART node,\r
+    //   return unsupported, and vice versa.\r
+    //\r
+    Status = gBS->OpenProtocolInformation (\r
+                    Handle,\r
+                    &gEfiWinNtIoProtocolGuid,\r
+                    &OpenInfoBuffer,\r
+                    &EntryCount\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    for (Index = 0; Index < EntryCount; Index++) {\r
+      if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
+        Status = gBS->OpenProtocol (\r
+                        OpenInfoBuffer[Index].ControllerHandle,\r
+                        &gEfiDevicePathProtocolGuid,\r
+                        (VOID **) &DevicePath,\r
+                        This->DriverBindingHandle,\r
+                        Handle,\r
+                        EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                        );\r
+        if (!EFI_ERROR (Status) &&\r
+            (ContainsFlowControl (RemainingDevicePath) ^ ContainsFlowControl (DevicePath))) {\r
+          Status = EFI_UNSUPPORTED;\r
+        }\r
+        break;\r
+      }\r
+    }\r
+    FreePool (OpenInfoBuffer);\r
+    return Status;\r
   }\r
 \r
   if (EFI_ERROR (Status)) {\r
@@ -276,19 +375,23 @@ Returns:
   EFI_WIN_NT_IO_PROTOCOL              *WinNtIo;\r
   WIN_NT_SERIAL_IO_PRIVATE_DATA       *Private;\r
   HANDLE                              NtHandle;\r
-  UART_DEVICE_PATH                    Node;\r
+  UART_DEVICE_PATH                    UartNode;\r
   EFI_DEVICE_PATH_PROTOCOL            *ParentDevicePath;\r
   EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
   UINTN                               EntryCount;\r
   UINTN                               Index;\r
   EFI_SERIAL_IO_PROTOCOL              *SerialIo;\r
-  UART_DEVICE_PATH                    *UartNode;\r
+  UART_DEVICE_PATH                    *Uart;\r
+  UINT32                              FlowControlMap;\r
+  UART_FLOW_CONTROL_DEVICE_PATH       *FlowControl;\r
+  EFI_DEVICE_PATH_PROTOCOL            *TempDevicePath;\r
+  UINT32                              Control;\r
 \r
   Private   = NULL;\r
   NtHandle  = INVALID_HANDLE_VALUE;\r
 \r
   //\r
-  // Grab the protocols we need\r
+  // Get the Parent Device Path\r
   //\r
   Status = gBS->OpenProtocol (\r
                   Handle,\r
@@ -348,7 +451,7 @@ Returns:
 \r
     Status = EFI_ALREADY_STARTED;\r
     for (Index = 0; Index < EntryCount; Index++) {\r
-      if (OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {\r
+      if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
         Status = gBS->OpenProtocol (\r
                         OpenInfoBuffer[Index].ControllerHandle,\r
                         &gEfiSerialIoProtocolGuid,\r
@@ -358,16 +461,34 @@ Returns:
                         EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
                         );\r
         if (!EFI_ERROR (Status)) {\r
-          UartNode = (UART_DEVICE_PATH *) RemainingDevicePath;\r
+          Uart   = (UART_DEVICE_PATH *) RemainingDevicePath;\r
           Status = SerialIo->SetAttributes (\r
-                              SerialIo,\r
-                              UartNode->BaudRate,\r
-                              SerialIo->Mode->ReceiveFifoDepth,\r
-                              SerialIo->Mode->Timeout,\r
-                              (EFI_PARITY_TYPE)UartNode->Parity,\r
-                              UartNode->DataBits,\r
-                              (EFI_STOP_BITS_TYPE)UartNode->StopBits\r
-                              );\r
+                               SerialIo,\r
+                               Uart->BaudRate,\r
+                               SerialIo->Mode->ReceiveFifoDepth,\r
+                               SerialIo->Mode->Timeout,\r
+                               (EFI_PARITY_TYPE) Uart->Parity,\r
+                               Uart->DataBits,\r
+                               (EFI_STOP_BITS_TYPE) Uart->StopBits\r
+                               );\r
+          FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Uart);\r
+          if (!EFI_ERROR (Status) && IsUartFlowControlNode (FlowControl)) {\r
+            Status = SerialIo->GetControl (SerialIo, &Control);\r
+            if (!EFI_ERROR (Status)) {\r
+              if (FlowControl->FlowControlMap == UART_FLOW_CONTROL_HARDWARE) {\r
+                Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;\r
+              } else {\r
+                Control &= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;\r
+              }\r
+              //\r
+              // Clear the bits that are not allowed to pass to SetControl\r
+              //\r
+              Control &= (EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY |\r
+                          EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE | \r
+                          EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE);\r
+              Status = SerialIo->SetControl (SerialIo, Control);\r
+            }\r
+          }\r
         }\r
         break;\r
       }\r
@@ -377,16 +498,18 @@ Returns:
     return Status;\r
   }\r
 \r
+  FlowControl    = NULL;\r
+  FlowControlMap = 0;\r
   if (RemainingDevicePath == NULL) {\r
     //\r
     // Build the device path by appending the UART node to the ParentDevicePath\r
     // from the WinNtIo handle. The Uart setings are zero here, since\r
     // SetAttribute() will update them to match the default setings.\r
     //\r
-    ZeroMem (&Node, sizeof (UART_DEVICE_PATH));\r
-    Node.Header.Type     = MESSAGING_DEVICE_PATH;\r
-    Node.Header.SubType  = MSG_UART_DP;\r
-    SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) &Node, sizeof (UART_DEVICE_PATH));\r
+    ZeroMem (&UartNode, sizeof (UART_DEVICE_PATH));\r
+    UartNode.Header.Type     = MESSAGING_DEVICE_PATH;\r
+    UartNode.Header.SubType  = MSG_UART_DP;\r
+    SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) &UartNode, sizeof (UART_DEVICE_PATH));\r
 \r
   } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
     //\r
@@ -398,7 +521,13 @@ Returns:
     // already checked to make sure the RemainingDevicePath contains settings\r
     // that we can support.\r
     //\r
-    CopyMem (&Node, RemainingDevicePath, sizeof (UART_DEVICE_PATH));\r
+    CopyMem (&UartNode, RemainingDevicePath, sizeof (UART_DEVICE_PATH));\r
+    FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (RemainingDevicePath);\r
+    if (IsUartFlowControlNode (FlowControl)) {\r
+      FlowControlMap = FlowControl->FlowControlMap;\r
+    } else {\r
+      FlowControl    = NULL;\r
+    }\r
 \r
   } else {\r
     //\r
@@ -447,12 +576,12 @@ Returns:
 \r
   Private->SoftwareLoopbackEnable = FALSE;\r
   Private->HardwareLoopbackEnable = FALSE;\r
-  Private->HardwareFlowControl    = FALSE;\r
+  Private->HardwareFlowControl    = (BOOLEAN) (FlowControlMap == UART_FLOW_CONTROL_HARDWARE);\r
   Private->Fifo.First             = 0;\r
   Private->Fifo.Last              = 0;\r
   Private->Fifo.Surplus           = SERIAL_MAX_BUFFER_SIZE;\r
 \r
-  CopyMem (&Private->UartDevicePath, &Node, sizeof (UART_DEVICE_PATH));\r
+  CopyMem (&Private->UartDevicePath, &UartNode, sizeof (UART_DEVICE_PATH));\r
 \r
   AddUnicodeString2 (\r
     "eng",\r
@@ -488,6 +617,19 @@ Returns:
                           ParentDevicePath,\r
                           (EFI_DEVICE_PATH_PROTOCOL *) &Private->UartDevicePath\r
                           );\r
+  //\r
+  // Only produce the FlowControl node when remaining device path has it\r
+  //\r
+  if (FlowControl != NULL) {\r
+    TempDevicePath = Private->DevicePath;\r
+    if (TempDevicePath != NULL) {\r
+      Private->DevicePath = AppendDevicePathNode (\r
+                              TempDevicePath,\r
+                              (EFI_DEVICE_PATH_PROTOCOL *) FlowControl\r
+                              );\r
+      FreePool (TempDevicePath);\r
+    }\r
+  }\r
   if (Private->DevicePath == NULL) {\r
     Status = EFI_OUT_OF_RESOURCES;\r
     goto Error;\r
@@ -791,7 +933,7 @@ Returns:
   COMMTIMEOUTS                  PortTimeOuts;\r
   DWORD                         ConvertedTime;\r
   BOOL                          Result;\r
-  EFI_DEVICE_PATH_PROTOCOL      *NewDevicePath;\r
+  UART_DEVICE_PATH              *Uart;\r
   EFI_TPL                       Tpl;\r
 \r
   Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);\r
@@ -841,7 +983,7 @@ Returns:
       break;\r
       }\r
   }\r
-       \r
+\r
   if ((ReceiveFifoDepth < 1) || (ReceiveFifoDepth > SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
@@ -976,37 +1118,25 @@ Returns:
   Private->UartDevicePath.Parity    = (UINT8) Parity;\r
   Private->UartDevicePath.StopBits  = (UINT8) StopBits;\r
 \r
-  NewDevicePath = AppendDevicePathNode (\r
-                    Private->ParentDevicePath,\r
-                    (EFI_DEVICE_PATH_PROTOCOL *) &Private->UartDevicePath\r
-                    );\r
-  if (NewDevicePath == NULL) {\r
-    gBS->RestoreTPL (Tpl);\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
-\r
+  Status = EFI_SUCCESS;\r
   if (Private->Handle != NULL) {\r
+    Uart = (UART_DEVICE_PATH *) (\r
+             (UINTN) Private->DevicePath\r
+             + GetDevicePathSize (Private->ParentDevicePath)\r
+             - END_DEVICE_PATH_LENGTH\r
+             );\r
+    CopyMem (Uart, &Private->UartDevicePath, sizeof (UART_DEVICE_PATH));\r
     Status = gBS->ReinstallProtocolInterface (\r
                     Private->Handle,\r
                     &gEfiDevicePathProtocolGuid,\r
                     Private->DevicePath,\r
-                    NewDevicePath\r
+                    Private->DevicePath\r
                     );\r
-    if (EFI_ERROR (Status)) {\r
-      gBS->RestoreTPL (Tpl);\r
-      return Status;\r
-    }\r
-  }\r
-\r
-  if (Private->DevicePath != NULL) {\r
-    FreePool (Private->DevicePath);\r
   }\r
 \r
-  Private->DevicePath = NewDevicePath;\r
-\r
   gBS->RestoreTPL (Tpl);\r
 \r
-  return EFI_SUCCESS;\r
+  return Status;\r
 }\r
 \r
 EFI_STATUS\r
@@ -1038,6 +1168,8 @@ Returns:
   BOOL                          Result;\r
   DCB                           Dcb;\r
   EFI_TPL                       Tpl;\r
+  UART_FLOW_CONTROL_DEVICE_PATH *FlowControl;\r
+  EFI_STATUS                    Status;\r
 \r
   //\r
   // first determine the parameter is invalid\r
@@ -1099,9 +1231,32 @@ Returns:
     return EFI_DEVICE_ERROR;\r
   }\r
 \r
+  Status = EFI_SUCCESS;\r
+  if (Private->Handle != NULL) {\r
+    FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) (\r
+                    (UINTN) Private->DevicePath\r
+                    + GetDevicePathSize (Private->ParentDevicePath)\r
+                    - END_DEVICE_PATH_LENGTH\r
+                    + sizeof (UART_DEVICE_PATH)\r
+                    );\r
+    if (IsUartFlowControlNode (FlowControl) &&\r
+        ((FlowControl->FlowControlMap == UART_FLOW_CONTROL_HARDWARE) ^ Private->HardwareFlowControl)) {\r
+      //\r
+      // Flow Control setting is changed, need to reinstall device path protocol\r
+      //\r
+      FlowControl->FlowControlMap = Private->HardwareFlowControl ? UART_FLOW_CONTROL_HARDWARE : 0;\r
+      Status = gBS->ReinstallProtocolInterface (\r
+                      Private->Handle,\r
+                      &gEfiDevicePathProtocolGuid,\r
+                      Private->DevicePath,\r
+                      Private->DevicePath\r
+                      );\r
+    }\r
+  }\r
+\r
   gBS->RestoreTPL (Tpl);\r
 \r
-  return EFI_SUCCESS;\r
+  return Status;\r
 }\r
 \r
 EFI_STATUS\r
index 348cca82b459c7467e74e2e0b6eee0ad73fa4dc3..53fd4593606519f1580536984e910ed1d609d5e2 100644 (file)
@@ -120,12 +120,15 @@ extern EFI_COMPONENT_NAME2_PROTOCOL  gWinNtSerialIoComponentName2;
 #define SERIAL_PARITY_DEFAULT   DefaultParity\r
 #define SERIAL_STOPBITS_DEFAULT DefaultStopBits\r
 \r
-#define SERIAL_CONTROL_MASK     (EFI_SERIAL_CLEAR_TO_SEND       | \\r
-                                 EFI_SERIAL_DATA_SET_READY      | \\r
-                                 EFI_SERIAL_RING_INDICATE       | \\r
-                                 EFI_SERIAL_CARRIER_DETECT      | \\r
-                                 EFI_SERIAL_REQUEST_TO_SEND     | \\r
-                                 EFI_SERIAL_DATA_TERMINAL_READY | \\r
+#define SERIAL_CONTROL_MASK     (EFI_SERIAL_CLEAR_TO_SEND                | \\r
+                                 EFI_SERIAL_DATA_SET_READY               | \\r
+                                 EFI_SERIAL_RING_INDICATE                | \\r
+                                 EFI_SERIAL_CARRIER_DETECT               | \\r
+                                 EFI_SERIAL_REQUEST_TO_SEND              | \\r
+                                 EFI_SERIAL_DATA_TERMINAL_READY          | \\r
+                                 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE     | \\r
+                                 EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE     | \\r
+                                 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE | \\r
                                  EFI_SERIAL_INPUT_BUFFER_EMPTY)\r
 \r
 #define ConvertBaud2Nt(x)       (DWORD) x\r
index 9be5441911e6533a25ebad661e8c07239c211e34..d4574ba54193f3bb0d2da851bbe83427915a2f55 100644 (file)
@@ -53,6 +53,7 @@
 \r
 [Guids]\r
   gEfiWinNtSerialPortGuid                       # ALWAYS_CONSUMED\r
+  gEfiUartDevicePathGuid\r
 \r
 [Protocols]\r
   gEfiSerialIoProtocolGuid                      # PROTOCOL BY_START\r