Some existing PCI adapters with UEFI option ROMs make unaligned requests through the PCI I/O Protocol. Add support for unaligned requests in the PCI IO protocol implementation in the PCI Bus driver to be compatible with those UEFI option ROMs.

This solution defines a PCD Feature Flag to enabled support for unaligned requests through the PCI I/O Protocol.  This flag is disabled by default. Platforms that do want to support such EFI/UEFI drivers that make unaligned PCI I/O requests should enable this feature.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11016 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
rsun3 2010-11-09 03:41:03 +00:00
parent 8835954602
commit aeeb84bab4
3 changed files with 143 additions and 0 deletions

View File

@ -101,6 +101,7 @@
[FeaturePcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport
gEfiMdeModulePkgTokenSpaceGuid.PcdPciBridgeIoAlignmentProbe
gEfiMdeModulePkgTokenSpaceGuid.PcdUnalignedPciIoEnable
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSystemPageSize

View File

@ -248,6 +248,39 @@ PciIoPollMem (
return EFI_INVALID_PARAMETER;
}
//
// If request is not aligned, then convert request to EfiPciIoWithXXXUint8
//
if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {
Status = PciIoMemRead (This, Width, BarIndex, Offset, 1, Result);
if (EFI_ERROR (Status)) {
return Status;
}
if ((*Result & Mask) == Value || Delay == 0) {
return EFI_SUCCESS;
}
do {
//
// Stall 10 us = 100 * 100ns
//
gBS->Stall (10);
Status = PciIoMemRead (This, Width, BarIndex, Offset, 1, Result);
if (EFI_ERROR (Status)) {
return Status;
}
if ((*Result & Mask) == Value) {
return EFI_SUCCESS;
}
if (Delay <= 100) {
return EFI_TIMEOUT;
}
Delay -= 100;
} while (TRUE);
}
}
Status = PciIoDevice->PciRootBridgeIo->PollMem (
PciIoDevice->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
@ -314,6 +347,39 @@ PciIoPollIo (
return EFI_UNSUPPORTED;
}
//
// If request is not aligned, then convert request to EfiPciIoWithXXXUint8
//
if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {
Status = PciIoIoRead (This, Width, BarIndex, Offset, 1, Result);
if (EFI_ERROR (Status)) {
return Status;
}
if ((*Result & Mask) == Value || Delay == 0) {
return EFI_SUCCESS;
}
do {
//
// Stall 10 us = 100 * 100ns
//
gBS->Stall (10);
Status = PciIoIoRead (This, Width, BarIndex, Offset, 1, Result);
if (EFI_ERROR (Status)) {
return Status;
}
if ((*Result & Mask) == Value) {
return EFI_SUCCESS;
}
if (Delay <= 100) {
return EFI_TIMEOUT;
}
Delay -= 100;
} while (TRUE);
}
}
Status = PciIoDevice->PciRootBridgeIo->PollIo (
PciIoDevice->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
@ -380,6 +446,17 @@ PciIoMemRead (
return EFI_UNSUPPORTED;
}
//
// If request is not aligned, then convert request to EfiPciIoWithXXXUint8
//
if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {
Width &= (~0x03);
Count *= (UINTN)(1 << (Width & 0x03));
}
}
Status = PciIoDevice->PciRootBridgeIo->Mem.Read (
PciIoDevice->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
@ -444,6 +521,16 @@ PciIoMemWrite (
return EFI_UNSUPPORTED;
}
//
// If request is not aligned, then convert request to EfiPciIoWithXXXUint8
//
if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {
Width &= (~0x03);
Count *= (UINTN)(1 << (Width & 0x03));
}
}
Status = PciIoDevice->PciRootBridgeIo->Mem.Write (
PciIoDevice->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
@ -508,6 +595,16 @@ PciIoIoRead (
return EFI_UNSUPPORTED;
}
//
// If request is not aligned, then convert request to EfiPciIoWithXXXUint8
//
if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {
Width &= (~0x03);
Count *= (UINTN)(1 << (Width & 0x03));
}
}
Status = PciIoDevice->PciRootBridgeIo->Io.Read (
PciIoDevice->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
@ -572,6 +669,16 @@ PciIoIoWrite (
return EFI_UNSUPPORTED;
}
//
// If request is not aligned, then convert request to EfiPciIoWithXXXUint8
//
if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {
Width &= (~0x03);
Count *= (UINTN)(1 << (Width & 0x03));
}
}
Status = PciIoDevice->PciRootBridgeIo->Io.Write (
PciIoDevice->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
@ -627,6 +734,16 @@ PciIoConfigRead (
return Status;
}
//
// If request is not aligned, then convert request to EfiPciIoWithXXXUint8
//
if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {
Width &= (~0x03);
Count *= (UINTN)(1 << (Width & 0x03));
}
}
Status = PciIoDevice->PciRootBridgeIo->Pci.Read (
PciIoDevice->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
@ -682,6 +799,16 @@ PciIoConfigWrite (
return Status;
}
//
// If request is not aligned, then convert request to EfiPciIoWithXXXUint8
//
if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {
Width &= (~0x03);
Count *= (UINTN)(1 << (Width & 0x03));
}
}
Status = PciIoDevice->PciRootBridgeIo->Pci.Write (
PciIoDevice->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
@ -767,6 +894,16 @@ PciIoCopyMem (
return EFI_UNSUPPORTED;
}
//
// If request is not aligned, then convert request to EfiPciIoWithXXXUint8
//
if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
if ((SrcOffset & ((1 << (Width & 0x03)) - 1)) != 0 || (DestOffset & ((1 << (Width & 0x03)) - 1)) != 0) {
Width &= (~0x03);
Count *= (UINTN)(1 << (Width & 0x03));
}
}
Status = PciIoDevice->PciRootBridgeIo->CopyMem (
PciIoDevice->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,

View File

@ -269,6 +269,11 @@
## This PCD specified whether ACPI SDT protocol is installed.
gEfiMdeModulePkgTokenSpaceGuid.PcdInstallAcpiSdtProtocol|FALSE|BOOLEAN|0x0001004d
## If TRUE, then unaligned I/O, MMIO, and PCI Configuration cycles through the PCI I/O Protocol are enabled.
# If FALSE, then unaligned I/O, MMIO, and PCI Configuration cycles through the PCI I/O Protocol are disabled.
# The default value for this PCD is to disable support for unaligned PCI I/O Protocol requests.
gEfiMdeModulePkgTokenSpaceGuid.PcdUnalignedPciIoEnable|FALSE|BOOLEAN|0x0001003e
[PcdsFeatureFlag.IA32, PcdsFeatureFlag.X64]
##
# This feature flag specifies whether DxeIpl switches to long mode to enter DXE phase.