aboutsummaryrefslogtreecommitdiffstats
path: root/vhost_user_gpio.c
diff options
context:
space:
mode:
Diffstat (limited to 'vhost_user_gpio.c')
-rw-r--r--vhost_user_gpio.c393
1 files changed, 0 insertions, 393 deletions
diff --git a/vhost_user_gpio.c b/vhost_user_gpio.c
deleted file mode 100644
index fd525fe..0000000
--- a/vhost_user_gpio.c
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * Based on vhost-user-gpio.c of QEMU project
- *
- * Copyright (c) 2022 Viresh Kumar <viresh.kumar@linaro.org>
- *
- * Copyright (c) 2023 Virtual Open Systems SAS.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <stdbool.h>
-#include <sys/param.h>
-#include <errno.h>
-
-/* Project header files */
-#include "vhost_user_gpio.h"
-
-#ifdef DEBUG
-#define DBG(...) printf("vhost-user-gpio: " __VA_ARGS__)
-#else
-#define DBG(...)
-#endif /* DEBUG */
-
-#define REALIZE_CONNECTION_RETRIES 3
-#define VHOST_NVQS 2
-
-static const int feature_bits[] = {
- VIRTIO_F_VERSION_1,
- VIRTIO_F_NOTIFY_ON_EMPTY,
- VIRTIO_RING_F_INDIRECT_DESC,
- VIRTIO_RING_F_EVENT_IDX,
- VIRTIO_GPIO_F_IRQ,
- VIRTIO_F_RING_RESET,
- VHOST_INVALID_FEATURE_BIT
-};
-
-static void vu_gpio_get_config(VirtIODevice *vdev, uint8_t *config)
-{
- VHostUserGPIO *gpio = dev->vdev->vhugpio;
-
- DBG("vu_gpio_get_config()\n");
- (void)vdev;
- memcpy(config, &gpio->config, sizeof(gpio->config));
-}
-
-static int vu_gpio_config_notifier(struct vhost_dev *dev)
-{
- VHostUserGPIO *gpio = dev->vdev->vhugpio;
-
- DBG("vu_gpio_config_notifier\n");
-
- memcpy(dev->vdev->config, &gpio->config, sizeof(gpio->config));
- virtio_notify_config(dev->vdev);
-
- return 0;
-}
-
-const VhostDevConfigOps gpio_ops = {
- .vhost_dev_config_notifier = vu_gpio_config_notifier,
-};
-
-static int vu_gpio_start(VirtIODevice *vdev)
-{
- VirtioBus *k = vdev->vbus;
- VHostUserGPIO *gpio = vdev->vhugpio;
- unsigned int i;
- int ret;
-
- DBG("vu_gpio_start()\n");
-
- if (!k->set_guest_notifiers) {
- DBG("binding does not support guest notifiers");
- return -ENOSYS;
- }
-
- ret = vhost_dev_enable_notifiers(gpio->vhost_dev, vdev);
- if (ret < 0) {
- DBG("Error enabling host notifiers: %d", ret);
- return ret;
- }
-
- ret = k->set_guest_notifiers(k->vdev, gpio->vhost_dev->nvqs, true);
- if (ret < 0) {
- DBG("Error binding guest notifier: %d", ret);
- goto out_with_err_host_notifiers;
- }
-
- vhost_ack_features(gpio->vhost_dev, feature_bits, vdev->guest_features);
-
- ret = vhost_dev_start(gpio->vhost_dev, vdev, true);
- if (ret < 0) {
- DBG("Error starting vhost-user-gpio: %d", ret);
- goto out_with_err_guest_notifiers;
- }
- gpio->started_vu = true;
-
- for (i = 0; i < gpio->vhost_dev->nvqs; i++) {
- vhost_virtqueue_mask(gpio->vhost_dev, vdev, i, false);
- }
-
- /*
- * TODO: check if we need the following is needed
- * ret = gpio->vhost_dev->vhost_ops->vhost_set_vring_enable(gpio->vhost_dev,
- * true);
- */
-
- return 0;
-
-out_with_err_guest_notifiers:
- k->set_guest_notifiers(k->vdev, gpio->vhost_dev->nvqs, false);
-out_with_err_host_notifiers:
- /*
- * TODO: implement the following functions:
- * vhost_dev_disable_notifiers(&gpio->vhost_dev, vdev);
- */
-
- return ret;
-}
-
-static void vu_gpio_stop(VirtIODevice *vdev)
-{
- DBG("vu_gpio_stop() not yet implemented\n");
- (void)vdev;
-}
-
-static void vu_gpio_set_status(VirtIODevice *vdev, uint8_t status)
-{
- VHostUserGPIO *gpio = vdev->vhugpio;
- bool should_start = virtio_device_started(vdev, status);
-
- DBG("vu_gpio_set_status()\n");
-
- if (!gpio->connected) {
- return;
- }
-
-printf("should_start: %d\n", should_start);
- if (gpio->vhost_dev->started) {
- return;
- }
-
- if (should_start) {
- if (vu_gpio_start(vdev)) {
- DBG("vu_gpio_start() failed\n");
- }
- } else {
- vu_gpio_stop(vdev);
- }
-}
-
-static uint64_t vu_gpio_get_features(VirtIODevice *vdev, uint64_t features)
-{
- VHostUserGPIO *gpio = vdev->vhugpio;
-
- DBG("vu_gpio_get_features()\n");
- return vhost_get_features(gpio->vhost_dev, feature_bits, features);
-}
-
-static void vu_gpio_handle_output(VirtIODevice *vdev, VirtQueue *vq)
-{
- /*
- * Not normally called; it's the daemon that handles the queue;
- * however virtio's cleanup path can call this.
- */
- DBG("vu_gpio_handle_output not yet implemented\n");
- (void)vdev;
- (void)vq;
-}
-
-static void vu_gpio_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask)
-{
- VHostUserGPIO *gpio = vdev->vhugpio;
-
- DBG("vu_gpio_guest_notifier_mask() not yet implemented\n");
-
- vhost_virtqueue_mask(gpio->vhost_dev, vdev, idx, mask);
-}
-
-static void do_vhost_user_cleanup(VirtIODevice *vdev, VHostUserGPIO *gpio)
-{
- DBG("do_vhost_user_cleanup() not yet implemented\n");
- (void)vdev;
- (void)gpio;
-}
-
-static int vu_gpio_connect(VirtIODevice *vdev)
-{
- VHostUserGPIO *gpio = vdev->vhugpio;
-
- DBG("vu_gpio_connect()\n");
-
- if (gpio->connected) {
- return 0;
- }
- gpio->connected = true;
-
- vhost_dev_set_config_notifier(gpio->vhost_dev, &gpio_ops);
- /*
- * TODO: Investigate if the following is needed
- * gpio->vhost_user.supports_config = true;
- */
-
- gpio->vhost_dev->nvqs = VHOST_NVQS;
- gpio->vhost_dev->vqs = gpio->vhost_vqs;
-
- vhost_dev_init(gpio->vhost_dev);
- /*
- * TODO: Add error handling
- * if (ret < 0) {
- * return ret;
- * }
- */
-
- /* restore vhost state */
- if (virtio_device_started(vdev, vdev->status)) {
- vu_gpio_start(vdev);
- }
-
- return 0;
-}
-
-static int vu_gpio_realize_connect(VHostUserGPIO *gpio)
-{
- int ret;
-
- DBG("vu_gpio_realize_connect()\n");
-
- ret = vu_gpio_connect(gpio->parent);
- if (ret < 0) {
- return ret;
- }
-
- ret = vhost_dev_get_config(gpio->vhost_dev, (uint8_t *)&gpio->config,
- sizeof(gpio->config));
-
- if (ret < 0) {
- DBG("vhost-user-gpio: get config failed\n");
- /*
- * TODO: Add cleanup function
- * vhost_dev_cleanup(vhost_dev);
- */
- return ret;
- }
-
- return 0;
-}
-
-static void vu_gpio_device_unrealize(VirtIODevice *vdev)
-{
- DBG("vu_gpio_device_unrealize() not yet implemented\n");
- (void)vdev;
-}
-
-static void print_config_gpio(uint8_t *config_data)
-{
- struct virtio_gpio_config *config =
- (struct virtio_gpio_config *)config_data;
-
- (void)config;
- DBG("ngpio: %hu\n", config->ngpio);
- DBG("gpio_names_size: %u\n", config->gpio_names_size);
-}
-
-static void vu_gpio_class_init(VirtIODevice *vdev)
-{
- DBG("vu_gpio_class_init()\n");
-
- vdev->vdev_class = (VirtioDeviceClass *)malloc(sizeof(VirtioDeviceClass));
- if (!vdev->vdev_class) {
- DBG("vdev_class memory allocation failed\n");
- return;
- }
- vdev->vdev_class->realize = vu_gpio_device_realize;
- vdev->vdev_class->unrealize = vu_gpio_device_unrealize;
- vdev->vdev_class->get_features = vu_gpio_get_features;
- vdev->vdev_class->get_config = vu_gpio_get_config;
- vdev->vdev_class->set_status = vu_gpio_set_status;
- vdev->vdev_class->guest_notifier_mask = vu_gpio_guest_notifier_mask;
-}
-
-void vu_gpio_init(VirtIODevice *vdev)
-{
- DBG("vu_gpio_init()\n");
-
- VHostUserGPIO *vhugpio = (VHostUserGPIO *)malloc(sizeof(VHostUserGPIO));
- if (!proxy) {
- DBG("proxy memory allocation failed\n");
- goto out;
- }
-
- vdev->vhugpio = vhugpio;
- vdev->nvqs = (int *)&dev->nvqs;
- vhugpio->parent = vdev;
- vhugpio->vhost_dev = dev;
-
- vu_gpio_class_init(vdev);
- virtio_loopback_bus_init(vdev->vbus);
-
-out:
- return;
-}
-
-/* TODO: Add queue_num, queue_size as parameters */
-void vu_gpio_device_realize(int queue_num, int queue_size)
-{
- int retries, ret;
-
- DBG("vu_gpio_device_realize()\n");
- (void)queue_num;
- (void)queue_size;
-
- /* This needs to be added */
- proxy = (VirtIOMMIOProxy *)malloc(sizeof(VirtIOMMIOProxy));
- if (!proxy) {
- DBG("proxy memory allocation failed\n");
- goto out_with_error;
- }
-
- *proxy = (VirtIOMMIOProxy) {
- .legacy = 1,
- };
-
- /* VIRTIO_ID_GPIO is 41, check virtio_ids.h in linux */
- virtio_dev_init(global_vdev, "virtio-gpio", 41,
- sizeof(struct virtio_gpio_config));
-
- vu_gpio_init(global_vdev);
- if (!global_vdev->vhugpio) {
- DBG("vhugpio memory allocation failed\n");
- goto out_with_proxy;
- }
-
- global_vdev->vhugpio->command_vq = virtio_add_queue(global_vdev, 64,
- vu_gpio_handle_output);
- global_vdev->vhugpio->interrupt_vq = virtio_add_queue(global_vdev, 64,
- vu_gpio_handle_output);
-
- global_vdev->vhugpio->vhost_vqs = (struct vhost_virtqueue *)
- malloc(sizeof(struct vhost_virtqueue *));
- if (!global_vdev->vhugpio->vhost_vqs) {
- DBG("vhost_vqs memory allocation failed\n");
- goto out_with_dev;
- }
-
- global_vdev->vhugpio->connected = false;
-
- retries = REALIZE_CONNECTION_RETRIES;
-
- do {
- ret = vu_gpio_realize_connect(global_vdev->vhugpio);
- } while (ret < 0 && retries--);
-
- if (ret < 0) {
- DBG("vu_gpio_realize_connect(): -EPROTO\n");
- do_vhost_user_cleanup(global_vdev, global_vdev->vhugpio);
- }
-
- print_config_gpio((uint8_t *)(&global_vdev->vhugpio->config));
- DBG("(realize completed)\n");
-
- return;
-
- /*
- * TODO: Fix the following considering also do_vhost_user_cleanup()
- *
- * out_with_cmd_vq:
- * free(global_vdev->vhugpio->command_vq);
- */
-out_with_dev:
- free(global_vdev->vhugpio);
-out_with_proxy:
- free(proxy);
-out_with_error:
- DBG("Realize funciton return error\n");
- return;
-}