pcienumeratorsupport.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,385 行 · 第 1/3 页
C
1,385 行
if (PciIoDevice->PciBar[BarIndex].Length == 0) {
PciIoDevice->PciBar[BarIndex].BarType = 0;
}
PciIoDevice->PciBar[BarIndex].Prefetchable = FALSE;
PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
} else {
Mask = 0xfffffff0;
PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
switch (Value & 0x07) {
//
//memory space; anywhere in 32 bit address space
//
case 0x00:
if (Value & 0x08) {
PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;
} else {
PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;
}
PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;
PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
break;
//
// memory space; anywhere in 64 bit address space
//
case 0x04:
if (Value & 0x08) {
PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;
} else {
PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;
}
//
// According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
// is regarded as an extension for the first bar. As a result
// the sizing will be conducted on combined 64 bit value
// Here just store the masked first 32bit value for future size
// calculation
//
PciIoDevice->PciBar[BarIndex].Length = Value & Mask;
PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
//
// Increment the offset to point to next DWORD
//
Offset += 4;
Status = BarExisted (
PciIoDevice,
Offset,
&Value,
&OriginalValue
);
if (EFI_ERROR (Status)) {
return Offset + 4;
}
//
// Fix the length to support some spefic 64 bit BAR
//
Data = Value;
Index = 0;
for (Data = Value; Data != 0; Data >>= 1) {
Index ++;
}
Value |= ((UINT32)(-1) << Index);
//
// Calculate the size of 64bit bar
//
PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);
PciIoDevice->PciBar[BarIndex].Length = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);
PciIoDevice->PciBar[BarIndex].Length = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;
PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
break;
//
// reserved
//
default:
PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;
PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
break;
}
}
//
// Check the length again so as to keep compatible with some special bars
//
if (PciIoDevice->PciBar[BarIndex].Length == 0) {
PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
PciIoDevice->PciBar[BarIndex].Alignment = 0;
}
//
// Increment number of bar
//
return Offset + 4;
}
EFI_STATUS
InitializePPB (
IN PCI_IO_DEVICE *PciIoDevice
)
/*++
Routine Description:
Arguments:
Returns:
None
--*/
{
EFI_PCI_IO_PROTOCOL *PciIo;
PciIo = &(PciIoDevice->PciIo);
//
// Put all the resource apertures including IO16
// Io32, pMem32, pMem64 to quiescent state
// Resource base all ones, Resource limit all zeros
//
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero);
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne);
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero);
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne);
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero);
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne);
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero);
//
// don't support use io32 as for now
//
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne);
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero);
return EFI_SUCCESS;
}
EFI_STATUS
InitializeP2C (
IN PCI_IO_DEVICE *PciIoDevice
)
/*++
Routine Description:
Arguments:
Returns:
None
--*/
{
EFI_PCI_IO_PROTOCOL *PciIo;
PciIo = &(PciIoDevice->PciIo);
//
// Put all the resource apertures including IO16
// Io32, pMem32, pMem64 to quiescent state(
// Resource base all ones, Resource limit all zeros
//
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne);
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero);
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne);
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero);
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne);
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero);
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne);
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero);
return EFI_SUCCESS;
}
PCI_IO_DEVICE *
CreatePciIoDevice (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
IN PCI_TYPE00 *Pci,
UINT8 Bus,
UINT8 Device,
UINT8 Func
)
/*++
Routine Description:
Arguments:
Returns:
None
--*/
{
EFI_STATUS Status;
PCI_IO_DEVICE *PciIoDevice;
PciIoDevice = NULL;
Status = gBS->AllocatePool (
EfiBootServicesData,
sizeof (PCI_IO_DEVICE),
(VOID **) &PciIoDevice
);
if (EFI_ERROR (Status)) {
return NULL;
}
EfiZeroMem (PciIoDevice, sizeof (PCI_IO_DEVICE));
PciIoDevice->Signature = PCI_IO_DEVICE_SIGNATURE;
PciIoDevice->Handle = NULL;
PciIoDevice->PciRootBridgeIo = PciRootBridgeIo;
PciIoDevice->DevicePath = NULL;
PciIoDevice->BusNumber = Bus;
PciIoDevice->DeviceNumber = Device;
PciIoDevice->FunctionNumber = Func;
PciIoDevice->Decodes = 0;
if (gFullEnumeration) {
PciIoDevice->Allocated = FALSE;
} else {
PciIoDevice->Allocated = TRUE;
}
PciIoDevice->Attributes = 0;
PciIoDevice->Supports = 0;
PciIoDevice->BusOverride = FALSE;
PciIoDevice->IsPciExp = FALSE;
EfiCopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01));
//
// Initialize the PCI I/O instance structure
//
Status = InitializePciIoInstance (PciIoDevice);
Status = InitializePciDriverOverrideInstance (PciIoDevice);
if (EFI_ERROR (Status)) {
gBS->FreePool (PciIoDevice);
return NULL;
}
//
// Initialize the reserved resource list
//
InitializeListHead (&PciIoDevice->ReservedResourceList);
//
// Initialize the driver list
//
InitializeListHead (&PciIoDevice->OptionRomDriverList);
//
// Initialize the child list
//
InitializeListHead (&PciIoDevice->ChildList);
return PciIoDevice;
}
EFI_STATUS
PciEnumeratorLight (
IN EFI_HANDLE Controller
)
/*++
Routine Description:
This routine is used to enumerate entire pci bus system
in a given platform
Arguments:
Returns:
None
--*/
{
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
PCI_IO_DEVICE *RootBridgeDev;
UINT16 MinBus;
UINT16 MaxBus;
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
MinBus = 0;
MaxBus = PCI_MAX_BUS;
Descriptors = NULL;
//
// If this host bridge has been already enumerated, then return successfully
//
if (RootBridgeExisted (Controller)) {
return EFI_SUCCESS;
}
//
// Open the IO Abstraction(s) needed to perform the supported test
//
Status = gBS->OpenProtocol (
Controller ,
&gEfiDevicePathProtocolGuid,
(VOID **)&ParentDevicePath,
gPciBusDriverBinding.DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
return Status;
}
//
// Open pci root bridge io protocol
//
Status = gBS->OpenProtocol (
Controller,
&gEfiPciRootBridgeIoProtocolGuid,
(VOID **) &PciRootBridgeIo,
gPciBusDriverBinding.DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
return Status;
}
//
// Load all EFI Drivers from all PCI Option ROMs behind the PCI Root Bridge
//
Status = PciRomLoadEfiDriversFromOptionRomTable (&gPciBusDriverBinding, PciRootBridgeIo);
Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
if (EFI_ERROR (Status)) {
return Status;
}
while (PciGetBusRange (Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) {
//
// Create a device node for root bridge device with a NULL host bridge controller handle
//
RootBridgeDev = CreateRootBridge (Controller);
//
// Record the root bridge device path
//
RootBridgeDev->DevicePath = ParentDevicePath;
//
// Record the root bridge io protocol
//
RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;
Status = PciPciDeviceInfoCollector (
RootBridgeDev,
(UINT8) MinBus
);
if (!EFI_ERROR (Status)) {
//
// If successfully, insert the node into device pool
//
InsertRootBridge (RootBridgeDev);
} else {
//
// If unsuccessly, destroy the entire node
//
DestroyRootBridge (RootBridgeDev);
}
Descriptors++;
}
return EFI_SUCCESS;
}
EFI_STATUS
PciGetBusRange (
IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors,
OUT UINT16 *MinBus,
OUT UINT16 *MaxBus,
OUT UINT16 *BusRange
)
/*++
Routine Description:
Get the bus range.
Arguments:
Descriptors - A pointer to the address space descriptor.
MinBus - The min bus.
MaxBus - The max bus.
BusRange - The bus range.
Returns:
Status Code.
--*/
{
while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) {
if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
if (MinBus != NULL) {
*MinBus = (UINT16)Descriptors->AddrRangeMin;
}
if (MaxBus != NULL) {
*MaxBus = (UINT16)Descriptors->AddrRangeMax;
}
if (BusRange != NULL) {
*BusRange = (UINT16)Descriptors->AddrLen;
}
return EFI_SUCCESS;
}
Descriptors ++;
}
return EFI_NOT_FOUND;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?