2 NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows
3 NVM Express specification.
5 Copyright (c) 2013, 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"
19 Read Nvm Express controller capability register.
21 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
22 @param Cap The buffer used to store capability register content.
24 @return EFI_SUCCESS Successfully read the controller capability register content.
25 @return EFI_DEVICE_ERROR Fail to read the controller capability register.
29 ReadNvmeControllerCapabilities (
30 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
34 EFI_PCI_IO_PROTOCOL
*PciIo
;
37 PciIo
= Private
->PciIo
;
38 Status
= PciIo
->Mem
.Read (
47 if (EFI_ERROR(Status
)) {
55 Read Nvm Express controller configuration register.
57 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
58 @param Cc The buffer used to store configuration register content.
60 @return EFI_SUCCESS Successfully read the controller configuration register content.
61 @return EFI_DEVICE_ERROR Fail to read the controller configuration register.
65 ReadNvmeControllerConfiguration (
66 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
70 EFI_PCI_IO_PROTOCOL
*PciIo
;
73 PciIo
= Private
->PciIo
;
74 Status
= PciIo
->Mem
.Read (
83 if (EFI_ERROR(Status
)) {
91 Write Nvm Express controller configuration register.
93 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
94 @param Cc The buffer used to store the content to be written into configuration register.
96 @return EFI_SUCCESS Successfully write data into the controller configuration register.
97 @return EFI_DEVICE_ERROR Fail to write data into the controller configuration register.
101 WriteNvmeControllerConfiguration (
102 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
106 EFI_PCI_IO_PROTOCOL
*PciIo
;
109 PciIo
= Private
->PciIo
;
110 Status
= PciIo
->Mem
.Write (
119 if (EFI_ERROR(Status
)) {
123 DEBUG ((EFI_D_INFO
, "Cc.En: %d\n", Cc
->En
));
124 DEBUG ((EFI_D_INFO
, "Cc.Css: %d\n", Cc
->Css
));
125 DEBUG ((EFI_D_INFO
, "Cc.Mps: %d\n", Cc
->Mps
));
126 DEBUG ((EFI_D_INFO
, "Cc.Ams: %d\n", Cc
->Ams
));
127 DEBUG ((EFI_D_INFO
, "Cc.Shn: %d\n", Cc
->Shn
));
128 DEBUG ((EFI_D_INFO
, "Cc.Iosqes: %d\n", Cc
->Iosqes
));
129 DEBUG ((EFI_D_INFO
, "Cc.Iocqes: %d\n", Cc
->Iocqes
));
135 Read Nvm Express controller status register.
137 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
138 @param Csts The buffer used to store status register content.
140 @return EFI_SUCCESS Successfully read the controller status register content.
141 @return EFI_DEVICE_ERROR Fail to read the controller status register.
145 ReadNvmeControllerStatus (
146 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
150 EFI_PCI_IO_PROTOCOL
*PciIo
;
153 PciIo
= Private
->PciIo
;
154 Status
= PciIo
->Mem
.Read (
163 if (EFI_ERROR(Status
)) {
171 Read Nvm Express admin queue attributes register.
173 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
174 @param Aqa The buffer used to store admin queue attributes register content.
176 @return EFI_SUCCESS Successfully read the admin queue attributes register content.
177 @return EFI_DEVICE_ERROR Fail to read the admin queue attributes register.
181 ReadNvmeAdminQueueAttributes (
182 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
186 EFI_PCI_IO_PROTOCOL
*PciIo
;
189 PciIo
= Private
->PciIo
;
190 Status
= PciIo
->Mem
.Read (
199 if (EFI_ERROR(Status
)) {
207 Write Nvm Express admin queue attributes register.
209 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
210 @param Aqa The buffer used to store the content to be written into admin queue attributes register.
212 @return EFI_SUCCESS Successfully write data into the admin queue attributes register.
213 @return EFI_DEVICE_ERROR Fail to write data into the admin queue attributes register.
217 WriteNvmeAdminQueueAttributes (
218 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
222 EFI_PCI_IO_PROTOCOL
*PciIo
;
225 PciIo
= Private
->PciIo
;
226 Status
= PciIo
->Mem
.Write (
235 if (EFI_ERROR(Status
)) {
239 DEBUG ((EFI_D_INFO
, "Aqa.Asqs: %d\n", Aqa
->Asqs
));
240 DEBUG ((EFI_D_INFO
, "Aqa.Acqs: %d\n", Aqa
->Acqs
));
246 Read Nvm Express admin submission queue base address register.
248 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
249 @param Asq The buffer used to store admin submission queue base address register content.
251 @return EFI_SUCCESS Successfully read the admin submission queue base address register content.
252 @return EFI_DEVICE_ERROR Fail to read the admin submission queue base address register.
256 ReadNvmeAdminSubmissionQueueBaseAddress (
257 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
261 EFI_PCI_IO_PROTOCOL
*PciIo
;
264 PciIo
= Private
->PciIo
;
265 Status
= PciIo
->Mem
.Read (
274 if (EFI_ERROR(Status
)) {
282 Write Nvm Express admin submission queue base address register.
284 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
285 @param Asq The buffer used to store the content to be written into admin submission queue base address register.
287 @return EFI_SUCCESS Successfully write data into the admin submission queue base address register.
288 @return EFI_DEVICE_ERROR Fail to write data into the admin submission queue base address register.
292 WriteNvmeAdminSubmissionQueueBaseAddress (
293 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
297 EFI_PCI_IO_PROTOCOL
*PciIo
;
300 PciIo
= Private
->PciIo
;
301 Status
= PciIo
->Mem
.Write (
310 if (EFI_ERROR(Status
)) {
314 DEBUG ((EFI_D_INFO
, "Asq.Asqb: %lx\n", Asq
->Asqb
));
320 Read Nvm Express admin completion queue base address register.
322 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
323 @param Acq The buffer used to store admin completion queue base address register content.
325 @return EFI_SUCCESS Successfully read the admin completion queue base address register content.
326 @return EFI_DEVICE_ERROR Fail to read the admin completion queue base address register.
330 ReadNvmeAdminCompletionQueueBaseAddress (
331 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
335 EFI_PCI_IO_PROTOCOL
*PciIo
;
338 PciIo
= Private
->PciIo
;
339 Status
= PciIo
->Mem
.Read (
348 if (EFI_ERROR(Status
)) {
356 Write Nvm Express admin completion queue base address register.
358 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
359 @param Acq The buffer used to store the content to be written into admin completion queue base address register.
361 @return EFI_SUCCESS Successfully write data into the admin completion queue base address register.
362 @return EFI_DEVICE_ERROR Fail to write data into the admin completion queue base address register.
366 WriteNvmeAdminCompletionQueueBaseAddress (
367 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
371 EFI_PCI_IO_PROTOCOL
*PciIo
;
374 PciIo
= Private
->PciIo
;
375 Status
= PciIo
->Mem
.Write (
384 if (EFI_ERROR(Status
)) {
388 DEBUG ((EFI_D_INFO
, "Acq.Acqb: %lxh\n", Acq
->Acqb
));
394 Disable the Nvm Express controller.
396 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
398 @return EFI_SUCCESS Successfully disable the controller.
399 @return EFI_DEVICE_ERROR Fail to disable the controller.
403 NvmeDisableController (
404 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
412 // Read Controller Configuration Register.
414 Status
= ReadNvmeControllerConfiguration (Private
, &Cc
);
415 if (EFI_ERROR(Status
)) {
422 // Disable the controller.
424 Status
= WriteNvmeControllerConfiguration (Private
, &Cc
);
426 if (EFI_ERROR(Status
)) {
433 // Check if the controller is reset
435 Status
= ReadNvmeControllerStatus (Private
, &Csts
);
437 if (EFI_ERROR(Status
)) {
442 return EFI_DEVICE_ERROR
;
445 DEBUG ((EFI_D_INFO
, "NVMe controller is disabled with status [%r].\n", Status
));
450 Enable the Nvm Express controller.
452 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
454 @return EFI_SUCCESS Successfully enable the controller.
455 @return EFI_DEVICE_ERROR Fail to enable the controller.
456 @return EFI_TIMEOUT Fail to enable the controller in given time slot.
460 NvmeEnableController (
461 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
471 // Enable the controller
473 ZeroMem (&Cc
, sizeof (NVME_CC
));
477 Status
= WriteNvmeControllerConfiguration (Private
, &Cc
);
479 if (EFI_ERROR(Status
)) {
484 // Cap.To specifies max delay time in 500ms increments for Csts.Rdy to set after
485 // Cc.Enable. Loop produces a 1 millisecond delay per itteration, up to 500 * Cap.To.
487 if (Private
->Cap
.To
== 0) {
490 Timeout
= Private
->Cap
.To
;
493 for(Index
= (Timeout
* 500); Index
!= 0; --Index
) {
497 // Check if the controller is initialized
499 Status
= ReadNvmeControllerStatus (Private
, &Csts
);
501 if (EFI_ERROR(Status
)) {
511 Status
= EFI_TIMEOUT
;
514 DEBUG ((EFI_D_INFO
, "NVMe controller is enabled with status [%r].\n", Status
));
519 Get identify controller data.
521 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
522 @param Buffer The buffer used to store the identify controller data.
524 @return EFI_SUCCESS Successfully get the identify controller data.
525 @return EFI_DEVICE_ERROR Fail to get the identify controller data.
529 NvmeIdentifyController (
530 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
534 NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
535 NVM_EXPRESS_COMMAND Command
;
536 NVM_EXPRESS_RESPONSE Response
;
539 ZeroMem (&CommandPacket
, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
540 ZeroMem (&Command
, sizeof(NVM_EXPRESS_COMMAND
));
541 ZeroMem (&Response
, sizeof(NVM_EXPRESS_RESPONSE
));
543 Command
.Cdw0
.Opcode
= NVME_ADMIN_IDENTIFY_OPC
;
544 Command
.Cdw0
.Cid
= Private
->Cid
[0]++;
546 // According to Nvm Express 1.1 spec Figure 38, When not used, the field shall be cleared to 0h.
547 // For the Identify command, the Namespace Identifier is only used for the Namespace data structure.
551 CommandPacket
.NvmeCmd
= &Command
;
552 CommandPacket
.NvmeResponse
= &Response
;
553 CommandPacket
.TransferBuffer
= Buffer
;
554 CommandPacket
.TransferLength
= sizeof (NVME_ADMIN_CONTROLLER_DATA
);
555 CommandPacket
.CommandTimeout
= NVME_GENERIC_TIMEOUT
;
556 CommandPacket
.QueueId
= NVME_ADMIN_QUEUE
;
558 // Set bit 0 (Cns bit) to 1 to identify a controller
561 Command
.Flags
= CDW10_VALID
;
563 Status
= Private
->Passthru
.PassThru (
575 Get specified identify namespace data.
577 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
578 @param NamespaceId The specified namespace identifier.
579 @param Buffer The buffer used to store the identify namespace data.
581 @return EFI_SUCCESS Successfully get the identify namespace data.
582 @return EFI_DEVICE_ERROR Fail to get the identify namespace data.
586 NvmeIdentifyNamespace (
587 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
,
588 IN UINT32 NamespaceId
,
592 NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
593 NVM_EXPRESS_COMMAND Command
;
594 NVM_EXPRESS_RESPONSE Response
;
597 ZeroMem (&CommandPacket
, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
598 ZeroMem (&Command
, sizeof(NVM_EXPRESS_COMMAND
));
599 ZeroMem (&Response
, sizeof(NVM_EXPRESS_RESPONSE
));
601 CommandPacket
.NvmeCmd
= &Command
;
602 CommandPacket
.NvmeResponse
= &Response
;
604 Command
.Cdw0
.Opcode
= NVME_ADMIN_IDENTIFY_OPC
;
605 Command
.Cdw0
.Cid
= Private
->Cid
[0]++;
606 Command
.Nsid
= NamespaceId
;
607 CommandPacket
.TransferBuffer
= Buffer
;
608 CommandPacket
.TransferLength
= sizeof (NVME_ADMIN_NAMESPACE_DATA
);
609 CommandPacket
.CommandTimeout
= NVME_GENERIC_TIMEOUT
;
610 CommandPacket
.QueueId
= NVME_ADMIN_QUEUE
;
612 // Set bit 0 (Cns bit) to 1 to identify a namespace
614 CommandPacket
.NvmeCmd
->Cdw10
= 0;
615 CommandPacket
.NvmeCmd
->Flags
= CDW10_VALID
;
617 Status
= Private
->Passthru
.PassThru (
629 Create io completion queue.
631 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
633 @return EFI_SUCCESS Successfully create io completion queue.
634 @return EFI_DEVICE_ERROR Fail to create io completion queue.
638 NvmeCreateIoCompletionQueue (
639 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
642 NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
643 NVM_EXPRESS_COMMAND Command
;
644 NVM_EXPRESS_RESPONSE Response
;
646 NVME_ADMIN_CRIOCQ CrIoCq
;
648 ZeroMem (&CommandPacket
, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
649 ZeroMem (&Command
, sizeof(NVM_EXPRESS_COMMAND
));
650 ZeroMem (&Response
, sizeof(NVM_EXPRESS_RESPONSE
));
651 ZeroMem (&CrIoCq
, sizeof(NVME_ADMIN_CRIOCQ
));
653 CommandPacket
.NvmeCmd
= &Command
;
654 CommandPacket
.NvmeResponse
= &Response
;
656 Command
.Cdw0
.Opcode
= NVME_ADMIN_CRIOCQ_OPC
;
657 Command
.Cdw0
.Cid
= Private
->Cid
[0]++;
658 CommandPacket
.TransferBuffer
= Private
->CqBufferPciAddr
[1];
659 CommandPacket
.TransferLength
= EFI_PAGE_SIZE
;
660 CommandPacket
.CommandTimeout
= NVME_GENERIC_TIMEOUT
;
661 CommandPacket
.QueueId
= NVME_ADMIN_QUEUE
;
663 CrIoCq
.Qid
= NVME_IO_QUEUE
;
664 CrIoCq
.Qsize
= NVME_CCQ_SIZE
;
666 CopyMem (&CommandPacket
.NvmeCmd
->Cdw10
, &CrIoCq
, sizeof (NVME_ADMIN_CRIOCQ
));
667 CommandPacket
.NvmeCmd
->Flags
= CDW10_VALID
| CDW11_VALID
;
669 Status
= Private
->Passthru
.PassThru (
681 Create io submission queue.
683 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
685 @return EFI_SUCCESS Successfully create io submission queue.
686 @return EFI_DEVICE_ERROR Fail to create io submission queue.
690 NvmeCreateIoSubmissionQueue (
691 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
694 NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
695 NVM_EXPRESS_COMMAND Command
;
696 NVM_EXPRESS_RESPONSE Response
;
698 NVME_ADMIN_CRIOSQ CrIoSq
;
700 ZeroMem (&CommandPacket
, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
701 ZeroMem (&Command
, sizeof(NVM_EXPRESS_COMMAND
));
702 ZeroMem (&Response
, sizeof(NVM_EXPRESS_RESPONSE
));
703 ZeroMem (&CrIoSq
, sizeof(NVME_ADMIN_CRIOSQ
));
705 CommandPacket
.NvmeCmd
= &Command
;
706 CommandPacket
.NvmeResponse
= &Response
;
708 Command
.Cdw0
.Opcode
= NVME_ADMIN_CRIOSQ_OPC
;
709 Command
.Cdw0
.Cid
= Private
->Cid
[0]++;
710 CommandPacket
.TransferBuffer
= Private
->SqBufferPciAddr
[1];
711 CommandPacket
.TransferLength
= EFI_PAGE_SIZE
;
712 CommandPacket
.CommandTimeout
= NVME_GENERIC_TIMEOUT
;
713 CommandPacket
.QueueId
= NVME_ADMIN_QUEUE
;
715 CrIoSq
.Qid
= NVME_IO_QUEUE
;
716 CrIoSq
.Qsize
= NVME_CSQ_SIZE
;
718 CrIoSq
.Cqid
= NVME_IO_QUEUE
;
720 CopyMem (&CommandPacket
.NvmeCmd
->Cdw10
, &CrIoSq
, sizeof (NVME_ADMIN_CRIOSQ
));
721 CommandPacket
.NvmeCmd
->Flags
= CDW10_VALID
| CDW11_VALID
;
723 Status
= Private
->Passthru
.PassThru (
735 Initialize the Nvm Express controller.
737 @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
739 @retval EFI_SUCCESS The NVM Express Controller is initialized successfully.
740 @retval Others A device error occurred while initializing the controller.
745 IN NVME_CONTROLLER_PRIVATE_DATA
*Private
749 EFI_PCI_IO_PROTOCOL
*PciIo
;
756 // Save original PCI attributes and enable this controller.
758 PciIo
= Private
->PciIo
;
759 Status
= PciIo
->Attributes (
761 EfiPciIoAttributeOperationGet
,
763 &Private
->PciAttributes
766 if (EFI_ERROR (Status
)) {
770 Status
= PciIo
->Attributes (
772 EfiPciIoAttributeOperationSupported
,
777 if (!EFI_ERROR (Status
)) {
778 Supports
&= EFI_PCI_DEVICE_ENABLE
;
779 Status
= PciIo
->Attributes (
781 EfiPciIoAttributeOperationEnable
,
787 if (EFI_ERROR (Status
)) {
788 DEBUG ((EFI_D_INFO
, "NvmeControllerInit: failed to enable controller\n"));
793 // Read the Controller Capabilities register and verify that the NVM command set is supported
795 Status
= ReadNvmeControllerCapabilities (Private
, &Private
->Cap
);
796 if (EFI_ERROR (Status
)) {
800 if (Private
->Cap
.Css
!= 0x01) {
801 DEBUG ((EFI_D_INFO
, "NvmeControllerInit: the controller doesn't support NVMe command set\n"));
802 return EFI_UNSUPPORTED
;
806 // Currently the driver only supports 4k page size.
808 ASSERT ((Private
->Cap
.Mpsmin
+ 12) <= EFI_PAGE_SHIFT
);
813 Status
= NvmeDisableController (Private
);
815 if (EFI_ERROR(Status
)) {
820 // set number of entries admin submission & completion queues.
822 Aqa
.Asqs
= NVME_ASQ_SIZE
;
823 Aqa
.Acqs
= NVME_ACQ_SIZE
;
826 // Address of admin submission queue.
829 Asq
.Asqb
= (UINT64
)(UINTN
)(Private
->BufferPciAddr
) >> 12;
832 // Address of admin completion queue.
835 Acq
.Acqb
= (UINT64
)(UINTN
)(Private
->BufferPciAddr
+ EFI_PAGE_SIZE
) >> 12;
838 // Address of I/O submission & completion queue.
840 Private
->SqBuffer
[0] = (NVME_SQ
*)(UINTN
)(Private
->Buffer
);
841 Private
->SqBufferPciAddr
[0] = (NVME_SQ
*)(UINTN
)(Private
->BufferPciAddr
);
842 Private
->CqBuffer
[0] = (NVME_CQ
*)(UINTN
)(Private
->Buffer
+ 1 * EFI_PAGE_SIZE
);
843 Private
->CqBufferPciAddr
[0] = (NVME_CQ
*)(UINTN
)(Private
->BufferPciAddr
+ 1 * EFI_PAGE_SIZE
);
844 Private
->SqBuffer
[1] = (NVME_SQ
*)(UINTN
)(Private
->Buffer
+ 2 * EFI_PAGE_SIZE
);
845 Private
->SqBufferPciAddr
[1] = (NVME_SQ
*)(UINTN
)(Private
->BufferPciAddr
+ 2 * EFI_PAGE_SIZE
);
846 Private
->CqBuffer
[1] = (NVME_CQ
*)(UINTN
)(Private
->Buffer
+ 3 * EFI_PAGE_SIZE
);
847 Private
->CqBufferPciAddr
[1] = (NVME_CQ
*)(UINTN
)(Private
->BufferPciAddr
+ 3 * EFI_PAGE_SIZE
);
849 DEBUG ((EFI_D_INFO
, "Private->Buffer = [%016X]\n", (UINT64
)(UINTN
)Private
->Buffer
));
850 DEBUG ((EFI_D_INFO
, "Admin Submission Queue size (Aqa.Asqs) = [%08X]\n", Aqa
.Asqs
));
851 DEBUG ((EFI_D_INFO
, "Admin Completion Queue size (Aqa.Acqs) = [%08X]\n", Aqa
.Acqs
));
852 DEBUG ((EFI_D_INFO
, "Admin Submission Queue (SqBuffer[0]) = [%016X]\n", Private
->SqBuffer
[0]));
853 DEBUG ((EFI_D_INFO
, "Admin Completion Queue (CqBuffer[0]) = [%016X]\n", Private
->CqBuffer
[0]));
854 DEBUG ((EFI_D_INFO
, "I/O Submission Queue (SqBuffer[1]) = [%016X]\n", Private
->SqBuffer
[1]));
855 DEBUG ((EFI_D_INFO
, "I/O Completion Queue (CqBuffer[1]) = [%016X]\n", Private
->CqBuffer
[1]));
858 // Program admin queue attributes.
860 Status
= WriteNvmeAdminQueueAttributes (Private
, &Aqa
);
862 if (EFI_ERROR(Status
)) {
867 // Program admin submission queue address.
869 Status
= WriteNvmeAdminSubmissionQueueBaseAddress (Private
, &Asq
);
871 if (EFI_ERROR(Status
)) {
876 // Program admin completion queue address.
878 Status
= WriteNvmeAdminCompletionQueueBaseAddress (Private
, &Acq
);
880 if (EFI_ERROR(Status
)) {
884 Status
= NvmeEnableController (Private
);
885 if (EFI_ERROR(Status
)) {
890 // Create one I/O completion queue.
892 Status
= NvmeCreateIoCompletionQueue (Private
);
893 if (EFI_ERROR(Status
)) {
898 // Create one I/O Submission queue.
900 Status
= NvmeCreateIoSubmissionQueue (Private
);
901 if (EFI_ERROR(Status
)) {
906 // Allocate buffer for Identify Controller data
908 Private
->ControllerData
= (NVME_ADMIN_CONTROLLER_DATA
*)AllocateZeroPool (sizeof(NVME_ADMIN_CONTROLLER_DATA
));
910 if (Private
->ControllerData
== NULL
) {
911 return EFI_OUT_OF_RESOURCES
;
915 // Get current Identify Controller Data
917 Status
= NvmeIdentifyController (Private
, Private
->ControllerData
);
919 if (EFI_ERROR(Status
)) {
920 FreePool(Private
->ControllerData
);
921 Private
->ControllerData
= NULL
;
922 return EFI_NOT_FOUND
;