summaryrefslogtreecommitdiffstats
path: root/qemu/hw/char
diff options
context:
space:
mode:
authorDon Dugger <n0ano@n0ano.com>2016-06-03 03:33:22 +0000
committerGerrit Code Review <gerrit@172.30.200.206>2016-06-03 03:33:23 +0000
commitda27230f80795d0028333713f036d44c53cb0e68 (patch)
treeb3d379eaf000adf72b36cb01cdf4d79c3e3f064c /qemu/hw/char
parent0e68cb048bb8aadb14675f5d4286d8ab2fc35449 (diff)
parent437fd90c0250dee670290f9b714253671a990160 (diff)
Merge "These changes are the raw update to qemu-2.6."
Diffstat (limited to 'qemu/hw/char')
-rw-r--r--qemu/hw/char/Makefile.objs1
-rw-r--r--qemu/hw/char/bcm2835_aux.c316
-rw-r--r--qemu/hw/char/cadence_uart.c8
-rw-r--r--qemu/hw/char/debugcon.c2
-rw-r--r--qemu/hw/char/digic-uart.c1
-rw-r--r--qemu/hw/char/escc.c18
-rw-r--r--qemu/hw/char/etraxfs_ser.c7
-rw-r--r--qemu/hw/char/exynos4210_uart.c16
-rw-r--r--qemu/hw/char/grlib_apbuart.c1
-rw-r--r--qemu/hw/char/imx_serial.c235
-rw-r--r--qemu/hw/char/ipoctal232.c1
-rw-r--r--qemu/hw/char/lm32_juart.c1
-rw-r--r--qemu/hw/char/lm32_uart.c1
-rw-r--r--qemu/hw/char/mcf_uart.c3
-rw-r--r--qemu/hw/char/milkymist-uart.c1
-rw-r--r--qemu/hw/char/omap_uart.c4
-rw-r--r--qemu/hw/char/parallel.c2
-rw-r--r--qemu/hw/char/pl011.c1
-rw-r--r--qemu/hw/char/sclpconsole-lm.c1
-rw-r--r--qemu/hw/char/sclpconsole.c1
-rw-r--r--qemu/hw/char/serial-isa.c2
-rw-r--r--qemu/hw/char/serial-pci.c2
-rw-r--r--qemu/hw/char/serial.c26
-rw-r--r--qemu/hw/char/sh_serial.c1
-rw-r--r--qemu/hw/char/spapr_vty.c4
-rw-r--r--qemu/hw/char/stm32f2xx_usart.c1
-rw-r--r--qemu/hw/char/virtio-console.c1
-rw-r--r--qemu/hw/char/virtio-serial-bus.c87
-rw-r--r--qemu/hw/char/xen_console.c26
-rw-r--r--qemu/hw/char/xilinx_uartlite.c1
30 files changed, 510 insertions, 262 deletions
diff --git a/qemu/hw/char/Makefile.objs b/qemu/hw/char/Makefile.objs
index 5931cc840..69a553cd8 100644
--- a/qemu/hw/char/Makefile.objs
+++ b/qemu/hw/char/Makefile.objs
@@ -16,6 +16,7 @@ obj-$(CONFIG_SH4) += sh_serial.o
obj-$(CONFIG_PSERIES) += spapr_vty.o
obj-$(CONFIG_DIGIC) += digic-uart.o
obj-$(CONFIG_STM32F2XX_USART) += stm32f2xx_usart.o
+obj-$(CONFIG_RASPI) += bcm2835_aux.o
common-obj-$(CONFIG_ETRAXFS) += etraxfs_ser.o
common-obj-$(CONFIG_ISA_DEBUG) += debugcon.o
diff --git a/qemu/hw/char/bcm2835_aux.c b/qemu/hw/char/bcm2835_aux.c
new file mode 100644
index 000000000..0394d11a8
--- /dev/null
+++ b/qemu/hw/char/bcm2835_aux.c
@@ -0,0 +1,316 @@
+/*
+ * BCM2835 (Raspberry Pi / Pi 2) Aux block (mini UART and SPI).
+ * Copyright (c) 2015, Microsoft
+ * Written by Andrew Baumann
+ * Based on pl011.c, copyright terms below:
+ *
+ * Arm PrimeCell PL011 UART
+ *
+ * Copyright (c) 2006 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the GPL.
+ *
+ * At present only the core UART functions (data path for tx/rx) are
+ * implemented. The following features/registers are unimplemented:
+ * - Line/modem control
+ * - Scratch register
+ * - Extra control
+ * - Baudrate
+ * - SPI interfaces
+ */
+
+#include "qemu/osdep.h"
+#include "hw/char/bcm2835_aux.h"
+
+#define AUX_IRQ 0x0
+#define AUX_ENABLES 0x4
+#define AUX_MU_IO_REG 0x40
+#define AUX_MU_IER_REG 0x44
+#define AUX_MU_IIR_REG 0x48
+#define AUX_MU_LCR_REG 0x4c
+#define AUX_MU_MCR_REG 0x50
+#define AUX_MU_LSR_REG 0x54
+#define AUX_MU_MSR_REG 0x58
+#define AUX_MU_SCRATCH 0x5c
+#define AUX_MU_CNTL_REG 0x60
+#define AUX_MU_STAT_REG 0x64
+#define AUX_MU_BAUD_REG 0x68
+
+/* bits in IER/IIR registers */
+#define TX_INT 0x1
+#define RX_INT 0x2
+
+static void bcm2835_aux_update(BCM2835AuxState *s)
+{
+ /* signal an interrupt if either:
+ * 1. rx interrupt is enabled and we have a non-empty rx fifo, or
+ * 2. the tx interrupt is enabled (since we instantly drain the tx fifo)
+ */
+ s->iir = 0;
+ if ((s->ier & RX_INT) && s->read_count != 0) {
+ s->iir |= RX_INT;
+ }
+ if (s->ier & TX_INT) {
+ s->iir |= TX_INT;
+ }
+ qemu_set_irq(s->irq, s->iir != 0);
+}
+
+static uint64_t bcm2835_aux_read(void *opaque, hwaddr offset, unsigned size)
+{
+ BCM2835AuxState *s = opaque;
+ uint32_t c, res;
+
+ switch (offset) {
+ case AUX_IRQ:
+ return s->iir != 0;
+
+ case AUX_ENABLES:
+ return 1; /* mini UART permanently enabled */
+
+ case AUX_MU_IO_REG:
+ /* "DLAB bit set means access baudrate register" is NYI */
+ c = s->read_fifo[s->read_pos];
+ if (s->read_count > 0) {
+ s->read_count--;
+ if (++s->read_pos == BCM2835_AUX_RX_FIFO_LEN) {
+ s->read_pos = 0;
+ }
+ }
+ if (s->chr) {
+ qemu_chr_accept_input(s->chr);
+ }
+ bcm2835_aux_update(s);
+ return c;
+
+ case AUX_MU_IER_REG:
+ /* "DLAB bit set means access baudrate register" is NYI */
+ return 0xc0 | s->ier; /* FIFO enables always read 1 */
+
+ case AUX_MU_IIR_REG:
+ res = 0xc0; /* FIFO enables */
+ /* The spec is unclear on what happens when both tx and rx
+ * interrupts are active, besides that this cannot occur. At
+ * present, we choose to prioritise the rx interrupt, since
+ * the tx fifo is always empty. */
+ if (s->read_count != 0) {
+ res |= 0x4;
+ } else {
+ res |= 0x2;
+ }
+ if (s->iir == 0) {
+ res |= 0x1;
+ }
+ return res;
+
+ case AUX_MU_LCR_REG:
+ qemu_log_mask(LOG_UNIMP, "%s: AUX_MU_LCR_REG unsupported\n", __func__);
+ return 0;
+
+ case AUX_MU_MCR_REG:
+ qemu_log_mask(LOG_UNIMP, "%s: AUX_MU_MCR_REG unsupported\n", __func__);
+ return 0;
+
+ case AUX_MU_LSR_REG:
+ res = 0x60; /* tx idle, empty */
+ if (s->read_count != 0) {
+ res |= 0x1;
+ }
+ return res;
+
+ case AUX_MU_MSR_REG:
+ qemu_log_mask(LOG_UNIMP, "%s: AUX_MU_MSR_REG unsupported\n", __func__);
+ return 0;
+
+ case AUX_MU_SCRATCH:
+ qemu_log_mask(LOG_UNIMP, "%s: AUX_MU_SCRATCH unsupported\n", __func__);
+ return 0;
+
+ case AUX_MU_CNTL_REG:
+ return 0x3; /* tx, rx enabled */
+
+ case AUX_MU_STAT_REG:
+ res = 0x30e; /* space in the output buffer, empty tx fifo, idle tx/rx */
+ if (s->read_count > 0) {
+ res |= 0x1; /* data in input buffer */
+ assert(s->read_count < BCM2835_AUX_RX_FIFO_LEN);
+ res |= ((uint32_t)s->read_count) << 16; /* rx fifo fill level */
+ }
+ return res;
+
+ case AUX_MU_BAUD_REG:
+ qemu_log_mask(LOG_UNIMP, "%s: AUX_MU_BAUD_REG unsupported\n", __func__);
+ return 0;
+
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
+ __func__, offset);
+ return 0;
+ }
+}
+
+static void bcm2835_aux_write(void *opaque, hwaddr offset, uint64_t value,
+ unsigned size)
+{
+ BCM2835AuxState *s = opaque;
+ unsigned char ch;
+
+ switch (offset) {
+ case AUX_ENABLES:
+ if (value != 1) {
+ qemu_log_mask(LOG_UNIMP, "%s: unsupported attempt to enable SPI "
+ "or disable UART\n", __func__);
+ }
+ break;
+
+ case AUX_MU_IO_REG:
+ /* "DLAB bit set means access baudrate register" is NYI */
+ ch = value;
+ if (s->chr) {
+ qemu_chr_fe_write(s->chr, &ch, 1);
+ }
+ break;
+
+ case AUX_MU_IER_REG:
+ /* "DLAB bit set means access baudrate register" is NYI */
+ s->ier = value & (TX_INT | RX_INT);
+ bcm2835_aux_update(s);
+ break;
+
+ case AUX_MU_IIR_REG:
+ if (value & 0x2) {
+ s->read_count = 0;
+ }
+ break;
+
+ case AUX_MU_LCR_REG:
+ qemu_log_mask(LOG_UNIMP, "%s: AUX_MU_LCR_REG unsupported\n", __func__);
+ break;
+
+ case AUX_MU_MCR_REG:
+ qemu_log_mask(LOG_UNIMP, "%s: AUX_MU_MCR_REG unsupported\n", __func__);
+ break;
+
+ case AUX_MU_SCRATCH:
+ qemu_log_mask(LOG_UNIMP, "%s: AUX_MU_SCRATCH unsupported\n", __func__);
+ break;
+
+ case AUX_MU_CNTL_REG:
+ qemu_log_mask(LOG_UNIMP, "%s: AUX_MU_CNTL_REG unsupported\n", __func__);
+ break;
+
+ case AUX_MU_BAUD_REG:
+ qemu_log_mask(LOG_UNIMP, "%s: AUX_MU_BAUD_REG unsupported\n", __func__);
+ break;
+
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
+ __func__, offset);
+ }
+
+ bcm2835_aux_update(s);
+}
+
+static int bcm2835_aux_can_receive(void *opaque)
+{
+ BCM2835AuxState *s = opaque;
+
+ return s->read_count < BCM2835_AUX_RX_FIFO_LEN;
+}
+
+static void bcm2835_aux_put_fifo(void *opaque, uint8_t value)
+{
+ BCM2835AuxState *s = opaque;
+ int slot;
+
+ slot = s->read_pos + s->read_count;
+ if (slot >= BCM2835_AUX_RX_FIFO_LEN) {
+ slot -= BCM2835_AUX_RX_FIFO_LEN;
+ }
+ s->read_fifo[slot] = value;
+ s->read_count++;
+ if (s->read_count == BCM2835_AUX_RX_FIFO_LEN) {
+ /* buffer full */
+ }
+ bcm2835_aux_update(s);
+}
+
+static void bcm2835_aux_receive(void *opaque, const uint8_t *buf, int size)
+{
+ bcm2835_aux_put_fifo(opaque, *buf);
+}
+
+static const MemoryRegionOps bcm2835_aux_ops = {
+ .read = bcm2835_aux_read,
+ .write = bcm2835_aux_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 4,
+};
+
+static const VMStateDescription vmstate_bcm2835_aux = {
+ .name = TYPE_BCM2835_AUX,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8_ARRAY(read_fifo, BCM2835AuxState,
+ BCM2835_AUX_RX_FIFO_LEN),
+ VMSTATE_UINT8(read_pos, BCM2835AuxState),
+ VMSTATE_UINT8(read_count, BCM2835AuxState),
+ VMSTATE_UINT8(ier, BCM2835AuxState),
+ VMSTATE_UINT8(iir, BCM2835AuxState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void bcm2835_aux_init(Object *obj)
+{
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ BCM2835AuxState *s = BCM2835_AUX(obj);
+
+ memory_region_init_io(&s->iomem, OBJECT(s), &bcm2835_aux_ops, s,
+ TYPE_BCM2835_AUX, 0x100);
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->irq);
+}
+
+static void bcm2835_aux_realize(DeviceState *dev, Error **errp)
+{
+ BCM2835AuxState *s = BCM2835_AUX(dev);
+
+ if (s->chr) {
+ qemu_chr_add_handlers(s->chr, bcm2835_aux_can_receive,
+ bcm2835_aux_receive, NULL, s);
+ }
+}
+
+static Property bcm2835_aux_props[] = {
+ DEFINE_PROP_CHR("chardev", BCM2835AuxState, chr),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void bcm2835_aux_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->realize = bcm2835_aux_realize;
+ dc->vmsd = &vmstate_bcm2835_aux;
+ set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
+ dc->props = bcm2835_aux_props;
+}
+
+static const TypeInfo bcm2835_aux_info = {
+ .name = TYPE_BCM2835_AUX,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(BCM2835AuxState),
+ .instance_init = bcm2835_aux_init,
+ .class_init = bcm2835_aux_class_init,
+};
+
+static void bcm2835_aux_register_types(void)
+{
+ type_register_static(&bcm2835_aux_info);
+}
+
+type_init(bcm2835_aux_register_types)
diff --git a/qemu/hw/char/cadence_uart.c b/qemu/hw/char/cadence_uart.c
index 9d379e5b1..797787823 100644
--- a/qemu/hw/char/cadence_uart.c
+++ b/qemu/hw/char/cadence_uart.c
@@ -16,6 +16,7 @@
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "qemu/osdep.h"
#include "hw/char/cadence_uart.h"
#ifdef CADENCE_UART_ERR_DEBUG
@@ -204,7 +205,7 @@ static void uart_parameters_setup(CadenceUARTState *s)
}
packet_size += ssp.data_bits + ssp.stop_bits;
- s->char_tx_time = (get_ticks_per_sec() / ssp.speed) * packet_size;
+ s->char_tx_time = (NANOSECONDS_PER_SECOND / ssp.speed) * packet_size;
if (s->chr) {
qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
}
@@ -374,6 +375,9 @@ static void uart_write(void *opaque, hwaddr offset,
DB_PRINT(" offset:%x data:%08x\n", (unsigned)offset, (unsigned)value);
offset >>= 2;
+ if (offset >= CADENCE_UART_R_MAX) {
+ return;
+ }
switch (offset) {
case R_IER: /* ier (wts imr) */
s->r[R_IMR] |= value;
@@ -478,7 +482,7 @@ static void cadence_uart_init(Object *obj)
sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->irq);
- s->char_tx_time = (get_ticks_per_sec() / 9600) * 10;
+ s->char_tx_time = (NANOSECONDS_PER_SECOND / 9600) * 10;
}
static int cadence_uart_post_load(void *opaque, int version_id)
diff --git a/qemu/hw/char/debugcon.c b/qemu/hw/char/debugcon.c
index 36f1c4adb..e7f025ec6 100644
--- a/qemu/hw/char/debugcon.c
+++ b/qemu/hw/char/debugcon.c
@@ -24,6 +24,8 @@
* THE SOFTWARE.
*/
+#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "hw/hw.h"
#include "sysemu/char.h"
#include "hw/isa/isa.h"
diff --git a/qemu/hw/char/digic-uart.c b/qemu/hw/char/digic-uart.c
index 6d44576ff..d3bc533d7 100644
--- a/qemu/hw/char/digic-uart.c
+++ b/qemu/hw/char/digic-uart.c
@@ -26,6 +26,7 @@
*
*/
+#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/sysbus.h"
#include "sysemu/char.h"
diff --git a/qemu/hw/char/escc.c b/qemu/hw/char/escc.c
index ba653efd6..7bf09a007 100644
--- a/qemu/hw/char/escc.c
+++ b/qemu/hw/char/escc.c
@@ -22,6 +22,7 @@
* THE SOFTWARE.
*/
+#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/sysbus.h"
#include "hw/char/escc.h"
@@ -714,7 +715,7 @@ MemoryRegion *escc_init(hwaddr base, qemu_irq irqA, qemu_irq irqB,
return &d->mmio;
}
-static const uint8_t qcode_to_keycode[Q_KEY_CODE_MAX] = {
+static const uint8_t qcode_to_keycode[Q_KEY_CODE__MAX] = {
[Q_KEY_CODE_SHIFT] = 99,
[Q_KEY_CODE_SHIFT_R] = 110,
[Q_KEY_CODE_ALT] = 19,
@@ -841,14 +842,16 @@ static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src,
{
ChannelState *s = (ChannelState *)dev;
int qcode, keycode;
+ InputKeyEvent *key;
- assert(evt->kind == INPUT_EVENT_KIND_KEY);
- qcode = qemu_input_key_value_to_qcode(evt->key->key);
+ assert(evt->type == INPUT_EVENT_KIND_KEY);
+ key = evt->u.key.data;
+ qcode = qemu_input_key_value_to_qcode(key->key);
trace_escc_sunkbd_event_in(qcode, QKeyCode_lookup[qcode],
- evt->key->down);
+ key->down);
if (qcode == Q_KEY_CODE_CAPS_LOCK) {
- if (evt->key->down) {
+ if (key->down) {
s->caps_lock_mode ^= 1;
if (s->caps_lock_mode == 2) {
return; /* Drop second press */
@@ -862,7 +865,7 @@ static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src,
}
if (qcode == Q_KEY_CODE_NUM_LOCK) {
- if (evt->key->down) {
+ if (key->down) {
s->num_lock_mode ^= 1;
if (s->num_lock_mode == 2) {
return; /* Drop second press */
@@ -876,7 +879,7 @@ static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src,
}
keycode = qcode_to_keycode[qcode];
- if (!evt->key->down) {
+ if (!key->down) {
keycode |= 0x80;
}
trace_escc_sunkbd_event_out(keycode);
@@ -1035,6 +1038,7 @@ static void escc_class_init(ObjectClass *klass, void *data)
dc->reset = escc_reset;
dc->vmsd = &vmstate_escc;
dc->props = escc_properties;
+ set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
}
static const TypeInfo escc_info = {
diff --git a/qemu/hw/char/etraxfs_ser.c b/qemu/hw/char/etraxfs_ser.c
index 857c13621..146b387e7 100644
--- a/qemu/hw/char/etraxfs_ser.c
+++ b/qemu/hw/char/etraxfs_ser.c
@@ -22,6 +22,7 @@
* THE SOFTWARE.
*/
+#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "sysemu/char.h"
#include "qemu/log.h"
@@ -165,7 +166,7 @@ static void serial_receive(void *opaque, const uint8_t *buf, int size)
/* Got a byte. */
if (s->rx_fifo_len >= 16) {
- qemu_log("WARNING: UART dropped char.\n");
+ D(qemu_log("WARNING: UART dropped char.\n"));
return;
}
@@ -182,15 +183,13 @@ static void serial_receive(void *opaque, const uint8_t *buf, int size)
static int serial_can_receive(void *opaque)
{
ETRAXSerial *s = opaque;
- int r;
/* Is the receiver enabled? */
if (!(s->regs[RW_REC_CTRL] & (1 << 3))) {
return 0;
}
- r = sizeof(s->rx_fifo) - s->rx_fifo_len;
- return r;
+ return sizeof(s->rx_fifo) - s->rx_fifo_len;
}
static void serial_event(void *opaque, int event)
diff --git a/qemu/hw/char/exynos4210_uart.c b/qemu/hw/char/exynos4210_uart.c
index 7614e5860..885ecc027 100644
--- a/qemu/hw/char/exynos4210_uart.c
+++ b/qemu/hw/char/exynos4210_uart.c
@@ -19,7 +19,9 @@
*
*/
+#include "qemu/osdep.h"
#include "hw/sysbus.h"
+#include "qemu/error-report.h"
#include "sysemu/sysemu.h"
#include "sysemu/char.h"
@@ -234,10 +236,8 @@ static int fifo_empty_elements_number(Exynos4210UartFIFO *q)
static void fifo_reset(Exynos4210UartFIFO *q)
{
- if (q->data != NULL) {
- g_free(q->data);
- q->data = NULL;
- }
+ g_free(q->data);
+ q->data = NULL;
q->data = (uint8_t *)g_malloc0(q->size);
@@ -597,15 +597,17 @@ DeviceState *exynos4210_uart_create(hwaddr addr,
if (!chr) {
if (channel >= MAX_SERIAL_PORTS) {
- hw_error("Only %d serial ports are supported by QEMU.\n",
- MAX_SERIAL_PORTS);
+ error_report("Only %d serial ports are supported by QEMU",
+ MAX_SERIAL_PORTS);
+ exit(1);
}
chr = serial_hds[channel];
if (!chr) {
snprintf(label, ARRAY_SIZE(label), "%s%d", chr_name, channel);
chr = qemu_chr_new(label, "null", NULL);
if (!(chr)) {
- hw_error("Can't assign serial port to UART%d.\n", channel);
+ error_report("Can't assign serial port to UART%d", channel);
+ exit(1);
}
}
}
diff --git a/qemu/hw/char/grlib_apbuart.c b/qemu/hw/char/grlib_apbuart.c
index 35ef66177..871524c82 100644
--- a/qemu/hw/char/grlib_apbuart.c
+++ b/qemu/hw/char/grlib_apbuart.c
@@ -22,6 +22,7 @@
* THE SOFTWARE.
*/
+#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "sysemu/char.h"
diff --git a/qemu/hw/char/imx_serial.c b/qemu/hw/char/imx_serial.c
index f3fbc776b..6df74ac7c 100644
--- a/qemu/hw/char/imx_serial.c
+++ b/qemu/hw/char/imx_serial.c
@@ -4,6 +4,7 @@
* Copyright (c) 2008 OKL
* Originally Written by Hans Jiang
* Copyright (c) 2011 NICTA Pty Ltd.
+ * Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
@@ -17,63 +18,25 @@
* is a real serial device.
*/
-#include "hw/hw.h"
-#include "hw/sysbus.h"
+#include "qemu/osdep.h"
+#include "hw/char/imx_serial.h"
#include "sysemu/sysemu.h"
#include "sysemu/char.h"
-#include "hw/arm/imx.h"
-//#define DEBUG_SERIAL 1
-#ifdef DEBUG_SERIAL
-#define DPRINTF(fmt, args...) \
-do { printf("imx_serial: " fmt , ##args); } while (0)
-#else
-#define DPRINTF(fmt, args...) do {} while (0)
-#endif
-
-/*
- * Define to 1 for messages about attempts to
- * access unimplemented registers or similar.
- */
-//#define DEBUG_IMPLEMENTATION 1
-#ifdef DEBUG_IMPLEMENTATION
-# define IPRINTF(fmt, args...) \
- do { fprintf(stderr, "imx_serial: " fmt, ##args); } while (0)
-#else
-# define IPRINTF(fmt, args...) do {} while (0)
+#ifndef DEBUG_IMX_UART
+#define DEBUG_IMX_UART 0
#endif
-#define TYPE_IMX_SERIAL "imx-serial"
-#define IMX_SERIAL(obj) OBJECT_CHECK(IMXSerialState, (obj), TYPE_IMX_SERIAL)
-
-typedef struct IMXSerialState {
- SysBusDevice parent_obj;
-
- MemoryRegion iomem;
- int32_t readbuff;
-
- uint32_t usr1;
- uint32_t usr2;
- uint32_t ucr1;
- uint32_t ucr2;
- uint32_t uts1;
-
- /*
- * The registers below are implemented just so that the
- * guest OS sees what it has written
- */
- uint32_t onems;
- uint32_t ufcr;
- uint32_t ubmr;
- uint32_t ubrc;
- uint32_t ucr3;
-
- qemu_irq irq;
- CharDriverState *chr;
-} IMXSerialState;
+#define DPRINTF(fmt, args...) \
+ do { \
+ if (DEBUG_IMX_UART) { \
+ fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_SERIAL, \
+ __func__, ##args); \
+ } \
+ } while (0)
static const VMStateDescription vmstate_imx_serial = {
- .name = "imx-serial",
+ .name = TYPE_IMX_SERIAL,
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
@@ -91,61 +54,14 @@ static const VMStateDescription vmstate_imx_serial = {
},
};
-
-#define URXD_CHARRDY (1<<15) /* character read is valid */
-#define URXD_ERR (1<<14) /* Character has error */
-#define URXD_BRK (1<<11) /* Break received */
-
-#define USR1_PARTYER (1<<15) /* Parity Error */
-#define USR1_RTSS (1<<14) /* RTS pin status */
-#define USR1_TRDY (1<<13) /* Tx ready */
-#define USR1_RTSD (1<<12) /* RTS delta: pin changed state */
-#define USR1_ESCF (1<<11) /* Escape sequence interrupt */
-#define USR1_FRAMERR (1<<10) /* Framing error */
-#define USR1_RRDY (1<<9) /* receiver ready */
-#define USR1_AGTIM (1<<8) /* Aging timer interrupt */
-#define USR1_DTRD (1<<7) /* DTR changed */
-#define USR1_RXDS (1<<6) /* Receiver is idle */
-#define USR1_AIRINT (1<<5) /* Aysnch IR interrupt */
-#define USR1_AWAKE (1<<4) /* Falling edge detected on RXd pin */
-
-#define USR2_ADET (1<<15) /* Autobaud complete */
-#define USR2_TXFE (1<<14) /* Transmit FIFO empty */
-#define USR2_DTRF (1<<13) /* DTR/DSR transition */
-#define USR2_IDLE (1<<12) /* UART has been idle for too long */
-#define USR2_ACST (1<<11) /* Autobaud counter stopped */
-#define USR2_RIDELT (1<<10) /* Ring Indicator delta */
-#define USR2_RIIN (1<<9) /* Ring Indicator Input */
-#define USR2_IRINT (1<<8) /* Serial Infrared Interrupt */
-#define USR2_WAKE (1<<7) /* Start bit detected */
-#define USR2_DCDDELT (1<<6) /* Data Carrier Detect delta */
-#define USR2_DCDIN (1<<5) /* Data Carrier Detect Input */
-#define USR2_RTSF (1<<4) /* RTS transition */
-#define USR2_TXDC (1<<3) /* Transmission complete */
-#define USR2_BRCD (1<<2) /* Break condition detected */
-#define USR2_ORE (1<<1) /* Overrun error */
-#define USR2_RDR (1<<0) /* Receive data ready */
-
-#define UCR1_TRDYEN (1<<13) /* Tx Ready Interrupt Enable */
-#define UCR1_RRDYEN (1<<9) /* Rx Ready Interrupt Enable */
-#define UCR1_TXMPTYEN (1<<6) /* Tx Empty Interrupt Enable */
-#define UCR1_UARTEN (1<<0) /* UART Enable */
-
-#define UCR2_TXEN (1<<2) /* Transmitter enable */
-#define UCR2_RXEN (1<<1) /* Receiver enable */
-#define UCR2_SRST (1<<0) /* Reset complete */
-
-#define UTS1_TXEMPTY (1<<6)
-#define UTS1_RXEMPTY (1<<5)
-#define UTS1_TXFULL (1<<4)
-#define UTS1_RXFULL (1<<3)
-
static void imx_update(IMXSerialState *s)
{
uint32_t flags;
flags = (s->usr1 & s->ucr1) & (USR1_TRDY|USR1_RRDY);
- if (!(s->ucr1 & UCR1_TXMPTYEN)) {
+ if (s->ucr1 & UCR1_TXMPTYEN) {
+ flags |= (s->uts1 & UTS1_TXEMPTY);
+ } else {
flags &= ~USR1_TRDY;
}
@@ -192,7 +108,8 @@ static uint64_t imx_serial_read(void *opaque, hwaddr offset,
IMXSerialState *s = (IMXSerialState *)opaque;
uint32_t c;
- DPRINTF("read(offset=%x)\n", offset >> 2);
+ DPRINTF("read(offset=0x%" HWADDR_PRIx ")\n", offset);
+
switch (offset >> 2) {
case 0x0: /* URXD */
c = s->readbuff;
@@ -203,7 +120,9 @@ static uint64_t imx_serial_read(void *opaque, hwaddr offset,
s->usr2 &= ~USR2_RDR;
s->uts1 |= UTS1_RXEMPTY;
imx_update(s);
- qemu_chr_accept_input(s->chr);
+ if (s->chr) {
+ qemu_chr_accept_input(s->chr);
+ }
}
return c;
@@ -242,20 +161,20 @@ static uint64_t imx_serial_read(void *opaque, hwaddr offset,
return 0x0; /* TODO */
default:
- IPRINTF("imx_serial_read: bad offset: 0x%x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
+ HWADDR_PRIx "\n", TYPE_IMX_SERIAL, __func__, offset);
return 0;
}
}
static void imx_serial_write(void *opaque, hwaddr offset,
- uint64_t value, unsigned size)
+ uint64_t value, unsigned size)
{
IMXSerialState *s = (IMXSerialState *)opaque;
unsigned char ch;
- DPRINTF("write(offset=%x, value = %x) to %s\n",
- offset >> 2,
- (unsigned int)value, s->chr ? s->chr->label : "NODEV");
+ DPRINTF("write(offset=0x%" HWADDR_PRIx ", value = 0x%x) to %s\n",
+ offset, (unsigned int)value, s->chr ? s->chr->label : "NODEV");
switch (offset >> 2) {
case 0x10: /* UTXD */
@@ -273,7 +192,9 @@ static void imx_serial_write(void *opaque, hwaddr offset,
case 0x20: /* UCR1 */
s->ucr1 = value & 0xffff;
+
DPRINTF("write(ucr1=%x)\n", (unsigned int)value);
+
imx_update(s);
break;
@@ -290,7 +211,9 @@ static void imx_serial_write(void *opaque, hwaddr offset,
}
if (value & UCR2_RXEN) {
if (!(s->ucr2 & UCR2_RXEN)) {
- qemu_chr_accept_input(s->chr);
+ if (s->chr) {
+ qemu_chr_accept_input(s->chr);
+ }
}
}
s->ucr2 = value & 0xffff;
@@ -298,25 +221,25 @@ static void imx_serial_write(void *opaque, hwaddr offset,
case 0x25: /* USR1 */
value &= USR1_AWAKE | USR1_AIRINT | USR1_DTRD | USR1_AGTIM |
- USR1_FRAMERR | USR1_ESCF | USR1_RTSD | USR1_PARTYER;
+ USR1_FRAMERR | USR1_ESCF | USR1_RTSD | USR1_PARTYER;
s->usr1 &= ~value;
break;
case 0x26: /* USR2 */
- /*
- * Writing 1 to some bits clears them; all other
- * values are ignored
- */
+ /*
+ * Writing 1 to some bits clears them; all other
+ * values are ignored
+ */
value &= USR2_ADET | USR2_DTRF | USR2_IDLE | USR2_ACST |
- USR2_RIDELT | USR2_IRINT | USR2_WAKE |
- USR2_DCDDELT | USR2_RTSF | USR2_BRCD | USR2_ORE;
+ USR2_RIDELT | USR2_IRINT | USR2_WAKE |
+ USR2_DCDDELT | USR2_RTSF | USR2_BRCD | USR2_ORE;
s->usr2 &= ~value;
break;
- /*
- * Linux expects to see what it writes to these registers
- * We don't currently alter the baud rate
- */
+ /*
+ * Linux expects to see what it writes to these registers
+ * We don't currently alter the baud rate
+ */
case 0x29: /* UBIR */
s->ubrc = value & 0xffff;
break;
@@ -339,12 +262,14 @@ static void imx_serial_write(void *opaque, hwaddr offset,
case 0x2d: /* UTS1 */
case 0x23: /* UCR4 */
- IPRINTF("Unimplemented Register %x written to\n", offset >> 2);
+ qemu_log_mask(LOG_UNIMP, "[%s]%s: Unimplemented reg 0x%"
+ HWADDR_PRIx "\n", TYPE_IMX_SERIAL, __func__, offset);
/* TODO */
break;
default:
- IPRINTF("imx_serial_write: Bad offset 0x%x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
+ HWADDR_PRIx "\n", TYPE_IMX_SERIAL, __func__, offset);
}
}
@@ -357,7 +282,9 @@ static int imx_can_receive(void *opaque)
static void imx_put_data(void *opaque, uint32_t value)
{
IMXSerialState *s = (IMXSerialState *)opaque;
+
DPRINTF("received char\n");
+
s->usr1 |= USR1_RRDY;
s->usr2 |= USR2_RDR;
s->uts1 &= ~UTS1_RXEMPTY;
@@ -384,62 +311,30 @@ static const struct MemoryRegionOps imx_serial_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int imx_serial_init(SysBusDevice *dev)
+static void imx_serial_realize(DeviceState *dev, Error **errp)
{
IMXSerialState *s = IMX_SERIAL(dev);
-
- memory_region_init_io(&s->iomem, OBJECT(s), &imx_serial_ops, s,
- "imx-serial", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
- sysbus_init_irq(dev, &s->irq);
-
if (s->chr) {
qemu_chr_add_handlers(s->chr, imx_can_receive, imx_receive,
imx_event, s);
} else {
- DPRINTF("No char dev for uart at 0x%lx\n",
- (unsigned long)s->iomem.ram_addr);
+ DPRINTF("No char dev for uart\n");
}
-
- return 0;
}
-void imx_serial_create(int uart, const hwaddr addr, qemu_irq irq)
+static void imx_serial_init(Object *obj)
{
- DeviceState *dev;
- SysBusDevice *bus;
- CharDriverState *chr;
- const char chr_name[] = "serial";
- char label[ARRAY_SIZE(chr_name) + 1];
-
- dev = qdev_create(NULL, TYPE_IMX_SERIAL);
-
- if (uart >= MAX_SERIAL_PORTS) {
- hw_error("Cannot assign uart %d: QEMU supports only %d ports\n",
- uart, MAX_SERIAL_PORTS);
- }
- chr = serial_hds[uart];
- if (!chr) {
- snprintf(label, ARRAY_SIZE(label), "%s%d", chr_name, uart);
- chr = qemu_chr_new(label, "null", NULL);
- if (!(chr)) {
- hw_error("Can't assign serial port to imx-uart%d.\n", uart);
- }
- }
-
- qdev_prop_set_chr(dev, "chardev", chr);
- bus = SYS_BUS_DEVICE(dev);
- qdev_init_nofail(dev);
- if (addr != (hwaddr)-1) {
- sysbus_mmio_map(bus, 0, addr);
- }
- sysbus_connect_irq(bus, 0, irq);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ IMXSerialState *s = IMX_SERIAL(obj);
+ memory_region_init_io(&s->iomem, obj, &imx_serial_ops, s,
+ TYPE_IMX_SERIAL, 0x1000);
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->irq);
}
-
-static Property imx32_serial_properties[] = {
+static Property imx_serial_properties[] = {
DEFINE_PROP_CHR("chardev", IMXSerialState, chr),
DEFINE_PROP_END_OF_LIST(),
};
@@ -447,21 +342,21 @@ static Property imx32_serial_properties[] = {
static void imx_serial_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = imx_serial_init;
+ dc->realize = imx_serial_realize;
dc->vmsd = &vmstate_imx_serial;
dc->reset = imx_serial_reset_at_boot;
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
dc->desc = "i.MX series UART";
- dc->props = imx32_serial_properties;
+ dc->props = imx_serial_properties;
}
static const TypeInfo imx_serial_info = {
- .name = TYPE_IMX_SERIAL,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(IMXSerialState),
- .class_init = imx_serial_class_init,
+ .name = TYPE_IMX_SERIAL,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(IMXSerialState),
+ .instance_init = imx_serial_init,
+ .class_init = imx_serial_class_init,
};
static void imx_serial_register_types(void)
diff --git a/qemu/hw/char/ipoctal232.c b/qemu/hw/char/ipoctal232.c
index c8d5cdb36..bc0ae4980 100644
--- a/qemu/hw/char/ipoctal232.c
+++ b/qemu/hw/char/ipoctal232.c
@@ -8,6 +8,7 @@
* later version.
*/
+#include "qemu/osdep.h"
#include "hw/ipack/ipack.h"
#include "qemu/bitops.h"
#include "sysemu/char.h"
diff --git a/qemu/hw/char/lm32_juart.c b/qemu/hw/char/lm32_juart.c
index 62763f2f4..5bf8acfe8 100644
--- a/qemu/hw/char/lm32_juart.c
+++ b/qemu/hw/char/lm32_juart.c
@@ -17,6 +17,7 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/sysbus.h"
#include "trace.h"
diff --git a/qemu/hw/char/lm32_uart.c b/qemu/hw/char/lm32_uart.c
index 837a46e8e..036813d0f 100644
--- a/qemu/hw/char/lm32_uart.c
+++ b/qemu/hw/char/lm32_uart.c
@@ -22,6 +22,7 @@
*/
+#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/sysbus.h"
#include "trace.h"
diff --git a/qemu/hw/char/mcf_uart.c b/qemu/hw/char/mcf_uart.c
index 98fd44e66..3c0438fd7 100644
--- a/qemu/hw/char/mcf_uart.c
+++ b/qemu/hw/char/mcf_uart.c
@@ -5,6 +5,7 @@
*
* This code is licensed under the GPL
*/
+#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/m68k/mcf.h"
#include "sysemu/char.h"
@@ -126,7 +127,7 @@ static void mcf_uart_do_tx(mcf_uart_state *s)
static void mcf_do_command(mcf_uart_state *s, uint8_t cmd)
{
/* Misc command. */
- switch ((cmd >> 4) & 3) {
+ switch ((cmd >> 4) & 7) {
case 0: /* No-op. */
break;
case 1: /* Reset mode register pointer. */
diff --git a/qemu/hw/char/milkymist-uart.c b/qemu/hw/char/milkymist-uart.c
index 9b89b7e63..03b36b223 100644
--- a/qemu/hw/char/milkymist-uart.c
+++ b/qemu/hw/char/milkymist-uart.c
@@ -21,6 +21,7 @@
* http://www.milkymist.org/socdoc/uart.pdf
*/
+#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/sysbus.h"
#include "trace.h"
diff --git a/qemu/hw/char/omap_uart.c b/qemu/hw/char/omap_uart.c
index 88f20943e..415bec5fa 100644
--- a/qemu/hw/char/omap_uart.c
+++ b/qemu/hw/char/omap_uart.c
@@ -17,6 +17,7 @@
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "qemu/osdep.h"
#include "sysemu/char.h"
#include "hw/hw.h"
#include "hw/arm/omap.h"
@@ -55,8 +56,7 @@ struct omap_uart_s *omap_uart_init(hwaddr base,
qemu_irq txdma, qemu_irq rxdma,
const char *label, CharDriverState *chr)
{
- struct omap_uart_s *s = (struct omap_uart_s *)
- g_malloc0(sizeof(struct omap_uart_s));
+ struct omap_uart_s *s = g_new0(struct omap_uart_s, 1);
s->base = base;
s->fclk = fclk;
diff --git a/qemu/hw/char/parallel.c b/qemu/hw/char/parallel.c
index c2b553f0d..11c78fed8 100644
--- a/qemu/hw/char/parallel.c
+++ b/qemu/hw/char/parallel.c
@@ -22,6 +22,8 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "hw/hw.h"
#include "sysemu/char.h"
#include "hw/isa/isa.h"
diff --git a/qemu/hw/char/pl011.c b/qemu/hw/char/pl011.c
index eac6fac09..210c87b4c 100644
--- a/qemu/hw/char/pl011.c
+++ b/qemu/hw/char/pl011.c
@@ -7,6 +7,7 @@
* This code is licensed under the GPL.
*/
+#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "sysemu/char.h"
diff --git a/qemu/hw/char/sclpconsole-lm.c b/qemu/hw/char/sclpconsole-lm.c
index 02ac80b65..7d4ff8120 100644
--- a/qemu/hw/char/sclpconsole-lm.c
+++ b/qemu/hw/char/sclpconsole-lm.c
@@ -13,6 +13,7 @@
*
*/
+#include "qemu/osdep.h"
#include "hw/qdev.h"
#include "qemu/thread.h"
#include "qemu/error-report.h"
diff --git a/qemu/hw/char/sclpconsole.c b/qemu/hw/char/sclpconsole.c
index b014c7f52..45997ff4a 100644
--- a/qemu/hw/char/sclpconsole.c
+++ b/qemu/hw/char/sclpconsole.c
@@ -12,6 +12,7 @@
*
*/
+#include "qemu/osdep.h"
#include <hw/qdev.h>
#include "qemu/thread.h"
#include "qemu/error-report.h"
diff --git a/qemu/hw/char/serial-isa.c b/qemu/hw/char/serial-isa.c
index f3db024d0..1594ec4db 100644
--- a/qemu/hw/char/serial-isa.c
+++ b/qemu/hw/char/serial-isa.c
@@ -23,6 +23,8 @@
* THE SOFTWARE.
*/
+#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "hw/char/serial.h"
#include "hw/isa/isa.h"
diff --git a/qemu/hw/char/serial-pci.c b/qemu/hw/char/serial-pci.c
index 1c8b9be5c..303104dd1 100644
--- a/qemu/hw/char/serial-pci.c
+++ b/qemu/hw/char/serial-pci.c
@@ -25,6 +25,8 @@
/* see docs/specs/pci-serial.txt */
+#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "hw/char/serial.h"
#include "hw/pci/pci.h"
diff --git a/qemu/hw/char/serial.c b/qemu/hw/char/serial.c
index 513d73c27..6d815b5c6 100644
--- a/qemu/hw/char/serial.c
+++ b/qemu/hw/char/serial.c
@@ -23,8 +23,10 @@
* THE SOFTWARE.
*/
+#include "qemu/osdep.h"
#include "hw/char/serial.h"
#include "sysemu/char.h"
+#include "qapi/error.h"
#include "qemu/timer.h"
#include "exec/address-spaces.h"
#include "qemu/error-report.h"
@@ -177,7 +179,7 @@ static void serial_update_parameters(SerialState *s)
ssp.parity = parity;
ssp.data_bits = data_bits;
ssp.stop_bits = stop_bits;
- s->char_transmit_time = (get_ticks_per_sec() / speed) * frame_size;
+ s->char_transmit_time = (NANOSECONDS_PER_SECOND / speed) * frame_size;
qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
DPRINTF("speed=%d parity=%c data=%d stop=%d\n",
@@ -215,8 +217,10 @@ static void serial_update_msl(SerialState *s)
/* The real 16550A apparently has a 250ns response latency to line status changes.
We'll be lazy and poll only every 10ms, and only poll it at all if MSI interrupts are turned on */
- if (s->poll_msl)
- timer_mod(s->modem_status_poll, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + get_ticks_per_sec() / 100);
+ if (s->poll_msl) {
+ timer_mod(s->modem_status_poll, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+ NANOSECONDS_PER_SECOND / 100);
+ }
}
static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
@@ -822,7 +826,7 @@ static void serial_reset(void *opaque)
s->mcr = UART_MCR_OUT2;
s->scr = 0;
s->tsr_retry = 0;
- s->char_transmit_time = (get_ticks_per_sec() / 9600) * 10;
+ s->char_transmit_time = (NANOSECONDS_PER_SECOND / 9600) * 10;
s->poll_msl = 0;
s->timeout_ipending = 0;
@@ -888,18 +892,13 @@ SerialState *serial_init(int base, qemu_irq irq, int baudbase,
CharDriverState *chr, MemoryRegion *system_io)
{
SerialState *s;
- Error *err = NULL;
s = g_malloc0(sizeof(SerialState));
s->irq = irq;
s->baudbase = baudbase;
s->chr = chr;
- serial_realize_core(s, &err);
- if (err != NULL) {
- error_report_err(err);
- exit(1);
- }
+ serial_realize_core(s, &error_fatal);
vmstate_register(NULL, base, &vmstate_serial, s);
@@ -949,7 +948,6 @@ SerialState *serial_mm_init(MemoryRegion *address_space,
CharDriverState *chr, enum device_endian end)
{
SerialState *s;
- Error *err = NULL;
s = g_malloc0(sizeof(SerialState));
@@ -958,11 +956,7 @@ SerialState *serial_mm_init(MemoryRegion *address_space,
s->baudbase = baudbase;
s->chr = chr;
- serial_realize_core(s, &err);
- if (err != NULL) {
- error_report_err(err);
- exit(1);
- }
+ serial_realize_core(s, &error_fatal);
vmstate_register(NULL, base, &vmstate_serial, s);
memory_region_init_io(&s->io, NULL, &serial_mm_ops[end], s,
diff --git a/qemu/hw/char/sh_serial.c b/qemu/hw/char/sh_serial.c
index 9328dd1b5..4c55dcb7d 100644
--- a/qemu/hw/char/sh_serial.c
+++ b/qemu/hw/char/sh_serial.c
@@ -24,6 +24,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/sh4/sh.h"
#include "sysemu/char.h"
diff --git a/qemu/hw/char/spapr_vty.c b/qemu/hw/char/spapr_vty.c
index 36b328b9a..3498d7b05 100644
--- a/qemu/hw/char/spapr_vty.c
+++ b/qemu/hw/char/spapr_vty.c
@@ -1,3 +1,7 @@
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "cpu.h"
#include "hw/qdev.h"
#include "sysemu/char.h"
#include "hw/ppc/spapr.h"
diff --git a/qemu/hw/char/stm32f2xx_usart.c b/qemu/hw/char/stm32f2xx_usart.c
index c9d3a1be7..a94d61ceb 100644
--- a/qemu/hw/char/stm32f2xx_usart.c
+++ b/qemu/hw/char/stm32f2xx_usart.c
@@ -22,6 +22,7 @@
* THE SOFTWARE.
*/
+#include "qemu/osdep.h"
#include "hw/char/stm32f2xx_usart.h"
#ifndef STM_USART_ERR_DEBUG
diff --git a/qemu/hw/char/virtio-console.c b/qemu/hw/char/virtio-console.c
index 2a867cb4e..2e36481a7 100644
--- a/qemu/hw/char/virtio-console.c
+++ b/qemu/hw/char/virtio-console.c
@@ -10,6 +10,7 @@
* the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include "sysemu/char.h"
#include "qemu/error-report.h"
#include "trace.h"
diff --git a/qemu/hw/char/virtio-serial-bus.c b/qemu/hw/char/virtio-serial-bus.c
index bc56f5d52..6e5de6dec 100644
--- a/qemu/hw/char/virtio-serial-bus.c
+++ b/qemu/hw/char/virtio-serial-bus.c
@@ -18,6 +18,8 @@
* GNU GPL, version 2 or (at your option) any later version.
*/
+#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "qemu/iov.h"
#include "monitor/monitor.h"
#include "qemu/error-report.h"
@@ -76,13 +78,13 @@ static VirtIOSerialPort *find_port_by_name(char *name)
static bool use_multiport(VirtIOSerial *vser)
{
VirtIODevice *vdev = VIRTIO_DEVICE(vser);
- return virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT);
+ return virtio_vdev_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT);
}
static size_t write_to_port(VirtIOSerialPort *port,
const uint8_t *buf, size_t size)
{
- VirtQueueElement elem;
+ VirtQueueElement *elem;
VirtQueue *vq;
size_t offset;
@@ -95,15 +97,17 @@ static size_t write_to_port(VirtIOSerialPort *port,
while (offset < size) {
size_t len;
- if (!virtqueue_pop(vq, &elem)) {
+ elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
+ if (!elem) {
break;
}
- len = iov_from_buf(elem.in_sg, elem.in_num, 0,
+ len = iov_from_buf(elem->in_sg, elem->in_num, 0,
buf + offset, size - offset);
offset += len;
- virtqueue_push(vq, &elem, len);
+ virtqueue_push(vq, elem, len);
+ g_free(elem);
}
virtio_notify(VIRTIO_DEVICE(port->vser), vq);
@@ -112,13 +116,18 @@ static size_t write_to_port(VirtIOSerialPort *port,
static void discard_vq_data(VirtQueue *vq, VirtIODevice *vdev)
{
- VirtQueueElement elem;
+ VirtQueueElement *elem;
if (!virtio_queue_ready(vq)) {
return;
}
- while (virtqueue_pop(vq, &elem)) {
- virtqueue_push(vq, &elem, 0);
+ for (;;) {
+ elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
+ if (!elem) {
+ break;
+ }
+ virtqueue_push(vq, elem, 0);
+ g_free(elem);
}
virtio_notify(vdev, vq);
}
@@ -137,21 +146,22 @@ static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
unsigned int i;
/* Pop an elem only if we haven't left off a previous one mid-way */
- if (!port->elem.out_num) {
- if (!virtqueue_pop(vq, &port->elem)) {
+ if (!port->elem) {
+ port->elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
+ if (!port->elem) {
break;
}
port->iov_idx = 0;
port->iov_offset = 0;
}
- for (i = port->iov_idx; i < port->elem.out_num; i++) {
+ for (i = port->iov_idx; i < port->elem->out_num; i++) {
size_t buf_size;
ssize_t ret;
- buf_size = port->elem.out_sg[i].iov_len - port->iov_offset;
+ buf_size = port->elem->out_sg[i].iov_len - port->iov_offset;
ret = vsc->have_data(port,
- port->elem.out_sg[i].iov_base
+ port->elem->out_sg[i].iov_base
+ port->iov_offset,
buf_size);
if (port->throttled) {
@@ -166,8 +176,9 @@ static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
if (port->throttled) {
break;
}
- virtqueue_push(vq, &port->elem, 0);
- port->elem.out_num = 0;
+ virtqueue_push(vq, port->elem, 0);
+ g_free(port->elem);
+ port->elem = NULL;
}
virtio_notify(vdev, vq);
}
@@ -184,22 +195,26 @@ static void flush_queued_data(VirtIOSerialPort *port)
static size_t send_control_msg(VirtIOSerial *vser, void *buf, size_t len)
{
- VirtQueueElement elem;
+ VirtQueueElement *elem;
VirtQueue *vq;
vq = vser->c_ivq;
if (!virtio_queue_ready(vq)) {
return 0;
}
- if (!virtqueue_pop(vq, &elem)) {
+
+ elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
+ if (!elem) {
return 0;
}
/* TODO: detect a buffer that's too short, set NEEDS_RESET */
- iov_from_buf(elem.in_sg, elem.in_num, 0, buf, len);
+ iov_from_buf(elem->in_sg, elem->in_num, 0, buf, len);
- virtqueue_push(vq, &elem, len);
+ virtqueue_push(vq, elem, len);
virtio_notify(VIRTIO_DEVICE(vser), vq);
+ g_free(elem);
+
return len;
}
@@ -413,7 +428,7 @@ static void control_in(VirtIODevice *vdev, VirtQueue *vq)
static void control_out(VirtIODevice *vdev, VirtQueue *vq)
{
- VirtQueueElement elem;
+ VirtQueueElement *elem;
VirtIOSerial *vser;
uint8_t *buf;
size_t len;
@@ -422,10 +437,15 @@ static void control_out(VirtIODevice *vdev, VirtQueue *vq)
len = 0;
buf = NULL;
- while (virtqueue_pop(vq, &elem)) {
+ for (;;) {
size_t cur_len;
- cur_len = iov_size(elem.out_sg, elem.out_num);
+ elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
+ if (!elem) {
+ break;
+ }
+
+ cur_len = iov_size(elem->out_sg, elem->out_num);
/*
* Allocate a new buf only if we didn't have one previously or
* if the size of the buf differs
@@ -436,10 +456,11 @@ static void control_out(VirtIODevice *vdev, VirtQueue *vq)
buf = g_malloc(cur_len);
len = cur_len;
}
- iov_to_buf(elem.out_sg, elem.out_num, 0, buf, cur_len);
+ iov_to_buf(elem->out_sg, elem->out_num, 0, buf, cur_len);
handle_control_message(vser, buf, cur_len);
- virtqueue_push(vq, &elem, 0);
+ virtqueue_push(vq, elem, 0);
+ g_free(elem);
}
g_free(buf);
virtio_notify(vdev, vq);
@@ -619,16 +640,14 @@ static void virtio_serial_save_device(VirtIODevice *vdev, QEMUFile *f)
qemu_put_byte(f, port->host_connected);
elem_popped = 0;
- if (port->elem.out_num) {
+ if (port->elem) {
elem_popped = 1;
}
qemu_put_be32s(f, &elem_popped);
if (elem_popped) {
qemu_put_be32s(f, &port->iov_idx);
qemu_put_be64s(f, &port->iov_offset);
-
- qemu_put_buffer(f, (unsigned char *)&port->elem,
- sizeof(port->elem));
+ qemu_put_virtqueue_element(f, port->elem);
}
}
}
@@ -703,12 +722,8 @@ static int fetch_active_ports_list(QEMUFile *f, int version_id,
qemu_get_be32s(f, &port->iov_idx);
qemu_get_be64s(f, &port->iov_offset);
- qemu_get_buffer(f, (unsigned char *)&port->elem,
- sizeof(port->elem));
- virtqueue_map_sg(port->elem.in_sg, port->elem.in_addr,
- port->elem.in_num, 1);
- virtqueue_map_sg(port->elem.out_sg, port->elem.out_addr,
- port->elem.out_num, 1);
+ port->elem =
+ qemu_get_virtqueue_element(f, sizeof(VirtQueueElement));
/*
* Port was throttled on source machine. Let's
@@ -801,7 +816,7 @@ static const TypeInfo virtser_bus_info = {
static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
{
- VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, qdev);
+ VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(qdev);
monitor_printf(mon, "%*sport %d, guest %s, host %s, throttle %s\n",
indent, "", port->id,
@@ -930,7 +945,7 @@ static void virtser_port_device_realize(DeviceState *dev, Error **errp)
return;
}
- port->elem.out_num = 0;
+ port->elem = NULL;
}
static void virtser_port_device_plug(HotplugHandler *hotplug_dev,
diff --git a/qemu/hw/char/xen_console.c b/qemu/hw/char/xen_console.c
index eb7f450ab..cbf1dccbb 100644
--- a/qemu/hw/char/xen_console.c
+++ b/qemu/hw/char/xen_console.c
@@ -19,14 +19,9 @@
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
+#include "qemu/osdep.h"
#include <sys/select.h>
-#include <fcntl.h>
-#include <unistd.h>
#include <termios.h>
-#include <stdarg.h>
#include <sys/mman.h>
#include "hw/hw.h"
@@ -228,12 +223,12 @@ static int con_initialise(struct XenDevice *xendev)
con->buffer.max_capacity = limit;
if (!xendev->dev) {
- con->sring = xc_map_foreign_range(xen_xc, con->xendev.dom,
- XC_PAGE_SIZE,
+ xen_pfn_t mfn = con->ring_ref;
+ con->sring = xenforeignmemory_map(xen_fmem, con->xendev.dom,
PROT_READ|PROT_WRITE,
- con->ring_ref);
+ 1, &mfn, NULL);
} else {
- con->sring = xc_gnttab_map_grant_ref(xendev->gnttabdev, con->xendev.dom,
+ con->sring = xengnttab_map_grant_ref(xendev->gnttabdev, con->xendev.dom,
con->ring_ref,
PROT_READ|PROT_WRITE);
}
@@ -265,9 +260,6 @@ static void con_disconnect(struct XenDevice *xendev)
{
struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
- if (!xendev->dev) {
- return;
- }
if (con->chr) {
qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL);
qemu_chr_fe_release(con->chr);
@@ -275,12 +267,12 @@ static void con_disconnect(struct XenDevice *xendev)
xen_be_unbind_evtchn(&con->xendev);
if (con->sring) {
- if (!xendev->gnttabdev) {
- munmap(con->sring, XC_PAGE_SIZE);
+ if (!xendev->dev) {
+ xenforeignmemory_unmap(xen_fmem, con->sring, 1);
} else {
- xc_gnttab_munmap(xendev->gnttabdev, con->sring, 1);
+ xengnttab_unmap(xendev->gnttabdev, con->sring, 1);
}
- con->sring = NULL;
+ con->sring = NULL;
}
}
diff --git a/qemu/hw/char/xilinx_uartlite.c b/qemu/hw/char/xilinx_uartlite.c
index ef883a898..911af4a0d 100644
--- a/qemu/hw/char/xilinx_uartlite.c
+++ b/qemu/hw/char/xilinx_uartlite.c
@@ -22,6 +22,7 @@
* THE SOFTWARE.
*/
+#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "sysemu/char.h"