pci.c

来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 421 行

C
421
字号
/*++

Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.


Module Name:

    Pci.c
    
Abstract:

    Pci functions that can be used to build device Paths.



Revision History

--*/

#include "efi.h"
#include "efilib.h"
#include "Pci22.h" 

#define EFI_ROOT_BRIDGE_LIST    'eprb'
typedef struct {
    UINTN           Signature;

    UINT16          BridgeNumber;
    UINT16          PrimaryBus;
    UINT16          SubordinateBus;

    EFI_DEVICE_PATH *DevicePath;

    LIST_ENTRY      Link;
} PCI_ROOT_BRIDGE_ENTRY;

extern EFI_DEVICE_IO_INTERFACE   *GlobalIoFncs;
extern LIST_ENTRY                PciRootBusList; 


VOID
PrintPciRootBridgeInfo (
    IN LIST_ENTRY   *ListHead
    );

EFI_DEVICE_PATH *
AppendPciDevicePath (
    IN      UINT8               Bus,
    IN      UINT8               Device,
    IN      UINT8               Func,
    IN      EFI_DEVICE_PATH     *DevicePath, 
    IN  OUT UINT16              *BridgePrimaryBus,
    IN  OUT UINT16              *BridgeSubordinateBus,
	OUT     EFI_STATUS          *Status 
    );

EFI_STATUS
PciFindDeviceClass (
    IN  OUT EFI_PCI_ADDRESS_UNION   *ClassAddress,
    IN      UINT8                   BaseClass,
    IN      UINT8                   SubClass
    )
/*++

    Find the First device that matches BassClass & SubClass

--*/
{
    UINT16       Bus;
    UINT8        Device, Func;
    UINT64       Address;
    PCI_TYPE00   Pci;

    //
    // BugBug: Shutdown PCI bus scan
    //
    for (Bus = 0; Bus <= PCI_MAX_BUS; Bus++) {
        for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
            for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
                Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
                ZeroMem(&Pci,sizeof(PCI_TYPE00));
                GlobalIoFncs->Pci.Read (GlobalIoFncs, IO_UINT32, Address, sizeof(UINT16), &Pci);
                if (Pci.Hdr.VendorId == 0xffff) {
                    break;
                } else {
                    GlobalIoFncs->Pci.Read (GlobalIoFncs, IO_UINT32, Address, sizeof(PCI_TYPE00)/sizeof(UINT32), &Pci);
                    if (Pci.Hdr.ClassCode[2] == BaseClass && 
                        Pci.Hdr.ClassCode[1] == SubClass) {
                        ClassAddress->EfiAddress.Bus = (UINT8)Bus;
                        ClassAddress->EfiAddress.Device = Device;
                        ClassAddress->EfiAddress.Function = Func;
                        return EFI_SUCCESS;
                    }
                    if (Func == 0 && !(Pci.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION)) {
                        //
                        // Skip sub functions, this is not a multi function device
                        //
                        Func = 8;
                    }
                }
            }
        }
    }
    return EFI_NOT_FOUND;
}

EFI_STATUS
PciFindDevice (
    IN  OUT EFI_PCI_ADDRESS_UNION   *DeviceAddress,
    IN      UINT16                  VendorId,
    IN      UINT16                  DeviceId,
    IN OUT  PCI_TYPE00              *Pci
    )
/*++

    Find the First device that matches VendorId & DeviceId

--*/
{
    UINT16       Bus;
    UINT8        Device, Func;
    UINT64       Address;

    //
    // BugBug: Shutdown PCI bus scan
    //
    for (Bus = 0; Bus <= PCI_MAX_BUS; Bus++) {
        for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
            for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
                Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
                ZeroMem(Pci,sizeof(PCI_TYPE00));
                GlobalIoFncs->Pci.Read (GlobalIoFncs, IO_UINT32, Address, sizeof(UINT16), Pci);
                if (Pci->Hdr.VendorId == 0xffff) {
                    break;
                } else {
                    GlobalIoFncs->Pci.Read (GlobalIoFncs, IO_UINT32, Address, sizeof(PCI_TYPE00)/sizeof(UINT32), Pci);
                    if (Pci->Hdr.VendorId == VendorId && 
                        Pci->Hdr.DeviceId == DeviceId) {
                        DeviceAddress->EfiAddress.Bus = (UINT8)Bus;
                        DeviceAddress->EfiAddress.Device = Device;
                        DeviceAddress->EfiAddress.Function = Func;
                        return EFI_SUCCESS;
                    }
                    if (Func == 0 && !(Pci->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION)) {
                        //
                        // Skip sub functions, this is not a multi function device
                        //
                        Func = 8;
                    }
                }
            }
        }
    }
    return EFI_NOT_FOUND;
}

EFI_STATUS
PciDevicePath (
    IN struct _EFI_DEVICE_IO_INTERFACE  *This,
    IN UINT64                           Address,
    IN OUT EFI_DEVICE_PATH              **PciDevicePath
    )
{
    PCI_ROOT_BRIDGE_ENTRY   *Entry;
    LIST_ENTRY              *Item;
    UINT16                  PrimaryBus, SubordinateBus; 
    UINT8                   Bus, Device, Func;
    EFI_PCI_ADDRESS_UNION   AddressUnion;
    ACPI_HID_DEVICE_PATH    AcpiNode;
	EFI_STATUS   Status;

    if (IsListEmpty(&PciRootBusList)) {
        return EFI_UNSUPPORTED;
    }

    AddressUnion.Address = Address;

    Bus = AddressUnion.EfiAddress.Bus;
    Device = AddressUnion.EfiAddress.Device;
    Func = AddressUnion.EfiAddress.Function;

    for (Item = PciRootBusList.Flink; Item != &PciRootBusList; Item = Item->Flink) {
        Entry = CR(Item, PCI_ROOT_BRIDGE_ENTRY, Link, EFI_ROOT_BRIDGE_LIST);
        if (Bus >= Entry->PrimaryBus && Bus <= Entry->SubordinateBus) {
            break;
        }
    }

    if (Item == &PciRootBusList) {
        return EFI_UNSUPPORTED;
    }

    ZeroMem (&AcpiNode, sizeof(AcpiNode));
    AcpiNode.Header.Type = ACPI_DEVICE_PATH;
    AcpiNode.Header.SubType = ACPI_DP;
    SetDevicePathNodeLength (&AcpiNode.Header, sizeof(AcpiNode));
    AcpiNode.HID = EISA_PNP_ID(0x0A03);
    AcpiNode.UID = Entry->BridgeNumber;

    *PciDevicePath = AppendDevicePathNode (EndDevicePath, &AcpiNode.Header);
    if (*PciDevicePath == NULL) {
        return EFI_OUT_OF_RESOURCES;
    }
    
    PrimaryBus = Entry->PrimaryBus;
    SubordinateBus = Entry->SubordinateBus;
    do {
        *PciDevicePath = AppendPciDevicePath (
                             Bus, Device, Func, 
                             *PciDevicePath,
                             &PrimaryBus, &SubordinateBus,
							 &Status
                             );
        if (*PciDevicePath == NULL) {
            return EFI_OUT_OF_RESOURCES;
        }
    } while (PrimaryBus != 0xffff);

    if (EFI_ERROR (Status)) {
        return EFI_UNSUPPORTED;
	}

    return EFI_SUCCESS;
}

EFI_DEVICE_PATH *
AppendPciDevicePath (
    IN      UINT8               Bus,
    IN      UINT8               Device,
    IN      UINT8               Function,
    IN      EFI_DEVICE_PATH     *DevicePath, 
    IN  OUT UINT16              *BridgePrimaryBus,
    IN  OUT UINT16              *BridgeSubordinateBus,
	OUT     EFI_STATUS          *Status 
    )
{
    UINT16              ThisBus; 
    UINT8               ThisDevice, ThisFunc;
    UINT64              Address;
    PCI_TYPE01          PciBridge, *PciPtr;
    EFI_DEVICE_PATH     *ReturnDevicePath;
    PCI_DEVICE_PATH     PciNode;    

    //
    // BugBug: Check to see if PtoP bridges are leagal on functions other than 0. Fix code if not true
    //

    PciPtr = &PciBridge;
    ReturnDevicePath=DevicePath;
	*Status = EFI_SUCCESS;
    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));
                GlobalIoFncs->Pci.Read (GlobalIoFncs, IO_UINT32, Address, 1, &(PciPtr->Hdr.VendorId));
                if (PciPtr->Hdr.VendorId == 0xffff) {
					if (ThisBus==Bus && ThisDevice==Device && ThisFunc==Function){
                        *BridgePrimaryBus = 0xffff;
                        *BridgeSubordinateBus = 0xffff;
						*Status = EFI_NOT_FOUND;
                        return ReturnDevicePath;
                	}	
                    break;
                } else {
                    GlobalIoFncs->Pci.Read (GlobalIoFncs, 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)) {
                        //
                        // Skip sub functions, this is not a multi function device
                        //
                        ThisFunc = 8;
                    }
                }
            }
        }
    }

    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;
}

VOID
InitializePciRootBusList (
    IN OUT LIST_ENTRY   *ListHead
    )
{
    UINT16                  Bus, MaxBus;
    UINT16                  BridgeNumber;
    UINT8                   Device, Func;
    UINT64                  Address;
    PCI_TYPE01              PciBridge, *PciPtr;
    PCI_ROOT_BRIDGE_ENTRY   *Entry;
    BOOLEAN                 AnyPciToPciBridges, AnyPciDevice;
    

    InitializeListHead (ListHead);

    PciPtr = &PciBridge;
    BridgeNumber = 0;

    //
    // BugBug: Shutdown PCI bus scan
    //
    for (Bus =0; Bus <= PCI_MAX_BUS; Bus++) {
        AnyPciToPciBridges = AnyPciDevice = FALSE;
        MaxBus = Bus;
        for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
            for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
                Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
                ZeroMem(PciPtr,sizeof(PCI_TYPE01));
                GlobalIoFncs->Pci.Read (GlobalIoFncs, IO_UINT32, Address, sizeof(UINT16), PciPtr);
                if (PciPtr->Hdr.VendorId == 0xffff) {
                    break;
                } else {
                    GlobalIoFncs->Pci.Read (GlobalIoFncs, IO_UINT32, Address, sizeof(PCI_TYPE01)/sizeof(UINT32), PciPtr);
                    AnyPciDevice = TRUE;
                    if (IS_PCI_BRIDGE(PciPtr)) {
                        AnyPciToPciBridges = TRUE;
                        if (PciPtr->Bridge.SubordinateBus > MaxBus) {
                            MaxBus = PciPtr->Bridge.SubordinateBus;
                        }
                    }
                    if (Func == 0 && !(PciPtr->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION)) {
                        //
                        // Skip sub functions, this is not a multi function device
                        //
                        Func = 8;
                    }
                }
            }
        }

        if (MaxBus > Bus) {
            Entry = AllocatePool (sizeof(PCI_ROOT_BRIDGE_ENTRY));
            Entry->Signature = EFI_ROOT_BRIDGE_LIST;
            Entry->BridgeNumber = BridgeNumber++;
            Entry->PrimaryBus = Bus;
            Entry->SubordinateBus = MaxBus;
            //
            // Assume only one PCI domain in the system
            //
            Entry->DevicePath = RootDevicePath;
            InsertTailList (ListHead, &Entry->Link);
 
            Bus = MaxBus;
        }
        if (!AnyPciToPciBridges && AnyPciDevice) {
            //
            // Root Bridge with no PtoP
            //
            Entry = AllocatePool (sizeof(PCI_ROOT_BRIDGE_ENTRY));
            Entry->Signature = EFI_ROOT_BRIDGE_LIST;
            Entry->BridgeNumber = BridgeNumber++;
            Entry->PrimaryBus = Bus; 
            Entry->SubordinateBus = Bus; 
            //
            // Assume only one PCI domain in the system
            //
            Entry->DevicePath = RootDevicePath;
            InsertTailList (ListHead, &Entry->Link);
        }
    }        


}

#ifdef EFI_DEBUG
VOID
PrintPciRootBridgeInfo (
    IN LIST_ENTRY   *ListHead
    )
{   
    PCI_ROOT_BRIDGE_ENTRY   *Entry;
    LIST_ENTRY              *Item;

    for (Item = ListHead->Flink; Item != ListHead; Item = Item->Flink) {
        Entry = CR(Item, PCI_ROOT_BRIDGE_ENTRY, Link, EFI_ROOT_BRIDGE_LIST);
        Print (L"\n PCI Root Bridge %d [0x%02x - 0x%02x]", 
                    Entry->BridgeNumber,
                    Entry->PrimaryBus,
                    Entry->SubordinateBus
                    );
    }
}

#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?