summaryrefslogtreecommitdiff
path: root/DuetPkg/PciRootBridgeNoEnumerationDxe
diff options
context:
space:
mode:
Diffstat (limited to 'DuetPkg/PciRootBridgeNoEnumerationDxe')
-rw-r--r--DuetPkg/PciRootBridgeNoEnumerationDxe/DeviceIo.c845
-rw-r--r--DuetPkg/PciRootBridgeNoEnumerationDxe/DeviceIo.h449
-rw-r--r--DuetPkg/PciRootBridgeNoEnumerationDxe/Ia32/PcatIo.c734
-rw-r--r--DuetPkg/PciRootBridgeNoEnumerationDxe/Ipf/PcatIo.c459
-rw-r--r--DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.c1018
-rw-r--r--DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.h215
-rw-r--r--DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeDevicePath.c87
-rw-r--r--DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeIo.c1054
-rw-r--r--DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf70
-rw-r--r--DuetPkg/PciRootBridgeNoEnumerationDxe/x64/PcatIo.c732
10 files changed, 5663 insertions, 0 deletions
diff --git a/DuetPkg/PciRootBridgeNoEnumerationDxe/DeviceIo.c b/DuetPkg/PciRootBridgeNoEnumerationDxe/DeviceIo.c
new file mode 100644
index 0000000000..286c03ef4c
--- /dev/null
+++ b/DuetPkg/PciRootBridgeNoEnumerationDxe/DeviceIo.c
@@ -0,0 +1,845 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ DeviceIo.c
+
+Abstract:
+
+ EFI PC-AT PCI Device IO driver
+
+--*/
+#include "PcatPciRootBridge.h"
+#include "DeviceIo.h"
+
+EFI_STATUS
+DeviceIoConstructor (
+ IN EFI_HANDLE Handle,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN UINT16 PrimaryBus,
+ IN UINT16 SubordinateBus
+ )
+/*++
+
+Routine Description:
+
+ Initialize and install a Device IO protocol on a empty device path handle.
+
+Arguments:
+
+ Handle - Handle of PCI RootBridge IO instance
+ PciRootBridgeIo - PCI RootBridge IO instance
+ DevicePath - Device Path of PCI RootBridge IO instance
+ PrimaryBus - Primary Bus
+ SubordinateBus - Subordinate Bus
+
+Returns:
+
+ EFI_SUCCESS - This driver is added to ControllerHandle.
+ EFI_ALREADY_STARTED - This driver is already running on ControllerHandle.
+ Others - This driver does not support this device.
+
+--*/
+{
+ EFI_STATUS Status;
+ DEVICE_IO_PRIVATE_DATA *Private;
+
+ //
+ // Initialize the Device IO device instance.
+ //
+ Private = AllocateZeroPool (sizeof (DEVICE_IO_PRIVATE_DATA));
+ if (Private == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Private->Signature = DEVICE_IO_PRIVATE_DATA_SIGNATURE;
+ Private->Handle = Handle;
+ Private->PciRootBridgeIo = PciRootBridgeIo;
+ Private->DevicePath = DevicePath;
+ Private->PrimaryBus = PrimaryBus;
+ Private->SubordinateBus = SubordinateBus;
+
+ Private->DeviceIo.Mem.Read = DeviceIoMemRead;
+ Private->DeviceIo.Mem.Write = DeviceIoMemWrite;
+ Private->DeviceIo.Io.Read = DeviceIoIoRead;
+ Private->DeviceIo.Io.Write = DeviceIoIoWrite;
+ Private->DeviceIo.Pci.Read = DeviceIoPciRead;
+ Private->DeviceIo.Pci.Write = DeviceIoPciWrite;
+ Private->DeviceIo.PciDevicePath = DeviceIoPciDevicePath;
+ Private->DeviceIo.Map = DeviceIoMap;
+ Private->DeviceIo.Unmap = DeviceIoUnmap;
+ Private->DeviceIo.AllocateBuffer = DeviceIoAllocateBuffer;
+ Private->DeviceIo.Flush = DeviceIoFlush;
+ Private->DeviceIo.FreeBuffer = DeviceIoFreeBuffer;
+
+ //
+ // Install protocol interfaces for the Device IO device.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Private->Handle,
+ &gEfiDeviceIoProtocolGuid,
+ &Private->DeviceIo,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoMemRead (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform reading memory mapped I/O space of device.
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO protocol instance.
+ Width - Width of I/O operations.
+ Address - The base address of I/O operations.
+ Count - The number of I/O operations to perform.
+ Bytes moves is Width size * Count, starting at Address.
+ Buffer - The destination buffer to store results.
+
+Returns:
+
+ EFI_SUCCESS - The data was read from the device.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
+
+--*/
+{
+ EFI_STATUS Status;
+ DEVICE_IO_PRIVATE_DATA *Private;
+
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ if (Width > MMIO_COPY_UINT64) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Width >= MMIO_COPY_UINT8) {
+ Width = Width - MMIO_COPY_UINT8;
+ Status = Private->PciRootBridgeIo->CopyMem (
+ Private->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ (UINT64) Buffer,
+ Address,
+ Count
+ );
+ } else {
+ Status = Private->PciRootBridgeIo->Mem.Read (
+ Private->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Address,
+ Count,
+ Buffer
+ );
+ }
+
+ return Status;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+DeviceIoMemWrite (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform writing memory mapped I/O space of device.
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO protocol instance.
+ Width - Width of I/O operations.
+ Address - The base address of I/O operations.
+ Count - The number of I/O operations to perform.
+ Bytes moves is Width size * Count, starting at Address.
+ Buffer - The source buffer of data to be written.
+
+Returns:
+
+ EFI_SUCCESS - The data was written to the device.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
+
+--*/
+{
+ EFI_STATUS Status;
+ DEVICE_IO_PRIVATE_DATA *Private;
+
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ if (Width > MMIO_COPY_UINT64) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Width >= MMIO_COPY_UINT8) {
+ Width = Width - MMIO_COPY_UINT8;
+ Status = Private->PciRootBridgeIo->CopyMem (
+ Private->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Address,
+ (UINT64) Buffer,
+ Count
+ );
+ } else {
+ Status = Private->PciRootBridgeIo->Mem.Write (
+ Private->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Address,
+ Count,
+ Buffer
+ );
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoIoRead (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform reading I/O space of device.
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO protocol instance.
+ Width - Width of I/O operations.
+ Address - The base address of I/O operations.
+ Count - The number of I/O operations to perform.
+ Bytes moves is Width size * Count, starting at Address.
+ Buffer - The destination buffer to store results.
+
+Returns:
+
+ EFI_SUCCESS - The data was read from the device.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
+
+--*/
+{
+ EFI_STATUS Status;
+ DEVICE_IO_PRIVATE_DATA *Private;
+
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ if (Width >= MMIO_COPY_UINT8) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = Private->PciRootBridgeIo->Io.Read (
+ Private->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Address,
+ Count,
+ Buffer
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoIoWrite (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform writing I/O space of device.
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO protocol instance.
+ Width - Width of I/O operations.
+ Address - The base address of I/O operations.
+ Count - The number of I/O operations to perform.
+ Bytes moves is Width size * Count, starting at Address.
+ Buffer - The source buffer of data to be written.
+
+Returns:
+
+ EFI_SUCCESS - The data was written to the device.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
+
+--*/
+{
+ EFI_STATUS Status;
+ DEVICE_IO_PRIVATE_DATA *Private;
+
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ if (Width >= MMIO_COPY_UINT8) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = Private->PciRootBridgeIo->Io.Write (
+ Private->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Address,
+ Count,
+ Buffer
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoPciRead (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform reading PCI configuration space of device
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO protocol instance.
+ Width - Width of I/O operations.
+ Address - The base address of I/O operations.
+ Count - The number of I/O operations to perform.
+ Bytes moves is Width size * Count, starting at Address.
+ Buffer - The destination buffer to store results.
+
+Returns:
+
+ EFI_SUCCESS - The data was read from the device.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
+
+--*/
+{
+ EFI_STATUS Status;
+ DEVICE_IO_PRIVATE_DATA *Private;
+
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ if (Width < 0 || Width >= MMIO_COPY_UINT8) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = Private->PciRootBridgeIo->Pci.Read (
+ Private->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Address,
+ Count,
+ Buffer
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoPciWrite (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform writing PCI configuration space of device.
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO protocol instance.
+ Width - Width of I/O operations.
+ Address - The base address of I/O operations.
+ Count - The number of I/O operations to perform.
+ Bytes moves is Width size * Count, starting at Address.
+ Buffer - The source buffer of data to be written.
+
+Returns:
+
+ EFI_SUCCESS - The data was written to the device.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
+
+--*/
+{
+ EFI_STATUS Status;
+ DEVICE_IO_PRIVATE_DATA *Private;
+
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ if (Width < 0 || Width >= MMIO_COPY_UINT8) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = Private->PciRootBridgeIo->Pci.Write (
+ Private->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Address,
+ Count,
+ Buffer
+ );
+
+ return Status;
+}
+
+EFI_DEVICE_PATH_PROTOCOL *
+AppendPciDevicePath (
+ IN DEVICE_IO_PRIVATE_DATA *Private,
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN OUT UINT16 *BridgePrimaryBus,
+ IN OUT UINT16 *BridgeSubordinateBus
+ )
+/*++
+
+Routine Description:
+
+ Append a PCI device path node to another device path.
+
+Arguments:
+
+ Private - A pointer to DEVICE_IO_PRIVATE_DATA instance.
+ Bus - PCI bus number of the device.
+ Device - PCI device number of the device.
+ Function - PCI function number of the device.
+ DevicePath - Original device path which will be appended a PCI device path node.
+ BridgePrimaryBus - Primary bus number of the bridge.
+ BridgeSubordinateBus - Subordinate bus number of the bridge.
+
+Returns:
+
+ Pointer to the appended PCI device path.
+
+--*/
+{
+ UINT16 ThisBus;
+ UINT8 ThisDevice;
+ UINT8 ThisFunc;
+ UINT64 Address;
+ PCI_TYPE01 PciBridge;
+ PCI_TYPE01 *PciPtr;
+ EFI_DEVICE_PATH_PROTOCOL *ReturnDevicePath;
+ PCI_DEVICE_PATH PciNode;
+
+ PciPtr = &PciBridge;
+ for (ThisBus = *BridgePrimaryBus; ThisBus <= *BridgeSubordinateBus; ThisBus++) {
+ for (ThisDevice = 0; ThisDevice <= PCI_MAX_DEVICE; ThisDevice++) {
+ for (ThisFunc = 0; ThisFunc <= PCI_MAX_FUNC; ThisFunc++) {
+ Address = EFI_PCI_ADDRESS (ThisBus, ThisDevice, ThisFunc, 0);
+ ZeroMem (PciPtr, sizeof (PCI_TYPE01));
+ Private->DeviceIo.Pci.Read (
+ &Private->DeviceIo,
+ IO_UINT32,
+ Address,
+ 1,
+ &(PciPtr->Hdr.VendorId)
+ );
+ if ((PciPtr->Hdr.VendorId == 0xffff) && (ThisFunc == 0)) {
+ break;
+ }
+ if (PciPtr->Hdr.VendorId == 0xffff) {
+ continue;
+ }
+
+ Private->DeviceIo.Pci.Read (
+ &Private->DeviceIo,
+ IO_UINT32,
+ Address,
+ sizeof (PCI_TYPE01) / sizeof (UINT32),
+ PciPtr
+ );
+ if (IS_PCI_BRIDGE (PciPtr)) {
+ if (Bus >= PciPtr->Bridge.SecondaryBus && Bus <= PciPtr->Bridge.SubordinateBus) {
+
+ PciNode.Header.Type = HARDWARE_DEVICE_PATH;
+ PciNode.Header.SubType = HW_PCI_DP;
+ SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
+
+ PciNode.Device = ThisDevice;
+ PciNode.Function = ThisFunc;
+ ReturnDevicePath = AppendDevicePathNode (DevicePath, &PciNode.Header);
+
+ *BridgePrimaryBus = PciPtr->Bridge.SecondaryBus;
+ *BridgeSubordinateBus = PciPtr->Bridge.SubordinateBus;
+ return ReturnDevicePath;
+ }
+ }
+
+ if ((ThisFunc == 0) && ((PciPtr->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x0)) {
+ //
+ // Skip sub functions, this is not a multi function device
+ //
+ break;
+ }
+ }
+ }
+ }
+
+ ZeroMem (&PciNode, sizeof (PciNode));
+ PciNode.Header.Type = HARDWARE_DEVICE_PATH;
+ PciNode.Header.SubType = HW_PCI_DP;
+ SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
+ PciNode.Device = Device;
+ PciNode.Function = Function;
+
+ ReturnDevicePath = AppendDevicePathNode (DevicePath, &PciNode.Header);
+
+ *BridgePrimaryBus = 0xffff;
+ *BridgeSubordinateBus = 0xffff;
+ return ReturnDevicePath;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoPciDevicePath (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN UINT64 Address,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **PciDevicePath
+ )
+/*++
+
+Routine Description:
+
+ Provides an EFI Device Path for a PCI device with the given PCI configuration space address.
+
+Arguments:
+
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+ Address - The PCI configuration space address of the device whose Device Path
+ is going to be returned.
+ PciDevicePath - A pointer to the pointer for the EFI Device Path for PciAddress.
+ Memory for the Device Path is allocated from the pool.
+
+Returns:
+
+ EFI_SUCCESS - The PciDevicePath returns a pointer to a valid EFI Device Path.
+ EFI_UNSUPPORTED - The PciAddress does not map to a valid EFI Device Path.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
+
+--*/
+{
+ DEVICE_IO_PRIVATE_DATA *Private;
+ UINT16 PrimaryBus;
+ UINT16 SubordinateBus;
+ UINT8 Bus;
+ UINT8 Device;
+ UINT8 Func;
+
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ Bus = (UINT8) (((UINT32) Address >> 24) & 0xff);
+ Device = (UINT8) (((UINT32) Address >> 16) & 0xff);
+ Func = (UINT8) (((UINT32) Address >> 8) & 0xff);
+
+ if (Bus < Private->PrimaryBus || Bus > Private->SubordinateBus) {
+ return EFI_UNSUPPORTED;
+ }
+
+ *PciDevicePath = Private->DevicePath;
+ PrimaryBus = Private->PrimaryBus;
+ SubordinateBus = Private->SubordinateBus;
+ do {
+ *PciDevicePath = AppendPciDevicePath (
+ Private,
+ Bus,
+ Device,
+ Func,
+ *PciDevicePath,
+ &PrimaryBus,
+ &SubordinateBus
+ );
+ if (*PciDevicePath == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } while (PrimaryBus != 0xffff);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoMap (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_OPERATION_TYPE Operation,
+ IN EFI_PHYSICAL_ADDRESS *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+/*++
+
+Routine Description:
+
+ Provides the device-specific addresses needed to access system memory.
+
+Arguments:
+
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+ Operation - Indicates if the bus master is going to read or write to system memory.
+ HostAddress - The system memory address to map to the device.
+ NumberOfBytes - On input the number of bytes to map. On output the number of bytes
+ that were mapped.
+ DeviceAddress - The resulting map address for the bus master device to use to access the
+ hosts HostAddress.
+ Mapping - A resulting value to pass to Unmap().
+
+Returns:
+
+ EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
+ EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
+ EFI_UNSUPPORTED - The HostAddress cannot be mapped as a common buffer.
+ EFI_DEVICE_ERROR - The system hardware could not map the requested address.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
+
+--*/
+{
+ EFI_STATUS Status;
+ DEVICE_IO_PRIVATE_DATA *Private;
+
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ if (Operation < 0 || Operation > EfiBusMasterCommonBuffer) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (((UINTN) (*HostAddress) != (*HostAddress)) && Operation == EfiBusMasterCommonBuffer) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = Private->PciRootBridgeIo->Map (
+ Private->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,
+ (VOID *) (UINTN) (*HostAddress),
+ NumberOfBytes,
+ DeviceAddress,
+ Mapping
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoUnmap (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+/*++
+
+Routine Description:
+
+ Completes the Map() operation and releases any corresponding resources.
+
+Arguments:
+
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+ Mapping - The mapping value returned from Map().
+
+Returns:
+
+ EFI_SUCCESS - The range was unmapped.
+ EFI_DEVICE_ERROR - The data was not committed to the target system memory.
+
+--*/
+{
+ EFI_STATUS Status;
+ DEVICE_IO_PRIVATE_DATA *Private;
+
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ Status = Private->PciRootBridgeIo->Unmap (
+ Private->PciRootBridgeIo,
+ Mapping
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoAllocateBuffer (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ IN OUT EFI_PHYSICAL_ADDRESS *PhysicalAddress
+ )
+/*++
+
+Routine Description:
+
+ Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.
+
+Arguments:
+
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+ Type - The type allocation to perform.
+ MemoryType - The type of memory to allocate, EfiBootServicesData or
+ EfiRuntimeServicesData.
+ Pages - The number of pages to allocate.
+ PhysicalAddress - A pointer to store the base address of the allocated range.
+
+Returns:
+
+ EFI_SUCCESS - The requested memory pages were allocated.
+ EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
+ EFI_INVALID_PARAMETER - The requested memory type is invalid.
+ EFI_UNSUPPORTED - The requested PhysicalAddress is not supported on
+ this platform.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS HostAddress;
+
+ HostAddress = *PhysicalAddress;
+
+ if ((MemoryType != EfiBootServicesData) && (MemoryType != EfiRuntimeServicesData)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Type >= MaxAllocateType) || (Type < AllocateAnyPages)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Type == AllocateAddress) && (HostAddress + EFI_PAGES_TO_SIZE (Pages) - 1 > MAX_COMMON_BUFFER)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((AllocateAnyPages == Type) || (AllocateMaxAddress == Type && HostAddress > MAX_COMMON_BUFFER)) {
+ Type = AllocateMaxAddress;
+ HostAddress = MAX_COMMON_BUFFER;
+ }
+
+ Status = gBS->AllocatePages (
+ Type,
+ MemoryType,
+ Pages,
+ &HostAddress
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+
+ *PhysicalAddress = HostAddress;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoFlush (
+ IN EFI_DEVICE_IO_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+
+ Flushes any posted write data to the device.
+
+Arguments:
+
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+
+Returns:
+
+ EFI_SUCCESS - The buffers were flushed.
+ EFI_DEVICE_ERROR - The buffers were not flushed due to a hardware error.
+
+--*/
+{
+ EFI_STATUS Status;
+ DEVICE_IO_PRIVATE_DATA *Private;
+
+ Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
+
+ Status = Private->PciRootBridgeIo->Flush (Private->PciRootBridgeIo);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DeviceIoFreeBuffer (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ IN EFI_PHYSICAL_ADDRESS HostAddress
+ )
+/*++
+
+Routine Description:
+
+ Frees pages that were allocated with AllocateBuffer().
+
+Arguments:
+
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+ Pages - The number of pages to free.
+ HostAddress - The base address of the range to free.
+
+Returns:
+
+ EFI_SUCCESS - The requested memory pages were freed.
+ EFI_NOT_FOUND - The requested memory pages were not allocated with
+ AllocateBuffer().
+ EFI_INVALID_PARAMETER - HostAddress is not page aligned or Pages is invalid.
+
+--*/
+{
+ if (((HostAddress & EFI_PAGE_MASK) != 0) || (Pages <= 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return gBS->FreePages (HostAddress, Pages);
+}
diff --git a/DuetPkg/PciRootBridgeNoEnumerationDxe/DeviceIo.h b/DuetPkg/PciRootBridgeNoEnumerationDxe/DeviceIo.h
new file mode 100644
index 0000000000..71d3a41e28
--- /dev/null
+++ b/DuetPkg/PciRootBridgeNoEnumerationDxe/DeviceIo.h
@@ -0,0 +1,449 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ DeviceIo.h
+
+Abstract:
+
+ Private Data definition for Device IO driver
+
+--*/
+
+#ifndef _DEVICE_IO_H
+#define _DEVICE_IO_H
+
+
+
+#define DEVICE_IO_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('d', 'e', 'v', 'I')
+
+#define MAX_COMMON_BUFFER 0x00000000FFFFFFFF
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_DEVICE_IO_PROTOCOL DeviceIo;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINT16 PrimaryBus;
+ UINT16 SubordinateBus;
+} DEVICE_IO_PRIVATE_DATA;
+
+#define DEVICE_IO_PRIVATE_DATA_FROM_THIS(a) CR (a, DEVICE_IO_PRIVATE_DATA, DeviceIo, DEVICE_IO_PRIVATE_DATA_SIGNATURE)
+
+EFI_STATUS
+DeviceIoConstructor (
+ IN EFI_HANDLE Handle,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN UINT16 PrimaryBus,
+ IN UINT16 SubordinateBus
+ )
+/*++
+
+Routine Description:
+
+ Initialize and install a Device IO protocol on a empty device path handle.
+
+Arguments:
+
+ Handle - Handle of PCI RootBridge IO instance
+ PciRootBridgeIo - PCI RootBridge IO instance
+ DevicePath - Device Path of PCI RootBridge IO instance
+ PrimaryBus - Primary Bus
+ SubordinateBus - Subordinate Bus
+
+Returns:
+
+ EFI_SUCCESS - This driver is added to ControllerHandle.
+ EFI_ALREADY_STARTED - This driver is already running on ControllerHandle.
+ Others - This driver does not support this device.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoMemRead (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform reading memory mapped I/O space of device.
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO protocol instance.
+ Width - Width of I/O operations.
+ Address - The base address of I/O operations.
+ Count - The number of I/O operations to perform.
+ Bytes moves is Width size * Count, starting at Address.
+ Buffer - The destination buffer to store results.
+
+Returns:
+
+ EFI_SUCCESS - The data was read from the device.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoMemWrite (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform writing memory mapped I/O space of device.
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO protocol instance.
+ Width - Width of I/O operations.
+ Address - The base address of I/O operations.
+ Count - The number of I/O operations to perform.
+ Bytes moves is Width size * Count, starting at Address.
+ Buffer - The source buffer of data to be written.
+
+Returns:
+
+ EFI_SUCCESS - The data was written to the device.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoIoRead (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform reading I/O space of device.
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO protocol instance.
+ Width - Width of I/O operations.
+ Address - The base address of I/O operations.
+ Count - The number of I/O operations to perform.
+ Bytes moves is Width size * Count, starting at Address.
+ Buffer - The destination buffer to store results.
+
+Returns:
+
+ EFI_SUCCESS - The data was read from the device.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoIoWrite (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform writing I/O space of device.
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO protocol instance.
+ Width - Width of I/O operations.
+ Address - The base address of I/O operations.
+ Count - The number of I/O operations to perform.
+ Bytes moves is Width size * Count, starting at Address.
+ Buffer - The source buffer of data to be written.
+
+Returns:
+
+ EFI_SUCCESS - The data was written to the device.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoPciRead (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform reading PCI configuration space of device
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO protocol instance.
+ Width - Width of I/O operations.
+ Address - The base address of I/O operations.
+ Count - The number of I/O operations to perform.
+ Bytes moves is Width size * Count, starting at Address.
+ Buffer - The destination buffer to store results.
+
+Returns:
+
+ EFI_SUCCESS - The data was read from the device.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoPciWrite (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Perform writing PCI configuration space of device.
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO protocol instance.
+ Width - Width of I/O operations.
+ Address - The base address of I/O operations.
+ Count - The number of I/O operations to perform.
+ Bytes moves is Width size * Count, starting at Address.
+ Buffer - The source buffer of data to be written.
+
+Returns:
+
+ EFI_SUCCESS - The data was written to the device.
+ EFI_INVALID_PARAMETER - Width is invalid.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoPciDevicePath (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN UINT64 Address,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **PciDevicePath
+ )
+/*++
+
+Routine Description:
+
+ Append a PCI device path node to another device path.
+
+Arguments:
+
+ This - A pointer to EFI_DEVICE_IO_PROTOCOL.
+ Address - PCI bus,device, function.
+ PciDevicePath - PCI device path.
+
+Returns:
+
+ Pointer to the appended PCI device path.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoMap (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_IO_OPERATION_TYPE Operation,
+ IN EFI_PHYSICAL_ADDRESS *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+/*++
+
+Routine Description:
+
+ Provides the device-specific addresses needed to access system memory.
+
+Arguments:
+
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+ Operation - Indicates if the bus master is going to read or write to system memory.
+ HostAddress - The system memory address to map to the device.
+ NumberOfBytes - On input the number of bytes to map. On output the number of bytes
+ that were mapped.
+ DeviceAddress - The resulting map address for the bus master device to use to access the
+ hosts HostAddress.
+ Mapping - A resulting value to pass to Unmap().
+
+Returns:
+
+ EFI_SUCCESS - The range was mapped for the returned NumberOfBytes.
+ EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined.
+ EFI_UNSUPPORTED - The HostAddress cannot be mapped as a common buffer.
+ EFI_DEVICE_ERROR - The system hardware could not map the requested address.
+ EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoUnmap (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+/*++
+
+Routine Description:
+
+ Completes the Map() operation and releases any corresponding resources.
+
+Arguments:
+
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+ Mapping - The mapping value returned from Map().
+
+Returns:
+
+ EFI_SUCCESS - The range was unmapped.
+ EFI_DEVICE_ERROR - The data was not committed to the target system memory.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoAllocateBuffer (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ IN OUT EFI_PHYSICAL_ADDRESS *HostAddress
+ )
+/*++
+
+Routine Description:
+
+ Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.
+
+Arguments:
+
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+ Type - The type allocation to perform.
+ MemoryType - The type of memory to allocate, EfiBootServicesData or
+ EfiRuntimeServicesData.
+ Pages - The number of pages to allocate.
+ HostAddress - A pointer to store the base address of the allocated range.
+
+Returns:
+
+ EFI_SUCCESS - The requested memory pages were allocated.
+ EFI_OUT_OF_RESOURCES - The memory pages could not be allocated.
+ EFI_INVALID_PARAMETER - The requested memory type is invalid.
+ EFI_UNSUPPORTED - The requested PhysicalAddress is not supported on
+ this platform.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoFlush (
+ IN EFI_DEVICE_IO_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+
+ Flushes any posted write data to the device.
+
+Arguments:
+
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+
+Returns:
+
+ EFI_SUCCESS - The buffers were flushed.
+ EFI_DEVICE_ERROR - The buffers were not flushed due to a hardware error.
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+DeviceIoFreeBuffer (
+ IN EFI_DEVICE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ IN EFI_PHYSICAL_ADDRESS HostAddress
+ )
+/*++
+
+Routine Description:
+
+ Frees pages that were allocated with AllocateBuffer().
+
+Arguments:
+
+ This - A pointer to the EFI_DEVICE_IO_INTERFACE instance.
+ Pages - The number of pages to free.
+ HostAddress - The base address of the range to free.
+
+Returns:
+
+ EFI_SUCCESS - The requested memory pages were freed.
+ EFI_NOT_FOUND - The requested memory pages were not allocated with
+ AllocateBuffer().
+ EFI_INVALID_PARAMETER - HostAddress is not page aligned or Pages is invalid.
+
+--*/
+;
+
+#endif
+
diff --git a/DuetPkg/PciRootBridgeNoEnumerationDxe/Ia32/PcatIo.c b/DuetPkg/PciRootBridgeNoEnumerationDxe/Ia32/PcatIo.c
new file mode 100644
index 0000000000..0cbf047254
--- /dev/null
+++ b/DuetPkg/PciRootBridgeNoEnumerationDxe/Ia32/PcatIo.c
@@ -0,0 +1,734 @@
+/*++
+
+Copyright (c) 2005 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ PcatPciRootBridgeIo.c
+
+Abstract:
+
+ EFI PC AT PCI Root Bridge Io Protocol
+
+Revision History
+
+--*/
+
+#include "PcatPciRootBridge.h"
+
+static BOOLEAN mPciOptionRomTableInstalled = FALSE;
+static EFI_PCI_OPTION_ROM_TABLE mPciOptionRomTable = {0, NULL};
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ )
+{
+ return gCpuIo->Io.Read (
+ gCpuIo,
+ (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
+ UserAddress,
+ Count,
+ UserBuffer
+ );
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ )
+{
+ return gCpuIo->Io.Write (
+ gCpuIo,
+ (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
+ UserAddress,
+ Count,
+ UserBuffer
+ );
+
+}
+
+EFI_STATUS
+PcatRootBridgeIoGetIoPortMapping (
+ OUT EFI_PHYSICAL_ADDRESS *IoPortMapping,
+ OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping
+ )
+/*++
+
+ Get the IO Port Mapping. For IA-32 it is always 0.
+
+--*/
+{
+ *IoPortMapping = 0;
+ *MemoryPortMapping = 0;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PcatRootBridgeIoPciRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ )
+{
+ PCI_CONFIG_ACCESS_CF8 Pci;
+ PCI_CONFIG_ACCESS_CF8 PciAligned;
+ UINT32 InStride;
+ UINT32 OutStride;
+ UINTN PciData;
+ UINTN PciDataStride;
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress;
+ UINT64 PciExpressRegAddr;
+ BOOLEAN UsePciExpressAccess;
+
+ if (Width < 0 || Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Width & 0x03) >= EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ InStride = 1 << (Width & 0x03);
+ OutStride = InStride;
+ if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
+ InStride = 0;
+ }
+
+ if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {
+ OutStride = 0;
+ }
+
+ UsePciExpressAccess = FALSE;
+
+ CopyMem (&PciAddress, &UserAddress, sizeof(UINT64));
+
+ if (PciAddress.ExtendedRegister > 0xFF) {
+ //
+ // Check PciExpressBaseAddress
+ //
+ if ((PrivateData->PciExpressBaseAddress == 0) ||
+ (PrivateData->PciExpressBaseAddress >= EFI_MAX_ADDRESS)) {
+ return EFI_UNSUPPORTED;
+ } else {
+ UsePciExpressAccess = TRUE;
+ }
+ } else {
+ if (PciAddress.ExtendedRegister != 0) {
+ Pci.Bits.Reg = PciAddress.ExtendedRegister & 0xFF;
+ } else {
+ Pci.Bits.Reg = PciAddress.Register;
+ }
+ //
+ // Note: We can also use PciExpress access here, if wanted.
+ //
+ }
+
+ if (!UsePciExpressAccess) {
+ Pci.Bits.Func = PciAddress.Function;
+ Pci.Bits.Dev = PciAddress.Device;
+ Pci.Bits.Bus = PciAddress.Bus;
+ Pci.Bits.Reserved = 0;
+ Pci.Bits.Enable = 1;
+
+ //
+ // PCI Config access are all 32-bit alligned, but by accessing the
+ // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
+ // are possible on PCI.
+ //
+ // To read a byte of PCI config space you load 0xcf8 and
+ // read 0xcfc, 0xcfd, 0xcfe, 0xcff
+ //
+ PciDataStride = Pci.Bits.Reg & 0x03;
+
+ while (Count) {
+ PciAligned = Pci;
+ PciAligned.Bits.Reg &= 0xfc;
+ PciData = (UINTN)PrivateData->PciData + PciDataStride;
+ EfiAcquireLock(&PrivateData->PciLock);
+ This->Io.Write (This, EfiPciWidthUint32, PrivateData->PciAddress, 1, &PciAligned);
+ if (Write) {
+ This->Io.Write (This, Width, PciData, 1, UserBuffer);
+ } else {
+ This->Io.Read (This, Width, PciData, 1, UserBuffer);
+ }
+ EfiReleaseLock(&PrivateData->PciLock);
+ UserBuffer = ((UINT8 *)UserBuffer) + OutStride;
+ PciDataStride = (PciDataStride + InStride) % 4;
+ Pci.Bits.Reg += InStride;
+ Count -= 1;
+ }
+ } else {
+ //
+ // Access PCI-Express space by using memory mapped method.
+ //
+ PciExpressRegAddr = (PrivateData->PciExpressBaseAddress) |
+ (PciAddress.Bus << 20) |
+ (PciAddress.Device << 15) |
+ (PciAddress.Function << 12);
+ if (PciAddress.ExtendedRegister != 0) {
+ PciExpressRegAddr += PciAddress.ExtendedRegister;
+ } else {
+ PciExpressRegAddr += PciAddress.Register;
+ }
+ while (Count) {
+ if (Write) {
+ This->Mem.Write (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);
+ } else {
+ This->Mem.Read (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);
+ }
+
+ UserBuffer = ((UINT8 *) UserBuffer) + OutStride;
+ PciExpressRegAddr += InStride;
+ Count -= 1;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+static
+VOID
+ScanPciBus(
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ UINT16 MinBus,
+ UINT16 MaxBus,
+ UINT16 MinDevice,
+ UINT16 MaxDevice,
+ UINT16 MinFunc,
+ UINT16 MaxFunc,
+ EFI_PCI_BUS_SCAN_CALLBACK Callback,
+ VOID *Context
+ )
+
+{
+ UINT16 Bus;
+ UINT16 Device;
+ UINT16 Func;
+ UINT64 Address;
+ PCI_TYPE00 PciHeader;
+
+ //
+ // Loop through all busses
+ //
+ for (Bus = MinBus; Bus <= MaxBus; Bus++) {
+ //
+ // Loop 32 devices per bus
+ //
+ for (Device = MinDevice; Device <= MaxDevice; Device++) {
+ //
+ // Loop through 8 functions per device
+ //
+ for (Func = MinFunc; Func <= MaxFunc; Func++) {
+
+ //
+ // Compute the EFI Address required to access the PCI Configuration Header of this PCI Device
+ //
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
+
+ //
+ // Read the VendorID from this PCI Device's Confioguration Header
+ //
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &PciHeader.Hdr.VendorId);
+
+ //
+ // If VendorId = 0xffff, there does not exist a device at this
+ // location. For each device, if there is any function on it,
+ // there must be 1 function at Function 0. So if Func = 0, there
+ // will be no more functions in the same device, so we can break
+ // loop to deal with the next device.
+ //
+ if (PciHeader.Hdr.VendorId == 0xffff && Func == 0) {
+ break;
+ }
+
+ if (PciHeader.Hdr.VendorId != 0xffff) {
+
+ //
+ // Read the HeaderType to determine if this is a multi-function device
+ //
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint8, Address + 0x0e, 1, &PciHeader.Hdr.HeaderType);
+
+ //
+ // Call the callback function for the device that was found
+ //
+ Callback(
+ IoDev,
+ MinBus, MaxBus,
+ MinDevice, MaxDevice,
+ MinFunc, MaxFunc,
+ Bus,
+ Device,
+ Func,
+ Context
+ );
+
+ //
+ // If this is not a multi-function device, we can leave the loop
+ // to deal with the next device.
+ //
+ if ((PciHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x00 && Func == 0) {
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+static
+VOID
+CheckForRom (
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ UINT16 MinBus,
+ UINT16 MaxBus,
+ UINT16 MinDevice,
+ UINT16 MaxDevice,
+ UINT16 MinFunc,
+ UINT16 MaxFunc,
+ UINT16 Bus,
+ UINT16 Device,
+ UINT16 Func,
+ IN VOID *VoidContext
+ )
+{
+ EFI_STATUS Status;
+ PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;
+ UINT64 Address;
+ PCI_TYPE00 PciHeader;
+ PCI_TYPE01 *PciBridgeHeader;
+ UINT32 Register;
+ UINT32 RomBar;
+ UINT32 RomBarSize;
+ EFI_PHYSICAL_ADDRESS RomBuffer;
+ UINT32 MaxRomSize;
+ EFI_PCI_EXPANSION_ROM_HEADER EfiRomHeader;
+ PCI_DATA_STRUCTURE Pcir;
+ EFI_PCI_OPTION_ROM_DESCRIPTOR *TempPciOptionRomDescriptors;
+ BOOLEAN LastImage;
+
+ Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
+
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
+
+ //
+ // Save the contents of the PCI Configuration Header
+ //
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);
+
+ if (IS_PCI_BRIDGE(&PciHeader)) {
+
+ PciBridgeHeader = (PCI_TYPE01 *)(&PciHeader);
+
+ //
+ // See if the PCI-PCI Bridge has its secondary interface enabled.
+ //
+ if (PciBridgeHeader->Bridge.SubordinateBus >= PciBridgeHeader->Bridge.SecondaryBus) {
+
+ //
+ // Disable the Prefetchable Memory Window
+ //
+ Register = 0x00000000;
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x26, 1, &Register);
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x2c, 1, &Register);
+ Register = 0xffffffff;
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x24, 1, &Register);
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x28, 1, &Register);
+
+ //
+ // Program Memory Window to the PCI Root Bridge Memory Window
+ //
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x20, 4, &Context->PpbMemoryWindow);
+
+ //
+ // Enable the Memory decode for the PCI-PCI Bridge
+ //
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+ Register |= 0x02;
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+
+ //
+ // Recurse on the Secondary Bus Number
+ //
+ ScanPciBus(
+ IoDev,
+ PciBridgeHeader->Bridge.SecondaryBus, PciBridgeHeader->Bridge.SecondaryBus,
+ 0, PCI_MAX_DEVICE,
+ 0, PCI_MAX_FUNC,
+ CheckForRom, Context
+ );
+ }
+ } else {
+
+ //
+ // Check if an Option ROM Register is present and save the Option ROM Window Register
+ //
+ RomBar = 0xffffffff;
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
+
+ RomBarSize = (~(RomBar & 0xfffff800)) + 1;
+
+ //
+ // Make sure the size of the ROM is between 0 and 16 MB
+ //
+ if (RomBarSize > 0 && RomBarSize <= 0x01000000) {
+
+ //
+ // Program Option ROM Window Register to the PCI Root Bridge Window and Enable the Option ROM Window
+ //
+ RomBar = (Context->PpbMemoryWindow & 0xffff) << 16;
+ RomBar = ((RomBar - 1) & (~(RomBarSize - 1))) + RomBarSize;
+ if (RomBar < (Context->PpbMemoryWindow & 0xffff0000)) {
+ MaxRomSize = (Context->PpbMemoryWindow & 0xffff0000) - RomBar;
+ RomBar = RomBar + 1;
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
+ RomBar = RomBar - 1;
+
+ //
+ // Enable the Memory decode for the PCI Device
+ //
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+ Register |= 0x02;
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+
+ //
+ // Follow the chain of images to determine the size of the Option ROM present
+ // Keep going until the last image is found by looking at the Indicator field
+ // or the size of an image is 0, or the size of all the images is bigger than the
+ // size of the window programmed into the PPB.
+ //
+ RomBarSize = 0;
+ do {
+
+ LastImage = TRUE;
+
+ ZeroMem (&EfiRomHeader, sizeof(EfiRomHeader));
+ IoDev->Mem.Read (
+ IoDev,
+ EfiPciWidthUint8,
+ RomBar + RomBarSize,
+ sizeof(EfiRomHeader),
+ &EfiRomHeader
+ );
+
+ Pcir.ImageLength = 0;
+
+ if (EfiRomHeader.Signature == 0xaa55) {
+
+ ZeroMem (&Pcir, sizeof(Pcir));
+ IoDev->Mem.Read (
+ IoDev,
+ EfiPciWidthUint8,
+ RomBar + RomBarSize + EfiRomHeader.PcirOffset,
+ sizeof(Pcir),
+ &Pcir
+ );
+
+ if ((Pcir.Indicator & 0x80) == 0x00) {
+ LastImage = FALSE;
+ }
+
+ RomBarSize += Pcir.ImageLength * 512;
+ }
+ } while (!LastImage && RomBarSize < MaxRomSize && Pcir.ImageLength !=0);
+
+ if (RomBarSize > 0) {
+
+ //
+ // Allocate a memory buffer for the Option ROM contents.
+ //
+ Status = gBS->AllocatePages(
+ AllocateAnyPages,
+ EfiBootServicesData,
+ EFI_SIZE_TO_PAGES(RomBarSize),
+ &RomBuffer
+ );
+
+ if (!EFI_ERROR (Status)) {
+
+ //
+ // Copy the contents of the Option ROM to the memory buffer
+ //
+ IoDev->Mem.Read (IoDev, EfiPciWidthUint32, RomBar, RomBarSize / sizeof(UINT32), (VOID *)(UINTN)RomBuffer);
+
+ Status = gBS->AllocatePool(
+ EfiBootServicesData,
+ ((UINT32)mPciOptionRomTable.PciOptionRomCount + 1) * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR),
+ &TempPciOptionRomDescriptors
+ );
+ if (mPciOptionRomTable.PciOptionRomCount > 0) {
+ CopyMem(
+ TempPciOptionRomDescriptors,
+ mPciOptionRomTable.PciOptionRomDescriptors,
+ (UINT32)mPciOptionRomTable.PciOptionRomCount * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR)
+ );
+
+ gBS->FreePool(mPciOptionRomTable.PciOptionRomDescriptors);
+ }
+
+ mPciOptionRomTable.PciOptionRomDescriptors = TempPciOptionRomDescriptors;
+
+ TempPciOptionRomDescriptors = &(mPciOptionRomTable.PciOptionRomDescriptors[(UINT32)mPciOptionRomTable.PciOptionRomCount]);
+
+ TempPciOptionRomDescriptors->RomAddress = RomBuffer;
+ TempPciOptionRomDescriptors->MemoryType = EfiBootServicesData;
+ TempPciOptionRomDescriptors->RomLength = RomBarSize;
+ TempPciOptionRomDescriptors->Seg = (UINT32)IoDev->SegmentNumber;
+ TempPciOptionRomDescriptors->Bus = (UINT8)Bus;
+ TempPciOptionRomDescriptors->Dev = (UINT8)Device;
+ TempPciOptionRomDescriptors->Func = (UINT8)Func;
+ TempPciOptionRomDescriptors->ExecutedLegacyBiosImage = TRUE;
+ TempPciOptionRomDescriptors->DontLoadEfiRom = FALSE;
+
+ mPciOptionRomTable.PciOptionRomCount++;
+ }
+ }
+
+ //
+ // Disable the Memory decode for the PCI-PCI Bridge
+ //
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+ Register &= (~0x02);
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+ }
+ }
+ }
+
+ //
+ // Restore the PCI Configuration Header
+ //
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);
+}
+
+static
+VOID
+SaveCommandRegister (
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ UINT16 MinBus,
+ UINT16 MaxBus,
+ UINT16 MinDevice,
+ UINT16 MaxDevice,
+ UINT16 MinFunc,
+ UINT16 MaxFunc,
+ UINT16 Bus,
+ UINT16 Device,
+ UINT16 Func,
+ IN VOID *VoidContext
+ )
+
+{
+ PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;
+ UINT64 Address;
+ UINTN Index;
+ UINT16 Command;
+
+ Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
+
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);
+
+ Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;
+
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);
+
+ //
+ // Clear the memory enable bit
+ //
+ Command = Context->CommandRegisterBuffer[Index] & (~0x02);
+
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Command);
+}
+
+static
+VOID
+RestoreCommandRegister (
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ UINT16 MinBus,
+ UINT16 MaxBus,
+ UINT16 MinDevice,
+ UINT16 MaxDevice,
+ UINT16 MinFunc,
+ UINT16 MaxFunc,
+ UINT16 Bus,
+ UINT16 Device,
+ UINT16 Func,
+ IN VOID *VoidContext
+ )
+
+{
+ PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;
+ UINT64 Address;
+ UINTN Index;
+
+ Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
+
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);
+
+ Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;
+
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);
+}
+
+EFI_STATUS
+ScanPciRootBridgeForRoms(
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev
+ )
+
+{
+ EFI_STATUS Status;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
+ UINT16 MinBus;
+ UINT16 MaxBus;
+ UINT64 RootWindowBase;
+ UINT64 RootWindowLimit;
+ PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT Context;
+
+ if (mPciOptionRomTableInstalled == FALSE) {
+ gBS->InstallConfigurationTable(&gEfiPciOptionRomTableGuid, &mPciOptionRomTable);
+ mPciOptionRomTableInstalled = TRUE;
+ }
+
+ Status = IoDev->Configuration(IoDev, &Descriptors);
+ if (EFI_ERROR (Status) || Descriptors == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ MinBus = 0xffff;
+ MaxBus = 0xffff;
+ RootWindowBase = 0;
+ RootWindowLimit = 0;
+ while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) {
+ //
+ // Find bus range
+ //
+ if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
+ MinBus = (UINT16)Descriptors->AddrRangeMin;
+ MaxBus = (UINT16)Descriptors->AddrRangeMax;
+ }
+ //
+ // Find memory descriptors that are not prefetchable
+ //
+ if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM && Descriptors->SpecificFlag == 0) {
+ //
+ // Find Memory Descriptors that are less than 4GB, so the PPB Memory Window can be used for downstream devices
+ //
+ if (Descriptors->AddrRangeMax < 0x100000000) {
+ //
+ // Find the largest Non-Prefetchable Memory Descriptor that is less than 4GB
+ //
+ if ((Descriptors->AddrRangeMax - Descriptors->AddrRangeMin) > (RootWindowLimit - RootWindowBase)) {
+ RootWindowBase = Descriptors->AddrRangeMin;
+ RootWindowLimit = Descriptors->AddrRangeMax;
+ }
+ }
+ }
+ Descriptors ++;
+ }
+
+ //
+ // Make sure a bus range was found
+ //
+ if (MinBus == 0xffff || MaxBus == 0xffff) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Make sure a non-prefetchable memory region was found
+ //
+ if (RootWindowBase == 0 && RootWindowLimit == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Round the Base and Limit values to 1 MB boudaries
+ //
+ RootWindowBase = ((RootWindowBase - 1) & 0xfff00000) + 0x00100000;
+ RootWindowLimit = ((RootWindowLimit + 1) & 0xfff00000) - 1;
+
+ //
+ // Make sure that the size of the rounded window is greater than zero
+ //
+ if (RootWindowLimit <= RootWindowBase) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Allocate buffer to save the Command register from all the PCI devices
+ //
+ Context.CommandRegisterBuffer = NULL;
+ Status = gBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(UINT16) * (MaxBus - MinBus + 1) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1),
+ &Context.CommandRegisterBuffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Context.PpbMemoryWindow = (((UINT32)RootWindowBase) >> 16) | ((UINT32)RootWindowLimit & 0xffff0000);
+
+ //
+ // Save the Command register from all the PCI devices, and disable the I/O, Mem, and BusMaster bits
+ //
+ ScanPciBus(
+ IoDev,
+ MinBus, MaxBus,
+ 0, PCI_MAX_DEVICE,
+ 0, PCI_MAX_FUNC,
+ SaveCommandRegister, &Context
+ );
+
+ //
+ // Recursively scan all the busses for PCI Option ROMs
+ //
+ ScanPciBus(
+ IoDev,
+ MinBus, MinBus,
+ 0, PCI_MAX_DEVICE,
+ 0, PCI_MAX_FUNC,
+ CheckForRom, &Context
+ );
+
+ //
+ // Restore the Command register in all the PCI devices
+ //
+ ScanPciBus(
+ IoDev,
+ MinBus, MaxBus,
+ 0, PCI_MAX_DEVICE,
+ 0, PCI_MAX_FUNC,
+ RestoreCommandRegister, &Context
+ );
+
+ //
+ // Free the buffer used to save all the Command register values
+ //
+ gBS->FreePool(Context.CommandRegisterBuffer);
+
+ return EFI_SUCCESS;
+}
diff --git a/DuetPkg/PciRootBridgeNoEnumerationDxe/Ipf/PcatIo.c b/DuetPkg/PciRootBridgeNoEnumerationDxe/Ipf/PcatIo.c
new file mode 100644
index 0000000000..9979d47c4e
--- /dev/null
+++ b/DuetPkg/PciRootBridgeNoEnumerationDxe/Ipf/PcatIo.c
@@ -0,0 +1,459 @@
+/*++
+
+Copyright (c) 2005, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ PcatPciRootBridgeIo.c
+
+Abstract:
+
+ EFI PC AT PCI Root Bridge Io Protocol
+
+Revision History
+
+--*/
+
+#include "PcatPciRootBridge.h"
+#include "pci22.h"
+#include "SalProc.h"
+
+#include EFI_GUID_DEFINITION (SalSystemTable)
+
+//
+// Might be good to put this in an include file, but people may start
+// using it! They should always access the EFI abstraction that is
+// contained in this file. Just a little information hiding.
+//
+#define PORT_TO_MEM(_Port) ( ((_Port) & 0xffffffffffff0000) | (((_Port) & 0xfffc) << 10) | ((_Port) & 0x0fff) )
+
+//
+// Macro's with casts make this much easier to use and read.
+//
+#define PORT_TO_MEM8(_Port) (*(UINT8 *)(PORT_TO_MEM(_Port)))
+#define PORT_TO_MEM16(_Port) (*(UINT16 *)(PORT_TO_MEM(_Port)))
+#define PORT_TO_MEM32(_Port) (*(UINT32 *)(PORT_TO_MEM(_Port)))
+
+#define EFI_PCI_ADDRESS_IA64(_seg, _bus,_dev,_func,_reg) \
+ ( (UINT64) ( (((UINTN)_seg) << 24) + (((UINTN)_bus) << 16) + (((UINTN)_dev) << 11) + (((UINTN)_func) << 8) + ((UINTN)_reg)) )
+
+//
+// Local variables for performing SAL Proc calls
+//
+static PLABEL mSalProcPlabel;
+static CALL_SAL_PROC mGlobalSalProc;
+
+EFI_STATUS
+PcatRootBridgeIoIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ )
+{
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ UINTN InStride;
+ UINTN OutStride;
+ UINTN AlignMask;
+ UINTN Address;
+ PTR Buffer;
+ UINT16 Data16;
+ UINT32 Data32;
+
+
+ if ( UserBuffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ Address = (UINTN) UserAddress;
+ Buffer.buf = (UINT8 *)UserBuffer;
+
+ if ( Address < PrivateData->IoBase || Address > PrivateData->IoLimit ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width < 0 || Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Width & 0x03) == EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AlignMask = (1 << (Width & 0x03)) - 1;
+ if ( Address & AlignMask ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InStride = 1 << (Width & 0x03);
+ OutStride = InStride;
+ if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+ InStride = 0;
+ }
+ if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
+ OutStride = 0;
+ }
+ Width = Width & 0x03;
+
+ Address += PrivateData->PhysicalIoBase;
+
+ //
+ // Loop for each iteration and move the data
+ //
+
+ switch (Width) {
+ case EfiPciWidthUint8:
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+ MEMORY_FENCE();
+ *Buffer.ui8 = PORT_TO_MEM8(Address);
+ MEMORY_FENCE();
+ }
+ break;
+
+ case EfiPciWidthUint16:
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+ MEMORY_FENCE();
+ if (Buffer.ui & 0x1) {
+ Data16 = PORT_TO_MEM16(Address);
+ *Buffer.ui8 = (UINT8)(Data16 & 0xff);
+ *(Buffer.ui8+1) = (UINT8)((Data16 >> 8) & 0xff);
+ } else {
+ *Buffer.ui16 = PORT_TO_MEM16(Address);
+ }
+ MEMORY_FENCE();
+ }
+ break;
+
+ case EfiPciWidthUint32:
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+ MEMORY_FENCE();
+ if (Buffer.ui & 0x3) {
+ Data32 = PORT_TO_MEM32(Address);
+ *Buffer.ui8 = (UINT8)(Data32 & 0xff);
+ *(Buffer.ui8+1) = (UINT8)((Data32 >> 8) & 0xff);
+ *(Buffer.ui8+2) = (UINT8)((Data32 >> 16) & 0xff);
+ *(Buffer.ui8+3) = (UINT8)((Data32 >> 24) & 0xff);
+ } else {
+ *Buffer.ui32 = PORT_TO_MEM32(Address);
+ }
+ MEMORY_FENCE();
+ }
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PcatRootBridgeIoIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ )
+{
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ UINTN InStride;
+ UINTN OutStride;
+ UINTN AlignMask;
+ UINTN Address;
+ PTR Buffer;
+ UINT16 Data16;
+ UINT32 Data32;
+
+ if ( UserBuffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ Address = (UINTN) UserAddress;
+ Buffer.buf = (UINT8 *)UserBuffer;
+
+ if ( Address < PrivateData->IoBase || Address > PrivateData->IoLimit ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width < 0 || Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Width & 0x03) == EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AlignMask = (1 << (Width & 0x03)) - 1;
+ if ( Address & AlignMask ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InStride = 1 << (Width & 0x03);
+ OutStride = InStride;
+ if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+ InStride = 0;
+ }
+ if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
+ OutStride = 0;
+ }
+ Width = Width & 0x03;
+
+ Address += PrivateData->PhysicalIoBase;
+
+ //
+ // Loop for each iteration and move the data
+ //
+
+ switch (Width) {
+ case EfiPciWidthUint8:
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+ MEMORY_FENCE();
+ PORT_TO_MEM8(Address) = *Buffer.ui8;
+ MEMORY_FENCE();
+ }
+ break;
+
+ case EfiPciWidthUint16:
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+ MEMORY_FENCE();
+ if (Buffer.ui & 0x1) {
+ Data16 = *Buffer.ui8;
+ Data16 = Data16 | (*(Buffer.ui8+1) << 8);
+ PORT_TO_MEM16(Address) = Data16;
+ } else {
+ PORT_TO_MEM16(Address) = *Buffer.ui16;
+ }
+ MEMORY_FENCE();
+ }
+ break;
+ case EfiPciWidthUint32:
+ for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {
+ MEMORY_FENCE();
+ if (Buffer.ui & 0x3) {
+ Data32 = *Buffer.ui8;
+ Data32 = Data32 | (*(Buffer.ui8+1) << 8);
+ Data32 = Data32 | (*(Buffer.ui8+2) << 16);
+ Data32 = Data32 | (*(Buffer.ui8+3) << 24);
+ PORT_TO_MEM32(Address) = Data32;
+ } else {
+ PORT_TO_MEM32(Address) = *Buffer.ui32;
+ }
+ MEMORY_FENCE();
+ }
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PcatRootBridgeIoGetIoPortMapping (
+ OUT EFI_PHYSICAL_ADDRESS *IoPortMapping,
+ OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping
+ )
+/*++
+
+ Get the IO Port Map from the SAL System Table.
+
+--*/
+{
+ SAL_SYSTEM_TABLE_ASCENDING_ORDER *SalSystemTable;
+ SAL_ST_MEMORY_DESCRIPTOR_ENTRY *SalMemDesc;
+ EFI_STATUS Status;
+
+ //
+ // On all Itanium architectures, bit 63 is the I/O bit for performming Memory Mapped I/O operations
+ //
+ *MemoryPortMapping = 0x8000000000000000;
+
+ Status = EfiLibGetSystemConfigurationTable(&gEfiSalSystemTableGuid, &SalSystemTable);
+ if (EFI_ERROR(Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // BugBug: Add code to test checksum on the Sal System Table
+ //
+ if (SalSystemTable->Entry0.Type != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ mSalProcPlabel.ProcEntryPoint = SalSystemTable->Entry0.SalProcEntry;
+ mSalProcPlabel.GP = SalSystemTable->Entry0.GlobalDataPointer;
+ mGlobalSalProc = (CALL_SAL_PROC)&mSalProcPlabel.ProcEntryPoint;
+
+ //
+ // The SalSystemTable pointer includes the Type 0 entry.
+ // The SalMemDesc is Type 1 so it comes next.
+ //
+ SalMemDesc = (SAL_ST_MEMORY_DESCRIPTOR_ENTRY *)(SalSystemTable + 1);
+ while (SalMemDesc->Type == SAL_ST_MEMORY_DESCRIPTOR) {
+ if (SalMemDesc->MemoryType == SAL_IO_PORT_MAPPING) {
+ *IoPortMapping = SalMemDesc->PhysicalMemoryAddress;
+ *IoPortMapping |= 0x8000000000000000;
+ return EFI_SUCCESS;
+ }
+ SalMemDesc++;
+ }
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+PcatRootBridgeIoPciRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT UINT8 *UserBuffer
+ )
+{
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ UINTN AlignMask;
+ UINTN InStride;
+ UINTN OutStride;
+ UINT64 Address;
+ DEFIO_PCI_ADDR *Defio;
+ PTR Buffer;
+ UINT32 Data32;
+ UINT16 Data16;
+ rArg Return;
+
+ if (Width < 0 || Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Width & 0x03) == EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AlignMask = (1 << (Width & 0x03)) - 1;
+ if ( UserAddress & AlignMask ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InStride = 1 << (Width & 0x03);
+ OutStride = InStride;
+ if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+ InStride = 0;
+ }
+ if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
+ OutStride = 0;
+ }
+ Width = Width & 0x03;
+
+ Defio = (DEFIO_PCI_ADDR *)&UserAddress;
+
+ if ((Defio->Function > PCI_MAX_FUNC) || (Defio->Device > PCI_MAX_DEVICE)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Buffer.buf = (UINT8 *)UserBuffer;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ Address = EFI_PCI_ADDRESS_IA64(
+ This->SegmentNumber,
+ Defio->Bus,
+ Defio->Device,
+ Defio->Function,
+ Defio->Register
+ );
+
+ //
+ // PCI Config access are all 32-bit alligned, but by accessing the
+ // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
+ // are possible on PCI.
+ //
+ // SalProc takes care of reading the proper register depending on stride
+ //
+
+ EfiAcquireLock(&PrivateData->PciLock);
+
+ while (Count) {
+
+ if(Write) {
+
+ if (Buffer.ui & 0x3) {
+ Data32 = (*(Buffer.ui8+0) << 0);
+ Data32 |= (*(Buffer.ui8+1) << 8);
+ Data32 |= (*(Buffer.ui8+2) << 16);
+ Data32 |= (*(Buffer.ui8+3) << 24);
+ } else {
+ Data32 = *Buffer.ui32;
+ }
+
+ Return.p0 = -3;
+ Return = mGlobalSalProc((UINT64) SAL_PCI_CONFIG_WRITE,
+ Address, 1 << Width, Data32, 0, 0, 0, 0);
+
+ if(Return.p0) {
+ EfiReleaseLock(&PrivateData->PciLock);
+ return EFI_UNSUPPORTED;
+ }
+
+ } else {
+
+ Return.p0 = -3;
+ Return = mGlobalSalProc((UINT64) SAL_PCI_CONFIG_READ,
+ Address, 1 << Width, 0, 0, 0, 0, 0);
+
+ if(Return.p0) {
+ EfiReleaseLock(&PrivateData->PciLock);
+ return EFI_UNSUPPORTED;
+ }
+
+ switch (Width) {
+ case EfiPciWidthUint8:
+ *Buffer.ui8 = (UINT8)Return.p1;
+ break;
+ case EfiPciWidthUint16:
+ if (Buffer.ui & 0x1) {
+ Data16 = (UINT16)Return.p1;
+ *(Buffer.ui8 + 0) = Data16 & 0xff;
+ *(Buffer.ui8 + 1) = (Data16 >> 8) & 0xff;
+ } else {
+ *Buffer.ui16 = (UINT16)Return.p1;
+ }
+ break;
+ case EfiPciWidthUint32:
+ if (Buffer.ui & 0x3) {
+ Data32 = (UINT32)Return.p1;
+ *(Buffer.ui8 + 0) = (UINT8)(Data32 & 0xff);
+ *(Buffer.ui8 + 1) = (UINT8)((Data32 >> 8) & 0xff);
+ *(Buffer.ui8 + 2) = (UINT8)((Data32 >> 16) & 0xff);
+ *(Buffer.ui8 + 3) = (UINT8)((Data32 >> 24) & 0xff);
+ } else {
+ *Buffer.ui32 = (UINT32)Return.p1;
+ }
+ break;
+ }
+ }
+
+ Address += InStride;
+ Buffer.buf += OutStride;
+ Count -= 1;
+ }
+
+ EfiReleaseLock(&PrivateData->PciLock);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ScanPciRootBridgeForRoms(
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev
+ )
+
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.c b/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.c
new file mode 100644
index 0000000000..ff53bb5c78
--- /dev/null
+++ b/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.c
@@ -0,0 +1,1018 @@
+/*++
+
+Copyright (c) 2005 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ PcatPciRootBridge.c
+
+Abstract:
+
+ EFI PC-AT PCI Root Bridge Controller
+
+--*/
+
+#include "PcatPciRootBridge.h"
+#include "DeviceIo.h"
+
+EFI_CPU_IO_PROTOCOL *gCpuIo;
+
+EFI_STATUS
+EFIAPI
+InitializePcatPciRootBridge (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ Initializes the PCI Root Bridge Controller
+
+Arguments:
+ ImageHandle -
+ SystemTable -
+
+Returns:
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ UINTN PciSegmentIndex;
+ UINTN PciRootBridgeIndex;
+ UINTN PrimaryBusIndex;
+ UINTN NumberOfPciRootBridges;
+ UINTN NumberOfPciDevices;
+ UINTN Device;
+ UINTN Function;
+ UINT16 VendorId;
+ PCI_TYPE01 PciConfigurationHeader;
+ UINT64 Address;
+ UINT64 Value;
+ UINT64 Base;
+ UINT64 Limit;
+
+ //
+ // Initialize gCpuIo now since the chipset init code requires it.
+ //
+ Status = gBS->LocateProtocol (&gEfiCpuIoProtocolGuid, NULL, &gCpuIo);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Initialize variables required to search all PCI segments for PCI devices
+ //
+ PciSegmentIndex = 0;
+ PciRootBridgeIndex = 0;
+ NumberOfPciRootBridges = 0;
+ PrimaryBusIndex = 0;
+
+ while (PciSegmentIndex <= PCI_MAX_SEGMENT) {
+
+ PrivateData = NULL;
+ Status = gBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof (PCAT_PCI_ROOT_BRIDGE_INSTANCE),
+ &PrivateData
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ ZeroMem (PrivateData, sizeof (PCAT_PCI_ROOT_BRIDGE_INSTANCE));
+
+ //
+ // Initialize the signature of the private data structure
+ //
+ PrivateData->Signature = PCAT_PCI_ROOT_BRIDGE_SIGNATURE;
+ PrivateData->Handle = NULL;
+ PrivateData->DevicePath = NULL;
+ InitializeListHead (&PrivateData->MapInfo);
+
+ //
+ // Initialize the PCI root bridge number and the bus range for that root bridge
+ //
+ PrivateData->RootBridgeNumber = (UINT32)PciRootBridgeIndex;
+ PrivateData->PrimaryBus = (UINT32)PrimaryBusIndex;
+ PrivateData->SubordinateBus = (UINT32)PrimaryBusIndex;
+
+ PrivateData->IoBase = 0xffffffff;
+ PrivateData->MemBase = 0xffffffff;
+ PrivateData->Mem32Base = 0xffffffffffffffff;
+ PrivateData->Pmem32Base = 0xffffffffffffffff;
+ PrivateData->Mem64Base = 0xffffffffffffffff;
+ PrivateData->Pmem64Base = 0xffffffffffffffff;
+
+ //
+ // The default mechanism for performing PCI Configuration cycles is to
+ // use the I/O ports at 0xCF8 and 0xCFC. This is only used for IA-32.
+ // IPF uses SAL calls to perform PCI COnfiguration cycles
+ //
+ PrivateData->PciAddress = 0xCF8;
+ PrivateData->PciData = 0xCFC;
+
+ //
+ // Get the physical I/O base for performing PCI I/O cycles
+ // For IA-32, this is always 0, because IA-32 has IN and OUT instructions
+ // For IPF, a SAL call is made to retrieve the base address for PCI I/O cycles
+ //
+ Status = PcatRootBridgeIoGetIoPortMapping (
+ &PrivateData->PhysicalIoBase,
+ &PrivateData->PhysicalMemoryBase
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Get PCI Express Base Address
+ //
+ PrivateData->PciExpressBaseAddress = GetPciExpressBaseAddressForRootBridge (PciSegmentIndex, PciRootBridgeIndex);
+ if (PrivateData->PciExpressBaseAddress != 0) {
+ DEBUG ((EFI_D_ERROR, "PCIE Base - 0x%lx\n", PrivateData->PciExpressBaseAddress));
+ }
+
+ //
+ // Create a lock for performing PCI Configuration cycles
+ //
+ EfiInitializeLock (&PrivateData->PciLock, TPL_HIGH_LEVEL);
+
+ //
+ // Initialize the attributes for this PCI root bridge
+ //
+ PrivateData->Attributes = 0;
+
+ //
+ // Build the EFI Device Path Protocol instance for this PCI Root Bridge
+ //
+ Status = PcatRootBridgeDevicePathConstructor (&PrivateData->DevicePath, PciRootBridgeIndex, (PrivateData->PciExpressBaseAddress != 0) ? TRUE : FALSE);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Build the PCI Root Bridge I/O Protocol instance for this PCI Root Bridge
+ //
+ Status = PcatRootBridgeIoConstructor (&PrivateData->Io, PciSegmentIndex);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Scan all the PCI devices on the primary bus of the PCI root bridge
+ //
+ for (Device = 0, NumberOfPciDevices = 0; Device <= PCI_MAX_DEVICE; Device++) {
+
+ for (Function = 0; Function <= PCI_MAX_FUNC; Function++) {
+
+ //
+ // Compute the PCI configuration address of the PCI device to probe
+ //
+ Address = EFI_PCI_ADDRESS (PrimaryBusIndex, Device, Function, 0);
+
+ //
+ // Read the Vendor ID from the PCI Configuration Header
+ //
+ Status = PrivateData->Io.Pci.Read (
+ &PrivateData->Io,
+ EfiPciWidthUint16,
+ Address,
+ sizeof (VendorId),
+ &VendorId
+ );
+ if ((EFI_ERROR (Status)) || ((VendorId == 0xffff) && (Function == 0))) {
+ //
+ // If the PCI Configuration Read fails, or a PCI device does not exist, then
+ // skip this entire PCI device
+ //
+ break;
+ }
+ if (VendorId == 0xffff) {
+ //
+ // If PCI function != 0, VendorId == 0xFFFF, we continue to search PCI function.
+ //
+ continue;
+ }
+
+ //
+ // Read the entire PCI Configuration Header
+ //
+ Status = PrivateData->Io.Pci.Read (
+ &PrivateData->Io,
+ EfiPciWidthUint32,
+ Address,
+ sizeof (PciConfigurationHeader) / sizeof (UINT32),
+ &PciConfigurationHeader
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // If the entire PCI Configuration Header can not be read, then skip this entire PCI device
+ //
+ break;
+ }
+
+ //
+ // Increment the number of PCI device found on the primary bus of the PCI root bridge
+ //
+ NumberOfPciDevices++;
+
+ //
+ // Look for devices with the VGA Palette Snoop enabled in the COMMAND register of the PCI Config Header
+ //
+ if (PciConfigurationHeader.Hdr.Command & 0x20) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
+ }
+
+ //
+ // If the device is a PCI-PCI Bridge, then look at the Subordinate Bus Number
+ //
+ if (IS_PCI_BRIDGE(&PciConfigurationHeader)) {
+ //
+ // Get the Bus range that the PPB is decoding
+ //
+ if (PciConfigurationHeader.Bridge.SubordinateBus > PrivateData->SubordinateBus) {
+ //
+ // If the suborinate bus number of the PCI-PCI bridge is greater than the PCI root bridge's
+ // current subordinate bus number, then update the PCI root bridge's subordinate bus number
+ //
+ PrivateData->SubordinateBus = PciConfigurationHeader.Bridge.SubordinateBus;
+ }
+
+ //
+ // Get the I/O range that the PPB is decoding
+ //
+ Value = PciConfigurationHeader.Bridge.IoBase & 0x0f;
+ Base = ((UINT32)PciConfigurationHeader.Bridge.IoBase & 0xf0) << 8;
+ Limit = (((UINT32)PciConfigurationHeader.Bridge.IoLimit & 0xf0) << 8) | 0x0fff;
+ if (Value == 0x01) {
+ Base |= ((UINT32)PciConfigurationHeader.Bridge.IoBaseUpper16 << 16);
+ Limit |= ((UINT32)PciConfigurationHeader.Bridge.IoLimitUpper16 << 16);
+ }
+ if (Base < Limit) {
+ if (PrivateData->IoBase > Base) {
+ PrivateData->IoBase = Base;
+ }
+ if (PrivateData->IoLimit < Limit) {
+ PrivateData->IoLimit = Limit;
+ }
+ }
+
+ //
+ // Get the Memory range that the PPB is decoding
+ //
+ Base = ((UINT32)PciConfigurationHeader.Bridge.MemoryBase & 0xfff0) << 16;
+ Limit = (((UINT32)PciConfigurationHeader.Bridge.MemoryLimit & 0xfff0) << 16) | 0xfffff;
+ if (Base < Limit) {
+ if (PrivateData->MemBase > Base) {
+ PrivateData->MemBase = Base;
+ }
+ if (PrivateData->MemLimit < Limit) {
+ PrivateData->MemLimit = Limit;
+ }
+ if (PrivateData->Mem32Base > Base) {
+ PrivateData->Mem32Base = Base;
+ }
+ if (PrivateData->Mem32Limit < Limit) {
+ PrivateData->Mem32Limit = Limit;
+ }
+ }
+
+ //
+ // Get the Prefetchable Memory range that the PPB is decoding
+ //
+ Value = PciConfigurationHeader.Bridge.PrefetchableMemoryBase & 0x0f;
+ Base = ((UINT32)PciConfigurationHeader.Bridge.PrefetchableMemoryBase & 0xfff0) << 16;
+ Limit = (((UINT32)PciConfigurationHeader.Bridge.PrefetchableMemoryLimit & 0xfff0) << 16) | 0xffffff;
+ if (Value == 0x01) {
+ Base |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.PrefetchableBaseUpper32,32);
+ Limit |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.PrefetchableLimitUpper32,32);
+ }
+ if (Base < Limit) {
+ if (PrivateData->MemBase > Base) {
+ PrivateData->MemBase = Base;
+ }
+ if (PrivateData->MemLimit < Limit) {
+ PrivateData->MemLimit = Limit;
+ }
+ if (Value == 0x00) {
+ if (PrivateData->Pmem32Base > Base) {
+ PrivateData->Pmem32Base = Base;
+ }
+ if (PrivateData->Pmem32Limit < Limit) {
+ PrivateData->Pmem32Limit = Limit;
+ }
+ }
+ if (Value == 0x01) {
+ if (PrivateData->Pmem64Base > Base) {
+ PrivateData->Pmem64Base = Base;
+ }
+ if (PrivateData->Pmem64Limit < Limit) {
+ PrivateData->Pmem64Limit = Limit;
+ }
+ }
+ }
+
+ //
+ // Look at the PPB Configuration for legacy decoding attributes
+ //
+ if (PciConfigurationHeader.Bridge.BridgeControl & 0x04) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
+ }
+ if (PciConfigurationHeader.Bridge.BridgeControl & 0x08) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
+ }
+
+ } else {
+ //
+ // Parse the BARs of the PCI device to determine what I/O Ranges,
+ // Memory Ranges, and Prefetchable Memory Ranges the device is decoding
+ //
+ if ((PciConfigurationHeader.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) {
+ Status = PcatPciRootBridgeParseBars (
+ PrivateData,
+ PciConfigurationHeader.Hdr.Command,
+ PrimaryBusIndex,
+ Device,
+ Function
+ );
+ }
+
+ //
+ // See if the PCI device is an IDE controller
+ //
+ if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x01 &&
+ PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ) {
+ if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x80) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
+ }
+ if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x01) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
+ }
+ if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x04) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
+ }
+ }
+
+ //
+ // See if the PCI device is a legacy VGA controller
+ //
+ if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x00 &&
+ PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
+ }
+
+ //
+ // See if the PCI device is a standard VGA controller
+ //
+ if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x03 &&
+ PciConfigurationHeader.Hdr.ClassCode[1] == 0x00 ) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
+ }
+
+ //
+ // See if the PCI Device is a PCI - ISA or PCI - EISA
+ // or ISA_POSITIVIE_DECODE Bridge device
+ //
+ if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x06) {
+ if (PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ||
+ PciConfigurationHeader.Hdr.ClassCode[1] == 0x02 ||
+ PciConfigurationHeader.Hdr.ClassCode[1] == 0x80 ) {
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
+ PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
+
+ if (PrivateData->MemBase > 0xa0000) {
+ PrivateData->MemBase = 0xa0000;
+ }
+ if (PrivateData->MemLimit < 0xbffff) {
+ PrivateData->MemLimit = 0xbffff;
+ }
+ }
+ }
+ }
+
+ //
+ // If this device is not a multi function device, then skip the rest of this PCI device
+ //
+ if (Function == 0 && !(PciConfigurationHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION)) {
+ break;
+ }
+ }
+ }
+
+ //
+ // After scanning all the PCI devices on the PCI root bridge's primary bus, update the
+ // Primary Bus Number for the next PCI root bridge to be this PCI root bridge's subordinate
+ // bus number + 1.
+ //
+ PrimaryBusIndex = PrivateData->SubordinateBus + 1;
+
+ //
+ // If at least one PCI device was found on the primary bus of this PCI root bridge, then the PCI root bridge
+ // exists.
+ //
+ if (NumberOfPciDevices > 0) {
+
+ //
+ // Adjust the I/O range used for bounds checking for the legacy decoding attributed
+ //
+ if (PrivateData->Attributes & 0x7f) {
+ PrivateData->IoBase = 0;
+ if (PrivateData->IoLimit < 0xffff) {
+ PrivateData->IoLimit = 0xffff;
+ }
+ }
+
+ //
+ // Adjust the Memory range used for bounds checking for the legacy decoding attributed
+ //
+ if (PrivateData->Attributes & EFI_PCI_ATTRIBUTE_VGA_MEMORY) {
+ if (PrivateData->MemBase > 0xa0000) {
+ PrivateData->MemBase = 0xa0000;
+ }
+ if (PrivateData->MemLimit < 0xbffff) {
+ PrivateData->MemLimit = 0xbffff;
+ }
+ }
+
+ //
+ // Build ACPI descriptors for the resources on the PCI Root Bridge
+ //
+ Status = ConstructConfiguration(PrivateData);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Create the handle for this PCI Root Bridge
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &PrivateData->Handle,
+ &gEfiDevicePathProtocolGuid,
+ PrivateData->DevicePath,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ &PrivateData->Io,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Contruct DeviceIoProtocol
+ //
+ Status = DeviceIoConstructor (
+ PrivateData->Handle,
+ &PrivateData->Io,
+ PrivateData->DevicePath,
+ (UINT16)PrivateData->PrimaryBus,
+ (UINT16)PrivateData->SubordinateBus
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Scan this PCI Root Bridge for PCI Option ROMs and add them to the PCI Option ROM Table
+ //
+ Status = ScanPciRootBridgeForRoms(&PrivateData->Io);
+
+ //
+ // Increment the index for the next PCI Root Bridge
+ //
+ PciRootBridgeIndex++;
+
+ } else {
+
+ //
+ // If no PCI Root Bridges were found on the current PCI segment, then exit
+ //
+ if (NumberOfPciRootBridges == 0) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ }
+
+ //
+ // If the PrimaryBusIndex is greater than the maximum allowable PCI bus number, then
+ // the PCI Segment Number is incremented, and the next segment is searched starting at Bus #0
+ // Otherwise, the search is continued on the next PCI Root Bridge
+ //
+ if (PrimaryBusIndex > PCI_MAX_BUS) {
+ PciSegmentIndex++;
+ NumberOfPciRootBridges = 0;
+ PrimaryBusIndex = 0;
+ } else {
+ NumberOfPciRootBridges++;
+ }
+
+ }
+
+ return EFI_SUCCESS;
+
+Done:
+ //
+ // Clean up memory allocated for the PCI Root Bridge that was searched but not created.
+ //
+ if (PrivateData) {
+ if (PrivateData->DevicePath) {
+ gBS->FreePool(PrivateData->DevicePath);
+ }
+ gBS->FreePool (PrivateData);
+ }
+
+ //
+ // If no PCI Root Bridges were discovered, then return the error condition from scanning the
+ // first PCI Root Bridge
+ //
+ if (PciRootBridgeIndex == 0) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ConstructConfiguration(
+ IN OUT PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+
+{
+ EFI_STATUS Status;
+ UINT8 NumConfig;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;
+ EFI_ACPI_END_TAG_DESCRIPTOR *ConfigurationEnd;
+
+ NumConfig = 0;
+ PrivateData->Configuration = NULL;
+
+ if (PrivateData->SubordinateBus >= PrivateData->PrimaryBus) {
+ NumConfig++;
+ }
+ if (PrivateData->IoLimit >= PrivateData->IoBase) {
+ NumConfig++;
+ }
+ if (PrivateData->Mem32Limit >= PrivateData->Mem32Base) {
+ NumConfig++;
+ }
+ if (PrivateData->Pmem32Limit >= PrivateData->Pmem32Base) {
+ NumConfig++;
+ }
+ if (PrivateData->Mem64Limit >= PrivateData->Mem64Base) {
+ NumConfig++;
+ }
+ if (PrivateData->Pmem64Limit >= PrivateData->Pmem64Base) {
+ NumConfig++;
+ }
+
+ if ( NumConfig == 0 ) {
+
+ //
+ // If there is no resource request
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
+ &PrivateData->Configuration
+ );
+ if (EFI_ERROR (Status )) {
+ return Status;
+ }
+
+ Configuration = PrivateData->Configuration;
+
+ ZeroMem (
+ Configuration,
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
+ );
+
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ Configuration++;
+
+ ConfigurationEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Configuration);
+ ConfigurationEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
+ ConfigurationEnd->Checksum = 0;
+ }
+
+ //
+ // If there is at least one type of resource request,
+ // allocate a acpi resource node
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
+ &PrivateData->Configuration
+ );
+ if (EFI_ERROR (Status )) {
+ return Status;
+ }
+
+ Configuration = PrivateData->Configuration;
+
+ ZeroMem (
+ Configuration,
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
+ );
+
+ if (PrivateData->SubordinateBus >= PrivateData->PrimaryBus) {
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;
+ Configuration->SpecificFlag = 0;
+ Configuration->AddrRangeMin = PrivateData->PrimaryBus;
+ Configuration->AddrRangeMax = PrivateData->SubordinateBus;
+ Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
+ Configuration++;
+ }
+ //
+ // Deal with io aperture
+ //
+ if (PrivateData->IoLimit >= PrivateData->IoBase) {
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
+ Configuration->SpecificFlag = 1; //non ISA range
+ Configuration->AddrRangeMin = PrivateData->IoBase;
+ Configuration->AddrRangeMax = PrivateData->IoLimit;
+ Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
+ Configuration++;
+ }
+
+ //
+ // Deal with mem32 aperture
+ //
+ if (PrivateData->Mem32Limit >= PrivateData->Mem32Base) {
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ Configuration->SpecificFlag = 0; //Nonprefechable
+ Configuration->AddrSpaceGranularity = 32; //32 bit
+ Configuration->AddrRangeMin = PrivateData->Mem32Base;
+ Configuration->AddrRangeMax = PrivateData->Mem32Limit;
+ Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
+ Configuration++;
+ }
+
+ //
+ // Deal with Pmem32 aperture
+ //
+ if (PrivateData->Pmem32Limit >= PrivateData->Pmem32Base) {
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ Configuration->SpecificFlag = 0x6; //prefechable
+ Configuration->AddrSpaceGranularity = 32; //32 bit
+ Configuration->AddrRangeMin = PrivateData->Pmem32Base;
+ Configuration->AddrRangeMax = PrivateData->Pmem32Limit;
+ Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
+ Configuration++;
+ }
+
+ //
+ // Deal with mem64 aperture
+ //
+ if (PrivateData->Mem64Limit >= PrivateData->Mem64Base) {
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ Configuration->SpecificFlag = 0; //nonprefechable
+ Configuration->AddrSpaceGranularity = 64; //32 bit
+ Configuration->AddrRangeMin = PrivateData->Mem64Base;
+ Configuration->AddrRangeMax = PrivateData->Mem64Limit;
+ Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
+ Configuration++;
+ }
+
+ //
+ // Deal with Pmem64 aperture
+ //
+ if (PrivateData->Pmem64Limit >= PrivateData->Pmem64Base) {
+ Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ Configuration->SpecificFlag = 0x06; //prefechable
+ Configuration->AddrSpaceGranularity = 64; //32 bit
+ Configuration->AddrRangeMin = PrivateData->Pmem64Base;
+ Configuration->AddrRangeMax = PrivateData->Pmem64Limit;
+ Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;
+ Configuration++;
+ }
+
+ //
+ // put the checksum
+ //
+ ConfigurationEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Configuration);
+ ConfigurationEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
+ ConfigurationEnd->Checksum = 0;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PcatPciRootBridgeBarExisted (
+ IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT64 Address,
+ OUT UINT32 *OriginalValue,
+ OUT UINT32 *Value
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 AllOnes;
+ EFI_TPL OldTpl;
+
+ //
+ // Preserve the original value
+ //
+ Status = PrivateData->Io.Pci.Read (
+ &PrivateData->Io,
+ EfiPciWidthUint32,
+ Address,
+ 1,
+ OriginalValue
+ );
+
+ //
+ // Raise TPL to high level to disable timer interrupt while the BAR is probed
+ //
+ OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+ AllOnes = 0xffffffff;
+
+ Status = PrivateData->Io.Pci.Write (
+ &PrivateData->Io,
+ EfiPciWidthUint32,
+ Address,
+ 1,
+ &AllOnes
+ );
+ Status = PrivateData->Io.Pci.Read (
+ &PrivateData->Io,
+ EfiPciWidthUint32,
+ Address,
+ 1,
+ Value
+ );
+
+ //
+ //Write back the original value
+ //
+ Status = PrivateData->Io.Pci.Write (
+ &PrivateData->Io,
+ EfiPciWidthUint32,
+ Address,
+ 1,
+ OriginalValue
+ );
+
+ //
+ // Restore TPL to its original level
+ //
+ gBS->RestoreTPL (OldTpl);
+
+ if ( *Value == 0 ) {
+ return EFI_DEVICE_ERROR;
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PcatPciRootBridgeParseBars (
+ IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT16 Command,
+ IN UINTN Bus,
+ IN UINTN Device,
+ IN UINTN Function
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT64 Address;
+ UINT32 OriginalValue;
+ UINT32 Value;
+ UINT32 OriginalUpperValue;
+ UINT32 UpperValue;
+ UINT64 Mask;
+ UINTN Offset;
+ UINT64 Base;
+ UINT64 Length;
+ UINT64 Limit;
+
+ for (Offset = 0x10; Offset < 0x28; Offset += 4) {
+ Address = EFI_PCI_ADDRESS (Bus, Device, Function, Offset);
+ Status = PcatPciRootBridgeBarExisted (
+ PrivateData,
+ Address,
+ &OriginalValue,
+ &Value
+ );
+
+ if (!EFI_ERROR (Status )) {
+ if ( Value & 0x01 ) {
+ if (Command & 0x0001) {
+ //
+ //Device I/Os
+ //
+ Mask = 0xfffffffc;
+ Base = OriginalValue & Mask;
+ Length = ((~(Value & Mask)) & Mask) + 0x04;
+ if (!(Value & 0xFFFF0000)){
+ Length &= 0x0000FFFF;
+ }
+ Limit = Base + Length - 1;
+
+ if (Base < Limit) {
+ if (PrivateData->IoBase > Base) {
+ PrivateData->IoBase = (UINT32)Base;
+ }
+ if (PrivateData->IoLimit < Limit) {
+ PrivateData->IoLimit = (UINT32)Limit;
+ }
+ }
+ }
+
+ } else {
+
+ if (Command & 0x0002) {
+
+ Mask = 0xfffffff0;
+ Base = OriginalValue & Mask;
+ Length = Value & Mask;
+
+ if ((Value & 0x07) != 0x04) {
+ Length = ((~Length) + 1) & 0xffffffff;
+ } else {
+ Offset += 4;
+ Address = EFI_PCI_ADDRESS (Bus, Device, Function, Offset);
+
+ Status = PcatPciRootBridgeBarExisted (
+ PrivateData,
+ Address,
+ &OriginalUpperValue,
+ &UpperValue
+ );
+
+ Base = Base | LShiftU64((UINT64)OriginalUpperValue,32);
+ Length = Length | LShiftU64((UINT64)UpperValue,32);
+ Length = (~Length) + 1;
+ }
+
+ Limit = Base + Length - 1;
+
+ if (Base < Limit) {
+ if (PrivateData->MemBase > Base) {
+ PrivateData->MemBase = Base;
+ }
+ if (PrivateData->MemLimit < Limit) {
+ PrivateData->MemLimit = Limit;
+ }
+
+ switch (Value &0x07) {
+ case 0x00: ////memory space; anywhere in 32 bit address space
+ if (Value & 0x08) {
+ if (PrivateData->Pmem32Base > Base) {
+ PrivateData->Pmem32Base = Base;
+ }
+ if (PrivateData->Pmem32Limit < Limit) {
+ PrivateData->Pmem32Limit = Limit;
+ }
+ } else {
+ if (PrivateData->Mem32Base > Base) {
+ PrivateData->Mem32Base = Base;
+ }
+ if (PrivateData->Mem32Limit < Limit) {
+ PrivateData->Mem32Limit = Limit;
+ }
+ }
+ break;
+ case 0x04: //memory space; anywhere in 64 bit address space
+ if (Value & 0x08) {
+ if (PrivateData->Pmem64Base > Base) {
+ PrivateData->Pmem64Base = Base;
+ }
+ if (PrivateData->Pmem64Limit < Limit) {
+ PrivateData->Pmem64Limit = Limit;
+ }
+ } else {
+ if (PrivateData->Mem64Base > Base) {
+ PrivateData->Mem64Base = Base;
+ }
+ if (PrivateData->Mem64Limit < Limit) {
+ PrivateData->Mem64Limit = Limit;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+UINT64
+GetPciExpressBaseAddressForRootBridge (
+ IN UINTN HostBridgeNumber,
+ IN UINTN RootBridgeNumber
+ )
+/*++
+
+Routine Description:
+ This routine is to get PciExpress Base Address for this RootBridge
+
+Arguments:
+ HostBridgeNumber - The number of HostBridge
+ RootBridgeNumber - The number of RootBridge
+
+Returns:
+ UINT64 - PciExpressBaseAddress for this HostBridge and RootBridge
+
+--*/
+{
+ EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION *PciExpressBaseAddressInfo;
+ UINTN BufferSize;
+ UINT32 Index;
+ UINT32 Number;
+ VOID *HobList;
+ EFI_STATUS Status;
+ EFI_PEI_HOB_POINTERS GuidHob;
+
+ //
+ // Get Hob List from configuration table
+ //
+ Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);
+ if (EFI_ERROR (Status)) {
+ return 0;
+ }
+
+ //
+ // Get PciExpressAddressInfo Hob
+ //
+ PciExpressBaseAddressInfo = NULL;
+ BufferSize = 0;
+ GuidHob.Raw = GetNextGuidHob (&gEfiPciExpressBaseAddressGuid, &HobList);
+ if (GuidHob.Raw != NULL) {
+ PciExpressBaseAddressInfo = GET_GUID_HOB_DATA (GuidHob.Guid);
+ BufferSize = GET_GUID_HOB_DATA_SIZE (GuidHob.Guid);
+ } else {
+ return 0;
+ }
+
+ //
+ // Search the PciExpress Base Address in the Hob for current RootBridge
+ //
+ Number = (UINT32)(BufferSize / sizeof(EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION));
+ for (Index = 0; Index < Number; Index++) {
+ if ((PciExpressBaseAddressInfo[Index].HostBridgeNumber == HostBridgeNumber) &&
+ (PciExpressBaseAddressInfo[Index].RootBridgeNumber == RootBridgeNumber)) {
+ return PciExpressBaseAddressInfo[Index].PciExpressBaseAddress;
+ }
+ }
+
+ //
+ // Do not find the PciExpress Base Address in the Hob
+ //
+ return 0;
+}
+
diff --git a/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.h b/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.h
new file mode 100644
index 0000000000..50bd9b43b2
--- /dev/null
+++ b/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.h
@@ -0,0 +1,215 @@
+/*++
+
+Copyright (c) 2005 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ PcatPciRootBridge.h
+
+Abstract:
+
+ The driver for the host to pci bridge (root bridge).
+
+--*/
+
+#ifndef _PCAT_PCI_ROOT_BRIDGE_H_
+#define _PCAT_PCI_ROOT_BRIDGE_H_
+
+#include <PiDxe.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/DeviceIo.h>
+#include <Protocol/CpuIo.h>
+
+#include <Library/UefiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HobLib.h>
+
+#include <Guid/PciOptionRomTable.h>
+#include <Guid/HobList.h>
+#include <Guid/PciExpressBaseAddress.h>
+
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Pci.h>
+//
+// Driver Instance Data Prototypes
+//
+#define PCAT_PCI_ROOT_BRIDGE_SIGNATURE EFI_SIGNATURE_32('p', 'c', 'r', 'b')
+
+typedef struct {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io;
+ EFI_CPU_IO_PROTOCOL *CpuIo;
+
+ UINT32 RootBridgeNumber;
+ UINT32 PrimaryBus;
+ UINT32 SubordinateBus;
+
+ UINT64 MemBase; // Offsets host to bus memory addr.
+ UINT64 MemLimit; // Max allowable memory access
+
+ UINT64 IoBase; // Offsets host to bus io addr.
+ UINT64 IoLimit; // Max allowable io access
+
+ UINT64 PciAddress;
+ UINT64 PciData;
+
+ UINT64 PhysicalMemoryBase;
+ UINT64 PhysicalIoBase;
+
+ EFI_LOCK PciLock;
+
+ UINT64 Attributes;
+
+ UINT64 Mem32Base;
+ UINT64 Mem32Limit;
+ UINT64 Pmem32Base;
+ UINT64 Pmem32Limit;
+ UINT64 Mem64Base;
+ UINT64 Mem64Limit;
+ UINT64 Pmem64Base;
+ UINT64 Pmem64Limit;
+
+ UINT64 PciExpressBaseAddress;
+
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;
+
+ LIST_ENTRY MapInfo;
+} PCAT_PCI_ROOT_BRIDGE_INSTANCE;
+
+//
+// Driver Instance Data Macros
+//
+#define DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) \
+ CR(a, PCAT_PCI_ROOT_BRIDGE_INSTANCE, Io, PCAT_PCI_ROOT_BRIDGE_SIGNATURE)
+
+#define VOLATILE volatile
+//
+// Private data types
+//
+typedef union {
+ UINT8 VOLATILE *buf;
+ UINT8 VOLATILE *ui8;
+ UINT16 VOLATILE *ui16;
+ UINT32 VOLATILE *ui32;
+ UINT64 VOLATILE *ui64;
+ UINTN VOLATILE ui;
+} PTR;
+
+typedef struct {
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation;
+ UINTN NumberOfBytes;
+ UINTN NumberOfPages;
+ EFI_PHYSICAL_ADDRESS HostAddress;
+ EFI_PHYSICAL_ADDRESS MappedHostAddress;
+} MAP_INFO;
+
+typedef struct {
+ LIST_ENTRY Link;
+ MAP_INFO * Map;
+} MAP_INFO_INSTANCE;
+
+typedef
+VOID
+(*EFI_PCI_BUS_SCAN_CALLBACK) (
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ UINT16 MinBus,
+ UINT16 MaxBus,
+ UINT16 MinDevice,
+ UINT16 MaxDevice,
+ UINT16 MinFunc,
+ UINT16 MaxFunc,
+ UINT16 Bus,
+ UINT16 Device,
+ UINT16 Func,
+ IN VOID *Context
+ );
+
+typedef struct {
+ UINT16 *CommandRegisterBuffer;
+ UINT32 PpbMemoryWindow;
+} PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT;
+
+//
+// Driver Protocol Constructor Prototypes
+//
+EFI_STATUS
+ConstructConfiguration(
+ IN OUT PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData
+ );
+
+EFI_STATUS
+PcatPciRootBridgeParseBars (
+ IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT16 Command,
+ IN UINTN Bus,
+ IN UINTN Device,
+ IN UINTN Function
+ );
+
+EFI_STATUS
+ScanPciRootBridgeForRoms(
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev
+ );
+
+EFI_STATUS
+PcatRootBridgeDevicePathConstructor (
+ IN EFI_DEVICE_PATH_PROTOCOL **Protocol,
+ IN UINTN RootBridgeNumber,
+ IN BOOLEAN IsPciExpress
+ );
+
+EFI_STATUS
+PcatRootBridgeIoConstructor (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol,
+ IN UINTN SegmentNumber
+ );
+
+EFI_STATUS
+PcatRootBridgeIoGetIoPortMapping (
+ OUT EFI_PHYSICAL_ADDRESS *IoPortMapping,
+ OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping
+ );
+
+EFI_STATUS
+PcatRootBridgeIoPciRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ );
+
+UINT64
+GetPciExpressBaseAddressForRootBridge (
+ IN UINTN HostBridgeNumber,
+ IN UINTN RootBridgeNumber
+ );
+
+//
+// Driver entry point prototype
+//
+EFI_STATUS
+EFIAPI
+InitializePcatPciRootBridge (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+extern EFI_CPU_IO_PROTOCOL *gCpuIo;
+
+#endif
diff --git a/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeDevicePath.c b/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeDevicePath.c
new file mode 100644
index 0000000000..ab1b5d8c56
--- /dev/null
+++ b/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeDevicePath.c
@@ -0,0 +1,87 @@
+/*++
+
+Copyright (c) 2005 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ PcatPciRootBridgeDevicePath.c
+
+Abstract:
+
+ EFI PCAT PCI Root Bridge Device Path Protocol
+
+Revision History
+
+--*/
+
+#include "PcatPciRootBridge.h"
+
+//
+// Static device path declarations for this driver.
+//
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH AcpiDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
+
+static EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath = {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8),
+ EISA_PNP_ID(0x0A03),
+ 0
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+};
+
+EFI_STATUS
+PcatRootBridgeDevicePathConstructor (
+ IN EFI_DEVICE_PATH_PROTOCOL **Protocol,
+ IN UINTN RootBridgeNumber,
+ IN BOOLEAN IsPciExpress
+ )
+/*++
+
+Routine Description:
+
+ Construct the device path protocol
+
+Arguments:
+
+ Protocol - protocol to initialize
+
+Returns:
+
+ None
+
+--*/
+{
+ ACPI_HID_DEVICE_PATH *AcpiDevicePath;
+
+ *Protocol = DuplicateDevicePath((EFI_DEVICE_PATH_PROTOCOL *)(&mEfiPciRootBridgeDevicePath));
+
+ AcpiDevicePath = (ACPI_HID_DEVICE_PATH *)(*Protocol);
+
+ AcpiDevicePath->UID = (UINT32)RootBridgeNumber;
+
+ if (IsPciExpress) {
+ AcpiDevicePath->HID = EISA_PNP_ID(0x0A08);
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeIo.c b/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeIo.c
new file mode 100644
index 0000000000..abb6acbd96
--- /dev/null
+++ b/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeIo.c
@@ -0,0 +1,1054 @@
+/*++
+
+Copyright (c) 2005 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ PcatPciRootBridgeIo.c
+
+Abstract:
+
+ EFI PC AT PCI Root Bridge Io Protocol
+
+Revision History
+
+--*/
+
+#include "PcatPciRootBridge.h"
+
+//
+// Protocol Member Function Prototypes
+//
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoPollMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoPollIo (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoCopyMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 DestAddress,
+ IN UINT64 SrcAddress,
+ IN UINTN Count
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoPciRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoPciWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoMap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoUnmap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoAllocateBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoFreeBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ OUT VOID *HostAddress
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoFlush (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoGetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT UINT64 *Supported,
+ OUT UINT64 *Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoSetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN OUT UINT64 *ResourceBase,
+ IN OUT UINT64 *ResourceLength
+ );
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoConfiguration (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT VOID **Resources
+ );
+
+//
+// Private Function Prototypes
+//
+STATIC
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoMemRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINTN Count,
+ IN BOOLEAN InStrideFlag,
+ IN PTR In,
+ IN BOOLEAN OutStrideFlag,
+ OUT PTR Out
+ );
+
+EFI_STATUS
+PcatRootBridgeIoConstructor (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol,
+ IN UINTN SegmentNumber
+ )
+/*++
+
+Routine Description:
+
+ Contruct the Pci Root Bridge Io protocol
+
+Arguments:
+
+ Protocol - protocol to initialize
+
+Returns:
+
+ None
+
+--*/
+{
+ Protocol->ParentHandle = NULL;
+
+ Protocol->PollMem = PcatRootBridgeIoPollMem;
+ Protocol->PollIo = PcatRootBridgeIoPollIo;
+
+ Protocol->Mem.Read = PcatRootBridgeIoMemRead;
+ Protocol->Mem.Write = PcatRootBridgeIoMemWrite;
+
+ Protocol->Io.Read = PcatRootBridgeIoIoRead;
+ Protocol->Io.Write = PcatRootBridgeIoIoWrite;
+
+ Protocol->CopyMem = PcatRootBridgeIoCopyMem;
+
+ Protocol->Pci.Read = PcatRootBridgeIoPciRead;
+ Protocol->Pci.Write = PcatRootBridgeIoPciWrite;
+
+ Protocol->Map = PcatRootBridgeIoMap;
+ Protocol->Unmap = PcatRootBridgeIoUnmap;
+
+ Protocol->AllocateBuffer = PcatRootBridgeIoAllocateBuffer;
+ Protocol->FreeBuffer = PcatRootBridgeIoFreeBuffer;
+
+ Protocol->Flush = PcatRootBridgeIoFlush;
+
+ Protocol->GetAttributes = PcatRootBridgeIoGetAttributes;
+ Protocol->SetAttributes = PcatRootBridgeIoSetAttributes;
+
+ Protocol->Configuration = PcatRootBridgeIoConfiguration;
+
+ Protocol->SegmentNumber = (UINT32)SegmentNumber;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoPollMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+{
+ EFI_STATUS Status;
+ UINT64 NumberOfTicks;
+ UINTN Remainder;
+
+ if (Result == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+
+ if (Width < 0 || Width > EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // No matter what, always do a single poll.
+ //
+ Status = This->Mem.Read (This, Width, Address, 1, Result);
+ if ( EFI_ERROR(Status) ) {
+ return Status;
+ }
+ if ( (*Result & Mask) == Value ) {
+ return EFI_SUCCESS;
+ }
+
+ if ( Delay != 0 ) {
+
+ NumberOfTicks = DivU64x32Remainder (Delay, 100, &Remainder);
+ if ( Remainder !=0 ) {
+ NumberOfTicks += 1;
+ }
+ NumberOfTicks += 1;
+
+ while ( NumberOfTicks ) {
+
+ gBS->Stall (10);
+
+ Status = This->Mem.Read (This, Width, Address, 1, Result);
+ if ( EFI_ERROR(Status) ) {
+ return Status;
+ }
+
+ if ( (*Result & Mask) == Value ) {
+ return EFI_SUCCESS;
+ }
+
+ NumberOfTicks -= 1;
+ }
+ }
+ return EFI_TIMEOUT;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoPollIo (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+{
+ EFI_STATUS Status;
+ UINT64 NumberOfTicks;
+ UINTN Remainder;
+
+ if (Result == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width < 0 || Width > EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // No matter what, always do a single poll.
+ //
+ Status = This->Io.Read (This, Width, Address, 1, Result);
+ if ( EFI_ERROR(Status) ) {
+ return Status;
+ }
+ if ( (*Result & Mask) == Value ) {
+ return EFI_SUCCESS;
+ }
+
+ if (Delay != 0) {
+
+ NumberOfTicks = DivU64x32Remainder (Delay, 100, &Remainder);
+ if ( Remainder !=0 ) {
+ NumberOfTicks += 1;
+ }
+ NumberOfTicks += 1;
+
+ while ( NumberOfTicks ) {
+
+ gBS->Stall(10);
+
+ Status = This->Io.Read (This, Width, Address, 1, Result);
+ if ( EFI_ERROR(Status) ) {
+ return Status;
+ }
+
+ if ( (*Result & Mask) == Value ) {
+ return EFI_SUCCESS;
+ }
+
+ NumberOfTicks -= 1;
+ }
+ }
+ return EFI_TIMEOUT;
+}
+
+BOOLEAN
+PcatRootBridgeMemAddressValid (
+ IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT64 Address
+ )
+{
+ if ((Address >= PrivateData->PciExpressBaseAddress) && (Address < PrivateData->PciExpressBaseAddress + 0x10000000)) {
+ return TRUE;
+ }
+ if ((Address >= PrivateData->MemBase) && (Address < PrivateData->MemLimit)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ UINTN AlignMask;
+ PTR In;
+ PTR Out;
+
+ if ( Buffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ if (!PcatRootBridgeMemAddressValid (PrivateData, Address)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AlignMask = (1 << (Width & 0x03)) - 1;
+ if (Address & AlignMask) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Address += PrivateData->PhysicalMemoryBase;
+
+ In.buf = Buffer;
+ Out.buf = (VOID *)(UINTN) Address;
+ if (Width >= EfiPciWidthUint8 && Width <= EfiPciWidthUint64) {
+ return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
+ }
+ if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+ return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
+ }
+ if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
+ return PcatRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ UINTN AlignMask;
+ PTR In;
+ PTR Out;
+
+ if ( Buffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ if (!PcatRootBridgeMemAddressValid (PrivateData, Address)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AlignMask = (1 << (Width & 0x03)) - 1;
+ if (Address & AlignMask) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Address += PrivateData->PhysicalMemoryBase;
+
+ In.buf = (VOID *)(UINTN) Address;
+ Out.buf = Buffer;
+ if (Width >= EfiPciWidthUint8 && Width <= EfiPciWidthUint64) {
+ return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
+ }
+ if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+ return PcatRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
+ }
+ if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
+ return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoCopyMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 DestAddress,
+ IN UINT64 SrcAddress,
+ IN UINTN Count
+ )
+
+{
+ EFI_STATUS Status;
+ BOOLEAN Direction;
+ UINTN Stride;
+ UINTN Index;
+ UINT64 Result;
+
+ if (Width < 0 || Width > EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DestAddress == SrcAddress) {
+ return EFI_SUCCESS;
+ }
+
+ Stride = (UINTN)1 << Width;
+
+ Direction = TRUE;
+ if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {
+ Direction = FALSE;
+ SrcAddress = SrcAddress + (Count-1) * Stride;
+ DestAddress = DestAddress + (Count-1) * Stride;
+ }
+
+ for (Index = 0;Index < Count;Index++) {
+ Status = PcatRootBridgeIoMemRead (
+ This,
+ Width,
+ SrcAddress,
+ 1,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = PcatRootBridgeIoMemWrite (
+ This,
+ Width,
+ DestAddress,
+ 1,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (Direction) {
+ SrcAddress += Stride;
+ DestAddress += Stride;
+ } else {
+ SrcAddress -= Stride;
+ DestAddress -= Stride;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoPciRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return PcatRootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoPciWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return PcatRootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoMap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;
+ MAP_INFO *MapInfo;
+ MAP_INFO_INSTANCE *MapInstance;
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ if ( HostAddress == NULL || NumberOfBytes == NULL ||
+ DeviceAddress == NULL || Mapping == NULL ) {
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Perform a fence operation to make sure all memory operations are flushed
+ //
+ MemoryFence();
+
+ //
+ // Initialize the return values to their defaults
+ //
+ *Mapping = NULL;
+
+ //
+ // Make sure that Operation is valid
+ //
+ if (Operation < 0 || Operation >= EfiPciOperationMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Most PCAT like chipsets can not handle performing DMA above 4GB.
+ // If any part of the DMA transfer being mapped is above 4GB, then
+ // map the DMA transfer to a buffer below 4GB.
+ //
+ PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;
+ if ((PhysicalAddress + *NumberOfBytes) > 0x100000000) {
+
+ //
+ // Common Buffer operations can not be remapped. If the common buffer
+ // if above 4GB, then it is not possible to generate a mapping, so return
+ // an error.
+ //
+ if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
+ // called later.
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof(MAP_INFO),
+ &MapInfo
+ );
+ if (EFI_ERROR (Status)) {
+ *NumberOfBytes = 0;
+ return Status;
+ }
+
+ //
+ // Return a pointer to the MAP_INFO structure in Mapping
+ //
+ *Mapping = MapInfo;
+
+ //
+ // Initialize the MAP_INFO structure
+ //
+ MapInfo->Operation = Operation;
+ MapInfo->NumberOfBytes = *NumberOfBytes;
+ MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES(*NumberOfBytes);
+ MapInfo->HostAddress = PhysicalAddress;
+ MapInfo->MappedHostAddress = 0x00000000ffffffff;
+
+ //
+ // Allocate a buffer below 4GB to map the transfer to.
+ //
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiBootServicesData,
+ MapInfo->NumberOfPages,
+ &MapInfo->MappedHostAddress
+ );
+ if (EFI_ERROR(Status)) {
+ gBS->FreePool (MapInfo);
+ *NumberOfBytes = 0;
+ return Status;
+ }
+
+ //
+ // If this is a read operation from the Bus Master's point of view,
+ // then copy the contents of the real buffer into the mapped buffer
+ // so the Bus Master can read the contents of the real buffer.
+ //
+ if (Operation == EfiPciOperationBusMasterRead || Operation == EfiPciOperationBusMasterRead64) {
+ CopyMem (
+ (VOID *)(UINTN)MapInfo->MappedHostAddress,
+ (VOID *)(UINTN)MapInfo->HostAddress,
+ MapInfo->NumberOfBytes
+ );
+ }
+
+
+ Status =gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof(MAP_INFO_INSTANCE),
+ &MapInstance
+ );
+ if (EFI_ERROR(Status)) {
+ gBS->FreePages (MapInfo->MappedHostAddress,MapInfo->NumberOfPages);
+ gBS->FreePool (MapInfo);
+ *NumberOfBytes = 0;
+ return Status;
+ }
+
+ MapInstance->Map=MapInfo;
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+ InsertTailList(&PrivateData->MapInfo,&MapInstance->Link);
+
+ //
+ // The DeviceAddress is the address of the maped buffer below 4GB
+ //
+ *DeviceAddress = MapInfo->MappedHostAddress;
+ } else {
+ //
+ // The transfer is below 4GB, so the DeviceAddress is simply the HostAddress
+ //
+ *DeviceAddress = PhysicalAddress;
+ }
+
+ //
+ // Perform a fence operation to make sure all memory operations are flushed
+ //
+ MemoryFence();
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoUnmap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+
+{
+ MAP_INFO *MapInfo;
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ LIST_ENTRY *Link;
+
+ //
+ // Perform a fence operation to make sure all memory operations are flushed
+ //
+ MemoryFence();
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+ //
+ // See if the Map() operation associated with this Unmap() required a mapping buffer.
+ // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.
+ //
+ if (Mapping != NULL) {
+ //
+ // Get the MAP_INFO structure from Mapping
+ //
+ MapInfo = (MAP_INFO *)Mapping;
+
+ for (Link = PrivateData->MapInfo.ForwardLink; Link != &PrivateData->MapInfo; Link = Link->ForwardLink) {
+ if (((MAP_INFO_INSTANCE*)Link)->Map == MapInfo)
+ break;
+ }
+
+ if (Link == &PrivateData->MapInfo) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RemoveEntryList(Link);
+ ((MAP_INFO_INSTANCE*)Link)->Map = NULL;
+ gBS->FreePool((MAP_INFO_INSTANCE*)Link);
+
+ //
+ // If this is a write operation from the Bus Master's point of view,
+ // then copy the contents of the mapped buffer into the real buffer
+ // so the processor can read the contents of the real buffer.
+ //
+ if (MapInfo->Operation == EfiPciOperationBusMasterWrite || MapInfo->Operation == EfiPciOperationBusMasterWrite64) {
+ CopyMem (
+ (VOID *)(UINTN)MapInfo->HostAddress,
+ (VOID *)(UINTN)MapInfo->MappedHostAddress,
+ MapInfo->NumberOfBytes
+ );
+ }
+
+ //
+ // Free the mapped buffer and the MAP_INFO structure.
+ //
+ gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);
+ gBS->FreePool (Mapping);
+ }
+
+ //
+ // Perform a fence operation to make sure all memory operations are flushed
+ //
+ MemoryFence();
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoAllocateBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;
+
+ //
+ // Validate Attributes
+ //
+ if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check for invalid inputs
+ //
+ if (HostAddress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
+ //
+ if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Limit allocations to memory below 4GB
+ //
+ PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(0xffffffff);
+
+ Status = gBS->AllocatePages (AllocateMaxAddress, MemoryType, Pages, &PhysicalAddress);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ *HostAddress = (VOID *)(UINTN)PhysicalAddress;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoFreeBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ OUT VOID *HostAddress
+ )
+
+{
+
+ if( HostAddress == NULL ){
+ return EFI_INVALID_PARAMETER;
+ }
+ return gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, Pages);
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoFlush (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
+ )
+
+{
+ //
+ // Perform a fence operation to make sure all memory operations are flushed
+ //
+ MemoryFence();
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoGetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT UINT64 *Supported, OPTIONAL
+ OUT UINT64 *Attributes
+ )
+
+{
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ if (Attributes == NULL && Supported == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Supported is an OPTIONAL parameter. See if it is NULL
+ //
+ if (Supported) {
+ //
+ // This is a generic driver for a PC-AT class system. It does not have any
+ // chipset specific knowlegde, so none of the attributes can be set or
+ // cleared. Any attempt to set attribute that are already set will succeed,
+ // and any attempt to set an attribute that is not supported will fail.
+ //
+ *Supported = PrivateData->Attributes;
+ }
+
+ //
+ // Set Attrbutes to the attributes detected when the PCI Root Bridge was initialized
+ //
+
+ if (Attributes) {
+ *Attributes = PrivateData->Attributes;
+ }
+
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoSetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN OUT UINT64 *ResourceBase,
+ IN OUT UINT64 *ResourceLength
+ )
+
+{
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ //
+ // This is a generic driver for a PC-AT class system. It does not have any
+ // chipset specific knowlegde, so none of the attributes can be set or
+ // cleared. Any attempt to set attribute that are already set will succeed,
+ // and any attempt to set an attribute that is not supported will fail.
+ //
+ if (Attributes & (~PrivateData->Attributes)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoConfiguration (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT VOID **Resources
+ )
+
+{
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ *Resources = PrivateData->Configuration;
+
+ return EFI_SUCCESS;
+}
+
+//
+// Internal function
+//
+
+STATIC
+EFI_STATUS
+EFIAPI
+PcatRootBridgeIoMemRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINTN Count,
+ IN BOOLEAN InStrideFlag,
+ IN PTR In,
+ IN BOOLEAN OutStrideFlag,
+ OUT PTR Out
+ )
+/*++
+
+Routine Description:
+
+ Private service to provide the memory read/write
+
+Arguments:
+
+ Width of the Memory Access
+ Count of the number of accesses to perform
+
+Returns:
+
+ Status
+
+ EFI_SUCCESS - Successful transaction
+ EFI_INVALID_PARAMETER - Unsupported width and address combination
+
+--*/
+{
+ UINTN Stride;
+ UINTN InStride;
+ UINTN OutStride;
+
+
+ Width = Width & 0x03;
+ Stride = (UINTN)1 << Width;
+ InStride = InStrideFlag ? Stride : 0;
+ OutStride = OutStrideFlag ? Stride : 0;
+
+ //
+ // Loop for each iteration and move the data
+ //
+ switch (Width) {
+ case EfiPciWidthUint8:
+ for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
+ MemoryFence();
+ *In.ui8 = *Out.ui8;
+ MemoryFence();
+ }
+ break;
+ case EfiPciWidthUint16:
+ for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
+ MemoryFence();
+ *In.ui16 = *Out.ui16;
+ MemoryFence();
+ }
+ break;
+ case EfiPciWidthUint32:
+ for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
+ MemoryFence();
+ *In.ui32 = *Out.ui32;
+ MemoryFence();
+ }
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf b/DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf
new file mode 100644
index 0000000000..fa0596db13
--- /dev/null
+++ b/DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf
@@ -0,0 +1,70 @@
+#/*++
+#
+# Copyright (c) 2005 - 2006, Intel Corporation
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+# Module Name:
+#
+# Abstract:
+#
+#--*/
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PcatPciRootBridge
+ FILE_GUID = 0F7EC77A-1EE1-400f-A99D-7CBD1FEB181E
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+ ENTRY_POINT = InitializePcatPciRootBridge
+
+[Packages]
+ MdePkg/MdePkg.dec
+ DuetPkg/DuetPkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UefiLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ DebugLib
+ BaseMemoryLib
+ DevicePathLib
+ HobLib
+
+[Sources.common]
+ PcatPciRootBridge.h
+ PcatPciRootBridge.c
+ PcatPciRootBridgeDevicePath.c
+ PcatPciRootBridgeIo.c
+ DeviceIo.h
+ DeviceIo.c
+
+[Sources.ia32]
+ ia32\PcatIo.c
+
+[Sources.x64]
+ x64\PcatIo.c
+
+[Sources.ipf]
+ Ipf\PcatIo.c
+
+[Protocols]
+ gEfiPciRootBridgeIoProtocolGuid
+ gEfiDeviceIoProtocolGuid
+ gEfiPciExpressBaseAddressGuid
+ gEfiCpuIoProtocolGuid
+
+[Guids]
+ gEfiPciOptionRomTableGuid \ No newline at end of file
diff --git a/DuetPkg/PciRootBridgeNoEnumerationDxe/x64/PcatIo.c b/DuetPkg/PciRootBridgeNoEnumerationDxe/x64/PcatIo.c
new file mode 100644
index 0000000000..830dcbb8c7
--- /dev/null
+++ b/DuetPkg/PciRootBridgeNoEnumerationDxe/x64/PcatIo.c
@@ -0,0 +1,732 @@
+/*++
+
+Copyright (c) 2005 - 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ PcatPciRootBridgeIo.c
+
+Abstract:
+
+ EFI PC AT PCI Root Bridge Io Protocol
+
+Revision History
+
+--*/
+
+#include "PcatPciRootBridge.h"
+
+static BOOLEAN mPciOptionRomTableInstalled = FALSE;
+static EFI_PCI_OPTION_ROM_TABLE mPciOptionRomTable = {0, NULL};
+
+EFI_STATUS
+PcatRootBridgeIoIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ )
+{
+ return gCpuIo->Io.Read (
+ gCpuIo,
+ (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
+ UserAddress,
+ Count,
+ UserBuffer
+ );
+}
+
+EFI_STATUS
+PcatRootBridgeIoIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ )
+{
+ return gCpuIo->Io.Write (
+ gCpuIo,
+ (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
+ UserAddress,
+ Count,
+ UserBuffer
+ );
+
+}
+
+EFI_STATUS
+PcatRootBridgeIoGetIoPortMapping (
+ OUT EFI_PHYSICAL_ADDRESS *IoPortMapping,
+ OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping
+ )
+/*++
+
+ Get the IO Port Mapping. For IA-32 it is always 0.
+
+--*/
+{
+ *IoPortMapping = 0;
+ *MemoryPortMapping = 0;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PcatRootBridgeIoPciRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ )
+{
+ PCI_CONFIG_ACCESS_CF8 Pci;
+ PCI_CONFIG_ACCESS_CF8 PciAligned;
+ UINT32 InStride;
+ UINT32 OutStride;
+ UINTN PciData;
+ UINTN PciDataStride;
+ PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress;
+ UINT64 PciExpressRegAddr;
+ BOOLEAN UsePciExpressAccess;
+
+ if (Width < 0 || Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Width & 0x03) >= EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+
+ InStride = 1 << (Width & 0x03);
+ OutStride = InStride;
+ if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
+ InStride = 0;
+ }
+
+ if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {
+ OutStride = 0;
+ }
+
+ UsePciExpressAccess = FALSE;
+
+ EfiCopyMem (&PciAddress, &UserAddress, sizeof(UINT64));
+
+ if (PciAddress.ExtendedRegister > 0xFF) {
+ //
+ // Check PciExpressBaseAddress
+ //
+ if ((PrivateData->PciExpressBaseAddress == 0) ||
+ (PrivateData->PciExpressBaseAddress >= EFI_MAX_ADDRESS)) {
+ return EFI_UNSUPPORTED;
+ } else {
+ UsePciExpressAccess = TRUE;
+ }
+ } else {
+ if (PciAddress.ExtendedRegister != 0) {
+ Pci.Reg = PciAddress.ExtendedRegister & 0xFF;
+ } else {
+ Pci.Reg = PciAddress.Register;
+ }
+ //
+ // Note: We can also use PciExpress access here, if wanted.
+ //
+ }
+
+ if (!UsePciExpressAccess) {
+ Pci.Func = PciAddress.Function;
+ Pci.Dev = PciAddress.Device;
+ Pci.Bus = PciAddress.Bus;
+ Pci.Reserved = 0;
+ Pci.Enable = 1;
+
+ //
+ // PCI Config access are all 32-bit alligned, but by accessing the
+ // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
+ // are possible on PCI.
+ //
+ // To read a byte of PCI config space you load 0xcf8 and
+ // read 0xcfc, 0xcfd, 0xcfe, 0xcff
+ //
+ PciDataStride = Pci.Reg & 0x03;
+
+ while (Count) {
+ PciAligned = Pci;
+ PciAligned.Reg &= 0xfc;
+ PciData = (UINTN)PrivateData->PciData + PciDataStride;
+ EfiAcquireLock(&PrivateData->PciLock);
+ This->Io.Write (This, EfiPciWidthUint32, PrivateData->PciAddress, 1, &PciAligned);
+ if (Write) {
+ This->Io.Write (This, Width, PciData, 1, UserBuffer);
+ } else {
+ This->Io.Read (This, Width, PciData, 1, UserBuffer);
+ }
+ EfiReleaseLock(&PrivateData->PciLock);
+ UserBuffer = ((UINT8 *)UserBuffer) + OutStride;
+ PciDataStride = (PciDataStride + InStride) % 4;
+ Pci.Reg += InStride;
+ Count -= 1;
+ }
+ } else {
+ //
+ // Access PCI-Express space by using memory mapped method.
+ //
+ PciExpressRegAddr = (PrivateData->PciExpressBaseAddress) |
+ (PciAddress.Bus << 20) |
+ (PciAddress.Device << 15) |
+ (PciAddress.Function << 12);
+ if (PciAddress.ExtendedRegister != 0) {
+ PciExpressRegAddr += PciAddress.ExtendedRegister;
+ } else {
+ PciExpressRegAddr += PciAddress.Register;
+ }
+ while (Count) {
+ if (Write) {
+ This->Mem.Write (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);
+ } else {
+ This->Mem.Read (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);
+ }
+
+ UserBuffer = ((UINT8 *) UserBuffer) + OutStride;
+ PciExpressRegAddr += InStride;
+ Count -= 1;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+static
+VOID
+ScanPciBus(
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ UINT16 MinBus,
+ UINT16 MaxBus,
+ UINT16 MinDevice,
+ UINT16 MaxDevice,
+ UINT16 MinFunc,
+ UINT16 MaxFunc,
+ EFI_PCI_BUS_SCAN_CALLBACK Callback,
+ VOID *Context
+ )
+
+{
+ UINT16 Bus;
+ UINT16 Device;
+ UINT16 Func;
+ UINT64 Address;
+ PCI_TYPE00 PciHeader;
+
+ //
+ // Loop through all busses
+ //
+ for (Bus = MinBus; Bus <= MaxBus; Bus++) {
+ //
+ // Loop 32 devices per bus
+ //
+ for (Device = MinDevice; Device <= MaxDevice; Device++) {
+ //
+ // Loop through 8 functions per device
+ //
+ for (Func = MinFunc; Func <= MaxFunc; Func++) {
+
+ //
+ // Compute the EFI Address required to access the PCI Configuration Header of this PCI Device
+ //
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
+
+ //
+ // Read the VendorID from this PCI Device's Confioguration Header
+ //
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &PciHeader.Hdr.VendorId);
+
+ //
+ // If VendorId = 0xffff, there does not exist a device at this
+ // location. For each device, if there is any function on it,
+ // there must be 1 function at Function 0. So if Func = 0, there
+ // will be no more functions in the same device, so we can break
+ // loop to deal with the next device.
+ //
+ if (PciHeader.Hdr.VendorId == 0xffff && Func == 0) {
+ break;
+ }
+
+ if (PciHeader.Hdr.VendorId != 0xffff) {
+
+ //
+ // Read the HeaderType to determine if this is a multi-function device
+ //
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint8, Address + 0x0e, 1, &PciHeader.Hdr.HeaderType);
+
+ //
+ // Call the callback function for the device that was found
+ //
+ Callback(
+ IoDev,
+ MinBus, MaxBus,
+ MinDevice, MaxDevice,
+ MinFunc, MaxFunc,
+ Bus,
+ Device,
+ Func,
+ Context
+ );
+
+ //
+ // If this is not a multi-function device, we can leave the loop
+ // to deal with the next device.
+ //
+ if ((PciHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x00 && Func == 0) {
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+static
+VOID
+CheckForRom (
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ UINT16 MinBus,
+ UINT16 MaxBus,
+ UINT16 MinDevice,
+ UINT16 MaxDevice,
+ UINT16 MinFunc,
+ UINT16 MaxFunc,
+ UINT16 Bus,
+ UINT16 Device,
+ UINT16 Func,
+ IN VOID *VoidContext
+ )
+{
+ EFI_STATUS Status;
+ PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;
+ UINT64 Address;
+ PCI_TYPE00 PciHeader;
+ PCI_TYPE01 *PciBridgeHeader;
+ UINT32 Register;
+ UINT32 RomBar;
+ UINT32 RomBarSize;
+ EFI_PHYSICAL_ADDRESS RomBuffer;
+ UINT32 MaxRomSize;
+ EFI_PCI_EXPANSION_ROM_HEADER EfiRomHeader;
+ PCI_DATA_STRUCTURE Pcir;
+ EFI_PCI_OPTION_ROM_DESCRIPTOR *TempPciOptionRomDescriptors;
+ BOOLEAN LastImage;
+
+ Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
+
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
+
+ //
+ // Save the contents of the PCI Configuration Header
+ //
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);
+
+ if (IS_PCI_BRIDGE(&PciHeader)) {
+
+ PciBridgeHeader = (PCI_TYPE01 *)(&PciHeader);
+
+ //
+ // See if the PCI-PCI Bridge has its secondary interface enabled.
+ //
+ if (PciBridgeHeader->Bridge.SubordinateBus >= PciBridgeHeader->Bridge.SecondaryBus) {
+
+ //
+ // Disable the Prefetchable Memory Window
+ //
+ Register = 0x00000000;
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x26, 1, &Register);
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x2c, 1, &Register);
+ Register = 0xffffffff;
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x24, 1, &Register);
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x28, 1, &Register);
+
+ //
+ // Program Memory Window to the PCI Root Bridge Memory Window
+ //
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x20, 4, &Context->PpbMemoryWindow);
+
+ //
+ // Enable the Memory decode for the PCI-PCI Bridge
+ //
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+ Register |= 0x02;
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+
+ //
+ // Recurse on the Secondary Bus Number
+ //
+ ScanPciBus(
+ IoDev,
+ PciBridgeHeader->Bridge.SecondaryBus, PciBridgeHeader->Bridge.SecondaryBus,
+ 0, PCI_MAX_DEVICE,
+ 0, PCI_MAX_FUNC,
+ CheckForRom, Context
+ );
+ }
+ } else {
+
+ //
+ // Check if an Option ROM Register is present and save the Option ROM Window Register
+ //
+ RomBar = 0xffffffff;
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
+
+ RomBarSize = (~(RomBar & 0xfffff800)) + 1;
+
+ //
+ // Make sure the size of the ROM is between 0 and 16 MB
+ //
+ if (RomBarSize > 0 && RomBarSize <= 0x01000000) {
+
+ //
+ // Program Option ROM Window Register to the PCI Root Bridge Window and Enable the Option ROM Window
+ //
+ RomBar = (Context->PpbMemoryWindow & 0xffff) << 16;
+ RomBar = ((RomBar - 1) & (~(RomBarSize - 1))) + RomBarSize;
+ if (RomBar < (Context->PpbMemoryWindow & 0xffff0000)) {
+ MaxRomSize = (Context->PpbMemoryWindow & 0xffff0000) - RomBar;
+ RomBar = RomBar + 1;
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
+ RomBar = RomBar - 1;
+
+ //
+ // Enable the Memory decode for the PCI Device
+ //
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+ Register |= 0x02;
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+
+ //
+ // Follow the chain of images to determine the size of the Option ROM present
+ // Keep going until the last image is found by looking at the Indicator field
+ // or the size of an image is 0, or the size of all the images is bigger than the
+ // size of the window programmed into the PPB.
+ //
+ RomBarSize = 0;
+ do {
+
+ LastImage = TRUE;
+
+ EfiZeroMem (&EfiRomHeader, sizeof(EfiRomHeader));
+ IoDev->Mem.Read (
+ IoDev,
+ EfiPciWidthUint8,
+ RomBar + RomBarSize,
+ sizeof(EfiRomHeader),
+ &EfiRomHeader
+ );
+
+ Pcir.ImageLength = 0;
+
+ if (EfiRomHeader.Signature == 0xaa55) {
+
+ EfiZeroMem (&Pcir, sizeof(Pcir));
+ IoDev->Mem.Read (
+ IoDev,
+ EfiPciWidthUint8,
+ RomBar + RomBarSize + EfiRomHeader.PcirOffset,
+ sizeof(Pcir),
+ &Pcir
+ );
+
+ if ((Pcir.Indicator & 0x80) == 0x00) {
+ LastImage = FALSE;
+ }
+
+ RomBarSize += Pcir.ImageLength * 512;
+ }
+ } while (!LastImage && RomBarSize < MaxRomSize && Pcir.ImageLength !=0);
+
+ if (RomBarSize > 0) {
+
+ //
+ // Allocate a memory buffer for the Option ROM contents.
+ //
+ Status = gBS->AllocatePages(
+ AllocateAnyPages,
+ EfiBootServicesData,
+ EFI_SIZE_TO_PAGES(RomBarSize),
+ &RomBuffer
+ );
+
+ if (!EFI_ERROR (Status)) {
+
+ //
+ // Copy the contents of the Option ROM to the memory buffer
+ //
+ IoDev->Mem.Read (IoDev, EfiPciWidthUint32, RomBar, RomBarSize / sizeof(UINT32), (VOID *)(UINTN)RomBuffer);
+
+ Status = gBS->AllocatePool(
+ EfiBootServicesData,
+ ((UINT32)mPciOptionRomTable.PciOptionRomCount + 1) * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR),
+ &TempPciOptionRomDescriptors
+ );
+ if (mPciOptionRomTable.PciOptionRomCount > 0) {
+ EfiCopyMem(
+ TempPciOptionRomDescriptors,
+ mPciOptionRomTable.PciOptionRomDescriptors,
+ (UINT32)mPciOptionRomTable.PciOptionRomCount * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR)
+ );
+
+ gBS->FreePool(mPciOptionRomTable.PciOptionRomDescriptors);
+ }
+
+ mPciOptionRomTable.PciOptionRomDescriptors = TempPciOptionRomDescriptors;
+
+ TempPciOptionRomDescriptors = &(mPciOptionRomTable.PciOptionRomDescriptors[(UINT32)mPciOptionRomTable.PciOptionRomCount]);
+
+ TempPciOptionRomDescriptors->RomAddress = RomBuffer;
+ TempPciOptionRomDescriptors->MemoryType = EfiBootServicesData;
+ TempPciOptionRomDescriptors->RomLength = RomBarSize;
+ TempPciOptionRomDescriptors->Seg = (UINT32)IoDev->SegmentNumber;
+ TempPciOptionRomDescriptors->Bus = (UINT8)Bus;
+ TempPciOptionRomDescriptors->Dev = (UINT8)Device;
+ TempPciOptionRomDescriptors->Func = (UINT8)Func;
+ TempPciOptionRomDescriptors->ExecutedLegacyBiosImage = TRUE;
+ TempPciOptionRomDescriptors->DontLoadEfiRom = FALSE;
+
+ mPciOptionRomTable.PciOptionRomCount++;
+ }
+ }
+
+ //
+ // Disable the Memory decode for the PCI-PCI Bridge
+ //
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+ Register &= (~0x02);
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
+ }
+ }
+ }
+
+ //
+ // Restore the PCI Configuration Header
+ //
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);
+}
+
+static
+VOID
+SaveCommandRegister (
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ UINT16 MinBus,
+ UINT16 MaxBus,
+ UINT16 MinDevice,
+ UINT16 MaxDevice,
+ UINT16 MinFunc,
+ UINT16 MaxFunc,
+ UINT16 Bus,
+ UINT16 Device,
+ UINT16 Func,
+ IN VOID *VoidContext
+ )
+
+{
+ PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;
+ UINT64 Address;
+ UINTN Index;
+ UINT16 Command;
+
+ Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
+
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);
+
+ Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;
+
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);
+
+ //
+ // Clear the memory enable bit
+ //
+ Command = Context->CommandRegisterBuffer[Index] & (~0x02);
+
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Command);
+}
+
+static
+VOID
+RestoreCommandRegister (
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ UINT16 MinBus,
+ UINT16 MaxBus,
+ UINT16 MinDevice,
+ UINT16 MaxDevice,
+ UINT16 MinFunc,
+ UINT16 MaxFunc,
+ UINT16 Bus,
+ UINT16 Device,
+ UINT16 Func,
+ IN VOID *VoidContext
+ )
+
+{
+ PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;
+ UINT64 Address;
+ UINTN Index;
+
+ Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;
+
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);
+
+ Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;
+
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);
+}
+
+EFI_STATUS
+ScanPciRootBridgeForRoms(
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev
+ )
+
+{
+ EFI_STATUS Status;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
+ UINT16 MinBus;
+ UINT16 MaxBus;
+ UINT64 RootWindowBase;
+ UINT64 RootWindowLimit;
+ PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT Context;
+
+ if (mPciOptionRomTableInstalled == FALSE) {
+ gBS->InstallConfigurationTable(&gEfiPciOptionRomTableGuid, &mPciOptionRomTable);
+ mPciOptionRomTableInstalled = TRUE;
+ }
+
+ Status = IoDev->Configuration(IoDev, &Descriptors);
+ if (EFI_ERROR (Status) || Descriptors == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ MinBus = 0xffff;
+ MaxBus = 0xffff;
+ RootWindowBase = 0;
+ RootWindowLimit = 0;
+ while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) {
+ //
+ // Find bus range
+ //
+ if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
+ MinBus = (UINT16)Descriptors->AddrRangeMin;
+ MaxBus = (UINT16)Descriptors->AddrRangeMax;
+ }
+ //
+ // Find memory descriptors that are not prefetchable
+ //
+ if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM && Descriptors->SpecificFlag == 0) {
+ //
+ // Find Memory Descriptors that are less than 4GB, so the PPB Memory Window can be used for downstream devices
+ //
+ if (Descriptors->AddrRangeMax < 0x100000000) {
+ //
+ // Find the largest Non-Prefetchable Memory Descriptor that is less than 4GB
+ //
+ if ((Descriptors->AddrRangeMax - Descriptors->AddrRangeMin) > (RootWindowLimit - RootWindowBase)) {
+ RootWindowBase = Descriptors->AddrRangeMin;
+ RootWindowLimit = Descriptors->AddrRangeMax;
+ }
+ }
+ }
+ Descriptors ++;
+ }
+
+ //
+ // Make sure a bus range was found
+ //
+ if (MinBus == 0xffff || MaxBus == 0xffff) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Make sure a non-prefetchable memory region was found
+ //
+ if (RootWindowBase == 0 && RootWindowLimit == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Round the Base and Limit values to 1 MB boudaries
+ //
+ RootWindowBase = ((RootWindowBase - 1) & 0xfff00000) + 0x00100000;
+ RootWindowLimit = ((RootWindowLimit + 1) & 0xfff00000) - 1;
+
+ //
+ // Make sure that the size of the rounded window is greater than zero
+ //
+ if (RootWindowLimit <= RootWindowBase) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Allocate buffer to save the Command register from all the PCI devices
+ //
+ Context.CommandRegisterBuffer = NULL;
+ Status = gBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(UINT16) * (MaxBus - MinBus + 1) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1),
+ &Context.CommandRegisterBuffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Context.PpbMemoryWindow = (((UINT32)RootWindowBase) >> 16) | ((UINT32)RootWindowLimit & 0xffff0000);
+
+ //
+ // Save the Command register from all the PCI devices, and disable the I/O, Mem, and BusMaster bits
+ //
+ ScanPciBus(
+ IoDev,
+ MinBus, MaxBus,
+ 0, PCI_MAX_DEVICE,
+ 0, PCI_MAX_FUNC,
+ SaveCommandRegister, &Context
+ );
+
+ //
+ // Recursively scan all the busses for PCI Option ROMs
+ //
+ ScanPciBus(
+ IoDev,
+ MinBus, MinBus,
+ 0, PCI_MAX_DEVICE,
+ 0, PCI_MAX_FUNC,
+ CheckForRom, &Context
+ );
+
+ //
+ // Restore the Command register in all the PCI devices
+ //
+ ScanPciBus(
+ IoDev,
+ MinBus, MaxBus,
+ 0, PCI_MAX_DEVICE,
+ 0, PCI_MAX_FUNC,
+ RestoreCommandRegister, &Context
+ );
+
+ //
+ // Free the buffer used to save all the Command register values
+ //
+ gBS->FreePool(Context.CommandRegisterBuffer);
+
+ return EFI_SUCCESS;
+}