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

1.1       root        1: /*
                      2:  * Virtio Console Device
                      3:  *
                      4:  * Copyright IBM, Corp. 2008
                      5:  *
                      6:  * Authors:
                      7:  *  Christian Ehrhardt <ehrhardt@linux.vnet.ibm.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: 
                     14: #include "hw.h"
                     15: #include "qemu-char.h"
                     16: #include "virtio.h"
                     17: #include "virtio-console.h"
                     18: 
                     19: 
                     20: typedef struct VirtIOConsole
                     21: {
                     22:     VirtIODevice vdev;
                     23:     VirtQueue *ivq, *dvq;
                     24:     CharDriverState *chr;
                     25: } VirtIOConsole;
                     26: 
                     27: static VirtIOConsole *to_virtio_console(VirtIODevice *vdev)
                     28: {
                     29:     return (VirtIOConsole *)vdev;
                     30: }
                     31: 
                     32: static void virtio_console_handle_output(VirtIODevice *vdev, VirtQueue *vq)
                     33: {
                     34:     VirtIOConsole *s = to_virtio_console(vdev);
                     35:     VirtQueueElement elem;
                     36: 
                     37:     while (virtqueue_pop(vq, &elem)) {
                     38:         ssize_t len = 0;
                     39:         int d;
                     40: 
                     41:         for (d=0; d < elem.out_num; d++)
                     42:             len += qemu_chr_write(s->chr, elem.out_sg[d].iov_base,elem.out_sg[d].iov_len);
                     43:         virtqueue_push(vq, &elem, len);
                     44:         virtio_notify(vdev, vq);
                     45:     }
                     46: }
                     47: 
                     48: static void virtio_console_handle_input(VirtIODevice *vdev, VirtQueue *vq)
                     49: {
                     50: }
                     51: 
                     52: static uint32_t virtio_console_get_features(VirtIODevice *vdev)
                     53: {
                     54:     return 0;
                     55: }
                     56: 
                     57: static int vcon_can_read(void *opaque)
                     58: {
                     59:     VirtIOConsole *s = (VirtIOConsole *) opaque;
                     60: 
                     61:     if (!virtio_queue_ready(s->ivq) ||
                     62:         !(s->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK) ||
                     63:         virtio_queue_empty(s->ivq))
                     64:         return 0;
                     65: 
                     66:     /* current implementations have a page sized buffer.
                     67:      * We fall back to a one byte per read if there is not enough room.
                     68:      * It would be cool to have a function that returns the available byte
                     69:      * instead of checking for a limit */
                     70:     if (virtqueue_avail_bytes(s->ivq, TARGET_PAGE_SIZE, 0))
                     71:         return TARGET_PAGE_SIZE;
                     72:     if (virtqueue_avail_bytes(s->ivq, 1, 0))
                     73:         return 1;
                     74:     return 0;
                     75: }
                     76: 
                     77: static void vcon_read(void *opaque, const uint8_t *buf, int size)
                     78: {
                     79:     VirtIOConsole *s = (VirtIOConsole *) opaque;
                     80:     VirtQueueElement elem;
                     81:     int offset = 0;
                     82: 
                     83:     /* The current kernel implementation has only one outstanding input
                     84:      * buffer of PAGE_SIZE. Nevertheless, this function is prepared to
                     85:      * handle multiple buffers with multiple sg element for input */
                     86:     while (offset < size) {
                     87:         int i = 0;
                     88:         if (!virtqueue_pop(s->ivq, &elem))
                     89:                 break;
                     90:         while (offset < size && i < elem.in_num) {
                     91:             int len = MIN(elem.in_sg[i].iov_len, size - offset);
                     92:             memcpy(elem.in_sg[i].iov_base, buf + offset, len);
                     93:             offset += len;
                     94:             i++;
                     95:         }
                     96:         virtqueue_push(s->ivq, &elem, size);
                     97:     }
                     98:     virtio_notify(&s->vdev, s->ivq);
                     99: }
                    100: 
                    101: static void vcon_event(void *opaque, int event)
                    102: {
                    103:     /* we will ignore any event for the time being */
                    104: }
                    105: 
                    106: static void virtio_console_save(QEMUFile *f, void *opaque)
                    107: {
                    108:     VirtIOConsole *s = opaque;
                    109: 
                    110:     virtio_save(&s->vdev, f);
                    111: }
                    112: 
                    113: static int virtio_console_load(QEMUFile *f, void *opaque, int version_id)
                    114: {
                    115:     VirtIOConsole *s = opaque;
                    116: 
                    117:     if (version_id != 1)
                    118:         return -EINVAL;
                    119: 
                    120:     virtio_load(&s->vdev, f);
                    121:     return 0;
                    122: }
                    123: 
                    124: void *virtio_console_init(PCIBus *bus, CharDriverState *chr)
                    125: {
                    126:     VirtIOConsole *s;
                    127: 
                    128:     s = (VirtIOConsole *)virtio_init_pci(bus, "virtio-console",
                    129:                                          PCI_VENDOR_ID_REDHAT_QUMRANET,
                    130:                                          PCI_DEVICE_ID_VIRTIO_CONSOLE,
                    131:                                          PCI_VENDOR_ID_REDHAT_QUMRANET,
                    132:                                          VIRTIO_ID_CONSOLE,
                    133:                                          PCI_CLASS_DISPLAY_OTHER, 0x00,
                    134:                                          0, sizeof(VirtIOConsole));
                    135:     if (s == NULL)
                    136:         return NULL;
                    137: 
                    138:     s->vdev.get_features = virtio_console_get_features;
                    139: 
                    140:     s->ivq = virtio_add_queue(&s->vdev, 128, virtio_console_handle_input);
                    141:     s->dvq = virtio_add_queue(&s->vdev, 128, virtio_console_handle_output);
                    142: 
                    143:     s->chr = chr;
                    144:     qemu_chr_add_handlers(chr, vcon_can_read, vcon_read, vcon_event, s);
                    145: 
                    146:     register_savevm("virtio-console", -1, 1, virtio_console_save, virtio_console_load, s);
                    147: 
                    148:     return &s->vdev;
                    149: }

unix.superglobalmegacorp.com