NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows\r
NVM Express specification.\r
\r
- Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.<BR>\r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php.\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
+ Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include <Uefi.h>\r
\r
#include <IndustryStandard/Pci.h>\r
+#include <IndustryStandard/Nvme.h>\r
\r
#include <Protocol/ComponentName.h>\r
#include <Protocol/ComponentName2.h>\r
#include <Protocol/PciIo.h>\r
#include <Protocol/NvmExpressPassthru.h>\r
#include <Protocol/BlockIo.h>\r
+#include <Protocol/BlockIo2.h>\r
#include <Protocol/DiskInfo.h>\r
#include <Protocol/DriverSupportedEfiVersion.h>\r
+#include <Protocol/StorageSecurityCommand.h>\r
+#include <Protocol/ResetNotification.h>\r
\r
#include <Library/BaseLib.h>\r
#include <Library/BaseMemoryLib.h>\r
#include <Library/MemoryAllocationLib.h>\r
#include <Library/UefiBootServicesTableLib.h>\r
#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/ReportStatusCodeLib.h>\r
\r
typedef struct _NVME_CONTROLLER_PRIVATE_DATA NVME_CONTROLLER_PRIVATE_DATA;\r
typedef struct _NVME_DEVICE_PRIVATE_DATA NVME_DEVICE_PRIVATE_DATA;\r
#define NVME_CSQ_SIZE 1 // Number of I/O submission queue entries, which is 0-based\r
#define NVME_CCQ_SIZE 1 // Number of I/O completion queue entries, which is 0-based\r
\r
-#define NVME_MAX_QUEUES 2 // Number of queues supported by the driver\r
+//\r
+// Number of asynchronous I/O submission queue entries, which is 0-based.\r
+// The asynchronous I/O submission queue size is 4kB in total.\r
+//\r
+#define NVME_ASYNC_CSQ_SIZE 63\r
+//\r
+// Number of asynchronous I/O completion queue entries, which is 0-based.\r
+// The asynchronous I/O completion queue size is 4kB in total.\r
+//\r
+#define NVME_ASYNC_CCQ_SIZE 255\r
+\r
+#define NVME_MAX_QUEUES 3 // Number of queues supported by the driver\r
\r
#define NVME_CONTROLLER_ID 0\r
\r
//\r
#define NVME_GENERIC_TIMEOUT EFI_TIMER_PERIOD_SECONDS (5)\r
\r
+//\r
+// Nvme async transfer timer interval, set by experience.\r
+//\r
+#define NVME_HC_ASYNC_TIMER EFI_TIMER_PERIOD_MILLISECONDS (1)\r
+\r
//\r
// Unique signature for private data structure.\r
//\r
//\r
// 6 x 4kB aligned buffers will be carved out of this buffer.\r
// 1st 4kB boundary is the start of the admin submission queue.\r
- // 2nd 4kB boundary is the start of the I/O submission queue #1.\r
- // 3rd 4kB boundary is the start of the admin completion queue.\r
- // 4th 4kB boundary is the start of the I/O completion queue #1.\r
- // 5th 4kB boundary is the start of the first PRP list page.\r
- // 6th 4kB boundary is the start of the second PRP list page.\r
+ // 2nd 4kB boundary is the start of the admin completion queue.\r
+ // 3rd 4kB boundary is the start of I/O submission queue #1.\r
+ // 4th 4kB boundary is the start of I/O completion queue #1.\r
+ // 5th 4kB boundary is the start of I/O submission queue #2.\r
+ // 6th 4kB boundary is the start of I/O completion queue #2.\r
//\r
UINT8 *Buffer;\r
UINT8 *BufferPciAddr;\r
//\r
NVME_SQTDBL SqTdbl[NVME_MAX_QUEUES];\r
NVME_CQHDBL CqHdbl[NVME_MAX_QUEUES];\r
+ UINT16 AsyncSqHead;\r
+\r
+ //\r
+ // Flag to indicate internal IO queue creation.\r
+ //\r
+ BOOLEAN CreateIoQueue;\r
\r
UINT8 Pt[NVME_MAX_QUEUES];\r
UINT16 Cid[NVME_MAX_QUEUES];\r
NVME_CAP Cap;\r
\r
VOID *Mapping;\r
+\r
+ //\r
+ // For Non-blocking operations.\r
+ //\r
+ EFI_EVENT TimerEvent;\r
+ LIST_ENTRY AsyncPassThruQueue;\r
+ LIST_ENTRY UnsubmittedSubtasks;\r
};\r
\r
#define NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU(a) \\r
// Nvme device private data structure\r
//\r
struct _NVME_DEVICE_PRIVATE_DATA {\r
- UINT32 Signature;\r
+ UINT32 Signature;\r
\r
- EFI_HANDLE DeviceHandle;\r
- EFI_HANDLE ControllerHandle;\r
- EFI_HANDLE DriverBindingHandle;\r
+ EFI_HANDLE DeviceHandle;\r
+ EFI_HANDLE ControllerHandle;\r
+ EFI_HANDLE DriverBindingHandle;\r
\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
\r
- EFI_UNICODE_STRING_TABLE *ControllerNameTable;\r
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;\r
\r
- UINT32 NamespaceId;\r
- UINT64 NamespaceUuid;\r
+ UINT32 NamespaceId;\r
+ UINT64 NamespaceUuid;\r
\r
- EFI_BLOCK_IO_MEDIA Media;\r
- EFI_BLOCK_IO_PROTOCOL BlockIo;\r
- EFI_DISK_INFO_PROTOCOL DiskInfo;\r
+ EFI_BLOCK_IO_MEDIA Media;\r
+ EFI_BLOCK_IO_PROTOCOL BlockIo;\r
+ EFI_BLOCK_IO2_PROTOCOL BlockIo2;\r
+ EFI_DISK_INFO_PROTOCOL DiskInfo;\r
+ EFI_STORAGE_SECURITY_COMMAND_PROTOCOL StorageSecurity;\r
\r
- EFI_LBA NumBlocks;\r
+ LIST_ENTRY AsyncQueue;\r
\r
- CHAR16 ModelName[80];\r
- NVME_ADMIN_NAMESPACE_DATA NamespaceData;\r
+ EFI_LBA NumBlocks;\r
\r
- NVME_CONTROLLER_PRIVATE_DATA *Controller;\r
+ CHAR16 ModelName[80];\r
+ NVME_ADMIN_NAMESPACE_DATA NamespaceData;\r
+\r
+ NVME_CONTROLLER_PRIVATE_DATA *Controller;\r
\r
};\r
\r
NVME_DEVICE_PRIVATE_DATA_SIGNATURE \\r
)\r
\r
+#define NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2(a) \\r
+ CR (a, \\r
+ NVME_DEVICE_PRIVATE_DATA, \\r
+ BlockIo2, \\r
+ NVME_DEVICE_PRIVATE_DATA_SIGNATURE \\r
+ )\r
+\r
#define NVME_DEVICE_PRIVATE_DATA_FROM_DISK_INFO(a) \\r
CR (a, \\r
NVME_DEVICE_PRIVATE_DATA, \\r
NVME_DEVICE_PRIVATE_DATA_SIGNATURE \\r
)\r
\r
+#define NVME_DEVICE_PRIVATE_DATA_FROM_STORAGE_SECURITY(a)\\r
+ CR (a, \\r
+ NVME_DEVICE_PRIVATE_DATA, \\r
+ StorageSecurity, \\r
+ NVME_DEVICE_PRIVATE_DATA_SIGNATURE \\r
+ )\r
+\r
+//\r
+// Nvme block I/O 2 request.\r
+//\r
+#define NVME_BLKIO2_REQUEST_SIGNATURE SIGNATURE_32 ('N', 'B', '2', 'R')\r
+\r
+typedef struct {\r
+ UINT32 Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ EFI_BLOCK_IO2_TOKEN *Token;\r
+ UINTN UnsubmittedSubtaskNum;\r
+ BOOLEAN LastSubtaskSubmitted;\r
+ //\r
+ // The queue for Nvme read/write sub-tasks of a BlockIo2 request.\r
+ //\r
+ LIST_ENTRY SubtasksQueue;\r
+} NVME_BLKIO2_REQUEST;\r
+\r
+#define NVME_BLKIO2_REQUEST_FROM_LINK(a) \\r
+ CR (a, NVME_BLKIO2_REQUEST, Link, NVME_BLKIO2_REQUEST_SIGNATURE)\r
+\r
+#define NVME_BLKIO2_SUBTASK_SIGNATURE SIGNATURE_32 ('N', 'B', '2', 'S')\r
+\r
+typedef struct {\r
+ UINT32 Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ BOOLEAN IsLast;\r
+ UINT32 NamespaceId;\r
+ EFI_EVENT Event;\r
+ EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *CommandPacket;\r
+ //\r
+ // The BlockIo2 request this subtask belongs to\r
+ //\r
+ NVME_BLKIO2_REQUEST *BlockIo2Request;\r
+} NVME_BLKIO2_SUBTASK;\r
+\r
+#define NVME_BLKIO2_SUBTASK_FROM_LINK(a) \\r
+ CR (a, NVME_BLKIO2_SUBTASK, Link, NVME_BLKIO2_SUBTASK_SIGNATURE)\r
+\r
+//\r
+// Nvme asynchronous passthru request.\r
+//\r
+#define NVME_PASS_THRU_ASYNC_REQ_SIG SIGNATURE_32 ('N', 'P', 'A', 'R')\r
+\r
+typedef struct {\r
+ UINT32 Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet;\r
+ UINT16 CommandId;\r
+ VOID *MapPrpList;\r
+ UINTN PrpListNo;\r
+ VOID *PrpListHost;\r
+ VOID *MapData;\r
+ VOID *MapMeta;\r
+ EFI_EVENT CallerEvent;\r
+} NVME_PASS_THRU_ASYNC_REQ;\r
+\r
+#define NVME_PASS_THRU_ASYNC_REQ_FROM_THIS(a) \\r
+ CR (a, \\r
+ NVME_PASS_THRU_ASYNC_REQ, \\r
+ Link, \\r
+ NVME_PASS_THRU_ASYNC_REQ_SIG \\r
+ )\r
+\r
/**\r
Retrieves a Unicode string that is the user readable name of the driver.\r
\r
IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath\r
);\r
\r
+/**\r
+ Dump the execution status from a given completion queue entry.\r
+\r
+ @param[in] Cq A pointer to the NVME_CQ item.\r
+\r
+**/\r
+VOID\r
+NvmeDumpStatus (\r
+ IN NVME_CQ *Cq\r
+ );\r
+\r
+/**\r
+ Register the shutdown notification through the ResetNotification protocol.\r
+\r
+ Register the shutdown notification when mNvmeControllerNumber increased from 0 to 1.\r
+**/\r
+VOID\r
+NvmeRegisterShutdownNotification (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Unregister the shutdown notification through the ResetNotification protocol.\r
+\r
+ Unregister the shutdown notification when mNvmeControllerNumber decreased from 1 to 0.\r
+**/\r
+VOID\r
+NvmeUnregisterShutdownNotification (\r
+ VOID\r
+ );\r
+\r
#endif\r