TianoCore EDK2 master
Loading...
Searching...
No Matches
NvmExpressHci.c
Go to the documentation of this file.
1
10#include "NvmExpress.h"
11#include <Guid/NVMeEventGroup.h>
12
13#define NVME_SHUTDOWN_PROCESS_TIMEOUT 45
14
15//
16// The number of NVME controllers managed by this driver, used by
17// NvmeRegisterShutdownNotification() and NvmeUnregisterShutdownNotification().
18//
19UINTN mNvmeControllerNumber = 0;
20
34 IN NVME_CAP *Cap
35 )
36{
38 EFI_STATUS Status;
39 UINT64 Data;
40
41 PciIo = Private->PciIo;
42 Status = PciIo->Mem.Read (
43 PciIo,
44 EfiPciIoWidthUint32,
45 NVME_BAR,
46 NVME_CAP_OFFSET,
47 2,
48 &Data
49 );
50
51 if (EFI_ERROR (Status)) {
52 return Status;
53 }
54
55 WriteUnaligned64 ((UINT64 *)Cap, Data);
56 return EFI_SUCCESS;
57}
58
72 IN NVME_CC *Cc
73 )
74{
76 EFI_STATUS Status;
77 UINT32 Data;
78
79 PciIo = Private->PciIo;
80 Status = PciIo->Mem.Read (
81 PciIo,
82 EfiPciIoWidthUint32,
83 NVME_BAR,
84 NVME_CC_OFFSET,
85 1,
86 &Data
87 );
88
89 if (EFI_ERROR (Status)) {
90 return Status;
91 }
92
93 WriteUnaligned32 ((UINT32 *)Cc, Data);
94 return EFI_SUCCESS;
95}
96
110 IN NVME_CC *Cc
111 )
112{
113 EFI_PCI_IO_PROTOCOL *PciIo;
114 EFI_STATUS Status;
115 UINT32 Data;
116
117 PciIo = Private->PciIo;
118 Data = ReadUnaligned32 ((UINT32 *)Cc);
119 Status = PciIo->Mem.Write (
120 PciIo,
121 EfiPciIoWidthUint32,
122 NVME_BAR,
123 NVME_CC_OFFSET,
124 1,
125 &Data
126 );
127
128 if (EFI_ERROR (Status)) {
129 return Status;
130 }
131
132 DEBUG ((DEBUG_INFO, "Cc.En: %d\n", Cc->En));
133 DEBUG ((DEBUG_INFO, "Cc.Css: %d\n", Cc->Css));
134 DEBUG ((DEBUG_INFO, "Cc.Mps: %d\n", Cc->Mps));
135 DEBUG ((DEBUG_INFO, "Cc.Ams: %d\n", Cc->Ams));
136 DEBUG ((DEBUG_INFO, "Cc.Shn: %d\n", Cc->Shn));
137 DEBUG ((DEBUG_INFO, "Cc.Iosqes: %d\n", Cc->Iosqes));
138 DEBUG ((DEBUG_INFO, "Cc.Iocqes: %d\n", Cc->Iocqes));
139
140 return EFI_SUCCESS;
141}
142
156 IN NVME_CSTS *Csts
157 )
158{
159 EFI_PCI_IO_PROTOCOL *PciIo;
160 EFI_STATUS Status;
161 UINT32 Data;
162
163 PciIo = Private->PciIo;
164 Status = PciIo->Mem.Read (
165 PciIo,
166 EfiPciIoWidthUint32,
167 NVME_BAR,
168 NVME_CSTS_OFFSET,
169 1,
170 &Data
171 );
172
173 if (EFI_ERROR (Status)) {
174 return Status;
175 }
176
177 WriteUnaligned32 ((UINT32 *)Csts, Data);
178 return EFI_SUCCESS;
179}
180
194 IN NVME_AQA *Aqa
195 )
196{
197 EFI_PCI_IO_PROTOCOL *PciIo;
198 EFI_STATUS Status;
199 UINT32 Data;
200
201 PciIo = Private->PciIo;
202 Data = ReadUnaligned32 ((UINT32 *)Aqa);
203 Status = PciIo->Mem.Write (
204 PciIo,
205 EfiPciIoWidthUint32,
206 NVME_BAR,
207 NVME_AQA_OFFSET,
208 1,
209 &Data
210 );
211
212 if (EFI_ERROR (Status)) {
213 return Status;
214 }
215
216 DEBUG ((DEBUG_INFO, "Aqa.Asqs: %d\n", Aqa->Asqs));
217 DEBUG ((DEBUG_INFO, "Aqa.Acqs: %d\n", Aqa->Acqs));
218
219 return EFI_SUCCESS;
220}
221
235 IN NVME_ASQ *Asq
236 )
237{
238 EFI_PCI_IO_PROTOCOL *PciIo;
239 EFI_STATUS Status;
240 UINT64 Data;
241
242 PciIo = Private->PciIo;
243 Data = ReadUnaligned64 ((UINT64 *)Asq);
244
245 Status = PciIo->Mem.Write (
246 PciIo,
247 EfiPciIoWidthUint32,
248 NVME_BAR,
249 NVME_ASQ_OFFSET,
250 2,
251 &Data
252 );
253
254 if (EFI_ERROR (Status)) {
255 return Status;
256 }
257
258 DEBUG ((DEBUG_INFO, "Asq: %lx\n", *Asq));
259
260 return EFI_SUCCESS;
261}
262
276 IN NVME_ACQ *Acq
277 )
278{
279 EFI_PCI_IO_PROTOCOL *PciIo;
280 EFI_STATUS Status;
281 UINT64 Data;
282
283 PciIo = Private->PciIo;
284 Data = ReadUnaligned64 ((UINT64 *)Acq);
285
286 Status = PciIo->Mem.Write (
287 PciIo,
288 EfiPciIoWidthUint32,
289 NVME_BAR,
290 NVME_ACQ_OFFSET,
291 2,
292 &Data
293 );
294
295 if (EFI_ERROR (Status)) {
296 return Status;
297 }
298
299 DEBUG ((DEBUG_INFO, "Acq: %lxh\n", *Acq));
300
301 return EFI_SUCCESS;
302}
303
316 )
317{
318 NVME_CC Cc;
319 NVME_CSTS Csts;
320 EFI_STATUS Status;
321 UINT32 Index;
322 UINT8 Timeout;
323
324 //
325 // Read Controller Configuration Register.
326 //
327 Status = ReadNvmeControllerConfiguration (Private, &Cc);
328 if (EFI_ERROR (Status)) {
329 return Status;
330 }
331
332 Cc.En = 0;
333
334 //
335 // Disable the controller.
336 //
337 Status = WriteNvmeControllerConfiguration (Private, &Cc);
338
339 if (EFI_ERROR (Status)) {
340 return Status;
341 }
342
343 //
344 // Cap.To specifies max delay time in 500ms increments for Csts.Rdy to transition from 1 to 0 after
345 // Cc.Enable transition from 1 to 0. Loop produces a 1 millisecond delay per itteration, up to 500 * Cap.To.
346 //
347 if (Private->Cap.To == 0) {
348 Timeout = 1;
349 } else {
350 Timeout = Private->Cap.To;
351 }
352
353 for (Index = (Timeout * 500); Index != 0; --Index) {
354 gBS->Stall (1000);
355
356 //
357 // Check if the controller is initialized
358 //
359 Status = ReadNvmeControllerStatus (Private, &Csts);
360
361 if (EFI_ERROR (Status)) {
362 return Status;
363 }
364
365 if (Csts.Rdy == 0) {
366 break;
367 }
368 }
369
370 if (Index == 0) {
371 Status = EFI_DEVICE_ERROR;
373 (EFI_ERROR_CODE | EFI_ERROR_MAJOR),
374 (EFI_IO_BUS_SCSI | EFI_IOB_EC_INTERFACE_ERROR)
375 );
376 }
377
378 DEBUG ((DEBUG_INFO, "NVMe controller is disabled with status [%r].\n", Status));
379 return Status;
380}
381
395 )
396{
397 NVME_CC Cc;
398 NVME_CSTS Csts;
399 EFI_STATUS Status;
400 UINT32 Index;
401 UINT8 Timeout;
402
403 EfiEventGroupSignal (&gNVMeEnableStartEventGroupGuid);
404
405 //
406 // Enable the controller.
407 // CC.AMS, CC.MPS and CC.CSS are all set to 0.
408 //
409 ZeroMem (&Cc, sizeof (NVME_CC));
410 Cc.En = 1;
411 Cc.Iosqes = 6;
412 Cc.Iocqes = 4;
413
414 Status = WriteNvmeControllerConfiguration (Private, &Cc);
415 if (EFI_ERROR (Status)) {
416 goto Cleanup;
417 }
418
419 //
420 // Cap.To specifies max delay time in 500ms increments for Csts.Rdy to set after
421 // Cc.Enable. Loop produces a 1 millisecond delay per itteration, up to 500 * Cap.To.
422 //
423 if (Private->Cap.To == 0) {
424 Timeout = 1;
425 } else {
426 Timeout = Private->Cap.To;
427 }
428
429 for (Index = (Timeout * 500); Index != 0; --Index) {
430 gBS->Stall (1000);
431
432 //
433 // Check if the controller is initialized
434 //
435 Status = ReadNvmeControllerStatus (Private, &Csts);
436
437 if (EFI_ERROR (Status)) {
438 goto Cleanup;
439 }
440
441 if (Csts.Rdy) {
442 break;
443 }
444 }
445
446 if (Index == 0) {
447 Status = EFI_TIMEOUT;
449 (EFI_ERROR_CODE | EFI_ERROR_MAJOR),
450 (EFI_IO_BUS_SCSI | EFI_IOB_EC_INTERFACE_ERROR)
451 );
452 }
453
454 DEBUG ((DEBUG_INFO, "NVMe controller is enabled with status [%r].\n", Status));
455
456Cleanup:
457 EfiEventGroupSignal (&gNVMeEnableCompleteEventGroupGuid);
458 return Status;
459}
460
474 IN VOID *Buffer
475 )
476{
480 EFI_STATUS Status;
481
482 ZeroMem (&CommandPacket, sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
483 ZeroMem (&Command, sizeof (EFI_NVM_EXPRESS_COMMAND));
484 ZeroMem (&Completion, sizeof (EFI_NVM_EXPRESS_COMPLETION));
485
486 Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_CMD;
487 //
488 // According to Nvm Express 1.1 spec Figure 38, When not used, the field shall be cleared to 0h.
489 // For the Identify command, the Namespace Identifier is only used for the Namespace data structure.
490 //
491 Command.Nsid = 0;
492
493 CommandPacket.NvmeCmd = &Command;
494 CommandPacket.NvmeCompletion = &Completion;
495 CommandPacket.TransferBuffer = Buffer;
496 CommandPacket.TransferLength = sizeof (NVME_ADMIN_CONTROLLER_DATA);
497 CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
498 CommandPacket.QueueType = NVME_ADMIN_QUEUE;
499 //
500 // Set bit 0 (Cns bit) to 1 to identify a controller
501 //
502 Command.Cdw10 = 1;
503 Command.Flags = CDW10_VALID;
504
505 Status = Private->Passthru.PassThru (
506 &Private->Passthru,
507 NVME_CONTROLLER_ID,
508 &CommandPacket,
509 NULL
510 );
511
512 return Status;
513}
514
529 IN UINT32 NamespaceId,
530 IN VOID *Buffer
531 )
532{
536 EFI_STATUS Status;
537
538 ZeroMem (&CommandPacket, sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
539 ZeroMem (&Command, sizeof (EFI_NVM_EXPRESS_COMMAND));
540 ZeroMem (&Completion, sizeof (EFI_NVM_EXPRESS_COMPLETION));
541
542 CommandPacket.NvmeCmd = &Command;
543 CommandPacket.NvmeCompletion = &Completion;
544
545 Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_CMD;
546 Command.Nsid = NamespaceId;
547 CommandPacket.TransferBuffer = Buffer;
548 CommandPacket.TransferLength = sizeof (NVME_ADMIN_NAMESPACE_DATA);
549 CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
550 CommandPacket.QueueType = NVME_ADMIN_QUEUE;
551 //
552 // Set bit 0 (Cns bit) to 1 to identify a namespace
553 //
554 CommandPacket.NvmeCmd->Cdw10 = 0;
555 CommandPacket.NvmeCmd->Flags = CDW10_VALID;
556
557 Status = Private->Passthru.PassThru (
558 &Private->Passthru,
559 NamespaceId,
560 &CommandPacket,
561 NULL
562 );
563
564 return Status;
565}
566
579 )
580{
584 EFI_STATUS Status;
585 NVME_ADMIN_CRIOCQ CrIoCq;
586 UINT32 Index;
587 UINT16 QueueSize;
588
589 Status = EFI_SUCCESS;
590 Private->CreateIoQueue = TRUE;
591
592 for (Index = 1; Index < NVME_MAX_QUEUES; Index++) {
593 ZeroMem (&CommandPacket, sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
594 ZeroMem (&Command, sizeof (EFI_NVM_EXPRESS_COMMAND));
595 ZeroMem (&Completion, sizeof (EFI_NVM_EXPRESS_COMPLETION));
596 ZeroMem (&CrIoCq, sizeof (NVME_ADMIN_CRIOCQ));
597
598 CommandPacket.NvmeCmd = &Command;
599 CommandPacket.NvmeCompletion = &Completion;
600
601 Command.Cdw0.Opcode = NVME_ADMIN_CRIOCQ_CMD;
602 CommandPacket.TransferBuffer = Private->CqBufferPciAddr[Index];
603 CommandPacket.TransferLength = EFI_PAGE_SIZE;
604 CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
605 CommandPacket.QueueType = NVME_ADMIN_QUEUE;
606
607 if (Index == 1) {
608 QueueSize = NVME_CCQ_SIZE;
609 } else {
610 if (Private->Cap.Mqes > NVME_ASYNC_CCQ_SIZE) {
611 QueueSize = NVME_ASYNC_CCQ_SIZE;
612 } else {
613 QueueSize = Private->Cap.Mqes;
614 }
615 }
616
617 CrIoCq.Qid = Index;
618 CrIoCq.Qsize = QueueSize;
619 CrIoCq.Pc = 1;
620 CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoCq, sizeof (NVME_ADMIN_CRIOCQ));
621 CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
622
623 Status = Private->Passthru.PassThru (
624 &Private->Passthru,
625 0,
626 &CommandPacket,
627 NULL
628 );
629 if (EFI_ERROR (Status)) {
630 break;
631 }
632 }
633
634 Private->CreateIoQueue = FALSE;
635
636 return Status;
637}
638
651 )
652{
656 EFI_STATUS Status;
657 NVME_ADMIN_CRIOSQ CrIoSq;
658 UINT32 Index;
659 UINT16 QueueSize;
660
661 Status = EFI_SUCCESS;
662 Private->CreateIoQueue = TRUE;
663
664 for (Index = 1; Index < NVME_MAX_QUEUES; Index++) {
665 ZeroMem (&CommandPacket, sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
666 ZeroMem (&Command, sizeof (EFI_NVM_EXPRESS_COMMAND));
667 ZeroMem (&Completion, sizeof (EFI_NVM_EXPRESS_COMPLETION));
668 ZeroMem (&CrIoSq, sizeof (NVME_ADMIN_CRIOSQ));
669
670 CommandPacket.NvmeCmd = &Command;
671 CommandPacket.NvmeCompletion = &Completion;
672
673 Command.Cdw0.Opcode = NVME_ADMIN_CRIOSQ_CMD;
674 CommandPacket.TransferBuffer = Private->SqBufferPciAddr[Index];
675 CommandPacket.TransferLength = EFI_PAGE_SIZE;
676 CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
677 CommandPacket.QueueType = NVME_ADMIN_QUEUE;
678
679 if (Index == 1) {
680 QueueSize = NVME_CSQ_SIZE;
681 } else {
682 if (Private->Cap.Mqes > NVME_ASYNC_CSQ_SIZE) {
683 QueueSize = NVME_ASYNC_CSQ_SIZE;
684 } else {
685 QueueSize = Private->Cap.Mqes;
686 }
687 }
688
689 CrIoSq.Qid = Index;
690 CrIoSq.Qsize = QueueSize;
691 CrIoSq.Pc = 1;
692 CrIoSq.Cqid = Index;
693 CrIoSq.Qprio = 0;
694 CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoSq, sizeof (NVME_ADMIN_CRIOSQ));
695 CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
696
697 Status = Private->Passthru.PassThru (
698 &Private->Passthru,
699 0,
700 &CommandPacket,
701 NULL
702 );
703 if (EFI_ERROR (Status)) {
704 break;
705 }
706 }
707
708 Private->CreateIoQueue = FALSE;
709
710 return Status;
711}
712
725 )
726{
727 EFI_STATUS Status;
728 EFI_PCI_IO_PROTOCOL *PciIo;
729 UINT64 Supports;
730 NVME_AQA Aqa;
731 NVME_ASQ Asq;
732 NVME_ACQ Acq;
733 UINT8 Sn[21];
734 UINT8 Mn[41];
735
736 //
737 // Enable this controller.
738 //
739 PciIo = Private->PciIo;
740 Status = PciIo->Attributes (
741 PciIo,
743 0,
744 &Supports
745 );
746
747 if (!EFI_ERROR (Status)) {
748 Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
749 Status = PciIo->Attributes (
750 PciIo,
752 Supports,
753 NULL
754 );
755 }
756
757 if (EFI_ERROR (Status)) {
758 DEBUG ((DEBUG_INFO, "NvmeControllerInit: failed to enable controller\n"));
759 return Status;
760 }
761
762 //
763 // Read the Controller Capabilities register and verify that the NVM command set is supported
764 //
765 Status = ReadNvmeControllerCapabilities (Private, &Private->Cap);
766 if (EFI_ERROR (Status)) {
767 return Status;
768 }
769
770 if ((Private->Cap.Css & BIT0) == 0) {
771 DEBUG ((DEBUG_INFO, "NvmeControllerInit: the controller doesn't support NVMe command set\n"));
772 return EFI_UNSUPPORTED;
773 }
774
775 //
776 // Currently the driver only supports 4k page size.
777 //
778 ASSERT ((Private->Cap.Mpsmin + 12) <= EFI_PAGE_SHIFT);
779
780 Private->Cid[0] = 0;
781 Private->Cid[1] = 0;
782 Private->Cid[2] = 0;
783 Private->Pt[0] = 0;
784 Private->Pt[1] = 0;
785 Private->Pt[2] = 0;
786 Private->SqTdbl[0].Sqt = 0;
787 Private->SqTdbl[1].Sqt = 0;
788 Private->SqTdbl[2].Sqt = 0;
789 Private->CqHdbl[0].Cqh = 0;
790 Private->CqHdbl[1].Cqh = 0;
791 Private->CqHdbl[2].Cqh = 0;
792 Private->AsyncSqHead = 0;
793
794 Status = NvmeDisableController (Private);
795
796 if (EFI_ERROR (Status)) {
797 return Status;
798 }
799
800 //
801 // set number of entries admin submission & completion queues.
802 //
803 Aqa.Asqs = NVME_ASQ_SIZE;
804 Aqa.Rsvd1 = 0;
805 Aqa.Acqs = NVME_ACQ_SIZE;
806 Aqa.Rsvd2 = 0;
807
808 //
809 // Address of admin submission queue.
810 //
811 Asq = (UINT64)(UINTN)(Private->BufferPciAddr) & ~0xFFF;
812
813 //
814 // Address of admin completion queue.
815 //
816 Acq = (UINT64)(UINTN)(Private->BufferPciAddr + EFI_PAGE_SIZE) & ~0xFFF;
817
818 //
819 // Address of I/O submission & completion queue.
820 //
821 ZeroMem (Private->Buffer, EFI_PAGES_TO_SIZE (6));
822 Private->SqBuffer[0] = (NVME_SQ *)(UINTN)(Private->Buffer);
823 Private->SqBufferPciAddr[0] = (NVME_SQ *)(UINTN)(Private->BufferPciAddr);
824 Private->CqBuffer[0] = (NVME_CQ *)(UINTN)(Private->Buffer + 1 * EFI_PAGE_SIZE);
825 Private->CqBufferPciAddr[0] = (NVME_CQ *)(UINTN)(Private->BufferPciAddr + 1 * EFI_PAGE_SIZE);
826 Private->SqBuffer[1] = (NVME_SQ *)(UINTN)(Private->Buffer + 2 * EFI_PAGE_SIZE);
827 Private->SqBufferPciAddr[1] = (NVME_SQ *)(UINTN)(Private->BufferPciAddr + 2 * EFI_PAGE_SIZE);
828 Private->CqBuffer[1] = (NVME_CQ *)(UINTN)(Private->Buffer + 3 * EFI_PAGE_SIZE);
829 Private->CqBufferPciAddr[1] = (NVME_CQ *)(UINTN)(Private->BufferPciAddr + 3 * EFI_PAGE_SIZE);
830 Private->SqBuffer[2] = (NVME_SQ *)(UINTN)(Private->Buffer + 4 * EFI_PAGE_SIZE);
831 Private->SqBufferPciAddr[2] = (NVME_SQ *)(UINTN)(Private->BufferPciAddr + 4 * EFI_PAGE_SIZE);
832 Private->CqBuffer[2] = (NVME_CQ *)(UINTN)(Private->Buffer + 5 * EFI_PAGE_SIZE);
833 Private->CqBufferPciAddr[2] = (NVME_CQ *)(UINTN)(Private->BufferPciAddr + 5 * EFI_PAGE_SIZE);
834
835 DEBUG ((DEBUG_INFO, "Private->Buffer = [%016X]\n", (UINT64)(UINTN)Private->Buffer));
836 DEBUG ((DEBUG_INFO, "Admin Submission Queue size (Aqa.Asqs) = [%08X]\n", Aqa.Asqs));
837 DEBUG ((DEBUG_INFO, "Admin Completion Queue size (Aqa.Acqs) = [%08X]\n", Aqa.Acqs));
838 DEBUG ((DEBUG_INFO, "Admin Submission Queue (SqBuffer[0]) = [%016X]\n", Private->SqBuffer[0]));
839 DEBUG ((DEBUG_INFO, "Admin Completion Queue (CqBuffer[0]) = [%016X]\n", Private->CqBuffer[0]));
840 DEBUG ((DEBUG_INFO, "Sync I/O Submission Queue (SqBuffer[1]) = [%016X]\n", Private->SqBuffer[1]));
841 DEBUG ((DEBUG_INFO, "Sync I/O Completion Queue (CqBuffer[1]) = [%016X]\n", Private->CqBuffer[1]));
842 DEBUG ((DEBUG_INFO, "Async I/O Submission Queue (SqBuffer[2]) = [%016X]\n", Private->SqBuffer[2]));
843 DEBUG ((DEBUG_INFO, "Async I/O Completion Queue (CqBuffer[2]) = [%016X]\n", Private->CqBuffer[2]));
844
845 //
846 // Program admin queue attributes.
847 //
848 Status = WriteNvmeAdminQueueAttributes (Private, &Aqa);
849
850 if (EFI_ERROR (Status)) {
851 return Status;
852 }
853
854 //
855 // Program admin submission queue address.
856 //
857 Status = WriteNvmeAdminSubmissionQueueBaseAddress (Private, &Asq);
858
859 if (EFI_ERROR (Status)) {
860 return Status;
861 }
862
863 //
864 // Program admin completion queue address.
865 //
866 Status = WriteNvmeAdminCompletionQueueBaseAddress (Private, &Acq);
867
868 if (EFI_ERROR (Status)) {
869 return Status;
870 }
871
872 Status = NvmeEnableController (Private);
873 if (EFI_ERROR (Status)) {
874 return Status;
875 }
876
877 //
878 // Allocate buffer for Identify Controller data
879 //
880 if (Private->ControllerData == NULL) {
881 Private->ControllerData = (NVME_ADMIN_CONTROLLER_DATA *)AllocateZeroPool (sizeof (NVME_ADMIN_CONTROLLER_DATA));
882
883 if (Private->ControllerData == NULL) {
884 return EFI_OUT_OF_RESOURCES;
885 }
886 }
887
888 //
889 // Get current Identify Controller Data
890 //
891 Status = NvmeIdentifyController (Private, Private->ControllerData);
892
893 if (EFI_ERROR (Status)) {
894 FreePool (Private->ControllerData);
895 Private->ControllerData = NULL;
896 return EFI_NOT_FOUND;
897 }
898
899 //
900 // Dump NvmExpress Identify Controller Data
901 //
902 CopyMem (Sn, Private->ControllerData->Sn, sizeof (Private->ControllerData->Sn));
903 Sn[20] = 0;
904 CopyMem (Mn, Private->ControllerData->Mn, sizeof (Private->ControllerData->Mn));
905 Mn[40] = 0;
906 DEBUG ((DEBUG_INFO, " == NVME IDENTIFY CONTROLLER DATA ==\n"));
907 DEBUG ((DEBUG_INFO, " PCI VID : 0x%x\n", Private->ControllerData->Vid));
908 DEBUG ((DEBUG_INFO, " PCI SSVID : 0x%x\n", Private->ControllerData->Ssvid));
909 DEBUG ((DEBUG_INFO, " SN : %a\n", Sn));
910 DEBUG ((DEBUG_INFO, " MN : %a\n", Mn));
911 DEBUG ((DEBUG_INFO, " FR : 0x%x\n", *((UINT64 *)Private->ControllerData->Fr)));
912 DEBUG ((DEBUG_INFO, " TNVMCAP (high 8-byte) : 0x%lx\n", *((UINT64 *)(Private->ControllerData->Tnvmcap + 8))));
913 DEBUG ((DEBUG_INFO, " TNVMCAP (low 8-byte) : 0x%lx\n", *((UINT64 *)Private->ControllerData->Tnvmcap)));
914 DEBUG ((DEBUG_INFO, " RAB : 0x%x\n", Private->ControllerData->Rab));
915 DEBUG ((DEBUG_INFO, " IEEE : 0x%x\n", *(UINT32 *)Private->ControllerData->Ieee_oui));
916 DEBUG ((DEBUG_INFO, " AERL : 0x%x\n", Private->ControllerData->Aerl));
917 DEBUG ((DEBUG_INFO, " SQES : 0x%x\n", Private->ControllerData->Sqes));
918 DEBUG ((DEBUG_INFO, " CQES : 0x%x\n", Private->ControllerData->Cqes));
919 DEBUG ((DEBUG_INFO, " NN : 0x%x\n", Private->ControllerData->Nn));
920
921 //
922 // Create two I/O completion queues.
923 // One for blocking I/O, one for non-blocking I/O.
924 //
925 Status = NvmeCreateIoCompletionQueue (Private);
926 if (EFI_ERROR (Status)) {
927 return Status;
928 }
929
930 //
931 // Create two I/O Submission queues.
932 // One for blocking I/O, one for non-blocking I/O.
933 //
934 Status = NvmeCreateIoSubmissionQueue (Private);
935
936 return Status;
937}
938
954VOID
955EFIAPI
957 IN EFI_RESET_TYPE ResetType,
958 IN EFI_STATUS ResetStatus,
959 IN UINTN DataSize,
960 IN VOID *ResetData OPTIONAL
961 )
962{
963 EFI_STATUS Status;
964 EFI_HANDLE *Handles;
965 UINTN HandleCount;
966 UINTN HandleIndex;
968 UINTN OpenInfoCount;
969 UINTN OpenInfoIndex;
971 NVME_CC Cc;
972 NVME_CSTS Csts;
973 UINTN Index;
975
976 Status = gBS->LocateHandleBuffer (
978 &gEfiPciIoProtocolGuid,
979 NULL,
980 &HandleCount,
981 &Handles
982 );
983 if (EFI_ERROR (Status)) {
984 HandleCount = 0;
985 }
986
987 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
988 Status = gBS->OpenProtocolInformation (
989 Handles[HandleIndex],
990 &gEfiPciIoProtocolGuid,
991 &OpenInfos,
992 &OpenInfoCount
993 );
994 if (EFI_ERROR (Status)) {
995 continue;
996 }
997
998 for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
999 //
1000 // Find all the NVME controller managed by this driver.
1001 // gImageHandle equals to DriverBinding handle for this driver.
1002 //
1003 if (((OpenInfos[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) &&
1004 (OpenInfos[OpenInfoIndex].AgentHandle == gImageHandle))
1005 {
1006 Status = gBS->OpenProtocol (
1007 OpenInfos[OpenInfoIndex].ControllerHandle,
1008 &gEfiNvmExpressPassThruProtocolGuid,
1009 (VOID **)&NvmePassThru,
1010 NULL,
1011 NULL,
1012 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1013 );
1014 if (EFI_ERROR (Status)) {
1015 continue;
1016 }
1017
1018 Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (NvmePassThru);
1019
1020 //
1021 // Read Controller Configuration Register.
1022 //
1023 Status = ReadNvmeControllerConfiguration (Private, &Cc);
1024 if (EFI_ERROR (Status)) {
1025 continue;
1026 }
1027
1028 //
1029 // The host should set the Shutdown Notification (CC.SHN) field to 01b
1030 // to indicate a normal shutdown operation.
1031 //
1032 Cc.Shn = NVME_CC_SHN_NORMAL_SHUTDOWN;
1033 Status = WriteNvmeControllerConfiguration (Private, &Cc);
1034 if (EFI_ERROR (Status)) {
1035 continue;
1036 }
1037
1038 //
1039 // The controller indicates when shutdown processing is completed by updating the
1040 // Shutdown Status (CSTS.SHST) field to 10b.
1041 // Wait up to 45 seconds (break down to 4500 x 10ms) for the shutdown to complete.
1042 //
1043 for (Index = 0; Index < NVME_SHUTDOWN_PROCESS_TIMEOUT * 100; Index++) {
1044 Status = ReadNvmeControllerStatus (Private, &Csts);
1045 if (!EFI_ERROR (Status) && (Csts.Shst == NVME_CSTS_SHST_SHUTDOWN_COMPLETED)) {
1046 DEBUG ((DEBUG_INFO, "NvmeShutdownController: shutdown processing is completed after %dms.\n", Index * 10));
1047 break;
1048 }
1049
1050 //
1051 // Stall for 10ms
1052 //
1053 gBS->Stall (10 * 1000);
1054 }
1055
1056 if (Index == NVME_SHUTDOWN_PROCESS_TIMEOUT * 100) {
1057 DEBUG ((DEBUG_ERROR, "NvmeShutdownController: shutdown processing is timed out\n"));
1058 }
1059 }
1060 }
1061 }
1062}
1063
1069VOID
1071 VOID
1072 )
1073{
1074 EFI_STATUS Status;
1076
1077 mNvmeControllerNumber++;
1078 if (mNvmeControllerNumber == 1) {
1079 Status = gBS->LocateProtocol (&gEfiResetNotificationProtocolGuid, NULL, (VOID **)&ResetNotify);
1080 if (!EFI_ERROR (Status)) {
1081 Status = ResetNotify->RegisterResetNotify (ResetNotify, NvmeShutdownAllControllers);
1082 ASSERT_EFI_ERROR (Status);
1083 } else {
1084 DEBUG ((DEBUG_WARN, "NVME: ResetNotification absent! Shutdown notification cannot be performed!\n"));
1085 }
1086 }
1087}
1088
1094VOID
1096 VOID
1097 )
1098{
1099 EFI_STATUS Status;
1101
1102 mNvmeControllerNumber--;
1103 if (mNvmeControllerNumber == 0) {
1104 Status = gBS->LocateProtocol (&gEfiResetNotificationProtocolGuid, NULL, (VOID **)&ResetNotify);
1105 if (!EFI_ERROR (Status)) {
1106 Status = ResetNotify->UnregisterResetNotify (ResetNotify, NvmeShutdownAllControllers);
1107 ASSERT_EFI_ERROR (Status);
1108 }
1109 }
1110}
UINT64 UINTN
UINT64 EFIAPI ReadUnaligned64(IN CONST UINT64 *Buffer)
Definition: Unaligned.c:204
UINT32 EFIAPI WriteUnaligned32(OUT UINT32 *Buffer, IN UINT32 Value)
Definition: Unaligned.c:177
UINT64 EFIAPI WriteUnaligned64(OUT UINT64 *Buffer, IN UINT64 Value)
Definition: Unaligned.c:236
UINT32 EFIAPI ReadUnaligned32(IN CONST UINT32 *Buffer)
Definition: Unaligned.c:145
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define REPORT_STATUS_CODE(Type, Value)
@ EfiPciIoAttributeOperationEnable
Definition: PciIo.h:111
@ EfiPciIoAttributeOperationSupported
Definition: PciIo.h:119
EFI_STATUS WriteNvmeAdminQueueAttributes(IN NVME_CONTROLLER_PRIVATE_DATA *Private, IN NVME_AQA *Aqa)
EFI_STATUS ReadNvmeControllerConfiguration(IN NVME_CONTROLLER_PRIVATE_DATA *Private, IN NVME_CC *Cc)
Definition: NvmExpressHci.c:70
EFI_STATUS WriteNvmeControllerConfiguration(IN NVME_CONTROLLER_PRIVATE_DATA *Private, IN NVME_CC *Cc)
EFI_STATUS NvmeDisableController(IN NVME_CONTROLLER_PRIVATE_DATA *Private)
EFI_STATUS NvmeEnableController(IN NVME_CONTROLLER_PRIVATE_DATA *Private)
EFI_STATUS ReadNvmeControllerCapabilities(IN NVME_CONTROLLER_PRIVATE_DATA *Private, IN NVME_CAP *Cap)
Definition: NvmExpressHci.c:32
EFI_STATUS NvmeIdentifyNamespace(IN NVME_CONTROLLER_PRIVATE_DATA *Private, IN UINT32 NamespaceId, IN VOID *Buffer)
VOID NvmeRegisterShutdownNotification(VOID)
EFI_STATUS NvmeCreateIoSubmissionQueue(IN NVME_CONTROLLER_PRIVATE_DATA *Private)
VOID EFIAPI NvmeShutdownAllControllers(IN EFI_RESET_TYPE ResetType, IN EFI_STATUS ResetStatus, IN UINTN DataSize, IN VOID *ResetData OPTIONAL)
EFI_STATUS NvmeCreateIoCompletionQueue(IN NVME_CONTROLLER_PRIVATE_DATA *Private)
EFI_STATUS NvmeIdentifyController(IN NVME_CONTROLLER_PRIVATE_DATA *Private, IN VOID *Buffer)
EFI_STATUS WriteNvmeAdminSubmissionQueueBaseAddress(IN NVME_CONTROLLER_PRIVATE_DATA *Private, IN NVME_ASQ *Asq)
EFI_STATUS ReadNvmeControllerStatus(IN NVME_CONTROLLER_PRIVATE_DATA *Private, IN NVME_CSTS *Csts)
VOID NvmeUnregisterShutdownNotification(VOID)
EFI_STATUS WriteNvmeAdminCompletionQueueBaseAddress(IN NVME_CONTROLLER_PRIVATE_DATA *Private, IN NVME_ACQ *Acq)
EFI_STATUS NvmeControllerInit(IN NVME_CONTROLLER_PRIVATE_DATA *Private)
EFI_STATUS EFIAPI NvmePassThru(IN EDKII_PEI_NVM_EXPRESS_PASS_THRU_PPI *This, IN UINT32 NamespaceId, IN OUT EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet)
#define EFI_PAGES_TO_SIZE(Pages)
Definition: UefiBaseType.h:213
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_HANDLE gImageHandle
EFI_BOOT_SERVICES * gBS
EFI_STATUS EFIAPI EfiEventGroupSignal(IN CONST EFI_GUID *EventGroup)
Definition: UefiLib.c:314
EFI_RESET_TYPE
@ ByProtocol
Definition: UefiSpec.h:1518
EFI_PCI_IO_PROTOCOL_IO_MEM Write
Definition: PciIo.h:197
EFI_PCI_IO_PROTOCOL_IO_MEM Read
Definition: PciIo.h:193
Definition: Nvme.h:113
Definition: Nvme.h:55
Definition: Nvme.h:84
Definition: Nvme.h:901
Definition: Nvme.h:865