pcienumeratorsupport.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,385 行 · 第 1/3 页
C
1,385 行
/*++
Copyright (c) 2005 - 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
PciEnumeratorSupport.c
Abstract:
PCI Bus Driver
Revision History
--*/
#include "Pcibus.h"
EFI_STATUS
InitializePPB (
IN PCI_IO_DEVICE *PciIoDevice
);
EFI_STATUS
InitializeP2C (
IN PCI_IO_DEVICE *PciIoDevice
);
PCI_IO_DEVICE*
CreatePciIoDevice (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
IN PCI_TYPE00 *Pci,
UINT8 Bus,
UINT8 Device,
UINT8 Func
);
PCI_IO_DEVICE*
GatherP2CInfo (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
IN PCI_TYPE00 *Pci,
UINT8 Bus,
UINT8 Device,
UINT8 Func
);
UINTN
PciParseBar (
IN PCI_IO_DEVICE *PciIoDevice,
IN UINTN Offset,
IN UINTN BarIndex
);
EFI_STATUS
PciSearchDevice (
IN PCI_IO_DEVICE *Bridge,
PCI_TYPE00 *Pci,
UINT8 Bus,
UINT8 Device,
UINT8 Func,
PCI_IO_DEVICE **PciDevice
);
EFI_STATUS
DetermineDeviceAttribute (
IN PCI_IO_DEVICE *PciIoDevice
);
EFI_STATUS
BarExisted (
IN PCI_IO_DEVICE *PciIoDevice,
IN UINTN Offset,
OUT UINT32 *BarLengthValue,
OUT UINT32 *OriginalBarValue
);
EFI_DEVICE_PATH_PROTOCOL*
CreatePciDevicePath(
IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
IN PCI_IO_DEVICE *PciIoDevice
);
PCI_IO_DEVICE*
GatherDeviceInfo (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
IN PCI_TYPE00 *Pci,
UINT8 Bus,
UINT8 Device,
UINT8 Func
);
PCI_IO_DEVICE*
GatherPPBInfo (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
IN PCI_TYPE00 *Pci,
UINT8 Bus,
UINT8 Device,
UINT8 Func
);
EFI_STATUS
PciDevicePresent (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
PCI_TYPE00 *Pci,
UINT8 Bus,
UINT8 Device,
UINT8 Func
)
/*++
Routine Description:
This routine is used to check whether the pci device is present
Arguments:
Returns:
None
--*/
{
UINT64 Address;
EFI_STATUS Status;
//
// Create PCI address map in terms of Bus, Device and Func
//
Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
//
// Read the Vendor Id register
//
Status = PciRootBridgeIo->Pci.Read (
PciRootBridgeIo,
EfiPciWidthUint32,
Address,
1,
Pci
);
if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) {
//
// Read the entire config header for the device
//
Status = PciRootBridgeIo->Pci.Read (
PciRootBridgeIo,
EfiPciWidthUint32,
Address,
sizeof (PCI_TYPE00) / sizeof (UINT32),
Pci
);
return EFI_SUCCESS;
}
return EFI_NOT_FOUND;
}
EFI_STATUS
PciPciDeviceInfoCollector (
IN PCI_IO_DEVICE *Bridge,
UINT8 StartBusNumber
)
/*++
Routine Description:
Arguments:
Returns:
None
--*/
{
EFI_STATUS Status;
PCI_TYPE00 Pci;
UINT8 Device;
UINT8 Func;
UINT8 SecBus;
PCI_IO_DEVICE *PciIoDevice;
EFI_PCI_IO_PROTOCOL *PciIo;
Status = EFI_SUCCESS;
SecBus = 0;
for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
//
// Check to see whether PCI device is present
//
Status = PciDevicePresent (
Bridge->PciRootBridgeIo,
&Pci,
(UINT8) StartBusNumber,
(UINT8) Device,
(UINT8) Func
);
if (!EFI_ERROR (Status)) {
//
// Collect all the information about the PCI device discovered
//
Status = PciSearchDevice (
Bridge,
&Pci,
(UINT8) StartBusNumber,
Device,
Func,
&PciIoDevice
);
//
// Recursively scan PCI busses on the other side of PCI-PCI bridges
//
//
if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {
//
// If it is PPB, we need to get the secondary bus to continue the enumeration
//
PciIo = &(PciIoDevice->PciIo);
Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, 1, &SecBus);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Deep enumerate the next level bus
//
Status = PciPciDeviceInfoCollector (
PciIoDevice,
(UINT8) (SecBus)
);
}
if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
//
// Skip sub functions, this is not a multi function device
//
Func = PCI_MAX_FUNC;
}
}
}
}
return EFI_SUCCESS;
}
EFI_STATUS
PciSearchDevice (
IN PCI_IO_DEVICE *Bridge,
IN PCI_TYPE00 *Pci,
IN UINT8 Bus,
IN UINT8 Device,
IN UINT8 Func,
OUT PCI_IO_DEVICE **PciDevice
)
/*++
Routine Description:
Search required device.
Arguments:
Bridge - A pointer to the PCI_IO_DEVICE.
Pci - A pointer to the PCI_TYPE00.
Bus - Bus number.
Device - Device number.
Func - Function number.
PciDevice - The Required pci device.
Returns:
Status code.
--*/
{
PCI_IO_DEVICE *PciIoDevice;
PciIoDevice = NULL;
if (!IS_PCI_BRIDGE (Pci)) {
if (IS_CARDBUS_BRIDGE (Pci)) {
PciIoDevice = GatherP2CInfo (
Bridge->PciRootBridgeIo,
Pci,
Bus,
Device,
Func
);
if (gFullEnumeration) {
InitializeP2C (PciIoDevice);
}
} else {
//
// Create private data for Pci Device
//
PciIoDevice = GatherDeviceInfo (
Bridge->PciRootBridgeIo,
Pci,
Bus,
Device,
Func
);
}
} else {
//
// Create private data for PPB
//
PciIoDevice = GatherPPBInfo (
Bridge->PciRootBridgeIo,
Pci,
Bus,
Device,
Func
);
//
// Special initialization for PPB including making the PPB quiet
//
if (gFullEnumeration) {
InitializePPB (PciIoDevice);
}
}
if (!PciIoDevice) {
return EFI_OUT_OF_RESOURCES;
}
//
// Create a device path for this PCI device and store it into its private data
//
CreatePciDevicePath(
Bridge->DevicePath,
PciIoDevice
);
//
// Detect this function has option rom
//
if (gFullEnumeration) {
if (!IS_CARDBUS_BRIDGE (Pci)) {
GetOpRomInfo (PciIoDevice);
}
ResetPowerManagementFeature (PciIoDevice);
}
else {
PciRomGetRomResourceFromPciOptionRomTable (
&gPciBusDriverBinding,
PciIoDevice->PciRootBridgeIo,
PciIoDevice
);
}
//
// Insert it into a global tree for future reference
//
InsertPciDevice (Bridge, PciIoDevice);
//
// Determine PCI device attributes
//
DetermineDeviceAttribute (PciIoDevice);
if (PciDevice != NULL) {
*PciDevice = PciIoDevice;
}
return EFI_SUCCESS;
}
PCI_IO_DEVICE *
GatherDeviceInfo (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
IN PCI_TYPE00 *Pci,
UINT8 Bus,
UINT8 Device,
UINT8 Func
)
/*++
Routine Description:
Arguments:
Returns:
None
--*/
{
UINTN Offset;
UINTN BarIndex;
PCI_IO_DEVICE *PciIoDevice;
PciIoDevice = CreatePciIoDevice (
PciRootBridgeIo,
Pci,
Bus,
Device,
Func
);
if (!PciIoDevice) {
return NULL;
}
//
// If it is a full enumeration, disconnect the device in advance
//
if (gFullEnumeration) {
PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
}
//
// Start to parse the bars
//
for (Offset = 0x10, BarIndex = 0; Offset <= 0x24; BarIndex++) {
Offset = PciParseBar (PciIoDevice, Offset, BarIndex);
}
return PciIoDevice;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?