Delete virtio mini driver

This commit is contained in:
zeroway
2023-08-28 20:55:13 +08:00
parent c55b83c97d
commit 833f80476b
4 changed files with 0 additions and 667 deletions

View File

@ -1,364 +0,0 @@
From 011c832118d82f4ef3d6f0166e20acc17a9bd58f Mon Sep 17 00:00:00 2001
From: zeroway <M_O_Bz@163.com>
Date: Fri, 14 Jul 2023 19:36:54 +0800
Subject: [PATCH] Add virtio mini device
---
hw/virtio/meson.build | 2 +
hw/virtio/virtio-mini-pci.c | 62 ++++++++
hw/virtio/virtio-mini.c | 154 +++++++++++++++++++
hw/virtio/virtio.c | 1 +
include/hw/pci/pci.h | 2 +
include/hw/virtio/virtio-mini.h | 18 +++
include/standard-headers/linux/virtio_ids.h | 5 +-
include/standard-headers/linux/virtio_mini.h | 7 +
softmmu/qdev-monitor.c | 3 +
9 files changed, 253 insertions(+), 1 deletion(-)
create mode 100644 hw/virtio/virtio-mini-pci.c
create mode 100644 hw/virtio/virtio-mini.c
create mode 100644 include/hw/virtio/virtio-mini.h
create mode 100644 include/standard-headers/linux/virtio_mini.h
diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
index 7e8877fd64..29e0442cfb 100644
--- a/hw/virtio/meson.build
+++ b/hw/virtio/meson.build
@@ -1,6 +1,8 @@
softmmu_virtio_ss = ss.source_set()
softmmu_virtio_ss.add(files('virtio-bus.c'))
softmmu_virtio_ss.add(when: 'CONFIG_VIRTIO_PCI', if_true: files('virtio-pci.c'))
+softmmu_virtio_ss.add(when: 'CONFIG_VIRTIO_PCI', if_true: files('virtio-mini.c'))
+softmmu_virtio_ss.add(when: 'CONFIG_VIRTIO_PCI', if_true: files('virtio-mini-pci.c'))
softmmu_virtio_ss.add(when: 'CONFIG_VIRTIO_MMIO', if_true: files('virtio-mmio.c'))
virtio_ss = ss.source_set()
diff --git a/hw/virtio/virtio-mini-pci.c b/hw/virtio/virtio-mini-pci.c
new file mode 100644
index 0000000000..6e82eb038f
--- /dev/null
+++ b/hw/virtio/virtio-mini-pci.c
@@ -0,0 +1,62 @@
+#include "qemu/osdep.h"
+#include "hw/hw.h"
+#include "hw/qdev-properties.h"
+#include "hw/virtio/virtio-pci.h"
+#include "hw/virtio/virtio-mini.h"
+#include "qom/object.h"
+
+typedef struct VirtIOMiniPCI VirtIOMiniPCI;
+
+#define TYPE_VIRTIO_MINI_PCI "virtio-mini-pci-base"
+#define VIRTIO_MINI_PCI(obj) \
+ OBJECT_CHECK(VirtIOMiniPCI, (obj), TYPE_VIRTIO_MINI_PCI)
+
+struct VirtIOMiniPCI {
+ VirtIOPCIProxy parent_obj;
+ VirtIOMini vdev;
+};
+
+static void virtio_mini_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) {
+ VirtIOMiniPCI *vmini = VIRTIO_MINI_PCI(vpci_dev);
+ DeviceState *vdev = DEVICE(&vmini->vdev);
+ Error *err = NULL;
+
+ qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &err);
+ object_property_set_bool(OBJECT(vdev), "realized", true, &err);
+}
+
+static void virtio_mini_pci_class_init(ObjectClass *klass, void *data) {
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
+ PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
+
+ k->realize = virtio_mini_pci_realize;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+
+ pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+ pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_MINI;
+ pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
+ pcidev_k->class_id = PCI_CLASS_OTHERS;
+}
+
+static void virtio_mini_initfn(Object *obj) {
+ VirtIOMiniPCI *dev = VIRTIO_MINI_PCI(obj);
+ virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
+ TYPE_VIRTIO_MINI);
+}
+
+static const VirtioPCIDeviceTypeInfo virtio_mini_pci_info = {
+ .base_name = TYPE_VIRTIO_MINI_PCI,
+ .generic_name = "virtio-mini-pci",
+ .transitional_name = "virtio-mini-pci-transitional",
+ .non_transitional_name = "virtio-mini-pci-non-transitional",
+ .instance_size = sizeof(VirtIOMiniPCI),
+ .instance_init = virtio_mini_initfn,
+ .class_init = virtio_mini_pci_class_init
+};
+
+static void virtio_mini_pci_register(void)
+{
+ virtio_pci_types_register(&virtio_mini_pci_info);
+}
+type_init(virtio_mini_pci_register);
diff --git a/hw/virtio/virtio-mini.c b/hw/virtio/virtio-mini.c
new file mode 100644
index 0000000000..d12b096ff1
--- /dev/null
+++ b/hw/virtio/virtio-mini.c
@@ -0,0 +1,154 @@
+#include "qemu/osdep.h"
+#include "hw/hw.h"
+#include "hw/virtio/virtio.h"
+#include "hw/virtio/virtio-mini.h"
+#include "qemu/iov.h"
+#include "qemu/error-report.h"
+#include "standard-headers/linux/virtio_ids.h"
+#include "qemu/error-report.h"
+#include "sysemu/runstate.h"
+
+static uint64_t virtio_mini_get_features(VirtIODevice *vdev, uint64_t f, Error **errp)
+{
+ return f;
+}
+
+static void virtio_mini_set_status(VirtIODevice *vdev, uint8_t status)
+{
+ if (!vdev->vm_running) {
+ return;
+ }
+ vdev->status = status;
+}
+
+/*
+ * callback for receiving virtqueue (outbuf on guest)
+ * Guest sendout will trigger this callback
+ *
+ * echo hello > /proc/virtio-mini-0
+ */
+static void virtio_mini_handle_outbuf(VirtIODevice *vdev, VirtQueue *vq)
+{
+ /* acllocation of VirtQueueElement happens in virtqueue_pop call */
+ VirtIOMini *vmini = VIRTIO_MINI(vdev);
+ VirtQueueElement *vqe;
+
+ while (!virtio_queue_ready(vq)) {
+ return;
+ }
+ if (!runstate_check(RUN_STATE_RUNNING)) {
+ return;
+ }
+
+ vqe = virtqueue_pop(vq, sizeof(VirtQueueElement));
+ iov_to_buf(vqe->out_sg, vqe->out_num, 0, vmini->rcv_bufs, vqe->out_sg->iov_len);
+ printf("GuestWrite: %s\n", vmini->rcv_bufs);
+ virtqueue_push(vq, vqe, 0);
+ virtio_notify(vdev, vq);
+ g_free(vqe);
+
+ return;
+}
+
+/*
+ * callback for transmitting virtqueue (inbuf on guest)
+ * Guest receive data will trigger this callback
+ *
+ * cat /proc/virtio-mini-0
+ */
+static void virtio_mini_handle_inbuf(VirtIODevice *vdev, VirtQueue *vq)
+{
+ VirtIOMini *vmini = VIRTIO_MINI(vdev);
+ VirtQueueElement *vqe;
+
+ while (!virtio_queue_ready(vq)) {
+ return;
+ }
+ if (!runstate_check(RUN_STATE_RUNNING)) {
+ return;
+ }
+ vqe = virtqueue_pop(vq, sizeof(VirtQueueElement));
+
+ iov_from_buf(vqe->in_sg, vqe->in_num, 0, vmini->rcv_bufs, vqe->in_sg->iov_len);
+ printf("GuestReceive: %s\n", vmini->rcv_bufs);
+ virtqueue_push(vq, vqe, vqe->in_sg->iov_len);
+ virtio_notify(vdev, vq);
+ g_free(vqe);
+
+ return;
+}
+
+static void virtio_mini_device_realize(DeviceState *dev, Error **errp)
+{
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VirtIOMini *vmin = VIRTIO_MINI(dev);
+ virtio_init(vdev, VIRTIO_ID_MINI, 0);
+
+ vmin->vq_rx = virtio_add_queue(vdev, 64, virtio_mini_handle_outbuf);
+ vmin->vq_tx = virtio_add_queue(vdev, 64, virtio_mini_handle_inbuf);
+}
+
+static void virtio_mini_device_unrealize(DeviceState *dev)
+{
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ virtio_cleanup(vdev);
+}
+
+static const VMStateDescription vmstate_virtio_mini = {
+ .name = "virtio-mini",
+ .minimum_version_id = 1,
+ .version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_VIRTIO_DEVICE,
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static int vmstate_virtio_mini_device_pre_save(void * opaque)
+{
+ return 0;
+}
+
+static int vmstate_virtio_mini_device_post_load(void * opaque, int version_id)
+{
+ return 0;
+}
+
+static const VMStateDescription vmstate_virtio_mini_device = {
+ .name = "virtio-mini-device",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .pre_save = vmstate_virtio_mini_device_pre_save,
+ .post_load = vmstate_virtio_mini_device_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_BUFFER(rcv_bufs, VirtIOMini),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static void virtio_mini_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->vmsd = &vmstate_virtio_mini;
+ VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+ vdc->realize = virtio_mini_device_realize;
+ vdc->unrealize = virtio_mini_device_unrealize;
+ vdc->get_features = virtio_mini_get_features;
+ vdc->set_status = virtio_mini_set_status;
+ vdc->vmsd = &vmstate_virtio_mini_device;
+}
+
+static const TypeInfo virtio_mini_info = {
+ .name = TYPE_VIRTIO_MINI,
+ .parent = TYPE_VIRTIO_DEVICE,
+ .instance_size = sizeof(VirtIOMini),
+ .class_init = virtio_mini_class_init,
+};
+
+static void virtio_register_types(void) {
+ type_register_static(&virtio_mini_info);
+}
+
+type_init(virtio_register_types);
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 5d607aeaa0..cb959f050b 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -137,6 +137,7 @@ const char *virtio_device_names[] = {
[VIRTIO_ID_BLOCK] = "virtio-blk",
[VIRTIO_ID_CONSOLE] = "virtio-serial",
[VIRTIO_ID_RNG] = "virtio-rng",
+ [VIRTIO_ID_MINI] = "virtio-mini",
[VIRTIO_ID_BALLOON] = "virtio-balloon",
[VIRTIO_ID_IOMEM] = "virtio-iomem",
[VIRTIO_ID_RPMSG] = "virtio-rpmsg",
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index b54b6ef88f..db8c320885 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -84,6 +84,8 @@ extern bool pci_available;
#define PCI_DEVICE_ID_VIRTIO_RNG 0x1005
#define PCI_DEVICE_ID_VIRTIO_9P 0x1009
#define PCI_DEVICE_ID_VIRTIO_VSOCK 0x1012
+/* PCI device ID = VIRTIO_ID_MINI + 0x1040 */
+#define PCI_DEVICE_ID_VIRTIO_MINI 0x1055
#define PCI_DEVICE_ID_VIRTIO_PMEM 0x1013
#define PCI_DEVICE_ID_VIRTIO_IOMMU 0x1014
#define PCI_DEVICE_ID_VIRTIO_MEM 0x1015
diff --git a/include/hw/virtio/virtio-mini.h b/include/hw/virtio/virtio-mini.h
new file mode 100644
index 0000000000..7f48ca342c
--- /dev/null
+++ b/include/hw/virtio/virtio-mini.h
@@ -0,0 +1,18 @@
+#ifndef QEMU_VIRTIO_MINI_H_
+#define QEMU_VIRTIO_MINI_H_
+
+#include "hw/virtio/virtio-pci.h"
+#include "standard-headers/linux/virtio_mini.h"
+
+#define TYPE_VIRTIO_MINI "virtio-mini-device"
+#define VIRTIO_MINI(obj) \
+ OBJECT_CHECK(VirtIOMini, (obj), TYPE_VIRTIO_MINI)
+
+typedef struct VirtIOMini {
+ VirtIODevice parent_obj;
+ VirtQueue *vq_tx;
+ VirtQueue *vq_rx;
+ uint8_t rcv_bufs[1024];
+} VirtIOMini;
+
+#endif
diff --git a/include/standard-headers/linux/virtio_ids.h b/include/standard-headers/linux/virtio_ids.h
index 80d76b75bc..6b2560deea 100644
--- a/include/standard-headers/linux/virtio_ids.h
+++ b/include/standard-headers/linux/virtio_ids.h
@@ -47,7 +47,9 @@
#define VIRTIO_ID_INPUT 18 /* virtio input */
#define VIRTIO_ID_VSOCK 19 /* virtio vsock transport */
#define VIRTIO_ID_CRYPTO 20 /* virtio crypto */
-#define VIRTIO_ID_SIGNAL_DIST 21 /* virtio signal distribution device */
+/* PCI device ID need plus 0x1040 */
+#define VIRTIO_ID_MINI 21 /* virtio mini */
+#define VIRTIO_ID_SIGNAL_DIST 42 /* virtio signal distribution device */
#define VIRTIO_ID_PSTORE 22 /* virtio pstore device */
#define VIRTIO_ID_IOMMU 23 /* virtio IOMMU */
#define VIRTIO_ID_MEM 24 /* virtio mem */
@@ -69,6 +71,7 @@
#define VIRTIO_ID_BT 40 /* virtio bluetooth */
#define VIRTIO_ID_GPIO 41 /* virtio gpio */
+
/*
* Virtio Transitional IDs
*/
diff --git a/include/standard-headers/linux/virtio_mini.h b/include/standard-headers/linux/virtio_mini.h
new file mode 100644
index 0000000000..daf0adf0de
--- /dev/null
+++ b/include/standard-headers/linux/virtio_mini.h
@@ -0,0 +1,7 @@
+#ifndef _LINUX_VIRTIO_MINI_H
+#define _LINUX_VIRTIO_MINI_H
+
+#include "standard-headers/linux/virtio_ids.h"
+#include "standard-headers/linux/virtio_config.h"
+
+#endif
diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c
index 4b0ef65780..24d2d245b4 100644
--- a/softmmu/qdev-monitor.c
+++ b/softmmu/qdev-monitor.c
@@ -99,6 +99,9 @@ static const QDevAlias qdev_alias_table[] = {
{ "virtio-net-device", "virtio-net", QEMU_ARCH_VIRTIO_MMIO },
{ "virtio-net-ccw", "virtio-net", QEMU_ARCH_VIRTIO_CCW },
{ "virtio-net-pci", "virtio-net", QEMU_ARCH_VIRTIO_PCI },
+ /* -device virtio-mini,disable-legacy=on */
+ { "virtio-mini-device", "virtio-mini", QEMU_ARCH_VIRTIO_MMIO },
+ { "virtio-mini-pci", "virtio-mini", QEMU_ARCH_VIRTIO_PCI },
{ "virtio-rng-device", "virtio-rng", QEMU_ARCH_VIRTIO_MMIO },
{ "virtio-rng-ccw", "virtio-rng", QEMU_ARCH_VIRTIO_CCW },
{ "virtio-rng-pci", "virtio-rng", QEMU_ARCH_VIRTIO_PCI },
--
2.35.1

View File

@ -6,7 +6,6 @@ DEBFLAGS = -O2
endif
obj-m := crypto-drv.o
obj-m := virtio_mini.o
KERNELDIR ?= /usr/src/linux
CC ?= gcc
PWD := $(shell pwd)

View File

@ -1,225 +0,0 @@
#include <linux/module.h>
#include <linux/uaccess.h>
#include <linux/scatterlist.h>
#include <linux/virtio_config.h>
#include "virtio_mini.h"
static int virtio_mini_open(struct inode *inode, struct file *file)
{
struct virtio_mini_device *vmini = PDE_DATA(inode);
file->private_data = vmini;
return 0;
}
/* cat /proc/virtio-mini-0 */
static ssize_t virtio_mini_read(struct file *fil, char *buf, size_t count, loff_t *offp)
{
struct virtio_mini_device *vmini = fil->private_data;
char *rcv_buf;
struct scatterlist sg;
unsigned long res;
struct virtqueue *vq = vmini->queues[VIRTIO_MINI_VQ_RX].vq;
if (vmini->buffers < 1)
{
printk(KERN_INFO "all buffers read!");
return 0;
}
rcv_buf = kzalloc(vmini->buf_lens[vmini->buffers - 1], GFP_KERNEL);
if (!rcv_buf)
{
return ENOMEM;
}
sg_init_one(&sg, rcv_buf, vmini->buf_lens[vmini->buffers - 1]);
virtqueue_add_inbuf(vq, &sg, 1, rcv_buf, GFP_KERNEL);
virtqueue_kick(vq);
wait_for_completion(&vmini->data_ready);
res = copy_to_user(buf, vmini->read_data, vmini->buf_lens[vmini->buffers]);
if (res != 0)
{
printk(KERN_INFO "Could not read %lu bytes!", res);
/* update length to actual number of bytes read */
vmini->buf_lens[vmini->buffers] = vmini->buf_lens[vmini->buffers] - res;
}
kfree(rcv_buf);
return vmini->buf_lens[vmini->buffers];
}
/* echo hello > /proc/virtio-mini-0 */
static ssize_t virtio_mini_write(struct file* fil, const char *buf, size_t count, loff_t *offp)
{
struct virtio_mini_device *vmini = fil->private_data;
void *to_send;
unsigned long res;
struct scatterlist sg;
struct virtqueue *vq = vmini->queues[VIRTIO_MINI_VQ_TX].vq;
if (vmini->buffers >= VIRTIO_MINI_BUFFERS)
{
printk(KERN_INFO "all buffers used!");
return ENOSPC;
}
/* 分配空间用于保存用户要发送的数据 */
to_send = kmalloc(count, GFP_KERNEL);
if (!to_send)
{
return 1;
}
/* 将用户的数据保存到to_send */
res = copy_from_user(to_send, buf, count);
if (res != 0) {
printk(KERN_INFO "Could not write %lu bytes!", res);
/* update count to actual number of bytes written */
count = count - res;
}
/*
* virtqueue中数据是存VirtQueueElement中的in_sg或out_sg散列中的
* 驱动中用对应的api来打包,这里virtqueue_add_outbuf
* 所以填充的out_sg
*
* 在设备中通过virtqueue_pop来获取到对应的VirtQueueElement后取出散列中的数据
* 1. 取出element
* vqe = virtqueue_pop(vq, sizeof(VirtQueueElement));
* 2. 取出element里的数据
* iov_to_buf(vqe->out_sg, vqe->out_num, 0, rcv_bufs, vqe->out_sg->iov_len);
*/
sg_init_one(&sg, to_send, count);
vmini->buf_lens[vmini->buffers++] = count;
virtqueue_add_outbuf(vq, &sg, 1, to_send, GFP_KERNEL);
virtqueue_kick(vq);
return count;
}
/* host has acknowledged the message; consume buffer */
void virtio_mini_tx_notify_cb(struct virtqueue *vq)
{
int len;
void *buf = virtqueue_get_buf(vq, &len);
/* free sent data */
if (buf)
{
kfree(buf);
}
return;
}
void virtio_mini_rx_notify_cb(struct virtqueue *vq)
{
int len;
struct virtio_mini_device *vmini = vq->vdev->priv;
vmini->read_data = virtqueue_get_buf(vq, &len);
vmini->buffers--;
complete(&vmini->data_ready);
printk(KERN_INFO "Received %i bytes", len);
}
int vmini_find_vqs(struct virtio_mini_device *vmini)
{
int i;
int err;
struct virtqueue *vqs[VIRTIO_MINI_VQ_MAX];
static const char *names[VIRTIO_MINI_VQ_MAX] = {
[VIRTIO_MINI_VQ_TX] = "virtio-mini-tx",
[VIRTIO_MINI_VQ_RX] = "virtio-mini-rx"
};
static vq_callback_t *callbacks[VIRTIO_MINI_VQ_MAX] = {
[VIRTIO_MINI_VQ_TX] = virtio_mini_tx_notify_cb,
[VIRTIO_MINI_VQ_RX] = virtio_mini_rx_notify_cb
};
err = virtio_find_vqs(vmini->vdev, VIRTIO_MINI_VQ_MAX, vqs, callbacks, names, NULL);
if (err)
{
return err;
}
for (i = 0; i < VIRTIO_MINI_VQ_MAX; i++)
vmini->queues[i].vq = vqs[i];
return 0;
}
int probe_virtio_mini(struct virtio_device *vdev)
{
struct virtio_mini_device *vmini;
int err;
char proc_name[20];
printk(KERN_INFO "virtio-mini device found\n");
vmini = kzalloc(sizeof(struct virtio_mini_device), GFP_KERNEL);
if (vmini == NULL) {
err = ENOMEM;
goto err;
}
/*
* make it possible to access underlying virtio_device
* from virtio_mini_device and vice versa
*/
vdev->priv = vmini;
vmini->vdev = vdev;
err = vmini_find_vqs(vmini);
if (err) {
printk(KERN_INFO "Error adding virtqueue\n");
goto err;
}
vmini->buffers = 0;
init_completion(&vmini->data_ready);
/*
* create a proc entry named "/proc/virtio-mini-<bus_idx>"
* proc_dir_entry data pointer points to associated virtio_mini_device
* allows access to virtqueues from defined file_operations functions
*/
snprintf(proc_name, sizeof(proc_name), "%s-%i", VIRTIO_MINI_STRING, vdev->index);
vmini->pde = proc_create_data(proc_name, 0644, NULL, &pde_fops, vmini);
if (!vmini->pde) {
printk(KERN_INFO "Error creating proc entry");
goto err;
}
printk(KERN_INFO "virtio-mini device probe successfully\n");
return 0;
err:
kfree(vmini);
return err;
}
void remove_virtio_mini(struct virtio_device *vdev)
{
struct virtio_mini_device *vmini = vdev->priv;
proc_remove(vmini->pde);
complete(&vmini->data_ready);
vdev->config->reset(vdev);
vdev->config->del_vqs(vdev);
kfree(vdev->priv);
printk(KERN_INFO "virtio-mini device removed\n");
}
module_virtio_driver(driver_virtio_mini);
MODULE_AUTHOR("zeroway");
MODULE_DESCRIPTION("virtio example front-end driver");
MODULE_LICENSE("GPL v2");

View File

@ -1,77 +0,0 @@
#include <linux/proc_fs.h>
#include <linux/virtio.h>
#include <linux/completion.h>
#ifndef VIRTIO_ID_MINI
#define VIRTIO_ID_MINI 21
#endif
#define VIRTIO_MINI_BUFFERS 1024
#define VIRTIO_MINI_STRING "virtio-mini"
enum {
/* device virtqueue indexes */
VIRTIO_MINI_VQ_TX = 0,
VIRTIO_MINI_VQ_RX,
/* # of device virtqueues */
VIRTIO_MINI_VQ_MAX
};
MODULE_AUTHOR("Matthias Prangl");
MODULE_DESCRIPTION("virtio example front-end driver");
MODULE_LICENSE("GPL v2");
static struct virtio_device_id id_table[] = {
{ VIRTIO_ID_MINI, VIRTIO_DEV_ANY_ID },
{ 0 },
};
static unsigned int feature_table[] = { };
struct virtio_mini_vqueue {
spinlock_t lock;
struct virtqueue *vq;
};
struct virtio_mini_device {
struct virtio_mini_vqueue queues[VIRTIO_MINI_VQ_MAX];
/* related virtio_device */
struct virtio_device *vdev;
/* proc dir entry for this instance of the device */
struct proc_dir_entry *pde;
/* store length of last sent message */
unsigned int buffers;
unsigned int buf_lens[VIRTIO_MINI_BUFFERS];
void *read_data;
struct completion data_ready;
};
static int virtio_mini_open(struct inode *inode, struct file *file);
static ssize_t virtio_mini_read(struct file *fil, char *buf, size_t count, loff_t *offp);
static ssize_t virtio_mini_write(struct file* fil, const char *buf, size_t count, loff_t *offp);
void virtio_mini_vq_tx_cb(struct virtqueue *vq);
void virtio_mini_vq_rx_cb(struct virtqueue *vq);
int vmini_find_vqs(struct virtio_mini_device *vmini);
int probe_virtio_mini(struct virtio_device *vdev);
void remove_virtio_mini(struct virtio_device *vdev);
static struct file_operations pde_fops = {
.owner = THIS_MODULE,
.open = virtio_mini_open,
.read = virtio_mini_read,
.write = virtio_mini_write,
};
static struct virtio_driver driver_virtio_mini = {
.driver.name = KBUILD_MODNAME,
.driver.owner = THIS_MODULE,
.id_table = id_table,
.feature_table = feature_table,
.feature_table_size = ARRAY_SIZE(feature_table),
.probe = probe_virtio_mini,
.remove = remove_virtio_mini
};