//\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
// 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
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
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
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
\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
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
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
// 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
\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
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
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
break;\r
}\r
}\r
- \r
+\r
if ((ReceiveFifoDepth < 1) || (ReceiveFifoDepth > SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
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
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
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