diff options
author | rsun3 <rsun3@6f19259b-4bc3-4df7-8a09-765794883524> | 2010-11-09 03:41:03 +0000 |
---|---|---|
committer | rsun3 <rsun3@6f19259b-4bc3-4df7-8a09-765794883524> | 2010-11-09 03:41:03 +0000 |
commit | aeeb84bab4d8743c3f432a93d913d38bef3f612e (patch) | |
tree | 74d146044813c9c667c483a21449bf4e646a7315 /MdeModulePkg/Bus | |
parent | 8835954602834c41db448064a7205ac0b8b66189 (diff) | |
download | edk2-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
Diffstat (limited to 'MdeModulePkg/Bus')
-rw-r--r-- | MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf | 1 | ||||
-rw-r--r-- | MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c | 137 |
2 files changed, 138 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,
|