pcienumeratorsupport.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,267 行 · 第 1/4 页
C
2,267 行
/*++
Copyright (c) 2004 - 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"
#include "PciEnumeratorSupport.h"
#include "PciCommand.h"
#include "PciIo.h"
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
--*/
// TODO: PciRootBridgeIo - add argument and description to function comment
// TODO: Pci - add argument and description to function comment
// TODO: Bus - add argument and description to function comment
// TODO: Device - add argument and description to function comment
// TODO: Func - add argument and description to function comment
// TODO: EFI_SUCCESS - add return value to function comment
// TODO: EFI_NOT_FOUND - add return value to function comment
{
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
--*/
// TODO: Bridge - add argument and description to function comment
// TODO: StartBusNumber - add argument and description to function comment
// TODO: EFI_SUCCESS - add return value to function comment
{
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)) {
//
// Call back to host bridge function
//
PreprocessController (Bridge, (UINT8) StartBusNumber, Device, Func, EfiPciBeforeResourceCollection);
//
// 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;
}
//
// Get resource padding for PPB
//
GetResourcePaddingPpb (PciIoDevice);
//
// 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.
--*/
// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
// TODO: EFI_SUCCESS - add return value to function comment
{
PCI_IO_DEVICE *PciIoDevice;
PciIoDevice = NULL;
if (!IS_PCI_BRIDGE (Pci)) {
if (IS_CARDBUS_BRIDGE (Pci)) {
PciIoDevice = GatherP2CInfo (
Bridge,
Pci,
Bus,
Device,
Func
);
if (gFullEnumeration) {
InitializeP2C (PciIoDevice);
}
} else {
//
// Create private data for Pci Device
//
PciIoDevice = GatherDeviceInfo (
Bridge,
Pci,
Bus,
Device,
Func
);
}
} else {
//
// Create private data for PPB
//
PciIoDevice = GatherPpbInfo (
Bridge,
Pci,
Bus,
Device,
Func
);
//
// Special initialization for PPB including making the PPB quiet
//
if (gFullEnumeration) {
InitializePpb (PciIoDevice);
}
}
if (!PciIoDevice) {
return EFI_OUT_OF_RESOURCES;
}
//
// Update the bar information for this PCI device so as to support some specific device
//
UpdatePciInfo (PciIoDevice);
if (PciIoDevice->DevicePath == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Detect this function has option rom
//
if (gFullEnumeration) {
if (!IS_CARDBUS_BRIDGE (Pci)) {
GetOpRomInfo (PciIoDevice);
}
ResetPowerManagementFeature (PciIoDevice);
}
//
// Insert it into a global tree for future reference
//
InsertPciDevice (Bridge, PciIoDevice);
//
// Determine PCI device attributes
//
if (PciDevice != NULL) {
*PciDevice = PciIoDevice;
}
return EFI_SUCCESS;
}
PCI_IO_DEVICE *
GatherDeviceInfo (
IN PCI_IO_DEVICE *Bridge,
IN PCI_TYPE00 *Pci,
UINT8 Bus,
UINT8 Device,
UINT8 Func
)
/*++
Routine Description:
Arguments:
Returns:
None
--*/
// TODO: Bridge - add argument and description to function comment
// TODO: Pci - add argument and description to function comment
// TODO: Bus - add argument and description to function comment
// TODO: Device - add argument and description to function comment
// TODO: Func - add argument and description to function comment
{
UINTN Offset;
UINTN BarIndex;
PCI_IO_DEVICE *PciIoDevice;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
PciRootBridgeIo = Bridge->PciRootBridgeIo;
PciIoDevice = CreatePciIoDevice (
PciRootBridgeIo,
Pci,
Bus,
Device,
Func
);
if (!PciIoDevice) {
return NULL;
}
//
// Create a device path for this PCI device and store it into its private data
//
CreatePciDevicePath (
Bridge->DevicePath,
PciIoDevice
);
//
// 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;
}
PCI_IO_DEVICE *
GatherPpbInfo (
IN PCI_IO_DEVICE *Bridge,
IN PCI_TYPE00 *Pci,
UINT8 Bus,
UINT8 Device,
UINT8 Func
)
/*++
Routine Description:
Arguments:
Returns:
None
--*/
// TODO: Bridge - add argument and description to function comment
// TODO: Pci - add argument and description to function comment
// TODO: Bus - add argument and description to function comment
// TODO: Device - add argument and description to function comment
// TODO: Func - add argument and description to function comment
{
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
PCI_IO_DEVICE *PciIoDevice;
EFI_STATUS Status;
UINT32 Value;
EFI_PCI_IO_PROTOCOL *PciIo;
UINT8 Temp;
PciRootBridgeIo = Bridge->PciRootBridgeIo;
PciIoDevice = CreatePciIoDevice (
PciRootBridgeIo,
Pci,
Bus,
Device,
Func
);
if (!PciIoDevice) {
return NULL;
}
//
// Create a device path for this PCI device and store it into its private data
//
CreatePciDevicePath (
Bridge->DevicePath,
PciIoDevice
);
if (gFullEnumeration) {
PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
//
// Initalize the bridge control register
//
PciDisableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED);
}
//
// PPB can have two BARs
//
if (PciParseBar (PciIoDevice, 0x10, PPB_BAR_0) == 0x14) {
//
// Not 64-bit bar
//
PciParseBar (PciIoDevice, 0x14, PPB_BAR_1);
}
PciIo = &PciIoDevice->PciIo;
//
// Test whether it support 32 decode or not
//
PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
if (Value) {
if (Value & 0x01) {
PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED;
} else {
PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
}
}
Status = BarExisted (
PciIoDevice,
0x24,
NULL,
NULL
);
//
// test if it supports 64 memory or not
//
if (!EFI_ERROR (Status)) {
Status = BarExisted (
PciIoDevice,
0x28,
NULL,
NULL
);
if (!EFI_ERROR (Status)) {
PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;
} else {
PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
}
}
//
// Memory 32 code is required for ppb
//
PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
GetResourcePaddingPpb (PciIoDevice);
return PciIoDevice;
}
PCI_IO_DEVICE *
GatherP2CInfo (
IN PCI_IO_DEVICE *Bridge,
IN PCI_TYPE00 *Pci,
UINT8 Bus,
UINT8 Device,
UINT8 Func
)
/*++
Routine Description:
Arguments:
Returns:
None
--*/
// TODO: Bridge - add argument and description to function comment
// TODO: Pci - add argument and description to function comment
// TODO: Bus - add argument and description to function comment
// TODO: Device - add argument and description to function comment
// TODO: Func - add argument and description to function comment
{
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
PCI_IO_DEVICE *PciIoDevice;
PciRootBridgeIo = Bridge->PciRootBridgeIo;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?