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