/** @file
|
File to contain all the hardware specific stuff for the Smm USB dispatch protocol.
|
|
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
**/
|
#include "PchSmmHelpers.h"
|
|
GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_SOURCE_DESC mUSB1_LEGACY = {
|
PCH_SMM_NO_FLAGS,
|
{
|
{
|
{
|
ACPI_ADDR_TYPE,
|
{R_PCH_SMI_EN}
|
},
|
S_PCH_SMI_EN,
|
N_PCH_SMI_EN_LEGACY_USB
|
},
|
NULL_BIT_DESC_INITIALIZER
|
},
|
{
|
{
|
{
|
ACPI_ADDR_TYPE,
|
{R_PCH_SMI_STS}
|
},
|
S_PCH_SMI_STS,
|
N_PCH_SMI_STS_LEGACY_USB
|
}
|
},
|
{
|
{
|
ACPI_ADDR_TYPE,
|
{R_PCH_SMI_STS}
|
},
|
S_PCH_SMI_STS,
|
N_PCH_SMI_STS_LEGACY_USB
|
}
|
};
|
|
GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_SOURCE_DESC mUSB3_LEGACY = {
|
PCH_SMM_NO_FLAGS,
|
{
|
{
|
{
|
ACPI_ADDR_TYPE,
|
{R_PCH_SMI_EN}
|
},
|
S_PCH_SMI_EN,
|
N_PCH_SMI_EN_LEGACY_USB3
|
},
|
NULL_BIT_DESC_INITIALIZER
|
},
|
{
|
{
|
{
|
ACPI_ADDR_TYPE,
|
{R_PCH_SMI_STS}
|
},
|
S_PCH_SMI_STS,
|
N_PCH_SMI_STS_LEGACY_USB3
|
}
|
},
|
{
|
{
|
ACPI_ADDR_TYPE,
|
{R_PCH_SMI_STS}
|
},
|
S_PCH_SMI_STS,
|
N_PCH_SMI_STS_LEGACY_USB3
|
}
|
};
|
|
typedef enum {
|
PchUsbControllerLpc0 = 0,
|
PchUsbControllerXhci,
|
PchUsbControllerTypeMax
|
} PCH_USB_CONTROLLER_TYPE;
|
|
typedef struct {
|
UINT8 Function;
|
UINT8 Device;
|
PCH_USB_CONTROLLER_TYPE UsbConType;
|
} USB_CONTROLLER;
|
|
GLOBAL_REMOVE_IF_UNREFERENCED USB_CONTROLLER mUsbControllersMap[] = {
|
{
|
PCI_FUNCTION_NUMBER_PCH_LPC,
|
PCI_DEVICE_NUMBER_PCH_LPC,
|
PchUsbControllerLpc0
|
},
|
{
|
PCI_FUNCTION_NUMBER_PCH_XHCI,
|
PCI_DEVICE_NUMBER_PCH_XHCI,
|
PchUsbControllerXhci
|
}
|
};
|
|
/**
|
Find the handle that best matches the input Device Path and return the USB controller type
|
|
@param[in] DevicePath Pointer to the device Path table
|
@param[out] Controller Returned with the USB controller type of the input device path
|
|
@retval EFI_SUCCESS Find the handle that best matches the input Device Path
|
@exception EFI_UNSUPPORTED Invalid device Path table or can't find any match USB device path
|
PCH_USB_CONTROLLER_TYPE The USB controller type of the input
|
device path
|
**/
|
EFI_STATUS
|
DevicePathToSupportedController (
|
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
|
OUT PCH_USB_CONTROLLER_TYPE *Controller
|
)
|
{
|
EFI_STATUS Status;
|
EFI_HANDLE DeviceHandle;
|
ACPI_HID_DEVICE_PATH *AcpiNode;
|
PCI_DEVICE_PATH *PciNode;
|
EFI_DEVICE_PATH_PROTOCOL *RemaingDevicePath;
|
UINT8 UsbIndex;
|
///
|
/// Find the handle that best matches the Device Path. If it is only a
|
/// partial match the remaining part of the device path is returned in
|
/// RemainingDevicePath.
|
///
|
RemaingDevicePath = DevicePath;
|
Status = gBS->LocateDevicePath (
|
&gEfiPciRootBridgeIoProtocolGuid,
|
&DevicePath,
|
&DeviceHandle
|
);
|
if (EFI_ERROR (Status)) {
|
return EFI_UNSUPPORTED;
|
}
|
|
DevicePath = RemaingDevicePath;
|
|
///
|
/// Get first node: Acpi Node
|
///
|
AcpiNode = (ACPI_HID_DEVICE_PATH *) RemaingDevicePath;
|
|
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
|
) {
|
return EFI_UNSUPPORTED;
|
} else {
|
///
|
/// Get the next node: Pci Node
|
///
|
RemaingDevicePath = NextDevicePathNode (RemaingDevicePath);
|
PciNode = (PCI_DEVICE_PATH *) RemaingDevicePath;
|
if (PciNode->Header.Type != HARDWARE_DEVICE_PATH ||
|
PciNode->Header.SubType != HW_PCI_DP ||
|
DevicePathNodeLength (&PciNode->Header) != sizeof (PCI_DEVICE_PATH)
|
) {
|
return EFI_UNSUPPORTED;
|
}
|
|
for (UsbIndex = 0; UsbIndex < sizeof (mUsbControllersMap) / sizeof (USB_CONTROLLER); UsbIndex++) {
|
if ((PciNode->Device == mUsbControllersMap[UsbIndex].Device) &&
|
(PciNode->Function == mUsbControllersMap[UsbIndex].Function)) {
|
*Controller = mUsbControllersMap[UsbIndex].UsbConType;
|
return EFI_SUCCESS;
|
}
|
}
|
|
return EFI_UNSUPPORTED;
|
}
|
}
|
|
/**
|
Maps a USB context to a source description.
|
|
@param[in] Context The context we need to map. Type must be USB.
|
@param[in] SrcDesc The source description that corresponds to the given context.
|
|
**/
|
VOID
|
MapUsbToSrcDesc (
|
IN PCH_SMM_CONTEXT *Context,
|
OUT PCH_SMM_SOURCE_DESC *SrcDesc
|
)
|
{
|
PCH_USB_CONTROLLER_TYPE Controller;
|
EFI_STATUS Status;
|
|
Status = DevicePathToSupportedController (Context->Usb.Device, &Controller);
|
///
|
/// Either the device path passed in by the child is incorrect or
|
/// the ones stored here internally are incorrect.
|
///
|
ASSERT_EFI_ERROR (Status);
|
|
switch (Context->Usb.Type) {
|
case UsbLegacy:
|
switch (Controller) {
|
case PchUsbControllerLpc0:
|
CopyMem ((VOID *) SrcDesc, (VOID *) (&mUSB1_LEGACY), sizeof (PCH_SMM_SOURCE_DESC));
|
break;
|
|
case PchUsbControllerXhci:
|
CopyMem ((VOID *) SrcDesc, (VOID *) (&mUSB3_LEGACY), sizeof (PCH_SMM_SOURCE_DESC));
|
break;
|
|
default:
|
ASSERT (FALSE);
|
break;
|
}
|
break;
|
|
case UsbWake:
|
ASSERT (FALSE);
|
break;
|
|
default:
|
ASSERT (FALSE);
|
break;
|
}
|
}
|