File:  [Qemu by Fabrice Bellard] / qemu / hw / virtio-console.c
Revision 1.1.1.8 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 19:49:49 2018 UTC (3 years ago) by root
Branches: qemu, MAIN
CVS tags: qemu1101, HEAD
qemu 1.1.1

    1: /*
    2:  * Virtio Console and Generic Serial Port Devices
    3:  *
    4:  * Copyright Red Hat, Inc. 2009, 2010
    5:  *
    6:  * Authors:
    7:  *  Amit Shah <amit.shah@redhat.com>
    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"
   14: #include "qemu-error.h"
   15: #include "trace.h"
   16: #include "virtio-serial.h"
   17: 
   18: typedef struct VirtConsole {
   19:     VirtIOSerialPort port;
   20:     CharDriverState *chr;
   21: } VirtConsole;
   22: 
   23: 
   24: /* Callback function that's called when the guest sends us data */
   25: static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
   26: {
   27:     VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
   28:     ssize_t ret;
   29: 
   30:     if (!vcon->chr) {
   31:         /* If there's no backend, we can just say we consumed all data. */
   32:         return len;
   33:     }
   34: 
   35:     ret = qemu_chr_fe_write(vcon->chr, buf, len);
   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: 
   60:     if (!vcon->chr) {
   61:         return;
   62:     }
   63:     qemu_chr_fe_open(vcon->chr);
   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: 
   71:     if (!vcon->chr) {
   72:         return;
   73:     }
   74:     qemu_chr_fe_close(vcon->chr);
   75: }
   76: 
   77: /* Readiness of the guest to accept data on a port */
   78: static int chr_can_read(void *opaque)
   79: {
   80:     VirtConsole *vcon = opaque;
   81: 
   82:     return virtio_serial_guest_ready(&vcon->port);
   83: }
   84: 
   85: /* Send data from a char device over to the guest */
   86: static void chr_read(void *opaque, const uint8_t *buf, int size)
   87: {
   88:     VirtConsole *vcon = opaque;
   89: 
   90:     trace_virtio_console_chr_read(vcon->port.id, size);
   91:     virtio_serial_write(&vcon->port, buf, size);
   92: }
   93: 
   94: static void chr_event(void *opaque, int event)
   95: {
   96:     VirtConsole *vcon = opaque;
   97: 
   98:     trace_virtio_console_chr_event(vcon->port.id, event);
   99:     switch (event) {
  100:     case CHR_EVENT_OPENED:
  101:         virtio_serial_open(&vcon->port);
  102:         break;
  103:     case CHR_EVENT_CLOSED:
  104:         virtio_serial_close(&vcon->port);
  105:         break;
  106:     }
  107: }
  108: 
  109: static int virtconsole_initfn(VirtIOSerialPort *port)
  110: {
  111:     VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
  112:     VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port);
  113: 
  114:     if (port->id == 0 && !k->is_console) {
  115:         error_report("Port number 0 on virtio-serial devices reserved for virtconsole devices for backward compatibility.");
  116:         return -1;
  117:     }
  118: 
  119:     if (vcon->chr) {
  120:         qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
  121:                               vcon);
  122:     }
  123: 
  124:     return 0;
  125: }
  126: 
  127: static Property virtconsole_properties[] = {
  128:     DEFINE_PROP_CHR("chardev", VirtConsole, chr),
  129:     DEFINE_PROP_END_OF_LIST(),
  130: };
  131: 
  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);
  136: 
  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: };
  151: 
  152: static Property virtserialport_properties[] = {
  153:     DEFINE_PROP_CHR("chardev", VirtConsole, chr),
  154:     DEFINE_PROP_END_OF_LIST(),
  155: };
  156: 
  157: static void virtserialport_class_init(ObjectClass *klass, void *data)
  158: {
  159:     DeviceClass *dc = DEVICE_CLASS(klass);
  160:     VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass);
  161: 
  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,
  174: };
  175: 
  176: static void virtconsole_register_types(void)
  177: {
  178:     type_register_static(&virtconsole_info);
  179:     type_register_static(&virtserialport_info);
  180: }
  181: 
  182: type_init(virtconsole_register_types)

unix.superglobalmegacorp.com