diff --git a/dev/virtio/include/dev/virtio.h b/dev/virtio/include/dev/virtio.h index de09e117..39ca31ae 100644 --- a/dev/virtio/include/dev/virtio.h +++ b/dev/virtio/include/dev/virtio.h @@ -49,6 +49,7 @@ struct virtio_device { enum handler_return (*irq_driver_callback)(struct virtio_device *dev, uint ring, const struct vring_used_elem *e); /* virtio rings */ + uint32_t active_rings_bitmap; struct vring ring[MAX_VIRTIO_RINGS]; }; diff --git a/dev/virtio/virtio.c b/dev/virtio/virtio.c index c619c401..f645fb3c 100644 --- a/dev/virtio/virtio.c +++ b/dev/virtio/virtio.c @@ -82,25 +82,30 @@ static enum handler_return virtio_mmio_irq(void *arg) LTRACEF("status 0x%x\n", irq_status); enum handler_return ret = INT_NO_RESCHEDULE; - if (irq_status & 0x1) { // used ring update - // XXX only handles ring 0 - struct vring *ring = &dev->ring[0]; - LTRACEF("used flags 0x%hhx idx 0x%hhx\n", ring->used->flags, ring->used->idx); + if (irq_status & 0x1) { /* used ring update */ - uint cur_idx = ring->used->idx; - for (uint i = ring->last_used; i != cur_idx; i = (i + 1) & ring->num_mask) { - LTRACEF("looking at idx %u\n", i); + /* cycle through all the active rings */ + for (uint r = 0; r < MAX_VIRTIO_RINGS; r++) { + if ((dev->active_rings_bitmap & (1<used->ring[i]; - LTRACEF("id %u, len %u\n", used_elem->id, used_elem->len); + struct vring *ring = &dev->ring[r]; + LTRACEF("ring %u: used flags 0x%hhx idx 0x%hhx\n", r, ring->used->flags, ring->used->idx); - DEBUG_ASSERT(dev->irq_driver_callback); - ret |= dev->irq_driver_callback(dev, 0, used_elem); + uint cur_idx = ring->used->idx; + for (uint i = ring->last_used; i != cur_idx; i = (i + 1) & ring->num_mask) { + LTRACEF("looking at idx %u\n", i); - ring->last_used = (ring->last_used + 1) & ring->num_mask; + // process chain + struct vring_used_elem *used_elem = &ring->used->ring[i]; + LTRACEF("id %u, len %u\n", used_elem->id, used_elem->len); + + DEBUG_ASSERT(dev->irq_driver_callback); + ret |= dev->irq_driver_callback(dev, r, used_elem); + + ring->last_used = (ring->last_used + 1) & ring->num_mask; + } } - // XXX is this safe? dev->mmio_config->interrupt_ack = 0x1; } @@ -331,6 +336,9 @@ status_t virtio_alloc_ring(struct virtio_device *dev, uint index, uint16_t len) dev->mmio_config->queue_align = PAGE_SIZE; dev->mmio_config->queue_pfn = pa / PAGE_SIZE; + /* mark the ring active */ + dev->active_rings_bitmap |= (1 << index); + return NO_ERROR; }