]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/VirtioNetDxe/DriverBinding.c
OvmfPkg: VIRTIO_DEVICE_PROTOCOL: widen the Features bitmap to 64 bits
[mirror_edk2.git] / OvmfPkg / VirtioNetDxe / DriverBinding.c
index c9259ab3397b2451d5100e4296bb40255e43afa2..bcf9ebbdadbdfc4dc495b240d3a62b74cad49664 100644 (file)
@@ -3,7 +3,7 @@
   Driver Binding code and its private helpers for the virtio-net driver.\r
 \r
   Copyright (C) 2013, Red Hat, Inc.\r
-  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2006 - 2014, 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
@@ -15,7 +15,6 @@
 \r
 **/\r
 \r
-#include <IndustryStandard/Pci.h>\r
 #include <Library/BaseMemoryLib.h>\r
 #include <Library/DevicePathLib.h>\r
 #include <Library/MemoryAllocationLib.h>\r
@@ -50,8 +49,7 @@
                                     unused.\r
 \r
   @retval EFI_UNSUPPORTED           The host doesn't supply a MAC address.\r
-  @return                           Status codes from Dev->PciIo->Io.Read(),\r
-                                    VIRTIO_CFG_READ() and VIRTIO_CFG_WRITE().\r
+  @return                           Status codes from VirtIo protocol members.\r
   @retval EFI_SUCCESS               Configuration values retrieved.\r
 */\r
 STATIC\r
@@ -66,7 +64,8 @@ VirtioNetGetFeatures (
 {\r
   EFI_STATUS Status;\r
   UINT8      NextDevStat;\r
-  UINT32     Features;\r
+  UINT64     Features;\r
+  UINTN      MacIdx;\r
   UINT16     LinkStatus;\r
 \r
   //\r
@@ -74,19 +73,19 @@ VirtioNetGetFeatures (
   // Initialization Sequence), but don't complete setting it up.\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
     return Status;\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 YieldDevice;\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 YieldDevice;\r
   }\r
@@ -94,7 +93,7 @@ VirtioNetGetFeatures (
   //\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 YieldDevice;\r
   }\r
@@ -106,16 +105,16 @@ VirtioNetGetFeatures (
     Status = EFI_UNSUPPORTED;\r
     goto YieldDevice;\r
   }\r
-  Status = Dev->PciIo->Io.Read (Dev->PciIo,           // PciIo\r
-                            EfiPciIoWidthUint8,       // Width\r
-                            PCI_BAR_IDX0,             // BarIndex\r
-                            OFFSET_OF_VNET (VhdrMac), // Offset\r
-                            SIZE_OF_VNET (VhdrMac),   // Count\r
-                            MacAddress                // Buffer\r
+  for (MacIdx = 0; MacIdx < SIZE_OF_VNET (Mac); ++MacIdx) {\r
+    Status = Dev->VirtIo->ReadDevice (Dev->VirtIo,\r
+                            OFFSET_OF_VNET (Mac) + MacIdx, // Offset\r
+                            1,                             // FieldSize\r
+                            1,                             // BufferSize\r
+                            &MacAddress->Addr[MacIdx]      // Buffer\r
                             );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    goto YieldDevice;\r
+    if (EFI_ERROR (Status)) {\r
+      goto YieldDevice;\r
+    }\r
   }\r
 \r
   //\r
@@ -126,15 +125,15 @@ VirtioNetGetFeatures (
   }\r
   else {\r
     *MediaPresentSupported = TRUE;\r
-    Status = VIRTIO_CFG_READ (Dev, VhdrLinkStatus, &LinkStatus);\r
+    Status = VIRTIO_CFG_READ (Dev, LinkStatus, &LinkStatus);\r
     if (EFI_ERROR (Status)) {\r
       goto YieldDevice;\r
     }\r
-    *MediaPresent = !!(LinkStatus & VIRTIO_NET_S_LINK_UP);\r
+    *MediaPresent = (BOOLEAN) ((LinkStatus & VIRTIO_NET_S_LINK_UP) != 0);\r
   }\r
 \r
 YieldDevice:\r
-  VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus,\r
+  Dev->VirtIo->SetDeviceStatus (Dev->VirtIo,\r
     EFI_ERROR (Status) ? VSTAT_FAILED : 0);\r
 \r
   return Status;\r
@@ -207,9 +206,9 @@ VirtioNetSnpPopulate (
   Dev->Snp.Mode           = &Dev->Snm;\r
 \r
   Dev->Snm.State                 = EfiSimpleNetworkStopped;\r
-  Dev->Snm.HwAddressSize         = SIZE_OF_VNET (VhdrMac);\r
-  Dev->Snm.MediaHeaderSize       = SIZE_OF_VNET (VhdrMac) + // dst MAC\r
-                                   SIZE_OF_VNET (VhdrMac) + // src MAC\r
+  Dev->Snm.HwAddressSize         = SIZE_OF_VNET (Mac);\r
+  Dev->Snm.MediaHeaderSize       = SIZE_OF_VNET (Mac) + // dst MAC\r
+                                   SIZE_OF_VNET (Mac) + // src MAC\r
                                    2;                       // Ethertype\r
   Dev->Snm.MaxPacketSize         = 1500;\r
   Dev->Snm.NvRamSize             = 0;\r
@@ -222,7 +221,7 @@ VirtioNetSnpPopulate (
   Dev->Snm.MacAddressChangeable  = FALSE;\r
   Dev->Snm.MultipleTxSupported   = TRUE;\r
 \r
-  ASSERT (SIZE_OF_VNET (VhdrMac) <= sizeof (EFI_MAC_ADDRESS));\r
+  ASSERT (SIZE_OF_VNET (Mac) <= sizeof (EFI_MAC_ADDRESS));\r
 \r
   Status = VirtioNetGetFeatures (Dev, &Dev->Snm.CurrentAddress,\r
              &Dev->Snm.MediaPresentSupported, &Dev->Snm.MediaPresent);\r
@@ -230,8 +229,8 @@ VirtioNetSnpPopulate (
     goto CloseWaitForPacket;\r
   }\r
   CopyMem (&Dev->Snm.PermanentAddress, &Dev->Snm.CurrentAddress,\r
-    SIZE_OF_VNET (VhdrMac));\r
-  SetMem (&Dev->Snm.BroadcastAddress, SIZE_OF_VNET (VhdrMac), 0xFF);\r
+    SIZE_OF_VNET (Mac));\r
+  SetMem (&Dev->Snm.BroadcastAddress, SIZE_OF_VNET (Mac), 0xFF);\r
 \r
   //\r
   // VirtioNetExitBoot() is queued by ExitBootServices(); its purpose is to\r
@@ -348,31 +347,36 @@ VirtioNetDriverBindingSupported (
   )\r
 {\r
   EFI_STATUS          Status;\r
-  EFI_PCI_IO_PROTOCOL *PciIo;\r
-  PCI_TYPE00          Pci;\r
-\r
-  Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
-                  (VOID **)&PciIo, This->DriverBindingHandle, DeviceHandle,\r
-                  EFI_OPEN_PROTOCOL_BY_DRIVER);\r
+  VIRTIO_DEVICE_PROTOCOL *VirtIo;\r
+\r
+  //\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
+                  &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 VirtIo access to\r
+                                              // the device; to be released\r
+                  );\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
-  Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0,\r
-                        sizeof Pci / sizeof (UINT32), &Pci);\r
+  if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_NETWORK_CARD) {\r
+    Status = EFI_UNSUPPORTED;\r
+  }\r
 \r
   //\r
-  // virtio-0.9.5, 2.1 PCI Discovery:\r
-  // the network device has Subsystem Device ID 1\r
+  // We needed VirtIo access only transitorily, to see whether we support the\r
+  // device or not.\r
   //\r
-  if (Status == EFI_SUCCESS) {\r
-    Status = (Pci.Hdr.VendorId == 0x1AF4 &&\r
-              Pci.Hdr.DeviceId >= 0x1000 && Pci.Hdr.DeviceId <= 0x103F &&\r
-              Pci.Hdr.RevisionID == 0x00 &&\r
-              Pci.Device.SubsystemID == VIRTIO_SUBSYSTEM_NETWORK_CARD) ? EFI_SUCCESS : EFI_UNSUPPORTED;\r
-  }\r
-\r
-  gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
+  gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
          This->DriverBindingHandle, DeviceHandle);\r
   return Status;\r
 }\r
@@ -438,7 +442,7 @@ VirtioNetDriverBindingStart (
   VNET_DEV                 *Dev;\r
   EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
   MAC_ADDR_DEVICE_PATH     MacNode;\r
-  VOID                     *ChildPciIo;\r
+  VOID                     *ChildVirtIo;\r
 \r
   //\r
   // allocate space for the driver instance\r
@@ -449,43 +453,24 @@ VirtioNetDriverBindingStart (
   }\r
   Dev->Signature = VNET_SIG;\r
 \r
-  //\r
-  // get PCI access to the device and keep it open\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 FreeVirtioNet;\r
   }\r
 \r
-  //\r
-  // save original PCI attributes and enable IO space access\r
-  //\r
-  Status = Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationGet,\r
-                         0, &Dev->OrigPciAttributes);\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
   // now we can run a basic one-shot virtio-net initialization required to\r
   // retrieve the MAC address\r
   //\r
   Status = VirtioNetSnpPopulate (Dev);\r
   if (EFI_ERROR (Status)) {\r
-    goto RestorePciAttributes;\r
+    goto CloseVirtIo;\r
   }\r
 \r
   //\r
-  // get the device path of the virtio-net PCI device -- one-shot open\r
+  // get the device path of the virtio-net device -- one-shot open\r
   //\r
   Status = gBS->OpenProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid,\r
                   (VOID **)&DevicePath, This->DriverBindingHandle,\r
@@ -523,11 +508,11 @@ VirtioNetDriverBindingStart (
   }\r
 \r
   //\r
-  // make a note that we keep this device open with PciIo for the sake of this\r
+  // make a note that we keep this device open with VirtIo for the sake of this\r
   // child\r
   //\r
-  Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
-                  &ChildPciIo, This->DriverBindingHandle,\r
+  Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
+                  &ChildVirtIo, This->DriverBindingHandle,\r
                   Dev->MacHandle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);\r
   if (EFI_ERROR (Status)) {\r
     goto UninstallMultiple;\r
@@ -547,12 +532,8 @@ FreeMacDevicePath:
 Evacuate:\r
   VirtioNetSnpEvacuate (Dev);\r
 \r
-RestorePciAttributes:\r
-  Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet,\r
-                Dev->OrigPciAttributes, NULL);\r
-\r
-ClosePciIo:\r
-  gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
+CloseVirtIo:\r
+  gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
          This->DriverBindingHandle, DeviceHandle);\r
 \r
 FreeVirtioNet:\r
@@ -637,7 +618,7 @@ VirtioNetDriverBindingStop (
       Status = EFI_DEVICE_ERROR;\r
     }\r
     else {\r
-      gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
+      gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
              This->DriverBindingHandle, Dev->MacHandle);\r
       gBS->UninstallMultipleProtocolInterfaces (Dev->MacHandle,\r
              &gEfiDevicePathProtocolGuid,    Dev->MacDevicePath,\r
@@ -645,8 +626,6 @@ VirtioNetDriverBindingStop (
              NULL);\r
       FreePool (Dev->MacDevicePath);\r
       VirtioNetSnpEvacuate (Dev);\r
-      Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet,\r
-                    Dev->OrigPciAttributes, NULL);\r
       FreePool (Dev);\r
     }\r
 \r
@@ -657,7 +636,7 @@ VirtioNetDriverBindingStop (
   //\r
   // release remaining resources, tied directly to the parent handle\r
   //\r
-  gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
+  gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
          This->DriverBindingHandle, DeviceHandle);\r
 \r
   return EFI_SUCCESS;\r