Annotation of qemu/hw/virtio-console.c, revision 1.1.1.7
1.1 root 1: /*
1.1.1.4 root 2: * Virtio Console and Generic Serial Port Devices
1.1 root 3: *
1.1.1.4 root 4: * Copyright Red Hat, Inc. 2009, 2010
1.1 root 5: *
6: * Authors:
1.1.1.4 root 7: * Amit Shah <amit.shah@redhat.com>
1.1 root 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: #include "qemu-char.h"
1.1.1.6 root 14: #include "qemu-error.h"
15: #include "trace.h"
1.1.1.4 root 16: #include "virtio-serial.h"
1.1 root 17:
1.1.1.4 root 18: typedef struct VirtConsole {
19: VirtIOSerialPort port;
1.1 root 20: CharDriverState *chr;
1.1.1.4 root 21: } VirtConsole;
1.1 root 22:
23:
1.1.1.4 root 24: /* Callback function that's called when the guest sends us data */
1.1.1.5 root 25: static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
1.1 root 26: {
1.1.1.4 root 27: VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
1.1.1.6 root 28: ssize_t ret;
1.1 root 29:
1.1.1.7 ! root 30: ret = qemu_chr_fe_write(vcon->chr, buf, len);
1.1.1.6 root 31: trace_virtio_console_flush_buf(port->id, len, ret);
32:
33: if (ret < 0) {
34: /*
35: * Ideally we'd get a better error code than just -1, but
36: * that's what the chardev interface gives us right now. If
37: * we had a finer-grained message, like -EPIPE, we could close
38: * this connection. Absent such error messages, the most we
39: * can do is to return 0 here.
40: *
41: * This will prevent stray -1 values to go to
42: * virtio-serial-bus.c and cause abort()s in
43: * do_flush_queued_data().
44: */
45: ret = 0;
46: }
47: return ret;
48: }
49:
50: /* Callback function that's called when the guest opens the port */
51: static void guest_open(VirtIOSerialPort *port)
52: {
53: VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
54:
1.1.1.7 ! root 55: qemu_chr_fe_open(vcon->chr);
1.1.1.6 root 56: }
57:
58: /* Callback function that's called when the guest closes the port */
59: static void guest_close(VirtIOSerialPort *port)
60: {
61: VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
62:
1.1.1.7 ! root 63: qemu_chr_fe_close(vcon->chr);
1.1 root 64: }
65:
1.1.1.4 root 66: /* Readiness of the guest to accept data on a port */
67: static int chr_can_read(void *opaque)
1.1 root 68: {
1.1.1.4 root 69: VirtConsole *vcon = opaque;
1.1 root 70:
1.1.1.4 root 71: return virtio_serial_guest_ready(&vcon->port);
1.1 root 72: }
73:
1.1.1.4 root 74: /* Send data from a char device over to the guest */
75: static void chr_read(void *opaque, const uint8_t *buf, int size)
1.1 root 76: {
1.1.1.4 root 77: VirtConsole *vcon = opaque;
1.1 root 78:
1.1.1.6 root 79: trace_virtio_console_chr_read(vcon->port.id, size);
1.1.1.4 root 80: virtio_serial_write(&vcon->port, buf, size);
1.1 root 81: }
82:
1.1.1.4 root 83: static void chr_event(void *opaque, int event)
1.1 root 84: {
1.1.1.4 root 85: VirtConsole *vcon = opaque;
86:
1.1.1.6 root 87: trace_virtio_console_chr_event(vcon->port.id, event);
1.1.1.4 root 88: switch (event) {
1.1.1.5 root 89: case CHR_EVENT_OPENED:
1.1.1.4 root 90: virtio_serial_open(&vcon->port);
91: break;
92: case CHR_EVENT_CLOSED:
93: virtio_serial_close(&vcon->port);
94: break;
1.1 root 95: }
96: }
97:
1.1.1.6 root 98: static int virtconsole_initfn(VirtIOSerialPort *port)
1.1 root 99: {
1.1.1.6 root 100: VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
101: VirtIOSerialPortInfo *info = DO_UPCAST(VirtIOSerialPortInfo, qdev,
102: vcon->port.dev.info);
103:
104: if (port->id == 0 && !info->is_console) {
105: error_report("Port number 0 on virtio-serial devices reserved for virtconsole devices for backward compatibility.");
106: return -1;
107: }
1.1.1.4 root 108:
109: if (vcon->chr) {
110: qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
111: vcon);
1.1.1.6 root 112: info->have_data = flush_buf;
113: info->guest_open = guest_open;
114: info->guest_close = guest_close;
1.1.1.4 root 115: }
1.1 root 116:
1.1.1.6 root 117: return 0;
1.1.1.5 root 118: }
119:
1.1.1.6 root 120: static int virtconsole_exitfn(VirtIOSerialPort *port)
1.1 root 121: {
1.1.1.4 root 122: VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
1.1 root 123:
1.1.1.4 root 124: if (vcon->chr) {
1.1.1.6 root 125: /*
126: * Instead of closing the chardev, free it so it can be used
127: * for other purposes.
128: */
129: qemu_chr_add_handlers(vcon->chr, NULL, NULL, NULL, NULL);
1.1.1.4 root 130: }
1.1 root 131:
132: return 0;
133: }
134:
1.1.1.4 root 135: static VirtIOSerialPortInfo virtconsole_info = {
136: .qdev.name = "virtconsole",
137: .qdev.size = sizeof(VirtConsole),
1.1.1.6 root 138: .is_console = true,
1.1.1.4 root 139: .init = virtconsole_initfn,
140: .exit = virtconsole_exitfn,
141: .qdev.props = (Property[]) {
142: DEFINE_PROP_CHR("chardev", VirtConsole, chr),
143: DEFINE_PROP_END_OF_LIST(),
144: },
145: };
146:
147: static void virtconsole_register(void)
148: {
149: virtio_serial_port_qdev_register(&virtconsole_info);
150: }
151: device_init(virtconsole_register)
152:
153: static VirtIOSerialPortInfo virtserialport_info = {
154: .qdev.name = "virtserialport",
155: .qdev.size = sizeof(VirtConsole),
1.1.1.6 root 156: .init = virtconsole_initfn,
1.1.1.4 root 157: .exit = virtconsole_exitfn,
158: .qdev.props = (Property[]) {
159: DEFINE_PROP_CHR("chardev", VirtConsole, chr),
160: DEFINE_PROP_END_OF_LIST(),
161: },
162: };
1.1 root 163:
1.1.1.4 root 164: static void virtserialport_register(void)
165: {
166: virtio_serial_port_qdev_register(&virtserialport_info);
1.1 root 167: }
1.1.1.4 root 168: device_init(virtserialport_register)
unix.superglobalmegacorp.com