]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / NvmExpressDxe / NvmExpressHci.c
1 /** @file
2 NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows
3 NVM Express specification.
4
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.
10
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.
13
14 **/
15
16 #include "NvmExpress.h"
17
18 #define NVME_SHUTDOWN_PROCESS_TIMEOUT 45
19
20 //
21 // The number of NVME controllers managed by this driver, used by
22 // NvmeRegisterShutdownNotification() and NvmeUnregisterShutdownNotification().
23 //
24 UINTN mNvmeControllerNumber = 0;
25
26 /**
27 Read Nvm Express controller capability register.
28
29 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
30 @param Cap The buffer used to store capability register content.
31
32 @return EFI_SUCCESS Successfully read the controller capability register content.
33 @return EFI_DEVICE_ERROR Fail to read the controller capability register.
34
35 **/
36 EFI_STATUS
37 ReadNvmeControllerCapabilities (
38 IN NVME_CONTROLLER_PRIVATE_DATA *Private,
39 IN NVME_CAP *Cap
40 )
41 {
42 EFI_PCI_IO_PROTOCOL *PciIo;
43 EFI_STATUS Status;
44 UINT64 Data;
45
46 PciIo = Private->PciIo;
47 Status = PciIo->Mem.Read (
48 PciIo,
49 EfiPciIoWidthUint32,
50 NVME_BAR,
51 NVME_CAP_OFFSET,
52 2,
53 &Data
54 );
55
56 if (EFI_ERROR(Status)) {
57 return Status;
58 }
59
60 WriteUnaligned64 ((UINT64*)Cap, Data);
61 return EFI_SUCCESS;
62 }
63
64 /**
65 Read Nvm Express controller configuration register.
66
67 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
68 @param Cc The buffer used to store configuration register content.
69
70 @return EFI_SUCCESS Successfully read the controller configuration register content.
71 @return EFI_DEVICE_ERROR Fail to read the controller configuration register.
72
73 **/
74 EFI_STATUS
75 ReadNvmeControllerConfiguration (
76 IN NVME_CONTROLLER_PRIVATE_DATA *Private,
77 IN NVME_CC *Cc
78 )
79 {
80 EFI_PCI_IO_PROTOCOL *PciIo;
81 EFI_STATUS Status;
82 UINT32 Data;
83
84 PciIo = Private->PciIo;
85 Status = PciIo->Mem.Read (
86 PciIo,
87 EfiPciIoWidthUint32,
88 NVME_BAR,
89 NVME_CC_OFFSET,
90 1,
91 &Data
92 );
93
94 if (EFI_ERROR(Status)) {
95 return Status;
96 }
97
98 WriteUnaligned32 ((UINT32*)Cc, Data);
99 return EFI_SUCCESS;
100 }
101
102 /**
103 Write Nvm Express controller configuration register.
104
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.
107
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.
110
111 **/
112 EFI_STATUS
113 WriteNvmeControllerConfiguration (
114 IN NVME_CONTROLLER_PRIVATE_DATA *Private,
115 IN NVME_CC *Cc
116 )
117 {
118 EFI_PCI_IO_PROTOCOL *PciIo;
119 EFI_STATUS Status;
120 UINT32 Data;
121
122 PciIo = Private->PciIo;
123 Data = ReadUnaligned32 ((UINT32*)Cc);
124 Status = PciIo->Mem.Write (
125 PciIo,
126 EfiPciIoWidthUint32,
127 NVME_BAR,
128 NVME_CC_OFFSET,
129 1,
130 &Data
131 );
132
133 if (EFI_ERROR(Status)) {
134 return Status;
135 }
136
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));
144
145 return EFI_SUCCESS;
146 }
147
148 /**
149 Read Nvm Express controller status register.
150
151 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
152 @param Csts The buffer used to store status register content.
153
154 @return EFI_SUCCESS Successfully read the controller status register content.
155 @return EFI_DEVICE_ERROR Fail to read the controller status register.
156
157 **/
158 EFI_STATUS
159 ReadNvmeControllerStatus (
160 IN NVME_CONTROLLER_PRIVATE_DATA *Private,
161 IN NVME_CSTS *Csts
162 )
163 {
164 EFI_PCI_IO_PROTOCOL *PciIo;
165 EFI_STATUS Status;
166 UINT32 Data;
167
168 PciIo = Private->PciIo;
169 Status = PciIo->Mem.Read (
170 PciIo,
171 EfiPciIoWidthUint32,
172 NVME_BAR,
173 NVME_CSTS_OFFSET,
174 1,
175 &Data
176 );
177
178 if (EFI_ERROR(Status)) {
179 return Status;
180 }
181
182 WriteUnaligned32 ((UINT32*)Csts, Data);
183 return EFI_SUCCESS;
184 }
185
186 /**
187 Read Nvm Express admin queue attributes register.
188
189 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
190 @param Aqa The buffer used to store admin queue attributes register content.
191
192 @return EFI_SUCCESS Successfully read the admin queue attributes register content.
193 @return EFI_DEVICE_ERROR Fail to read the admin queue attributes register.
194
195 **/
196 EFI_STATUS
197 ReadNvmeAdminQueueAttributes (
198 IN NVME_CONTROLLER_PRIVATE_DATA *Private,
199 IN NVME_AQA *Aqa
200 )
201 {
202 EFI_PCI_IO_PROTOCOL *PciIo;
203 EFI_STATUS Status;
204 UINT32 Data;
205
206 PciIo = Private->PciIo;
207 Status = PciIo->Mem.Read (
208 PciIo,
209 EfiPciIoWidthUint32,
210 NVME_BAR,
211 NVME_AQA_OFFSET,
212 1,
213 &Data
214 );
215
216 if (EFI_ERROR(Status)) {
217 return Status;
218 }
219
220 WriteUnaligned32 ((UINT32*)Aqa, Data);
221 return EFI_SUCCESS;
222 }
223
224 /**
225 Write Nvm Express admin queue attributes register.
226
227 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
228 @param Aqa The buffer used to store the content to be written into admin queue attributes register.
229
230 @return EFI_SUCCESS Successfully write data into the admin queue attributes register.
231 @return EFI_DEVICE_ERROR Fail to write data into the admin queue attributes register.
232
233 **/
234 EFI_STATUS
235 WriteNvmeAdminQueueAttributes (
236 IN NVME_CONTROLLER_PRIVATE_DATA *Private,
237 IN NVME_AQA *Aqa
238 )
239 {
240 EFI_PCI_IO_PROTOCOL *PciIo;
241 EFI_STATUS Status;
242 UINT32 Data;
243
244 PciIo = Private->PciIo;
245 Data = ReadUnaligned32 ((UINT32*)Aqa);
246 Status = PciIo->Mem.Write (
247 PciIo,
248 EfiPciIoWidthUint32,
249 NVME_BAR,
250 NVME_AQA_OFFSET,
251 1,
252 &Data
253 );
254
255 if (EFI_ERROR(Status)) {
256 return Status;
257 }
258
259 DEBUG ((EFI_D_INFO, "Aqa.Asqs: %d\n", Aqa->Asqs));
260 DEBUG ((EFI_D_INFO, "Aqa.Acqs: %d\n", Aqa->Acqs));
261
262 return EFI_SUCCESS;
263 }
264
265 /**
266 Read Nvm Express admin submission queue base address register.
267
268 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
269 @param Asq The buffer used to store admin submission queue base address register content.
270
271 @return EFI_SUCCESS Successfully read the admin submission queue base address register content.
272 @return EFI_DEVICE_ERROR Fail to read the admin submission queue base address register.
273
274 **/
275 EFI_STATUS
276 ReadNvmeAdminSubmissionQueueBaseAddress (
277 IN NVME_CONTROLLER_PRIVATE_DATA *Private,
278 IN NVME_ASQ *Asq
279 )
280 {
281 EFI_PCI_IO_PROTOCOL *PciIo;
282 EFI_STATUS Status;
283 UINT64 Data;
284
285 PciIo = Private->PciIo;
286 Status = PciIo->Mem.Read (
287 PciIo,
288 EfiPciIoWidthUint32,
289 NVME_BAR,
290 NVME_ASQ_OFFSET,
291 2,
292 &Data
293 );
294
295 if (EFI_ERROR(Status)) {
296 return Status;
297 }
298
299 WriteUnaligned64 ((UINT64*)Asq, Data);
300 return EFI_SUCCESS;
301 }
302
303 /**
304 Write Nvm Express admin submission queue base address register.
305
306 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
307 @param Asq The buffer used to store the content to be written into admin submission queue base address register.
308
309 @return EFI_SUCCESS Successfully write data into the admin submission queue base address register.
310 @return EFI_DEVICE_ERROR Fail to write data into the admin submission queue base address register.
311
312 **/
313 EFI_STATUS
314 WriteNvmeAdminSubmissionQueueBaseAddress (
315 IN NVME_CONTROLLER_PRIVATE_DATA *Private,
316 IN NVME_ASQ *Asq
317 )
318 {
319 EFI_PCI_IO_PROTOCOL *PciIo;
320 EFI_STATUS Status;
321 UINT64 Data;
322
323 PciIo = Private->PciIo;
324 Data = ReadUnaligned64 ((UINT64*)Asq);
325
326 Status = PciIo->Mem.Write (
327 PciIo,
328 EfiPciIoWidthUint32,
329 NVME_BAR,
330 NVME_ASQ_OFFSET,
331 2,
332 &Data
333 );
334
335 if (EFI_ERROR(Status)) {
336 return Status;
337 }
338
339 DEBUG ((EFI_D_INFO, "Asq: %lx\n", *Asq));
340
341 return EFI_SUCCESS;
342 }
343
344 /**
345 Read Nvm Express admin completion queue base address register.
346
347 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
348 @param Acq The buffer used to store admin completion queue base address register content.
349
350 @return EFI_SUCCESS Successfully read the admin completion queue base address register content.
351 @return EFI_DEVICE_ERROR Fail to read the admin completion queue base address register.
352
353 **/
354 EFI_STATUS
355 ReadNvmeAdminCompletionQueueBaseAddress (
356 IN NVME_CONTROLLER_PRIVATE_DATA *Private,
357 IN NVME_ACQ *Acq
358 )
359 {
360 EFI_PCI_IO_PROTOCOL *PciIo;
361 EFI_STATUS Status;
362 UINT64 Data;
363
364 PciIo = Private->PciIo;
365
366 Status = PciIo->Mem.Read (
367 PciIo,
368 EfiPciIoWidthUint32,
369 NVME_BAR,
370 NVME_ACQ_OFFSET,
371 2,
372 &Data
373 );
374
375 if (EFI_ERROR(Status)) {
376 return Status;
377 }
378
379 WriteUnaligned64 ((UINT64*)Acq, Data);
380 return EFI_SUCCESS;
381 }
382
383 /**
384 Write Nvm Express admin completion queue base address register.
385
386 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
387 @param Acq The buffer used to store the content to be written into admin completion queue base address register.
388
389 @return EFI_SUCCESS Successfully write data into the admin completion queue base address register.
390 @return EFI_DEVICE_ERROR Fail to write data into the admin completion queue base address register.
391
392 **/
393 EFI_STATUS
394 WriteNvmeAdminCompletionQueueBaseAddress (
395 IN NVME_CONTROLLER_PRIVATE_DATA *Private,
396 IN NVME_ACQ *Acq
397 )
398 {
399 EFI_PCI_IO_PROTOCOL *PciIo;
400 EFI_STATUS Status;
401 UINT64 Data;
402
403 PciIo = Private->PciIo;
404 Data = ReadUnaligned64 ((UINT64*)Acq);
405
406 Status = PciIo->Mem.Write (
407 PciIo,
408 EfiPciIoWidthUint32,
409 NVME_BAR,
410 NVME_ACQ_OFFSET,
411 2,
412 &Data
413 );
414
415 if (EFI_ERROR(Status)) {
416 return Status;
417 }
418
419 DEBUG ((EFI_D_INFO, "Acq: %lxh\n", *Acq));
420
421 return EFI_SUCCESS;
422 }
423
424 /**
425 Disable the Nvm Express controller.
426
427 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
428
429 @return EFI_SUCCESS Successfully disable the controller.
430 @return EFI_DEVICE_ERROR Fail to disable the controller.
431
432 **/
433 EFI_STATUS
434 NvmeDisableController (
435 IN NVME_CONTROLLER_PRIVATE_DATA *Private
436 )
437 {
438 NVME_CC Cc;
439 NVME_CSTS Csts;
440 EFI_STATUS Status;
441 UINT32 Index;
442 UINT8 Timeout;
443
444 //
445 // Read Controller Configuration Register.
446 //
447 Status = ReadNvmeControllerConfiguration (Private, &Cc);
448 if (EFI_ERROR(Status)) {
449 return Status;
450 }
451
452 Cc.En = 0;
453
454 //
455 // Disable the controller.
456 //
457 Status = WriteNvmeControllerConfiguration (Private, &Cc);
458
459 if (EFI_ERROR(Status)) {
460 return Status;
461 }
462
463 //
464 // Cap.To specifies max delay time in 500ms increments for Csts.Rdy to transition from 1 to 0 after
465 // Cc.Enable transition from 1 to 0. Loop produces a 1 millisecond delay per itteration, up to 500 * Cap.To.
466 //
467 if (Private->Cap.To == 0) {
468 Timeout = 1;
469 } else {
470 Timeout = Private->Cap.To;
471 }
472
473 for(Index = (Timeout * 500); Index != 0; --Index) {
474 gBS->Stall(1000);
475
476 //
477 // Check if the controller is initialized
478 //
479 Status = ReadNvmeControllerStatus (Private, &Csts);
480
481 if (EFI_ERROR(Status)) {
482 return Status;
483 }
484
485 if (Csts.Rdy == 0) {
486 break;
487 }
488 }
489
490 if (Index == 0) {
491 Status = EFI_DEVICE_ERROR;
492 }
493
494 DEBUG ((EFI_D_INFO, "NVMe controller is disabled with status [%r].\n", Status));
495 return Status;
496 }
497
498 /**
499 Enable the Nvm Express controller.
500
501 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
502
503 @return EFI_SUCCESS Successfully enable the controller.
504 @return EFI_DEVICE_ERROR Fail to enable the controller.
505 @return EFI_TIMEOUT Fail to enable the controller in given time slot.
506
507 **/
508 EFI_STATUS
509 NvmeEnableController (
510 IN NVME_CONTROLLER_PRIVATE_DATA *Private
511 )
512 {
513 NVME_CC Cc;
514 NVME_CSTS Csts;
515 EFI_STATUS Status;
516 UINT32 Index;
517 UINT8 Timeout;
518
519 //
520 // Enable the controller.
521 // CC.AMS, CC.MPS and CC.CSS are all set to 0.
522 //
523 ZeroMem (&Cc, sizeof (NVME_CC));
524 Cc.En = 1;
525 Cc.Iosqes = 6;
526 Cc.Iocqes = 4;
527
528 Status = WriteNvmeControllerConfiguration (Private, &Cc);
529 if (EFI_ERROR(Status)) {
530 return Status;
531 }
532
533 //
534 // Cap.To specifies max delay time in 500ms increments for Csts.Rdy to set after
535 // Cc.Enable. Loop produces a 1 millisecond delay per itteration, up to 500 * Cap.To.
536 //
537 if (Private->Cap.To == 0) {
538 Timeout = 1;
539 } else {
540 Timeout = Private->Cap.To;
541 }
542
543 for(Index = (Timeout * 500); Index != 0; --Index) {
544 gBS->Stall(1000);
545
546 //
547 // Check if the controller is initialized
548 //
549 Status = ReadNvmeControllerStatus (Private, &Csts);
550
551 if (EFI_ERROR(Status)) {
552 return Status;
553 }
554
555 if (Csts.Rdy) {
556 break;
557 }
558 }
559
560 if (Index == 0) {
561 Status = EFI_TIMEOUT;
562 }
563
564 DEBUG ((EFI_D_INFO, "NVMe controller is enabled with status [%r].\n", Status));
565 return Status;
566 }
567
568 /**
569 Get identify controller data.
570
571 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
572 @param Buffer The buffer used to store the identify controller data.
573
574 @return EFI_SUCCESS Successfully get the identify controller data.
575 @return EFI_DEVICE_ERROR Fail to get the identify controller data.
576
577 **/
578 EFI_STATUS
579 NvmeIdentifyController (
580 IN NVME_CONTROLLER_PRIVATE_DATA *Private,
581 IN VOID *Buffer
582 )
583 {
584 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
585 EFI_NVM_EXPRESS_COMMAND Command;
586 EFI_NVM_EXPRESS_COMPLETION Completion;
587 EFI_STATUS Status;
588
589 ZeroMem (&CommandPacket, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
590 ZeroMem (&Command, sizeof(EFI_NVM_EXPRESS_COMMAND));
591 ZeroMem (&Completion, sizeof(EFI_NVM_EXPRESS_COMPLETION));
592
593 Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_CMD;
594 //
595 // According to Nvm Express 1.1 spec Figure 38, When not used, the field shall be cleared to 0h.
596 // For the Identify command, the Namespace Identifier is only used for the Namespace data structure.
597 //
598 Command.Nsid = 0;
599
600 CommandPacket.NvmeCmd = &Command;
601 CommandPacket.NvmeCompletion = &Completion;
602 CommandPacket.TransferBuffer = Buffer;
603 CommandPacket.TransferLength = sizeof (NVME_ADMIN_CONTROLLER_DATA);
604 CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
605 CommandPacket.QueueType = NVME_ADMIN_QUEUE;
606 //
607 // Set bit 0 (Cns bit) to 1 to identify a controller
608 //
609 Command.Cdw10 = 1;
610 Command.Flags = CDW10_VALID;
611
612 Status = Private->Passthru.PassThru (
613 &Private->Passthru,
614 NVME_CONTROLLER_ID,
615 &CommandPacket,
616 NULL
617 );
618
619 return Status;
620 }
621
622 /**
623 Get specified identify namespace data.
624
625 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
626 @param NamespaceId The specified namespace identifier.
627 @param Buffer The buffer used to store the identify namespace data.
628
629 @return EFI_SUCCESS Successfully get the identify namespace data.
630 @return EFI_DEVICE_ERROR Fail to get the identify namespace data.
631
632 **/
633 EFI_STATUS
634 NvmeIdentifyNamespace (
635 IN NVME_CONTROLLER_PRIVATE_DATA *Private,
636 IN UINT32 NamespaceId,
637 IN VOID *Buffer
638 )
639 {
640 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
641 EFI_NVM_EXPRESS_COMMAND Command;
642 EFI_NVM_EXPRESS_COMPLETION Completion;
643 EFI_STATUS Status;
644
645 ZeroMem (&CommandPacket, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
646 ZeroMem (&Command, sizeof(EFI_NVM_EXPRESS_COMMAND));
647 ZeroMem (&Completion, sizeof(EFI_NVM_EXPRESS_COMPLETION));
648
649 CommandPacket.NvmeCmd = &Command;
650 CommandPacket.NvmeCompletion = &Completion;
651
652 Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_CMD;
653 Command.Nsid = NamespaceId;
654 CommandPacket.TransferBuffer = Buffer;
655 CommandPacket.TransferLength = sizeof (NVME_ADMIN_NAMESPACE_DATA);
656 CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
657 CommandPacket.QueueType = NVME_ADMIN_QUEUE;
658 //
659 // Set bit 0 (Cns bit) to 1 to identify a namespace
660 //
661 CommandPacket.NvmeCmd->Cdw10 = 0;
662 CommandPacket.NvmeCmd->Flags = CDW10_VALID;
663
664 Status = Private->Passthru.PassThru (
665 &Private->Passthru,
666 NamespaceId,
667 &CommandPacket,
668 NULL
669 );
670
671 return Status;
672 }
673
674 /**
675 Create io completion queue.
676
677 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
678
679 @return EFI_SUCCESS Successfully create io completion queue.
680 @return EFI_DEVICE_ERROR Fail to create io completion queue.
681
682 **/
683 EFI_STATUS
684 NvmeCreateIoCompletionQueue (
685 IN NVME_CONTROLLER_PRIVATE_DATA *Private
686 )
687 {
688 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
689 EFI_NVM_EXPRESS_COMMAND Command;
690 EFI_NVM_EXPRESS_COMPLETION Completion;
691 EFI_STATUS Status;
692 NVME_ADMIN_CRIOCQ CrIoCq;
693 UINT32 Index;
694 UINT16 QueueSize;
695
696 Status = EFI_SUCCESS;
697
698 for (Index = 1; Index < NVME_MAX_QUEUES; Index++) {
699 ZeroMem (&CommandPacket, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
700 ZeroMem (&Command, sizeof(EFI_NVM_EXPRESS_COMMAND));
701 ZeroMem (&Completion, sizeof(EFI_NVM_EXPRESS_COMPLETION));
702 ZeroMem (&CrIoCq, sizeof(NVME_ADMIN_CRIOCQ));
703
704 CommandPacket.NvmeCmd = &Command;
705 CommandPacket.NvmeCompletion = &Completion;
706
707 Command.Cdw0.Opcode = NVME_ADMIN_CRIOCQ_CMD;
708 CommandPacket.TransferBuffer = Private->CqBufferPciAddr[Index];
709 CommandPacket.TransferLength = EFI_PAGE_SIZE;
710 CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
711 CommandPacket.QueueType = NVME_ADMIN_QUEUE;
712
713 if (Index == 1) {
714 QueueSize = NVME_CCQ_SIZE;
715 } else {
716 if (Private->Cap.Mqes > NVME_ASYNC_CCQ_SIZE) {
717 QueueSize = NVME_ASYNC_CCQ_SIZE;
718 } else {
719 QueueSize = Private->Cap.Mqes;
720 }
721 }
722
723 CrIoCq.Qid = Index;
724 CrIoCq.Qsize = QueueSize;
725 CrIoCq.Pc = 1;
726 CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoCq, sizeof (NVME_ADMIN_CRIOCQ));
727 CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
728
729 Status = Private->Passthru.PassThru (
730 &Private->Passthru,
731 0,
732 &CommandPacket,
733 NULL
734 );
735 if (EFI_ERROR (Status)) {
736 break;
737 }
738 }
739
740 return Status;
741 }
742
743 /**
744 Create io submission queue.
745
746 @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
747
748 @return EFI_SUCCESS Successfully create io submission queue.
749 @return EFI_DEVICE_ERROR Fail to create io submission queue.
750
751 **/
752 EFI_STATUS
753 NvmeCreateIoSubmissionQueue (
754 IN NVME_CONTROLLER_PRIVATE_DATA *Private
755 )
756 {
757 EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
758 EFI_NVM_EXPRESS_COMMAND Command;
759 EFI_NVM_EXPRESS_COMPLETION Completion;
760 EFI_STATUS Status;
761 NVME_ADMIN_CRIOSQ CrIoSq;
762 UINT32 Index;
763 UINT16 QueueSize;
764
765 Status = EFI_SUCCESS;
766
767 for (Index = 1; Index < NVME_MAX_QUEUES; Index++) {
768 ZeroMem (&CommandPacket, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
769 ZeroMem (&Command, sizeof(EFI_NVM_EXPRESS_COMMAND));
770 ZeroMem (&Completion, sizeof(EFI_NVM_EXPRESS_COMPLETION));
771 ZeroMem (&CrIoSq, sizeof(NVME_ADMIN_CRIOSQ));
772
773 CommandPacket.NvmeCmd = &Command;
774 CommandPacket.NvmeCompletion = &Completion;
775
776 Command.Cdw0.Opcode = NVME_ADMIN_CRIOSQ_CMD;
777 CommandPacket.TransferBuffer = Private->SqBufferPciAddr[Index];
778 CommandPacket.TransferLength = EFI_PAGE_SIZE;
779 CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
780 CommandPacket.QueueType = NVME_ADMIN_QUEUE;
781
782 if (Index == 1) {
783 QueueSize = NVME_CSQ_SIZE;
784 } else {
785 if (Private->Cap.Mqes > NVME_ASYNC_CSQ_SIZE) {
786 QueueSize = NVME_ASYNC_CSQ_SIZE;
787 } else {
788 QueueSize = Private->Cap.Mqes;
789 }
790 }
791
792 CrIoSq.Qid = Index;
793 CrIoSq.Qsize = QueueSize;
794 CrIoSq.Pc = 1;
795 CrIoSq.Cqid = Index;
796 CrIoSq.Qprio = 0;
797 CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoSq, sizeof (NVME_ADMIN_CRIOSQ));
798 CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
799
800 Status = Private->Passthru.PassThru (
801 &Private->Passthru,
802 0,
803 &CommandPacket,
804 NULL
805 );
806 if (EFI_ERROR (Status)) {
807 break;
808 }
809 }
810
811 return Status;
812 }
813
814 /**
815 Initialize the Nvm Express controller.
816
817 @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
818
819 @retval EFI_SUCCESS The NVM Express Controller is initialized successfully.
820 @retval Others A device error occurred while initializing the controller.
821
822 **/
823 EFI_STATUS
824 NvmeControllerInit (
825 IN NVME_CONTROLLER_PRIVATE_DATA *Private
826 )
827 {
828 EFI_STATUS Status;
829 EFI_PCI_IO_PROTOCOL *PciIo;
830 UINT64 Supports;
831 NVME_AQA Aqa;
832 NVME_ASQ Asq;
833 NVME_ACQ Acq;
834 UINT8 Sn[21];
835 UINT8 Mn[41];
836 //
837 // Save original PCI attributes and enable this controller.
838 //
839 PciIo = Private->PciIo;
840 Status = PciIo->Attributes (
841 PciIo,
842 EfiPciIoAttributeOperationGet,
843 0,
844 &Private->PciAttributes
845 );
846
847 if (EFI_ERROR (Status)) {
848 return Status;
849 }
850
851 Status = PciIo->Attributes (
852 PciIo,
853 EfiPciIoAttributeOperationSupported,
854 0,
855 &Supports
856 );
857
858 if (!EFI_ERROR (Status)) {
859 Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
860 Status = PciIo->Attributes (
861 PciIo,
862 EfiPciIoAttributeOperationEnable,
863 Supports,
864 NULL
865 );
866 }
867
868 if (EFI_ERROR (Status)) {
869 DEBUG ((EFI_D_INFO, "NvmeControllerInit: failed to enable controller\n"));
870 return Status;
871 }
872
873 //
874 // Enable 64-bit DMA support in the PCI layer.
875 //
876 Status = PciIo->Attributes (
877 PciIo,
878 EfiPciIoAttributeOperationEnable,
879 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,
880 NULL
881 );
882 if (EFI_ERROR (Status)) {
883 DEBUG ((EFI_D_WARN, "NvmeControllerInit: failed to enable 64-bit DMA (%r)\n", Status));
884 }
885
886 //
887 // Read the Controller Capabilities register and verify that the NVM command set is supported
888 //
889 Status = ReadNvmeControllerCapabilities (Private, &Private->Cap);
890 if (EFI_ERROR (Status)) {
891 return Status;
892 }
893
894 if (Private->Cap.Css != 0x01) {
895 DEBUG ((EFI_D_INFO, "NvmeControllerInit: the controller doesn't support NVMe command set\n"));
896 return EFI_UNSUPPORTED;
897 }
898
899 //
900 // Currently the driver only supports 4k page size.
901 //
902 ASSERT ((Private->Cap.Mpsmin + 12) <= EFI_PAGE_SHIFT);
903
904 Private->Cid[0] = 0;
905 Private->Cid[1] = 0;
906 Private->Cid[2] = 0;
907 Private->Pt[0] = 0;
908 Private->Pt[1] = 0;
909 Private->Pt[2] = 0;
910 Private->SqTdbl[0].Sqt = 0;
911 Private->SqTdbl[1].Sqt = 0;
912 Private->SqTdbl[2].Sqt = 0;
913 Private->CqHdbl[0].Cqh = 0;
914 Private->CqHdbl[1].Cqh = 0;
915 Private->CqHdbl[2].Cqh = 0;
916 Private->AsyncSqHead = 0;
917
918 Status = NvmeDisableController (Private);
919
920 if (EFI_ERROR(Status)) {
921 return Status;
922 }
923
924 //
925 // set number of entries admin submission & completion queues.
926 //
927 Aqa.Asqs = NVME_ASQ_SIZE;
928 Aqa.Rsvd1 = 0;
929 Aqa.Acqs = NVME_ACQ_SIZE;
930 Aqa.Rsvd2 = 0;
931
932 //
933 // Address of admin submission queue.
934 //
935 Asq = (UINT64)(UINTN)(Private->BufferPciAddr) & ~0xFFF;
936
937 //
938 // Address of admin completion queue.
939 //
940 Acq = (UINT64)(UINTN)(Private->BufferPciAddr + EFI_PAGE_SIZE) & ~0xFFF;
941
942 //
943 // Address of I/O submission & completion queue.
944 //
945 ZeroMem (Private->Buffer, EFI_PAGES_TO_SIZE (6));
946 Private->SqBuffer[0] = (NVME_SQ *)(UINTN)(Private->Buffer);
947 Private->SqBufferPciAddr[0] = (NVME_SQ *)(UINTN)(Private->BufferPciAddr);
948 Private->CqBuffer[0] = (NVME_CQ *)(UINTN)(Private->Buffer + 1 * EFI_PAGE_SIZE);
949 Private->CqBufferPciAddr[0] = (NVME_CQ *)(UINTN)(Private->BufferPciAddr + 1 * EFI_PAGE_SIZE);
950 Private->SqBuffer[1] = (NVME_SQ *)(UINTN)(Private->Buffer + 2 * EFI_PAGE_SIZE);
951 Private->SqBufferPciAddr[1] = (NVME_SQ *)(UINTN)(Private->BufferPciAddr + 2 * EFI_PAGE_SIZE);
952 Private->CqBuffer[1] = (NVME_CQ *)(UINTN)(Private->Buffer + 3 * EFI_PAGE_SIZE);
953 Private->CqBufferPciAddr[1] = (NVME_CQ *)(UINTN)(Private->BufferPciAddr + 3 * EFI_PAGE_SIZE);
954 Private->SqBuffer[2] = (NVME_SQ *)(UINTN)(Private->Buffer + 4 * EFI_PAGE_SIZE);
955 Private->SqBufferPciAddr[2] = (NVME_SQ *)(UINTN)(Private->BufferPciAddr + 4 * EFI_PAGE_SIZE);
956 Private->CqBuffer[2] = (NVME_CQ *)(UINTN)(Private->Buffer + 5 * EFI_PAGE_SIZE);
957 Private->CqBufferPciAddr[2] = (NVME_CQ *)(UINTN)(Private->BufferPciAddr + 5 * EFI_PAGE_SIZE);
958
959 DEBUG ((EFI_D_INFO, "Private->Buffer = [%016X]\n", (UINT64)(UINTN)Private->Buffer));
960 DEBUG ((EFI_D_INFO, "Admin Submission Queue size (Aqa.Asqs) = [%08X]\n", Aqa.Asqs));
961 DEBUG ((EFI_D_INFO, "Admin Completion Queue size (Aqa.Acqs) = [%08X]\n", Aqa.Acqs));
962 DEBUG ((EFI_D_INFO, "Admin Submission Queue (SqBuffer[0]) = [%016X]\n", Private->SqBuffer[0]));
963 DEBUG ((EFI_D_INFO, "Admin Completion Queue (CqBuffer[0]) = [%016X]\n", Private->CqBuffer[0]));
964 DEBUG ((EFI_D_INFO, "Sync I/O Submission Queue (SqBuffer[1]) = [%016X]\n", Private->SqBuffer[1]));
965 DEBUG ((EFI_D_INFO, "Sync I/O Completion Queue (CqBuffer[1]) = [%016X]\n", Private->CqBuffer[1]));
966 DEBUG ((EFI_D_INFO, "Async I/O Submission Queue (SqBuffer[2]) = [%016X]\n", Private->SqBuffer[2]));
967 DEBUG ((EFI_D_INFO, "Async I/O Completion Queue (CqBuffer[2]) = [%016X]\n", Private->CqBuffer[2]));
968
969 //
970 // Program admin queue attributes.
971 //
972 Status = WriteNvmeAdminQueueAttributes (Private, &Aqa);
973
974 if (EFI_ERROR(Status)) {
975 return Status;
976 }
977
978 //
979 // Program admin submission queue address.
980 //
981 Status = WriteNvmeAdminSubmissionQueueBaseAddress (Private, &Asq);
982
983 if (EFI_ERROR(Status)) {
984 return Status;
985 }
986
987 //
988 // Program admin completion queue address.
989 //
990 Status = WriteNvmeAdminCompletionQueueBaseAddress (Private, &Acq);
991
992 if (EFI_ERROR(Status)) {
993 return Status;
994 }
995
996 Status = NvmeEnableController (Private);
997 if (EFI_ERROR(Status)) {
998 return Status;
999 }
1000
1001 //
1002 // Allocate buffer for Identify Controller data
1003 //
1004 if (Private->ControllerData == NULL) {
1005 Private->ControllerData = (NVME_ADMIN_CONTROLLER_DATA *)AllocateZeroPool (sizeof(NVME_ADMIN_CONTROLLER_DATA));
1006
1007 if (Private->ControllerData == NULL) {
1008 return EFI_OUT_OF_RESOURCES;
1009 }
1010 }
1011
1012 //
1013 // Get current Identify Controller Data
1014 //
1015 Status = NvmeIdentifyController (Private, Private->ControllerData);
1016
1017 if (EFI_ERROR(Status)) {
1018 FreePool(Private->ControllerData);
1019 Private->ControllerData = NULL;
1020 return EFI_NOT_FOUND;
1021 }
1022
1023 //
1024 // Dump NvmExpress Identify Controller Data
1025 //
1026 CopyMem (Sn, Private->ControllerData->Sn, sizeof (Private->ControllerData->Sn));
1027 Sn[20] = 0;
1028 CopyMem (Mn, Private->ControllerData->Mn, sizeof (Private->ControllerData->Mn));
1029 Mn[40] = 0;
1030 DEBUG ((EFI_D_INFO, " == NVME IDENTIFY CONTROLLER DATA ==\n"));
1031 DEBUG ((EFI_D_INFO, " PCI VID : 0x%x\n", Private->ControllerData->Vid));
1032 DEBUG ((EFI_D_INFO, " PCI SSVID : 0x%x\n", Private->ControllerData->Ssvid));
1033 DEBUG ((EFI_D_INFO, " SN : %a\n", Sn));
1034 DEBUG ((EFI_D_INFO, " MN : %a\n", Mn));
1035 DEBUG ((EFI_D_INFO, " FR : 0x%x\n", *((UINT64*)Private->ControllerData->Fr)));
1036 DEBUG ((EFI_D_INFO, " RAB : 0x%x\n", Private->ControllerData->Rab));
1037 DEBUG ((EFI_D_INFO, " IEEE : 0x%x\n", *(UINT32*)Private->ControllerData->Ieee_oui));
1038 DEBUG ((EFI_D_INFO, " AERL : 0x%x\n", Private->ControllerData->Aerl));
1039 DEBUG ((EFI_D_INFO, " SQES : 0x%x\n", Private->ControllerData->Sqes));
1040 DEBUG ((EFI_D_INFO, " CQES : 0x%x\n", Private->ControllerData->Cqes));
1041 DEBUG ((EFI_D_INFO, " NN : 0x%x\n", Private->ControllerData->Nn));
1042
1043 //
1044 // Create two I/O completion queues.
1045 // One for blocking I/O, one for non-blocking I/O.
1046 //
1047 Status = NvmeCreateIoCompletionQueue (Private);
1048 if (EFI_ERROR(Status)) {
1049 return Status;
1050 }
1051
1052 //
1053 // Create two I/O Submission queues.
1054 // One for blocking I/O, one for non-blocking I/O.
1055 //
1056 Status = NvmeCreateIoSubmissionQueue (Private);
1057
1058 return Status;
1059 }
1060
1061 /**
1062 This routine is called to properly shutdown the Nvm Express controller per NVMe spec.
1063
1064 @param[in] ResetType The type of reset to perform.
1065 @param[in] ResetStatus The status code for the reset.
1066 @param[in] DataSize The size, in bytes, of ResetData.
1067 @param[in] ResetData For a ResetType of EfiResetCold, EfiResetWarm, or
1068 EfiResetShutdown the data buffer starts with a Null-terminated
1069 string, optionally followed by additional binary data.
1070 The string is a description that the caller may use to further
1071 indicate the reason for the system reset. ResetData is only
1072 valid if ResetStatus is something other than EFI_SUCCESS
1073 unless the ResetType is EfiResetPlatformSpecific
1074 where a minimum amount of ResetData is always required.
1075 For a ResetType of EfiResetPlatformSpecific the data buffer
1076 also starts with a Null-terminated string that is followed
1077 by an EFI_GUID that describes the specific type of reset to perform.
1078 **/
1079 VOID
1080 EFIAPI
1081 NvmeShutdownAllControllers (
1082 IN EFI_RESET_TYPE ResetType,
1083 IN EFI_STATUS ResetStatus,
1084 IN UINTN DataSize,
1085 IN VOID *ResetData OPTIONAL
1086 )
1087 {
1088 EFI_STATUS Status;
1089 EFI_HANDLE *Handles;
1090 UINTN HandleCount;
1091 UINTN HandleIndex;
1092 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfos;
1093 UINTN OpenInfoCount;
1094 UINTN OpenInfoIndex;
1095 EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *NvmePassThru;
1096 NVME_CC Cc;
1097 NVME_CSTS Csts;
1098 UINTN Index;
1099 NVME_CONTROLLER_PRIVATE_DATA *Private;
1100
1101 Status = gBS->LocateHandleBuffer (
1102 ByProtocol,
1103 &gEfiPciIoProtocolGuid,
1104 NULL,
1105 &HandleCount,
1106 &Handles
1107 );
1108 if (EFI_ERROR (Status)) {
1109 HandleCount = 0;
1110 }
1111
1112 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
1113 Status = gBS->OpenProtocolInformation (
1114 Handles[HandleIndex],
1115 &gEfiPciIoProtocolGuid,
1116 &OpenInfos,
1117 &OpenInfoCount
1118 );
1119 if (EFI_ERROR (Status)) {
1120 continue;
1121 }
1122
1123 for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
1124 //
1125 // Find all the NVME controller managed by this driver.
1126 // gImageHandle equals to DriverBinding handle for this driver.
1127 //
1128 if (((OpenInfos[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) &&
1129 (OpenInfos[OpenInfoIndex].AgentHandle == gImageHandle)) {
1130 Status = gBS->OpenProtocol (
1131 OpenInfos[OpenInfoIndex].ControllerHandle,
1132 &gEfiNvmExpressPassThruProtocolGuid,
1133 (VOID **) &NvmePassThru,
1134 NULL,
1135 NULL,
1136 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1137 );
1138 if (EFI_ERROR (Status)) {
1139 continue;
1140 }
1141 Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (NvmePassThru);
1142
1143 //
1144 // Read Controller Configuration Register.
1145 //
1146 Status = ReadNvmeControllerConfiguration (Private, &Cc);
1147 if (EFI_ERROR(Status)) {
1148 continue;
1149 }
1150 //
1151 // The host should set the Shutdown Notification (CC.SHN) field to 01b
1152 // to indicate a normal shutdown operation.
1153 //
1154 Cc.Shn = NVME_CC_SHN_NORMAL_SHUTDOWN;
1155 Status = WriteNvmeControllerConfiguration (Private, &Cc);
1156 if (EFI_ERROR(Status)) {
1157 continue;
1158 }
1159
1160 //
1161 // The controller indicates when shutdown processing is completed by updating the
1162 // Shutdown Status (CSTS.SHST) field to 10b.
1163 // Wait up to 45 seconds (break down to 4500 x 10ms) for the shutdown to complete.
1164 //
1165 for (Index = 0; Index < NVME_SHUTDOWN_PROCESS_TIMEOUT * 100; Index++) {
1166 Status = ReadNvmeControllerStatus (Private, &Csts);
1167 if (!EFI_ERROR(Status) && (Csts.Shst == NVME_CSTS_SHST_SHUTDOWN_COMPLETED)) {
1168 DEBUG((DEBUG_INFO, "NvmeShutdownController: shutdown processing is completed after %dms.\n", Index * 10));
1169 break;
1170 }
1171 //
1172 // Stall for 10ms
1173 //
1174 gBS->Stall (10 * 1000);
1175 }
1176
1177 if (Index == NVME_SHUTDOWN_PROCESS_TIMEOUT * 100) {
1178 DEBUG((DEBUG_ERROR, "NvmeShutdownController: shutdown processing is timed out\n"));
1179 }
1180 }
1181 }
1182 }
1183 }
1184
1185 /**
1186 Register the shutdown notification through the ResetNotification protocol.
1187
1188 Register the shutdown notification when mNvmeControllerNumber increased from 0 to 1.
1189 **/
1190 VOID
1191 NvmeRegisterShutdownNotification (
1192 VOID
1193 )
1194 {
1195 EFI_STATUS Status;
1196 EFI_RESET_NOTIFICATION_PROTOCOL *ResetNotify;
1197
1198 mNvmeControllerNumber++;
1199 if (mNvmeControllerNumber == 1) {
1200 Status = gBS->LocateProtocol (&gEfiResetNotificationProtocolGuid, NULL, (VOID **) &ResetNotify);
1201 if (!EFI_ERROR (Status)) {
1202 Status = ResetNotify->RegisterResetNotify (ResetNotify, NvmeShutdownAllControllers);
1203 ASSERT_EFI_ERROR (Status);
1204 } else {
1205 DEBUG ((DEBUG_WARN, "NVME: ResetNotification absent! Shutdown notification cannot be performed!\n"));
1206 }
1207 }
1208 }
1209
1210 /**
1211 Unregister the shutdown notification through the ResetNotification protocol.
1212
1213 Unregister the shutdown notification when mNvmeControllerNumber decreased from 1 to 0.
1214 **/
1215 VOID
1216 NvmeUnregisterShutdownNotification (
1217 VOID
1218 )
1219 {
1220 EFI_STATUS Status;
1221 EFI_RESET_NOTIFICATION_PROTOCOL *ResetNotify;
1222
1223 mNvmeControllerNumber--;
1224 if (mNvmeControllerNumber == 0) {
1225 Status = gBS->LocateProtocol (&gEfiResetNotificationProtocolGuid, NULL, (VOID **) &ResetNotify);
1226 if (!EFI_ERROR (Status)) {
1227 Status = ResetNotify->UnregisterResetNotify (ResetNotify, NvmeShutdownAllControllers);
1228 ASSERT_EFI_ERROR (Status);
1229 }
1230 }
1231 }