Home | History | Annotate | Download | only in PciBusDxe
      1 /** @file
      2   PCI emumeration support functions implementation for PCI Bus module.
      3 
      4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
      5 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "PciBus.h"
     17 
     18 extern CHAR16  *mBarTypeStr[];
     19 
     20 /**
     21   This routine is used to check whether the pci device is present.
     22 
     23   @param PciRootBridgeIo   Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
     24   @param Pci               Output buffer for PCI device configuration space.
     25   @param Bus               PCI bus NO.
     26   @param Device            PCI device NO.
     27   @param Func              PCI Func NO.
     28 
     29   @retval EFI_NOT_FOUND    PCI device not present.
     30   @retval EFI_SUCCESS      PCI device is found.
     31 
     32 **/
     33 EFI_STATUS
     34 PciDevicePresent (
     35   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL     *PciRootBridgeIo,
     36   OUT PCI_TYPE00                          *Pci,
     37   IN  UINT8                               Bus,
     38   IN  UINT8                               Device,
     39   IN  UINT8                               Func
     40   )
     41 {
     42   UINT64      Address;
     43   EFI_STATUS  Status;
     44 
     45   //
     46   // Create PCI address map in terms of Bus, Device and Func
     47   //
     48   Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
     49 
     50   //
     51   // Read the Vendor ID register
     52   //
     53   Status = PciRootBridgeIo->Pci.Read (
     54                                   PciRootBridgeIo,
     55                                   EfiPciWidthUint32,
     56                                   Address,
     57                                   1,
     58                                   Pci
     59                                   );
     60 
     61   if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) {
     62     //
     63     // Read the entire config header for the device
     64     //
     65     Status = PciRootBridgeIo->Pci.Read (
     66                                     PciRootBridgeIo,
     67                                     EfiPciWidthUint32,
     68                                     Address,
     69                                     sizeof (PCI_TYPE00) / sizeof (UINT32),
     70                                     Pci
     71                                     );
     72 
     73     return EFI_SUCCESS;
     74   }
     75 
     76   return EFI_NOT_FOUND;
     77 }
     78 
     79 /**
     80   Collect all the resource information under this root bridge.
     81 
     82   A database that records all the information about pci device subject to this
     83   root bridge will then be created.
     84 
     85   @param Bridge         Parent bridge instance.
     86   @param StartBusNumber Bus number of begining.
     87 
     88   @retval EFI_SUCCESS   PCI device is found.
     89   @retval other         Some error occurred when reading PCI bridge information.
     90 
     91 **/
     92 EFI_STATUS
     93 PciPciDeviceInfoCollector (
     94   IN PCI_IO_DEVICE                      *Bridge,
     95   IN UINT8                              StartBusNumber
     96   )
     97 {
     98   EFI_STATUS          Status;
     99   PCI_TYPE00          Pci;
    100   UINT8               Device;
    101   UINT8               Func;
    102   UINT8               SecBus;
    103   PCI_IO_DEVICE       *PciIoDevice;
    104   EFI_PCI_IO_PROTOCOL *PciIo;
    105 
    106   Status  = EFI_SUCCESS;
    107   SecBus  = 0;
    108 
    109   for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
    110 
    111     for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
    112 
    113       //
    114       // Check to see whether PCI device is present
    115       //
    116       Status = PciDevicePresent (
    117                  Bridge->PciRootBridgeIo,
    118                  &Pci,
    119                  (UINT8) StartBusNumber,
    120                  (UINT8) Device,
    121                  (UINT8) Func
    122                  );
    123 
    124       if (EFI_ERROR (Status) && Func == 0) {
    125         //
    126         // go to next device if there is no Function 0
    127         //
    128         break;
    129       }
    130 
    131       if (!EFI_ERROR (Status)) {
    132 
    133         //
    134         // Call back to host bridge function
    135         //
    136         PreprocessController (Bridge, (UINT8) StartBusNumber, Device, Func, EfiPciBeforeResourceCollection);
    137 
    138         //
    139         // Collect all the information about the PCI device discovered
    140         //
    141         Status = PciSearchDevice (
    142                    Bridge,
    143                    &Pci,
    144                    (UINT8) StartBusNumber,
    145                    Device,
    146                    Func,
    147                    &PciIoDevice
    148                    );
    149 
    150         //
    151         // Recursively scan PCI busses on the other side of PCI-PCI bridges
    152         //
    153         //
    154         if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {
    155 
    156           //
    157           // If it is PPB, we need to get the secondary bus to continue the enumeration
    158           //
    159           PciIo   = &(PciIoDevice->PciIo);
    160 
    161           Status  = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, 1, &SecBus);
    162 
    163           if (EFI_ERROR (Status)) {
    164             return Status;
    165           }
    166 
    167           //
    168           // Ensure secondary bus number is greater than the primary bus number to avoid
    169           // any potential dead loop when PcdPciDisableBusEnumeration is set to TRUE
    170           //
    171           if (SecBus <= StartBusNumber) {
    172             break;
    173           }
    174 
    175           //
    176           // Get resource padding for PPB
    177           //
    178           GetResourcePaddingPpb (PciIoDevice);
    179 
    180           //
    181           // Deep enumerate the next level bus
    182           //
    183           Status = PciPciDeviceInfoCollector (
    184                      PciIoDevice,
    185                      (UINT8) (SecBus)
    186                      );
    187 
    188         }
    189 
    190         if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
    191 
    192           //
    193           // Skip sub functions, this is not a multi function device
    194           //
    195           Func = PCI_MAX_FUNC;
    196         }
    197       }
    198 
    199     }
    200   }
    201 
    202   return EFI_SUCCESS;
    203 }
    204 
    205 /**
    206   Seach required device and create PCI device instance.
    207 
    208   @param Bridge     Parent bridge instance.
    209   @param Pci        Input PCI device information block.
    210   @param Bus        PCI bus NO.
    211   @param Device     PCI device NO.
    212   @param Func       PCI func  NO.
    213   @param PciDevice  Output of searched PCI device instance.
    214 
    215   @retval EFI_SUCCESS           Successfully created PCI device instance.
    216   @retval EFI_OUT_OF_RESOURCES  Cannot get PCI device information.
    217 
    218 **/
    219 EFI_STATUS
    220 PciSearchDevice (
    221   IN  PCI_IO_DEVICE                         *Bridge,
    222   IN  PCI_TYPE00                            *Pci,
    223   IN  UINT8                                 Bus,
    224   IN  UINT8                                 Device,
    225   IN  UINT8                                 Func,
    226   OUT PCI_IO_DEVICE                         **PciDevice
    227   )
    228 {
    229   PCI_IO_DEVICE *PciIoDevice;
    230 
    231   PciIoDevice = NULL;
    232 
    233   DEBUG ((
    234     EFI_D_INFO,
    235     "PciBus: Discovered %s @ [%02x|%02x|%02x]\n",
    236     IS_PCI_BRIDGE (Pci) ?     L"PPB" :
    237     IS_CARDBUS_BRIDGE (Pci) ? L"P2C" :
    238                               L"PCI",
    239     Bus, Device, Func
    240     ));
    241 
    242   if (!IS_PCI_BRIDGE (Pci)) {
    243 
    244     if (IS_CARDBUS_BRIDGE (Pci)) {
    245       PciIoDevice = GatherP2CInfo (
    246                       Bridge,
    247                       Pci,
    248                       Bus,
    249                       Device,
    250                       Func
    251                       );
    252       if ((PciIoDevice != NULL) && gFullEnumeration) {
    253         InitializeP2C (PciIoDevice);
    254       }
    255     } else {
    256 
    257       //
    258       // Create private data for Pci Device
    259       //
    260       PciIoDevice = GatherDeviceInfo (
    261                       Bridge,
    262                       Pci,
    263                       Bus,
    264                       Device,
    265                       Func
    266                       );
    267 
    268     }
    269 
    270   } else {
    271 
    272     //
    273     // Create private data for PPB
    274     //
    275     PciIoDevice = GatherPpbInfo (
    276                     Bridge,
    277                     Pci,
    278                     Bus,
    279                     Device,
    280                     Func
    281                     );
    282 
    283     //
    284     // Special initialization for PPB including making the PPB quiet
    285     //
    286     if ((PciIoDevice != NULL) && gFullEnumeration) {
    287       InitializePpb (PciIoDevice);
    288     }
    289   }
    290 
    291   if (PciIoDevice == NULL) {
    292     return EFI_OUT_OF_RESOURCES;
    293   }
    294 
    295   //
    296   // Update the bar information for this PCI device so as to support some specific device
    297   //
    298   UpdatePciInfo (PciIoDevice);
    299 
    300   if (PciIoDevice->DevicePath == NULL) {
    301     return EFI_OUT_OF_RESOURCES;
    302   }
    303 
    304   //
    305   // Detect this function has option rom
    306   //
    307   if (gFullEnumeration) {
    308 
    309     if (!IS_CARDBUS_BRIDGE (Pci)) {
    310 
    311       GetOpRomInfo (PciIoDevice);
    312 
    313     }
    314 
    315     ResetPowerManagementFeature (PciIoDevice);
    316 
    317   }
    318 
    319   //
    320   // Insert it into a global tree for future reference
    321   //
    322   InsertPciDevice (Bridge, PciIoDevice);
    323 
    324   //
    325   // Determine PCI device attributes
    326   //
    327 
    328   if (PciDevice != NULL) {
    329     *PciDevice = PciIoDevice;
    330   }
    331 
    332   return EFI_SUCCESS;
    333 }
    334 
    335 /**
    336   Dump the PPB padding resource information.
    337 
    338   @param PciIoDevice     PCI IO instance.
    339   @param ResourceType    The desired resource type to dump.
    340                          PciBarTypeUnknown means to dump all types of resources.
    341 **/
    342 VOID
    343 DumpPpbPaddingResource (
    344   IN PCI_IO_DEVICE                    *PciIoDevice,
    345   IN PCI_BAR_TYPE                     ResourceType
    346   )
    347 {
    348   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
    349   PCI_BAR_TYPE                      Type;
    350 
    351   if (PciIoDevice->ResourcePaddingDescriptors == NULL) {
    352     return;
    353   }
    354 
    355   if (ResourceType == PciBarTypeIo16 || ResourceType == PciBarTypeIo32) {
    356     ResourceType = PciBarTypeIo;
    357   }
    358 
    359   for (Descriptor = PciIoDevice->ResourcePaddingDescriptors; Descriptor->Desc != ACPI_END_TAG_DESCRIPTOR; Descriptor++) {
    360 
    361     Type = PciBarTypeUnknown;
    362     if (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {
    363       Type = PciBarTypeIo;
    364     } else if (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
    365 
    366       if (Descriptor->AddrSpaceGranularity == 32) {
    367         //
    368         // prefechable
    369         //
    370         if (Descriptor->SpecificFlag == EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) {
    371           Type = PciBarTypePMem32;
    372         }
    373 
    374         //
    375         // Non-prefechable
    376         //
    377         if (Descriptor->SpecificFlag == 0) {
    378           Type = PciBarTypeMem32;
    379         }
    380       }
    381 
    382       if (Descriptor->AddrSpaceGranularity == 64) {
    383         //
    384         // prefechable
    385         //
    386         if (Descriptor->SpecificFlag == EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) {
    387           Type = PciBarTypePMem64;
    388         }
    389 
    390         //
    391         // Non-prefechable
    392         //
    393         if (Descriptor->SpecificFlag == 0) {
    394           Type = PciBarTypeMem64;
    395         }
    396       }
    397     }
    398 
    399     if ((Type != PciBarTypeUnknown) && ((ResourceType == PciBarTypeUnknown) || (ResourceType == Type))) {
    400       DEBUG ((
    401         EFI_D_INFO,
    402         "   Padding: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx\n",
    403         mBarTypeStr[Type], Descriptor->AddrRangeMax, Descriptor->AddrLen
    404         ));
    405     }
    406   }
    407 
    408 }
    409 
    410 /**
    411   Dump the PCI BAR information.
    412 
    413   @param PciIoDevice     PCI IO instance.
    414 **/
    415 VOID
    416 DumpPciBars (
    417   IN PCI_IO_DEVICE                    *PciIoDevice
    418   )
    419 {
    420   UINTN                               Index;
    421 
    422   for (Index = 0; Index < PCI_MAX_BAR; Index++) {
    423     if (PciIoDevice->PciBar[Index].BarType == PciBarTypeUnknown) {
    424       continue;
    425     }
    426 
    427     DEBUG ((
    428       EFI_D_INFO,
    429       "   BAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",
    430       Index, mBarTypeStr[MIN (PciIoDevice->PciBar[Index].BarType, PciBarTypeMaxType)],
    431       PciIoDevice->PciBar[Index].Alignment, PciIoDevice->PciBar[Index].Length, PciIoDevice->PciBar[Index].Offset
    432       ));
    433   }
    434 
    435   for (Index = 0; Index < PCI_MAX_BAR; Index++) {
    436     if ((PciIoDevice->VfPciBar[Index].BarType == PciBarTypeUnknown) && (PciIoDevice->VfPciBar[Index].Length == 0)) {
    437       continue;
    438     }
    439 
    440     DEBUG ((
    441       EFI_D_INFO,
    442       " VFBAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",
    443       Index, mBarTypeStr[MIN (PciIoDevice->VfPciBar[Index].BarType, PciBarTypeMaxType)],
    444       PciIoDevice->VfPciBar[Index].Alignment, PciIoDevice->VfPciBar[Index].Length, PciIoDevice->VfPciBar[Index].Offset
    445       ));
    446   }
    447   DEBUG ((EFI_D_INFO, "\n"));
    448 }
    449 
    450 /**
    451   Create PCI device instance for PCI device.
    452 
    453   @param Bridge   Parent bridge instance.
    454   @param Pci      Input PCI device information block.
    455   @param Bus      PCI device Bus NO.
    456   @param Device   PCI device Device NO.
    457   @param Func     PCI device's func NO.
    458 
    459   @return  Created PCI device instance.
    460 
    461 **/
    462 PCI_IO_DEVICE *
    463 GatherDeviceInfo (
    464   IN PCI_IO_DEVICE                    *Bridge,
    465   IN PCI_TYPE00                       *Pci,
    466   IN UINT8                            Bus,
    467   IN UINT8                            Device,
    468   IN UINT8                            Func
    469   )
    470 {
    471   UINTN                           Offset;
    472   UINTN                           BarIndex;
    473   PCI_IO_DEVICE                   *PciIoDevice;
    474 
    475   PciIoDevice = CreatePciIoDevice (
    476                   Bridge,
    477                   Pci,
    478                   Bus,
    479                   Device,
    480                   Func
    481                   );
    482 
    483   if (PciIoDevice == NULL) {
    484     return NULL;
    485   }
    486 
    487   //
    488   // If it is a full enumeration, disconnect the device in advance
    489   //
    490   if (gFullEnumeration) {
    491 
    492     PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
    493 
    494   }
    495 
    496   //
    497   // Start to parse the bars
    498   //
    499   for (Offset = 0x10, BarIndex = 0; Offset <= 0x24 && BarIndex < PCI_MAX_BAR; BarIndex++) {
    500     Offset = PciParseBar (PciIoDevice, Offset, BarIndex);
    501   }
    502 
    503   //
    504   // Parse the SR-IOV VF bars
    505   //
    506   if (PcdGetBool (PcdSrIovSupport) && PciIoDevice->SrIovCapabilityOffset != 0) {
    507     for (Offset = PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_BAR0, BarIndex = 0;
    508          Offset <= PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_BAR5;
    509          BarIndex++) {
    510 
    511       ASSERT (BarIndex < PCI_MAX_BAR);
    512       Offset = PciIovParseVfBar (PciIoDevice, Offset, BarIndex);
    513     }
    514   }
    515 
    516   DEBUG_CODE (DumpPciBars (PciIoDevice););
    517   return PciIoDevice;
    518 }
    519 
    520 /**
    521   Create PCI device instance for PCI-PCI bridge.
    522 
    523   @param Bridge   Parent bridge instance.
    524   @param Pci      Input PCI device information block.
    525   @param Bus      PCI device Bus NO.
    526   @param Device   PCI device Device NO.
    527   @param Func     PCI device's func NO.
    528 
    529   @return  Created PCI device instance.
    530 
    531 **/
    532 PCI_IO_DEVICE *
    533 GatherPpbInfo (
    534   IN PCI_IO_DEVICE                    *Bridge,
    535   IN PCI_TYPE00                       *Pci,
    536   IN UINT8                            Bus,
    537   IN UINT8                            Device,
    538   IN UINT8                            Func
    539   )
    540 {
    541   PCI_IO_DEVICE                   *PciIoDevice;
    542   EFI_STATUS                      Status;
    543   UINT8                           Value;
    544   EFI_PCI_IO_PROTOCOL             *PciIo;
    545   UINT8                           Temp;
    546   UINT32                          PMemBaseLimit;
    547   UINT16                          PrefetchableMemoryBase;
    548   UINT16                          PrefetchableMemoryLimit;
    549 
    550   PciIoDevice = CreatePciIoDevice (
    551                   Bridge,
    552                   Pci,
    553                   Bus,
    554                   Device,
    555                   Func
    556                   );
    557 
    558   if (PciIoDevice == NULL) {
    559     return NULL;
    560   }
    561 
    562   if (gFullEnumeration) {
    563     PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
    564 
    565     //
    566     // Initalize the bridge control register
    567     //
    568     PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED);
    569 
    570   }
    571 
    572   //
    573   // PPB can have two BARs
    574   //
    575   if (PciParseBar (PciIoDevice, 0x10, PPB_BAR_0) == 0x14) {
    576     //
    577     // Not 64-bit bar
    578     //
    579     PciParseBar (PciIoDevice, 0x14, PPB_BAR_1);
    580   }
    581 
    582   PciIo = &PciIoDevice->PciIo;
    583 
    584   //
    585   // Test whether it support 32 decode or not
    586   //
    587   PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
    588   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
    589   PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
    590   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
    591 
    592   if (Value != 0) {
    593     if ((Value & 0x01) != 0) {
    594       PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED;
    595     } else {
    596       PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
    597     }
    598   }
    599 
    600   //
    601   // if PcdPciBridgeIoAlignmentProbe is TRUE, PCI bus driver probes
    602   // PCI bridge supporting non-standard I/O window alignment less than 4K.
    603   //
    604 
    605   PciIoDevice->BridgeIoAlignment = 0xFFF;
    606   if (FeaturePcdGet (PcdPciBridgeIoAlignmentProbe)) {
    607     //
    608     // Check any bits of bit 3-1 of I/O Base Register are writable.
    609     // if so, it is assumed non-standard I/O window alignment is supported by this bridge.
    610     // Per spec, bit 3-1 of I/O Base Register are reserved bits, so its content can't be assumed.
    611     //
    612     Value = (UINT8)(Temp ^ (BIT3 | BIT2 | BIT1));
    613     PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
    614     PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
    615     PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
    616     Value = (UINT8)((Value ^ Temp) & (BIT3 | BIT2 | BIT1));
    617     switch (Value) {
    618       case BIT3:
    619         PciIoDevice->BridgeIoAlignment = 0x7FF;
    620         break;
    621       case BIT3 | BIT2:
    622         PciIoDevice->BridgeIoAlignment = 0x3FF;
    623         break;
    624       case BIT3 | BIT2 | BIT1:
    625         PciIoDevice->BridgeIoAlignment = 0x1FF;
    626         break;
    627     }
    628   }
    629 
    630   Status = BarExisted (
    631             PciIoDevice,
    632             0x24,
    633             NULL,
    634             &PMemBaseLimit
    635             );
    636 
    637   //
    638   // Test if it supports 64 memory or not
    639   //
    640   // The bottom 4 bits of both the Prefetchable Memory Base and Prefetchable Memory Limit
    641   // registers:
    642   //   0 - the bridge supports only 32 bit addresses.
    643   //   1 - the bridge supports 64-bit addresses.
    644   //
    645   PrefetchableMemoryBase = (UINT16)(PMemBaseLimit & 0xffff);
    646   PrefetchableMemoryLimit = (UINT16)(PMemBaseLimit >> 16);
    647   if (!EFI_ERROR (Status) &&
    648       (PrefetchableMemoryBase & 0x000f) == 0x0001 &&
    649       (PrefetchableMemoryLimit & 0x000f) == 0x0001) {
    650     Status = BarExisted (
    651               PciIoDevice,
    652               0x28,
    653               NULL,
    654               NULL
    655               );
    656 
    657     if (!EFI_ERROR (Status)) {
    658       PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
    659       PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;
    660     } else {
    661       PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
    662     }
    663   }
    664 
    665   //
    666   // Memory 32 code is required for ppb
    667   //
    668   PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
    669 
    670   GetResourcePaddingPpb (PciIoDevice);
    671 
    672   DEBUG_CODE (
    673     DumpPpbPaddingResource (PciIoDevice, PciBarTypeUnknown);
    674     DumpPciBars (PciIoDevice);
    675   );
    676 
    677   return PciIoDevice;
    678 }
    679 
    680 
    681 /**
    682   Create PCI device instance for PCI Card bridge device.
    683 
    684   @param Bridge   Parent bridge instance.
    685   @param Pci      Input PCI device information block.
    686   @param Bus      PCI device Bus NO.
    687   @param Device   PCI device Device NO.
    688   @param Func     PCI device's func NO.
    689 
    690   @return  Created PCI device instance.
    691 
    692 **/
    693 PCI_IO_DEVICE *
    694 GatherP2CInfo (
    695   IN PCI_IO_DEVICE                    *Bridge,
    696   IN PCI_TYPE00                       *Pci,
    697   IN UINT8                            Bus,
    698   IN UINT8                            Device,
    699   IN UINT8                            Func
    700   )
    701 {
    702   PCI_IO_DEVICE                   *PciIoDevice;
    703 
    704   PciIoDevice = CreatePciIoDevice (
    705                   Bridge,
    706                   Pci,
    707                   Bus,
    708                   Device,
    709                   Func
    710                   );
    711 
    712   if (PciIoDevice == NULL) {
    713     return NULL;
    714   }
    715 
    716   if (gFullEnumeration) {
    717     PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
    718 
    719     //
    720     // Initalize the bridge control register
    721     //
    722     PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED);
    723   }
    724 
    725   //
    726   // P2C only has one bar that is in 0x10
    727   //
    728   PciParseBar (PciIoDevice, 0x10, P2C_BAR_0);
    729 
    730   //
    731   // Read PciBar information from the bar register
    732   //
    733   GetBackPcCardBar (PciIoDevice);
    734   PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED  |
    735                          EFI_BRIDGE_PMEM32_DECODE_SUPPORTED |
    736                          EFI_BRIDGE_IO32_DECODE_SUPPORTED;
    737 
    738   DEBUG_CODE (DumpPciBars (PciIoDevice););
    739 
    740   return PciIoDevice;
    741 }
    742 
    743 /**
    744   Create device path for pci deivce.
    745 
    746   @param ParentDevicePath  Parent bridge's path.
    747   @param PciIoDevice       Pci device instance.
    748 
    749   @return Device path protocol instance for specific pci device.
    750 
    751 **/
    752 EFI_DEVICE_PATH_PROTOCOL *
    753 CreatePciDevicePath (
    754   IN  EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
    755   IN  PCI_IO_DEVICE            *PciIoDevice
    756   )
    757 {
    758 
    759   PCI_DEVICE_PATH PciNode;
    760 
    761   //
    762   // Create PCI device path
    763   //
    764   PciNode.Header.Type     = HARDWARE_DEVICE_PATH;
    765   PciNode.Header.SubType  = HW_PCI_DP;
    766   SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
    767 
    768   PciNode.Device          = PciIoDevice->DeviceNumber;
    769   PciNode.Function        = PciIoDevice->FunctionNumber;
    770   PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header);
    771 
    772   return PciIoDevice->DevicePath;
    773 }
    774 
    775 /**
    776   Check whether the PCI IOV VF bar is existed or not.
    777 
    778   @param PciIoDevice       A pointer to the PCI_IO_DEVICE.
    779   @param Offset            The offset.
    780   @param BarLengthValue    The bar length value returned.
    781   @param OriginalBarValue  The original bar value returned.
    782 
    783   @retval EFI_NOT_FOUND    The bar doesn't exist.
    784   @retval EFI_SUCCESS      The bar exist.
    785 
    786 **/
    787 EFI_STATUS
    788 VfBarExisted (
    789   IN PCI_IO_DEVICE *PciIoDevice,
    790   IN UINTN         Offset,
    791   OUT UINT32       *BarLengthValue,
    792   OUT UINT32       *OriginalBarValue
    793   )
    794 {
    795   EFI_PCI_IO_PROTOCOL *PciIo;
    796   UINT32              OriginalValue;
    797   UINT32              Value;
    798   EFI_TPL             OldTpl;
    799 
    800   //
    801   // Ensure it is called properly
    802   //
    803   ASSERT (PciIoDevice->SrIovCapabilityOffset != 0);
    804   if (PciIoDevice->SrIovCapabilityOffset == 0) {
    805     return EFI_NOT_FOUND;
    806   }
    807 
    808   PciIo = &PciIoDevice->PciIo;
    809 
    810   //
    811   // Preserve the original value
    812   //
    813 
    814   PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &OriginalValue);
    815 
    816   //
    817   // Raise TPL to high level to disable timer interrupt while the BAR is probed
    818   //
    819   OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
    820 
    821   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &gAllOne);
    822   PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &Value);
    823 
    824   //
    825   // Write back the original value
    826   //
    827   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &OriginalValue);
    828 
    829   //
    830   // Restore TPL to its original level
    831   //
    832   gBS->RestoreTPL (OldTpl);
    833 
    834   if (BarLengthValue != NULL) {
    835     *BarLengthValue = Value;
    836   }
    837 
    838   if (OriginalBarValue != NULL) {
    839     *OriginalBarValue = OriginalValue;
    840   }
    841 
    842   if (Value == 0) {
    843     return EFI_NOT_FOUND;
    844   } else {
    845     return EFI_SUCCESS;
    846   }
    847 }
    848 
    849 /**
    850   Check whether the bar is existed or not.
    851 
    852   @param PciIoDevice       A pointer to the PCI_IO_DEVICE.
    853   @param Offset            The offset.
    854   @param BarLengthValue    The bar length value returned.
    855   @param OriginalBarValue  The original bar value returned.
    856 
    857   @retval EFI_NOT_FOUND    The bar doesn't exist.
    858   @retval EFI_SUCCESS      The bar exist.
    859 
    860 **/
    861 EFI_STATUS
    862 BarExisted (
    863   IN  PCI_IO_DEVICE *PciIoDevice,
    864   IN  UINTN         Offset,
    865   OUT UINT32        *BarLengthValue,
    866   OUT UINT32        *OriginalBarValue
    867   )
    868 {
    869   EFI_PCI_IO_PROTOCOL *PciIo;
    870   UINT32              OriginalValue;
    871   UINT32              Value;
    872   EFI_TPL             OldTpl;
    873 
    874   PciIo = &PciIoDevice->PciIo;
    875 
    876   //
    877   // Preserve the original value
    878   //
    879   PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);
    880 
    881   //
    882   // Raise TPL to high level to disable timer interrupt while the BAR is probed
    883   //
    884   OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
    885 
    886   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOne);
    887   PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value);
    888 
    889   //
    890   // Write back the original value
    891   //
    892   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);
    893 
    894   //
    895   // Restore TPL to its original level
    896   //
    897   gBS->RestoreTPL (OldTpl);
    898 
    899   if (BarLengthValue != NULL) {
    900     *BarLengthValue = Value;
    901   }
    902 
    903   if (OriginalBarValue != NULL) {
    904     *OriginalBarValue = OriginalValue;
    905   }
    906 
    907   if (Value == 0) {
    908     return EFI_NOT_FOUND;
    909   } else {
    910     return EFI_SUCCESS;
    911   }
    912 }
    913 
    914 /**
    915   Test whether the device can support given attributes.
    916 
    917   @param PciIoDevice      Pci device instance.
    918   @param Command          Input command register value, and
    919                           returned supported register value.
    920   @param BridgeControl    Inout bridge control value for PPB or P2C, and
    921                           returned supported bridge control value.
    922   @param OldCommand       Returned and stored old command register offset.
    923   @param OldBridgeControl Returned and stored old Bridge control value for PPB or P2C.
    924 
    925 **/
    926 VOID
    927 PciTestSupportedAttribute (
    928   IN     PCI_IO_DEVICE                      *PciIoDevice,
    929   IN OUT UINT16                             *Command,
    930   IN OUT UINT16                             *BridgeControl,
    931      OUT UINT16                             *OldCommand,
    932      OUT UINT16                             *OldBridgeControl
    933   )
    934 {
    935   EFI_TPL OldTpl;
    936 
    937   //
    938   // Preserve the original value
    939   //
    940   PCI_READ_COMMAND_REGISTER (PciIoDevice, OldCommand);
    941 
    942   //
    943   // Raise TPL to high level to disable timer interrupt while the BAR is probed
    944   //
    945   OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
    946 
    947   PCI_SET_COMMAND_REGISTER (PciIoDevice, *Command);
    948   PCI_READ_COMMAND_REGISTER (PciIoDevice, Command);
    949 
    950   //
    951   // Write back the original value
    952   //
    953   PCI_SET_COMMAND_REGISTER (PciIoDevice, *OldCommand);
    954 
    955   //
    956   // Restore TPL to its original level
    957   //
    958   gBS->RestoreTPL (OldTpl);
    959 
    960   if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
    961 
    962     //
    963     // Preserve the original value
    964     //
    965     PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice, OldBridgeControl);
    966 
    967     //
    968     // Raise TPL to high level to disable timer interrupt while the BAR is probed
    969     //
    970     OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
    971 
    972     PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice, *BridgeControl);
    973     PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice, BridgeControl);
    974 
    975     //
    976     // Write back the original value
    977     //
    978     PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice, *OldBridgeControl);
    979 
    980     //
    981     // Restore TPL to its original level
    982     //
    983     gBS->RestoreTPL (OldTpl);
    984 
    985   } else {
    986     *OldBridgeControl = 0;
    987     *BridgeControl    = 0;
    988   }
    989 }
    990 
    991 /**
    992   Set the supported or current attributes of a PCI device.
    993 
    994   @param PciIoDevice    Structure pointer for PCI device.
    995   @param Command        Command register value.
    996   @param BridgeControl  Bridge control value for PPB or P2C.
    997   @param Option         Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.
    998 
    999 **/
   1000 VOID
   1001 PciSetDeviceAttribute (
   1002   IN PCI_IO_DEVICE                      *PciIoDevice,
   1003   IN UINT16                             Command,
   1004   IN UINT16                             BridgeControl,
   1005   IN UINTN                              Option
   1006   )
   1007 {
   1008   UINT64  Attributes;
   1009 
   1010   Attributes = 0;
   1011 
   1012   if ((Command & EFI_PCI_COMMAND_IO_SPACE) != 0) {
   1013     Attributes |= EFI_PCI_IO_ATTRIBUTE_IO;
   1014   }
   1015 
   1016   if ((Command & EFI_PCI_COMMAND_MEMORY_SPACE) != 0) {
   1017     Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY;
   1018   }
   1019 
   1020   if ((Command & EFI_PCI_COMMAND_BUS_MASTER) != 0) {
   1021     Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;
   1022   }
   1023 
   1024   if ((Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) {
   1025     Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
   1026   }
   1027 
   1028   if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) != 0) {
   1029     Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;
   1030   }
   1031 
   1032   if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) != 0) {
   1033     Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;
   1034     Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
   1035     Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
   1036   }
   1037 
   1038   if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16) != 0) {
   1039     Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO_16;
   1040     Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16;
   1041   }
   1042 
   1043   if (Option == EFI_SET_SUPPORTS) {
   1044 
   1045     Attributes |= (UINT64) (EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE |
   1046                   EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED        |
   1047                   EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE       |
   1048                   EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE      |
   1049                   EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM         |
   1050                   EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE);
   1051 
   1052     if (IS_PCI_LPC (&PciIoDevice->Pci)) {
   1053         Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;
   1054         Attributes |= (mReserveIsaAliases ? (UINT64) EFI_PCI_IO_ATTRIBUTE_ISA_IO : \
   1055                                             (UINT64) EFI_PCI_IO_ATTRIBUTE_ISA_IO_16);
   1056     }
   1057 
   1058     if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
   1059       //
   1060       // For bridge, it should support IDE attributes
   1061       //
   1062       Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;
   1063       Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;
   1064 
   1065       if (mReserveVgaAliases) {
   1066         Attributes &= ~(UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 | \
   1067                                 EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16);
   1068       } else {
   1069         Attributes &= ~(UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO | \
   1070                                 EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO);
   1071       }
   1072     } else {
   1073 
   1074       if (IS_PCI_IDE (&PciIoDevice->Pci)) {
   1075         Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;
   1076         Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;
   1077       }
   1078 
   1079       if (IS_PCI_VGA (&PciIoDevice->Pci)) {
   1080         Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
   1081         Attributes |= (mReserveVgaAliases ? (UINT64) EFI_PCI_IO_ATTRIBUTE_VGA_IO : \
   1082                                             (UINT64) EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);
   1083       }
   1084     }
   1085 
   1086     PciIoDevice->Supports = Attributes;
   1087     PciIoDevice->Supports &= ( (PciIoDevice->Parent->Supports) | \
   1088                                EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | \
   1089                                EFI_PCI_IO_ATTRIBUTE_BUS_MASTER );
   1090 
   1091   } else {
   1092     //
   1093     // When this attribute is clear, the RomImage and RomSize fields in the PCI IO were
   1094     // initialized based on the PCI option ROM found through the ROM BAR of the PCI controller.
   1095     // When this attribute is set, the PCI option ROM described by the RomImage and RomSize
   1096     // fields is not from the the ROM BAR of the PCI controller.
   1097     //
   1098     if (!PciIoDevice->EmbeddedRom) {
   1099       Attributes |= EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM;
   1100     }
   1101     PciIoDevice->Attributes = Attributes;
   1102   }
   1103 }
   1104 
   1105 /**
   1106   Determine if the device can support Fast Back to Back attribute.
   1107 
   1108   @param PciIoDevice  Pci device instance.
   1109   @param StatusIndex  Status register value.
   1110 
   1111   @retval EFI_SUCCESS       This device support Fast Back to Back attribute.
   1112   @retval EFI_UNSUPPORTED   This device doesn't support Fast Back to Back attribute.
   1113 
   1114 **/
   1115 EFI_STATUS
   1116 GetFastBackToBackSupport (
   1117   IN PCI_IO_DEVICE                      *PciIoDevice,
   1118   IN UINT8                              StatusIndex
   1119   )
   1120 {
   1121   EFI_PCI_IO_PROTOCOL *PciIo;
   1122   EFI_STATUS          Status;
   1123   UINT32              StatusRegister;
   1124 
   1125   //
   1126   // Read the status register
   1127   //
   1128   PciIo   = &PciIoDevice->PciIo;
   1129   Status  = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, StatusIndex, 1, &StatusRegister);
   1130   if (EFI_ERROR (Status)) {
   1131     return EFI_UNSUPPORTED;
   1132   }
   1133 
   1134   //
   1135   // Check the Fast B2B bit
   1136   //
   1137   if ((StatusRegister & EFI_PCI_FAST_BACK_TO_BACK_CAPABLE) != 0) {
   1138     return EFI_SUCCESS;
   1139   } else {
   1140     return EFI_UNSUPPORTED;
   1141   }
   1142 }
   1143 
   1144 /**
   1145   Process the option ROM for all the children of the specified parent PCI device.
   1146   It can only be used after the first full Option ROM process.
   1147 
   1148   @param PciIoDevice Pci device instance.
   1149 
   1150 **/
   1151 VOID
   1152 ProcessOptionRomLight (
   1153   IN PCI_IO_DEVICE                      *PciIoDevice
   1154   )
   1155 {
   1156   PCI_IO_DEVICE   *Temp;
   1157   LIST_ENTRY      *CurrentLink;
   1158 
   1159   //
   1160   // For RootBridge, PPB , P2C, go recursively to traverse all its children
   1161   //
   1162   CurrentLink = PciIoDevice->ChildList.ForwardLink;
   1163   while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {
   1164 
   1165     Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
   1166 
   1167     if (!IsListEmpty (&Temp->ChildList)) {
   1168       ProcessOptionRomLight (Temp);
   1169     }
   1170 
   1171     PciRomGetImageMapping (Temp);
   1172 
   1173     //
   1174     // The OpRom has already been processed in the first round
   1175     //
   1176     Temp->AllOpRomProcessed = TRUE;
   1177 
   1178     CurrentLink = CurrentLink->ForwardLink;
   1179   }
   1180 }
   1181 
   1182 /**
   1183   Determine the related attributes of all devices under a Root Bridge.
   1184 
   1185   @param PciIoDevice   PCI device instance.
   1186 
   1187 **/
   1188 EFI_STATUS
   1189 DetermineDeviceAttribute (
   1190   IN PCI_IO_DEVICE                      *PciIoDevice
   1191   )
   1192 {
   1193   UINT16          Command;
   1194   UINT16          BridgeControl;
   1195   UINT16          OldCommand;
   1196   UINT16          OldBridgeControl;
   1197   BOOLEAN         FastB2BSupport;
   1198   PCI_IO_DEVICE   *Temp;
   1199   LIST_ENTRY      *CurrentLink;
   1200   EFI_STATUS      Status;
   1201 
   1202   //
   1203   // For Root Bridge, just copy it by RootBridgeIo proctocol
   1204   // so as to keep consistent with the actual attribute
   1205   //
   1206   if (PciIoDevice->Parent == NULL) {
   1207     Status = PciIoDevice->PciRootBridgeIo->GetAttributes (
   1208                                             PciIoDevice->PciRootBridgeIo,
   1209                                             &PciIoDevice->Supports,
   1210                                             &PciIoDevice->Attributes
   1211                                             );
   1212     if (EFI_ERROR (Status)) {
   1213       return Status;
   1214     }
   1215     //
   1216     // Assume the PCI Root Bridge supports DAC
   1217     //
   1218     PciIoDevice->Supports |= (UINT64)(EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE |
   1219                               EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM |
   1220                               EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE);
   1221 
   1222   } else {
   1223 
   1224     //
   1225     // Set the attributes to be checked for common PCI devices and PPB or P2C
   1226     // Since some devices only support part of them, it is better to set the
   1227     // attribute according to its command or bridge control register
   1228     //
   1229     Command = EFI_PCI_COMMAND_IO_SPACE     |
   1230               EFI_PCI_COMMAND_MEMORY_SPACE |
   1231               EFI_PCI_COMMAND_BUS_MASTER   |
   1232               EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
   1233 
   1234     BridgeControl = EFI_PCI_BRIDGE_CONTROL_ISA | EFI_PCI_BRIDGE_CONTROL_VGA | EFI_PCI_BRIDGE_CONTROL_VGA_16;
   1235 
   1236     //
   1237     // Test whether the device can support attributes above
   1238     //
   1239     PciTestSupportedAttribute (PciIoDevice, &Command, &BridgeControl, &OldCommand, &OldBridgeControl);
   1240 
   1241     //
   1242     // Set the supported attributes for specified PCI device
   1243     //
   1244     PciSetDeviceAttribute (PciIoDevice, Command, BridgeControl, EFI_SET_SUPPORTS);
   1245 
   1246     //
   1247     // Set the current attributes for specified PCI device
   1248     //
   1249     PciSetDeviceAttribute (PciIoDevice, OldCommand, OldBridgeControl, EFI_SET_ATTRIBUTES);
   1250 
   1251     //
   1252     // Enable other supported attributes but not defined in PCI_IO_PROTOCOL
   1253     //
   1254     PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE);
   1255   }
   1256 
   1257   FastB2BSupport = TRUE;
   1258 
   1259   //
   1260   // P2C can not support FB2B on the secondary side
   1261   //
   1262   if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
   1263     FastB2BSupport = FALSE;
   1264   }
   1265 
   1266   //
   1267   // For RootBridge, PPB , P2C, go recursively to traverse all its children
   1268   //
   1269   CurrentLink = PciIoDevice->ChildList.ForwardLink;
   1270   while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {
   1271 
   1272     Temp    = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
   1273     Status  = DetermineDeviceAttribute (Temp);
   1274     if (EFI_ERROR (Status)) {
   1275       return Status;
   1276     }
   1277     //
   1278     // Detect Fast Bact to Bact support for the device under the bridge
   1279     //
   1280     Status = GetFastBackToBackSupport (Temp, PCI_PRIMARY_STATUS_OFFSET);
   1281     if (FastB2BSupport && EFI_ERROR (Status)) {
   1282       FastB2BSupport = FALSE;
   1283     }
   1284 
   1285     CurrentLink = CurrentLink->ForwardLink;
   1286   }
   1287   //
   1288   // Set or clear Fast Back to Back bit for the whole bridge
   1289   //
   1290   if (!IsListEmpty (&PciIoDevice->ChildList)) {
   1291 
   1292     if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
   1293 
   1294       Status = GetFastBackToBackSupport (PciIoDevice, PCI_BRIDGE_STATUS_REGISTER_OFFSET);
   1295 
   1296       if (EFI_ERROR (Status) || (!FastB2BSupport)) {
   1297         FastB2BSupport = FALSE;
   1298         PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);
   1299       } else {
   1300         PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);
   1301       }
   1302     }
   1303 
   1304     CurrentLink = PciIoDevice->ChildList.ForwardLink;
   1305     while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {
   1306       Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
   1307       if (FastB2BSupport) {
   1308         PCI_ENABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);
   1309       } else {
   1310         PCI_DISABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);
   1311       }
   1312 
   1313       CurrentLink = CurrentLink->ForwardLink;
   1314     }
   1315   }
   1316   //
   1317   // End for IsListEmpty
   1318   //
   1319   return EFI_SUCCESS;
   1320 }
   1321 
   1322 /**
   1323   This routine is used to update the bar information for those incompatible PCI device.
   1324 
   1325   @param PciIoDevice      Input Pci device instance. Output Pci device instance with updated
   1326                           Bar information.
   1327 
   1328   @retval EFI_SUCCESS     Successfully updated bar information.
   1329   @retval EFI_UNSUPPORTED Given PCI device doesn't belong to incompatible PCI device list.
   1330 
   1331 **/
   1332 EFI_STATUS
   1333 UpdatePciInfo (
   1334   IN OUT PCI_IO_DEVICE    *PciIoDevice
   1335   )
   1336 {
   1337   EFI_STATUS                        Status;
   1338   UINTN                             BarIndex;
   1339   UINTN                             BarEndIndex;
   1340   BOOLEAN                           SetFlag;
   1341   VOID                              *Configuration;
   1342   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
   1343 
   1344   Configuration = NULL;
   1345   Status        = EFI_SUCCESS;
   1346 
   1347   if (gIncompatiblePciDeviceSupport == NULL) {
   1348     //
   1349     // It can only be supported after the Incompatible PCI Device
   1350     // Support Protocol has been installed
   1351     //
   1352     Status = gBS->LocateProtocol (
   1353                     &gEfiIncompatiblePciDeviceSupportProtocolGuid,
   1354                     NULL,
   1355                     (VOID **) &gIncompatiblePciDeviceSupport
   1356                     );
   1357   }
   1358   if (Status == EFI_SUCCESS) {
   1359       //
   1360       // Check whether the device belongs to incompatible devices from protocol or not
   1361       // If it is , then get its special requirement in the ACPI table
   1362       //
   1363       Status = gIncompatiblePciDeviceSupport->CheckDevice (
   1364                                                 gIncompatiblePciDeviceSupport,
   1365                                                 PciIoDevice->Pci.Hdr.VendorId,
   1366                                                 PciIoDevice->Pci.Hdr.DeviceId,
   1367                                                 PciIoDevice->Pci.Hdr.RevisionID,
   1368                                                 PciIoDevice->Pci.Device.SubsystemVendorID,
   1369                                                 PciIoDevice->Pci.Device.SubsystemID,
   1370                                                 &Configuration
   1371                                                 );
   1372 
   1373   }
   1374 
   1375   if (EFI_ERROR (Status) || Configuration == NULL ) {
   1376     return EFI_UNSUPPORTED;
   1377   }
   1378 
   1379   //
   1380   // Update PCI device information from the ACPI table
   1381   //
   1382   Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
   1383 
   1384   while (Ptr->Desc != ACPI_END_TAG_DESCRIPTOR) {
   1385 
   1386     if (Ptr->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
   1387       //
   1388       // The format is not support
   1389       //
   1390       break;
   1391     }
   1392 
   1393     BarIndex    = (UINTN) Ptr->AddrTranslationOffset;
   1394     BarEndIndex = BarIndex;
   1395 
   1396     //
   1397     // Update all the bars in the device
   1398     //
   1399     if (BarIndex == PCI_BAR_ALL) {
   1400       BarIndex    = 0;
   1401       BarEndIndex = PCI_MAX_BAR - 1;
   1402     }
   1403 
   1404     if (BarIndex > PCI_MAX_BAR) {
   1405       Ptr++;
   1406       continue;
   1407     }
   1408 
   1409     for (; BarIndex <= BarEndIndex; BarIndex++) {
   1410       SetFlag = FALSE;
   1411       switch (Ptr->ResType) {
   1412       case ACPI_ADDRESS_SPACE_TYPE_MEM:
   1413 
   1414         //
   1415         // Make sure the bar is memory type
   1416         //
   1417         if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeMem)) {
   1418           SetFlag = TRUE;
   1419 
   1420           //
   1421           // Ignored if granularity is 0.
   1422           // Ignored if PCI BAR is I/O or 32-bit memory.
   1423           // If PCI BAR is 64-bit memory and granularity is 32, then
   1424           // the PCI BAR resource is allocated below 4GB.
   1425           // If PCI BAR is 64-bit memory and granularity is 64, then
   1426           // the PCI BAR resource is allocated above 4GB.
   1427           //
   1428           if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeMem64) {
   1429             switch (Ptr->AddrSpaceGranularity) {
   1430             case 32:
   1431               PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;
   1432             case 64:
   1433               PciIoDevice->PciBar[BarIndex].BarTypeFixed = TRUE;
   1434               break;
   1435             default:
   1436               break;
   1437             }
   1438           }
   1439 
   1440           if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypePMem64) {
   1441             switch (Ptr->AddrSpaceGranularity) {
   1442             case 32:
   1443               PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;
   1444             case 64:
   1445               PciIoDevice->PciBar[BarIndex].BarTypeFixed = TRUE;
   1446               break;
   1447             default:
   1448               break;
   1449             }
   1450           }
   1451         }
   1452         break;
   1453 
   1454       case ACPI_ADDRESS_SPACE_TYPE_IO:
   1455 
   1456         //
   1457         // Make sure the bar is IO type
   1458         //
   1459         if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeIo)) {
   1460           SetFlag = TRUE;
   1461         }
   1462         break;
   1463       }
   1464 
   1465       if (SetFlag) {
   1466 
   1467         //
   1468         // Update the new alignment for the device
   1469         //
   1470         SetNewAlign (&(PciIoDevice->PciBar[BarIndex].Alignment), Ptr->AddrRangeMax);
   1471 
   1472         //
   1473         // Update the new length for the device
   1474         //
   1475         if (Ptr->AddrLen != PCI_BAR_NOCHANGE) {
   1476           PciIoDevice->PciBar[BarIndex].Length = Ptr->AddrLen;
   1477         }
   1478       }
   1479     }
   1480 
   1481     Ptr++;
   1482   }
   1483 
   1484   FreePool (Configuration);
   1485 
   1486   return EFI_SUCCESS;
   1487 }
   1488 
   1489 /**
   1490   This routine will update the alignment with the new alignment.
   1491 
   1492   @param Alignment    Input Old alignment. Output updated alignment.
   1493   @param NewAlignment New alignment.
   1494 
   1495 **/
   1496 VOID
   1497 SetNewAlign (
   1498   IN OUT UINT64     *Alignment,
   1499   IN     UINT64     NewAlignment
   1500   )
   1501 {
   1502   UINT64  OldAlignment;
   1503   UINTN   ShiftBit;
   1504 
   1505   //
   1506   // The new alignment is the same as the original,
   1507   // so skip it
   1508   //
   1509   if (NewAlignment == PCI_BAR_OLD_ALIGN) {
   1510     return ;
   1511   }
   1512   //
   1513   // Check the validity of the parameter
   1514   //
   1515    if (NewAlignment != PCI_BAR_EVEN_ALIGN  &&
   1516        NewAlignment != PCI_BAR_SQUAD_ALIGN &&
   1517        NewAlignment != PCI_BAR_DQUAD_ALIGN ) {
   1518     *Alignment = NewAlignment;
   1519     return ;
   1520   }
   1521 
   1522   OldAlignment  = (*Alignment) + 1;
   1523   ShiftBit      = 0;
   1524 
   1525   //
   1526   // Get the first non-zero hex value of the length
   1527   //
   1528   while ((OldAlignment & 0x0F) == 0x00) {
   1529     OldAlignment = RShiftU64 (OldAlignment, 4);
   1530     ShiftBit += 4;
   1531   }
   1532 
   1533   //
   1534   // Adjust the alignment to even, quad or double quad boundary
   1535   //
   1536   if (NewAlignment == PCI_BAR_EVEN_ALIGN) {
   1537     if ((OldAlignment & 0x01) != 0) {
   1538       OldAlignment = OldAlignment + 2 - (OldAlignment & 0x01);
   1539     }
   1540   } else if (NewAlignment == PCI_BAR_SQUAD_ALIGN) {
   1541     if ((OldAlignment & 0x03) != 0) {
   1542       OldAlignment = OldAlignment + 4 - (OldAlignment & 0x03);
   1543     }
   1544   } else if (NewAlignment == PCI_BAR_DQUAD_ALIGN) {
   1545     if ((OldAlignment & 0x07) != 0) {
   1546       OldAlignment = OldAlignment + 8 - (OldAlignment & 0x07);
   1547     }
   1548   }
   1549 
   1550   //
   1551   // Update the old value
   1552   //
   1553   NewAlignment  = LShiftU64 (OldAlignment, ShiftBit) - 1;
   1554   *Alignment    = NewAlignment;
   1555 
   1556   return ;
   1557 }
   1558 
   1559 /**
   1560   Parse PCI IOV VF bar information and fill them into PCI device instance.
   1561 
   1562   @param PciIoDevice  Pci device instance.
   1563   @param Offset       Bar offset.
   1564   @param BarIndex     Bar index.
   1565 
   1566   @return Next bar offset.
   1567 
   1568 **/
   1569 UINTN
   1570 PciIovParseVfBar (
   1571   IN PCI_IO_DEVICE  *PciIoDevice,
   1572   IN UINTN          Offset,
   1573   IN UINTN          BarIndex
   1574   )
   1575 {
   1576   UINT32      Value;
   1577   UINT32      OriginalValue;
   1578   UINT32      Mask;
   1579   EFI_STATUS  Status;
   1580 
   1581   //
   1582   // Ensure it is called properly
   1583   //
   1584   ASSERT (PciIoDevice->SrIovCapabilityOffset != 0);
   1585   if (PciIoDevice->SrIovCapabilityOffset == 0) {
   1586     return 0;
   1587   }
   1588 
   1589   OriginalValue = 0;
   1590   Value         = 0;
   1591 
   1592   Status = VfBarExisted (
   1593             PciIoDevice,
   1594             Offset,
   1595             &Value,
   1596             &OriginalValue
   1597             );
   1598 
   1599   if (EFI_ERROR (Status)) {
   1600     PciIoDevice->VfPciBar[BarIndex].BaseAddress = 0;
   1601     PciIoDevice->VfPciBar[BarIndex].Length      = 0;
   1602     PciIoDevice->VfPciBar[BarIndex].Alignment   = 0;
   1603 
   1604     //
   1605     // Scan all the BARs anyway
   1606     //
   1607     PciIoDevice->VfPciBar[BarIndex].Offset = (UINT16) Offset;
   1608     return Offset + 4;
   1609   }
   1610 
   1611   PciIoDevice->VfPciBar[BarIndex].Offset = (UINT16) Offset;
   1612   if ((Value & 0x01) != 0) {
   1613     //
   1614     // Device I/Os. Impossible
   1615     //
   1616     ASSERT (FALSE);
   1617     return Offset + 4;
   1618 
   1619   } else {
   1620 
   1621     Mask  = 0xfffffff0;
   1622 
   1623     PciIoDevice->VfPciBar[BarIndex].BaseAddress = OriginalValue & Mask;
   1624 
   1625     switch (Value & 0x07) {
   1626 
   1627     //
   1628     //memory space; anywhere in 32 bit address space
   1629     //
   1630     case 0x00:
   1631       if ((Value & 0x08) != 0) {
   1632         PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem32;
   1633       } else {
   1634         PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem32;
   1635       }
   1636 
   1637       PciIoDevice->VfPciBar[BarIndex].Length    = (~(Value & Mask)) + 1;
   1638       PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;
   1639 
   1640       //
   1641       // Adjust Length
   1642       //
   1643       PciIoDevice->VfPciBar[BarIndex].Length = MultU64x32 (PciIoDevice->VfPciBar[BarIndex].Length, PciIoDevice->InitialVFs);
   1644       //
   1645       // Adjust Alignment
   1646       //
   1647       if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {
   1648         PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;
   1649       }
   1650 
   1651       break;
   1652 
   1653     //
   1654     // memory space; anywhere in 64 bit address space
   1655     //
   1656     case 0x04:
   1657       if ((Value & 0x08) != 0) {
   1658         PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem64;
   1659       } else {
   1660         PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem64;
   1661       }
   1662 
   1663       //
   1664       // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
   1665       // is regarded as an extension for the first bar. As a result
   1666       // the sizing will be conducted on combined 64 bit value
   1667       // Here just store the masked first 32bit value for future size
   1668       // calculation
   1669       //
   1670       PciIoDevice->VfPciBar[BarIndex].Length    = Value & Mask;
   1671       PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;
   1672 
   1673       if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {
   1674         PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;
   1675       }
   1676 
   1677       //
   1678       // Increment the offset to point to next DWORD
   1679       //
   1680       Offset += 4;
   1681 
   1682       Status = VfBarExisted (
   1683                 PciIoDevice,
   1684                 Offset,
   1685                 &Value,
   1686                 &OriginalValue
   1687                 );
   1688 
   1689       if (EFI_ERROR (Status)) {
   1690         return Offset + 4;
   1691       }
   1692 
   1693       //
   1694       // Fix the length to support some spefic 64 bit BAR
   1695       //
   1696       Value |= ((UINT32) -1 << HighBitSet32 (Value));
   1697 
   1698       //
   1699       // Calculate the size of 64bit bar
   1700       //
   1701       PciIoDevice->VfPciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);
   1702 
   1703       PciIoDevice->VfPciBar[BarIndex].Length    = PciIoDevice->VfPciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);
   1704       PciIoDevice->VfPciBar[BarIndex].Length    = (~(PciIoDevice->VfPciBar[BarIndex].Length)) + 1;
   1705       PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;
   1706 
   1707       //
   1708       // Adjust Length
   1709       //
   1710       PciIoDevice->VfPciBar[BarIndex].Length = MultU64x32 (PciIoDevice->VfPciBar[BarIndex].Length, PciIoDevice->InitialVFs);
   1711       //
   1712       // Adjust Alignment
   1713       //
   1714       if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {
   1715         PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;
   1716       }
   1717 
   1718       break;
   1719 
   1720     //
   1721     // reserved
   1722     //
   1723     default:
   1724       PciIoDevice->VfPciBar[BarIndex].BarType   = PciBarTypeUnknown;
   1725       PciIoDevice->VfPciBar[BarIndex].Length    = (~(Value & Mask)) + 1;
   1726       PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;
   1727 
   1728       if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {
   1729         PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;
   1730       }
   1731 
   1732       break;
   1733     }
   1734   }
   1735 
   1736   //
   1737   // Check the length again so as to keep compatible with some special bars
   1738   //
   1739   if (PciIoDevice->VfPciBar[BarIndex].Length == 0) {
   1740     PciIoDevice->VfPciBar[BarIndex].BarType     = PciBarTypeUnknown;
   1741     PciIoDevice->VfPciBar[BarIndex].BaseAddress = 0;
   1742     PciIoDevice->VfPciBar[BarIndex].Alignment   = 0;
   1743   }
   1744 
   1745   //
   1746   // Increment number of bar
   1747   //
   1748   return Offset + 4;
   1749 }
   1750 
   1751 /**
   1752   Parse PCI bar information and fill them into PCI device instance.
   1753 
   1754   @param PciIoDevice  Pci device instance.
   1755   @param Offset       Bar offset.
   1756   @param BarIndex     Bar index.
   1757 
   1758   @return Next bar offset.
   1759 
   1760 **/
   1761 UINTN
   1762 PciParseBar (
   1763   IN PCI_IO_DEVICE  *PciIoDevice,
   1764   IN UINTN          Offset,
   1765   IN UINTN          BarIndex
   1766   )
   1767 {
   1768   UINT32      Value;
   1769   UINT32      OriginalValue;
   1770   UINT32      Mask;
   1771   EFI_STATUS  Status;
   1772 
   1773   OriginalValue = 0;
   1774   Value         = 0;
   1775 
   1776   Status = BarExisted (
   1777              PciIoDevice,
   1778              Offset,
   1779              &Value,
   1780              &OriginalValue
   1781              );
   1782 
   1783   if (EFI_ERROR (Status)) {
   1784     PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
   1785     PciIoDevice->PciBar[BarIndex].Length      = 0;
   1786     PciIoDevice->PciBar[BarIndex].Alignment   = 0;
   1787 
   1788     //
   1789     // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
   1790     //
   1791     PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
   1792     return Offset + 4;
   1793   }
   1794 
   1795   PciIoDevice->PciBar[BarIndex].BarTypeFixed = FALSE;
   1796   PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
   1797   if ((Value & 0x01) != 0) {
   1798     //
   1799     // Device I/Os
   1800     //
   1801     Mask = 0xfffffffc;
   1802 
   1803     if ((Value & 0xFFFF0000) != 0) {
   1804       //
   1805       // It is a IO32 bar
   1806       //
   1807       PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeIo32;
   1808       PciIoDevice->PciBar[BarIndex].Length    = ((~(Value & Mask)) + 1);
   1809       PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
   1810 
   1811     } else {
   1812       //
   1813       // It is a IO16 bar
   1814       //
   1815       PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeIo16;
   1816       PciIoDevice->PciBar[BarIndex].Length    = 0x0000FFFF & ((~(Value & Mask)) + 1);
   1817       PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
   1818 
   1819     }
   1820     //
   1821     // Workaround. Some platforms inplement IO bar with 0 length
   1822     // Need to treat it as no-bar
   1823     //
   1824     if (PciIoDevice->PciBar[BarIndex].Length == 0) {
   1825       PciIoDevice->PciBar[BarIndex].BarType = (PCI_BAR_TYPE) 0;
   1826     }
   1827 
   1828     PciIoDevice->PciBar[BarIndex].BaseAddress   = OriginalValue & Mask;
   1829 
   1830   } else {
   1831 
   1832     Mask  = 0xfffffff0;
   1833 
   1834     PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
   1835 
   1836     switch (Value & 0x07) {
   1837 
   1838     //
   1839     //memory space; anywhere in 32 bit address space
   1840     //
   1841     case 0x00:
   1842       if ((Value & 0x08) != 0) {
   1843         PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;
   1844       } else {
   1845         PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;
   1846       }
   1847 
   1848       PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;
   1849       if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {
   1850         //
   1851         // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
   1852         //
   1853         PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);
   1854       } else {
   1855         PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
   1856       }
   1857       break;
   1858 
   1859     //
   1860     // memory space; anywhere in 64 bit address space
   1861     //
   1862     case 0x04:
   1863       if ((Value & 0x08) != 0) {
   1864         PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;
   1865       } else {
   1866         PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;
   1867       }
   1868 
   1869       //
   1870       // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
   1871       // is regarded as an extension for the first bar. As a result
   1872       // the sizing will be conducted on combined 64 bit value
   1873       // Here just store the masked first 32bit value for future size
   1874       // calculation
   1875       //
   1876       PciIoDevice->PciBar[BarIndex].Length    = Value & Mask;
   1877       PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
   1878 
   1879       //
   1880       // Increment the offset to point to next DWORD
   1881       //
   1882       Offset += 4;
   1883 
   1884       Status = BarExisted (
   1885                  PciIoDevice,
   1886                  Offset,
   1887                  &Value,
   1888                  &OriginalValue
   1889                  );
   1890 
   1891       if (EFI_ERROR (Status)) {
   1892         //
   1893         // the high 32 bit does not claim any BAR, we need to re-check the low 32 bit BAR again
   1894         //
   1895         if (PciIoDevice->PciBar[BarIndex].Length == 0) {
   1896           //
   1897           // some device implement MMIO bar with 0 length, need to treat it as no-bar
   1898           //
   1899           PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
   1900           return Offset + 4;
   1901         }
   1902       }
   1903 
   1904       //
   1905       // Fix the length to support some spefic 64 bit BAR
   1906       //
   1907       if (Value == 0) {
   1908         DEBUG ((EFI_D_INFO, "[PciBus]BAR probing for upper 32bit of MEM64 BAR returns 0, change to 0xFFFFFFFF.\n"));
   1909         Value = (UINT32) -1;
   1910       } else {
   1911         Value |= ((UINT32)(-1) << HighBitSet32 (Value));
   1912       }
   1913 
   1914       //
   1915       // Calculate the size of 64bit bar
   1916       //
   1917       PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);
   1918 
   1919       PciIoDevice->PciBar[BarIndex].Length    = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);
   1920       PciIoDevice->PciBar[BarIndex].Length    = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;
   1921       if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {
   1922         //
   1923         // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
   1924         //
   1925         PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);
   1926       } else {
   1927         PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
   1928       }
   1929 
   1930       break;
   1931 
   1932     //
   1933     // reserved
   1934     //
   1935     default:
   1936       PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeUnknown;
   1937       PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;
   1938       if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {
   1939         //
   1940         // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
   1941         //
   1942         PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);
   1943       } else {
   1944         PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
   1945       }
   1946       break;
   1947     }
   1948   }
   1949 
   1950   //
   1951   // Check the length again so as to keep compatible with some special bars
   1952   //
   1953   if (PciIoDevice->PciBar[BarIndex].Length == 0) {
   1954     PciIoDevice->PciBar[BarIndex].BarType     = PciBarTypeUnknown;
   1955     PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
   1956     PciIoDevice->PciBar[BarIndex].Alignment   = 0;
   1957   }
   1958 
   1959   //
   1960   // Increment number of bar
   1961   //
   1962   return Offset + 4;
   1963 }
   1964 
   1965 /**
   1966   This routine is used to initialize the bar of a PCI device.
   1967 
   1968   @param PciIoDevice Pci device instance.
   1969 
   1970   @note It can be called typically when a device is going to be rejected.
   1971 
   1972 **/
   1973 VOID
   1974 InitializePciDevice (
   1975   IN PCI_IO_DEVICE    *PciIoDevice
   1976   )
   1977 {
   1978   EFI_PCI_IO_PROTOCOL *PciIo;
   1979   UINT8               Offset;
   1980 
   1981   PciIo = &(PciIoDevice->PciIo);
   1982 
   1983   //
   1984   // Put all the resource apertures
   1985   // Resource base is set to all ones so as to indicate its resource
   1986   // has not been alloacted
   1987   //
   1988   for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {
   1989     PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllOne);
   1990   }
   1991 }
   1992 
   1993 /**
   1994   This routine is used to initialize the bar of a PCI-PCI Bridge device.
   1995 
   1996   @param  PciIoDevice PCI-PCI bridge device instance.
   1997 
   1998 **/
   1999 VOID
   2000 InitializePpb (
   2001   IN PCI_IO_DEVICE    *PciIoDevice
   2002   )
   2003 {
   2004   EFI_PCI_IO_PROTOCOL *PciIo;
   2005 
   2006   PciIo = &(PciIoDevice->PciIo);
   2007 
   2008   //
   2009   // Put all the resource apertures including IO16
   2010   // Io32, pMem32, pMem64 to quiescent state
   2011   // Resource base all ones, Resource limit all zeros
   2012   //
   2013   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
   2014   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero);
   2015 
   2016   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne);
   2017   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero);
   2018 
   2019   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne);
   2020   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero);
   2021 
   2022   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne);
   2023   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero);
   2024 
   2025   //
   2026   // Don't support use io32 as for now
   2027   //
   2028   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne);
   2029   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero);
   2030 
   2031   //
   2032   // Force Interrupt line to zero for cards that come up randomly
   2033   //
   2034   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);
   2035 }
   2036 
   2037 /**
   2038   This routine is used to initialize the bar of a PCI Card Bridge device.
   2039 
   2040   @param PciIoDevice  PCI Card bridge device.
   2041 
   2042 **/
   2043 VOID
   2044 InitializeP2C (
   2045   IN PCI_IO_DEVICE    *PciIoDevice
   2046   )
   2047 {
   2048   EFI_PCI_IO_PROTOCOL *PciIo;
   2049 
   2050   PciIo = &(PciIoDevice->PciIo);
   2051 
   2052   //
   2053   // Put all the resource apertures including IO16
   2054   // Io32, pMem32, pMem64 to quiescent state(
   2055   // Resource base all ones, Resource limit all zeros
   2056   //
   2057   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne);
   2058   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero);
   2059 
   2060   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne);
   2061   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero);
   2062 
   2063   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne);
   2064   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero);
   2065 
   2066   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne);
   2067   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero);
   2068 
   2069   //
   2070   // Force Interrupt line to zero for cards that come up randomly
   2071   //
   2072   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);
   2073 }
   2074 
   2075 /**
   2076   Create and initiliaze general PCI I/O device instance for
   2077   PCI device/bridge device/hotplug bridge device.
   2078 
   2079   @param PciRootBridgeIo   Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
   2080   @param Pci               Input Pci information block.
   2081   @param Bus               Device Bus NO.
   2082   @param Device            Device device NO.
   2083   @param Func              Device func NO.
   2084 
   2085   @return Instance of PCI device. NULL means no instance created.
   2086 
   2087 **/
   2088 PCI_IO_DEVICE *
   2089 CreatePciIoDevice (
   2090   IN PCI_IO_DEVICE                    *Bridge,
   2091   IN PCI_TYPE00                       *Pci,
   2092   IN UINT8                            Bus,
   2093   IN UINT8                            Device,
   2094   IN UINT8                            Func
   2095   )
   2096 {
   2097   PCI_IO_DEVICE        *PciIoDevice;
   2098   EFI_PCI_IO_PROTOCOL  *PciIo;
   2099   EFI_STATUS           Status;
   2100 
   2101   PciIoDevice = AllocateZeroPool (sizeof (PCI_IO_DEVICE));
   2102   if (PciIoDevice == NULL) {
   2103     return NULL;
   2104   }
   2105 
   2106   PciIoDevice->Signature        = PCI_IO_DEVICE_SIGNATURE;
   2107   PciIoDevice->Handle           = NULL;
   2108   PciIoDevice->PciRootBridgeIo  = Bridge->PciRootBridgeIo;
   2109   PciIoDevice->DevicePath       = NULL;
   2110   PciIoDevice->BusNumber        = Bus;
   2111   PciIoDevice->DeviceNumber     = Device;
   2112   PciIoDevice->FunctionNumber   = Func;
   2113   PciIoDevice->Decodes          = 0;
   2114 
   2115   if (gFullEnumeration) {
   2116     PciIoDevice->Allocated = FALSE;
   2117   } else {
   2118     PciIoDevice->Allocated = TRUE;
   2119   }
   2120 
   2121   PciIoDevice->Registered         = FALSE;
   2122   PciIoDevice->Attributes         = 0;
   2123   PciIoDevice->Supports           = 0;
   2124   PciIoDevice->BusOverride        = FALSE;
   2125   PciIoDevice->AllOpRomProcessed  = FALSE;
   2126 
   2127   PciIoDevice->IsPciExp           = FALSE;
   2128 
   2129   CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01));
   2130 
   2131   //
   2132   // Initialize the PCI I/O instance structure
   2133   //
   2134   InitializePciIoInstance (PciIoDevice);
   2135   InitializePciDriverOverrideInstance (PciIoDevice);
   2136   InitializePciLoadFile2 (PciIoDevice);
   2137   PciIo = &PciIoDevice->PciIo;
   2138 
   2139   //
   2140   // Create a device path for this PCI device and store it into its private data
   2141   //
   2142   CreatePciDevicePath (
   2143     Bridge->DevicePath,
   2144     PciIoDevice
   2145     );
   2146 
   2147   //
   2148   // Detect if PCI Express Device
   2149   //
   2150   PciIoDevice->PciExpressCapabilityOffset = 0;
   2151   Status = LocateCapabilityRegBlock (
   2152              PciIoDevice,
   2153              EFI_PCI_CAPABILITY_ID_PCIEXP,
   2154              &PciIoDevice->PciExpressCapabilityOffset,
   2155              NULL
   2156              );
   2157   if (!EFI_ERROR (Status)) {
   2158     PciIoDevice->IsPciExp = TRUE;
   2159   }
   2160 
   2161   if (PcdGetBool (PcdAriSupport)) {
   2162     //
   2163     // Check if the device is an ARI device.
   2164     //
   2165     Status = LocatePciExpressCapabilityRegBlock (
   2166                PciIoDevice,
   2167                EFI_PCIE_CAPABILITY_ID_ARI,
   2168                &PciIoDevice->AriCapabilityOffset,
   2169                NULL
   2170                );
   2171     if (!EFI_ERROR (Status)) {
   2172       //
   2173       // We need to enable ARI feature before calculate BusReservation,
   2174       // because FirstVFOffset and VFStride may change after that.
   2175       //
   2176       EFI_PCI_IO_PROTOCOL  *ParentPciIo;
   2177       UINT32               Data32;
   2178 
   2179       //
   2180       // Check if its parent supports ARI forwarding.
   2181       //
   2182       ParentPciIo = &Bridge->PciIo;
   2183       ParentPciIo->Pci.Read (
   2184                           ParentPciIo,
   2185                           EfiPciIoWidthUint32,
   2186                           Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET,
   2187                           1,
   2188                           &Data32
   2189                           );
   2190       if ((Data32 & EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_ARI_FORWARDING) != 0) {
   2191         //
   2192         // ARI forward support in bridge, so enable it.
   2193         //
   2194         ParentPciIo->Pci.Read (
   2195                             ParentPciIo,
   2196                             EfiPciIoWidthUint32,
   2197                             Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET,
   2198                             1,
   2199                             &Data32
   2200                             );
   2201         if ((Data32 & EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING) == 0) {
   2202           Data32 |= EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING;
   2203           ParentPciIo->Pci.Write (
   2204                               ParentPciIo,
   2205                               EfiPciIoWidthUint32,
   2206                               Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET,
   2207                               1,
   2208                               &Data32
   2209                               );
   2210           DEBUG ((
   2211             EFI_D_INFO,
   2212             " ARI: forwarding enabled for PPB[%02x:%02x:%02x]\n",
   2213             Bridge->BusNumber,
   2214             Bridge->DeviceNumber,
   2215             Bridge->FunctionNumber
   2216             ));
   2217         }
   2218       }
   2219 
   2220       DEBUG ((EFI_D_INFO, " ARI: CapOffset = 0x%x\n", PciIoDevice->AriCapabilityOffset));
   2221     }
   2222   }
   2223 
   2224   //
   2225   // Initialization for SR-IOV
   2226   //
   2227 
   2228   if (PcdGetBool (PcdSrIovSupport)) {
   2229     Status = LocatePciExpressCapabilityRegBlock (
   2230                PciIoDevice,
   2231                EFI_PCIE_CAPABILITY_ID_SRIOV,
   2232                &PciIoDevice->SrIovCapabilityOffset,
   2233                NULL
   2234                );
   2235     if (!EFI_ERROR (Status)) {
   2236       UINT32    SupportedPageSize;
   2237       UINT16    VFStride;
   2238       UINT16    FirstVFOffset;
   2239       UINT16    Data16;
   2240       UINT32    PFRid;
   2241       UINT32    LastVF;
   2242 
   2243       //
   2244       // If the SR-IOV device is an ARI device, then Set ARI Capable Hierarchy for the device.
   2245       //
   2246       if (PcdGetBool (PcdAriSupport) && PciIoDevice->AriCapabilityOffset != 0) {
   2247         PciIo->Pci.Read (
   2248                      PciIo,
   2249                      EfiPciIoWidthUint16,
   2250                      PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL,
   2251                      1,
   2252                      &Data16
   2253                      );
   2254         Data16 |= EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL_ARI_HIERARCHY;
   2255         PciIo->Pci.Write (
   2256                      PciIo,
   2257                      EfiPciIoWidthUint16,
   2258                      PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL,
   2259                      1,
   2260                      &Data16
   2261                      );
   2262       }
   2263 
   2264       //
   2265       // Calculate SystemPageSize
   2266       //
   2267 
   2268       PciIo->Pci.Read (
   2269                    PciIo,
   2270                    EfiPciIoWidthUint32,
   2271                    PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SUPPORTED_PAGE_SIZE,
   2272                    1,
   2273                    &SupportedPageSize
   2274                    );
   2275       PciIoDevice->SystemPageSize = (PcdGet32 (PcdSrIovSystemPageSize) & SupportedPageSize);
   2276       ASSERT (PciIoDevice->SystemPageSize != 0);
   2277 
   2278       PciIo->Pci.Write (
   2279                    PciIo,
   2280                    EfiPciIoWidthUint32,
   2281                    PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SYSTEM_PAGE_SIZE,
   2282                    1,
   2283                    &PciIoDevice->SystemPageSize
   2284                    );
   2285       //
   2286       // Adjust SystemPageSize for Alignment usage later
   2287       //
   2288       PciIoDevice->SystemPageSize <<= 12;
   2289 
   2290       //
   2291       // Calculate BusReservation for PCI IOV
   2292       //
   2293 
   2294       //
   2295       // Read First FirstVFOffset, InitialVFs, and VFStride
   2296       //
   2297       PciIo->Pci.Read (
   2298                    PciIo,
   2299                    EfiPciIoWidthUint16,
   2300                    PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_FIRSTVF,
   2301                    1,
   2302                    &FirstVFOffset
   2303                    );
   2304       PciIo->Pci.Read (
   2305                    PciIo,
   2306                    EfiPciIoWidthUint16,
   2307                    PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_INITIALVFS,
   2308                    1,
   2309                    &PciIoDevice->InitialVFs
   2310                    );
   2311       PciIo->Pci.Read (
   2312                    PciIo,
   2313                    EfiPciIoWidthUint16,
   2314                    PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_VFSTRIDE,
   2315                    1,
   2316                    &VFStride
   2317                    );
   2318       //
   2319       // Calculate LastVF
   2320       //
   2321       PFRid = EFI_PCI_RID(Bus, Device, Func);
   2322       LastVF = PFRid + FirstVFOffset + (PciIoDevice->InitialVFs - 1) * VFStride;
   2323 
   2324       //
   2325       // Calculate ReservedBusNum for this PF
   2326       //
   2327       PciIoDevice->ReservedBusNum = (UINT16)(EFI_PCI_BUS_OF_RID (LastVF) - Bus + 1);
   2328 
   2329       DEBUG ((
   2330         EFI_D_INFO,
   2331         " SR-IOV: SupportedPageSize = 0x%x; SystemPageSize = 0x%x; FirstVFOffset = 0x%x;\n",
   2332         SupportedPageSize, PciIoDevice->SystemPageSize >> 12, FirstVFOffset
   2333         ));
   2334       DEBUG ((
   2335         EFI_D_INFO,
   2336         "         InitialVFs = 0x%x; ReservedBusNum = 0x%x; CapOffset = 0x%x\n",
   2337         PciIoDevice->InitialVFs, PciIoDevice->ReservedBusNum, PciIoDevice->SrIovCapabilityOffset
   2338         ));
   2339     }
   2340   }
   2341 
   2342   if (PcdGetBool (PcdMrIovSupport)) {
   2343     Status = LocatePciExpressCapabilityRegBlock (
   2344                PciIoDevice,
   2345                EFI_PCIE_CAPABILITY_ID_MRIOV,
   2346                &PciIoDevice->MrIovCapabilityOffset,
   2347                NULL
   2348                );
   2349     if (!EFI_ERROR (Status)) {
   2350       DEBUG ((EFI_D_INFO, " MR-IOV: CapOffset = 0x%x\n", PciIoDevice->MrIovCapabilityOffset));
   2351     }
   2352   }
   2353 
   2354   //
   2355   // Initialize the reserved resource list
   2356   //
   2357   InitializeListHead (&PciIoDevice->ReservedResourceList);
   2358 
   2359   //
   2360   // Initialize the driver list
   2361   //
   2362   InitializeListHead (&PciIoDevice->OptionRomDriverList);
   2363 
   2364   //
   2365   // Initialize the child list
   2366   //
   2367   InitializeListHead (&PciIoDevice->ChildList);
   2368 
   2369   return PciIoDevice;
   2370 }
   2371 
   2372 /**
   2373   This routine is used to enumerate entire pci bus system
   2374   in a given platform.
   2375 
   2376   It is only called on the second start on the same Root Bridge.
   2377 
   2378   @param  Controller     Parent bridge handler.
   2379 
   2380   @retval EFI_SUCCESS    PCI enumeration finished successfully.
   2381   @retval other          Some error occurred when enumerating the pci bus system.
   2382 
   2383 **/
   2384 EFI_STATUS
   2385 PciEnumeratorLight (
   2386   IN EFI_HANDLE                    Controller
   2387   )
   2388 {
   2389 
   2390   EFI_STATUS                        Status;
   2391   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   *PciRootBridgeIo;
   2392   PCI_IO_DEVICE                     *RootBridgeDev;
   2393   UINT16                            MinBus;
   2394   UINT16                            MaxBus;
   2395   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
   2396 
   2397   MinBus      = 0;
   2398   MaxBus      = PCI_MAX_BUS;
   2399   Descriptors = NULL;
   2400 
   2401   //
   2402   // If this root bridge has been already enumerated, then return successfully
   2403   //
   2404   if (GetRootBridgeByHandle (Controller) != NULL) {
   2405     return EFI_SUCCESS;
   2406   }
   2407 
   2408   //
   2409   // Open pci root bridge io protocol
   2410   //
   2411   Status = gBS->OpenProtocol (
   2412                   Controller,
   2413                   &gEfiPciRootBridgeIoProtocolGuid,
   2414                   (VOID **) &PciRootBridgeIo,
   2415                   gPciBusDriverBinding.DriverBindingHandle,
   2416                   Controller,
   2417                   EFI_OPEN_PROTOCOL_BY_DRIVER
   2418                   );
   2419   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
   2420     return Status;
   2421   }
   2422 
   2423   Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
   2424 
   2425   if (EFI_ERROR (Status)) {
   2426     return Status;
   2427   }
   2428 
   2429   while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) {
   2430 
   2431     //
   2432     // Create a device node for root bridge device with a NULL host bridge controller handle
   2433     //
   2434     RootBridgeDev = CreateRootBridge (Controller);
   2435 
   2436     if (RootBridgeDev == NULL) {
   2437       Descriptors++;
   2438       continue;
   2439     }
   2440 
   2441     //
   2442     // Record the root bridgeio protocol
   2443     //
   2444     RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;
   2445 
   2446     Status = PciPciDeviceInfoCollector (
   2447                RootBridgeDev,
   2448                (UINT8) MinBus
   2449                );
   2450 
   2451     if (!EFI_ERROR (Status)) {
   2452 
   2453       //
   2454       // Remove those PCI devices which are rejected when full enumeration
   2455       //
   2456       RemoveRejectedPciDevices (RootBridgeDev->Handle, RootBridgeDev);
   2457 
   2458       //
   2459       // Process option rom light
   2460       //
   2461       ProcessOptionRomLight (RootBridgeDev);
   2462 
   2463       //
   2464       // Determine attributes for all devices under this root bridge
   2465       //
   2466       DetermineDeviceAttribute (RootBridgeDev);
   2467 
   2468       //
   2469       // If successfully, insert the node into device pool
   2470       //
   2471       InsertRootBridge (RootBridgeDev);
   2472     } else {
   2473 
   2474       //
   2475       // If unsuccessly, destroy the entire node
   2476       //
   2477       DestroyRootBridge (RootBridgeDev);
   2478     }
   2479 
   2480     Descriptors++;
   2481   }
   2482 
   2483   return EFI_SUCCESS;
   2484 }
   2485 
   2486 /**
   2487   Get bus range from PCI resource descriptor list.
   2488 
   2489   @param Descriptors  A pointer to the address space descriptor.
   2490   @param MinBus       The min bus returned.
   2491   @param MaxBus       The max bus returned.
   2492   @param BusRange     The bus range returned.
   2493 
   2494   @retval EFI_SUCCESS    Successfully got bus range.
   2495   @retval EFI_NOT_FOUND  Can not find the specific bus.
   2496 
   2497 **/
   2498 EFI_STATUS
   2499 PciGetBusRange (
   2500   IN     EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  **Descriptors,
   2501   OUT    UINT16                             *MinBus,
   2502   OUT    UINT16                             *MaxBus,
   2503   OUT    UINT16                             *BusRange
   2504   )
   2505 {
   2506   while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {
   2507     if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
   2508       if (MinBus != NULL) {
   2509         *MinBus = (UINT16) (*Descriptors)->AddrRangeMin;
   2510       }
   2511 
   2512       if (MaxBus != NULL) {
   2513         *MaxBus = (UINT16) (*Descriptors)->AddrRangeMax;
   2514       }
   2515 
   2516       if (BusRange != NULL) {
   2517         *BusRange = (UINT16) (*Descriptors)->AddrLen;
   2518       }
   2519 
   2520       return EFI_SUCCESS;
   2521     }
   2522 
   2523     (*Descriptors)++;
   2524   }
   2525 
   2526   return EFI_NOT_FOUND;
   2527 }
   2528 
   2529 /**
   2530   This routine can be used to start the root bridge.
   2531 
   2532   @param RootBridgeDev     Pci device instance.
   2533 
   2534   @retval EFI_SUCCESS      This device started.
   2535   @retval other            Failed to get PCI Root Bridge I/O protocol.
   2536 
   2537 **/
   2538 EFI_STATUS
   2539 StartManagingRootBridge (
   2540   IN PCI_IO_DEVICE *RootBridgeDev
   2541   )
   2542 {
   2543   EFI_HANDLE                      RootBridgeHandle;
   2544   EFI_STATUS                      Status;
   2545   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
   2546 
   2547   //
   2548   // Get the root bridge handle
   2549   //
   2550   RootBridgeHandle = RootBridgeDev->Handle;
   2551   PciRootBridgeIo  = NULL;
   2552 
   2553   //
   2554   // Get the pci root bridge io protocol
   2555   //
   2556   Status = gBS->OpenProtocol (
   2557                   RootBridgeHandle,
   2558                   &gEfiPciRootBridgeIoProtocolGuid,
   2559                   (VOID **) &PciRootBridgeIo,
   2560                   gPciBusDriverBinding.DriverBindingHandle,
   2561                   RootBridgeHandle,
   2562                   EFI_OPEN_PROTOCOL_BY_DRIVER
   2563                   );
   2564 
   2565   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
   2566     return Status;
   2567   }
   2568 
   2569   //
   2570   // Store the PciRootBridgeIo protocol into root bridge private data
   2571   //
   2572   RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;
   2573 
   2574   return EFI_SUCCESS;
   2575 
   2576 }
   2577 
   2578 /**
   2579   This routine can be used to check whether a PCI device should be rejected when light enumeration.
   2580 
   2581   @param PciIoDevice  Pci device instance.
   2582 
   2583   @retval TRUE      This device should be rejected.
   2584   @retval FALSE     This device shouldn't be rejected.
   2585 
   2586 **/
   2587 BOOLEAN
   2588 IsPciDeviceRejected (
   2589   IN PCI_IO_DEVICE *PciIoDevice
   2590   )
   2591 {
   2592   EFI_STATUS  Status;
   2593   UINT32      TestValue;
   2594   UINT32      OldValue;
   2595   UINT32      Mask;
   2596   UINT8       BarOffset;
   2597 
   2598   //
   2599   // PPB should be skip!
   2600   //
   2601   if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
   2602     return FALSE;
   2603   }
   2604 
   2605   if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
   2606     //
   2607     // Only test base registers for P2C
   2608     //
   2609     for (BarOffset = 0x1C; BarOffset <= 0x38; BarOffset += 2 * sizeof (UINT32)) {
   2610 
   2611       Mask    = (BarOffset < 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;
   2612       Status  = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
   2613       if (EFI_ERROR (Status)) {
   2614         continue;
   2615       }
   2616 
   2617       TestValue = TestValue & Mask;
   2618       if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
   2619         //
   2620         // The bar isn't programed, so it should be rejected
   2621         //
   2622         return TRUE;
   2623       }
   2624     }
   2625 
   2626     return FALSE;
   2627   }
   2628 
   2629   for (BarOffset = 0x14; BarOffset <= 0x24; BarOffset += sizeof (UINT32)) {
   2630     //
   2631     // Test PCI devices
   2632     //
   2633     Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
   2634     if (EFI_ERROR (Status)) {
   2635       continue;
   2636     }
   2637 
   2638     if ((TestValue & 0x01) != 0) {
   2639 
   2640       //
   2641       // IO Bar
   2642       //
   2643       Mask      = 0xFFFFFFFC;
   2644       TestValue = TestValue & Mask;
   2645       if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
   2646         return TRUE;
   2647       }
   2648 
   2649     } else {
   2650 
   2651       //
   2652       // Mem Bar
   2653       //
   2654       Mask      = 0xFFFFFFF0;
   2655       TestValue = TestValue & Mask;
   2656 
   2657       if ((TestValue & 0x07) == 0x04) {
   2658 
   2659         //
   2660         // Mem64 or PMem64
   2661         //
   2662         BarOffset += sizeof (UINT32);
   2663         if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
   2664 
   2665           //
   2666           // Test its high 32-Bit BAR
   2667           //
   2668           Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
   2669           if (TestValue == OldValue) {
   2670             return TRUE;
   2671           }
   2672         }
   2673 
   2674       } else {
   2675 
   2676         //
   2677         // Mem32 or PMem32
   2678         //
   2679         if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
   2680           return TRUE;
   2681         }
   2682       }
   2683     }
   2684   }
   2685 
   2686   return FALSE;
   2687 }
   2688 
   2689 /**
   2690   Reset all bus number from specific bridge.
   2691 
   2692   @param Bridge           Parent specific bridge.
   2693   @param StartBusNumber   Start bus number.
   2694 
   2695 **/
   2696 VOID
   2697 ResetAllPpbBusNumber (
   2698   IN PCI_IO_DEVICE                      *Bridge,
   2699   IN UINT8                              StartBusNumber
   2700   )
   2701 {
   2702   EFI_STATUS                      Status;
   2703   PCI_TYPE00                      Pci;
   2704   UINT8                           Device;
   2705   UINT32                          Register;
   2706   UINT8                           Func;
   2707   UINT64                          Address;
   2708   UINT8                           SecondaryBus;
   2709   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
   2710 
   2711   PciRootBridgeIo = Bridge->PciRootBridgeIo;
   2712 
   2713   for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
   2714     for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
   2715 
   2716       //
   2717       // Check to see whether a pci device is present
   2718       //
   2719       Status = PciDevicePresent (
   2720                  PciRootBridgeIo,
   2721                  &Pci,
   2722                  StartBusNumber,
   2723                  Device,
   2724                  Func
   2725                  );
   2726 
   2727       if (EFI_ERROR (Status) && Func == 0) {
   2728         //
   2729         // go to next device if there is no Function 0
   2730         //
   2731         break;
   2732       }
   2733 
   2734       if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci))) {
   2735 
   2736         Register  = 0;
   2737         Address   = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
   2738         Status    = PciRootBridgeIo->Pci.Read (
   2739                                            PciRootBridgeIo,
   2740                                            EfiPciWidthUint32,
   2741                                            Address,
   2742                                            1,
   2743                                            &Register
   2744                                            );
   2745         SecondaryBus = (UINT8)(Register >> 8);
   2746 
   2747         if (SecondaryBus != 0) {
   2748           ResetAllPpbBusNumber (Bridge, SecondaryBus);
   2749         }
   2750 
   2751         //
   2752         // Reset register 18h, 19h, 1Ah on PCI Bridge
   2753         //
   2754         Register &= 0xFF000000;
   2755         Status = PciRootBridgeIo->Pci.Write (
   2756                                         PciRootBridgeIo,
   2757                                         EfiPciWidthUint32,
   2758                                         Address,
   2759                                         1,
   2760                                         &Register
   2761                                         );
   2762       }
   2763 
   2764       if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
   2765         //
   2766         // Skip sub functions, this is not a multi function device
   2767         //
   2768         Func = PCI_MAX_FUNC;
   2769       }
   2770     }
   2771   }
   2772 }
   2773 
   2774