diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2014-09-15 17:18:06 -0700 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2014-09-16 22:46:16 +0100 |
commit | 49d41c1a0b223eace0bdc0596438de84bc20af05 (patch) | |
tree | 41ae2e71c273ea89f4fd41b0e6ba6474a4d9c9ed | |
parent | c02f327dc9fedaf6276c43c3d582d57f697a188e (diff) |
virtserial ping-pong deviceranchu-virtserial
Version of the android pipe pingpong test backend using virtserial
-rw-r--r-- | hw/char/Makefile.objs | 1 | ||||
-rw-r--r-- | hw/char/virtio-pingpong.c | 115 |
2 files changed, 116 insertions, 0 deletions
diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs index 317385d26f..7170aeff40 100644 --- a/hw/char/Makefile.objs +++ b/hw/char/Makefile.objs @@ -5,6 +5,7 @@ common-obj-$(CONFIG_PL011) += pl011.o common-obj-$(CONFIG_SERIAL) += serial.o serial-isa.o common-obj-$(CONFIG_SERIAL_PCI) += serial-pci.o common-obj-$(CONFIG_VIRTIO) += virtio-console.o +common-obj-$(CONFIG_VIRTIO) += virtio-pingpong.o common-obj-$(CONFIG_XILINX) += xilinx_uartlite.o common-obj-$(CONFIG_XEN_BACKEND) += xen_console.o common-obj-$(CONFIG_CADENCE) += cadence_uart.o diff --git a/hw/char/virtio-pingpong.c b/hw/char/virtio-pingpong.c new file mode 100644 index 0000000000..db299215e7 --- /dev/null +++ b/hw/char/virtio-pingpong.c @@ -0,0 +1,115 @@ +/* virtio-pingpong: virtio-serial backend that just sends all + * data it receives back to the guest. + * + * Copyright (c) 2013 Linaro Limited + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + */ + +#include "sysemu/char.h" +#include "qemu/error-report.h" +#include "trace.h" +#include "hw/virtio/virtio-serial.h" + +#define TYPE_VIRTIO_PINGPONG "virtpingpong" +#define VIRTIO_PINGPONG(obj) \ + OBJECT_CHECK(VirtPingpong, (obj), TYPE_VIRTIO_PINGPONG) + +typedef struct VirtPingpong { + VirtIOSerialPort parent_obj; + /* Any per-backend data goes here */ +} VirtPingpong; + + +/* Callback function that's called when the guest sends us data */ +static ssize_t virtpingpong_have_data(VirtIOSerialPort *port, + const uint8_t *buf, ssize_t len) +{ + VirtPingpong *vpp = VIRTIO_PINGPONG(port); + ssize_t ret; + + printf("virtpingpong_have_data: %ld bytes\n", len); + + ret = virtio_serial_write(port, buf, len); + + printf("virtpingpong_have_data: passed %ld bytes back\n", ret); + + if (ret < len) { + /* We didn't manage to send all the data: throttle the + * port so we don't get any more for now. + */ + virtio_serial_throttle_port(port, true); + } + + return ret; +} + +static void virtpingpong_guest_writable(VirtIOSerialPort *port) +{ + printf("virtpingpong_guest_writable\n"); + /* Just unthrottle the other end of the port so it can send us more data */ + virtio_serial_throttle_port(port, false); +} + +/* Callback function that's called when the guest opens/closes the port */ +static void virtpingpong_set_guest_connected(VirtIOSerialPort *port, + int guest_connected) +{ + VirtPingpong *vpp = VIRTIO_PINGPONG(port); + + printf("virtpingpong: guest %sconnected\n", guest_connected ? "" : "dis"); +} + +static void virtpingpong_realize(DeviceState *dev, Error **errp) +{ + VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev); + VirtPingpong *vpp = VIRTIO_PINGPONG(dev); + VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(dev); + + if (port->id == 0 && !k->is_console) { + error_setg(errp, "Port number 0 on virtio-serial devices reserved " + "for virtconsole devices for backward compatibility."); + return; + } + + /* The host end of this connection is always open. */ + virtio_serial_open(port); +} + +static void virtpingpong_unrealize(DeviceState *dev, Error **errp) +{ + VirtPingpong *vpp = VIRTIO_PINGPONG(dev); + + /* Nothing for us to do here */ +} + +static void virtpingpong_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass); + + k->realize = virtpingpong_realize; + k->unrealize = virtpingpong_unrealize; + k->have_data = virtpingpong_have_data; + k->guest_writable = virtpingpong_guest_writable; + k->set_guest_connected = virtpingpong_set_guest_connected; + /* If we have any device state for save/load we should + * register a vmstate here. + */ +} + +static const TypeInfo virtpingpong_info = { + .name = TYPE_VIRTIO_PINGPONG, + .parent = TYPE_VIRTIO_SERIAL_PORT, + .instance_size = sizeof(VirtPingpong), + .class_init = virtpingpong_class_init, +}; + +static void virtpingpong_register_types(void) +{ + type_register_static(&virtpingpong_info); +} + +type_init(virtpingpong_register_types) |