CorebootModulePkg: Remove unused PCI non-enumeration drivers
CorebootPayloadPkg has switched to use the generic PciBus and PciHostBridge driver form MdeModulePkg. As a result, the non-enumeration drivers including PciBusNoEnumerationDxe and PciRootBridgenoEnumerationDxe need to be removed. Cc: Prince Agyeman <prince.agyeman@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Maurice Ma <maurice.ma@intel.com> Reviewed-by: Prince Agyeman <prince.agyeman@intel.com>
This commit is contained in:
@ -1,845 +0,0 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
|
||||
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 = (EFI_IO_WIDTH) (Width - MMIO_COPY_UINT8);
|
||||
Status = Private->PciRootBridgeIo->CopyMem (
|
||||
Private->PciRootBridgeIo,
|
||||
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
|
||||
(UINT64)(UINTN) 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 = (EFI_IO_WIDTH) (Width - MMIO_COPY_UINT8);
|
||||
Status = Private->PciRootBridgeIo->CopyMem (
|
||||
Private->PciRootBridgeIo,
|
||||
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
|
||||
Address,
|
||||
(UINT64)(UINTN) 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 ((UINT32)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 ((UINT32)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 ((UINT32)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 ((UINT32)Type >= MaxAllocateType) {
|
||||
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);
|
||||
}
|
@ -1,449 +0,0 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
|
||||
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 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
|
||||
|
@ -1,738 +0,0 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
|
||||
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"
|
||||
|
||||
BOOLEAN mPciOptionRomTableInstalled = FALSE;
|
||||
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 ((UINT32)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 >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
|
||||
InStride = 0;
|
||||
}
|
||||
|
||||
if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
|
||||
OutStride = 0;
|
||||
}
|
||||
|
||||
UsePciExpressAccess = FALSE;
|
||||
|
||||
CopyMem (&PciAddress, &UserAddress, sizeof(UINT64));
|
||||
|
||||
if (PciAddress.ExtendedRegister > 0xFF) {
|
||||
//
|
||||
// Check PciExpressBaseAddress
|
||||
//
|
||||
if ((PrivateData->PciExpressBaseAddress == 0) ||
|
||||
(PrivateData->PciExpressBaseAddress >= 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 == PCI_EXPANSION_ROM_HEADER_SIGNATURE &&
|
||||
EfiRomHeader.PcirOffset != 0 &&
|
||||
(EfiRomHeader.PcirOffset & 3) == 0 &&
|
||||
RomBarSize + EfiRomHeader.PcirOffset + sizeof (PCI_DATA_STRUCTURE) <= MaxRomSize) {
|
||||
ZeroMem (&Pcir, sizeof(Pcir));
|
||||
IoDev->Mem.Read (
|
||||
IoDev,
|
||||
EfiPciWidthUint8,
|
||||
RomBar + RomBarSize + EfiRomHeader.PcirOffset,
|
||||
sizeof(Pcir),
|
||||
&Pcir
|
||||
);
|
||||
|
||||
if (Pcir.Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
|
||||
break;
|
||||
}
|
||||
if (RomBarSize + Pcir.ImageLength * 512 > MaxRomSize) {
|
||||
break;
|
||||
}
|
||||
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),
|
||||
(VOID*)&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);
|
||||
}
|
||||
|
||||
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 = (UINT16) (Context->CommandRegisterBuffer[Index] & (~0x02));
|
||||
|
||||
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Command);
|
||||
}
|
||||
|
||||
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, (VOID **)&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 < 0x100000000ULL) {
|
||||
//
|
||||
// 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),
|
||||
(VOID **)&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;
|
||||
}
|
@ -1,459 +0,0 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
|
||||
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 <IndustryStandard/Pci.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
|
||||
//
|
||||
PLABEL mSalProcPlabel;
|
||||
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 ((UINT32)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;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,244 +0,0 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.<BR>
|
||||
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/CpuIo2.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>
|
||||
|
||||
#define PCI_MAX_SEGMENT 0
|
||||
//
|
||||
// Driver Instance Data Prototypes
|
||||
//
|
||||
#define PCAT_PCI_ROOT_BRIDGE_SIGNATURE 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_IO2_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)
|
||||
|
||||
//
|
||||
// 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;
|
||||
|
||||
typedef struct {
|
||||
UINT8 Register;
|
||||
UINT8 Function;
|
||||
UINT8 Device;
|
||||
UINT8 Bus;
|
||||
UINT8 Reserved[4];
|
||||
} DEFIO_PCI_ADDR;
|
||||
|
||||
//
|
||||
// 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
|
||||
);
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
//
|
||||
// Driver entry point prototype
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
InitializePcatPciRootBridge (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
);
|
||||
|
||||
extern EFI_CPU_IO2_PROTOCOL *gCpuIo;
|
||||
|
||||
#endif
|
@ -1,93 +0,0 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.<BR>
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,69 +0,0 @@
|
||||
## @file
|
||||
#
|
||||
# Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
# 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
|
||||
|
||||
ENTRY_POINT = InitializePcatPciRootBridge
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
DuetPkg/DuetPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
UefiDriverEntryPoint
|
||||
UefiLib
|
||||
MemoryAllocationLib
|
||||
UefiBootServicesTableLib
|
||||
DebugLib
|
||||
BaseMemoryLib
|
||||
DevicePathLib
|
||||
HobLib
|
||||
|
||||
[Sources]
|
||||
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
|
||||
gEfiCpuIo2ProtocolGuid
|
||||
|
||||
[Guids]
|
||||
gEfiPciOptionRomTableGuid
|
||||
gEfiPciExpressBaseAddressGuid
|
||||
|
||||
[Depex]
|
||||
gEfiCpuIo2ProtocolGuid
|
@ -1,738 +0,0 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
|
||||
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"
|
||||
|
||||
BOOLEAN mPciOptionRomTableInstalled = FALSE;
|
||||
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 ((UINT32)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 >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
|
||||
InStride = 0;
|
||||
}
|
||||
|
||||
if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
|
||||
OutStride = 0;
|
||||
}
|
||||
|
||||
UsePciExpressAccess = FALSE;
|
||||
|
||||
CopyMem (&PciAddress, &UserAddress, sizeof(UINT64));
|
||||
|
||||
if (PciAddress.ExtendedRegister > 0xFF) {
|
||||
//
|
||||
// Check PciExpressBaseAddress
|
||||
//
|
||||
if ((PrivateData->PciExpressBaseAddress == 0) ||
|
||||
(PrivateData->PciExpressBaseAddress >= 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 == PCI_EXPANSION_ROM_HEADER_SIGNATURE &&
|
||||
EfiRomHeader.PcirOffset != 0 &&
|
||||
(EfiRomHeader.PcirOffset & 3) == 0 &&
|
||||
RomBarSize + EfiRomHeader.PcirOffset + sizeof (PCI_DATA_STRUCTURE) <= MaxRomSize) {
|
||||
ZeroMem (&Pcir, sizeof(Pcir));
|
||||
IoDev->Mem.Read (
|
||||
IoDev,
|
||||
EfiPciWidthUint8,
|
||||
RomBar + RomBarSize + EfiRomHeader.PcirOffset,
|
||||
sizeof(Pcir),
|
||||
&Pcir
|
||||
);
|
||||
|
||||
if (Pcir.Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
|
||||
break;
|
||||
}
|
||||
if (RomBarSize + Pcir.ImageLength * 512 > MaxRomSize) {
|
||||
break;
|
||||
}
|
||||
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),
|
||||
(VOID **) &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);
|
||||
}
|
||||
|
||||
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 = (UINT16) (Context->CommandRegisterBuffer[Index] & (~0x02));
|
||||
|
||||
IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Command);
|
||||
}
|
||||
|
||||
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, (VOID **) &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 < 0x100000000ULL) {
|
||||
//
|
||||
// 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),
|
||||
(VOID **) &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;
|
||||
}
|
Reference in New Issue
Block a user