Annotation of qemu/hw/virtio-console.c, revision 1.1.1.6

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.6 ! root       30:     ret = qemu_chr_write(vcon->chr, buf, len);
        !            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: 
        !            55:     qemu_chr_guest_open(vcon->chr);
        !            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: 
        !            63:     qemu_chr_guest_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