Statistics
| Branch: | Revision:

root / hw / virtio-console.c @ 0dad6c35

History | View | Annotate | Download (4.9 kB)

1 98b19252 Amit Shah
/*
2 98b19252 Amit Shah
 * Virtio Console and Generic Serial Port Devices
3 98b19252 Amit Shah
 *
4 71c092e9 Amit Shah
 * Copyright Red Hat, Inc. 2009, 2010
5 98b19252 Amit Shah
 *
6 98b19252 Amit Shah
 * Authors:
7 98b19252 Amit Shah
 *  Amit Shah <amit.shah@redhat.com>
8 98b19252 Amit Shah
 *
9 98b19252 Amit Shah
 * This work is licensed under the terms of the GNU GPL, version 2.  See
10 98b19252 Amit Shah
 * the COPYING file in the top-level directory.
11 98b19252 Amit Shah
 */
12 98b19252 Amit Shah
13 98b19252 Amit Shah
#include "qemu-char.h"
14 0b8b716d Amit Shah
#include "qemu-error.h"
15 d02e4fa4 Amit Shah
#include "trace.h"
16 98b19252 Amit Shah
#include "virtio-serial.h"
17 98b19252 Amit Shah
18 98b19252 Amit Shah
typedef struct VirtConsole {
19 98b19252 Amit Shah
    VirtIOSerialPort port;
20 98b19252 Amit Shah
    CharDriverState *chr;
21 98b19252 Amit Shah
} VirtConsole;
22 98b19252 Amit Shah
23 98b19252 Amit Shah
24 98b19252 Amit Shah
/* Callback function that's called when the guest sends us data */
25 e300ac27 Amit Shah
static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
26 98b19252 Amit Shah
{
27 98b19252 Amit Shah
    VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
28 d02e4fa4 Amit Shah
    ssize_t ret;
29 98b19252 Amit Shah
30 6640422c Amit Shah
    if (!vcon->chr) {
31 6640422c Amit Shah
        /* If there's no backend, we can just say we consumed all data. */
32 6640422c Amit Shah
        return len;
33 6640422c Amit Shah
    }
34 6640422c Amit Shah
35 2cc6e0a1 Anthony Liguori
    ret = qemu_chr_fe_write(vcon->chr, buf, len);
36 d02e4fa4 Amit Shah
    trace_virtio_console_flush_buf(port->id, len, ret);
37 0219d732 Amit Shah
38 0219d732 Amit Shah
    if (ret < 0) {
39 0219d732 Amit Shah
        /*
40 0219d732 Amit Shah
         * Ideally we'd get a better error code than just -1, but
41 0219d732 Amit Shah
         * that's what the chardev interface gives us right now.  If
42 0219d732 Amit Shah
         * we had a finer-grained message, like -EPIPE, we could close
43 0219d732 Amit Shah
         * this connection.  Absent such error messages, the most we
44 0219d732 Amit Shah
         * can do is to return 0 here.
45 0219d732 Amit Shah
         *
46 0219d732 Amit Shah
         * This will prevent stray -1 values to go to
47 0219d732 Amit Shah
         * virtio-serial-bus.c and cause abort()s in
48 0219d732 Amit Shah
         * do_flush_queued_data().
49 0219d732 Amit Shah
         */
50 0219d732 Amit Shah
        ret = 0;
51 0219d732 Amit Shah
    }
52 d02e4fa4 Amit Shah
    return ret;
53 98b19252 Amit Shah
}
54 98b19252 Amit Shah
55 0b6d2266 Hans de Goede
/* Callback function that's called when the guest opens the port */
56 0b6d2266 Hans de Goede
static void guest_open(VirtIOSerialPort *port)
57 0b6d2266 Hans de Goede
{
58 0b6d2266 Hans de Goede
    VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
59 0b6d2266 Hans de Goede
60 6640422c Amit Shah
    if (!vcon->chr) {
61 6640422c Amit Shah
        return;
62 6640422c Amit Shah
    }
63 c9d830ed Anthony Liguori
    qemu_chr_fe_open(vcon->chr);
64 0b6d2266 Hans de Goede
}
65 0b6d2266 Hans de Goede
66 0b6d2266 Hans de Goede
/* Callback function that's called when the guest closes the port */
67 0b6d2266 Hans de Goede
static void guest_close(VirtIOSerialPort *port)
68 0b6d2266 Hans de Goede
{
69 0b6d2266 Hans de Goede
    VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
70 0b6d2266 Hans de Goede
71 6640422c Amit Shah
    if (!vcon->chr) {
72 6640422c Amit Shah
        return;
73 6640422c Amit Shah
    }
74 2817822d Anthony Liguori
    qemu_chr_fe_close(vcon->chr);
75 0b6d2266 Hans de Goede
}
76 0b6d2266 Hans de Goede
77 98b19252 Amit Shah
/* Readiness of the guest to accept data on a port */
78 98b19252 Amit Shah
static int chr_can_read(void *opaque)
79 98b19252 Amit Shah
{
80 98b19252 Amit Shah
    VirtConsole *vcon = opaque;
81 98b19252 Amit Shah
82 98b19252 Amit Shah
    return virtio_serial_guest_ready(&vcon->port);
83 98b19252 Amit Shah
}
84 98b19252 Amit Shah
85 98b19252 Amit Shah
/* Send data from a char device over to the guest */
86 98b19252 Amit Shah
static void chr_read(void *opaque, const uint8_t *buf, int size)
87 98b19252 Amit Shah
{
88 98b19252 Amit Shah
    VirtConsole *vcon = opaque;
89 98b19252 Amit Shah
90 d02e4fa4 Amit Shah
    trace_virtio_console_chr_read(vcon->port.id, size);
91 98b19252 Amit Shah
    virtio_serial_write(&vcon->port, buf, size);
92 98b19252 Amit Shah
}
93 98b19252 Amit Shah
94 98b19252 Amit Shah
static void chr_event(void *opaque, int event)
95 98b19252 Amit Shah
{
96 98b19252 Amit Shah
    VirtConsole *vcon = opaque;
97 98b19252 Amit Shah
98 d02e4fa4 Amit Shah
    trace_virtio_console_chr_event(vcon->port.id, event);
99 98b19252 Amit Shah
    switch (event) {
100 28eaf465 Amit Shah
    case CHR_EVENT_OPENED:
101 98b19252 Amit Shah
        virtio_serial_open(&vcon->port);
102 98b19252 Amit Shah
        break;
103 98b19252 Amit Shah
    case CHR_EVENT_CLOSED:
104 98b19252 Amit Shah
        virtio_serial_close(&vcon->port);
105 98b19252 Amit Shah
        break;
106 98b19252 Amit Shah
    }
107 98b19252 Amit Shah
}
108 98b19252 Amit Shah
109 7edfe652 Markus Armbruster
static int virtconsole_initfn(VirtIOSerialPort *port)
110 98b19252 Amit Shah
{
111 7edfe652 Markus Armbruster
    VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
112 f82e35e3 Anthony Liguori
    VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port);
113 a15bb0d6 Markus Armbruster
114 f82e35e3 Anthony Liguori
    if (port->id == 0 && !k->is_console) {
115 7edfe652 Markus Armbruster
        error_report("Port number 0 on virtio-serial devices reserved for virtconsole devices for backward compatibility.");
116 7edfe652 Markus Armbruster
        return -1;
117 7edfe652 Markus Armbruster
    }
118 7edfe652 Markus Armbruster
119 98b19252 Amit Shah
    if (vcon->chr) {
120 98b19252 Amit Shah
        qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
121 98b19252 Amit Shah
                              vcon);
122 98b19252 Amit Shah
    }
123 cbe77b61 Amit Shah
124 7edfe652 Markus Armbruster
    return 0;
125 cbe77b61 Amit Shah
}
126 cbe77b61 Amit Shah
127 f82e35e3 Anthony Liguori
static Property virtconsole_properties[] = {
128 f82e35e3 Anthony Liguori
    DEFINE_PROP_CHR("chardev", VirtConsole, chr),
129 f82e35e3 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
130 f82e35e3 Anthony Liguori
};
131 f82e35e3 Anthony Liguori
132 f82e35e3 Anthony Liguori
static void virtconsole_class_init(ObjectClass *klass, void *data)
133 f82e35e3 Anthony Liguori
{
134 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
135 f82e35e3 Anthony Liguori
    VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass);
136 f82e35e3 Anthony Liguori
137 f82e35e3 Anthony Liguori
    k->is_console = true;
138 f82e35e3 Anthony Liguori
    k->init = virtconsole_initfn;
139 f82e35e3 Anthony Liguori
    k->have_data = flush_buf;
140 f82e35e3 Anthony Liguori
    k->guest_open = guest_open;
141 f82e35e3 Anthony Liguori
    k->guest_close = guest_close;
142 39bffca2 Anthony Liguori
    dc->props = virtconsole_properties;
143 f82e35e3 Anthony Liguori
}
144 f82e35e3 Anthony Liguori
145 39bffca2 Anthony Liguori
static TypeInfo virtconsole_info = {
146 39bffca2 Anthony Liguori
    .name          = "virtconsole",
147 39bffca2 Anthony Liguori
    .parent        = TYPE_VIRTIO_SERIAL_PORT,
148 39bffca2 Anthony Liguori
    .instance_size = sizeof(VirtConsole),
149 39bffca2 Anthony Liguori
    .class_init    = virtconsole_class_init,
150 98b19252 Amit Shah
};
151 98b19252 Amit Shah
152 98b19252 Amit Shah
static void virtconsole_register(void)
153 98b19252 Amit Shah
{
154 39bffca2 Anthony Liguori
    type_register_static(&virtconsole_info);
155 98b19252 Amit Shah
}
156 98b19252 Amit Shah
device_init(virtconsole_register)
157 b60c470b Amit Shah
158 f82e35e3 Anthony Liguori
static Property virtserialport_properties[] = {
159 f82e35e3 Anthony Liguori
    DEFINE_PROP_CHR("chardev", VirtConsole, chr),
160 f82e35e3 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
161 f82e35e3 Anthony Liguori
};
162 f82e35e3 Anthony Liguori
163 f82e35e3 Anthony Liguori
static void virtserialport_class_init(ObjectClass *klass, void *data)
164 f82e35e3 Anthony Liguori
{
165 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
166 f82e35e3 Anthony Liguori
    VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass);
167 f82e35e3 Anthony Liguori
168 f82e35e3 Anthony Liguori
    k->init = virtconsole_initfn;
169 f82e35e3 Anthony Liguori
    k->have_data = flush_buf;
170 f82e35e3 Anthony Liguori
    k->guest_open = guest_open;
171 f82e35e3 Anthony Liguori
    k->guest_close = guest_close;
172 39bffca2 Anthony Liguori
    dc->props = virtserialport_properties;
173 f82e35e3 Anthony Liguori
}
174 f82e35e3 Anthony Liguori
175 39bffca2 Anthony Liguori
static TypeInfo virtserialport_info = {
176 39bffca2 Anthony Liguori
    .name          = "virtserialport",
177 39bffca2 Anthony Liguori
    .parent        = TYPE_VIRTIO_SERIAL_PORT,
178 39bffca2 Anthony Liguori
    .instance_size = sizeof(VirtConsole),
179 39bffca2 Anthony Liguori
    .class_init    = virtserialport_class_init,
180 b60c470b Amit Shah
};
181 b60c470b Amit Shah
182 b60c470b Amit Shah
static void virtserialport_register(void)
183 b60c470b Amit Shah
{
184 39bffca2 Anthony Liguori
    type_register_static(&virtserialport_info);
185 b60c470b Amit Shah
}
186 b60c470b Amit Shah
device_init(virtserialport_register)