Home | History | Annotate | Download | only in PciBusNoEnumerationDxe
      1 /*++
      2 
      3 Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved.<BR>
      4 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 Module Name:
     14 
     15   PciEnumeratorSupport.c
     16 
     17 Abstract:
     18 
     19   PCI Bus Driver
     20 
     21 Revision History
     22 
     23 --*/
     24 
     25 #include "PciBus.h"
     26 
     27 EFI_STATUS
     28 InitializePPB (
     29   IN PCI_IO_DEVICE *PciIoDevice
     30 );
     31 
     32 EFI_STATUS
     33 InitializeP2C (
     34   IN PCI_IO_DEVICE *PciIoDevice
     35 );
     36 
     37 PCI_IO_DEVICE*
     38 CreatePciIoDevice (
     39   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
     40   IN PCI_TYPE00                       *Pci,
     41   UINT8                               Bus,
     42   UINT8                               Device,
     43   UINT8                               Func
     44 );
     45 
     46 
     47 PCI_IO_DEVICE*
     48 GatherP2CInfo (
     49   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
     50   IN PCI_TYPE00                       *Pci,
     51   UINT8                               Bus,
     52   UINT8                               Device,
     53   UINT8                               Func
     54 );
     55 
     56 UINTN
     57 PciParseBar (
     58   IN PCI_IO_DEVICE  *PciIoDevice,
     59   IN UINTN          Offset,
     60   IN UINTN          BarIndex
     61 );
     62 
     63 
     64 EFI_STATUS
     65 PciSearchDevice (
     66   IN PCI_IO_DEVICE                      *Bridge,
     67   PCI_TYPE00                            *Pci,
     68   UINT8                                 Bus,
     69   UINT8                                 Device,
     70   UINT8                                 Func,
     71   PCI_IO_DEVICE                         **PciDevice
     72 );
     73 
     74 
     75 EFI_STATUS
     76 DetermineDeviceAttribute (
     77   IN PCI_IO_DEVICE                      *PciIoDevice
     78 );
     79 
     80 EFI_STATUS
     81 BarExisted (
     82   IN PCI_IO_DEVICE *PciIoDevice,
     83   IN UINTN         Offset,
     84   OUT UINT32       *BarLengthValue,
     85   OUT UINT32       *OriginalBarValue
     86   );
     87 
     88 
     89 
     90 EFI_DEVICE_PATH_PROTOCOL*
     91 CreatePciDevicePath(
     92   IN  EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
     93   IN  PCI_IO_DEVICE            *PciIoDevice
     94 );
     95 
     96 PCI_IO_DEVICE*
     97 GatherDeviceInfo (
     98   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
     99   IN PCI_TYPE00                       *Pci,
    100   UINT8                               Bus,
    101   UINT8                               Device,
    102   UINT8                               Func
    103 );
    104 
    105 PCI_IO_DEVICE*
    106 GatherPPBInfo (
    107   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
    108   IN PCI_TYPE00                       *Pci,
    109   UINT8                               Bus,
    110   UINT8                               Device,
    111   UINT8                               Func
    112 );
    113 
    114 EFI_STATUS
    115 PciDevicePresent (
    116   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
    117   PCI_TYPE00                          *Pci,
    118   UINT8                               Bus,
    119   UINT8                               Device,
    120   UINT8                               Func
    121   )
    122 /*++
    123 
    124 Routine Description:
    125 
    126   This routine is used to check whether the pci device is present
    127 
    128 Arguments:
    129 
    130 Returns:
    131 
    132   None
    133 
    134 --*/
    135 {
    136   UINT64      Address;
    137   EFI_STATUS  Status;
    138 
    139   //
    140   // Create PCI address map in terms of Bus, Device and Func
    141   //
    142   Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
    143 
    144   //
    145   // Read the Vendor Id register
    146   //
    147   Status = PciRootBridgeIo->Pci.Read (
    148                                   PciRootBridgeIo,
    149                                   EfiPciWidthUint32,
    150                                   Address,
    151                                   1,
    152                                   Pci
    153                                   );
    154 
    155   if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) {
    156 
    157     //
    158     // Read the entire config header for the device
    159     //
    160 
    161     Status = PciRootBridgeIo->Pci.Read (
    162                                     PciRootBridgeIo,
    163                                     EfiPciWidthUint32,
    164                                     Address,
    165                                     sizeof (PCI_TYPE00) / sizeof (UINT32),
    166                                     Pci
    167                                     );
    168 
    169     return EFI_SUCCESS;
    170   }
    171 
    172   return EFI_NOT_FOUND;
    173 }
    174 
    175 EFI_STATUS
    176 PciPciDeviceInfoCollector (
    177   IN PCI_IO_DEVICE                      *Bridge,
    178   UINT8                                 StartBusNumber
    179   )
    180 /*++
    181 
    182 Routine Description:
    183 
    184 Arguments:
    185 
    186 Returns:
    187 
    188   None
    189 
    190 --*/
    191 {
    192   EFI_STATUS          Status;
    193   PCI_TYPE00          Pci;
    194   UINT8               Device;
    195   UINT8               Func;
    196   UINT8               SecBus;
    197   PCI_IO_DEVICE       *PciIoDevice;
    198   EFI_PCI_IO_PROTOCOL *PciIo;
    199 
    200   Status      = EFI_SUCCESS;
    201   SecBus      = 0;
    202   PciIoDevice = NULL;
    203 
    204   for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
    205 
    206     for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
    207 
    208       //
    209       // Check to see whether PCI device is present
    210       //
    211 
    212       Status = PciDevicePresent (
    213                 Bridge->PciRootBridgeIo,
    214                 &Pci,
    215                 (UINT8) StartBusNumber,
    216                 (UINT8) Device,
    217                 (UINT8) Func
    218                 );
    219 
    220       if (EFI_ERROR (Status) && Func == 0) {
    221         //
    222         // go to next device if there is no Function 0
    223         //
    224         break;
    225       }
    226 
    227       if (!EFI_ERROR (Status)) {
    228 
    229         //
    230         // Collect all the information about the PCI device discovered
    231         //
    232         Status = PciSearchDevice (
    233                   Bridge,
    234                   &Pci,
    235                   (UINT8) StartBusNumber,
    236                   Device,
    237                   Func,
    238                   &PciIoDevice
    239                   );
    240 
    241         //
    242         // Recursively scan PCI busses on the other side of PCI-PCI bridges
    243         //
    244         //
    245 
    246         if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {
    247 
    248           //
    249           // If it is PPB, we need to get the secondary bus to continue the enumeration
    250           //
    251           PciIo   = &(PciIoDevice->PciIo);
    252 
    253           Status  = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, 1, &SecBus);
    254 
    255           if (EFI_ERROR (Status)) {
    256             return Status;
    257           }
    258 
    259           //
    260           // Deep enumerate the next level bus
    261           //
    262           Status = PciPciDeviceInfoCollector (
    263                     PciIoDevice,
    264                     (UINT8) (SecBus)
    265                     );
    266 
    267         }
    268 
    269         if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
    270 
    271           //
    272           // Skip sub functions, this is not a multi function device
    273           //
    274           Func = PCI_MAX_FUNC;
    275         }
    276       }
    277 
    278     }
    279   }
    280 
    281   return EFI_SUCCESS;
    282 }
    283 
    284 EFI_STATUS
    285 PciSearchDevice (
    286   IN  PCI_IO_DEVICE                         *Bridge,
    287   IN  PCI_TYPE00                            *Pci,
    288   IN  UINT8                                 Bus,
    289   IN  UINT8                                 Device,
    290   IN  UINT8                                 Func,
    291   OUT PCI_IO_DEVICE                         **PciDevice
    292   )
    293 /*++
    294 
    295 Routine Description:
    296 
    297   Search required device.
    298 
    299 Arguments:
    300 
    301   Bridge     - A pointer to the PCI_IO_DEVICE.
    302   Pci        - A pointer to the PCI_TYPE00.
    303   Bus        - Bus number.
    304   Device     - Device number.
    305   Func       - Function number.
    306   PciDevice  - The Required pci device.
    307 
    308 Returns:
    309 
    310   Status code.
    311 
    312 --*/
    313 {
    314   PCI_IO_DEVICE *PciIoDevice;
    315 
    316   PciIoDevice = NULL;
    317 
    318   if (!IS_PCI_BRIDGE (Pci)) {
    319 
    320     if (IS_CARDBUS_BRIDGE (Pci)) {
    321       PciIoDevice = GatherP2CInfo (
    322                       Bridge->PciRootBridgeIo,
    323                       Pci,
    324                       Bus,
    325                       Device,
    326                       Func
    327                       );
    328       if ((PciIoDevice != NULL) && (gFullEnumeration == TRUE)) {
    329         InitializeP2C (PciIoDevice);
    330       }
    331     } else {
    332 
    333       //
    334       // Create private data for Pci Device
    335       //
    336       PciIoDevice = GatherDeviceInfo (
    337                       Bridge->PciRootBridgeIo,
    338                       Pci,
    339                       Bus,
    340                       Device,
    341                       Func
    342                       );
    343 
    344     }
    345 
    346   } else {
    347 
    348     //
    349     // Create private data for PPB
    350     //
    351     PciIoDevice = GatherPPBInfo (
    352                     Bridge->PciRootBridgeIo,
    353                     Pci,
    354                     Bus,
    355                     Device,
    356                     Func
    357                     );
    358 
    359     //
    360     // Special initialization for PPB including making the PPB quiet
    361     //
    362     if ((PciIoDevice != NULL) && (gFullEnumeration == TRUE)) {
    363       InitializePPB (PciIoDevice);
    364     }
    365   }
    366 
    367   if (!PciIoDevice) {
    368     return EFI_OUT_OF_RESOURCES;
    369   }
    370 
    371   //
    372   // Create a device path for this PCI device and store it into its private data
    373   //
    374   CreatePciDevicePath(
    375     Bridge->DevicePath,
    376     PciIoDevice
    377     );
    378 
    379   //
    380   // Detect this function has option rom
    381   //
    382   if (gFullEnumeration) {
    383 
    384     if (!IS_CARDBUS_BRIDGE (Pci)) {
    385 
    386       GetOpRomInfo (PciIoDevice);
    387 
    388     }
    389 
    390     ResetPowerManagementFeature (PciIoDevice);
    391 
    392   }
    393   else {
    394     PciRomGetRomResourceFromPciOptionRomTable (
    395       &gPciBusDriverBinding,
    396       PciIoDevice->PciRootBridgeIo,
    397       PciIoDevice
    398       );
    399   }
    400 
    401 
    402   //
    403   // Insert it into a global tree for future reference
    404   //
    405   InsertPciDevice (Bridge, PciIoDevice);
    406 
    407   //
    408   // Determine PCI device attributes
    409   //
    410   DetermineDeviceAttribute (PciIoDevice);
    411 
    412   if (PciDevice != NULL) {
    413     *PciDevice = PciIoDevice;
    414   }
    415 
    416   return EFI_SUCCESS;
    417 }
    418 
    419 PCI_IO_DEVICE *
    420 GatherDeviceInfo (
    421   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
    422   IN PCI_TYPE00                       *Pci,
    423   UINT8                               Bus,
    424   UINT8                               Device,
    425   UINT8                               Func
    426   )
    427 /*++
    428 
    429 Routine Description:
    430 
    431 Arguments:
    432 
    433 Returns:
    434 
    435   None
    436 
    437 --*/
    438 {
    439   UINTN                           Offset;
    440   UINTN                           BarIndex;
    441   PCI_IO_DEVICE                   *PciIoDevice;
    442 
    443   PciIoDevice = CreatePciIoDevice (
    444                   PciRootBridgeIo,
    445                   Pci,
    446                   Bus,
    447                   Device,
    448                   Func
    449                   );
    450 
    451   if (!PciIoDevice) {
    452     return NULL;
    453   }
    454 
    455   //
    456   // If it is a full enumeration, disconnect the device in advance
    457   //
    458   if (gFullEnumeration) {
    459 
    460     PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
    461 
    462   }
    463 
    464   //
    465   // Start to parse the bars
    466   //
    467   for (Offset = 0x10, BarIndex = 0; Offset <= 0x24; BarIndex++) {
    468     Offset = PciParseBar (PciIoDevice, Offset, BarIndex);
    469   }
    470 
    471   return PciIoDevice;
    472 }
    473 
    474 PCI_IO_DEVICE *
    475 GatherPPBInfo (
    476   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
    477   IN PCI_TYPE00                       *Pci,
    478   UINT8                               Bus,
    479   UINT8                               Device,
    480   UINT8                               Func
    481   )
    482 /*++
    483 
    484 Routine Description:
    485 
    486 Arguments:
    487 
    488 Returns:
    489 
    490   None
    491 
    492 --*/
    493 {
    494   PCI_IO_DEVICE                   *PciIoDevice;
    495   EFI_STATUS                      Status;
    496   UINT8                           Value;
    497   EFI_PCI_IO_PROTOCOL             *PciIo;
    498   UINT8                           Temp;
    499 
    500   PciIoDevice = CreatePciIoDevice (
    501                   PciRootBridgeIo,
    502                   Pci,
    503                   Bus,
    504                   Device,
    505                   Func
    506                   );
    507 
    508   if (!PciIoDevice) {
    509     return NULL;
    510   }
    511 
    512   if (gFullEnumeration) {
    513     PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
    514 
    515     //
    516     // Initalize the bridge control register
    517     //
    518     PciDisableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED);
    519   }
    520 
    521   PciIo = &PciIoDevice->PciIo;
    522 
    523   //
    524   // Test whether it support 32 decode or not
    525   //
    526   PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
    527   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
    528   PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
    529   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
    530 
    531   if (Value) {
    532     if (Value & 0x01) {
    533       PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED;
    534     } else {
    535       PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
    536     }
    537   }
    538 
    539   Status = BarExisted (
    540             PciIoDevice,
    541             0x24,
    542             NULL,
    543             NULL
    544             );
    545 
    546   //
    547   // test if it supports 64 memory or not
    548   //
    549   if (!EFI_ERROR (Status)) {
    550 
    551     Status = BarExisted (
    552               PciIoDevice,
    553               0x28,
    554               NULL,
    555               NULL
    556               );
    557 
    558     if (!EFI_ERROR (Status)) {
    559       PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
    560       PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;
    561     } else {
    562       PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
    563     }
    564   }
    565 
    566   //
    567   // Memory 32 code is required for ppb
    568   //
    569   PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
    570 
    571   return PciIoDevice;
    572 }
    573 
    574 PCI_IO_DEVICE *
    575 GatherP2CInfo (
    576   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
    577   IN PCI_TYPE00                       *Pci,
    578   UINT8                               Bus,
    579   UINT8                               Device,
    580   UINT8                               Func
    581   )
    582 /*++
    583 
    584 Routine Description:
    585 
    586 Arguments:
    587 
    588 Returns:
    589 
    590   None
    591 
    592 --*/
    593 {
    594   PCI_IO_DEVICE         *PciIoDevice;
    595 
    596   PciIoDevice = CreatePciIoDevice (
    597                   PciRootBridgeIo,
    598                   Pci,
    599                   Bus,
    600                   Device,
    601                   Func
    602                   );
    603 
    604   if (!PciIoDevice) {
    605     return NULL;
    606   }
    607 
    608   if (gFullEnumeration) {
    609     PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
    610 
    611     //
    612     // Initalize the bridge control register
    613     //
    614     PciDisableBridgeControlRegister (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED);
    615 
    616   }
    617   //
    618   // P2C only has one bar that is in 0x10
    619   //
    620   PciParseBar(PciIoDevice, 0x10, 0);
    621 
    622   PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED  |
    623                          EFI_BRIDGE_PMEM32_DECODE_SUPPORTED |
    624                          EFI_BRIDGE_IO32_DECODE_SUPPORTED;
    625 
    626   return PciIoDevice;
    627 }
    628 
    629 EFI_DEVICE_PATH_PROTOCOL *
    630 CreatePciDevicePath (
    631   IN  EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
    632   IN  PCI_IO_DEVICE            *PciIoDevice
    633   )
    634 /*++
    635 
    636 Routine Description:
    637 
    638 Arguments:
    639 
    640 Returns:
    641 
    642   None
    643 
    644 --*/
    645 {
    646 
    647   PCI_DEVICE_PATH PciNode;
    648 
    649   //
    650   // Create PCI device path
    651   //
    652   PciNode.Header.Type     = HARDWARE_DEVICE_PATH;
    653   PciNode.Header.SubType  = HW_PCI_DP;
    654   SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
    655 
    656   PciNode.Device          = PciIoDevice->DeviceNumber;
    657   PciNode.Function        = PciIoDevice->FunctionNumber;
    658   PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header);
    659 
    660   return PciIoDevice->DevicePath;
    661 }
    662 
    663 EFI_STATUS
    664 BarExisted (
    665   IN PCI_IO_DEVICE *PciIoDevice,
    666   IN UINTN         Offset,
    667   OUT UINT32       *BarLengthValue,
    668   OUT UINT32       *OriginalBarValue
    669   )
    670 /*++
    671 
    672 Routine Description:
    673 
    674   Check the bar is existed or not.
    675 
    676 Arguments:
    677 
    678   PciIoDevice       - A pointer to the PCI_IO_DEVICE.
    679   Offset            - The offset.
    680   BarLengthValue    - The bar length value.
    681   OriginalBarValue  - The original bar value.
    682 
    683 Returns:
    684 
    685   EFI_NOT_FOUND     - The bar don't exist.
    686   EFI_SUCCESS       - The bar exist.
    687 
    688 --*/
    689 {
    690   EFI_PCI_IO_PROTOCOL *PciIo;
    691   UINT32              OriginalValue;
    692   UINT32              Value;
    693   EFI_TPL             OldTpl;
    694 
    695   PciIo = &PciIoDevice->PciIo;
    696 
    697   //
    698   // Preserve the original value
    699   //
    700 
    701   PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);
    702 
    703   //
    704   // Raise TPL to high level to disable timer interrupt while the BAR is probed
    705   //
    706   OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
    707 
    708   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOne);
    709   PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value);
    710 
    711   //
    712   // Write back the original value
    713   //
    714   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);
    715 
    716   //
    717   // Restore TPL to its original level
    718   //
    719   gBS->RestoreTPL (OldTpl);
    720 
    721   if (BarLengthValue != NULL) {
    722     *BarLengthValue = Value;
    723   }
    724 
    725   if (OriginalBarValue != NULL) {
    726     *OriginalBarValue = OriginalValue;
    727   }
    728 
    729   if (Value == 0) {
    730     return EFI_NOT_FOUND;
    731   } else {
    732     return EFI_SUCCESS;
    733   }
    734 }
    735 
    736 
    737 EFI_STATUS
    738 DetermineDeviceAttribute (
    739   IN PCI_IO_DEVICE                      *PciIoDevice
    740   )
    741 /*++
    742 
    743 Routine Description:
    744 
    745   Determine the related attributes of all devices under a Root Bridge
    746 
    747 Arguments:
    748 
    749 Returns:
    750 
    751   None
    752 
    753 --*/
    754 {
    755   UINT16          Command;
    756   UINT16          BridgeControl;
    757 
    758   Command = 0;
    759 
    760   PciIoDevice->Supports |= EFI_PCI_DEVICE_ENABLE;
    761   PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
    762 
    763   if (IS_PCI_VGA (&(PciIoDevice->Pci))){
    764 
    765     //
    766     // If the device is VGA, VGA related Attributes are supported
    767     //
    768     PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO ;
    769     PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY   ;
    770     PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_IO    ;
    771   }
    772 
    773   if(IS_ISA_BRIDGE(&(PciIoDevice->Pci)) || IS_INTEL_ISA_BRIDGE(&(PciIoDevice->Pci))) {
    774     //
    775     // If the devie is a ISA Bridge, set the two attributes
    776     //
    777     PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;
    778     PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;
    779   }
    780 
    781   if (IS_PCI_GFX (&(PciIoDevice->Pci))) {
    782 
    783     //
    784     // If the device is GFX, then only set the EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
    785     // attribute
    786     //
    787     PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO    ;
    788   }
    789 
    790 
    791   //
    792   // If the device is IDE, IDE related attributes are supported
    793   //
    794   if (IS_PCI_IDE (&(PciIoDevice->Pci))) {
    795     PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO  ;
    796     PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO  ;
    797   }
    798 
    799   PciReadCommandRegister(PciIoDevice, &Command);
    800 
    801 
    802   if (Command & EFI_PCI_COMMAND_IO_SPACE) {
    803     PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_IO;
    804   }
    805 
    806   if (Command & EFI_PCI_COMMAND_MEMORY_SPACE) {
    807     PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY;
    808   }
    809 
    810   if (Command & EFI_PCI_COMMAND_BUS_MASTER) {
    811     PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;
    812   }
    813 
    814   if (IS_PCI_BRIDGE (&(PciIoDevice->Pci)) ||
    815       IS_CARDBUS_BRIDGE (&(PciIoDevice->Pci))){
    816 
    817     //
    818     // If it is a PPB, read the Bridge Control Register to determine
    819     // the relevant attributes
    820     //
    821     BridgeControl = 0;
    822     PciReadBridgeControlRegister(PciIoDevice, &BridgeControl);
    823 
    824     //
    825     // Determine whether the ISA bit is set
    826     // If ISA Enable on Bridge is set, the PPB
    827     // will block forwarding 0x100-0x3ff for each 1KB in the
    828     // first 64KB I/O range.
    829     //
    830     if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) != 0) {
    831       PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;
    832     }
    833 
    834     //
    835     // Determine whether the VGA bit is set
    836     // If it is set, the bridge is set to decode VGA memory range
    837     // and palette register range
    838     //
    839     if (IS_PCI_VGA (&(PciIoDevice->Pci)) &&BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) {
    840       PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;
    841       PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
    842       PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
    843     }
    844 
    845     //
    846     // if the palette snoop bit is set, then the brige is set to
    847     // decode palette IO write
    848     //
    849     if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) {
    850       PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
    851     }
    852   }
    853 
    854   return EFI_SUCCESS;
    855 }
    856 
    857 UINTN
    858 PciParseBar (
    859   IN PCI_IO_DEVICE  *PciIoDevice,
    860   IN UINTN          Offset,
    861   IN UINTN          BarIndex
    862   )
    863 /*++
    864 
    865 Routine Description:
    866 
    867 Arguments:
    868 
    869 Returns:
    870 
    871   None
    872 
    873 --*/
    874 {
    875   UINT32      Value;
    876   UINT32      OriginalValue;
    877   UINT32      Mask;
    878   EFI_STATUS  Status;
    879 
    880   OriginalValue = 0;
    881   Value         = 0;
    882 
    883   Status = BarExisted (
    884             PciIoDevice,
    885             Offset,
    886             &Value,
    887             &OriginalValue
    888             );
    889 
    890   if (EFI_ERROR (Status)) {
    891     PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
    892     PciIoDevice->PciBar[BarIndex].Length      = 0;
    893     PciIoDevice->PciBar[BarIndex].Alignment   = 0;
    894 
    895     //
    896     // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
    897     //
    898     PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
    899     return Offset + 4;
    900   }
    901 
    902   PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
    903   if (Value & 0x01) {
    904     //
    905     // Device I/Os
    906     //
    907     Mask = 0xfffffffc;
    908 
    909     if (Value & 0xFFFF0000) {
    910       //
    911       // It is a IO32 bar
    912       //
    913       PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeIo32;
    914       PciIoDevice->PciBar[BarIndex].Length    = ((~(Value & Mask)) + 1);
    915       PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
    916 
    917     } else {
    918       //
    919       // It is a IO16 bar
    920       //
    921       PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeIo16;
    922       PciIoDevice->PciBar[BarIndex].Length    = 0x0000FFFF & ((~(Value & Mask)) + 1);
    923       PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
    924 
    925     }
    926     //
    927     // Workaround. Some platforms inplement IO bar with 0 length
    928     // Need to treat it as no-bar
    929     //
    930     if (PciIoDevice->PciBar[BarIndex].Length == 0) {
    931       PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
    932     }
    933 
    934     PciIoDevice->PciBar[BarIndex].Prefetchable  = FALSE;
    935     PciIoDevice->PciBar[BarIndex].BaseAddress   = OriginalValue & Mask;
    936 
    937   } else {
    938 
    939     Mask  = 0xfffffff0;
    940 
    941     PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
    942 
    943     switch (Value & 0x07) {
    944 
    945     //
    946     //memory space; anywhere in 32 bit address space
    947     //
    948     case 0x00:
    949       if (Value & 0x08) {
    950         PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;
    951       } else {
    952         PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;
    953       }
    954 
    955       PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;
    956       PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
    957 
    958       break;
    959 
    960     //
    961     // memory space; anywhere in 64 bit address space
    962     //
    963     case 0x04:
    964       if (Value & 0x08) {
    965         PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;
    966       } else {
    967         PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;
    968       }
    969 
    970       //
    971       // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
    972       // is regarded as an extension for the first bar. As a result
    973       // the sizing will be conducted on combined 64 bit value
    974       // Here just store the masked first 32bit value for future size
    975       // calculation
    976       //
    977       PciIoDevice->PciBar[BarIndex].Length    = Value & Mask;
    978       PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
    979 
    980       //
    981       // Increment the offset to point to next DWORD
    982       //
    983       Offset += 4;
    984 
    985       Status = BarExisted (
    986                 PciIoDevice,
    987                 Offset,
    988                 &Value,
    989                 &OriginalValue
    990                 );
    991 
    992       if (EFI_ERROR (Status)) {
    993         return Offset + 4;
    994       }
    995 
    996       //
    997       // Fix the length to support some spefic 64 bit BAR
    998       //
    999       Value |= ((UINT32)(-1) << HighBitSet32 (Value));
   1000 
   1001       //
   1002       // Calculate the size of 64bit bar
   1003       //
   1004       PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);
   1005 
   1006       PciIoDevice->PciBar[BarIndex].Length    = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);
   1007       PciIoDevice->PciBar[BarIndex].Length    = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;
   1008       PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
   1009 
   1010       break;
   1011 
   1012     //
   1013     // reserved
   1014     //
   1015     default:
   1016       PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeUnknown;
   1017       PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;
   1018       PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
   1019 
   1020       break;
   1021     }
   1022   }
   1023 
   1024   //
   1025   // Check the length again so as to keep compatible with some special bars
   1026   //
   1027   if (PciIoDevice->PciBar[BarIndex].Length == 0) {
   1028     PciIoDevice->PciBar[BarIndex].BarType     = PciBarTypeUnknown;
   1029     PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
   1030     PciIoDevice->PciBar[BarIndex].Alignment   = 0;
   1031   }
   1032 
   1033   //
   1034   // Increment number of bar
   1035   //
   1036   return Offset + 4;
   1037 }
   1038 
   1039 EFI_STATUS
   1040 InitializePPB (
   1041   IN PCI_IO_DEVICE *PciIoDevice
   1042   )
   1043 /*++
   1044 
   1045 Routine Description:
   1046 
   1047 Arguments:
   1048 
   1049 Returns:
   1050 
   1051   None
   1052 
   1053 --*/
   1054 {
   1055   EFI_PCI_IO_PROTOCOL *PciIo;
   1056 
   1057   PciIo = &(PciIoDevice->PciIo);
   1058 
   1059   //
   1060   // Put all the resource apertures including IO16
   1061   // Io32, pMem32, pMem64 to quiescent state
   1062   // Resource base all ones, Resource limit all zeros
   1063   //
   1064   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
   1065   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero);
   1066 
   1067   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne);
   1068   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero);
   1069 
   1070   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne);
   1071   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero);
   1072 
   1073   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne);
   1074   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero);
   1075 
   1076   //
   1077   // don't support use io32 as for now
   1078   //
   1079   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne);
   1080   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero);
   1081 
   1082   return EFI_SUCCESS;
   1083 }
   1084 
   1085 EFI_STATUS
   1086 InitializeP2C (
   1087   IN PCI_IO_DEVICE *PciIoDevice
   1088   )
   1089 /*++
   1090 
   1091 Routine Description:
   1092 
   1093 Arguments:
   1094 
   1095 Returns:
   1096 
   1097   None
   1098 
   1099 --*/
   1100 {
   1101   EFI_PCI_IO_PROTOCOL *PciIo;
   1102 
   1103   PciIo = &(PciIoDevice->PciIo);
   1104 
   1105   //
   1106   // Put all the resource apertures including IO16
   1107   // Io32, pMem32, pMem64 to quiescent state(
   1108   // Resource base all ones, Resource limit all zeros
   1109   //
   1110   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne);
   1111   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero);
   1112 
   1113   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne);
   1114   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero);
   1115 
   1116   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne);
   1117   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero);
   1118 
   1119   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne);
   1120   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero);
   1121 
   1122   return EFI_SUCCESS;
   1123 }
   1124 
   1125 PCI_IO_DEVICE *
   1126 CreatePciIoDevice (
   1127   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
   1128   IN PCI_TYPE00                       *Pci,
   1129   UINT8                               Bus,
   1130   UINT8                               Device,
   1131   UINT8                               Func
   1132   )
   1133 /*++
   1134 
   1135 Routine Description:
   1136 
   1137 Arguments:
   1138 
   1139 Returns:
   1140 
   1141   None
   1142 
   1143 --*/
   1144 {
   1145 
   1146   EFI_STATUS    Status;
   1147   PCI_IO_DEVICE *PciIoDevice;
   1148 
   1149   PciIoDevice = NULL;
   1150 
   1151   Status = gBS->AllocatePool (
   1152                   EfiBootServicesData,
   1153                   sizeof (PCI_IO_DEVICE),
   1154                   (VOID **) &PciIoDevice
   1155                   );
   1156 
   1157   if (EFI_ERROR (Status)) {
   1158     return NULL;
   1159   }
   1160 
   1161   ZeroMem (PciIoDevice, sizeof (PCI_IO_DEVICE));
   1162 
   1163   PciIoDevice->Signature        = PCI_IO_DEVICE_SIGNATURE;
   1164   PciIoDevice->Handle           = NULL;
   1165   PciIoDevice->PciRootBridgeIo  = PciRootBridgeIo;
   1166   PciIoDevice->DevicePath       = NULL;
   1167   PciIoDevice->BusNumber        = Bus;
   1168   PciIoDevice->DeviceNumber     = Device;
   1169   PciIoDevice->FunctionNumber   = Func;
   1170   PciIoDevice->Decodes          = 0;
   1171   if (gFullEnumeration) {
   1172     PciIoDevice->Allocated = FALSE;
   1173   } else {
   1174     PciIoDevice->Allocated = TRUE;
   1175   }
   1176 
   1177   PciIoDevice->Attributes         = 0;
   1178   PciIoDevice->Supports           = 0;
   1179   PciIoDevice->BusOverride        = FALSE;
   1180   PciIoDevice->IsPciExp           = FALSE;
   1181 
   1182   CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01));
   1183 
   1184   //
   1185   // Initialize the PCI I/O instance structure
   1186   //
   1187 
   1188   Status  = InitializePciIoInstance (PciIoDevice);
   1189   Status  = InitializePciDriverOverrideInstance (PciIoDevice);
   1190 
   1191   if (EFI_ERROR (Status)) {
   1192     gBS->FreePool (PciIoDevice);
   1193     return NULL;
   1194   }
   1195 
   1196   //
   1197   // Initialize the reserved resource list
   1198   //
   1199   InitializeListHead (&PciIoDevice->ReservedResourceList);
   1200 
   1201   //
   1202   // Initialize the driver list
   1203   //
   1204   InitializeListHead (&PciIoDevice->OptionRomDriverList);
   1205 
   1206   //
   1207   // Initialize the child list
   1208   //
   1209   InitializeListHead (&PciIoDevice->ChildList);
   1210 
   1211   return PciIoDevice;
   1212 }
   1213 
   1214 EFI_STATUS
   1215 PciEnumeratorLight (
   1216   IN EFI_HANDLE                    Controller
   1217   )
   1218 /*++
   1219 
   1220 Routine Description:
   1221 
   1222   This routine is used to enumerate entire pci bus system
   1223   in a given platform
   1224 
   1225 Arguments:
   1226 
   1227 Returns:
   1228 
   1229   None
   1230 
   1231 --*/
   1232 {
   1233 
   1234   EFI_STATUS                        Status;
   1235   EFI_DEVICE_PATH_PROTOCOL          *ParentDevicePath;
   1236   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   *PciRootBridgeIo;
   1237   PCI_IO_DEVICE                     *RootBridgeDev;
   1238   UINT16                            MinBus;
   1239   UINT16                            MaxBus;
   1240   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
   1241 
   1242   MinBus      = 0;
   1243   MaxBus      = PCI_MAX_BUS;
   1244   Descriptors = NULL;
   1245 
   1246   //
   1247   // If this host bridge has been already enumerated, then return successfully
   1248   //
   1249   if (RootBridgeExisted (Controller)) {
   1250     return EFI_SUCCESS;
   1251   }
   1252 
   1253   //
   1254   // Open the IO Abstraction(s) needed to perform the supported test
   1255   //
   1256   Status = gBS->OpenProtocol (
   1257                   Controller      ,
   1258                   &gEfiDevicePathProtocolGuid,
   1259                   (VOID **)&ParentDevicePath,
   1260                   gPciBusDriverBinding.DriverBindingHandle,
   1261                   Controller,
   1262                   EFI_OPEN_PROTOCOL_BY_DRIVER
   1263                   );
   1264   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
   1265     return Status;
   1266   }
   1267 
   1268   //
   1269   // Open pci root bridge io protocol
   1270   //
   1271   Status = gBS->OpenProtocol (
   1272                   Controller,
   1273                   &gEfiPciRootBridgeIoProtocolGuid,
   1274                   (VOID **) &PciRootBridgeIo,
   1275                   gPciBusDriverBinding.DriverBindingHandle,
   1276                   Controller,
   1277                   EFI_OPEN_PROTOCOL_BY_DRIVER
   1278                   );
   1279   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
   1280     return Status;
   1281   }
   1282 
   1283   //
   1284   // Load all EFI Drivers from all PCI Option ROMs behind the PCI Root Bridge
   1285   //
   1286   Status = PciRomLoadEfiDriversFromOptionRomTable (&gPciBusDriverBinding, PciRootBridgeIo);
   1287 
   1288   Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
   1289 
   1290   if (EFI_ERROR (Status)) {
   1291     return Status;
   1292   }
   1293 
   1294   while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) {
   1295 
   1296     //
   1297     // Create a device node for root bridge device with a NULL host bridge controller handle
   1298     //
   1299     RootBridgeDev = CreateRootBridge (Controller);
   1300 
   1301     //
   1302     // Record the root bridge device path
   1303     //
   1304     RootBridgeDev->DevicePath = ParentDevicePath;
   1305 
   1306     //
   1307     // Record the root bridge io protocol
   1308     //
   1309     RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;
   1310 
   1311     Status = PciPciDeviceInfoCollector (
   1312               RootBridgeDev,
   1313               (UINT8) MinBus
   1314               );
   1315 
   1316     if (!EFI_ERROR (Status)) {
   1317 
   1318       //
   1319       // If successfully, insert the node into device pool
   1320       //
   1321       InsertRootBridge (RootBridgeDev);
   1322     } else {
   1323 
   1324       //
   1325       // If unsuccessly, destroy the entire node
   1326       //
   1327       DestroyRootBridge (RootBridgeDev);
   1328     }
   1329 
   1330     Descriptors++;
   1331   }
   1332 
   1333   return EFI_SUCCESS;
   1334 }
   1335 
   1336 EFI_STATUS
   1337 PciGetBusRange (
   1338   IN     EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  **Descriptors,
   1339   OUT    UINT16                             *MinBus,
   1340   OUT    UINT16                             *MaxBus,
   1341   OUT    UINT16                             *BusRange
   1342   )
   1343 /*++
   1344 
   1345 Routine Description:
   1346 
   1347   Get the bus range.
   1348 
   1349 Arguments:
   1350 
   1351   Descriptors     - A pointer to the address space descriptor.
   1352   MinBus          - The min bus.
   1353   MaxBus          - The max bus.
   1354   BusRange        - The bus range.
   1355 
   1356 Returns:
   1357 
   1358   Status Code.
   1359 
   1360 --*/
   1361 {
   1362 
   1363   while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {
   1364     if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
   1365       if (MinBus != NULL) {
   1366         *MinBus = (UINT16)(*Descriptors)->AddrRangeMin;
   1367       }
   1368 
   1369       if (MaxBus != NULL) {
   1370         *MaxBus = (UINT16)(*Descriptors)->AddrRangeMax;
   1371       }
   1372 
   1373       if (BusRange != NULL) {
   1374         *BusRange = (UINT16)(*Descriptors)->AddrLen;
   1375       }
   1376       return EFI_SUCCESS;
   1377     }
   1378 
   1379     (*Descriptors)++;
   1380   }
   1381 
   1382   return EFI_NOT_FOUND;
   1383 }
   1384 
   1385