2
* Virtio Console Device
4
* Copyright IBM, Corp. 2008
7
* Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
9
* This work is licensed under the terms of the GNU GPL, version 2. See
10
* the COPYING file in the top-level directory.
15
#include "qemu-char.h"
17
#include "virtio-console.h"
20
typedef struct VirtIOConsole
27
static VirtIOConsole *to_virtio_console(VirtIODevice *vdev)
29
return (VirtIOConsole *)vdev;
32
static void virtio_console_handle_output(VirtIODevice *vdev, VirtQueue *vq)
34
VirtIOConsole *s = to_virtio_console(vdev);
35
VirtQueueElement elem;
37
while (virtqueue_pop(vq, &elem)) {
41
for (d = 0; d < elem.out_num; d++) {
42
len += qemu_chr_write(s->chr, (uint8_t *)elem.out_sg[d].iov_base,
43
elem.out_sg[d].iov_len);
45
virtqueue_push(vq, &elem, len);
46
virtio_notify(vdev, vq);
50
static void virtio_console_handle_input(VirtIODevice *vdev, VirtQueue *vq)
54
static uint32_t virtio_console_get_features(VirtIODevice *vdev)
59
static int vcon_can_read(void *opaque)
61
VirtIOConsole *s = (VirtIOConsole *) opaque;
63
if (!virtio_queue_ready(s->ivq) ||
64
!(s->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK) ||
65
virtio_queue_empty(s->ivq))
68
/* current implementations have a page sized buffer.
69
* We fall back to a one byte per read if there is not enough room.
70
* It would be cool to have a function that returns the available byte
71
* instead of checking for a limit */
72
if (virtqueue_avail_bytes(s->ivq, TARGET_PAGE_SIZE, 0))
73
return TARGET_PAGE_SIZE;
74
if (virtqueue_avail_bytes(s->ivq, 1, 0))
79
static void vcon_read(void *opaque, const uint8_t *buf, int size)
81
VirtIOConsole *s = (VirtIOConsole *) opaque;
82
VirtQueueElement elem;
85
/* The current kernel implementation has only one outstanding input
86
* buffer of PAGE_SIZE. Nevertheless, this function is prepared to
87
* handle multiple buffers with multiple sg element for input */
88
while (offset < size) {
90
if (!virtqueue_pop(s->ivq, &elem))
92
while (offset < size && i < elem.in_num) {
93
int len = MIN(elem.in_sg[i].iov_len, size - offset);
94
memcpy(elem.in_sg[i].iov_base, buf + offset, len);
98
virtqueue_push(s->ivq, &elem, size);
100
virtio_notify(&s->vdev, s->ivq);
103
static void vcon_event(void *opaque, int event)
105
/* we will ignore any event for the time being */
108
static void virtio_console_save(QEMUFile *f, void *opaque)
110
VirtIOConsole *s = opaque;
112
virtio_save(&s->vdev, f);
115
static int virtio_console_load(QEMUFile *f, void *opaque, int version_id)
117
VirtIOConsole *s = opaque;
122
virtio_load(&s->vdev, f);
126
VirtIODevice *virtio_console_init(DeviceState *dev)
129
s = (VirtIOConsole *)virtio_common_init("virtio-console",
131
0, sizeof(VirtIOConsole));
132
s->vdev.get_features = virtio_console_get_features;
134
s->ivq = virtio_add_queue(&s->vdev, 128, virtio_console_handle_input);
135
s->ovq = virtio_add_queue(&s->vdev, 128, virtio_console_handle_output);
137
s->chr = qdev_init_chardev(dev);
138
qemu_chr_add_handlers(s->chr, vcon_can_read, vcon_read, vcon_event, s);
140
register_savevm("virtio-console", -1, 1, virtio_console_save, virtio_console_load, s);