Annotation of qemu/hw/virtio-console.c, revision 1.1.1.1
1.1 root 1: /*
2: * Virtio Console Device
3: *
4: * Copyright IBM, Corp. 2008
5: *
6: * Authors:
7: * Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
8: *
9: * This work is licensed under the terms of the GNU GPL, version 2. See
10: * the COPYING file in the top-level directory.
11: *
12: */
13:
14: #include "hw.h"
15: #include "qemu-char.h"
16: #include "virtio.h"
17: #include "virtio-console.h"
18:
19:
20: typedef struct VirtIOConsole
21: {
22: VirtIODevice vdev;
23: VirtQueue *ivq, *dvq;
24: CharDriverState *chr;
25: } VirtIOConsole;
26:
27: static VirtIOConsole *to_virtio_console(VirtIODevice *vdev)
28: {
29: return (VirtIOConsole *)vdev;
30: }
31:
32: static void virtio_console_handle_output(VirtIODevice *vdev, VirtQueue *vq)
33: {
34: VirtIOConsole *s = to_virtio_console(vdev);
35: VirtQueueElement elem;
36:
37: while (virtqueue_pop(vq, &elem)) {
38: ssize_t len = 0;
39: int d;
40:
41: for (d=0; d < elem.out_num; d++)
42: len += qemu_chr_write(s->chr, elem.out_sg[d].iov_base,elem.out_sg[d].iov_len);
43: virtqueue_push(vq, &elem, len);
44: virtio_notify(vdev, vq);
45: }
46: }
47:
48: static void virtio_console_handle_input(VirtIODevice *vdev, VirtQueue *vq)
49: {
50: }
51:
52: static uint32_t virtio_console_get_features(VirtIODevice *vdev)
53: {
54: return 0;
55: }
56:
57: static int vcon_can_read(void *opaque)
58: {
59: VirtIOConsole *s = (VirtIOConsole *) opaque;
60:
61: if (!virtio_queue_ready(s->ivq) ||
62: !(s->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK) ||
63: virtio_queue_empty(s->ivq))
64: return 0;
65:
66: /* current implementations have a page sized buffer.
67: * We fall back to a one byte per read if there is not enough room.
68: * It would be cool to have a function that returns the available byte
69: * instead of checking for a limit */
70: if (virtqueue_avail_bytes(s->ivq, TARGET_PAGE_SIZE, 0))
71: return TARGET_PAGE_SIZE;
72: if (virtqueue_avail_bytes(s->ivq, 1, 0))
73: return 1;
74: return 0;
75: }
76:
77: static void vcon_read(void *opaque, const uint8_t *buf, int size)
78: {
79: VirtIOConsole *s = (VirtIOConsole *) opaque;
80: VirtQueueElement elem;
81: int offset = 0;
82:
83: /* The current kernel implementation has only one outstanding input
84: * buffer of PAGE_SIZE. Nevertheless, this function is prepared to
85: * handle multiple buffers with multiple sg element for input */
86: while (offset < size) {
87: int i = 0;
88: if (!virtqueue_pop(s->ivq, &elem))
89: break;
90: while (offset < size && i < elem.in_num) {
91: int len = MIN(elem.in_sg[i].iov_len, size - offset);
92: memcpy(elem.in_sg[i].iov_base, buf + offset, len);
93: offset += len;
94: i++;
95: }
96: virtqueue_push(s->ivq, &elem, size);
97: }
98: virtio_notify(&s->vdev, s->ivq);
99: }
100:
101: static void vcon_event(void *opaque, int event)
102: {
103: /* we will ignore any event for the time being */
104: }
105:
106: static void virtio_console_save(QEMUFile *f, void *opaque)
107: {
108: VirtIOConsole *s = opaque;
109:
110: virtio_save(&s->vdev, f);
111: }
112:
113: static int virtio_console_load(QEMUFile *f, void *opaque, int version_id)
114: {
115: VirtIOConsole *s = opaque;
116:
117: if (version_id != 1)
118: return -EINVAL;
119:
120: virtio_load(&s->vdev, f);
121: return 0;
122: }
123:
124: void *virtio_console_init(PCIBus *bus, CharDriverState *chr)
125: {
126: VirtIOConsole *s;
127:
128: s = (VirtIOConsole *)virtio_init_pci(bus, "virtio-console",
129: PCI_VENDOR_ID_REDHAT_QUMRANET,
130: PCI_DEVICE_ID_VIRTIO_CONSOLE,
131: PCI_VENDOR_ID_REDHAT_QUMRANET,
132: VIRTIO_ID_CONSOLE,
133: PCI_CLASS_DISPLAY_OTHER, 0x00,
134: 0, sizeof(VirtIOConsole));
135: if (s == NULL)
136: return NULL;
137:
138: s->vdev.get_features = virtio_console_get_features;
139:
140: s->ivq = virtio_add_queue(&s->vdev, 128, virtio_console_handle_input);
141: s->dvq = virtio_add_queue(&s->vdev, 128, virtio_console_handle_output);
142:
143: s->chr = chr;
144: qemu_chr_add_handlers(chr, vcon_can_read, vcon_read, vcon_event, s);
145:
146: register_savevm("virtio-console", -1, 1, virtio_console_save, virtio_console_load, s);
147:
148: return &s->vdev;
149: }
unix.superglobalmegacorp.com