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