#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu/iov.h"
+#include "qemu/main-loop.h"
+#include "qemu/module.h"
+#include "migration/qemu-file-types.h"
#include "monitor/monitor.h"
#include "qemu/error-report.h"
#include "qemu/queue.h"
+#include "hw/qdev-properties.h"
#include "hw/sysbus.h"
#include "trace.h"
#include "hw/virtio/virtio-serial.h"
VirtIOSerial *vser = VIRTIO_SERIAL(vdev);
struct virtio_console_config *config =
(struct virtio_console_config *)config_data;
- uint8_t emerg_wr_lo = le32_to_cpu(config->emerg_wr);
VirtIOSerialPort *port = find_first_connected_console(vser);
VirtIOSerialPortClass *vsc;
+ uint8_t emerg_wr_lo;
- if (!config->emerg_wr) {
+ if (!virtio_has_feature(vser->host_features,
+ VIRTIO_CONSOLE_F_EMERG_WRITE) || !config->emerg_wr) {
return;
}
+
+ emerg_wr_lo = le32_to_cpu(config->emerg_wr);
/* Make sure we don't misdetect an emergency write when the guest
* does a short config write after an emergency write. */
config->emerg_wr = 0;
if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
guest_reset(vser);
}
+
+ QTAILQ_FOREACH(port, &vser->ports, next) {
+ VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
+ if (vsc->enable_backend) {
+ vsc->enable_backend(port, vdev->vm_running);
+ }
+ }
}
static void vser_reset(VirtIODevice *vdev)
/* The config space (ignored on the far end in current versions) */
get_config(vdev, (uint8_t *)&config);
- qemu_put_be16s(f, &config.cols);
- qemu_put_be16s(f, &config.rows);
- qemu_put_be32s(f, &config.max_nr_ports);
+ qemu_put_be16(f, config.cols);
+ qemu_put_be16(f, config.rows);
+ qemu_put_be32(f, config.max_nr_ports);
/* The ports map */
max_nr_ports = s->serial.max_virtserial_ports;
- for (i = 0; i < (max_nr_ports + 31) / 32; i++) {
+ for (i = 0; i < DIV_ROUND_UP(max_nr_ports, 32); i++) {
qemu_put_be32s(f, &s->ports_map[i]);
}
qemu_put_byte(f, port->guest_connected);
qemu_put_byte(f, port->host_connected);
- elem_popped = 0;
+ elem_popped = 0;
if (port->elem) {
elem_popped = 1;
}
if (elem_popped) {
qemu_put_be32s(f, &port->iov_idx);
qemu_put_be64s(f, &port->iov_offset);
- qemu_put_virtqueue_element(f, port->elem);
+ qemu_put_virtqueue_element(vdev, f, port->elem);
}
}
}
}
}
g_free(s->post_load->connected);
- timer_del(s->post_load->timer);
timer_free(s->post_load->timer);
g_free(s->post_load);
s->post_load = NULL;
qemu_get_be32s(f, &tmp);
max_nr_ports = s->serial.max_virtserial_ports;
- for (i = 0; i < (max_nr_ports + 31) / 32; i++) {
+ for (i = 0; i < DIV_ROUND_UP(max_nr_ports, 32); i++) {
qemu_get_be32s(f, &ports_map);
if (ports_map != s->ports_map[i]) {
DEFINE_PROP_END_OF_LIST()
};
-#define TYPE_VIRTIO_SERIAL_BUS "virtio-serial-bus"
-#define VIRTIO_SERIAL_BUS(obj) \
- OBJECT_CHECK(VirtIOSerialBus, (obj), TYPE_VIRTIO_SERIAL_BUS)
-
static void virtser_bus_class_init(ObjectClass *klass, void *data)
{
BusClass *k = BUS_CLASS(klass);
unsigned int i, max_nr_ports;
max_nr_ports = vser->serial.max_virtserial_ports;
- for (i = 0; i < (max_nr_ports + 31) / 32; i++) {
+ for (i = 0; i < DIV_ROUND_UP(max_nr_ports, 32); i++) {
uint32_t map, zeroes;
map = vser->ports_map[i];
Error *err = NULL;
port->vser = bus->vser;
- port->bh = qemu_bh_new(flush_queued_data_bh, port);
assert(vsc->have_data);
return;
}
+ port->bh = qemu_bh_new(flush_queued_data_bh, port);
port->elem = NULL;
}
virtio_notify_config(VIRTIO_DEVICE(hotplug_dev));
}
-static void virtser_port_device_unrealize(DeviceState *dev, Error **errp)
+static void virtser_port_device_unrealize(DeviceState *dev)
{
VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev);
VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(dev);
QTAILQ_REMOVE(&vser->ports, port, next);
if (vsc->unrealize) {
- vsc->unrealize(dev, errp);
+ vsc->unrealize(dev);
}
}
/* Spawn a new virtio-serial bus on which the ports will ride as devices */
qbus_create_inplace(&vser->bus, sizeof(vser->bus), TYPE_VIRTIO_SERIAL_BUS,
dev, vdev->bus_name);
- qbus_set_hotplug_handler(BUS(&vser->bus), DEVICE(vser), errp);
+ qbus_set_hotplug_handler(BUS(&vser->bus), OBJECT(vser));
vser->bus.vser = vser;
QTAILQ_INIT(&vser->ports);
vser->ovqs[i] = virtio_add_queue(vdev, 128, handle_output);
}
- vser->ports_map = g_malloc0(((vser->serial.max_virtserial_ports + 31) / 32)
+ vser->ports_map = g_malloc0((DIV_ROUND_UP(vser->serial.max_virtserial_ports, 32))
* sizeof(vser->ports_map[0]));
/*
* Reserve location 0 for a console port for backward compat
k->bus_type = TYPE_VIRTIO_SERIAL_BUS;
k->realize = virtser_port_device_realize;
k->unrealize = virtser_port_device_unrealize;
- k->props = virtser_props;
+ device_class_set_props(k, virtser_props);
}
static const TypeInfo virtio_serial_port_type_info = {
.class_init = virtio_serial_port_class_init,
};
-static void virtio_serial_device_unrealize(DeviceState *dev, Error **errp)
+static void virtio_serial_device_unrealize(DeviceState *dev)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtIOSerial *vser = VIRTIO_SERIAL(dev);
+ int i;
QLIST_REMOVE(vser, next);
+ virtio_delete_queue(vser->c_ivq);
+ virtio_delete_queue(vser->c_ovq);
+ for (i = 0; i < vser->bus.max_nr_ports; i++) {
+ virtio_delete_queue(vser->ivqs[i]);
+ virtio_delete_queue(vser->ovqs[i]);
+ }
+
g_free(vser->ivqs);
g_free(vser->ovqs);
g_free(vser->ports_map);
if (vser->post_load) {
g_free(vser->post_load->connected);
- timer_del(vser->post_load->timer);
timer_free(vser->post_load->timer);
g_free(vser->post_load);
}
- qbus_set_hotplug_handler(BUS(&vser->bus), NULL, errp);
+ qbus_set_hotplug_handler(BUS(&vser->bus), NULL);
virtio_cleanup(vdev);
}
QLIST_INIT(&vserdevices.devices);
- dc->props = virtio_serial_properties;
+ device_class_set_props(dc, virtio_serial_properties);
dc->vmsd = &vmstate_virtio_console;
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
vdc->realize = virtio_serial_device_realize;