summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrsun3 <rsun3@6f19259b-4bc3-4df7-8a09-765794883524>2010-11-09 03:41:03 +0000
committerrsun3 <rsun3@6f19259b-4bc3-4df7-8a09-765794883524>2010-11-09 03:41:03 +0000
commitaeeb84bab4d8743c3f432a93d913d38bef3f612e (patch)
tree74d146044813c9c667c483a21449bf4e646a7315
parent8835954602834c41db448064a7205ac0b8b66189 (diff)
downloadedk2-platforms-aeeb84bab4d8743c3f432a93d913d38bef3f612e.tar.xz
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
-rw-r--r--MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf1
-rw-r--r--MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c137
-rw-r--r--MdeModulePkg/MdeModulePkg.dec5
3 files changed, 143 insertions, 0 deletions
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
index 7096b11618..3c581ec27d 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
@@ -101,6 +101,7 @@
[FeaturePcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport
gEfiMdeModulePkgTokenSpaceGuid.PcdPciBridgeIoAlignmentProbe
+ gEfiMdeModulePkgTokenSpaceGuid.PcdUnalignedPciIoEnable
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSystemPageSize
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c
index 310cedad04..e7d4ae3e55 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c
@@ -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,
@@ -626,6 +733,16 @@ PciIoConfigRead (
if (EFI_ERROR (Status)) {
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,
@@ -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,
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index e26ff142c8..aa805630c3 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -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.