public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v3 0/5] MdeModulePkg: add support for non-discoverable devices
@ 2016-11-16 16:59 Ard Biesheuvel
  2016-11-16 16:59 ` [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol Ard Biesheuvel
                   ` (5 more replies)
  0 siblings, 6 replies; 27+ messages in thread
From: Ard Biesheuvel @ 2016-11-16 16:59 UTC (permalink / raw)
  To: edk2-devel, liming.gao, ruiyu.ni, michael.d.kinney
  Cc: afish, mw, leif.lindholm, Ard Biesheuvel

The rationale for this series is the fact that many ARM platforms implement
some form of PCI 'emulation', to allow non-discoverable devices that implement
standardized host controller interfaces (i.e., EHCI, AHCI) to be controlled by
the generic EDK2 drivers, which are layered on top of the PCI I/O protocols
(even though the respective host controller specifications don't mandate that)

There are a couple of problems with that approach:
- Most implementations are based on the original code created for BeagleBoard,
  which is a 32-bit platform. Unlike x86, which usually does not perform PCI
  DMA above 4 GB, the ARM ecosystem is much more heterogeneous, and platforms
  that have memory both above and below the 4 GB mark may ship with, e.g., EHCI
  controllers that do not implement 64-bit DMA addressing.
- Implementations depend on the DmaLib library class in EmbeddedPkg, of which
  coherent and non-coherent implementations exists. However, both types of
  devices may appear on a single platform, requiring several instances of the
  same driver.
- Existing implementations do not follow the UEFI driver model, but instantiate
  a fixed number of PCI I/O protocol handles, and bring up all the devices when
  doing so. However, the UEFI philosophy is to only instantiate (and thus
  initialize) devices that are involved in booting.

So instead, let's define a base protocol that simply asserts the presence of
a certain kind of device at a certain memory offset, allowing platforms to
instantiate any number of these statically, and leave it to post-DXE driver
dispatch to actually bind the drivers as usual. This is implemented in patch #1.
Note that it includes an AMBA device type, which we intend to use in the future
to move ARM AMBA drivers to the UEFI driver model as well (i.e., LCD controller,
SD/MMC controller)

Patch #2 implements a utility library to register non-discoverable devices.

Patch #3 implements the UEFI driver that instantiates PCI I/O protocol handles
for non-discoverable devices that we know can be driven by a generic driver in
EDK2. The initial version implements coherent DMA only.

Patch #4 implements non-coherent DMA for the driver added in patch #3.

Patch #5 is included for reference. It ports the BeagleBoard platform to the
new driver stack.

Changes in v3:
- Modified the base protocol to describe any number of resources using ACPI
  resource descriptors. The current crop of targeted peripherals does not
  require that, but it allows for much more flexibility in the future. This
  also means that the MMIO region sizes are no longer hard-coded base on the
  controller type (EHCI, AHCI, etc) but need to be declared when the devices
  are registered.
- Update the registration library API to allow multiple MMIO regions to be
  declared.
- When performing uncached allocations, record the original memory region
  attributes so we can restore them correctly on free.
- Some fixes in the 4GB boundary checks for Map/Unmap
- Rename gNonDiscoverableDeviceProtocolGuid to
  gEdkiiNonDiscoverableDeviceProtocolGuid

Ard Biesheuvel (5):
  MdeModulePkg: introduce non-discoverable device protocol
  MdeModule: introduce helper library to register non-discoverable
    devices
  MdeModulePkg: implement generic PCI I/O driver for non-discoverable
    devices
  MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent
    DMA
  Omap35xxPkg/PciEmulation: port to new non-discoverable device
    infrastructure

 BeagleBoardPkg/BeagleBoardPkg.dsc                                                                  |    2 +
 BeagleBoardPkg/BeagleBoardPkg.fdf                                                                  |    1 +
 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/ComponentName.c                                   |   75 ++
 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c                     |  226 ++++
 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf                   |   44 +
 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c                      | 1187 ++++++++++++++++++++
 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h                      |  113 ++
 MdeModulePkg/Include/Library/NonDiscoverableDeviceRegistrationLib.h                                |   49 +
 MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h                                              |   90 ++
 MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.c   |  161 +++
 MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf |   34 +
 MdeModulePkg/MdeModulePkg.dec                                                                      |    7 +
 MdeModulePkg/MdeModulePkg.dsc                                                                      |    3 +
 Omap35xxPkg/Omap35xxPkg.dsc                                                                        |    2 +-
 Omap35xxPkg/PciEmulation/PciEmulation.c                                                            |  578 +---------
 Omap35xxPkg/PciEmulation/PciEmulation.h                                                            |  292 -----
 Omap35xxPkg/PciEmulation/PciEmulation.inf                                                          |   16 +-
 Omap35xxPkg/PciEmulation/PciRootBridgeIo.c                                                         |  306 -----
 18 files changed, 2025 insertions(+), 1161 deletions(-)
 create mode 100644 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/ComponentName.c
 create mode 100644 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
 create mode 100644 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
 create mode 100644 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
 create mode 100644 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h
 create mode 100644 MdeModulePkg/Include/Library/NonDiscoverableDeviceRegistrationLib.h
 create mode 100644 MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
 create mode 100644 MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.c
 create mode 100644 MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
 delete mode 100644 Omap35xxPkg/PciEmulation/PciEmulation.h
 delete mode 100644 Omap35xxPkg/PciEmulation/PciRootBridgeIo.c

-- 
2.7.4



^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol
  2016-11-16 16:59 [PATCH v3 0/5] MdeModulePkg: add support for non-discoverable devices Ard Biesheuvel
@ 2016-11-16 16:59 ` Ard Biesheuvel
  2016-11-16 17:48   ` Leif Lindholm
  2016-11-16 16:59 ` [PATCH v3 2/5] MdeModule: introduce helper library to register non-discoverable devices Ard Biesheuvel
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 27+ messages in thread
From: Ard Biesheuvel @ 2016-11-16 16:59 UTC (permalink / raw)
  To: edk2-devel, liming.gao, ruiyu.ni, michael.d.kinney
  Cc: afish, mw, leif.lindholm, Ard Biesheuvel

Introduce a protocol that can be exposed by a platform for devices that
are not discoverable, usually because they are wired straight to the
memory bus rather than to an enumerable bus like PCI or USB.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h | 90 ++++++++++++++++++++
 MdeModulePkg/MdeModulePkg.dec                         |  3 +
 2 files changed, 93 insertions(+)

diff --git a/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
new file mode 100644
index 000000000000..47ed841b407b
--- /dev/null
+++ b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
@@ -0,0 +1,90 @@
+/** @file
+  Protocol to describe devices that are not on a discoverable bus
+
+  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_DEVICE_H__
+#define __NON_DISCOVERABLE_DEVICE_H__
+
+#include <IndustryStandard/Acpi.h>
+
+#define EDKII_NON_DISCOVERABLE_DEVICE_PROTOCOL_GUID \
+  { 0x0d51905b, 0xb77e, 0x452a, {0xa2, 0xc0, 0xec, 0xa0, 0xcc, 0x8d, 0x51, 0x4a } }
+
+//
+// Protocol interface structure
+//
+typedef struct _NON_DISCOVERABLE_DEVICE NON_DISCOVERABLE_DEVICE;
+
+//
+// Data Types
+//
+typedef enum {
+  NonDiscoverableDeviceTypeAmba,
+  NonDiscoverableDeviceTypeOhci,
+  NonDiscoverableDeviceTypeUhci,
+  NonDiscoverableDeviceTypeEhci,
+  NonDiscoverableDeviceTypeXhci,
+  NonDiscoverableDeviceTypeAhci,
+  NonDiscoverableDeviceTypeSdhci,
+  NonDiscoverableDeviceTypeUfs,
+  NonDiscoverableDeviceTypeNvme,
+  NonDiscoverableDeviceTypeMax,
+} NON_DISCOVERABLE_DEVICE_TYPE;
+
+typedef enum {
+  NonDiscoverableDeviceDmaTypeCoherent,
+  NonDiscoverableDeviceDmaTypeNonCoherent,
+  NonDiscoverableDeviceDmaTypeMax,
+} NON_DISCOVERABLE_DEVICE_DMA_TYPE;
+
+//
+// Function Prototypes
+//
+
+/**
+  Perform device specific initialization before the device is started
+
+  @param  This          The non-discoverable device protocol pointer
+
+  @retval EFI_SUCCESS   Initialization successful, the device may be used
+  @retval Other         Initialization failed, device should not be started
+**/
+typedef
+EFI_STATUS
+(EFIAPI *NON_DISCOVERABLE_DEVICE_INIT) (
+  IN  NON_DISCOVERABLE_DEVICE       *This
+  );
+
+struct _NON_DISCOVERABLE_DEVICE {
+  //
+  // The type of device
+  //
+  NON_DISCOVERABLE_DEVICE_TYPE        Type;
+  //
+  // Whether this device is DMA coherent
+  //
+  NON_DISCOVERABLE_DEVICE_DMA_TYPE    DmaType;
+  //
+  // Initialization function for the device
+  //
+  NON_DISCOVERABLE_DEVICE_INIT        Initialize;
+  //
+  // The MMIO and I/O regions owned by the device
+  //
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Resources;
+};
+
+extern EFI_GUID gEdkiiNonDiscoverableDeviceProtocolGuid;
+
+#endif
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 74b870051c67..6b956fc80c93 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -505,6 +505,9 @@ [Protocols]
   #  Include/Protocol/Ps2Policy.h
   gEfiPs2PolicyProtocolGuid = { 0x4DF19259, 0xDC71, 0x4D46, { 0xBE, 0xF1, 0x35, 0x7B, 0xB5, 0x78, 0xC4, 0x18 } }
 
+  ## Include/Protocol/NonDiscoverableDevice.h
+  gEdkiiNonDiscoverableDeviceProtocolGuid = { 0x0d51905b, 0xb77e, 0x452a, {0xa2, 0xc0, 0xec, 0xa0, 0xcc, 0x8d, 0x51, 0x4a } }
+
 #
 # [Error.gEfiMdeModulePkgTokenSpaceGuid]
 #   0x80000001 | Invalid value provided.
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 2/5] MdeModule: introduce helper library to register non-discoverable devices
  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 16:59 ` Ard Biesheuvel
  2016-11-16 16:59 ` [PATCH v3 3/5] MdeModulePkg: implement generic PCI I/O driver for " Ard Biesheuvel
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 27+ messages in thread
From: Ard Biesheuvel @ 2016-11-16 16:59 UTC (permalink / raw)
  To: edk2-devel, liming.gao, ruiyu.ni, michael.d.kinney
  Cc: afish, mw, leif.lindholm, Ard Biesheuvel

Non-discoverable devices need to be registered explicitly by the platform.
Introduce a helper library that takes care of this.

This implementation currently only supports registering devices that are
covered by one or more MMIO resources. The underlying protocol allows for
more flexibility than that, but this is currently sufficient for the use
cases that we know about.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 MdeModulePkg/Include/Library/NonDiscoverableDeviceRegistrationLib.h                                |  49 ++++++
 MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.c   | 161 ++++++++++++++++++++
 MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf |  34 +++++
 MdeModulePkg/MdeModulePkg.dec                                                                      |   4 +
 MdeModulePkg/MdeModulePkg.dsc                                                                      |   2 +
 5 files changed, 250 insertions(+)

diff --git a/MdeModulePkg/Include/Library/NonDiscoverableDeviceRegistrationLib.h b/MdeModulePkg/Include/Library/NonDiscoverableDeviceRegistrationLib.h
new file mode 100644
index 000000000000..d5535e2e435c
--- /dev/null
+++ b/MdeModulePkg/Include/Library/NonDiscoverableDeviceRegistrationLib.h
@@ -0,0 +1,49 @@
+/** @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_DEVICE_REGISTRATION_LIB_H__
+#define __NON_DISCOVERABLE_DEVICE_REGISTRATION_LIB_H__
+
+#include <Protocol/NonDiscoverableDevice.h>
+
+/**
+  Register a non-discoverable MMIO device
+
+  @param[in]      DeviceType          The type of non-discoverable device
+  @param[in]      DmaType             Whether the device is DMA coherent
+  @param[in]      InitFunc            Initialization routine to be invoked when
+                                      the device is enabled
+  @param[in,out]  Handle              The handle onto which to install the
+                                      non-discoverable device protocol.
+                                      If Handle is NULL or *Handle is NULL, a
+                                      new handle will be allocated.
+  @param[in]      NumMmioResources    The number of UINTN base/size pairs that
+                                      follow, each describing an MMIO region
+                                      owned by the device
+
+  @retval EFI_SUCCESS                 The registration succeeded.
+  @retval Other                       The registration failed.
+
+**/
+EFI_STATUS
+EFIAPI
+RegisterNonDiscoverableMmioDevice (
+  IN      NON_DISCOVERABLE_DEVICE_TYPE      Type,
+  IN      NON_DISCOVERABLE_DEVICE_DMA_TYPE  DmaType,
+  IN      NON_DISCOVERABLE_DEVICE_INIT      InitFunc,
+  IN OUT  EFI_HANDLE                        *Handle OPTIONAL,
+  IN      UINTN                             NumMmioResources,
+  ...
+  );
+
+#endif
diff --git a/MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.c b/MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.c
new file mode 100644
index 000000000000..524b6794e18f
--- /dev/null
+++ b/MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.c
@@ -0,0 +1,161 @@
+/** @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.
+
+**/
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NonDiscoverableDeviceRegistrationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/DevicePath.h>
+#include <Protocol/NonDiscoverableDevice.h>
+
+#pragma pack (1)
+typedef struct {
+  VENDOR_DEVICE_PATH                  Vendor;
+  UINT64                              BaseAddress;
+  UINT8                               ResourceType;
+  EFI_DEVICE_PATH_PROTOCOL            End;
+} NON_DISCOVERABLE_DEVICE_PATH;
+#pragma pack ()
+
+/**
+  Register a non-discoverable MMIO device
+
+  @param[in]      DeviceType          The type of non-discoverable device
+  @param[in]      DmaType             Whether the device is DMA coherent
+  @param[in]      InitFunc            Initialization routine to be invoked when
+                                      the device is enabled
+  @param[in,out]  Handle              The handle onto which to install the
+                                      non-discoverable device protocol.
+                                      If Handle is NULL or *Handle is NULL, a
+                                      new handle will be allocated.
+  @param[in]      NumMmioResources    The number of UINTN base/size pairs that
+                                      follow, each describing an MMIO region
+                                      owned by the device
+
+  @retval EFI_SUCCESS                 The registration succeeded.
+  @retval EFI_INVALID_PARAMETER       An invalid argument was given
+  @retval Other                       The registration failed.
+
+**/
+EFI_STATUS
+EFIAPI
+RegisterNonDiscoverableMmioDevice (
+  IN      NON_DISCOVERABLE_DEVICE_TYPE      Type,
+  IN      NON_DISCOVERABLE_DEVICE_DMA_TYPE  DmaType,
+  IN      NON_DISCOVERABLE_DEVICE_INIT      InitFunc,
+  IN OUT  EFI_HANDLE                        *Handle OPTIONAL,
+  IN      UINTN                             NumMmioResources,
+  ...
+  )
+{
+  NON_DISCOVERABLE_DEVICE             *Device;
+  NON_DISCOVERABLE_DEVICE_PATH        *DevicePath;
+  EFI_HANDLE                          LocalHandle;
+  EFI_STATUS                          Status;
+  UINTN                               AllocSize;
+  UINTN                               Index;
+  VA_LIST                             Args;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Desc;
+  EFI_ACPI_END_TAG_DESCRIPTOR         *End;
+  UINTN                               Base, Size;
+
+  if (Type >= NonDiscoverableDeviceTypeMax ||
+      DmaType >= NonDiscoverableDeviceDmaTypeMax ||
+      NumMmioResources == 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Handle == NULL) {
+    Handle = &LocalHandle;
+    LocalHandle = NULL;
+  }
+
+  AllocSize = sizeof *Device +
+              NumMmioResources * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +
+              sizeof (EFI_ACPI_END_TAG_DESCRIPTOR);
+  Device = (NON_DISCOVERABLE_DEVICE *)AllocateZeroPool (AllocSize);
+  if (Device == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Device->Type = Type;
+  Device->DmaType = DmaType;
+  Device->Initialize = InitFunc;
+  Device->Resources = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(Device + 1);
+
+  VA_START (Args, NumMmioResources);
+  for (Index = 0; Index < NumMmioResources; Index++) {
+    Desc = &Device->Resources [Index];
+    Base = VA_ARG (Args, UINTN);
+    Size = VA_ARG (Args, UINTN);
+
+    Desc->Desc                  = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+    Desc->Len                   = sizeof *Desc - 3;
+    Desc->AddrRangeMin          = Base;
+    Desc->AddrLen               = Size;
+    Desc->AddrRangeMax          = Base + Size - 1;
+    Desc->ResType               = ACPI_ADDRESS_SPACE_TYPE_MEM;
+    Desc->AddrSpaceGranularity  = (Base + Size > SIZE_4GB) ? 64 : 32;
+    Desc->AddrTranslationOffset = 0;
+  }
+  VA_END (Args);
+
+  End = (EFI_ACPI_END_TAG_DESCRIPTOR *)&Device->Resources [NumMmioResources];
+
+  End->Desc     = ACPI_END_TAG_DESCRIPTOR;
+  End->Checksum = 0;
+
+  DevicePath = (NON_DISCOVERABLE_DEVICE_PATH *)CreateDeviceNode (
+                                                 HARDWARE_DEVICE_PATH,
+                                                 HW_VENDOR_DP,
+                                                 sizeof (*DevicePath));
+  if (DevicePath == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto FreeDevice;
+  }
+
+  CopyGuid (&DevicePath->Vendor.Guid, &gEdkiiNonDiscoverableDeviceProtocolGuid);
+
+  //
+  // Use the base address and type of the first region to
+  // make the device path unique
+  //
+  DevicePath->BaseAddress = Device->Resources [0].AddrRangeMin;
+  DevicePath->ResourceType = Device->Resources [0].ResType;
+
+  SetDevicePathNodeLength (&DevicePath->Vendor,
+    sizeof (*DevicePath) - sizeof (DevicePath->End));
+  SetDevicePathEndNode (&DevicePath->End);
+
+  Status = gBS->InstallMultipleProtocolInterfaces (Handle,
+                  &gEdkiiNonDiscoverableDeviceProtocolGuid, Device,
+                  &gEfiDevicePathProtocolGuid, DevicePath,
+                  NULL);
+  if (EFI_ERROR (Status)) {
+    goto FreeDevicePath;
+  }
+  return EFI_SUCCESS;
+
+FreeDevicePath:
+  FreePool (DevicePath);
+
+FreeDevice:
+  FreePool (Device);
+
+  return Status;
+}
diff --git a/MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf b/MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
new file mode 100644
index 000000000000..fc252c4b183c
--- /dev/null
+++ b/MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
@@ -0,0 +1,34 @@
+# @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.
+#
+
+[Defines]
+  INF_VERSION                    = 0x00010019
+  BASE_NAME                      = NonDiscoverableDeviceRegistrationLib
+  FILE_GUID                      = 8802ae41-8184-49cb-8aec-62627cd7ceb4
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = NonDiscoverableDeviceRegistrationLib
+
+[Sources]
+  NonDiscoverableDeviceRegistrationLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  DebugLib
+  DevicePathLib
+  UefiBootServicesTableLib
+
+[Protocols]
+  gEdkiiNonDiscoverableDeviceProtocolGuid
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 6b956fc80c93..930debea695b 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -157,6 +157,10 @@ [LibraryClasses]
   ##
   FrameBufferBltLib|Include/Library/FrameBufferBltLib.h
 
+  ## @libraryclass   Provides a service to register non-discoverable device
+  ##
+  NonDiscoverableDeviceRegistrationLib|Include/Library/NonDiscoverableDeviceRegistrationLib.h
+
 [Guids]
   ## MdeModule package token space guid
   # Include/Guid/MdeModulePkgTokenSpace.h
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index 757d52dbede4..43421d610ede 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -102,6 +102,7 @@ [LibraryClasses]
   AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
   VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
   FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
+  NonDiscoverableDeviceRegistrationLib|MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
 
 [LibraryClasses.EBC.PEIM]
   IoLib|MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf
@@ -317,6 +318,7 @@ [Components]
   MdeModulePkg/Library/PeiIpmiLibIpmiPpi/PeiIpmiLibIpmiPpi.inf
   MdeModulePkg/Library/SmmIpmiLibSmmIpmiProtocol/SmmIpmiLibSmmIpmiProtocol.inf
   MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
+  MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
 
   MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
   MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuApp.inf
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 3/5] MdeModulePkg: implement generic PCI I/O driver for non-discoverable devices
  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 16:59 ` [PATCH v3 2/5] MdeModule: introduce helper library to register non-discoverable devices Ard Biesheuvel
@ 2016-11-16 16:59 ` Ard Biesheuvel
  2016-11-17  3:29   ` Ni, Ruiyu
  2016-11-16 16:59 ` [PATCH v3 4/5] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA Ard Biesheuvel
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 27+ messages in thread
From: Ard Biesheuvel @ 2016-11-16 16:59 UTC (permalink / raw)
  To: edk2-devel, liming.gao, ruiyu.ni, michael.d.kinney
  Cc: afish, mw, leif.lindholm, Ard Biesheuvel

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/NonDiscoverablePciDeviceDxe.c   | 223 +++++
 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf |  42 +
 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c    | 868 ++++++++++++++++++++
 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h    |  84 ++
 MdeModulePkg/MdeModulePkg.dsc                                                    |   1 +
 6 files changed, 1293 insertions(+)

diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/ComponentName.c b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/ComponentName.c
new file mode 100644
index 000000000000..6e51d00fe434
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/ComponentName.c
@@ -0,0 +1,75 @@
+/** @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.
+
+**/
+
+#include "NonDiscoverablePciDeviceIo.h"
+
+//
+// The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
+// EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
+// in English, for display on standard console devices. This is recommended for
+// UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
+// Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
+//
+
+STATIC
+EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
+  { "eng;en", L"PCI I/O protocol emulation driver for non-discoverable devices" },
+  { NULL,     NULL                   }
+};
+
+EFI_COMPONENT_NAME_PROTOCOL gComponentName;
+
+STATIC
+EFI_STATUS
+EFIAPI
+NonDiscoverablePciGetDriverName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL *This,
+  IN  CHAR8                       *Language,
+  OUT CHAR16                      **DriverName
+  )
+{
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           mDriverNameTable,
+           DriverName,
+           (BOOLEAN)(This == &gComponentName) // Iso639Language
+           );
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+NonDiscoverablePciGetDeviceName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL *This,
+  IN  EFI_HANDLE                  DeviceHandle,
+  IN  EFI_HANDLE                  ChildHandle,
+  IN  CHAR8                       *Language,
+  OUT CHAR16                      **ControllerName
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EFI_COMPONENT_NAME_PROTOCOL gComponentName = {
+  &NonDiscoverablePciGetDriverName,
+  &NonDiscoverablePciGetDeviceName,
+  "eng" // SupportedLanguages, ISO 639-2 language codes
+};
+
+EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {
+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)     &NonDiscoverablePciGetDriverName,
+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &NonDiscoverablePciGetDeviceName,
+  "en" // SupportedLanguages, RFC 4646 language codes
+};
diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
new file mode 100644
index 000000000000..32da576485aa
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
@@ -0,0 +1,223 @@
+/** @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.
+
+**/
+
+#include "NonDiscoverablePciDeviceIo.h"
+
+#include <Protocol/DriverBinding.h>
+
+//
+// Probe, start and stop functions of this driver, called by the DXE core for
+// specific devices.
+//
+// The following specifications document these interfaces:
+// - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol
+// - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol
+//
+// The implementation follows:
+// - Driver Writer's Guide for UEFI 2.3.1 v1.01
+//   - 5.1.3.4 OpenProtocol() and CloseProtocol()
+// - UEFI Spec 2.3.1 + Errata C
+//   -  6.3 Protocol Handler Services
+//
+
+STATIC
+EFI_STATUS
+EFIAPI
+NonDiscoverablePciDeviceSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL *This,
+  IN EFI_HANDLE                  DeviceHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
+  )
+{
+  NON_DISCOVERABLE_DEVICE             *Device;
+  EFI_STATUS                          Status;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Desc;
+
+  Status = gBS->OpenProtocol (DeviceHandle,
+                  &gEdkiiNonDiscoverableDeviceProtocolGuid, (VOID **)&Device,
+                  This->DriverBindingHandle, DeviceHandle,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  switch (Device->Type) {
+  //
+  // We only support the following device types
+  //
+  case NonDiscoverableDeviceTypeOhci:
+  case NonDiscoverableDeviceTypeUhci:
+  case NonDiscoverableDeviceTypeEhci:
+  case NonDiscoverableDeviceTypeXhci:
+  case NonDiscoverableDeviceTypeAhci:
+  case NonDiscoverableDeviceTypeSdhci:
+  case NonDiscoverableDeviceTypeUfs:
+  case NonDiscoverableDeviceTypeNvme:
+    //
+    // Restricted to DMA coherent for now
+    //
+    if (Device->DmaType == NonDiscoverableDeviceDmaTypeCoherent) {
+      Status = EFI_SUCCESS;
+      break;
+    }
+  default:
+    Status = EFI_UNSUPPORTED;
+    goto CloseProtocol;
+  }
+
+  //
+  // We only support MMIO devices, so iterate over the resources to ensure
+  // that they only describe things that we can handle
+  //
+  for (Desc = Device->Resources; Desc->Desc != ACPI_END_TAG_DESCRIPTOR;
+       Desc = (VOID *)((UINT8 *)Desc + Desc->Len + 3)) {
+    if (Desc->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR ||
+        Desc->ResType != ACPI_ADDRESS_SPACE_TYPE_MEM) {
+      Status = EFI_UNSUPPORTED;
+      break;
+    }
+  }
+
+CloseProtocol:
+  gBS->CloseProtocol (DeviceHandle, &gEdkiiNonDiscoverableDeviceProtocolGuid,
+         This->DriverBindingHandle, DeviceHandle);
+
+  return Status;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+NonDiscoverablePciDeviceStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL *This,
+  IN EFI_HANDLE                  DeviceHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
+  )
+{
+  NON_DISCOVERABLE_PCI_DEVICE   *Dev;
+  EFI_STATUS                    Status;
+
+  Dev = AllocateZeroPool (sizeof *Dev);
+  if (Dev == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = gBS->OpenProtocol (DeviceHandle,
+                  &gEdkiiNonDiscoverableDeviceProtocolGuid,
+                  (VOID **)&Dev->Device, This->DriverBindingHandle,
+                  DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);
+  if (EFI_ERROR (Status)) {
+    goto FreeDev;
+  }
+
+  InitializePciIoProtocol (Dev);
+
+  //
+  // Setup complete, attempt to export the driver instance's
+  // EFI_PCI_IO_PROTOCOL interface.
+  //
+  Dev->Signature = NON_DISCOVERABLE_PCI_DEVICE_SIG;
+  Status = gBS->InstallProtocolInterface (&DeviceHandle, &gEfiPciIoProtocolGuid,
+                  EFI_NATIVE_INTERFACE, &Dev->PciIo);
+  if (EFI_ERROR (Status)) {
+    goto CloseProtocol;
+  }
+
+  return EFI_SUCCESS;
+
+CloseProtocol:
+  gBS->CloseProtocol (DeviceHandle, &gEdkiiNonDiscoverableDeviceProtocolGuid,
+         This->DriverBindingHandle, DeviceHandle);
+
+FreeDev:
+  FreePool (Dev);
+
+  return Status;
+}
+
+
+STATIC
+EFI_STATUS
+EFIAPI
+NonDiscoverablePciDeviceStop (
+  IN EFI_DRIVER_BINDING_PROTOCOL *This,
+  IN EFI_HANDLE                  DeviceHandle,
+  IN UINTN                       NumberOfChildren,
+  IN EFI_HANDLE                  *ChildHandleBuffer
+  )
+{
+  EFI_STATUS                      Status;
+  EFI_PCI_IO_PROTOCOL             *PciIo;
+  NON_DISCOVERABLE_PCI_DEVICE     *Dev;
+
+  Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
+                  (VOID **)&PciIo, This->DriverBindingHandle, DeviceHandle,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (PciIo);
+
+  //
+  // Handle Stop() requests for in-use driver instances gracefully.
+  //
+  Status = gBS->UninstallProtocolInterface (DeviceHandle,
+                  &gEfiPciIoProtocolGuid, &Dev->PciIo);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  gBS->CloseProtocol (DeviceHandle, &gEdkiiNonDiscoverableDeviceProtocolGuid,
+         This->DriverBindingHandle, DeviceHandle);
+
+  FreePool (Dev);
+
+  return EFI_SUCCESS;
+}
+
+
+//
+// The static object that groups the Supported() (ie. probe), Start() and
+// Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
+// C, 10.1 EFI Driver Binding Protocol.
+//
+STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
+  &NonDiscoverablePciDeviceSupported,
+  &NonDiscoverablePciDeviceStart,
+  &NonDiscoverablePciDeviceStop,
+  0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
+  NULL,
+  NULL
+};
+
+//
+// Entry point of this driver.
+//
+EFI_STATUS
+EFIAPI
+NonDiscoverablePciDeviceDxeEntryPoint (
+  IN EFI_HANDLE       ImageHandle,
+  IN EFI_SYSTEM_TABLE *SystemTable
+  )
+{
+  return EfiLibInstallDriverBindingComponentName2 (
+           ImageHandle,
+           SystemTable,
+           &gDriverBinding,
+           ImageHandle,
+           &gComponentName,
+           &gComponentName2
+           );
+}
diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
new file mode 100644
index 000000000000..543e622694a0
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
@@ -0,0 +1,42 @@
+## @file
+# Copyright (C) 2016, Linaro Ltd.
+#
+# 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.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010019
+  BASE_NAME                      = NonDiscoverablePciDeviceDxe
+  FILE_GUID                      = 71fd84cd-353b-464d-b7a4-6ea7b96995cb
+  MODULE_TYPE                    = UEFI_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = NonDiscoverablePciDeviceDxeEntryPoint
+
+[Sources]
+  ComponentName.c
+  NonDiscoverablePciDeviceDxe.c
+  NonDiscoverablePciDeviceIo.c
+  NonDiscoverablePciDeviceIo.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  DebugLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  UefiLib
+
+[Protocols]
+  gEfiPciIoProtocolGuid                         ## BY_START
+  gEdkiiNonDiscoverableDeviceProtocolGuid       ## TO_START
diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
new file mode 100644
index 000000000000..23466318bfc1
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.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;
+    } 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;
+
+    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;
+    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/NonDiscoverablePciDeviceIo.h b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h
new file mode 100644
index 000000000000..bc0a3d3258f9
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.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/NonDiscoverablePciDeviceDxe.inf
 
   MdeModulePkg/Core/Dxe/DxeMain.inf {
     <LibraryClasses>
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 4/5] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA
  2016-11-16 16:59 [PATCH v3 0/5] MdeModulePkg: add support for non-discoverable devices Ard Biesheuvel
                   ` (2 preceding siblings ...)
  2016-11-16 16:59 ` [PATCH v3 3/5] MdeModulePkg: implement generic PCI I/O driver for " Ard Biesheuvel
@ 2016-11-16 16:59 ` 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
  5 siblings, 0 replies; 27+ messages in thread
From: Ard Biesheuvel @ 2016-11-16 16:59 UTC (permalink / raw)
  To: edk2-devel, liming.gao, ruiyu.ni, michael.d.kinney
  Cc: afish, mw, leif.lindholm, Ard Biesheuvel

Add support for non-coherent DMA, either by performing explicit cache
maintenance when DMA mappings are aligned to the CPU's DMA buffer alignment,
or by bounce buffering via uncached mappings otherwise.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c   |  17 +-
 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf |   2 +
 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c    | 319 ++++++++++++++++++++
 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h    |  29 ++
 4 files changed, 360 insertions(+), 7 deletions(-)

diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
index 32da576485aa..8159c98338fb 100644
--- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
@@ -16,6 +16,8 @@
 
 #include <Protocol/DriverBinding.h>
 
+EFI_CPU_ARCH_PROTOCOL      *mCpu;
+
 //
 // Probe, start and stop functions of this driver, called by the DXE core for
 // specific devices.
@@ -64,13 +66,9 @@ NonDiscoverablePciDeviceSupported (
   case NonDiscoverableDeviceTypeSdhci:
   case NonDiscoverableDeviceTypeUfs:
   case NonDiscoverableDeviceTypeNvme:
-    //
-    // Restricted to DMA coherent for now
-    //
-    if (Device->DmaType == NonDiscoverableDeviceDmaTypeCoherent) {
-      Status = EFI_SUCCESS;
-      break;
-    }
+    Status = EFI_SUCCESS;
+    break;
+
   default:
     Status = EFI_UNSUPPORTED;
     goto CloseProtocol;
@@ -212,6 +210,11 @@ NonDiscoverablePciDeviceDxeEntryPoint (
   IN EFI_SYSTEM_TABLE *SystemTable
   )
 {
+  EFI_STATUS      Status;
+
+  Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&mCpu);
+  ASSERT_EFI_ERROR(Status);
+
   return EfiLibInstallDriverBindingComponentName2 (
            ImageHandle,
            SystemTable,
diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
index 543e622694a0..3ffc634840c7 100644
--- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
@@ -32,6 +32,7 @@ [Packages]
 [LibraryClasses]
   BaseMemoryLib
   DebugLib
+  DxeServicesTableLib
   MemoryAllocationLib
   UefiBootServicesTableLib
   UefiDriverEntryPoint
@@ -40,3 +41,4 @@ [LibraryClasses]
 [Protocols]
   gEfiPciIoProtocolGuid                         ## BY_START
   gEdkiiNonDiscoverableDeviceProtocolGuid       ## TO_START
+  gEfiCpuArchProtocolGuid                       ## CONSUMES
diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
index 23466318bfc1..db91d065a330 100644
--- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
@@ -15,6 +15,8 @@
 
 #include "NonDiscoverablePciDeviceIo.h"
 
+#include <Library/DxeServicesTableLib.h>
+
 #include <IndustryStandard/Acpi.h>
 
 #include <Protocol/PciRootBridgeIo.h>
@@ -579,6 +581,316 @@ CoherentPciIoFreeBuffer (
   return EFI_SUCCESS;
 }
 
+STATIC
+EFI_STATUS
+NonCoherentPciIoFreeBuffer (
+  IN  EFI_PCI_IO_PROTOCOL         *This,
+  IN  UINTN                       Pages,
+  IN  VOID                        *HostAddress
+  )
+{
+  NON_DISCOVERABLE_PCI_DEVICE                   *Dev;
+  LIST_ENTRY                                    *Entry;
+  EFI_STATUS                                    Status;
+  NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION   *Alloc;
+  BOOLEAN                                       Found;
+
+  Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
+
+  Found = FALSE;
+
+  //
+  // Find the uncached allocation list entry associated
+  // with this allocation
+  //
+  for (Entry = Dev->UncachedAllocationList.ForwardLink;
+       Entry != &Dev->UncachedAllocationList;
+       Entry = Entry->ForwardLink) {
+
+    Alloc = BASE_CR (Entry, NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION, List);
+    if (Alloc->HostAddress == HostAddress && Alloc->NumPages == Pages) {
+      //
+      // We are freeing the exact allocation we were given
+      // before by AllocateBuffer()
+      //
+      Found = TRUE;
+      break;
+    }
+  }
+
+  if (!Found) {
+    ASSERT_EFI_ERROR (EFI_NOT_FOUND);
+    return EFI_NOT_FOUND;
+  }
+
+  RemoveEntryList (&Alloc->List);
+
+  Status = gDS->SetMemorySpaceAttributes (
+                  (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,
+                  EFI_PAGES_TO_SIZE (Pages),
+                  Alloc->Attributes);
+  if (EFI_ERROR (Status)) {
+    goto FreeAlloc;
+  }
+
+  //
+  // If we fail to restore the original attributes, it is better to leak the
+  // memory than to return it to the heap
+  //
+  FreePages (HostAddress, Pages);
+
+FreeAlloc:
+  FreePool (Alloc);
+  return Status;
+}
+
+STATIC
+EFI_STATUS
+NonCoherentPciIoAllocateBuffer (
+  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_GCD_MEMORY_SPACE_DESCRIPTOR             GcdDescriptor;
+  EFI_STATUS                                  Status;
+  UINT64                                      MemType;
+  NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc;
+
+  Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
+
+  Status = CoherentPciIoAllocateBuffer (This, Type, MemoryType, Pages,
+             HostAddress, Attributes);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = gDS->GetMemorySpaceDescriptor (
+                  (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,
+                  &GcdDescriptor);
+  if (EFI_ERROR (Status)) {
+    goto FreeBuffer;
+  }
+
+  if ((GcdDescriptor.Capabilities & (EFI_MEMORY_WC | EFI_MEMORY_UC)) == 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Set the preferred memory attributes
+  //
+  if ((Attributes & EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE) != 0 ||
+      (GcdDescriptor.Capabilities & EFI_MEMORY_UC) == 0) {
+    //
+    // Use write combining if it was requested, or if it is the only
+    // type supported by the region.
+    //
+    MemType = EFI_MEMORY_WC;
+  } else {
+    MemType = EFI_MEMORY_UC;
+  }
+
+  Alloc = AllocatePool (sizeof *Alloc);
+  if (Alloc == NULL) {
+    goto FreeBuffer;
+  }
+
+  Alloc->HostAddress = *HostAddress;
+  Alloc->NumPages = Pages;
+  Alloc->Attributes = GcdDescriptor.Attributes;
+
+  //
+  // Record this allocation in the linked list, so we
+  // can restore the memory space attributes later
+  //
+  InsertHeadList (&Dev->UncachedAllocationList, &Alloc->List);
+
+  Status = gDS->SetMemorySpaceAttributes (
+                  (EFI_PHYSICAL_ADDRESS)(UINTN)*HostAddress,
+                  EFI_PAGES_TO_SIZE (Pages),
+                  MemType);
+  if (EFI_ERROR (Status)) {
+    goto RemoveList;
+  }
+
+  Status = mCpu->FlushDataCache (
+                   mCpu,
+                   (EFI_PHYSICAL_ADDRESS)(UINTN)*HostAddress,
+                   EFI_PAGES_TO_SIZE (Pages),
+                   EfiCpuFlushTypeInvalidate);
+  if (EFI_ERROR (Status)) {
+    goto RemoveList;
+  }
+
+  return EFI_SUCCESS;
+
+RemoveList:
+  RemoveEntryList (&Alloc->List);
+  FreePool (Alloc);
+
+FreeBuffer:
+  NonCoherentPciIoFreeBuffer (This, Pages, *HostAddress);
+  return Status;
+}
+
+STATIC
+EFI_STATUS
+NonCoherentPciIoMap (
+  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;
+  UINTN                                 AlignMask;
+  VOID                                  *AllocAddress;
+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR       GcdDescriptor;
+  BOOLEAN                               Bounce;
+
+  MapInfo = AllocatePool (sizeof *MapInfo);
+  if (MapInfo == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  MapInfo->HostAddress = HostAddress;
+  MapInfo->Operation = Operation;
+  MapInfo->NumberOfBytes = *NumberOfBytes;
+
+  Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This);
+
+  //
+  // If this device does not support 64-bit DMA addressing, we need to allocate
+  // a bounce buffer and copy over the data in case HostAddress >= 4 GB.
+  //
+  Bounce = ((Dev->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0 &&
+            (UINTN)HostAddress + *NumberOfBytes > SIZE_4GB);
+
+  if (!Bounce) {
+    switch (Operation) {
+    case EfiPciIoOperationBusMasterRead:
+    case EfiPciIoOperationBusMasterWrite:
+      //
+      // For streaming DMA, it is sufficient if the buffer is aligned to
+      // the CPUs DMA buffer alignment.
+      //
+      AlignMask = mCpu->DmaBufferAlignment - 1;
+      if ((((UINTN) HostAddress | *NumberOfBytes) & AlignMask) == 0) {
+        break;
+      }
+      // fall through
+
+    case EfiPciIoOperationBusMasterCommonBuffer:
+      //
+      // Check whether the host address refers to an uncached mapping.
+      //
+      Status = gDS->GetMemorySpaceDescriptor (
+                      (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,
+                      &GcdDescriptor);
+      if (EFI_ERROR (Status) ||
+          (GcdDescriptor.Attributes & (EFI_MEMORY_WB|EFI_MEMORY_WT)) != 0) {
+        Bounce = TRUE;
+      }
+      break;
+
+    default:
+      ASSERT (FALSE);
+    }
+  }
+
+  if (Bounce) {
+    if (Operation == EfiPciIoOperationBusMasterCommonBuffer) {
+      Status = EFI_DEVICE_ERROR;
+      goto FreeMapInfo;
+    }
+
+    Status = NonCoherentPciIoAllocateBuffer (This, AllocateAnyPages,
+               EfiBootServicesData, EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes),
+               &AllocAddress, EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE);
+    if (EFI_ERROR (Status)) {
+      goto FreeMapInfo;
+    }
+    MapInfo->AllocAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress;
+    if (Operation == EfiPciIoOperationBusMasterRead) {
+      gBS->CopyMem (AllocAddress, HostAddress, *NumberOfBytes);
+    }
+    *DeviceAddress = MapInfo->AllocAddress;
+  } else {
+    MapInfo->AllocAddress = 0;
+    *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;
+
+    //
+    // We are not using a bounce buffer: the mapping is sufficiently
+    // aligned to allow us to simply flush the caches. Note that cleaning
+    // the caches is necessary for both data directions:
+    // - for bus master read, we want the latest data to be present
+    //   in main memory
+    // - for bus master write, we don't want any stale dirty cachelines that
+    //   may be written back unexpectedly, and clobber the data written to
+    //   main memory by the device.
+    //
+    mCpu->FlushDataCache (mCpu, (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,
+            *NumberOfBytes, EfiCpuFlushTypeWriteBack);
+  }
+
+  *Mapping = MapInfo;
+  return EFI_SUCCESS;
+
+FreeMapInfo:
+  FreePool (MapInfo);
+
+  return Status;
+}
+
+STATIC
+EFI_STATUS
+NonCoherentPciIoUnmap (
+  IN  EFI_PCI_IO_PROTOCOL          *This,
+  IN  VOID                         *Mapping
+  )
+{
+  NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO  *MapInfo;
+
+  if (Mapping == NULL) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  MapInfo = Mapping;
+  if (MapInfo->AllocAddress != 0) {
+    //
+    // We are using a bounce buffer: copy back the data if necessary,
+    // and free the buffer.
+    //
+    if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) {
+      gBS->CopyMem (MapInfo->HostAddress, (VOID *)(UINTN)MapInfo->AllocAddress,
+             MapInfo->NumberOfBytes);
+    }
+    NonCoherentPciIoFreeBuffer (This,
+      EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes),
+      (VOID *)(UINTN)MapInfo->AllocAddress);
+  } else {
+    //
+    // We are *not* using a bounce buffer: if this is a bus master write,
+    // we have to invalidate the caches so the CPU will see the uncached
+    // data written by the device.
+    //
+    if (MapInfo->Operation == EfiPciIoOperationBusMasterWrite) {
+      mCpu->FlushDataCache (mCpu,
+              (EFI_PHYSICAL_ADDRESS)(UINTN)MapInfo->HostAddress,
+              MapInfo->NumberOfBytes, EfiCpuFlushTypeInvalidate);
+    }
+  }
+  FreePool (MapInfo);
+  return EFI_SUCCESS;
+}
 
 STATIC
 EFI_STATUS
@@ -771,6 +1083,13 @@ InitializePciIoProtocol (
   // Copy protocol structure
   CopyMem(&Dev->PciIo, &PciIoTemplate, sizeof PciIoTemplate);
 
+  if (Dev->Device->DmaType == NonDiscoverableDeviceDmaTypeNonCoherent) {
+    Dev->PciIo.AllocateBuffer   = NonCoherentPciIoAllocateBuffer;
+    Dev->PciIo.FreeBuffer       = NonCoherentPciIoFreeBuffer;
+    Dev->PciIo.Map              = NonCoherentPciIoMap;
+    Dev->PciIo.Unmap            = NonCoherentPciIoUnmap;
+  }
+
   switch (Dev->Device->Type) {
   case NonDiscoverableDeviceTypeOhci:
     Dev->ConfigSpace.Hdr.ClassCode[0] = PCI_IF_OHCI;
diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h
index bc0a3d3258f9..449614862911 100644
--- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h
@@ -15,6 +15,8 @@
 #ifndef __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
 #define __NON_DISCOVERABLE_PCI_DEVICE_IO_H__
 
+#include <PiDxe.h>
+
 #include <Library/BaseMemoryLib.h>
 #include <Library/DebugLib.h>
 #include <Library/MemoryAllocationLib.h>
@@ -25,6 +27,7 @@
 
 #include <Protocol/ComponentName.h>
 #include <Protocol/NonDiscoverableDevice.h>
+#include <Protocol/Cpu.h>
 #include <Protocol/PciIo.h>
 
 #define NON_DISCOVERABLE_PCI_DEVICE_SIG SIGNATURE_32 ('P', 'P', 'I', 'D')
@@ -38,6 +41,27 @@
 
 #define PCI_MAX_BARS                  6
 
+extern EFI_CPU_ARCH_PROTOCOL      *mCpu;
+
+typedef struct {
+  //
+  // The linked-list next pointer
+  //
+  LIST_ENTRY          List;
+  //
+  // The address of the uncached allocation
+  //
+  VOID                *HostAddress;
+  //
+  // The number of pages in the allocation
+  //
+  UINTN               NumPages;
+  //
+  // The attributes of the allocation
+  //
+  UINT64              Attributes;
+} NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION;
+
 typedef struct {
   UINT32                    Signature;
   //
@@ -71,6 +95,11 @@ typedef struct {
   // Whether this device has been enabled
   //
   BOOLEAN                   Enabled;
+  //
+  // Linked list to keep track of uncached allocations performed
+  // on behalf of this device
+  //
+  LIST_ENTRY                UncachedAllocationList;
 } NON_DISCOVERABLE_PCI_DEVICE;
 
 VOID
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v3 5/5] Omap35xxPkg/PciEmulation: port to new non-discoverable device infrastructure
  2016-11-16 16:59 [PATCH v3 0/5] MdeModulePkg: add support for non-discoverable devices Ard Biesheuvel
                   ` (3 preceding siblings ...)
  2016-11-16 16:59 ` [PATCH v3 4/5] MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA Ard Biesheuvel
@ 2016-11-16 16:59 ` Ard Biesheuvel
  2016-11-17  4:36 ` [PATCH v3 0/5] MdeModulePkg: add support for non-discoverable devices Marcin Wojtas
  5 siblings, 0 replies; 27+ messages in thread
From: Ard Biesheuvel @ 2016-11-16 16:59 UTC (permalink / raw)
  To: edk2-devel, liming.gao, ruiyu.ni, michael.d.kinney
  Cc: afish, mw, leif.lindholm, Ard Biesheuvel

Move to the new non-discoverable device protocols for wiring the PCI based
EHCI controller driver to the non-discoverable EHCI controller found on the
OMAP 3530.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 BeagleBoardPkg/BeagleBoardPkg.dsc          |   2 +
 BeagleBoardPkg/BeagleBoardPkg.fdf          |   1 +
 Omap35xxPkg/Omap35xxPkg.dsc                |   2 +-
 Omap35xxPkg/PciEmulation/PciEmulation.c    | 578 +-------------------
 Omap35xxPkg/PciEmulation/PciEmulation.h    | 292 ----------
 Omap35xxPkg/PciEmulation/PciEmulation.inf  |  16 +-
 Omap35xxPkg/PciEmulation/PciRootBridgeIo.c | 306 -----------
 7 files changed, 36 insertions(+), 1161 deletions(-)

diff --git a/BeagleBoardPkg/BeagleBoardPkg.dsc b/BeagleBoardPkg/BeagleBoardPkg.dsc
index 1e2ecdc21ad9..d6ed5e9865f9 100644
--- a/BeagleBoardPkg/BeagleBoardPkg.dsc
+++ b/BeagleBoardPkg/BeagleBoardPkg.dsc
@@ -184,6 +184,7 @@ [LibraryClasses.common.DXE_DRIVER]
   DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
   SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
   PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf
+  NonDiscoverableDeviceRegistrationLib|MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
 
 [LibraryClasses.common.UEFI_APPLICATION]
   ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
@@ -449,6 +450,7 @@ [Components.common]
   # USB
   #
   Omap35xxPkg/PciEmulation/PciEmulation.inf
+  MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
 
   MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf {
     <PcdsFixedAtBuild>
diff --git a/BeagleBoardPkg/BeagleBoardPkg.fdf b/BeagleBoardPkg/BeagleBoardPkg.fdf
index fcaf44abb5cf..23696e122656 100644
--- a/BeagleBoardPkg/BeagleBoardPkg.fdf
+++ b/BeagleBoardPkg/BeagleBoardPkg.fdf
@@ -167,6 +167,7 @@ [FV.FvMain]
   #
 
   INF Omap35xxPkg/PciEmulation/PciEmulation.inf
+  INF MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
 
   INF MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf
   INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
diff --git a/Omap35xxPkg/Omap35xxPkg.dsc b/Omap35xxPkg/Omap35xxPkg.dsc
index 4a3317f255f6..89a407049f31 100644
--- a/Omap35xxPkg/Omap35xxPkg.dsc
+++ b/Omap35xxPkg/Omap35xxPkg.dsc
@@ -79,7 +79,7 @@ [LibraryClasses.common]
 
 [LibraryClasses.common.DXE_DRIVER]
   DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
-
+  NonDiscoverableDeviceRegistrationLib|MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
 
 [LibraryClasses.ARM]
   NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
diff --git a/Omap35xxPkg/PciEmulation/PciEmulation.c b/Omap35xxPkg/PciEmulation/PciEmulation.c
index 17ea03ccf486..d17646a9ed58 100644
--- a/Omap35xxPkg/PciEmulation/PciEmulation.c
+++ b/Omap35xxPkg/PciEmulation/PciEmulation.c
@@ -1,6 +1,7 @@
 /** @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
@@ -12,49 +13,27 @@
 
 **/
 
-#include "PciEmulation.h"
+#include <PiDxe.h>
 
-EMBEDDED_EXTERNAL_DEVICE   *gTPS65950;
-
-#define HOST_CONTROLLER_OPERATION_REG_SIZE  0x44
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/NonDiscoverableDeviceRegistrationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
 
-typedef struct {
-  ACPI_HID_DEVICE_PATH      AcpiDevicePath;
-  PCI_DEVICE_PATH           PciDevicePath;
-  EFI_DEVICE_PATH_PROTOCOL  EndDevicePath;
-} EFI_PCI_IO_DEVICE_PATH;
+#include <Protocol/EmbeddedExternalDevice.h>
 
-typedef struct {
-  UINT32                  Signature;
-  EFI_PCI_IO_DEVICE_PATH  DevicePath;
-  EFI_PCI_IO_PROTOCOL     PciIoProtocol;
-  PCI_TYPE00              *ConfigSpace;
-  PCI_ROOT_BRIDGE         RootBridge;
-  UINTN                   Segment;
-} EFI_PCI_IO_PRIVATE_DATA;
+#include <TPS65950.h>
+#include <Omap3530/Omap3530.h>
 
-#define EFI_PCI_IO_PRIVATE_DATA_SIGNATURE     SIGNATURE_32('p', 'c', 'i', 'o')
-#define EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(a)  CR(a, EFI_PCI_IO_PRIVATE_DATA, PciIoProtocol, EFI_PCI_IO_PRIVATE_DATA_SIGNATURE)
+EMBEDDED_EXTERNAL_DEVICE   *gTPS65950;
 
-EFI_PCI_IO_DEVICE_PATH PciIoDevicePathTemplate =
-{
-  {
-    { ACPI_DEVICE_PATH, ACPI_DP, { sizeof (ACPI_HID_DEVICE_PATH), 0 } },
-    EISA_PNP_ID(0x0A03),  // HID
-    0                     // UID
-  },
-  {
-    { HARDWARE_DEVICE_PATH, HW_PCI_DP, { sizeof (PCI_DEVICE_PATH), 0 } },
-    0,
-    0
-  },
-  { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0} }
-};
+#define HOST_CONTROLLER_OPERATION_REG_SIZE  0x44
 
 STATIC
-VOID
+EFI_STATUS
 ConfigureUSBHost (
-  VOID
+  NON_DISCOVERABLE_DEVICE   *Device
   )
 {
   EFI_STATUS Status;
@@ -103,454 +82,10 @@ ConfigureUSBHost (
 
   Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID3, LEDEN), 1, &Data);
   ASSERT_EFI_ERROR (Status);
-}
-
-
-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;
-}
-
-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;
-}
-
-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
-  )
-{
-  EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
-
-  return PciRootBridgeIoMemRead (&Private->RootBridge.Io,
-                                (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
-                                Private->ConfigSpace->Device.Bar[BarIndex] + Offset,
-                                Count,
-                                Buffer
-                                );
-}
-
-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
-  )
-{
-  EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
-
-  return PciRootBridgeIoMemWrite (&Private->RootBridge.Io,
-                                 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
-                                 Private->ConfigSpace->Device.Bar[BarIndex] + Offset,
-                                 Count,
-                                 Buffer
-                                 );
-}
-
-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;
-}
-
-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;
-}
-
-/**
-  Enable a PCI driver to read PCI controller registers in PCI configuration space.
-
-  @param[in]      This    A pointer to the EFI_PCI_IO_PROTOCOL instance.
-  @param[in]      Width   Signifies the width of the memory operations.
-  @param[in]      Offset  The offset within the PCI configuration space for
-                          the PCI controller.
-  @param[in]      Count   The number of PCI configuration operations to
-                          perform. Bytes moved is Width size * Count,
-                          starting at Offset.
-
-  @param[in out]  Buffer  The destination buffer to store the results.
-
-  @retval  EFI_SUCCESS            The data was read from the PCI controller.
-  @retval  EFI_INVALID_PARAMETER  "Width" is invalid.
-  @retval  EFI_INVALID_PARAMETER  "Buffer" is NULL.
-
-**/
-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
-  )
-{
-  EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);
-  EFI_STATUS Status;
-
-  if ((Width < 0) || (Width >= EfiPciIoWidthMaximum) || (Buffer == NULL)) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  Status = PciRootBridgeIoMemRW (
-             (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width,
-             Count,
-             TRUE,
-             (PTR)(UINTN)Buffer,
-             TRUE,
-             (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset)  //Fix me ConfigSpace
-             );
-
-  return Status;
-}
-
-/**
-  Enable a PCI driver to write PCI controller registers in PCI configuration space.
-
-  @param[in]      This    A pointer to the EFI_PCI_IO_PROTOCOL instance.
-  @param[in]      Width   Signifies the width of the memory operations.
-  @param[in]      Offset  The offset within the PCI configuration space for
-                          the PCI controller.
-  @param[in]      Count   The number of PCI configuration operations to
-                          perform. Bytes moved is Width size * Count,
-                          starting at Offset.
-
-  @param[in out]  Buffer  The source buffer to write data from.
-
-  @retval  EFI_SUCCESS            The data was read from the PCI controller.
-  @retval  EFI_INVALID_PARAMETER  "Width" is invalid.
-  @retval  EFI_INVALID_PARAMETER  "Buffer" is NULL.
-
-**/
-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
-  )
-{
-  EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);
-
-  if ((Width < 0) || (Width >= EfiPciIoWidthMaximum) || (Buffer == NULL)) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
-                               Count,
-                               TRUE,
-                               (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset),
-                               TRUE,
-                               (PTR)(UINTN)Buffer
-                               );
-}
-
-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;
-}
-
-EFI_STATUS
-PciIoMap (
-  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
-  )
-{
-  DMA_MAP_OPERATION   DmaOperation;
-
-  if (Operation == EfiPciIoOperationBusMasterRead) {
-    DmaOperation = MapOperationBusMasterRead;
-  } else if (Operation == EfiPciIoOperationBusMasterWrite) {
-    DmaOperation = MapOperationBusMasterWrite;
-  } else if (Operation == EfiPciIoOperationBusMasterCommonBuffer) {
-    DmaOperation = MapOperationBusMasterCommonBuffer;
-  } else {
-    return EFI_INVALID_PARAMETER;
-  }
-  return DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping);
-}
 
-EFI_STATUS
-PciIoUnmap (
-  IN EFI_PCI_IO_PROTOCOL           *This,
-  IN  VOID                         *Mapping
-  )
-{
-  return DmaUnmap (Mapping);
-}
-
-/**
-  Allocate pages that are suitable for an EfiPciIoOperationBusMasterCommonBuffer
-  mapping.
-
-  @param[in]   This         A pointer to the EFI_PCI_IO_PROTOCOL instance.
-  @param[in]   Type         This parameter is not used and must be ignored.
-  @param[in]   MemoryType   The type of memory to allocate, EfiBootServicesData or
-                            EfiRuntimeServicesData.
-  @param[in]   Pages        The number of pages to allocate.
-  @param[out]  HostAddress  A pointer to store the base system memory address of
-                            the allocated range.
-  @param[in]   Attributes   The requested bit mask of attributes for the allocated
-                            range. Only the attributes,
-                            EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE and
-                            EFI_PCI_ATTRIBUTE_MEMORY_CACHED may be used with this
-                            function. If any other bits are set, then EFI_UNSUPPORTED
-                            is returned. This function ignores this bit mask.
-
-  @retval  EFI_SUCCESS            The requested memory pages were allocated.
-  @retval  EFI_INVALID_PARAMETER  HostAddress is NULL.
-  @retval  EFI_INVALID_PARAMETER  MemoryType is invalid.
-  @retval  EFI_UNSUPPORTED        Attributes is unsupported.
-  @retval  EFI_OUT_OF_RESOURCES   The memory pages could not be allocated.
-
-**/
-EFI_STATUS
-PciIoAllocateBuffer (
-  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
-  )
-{
-  if (Attributes &
-      (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE |
-         EFI_PCI_ATTRIBUTE_MEMORY_CACHED         ))) {
-    return EFI_UNSUPPORTED;
-  }
-
-  return DmaAllocateBuffer (MemoryType, Pages, HostAddress);
-}
-
-
-EFI_STATUS
-PciIoFreeBuffer (
-  IN EFI_PCI_IO_PROTOCOL           *This,
-  IN  UINTN                        Pages,
-  IN  VOID                         *HostAddress
-  )
-{
-  return DmaFreeBuffer (Pages, HostAddress);
-}
-
-
-EFI_STATUS
-PciIoFlush (
-  IN EFI_PCI_IO_PROTOCOL  *This
-  )
-{
   return EFI_SUCCESS;
 }
 
-/**
-  Retrieves this PCI controller's current PCI bus number, device number, and function number.
-
-  @param[in]   This            A pointer to the EFI_PCI_IO_PROTOCOL instance.
-  @param[out]  SegmentNumber   The PCI controller's current PCI segment number.
-  @param[out]  BusNumber       The PCI controller's current PCI bus number.
-  @param[out]  DeviceNumber    The PCI controller's current PCI device number.
-  @param[out]  FunctionNumber  The PCI controller's current PCI function number.
-
-  @retval  EFI_SUCCESS            The PCI controller location was returned.
-  @retval  EFI_INVALID_PARAMETER  At least one out of the four output parameters is
-                                  a NULL pointer.
-**/
-EFI_STATUS
-PciIoGetLocation (
-  IN   EFI_PCI_IO_PROTOCOL  *This,
-  OUT  UINTN                *SegmentNumber,
-  OUT  UINTN                *BusNumber,
-  OUT  UINTN                *DeviceNumber,
-  OUT  UINTN                *FunctionNumber
-  )
-{
-  EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);
-
-  if ((SegmentNumber == NULL) || (BusNumber      == NULL) ||
-      (DeviceNumber  == NULL) || (FunctionNumber == NULL)    ) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  *SegmentNumber  = Private->Segment;
-  *BusNumber      = 0xff;
-  *DeviceNumber   = 0;
-  *FunctionNumber = 0;
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Performs an operation on the attributes that this PCI controller supports.
-
-  The operations include getting the set of supported attributes, retrieving
-  the current attributes, setting the current attributes, enabling attributes,
-  and disabling attributes.
-
-  @param[in]   This        A pointer to the EFI_PCI_IO_PROTOCOL instance.
-  @param[in]   Operation   The operation to perform on the attributes for this
-                           PCI controller.
-  @param[in]   Attributes  The mask of attributes that are used for Set,
-                           Enable and Disable operations.
-  @param[out]  Result      A pointer to the result mask of attributes that are
-                           returned for the Get and Supported operations. This
-                           is an optional parameter that may be NULL for the
-                           Set, Enable, and Disable operations.
-
-  @retval  EFI_SUCCESS            The operation on the PCI controller's
-                                  attributes was completed. If the operation
-                                  was Get or Supported, then the attribute mask
-                                  is returned in Result.
-  @retval  EFI_INVALID_PARAMETER  Operation is greater than or equal to
-                                  EfiPciIoAttributeOperationMaximum.
-  @retval  EFI_INVALID_PARAMETER  Operation is Get and Result is NULL.
-  @retval  EFI_INVALID_PARAMETER  Operation is Supported and Result is NULL.
-
-**/
-EFI_STATUS
-PciIoAttributes (
-  IN EFI_PCI_IO_PROTOCOL                       *This,
-  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,
-  IN  UINT64                                   Attributes,
-  OUT UINT64                                   *Result OPTIONAL
-  )
-{
-  switch (Operation) {
-  case EfiPciIoAttributeOperationGet:
-  case EfiPciIoAttributeOperationSupported:
-    if (Result == NULL) {
-      return EFI_INVALID_PARAMETER;
-    }
-    //
-    // We are not a real PCI device so just say things we kind of do
-    //
-    *Result = EFI_PCI_DEVICE_ENABLE;
-    break;
-
-  case EfiPciIoAttributeOperationSet:
-  case EfiPciIoAttributeOperationEnable:
-  case EfiPciIoAttributeOperationDisable:
-    if (Attributes & (~EFI_PCI_DEVICE_ENABLE)) {
-      return EFI_UNSUPPORTED;
-    }
-    // Since we are not a real PCI device no enable/set or disable operations exist.
-    return EFI_SUCCESS;
-
-  default:
-    return EFI_INVALID_PARAMETER;
-  };
-  return EFI_SUCCESS;
-}
-
-EFI_STATUS
-PciIoGetBarAttributes (
-  IN EFI_PCI_IO_PROTOCOL             *This,
-  IN  UINT8                          BarIndex,
-  OUT UINT64                         *Supports, OPTIONAL
-  OUT VOID                           **Resources OPTIONAL
-  )
-{
-  ASSERT (FALSE);
-  return EFI_UNSUPPORTED;
-}
-
-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;
-}
-
-EFI_PCI_IO_PROTOCOL PciIoTemplate =
-{
-  PciIoPollMem,
-  PciIoPollIo,
-  { PciIoMemRead, PciIoMemWrite },
-  { PciIoIoRead,  PciIoIoWrite },
-  { PciIoPciRead, PciIoPciWrite },
-  PciIoCopyMem,
-  PciIoMap,
-  PciIoUnmap,
-  PciIoAllocateBuffer,
-  PciIoFreeBuffer,
-  PciIoFlush,
-  PciIoGetLocation,
-  PciIoAttributes,
-  PciIoGetBarAttributes,
-  PciIoSetBarAttributes,
-  0,
-  0
-};
-
 EFI_STATUS
 EFIAPI
 PciEmulationEntryPoint (
@@ -558,76 +93,21 @@ PciEmulationEntryPoint (
   IN EFI_SYSTEM_TABLE *SystemTable
   )
 {
-  EFI_STATUS              Status;
-  EFI_HANDLE              Handle;
-  EFI_PCI_IO_PRIVATE_DATA *Private;
   UINT8                   CapabilityLength;
   UINT8                   PhysicalPorts;
-  UINTN                   Count;
-
-
-  //Configure USB host for OMAP3530.
-  ConfigureUSBHost();
-
-  // Create a private structure
-  Private = AllocatePool(sizeof(EFI_PCI_IO_PRIVATE_DATA));
-  if (Private == NULL) {
-    Status = EFI_OUT_OF_RESOURCES;
-    return Status;
-  }
-
-  Private->Signature              = EFI_PCI_IO_PRIVATE_DATA_SIGNATURE;  // Fill in signature
-  Private->RootBridge.Signature   = PCI_ROOT_BRIDGE_SIGNATURE;          // Fake Root Bridge structure needs a signature too
-  Private->RootBridge.MemoryStart = USB_EHCI_HCCAPBASE;                 // Get the USB capability register base
-  Private->Segment                = 0;                                  // Default to segment zero
-
-  // Find out the capability register length and number of physical ports.
-  CapabilityLength = MmioRead8(Private->RootBridge.MemoryStart);
-  PhysicalPorts    = (MmioRead32 (Private->RootBridge.MemoryStart + 0x4)) & 0x0000000F;
-
-  // Calculate the total size of the USB registers.
-  Private->RootBridge.MemorySize = CapabilityLength + (HOST_CONTROLLER_OPERATION_REG_SIZE + ((4 * PhysicalPorts) - 1));
-
-  // Enable Port Power bit in Port status and control registers in EHCI register space.
-  // Port Power Control (PPC) bit in the HCSPARAMS register is already set which indicates
-  // host controller implementation includes port power control.
-  for (Count = 0; Count < PhysicalPorts; Count++) {
-    MmioOr32 ((Private->RootBridge.MemoryStart + CapabilityLength + HOST_CONTROLLER_OPERATION_REG_SIZE + 4*Count), 0x00001000);
-  }
-
-  // Create fake PCI config space.
-  Private->ConfigSpace = AllocateZeroPool(sizeof(PCI_TYPE00));
-  if (Private->ConfigSpace == NULL) {
-    Status = EFI_OUT_OF_RESOURCES;
-    FreePool(Private);
-    return Status;
-  }
-
-  // Configure PCI config space
-  Private->ConfigSpace->Hdr.VendorId = 0xFFFF; // Invalid vendor Id as it is not an actual device.
-  Private->ConfigSpace->Hdr.DeviceId = 0x0000; // Not relevant as the vendor id is not valid.
-  Private->ConfigSpace->Hdr.ClassCode[0] = 0x20;
-  Private->ConfigSpace->Hdr.ClassCode[1] = 0x03;
-  Private->ConfigSpace->Hdr.ClassCode[2] = 0x0C;
-  Private->ConfigSpace->Device.Bar[0] = Private->RootBridge.MemoryStart;
-
-  Handle = NULL;
-
-  // Unique device path.
-  CopyMem(&Private->DevicePath, &PciIoDevicePathTemplate, sizeof(PciIoDevicePathTemplate));
-  Private->DevicePath.AcpiDevicePath.UID = 0;
-
-  // Copy protocol structure
-  CopyMem(&Private->PciIoProtocol, &PciIoTemplate, sizeof(PciIoTemplate));
-
-  Status = gBS->InstallMultipleProtocolInterfaces(&Handle,
-                                                  &gEfiPciIoProtocolGuid,       &Private->PciIoProtocol,
-                                                  &gEfiDevicePathProtocolGuid,  &Private->DevicePath,
-                                                  NULL);
-  if (EFI_ERROR(Status)) {
-    DEBUG((EFI_D_ERROR, "PciEmulationEntryPoint InstallMultipleProtocolInterfaces() failed.\n"));
-  }
-
-  return Status;
+  UINTN                   MemorySize;
+
+  CapabilityLength = MmioRead8 (USB_EHCI_HCCAPBASE);
+  PhysicalPorts    = MmioRead32 (USB_EHCI_HCCAPBASE + 0x4) & 0x0000000F;
+  MemorySize       = CapabilityLength + HOST_CONTROLLER_OPERATION_REG_SIZE +
+                     4 * PhysicalPorts - 1;
+
+  return RegisterNonDiscoverableMmioDevice (
+           NonDiscoverableDeviceTypeEhci,
+           NonDiscoverableDeviceDmaTypeNonCoherent,
+           ConfigureUSBHost,
+           NULL,
+           1,
+           USB_EHCI_HCCAPBASE, MemorySize
+           );
 }
-
diff --git a/Omap35xxPkg/PciEmulation/PciEmulation.h b/Omap35xxPkg/PciEmulation/PciEmulation.h
deleted file mode 100644
index d5ee04318939..000000000000
--- a/Omap35xxPkg/PciEmulation/PciEmulation.h
+++ /dev/null
@@ -1,292 +0,0 @@
-/** @file
-
-  Copyright (c) 2008 - 2009, Apple Inc. 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 _PCI_ROOT_BRIDGE_H_
-#define _PCI_ROOT_BRIDGE_H_
-
-#include <PiDxe.h>
-
-#include <TPS65950.h>
-
-#include <Library/BaseLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/DebugLib.h>
-#include <Library/DxeServicesTableLib.h>
-#include <Library/IoLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/PciLib.h>
-#include <Library/UefiLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/OmapDmaLib.h>
-#include <Library/DmaLib.h>
-
-#include <Protocol/EmbeddedExternalDevice.h>
-#include <Protocol/DevicePath.h>
-#include <Protocol/PciIo.h>
-#include <Protocol/PciRootBridgeIo.h>
-#include <Protocol/PciHostBridgeResourceAllocation.h>
-
-#include <IndustryStandard/Pci22.h>
-#include <IndustryStandard/Acpi.h>
-
-#include <Omap3530/Omap3530.h>
-
-
-
-#define EFI_RESOURCE_NONEXISTENT  0xFFFFFFFFFFFFFFFFULL
-#define EFI_RESOURCE_LESS         0xFFFFFFFFFFFFFFFEULL
-#define EFI_RESOURCE_SATISFIED    0x0000000000000000ULL
-
-
-typedef struct {
-  ACPI_HID_DEVICE_PATH      AcpiDevicePath;
-  EFI_DEVICE_PATH_PROTOCOL  EndDevicePath;
-} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
-
-
-#define ACPI_CONFIG_IO    0
-#define ACPI_CONFIG_MMIO  1
-#define ACPI_CONFIG_BUS   2
-
-typedef struct {
-  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR Desc[3];
-  EFI_ACPI_END_TAG_DESCRIPTOR       EndDesc;
-} ACPI_CONFIG_INFO;
-
-
-#define PCI_ROOT_BRIDGE_SIGNATURE SIGNATURE_32 ('P', 'c', 'i', 'F')
-
-typedef struct {
-  UINT32                                            Signature;
-  EFI_HANDLE                                        Handle;
-  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL                   Io;
-  EFI_PCI_ROOT_BRIDGE_DEVICE_PATH                   DevicePath;
-
-  UINT8   StartBus;
-  UINT8   EndBus;
-  UINT16  Type;
-  UINT32  MemoryStart;
-  UINT32  MemorySize;
-  UINTN   IoOffset;
-  UINT32  IoStart;
-  UINT32  IoSize;
-  UINT64  PciAttributes;
-
-  ACPI_CONFIG_INFO  *Config;
-
-} PCI_ROOT_BRIDGE;
-
-
-#define INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) CR (a, PCI_ROOT_BRIDGE, Io, PCI_ROOT_BRIDGE_SIGNATURE)
-
-
-typedef union {
-  UINT8   volatile  *buf;
-  UINT8   volatile  *ui8;
-  UINT16  volatile  *ui16;
-  UINT32  volatile  *ui32;
-  UINT64  volatile  *ui64;
-  UINTN   volatile  ui;
-} PTR;
-
-
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoPollMem (
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN  UINT64                                 Address,
-  IN  UINT64                                 Mask,
-  IN  UINT64                                 Value,
-  IN  UINT64                                 Delay,
-  OUT UINT64                                 *Result
-  );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoPollIo (
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN  UINT64                                 Address,
-  IN  UINT64                                 Mask,
-  IN  UINT64                                 Value,
-  IN  UINT64                                 Delay,
-  OUT UINT64                                 *Result
-  );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoMemRead (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN     UINT64                                 Address,
-  IN     UINTN                                  Count,
-  IN OUT VOID                                   *Buffer
-  );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoMemWrite (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN     UINT64                                 Address,
-  IN     UINTN                                  Count,
-  IN OUT VOID                                   *Buffer
-  );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoIoRead (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN     UINT64                                 UserAddress,
-  IN     UINTN                                  Count,
-  IN OUT VOID                                   *UserBuffer
-  );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoIoWrite (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN     UINT64                                 UserAddress,
-  IN     UINTN                                  Count,
-  IN OUT VOID                                   *UserBuffer
-  );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoCopyMem (
-  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN UINT64                                 DestAddress,
-  IN UINT64                                 SrcAddress,
-  IN UINTN                                  Count
-  );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoPciRead (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN     UINT64                                 Address,
-  IN     UINTN                                  Count,
-  IN OUT VOID                                   *Buffer
-  );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoPciWrite (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN     UINT64                                 Address,
-  IN     UINTN                                  Count,
-  IN OUT VOID                                   *Buffer
-  );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoMap (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL            *This,
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  Operation,
-  IN     VOID                                       *HostAddress,
-  IN OUT UINTN                                      *NumberOfBytes,
-  OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,
-  OUT    VOID                                       **Mapping
-  );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoUnmap (
-  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
-  IN VOID                             *Mapping
-  );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoAllocateBuffer (
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
-  IN  EFI_ALLOCATE_TYPE                Type,
-  IN  EFI_MEMORY_TYPE                  MemoryType,
-  IN  UINTN                            Pages,
-  OUT VOID                             **HostAddress,
-  IN  UINT64                           Attributes
-  );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoFreeBuffer (
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
-  IN  UINTN                            Pages,
-  OUT VOID                             *HostAddress
-  );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoFlush (
-  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This
-  );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoGetAttributes (
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
-  OUT UINT64                           *Supported,
-  OUT UINT64                           *Attributes
-  );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoSetAttributes (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
-  IN     UINT64                           Attributes,
-  IN OUT UINT64                           *ResourceBase,
-  IN OUT UINT64                           *ResourceLength
-  );
-
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoConfiguration (
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
-  OUT VOID                             **Resources
-  );
-
-//
-// Private Function Prototypes
-//
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoMemRW (
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN  UINTN                                  Count,
-  IN  BOOLEAN                                InStrideFlag,
-  IN  PTR                                    In,
-  IN  BOOLEAN                                OutStrideFlag,
-  OUT PTR                                    Out
-  );
-
-BOOLEAN
-PciIoMemAddressValid (
-  IN EFI_PCI_IO_PROTOCOL  *This,
-  IN UINT64               Address
-  );
-
-EFI_STATUS
-EmulatePciIoForEhci (
-  INTN    MvPciIfMaxIf
-  );
-
-#endif
-
diff --git a/Omap35xxPkg/PciEmulation/PciEmulation.inf b/Omap35xxPkg/PciEmulation/PciEmulation.inf
index 2180bb49898d..4df9c505e8cd 100644
--- a/Omap35xxPkg/PciEmulation/PciEmulation.inf
+++ b/Omap35xxPkg/PciEmulation/PciEmulation.inf
@@ -22,33 +22,23 @@ [Defines]
   ENTRY_POINT                     = PciEmulationEntryPoint
 
 [Sources.common]
-  PciRootBridgeIo.c
   PciEmulation.c
 
 [Packages]
   MdePkg/MdePkg.dec
   MdeModulePkg/MdeModulePkg.dec
-  IntelFrameworkPkg/IntelFrameworkPkg.dec
-  ArmPkg/ArmPkg.dec
   EmbeddedPkg/EmbeddedPkg.dec
   Omap35xxPkg/Omap35xxPkg.dec
 
 [LibraryClasses]
   BaseLib
-  DxeServicesTableLib
-  UefiLib
+  DebugLib
+  IoLib
+  NonDiscoverableDeviceRegistrationLib
   UefiBootServicesTableLib
   UefiDriverEntryPoint
-  UefiRuntimeServicesTableLib
-  IoLib
-  OmapDmaLib
-  DmaLib
 
 [Protocols]
-  gEfiPciRootBridgeIoProtocolGuid
-  gEfiDevicePathProtocolGuid
-  gEfiPciHostBridgeResourceAllocationProtocolGuid
-  gEfiPciIoProtocolGuid
   gEmbeddedExternalDeviceProtocolGuid
 
 [Depex]
diff --git a/Omap35xxPkg/PciEmulation/PciRootBridgeIo.c b/Omap35xxPkg/PciEmulation/PciRootBridgeIo.c
deleted file mode 100644
index e8635ed88d91..000000000000
--- a/Omap35xxPkg/PciEmulation/PciRootBridgeIo.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/** @file
-
-  Copyright (c) 2008 - 2009, Apple Inc. 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 "PciEmulation.h"
-
-BOOLEAN
-PciRootBridgeMemAddressValid (
-  IN PCI_ROOT_BRIDGE  *Private,
-  IN UINT64           Address
-  )
-{
-  if ((Address >= Private->MemoryStart) && (Address < (Private->MemoryStart + Private->MemorySize))) {
-    return TRUE;
-  }
-
-  return FALSE;
-}
-
-
-EFI_STATUS
-PciRootBridgeIoMemRW (
-  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN  UINTN                                  Count,
-  IN  BOOLEAN                                InStrideFlag,
-  IN  PTR                                    In,
-  IN  BOOLEAN                                OutStrideFlag,
-  OUT PTR                                    Out
-  )
-{
-  UINTN  Stride;
-  UINTN  InStride;
-  UINTN  OutStride;
-
-
-  Width     = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
-  Stride    = (UINTN)1 << Width;
-  InStride  = InStrideFlag  ? Stride : 0;
-  OutStride = OutStrideFlag ? Stride : 0;
-
-  //
-  // Loop for each iteration and move the data
-  //
-  switch (Width) {
-  case EfiPciWidthUint8:
-    for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
-      *In.ui8 = *Out.ui8;
-    }
-    break;
-  case EfiPciWidthUint16:
-    for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
-      *In.ui16 = *Out.ui16;
-    }
-    break;
-  case EfiPciWidthUint32:
-    for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
-      *In.ui32 = *Out.ui32;
-    }
-    break;
-  default:
-    return EFI_INVALID_PARAMETER;
-  }
-
-  return EFI_SUCCESS;
-}
-
-EFI_STATUS
-PciRootBridgeIoPciRW (
-  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN BOOLEAN                                Write,
-  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN UINT64                                 UserAddress,
-  IN UINTN                                  Count,
-  IN OUT VOID                               *UserBuffer
-  )
-{
-  return EFI_SUCCESS;
-}
-
-/**
-  Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
-
-  @param  This                  A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-  @param  Width                 Signifies the width of the memory operations.
-  @param  Address               The base address of the memory operations.
-  @param  Count                 The number of memory operations to perform.
-  @param  Buffer                For read operations, the destination buffer to store the results. For write
-                                operations, the source buffer to write data from.
-
-  @retval EFI_SUCCESS           The data was read from or written to the PCI root bridge.
-  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
-  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
-
-**/
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoMemRead (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN     UINT64                                 Address,
-  IN     UINTN                                  Count,
-  IN OUT VOID                                   *Buffer
-  )
-{
-  PCI_ROOT_BRIDGE   *Private;
-  UINTN             AlignMask;
-  PTR               In;
-  PTR               Out;
-
-  if ( Buffer == NULL ) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  Private = INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
-
-  if (!PciRootBridgeMemAddressValid (Private, Address)) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  AlignMask = (1 << (Width & 0x03)) - 1;
-  if (Address & AlignMask) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  In.buf  = Buffer;
-  Out.buf = (VOID *)(UINTN) Address;
-
-  switch (Width) {
-  case EfiPciWidthUint8:
-  case EfiPciWidthUint16:
-  case EfiPciWidthUint32:
-  case EfiPciWidthUint64:
-    return PciRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
-
-  case EfiPciWidthFifoUint8:
-  case EfiPciWidthFifoUint16:
-  case EfiPciWidthFifoUint32:
-  case EfiPciWidthFifoUint64:
-    return PciRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
-
-  case EfiPciWidthFillUint8:
-  case EfiPciWidthFillUint16:
-  case EfiPciWidthFillUint32:
-  case EfiPciWidthFillUint64:
-    return PciRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
-
-  default:
-    break;
-  }
-
-  return EFI_INVALID_PARAMETER;
-}
-
-
-
-/**
-  Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
-
-  @param  This                  A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-  @param  Width                 Signifies the width of the memory operations.
-  @param  Address               The base address of the memory operations.
-  @param  Count                 The number of memory operations to perform.
-  @param  Buffer                For read operations, the destination buffer to store the results. For write
-                                operations, the source buffer to write data from.
-
-  @retval EFI_SUCCESS           The data was read from or written to the PCI root bridge.
-  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
-  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
-
-**/
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoMemWrite (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN     UINT64                                 Address,
-  IN     UINTN                                  Count,
-  IN OUT VOID                                   *Buffer
-  )
-{
-  PCI_ROOT_BRIDGE *Private;
-  UINTN  AlignMask;
-  PTR    In;
-  PTR    Out;
-
-  if ( Buffer == NULL ) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  Private = INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
-
-  if (!PciRootBridgeMemAddressValid (Private, Address)) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  AlignMask = (1 << (Width & 0x03)) - 1;
-  if (Address & AlignMask) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  In.buf  = (VOID *)(UINTN) Address;
-  Out.buf = Buffer;
-
-  switch (Width) {
-  case EfiPciWidthUint8:
-  case EfiPciWidthUint16:
-  case EfiPciWidthUint32:
-  case EfiPciWidthUint64:
-    return PciRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
-
-  case EfiPciWidthFifoUint8:
-  case EfiPciWidthFifoUint16:
-  case EfiPciWidthFifoUint32:
-  case EfiPciWidthFifoUint64:
-    return PciRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
-
-  case EfiPciWidthFillUint8:
-  case EfiPciWidthFillUint16:
-  case EfiPciWidthFillUint32:
-  case EfiPciWidthFillUint64:
-    return PciRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
-
-  default:
-    break;
-  }
-
-  return EFI_INVALID_PARAMETER;
-}
-
-/**
-  Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
-
-  @param  This                  A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-  @param  Width                 Signifies the width of the memory operations.
-  @param  Address               The base address of the memory operations.
-  @param  Count                 The number of memory operations to perform.
-  @param  Buffer                For read operations, the destination buffer to store the results. For write
-                                operations, the source buffer to write data from.
-
-  @retval EFI_SUCCESS           The data was read from or written to the PCI root bridge.
-  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
-  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
-
-**/
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoPciRead (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN     UINT64                                 Address,
-  IN     UINTN                                  Count,
-  IN OUT VOID                                   *Buffer
-  )
-{
-  if (Buffer == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  return PciRootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
-}
-
-
-
-/**
-  Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
-
-  @param  This                  A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
-  @param  Width                 Signifies the width of the memory operations.
-  @param  Address               The base address of the memory operations.
-  @param  Count                 The number of memory operations to perform.
-  @param  Buffer                For read operations, the destination buffer to store the results. For write
-                                operations, the source buffer to write data from.
-
-  @retval EFI_SUCCESS           The data was read from or written to the PCI root bridge.
-  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
-  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
-
-**/
-EFI_STATUS
-EFIAPI
-PciRootBridgeIoPciWrite (
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
-  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
-  IN     UINT64                                 Address,
-  IN     UINTN                                  Count,
-  IN OUT VOID                                   *Buffer
-  )
-{
-  if (Buffer == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  return PciRootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
-}
-
-
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol
  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
  0 siblings, 1 reply; 27+ messages in thread
From: Leif Lindholm @ 2016-11-16 17:48 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: edk2-devel, liming.gao, ruiyu.ni, michael.d.kinney, afish, mw

On Wed, Nov 16, 2016 at 04:59:27PM +0000, Ard Biesheuvel wrote:
> Introduce a protocol that can be exposed by a platform for devices that
> are not discoverable, usually because they are wired straight to the
> memory bus rather than to an enumerable bus like PCI or USB.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>  MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h | 90 ++++++++++++++++++++
>  MdeModulePkg/MdeModulePkg.dec                         |  3 +
>  2 files changed, 93 insertions(+)
> 
> diff --git a/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
> new file mode 100644
> index 000000000000..47ed841b407b
> --- /dev/null
> +++ b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
> @@ -0,0 +1,90 @@
> +/** @file
> +  Protocol to describe devices that are not on a discoverable bus
> +
> +  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_DEVICE_H__
> +#define __NON_DISCOVERABLE_DEVICE_H__
> +
> +#include <IndustryStandard/Acpi.h>
> +
> +#define EDKII_NON_DISCOVERABLE_DEVICE_PROTOCOL_GUID \
> +  { 0x0d51905b, 0xb77e, 0x452a, {0xa2, 0xc0, 0xec, 0xa0, 0xcc, 0x8d, 0x51, 0x4a } }
> +
> +//
> +// Protocol interface structure
> +//
> +typedef struct _NON_DISCOVERABLE_DEVICE NON_DISCOVERABLE_DEVICE;
> +
> +//
> +// Data Types
> +//
> +typedef enum {
> +  NonDiscoverableDeviceTypeAmba,
> +  NonDiscoverableDeviceTypeOhci,
> +  NonDiscoverableDeviceTypeUhci,
> +  NonDiscoverableDeviceTypeEhci,
> +  NonDiscoverableDeviceTypeXhci,
> +  NonDiscoverableDeviceTypeAhci,
> +  NonDiscoverableDeviceTypeSdhci,
> +  NonDiscoverableDeviceTypeUfs,
> +  NonDiscoverableDeviceTypeNvme,

Just one OCD comment/question left:
Can we keep these sorted alphabetically?
(Also in switch statements in later patches?)

Other than that, I'm (very) happy with this series.

/
    Leif

> +  NonDiscoverableDeviceTypeMax,
> +} NON_DISCOVERABLE_DEVICE_TYPE;
> +
> +typedef enum {
> +  NonDiscoverableDeviceDmaTypeCoherent,
> +  NonDiscoverableDeviceDmaTypeNonCoherent,
> +  NonDiscoverableDeviceDmaTypeMax,
> +} NON_DISCOVERABLE_DEVICE_DMA_TYPE;
> +
> +//
> +// Function Prototypes
> +//
> +
> +/**
> +  Perform device specific initialization before the device is started
> +
> +  @param  This          The non-discoverable device protocol pointer
> +
> +  @retval EFI_SUCCESS   Initialization successful, the device may be used
> +  @retval Other         Initialization failed, device should not be started
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *NON_DISCOVERABLE_DEVICE_INIT) (
> +  IN  NON_DISCOVERABLE_DEVICE       *This
> +  );
> +
> +struct _NON_DISCOVERABLE_DEVICE {
> +  //
> +  // The type of device
> +  //
> +  NON_DISCOVERABLE_DEVICE_TYPE        Type;
> +  //
> +  // Whether this device is DMA coherent
> +  //
> +  NON_DISCOVERABLE_DEVICE_DMA_TYPE    DmaType;
> +  //
> +  // Initialization function for the device
> +  //
> +  NON_DISCOVERABLE_DEVICE_INIT        Initialize;
> +  //
> +  // The MMIO and I/O regions owned by the device
> +  //
> +  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Resources;
> +};
> +
> +extern EFI_GUID gEdkiiNonDiscoverableDeviceProtocolGuid;
> +
> +#endif
> diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
> index 74b870051c67..6b956fc80c93 100644
> --- a/MdeModulePkg/MdeModulePkg.dec
> +++ b/MdeModulePkg/MdeModulePkg.dec
> @@ -505,6 +505,9 @@ [Protocols]
>    #  Include/Protocol/Ps2Policy.h
>    gEfiPs2PolicyProtocolGuid = { 0x4DF19259, 0xDC71, 0x4D46, { 0xBE, 0xF1, 0x35, 0x7B, 0xB5, 0x78, 0xC4, 0x18 } }
>  
> +  ## Include/Protocol/NonDiscoverableDevice.h
> +  gEdkiiNonDiscoverableDeviceProtocolGuid = { 0x0d51905b, 0xb77e, 0x452a, {0xa2, 0xc0, 0xec, 0xa0, 0xcc, 0x8d, 0x51, 0x4a } }
> +
>  #
>  # [Error.gEfiMdeModulePkgTokenSpaceGuid]
>  #   0x80000001 | Invalid value provided.
> -- 
> 2.7.4
> 


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol
  2016-11-16 17:48   ` Leif Lindholm
@ 2016-11-17  2:53     ` Ni, Ruiyu
  2016-11-17  6:07       ` Ard Biesheuvel
  0 siblings, 1 reply; 27+ messages in thread
From: Ni, Ruiyu @ 2016-11-17  2:53 UTC (permalink / raw)
  To: Leif Lindholm, Ard Biesheuvel
  Cc: edk2-devel@lists.01.org, afish@apple.com, Gao, Liming,
	Kinney, Michael D

Ard,
I have two comments in below.

Thanks/Ray

> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
> Leif Lindholm
> Sent: Thursday, November 17, 2016 1:49 AM
> To: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Ni, Ruiyu <ruiyu.ni@intel.com>; edk2-devel@lists.01.org;
> afish@apple.com; Gao, Liming <liming.gao@intel.com>; Kinney, Michael D
> <michael.d.kinney@intel.com>
> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-
> discoverable device protocol
> 
> On Wed, Nov 16, 2016 at 04:59:27PM +0000, Ard Biesheuvel wrote:
> > Introduce a protocol that can be exposed by a platform for devices
> > that are not discoverable, usually because they are wired straight to
> > the memory bus rather than to an enumerable bus like PCI or USB.
> >
> > Contributed-under: TianoCore Contribution Agreement 1.0
> > Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > ---
> >  MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h | 90
> ++++++++++++++++++++
> >  MdeModulePkg/MdeModulePkg.dec                         |  3 +
> >  2 files changed, 93 insertions(+)
> >
> > diff --git a/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
> > b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
> > new file mode 100644
> > index 000000000000..47ed841b407b
> > --- /dev/null
> > +++ b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
> > @@ -0,0 +1,90 @@
> > +/** @file
> > +  Protocol to describe devices that are not on a discoverable bus
> > +
> > +  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_DEVICE_H__ #define
> > +__NON_DISCOVERABLE_DEVICE_H__
> > +
> > +#include <IndustryStandard/Acpi.h>
> > +
> > +#define EDKII_NON_DISCOVERABLE_DEVICE_PROTOCOL_GUID \
> > +  { 0x0d51905b, 0xb77e, 0x452a, {0xa2, 0xc0, 0xec, 0xa0, 0xcc, 0x8d,
> > +0x51, 0x4a } }

1. Can you add "PCI" keyword into the protocol name?
e.g.: EDKII_NON_DISCOVERABLE_PCI_DEVICE_PROTOCOL_GUID

> > +
> > +//
> > +// Protocol interface structure
> > +//
> > +typedef struct _NON_DISCOVERABLE_DEVICE
> NON_DISCOVERABLE_DEVICE;
> > +
> > +//
> > +// Data Types
> > +//
> > +typedef enum {
> > +  NonDiscoverableDeviceTypeAmba,
> > +  NonDiscoverableDeviceTypeOhci,
> > +  NonDiscoverableDeviceTypeUhci,
> > +  NonDiscoverableDeviceTypeEhci,
> > +  NonDiscoverableDeviceTypeXhci,
> > +  NonDiscoverableDeviceTypeAhci,
> > +  NonDiscoverableDeviceTypeSdhci,
> > +  NonDiscoverableDeviceTypeUfs,
> > +  NonDiscoverableDeviceTypeNvme,


> 
> Just one OCD comment/question left:
> Can we keep these sorted alphabetically?
> (Also in switch statements in later patches?)
> 
> Other than that, I'm (very) happy with this series.
> 
> /
>     Leif
> 
> > +  NonDiscoverableDeviceTypeMax,
> > +} NON_DISCOVERABLE_DEVICE_TYPE;
> > +
> > +typedef enum {
> > +  NonDiscoverableDeviceDmaTypeCoherent,
> > +  NonDiscoverableDeviceDmaTypeNonCoherent,
> > +  NonDiscoverableDeviceDmaTypeMax,
> > +} NON_DISCOVERABLE_DEVICE_DMA_TYPE;
> > +
> > +//
> > +// Function Prototypes
> > +//
> > +
> > +/**
> > +  Perform device specific initialization before the device is started
> > +
> > +  @param  This          The non-discoverable device protocol pointer
> > +
> > +  @retval EFI_SUCCESS   Initialization successful, the device may be used
> > +  @retval Other         Initialization failed, device should not be started
> > +**/
> > +typedef
> > +EFI_STATUS
> > +(EFIAPI *NON_DISCOVERABLE_DEVICE_INIT) (
> > +  IN  NON_DISCOVERABLE_DEVICE       *This
> > +  );
> > +
> > +struct _NON_DISCOVERABLE_DEVICE {
> > +  //
> > +  // The type of device
> > +  //
> > +  NON_DISCOVERABLE_DEVICE_TYPE        Type;
2. Can you use PCI class code to replace the enum type here?
e.g.: UINT8 Class; UINT8 SubClass; UINT8 Programming Interface;
The enum type can be defined in the helper library.
In this way, we make the protocol definition stable enough.

> > +  //
> > +  // Whether this device is DMA coherent
> > +  //
> > +  NON_DISCOVERABLE_DEVICE_DMA_TYPE    DmaType;
> > +  //
> > +  // Initialization function for the device
> > +  //
> > +  NON_DISCOVERABLE_DEVICE_INIT        Initialize;
> > +  //
> > +  // The MMIO and I/O regions owned by the device
> > +  //
> > +  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Resources;
> > +};
> > +
> > +extern EFI_GUID gEdkiiNonDiscoverableDeviceProtocolGuid;
> > +
> > +#endif
> > diff --git a/MdeModulePkg/MdeModulePkg.dec
> > b/MdeModulePkg/MdeModulePkg.dec index 74b870051c67..6b956fc80c93
> > 100644
> > --- a/MdeModulePkg/MdeModulePkg.dec
> > +++ b/MdeModulePkg/MdeModulePkg.dec
> > @@ -505,6 +505,9 @@ [Protocols]
> >    #  Include/Protocol/Ps2Policy.h
> >    gEfiPs2PolicyProtocolGuid = { 0x4DF19259, 0xDC71, 0x4D46, { 0xBE,
> > 0xF1, 0x35, 0x7B, 0xB5, 0x78, 0xC4, 0x18 } }
> >
> > +  ## Include/Protocol/NonDiscoverableDevice.h
> > +  gEdkiiNonDiscoverableDeviceProtocolGuid = { 0x0d51905b, 0xb77e,
> > + 0x452a, {0xa2, 0xc0, 0xec, 0xa0, 0xcc, 0x8d, 0x51, 0x4a } }
> > +
> >  #
> >  # [Error.gEfiMdeModulePkgTokenSpaceGuid]
> >  #   0x80000001 | Invalid value provided.
> > --
> > 2.7.4
> >
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 3/5] MdeModulePkg: implement generic PCI I/O driver for non-discoverable devices
  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
  0 siblings, 1 reply; 27+ messages in thread
From: Ni, Ruiyu @ 2016-11-17  3:29 UTC (permalink / raw)
  To: Ard Biesheuvel, edk2-devel@lists.01.org, Gao, Liming,
	Kinney, Michael D
  Cc: afish@apple.com, mw@semihalf.com, leif.lindholm@linaro.org



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/ComponentNam
> e.c
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/ComponentNam
> e.c
> new file mode 100644
> index 000000000000..6e51d00fe434
> --- /dev/null
> +++
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/ComponentNam
> e.c
> @@ -0,0 +1,75 @@
> +/** @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.
> +
> +**/
> +
> +#include "NonDiscoverablePciDeviceIo.h"
> +
> +//
> +// The purpose of the following scaffolding
> +(EFI_COMPONENT_NAME_PROTOCOL and //
> EFI_COMPONENT_NAME2_PROTOCOL
> +implementation) is to format the driver's name // in English, for
> +display on standard console devices. This is recommended for // UEFI
> +drivers that follow the UEFI Driver Model. Refer to the Driver Writer's //
> Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
> +//
> +
> +STATIC
> +EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
> +  { "eng;en", L"PCI I/O protocol emulation driver for non-discoverable
> devices" },
> +  { NULL,     NULL                   }
> +};
> +
> +EFI_COMPONENT_NAME_PROTOCOL gComponentName;
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +NonDiscoverablePciGetDriverName (
> +  IN  EFI_COMPONENT_NAME_PROTOCOL *This,
> +  IN  CHAR8                       *Language,
> +  OUT CHAR16                      **DriverName
> +  )
> +{
> +  return LookupUnicodeString2 (
> +           Language,
> +           This->SupportedLanguages,
> +           mDriverNameTable,
> +           DriverName,
> +           (BOOLEAN)(This == &gComponentName) // Iso639Language
> +           );
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +NonDiscoverablePciGetDeviceName (
> +  IN  EFI_COMPONENT_NAME_PROTOCOL *This,
> +  IN  EFI_HANDLE                  DeviceHandle,
> +  IN  EFI_HANDLE                  ChildHandle,
> +  IN  CHAR8                       *Language,
> +  OUT CHAR16                      **ControllerName
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +EFI_COMPONENT_NAME_PROTOCOL gComponentName = {
> +  &NonDiscoverablePciGetDriverName,
> +  &NonDiscoverablePciGetDeviceName,
> +  "eng" // SupportedLanguages, ISO 639-2 language codes };
> +
> +EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {
> +  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)
> &NonDiscoverablePciGetDriverName,
> +  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)
> +&NonDiscoverablePciGetDeviceName,
> +  "en" // SupportedLanguages, RFC 4646 language codes };
> diff --git
> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceDxe.c
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceDxe.c
> new file mode 100644
> index 000000000000..32da576485aa
> --- /dev/null
> +++
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> Pc
> +++ iDeviceDxe.c
> @@ -0,0 +1,223 @@
> +/** @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.
> +
> +**/
> +
> +#include "NonDiscoverablePciDeviceIo.h"
> +
> +#include <Protocol/DriverBinding.h>
> +
> +//
> +// Probe, start and stop functions of this driver, called by the DXE
> +core for // specific devices.
> +//
> +// The following specifications document these interfaces:
> +// - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding
> +Protocol // - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding
> +Protocol // // The implementation follows:
> +// - Driver Writer's Guide for UEFI 2.3.1 v1.01
> +//   - 5.1.3.4 OpenProtocol() and CloseProtocol()
> +// - UEFI Spec 2.3.1 + Errata C
> +//   -  6.3 Protocol Handler Services
> +//
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +NonDiscoverablePciDeviceSupported (
> +  IN EFI_DRIVER_BINDING_PROTOCOL *This,
> +  IN EFI_HANDLE                  DeviceHandle,
> +  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
> +  )
> +{
> +  NON_DISCOVERABLE_DEVICE             *Device;
> +  EFI_STATUS                          Status;
> +  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Desc;
> +
> +  Status = gBS->OpenProtocol (DeviceHandle,
> +                  &gEdkiiNonDiscoverableDeviceProtocolGuid, (VOID **)&Device,
> +                  This->DriverBindingHandle, DeviceHandle,
> +                  EFI_OPEN_PROTOCOL_BY_DRIVER);  if (EFI_ERROR
> + (Status)) {
> +    return Status;
> +  }
> +
> +  switch (Device->Type) {
> +  //
> +  // We only support the following device types  //  case
> + NonDiscoverableDeviceTypeOhci:
> +  case NonDiscoverableDeviceTypeUhci:
> +  case NonDiscoverableDeviceTypeEhci:
> +  case NonDiscoverableDeviceTypeXhci:
> +  case NonDiscoverableDeviceTypeAhci:
> +  case NonDiscoverableDeviceTypeSdhci:
> +  case NonDiscoverableDeviceTypeUfs:
> +  case NonDiscoverableDeviceTypeNvme:
> +    //
> +    // Restricted to DMA coherent for now
> +    //
> +    if (Device->DmaType == NonDiscoverableDeviceDmaTypeCoherent) {
> +      Status = EFI_SUCCESS;
> +      break;
> +    }
> +  default:
> +    Status = EFI_UNSUPPORTED;
> +    goto CloseProtocol;
> +  }
> +
> +  //
> +  // We only support MMIO devices, so iterate over the resources to
> + ensure  // that they only describe things that we can handle  //  for
> + (Desc = Device->Resources; Desc->Desc != ACPI_END_TAG_DESCRIPTOR;
> +       Desc = (VOID *)((UINT8 *)Desc + Desc->Len + 3)) {
> +    if (Desc->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR ||
> +        Desc->ResType != ACPI_ADDRESS_SPACE_TYPE_MEM) {
> +      Status = EFI_UNSUPPORTED;
> +      break;
> +    }
> +  }
> +
> +CloseProtocol:
> +  gBS->CloseProtocol (DeviceHandle,
> &gEdkiiNonDiscoverableDeviceProtocolGuid,
> +         This->DriverBindingHandle, DeviceHandle);
> +
> +  return Status;
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +NonDiscoverablePciDeviceStart (
> +  IN EFI_DRIVER_BINDING_PROTOCOL *This,
> +  IN EFI_HANDLE                  DeviceHandle,
> +  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
> +  )
> +{
> +  NON_DISCOVERABLE_PCI_DEVICE   *Dev;
> +  EFI_STATUS                    Status;
> +
> +  Dev = AllocateZeroPool (sizeof *Dev);  if (Dev == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  Status = gBS->OpenProtocol (DeviceHandle,
> +                  &gEdkiiNonDiscoverableDeviceProtocolGuid,
> +                  (VOID **)&Dev->Device, This->DriverBindingHandle,
> +                  DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);  if
> + (EFI_ERROR (Status)) {
> +    goto FreeDev;
> +  }
> +
> +  InitializePciIoProtocol (Dev);
> +
> +  //
> +  // Setup complete, attempt to export the driver instance's  //
> + EFI_PCI_IO_PROTOCOL interface.
> +  //
> +  Dev->Signature = NON_DISCOVERABLE_PCI_DEVICE_SIG;  Status =
> + gBS->InstallProtocolInterface (&DeviceHandle, &gEfiPciIoProtocolGuid,
> +                  EFI_NATIVE_INTERFACE, &Dev->PciIo);  if (EFI_ERROR
> + (Status)) {
> +    goto CloseProtocol;
> +  }
> +
> +  return EFI_SUCCESS;
> +
> +CloseProtocol:
> +  gBS->CloseProtocol (DeviceHandle,
> &gEdkiiNonDiscoverableDeviceProtocolGuid,
> +         This->DriverBindingHandle, DeviceHandle);
> +
> +FreeDev:
> +  FreePool (Dev);
> +
> +  return Status;
> +}
> +
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +NonDiscoverablePciDeviceStop (
> +  IN EFI_DRIVER_BINDING_PROTOCOL *This,
> +  IN EFI_HANDLE                  DeviceHandle,
> +  IN UINTN                       NumberOfChildren,
> +  IN EFI_HANDLE                  *ChildHandleBuffer
> +  )
> +{
> +  EFI_STATUS                      Status;
> +  EFI_PCI_IO_PROTOCOL             *PciIo;
> +  NON_DISCOVERABLE_PCI_DEVICE     *Dev;
> +
> +  Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
> +                  (VOID **)&PciIo, This->DriverBindingHandle, DeviceHandle,
> +                  EFI_OPEN_PROTOCOL_GET_PROTOCOL);  if (EFI_ERROR
> + (Status)) {
> +    return Status;
> +  }
> +
> +  Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (PciIo);
> +
> +  //
> +  // Handle Stop() requests for in-use driver instances gracefully.
> +  //
> +  Status = gBS->UninstallProtocolInterface (DeviceHandle,
> +                  &gEfiPciIoProtocolGuid, &Dev->PciIo);  if (EFI_ERROR
> + (Status)) {
> +    return Status;
> +  }
> +
> +  gBS->CloseProtocol (DeviceHandle,
> &gEdkiiNonDiscoverableDeviceProtocolGuid,
> +         This->DriverBindingHandle, DeviceHandle);
> +
> +  FreePool (Dev);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +//
> +// The static object that groups the Supported() (ie. probe), Start()
> +and // Stop() functions of the driver together. Refer to UEFI Spec
> +2.3.1 + Errata // C, 10.1 EFI Driver Binding Protocol.
> +//
> +STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
> +  &NonDiscoverablePciDeviceSupported,
> +  &NonDiscoverablePciDeviceStart,
> +  &NonDiscoverablePciDeviceStop,
> +  0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed
> +drivers
> +  NULL,
> +  NULL
> +};
> +
> +//
> +// Entry point of this driver.
> +//
> +EFI_STATUS
> +EFIAPI
> +NonDiscoverablePciDeviceDxeEntryPoint (
> +  IN EFI_HANDLE       ImageHandle,
> +  IN EFI_SYSTEM_TABLE *SystemTable
> +  )
> +{
> +  return EfiLibInstallDriverBindingComponentName2 (
> +           ImageHandle,
> +           SystemTable,
> +           &gDriverBinding,
> +           ImageHandle,
> +           &gComponentName,
> +           &gComponentName2
> +           );
> +}
> diff --git
> a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceDxe.inf
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> PciDeviceDxe.inf
> new file mode 100644
> index 000000000000..543e622694a0
> --- /dev/null
> +++
> b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverable
> Pc
> +++ iDeviceDxe.inf
> @@ -0,0 +1,42 @@
> +## @file
> +# Copyright (C) 2016, Linaro Ltd.
> +#
> +# 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.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010019
> +  BASE_NAME                      = NonDiscoverablePciDeviceDxe
> +  FILE_GUID                      = 71fd84cd-353b-464d-b7a4-6ea7b96995cb
> +  MODULE_TYPE                    = UEFI_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = NonDiscoverablePciDeviceDxeEntryPoint
> +
> +[Sources]
> +  ComponentName.c
> +  NonDiscoverablePciDeviceDxe.c
> +  NonDiscoverablePciDeviceIo.c
> +  NonDiscoverablePciDeviceIo.h
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[LibraryClasses]
> +  BaseMemoryLib
> +  DebugLib
> +  MemoryAllocationLib
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +  UefiLib
> +
> +[Protocols]
> +  gEfiPciIoProtocolGuid                         ## BY_START
> +  gEdkiiNonDiscoverableDeviceProtocolGuid       ## TO_START
> 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.

> +    } 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.

> +
> +    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



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 0/5] MdeModulePkg: add support for non-discoverable devices
  2016-11-16 16:59 [PATCH v3 0/5] MdeModulePkg: add support for non-discoverable devices Ard Biesheuvel
                   ` (4 preceding siblings ...)
  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 ` Marcin Wojtas
  2016-11-23 14:31   ` Marcin Wojtas
  5 siblings, 1 reply; 27+ messages in thread
From: Marcin Wojtas @ 2016-11-17  4:36 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: edk2-devel-01, Gao, Liming, Ni, Ruiyu, Kinney, Michael D, afish,
	Leif Lindholm

Hi Ard,

Series tested on Marvell Armada 7040 board (XHCI and SDHCI). You can add:
Tested-by: Marcin Wojtas <mw@semihalf.com>

Best regards,
Marcin

2016-11-16 17:59 GMT+01:00 Ard Biesheuvel <ard.biesheuvel@linaro.org>:
> The rationale for this series is the fact that many ARM platforms implement
> some form of PCI 'emulation', to allow non-discoverable devices that implement
> standardized host controller interfaces (i.e., EHCI, AHCI) to be controlled by
> the generic EDK2 drivers, which are layered on top of the PCI I/O protocols
> (even though the respective host controller specifications don't mandate that)
>
> There are a couple of problems with that approach:
> - Most implementations are based on the original code created for BeagleBoard,
>   which is a 32-bit platform. Unlike x86, which usually does not perform PCI
>   DMA above 4 GB, the ARM ecosystem is much more heterogeneous, and platforms
>   that have memory both above and below the 4 GB mark may ship with, e.g., EHCI
>   controllers that do not implement 64-bit DMA addressing.
> - Implementations depend on the DmaLib library class in EmbeddedPkg, of which
>   coherent and non-coherent implementations exists. However, both types of
>   devices may appear on a single platform, requiring several instances of the
>   same driver.
> - Existing implementations do not follow the UEFI driver model, but instantiate
>   a fixed number of PCI I/O protocol handles, and bring up all the devices when
>   doing so. However, the UEFI philosophy is to only instantiate (and thus
>   initialize) devices that are involved in booting.
>
> So instead, let's define a base protocol that simply asserts the presence of
> a certain kind of device at a certain memory offset, allowing platforms to
> instantiate any number of these statically, and leave it to post-DXE driver
> dispatch to actually bind the drivers as usual. This is implemented in patch #1.
> Note that it includes an AMBA device type, which we intend to use in the future
> to move ARM AMBA drivers to the UEFI driver model as well (i.e., LCD controller,
> SD/MMC controller)
>
> Patch #2 implements a utility library to register non-discoverable devices.
>
> Patch #3 implements the UEFI driver that instantiates PCI I/O protocol handles
> for non-discoverable devices that we know can be driven by a generic driver in
> EDK2. The initial version implements coherent DMA only.
>
> Patch #4 implements non-coherent DMA for the driver added in patch #3.
>
> Patch #5 is included for reference. It ports the BeagleBoard platform to the
> new driver stack.
>
> Changes in v3:
> - Modified the base protocol to describe any number of resources using ACPI
>   resource descriptors. The current crop of targeted peripherals does not
>   require that, but it allows for much more flexibility in the future. This
>   also means that the MMIO region sizes are no longer hard-coded base on the
>   controller type (EHCI, AHCI, etc) but need to be declared when the devices
>   are registered.
> - Update the registration library API to allow multiple MMIO regions to be
>   declared.
> - When performing uncached allocations, record the original memory region
>   attributes so we can restore them correctly on free.
> - Some fixes in the 4GB boundary checks for Map/Unmap
> - Rename gNonDiscoverableDeviceProtocolGuid to
>   gEdkiiNonDiscoverableDeviceProtocolGuid
>
> Ard Biesheuvel (5):
>   MdeModulePkg: introduce non-discoverable device protocol
>   MdeModule: introduce helper library to register non-discoverable
>     devices
>   MdeModulePkg: implement generic PCI I/O driver for non-discoverable
>     devices
>   MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent
>     DMA
>   Omap35xxPkg/PciEmulation: port to new non-discoverable device
>     infrastructure
>
>  BeagleBoardPkg/BeagleBoardPkg.dsc                                                                  |    2 +
>  BeagleBoardPkg/BeagleBoardPkg.fdf                                                                  |    1 +
>  MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/ComponentName.c                                   |   75 ++
>  MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c                     |  226 ++++
>  MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf                   |   44 +
>  MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c                      | 1187 ++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h                      |  113 ++
>  MdeModulePkg/Include/Library/NonDiscoverableDeviceRegistrationLib.h                                |   49 +
>  MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h                                              |   90 ++
>  MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.c   |  161 +++
>  MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf |   34 +
>  MdeModulePkg/MdeModulePkg.dec                                                                      |    7 +
>  MdeModulePkg/MdeModulePkg.dsc                                                                      |    3 +
>  Omap35xxPkg/Omap35xxPkg.dsc                                                                        |    2 +-
>  Omap35xxPkg/PciEmulation/PciEmulation.c                                                            |  578 +---------
>  Omap35xxPkg/PciEmulation/PciEmulation.h                                                            |  292 -----
>  Omap35xxPkg/PciEmulation/PciEmulation.inf                                                          |   16 +-
>  Omap35xxPkg/PciEmulation/PciRootBridgeIo.c                                                         |  306 -----
>  18 files changed, 2025 insertions(+), 1161 deletions(-)
>  create mode 100644 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/ComponentName.c
>  create mode 100644 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
>  create mode 100644 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
>  create mode 100644 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
>  create mode 100644 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h
>  create mode 100644 MdeModulePkg/Include/Library/NonDiscoverableDeviceRegistrationLib.h
>  create mode 100644 MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>  create mode 100644 MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.c
>  create mode 100644 MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
>  delete mode 100644 Omap35xxPkg/PciEmulation/PciEmulation.h
>  delete mode 100644 Omap35xxPkg/PciEmulation/PciRootBridgeIo.c
>
> --
> 2.7.4
>


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol
  2016-11-17  2:53     ` Ni, Ruiyu
@ 2016-11-17  6:07       ` Ard Biesheuvel
  2016-11-17  7:52         ` Ni, Ruiyu
  0 siblings, 1 reply; 27+ messages in thread
From: Ard Biesheuvel @ 2016-11-17  6:07 UTC (permalink / raw)
  To: Ni, Ruiyu
  Cc: Leif Lindholm, edk2-devel@lists.01.org, afish@apple.com,
	Gao, Liming, Kinney, Michael D



> On 17 Nov 2016, at 02:53, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
> 
> Ard,
> I have two comments in below.
> 
> Thanks/Ray
> 
>> -----Original Message-----
>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
>> Leif Lindholm
>> Sent: Thursday, November 17, 2016 1:49 AM
>> To: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> Cc: Ni, Ruiyu <ruiyu.ni@intel.com>; edk2-devel@lists.01.org;
>> afish@apple.com; Gao, Liming <liming.gao@intel.com>; Kinney, Michael D
>> <michael.d.kinney@intel.com>
>> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-
>> discoverable device protocol
>> 
>>> On Wed, Nov 16, 2016 at 04:59:27PM +0000, Ard Biesheuvel wrote:
>>> Introduce a protocol that can be exposed by a platform for devices
>>> that are not discoverable, usually because they are wired straight to
>>> the memory bus rather than to an enumerable bus like PCI or USB.
>>> 
>>> Contributed-under: TianoCore Contribution Agreement 1.0
>>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>> ---
>>> MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h | 90
>> ++++++++++++++++++++
>>> MdeModulePkg/MdeModulePkg.dec                         |  3 +
>>> 2 files changed, 93 insertions(+)
>>> 
>>> diff --git a/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>> b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>> new file mode 100644
>>> index 000000000000..47ed841b407b
>>> --- /dev/null
>>> +++ b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>> @@ -0,0 +1,90 @@
>>> +/** @file
>>> +  Protocol to describe devices that are not on a discoverable bus
>>> +
>>> +  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_DEVICE_H__ #define
>>> +__NON_DISCOVERABLE_DEVICE_H__
>>> +
>>> +#include <IndustryStandard/Acpi.h>
>>> +
>>> +#define EDKII_NON_DISCOVERABLE_DEVICE_PROTOCOL_GUID \
>>> +  { 0x0d51905b, 0xb77e, 0x452a, {0xa2, 0xc0, 0xec, 0xa0, 0xcc, 0x8d,
>>> +0x51, 0x4a } }
> 
> 1. Can you add "PCI" keyword into the protocol name?
> e.g.: EDKII_NON_DISCOVERABLE_PCI_DEVICE_PROTOCOL_GUID
> 

No. This protocol does not describe pci devices, and it is a peculiarity of the edk2 driver stack that some non-pci devices can only be driven by pci drivers.

in other words, pci is part of the /driver/ side, and it is perfectly possible for, e.g., a non-discoverable ahci device to be driven by a different non-pci driver in the future.

>>> +
>>> +//
>>> +// Protocol interface structure
>>> +//
>>> +typedef struct _NON_DISCOVERABLE_DEVICE
>> NON_DISCOVERABLE_DEVICE;
>>> +
>>> +//
>>> +// Data Types
>>> +//
>>> +typedef enum {
>>> +  NonDiscoverableDeviceTypeAmba,
>>> +  NonDiscoverableDeviceTypeOhci,
>>> +  NonDiscoverableDeviceTypeUhci,
>>> +  NonDiscoverableDeviceTypeEhci,
>>> +  NonDiscoverableDeviceTypeXhci,
>>> +  NonDiscoverableDeviceTypeAhci,
>>> +  NonDiscoverableDeviceTypeSdhci,
>>> +  NonDiscoverableDeviceTypeUfs,
>>> +  NonDiscoverableDeviceTypeNvme,
> 
> 
>> 
>> Just one OCD comment/question left:
>> Can we keep these sorted alphabetically?
>> (Also in switch statements in later patches?)
>> 
>> Other than that, I'm (very) happy with this series.
>> 
>> /
>>    Leif
>> 
>>> +  NonDiscoverableDeviceTypeMax,
>>> +} NON_DISCOVERABLE_DEVICE_TYPE;
>>> +
>>> +typedef enum {
>>> +  NonDiscoverableDeviceDmaTypeCoherent,
>>> +  NonDiscoverableDeviceDmaTypeNonCoherent,
>>> +  NonDiscoverableDeviceDmaTypeMax,
>>> +} NON_DISCOVERABLE_DEVICE_DMA_TYPE;
>>> +
>>> +//
>>> +// Function Prototypes
>>> +//
>>> +
>>> +/**
>>> +  Perform device specific initialization before the device is started
>>> +
>>> +  @param  This          The non-discoverable device protocol pointer
>>> +
>>> +  @retval EFI_SUCCESS   Initialization successful, the device may be used
>>> +  @retval Other         Initialization failed, device should not be started
>>> +**/
>>> +typedef
>>> +EFI_STATUS
>>> +(EFIAPI *NON_DISCOVERABLE_DEVICE_INIT) (
>>> +  IN  NON_DISCOVERABLE_DEVICE       *This
>>> +  );
>>> +
>>> +struct _NON_DISCOVERABLE_DEVICE {
>>> +  //
>>> +  // The type of device
>>> +  //
>>> +  NON_DISCOVERABLE_DEVICE_TYPE        Type;
> 2. Can you use PCI class code to replace the enum type here?
> e.g.: UINT8 Class; UINT8 SubClass; UINT8 Programming Interface;
> The enum type can be defined in the helper library.
> In this way, we make the protocol definition stable enough.
> 

Again, i think this is a bad idea. This is meant to describe the /device/, not the edk2 implementation detail that some standardized host controller interfaces were implemented in a way that requires pci. It would also make it impossible to describe AMBA devices

>>> +  //
>>> +  // Whether this device is DMA coherent
>>> +  //
>>> +  NON_DISCOVERABLE_DEVICE_DMA_TYPE    DmaType;
>>> +  //
>>> +  // Initialization function for the device
>>> +  //
>>> +  NON_DISCOVERABLE_DEVICE_INIT        Initialize;
>>> +  //
>>> +  // The MMIO and I/O regions owned by the device
>>> +  //
>>> +  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Resources;
>>> +};
>>> +
>>> +extern EFI_GUID gEdkiiNonDiscoverableDeviceProtocolGuid;
>>> +
>>> +#endif
>>> diff --git a/MdeModulePkg/MdeModulePkg.dec
>>> b/MdeModulePkg/MdeModulePkg.dec index 74b870051c67..6b956fc80c93
>>> 100644
>>> --- a/MdeModulePkg/MdeModulePkg.dec
>>> +++ b/MdeModulePkg/MdeModulePkg.dec
>>> @@ -505,6 +505,9 @@ [Protocols]
>>>   #  Include/Protocol/Ps2Policy.h
>>>   gEfiPs2PolicyProtocolGuid = { 0x4DF19259, 0xDC71, 0x4D46, { 0xBE,
>>> 0xF1, 0x35, 0x7B, 0xB5, 0x78, 0xC4, 0x18 } }
>>> 
>>> +  ## Include/Protocol/NonDiscoverableDevice.h
>>> +  gEdkiiNonDiscoverableDeviceProtocolGuid = { 0x0d51905b, 0xb77e,
>>> + 0x452a, {0xa2, 0xc0, 0xec, 0xa0, 0xcc, 0x8d, 0x51, 0x4a } }
>>> +
>>> #
>>> # [Error.gEfiMdeModulePkgTokenSpaceGuid]
>>> #   0x80000001 | Invalid value provided.
>>> --
>>> 2.7.4
>>> 
>> _______________________________________________
>> edk2-devel mailing list
>> edk2-devel@lists.01.org
>> https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol
  2016-11-17  6:07       ` Ard Biesheuvel
@ 2016-11-17  7:52         ` Ni, Ruiyu
  2016-11-17 10:43           ` Ard Biesheuvel
  0 siblings, 1 reply; 27+ messages in thread
From: Ni, Ruiyu @ 2016-11-17  7:52 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Kinney, Michael D, edk2-devel@lists.01.org, Gao, Liming,
	afish@apple.com, Leif Lindholm



Thanks/Ray

> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
> Ard Biesheuvel
> Sent: Thursday, November 17, 2016 2:07 PM
> To: Ni, Ruiyu <ruiyu.ni@intel.com>
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; edk2-
> devel@lists.01.org; Gao, Liming <liming.gao@intel.com>; afish@apple.com;
> Leif Lindholm <leif.lindholm@linaro.org>
> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-
> discoverable device protocol
> 
> 
> 
> > On 17 Nov 2016, at 02:53, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
> >
> > Ard,
> > I have two comments in below.
> >
> > Thanks/Ray
> >
> >> -----Original Message-----
> >> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf
> >> Of Leif Lindholm
> >> Sent: Thursday, November 17, 2016 1:49 AM
> >> To: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> >> Cc: Ni, Ruiyu <ruiyu.ni@intel.com>; edk2-devel@lists.01.org;
> >> afish@apple.com; Gao, Liming <liming.gao@intel.com>; Kinney, Michael
> >> D <michael.d.kinney@intel.com>
> >> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-
> >> discoverable device protocol
> >>
> >>> On Wed, Nov 16, 2016 at 04:59:27PM +0000, Ard Biesheuvel wrote:
> >>> Introduce a protocol that can be exposed by a platform for devices
> >>> that are not discoverable, usually because they are wired straight
> >>> to the memory bus rather than to an enumerable bus like PCI or USB.
> >>>
> >>> Contributed-under: TianoCore Contribution Agreement 1.0
> >>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> >>> ---
> >>> MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h | 90
> >> ++++++++++++++++++++
> >>> MdeModulePkg/MdeModulePkg.dec                         |  3 +
> >>> 2 files changed, 93 insertions(+)
> >>>
> >>> diff --git a/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
> >>> b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
> >>> new file mode 100644
> >>> index 000000000000..47ed841b407b
> >>> --- /dev/null
> >>> +++ b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
> >>> @@ -0,0 +1,90 @@
> >>> +/** @file
> >>> +  Protocol to describe devices that are not on a discoverable bus
> >>> +
> >>> +  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_DEVICE_H__ #define
> >>> +__NON_DISCOVERABLE_DEVICE_H__
> >>> +
> >>> +#include <IndustryStandard/Acpi.h>
> >>> +
> >>> +#define EDKII_NON_DISCOVERABLE_DEVICE_PROTOCOL_GUID \
> >>> +  { 0x0d51905b, 0xb77e, 0x452a, {0xa2, 0xc0, 0xec, 0xa0, 0xcc,
> >>> +0x8d, 0x51, 0x4a } }
> >
> > 1. Can you add "PCI" keyword into the protocol name?
> > e.g.: EDKII_NON_DISCOVERABLE_PCI_DEVICE_PROTOCOL_GUID
> >
> 
> No. This protocol does not describe pci devices, and it is a peculiarity of the
> edk2 driver stack that some non-pci devices can only be driven by pci drivers.
> 
> in other words, pci is part of the /driver/ side, and it is perfectly possible for,
> e.g., a non-discoverable ahci device to be driven by a different non-pci driver
> in the future.
> 

I see. So some types of devices are handled by the current
NonDiscoveablePciDevice driver, and some other types of devices may be
handled by a future NonDiscoverableXXXDevice driver.
Now since the AHCI type is already handled by the NonDiscoverablePciDevice
driver, when there is a new NonDiscoverableXXXDevice driver, how can the two
know whether it should manage the AHCI type device or not?
Besides since now all the EDKII Host Controller drivers are based on
PciIo, it implicitly requires all the low layer needs to produce PciIo interface
in order to re-use the EDKII Host Controller drivers.

> >>> +
> >>> +//
> >>> +// Protocol interface structure
> >>> +//
> >>> +typedef struct _NON_DISCOVERABLE_DEVICE
> >> NON_DISCOVERABLE_DEVICE;
> >>> +
> >>> +//
> >>> +// Data Types
> >>> +//
> >>> +typedef enum {
> >>> +  NonDiscoverableDeviceTypeAmba,
> >>> +  NonDiscoverableDeviceTypeOhci,
> >>> +  NonDiscoverableDeviceTypeUhci,
> >>> +  NonDiscoverableDeviceTypeEhci,
> >>> +  NonDiscoverableDeviceTypeXhci,
> >>> +  NonDiscoverableDeviceTypeAhci,
> >>> +  NonDiscoverableDeviceTypeSdhci,
> >>> +  NonDiscoverableDeviceTypeUfs,
> >>> +  NonDiscoverableDeviceTypeNvme,
> >
> >
> >>
> >> Just one OCD comment/question left:
> >> Can we keep these sorted alphabetically?
> >> (Also in switch statements in later patches?)
> >>
> >> Other than that, I'm (very) happy with this series.
> >>
> >> /
> >>    Leif
> >>
> >>> +  NonDiscoverableDeviceTypeMax,
> >>> +} NON_DISCOVERABLE_DEVICE_TYPE;
> >>> +
> >>> +typedef enum {
> >>> +  NonDiscoverableDeviceDmaTypeCoherent,
> >>> +  NonDiscoverableDeviceDmaTypeNonCoherent,
> >>> +  NonDiscoverableDeviceDmaTypeMax,
> >>> +} NON_DISCOVERABLE_DEVICE_DMA_TYPE;
> >>> +
> >>> +//
> >>> +// Function Prototypes
> >>> +//
> >>> +
> >>> +/**
> >>> +  Perform device specific initialization before the device is
> >>> +started
> >>> +
> >>> +  @param  This          The non-discoverable device protocol pointer
> >>> +
> >>> +  @retval EFI_SUCCESS   Initialization successful, the device may be
> used
> >>> +  @retval Other         Initialization failed, device should not be started
> >>> +**/
> >>> +typedef
> >>> +EFI_STATUS
> >>> +(EFIAPI *NON_DISCOVERABLE_DEVICE_INIT) (
> >>> +  IN  NON_DISCOVERABLE_DEVICE       *This
> >>> +  );
> >>> +
> >>> +struct _NON_DISCOVERABLE_DEVICE {
> >>> +  //
> >>> +  // The type of device
> >>> +  //
> >>> +  NON_DISCOVERABLE_DEVICE_TYPE        Type;
> > 2. Can you use PCI class code to replace the enum type here?
> > e.g.: UINT8 Class; UINT8 SubClass; UINT8 Programming Interface; The
> > enum type can be defined in the helper library.
> > In this way, we make the protocol definition stable enough.
> >
> 
> Again, i think this is a bad idea. This is meant to describe the /device/, not the
> edk2 implementation detail that some standardized host controller
> interfaces were implemented in a way that requires pci. It would also make it
> impossible to describe AMBA devices
Does AMBA  stand for Advanced Microcontroller Bus Architecture?
I have no idea about the AMBA.
Can you explain more why it's impossible to describe AMBA devices?

> 
> >>> +  //
> >>> +  // Whether this device is DMA coherent
> >>> +  //
> >>> +  NON_DISCOVERABLE_DEVICE_DMA_TYPE    DmaType;
> >>> +  //
> >>> +  // Initialization function for the device
> >>> +  //
> >>> +  NON_DISCOVERABLE_DEVICE_INIT        Initialize;
> >>> +  //
> >>> +  // The MMIO and I/O regions owned by the device
> >>> +  //
> >>> +  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Resources;
> >>> +};
> >>> +
> >>> +extern EFI_GUID gEdkiiNonDiscoverableDeviceProtocolGuid;
> >>> +
> >>> +#endif
> >>> diff --git a/MdeModulePkg/MdeModulePkg.dec
> >>> b/MdeModulePkg/MdeModulePkg.dec index
> 74b870051c67..6b956fc80c93
> >>> 100644
> >>> --- a/MdeModulePkg/MdeModulePkg.dec
> >>> +++ b/MdeModulePkg/MdeModulePkg.dec
> >>> @@ -505,6 +505,9 @@ [Protocols]
> >>>   #  Include/Protocol/Ps2Policy.h
> >>>   gEfiPs2PolicyProtocolGuid = { 0x4DF19259, 0xDC71, 0x4D46, { 0xBE,
> >>> 0xF1, 0x35, 0x7B, 0xB5, 0x78, 0xC4, 0x18 } }
> >>>
> >>> +  ## Include/Protocol/NonDiscoverableDevice.h
> >>> +  gEdkiiNonDiscoverableDeviceProtocolGuid = { 0x0d51905b, 0xb77e,
> >>> + 0x452a, {0xa2, 0xc0, 0xec, 0xa0, 0xcc, 0x8d, 0x51, 0x4a } }
> >>> +
> >>> #
> >>> # [Error.gEfiMdeModulePkgTokenSpaceGuid]
> >>> #   0x80000001 | Invalid value provided.
> >>> --
> >>> 2.7.4
> >>>
> >> _______________________________________________
> >> edk2-devel mailing list
> >> edk2-devel@lists.01.org
> >> https://lists.01.org/mailman/listinfo/edk2-devel
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol
  2016-11-17  7:52         ` Ni, Ruiyu
@ 2016-11-17 10:43           ` Ard Biesheuvel
  2016-11-18  2:11             ` Ni, Ruiyu
  0 siblings, 1 reply; 27+ messages in thread
From: Ard Biesheuvel @ 2016-11-17 10:43 UTC (permalink / raw)
  To: Ni, Ruiyu
  Cc: Kinney, Michael D, edk2-devel@lists.01.org, Gao, Liming,
	afish@apple.com, Leif Lindholm


> On 17 Nov 2016, at 08:52, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
> 
> 
> 
> Thanks/Ray
> 
>> -----Original Message-----
>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
>> Ard Biesheuvel
>> Sent: Thursday, November 17, 2016 2:07 PM
>> To: Ni, Ruiyu <ruiyu.ni@intel.com>
>> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; edk2-
>> devel@lists.01.org; Gao, Liming <liming.gao@intel.com>; afish@apple.com;
>> Leif Lindholm <leif.lindholm@linaro.org>
>> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-
>> discoverable device protocol
>> 
>> 
>> 
>>> On 17 Nov 2016, at 02:53, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>>> 
>>> Ard,
>>> I have two comments in below.
>>> 
>>> Thanks/Ray
>>> 
>>>> -----Original Message-----
>>>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf
>>>> Of Leif Lindholm
>>>> Sent: Thursday, November 17, 2016 1:49 AM
>>>> To: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>>> Cc: Ni, Ruiyu <ruiyu.ni@intel.com>; edk2-devel@lists.01.org;
>>>> afish@apple.com; Gao, Liming <liming.gao@intel.com>; Kinney, Michael
>>>> D <michael.d.kinney@intel.com>
>>>> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-
>>>> discoverable device protocol
>>>> 
>>>>> On Wed, Nov 16, 2016 at 04:59:27PM +0000, Ard Biesheuvel wrote:
>>>>> Introduce a protocol that can be exposed by a platform for devices
>>>>> that are not discoverable, usually because they are wired straight
>>>>> to the memory bus rather than to an enumerable bus like PCI or USB.
>>>>> 
>>>>> Contributed-under: TianoCore Contribution Agreement 1.0
>>>>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>>>> ---
>>>>> MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h | 90
>>>> ++++++++++++++++++++
>>>>> MdeModulePkg/MdeModulePkg.dec                         |  3 +
>>>>> 2 files changed, 93 insertions(+)
>>>>> 
>>>>> diff --git a/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>> b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>> new file mode 100644
>>>>> index 000000000000..47ed841b407b
>>>>> --- /dev/null
>>>>> +++ b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>> @@ -0,0 +1,90 @@
>>>>> +/** @file
>>>>> +  Protocol to describe devices that are not on a discoverable bus
>>>>> +
>>>>> +  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_DEVICE_H__ #define
>>>>> +__NON_DISCOVERABLE_DEVICE_H__
>>>>> +
>>>>> +#include <IndustryStandard/Acpi.h>
>>>>> +
>>>>> +#define EDKII_NON_DISCOVERABLE_DEVICE_PROTOCOL_GUID \
>>>>> +  { 0x0d51905b, 0xb77e, 0x452a, {0xa2, 0xc0, 0xec, 0xa0, 0xcc,
>>>>> +0x8d, 0x51, 0x4a } }
>>> 
>>> 1. Can you add "PCI" keyword into the protocol name?
>>> e.g.: EDKII_NON_DISCOVERABLE_PCI_DEVICE_PROTOCOL_GUID
>>> 
>> 
>> No. This protocol does not describe pci devices, and it is a peculiarity of the
>> edk2 driver stack that some non-pci devices can only be driven by pci drivers.
>> 
>> in other words, pci is part of the /driver/ side, and it is perfectly possible for,
>> e.g., a non-discoverable ahci device to be driven by a different non-pci driver
>> in the future.
>> 
> 
> I see. So some types of devices are handled by the current
> NonDiscoveablePciDevice driver, and some other types of devices may be
> handled by a future NonDiscoverableXXXDevice driver.
> Now since the AHCI type is already handled by the NonDiscoverablePciDevice
> driver, when there is a new NonDiscoverableXXXDevice driver, how can the two
> know whether it should manage the AHCI type device or not?

Good question. But how does the UEFI driver model deal with that? What happens if i have two drivers that both support the Ahci Pci class codes?

> Besides since now all the EDKII Host Controller drivers are based on
> PciIo, it implicitly requires all the low layer needs to produce PciIo interface
> in order to re-use the EDKII Host Controller drivers.
> 

Yes, that is the whole point of these patches. My preferred solution would be to split the ?hci drivers from pci i/o, by introducing intermediate protocols, but we both know that is unlikely to be accepted

>>>>> +
>>>>> +//
>>>>> +// Protocol interface structure
>>>>> +//
>>>>> +typedef struct _NON_DISCOVERABLE_DEVICE
>>>> NON_DISCOVERABLE_DEVICE;
>>>>> +
>>>>> +//
>>>>> +// Data Types
>>>>> +//
>>>>> +typedef enum {
>>>>> +  NonDiscoverableDeviceTypeAmba,
>>>>> +  NonDiscoverableDeviceTypeOhci,
>>>>> +  NonDiscoverableDeviceTypeUhci,
>>>>> +  NonDiscoverableDeviceTypeEhci,
>>>>> +  NonDiscoverableDeviceTypeXhci,
>>>>> +  NonDiscoverableDeviceTypeAhci,
>>>>> +  NonDiscoverableDeviceTypeSdhci,
>>>>> +  NonDiscoverableDeviceTypeUfs,
>>>>> +  NonDiscoverableDeviceTypeNvme,
>>> 
>>> 
>>>> 
>>>> Just one OCD comment/question left:
>>>> Can we keep these sorted alphabetically?
>>>> (Also in switch statements in later patches?)
>>>> 
>>>> Other than that, I'm (very) happy with this series.
>>>> 
>>>> /
>>>>   Leif
>>>> 
>>>>> +  NonDiscoverableDeviceTypeMax,
>>>>> +} NON_DISCOVERABLE_DEVICE_TYPE;
>>>>> +
>>>>> +typedef enum {
>>>>> +  NonDiscoverableDeviceDmaTypeCoherent,
>>>>> +  NonDiscoverableDeviceDmaTypeNonCoherent,
>>>>> +  NonDiscoverableDeviceDmaTypeMax,
>>>>> +} NON_DISCOVERABLE_DEVICE_DMA_TYPE;
>>>>> +
>>>>> +//
>>>>> +// Function Prototypes
>>>>> +//
>>>>> +
>>>>> +/**
>>>>> +  Perform device specific initialization before the device is
>>>>> +started
>>>>> +
>>>>> +  @param  This          The non-discoverable device protocol pointer
>>>>> +
>>>>> +  @retval EFI_SUCCESS   Initialization successful, the device may be
>> used
>>>>> +  @retval Other         Initialization failed, device should not be started
>>>>> +**/
>>>>> +typedef
>>>>> +EFI_STATUS
>>>>> +(EFIAPI *NON_DISCOVERABLE_DEVICE_INIT) (
>>>>> +  IN  NON_DISCOVERABLE_DEVICE       *This
>>>>> +  );
>>>>> +
>>>>> +struct _NON_DISCOVERABLE_DEVICE {
>>>>> +  //
>>>>> +  // The type of device
>>>>> +  //
>>>>> +  NON_DISCOVERABLE_DEVICE_TYPE        Type;
>>> 2. Can you use PCI class code to replace the enum type here?
>>> e.g.: UINT8 Class; UINT8 SubClass; UINT8 Programming Interface; The
>>> enum type can be defined in the helper library.
>>> In this way, we make the protocol definition stable enough.
>>> 
>> 
>> Again, i think this is a bad idea. This is meant to describe the /device/, not the
>> edk2 implementation detail that some standardized host controller
>> interfaces were implemented in a way that requires pci. It would also make it
>> impossible to describe AMBA devices
> Does AMBA  stand for Advanced Microcontroller Bus Architecture?
> I have no idea about the AMBA.
> Can you explain more why it's impossible to describe AMBA devices?
> 

Amba devices are identifiable but not discoverable. If you know the base address, you know where the id registers are because they are always at the same register offset

Thanks,
Ard.

>> 
>>>>> +  //
>>>>> +  // Whether this device is DMA coherent
>>>>> +  //
>>>>> +  NON_DISCOVERABLE_DEVICE_DMA_TYPE    DmaType;
>>>>> +  //
>>>>> +  // Initialization function for the device
>>>>> +  //
>>>>> +  NON_DISCOVERABLE_DEVICE_INIT        Initialize;
>>>>> +  //
>>>>> +  // The MMIO and I/O regions owned by the device
>>>>> +  //
>>>>> +  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Resources;
>>>>> +};
>>>>> +
>>>>> +extern EFI_GUID gEdkiiNonDiscoverableDeviceProtocolGuid;
>>>>> +
>>>>> +#endif
>>>>> diff --git a/MdeModulePkg/MdeModulePkg.dec
>>>>> b/MdeModulePkg/MdeModulePkg.dec index
>> 74b870051c67..6b956fc80c93
>>>>> 100644
>>>>> --- a/MdeModulePkg/MdeModulePkg.dec
>>>>> +++ b/MdeModulePkg/MdeModulePkg.dec
>>>>> @@ -505,6 +505,9 @@ [Protocols]
>>>>>  #  Include/Protocol/Ps2Policy.h
>>>>>  gEfiPs2PolicyProtocolGuid = { 0x4DF19259, 0xDC71, 0x4D46, { 0xBE,
>>>>> 0xF1, 0x35, 0x7B, 0xB5, 0x78, 0xC4, 0x18 } }
>>>>> 
>>>>> +  ## Include/Protocol/NonDiscoverableDevice.h
>>>>> +  gEdkiiNonDiscoverableDeviceProtocolGuid = { 0x0d51905b, 0xb77e,
>>>>> + 0x452a, {0xa2, 0xc0, 0xec, 0xa0, 0xcc, 0x8d, 0x51, 0x4a } }
>>>>> +
>>>>> #
>>>>> # [Error.gEfiMdeModulePkgTokenSpaceGuid]
>>>>> #   0x80000001 | Invalid value provided.
>>>>> --
>>>>> 2.7.4
>>>>> 
>>>> _______________________________________________
>>>> edk2-devel mailing list
>>>> edk2-devel@lists.01.org
>>>> https://lists.01.org/mailman/listinfo/edk2-devel
>> _______________________________________________
>> edk2-devel mailing list
>> edk2-devel@lists.01.org
>> https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol
  2016-11-17 10:43           ` Ard Biesheuvel
@ 2016-11-18  2:11             ` Ni, Ruiyu
  2016-11-18  4:59               ` Ard Biesheuvel
  0 siblings, 1 reply; 27+ messages in thread
From: Ni, Ruiyu @ 2016-11-18  2:11 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Kinney, Michael D, edk2-devel@lists.01.org, Gao, Liming,
	afish@apple.com, Leif Lindholm



Regards,
Ray

>-----Original Message-----
>From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org]
>Sent: Thursday, November 17, 2016 6:43 PM
>To: Ni, Ruiyu <ruiyu.ni@intel.com>
>Cc: Kinney, Michael D <michael.d.kinney@intel.com>; edk2-devel@lists.01.org; Gao, Liming <liming.gao@intel.com>;
>afish@apple.com; Leif Lindholm <leif.lindholm@linaro.org>
>Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol
>
>
>> On 17 Nov 2016, at 08:52, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>>
>>
>>
>> Thanks/Ray
>>
>>> -----Original Message-----
>>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
>>> Ard Biesheuvel
>>> Sent: Thursday, November 17, 2016 2:07 PM
>>> To: Ni, Ruiyu <ruiyu.ni@intel.com>
>>> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; edk2-
>>> devel@lists.01.org; Gao, Liming <liming.gao@intel.com>; afish@apple.com;
>>> Leif Lindholm <leif.lindholm@linaro.org>
>>> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-
>>> discoverable device protocol
>>>
>>>
>>>
>>>> On 17 Nov 2016, at 02:53, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>>>>
>>>> Ard,
>>>> I have two comments in below.
>>>>
>>>> Thanks/Ray
>>>>
>>>>> -----Original Message-----
>>>>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf
>>>>> Of Leif Lindholm
>>>>> Sent: Thursday, November 17, 2016 1:49 AM
>>>>> To: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>>>> Cc: Ni, Ruiyu <ruiyu.ni@intel.com>; edk2-devel@lists.01.org;
>>>>> afish@apple.com; Gao, Liming <liming.gao@intel.com>; Kinney, Michael
>>>>> D <michael.d.kinney@intel.com>
>>>>> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-
>>>>> discoverable device protocol
>>>>>
>>>>>> On Wed, Nov 16, 2016 at 04:59:27PM +0000, Ard Biesheuvel wrote:
>>>>>> Introduce a protocol that can be exposed by a platform for devices
>>>>>> that are not discoverable, usually because they are wired straight
>>>>>> to the memory bus rather than to an enumerable bus like PCI or USB.
>>>>>>
>>>>>> Contributed-under: TianoCore Contribution Agreement 1.0
>>>>>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>>>>> ---
>>>>>> MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h | 90
>>>>> ++++++++++++++++++++
>>>>>> MdeModulePkg/MdeModulePkg.dec                         |  3 +
>>>>>> 2 files changed, 93 insertions(+)
>>>>>>
>>>>>> diff --git a/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>>> b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>>> new file mode 100644
>>>>>> index 000000000000..47ed841b407b
>>>>>> --- /dev/null
>>>>>> +++ b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>>> @@ -0,0 +1,90 @@
>>>>>> +/** @file
>>>>>> +  Protocol to describe devices that are not on a discoverable bus
>>>>>> +
>>>>>> +  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_DEVICE_H__ #define
>>>>>> +__NON_DISCOVERABLE_DEVICE_H__
>>>>>> +
>>>>>> +#include <IndustryStandard/Acpi.h>
>>>>>> +
>>>>>> +#define EDKII_NON_DISCOVERABLE_DEVICE_PROTOCOL_GUID \
>>>>>> +  { 0x0d51905b, 0xb77e, 0x452a, {0xa2, 0xc0, 0xec, 0xa0, 0xcc,
>>>>>> +0x8d, 0x51, 0x4a } }
>>>>
>>>> 1. Can you add "PCI" keyword into the protocol name?
>>>> e.g.: EDKII_NON_DISCOVERABLE_PCI_DEVICE_PROTOCOL_GUID
>>>>
>>>
>>> No. This protocol does not describe pci devices, and it is a peculiarity of the
>>> edk2 driver stack that some non-pci devices can only be driven by pci drivers.
>>>
>>> in other words, pci is part of the /driver/ side, and it is perfectly possible for,
>>> e.g., a non-discoverable ahci device to be driven by a different non-pci driver
>>> in the future.
>>>
>>
>> I see. So some types of devices are handled by the current
>> NonDiscoveablePciDevice driver, and some other types of devices may be
>> handled by a future NonDiscoverableXXXDevice driver.
>> Now since the AHCI type is already handled by the NonDiscoverablePciDevice
>> driver, when there is a new NonDiscoverableXXXDevice driver, how can the two
>> know whether it should manage the AHCI type device or not?
>
>Good question. But how does the UEFI driver model deal with that? What happens if i have two drivers that both support the
>Ahci Pci class codes?
PCI CFG header contains VendorID/DeviceID fields which can be used to distinguish
them.

>
>> Besides since now all the EDKII Host Controller drivers are based on
>> PciIo, it implicitly requires all the low layer needs to produce PciIo interface
>> in order to re-use the EDKII Host Controller drivers.
>>
>
>Yes, that is the whole point of these patches. My preferred solution would be to split the ?hci drivers from pci i/o, by
>introducing intermediate protocols, but we both know that is unlikely to be accepted
>
>>>>>> +
>>>>>> +//
>>>>>> +// Protocol interface structure
>>>>>> +//
>>>>>> +typedef struct _NON_DISCOVERABLE_DEVICE
>>>>> NON_DISCOVERABLE_DEVICE;
>>>>>> +
>>>>>> +//
>>>>>> +// Data Types
>>>>>> +//
>>>>>> +typedef enum {
>>>>>> +  NonDiscoverableDeviceTypeAmba,
>>>>>> +  NonDiscoverableDeviceTypeOhci,
>>>>>> +  NonDiscoverableDeviceTypeUhci,
>>>>>> +  NonDiscoverableDeviceTypeEhci,
>>>>>> +  NonDiscoverableDeviceTypeXhci,
>>>>>> +  NonDiscoverableDeviceTypeAhci,
>>>>>> +  NonDiscoverableDeviceTypeSdhci,
>>>>>> +  NonDiscoverableDeviceTypeUfs,
>>>>>> +  NonDiscoverableDeviceTypeNvme,
>>>>
>>>>
>>>>>
>>>>> Just one OCD comment/question left:
>>>>> Can we keep these sorted alphabetically?
>>>>> (Also in switch statements in later patches?)
>>>>>
>>>>> Other than that, I'm (very) happy with this series.
>>>>>
>>>>> /
>>>>>   Leif
>>>>>
>>>>>> +  NonDiscoverableDeviceTypeMax,
>>>>>> +} NON_DISCOVERABLE_DEVICE_TYPE;
>>>>>> +
>>>>>> +typedef enum {
>>>>>> +  NonDiscoverableDeviceDmaTypeCoherent,
>>>>>> +  NonDiscoverableDeviceDmaTypeNonCoherent,
>>>>>> +  NonDiscoverableDeviceDmaTypeMax,
>>>>>> +} NON_DISCOVERABLE_DEVICE_DMA_TYPE;
>>>>>> +
>>>>>> +//
>>>>>> +// Function Prototypes
>>>>>> +//
>>>>>> +
>>>>>> +/**
>>>>>> +  Perform device specific initialization before the device is
>>>>>> +started
>>>>>> +
>>>>>> +  @param  This          The non-discoverable device protocol pointer
>>>>>> +
>>>>>> +  @retval EFI_SUCCESS   Initialization successful, the device may be
>>> used
>>>>>> +  @retval Other         Initialization failed, device should not be started
>>>>>> +**/
>>>>>> +typedef
>>>>>> +EFI_STATUS
>>>>>> +(EFIAPI *NON_DISCOVERABLE_DEVICE_INIT) (
>>>>>> +  IN  NON_DISCOVERABLE_DEVICE       *This
>>>>>> +  );
>>>>>> +
>>>>>> +struct _NON_DISCOVERABLE_DEVICE {
>>>>>> +  //
>>>>>> +  // The type of device
>>>>>> +  //
>>>>>> +  NON_DISCOVERABLE_DEVICE_TYPE        Type;
>>>> 2. Can you use PCI class code to replace the enum type here?
>>>> e.g.: UINT8 Class; UINT8 SubClass; UINT8 Programming Interface; The
>>>> enum type can be defined in the helper library.
>>>> In this way, we make the protocol definition stable enough.
>>>>
>>>
>>> Again, i think this is a bad idea. This is meant to describe the /device/, not the
>>> edk2 implementation detail that some standardized host controller
>>> interfaces were implemented in a way that requires pci. It would also make it
>>> impossible to describe AMBA devices
>> Does AMBA  stand for Advanced Microcontroller Bus Architecture?
>> I have no idea about the AMBA.
>> Can you explain more why it's impossible to describe AMBA devices?
>>
>
>Amba devices are identifiable but not discoverable. If you know the base address, you know where the id registers are
>because they are always at the same register offset
>
>Thanks,
>Ard.
>
>>>
>>>>>> +  //
>>>>>> +  // Whether this device is DMA coherent
>>>>>> +  //
>>>>>> +  NON_DISCOVERABLE_DEVICE_DMA_TYPE    DmaType;
>>>>>> +  //
>>>>>> +  // Initialization function for the device
>>>>>> +  //
>>>>>> +  NON_DISCOVERABLE_DEVICE_INIT        Initialize;
>>>>>> +  //
>>>>>> +  // The MMIO and I/O regions owned by the device
>>>>>> +  //
>>>>>> +  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Resources;
>>>>>> +};
>>>>>> +
>>>>>> +extern EFI_GUID gEdkiiNonDiscoverableDeviceProtocolGuid;
>>>>>> +
>>>>>> +#endif
>>>>>> diff --git a/MdeModulePkg/MdeModulePkg.dec
>>>>>> b/MdeModulePkg/MdeModulePkg.dec index
>>> 74b870051c67..6b956fc80c93
>>>>>> 100644
>>>>>> --- a/MdeModulePkg/MdeModulePkg.dec
>>>>>> +++ b/MdeModulePkg/MdeModulePkg.dec
>>>>>> @@ -505,6 +505,9 @@ [Protocols]
>>>>>>  #  Include/Protocol/Ps2Policy.h
>>>>>>  gEfiPs2PolicyProtocolGuid = { 0x4DF19259, 0xDC71, 0x4D46, { 0xBE,
>>>>>> 0xF1, 0x35, 0x7B, 0xB5, 0x78, 0xC4, 0x18 } }
>>>>>>
>>>>>> +  ## Include/Protocol/NonDiscoverableDevice.h
>>>>>> +  gEdkiiNonDiscoverableDeviceProtocolGuid = { 0x0d51905b, 0xb77e,
>>>>>> + 0x452a, {0xa2, 0xc0, 0xec, 0xa0, 0xcc, 0x8d, 0x51, 0x4a } }
>>>>>> +
>>>>>> #
>>>>>> # [Error.gEfiMdeModulePkgTokenSpaceGuid]
>>>>>> #   0x80000001 | Invalid value provided.
>>>>>> --
>>>>>> 2.7.4
>>>>>>
>>>>> _______________________________________________
>>>>> edk2-devel mailing list
>>>>> edk2-devel@lists.01.org
>>>>> https://lists.01.org/mailman/listinfo/edk2-devel
>>> _______________________________________________
>>> edk2-devel mailing list
>>> edk2-devel@lists.01.org
>>> https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol
  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:13                 ` Ni, Ruiyu
  0 siblings, 2 replies; 27+ messages in thread
From: Ard Biesheuvel @ 2016-11-18  4:59 UTC (permalink / raw)
  To: Ni, Ruiyu
  Cc: Kinney, Michael D, edk2-devel@lists.01.org, Leif Lindholm,
	afish@apple.com, Gao, Liming

On 18 November 2016 at 02:11, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>
>
> Regards,
> Ray
>
>>-----Original Message-----
>>From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org]
>>Sent: Thursday, November 17, 2016 6:43 PM
>>To: Ni, Ruiyu <ruiyu.ni@intel.com>
>>Cc: Kinney, Michael D <michael.d.kinney@intel.com>; edk2-devel@lists.01.org; Gao, Liming <liming.gao@intel.com>;
>>afish@apple.com; Leif Lindholm <leif.lindholm@linaro.org>
>>Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol
>>
>>
>>> On 17 Nov 2016, at 08:52, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>>>
>>>
>>>
>>> Thanks/Ray
>>>
>>>> -----Original Message-----
>>>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
>>>> Ard Biesheuvel
>>>> Sent: Thursday, November 17, 2016 2:07 PM
>>>> To: Ni, Ruiyu <ruiyu.ni@intel.com>
>>>> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; edk2-
>>>> devel@lists.01.org; Gao, Liming <liming.gao@intel.com>; afish@apple.com;
>>>> Leif Lindholm <leif.lindholm@linaro.org>
>>>> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-
>>>> discoverable device protocol
>>>>
>>>>
>>>>
>>>>> On 17 Nov 2016, at 02:53, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>>>>>
>>>>> Ard,
>>>>> I have two comments in below.
>>>>>
>>>>> Thanks/Ray
>>>>>
>>>>>> -----Original Message-----
>>>>>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf
>>>>>> Of Leif Lindholm
>>>>>> Sent: Thursday, November 17, 2016 1:49 AM
>>>>>> To: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>>>>> Cc: Ni, Ruiyu <ruiyu.ni@intel.com>; edk2-devel@lists.01.org;
>>>>>> afish@apple.com; Gao, Liming <liming.gao@intel.com>; Kinney, Michael
>>>>>> D <michael.d.kinney@intel.com>
>>>>>> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-
>>>>>> discoverable device protocol
>>>>>>
>>>>>>> On Wed, Nov 16, 2016 at 04:59:27PM +0000, Ard Biesheuvel wrote:
>>>>>>> Introduce a protocol that can be exposed by a platform for devices
>>>>>>> that are not discoverable, usually because they are wired straight
>>>>>>> to the memory bus rather than to an enumerable bus like PCI or USB.
>>>>>>>
>>>>>>> Contributed-under: TianoCore Contribution Agreement 1.0
>>>>>>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>>>>>> ---
>>>>>>> MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h | 90
>>>>>> ++++++++++++++++++++
>>>>>>> MdeModulePkg/MdeModulePkg.dec                         |  3 +
>>>>>>> 2 files changed, 93 insertions(+)
>>>>>>>
>>>>>>> diff --git a/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>>>> b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>>>> new file mode 100644
>>>>>>> index 000000000000..47ed841b407b
>>>>>>> --- /dev/null
>>>>>>> +++ b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>>>> @@ -0,0 +1,90 @@
>>>>>>> +/** @file
>>>>>>> +  Protocol to describe devices that are not on a discoverable bus
>>>>>>> +
>>>>>>> +  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_DEVICE_H__ #define
>>>>>>> +__NON_DISCOVERABLE_DEVICE_H__
>>>>>>> +
>>>>>>> +#include <IndustryStandard/Acpi.h>
>>>>>>> +
>>>>>>> +#define EDKII_NON_DISCOVERABLE_DEVICE_PROTOCOL_GUID \
>>>>>>> +  { 0x0d51905b, 0xb77e, 0x452a, {0xa2, 0xc0, 0xec, 0xa0, 0xcc,
>>>>>>> +0x8d, 0x51, 0x4a } }
>>>>>
>>>>> 1. Can you add "PCI" keyword into the protocol name?
>>>>> e.g.: EDKII_NON_DISCOVERABLE_PCI_DEVICE_PROTOCOL_GUID
>>>>>
>>>>
>>>> No. This protocol does not describe pci devices, and it is a peculiarity of the
>>>> edk2 driver stack that some non-pci devices can only be driven by pci drivers.
>>>>
>>>> in other words, pci is part of the /driver/ side, and it is perfectly possible for,
>>>> e.g., a non-discoverable ahci device to be driven by a different non-pci driver
>>>> in the future.
>>>>
>>>
>>> I see. So some types of devices are handled by the current
>>> NonDiscoveablePciDevice driver, and some other types of devices may be
>>> handled by a future NonDiscoverableXXXDevice driver.
>>> Now since the AHCI type is already handled by the NonDiscoverablePciDevice
>>> driver, when there is a new NonDiscoverableXXXDevice driver, how can the two
>>> know whether it should manage the AHCI type device or not?
>>
>>Good question. But how does the UEFI driver model deal with that? What happens if i have two drivers that both support the
>>Ahci Pci class codes?
> PCI CFG header contains VendorID/DeviceID fields which can be used to distinguish
> them.
>

No, that is not what I mean.

Your question is how we should deal with multiple drivers that
support, for instance, the AHCI non-discoverable device type. My
answer is that this is not any different from a platform configuration
that has more than one PCI I/O based driver that supports the AHCI PCI
class codes. The UEFI driver model has priority rules and protocols to
decide which driver gets precedence. I don't see how it should be any
different here.

Thanks,
Ard.


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol
  2016-11-18  4:59               ` Ard Biesheuvel
@ 2016-11-18  5:24                 ` Tian, Feng
  2016-11-18  6:57                   ` Ard Biesheuvel
  2016-11-18  6:13                 ` Ni, Ruiyu
  1 sibling, 1 reply; 27+ messages in thread
From: Tian, Feng @ 2016-11-18  5:24 UTC (permalink / raw)
  To: Ard Biesheuvel, Ni, Ruiyu
  Cc: Kinney, Michael D, edk2-devel@lists.01.org, Gao, Liming,
	afish@apple.com, Leif Lindholm, Tian, Feng

Ard,

I have another question.

Is it the only way to specify device type in below enum? Looks like it will be changed often. Is it possible to make use of DevicePath node? Of course, I have no good idea to handle AMBA controller...

+//
+// Data Types
+//
+typedef enum {
+  NonDiscoverableDeviceTypeAmba,
+  NonDiscoverableDeviceTypeOhci,
+  NonDiscoverableDeviceTypeUhci,
+  NonDiscoverableDeviceTypeEhci,
+  NonDiscoverableDeviceTypeXhci,
+  NonDiscoverableDeviceTypeAhci,
+  NonDiscoverableDeviceTypeSdhci,
+  NonDiscoverableDeviceTypeUfs,
+  NonDiscoverableDeviceTypeNvme,
+  NonDiscoverableDeviceTypeMax,
+} NON_DISCOVERABLE_DEVICE_TYPE;

Thanks
Feng

-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Ard Biesheuvel
Sent: Friday, November 18, 2016 12:59 PM
To: Ni, Ruiyu <ruiyu.ni@intel.com>
Cc: Kinney, Michael D <michael.d.kinney@intel.com>; edk2-devel@lists.01.org; Gao, Liming <liming.gao@intel.com>; afish@apple.com; Leif Lindholm <leif.lindholm@linaro.org>
Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol

On 18 November 2016 at 02:11, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>
>
> Regards,
> Ray
>
>>-----Original Message-----
>>From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org]
>>Sent: Thursday, November 17, 2016 6:43 PM
>>To: Ni, Ruiyu <ruiyu.ni@intel.com>
>>Cc: Kinney, Michael D <michael.d.kinney@intel.com>; 
>>edk2-devel@lists.01.org; Gao, Liming <liming.gao@intel.com>; 
>>afish@apple.com; Leif Lindholm <leif.lindholm@linaro.org>
>>Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce 
>>non-discoverable device protocol
>>
>>
>>> On 17 Nov 2016, at 08:52, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>>>
>>>
>>>
>>> Thanks/Ray
>>>
>>>> -----Original Message-----
>>>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf 
>>>> Of Ard Biesheuvel
>>>> Sent: Thursday, November 17, 2016 2:07 PM
>>>> To: Ni, Ruiyu <ruiyu.ni@intel.com>
>>>> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; edk2- 
>>>> devel@lists.01.org; Gao, Liming <liming.gao@intel.com>; 
>>>> afish@apple.com; Leif Lindholm <leif.lindholm@linaro.org>
>>>> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non- 
>>>> discoverable device protocol
>>>>
>>>>
>>>>
>>>>> On 17 Nov 2016, at 02:53, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>>>>>
>>>>> Ard,
>>>>> I have two comments in below.
>>>>>
>>>>> Thanks/Ray
>>>>>
>>>>>> -----Original Message-----
>>>>>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On 
>>>>>> Behalf Of Leif Lindholm
>>>>>> Sent: Thursday, November 17, 2016 1:49 AM
>>>>>> To: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>>>>> Cc: Ni, Ruiyu <ruiyu.ni@intel.com>; edk2-devel@lists.01.org; 
>>>>>> afish@apple.com; Gao, Liming <liming.gao@intel.com>; Kinney, 
>>>>>> Michael D <michael.d.kinney@intel.com>
>>>>>> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non- 
>>>>>> discoverable device protocol
>>>>>>
>>>>>>> On Wed, Nov 16, 2016 at 04:59:27PM +0000, Ard Biesheuvel wrote:
>>>>>>> Introduce a protocol that can be exposed by a platform for 
>>>>>>> devices that are not discoverable, usually because they are 
>>>>>>> wired straight to the memory bus rather than to an enumerable bus like PCI or USB.
>>>>>>>
>>>>>>> Contributed-under: TianoCore Contribution Agreement 1.0
>>>>>>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>>>>>> ---
>>>>>>> MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h | 90
>>>>>> ++++++++++++++++++++
>>>>>>> MdeModulePkg/MdeModulePkg.dec                         |  3 +
>>>>>>> 2 files changed, 93 insertions(+)
>>>>>>>
>>>>>>> diff --git 
>>>>>>> a/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>>>> b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>>>> new file mode 100644
>>>>>>> index 000000000000..47ed841b407b
>>>>>>> --- /dev/null
>>>>>>> +++ b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>>>> @@ -0,0 +1,90 @@
>>>>>>> +/** @file
>>>>>>> +  Protocol to describe devices that are not on a discoverable 
>>>>>>> +bus
>>>>>>> +
>>>>>>> +  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_DEVICE_H__ #define 
>>>>>>> +__NON_DISCOVERABLE_DEVICE_H__
>>>>>>> +
>>>>>>> +#include <IndustryStandard/Acpi.h>
>>>>>>> +
>>>>>>> +#define EDKII_NON_DISCOVERABLE_DEVICE_PROTOCOL_GUID \
>>>>>>> +  { 0x0d51905b, 0xb77e, 0x452a, {0xa2, 0xc0, 0xec, 0xa0, 0xcc, 
>>>>>>> +0x8d, 0x51, 0x4a } }
>>>>>
>>>>> 1. Can you add "PCI" keyword into the protocol name?
>>>>> e.g.: EDKII_NON_DISCOVERABLE_PCI_DEVICE_PROTOCOL_GUID
>>>>>
>>>>
>>>> No. This protocol does not describe pci devices, and it is a 
>>>> peculiarity of the
>>>> edk2 driver stack that some non-pci devices can only be driven by pci drivers.
>>>>
>>>> in other words, pci is part of the /driver/ side, and it is 
>>>> perfectly possible for, e.g., a non-discoverable ahci device to be 
>>>> driven by a different non-pci driver in the future.
>>>>
>>>
>>> I see. So some types of devices are handled by the current 
>>> NonDiscoveablePciDevice driver, and some other types of devices may 
>>> be handled by a future NonDiscoverableXXXDevice driver.
>>> Now since the AHCI type is already handled by the 
>>> NonDiscoverablePciDevice driver, when there is a new 
>>> NonDiscoverableXXXDevice driver, how can the two know whether it should manage the AHCI type device or not?
>>
>>Good question. But how does the UEFI driver model deal with that? What 
>>happens if i have two drivers that both support the Ahci Pci class codes?
> PCI CFG header contains VendorID/DeviceID fields which can be used to 
> distinguish them.
>

No, that is not what I mean.

Your question is how we should deal with multiple drivers that support, for instance, the AHCI non-discoverable device type. My answer is that this is not any different from a platform configuration that has more than one PCI I/O based driver that supports the AHCI PCI class codes. The UEFI driver model has priority rules and protocols to decide which driver gets precedence. I don't see how it should be any different here.

Thanks,
Ard.
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol
  2016-11-18  4:59               ` Ard Biesheuvel
  2016-11-18  5:24                 ` Tian, Feng
@ 2016-11-18  6:13                 ` Ni, Ruiyu
  2016-11-18  7:04                   ` Ard Biesheuvel
  1 sibling, 1 reply; 27+ messages in thread
From: Ni, Ruiyu @ 2016-11-18  6:13 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Kinney, Michael D, edk2-devel@lists.01.org, Gao, Liming,
	afish@apple.com, Leif Lindholm



Regards,
Ray

>-----Original Message-----
>From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Ard Biesheuvel
>Sent: Friday, November 18, 2016 12:59 PM
>To: Ni, Ruiyu <ruiyu.ni@intel.com>
>Cc: Kinney, Michael D <michael.d.kinney@intel.com>; edk2-devel@lists.01.org; Gao, Liming <liming.gao@intel.com>;
>afish@apple.com; Leif Lindholm <leif.lindholm@linaro.org>
>Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol
>
>On 18 November 2016 at 02:11, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>>
>>
>> Regards,
>> Ray
>>
>>>-----Original Message-----
>>>From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org]
>>>Sent: Thursday, November 17, 2016 6:43 PM
>>>To: Ni, Ruiyu <ruiyu.ni@intel.com>
>>>Cc: Kinney, Michael D <michael.d.kinney@intel.com>; edk2-devel@lists.01.org; Gao, Liming <liming.gao@intel.com>;
>>>afish@apple.com; Leif Lindholm <leif.lindholm@linaro.org>
>>>Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol
>>>
>>>
>>>> On 17 Nov 2016, at 08:52, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>>>>
>>>>
>>>>
>>>> Thanks/Ray
>>>>
>>>>> -----Original Message-----
>>>>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
>>>>> Ard Biesheuvel
>>>>> Sent: Thursday, November 17, 2016 2:07 PM
>>>>> To: Ni, Ruiyu <ruiyu.ni@intel.com>
>>>>> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; edk2-
>>>>> devel@lists.01.org; Gao, Liming <liming.gao@intel.com>; afish@apple.com;
>>>>> Leif Lindholm <leif.lindholm@linaro.org>
>>>>> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-
>>>>> discoverable device protocol
>>>>>
>>>>>
>>>>>
>>>>>> On 17 Nov 2016, at 02:53, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>>>>>>
>>>>>> Ard,
>>>>>> I have two comments in below.
>>>>>>
>>>>>> Thanks/Ray
>>>>>>
>>>>>>> -----Original Message-----
>>>>>>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf
>>>>>>> Of Leif Lindholm
>>>>>>> Sent: Thursday, November 17, 2016 1:49 AM
>>>>>>> To: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>>>>>> Cc: Ni, Ruiyu <ruiyu.ni@intel.com>; edk2-devel@lists.01.org;
>>>>>>> afish@apple.com; Gao, Liming <liming.gao@intel.com>; Kinney, Michael
>>>>>>> D <michael.d.kinney@intel.com>
>>>>>>> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-
>>>>>>> discoverable device protocol
>>>>>>>
>>>>>>>> On Wed, Nov 16, 2016 at 04:59:27PM +0000, Ard Biesheuvel wrote:
>>>>>>>> Introduce a protocol that can be exposed by a platform for devices
>>>>>>>> that are not discoverable, usually because they are wired straight
>>>>>>>> to the memory bus rather than to an enumerable bus like PCI or USB.
>>>>>>>>
>>>>>>>> Contributed-under: TianoCore Contribution Agreement 1.0
>>>>>>>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>>>>>>> ---
>>>>>>>> MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h | 90
>>>>>>> ++++++++++++++++++++
>>>>>>>> MdeModulePkg/MdeModulePkg.dec                         |  3 +
>>>>>>>> 2 files changed, 93 insertions(+)
>>>>>>>>
>>>>>>>> diff --git a/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>>>>> b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>>>>> new file mode 100644
>>>>>>>> index 000000000000..47ed841b407b
>>>>>>>> --- /dev/null
>>>>>>>> +++ b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>>>>> @@ -0,0 +1,90 @@
>>>>>>>> +/** @file
>>>>>>>> +  Protocol to describe devices that are not on a discoverable bus
>>>>>>>> +
>>>>>>>> +  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_DEVICE_H__ #define
>>>>>>>> +__NON_DISCOVERABLE_DEVICE_H__
>>>>>>>> +
>>>>>>>> +#include <IndustryStandard/Acpi.h>
>>>>>>>> +
>>>>>>>> +#define EDKII_NON_DISCOVERABLE_DEVICE_PROTOCOL_GUID \
>>>>>>>> +  { 0x0d51905b, 0xb77e, 0x452a, {0xa2, 0xc0, 0xec, 0xa0, 0xcc,
>>>>>>>> +0x8d, 0x51, 0x4a } }
>>>>>>
>>>>>> 1. Can you add "PCI" keyword into the protocol name?
>>>>>> e.g.: EDKII_NON_DISCOVERABLE_PCI_DEVICE_PROTOCOL_GUID
>>>>>>
>>>>>
>>>>> No. This protocol does not describe pci devices, and it is a peculiarity of the
>>>>> edk2 driver stack that some non-pci devices can only be driven by pci drivers.
>>>>>
>>>>> in other words, pci is part of the /driver/ side, and it is perfectly possible for,
>>>>> e.g., a non-discoverable ahci device to be driven by a different non-pci driver
>>>>> in the future.
>>>>>
>>>>
>>>> I see. So some types of devices are handled by the current
>>>> NonDiscoveablePciDevice driver, and some other types of devices may be
>>>> handled by a future NonDiscoverableXXXDevice driver.
>>>> Now since the AHCI type is already handled by the NonDiscoverablePciDevice
>>>> driver, when there is a new NonDiscoverableXXXDevice driver, how can the two
>>>> know whether it should manage the AHCI type device or not?
>>>
>>>Good question. But how does the UEFI driver model deal with that? What happens if i have two drivers that both support
>the
>>>Ahci Pci class codes?
>> PCI CFG header contains VendorID/DeviceID fields which can be used to distinguish
>> them.
>>
>
>No, that is not what I mean.
>
>Your question is how we should deal with multiple drivers that
>support, for instance, the AHCI non-discoverable device type. My
>answer is that this is not any different from a platform configuration
>that has more than one PCI I/O based driver that supports the AHCI PCI
>class codes. The UEFI driver model has priority rules and protocols to
>decide which driver gets precedence. I don't see how it should be any
>different here.

I see they are different. Based on PciIo, the *HCI drivers can query
additional information from PCI CFG header, instead of just using
the PCI class code.

But with the NonDiscoverableDevice protocol, there is no additional
information can help the *HCI drivers decide which to manage.

I don't see any practical negative point which prevents degrading
NonDiscoverableDevice protocol to NonDiscoverable*Pci*Protocol.
After all, as I said, all *HCI drivers are based on PciIo.

>
>Thanks,
>Ard.
>_______________________________________________
>edk2-devel mailing list
>edk2-devel@lists.01.org
>https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol
  2016-11-18  5:24                 ` Tian, Feng
@ 2016-11-18  6:57                   ` Ard Biesheuvel
  2016-11-18  8:39                     ` Tian, Feng
  0 siblings, 1 reply; 27+ messages in thread
From: Ard Biesheuvel @ 2016-11-18  6:57 UTC (permalink / raw)
  To: Tian, Feng
  Cc: Ni, Ruiyu, Kinney, Michael D, edk2-devel@lists.01.org,
	Gao, Liming, afish@apple.com, Leif Lindholm

On 18 November 2016 at 05:24, Tian, Feng <feng.tian@intel.com> wrote:
> Ard,
>
> I have another question.
>
> Is it the only way to specify device type in below enum? Looks like it will be changed often. Is it possible to make use of DevicePath node? Of course, I have no good idea to handle AMBA controller...
>

How would you use a device path node to do that? I think we will
always need a mapping somewhere in the code between numbers and
AHCI/EHCI/etc types, given that the device itself cannot be
interrogated to provide this information. If we can do the same with a
device path, I'm happy to investigate, but I will need some help
understanding how that would work

> +//
> +// Data Types
> +//
> +typedef enum {
> +  NonDiscoverableDeviceTypeAmba,
> +  NonDiscoverableDeviceTypeOhci,
> +  NonDiscoverableDeviceTypeUhci,
> +  NonDiscoverableDeviceTypeEhci,
> +  NonDiscoverableDeviceTypeXhci,
> +  NonDiscoverableDeviceTypeAhci,
> +  NonDiscoverableDeviceTypeSdhci,
> +  NonDiscoverableDeviceTypeUfs,
> +  NonDiscoverableDeviceTypeNvme,
> +  NonDiscoverableDeviceTypeMax,
> +} NON_DISCOVERABLE_DEVICE_TYPE;
>
> Thanks
> Feng
>
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Ard Biesheuvel
> Sent: Friday, November 18, 2016 12:59 PM
> To: Ni, Ruiyu <ruiyu.ni@intel.com>
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; edk2-devel@lists.01.org; Gao, Liming <liming.gao@intel.com>; afish@apple.com; Leif Lindholm <leif.lindholm@linaro.org>
> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol
>
> On 18 November 2016 at 02:11, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>>
>>
>> Regards,
>> Ray
>>
>>>-----Original Message-----
>>>From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org]
>>>Sent: Thursday, November 17, 2016 6:43 PM
>>>To: Ni, Ruiyu <ruiyu.ni@intel.com>
>>>Cc: Kinney, Michael D <michael.d.kinney@intel.com>;
>>>edk2-devel@lists.01.org; Gao, Liming <liming.gao@intel.com>;
>>>afish@apple.com; Leif Lindholm <leif.lindholm@linaro.org>
>>>Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce
>>>non-discoverable device protocol
>>>
>>>
>>>> On 17 Nov 2016, at 08:52, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>>>>
>>>>
>>>>
>>>> Thanks/Ray
>>>>
>>>>> -----Original Message-----
>>>>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf
>>>>> Of Ard Biesheuvel
>>>>> Sent: Thursday, November 17, 2016 2:07 PM
>>>>> To: Ni, Ruiyu <ruiyu.ni@intel.com>
>>>>> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; edk2-
>>>>> devel@lists.01.org; Gao, Liming <liming.gao@intel.com>;
>>>>> afish@apple.com; Leif Lindholm <leif.lindholm@linaro.org>
>>>>> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-
>>>>> discoverable device protocol
>>>>>
>>>>>
>>>>>
>>>>>> On 17 Nov 2016, at 02:53, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>>>>>>
>>>>>> Ard,
>>>>>> I have two comments in below.
>>>>>>
>>>>>> Thanks/Ray
>>>>>>
>>>>>>> -----Original Message-----
>>>>>>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On
>>>>>>> Behalf Of Leif Lindholm
>>>>>>> Sent: Thursday, November 17, 2016 1:49 AM
>>>>>>> To: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>>>>>> Cc: Ni, Ruiyu <ruiyu.ni@intel.com>; edk2-devel@lists.01.org;
>>>>>>> afish@apple.com; Gao, Liming <liming.gao@intel.com>; Kinney,
>>>>>>> Michael D <michael.d.kinney@intel.com>
>>>>>>> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-
>>>>>>> discoverable device protocol
>>>>>>>
>>>>>>>> On Wed, Nov 16, 2016 at 04:59:27PM +0000, Ard Biesheuvel wrote:
>>>>>>>> Introduce a protocol that can be exposed by a platform for
>>>>>>>> devices that are not discoverable, usually because they are
>>>>>>>> wired straight to the memory bus rather than to an enumerable bus like PCI or USB.
>>>>>>>>
>>>>>>>> Contributed-under: TianoCore Contribution Agreement 1.0
>>>>>>>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>>>>>>> ---
>>>>>>>> MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h | 90
>>>>>>> ++++++++++++++++++++
>>>>>>>> MdeModulePkg/MdeModulePkg.dec                         |  3 +
>>>>>>>> 2 files changed, 93 insertions(+)
>>>>>>>>
>>>>>>>> diff --git
>>>>>>>> a/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>>>>> b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>>>>> new file mode 100644
>>>>>>>> index 000000000000..47ed841b407b
>>>>>>>> --- /dev/null
>>>>>>>> +++ b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>>>>> @@ -0,0 +1,90 @@
>>>>>>>> +/** @file
>>>>>>>> +  Protocol to describe devices that are not on a discoverable
>>>>>>>> +bus
>>>>>>>> +
>>>>>>>> +  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_DEVICE_H__ #define
>>>>>>>> +__NON_DISCOVERABLE_DEVICE_H__
>>>>>>>> +
>>>>>>>> +#include <IndustryStandard/Acpi.h>
>>>>>>>> +
>>>>>>>> +#define EDKII_NON_DISCOVERABLE_DEVICE_PROTOCOL_GUID \
>>>>>>>> +  { 0x0d51905b, 0xb77e, 0x452a, {0xa2, 0xc0, 0xec, 0xa0, 0xcc,
>>>>>>>> +0x8d, 0x51, 0x4a } }
>>>>>>
>>>>>> 1. Can you add "PCI" keyword into the protocol name?
>>>>>> e.g.: EDKII_NON_DISCOVERABLE_PCI_DEVICE_PROTOCOL_GUID
>>>>>>
>>>>>
>>>>> No. This protocol does not describe pci devices, and it is a
>>>>> peculiarity of the
>>>>> edk2 driver stack that some non-pci devices can only be driven by pci drivers.
>>>>>
>>>>> in other words, pci is part of the /driver/ side, and it is
>>>>> perfectly possible for, e.g., a non-discoverable ahci device to be
>>>>> driven by a different non-pci driver in the future.
>>>>>
>>>>
>>>> I see. So some types of devices are handled by the current
>>>> NonDiscoveablePciDevice driver, and some other types of devices may
>>>> be handled by a future NonDiscoverableXXXDevice driver.
>>>> Now since the AHCI type is already handled by the
>>>> NonDiscoverablePciDevice driver, when there is a new
>>>> NonDiscoverableXXXDevice driver, how can the two know whether it should manage the AHCI type device or not?
>>>
>>>Good question. But how does the UEFI driver model deal with that? What
>>>happens if i have two drivers that both support the Ahci Pci class codes?
>> PCI CFG header contains VendorID/DeviceID fields which can be used to
>> distinguish them.
>>
>
> No, that is not what I mean.
>
> Your question is how we should deal with multiple drivers that support, for instance, the AHCI non-discoverable device type. My answer is that this is not any different from a platform configuration that has more than one PCI I/O based driver that supports the AHCI PCI class codes. The UEFI driver model has priority rules and protocols to decide which driver gets precedence. I don't see how it should be any different here.
>
> Thanks,
> Ard.
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol
  2016-11-18  6:13                 ` Ni, Ruiyu
@ 2016-11-18  7:04                   ` Ard Biesheuvel
  2016-11-18 13:39                     ` Ni, Ruiyu
  0 siblings, 1 reply; 27+ messages in thread
From: Ard Biesheuvel @ 2016-11-18  7:04 UTC (permalink / raw)
  To: Ni, Ruiyu
  Cc: Kinney, Michael D, edk2-devel@lists.01.org, Gao, Liming,
	afish@apple.com, Leif Lindholm

On 18 November 2016 at 06:13, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>
>
> Regards,
> Ray
>
>>-----Original Message-----
>>From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Ard Biesheuvel
>>Sent: Friday, November 18, 2016 12:59 PM
>>To: Ni, Ruiyu <ruiyu.ni@intel.com>
>>Cc: Kinney, Michael D <michael.d.kinney@intel.com>; edk2-devel@lists.01.org; Gao, Liming <liming.gao@intel.com>;
>>afish@apple.com; Leif Lindholm <leif.lindholm@linaro.org>
>>Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol
>>
>>On 18 November 2016 at 02:11, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>>>
>>>
>>> Regards,
>>> Ray
>>>
>>>>-----Original Message-----
>>>>From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org]
>>>>Sent: Thursday, November 17, 2016 6:43 PM
>>>>To: Ni, Ruiyu <ruiyu.ni@intel.com>
>>>>Cc: Kinney, Michael D <michael.d.kinney@intel.com>; edk2-devel@lists.01.org; Gao, Liming <liming.gao@intel.com>;
>>>>afish@apple.com; Leif Lindholm <leif.lindholm@linaro.org>
>>>>Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol
>>>>
>>>>
>>>>> On 17 Nov 2016, at 08:52, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>>>>>
>>>>>
>>>>>
>>>>> Thanks/Ray
>>>>>
>>>>>> -----Original Message-----
>>>>>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
>>>>>> Ard Biesheuvel
>>>>>> Sent: Thursday, November 17, 2016 2:07 PM
>>>>>> To: Ni, Ruiyu <ruiyu.ni@intel.com>
>>>>>> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; edk2-
>>>>>> devel@lists.01.org; Gao, Liming <liming.gao@intel.com>; afish@apple.com;
>>>>>> Leif Lindholm <leif.lindholm@linaro.org>
>>>>>> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-
>>>>>> discoverable device protocol
>>>>>>
>>>>>>
>>>>>>
>>>>>>> On 17 Nov 2016, at 02:53, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>>>>>>>
>>>>>>> Ard,
>>>>>>> I have two comments in below.
>>>>>>>
>>>>>>> Thanks/Ray
>>>>>>>
>>>>>>>> -----Original Message-----
>>>>>>>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf
>>>>>>>> Of Leif Lindholm
>>>>>>>> Sent: Thursday, November 17, 2016 1:49 AM
>>>>>>>> To: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>>>>>>> Cc: Ni, Ruiyu <ruiyu.ni@intel.com>; edk2-devel@lists.01.org;
>>>>>>>> afish@apple.com; Gao, Liming <liming.gao@intel.com>; Kinney, Michael
>>>>>>>> D <michael.d.kinney@intel.com>
>>>>>>>> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-
>>>>>>>> discoverable device protocol
>>>>>>>>
>>>>>>>>> On Wed, Nov 16, 2016 at 04:59:27PM +0000, Ard Biesheuvel wrote:
>>>>>>>>> Introduce a protocol that can be exposed by a platform for devices
>>>>>>>>> that are not discoverable, usually because they are wired straight
>>>>>>>>> to the memory bus rather than to an enumerable bus like PCI or USB.
>>>>>>>>>
>>>>>>>>> Contributed-under: TianoCore Contribution Agreement 1.0
>>>>>>>>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>>>>>>>> ---
>>>>>>>>> MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h | 90
>>>>>>>> ++++++++++++++++++++
>>>>>>>>> MdeModulePkg/MdeModulePkg.dec                         |  3 +
>>>>>>>>> 2 files changed, 93 insertions(+)
>>>>>>>>>
>>>>>>>>> diff --git a/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>>>>>> b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>>>>>> new file mode 100644
>>>>>>>>> index 000000000000..47ed841b407b
>>>>>>>>> --- /dev/null
>>>>>>>>> +++ b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>>>>>> @@ -0,0 +1,90 @@
>>>>>>>>> +/** @file
>>>>>>>>> +  Protocol to describe devices that are not on a discoverable bus
>>>>>>>>> +
>>>>>>>>> +  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_DEVICE_H__ #define
>>>>>>>>> +__NON_DISCOVERABLE_DEVICE_H__
>>>>>>>>> +
>>>>>>>>> +#include <IndustryStandard/Acpi.h>
>>>>>>>>> +
>>>>>>>>> +#define EDKII_NON_DISCOVERABLE_DEVICE_PROTOCOL_GUID \
>>>>>>>>> +  { 0x0d51905b, 0xb77e, 0x452a, {0xa2, 0xc0, 0xec, 0xa0, 0xcc,
>>>>>>>>> +0x8d, 0x51, 0x4a } }
>>>>>>>
>>>>>>> 1. Can you add "PCI" keyword into the protocol name?
>>>>>>> e.g.: EDKII_NON_DISCOVERABLE_PCI_DEVICE_PROTOCOL_GUID
>>>>>>>
>>>>>>
>>>>>> No. This protocol does not describe pci devices, and it is a peculiarity of the
>>>>>> edk2 driver stack that some non-pci devices can only be driven by pci drivers.
>>>>>>
>>>>>> in other words, pci is part of the /driver/ side, and it is perfectly possible for,
>>>>>> e.g., a non-discoverable ahci device to be driven by a different non-pci driver
>>>>>> in the future.
>>>>>>
>>>>>
>>>>> I see. So some types of devices are handled by the current
>>>>> NonDiscoveablePciDevice driver, and some other types of devices may be
>>>>> handled by a future NonDiscoverableXXXDevice driver.
>>>>> Now since the AHCI type is already handled by the NonDiscoverablePciDevice
>>>>> driver, when there is a new NonDiscoverableXXXDevice driver, how can the two
>>>>> know whether it should manage the AHCI type device or not?
>>>>
>>>>Good question. But how does the UEFI driver model deal with that? What happens if i have two drivers that both support
>>the
>>>>Ahci Pci class codes?
>>> PCI CFG header contains VendorID/DeviceID fields which can be used to distinguish
>>> them.
>>>
>>
>>No, that is not what I mean.
>>
>>Your question is how we should deal with multiple drivers that
>>support, for instance, the AHCI non-discoverable device type. My
>>answer is that this is not any different from a platform configuration
>>that has more than one PCI I/O based driver that supports the AHCI PCI
>>class codes. The UEFI driver model has priority rules and protocols to
>>decide which driver gets precedence. I don't see how it should be any
>>different here.
>
> I see they are different. Based on PciIo, the *HCI drivers can query
> additional information from PCI CFG header, instead of just using
> the PCI class code.
>
> But with the NonDiscoverableDevice protocol, there is no additional
> information can help the *HCI drivers decide which to manage.
>
> I don't see any practical negative point which prevents degrading
> NonDiscoverableDevice protocol to NonDiscoverable*Pci*Protocol.
> After all, as I said, all *HCI drivers are based on PciIo.
>

Yes the *drivers* are based on PCI. But that does not make the
*devices* PCI devices. That is the whole problem we are trying to deal
with. So describing the non-PCI devices as PCI devices is incorrect
imo. The fact that we will use PCI drivers to drive non-PCI devices is
an implementation detail of EDK2, and is a property of the *driver*
side not the *device* side. So using PCI class codes etc to wire up
the correct driver should be local to the driver, and not pollute the
description of the device.

For example, if we would ever split the AHCI driver into a AHCI part
and a PCI part (which I know is unlikely to occur), I would want the
non-PCI AHCI driver to be used with the same protocol. Perhaps that
means we need a protocol for each type of device rather than an enum?
In any case, putting PCI-specific metadata into the device description
makes the situation worse, because now both the *device* and the
*driver* side are forced to use PCI internals to describe devices that
have nothing to do with PCI

Thanks,
Ard.


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol
  2016-11-18  6:57                   ` Ard Biesheuvel
@ 2016-11-18  8:39                     ` Tian, Feng
  2016-11-18  8:52                       ` Ard Biesheuvel
  0 siblings, 1 reply; 27+ messages in thread
From: Tian, Feng @ 2016-11-18  8:39 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Ni, Ruiyu, Kinney, Michael D, edk2-devel@lists.01.org,
	Gao, Liming, afish@apple.com, Leif Lindholm, Tian, Feng

The simplest way I can think is

+struct _NON_DISCOVERABLE_DEVICE {
+  //
+  // The type of device
+  //
+  NON_DISCOVERABLE_DEVICE_TYPE        Type; -> change it to UINT8 Type; //Type is the subtype of corresponding device, such as SATA is MSG_SATA_DP(0x12)
+  //
+  // Whether this device is DMA coherent
+  //
+  NON_DISCOVERABLE_DEVICE_DMA_TYPE    DmaType;
+  //
+  // Initialization function for the device
+  //
+  NON_DISCOVERABLE_DEVICE_INIT        Initialize;
+  //
+  // The MMIO and I/O regions owned by the device
+  //
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Resources;
+};

Thanks
Feng

-----Original Message-----
From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org] 
Sent: Friday, November 18, 2016 2:57 PM
To: Tian, Feng <feng.tian@intel.com>
Cc: Ni, Ruiyu <ruiyu.ni@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; edk2-devel@lists.01.org; Gao, Liming <liming.gao@intel.com>; afish@apple.com; Leif Lindholm <leif.lindholm@linaro.org>
Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol

On 18 November 2016 at 05:24, Tian, Feng <feng.tian@intel.com> wrote:
> Ard,
>
> I have another question.
>
> Is it the only way to specify device type in below enum? Looks like it will be changed often. Is it possible to make use of DevicePath node? Of course, I have no good idea to handle AMBA controller...
>

How would you use a device path node to do that? I think we will always need a mapping somewhere in the code between numbers and AHCI/EHCI/etc types, given that the device itself cannot be interrogated to provide this information. If we can do the same with a device path, I'm happy to investigate, but I will need some help understanding how that would work

> +//
> +// Data Types
> +//
> +typedef enum {
> +  NonDiscoverableDeviceTypeAmba,
> +  NonDiscoverableDeviceTypeOhci,
> +  NonDiscoverableDeviceTypeUhci,
> +  NonDiscoverableDeviceTypeEhci,
> +  NonDiscoverableDeviceTypeXhci,
> +  NonDiscoverableDeviceTypeAhci,
> +  NonDiscoverableDeviceTypeSdhci,
> +  NonDiscoverableDeviceTypeUfs,
> +  NonDiscoverableDeviceTypeNvme,
> +  NonDiscoverableDeviceTypeMax,
> +} NON_DISCOVERABLE_DEVICE_TYPE;
>
> Thanks
> Feng
>
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of 
> Ard Biesheuvel
> Sent: Friday, November 18, 2016 12:59 PM
> To: Ni, Ruiyu <ruiyu.ni@intel.com>
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; 
> edk2-devel@lists.01.org; Gao, Liming <liming.gao@intel.com>; 
> afish@apple.com; Leif Lindholm <leif.lindholm@linaro.org>
> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce 
> non-discoverable device protocol
>
> On 18 November 2016 at 02:11, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>>
>>
>> Regards,
>> Ray
>>
>>>-----Original Message-----
>>>From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org]
>>>Sent: Thursday, November 17, 2016 6:43 PM
>>>To: Ni, Ruiyu <ruiyu.ni@intel.com>
>>>Cc: Kinney, Michael D <michael.d.kinney@intel.com>; 
>>>edk2-devel@lists.01.org; Gao, Liming <liming.gao@intel.com>; 
>>>afish@apple.com; Leif Lindholm <leif.lindholm@linaro.org>
>>>Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce 
>>>non-discoverable device protocol
>>>
>>>
>>>> On 17 Nov 2016, at 08:52, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>>>>
>>>>
>>>>
>>>> Thanks/Ray
>>>>
>>>>> -----Original Message-----
>>>>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On 
>>>>> Behalf Of Ard Biesheuvel
>>>>> Sent: Thursday, November 17, 2016 2:07 PM
>>>>> To: Ni, Ruiyu <ruiyu.ni@intel.com>
>>>>> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; edk2- 
>>>>> devel@lists.01.org; Gao, Liming <liming.gao@intel.com>; 
>>>>> afish@apple.com; Leif Lindholm <leif.lindholm@linaro.org>
>>>>> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non- 
>>>>> discoverable device protocol
>>>>>
>>>>>
>>>>>
>>>>>> On 17 Nov 2016, at 02:53, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>>>>>>
>>>>>> Ard,
>>>>>> I have two comments in below.
>>>>>>
>>>>>> Thanks/Ray
>>>>>>
>>>>>>> -----Original Message-----
>>>>>>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On 
>>>>>>> Behalf Of Leif Lindholm
>>>>>>> Sent: Thursday, November 17, 2016 1:49 AM
>>>>>>> To: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>>>>>> Cc: Ni, Ruiyu <ruiyu.ni@intel.com>; edk2-devel@lists.01.org; 
>>>>>>> afish@apple.com; Gao, Liming <liming.gao@intel.com>; Kinney, 
>>>>>>> Michael D <michael.d.kinney@intel.com>
>>>>>>> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non- 
>>>>>>> discoverable device protocol
>>>>>>>
>>>>>>>> On Wed, Nov 16, 2016 at 04:59:27PM +0000, Ard Biesheuvel wrote:
>>>>>>>> Introduce a protocol that can be exposed by a platform for 
>>>>>>>> devices that are not discoverable, usually because they are 
>>>>>>>> wired straight to the memory bus rather than to an enumerable bus like PCI or USB.
>>>>>>>>
>>>>>>>> Contributed-under: TianoCore Contribution Agreement 1.0
>>>>>>>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>>>>>>> ---
>>>>>>>> MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h | 90
>>>>>>> ++++++++++++++++++++
>>>>>>>> MdeModulePkg/MdeModulePkg.dec                         |  3 +
>>>>>>>> 2 files changed, 93 insertions(+)
>>>>>>>>
>>>>>>>> diff --git
>>>>>>>> a/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>>>>> b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>>>>> new file mode 100644
>>>>>>>> index 000000000000..47ed841b407b
>>>>>>>> --- /dev/null
>>>>>>>> +++ b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>>>>> @@ -0,0 +1,90 @@
>>>>>>>> +/** @file
>>>>>>>> +  Protocol to describe devices that are not on a discoverable 
>>>>>>>> +bus
>>>>>>>> +
>>>>>>>> +  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_DEVICE_H__ #define 
>>>>>>>> +__NON_DISCOVERABLE_DEVICE_H__
>>>>>>>> +
>>>>>>>> +#include <IndustryStandard/Acpi.h>
>>>>>>>> +
>>>>>>>> +#define EDKII_NON_DISCOVERABLE_DEVICE_PROTOCOL_GUID \
>>>>>>>> +  { 0x0d51905b, 0xb77e, 0x452a, {0xa2, 0xc0, 0xec, 0xa0, 0xcc, 
>>>>>>>> +0x8d, 0x51, 0x4a } }
>>>>>>
>>>>>> 1. Can you add "PCI" keyword into the protocol name?
>>>>>> e.g.: EDKII_NON_DISCOVERABLE_PCI_DEVICE_PROTOCOL_GUID
>>>>>>
>>>>>
>>>>> No. This protocol does not describe pci devices, and it is a 
>>>>> peculiarity of the
>>>>> edk2 driver stack that some non-pci devices can only be driven by pci drivers.
>>>>>
>>>>> in other words, pci is part of the /driver/ side, and it is 
>>>>> perfectly possible for, e.g., a non-discoverable ahci device to be 
>>>>> driven by a different non-pci driver in the future.
>>>>>
>>>>
>>>> I see. So some types of devices are handled by the current 
>>>> NonDiscoveablePciDevice driver, and some other types of devices may 
>>>> be handled by a future NonDiscoverableXXXDevice driver.
>>>> Now since the AHCI type is already handled by the 
>>>> NonDiscoverablePciDevice driver, when there is a new 
>>>> NonDiscoverableXXXDevice driver, how can the two know whether it should manage the AHCI type device or not?
>>>
>>>Good question. But how does the UEFI driver model deal with that? 
>>>What happens if i have two drivers that both support the Ahci Pci class codes?
>> PCI CFG header contains VendorID/DeviceID fields which can be used to 
>> distinguish them.
>>
>
> No, that is not what I mean.
>
> Your question is how we should deal with multiple drivers that support, for instance, the AHCI non-discoverable device type. My answer is that this is not any different from a platform configuration that has more than one PCI I/O based driver that supports the AHCI PCI class codes. The UEFI driver model has priority rules and protocols to decide which driver gets precedence. I don't see how it should be any different here.
>
> Thanks,
> Ard.
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol
  2016-11-18  8:39                     ` Tian, Feng
@ 2016-11-18  8:52                       ` Ard Biesheuvel
  0 siblings, 0 replies; 27+ messages in thread
From: Ard Biesheuvel @ 2016-11-18  8:52 UTC (permalink / raw)
  To: Tian, Feng
  Cc: Ni, Ruiyu, Kinney, Michael D, edk2-devel@lists.01.org,
	Gao, Liming, afish@apple.com, Leif Lindholm

On 18 November 2016 at 08:39, Tian, Feng <feng.tian@intel.com> wrote:
> The simplest way I can think is
>
> +struct _NON_DISCOVERABLE_DEVICE {
> +  //
> +  // The type of device
> +  //
> +  NON_DISCOVERABLE_DEVICE_TYPE        Type; -> change it to UINT8 Type; //Type is the subtype of corresponding device, such as SATA is MSG_SATA_DP(0x12)

What should we use for AMBA devices then?

> +  //
> +  // Whether this device is DMA coherent
> +  //
> +  NON_DISCOVERABLE_DEVICE_DMA_TYPE    DmaType;
> +  //
> +  // Initialization function for the device
> +  //
> +  NON_DISCOVERABLE_DEVICE_INIT        Initialize;
> +  //
> +  // The MMIO and I/O regions owned by the device
> +  //
> +  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Resources;
> +};
>
> Thanks
> Feng
>
> -----Original Message-----
> From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org]
> Sent: Friday, November 18, 2016 2:57 PM
> To: Tian, Feng <feng.tian@intel.com>
> Cc: Ni, Ruiyu <ruiyu.ni@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; edk2-devel@lists.01.org; Gao, Liming <liming.gao@intel.com>; afish@apple.com; Leif Lindholm <leif.lindholm@linaro.org>
> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol
>
> On 18 November 2016 at 05:24, Tian, Feng <feng.tian@intel.com> wrote:
>> Ard,
>>
>> I have another question.
>>
>> Is it the only way to specify device type in below enum? Looks like it will be changed often. Is it possible to make use of DevicePath node? Of course, I have no good idea to handle AMBA controller...
>>
>
> How would you use a device path node to do that? I think we will always need a mapping somewhere in the code between numbers and AHCI/EHCI/etc types, given that the device itself cannot be interrogated to provide this information. If we can do the same with a device path, I'm happy to investigate, but I will need some help understanding how that would work
>
>> +//
>> +// Data Types
>> +//
>> +typedef enum {
>> +  NonDiscoverableDeviceTypeAmba,
>> +  NonDiscoverableDeviceTypeOhci,
>> +  NonDiscoverableDeviceTypeUhci,
>> +  NonDiscoverableDeviceTypeEhci,
>> +  NonDiscoverableDeviceTypeXhci,
>> +  NonDiscoverableDeviceTypeAhci,
>> +  NonDiscoverableDeviceTypeSdhci,
>> +  NonDiscoverableDeviceTypeUfs,
>> +  NonDiscoverableDeviceTypeNvme,
>> +  NonDiscoverableDeviceTypeMax,
>> +} NON_DISCOVERABLE_DEVICE_TYPE;
>>
>> Thanks
>> Feng
>>
>> -----Original Message-----
>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
>> Ard Biesheuvel
>> Sent: Friday, November 18, 2016 12:59 PM
>> To: Ni, Ruiyu <ruiyu.ni@intel.com>
>> Cc: Kinney, Michael D <michael.d.kinney@intel.com>;
>> edk2-devel@lists.01.org; Gao, Liming <liming.gao@intel.com>;
>> afish@apple.com; Leif Lindholm <leif.lindholm@linaro.org>
>> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce
>> non-discoverable device protocol
>>
>> On 18 November 2016 at 02:11, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>>>
>>>
>>> Regards,
>>> Ray
>>>
>>>>-----Original Message-----
>>>>From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org]
>>>>Sent: Thursday, November 17, 2016 6:43 PM
>>>>To: Ni, Ruiyu <ruiyu.ni@intel.com>
>>>>Cc: Kinney, Michael D <michael.d.kinney@intel.com>;
>>>>edk2-devel@lists.01.org; Gao, Liming <liming.gao@intel.com>;
>>>>afish@apple.com; Leif Lindholm <leif.lindholm@linaro.org>
>>>>Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce
>>>>non-discoverable device protocol
>>>>
>>>>
>>>>> On 17 Nov 2016, at 08:52, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>>>>>
>>>>>
>>>>>
>>>>> Thanks/Ray
>>>>>
>>>>>> -----Original Message-----
>>>>>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On
>>>>>> Behalf Of Ard Biesheuvel
>>>>>> Sent: Thursday, November 17, 2016 2:07 PM
>>>>>> To: Ni, Ruiyu <ruiyu.ni@intel.com>
>>>>>> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; edk2-
>>>>>> devel@lists.01.org; Gao, Liming <liming.gao@intel.com>;
>>>>>> afish@apple.com; Leif Lindholm <leif.lindholm@linaro.org>
>>>>>> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-
>>>>>> discoverable device protocol
>>>>>>
>>>>>>
>>>>>>
>>>>>>> On 17 Nov 2016, at 02:53, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>>>>>>>
>>>>>>> Ard,
>>>>>>> I have two comments in below.
>>>>>>>
>>>>>>> Thanks/Ray
>>>>>>>
>>>>>>>> -----Original Message-----
>>>>>>>> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On
>>>>>>>> Behalf Of Leif Lindholm
>>>>>>>> Sent: Thursday, November 17, 2016 1:49 AM
>>>>>>>> To: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>>>>>>> Cc: Ni, Ruiyu <ruiyu.ni@intel.com>; edk2-devel@lists.01.org;
>>>>>>>> afish@apple.com; Gao, Liming <liming.gao@intel.com>; Kinney,
>>>>>>>> Michael D <michael.d.kinney@intel.com>
>>>>>>>> Subject: Re: [edk2] [PATCH v3 1/5] MdeModulePkg: introduce non-
>>>>>>>> discoverable device protocol
>>>>>>>>
>>>>>>>>> On Wed, Nov 16, 2016 at 04:59:27PM +0000, Ard Biesheuvel wrote:
>>>>>>>>> Introduce a protocol that can be exposed by a platform for
>>>>>>>>> devices that are not discoverable, usually because they are
>>>>>>>>> wired straight to the memory bus rather than to an enumerable bus like PCI or USB.
>>>>>>>>>
>>>>>>>>> Contributed-under: TianoCore Contribution Agreement 1.0
>>>>>>>>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>>>>>>>> ---
>>>>>>>>> MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h | 90
>>>>>>>> ++++++++++++++++++++
>>>>>>>>> MdeModulePkg/MdeModulePkg.dec                         |  3 +
>>>>>>>>> 2 files changed, 93 insertions(+)
>>>>>>>>>
>>>>>>>>> diff --git
>>>>>>>>> a/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>>>>>> b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>>>>>> new file mode 100644
>>>>>>>>> index 000000000000..47ed841b407b
>>>>>>>>> --- /dev/null
>>>>>>>>> +++ b/MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>>>>>>>> @@ -0,0 +1,90 @@
>>>>>>>>> +/** @file
>>>>>>>>> +  Protocol to describe devices that are not on a discoverable
>>>>>>>>> +bus
>>>>>>>>> +
>>>>>>>>> +  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_DEVICE_H__ #define
>>>>>>>>> +__NON_DISCOVERABLE_DEVICE_H__
>>>>>>>>> +
>>>>>>>>> +#include <IndustryStandard/Acpi.h>
>>>>>>>>> +
>>>>>>>>> +#define EDKII_NON_DISCOVERABLE_DEVICE_PROTOCOL_GUID \
>>>>>>>>> +  { 0x0d51905b, 0xb77e, 0x452a, {0xa2, 0xc0, 0xec, 0xa0, 0xcc,
>>>>>>>>> +0x8d, 0x51, 0x4a } }
>>>>>>>
>>>>>>> 1. Can you add "PCI" keyword into the protocol name?
>>>>>>> e.g.: EDKII_NON_DISCOVERABLE_PCI_DEVICE_PROTOCOL_GUID
>>>>>>>
>>>>>>
>>>>>> No. This protocol does not describe pci devices, and it is a
>>>>>> peculiarity of the
>>>>>> edk2 driver stack that some non-pci devices can only be driven by pci drivers.
>>>>>>
>>>>>> in other words, pci is part of the /driver/ side, and it is
>>>>>> perfectly possible for, e.g., a non-discoverable ahci device to be
>>>>>> driven by a different non-pci driver in the future.
>>>>>>
>>>>>
>>>>> I see. So some types of devices are handled by the current
>>>>> NonDiscoveablePciDevice driver, and some other types of devices may
>>>>> be handled by a future NonDiscoverableXXXDevice driver.
>>>>> Now since the AHCI type is already handled by the
>>>>> NonDiscoverablePciDevice driver, when there is a new
>>>>> NonDiscoverableXXXDevice driver, how can the two know whether it should manage the AHCI type device or not?
>>>>
>>>>Good question. But how does the UEFI driver model deal with that?
>>>>What happens if i have two drivers that both support the Ahci Pci class codes?
>>> PCI CFG header contains VendorID/DeviceID fields which can be used to
>>> distinguish them.
>>>
>>
>> No, that is not what I mean.
>>
>> Your question is how we should deal with multiple drivers that support, for instance, the AHCI non-discoverable device type. My answer is that this is not any different from a platform configuration that has more than one PCI I/O based driver that supports the AHCI PCI class codes. The UEFI driver model has priority rules and protocols to decide which driver gets precedence. I don't see how it should be any different here.
>>
>> Thanks,
>> Ard.
>> _______________________________________________
>> edk2-devel mailing list
>> edk2-devel@lists.01.org
>> https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 3/5] MdeModulePkg: implement generic PCI I/O driver for non-discoverable devices
  2016-11-17  3:29   ` Ni, Ruiyu
@ 2016-11-18 12:30     ` Ard Biesheuvel
  2016-11-24 18:14       ` Ard Biesheuvel
  0 siblings, 1 reply; 27+ messages in thread
From: Ard Biesheuvel @ 2016-11-18 12:30 UTC (permalink / raw)
  To: Ni, Ruiyu
  Cc: edk2-devel@lists.01.org, Gao, Liming, Kinney, Michael D,
	afish@apple.com, mw@semihalf.com, leif.lindholm@linaro.org

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
>


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol
  2016-11-18  7:04                   ` Ard Biesheuvel
@ 2016-11-18 13:39                     ` Ni, Ruiyu
  2016-11-18 13:50                       ` Ard Biesheuvel
  0 siblings, 1 reply; 27+ messages in thread
From: Ni, Ruiyu @ 2016-11-18 13:39 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Kinney, Michael D, edk2-devel@lists.01.org, Gao, Liming,
	afish@apple.com, Leif Lindholm

>>>>>>>> 1. Can you add "PCI" keyword into the protocol name?
>>>>>>>> e.g.: EDKII_NON_DISCOVERABLE_PCI_DEVICE_PROTOCOL_GUID
>>>>>>>>
>>>>>>>
>>>>>>> No. This protocol does not describe pci devices, and it is a peculiarity of the
>>>>>>> edk2 driver stack that some non-pci devices can only be driven by pci drivers.
>>>>>>>
>>>>>>> in other words, pci is part of the /driver/ side, and it is perfectly possible for,
>>>>>>> e.g., a non-discoverable ahci device to be driven by a different non-pci driver
>>>>>>> in the future.
>>>>>>>
>>>>>>
>>>>>> I see. So some types of devices are handled by the current
>>>>>> NonDiscoveablePciDevice driver, and some other types of devices may be
>>>>>> handled by a future NonDiscoverableXXXDevice driver.
>>>>>> Now since the AHCI type is already handled by the NonDiscoverablePciDevice
>>>>>> driver, when there is a new NonDiscoverableXXXDevice driver, how can the two
>>>>>> know whether it should manage the AHCI type device or not?
>>>>>
>>>>>Good question. But how does the UEFI driver model deal with that? What happens if i have two drivers that both support
>>>the
>>>>>Ahci Pci class codes?
>>>> PCI CFG header contains VendorID/DeviceID fields which can be used to distinguish
>>>> them.
>>>>
>>>
>>>No, that is not what I mean.
>>>
>>>Your question is how we should deal with multiple drivers that
>>>support, for instance, the AHCI non-discoverable device type. My
>>>answer is that this is not any different from a platform configuration
>>>that has more than one PCI I/O based driver that supports the AHCI PCI
>>>class codes. The UEFI driver model has priority rules and protocols to
>>>decide which driver gets precedence. I don't see how it should be any
>>>different here.
>>
>> I see they are different. Based on PciIo, the *HCI drivers can query
>> additional information from PCI CFG header, instead of just using
>> the PCI class code.
>>
>> But with the NonDiscoverableDevice protocol, there is no additional
>> information can help the *HCI drivers decide which to manage.
>>
>> I don't see any practical negative point which prevents degrading
>> NonDiscoverableDevice protocol to NonDiscoverable*Pci*Protocol.
>> After all, as I said, all *HCI drivers are based on PciIo.
>>
>
>Yes the *drivers* are based on PCI. But that does not make the
>*devices* PCI devices. That is the whole problem we are trying to deal
>with. So describing the non-PCI devices as PCI devices is incorrect
>imo. The fact that we will use PCI drivers to drive non-PCI devices is
>an implementation detail of EDK2, and is a property of the *driver*
>side not the *device* side. So using PCI class codes etc to wire up
>the correct driver should be local to the driver, and not pollute the
>description of the device.
>
>For example, if we would ever split the AHCI driver into a AHCI part
>and a PCI part (which I know is unlikely to occur), I would want the
>non-PCI AHCI driver to be used with the same protocol. Perhaps that
>means we need a protocol for each type of device rather than an enum?
>In any case, putting PCI-specific metadata into the device description
>makes the situation worse, because now both the *device* and the
>*driver* side are forced to use PCI internals to describe devices that
>have nothing to do with PCI

If I understand correctly, you want the protocol producer can simply
produce such protocol without the knowledge of PCI. I agree!
But we do need to make the protocol definition stable enough. I do not
like to see the enum type being extended in future to support more types
of devices.
1. Can you use different GUIDs for different types of devices?
2. As I replied as comment #2 to patch 3/5, do you have better way to
deal with the SDHCI Host controller driver access?


>
>Thanks,
>Ard.


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol
  2016-11-18 13:39                     ` Ni, Ruiyu
@ 2016-11-18 13:50                       ` Ard Biesheuvel
  2016-11-25 15:21                         ` Ard Biesheuvel
  0 siblings, 1 reply; 27+ messages in thread
From: Ard Biesheuvel @ 2016-11-18 13:50 UTC (permalink / raw)
  To: Ni, Ruiyu
  Cc: Kinney, Michael D, edk2-devel@lists.01.org, Gao, Liming,
	afish@apple.com, Leif Lindholm


On 18 Nov 2016, at 14:39, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:

>>>>>>>>> 1. Can you add "PCI" keyword into the protocol name?
>>>>>>>>> e.g.: EDKII_NON_DISCOVERABLE_PCI_DEVICE_PROTOCOL_GUID
>>>>>>>>> 
>>>>>>>> 
>>>>>>>> No. This protocol does not describe pci devices, and it is a peculiarity of the
>>>>>>>> edk2 driver stack that some non-pci devices can only be driven by pci drivers.
>>>>>>>> 
>>>>>>>> in other words, pci is part of the /driver/ side, and it is perfectly possible for,
>>>>>>>> e.g., a non-discoverable ahci device to be driven by a different non-pci driver
>>>>>>>> in the future.
>>>>>>>> 
>>>>>>> 
>>>>>>> I see. So some types of devices are handled by the current
>>>>>>> NonDiscoveablePciDevice driver, and some other types of devices may be
>>>>>>> handled by a future NonDiscoverableXXXDevice driver.
>>>>>>> Now since the AHCI type is already handled by the NonDiscoverablePciDevice
>>>>>>> driver, when there is a new NonDiscoverableXXXDevice driver, how can the two
>>>>>>> know whether it should manage the AHCI type device or not?
>>>>>> 
>>>>>> Good question. But how does the UEFI driver model deal with that? What happens if i have two drivers that both support
>>>> the
>>>>>> Ahci Pci class codes?
>>>>> PCI CFG header contains VendorID/DeviceID fields which can be used to distinguish
>>>>> them.
>>>>> 
>>>> 
>>>> No, that is not what I mean.
>>>> 
>>>> Your question is how we should deal with multiple drivers that
>>>> support, for instance, the AHCI non-discoverable device type. My
>>>> answer is that this is not any different from a platform configuration
>>>> that has more than one PCI I/O based driver that supports the AHCI PCI
>>>> class codes. The UEFI driver model has priority rules and protocols to
>>>> decide which driver gets precedence. I don't see how it should be any
>>>> different here.
>>> 
>>> I see they are different. Based on PciIo, the *HCI drivers can query
>>> additional information from PCI CFG header, instead of just using
>>> the PCI class code.
>>> 
>>> But with the NonDiscoverableDevice protocol, there is no additional
>>> information can help the *HCI drivers decide which to manage.
>>> 
>>> I don't see any practical negative point which prevents degrading
>>> NonDiscoverableDevice protocol to NonDiscoverable*Pci*Protocol.
>>> After all, as I said, all *HCI drivers are based on PciIo.
>>> 
>> 
>> Yes the *drivers* are based on PCI. But that does not make the
>> *devices* PCI devices. That is the whole problem we are trying to deal
>> with. So describing the non-PCI devices as PCI devices is incorrect
>> imo. The fact that we will use PCI drivers to drive non-PCI devices is
>> an implementation detail of EDK2, and is a property of the *driver*
>> side not the *device* side. So using PCI class codes etc to wire up
>> the correct driver should be local to the driver, and not pollute the
>> description of the device.
>> 
>> For example, if we would ever split the AHCI driver into a AHCI part
>> and a PCI part (which I know is unlikely to occur), I would want the
>> non-PCI AHCI driver to be used with the same protocol. Perhaps that
>> means we need a protocol for each type of device rather than an enum?
>> In any case, putting PCI-specific metadata into the device description
>> makes the situation worse, because now both the *device* and the
>> *driver* side are forced to use PCI internals to describe devices that
>> have nothing to do with PCI
> 
> If I understand correctly, you want the protocol producer can simply
> produce such protocol without the knowledge of PCI. I agree!
> But we do need to make the protocol definition stable enough. I do not
> like to see the enum type being extended in future to support more types
> of devices.
> 1. Can you use different GUIDs for different types of devices?

Yes that seems like a reasonable approach, in the spirit of EDK2 :-)

> 2. As I replied as comment #2 to patch 3/5, do you have better way to
> deal with the SDHCI Host controller driver access?


I need to think about this

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 0/5] MdeModulePkg: add support for non-discoverable devices
  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
  0 siblings, 0 replies; 27+ messages in thread
From: Marcin Wojtas @ 2016-11-23 14:31 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: edk2-devel-01, Gao, Liming, Ni, Ruiyu, Kinney, Michael D, afish,
	Leif Lindholm

Hi,

Also AHCI works fine, as well as init quirk mechanism.

Best regards,
Marcin

2016-11-17 5:36 GMT+01:00 Marcin Wojtas <mw@semihalf.com>:
> Hi Ard,
>
> Series tested on Marvell Armada 7040 board (XHCI and SDHCI). You can add:
> Tested-by: Marcin Wojtas <mw@semihalf.com>
>
> Best regards,
> Marcin
>
> 2016-11-16 17:59 GMT+01:00 Ard Biesheuvel <ard.biesheuvel@linaro.org>:
>> The rationale for this series is the fact that many ARM platforms implement
>> some form of PCI 'emulation', to allow non-discoverable devices that implement
>> standardized host controller interfaces (i.e., EHCI, AHCI) to be controlled by
>> the generic EDK2 drivers, which are layered on top of the PCI I/O protocols
>> (even though the respective host controller specifications don't mandate that)
>>
>> There are a couple of problems with that approach:
>> - Most implementations are based on the original code created for BeagleBoard,
>>   which is a 32-bit platform. Unlike x86, which usually does not perform PCI
>>   DMA above 4 GB, the ARM ecosystem is much more heterogeneous, and platforms
>>   that have memory both above and below the 4 GB mark may ship with, e.g., EHCI
>>   controllers that do not implement 64-bit DMA addressing.
>> - Implementations depend on the DmaLib library class in EmbeddedPkg, of which
>>   coherent and non-coherent implementations exists. However, both types of
>>   devices may appear on a single platform, requiring several instances of the
>>   same driver.
>> - Existing implementations do not follow the UEFI driver model, but instantiate
>>   a fixed number of PCI I/O protocol handles, and bring up all the devices when
>>   doing so. However, the UEFI philosophy is to only instantiate (and thus
>>   initialize) devices that are involved in booting.
>>
>> So instead, let's define a base protocol that simply asserts the presence of
>> a certain kind of device at a certain memory offset, allowing platforms to
>> instantiate any number of these statically, and leave it to post-DXE driver
>> dispatch to actually bind the drivers as usual. This is implemented in patch #1.
>> Note that it includes an AMBA device type, which we intend to use in the future
>> to move ARM AMBA drivers to the UEFI driver model as well (i.e., LCD controller,
>> SD/MMC controller)
>>
>> Patch #2 implements a utility library to register non-discoverable devices.
>>
>> Patch #3 implements the UEFI driver that instantiates PCI I/O protocol handles
>> for non-discoverable devices that we know can be driven by a generic driver in
>> EDK2. The initial version implements coherent DMA only.
>>
>> Patch #4 implements non-coherent DMA for the driver added in patch #3.
>>
>> Patch #5 is included for reference. It ports the BeagleBoard platform to the
>> new driver stack.
>>
>> Changes in v3:
>> - Modified the base protocol to describe any number of resources using ACPI
>>   resource descriptors. The current crop of targeted peripherals does not
>>   require that, but it allows for much more flexibility in the future. This
>>   also means that the MMIO region sizes are no longer hard-coded base on the
>>   controller type (EHCI, AHCI, etc) but need to be declared when the devices
>>   are registered.
>> - Update the registration library API to allow multiple MMIO regions to be
>>   declared.
>> - When performing uncached allocations, record the original memory region
>>   attributes so we can restore them correctly on free.
>> - Some fixes in the 4GB boundary checks for Map/Unmap
>> - Rename gNonDiscoverableDeviceProtocolGuid to
>>   gEdkiiNonDiscoverableDeviceProtocolGuid
>>
>> Ard Biesheuvel (5):
>>   MdeModulePkg: introduce non-discoverable device protocol
>>   MdeModule: introduce helper library to register non-discoverable
>>     devices
>>   MdeModulePkg: implement generic PCI I/O driver for non-discoverable
>>     devices
>>   MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent
>>     DMA
>>   Omap35xxPkg/PciEmulation: port to new non-discoverable device
>>     infrastructure
>>
>>  BeagleBoardPkg/BeagleBoardPkg.dsc                                                                  |    2 +
>>  BeagleBoardPkg/BeagleBoardPkg.fdf                                                                  |    1 +
>>  MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/ComponentName.c                                   |   75 ++
>>  MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c                     |  226 ++++
>>  MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf                   |   44 +
>>  MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c                      | 1187 ++++++++++++++++++++
>>  MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h                      |  113 ++
>>  MdeModulePkg/Include/Library/NonDiscoverableDeviceRegistrationLib.h                                |   49 +
>>  MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h                                              |   90 ++
>>  MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.c   |  161 +++
>>  MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf |   34 +
>>  MdeModulePkg/MdeModulePkg.dec                                                                      |    7 +
>>  MdeModulePkg/MdeModulePkg.dsc                                                                      |    3 +
>>  Omap35xxPkg/Omap35xxPkg.dsc                                                                        |    2 +-
>>  Omap35xxPkg/PciEmulation/PciEmulation.c                                                            |  578 +---------
>>  Omap35xxPkg/PciEmulation/PciEmulation.h                                                            |  292 -----
>>  Omap35xxPkg/PciEmulation/PciEmulation.inf                                                          |   16 +-
>>  Omap35xxPkg/PciEmulation/PciRootBridgeIo.c                                                         |  306 -----
>>  18 files changed, 2025 insertions(+), 1161 deletions(-)
>>  create mode 100644 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/ComponentName.c
>>  create mode 100644 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
>>  create mode 100644 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
>>  create mode 100644 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
>>  create mode 100644 MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.h
>>  create mode 100644 MdeModulePkg/Include/Library/NonDiscoverableDeviceRegistrationLib.h
>>  create mode 100644 MdeModulePkg/Include/Protocol/NonDiscoverableDevice.h
>>  create mode 100644 MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.c
>>  create mode 100644 MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf
>>  delete mode 100644 Omap35xxPkg/PciEmulation/PciEmulation.h
>>  delete mode 100644 Omap35xxPkg/PciEmulation/PciRootBridgeIo.c
>>
>> --
>> 2.7.4
>>


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 3/5] MdeModulePkg: implement generic PCI I/O driver for non-discoverable devices
  2016-11-18 12:30     ` Ard Biesheuvel
@ 2016-11-24 18:14       ` Ard Biesheuvel
  0 siblings, 0 replies; 27+ messages in thread
From: Ard Biesheuvel @ 2016-11-24 18:14 UTC (permalink / raw)
  To: Ni, Ruiyu
  Cc: edk2-devel@lists.01.org, Gao, Liming, Kinney, Michael D,
	afish@apple.com, mw@semihalf.com, leif.lindholm@linaro.org

Ray, I still need some help understanding how you think this is supposed to work

Thanks,
Ard.


On 18 November 2016 at 12:30, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> On 17 November 2016 at 03:29, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
[...]
>>> +//
>>> +// 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
>>


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 1/5] MdeModulePkg: introduce non-discoverable device protocol
  2016-11-18 13:50                       ` Ard Biesheuvel
@ 2016-11-25 15:21                         ` Ard Biesheuvel
  0 siblings, 0 replies; 27+ messages in thread
From: Ard Biesheuvel @ 2016-11-25 15:21 UTC (permalink / raw)
  To: Ni, Ruiyu
  Cc: Kinney, Michael D, edk2-devel@lists.01.org, Gao, Liming,
	afish@apple.com, Leif Lindholm

On 18 November 2016 at 13:50, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>
> On 18 Nov 2016, at 14:39, Ni, Ruiyu <ruiyu.ni@intel.com> wrote:
>
>>>>>>>>>> 1. Can you add "PCI" keyword into the protocol name?
>>>>>>>>>> e.g.: EDKII_NON_DISCOVERABLE_PCI_DEVICE_PROTOCOL_GUID
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> No. This protocol does not describe pci devices, and it is a peculiarity of the
>>>>>>>>> edk2 driver stack that some non-pci devices can only be driven by pci drivers.
>>>>>>>>>
>>>>>>>>> in other words, pci is part of the /driver/ side, and it is perfectly possible for,
>>>>>>>>> e.g., a non-discoverable ahci device to be driven by a different non-pci driver
>>>>>>>>> in the future.
>>>>>>>>>
>>>>>>>>
>>>>>>>> I see. So some types of devices are handled by the current
>>>>>>>> NonDiscoveablePciDevice driver, and some other types of devices may be
>>>>>>>> handled by a future NonDiscoverableXXXDevice driver.
>>>>>>>> Now since the AHCI type is already handled by the NonDiscoverablePciDevice
>>>>>>>> driver, when there is a new NonDiscoverableXXXDevice driver, how can the two
>>>>>>>> know whether it should manage the AHCI type device or not?
>>>>>>>
>>>>>>> Good question. But how does the UEFI driver model deal with that? What happens if i have two drivers that both support
>>>>> the
>>>>>>> Ahci Pci class codes?
>>>>>> PCI CFG header contains VendorID/DeviceID fields which can be used to distinguish
>>>>>> them.
>>>>>>
>>>>>
>>>>> No, that is not what I mean.
>>>>>
>>>>> Your question is how we should deal with multiple drivers that
>>>>> support, for instance, the AHCI non-discoverable device type. My
>>>>> answer is that this is not any different from a platform configuration
>>>>> that has more than one PCI I/O based driver that supports the AHCI PCI
>>>>> class codes. The UEFI driver model has priority rules and protocols to
>>>>> decide which driver gets precedence. I don't see how it should be any
>>>>> different here.
>>>>
>>>> I see they are different. Based on PciIo, the *HCI drivers can query
>>>> additional information from PCI CFG header, instead of just using
>>>> the PCI class code.
>>>>
>>>> But with the NonDiscoverableDevice protocol, there is no additional
>>>> information can help the *HCI drivers decide which to manage.
>>>>
>>>> I don't see any practical negative point which prevents degrading
>>>> NonDiscoverableDevice protocol to NonDiscoverable*Pci*Protocol.
>>>> After all, as I said, all *HCI drivers are based on PciIo.
>>>>
>>>
>>> Yes the *drivers* are based on PCI. But that does not make the
>>> *devices* PCI devices. That is the whole problem we are trying to deal
>>> with. So describing the non-PCI devices as PCI devices is incorrect
>>> imo. The fact that we will use PCI drivers to drive non-PCI devices is
>>> an implementation detail of EDK2, and is a property of the *driver*
>>> side not the *device* side. So using PCI class codes etc to wire up
>>> the correct driver should be local to the driver, and not pollute the
>>> description of the device.
>>>
>>> For example, if we would ever split the AHCI driver into a AHCI part
>>> and a PCI part (which I know is unlikely to occur), I would want the
>>> non-PCI AHCI driver to be used with the same protocol. Perhaps that
>>> means we need a protocol for each type of device rather than an enum?
>>> In any case, putting PCI-specific metadata into the device description
>>> makes the situation worse, because now both the *device* and the
>>> *driver* side are forced to use PCI internals to describe devices that
>>> have nothing to do with PCI
>>
>> If I understand correctly, you want the protocol producer can simply
>> produce such protocol without the knowledge of PCI. I agree!
>> But we do need to make the protocol definition stable enough. I do not
>> like to see the enum type being extended in future to support more types
>> of devices.
>> 1. Can you use different GUIDs for different types of devices?
>
> Yes that seems like a reasonable approach, in the spirit of EDK2 :-)
>
>> 2. As I replied as comment #2 to patch 3/5, do you have better way to
>> deal with the SDHCI Host controller driver access?
>

The best way is to revert to the previous solution. This means two
SDHCI slots will be modeled as two separate non-discoverable devices,
and will each receive a separate instance of the PCI I/O protocol,
describing a SDHCI-PCI device with a single slot. But actually, I
don't think that matters at all. The way the SDHCI driver is
implemented is debatable anway: I still think it should be a bus
driver, with each slot a separate device on this bus.


^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2016-11-25 15:21 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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
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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox