~vcs-imports/qemu/git

« back to all changes in this revision

Viewing changes to hw/virtio-console.c

  • Committer: Blue Swirl
  • Date: 2009-08-31 15:14:40 UTC
  • Revision ID: git-v1:528e93a9787ccfc59582a44035f5f342caf5b84f
Fix breakage due to __thread

Thread-local storage is not supported on all hosts.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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, *ovq;
 
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, (uint8_t *)elem.out_sg[d].iov_base,
 
43
                                  elem.out_sg[d].iov_len);
 
44
        }
 
45
        virtqueue_push(vq, &elem, len);
 
46
        virtio_notify(vdev, vq);
 
47
    }
 
48
}
 
49
 
 
50
static void virtio_console_handle_input(VirtIODevice *vdev, VirtQueue *vq)
 
51
{
 
52
}
 
53
 
 
54
static uint32_t virtio_console_get_features(VirtIODevice *vdev)
 
55
{
 
56
    return 0;
 
57
}
 
58
 
 
59
static int vcon_can_read(void *opaque)
 
60
{
 
61
    VirtIOConsole *s = (VirtIOConsole *) opaque;
 
62
 
 
63
    if (!virtio_queue_ready(s->ivq) ||
 
64
        !(s->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK) ||
 
65
        virtio_queue_empty(s->ivq))
 
66
        return 0;
 
67
 
 
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))
 
75
        return 1;
 
76
    return 0;
 
77
}
 
78
 
 
79
static void vcon_read(void *opaque, const uint8_t *buf, int size)
 
80
{
 
81
    VirtIOConsole *s = (VirtIOConsole *) opaque;
 
82
    VirtQueueElement elem;
 
83
    int offset = 0;
 
84
 
 
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) {
 
89
        int i = 0;
 
90
        if (!virtqueue_pop(s->ivq, &elem))
 
91
                break;
 
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);
 
95
            offset += len;
 
96
            i++;
 
97
        }
 
98
        virtqueue_push(s->ivq, &elem, size);
 
99
    }
 
100
    virtio_notify(&s->vdev, s->ivq);
 
101
}
 
102
 
 
103
static void vcon_event(void *opaque, int event)
 
104
{
 
105
    /* we will ignore any event for the time being */
 
106
}
 
107
 
 
108
static void virtio_console_save(QEMUFile *f, void *opaque)
 
109
{
 
110
    VirtIOConsole *s = opaque;
 
111
 
 
112
    virtio_save(&s->vdev, f);
 
113
}
 
114
 
 
115
static int virtio_console_load(QEMUFile *f, void *opaque, int version_id)
 
116
{
 
117
    VirtIOConsole *s = opaque;
 
118
 
 
119
    if (version_id != 1)
 
120
        return -EINVAL;
 
121
 
 
122
    virtio_load(&s->vdev, f);
 
123
    return 0;
 
124
}
 
125
 
 
126
VirtIODevice *virtio_console_init(DeviceState *dev)
 
127
{
 
128
    VirtIOConsole *s;
 
129
    s = (VirtIOConsole *)virtio_common_init("virtio-console",
 
130
                                            VIRTIO_ID_CONSOLE,
 
131
                                            0, sizeof(VirtIOConsole));
 
132
    s->vdev.get_features = virtio_console_get_features;
 
133
 
 
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);
 
136
 
 
137
    s->chr = qdev_init_chardev(dev);
 
138
    qemu_chr_add_handlers(s->chr, vcon_can_read, vcon_read, vcon_event, s);
 
139
 
 
140
    register_savevm("virtio-console", -1, 1, virtio_console_save, virtio_console_load, s);
 
141
 
 
142
    return &s->vdev;
 
143
}