Home | History | Annotate | Download | only in PciBusNoEnumerationDxe
      1 /*++
      2 
      3 Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved.<BR>
      4 This program and the accompanying materials
      5 are licensed and made available under the terms and conditions of the BSD License
      6 which accompanies this distribution.  The full text of the license may be found at
      7 http://opensource.org/licenses/bsd-license.php
      8 
      9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12 Module Name:
     13 
     14   PciIo.c
     15 
     16 Abstract:
     17 
     18   PCI I/O Abstraction Driver
     19 
     20 Revision History
     21 
     22 --*/
     23 
     24 #include "PciBus.h"
     25 
     26 //
     27 // PCI I/O Support Function Prototypes
     28 //
     29 //
     30 
     31 BOOLEAN
     32 PciDevicesOnTheSamePath (
     33   IN PCI_IO_DEVICE       *PciDevice1,
     34   IN PCI_IO_DEVICE       *PciDevice2
     35 );
     36 
     37 
     38 EFI_STATUS
     39 UpStreamBridgesAttributes (
     40   IN  PCI_IO_DEVICE                            *PciIoDevice,
     41   IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,
     42   IN  UINT64                                   Attributes
     43 );
     44 
     45 
     46 BOOLEAN
     47 CheckBarType (
     48   IN PCI_IO_DEVICE  *PciIoDevice,
     49   UINT8             BarIndex,
     50   PCI_BAR_TYPE      BarType
     51 );
     52 
     53 
     54 EFI_STATUS
     55 SetBootVGA (
     56   IN  PCI_IO_DEVICE                  *PciIoDevice
     57 );
     58 
     59 EFI_STATUS
     60 DisableBootVGA (
     61   IN  PCI_IO_DEVICE                  *PciIoDevice
     62 );
     63 
     64 
     65 EFI_STATUS
     66 PciIoVerifyBarAccess (
     67   PCI_IO_DEVICE                 *PciIoDevice,
     68   UINT8                         BarIndex,
     69   PCI_BAR_TYPE                  Type,
     70   IN EFI_PCI_IO_PROTOCOL_WIDTH  Width,
     71   IN UINTN                      Count,
     72   UINT64                        *Offset
     73 );
     74 
     75 EFI_STATUS
     76 PciIoVerifyConfigAccess (
     77   PCI_IO_DEVICE                 *PciIoDevice,
     78   IN EFI_PCI_IO_PROTOCOL_WIDTH  Width,
     79   IN UINTN                      Count,
     80   IN UINT64                     *Offset
     81 );
     82 
     83 EFI_STATUS
     84 EFIAPI
     85 PciIoPollMem (
     86   IN  EFI_PCI_IO_PROTOCOL        *This,
     87   IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,
     88   IN  UINT8                      BarIndex,
     89   IN  UINT64                     Offset,
     90   IN  UINT64                     Mask,
     91   IN  UINT64                     Value,
     92   IN  UINT64                     Delay,
     93   OUT UINT64                     *Result
     94 );
     95 
     96 EFI_STATUS
     97 EFIAPI
     98 PciIoPollIo (
     99   IN  EFI_PCI_IO_PROTOCOL        *This,
    100   IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,
    101   IN  UINT8                      BarIndex,
    102   IN  UINT64                     Offset,
    103   IN  UINT64                     Mask,
    104   IN  UINT64                     Value,
    105   IN  UINT64                     Delay,
    106   OUT UINT64                     *Result
    107 );
    108 
    109 EFI_STATUS
    110 EFIAPI
    111 PciIoMemRead (
    112   IN     EFI_PCI_IO_PROTOCOL        *This,
    113   IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
    114   IN     UINT8                      BarIndex,
    115   IN     UINT64                     Offset,
    116   IN     UINTN                      Count,
    117   IN OUT VOID                       *Buffer
    118 );
    119 
    120 EFI_STATUS
    121 EFIAPI
    122 PciIoMemWrite (
    123   IN     EFI_PCI_IO_PROTOCOL        *This,
    124   IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
    125   IN     UINT8                      BarIndex,
    126   IN     UINT64                     Offset,
    127   IN     UINTN                      Count,
    128   IN OUT VOID                       *Buffer
    129 );
    130 
    131 EFI_STATUS
    132 EFIAPI
    133 PciIoIoRead (
    134   IN     EFI_PCI_IO_PROTOCOL        *This,
    135   IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
    136   IN     UINT8                      BarIndex,
    137   IN     UINT64                     Offset,
    138   IN     UINTN                      Count,
    139   IN OUT VOID                       *Buffer
    140 );
    141 
    142 EFI_STATUS
    143 EFIAPI
    144 PciIoIoWrite (
    145   IN     EFI_PCI_IO_PROTOCOL        *This,
    146   IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
    147   IN     UINT8                      BarIndex,
    148   IN     UINT64                     Offset,
    149   IN     UINTN                      Count,
    150   IN OUT VOID                       *Buffer
    151 );
    152 
    153 EFI_STATUS
    154 EFIAPI
    155 PciIoConfigRead (
    156   IN     EFI_PCI_IO_PROTOCOL        *This,
    157   IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
    158   IN     UINT32                     Offset,
    159   IN     UINTN                      Count,
    160   IN OUT VOID                       *Buffer
    161 );
    162 
    163 EFI_STATUS
    164 EFIAPI
    165 PciIoConfigWrite (
    166   IN     EFI_PCI_IO_PROTOCOL        *This,
    167   IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
    168   IN     UINT32                     Offset,
    169   IN     UINTN                      Count,
    170   IN OUT VOID                       *Buffer
    171 );
    172 
    173 EFI_STATUS
    174 EFIAPI
    175 PciIoCopyMem (
    176   IN     EFI_PCI_IO_PROTOCOL  *This,
    177   IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,
    178   IN     UINT8                        DestBarIndex,
    179   IN     UINT64                       DestOffset,
    180   IN     UINT8                        SrcBarIndex,
    181   IN     UINT64                       SrcOffset,
    182   IN     UINTN                        Count
    183 );
    184 
    185 EFI_STATUS
    186 EFIAPI
    187 PciIoMap (
    188   IN     EFI_PCI_IO_PROTOCOL            *This,
    189   IN     EFI_PCI_IO_PROTOCOL_OPERATION  Operation,
    190   IN     VOID                           *HostAddress,
    191   IN OUT UINTN                          *NumberOfBytes,
    192   OUT    EFI_PHYSICAL_ADDRESS           *DeviceAddress,
    193   OUT    VOID                           **Mapping
    194 );
    195 
    196 EFI_STATUS
    197 EFIAPI
    198 PciIoUnmap (
    199   IN  EFI_PCI_IO_PROTOCOL  *This,
    200   IN  VOID                 *Mapping
    201 );
    202 
    203 EFI_STATUS
    204 EFIAPI
    205 PciIoAllocateBuffer (
    206   IN  EFI_PCI_IO_PROTOCOL    *This,
    207   IN  EFI_ALLOCATE_TYPE      Type,
    208   IN  EFI_MEMORY_TYPE        MemoryType,
    209   IN  UINTN                  Pages,
    210   OUT VOID                   **HostAddress,
    211   IN  UINT64                 Attributes
    212 );
    213 
    214 EFI_STATUS
    215 EFIAPI
    216 PciIoFreeBuffer (
    217   IN  EFI_PCI_IO_PROTOCOL   *This,
    218   IN  UINTN                 Pages,
    219   IN  VOID                  *HostAddress
    220   );
    221 
    222 EFI_STATUS
    223 EFIAPI
    224 PciIoFlush (
    225   IN  EFI_PCI_IO_PROTOCOL  *This
    226   );
    227 
    228 EFI_STATUS
    229 EFIAPI
    230 PciIoGetLocation (
    231   IN  EFI_PCI_IO_PROTOCOL  *This,
    232   OUT UINTN                *Segment,
    233   OUT UINTN                *Bus,
    234   OUT UINTN                *Device,
    235   OUT UINTN                *Function
    236   );
    237 
    238 EFI_STATUS
    239 EFIAPI
    240 PciIoAttributes (
    241   IN  EFI_PCI_IO_PROTOCOL              *This,
    242   IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,
    243   IN  UINT64                                   Attributes,
    244   OUT UINT64                                   *Result   OPTIONAL
    245   );
    246 
    247 EFI_STATUS
    248 EFIAPI
    249 PciIoGetBarAttributes(
    250   IN  EFI_PCI_IO_PROTOCOL    *This,
    251   IN  UINT8                          BarIndex,
    252   OUT UINT64                         *Supports,   OPTIONAL
    253   OUT VOID                           **Resources  OPTIONAL
    254   );
    255 
    256 EFI_STATUS
    257 EFIAPI
    258 PciIoSetBarAttributes(
    259   IN     EFI_PCI_IO_PROTOCOL  *This,
    260   IN     UINT64                       Attributes,
    261   IN     UINT8                        BarIndex,
    262   IN OUT UINT64                       *Offset,
    263   IN OUT UINT64                       *Length
    264   );
    265 
    266 
    267 //
    268 // Pci Io Protocol Interface
    269 //
    270 EFI_PCI_IO_PROTOCOL  PciIoInterface = {
    271   PciIoPollMem,
    272   PciIoPollIo,
    273   {
    274     PciIoMemRead,
    275     PciIoMemWrite
    276   },
    277   {
    278     PciIoIoRead,
    279     PciIoIoWrite
    280   },
    281   {
    282     PciIoConfigRead,
    283     PciIoConfigWrite
    284   },
    285   PciIoCopyMem,
    286   PciIoMap,
    287   PciIoUnmap,
    288   PciIoAllocateBuffer,
    289   PciIoFreeBuffer,
    290   PciIoFlush,
    291   PciIoGetLocation,
    292   PciIoAttributes,
    293   PciIoGetBarAttributes,
    294   PciIoSetBarAttributes,
    295   0,
    296   NULL
    297 };
    298 
    299 
    300 EFI_STATUS
    301 InitializePciIoInstance (
    302   PCI_IO_DEVICE  *PciIoDevice
    303   )
    304 /*++
    305 
    306 Routine Description:
    307 
    308   Initializes a PCI I/O Instance
    309 
    310 Arguments:
    311 
    312 Returns:
    313 
    314   None
    315 
    316 --*/
    317 
    318 {
    319   CopyMem (&PciIoDevice->PciIo, &PciIoInterface, sizeof (EFI_PCI_IO_PROTOCOL));
    320   return EFI_SUCCESS;
    321 }
    322 
    323 EFI_STATUS
    324 PciIoVerifyBarAccess (
    325   PCI_IO_DEVICE                   *PciIoDevice,
    326   UINT8                           BarIndex,
    327   PCI_BAR_TYPE                    Type,
    328   IN EFI_PCI_IO_PROTOCOL_WIDTH    Width,
    329   IN UINTN                        Count,
    330   UINT64                          *Offset
    331   )
    332 /*++
    333 
    334 Routine Description:
    335 
    336   Verifies access to a PCI Base Address Register (BAR)
    337 
    338 Arguments:
    339 
    340 Returns:
    341 
    342   None
    343 
    344 --*/
    345 {
    346   if ((UINT32)Width >= EfiPciIoWidthMaximum) {
    347     return EFI_INVALID_PARAMETER;
    348   }
    349 
    350   if (BarIndex == EFI_PCI_IO_PASS_THROUGH_BAR) {
    351     return EFI_SUCCESS;
    352   }
    353 
    354   //
    355   // BarIndex 0-5 is legal
    356   //
    357   if (BarIndex >= PCI_MAX_BAR) {
    358     return EFI_INVALID_PARAMETER;
    359   }
    360 
    361   if (!CheckBarType (PciIoDevice, BarIndex, Type)) {
    362     return EFI_INVALID_PARAMETER;
    363   }
    364 
    365   //
    366   // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX
    367   // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX
    368   //
    369   if (Width >= EfiPciIoWidthFifoUint8 && Width <= EfiPciIoWidthFifoUint64) {
    370     Count = 1;
    371   }
    372 
    373   Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03);
    374 
    375   if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PciIoDevice->PciBar[BarIndex].Length) {
    376     return EFI_INVALID_PARAMETER;
    377   }
    378 
    379   *Offset = *Offset + PciIoDevice->PciBar[BarIndex].BaseAddress;
    380 
    381   return EFI_SUCCESS;
    382 }
    383 
    384 EFI_STATUS
    385 PciIoVerifyConfigAccess (
    386   PCI_IO_DEVICE                 *PciIoDevice,
    387   IN EFI_PCI_IO_PROTOCOL_WIDTH  Width,
    388   IN UINTN                      Count,
    389   IN UINT64                     *Offset
    390   )
    391 /*++
    392 
    393 Routine Description:
    394 
    395   Verifies access to a PCI Config Header
    396 
    397 Arguments:
    398 
    399 Returns:
    400 
    401   None
    402 
    403 --*/
    404 {
    405   UINT64  ExtendOffset;
    406 
    407   if ((UINT32)Width >= EfiPciIoWidthMaximum) {
    408     return EFI_INVALID_PARAMETER;
    409   }
    410 
    411   //
    412   // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX
    413   // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX
    414   //
    415   Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03);
    416 
    417   if (PciIoDevice->IsPciExp) {
    418     if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PCI_EXP_MAX_CONFIG_OFFSET) {
    419       return EFI_UNSUPPORTED;
    420     }
    421 
    422     ExtendOffset  = LShiftU64 (*Offset, 32);
    423     *Offset       = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);
    424     *Offset       = (*Offset) | ExtendOffset;
    425 
    426   } else {
    427     if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PCI_MAX_CONFIG_OFFSET) {
    428       return EFI_UNSUPPORTED;
    429     }
    430 
    431     *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, *Offset);
    432   }
    433 
    434   return EFI_SUCCESS;
    435 }
    436 
    437 EFI_STATUS
    438 EFIAPI
    439 PciIoPollMem (
    440   IN  EFI_PCI_IO_PROTOCOL        *This,
    441   IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,
    442   IN  UINT8                      BarIndex,
    443   IN  UINT64                     Offset,
    444   IN  UINT64                     Mask,
    445   IN  UINT64                     Value,
    446   IN  UINT64                     Delay,
    447   OUT UINT64                     *Result
    448   )
    449 /*++
    450 
    451 Routine Description:
    452 
    453   Poll PCI Memmory
    454 
    455 Arguments:
    456 
    457 Returns:
    458 
    459   None
    460 
    461 --*/
    462 {
    463   EFI_STATUS    Status;
    464   PCI_IO_DEVICE *PciIoDevice;
    465 
    466   PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
    467 
    468   if ((UINT32)Width >= EfiPciIoWidthMaximum) {
    469     return EFI_INVALID_PARAMETER;
    470   }
    471 
    472   Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, 1, &Offset);
    473   if (EFI_ERROR (Status)) {
    474     return EFI_UNSUPPORTED;
    475   }
    476 
    477   if (Width > EfiPciIoWidthUint64) {
    478     return EFI_INVALID_PARAMETER;
    479   }
    480 
    481   Status = PciIoDevice->PciRootBridgeIo->PollMem (
    482                                           PciIoDevice->PciRootBridgeIo,
    483                                           (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
    484                                           Offset,
    485                                           Mask,
    486                                           Value,
    487                                           Delay,
    488                                           Result
    489                                           );
    490   return Status;
    491 }
    492 
    493 EFI_STATUS
    494 EFIAPI
    495 PciIoPollIo (
    496   IN  EFI_PCI_IO_PROTOCOL        *This,
    497   IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,
    498   IN  UINT8                      BarIndex,
    499   IN  UINT64                     Offset,
    500   IN  UINT64                     Mask,
    501   IN  UINT64                     Value,
    502   IN  UINT64                     Delay,
    503   OUT UINT64                     *Result
    504   )
    505 /*++
    506 
    507 Routine Description:
    508 
    509   Poll PCI IO
    510 
    511 Arguments:
    512 
    513 Returns:
    514 
    515   None
    516 
    517 --*/
    518 {
    519   EFI_STATUS    Status;
    520   PCI_IO_DEVICE *PciIoDevice;
    521 
    522   PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
    523 
    524   if ((UINT32)Width > EfiPciIoWidthUint64) {
    525     return EFI_INVALID_PARAMETER;
    526   }
    527 
    528   Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, 1, &Offset);
    529   if (EFI_ERROR (Status)) {
    530     return EFI_UNSUPPORTED;
    531   }
    532 
    533   Status = PciIoDevice->PciRootBridgeIo->PollIo (
    534                                           PciIoDevice->PciRootBridgeIo,
    535                                           (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
    536                                           Offset,
    537                                           Mask,
    538                                           Value,
    539                                           Delay,
    540                                           Result
    541                                           );
    542 
    543   return Status;
    544 }
    545 
    546 EFI_STATUS
    547 EFIAPI
    548 PciIoMemRead (
    549   IN     EFI_PCI_IO_PROTOCOL        *This,
    550   IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
    551   IN     UINT8                      BarIndex,
    552   IN     UINT64                     Offset,
    553   IN     UINTN                      Count,
    554   IN OUT VOID                       *Buffer
    555   )
    556 /*++
    557 
    558 Routine Description:
    559 
    560   Performs a PCI Memory Read Cycle
    561 
    562 Arguments:
    563 
    564 Returns:
    565 
    566   None
    567 
    568 --*/
    569 {
    570   EFI_STATUS    Status;
    571   PCI_IO_DEVICE *PciIoDevice;
    572 
    573   if (Buffer == NULL){
    574     return EFI_INVALID_PARAMETER;
    575   }
    576 
    577   PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
    578 
    579   if ((UINT32)Width >= EfiPciIoWidthMaximum) {
    580     return EFI_INVALID_PARAMETER;
    581   }
    582 
    583   Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);
    584   if (EFI_ERROR (Status)) {
    585     return EFI_UNSUPPORTED;
    586   }
    587 
    588   Status = PciIoDevice->PciRootBridgeIo->Mem.Read (
    589                                               PciIoDevice->PciRootBridgeIo,
    590                                               (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
    591                                               Offset,
    592                                               Count,
    593                                               Buffer
    594                                               );
    595 
    596   return Status;
    597 }
    598 
    599 EFI_STATUS
    600 EFIAPI
    601 PciIoMemWrite (
    602   IN     EFI_PCI_IO_PROTOCOL        *This,
    603   IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
    604   IN     UINT8                      BarIndex,
    605   IN     UINT64                     Offset,
    606   IN     UINTN                      Count,
    607   IN OUT VOID                       *Buffer
    608   )
    609 /*++
    610 
    611 Routine Description:
    612 
    613   Performs a PCI Memory Write Cycle
    614 
    615 Arguments:
    616 
    617 Returns:
    618 
    619   None
    620 
    621 --*/
    622 {
    623   EFI_STATUS    Status;
    624   PCI_IO_DEVICE *PciIoDevice;
    625 
    626   if (Buffer == NULL){
    627     return EFI_INVALID_PARAMETER;
    628   }
    629 
    630   PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
    631 
    632   if ((UINT32)Width >= EfiPciIoWidthMaximum) {
    633     return EFI_INVALID_PARAMETER;
    634   }
    635 
    636   Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);
    637   if (EFI_ERROR (Status)) {
    638     return EFI_UNSUPPORTED;
    639   }
    640 
    641   Status = PciIoDevice->PciRootBridgeIo->Mem.Write (
    642                                               PciIoDevice->PciRootBridgeIo,
    643                                               (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
    644                                               Offset,
    645                                               Count,
    646                                               Buffer
    647                                               );
    648 
    649   return Status;
    650 }
    651 
    652 EFI_STATUS
    653 EFIAPI
    654 PciIoIoRead (
    655   IN     EFI_PCI_IO_PROTOCOL        *This,
    656   IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
    657   IN     UINT8                      BarIndex,
    658   IN     UINT64                     Offset,
    659   IN     UINTN                      Count,
    660   IN OUT VOID                       *Buffer
    661   )
    662 /*++
    663 
    664 Routine Description:
    665 
    666   Performs a PCI I/O Read Cycle
    667 
    668 Arguments:
    669 
    670 Returns:
    671 
    672   None
    673 
    674 --*/
    675 {
    676   EFI_STATUS    Status;
    677   PCI_IO_DEVICE *PciIoDevice;
    678 
    679   if (Buffer == NULL){
    680     return EFI_INVALID_PARAMETER;
    681   }
    682 
    683   PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
    684 
    685   if ((UINT32)Width >= EfiPciIoWidthMaximum) {
    686     return EFI_INVALID_PARAMETER;
    687   }
    688 
    689   Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);
    690   if (EFI_ERROR (Status)) {
    691     return EFI_UNSUPPORTED;
    692   }
    693 
    694   Status = PciIoDevice->PciRootBridgeIo->Io.Read (
    695                                               PciIoDevice->PciRootBridgeIo,
    696                                               (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
    697                                               Offset,
    698                                               Count,
    699                                               Buffer
    700                                               );
    701 
    702   return Status;
    703 }
    704 
    705 EFI_STATUS
    706 EFIAPI
    707 PciIoIoWrite (
    708   IN     EFI_PCI_IO_PROTOCOL        *This,
    709   IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
    710   IN     UINT8                      BarIndex,
    711   IN     UINT64                     Offset,
    712   IN     UINTN                      Count,
    713   IN OUT VOID                       *Buffer
    714   )
    715 /*++
    716 
    717 Routine Description:
    718 
    719   Performs a PCI I/O Write Cycle
    720 
    721 Arguments:
    722 
    723 Returns:
    724 
    725   None
    726 
    727 --*/
    728 {
    729   EFI_STATUS    Status;
    730   PCI_IO_DEVICE *PciIoDevice;
    731 
    732   if (Buffer == NULL){
    733     return EFI_INVALID_PARAMETER;
    734   }
    735 
    736   PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
    737 
    738   if ((UINT32)Width >= EfiPciIoWidthMaximum) {
    739     return EFI_INVALID_PARAMETER;
    740   }
    741 
    742   Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);
    743   if (EFI_ERROR (Status)) {
    744     return EFI_UNSUPPORTED;
    745   }
    746 
    747   Status = PciIoDevice->PciRootBridgeIo->Io.Write (
    748                                               PciIoDevice->PciRootBridgeIo,
    749                                               (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
    750                                               Offset,
    751                                               Count,
    752                                               Buffer
    753                                               );
    754 
    755   return Status;
    756 }
    757 
    758 EFI_STATUS
    759 EFIAPI
    760 PciIoConfigRead (
    761   IN     EFI_PCI_IO_PROTOCOL        *This,
    762   IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
    763   IN     UINT32                     Offset,
    764   IN     UINTN                      Count,
    765   IN OUT VOID                       *Buffer
    766   )
    767 /*++
    768 
    769 Routine Description:
    770 
    771   Performs a PCI Configuration Read Cycle
    772 
    773 Arguments:
    774 
    775 Returns:
    776 
    777   None
    778 
    779 --*/
    780 {
    781   EFI_STATUS    Status;
    782   PCI_IO_DEVICE *PciIoDevice;
    783   UINT64        Address;
    784 
    785   PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
    786 
    787   Address     = Offset;
    788   Status      = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);
    789   if (EFI_ERROR (Status)) {
    790     return Status;
    791   }
    792 
    793   Status = PciIoDevice->PciRootBridgeIo->Pci.Read (
    794                                               PciIoDevice->PciRootBridgeIo,
    795                                               (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
    796                                               Address,
    797                                               Count,
    798                                               Buffer
    799                                               );
    800 
    801   return Status;
    802 }
    803 
    804 EFI_STATUS
    805 EFIAPI
    806 PciIoConfigWrite (
    807   IN     EFI_PCI_IO_PROTOCOL        *This,
    808   IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
    809   IN     UINT32                     Offset,
    810   IN     UINTN                      Count,
    811   IN OUT VOID                       *Buffer
    812   )
    813 /*++
    814 
    815 Routine Description:
    816 
    817   Performs a PCI Configuration Write Cycle
    818 
    819 Arguments:
    820 
    821 Returns:
    822 
    823   None
    824 
    825 --*/
    826 {
    827   EFI_STATUS    Status;
    828   PCI_IO_DEVICE *PciIoDevice;
    829   UINT64        Address;
    830 
    831   PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
    832 
    833   Address     = Offset;
    834   Status      = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);
    835   if (EFI_ERROR (Status)) {
    836     return Status;
    837   }
    838 
    839   Status = PciIoDevice->PciRootBridgeIo->Pci.Write (
    840                                               PciIoDevice->PciRootBridgeIo,
    841                                               (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
    842                                               Address,
    843                                               Count,
    844                                               Buffer
    845                                               );
    846 
    847   return Status;
    848 }
    849 
    850 EFI_STATUS
    851 EFIAPI
    852 PciIoCopyMem (
    853   IN EFI_PCI_IO_PROTOCOL              *This,
    854   IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,
    855   IN     UINT8                        DestBarIndex,
    856   IN     UINT64                       DestOffset,
    857   IN     UINT8                        SrcBarIndex,
    858   IN     UINT64                       SrcOffset,
    859   IN     UINTN                        Count
    860   )
    861 /*++
    862 
    863 Routine Description:
    864 
    865   Copy PCI Memory
    866 
    867 Arguments:
    868 
    869 Returns:
    870 
    871   None
    872 
    873 --*/
    874 {
    875   EFI_STATUS    Status;
    876   PCI_IO_DEVICE *PciIoDevice;
    877 
    878   PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
    879 
    880   if ((UINT32)Width >= EfiPciIoWidthMaximum) {
    881     return EFI_INVALID_PARAMETER;
    882   }
    883 
    884   if (Width == EfiPciIoWidthFifoUint8  ||
    885       Width == EfiPciIoWidthFifoUint16 ||
    886       Width == EfiPciIoWidthFifoUint32 ||
    887       Width == EfiPciIoWidthFifoUint64 ||
    888       Width == EfiPciIoWidthFillUint8  ||
    889       Width == EfiPciIoWidthFillUint16 ||
    890       Width == EfiPciIoWidthFillUint32 ||
    891       Width == EfiPciIoWidthFillUint64) {
    892     return EFI_INVALID_PARAMETER;
    893   }
    894 
    895   Status = PciIoVerifyBarAccess (PciIoDevice, DestBarIndex, PciBarTypeMem, Width, Count, &DestOffset);
    896   if (EFI_ERROR (Status)) {
    897     return EFI_UNSUPPORTED;
    898   }
    899 
    900   Status = PciIoVerifyBarAccess (PciIoDevice, SrcBarIndex, PciBarTypeMem, Width, Count, &SrcOffset);
    901   if (EFI_ERROR (Status)) {
    902     return EFI_UNSUPPORTED;
    903   }
    904 
    905   Status = PciIoDevice->PciRootBridgeIo->CopyMem (
    906                                           PciIoDevice->PciRootBridgeIo,
    907                                           (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
    908                                           DestOffset,
    909                                           SrcOffset,
    910                                           Count
    911                                           );
    912 
    913   return Status;
    914 }
    915 
    916 EFI_STATUS
    917 EFIAPI
    918 PciIoMap (
    919   IN     EFI_PCI_IO_PROTOCOL            *This,
    920   IN     EFI_PCI_IO_PROTOCOL_OPERATION  Operation,
    921   IN     VOID                           *HostAddress,
    922   IN OUT UINTN                          *NumberOfBytes,
    923   OUT    EFI_PHYSICAL_ADDRESS           *DeviceAddress,
    924   OUT    VOID                           **Mapping
    925   )
    926 /*++
    927 
    928 Routine Description:
    929 
    930   Maps a memory region for DMA
    931 
    932 Arguments:
    933 
    934 Returns:
    935 
    936   None
    937 
    938 --*/
    939 {
    940   EFI_STATUS    Status;
    941   PCI_IO_DEVICE *PciIoDevice;
    942 
    943   PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
    944 
    945   if ((UINT32)Operation >= EfiPciIoOperationMaximum) {
    946     return EFI_INVALID_PARAMETER;
    947   }
    948 
    949   if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {
    950     return EFI_INVALID_PARAMETER;
    951   }
    952 
    953   if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) {
    954     Operation = (EFI_PCI_IO_PROTOCOL_OPERATION) (Operation + EfiPciOperationBusMasterRead64);
    955   }
    956 
    957   Status = PciIoDevice->PciRootBridgeIo->Map (
    958                                           PciIoDevice->PciRootBridgeIo,
    959                                           (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,
    960                                           HostAddress,
    961                                           NumberOfBytes,
    962                                           DeviceAddress,
    963                                           Mapping
    964                                           );
    965 
    966   return Status;
    967 }
    968 
    969 EFI_STATUS
    970 EFIAPI
    971 PciIoUnmap (
    972   IN  EFI_PCI_IO_PROTOCOL  *This,
    973   IN  VOID                 *Mapping
    974   )
    975 /*++
    976 
    977 Routine Description:
    978 
    979   Unmaps a memory region for DMA
    980 
    981 Arguments:
    982 
    983 Returns:
    984 
    985   None
    986 
    987 --*/
    988 {
    989   EFI_STATUS    Status;
    990   PCI_IO_DEVICE *PciIoDevice;
    991 
    992   PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
    993 
    994   Status = PciIoDevice->PciRootBridgeIo->Unmap (
    995                                           PciIoDevice->PciRootBridgeIo,
    996                                           Mapping
    997                                           );
    998 
    999   return Status;
   1000 }
   1001 
   1002 EFI_STATUS
   1003 EFIAPI
   1004 PciIoAllocateBuffer (
   1005   IN  EFI_PCI_IO_PROTOCOL   *This,
   1006   IN  EFI_ALLOCATE_TYPE     Type,
   1007   IN  EFI_MEMORY_TYPE       MemoryType,
   1008   IN  UINTN                 Pages,
   1009   OUT VOID                  **HostAddress,
   1010   IN  UINT64                Attributes
   1011   )
   1012 /*++
   1013 
   1014 Routine Description:
   1015 
   1016   Allocates a common buffer for DMA
   1017 
   1018 Arguments:
   1019 
   1020 Returns:
   1021 
   1022   None
   1023 
   1024 --*/
   1025 {
   1026   EFI_STATUS    Status;
   1027   PCI_IO_DEVICE *PciIoDevice;
   1028 
   1029   if (Attributes &
   1030       (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED))) {
   1031     return EFI_UNSUPPORTED;
   1032   }
   1033 
   1034   PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
   1035 
   1036   if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) {
   1037     Attributes |= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
   1038   }
   1039 
   1040   Status = PciIoDevice->PciRootBridgeIo->AllocateBuffer (
   1041                                           PciIoDevice->PciRootBridgeIo,
   1042                                           Type,
   1043                                           MemoryType,
   1044                                           Pages,
   1045                                           HostAddress,
   1046                                           Attributes
   1047                                           );
   1048 
   1049   return Status;
   1050 }
   1051 
   1052 EFI_STATUS
   1053 EFIAPI
   1054 PciIoFreeBuffer (
   1055   IN  EFI_PCI_IO_PROTOCOL   *This,
   1056   IN  UINTN                 Pages,
   1057   IN  VOID                  *HostAddress
   1058   )
   1059 /*++
   1060 
   1061 Routine Description:
   1062 
   1063   Frees a common buffer
   1064 
   1065 Arguments:
   1066 
   1067 Returns:
   1068 
   1069   None
   1070 
   1071 --*/
   1072 {
   1073   EFI_STATUS    Status;
   1074   PCI_IO_DEVICE *PciIoDevice;
   1075 
   1076   if( HostAddress == NULL ){
   1077      return EFI_INVALID_PARAMETER;
   1078   }
   1079 
   1080   PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
   1081 
   1082   Status = PciIoDevice->PciRootBridgeIo->FreeBuffer (
   1083                                           PciIoDevice->PciRootBridgeIo,
   1084                                           Pages,
   1085                                           HostAddress
   1086                                           );
   1087 
   1088   return Status;
   1089 }
   1090 
   1091 EFI_STATUS
   1092 EFIAPI
   1093 PciIoFlush (
   1094   IN  EFI_PCI_IO_PROTOCOL  *This
   1095   )
   1096 /*++
   1097 
   1098 Routine Description:
   1099 
   1100   Flushes a DMA buffer
   1101 
   1102 Arguments:
   1103 
   1104 Returns:
   1105 
   1106   None
   1107 
   1108 --*/
   1109 
   1110 {
   1111   EFI_STATUS    Status;
   1112   UINT32         Register;
   1113   PCI_IO_DEVICE  *PciIoDevice;
   1114 
   1115   PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
   1116 
   1117   //
   1118   // If the device is behind a PCI-PCI Bridge, then perform a read cycles to the device to
   1119   // flush the posted write cycles through the PCI-PCI bridges
   1120   //
   1121   if (PciIoDevice->Parent != NULL) {
   1122     Status = This->Pci.Read (This, EfiPciIoWidthUint32, 0, 1, &Register);
   1123   }
   1124 
   1125   //
   1126   // Call the PCI Root Bridge I/O Protocol to flush the posted write cycles through the chipset
   1127   //
   1128   Status = PciIoDevice->PciRootBridgeIo->Flush (
   1129                                            PciIoDevice->PciRootBridgeIo
   1130                                            );
   1131 
   1132   return Status;
   1133 }
   1134 
   1135 EFI_STATUS
   1136 EFIAPI
   1137 PciIoGetLocation (
   1138   IN  EFI_PCI_IO_PROTOCOL  *This,
   1139   OUT UINTN                *Segment,
   1140   OUT UINTN                *Bus,
   1141   OUT UINTN                *Device,
   1142   OUT UINTN                *Function
   1143   )
   1144 /*++
   1145 
   1146 Routine Description:
   1147 
   1148   Gets a PCI device's current bus number, device number, and function number.
   1149 
   1150 Arguments:
   1151 
   1152 Returns:
   1153 
   1154   None
   1155 
   1156 --*/
   1157 {
   1158   PCI_IO_DEVICE *PciIoDevice;
   1159 
   1160   PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
   1161 
   1162   if (Segment == NULL || Bus == NULL || Device == NULL || Function == NULL) {
   1163     return EFI_INVALID_PARAMETER;
   1164   }
   1165 
   1166   *Segment  = PciIoDevice->PciRootBridgeIo->SegmentNumber;
   1167   *Bus      = PciIoDevice->BusNumber;
   1168   *Device   = PciIoDevice->DeviceNumber;
   1169   *Function = PciIoDevice->FunctionNumber;
   1170 
   1171   return EFI_SUCCESS;
   1172 }
   1173 
   1174 BOOLEAN
   1175 CheckBarType (
   1176   IN PCI_IO_DEVICE       *PciIoDevice,
   1177   UINT8                  BarIndex,
   1178   PCI_BAR_TYPE           BarType
   1179   )
   1180 /*++
   1181 
   1182 Routine Description:
   1183 
   1184   Sets a PCI controllers attributes on a resource range
   1185 
   1186 Arguments:
   1187 
   1188 Returns:
   1189 
   1190   None
   1191 
   1192 --*/
   1193 {
   1194   switch (BarType) {
   1195 
   1196   case PciBarTypeMem:
   1197 
   1198     if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem32  &&
   1199         PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem32 &&
   1200         PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem64 &&
   1201         PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem64    ) {
   1202       return FALSE;
   1203     }
   1204 
   1205     return TRUE;
   1206 
   1207   case PciBarTypeIo:
   1208     if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo32 &&
   1209         PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo16){
   1210       return FALSE;
   1211     }
   1212 
   1213     return TRUE;
   1214 
   1215   default:
   1216     break;
   1217   }
   1218 
   1219   return FALSE;
   1220 }
   1221 
   1222 EFI_STATUS
   1223 EFIAPI
   1224 PciIoAttributes (
   1225   IN EFI_PCI_IO_PROTOCOL                       * This,
   1226   IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,
   1227   IN  UINT64                                   Attributes,
   1228   OUT UINT64                                   *Result OPTIONAL
   1229   )
   1230 /*++
   1231 
   1232 Routine Description:
   1233 
   1234 
   1235 Arguments:
   1236 
   1237 Returns:
   1238 
   1239   None
   1240 
   1241 --*/
   1242 {
   1243   EFI_STATUS    Status;
   1244 
   1245   PCI_IO_DEVICE *PciIoDevice;
   1246   PCI_IO_DEVICE *Temp;
   1247   UINT64         NewAttributes;
   1248   UINT64         PciRootBridgeSupports;
   1249   UINT64         PciRootBridgeAttributes;
   1250   UINT64         NewPciRootBridgeAttributes;
   1251   UINT64         NewUpStreamBridgeAttributes;
   1252   UINT64         ModifiedPciRootBridgeAttributes;
   1253   UINT16         EnableCommand;
   1254   UINT16         DisableCommand;
   1255   UINT16         EnableBridge;
   1256   UINT16         DisableBridge;
   1257   UINT16         Command;
   1258 
   1259   PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
   1260   NewUpStreamBridgeAttributes = 0;
   1261 
   1262   EnableCommand   = 0;
   1263   DisableCommand  = 0;
   1264   EnableBridge    = 0;
   1265   DisableBridge   = 0;
   1266 
   1267   switch (Operation) {
   1268   case EfiPciIoAttributeOperationGet:
   1269     if (Result == NULL) {
   1270       return EFI_INVALID_PARAMETER;
   1271     }
   1272 
   1273     *Result = PciIoDevice->Attributes;
   1274     return EFI_SUCCESS;
   1275 
   1276   case EfiPciIoAttributeOperationSupported:
   1277     if (Result == NULL) {
   1278       return EFI_INVALID_PARAMETER;
   1279     }
   1280 
   1281     *Result = PciIoDevice->Supports;
   1282     return EFI_SUCCESS;
   1283 
   1284   case EfiPciIoAttributeOperationEnable:
   1285     if(Attributes & ~(PciIoDevice->Supports)) {
   1286       return EFI_UNSUPPORTED;
   1287     }
   1288     NewAttributes = PciIoDevice->Attributes | Attributes;
   1289     break;
   1290   case EfiPciIoAttributeOperationDisable:
   1291     if(Attributes & ~(PciIoDevice->Supports)) {
   1292       return EFI_UNSUPPORTED;
   1293     }
   1294     NewAttributes = PciIoDevice->Attributes & (~Attributes);
   1295     break;
   1296   case EfiPciIoAttributeOperationSet:
   1297     if(Attributes & ~(PciIoDevice->Supports)) {
   1298       return EFI_UNSUPPORTED;
   1299     }
   1300     NewAttributes = Attributes;
   1301     break;
   1302   default:
   1303     return EFI_INVALID_PARAMETER;
   1304   }
   1305 
   1306   //
   1307   // If VGA_IO is set, then set VGA_MEMORY too.  This driver can not enable them seperately.
   1308   //
   1309   if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {
   1310     NewAttributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
   1311   }
   1312 
   1313   //
   1314   // If VGA_MEMORY is set, then set VGA_IO too.  This driver can not enable them seperately.
   1315   //
   1316   if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY) {
   1317     NewAttributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;
   1318   }
   1319 
   1320   //
   1321   // If the attributes are already set correctly, then just return EFI_SUCCESS;
   1322   //
   1323   if ((NewAttributes ^ PciIoDevice->Attributes) == 0) {
   1324     return EFI_SUCCESS;
   1325   }
   1326 
   1327   //
   1328   // This driver takes care of EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_MEMORY, and
   1329   // EFI_PCI_IO_ATTRIBUTE_BUS_MASTER.  Strip these 3 bits off the new attribute mask so
   1330   // a call to the PCI Root Bridge I/O Protocol can be made
   1331   //
   1332 
   1333   if (!IS_PCI_BRIDGE(&PciIoDevice->Pci)) {
   1334     NewPciRootBridgeAttributes = NewAttributes & (~(EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE));
   1335 
   1336     //
   1337     // Get the current attributes of this PCI device's PCI Root Bridge
   1338     //
   1339     Status = PciIoDevice->PciRootBridgeIo->GetAttributes (
   1340                                             PciIoDevice->PciRootBridgeIo,
   1341                                             &PciRootBridgeSupports,
   1342                                             &PciRootBridgeAttributes
   1343                                             );
   1344 
   1345     //
   1346     // Check to see if any of the PCI Root Bridge attributes are being modified
   1347     //
   1348     ModifiedPciRootBridgeAttributes = NewPciRootBridgeAttributes ^ PciRootBridgeAttributes;
   1349     if (ModifiedPciRootBridgeAttributes) {
   1350 
   1351       //
   1352       // Check to see if the PCI Root Bridge supports modifiying the attributes that are changing
   1353       //
   1354       if ((ModifiedPciRootBridgeAttributes & PciRootBridgeSupports) != ModifiedPciRootBridgeAttributes) {
   1355   //     return EFI_UNSUPPORTED;
   1356       }
   1357       //
   1358       // Call the PCI Root Bridge to attempt to modify the attributes
   1359       //
   1360       Status = PciIoDevice->PciRootBridgeIo->SetAttributes (
   1361                                              PciIoDevice->PciRootBridgeIo,
   1362                                              NewPciRootBridgeAttributes,
   1363                                              NULL,
   1364                                              NULL
   1365                                              );
   1366       if (EFI_ERROR (Status)) {
   1367       //
   1368       // The PCI Root Bridge could not modify the attributes, so return the error.
   1369       //
   1370         return Status;
   1371       }
   1372     }
   1373   }
   1374 
   1375 
   1376   if (IS_PCI_BRIDGE(&PciIoDevice->Pci)) {
   1377 
   1378 
   1379     //
   1380     // Check to see if an VGA related attributes are being set.
   1381     //
   1382     if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO)) {
   1383 
   1384       if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {
   1385         EnableBridge  |= EFI_PCI_BRIDGE_CONTROL_VGA;
   1386       } else {
   1387         DisableBridge  |= EFI_PCI_BRIDGE_CONTROL_VGA;
   1388       }
   1389     }
   1390 
   1391     //
   1392     // Check to see if an VGA related attributes are being set.
   1393     // If ISA Enable on the PPB is set, the PPB will block the
   1394     // 0x100-0x3FF for each 1KB block in the first 64K I/O block
   1395     //
   1396     if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO)) {
   1397 
   1398       if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) {
   1399         DisableBridge  |= EFI_PCI_BRIDGE_CONTROL_ISA;
   1400       } else {
   1401         EnableBridge  |= EFI_PCI_BRIDGE_CONTROL_ISA;
   1402       }
   1403     }
   1404 
   1405     //
   1406     // Check to see if an VGA related attributes are being set.
   1407     //
   1408     if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO)) {
   1409 
   1410       if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) {
   1411         EnableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
   1412       } else {
   1413         DisableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
   1414       }
   1415     }
   1416 
   1417   } else {
   1418 
   1419     if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO)) {
   1420 
   1421       if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {
   1422 
   1423         //
   1424         //Check if there have been an active VGA device on the same segment
   1425         //
   1426         Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);
   1427 
   1428         if (Temp && Temp != PciIoDevice) {
   1429           return EFI_UNSUPPORTED;
   1430         }
   1431       }
   1432     }
   1433 
   1434     if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO)) {
   1435       if (IS_PCI_GFX(&PciIoDevice->Pci)) {
   1436 
   1437         //
   1438         //Get the boot VGA on the same segement
   1439         //
   1440         Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);
   1441 
   1442         if (!Temp) {
   1443 
   1444           //
   1445           // If there is no VGA device on the segement, set
   1446           // this graphics card to decode the palette range
   1447           //
   1448           DisableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
   1449         } else {
   1450 
   1451           //
   1452           // Check these two agents are on the same path
   1453           //
   1454           if (PciDevicesOnTheSamePath(Temp, PciIoDevice)) {
   1455 
   1456             //
   1457             // Check if they are on the same bus
   1458             //
   1459             if (Temp->Parent == PciIoDevice->Parent) {
   1460 
   1461               PciReadCommandRegister (Temp, &Command);
   1462 
   1463               //
   1464               // If they are on the same bus, either one can
   1465               // be set to snoop, the other set to decode
   1466               //
   1467               if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) {
   1468                 DisableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
   1469               } else {
   1470                 EnableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
   1471               }
   1472             } else {
   1473 
   1474               //
   1475               // If they are on  the same path but on the different bus
   1476               // The first agent is set to snoop, the second one set to
   1477               // decode
   1478               //
   1479               if (Temp->BusNumber > PciIoDevice->BusNumber) {
   1480                 PciEnableCommandRegister(Temp,EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);
   1481                 DisableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
   1482               } else {
   1483                 PciDisableCommandRegister(Temp,EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);
   1484                 EnableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
   1485               }
   1486             }
   1487           } else {
   1488 
   1489             EnableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
   1490           }
   1491         }
   1492       }
   1493     }
   1494   }
   1495 
   1496   //
   1497   // Check to see of the I/O enable is being modified
   1498   //
   1499   if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_IO)) {
   1500     if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_IO) {
   1501       EnableCommand |= EFI_PCI_COMMAND_IO_SPACE;
   1502     } else {
   1503       DisableCommand |= EFI_PCI_COMMAND_IO_SPACE;
   1504     }
   1505   }
   1506 
   1507   //
   1508   // Check to see of the Memory enable is being modified
   1509   //
   1510   if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_MEMORY)) {
   1511     if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) {
   1512       EnableCommand |= EFI_PCI_COMMAND_MEMORY_SPACE;
   1513     } else {
   1514       DisableCommand |= EFI_PCI_COMMAND_MEMORY_SPACE;
   1515     }
   1516   }
   1517 
   1518   //
   1519   // Check to see of the Bus Master enable is being modified
   1520   //
   1521   if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER)) {
   1522     if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) {
   1523       EnableCommand  |= EFI_PCI_COMMAND_BUS_MASTER;
   1524     } else {
   1525       DisableCommand |= EFI_PCI_COMMAND_BUS_MASTER;
   1526     }
   1527   }
   1528 
   1529   Status = EFI_SUCCESS;
   1530   if (EnableCommand) {
   1531     Status = PciEnableCommandRegister(PciIoDevice, EnableCommand);
   1532   }
   1533 
   1534   if (DisableCommand) {
   1535     Status = PciDisableCommandRegister(PciIoDevice, DisableCommand);
   1536   }
   1537 
   1538   if (EFI_ERROR(Status)) {
   1539     return EFI_UNSUPPORTED;
   1540   }
   1541 
   1542   if (EnableBridge) {
   1543     Status = PciEnableBridgeControlRegister(PciIoDevice, EnableBridge);
   1544   }
   1545 
   1546   if (DisableBridge) {
   1547     Status = PciDisableBridgeControlRegister(PciIoDevice, DisableBridge);
   1548   }
   1549 
   1550   if (EFI_ERROR(Status)) {
   1551     return EFI_UNSUPPORTED;
   1552   }
   1553 
   1554   //
   1555   // Set the upstream bridge attributes
   1556   //
   1557   if (Operation != EfiPciIoAttributeOperationGet && Operation != EfiPciIoAttributeOperationSupported) {
   1558 
   1559     //
   1560     // EFI_PCI_IO_ATTRIBUTE_MEMORY, EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
   1561     // EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED
   1562     // EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE will not effect to upstream bridge
   1563     //
   1564     NewUpStreamBridgeAttributes = Attributes & \
   1565                                 (~(EFI_PCI_IO_ATTRIBUTE_IO | \
   1566                                 EFI_PCI_IO_ATTRIBUTE_MEMORY | \
   1567                                 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | \
   1568                                 EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | \
   1569                                 EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED | \
   1570                                 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE));
   1571 
   1572     if (NewUpStreamBridgeAttributes){
   1573       UpStreamBridgesAttributes(PciIoDevice, Operation, NewUpStreamBridgeAttributes);
   1574     }
   1575   }
   1576 
   1577   PciIoDevice->Attributes = NewAttributes;
   1578 
   1579   return Status;
   1580 }
   1581 
   1582 EFI_STATUS
   1583 EFIAPI
   1584 PciIoGetBarAttributes (
   1585   IN EFI_PCI_IO_PROTOCOL             * This,
   1586   IN  UINT8                          BarIndex,
   1587   OUT UINT64                         *Supports, OPTIONAL
   1588   OUT VOID                           **Resources OPTIONAL
   1589   )
   1590 /*++
   1591 
   1592 Routine Description:
   1593 
   1594 
   1595 Arguments:
   1596 
   1597 Returns:
   1598 
   1599   None
   1600 
   1601 --*/
   1602 {
   1603   UINT8                             *Configuration;
   1604   PCI_IO_DEVICE                     *PciIoDevice;
   1605   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *AddressSpace;
   1606   EFI_ACPI_END_TAG_DESCRIPTOR       *End;
   1607 
   1608   PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
   1609 
   1610   if (Supports == NULL && Resources == NULL) {
   1611     return EFI_INVALID_PARAMETER;
   1612   }
   1613 
   1614   if ((BarIndex >= PCI_MAX_BAR) || (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown)) {
   1615     return EFI_UNSUPPORTED;
   1616   }
   1617 
   1618   //
   1619   // This driver does not support modifications to the WRITE_COMBINE or
   1620   // CACHED attributes for BAR ranges.
   1621   //
   1622   if (Supports != NULL) {
   1623     *Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;
   1624   }
   1625 
   1626   if (Resources != NULL) {
   1627     Configuration = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
   1628     if (Configuration == NULL) {
   1629       return EFI_OUT_OF_RESOURCES;
   1630     }
   1631 
   1632     AddressSpace = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
   1633 
   1634     AddressSpace->Desc         = ACPI_ADDRESS_SPACE_DESCRIPTOR;
   1635     AddressSpace->Len          = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);
   1636 
   1637     AddressSpace->AddrRangeMin = PciIoDevice->PciBar[BarIndex].BaseAddress;
   1638     AddressSpace->AddrLen      = PciIoDevice->PciBar[BarIndex].Length;
   1639     AddressSpace->AddrRangeMax = PciIoDevice->PciBar[BarIndex].Alignment;
   1640 
   1641     switch (PciIoDevice->PciBar[BarIndex].BarType) {
   1642     case PciBarTypeIo16:
   1643     case PciBarTypeIo32:
   1644       //
   1645       // Io
   1646       //
   1647       AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
   1648       break;
   1649 
   1650     case PciBarTypeMem32:
   1651       //
   1652       // Mem
   1653       //
   1654       AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
   1655       //
   1656       // 32 bit
   1657       //
   1658       AddressSpace->AddrSpaceGranularity = 32;
   1659       break;
   1660 
   1661     case PciBarTypePMem32:
   1662       //
   1663       // Mem
   1664       //
   1665       AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
   1666       //
   1667       // prefechable
   1668       //
   1669       AddressSpace->SpecificFlag = 0x6;
   1670       //
   1671       // 32 bit
   1672       //
   1673       AddressSpace->AddrSpaceGranularity = 32;
   1674       break;
   1675 
   1676     case PciBarTypeMem64:
   1677       //
   1678       // Mem
   1679       //
   1680       AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
   1681       //
   1682       // 64 bit
   1683       //
   1684       AddressSpace->AddrSpaceGranularity = 64;
   1685       break;
   1686 
   1687     case PciBarTypePMem64:
   1688       //
   1689       // Mem
   1690       //
   1691       AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
   1692       //
   1693       // prefechable
   1694       //
   1695       AddressSpace->SpecificFlag = 0x6;
   1696       //
   1697       // 64 bit
   1698       //
   1699       AddressSpace->AddrSpaceGranularity = 64;
   1700       break;
   1701 
   1702     default:
   1703       break;
   1704     }
   1705 
   1706     //
   1707     // put the checksum
   1708     //
   1709     End           = (EFI_ACPI_END_TAG_DESCRIPTOR *) (AddressSpace + 1);
   1710     End->Desc     = ACPI_END_TAG_DESCRIPTOR;
   1711     End->Checksum = 0;
   1712 
   1713     *Resources    = Configuration;
   1714   }
   1715 
   1716   return EFI_SUCCESS;
   1717 }
   1718 
   1719 EFI_STATUS
   1720 EFIAPI
   1721 PciIoSetBarAttributes (
   1722   IN EFI_PCI_IO_PROTOCOL              *This,
   1723   IN     UINT64                       Attributes,
   1724   IN     UINT8                        BarIndex,
   1725   IN OUT UINT64                       *Offset,
   1726   IN OUT UINT64                       *Length
   1727   )
   1728 /*++
   1729 
   1730 Routine Description:
   1731 
   1732 
   1733 Arguments:
   1734 
   1735 Returns:
   1736 
   1737   None
   1738 
   1739 --*/
   1740 {
   1741   EFI_STATUS    Status;
   1742   PCI_IO_DEVICE *PciIoDevice;
   1743   UINT64        NonRelativeOffset;
   1744   UINT64        Supports;
   1745 
   1746   PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
   1747 
   1748   //
   1749   // Make sure Offset and Length are not NULL
   1750   //
   1751   if (Offset == NULL || Length == NULL) {
   1752     return EFI_INVALID_PARAMETER;
   1753   }
   1754 
   1755   if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown) {
   1756     return EFI_UNSUPPORTED;
   1757   }
   1758   //
   1759   // This driver does not support setting the WRITE_COMBINE or the CACHED attributes.
   1760   // If Attributes is not 0, then return EFI_UNSUPPORTED.
   1761   //
   1762   Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;
   1763 
   1764   if (Attributes != (Attributes & Supports)) {
   1765     return EFI_UNSUPPORTED;
   1766   }
   1767   //
   1768   // Attributes must be supported.  Make sure the BAR range describd by BarIndex, Offset, and
   1769   // Length are valid for this PCI device.
   1770   //
   1771   NonRelativeOffset = *Offset;
   1772   Status = PciIoVerifyBarAccess (
   1773             PciIoDevice,
   1774             BarIndex,
   1775             PciBarTypeMem,
   1776             EfiPciIoWidthUint8,
   1777             (UINT32) *Length,
   1778             &NonRelativeOffset
   1779             );
   1780   if (EFI_ERROR (Status)) {
   1781     return EFI_UNSUPPORTED;
   1782   }
   1783 
   1784   return EFI_SUCCESS;
   1785 }
   1786 
   1787 EFI_STATUS
   1788 UpStreamBridgesAttributes (
   1789   IN  PCI_IO_DEVICE                            *PciIoDevice,
   1790   IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,
   1791   IN  UINT64                                   Attributes
   1792   )
   1793 /*++
   1794 
   1795 Routine Description:
   1796 
   1797 Arguments:
   1798 
   1799 Returns:
   1800 
   1801   None
   1802 
   1803 --*/
   1804 {
   1805   PCI_IO_DEVICE       *Parent;
   1806   EFI_PCI_IO_PROTOCOL *PciIo;
   1807 
   1808   Parent = PciIoDevice->Parent;
   1809 
   1810   while (Parent && IS_PCI_BRIDGE (&Parent->Pci)) {
   1811 
   1812     //
   1813     // Get the PciIo Protocol
   1814     //
   1815     PciIo = &Parent->PciIo;
   1816 
   1817     PciIo->Attributes (PciIo, Operation, Attributes, NULL);
   1818 
   1819     Parent = Parent->Parent;
   1820   }
   1821 
   1822   return EFI_SUCCESS;
   1823 }
   1824 
   1825 BOOLEAN
   1826 PciDevicesOnTheSamePath (
   1827   IN PCI_IO_DEVICE        *PciDevice1,
   1828   IN PCI_IO_DEVICE        *PciDevice2
   1829   )
   1830 /*++
   1831 
   1832 Routine Description:
   1833 
   1834 Arguments:
   1835 
   1836   PciDevice1  -  The pointer to the first PCI_IO_DEVICE.
   1837   PciDevice2  -  The pointer to the second PCI_IO_DEVICE.
   1838 
   1839 Returns:
   1840 
   1841   TRUE   -  The two Pci devices are on the same path.
   1842   FALSE  -  The two Pci devices are not on the same path.
   1843 
   1844 --*/
   1845 {
   1846 
   1847   if (PciDevice1->Parent == PciDevice2->Parent) {
   1848     return TRUE;
   1849   }
   1850 
   1851   return (BOOLEAN) ((PciDeviceExisted (PciDevice1->Parent, PciDevice2)|| PciDeviceExisted (PciDevice2->Parent, PciDevice1)));
   1852 }
   1853