if (vq) {
hw = vq->hw;
- /* Select and deactivate the queue */
- VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_SEL, vq->vq_queue_index);
- VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_QUEUE_PFN, 0);
+ hw->vtpci_ops->del_queue(hw, vq);
rte_free(vq->sw_ring);
rte_free(vq);
struct virtio_hw *hw = dev->data->dev_private;
struct virtqueue *vq = NULL;
- /* Write the virtqueue index to the Queue Select Field */
- VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_SEL, vtpci_queue_idx);
- PMD_INIT_LOG(DEBUG, "selecting queue: %u", vtpci_queue_idx);
+ PMD_INIT_LOG(DEBUG, "setting up queue: %u", vtpci_queue_idx);
/*
* Read the virtqueue size from the Queue Size field
* Always power of 2 and if 0 virtqueue does not exist
*/
- vq_size = VIRTIO_READ_REG_2(hw, VIRTIO_PCI_QUEUE_NUM);
+ vq_size = hw->vtpci_ops->get_queue_num(hw, vtpci_queue_idx);
PMD_INIT_LOG(DEBUG, "vq_size: %u nb_desc:%u", vq_size, nb_desc);
if (vq_size == 0) {
PMD_INIT_LOG(ERR, "%s: virtqueue does not exist", __func__);
memset(vq->virtio_net_hdr_mz->addr, 0, PAGE_SIZE);
}
- /*
- * Set guest physical address of the virtqueue
- * in VIRTIO_PCI_QUEUE_PFN config register of device
- */
- VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_QUEUE_PFN,
- mz->phys_addr >> VIRTIO_PCI_QUEUE_ADDR_SHIFT);
+ hw->vtpci_ops->setup_queue(hw, vq);
+
*pvq = vq;
return 0;
}
hw->guest_features);
/* Read device(host) feature bits */
- host_features = VIRTIO_READ_REG_4(hw, VIRTIO_PCI_HOST_FEATURES);
+ host_features = hw->vtpci_ops->get_features(hw);
PMD_INIT_LOG(DEBUG, "host_features before negotiate = %x",
host_features);
pci_dev = eth_dev->pci_dev;
+ vtpci_init(pci_dev, hw);
+
if (virtio_resource_init(pci_dev) < 0)
return -1;
#include "virtio_pci.h"
#include "virtio_logs.h"
+#include "virtqueue.h"
-static uint8_t vtpci_get_status(struct virtio_hw *);
-
-void
-vtpci_read_dev_config(struct virtio_hw *hw, size_t offset,
- void *dst, int length)
+static void
+legacy_read_dev_config(struct virtio_hw *hw, size_t offset,
+ void *dst, int length)
{
uint64_t off;
uint8_t *d;
}
}
-void
-vtpci_write_dev_config(struct virtio_hw *hw, size_t offset,
- void *src, int length)
+static void
+legacy_write_dev_config(struct virtio_hw *hw, size_t offset,
+ const void *src, int length)
{
uint64_t off;
- uint8_t *s;
+ const uint8_t *s;
int size;
off = VIRTIO_PCI_CONFIG(hw) + offset;
for (s = src; length > 0; s += size, off += size, length -= size) {
if (length >= 4) {
size = 4;
- VIRTIO_WRITE_REG_4(hw, off, *(uint32_t *)s);
+ VIRTIO_WRITE_REG_4(hw, off, *(const uint32_t *)s);
} else if (length >= 2) {
size = 2;
- VIRTIO_WRITE_REG_2(hw, off, *(uint16_t *)s);
+ VIRTIO_WRITE_REG_2(hw, off, *(const uint16_t *)s);
} else {
size = 1;
VIRTIO_WRITE_REG_1(hw, off, *s);
}
}
+static uint32_t
+legacy_get_features(struct virtio_hw *hw)
+{
+ return VIRTIO_READ_REG_4(hw, VIRTIO_PCI_HOST_FEATURES);
+}
+
+static void
+legacy_set_features(struct virtio_hw *hw, uint32_t features)
+{
+ VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_GUEST_FEATURES, features);
+}
+
+static uint8_t
+legacy_get_status(struct virtio_hw *hw)
+{
+ return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_STATUS);
+}
+
+static void
+legacy_set_status(struct virtio_hw *hw, uint8_t status)
+{
+ VIRTIO_WRITE_REG_1(hw, VIRTIO_PCI_STATUS, status);
+}
+
+static void
+legacy_reset(struct virtio_hw *hw)
+{
+ legacy_set_status(hw, VIRTIO_CONFIG_STATUS_RESET);
+}
+
+static uint8_t
+legacy_get_isr(struct virtio_hw *hw)
+{
+ return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_ISR);
+}
+
+/* Enable one vector (0) for Link State Intrerrupt */
+static uint16_t
+legacy_set_config_irq(struct virtio_hw *hw, uint16_t vec)
+{
+ VIRTIO_WRITE_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR, vec);
+ return VIRTIO_READ_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR);
+}
+
+static uint16_t
+legacy_get_queue_num(struct virtio_hw *hw, uint16_t queue_id)
+{
+ VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_SEL, queue_id);
+ return VIRTIO_READ_REG_2(hw, VIRTIO_PCI_QUEUE_NUM);
+}
+
+static void
+legacy_setup_queue(struct virtio_hw *hw, struct virtqueue *vq)
+{
+ VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_SEL, vq->vq_queue_index);
+
+ VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_QUEUE_PFN,
+ vq->mz->phys_addr >> VIRTIO_PCI_QUEUE_ADDR_SHIFT);
+}
+
+static void
+legacy_del_queue(struct virtio_hw *hw, struct virtqueue *vq)
+{
+ VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_SEL, vq->vq_queue_index);
+
+ VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_QUEUE_PFN, 0);
+}
+
+static void
+legacy_notify_queue(struct virtio_hw *hw, struct virtqueue *vq)
+{
+ VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_NOTIFY, vq->vq_queue_index);
+}
+
+
+static const struct virtio_pci_ops legacy_ops = {
+ .read_dev_cfg = legacy_read_dev_config,
+ .write_dev_cfg = legacy_write_dev_config,
+ .reset = legacy_reset,
+ .get_status = legacy_get_status,
+ .set_status = legacy_set_status,
+ .get_features = legacy_get_features,
+ .set_features = legacy_set_features,
+ .get_isr = legacy_get_isr,
+ .set_config_irq = legacy_set_config_irq,
+ .get_queue_num = legacy_get_queue_num,
+ .setup_queue = legacy_setup_queue,
+ .del_queue = legacy_del_queue,
+ .notify_queue = legacy_notify_queue,
+};
+
+
+void
+vtpci_read_dev_config(struct virtio_hw *hw, size_t offset,
+ void *dst, int length)
+{
+ hw->vtpci_ops->read_dev_cfg(hw, offset, dst, length);
+}
+
+void
+vtpci_write_dev_config(struct virtio_hw *hw, size_t offset,
+ const void *src, int length)
+{
+ hw->vtpci_ops->write_dev_cfg(hw, offset, src, length);
+}
+
uint32_t
vtpci_negotiate_features(struct virtio_hw *hw, uint32_t host_features)
{
uint32_t features;
+
/*
* Limit negotiated features to what the driver, virtqueue, and
* host all support.
*/
features = host_features & hw->guest_features;
+ hw->vtpci_ops->set_features(hw, features);
- VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_GUEST_FEATURES, features);
return features;
}
-
void
vtpci_reset(struct virtio_hw *hw)
{
- /*
- * Setting the status to RESET sets the host device to
- * the original, uninitialized state.
- */
- vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_RESET);
- vtpci_get_status(hw);
+ hw->vtpci_ops->set_status(hw, VIRTIO_CONFIG_STATUS_RESET);
+ /* flush status write */
+ hw->vtpci_ops->get_status(hw);
}
void
vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER_OK);
}
-static uint8_t
-vtpci_get_status(struct virtio_hw *hw)
-{
- return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_STATUS);
-}
-
void
vtpci_set_status(struct virtio_hw *hw, uint8_t status)
{
if (status != VIRTIO_CONFIG_STATUS_RESET)
- status = (uint8_t)(status | vtpci_get_status(hw));
+ status |= hw->vtpci_ops->get_status(hw);
- VIRTIO_WRITE_REG_1(hw, VIRTIO_PCI_STATUS, status);
+ hw->vtpci_ops->set_status(hw, status);
}
uint8_t
vtpci_isr(struct virtio_hw *hw)
{
-
- return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_ISR);
+ return hw->vtpci_ops->get_isr(hw);
}
uint16_t
vtpci_irq_config(struct virtio_hw *hw, uint16_t vec)
{
- VIRTIO_WRITE_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR, vec);
- return VIRTIO_READ_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR);
+ return hw->vtpci_ops->set_config_irq(hw, vec);
+}
+
+int
+vtpci_init(struct rte_pci_device *dev __rte_unused, struct virtio_hw *hw)
+{
+ hw->vtpci_ops = &legacy_ops;
+
+ return 0;
}
*/
#define VIRTIO_MAX_VIRTQUEUES 8
+struct virtio_hw;
+
+struct virtio_pci_ops {
+ void (*read_dev_cfg)(struct virtio_hw *hw, size_t offset,
+ void *dst, int len);
+ void (*write_dev_cfg)(struct virtio_hw *hw, size_t offset,
+ const void *src, int len);
+ void (*reset)(struct virtio_hw *hw);
+
+ uint8_t (*get_status)(struct virtio_hw *hw);
+ void (*set_status)(struct virtio_hw *hw, uint8_t status);
+
+ uint32_t (*get_features)(struct virtio_hw *hw);
+ void (*set_features)(struct virtio_hw *hw, uint32_t features);
+
+ uint8_t (*get_isr)(struct virtio_hw *hw);
+
+ uint16_t (*set_config_irq)(struct virtio_hw *hw, uint16_t vec);
+
+ uint16_t (*get_queue_num)(struct virtio_hw *hw, uint16_t queue_id);
+ void (*setup_queue)(struct virtio_hw *hw, struct virtqueue *vq);
+ void (*del_queue)(struct virtio_hw *hw, struct virtqueue *vq);
+ void (*notify_queue)(struct virtio_hw *hw, struct virtqueue *vq);
+};
+
struct virtio_hw {
struct virtqueue *cvq;
uint32_t io_base;
uint8_t use_msix;
uint8_t started;
uint8_t mac_addr[ETHER_ADDR_LEN];
+ const struct virtio_pci_ops *vtpci_ops;
};
/*
/*
* Function declaration from virtio_pci.c
*/
+int vtpci_init(struct rte_pci_device *, struct virtio_hw *);
void vtpci_reset(struct virtio_hw *);
void vtpci_reinit_complete(struct virtio_hw *);
uint32_t vtpci_negotiate_features(struct virtio_hw *, uint32_t);
-void vtpci_write_dev_config(struct virtio_hw *, size_t, void *, int);
+void vtpci_write_dev_config(struct virtio_hw *, size_t, const void *, int);
void vtpci_read_dev_config(struct virtio_hw *, size_t, void *, int);