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