123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600 |
- /** @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;
- }
- }
|