mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-01 23:18:21 +00:00
virtio: feature negotiation
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user