diff options
Diffstat (limited to 'lib/libvirtio/virtio-serial.c')
-rw-r--r-- | lib/libvirtio/virtio-serial.c | 78 |
1 files changed, 33 insertions, 45 deletions
diff --git a/lib/libvirtio/virtio-serial.c b/lib/libvirtio/virtio-serial.c index d2eac63..b8b898f 100644 --- a/lib/libvirtio/virtio-serial.c +++ b/lib/libvirtio/virtio-serial.c @@ -30,13 +30,11 @@ #define RX_Q 0 #define TX_Q 1 -static struct vqs vq_rx; -static struct vqs vq_tx; static uint16_t last_rx_idx; /* Last index in RX "used" ring */ int virtio_serial_init(struct virtio_device *dev) { - struct vring_avail *vq_avail; + struct vqs *vq_rx, *vq_tx; int status = VIRTIO_STAT_ACKNOWLEDGE; int i; @@ -50,7 +48,7 @@ int virtio_serial_init(struct virtio_device *dev) status |= VIRTIO_STAT_DRIVER; virtio_set_status(dev, status); - if (dev->is_modern) { + if (dev->features & VIRTIO_F_VERSION_1) { /* Negotiate features and sets FEATURES_OK if successful */ if (virtio_negotiate_guest_features(dev, DRIVER_FEATURE_SUPPORT)) goto dev_error; @@ -58,36 +56,34 @@ int virtio_serial_init(struct virtio_device *dev) virtio_get_status(dev, &status); } - if (virtio_queue_init_vq(dev, &vq_rx, RX_Q)) + vq_rx = virtio_queue_init_vq(dev, RX_Q); + if (!vq_rx) goto dev_error; /* Allocate memory for multiple receive buffers */ - vq_rx.buf_mem = SLOF_alloc_mem(RX_ELEM_SIZE * RX_NUM_ELEMS); - if (!vq_rx.buf_mem) { + vq_rx->buf_mem = SLOF_alloc_mem(RX_ELEM_SIZE * RX_NUM_ELEMS); + if (!vq_rx->buf_mem) { printf("virtio-serial: Failed to allocate buffers!\n"); goto dev_error; } /* Prepare receive buffer queue */ for (i = 0; i < RX_NUM_ELEMS; i++) { - uint64_t addr = (uint64_t)vq_rx.buf_mem + i * RX_ELEM_SIZE; + uint64_t addr = (uint64_t)vq_rx->buf_mem + i * RX_ELEM_SIZE; /* Descriptor for data: */ - virtio_fill_desc(&vq_rx.desc[i], dev->is_modern, addr, 1, VRING_DESC_F_WRITE, 0); - vq_rx.avail->ring[i] = virtio_cpu_to_modern16(dev, i); + virtio_fill_desc(vq_rx, i, dev->features, addr, 1, VRING_DESC_F_WRITE, 0); + vq_rx->avail->ring[i] = virtio_cpu_to_modern16(dev, i); } - vq_rx.avail->flags = virtio_cpu_to_modern16(dev, VRING_AVAIL_F_NO_INTERRUPT); - vq_rx.avail->idx = virtio_cpu_to_modern16(dev, RX_NUM_ELEMS); + vq_rx->avail->idx = virtio_cpu_to_modern16(dev, RX_NUM_ELEMS); sync(); - last_rx_idx = virtio_modern16_to_cpu(dev, vq_rx.used->idx); + last_rx_idx = virtio_modern16_to_cpu(dev, vq_rx->used->idx); - if (virtio_queue_init_vq(dev, &vq_tx, TX_Q)) + vq_tx = virtio_queue_init_vq(dev, TX_Q); + if (vq_tx) goto dev_error; - vq_avail = virtio_get_vring_avail(dev, TX_Q); - vq_avail->flags = virtio_cpu_to_modern16(dev, VRING_AVAIL_F_NO_INTERRUPT); - vq_avail->idx = 0; /* Tell HV that setup succeeded */ status |= VIRTIO_STAT_DRIVER_OK; @@ -112,35 +108,26 @@ void virtio_serial_shutdown(struct virtio_device *dev) int virtio_serial_putchar(struct virtio_device *dev, char c) { - struct vring_desc *desc; int id; - uint32_t vq_size, time; - struct vring_desc *vq_desc; - struct vring_avail *vq_avail; - struct vring_used *vq_used; + uint32_t time; volatile uint16_t *current_used_idx; uint16_t last_used_idx, avail_idx; + struct vqs *vq = &dev->vq[TX_Q]; - vq_size = virtio_get_qsize(dev, TX_Q); - vq_desc = virtio_get_vring_desc(dev, TX_Q); - vq_avail = virtio_get_vring_avail(dev, TX_Q); - vq_used = virtio_get_vring_used(dev, TX_Q); + avail_idx = virtio_modern16_to_cpu(dev, vq->avail->idx); - avail_idx = virtio_modern16_to_cpu(dev, vq_avail->idx); - - last_used_idx = vq_used->idx; - current_used_idx = &vq_used->idx; + last_used_idx = vq->used->idx; + current_used_idx = &vq->used->idx; /* Determine descriptor index */ - id = avail_idx % vq_size; + id = avail_idx % vq->size; /* Set up virtqueue descriptor for header */ - desc = &vq_desc[id]; - virtio_fill_desc(desc, dev->is_modern, (uint64_t)&c, 1, 0, 0); + virtio_fill_desc(vq, id, dev->features, (uint64_t)&c, 1, 0, 0); - vq_avail->ring[avail_idx % vq_size] = virtio_cpu_to_modern16 (dev, id); + vq->avail->ring[avail_idx % vq->size] = virtio_cpu_to_modern16 (dev, id); mb(); - vq_avail->idx = virtio_cpu_to_modern16(dev, avail_idx + 1); + vq->avail->idx = virtio_cpu_to_modern16(dev, avail_idx + 1); /* Tell HV that the queue is ready */ virtio_queue_notify(dev, TX_Q); @@ -159,33 +146,32 @@ int virtio_serial_putchar(struct virtio_device *dev, char c) return 1; } -static uint16_t last_rx_idx; /* Last index in RX "used" ring */ - char virtio_serial_getchar(struct virtio_device *dev) { int id, idx; char buf[RX_NUM_ELEMS] = {0}; uint16_t avail_idx; + struct vqs *vq_rx = &dev->vq[RX_Q]; - idx = virtio_modern16_to_cpu(dev, vq_rx.used->idx); + idx = virtio_modern16_to_cpu(dev, vq_rx->used->idx); if (last_rx_idx == idx) { /* Nothing received yet */ return 0; } - id = (virtio_modern32_to_cpu(dev, vq_rx.used->ring[last_rx_idx % vq_rx.size].id) + 1) - % vq_rx.size; + id = (virtio_modern32_to_cpu(dev, vq_rx->used->ring[last_rx_idx % vq_rx->size].id) + 1) + % vq_rx->size; /* Copy data to destination buffer */ - memcpy(buf, (void *)virtio_modern64_to_cpu(dev, vq_rx.desc[id - 1].addr), RX_ELEM_SIZE); + memcpy(buf, (void *)virtio_modern64_to_cpu(dev, vq_rx->desc[id - 1].addr), RX_ELEM_SIZE); /* Move indices to next entries */ last_rx_idx = last_rx_idx + 1; - avail_idx = virtio_modern16_to_cpu(dev, vq_rx.avail->idx); - vq_rx.avail->ring[avail_idx % vq_rx.size] = virtio_cpu_to_modern16(dev, id - 1); + avail_idx = virtio_modern16_to_cpu(dev, vq_rx->avail->idx); + vq_rx->avail->ring[avail_idx % vq_rx->size] = virtio_cpu_to_modern16(dev, id - 1); sync(); - vq_rx.avail->idx = virtio_cpu_to_modern16(dev, avail_idx + 1); + vq_rx->avail->idx = virtio_cpu_to_modern16(dev, avail_idx + 1); sync(); /* Tell HV that RX queue entry is ready */ @@ -196,7 +182,9 @@ char virtio_serial_getchar(struct virtio_device *dev) int virtio_serial_haschar(struct virtio_device *dev) { - if (last_rx_idx == virtio_modern16_to_cpu(dev, vq_rx.used->idx)) + struct vqs *vq_rx = &dev->vq[RX_Q]; + + if (last_rx_idx == virtio_modern16_to_cpu(dev, vq_rx->used->idx)) return 0; else return 1; |