From 87b0ff64b21a560d6ea7c1816acbcfd7c31dff12 Mon Sep 17 00:00:00 2001 From: Matheus Date: Fri, 29 Mar 2024 13:36:48 -0300 Subject: [PATCH] virtio: feature negotiation --- kernel-src/include/kernel/virtio.h | 3 +++ kernel-src/io/block/vioblk.c | 5 +---- kernel-src/io/virtio.c | 24 +++++++++++++++++++++++- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/kernel-src/include/kernel/virtio.h b/kernel-src/include/kernel/virtio.h index b3a51e05..e53ba60d 100644 --- a/kernel-src/include/kernel/virtio.h +++ b/kernel-src/include/kernel/virtio.h @@ -46,9 +46,12 @@ typedef struct { void virtio_init(); size_t virtio_queuesize(viodevice_t *viodevice, int queue); void virtio_enablequeue(viodevice_t *viodevice, int queue); +uint64_t virtio_negotiatefeatures(viodevice_t *viodevice, uint64_t features); void *virtio_createqueue(viodevice_t *viodevice, vioqueue_t *vioqueue, int queue, size_t size, int msix); void virtio_enabledevice(viodevice_t *viodevice); +#define VIO_FEATURE_VERSION_1 (1l << 32) + #define VIO_CONFIG_STATUS_SET(x, v) (x)->config->status |= v #define VIO_CONFIG_STATUS_ACK 1 #define VIO_CONFIG_STATUS_DRIVER 2 diff --git a/kernel-src/io/block/vioblk.c b/kernel-src/io/block/vioblk.c index 7576b152..4e7341d7 100644 --- a/kernel-src/io/block/vioblk.c +++ b/kernel-src/io/block/vioblk.c @@ -151,10 +151,7 @@ int vioblk_newdevice(viodevice_t *viodevice) { pci_initmsix(viodevice->e); // TODO support several queues - // no extra features will be used yet - VIO_CONFIG_STATUS_SET(viodevice, VIO_CONFIG_STATUS_FEATURESOK); - if ((viodevice->config->status & VIO_CONFIG_STATUS_FEATURESOK) == 0) - return 1; + __assert(virtio_negotiatefeatures(viodevice, VIO_FEATURE_VERSION_1) == VIO_FEATURE_VERSION_1); // initialize device object vioblkdev_t *blkdev = alloc(sizeof(vioblkdev_t)); diff --git a/kernel-src/io/virtio.c b/kernel-src/io/virtio.c index 3f2d0508..3af4b385 100644 --- a/kernel-src/io/virtio.c +++ b/kernel-src/io/virtio.c @@ -17,9 +17,11 @@ static char *devname[] = { void vioblk_init(); int vioblk_newdevice(viodevice_t *); +void vionet_init(); +int vionet_newdevice(viodevice_t *); static int (*drivedevice[]) (viodevice_t *) = { - NULL, + vionet_newdevice, vioblk_newdevice }; @@ -33,6 +35,24 @@ void virtio_enablequeue(viodevice_t *viodevice, int queue) { viodevice->config->queueenable = 1; } +uint64_t virtio_negotiatefeatures(viodevice_t *viodevice, uint64_t features) { + viodevice->config->devicefeatureselect = 0; + uint64_t offered = viodevice->config->devicefeature; + viodevice->config->devicefeatureselect = 1; + offered |= (uint64_t)viodevice->config->devicefeature << 32; + uint64_t negotiable = features & offered; + + viodevice->config->driverfeatureselect = 0; + viodevice->config->driverfeature = negotiable & 0xffffffff; + viodevice->config->driverfeatureselect = 1; + viodevice->config->driverfeature = (negotiable >> 32) & 0xffffffff; + + VIO_CONFIG_STATUS_SET(viodevice, VIO_CONFIG_STATUS_FEATURESOK); + __assert(viodevice->config->status & VIO_CONFIG_STATUS_FEATURESOK); + + return negotiable; +} + static uint16_t *virtio_queuenotifyaddress(viodevice_t *viodevice, int queue) { viodevice->config->queueselect = queue; return (uint16_t *)((uintptr_t)viodevice->notify + viodevice->config->queuenotifyoffset * viodevice->notifymultiplier); @@ -79,6 +99,7 @@ void virtio_enabledevice(viodevice_t *viodevice) { static void virtio_newdevice(pcienum_t *e) { pci_setcommand(e, PCI_COMMAND_MMIO, 1); pci_setcommand(e, PCI_COMMAND_IO, 0); + pci_setcommand(e, PCI_COMMAND_BUSMASTER, 1); pci_setcommand(e, PCI_COMMAND_IRQDISABLE, 1); int devtype = e->deviceid - VIRTIO_DEVICE_MIN; @@ -146,6 +167,7 @@ static void virtio_newdevice(pcienum_t *e) { void virtio_init() { vioblk_init(); + vionet_init(); for (int dev = VIRTIO_DEVICE_MIN; dev <= VIRTIO_DEVICE_MAX; ++dev) { int i = 0;