From aeeb84bab4d8743c3f432a93d913d38bef3f612e Mon Sep 17 00:00:00 2001 From: rsun3 Date: Tue, 9 Nov 2010 03:41:03 +0000 Subject: [PATCH] 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 --- MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf | 1 + MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c | 137 +++++++++++++++++++ MdeModulePkg/MdeModulePkg.dec | 5 + 3 files changed, 143 insertions(+) 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. -- 2.39.2