2 NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows
3 NVM Express specification.
5 (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
6 Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include "NvmExpress.h"
14 Dump the execution status from a given completion queue entry.
16 @param[in] Cq A pointer to the NVME_CQ item.
24 DEBUG ((DEBUG_VERBOSE
, "Dump NVMe Completion Entry Status from [0x%x]:\n", Cq
));
26 DEBUG ((DEBUG_VERBOSE
, " SQ Identifier : [0x%x], Phase Tag : [%d], Cmd Identifier : [0x%x]\n", Cq
->Sqid
, Cq
->Pt
, Cq
->Cid
));
28 DEBUG ((DEBUG_VERBOSE
, " NVMe Cmd Execution Result - "));
34 DEBUG ((DEBUG_VERBOSE
, "Successful Completion\n"));
37 DEBUG ((DEBUG_VERBOSE
, "Invalid Command Opcode\n"));
40 DEBUG ((DEBUG_VERBOSE
, "Invalid Field in Command\n"));
43 DEBUG ((DEBUG_VERBOSE
, "Command ID Conflict\n"));
46 DEBUG ((DEBUG_VERBOSE
, "Data Transfer Error\n"));
49 DEBUG ((DEBUG_VERBOSE
, "Commands Aborted due to Power Loss Notification\n"));
52 DEBUG ((DEBUG_VERBOSE
, "Internal Device Error\n"));
55 DEBUG ((DEBUG_VERBOSE
, "Command Abort Requested\n"));
58 DEBUG ((DEBUG_VERBOSE
, "Command Aborted due to SQ Deletion\n"));
61 DEBUG ((DEBUG_VERBOSE
, "Command Aborted due to Failed Fused Command\n"));
64 DEBUG ((DEBUG_VERBOSE
, "Command Aborted due to Missing Fused Command\n"));
67 DEBUG ((DEBUG_VERBOSE
, "Invalid Namespace or Format\n"));
70 DEBUG ((DEBUG_VERBOSE
, "Command Sequence Error\n"));
73 DEBUG ((DEBUG_VERBOSE
, "Invalid SGL Last Segment Descriptor\n"));
76 DEBUG ((DEBUG_VERBOSE
, "Invalid Number of SGL Descriptors\n"));
79 DEBUG ((DEBUG_VERBOSE
, "Data SGL Length Invalid\n"));
82 DEBUG ((DEBUG_VERBOSE
, "Metadata SGL Length Invalid\n"));
85 DEBUG ((DEBUG_VERBOSE
, "SGL Descriptor Type Invalid\n"));
88 DEBUG ((DEBUG_VERBOSE
, "LBA Out of Range\n"));
91 DEBUG ((DEBUG_VERBOSE
, "Capacity Exceeded\n"));
94 DEBUG ((DEBUG_VERBOSE
, "Namespace Not Ready\n"));
97 DEBUG ((DEBUG_VERBOSE
, "Reservation Conflict\n"));
106 DEBUG ((DEBUG_VERBOSE
, "Completion Queue Invalid\n"));
109 DEBUG ((DEBUG_VERBOSE
, "Invalid Queue Identifier\n"));
112 DEBUG ((DEBUG_VERBOSE
, "Maximum Queue Size Exceeded\n"));
115 DEBUG ((DEBUG_VERBOSE
, "Abort Command Limit Exceeded\n"));
118 DEBUG ((DEBUG_VERBOSE
, "Asynchronous Event Request Limit Exceeded\n"));
121 DEBUG ((DEBUG_VERBOSE
, "Invalid Firmware Slot\n"));
124 DEBUG ((DEBUG_VERBOSE
, "Invalid Firmware Image\n"));
127 DEBUG ((DEBUG_VERBOSE
, "Invalid Interrupt Vector\n"));
130 DEBUG ((DEBUG_VERBOSE
, "Invalid Log Page\n"));
133 DEBUG ((DEBUG_VERBOSE
, "Invalid Format\n"));
136 DEBUG ((DEBUG_VERBOSE
, "Firmware Application Requires Conventional Reset\n"));
139 DEBUG ((DEBUG_VERBOSE
, "Invalid Queue Deletion\n"));
142 DEBUG ((DEBUG_VERBOSE
, "Feature Identifier Not Saveable\n"));
145 DEBUG ((DEBUG_VERBOSE
, "Feature Not Changeable\n"));
148 DEBUG ((DEBUG_VERBOSE
, "Feature Not Namespace Specific\n"));
151 DEBUG ((DEBUG_VERBOSE
, "Firmware Application Requires NVM Subsystem Reset\n"));
154 DEBUG ((DEBUG_VERBOSE
, "Conflicting Attributes\n"));
157 DEBUG ((DEBUG_VERBOSE
, "Invalid Protection Information\n"));
160 DEBUG ((DEBUG_VERBOSE
, "Attempted Write to Read Only Range\n"));
169 DEBUG ((DEBUG_VERBOSE
, "Write Fault\n"));
172 DEBUG ((DEBUG_VERBOSE
, "Unrecovered Read Error\n"));
175 DEBUG ((DEBUG_VERBOSE
, "End-to-end Guard Check Error\n"));
178 DEBUG ((DEBUG_VERBOSE
, "End-to-end Application Tag Check Error\n"));
181 DEBUG ((DEBUG_VERBOSE
, "End-to-end Reference Tag Check Error\n"));
184 DEBUG ((DEBUG_VERBOSE
, "Compare Failure\n"));
187 DEBUG ((DEBUG_VERBOSE
, "Access Denied\n"));
199 Create PRP lists for data transfer which is larger than 2 memory pages.
200 Note here we calcuate the number of required PRP lists and allocate them at one time.
202 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
203 @param[in] PhysicalAddr The physical base address of data buffer.
204 @param[in] Pages The number of pages to be transfered.
205 @param[out] PrpListHost The host base address of PRP lists.
206 @param[in,out] PrpListNo The number of PRP List.
207 @param[out] Mapping The mapping value returned from PciIo.Map().
209 @retval The pointer to the first PRP List of the PRP lists.
214 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
215 IN EFI_PHYSICAL_ADDRESS PhysicalAddr
,
217 OUT VOID
**PrpListHost
,
218 IN OUT UINTN
*PrpListNo
,
227 EFI_PHYSICAL_ADDRESS PrpListPhyAddr
;
232 // The number of Prp Entry in a memory page.
234 PrpEntryNo
= EFI_PAGE_SIZE
/ sizeof (UINT64
);
237 // Calculate total PrpList number.
239 *PrpListNo
= (UINTN
)DivU64x64Remainder ((UINT64
)Pages
, (UINT64
)PrpEntryNo
- 1, &Remainder
);
240 if (*PrpListNo
== 0) {
242 } else if ((Remainder
!= 0) && (Remainder
!= 1)) {
244 } else if (Remainder
== 1) {
245 Remainder
= PrpEntryNo
;
246 } else if (Remainder
== 0) {
247 Remainder
= PrpEntryNo
- 1;
250 Status
= PciIo
->AllocateBuffer (
259 if (EFI_ERROR (Status
)) {
263 Bytes
= EFI_PAGES_TO_SIZE (*PrpListNo
);
264 Status
= PciIo
->Map (
266 EfiPciIoOperationBusMasterCommonBuffer
,
273 if (EFI_ERROR (Status
) || (Bytes
!= EFI_PAGES_TO_SIZE (*PrpListNo
))) {
274 DEBUG ((DEBUG_ERROR
, "NvmeCreatePrpList: create PrpList failure!\n"));
279 // Fill all PRP lists except of last one.
281 ZeroMem (*PrpListHost
, Bytes
);
282 for (PrpListIndex
= 0; PrpListIndex
< *PrpListNo
- 1; ++PrpListIndex
) {
283 PrpListBase
= *(UINT64
*)PrpListHost
+ PrpListIndex
* EFI_PAGE_SIZE
;
285 for (PrpEntryIndex
= 0; PrpEntryIndex
< PrpEntryNo
; ++PrpEntryIndex
) {
286 if (PrpEntryIndex
!= PrpEntryNo
- 1) {
288 // Fill all PRP entries except of last one.
290 *((UINT64
*)(UINTN
)PrpListBase
+ PrpEntryIndex
) = PhysicalAddr
;
291 PhysicalAddr
+= EFI_PAGE_SIZE
;
294 // Fill last PRP entries with next PRP List pointer.
296 *((UINT64
*)(UINTN
)PrpListBase
+ PrpEntryIndex
) = PrpListPhyAddr
+ (PrpListIndex
+ 1) * EFI_PAGE_SIZE
;
302 // Fill last PRP list.
304 PrpListBase
= *(UINT64
*)PrpListHost
+ PrpListIndex
* EFI_PAGE_SIZE
;
305 for (PrpEntryIndex
= 0; PrpEntryIndex
< Remainder
; ++PrpEntryIndex
) {
306 *((UINT64
*)(UINTN
)PrpListBase
+ PrpEntryIndex
) = PhysicalAddr
;
307 PhysicalAddr
+= EFI_PAGE_SIZE
;
310 return (VOID
*)(UINTN
)PrpListPhyAddr
;
313 PciIo
->FreeBuffer (PciIo
, *PrpListNo
, *PrpListHost
);
318 Aborts the asynchronous PassThru requests.
320 @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA
323 @retval EFI_SUCCESS The asynchronous PassThru requests have been aborted.
324 @return EFI_DEVICE_ERROR Fail to abort all the asynchronous PassThru requests.
328 AbortAsyncPassThruTasks (
329 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
332 EFI_PCI_IO_PROTOCOL
*PciIo
;
334 LIST_ENTRY
*NextLink
;
335 NVME_BLKIO2_SUBTASK
*Subtask
;
336 NVME_BLKIO2_REQUEST
*BlkIo2Request
;
337 NVME_PASS_THRU_ASYNC_REQ
*AsyncRequest
;
338 EFI_BLOCK_IO2_TOKEN
*Token
;
342 PciIo
= Private
->PciIo
;
343 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
346 // Cancel the unsubmitted subtasks.
348 for (Link
= GetFirstNode (&Private
->UnsubmittedSubtasks
);
349 !IsNull (&Private
->UnsubmittedSubtasks
, Link
);
352 NextLink
= GetNextNode (&Private
->UnsubmittedSubtasks
, Link
);
353 Subtask
= NVME_BLKIO2_SUBTASK_FROM_LINK (Link
);
354 BlkIo2Request
= Subtask
->BlockIo2Request
;
355 Token
= BlkIo2Request
->Token
;
357 BlkIo2Request
->UnsubmittedSubtaskNum
--;
358 if (Subtask
->IsLast
) {
359 BlkIo2Request
->LastSubtaskSubmitted
= TRUE
;
362 Token
->TransactionStatus
= EFI_ABORTED
;
364 RemoveEntryList (Link
);
365 InsertTailList (&BlkIo2Request
->SubtasksQueue
, Link
);
366 gBS
->SignalEvent (Subtask
->Event
);
370 // Cleanup the resources for the asynchronous PassThru requests.
372 for (Link
= GetFirstNode (&Private
->AsyncPassThruQueue
);
373 !IsNull (&Private
->AsyncPassThruQueue
, Link
);
376 NextLink
= GetNextNode (&Private
->AsyncPassThruQueue
, Link
);
377 AsyncRequest
= NVME_PASS_THRU_ASYNC_REQ_FROM_THIS (Link
);
379 if (AsyncRequest
->MapData
!= NULL
) {
380 PciIo
->Unmap (PciIo
, AsyncRequest
->MapData
);
383 if (AsyncRequest
->MapMeta
!= NULL
) {
384 PciIo
->Unmap (PciIo
, AsyncRequest
->MapMeta
);
387 if (AsyncRequest
->MapPrpList
!= NULL
) {
388 PciIo
->Unmap (PciIo
, AsyncRequest
->MapPrpList
);
391 if (AsyncRequest
->PrpListHost
!= NULL
) {
394 AsyncRequest
->PrpListNo
,
395 AsyncRequest
->PrpListHost
399 RemoveEntryList (Link
);
400 gBS
->SignalEvent (AsyncRequest
->CallerEvent
);
401 FreePool (AsyncRequest
);
404 if (IsListEmpty (&Private
->AsyncPassThruQueue
) &&
405 IsListEmpty (&Private
->UnsubmittedSubtasks
))
407 Status
= EFI_SUCCESS
;
409 Status
= EFI_DEVICE_ERROR
;
412 gBS
->RestoreTPL (OldTpl
);
418 Sends an NVM Express Command Packet to an NVM Express controller or namespace. This function supports
419 both blocking I/O and non-blocking I/O. The blocking I/O functionality is required, and the non-blocking
420 I/O functionality is optional.
423 @param[in] This A pointer to the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL instance.
424 @param[in] NamespaceId A 32 bit namespace ID as defined in the NVMe specification to which the NVM Express Command
425 Packet will be sent. A value of 0 denotes the NVM Express controller, a value of all 0xFF's
426 (all bytes are 0xFF) in the namespace ID specifies that the command packet should be sent to
427 all valid namespaces.
428 @param[in,out] Packet A pointer to the NVM Express Command Packet.
429 @param[in] Event If non-blocking I/O is not supported then Event is ignored, and blocking I/O is performed.
430 If Event is NULL, then blocking I/O is performed. If Event is not NULL and non-blocking I/O
431 is supported, then non-blocking I/O is performed, and Event will be signaled when the NVM
432 Express Command Packet completes.
434 @retval EFI_SUCCESS The NVM Express Command Packet was sent by the host. TransferLength bytes were transferred
435 to, or from DataBuffer.
436 @retval EFI_BAD_BUFFER_SIZE The NVM Express Command Packet was not executed. The number of bytes that could be transferred
437 is returned in TransferLength.
438 @retval EFI_NOT_READY The NVM Express Command Packet could not be sent because the controller is not ready. The caller
439 may retry again later.
440 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the NVM Express Command Packet.
441 @retval EFI_INVALID_PARAMETER NamespaceId or the contents of EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET are invalid. The NVM
442 Express Command Packet was not sent, so no additional status information is available.
443 @retval EFI_UNSUPPORTED The command described by the NVM Express Command Packet is not supported by the NVM Express
444 controller. The NVM Express Command Packet was not sent so no additional status information
446 @retval EFI_TIMEOUT A timeout occurred while waiting for the NVM Express Command Packet to execute.
452 IN EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL
*This
,
453 IN UINT32 NamespaceId
,
454 IN OUT EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
*Packet
,
455 IN EFI_EVENT Event OPTIONAL
458 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
460 EFI_STATUS PreviousStatus
;
461 EFI_PCI_IO_PROTOCOL
*PciIo
;
468 EFI_EVENT TimerEvent
;
469 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
470 EFI_PHYSICAL_ADDRESS PhyAddr
;
482 NVME_PASS_THRU_ASYNC_REQ
*AsyncRequest
;
486 // check the data fields in Packet parameter.
488 if ((This
== NULL
) || (Packet
== NULL
)) {
489 return EFI_INVALID_PARAMETER
;
492 if ((Packet
->NvmeCmd
== NULL
) || (Packet
->NvmeCompletion
== NULL
)) {
493 return EFI_INVALID_PARAMETER
;
496 if ((Packet
->QueueType
!= NVME_ADMIN_QUEUE
) && (Packet
->QueueType
!= NVME_IO_QUEUE
)) {
497 return EFI_INVALID_PARAMETER
;
501 // 'Attributes' with neither EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL nor
502 // EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL set is an illegal
505 Attributes
= This
->Mode
->Attributes
;
506 if ((Attributes
& (EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL
|
507 EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL
)) == 0)
509 return EFI_INVALID_PARAMETER
;
513 // Buffer alignment check for TransferBuffer & MetadataBuffer.
515 IoAlign
= This
->Mode
->IoAlign
;
516 if ((IoAlign
> 0) && (((UINTN
)Packet
->TransferBuffer
& (IoAlign
- 1)) != 0)) {
517 return EFI_INVALID_PARAMETER
;
520 if ((IoAlign
> 0) && (((UINTN
)Packet
->MetadataBuffer
& (IoAlign
- 1)) != 0)) {
521 return EFI_INVALID_PARAMETER
;
524 Private
= NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (This
);
527 // Check NamespaceId is valid or not.
529 if ((NamespaceId
> Private
->ControllerData
->Nn
) &&
530 (NamespaceId
!= (UINT32
)-1))
532 return EFI_INVALID_PARAMETER
;
536 // Check whether TransferLength exceeds the maximum data transfer size.
538 if (Private
->ControllerData
->Mdts
!= 0) {
539 MaxTransLen
= (1 << (Private
->ControllerData
->Mdts
)) *
540 (1 << (Private
->Cap
.Mpsmin
+ 12));
541 if (Packet
->TransferLength
> MaxTransLen
) {
542 Packet
->TransferLength
= MaxTransLen
;
543 return EFI_BAD_BUFFER_SIZE
;
547 PciIo
= Private
->PciIo
;
555 Status
= EFI_SUCCESS
;
556 QueueSize
= MIN (NVME_ASYNC_CSQ_SIZE
, Private
->Cap
.Mqes
) + 1;
558 if (Packet
->QueueType
== NVME_ADMIN_QUEUE
) {
567 // Submission queue full check.
569 if ((Private
->SqTdbl
[QueueId
].Sqt
+ 1) % QueueSize
==
570 Private
->AsyncSqHead
)
572 return EFI_NOT_READY
;
577 Sq
= Private
->SqBuffer
[QueueId
] + Private
->SqTdbl
[QueueId
].Sqt
;
578 Cq
= Private
->CqBuffer
[QueueId
] + Private
->CqHdbl
[QueueId
].Cqh
;
580 if (Packet
->NvmeCmd
->Nsid
!= NamespaceId
) {
581 return EFI_INVALID_PARAMETER
;
584 ZeroMem (Sq
, sizeof (NVME_SQ
));
585 Sq
->Opc
= (UINT8
)Packet
->NvmeCmd
->Cdw0
.Opcode
;
586 Sq
->Fuse
= (UINT8
)Packet
->NvmeCmd
->Cdw0
.FusedOperation
;
587 Sq
->Cid
= Private
->Cid
[QueueId
]++;
588 Sq
->Nsid
= Packet
->NvmeCmd
->Nsid
;
591 // Currently we only support PRP for data transfer, SGL is NOT supported.
593 ASSERT (Sq
->Psdt
== 0);
595 DEBUG ((DEBUG_ERROR
, "NvmExpressPassThru: doesn't support SGL mechanism\n"));
596 return EFI_UNSUPPORTED
;
599 Sq
->Prp
[0] = (UINT64
)(UINTN
)Packet
->TransferBuffer
;
600 if ((Packet
->QueueType
== NVME_ADMIN_QUEUE
) &&
601 ((Sq
->Opc
== NVME_ADMIN_CRIOCQ_CMD
) || (Sq
->Opc
== NVME_ADMIN_CRIOSQ_CMD
)))
604 // Currently, we only use the IO Completion/Submission queues created internally
605 // by this driver during controller initialization. Any other IO queues created
606 // will not be consumed here. The value is little to accept external IO queue
607 // creation requests, so here we will return EFI_UNSUPPORTED for external IO
608 // queue creation request.
610 if (!Private
->CreateIoQueue
) {
611 DEBUG ((DEBUG_ERROR
, "NvmExpressPassThru: Does not support external IO queues creation request.\n"));
612 return EFI_UNSUPPORTED
;
614 } else if ((Sq
->Opc
& (BIT0
| BIT1
)) != 0) {
616 // If the NVMe cmd has data in or out, then mapping the user buffer to the PCI controller specific addresses.
618 if (((Packet
->TransferLength
!= 0) && (Packet
->TransferBuffer
== NULL
)) ||
619 ((Packet
->TransferLength
== 0) && (Packet
->TransferBuffer
!= NULL
)))
621 return EFI_INVALID_PARAMETER
;
624 if ((Sq
->Opc
& BIT0
) != 0) {
625 Flag
= EfiPciIoOperationBusMasterRead
;
627 Flag
= EfiPciIoOperationBusMasterWrite
;
630 if ((Packet
->TransferLength
!= 0) && (Packet
->TransferBuffer
!= NULL
)) {
631 MapLength
= Packet
->TransferLength
;
632 Status
= PciIo
->Map (
635 Packet
->TransferBuffer
,
640 if (EFI_ERROR (Status
) || (Packet
->TransferLength
!= MapLength
)) {
641 return EFI_OUT_OF_RESOURCES
;
644 Sq
->Prp
[0] = PhyAddr
;
648 if ((Packet
->MetadataLength
!= 0) && (Packet
->MetadataBuffer
!= NULL
)) {
649 MapLength
= Packet
->MetadataLength
;
650 Status
= PciIo
->Map (
653 Packet
->MetadataBuffer
,
658 if (EFI_ERROR (Status
) || (Packet
->MetadataLength
!= MapLength
)) {
664 return EFI_OUT_OF_RESOURCES
;
672 // If the buffer size spans more than two memory pages (page size as defined in CC.Mps),
673 // then build a PRP list in the second PRP submission queue entry.
675 Offset
= ((UINT16
)Sq
->Prp
[0]) & (EFI_PAGE_SIZE
- 1);
676 Bytes
= Packet
->TransferLength
;
678 if ((Offset
+ Bytes
) > (EFI_PAGE_SIZE
* 2)) {
680 // Create PrpList for remaining data buffer.
682 PhyAddr
= (Sq
->Prp
[0] + EFI_PAGE_SIZE
) & ~(EFI_PAGE_SIZE
- 1);
683 Prp
= NvmeCreatePrpList (PciIo
, PhyAddr
, EFI_SIZE_TO_PAGES (Offset
+ Bytes
) - 1, &PrpListHost
, &PrpListNo
, &MapPrpList
);
685 Status
= EFI_OUT_OF_RESOURCES
;
689 Sq
->Prp
[1] = (UINT64
)(UINTN
)Prp
;
690 } else if ((Offset
+ Bytes
) > EFI_PAGE_SIZE
) {
691 Sq
->Prp
[1] = (Sq
->Prp
[0] + EFI_PAGE_SIZE
) & ~(EFI_PAGE_SIZE
- 1);
694 if (Packet
->NvmeCmd
->Flags
& CDW2_VALID
) {
695 Sq
->Rsvd2
= (UINT64
)Packet
->NvmeCmd
->Cdw2
;
698 if (Packet
->NvmeCmd
->Flags
& CDW3_VALID
) {
699 Sq
->Rsvd2
|= LShiftU64 ((UINT64
)Packet
->NvmeCmd
->Cdw3
, 32);
702 if (Packet
->NvmeCmd
->Flags
& CDW10_VALID
) {
703 Sq
->Payload
.Raw
.Cdw10
= Packet
->NvmeCmd
->Cdw10
;
706 if (Packet
->NvmeCmd
->Flags
& CDW11_VALID
) {
707 Sq
->Payload
.Raw
.Cdw11
= Packet
->NvmeCmd
->Cdw11
;
710 if (Packet
->NvmeCmd
->Flags
& CDW12_VALID
) {
711 Sq
->Payload
.Raw
.Cdw12
= Packet
->NvmeCmd
->Cdw12
;
714 if (Packet
->NvmeCmd
->Flags
& CDW13_VALID
) {
715 Sq
->Payload
.Raw
.Cdw13
= Packet
->NvmeCmd
->Cdw13
;
718 if (Packet
->NvmeCmd
->Flags
& CDW14_VALID
) {
719 Sq
->Payload
.Raw
.Cdw14
= Packet
->NvmeCmd
->Cdw14
;
722 if (Packet
->NvmeCmd
->Flags
& CDW15_VALID
) {
723 Sq
->Payload
.Raw
.Cdw15
= Packet
->NvmeCmd
->Cdw15
;
727 // Ring the submission queue doorbell.
729 if ((Event
!= NULL
) && (QueueId
!= 0)) {
730 Private
->SqTdbl
[QueueId
].Sqt
=
731 (Private
->SqTdbl
[QueueId
].Sqt
+ 1) % QueueSize
;
733 Private
->SqTdbl
[QueueId
].Sqt
^= 1;
736 Data
= ReadUnaligned32 ((UINT32
*)&Private
->SqTdbl
[QueueId
]);
737 Status
= PciIo
->Mem
.Write (
741 NVME_SQTDBL_OFFSET (QueueId
, Private
->Cap
.Dstrd
),
746 if (EFI_ERROR (Status
)) {
751 // For non-blocking requests, return directly if the command is placed
752 // in the submission queue.
754 if ((Event
!= NULL
) && (QueueId
!= 0)) {
755 AsyncRequest
= AllocateZeroPool (sizeof (NVME_PASS_THRU_ASYNC_REQ
));
756 if (AsyncRequest
== NULL
) {
757 Status
= EFI_DEVICE_ERROR
;
761 AsyncRequest
->Signature
= NVME_PASS_THRU_ASYNC_REQ_SIG
;
762 AsyncRequest
->Packet
= Packet
;
763 AsyncRequest
->CommandId
= Sq
->Cid
;
764 AsyncRequest
->CallerEvent
= Event
;
765 AsyncRequest
->MapData
= MapData
;
766 AsyncRequest
->MapMeta
= MapMeta
;
767 AsyncRequest
->MapPrpList
= MapPrpList
;
768 AsyncRequest
->PrpListNo
= PrpListNo
;
769 AsyncRequest
->PrpListHost
= PrpListHost
;
771 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
772 InsertTailList (&Private
->AsyncPassThruQueue
, &AsyncRequest
->Link
);
773 gBS
->RestoreTPL (OldTpl
);
778 Status
= gBS
->CreateEvent (
785 if (EFI_ERROR (Status
)) {
789 Status
= gBS
->SetTimer (TimerEvent
, TimerRelative
, Packet
->CommandTimeout
);
791 if (EFI_ERROR (Status
)) {
796 // Wait for completion queue to get filled in.
798 Status
= EFI_TIMEOUT
;
799 while (EFI_ERROR (gBS
->CheckEvent (TimerEvent
))) {
800 if (Cq
->Pt
!= Private
->Pt
[QueueId
]) {
801 Status
= EFI_SUCCESS
;
807 // Check the NVMe cmd execution result
809 if (Status
!= EFI_TIMEOUT
) {
810 if ((Cq
->Sct
== 0) && (Cq
->Sc
== 0)) {
811 Status
= EFI_SUCCESS
;
813 Status
= EFI_DEVICE_ERROR
;
815 // Dump every completion entry status for debugging.
823 // Copy the Respose Queue entry for this command to the callers response buffer
825 CopyMem (Packet
->NvmeCompletion
, Cq
, sizeof (EFI_NVM_EXPRESS_COMPLETION
));
828 // Timeout occurs for an NVMe command. Reset the controller to abort the
829 // outstanding commands.
831 DEBUG ((DEBUG_ERROR
, "NvmExpressPassThru: Timeout occurs for an NVMe command.\n"));
834 // Disable the timer to trigger the process of async transfers temporarily.
836 Status
= gBS
->SetTimer (Private
->TimerEvent
, TimerCancel
, 0);
837 if (EFI_ERROR (Status
)) {
842 // Reset the NVMe controller.
844 Status
= NvmeControllerInit (Private
);
845 if (!EFI_ERROR (Status
)) {
846 Status
= AbortAsyncPassThruTasks (Private
);
847 if (!EFI_ERROR (Status
)) {
849 // Re-enable the timer to trigger the process of async transfers.
851 Status
= gBS
->SetTimer (Private
->TimerEvent
, TimerPeriodic
, NVME_HC_ASYNC_TIMER
);
852 if (!EFI_ERROR (Status
)) {
854 // Return EFI_TIMEOUT to indicate a timeout occurs for NVMe PassThru command.
856 Status
= EFI_TIMEOUT
;
860 Status
= EFI_DEVICE_ERROR
;
866 if ((Private
->CqHdbl
[QueueId
].Cqh
^= 1) == 0) {
867 Private
->Pt
[QueueId
] ^= 1;
870 Data
= ReadUnaligned32 ((UINT32
*)&Private
->CqHdbl
[QueueId
]);
871 PreviousStatus
= Status
;
872 Status
= PciIo
->Mem
.Write (
876 NVME_CQHDBL_OFFSET (QueueId
, Private
->Cap
.Dstrd
),
880 // The return status of PciIo->Mem.Write should not override
881 // previous status if previous status contains error.
882 Status
= EFI_ERROR (PreviousStatus
) ? PreviousStatus
: Status
;
885 // For now, the code does not support the non-blocking feature for admin queue.
886 // If Event is not NULL for admin queue, signal the caller's event here.
889 ASSERT (QueueId
== 0);
890 gBS
->SignalEvent (Event
);
894 if (MapData
!= NULL
) {
901 if (MapMeta
!= NULL
) {
908 if (MapPrpList
!= NULL
) {
916 PciIo
->FreeBuffer (PciIo
, PrpListNo
, PrpListHost
);
919 if (TimerEvent
!= NULL
) {
920 gBS
->CloseEvent (TimerEvent
);
927 Used to retrieve the next namespace ID for this NVM Express controller.
929 The EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL.GetNextNamespace() function retrieves the next valid
930 namespace ID on this NVM Express controller.
932 If on input the value pointed to by NamespaceId is 0xFFFFFFFF, then the first valid namespace
933 ID defined on the NVM Express controller is returned in the location pointed to by NamespaceId
934 and a status of EFI_SUCCESS is returned.
936 If on input the value pointed to by NamespaceId is an invalid namespace ID other than 0xFFFFFFFF,
937 then EFI_INVALID_PARAMETER is returned.
939 If on input the value pointed to by NamespaceId is a valid namespace ID, then the next valid
940 namespace ID on the NVM Express controller is returned in the location pointed to by NamespaceId,
941 and EFI_SUCCESS is returned.
943 If the value pointed to by NamespaceId is the namespace ID of the last namespace on the NVM
944 Express controller, then EFI_NOT_FOUND is returned.
946 @param[in] This A pointer to the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL instance.
947 @param[in,out] NamespaceId On input, a pointer to a legal NamespaceId for an NVM Express
948 namespace present on the NVM Express controller. On output, a
949 pointer to the next NamespaceId of an NVM Express namespace on
950 an NVM Express controller. An input value of 0xFFFFFFFF retrieves
951 the first NamespaceId for an NVM Express namespace present on an
952 NVM Express controller.
954 @retval EFI_SUCCESS The Namespace ID of the next Namespace was returned.
955 @retval EFI_NOT_FOUND There are no more namespaces defined on this controller.
956 @retval EFI_INVALID_PARAMETER NamespaceId is an invalid value other than 0xFFFFFFFF.
961 NvmExpressGetNextNamespace (
962 IN EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL
*This
,
963 IN OUT UINT32
*NamespaceId
966 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
967 NVME_ADMIN_NAMESPACE_DATA
*NamespaceData
;
968 UINT32 NextNamespaceId
;
971 if ((This
== NULL
) || (NamespaceId
== NULL
)) {
972 return EFI_INVALID_PARAMETER
;
975 NamespaceData
= NULL
;
976 Status
= EFI_NOT_FOUND
;
978 Private
= NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (This
);
980 // If the NamespaceId input value is 0xFFFFFFFF, then get the first valid namespace ID
982 if (*NamespaceId
== 0xFFFFFFFF) {
984 // Start with the first namespace ID
988 // Allocate buffer for Identify Namespace data.
990 NamespaceData
= (NVME_ADMIN_NAMESPACE_DATA
*)AllocateZeroPool (sizeof (NVME_ADMIN_NAMESPACE_DATA
));
992 if (NamespaceData
== NULL
) {
993 return EFI_NOT_FOUND
;
996 Status
= NvmeIdentifyNamespace (Private
, NextNamespaceId
, NamespaceData
);
997 if (EFI_ERROR (Status
)) {
1001 *NamespaceId
= NextNamespaceId
;
1003 if (*NamespaceId
> Private
->ControllerData
->Nn
) {
1004 return EFI_INVALID_PARAMETER
;
1007 NextNamespaceId
= *NamespaceId
+ 1;
1008 if (NextNamespaceId
> Private
->ControllerData
->Nn
) {
1009 return EFI_NOT_FOUND
;
1013 // Allocate buffer for Identify Namespace data.
1015 NamespaceData
= (NVME_ADMIN_NAMESPACE_DATA
*)AllocateZeroPool (sizeof (NVME_ADMIN_NAMESPACE_DATA
));
1016 if (NamespaceData
== NULL
) {
1017 return EFI_NOT_FOUND
;
1020 Status
= NvmeIdentifyNamespace (Private
, NextNamespaceId
, NamespaceData
);
1021 if (EFI_ERROR (Status
)) {
1025 *NamespaceId
= NextNamespaceId
;
1029 if (NamespaceData
!= NULL
) {
1030 FreePool (NamespaceData
);
1037 Used to translate a device path node to a namespace ID.
1039 The EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL.GetNamespace() function determines the namespace ID associated with the
1040 namespace described by DevicePath.
1042 If DevicePath is a device path node type that the NVM Express Pass Thru driver supports, then the NVM Express
1043 Pass Thru driver will attempt to translate the contents DevicePath into a namespace ID.
1045 If this translation is successful, then that namespace ID is returned in NamespaceId, and EFI_SUCCESS is returned
1047 @param[in] This A pointer to the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL instance.
1048 @param[in] DevicePath A pointer to the device path node that describes an NVM Express namespace on
1049 the NVM Express controller.
1050 @param[out] NamespaceId The NVM Express namespace ID contained in the device path node.
1052 @retval EFI_SUCCESS DevicePath was successfully translated to NamespaceId.
1053 @retval EFI_INVALID_PARAMETER If DevicePath or NamespaceId are NULL, then EFI_INVALID_PARAMETER is returned.
1054 @retval EFI_UNSUPPORTED If DevicePath is not a device path node type that the NVM Express Pass Thru driver
1055 supports, then EFI_UNSUPPORTED is returned.
1056 @retval EFI_NOT_FOUND If DevicePath is a device path node type that the NVM Express Pass Thru driver
1057 supports, but there is not a valid translation from DevicePath to a namespace ID,
1058 then EFI_NOT_FOUND is returned.
1062 NvmExpressGetNamespace (
1063 IN EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL
*This
,
1064 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1065 OUT UINT32
*NamespaceId
1068 NVME_NAMESPACE_DEVICE_PATH
*Node
;
1069 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
1071 if ((This
== NULL
) || (DevicePath
== NULL
) || (NamespaceId
== NULL
)) {
1072 return EFI_INVALID_PARAMETER
;
1075 if (DevicePath
->Type
!= MESSAGING_DEVICE_PATH
) {
1076 return EFI_UNSUPPORTED
;
1079 Node
= (NVME_NAMESPACE_DEVICE_PATH
*)DevicePath
;
1080 Private
= NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (This
);
1082 if (DevicePath
->SubType
== MSG_NVME_NAMESPACE_DP
) {
1083 if (DevicePathNodeLength (DevicePath
) != sizeof (NVME_NAMESPACE_DEVICE_PATH
)) {
1084 return EFI_NOT_FOUND
;
1088 // Check NamespaceId in the device path node is valid or not.
1090 if ((Node
->NamespaceId
== 0) ||
1091 (Node
->NamespaceId
> Private
->ControllerData
->Nn
))
1093 return EFI_NOT_FOUND
;
1096 *NamespaceId
= Node
->NamespaceId
;
1100 return EFI_UNSUPPORTED
;
1105 Used to allocate and build a device path node for an NVM Express namespace on an NVM Express controller.
1107 The EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL.BuildDevicePath() function allocates and builds a single device
1108 path node for the NVM Express namespace specified by NamespaceId.
1110 If the NamespaceId is not valid, then EFI_NOT_FOUND is returned.
1112 If DevicePath is NULL, then EFI_INVALID_PARAMETER is returned.
1114 If there are not enough resources to allocate the device path node, then EFI_OUT_OF_RESOURCES is returned.
1116 Otherwise, DevicePath is allocated with the boot service AllocatePool(), the contents of DevicePath are
1117 initialized to describe the NVM Express namespace specified by NamespaceId, and EFI_SUCCESS is returned.
1119 @param[in] This A pointer to the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL instance.
1120 @param[in] NamespaceId The NVM Express namespace ID for which a device path node is to be
1121 allocated and built. Caller must set the NamespaceId to zero if the
1122 device path node will contain a valid UUID.
1123 @param[in,out] DevicePath A pointer to a single device path node that describes the NVM Express
1124 namespace specified by NamespaceId. This function is responsible for
1125 allocating the buffer DevicePath with the boot service AllocatePool().
1126 It is the caller's responsibility to free DevicePath when the caller
1127 is finished with DevicePath.
1128 @retval EFI_SUCCESS The device path node that describes the NVM Express namespace specified
1129 by NamespaceId was allocated and returned in DevicePath.
1130 @retval EFI_NOT_FOUND The NamespaceId is not valid.
1131 @retval EFI_INVALID_PARAMETER DevicePath is NULL.
1132 @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate the DevicePath node.
1137 NvmExpressBuildDevicePath (
1138 IN EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL
*This
,
1139 IN UINT32 NamespaceId
,
1140 IN OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
1143 NVME_NAMESPACE_DEVICE_PATH
*Node
;
1144 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
1146 NVME_ADMIN_NAMESPACE_DATA
*NamespaceData
;
1149 // Validate parameters
1151 if ((This
== NULL
) || (DevicePath
== NULL
)) {
1152 return EFI_INVALID_PARAMETER
;
1155 Status
= EFI_SUCCESS
;
1156 Private
= NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (This
);
1159 // Check NamespaceId is valid or not.
1161 if ((NamespaceId
== 0) ||
1162 (NamespaceId
> Private
->ControllerData
->Nn
))
1164 return EFI_NOT_FOUND
;
1167 Node
= (NVME_NAMESPACE_DEVICE_PATH
*)AllocateZeroPool (sizeof (NVME_NAMESPACE_DEVICE_PATH
));
1169 return EFI_OUT_OF_RESOURCES
;
1172 Node
->Header
.Type
= MESSAGING_DEVICE_PATH
;
1173 Node
->Header
.SubType
= MSG_NVME_NAMESPACE_DP
;
1174 SetDevicePathNodeLength (&Node
->Header
, sizeof (NVME_NAMESPACE_DEVICE_PATH
));
1175 Node
->NamespaceId
= NamespaceId
;
1178 // Allocate a buffer for Identify Namespace data.
1180 NamespaceData
= NULL
;
1181 NamespaceData
= AllocateZeroPool (sizeof (NVME_ADMIN_NAMESPACE_DATA
));
1182 if (NamespaceData
== NULL
) {
1183 Status
= EFI_OUT_OF_RESOURCES
;
1188 // Get UUID from specified Identify Namespace data.
1190 Status
= NvmeIdentifyNamespace (
1193 (VOID
*)NamespaceData
1196 if (EFI_ERROR (Status
)) {
1200 Node
->NamespaceUuid
= NamespaceData
->Eui64
;
1202 *DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*)Node
;
1205 if (NamespaceData
!= NULL
) {
1206 FreePool (NamespaceData
);
1209 if (EFI_ERROR (Status
)) {