2 NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows
3 NVM Express specification.
5 Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "NvmExpress.h"
18 #define NVME_SHUTDOWN_PROCESS_TIMEOUT 45
21 // The number of NVME controllers managed by this driver, used by
22 // NvmeRegisterShutdownNotification() and NvmeUnregisterShutdownNotification().
24 UINTN mNvmeControllerNumber
= 0;
27 Read Nvm Express controller capability register.
29 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
30 @param Cap The buffer used to store capability register content.
32 @return EFI_SUCCESS Successfully read the controller capability register content.
33 @return EFI_DEVICE_ERROR Fail to read the controller capability register.
37 ReadNvmeControllerCapabilities (
38 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
42 EFI_PCI_IO_PROTOCOL
*PciIo
;
46 PciIo
= Private
->PciIo
;
47 Status
= PciIo
->Mem
.Read (
56 if (EFI_ERROR(Status
)) {
60 WriteUnaligned64 ((UINT64
*)Cap
, Data
);
65 Read Nvm Express controller configuration register.
67 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
68 @param Cc The buffer used to store configuration register content.
70 @return EFI_SUCCESS Successfully read the controller configuration register content.
71 @return EFI_DEVICE_ERROR Fail to read the controller configuration register.
75 ReadNvmeControllerConfiguration (
76 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
80 EFI_PCI_IO_PROTOCOL
*PciIo
;
84 PciIo
= Private
->PciIo
;
85 Status
= PciIo
->Mem
.Read (
94 if (EFI_ERROR(Status
)) {
98 WriteUnaligned32 ((UINT32
*)Cc
, Data
);
103 Write Nvm Express controller configuration register.
105 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
106 @param Cc The buffer used to store the content to be written into configuration register.
108 @return EFI_SUCCESS Successfully write data into the controller configuration register.
109 @return EFI_DEVICE_ERROR Fail to write data into the controller configuration register.
113 WriteNvmeControllerConfiguration (
114 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
118 EFI_PCI_IO_PROTOCOL
*PciIo
;
122 PciIo
= Private
->PciIo
;
123 Data
= ReadUnaligned32 ((UINT32
*)Cc
);
124 Status
= PciIo
->Mem
.Write (
133 if (EFI_ERROR(Status
)) {
137 DEBUG ((EFI_D_INFO
, "Cc.En: %d\n", Cc
->En
));
138 DEBUG ((EFI_D_INFO
, "Cc.Css: %d\n", Cc
->Css
));
139 DEBUG ((EFI_D_INFO
, "Cc.Mps: %d\n", Cc
->Mps
));
140 DEBUG ((EFI_D_INFO
, "Cc.Ams: %d\n", Cc
->Ams
));
141 DEBUG ((EFI_D_INFO
, "Cc.Shn: %d\n", Cc
->Shn
));
142 DEBUG ((EFI_D_INFO
, "Cc.Iosqes: %d\n", Cc
->Iosqes
));
143 DEBUG ((EFI_D_INFO
, "Cc.Iocqes: %d\n", Cc
->Iocqes
));
149 Read Nvm Express controller status register.
151 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
152 @param Csts The buffer used to store status register content.
154 @return EFI_SUCCESS Successfully read the controller status register content.
155 @return EFI_DEVICE_ERROR Fail to read the controller status register.
159 ReadNvmeControllerStatus (
160 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
164 EFI_PCI_IO_PROTOCOL
*PciIo
;
168 PciIo
= Private
->PciIo
;
169 Status
= PciIo
->Mem
.Read (
178 if (EFI_ERROR(Status
)) {
182 WriteUnaligned32 ((UINT32
*)Csts
, Data
);
189 Write Nvm Express admin queue attributes register.
191 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
192 @param Aqa The buffer used to store the content to be written into admin queue attributes register.
194 @return EFI_SUCCESS Successfully write data into the admin queue attributes register.
195 @return EFI_DEVICE_ERROR Fail to write data into the admin queue attributes register.
199 WriteNvmeAdminQueueAttributes (
200 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
204 EFI_PCI_IO_PROTOCOL
*PciIo
;
208 PciIo
= Private
->PciIo
;
209 Data
= ReadUnaligned32 ((UINT32
*)Aqa
);
210 Status
= PciIo
->Mem
.Write (
219 if (EFI_ERROR(Status
)) {
223 DEBUG ((EFI_D_INFO
, "Aqa.Asqs: %d\n", Aqa
->Asqs
));
224 DEBUG ((EFI_D_INFO
, "Aqa.Acqs: %d\n", Aqa
->Acqs
));
231 Write Nvm Express admin submission queue base address register.
233 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
234 @param Asq The buffer used to store the content to be written into admin submission queue base address register.
236 @return EFI_SUCCESS Successfully write data into the admin submission queue base address register.
237 @return EFI_DEVICE_ERROR Fail to write data into the admin submission queue base address register.
241 WriteNvmeAdminSubmissionQueueBaseAddress (
242 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
246 EFI_PCI_IO_PROTOCOL
*PciIo
;
250 PciIo
= Private
->PciIo
;
251 Data
= ReadUnaligned64 ((UINT64
*)Asq
);
253 Status
= PciIo
->Mem
.Write (
262 if (EFI_ERROR(Status
)) {
266 DEBUG ((EFI_D_INFO
, "Asq: %lx\n", *Asq
));
274 Write Nvm Express admin completion queue base address register.
276 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
277 @param Acq The buffer used to store the content to be written into admin completion queue base address register.
279 @return EFI_SUCCESS Successfully write data into the admin completion queue base address register.
280 @return EFI_DEVICE_ERROR Fail to write data into the admin completion queue base address register.
284 WriteNvmeAdminCompletionQueueBaseAddress (
285 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
289 EFI_PCI_IO_PROTOCOL
*PciIo
;
293 PciIo
= Private
->PciIo
;
294 Data
= ReadUnaligned64 ((UINT64
*)Acq
);
296 Status
= PciIo
->Mem
.Write (
305 if (EFI_ERROR(Status
)) {
309 DEBUG ((EFI_D_INFO
, "Acq: %lxh\n", *Acq
));
315 Disable the Nvm Express controller.
317 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
319 @return EFI_SUCCESS Successfully disable the controller.
320 @return EFI_DEVICE_ERROR Fail to disable the controller.
324 NvmeDisableController (
325 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
335 // Read Controller Configuration Register.
337 Status
= ReadNvmeControllerConfiguration (Private
, &Cc
);
338 if (EFI_ERROR(Status
)) {
345 // Disable the controller.
347 Status
= WriteNvmeControllerConfiguration (Private
, &Cc
);
349 if (EFI_ERROR(Status
)) {
354 // Cap.To specifies max delay time in 500ms increments for Csts.Rdy to transition from 1 to 0 after
355 // Cc.Enable transition from 1 to 0. Loop produces a 1 millisecond delay per itteration, up to 500 * Cap.To.
357 if (Private
->Cap
.To
== 0) {
360 Timeout
= Private
->Cap
.To
;
363 for(Index
= (Timeout
* 500); Index
!= 0; --Index
) {
367 // Check if the controller is initialized
369 Status
= ReadNvmeControllerStatus (Private
, &Csts
);
371 if (EFI_ERROR(Status
)) {
381 Status
= EFI_DEVICE_ERROR
;
384 DEBUG ((EFI_D_INFO
, "NVMe controller is disabled with status [%r].\n", Status
));
389 Enable the Nvm Express controller.
391 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
393 @return EFI_SUCCESS Successfully enable the controller.
394 @return EFI_DEVICE_ERROR Fail to enable the controller.
395 @return EFI_TIMEOUT Fail to enable the controller in given time slot.
399 NvmeEnableController (
400 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
410 // Enable the controller.
411 // CC.AMS, CC.MPS and CC.CSS are all set to 0.
413 ZeroMem (&Cc
, sizeof (NVME_CC
));
418 Status
= WriteNvmeControllerConfiguration (Private
, &Cc
);
419 if (EFI_ERROR(Status
)) {
424 // Cap.To specifies max delay time in 500ms increments for Csts.Rdy to set after
425 // Cc.Enable. Loop produces a 1 millisecond delay per itteration, up to 500 * Cap.To.
427 if (Private
->Cap
.To
== 0) {
430 Timeout
= Private
->Cap
.To
;
433 for(Index
= (Timeout
* 500); Index
!= 0; --Index
) {
437 // Check if the controller is initialized
439 Status
= ReadNvmeControllerStatus (Private
, &Csts
);
441 if (EFI_ERROR(Status
)) {
451 Status
= EFI_TIMEOUT
;
454 DEBUG ((EFI_D_INFO
, "NVMe controller is enabled with status [%r].\n", Status
));
459 Get identify controller data.
461 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
462 @param Buffer The buffer used to store the identify controller data.
464 @return EFI_SUCCESS Successfully get the identify controller data.
465 @return EFI_DEVICE_ERROR Fail to get the identify controller data.
469 NvmeIdentifyController (
470 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
474 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
475 EFI_NVM_EXPRESS_COMMAND Command
;
476 EFI_NVM_EXPRESS_COMPLETION Completion
;
479 ZeroMem (&CommandPacket
, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
480 ZeroMem (&Command
, sizeof(EFI_NVM_EXPRESS_COMMAND
));
481 ZeroMem (&Completion
, sizeof(EFI_NVM_EXPRESS_COMPLETION
));
483 Command
.Cdw0
.Opcode
= NVME_ADMIN_IDENTIFY_CMD
;
485 // According to Nvm Express 1.1 spec Figure 38, When not used, the field shall be cleared to 0h.
486 // For the Identify command, the Namespace Identifier is only used for the Namespace data structure.
490 CommandPacket
.NvmeCmd
= &Command
;
491 CommandPacket
.NvmeCompletion
= &Completion
;
492 CommandPacket
.TransferBuffer
= Buffer
;
493 CommandPacket
.TransferLength
= sizeof (NVME_ADMIN_CONTROLLER_DATA
);
494 CommandPacket
.CommandTimeout
= NVME_GENERIC_TIMEOUT
;
495 CommandPacket
.QueueType
= NVME_ADMIN_QUEUE
;
497 // Set bit 0 (Cns bit) to 1 to identify a controller
500 Command
.Flags
= CDW10_VALID
;
502 Status
= Private
->Passthru
.PassThru (
513 Get specified identify namespace data.
515 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
516 @param NamespaceId The specified namespace identifier.
517 @param Buffer The buffer used to store the identify namespace data.
519 @return EFI_SUCCESS Successfully get the identify namespace data.
520 @return EFI_DEVICE_ERROR Fail to get the identify namespace data.
524 NvmeIdentifyNamespace (
525 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
526 IN UINT32 NamespaceId
,
530 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
531 EFI_NVM_EXPRESS_COMMAND Command
;
532 EFI_NVM_EXPRESS_COMPLETION Completion
;
535 ZeroMem (&CommandPacket
, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
536 ZeroMem (&Command
, sizeof(EFI_NVM_EXPRESS_COMMAND
));
537 ZeroMem (&Completion
, sizeof(EFI_NVM_EXPRESS_COMPLETION
));
539 CommandPacket
.NvmeCmd
= &Command
;
540 CommandPacket
.NvmeCompletion
= &Completion
;
542 Command
.Cdw0
.Opcode
= NVME_ADMIN_IDENTIFY_CMD
;
543 Command
.Nsid
= NamespaceId
;
544 CommandPacket
.TransferBuffer
= Buffer
;
545 CommandPacket
.TransferLength
= sizeof (NVME_ADMIN_NAMESPACE_DATA
);
546 CommandPacket
.CommandTimeout
= NVME_GENERIC_TIMEOUT
;
547 CommandPacket
.QueueType
= NVME_ADMIN_QUEUE
;
549 // Set bit 0 (Cns bit) to 1 to identify a namespace
551 CommandPacket
.NvmeCmd
->Cdw10
= 0;
552 CommandPacket
.NvmeCmd
->Flags
= CDW10_VALID
;
554 Status
= Private
->Passthru
.PassThru (
565 Create io completion queue.
567 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
569 @return EFI_SUCCESS Successfully create io completion queue.
570 @return EFI_DEVICE_ERROR Fail to create io completion queue.
574 NvmeCreateIoCompletionQueue (
575 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
578 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
579 EFI_NVM_EXPRESS_COMMAND Command
;
580 EFI_NVM_EXPRESS_COMPLETION Completion
;
582 NVME_ADMIN_CRIOCQ CrIoCq
;
586 Status
= EFI_SUCCESS
;
587 Private
->CreateIoQueue
= TRUE
;
589 for (Index
= 1; Index
< NVME_MAX_QUEUES
; Index
++) {
590 ZeroMem (&CommandPacket
, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
591 ZeroMem (&Command
, sizeof(EFI_NVM_EXPRESS_COMMAND
));
592 ZeroMem (&Completion
, sizeof(EFI_NVM_EXPRESS_COMPLETION
));
593 ZeroMem (&CrIoCq
, sizeof(NVME_ADMIN_CRIOCQ
));
595 CommandPacket
.NvmeCmd
= &Command
;
596 CommandPacket
.NvmeCompletion
= &Completion
;
598 Command
.Cdw0
.Opcode
= NVME_ADMIN_CRIOCQ_CMD
;
599 CommandPacket
.TransferBuffer
= Private
->CqBufferPciAddr
[Index
];
600 CommandPacket
.TransferLength
= EFI_PAGE_SIZE
;
601 CommandPacket
.CommandTimeout
= NVME_GENERIC_TIMEOUT
;
602 CommandPacket
.QueueType
= NVME_ADMIN_QUEUE
;
605 QueueSize
= NVME_CCQ_SIZE
;
607 if (Private
->Cap
.Mqes
> NVME_ASYNC_CCQ_SIZE
) {
608 QueueSize
= NVME_ASYNC_CCQ_SIZE
;
610 QueueSize
= Private
->Cap
.Mqes
;
615 CrIoCq
.Qsize
= QueueSize
;
617 CopyMem (&CommandPacket
.NvmeCmd
->Cdw10
, &CrIoCq
, sizeof (NVME_ADMIN_CRIOCQ
));
618 CommandPacket
.NvmeCmd
->Flags
= CDW10_VALID
| CDW11_VALID
;
620 Status
= Private
->Passthru
.PassThru (
626 if (EFI_ERROR (Status
)) {
631 Private
->CreateIoQueue
= FALSE
;
637 Create io submission queue.
639 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
641 @return EFI_SUCCESS Successfully create io submission queue.
642 @return EFI_DEVICE_ERROR Fail to create io submission queue.
646 NvmeCreateIoSubmissionQueue (
647 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
650 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
651 EFI_NVM_EXPRESS_COMMAND Command
;
652 EFI_NVM_EXPRESS_COMPLETION Completion
;
654 NVME_ADMIN_CRIOSQ CrIoSq
;
658 Status
= EFI_SUCCESS
;
659 Private
->CreateIoQueue
= TRUE
;
661 for (Index
= 1; Index
< NVME_MAX_QUEUES
; Index
++) {
662 ZeroMem (&CommandPacket
, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
663 ZeroMem (&Command
, sizeof(EFI_NVM_EXPRESS_COMMAND
));
664 ZeroMem (&Completion
, sizeof(EFI_NVM_EXPRESS_COMPLETION
));
665 ZeroMem (&CrIoSq
, sizeof(NVME_ADMIN_CRIOSQ
));
667 CommandPacket
.NvmeCmd
= &Command
;
668 CommandPacket
.NvmeCompletion
= &Completion
;
670 Command
.Cdw0
.Opcode
= NVME_ADMIN_CRIOSQ_CMD
;
671 CommandPacket
.TransferBuffer
= Private
->SqBufferPciAddr
[Index
];
672 CommandPacket
.TransferLength
= EFI_PAGE_SIZE
;
673 CommandPacket
.CommandTimeout
= NVME_GENERIC_TIMEOUT
;
674 CommandPacket
.QueueType
= NVME_ADMIN_QUEUE
;
677 QueueSize
= NVME_CSQ_SIZE
;
679 if (Private
->Cap
.Mqes
> NVME_ASYNC_CSQ_SIZE
) {
680 QueueSize
= NVME_ASYNC_CSQ_SIZE
;
682 QueueSize
= Private
->Cap
.Mqes
;
687 CrIoSq
.Qsize
= QueueSize
;
691 CopyMem (&CommandPacket
.NvmeCmd
->Cdw10
, &CrIoSq
, sizeof (NVME_ADMIN_CRIOSQ
));
692 CommandPacket
.NvmeCmd
->Flags
= CDW10_VALID
| CDW11_VALID
;
694 Status
= Private
->Passthru
.PassThru (
700 if (EFI_ERROR (Status
)) {
705 Private
->CreateIoQueue
= FALSE
;
711 Initialize the Nvm Express controller.
713 @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
715 @retval EFI_SUCCESS The NVM Express Controller is initialized successfully.
716 @retval Others A device error occurred while initializing the controller.
721 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
725 EFI_PCI_IO_PROTOCOL
*PciIo
;
733 // Save original PCI attributes and enable this controller.
735 PciIo
= Private
->PciIo
;
736 Status
= PciIo
->Attributes (
738 EfiPciIoAttributeOperationGet
,
740 &Private
->PciAttributes
743 if (EFI_ERROR (Status
)) {
747 Status
= PciIo
->Attributes (
749 EfiPciIoAttributeOperationSupported
,
754 if (!EFI_ERROR (Status
)) {
755 Supports
&= (UINT64
)EFI_PCI_DEVICE_ENABLE
;
756 Status
= PciIo
->Attributes (
758 EfiPciIoAttributeOperationEnable
,
764 if (EFI_ERROR (Status
)) {
765 DEBUG ((EFI_D_INFO
, "NvmeControllerInit: failed to enable controller\n"));
770 // Enable 64-bit DMA support in the PCI layer.
772 Status
= PciIo
->Attributes (
774 EfiPciIoAttributeOperationEnable
,
775 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
,
778 if (EFI_ERROR (Status
)) {
779 DEBUG ((EFI_D_WARN
, "NvmeControllerInit: failed to enable 64-bit DMA (%r)\n", Status
));
783 // Read the Controller Capabilities register and verify that the NVM command set is supported
785 Status
= ReadNvmeControllerCapabilities (Private
, &Private
->Cap
);
786 if (EFI_ERROR (Status
)) {
790 if (Private
->Cap
.Css
!= 0x01) {
791 DEBUG ((EFI_D_INFO
, "NvmeControllerInit: the controller doesn't support NVMe command set\n"));
792 return EFI_UNSUPPORTED
;
796 // Currently the driver only supports 4k page size.
798 ASSERT ((Private
->Cap
.Mpsmin
+ 12) <= EFI_PAGE_SHIFT
);
806 Private
->SqTdbl
[0].Sqt
= 0;
807 Private
->SqTdbl
[1].Sqt
= 0;
808 Private
->SqTdbl
[2].Sqt
= 0;
809 Private
->CqHdbl
[0].Cqh
= 0;
810 Private
->CqHdbl
[1].Cqh
= 0;
811 Private
->CqHdbl
[2].Cqh
= 0;
812 Private
->AsyncSqHead
= 0;
814 Status
= NvmeDisableController (Private
);
816 if (EFI_ERROR(Status
)) {
821 // set number of entries admin submission & completion queues.
823 Aqa
.Asqs
= NVME_ASQ_SIZE
;
825 Aqa
.Acqs
= NVME_ACQ_SIZE
;
829 // Address of admin submission queue.
831 Asq
= (UINT64
)(UINTN
)(Private
->BufferPciAddr
) & ~0xFFF;
834 // Address of admin completion queue.
836 Acq
= (UINT64
)(UINTN
)(Private
->BufferPciAddr
+ EFI_PAGE_SIZE
) & ~0xFFF;
839 // Address of I/O submission & completion queue.
841 ZeroMem (Private
->Buffer
, EFI_PAGES_TO_SIZE (6));
842 Private
->SqBuffer
[0] = (NVME_SQ
*)(UINTN
)(Private
->Buffer
);
843 Private
->SqBufferPciAddr
[0] = (NVME_SQ
*)(UINTN
)(Private
->BufferPciAddr
);
844 Private
->CqBuffer
[0] = (NVME_CQ
*)(UINTN
)(Private
->Buffer
+ 1 * EFI_PAGE_SIZE
);
845 Private
->CqBufferPciAddr
[0] = (NVME_CQ
*)(UINTN
)(Private
->BufferPciAddr
+ 1 * EFI_PAGE_SIZE
);
846 Private
->SqBuffer
[1] = (NVME_SQ
*)(UINTN
)(Private
->Buffer
+ 2 * EFI_PAGE_SIZE
);
847 Private
->SqBufferPciAddr
[1] = (NVME_SQ
*)(UINTN
)(Private
->BufferPciAddr
+ 2 * EFI_PAGE_SIZE
);
848 Private
->CqBuffer
[1] = (NVME_CQ
*)(UINTN
)(Private
->Buffer
+ 3 * EFI_PAGE_SIZE
);
849 Private
->CqBufferPciAddr
[1] = (NVME_CQ
*)(UINTN
)(Private
->BufferPciAddr
+ 3 * EFI_PAGE_SIZE
);
850 Private
->SqBuffer
[2] = (NVME_SQ
*)(UINTN
)(Private
->Buffer
+ 4 * EFI_PAGE_SIZE
);
851 Private
->SqBufferPciAddr
[2] = (NVME_SQ
*)(UINTN
)(Private
->BufferPciAddr
+ 4 * EFI_PAGE_SIZE
);
852 Private
->CqBuffer
[2] = (NVME_CQ
*)(UINTN
)(Private
->Buffer
+ 5 * EFI_PAGE_SIZE
);
853 Private
->CqBufferPciAddr
[2] = (NVME_CQ
*)(UINTN
)(Private
->BufferPciAddr
+ 5 * EFI_PAGE_SIZE
);
855 DEBUG ((EFI_D_INFO
, "Private->Buffer = [%016X]\n", (UINT64
)(UINTN
)Private
->Buffer
));
856 DEBUG ((EFI_D_INFO
, "Admin Submission Queue size (Aqa.Asqs) = [%08X]\n", Aqa
.Asqs
));
857 DEBUG ((EFI_D_INFO
, "Admin Completion Queue size (Aqa.Acqs) = [%08X]\n", Aqa
.Acqs
));
858 DEBUG ((EFI_D_INFO
, "Admin Submission Queue (SqBuffer[0]) = [%016X]\n", Private
->SqBuffer
[0]));
859 DEBUG ((EFI_D_INFO
, "Admin Completion Queue (CqBuffer[0]) = [%016X]\n", Private
->CqBuffer
[0]));
860 DEBUG ((EFI_D_INFO
, "Sync I/O Submission Queue (SqBuffer[1]) = [%016X]\n", Private
->SqBuffer
[1]));
861 DEBUG ((EFI_D_INFO
, "Sync I/O Completion Queue (CqBuffer[1]) = [%016X]\n", Private
->CqBuffer
[1]));
862 DEBUG ((EFI_D_INFO
, "Async I/O Submission Queue (SqBuffer[2]) = [%016X]\n", Private
->SqBuffer
[2]));
863 DEBUG ((EFI_D_INFO
, "Async I/O Completion Queue (CqBuffer[2]) = [%016X]\n", Private
->CqBuffer
[2]));
866 // Program admin queue attributes.
868 Status
= WriteNvmeAdminQueueAttributes (Private
, &Aqa
);
870 if (EFI_ERROR(Status
)) {
875 // Program admin submission queue address.
877 Status
= WriteNvmeAdminSubmissionQueueBaseAddress (Private
, &Asq
);
879 if (EFI_ERROR(Status
)) {
884 // Program admin completion queue address.
886 Status
= WriteNvmeAdminCompletionQueueBaseAddress (Private
, &Acq
);
888 if (EFI_ERROR(Status
)) {
892 Status
= NvmeEnableController (Private
);
893 if (EFI_ERROR(Status
)) {
898 // Allocate buffer for Identify Controller data
900 if (Private
->ControllerData
== NULL
) {
901 Private
->ControllerData
= (NVME_ADMIN_CONTROLLER_DATA
*)AllocateZeroPool (sizeof(NVME_ADMIN_CONTROLLER_DATA
));
903 if (Private
->ControllerData
== NULL
) {
904 return EFI_OUT_OF_RESOURCES
;
909 // Get current Identify Controller Data
911 Status
= NvmeIdentifyController (Private
, Private
->ControllerData
);
913 if (EFI_ERROR(Status
)) {
914 FreePool(Private
->ControllerData
);
915 Private
->ControllerData
= NULL
;
916 return EFI_NOT_FOUND
;
920 // Dump NvmExpress Identify Controller Data
922 CopyMem (Sn
, Private
->ControllerData
->Sn
, sizeof (Private
->ControllerData
->Sn
));
924 CopyMem (Mn
, Private
->ControllerData
->Mn
, sizeof (Private
->ControllerData
->Mn
));
926 DEBUG ((EFI_D_INFO
, " == NVME IDENTIFY CONTROLLER DATA ==\n"));
927 DEBUG ((EFI_D_INFO
, " PCI VID : 0x%x\n", Private
->ControllerData
->Vid
));
928 DEBUG ((EFI_D_INFO
, " PCI SSVID : 0x%x\n", Private
->ControllerData
->Ssvid
));
929 DEBUG ((EFI_D_INFO
, " SN : %a\n", Sn
));
930 DEBUG ((EFI_D_INFO
, " MN : %a\n", Mn
));
931 DEBUG ((EFI_D_INFO
, " FR : 0x%x\n", *((UINT64
*)Private
->ControllerData
->Fr
)));
932 DEBUG ((EFI_D_INFO
, " RAB : 0x%x\n", Private
->ControllerData
->Rab
));
933 DEBUG ((EFI_D_INFO
, " IEEE : 0x%x\n", *(UINT32
*)Private
->ControllerData
->Ieee_oui
));
934 DEBUG ((EFI_D_INFO
, " AERL : 0x%x\n", Private
->ControllerData
->Aerl
));
935 DEBUG ((EFI_D_INFO
, " SQES : 0x%x\n", Private
->ControllerData
->Sqes
));
936 DEBUG ((EFI_D_INFO
, " CQES : 0x%x\n", Private
->ControllerData
->Cqes
));
937 DEBUG ((EFI_D_INFO
, " NN : 0x%x\n", Private
->ControllerData
->Nn
));
940 // Create two I/O completion queues.
941 // One for blocking I/O, one for non-blocking I/O.
943 Status
= NvmeCreateIoCompletionQueue (Private
);
944 if (EFI_ERROR(Status
)) {
949 // Create two I/O Submission queues.
950 // One for blocking I/O, one for non-blocking I/O.
952 Status
= NvmeCreateIoSubmissionQueue (Private
);
958 This routine is called to properly shutdown the Nvm Express controller per NVMe spec.
960 @param[in] ResetType The type of reset to perform.
961 @param[in] ResetStatus The status code for the reset.
962 @param[in] DataSize The size, in bytes, of ResetData.
963 @param[in] ResetData For a ResetType of EfiResetCold, EfiResetWarm, or
964 EfiResetShutdown the data buffer starts with a Null-terminated
965 string, optionally followed by additional binary data.
966 The string is a description that the caller may use to further
967 indicate the reason for the system reset. ResetData is only
968 valid if ResetStatus is something other than EFI_SUCCESS
969 unless the ResetType is EfiResetPlatformSpecific
970 where a minimum amount of ResetData is always required.
971 For a ResetType of EfiResetPlatformSpecific the data buffer
972 also starts with a Null-terminated string that is followed
973 by an EFI_GUID that describes the specific type of reset to perform.
977 NvmeShutdownAllControllers (
978 IN EFI_RESET_TYPE ResetType
,
979 IN EFI_STATUS ResetStatus
,
981 IN VOID
*ResetData OPTIONAL
988 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfos
;
991 EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL
*NvmePassThru
;
995 NVME_CONTROLLER_PRIVATE_DATA
*Private
;
997 Status
= gBS
->LocateHandleBuffer (
999 &gEfiPciIoProtocolGuid
,
1004 if (EFI_ERROR (Status
)) {
1008 for (HandleIndex
= 0; HandleIndex
< HandleCount
; HandleIndex
++) {
1009 Status
= gBS
->OpenProtocolInformation (
1010 Handles
[HandleIndex
],
1011 &gEfiPciIoProtocolGuid
,
1015 if (EFI_ERROR (Status
)) {
1019 for (OpenInfoIndex
= 0; OpenInfoIndex
< OpenInfoCount
; OpenInfoIndex
++) {
1021 // Find all the NVME controller managed by this driver.
1022 // gImageHandle equals to DriverBinding handle for this driver.
1024 if (((OpenInfos
[OpenInfoIndex
].Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) &&
1025 (OpenInfos
[OpenInfoIndex
].AgentHandle
== gImageHandle
)) {
1026 Status
= gBS
->OpenProtocol (
1027 OpenInfos
[OpenInfoIndex
].ControllerHandle
,
1028 &gEfiNvmExpressPassThruProtocolGuid
,
1029 (VOID
**) &NvmePassThru
,
1032 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1034 if (EFI_ERROR (Status
)) {
1037 Private
= NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (NvmePassThru
);
1040 // Read Controller Configuration Register.
1042 Status
= ReadNvmeControllerConfiguration (Private
, &Cc
);
1043 if (EFI_ERROR(Status
)) {
1047 // The host should set the Shutdown Notification (CC.SHN) field to 01b
1048 // to indicate a normal shutdown operation.
1050 Cc
.Shn
= NVME_CC_SHN_NORMAL_SHUTDOWN
;
1051 Status
= WriteNvmeControllerConfiguration (Private
, &Cc
);
1052 if (EFI_ERROR(Status
)) {
1057 // The controller indicates when shutdown processing is completed by updating the
1058 // Shutdown Status (CSTS.SHST) field to 10b.
1059 // Wait up to 45 seconds (break down to 4500 x 10ms) for the shutdown to complete.
1061 for (Index
= 0; Index
< NVME_SHUTDOWN_PROCESS_TIMEOUT
* 100; Index
++) {
1062 Status
= ReadNvmeControllerStatus (Private
, &Csts
);
1063 if (!EFI_ERROR(Status
) && (Csts
.Shst
== NVME_CSTS_SHST_SHUTDOWN_COMPLETED
)) {
1064 DEBUG((DEBUG_INFO
, "NvmeShutdownController: shutdown processing is completed after %dms.\n", Index
* 10));
1070 gBS
->Stall (10 * 1000);
1073 if (Index
== NVME_SHUTDOWN_PROCESS_TIMEOUT
* 100) {
1074 DEBUG((DEBUG_ERROR
, "NvmeShutdownController: shutdown processing is timed out\n"));
1082 Register the shutdown notification through the ResetNotification protocol.
1084 Register the shutdown notification when mNvmeControllerNumber increased from 0 to 1.
1087 NvmeRegisterShutdownNotification (
1092 EFI_RESET_NOTIFICATION_PROTOCOL
*ResetNotify
;
1094 mNvmeControllerNumber
++;
1095 if (mNvmeControllerNumber
== 1) {
1096 Status
= gBS
->LocateProtocol (&gEfiResetNotificationProtocolGuid
, NULL
, (VOID
**) &ResetNotify
);
1097 if (!EFI_ERROR (Status
)) {
1098 Status
= ResetNotify
->RegisterResetNotify (ResetNotify
, NvmeShutdownAllControllers
);
1099 ASSERT_EFI_ERROR (Status
);
1101 DEBUG ((DEBUG_WARN
, "NVME: ResetNotification absent! Shutdown notification cannot be performed!\n"));
1107 Unregister the shutdown notification through the ResetNotification protocol.
1109 Unregister the shutdown notification when mNvmeControllerNumber decreased from 1 to 0.
1112 NvmeUnregisterShutdownNotification (
1117 EFI_RESET_NOTIFICATION_PROTOCOL
*ResetNotify
;
1119 mNvmeControllerNumber
--;
1120 if (mNvmeControllerNumber
== 0) {
1121 Status
= gBS
->LocateProtocol (&gEfiResetNotificationProtocolGuid
, NULL
, (VOID
**) &ResetNotify
);
1122 if (!EFI_ERROR (Status
)) {
1123 Status
= ResetNotify
->UnregisterResetNotify (ResetNotify
, NvmeShutdownAllControllers
);
1124 ASSERT_EFI_ERROR (Status
);