]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/VirtioBlkDxe/VirtioBlk.c
OvmfPkg: librarize reusable bits from VirtioBlkDxe's SynchronousRequest()
[mirror_edk2.git] / OvmfPkg / VirtioBlkDxe / VirtioBlk.c
index ce38ff70936ed1744020d12dc06af225fd4766e6..44a05cfb5f8be21a546ed48deb95605fed21ea95 100644 (file)
@@ -248,9 +248,7 @@ SynchronousRequest (
   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
@@ -275,11 +273,7 @@ SynchronousRequest (
   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
@@ -292,17 +286,11 @@ SynchronousRequest (
   //\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
@@ -323,50 +311,20 @@ SynchronousRequest (
     //\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