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
ReadNvmeControllerCapabilities(IN NVME_CONTROLLER_PRIVATE_DATA * Private,IN NVME_CAP * Cap)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
ReadNvmeControllerConfiguration(IN NVME_CONTROLLER_PRIVATE_DATA * Private,IN NVME_CC * Cc)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
WriteNvmeControllerConfiguration(IN NVME_CONTROLLER_PRIVATE_DATA * Private,IN NVME_CC * Cc)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 ((EFI_D_INFO, "Cc.En: %d\n", Cc->En));
132   DEBUG ((EFI_D_INFO, "Cc.Css: %d\n", Cc->Css));
133   DEBUG ((EFI_D_INFO, "Cc.Mps: %d\n", Cc->Mps));
134   DEBUG ((EFI_D_INFO, "Cc.Ams: %d\n", Cc->Ams));
135   DEBUG ((EFI_D_INFO, "Cc.Shn: %d\n", Cc->Shn));
136   DEBUG ((EFI_D_INFO, "Cc.Iosqes: %d\n", Cc->Iosqes));
137   DEBUG ((EFI_D_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
ReadNvmeControllerStatus(IN NVME_CONTROLLER_PRIVATE_DATA * Private,IN NVME_CSTS * Csts)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
WriteNvmeAdminQueueAttributes(IN NVME_CONTROLLER_PRIVATE_DATA * Private,IN NVME_AQA * Aqa)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 ((EFI_D_INFO, "Aqa.Asqs: %d\n", Aqa->Asqs));
218   DEBUG ((EFI_D_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
WriteNvmeAdminSubmissionQueueBaseAddress(IN NVME_CONTROLLER_PRIVATE_DATA * Private,IN NVME_ASQ * Asq)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 ((EFI_D_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
WriteNvmeAdminCompletionQueueBaseAddress(IN NVME_CONTROLLER_PRIVATE_DATA * Private,IN NVME_ACQ * Acq)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 ((EFI_D_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
NvmeDisableController(IN NVME_CONTROLLER_PRIVATE_DATA * Private)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 ((EFI_D_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
NvmeEnableController(IN NVME_CONTROLLER_PRIVATE_DATA * Private)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 ((EFI_D_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
NvmeIdentifyController(IN NVME_CONTROLLER_PRIVATE_DATA * Private,IN VOID * Buffer)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
NvmeIdentifyNamespace(IN NVME_CONTROLLER_PRIVATE_DATA * Private,IN UINT32 NamespaceId,IN VOID * Buffer)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
NvmeCreateIoCompletionQueue(IN NVME_CONTROLLER_PRIVATE_DATA * Private)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
NvmeCreateIoSubmissionQueue(IN NVME_CONTROLLER_PRIVATE_DATA * Private)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
NvmeControllerInit(IN NVME_CONTROLLER_PRIVATE_DATA * Private)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 ((EFI_D_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 ((EFI_D_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 ((EFI_D_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 ((EFI_D_INFO, "Private->Buffer = [%016X]\n", (UINT64)(UINTN)Private->Buffer));
858   DEBUG ((EFI_D_INFO, "Admin     Submission Queue size (Aqa.Asqs) = [%08X]\n", Aqa.Asqs));
859   DEBUG ((EFI_D_INFO, "Admin     Completion Queue size (Aqa.Acqs) = [%08X]\n", Aqa.Acqs));
860   DEBUG ((EFI_D_INFO, "Admin     Submission Queue (SqBuffer[0]) = [%016X]\n", Private->SqBuffer[0]));
861   DEBUG ((EFI_D_INFO, "Admin     Completion Queue (CqBuffer[0]) = [%016X]\n", Private->CqBuffer[0]));
862   DEBUG ((EFI_D_INFO, "Sync  I/O Submission Queue (SqBuffer[1]) = [%016X]\n", Private->SqBuffer[1]));
863   DEBUG ((EFI_D_INFO, "Sync  I/O Completion Queue (CqBuffer[1]) = [%016X]\n", Private->CqBuffer[1]));
864   DEBUG ((EFI_D_INFO, "Async I/O Submission Queue (SqBuffer[2]) = [%016X]\n", Private->SqBuffer[2]));
865   DEBUG ((EFI_D_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 ((EFI_D_INFO, " == NVME IDENTIFY CONTROLLER DATA ==\n"));
929   DEBUG ((EFI_D_INFO, "    PCI VID   : 0x%x\n", Private->ControllerData->Vid));
930   DEBUG ((EFI_D_INFO, "    PCI SSVID : 0x%x\n", Private->ControllerData->Ssvid));
931   DEBUG ((EFI_D_INFO, "    SN        : %a\n",   Sn));
932   DEBUG ((EFI_D_INFO, "    MN        : %a\n",   Mn));
933   DEBUG ((EFI_D_INFO, "    FR        : 0x%x\n", *((UINT64*)Private->ControllerData->Fr)));
934   DEBUG ((EFI_D_INFO, "    RAB       : 0x%x\n", Private->ControllerData->Rab));
935   DEBUG ((EFI_D_INFO, "    IEEE      : 0x%x\n", *(UINT32*)Private->ControllerData->Ieee_oui));
936   DEBUG ((EFI_D_INFO, "    AERL      : 0x%x\n", Private->ControllerData->Aerl));
937   DEBUG ((EFI_D_INFO, "    SQES      : 0x%x\n", Private->ControllerData->Sqes));
938   DEBUG ((EFI_D_INFO, "    CQES      : 0x%x\n", Private->ControllerData->Cqes));
939   DEBUG ((EFI_D_INFO, "    NN        : 0x%x\n", Private->ControllerData->Nn));
940 
941   //
942   // Create two I/O completion queues.
943   // One for blocking I/O, one for non-blocking I/O.
944   //
945   Status = NvmeCreateIoCompletionQueue (Private);
946   if (EFI_ERROR(Status)) {
947    return Status;
948   }
949 
950   //
951   // Create two I/O Submission queues.
952   // One for blocking I/O, one for non-blocking I/O.
953   //
954   Status = NvmeCreateIoSubmissionQueue (Private);
955 
956   return Status;
957 }
958 
959 /**
960  This routine is called to properly shutdown the Nvm Express controller per NVMe spec.
961 
962   @param[in]  ResetType         The type of reset to perform.
963   @param[in]  ResetStatus       The status code for the reset.
964   @param[in]  DataSize          The size, in bytes, of ResetData.
965   @param[in]  ResetData         For a ResetType of EfiResetCold, EfiResetWarm, or
966                                 EfiResetShutdown the data buffer starts with a Null-terminated
967                                 string, optionally followed by additional binary data.
968                                 The string is a description that the caller may use to further
969                                 indicate the reason for the system reset.
970                                 For a ResetType of EfiResetPlatformSpecific the data buffer
971                                 also starts with a Null-terminated string that is followed
972                                 by an EFI_GUID that describes the specific type of reset to perform.
973 **/
974 VOID
975 EFIAPI
NvmeShutdownAllControllers(IN EFI_RESET_TYPE ResetType,IN EFI_STATUS ResetStatus,IN UINTN DataSize,IN VOID * ResetData OPTIONAL)976 NvmeShutdownAllControllers (
977   IN EFI_RESET_TYPE           ResetType,
978   IN EFI_STATUS               ResetStatus,
979   IN UINTN                    DataSize,
980   IN VOID                     *ResetData OPTIONAL
981   )
982 {
983   EFI_STATUS                          Status;
984   EFI_HANDLE                          *Handles;
985   UINTN                               HandleCount;
986   UINTN                               HandleIndex;
987   EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfos;
988   UINTN                               OpenInfoCount;
989   UINTN                               OpenInfoIndex;
990   EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL  *NvmePassThru;
991   NVME_CC                             Cc;
992   NVME_CSTS                           Csts;
993   UINTN                               Index;
994   NVME_CONTROLLER_PRIVATE_DATA        *Private;
995 
996   Status = gBS->LocateHandleBuffer (
997                   ByProtocol,
998                   &gEfiPciIoProtocolGuid,
999                   NULL,
1000                   &HandleCount,
1001                   &Handles
1002                   );
1003   if (EFI_ERROR (Status)) {
1004     HandleCount = 0;
1005   }
1006 
1007   for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
1008     Status = gBS->OpenProtocolInformation (
1009                     Handles[HandleIndex],
1010                     &gEfiPciIoProtocolGuid,
1011                     &OpenInfos,
1012                     &OpenInfoCount
1013                     );
1014     if (EFI_ERROR (Status)) {
1015       continue;
1016     }
1017 
1018     for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
1019       //
1020       // Find all the NVME controller managed by this driver.
1021       // gImageHandle equals to DriverBinding handle for this driver.
1022       //
1023       if (((OpenInfos[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) &&
1024           (OpenInfos[OpenInfoIndex].AgentHandle == gImageHandle)) {
1025         Status = gBS->OpenProtocol (
1026                         OpenInfos[OpenInfoIndex].ControllerHandle,
1027                         &gEfiNvmExpressPassThruProtocolGuid,
1028                         (VOID **) &NvmePassThru,
1029                         NULL,
1030                         NULL,
1031                         EFI_OPEN_PROTOCOL_GET_PROTOCOL
1032                         );
1033         if (EFI_ERROR (Status)) {
1034           continue;
1035         }
1036         Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (NvmePassThru);
1037 
1038         //
1039         // Read Controller Configuration Register.
1040         //
1041         Status = ReadNvmeControllerConfiguration (Private, &Cc);
1042         if (EFI_ERROR(Status)) {
1043           continue;
1044         }
1045         //
1046         // The host should set the Shutdown Notification (CC.SHN) field to 01b
1047         // to indicate a normal shutdown operation.
1048         //
1049         Cc.Shn = NVME_CC_SHN_NORMAL_SHUTDOWN;
1050         Status = WriteNvmeControllerConfiguration (Private, &Cc);
1051         if (EFI_ERROR(Status)) {
1052           continue;
1053         }
1054 
1055         //
1056         // The controller indicates when shutdown processing is completed by updating the
1057         // Shutdown Status (CSTS.SHST) field to 10b.
1058         // Wait up to 45 seconds (break down to 4500 x 10ms) for the shutdown to complete.
1059         //
1060         for (Index = 0; Index < NVME_SHUTDOWN_PROCESS_TIMEOUT * 100; Index++) {
1061           Status = ReadNvmeControllerStatus (Private, &Csts);
1062           if (!EFI_ERROR(Status) && (Csts.Shst == NVME_CSTS_SHST_SHUTDOWN_COMPLETED)) {
1063             DEBUG((DEBUG_INFO, "NvmeShutdownController: shutdown processing is completed after %dms.\n", Index * 10));
1064             break;
1065           }
1066           //
1067           // Stall for 10ms
1068           //
1069           gBS->Stall (10 * 1000);
1070         }
1071 
1072         if (Index == NVME_SHUTDOWN_PROCESS_TIMEOUT * 100) {
1073           DEBUG((DEBUG_ERROR, "NvmeShutdownController: shutdown processing is timed out\n"));
1074         }
1075       }
1076     }
1077   }
1078 }
1079 
1080 /**
1081   Register the shutdown notification through the ResetNotification protocol.
1082 
1083   Register the shutdown notification when mNvmeControllerNumber increased from 0 to 1.
1084 **/
1085 VOID
NvmeRegisterShutdownNotification(VOID)1086 NvmeRegisterShutdownNotification (
1087   VOID
1088   )
1089 {
1090   EFI_STATUS                      Status;
1091   EFI_RESET_NOTIFICATION_PROTOCOL *ResetNotify;
1092 
1093   mNvmeControllerNumber++;
1094   if (mNvmeControllerNumber == 1) {
1095     Status = gBS->LocateProtocol (&gEfiResetNotificationProtocolGuid, NULL, (VOID **) &ResetNotify);
1096     if (!EFI_ERROR (Status)) {
1097       Status = ResetNotify->RegisterResetNotify (ResetNotify, NvmeShutdownAllControllers);
1098       ASSERT_EFI_ERROR (Status);
1099     } else {
1100       DEBUG ((DEBUG_WARN, "NVME: ResetNotification absent! Shutdown notification cannot be performed!\n"));
1101     }
1102   }
1103 }
1104 
1105 /**
1106   Unregister the shutdown notification through the ResetNotification protocol.
1107 
1108   Unregister the shutdown notification when mNvmeControllerNumber decreased from 1 to 0.
1109 **/
1110 VOID
NvmeUnregisterShutdownNotification(VOID)1111 NvmeUnregisterShutdownNotification (
1112   VOID
1113   )
1114 {
1115   EFI_STATUS                      Status;
1116   EFI_RESET_NOTIFICATION_PROTOCOL *ResetNotify;
1117 
1118   mNvmeControllerNumber--;
1119   if (mNvmeControllerNumber == 0) {
1120     Status = gBS->LocateProtocol (&gEfiResetNotificationProtocolGuid, NULL, (VOID **) &ResetNotify);
1121     if (!EFI_ERROR (Status)) {
1122       Status = ResetNotify->UnregisterResetNotify (ResetNotify, NvmeShutdownAllControllers);
1123       ASSERT_EFI_ERROR (Status);
1124     }
1125   }
1126 }
1127