Home | History | Annotate | Download | only in PciRootBridgeNoEnumerationDxe
      1 /*++
      2 
      3 Copyright (c) 2006 - 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 
     14     DeviceIo.c
     15 
     16 Abstract:
     17 
     18     EFI PC-AT PCI Device IO driver
     19 
     20 --*/
     21 #include "PcatPciRootBridge.h"
     22 #include "DeviceIo.h"
     23 
     24 EFI_STATUS
     25 DeviceIoConstructor (
     26   IN EFI_HANDLE                      Handle,
     27   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
     28   IN EFI_DEVICE_PATH_PROTOCOL        *DevicePath,
     29   IN UINT16                          PrimaryBus,
     30   IN UINT16                          SubordinateBus
     31   )
     32 /*++
     33 
     34 Routine Description:
     35 
     36   Initialize and install a Device IO protocol on a empty device path handle.
     37 
     38 Arguments:
     39 
     40   Handle               - Handle of PCI RootBridge IO instance
     41   PciRootBridgeIo      - PCI RootBridge IO instance
     42   DevicePath           - Device Path of PCI RootBridge IO instance
     43   PrimaryBus           - Primary Bus
     44   SubordinateBus       - Subordinate Bus
     45 
     46 Returns:
     47 
     48   EFI_SUCCESS          -  This driver is added to ControllerHandle.
     49   EFI_ALREADY_STARTED  -  This driver is already running on ControllerHandle.
     50   Others               -  This driver does not support this device.
     51 
     52 --*/
     53 {
     54   EFI_STATUS                      Status;
     55   DEVICE_IO_PRIVATE_DATA          *Private;
     56 
     57   //
     58   // Initialize the Device IO device instance.
     59   //
     60   Private = AllocateZeroPool (sizeof (DEVICE_IO_PRIVATE_DATA));
     61   if (Private == NULL) {
     62     return EFI_OUT_OF_RESOURCES;
     63   }
     64 
     65   Private->Signature                = DEVICE_IO_PRIVATE_DATA_SIGNATURE;
     66   Private->Handle                   = Handle;
     67   Private->PciRootBridgeIo          = PciRootBridgeIo;
     68   Private->DevicePath               = DevicePath;
     69   Private->PrimaryBus               = PrimaryBus;
     70   Private->SubordinateBus           = SubordinateBus;
     71 
     72   Private->DeviceIo.Mem.Read        = DeviceIoMemRead;
     73   Private->DeviceIo.Mem.Write       = DeviceIoMemWrite;
     74   Private->DeviceIo.Io.Read         = DeviceIoIoRead;
     75   Private->DeviceIo.Io.Write        = DeviceIoIoWrite;
     76   Private->DeviceIo.Pci.Read        = DeviceIoPciRead;
     77   Private->DeviceIo.Pci.Write       = DeviceIoPciWrite;
     78   Private->DeviceIo.PciDevicePath   = DeviceIoPciDevicePath;
     79   Private->DeviceIo.Map             = DeviceIoMap;
     80   Private->DeviceIo.Unmap           = DeviceIoUnmap;
     81   Private->DeviceIo.AllocateBuffer  = DeviceIoAllocateBuffer;
     82   Private->DeviceIo.Flush           = DeviceIoFlush;
     83   Private->DeviceIo.FreeBuffer      = DeviceIoFreeBuffer;
     84 
     85   //
     86   // Install protocol interfaces for the Device IO device.
     87   //
     88   Status = gBS->InstallMultipleProtocolInterfaces (
     89                   &Private->Handle,
     90                   &gEfiDeviceIoProtocolGuid,
     91                   &Private->DeviceIo,
     92                   NULL
     93                   );
     94   ASSERT_EFI_ERROR (Status);
     95 
     96   return Status;
     97 }
     98 
     99 EFI_STATUS
    100 EFIAPI
    101 DeviceIoMemRead (
    102   IN     EFI_DEVICE_IO_PROTOCOL   *This,
    103   IN     EFI_IO_WIDTH             Width,
    104   IN     UINT64                   Address,
    105   IN     UINTN                    Count,
    106   IN OUT VOID                     *Buffer
    107   )
    108 /*++
    109 
    110 Routine Description:
    111 
    112   Perform reading memory mapped I/O space of device.
    113 
    114 Arguments:
    115 
    116   This     -  A pointer to EFI_DEVICE_IO protocol instance.
    117   Width    -  Width of I/O operations.
    118   Address  -  The base address of I/O operations.
    119   Count    -  The number of I/O operations to perform.
    120               Bytes moves is Width size * Count, starting at Address.
    121   Buffer   -  The destination buffer to store results.
    122 
    123 Returns:
    124 
    125   EFI_SUCCESS            -  The data was read from the device.
    126   EFI_INVALID_PARAMETER  -  Width is invalid.
    127   EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.
    128 
    129 --*/
    130 {
    131   EFI_STATUS              Status;
    132   DEVICE_IO_PRIVATE_DATA  *Private;
    133 
    134   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
    135 
    136   if (Width > MMIO_COPY_UINT64) {
    137     return EFI_INVALID_PARAMETER;
    138   }
    139   if (Width >= MMIO_COPY_UINT8) {
    140     Width = (EFI_IO_WIDTH) (Width - MMIO_COPY_UINT8);
    141     Status = Private->PciRootBridgeIo->CopyMem (
    142                                          Private->PciRootBridgeIo,
    143                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
    144                                          (UINT64)(UINTN) Buffer,
    145                                          Address,
    146                                          Count
    147                                          );
    148   } else {
    149     Status = Private->PciRootBridgeIo->Mem.Read (
    150                                              Private->PciRootBridgeIo,
    151                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
    152                                              Address,
    153                                              Count,
    154                                              Buffer
    155                                              );
    156   }
    157 
    158   return Status;
    159 }
    160 
    161 
    162 
    163 EFI_STATUS
    164 EFIAPI
    165 DeviceIoMemWrite (
    166   IN     EFI_DEVICE_IO_PROTOCOL    *This,
    167   IN     EFI_IO_WIDTH              Width,
    168   IN     UINT64                    Address,
    169   IN     UINTN                     Count,
    170   IN OUT VOID                      *Buffer
    171   )
    172 /*++
    173 
    174 Routine Description:
    175 
    176   Perform writing memory mapped I/O space of device.
    177 
    178 Arguments:
    179 
    180   This     -  A pointer to EFI_DEVICE_IO protocol instance.
    181   Width    -  Width of I/O operations.
    182   Address  -  The base address of I/O operations.
    183   Count    -  The number of I/O operations to perform.
    184               Bytes moves is Width size * Count, starting at Address.
    185   Buffer   -  The source buffer of data to be written.
    186 
    187 Returns:
    188 
    189   EFI_SUCCESS            -  The data was written to the device.
    190   EFI_INVALID_PARAMETER  -  Width is invalid.
    191   EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.
    192 
    193 --*/
    194 {
    195   EFI_STATUS              Status;
    196   DEVICE_IO_PRIVATE_DATA  *Private;
    197 
    198   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
    199 
    200   if (Width > MMIO_COPY_UINT64) {
    201     return EFI_INVALID_PARAMETER;
    202   }
    203   if (Width >= MMIO_COPY_UINT8) {
    204     Width = (EFI_IO_WIDTH) (Width - MMIO_COPY_UINT8);
    205     Status = Private->PciRootBridgeIo->CopyMem (
    206                                          Private->PciRootBridgeIo,
    207                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
    208                                          Address,
    209                                          (UINT64)(UINTN) Buffer,
    210                                          Count
    211                                          );
    212   } else {
    213     Status = Private->PciRootBridgeIo->Mem.Write (
    214                                              Private->PciRootBridgeIo,
    215                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
    216                                              Address,
    217                                              Count,
    218                                              Buffer
    219                                              );
    220   }
    221 
    222   return Status;
    223 }
    224 
    225 EFI_STATUS
    226 EFIAPI
    227 DeviceIoIoRead (
    228   IN     EFI_DEVICE_IO_PROTOCOL   *This,
    229   IN     EFI_IO_WIDTH             Width,
    230   IN     UINT64                   Address,
    231   IN     UINTN                    Count,
    232   IN OUT VOID                     *Buffer
    233   )
    234 /*++
    235 
    236 Routine Description:
    237 
    238   Perform reading I/O space of device.
    239 
    240 Arguments:
    241 
    242   This     -  A pointer to EFI_DEVICE_IO protocol instance.
    243   Width    -  Width of I/O operations.
    244   Address  -  The base address of I/O operations.
    245   Count    -  The number of I/O operations to perform.
    246               Bytes moves is Width size * Count, starting at Address.
    247   Buffer   -  The destination buffer to store results.
    248 
    249 Returns:
    250 
    251   EFI_SUCCESS            -  The data was read from the device.
    252   EFI_INVALID_PARAMETER  -  Width is invalid.
    253   EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.
    254 
    255 --*/
    256 {
    257   EFI_STATUS              Status;
    258   DEVICE_IO_PRIVATE_DATA  *Private;
    259 
    260   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
    261 
    262   if (Width >= MMIO_COPY_UINT8) {
    263     return EFI_INVALID_PARAMETER;
    264   }
    265 
    266   Status = Private->PciRootBridgeIo->Io.Read (
    267                                           Private->PciRootBridgeIo,
    268                                           (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
    269                                           Address,
    270                                           Count,
    271                                           Buffer
    272                                           );
    273 
    274   return Status;
    275 }
    276 
    277 EFI_STATUS
    278 EFIAPI
    279 DeviceIoIoWrite (
    280   IN     EFI_DEVICE_IO_PROTOCOL    *This,
    281   IN     EFI_IO_WIDTH              Width,
    282   IN     UINT64                    Address,
    283   IN     UINTN                     Count,
    284   IN OUT VOID                      *Buffer
    285   )
    286 /*++
    287 
    288 Routine Description:
    289 
    290   Perform writing I/O space of device.
    291 
    292 Arguments:
    293 
    294   This     -  A pointer to EFI_DEVICE_IO protocol instance.
    295   Width    -  Width of I/O operations.
    296   Address  -  The base address of I/O operations.
    297   Count    -  The number of I/O operations to perform.
    298               Bytes moves is Width size * Count, starting at Address.
    299   Buffer   -  The source buffer of data to be written.
    300 
    301 Returns:
    302 
    303   EFI_SUCCESS            -  The data was written to the device.
    304   EFI_INVALID_PARAMETER  -  Width is invalid.
    305   EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.
    306 
    307 --*/
    308 {
    309   EFI_STATUS              Status;
    310   DEVICE_IO_PRIVATE_DATA  *Private;
    311 
    312   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
    313 
    314   if (Width >= MMIO_COPY_UINT8) {
    315     return EFI_INVALID_PARAMETER;
    316   }
    317 
    318   Status = Private->PciRootBridgeIo->Io.Write (
    319                                           Private->PciRootBridgeIo,
    320                                           (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
    321                                           Address,
    322                                           Count,
    323                                           Buffer
    324                                           );
    325 
    326   return Status;
    327 }
    328 
    329 EFI_STATUS
    330 EFIAPI
    331 DeviceIoPciRead (
    332   IN     EFI_DEVICE_IO_PROTOCOL   *This,
    333   IN     EFI_IO_WIDTH             Width,
    334   IN     UINT64                   Address,
    335   IN     UINTN                    Count,
    336   IN OUT VOID                     *Buffer
    337   )
    338 /*++
    339 
    340 Routine Description:
    341 
    342   Perform reading PCI configuration space of device
    343 
    344 Arguments:
    345 
    346   This     -  A pointer to EFI_DEVICE_IO protocol instance.
    347   Width    -  Width of I/O operations.
    348   Address  -  The base address of I/O operations.
    349   Count    -  The number of I/O operations to perform.
    350               Bytes moves is Width size * Count, starting at Address.
    351   Buffer   -  The destination buffer to store results.
    352 
    353 Returns:
    354 
    355   EFI_SUCCESS            -  The data was read from the device.
    356   EFI_INVALID_PARAMETER  -  Width is invalid.
    357   EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.
    358 
    359 --*/
    360 {
    361   EFI_STATUS              Status;
    362   DEVICE_IO_PRIVATE_DATA  *Private;
    363 
    364   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
    365 
    366   if ((UINT32)Width >= MMIO_COPY_UINT8) {
    367     return EFI_INVALID_PARAMETER;
    368   }
    369 
    370   Status = Private->PciRootBridgeIo->Pci.Read (
    371                                            Private->PciRootBridgeIo,
    372                                            (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
    373                                            Address,
    374                                            Count,
    375                                            Buffer
    376                                            );
    377 
    378   return Status;
    379 }
    380 
    381 EFI_STATUS
    382 EFIAPI
    383 DeviceIoPciWrite (
    384   IN     EFI_DEVICE_IO_PROTOCOL    *This,
    385   IN     EFI_IO_WIDTH              Width,
    386   IN     UINT64                    Address,
    387   IN     UINTN                     Count,
    388   IN OUT VOID                      *Buffer
    389   )
    390 /*++
    391 
    392 Routine Description:
    393 
    394   Perform writing PCI configuration space of device.
    395 
    396 Arguments:
    397 
    398   This     -  A pointer to EFI_DEVICE_IO protocol instance.
    399   Width    -  Width of I/O operations.
    400   Address  -  The base address of I/O operations.
    401   Count    -  The number of I/O operations to perform.
    402               Bytes moves is Width size * Count, starting at Address.
    403   Buffer   -  The source buffer of data to be written.
    404 
    405 Returns:
    406 
    407   EFI_SUCCESS            -  The data was written to the device.
    408   EFI_INVALID_PARAMETER  -  Width is invalid.
    409   EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.
    410 
    411 --*/
    412 {
    413   EFI_STATUS              Status;
    414   DEVICE_IO_PRIVATE_DATA  *Private;
    415 
    416   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
    417 
    418   if ((UINT32)Width >= MMIO_COPY_UINT8) {
    419     return EFI_INVALID_PARAMETER;
    420   }
    421 
    422   Status = Private->PciRootBridgeIo->Pci.Write (
    423                                            Private->PciRootBridgeIo,
    424                                            (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
    425                                            Address,
    426                                            Count,
    427                                            Buffer
    428                                            );
    429 
    430   return Status;
    431 }
    432 
    433 EFI_DEVICE_PATH_PROTOCOL *
    434 AppendPciDevicePath (
    435   IN     DEVICE_IO_PRIVATE_DATA    *Private,
    436   IN     UINT8                     Bus,
    437   IN     UINT8                     Device,
    438   IN     UINT8                     Function,
    439   IN     EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
    440   IN OUT UINT16                    *BridgePrimaryBus,
    441   IN OUT UINT16                    *BridgeSubordinateBus
    442   )
    443 /*++
    444 
    445 Routine Description:
    446 
    447   Append a PCI device path node to another device path.
    448 
    449 Arguments:
    450 
    451   Private               -  A pointer to DEVICE_IO_PRIVATE_DATA instance.
    452   Bus                   -  PCI bus number of the device.
    453   Device                -  PCI device number of the device.
    454   Function              -  PCI function number of the device.
    455   DevicePath            -  Original device path which will be appended a PCI device path node.
    456   BridgePrimaryBus      -  Primary bus number of the bridge.
    457   BridgeSubordinateBus  -  Subordinate bus number of the bridge.
    458 
    459 Returns:
    460 
    461   Pointer to the appended PCI device path.
    462 
    463 --*/
    464 {
    465   UINT16                    ThisBus;
    466   UINT8                     ThisDevice;
    467   UINT8                     ThisFunc;
    468   UINT64                    Address;
    469   PCI_TYPE01                PciBridge;
    470   PCI_TYPE01                *PciPtr;
    471   EFI_DEVICE_PATH_PROTOCOL  *ReturnDevicePath;
    472   PCI_DEVICE_PATH           PciNode;
    473 
    474   PciPtr = &PciBridge;
    475   for (ThisBus = *BridgePrimaryBus; ThisBus <= *BridgeSubordinateBus; ThisBus++) {
    476     for (ThisDevice = 0; ThisDevice <= PCI_MAX_DEVICE; ThisDevice++) {
    477       for (ThisFunc = 0; ThisFunc <= PCI_MAX_FUNC; ThisFunc++) {
    478         Address = EFI_PCI_ADDRESS (ThisBus, ThisDevice, ThisFunc, 0);
    479         ZeroMem (PciPtr, sizeof (PCI_TYPE01));
    480         Private->DeviceIo.Pci.Read (
    481                                 &Private->DeviceIo,
    482                                 IO_UINT32,
    483                                 Address,
    484                                 1,
    485                                 &(PciPtr->Hdr.VendorId)
    486                                 );
    487         if ((PciPtr->Hdr.VendorId == 0xffff) && (ThisFunc == 0)) {
    488           break;
    489         }
    490         if (PciPtr->Hdr.VendorId == 0xffff) {
    491           continue;
    492         }
    493 
    494         Private->DeviceIo.Pci.Read (
    495                                 &Private->DeviceIo,
    496                                 IO_UINT32,
    497                                 Address,
    498                                 sizeof (PCI_TYPE01) / sizeof (UINT32),
    499                                 PciPtr
    500                                 );
    501         if (IS_PCI_BRIDGE (PciPtr)) {
    502           if (Bus >= PciPtr->Bridge.SecondaryBus && Bus <= PciPtr->Bridge.SubordinateBus) {
    503 
    504             PciNode.Header.Type     = HARDWARE_DEVICE_PATH;
    505             PciNode.Header.SubType  = HW_PCI_DP;
    506             SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
    507 
    508             PciNode.Device        = ThisDevice;
    509             PciNode.Function      = ThisFunc;
    510             ReturnDevicePath      = AppendDevicePathNode (DevicePath, &PciNode.Header);
    511 
    512             *BridgePrimaryBus     = PciPtr->Bridge.SecondaryBus;
    513             *BridgeSubordinateBus = PciPtr->Bridge.SubordinateBus;
    514             return ReturnDevicePath;
    515           }
    516         }
    517 
    518         if ((ThisFunc == 0) && ((PciPtr->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x0)) {
    519           //
    520           // Skip sub functions, this is not a multi function device
    521           //
    522           break;
    523         }
    524       }
    525     }
    526   }
    527 
    528   ZeroMem (&PciNode, sizeof (PciNode));
    529   PciNode.Header.Type     = HARDWARE_DEVICE_PATH;
    530   PciNode.Header.SubType  = HW_PCI_DP;
    531   SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
    532   PciNode.Device        = Device;
    533   PciNode.Function      = Function;
    534 
    535   ReturnDevicePath      = AppendDevicePathNode (DevicePath, &PciNode.Header);
    536 
    537   *BridgePrimaryBus     = 0xffff;
    538   *BridgeSubordinateBus = 0xffff;
    539   return ReturnDevicePath;
    540 }
    541 
    542 EFI_STATUS
    543 EFIAPI
    544 DeviceIoPciDevicePath (
    545   IN     EFI_DEVICE_IO_PROTOCOL        *This,
    546   IN     UINT64                        Address,
    547   IN OUT EFI_DEVICE_PATH_PROTOCOL      **PciDevicePath
    548   )
    549 /*++
    550 
    551 Routine Description:
    552 
    553   Provides an EFI Device Path for a PCI device with the given PCI configuration space address.
    554 
    555 Arguments:
    556 
    557   This           -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.
    558   Address        -  The PCI configuration space address of the device whose Device Path
    559                     is going to be returned.
    560   PciDevicePath  -  A pointer to the pointer for the EFI Device Path for PciAddress.
    561                     Memory for the Device Path is allocated from the pool.
    562 
    563 Returns:
    564 
    565   EFI_SUCCESS           -  The PciDevicePath returns a pointer to a valid EFI Device Path.
    566   EFI_UNSUPPORTED       -  The PciAddress does not map to a valid EFI Device Path.
    567   EFI_OUT_OF_RESOURCES  -  The request could not be completed due to a lack of resources.
    568 
    569 --*/
    570 {
    571   DEVICE_IO_PRIVATE_DATA  *Private;
    572   UINT16                  PrimaryBus;
    573   UINT16                  SubordinateBus;
    574   UINT8                   Bus;
    575   UINT8                   Device;
    576   UINT8                   Func;
    577 
    578   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
    579 
    580   Bus     = (UINT8) (((UINT32) Address >> 24) & 0xff);
    581   Device  = (UINT8) (((UINT32) Address >> 16) & 0xff);
    582   Func    = (UINT8) (((UINT32) Address >> 8) & 0xff);
    583 
    584   if (Bus < Private->PrimaryBus || Bus > Private->SubordinateBus) {
    585     return EFI_UNSUPPORTED;
    586   }
    587 
    588   *PciDevicePath  = Private->DevicePath;
    589   PrimaryBus      = Private->PrimaryBus;
    590   SubordinateBus  = Private->SubordinateBus;
    591   do {
    592     *PciDevicePath = AppendPciDevicePath (
    593                        Private,
    594                        Bus,
    595                        Device,
    596                        Func,
    597                        *PciDevicePath,
    598                        &PrimaryBus,
    599                        &SubordinateBus
    600                        );
    601     if (*PciDevicePath == NULL) {
    602       return EFI_OUT_OF_RESOURCES;
    603     }
    604   } while (PrimaryBus != 0xffff);
    605 
    606   return EFI_SUCCESS;
    607 }
    608 
    609 EFI_STATUS
    610 EFIAPI
    611 DeviceIoMap (
    612   IN     EFI_DEVICE_IO_PROTOCOL   *This,
    613   IN     EFI_IO_OPERATION_TYPE    Operation,
    614   IN     EFI_PHYSICAL_ADDRESS     *HostAddress,
    615   IN OUT UINTN                    *NumberOfBytes,
    616   OUT    EFI_PHYSICAL_ADDRESS     *DeviceAddress,
    617   OUT    VOID                     **Mapping
    618   )
    619 /*++
    620 
    621 Routine Description:
    622 
    623   Provides the device-specific addresses needed to access system memory.
    624 
    625 Arguments:
    626 
    627   This           -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.
    628   Operation      -  Indicates if the bus master is going to read or write to system memory.
    629   HostAddress    -  The system memory address to map to the device.
    630   NumberOfBytes  -  On input the number of bytes to map. On output the number of bytes
    631                     that were mapped.
    632   DeviceAddress  -  The resulting map address for the bus master device to use to access the
    633                     hosts HostAddress.
    634   Mapping        -  A resulting value to pass to Unmap().
    635 
    636 Returns:
    637 
    638   EFI_SUCCESS            -  The range was mapped for the returned NumberOfBytes.
    639   EFI_INVALID_PARAMETER  -  The Operation or HostAddress is undefined.
    640   EFI_UNSUPPORTED        -  The HostAddress cannot be mapped as a common buffer.
    641   EFI_DEVICE_ERROR       -  The system hardware could not map the requested address.
    642   EFI_OUT_OF_RESOURCES   -  The request could not be completed due to a lack of resources.
    643 
    644 --*/
    645 {
    646   EFI_STATUS              Status;
    647   DEVICE_IO_PRIVATE_DATA  *Private;
    648 
    649   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
    650 
    651   if ((UINT32)Operation > EfiBusMasterCommonBuffer) {
    652     return EFI_INVALID_PARAMETER;
    653   }
    654 
    655   if (((UINTN) (*HostAddress) != (*HostAddress)) && Operation == EfiBusMasterCommonBuffer) {
    656     return EFI_UNSUPPORTED;
    657   }
    658 
    659   Status = Private->PciRootBridgeIo->Map (
    660                                        Private->PciRootBridgeIo,
    661                                        (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,
    662                                        (VOID *) (UINTN) (*HostAddress),
    663                                        NumberOfBytes,
    664                                        DeviceAddress,
    665                                        Mapping
    666                                        );
    667 
    668   return Status;
    669 }
    670 
    671 EFI_STATUS
    672 EFIAPI
    673 DeviceIoUnmap (
    674   IN EFI_DEVICE_IO_PROTOCOL   *This,
    675   IN VOID                     *Mapping
    676   )
    677 /*++
    678 
    679 Routine Description:
    680 
    681   Completes the Map() operation and releases any corresponding resources.
    682 
    683 Arguments:
    684 
    685   This     -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.
    686   Mapping  -  The mapping value returned from Map().
    687 
    688 Returns:
    689 
    690   EFI_SUCCESS       -  The range was unmapped.
    691   EFI_DEVICE_ERROR  -  The data was not committed to the target system memory.
    692 
    693 --*/
    694 {
    695   EFI_STATUS              Status;
    696   DEVICE_IO_PRIVATE_DATA  *Private;
    697 
    698   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
    699 
    700   Status = Private->PciRootBridgeIo->Unmap (
    701                                        Private->PciRootBridgeIo,
    702                                        Mapping
    703                                        );
    704 
    705   return Status;
    706 }
    707 
    708 EFI_STATUS
    709 EFIAPI
    710 DeviceIoAllocateBuffer (
    711   IN     EFI_DEVICE_IO_PROTOCOL    *This,
    712   IN     EFI_ALLOCATE_TYPE         Type,
    713   IN     EFI_MEMORY_TYPE           MemoryType,
    714   IN     UINTN                     Pages,
    715   IN OUT EFI_PHYSICAL_ADDRESS      *PhysicalAddress
    716   )
    717 /*++
    718 
    719 Routine Description:
    720 
    721   Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.
    722 
    723 Arguments:
    724 
    725   This             -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.
    726   Type             -  The type allocation to perform.
    727   MemoryType       -  The type of memory to allocate, EfiBootServicesData or
    728                       EfiRuntimeServicesData.
    729   Pages            -  The number of pages to allocate.
    730   PhysicalAddress  -  A pointer to store the base address of the allocated range.
    731 
    732 Returns:
    733 
    734   EFI_SUCCESS            -  The requested memory pages were allocated.
    735   EFI_OUT_OF_RESOURCES   -  The memory pages could not be allocated.
    736   EFI_INVALID_PARAMETER  -  The requested memory type is invalid.
    737   EFI_UNSUPPORTED        -  The requested PhysicalAddress is not supported on
    738                             this platform.
    739 
    740 --*/
    741 {
    742   EFI_STATUS            Status;
    743   EFI_PHYSICAL_ADDRESS  HostAddress;
    744 
    745   HostAddress = *PhysicalAddress;
    746 
    747   if ((MemoryType != EfiBootServicesData) && (MemoryType != EfiRuntimeServicesData)) {
    748     return EFI_INVALID_PARAMETER;
    749   }
    750 
    751   if ((UINT32)Type >= MaxAllocateType) {
    752     return EFI_INVALID_PARAMETER;
    753   }
    754 
    755   if ((Type == AllocateAddress) && (HostAddress + EFI_PAGES_TO_SIZE (Pages) - 1 > MAX_COMMON_BUFFER)) {
    756     return EFI_UNSUPPORTED;
    757   }
    758 
    759   if ((AllocateAnyPages == Type) || (AllocateMaxAddress == Type && HostAddress > MAX_COMMON_BUFFER)) {
    760     Type        = AllocateMaxAddress;
    761     HostAddress = MAX_COMMON_BUFFER;
    762   }
    763 
    764   Status = gBS->AllocatePages (
    765                   Type,
    766                   MemoryType,
    767                   Pages,
    768                   &HostAddress
    769                   );
    770   if (EFI_ERROR (Status)) {
    771     return Status;
    772   }
    773 
    774 
    775   *PhysicalAddress = HostAddress;
    776 
    777   return EFI_SUCCESS;
    778 }
    779 
    780 EFI_STATUS
    781 EFIAPI
    782 DeviceIoFlush (
    783   IN EFI_DEVICE_IO_PROTOCOL  *This
    784   )
    785 /*++
    786 
    787 Routine Description:
    788 
    789   Flushes any posted write data to the device.
    790 
    791 Arguments:
    792 
    793   This  -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.
    794 
    795 Returns:
    796 
    797   EFI_SUCCESS       -  The buffers were flushed.
    798   EFI_DEVICE_ERROR  -  The buffers were not flushed due to a hardware error.
    799 
    800 --*/
    801 {
    802   EFI_STATUS              Status;
    803   DEVICE_IO_PRIVATE_DATA  *Private;
    804 
    805   Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);
    806 
    807   Status  = Private->PciRootBridgeIo->Flush (Private->PciRootBridgeIo);
    808 
    809   return Status;
    810 }
    811 
    812 EFI_STATUS
    813 EFIAPI
    814 DeviceIoFreeBuffer (
    815   IN EFI_DEVICE_IO_PROTOCOL   *This,
    816   IN UINTN                    Pages,
    817   IN EFI_PHYSICAL_ADDRESS     HostAddress
    818   )
    819 /*++
    820 
    821 Routine Description:
    822 
    823   Frees pages that were allocated with AllocateBuffer().
    824 
    825 Arguments:
    826 
    827   This         -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.
    828   Pages        -  The number of pages to free.
    829   HostAddress  -  The base address of the range to free.
    830 
    831 Returns:
    832 
    833   EFI_SUCCESS            -  The requested memory pages were freed.
    834   EFI_NOT_FOUND          -  The requested memory pages were not allocated with
    835                             AllocateBuffer().
    836   EFI_INVALID_PARAMETER  -  HostAddress is not page aligned or Pages is invalid.
    837 
    838 --*/
    839 {
    840   if (((HostAddress & EFI_PAGE_MASK) != 0) || (Pages <= 0)) {
    841     return EFI_INVALID_PARAMETER;
    842   }
    843 
    844   return gBS->FreePages (HostAddress, Pages);
    845 }
    846