1a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni/** @file 2a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Serial driver for PCI or SIO UARTS. 3a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 4a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiCopyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR> 5a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiThis program and the accompanying materials 6a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Niare licensed and made available under the terms and conditions of the BSD License 7a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Niwhich accompanies this distribution. The full text of the license may be found at 8a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Nihttp://opensource.org/licenses/bsd-license.php 9a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 10a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 13a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni**/ 14a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 15a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni#include "Serial.h" 16a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 17a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni// 18a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni// ISA Serial Driver Global Variables 19a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni// 20a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 21a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiEFI_DRIVER_BINDING_PROTOCOL gSerialControllerDriver = { 22a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialControllerDriverSupported, 23a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialControllerDriverStart, 24a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialControllerDriverStop, 25a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 0xa, 26a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni NULL, 27a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni NULL 28a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni}; 29a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 30a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiCONTROLLER_DEVICE_PATH mControllerDevicePathTemplate = { 31a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni { 32a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni HARDWARE_DEVICE_PATH, 33a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni HW_CONTROLLER_DP, 3483809dc0186eea34a9b0db6df306abe9e1c7776bMichael Kinney { 3583809dc0186eea34a9b0db6df306abe9e1c7776bMichael Kinney (UINT8) (sizeof (CONTROLLER_DEVICE_PATH)), 3683809dc0186eea34a9b0db6df306abe9e1c7776bMichael Kinney (UINT8) ((sizeof (CONTROLLER_DEVICE_PATH)) >> 8) 3783809dc0186eea34a9b0db6df306abe9e1c7776bMichael Kinney } 38a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni }, 39a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 0 40a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni}; 41a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 42a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiSERIAL_DEV gSerialDevTemplate = { 43a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SERIAL_DEV_SIGNATURE, 44a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni NULL, 45a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni { 46a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SERIAL_IO_INTERFACE_REVISION, 47a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialReset, 48a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialSetAttributes, 49a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialSetControl, 50a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialGetControl, 51a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialWrite, 52a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialRead, 53a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni NULL 54a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni }, // SerialIo 55a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni { 56a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SERIAL_PORT_SUPPORT_CONTROL_MASK, 57a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SERIAL_PORT_DEFAULT_TIMEOUT, 58a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 0, 59a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 16, 60a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 0, 61a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 0, 62a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 0 63a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni }, // SerialMode 64a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni NULL, // DevicePath 65a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni NULL, // ParentDevicePath 66a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni { 67a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni { 68a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni MESSAGING_DEVICE_PATH, 69a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni MSG_UART_DP, 70a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni { 71a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (UINT8) (sizeof (UART_DEVICE_PATH)), 72a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8) 73a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 74a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni }, 75a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 0, 0, 0, 0, 0 76a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni }, // UartDevicePath 77a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 0, // BaseAddress 78a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni FALSE, // MmioAccess 79a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1, // RegisterStride 80a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 0, // ClockRate 81a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 16, // ReceiveFifoDepth 82a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni { 0, 0 }, // Receive; 83a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 16, // TransmitFifoDepth 84a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni { 0, 0 }, // Transmit; 85a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni FALSE, // SoftwareLoopbackEnable; 86a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni FALSE, // HardwareFlowControl; 87a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni NULL, // *ControllerNameTable; 88a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni FALSE, // ContainsControllerNode; 89a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 0, // Instance; 90a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni NULL // *PciDeviceInfo; 91a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni}; 92a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 93a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni/** 94a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Check the device path node whether it's the Flow Control node or not. 95a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 96a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param[in] FlowControl The device path node to be checked. 97a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 98a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @retval TRUE It's the Flow Control node. 99a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @retval FALSE It's not. 100a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 101a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni**/ 102a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiBOOLEAN 103a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiIsUartFlowControlDevicePathNode ( 104a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IN UART_FLOW_CONTROL_DEVICE_PATH *FlowControl 105a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ) 106a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni{ 107a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni return (BOOLEAN) ( 108a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (DevicePathType (FlowControl) == MESSAGING_DEVICE_PATH) && 109a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (DevicePathSubType (FlowControl) == MSG_VENDOR_DP) && 110a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (CompareGuid (&FlowControl->Guid, &gEfiUartDevicePathGuid)) 111a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 112a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni} 113a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 114a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni/** 115a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni The user Entry Point for module PciSioSerial. The user code starts with this function. 116a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 117a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param[in] ImageHandle The firmware allocated handle for the EFI image. 118a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param[in] SystemTable A pointer to the EFI System Table. 119a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 120a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @retval EFI_SUCCESS The entry point is executed successfully. 121a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @retval other Some error occurs when executing this entry point. 122a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 123a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni**/ 124a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiEFI_STATUS 125a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiEFIAPI 126a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiInitializePciSioSerial ( 127a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IN EFI_HANDLE ImageHandle, 128a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IN EFI_SYSTEM_TABLE *SystemTable 129a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ) 130a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni{ 131a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_STATUS Status; 132a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 133a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 134a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Install driver model protocol(s). 135a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 136a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = EfiLibInstallDriverBindingComponentName2 ( 137a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ImageHandle, 138a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SystemTable, 139a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &gSerialControllerDriver, 140a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ImageHandle, 141a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &gPciSioSerialComponentName, 142a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &gPciSioSerialComponentName2 143a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 144a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ASSERT_EFI_ERROR (Status); 145a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 146a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 147a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Initialize UART default setting in gSerialDevTempate 148a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 149a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gSerialDevTemplate.SerialMode.BaudRate = PcdGet64 (PcdUartDefaultBaudRate); 150a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gSerialDevTemplate.SerialMode.DataBits = PcdGet8 (PcdUartDefaultDataBits); 151a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gSerialDevTemplate.SerialMode.Parity = PcdGet8 (PcdUartDefaultParity); 152a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gSerialDevTemplate.SerialMode.StopBits = PcdGet8 (PcdUartDefaultStopBits); 153a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gSerialDevTemplate.UartDevicePath.BaudRate = PcdGet64 (PcdUartDefaultBaudRate); 154a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gSerialDevTemplate.UartDevicePath.DataBits = PcdGet8 (PcdUartDefaultDataBits); 155a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gSerialDevTemplate.UartDevicePath.Parity = PcdGet8 (PcdUartDefaultParity); 156a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gSerialDevTemplate.UartDevicePath.StopBits = PcdGet8 (PcdUartDefaultStopBits); 157a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gSerialDevTemplate.ClockRate = PcdGet32 (PcdSerialClockRate); 158a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 159a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni return Status; 160a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni} 161a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 162a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni/** 163a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Return whether the controller is a SIO serial controller. 164a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 165a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param Controller The controller handle. 166a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 167a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @retval EFI_SUCCESS The controller is a SIO serial controller. 168a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @retval others The controller is not a SIO serial controller. 169a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni**/ 170a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiEFI_STATUS 171a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiIsSioSerialController ( 172a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_HANDLE Controller 173a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ) 174a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni{ 175a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_STATUS Status; 176a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_SIO_PROTOCOL *Sio; 177a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_DEVICE_PATH_PROTOCOL *DevicePath; 178a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ACPI_HID_DEVICE_PATH *Acpi; 179a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 180a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 181a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Open the IO Abstraction(s) needed to perform the supported test 182a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 183a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = gBS->OpenProtocol ( 184a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 185a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &gEfiSioProtocolGuid, 186a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (VOID **) &Sio, 187a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gSerialControllerDriver.DriverBindingHandle, 188a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 189a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_OPEN_PROTOCOL_BY_DRIVER 190a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 191a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (Status == EFI_ALREADY_STARTED) { 192a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni return EFI_SUCCESS; 193a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 194a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 195a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (!EFI_ERROR (Status)) { 196a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 197a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Close the I/O Abstraction(s) used to perform the supported test 198a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 199a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gBS->CloseProtocol ( 200a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 201a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &gEfiSioProtocolGuid, 202a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gSerialControllerDriver.DriverBindingHandle, 203a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller 204a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 205a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 206a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = gBS->OpenProtocol ( 207a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 208a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &gEfiDevicePathProtocolGuid, 209a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (VOID **) &DevicePath, 210a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gSerialControllerDriver.DriverBindingHandle, 211a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 212a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_OPEN_PROTOCOL_BY_DRIVER 213a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 214a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ASSERT (Status != EFI_ALREADY_STARTED); 215a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 216a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (!EFI_ERROR (Status)) { 217a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni do { 218a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Acpi = (ACPI_HID_DEVICE_PATH *) DevicePath; 219a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni DevicePath = NextDevicePathNode (DevicePath); 220a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } while (!IsDevicePathEnd (DevicePath)); 221a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 222a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (DevicePathType (Acpi) != ACPI_DEVICE_PATH || 223a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (DevicePathSubType (Acpi) != ACPI_DP && DevicePathSubType (Acpi) != ACPI_EXTENDED_DP) || 224a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Acpi->HID != EISA_PNP_ID (0x501) 225a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ) { 226a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = EFI_UNSUPPORTED; 227a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 228a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 229a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 230a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 231a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Close protocol, don't use device path protocol in the Support() function 232a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 233a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gBS->CloseProtocol ( 234a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 235a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &gEfiDevicePathProtocolGuid, 236a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gSerialControllerDriver.DriverBindingHandle, 237a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller 238a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 239a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 240a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni return Status; 241a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni} 242a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 243a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni/** 244a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Return whether the controller is a PCI serial controller. 245a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 246a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param Controller The controller handle. 247a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 248a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @retval EFI_SUCCESS The controller is a PCI serial controller. 249a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @retval others The controller is not a PCI serial controller. 250a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni**/ 251a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiEFI_STATUS 252a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiIsPciSerialController ( 253a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_HANDLE Controller 254a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ) 255a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni{ 256a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_STATUS Status; 257a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_PCI_IO_PROTOCOL *PciIo; 258a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_DEVICE_PATH_PROTOCOL *DevicePath; 259a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PCI_TYPE00 Pci; 260a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PCI_SERIAL_PARAMETER *PciSerialParameter; 261a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 262a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 263a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Open the IO Abstraction(s) needed to perform the supported test 264a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 265a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = gBS->OpenProtocol ( 266a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 267a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &gEfiPciIoProtocolGuid, 268a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (VOID **) &PciIo, 269a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gSerialControllerDriver.DriverBindingHandle, 270a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 271a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_OPEN_PROTOCOL_BY_DRIVER 272a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 273a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (Status == EFI_ALREADY_STARTED) { 274a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni return EFI_SUCCESS; 275a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 276a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 277a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (!EFI_ERROR (Status)) { 278a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0, sizeof (Pci), &Pci); 279a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (!EFI_ERROR (Status)) { 280a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (!IS_PCI_16550_SERIAL (&Pci)) { 281a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni for (PciSerialParameter = (PCI_SERIAL_PARAMETER *) PcdGetPtr (PcdPciSerialParameters) 282a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ; PciSerialParameter->VendorId != 0xFFFF 283a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ; PciSerialParameter++ 284a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ) { 285a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if ((Pci.Hdr.VendorId == PciSerialParameter->VendorId) && 286a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (Pci.Hdr.DeviceId == PciSerialParameter->DeviceId) 287a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ) { 288a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni break; 289a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 290a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 291a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (PciSerialParameter->VendorId == 0xFFFF) { 292a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = EFI_UNSUPPORTED; 293a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } else { 294a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = EFI_SUCCESS; 295a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 296a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 297a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 298a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 299a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 300a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Close the I/O Abstraction(s) used to perform the supported test 301a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 302a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gBS->CloseProtocol ( 303a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 304a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &gEfiPciIoProtocolGuid, 305a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gSerialControllerDriver.DriverBindingHandle, 306a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller 307a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 308a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 309a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (EFI_ERROR (Status)) { 310a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni return Status; 311a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 312a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 313a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 314a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Open the EFI Device Path protocol needed to perform the supported test 315a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 316a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = gBS->OpenProtocol ( 317a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 318a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &gEfiDevicePathProtocolGuid, 319a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (VOID **) &DevicePath, 320a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gSerialControllerDriver.DriverBindingHandle, 321a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 322a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_OPEN_PROTOCOL_BY_DRIVER 323a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 324a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ASSERT (Status != EFI_ALREADY_STARTED); 325a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 326a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 327a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Close protocol, don't use device path protocol in the Support() function 328a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 329a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gBS->CloseProtocol ( 330a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 331a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &gEfiDevicePathProtocolGuid, 332a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gSerialControllerDriver.DriverBindingHandle, 333a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller 334a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 335a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 336a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni return Status; 337a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni} 338a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 339a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni/** 340a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Check to see if this driver supports the given controller 341a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 342a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. 343a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param Controller The handle of the controller to test. 344a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param RemainingDevicePath A pointer to the remaining portion of a device path. 345a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 346a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @return EFI_SUCCESS This driver can support the given controller 347a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 348a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni**/ 349a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiEFI_STATUS 350a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiEFIAPI 351a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiSerialControllerDriverSupported ( 352a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IN EFI_DRIVER_BINDING_PROTOCOL *This, 353a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IN EFI_HANDLE Controller, 354a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 355a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ) 356a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 357a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni{ 358a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_STATUS Status; 359a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni UART_DEVICE_PATH *Uart; 360a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni UART_FLOW_CONTROL_DEVICE_PATH *FlowControl; 361a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 362a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 363a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Test RemainingDevicePath 364a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 365a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if ((RemainingDevicePath != NULL) && !IsDevicePathEnd (RemainingDevicePath)) { 366a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = EFI_UNSUPPORTED; 367a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 368a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Uart = SkipControllerDevicePathNode (RemainingDevicePath, NULL, NULL); 369a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (DevicePathType (Uart) != MESSAGING_DEVICE_PATH || 370a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni DevicePathSubType (Uart) != MSG_UART_DP || 371a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni DevicePathNodeLength (Uart) != sizeof (UART_DEVICE_PATH) 372a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ) { 373a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni return EFI_UNSUPPORTED; 374a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 375a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 376a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 377a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Do a rough check because Clock Rate is unknown until DriverBindingStart() 378a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 379a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (!VerifyUartParameters (0, Uart->BaudRate, Uart->DataBits, Uart->Parity, Uart->StopBits, NULL, NULL)) { 380a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni return EFI_UNSUPPORTED; 381a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 382a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 383a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Uart); 384a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (IsUartFlowControlDevicePathNode (FlowControl)) { 385a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 386a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // If the second node is Flow Control Node, 387a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // return error when it request other than hardware flow control. 388a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 389a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if ((ReadUnaligned32 (&FlowControl->FlowControlMap) & ~UART_FLOW_CONTROL_HARDWARE) != 0) { 390a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni return EFI_UNSUPPORTED; 391a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 392a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 393a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 394a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 395a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = IsSioSerialController (Controller); 396a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (EFI_ERROR (Status)) { 397a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = IsPciSerialController (Controller); 398a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 399a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni return Status; 400a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni} 401a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 402a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni/** 403a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Create the child serial device instance. 404a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 405a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param Controller The parent controller handle. 406a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param Uart Pointer to the UART device path node in RemainingDevicePath, 407a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni or NULL if RemainingDevicePath is NULL. 408a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param ParentDevicePath Pointer to the parent device path. 409a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param CreateControllerNode TRUE to create the controller node. 410a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param Instance Instance number of the serial device. 411a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni The value will be set to the controller node 412a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if CreateControllerNode is TRUE. 413a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param ParentIo A union type pointer to either Sio or PciIo. 414a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param PciSerialParameter The PCI serial parameter to be used by current serial device. 415a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni NULL for SIO serial device. 416a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param PciDeviceInfo The PCI device info for the current serial device. 417a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni NULL for SIO serial device. 418a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 419a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @retval EFI_SUCCESS The serial device was created successfully. 420a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @retval others The serial device wasn't created. 421a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni**/ 422a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiEFI_STATUS 423a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiCreateSerialDevice ( 424a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IN EFI_HANDLE Controller, 425a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IN UART_DEVICE_PATH *Uart, 426a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, 427a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IN BOOLEAN CreateControllerNode, 428a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IN UINT32 Instance, 429a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IN PARENT_IO_PROTOCOL_PTR ParentIo, 430a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IN PCI_SERIAL_PARAMETER *PciSerialParameter, OPTIONAL 431a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IN PCI_DEVICE_INFO *PciDeviceInfo OPTIONAL 432a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ) 433a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni{ 434a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_STATUS Status; 435a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SERIAL_DEV *SerialDevice; 436a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni UINT8 BarIndex; 437a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni UINT64 Offset; 438a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni UART_FLOW_CONTROL_DEVICE_PATH *FlowControl; 439a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni UINT32 FlowControlMap; 440a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ACPI_RESOURCE_HEADER_PTR Resources; 441a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_ACPI_IO_PORT_DESCRIPTOR *Io; 442a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR *FixedIo; 443a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *AddressSpace; 444a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; 445a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 446a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni BarIndex = 0; 447a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Offset = 0; 448a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni FlowControl = NULL; 449a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni FlowControlMap = 0; 450a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 451a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 452a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Initialize the serial device instance 453a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 454a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice = AllocateCopyPool (sizeof (SERIAL_DEV), &gSerialDevTemplate); 455a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ASSERT (SerialDevice != NULL); 456a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 457a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->SerialIo.Mode = &(SerialDevice->SerialMode); 458a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->ParentDevicePath = ParentDevicePath; 459a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->PciDeviceInfo = PciDeviceInfo; 460a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->Instance = Instance; 461a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 462a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (Uart != NULL) { 463a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni CopyMem (&SerialDevice->UartDevicePath, Uart, sizeof (UART_DEVICE_PATH)); 464a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Uart); 465a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (IsUartFlowControlDevicePathNode (FlowControl)) { 466a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni FlowControlMap = ReadUnaligned32 (&FlowControl->FlowControlMap); 467a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } else { 468a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni FlowControl = NULL; 469a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 470a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 471a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 472a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 473a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // For PCI serial device, use the information from PCD 474a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 475a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (PciSerialParameter != NULL) { 476a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni BarIndex = (PciSerialParameter->BarIndex == PCI_BAR_ALL) ? 0 : PciSerialParameter->BarIndex; 477a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Offset = PciSerialParameter->Offset; 478a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (PciSerialParameter->RegisterStride != 0) { 479a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->RegisterStride = PciSerialParameter->RegisterStride; 480a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 481a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (PciSerialParameter->ClockRate != 0) { 482a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->ClockRate = PciSerialParameter->ClockRate; 483a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 484a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (PciSerialParameter->ReceiveFifoDepth != 0) { 485a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->ReceiveFifoDepth = PciSerialParameter->ReceiveFifoDepth; 486a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 487a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (PciSerialParameter->TransmitFifoDepth != 0) { 488a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->TransmitFifoDepth = PciSerialParameter->TransmitFifoDepth; 489a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 490a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 491a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 492a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 493a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Pass NULL ActualBaudRate to VerifyUartParameters to disallow baudrate degrade. 494a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // DriverBindingStart() shouldn't create a handle with different UART device path. 495a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 496a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (!VerifyUartParameters (SerialDevice->ClockRate, SerialDevice->UartDevicePath.BaudRate, SerialDevice->UartDevicePath.DataBits, 497a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->UartDevicePath.Parity, SerialDevice->UartDevicePath.StopBits, NULL, NULL 498a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni )) { 499a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = EFI_INVALID_PARAMETER; 500a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni goto CreateError; 501a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 502a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 503a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (PciSerialParameter == NULL) { 504a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = ParentIo.Sio->GetResources (ParentIo.Sio, &Resources); 505a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } else { 506a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = ParentIo.PciIo->GetBarAttributes (ParentIo.PciIo, BarIndex, NULL, (VOID **) &Resources); 507a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 508a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 509a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (!EFI_ERROR (Status)) { 510a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 511a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Get the base address information from ACPI resource descriptor. 512a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // ACPI_IO_PORT_DESCRIPTOR and ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR are returned from Sio; 513a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // ACPI_ADDRESS_SPACE_DESCRIPTOR is returned from PciIo. 514a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 515a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni while ((Resources.SmallHeader->Byte != ACPI_END_TAG_DESCRIPTOR) && (SerialDevice->BaseAddress == 0)) { 516a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni switch (Resources.SmallHeader->Byte) { 517a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni case ACPI_IO_PORT_DESCRIPTOR: 518a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Io = (EFI_ACPI_IO_PORT_DESCRIPTOR *) Resources.SmallHeader; 519a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (Io->Length != 0) { 520a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->BaseAddress = Io->BaseAddressMin; 521a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 522a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni break; 523a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 524a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni case ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR: 525a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni FixedIo = (EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR *) Resources.SmallHeader; 526a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (FixedIo->Length != 0) { 527a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->BaseAddress = FixedIo->BaseAddress; 528a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 529a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni break; 530a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 531a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni case ACPI_ADDRESS_SPACE_DESCRIPTOR: 532a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni AddressSpace = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Resources.SmallHeader; 533a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (AddressSpace->AddrLen != 0) { 534a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (AddressSpace->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) { 535a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->MmioAccess = TRUE; 536a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 537a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->BaseAddress = AddressSpace->AddrRangeMin + Offset; 538a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 539a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni break; 540a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 541a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 542a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (Resources.SmallHeader->Bits.Type == 0) { 543a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Resources.SmallHeader = (ACPI_SMALL_RESOURCE_HEADER *) ((UINT8 *) Resources.SmallHeader 544a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni + Resources.SmallHeader->Bits.Length 545a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni + sizeof (*Resources.SmallHeader)); 546a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } else { 547a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Resources.LargeHeader = (ACPI_LARGE_RESOURCE_HEADER *) ((UINT8 *) Resources.LargeHeader 548a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni + Resources.LargeHeader->Length 549a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni + sizeof (*Resources.LargeHeader)); 550a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 551a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 552a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 553a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 554a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (SerialDevice->BaseAddress == 0) { 555a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = EFI_INVALID_PARAMETER; 556a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni goto CreateError; 557a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 558a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 559a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->HardwareFlowControl = (BOOLEAN) (FlowControlMap == UART_FLOW_CONTROL_HARDWARE); 560a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 561a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 562a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Report status code the serial present 563a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 564a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni REPORT_STATUS_CODE_WITH_DEVICE_PATH ( 565a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_PROGRESS_CODE, 566a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_P_PC_PRESENCE_DETECT | EFI_PERIPHERAL_SERIAL_PORT, 567a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->ParentDevicePath 568a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 569a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 570a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (!SerialPresent (SerialDevice)) { 571a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = EFI_DEVICE_ERROR; 572a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni REPORT_STATUS_CODE_WITH_DEVICE_PATH ( 573a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_ERROR_CODE, 574a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_P_EC_NOT_DETECTED | EFI_PERIPHERAL_SERIAL_PORT, 575a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->ParentDevicePath 576a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 577a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni goto CreateError; 578a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 579a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 580a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 581a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 1. Append Controller device path node. 582a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 583a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (CreateControllerNode) { 584a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni mControllerDevicePathTemplate.ControllerNumber = SerialDevice->Instance; 585a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->DevicePath = AppendDevicePathNode ( 586a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->ParentDevicePath, 587a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (EFI_DEVICE_PATH_PROTOCOL *) &mControllerDevicePathTemplate 588a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 589a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->ContainsControllerNode = TRUE; 590a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 591a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 592a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 593a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 2. Append UART device path node. 594a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // The Uart setings are zero here. 595a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // SetAttribute() will update them to match the default setings. 596a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 597a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni TempDevicePath = SerialDevice->DevicePath; 598a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (TempDevicePath != NULL) { 599a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->DevicePath = AppendDevicePathNode ( 600a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni TempDevicePath, 601a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (EFI_DEVICE_PATH_PROTOCOL *) &SerialDevice->UartDevicePath 602a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 603a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni FreePool (TempDevicePath); 604a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } else { 605a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->DevicePath = AppendDevicePathNode ( 606a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->ParentDevicePath, 607a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (EFI_DEVICE_PATH_PROTOCOL *) &SerialDevice->UartDevicePath 608a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 609a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 610a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 611a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 3. Append the Flow Control device path node. 612a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Only produce the Flow Control node when remaining device path has it 613a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 614a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (FlowControl != NULL) { 615a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni TempDevicePath = SerialDevice->DevicePath; 616a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (TempDevicePath != NULL) { 617a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->DevicePath = AppendDevicePathNode ( 618a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni TempDevicePath, 619a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (EFI_DEVICE_PATH_PROTOCOL *) FlowControl 620a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 621a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni FreePool (TempDevicePath); 622a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 623a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 624a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ASSERT (SerialDevice->DevicePath != NULL); 625a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 626a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 627a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults. 628a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 629a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->SerialMode.BaudRate = SerialDevice->UartDevicePath.BaudRate; 630a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->SerialMode.DataBits = SerialDevice->UartDevicePath.DataBits; 631a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->SerialMode.Parity = SerialDevice->UartDevicePath.Parity; 632a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->SerialMode.StopBits = SerialDevice->UartDevicePath.StopBits; 633a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 634a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 635a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Issue a reset to initialize the COM port 636a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 637a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = SerialDevice->SerialIo.Reset (&SerialDevice->SerialIo); 638a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (EFI_ERROR (Status)) { 639a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni REPORT_STATUS_CODE_WITH_DEVICE_PATH ( 640a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_ERROR_CODE, 641a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_P_EC_CONTROLLER_ERROR | EFI_PERIPHERAL_SERIAL_PORT, 642a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->DevicePath 643a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 644a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni goto CreateError; 645a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 646a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 647a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni AddName (SerialDevice, Instance); 648a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 649a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Install protocol interfaces for the serial device. 650a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 651a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = gBS->InstallMultipleProtocolInterfaces ( 652a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &SerialDevice->Handle, 653a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &gEfiDevicePathProtocolGuid, SerialDevice->DevicePath, 654a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &gEfiSerialIoProtocolGuid, &SerialDevice->SerialIo, 655a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni NULL 656a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 657a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (EFI_ERROR (Status)) { 658a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni goto CreateError; 659a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 660a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 661a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Open For Child Device 662a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 663a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = gBS->OpenProtocol ( 664a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 665a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PciSerialParameter != NULL ? &gEfiPciIoProtocolGuid : &gEfiSioProtocolGuid, 666a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (VOID **) &ParentIo, 667a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gSerialControllerDriver.DriverBindingHandle, 668a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice->Handle, 669a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 670a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 671a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 672a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (EFI_ERROR (Status)) { 673a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gBS->UninstallMultipleProtocolInterfaces ( 674a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &SerialDevice->Handle, 675a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &gEfiDevicePathProtocolGuid, SerialDevice->DevicePath, 676a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &gEfiSerialIoProtocolGuid, &SerialDevice->SerialIo, 677a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni NULL 678a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 679a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 680a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 681a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiCreateError: 682a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (EFI_ERROR (Status)) { 683a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (SerialDevice->DevicePath != NULL) { 684a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni FreePool (SerialDevice->DevicePath); 685a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 686a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (SerialDevice->ControllerNameTable != NULL) { 687a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni FreeUnicodeStringTable (SerialDevice->ControllerNameTable); 688a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 689a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni FreePool (SerialDevice); 690a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 691a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni return Status; 692a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni} 693a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 694a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni/** 695a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Returns an array of pointers containing all the child serial device pointers. 696a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 697a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param Controller The parent controller handle. 698a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param IoProtocolGuid The protocol GUID, either equals to gEfiSioProtocolGuid 699a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni or equals to gEfiPciIoProtocolGuid. 700a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param Count Count of the serial devices. 701a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 702a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @return An array of pointers containing all the child serial device pointers. 703a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni**/ 704a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiSERIAL_DEV ** 705a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiGetChildSerialDevices ( 706a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IN EFI_HANDLE Controller, 707a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IN EFI_GUID *IoProtocolGuid, 708a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni OUT UINTN *Count 709a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ) 710a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni{ 711a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_STATUS Status; 712a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni UINTN Index; 713a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; 714a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni UINTN EntryCount; 715a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SERIAL_DEV **SerialDevices; 716a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_SERIAL_IO_PROTOCOL *SerialIo; 717a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni BOOLEAN OpenByDriver; 718a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 719a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni *Count = 0; 720a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 721a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // If the SerialIo instance specified by RemainingDevicePath is already created, 722a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // update the attributes/control. 723a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 724a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = gBS->OpenProtocolInformation ( 725a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 726a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IoProtocolGuid, 727a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &OpenInfoBuffer, 728a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &EntryCount 729a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 730a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (EFI_ERROR (Status)) { 731a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni return NULL; 732a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 733a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 734a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevices = AllocatePool (EntryCount * sizeof (SERIAL_DEV *)); 735a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ASSERT (SerialDevices != NULL); 736a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 737a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni *Count = 0; 738a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni OpenByDriver = FALSE; 739a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni for (Index = 0; Index < EntryCount; Index++) { 740a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { 741a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = gBS->OpenProtocol ( 742a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni OpenInfoBuffer[Index].ControllerHandle, 743a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &gEfiSerialIoProtocolGuid, 744a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (VOID **) &SerialIo, 745a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gSerialControllerDriver.DriverBindingHandle, 746a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 747a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_OPEN_PROTOCOL_GET_PROTOCOL 748a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 749a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (!EFI_ERROR (Status)) { 750a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevices[(*Count)++] = SERIAL_DEV_FROM_THIS (SerialIo); 751a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 752a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 753a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 754a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 755a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) { 756a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ASSERT (OpenInfoBuffer[Index].AgentHandle == gSerialControllerDriver.DriverBindingHandle); 757a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni OpenByDriver = TRUE; 758a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 759a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 760a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (OpenInfoBuffer != NULL) { 761a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni FreePool (OpenInfoBuffer); 762a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 763a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 764a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ASSERT ((*Count == 0) || (OpenByDriver)); 765a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 766a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni return SerialDevices; 767a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni} 768a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 769a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni/** 770a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Start to management the controller passed in 771a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 772a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. 773a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param Controller The handle of the controller to test. 774a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param RemainingDevicePath A pointer to the remaining portion of a device path. 775a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 776a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @return EFI_SUCCESS Driver is started successfully 777a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni**/ 778a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiEFI_STATUS 779a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiEFIAPI 780a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiSerialControllerDriverStart ( 781a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IN EFI_DRIVER_BINDING_PROTOCOL *This, 782a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IN EFI_HANDLE Controller, 783a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 784a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ) 785a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni{ 786a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_STATUS Status; 787a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni UINTN Index; 788a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; 789a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_DEVICE_PATH_PROTOCOL *Node; 790a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_SERIAL_IO_PROTOCOL *SerialIo; 791a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni UINT32 ControllerNumber; 792a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni UART_DEVICE_PATH *Uart; 793a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni UART_FLOW_CONTROL_DEVICE_PATH *FlowControl; 794a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni UINT32 Control; 795a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PARENT_IO_PROTOCOL_PTR ParentIo; 796a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ACPI_HID_DEVICE_PATH *Acpi; 797a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_GUID *IoProtocolGuid; 798a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PCI_SERIAL_PARAMETER *PciSerialParameter; 799a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PCI_SERIAL_PARAMETER DefaultPciSerialParameter; 800a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PCI_TYPE00 Pci; 801a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni UINT32 PciSerialCount; 802a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SERIAL_DEV **SerialDevices; 803a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni UINTN SerialDeviceCount; 804a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PCI_DEVICE_INFO *PciDeviceInfo; 805a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni UINT64 Supports; 806a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni BOOLEAN ContainsControllerNode; 807a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 808a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 809a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Get the Parent Device Path 810a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 811a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = gBS->OpenProtocol ( 812a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 813a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &gEfiDevicePathProtocolGuid, 814a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (VOID **) &ParentDevicePath, 815a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni This->DriverBindingHandle, 816a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 817a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_OPEN_PROTOCOL_BY_DRIVER 818a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 819a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { 820a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni return Status; 821a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 822a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 823a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Report status code enable the serial 824a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 825a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni REPORT_STATUS_CODE_WITH_DEVICE_PATH ( 826a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_PROGRESS_CODE, 827a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_P_PC_ENABLE | EFI_PERIPHERAL_SERIAL_PORT, 828a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ParentDevicePath 829a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 830a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 831a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 832a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Grab the IO abstraction we need to get any work done 833a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 834a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IoProtocolGuid = &gEfiSioProtocolGuid; 835a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = gBS->OpenProtocol ( 836a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 837a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IoProtocolGuid, 838a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (VOID **) &ParentIo, 839a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni This->DriverBindingHandle, 840a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 841a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_OPEN_PROTOCOL_BY_DRIVER 842a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 843a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { 844a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IoProtocolGuid = &gEfiPciIoProtocolGuid; 845a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = gBS->OpenProtocol ( 846a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 847a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IoProtocolGuid, 848a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (VOID **) &ParentIo, 849a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni This->DriverBindingHandle, 850a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 851a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_OPEN_PROTOCOL_BY_DRIVER 852a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 853a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 854a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ASSERT (!EFI_ERROR (Status) || Status == EFI_ALREADY_STARTED); 855a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 856a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 857a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Do nothing for END device path node 858a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 859a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if ((RemainingDevicePath != NULL) && IsDevicePathEnd (RemainingDevicePath)) { 860a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni return EFI_SUCCESS; 861a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 862a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 86383809dc0186eea34a9b0db6df306abe9e1c7776bMichael Kinney ControllerNumber = 0; 86483809dc0186eea34a9b0db6df306abe9e1c7776bMichael Kinney ContainsControllerNode = FALSE; 865a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevices = GetChildSerialDevices (Controller, IoProtocolGuid, &SerialDeviceCount); 866a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 867a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // If the SerialIo instance specified by RemainingDevicePath is already created, 868a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // update the attributes/control. 869a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 870a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if ((SerialDeviceCount != 0) && (RemainingDevicePath != NULL)) { 871a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Uart = (UART_DEVICE_PATH *) SkipControllerDevicePathNode (RemainingDevicePath, &ContainsControllerNode, &ControllerNumber); 872a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni for (Index = 0; Index < SerialDeviceCount; Index++) { 87312f5ff97f6c1f87370213a00d0b36e8208beacf9Feng Tian ASSERT ((SerialDevices != NULL) && (SerialDevices[Index] != NULL)); 874a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if ((!SerialDevices[Index]->ContainsControllerNode && !ContainsControllerNode) || 875a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (SerialDevices[Index]->ContainsControllerNode && ContainsControllerNode && SerialDevices[Index]->Instance == ControllerNumber) 876a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ) { 87783809dc0186eea34a9b0db6df306abe9e1c7776bMichael Kinney SerialIo = &SerialDevices[Index]->SerialIo; 878a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = EFI_INVALID_PARAMETER; 879a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 880a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Pass NULL ActualBaudRate to VerifyUartParameters to disallow baudrate degrade. 881a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // DriverBindingStart() shouldn't create a handle with different UART device path. 882a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 883a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (VerifyUartParameters (SerialDevices[Index]->ClockRate, Uart->BaudRate, Uart->DataBits, 884a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (EFI_PARITY_TYPE) Uart->Parity, (EFI_STOP_BITS_TYPE) Uart->StopBits, NULL, NULL)) { 885a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = SerialIo->SetAttributes ( 886a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialIo, 887a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Uart->BaudRate, 888a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialIo->Mode->ReceiveFifoDepth, 889a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialIo->Mode->Timeout, 890a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (EFI_PARITY_TYPE) Uart->Parity, 891a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Uart->DataBits, 892a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (EFI_STOP_BITS_TYPE) Uart->StopBits 893a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 894a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 895a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Uart); 896a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (!EFI_ERROR (Status) && IsUartFlowControlDevicePathNode (FlowControl)) { 897a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = SerialIo->GetControl (SerialIo, &Control); 898a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (!EFI_ERROR (Status)) { 899a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (ReadUnaligned32 (&FlowControl->FlowControlMap) == UART_FLOW_CONTROL_HARDWARE) { 900a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; 901a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } else { 902a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Control &= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; 903a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 904a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 905a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Clear the bits that are not allowed to pass to SetControl 906a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 907a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Control &= (EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY | 908a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE | 909a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE); 910a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = SerialIo->SetControl (SerialIo, Control); 911a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 912a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 913a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni break; 914a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 915a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 916a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (Index != SerialDeviceCount) { 917a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 918a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Directly return if the SerialIo instance specified by RemainingDevicePath is found and updated. 919a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Otherwise continue to create the instance specified by RemainingDevicePath. 920a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 921a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (SerialDevices != NULL) { 922a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni FreePool (SerialDevices); 923a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 924a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni return Status; 925a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 926a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 927a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 928a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (RemainingDevicePath != NULL) { 929a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Uart = (UART_DEVICE_PATH *) SkipControllerDevicePathNode (RemainingDevicePath, &ContainsControllerNode, &ControllerNumber); 930a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } else { 931a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Uart = NULL; 932a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 933a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 934a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PciDeviceInfo = NULL; 935a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (IoProtocolGuid == &gEfiSioProtocolGuid) { 936a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = EFI_NOT_FOUND; 937a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (RemainingDevicePath == NULL || !ContainsControllerNode) { 938a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Node = ParentDevicePath; 939a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni do { 940a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Acpi = (ACPI_HID_DEVICE_PATH *) Node; 941a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Node = NextDevicePathNode (Node); 942a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } while (!IsDevicePathEnd (Node)); 943a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = CreateSerialDevice (Controller, Uart, ParentDevicePath, FALSE, Acpi->UID, ParentIo, NULL, NULL); 944a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni DEBUG ((EFI_D_INFO, "PciSioSerial: Create SIO child serial device - %r\n", Status)); 945a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 946a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } else { 947a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = ParentIo.PciIo->Pci.Read (ParentIo.PciIo, EfiPciIoWidthUint8, 0, sizeof (Pci), &Pci); 948a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (!EFI_ERROR (Status)) { 949a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 950a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // PcdPciSerialParameters takes the higher priority. 951a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 952a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PciSerialCount = 0; 953a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni for (PciSerialParameter = PcdGetPtr (PcdPciSerialParameters); PciSerialParameter->VendorId != 0xFFFF; PciSerialParameter++) { 954a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if ((PciSerialParameter->VendorId == Pci.Hdr.VendorId) && 955a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (PciSerialParameter->DeviceId == Pci.Hdr.DeviceId) 956a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ) { 957a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PciSerialCount++; 958a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 959a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 960a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 961a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (SerialDeviceCount == 0) { 962a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 963a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Enable the IO & MEM decoding when creating the first child. 964a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Restore the PCI attributes when all children is destroyed (PciDeviceInfo->ChildCount == 0). 965a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 966a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PciDeviceInfo = AllocatePool (sizeof (PCI_DEVICE_INFO)); 96712f5ff97f6c1f87370213a00d0b36e8208beacf9Feng Tian ASSERT (PciDeviceInfo != NULL); 968a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PciDeviceInfo->ChildCount = 0; 969a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PciDeviceInfo->PciIo = ParentIo.PciIo; 970a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = ParentIo.PciIo->Attributes ( 971a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ParentIo.PciIo, 972a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EfiPciIoAttributeOperationGet, 973a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 0, 974a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &PciDeviceInfo->PciAttributes 975a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 976a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 977a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (!EFI_ERROR (Status)) { 978a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = ParentIo.PciIo->Attributes ( 979a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ParentIo.PciIo, 980a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EfiPciIoAttributeOperationSupported, 981a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 0, 982a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &Supports 983a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 984a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (!EFI_ERROR (Status)) { 985d14198b3397d85da37d8a9f81cf233ce08c7758aFeng Tian Supports &= (UINT64)(EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY); 986a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = ParentIo.PciIo->Attributes ( 987a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ParentIo.PciIo, 988a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EfiPciIoAttributeOperationEnable, 989a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Supports, 990a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni NULL 991a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 992a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 993a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 994a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } else { 995a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 996a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Re-use the PciDeviceInfo stored in existing children. 997a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 99812f5ff97f6c1f87370213a00d0b36e8208beacf9Feng Tian ASSERT ((SerialDevices != NULL) && (SerialDevices[0] != NULL)); 999a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PciDeviceInfo = SerialDevices[0]->PciDeviceInfo; 1000a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ASSERT (PciDeviceInfo != NULL); 1001a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 1002a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1003a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = EFI_NOT_FOUND; 1004a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (PciSerialCount <= 1) { 1005a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 1006a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // PCI serial device contains only one UART 1007a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 1008a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (RemainingDevicePath == NULL || !ContainsControllerNode) { 1009a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 1010a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // This PCI serial device is matched by class code in Supported() 1011a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 1012a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (PciSerialCount == 0) { 1013a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni DefaultPciSerialParameter.VendorId = Pci.Hdr.VendorId; 1014a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni DefaultPciSerialParameter.DeviceId = Pci.Hdr.DeviceId; 1015a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni DefaultPciSerialParameter.BarIndex = 0; 1016a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni DefaultPciSerialParameter.Offset = 0; 1017a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni DefaultPciSerialParameter.RegisterStride = 0; 1018a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni DefaultPciSerialParameter.ClockRate = 0; 1019a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PciSerialParameter = &DefaultPciSerialParameter; 1020a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } else if (PciSerialCount == 1) { 1021a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PciSerialParameter = PcdGetPtr (PcdPciSerialParameters); 1022a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 1023a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1024a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = CreateSerialDevice (Controller, Uart, ParentDevicePath, FALSE, 0, ParentIo, PciSerialParameter, PciDeviceInfo); 1025a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni DEBUG ((EFI_D_INFO, "PciSioSerial: Create PCI child serial device (single) - %r\n", Status)); 1026a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (!EFI_ERROR (Status)) { 1027a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PciDeviceInfo->ChildCount++; 1028a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 1029a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 1030a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } else { 1031a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 1032a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // PCI serial device contains multiple UARTs 1033a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 1034a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (RemainingDevicePath == NULL || ContainsControllerNode) { 1035a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PciSerialCount = 0; 1036a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni for (PciSerialParameter = PcdGetPtr (PcdPciSerialParameters); PciSerialParameter->VendorId != 0xFFFF; PciSerialParameter++) { 1037a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if ((PciSerialParameter->VendorId == Pci.Hdr.VendorId) && 1038a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (PciSerialParameter->DeviceId == Pci.Hdr.DeviceId) && 1039a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ((RemainingDevicePath == NULL) || (ControllerNumber == PciSerialCount)) 1040a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ) { 1041a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 1042a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Create controller node when PCI serial device contains multiple UARTs 1043a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 1044a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = CreateSerialDevice (Controller, Uart, ParentDevicePath, TRUE, PciSerialCount, ParentIo, PciSerialParameter, PciDeviceInfo); 1045a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PciSerialCount++; 1046a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni DEBUG ((EFI_D_INFO, "PciSioSerial: Create PCI child serial device (multiple) - %r\n", Status)); 1047a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (!EFI_ERROR (Status)) { 1048a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PciDeviceInfo->ChildCount++; 1049a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 1050a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 1051a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 1052a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 1053a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 1054a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 1055a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 1056a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1057a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (SerialDevices != NULL) { 1058a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni FreePool (SerialDevices); 1059a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 1060a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1061a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 1062a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // For multiple PCI serial devices, set Status to SUCCESS if one child is created successfully 1063a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 1064a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if ((PciDeviceInfo != NULL) && (PciDeviceInfo->ChildCount != 0)) { 1065a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = EFI_SUCCESS; 1066a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 1067a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1068a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (EFI_ERROR (Status) && (SerialDeviceCount == 0)) { 1069a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (PciDeviceInfo != NULL) { 1070a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = ParentIo.PciIo->Attributes ( 1071a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ParentIo.PciIo, 1072a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EfiPciIoAttributeOperationSet, 1073a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PciDeviceInfo->PciAttributes, 1074a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni NULL 1075a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 1076a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ASSERT_EFI_ERROR (Status); 1077a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni FreePool (PciDeviceInfo); 1078a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 1079a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gBS->CloseProtocol ( 1080a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 1081a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &gEfiDevicePathProtocolGuid, 1082a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni This->DriverBindingHandle, 1083a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller 1084a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 1085a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gBS->CloseProtocol ( 1086a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 1087a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IoProtocolGuid, 1088a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni This->DriverBindingHandle, 1089a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller 1090a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 1091a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 1092a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1093a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni return Status; 1094a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni} 1095a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1096a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni/** 1097a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Disconnect this driver with the controller, uninstall related protocol instance 1098a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1099a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. 1100a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param Controller The handle of the controller to test. 1101a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param NumberOfChildren Number of child device. 1102a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @param ChildHandleBuffer A pointer to the remaining portion of a device path. 1103a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1104a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @retval EFI_SUCCESS Operation successfully 1105a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni @retval EFI_DEVICE_ERROR Cannot stop the driver successfully 1106a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1107a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni**/ 1108a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiEFI_STATUS 1109a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiEFIAPI 1110a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu NiSerialControllerDriverStop ( 1111a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IN EFI_DRIVER_BINDING_PROTOCOL *This, 1112a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IN EFI_HANDLE Controller, 1113a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IN UINTN NumberOfChildren, 1114a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni IN EFI_HANDLE *ChildHandleBuffer 1115a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ) 1116a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1117a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni{ 1118a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_STATUS Status; 1119a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni UINTN Index; 1120a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni BOOLEAN AllChildrenStopped; 1121a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_SERIAL_IO_PROTOCOL *SerialIo; 1122a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SERIAL_DEV *SerialDevice; 1123a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni VOID *IoProtocol; 1124a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_DEVICE_PATH_PROTOCOL *DevicePath; 1125a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PCI_DEVICE_INFO *PciDeviceInfo; 1126a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1127a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PciDeviceInfo = NULL; 1128a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1129a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = gBS->HandleProtocol ( 1130a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 1131a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &gEfiDevicePathProtocolGuid, 1132a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (VOID **) &DevicePath 1133a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 1134a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1135a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 1136a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Report the status code disable the serial 1137a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 1138a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni REPORT_STATUS_CODE_WITH_DEVICE_PATH ( 1139a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_PROGRESS_CODE, 1140a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_P_PC_DISABLE | EFI_PERIPHERAL_SERIAL_PORT, 1141a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni DevicePath 1142a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 1143a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1144a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (NumberOfChildren == 0) { 1145a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 1146a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // Close the bus driver 1147a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 1148a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = gBS->OpenProtocol ( 1149a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 1150a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &gEfiPciIoProtocolGuid, 1151a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &IoProtocol, 1152a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni This->DriverBindingHandle, 1153a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 1154a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_OPEN_PROTOCOL_TEST_PROTOCOL 1155a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 1156a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gBS->CloseProtocol ( 1157a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 1158a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni !EFI_ERROR (Status) ? &gEfiPciIoProtocolGuid : &gEfiSioProtocolGuid, 1159a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni This->DriverBindingHandle, 1160a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller 1161a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 1162a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1163a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gBS->CloseProtocol ( 1164a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 1165a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &gEfiDevicePathProtocolGuid, 1166a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni This->DriverBindingHandle, 1167a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller 1168a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 1169a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni return EFI_SUCCESS; 1170a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 1171a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1172a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni AllChildrenStopped = TRUE; 1173a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1174a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni for (Index = 0; Index < NumberOfChildren; Index++) { 1175a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1176a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = gBS->OpenProtocol ( 1177a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ChildHandleBuffer[Index], 1178a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &gEfiSerialIoProtocolGuid, 1179a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni (VOID **) &SerialIo, 1180a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni This->DriverBindingHandle, 1181a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 1182a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_OPEN_PROTOCOL_GET_PROTOCOL 1183a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 1184a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (!EFI_ERROR (Status)) { 1185a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1186a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni SerialDevice = SERIAL_DEV_FROM_THIS (SerialIo); 1187a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ASSERT ((PciDeviceInfo == NULL) || (PciDeviceInfo == SerialDevice->PciDeviceInfo)); 1188a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PciDeviceInfo = SerialDevice->PciDeviceInfo; 1189a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1190a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = gBS->CloseProtocol ( 1191a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 1192a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PciDeviceInfo != NULL ? &gEfiPciIoProtocolGuid : &gEfiSioProtocolGuid, 1193a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni This->DriverBindingHandle, 1194a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ChildHandleBuffer[Index] 1195a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 1196a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1197a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = gBS->UninstallMultipleProtocolInterfaces ( 1198a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ChildHandleBuffer[Index], 1199a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &gEfiDevicePathProtocolGuid, SerialDevice->DevicePath, 1200a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &gEfiSerialIoProtocolGuid, &SerialDevice->SerialIo, 1201a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni NULL 1202a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 1203a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (EFI_ERROR (Status)) { 1204a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni gBS->OpenProtocol ( 1205a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Controller, 1206a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PciDeviceInfo != NULL ? &gEfiPciIoProtocolGuid : &gEfiSioProtocolGuid, 1207a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni &IoProtocol, 1208a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni This->DriverBindingHandle, 1209a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ChildHandleBuffer[Index], 1210a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 1211a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 1212a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } else { 1213a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni FreePool (SerialDevice->DevicePath); 1214a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni FreeUnicodeStringTable (SerialDevice->ControllerNameTable); 1215a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni FreePool (SerialDevice); 1216a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1217a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (PciDeviceInfo != NULL) { 1218a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ASSERT (PciDeviceInfo->ChildCount != 0); 1219a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PciDeviceInfo->ChildCount--; 1220a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 1221a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 1222a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 1223a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1224a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (EFI_ERROR (Status)) { 1225a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni AllChildrenStopped = FALSE; 1226a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 1227a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 1228a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni 1229a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if (!AllChildrenStopped) { 1230a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni return EFI_DEVICE_ERROR; 1231a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } else { 1232a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 1233a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // If all children are destroyed, restore the PCI attributes. 1234a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni // 1235a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni if ((PciDeviceInfo != NULL) && (PciDeviceInfo->ChildCount == 0)) { 1236a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ASSERT (PciDeviceInfo->PciIo != NULL); 1237a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni Status = PciDeviceInfo->PciIo->Attributes ( 1238a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PciDeviceInfo->PciIo, 1239a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni EfiPciIoAttributeOperationSet, 1240a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni PciDeviceInfo->PciAttributes, 1241a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni NULL 1242a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ); 1243a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni ASSERT_EFI_ERROR (Status); 1244a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni FreePool (PciDeviceInfo); 1245a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 1246a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni return EFI_SUCCESS; 1247a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni } 1248a59e2edebeb2762af458aa63725f5bb0facb7c5eRuiyu Ni} 1249