virtio: feature negotiation

This commit is contained in:
Matheus
2024-03-29 13:36:48 -03:00
parent 2030ca8c5b
commit 87b0ff64b2
3 changed files with 27 additions and 5 deletions
+3
View File
@@ -46,9 +46,12 @@ typedef struct {
void virtio_init(); void virtio_init();
size_t virtio_queuesize(viodevice_t *viodevice, int queue); size_t virtio_queuesize(viodevice_t *viodevice, int queue);
void virtio_enablequeue(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_createqueue(viodevice_t *viodevice, vioqueue_t *vioqueue, int queue, size_t size, int msix);
void virtio_enabledevice(viodevice_t *viodevice); 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_SET(x, v) (x)->config->status |= v
#define VIO_CONFIG_STATUS_ACK 1 #define VIO_CONFIG_STATUS_ACK 1
#define VIO_CONFIG_STATUS_DRIVER 2 #define VIO_CONFIG_STATUS_DRIVER 2
+1 -4
View File
@@ -151,10 +151,7 @@ int vioblk_newdevice(viodevice_t *viodevice) {
pci_initmsix(viodevice->e); pci_initmsix(viodevice->e);
// TODO support several queues // TODO support several queues
// no extra features will be used yet __assert(virtio_negotiatefeatures(viodevice, VIO_FEATURE_VERSION_1) == VIO_FEATURE_VERSION_1);
VIO_CONFIG_STATUS_SET(viodevice, VIO_CONFIG_STATUS_FEATURESOK);
if ((viodevice->config->status & VIO_CONFIG_STATUS_FEATURESOK) == 0)
return 1;
// initialize device object // initialize device object
vioblkdev_t *blkdev = alloc(sizeof(vioblkdev_t)); vioblkdev_t *blkdev = alloc(sizeof(vioblkdev_t));
+23 -1
View File
@@ -17,9 +17,11 @@ static char *devname[] = {
void vioblk_init(); void vioblk_init();
int vioblk_newdevice(viodevice_t *); int vioblk_newdevice(viodevice_t *);
void vionet_init();
int vionet_newdevice(viodevice_t *);
static int (*drivedevice[]) (viodevice_t *) = { static int (*drivedevice[]) (viodevice_t *) = {
NULL, vionet_newdevice,
vioblk_newdevice vioblk_newdevice
}; };
@@ -33,6 +35,24 @@ void virtio_enablequeue(viodevice_t *viodevice, int queue) {
viodevice->config->queueenable = 1; 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) { static uint16_t *virtio_queuenotifyaddress(viodevice_t *viodevice, int queue) {
viodevice->config->queueselect = queue; viodevice->config->queueselect = queue;
return (uint16_t *)((uintptr_t)viodevice->notify + viodevice->config->queuenotifyoffset * viodevice->notifymultiplier); 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) { static void virtio_newdevice(pcienum_t *e) {
pci_setcommand(e, PCI_COMMAND_MMIO, 1); pci_setcommand(e, PCI_COMMAND_MMIO, 1);
pci_setcommand(e, PCI_COMMAND_IO, 0); pci_setcommand(e, PCI_COMMAND_IO, 0);
pci_setcommand(e, PCI_COMMAND_BUSMASTER, 1);
pci_setcommand(e, PCI_COMMAND_IRQDISABLE, 1); pci_setcommand(e, PCI_COMMAND_IRQDISABLE, 1);
int devtype = e->deviceid - VIRTIO_DEVICE_MIN; int devtype = e->deviceid - VIRTIO_DEVICE_MIN;
@@ -146,6 +167,7 @@ static void virtio_newdevice(pcienum_t *e) {
void virtio_init() { void virtio_init() {
vioblk_init(); vioblk_init();
vionet_init();
for (int dev = VIRTIO_DEVICE_MIN; dev <= VIRTIO_DEVICE_MAX; ++dev) { for (int dev = VIRTIO_DEVICE_MIN; dev <= VIRTIO_DEVICE_MAX; ++dev) {
int i = 0; int i = 0;