pcihostbridge.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,244 行 · 第 1/3 页

C
1,244
字号
/*++

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:

    PciHostBridge.c
    
Abstract:
   
    Pci Host Bridge driver: 
    Adapted to work under the NT32 environment and will thunk to the appropriate
    Kernel driver services if installed.

Revision History

--*/

#include "PciHostBridge.h"
#include "PciRootBridge.h"
#include "DeviceIo.h"
#include "Acpi.h"

#define RES_IO_BASE   0x1000
#define RES_MEM_BASE  0x80000000

//
// Support 64 K IO space
//
#define RES_IO_LIMIT  0xFFFF
//
// Supports 4G address space
//
#define RES_MEM_LIMIT 0xBFFFFFFF

//
// Hard code: Root Bridge Number within the host bridge
//            Root Bridge's attribute
//            Root Bridge's device path
//            Root Bridge's resource appeture
//
static UINTN mRootBridgeNumber[1] = {
  1
};

static UINT64 mRootBridgeAttribute[1][1] = {
  EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
};

static EFI_PCI_ROOT_BRIDGE_DEVICE_PATH    mEfiPciRootBridgeDevicePath[1][1] = {
  {
    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
  }
};

static PCI_ROOT_BRIDGE_RESOURCE_APPETURE  mResAppeture[1][1] = {
  {0, 255, 0, 0xffffffff, 0, 1 << 16}
};

static EFI_HANDLE                         mDriverImageHandle;

//
// Implementation
//
EFI_STATUS
InitializePciHostBridge (
  IN EFI_HANDLE       ImageHandle,
  IN EFI_SYSTEM_TABLE *SystemTable
  )
/*++

Routine Description:
  Entry point of this driver

Arguments:

    ImageHandle -

    SystemTable -
    
Returns:

--*/
// TODO:    EFI_DEVICE_ERROR - add return value to function comment
// TODO:    EFI_DEVICE_ERROR - add return value to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
{
  EFI_STATUS                Status;
  UINTN                     Loop1;
  UINTN                     Loop2;
  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
  PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;

  DxeInitializeDriverLib (ImageHandle, SystemTable);

  mDriverImageHandle = ImageHandle;

  //
  // Support one Host Bridge (one Root Bridge in this Host Bridge)
  //
  
  //
  // Create Host Bridge Device Handle
  //
  for (Loop1 = 0; Loop1 < HOST_BRIDGE_NUMBER; Loop1++) {
    Status = gBS->AllocatePool (
                    EfiBootServicesData,
                    sizeof (PCI_HOST_BRIDGE_INSTANCE),
                    &HostBridge
                    );
    ASSERT (!EFI_ERROR (Status));

    HostBridge->Signature                     = PCI_HOST_BRIDGE_SIGNATURE;
    HostBridge->RootBridgeNumber              = mRootBridgeNumber[Loop1];
    HostBridge->ResourceSubmited              = FALSE;
    HostBridge->CanRestarted                  = TRUE;

    HostBridge->ResAlloc.NotifyPhase          = NotifyPhase;
    HostBridge->ResAlloc.GetNextRootBridge    = GetNextRootBridge;
    HostBridge->ResAlloc.GetAllocAttributes   = GetAttributes;
    HostBridge->ResAlloc.StartBusEnumeration  = StartBusEnumeration;
    HostBridge->ResAlloc.SetBusNumbers        = SetBusNumbers;
    HostBridge->ResAlloc.SubmitResources      = SubmitResources;
    HostBridge->ResAlloc.GetProposedResources = GetProposedResources;
    HostBridge->ResAlloc.PreprocessController = PreprocessController;

    HostBridge->HostBridgeHandle              = NULL;
    Status = gBS->InstallProtocolInterface (
                    &HostBridge->HostBridgeHandle,
                    &gEfiPciHostBridgeResourceAllocationProtocolGuid,
                    EFI_NATIVE_INTERFACE,
                    &HostBridge->ResAlloc
                    );

    if (EFI_ERROR (Status)) {
      gBS->FreePool (HostBridge);
      return EFI_DEVICE_ERROR;
    }
  
    //
    // Create Root Bridge Device Handle in this Host Bridge
    //
    InitializeListHead (&HostBridge->Head);

    for (Loop2 = 0; Loop2 < HostBridge->RootBridgeNumber; Loop2++) {
      Status = gBS->AllocatePool (
                      EfiBootServicesData,
                      sizeof (PCI_ROOT_BRIDGE_INSTANCE),
                      &PrivateData
                      );
      ASSERT (!EFI_ERROR (Status));

      PrivateData->Signature  = PCI_ROOT_BRIDGE_SIGNATURE;

      PrivateData->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) &mEfiPciRootBridgeDevicePath[Loop1][Loop2];
      RootBridgeConstructor (
        &PrivateData->Io,
        HostBridge->HostBridgeHandle,
        mRootBridgeAttribute[Loop1][Loop2],
        mResAppeture[Loop1][Loop2]
        );

      PrivateData->Handle = NULL;
      Status = gBS->InstallMultipleProtocolInterfaces (
                      &PrivateData->Handle,
                      &gEfiDevicePathProtocolGuid,
                      PrivateData->DevicePath,
                      &gEfiPciRootBridgeIoProtocolGuid,
                      &PrivateData->Io,
                      NULL
                      );
      if (EFI_ERROR (Status)) {
        gBS->FreePool (PrivateData);
        return EFI_DEVICE_ERROR;
      }

      InsertTailList (&HostBridge->Head, &PrivateData->Link);
    }
    //
    // end for
    //
  }
  //
  // end for
  //
  Status = gDS->AddIoSpace (
                  EfiGcdIoTypeIo,
                  RES_IO_BASE,
                  RES_IO_LIMIT - RES_IO_BASE + 1
                  );

  Status = gDS->AddMemorySpace (
                  EfiGcdMemoryTypeMemoryMappedIo,
                  RES_MEM_BASE,
                  RES_MEM_LIMIT - RES_MEM_BASE + 1,
                  0
                  );

  DeviceIoConstructor ();

  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
NotifyPhase (
  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE    Phase
  )
/*++

Routine Description:
  Enter a certain phase of the PCI enumeration process

Arguments:
  This  -- The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance
  Phase -- The phase during enumeration
    
Returns:

--*/
// TODO:    EFI_NOT_READY - add return value to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
// TODO:    EFI_NOT_READY - add return value to function comment
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
{
  PCI_HOST_BRIDGE_INSTANCE  *HostBridgeInstance;
  PCI_ROOT_BRIDGE_INSTANCE  *RootBridgeInstance;
  PCI_RESOURCE_TYPE         Index;
  EFI_LIST_ENTRY            *List;
  EFI_PHYSICAL_ADDRESS      BaseAddress;
  UINT64                    AddrLen;
  UINTN                     BitsOfAlignment;
  UINT64                    Alignment;
  EFI_STATUS                Status;
  EFI_STATUS                ReturnStatus;

  HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);

  switch (Phase) {
  case EfiPciHostBridgeBeginEnumeration:
    if (HostBridgeInstance->CanRestarted) {
      //
      // Reset the Each Root Bridge
      //
      List = HostBridgeInstance->Head.ForwardLink;

      while (List != &HostBridgeInstance->Head) {
        RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
        for (Index = TypeIo; Index < TypeMax; Index++) {
          RootBridgeInstance->ResAllocNode[Index].Type    = Index;
          RootBridgeInstance->ResAllocNode[Index].Base    = 0;
          RootBridgeInstance->ResAllocNode[Index].Length  = 0;
          RootBridgeInstance->ResAllocNode[Index].Status  = ResNone;
        }

        List = List->ForwardLink;
      }

      HostBridgeInstance->ResourceSubmited  = FALSE;
      HostBridgeInstance->CanRestarted      = TRUE;
    } else {
      //
      // Can not restart
      //
      return EFI_NOT_READY;
    }
    break;

  case EfiPciHostBridgeBeginBusAllocation:
    //
    // No specific action is required here, can perform any chipset specific programing
    //
    HostBridgeInstance->CanRestarted = FALSE;
    return EFI_SUCCESS;
    break;

  case EfiPciHostBridgeEndBusAllocation:
    //
    // No specific action is required here, can perform any chipset specific programing
    //
    return EFI_SUCCESS;
    break;

  case EfiPciHostBridgeBeginResourceAllocation:
    //
    // No specific action is required here, can perform any chipset specific programing
    //
    return EFI_SUCCESS;
    break;

  case EfiPciHostBridgeAllocateResources:
    ReturnStatus = EFI_SUCCESS;
    if (HostBridgeInstance->ResourceSubmited) {
      //
      // Take care of the resource dependencies between the root bridges
      //
      List = HostBridgeInstance->Head.ForwardLink;

      while (List != &HostBridgeInstance->Head) {
        RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
        for (Index = TypeIo; Index < TypeBus; Index++) {
          if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {

            AddrLen   = RootBridgeInstance->ResAllocNode[Index].Length;
            Alignment = RootBridgeInstance->ResAllocNode[Index].Alignment;

            //
            // Get the number of '1' in Alignment.
            //
            for (BitsOfAlignment = 0; Alignment != 0; BitsOfAlignment++) {
              Alignment = RShiftU64 (Alignment, 1);
            }

            switch (Index) {
            case TypeIo:
              //
              // It is impossible to align 0xFFFF for IO16
              // So clear it
              //
              if (BitsOfAlignment >= 16) {
                BitsOfAlignment = 0;
              }

              Status = gDS->AllocateIoSpace (
                              EfiGcdAllocateAnySearchBottomUp,
                              EfiGcdIoTypeIo,
                              BitsOfAlignment,
                              AddrLen,
                              &BaseAddress,
                              mDriverImageHandle,
                              NULL
                              );

              if (!EFI_ERROR (Status)) {
                RootBridgeInstance->ResAllocNode[Index].Base    = (UINTN) BaseAddress;
                RootBridgeInstance->ResAllocNode[Index].Status  = ResAllocated;
              } else {
                ReturnStatus = Status;
                if (Status != EFI_OUT_OF_RESOURCES) {
                  RootBridgeInstance->ResAllocNode[Index].Length = 0;
                }
              }

              break;

            case TypeMem32:
              //
              // It is impossible to align 0xFFFFFFFF for Mem32
              // So clear it
              //
              if (BitsOfAlignment >= 32) {
                BitsOfAlignment = 0;
              }

              Status = gDS->AllocateMemorySpace (
                              EfiGcdAllocateAnySearchBottomUp,
                              EfiGcdMemoryTypeMemoryMappedIo,
                              BitsOfAlignment,
                              AddrLen,
                              &BaseAddress,
                              mDriverImageHandle,
                              NULL
                              );

              if (!EFI_ERROR (Status)) {
                RootBridgeInstance->ResAllocNode[Index].Base    = (UINTN) BaseAddress;
                RootBridgeInstance->ResAllocNode[Index].Status  = ResAllocated;
              } else {
                ReturnStatus = Status;
                if (Status != EFI_OUT_OF_RESOURCES) {
                  RootBridgeInstance->ResAllocNode[Index].Length = 0;
                }
              }
              break;

            case TypePMem32:
            case TypeMem64:
            case TypePMem64:
              ReturnStatus = EFI_ABORTED;
              break;
            }
            //
            // end switch
            //
          }
        }

        List = List->ForwardLink;
      }

      return ReturnStatus;

    } else {
      return EFI_NOT_READY;
    }

⌨️ 快捷键说明

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