From: KONRAD Frederic <fred.kon...@greensocs.com> Create virtio-serial which extends virtio-device, so it can be connected on virtio-bus.
Signed-off-by: KONRAD Frederic <fred.kon...@greensocs.com> --- hw/virtio-pci.c | 8 +++- hw/virtio-serial-bus.c | 100 +++++++++++++++++++++++++++++++++++++++++++++---- hw/virtio-serial.h | 11 ++++++ 3 files changed, 111 insertions(+), 8 deletions(-) diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 8b89758..3aa96fc 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -820,7 +820,7 @@ static Property virtio_serial_properties[] = { DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, DEV_NVECTORS_UNSPECIFIED), DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0), DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features), - DEFINE_PROP_UINT32("max_ports", VirtIOPCIProxy, serial.max_virtserial_ports, 31), + DEFINE_VIRTIO_SERIAL_PROPERTIES(VirtIOPCIProxy, serial), DEFINE_PROP_END_OF_LIST(), }; @@ -885,6 +885,12 @@ static void virtio_pci_device_plugged(DeviceState *d) PCI_DEVICE_ID_VIRTIO_RNG); pci_config_set_class(proxy->pci_dev.config, PCI_CLASS_OTHERS); break; + case VIRTIO_ID_CONSOLE: + pci_config_set_device_id(proxy->pci_dev.config, + PCI_DEVICE_ID_VIRTIO_CONSOLE); + pci_config_set_class(proxy->pci_dev.config, + PCI_CLASS_COMMUNICATION_OTHER); + break; default: error_report("unknown device id\n"); break; diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c index b7cce7a..5186191 100644 --- a/hw/virtio-serial-bus.c +++ b/hw/virtio-serial-bus.c @@ -904,10 +904,12 @@ static int virtser_port_qdev_exit(DeviceState *qdev) return 0; } -VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *conf) +static VirtIODevice *virtio_serial_common_init(DeviceState *dev, + virtio_serial_conf *conf, + VirtIODevice **pvdev) { VirtIOSerial *vser; - VirtIODevice *vdev; + VirtIODevice *vdev = *pvdev; uint32_t i, max_supported_ports; if (!conf->max_virtserial_ports) @@ -921,11 +923,22 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *conf) return NULL; } - vdev = virtio_common_init("virtio-serial", VIRTIO_ID_CONSOLE, - sizeof(struct virtio_console_config), - sizeof(VirtIOSerial)); - - vser = DO_UPCAST(VirtIOSerial, vdev, vdev); + /* + * We have two cases here : the old virtio-serial-pci device, and the + * refactored virtio-serial. + */ + if (vdev == NULL) { + /* virtio-serial-pci */ + vdev = virtio_common_init("virtio-serial", VIRTIO_ID_CONSOLE, + sizeof(struct virtio_console_config), + sizeof(VirtIOSerial)); + vser = DO_UPCAST(VirtIOSerial, vdev, vdev); + } else { + /* virtio-serial */ + virtio_init(vdev, "virtio-serial", VIRTIO_ID_CONSOLE, + sizeof(struct virtio_console_config)); + vser = VIRTIO_SERIAL(vdev); + } /* Spawn a new virtio-serial bus on which the ports will ride as devices */ qbus_create_inplace(&vser->bus.qbus, TYPE_VIRTIO_SERIAL_BUS, dev, NULL); @@ -989,6 +1002,16 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *conf) return vdev; } +/* + * The two following functions will be cleaned up at the end. + */ + +VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *conf) +{ + VirtIODevice *vdev = NULL; + return virtio_serial_common_init(dev, conf, &vdev); +} + void virtio_serial_exit(VirtIODevice *vdev) { VirtIOSerial *vser = DO_UPCAST(VirtIOSerial, vdev, vdev); @@ -1026,10 +1049,73 @@ static TypeInfo virtio_serial_port_type_info = { .class_init = virtio_serial_port_class_init, }; +void virtio_serial_set_conf(DeviceState *dev, virtio_serial_conf *serial) +{ + VirtIOSerial *s = VIRTIO_SERIAL(dev); + memcpy(&(s->serial), serial, sizeof(virtio_serial_conf)); +} + +static int virtio_serial_device_init(VirtIODevice *vdev) +{ + DeviceState *qdev = DEVICE(vdev); + VirtIOSerial *vser = VIRTIO_SERIAL(vdev); + if (virtio_serial_common_init(qdev, &(vser->serial), &vdev) == NULL) { + return -1; + } + return 0; +} + +static int virtio_serial_device_exit(DeviceState *dev) +{ + VirtIOSerial *vser = VIRTIO_SERIAL(dev); + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + + unregister_savevm(dev, "virtio-console", vser); + + g_free(vser->ivqs); + g_free(vser->ovqs); + g_free(vser->ports_map); + if (vser->post_load) { + g_free(vser->post_load->connected); + qemu_del_timer(vser->post_load->timer); + qemu_free_timer(vser->post_load->timer); + g_free(vser->post_load); + } + virtio_common_cleanup(vdev); + return 0; +} + +static Property virtio_serial_properties[] = { + DEFINE_VIRTIO_SERIAL_PROPERTIES(VirtIOSerial, serial), + DEFINE_PROP_END_OF_LIST(), +}; + +static void virtio_serial_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + dc->exit = virtio_serial_device_exit; + dc->props = virtio_serial_properties; + vdc->init = virtio_serial_device_init; + vdc->get_features = get_features; + vdc->get_config = get_config; + vdc->set_config = set_config; + vdc->set_status = set_status; + vdc->reset = vser_reset; +} + +static const TypeInfo virtio_device_info = { + .name = TYPE_VIRTIO_SERIAL, + .parent = TYPE_VIRTIO_DEVICE, + .instance_size = sizeof(VirtIOSerial), + .class_init = virtio_serial_class_init, +}; + static void virtio_serial_register_types(void) { type_register_static(&virtser_bus_info); type_register_static(&virtio_serial_port_type_info); + type_register_static(&virtio_device_info); } type_init(virtio_serial_register_types) diff --git a/hw/virtio-serial.h b/hw/virtio-serial.h index 722d01b..f5960f9 100644 --- a/hw/virtio-serial.h +++ b/hw/virtio-serial.h @@ -212,6 +212,8 @@ struct VirtIOSerial { struct virtio_console_config config; struct VirtIOSerialPostLoad *post_load; + + virtio_serial_conf serial; }; /* Interface to the virtio-serial bus */ @@ -246,4 +248,13 @@ size_t virtio_serial_guest_ready(VirtIOSerialPort *port); */ void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle); +#define TYPE_VIRTIO_SERIAL "virtio-serial" +#define VIRTIO_SERIAL(obj) \ + OBJECT_CHECK(VirtIOSerial, (obj), TYPE_VIRTIO_SERIAL) + +#define DEFINE_VIRTIO_SERIAL_PROPERTIES(_state, _field) \ + DEFINE_PROP_UINT32("max_ports", _state, _field.max_virtserial_ports, 31) + +void virtio_serial_set_conf(DeviceState *dev, virtio_serial_conf *serial); + #endif -- 1.7.11.7