/** @file Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent Module Name: LpcDriver.c Abstract: EFI Lpc Driver for a Generic PC Platform --*/ #include "LpcDriver.h" #include "IndustryStandard/Pci22.h" // // This driver is for ACPI(PNP0A03,0)/PCI(0x1f,0) // // // Lpc Driver Global Variables // EFI_DRIVER_BINDING_PROTOCOL gLpcDriver = { LpcDriverSupported, LpcDriverStart, LpcDriverStop, 0x10, NULL, NULL }; LPC_DEV mLpc = { LPC_DEV_SIGNATURE, NULL, { IsaDeviceEnumerate, IsaDeviceSetPower, IsaGetCurrentResource, IsaGetPossibleResource, IsaSetResource, IsaEnableDevice, IsaInitDevice, LpcInterfaceInit }, NULL }; BOOLEAN InitExecuted = FALSE; /** the entry point of the Lpc driver **/ EFI_STATUS EFIAPI LpcDriverEntryPoint( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { return EfiLibInstallDriverBinding (ImageHandle, SystemTable, &gLpcDriver, ImageHandle); } /** ControllerDriver Protocol Method **/ EFI_STATUS EFIAPI LpcDriverSupported ( 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 *IsaBridgeDevicePath; ACPI_HID_DEVICE_PATH *AcpiNode; PCI_DEVICE_PATH *PciNode; PCI_TYPE00 Pci; // // Get the ISA bridge's Device Path and test it // the following code is specific // 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 (AcpiNode->Header.Type != ACPI_DEVICE_PATH || AcpiNode->Header.SubType != ACPI_DP || DevicePathNodeLength (&AcpiNode->Header) != sizeof(ACPI_HID_DEVICE_PATH) || AcpiNode -> HID != EISA_PNP_ID(0x0A03) || AcpiNode -> UID != 0 ) { Status = EFI_UNSUPPORTED; } else { // // Get the next node // IsaBridgeDevicePath = NextDevicePathNode (IsaBridgeDevicePath); PciNode = (PCI_DEVICE_PATH *)IsaBridgeDevicePath; if (PciNode->Header.Type != HARDWARE_DEVICE_PATH || PciNode->Header.SubType != HW_PCI_DP || DevicePathNodeLength (&PciNode->Header) != sizeof (PCI_DEVICE_PATH) || PciNode -> Function != 0x00 || PciNode -> Device != 0x1f ) { Status = EFI_UNSUPPORTED; } } gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } // // Get PciIo protocol instance // 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) / sizeof(UINT32), &Pci ); if (!EFI_ERROR (Status)) { Status = EFI_SUCCESS; //TODO: force return success as temp solution EFI_UNSUPPORTED; if ((Pci.Hdr.Command & 0x03) == 0x03) { 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; } else { } // // 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 && Pci.Hdr.DeviceId == 0x7110) { Status = EFI_SUCCESS; } else { } } else { } } else { } } gBS->CloseProtocol ( Controller, &gEfiPciIoProtocolGuid, This->DriverBindingHandle, Controller ); return Status; } /** Install EFI_ISA_ACPI_PROTOCOL **/ EFI_STATUS EFIAPI LpcDriverStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; EFI_PCI_IO_PROTOCOL *PciIo; // // 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) { return Status; } mLpc.PciIo = PciIo; // // Install IsaAcpi interface, the Sio interface is not installed! // Status = gBS->InstallMultipleProtocolInterfaces ( &Controller, &gEfiIsaAcpiProtocolGuid, &mLpc.IsaAcpi, NULL ); return Status; } EFI_STATUS EFIAPI LpcDriverStop ( 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; LPC_DEV *LpcDev; // // Get EFI_ISA_ACPI_PROTOCOL interface // Status = gBS->OpenProtocol ( Controller, &gEfiIsaAcpiProtocolGuid, (VOID **)&IsaAcpi, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return Status; } LpcDev = LPC_ISA_ACPI_FROM_THIS (IsaAcpi); // // Uninstall protocol interface: EFI_ISA_ACPI_PROTOCOL // Status = gBS->UninstallProtocolInterface ( Controller, &gEfiIsaAcpiProtocolGuid, &LpcDev->IsaAcpi ); if (EFI_ERROR (Status)) { return Status; } gBS->CloseProtocol ( Controller, &gEfiPciIoProtocolGuid, This->DriverBindingHandle, Controller ); return EFI_SUCCESS; } VOID LpcIoRead8 ( IN UINT16 Port, OUT UINT8 *Data ) { mLpc.PciIo->Io.Read( mLpc.PciIo, EfiPciWidthUint8, EFI_PCI_IO_PASS_THROUGH_BAR, Port, 1, Data ); } VOID LpcIoWrite8 ( IN UINT16 Port, IN UINT8 Data ) { mLpc.PciIo->Io.Write( mLpc.PciIo, EfiPciWidthUint8, EFI_PCI_IO_PASS_THROUGH_BAR, Port, 1, &Data ); }