2 NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows
3 NVM Express specification.
5 Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "NvmExpress.h"
12 #define NVME_SHUTDOWN_PROCESS_TIMEOUT 45
15 // The number of NVME controllers managed by this driver, used by
16 // NvmeRegisterShutdownNotification() and NvmeUnregisterShutdownNotification().
18 UINTN mNvmeControllerNumber
= 0;
21 Read Nvm Express controller capability register.
23 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
24 @param Cap The buffer used to store capability register content.
26 @return EFI_SUCCESS Successfully read the controller capability register content.
27 @return EFI_DEVICE_ERROR Fail to read the controller capability register.
31 ReadNvmeControllerCapabilities (
32 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
36 EFI_PCI_IO_PROTOCOL
*PciIo
;
40 PciIo
= Private
->PciIo
;
41 Status
= PciIo
->Mem
.Read (
50 if (EFI_ERROR(Status
)) {
54 WriteUnaligned64 ((UINT64
*)Cap
, Data
);
59 Read Nvm Express controller configuration register.
61 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
62 @param Cc The buffer used to store configuration register content.
64 @return EFI_SUCCESS Successfully read the controller configuration register content.
65 @return EFI_DEVICE_ERROR Fail to read the controller configuration register.
69 ReadNvmeControllerConfiguration (
70 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
74 EFI_PCI_IO_PROTOCOL
*PciIo
;
78 PciIo
= Private
->PciIo
;
79 Status
= PciIo
->Mem
.Read (
88 if (EFI_ERROR(Status
)) {
92 WriteUnaligned32 ((UINT32
*)Cc
, Data
);
97 Write Nvm Express controller configuration register.
99 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
100 @param Cc The buffer used to store the content to be written into configuration register.
102 @return EFI_SUCCESS Successfully write data into the controller configuration register.
103 @return EFI_DEVICE_ERROR Fail to write data into the controller configuration register.
107 WriteNvmeControllerConfiguration (
108 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
112 EFI_PCI_IO_PROTOCOL
*PciIo
;
116 PciIo
= Private
->PciIo
;
117 Data
= ReadUnaligned32 ((UINT32
*)Cc
);
118 Status
= PciIo
->Mem
.Write (
127 if (EFI_ERROR(Status
)) {
131 DEBUG ((DEBUG_INFO
, "Cc.En: %d\n", Cc
->En
));
132 DEBUG ((DEBUG_INFO
, "Cc.Css: %d\n", Cc
->Css
));
133 DEBUG ((DEBUG_INFO
, "Cc.Mps: %d\n", Cc
->Mps
));
134 DEBUG ((DEBUG_INFO
, "Cc.Ams: %d\n", Cc
->Ams
));
135 DEBUG ((DEBUG_INFO
, "Cc.Shn: %d\n", Cc
->Shn
));
136 DEBUG ((DEBUG_INFO
, "Cc.Iosqes: %d\n", Cc
->Iosqes
));
137 DEBUG ((DEBUG_INFO
, "Cc.Iocqes: %d\n", Cc
->Iocqes
));
143 Read Nvm Express controller status register.
145 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
146 @param Csts The buffer used to store status register content.
148 @return EFI_SUCCESS Successfully read the controller status register content.
149 @return EFI_DEVICE_ERROR Fail to read the controller status register.
153 ReadNvmeControllerStatus (
154 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
158 EFI_PCI_IO_PROTOCOL
*PciIo
;
162 PciIo
= Private
->PciIo
;
163 Status
= PciIo
->Mem
.Read (
172 if (EFI_ERROR(Status
)) {
176 WriteUnaligned32 ((UINT32
*)Csts
, Data
);
183 Write Nvm Express admin queue attributes register.
185 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
186 @param Aqa The buffer used to store the content to be written into admin queue attributes register.
188 @return EFI_SUCCESS Successfully write data into the admin queue attributes register.
189 @return EFI_DEVICE_ERROR Fail to write data into the admin queue attributes register.
193 WriteNvmeAdminQueueAttributes (
194 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
198 EFI_PCI_IO_PROTOCOL
*PciIo
;
202 PciIo
= Private
->PciIo
;
203 Data
= ReadUnaligned32 ((UINT32
*)Aqa
);
204 Status
= PciIo
->Mem
.Write (
213 if (EFI_ERROR(Status
)) {
217 DEBUG ((DEBUG_INFO
, "Aqa.Asqs: %d\n", Aqa
->Asqs
));
218 DEBUG ((DEBUG_INFO
, "Aqa.Acqs: %d\n", Aqa
->Acqs
));
225 Write Nvm Express admin submission queue base address register.
227 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
228 @param Asq The buffer used to store the content to be written into admin submission queue base address register.
230 @return EFI_SUCCESS Successfully write data into the admin submission queue base address register.
231 @return EFI_DEVICE_ERROR Fail to write data into the admin submission queue base address register.
235 WriteNvmeAdminSubmissionQueueBaseAddress (
236 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
240 EFI_PCI_IO_PROTOCOL
*PciIo
;
244 PciIo
= Private
->PciIo
;
245 Data
= ReadUnaligned64 ((UINT64
*)Asq
);
247 Status
= PciIo
->Mem
.Write (
256 if (EFI_ERROR(Status
)) {
260 DEBUG ((DEBUG_INFO
, "Asq: %lx\n", *Asq
));
268 Write Nvm Express admin completion queue base address register.
270 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
271 @param Acq The buffer used to store the content to be written into admin completion queue base address register.
273 @return EFI_SUCCESS Successfully write data into the admin completion queue base address register.
274 @return EFI_DEVICE_ERROR Fail to write data into the admin completion queue base address register.
278 WriteNvmeAdminCompletionQueueBaseAddress (
279 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
283 EFI_PCI_IO_PROTOCOL
*PciIo
;
287 PciIo
= Private
->PciIo
;
288 Data
= ReadUnaligned64 ((UINT64
*)Acq
);
290 Status
= PciIo
->Mem
.Write (
299 if (EFI_ERROR(Status
)) {
303 DEBUG ((DEBUG_INFO
, "Acq: %lxh\n", *Acq
));
309 Disable the Nvm Express controller.
311 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
313 @return EFI_SUCCESS Successfully disable the controller.
314 @return EFI_DEVICE_ERROR Fail to disable the controller.
318 NvmeDisableController (
319 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
329 // Read Controller Configuration Register.
331 Status
= ReadNvmeControllerConfiguration (Private
, &Cc
);
332 if (EFI_ERROR(Status
)) {
339 // Disable the controller.
341 Status
= WriteNvmeControllerConfiguration (Private
, &Cc
);
343 if (EFI_ERROR(Status
)) {
348 // Cap.To specifies max delay time in 500ms increments for Csts.Rdy to transition from 1 to 0 after
349 // Cc.Enable transition from 1 to 0. Loop produces a 1 millisecond delay per itteration, up to 500 * Cap.To.
351 if (Private
->Cap
.To
== 0) {
354 Timeout
= Private
->Cap
.To
;
357 for(Index
= (Timeout
* 500); Index
!= 0; --Index
) {
361 // Check if the controller is initialized
363 Status
= ReadNvmeControllerStatus (Private
, &Csts
);
365 if (EFI_ERROR(Status
)) {
375 Status
= EFI_DEVICE_ERROR
;
377 (EFI_ERROR_CODE
| EFI_ERROR_MAJOR
),
378 (EFI_IO_BUS_SCSI
| EFI_IOB_EC_INTERFACE_ERROR
)
382 DEBUG ((DEBUG_INFO
, "NVMe controller is disabled with status [%r].\n", Status
));
387 Enable the Nvm Express controller.
389 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
391 @return EFI_SUCCESS Successfully enable the controller.
392 @return EFI_DEVICE_ERROR Fail to enable the controller.
393 @return EFI_TIMEOUT Fail to enable the controller in given time slot.
397 NvmeEnableController (
398 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
408 // Enable the controller.
409 // CC.AMS, CC.MPS and CC.CSS are all set to 0.
411 ZeroMem (&Cc
, sizeof (NVME_CC
));
416 Status
= WriteNvmeControllerConfiguration (Private
, &Cc
);
417 if (EFI_ERROR(Status
)) {
422 // Cap.To specifies max delay time in 500ms increments for Csts.Rdy to set after
423 // Cc.Enable. Loop produces a 1 millisecond delay per itteration, up to 500 * Cap.To.
425 if (Private
->Cap
.To
== 0) {
428 Timeout
= Private
->Cap
.To
;
431 for(Index
= (Timeout
* 500); Index
!= 0; --Index
) {
435 // Check if the controller is initialized
437 Status
= ReadNvmeControllerStatus (Private
, &Csts
);
439 if (EFI_ERROR(Status
)) {
449 Status
= EFI_TIMEOUT
;
451 (EFI_ERROR_CODE
| EFI_ERROR_MAJOR
),
452 (EFI_IO_BUS_SCSI
| EFI_IOB_EC_INTERFACE_ERROR
)
456 DEBUG ((DEBUG_INFO
, "NVMe controller is enabled with status [%r].\n", Status
));
461 Get identify controller data.
463 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
464 @param Buffer The buffer used to store the identify controller data.
466 @return EFI_SUCCESS Successfully get the identify controller data.
467 @return EFI_DEVICE_ERROR Fail to get the identify controller data.
471 NvmeIdentifyController (
472 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
476 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
477 EFI_NVM_EXPRESS_COMMAND Command
;
478 EFI_NVM_EXPRESS_COMPLETION Completion
;
481 ZeroMem (&CommandPacket
, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
482 ZeroMem (&Command
, sizeof(EFI_NVM_EXPRESS_COMMAND
));
483 ZeroMem (&Completion
, sizeof(EFI_NVM_EXPRESS_COMPLETION
));
485 Command
.Cdw0
.Opcode
= NVME_ADMIN_IDENTIFY_CMD
;
487 // According to Nvm Express 1.1 spec Figure 38, When not used, the field shall be cleared to 0h.
488 // For the Identify command, the Namespace Identifier is only used for the Namespace data structure.
492 CommandPacket
.NvmeCmd
= &Command
;
493 CommandPacket
.NvmeCompletion
= &Completion
;
494 CommandPacket
.TransferBuffer
= Buffer
;
495 CommandPacket
.TransferLength
= sizeof (NVME_ADMIN_CONTROLLER_DATA
);
496 CommandPacket
.CommandTimeout
= NVME_GENERIC_TIMEOUT
;
497 CommandPacket
.QueueType
= NVME_ADMIN_QUEUE
;
499 // Set bit 0 (Cns bit) to 1 to identify a controller
502 Command
.Flags
= CDW10_VALID
;
504 Status
= Private
->Passthru
.PassThru (
515 Get specified identify namespace data.
517 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
518 @param NamespaceId The specified namespace identifier.
519 @param Buffer The buffer used to store the identify namespace data.
521 @return EFI_SUCCESS Successfully get the identify namespace data.
522 @return EFI_DEVICE_ERROR Fail to get the identify namespace data.
526 NvmeIdentifyNamespace (
527 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
528 IN UINT32 NamespaceId
,
532 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
533 EFI_NVM_EXPRESS_COMMAND Command
;
534 EFI_NVM_EXPRESS_COMPLETION Completion
;
537 ZeroMem (&CommandPacket
, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
538 ZeroMem (&Command
, sizeof(EFI_NVM_EXPRESS_COMMAND
));
539 ZeroMem (&Completion
, sizeof(EFI_NVM_EXPRESS_COMPLETION
));
541 CommandPacket
.NvmeCmd
= &Command
;
542 CommandPacket
.NvmeCompletion
= &Completion
;
544 Command
.Cdw0
.Opcode
= NVME_ADMIN_IDENTIFY_CMD
;
545 Command
.Nsid
= NamespaceId
;
546 CommandPacket
.TransferBuffer
= Buffer
;
547 CommandPacket
.TransferLength
= sizeof (NVME_ADMIN_NAMESPACE_DATA
);
548 CommandPacket
.CommandTimeout
= NVME_GENERIC_TIMEOUT
;
549 CommandPacket
.QueueType
= NVME_ADMIN_QUEUE
;
551 // Set bit 0 (Cns bit) to 1 to identify a namespace
553 CommandPacket
.NvmeCmd
->Cdw10
= 0;
554 CommandPacket
.NvmeCmd
->Flags
= CDW10_VALID
;
556 Status
= Private
->Passthru
.PassThru (
567 Create io completion queue.
569 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
571 @return EFI_SUCCESS Successfully create io completion queue.
572 @return EFI_DEVICE_ERROR Fail to create io completion queue.
576 NvmeCreateIoCompletionQueue (
577 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
580 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
581 EFI_NVM_EXPRESS_COMMAND Command
;
582 EFI_NVM_EXPRESS_COMPLETION Completion
;
584 NVME_ADMIN_CRIOCQ CrIoCq
;
588 Status
= EFI_SUCCESS
;
589 Private
->CreateIoQueue
= TRUE
;
591 for (Index
= 1; Index
< NVME_MAX_QUEUES
; Index
++) {
592 ZeroMem (&CommandPacket
, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
593 ZeroMem (&Command
, sizeof(EFI_NVM_EXPRESS_COMMAND
));
594 ZeroMem (&Completion
, sizeof(EFI_NVM_EXPRESS_COMPLETION
));
595 ZeroMem (&CrIoCq
, sizeof(NVME_ADMIN_CRIOCQ
));
597 CommandPacket
.NvmeCmd
= &Command
;
598 CommandPacket
.NvmeCompletion
= &Completion
;
600 Command
.Cdw0
.Opcode
= NVME_ADMIN_CRIOCQ_CMD
;
601 CommandPacket
.TransferBuffer
= Private
->CqBufferPciAddr
[Index
];
602 CommandPacket
.TransferLength
= EFI_PAGE_SIZE
;
603 CommandPacket
.CommandTimeout
= NVME_GENERIC_TIMEOUT
;
604 CommandPacket
.QueueType
= NVME_ADMIN_QUEUE
;
607 QueueSize
= NVME_CCQ_SIZE
;
609 if (Private
->Cap
.Mqes
> NVME_ASYNC_CCQ_SIZE
) {
610 QueueSize
= NVME_ASYNC_CCQ_SIZE
;
612 QueueSize
= Private
->Cap
.Mqes
;
617 CrIoCq
.Qsize
= QueueSize
;
619 CopyMem (&CommandPacket
.NvmeCmd
->Cdw10
, &CrIoCq
, sizeof (NVME_ADMIN_CRIOCQ
));
620 CommandPacket
.NvmeCmd
->Flags
= CDW10_VALID
| CDW11_VALID
;
622 Status
= Private
->Passthru
.PassThru (
628 if (EFI_ERROR (Status
)) {
633 Private
->CreateIoQueue
= FALSE
;
639 Create io submission queue.
641 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
643 @return EFI_SUCCESS Successfully create io submission queue.
644 @return EFI_DEVICE_ERROR Fail to create io submission queue.
648 NvmeCreateIoSubmissionQueue (
649 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
652 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
653 EFI_NVM_EXPRESS_COMMAND Command
;
654 EFI_NVM_EXPRESS_COMPLETION Completion
;
656 NVME_ADMIN_CRIOSQ CrIoSq
;
660 Status
= EFI_SUCCESS
;
661 Private
->CreateIoQueue
= TRUE
;
663 for (Index
= 1; Index
< NVME_MAX_QUEUES
; Index
++) {
664 ZeroMem (&CommandPacket
, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
665 ZeroMem (&Command
, sizeof(EFI_NVM_EXPRESS_COMMAND
));
666 ZeroMem (&Completion
, sizeof(EFI_NVM_EXPRESS_COMPLETION
));
667 ZeroMem (&CrIoSq
, sizeof(NVME_ADMIN_CRIOSQ
));
669 CommandPacket
.NvmeCmd
= &Command
;
670 CommandPacket
.NvmeCompletion
= &Completion
;
672 Command
.Cdw0
.Opcode
= NVME_ADMIN_CRIOSQ_CMD
;
673 CommandPacket
.TransferBuffer
= Private
->SqBufferPciAddr
[Index
];
674 CommandPacket
.TransferLength
= EFI_PAGE_SIZE
;
675 CommandPacket
.CommandTimeout
= NVME_GENERIC_TIMEOUT
;
676 CommandPacket
.QueueType
= NVME_ADMIN_QUEUE
;
679 QueueSize
= NVME_CSQ_SIZE
;
681 if (Private
->Cap
.Mqes
> NVME_ASYNC_CSQ_SIZE
) {
682 QueueSize
= NVME_ASYNC_CSQ_SIZE
;
684 QueueSize
= Private
->Cap
.Mqes
;
689 CrIoSq
.Qsize
= QueueSize
;
693 CopyMem (&CommandPacket
.NvmeCmd
->Cdw10
, &CrIoSq
, sizeof (NVME_ADMIN_CRIOSQ
));
694 CommandPacket
.NvmeCmd
->Flags
= CDW10_VALID
| CDW11_VALID
;
696 Status
= Private
->Passthru
.PassThru (
702 if (EFI_ERROR (Status
)) {
707 Private
->CreateIoQueue
= FALSE
;
713 Initialize the Nvm Express controller.
715 @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
717 @retval EFI_SUCCESS The NVM Express Controller is initialized successfully.
718 @retval Others A device error occurred while initializing the controller.
723 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
727 EFI_PCI_IO_PROTOCOL
*PciIo
;
735 // Save original PCI attributes and enable this controller.
737 PciIo
= Private
->PciIo
;
738 Status
= PciIo
->Attributes (
740 EfiPciIoAttributeOperationGet
,
742 &Private
->PciAttributes
745 if (EFI_ERROR (Status
)) {
749 Status
= PciIo
->Attributes (
751 EfiPciIoAttributeOperationSupported
,
756 if (!EFI_ERROR (Status
)) {
757 Supports
&= (UINT64
)EFI_PCI_DEVICE_ENABLE
;
758 Status
= PciIo
->Attributes (
760 EfiPciIoAttributeOperationEnable
,
766 if (EFI_ERROR (Status
)) {
767 DEBUG ((DEBUG_INFO
, "NvmeControllerInit: failed to enable controller\n"));
772 // Enable 64-bit DMA support in the PCI layer.
774 Status
= PciIo
->Attributes (
776 EfiPciIoAttributeOperationEnable
,
777 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
,
780 if (EFI_ERROR (Status
)) {
781 DEBUG ((DEBUG_WARN
, "NvmeControllerInit: failed to enable 64-bit DMA (%r)\n", Status
));
785 // Read the Controller Capabilities register and verify that the NVM command set is supported
787 Status
= ReadNvmeControllerCapabilities (Private
, &Private
->Cap
);
788 if (EFI_ERROR (Status
)) {
792 if (Private
->Cap
.Css
!= 0x01) {
793 DEBUG ((DEBUG_INFO
, "NvmeControllerInit: the controller doesn't support NVMe command set\n"));
794 return EFI_UNSUPPORTED
;
798 // Currently the driver only supports 4k page size.
800 ASSERT ((Private
->Cap
.Mpsmin
+ 12) <= EFI_PAGE_SHIFT
);
808 Private
->SqTdbl
[0].Sqt
= 0;
809 Private
->SqTdbl
[1].Sqt
= 0;
810 Private
->SqTdbl
[2].Sqt
= 0;
811 Private
->CqHdbl
[0].Cqh
= 0;
812 Private
->CqHdbl
[1].Cqh
= 0;
813 Private
->CqHdbl
[2].Cqh
= 0;
814 Private
->AsyncSqHead
= 0;
816 Status
= NvmeDisableController (Private
);
818 if (EFI_ERROR(Status
)) {
823 // set number of entries admin submission & completion queues.
825 Aqa
.Asqs
= NVME_ASQ_SIZE
;
827 Aqa
.Acqs
= NVME_ACQ_SIZE
;
831 // Address of admin submission queue.
833 Asq
= (UINT64
)(UINTN
)(Private
->BufferPciAddr
) & ~0xFFF;
836 // Address of admin completion queue.
838 Acq
= (UINT64
)(UINTN
)(Private
->BufferPciAddr
+ EFI_PAGE_SIZE
) & ~0xFFF;
841 // Address of I/O submission & completion queue.
843 ZeroMem (Private
->Buffer
, EFI_PAGES_TO_SIZE (6));
844 Private
->SqBuffer
[0] = (NVME_SQ
*)(UINTN
)(Private
->Buffer
);
845 Private
->SqBufferPciAddr
[0] = (NVME_SQ
*)(UINTN
)(Private
->BufferPciAddr
);
846 Private
->CqBuffer
[0] = (NVME_CQ
*)(UINTN
)(Private
->Buffer
+ 1 * EFI_PAGE_SIZE
);
847 Private
->CqBufferPciAddr
[0] = (NVME_CQ
*)(UINTN
)(Private
->BufferPciAddr
+ 1 * EFI_PAGE_SIZE
);
848 Private
->SqBuffer
[1] = (NVME_SQ
*)(UINTN
)(Private
->Buffer
+ 2 * EFI_PAGE_SIZE
);
849 Private
->SqBufferPciAddr
[1] = (NVME_SQ
*)(UINTN
)(Private
->BufferPciAddr
+ 2 * EFI_PAGE_SIZE
);
850 Private
->CqBuffer
[1] = (NVME_CQ
*)(UINTN
)(Private
->Buffer
+ 3 * EFI_PAGE_SIZE
);
851 Private
->CqBufferPciAddr
[1] = (NVME_CQ
*)(UINTN
)(Private
->BufferPciAddr
+ 3 * EFI_PAGE_SIZE
);
852 Private
->SqBuffer
[2] = (NVME_SQ
*)(UINTN
)(Private
->Buffer
+ 4 * EFI_PAGE_SIZE
);
853 Private
->SqBufferPciAddr
[2] = (NVME_SQ
*)(UINTN
)(Private
->BufferPciAddr
+ 4 * EFI_PAGE_SIZE
);
854 Private
->CqBuffer
[2] = (NVME_CQ
*)(UINTN
)(Private
->Buffer
+ 5 * EFI_PAGE_SIZE
);
855 Private
->CqBufferPciAddr
[2] = (NVME_CQ
*)(UINTN
)(Private
->BufferPciAddr
+ 5 * EFI_PAGE_SIZE
);
857 DEBUG ((DEBUG_INFO
, "Private->Buffer = [%016X]\n", (UINT64
)(UINTN
)Private
->Buffer
));
858 DEBUG ((DEBUG_INFO
, "Admin Submission Queue size (Aqa.Asqs) = [%08X]\n", Aqa
.Asqs
));
859 DEBUG ((DEBUG_INFO
, "Admin Completion Queue size (Aqa.Acqs) = [%08X]\n", Aqa
.Acqs
));
860 DEBUG ((DEBUG_INFO
, "Admin Submission Queue (SqBuffer[0]) = [%016X]\n", Private
->SqBuffer
[0]));
861 DEBUG ((DEBUG_INFO
, "Admin Completion Queue (CqBuffer[0]) = [%016X]\n", Private
->CqBuffer
[0]));
862 DEBUG ((DEBUG_INFO
, "Sync I/O Submission Queue (SqBuffer[1]) = [%016X]\n", Private
->SqBuffer
[1]));
863 DEBUG ((DEBUG_INFO
, "Sync I/O Completion Queue (CqBuffer[1]) = [%016X]\n", Private
->CqBuffer
[1]));
864 DEBUG ((DEBUG_INFO
, "Async I/O Submission Queue (SqBuffer[2]) = [%016X]\n", Private
->SqBuffer
[2]));
865 DEBUG ((DEBUG_INFO
, "Async I/O Completion Queue (CqBuffer[2]) = [%016X]\n", Private
->CqBuffer
[2]));
868 // Program admin queue attributes.
870 Status
= WriteNvmeAdminQueueAttributes (Private
, &Aqa
);
872 if (EFI_ERROR(Status
)) {
877 // Program admin submission queue address.
879 Status
= WriteNvmeAdminSubmissionQueueBaseAddress (Private
, &Asq
);
881 if (EFI_ERROR(Status
)) {
886 // Program admin completion queue address.
888 Status
= WriteNvmeAdminCompletionQueueBaseAddress (Private
, &Acq
);
890 if (EFI_ERROR(Status
)) {
894 Status
= NvmeEnableController (Private
);
895 if (EFI_ERROR(Status
)) {
900 // Allocate buffer for Identify Controller data
902 if (Private
->ControllerData
== NULL
) {
903 Private
->ControllerData
= (NVME_ADMIN_CONTROLLER_DATA
*)AllocateZeroPool (sizeof(NVME_ADMIN_CONTROLLER_DATA
));
905 if (Private
->ControllerData
== NULL
) {
906 return EFI_OUT_OF_RESOURCES
;
911 // Get current Identify Controller Data
913 Status
= NvmeIdentifyController (Private
, Private
->ControllerData
);
915 if (EFI_ERROR(Status
)) {
916 FreePool(Private
->ControllerData
);
917 Private
->ControllerData
= NULL
;
918 return EFI_NOT_FOUND
;
922 // Dump NvmExpress Identify Controller Data
924 CopyMem (Sn
, Private
->ControllerData
->Sn
, sizeof (Private
->ControllerData
->Sn
));
926 CopyMem (Mn
, Private
->ControllerData
->Mn
, sizeof (Private
->ControllerData
->Mn
));
928 DEBUG ((DEBUG_INFO
, " == NVME IDENTIFY CONTROLLER DATA ==\n"));
929 DEBUG ((DEBUG_INFO
, " PCI VID : 0x%x\n", Private
->ControllerData
->Vid
));
930 DEBUG ((DEBUG_INFO
, " PCI SSVID : 0x%x\n", Private
->ControllerData
->Ssvid
));
931 DEBUG ((DEBUG_INFO
, " SN : %a\n", Sn
));
932 DEBUG ((DEBUG_INFO
, " MN : %a\n", Mn
));
933 DEBUG ((DEBUG_INFO
, " FR : 0x%x\n", *((UINT64
*)Private
->ControllerData
->Fr
)));
934 DEBUG ((DEBUG_INFO
, " TNVMCAP (high 8-byte) : 0x%lx\n", *((UINT64
*)(Private
->ControllerData
->Tnvmcap
+ 8))));
935 DEBUG ((DEBUG_INFO
, " TNVMCAP (low 8-byte) : 0x%lx\n", *((UINT64
*)Private
->ControllerData
->Tnvmcap
)));
936 DEBUG ((DEBUG_INFO
, " RAB : 0x%x\n", Private
->ControllerData
->Rab
));
937 DEBUG ((DEBUG_INFO
, " IEEE : 0x%x\n", *(UINT32
*)Private
->ControllerData
->Ieee_oui
));
938 DEBUG ((DEBUG_INFO
, " AERL : 0x%x\n", Private
->ControllerData
->Aerl
));
939 DEBUG ((DEBUG_INFO
, " SQES : 0x%x\n", Private
->ControllerData
->Sqes
));
940 DEBUG ((DEBUG_INFO
, " CQES : 0x%x\n", Private
->ControllerData
->Cqes
));
941 DEBUG ((DEBUG_INFO
, " NN : 0x%x\n", Private
->ControllerData
->Nn
));
944 // Create two I/O completion queues.
945 // One for blocking I/O, one for non-blocking I/O.
947 Status
= NvmeCreateIoCompletionQueue (Private
);
948 if (EFI_ERROR(Status
)) {
953 // Create two I/O Submission queues.
954 // One for blocking I/O, one for non-blocking I/O.
956 Status
= NvmeCreateIoSubmissionQueue (Private
);
962 This routine is called to properly shutdown the Nvm Express controller per NVMe spec.
964 @param[in] ResetType The type of reset to perform.
965 @param[in] ResetStatus The status code for the reset.
966 @param[in] DataSize The size, in bytes, of ResetData.
967 @param[in] ResetData For a ResetType of EfiResetCold, EfiResetWarm, or
968 EfiResetShutdown the data buffer starts with a Null-terminated
969 string, optionally followed by additional binary data.
970 The string is a description that the caller may use to further
971 indicate the reason for the system reset.
972 For a ResetType of EfiResetPlatformSpecific the data buffer
973 also starts with a Null-terminated string that is followed
974 by an EFI_GUID that describes the specific type of reset to perform.
978 NvmeShutdownAllControllers (
979 IN EFI_RESET_TYPE ResetType
,
980 IN EFI_STATUS ResetStatus
,
982 IN VOID
*ResetData OPTIONAL
989 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfos
;
992 EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL
*NvmePassThru
;
996 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
998 Status
= gBS
->LocateHandleBuffer (
1000 &gEfiPciIoProtocolGuid
,
1005 if (EFI_ERROR (Status
)) {
1009 for (HandleIndex
= 0; HandleIndex
< HandleCount
; HandleIndex
++) {
1010 Status
= gBS
->OpenProtocolInformation (
1011 Handles
[HandleIndex
],
1012 &gEfiPciIoProtocolGuid
,
1016 if (EFI_ERROR (Status
)) {
1020 for (OpenInfoIndex
= 0; OpenInfoIndex
< OpenInfoCount
; OpenInfoIndex
++) {
1022 // Find all the NVME controller managed by this driver.
1023 // gImageHandle equals to DriverBinding handle for this driver.
1025 if (((OpenInfos
[OpenInfoIndex
].Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) &&
1026 (OpenInfos
[OpenInfoIndex
].AgentHandle
== gImageHandle
)) {
1027 Status
= gBS
->OpenProtocol (
1028 OpenInfos
[OpenInfoIndex
].ControllerHandle
,
1029 &gEfiNvmExpressPassThruProtocolGuid
,
1030 (VOID
**) &NvmePassThru
,
1033 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1035 if (EFI_ERROR (Status
)) {
1038 Private
= NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (NvmePassThru
);
1041 // Read Controller Configuration Register.
1043 Status
= ReadNvmeControllerConfiguration (Private
, &Cc
);
1044 if (EFI_ERROR(Status
)) {
1048 // The host should set the Shutdown Notification (CC.SHN) field to 01b
1049 // to indicate a normal shutdown operation.
1051 Cc
.Shn
= NVME_CC_SHN_NORMAL_SHUTDOWN
;
1052 Status
= WriteNvmeControllerConfiguration (Private
, &Cc
);
1053 if (EFI_ERROR(Status
)) {
1058 // The controller indicates when shutdown processing is completed by updating the
1059 // Shutdown Status (CSTS.SHST) field to 10b.
1060 // Wait up to 45 seconds (break down to 4500 x 10ms) for the shutdown to complete.
1062 for (Index
= 0; Index
< NVME_SHUTDOWN_PROCESS_TIMEOUT
* 100; Index
++) {
1063 Status
= ReadNvmeControllerStatus (Private
, &Csts
);
1064 if (!EFI_ERROR(Status
) && (Csts
.Shst
== NVME_CSTS_SHST_SHUTDOWN_COMPLETED
)) {
1065 DEBUG((DEBUG_INFO
, "NvmeShutdownController: shutdown processing is completed after %dms.\n", Index
* 10));
1071 gBS
->Stall (10 * 1000);
1074 if (Index
== NVME_SHUTDOWN_PROCESS_TIMEOUT
* 100) {
1075 DEBUG((DEBUG_ERROR
, "NvmeShutdownController: shutdown processing is timed out\n"));
1083 Register the shutdown notification through the ResetNotification protocol.
1085 Register the shutdown notification when mNvmeControllerNumber increased from 0 to 1.
1088 NvmeRegisterShutdownNotification (
1093 EFI_RESET_NOTIFICATION_PROTOCOL
*ResetNotify
;
1095 mNvmeControllerNumber
++;
1096 if (mNvmeControllerNumber
== 1) {
1097 Status
= gBS
->LocateProtocol (&gEfiResetNotificationProtocolGuid
, NULL
, (VOID
**) &ResetNotify
);
1098 if (!EFI_ERROR (Status
)) {
1099 Status
= ResetNotify
->RegisterResetNotify (ResetNotify
, NvmeShutdownAllControllers
);
1100 ASSERT_EFI_ERROR (Status
);
1102 DEBUG ((DEBUG_WARN
, "NVME: ResetNotification absent! Shutdown notification cannot be performed!\n"));
1108 Unregister the shutdown notification through the ResetNotification protocol.
1110 Unregister the shutdown notification when mNvmeControllerNumber decreased from 1 to 0.
1113 NvmeUnregisterShutdownNotification (
1118 EFI_RESET_NOTIFICATION_PROTOCOL
*ResetNotify
;
1120 mNvmeControllerNumber
--;
1121 if (mNvmeControllerNumber
== 0) {
1122 Status
= gBS
->LocateProtocol (&gEfiResetNotificationProtocolGuid
, NULL
, (VOID
**) &ResetNotify
);
1123 if (!EFI_ERROR (Status
)) {
1124 Status
= ResetNotify
->UnregisterResetNotify (ResetNotify
, NvmeShutdownAllControllers
);
1125 ASSERT_EFI_ERROR (Status
);