]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/VirtioBlkDxe/VirtioBlk.c
OvmfPkg: Make the VirtIo devices use the new VIRTIO_DEVICE_PROTOCOL
[mirror_edk2.git] / OvmfPkg / VirtioBlkDxe / VirtioBlk.c
index 199b9dd0ae895c86b894b0f6da3515a338c98555..f09b0d1118dca684454eec61f026fd549494b011 100644 (file)
@@ -23,7 +23,6 @@
 \r
 **/\r
 \r
-#include <IndustryStandard/Pci.h>\r
 #include <IndustryStandard/VirtioBlk.h>\r
 #include <Library/BaseMemoryLib.h>\r
 #include <Library/DebugLib.h>\r
 /**\r
 \r
   Convenience macros to read and write region 0 IO space elements of the\r
-  virtio-blk PCI device, for configuration purposes.\r
+  virtio-blk device, for configuration purposes.\r
 \r
   The following macros make it possible to specify only the "core parameters"\r
   for such accesses and to derive the rest. By the time VIRTIO_CFG_WRITE()\r
   returns, the transaction will have been completed.\r
 \r
-  @param[in] Dev       Pointer to the VBLK_DEV structure whose PCI IO space\r
-                       we're accessing. Dev->PciIo must be valid.\r
+  @param[in] Dev       Pointer to the VBLK_DEV structure whose VirtIo space\r
+                       we're accessing. Dev->VirtIo must be valid.\r
 \r
   @param[in] Field     A field name from VBLK_HDR, identifying the virtio-blk\r
                        configuration item to access.\r
                        one of UINT8, UINT16, UINT32, UINT64.\r
 \r
 \r
-  @return  Status code returned by VirtioWrite() / VirtioRead().\r
+  @return  Status code returned by VirtioWriteDevice() / VirtioReadDevice().\r
 \r
 **/\r
 \r
-#define VIRTIO_CFG_WRITE(Dev, Field, Value)  (VirtioWrite (             \\r
-                                                (Dev)->PciIo,           \\r
+#define VIRTIO_CFG_WRITE(Dev, Field, Value)  (VirtioWriteDevice (       \\r
+                                                (Dev)->VirtIo,          \\r
                                                 OFFSET_OF_VBLK (Field), \\r
                                                 SIZE_OF_VBLK (Field),   \\r
                                                 (Value)                 \\r
                                                 ))\r
 \r
-#define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioRead (              \\r
-                                                (Dev)->PciIo,           \\r
+#define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioReadDevice (        \\r
+                                                (Dev)->VirtIo,          \\r
                                                 OFFSET_OF_VBLK (Field), \\r
                                                 SIZE_OF_VBLK (Field),   \\r
                                                 sizeof *(Pointer),      \\r
@@ -229,7 +228,7 @@ VerifyReadWriteRequest (
 \r
   @retval EFI_SUCCESS          Transfer complete.\r
 \r
-  @retval EFI_DEVICE_ERROR     Failed to notify host side via PCI write, or\r
+  @retval EFI_DEVICE_ERROR     Failed to notify host side via VirtIo write, or\r
                                unable to parse host response, or host response\r
                                is not VIRTIO_BLK_S_OK.\r
 \r
@@ -324,7 +323,7 @@ SynchronousRequest (
   //\r
   // virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).\r
   //\r
-  if (VirtioFlush (Dev->PciIo, 0, &Dev->Ring, &Indices) == EFI_SUCCESS &&\r
+  if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices) == EFI_SUCCESS &&\r
       HostStatus == VIRTIO_BLK_S_OK) {\r
     return EFI_SUCCESS;\r
   }\r
@@ -500,11 +499,6 @@ VirtioBlkFlushBlocks (
       underlying device\r
     - 9 Driver Binding Protocol -- for exporting ourselves\r
 \r
-  Specs relevant in the specific sense:\r
-  - UEFI Spec 2.3.1 + Errata C, 13.4 EFI PCI I/O Protocol\r
-  - Driver Writer's Guide for UEFI 2.3.1 v1.01, 18 PCI Driver Design\r
-    Guidelines, 18.3 PCI drivers.\r
-\r
   @param[in]  This                The EFI_DRIVER_BINDING_PROTOCOL object\r
                                   incorporating this driver (independently of\r
                                   any device).\r
@@ -516,11 +510,11 @@ VirtioBlkFlushBlocks (
 \r
   @retval EFI_SUCCESS      The driver supports the device being probed.\r
 \r
-  @retval EFI_UNSUPPORTED  Based on virtio-blk PCI discovery, we do not support\r
+  @retval EFI_UNSUPPORTED  Based on virtio-blk discovery, we do not support\r
                            the device.\r
 \r
   @return                  Error codes from the OpenProtocol() boot service or\r
-                           the PciIo protocol.\r
+                           the VirtIo protocol.\r
 \r
 **/\r
 \r
@@ -533,56 +527,36 @@ VirtioBlkDriverBindingSupported (
   )\r
 {\r
   EFI_STATUS          Status;\r
-  EFI_PCI_IO_PROTOCOL *PciIo;\r
-  PCI_TYPE00          Pci;\r
+  VIRTIO_DEVICE_PROTOCOL *VirtIo;\r
 \r
   //\r
-  // Attempt to open the device with the PciIo set of interfaces. On success,\r
-  // the protocol is "instantiated" for the PCI device. Covers duplicate open\r
+  // Attempt to open the device with the VirtIo set of interfaces. On success,\r
+  // the protocol is "instantiated" for the VirtIo device. Covers duplicate open\r
   // attempts (EFI_ALREADY_STARTED).\r
   //\r
   Status = gBS->OpenProtocol (\r
                   DeviceHandle,               // candidate device\r
-                  &gEfiPciIoProtocolGuid,     // for generic PCI access\r
-                  (VOID **)&PciIo,            // handle to instantiate\r
+                  &gVirtioDeviceProtocolGuid, // for generic VirtIo access\r
+                  (VOID **)&VirtIo,           // handle to instantiate\r
                   This->DriverBindingHandle,  // requestor driver identity\r
                   DeviceHandle,               // ControllerHandle, according to\r
                                               // the UEFI Driver Model\r
-                  EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive PciIo access to\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive VirtIo access to\r
                                               // the device; to be released\r
                   );\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
-  //\r
-  // Read entire PCI configuration header for more extensive check ahead.\r
-  //\r
-  Status = PciIo->Pci.Read (\r
-                        PciIo,                        // (protocol, device)\r
-                                                      // handle\r
-                        EfiPciIoWidthUint32,          // access width & copy\r
-                                                      // mode\r
-                        0,                            // Offset\r
-                        sizeof Pci / sizeof (UINT32), // Count\r
-                        &Pci                          // target buffer\r
-                        );\r
-\r
-  if (Status == EFI_SUCCESS) {\r
-    //\r
-    // virtio-0.9.5, 2.1 PCI Discovery\r
-    //\r
-    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
+  if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_BLOCK_DEVICE) {\r
+    Status = EFI_UNSUPPORTED;\r
   }\r
 \r
   //\r
-  // We needed PCI IO access only transitorily, to see whether we support the\r
+  // We needed VirtIo access only transitorily, to see whether we support the\r
   // device or not.\r
   //\r
-  gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
+  gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
          This->DriverBindingHandle, DeviceHandle);\r
   return Status;\r
 }\r
@@ -594,8 +568,8 @@ VirtioBlkDriverBindingSupported (
   device.\r
 \r
   @param[in out] Dev  The driver instance to configure. The caller is\r
-                      responsible for Dev->PciIo's validity (ie. working IO\r
-                      access to the underlying virtio-blk PCI device).\r
+                      responsible for Dev->VirtIo's validity (ie. working IO\r
+                      access to the underlying virtio-blk device).\r
 \r
   @retval EFI_SUCCESS      Setup complete.\r
 \r
@@ -626,19 +600,27 @@ VirtioBlkInit (
   // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.\r
   //\r
   NextDevStat = 0;             // step 1 -- reset device\r
-  Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+  Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
   if (EFI_ERROR (Status)) {\r
     goto Failed;\r
   }\r
 \r
   NextDevStat |= VSTAT_ACK;    // step 2 -- acknowledge device presence\r
-  Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+  Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
   if (EFI_ERROR (Status)) {\r
     goto Failed;\r
   }\r
 \r
   NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it\r
-  Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+  Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Failed;\r
+  }\r
+\r
+  //\r
+  // Set Page Size - MMIO VirtIo Specific\r
+  //\r
+  Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE);\r
   if (EFI_ERROR (Status)) {\r
     goto Failed;\r
   }\r
@@ -646,11 +628,12 @@ VirtioBlkInit (
   //\r
   // step 4a -- retrieve and validate features\r
   //\r
-  Status = VIRTIO_CFG_READ (Dev, Generic.VhdrDeviceFeatureBits, &Features);\r
+  Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features);\r
   if (EFI_ERROR (Status)) {\r
     goto Failed;\r
   }\r
-  Status = VIRTIO_CFG_READ (Dev, VhdrCapacity, &NumSectors);\r
+\r
+  Status = VIRTIO_CFG_READ (Dev, Capacity, &NumSectors);\r
   if (EFI_ERROR (Status)) {\r
     goto Failed;\r
   }\r
@@ -660,7 +643,7 @@ VirtioBlkInit (
   }\r
 \r
   if (Features & VIRTIO_BLK_F_BLK_SIZE) {\r
-    Status = VIRTIO_CFG_READ (Dev, VhdrBlkSize, &BlockSize);\r
+    Status = VIRTIO_CFG_READ (Dev, BlkSize, &BlockSize);\r
     if (EFI_ERROR (Status)) {\r
       goto Failed;\r
     }\r
@@ -681,11 +664,11 @@ VirtioBlkInit (
   //\r
   // step 4b -- allocate virtqueue\r
   //\r
-  Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueSelect, 0);\r
+  Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, 0);\r
   if (EFI_ERROR (Status)) {\r
     goto Failed;\r
   }\r
-  Status = VIRTIO_CFG_READ (Dev, Generic.VhdrQueueSize, &QueueSize);\r
+  Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize);\r
   if (EFI_ERROR (Status)) {\r
     goto Failed;\r
   }\r
@@ -700,22 +683,36 @@ VirtioBlkInit (
   }\r
 \r
   //\r
-  // step 4c -- Report GPFN (guest-physical frame number) of queue. If anything\r
-  // fails from here on, we must release the ring resources.\r
+  // Additional steps for MMIO: align the queue appropriately, and set the\r
+  // size. If anything fails from here on, we must release the ring resources.\r
+  //\r
+  Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ReleaseQueue;\r
+  }\r
+\r
+  Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ReleaseQueue;\r
+  }\r
+\r
+  //\r
+  // step 4c -- Report GPFN (guest-physical frame number) of queue.\r
   //\r
-  Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueAddress,\r
-             (UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT);\r
+  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo,\r
+      (UINT32)(UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT);\r
   if (EFI_ERROR (Status)) {\r
     goto ReleaseQueue;\r
   }\r
 \r
+\r
   //\r
   // step 5 -- Report understood features. There are no virtio-blk specific\r
   // features to negotiate in virtio-0.9.5, plus we do not want any of the\r
   // device-independent (known or unknown) VIRTIO_F_* capabilities (see\r
   // Appendix B).\r
   //\r
-  Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrGuestFeatureBits, 0);\r
+  Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, 0);\r
   if (EFI_ERROR (Status)) {\r
     goto ReleaseQueue;\r
   }\r
@@ -724,7 +721,7 @@ VirtioBlkInit (
   // step 6 -- initialization complete\r
   //\r
   NextDevStat |= VSTAT_DRIVER_OK;\r
-  Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+  Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
   if (EFI_ERROR (Status)) {\r
     goto ReleaseQueue;\r
   }\r
@@ -758,10 +755,10 @@ ReleaseQueue:
 Failed:\r
   //\r
   // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device\r
-  // Status. PCI IO access failure here should not mask the original error.\r
+  // Status. VirtIo access failure here should not mask the original error.\r
   //\r
   NextDevStat |= VSTAT_FAILED;\r
-  VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+  Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
 \r
   return Status; // reached only via Failed above\r
 }\r
@@ -788,7 +785,7 @@ VirtioBlkUninit (
   // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from\r
   // the old comms area.\r
   //\r
-  VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0);\r
+  Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
 \r
   VirtioRingUninit (&Dev->Ring);\r
 \r
@@ -815,13 +812,13 @@ VirtioBlkUninit (
 \r
 \r
   @retval EFI_SUCCESS           Driver instance has been created and\r
-                                initialized  for the virtio-blk PCI device, it\r
+                                initialized  for the virtio-blk device, it\r
                                 is now accessibla via EFI_BLOCK_IO_PROTOCOL.\r
 \r
   @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.\r
 \r
   @return                       Error codes from the OpenProtocol() boot\r
-                                service, the PciIo protocol, VirtioBlkInit(),\r
+                                service, the VirtIo protocol, VirtioBlkInit(),\r
                                 or the InstallProtocolInterface() boot service.\r
 \r
 **/\r
@@ -842,43 +839,19 @@ VirtioBlkDriverBindingStart (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
-                  (VOID **)&Dev->PciIo, This->DriverBindingHandle,\r
+  Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
+                  (VOID **)&Dev->VirtIo, This->DriverBindingHandle,\r
                   DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);\r
   if (EFI_ERROR (Status)) {\r
     goto FreeVirtioBlk;\r
   }\r
 \r
   //\r
-  // We must retain and ultimately restore the original PCI attributes of the\r
-  // device. See Driver Writer's Guide for UEFI 2.3.1 v1.01, 18.3 PCI drivers /\r
-  // 18.3.2 Start() and Stop().\r
-  //\r
-  // The third parameter ("Attributes", input) is ignored by the Get operation.\r
-  // The fourth parameter ("Result", output) is ignored by the Enable and Set\r
-  // operations.\r
-  //\r
-  // For virtio-blk we only need IO space access.\r
-  //\r
-  Status = Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationGet,\r
-                         0, &Dev->OriginalPciAttributes);\r
-  if (EFI_ERROR (Status)) {\r
-    goto ClosePciIo;\r
-  }\r
-\r
-  Status = Dev->PciIo->Attributes (Dev->PciIo,\r
-                         EfiPciIoAttributeOperationEnable,\r
-                         EFI_PCI_IO_ATTRIBUTE_IO, NULL);\r
-  if (EFI_ERROR (Status)) {\r
-    goto ClosePciIo;\r
-  }\r
-\r
-  //\r
-  // PCI IO access granted, configure virtio-blk device.\r
+  // VirtIo access granted, configure virtio-blk device.\r
   //\r
   Status = VirtioBlkInit (Dev);\r
   if (EFI_ERROR (Status)) {\r
-    goto RestorePciAttributes;\r
+    goto CloseVirtIo;\r
   }\r
 \r
   //\r
@@ -897,12 +870,8 @@ VirtioBlkDriverBindingStart (
 UninitDev:\r
   VirtioBlkUninit (Dev);\r
 \r
-RestorePciAttributes:\r
-  Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet,\r
-                Dev->OriginalPciAttributes, NULL);\r
-\r
-ClosePciIo:\r
-  gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
+CloseVirtIo:\r
+  gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
          This->DriverBindingHandle, DeviceHandle);\r
 \r
 FreeVirtioBlk:\r
@@ -944,25 +913,36 @@ 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
-  Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet,\r
-                Dev->OriginalPciAttributes, NULL);\r
-\r
-  gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
+  gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
          This->DriverBindingHandle, DeviceHandle);\r
 \r
   FreePool (Dev);\r