alder_lake_bios/Insyde/InsydeModulePkg/Universal/IsaAcpiDxe/IsaAcpiDxe.c

360 lines
12 KiB
C

/** @file
ISA ACPI Driver
;******************************************************************************
;* Copyright (c) 2019, Insyde Software Corporation. All Rights Reserved.
;*
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
;* transmit, broadcast, present, recite, release, license or otherwise exploit
;* any part of this publication in any form, by any means, without the prior
;* written permission of Insyde Software Corporation.
;*
;******************************************************************************
*/
#include "IsaAcpiDxe.h"
#include "IsaAcpi.h"
EFI_DRIVER_BINDING_PROTOCOL gIsaAcpiDriverBinding = {
IsaAcpiDriverSupported,
IsaAcpiDriverStart,
IsaAcpiDriverStop,
1,
NULL,
NULL
};
/**
The entry point of IsaAcpiDxe.
@param[in] ImageHandle Pointer to the loaded image protocol for this driver.
@param[in] SystemTable Pointer to the EFI System Table.
@retval EFI_SUCCESS Function complete successfully.
**/
EFI_STATUS
EFIAPI
IsaAcpiDriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
return EfiLibInstallDriverBinding (
ImageHandle,
SystemTable,
&gIsaAcpiDriverBinding,
ImageHandle
);
}
/**
Tests to see if this driver supports a given controller.
@param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
@param[in] ControllerHandle The handle of the controller to test. This handle
must support a protocol interface that supplies
an I/O abstraction to the driver.
@param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
parameter is ignored by device drivers, and is optional for bus
drivers. For bus drivers, if this parameter is not NULL, then
the bus driver must determine if the bus controller specified
by ControllerHandle and the child controller specified
by RemainingDevicePath are both supported by this
bus driver.
@retval EFI_SUCCESS The device specified by ControllerHandle and
RemainingDevicePath is supported by the driver specified by This.
@retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
RemainingDevicePath is already being managed by the driver
specified by This.
@retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
RemainingDevicePath is already being managed by a different
driver or an application that requires exclusive access.
Currently not implemented.
@retval EFI_UNSUPPORTED The device specified by ControllerHandle and
RemainingDevicePath is not supported by the driver specified by This.
**/
EFI_STATUS
EFIAPI
IsaAcpiDriverSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
{
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *IsaBridgeDevicePath;
ACPI_HID_DEVICE_PATH *AcpiNode;
PCI_DEVICE_PATH *PciNode;
UINT8 IsaBridgeDevice;
UINT8 IsaBridgeFunction;
EFI_PCI_IO_PROTOCOL *PciIo;
PCI_TYPE00 Pci;
//
// Verify if there were an ISA bridge present on PCI bus
//
Status = gBS->OpenProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
(VOID**) &IsaBridgeDevicePath,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = EFI_SUCCESS;
AcpiNode = (ACPI_HID_DEVICE_PATH *) IsaBridgeDevicePath;
if (DevicePathNodeLength (&AcpiNode->Header) != sizeof (ACPI_HID_DEVICE_PATH) ||
AcpiNode->Header.Type != ACPI_DEVICE_PATH ||
AcpiNode->Header.SubType != ACPI_DP ||
AcpiNode->HID != EISA_PNP_ID (0x0A03) ||
AcpiNode->UID != 0
)
{
Status = EFI_UNSUPPORTED;
} else {
IsaBridgeDevicePath = NextDevicePathNode (IsaBridgeDevicePath);
PciNode = (PCI_DEVICE_PATH *) IsaBridgeDevicePath;
DxeCsSvcSetIsaInfo (&IsaBridgeDevice, &IsaBridgeFunction);
if (DevicePathNodeLength (&PciNode->Header) != sizeof (PCI_DEVICE_PATH) ||
PciNode->Header.Type != HARDWARE_DEVICE_PATH ||
PciNode->Header.SubType != HW_PCI_DP ||
PciNode->Function != IsaBridgeDevice ||
PciNode->Device != IsaBridgeFunction
)
{
Status = EFI_UNSUPPORTED;
}
}
gBS->CloseProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
This->DriverBindingHandle,
Controller
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Verify if it were an ISA Bridge
//
Status = gBS->OpenProtocol (
Controller,
&gEfiPciIoProtocolGuid,
(VOID**) &PciIo,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = PciIo->Pci.Read (
PciIo,
EfiPciIoWidthUint32,
0,
sizeof (PCI_TYPE00) / sizeof (UINT32),
&Pci
);
if (!EFI_ERROR (Status)) {
Status = EFI_UNSUPPORTED;
if ((Pci.Hdr.Command & (EFI_PCI_COMMAND_IO_SPACE | EFI_PCI_COMMAND_MEMORY_SPACE)) != 0) {
if (IS_PCI_LPC (&Pci)) {
Status = EFI_SUCCESS;
} else {
if (IS_CLASS2 (&Pci, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE) &&
Pci.Hdr.VendorId == V_INTEL_VENDOR_ID
)
{
Status = EFI_SUCCESS;
}
}
}
}
gBS->CloseProtocol (
Controller,
&gEfiPciIoProtocolGuid,
This->DriverBindingHandle,
Controller
);
return Status;
}
/**
Starts the device controller.
@param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
@param[in] ControllerHandle The handle of the controller to start. This handle
must support a protocol interface that supplies
an I/O abstraction to the driver.
@param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
parameter is ignored by device drivers, and is optional for bus
drivers. For a bus driver, if this parameter is NULL, then handles
for all the children of Controller are created by this driver.
If this parameter is not NULL and the first Device Path Node is
not the End of Device Path Node, then only the handle for the
child device specified by the first Device Path Node of
RemainingDevicePath is created by this driver.
If the first Device Path Node of RemainingDevicePath is
the End of Device Path Node, no child handle is created by this
driver.
@retval EFI_SUCCESS The device was started.
@retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
@retval Others The driver failded to start the device.
**/
EFI_STATUS
EFIAPI
IsaAcpiDriverStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
{
EFI_STATUS Status;
EFI_PCI_IO_PROTOCOL *PciIo;
H2O_ISA_BRIDGE *IsaBridge;
PostCode (BDS_START_ISA_ACPI_CONTROLLER);
Status = gBS->OpenProtocol (
Controller,
&gEfiPciIoProtocolGuid,
(VOID**) &PciIo,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
return Status;
}
IsaBridge = AllocateZeroPool (sizeof (H2O_ISA_BRIDGE));
if (IsaBridge == NULL) {
gBS->CloseProtocol (
Controller,
&gEfiPciIoProtocolGuid,
This->DriverBindingHandle,
Controller
);
return EFI_OUT_OF_RESOURCES;
}
IsaBridge->Signature = H2O_ISA_BRIDGE_SIGNATURE;
IsaBridge->Handle = Controller;
IsaBridge->PciIo = PciIo;
IsaBridge->IsaAcpi.DeviceEnumerate = IsaDeviceEnumerate;
IsaBridge->IsaAcpi.SetPower = IsaSetPower;
IsaBridge->IsaAcpi.GetCurResource = IsaGetCurrentResource;
IsaBridge->IsaAcpi.GetPosResource = IsaGetPossibleResource;
IsaBridge->IsaAcpi.SetResource = IsaSetResource;
IsaBridge->IsaAcpi.EnableDevice = IsaEnableDevice;
IsaBridge->IsaAcpi.InitDevice = IsaInitDevice;
IsaBridge->IsaAcpi.InterfaceInit = IsaInterfaceInit;
IsaBridge->IsaAcpi.DriverStopCallback = IsaAcpiDriverStopCallback;
Status = gBS->InstallMultipleProtocolInterfaces (
&Controller,
&gEfiIsaAcpiProtocolGuid,
(VOID**) &IsaBridge->IsaAcpi,
NULL
);
if (EFI_ERROR (Status)) {
gBS->CloseProtocol (
Controller,
&gEfiPciIoProtocolGuid,
This->DriverBindingHandle,
Controller
);
FreePool (IsaBridge);
return Status;
}
IsaInterfaceInit (NULL);
return EFI_SUCCESS;
}
/**
Stops the device controller.
@param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
@param[in] ControllerHandle A handle to the device being stopped. The handle must
support a bus specific I/O protocol for the driver
to use to stop the device.
@param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
@param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
if NumberOfChildren is 0.
@retval EFI_SUCCESS The device was stopped.
@retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
**/
EFI_STATUS
EFIAPI
IsaAcpiDriverStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
)
{
EFI_STATUS Status;
EFI_ISA_ACPI_PROTOCOL *IsaAcpi;
H2O_ISA_BRIDGE *IsaBridge;
Status = gBS->OpenProtocol (
Controller,
&gEfiIsaAcpiProtocolGuid,
(VOID**) &IsaAcpi,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = IsaAcpi->DriverStopCallback (IsaAcpi);
if (EFI_ERROR (Status)) {
return Status;
}
IsaBridge = H2O_ISA_BRIDGE_FROM_PROTOCOL (IsaAcpi);
Status = gBS->UninstallProtocolInterface (
Controller,
&gEfiIsaAcpiProtocolGuid,
(VOID**) &IsaBridge->IsaAcpi
);
if (EFI_ERROR (Status)) {
return Status;
}
gBS->CloseProtocol (
Controller,
&gEfiPciIoProtocolGuid,
This->DriverBindingHandle,
Controller
);
FreePool (IsaBridge);
return EFI_SUCCESS;
}