diff options
author | hyokeun <hyokeun.jeon@samsung.com> | 2016-09-06 14:09:22 +0900 |
---|---|---|
committer | hyokeun <hyokeun.jeon@samsung.com> | 2016-09-06 14:09:22 +0900 |
commit | bd54c25035217800f3b1d39f6472d599cd602d5a (patch) | |
tree | 299417fe96f546225439ff92b27ac3e55909a970 /hw/char | |
parent | 186efde2677c31fb40d154a81a5f3731eab52414 (diff) | |
download | qemu-bd54c25035217800f3b1d39f6472d599cd602d5a.tar.gz qemu-bd54c25035217800f3b1d39f6472d599cd602d5a.tar.bz2 qemu-bd54c25035217800f3b1d39f6472d599cd602d5a.zip |
Imported Upstream version 2.7.0upstream/2.7.0
Diffstat (limited to 'hw/char')
-rw-r--r-- | hw/char/bcm2835_aux.c | 1 | ||||
-rw-r--r-- | hw/char/cadence_uart.c | 33 | ||||
-rw-r--r-- | hw/char/digic-uart.c | 11 | ||||
-rw-r--r-- | hw/char/escc.c | 38 | ||||
-rw-r--r-- | hw/char/etraxfs_ser.c | 27 | ||||
-rw-r--r-- | hw/char/imx_serial.c | 1 | ||||
-rw-r--r-- | hw/char/ipoctal232.c | 2 | ||||
-rw-r--r-- | hw/char/lm32_juart.c | 17 | ||||
-rw-r--r-- | hw/char/lm32_uart.c | 28 | ||||
-rw-r--r-- | hw/char/milkymist-uart.c | 12 | ||||
-rw-r--r-- | hw/char/pl011.c | 12 | ||||
-rw-r--r-- | hw/char/sclpconsole-lm.c | 14 | ||||
-rw-r--r-- | hw/char/sclpconsole.c | 14 | ||||
-rw-r--r-- | hw/char/serial.c | 67 | ||||
-rw-r--r-- | hw/char/stm32f2xx_usart.c | 16 | ||||
-rw-r--r-- | hw/char/trace-events | 49 | ||||
-rw-r--r-- | hw/char/virtio-console.c | 25 | ||||
-rw-r--r-- | hw/char/virtio-serial-bus.c | 62 | ||||
-rw-r--r-- | hw/char/xen_console.c | 1 | ||||
-rw-r--r-- | hw/char/xilinx_uartlite.c | 10 |
20 files changed, 289 insertions, 151 deletions
diff --git a/hw/char/bcm2835_aux.c b/hw/char/bcm2835_aux.c index 0394d11a8..319f1652f 100644 --- a/hw/char/bcm2835_aux.c +++ b/hw/char/bcm2835_aux.c @@ -22,6 +22,7 @@ #include "qemu/osdep.h" #include "hw/char/bcm2835_aux.h" +#include "qemu/log.h" #define AUX_IRQ 0x0 #define AUX_ENABLES 0x4 diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c index 797787823..e3bc52f7d 100644 --- a/hw/char/cadence_uart.c +++ b/hw/char/cadence_uart.c @@ -17,6 +17,10 @@ */ #include "qemu/osdep.h" +#include "hw/sysbus.h" +#include "sysemu/char.h" +#include "qemu/timer.h" +#include "qemu/log.h" #include "hw/char/cadence_uart.h" #ifdef CADENCE_UART_ERR_DEBUG @@ -284,13 +288,19 @@ static gboolean cadence_uart_xmit(GIOChannel *chan, GIOCondition cond, } ret = qemu_chr_fe_write(s->chr, s->tx_fifo, s->tx_count); - s->tx_count -= ret; - memmove(s->tx_fifo, s->tx_fifo + ret, s->tx_count); + + if (ret >= 0) { + s->tx_count -= ret; + memmove(s->tx_fifo, s->tx_fifo + ret, s->tx_count); + } if (s->tx_count) { - int r = qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP, - cadence_uart_xmit, s); - assert(r); + guint r = qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP, + cadence_uart_xmit, s); + if (!r) { + s->tx_count = 0; + return FALSE; + } } uart_update_status(s); @@ -464,9 +474,6 @@ static void cadence_uart_realize(DeviceState *dev, Error **errp) s->fifo_trigger_handle = timer_new_ns(QEMU_CLOCK_VIRTUAL, fifo_trigger_update, s); - /* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */ - s->chr = qemu_char_get_next_serial(); - if (s->chr) { qemu_chr_add_handlers(s->chr, uart_can_receive, uart_receive, uart_event, s); @@ -513,6 +520,11 @@ static const VMStateDescription vmstate_cadence_uart = { } }; +static Property cadence_uart_properties[] = { + DEFINE_PROP_CHR("chardev", CadenceUARTState, chr), + DEFINE_PROP_END_OF_LIST(), +}; + static void cadence_uart_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -520,9 +532,8 @@ static void cadence_uart_class_init(ObjectClass *klass, void *data) dc->realize = cadence_uart_realize; dc->vmsd = &vmstate_cadence_uart; dc->reset = cadence_uart_reset; - /* Reason: realize() method uses qemu_char_get_next_serial() */ - dc->cannot_instantiate_with_device_add_yet = true; -} + dc->props = cadence_uart_properties; + } static const TypeInfo cadence_uart_info = { .name = TYPE_CADENCE_UART, diff --git a/hw/char/digic-uart.c b/hw/char/digic-uart.c index d3bc533d7..c7604e676 100644 --- a/hw/char/digic-uart.c +++ b/hw/char/digic-uart.c @@ -30,6 +30,7 @@ #include "hw/hw.h" #include "hw/sysbus.h" #include "sysemu/char.h" +#include "qemu/log.h" #include "hw/char/digic-uart.h" @@ -144,8 +145,6 @@ static void digic_uart_realize(DeviceState *dev, Error **errp) { DigicUartState *s = DIGIC_UART(dev); - /* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */ - s->chr = qemu_char_get_next_serial(); if (s->chr) { qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s); } @@ -171,6 +170,11 @@ static const VMStateDescription vmstate_digic_uart = { } }; +static Property digic_uart_properties[] = { + DEFINE_PROP_CHR("chardev", DigicUartState, chr), + DEFINE_PROP_END_OF_LIST(), +}; + static void digic_uart_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -178,8 +182,7 @@ static void digic_uart_class_init(ObjectClass *klass, void *data) dc->realize = digic_uart_realize; dc->reset = digic_uart_reset; dc->vmsd = &vmstate_digic_uart; - /* Reason: realize() method uses qemu_char_get_next_serial() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->props = digic_uart_properties; } static const TypeInfo digic_uart_info = { diff --git a/hw/char/escc.c b/hw/char/escc.c index 7bf09a007..31a5f902f 100644 --- a/hw/char/escc.c +++ b/hw/char/escc.c @@ -983,28 +983,40 @@ void slavio_serial_ms_kbd_init(hwaddr base, qemu_irq irq, sysbus_mmio_map(s, 0, base); } -static int escc_init1(SysBusDevice *dev) +static void escc_init1(Object *obj) +{ + ESCCState *s = ESCC(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); + unsigned int i; + + for (i = 0; i < 2; i++) { + sysbus_init_irq(dev, &s->chn[i].irq); + s->chn[i].chn = 1 - i; + } + s->chn[0].otherchn = &s->chn[1]; + s->chn[1].otherchn = &s->chn[0]; + + sysbus_init_mmio(dev, &s->mmio); +} + +static void escc_realize(DeviceState *dev, Error **errp) { ESCCState *s = ESCC(dev); unsigned int i; s->chn[0].disabled = s->disabled; s->chn[1].disabled = s->disabled; + + memory_region_init_io(&s->mmio, OBJECT(dev), &escc_mem_ops, s, "escc", + ESCC_SIZE << s->it_shift); + for (i = 0; i < 2; i++) { - sysbus_init_irq(dev, &s->chn[i].irq); - s->chn[i].chn = 1 - i; - s->chn[i].clock = s->frequency / 2; if (s->chn[i].chr) { + s->chn[i].clock = s->frequency / 2; qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive, serial_receive1, serial_event, &s->chn[i]); } } - s->chn[0].otherchn = &s->chn[1]; - s->chn[1].otherchn = &s->chn[0]; - - memory_region_init_io(&s->mmio, OBJECT(s), &escc_mem_ops, s, "escc", - ESCC_SIZE << s->it_shift); - sysbus_init_mmio(dev, &s->mmio); if (s->chn[0].type == mouse) { qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0, @@ -1014,8 +1026,6 @@ static int escc_init1(SysBusDevice *dev) s->chn[1].hs = qemu_input_handler_register((DeviceState *)(&s->chn[1]), &sunkbd_handler); } - - return 0; } static Property escc_properties[] = { @@ -1032,10 +1042,9 @@ static Property escc_properties[] = { static void escc_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = escc_init1; dc->reset = escc_reset; + dc->realize = escc_realize; dc->vmsd = &vmstate_escc; dc->props = escc_properties; set_bit(DEVICE_CATEGORY_INPUT, dc->categories); @@ -1045,6 +1054,7 @@ static const TypeInfo escc_info = { .name = TYPE_ESCC, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(ESCCState), + .instance_init = escc_init1, .class_init = escc_class_init, }; diff --git a/hw/char/etraxfs_ser.c b/hw/char/etraxfs_ser.c index 146b387e7..04ca04fe2 100644 --- a/hw/char/etraxfs_ser.c +++ b/hw/char/etraxfs_ser.c @@ -159,6 +159,11 @@ static const MemoryRegionOps ser_ops = { } }; +static Property etraxfs_ser_properties[] = { + DEFINE_PROP_CHR("chardev", ETRAXSerial, chr), + DEFINE_PROP_END_OF_LIST(), +}; + static void serial_receive(void *opaque, const uint8_t *buf, int size) { ETRAXSerial *s = opaque; @@ -209,40 +214,42 @@ static void etraxfs_ser_reset(DeviceState *d) } -static int etraxfs_ser_init(SysBusDevice *dev) +static void etraxfs_ser_init(Object *obj) { - ETRAXSerial *s = ETRAX_SERIAL(dev); + ETRAXSerial *s = ETRAX_SERIAL(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); sysbus_init_irq(dev, &s->irq); - memory_region_init_io(&s->mmio, OBJECT(s), &ser_ops, s, + memory_region_init_io(&s->mmio, obj, &ser_ops, s, "etraxfs-serial", R_MAX * 4); sysbus_init_mmio(dev, &s->mmio); +} + +static void etraxfs_ser_realize(DeviceState *dev, Error **errp) +{ + ETRAXSerial *s = ETRAX_SERIAL(dev); - /* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */ - s->chr = qemu_char_get_next_serial(); if (s->chr) { qemu_chr_add_handlers(s->chr, serial_can_receive, serial_receive, serial_event, s); } - return 0; } static void etraxfs_ser_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = etraxfs_ser_init; dc->reset = etraxfs_ser_reset; - /* Reason: init() method uses qemu_char_get_next_serial() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->props = etraxfs_ser_properties; + dc->realize = etraxfs_ser_realize; } static const TypeInfo etraxfs_ser_info = { .name = TYPE_ETRAX_FS_SERIAL, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(ETRAXSerial), + .instance_init = etraxfs_ser_init, .class_init = etraxfs_ser_class_init, }; diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c index 6df74ac7c..44856d671 100644 --- a/hw/char/imx_serial.c +++ b/hw/char/imx_serial.c @@ -22,6 +22,7 @@ #include "hw/char/imx_serial.h" #include "sysemu/sysemu.h" #include "sysemu/char.h" +#include "qemu/log.h" #ifndef DEBUG_IMX_UART #define DEBUG_IMX_UART 0 diff --git a/hw/char/ipoctal232.c b/hw/char/ipoctal232.c index bc0ae4980..9ead32af6 100644 --- a/hw/char/ipoctal232.c +++ b/hw/char/ipoctal232.c @@ -2,7 +2,7 @@ * QEMU GE IP-Octal 232 IndustryPack emulation * * Copyright (C) 2012 Igalia, S.L. - * Author: Alberto Garcia <agarcia@igalia.com> + * Author: Alberto Garcia <berto@igalia.com> * * This code is licensed under the GNU GPL v2 or (at your option) any * later version. diff --git a/hw/char/lm32_juart.c b/hw/char/lm32_juart.c index 5bf8acfe8..28c2cf702 100644 --- a/hw/char/lm32_juart.c +++ b/hw/char/lm32_juart.c @@ -114,17 +114,13 @@ static void juart_reset(DeviceState *d) s->jrx = 0; } -static int lm32_juart_init(SysBusDevice *dev) +static void lm32_juart_realize(DeviceState *dev, Error **errp) { LM32JuartState *s = LM32_JUART(dev); - /* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */ - s->chr = qemu_char_get_next_serial(); if (s->chr) { qemu_chr_add_handlers(s->chr, juart_can_rx, juart_rx, juart_event, s); } - - return 0; } static const VMStateDescription vmstate_lm32_juart = { @@ -138,16 +134,19 @@ static const VMStateDescription vmstate_lm32_juart = { } }; +static Property lm32_juart_properties[] = { + DEFINE_PROP_CHR("chardev", LM32JuartState, chr), + DEFINE_PROP_END_OF_LIST(), +}; + static void lm32_juart_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = lm32_juart_init; dc->reset = juart_reset; dc->vmsd = &vmstate_lm32_juart; - /* Reason: init() method uses qemu_char_get_next_serial() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->props = lm32_juart_properties; + dc->realize = lm32_juart_realize; } static const TypeInfo lm32_juart_info = { diff --git a/hw/char/lm32_uart.c b/hw/char/lm32_uart.c index 036813d0f..b5c760dda 100644 --- a/hw/char/lm32_uart.c +++ b/hw/char/lm32_uart.c @@ -249,23 +249,25 @@ static void uart_reset(DeviceState *d) s->regs[R_LSR] = LSR_THRE | LSR_TEMT; } -static int lm32_uart_init(SysBusDevice *dev) +static void lm32_uart_init(Object *obj) { - LM32UartState *s = LM32_UART(dev); + LM32UartState *s = LM32_UART(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); sysbus_init_irq(dev, &s->irq); - memory_region_init_io(&s->iomem, OBJECT(s), &uart_ops, s, + memory_region_init_io(&s->iomem, obj, &uart_ops, s, "uart", R_MAX * 4); sysbus_init_mmio(dev, &s->iomem); +} + +static void lm32_uart_realize(DeviceState *dev, Error **errp) +{ + LM32UartState *s = LM32_UART(dev); - /* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */ - s->chr = qemu_char_get_next_serial(); if (s->chr) { qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s); } - - return 0; } static const VMStateDescription vmstate_lm32_uart = { @@ -278,22 +280,26 @@ static const VMStateDescription vmstate_lm32_uart = { } }; +static Property lm32_uart_properties[] = { + DEFINE_PROP_CHR("chardev", LM32UartState, chr), + DEFINE_PROP_END_OF_LIST(), +}; + static void lm32_uart_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = lm32_uart_init; dc->reset = uart_reset; dc->vmsd = &vmstate_lm32_uart; - /* Reason: init() method uses qemu_char_get_next_serial() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->props = lm32_uart_properties; + dc->realize = lm32_uart_realize; } static const TypeInfo lm32_uart_info = { .name = TYPE_LM32_UART, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(LM32UartState), + .instance_init = lm32_uart_init, .class_init = lm32_uart_class_init, }; diff --git a/hw/char/milkymist-uart.c b/hw/char/milkymist-uart.c index 03b36b223..baddb3764 100644 --- a/hw/char/milkymist-uart.c +++ b/hw/char/milkymist-uart.c @@ -18,7 +18,7 @@ * * * Specification available at: - * http://www.milkymist.org/socdoc/uart.pdf + * http://milkymist.walle.cc/socdoc/uart.pdf */ #include "qemu/osdep.h" @@ -200,8 +200,6 @@ static void milkymist_uart_realize(DeviceState *dev, Error **errp) { MilkymistUartState *s = MILKYMIST_UART(dev); - /* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */ - s->chr = qemu_char_get_next_serial(); if (s->chr) { qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s); } @@ -229,6 +227,11 @@ static const VMStateDescription vmstate_milkymist_uart = { } }; +static Property milkymist_uart_properties[] = { + DEFINE_PROP_CHR("chardev", MilkymistUartState, chr), + DEFINE_PROP_END_OF_LIST(), +}; + static void milkymist_uart_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -236,8 +239,7 @@ static void milkymist_uart_class_init(ObjectClass *klass, void *data) dc->realize = milkymist_uart_realize; dc->reset = milkymist_uart_reset; dc->vmsd = &vmstate_milkymist_uart; - /* Reason: realize() method uses qemu_char_get_next_serial() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->props = milkymist_uart_properties; } static const TypeInfo milkymist_uart_info = { diff --git a/hw/char/pl011.c b/hw/char/pl011.c index 210c87b4c..c0fbf8a87 100644 --- a/hw/char/pl011.c +++ b/hw/char/pl011.c @@ -10,6 +10,7 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" #include "sysemu/char.h" +#include "qemu/log.h" #define TYPE_PL011 "pl011" #define PL011(obj) OBJECT_CHECK(PL011State, (obj), TYPE_PL011) @@ -273,6 +274,11 @@ static const VMStateDescription vmstate_pl011 = { } }; +static Property pl011_properties[] = { + DEFINE_PROP_CHR("chardev", PL011State, chr), + DEFINE_PROP_END_OF_LIST(), +}; + static void pl011_init(Object *obj) { SysBusDevice *sbd = SYS_BUS_DEVICE(obj); @@ -294,9 +300,6 @@ static void pl011_realize(DeviceState *dev, Error **errp) { PL011State *s = PL011(dev); - /* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */ - s->chr = qemu_char_get_next_serial(); - if (s->chr) { qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive, pl011_event, s); @@ -309,8 +312,7 @@ static void pl011_class_init(ObjectClass *oc, void *data) dc->realize = pl011_realize; dc->vmsd = &vmstate_pl011; - /* Reason: realize() method uses qemu_char_get_next_serial() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->props = pl011_properties; } static const TypeInfo pl011_arm_info = { diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c index 7d4ff8120..a22ad8d01 100644 --- a/hw/char/sclpconsole-lm.c +++ b/hw/char/sclpconsole-lm.c @@ -44,6 +44,10 @@ typedef struct SCLPConsoleLM { uint8_t buf[SIZE_CONSOLE_BUFFER]; } SCLPConsoleLM; +#define TYPE_SCLPLM_CONSOLE "sclplmconsole" +#define SCLPLM_CONSOLE(obj) \ + OBJECT_CHECK(SCLPConsoleLM, (obj), TYPE_SCLPLM_CONSOLE) + /* * Character layer call-back functions * @@ -116,7 +120,7 @@ static int get_console_data(SCLPEvent *event, uint8_t *buf, size_t *size, { int len; - SCLPConsoleLM *cons = DO_UPCAST(SCLPConsoleLM, event, event); + SCLPConsoleLM *cons = SCLPLM_CONSOLE(event); len = cons->length; /* data need to fit into provided SCLP buffer */ @@ -190,7 +194,7 @@ static int write_console_data(SCLPEvent *event, const uint8_t *buf, int len) int ret = 0; const uint8_t *buf_offset; - SCLPConsoleLM *scon = DO_UPCAST(SCLPConsoleLM, event, event); + SCLPConsoleLM *scon = SCLPLM_CONSOLE(event); if (!scon->chr) { /* If there's no backend, we can just say we consumed all data. */ @@ -244,7 +248,7 @@ static int write_event_data(SCLPEvent *event, EventBufferHeader *ebh) int errors = 0; MDBO *mdbo; SclpMsg *data = (SclpMsg *) ebh; - SCLPConsoleLM *scon = DO_UPCAST(SCLPConsoleLM, event, event); + SCLPConsoleLM *scon = SCLPLM_CONSOLE(event); len = be16_to_cpu(data->mdb.header.length); if (len < sizeof(data->mdb.header)) { @@ -313,7 +317,7 @@ static int console_init(SCLPEvent *event) { static bool console_available; - SCLPConsoleLM *scon = DO_UPCAST(SCLPConsoleLM, event, event); + SCLPConsoleLM *scon = SCLPLM_CONSOLE(event); if (console_available) { error_report("Multiple line-mode operator consoles are not supported"); @@ -336,7 +340,7 @@ static int console_exit(SCLPEvent *event) static void console_reset(DeviceState *dev) { SCLPEvent *event = SCLP_EVENT(dev); - SCLPConsoleLM *scon = DO_UPCAST(SCLPConsoleLM, event, event); + SCLPConsoleLM *scon = SCLPLM_CONSOLE(event); event->event_pending = false; scon->length = 0; diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c index 45997ff4a..d22464826 100644 --- a/hw/char/sclpconsole.c +++ b/hw/char/sclpconsole.c @@ -13,7 +13,7 @@ */ #include "qemu/osdep.h" -#include <hw/qdev.h> +#include "hw/qdev.h" #include "qemu/thread.h" #include "qemu/error-report.h" @@ -40,6 +40,10 @@ typedef struct SCLPConsole { bool notify; /* qemu_notify_event() req'd if true */ } SCLPConsole; +#define TYPE_SCLP_CONSOLE "sclpconsole" +#define SCLP_CONSOLE(obj) \ + OBJECT_CHECK(SCLPConsole, (obj), TYPE_SCLP_CONSOLE) + /* character layer call-back functions */ /* Return number of bytes that fit into iov buffer */ @@ -95,7 +99,7 @@ static unsigned int receive_mask(void) static void get_console_data(SCLPEvent *event, uint8_t *buf, size_t *size, int avail) { - SCLPConsole *cons = DO_UPCAST(SCLPConsole, event, event); + SCLPConsole *cons = SCLP_CONSOLE(event); /* first byte is hex 0 saying an ascii string follows */ *buf++ = '\0'; @@ -157,7 +161,7 @@ static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr, static ssize_t write_console_data(SCLPEvent *event, const uint8_t *buf, size_t len) { - SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event); + SCLPConsole *scon = SCLP_CONSOLE(event); if (!scon->chr) { /* If there's no backend, we can just say we consumed all data. */ @@ -214,7 +218,7 @@ static int console_init(SCLPEvent *event) { static bool console_available; - SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event); + SCLPConsole *scon = SCLP_CONSOLE(event); if (console_available) { error_report("Multiple VT220 operator consoles are not supported"); @@ -232,7 +236,7 @@ static int console_init(SCLPEvent *event) static void console_reset(DeviceState *dev) { SCLPEvent *event = SCLP_EVENT(dev); - SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event); + SCLPConsole *scon = SCLP_CONSOLE(event); event->event_pending = false; scon->iov_sclp = 0; diff --git a/hw/char/serial.c b/hw/char/serial.c index 6d815b5c6..3442f47d3 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -106,6 +106,7 @@ do {} while (0) #endif static void serial_receive1(void *opaque, const uint8_t *buf, int size); +static void serial_xmit(SerialState *s); static inline void recv_fifo_put(SerialState *s, uint8_t chr) { @@ -223,13 +224,20 @@ static void serial_update_msl(SerialState *s) } } -static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque) +static gboolean serial_watch_cb(GIOChannel *chan, GIOCondition cond, + void *opaque) { SerialState *s = opaque; + s->watch_tag = 0; + serial_xmit(s); + return FALSE; +} +static void serial_xmit(SerialState *s) +{ do { assert(!(s->lsr & UART_LSR_TEMT)); - if (s->tsr_retry <= 0) { + if (s->tsr_retry == 0) { assert(!(s->lsr & UART_LSR_THRE)); if (s->fcr & UART_FCR_FE) { @@ -251,17 +259,17 @@ static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque) if (s->mcr & UART_MCR_LOOP) { /* in loopback mode, say that we just received a char */ serial_receive1(s, &s->tsr, 1); - } else if (qemu_chr_fe_write(s->chr, &s->tsr, 1) != 1) { - if (s->tsr_retry >= 0 && s->tsr_retry < MAX_XMIT_RETRY && - qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP, - serial_xmit, s) > 0) { + } else if (qemu_chr_fe_write(s->chr, &s->tsr, 1) != 1 && + s->tsr_retry < MAX_XMIT_RETRY) { + assert(s->watch_tag == 0); + s->watch_tag = qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP, + serial_watch_cb, s); + if (s->watch_tag > 0) { s->tsr_retry++; - return FALSE; + return; } - s->tsr_retry = 0; - } else { - s->tsr_retry = 0; } + s->tsr_retry = 0; /* Transmit another byte if it is already available. It is only possible when FIFO is enabled and not empty. */ @@ -269,11 +277,8 @@ static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque) s->last_xmit_ts = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); s->lsr |= UART_LSR_TEMT; - - return FALSE; } - /* Setter for FCR. is_load flag means, that value is set while loading VM state and interrupt should not be invoked */ @@ -330,8 +335,8 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val, s->lsr &= ~UART_LSR_THRE; s->lsr &= ~UART_LSR_TEMT; serial_update_irq(s); - if (s->tsr_retry <= 0) { - serial_xmit(NULL, G_IO_OUT, s); + if (s->tsr_retry == 0) { + serial_xmit(s); } } break; @@ -639,6 +644,31 @@ static int serial_post_load(void *opaque, int version_id) if (s->thr_ipending == -1) { s->thr_ipending = ((s->iir & UART_IIR_ID) == UART_IIR_THRI); } + + if (s->tsr_retry > 0) { + /* tsr_retry > 0 implies LSR.TEMT = 0 (transmitter not empty). */ + if (s->lsr & UART_LSR_TEMT) { + error_report("inconsistent state in serial device " + "(tsr empty, tsr_retry=%d", s->tsr_retry); + return -1; + } + + if (s->tsr_retry > MAX_XMIT_RETRY) { + s->tsr_retry = MAX_XMIT_RETRY; + } + + assert(s->watch_tag == 0); + s->watch_tag = qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP, + serial_watch_cb, s); + } else { + /* tsr_retry == 0 implies LSR.TEMT = 1 (transmitter empty). */ + if (!(s->lsr & UART_LSR_TEMT)) { + error_report("inconsistent state in serial device " + "(tsr not empty, tsr_retry=0"); + return -1; + } + } + s->last_break_enable = (s->lcr >> 6) & 1; /* Initialize fcr via setter to perform essential side-effects */ serial_write_fcr(s, s->fcr_vmstate); @@ -685,7 +715,7 @@ static const VMStateDescription vmstate_serial_tsr = { .minimum_version_id = 1, .needed = serial_tsr_needed, .fields = (VMStateField[]) { - VMSTATE_INT32(tsr_retry, SerialState), + VMSTATE_UINT32(tsr_retry, SerialState), VMSTATE_UINT8(thr, SerialState), VMSTATE_UINT8(tsr, SerialState), VMSTATE_END_OF_LIST() @@ -815,6 +845,11 @@ static void serial_reset(void *opaque) { SerialState *s = opaque; + if (s->watch_tag > 0) { + g_source_remove(s->watch_tag); + s->watch_tag = 0; + } + s->rbr = 0; s->ier = 0; s->iir = UART_IIR_NO_INT; diff --git a/hw/char/stm32f2xx_usart.c b/hw/char/stm32f2xx_usart.c index a94d61ceb..15657abda 100644 --- a/hw/char/stm32f2xx_usart.c +++ b/hw/char/stm32f2xx_usart.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "hw/char/stm32f2xx_usart.h" +#include "qemu/log.h" #ifndef STM_USART_ERR_DEBUG #define STM_USART_ERR_DEBUG 0 @@ -189,6 +190,11 @@ static const MemoryRegionOps stm32f2xx_usart_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; +static Property stm32f2xx_usart_properties[] = { + DEFINE_PROP_CHR("chardev", STM32F2XXUsartState, chr), + DEFINE_PROP_END_OF_LIST(), +}; + static void stm32f2xx_usart_init(Object *obj) { STM32F2XXUsartState *s = STM32F2XX_USART(obj); @@ -198,9 +204,11 @@ static void stm32f2xx_usart_init(Object *obj) memory_region_init_io(&s->mmio, obj, &stm32f2xx_usart_ops, s, TYPE_STM32F2XX_USART, 0x2000); sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); +} - /* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */ - s->chr = qemu_char_get_next_serial(); +static void stm32f2xx_usart_realize(DeviceState *dev, Error **errp) +{ + STM32F2XXUsartState *s = STM32F2XX_USART(dev); if (s->chr) { qemu_chr_add_handlers(s->chr, stm32f2xx_usart_can_receive, @@ -213,8 +221,8 @@ static void stm32f2xx_usart_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); dc->reset = stm32f2xx_usart_reset; - /* Reason: instance_init() method uses qemu_char_get_next_serial() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->props = stm32f2xx_usart_properties; + dc->realize = stm32f2xx_usart_realize; } static const TypeInfo stm32f2xx_usart_info = { diff --git a/hw/char/trace-events b/hw/char/trace-events new file mode 100644 index 000000000..d53577c99 --- /dev/null +++ b/hw/char/trace-events @@ -0,0 +1,49 @@ +# See docs/tracing.txt for syntax documentation. + +# hw/char/virtio-serial-bus.c +virtio_serial_send_control_event(unsigned int port, uint16_t event, uint16_t value) "port %u, event %u, value %u" +virtio_serial_throttle_port(unsigned int port, bool throttle) "port %u, throttle %d" +virtio_serial_handle_control_message(uint16_t event, uint16_t value) "event %u, value %u" +virtio_serial_handle_control_message_port(unsigned int port) "port %u" + +# hw/char/virtio-console.c +virtio_console_flush_buf(unsigned int port, size_t len, ssize_t ret) "port %u, in_len %zu, out_len %zd" +virtio_console_chr_read(unsigned int port, int size) "port %u, size %d" +virtio_console_chr_event(unsigned int port, int event) "port %u, event %d" + +# hw/char/grlib_apbuart.c +grlib_apbuart_event(int event) "event:%d" +grlib_apbuart_writel_unknown(uint64_t addr, uint32_t value) "addr 0x%"PRIx64" value 0x%x" +grlib_apbuart_readl_unknown(uint64_t addr) "addr 0x%"PRIx64 + +# hw/char/lm32_juart.c +lm32_juart_get_jtx(uint32_t value) "jtx 0x%08x" +lm32_juart_set_jtx(uint32_t value) "jtx 0x%08x" +lm32_juart_get_jrx(uint32_t value) "jrx 0x%08x" +lm32_juart_set_jrx(uint32_t value) "jrx 0x%08x" + +# hw/char/lm32_uart.c +lm32_uart_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" +lm32_uart_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" +lm32_uart_irq_state(int level) "irq state %d" + +# hw/char/milkymist-uart.c +milkymist_uart_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" +milkymist_uart_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" +milkymist_uart_raise_irq(void) "Raise IRQ" +milkymist_uart_lower_irq(void) "Lower IRQ" + +# hw/char/escc.c +escc_put_queue(char channel, int b) "channel %c put: 0x%02x" +escc_get_queue(char channel, int val) "channel %c get 0x%02x" +escc_update_irq(int irq) "IRQ = %d" +escc_update_parameters(char channel, int speed, int parity, int data_bits, int stop_bits) "channel %c: speed=%d parity=%c data=%d stop=%d" +escc_mem_writeb_ctrl(char channel, uint32_t reg, uint32_t val) "Write channel %c, reg[%d] = %2.2x" +escc_mem_writeb_data(char channel, uint32_t val) "Write channel %c, ch %d" +escc_mem_readb_ctrl(char channel, uint32_t reg, uint8_t val) "Read channel %c, reg[%d] = %2.2x" +escc_mem_readb_data(char channel, uint32_t ret) "Read channel %c, ch %d" +escc_serial_receive_byte(char channel, int ch) "channel %c put ch %d" +escc_sunkbd_event_in(int ch, const char *name, int down) "QKeyCode 0x%2.2x [%s], down %d" +escc_sunkbd_event_out(int ch) "Translated keycode 0x%2.2x" +escc_kbd_command(int val) "Command %d" +escc_sunmouse_event(int dx, int dy, int buttons_state) "dx=%d dy=%d buttons=%01x" diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c index 2e36481a7..4f0e03d3b 100644 --- a/hw/char/virtio-console.c +++ b/hw/char/virtio-console.c @@ -85,8 +85,9 @@ static void set_guest_connected(VirtIOSerialPort *port, int guest_connected) { VirtConsole *vcon = VIRTIO_CONSOLE(port); DeviceState *dev = DEVICE(port); + VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port); - if (vcon->chr) { + if (vcon->chr && !k->is_console) { qemu_chr_fe_set_open(vcon->chr, guest_connected); } @@ -156,9 +157,25 @@ static void virtconsole_realize(DeviceState *dev, Error **errp) } if (vcon->chr) { - vcon->chr->explicit_fe_open = 1; - qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event, - vcon); + /* + * For consoles we don't block guest data transfer just + * because nothing is connected - we'll just let it go + * whetherever the chardev wants - /dev/null probably. + * + * For serial ports we need 100% reliable data transfer + * so we use the opened/closed signals from chardev to + * trigger open/close of the device + */ + if (k->is_console) { + vcon->chr->explicit_fe_open = 0; + qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, + NULL, vcon); + virtio_serial_open(port); + } else { + vcon->chr->explicit_fe_open = 1; + qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, + chr_event, vcon); + } } } diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index 6e5de6dec..db57a3854 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -594,12 +594,6 @@ static void vser_reset(VirtIODevice *vdev) guest_reset(vser); } -static void virtio_serial_save(QEMUFile *f, void *opaque) -{ - /* The virtio device */ - virtio_save(VIRTIO_DEVICE(opaque), f); -} - static void virtio_serial_save_device(VirtIODevice *vdev, QEMUFile *f) { VirtIOSerial *s = VIRTIO_SERIAL(vdev); @@ -685,7 +679,7 @@ static void virtio_serial_post_load_timer_cb(void *opaque) s->post_load = NULL; } -static int fetch_active_ports_list(QEMUFile *f, int version_id, +static int fetch_active_ports_list(QEMUFile *f, VirtIOSerial *s, uint32_t nr_active_ports) { uint32_t i; @@ -702,6 +696,7 @@ static int fetch_active_ports_list(QEMUFile *f, int version_id, /* Items in struct VirtIOSerialPort */ for (i = 0; i < nr_active_ports; i++) { VirtIOSerialPort *port; + uint32_t elem_popped; uint32_t id; id = qemu_get_be32(f); @@ -714,37 +709,29 @@ static int fetch_active_ports_list(QEMUFile *f, int version_id, s->post_load->connected[i].port = port; s->post_load->connected[i].host_connected = qemu_get_byte(f); - if (version_id > 2) { - uint32_t elem_popped; - - qemu_get_be32s(f, &elem_popped); - if (elem_popped) { - qemu_get_be32s(f, &port->iov_idx); - qemu_get_be64s(f, &port->iov_offset); + qemu_get_be32s(f, &elem_popped); + if (elem_popped) { + qemu_get_be32s(f, &port->iov_idx); + qemu_get_be64s(f, &port->iov_offset); - port->elem = - qemu_get_virtqueue_element(f, sizeof(VirtQueueElement)); + port->elem = + qemu_get_virtqueue_element(f, sizeof(VirtQueueElement)); - /* - * Port was throttled on source machine. Let's - * unthrottle it here so data starts flowing again. - */ - virtio_serial_throttle_port(port, false); - } + /* + * Port was throttled on source machine. Let's + * unthrottle it here so data starts flowing again. + */ + virtio_serial_throttle_port(port, false); } } timer_mod(s->post_load->timer, 1); return 0; } -static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id) +static int virtio_serial_load(QEMUFile *f, void *opaque, size_t size) { - if (version_id > 3) { - return -EINVAL; - } - /* The virtio device */ - return virtio_load(VIRTIO_DEVICE(opaque), f, version_id); + return virtio_load(VIRTIO_DEVICE(opaque), f, 3); } static int virtio_serial_load_device(VirtIODevice *vdev, QEMUFile *f, @@ -756,10 +743,6 @@ static int virtio_serial_load_device(VirtIODevice *vdev, QEMUFile *f, int ret; uint32_t tmp; - if (version_id < 2) { - return 0; - } - /* Unused */ qemu_get_be16s(f, (uint16_t *) &tmp); qemu_get_be16s(f, (uint16_t *) &tmp); @@ -781,7 +764,7 @@ static int virtio_serial_load_device(VirtIODevice *vdev, QEMUFile *f, qemu_get_be32s(f, &nr_active_ports); if (nr_active_ports) { - ret = fetch_active_ports_list(f, version_id, s, nr_active_ports); + ret = fetch_active_ports_list(f, s, nr_active_ports); if (ret) { return ret; } @@ -1049,13 +1032,6 @@ static void virtio_serial_device_realize(DeviceState *dev, Error **errp) vser->post_load = NULL; - /* - * Register for the savevm section with the virtio-console name - * to preserve backward compat - */ - register_savevm(dev, "virtio-console", -1, 3, virtio_serial_save, - virtio_serial_load, vser); - QLIST_INSERT_HEAD(&vserdevices.devices, vser, next); } @@ -1086,8 +1062,6 @@ static void virtio_serial_device_unrealize(DeviceState *dev, Error **errp) QLIST_REMOVE(vser, next); - unregister_savevm(dev, "virtio-console", vser); - g_free(vser->ivqs); g_free(vser->ovqs); g_free(vser->ports_map); @@ -1100,6 +1074,9 @@ static void virtio_serial_device_unrealize(DeviceState *dev, Error **errp) virtio_cleanup(vdev); } +/* Note: 'console' is used for backwards compatibility */ +VMSTATE_VIRTIO_DEVICE(console, 3, virtio_serial_load, virtio_vmstate_save); + static Property virtio_serial_properties[] = { DEFINE_PROP_UINT32("max_ports", VirtIOSerial, serial.max_virtserial_ports, 31), @@ -1115,6 +1092,7 @@ static void virtio_serial_class_init(ObjectClass *klass, void *data) QLIST_INIT(&vserdevices.devices); dc->props = virtio_serial_properties; + dc->vmsd = &vmstate_virtio_console; set_bit(DEVICE_CATEGORY_INPUT, dc->categories); vdc->realize = virtio_serial_device_realize; vdc->unrealize = virtio_serial_device_unrealize; diff --git a/hw/char/xen_console.c b/hw/char/xen_console.c index cbf1dccbb..83108b0bd 100644 --- a/hw/char/xen_console.c +++ b/hw/char/xen_console.c @@ -22,7 +22,6 @@ #include "qemu/osdep.h" #include <sys/select.h> #include <termios.h> -#include <sys/mman.h> #include "hw/hw.h" #include "sysemu/char.h" diff --git a/hw/char/xilinx_uartlite.c b/hw/char/xilinx_uartlite.c index 911af4a0d..4847efb29 100644 --- a/hw/char/xilinx_uartlite.c +++ b/hw/char/xilinx_uartlite.c @@ -172,6 +172,11 @@ static const MemoryRegionOps uart_ops = { } }; +static Property xilinx_uartlite_properties[] = { + DEFINE_PROP_CHR("chardev", XilinxUARTLite, chr), + DEFINE_PROP_END_OF_LIST(), +}; + static void uart_rx(void *opaque, const uint8_t *buf, int size) { XilinxUARTLite *s = opaque; @@ -206,8 +211,6 @@ static void xilinx_uartlite_realize(DeviceState *dev, Error **errp) { XilinxUARTLite *s = XILINX_UARTLITE(dev); - /* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */ - s->chr = qemu_char_get_next_serial(); if (s->chr) qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s); } @@ -229,8 +232,7 @@ static void xilinx_uartlite_class_init(ObjectClass *klass, void *data) dc->reset = xilinx_uartlite_reset; dc->realize = xilinx_uartlite_realize; - /* Reason: realize() method uses qemu_char_get_next_serial() */ - dc->cannot_instantiate_with_device_add_yet = true; + dc->props = xilinx_uartlite_properties; } static const TypeInfo xilinx_uartlite_info = { |