mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
virtio: vioqueue_t
This commit is contained in:
@@ -36,11 +36,17 @@ typedef struct {
|
||||
size_t notifymultiplier;
|
||||
} viodevice_t;
|
||||
|
||||
typedef struct {
|
||||
void *address;
|
||||
size_t size;
|
||||
uint16_t *notify;
|
||||
uint16_t lastusedindex;
|
||||
} vioqueue_t;
|
||||
|
||||
void virtio_init();
|
||||
size_t virtio_queuesize(viodevice_t *viodevice, int queue);
|
||||
uint16_t *virtio_queuenotifyaddress(viodevice_t *viodevice, int queue);
|
||||
void virtio_enablequeue(viodevice_t *viodevice, int queue);
|
||||
void *virtio_createqueue(viodevice_t *viodevice, 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);
|
||||
|
||||
#define VIO_CONFIG_STATUS_SET(x, v) (x)->config->status |= v
|
||||
@@ -97,12 +103,12 @@ struct {
|
||||
*/
|
||||
|
||||
#define VIO_QUEUE_BYTESIZE(s) (sizeof(viobuffer_t) * (s) + sizeof(uint16_t) * ((s) + 6) + sizeof(viousedentry_t) * (s))
|
||||
#define VIO_QUEUE_BUFFERS(q, s) ((volatile viobuffer_t *)(q))
|
||||
#define VIO_QUEUE_DRV(q, s) ((volatile uint16_t *)((uintptr_t)(q) + (s) * sizeof(viobuffer_t)))
|
||||
#define VIO_QUEUE_DRV_IDX(q, s) ((volatile uint16_t *)((uintptr_t)(q) + (s) * sizeof(viobuffer_t)))[1]
|
||||
#define VIO_QUEUE_DRV_RING(q, s) ((volatile uint16_t *)((uintptr_t)(q) + (s) * sizeof(viobuffer_t) + 2 * sizeof(uint16_t)))
|
||||
#define VIO_QUEUE_DEV(q, s) ((volatile uint16_t *)((uintptr_t)(q) + (s) * sizeof(viobuffer_t) + sizeof(uint16_t) * ((s) + 3 + (1 - ((s) % 2)))))
|
||||
#define VIO_QUEUE_DEV_IDX(q, s) ((volatile uint16_t *)((uintptr_t)(q) + (s) * sizeof(viobuffer_t) + sizeof(uint16_t) * ((s) + 3 + (1 - ((s) % 2)))))[1]
|
||||
#define VIO_QUEUE_DEV_RING(q, s) ((volatile viousedentry_t *)((uintptr_t)(q) + (s) * sizeof(viobuffer_t) + sizeof(uint16_t) * ((s) + 5 + (1 - ((s) % 2)))))
|
||||
#define VIO_QUEUE_BUFFERS(q) ((volatile viobuffer_t *)(q)->address)
|
||||
#define VIO_QUEUE_DRV(q) ((volatile uint16_t *)((uintptr_t)(q)->address + (q)->size * sizeof(viobuffer_t)))
|
||||
#define VIO_QUEUE_DRV_IDX(q) ((volatile uint16_t *)((uintptr_t)(q)->address + (q)->size * sizeof(viobuffer_t)))[1]
|
||||
#define VIO_QUEUE_DRV_RING(q) ((volatile uint16_t *)((uintptr_t)(q)->address + (q)->size * sizeof(viobuffer_t) + 2 * sizeof(uint16_t)))
|
||||
#define VIO_QUEUE_DEV(q) ((volatile uint16_t *)((uintptr_t)(q)->address + (q)->size * sizeof(viobuffer_t) + sizeof(uint16_t) * ((q)->size + 3 + (1 - ((q)->size % 2)))))
|
||||
#define VIO_QUEUE_DEV_IDX(q) ((volatile uint16_t *)((uintptr_t)(q)->address + (q)->size * sizeof(viobuffer_t) + sizeof(uint16_t) * ((q)->size + 3 + (1 - ((q)->size % 2)))))[1]
|
||||
#define VIO_QUEUE_DEV_RING(q) ((volatile viousedentry_t *)((uintptr_t)(q)->address + (q)->size * sizeof(viobuffer_t) + sizeof(uint16_t) * ((q)->size + 5 + (1 - ((q)->size % 2)))))
|
||||
|
||||
#endif
|
||||
|
||||
@@ -19,14 +19,11 @@ typedef struct {
|
||||
viodevice_t *viodevice;
|
||||
size_t capacity;
|
||||
int id;
|
||||
void *queue;
|
||||
size_t queuesize;
|
||||
vioqueue_t queue;
|
||||
dpc_t queuedpc;
|
||||
spinlock_t queuelock;
|
||||
semaphore_t queuesem;
|
||||
event_t *queuewaiting[QUEUE_MAX_SIZE / 2];
|
||||
uint16_t *queuenotify;
|
||||
uint16_t queuelastindex;
|
||||
} vioblkdev_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -43,11 +40,11 @@ static scache_t *headercache;
|
||||
|
||||
static void vioblk_dpc(context_t *context, dpcarg_t arg) {
|
||||
vioblkdev_t *blkdev = arg;
|
||||
volatile viobuffer_t *buffers = VIO_QUEUE_BUFFERS(blkdev->queue, blkdev->queuesize);
|
||||
volatile viobuffer_t *buffers = VIO_QUEUE_BUFFERS(&blkdev->queue);
|
||||
spinlock_acquire(&blkdev->queuelock);
|
||||
while (blkdev->queuelastindex != VIO_QUEUE_DEV_IDX(blkdev->queue, blkdev->queuesize)) {
|
||||
int idx = blkdev->queuelastindex++ % blkdev->queuesize;
|
||||
int buffidx = VIO_QUEUE_DEV_RING(blkdev->queue, blkdev->queuesize)[idx].index;
|
||||
while (blkdev->queue.lastusedindex != VIO_QUEUE_DEV_IDX(&blkdev->queue)) {
|
||||
int idx = blkdev->queue.lastusedindex++ % blkdev->queue.size;
|
||||
int buffidx = VIO_QUEUE_DEV_RING(&blkdev->queue)[idx].index;
|
||||
__assert(blkdev->queuewaiting[buffidx / 2]);
|
||||
event_signal(blkdev->queuewaiting[buffidx / 2]);
|
||||
blkdev->queuewaiting[buffidx / 2] = NULL;
|
||||
@@ -75,7 +72,7 @@ static void vioblk_enqueue(vioblkdev_t *blkdev, void *driver, size_t driverlen,
|
||||
|
||||
spinlock_acquire(&blkdev->queuelock);
|
||||
int idx = 0;
|
||||
volatile viobuffer_t *buffers = VIO_QUEUE_BUFFERS(blkdev->queue, blkdev->queuesize);
|
||||
volatile viobuffer_t *buffers = VIO_QUEUE_BUFFERS(&blkdev->queue);
|
||||
while (buffers[idx].address && idx < QUEUE_MAX_SIZE)
|
||||
++idx;
|
||||
|
||||
@@ -90,12 +87,12 @@ static void vioblk_enqueue(vioblkdev_t *blkdev, void *driver, size_t driverlen,
|
||||
buffers[idx + 1].length = devicelen;
|
||||
buffers[idx + 1].flags = VIO_QUEUE_BUFFER_DEVICE;
|
||||
|
||||
size_t driveridx = VIO_QUEUE_DRV_IDX(blkdev->queue, blkdev->queuesize)++;
|
||||
VIO_QUEUE_DRV_RING(blkdev->queue, blkdev->queuesize)[driveridx % blkdev->queuesize] = idx;
|
||||
size_t driveridx = VIO_QUEUE_DRV_IDX(&blkdev->queue)++;
|
||||
VIO_QUEUE_DRV_RING(&blkdev->queue)[driveridx % blkdev->queue.size] = idx;
|
||||
|
||||
blkdev->queuewaiting[idx / 2] = &event;
|
||||
|
||||
*blkdev->queuenotify = 0;
|
||||
*blkdev->queue.notify = 0;
|
||||
spinlock_release(&blkdev->queuelock);
|
||||
|
||||
event_wait(&event, false);
|
||||
@@ -151,7 +148,7 @@ int vioblk_newdevice(viodevice_t *viodevice) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t intcount = pci_initmsix(viodevice->e);
|
||||
pci_initmsix(viodevice->e);
|
||||
|
||||
// TODO support several queues
|
||||
// no extra features will be used yet
|
||||
@@ -179,10 +176,9 @@ int vioblk_newdevice(viodevice_t *viodevice) {
|
||||
__assert(hashtable_set(&inttable, blkdev, &isr->id, sizeof(isr->id), true) == 0);
|
||||
|
||||
// initialize queue
|
||||
blkdev->queuesize = min(QUEUE_MAX_SIZE, virtio_queuesize(viodevice, 0));
|
||||
blkdev->queue = MAKE_HHDM(virtio_createqueue(viodevice, 0, blkdev->queuesize, 0));
|
||||
blkdev->queuenotify = virtio_queuenotifyaddress(viodevice, 0);
|
||||
SEMAPHORE_INIT(&blkdev->queuesem, blkdev->queuesize / 2);
|
||||
size_t size = min(QUEUE_MAX_SIZE, virtio_queuesize(viodevice, 0));
|
||||
virtio_createqueue(viodevice, &blkdev->queue, 0, size, 0);
|
||||
SEMAPHORE_INIT(&blkdev->queuesem, blkdev->queue.size / 2);
|
||||
SPINLOCK_INIT(blkdev->queuelock);
|
||||
|
||||
virtio_enablequeue(viodevice, 0);
|
||||
|
||||
+13
-7
@@ -33,12 +33,12 @@ void virtio_enablequeue(viodevice_t *viodevice, int queue) {
|
||||
viodevice->config->queueenable = 1;
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
void *virtio_createqueue(viodevice_t *viodevice, int queue, size_t size, int msix) {
|
||||
void *virtio_createqueue(viodevice_t *viodevice, vioqueue_t *vioqueue, int queue, size_t size, int msix) {
|
||||
size_t bytesize = VIO_QUEUE_BYTESIZE(size);
|
||||
size_t pagesize = ROUND_UP(bytesize, PAGE_SIZE) / PAGE_SIZE;
|
||||
|
||||
@@ -46,13 +46,19 @@ void *virtio_createqueue(viodevice_t *viodevice, int queue, size_t size, int msi
|
||||
__assert(queuephys);
|
||||
memset(MAKE_HHDM(queuephys), 0, bytesize);
|
||||
|
||||
vioqueue->address = queuephys;
|
||||
vioqueue->size = size;
|
||||
vioqueue->notify = virtio_queuenotifyaddress(viodevice, queue);
|
||||
|
||||
viodevice->config->queueselect = queue;
|
||||
viodevice->config->queuesize = size;
|
||||
viodevice->config->queuemsixvector = msix;
|
||||
__assert(viodevice->config->queuemsixvector == msix);
|
||||
viodevice->config->queuedesc = (uint64_t)VIO_QUEUE_BUFFERS(queuephys, size);
|
||||
viodevice->config->queuedriver = (uint64_t)VIO_QUEUE_DRV(queuephys, size);
|
||||
viodevice->config->queuedevice = (uint64_t)VIO_QUEUE_DEV(queuephys, size);
|
||||
viodevice->config->queuedesc = (uint64_t)VIO_QUEUE_BUFFERS(vioqueue);
|
||||
viodevice->config->queuedriver = (uint64_t)VIO_QUEUE_DRV(vioqueue);
|
||||
viodevice->config->queuedevice = (uint64_t)VIO_QUEUE_DEV(vioqueue);
|
||||
|
||||
vioqueue->address = MAKE_HHDM(queuephys);
|
||||
|
||||
return queuephys;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user