EFI_NVM_EXPRESS_COMPLETION Completion;\r
EFI_STATUS Status;\r
NVME_ADMIN_CRIOCQ CrIoCq;\r
+ UINT32 Index;\r
+ UINT16 QueueSize;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ for (Index = 1; Index < NVME_MAX_QUEUES; Index++) {\r
+ ZeroMem (&CommandPacket, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));\r
+ ZeroMem (&Command, sizeof(EFI_NVM_EXPRESS_COMMAND));\r
+ ZeroMem (&Completion, sizeof(EFI_NVM_EXPRESS_COMPLETION));\r
+ ZeroMem (&CrIoCq, sizeof(NVME_ADMIN_CRIOCQ));\r
+\r
+ CommandPacket.NvmeCmd = &Command;\r
+ CommandPacket.NvmeCompletion = &Completion;\r
+\r
+ Command.Cdw0.Opcode = NVME_ADMIN_CRIOCQ_CMD;\r
+ CommandPacket.TransferBuffer = Private->CqBufferPciAddr[Index];\r
+ CommandPacket.TransferLength = EFI_PAGE_SIZE;\r
+ CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;\r
+ CommandPacket.QueueType = NVME_ADMIN_QUEUE;\r
+\r
+ if (Index == 1) {\r
+ QueueSize = NVME_CCQ_SIZE;\r
+ } else {\r
+ if (Private->Cap.Mqes > NVME_ASYNC_CCQ_SIZE) {\r
+ QueueSize = NVME_ASYNC_CCQ_SIZE;\r
+ } else {\r
+ QueueSize = Private->Cap.Mqes;\r
+ }\r
+ }\r
\r
- ZeroMem (&CommandPacket, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));\r
- ZeroMem (&Command, sizeof(EFI_NVM_EXPRESS_COMMAND));\r
- ZeroMem (&Completion, sizeof(EFI_NVM_EXPRESS_COMPLETION));\r
- ZeroMem (&CrIoCq, sizeof(NVME_ADMIN_CRIOCQ));\r
-\r
- CommandPacket.NvmeCmd = &Command;\r
- CommandPacket.NvmeCompletion = &Completion;\r
-\r
- Command.Cdw0.Opcode = NVME_ADMIN_CRIOCQ_CMD;\r
- CommandPacket.TransferBuffer = Private->CqBufferPciAddr[1];\r
- CommandPacket.TransferLength = EFI_PAGE_SIZE;\r
- CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;\r
- CommandPacket.QueueType = NVME_ADMIN_QUEUE;\r
-\r
- CrIoCq.Qid = NVME_IO_QUEUE;\r
- CrIoCq.Qsize = NVME_CCQ_SIZE;\r
- CrIoCq.Pc = 1;\r
- CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoCq, sizeof (NVME_ADMIN_CRIOCQ));\r
- CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;\r
-\r
- Status = Private->Passthru.PassThru (\r
- &Private->Passthru,\r
- 0,\r
- &CommandPacket,\r
- NULL\r
- );\r
+ CrIoCq.Qid = Index;\r
+ CrIoCq.Qsize = QueueSize;\r
+ CrIoCq.Pc = 1;\r
+ CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoCq, sizeof (NVME_ADMIN_CRIOCQ));\r
+ CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;\r
+\r
+ Status = Private->Passthru.PassThru (\r
+ &Private->Passthru,\r
+ 0,\r
+ &CommandPacket,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ }\r
\r
return Status;\r
}\r
EFI_NVM_EXPRESS_COMPLETION Completion;\r
EFI_STATUS Status;\r
NVME_ADMIN_CRIOSQ CrIoSq;\r
+ UINT32 Index;\r
+ UINT16 QueueSize;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ for (Index = 1; Index < NVME_MAX_QUEUES; Index++) {\r
+ ZeroMem (&CommandPacket, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));\r
+ ZeroMem (&Command, sizeof(EFI_NVM_EXPRESS_COMMAND));\r
+ ZeroMem (&Completion, sizeof(EFI_NVM_EXPRESS_COMPLETION));\r
+ ZeroMem (&CrIoSq, sizeof(NVME_ADMIN_CRIOSQ));\r
+\r
+ CommandPacket.NvmeCmd = &Command;\r
+ CommandPacket.NvmeCompletion = &Completion;\r
+\r
+ Command.Cdw0.Opcode = NVME_ADMIN_CRIOSQ_CMD;\r
+ CommandPacket.TransferBuffer = Private->SqBufferPciAddr[Index];\r
+ CommandPacket.TransferLength = EFI_PAGE_SIZE;\r
+ CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;\r
+ CommandPacket.QueueType = NVME_ADMIN_QUEUE;\r
+\r
+ if (Index == 1) {\r
+ QueueSize = NVME_CSQ_SIZE;\r
+ } else {\r
+ if (Private->Cap.Mqes > NVME_ASYNC_CSQ_SIZE) {\r
+ QueueSize = NVME_ASYNC_CSQ_SIZE;\r
+ } else {\r
+ QueueSize = Private->Cap.Mqes;\r
+ }\r
+ }\r
\r
- ZeroMem (&CommandPacket, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));\r
- ZeroMem (&Command, sizeof(EFI_NVM_EXPRESS_COMMAND));\r
- ZeroMem (&Completion, sizeof(EFI_NVM_EXPRESS_COMPLETION));\r
- ZeroMem (&CrIoSq, sizeof(NVME_ADMIN_CRIOSQ));\r
-\r
- CommandPacket.NvmeCmd = &Command;\r
- CommandPacket.NvmeCompletion = &Completion;\r
-\r
- Command.Cdw0.Opcode = NVME_ADMIN_CRIOSQ_CMD;\r
- CommandPacket.TransferBuffer = Private->SqBufferPciAddr[1];\r
- CommandPacket.TransferLength = EFI_PAGE_SIZE;\r
- CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;\r
- CommandPacket.QueueType = NVME_ADMIN_QUEUE;\r
-\r
- CrIoSq.Qid = NVME_IO_QUEUE;\r
- CrIoSq.Qsize = NVME_CSQ_SIZE;\r
- CrIoSq.Pc = 1;\r
- CrIoSq.Cqid = NVME_IO_QUEUE;\r
- CrIoSq.Qprio = 0;\r
- CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoSq, sizeof (NVME_ADMIN_CRIOSQ));\r
- CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;\r
-\r
- Status = Private->Passthru.PassThru (\r
- &Private->Passthru,\r
- 0,\r
- &CommandPacket,\r
- NULL\r
- );\r
+ CrIoSq.Qid = Index;\r
+ CrIoSq.Qsize = QueueSize;\r
+ CrIoSq.Pc = 1;\r
+ CrIoSq.Cqid = Index;\r
+ CrIoSq.Qprio = 0;\r
+ CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoSq, sizeof (NVME_ADMIN_CRIOSQ));\r
+ CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;\r
+\r
+ Status = Private->Passthru.PassThru (\r
+ &Private->Passthru,\r
+ 0,\r
+ &CommandPacket,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ }\r
\r
return Status;\r
}\r
NVME_AQA Aqa;\r
NVME_ASQ Asq;\r
NVME_ACQ Acq;\r
-\r
+ UINT8 Sn[21];\r
+ UINT8 Mn[41];\r
//\r
// Save original PCI attributes and enable this controller.\r
//\r
return Status;\r
}\r
\r
+ //\r
+ // Enable 64-bit DMA support in the PCI layer.\r
+ //\r
+ Status = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationEnable,\r
+ EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_WARN, "NvmeControllerInit: failed to enable 64-bit DMA (%r)\n", Status));\r
+ }\r
+\r
//\r
// Read the Controller Capabilities register and verify that the NVM command set is supported\r
//\r
\r
Private->Cid[0] = 0;\r
Private->Cid[1] = 0;\r
+ Private->Cid[2] = 0;\r
+ Private->Pt[0] = 0;\r
+ Private->Pt[1] = 0;\r
+ Private->Pt[2] = 0;\r
+ Private->SqTdbl[0].Sqt = 0;\r
+ Private->SqTdbl[1].Sqt = 0;\r
+ Private->SqTdbl[2].Sqt = 0;\r
+ Private->CqHdbl[0].Cqh = 0;\r
+ Private->CqHdbl[1].Cqh = 0;\r
+ Private->CqHdbl[2].Cqh = 0;\r
+ Private->AsyncSqHead = 0;\r
\r
Status = NvmeDisableController (Private);\r
\r
//\r
// Address of I/O submission & completion queue.\r
//\r
+ ZeroMem (Private->Buffer, EFI_PAGES_TO_SIZE (6));\r
Private->SqBuffer[0] = (NVME_SQ *)(UINTN)(Private->Buffer);\r
Private->SqBufferPciAddr[0] = (NVME_SQ *)(UINTN)(Private->BufferPciAddr);\r
Private->CqBuffer[0] = (NVME_CQ *)(UINTN)(Private->Buffer + 1 * EFI_PAGE_SIZE);\r
Private->SqBufferPciAddr[1] = (NVME_SQ *)(UINTN)(Private->BufferPciAddr + 2 * EFI_PAGE_SIZE);\r
Private->CqBuffer[1] = (NVME_CQ *)(UINTN)(Private->Buffer + 3 * EFI_PAGE_SIZE);\r
Private->CqBufferPciAddr[1] = (NVME_CQ *)(UINTN)(Private->BufferPciAddr + 3 * EFI_PAGE_SIZE);\r
+ Private->SqBuffer[2] = (NVME_SQ *)(UINTN)(Private->Buffer + 4 * EFI_PAGE_SIZE);\r
+ Private->SqBufferPciAddr[2] = (NVME_SQ *)(UINTN)(Private->BufferPciAddr + 4 * EFI_PAGE_SIZE);\r
+ Private->CqBuffer[2] = (NVME_CQ *)(UINTN)(Private->Buffer + 5 * EFI_PAGE_SIZE);\r
+ Private->CqBufferPciAddr[2] = (NVME_CQ *)(UINTN)(Private->BufferPciAddr + 5 * EFI_PAGE_SIZE);\r
\r
DEBUG ((EFI_D_INFO, "Private->Buffer = [%016X]\n", (UINT64)(UINTN)Private->Buffer));\r
- DEBUG ((EFI_D_INFO, "Admin Submission Queue size (Aqa.Asqs) = [%08X]\n", Aqa.Asqs));\r
- DEBUG ((EFI_D_INFO, "Admin Completion Queue size (Aqa.Acqs) = [%08X]\n", Aqa.Acqs));\r
- DEBUG ((EFI_D_INFO, "Admin Submission Queue (SqBuffer[0]) = [%016X]\n", Private->SqBuffer[0]));\r
- DEBUG ((EFI_D_INFO, "Admin Completion Queue (CqBuffer[0]) = [%016X]\n", Private->CqBuffer[0]));\r
- DEBUG ((EFI_D_INFO, "I/O Submission Queue (SqBuffer[1]) = [%016X]\n", Private->SqBuffer[1]));\r
- DEBUG ((EFI_D_INFO, "I/O Completion Queue (CqBuffer[1]) = [%016X]\n", Private->CqBuffer[1]));\r
+ DEBUG ((EFI_D_INFO, "Admin Submission Queue size (Aqa.Asqs) = [%08X]\n", Aqa.Asqs));\r
+ DEBUG ((EFI_D_INFO, "Admin Completion Queue size (Aqa.Acqs) = [%08X]\n", Aqa.Acqs));\r
+ DEBUG ((EFI_D_INFO, "Admin Submission Queue (SqBuffer[0]) = [%016X]\n", Private->SqBuffer[0]));\r
+ DEBUG ((EFI_D_INFO, "Admin Completion Queue (CqBuffer[0]) = [%016X]\n", Private->CqBuffer[0]));\r
+ DEBUG ((EFI_D_INFO, "Sync I/O Submission Queue (SqBuffer[1]) = [%016X]\n", Private->SqBuffer[1]));\r
+ DEBUG ((EFI_D_INFO, "Sync I/O Completion Queue (CqBuffer[1]) = [%016X]\n", Private->CqBuffer[1]));\r
+ DEBUG ((EFI_D_INFO, "Async I/O Submission Queue (SqBuffer[2]) = [%016X]\n", Private->SqBuffer[2]));\r
+ DEBUG ((EFI_D_INFO, "Async I/O Completion Queue (CqBuffer[2]) = [%016X]\n", Private->CqBuffer[2]));\r
\r
//\r
// Program admin queue attributes.\r
//\r
// Allocate buffer for Identify Controller data\r
//\r
- Private->ControllerData = (NVME_ADMIN_CONTROLLER_DATA *)AllocateZeroPool (sizeof(NVME_ADMIN_CONTROLLER_DATA));\r
-\r
if (Private->ControllerData == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ Private->ControllerData = (NVME_ADMIN_CONTROLLER_DATA *)AllocateZeroPool (sizeof(NVME_ADMIN_CONTROLLER_DATA));\r
+ \r
+ if (Private->ControllerData == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
}\r
\r
//\r
//\r
// Dump NvmExpress Identify Controller Data\r
//\r
- Private->ControllerData->Sn[19] = 0;\r
- Private->ControllerData->Mn[39] = 0;\r
+ CopyMem (Sn, Private->ControllerData->Sn, sizeof (Private->ControllerData->Sn));\r
+ Sn[20] = 0;\r
+ CopyMem (Mn, Private->ControllerData->Mn, sizeof (Private->ControllerData->Mn));\r
+ Mn[40] = 0;\r
DEBUG ((EFI_D_INFO, " == NVME IDENTIFY CONTROLLER DATA ==\n"));\r
DEBUG ((EFI_D_INFO, " PCI VID : 0x%x\n", Private->ControllerData->Vid));\r
DEBUG ((EFI_D_INFO, " PCI SSVID : 0x%x\n", Private->ControllerData->Ssvid));\r
- DEBUG ((EFI_D_INFO, " SN : %a\n", (CHAR8 *)(Private->ControllerData->Sn)));\r
- DEBUG ((EFI_D_INFO, " MN : %a\n", (CHAR8 *)(Private->ControllerData->Mn)));\r
+ DEBUG ((EFI_D_INFO, " SN : %a\n", Sn));\r
+ DEBUG ((EFI_D_INFO, " MN : %a\n", Mn));\r
DEBUG ((EFI_D_INFO, " FR : 0x%x\n", *((UINT64*)Private->ControllerData->Fr)));\r
DEBUG ((EFI_D_INFO, " RAB : 0x%x\n", Private->ControllerData->Rab));\r
DEBUG ((EFI_D_INFO, " IEEE : 0x%x\n", *(UINT32*)Private->ControllerData->Ieee_oui));\r
DEBUG ((EFI_D_INFO, " NN : 0x%x\n", Private->ControllerData->Nn));\r
\r
//\r
- // Create one I/O completion queue.\r
+ // Create two I/O completion queues.\r
+ // One for blocking I/O, one for non-blocking I/O.\r
//\r
Status = NvmeCreateIoCompletionQueue (Private);\r
if (EFI_ERROR(Status)) {\r
}\r
\r
//\r
- // Create one I/O Submission queue.\r
+ // Create two I/O Submission queues.\r
+ // One for blocking I/O, one for non-blocking I/O.\r
//\r
Status = NvmeCreateIoSubmissionQueue (Private);\r
if (EFI_ERROR(Status)) {\r