| /* | |
| * Virtio Serial / Console Support | |
| * | |
| * Copyright IBM, Corp. 2008 | |
| * Copyright Red Hat, Inc. 2009, 2010 | |
| * | |
| * Authors: | |
| * Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com> | |
| * Amit Shah <amit.shah@redhat.com> | |
| * | |
| * This work is licensed under the terms of the GNU GPL, version 2. See | |
| * the COPYING file in the top-level directory. | |
| * | |
| */ | |
| #ifndef QEMU_VIRTIO_SERIAL_H | |
| #define QEMU_VIRTIO_SERIAL_H | |
| #include "standard-headers/linux/virtio_console.h" | |
| #include "hw/virtio/virtio.h" | |
| #include "qom/object.h" | |
| struct virtio_serial_conf { | |
| /* Max. number of ports we can have for a virtio-serial device */ | |
| uint32_t max_virtserial_ports; | |
| }; | |
| #define TYPE_VIRTIO_SERIAL_PORT "virtio-serial-port" | |
| OBJECT_DECLARE_TYPE(VirtIOSerialPort, VirtIOSerialPortClass, | |
| VIRTIO_SERIAL_PORT) | |
| #define TYPE_VIRTIO_SERIAL "virtio-serial-device" | |
| OBJECT_DECLARE_SIMPLE_TYPE(VirtIOSerial, VIRTIO_SERIAL) | |
| #define TYPE_VIRTIO_SERIAL_BUS "virtio-serial-bus" | |
| OBJECT_DECLARE_SIMPLE_TYPE(VirtIOSerialBus, VIRTIO_SERIAL_BUS) | |
| struct VirtIOSerialPortClass { | |
| DeviceClass parent_class; | |
| /* Is this a device that binds with hvc in the guest? */ | |
| bool is_console; | |
| /* | |
| * The per-port (or per-app) realize function that's called when a | |
| * new device is found on the bus. | |
| */ | |
| DeviceRealize realize; | |
| /* | |
| * Per-port unrealize function that's called when a port gets | |
| * hot-unplugged or removed. | |
| */ | |
| DeviceUnrealize unrealize; | |
| /* Callbacks for guest events */ | |
| /* Guest opened/closed device. */ | |
| void (*set_guest_connected)(VirtIOSerialPort *port, int guest_connected); | |
| /* Enable/disable backend for virtio serial port */ | |
| void (*enable_backend)(VirtIOSerialPort *port, bool enable); | |
| /* Guest is now ready to accept data (virtqueues set up). */ | |
| void (*guest_ready)(VirtIOSerialPort *port); | |
| /* | |
| * Guest has enqueued a buffer for the host to write into. | |
| * Called each time a buffer is enqueued by the guest; | |
| * irrespective of whether there already were free buffers the | |
| * host could have consumed. | |
| * | |
| * This is dependent on both the guest and host end being | |
| * connected. | |
| */ | |
| void (*guest_writable)(VirtIOSerialPort *port); | |
| /* | |
| * Guest wrote some data to the port. This data is handed over to | |
| * the app via this callback. The app can return a size less than | |
| * 'len'. In this case, throttling will be enabled for this port. | |
| */ | |
| ssize_t (*have_data)(VirtIOSerialPort *port, const uint8_t *buf, | |
| ssize_t len); | |
| }; | |
| /* | |
| * This is the state that's shared between all the ports. Some of the | |
| * state is configurable via command-line options. Some of it can be | |
| * set by individual devices in their initfn routines. Some of the | |
| * state is set by the generic qdev device init routine. | |
| */ | |
| struct VirtIOSerialPort { | |
| DeviceState dev; | |
| QTAILQ_ENTRY(VirtIOSerialPort) next; | |
| /* | |
| * This field gives us the virtio device as well as the qdev bus | |
| * that we are associated with | |
| */ | |
| VirtIOSerial *vser; | |
| VirtQueue *ivq, *ovq; | |
| /* | |
| * This name is sent to the guest and exported via sysfs. | |
| * The guest could create symlinks based on this information. | |
| * The name is in the reverse fqdn format, like org.qemu.console.0 | |
| */ | |
| char *name; | |
| /* | |
| * This id helps identify ports between the guest and the host. | |
| * The guest sends a "header" with this id with each data packet | |
| * that it sends and the host can then find out which associated | |
| * device to send out this data to | |
| */ | |
| uint32_t id; | |
| /* | |
| * This is the elem that we pop from the virtqueue. A slow | |
| * backend that consumes guest data (e.g. the file backend for | |
| * qemu chardevs) can cause the guest to block till all the output | |
| * is flushed. This isn't desired, so we keep a note of the last | |
| * element popped and continue consuming it once the backend | |
| * becomes writable again. | |
| */ | |
| VirtQueueElement *elem; | |
| /* | |
| * The index and the offset into the iov buffer that was popped in | |
| * elem above. | |
| */ | |
| uint32_t iov_idx; | |
| uint64_t iov_offset; | |
| /* | |
| * When unthrottling we use a bottom-half to call flush_queued_data. | |
| */ | |
| QEMUBH *bh; | |
| /* Is the corresponding guest device open? */ | |
| bool guest_connected; | |
| /* Is this device open for IO on the host? */ | |
| bool host_connected; | |
| /* Do apps not want to receive data? */ | |
| bool throttled; | |
| /* Terminal size reported to the guest. Only used for consoles. */ | |
| uint16_t cols, rows; | |
| }; | |
| /* The virtio-serial bus on top of which the ports will ride as devices */ | |
| struct VirtIOSerialBus { | |
| BusState qbus; | |
| /* This is the parent device that provides the bus for ports. */ | |
| VirtIOSerial *vser; | |
| /* The maximum number of ports that can ride on top of this bus */ | |
| uint32_t max_nr_ports; | |
| }; | |
| typedef struct VirtIOSerialPostLoad { | |
| QEMUTimer *timer; | |
| uint32_t nr_active_ports; | |
| struct { | |
| VirtIOSerialPort *port; | |
| uint8_t host_connected; | |
| } *connected; | |
| } VirtIOSerialPostLoad; | |
| struct VirtIOSerial { | |
| VirtIODevice parent_obj; | |
| VirtQueue *c_ivq, *c_ovq; | |
| /* Arrays of ivqs and ovqs: one per port */ | |
| VirtQueue **ivqs, **ovqs; | |
| VirtIOSerialBus bus; | |
| QTAILQ_HEAD(, VirtIOSerialPort) ports; | |
| QLIST_ENTRY(VirtIOSerial) next; | |
| /* bitmap for identifying active ports */ | |
| uint32_t *ports_map; | |
| struct VirtIOSerialPostLoad *post_load; | |
| virtio_serial_conf serial; | |
| uint64_t host_features; | |
| }; | |
| /* Interface to the virtio-serial bus */ | |
| /* | |
| * Open a connection to the port | |
| * Returns 0 on success (always). | |
| */ | |
| int virtio_serial_open(VirtIOSerialPort *port); | |
| /* | |
| * Close the connection to the port | |
| * Returns 0 on success (always). | |
| */ | |
| int virtio_serial_close(VirtIOSerialPort *port); | |
| /* | |
| * Send data to Guest | |
| */ | |
| ssize_t virtio_serial_write(VirtIOSerialPort *port, const uint8_t *buf, | |
| size_t size); | |
| /* | |
| * Query whether a guest is ready to receive data. | |
| */ | |
| size_t virtio_serial_guest_ready(VirtIOSerialPort *port); | |
| /* | |
| * Flow control: Ports can signal to the virtio-serial core to stop | |
| * sending data or re-start sending data, depending on the 'throttle' | |
| * value here. | |
| */ | |
| void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle); | |
| void virtio_serial_resize_console(VirtIOSerialPort *port, | |
| uint16_t cols, uint16_t rows); | |
| #endif |