Home | History | Annotate | Download | only in PciRootBridgeNoEnumerationDxe
      1 /*++
      2 
      3 Copyright (c) 2005 - 2012, 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     PcatPciRootBridgeIo.c
     14 
     15 Abstract:
     16 
     17     EFI PC AT PCI Root Bridge Io Protocol
     18 
     19 Revision History
     20 
     21 --*/
     22 
     23 #include "PcatPciRootBridge.h"
     24 
     25 //
     26 // Protocol Member Function Prototypes
     27 //
     28 EFI_STATUS
     29 EFIAPI
     30 PcatRootBridgeIoPollMem (
     31   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
     32   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
     33   IN  UINT64                                 Address,
     34   IN  UINT64                                 Mask,
     35   IN  UINT64                                 Value,
     36   IN  UINT64                                 Delay,
     37   OUT UINT64                                 *Result
     38   );
     39 
     40 EFI_STATUS
     41 EFIAPI
     42 PcatRootBridgeIoPollIo (
     43   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
     44   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
     45   IN  UINT64                                 Address,
     46   IN  UINT64                                 Mask,
     47   IN  UINT64                                 Value,
     48   IN  UINT64                                 Delay,
     49   OUT UINT64                                 *Result
     50   );
     51 
     52 EFI_STATUS
     53 EFIAPI
     54 PcatRootBridgeIoMemRead (
     55   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
     56   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
     57   IN     UINT64                                 Address,
     58   IN     UINTN                                  Count,
     59   IN OUT VOID                                   *Buffer
     60   );
     61 
     62 EFI_STATUS
     63 EFIAPI
     64 PcatRootBridgeIoMemWrite (
     65   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
     66   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
     67   IN     UINT64                                 Address,
     68   IN     UINTN                                  Count,
     69   IN OUT VOID                                   *Buffer
     70   );
     71 
     72 EFI_STATUS
     73 EFIAPI
     74 PcatRootBridgeIoCopyMem (
     75   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
     76   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
     77   IN UINT64                                 DestAddress,
     78   IN UINT64                                 SrcAddress,
     79   IN UINTN                                  Count
     80   );
     81 
     82 EFI_STATUS
     83 EFIAPI
     84 PcatRootBridgeIoPciRead (
     85   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
     86   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
     87   IN     UINT64                                 Address,
     88   IN     UINTN                                  Count,
     89   IN OUT VOID                                   *Buffer
     90   );
     91 
     92 EFI_STATUS
     93 EFIAPI
     94 PcatRootBridgeIoPciWrite (
     95   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
     96   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
     97   IN     UINT64                                 Address,
     98   IN     UINTN                                  Count,
     99   IN OUT VOID                                   *Buffer
    100   );
    101 
    102 EFI_STATUS
    103 EFIAPI
    104 PcatRootBridgeIoMap (
    105   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL            *This,
    106   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  Operation,
    107   IN     VOID                                       *HostAddress,
    108   IN OUT UINTN                                      *NumberOfBytes,
    109   OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,
    110   OUT    VOID                                       **Mapping
    111   );
    112 
    113 EFI_STATUS
    114 EFIAPI
    115 PcatRootBridgeIoUnmap (
    116   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
    117   IN VOID                             *Mapping
    118   );
    119 
    120 EFI_STATUS
    121 EFIAPI
    122 PcatRootBridgeIoAllocateBuffer (
    123   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
    124   IN  EFI_ALLOCATE_TYPE                Type,
    125   IN  EFI_MEMORY_TYPE                  MemoryType,
    126   IN  UINTN                            Pages,
    127   OUT VOID                             **HostAddress,
    128   IN  UINT64                           Attributes
    129   );
    130 
    131 EFI_STATUS
    132 EFIAPI
    133 PcatRootBridgeIoFreeBuffer (
    134   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
    135   IN  UINTN                            Pages,
    136   OUT VOID                             *HostAddress
    137   );
    138 
    139 EFI_STATUS
    140 EFIAPI
    141 PcatRootBridgeIoFlush (
    142   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This
    143   );
    144 
    145 EFI_STATUS
    146 EFIAPI
    147 PcatRootBridgeIoGetAttributes (
    148   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
    149   OUT UINT64                           *Supported,
    150   OUT UINT64                           *Attributes
    151   );
    152 
    153 EFI_STATUS
    154 EFIAPI
    155 PcatRootBridgeIoSetAttributes (
    156   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
    157   IN     UINT64                           Attributes,
    158   IN OUT UINT64                           *ResourceBase,
    159   IN OUT UINT64                           *ResourceLength
    160   );
    161 
    162 EFI_STATUS
    163 EFIAPI
    164 PcatRootBridgeIoConfiguration (
    165   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
    166   OUT VOID                             **Resources
    167   );
    168 
    169 //
    170 // Private Function Prototypes
    171 //
    172 EFI_STATUS
    173 EFIAPI
    174 PcatRootBridgeIoMemRW (
    175   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
    176   IN  UINTN                                  Count,
    177   IN  BOOLEAN                                InStrideFlag,
    178   IN  PTR                                    In,
    179   IN  BOOLEAN                                OutStrideFlag,
    180   OUT PTR                                    Out
    181   );
    182 
    183 EFI_STATUS
    184 PcatRootBridgeIoConstructor (
    185   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *Protocol,
    186   IN UINTN                            SegmentNumber
    187   )
    188 /*++
    189 
    190 Routine Description:
    191 
    192     Contruct the Pci Root Bridge Io protocol
    193 
    194 Arguments:
    195 
    196     Protocol - protocol to initialize
    197 
    198 Returns:
    199 
    200     None
    201 
    202 --*/
    203 {
    204   Protocol->ParentHandle   = NULL;
    205 
    206   Protocol->PollMem        = PcatRootBridgeIoPollMem;
    207   Protocol->PollIo         = PcatRootBridgeIoPollIo;
    208 
    209   Protocol->Mem.Read       = PcatRootBridgeIoMemRead;
    210   Protocol->Mem.Write      = PcatRootBridgeIoMemWrite;
    211 
    212   Protocol->Io.Read        = PcatRootBridgeIoIoRead;
    213   Protocol->Io.Write       = PcatRootBridgeIoIoWrite;
    214 
    215   Protocol->CopyMem        = PcatRootBridgeIoCopyMem;
    216 
    217   Protocol->Pci.Read       = PcatRootBridgeIoPciRead;
    218   Protocol->Pci.Write      = PcatRootBridgeIoPciWrite;
    219 
    220   Protocol->Map            = PcatRootBridgeIoMap;
    221   Protocol->Unmap          = PcatRootBridgeIoUnmap;
    222 
    223   Protocol->AllocateBuffer = PcatRootBridgeIoAllocateBuffer;
    224   Protocol->FreeBuffer     = PcatRootBridgeIoFreeBuffer;
    225 
    226   Protocol->Flush          = PcatRootBridgeIoFlush;
    227 
    228   Protocol->GetAttributes  = PcatRootBridgeIoGetAttributes;
    229   Protocol->SetAttributes  = PcatRootBridgeIoSetAttributes;
    230 
    231   Protocol->Configuration  = PcatRootBridgeIoConfiguration;
    232 
    233   Protocol->SegmentNumber  = (UINT32)SegmentNumber;
    234 
    235   return EFI_SUCCESS;
    236 }
    237 
    238 EFI_STATUS
    239 EFIAPI
    240 PcatRootBridgeIoPollMem (
    241   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
    242   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
    243   IN  UINT64                                 Address,
    244   IN  UINT64                                 Mask,
    245   IN  UINT64                                 Value,
    246   IN  UINT64                                 Delay,
    247   OUT UINT64                                 *Result
    248   )
    249 {
    250   EFI_STATUS  Status;
    251   UINT64      NumberOfTicks;
    252   UINT32      Remainder;
    253 
    254   if (Result == NULL) {
    255     return EFI_INVALID_PARAMETER;
    256   }
    257 
    258 
    259   if ((UINT32)Width > EfiPciWidthUint64) {
    260     return EFI_INVALID_PARAMETER;
    261   }
    262   //
    263   // No matter what, always do a single poll.
    264   //
    265   Status = This->Mem.Read (This, Width, Address, 1, Result);
    266   if ( EFI_ERROR(Status) ) {
    267     return Status;
    268   }
    269   if ( (*Result & Mask) == Value ) {
    270     return EFI_SUCCESS;
    271   }
    272 
    273   if (Delay == 0) {
    274     return EFI_SUCCESS;
    275   } else {
    276 
    277     NumberOfTicks = DivU64x32Remainder (Delay, 100, &Remainder);
    278     if ( Remainder !=0 ) {
    279       NumberOfTicks += 1;
    280     }
    281     NumberOfTicks += 1;
    282 
    283     while ( NumberOfTicks ) {
    284 
    285       gBS->Stall (10);
    286 
    287       Status = This->Mem.Read (This, Width, Address, 1, Result);
    288       if ( EFI_ERROR(Status) ) {
    289         return Status;
    290       }
    291 
    292       if ( (*Result & Mask) == Value ) {
    293         return EFI_SUCCESS;
    294       }
    295 
    296       NumberOfTicks -= 1;
    297     }
    298   }
    299   return EFI_TIMEOUT;
    300 }
    301 
    302 EFI_STATUS
    303 EFIAPI
    304 PcatRootBridgeIoPollIo (
    305   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
    306   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
    307   IN  UINT64                                 Address,
    308   IN  UINT64                                 Mask,
    309   IN  UINT64                                 Value,
    310   IN  UINT64                                 Delay,
    311   OUT UINT64                                 *Result
    312   )
    313 {
    314   EFI_STATUS  Status;
    315   UINT64      NumberOfTicks;
    316   UINT32       Remainder;
    317 
    318   if (Result == NULL) {
    319     return EFI_INVALID_PARAMETER;
    320   }
    321 
    322   if ((UINT32)Width > EfiPciWidthUint64) {
    323     return EFI_INVALID_PARAMETER;
    324   }
    325   //
    326   // No matter what, always do a single poll.
    327   //
    328   Status = This->Io.Read (This, Width, Address, 1, Result);
    329   if ( EFI_ERROR(Status) ) {
    330     return Status;
    331   }
    332   if ( (*Result & Mask) == Value ) {
    333     return EFI_SUCCESS;
    334   }
    335 
    336   if (Delay == 0) {
    337     return EFI_SUCCESS;
    338   } else {
    339 
    340     NumberOfTicks = DivU64x32Remainder (Delay, 100, &Remainder);
    341     if ( Remainder !=0 ) {
    342       NumberOfTicks += 1;
    343     }
    344     NumberOfTicks += 1;
    345 
    346     while ( NumberOfTicks ) {
    347 
    348       gBS->Stall(10);
    349 
    350       Status = This->Io.Read (This, Width, Address, 1, Result);
    351       if ( EFI_ERROR(Status) ) {
    352         return Status;
    353       }
    354 
    355       if ( (*Result & Mask) == Value ) {
    356         return EFI_SUCCESS;
    357       }
    358 
    359       NumberOfTicks -= 1;
    360     }
    361   }
    362   return EFI_TIMEOUT;
    363 }
    364 
    365 BOOLEAN
    366 PcatRootBridgeMemAddressValid (
    367   IN PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData,
    368   IN UINT64                         Address
    369   )
    370 {
    371   if ((Address >= PrivateData->PciExpressBaseAddress) && (Address < PrivateData->PciExpressBaseAddress + 0x10000000)) {
    372     return TRUE;
    373   }
    374   if ((Address >= PrivateData->MemBase) && (Address < PrivateData->MemLimit)) {
    375     return TRUE;
    376   }
    377 
    378   return FALSE;
    379 }
    380 
    381 EFI_STATUS
    382 EFIAPI
    383 PcatRootBridgeIoMemRead (
    384   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
    385   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
    386   IN     UINT64                                 Address,
    387   IN     UINTN                                  Count,
    388   IN OUT VOID                                   *Buffer
    389   )
    390 {
    391   PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
    392   UINTN                          AlignMask;
    393   PTR                            In;
    394   PTR                            Out;
    395 
    396   if ( Buffer == NULL ) {
    397     return EFI_INVALID_PARAMETER;
    398   }
    399 
    400   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
    401 
    402   if (!PcatRootBridgeMemAddressValid (PrivateData, Address)) {
    403     return EFI_INVALID_PARAMETER;
    404   }
    405 
    406   AlignMask = (1 << (Width & 0x03)) - 1;
    407   if (Address & AlignMask) {
    408     return EFI_INVALID_PARAMETER;
    409   }
    410 
    411   Address += PrivateData->PhysicalMemoryBase;
    412 
    413   In.buf  = Buffer;
    414   Out.buf = (VOID *)(UINTN) Address;
    415   if ((UINT32)Width <= EfiPciWidthUint64) {
    416     return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
    417   }
    418   if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
    419     return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
    420   }
    421   if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
    422     return PcatRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
    423   }
    424 
    425   return EFI_INVALID_PARAMETER;
    426 }
    427 
    428 EFI_STATUS
    429 EFIAPI
    430 PcatRootBridgeIoMemWrite (
    431   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
    432   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
    433   IN     UINT64                                 Address,
    434   IN     UINTN                                  Count,
    435   IN OUT VOID                                   *Buffer
    436   )
    437 {
    438   PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
    439   UINTN  AlignMask;
    440   PTR    In;
    441   PTR    Out;
    442 
    443   if ( Buffer == NULL ) {
    444     return EFI_INVALID_PARAMETER;
    445   }
    446 
    447   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
    448 
    449   if (!PcatRootBridgeMemAddressValid (PrivateData, Address)) {
    450     return EFI_INVALID_PARAMETER;
    451   }
    452 
    453   AlignMask = (1 << (Width & 0x03)) - 1;
    454   if (Address & AlignMask) {
    455     return EFI_INVALID_PARAMETER;
    456   }
    457 
    458   Address += PrivateData->PhysicalMemoryBase;
    459 
    460   In.buf  = (VOID *)(UINTN) Address;
    461   Out.buf = Buffer;
    462   if ((UINT32)Width <= EfiPciWidthUint64) {
    463     return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
    464   }
    465   if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
    466     return PcatRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
    467   }
    468   if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {
    469     return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
    470   }
    471 
    472   return EFI_INVALID_PARAMETER;
    473 }
    474 
    475 EFI_STATUS
    476 EFIAPI
    477 PcatRootBridgeIoCopyMem (
    478   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
    479   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
    480   IN UINT64                                 DestAddress,
    481   IN UINT64                                 SrcAddress,
    482   IN UINTN                                  Count
    483   )
    484 
    485 {
    486   EFI_STATUS  Status;
    487   BOOLEAN     Direction;
    488   UINTN       Stride;
    489   UINTN       Index;
    490   UINT64      Result;
    491 
    492   if ((UINT32)Width > EfiPciWidthUint64) {
    493     return EFI_INVALID_PARAMETER;
    494   }
    495 
    496   if (DestAddress == SrcAddress) {
    497     return EFI_SUCCESS;
    498   }
    499 
    500   Stride = (UINTN)1 << Width;
    501 
    502   Direction = TRUE;
    503   if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {
    504     Direction   = FALSE;
    505     SrcAddress  = SrcAddress  + (Count-1) * Stride;
    506     DestAddress = DestAddress + (Count-1) * Stride;
    507   }
    508 
    509   for (Index = 0;Index < Count;Index++) {
    510     Status = PcatRootBridgeIoMemRead (
    511                This,
    512                Width,
    513                SrcAddress,
    514                1,
    515                &Result
    516                );
    517     if (EFI_ERROR (Status)) {
    518       return Status;
    519     }
    520     Status = PcatRootBridgeIoMemWrite (
    521                This,
    522                Width,
    523                DestAddress,
    524                1,
    525                &Result
    526                );
    527     if (EFI_ERROR (Status)) {
    528       return Status;
    529     }
    530     if (Direction) {
    531       SrcAddress  += Stride;
    532       DestAddress += Stride;
    533     } else {
    534       SrcAddress  -= Stride;
    535       DestAddress -= Stride;
    536     }
    537   }
    538   return EFI_SUCCESS;
    539 }
    540 
    541 EFI_STATUS
    542 EFIAPI
    543 PcatRootBridgeIoPciRead (
    544   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
    545   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
    546   IN     UINT64                                 Address,
    547   IN     UINTN                                  Count,
    548   IN OUT VOID                                   *Buffer
    549   )
    550 {
    551   if (Buffer == NULL) {
    552     return EFI_INVALID_PARAMETER;
    553   }
    554 
    555   return PcatRootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
    556 }
    557 
    558 EFI_STATUS
    559 EFIAPI
    560 PcatRootBridgeIoPciWrite (
    561   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
    562   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
    563   IN     UINT64                                 Address,
    564   IN     UINTN                                  Count,
    565   IN OUT VOID                                   *Buffer
    566   )
    567 {
    568   if (Buffer == NULL) {
    569     return EFI_INVALID_PARAMETER;
    570   }
    571 
    572   return PcatRootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
    573 }
    574 
    575 EFI_STATUS
    576 EFIAPI
    577 PcatRootBridgeIoMap (
    578   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL            *This,
    579   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  Operation,
    580   IN     VOID                                       *HostAddress,
    581   IN OUT UINTN                                      *NumberOfBytes,
    582   OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,
    583   OUT    VOID                                       **Mapping
    584   )
    585 
    586 {
    587   EFI_STATUS            Status;
    588   EFI_PHYSICAL_ADDRESS  PhysicalAddress;
    589   MAP_INFO              *MapInfo;
    590   MAP_INFO_INSTANCE    *MapInstance;
    591   PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
    592 
    593   if ( HostAddress == NULL || NumberOfBytes == NULL ||
    594        DeviceAddress == NULL || Mapping == NULL ) {
    595 
    596     return EFI_INVALID_PARAMETER;
    597   }
    598 
    599   //
    600   // Perform a fence operation to make sure all memory operations are flushed
    601   //
    602   MemoryFence();
    603 
    604   //
    605   // Initialize the return values to their defaults
    606   //
    607   *Mapping = NULL;
    608 
    609   //
    610   // Make sure that Operation is valid
    611   //
    612   if ((UINT32)Operation >= EfiPciOperationMaximum) {
    613     return EFI_INVALID_PARAMETER;
    614   }
    615 
    616   //
    617   // Most PCAT like chipsets can not handle performing DMA above 4GB.
    618   // If any part of the DMA transfer being mapped is above 4GB, then
    619   // map the DMA transfer to a buffer below 4GB.
    620   //
    621   PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;
    622   if ((PhysicalAddress + *NumberOfBytes) > 0x100000000ULL) {
    623 
    624     //
    625     // Common Buffer operations can not be remapped.  If the common buffer
    626     // if above 4GB, then it is not possible to generate a mapping, so return
    627     // an error.
    628     //
    629     if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {
    630       return EFI_UNSUPPORTED;
    631     }
    632 
    633     //
    634     // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
    635     // called later.
    636     //
    637     Status = gBS->AllocatePool (
    638                     EfiBootServicesData,
    639                     sizeof(MAP_INFO),
    640                     (VOID **)&MapInfo
    641                     );
    642     if (EFI_ERROR (Status)) {
    643       *NumberOfBytes = 0;
    644       return Status;
    645     }
    646 
    647     //
    648     // Return a pointer to the MAP_INFO structure in Mapping
    649     //
    650     *Mapping = MapInfo;
    651 
    652     //
    653     // Initialize the MAP_INFO structure
    654     //
    655     MapInfo->Operation         = Operation;
    656     MapInfo->NumberOfBytes     = *NumberOfBytes;
    657     MapInfo->NumberOfPages     = EFI_SIZE_TO_PAGES(*NumberOfBytes);
    658     MapInfo->HostAddress       = PhysicalAddress;
    659     MapInfo->MappedHostAddress = 0x00000000ffffffff;
    660 
    661     //
    662     // Allocate a buffer below 4GB to map the transfer to.
    663     //
    664     Status = gBS->AllocatePages (
    665                     AllocateMaxAddress,
    666                     EfiBootServicesData,
    667                     MapInfo->NumberOfPages,
    668                     &MapInfo->MappedHostAddress
    669                     );
    670     if (EFI_ERROR(Status)) {
    671       gBS->FreePool (MapInfo);
    672       *NumberOfBytes = 0;
    673       return Status;
    674     }
    675 
    676     //
    677     // If this is a read operation from the Bus Master's point of view,
    678     // then copy the contents of the real buffer into the mapped buffer
    679     // so the Bus Master can read the contents of the real buffer.
    680     //
    681     if (Operation == EfiPciOperationBusMasterRead || Operation == EfiPciOperationBusMasterRead64) {
    682       CopyMem (
    683         (VOID *)(UINTN)MapInfo->MappedHostAddress,
    684         (VOID *)(UINTN)MapInfo->HostAddress,
    685         MapInfo->NumberOfBytes
    686         );
    687     }
    688 
    689 
    690   Status =gBS->AllocatePool (
    691                     EfiBootServicesData,
    692                     sizeof(MAP_INFO_INSTANCE),
    693                     (VOID **)&MapInstance
    694                     );
    695     if (EFI_ERROR(Status)) {
    696       gBS->FreePages (MapInfo->MappedHostAddress,MapInfo->NumberOfPages);
    697       gBS->FreePool (MapInfo);
    698       *NumberOfBytes = 0;
    699       return Status;
    700     }
    701 
    702     MapInstance->Map=MapInfo;
    703     PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
    704     InsertTailList(&PrivateData->MapInfo,&MapInstance->Link);
    705 
    706   //
    707     // The DeviceAddress is the address of the maped buffer below 4GB
    708     //
    709     *DeviceAddress = MapInfo->MappedHostAddress;
    710   } else {
    711     //
    712     // The transfer is below 4GB, so the DeviceAddress is simply the HostAddress
    713     //
    714     *DeviceAddress = PhysicalAddress;
    715   }
    716 
    717   //
    718   // Perform a fence operation to make sure all memory operations are flushed
    719   //
    720   MemoryFence();
    721 
    722   return EFI_SUCCESS;
    723 }
    724 
    725 EFI_STATUS
    726 EFIAPI
    727 PcatRootBridgeIoUnmap (
    728   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
    729   IN VOID                             *Mapping
    730   )
    731 
    732 {
    733   MAP_INFO    *MapInfo;
    734   PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
    735   LIST_ENTRY *Link;
    736 
    737   //
    738   // Perform a fence operation to make sure all memory operations are flushed
    739   //
    740   MemoryFence();
    741 
    742   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
    743   //
    744   // See if the Map() operation associated with this Unmap() required a mapping buffer.
    745   // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.
    746   //
    747   if (Mapping != NULL) {
    748     //
    749     // Get the MAP_INFO structure from Mapping
    750     //
    751     MapInfo = (MAP_INFO *)Mapping;
    752 
    753   for (Link = PrivateData->MapInfo.ForwardLink; Link != &PrivateData->MapInfo; Link = Link->ForwardLink) {
    754       if (((MAP_INFO_INSTANCE*)Link)->Map == MapInfo)
    755         break;
    756     }
    757 
    758     if (Link == &PrivateData->MapInfo) {
    759       return EFI_INVALID_PARAMETER;
    760   }
    761 
    762     RemoveEntryList(Link);
    763     ((MAP_INFO_INSTANCE*)Link)->Map = NULL;
    764     gBS->FreePool((MAP_INFO_INSTANCE*)Link);
    765 
    766     //
    767     // If this is a write operation from the Bus Master's point of view,
    768     // then copy the contents of the mapped buffer into the real buffer
    769     // so the processor can read the contents of the real buffer.
    770     //
    771     if (MapInfo->Operation == EfiPciOperationBusMasterWrite || MapInfo->Operation == EfiPciOperationBusMasterWrite64) {
    772       CopyMem (
    773         (VOID *)(UINTN)MapInfo->HostAddress,
    774         (VOID *)(UINTN)MapInfo->MappedHostAddress,
    775         MapInfo->NumberOfBytes
    776         );
    777     }
    778 
    779     //
    780     // Free the mapped buffer and the MAP_INFO structure.
    781     //
    782     gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);
    783     gBS->FreePool (Mapping);
    784   }
    785 
    786   //
    787   // Perform a fence operation to make sure all memory operations are flushed
    788   //
    789   MemoryFence();
    790 
    791   return EFI_SUCCESS;
    792 }
    793 
    794 EFI_STATUS
    795 EFIAPI
    796 PcatRootBridgeIoAllocateBuffer (
    797   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
    798   IN  EFI_ALLOCATE_TYPE                Type,
    799   IN  EFI_MEMORY_TYPE                  MemoryType,
    800   IN  UINTN                            Pages,
    801   OUT VOID                             **HostAddress,
    802   IN  UINT64                           Attributes
    803   )
    804 {
    805   EFI_STATUS            Status;
    806   EFI_PHYSICAL_ADDRESS  PhysicalAddress;
    807 
    808   //
    809   // Validate Attributes
    810   //
    811   if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {
    812     return EFI_UNSUPPORTED;
    813   }
    814 
    815   //
    816   // Check for invalid inputs
    817   //
    818   if (HostAddress == NULL) {
    819     return EFI_INVALID_PARAMETER;
    820   }
    821 
    822   //
    823   // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
    824   //
    825   if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) {
    826     return EFI_INVALID_PARAMETER;
    827   }
    828 
    829   //
    830   // Limit allocations to memory below 4GB
    831   //
    832   PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(0xffffffff);
    833 
    834   Status = gBS->AllocatePages (AllocateMaxAddress, MemoryType, Pages, &PhysicalAddress);
    835   if (EFI_ERROR (Status)) {
    836     return Status;
    837   }
    838 
    839   *HostAddress = (VOID *)(UINTN)PhysicalAddress;
    840 
    841   return EFI_SUCCESS;
    842 }
    843 
    844 EFI_STATUS
    845 EFIAPI
    846 PcatRootBridgeIoFreeBuffer (
    847   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
    848   IN  UINTN                            Pages,
    849   OUT VOID                             *HostAddress
    850   )
    851 
    852 {
    853 
    854   if( HostAddress == NULL ){
    855      return EFI_INVALID_PARAMETER;
    856   }
    857   return gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, Pages);
    858 }
    859 
    860 EFI_STATUS
    861 EFIAPI
    862 PcatRootBridgeIoFlush (
    863   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This
    864   )
    865 
    866 {
    867   //
    868   // Perform a fence operation to make sure all memory operations are flushed
    869   //
    870   MemoryFence();
    871 
    872   return EFI_SUCCESS;
    873 }
    874 
    875 EFI_STATUS
    876 EFIAPI
    877 PcatRootBridgeIoGetAttributes (
    878   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
    879   OUT UINT64                           *Supported,  OPTIONAL
    880   OUT UINT64                           *Attributes
    881   )
    882 
    883 {
    884   PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
    885 
    886   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
    887 
    888   if (Attributes == NULL && Supported == NULL) {
    889     return EFI_INVALID_PARAMETER;
    890   }
    891 
    892   //
    893   // Supported is an OPTIONAL parameter.  See if it is NULL
    894   //
    895   if (Supported) {
    896     //
    897     // This is a generic driver for a PC-AT class system.  It does not have any
    898     // chipset specific knowlegde, so none of the attributes can be set or
    899     // cleared.  Any attempt to set attribute that are already set will succeed,
    900     // and any attempt to set an attribute that is not supported will fail.
    901     //
    902     *Supported = PrivateData->Attributes;
    903   }
    904 
    905   //
    906   // Set Attrbutes to the attributes detected when the PCI Root Bridge was initialized
    907   //
    908 
    909   if (Attributes) {
    910     *Attributes = PrivateData->Attributes;
    911   }
    912 
    913 
    914   return EFI_SUCCESS;
    915 }
    916 
    917 EFI_STATUS
    918 EFIAPI
    919 PcatRootBridgeIoSetAttributes (
    920   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
    921   IN     UINT64                           Attributes,
    922   IN OUT UINT64                           *ResourceBase,
    923   IN OUT UINT64                           *ResourceLength
    924   )
    925 
    926 {
    927   PCAT_PCI_ROOT_BRIDGE_INSTANCE   *PrivateData;
    928 
    929   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
    930 
    931   //
    932   // This is a generic driver for a PC-AT class system.  It does not have any
    933   // chipset specific knowlegde, so none of the attributes can be set or
    934   // cleared.  Any attempt to set attribute that are already set will succeed,
    935   // and any attempt to set an attribute that is not supported will fail.
    936   //
    937   if (Attributes & (~PrivateData->Attributes)) {
    938     return EFI_UNSUPPORTED;
    939   }
    940 
    941   return EFI_SUCCESS;
    942 }
    943 
    944 EFI_STATUS
    945 EFIAPI
    946 PcatRootBridgeIoConfiguration (
    947   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
    948   OUT VOID                             **Resources
    949   )
    950 
    951 {
    952   PCAT_PCI_ROOT_BRIDGE_INSTANCE   *PrivateData;
    953 
    954   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
    955 
    956   *Resources = PrivateData->Configuration;
    957 
    958   return EFI_SUCCESS;
    959 }
    960 
    961 //
    962 // Internal function
    963 //
    964 
    965 EFI_STATUS
    966 EFIAPI
    967 PcatRootBridgeIoMemRW (
    968   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
    969   IN  UINTN                                  Count,
    970   IN  BOOLEAN                                InStrideFlag,
    971   IN  PTR                                    In,
    972   IN  BOOLEAN                                OutStrideFlag,
    973   OUT PTR                                    Out
    974   )
    975 /*++
    976 
    977 Routine Description:
    978 
    979   Private service to provide the memory read/write
    980 
    981 Arguments:
    982 
    983   Width of the Memory Access
    984   Count of the number of accesses to perform
    985 
    986 Returns:
    987 
    988   Status
    989 
    990   EFI_SUCCESS           - Successful transaction
    991   EFI_INVALID_PARAMETER - Unsupported width and address combination
    992 
    993 --*/
    994 {
    995   UINTN  Stride;
    996   UINTN  InStride;
    997   UINTN  OutStride;
    998 
    999 
   1000   Width     = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
   1001   Stride    = (UINTN)1 << Width;
   1002   InStride  = InStrideFlag  ? Stride : 0;
   1003   OutStride = OutStrideFlag ? Stride : 0;
   1004 
   1005   //
   1006   // Loop for each iteration and move the data
   1007   //
   1008   switch (Width) {
   1009   case EfiPciWidthUint8:
   1010     for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
   1011       MemoryFence();
   1012       *In.ui8 = *Out.ui8;
   1013       MemoryFence();
   1014     }
   1015     break;
   1016   case EfiPciWidthUint16:
   1017     for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
   1018       MemoryFence();
   1019       *In.ui16 = *Out.ui16;
   1020       MemoryFence();
   1021     }
   1022     break;
   1023   case EfiPciWidthUint32:
   1024     for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
   1025       MemoryFence();
   1026       *In.ui32 = *Out.ui32;
   1027       MemoryFence();
   1028     }
   1029     break;
   1030   default:
   1031     return EFI_INVALID_PARAMETER;
   1032   }
   1033 
   1034   return EFI_SUCCESS;
   1035 }
   1036 
   1037