|
@@ -0,0 +1,600 @@
|
|
|
+/** @file
|
|
|
+ EFI Driver following Driver Binding Protocol.
|
|
|
+
|
|
|
+ Copyright (c) 2010 - 2019 Intel Corporation. All rights reserved. <BR>
|
|
|
+
|
|
|
+ SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
+**/
|
|
|
+
|
|
|
+#include "SioDriver.h"
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// This driver is for ACPI(PNP0A03,0)/PCI(0x1f,0)
|
|
|
+//
|
|
|
+//
|
|
|
+// Sio Driver Global Variables
|
|
|
+//
|
|
|
+EFI_DRIVER_BINDING_PROTOCOL mSioDriver = {
|
|
|
+ SioDriverSupported,
|
|
|
+ SioDriverStart,
|
|
|
+ SioDriverStop,
|
|
|
+ 1,
|
|
|
+ NULL,
|
|
|
+ NULL
|
|
|
+};
|
|
|
+
|
|
|
+//
|
|
|
+// The list of the created SIO_DEV
|
|
|
+//
|
|
|
+LIST_ENTRY mSioDevPool = INITIALIZE_LIST_HEAD_VARIABLE (mSioDevPool);
|
|
|
+
|
|
|
+//
|
|
|
+// Template structure to create SIO_DEV
|
|
|
+//
|
|
|
+SIO_DEV mSioDevTemplate = {
|
|
|
+ SIO_DEV_SIGNATURE, // Signature
|
|
|
+ NULL, // PciHandle
|
|
|
+ {
|
|
|
+ 0x00000000, // HID
|
|
|
+ 0x00000000 // UID
|
|
|
+ },
|
|
|
+ NULL, // Handle
|
|
|
+ { // Sio Instance
|
|
|
+ SioRegisterAccess,
|
|
|
+ SioGetResources,
|
|
|
+ SioSetResources,
|
|
|
+ SioPossibleResources,
|
|
|
+ SioModify
|
|
|
+ },
|
|
|
+ NULL, // DevicePath
|
|
|
+ {
|
|
|
+ NULL, // ForwardLink
|
|
|
+ NULL, // BackLink
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+//
|
|
|
+// Template ACPI_HID_DEVICE_PATH structure to create device path
|
|
|
+//
|
|
|
+ACPI_HID_DEVICE_PATH mAcpiNodeTemplate = {
|
|
|
+ {
|
|
|
+ ACPI_DEVICE_PATH, // Type
|
|
|
+ ACPI_DP, // SubType
|
|
|
+ {
|
|
|
+ sizeof (ACPI_HID_DEVICE_PATH), // Length[0]
|
|
|
+ 0 // Length[1]
|
|
|
+ }
|
|
|
+ },
|
|
|
+ 0x00000000, // HID
|
|
|
+ 0x00000000 // UID
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ The user Entry Point for module Lpc47m17x. The user code starts with this function.
|
|
|
+
|
|
|
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
|
|
|
+ @param[in] SystemTable A pointer to the EFI System Table.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS The entry point is executed successfully.
|
|
|
+ @retval other Some error occurs when executing this entry point.
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+SioDriverEntryPoint (
|
|
|
+ IN EFI_HANDLE ImageHandle,
|
|
|
+ IN EFI_SYSTEM_TABLE *SystemTable
|
|
|
+ )
|
|
|
+{
|
|
|
+ if (EFI_ERROR (SioInit())) {
|
|
|
+ return EFI_UNSUPPORTED;
|
|
|
+ } else {
|
|
|
+
|
|
|
+ //
|
|
|
+ // Install protocols
|
|
|
+ //
|
|
|
+ return EfiLibInstallDriverBindingComponentName2 (
|
|
|
+ ImageHandle,
|
|
|
+ SystemTable,
|
|
|
+ &mSioDriver,
|
|
|
+ ImageHandle,
|
|
|
+ &mSioComponentName,
|
|
|
+ &mSioComponentName2
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ Test to see if this driver supports Controller Handle.
|
|
|
+
|
|
|
+ @param[in] This Protocol instance pointer.
|
|
|
+ @param[in] Controller Handle of device to test
|
|
|
+ @param[in] RemainingDevicePath Optional parameter use to pick a specific child
|
|
|
+ device to start.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS This driver supports this device
|
|
|
+ @retval EFI_ALREADY_STARTED This driver is already running on this device
|
|
|
+ @retval other This driver does not support this device
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+SioDriverSupported (
|
|
|
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
|
+ IN EFI_HANDLE Controller,
|
|
|
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_STATUS Status;
|
|
|
+ EFI_PCI_IO_PROTOCOL *PciIo;
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
|
|
|
+ ACPI_HID_DEVICE_PATH *AcpiNode;
|
|
|
+ PCI_TYPE00 Pci;
|
|
|
+ UINTN Index;
|
|
|
+ EFI_SIO_ACPI_DEVICE_ID *Devices;
|
|
|
+ UINTN Count;
|
|
|
+ UINTN SegmentNumber;
|
|
|
+ UINTN BusNumber;
|
|
|
+ UINTN DeviceNumber;
|
|
|
+ UINTN FunctionNumber;
|
|
|
+
|
|
|
+ //
|
|
|
+ // If RemainingDevicePath is not NULL, it should verify that the first device
|
|
|
+ // path node in RemainingDevicePath is an ACPI Device path node which is a
|
|
|
+ // legal Device Path Node for this bus driver's children.
|
|
|
+ //
|
|
|
+ if (RemainingDevicePath != NULL) {
|
|
|
+ if (!IsDevicePathEnd (RemainingDevicePath)) {
|
|
|
+ if ((RemainingDevicePath->Type != ACPI_DEVICE_PATH) ||
|
|
|
+ (((RemainingDevicePath->SubType != ACPI_DP) || (DevicePathNodeLength (RemainingDevicePath) != sizeof (ACPI_HID_DEVICE_PATH))) &&
|
|
|
+ ((RemainingDevicePath->SubType != ACPI_EXTENDED_DP) || (DevicePathNodeLength (RemainingDevicePath) != sizeof (ACPI_EXTENDED_HID_DEVICE_PATH))))
|
|
|
+ ) {
|
|
|
+ return EFI_UNSUPPORTED;
|
|
|
+ }
|
|
|
+
|
|
|
+ DeviceGetList (&Devices, &Count);
|
|
|
+ if (Devices == NULL) {
|
|
|
+ return EFI_OUT_OF_RESOURCES;
|
|
|
+ }
|
|
|
+ AcpiNode = (ACPI_HID_DEVICE_PATH *) RemainingDevicePath;
|
|
|
+ for (Index = 0; Index < Count; Index++) {
|
|
|
+ if ((AcpiNode->HID == Devices[Index].HID) &&
|
|
|
+ (AcpiNode->UID == Devices[Index].UID)) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ FreePool (Devices);
|
|
|
+ if (Index == Count) {
|
|
|
+ return EFI_UNSUPPORTED;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // See if the parent device path can be opened BY_DRIVER
|
|
|
+ //
|
|
|
+ Status = gBS->OpenProtocol (
|
|
|
+ Controller,
|
|
|
+ &gEfiDevicePathProtocolGuid,
|
|
|
+ (VOID **) &ParentDevicePath,
|
|
|
+ This->DriverBindingHandle,
|
|
|
+ Controller,
|
|
|
+ EFI_OPEN_PROTOCOL_BY_DRIVER
|
|
|
+ );
|
|
|
+ if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ gBS->CloseProtocol (
|
|
|
+ Controller,
|
|
|
+ &gEfiDevicePathProtocolGuid,
|
|
|
+ This->DriverBindingHandle,
|
|
|
+ Controller
|
|
|
+ );
|
|
|
+
|
|
|
+ //
|
|
|
+ // Get PciIo protocol instance
|
|
|
+ //
|
|
|
+ Status = gBS->OpenProtocol (
|
|
|
+ Controller,
|
|
|
+ &gEfiPciIoProtocolGuid,
|
|
|
+ (VOID **) &PciIo,
|
|
|
+ This->DriverBindingHandle,
|
|
|
+ Controller,
|
|
|
+ EFI_OPEN_PROTOCOL_BY_DRIVER
|
|
|
+ );
|
|
|
+
|
|
|
+ if (!EFI_ERROR (Status)) {
|
|
|
+ Status = PciIo->Pci.Read (
|
|
|
+ PciIo,
|
|
|
+ EfiPciIoWidthUint32,
|
|
|
+ 0,
|
|
|
+ sizeof (Pci) / sizeof (UINT32),
|
|
|
+ &Pci
|
|
|
+ );
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+
|
|
|
+ Status = EFI_UNSUPPORTED;
|
|
|
+ if ((Pci.Hdr.Command & (EFI_PCI_COMMAND_IO_SPACE | EFI_PCI_COMMAND_MEMORY_SPACE))
|
|
|
+ == (EFI_PCI_COMMAND_IO_SPACE | EFI_PCI_COMMAND_MEMORY_SPACE)
|
|
|
+ ) {
|
|
|
+ if (Pci.Hdr.ClassCode[2] == PCI_CLASS_BRIDGE) {
|
|
|
+ //
|
|
|
+ // See if this is a standard PCI to ISA Bridge from the Base Code and Class Code
|
|
|
+ //
|
|
|
+ if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA) {
|
|
|
+ Status = EFI_SUCCESS;
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // See if this is an Intel PCI to ISA Bridge in Positive Decode Mode
|
|
|
+ //
|
|
|
+ if ((Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA_PDECODE) &&
|
|
|
+ (Pci.Hdr.VendorId == 0x8086)) {
|
|
|
+ //
|
|
|
+ // See if this is on Function #0 to avoid false positive on
|
|
|
+ // PCI_CLASS_BRIDGE_OTHER that has the same value as
|
|
|
+ // PCI_CLASS_BRIDGE_ISA_PDECODE
|
|
|
+ //
|
|
|
+ Status = PciIo->GetLocation (
|
|
|
+ PciIo,
|
|
|
+ &SegmentNumber,
|
|
|
+ &BusNumber,
|
|
|
+ &DeviceNumber,
|
|
|
+ &FunctionNumber
|
|
|
+ );
|
|
|
+ if (!EFI_ERROR (Status) && (FunctionNumber == 0)) {
|
|
|
+ Status = EFI_SUCCESS;
|
|
|
+ } else {
|
|
|
+ Status = EFI_UNSUPPORTED;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ gBS->CloseProtocol (
|
|
|
+ Controller,
|
|
|
+ &gEfiPciIoProtocolGuid,
|
|
|
+ This->DriverBindingHandle,
|
|
|
+ Controller
|
|
|
+ );
|
|
|
+ }
|
|
|
+ if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ return EFI_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ Destroy the SIO controller handle.
|
|
|
+
|
|
|
+ @param[in] ChildHandle The SIO controller handle.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS The SIO controller handle is destroyed successfully.
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+SioDestroyDevice (
|
|
|
+ IN EFI_HANDLE ChildHandle
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_STATUS Status;
|
|
|
+ SIO_DEV *SioDev;
|
|
|
+ EFI_SIO_PROTOCOL *Sio;
|
|
|
+ EFI_PCI_IO_PROTOCOL *PciIo;
|
|
|
+
|
|
|
+ Status = gBS->HandleProtocol (
|
|
|
+ ChildHandle,
|
|
|
+ &gEfiSioProtocolGuid,
|
|
|
+ (VOID **) &Sio
|
|
|
+ );
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+
|
|
|
+ SioDev = SIO_DEV_FROM_THIS (Sio);
|
|
|
+
|
|
|
+ Status = gBS->CloseProtocol (
|
|
|
+ SioDev->PciHandle,
|
|
|
+ &gEfiPciIoProtocolGuid,
|
|
|
+ mSioDriver.DriverBindingHandle,
|
|
|
+ ChildHandle
|
|
|
+ );
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+
|
|
|
+ Status = gBS->UninstallMultipleProtocolInterfaces (
|
|
|
+ ChildHandle,
|
|
|
+ &gEfiDevicePathProtocolGuid,
|
|
|
+ SioDev->DevicePath,
|
|
|
+ &gEfiSioProtocolGuid,
|
|
|
+ &SioDev->Sio,
|
|
|
+ NULL
|
|
|
+ );
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ gBS->OpenProtocol (
|
|
|
+ SioDev->PciHandle,
|
|
|
+ &gEfiPciIoProtocolGuid,
|
|
|
+ (VOID **) &PciIo,
|
|
|
+ mSioDriver.DriverBindingHandle,
|
|
|
+ ChildHandle,
|
|
|
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
|
|
+ );
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ RemoveEntryList (&SioDev->Link);
|
|
|
+ FreePool (SioDev->DevicePath);
|
|
|
+ FreePool (SioDev);
|
|
|
+ return EFI_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ Create the SIO controller handle.
|
|
|
+
|
|
|
+ @param[in] Controller The parent PCI controller handle.
|
|
|
+ @param[in] Device Pointer to EFI_SIO_ACPI_DEVICE_ID.
|
|
|
+ @param[in] ParentDevicePath The device path of the parent controller.
|
|
|
+ @param[out] PciIo The PciIo instance of the parent controller.
|
|
|
+**/
|
|
|
+VOID
|
|
|
+SioCreateDevice (
|
|
|
+ IN EFI_HANDLE Controller,
|
|
|
+ IN EFI_SIO_ACPI_DEVICE_ID *Device,
|
|
|
+ IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
|
|
|
+ OUT EFI_PCI_IO_PROTOCOL *PciIo
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_STATUS Status;
|
|
|
+ SIO_DEV *SioDev;
|
|
|
+
|
|
|
+ DeviceEnable (Device);
|
|
|
+ SioDev = AllocateCopyPool (sizeof (SIO_DEV), &mSioDevTemplate);
|
|
|
+ ASSERT (SioDev != NULL);
|
|
|
+ if (SioDev == NULL) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ InsertHeadList (&mSioDevPool, &SioDev->Link);
|
|
|
+
|
|
|
+ SioDev->PciHandle = Controller;
|
|
|
+
|
|
|
+ CopyMem (&SioDev->Device, Device, sizeof (*Device));
|
|
|
+
|
|
|
+ mAcpiNodeTemplate.HID = Device->HID;
|
|
|
+ mAcpiNodeTemplate.UID = Device->UID;
|
|
|
+ SioDev->DevicePath = AppendDevicePathNode (ParentDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &mAcpiNodeTemplate);
|
|
|
+ ASSERT (SioDev->DevicePath != NULL);
|
|
|
+
|
|
|
+ Status = gBS->InstallMultipleProtocolInterfaces (
|
|
|
+ &SioDev->Handle,
|
|
|
+ &gEfiSioProtocolGuid, &SioDev->Sio,
|
|
|
+ &gEfiDevicePathProtocolGuid, SioDev->DevicePath,
|
|
|
+ NULL
|
|
|
+ );
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+
|
|
|
+ Status = gBS->OpenProtocol (
|
|
|
+ Controller,
|
|
|
+ &gEfiPciIoProtocolGuid,
|
|
|
+ (VOID **) &PciIo,
|
|
|
+ mSioDriver.DriverBindingHandle,
|
|
|
+ SioDev->Handle,
|
|
|
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
|
|
+ );
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ Start this driver on ControllerHandle.
|
|
|
+
|
|
|
+ @param[in] This Protocol instance pointer.
|
|
|
+ @param[in] Controller Handle of device to bind driver to
|
|
|
+ @param[in] RemainingDevicePath Optional parameter use to pick a specific child
|
|
|
+ device to start.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS This driver is added to ControllerHandle
|
|
|
+ @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
|
|
|
+ @retval other This driver does not support this device
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+SioDriverStart (
|
|
|
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
|
+ IN EFI_HANDLE Controller,
|
|
|
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_STATUS Status;
|
|
|
+ EFI_PCI_IO_PROTOCOL *PciIo;
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
|
|
|
+ EFI_SIO_ACPI_DEVICE_ID *Devices;
|
|
|
+ SIO_DEV *SioDev;
|
|
|
+ UINTN Count;
|
|
|
+ UINTN Index;
|
|
|
+ ACPI_HID_DEVICE_PATH *AcpiNode;
|
|
|
+ BOOLEAN *HasCreated;
|
|
|
+ BOOLEAN *RequestCreate;
|
|
|
+ LIST_ENTRY *Node;
|
|
|
+
|
|
|
+ HasCreated = NULL;
|
|
|
+ RequestCreate = NULL;
|
|
|
+ //
|
|
|
+ // Get the ISA bridge's Device Path
|
|
|
+ //
|
|
|
+ Status = gBS->OpenProtocol (
|
|
|
+ Controller,
|
|
|
+ &gEfiDevicePathProtocolGuid,
|
|
|
+ (VOID **) &ParentDevicePath,
|
|
|
+ This->DriverBindingHandle,
|
|
|
+ Controller,
|
|
|
+ EFI_OPEN_PROTOCOL_BY_DRIVER
|
|
|
+ );
|
|
|
+ if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // Get Pci IO
|
|
|
+ //
|
|
|
+ Status = gBS->OpenProtocol (
|
|
|
+ Controller,
|
|
|
+ &gEfiPciIoProtocolGuid,
|
|
|
+ (VOID **) &PciIo,
|
|
|
+ This->DriverBindingHandle,
|
|
|
+ Controller,
|
|
|
+ EFI_OPEN_PROTOCOL_BY_DRIVER
|
|
|
+ );
|
|
|
+
|
|
|
+ if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
|
|
|
+ gBS->CloseProtocol (
|
|
|
+ Controller,
|
|
|
+ &gEfiDevicePathProtocolGuid,
|
|
|
+ This->DriverBindingHandle,
|
|
|
+ Controller
|
|
|
+ );
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((RemainingDevicePath != NULL) && IsDevicePathEnd (RemainingDevicePath)) {
|
|
|
+ return EFI_SUCCESS;
|
|
|
+ }
|
|
|
+
|
|
|
+ DeviceGetList (&Devices, &Count);
|
|
|
+ if (Devices == NULL) {
|
|
|
+ Status = EFI_OUT_OF_RESOURCES;
|
|
|
+ goto Exit_Start;
|
|
|
+ }
|
|
|
+ HasCreated = AllocatePool (sizeof (BOOLEAN) * Count);
|
|
|
+ ASSERT (HasCreated != NULL);
|
|
|
+ if (HasCreated == NULL) {
|
|
|
+ Status = EFI_OUT_OF_RESOURCES;
|
|
|
+ goto Exit_Start;
|
|
|
+ }
|
|
|
+ RequestCreate = AllocatePool (sizeof (BOOLEAN) * Count);
|
|
|
+ ASSERT (RequestCreate != NULL);
|
|
|
+ if (RequestCreate == NULL) {
|
|
|
+ Status = EFI_OUT_OF_RESOURCES;
|
|
|
+ goto Exit_Start;
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // Assume no children has been created.
|
|
|
+ // Assume the SIO interface hasn't been initialized.
|
|
|
+ //
|
|
|
+ ZeroMem (HasCreated, sizeof (BOOLEAN) * Count);
|
|
|
+
|
|
|
+ if (Status == EFI_ALREADY_STARTED) {
|
|
|
+ for (Node = GetFirstNode (&mSioDevPool);
|
|
|
+ !IsNull (&mSioDevPool, Node);
|
|
|
+ Node = GetNextNode (&mSioDevPool, Node)
|
|
|
+ ) {
|
|
|
+ SioDev = CR (Node, SIO_DEV, Link, SIO_DEV_SIGNATURE);
|
|
|
+ Status = gBS->HandleProtocol (
|
|
|
+ SioDev->PciHandle,
|
|
|
+ &gEfiDevicePathProtocolGuid,
|
|
|
+ (VOID **) &DevicePath
|
|
|
+ );
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+
|
|
|
+ //
|
|
|
+ // See if they are under the same PCI to ISA Bridge
|
|
|
+ //
|
|
|
+ if (CompareMem (DevicePath, ParentDevicePath, GetDevicePathSize (DevicePath)) == 0) {
|
|
|
+ for (Index = 0; Index < Count; Index++) {
|
|
|
+ if (CompareMem (&SioDev->Device, &Devices[Index], sizeof (EFI_SIO_ACPI_DEVICE_ID)) == 0) {
|
|
|
+ HasCreated[Index] = TRUE;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ AcpiNode = (ACPI_HID_DEVICE_PATH *) RemainingDevicePath;
|
|
|
+ for (Index = 0; Index < Count; Index++) {
|
|
|
+ if ((AcpiNode == NULL) ||
|
|
|
+ ((AcpiNode->HID == Devices[Index].HID) && (AcpiNode->UID == Devices[Index].UID))
|
|
|
+ ) {
|
|
|
+ RequestCreate[Index] = TRUE;
|
|
|
+ } else {
|
|
|
+ RequestCreate[Index] = FALSE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for (Index = 0; Index < Count; Index++) {
|
|
|
+ if (RequestCreate[Index] && !HasCreated[Index]) {
|
|
|
+ SioCreateDevice (Controller, &Devices[Index], ParentDevicePath, PciIo);
|
|
|
+ }
|
|
|
+ }
|
|
|
+Exit_Start:
|
|
|
+ if (Devices != NULL) {
|
|
|
+ FreePool (Devices);
|
|
|
+ }
|
|
|
+ if (HasCreated != NULL) {
|
|
|
+ FreePool (HasCreated);
|
|
|
+ }
|
|
|
+ if (RequestCreate != NULL) {
|
|
|
+ FreePool (RequestCreate);
|
|
|
+ }
|
|
|
+
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ Stop this driver on ControllerHandle.
|
|
|
+
|
|
|
+ @param[in] This Protocol instance pointer.
|
|
|
+ @param[in] Controller Handle of device to stop driver on
|
|
|
+ @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
|
|
|
+ children is zero stop the entire bus driver.
|
|
|
+ @param[in] ChildHandleBuffer List of Child Handles to Stop.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS This driver is removed ControllerHandle
|
|
|
+ @retval other This driver was not removed from this device
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+SioDriverStop (
|
|
|
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
|
+ IN EFI_HANDLE Controller,
|
|
|
+ IN UINTN NumberOfChildren,
|
|
|
+ IN EFI_HANDLE *ChildHandleBuffer
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_STATUS Status;
|
|
|
+ UINTN Index;
|
|
|
+ BOOLEAN AllChildrenStopped;
|
|
|
+
|
|
|
+ if (NumberOfChildren == 0) {
|
|
|
+ gBS->CloseProtocol (
|
|
|
+ Controller,
|
|
|
+ &gEfiDevicePathProtocolGuid,
|
|
|
+ This->DriverBindingHandle,
|
|
|
+ Controller
|
|
|
+ );
|
|
|
+ gBS->CloseProtocol (
|
|
|
+ Controller,
|
|
|
+ &gEfiPciIoProtocolGuid,
|
|
|
+ This->DriverBindingHandle,
|
|
|
+ Controller
|
|
|
+ );
|
|
|
+ return EFI_SUCCESS;
|
|
|
+ }
|
|
|
+
|
|
|
+ AllChildrenStopped = TRUE;
|
|
|
+ for (Index = 0; Index < NumberOfChildren; Index++) {
|
|
|
+ Status = SioDestroyDevice (ChildHandleBuffer[Index]);
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ AllChildrenStopped = FALSE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (AllChildrenStopped) {
|
|
|
+ return EFI_SUCCESS;
|
|
|
+ } else {
|
|
|
+ return EFI_DEVICE_ERROR;
|
|
|
+ }
|
|
|
+}
|