]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/VirtioBlkDxe/VirtioBlk.c
OvmfPkg: Removed magic values for the Virtio Sub-System ID in the PCI device drivers
[mirror_edk2.git] / OvmfPkg / VirtioBlkDxe / VirtioBlk.c
index eeeb4bef6e21ec7ef6434b066552030ae5f1a411..17b9f71d63beadcb434ea4bda2a0bf632a5e729f 100644 (file)
@@ -11,6 +11,7 @@
     synchronous requests and EFI_BLOCK_IO_PROTOCOL for now.\r
 \r
   Copyright (C) 2012, Red Hat, Inc.\r
+  Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
 \r
   This program and the accompanying materials are licensed and made available\r
   under the terms and conditions of the BSD License which accompanies this\r
@@ -248,9 +249,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
@@ -273,13 +272,9 @@ SynchronousRequest (
                    (BufferSize == 0 ? VIRTIO_BLK_T_FLUSH : VIRTIO_BLK_T_OUT) :\r
                    VIRTIO_BLK_T_IN;\r
   Request.IoPrio = 0;\r
-  Request.Sector = Lba * (BlockSize / 512);\r
+  Request.Sector = MultU64x32(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 +287,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
-  AppendDesc (&Dev->Ring, (UINTN) &Request, sizeof Request, VRING_DESC_F_NEXT,\r
-    FirstAvailIdx, &NextAvailIdx);\r
+  VirtioAppendDesc (&Dev->Ring, (UINTN) &Request, sizeof Request,\r
+    VRING_DESC_F_NEXT, &Indices);\r
 \r
   //\r
   // data buffer for read/write in second desc\r
@@ -321,52 +310,22 @@ SynchronousRequest (
     //\r
     // VRING_DESC_F_WRITE is interpreted from the host's point of view.\r
     //\r
-    AppendDesc (&Dev->Ring, (UINTN) Buffer, (UINT32) BufferSize,\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
-  AppendDesc (&Dev->Ring, (UINTN) &HostStatus, sizeof HostStatus,\r
-    VRING_DESC_F_WRITE, FirstAvailIdx, &NextAvailIdx);\r
+  VirtioAppendDesc (&Dev->Ring, (UINTN) &HostStatus, sizeof HostStatus,\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
@@ -616,7 +575,7 @@ VirtioBlkDriverBindingSupported (
     Status = (Pci.Hdr.VendorId == 0x1AF4 &&\r
               Pci.Hdr.DeviceId >= 0x1000 && Pci.Hdr.DeviceId <= 0x103F &&\r
               Pci.Hdr.RevisionID == 0x00 &&\r
-              Pci.Device.SubsystemID == 0x02) ? EFI_SUCCESS : EFI_UNSUPPORTED;\r
+              Pci.Device.SubsystemID == VIRTIO_SUBSYSTEM_BLOCK_DEVICE) ? EFI_SUCCESS : EFI_UNSUPPORTED;\r
   }\r
 \r
   //\r
@@ -706,7 +665,7 @@ VirtioBlkInit (
       goto Failed;\r
     }\r
     if (BlockSize == 0 || BlockSize % 512 != 0 ||\r
-        NumSectors % (BlockSize / 512) != 0) {\r
+        ModU64x32 (NumSectors, BlockSize / 512) != 0) {\r
       //\r
       // We can only handle a logical block consisting of whole sectors,\r
       // and only a disk composed of whole logical blocks.\r
@@ -789,7 +748,8 @@ VirtioBlkInit (
   Dev->BlockIoMedia.WriteCaching     = !!(Features & VIRTIO_BLK_F_FLUSH);\r
   Dev->BlockIoMedia.BlockSize        = BlockSize;\r
   Dev->BlockIoMedia.IoAlign          = 0;\r
-  Dev->BlockIoMedia.LastBlock        = NumSectors / (BlockSize / 512) - 1;\r
+  Dev->BlockIoMedia.LastBlock        = DivU64x32 (NumSectors,\r
+                                         BlockSize / 512) - 1;\r
   return EFI_SUCCESS;\r
 \r
 ReleaseQueue:\r
@@ -984,18 +944,32 @@ VirtioBlkDriverBindingStop (
   IN EFI_HANDLE                  *ChildHandleBuffer\r
   )\r
 {\r
-  VBLK_DEV   *Dev;\r
-  EFI_STATUS Status;\r
+  EFI_STATUS            Status;\r
+  EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
+  VBLK_DEV              *Dev;\r
 \r
-  Dev = VIRTIO_BLK_FROM_BLOCK_IO (This);\r
+  Status = gBS->OpenProtocol (\r
+                  DeviceHandle,                  // candidate device\r
+                  &gEfiBlockIoProtocolGuid,      // retrieve the BlockIo iface\r
+                  (VOID **)&BlockIo,             // target pointer\r
+                  This->DriverBindingHandle,     // requestor driver identity\r
+                  DeviceHandle,                  // requesting lookup for dev.\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no ref. added\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Dev = VIRTIO_BLK_FROM_BLOCK_IO (BlockIo);\r
 \r
   //\r
-  // If DriverBindingStop() is called with the driver instance still in use,\r
-  // or any of the parameters are invalid, we've caught a bug.\r
+  // Handle Stop() requests for in-use driver instances gracefully.\r
   //\r
   Status = gBS->UninstallProtocolInterface (DeviceHandle,\r
                   &gEfiBlockIoProtocolGuid, &Dev->BlockIo);\r
-  ASSERT (Status == EFI_SUCCESS);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
   VirtioBlkUninit (Dev);\r
 \r
@@ -1039,13 +1013,13 @@ STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
 // for unambiguous identification.\r
 //\r
 \r
-STATIC GLOBAL_REMOVE_IF_UNREFERENCED\r
+STATIC\r
 EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {\r
   { "eng;en", L"Virtio Block Driver" },\r
   { NULL,     NULL                   }\r
 };\r
 \r
-STATIC GLOBAL_REMOVE_IF_UNREFERENCED\r
+STATIC\r
 EFI_COMPONENT_NAME_PROTOCOL gComponentName;\r
 \r
 EFI_STATUS\r
@@ -1078,14 +1052,14 @@ VirtioBlkGetDeviceName (
   return EFI_UNSUPPORTED;\r
 }\r
 \r
-STATIC GLOBAL_REMOVE_IF_UNREFERENCED\r
+STATIC\r
 EFI_COMPONENT_NAME_PROTOCOL gComponentName = {\r
   &VirtioBlkGetDriverName,\r
   &VirtioBlkGetDeviceName,\r
   "eng" // SupportedLanguages, ISO 639-2 language codes\r
 };\r
 \r
-STATIC GLOBAL_REMOVE_IF_UNREFERENCED\r
+STATIC\r
 EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {\r
   (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)     &VirtioBlkGetDriverName,\r
   (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &VirtioBlkGetDeviceName,\r