mirror of https://github.com/acidanthera/audk.git
MdeModulePkg UhciPei: Support IoMmu
Update the UhciPei driver to consume IOMMU_PPI to allocate DMA buffer. If no IOMMU_PPI exists, this driver still calls PEI service to allocate DMA buffer, with assumption that DRAM==DMA. Cc: Jiewen Yao <jiewen.yao@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Star Zeng <star.zeng@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
This commit is contained in:
parent
c34a5aab53
commit
8284b1791e
|
@ -0,0 +1,251 @@
|
|||
/** @file
|
||||
The DMA memory help functions.
|
||||
|
||||
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions
|
||||
of the BSD License which accompanies this distribution. The
|
||||
full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "UhcPeim.h"
|
||||
|
||||
/**
|
||||
Provides the controller-specific addresses required to access system memory from a
|
||||
DMA bus master.
|
||||
|
||||
@param IoMmu Pointer to IOMMU PPI.
|
||||
@param Operation Indicates if the bus master is going to read or write to system memory.
|
||||
@param HostAddress The system memory address to map to the PCI controller.
|
||||
@param NumberOfBytes On input the number of bytes to map. On output the number of bytes
|
||||
that were mapped.
|
||||
@param DeviceAddress The resulting map address for the bus master PCI controller to use to
|
||||
access the hosts HostAddress.
|
||||
@param Mapping A resulting value to pass to Unmap().
|
||||
|
||||
@retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
|
||||
@retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
|
||||
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
|
||||
@retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
IoMmuMap (
|
||||
IN EDKII_IOMMU_PPI *IoMmu,
|
||||
IN EDKII_IOMMU_OPERATION Operation,
|
||||
IN VOID *HostAddress,
|
||||
IN OUT UINTN *NumberOfBytes,
|
||||
OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
|
||||
OUT VOID **Mapping
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT64 Attribute;
|
||||
|
||||
if (IoMmu != NULL) {
|
||||
Status = IoMmu->Map (
|
||||
IoMmu,
|
||||
Operation,
|
||||
HostAddress,
|
||||
NumberOfBytes,
|
||||
DeviceAddress,
|
||||
Mapping
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
switch (Operation) {
|
||||
case EdkiiIoMmuOperationBusMasterRead:
|
||||
case EdkiiIoMmuOperationBusMasterRead64:
|
||||
Attribute = EDKII_IOMMU_ACCESS_READ;
|
||||
break;
|
||||
case EdkiiIoMmuOperationBusMasterWrite:
|
||||
case EdkiiIoMmuOperationBusMasterWrite64:
|
||||
Attribute = EDKII_IOMMU_ACCESS_WRITE;
|
||||
break;
|
||||
case EdkiiIoMmuOperationBusMasterCommonBuffer:
|
||||
case EdkiiIoMmuOperationBusMasterCommonBuffer64:
|
||||
Attribute = EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE;
|
||||
break;
|
||||
default:
|
||||
ASSERT(FALSE);
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
Status = IoMmu->SetAttribute (
|
||||
IoMmu,
|
||||
*Mapping,
|
||||
Attribute
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
IoMmu->Unmap (IoMmu, Mapping);
|
||||
*Mapping = NULL;
|
||||
return Status;
|
||||
}
|
||||
} else {
|
||||
*DeviceAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
|
||||
*Mapping = NULL;
|
||||
Status = EFI_SUCCESS;
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Completes the Map() operation and releases any corresponding resources.
|
||||
|
||||
@param IoMmu Pointer to IOMMU PPI.
|
||||
@param Mapping The mapping value returned from Map().
|
||||
|
||||
**/
|
||||
VOID
|
||||
IoMmuUnmap (
|
||||
IN EDKII_IOMMU_PPI *IoMmu,
|
||||
IN VOID *Mapping
|
||||
)
|
||||
{
|
||||
if (IoMmu != NULL) {
|
||||
IoMmu->SetAttribute (IoMmu, Mapping, 0);
|
||||
IoMmu->Unmap (IoMmu, Mapping);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
|
||||
OperationBusMasterCommonBuffer64 mapping.
|
||||
|
||||
@param IoMmu Pointer to IOMMU PPI.
|
||||
@param Pages The number of pages to allocate.
|
||||
@param HostAddress A pointer to store the base system memory address of the
|
||||
allocated range.
|
||||
@param DeviceAddress The resulting map address for the bus master PCI controller to use to
|
||||
access the hosts HostAddress.
|
||||
@param Mapping A resulting value to pass to Unmap().
|
||||
|
||||
@retval EFI_SUCCESS The requested memory pages were allocated.
|
||||
@retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
|
||||
MEMORY_WRITE_COMBINE and MEMORY_CACHED.
|
||||
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
IoMmuAllocateBuffer (
|
||||
IN EDKII_IOMMU_PPI *IoMmu,
|
||||
IN UINTN Pages,
|
||||
OUT VOID **HostAddress,
|
||||
OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
|
||||
OUT VOID **Mapping
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN NumberOfBytes;
|
||||
EFI_PHYSICAL_ADDRESS HostPhyAddress;
|
||||
|
||||
*HostAddress = NULL;
|
||||
*DeviceAddress = 0;
|
||||
*Mapping = NULL;
|
||||
|
||||
if (IoMmu != NULL) {
|
||||
Status = IoMmu->AllocateBuffer (
|
||||
IoMmu,
|
||||
EfiBootServicesData,
|
||||
Pages,
|
||||
HostAddress,
|
||||
0
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
NumberOfBytes = EFI_PAGES_TO_SIZE (Pages);
|
||||
Status = IoMmu->Map (
|
||||
IoMmu,
|
||||
EdkiiIoMmuOperationBusMasterCommonBuffer,
|
||||
*HostAddress,
|
||||
&NumberOfBytes,
|
||||
DeviceAddress,
|
||||
Mapping
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);
|
||||
*HostAddress = NULL;
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
Status = IoMmu->SetAttribute (
|
||||
IoMmu,
|
||||
*Mapping,
|
||||
EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
IoMmu->Unmap (IoMmu, *Mapping);
|
||||
IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);
|
||||
*Mapping = NULL;
|
||||
*HostAddress = NULL;
|
||||
return Status;
|
||||
}
|
||||
} else {
|
||||
Status = PeiServicesAllocatePages (
|
||||
EfiBootServicesData,
|
||||
Pages,
|
||||
&HostPhyAddress
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
*HostAddress = (VOID *) (UINTN) HostPhyAddress;
|
||||
*DeviceAddress = HostPhyAddress;
|
||||
*Mapping = NULL;
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Frees memory that was allocated with AllocateBuffer().
|
||||
|
||||
@param IoMmu Pointer to IOMMU PPI.
|
||||
@param Pages The number of pages to free.
|
||||
@param HostAddress The base system memory address of the allocated range.
|
||||
@param Mapping The mapping value returned from Map().
|
||||
|
||||
**/
|
||||
VOID
|
||||
IoMmuFreeBuffer (
|
||||
IN EDKII_IOMMU_PPI *IoMmu,
|
||||
IN UINTN Pages,
|
||||
IN VOID *HostAddress,
|
||||
IN VOID *Mapping
|
||||
)
|
||||
{
|
||||
if (IoMmu != NULL) {
|
||||
IoMmu->SetAttribute (IoMmu, Mapping, 0);
|
||||
IoMmu->Unmap (IoMmu, Mapping);
|
||||
IoMmu->FreeBuffer (IoMmu, Pages, HostAddress);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize IOMMU.
|
||||
|
||||
@param IoMmu Pointer to pointer to IOMMU PPI.
|
||||
|
||||
**/
|
||||
VOID
|
||||
IoMmuInit (
|
||||
OUT EDKII_IOMMU_PPI **IoMmu
|
||||
)
|
||||
{
|
||||
*IoMmu = NULL;
|
||||
PeiServicesLocatePpi (
|
||||
&gEdkiiIoMmuPpiGuid,
|
||||
0,
|
||||
NULL,
|
||||
(VOID **) IoMmu
|
||||
);
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
PEIM to produce gPeiUsbHostControllerPpiGuid based on gPeiUsbControllerPpiGuid
|
||||
which is used to enable recovery function from USB Drivers.
|
||||
|
||||
Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved. <BR>
|
||||
Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved. <BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions
|
||||
|
@ -17,6 +17,78 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||
|
||||
#include "UhcPeim.h"
|
||||
|
||||
/**
|
||||
Stop the host controller.
|
||||
|
||||
@param Uhc The UHCI device.
|
||||
@param Timeout Max time allowed.
|
||||
|
||||
@retval EFI_SUCCESS The host controller is stopped.
|
||||
@retval EFI_TIMEOUT Failed to stop the host controller.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UhciStopHc (
|
||||
IN USB_UHC_DEV *Uhc,
|
||||
IN UINTN Timeout
|
||||
)
|
||||
{
|
||||
UINT16 CommandContent;
|
||||
UINT16 UsbSts;
|
||||
UINTN Index;
|
||||
|
||||
CommandContent = USBReadPortW (Uhc, Uhc->UsbHostControllerBaseAddress + USBCMD);
|
||||
CommandContent &= USBCMD_RS;
|
||||
USBWritePortW (Uhc, Uhc->UsbHostControllerBaseAddress + USBCMD, CommandContent);
|
||||
|
||||
//
|
||||
// ensure the HC is in halt status after send the stop command
|
||||
// Timeout is in us unit.
|
||||
//
|
||||
for (Index = 0; Index < (Timeout / 50) + 1; Index++) {
|
||||
UsbSts = USBReadPortW (Uhc, Uhc->UsbHostControllerBaseAddress + USBSTS);
|
||||
|
||||
if ((UsbSts & USBSTS_HCH) == USBSTS_HCH) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
MicroSecondDelay (50);
|
||||
}
|
||||
|
||||
return EFI_TIMEOUT;
|
||||
}
|
||||
|
||||
/**
|
||||
One notified function to stop the Host Controller at the end of PEI
|
||||
|
||||
@param[in] PeiServices Pointer to PEI Services Table.
|
||||
@param[in] NotifyDescriptor Pointer to the descriptor for the Notification event that
|
||||
caused this function to execute.
|
||||
@param[in] Ppi Pointer to the PPI data associated with this function.
|
||||
|
||||
@retval EFI_SUCCESS The function completes successfully
|
||||
@retval others
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UhcEndOfPei (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
|
||||
IN VOID *Ppi
|
||||
)
|
||||
{
|
||||
USB_UHC_DEV *Uhc;
|
||||
|
||||
Uhc = PEI_RECOVERY_USB_UHC_DEV_FROM_THIS_NOTIFY (NotifyDescriptor);
|
||||
|
||||
//
|
||||
// Stop the Host Controller
|
||||
//
|
||||
UhciStopHc (Uhc, 1000 * 1000);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes Usb Host Controller.
|
||||
|
||||
|
@ -98,6 +170,7 @@ UhcPeimEntry (
|
|||
|
||||
UhcDev = (USB_UHC_DEV *) ((UINTN) TempPtr);
|
||||
UhcDev->Signature = USB_UHC_DEV_SIGNATURE;
|
||||
IoMmuInit (&UhcDev->IoMmu);
|
||||
UhcDev->UsbHostControllerBaseAddress = (UINT32) BaseAddress;
|
||||
|
||||
//
|
||||
|
@ -133,6 +206,12 @@ UhcPeimEntry (
|
|||
continue;
|
||||
}
|
||||
|
||||
UhcDev->EndOfPeiNotifyList.Flags = (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
|
||||
UhcDev->EndOfPeiNotifyList.Guid = &gEfiEndOfPeiSignalPpiGuid;
|
||||
UhcDev->EndOfPeiNotifyList.Notify = UhcEndOfPei;
|
||||
|
||||
PeiServicesNotifyPpi (&UhcDev->EndOfPeiNotifyList);
|
||||
|
||||
Index++;
|
||||
}
|
||||
|
||||
|
@ -190,9 +269,11 @@ UhcControlTransfer (
|
|||
TD_STRUCT *PtrStatusTD;
|
||||
EFI_STATUS Status;
|
||||
UINT32 DataLen;
|
||||
UINT8 *PtrDataSource;
|
||||
UINT8 *Ptr;
|
||||
UINT8 DataToggle;
|
||||
UINT8 *RequestPhy;
|
||||
VOID *RequestMap;
|
||||
UINT8 *DataPhy;
|
||||
VOID *DataMap;
|
||||
|
||||
UhcDev = PEI_RECOVERY_USB_UHC_DEV_FROM_UHCI_THIS (This);
|
||||
|
||||
|
@ -216,6 +297,24 @@ UhcControlTransfer (
|
|||
|
||||
ClearStatusReg (UhcDev, StatusReg);
|
||||
|
||||
//
|
||||
// Map the Request and data for bus master access,
|
||||
// then create a list of TD for this transfer
|
||||
//
|
||||
Status = UhciMapUserRequest (UhcDev, Request, &RequestPhy, &RequestMap);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = UhciMapUserData (UhcDev, TransferDirection, Data, DataLength, &PktID, &DataPhy, &DataMap);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
if (RequestMap != NULL) {
|
||||
IoMmuUnmap (UhcDev->IoMmu, RequestMap);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// generate Setup Stage TD
|
||||
//
|
||||
|
@ -228,6 +327,7 @@ UhcControlTransfer (
|
|||
0,
|
||||
DeviceSpeed,
|
||||
(UINT8 *) Request,
|
||||
RequestPhy,
|
||||
(UINT8) sizeof (EFI_USB_DEVICE_REQUEST),
|
||||
&PtrSetupTD
|
||||
);
|
||||
|
@ -242,38 +342,11 @@ UhcControlTransfer (
|
|||
//
|
||||
// Data Stage of Control Transfer
|
||||
//
|
||||
switch (TransferDirection) {
|
||||
|
||||
case EfiUsbDataIn:
|
||||
PktID = INPUT_PACKET_ID;
|
||||
PtrDataSource = Data;
|
||||
DataLen = (UINT32) *DataLength;
|
||||
Ptr = PtrDataSource;
|
||||
break;
|
||||
|
||||
case EfiUsbDataOut:
|
||||
PktID = OUTPUT_PACKET_ID;
|
||||
PtrDataSource = Data;
|
||||
DataLen = (UINT32) *DataLength;
|
||||
Ptr = PtrDataSource;
|
||||
break;
|
||||
|
||||
//
|
||||
// no data stage
|
||||
//
|
||||
case EfiUsbNoData:
|
||||
if (*DataLength != 0) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
PktID = OUTPUT_PACKET_ID;
|
||||
PtrDataSource = NULL;
|
||||
DataLen = 0;
|
||||
Ptr = NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
return EFI_INVALID_PARAMETER;
|
||||
if (TransferDirection == EfiUsbNoData) {
|
||||
DataLen = 0;
|
||||
} else {
|
||||
DataLen = (UINT32) *DataLength;
|
||||
}
|
||||
|
||||
DataToggle = 1;
|
||||
|
@ -297,7 +370,8 @@ UhcControlTransfer (
|
|||
UhcDev,
|
||||
DeviceAddress,
|
||||
0,
|
||||
Ptr,
|
||||
Data,
|
||||
DataPhy,
|
||||
PacketSize,
|
||||
PktID,
|
||||
DataToggle,
|
||||
|
@ -312,7 +386,8 @@ UhcControlTransfer (
|
|||
PtrPreTD = PtrTD;
|
||||
|
||||
DataToggle ^= 1;
|
||||
Ptr += PacketSize;
|
||||
Data = (VOID *) ((UINT8 *) Data + PacketSize);
|
||||
DataPhy += PacketSize;
|
||||
DataLen -= PacketSize;
|
||||
}
|
||||
|
||||
|
@ -365,14 +440,19 @@ UhcControlTransfer (
|
|||
// if has errors that cause host controller halt, then return EFI_DEVICE_ERROR directly.
|
||||
//
|
||||
if (!IsStatusOK (UhcDev, StatusReg)) {
|
||||
|
||||
ClearStatusReg (UhcDev, StatusReg);
|
||||
*TransferResult |= EFI_USB_ERR_SYSTEM;
|
||||
return EFI_DEVICE_ERROR;
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
ClearStatusReg (UhcDev, StatusReg);
|
||||
|
||||
if (DataMap != NULL) {
|
||||
IoMmuUnmap (UhcDev->IoMmu, DataMap);
|
||||
}
|
||||
if (RequestMap != NULL) {
|
||||
IoMmuUnmap (UhcDev->IoMmu, RequestMap);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -431,8 +511,6 @@ UhcBulkTransfer (
|
|||
TD_STRUCT *PtrPreTD;
|
||||
|
||||
UINT8 PktID;
|
||||
UINT8 *PtrDataSource;
|
||||
UINT8 *Ptr;
|
||||
|
||||
BOOLEAN IsFirstTD;
|
||||
|
||||
|
@ -444,6 +522,9 @@ UhcBulkTransfer (
|
|||
|
||||
UINT16 CommandContent;
|
||||
|
||||
UINT8 *DataPhy;
|
||||
VOID *DataMap;
|
||||
|
||||
UhcDev = PEI_RECOVERY_USB_UHC_DEV_FROM_UHCI_THIS (This);
|
||||
|
||||
//
|
||||
|
@ -467,7 +548,6 @@ UhcBulkTransfer (
|
|||
PtrFirstTD = NULL;
|
||||
PtrPreTD = NULL;
|
||||
DataLen = 0;
|
||||
Ptr = NULL;
|
||||
|
||||
ShortPacketEnable = FALSE;
|
||||
|
||||
|
@ -495,33 +575,24 @@ UhcBulkTransfer (
|
|||
|
||||
ClearStatusReg (UhcDev, StatusReg);
|
||||
|
||||
//
|
||||
// Map the source data buffer for bus master access,
|
||||
// then create a list of TDs
|
||||
//
|
||||
if ((EndPointAddress & 0x80) != 0) {
|
||||
TransferDirection = EfiUsbDataIn;
|
||||
} else {
|
||||
TransferDirection = EfiUsbDataOut;
|
||||
}
|
||||
|
||||
switch (TransferDirection) {
|
||||
Status = UhciMapUserData (UhcDev, TransferDirection, Data, DataLength, &PktID, &DataPhy, &DataMap);
|
||||
|
||||
case EfiUsbDataIn:
|
||||
ShortPacketEnable = TRUE;
|
||||
PktID = INPUT_PACKET_ID;
|
||||
PtrDataSource = Data;
|
||||
DataLen = (UINT32) *DataLength;
|
||||
Ptr = PtrDataSource;
|
||||
break;
|
||||
|
||||
case EfiUsbDataOut:
|
||||
PktID = OUTPUT_PACKET_ID;
|
||||
PtrDataSource = Data;
|
||||
DataLen = (UINT32) *DataLength;
|
||||
Ptr = PtrDataSource;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
DataLen = (UINT32) *DataLength;
|
||||
|
||||
PtrQH = UhcDev->BulkQH;
|
||||
|
||||
IsFirstTD = TRUE;
|
||||
|
@ -540,7 +611,8 @@ UhcBulkTransfer (
|
|||
UhcDev,
|
||||
DeviceAddress,
|
||||
EndPointAddress,
|
||||
Ptr,
|
||||
Data,
|
||||
DataPhy,
|
||||
PacketSize,
|
||||
PktID,
|
||||
*DataToggle,
|
||||
|
@ -570,7 +642,8 @@ UhcBulkTransfer (
|
|||
PtrPreTD = PtrTD;
|
||||
|
||||
*DataToggle ^= 1;
|
||||
Ptr += PacketSize;
|
||||
Data = (VOID *) ((UINT8 *) Data + PacketSize);
|
||||
DataPhy += PacketSize;
|
||||
DataLen -= PacketSize;
|
||||
}
|
||||
//
|
||||
|
@ -604,14 +677,16 @@ UhcBulkTransfer (
|
|||
// if has errors that cause host controller halt, then return EFI_DEVICE_ERROR directly.
|
||||
//
|
||||
if (!IsStatusOK (UhcDev, StatusReg)) {
|
||||
|
||||
ClearStatusReg (UhcDev, StatusReg);
|
||||
*TransferResult |= EFI_USB_ERR_SYSTEM;
|
||||
return EFI_DEVICE_ERROR;
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
ClearStatusReg (UhcDev, StatusReg);
|
||||
|
||||
if (DataMap != NULL) {
|
||||
IoMmuUnmap (UhcDev->IoMmu, DataMap);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -1492,7 +1567,8 @@ CreateTD (
|
|||
@param DevAddr Device address.
|
||||
@param Endpoint Endpoint number.
|
||||
@param DeviceSpeed Device Speed.
|
||||
@param DevRequest Device reuquest.
|
||||
@param DevRequest CPU memory address of request structure buffer to transfer.
|
||||
@param RequestPhy PCI memory address of request structure buffer to transfer.
|
||||
@param RequestLen Request length.
|
||||
@param PtrTD TD_STRUCT generated.
|
||||
|
||||
|
@ -1507,6 +1583,7 @@ GenSetupStageTD (
|
|||
IN UINT8 Endpoint,
|
||||
IN UINT8 DeviceSpeed,
|
||||
IN UINT8 *DevRequest,
|
||||
IN UINT8 *RequestPhy,
|
||||
IN UINT8 RequestLen,
|
||||
OUT TD_STRUCT **PtrTD
|
||||
)
|
||||
|
@ -1583,7 +1660,11 @@ GenSetupStageTD (
|
|||
|
||||
TdStruct->PtrTDBuffer = (UINT8 *) DevRequest;
|
||||
TdStruct->TDBufferLength = RequestLen;
|
||||
SetTDDataBuffer (TdStruct);
|
||||
//
|
||||
// Set the beginning address of the buffer that will be used
|
||||
// during the transaction.
|
||||
//
|
||||
TdStruct->TDData.TDBufferPtr = (UINT32) (UINTN) RequestPhy;
|
||||
|
||||
*PtrTD = TdStruct;
|
||||
|
||||
|
@ -1596,7 +1677,8 @@ GenSetupStageTD (
|
|||
@param UhcDev The UHCI device.
|
||||
@param DevAddr Device address.
|
||||
@param Endpoint Endpoint number.
|
||||
@param PtrData Data buffer.
|
||||
@param PtrData CPU memory address of user data buffer to transfer.
|
||||
@param DataPhy PCI memory address of user data buffer to transfer.
|
||||
@param Len Data length.
|
||||
@param PktID PacketID.
|
||||
@param Toggle Data toggle value.
|
||||
|
@ -1613,6 +1695,7 @@ GenDataTD (
|
|||
IN UINT8 DevAddr,
|
||||
IN UINT8 Endpoint,
|
||||
IN UINT8 *PtrData,
|
||||
IN UINT8 *DataPhy,
|
||||
IN UINT8 Len,
|
||||
IN UINT8 PktID,
|
||||
IN UINT8 Toggle,
|
||||
|
@ -1700,7 +1783,11 @@ GenDataTD (
|
|||
|
||||
TdStruct->PtrTDBuffer = (UINT8 *) PtrData;
|
||||
TdStruct->TDBufferLength = Len;
|
||||
SetTDDataBuffer (TdStruct);
|
||||
//
|
||||
// Set the beginning address of the buffer that will be used
|
||||
// during the transaction.
|
||||
//
|
||||
TdStruct->TDData.TDBufferPtr = (UINT32) (UINTN) DataPhy;
|
||||
|
||||
*PtrTD = TdStruct;
|
||||
|
||||
|
@ -1803,7 +1890,11 @@ CreateStatusTD (
|
|||
|
||||
PtrTDStruct->PtrTDBuffer = NULL;
|
||||
PtrTDStruct->TDBufferLength = 0;
|
||||
SetTDDataBuffer (PtrTDStruct);
|
||||
//
|
||||
// Set the beginning address of the buffer that will be used
|
||||
// during the transaction.
|
||||
//
|
||||
PtrTDStruct->TDData.TDBufferPtr = 0;
|
||||
|
||||
*PtrTD = PtrTDStruct;
|
||||
|
||||
|
@ -2173,25 +2264,6 @@ SetTDTokenPacketID (
|
|||
PtrTDStruct->TDData.TDTokenPID = PacketID;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the beginning address of the data buffer that will be used
|
||||
during the transaction.
|
||||
|
||||
@param PtrTDStruct Place to store TD_STRUCT pointer.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SetTDDataBuffer (
|
||||
IN TD_STRUCT *PtrTDStruct
|
||||
)
|
||||
{
|
||||
//
|
||||
// Set the beginning address of the data buffer that will be used
|
||||
// during the transaction.
|
||||
//
|
||||
PtrTDStruct->TDData.TDBufferPtr = (UINT32) (UINTN) (PtrTDStruct->PtrTDBuffer);
|
||||
}
|
||||
|
||||
/**
|
||||
Detect whether the TD is active.
|
||||
|
||||
|
@ -2773,25 +2845,29 @@ CreateMemoryBlock (
|
|||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_PHYSICAL_ADDRESS TempPtr;
|
||||
UINT8 *TempPtr;
|
||||
UINTN MemPages;
|
||||
UINT8 *Ptr;
|
||||
VOID *Mapping;
|
||||
EFI_PHYSICAL_ADDRESS MappedAddr;
|
||||
|
||||
//
|
||||
// Memory Block uses MemoryBlockSizeInPages pages,
|
||||
// memory management header and bit array use 1 page
|
||||
//
|
||||
MemPages = MemoryBlockSizeInPages + 1;
|
||||
Status = PeiServicesAllocatePages (
|
||||
EfiBootServicesData,
|
||||
Status = IoMmuAllocateBuffer (
|
||||
UhcDev->IoMmu,
|
||||
MemPages,
|
||||
&TempPtr
|
||||
(VOID **) &TempPtr,
|
||||
&MappedAddr,
|
||||
&Mapping
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Ptr = (UINT8 *) ((UINTN) TempPtr);
|
||||
Ptr = TempPtr;
|
||||
|
||||
ZeroMem (Ptr, MemPages * EFI_PAGE_SIZE);
|
||||
|
||||
|
@ -2810,7 +2886,7 @@ CreateMemoryBlock (
|
|||
//
|
||||
// Memory block initial address
|
||||
//
|
||||
Ptr = (UINT8 *) ((UINTN) TempPtr);
|
||||
Ptr = TempPtr;
|
||||
Ptr += EFI_PAGE_SIZE;
|
||||
(*MemoryHeader)->MemoryBlockPtr = Ptr;
|
||||
//
|
||||
|
@ -3217,3 +3293,135 @@ DelinkMemoryBlock (
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Map address of request structure buffer.
|
||||
|
||||
@param Uhc The UHCI device.
|
||||
@param Request The user request buffer.
|
||||
@param MappedAddr Mapped address of request.
|
||||
@param Map Identificaion of this mapping to return.
|
||||
|
||||
@return EFI_SUCCESS Success.
|
||||
@return EFI_DEVICE_ERROR Fail to map the user request.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UhciMapUserRequest (
|
||||
IN USB_UHC_DEV *Uhc,
|
||||
IN OUT VOID *Request,
|
||||
OUT UINT8 **MappedAddr,
|
||||
OUT VOID **Map
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN Len;
|
||||
EFI_PHYSICAL_ADDRESS PhyAddr;
|
||||
|
||||
Len = sizeof (EFI_USB_DEVICE_REQUEST);
|
||||
Status = IoMmuMap (
|
||||
Uhc->IoMmu,
|
||||
EdkiiIoMmuOperationBusMasterRead,
|
||||
Request,
|
||||
&Len,
|
||||
&PhyAddr,
|
||||
Map
|
||||
);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
*MappedAddr = (UINT8 *) (UINTN) PhyAddr;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Map address of user data buffer.
|
||||
|
||||
@param Uhc The UHCI device.
|
||||
@param Direction Direction of the data transfer.
|
||||
@param Data The user data buffer.
|
||||
@param Len Length of the user data.
|
||||
@param PktId Packet identificaion.
|
||||
@param MappedAddr Mapped address to return.
|
||||
@param Map Identificaion of this mapping to return.
|
||||
|
||||
@return EFI_SUCCESS Success.
|
||||
@return EFI_DEVICE_ERROR Fail to map the user data.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UhciMapUserData (
|
||||
IN USB_UHC_DEV *Uhc,
|
||||
IN EFI_USB_DATA_DIRECTION Direction,
|
||||
IN VOID *Data,
|
||||
IN OUT UINTN *Len,
|
||||
OUT UINT8 *PktId,
|
||||
OUT UINT8 **MappedAddr,
|
||||
OUT VOID **Map
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_PHYSICAL_ADDRESS PhyAddr;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
switch (Direction) {
|
||||
case EfiUsbDataIn:
|
||||
//
|
||||
// BusMasterWrite means cpu read
|
||||
//
|
||||
*PktId = INPUT_PACKET_ID;
|
||||
Status = IoMmuMap (
|
||||
Uhc->IoMmu,
|
||||
EdkiiIoMmuOperationBusMasterWrite,
|
||||
Data,
|
||||
Len,
|
||||
&PhyAddr,
|
||||
Map
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
*MappedAddr = (UINT8 *) (UINTN) PhyAddr;
|
||||
break;
|
||||
|
||||
case EfiUsbDataOut:
|
||||
*PktId = OUTPUT_PACKET_ID;
|
||||
Status = IoMmuMap (
|
||||
Uhc->IoMmu,
|
||||
EdkiiIoMmuOperationBusMasterRead,
|
||||
Data,
|
||||
Len,
|
||||
&PhyAddr,
|
||||
Map
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
*MappedAddr = (UINT8 *) (UINTN) PhyAddr;
|
||||
break;
|
||||
|
||||
case EfiUsbNoData:
|
||||
if ((Len != NULL) && (*Len != 0)) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
*PktId = OUTPUT_PACKET_ID;
|
||||
*MappedAddr = NULL;
|
||||
*Map = NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
EXIT:
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/** @file
|
||||
Private Header file for Usb Host Controller PEIM
|
||||
|
||||
Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions
|
||||
|
@ -22,6 +22,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||
|
||||
#include <Ppi/UsbController.h>
|
||||
#include <Ppi/UsbHostController.h>
|
||||
#include <Ppi/IoMmu.h>
|
||||
#include <Ppi/EndOfPeiPhase.h>
|
||||
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/PeimEntryPoint.h>
|
||||
|
@ -177,7 +179,13 @@ struct _MEMORY_MANAGE_HEADER {
|
|||
typedef struct {
|
||||
UINTN Signature;
|
||||
PEI_USB_HOST_CONTROLLER_PPI UsbHostControllerPpi;
|
||||
EDKII_IOMMU_PPI *IoMmu;
|
||||
EFI_PEI_PPI_DESCRIPTOR PpiDescriptor;
|
||||
//
|
||||
// EndOfPei callback is used to stop the UHC DMA operation
|
||||
// after exit PEI phase.
|
||||
//
|
||||
EFI_PEI_NOTIFY_DESCRIPTOR EndOfPeiNotifyList;
|
||||
|
||||
UINT32 UsbHostControllerBaseAddress;
|
||||
FRAMELIST_ENTRY *FrameListEntry;
|
||||
|
@ -191,6 +199,7 @@ typedef struct {
|
|||
} USB_UHC_DEV;
|
||||
|
||||
#define PEI_RECOVERY_USB_UHC_DEV_FROM_UHCI_THIS(a) CR (a, USB_UHC_DEV, UsbHostControllerPpi, USB_UHC_DEV_SIGNATURE)
|
||||
#define PEI_RECOVERY_USB_UHC_DEV_FROM_THIS_NOTIFY(a) CR (a, USB_UHC_DEV, EndOfPeiNotifyList, USB_UHC_DEV_SIGNATURE)
|
||||
|
||||
/**
|
||||
Submits control transfer to a target USB device.
|
||||
|
@ -654,7 +663,8 @@ CreateTD (
|
|||
@param DevAddr Device address.
|
||||
@param Endpoint Endpoint number.
|
||||
@param DeviceSpeed Device Speed.
|
||||
@param DevRequest Device reuquest.
|
||||
@param DevRequest CPU memory address of request structure buffer to transfer.
|
||||
@param RequestPhy PCI memory address of request structure buffer to transfer.
|
||||
@param RequestLen Request length.
|
||||
@param PtrTD TD_STRUCT generated.
|
||||
|
||||
|
@ -669,6 +679,7 @@ GenSetupStageTD (
|
|||
IN UINT8 Endpoint,
|
||||
IN UINT8 DeviceSpeed,
|
||||
IN UINT8 *DevRequest,
|
||||
IN UINT8 *RequestPhy,
|
||||
IN UINT8 RequestLen,
|
||||
OUT TD_STRUCT **PtrTD
|
||||
);
|
||||
|
@ -679,7 +690,8 @@ GenSetupStageTD (
|
|||
@param UhcDev The UHCI device.
|
||||
@param DevAddr Device address.
|
||||
@param Endpoint Endpoint number.
|
||||
@param PtrData Data buffer.
|
||||
@param PtrData CPU memory address of user data buffer to transfer.
|
||||
@param DataPhy PCI memory address of user data buffer to transfer.
|
||||
@param Len Data length.
|
||||
@param PktID PacketID.
|
||||
@param Toggle Data toggle value.
|
||||
|
@ -696,6 +708,7 @@ GenDataTD (
|
|||
IN UINT8 DevAddr,
|
||||
IN UINT8 Endpoint,
|
||||
IN UINT8 *PtrData,
|
||||
IN UINT8 *DataPhy,
|
||||
IN UINT8 Len,
|
||||
IN UINT8 PktID,
|
||||
IN UINT8 Toggle,
|
||||
|
@ -1330,4 +1343,149 @@ DelinkMemoryBlock (
|
|||
IN MEMORY_MANAGE_HEADER *FreeMemoryHeader
|
||||
);
|
||||
|
||||
/**
|
||||
Map address of request structure buffer.
|
||||
|
||||
@param Uhc The UHCI device.
|
||||
@param Request The user request buffer.
|
||||
@param MappedAddr Mapped address of request.
|
||||
@param Map Identificaion of this mapping to return.
|
||||
|
||||
@return EFI_SUCCESS Success.
|
||||
@return EFI_DEVICE_ERROR Fail to map the user request.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UhciMapUserRequest (
|
||||
IN USB_UHC_DEV *Uhc,
|
||||
IN OUT VOID *Request,
|
||||
OUT UINT8 **MappedAddr,
|
||||
OUT VOID **Map
|
||||
);
|
||||
|
||||
/**
|
||||
Map address of user data buffer.
|
||||
|
||||
@param Uhc The UHCI device.
|
||||
@param Direction Direction of the data transfer.
|
||||
@param Data The user data buffer.
|
||||
@param Len Length of the user data.
|
||||
@param PktId Packet identificaion.
|
||||
@param MappedAddr Mapped address to return.
|
||||
@param Map Identificaion of this mapping to return.
|
||||
|
||||
@return EFI_SUCCESS Success.
|
||||
@return EFI_DEVICE_ERROR Fail to map the user data.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UhciMapUserData (
|
||||
IN USB_UHC_DEV *Uhc,
|
||||
IN EFI_USB_DATA_DIRECTION Direction,
|
||||
IN VOID *Data,
|
||||
IN OUT UINTN *Len,
|
||||
OUT UINT8 *PktId,
|
||||
OUT UINT8 **MappedAddr,
|
||||
OUT VOID **Map
|
||||
);
|
||||
|
||||
/**
|
||||
Provides the controller-specific addresses required to access system memory from a
|
||||
DMA bus master.
|
||||
|
||||
@param IoMmu Pointer to IOMMU PPI.
|
||||
@param Operation Indicates if the bus master is going to read or write to system memory.
|
||||
@param HostAddress The system memory address to map to the PCI controller.
|
||||
@param NumberOfBytes On input the number of bytes to map. On output the number of bytes
|
||||
that were mapped.
|
||||
@param DeviceAddress The resulting map address for the bus master PCI controller to use to
|
||||
access the hosts HostAddress.
|
||||
@param Mapping A resulting value to pass to Unmap().
|
||||
|
||||
@retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
|
||||
@retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
|
||||
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
|
||||
@retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
IoMmuMap (
|
||||
IN EDKII_IOMMU_PPI *IoMmu,
|
||||
IN EDKII_IOMMU_OPERATION Operation,
|
||||
IN VOID *HostAddress,
|
||||
IN OUT UINTN *NumberOfBytes,
|
||||
OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
|
||||
OUT VOID **Mapping
|
||||
);
|
||||
|
||||
/**
|
||||
Completes the Map() operation and releases any corresponding resources.
|
||||
|
||||
@param IoMmu Pointer to IOMMU PPI.
|
||||
@param Mapping The mapping value returned from Map().
|
||||
|
||||
**/
|
||||
VOID
|
||||
IoMmuUnmap (
|
||||
IN EDKII_IOMMU_PPI *IoMmu,
|
||||
IN VOID *Mapping
|
||||
);
|
||||
|
||||
/**
|
||||
Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
|
||||
OperationBusMasterCommonBuffer64 mapping.
|
||||
|
||||
@param IoMmu Pointer to IOMMU PPI.
|
||||
@param Pages The number of pages to allocate.
|
||||
@param HostAddress A pointer to store the base system memory address of the
|
||||
allocated range.
|
||||
@param DeviceAddress The resulting map address for the bus master PCI controller to use to
|
||||
access the hosts HostAddress.
|
||||
@param Mapping A resulting value to pass to Unmap().
|
||||
|
||||
@retval EFI_SUCCESS The requested memory pages were allocated.
|
||||
@retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
|
||||
MEMORY_WRITE_COMBINE and MEMORY_CACHED.
|
||||
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
IoMmuAllocateBuffer (
|
||||
IN EDKII_IOMMU_PPI *IoMmu,
|
||||
IN UINTN Pages,
|
||||
OUT VOID **HostAddress,
|
||||
OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
|
||||
OUT VOID **Mapping
|
||||
);
|
||||
|
||||
/**
|
||||
Frees memory that was allocated with AllocateBuffer().
|
||||
|
||||
@param IoMmu Pointer to IOMMU PPI.
|
||||
@param Pages The number of pages to free.
|
||||
@param HostAddress The base system memory address of the allocated range.
|
||||
@param Mapping The mapping value returned from Map().
|
||||
|
||||
**/
|
||||
VOID
|
||||
IoMmuFreeBuffer (
|
||||
IN EDKII_IOMMU_PPI *IoMmu,
|
||||
IN UINTN Pages,
|
||||
IN VOID *HostAddress,
|
||||
IN VOID *Mapping
|
||||
);
|
||||
|
||||
/**
|
||||
Initialize IOMMU.
|
||||
|
||||
@param IoMmu Pointer to pointer to IOMMU PPI.
|
||||
|
||||
**/
|
||||
VOID
|
||||
IoMmuInit (
|
||||
OUT EDKII_IOMMU_PPI **IoMmu
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# It produces gPeiUsbHostControllerPpiGuid based on gPeiUsbControllerPpiGuid which is used
|
||||
# to enable recovery function from USB Drivers.
|
||||
#
|
||||
# Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions
|
||||
|
@ -36,6 +36,7 @@
|
|||
[Sources]
|
||||
UhcPeim.c
|
||||
UhcPeim.h
|
||||
DmaMem.c
|
||||
|
||||
|
||||
[Packages]
|
||||
|
@ -55,6 +56,8 @@
|
|||
[Ppis]
|
||||
gPeiUsbHostControllerPpiGuid ## PRODUCES
|
||||
gPeiUsbControllerPpiGuid ## CONSUMES
|
||||
gEdkiiIoMmuPpiGuid ## CONSUMES
|
||||
gEfiEndOfPeiSignalPpiGuid ## CONSUMES
|
||||
|
||||
|
||||
[Depex]
|
||||
|
|
Loading…
Reference in New Issue