public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
To: "Ni, Ruiyu" <ruiyu.ni@intel.com>
Cc: "edk2-devel@lists.01.org" <edk2-devel@lists.01.org>,
	"Gao, Liming" <liming.gao@intel.com>,
	 "Kinney, Michael D" <michael.d.kinney@intel.com>,
	"afish@apple.com" <afish@apple.com>,
	"mw@semihalf.com" <mw@semihalf.com>,
	"leif.lindholm@linaro.org" <leif.lindholm@linaro.org>
Subject: Re: [PATCH v3 3/5] MdeModulePkg: implement generic PCI I/O driver for non-discoverable devices
Date: Fri, 18 Nov 2016 12:30:08 +0000	[thread overview]
Message-ID: <CAKv+Gu91SCK-H=jjK=i0ULeHaXjREsZhamhsM+hJH5kzqyR4Hw@mail.gmail.com> (raw)
In-Reply-To: <734D49CCEBEEF84792F5B80ED585239D58E7C886@SHSMSX104.ccr.corp.intel.com>

On 17 November 2016 at 03:29, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>
>
> Thanks/Ray
>
>> -----Original Message-----
>> From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org]
>> Sent: Thursday, November 17, 2016 12:59 AM
>> To: edk2-devel@lists.01.org; Gao, Liming <liming.gao@intel.com>; Ni, Ruiyu
>> <ruiyu.ni@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>
>> Cc: afish@apple.com; mw@semihalf.com; leif.lindholm@linaro.org; Ard
>> Biesheuvel <ard.biesheuvel@linaro.org>
>> Subject: [PATCH v3 3/5] MdeModulePkg: implement generic PCI I/O driver
>> for non-discoverable devices
>>
>> This implements support for non-discoverable PCI compatible devices, i.e,
>> devices that are not on a PCI bus but that can be controlled by generic PCI
>> drivers in EDK2.
>>
>> This is implemented as a UEFI driver, which means we take full advantage of
>> the UEFI driver model, and only instantiate those devices that are necessary
>> for booting.
>>
>> Care is taken to deal with DMA addressing limitations: DMA mappings and
>> allocations are moved below 4 GB if the PCI driver has not informed us that
>> the device being driven is 64-bit DMA capable. DMA is implemented as
>> coherent, support for non-coherent DMA is implemented by a subsequent
>> patch.
>>
>> Contributed-under: TianoCore Contribution Agreement 1.0
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> ---
>>
>> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/ComponentName.c
>> |  75 ++
>>
>> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
>> DeviceDxe.c   | 223 +++++
>>
>> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
>> DeviceDxe.inf |  42 +
>>
>> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
>> DeviceIo.c    | 868 ++++++++++++++++++++
>>
>> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
>> DeviceIo.h    |  84 ++
>>  MdeModulePkg/MdeModulePkg.dsc                                                    |   1 +
>>  6 files changed, 1293 insertions(+)
>>
[...]
>> diff --git
>> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> PciDeviceIo.c
>> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> PciDeviceIo.c
>> new file mode 100644
>> index 000000000000..23466318bfc1
>> --- /dev/null
>> +++
>> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> Pc
>> +++ iDeviceIo.c
>> @@ -0,0 +1,868 @@
>> +/** @file
>> +
>> +  Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
>> + Copyright (c) 2016, Linaro, Ltd. All rights reserved.<BR>
>> +
>> +  This program and the accompanying materials  are licensed and made
>> + available under the terms and conditions of the BSD License  which
>> + accompanies this distribution.  The full text of the license may be
>> + found at  http://opensource.org/licenses/bsd-license.php
>> +
>> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
>> BASIS,
>> + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
>> EXPRESS OR IMPLIED.
>> +
>> +**/
>> +
>> +#include "NonDiscoverablePciDeviceIo.h"
>> +
>> +#include <IndustryStandard/Acpi.h>
>> +
>> +#include <Protocol/PciRootBridgeIo.h>
>> +
>> +typedef struct {
>> +  EFI_PHYSICAL_ADDRESS            AllocAddress;
>> +  VOID                            *HostAddress;
>> +  EFI_PCI_IO_PROTOCOL_OPERATION   Operation;
>> +  UINTN                           NumberOfBytes;
>> +} NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO;
>> +
>> +//
>> +// Get the resource associated with BAR number 'BarIndex'. This takes
>> +into // account that 64-bit resource use up 2 BAR slots, which means
>> +that BAR // n + 1 is reported as not found if BAR n refers to a 64-bit resource.
>> +//
>> +STATIC
>> +EFI_STATUS
>> +GetBarResource (
>> +  IN  NON_DISCOVERABLE_PCI_DEVICE         *Dev,
>> +  IN  UINT8                               BarIndex,
>> +  OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   **Descriptor
>> +  )
>> +{
>> +  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Desc;
>> +
>> +  if (BarIndex < Dev->BarOffset) {
>> +    return EFI_NOT_FOUND;
>> +  }
>> +
>> +  BarIndex -= Dev->BarOffset;
>> +
>> +  for (Desc = Dev->Device->Resources;
>> +       Desc->Desc != ACPI_END_TAG_DESCRIPTOR;
>> +       Desc = (VOID *)((UINT8 *)Desc + Desc->Len + 3)) {
>> +
>> +    if (BarIndex == 0) {
>> +      *Descriptor = Desc;
>> +      return EFI_SUCCESS;
>> +    }
>> +
>> +    if (Desc->AddrSpaceGranularity == 64) {
>> +      if (BarIndex == 1) {
>> +        break;
>> +      }
>> +      BarIndex -= 2;
>
> 1. I think we only need to decrease *one* from BarIndex instead of two,
> even for 64bit BAR.
> I remember MdeModulePkg/PciBusDxe ever had a bug to treat 64bit
> BAR as 2 logic BARs but it should have fixed long ago.
>

Right. So does that mean BarIndex '2' refers to BARs 4 and 5 if we
have 3 64-bit BARs in total?

>> +    } else {
>> +      BarIndex -= 1;
>> +    }
>> +  }
>> +  return EFI_NOT_FOUND;
>> +}
>> +
>> +STATIC
>> +EFI_STATUS
>> +PciIoPollMem (
>> +  IN  EFI_PCI_IO_PROTOCOL         *This,
>> +  IN  EFI_PCI_IO_PROTOCOL_WIDTH   Width,
>> +  IN  UINT8                       BarIndex,
>> +  IN  UINT64                      Offset,
>> +  IN  UINT64                      Mask,
>> +  IN  UINT64                      Value,
>> +  IN  UINT64                      Delay,
>> +  OUT UINT64                      *Result
>> +  )
>> +{
>> +  ASSERT (FALSE);
>> +  return EFI_UNSUPPORTED;
>> +}
>> +
>> +STATIC
>> +EFI_STATUS
>> +PciIoPollIo (
>> +  IN  EFI_PCI_IO_PROTOCOL         *This,
>> +  IN  EFI_PCI_IO_PROTOCOL_WIDTH   Width,
>> +  IN  UINT8                       BarIndex,
>> +  IN  UINT64                      Offset,
>> +  IN  UINT64                      Mask,
>> +  IN  UINT64                      Value,
>> +  IN  UINT64                      Delay,
>> +  OUT UINT64                      *Result
>> +  )
>> +{
>> +  ASSERT (FALSE);
>> +  return EFI_UNSUPPORTED;
>> +}
>> +
>> +STATIC
>> +EFI_STATUS
>> +PciIoMemRW (
>> +  IN  EFI_PCI_IO_PROTOCOL_WIDTH   Width,
>> +  IN  UINTN                       Count,
>> +  IN  UINTN                       DstStride,
>> +  IN  VOID                        *Dst,
>> +  IN  UINTN                       SrcStride,
>> +  OUT CONST VOID                  *Src
>> +  )
>> +{
>> +  volatile UINT8             *Dst8;
>> +  volatile UINT16            *Dst16;
>> +  volatile UINT32            *Dst32;
>> +  volatile CONST UINT8       *Src8;
>> +  volatile CONST UINT16      *Src16;
>> +  volatile CONST UINT32      *Src32;
>> +
>> +  //
>> +  // Loop for each iteration and move the data  //  switch (Width &
>> + 0x3) {  case EfiPciWidthUint8:
>> +    Dst8 = (UINT8 *)Dst;
>> +    Src8 = (UINT8 *)Src;
>> +    for (;Count > 0; Count--, Dst8 += DstStride, Src8 += SrcStride) {
>> +      *Dst8 = *Src8;
>> +    }
>> +    break;
>> +  case EfiPciWidthUint16:
>> +    Dst16 = (UINT16 *)Dst;
>> +    Src16 = (UINT16 *)Src;
>> +    for (;Count > 0; Count--, Dst16 += DstStride, Src16 += SrcStride) {
>> +      *Dst16 = *Src16;
>> +    }
>> +    break;
>> +  case EfiPciWidthUint32:
>> +    Dst32 = (UINT32 *)Dst;
>> +    Src32 = (UINT32 *)Src;
>> +    for (;Count > 0; Count--, Dst32 += DstStride, Src32 += SrcStride) {
>> +      *Dst32 = *Src32;
>> +    }
>> +    break;
>> +  default:
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +STATIC
>> +EFI_STATUS
>> +PciIoMemRead (
>> +  IN     EFI_PCI_IO_PROTOCOL          *This,
>> +  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,
>> +  IN     UINT8                        BarIndex,
>> +  IN     UINT64                       Offset,
>> +  IN     UINTN                        Count,
>> +  IN OUT VOID                         *Buffer
>> +  )
>> +{
>> +  NON_DISCOVERABLE_PCI_DEVICE         *Dev;
>> +  UINTN                               AlignMask;
>> +  VOID                                *Address;
>> +  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Desc;
>> +  EFI_STATUS                          Status;
>> +
>> +  if (Buffer == NULL) {
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
>> +
>> +  //
>> +  // Only allow accesses to the BARs we emulate  //  Status =
>> + GetBarResource (Dev, BarIndex, &Desc);  if (EFI_ERROR (Status)) {
>> +    return Status;
>> +  }
>> +
>> +  if (Offset + (Count << (Width & 0x3)) > Desc->AddrLen) {
>> +    return EFI_UNSUPPORTED;
>> +  }
>> +
>> +  Address = (VOID *)((UINTN)Desc->AddrRangeMin + Offset);  AlignMask =
>> + (1 << (Width & 0x03)) - 1;  if ((UINTN)Address & AlignMask) {
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  switch (Width) {
>> +  case EfiPciWidthUint8:
>> +  case EfiPciWidthUint16:
>> +  case EfiPciWidthUint32:
>> +  case EfiPciWidthUint64:
>> +    return PciIoMemRW (Width, Count, 1, Buffer, 1, Address);
>> +
>> +  case EfiPciWidthFifoUint8:
>> +  case EfiPciWidthFifoUint16:
>> +  case EfiPciWidthFifoUint32:
>> +  case EfiPciWidthFifoUint64:
>> +    return PciIoMemRW (Width, Count, 1, Buffer, 0, Address);
>> +
>> +  case EfiPciWidthFillUint8:
>> +  case EfiPciWidthFillUint16:
>> +  case EfiPciWidthFillUint32:
>> +  case EfiPciWidthFillUint64:
>> +    return PciIoMemRW (Width, Count, 0, Buffer, 1, Address);
>> +
>> +  default:
>> +    break;
>> +  }
>> +  return EFI_INVALID_PARAMETER;
>> +}
>> +
>> +STATIC
>> +EFI_STATUS
>> +PciIoMemWrite (
>> +  IN     EFI_PCI_IO_PROTOCOL          *This,
>> +  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,
>> +  IN     UINT8                        BarIndex,
>> +  IN     UINT64                       Offset,
>> +  IN     UINTN                        Count,
>> +  IN OUT VOID                         *Buffer
>> +  )
>> +{
>> +  NON_DISCOVERABLE_PCI_DEVICE         *Dev;
>> +  UINTN                               AlignMask;
>> +  VOID                                *Address;
>> +  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Desc;
>> +  EFI_STATUS                          Status;
>> +
>> +  if (Buffer == NULL) {
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
>> +
>> +  //
>> +  // Only allow accesses to the BARs we emulate  //  Status =
>> + GetBarResource (Dev, BarIndex, &Desc);  if (EFI_ERROR (Status)) {
>> +    return Status;
>> +  }
>> +
>> +  if (Offset + (Count << (Width & 0x3)) > Desc->AddrLen) {
>> +    return EFI_UNSUPPORTED;
>> +  }
>> +
>> +  Address = (VOID *)((UINTN)Desc->AddrRangeMin + Offset);  AlignMask =
>> + (1 << (Width & 0x03)) - 1;  if ((UINTN)Address & AlignMask) {
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  switch (Width) {
>> +  case EfiPciWidthUint8:
>> +  case EfiPciWidthUint16:
>> +  case EfiPciWidthUint32:
>> +  case EfiPciWidthUint64:
>> +    return PciIoMemRW (Width, Count, 1, Address, 1, Buffer);
>> +
>> +  case EfiPciWidthFifoUint8:
>> +  case EfiPciWidthFifoUint16:
>> +  case EfiPciWidthFifoUint32:
>> +  case EfiPciWidthFifoUint64:
>> +    return PciIoMemRW (Width, Count, 0, Address, 1, Buffer);
>> +
>> +  case EfiPciWidthFillUint8:
>> +  case EfiPciWidthFillUint16:
>> +  case EfiPciWidthFillUint32:
>> +  case EfiPciWidthFillUint64:
>> +    return PciIoMemRW (Width, Count, 1, Address, 0, Buffer);
>> +
>> +  default:
>> +    break;
>> +  }
>> +  return EFI_INVALID_PARAMETER;
>> +}
>> +
>> +STATIC
>> +EFI_STATUS
>> +PciIoIoRead (
>> +  IN EFI_PCI_IO_PROTOCOL              *This,
>> +  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,
>> +  IN     UINT8                        BarIndex,
>> +  IN     UINT64                       Offset,
>> +  IN     UINTN                        Count,
>> +  IN OUT VOID                         *Buffer
>> +  )
>> +{
>> +  ASSERT (FALSE);
>> +  return EFI_UNSUPPORTED;
>> +}
>> +
>> +STATIC
>> +EFI_STATUS
>> +PciIoIoWrite (
>> +  IN     EFI_PCI_IO_PROTOCOL          *This,
>> +  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,
>> +  IN     UINT8                        BarIndex,
>> +  IN     UINT64                       Offset,
>> +  IN     UINTN                        Count,
>> +  IN OUT VOID                         *Buffer
>> +  )
>> +{
>> +  ASSERT (FALSE);
>> +  return EFI_UNSUPPORTED;
>> +}
>> +
>> +STATIC
>> +EFI_STATUS
>> +PciIoPciRead (
>> +  IN     EFI_PCI_IO_PROTOCOL        *This,
>> +  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
>> +  IN     UINT32                     Offset,
>> +  IN     UINTN                      Count,
>> +  IN OUT VOID                       *Buffer
>> +  )
>> +{
>> +  NON_DISCOVERABLE_PCI_DEVICE   *Dev;
>> +  UINTN                         Length;
>> +
>> +  if (Width < 0 || Width >= EfiPciIoWidthMaximum || Buffer == NULL) {
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
>> +  Length = Count << ((UINTN)Width & 0x3);
>> +
>> +  if (Offset + Length > sizeof (Dev->ConfigSpace)) {
>> +    return EFI_UNSUPPORTED;
>> +  }
>> +
>> +  return PciIoMemRW (Width, Count, 1, Buffer, 1,
>> +           (UINT8 *)&Dev->ConfigSpace + Offset); }
>> +
>> +//
>> +// taken from MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
>> +//
>> +#define SD_MMC_HC_SLOT_OFFSET         0x40
>> +
>> +typedef struct {
>> +  UINT8    FirstBar:3;        // bit 0:2
>> +  UINT8    Reserved:1;        // bit 3
>> +  UINT8    SlotNum:3;         // bit 4:6
>> +  UINT8    Reserved1:1;       // bit 7
>> +} SD_MMC_HC_SLOT_INFO;
>> +
>> +STATIC
>> +EFI_STATUS
>> +PciIoPciReadSdhci (
>> +  IN     EFI_PCI_IO_PROTOCOL        *This,
>> +  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,
>> +  IN     UINT32                     Offset,
>> +  IN     UINTN                      Count,
>> +  IN OUT VOID                       *Buffer
>> +  )
>> +{
>> +  NON_DISCOVERABLE_PCI_DEVICE   *Dev;
>> +  UINTN                         Length;
>> +  SD_MMC_HC_SLOT_INFO           *SlotInfo;
>> +
>> +  if (Width < 0 || Width >= EfiPciIoWidthMaximum || Buffer == NULL) {
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
>> +  Length = Count << ((UINTN)Width & 0x3);
>> +
>> +  //
>> +  // The SDHCI driver reads beyond the 64-byte PCI config space to read
>> + // the number of slots and the BAR offset. So allow that  //  if
>> + (Offset == SD_MMC_HC_SLOT_OFFSET && Length == 1) {
>> +    SlotInfo = Buffer;
>> +
>> +    SlotInfo->FirstBar = Dev->BarOffset;
>> +    SlotInfo->SlotNum = Dev->BarCount - 1;
>
> 2. It's a little bit tricky to hook the SDHCI access.
> We need to make this driver generic enough and stable
> for future possible requirements.
> We now see the needs for SDHCI access. We may have other similar needs.
> Can we pass such information from NonDiscoverredPciDevice?
> The information like array of <Offset, Uint8Value> can be included in the protocol.
> Just my rough idea. Feel free to reject it.
>

Well, this is another side effect of the design decision of folding
SDHCI support into a SDHCI-PCI driver.

For other host controller interfaces, there is always a 1:1
relationship between a PCI device and a ?HCI device. However, for
SDHCI, the correct way to implement this on the driver side would have
been to implement a SDHCI-PCI bus driver that allocates a SHDCI device
handle for each slot on the PCI device. That would allow the SDHCI
*driver* to only worry about a single device, and there would be no
need for this hack.

In the first iteration of this series, I did not have this since there
was a 1:1 relationship between non-discoverable devices and PCI
drivers, but due to the move to ACPI resource descriptors, this is
different now.


>> +
>> +    return EFI_SUCCESS;
>> +  }
>> +
>> +  if (Offset + Length > sizeof (Dev->ConfigSpace)) {
>> +    return EFI_UNSUPPORTED;
>> +  }
>> +
>> +  return PciIoMemRW (Width, Count, 1, Buffer, 1,
>> +           (UINT8 *)&Dev->ConfigSpace + Offset); }
>> +
>> +STATIC
>> +EFI_STATUS
>> +PciIoPciWrite (
>> +  IN EFI_PCI_IO_PROTOCOL              *This,
>> +  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,
>> +  IN     UINT32                       Offset,
>> +  IN     UINTN                        Count,
>> +  IN OUT VOID                         *Buffer
>> +  )
>> +{
>> +  NON_DISCOVERABLE_PCI_DEVICE   *Dev;
>> +  VOID                          *Address;
>> +
>> +  if (Width < 0 || Width >= EfiPciIoWidthMaximum || Buffer == NULL) {
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
>> +  Address = (UINT8 *)&Dev->ConfigSpace + Offset;
>> +
>> +  if (Offset + Count * (1UL << (Width & 0x3)) > sizeof (Dev->ConfigSpace)) {
>> +    return EFI_UNSUPPORTED;
>> +  }
>> +
>> +  return PciIoMemRW (Width, Count, 1, Address, 1, Buffer); }
>> +
>> +STATIC
>> +EFI_STATUS
>> +PciIoCopyMem (
>> +  IN EFI_PCI_IO_PROTOCOL              *This,
>> +  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,
>> +  IN     UINT8                        DestBarIndex,
>> +  IN     UINT64                       DestOffset,
>> +  IN     UINT8                        SrcBarIndex,
>> +  IN     UINT64                       SrcOffset,
>> +  IN     UINTN                        Count
>> +  )
>> +{
>> +  ASSERT (FALSE);
>> +  return EFI_UNSUPPORTED;
>> +}
>> +
>> +STATIC
>> +EFI_STATUS
>> +CoherentPciIoMap (
>> +  IN     EFI_PCI_IO_PROTOCOL            *This,
>> +  IN     EFI_PCI_IO_PROTOCOL_OPERATION  Operation,
>> +  IN     VOID                           *HostAddress,
>> +  IN OUT UINTN                          *NumberOfBytes,
>> +  OUT    EFI_PHYSICAL_ADDRESS           *DeviceAddress,
>> +  OUT    VOID                           **Mapping
>> +  )
>> +{
>> +  NON_DISCOVERABLE_PCI_DEVICE           *Dev;
>> +  EFI_STATUS                            Status;
>> +  NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO  *MapInfo;
>> +
>> +  //
>> +  // If HostAddress exceeds 4 GB, and this device does not support
>> + 64-bit DMA  // addressing, we need to allocate a bounce buffer and copy
>> over the data.
>> +  //
>> +  Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
>> +  if ((Dev->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) ==
>> 0 &&
>> +      (UINTN)HostAddress + *NumberOfBytes > SIZE_4GB) {
>> +
>> +    //
>> +    // Bounce buffering is not possible for consistent mappings
>> +    //
>> +    if (Operation == EfiPciIoOperationBusMasterCommonBuffer) {
>> +      return EFI_UNSUPPORTED;
>> +    }
>> +
>> +    MapInfo = AllocatePool (sizeof *MapInfo);
>> +    if (MapInfo == NULL) {
>> +      return EFI_OUT_OF_RESOURCES;
>> +    }
>> +
>> +    MapInfo->AllocAddress = MAX_UINT32;
>> +    MapInfo->HostAddress = HostAddress;
>> +    MapInfo->Operation = Operation;
>> +    MapInfo->NumberOfBytes = *NumberOfBytes;
>> +
>> +    Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData,
>> +                    EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes),
>> +                    &MapInfo->AllocAddress);
>> +    if (EFI_ERROR (Status)) {
>> +      //
>> +      // If we fail here, it is likely because the system has no memory below
>> +      // 4 GB to begin with. There is not much we can do about that other than
>> +      // fail the map request.
>> +      //
>> +      FreePool (MapInfo);
>> +      return EFI_DEVICE_ERROR;
>> +    }
>> +    if (Operation == EfiPciIoOperationBusMasterRead) {
>> +      gBS->CopyMem ((VOID *)(UINTN)MapInfo->AllocAddress, HostAddress,
>> +             *NumberOfBytes);
>> +    }
>> +    *DeviceAddress = MapInfo->AllocAddress;
>> +    *Mapping = MapInfo;
>> +  } else {
>> +    *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;
>> +    *Mapping = NULL;
>> +  }
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +STATIC
>> +EFI_STATUS
>> +CoherentPciIoUnmap (
>> +  IN  EFI_PCI_IO_PROTOCOL          *This,
>> +  IN  VOID                         *Mapping
>> +  )
>> +{
>> +  NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO  *MapInfo;
>> +
>> +  MapInfo = Mapping;
>> +  if (MapInfo != NULL) {
>> +    if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) {
>> +      gBS->CopyMem (MapInfo->HostAddress, (VOID *)(UINTN)MapInfo-
>> >AllocAddress,
>> +             MapInfo->NumberOfBytes);
>> +    }
>> +    gBS->FreePages (MapInfo->AllocAddress,
>> +           EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes));
>> +    FreePool (MapInfo);
>> +  }
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +STATIC
>> +EFI_STATUS
>> +CoherentPciIoAllocateBuffer (
>> +  IN  EFI_PCI_IO_PROTOCOL         *This,
>> +  IN  EFI_ALLOCATE_TYPE           Type,
>> +  IN  EFI_MEMORY_TYPE             MemoryType,
>> +  IN  UINTN                       Pages,
>> +  OUT VOID                        **HostAddress,
>> +  IN  UINT64                      Attributes
>> +  )
>> +{
>> +  NON_DISCOVERABLE_PCI_DEVICE       *Dev;
>> +  EFI_PHYSICAL_ADDRESS              AllocAddress;
>> +  EFI_ALLOCATE_TYPE                 AllocType;
>> +  EFI_STATUS                        Status;
>> +
>> +  if ((Attributes & ~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE |
>> +                      EFI_PCI_ATTRIBUTE_MEMORY_CACHED)) != 0) {
>> +    return EFI_UNSUPPORTED;
>> +  }
>> +
>> +  //
>> +  // Allocate below 4 GB if the dual address cycle attribute has not
>> + // been set. If the system has no memory available below 4 GB, there
>> + // is little we can do except propagate the error.
>> +  //
>> +  Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
>> +  if ((Dev->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) ==
>> 0) {
>> +    AllocAddress = MAX_UINT32;
>
> 3. better to use BASE_4GB -1.
>
>> +    AllocType = AllocateMaxAddress;
>> +  } else {
>> +    AllocType = AllocateAnyPages;
>> +  }
>> +
>> +  Status = gBS->AllocatePages (AllocType, MemoryType, Pages,
>> +&AllocAddress);
>> +  if (!EFI_ERROR (Status)) {
>> +    *HostAddress = (VOID *)(UINTN)AllocAddress;
>> +  }
>> +  return Status;
>> +}
>> +
>> +STATIC
>> +EFI_STATUS
>> +CoherentPciIoFreeBuffer (
>> +  IN  EFI_PCI_IO_PROTOCOL         *This,
>> +  IN  UINTN                       Pages,
>> +  IN  VOID                        *HostAddress
>> +  )
>> +{
>> +  FreePages (HostAddress, Pages);
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +
>> +STATIC
>> +EFI_STATUS
>> +PciIoFlush (
>> +  IN EFI_PCI_IO_PROTOCOL          *This
>> +  )
>> +{
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +STATIC
>> +EFI_STATUS
>> +PciIoGetLocation (
>> +  IN   EFI_PCI_IO_PROTOCOL  *This,
>> +  OUT  UINTN                *SegmentNumber,
>> +  OUT  UINTN                *BusNumber,
>> +  OUT  UINTN                *DeviceNumber,
>> +  OUT  UINTN                *FunctionNumber
>> +  )
>> +{
>> +  if (SegmentNumber == NULL ||
>> +      BusNumber == NULL ||
>> +      DeviceNumber == NULL ||
>> +      FunctionNumber == NULL) {
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  *SegmentNumber  = 0;
>> +  *BusNumber      = 0xff;
>> +  *DeviceNumber   = 0;
>> +  *FunctionNumber = 0;
>> +
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +STATIC
>> +EFI_STATUS
>> +PciIoAttributes (
>> +  IN  EFI_PCI_IO_PROTOCOL                      *This,
>> +  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,
>> +  IN  UINT64                                   Attributes,
>> +  OUT UINT64                                   *Result OPTIONAL
>> +  )
>> +{
>> +  NON_DISCOVERABLE_PCI_DEVICE   *Dev;
>> +  BOOLEAN                       Enable;
>> +
>> +  Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
>> +
>> +  Enable = FALSE;
>> +  switch (Operation) {
>> +  case EfiPciIoAttributeOperationGet:
>> +    if (Result == NULL) {
>> +      return EFI_INVALID_PARAMETER;
>> +    }
>> +    *Result = Dev->Attributes;
>> +    break;
>> +
>> +  case EfiPciIoAttributeOperationSupported:
>> +    if (Result == NULL) {
>> +      return EFI_INVALID_PARAMETER;
>> +    }
>> +    *Result = EFI_PCI_DEVICE_ENABLE |
>> EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
>> +    break;
>> +
>> +  case EfiPciIoAttributeOperationEnable:
>> +    Attributes |= Dev->Attributes;
>> +  case EfiPciIoAttributeOperationSet:
>> +    Enable = ((~Dev->Attributes & Attributes) & EFI_PCI_DEVICE_ENABLE) !=
>> 0;
>> +    Dev->Attributes = Attributes;
>> +    break;
>> +
>> +  case EfiPciIoAttributeOperationDisable:
>> +    Dev->Attributes &= ~Attributes;
>> +    break;
>> +
>> +  default:
>> +    return EFI_INVALID_PARAMETER;
>> +  };
>> +
>> +  //
>> +  // If we're setting any of the EFI_PCI_DEVICE_ENABLE bits, perform
>> +  // the device specific initialization now.
>> +  //
>> +  if (Enable && !Dev->Enabled && Dev->Device->Initialize != NULL) {
>> +    Dev->Device->Initialize (Dev->Device);
>> +    Dev->Enabled = TRUE;
>> +  }
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +STATIC
>> +EFI_STATUS
>> +PciIoGetBarAttributes (
>> +  IN EFI_PCI_IO_PROTOCOL             *This,
>> +  IN  UINT8                          BarIndex,
>> +  OUT UINT64                         *Supports OPTIONAL,
>> +  OUT VOID                           **Resources OPTIONAL
>> +  )
>> +{
>> +  NON_DISCOVERABLE_PCI_DEVICE       *Dev;
>> +  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor, *BarDesc;
>> +  EFI_ACPI_END_TAG_DESCRIPTOR       *End;
>> +  EFI_STATUS                        Status;
>> +
>> +  if (Supports == NULL && Resources == NULL) {
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
>> +
>> +  Status = GetBarResource (Dev, BarIndex, &BarDesc);  if (EFI_ERROR
>> + (Status)) {
>> +    return Status;
>> +  }
>> +
>> +  //
>> +  // Don't expose any configurable attributes for our emulated BAR  //
>> + if (Supports != NULL) {
>> +    *Supports = 0;
>> +  }
>> +
>> +  if (Resources != NULL) {
>> +    Descriptor = AllocatePool (sizeof
>> (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +
>> +                               sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
>> +    if (Descriptor == NULL) {
>> +      return EFI_OUT_OF_RESOURCES;
>> +    }
>> +
>> +    CopyMem (Descriptor, BarDesc, sizeof *Descriptor);
>> +
>> +    End           = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);
>> +    End->Desc     = ACPI_END_TAG_DESCRIPTOR;
>> +    End->Checksum = 0;
>> +
>> +    *Resources = Descriptor;
>> +  }
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +STATIC
>> +EFI_STATUS
>> +PciIoSetBarAttributes (
>> +  IN     EFI_PCI_IO_PROTOCOL          *This,
>> +  IN     UINT64                       Attributes,
>> +  IN     UINT8                        BarIndex,
>> +  IN OUT UINT64                       *Offset,
>> +  IN OUT UINT64                       *Length
>> +  )
>> +{
>> +  ASSERT (FALSE);
>> +  return EFI_UNSUPPORTED;
>> +}
>> +
>> +STATIC CONST EFI_PCI_IO_PROTOCOL PciIoTemplate = {
>> +  PciIoPollMem,
>> +  PciIoPollIo,
>> +  { PciIoMemRead, PciIoMemWrite },
>> +  { PciIoIoRead,  PciIoIoWrite },
>> +  { PciIoPciRead, PciIoPciWrite },
>> +  PciIoCopyMem,
>> +  CoherentPciIoMap,
>> +  CoherentPciIoUnmap,
>> +  CoherentPciIoAllocateBuffer,
>> +  CoherentPciIoFreeBuffer,
>> +  PciIoFlush,
>> +  PciIoGetLocation,
>> +  PciIoAttributes,
>> +  PciIoGetBarAttributes,
>> +  PciIoSetBarAttributes,
>> +  0,
>> +  0
>> +};
>> +
>> +VOID
>> +InitializePciIoProtocol (
>> +  NON_DISCOVERABLE_PCI_DEVICE     *Dev
>> +  )
>> +{
>> +  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Desc;
>> +  INTN                                Idx;
>> +
>> +  InitializeListHead (&Dev->UncachedAllocationList);
>> +
>> +  Dev->ConfigSpace.Hdr.VendorId = PCI_ID_VENDOR_UNKNOWN;
>> + Dev->ConfigSpace.Hdr.DeviceId = PCI_ID_DEVICE_DONTCARE;
>> +
>> +  // Copy protocol structure
>> +  CopyMem(&Dev->PciIo, &PciIoTemplate, sizeof PciIoTemplate);
>> +
>> +  switch (Dev->Device->Type) {
>> +  case NonDiscoverableDeviceTypeOhci:
>> +    Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_OHCI;
>> +    Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_SERIAL_USB;
>> +    Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_SERIAL;
>> +    Dev->BarOffset = 0;
>> +    break;
>> +
>> +  case NonDiscoverableDeviceTypeUhci:
>> +    Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_UHCI;
>> +    Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_SERIAL_USB;
>> +    Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_SERIAL;
>> +    Dev->BarOffset = 0;
>> +    break;
>> +
>> +  case NonDiscoverableDeviceTypeEhci:
>> +    Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_EHCI;
>> +    Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_SERIAL_USB;
>> +    Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_SERIAL;
>> +    Dev->BarOffset = 0;
>> +    break;
>> +
>> +  case NonDiscoverableDeviceTypeXhci:
>> +    Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_XHCI;
>> +    Dev->ConfigSpace.Hdr.ClassCode[1] = PCI_CLASS_SERIAL_USB;
>> +    Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_SERIAL;
>> +    Dev->BarOffset = 0;
>> +    break;
>> +
>> +  case NonDiscoverableDeviceTypeAhci:
>> +    Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_MASS_STORAGE_AHCI;
>> +    Dev->ConfigSpace.Hdr.ClassCode[1] =
>> PCI_CLASS_MASS_STORAGE_SATADPA;
>> +    Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_MASS_STORAGE;
>> +    Dev->BarOffset = 5;
>> +    break;
>> +
>> +  case NonDiscoverableDeviceTypeSdhci:
>> +    Dev->ConfigSpace.Hdr.ClassCode[0] = 0x0; // don't care
>> +    Dev->ConfigSpace.Hdr.ClassCode[1] =
>> PCI_SUBCLASS_SD_HOST_CONTROLLER;
>> +    Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_SYSTEM_PERIPHERAL;
>> +    Dev->BarOffset = 0;
>> +
>> +    //
>> +    // Use the special config space accessor so that the SDHCI driver
>> +    // is able to retrieve the number of slots and the BAR offset
>> +    //
>> +    Dev->PciIo.Pci.Read = PciIoPciReadSdhci;
>> +    break;
>> +
>> +  case NonDiscoverableDeviceTypeUfs:
>> +    Dev->ConfigSpace.Hdr.ClassCode[0] = 0x0; // don't care
>> +    Dev->ConfigSpace.Hdr.ClassCode[1] = 0x9; // UFS controller subclass;
>> +    Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_MASS_STORAGE;
>> +    Dev->BarOffset = 0;
>> +    break;
>> +
>> +  case NonDiscoverableDeviceTypeNvme:
>> +    Dev->ConfigSpace.Hdr.ClassCode[0] = 0x2; // PCI_IF_NVMHCI
>> +    Dev->ConfigSpace.Hdr.ClassCode[1] = 0x8; //
>> PCI_CLASS_MASS_STORAGE_NVM
>> +    Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_MASS_STORAGE;
>> +    Dev->BarOffset = 0;
>> +
>> +  default:
>> +    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);  }
>> +
>> +  //
>> +  // Iterate over the resources to populate the virtual BARs  //  Idx =
>> + Dev->BarOffset;  for (Desc = Dev->Device->Resources, Dev->BarCount =
>> + 0;
>> +       Desc->Desc != ACPI_END_TAG_DESCRIPTOR;
>> +       Desc = (VOID *)((UINT8 *)Desc + Desc->Len + 3)) {
>> +
>> +    ASSERT (Desc->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR);
>> +    ASSERT (Desc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM);
>> +
>> +    if (Idx >= PCI_MAX_BARS ||
>> +        (Idx == PCI_MAX_BARS - 1 && Desc->AddrSpaceGranularity == 64)) {
>> +      DEBUG ((DEBUG_ERROR,
>> +        "%a: resource count exceeds number of emulated BARs\n",
>> +        __FUNCTION__));
>> +      ASSERT (FALSE);
>> +      break;
>> +    }
>> +
>> +    Dev->ConfigSpace.Device.Bar[Idx] = (UINT32)Desc->AddrRangeMin;
>> +    Dev->BarCount++;
>> +
>> +    if (Desc->AddrSpaceGranularity == 64) {
>> +      Dev->ConfigSpace.Device.Bar[Idx] |= 0x4;
>> +      Dev->ConfigSpace.Device.Bar[++Idx] = (UINT32)(Desc-
>> >AddrRangeMin >> 32);
>> +    }
>> +  }
>> +}
>> diff --git
>> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> PciDeviceIo.h
>> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> PciDeviceIo.h
>> new file mode 100644
>> index 000000000000..bc0a3d3258f9
>> --- /dev/null
>> +++
>> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
>> Pc
>> +++ iDeviceIo.h
>> @@ -0,0 +1,84 @@
>> +/** @file
>> +
>> +  Copyright (C) 2016, Linaro Ltd. All rights reserved.<BR>
>> +
>> +  This program and the accompanying materials are licensed and made
>> + available  under the terms and conditions of the BSD License which
>> + accompanies this  distribution. The full text of the license may be
>> + found at  http://opensource.org/licenses/bsd-license.php
>> +
>> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
>> BASIS,
>> + WITHOUT  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
>> EXPRESS OR IMPLIED.
>> +
>> +**/
>> +
>> +#ifndef __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
>> +#define __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
>> +
>> +#include <Library/BaseMemoryLib.h>
>> +#include <Library/DebugLib.h>
>> +#include <Library/MemoryAllocationLib.h> #include
>> +<Library/UefiBootServicesTableLib.h>
>> +#include <Library/UefiLib.h>
>> +
>> +#include <IndustryStandard/Pci.h>
>> +
>> +#include <Protocol/ComponentName.h>
>> +#include <Protocol/NonDiscoverableDevice.h>
>> +#include <Protocol/PciIo.h>
>> +
>> +#define NON_DISCOVERABLE_PCI_DEVICE_SIG SIGNATURE_32 ('P', 'P', 'I',
>> +'D')
>> +
>> +#define NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(PciIoPointer) \
>> +        CR (PciIoPointer, NON_DISCOVERABLE_PCI_DEVICE, PciIo, \
>> +            NON_DISCOVERABLE_PCI_DEVICE_SIG)
>> +
>> +#define PCI_ID_VENDOR_UNKNOWN         0xffff
>> +#define PCI_ID_DEVICE_DONTCARE        0x0000
>> +
>> +#define PCI_MAX_BARS                  6
>> +
>> +typedef struct {
>> +  UINT32                    Signature;
>> +  //
>> +  // The bound non-discoverable device protocol instance
>> +  //
>> +  NON_DISCOVERABLE_DEVICE   *Device;
>> +  //
>> +  // The exposed PCI I/O protocol instance.
>> +  //
>> +  EFI_PCI_IO_PROTOCOL       PciIo;
>> +  //
>> +  // The emulated PCI config space of the device. Only the minimally
>> +required
>> +  // items are assigned.
>> +  //
>> +  PCI_TYPE00                ConfigSpace;
>> +  //
>> +  // The first virtual BAR to assign based on the resources described
>> +  // by the non-discoverable device.
>> +  //
>> +  UINT32                    BarOffset;
>> +  //
>> +  // The number of virtual BARs we expose based on the number of
>> +  // resources
>> +  //
>> +  UINT32                    BarCount;
>> +  //
>> +  // The PCI I/O attributes for this device
>> +  //
>> +  UINT64                    Attributes;
>> +  //
>> +  // Whether this device has been enabled
>> +  //
>> +  BOOLEAN                   Enabled;
>> +} NON_DISCOVERABLE_PCI_DEVICE;
>> +
>> +VOID
>> +InitializePciIoProtocol (
>> +  NON_DISCOVERABLE_PCI_DEVICE     *Device
>> +  );
>> +
>> +extern EFI_COMPONENT_NAME_PROTOCOL gComponentName; extern
>> +EFI_COMPONENT_NAME2_PROTOCOL gComponentName2;
>> +
>> +#endif
>> diff --git a/MdeModulePkg/MdeModulePkg.dsc
>> b/MdeModulePkg/MdeModulePkg.dsc index 43421d610ede..aac05408599d
>> 100644
>> --- a/MdeModulePkg/MdeModulePkg.dsc
>> +++ b/MdeModulePkg/MdeModulePkg.dsc
>> @@ -260,6 +260,7 @@ [Components]
>>    MdeModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf
>>    MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
>>    MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf
>> +
>> +
>> MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePci
>> Dev
>> + iceDxe.inf
>>
>>    MdeModulePkg/Core/Dxe/DxeMain.inf {
>>      <LibraryClasses>
>> --
>> 2.7.4
>


  reply	other threads:[~2016-11-18 12:30 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-16 16:59 [PATCH v3 0/5] MdeModulePkg: add support for non-discoverable devices Ard Biesheuvel
2016-11-16 16:59 ` [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol Ard Biesheuvel
2016-11-16 17:48   ` Leif Lindholm
2016-11-17  2:53     ` Ni, Ruiyu
2016-11-17  6:07       ` Ard Biesheuvel
2016-11-17  7:52         ` Ni, Ruiyu
2016-11-17 10:43           ` Ard Biesheuvel
2016-11-18  2:11             ` Ni, Ruiyu
2016-11-18  4:59               ` Ard Biesheuvel
2016-11-18  5:24                 ` Tian, Feng
2016-11-18  6:57                   ` Ard Biesheuvel
2016-11-18  8:39                     ` Tian, Feng
2016-11-18  8:52                       ` Ard Biesheuvel
2016-11-18  6:13                 ` Ni, Ruiyu
2016-11-18  7:04                   ` Ard Biesheuvel
2016-11-18 13:39                     ` Ni, Ruiyu
2016-11-18 13:50                       ` Ard Biesheuvel
2016-11-25 15:21                         ` Ard Biesheuvel
2016-11-16 16:59 ` [PATCH v3 2/5] MdeModule: introduce helper library to register non-discoverable devices Ard Biesheuvel
2016-11-16 16:59 ` [PATCH v3 3/5] MdeModulePkg: implement generic PCI I/O driver for " Ard Biesheuvel
2016-11-17  3:29   ` Ni, Ruiyu
2016-11-18 12:30     ` Ard Biesheuvel [this message]
2016-11-24 18:14       ` Ard Biesheuvel
2016-11-16 16:59 ` [PATCH v3 4/5] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA Ard Biesheuvel
2016-11-16 16:59 ` [PATCH v3 5/5] Omap35xxPkg/PciEmulation: port to new non-discoverable device infrastructure Ard Biesheuvel
2016-11-17  4:36 ` [PATCH v3 0/5] MdeModulePkg: add support for non-discoverable devices Marcin Wojtas
2016-11-23 14:31   ` Marcin Wojtas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAKv+Gu91SCK-H=jjK=i0ULeHaXjREsZhamhsM+hJH5kzqyR4Hw@mail.gmail.com' \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox