open -> new rename fallout
[qemu/aliguori.git] / hw / virtio-console.c
blobe5e64ac113e3dfeef894e97c516cf9d323c34152
1 /*
2 * Virtio Console and Generic Serial Port Devices
4 * Copyright Red Hat, Inc. 2009, 2010
6 * Authors:
7 * Amit Shah <amit.shah@redhat.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.
13 #include "qemu-char.h"
14 #include "qemu-error.h"
15 #include "trace.h"
16 #include "virtio-serial.h"
18 typedef struct VirtConsole {
19 VirtIOSerialPort port;
20 CharDriverState *chr;
21 } VirtConsole;
23 static void virtconsole_update_handlers(VirtConsole *vcon);
25 /* Callback function that's called when the guest sends us data */
26 static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
28 VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
29 ssize_t ret;
31 ret = qemu_chr_fe_write(vcon->chr, buf, len);
32 trace_virtio_console_flush_buf(port->id, len, ret);
34 if (ret < 0) {
36 * Ideally we'd get a better error code than just -1, but
37 * that's what the chardev interface gives us right now. If
38 * we had a finer-grained message, like -EPIPE, we could close
39 * this connection. Absent such error messages, the most we
40 * can do is to return 0 here.
42 * This will prevent stray -1 values to go to
43 * virtio-serial-bus.c and cause abort()s in
44 * do_flush_queued_data().
46 ret = 0;
48 return ret;
51 /* Callback function that's called when the guest opens the port */
52 static void guest_open(VirtIOSerialPort *port)
54 VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
56 qemu_chr_fe_open(vcon->chr);
57 virtconsole_update_handlers(vcon);
60 /* Callback function that's called when the guest closes the port */
61 static void guest_close(VirtIOSerialPort *port)
63 VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
65 qemu_chr_fe_close(vcon->chr);
68 /* Send data from a char device over to the guest */
69 static void chr_read_handler(void *opaque)
71 VirtConsole *vcon = opaque;
72 uint8_t buf[4096];
73 int size;
75 size = virtio_serial_guest_ready(&vcon->port);
76 size = MIN(size, sizeof(buf));
77 size = qemu_chr_fe_read(vcon->chr, buf, size);
79 trace_virtio_console_chr_read(vcon->port.id, size);
80 virtio_serial_write(&vcon->port, buf, size);
83 static int chr_event(void *opaque, int event, void *data)
85 VirtConsole *vcon = opaque;
87 trace_virtio_console_chr_event(vcon->port.id, event);
88 switch (event) {
89 case CHR_EVENT_OPENED:
90 virtio_serial_open(&vcon->port);
91 break;
92 case CHR_EVENT_CLOSED:
93 virtio_serial_close(&vcon->port);
94 break;
97 return 0;
100 static void virtconsole_update_handlers(VirtConsole *vcon)
102 if (virtio_serial_guest_ready(&vcon->port) > 0) {
103 qemu_chr_fe_set_handlers(vcon->chr, chr_read_handler, NULL, chr_event,
104 vcon);
105 } else {
106 qemu_chr_fe_set_handlers(vcon->chr, NULL, NULL, chr_event,
107 vcon);
111 static int virtconsole_initfn(VirtIOSerialPort *port)
113 VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
114 VirtIOSerialPortInfo *info = DO_UPCAST(VirtIOSerialPortInfo, qdev,
115 vcon->port.dev.info);
117 if (port->id == 0 && !info->is_console) {
118 error_report("Port number 0 on virtio-serial devices reserved for virtconsole devices for backward compatibility.");
119 return -1;
122 if (vcon->chr) {
123 /* FIXME we need a notifier for when guest ready changes */
124 info->have_data = flush_buf;
125 info->guest_open = guest_open;
126 info->guest_close = guest_close;
129 return 0;
132 static int virtconsole_exitfn(VirtIOSerialPort *port)
134 VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
136 if (vcon->chr) {
137 qemu_chr_fe_close(vcon->chr);
140 return 0;
143 static VirtIOSerialPortInfo virtconsole_info = {
144 .qdev.name = "virtconsole",
145 .qdev.size = sizeof(VirtConsole),
146 .is_console = true,
147 .init = virtconsole_initfn,
148 .exit = virtconsole_exitfn,
149 .qdev.props = (Property[]) {
150 DEFINE_PROP_CHR("chardev", VirtConsole, chr),
151 DEFINE_PROP_END_OF_LIST(),
155 static void virtconsole_register(void)
157 virtio_serial_port_qdev_register(&virtconsole_info);
159 device_init(virtconsole_register)
161 static VirtIOSerialPortInfo virtserialport_info = {
162 .qdev.name = "virtserialport",
163 .qdev.size = sizeof(VirtConsole),
164 .init = virtconsole_initfn,
165 .exit = virtconsole_exitfn,
166 .qdev.props = (Property[]) {
167 DEFINE_PROP_CHR("chardev", VirtConsole, chr),
168 DEFINE_PROP_END_OF_LIST(),
172 static void virtserialport_register(void)
174 virtio_serial_port_qdev_register(&virtserialport_info);
176 device_init(virtserialport_register)