EFI_PCI_IO_PROTOCOL *PciIo;\r
NVME_SQ *Sq;\r
NVME_CQ *Cq;\r
- UINT8 QueueType;\r
+ UINT16 QueueId;\r
UINT32 Bytes;\r
UINT16 Offset;\r
EFI_EVENT TimerEvent;\r
VOID *PrpListHost;\r
UINTN PrpListNo;\r
UINT32 Data;\r
+ NVME_PASS_THRU_ASYNC_REQ *AsyncRequest;\r
+ EFI_TPL OldTpl;\r
\r
//\r
// check the data fields in Packet parameter.\r
TimerEvent = NULL;\r
Status = EFI_SUCCESS;\r
\r
- QueueType = Packet->QueueType;\r
- Sq = Private->SqBuffer[QueueType] + Private->SqTdbl[QueueType].Sqt;\r
- Cq = Private->CqBuffer[QueueType] + Private->CqHdbl[QueueType].Cqh;\r
+ if (Packet->QueueType == NVME_ADMIN_QUEUE) {\r
+ QueueId = 0;\r
+ } else {\r
+ if (Event == NULL) {\r
+ QueueId = 1;\r
+ } else {\r
+ QueueId = 2;\r
+\r
+ //\r
+ // Submission queue full check.\r
+ //\r
+ if ((Private->SqTdbl[QueueId].Sqt + 1) % (NVME_ASYNC_CSQ_SIZE + 1) ==\r
+ Private->AsyncSqHead) {\r
+ return EFI_NOT_READY;\r
+ }\r
+ }\r
+ }\r
+ Sq = Private->SqBuffer[QueueId] + Private->SqTdbl[QueueId].Sqt;\r
+ Cq = Private->CqBuffer[QueueId] + Private->CqHdbl[QueueId].Cqh;\r
\r
if (Packet->NvmeCmd->Nsid != NamespaceId) {\r
return EFI_INVALID_PARAMETER;\r
ZeroMem (Sq, sizeof (NVME_SQ));\r
Sq->Opc = (UINT8)Packet->NvmeCmd->Cdw0.Opcode;\r
Sq->Fuse = (UINT8)Packet->NvmeCmd->Cdw0.FusedOperation;\r
- Sq->Cid = Private->Cid[QueueType]++;\r
+ Sq->Cid = Private->Cid[QueueId]++;\r
Sq->Nsid = Packet->NvmeCmd->Nsid;\r
\r
//\r
//\r
// Ring the submission queue doorbell.\r
//\r
- Private->SqTdbl[QueueType].Sqt ^= 1;\r
- Data = ReadUnaligned32 ((UINT32*)&Private->SqTdbl[QueueType]);\r
+ if (Event != NULL) {\r
+ Private->SqTdbl[QueueId].Sqt =\r
+ (Private->SqTdbl[QueueId].Sqt + 1) % (NVME_ASYNC_CSQ_SIZE + 1);\r
+ } else {\r
+ Private->SqTdbl[QueueId].Sqt ^= 1;\r
+ }\r
+ Data = ReadUnaligned32 ((UINT32*)&Private->SqTdbl[QueueId]);\r
PciIo->Mem.Write (\r
PciIo,\r
EfiPciIoWidthUint32,\r
NVME_BAR,\r
- NVME_SQTDBL_OFFSET(QueueType, Private->Cap.Dstrd),\r
+ NVME_SQTDBL_OFFSET(QueueId, Private->Cap.Dstrd),\r
1,\r
&Data\r
);\r
\r
+ //\r
+ // For non-blocking requests, return directly if the command is placed\r
+ // in the submission queue.\r
+ //\r
+ if (Event != NULL) {\r
+ AsyncRequest = AllocateZeroPool (sizeof (NVME_PASS_THRU_ASYNC_REQ));\r
+ if (AsyncRequest == NULL) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto EXIT;\r
+ }\r
+\r
+ AsyncRequest->Signature = NVME_PASS_THRU_ASYNC_REQ_SIG;\r
+ AsyncRequest->Packet = Packet;\r
+ AsyncRequest->CommandId = Sq->Cid;\r
+ AsyncRequest->CallerEvent = Event;\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+ InsertTailList (&Private->AsyncPassThruQueue, &AsyncRequest->Link);\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
Status = gBS->CreateEvent (\r
EVT_TIMER,\r
TPL_CALLBACK,\r
//\r
Status = EFI_TIMEOUT;\r
while (EFI_ERROR (gBS->CheckEvent (TimerEvent))) {\r
- if (Cq->Pt != Private->Pt[QueueType]) {\r
+ if (Cq->Pt != Private->Pt[QueueId]) {\r
Status = EFI_SUCCESS;\r
break;\r
}\r
}\r
}\r
\r
- if ((Private->CqHdbl[QueueType].Cqh ^= 1) == 0) {\r
- Private->Pt[QueueType] ^= 1;\r
+ if ((Private->CqHdbl[QueueId].Cqh ^= 1) == 0) {\r
+ Private->Pt[QueueId] ^= 1;\r
}\r
\r
- Data = ReadUnaligned32 ((UINT32*)&Private->CqHdbl[QueueType]);\r
+ Data = ReadUnaligned32 ((UINT32*)&Private->CqHdbl[QueueId]);\r
PciIo->Mem.Write (\r
PciIo,\r
EfiPciIoWidthUint32,\r
NVME_BAR,\r
- NVME_CQHDBL_OFFSET(QueueType, Private->Cap.Dstrd),\r
+ NVME_CQHDBL_OFFSET(QueueId, Private->Cap.Dstrd),\r
1,\r
&Data\r
);\r