Revision: 17246
http://sourceforge.net/p/edk2/code/17246
Author: erictian
Date: 2015-04-29 02:42:58 +0000 (Wed, 29 Apr 2015)
Log Message:
-----------
MdeModulePkg: Add UFS (Universal Flash Storage) Stack
It includes 4 drivers:
1. UfsPassThruDxe, which is a UEFI driver and consumes
EFI_UFS_HOST_CONTROLLER_PROTOCOL and produces EFI_EXT_SCSI_PASS_THRU_PROTOCOL
2. UfsPciHcDxe, which is specific for pci-based UFS HC implementation and is a
UEFI driver to produce EFI_UFS_HOST_CONTROLLER_PROTOCOL.
3. UfsBlockIoPei, which is a PEI driver and consumes
EFI_UFS_HOST_CONTROLLER_PPI and produces EFI_PEI_VIRTUAL_BLOCK_IO_PPI.
4. UfsPciHcPei, which is specific for pci-based UFS HC implementation and is a
PEI driver to produce EFI_UFS_HOST_CONTROLLER_PPI.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Feng Tian <[email protected]>
Reviewed-by: Star Zeng <[email protected]>
Modified Paths:
--------------
trunk/edk2/MdeModulePkg/MdeModulePkg.dec
trunk/edk2/MdeModulePkg/MdeModulePkg.dsc
trunk/edk2/MdeModulePkg/MdeModulePkg.uni
Added Paths:
-----------
trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/
trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/ComponentName.c
trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.c
trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.h
trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.inf
trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.uni
trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxeExtra.uni
trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/
trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.c
trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.h
trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.inf
trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.uni
trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPeiExtra.uni
trunk/edk2/MdeModulePkg/Bus/Ufs/
trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/
trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.c
trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.h
trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.inf
trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.uni
trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPeiExtra.uni
trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHcMem.c
trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHcMem.h
trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHci.c
trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHci.h
trunk/edk2/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/
trunk/edk2/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/ComponentName.c
trunk/edk2/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
trunk/edk2/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.h
trunk/edk2/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.uni
trunk/edk2/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruDxe.inf
trunk/edk2/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruExtra.uni
trunk/edk2/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.c
trunk/edk2/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.h
trunk/edk2/MdeModulePkg/Include/Ppi/UfsHostController.h
trunk/edk2/MdeModulePkg/Include/Protocol/UfsHostController.h
Added: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/ComponentName.c
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/ComponentName.c
(rev 0)
+++ trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/ComponentName.c 2015-04-29
02:42:58 UTC (rev 17246)
@@ -0,0 +1,225 @@
+/** @file
+ UfsHcDxe driver produces EFI_UFS_HOST_CONTROLLER_PROTOCOL. The upper layer
module
+ uses it to query the MMIO base address of the UFS host controller.
+
+ Copyright (c) 2014, Intel Corporation. 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 "UfsPciHcDxe.h"
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gUfsHcComponentName
= {
+ UfsHcComponentNameGetDriverName,
+ UfsHcComponentNameGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL
gUfsHcComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) UfsHcComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)
UfsHcComponentNameGetControllerName,
+ "en"
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mUfsHcDriverNameTable[]
= {
+ {
+ "eng;en",
+ L"Universal Flash Storage (UFS) Pci Host Controller Driver"
+ },
+ {
+ NULL,
+ NULL
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE
mUfsHcControllerNameTable[] = {
+ {
+ "eng;en",
+ L"Universal Flash Storage (UFS) Pci Host Controller"
+ },
+ {
+ NULL,
+ NULL
+ }
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL
or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mUfsHcDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gUfsHcComponentName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified
by
+ Language, then a pointer to the controller name is returned in
ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not
currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL
or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter
that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus
drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name
in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle
OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ EFI_STATUS Status;
+
+ if (Language == NULL || ControllerName == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Make sure this driver is currently managing Controller Handle
+ //
+ Status = EfiTestManagedDevice (
+ ControllerHandle,
+ gUfsHcDriverBinding.DriverBindingHandle,
+ &gEfiPciIoProtocolGuid
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mUfsHcControllerNameTable,
+ ControllerName,
+ (BOOLEAN)(This == &gUfsHcComponentName)
+ );
+
+}
Added: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.c
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.c
(rev 0)
+++ trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.c 2015-04-29
02:42:58 UTC (rev 17246)
@@ -0,0 +1,699 @@
+/** @file
+ UfsHcDxe driver is used to provide platform-dependent info, mainly UFS host
controller
+ MMIO base, to upper layer UFS drivers.
+
+ Copyright (c) 2014, Intel Corporation. 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 "UfsPciHcDxe.h"
+
+//
+// NVM Express Driver Binding Protocol Instance
+//
+EFI_DRIVER_BINDING_PROTOCOL gUfsHcDriverBinding = {
+ UfsHcDriverBindingSupported,
+ UfsHcDriverBindingStart,
+ UfsHcDriverBindingStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+//
+// Template for Ufs host controller private data.
+//
+UFS_HOST_CONTROLLER_PRIVATE_DATA gUfsHcTemplate = {
+ UFS_HC_PRIVATE_DATA_SIGNATURE, // Signature
+ NULL, // Handle
+ { // UfsHcProtocol
+ UfsHcGetMmioBar,
+ UfsHcAllocateBuffer,
+ UfsHcFreeBuffer,
+ UfsHcMap,
+ UfsHcUnmap,
+ UfsHcFlush
+ },
+ NULL, // PciIo
+ 0 // PciAttributes
+};
+
+/**
+ Get the MMIO base of the UFS host controller.
+
+ @param[in] This A pointer to the
EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
+ @param[out] MmioBar The MMIO base address of UFS host controller.
+
+ @retval EFI_SUCCESS The operation succeeds.
+ @retval others The operation fails.
+**/
+EFI_STATUS
+EFIAPI
+UfsHcGetMmioBar (
+ IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
+ OUT UINTN *MmioBar
+ )
+{
+ UFS_HOST_CONTROLLER_PRIVATE_DATA *Private;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+
+ if ((This == NULL) || (MmioBar == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
+ PciIo = Private->PciIo;
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ PCI_BASE_ADDRESSREG_OFFSET,
+ sizeof (UINT32),
+ MmioBar
+ );
+
+ if (!EFI_ERROR (Status)) {
+ *MmioBar &= (UINTN)~0xF;
+ }
+ return Status;
+}
+
+/**
+ Provides the UFS controller-specific addresses needed to access system
memory.
+
+ @param This A pointer to the
EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
+ @param Operation Indicates if the bus master is going to read
or write to system memory.
+ @param HostAddress The system memory address to map to the UFS
controller.
+ @param NumberOfBytes On input the number of bytes to map. On output
the number of bytes
+ that were mapped.
+ @param DeviceAddress The resulting map address for the bus master
UFS controller to use to
+ access the hosts HostAddress.
+ @param Mapping A resulting value to pass to Unmap().
+
+ @retval EFI_SUCCESS The range was mapped for the returned
NumberOfBytes.
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common
buffer.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
lack of resources.
+ @retval EFI_DEVICE_ERROR The system hardware could not map the
requested address.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcMap (
+ IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
+ IN EDKII_UFS_HOST_CONTROLLER_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+{
+ UFS_HOST_CONTROLLER_PRIVATE_DATA *Private;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+
+ if ((This == NULL) || (HostAddress == NULL) || (NumberOfBytes == NULL) ||
(DeviceAddress == NULL) || (Mapping == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
+ PciIo = Private->PciIo;
+
+ Status = PciIo->Map (PciIo, Operation, HostAddress, NumberOfBytes,
DeviceAddress, Mapping);
+ return Status;
+}
+
+/**
+ Completes the Map() operation and releases any corresponding resources.
+
+ @param This A pointer to the
EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
+ @param Mapping The mapping value returned from Map().
+
+ @retval EFI_SUCCESS The range was unmapped.
+ @retval EFI_DEVICE_ERROR The data was not committed to the target
system memory.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcUnmap (
+ IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+{
+ UFS_HOST_CONTROLLER_PRIVATE_DATA *Private;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+
+ if ((This == NULL) || (Mapping == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
+ PciIo = Private->PciIo;
+
+ Status = PciIo->Unmap (PciIo, Mapping);
+ return Status;
+}
+
+/**
+ Allocates pages that are suitable for an
EfiUfsHcOperationBusMasterCommonBuffer
+ mapping.
+
+ @param This A pointer to the
EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
+ @param Type This parameter is not used and must be ignored.
+ @param MemoryType The type of memory to allocate,
EfiBootServicesData or
+ EfiRuntimeServicesData.
+ @param Pages The number of pages to allocate.
+ @param HostAddress A pointer to store the base system memory
address of the
+ allocated range.
+ @param Attributes The requested bit mask of attributes for the
allocated range.
+
+ @retval EFI_SUCCESS The requested memory pages were allocated.
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal
attribute bits are
+ MEMORY_WRITE_COMBINE and MEMORY_CACHED.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcAllocateBuffer (
+ IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ )
+{
+ UFS_HOST_CONTROLLER_PRIVATE_DATA *Private;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+
+ if ((This == NULL) || (HostAddress == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
+ PciIo = Private->PciIo;
+
+ Status = PciIo->AllocateBuffer (PciIo, Type, MemoryType, Pages,
HostAddress, Attributes);
+ return Status;
+}
+
+/**
+ Frees memory that was allocated with AllocateBuffer().
+
+ @param This A pointer to the
EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
+ @param Pages The number of pages to free.
+ @param HostAddress The base system memory address of the
allocated range.
+
+ @retval EFI_SUCCESS The requested memory pages were freed.
+ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and
Pages
+ was not allocated with AllocateBuffer().
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcFreeBuffer (
+ IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
+ IN UINTN Pages,
+ IN VOID *HostAddress
+ )
+{
+ UFS_HOST_CONTROLLER_PRIVATE_DATA *Private;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+
+ if ((This == NULL) || (HostAddress == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
+ PciIo = Private->PciIo;
+
+ Status = PciIo->FreeBuffer (PciIo, Pages, HostAddress);
+ return Status;
+}
+
+/**
+ Flushes all posted write transactions from the UFS bus to attached UFS
device.
+
+ @param This A pointer to the
EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
+
+ @retval EFI_SUCCESS The posted write transactions were flushed
from the UFS bus
+ to attached UFS device.
+ @retval EFI_DEVICE_ERROR The posted write transactions were not flushed
from the UFS
+ bus to attached UFS device due to a hardware
error.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcFlush (
+ IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This
+ )
+{
+ UFS_HOST_CONTROLLER_PRIVATE_DATA *Private;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+
+ Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
+ PciIo = Private->PciIo;
+
+ Status = PciIo->Flush (PciIo);
+ return Status;
+}
+
+/**
+ Tests to see if this driver supports a given controller. If a child device
is provided,
+ it further tests to see if this driver supports creating a handle for the
specified child device.
+
+ This function checks to see if the driver specified by This supports the
device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This
function
+ may be called many times during platform initialization. In order to reduce
boot times, the tests
+ performed by this function must be very small, and take as little time as
possible to execute. This
+ function must not change the state of any hardware devices, and this
function must be aware that the
+ device specified by ControllerHandle may already be managed by the same
driver or a
+ different driver. This function must match its calls to AllocatePages() with
FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Since ControllerHandle may have been previously started by the same driver,
if a protocol is
+ already in the opened state, then it must not be closed with
CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the
EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This
handle
+ must support a protocol interface that
supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a
device path. This
+ parameter is ignored by device drivers, and
is optional for bus
+ drivers. For bus drivers, if this parameter
is not NULL, then
+ the bus driver must determine if the bus
controller specified
+ by ControllerHandle and the child
controller specified
+ by RemainingDevicePath are both supported
by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the
driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being
managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being
managed by a different
+ driver or an application that requires
exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the
driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+UfsHcDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN UfsHcFound;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 PciData;
+
+ PciIo = NULL;
+ ParentDevicePath = NULL;
+ UfsHcFound = FALSE;
+
+ //
+ // UfsHcDxe is a device driver, and should ingore the
+ // "RemainingDevicePath" according to EFI spec
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID *) &ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // EFI_ALREADY_STARTED is also an error
+ //
+ return Status;
+ }
+ //
+ // Close the protocol because we don't use it here
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
+ // Now test the EfiPciIoProtocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Now further check the PCI header: Base class (offset 0x0B) and
+ // Sub Class (offset 0x0A). This controller should be an UFS controller
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ sizeof (PciData),
+ &PciData
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Since we already got the PciData, we can close protocol to avoid to carry
it on for multiple exit points.
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
+ // Examine UFS Host Controller PCI Configuration table fields
+ //
+ if (PciData.Hdr.ClassCode[2] == PCI_CLASS_MASS_STORAGE) {
+ if (PciData.Hdr.ClassCode[1] == 0x09 ) { //UFS Controller Subclass
+ UfsHcFound = TRUE;
+ }
+ }
+
+ if (!UfsHcFound) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return Status;
+}
+
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service
ConnectController().
+ As a result, much of the error checking on the parameters to Start() has
been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed or the system
behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a
naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver
specified by This must
+ have been called with the same calling parameters, and Supported() must
have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the
EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This
handle
+ must support a protocol interface that
supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a
device path. This
+ parameter is ignored by device drivers, and
is optional for bus
+ drivers. For a bus driver, if this
parameter is NULL, then handles
+ for all the children of Controller are
created by this driver.
+ If this parameter is not NULL and the first
Device Path Node is
+ not the End of Device Path Node, then only
the handle for the
+ child device specified by the first Device
Path Node of
+ RemainingDevicePath is created by this
driver.
+ If the first Device Path Node of
RemainingDevicePath is
+ the End of Device Path Node, no child
handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a
device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UFS_HOST_CONTROLLER_PRIVATE_DATA *Private;
+ UINT64 Supports;
+
+ PciIo = NULL;
+ Private = NULL;
+ Supports = 0;
+
+ //
+ // Now test and open the EfiPciIoProtocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ //
+ // Status == 0 - A normal execution flow, SUCCESS and the program proceeds.
+ // Status == ALREADY_STARTED - A non-zero Status code returned. It indicates
+ // that the protocol has been opened and should be treated as a
+ // normal condition and the program proceeds. The Protocol will not
+ // opened 'again' by this call.
+ // Status != ALREADY_STARTED - Error status, terminate program execution
+ //
+ if (EFI_ERROR (Status)) {
+ //
+ // EFI_ALREADY_STARTED is also an error
+ //
+ return Status;
+ }
+
+ Private = AllocateCopyPool (sizeof (UFS_HOST_CONTROLLER_PRIVATE_DATA),
&gUfsHcTemplate);
+ if (Private == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ Private->PciIo = PciIo;
+
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationGet,
+ 0,
+ &Private->PciAttributes
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationSupported,
+ 0,
+ &Supports
+ );
+
+ if (!EFI_ERROR (Status)) {
+ Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ Supports,
+ NULL
+ );
+ } else {
+ goto Done;
+ }
+
+ ///
+ /// Install UFS_HOST_CONTROLLER protocol
+ ///
+ Status = gBS->InstallProtocolInterface (
+ &Controller,
+ &gEdkiiUfsHostControllerProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ (VOID*)&(Private->UfsHc)
+ );
+
+Done:
+ if (EFI_ERROR (Status)) {
+ if ((Private != NULL) && (Private->PciAttributes != 0)) {
+ //
+ // Restore original PCI attributes
+ //
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationSet,
+ Private->PciAttributes,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ if (Private != NULL) {
+ FreePool (Private);
+ }
+ }
+
+ return Status;
+}
+
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service
DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been
moved
+ into this common boot service. It is legal to call Stop() from other
locations,
+ but the following calling restrictions must be followed or the system
behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous
call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a
valid
+ EFI_HANDLE. In addition, all of these handles must have been created in
this driver's
+ Start() function, and the Start() function must have called
OpenProtocol() on
+ ControllerHandle with an Attribute of
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL
instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The
handle must
+ support a bus specific I/O protocol for the
driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in
ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be
NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a
device error.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+ UFS_HOST_CONTROLLER_PRIVATE_DATA *Private;
+ EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
+
+ ///
+ /// Get private data
+ ///
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEdkiiUfsHostControllerProtocolGuid,
+ (VOID **) &UfsHc,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (UfsHc);
+
+ Status = gBS->UninstallProtocolInterface (
+ Controller,
+ &gEdkiiUfsHostControllerProtocolGuid,
+ &(Private->UfsHc)
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Restore original PCI attributes
+ //
+ Status = Private->PciIo->Attributes (
+ Private->PciIo,
+ EfiPciIoAttributeOperationSet,
+ Private->PciAttributes,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Close protocols opened by UFS host controller driver
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ FreePool (Private);
+ }
+
+ return Status;
+}
+
+/**
+ The entry point for UFS host controller driver, used to install this driver
on the ImageHandle.
+
+ @param[in] ImageHandle The firmware allocated handle for this driver
image.
+ @param[in] SystemTable Pointer to the EFI system table.
+
+ @retval EFI_SUCCESS Driver loaded.
+ @retval other Driver not loaded.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcDriverEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gUfsHcDriverBinding,
+ ImageHandle,
+ &gUfsHcComponentName,
+ &gUfsHcComponentName2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
Added: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.h
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.h
(rev 0)
+++ trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.h 2015-04-29
02:42:58 UTC (rev 17246)
@@ -0,0 +1,453 @@
+/** @file
+ UfsHcDxe driver is used to provide platform-dependent info, mainly UFS host
controller
+ MMIO base, to upper layer UFS drivers.
+
+ Copyright (c) 2014, Intel Corporation. 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 _EFI_UFS_HOST_CONTROLLER_H_
+#define _EFI_UFS_HOST_CONTROLLER_H_
+
+#include <Uefi.h>
+
+#include <IndustryStandard/Pci.h>
+
+#include <Protocol/ComponentName.h>
+#include <Protocol/ComponentName2.h>
+#include <Protocol/DriverBinding.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/UfsHostController.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+
+extern EFI_DRIVER_BINDING_PROTOCOL gUfsHcDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gUfsHcComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gUfsHcComponentName2;
+
+//
+// Unique signature for private data structure.
+//
+#define UFS_HC_PRIVATE_DATA_SIGNATURE SIGNATURE_32
('U','F','S','H')
+
+typedef struct _UFS_HOST_CONTROLLER_PRIVATE_DATA
UFS_HOST_CONTROLLER_PRIVATE_DATA;
+
+//
+// Nvme private data structure.
+//
+struct _UFS_HOST_CONTROLLER_PRIVATE_DATA {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+
+ EDKII_UFS_HOST_CONTROLLER_PROTOCOL UfsHc;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT64 PciAttributes;
+};
+
+#define UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC(a) \
+ CR (a, \
+ UFS_HOST_CONTROLLER_PRIVATE_DATA, \
+ UfsHc, \
+ UFS_HC_PRIVATE_DATA_SIGNATURE \
+ )
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL
or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified
by
+ Language, then a pointer to the controller name is returned in
ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not
currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL
or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter
that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus
drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name
in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle
OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+/**
+ Tests to see if this driver supports a given controller. If a child device
is provided,
+ it further tests to see if this driver supports creating a handle for the
specified child device.
+
+ This function checks to see if the driver specified by This supports the
device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This
function
+ may be called many times during platform initialization. In order to reduce
boot times, the tests
+ performed by this function must be very small, and take as little time as
possible to execute. This
+ function must not change the state of any hardware devices, and this
function must be aware that the
+ device specified by ControllerHandle may already be managed by the same
driver or a
+ different driver. This function must match its calls to AllocatePages() with
FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Since ControllerHandle may have been previously started by the same driver,
if a protocol is
+ already in the opened state, then it must not be closed with
CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the
EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This
handle
+ must support a protocol interface that
supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a
device path. This
+ parameter is ignored by device drivers, and
is optional for bus
+ drivers. For bus drivers, if this parameter
is not NULL, then
+ the bus driver must determine if the bus
controller specified
+ by ControllerHandle and the child
controller specified
+ by RemainingDevicePath are both supported
by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the
driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being
managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being
managed by a different
+ driver or an application that requires
exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the
driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+UfsHcDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service
ConnectController().
+ As a result, much of the error checking on the parameters to Start() has
been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed or the system
behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a
naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver
specified by This must
+ have been called with the same calling parameters, and Supported() must
have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the
EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This
handle
+ must support a protocol interface that
supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a
device path. This
+ parameter is ignored by device drivers, and
is optional for bus
+ drivers. For a bus driver, if this
parameter is NULL, then handles
+ for all the children of Controller are
created by this driver.
+ If this parameter is not NULL and the first
Device Path Node is
+ not the End of Device Path Node, then only
the handle for the
+ child device specified by the first Device
Path Node of
+ RemainingDevicePath is created by this
driver.
+ If the first Device Path Node of
RemainingDevicePath is
+ the End of Device Path Node, no child
handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a
device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service
DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been
moved
+ into this common boot service. It is legal to call Stop() from other
locations,
+ but the following calling restrictions must be followed or the system
behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous
call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a
valid
+ EFI_HANDLE. In addition, all of these handles must have been created in
this driver's
+ Start() function, and the Start() function must have called
OpenProtocol() on
+ ControllerHandle with an Attribute of
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL
instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The
handle must
+ support a bus specific I/O protocol for the
driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in
ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be
NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a
device error.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+/**
+ Get the MMIO base of the UFS host controller.
+
+ @param[in] This A pointer to the
EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
+ @param[out] MmioBar The MMIO base address of UFS host controller.
+
+ @retval EFI_SUCCESS The operation succeeds.
+ @retval others The operation fails.
+**/
+EFI_STATUS
+EFIAPI
+UfsHcGetMmioBar (
+ IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
+ OUT UINTN *MmioBar
+ );
+
+/**
+ Provides the UFS controller-specific addresses needed to access system
memory.
+
+ @param This A pointer to the
EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
+ @param Operation Indicates if the bus master is going to read
or write to system memory.
+ @param HostAddress The system memory address to map to the UFS
controller.
+ @param NumberOfBytes On input the number of bytes to map. On output
the number of bytes
+ that were mapped.
+ @param DeviceAddress The resulting map address for the bus master
UFS controller to use to
+ access the hosts HostAddress.
+ @param Mapping A resulting value to pass to Unmap().
+
+ @retval EFI_SUCCESS The range was mapped for the returned
NumberOfBytes.
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common
buffer.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
lack of resources.
+ @retval EFI_DEVICE_ERROR The system hardware could not map the
requested address.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcMap (
+ IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
+ IN EDKII_UFS_HOST_CONTROLLER_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ );
+
+/**
+ Completes the Map() operation and releases any corresponding resources.
+
+ @param This A pointer to the
EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
+ @param Mapping The mapping value returned from Map().
+
+ @retval EFI_SUCCESS The range was unmapped.
+ @retval EFI_DEVICE_ERROR The data was not committed to the target
system memory.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcUnmap (
+ IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
+ IN VOID *Mapping
+ );
+
+/**
+ Allocates pages that are suitable for an
EfiUfsHcOperationBusMasterCommonBuffer
+ mapping.
+
+ @param This A pointer to the
EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
+ @param Type This parameter is not used and must be ignored.
+ @param MemoryType The type of memory to allocate,
EfiBootServicesData or
+ EfiRuntimeServicesData.
+ @param Pages The number of pages to allocate.
+ @param HostAddress A pointer to store the base system memory
address of the
+ allocated range.
+ @param Attributes The requested bit mask of attributes for the
allocated range.
+
+ @retval EFI_SUCCESS The requested memory pages were allocated.
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal
attribute bits are
+ MEMORY_WRITE_COMBINE and MEMORY_CACHED.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcAllocateBuffer (
+ IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ );
+
+/**
+ Frees memory that was allocated with AllocateBuffer().
+
+ @param This A pointer to the
EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
+ @param Pages The number of pages to free.
+ @param HostAddress The base system memory address of the
allocated range.
+
+ @retval EFI_SUCCESS The requested memory pages were freed.
+ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and
Pages
+ was not allocated with AllocateBuffer().
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcFreeBuffer (
+ IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
+ IN UINTN Pages,
+ IN VOID *HostAddress
+ );
+
+/**
+ Flushes all posted write transactions from the UFS bus to attached UFS
device.
+
+ @param This A pointer to the
EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
+
+ @retval EFI_SUCCESS The posted write transactions were flushed
from the UFS bus
+ to attached UFS device.
+ @retval EFI_DEVICE_ERROR The posted write transactions were not flushed
from the UFS
+ bus to attached UFS device due to a hardware
error.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsHcFlush (
+ IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This
+ );
+
+#endif
Added: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.inf
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.inf
(rev 0)
+++ trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.inf 2015-04-29
02:42:58 UTC (rev 17246)
@@ -0,0 +1,56 @@
+## @file
+# Component Description File For Universal Flash Storage Pci Host Controller
Module.
+#
+# Copyright (c) 2014 - 2015, Intel Corporation. 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 = 0x00010005
+ BASE_NAME = UfsPciHcDxe
+ MODULE_UNI_FILE = UfsPciHcDxe.uni
+ FILE_GUID = AF43E178-C2E9-4712-A7CD-08BFDAC7482C
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 0.9
+ ENTRY_POINT = UfsHcDriverEntry
+
+#
+# The following information is for reference only and not required by the
build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+# DRIVER_BINDING = gUfsHcDriverBinding
+# COMPONENT_NAME = gUfsHcComponentName
+# COMPONENT_NAME2 = gUfsHcComponentName2
+
+[Sources]
+ ComponentName.c
+ UfsPciHcDxe.c
+ UfsPciHcDxe.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ DevicePathLib
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ UefiLib
+
+[Protocols]
+ gEfiPciIoProtocolGuid ## TO_START
+ gEfiDevicePathProtocolGuid ## TO_START
+ gEdkiiUfsHostControllerProtocolGuid ## BY_START
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ UfsPciHcDxeExtra.uni
\ No newline at end of file
Added: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.uni
===================================================================
(Binary files differ)
Index: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.uni
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.uni 2015-04-29
02:37:30 UTC (rev 17245)
+++ trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.uni 2015-04-29
02:42:58 UTC (rev 17246)
Property changes on: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.uni
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Added: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxeExtra.uni
===================================================================
(Binary files differ)
Index: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxeExtra.uni
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxeExtra.uni
2015-04-29 02:37:30 UTC (rev 17245)
+++ trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxeExtra.uni
2015-04-29 02:42:58 UTC (rev 17246)
Property changes on:
trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxeExtra.uni
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Added: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.c
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.c
(rev 0)
+++ trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.c 2015-04-29
02:42:58 UTC (rev 17246)
@@ -0,0 +1,152 @@
+/** @file
+ UfsPciHcPei driver is used to provide platform-dependent info, mainly UFS
host controller
+ MMIO base, to upper layer UFS drivers.
+
+ Copyright (c) 2014, Intel Corporation. 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 "UfsPciHcPei.h"
+
+EDKII_UFS_HOST_CONTROLLER_PPI mUfsHostControllerPpi = { GetUfsHcMmioBar };
+
+EFI_PEI_PPI_DESCRIPTOR mPpiList = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEdkiiPeiUfsHostControllerPpiGuid,
+ &mUfsHostControllerPpi
+};
+
+/**
+ Get the MMIO base address of UFS host controller.
+
+ @param[in] This The protocol instance pointer.
+ @param[in] ControllerId The ID of the UFS host controller.
+ @param[out] MmioBar Pointer to the UFS host controller MMIO base
address.
+
+ @retval EFI_SUCCESS The operation succeeds.
+ @retval EFI_INVALID_PARAMETER The parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+GetUfsHcMmioBar (
+ IN EDKII_UFS_HOST_CONTROLLER_PPI *This,
+ IN UINT8 ControllerId,
+ OUT UINTN *MmioBar
+ )
+{
+ UFS_HC_PEI_PRIVATE_DATA *Private;
+
+ if ((This == NULL) || (MmioBar == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = UFS_HC_PEI_PRIVATE_DATA_FROM_THIS (This);
+
+ if (ControllerId >= Private->TotalUfsHcs) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *MmioBar = (UINTN)Private->UfsHcPciAddr[ControllerId];
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The user code starts with this function.
+
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Describes the list of possible PEI Services.
+
+ @retval EFI_SUCCESS The driver is successfully initialized.
+ @retval Others Can't initialize the driver.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeUfsHcPeim (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_BOOT_MODE BootMode;
+ EFI_STATUS Status;
+ UINT16 Bus;
+ UINT16 Device;
+ UINT16 Function;
+ UINT32 Size;
+ UINT8 SubClass;
+ UINT8 BaseClass;
+ UFS_HC_PEI_PRIVATE_DATA *Private;
+
+ //
+ // Shadow this PEIM to run from memory
+ //
+ if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
+ return EFI_SUCCESS;
+ }
+
+ Status = PeiServicesGetBootMode (&BootMode);
+ ///
+ /// We do not export this in S3 boot path, because it is only for recovery.
+ ///
+ if (BootMode == BOOT_ON_S3_RESUME) {
+ return EFI_SUCCESS;
+ }
+
+ Private = (UFS_HC_PEI_PRIVATE_DATA *) AllocateZeroPool (sizeof
(UFS_HC_PEI_PRIVATE_DATA));
+ if (Private == NULL) {
+ DEBUG ((EFI_D_ERROR, "Failed to allocate memory for
UFS_HC_PEI_PRIVATE_DATA! \n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Private->Signature = UFS_HC_PEI_SIGNATURE;
+ Private->UfsHostControllerPpi = mUfsHostControllerPpi;
+ Private->PpiList = mPpiList;
+ Private->PpiList.Ppi = &Private->UfsHostControllerPpi;
+
+ for (Bus = 0; Bus < 256; Bus++) {
+ for (Device = 0; Device < 32; Device++) {
+ for (Function = 0; Function < 8; Function++) {
+ SubClass = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0A));
+ BaseClass = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0B));
+
+ if ((SubClass == 0x09) && (BaseClass == PCI_CLASS_MASS_STORAGE)) {
+ //
+ // Get the Ufs Pci host controller's MMIO region size.
+ //
+ PciAnd16 (PCI_LIB_ADDRESS (Bus, Device, Function,
PCI_COMMAND_OFFSET), (UINT16)~(EFI_PCI_COMMAND_BUS_MASTER |
EFI_PCI_COMMAND_MEMORY_SPACE));
+ PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function,
PCI_BASE_ADDRESSREG_OFFSET), 0xFFFFFFFF);
+ Size = PciRead32 (PCI_LIB_ADDRESS (Bus, Device, Function,
PCI_BASE_ADDRESSREG_OFFSET));
+ //
+ // Assign resource to the Ufs Pci host controller's MMIO BAR.
+ // Enable the Ufs Pci host controller by setting BME and MSE bits of
PCI_CMD register.
+ //
+ PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function,
PCI_BASE_ADDRESSREG_OFFSET), (UINT32)(PcdGet32
(PcdUfsPciHostControllerMmioBase) + Size * Private->TotalUfsHcs));
+ PciOr16 (PCI_LIB_ADDRESS (Bus, Device, Function,
PCI_COMMAND_OFFSET), (EFI_PCI_COMMAND_BUS_MASTER |
EFI_PCI_COMMAND_MEMORY_SPACE));
+ //
+ // Record the allocated Mmio base address.
+ //
+ Private->UfsHcPciAddr[Private->TotalUfsHcs] = PcdGet32
(PcdUfsPciHostControllerMmioBase) + Size * Private->TotalUfsHcs;
+ Private->TotalUfsHcs++;
+ ASSERT (Private->TotalUfsHcs < MAX_UFS_HCS);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Install Ufs Host Controller PPI
+ ///
+ Status = PeiServicesInstallPpi (&Private->PpiList);
+
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
Added: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.h
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.h
(rev 0)
+++ trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.h 2015-04-29
02:42:58 UTC (rev 17246)
@@ -0,0 +1,62 @@
+/** @file
+ Copyright (c) 2014, Intel Corporation. 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 _UFS_PCI_HOST_CONTROLLER_PEI_H_
+#define _UFS_PCI_HOST_CONTROLLER_PEI_H_
+
+#include <PiPei.h>
+
+#include <Ppi/MasterBootMode.h>
+#include <Ppi/UfsHostController.h>
+
+#include <IndustryStandard/Pci.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PciLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#define UFS_HC_PEI_SIGNATURE SIGNATURE_32 ('U', 'F', 'S', 'P')
+#define MAX_UFS_HCS 8
+
+typedef struct {
+ UINTN Signature;
+ EDKII_UFS_HOST_CONTROLLER_PPI UfsHostControllerPpi;
+ EFI_PEI_PPI_DESCRIPTOR PpiList;
+ UINTN TotalUfsHcs;
+ UINTN UfsHcPciAddr[MAX_UFS_HCS];
+} UFS_HC_PEI_PRIVATE_DATA;
+
+#define UFS_HC_PEI_PRIVATE_DATA_FROM_THIS(a) CR (a, UFS_HC_PEI_PRIVATE_DATA,
UfsHostControllerPpi, UFS_HC_PEI_SIGNATURE)
+
+/**
+ Get the MMIO base address of UFS host controller.
+
+ @param[in] This The protocol instance pointer.
+ @param[in] ControllerId The ID of the UFS host controller.
+ @param[out] MmioBar Pointer to the UFS host controller MMIO base
address.
+
+ @retval EFI_SUCCESS The operation succeeds.
+ @retval EFI_INVALID_PARAMETER The parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+GetUfsHcMmioBar (
+ IN EDKII_UFS_HOST_CONTROLLER_PPI *This,
+ IN UINT8 ControllerId,
+ OUT UINTN *MmioBar
+ );
+
+#endif
Added: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.inf
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.inf
(rev 0)
+++ trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.inf 2015-04-29
02:42:58 UTC (rev 17246)
@@ -0,0 +1,56 @@
+## @file
+# Component Description File For Universal Flash Storage Pci Host Controller
Pei Module.
+#
+# Copyright (c) 2014 - 2015, Intel Corporation. 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 = 0x00010005
+ BASE_NAME = UfsPciHcPei
+ MODULE_UNI_FILE = UfsPciHcPei.uni
+ FILE_GUID = 905DC1AD-C44D-4965-98AC-B6B4444BFD65
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 0.9
+
+ ENTRY_POINT = InitializeUfsHcPeim
+
+#
+# The following information is for reference only and not required by the
build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ UfsPciHcPei.c
+ UfsPciHcPei.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ PciLib
+ DebugLib
+ PeiServicesLib
+ MemoryAllocationLib
+ PeimEntryPoint
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdUfsPciHostControllerMmioBase ## CONSUMES
+
+[Ppis]
+ gEdkiiPeiUfsHostControllerPpiGuid ## PRODUCES
+
+[Depex]
+ gEfiPeiMasterBootModePpiGuid AND gEfiPeiMemoryDiscoveredPpiGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ UfsPciHcPeiExtra.uni
\ No newline at end of file
Added: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.uni
===================================================================
(Binary files differ)
Index: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.uni
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.uni 2015-04-29
02:37:30 UTC (rev 17245)
+++ trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.uni 2015-04-29
02:42:58 UTC (rev 17246)
Property changes on: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.uni
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Added: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPeiExtra.uni
===================================================================
(Binary files differ)
Index: trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPeiExtra.uni
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPeiExtra.uni
2015-04-29 02:37:30 UTC (rev 17245)
+++ trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPeiExtra.uni
2015-04-29 02:42:58 UTC (rev 17246)
Property changes on:
trunk/edk2/MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPeiExtra.uni
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Added: trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.c
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.c
(rev 0)
+++ trunk/edk2/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.c
2015-04-29 02:42:58 UTC (rev 17246)
@@ -0,0 +1,995 @@
+/** @file
+
+ Copyright (c) 2014, Intel Corporation. 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 "UfsBlockIoPei.h"
+
+//
+// Template for UFS HC Peim Private Data.
+//
+UFS_PEIM_HC_PRIVATE_DATA gUfsHcPeimTemplate = {
+ UFS_PEIM_HC_SIG, // Signature
+ NULL, // Controller
+ NULL, // Pool
+ { // BlkIoPpi
+ UfsBlockIoPeimGetDeviceNo,
+ UfsBlockIoPeimGetMediaInfo,
+ UfsBlockIoPeimReadBlocks
+ },
+ { // BlkIoPpiList
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gEfiPeiVirtualBlockIoPpiGuid,
+ NULL
+ },
+ { // Media
+ {
+ UfsDevice,
+ TRUE,
+ 0,
+ 0x1000
+ },
+ {
+ UfsDevice,
+ TRUE,
+ 0,
+ 0x1000
+ },
+ {
+ UfsDevice,
+ TRUE,
+ 0,
+ 0x1000
+ },
+ {
+ UfsDevice,
+ TRUE,
+ 0,
+ 0x1000
+ },
+ {
+ UfsDevice,
+ TRUE,
+ 0,
+ 0x1000
+ },
+ {
+ UfsDevice,
+ TRUE,
+ 0,
+ 0x1000
+ },
+ {
+ UfsDevice,
+ TRUE,
+ 0,
+ 0x1000
+ },
+ {
+ UfsDevice,
+ TRUE,
+ 0,
+ 0x1000
+ }
+ },
+ 0, // UfsHcBase
+ 0, // Capabilities
+ 0, // TaskTag
+ 0, // UtpTrlBase
+ 0, // Nutrs
+ 0, // UtpTmrlBase
+ 0, // Nutmrs
+ { // Luns
+ {
+ UFS_LUN_0, // Ufs Common Lun 0
+ UFS_LUN_1, // Ufs Common Lun 1
+ UFS_LUN_2, // Ufs Common Lun 2
+ UFS_LUN_3, // Ufs Common Lun 3
+ UFS_LUN_4, // Ufs Common Lun 4
+ UFS_LUN_5, // Ufs Common Lun 5
+ UFS_LUN_6, // Ufs Common Lun 6
+ UFS_LUN_7, // Ufs Common Lun 7
+ },
+ 0x0000, // By default exposing all Luns.
+ 0x0
+ }
+};
+
+/**
+ Execute Request Sense SCSI command on a specific UFS device.
+
+ @param[in] Private A pointer to UFS_PEIM_HC_PRIVATE_DATA data
structure.
+ @param[in] Lun The lun on which the SCSI cmd executed.
+ @param[out] DataBuffer A pointer to output sense data.
+ @param[out] DataBufferLength The length of output sense data.
+
+ @retval EFI_SUCCESS The command executed successfully.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to
send SCSI Request Packet.
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the
SCSI Request Packet to execute.
+
+**/
+EFI_STATUS
+UfsPeimRequestSense (
+ IN UFS_PEIM_HC_PRIVATE_DATA *Private,
+ IN UINTN Lun,
+ OUT VOID *DataBuffer,
+ OUT UINT32 *DataBufferLength
+ )
+{
+ UFS_SCSI_REQUEST_PACKET Packet;
+ UINT8 Cdb[UFS_SCSI_OP_LENGTH_SIX];
+ EFI_STATUS Status;
+
+ ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
+ ZeroMem (Cdb, sizeof (Cdb));
+
+ Cdb[0] = EFI_SCSI_OP_REQUEST_SENSE;
+
+ Packet.Timeout = UFS_TIMEOUT;
+ Packet.Cdb = Cdb;
+ Packet.CdbLength = sizeof (Cdb);
+ Packet.DataDirection = UfsDataIn;
+ Packet.InDataBuffer = DataBuffer;
+ Packet.InTransferLength = *DataBufferLength;
+ Packet.SenseData = NULL;
+ Packet.SenseDataLength = 0;
+
+ Status = UfsExecScsiCmds (Private,(UINT8)Lun, &Packet);
+
+ if (!EFI_ERROR (Status)) {
+ *DataBufferLength = Packet.InTransferLength;
+ }
+
+ return Status;
+}
+
+/**
+ Execute TEST UNITY READY SCSI command on a specific UFS device.
+
+ @param[in] Private A pointer to UFS_PEIM_HC_PRIVATE_DATA data
structure.
+ @param[in] Lun The lun on which the SCSI cmd executed.
+ @param[out] SenseData A pointer to output sense data.
+ @param[out] SenseDataLength The length of output sense data.
+
+ @retval EFI_SUCCESS The command executed successfully.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to
send SCSI Request Packet.
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the
SCSI Request Packet to execute.
+
+**/
+EFI_STATUS
+UfsPeimTestUnitReady (
+ IN UFS_PEIM_HC_PRIVATE_DATA *Private,
+ IN UINTN Lun,
+ OUT VOID *SenseData, OPTIONAL
+ OUT UINT8 *SenseDataLength
+ )
+{
+ UFS_SCSI_REQUEST_PACKET Packet;
+ UINT8 Cdb[UFS_SCSI_OP_LENGTH_SIX];
+ EFI_STATUS Status;
+
+ ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
+ ZeroMem (Cdb, sizeof (Cdb));
+
+ Cdb[0] = EFI_SCSI_OP_TEST_UNIT_READY;
+
+ Packet.Timeout = UFS_TIMEOUT;
+ Packet.Cdb = Cdb;
+ Packet.CdbLength = sizeof (Cdb);
+ Packet.DataDirection = UfsNoData;
+ Packet.SenseData = SenseData;
+ Packet.SenseDataLength = *SenseDataLength;
+
+ Status = UfsExecScsiCmds (Private,(UINT8)Lun, &Packet);
+
+ if (*SenseDataLength != 0) {
+ *SenseDataLength = Packet.SenseDataLength;
+ }
+
+ return Status;
+}
+
+/**
+ Execute INQUIRY SCSI command on a specific UFS device.
+
+ @param[in] Private A pointer to UFS_PEIM_HC_PRIVATE_DATA data
structure.
+ @param[in] Lun The lun on which the SCSI cmd executed.
+ @param[out] Inquiry A pointer to Inquiry data buffer.
+ @param[out] InquiryLengths The length of output Inquiry data.
+ @param[out] SenseData A pointer to output sense data.
+ @param[out] SenseDataLength The length of output sense data.
+
+ @retval EFI_SUCCESS The command executed successfully.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to
send SCSI Request Packet.
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the
SCSI Request Packet to execute.
+
+**/
+EFI_STATUS
+UfsPeimInquiry (
+ IN UFS_PEIM_HC_PRIVATE_DATA *Private,
+ IN UINTN Lun,
+ OUT VOID *Inquiry,
+ OUT UINT32 *InquiryLength,
+ OUT VOID *SenseData, OPTIONAL
+ OUT UINT8 *SenseDataLength
+ )
+{
+ UFS_SCSI_REQUEST_PACKET Packet;
+ UINT8 Cdb[UFS_SCSI_OP_LENGTH_SIX];
+ EFI_STATUS Status;
+
+ ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
+ ZeroMem (Cdb, sizeof (Cdb));
+
+ Cdb[0] = EFI_SCSI_OP_INQUIRY;
+ Cdb[4] = sizeof (EFI_SCSI_INQUIRY_DATA);
+
+ Packet.Timeout = UFS_TIMEOUT;
+ Packet.Cdb = Cdb;
+ Packet.CdbLength = sizeof (Cdb);
+ Packet.InDataBuffer = Inquiry;
+ Packet.InTransferLength = *InquiryLength;
+ Packet.DataDirection = UfsDataIn;
+ Packet.SenseData = SenseData;
+ Packet.SenseDataLength = *SenseDataLength;
+
+ Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);
+
+ if (*SenseDataLength != 0) {
+ *SenseDataLength = Packet.SenseDataLength;
+ }
+
+ if (!EFI_ERROR (Status)) {
+ *InquiryLength = Packet.InTransferLength;
+ }
+
+ return Status;
+}
+
+/**
+ Execute READ CAPACITY(10) SCSI command on a specific UFS device.
+
+ @param[in] Private A pointer to UFS_PEIM_HC_PRIVATE_DATA data
structure.
+ @param[in] Lun The lun on which the SCSI cmd executed.
+ @param[out] DataBuffer A pointer to READ_CAPACITY data buffer.
+ @param[out] DataLength The length of output READ_CAPACITY data.
+ @param[out] SenseData A pointer to output sense data.
+ @param[out] SenseDataLength The length of output sense data.
+
+ @retval EFI_SUCCESS The command executed successfully.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to
send SCSI Request Packet.
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the
SCSI Request Packet to execute.
+
+**/
+EFI_STATUS
+UfsPeimReadCapacity (
+ IN UFS_PEIM_HC_PRIVATE_DATA *Private,
+ IN UINTN Lun,
+ OUT VOID *DataBuffer,
+ OUT UINT32 *DataLength,
+ OUT VOID *SenseData, OPTIONAL
+ OUT UINT8 *SenseDataLength
+ )
+{
+ UFS_SCSI_REQUEST_PACKET Packet;
+ UINT8 Cdb[UFS_SCSI_OP_LENGTH_TEN];
+ EFI_STATUS Status;
+
+ ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
+ ZeroMem (Cdb, sizeof (Cdb));
+
+ Cdb[0] = EFI_SCSI_OP_READ_CAPACITY;
+
+ Packet.Timeout = UFS_TIMEOUT;
+ Packet.Cdb = Cdb;
+ Packet.CdbLength = sizeof (Cdb);
+ Packet.InDataBuffer = DataBuffer;
+ Packet.InTransferLength = *DataLength;
+ Packet.DataDirection = UfsDataIn;
+ Packet.SenseData = SenseData;
+ Packet.SenseDataLength = *SenseDataLength;
+
+ Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);
+
+ if (*SenseDataLength != 0) {
+ *SenseDataLength = Packet.SenseDataLength;
+ }
+
+ if (!EFI_ERROR (Status)) {
+ *DataLength = Packet.InTransferLength;
+ }
+
+ return Status;
+}
+
+/**
+ Execute READ CAPACITY(16) SCSI command on a specific UFS device.
+
+ @param[in] Private A pointer to UFS_PEIM_HC_PRIVATE_DATA data
structure.
+ @param[in] Lun The lun on which the SCSI cmd executed.
+ @param[out] DataBuffer A pointer to READ_CAPACITY data buffer.
+ @param[out] DataLength The length of output READ_CAPACITY data.
+ @param[out] SenseData A pointer to output sense data.
+ @param[out] SenseDataLength The length of output sense data.
+
+ @retval EFI_SUCCESS The command executed successfully.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to
send SCSI Request Packet.
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the
SCSI Request Packet to execute.
+
+**/
+EFI_STATUS
+UfsPeimReadCapacity16 (
+ IN UFS_PEIM_HC_PRIVATE_DATA *Private,
+ IN UINTN Lun,
+ OUT VOID *DataBuffer,
+ OUT UINT32 *DataLength,
+ OUT VOID *SenseData, OPTIONAL
+ OUT UINT8 *SenseDataLength
+ )
+{
+ UFS_SCSI_REQUEST_PACKET Packet;
+ UINT8 Cdb[UFS_SCSI_OP_LENGTH_SIXTEEN];
+ EFI_STATUS Status;
+
+ ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
+ ZeroMem (Cdb, sizeof (Cdb));
+
+ Cdb[0] = EFI_SCSI_OP_READ_CAPACITY16;
+ Cdb[1] = 0x10; // Service Action should be 0x10 for UFS device.
+ Cdb[13] = 0x20; // The maximum number of bytes for returned data.
+
+ Packet.Timeout = UFS_TIMEOUT;
+ Packet.Cdb = Cdb;
+ Packet.CdbLength = sizeof (Cdb);
+ Packet.InDataBuffer = DataBuffer;
+ Packet.InTransferLength = *DataLength;
+ Packet.DataDirection = UfsDataIn;
+ Packet.SenseData = SenseData;
+ Packet.SenseDataLength = *SenseDataLength;
+
+ Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);
+
+ if (*SenseDataLength != 0) {
+ *SenseDataLength = Packet.SenseDataLength;
+ }
+
+ if (!EFI_ERROR (Status)) {
+ *DataLength = Packet.InTransferLength;
+ }
+
+ return Status;
+}
+
+/**
+ Execute READ (10) SCSI command on a specific UFS device.
+
+ @param[in] Private A pointer to UFS_PEIM_HC_PRIVATE_DATA data
structure.
+ @param[in] Lun The lun on which the SCSI cmd executed.
+ @param[in] StartLba The start LBA.
+ @param[in] SectorNum The sector number to be read.
+ @param[out] DataBuffer A pointer to data buffer.
+ @param[out] DataLength The length of output data.
+ @param[out] SenseData A pointer to output sense data.
+ @param[out] SenseDataLength The length of output sense data.
+
+ @retval EFI_SUCCESS The command executed successfully.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to
send SCSI Request Packet.
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the
SCSI Request Packet to execute.
+
+**/
+EFI_STATUS
+UfsPeimRead10 (
+ IN UFS_PEIM_HC_PRIVATE_DATA *Private,
+ IN UINTN Lun,
+ IN UINTN StartLba,
+ IN UINT32 SectorNum,
+ OUT VOID *DataBuffer,
+ OUT UINT32 *DataLength,
+ OUT VOID *SenseData, OPTIONAL
+ OUT UINT8 *SenseDataLength
+ )
+{
+ UFS_SCSI_REQUEST_PACKET Packet;
+ UINT8 Cdb[UFS_SCSI_OP_LENGTH_TEN];
+ EFI_STATUS Status;
+
+ ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
+ ZeroMem (Cdb, sizeof (Cdb));
+
+ Cdb[0] = EFI_SCSI_OP_READ10;
+ WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 ((UINT32) StartLba));
+ WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorNum));
+
+ Packet.Timeout = UFS_TIMEOUT;
+ Packet.Cdb = Cdb;
+ Packet.CdbLength = sizeof (Cdb);
+ Packet.InDataBuffer = DataBuffer;
+ Packet.InTransferLength = *DataLength;
+ Packet.DataDirection = UfsDataIn;
+ Packet.SenseData = SenseData;
+ Packet.SenseDataLength = *SenseDataLength;
+
+ Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);
+
+ if (*SenseDataLength != 0) {
+ *SenseDataLength = Packet.SenseDataLength;
+ }
+
+ if (!EFI_ERROR (Status)) {
+ *DataLength = Packet.InTransferLength;
+ }
+
+ return Status;
+}
+
+/**
+ Execute READ (16) SCSI command on a specific UFS device.
+
+ @param[in] Private A pointer to UFS_PEIM_HC_PRIVATE_DATA data
structure.
+ @param[in] Lun The lun on which the SCSI cmd executed.
+ @param[in] StartLba The start LBA.
+ @param[in] SectorNum The sector number to be read.
+ @param[out] DataBuffer A pointer to data buffer.
+ @param[out] DataLength The length of output data.
+ @param[out] SenseData A pointer to output sense data.
+ @param[out] SenseDataLength The length of output sense data.
+
+ @retval EFI_SUCCESS The command executed successfully.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to
send SCSI Request Packet.
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the
SCSI Request Packet to execute.
+
+**/
+EFI_STATUS
+UfsPeimRead16 (
+ IN UFS_PEIM_HC_PRIVATE_DATA *Private,
+ IN UINTN Lun,
+ IN UINTN StartLba,
+ IN UINT32 SectorNum,
+ OUT VOID *DataBuffer,
+ OUT UINT32 *DataLength,
+ OUT VOID *SenseData, OPTIONAL
+ OUT UINT8 *SenseDataLength
+ )
+{
+ UFS_SCSI_REQUEST_PACKET Packet;
+ UINT8 Cdb[UFS_SCSI_OP_LENGTH_SIXTEEN];
+ EFI_STATUS Status;
+
+ ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
+ ZeroMem (Cdb, sizeof (Cdb));
+
+ Cdb[0] = EFI_SCSI_OP_READ16;
+ WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));
+ WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorNum));
+
+ Packet.Timeout = UFS_TIMEOUT;
+ Packet.Cdb = Cdb;
+ Packet.CdbLength = sizeof (Cdb);
+ Packet.InDataBuffer = DataBuffer;
+ Packet.InTransferLength = *DataLength;
+ Packet.DataDirection = UfsDataIn;
+ Packet.SenseData = SenseData;
+ Packet.SenseDataLength = *SenseDataLength;
+
+ Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);
+
+ if (*SenseDataLength != 0) {
+ *SenseDataLength = Packet.SenseDataLength;
+ }
+
+ if (!EFI_ERROR (Status)) {
+ *DataLength = Packet.InTransferLength;
+ }
+
+ return Status;
+}
+
+/**
+ Parsing Sense Keys from sense data.
+
+ @param Media The pointer of EFI_PEI_BLOCK_IO_MEDIA
+ @param SenseData The pointer of EFI_SCSI_SENSE_DATA
+ @param NeedRetry The pointer of action which indicates what is
need to retry
+
+ @retval EFI_DEVICE_ERROR Indicates that error occurs
+ @retval EFI_SUCCESS Successfully to complete the parsing
+
+**/
+EFI_STATUS
+UfsPeimParsingSenseKeys (
+ IN EFI_PEI_BLOCK_IO_MEDIA *Media,
+ IN EFI_SCSI_SENSE_DATA *SenseData,
+ OUT BOOLEAN *NeedRetry
+ )
+{
+ if ((SenseData->Sense_Key == EFI_SCSI_SK_NOT_READY) &&
+ (SenseData->Addnl_Sense_Code == EFI_SCSI_ASC_NO_MEDIA)) {
+ Media->MediaPresent = FALSE;
+ *NeedRetry = FALSE;
+ DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Is No Media\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ((SenseData->Sense_Key == EFI_SCSI_SK_UNIT_ATTENTION) &&
+ (SenseData->Addnl_Sense_Code == EFI_SCSI_ASC_MEDIA_CHANGE)) {
+ *NeedRetry = TRUE;
+ DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Is Media Change\n"));
+ return EFI_SUCCESS;
+ }
+
+ if ((SenseData->Sense_Key == EFI_SCSI_SK_UNIT_ATTENTION) &&
+ (SenseData->Addnl_Sense_Code == EFI_SCSI_ASC_RESET)) {
+ *NeedRetry = TRUE;
+ DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Was Reset Before\n"));
+ return EFI_SUCCESS;
+ }
+
+ if ((SenseData->Sense_Key == EFI_SCSI_SK_MEDIUM_ERROR) ||
+ ((SenseData->Sense_Key == EFI_SCSI_SK_NOT_READY) &&
+ (SenseData->Addnl_Sense_Code == EFI_SCSI_ASC_MEDIA_UPSIDE_DOWN))) {
+ *NeedRetry = FALSE;
+ DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Media Error\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (SenseData->Sense_Key == EFI_SCSI_SK_HARDWARE_ERROR) {
+ *NeedRetry = FALSE;
+ DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Hardware Error\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ((SenseData->Sense_Key == EFI_SCSI_SK_NOT_READY) &&
+ (SenseData->Addnl_Sense_Code == EFI_SCSI_ASC_NOT_READY) &&
+ (SenseData->Addnl_Sense_Code_Qualifier == EFI_SCSI_ASCQ_IN_PROGRESS)) {
+ *NeedRetry = TRUE;
+ DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Was Reset Before\n"));
+ return EFI_SUCCESS;
+ }
+
+ *NeedRetry = FALSE;
+ DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Sense Key = 0x%x ASC = 0x%x!\n",
SenseData->Sense_Key, SenseData->Addnl_Sense_Code));
+ return EFI_DEVICE_ERROR;
+}
+
+
+/**
+ Gets the count of block I/O devices that one specific block driver detects.
+
+ This function is used for getting the count of block I/O devices that one
+ specific block driver detects. To the PEI ATAPI driver, it returns the
number
+ of all the detected ATAPI devices it detects during the enumeration process.
+ To the PEI legacy floppy driver, it returns the number of all the legacy
+ devices it finds during its enumeration process. If no device is detected,
+ then the function will return zero.
+
+ @param[in] PeiServices General-purpose services that are available
+ to every PEIM.
+ @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI
+ instance.
+ @param[out] NumberBlockDevices The number of block I/O devices discovered.
+
+ @retval EFI_SUCCESS The operation performed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsBlockIoPeimGetDeviceNo (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ OUT UINTN *NumberBlockDevices
+ )
+{
+ //
+ // For Ufs device, it has up to 8 normal Luns plus some well-known Luns.
+ // At PEI phase, we will only expose normal Luns to user.
+ // For those disabled Lun, when user try to access it, the operation would
fail.
+ //
+ *NumberBlockDevices = UFS_PEIM_MAX_LUNS;
+ return EFI_SUCCESS;
+}
+
+/**
+ Gets a block device's media information.
+
+ This function will provide the caller with the specified block device's
media
+ information. If the media changes, calling this function will update the
media
+ information accordingly.
+
+ @param[in] PeiServices General-purpose services that are available to
every
+ PEIM
+ @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI
instance.
+ @param[in] DeviceIndex Specifies the block device to which the function
wants
+ to talk. Because the driver that implements Block
I/O
+ PPIs will manage multiple block devices, the PPIs
that
+ want to talk to a single device must specify the
+ device index that was assigned during the
enumeration
+ process. This index is a number from one to
+ NumberBlockDevices.
+ @param[out] MediaInfo The media information of the specified block
media.
+ The caller is responsible for the ownership of
this
+ data structure.
+
+ @par Note:
+ The MediaInfo structure describes an enumeration of possible block
device
+ types. This enumeration exists because no device paths are actually
passed
+ across interfaces that describe the type or class of hardware that is
publishing
+ the block I/O interface. This enumeration will allow for policy decisions
+ in the Recovery PEIM, such as "Try to recover from legacy floppy first,
+ LS-120 second, CD-ROM third." If there are multiple partitions
abstracted
+ by a given device type, they should be reported in ascending order; this
+ order also applies to nested partitions, such as legacy MBR, where the
+ outermost partitions would have precedence in the reporting order. The
+ same logic applies to systems such as IDE that have precedence
relationships
+ like "Master/Slave" or "Primary/Secondary". The master device should be
+ reported first, the slave second.
+
+ @retval EFI_SUCCESS Media information about the specified block
device
+ was obtained successfully.
+ @retval EFI_DEVICE_ERROR Cannot get the media information due to a
hardware
+ error.
+
+**/
+EFI_STATUS
+EFIAPI
+UfsBlockIoPeimGetMediaInfo (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ IN UINTN DeviceIndex,
+ OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo
+ )
+{
+ EFI_STATUS Status;
+ UFS_PEIM_HC_PRIVATE_DATA *Private;
+ EFI_SCSI_SENSE_DATA SenseData;
+ UINT8 SenseDataLength;
+ EFI_SCSI_DISK_CAPACITY_DATA Capacity;
+ EFI_SCSI_DISK_CAPACITY_DATA16 Capacity16;
+ UINTN DataLength;
+ BOOLEAN NeedRetry;
+
+ Private = GET_UFS_PEIM_HC_PRIVATE_DATA_FROM_THIS (This);
+ NeedRetry = TRUE;
+
+ if (DeviceIndex >= UFS_PEIM_MAX_LUNS) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Private->Luns.BitMask & (BIT0 << DeviceIndex)) == 0) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ ZeroMem (&SenseData, sizeof (SenseData));
+ ZeroMem (&Capacity, sizeof (Capacity));
+ ZeroMem (&Capacity16, sizeof (Capacity16));
+ SenseDataLength = sizeof (SenseData);
+ //
+ // First test unit ready
+ //
+ do {
+ Status = UfsPeimTestUnitReady (
+ Private,
+ DeviceIndex,
+ &SenseData,
+ &SenseDataLength
+ );
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+
+ if (SenseDataLength == 0) {
+ continue;
+ }
+
+ Status = UfsPeimParsingSenseKeys (&(Private->Media[DeviceIndex]),
&SenseData, &NeedRetry);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ } while (NeedRetry);
+
+ DataLength = sizeof (EFI_SCSI_DISK_CAPACITY_DATA);
+ SenseDataLength = 0;
+ Status = UfsPeimReadCapacity (Private, DeviceIndex, &Capacity, (UINT32
*)&DataLength, NULL, &SenseDataLength);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ((Capacity.LastLba3 == 0xff) && (Capacity.LastLba2 == 0xff) &&
+ (Capacity.LastLba1 == 0xff) && (Capacity.LastLba0 == 0xff)) {
+ DataLength = sizeof (EFI_SCSI_DISK_CAPACITY_DATA16);
+ SenseDataLength = 0;
+ Status = UfsPeimReadCapacity16 (Private, DeviceIndex, &Capacity16, (UINT32
*)&DataLength, NULL, &SenseDataLength);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ MediaInfo->LastBlock = (Capacity16.LastLba3 << 24) | (Capacity16.LastLba2
<< 16) | (Capacity16.LastLba1 << 8) | Capacity16.LastLba0;
@@ Diff output truncated at 100000 characters. @@
------------------------------------------------------------------------------
One dashboard for servers and applications across Physical-Virtual-Cloud
Widest out-of-the-box monitoring support with 50+ applications
Performance metrics, stats and reports that give you Actionable Insights
Deep dive visibility with transaction tracing using APM Insight.
http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
_______________________________________________
edk2-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-commits