virtio: refactor pci device code

Type: refactor

Change-Id: I7342178f9ab9adb99b91a4f984bc22bef2ce8021
Signed-off-by: Mohsin Kazmi <sykazmi@cisco.com>
diff --git a/src/vnet/devices/virtio/virtio_pci_legacy.c b/src/vnet/devices/virtio/virtio_pci_legacy.c
new file mode 100644
index 0000000..f70776d
--- /dev/null
+++ b/src/vnet/devices/virtio/virtio_pci_legacy.c
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2018 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <vlib/vlib.h>
+#include <vlib/pci/pci.h>
+#include <vnet/ethernet/ethernet.h>
+#include <vnet/ip/ip4_packet.h>
+#include <vnet/ip/ip6_packet.h>
+#include <vnet/devices/virtio/virtio.h>
+#include <vnet/devices/virtio/virtio_pci_legacy.h>
+#include <vnet/devices/virtio/pci.h>
+
+#define PCI_CONFIG_SIZE(vif) ((vif->msix_enabled == VIRTIO_MSIX_ENABLED) ? \
+  24 : 20)
+
+static void
+virtio_pci_legacy_read_config (vlib_main_t * vm, virtio_if_t * vif, void *dst,
+			       int len, u32 addr)
+{
+  u32 size = 0;
+  vlib_pci_dev_handle_t h = vif->pci_dev_handle;
+
+  while (len > 0)
+    {
+      if (len >= 4)
+	{
+	  size = 4;
+	  vlib_pci_read_io_u32 (vm, h, PCI_CONFIG_SIZE (vif) + addr, dst);
+	}
+      else if (len >= 2)
+	{
+	  size = 2;
+	  vlib_pci_read_io_u16 (vm, h, PCI_CONFIG_SIZE (vif) + addr, dst);
+	}
+      else
+	{
+	  size = 1;
+	  vlib_pci_read_io_u8 (vm, h, PCI_CONFIG_SIZE (vif) + addr, dst);
+	}
+      dst = (u8 *) dst + size;
+      addr += size;
+      len -= size;
+    }
+}
+
+static void
+virtio_pci_legacy_write_config (vlib_main_t * vm, virtio_if_t * vif,
+				void *src, int len, u32 addr)
+{
+  u32 size = 0;
+  vlib_pci_dev_handle_t h = vif->pci_dev_handle;
+
+  while (len > 0)
+    {
+      if (len >= 4)
+	{
+	  size = 4;
+	  vlib_pci_write_io_u32 (vm, h, PCI_CONFIG_SIZE (vif) + addr, src);
+	}
+      else if (len >= 2)
+	{
+	  size = 2;
+	  vlib_pci_write_io_u16 (vm, h, PCI_CONFIG_SIZE (vif) + addr, src);
+	}
+      else
+	{
+	  size = 1;
+	  vlib_pci_write_io_u8 (vm, h, PCI_CONFIG_SIZE (vif) + addr, src);
+	}
+      src = (u8 *) src + size;
+      addr += size;
+      len -= size;
+    }
+}
+
+static u64
+virtio_pci_legacy_get_host_features (vlib_main_t * vm, virtio_if_t * vif)
+{
+  u32 host_features;
+  vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_HOST_FEATURES,
+			&host_features);
+  return host_features;
+}
+
+static u64
+virtio_pci_legacy_get_guest_features (vlib_main_t * vm, virtio_if_t * vif)
+{
+  u32 guest_features = 0;
+  vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_GUEST_FEATURES,
+			&guest_features);
+  vif->features = guest_features;
+  return guest_features;
+}
+
+static void
+virtio_pci_legacy_set_guest_features (vlib_main_t * vm, virtio_if_t * vif,
+				      u64 guest_features)
+{
+  if ((guest_features >> 32) != 0)
+    {
+      clib_warning ("only 32 bit features are allowed for legacy virtio!");
+    }
+  u32 features = 0;
+  vlib_pci_write_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_GUEST_FEATURES,
+			 (u32 *) & guest_features);
+  vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_GUEST_FEATURES,
+			&features);
+  if (features != (u32) guest_features)
+    {
+      clib_warning ("legacy set guest features failed!");
+    }
+}
+
+static u8
+virtio_pci_legacy_get_status (vlib_main_t * vm, virtio_if_t * vif)
+{
+  u8 status = 0;
+  vlib_pci_read_io_u8 (vm, vif->pci_dev_handle, VIRTIO_PCI_STATUS, &status);
+  return status;
+}
+
+static void
+virtio_pci_legacy_set_status (vlib_main_t * vm, virtio_if_t * vif, u8 status)
+{
+  if (status != VIRTIO_CONFIG_STATUS_RESET)
+    status |= virtio_pci_legacy_get_status (vm, vif);
+  vlib_pci_write_io_u8 (vm, vif->pci_dev_handle, VIRTIO_PCI_STATUS, &status);
+}
+
+static u8
+virtio_pci_legacy_reset (vlib_main_t * vm, virtio_if_t * vif)
+{
+  virtio_pci_legacy_set_status (vm, vif, VIRTIO_CONFIG_STATUS_RESET);
+  return virtio_pci_legacy_get_status (vm, vif);
+}
+
+static u8
+virtio_pci_legacy_get_isr (vlib_main_t * vm, virtio_if_t * vif)
+{
+  u8 isr = 0;
+  vlib_pci_read_io_u8 (vm, vif->pci_dev_handle, VIRTIO_PCI_ISR, &isr);
+  return isr;
+}
+
+static u16
+virtio_pci_legacy_get_queue_num (vlib_main_t * vm, virtio_if_t * vif,
+				 u16 queue_id)
+{
+  u16 queue_num = 0;
+  vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_SEL,
+			 &queue_id);
+  vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_NUM,
+			&queue_num);
+  return queue_num;
+}
+
+static void
+virtio_pci_legacy_set_queue_num (vlib_main_t * vm, virtio_if_t * vif,
+				 u16 queue_id, u16 queue_size)
+{
+  /* do nothing */
+}
+
+static u8
+virtio_pci_legacy_setup_queue (vlib_main_t * vm, virtio_if_t * vif,
+			       u16 queue_id, void *p)
+{
+  u64 addr = vlib_physmem_get_pa (vm, p) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
+  u32 addr2 = 0;
+  vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_SEL,
+			 &queue_id);
+  vlib_pci_write_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_PFN,
+			 (u32 *) & addr);
+  vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_PFN,
+			&addr2);
+  if ((u32) addr == addr2)
+    return 0;
+
+  clib_warning ("legacy queue setup failed!");
+  return 1;
+}
+
+static void
+virtio_pci_legacy_del_queue (vlib_main_t * vm, virtio_if_t * vif,
+			     u16 queue_id)
+{
+  u32 src = 0;
+  vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_SEL,
+			 &queue_id);
+  vlib_pci_write_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_PFN, &src);
+}
+
+inline void
+virtio_pci_legacy_notify_queue (vlib_main_t * vm, virtio_if_t * vif,
+				u16 queue_id)
+{
+  vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_NOTIFY,
+			 &queue_id);
+}
+
+/* Enable one vector (0) for Link State Intrerrupt */
+static u16
+virtio_pci_legacy_set_config_irq (vlib_main_t * vm, virtio_if_t * vif,
+				  u16 vec)
+{
+  vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_MSI_CONFIG_VECTOR,
+			 &vec);
+  vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_MSI_CONFIG_VECTOR,
+			&vec);
+  return vec;
+}
+
+static u16
+virtio_pci_legacy_set_queue_irq (vlib_main_t * vm, virtio_if_t * vif, u16 vec,
+				 u16 queue_id)
+{
+  vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_SEL,
+			 &queue_id);
+  vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_MSI_QUEUE_VECTOR,
+			 &vec);
+  vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_MSI_QUEUE_VECTOR,
+			&vec);
+  return vec;
+}
+
+static void
+virtio_pci_legacy_get_mac (vlib_main_t * vm, virtio_if_t * vif)
+{
+  virtio_pci_legacy_read_config (vm, vif, vif->mac_addr,
+				 sizeof (vif->mac_addr), 0);
+}
+
+static void
+virtio_pci_legacy_set_mac (vlib_main_t * vm, virtio_if_t * vif)
+{
+  virtio_pci_legacy_write_config (vm, vif, vif->mac_addr,
+				  sizeof (vif->mac_addr), 0);
+}
+
+static u16
+virtio_pci_legacy_get_device_status (vlib_main_t * vm, virtio_if_t * vif)
+{
+  u16 status = 0;
+  virtio_pci_legacy_read_config (vm, vif, &status,
+				 sizeof (status),
+				 STRUCT_OFFSET_OF
+				 (virtio_net_config_t, status));
+  return status;
+}
+
+static u16
+virtio_pci_legacy_get_max_queue_pairs (vlib_main_t * vm, virtio_if_t * vif)
+{
+  virtio_net_config_t config;
+  virtio_pci_legacy_read_config (vm, vif, &config.max_virtqueue_pairs,
+				 sizeof (config.max_virtqueue_pairs),
+				 STRUCT_OFFSET_OF
+				 (virtio_net_config_t, max_virtqueue_pairs));
+  return config.max_virtqueue_pairs;
+}
+
+static u16
+virtio_pci_legacy_get_mtu (vlib_main_t * vm, virtio_if_t * vif)
+{
+  virtio_net_config_t config;
+  virtio_pci_legacy_read_config (vm, vif, &config.mtu,
+				 sizeof (config.mtu),
+				 STRUCT_OFFSET_OF (virtio_net_config_t, mtu));
+  return config.mtu;
+}
+
+
+static void
+virtio_pci_legacy_device_debug_config_space (vlib_main_t * vm,
+					     virtio_if_t * vif)
+{
+  u32 data_u32;
+  u16 data_u16;
+  u8 data_u8;
+  vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_HOST_FEATURES,
+			&data_u32);
+  vlib_cli_output (vm, "remote features 0x%lx", data_u32);
+  vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_GUEST_FEATURES,
+			&data_u32);
+  vlib_cli_output (vm, "guest features 0x%lx", data_u32);
+  vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_PFN,
+			&data_u32);
+  vlib_cli_output (vm, "queue address 0x%lx", data_u32);
+  vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_NUM,
+			&data_u16);
+  vlib_cli_output (vm, "queue size 0x%x", data_u16);
+  vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_SEL,
+			&data_u16);
+  vlib_cli_output (vm, "queue select 0x%x", data_u16);
+  vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_NOTIFY,
+			&data_u16);
+  vlib_cli_output (vm, "queue notify 0x%x", data_u16);
+  vlib_pci_read_io_u8 (vm, vif->pci_dev_handle, VIRTIO_PCI_STATUS, &data_u8);
+  vlib_cli_output (vm, "status 0x%x", data_u8);
+  vlib_pci_read_io_u8 (vm, vif->pci_dev_handle, VIRTIO_PCI_ISR, &data_u8);
+  vlib_cli_output (vm, "isr 0x%x", data_u8);
+
+  if (vif->msix_enabled == VIRTIO_MSIX_ENABLED)
+    {
+      vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_MSI_CONFIG_VECTOR,
+			    &data_u16);
+      vlib_cli_output (vm, "config vector 0x%x", data_u16);
+      u16 queue_id = 0;
+      vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_SEL,
+			     &queue_id);
+      vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_MSI_QUEUE_VECTOR,
+			    &data_u16);
+      vlib_cli_output (vm, "queue vector for queue (0) 0x%x", data_u16);
+    }
+
+  u8 mac[6];
+  virtio_pci_legacy_read_config (vm, vif, mac, sizeof (mac), 0);
+  vlib_cli_output (vm, "mac %U", format_ethernet_address, mac);
+  virtio_pci_legacy_read_config (vm, vif, &data_u16, sizeof (u16),	/* offset to status */
+				 6);
+  vlib_cli_output (vm, "link up/down status 0x%x", data_u16);
+  virtio_pci_legacy_read_config (vm, vif, &data_u16, sizeof (u16),
+				 /* offset to max_virtqueue */ 8);
+  vlib_cli_output (vm, "num of virtqueue 0x%x", data_u16);
+  virtio_pci_legacy_read_config (vm, vif, &data_u16, sizeof (u16),	/* offset to mtu */
+				 10);
+  vlib_cli_output (vm, "mtu 0x%x", data_u16);
+
+  u32 i = PCI_CONFIG_SIZE (vif) + 12, a = 4;
+  i += a;
+  i &= ~a;
+  for (; i < 64; i += 4)
+    {
+      u32 data = 0;
+      vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, i, &data);
+      vlib_cli_output (vm, "0x%lx", data);
+    }
+}
+
+const virtio_pci_func_t virtio_pci_legacy_func = {
+  .read_config = virtio_pci_legacy_read_config,
+  .write_config = virtio_pci_legacy_write_config,
+  .get_device_features = virtio_pci_legacy_get_host_features,
+  .get_driver_features = virtio_pci_legacy_get_guest_features,
+  .set_driver_features = virtio_pci_legacy_set_guest_features,
+  .get_status = virtio_pci_legacy_get_status,
+  .set_status = virtio_pci_legacy_set_status,
+  .device_reset = virtio_pci_legacy_reset,
+  .get_isr = virtio_pci_legacy_get_isr,
+  .get_queue_size = virtio_pci_legacy_get_queue_num,
+  .set_queue_size = virtio_pci_legacy_set_queue_num,
+  .setup_queue = virtio_pci_legacy_setup_queue,
+  .del_queue = virtio_pci_legacy_del_queue,
+  .notify_queue = virtio_pci_legacy_notify_queue,
+  .set_config_irq = virtio_pci_legacy_set_config_irq,
+  .set_queue_irq = virtio_pci_legacy_set_queue_irq,
+  .get_mac = virtio_pci_legacy_get_mac,
+  .set_mac = virtio_pci_legacy_set_mac,
+  .get_device_status = virtio_pci_legacy_get_device_status,
+  .get_max_queue_pairs = virtio_pci_legacy_get_max_queue_pairs,
+  .get_mtu = virtio_pci_legacy_get_mtu,
+  .device_debug_config_space = virtio_pci_legacy_device_debug_config_space,
+};
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */