+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
-\r
-Module Name:\r
- PcatPciRootBridgeIo.c\r
- \r
-Abstract:\r
-\r
- EFI PC AT PCI Root Bridge Io Protocol\r
-\r
-Revision History\r
-\r
---*/\r
-\r
-#include "PcatPciRootBridge.h"\r
-\r
-BOOLEAN mPciOptionRomTableInstalled = FALSE;\r
-EFI_PCI_OPTION_ROM_TABLE mPciOptionRomTable = {0, NULL};\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-PcatRootBridgeIoIoRead (\r
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
- IN UINT64 UserAddress,\r
- IN UINTN Count,\r
- IN OUT VOID *UserBuffer\r
- )\r
-{\r
- return gCpuIo->Io.Read (\r
- gCpuIo,\r
- (EFI_CPU_IO_PROTOCOL_WIDTH) Width,\r
- UserAddress,\r
- Count,\r
- UserBuffer\r
- );\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-PcatRootBridgeIoIoWrite (\r
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
- IN UINT64 UserAddress,\r
- IN UINTN Count,\r
- IN OUT VOID *UserBuffer\r
- )\r
-{\r
- return gCpuIo->Io.Write (\r
- gCpuIo,\r
- (EFI_CPU_IO_PROTOCOL_WIDTH) Width,\r
- UserAddress,\r
- Count,\r
- UserBuffer\r
- );\r
-\r
-}\r
-\r
-EFI_STATUS\r
-PcatRootBridgeIoGetIoPortMapping (\r
- OUT EFI_PHYSICAL_ADDRESS *IoPortMapping,\r
- OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping\r
- )\r
-/*++\r
-\r
- Get the IO Port Mapping. For IA-32 it is always 0.\r
- \r
---*/\r
-{\r
- *IoPortMapping = 0;\r
- *MemoryPortMapping = 0;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-PcatRootBridgeIoPciRW (\r
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
- IN BOOLEAN Write,\r
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
- IN UINT64 UserAddress,\r
- IN UINTN Count,\r
- IN OUT VOID *UserBuffer\r
- )\r
-{\r
- PCI_CONFIG_ACCESS_CF8 Pci;\r
- PCI_CONFIG_ACCESS_CF8 PciAligned;\r
- UINT32 InStride;\r
- UINT32 OutStride;\r
- UINTN PciData;\r
- UINTN PciDataStride;\r
- PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
- EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress;\r
- UINT64 PciExpressRegAddr;\r
- BOOLEAN UsePciExpressAccess;\r
-\r
- if ((UINT32)Width >= EfiPciWidthMaximum) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- \r
- if ((Width & 0x03) >= EfiPciWidthUint64) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- \r
- PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
-\r
- InStride = 1 << (Width & 0x03);\r
- OutStride = InStride;\r
- if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
- InStride = 0;\r
- }\r
-\r
- if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {\r
- OutStride = 0;\r
- }\r
-\r
- UsePciExpressAccess = FALSE;\r
-\r
- CopyMem (&PciAddress, &UserAddress, sizeof(UINT64));\r
-\r
- if (PciAddress.ExtendedRegister > 0xFF) {\r
- //\r
- // Check PciExpressBaseAddress\r
- //\r
- if ((PrivateData->PciExpressBaseAddress == 0) ||\r
- (PrivateData->PciExpressBaseAddress >= MAX_ADDRESS)) {\r
- return EFI_UNSUPPORTED;\r
- } else {\r
- UsePciExpressAccess = TRUE;\r
- }\r
- } else {\r
- if (PciAddress.ExtendedRegister != 0) {\r
- Pci.Bits.Reg = PciAddress.ExtendedRegister & 0xFF;\r
- } else {\r
- Pci.Bits.Reg = PciAddress.Register;\r
- }\r
- //\r
- // Note: We can also use PciExpress access here, if wanted.\r
- //\r
- }\r
-\r
- if (!UsePciExpressAccess) {\r
- Pci.Bits.Func = PciAddress.Function;\r
- Pci.Bits.Dev = PciAddress.Device;\r
- Pci.Bits.Bus = PciAddress.Bus;\r
- Pci.Bits.Reserved = 0;\r
- Pci.Bits.Enable = 1;\r
-\r
- //\r
- // PCI Config access are all 32-bit alligned, but by accessing the\r
- // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types\r
- // are possible on PCI.\r
- //\r
- // To read a byte of PCI config space you load 0xcf8 and \r
- // read 0xcfc, 0xcfd, 0xcfe, 0xcff\r
- //\r
- PciDataStride = Pci.Bits.Reg & 0x03;\r
-\r
- while (Count) {\r
- PciAligned = Pci;\r
- PciAligned.Bits.Reg &= 0xfc;\r
- PciData = (UINTN)PrivateData->PciData + PciDataStride;\r
- EfiAcquireLock(&PrivateData->PciLock);\r
- This->Io.Write (This, EfiPciWidthUint32, PrivateData->PciAddress, 1, &PciAligned);\r
- if (Write) {\r
- This->Io.Write (This, Width, PciData, 1, UserBuffer);\r
- } else {\r
- This->Io.Read (This, Width, PciData, 1, UserBuffer);\r
- }\r
- EfiReleaseLock(&PrivateData->PciLock);\r
- UserBuffer = ((UINT8 *)UserBuffer) + OutStride;\r
- PciDataStride = (PciDataStride + InStride) % 4;\r
- Pci.Bits.Reg += InStride;\r
- Count -= 1;\r
- }\r
- } else {\r
- //\r
- // Access PCI-Express space by using memory mapped method.\r
- //\r
- PciExpressRegAddr = (PrivateData->PciExpressBaseAddress) |\r
- (PciAddress.Bus << 20) |\r
- (PciAddress.Device << 15) |\r
- (PciAddress.Function << 12);\r
- if (PciAddress.ExtendedRegister != 0) {\r
- PciExpressRegAddr += PciAddress.ExtendedRegister;\r
- } else {\r
- PciExpressRegAddr += PciAddress.Register;\r
- }\r
- while (Count) {\r
- if (Write) {\r
- This->Mem.Write (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);\r
- } else {\r
- This->Mem.Read (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);\r
- }\r
-\r
- UserBuffer = ((UINT8 *) UserBuffer) + OutStride;\r
- PciExpressRegAddr += InStride;\r
- Count -= 1;\r
- }\r
- }\r
- \r
- return EFI_SUCCESS;\r
-}\r
-\r
-VOID\r
-ScanPciBus(\r
- EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,\r
- UINT16 MinBus,\r
- UINT16 MaxBus,\r
- UINT16 MinDevice,\r
- UINT16 MaxDevice,\r
- UINT16 MinFunc,\r
- UINT16 MaxFunc,\r
- EFI_PCI_BUS_SCAN_CALLBACK Callback,\r
- VOID *Context\r
- )\r
- \r
-{\r
- UINT16 Bus;\r
- UINT16 Device;\r
- UINT16 Func;\r
- UINT64 Address;\r
- PCI_TYPE00 PciHeader;\r
-\r
- //\r
- // Loop through all busses\r
- //\r
- for (Bus = MinBus; Bus <= MaxBus; Bus++) {\r
- // \r
- // Loop 32 devices per bus\r
- //\r
- for (Device = MinDevice; Device <= MaxDevice; Device++) {\r
- //\r
- // Loop through 8 functions per device\r
- //\r
- for (Func = MinFunc; Func <= MaxFunc; Func++) {\r
-\r
- //\r
- // Compute the EFI Address required to access the PCI Configuration Header of this PCI Device\r
- //\r
- Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);\r
-\r
- //\r
- // Read the VendorID from this PCI Device's Confioguration Header\r
- //\r
- IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &PciHeader.Hdr.VendorId);\r
- \r
- //\r
- // If VendorId = 0xffff, there does not exist a device at this \r
- // location. For each device, if there is any function on it, \r
- // there must be 1 function at Function 0. So if Func = 0, there\r
- // will be no more functions in the same device, so we can break\r
- // loop to deal with the next device.\r
- // \r
- if (PciHeader.Hdr.VendorId == 0xffff && Func == 0) {\r
- break;\r
- }\r
- \r
- if (PciHeader.Hdr.VendorId != 0xffff) {\r
-\r
- //\r
- // Read the HeaderType to determine if this is a multi-function device\r
- //\r
- IoDev->Pci.Read (IoDev, EfiPciWidthUint8, Address + 0x0e, 1, &PciHeader.Hdr.HeaderType);\r
-\r
- //\r
- // Call the callback function for the device that was found\r
- //\r
- Callback(\r
- IoDev, \r
- MinBus, MaxBus,\r
- MinDevice, MaxDevice,\r
- MinFunc, MaxFunc,\r
- Bus,\r
- Device,\r
- Func,\r
- Context\r
- );\r
-\r
- //\r
- // If this is not a multi-function device, we can leave the loop \r
- // to deal with the next device.\r
- //\r
- if ((PciHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x00 && Func == 0) {\r
- break;\r
- }\r
- } \r
- }\r
- }\r
- }\r
-}\r
-\r
-VOID\r
-CheckForRom (\r
- EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,\r
- UINT16 MinBus,\r
- UINT16 MaxBus,\r
- UINT16 MinDevice,\r
- UINT16 MaxDevice,\r
- UINT16 MinFunc,\r
- UINT16 MaxFunc,\r
- UINT16 Bus,\r
- UINT16 Device,\r
- UINT16 Func,\r
- IN VOID *VoidContext\r
- )\r
-{\r
- EFI_STATUS Status;\r
- PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;\r
- UINT64 Address;\r
- PCI_TYPE00 PciHeader;\r
- PCI_TYPE01 *PciBridgeHeader;\r
- UINT32 Register;\r
- UINT32 RomBar;\r
- UINT32 RomBarSize;\r
- EFI_PHYSICAL_ADDRESS RomBuffer;\r
- UINT32 MaxRomSize;\r
- EFI_PCI_EXPANSION_ROM_HEADER EfiRomHeader;\r
- PCI_DATA_STRUCTURE Pcir;\r
- EFI_PCI_OPTION_ROM_DESCRIPTOR *TempPciOptionRomDescriptors;\r
- BOOLEAN LastImage;\r
-\r
- Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;\r
-\r
- Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);\r
-\r
- //\r
- // Save the contents of the PCI Configuration Header\r
- //\r
- IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);\r
-\r
- if (IS_PCI_BRIDGE(&PciHeader)) {\r
-\r
- PciBridgeHeader = (PCI_TYPE01 *)(&PciHeader);\r
-\r
- //\r
- // See if the PCI-PCI Bridge has its secondary interface enabled.\r
- //\r
- if (PciBridgeHeader->Bridge.SubordinateBus >= PciBridgeHeader->Bridge.SecondaryBus) {\r
-\r
- //\r
- // Disable the Prefetchable Memory Window\r
- //\r
- Register = 0x00000000;\r
- IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x26, 1, &Register);\r
- IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x2c, 1, &Register);\r
- Register = 0xffffffff;\r
- IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x24, 1, &Register);\r
- IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x28, 1, &Register);\r
-\r
- //\r
- // Program Memory Window to the PCI Root Bridge Memory Window\r
- //\r
- IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x20, 4, &Context->PpbMemoryWindow);\r
-\r
- //\r
- // Enable the Memory decode for the PCI-PCI Bridge\r
- //\r
- IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);\r
- Register |= 0x02;\r
- IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);\r
-\r
- //\r
- // Recurse on the Secondary Bus Number\r
- //\r
- ScanPciBus(\r
- IoDev,\r
- PciBridgeHeader->Bridge.SecondaryBus, PciBridgeHeader->Bridge.SecondaryBus, \r
- 0, PCI_MAX_DEVICE, \r
- 0, PCI_MAX_FUNC, \r
- CheckForRom, Context\r
- );\r
- }\r
- } else {\r
-\r
- //\r
- // Check if an Option ROM Register is present and save the Option ROM Window Register\r
- //\r
- RomBar = 0xffffffff;\r
- IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);\r
- IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);\r
-\r
- RomBarSize = (~(RomBar & 0xfffff800)) + 1;\r
-\r
- //\r
- // Make sure the size of the ROM is between 0 and 16 MB\r
- //\r
- if (RomBarSize > 0 && RomBarSize <= 0x01000000) {\r
-\r
- //\r
- // Program Option ROM Window Register to the PCI Root Bridge Window and Enable the Option ROM Window\r
- //\r
- RomBar = (Context->PpbMemoryWindow & 0xffff) << 16;\r
- RomBar = ((RomBar - 1) & (~(RomBarSize - 1))) + RomBarSize;\r
- if (RomBar < (Context->PpbMemoryWindow & 0xffff0000)) {\r
- MaxRomSize = (Context->PpbMemoryWindow & 0xffff0000) - RomBar;\r
- RomBar = RomBar + 1;\r
- IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);\r
- IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);\r
- RomBar = RomBar - 1;\r
-\r
- //\r
- // Enable the Memory decode for the PCI Device\r
- //\r
- IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);\r
- Register |= 0x02;\r
- IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);\r
-\r
- //\r
- // Follow the chain of images to determine the size of the Option ROM present\r
- // Keep going until the last image is found by looking at the Indicator field\r
- // or the size of an image is 0, or the size of all the images is bigger than the\r
- // size of the window programmed into the PPB.\r
- //\r
- RomBarSize = 0;\r
- do {\r
-\r
- LastImage = TRUE;\r
-\r
- ZeroMem (&EfiRomHeader, sizeof(EfiRomHeader));\r
- IoDev->Mem.Read (\r
- IoDev, \r
- EfiPciWidthUint8, \r
- RomBar + RomBarSize, \r
- sizeof(EfiRomHeader),\r
- &EfiRomHeader\r
- );\r
-\r
- Pcir.ImageLength = 0;\r
-\r
- if (EfiRomHeader.Signature == PCI_EXPANSION_ROM_HEADER_SIGNATURE &&\r
- EfiRomHeader.PcirOffset != 0 &&\r
- (EfiRomHeader.PcirOffset & 3) == 0 &&\r
- RomBarSize + EfiRomHeader.PcirOffset + sizeof (PCI_DATA_STRUCTURE) <= MaxRomSize) {\r
- ZeroMem (&Pcir, sizeof(Pcir));\r
- IoDev->Mem.Read (\r
- IoDev, \r
- EfiPciWidthUint8, \r
- RomBar + RomBarSize + EfiRomHeader.PcirOffset, \r
- sizeof(Pcir),\r
- &Pcir\r
- );\r
-\r
- if (Pcir.Signature != PCI_DATA_STRUCTURE_SIGNATURE) {\r
- break;\r
- }\r
- if (RomBarSize + Pcir.ImageLength * 512 > MaxRomSize) {\r
- break;\r
- }\r
- if ((Pcir.Indicator & 0x80) == 0x00) {\r
- LastImage = FALSE;\r
- }\r
-\r
- RomBarSize += Pcir.ImageLength * 512;\r
- }\r
- } while (!LastImage && RomBarSize < MaxRomSize && Pcir.ImageLength !=0);\r
-\r
- if (RomBarSize > 0) {\r
-\r
- //\r
- // Allocate a memory buffer for the Option ROM contents.\r
- //\r
- Status = gBS->AllocatePages(\r
- AllocateAnyPages,\r
- EfiBootServicesData,\r
- EFI_SIZE_TO_PAGES(RomBarSize),\r
- &RomBuffer\r
- );\r
-\r
- if (!EFI_ERROR (Status)) {\r
-\r
- //\r
- // Copy the contents of the Option ROM to the memory buffer\r
- //\r
- IoDev->Mem.Read (IoDev, EfiPciWidthUint32, RomBar, RomBarSize / sizeof(UINT32), (VOID *)(UINTN)RomBuffer);\r
-\r
- Status = gBS->AllocatePool(\r
- EfiBootServicesData,\r
- ((UINT32)mPciOptionRomTable.PciOptionRomCount + 1) * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR),\r
- (VOID **) &TempPciOptionRomDescriptors\r
- );\r
- if (mPciOptionRomTable.PciOptionRomCount > 0) {\r
- CopyMem(\r
- TempPciOptionRomDescriptors, \r
- mPciOptionRomTable.PciOptionRomDescriptors, \r
- (UINT32)mPciOptionRomTable.PciOptionRomCount * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR)\r
- );\r
-\r
- gBS->FreePool(mPciOptionRomTable.PciOptionRomDescriptors);\r
- }\r
-\r
- mPciOptionRomTable.PciOptionRomDescriptors = TempPciOptionRomDescriptors; \r
-\r
- TempPciOptionRomDescriptors = &(mPciOptionRomTable.PciOptionRomDescriptors[(UINT32)mPciOptionRomTable.PciOptionRomCount]);\r
-\r
- TempPciOptionRomDescriptors->RomAddress = RomBuffer;\r
- TempPciOptionRomDescriptors->MemoryType = EfiBootServicesData;\r
- TempPciOptionRomDescriptors->RomLength = RomBarSize;\r
- TempPciOptionRomDescriptors->Seg = (UINT32)IoDev->SegmentNumber;\r
- TempPciOptionRomDescriptors->Bus = (UINT8)Bus;\r
- TempPciOptionRomDescriptors->Dev = (UINT8)Device;\r
- TempPciOptionRomDescriptors->Func = (UINT8)Func;\r
- TempPciOptionRomDescriptors->ExecutedLegacyBiosImage = TRUE;\r
- TempPciOptionRomDescriptors->DontLoadEfiRom = FALSE;\r
-\r
- mPciOptionRomTable.PciOptionRomCount++;\r
- }\r
- }\r
-\r
- //\r
- // Disable the Memory decode for the PCI-PCI Bridge\r
- //\r
- IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);\r
- Register &= (~0x02);\r
- IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);\r
- }\r
- }\r
- }\r
-\r
- //\r
- // Restore the PCI Configuration Header \r
- //\r
- IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);\r
-}\r
-\r
-VOID\r
-SaveCommandRegister (\r
- EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,\r
- UINT16 MinBus,\r
- UINT16 MaxBus,\r
- UINT16 MinDevice,\r
- UINT16 MaxDevice,\r
- UINT16 MinFunc,\r
- UINT16 MaxFunc,\r
- UINT16 Bus,\r
- UINT16 Device,\r
- UINT16 Func,\r
- IN VOID *VoidContext\r
- )\r
-\r
-{\r
- PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;\r
- UINT64 Address;\r
- UINTN Index;\r
- UINT16 Command;\r
-\r
- Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;\r
-\r
- Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);\r
-\r
- Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;\r
-\r
- IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);\r
-\r
- //\r
- // Clear the memory enable bit\r
- //\r
- Command = (UINT16) (Context->CommandRegisterBuffer[Index] & (~0x02));\r
-\r
- IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Command);\r
-}\r
-\r
-VOID\r
-RestoreCommandRegister (\r
- EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,\r
- UINT16 MinBus,\r
- UINT16 MaxBus,\r
- UINT16 MinDevice,\r
- UINT16 MaxDevice,\r
- UINT16 MinFunc,\r
- UINT16 MaxFunc,\r
- UINT16 Bus,\r
- UINT16 Device,\r
- UINT16 Func,\r
- IN VOID *VoidContext\r
- )\r
-\r
-{\r
- PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;\r
- UINT64 Address;\r
- UINTN Index;\r
-\r
- Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;\r
-\r
- Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);\r
-\r
- Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;\r
-\r
- IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);\r
-}\r
-\r
-EFI_STATUS\r
-ScanPciRootBridgeForRoms(\r
- EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev\r
- )\r
- \r
-{\r
- EFI_STATUS Status;\r
- EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors; \r
- UINT16 MinBus;\r
- UINT16 MaxBus;\r
- UINT64 RootWindowBase;\r
- UINT64 RootWindowLimit;\r
- PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT Context;\r
-\r
- if (mPciOptionRomTableInstalled == FALSE) {\r
- gBS->InstallConfigurationTable(&gEfiPciOptionRomTableGuid, &mPciOptionRomTable);\r
- mPciOptionRomTableInstalled = TRUE;\r
- }\r
-\r
- Status = IoDev->Configuration(IoDev, (VOID **) &Descriptors);\r
- if (EFI_ERROR (Status) || Descriptors == NULL) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- MinBus = 0xffff;\r
- MaxBus = 0xffff;\r
- RootWindowBase = 0;\r
- RootWindowLimit = 0;\r
- while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
- //\r
- // Find bus range\r
- //\r
- if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {\r
- MinBus = (UINT16)Descriptors->AddrRangeMin;\r
- MaxBus = (UINT16)Descriptors->AddrRangeMax;\r
- }\r
- //\r
- // Find memory descriptors that are not prefetchable\r
- //\r
- if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM && Descriptors->SpecificFlag == 0) {\r
- //\r
- // Find Memory Descriptors that are less than 4GB, so the PPB Memory Window can be used for downstream devices\r
- //\r
- if (Descriptors->AddrRangeMax < 0x100000000ULL) {\r
- //\r
- // Find the largest Non-Prefetchable Memory Descriptor that is less than 4GB\r
- //\r
- if ((Descriptors->AddrRangeMax - Descriptors->AddrRangeMin) > (RootWindowLimit - RootWindowBase)) {\r
- RootWindowBase = Descriptors->AddrRangeMin;\r
- RootWindowLimit = Descriptors->AddrRangeMax;\r
- }\r
- }\r
- }\r
- Descriptors ++;\r
- }\r
-\r
- //\r
- // Make sure a bus range was found\r
- //\r
- if (MinBus == 0xffff || MaxBus == 0xffff) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- //\r
- // Make sure a non-prefetchable memory region was found\r
- //\r
- if (RootWindowBase == 0 && RootWindowLimit == 0) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- //\r
- // Round the Base and Limit values to 1 MB boudaries\r
- //\r
- RootWindowBase = ((RootWindowBase - 1) & 0xfff00000) + 0x00100000;\r
- RootWindowLimit = ((RootWindowLimit + 1) & 0xfff00000) - 1;\r
-\r
- //\r
- // Make sure that the size of the rounded window is greater than zero\r
- //\r
- if (RootWindowLimit <= RootWindowBase) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- //\r
- // Allocate buffer to save the Command register from all the PCI devices\r
- //\r
- Context.CommandRegisterBuffer = NULL;\r
- Status = gBS->AllocatePool(\r
- EfiBootServicesData,\r
- sizeof(UINT16) * (MaxBus - MinBus + 1) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1),\r
- (VOID **) &Context.CommandRegisterBuffer\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Context.PpbMemoryWindow = (((UINT32)RootWindowBase) >> 16) | ((UINT32)RootWindowLimit & 0xffff0000);\r
-\r
- //\r
- // Save the Command register from all the PCI devices, and disable the I/O, Mem, and BusMaster bits\r
- //\r
- ScanPciBus(\r
- IoDev,\r
- MinBus, MaxBus, \r
- 0, PCI_MAX_DEVICE, \r
- 0, PCI_MAX_FUNC, \r
- SaveCommandRegister, &Context\r
- );\r
-\r
- //\r
- // Recursively scan all the busses for PCI Option ROMs\r
- //\r
- ScanPciBus(\r
- IoDev,\r
- MinBus, MinBus, \r
- 0, PCI_MAX_DEVICE, \r
- 0, PCI_MAX_FUNC, \r
- CheckForRom, &Context\r
- );\r
-\r
- //\r
- // Restore the Command register in all the PCI devices\r
- //\r
- ScanPciBus(\r
- IoDev,\r
- MinBus, MaxBus, \r
- 0, PCI_MAX_DEVICE, \r
- 0, PCI_MAX_FUNC, \r
- RestoreCommandRegister, &Context\r
- );\r
-\r
- //\r
- // Free the buffer used to save all the Command register values\r
- //\r
- gBS->FreePool(Context.CommandRegisterBuffer);\r
-\r
- return EFI_SUCCESS;\r
-}\r