Annotation of qemu/hw/virtio-console.c, revision 1.1.1.8
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.8 ! root 30: if (!vcon->chr) {
! 31: /* If there's no backend, we can just say we consumed all data. */
! 32: return len;
! 33: }
! 34:
1.1.1.7 root 35: ret = qemu_chr_fe_write(vcon->chr, buf, len);
1.1.1.6 root 36: trace_virtio_console_flush_buf(port->id, len, ret);
37:
38: if (ret < 0) {
39: /*
40: * Ideally we'd get a better error code than just -1, but
41: * that's what the chardev interface gives us right now. If
42: * we had a finer-grained message, like -EPIPE, we could close
43: * this connection. Absent such error messages, the most we
44: * can do is to return 0 here.
45: *
46: * This will prevent stray -1 values to go to
47: * virtio-serial-bus.c and cause abort()s in
48: * do_flush_queued_data().
49: */
50: ret = 0;
51: }
52: return ret;
53: }
54:
55: /* Callback function that's called when the guest opens the port */
56: static void guest_open(VirtIOSerialPort *port)
57: {
58: VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
59:
1.1.1.8 ! root 60: if (!vcon->chr) {
! 61: return;
! 62: }
1.1.1.7 root 63: qemu_chr_fe_open(vcon->chr);
1.1.1.6 root 64: }
65:
66: /* Callback function that's called when the guest closes the port */
67: static void guest_close(VirtIOSerialPort *port)
68: {
69: VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
70:
1.1.1.8 ! root 71: if (!vcon->chr) {
! 72: return;
! 73: }
1.1.1.7 root 74: qemu_chr_fe_close(vcon->chr);
1.1 root 75: }
76:
1.1.1.4 root 77: /* Readiness of the guest to accept data on a port */
78: static int chr_can_read(void *opaque)
1.1 root 79: {
1.1.1.4 root 80: VirtConsole *vcon = opaque;
1.1 root 81:
1.1.1.4 root 82: return virtio_serial_guest_ready(&vcon->port);
1.1 root 83: }
84:
1.1.1.4 root 85: /* Send data from a char device over to the guest */
86: static void chr_read(void *opaque, const uint8_t *buf, int size)
1.1 root 87: {
1.1.1.4 root 88: VirtConsole *vcon = opaque;
1.1 root 89:
1.1.1.6 root 90: trace_virtio_console_chr_read(vcon->port.id, size);
1.1.1.4 root 91: virtio_serial_write(&vcon->port, buf, size);
1.1 root 92: }
93:
1.1.1.4 root 94: static void chr_event(void *opaque, int event)
1.1 root 95: {
1.1.1.4 root 96: VirtConsole *vcon = opaque;
97:
1.1.1.6 root 98: trace_virtio_console_chr_event(vcon->port.id, event);
1.1.1.4 root 99: switch (event) {
1.1.1.5 root 100: case CHR_EVENT_OPENED:
1.1.1.4 root 101: virtio_serial_open(&vcon->port);
102: break;
103: case CHR_EVENT_CLOSED:
104: virtio_serial_close(&vcon->port);
105: break;
1.1 root 106: }
107: }
108:
1.1.1.6 root 109: static int virtconsole_initfn(VirtIOSerialPort *port)
1.1 root 110: {
1.1.1.6 root 111: VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
1.1.1.8 ! root 112: VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port);
1.1.1.6 root 113:
1.1.1.8 ! root 114: if (port->id == 0 && !k->is_console) {
1.1.1.6 root 115: error_report("Port number 0 on virtio-serial devices reserved for virtconsole devices for backward compatibility.");
116: return -1;
117: }
1.1.1.4 root 118:
119: if (vcon->chr) {
120: qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
121: vcon);
122: }
1.1 root 123:
1.1.1.6 root 124: return 0;
1.1.1.5 root 125: }
126:
1.1.1.8 ! root 127: static Property virtconsole_properties[] = {
! 128: DEFINE_PROP_CHR("chardev", VirtConsole, chr),
! 129: DEFINE_PROP_END_OF_LIST(),
! 130: };
1.1 root 131:
1.1.1.8 ! root 132: static void virtconsole_class_init(ObjectClass *klass, void *data)
! 133: {
! 134: DeviceClass *dc = DEVICE_CLASS(klass);
! 135: VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass);
1.1 root 136:
1.1.1.8 ! root 137: k->is_console = true;
! 138: k->init = virtconsole_initfn;
! 139: k->have_data = flush_buf;
! 140: k->guest_open = guest_open;
! 141: k->guest_close = guest_close;
! 142: dc->props = virtconsole_properties;
! 143: }
! 144:
! 145: static TypeInfo virtconsole_info = {
! 146: .name = "virtconsole",
! 147: .parent = TYPE_VIRTIO_SERIAL_PORT,
! 148: .instance_size = sizeof(VirtConsole),
! 149: .class_init = virtconsole_class_init,
! 150: };
1.1 root 151:
1.1.1.8 ! root 152: static Property virtserialport_properties[] = {
! 153: DEFINE_PROP_CHR("chardev", VirtConsole, chr),
! 154: DEFINE_PROP_END_OF_LIST(),
1.1.1.4 root 155: };
156:
1.1.1.8 ! root 157: static void virtserialport_class_init(ObjectClass *klass, void *data)
1.1.1.4 root 158: {
1.1.1.8 ! root 159: DeviceClass *dc = DEVICE_CLASS(klass);
! 160: VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass);
1.1.1.4 root 161:
1.1.1.8 ! root 162: k->init = virtconsole_initfn;
! 163: k->have_data = flush_buf;
! 164: k->guest_open = guest_open;
! 165: k->guest_close = guest_close;
! 166: dc->props = virtserialport_properties;
! 167: }
! 168:
! 169: static TypeInfo virtserialport_info = {
! 170: .name = "virtserialport",
! 171: .parent = TYPE_VIRTIO_SERIAL_PORT,
! 172: .instance_size = sizeof(VirtConsole),
! 173: .class_init = virtserialport_class_init,
1.1.1.4 root 174: };
1.1 root 175:
1.1.1.8 ! root 176: static void virtconsole_register_types(void)
1.1.1.4 root 177: {
1.1.1.8 ! root 178: type_register_static(&virtconsole_info);
! 179: type_register_static(&virtserialport_info);
1.1 root 180: }
1.1.1.8 ! root 181:
! 182: type_init(virtconsole_register_types)
unix.superglobalmegacorp.com