UINT32 BlockSize;\r
volatile VIRTIO_BLK_REQ Request;\r
volatile UINT8 HostStatus;\r
- UINT16 FirstAvailIdx;\r
- UINT16 NextAvailIdx;\r
- UINTN PollPeriodUsecs;\r
+ DESC_INDICES Indices;\r
\r
BlockSize = Dev->BlockIoMedia.BlockSize;\r
\r
Request.IoPrio = 0;\r
Request.Sector = Lba * (BlockSize / 512);\r
\r
- //\r
- // Prepare for virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device.\r
- // We're going to poll the answer, the host should not send an interrupt.\r
- //\r
- *Dev->Ring.Avail.Flags = (UINT16) VRING_AVAIL_F_NO_INTERRUPT;\r
+ VirtioPrepare (&Dev->Ring, &Indices);\r
\r
//\r
// preset a host status for ourselves that we do not accept as success\r
//\r
ASSERT (Dev->Ring.QueueSize >= 3);\r
\r
- //\r
- // Implement virtio-0.9.5, 2.4.1 Supplying Buffers to the Device.\r
- //\r
- FirstAvailIdx = *Dev->Ring.Avail.Idx;\r
- NextAvailIdx = FirstAvailIdx;\r
-\r
//\r
// virtio-blk header in first desc\r
//\r
VirtioAppendDesc (&Dev->Ring, (UINTN) &Request, sizeof Request,\r
- VRING_DESC_F_NEXT, FirstAvailIdx, &NextAvailIdx);\r
+ VRING_DESC_F_NEXT, &Indices);\r
\r
//\r
// data buffer for read/write in second desc\r
//\r
VirtioAppendDesc (&Dev->Ring, (UINTN) Buffer, (UINT32) BufferSize,\r
VRING_DESC_F_NEXT | (RequestIsWrite ? 0 : VRING_DESC_F_WRITE),\r
- FirstAvailIdx, &NextAvailIdx);\r
+ &Indices);\r
}\r
\r
//\r
// host status in last (second or third) desc\r
//\r
VirtioAppendDesc (&Dev->Ring, (UINTN) &HostStatus, sizeof HostStatus,\r
- VRING_DESC_F_WRITE, FirstAvailIdx, &NextAvailIdx);\r
+ VRING_DESC_F_WRITE, &Indices);\r
\r
//\r
- // virtio-0.9.5, 2.4.1.3 Updating the Index Field\r
+ // virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).\r
//\r
- MemoryFence();\r
- *Dev->Ring.Avail.Idx = NextAvailIdx;\r
-\r
- //\r
- // virtio-0.9.5, 2.4.1.4 Notifying the Device -- gratuitous notifications are\r
- // OK. virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).\r
- //\r
- MemoryFence();\r
- if (EFI_ERROR (VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueNotify, 0))) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- //\r
- // virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device\r
- // Wait until the host processes and acknowledges our 3-part descriptor\r
- // chain. The condition we use for polling is greatly simplified and relies\r
- // on synchronous, the lock-step progress.\r
- //\r
- // Keep slowing down until we reach a poll period of slightly above 1 ms.\r
- //\r
- PollPeriodUsecs = 1;\r
- MemoryFence();\r
- while (*Dev->Ring.Used.Idx != NextAvailIdx) {\r
- gBS->Stall (PollPeriodUsecs); // calls AcpiTimerLib::MicroSecondDelay\r
-\r
- if (PollPeriodUsecs < 1024) {\r
- PollPeriodUsecs *= 2;\r
- }\r
- MemoryFence();\r
- }\r
-\r
- if (HostStatus == VIRTIO_BLK_S_OK) {\r
+ if (VirtioFlush (Dev->PciIo, 0, &Dev->Ring, &Indices) == EFI_SUCCESS &&\r
+ HostStatus == VIRTIO_BLK_S_OK) {\r
return EFI_SUCCESS;\r
}\r
\r