From ff72001b5b0e581e53614015d93abd1107bee25b Mon Sep 17 00:00:00 2001 From: niruiyu Date: Fri, 9 Apr 2010 08:38:23 +0000 Subject: =?UTF-8?q?Nt32SerialIo=20driver=20was=20changed=20to=20produce=20?= =?UTF-8?q?the=20flow=20control=20device=20path=20node=20when=20the=20rema?= =?UTF-8?q?ining=20device=20path=20contains=20such=20node.=20And=20it=20wi?= =?UTF-8?q?ll=20return=20unsupported=20when=20receiving=20a=20remaining=20?= =?UTF-8?q?device=20path=20only=20contains=20UART=20node=20and=20it?= =?UTF-8?q?=E2=80=99s=20already=20produced=20the=20flow=20control=20node.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10352 6f19259b-4bc3-4df7-8a09-765794883524 --- Nt32Pkg/WinNtSerialIoDxe/WinNtSerialIo.c | 253 +++++++++++++++++++++----- Nt32Pkg/WinNtSerialIoDxe/WinNtSerialIo.h | 15 +- Nt32Pkg/WinNtSerialIoDxe/WinNtSerialIoDxe.inf | 1 + 3 files changed, 214 insertions(+), 55 deletions(-) (limited to 'Nt32Pkg/WinNtSerialIoDxe') diff --git a/Nt32Pkg/WinNtSerialIoDxe/WinNtSerialIo.c b/Nt32Pkg/WinNtSerialIoDxe/WinNtSerialIo.c index b2c9089572..44bc510d7c 100644 --- a/Nt32Pkg/WinNtSerialIoDxe/WinNtSerialIo.c +++ b/Nt32Pkg/WinNtSerialIoDxe/WinNtSerialIo.c @@ -61,6 +61,51 @@ EFI_DRIVER_BINDING_PROTOCOL gWinNtSerialIoDriverBinding = { // 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}; +/** + Check the device path node whether it's the Flow Control node or not. + + @param[in] FlowControl The device path node to be checked. + + @retval TRUE It's the Flow Control node. + @retval FALSE It's not. + +**/ +BOOLEAN +IsUartFlowControlNode ( + IN UART_FLOW_CONTROL_DEVICE_PATH *FlowControl + ) +{ + return (BOOLEAN) ( + (DevicePathType (FlowControl) == MESSAGING_DEVICE_PATH) && + (DevicePathSubType (FlowControl) == MSG_VENDOR_DP) && + (CompareGuid (&FlowControl->Guid, &gEfiUartDevicePathGuid)) + ); +} + +/** + Check the device path node whether it contains Flow Control node or not. + + @param[in] DevicePath The device path to be checked. + + @retval TRUE It contains the Flow Control node. + @retval FALSE It doesn't. + +**/ +BOOLEAN +ContainsFlowControl ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + while (!IsDevicePathEnd (DevicePath)) { + if (IsUartFlowControlNode ((UART_FLOW_CONTROL_DEVICE_PATH *) DevicePath)) { + return TRUE; + } + DevicePath = NextDevicePathNode (DevicePath); + } + + return FALSE; +} + /** The user Entry Point for module WinNtSerialIo. The user code starts with this function. @@ -121,10 +166,15 @@ Returns: // TODO: EFI_SUCCESS - add return value to function comment // TODO: EFI_SUCCESS - add return value to function comment { - EFI_STATUS Status; - EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; - EFI_WIN_NT_IO_PROTOCOL *WinNtIo; - UART_DEVICE_PATH *UartNode; + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_WIN_NT_IO_PROTOCOL *WinNtIo; + UART_DEVICE_PATH *UartNode; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UART_FLOW_CONTROL_DEVICE_PATH *FlowControlNode; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; + UINTN EntryCount; + UINTN Index; // // Check RemainingDevicePath validation @@ -165,6 +215,17 @@ Returns: if ((UartNode->DataBits >= 6) && (UartNode->DataBits <= 8) && (UartNode->StopBits == OneFiveStopBits)) { goto Error; } + + FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (UartNode); + if (IsUartFlowControlNode (FlowControlNode)) { + // + // If the second node is Flow Control Node, + // return error when it request other than hardware flow control. + // + if ((FlowControlNode->FlowControlMap & ~UART_FLOW_CONTROL_HARDWARE) != 0) { + goto Error; + } + } } } @@ -180,7 +241,45 @@ Returns: EFI_OPEN_PROTOCOL_BY_DRIVER ); if (Status == EFI_ALREADY_STARTED) { - return EFI_SUCCESS; + if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) { + // + // If RemainingDevicePath is NULL or is the End of Device Path Node + // + return EFI_SUCCESS; + } + // + // When the driver has produced device path with flow control node but RemainingDevicePath only contains UART node, + // return unsupported, and vice versa. + // + Status = gBS->OpenProtocolInformation ( + Handle, + &gEfiWinNtIoProtocolGuid, + &OpenInfoBuffer, + &EntryCount + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < EntryCount; Index++) { + if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { + Status = gBS->OpenProtocol ( + OpenInfoBuffer[Index].ControllerHandle, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status) && + (ContainsFlowControl (RemainingDevicePath) ^ ContainsFlowControl (DevicePath))) { + Status = EFI_UNSUPPORTED; + } + break; + } + } + FreePool (OpenInfoBuffer); + return Status; } if (EFI_ERROR (Status)) { @@ -276,19 +375,23 @@ Returns: EFI_WIN_NT_IO_PROTOCOL *WinNtIo; WIN_NT_SERIAL_IO_PRIVATE_DATA *Private; HANDLE NtHandle; - UART_DEVICE_PATH Node; + UART_DEVICE_PATH UartNode; EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; UINTN EntryCount; UINTN Index; EFI_SERIAL_IO_PROTOCOL *SerialIo; - UART_DEVICE_PATH *UartNode; + UART_DEVICE_PATH *Uart; + UINT32 FlowControlMap; + UART_FLOW_CONTROL_DEVICE_PATH *FlowControl; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + UINT32 Control; Private = NULL; NtHandle = INVALID_HANDLE_VALUE; // - // Grab the protocols we need + // Get the Parent Device Path // Status = gBS->OpenProtocol ( Handle, @@ -348,7 +451,7 @@ Returns: Status = EFI_ALREADY_STARTED; for (Index = 0; Index < EntryCount; Index++) { - if (OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) { + if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { Status = gBS->OpenProtocol ( OpenInfoBuffer[Index].ControllerHandle, &gEfiSerialIoProtocolGuid, @@ -358,16 +461,34 @@ Returns: EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (!EFI_ERROR (Status)) { - UartNode = (UART_DEVICE_PATH *) RemainingDevicePath; + Uart = (UART_DEVICE_PATH *) RemainingDevicePath; Status = SerialIo->SetAttributes ( - SerialIo, - UartNode->BaudRate, - SerialIo->Mode->ReceiveFifoDepth, - SerialIo->Mode->Timeout, - (EFI_PARITY_TYPE)UartNode->Parity, - UartNode->DataBits, - (EFI_STOP_BITS_TYPE)UartNode->StopBits - ); + SerialIo, + Uart->BaudRate, + SerialIo->Mode->ReceiveFifoDepth, + SerialIo->Mode->Timeout, + (EFI_PARITY_TYPE) Uart->Parity, + Uart->DataBits, + (EFI_STOP_BITS_TYPE) Uart->StopBits + ); + FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Uart); + if (!EFI_ERROR (Status) && IsUartFlowControlNode (FlowControl)) { + Status = SerialIo->GetControl (SerialIo, &Control); + if (!EFI_ERROR (Status)) { + if (FlowControl->FlowControlMap == UART_FLOW_CONTROL_HARDWARE) { + Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; + } else { + Control &= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; + } + // + // Clear the bits that are not allowed to pass to SetControl + // + Control &= (EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY | + EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE | + EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE); + Status = SerialIo->SetControl (SerialIo, Control); + } + } } break; } @@ -377,16 +498,18 @@ Returns: return Status; } + FlowControl = NULL; + FlowControlMap = 0; if (RemainingDevicePath == NULL) { // // Build the device path by appending the UART node to the ParentDevicePath // from the WinNtIo handle. The Uart setings are zero here, since // SetAttribute() will update them to match the default setings. // - ZeroMem (&Node, sizeof (UART_DEVICE_PATH)); - Node.Header.Type = MESSAGING_DEVICE_PATH; - Node.Header.SubType = MSG_UART_DP; - SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) &Node, sizeof (UART_DEVICE_PATH)); + ZeroMem (&UartNode, sizeof (UART_DEVICE_PATH)); + UartNode.Header.Type = MESSAGING_DEVICE_PATH; + UartNode.Header.SubType = MSG_UART_DP; + SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) &UartNode, sizeof (UART_DEVICE_PATH)); } else if (!IsDevicePathEnd (RemainingDevicePath)) { // @@ -398,7 +521,13 @@ Returns: // already checked to make sure the RemainingDevicePath contains settings // that we can support. // - CopyMem (&Node, RemainingDevicePath, sizeof (UART_DEVICE_PATH)); + CopyMem (&UartNode, RemainingDevicePath, sizeof (UART_DEVICE_PATH)); + FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (RemainingDevicePath); + if (IsUartFlowControlNode (FlowControl)) { + FlowControlMap = FlowControl->FlowControlMap; + } else { + FlowControl = NULL; + } } else { // @@ -447,12 +576,12 @@ Returns: Private->SoftwareLoopbackEnable = FALSE; Private->HardwareLoopbackEnable = FALSE; - Private->HardwareFlowControl = FALSE; + Private->HardwareFlowControl = (BOOLEAN) (FlowControlMap == UART_FLOW_CONTROL_HARDWARE); Private->Fifo.First = 0; Private->Fifo.Last = 0; Private->Fifo.Surplus = SERIAL_MAX_BUFFER_SIZE; - CopyMem (&Private->UartDevicePath, &Node, sizeof (UART_DEVICE_PATH)); + CopyMem (&Private->UartDevicePath, &UartNode, sizeof (UART_DEVICE_PATH)); AddUnicodeString2 ( "eng", @@ -488,6 +617,19 @@ Returns: ParentDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &Private->UartDevicePath ); + // + // Only produce the FlowControl node when remaining device path has it + // + if (FlowControl != NULL) { + TempDevicePath = Private->DevicePath; + if (TempDevicePath != NULL) { + Private->DevicePath = AppendDevicePathNode ( + TempDevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) FlowControl + ); + FreePool (TempDevicePath); + } + } if (Private->DevicePath == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Error; @@ -791,7 +933,7 @@ Returns: COMMTIMEOUTS PortTimeOuts; DWORD ConvertedTime; BOOL Result; - EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + UART_DEVICE_PATH *Uart; EFI_TPL Tpl; Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This); @@ -841,7 +983,7 @@ Returns: break; } } - + if ((ReceiveFifoDepth < 1) || (ReceiveFifoDepth > SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH)) { return EFI_INVALID_PARAMETER; } @@ -976,37 +1118,25 @@ Returns: Private->UartDevicePath.Parity = (UINT8) Parity; Private->UartDevicePath.StopBits = (UINT8) StopBits; - NewDevicePath = AppendDevicePathNode ( - Private->ParentDevicePath, - (EFI_DEVICE_PATH_PROTOCOL *) &Private->UartDevicePath - ); - if (NewDevicePath == NULL) { - gBS->RestoreTPL (Tpl); - return EFI_DEVICE_ERROR; - } - + Status = EFI_SUCCESS; if (Private->Handle != NULL) { + Uart = (UART_DEVICE_PATH *) ( + (UINTN) Private->DevicePath + + GetDevicePathSize (Private->ParentDevicePath) + - END_DEVICE_PATH_LENGTH + ); + CopyMem (Uart, &Private->UartDevicePath, sizeof (UART_DEVICE_PATH)); Status = gBS->ReinstallProtocolInterface ( Private->Handle, &gEfiDevicePathProtocolGuid, Private->DevicePath, - NewDevicePath + Private->DevicePath ); - if (EFI_ERROR (Status)) { - gBS->RestoreTPL (Tpl); - return Status; - } - } - - if (Private->DevicePath != NULL) { - FreePool (Private->DevicePath); } - Private->DevicePath = NewDevicePath; - gBS->RestoreTPL (Tpl); - return EFI_SUCCESS; + return Status; } EFI_STATUS @@ -1038,6 +1168,8 @@ Returns: BOOL Result; DCB Dcb; EFI_TPL Tpl; + UART_FLOW_CONTROL_DEVICE_PATH *FlowControl; + EFI_STATUS Status; // // first determine the parameter is invalid @@ -1099,9 +1231,32 @@ Returns: return EFI_DEVICE_ERROR; } + Status = EFI_SUCCESS; + if (Private->Handle != NULL) { + FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) ( + (UINTN) Private->DevicePath + + GetDevicePathSize (Private->ParentDevicePath) + - END_DEVICE_PATH_LENGTH + + sizeof (UART_DEVICE_PATH) + ); + if (IsUartFlowControlNode (FlowControl) && + ((FlowControl->FlowControlMap == UART_FLOW_CONTROL_HARDWARE) ^ Private->HardwareFlowControl)) { + // + // Flow Control setting is changed, need to reinstall device path protocol + // + FlowControl->FlowControlMap = Private->HardwareFlowControl ? UART_FLOW_CONTROL_HARDWARE : 0; + Status = gBS->ReinstallProtocolInterface ( + Private->Handle, + &gEfiDevicePathProtocolGuid, + Private->DevicePath, + Private->DevicePath + ); + } + } + gBS->RestoreTPL (Tpl); - return EFI_SUCCESS; + return Status; } EFI_STATUS diff --git a/Nt32Pkg/WinNtSerialIoDxe/WinNtSerialIo.h b/Nt32Pkg/WinNtSerialIoDxe/WinNtSerialIo.h index 348cca82b4..53fd459360 100644 --- a/Nt32Pkg/WinNtSerialIoDxe/WinNtSerialIo.h +++ b/Nt32Pkg/WinNtSerialIoDxe/WinNtSerialIo.h @@ -120,12 +120,15 @@ extern EFI_COMPONENT_NAME2_PROTOCOL gWinNtSerialIoComponentName2; #define SERIAL_PARITY_DEFAULT DefaultParity #define SERIAL_STOPBITS_DEFAULT DefaultStopBits -#define SERIAL_CONTROL_MASK (EFI_SERIAL_CLEAR_TO_SEND | \ - EFI_SERIAL_DATA_SET_READY | \ - EFI_SERIAL_RING_INDICATE | \ - EFI_SERIAL_CARRIER_DETECT | \ - EFI_SERIAL_REQUEST_TO_SEND | \ - EFI_SERIAL_DATA_TERMINAL_READY | \ +#define SERIAL_CONTROL_MASK (EFI_SERIAL_CLEAR_TO_SEND | \ + EFI_SERIAL_DATA_SET_READY | \ + EFI_SERIAL_RING_INDICATE | \ + EFI_SERIAL_CARRIER_DETECT | \ + EFI_SERIAL_REQUEST_TO_SEND | \ + EFI_SERIAL_DATA_TERMINAL_READY | \ + EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | \ + EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE | \ + EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE | \ EFI_SERIAL_INPUT_BUFFER_EMPTY) #define ConvertBaud2Nt(x) (DWORD) x diff --git a/Nt32Pkg/WinNtSerialIoDxe/WinNtSerialIoDxe.inf b/Nt32Pkg/WinNtSerialIoDxe/WinNtSerialIoDxe.inf index 9be5441911..d4574ba541 100644 --- a/Nt32Pkg/WinNtSerialIoDxe/WinNtSerialIoDxe.inf +++ b/Nt32Pkg/WinNtSerialIoDxe/WinNtSerialIoDxe.inf @@ -53,6 +53,7 @@ [Guids] gEfiWinNtSerialPortGuid # ALWAYS_CONSUMED + gEfiUartDevicePathGuid [Protocols] gEfiSerialIoProtocolGuid # PROTOCOL BY_START -- cgit v1.2.3