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