summaryrefslogtreecommitdiffstats
path: root/qemu/hw/char
diff options
context:
space:
mode:
authorRajithaY <rajithax.yerrumsetty@intel.com>2017-04-25 03:31:15 -0700
committerRajitha Yerrumchetty <rajithax.yerrumsetty@intel.com>2017-05-22 06:48:08 +0000
commitbb756eebdac6fd24e8919e2c43f7d2c8c4091f59 (patch)
treeca11e03542edf2d8f631efeca5e1626d211107e3 /qemu/hw/char
parenta14b48d18a9ed03ec191cf16b162206998a895ce (diff)
Adding qemu as a submodule of KVMFORNFV
This Patch includes the changes to add qemu as a submodule to kvmfornfv repo and make use of the updated latest qemu for the execution of all testcase Change-Id: I1280af507a857675c7f81d30c95255635667bdd7 Signed-off-by:RajithaY<rajithax.yerrumsetty@intel.com>
Diffstat (limited to 'qemu/hw/char')
-rw-r--r--qemu/hw/char/Makefile.objs30
-rw-r--r--qemu/hw/char/bcm2835_aux.c316
-rw-r--r--qemu/hw/char/cadence_uart.c540
-rw-r--r--qemu/hw/char/debugcon.c142
-rw-r--r--qemu/hw/char/digic-uart.c198
-rw-r--r--qemu/hw/char/escc.c1056
-rw-r--r--qemu/hw/char/etraxfs_ser.c254
-rw-r--r--qemu/hw/char/exynos4210_uart.c678
-rw-r--r--qemu/hw/char/grlib_apbuart.c299
-rw-r--r--qemu/hw/char/imx_serial.c367
-rw-r--r--qemu/hw/char/ipoctal232.c604
-rw-r--r--qemu/hw/char/lm32_juart.c165
-rw-r--r--qemu/hw/char/lm32_uart.c305
-rw-r--r--qemu/hw/char/mcf_uart.c308
-rw-r--r--qemu/hw/char/milkymist-uart.c256
-rw-r--r--qemu/hw/char/omap_uart.c188
-rw-r--r--qemu/hw/char/parallel.c645
-rw-r--r--qemu/hw/char/pl011.c343
-rw-r--r--qemu/hw/char/sclpconsole-lm.c384
-rw-r--r--qemu/hw/char/sclpconsole.c286
-rw-r--r--qemu/hw/char/serial-isa.c147
-rw-r--r--qemu/hw/char/serial-pci.c276
-rw-r--r--qemu/hw/char/serial.c966
-rw-r--r--qemu/hw/char/sh_serial.c409
-rw-r--r--qemu/hw/char/spapr_vty.c249
-rw-r--r--qemu/hw/char/stm32f2xx_usart.c233
-rw-r--r--qemu/hw/char/virtio-console.c218
-rw-r--r--qemu/hw/char/virtio-serial-bus.c1149
-rw-r--r--qemu/hw/char/xen_console.c297
-rw-r--r--qemu/hw/char/xilinx_uartlite.c249
30 files changed, 0 insertions, 11557 deletions
diff --git a/qemu/hw/char/Makefile.objs b/qemu/hw/char/Makefile.objs
deleted file mode 100644
index 69a553cd8..000000000
--- a/qemu/hw/char/Makefile.objs
+++ /dev/null
@@ -1,30 +0,0 @@
-common-obj-$(CONFIG_IPACK) += ipoctal232.o
-common-obj-$(CONFIG_ESCC) += escc.o
-common-obj-$(CONFIG_PARALLEL) += parallel.o
-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_XILINX) += xilinx_uartlite.o
-common-obj-$(CONFIG_XEN_BACKEND) += xen_console.o
-common-obj-$(CONFIG_CADENCE) += cadence_uart.o
-
-obj-$(CONFIG_EXYNOS4) += exynos4210_uart.o
-obj-$(CONFIG_COLDFIRE) += mcf_uart.o
-obj-$(CONFIG_OMAP) += omap_uart.o
-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
-common-obj-$(CONFIG_GRLIB) += grlib_apbuart.o
-common-obj-$(CONFIG_IMX) += imx_serial.o
-common-obj-$(CONFIG_LM32) += lm32_juart.o
-common-obj-$(CONFIG_LM32) += lm32_uart.o
-common-obj-$(CONFIG_MILKYMIST) += milkymist-uart.o
-common-obj-$(CONFIG_SCLPCONSOLE) += sclpconsole.o sclpconsole-lm.o
-
-obj-$(CONFIG_VIRTIO) += virtio-serial-bus.o
diff --git a/qemu/hw/char/bcm2835_aux.c b/qemu/hw/char/bcm2835_aux.c
deleted file mode 100644
index 0394d11a8..000000000
--- a/qemu/hw/char/bcm2835_aux.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * 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
deleted file mode 100644
index 797787823..000000000
--- a/qemu/hw/char/cadence_uart.c
+++ /dev/null
@@ -1,540 +0,0 @@
-/*
- * Device model for Cadence UART
- *
- * Copyright (c) 2010 Xilinx Inc.
- * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwaite@petalogix.com)
- * Copyright (c) 2012 PetaLogix Pty Ltd.
- * Written by Haibing Ma
- * M.Habib
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * 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 "hw/char/cadence_uart.h"
-
-#ifdef CADENCE_UART_ERR_DEBUG
-#define DB_PRINT(...) do { \
- fprintf(stderr, ": %s: ", __func__); \
- fprintf(stderr, ## __VA_ARGS__); \
- } while (0);
-#else
- #define DB_PRINT(...)
-#endif
-
-#define UART_SR_INTR_RTRIG 0x00000001
-#define UART_SR_INTR_REMPTY 0x00000002
-#define UART_SR_INTR_RFUL 0x00000004
-#define UART_SR_INTR_TEMPTY 0x00000008
-#define UART_SR_INTR_TFUL 0x00000010
-/* somewhat awkwardly, TTRIG is misaligned between SR and ISR */
-#define UART_SR_TTRIG 0x00002000
-#define UART_INTR_TTRIG 0x00000400
-/* bits fields in CSR that correlate to CISR. If any of these bits are set in
- * SR, then the same bit in CISR is set high too */
-#define UART_SR_TO_CISR_MASK 0x0000001F
-
-#define UART_INTR_ROVR 0x00000020
-#define UART_INTR_FRAME 0x00000040
-#define UART_INTR_PARE 0x00000080
-#define UART_INTR_TIMEOUT 0x00000100
-#define UART_INTR_DMSI 0x00000200
-#define UART_INTR_TOVR 0x00001000
-
-#define UART_SR_RACTIVE 0x00000400
-#define UART_SR_TACTIVE 0x00000800
-#define UART_SR_FDELT 0x00001000
-
-#define UART_CR_RXRST 0x00000001
-#define UART_CR_TXRST 0x00000002
-#define UART_CR_RX_EN 0x00000004
-#define UART_CR_RX_DIS 0x00000008
-#define UART_CR_TX_EN 0x00000010
-#define UART_CR_TX_DIS 0x00000020
-#define UART_CR_RST_TO 0x00000040
-#define UART_CR_STARTBRK 0x00000080
-#define UART_CR_STOPBRK 0x00000100
-
-#define UART_MR_CLKS 0x00000001
-#define UART_MR_CHRL 0x00000006
-#define UART_MR_CHRL_SH 1
-#define UART_MR_PAR 0x00000038
-#define UART_MR_PAR_SH 3
-#define UART_MR_NBSTOP 0x000000C0
-#define UART_MR_NBSTOP_SH 6
-#define UART_MR_CHMODE 0x00000300
-#define UART_MR_CHMODE_SH 8
-#define UART_MR_UCLKEN 0x00000400
-#define UART_MR_IRMODE 0x00000800
-
-#define UART_DATA_BITS_6 (0x3 << UART_MR_CHRL_SH)
-#define UART_DATA_BITS_7 (0x2 << UART_MR_CHRL_SH)
-#define UART_PARITY_ODD (0x1 << UART_MR_PAR_SH)
-#define UART_PARITY_EVEN (0x0 << UART_MR_PAR_SH)
-#define UART_STOP_BITS_1 (0x3 << UART_MR_NBSTOP_SH)
-#define UART_STOP_BITS_2 (0x2 << UART_MR_NBSTOP_SH)
-#define NORMAL_MODE (0x0 << UART_MR_CHMODE_SH)
-#define ECHO_MODE (0x1 << UART_MR_CHMODE_SH)
-#define LOCAL_LOOPBACK (0x2 << UART_MR_CHMODE_SH)
-#define REMOTE_LOOPBACK (0x3 << UART_MR_CHMODE_SH)
-
-#define UART_INPUT_CLK 50000000
-
-#define R_CR (0x00/4)
-#define R_MR (0x04/4)
-#define R_IER (0x08/4)
-#define R_IDR (0x0C/4)
-#define R_IMR (0x10/4)
-#define R_CISR (0x14/4)
-#define R_BRGR (0x18/4)
-#define R_RTOR (0x1C/4)
-#define R_RTRIG (0x20/4)
-#define R_MCR (0x24/4)
-#define R_MSR (0x28/4)
-#define R_SR (0x2C/4)
-#define R_TX_RX (0x30/4)
-#define R_BDIV (0x34/4)
-#define R_FDEL (0x38/4)
-#define R_PMIN (0x3C/4)
-#define R_PWID (0x40/4)
-#define R_TTRIG (0x44/4)
-
-
-static void uart_update_status(CadenceUARTState *s)
-{
- s->r[R_SR] = 0;
-
- s->r[R_SR] |= s->rx_count == CADENCE_UART_RX_FIFO_SIZE ? UART_SR_INTR_RFUL
- : 0;
- s->r[R_SR] |= !s->rx_count ? UART_SR_INTR_REMPTY : 0;
- s->r[R_SR] |= s->rx_count >= s->r[R_RTRIG] ? UART_SR_INTR_RTRIG : 0;
-
- s->r[R_SR] |= s->tx_count == CADENCE_UART_TX_FIFO_SIZE ? UART_SR_INTR_TFUL
- : 0;
- s->r[R_SR] |= !s->tx_count ? UART_SR_INTR_TEMPTY : 0;
- s->r[R_SR] |= s->tx_count >= s->r[R_TTRIG] ? UART_SR_TTRIG : 0;
-
- s->r[R_CISR] |= s->r[R_SR] & UART_SR_TO_CISR_MASK;
- s->r[R_CISR] |= s->r[R_SR] & UART_SR_TTRIG ? UART_INTR_TTRIG : 0;
- qemu_set_irq(s->irq, !!(s->r[R_IMR] & s->r[R_CISR]));
-}
-
-static void fifo_trigger_update(void *opaque)
-{
- CadenceUARTState *s = opaque;
-
- s->r[R_CISR] |= UART_INTR_TIMEOUT;
-
- uart_update_status(s);
-}
-
-static void uart_rx_reset(CadenceUARTState *s)
-{
- s->rx_wpos = 0;
- s->rx_count = 0;
- if (s->chr) {
- qemu_chr_accept_input(s->chr);
- }
-}
-
-static void uart_tx_reset(CadenceUARTState *s)
-{
- s->tx_count = 0;
-}
-
-static void uart_send_breaks(CadenceUARTState *s)
-{
- int break_enabled = 1;
-
- if (s->chr) {
- qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
- &break_enabled);
- }
-}
-
-static void uart_parameters_setup(CadenceUARTState *s)
-{
- QEMUSerialSetParams ssp;
- unsigned int baud_rate, packet_size;
-
- baud_rate = (s->r[R_MR] & UART_MR_CLKS) ?
- UART_INPUT_CLK / 8 : UART_INPUT_CLK;
-
- ssp.speed = baud_rate / (s->r[R_BRGR] * (s->r[R_BDIV] + 1));
- packet_size = 1;
-
- switch (s->r[R_MR] & UART_MR_PAR) {
- case UART_PARITY_EVEN:
- ssp.parity = 'E';
- packet_size++;
- break;
- case UART_PARITY_ODD:
- ssp.parity = 'O';
- packet_size++;
- break;
- default:
- ssp.parity = 'N';
- break;
- }
-
- switch (s->r[R_MR] & UART_MR_CHRL) {
- case UART_DATA_BITS_6:
- ssp.data_bits = 6;
- break;
- case UART_DATA_BITS_7:
- ssp.data_bits = 7;
- break;
- default:
- ssp.data_bits = 8;
- break;
- }
-
- switch (s->r[R_MR] & UART_MR_NBSTOP) {
- case UART_STOP_BITS_1:
- ssp.stop_bits = 1;
- break;
- default:
- ssp.stop_bits = 2;
- break;
- }
-
- packet_size += ssp.data_bits + ssp.stop_bits;
- 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);
- }
-}
-
-static int uart_can_receive(void *opaque)
-{
- CadenceUARTState *s = opaque;
- int ret = MAX(CADENCE_UART_RX_FIFO_SIZE, CADENCE_UART_TX_FIFO_SIZE);
- uint32_t ch_mode = s->r[R_MR] & UART_MR_CHMODE;
-
- if (ch_mode == NORMAL_MODE || ch_mode == ECHO_MODE) {
- ret = MIN(ret, CADENCE_UART_RX_FIFO_SIZE - s->rx_count);
- }
- if (ch_mode == REMOTE_LOOPBACK || ch_mode == ECHO_MODE) {
- ret = MIN(ret, CADENCE_UART_TX_FIFO_SIZE - s->tx_count);
- }
- return ret;
-}
-
-static void uart_ctrl_update(CadenceUARTState *s)
-{
- if (s->r[R_CR] & UART_CR_TXRST) {
- uart_tx_reset(s);
- }
-
- if (s->r[R_CR] & UART_CR_RXRST) {
- uart_rx_reset(s);
- }
-
- s->r[R_CR] &= ~(UART_CR_TXRST | UART_CR_RXRST);
-
- if (s->r[R_CR] & UART_CR_STARTBRK && !(s->r[R_CR] & UART_CR_STOPBRK)) {
- uart_send_breaks(s);
- }
-}
-
-static void uart_write_rx_fifo(void *opaque, const uint8_t *buf, int size)
-{
- CadenceUARTState *s = opaque;
- uint64_t new_rx_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- int i;
-
- if ((s->r[R_CR] & UART_CR_RX_DIS) || !(s->r[R_CR] & UART_CR_RX_EN)) {
- return;
- }
-
- if (s->rx_count == CADENCE_UART_RX_FIFO_SIZE) {
- s->r[R_CISR] |= UART_INTR_ROVR;
- } else {
- for (i = 0; i < size; i++) {
- s->rx_fifo[s->rx_wpos] = buf[i];
- s->rx_wpos = (s->rx_wpos + 1) % CADENCE_UART_RX_FIFO_SIZE;
- s->rx_count++;
- }
- timer_mod(s->fifo_trigger_handle, new_rx_time +
- (s->char_tx_time * 4));
- }
- uart_update_status(s);
-}
-
-static gboolean cadence_uart_xmit(GIOChannel *chan, GIOCondition cond,
- void *opaque)
-{
- CadenceUARTState *s = opaque;
- int ret;
-
- /* instant drain the fifo when there's no back-end */
- if (!s->chr) {
- s->tx_count = 0;
- return FALSE;
- }
-
- if (!s->tx_count) {
- return FALSE;
- }
-
- 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 (s->tx_count) {
- int r = qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP,
- cadence_uart_xmit, s);
- assert(r);
- }
-
- uart_update_status(s);
- return FALSE;
-}
-
-static void uart_write_tx_fifo(CadenceUARTState *s, const uint8_t *buf,
- int size)
-{
- if ((s->r[R_CR] & UART_CR_TX_DIS) || !(s->r[R_CR] & UART_CR_TX_EN)) {
- return;
- }
-
- if (size > CADENCE_UART_TX_FIFO_SIZE - s->tx_count) {
- size = CADENCE_UART_TX_FIFO_SIZE - s->tx_count;
- /*
- * This can only be a guest error via a bad tx fifo register push,
- * as can_receive() should stop remote loop and echo modes ever getting
- * us to here.
- */
- qemu_log_mask(LOG_GUEST_ERROR, "cadence_uart: TxFIFO overflow");
- s->r[R_CISR] |= UART_INTR_ROVR;
- }
-
- memcpy(s->tx_fifo + s->tx_count, buf, size);
- s->tx_count += size;
-
- cadence_uart_xmit(NULL, G_IO_OUT, s);
-}
-
-static void uart_receive(void *opaque, const uint8_t *buf, int size)
-{
- CadenceUARTState *s = opaque;
- uint32_t ch_mode = s->r[R_MR] & UART_MR_CHMODE;
-
- if (ch_mode == NORMAL_MODE || ch_mode == ECHO_MODE) {
- uart_write_rx_fifo(opaque, buf, size);
- }
- if (ch_mode == REMOTE_LOOPBACK || ch_mode == ECHO_MODE) {
- uart_write_tx_fifo(s, buf, size);
- }
-}
-
-static void uart_event(void *opaque, int event)
-{
- CadenceUARTState *s = opaque;
- uint8_t buf = '\0';
-
- if (event == CHR_EVENT_BREAK) {
- uart_write_rx_fifo(opaque, &buf, 1);
- }
-
- uart_update_status(s);
-}
-
-static void uart_read_rx_fifo(CadenceUARTState *s, uint32_t *c)
-{
- if ((s->r[R_CR] & UART_CR_RX_DIS) || !(s->r[R_CR] & UART_CR_RX_EN)) {
- return;
- }
-
- if (s->rx_count) {
- uint32_t rx_rpos = (CADENCE_UART_RX_FIFO_SIZE + s->rx_wpos -
- s->rx_count) % CADENCE_UART_RX_FIFO_SIZE;
- *c = s->rx_fifo[rx_rpos];
- s->rx_count--;
-
- if (s->chr) {
- qemu_chr_accept_input(s->chr);
- }
- } else {
- *c = 0;
- }
-
- uart_update_status(s);
-}
-
-static void uart_write(void *opaque, hwaddr offset,
- uint64_t value, unsigned size)
-{
- CadenceUARTState *s = opaque;
-
- 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;
- break;
- case R_IDR: /* idr (wtc imr) */
- s->r[R_IMR] &= ~value;
- break;
- case R_IMR: /* imr (read only) */
- break;
- case R_CISR: /* cisr (wtc) */
- s->r[R_CISR] &= ~value;
- break;
- case R_TX_RX: /* UARTDR */
- switch (s->r[R_MR] & UART_MR_CHMODE) {
- case NORMAL_MODE:
- uart_write_tx_fifo(s, (uint8_t *) &value, 1);
- break;
- case LOCAL_LOOPBACK:
- uart_write_rx_fifo(opaque, (uint8_t *) &value, 1);
- break;
- }
- break;
- default:
- s->r[offset] = value;
- }
-
- switch (offset) {
- case R_CR:
- uart_ctrl_update(s);
- break;
- case R_MR:
- uart_parameters_setup(s);
- break;
- }
- uart_update_status(s);
-}
-
-static uint64_t uart_read(void *opaque, hwaddr offset,
- unsigned size)
-{
- CadenceUARTState *s = opaque;
- uint32_t c = 0;
-
- offset >>= 2;
- if (offset >= CADENCE_UART_R_MAX) {
- c = 0;
- } else if (offset == R_TX_RX) {
- uart_read_rx_fifo(s, &c);
- } else {
- c = s->r[offset];
- }
-
- DB_PRINT(" offset:%x data:%08x\n", (unsigned)(offset << 2), (unsigned)c);
- return c;
-}
-
-static const MemoryRegionOps uart_ops = {
- .read = uart_read,
- .write = uart_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void cadence_uart_reset(DeviceState *dev)
-{
- CadenceUARTState *s = CADENCE_UART(dev);
-
- s->r[R_CR] = 0x00000128;
- s->r[R_IMR] = 0;
- s->r[R_CISR] = 0;
- s->r[R_RTRIG] = 0x00000020;
- s->r[R_BRGR] = 0x0000000F;
- s->r[R_TTRIG] = 0x00000020;
-
- uart_rx_reset(s);
- uart_tx_reset(s);
-
- uart_update_status(s);
-}
-
-static void cadence_uart_realize(DeviceState *dev, Error **errp)
-{
- CadenceUARTState *s = CADENCE_UART(dev);
-
- 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);
- }
-}
-
-static void cadence_uart_init(Object *obj)
-{
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
- CadenceUARTState *s = CADENCE_UART(obj);
-
- memory_region_init_io(&s->iomem, obj, &uart_ops, s, "uart", 0x1000);
- sysbus_init_mmio(sbd, &s->iomem);
- sysbus_init_irq(sbd, &s->irq);
-
- s->char_tx_time = (NANOSECONDS_PER_SECOND / 9600) * 10;
-}
-
-static int cadence_uart_post_load(void *opaque, int version_id)
-{
- CadenceUARTState *s = opaque;
-
- uart_parameters_setup(s);
- uart_update_status(s);
- return 0;
-}
-
-static const VMStateDescription vmstate_cadence_uart = {
- .name = "cadence_uart",
- .version_id = 2,
- .minimum_version_id = 2,
- .post_load = cadence_uart_post_load,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32_ARRAY(r, CadenceUARTState, CADENCE_UART_R_MAX),
- VMSTATE_UINT8_ARRAY(rx_fifo, CadenceUARTState,
- CADENCE_UART_RX_FIFO_SIZE),
- VMSTATE_UINT8_ARRAY(tx_fifo, CadenceUARTState,
- CADENCE_UART_TX_FIFO_SIZE),
- VMSTATE_UINT32(rx_count, CadenceUARTState),
- VMSTATE_UINT32(tx_count, CadenceUARTState),
- VMSTATE_UINT32(rx_wpos, CadenceUARTState),
- VMSTATE_TIMER_PTR(fifo_trigger_handle, CadenceUARTState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void cadence_uart_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- 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;
-}
-
-static const TypeInfo cadence_uart_info = {
- .name = TYPE_CADENCE_UART,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(CadenceUARTState),
- .instance_init = cadence_uart_init,
- .class_init = cadence_uart_class_init,
-};
-
-static void cadence_uart_register_types(void)
-{
- type_register_static(&cadence_uart_info);
-}
-
-type_init(cadence_uart_register_types)
diff --git a/qemu/hw/char/debugcon.c b/qemu/hw/char/debugcon.c
deleted file mode 100644
index e7f025ec6..000000000
--- a/qemu/hw/char/debugcon.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * QEMU Bochs-style debug console ("port E9") emulation
- *
- * Copyright (c) 2003-2004 Fabrice Bellard
- * Copyright (c) 2008 Citrix Systems, Inc.
- * Copyright (c) Intel Corporation; author: H. Peter Anvin
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * 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"
-#include "hw/i386/pc.h"
-
-#define TYPE_ISA_DEBUGCON_DEVICE "isa-debugcon"
-#define ISA_DEBUGCON_DEVICE(obj) \
- OBJECT_CHECK(ISADebugconState, (obj), TYPE_ISA_DEBUGCON_DEVICE)
-
-//#define DEBUG_DEBUGCON
-
-typedef struct DebugconState {
- MemoryRegion io;
- CharDriverState *chr;
- uint32_t readback;
-} DebugconState;
-
-typedef struct ISADebugconState {
- ISADevice parent_obj;
-
- uint32_t iobase;
- DebugconState state;
-} ISADebugconState;
-
-static void debugcon_ioport_write(void *opaque, hwaddr addr, uint64_t val,
- unsigned width)
-{
- DebugconState *s = opaque;
- unsigned char ch = val;
-
-#ifdef DEBUG_DEBUGCON
- printf(" [debugcon: write addr=0x%04" HWADDR_PRIx " val=0x%02" PRIx64 "]\n", addr, val);
-#endif
-
- qemu_chr_fe_write(s->chr, &ch, 1);
-}
-
-
-static uint64_t debugcon_ioport_read(void *opaque, hwaddr addr, unsigned width)
-{
- DebugconState *s = opaque;
-
-#ifdef DEBUG_DEBUGCON
- printf("debugcon: read addr=0x%04" HWADDR_PRIx "\n", addr);
-#endif
-
- return s->readback;
-}
-
-static const MemoryRegionOps debugcon_ops = {
- .read = debugcon_ioport_read,
- .write = debugcon_ioport_write,
- .valid.min_access_size = 1,
- .valid.max_access_size = 1,
- .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static void debugcon_realize_core(DebugconState *s, Error **errp)
-{
- if (!s->chr) {
- error_setg(errp, "Can't create debugcon device, empty char device");
- return;
- }
-
- qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, s);
-}
-
-static void debugcon_isa_realizefn(DeviceState *dev, Error **errp)
-{
- ISADevice *d = ISA_DEVICE(dev);
- ISADebugconState *isa = ISA_DEBUGCON_DEVICE(dev);
- DebugconState *s = &isa->state;
- Error *err = NULL;
-
- debugcon_realize_core(s, &err);
- if (err != NULL) {
- error_propagate(errp, err);
- return;
- }
- memory_region_init_io(&s->io, OBJECT(dev), &debugcon_ops, s,
- TYPE_ISA_DEBUGCON_DEVICE, 1);
- memory_region_add_subregion(isa_address_space_io(d),
- isa->iobase, &s->io);
-}
-
-static Property debugcon_isa_properties[] = {
- DEFINE_PROP_UINT32("iobase", ISADebugconState, iobase, 0xe9),
- DEFINE_PROP_CHR("chardev", ISADebugconState, state.chr),
- DEFINE_PROP_UINT32("readback", ISADebugconState, state.readback, 0xe9),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void debugcon_isa_class_initfn(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->realize = debugcon_isa_realizefn;
- dc->props = debugcon_isa_properties;
- set_bit(DEVICE_CATEGORY_MISC, dc->categories);
-}
-
-static const TypeInfo debugcon_isa_info = {
- .name = TYPE_ISA_DEBUGCON_DEVICE,
- .parent = TYPE_ISA_DEVICE,
- .instance_size = sizeof(ISADebugconState),
- .class_init = debugcon_isa_class_initfn,
-};
-
-static void debugcon_register_types(void)
-{
- type_register_static(&debugcon_isa_info);
-}
-
-type_init(debugcon_register_types)
diff --git a/qemu/hw/char/digic-uart.c b/qemu/hw/char/digic-uart.c
deleted file mode 100644
index d3bc533d7..000000000
--- a/qemu/hw/char/digic-uart.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * QEMU model of the Canon DIGIC UART block.
- *
- * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.com>
- *
- * This model is based on reverse engineering efforts
- * made by CHDK (http://chdk.wikia.com) and
- * Magic Lantern (http://www.magiclantern.fm) projects
- * contributors.
- *
- * See "Serial terminal" docs here:
- * http://magiclantern.wikia.com/wiki/Register_Map#Misc_Registers
- *
- * The QEMU model of the Milkymist UART block by Michael Walle
- * is used as a template.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include "qemu/osdep.h"
-#include "hw/hw.h"
-#include "hw/sysbus.h"
-#include "sysemu/char.h"
-
-#include "hw/char/digic-uart.h"
-
-enum {
- ST_RX_RDY = (1 << 0),
- ST_TX_RDY = (1 << 1),
-};
-
-static uint64_t digic_uart_read(void *opaque, hwaddr addr,
- unsigned size)
-{
- DigicUartState *s = opaque;
- uint64_t ret = 0;
-
- addr >>= 2;
-
- switch (addr) {
- case R_RX:
- s->reg_st &= ~(ST_RX_RDY);
- ret = s->reg_rx;
- break;
-
- case R_ST:
- ret = s->reg_st;
- break;
-
- default:
- qemu_log_mask(LOG_UNIMP,
- "digic-uart: read access to unknown register 0x"
- TARGET_FMT_plx, addr << 2);
- }
-
- return ret;
-}
-
-static void digic_uart_write(void *opaque, hwaddr addr, uint64_t value,
- unsigned size)
-{
- DigicUartState *s = opaque;
- unsigned char ch = value;
-
- addr >>= 2;
-
- switch (addr) {
- case R_TX:
- if (s->chr) {
- qemu_chr_fe_write_all(s->chr, &ch, 1);
- }
- break;
-
- case R_ST:
- /*
- * Ignore write to R_ST.
- *
- * The point is that this register is actively used
- * during receiving and transmitting symbols,
- * but we don't know the function of most of bits.
- *
- * Ignoring writes to R_ST is only a simplification
- * of the model. It has no perceptible side effects
- * for existing guests.
- */
- break;
-
- default:
- qemu_log_mask(LOG_UNIMP,
- "digic-uart: write access to unknown register 0x"
- TARGET_FMT_plx, addr << 2);
- }
-}
-
-static const MemoryRegionOps uart_mmio_ops = {
- .read = digic_uart_read,
- .write = digic_uart_write,
- .valid = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int uart_can_rx(void *opaque)
-{
- DigicUartState *s = opaque;
-
- return !(s->reg_st & ST_RX_RDY);
-}
-
-static void uart_rx(void *opaque, const uint8_t *buf, int size)
-{
- DigicUartState *s = opaque;
-
- assert(uart_can_rx(opaque));
-
- s->reg_st |= ST_RX_RDY;
- s->reg_rx = *buf;
-}
-
-static void uart_event(void *opaque, int event)
-{
-}
-
-static void digic_uart_reset(DeviceState *d)
-{
- DigicUartState *s = DIGIC_UART(d);
-
- s->reg_rx = 0;
- s->reg_st = ST_TX_RDY;
-}
-
-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);
- }
-}
-
-static void digic_uart_init(Object *obj)
-{
- DigicUartState *s = DIGIC_UART(obj);
-
- memory_region_init_io(&s->regs_region, OBJECT(s), &uart_mmio_ops, s,
- TYPE_DIGIC_UART, 0x18);
- sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->regs_region);
-}
-
-static const VMStateDescription vmstate_digic_uart = {
- .name = "digic-uart",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(reg_rx, DigicUartState),
- VMSTATE_UINT32(reg_st, DigicUartState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void digic_uart_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- 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;
-}
-
-static const TypeInfo digic_uart_info = {
- .name = TYPE_DIGIC_UART,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(DigicUartState),
- .instance_init = digic_uart_init,
- .class_init = digic_uart_class_init,
-};
-
-static void digic_uart_register_types(void)
-{
- type_register_static(&digic_uart_info);
-}
-
-type_init(digic_uart_register_types)
diff --git a/qemu/hw/char/escc.c b/qemu/hw/char/escc.c
deleted file mode 100644
index 7bf09a007..000000000
--- a/qemu/hw/char/escc.c
+++ /dev/null
@@ -1,1056 +0,0 @@
-/*
- * QEMU ESCC (Z8030/Z8530/Z85C30/SCC/ESCC) serial port emulation
- *
- * Copyright (c) 2003-2005 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * 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/sysbus.h"
-#include "hw/char/escc.h"
-#include "sysemu/char.h"
-#include "ui/console.h"
-#include "ui/input.h"
-#include "trace.h"
-
-/*
- * Chipset docs:
- * "Z80C30/Z85C30/Z80230/Z85230/Z85233 SCC/ESCC User Manual",
- * http://www.zilog.com/docs/serial/scc_escc_um.pdf
- *
- * On Sparc32 this is the serial port, mouse and keyboard part of chip STP2001
- * (Slave I/O), also produced as NCR89C105. See
- * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
- *
- * The serial ports implement full AMD AM8530 or Zilog Z8530 chips,
- * mouse and keyboard ports don't implement all functions and they are
- * only asynchronous. There is no DMA.
- *
- * Z85C30 is also used on PowerMacs. There are some small differences
- * between Sparc version (sunzilog) and PowerMac (pmac):
- * Offset between control and data registers
- * There is some kind of lockup bug, but we can ignore it
- * CTS is inverted
- * DMA on pmac using DBDMA chip
- * pmac can do IRDA and faster rates, sunzilog can only do 38400
- * pmac baud rate generator clock is 3.6864 MHz, sunzilog 4.9152 MHz
- */
-
-/*
- * Modifications:
- * 2006-Aug-10 Igor Kovalenko : Renamed KBDQueue to SERIOQueue, implemented
- * serial mouse queue.
- * Implemented serial mouse protocol.
- *
- * 2010-May-23 Artyom Tarasenko: Reworked IUS logic
- */
-
-typedef enum {
- chn_a, chn_b,
-} ChnID;
-
-#define CHN_C(s) ((s)->chn == chn_b? 'b' : 'a')
-
-typedef enum {
- ser, kbd, mouse,
-} ChnType;
-
-#define SERIO_QUEUE_SIZE 256
-
-typedef struct {
- uint8_t data[SERIO_QUEUE_SIZE];
- int rptr, wptr, count;
-} SERIOQueue;
-
-#define SERIAL_REGS 16
-typedef struct ChannelState {
- qemu_irq irq;
- uint32_t rxint, txint, rxint_under_svc, txint_under_svc;
- struct ChannelState *otherchn;
- uint32_t reg;
- uint8_t wregs[SERIAL_REGS], rregs[SERIAL_REGS];
- SERIOQueue queue;
- CharDriverState *chr;
- int e0_mode, led_mode, caps_lock_mode, num_lock_mode;
- int disabled;
- int clock;
- uint32_t vmstate_dummy;
- ChnID chn; // this channel, A (base+4) or B (base+0)
- ChnType type;
- uint8_t rx, tx;
- QemuInputHandlerState *hs;
-} ChannelState;
-
-#define ESCC(obj) OBJECT_CHECK(ESCCState, (obj), TYPE_ESCC)
-
-typedef struct ESCCState {
- SysBusDevice parent_obj;
-
- struct ChannelState chn[2];
- uint32_t it_shift;
- MemoryRegion mmio;
- uint32_t disabled;
- uint32_t frequency;
-} ESCCState;
-
-#define SERIAL_CTRL 0
-#define SERIAL_DATA 1
-
-#define W_CMD 0
-#define CMD_PTR_MASK 0x07
-#define CMD_CMD_MASK 0x38
-#define CMD_HI 0x08
-#define CMD_CLR_TXINT 0x28
-#define CMD_CLR_IUS 0x38
-#define W_INTR 1
-#define INTR_INTALL 0x01
-#define INTR_TXINT 0x02
-#define INTR_RXMODEMSK 0x18
-#define INTR_RXINT1ST 0x08
-#define INTR_RXINTALL 0x10
-#define W_IVEC 2
-#define W_RXCTRL 3
-#define RXCTRL_RXEN 0x01
-#define W_TXCTRL1 4
-#define TXCTRL1_PAREN 0x01
-#define TXCTRL1_PAREV 0x02
-#define TXCTRL1_1STOP 0x04
-#define TXCTRL1_1HSTOP 0x08
-#define TXCTRL1_2STOP 0x0c
-#define TXCTRL1_STPMSK 0x0c
-#define TXCTRL1_CLK1X 0x00
-#define TXCTRL1_CLK16X 0x40
-#define TXCTRL1_CLK32X 0x80
-#define TXCTRL1_CLK64X 0xc0
-#define TXCTRL1_CLKMSK 0xc0
-#define W_TXCTRL2 5
-#define TXCTRL2_TXEN 0x08
-#define TXCTRL2_BITMSK 0x60
-#define TXCTRL2_5BITS 0x00
-#define TXCTRL2_7BITS 0x20
-#define TXCTRL2_6BITS 0x40
-#define TXCTRL2_8BITS 0x60
-#define W_SYNC1 6
-#define W_SYNC2 7
-#define W_TXBUF 8
-#define W_MINTR 9
-#define MINTR_STATUSHI 0x10
-#define MINTR_RST_MASK 0xc0
-#define MINTR_RST_B 0x40
-#define MINTR_RST_A 0x80
-#define MINTR_RST_ALL 0xc0
-#define W_MISC1 10
-#define W_CLOCK 11
-#define CLOCK_TRXC 0x08
-#define W_BRGLO 12
-#define W_BRGHI 13
-#define W_MISC2 14
-#define MISC2_PLLDIS 0x30
-#define W_EXTINT 15
-#define EXTINT_DCD 0x08
-#define EXTINT_SYNCINT 0x10
-#define EXTINT_CTSINT 0x20
-#define EXTINT_TXUNDRN 0x40
-#define EXTINT_BRKINT 0x80
-
-#define R_STATUS 0
-#define STATUS_RXAV 0x01
-#define STATUS_ZERO 0x02
-#define STATUS_TXEMPTY 0x04
-#define STATUS_DCD 0x08
-#define STATUS_SYNC 0x10
-#define STATUS_CTS 0x20
-#define STATUS_TXUNDRN 0x40
-#define STATUS_BRK 0x80
-#define R_SPEC 1
-#define SPEC_ALLSENT 0x01
-#define SPEC_BITS8 0x06
-#define R_IVEC 2
-#define IVEC_TXINTB 0x00
-#define IVEC_LONOINT 0x06
-#define IVEC_LORXINTA 0x0c
-#define IVEC_LORXINTB 0x04
-#define IVEC_LOTXINTA 0x08
-#define IVEC_HINOINT 0x60
-#define IVEC_HIRXINTA 0x30
-#define IVEC_HIRXINTB 0x20
-#define IVEC_HITXINTA 0x10
-#define R_INTR 3
-#define INTR_EXTINTB 0x01
-#define INTR_TXINTB 0x02
-#define INTR_RXINTB 0x04
-#define INTR_EXTINTA 0x08
-#define INTR_TXINTA 0x10
-#define INTR_RXINTA 0x20
-#define R_IPEN 4
-#define R_TXCTRL1 5
-#define R_TXCTRL2 6
-#define R_BC 7
-#define R_RXBUF 8
-#define R_RXCTRL 9
-#define R_MISC 10
-#define R_MISC1 11
-#define R_BRGLO 12
-#define R_BRGHI 13
-#define R_MISC1I 14
-#define R_EXTINT 15
-
-static void handle_kbd_command(ChannelState *s, int val);
-static int serial_can_receive(void *opaque);
-static void serial_receive_byte(ChannelState *s, int ch);
-
-static void clear_queue(void *opaque)
-{
- ChannelState *s = opaque;
- SERIOQueue *q = &s->queue;
- q->rptr = q->wptr = q->count = 0;
-}
-
-static void put_queue(void *opaque, int b)
-{
- ChannelState *s = opaque;
- SERIOQueue *q = &s->queue;
-
- trace_escc_put_queue(CHN_C(s), b);
- if (q->count >= SERIO_QUEUE_SIZE)
- return;
- q->data[q->wptr] = b;
- if (++q->wptr == SERIO_QUEUE_SIZE)
- q->wptr = 0;
- q->count++;
- serial_receive_byte(s, 0);
-}
-
-static uint32_t get_queue(void *opaque)
-{
- ChannelState *s = opaque;
- SERIOQueue *q = &s->queue;
- int val;
-
- if (q->count == 0) {
- return 0;
- } else {
- val = q->data[q->rptr];
- if (++q->rptr == SERIO_QUEUE_SIZE)
- q->rptr = 0;
- q->count--;
- }
- trace_escc_get_queue(CHN_C(s), val);
- if (q->count > 0)
- serial_receive_byte(s, 0);
- return val;
-}
-
-static int escc_update_irq_chn(ChannelState *s)
-{
- if ((((s->wregs[W_INTR] & INTR_TXINT) && (s->txint == 1)) ||
- // tx ints enabled, pending
- ((((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINT1ST) ||
- ((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINTALL)) &&
- s->rxint == 1) || // rx ints enabled, pending
- ((s->wregs[W_EXTINT] & EXTINT_BRKINT) &&
- (s->rregs[R_STATUS] & STATUS_BRK)))) { // break int e&p
- return 1;
- }
- return 0;
-}
-
-static void escc_update_irq(ChannelState *s)
-{
- int irq;
-
- irq = escc_update_irq_chn(s);
- irq |= escc_update_irq_chn(s->otherchn);
-
- trace_escc_update_irq(irq);
- qemu_set_irq(s->irq, irq);
-}
-
-static void escc_reset_chn(ChannelState *s)
-{
- int i;
-
- s->reg = 0;
- for (i = 0; i < SERIAL_REGS; i++) {
- s->rregs[i] = 0;
- s->wregs[i] = 0;
- }
- s->wregs[W_TXCTRL1] = TXCTRL1_1STOP; // 1X divisor, 1 stop bit, no parity
- s->wregs[W_MINTR] = MINTR_RST_ALL;
- s->wregs[W_CLOCK] = CLOCK_TRXC; // Synch mode tx clock = TRxC
- s->wregs[W_MISC2] = MISC2_PLLDIS; // PLL disabled
- s->wregs[W_EXTINT] = EXTINT_DCD | EXTINT_SYNCINT | EXTINT_CTSINT |
- EXTINT_TXUNDRN | EXTINT_BRKINT; // Enable most interrupts
- if (s->disabled)
- s->rregs[R_STATUS] = STATUS_TXEMPTY | STATUS_DCD | STATUS_SYNC |
- STATUS_CTS | STATUS_TXUNDRN;
- else
- s->rregs[R_STATUS] = STATUS_TXEMPTY | STATUS_TXUNDRN;
- s->rregs[R_SPEC] = SPEC_BITS8 | SPEC_ALLSENT;
-
- s->rx = s->tx = 0;
- s->rxint = s->txint = 0;
- s->rxint_under_svc = s->txint_under_svc = 0;
- s->e0_mode = s->led_mode = s->caps_lock_mode = s->num_lock_mode = 0;
- clear_queue(s);
-}
-
-static void escc_reset(DeviceState *d)
-{
- ESCCState *s = ESCC(d);
-
- escc_reset_chn(&s->chn[0]);
- escc_reset_chn(&s->chn[1]);
-}
-
-static inline void set_rxint(ChannelState *s)
-{
- s->rxint = 1;
- /* XXX: missing daisy chainnig: chn_b rx should have a lower priority
- than chn_a rx/tx/special_condition service*/
- s->rxint_under_svc = 1;
- if (s->chn == chn_a) {
- s->rregs[R_INTR] |= INTR_RXINTA;
- if (s->wregs[W_MINTR] & MINTR_STATUSHI)
- s->otherchn->rregs[R_IVEC] = IVEC_HIRXINTA;
- else
- s->otherchn->rregs[R_IVEC] = IVEC_LORXINTA;
- } else {
- s->otherchn->rregs[R_INTR] |= INTR_RXINTB;
- if (s->wregs[W_MINTR] & MINTR_STATUSHI)
- s->rregs[R_IVEC] = IVEC_HIRXINTB;
- else
- s->rregs[R_IVEC] = IVEC_LORXINTB;
- }
- escc_update_irq(s);
-}
-
-static inline void set_txint(ChannelState *s)
-{
- s->txint = 1;
- if (!s->rxint_under_svc) {
- s->txint_under_svc = 1;
- if (s->chn == chn_a) {
- if (s->wregs[W_INTR] & INTR_TXINT) {
- s->rregs[R_INTR] |= INTR_TXINTA;
- }
- if (s->wregs[W_MINTR] & MINTR_STATUSHI)
- s->otherchn->rregs[R_IVEC] = IVEC_HITXINTA;
- else
- s->otherchn->rregs[R_IVEC] = IVEC_LOTXINTA;
- } else {
- s->rregs[R_IVEC] = IVEC_TXINTB;
- if (s->wregs[W_INTR] & INTR_TXINT) {
- s->otherchn->rregs[R_INTR] |= INTR_TXINTB;
- }
- }
- escc_update_irq(s);
- }
-}
-
-static inline void clr_rxint(ChannelState *s)
-{
- s->rxint = 0;
- s->rxint_under_svc = 0;
- if (s->chn == chn_a) {
- if (s->wregs[W_MINTR] & MINTR_STATUSHI)
- s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;
- else
- s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
- s->rregs[R_INTR] &= ~INTR_RXINTA;
- } else {
- if (s->wregs[W_MINTR] & MINTR_STATUSHI)
- s->rregs[R_IVEC] = IVEC_HINOINT;
- else
- s->rregs[R_IVEC] = IVEC_LONOINT;
- s->otherchn->rregs[R_INTR] &= ~INTR_RXINTB;
- }
- if (s->txint)
- set_txint(s);
- escc_update_irq(s);
-}
-
-static inline void clr_txint(ChannelState *s)
-{
- s->txint = 0;
- s->txint_under_svc = 0;
- if (s->chn == chn_a) {
- if (s->wregs[W_MINTR] & MINTR_STATUSHI)
- s->otherchn->rregs[R_IVEC] = IVEC_HINOINT;
- else
- s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
- s->rregs[R_INTR] &= ~INTR_TXINTA;
- } else {
- s->otherchn->rregs[R_INTR] &= ~INTR_TXINTB;
- if (s->wregs[W_MINTR] & MINTR_STATUSHI)
- s->rregs[R_IVEC] = IVEC_HINOINT;
- else
- s->rregs[R_IVEC] = IVEC_LONOINT;
- s->otherchn->rregs[R_INTR] &= ~INTR_TXINTB;
- }
- if (s->rxint)
- set_rxint(s);
- escc_update_irq(s);
-}
-
-static void escc_update_parameters(ChannelState *s)
-{
- int speed, parity, data_bits, stop_bits;
- QEMUSerialSetParams ssp;
-
- if (!s->chr || s->type != ser)
- return;
-
- if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREN) {
- if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREV)
- parity = 'E';
- else
- parity = 'O';
- } else {
- parity = 'N';
- }
- if ((s->wregs[W_TXCTRL1] & TXCTRL1_STPMSK) == TXCTRL1_2STOP)
- stop_bits = 2;
- else
- stop_bits = 1;
- switch (s->wregs[W_TXCTRL2] & TXCTRL2_BITMSK) {
- case TXCTRL2_5BITS:
- data_bits = 5;
- break;
- case TXCTRL2_7BITS:
- data_bits = 7;
- break;
- case TXCTRL2_6BITS:
- data_bits = 6;
- break;
- default:
- case TXCTRL2_8BITS:
- data_bits = 8;
- break;
- }
- speed = s->clock / ((s->wregs[W_BRGLO] | (s->wregs[W_BRGHI] << 8)) + 2);
- switch (s->wregs[W_TXCTRL1] & TXCTRL1_CLKMSK) {
- case TXCTRL1_CLK1X:
- break;
- case TXCTRL1_CLK16X:
- speed /= 16;
- break;
- case TXCTRL1_CLK32X:
- speed /= 32;
- break;
- default:
- case TXCTRL1_CLK64X:
- speed /= 64;
- break;
- }
- ssp.speed = speed;
- ssp.parity = parity;
- ssp.data_bits = data_bits;
- ssp.stop_bits = stop_bits;
- trace_escc_update_parameters(CHN_C(s), speed, parity, data_bits, stop_bits);
- qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
-}
-
-static void escc_mem_write(void *opaque, hwaddr addr,
- uint64_t val, unsigned size)
-{
- ESCCState *serial = opaque;
- ChannelState *s;
- uint32_t saddr;
- int newreg, channel;
-
- val &= 0xff;
- saddr = (addr >> serial->it_shift) & 1;
- channel = (addr >> (serial->it_shift + 1)) & 1;
- s = &serial->chn[channel];
- switch (saddr) {
- case SERIAL_CTRL:
- trace_escc_mem_writeb_ctrl(CHN_C(s), s->reg, val & 0xff);
- newreg = 0;
- switch (s->reg) {
- case W_CMD:
- newreg = val & CMD_PTR_MASK;
- val &= CMD_CMD_MASK;
- switch (val) {
- case CMD_HI:
- newreg |= CMD_HI;
- break;
- case CMD_CLR_TXINT:
- clr_txint(s);
- break;
- case CMD_CLR_IUS:
- if (s->rxint_under_svc) {
- s->rxint_under_svc = 0;
- if (s->txint) {
- set_txint(s);
- }
- } else if (s->txint_under_svc) {
- s->txint_under_svc = 0;
- }
- escc_update_irq(s);
- break;
- default:
- break;
- }
- break;
- case W_INTR ... W_RXCTRL:
- case W_SYNC1 ... W_TXBUF:
- case W_MISC1 ... W_CLOCK:
- case W_MISC2 ... W_EXTINT:
- s->wregs[s->reg] = val;
- break;
- case W_TXCTRL1:
- case W_TXCTRL2:
- s->wregs[s->reg] = val;
- escc_update_parameters(s);
- break;
- case W_BRGLO:
- case W_BRGHI:
- s->wregs[s->reg] = val;
- s->rregs[s->reg] = val;
- escc_update_parameters(s);
- break;
- case W_MINTR:
- switch (val & MINTR_RST_MASK) {
- case 0:
- default:
- break;
- case MINTR_RST_B:
- escc_reset_chn(&serial->chn[0]);
- return;
- case MINTR_RST_A:
- escc_reset_chn(&serial->chn[1]);
- return;
- case MINTR_RST_ALL:
- escc_reset(DEVICE(serial));
- return;
- }
- break;
- default:
- break;
- }
- if (s->reg == 0)
- s->reg = newreg;
- else
- s->reg = 0;
- break;
- case SERIAL_DATA:
- trace_escc_mem_writeb_data(CHN_C(s), val);
- s->tx = val;
- if (s->wregs[W_TXCTRL2] & TXCTRL2_TXEN) { // tx enabled
- if (s->chr)
- qemu_chr_fe_write(s->chr, &s->tx, 1);
- else if (s->type == kbd && !s->disabled) {
- handle_kbd_command(s, val);
- }
- }
- s->rregs[R_STATUS] |= STATUS_TXEMPTY; // Tx buffer empty
- s->rregs[R_SPEC] |= SPEC_ALLSENT; // All sent
- set_txint(s);
- break;
- default:
- break;
- }
-}
-
-static uint64_t escc_mem_read(void *opaque, hwaddr addr,
- unsigned size)
-{
- ESCCState *serial = opaque;
- ChannelState *s;
- uint32_t saddr;
- uint32_t ret;
- int channel;
-
- saddr = (addr >> serial->it_shift) & 1;
- channel = (addr >> (serial->it_shift + 1)) & 1;
- s = &serial->chn[channel];
- switch (saddr) {
- case SERIAL_CTRL:
- trace_escc_mem_readb_ctrl(CHN_C(s), s->reg, s->rregs[s->reg]);
- ret = s->rregs[s->reg];
- s->reg = 0;
- return ret;
- case SERIAL_DATA:
- s->rregs[R_STATUS] &= ~STATUS_RXAV;
- clr_rxint(s);
- if (s->type == kbd || s->type == mouse)
- ret = get_queue(s);
- else
- ret = s->rx;
- trace_escc_mem_readb_data(CHN_C(s), ret);
- if (s->chr)
- qemu_chr_accept_input(s->chr);
- return ret;
- default:
- break;
- }
- return 0;
-}
-
-static const MemoryRegionOps escc_mem_ops = {
- .read = escc_mem_read,
- .write = escc_mem_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
- .valid = {
- .min_access_size = 1,
- .max_access_size = 1,
- },
-};
-
-static int serial_can_receive(void *opaque)
-{
- ChannelState *s = opaque;
- int ret;
-
- if (((s->wregs[W_RXCTRL] & RXCTRL_RXEN) == 0) // Rx not enabled
- || ((s->rregs[R_STATUS] & STATUS_RXAV) == STATUS_RXAV))
- // char already available
- ret = 0;
- else
- ret = 1;
- return ret;
-}
-
-static void serial_receive_byte(ChannelState *s, int ch)
-{
- trace_escc_serial_receive_byte(CHN_C(s), ch);
- s->rregs[R_STATUS] |= STATUS_RXAV;
- s->rx = ch;
- set_rxint(s);
-}
-
-static void serial_receive_break(ChannelState *s)
-{
- s->rregs[R_STATUS] |= STATUS_BRK;
- escc_update_irq(s);
-}
-
-static void serial_receive1(void *opaque, const uint8_t *buf, int size)
-{
- ChannelState *s = opaque;
- serial_receive_byte(s, buf[0]);
-}
-
-static void serial_event(void *opaque, int event)
-{
- ChannelState *s = opaque;
- if (event == CHR_EVENT_BREAK)
- serial_receive_break(s);
-}
-
-static const VMStateDescription vmstate_escc_chn = {
- .name ="escc_chn",
- .version_id = 2,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(vmstate_dummy, ChannelState),
- VMSTATE_UINT32(reg, ChannelState),
- VMSTATE_UINT32(rxint, ChannelState),
- VMSTATE_UINT32(txint, ChannelState),
- VMSTATE_UINT32(rxint_under_svc, ChannelState),
- VMSTATE_UINT32(txint_under_svc, ChannelState),
- VMSTATE_UINT8(rx, ChannelState),
- VMSTATE_UINT8(tx, ChannelState),
- VMSTATE_BUFFER(wregs, ChannelState),
- VMSTATE_BUFFER(rregs, ChannelState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_escc = {
- .name ="escc",
- .version_id = 2,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_STRUCT_ARRAY(chn, ESCCState, 2, 2, vmstate_escc_chn,
- ChannelState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-MemoryRegion *escc_init(hwaddr base, qemu_irq irqA, qemu_irq irqB,
- CharDriverState *chrA, CharDriverState *chrB,
- int clock, int it_shift)
-{
- DeviceState *dev;
- SysBusDevice *s;
- ESCCState *d;
-
- dev = qdev_create(NULL, TYPE_ESCC);
- qdev_prop_set_uint32(dev, "disabled", 0);
- qdev_prop_set_uint32(dev, "frequency", clock);
- qdev_prop_set_uint32(dev, "it_shift", it_shift);
- qdev_prop_set_chr(dev, "chrB", chrB);
- qdev_prop_set_chr(dev, "chrA", chrA);
- qdev_prop_set_uint32(dev, "chnBtype", ser);
- qdev_prop_set_uint32(dev, "chnAtype", ser);
- qdev_init_nofail(dev);
- s = SYS_BUS_DEVICE(dev);
- sysbus_connect_irq(s, 0, irqB);
- sysbus_connect_irq(s, 1, irqA);
- if (base) {
- sysbus_mmio_map(s, 0, base);
- }
-
- d = ESCC(s);
- return &d->mmio;
-}
-
-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,
- [Q_KEY_CODE_ALT_R] = 13,
- [Q_KEY_CODE_ALTGR] = 13,
- [Q_KEY_CODE_CTRL] = 76,
- [Q_KEY_CODE_CTRL_R] = 76,
- [Q_KEY_CODE_ESC] = 29,
- [Q_KEY_CODE_1] = 30,
- [Q_KEY_CODE_2] = 31,
- [Q_KEY_CODE_3] = 32,
- [Q_KEY_CODE_4] = 33,
- [Q_KEY_CODE_5] = 34,
- [Q_KEY_CODE_6] = 35,
- [Q_KEY_CODE_7] = 36,
- [Q_KEY_CODE_8] = 37,
- [Q_KEY_CODE_9] = 38,
- [Q_KEY_CODE_0] = 39,
- [Q_KEY_CODE_MINUS] = 40,
- [Q_KEY_CODE_EQUAL] = 41,
- [Q_KEY_CODE_BACKSPACE] = 43,
- [Q_KEY_CODE_TAB] = 53,
- [Q_KEY_CODE_Q] = 54,
- [Q_KEY_CODE_W] = 55,
- [Q_KEY_CODE_E] = 56,
- [Q_KEY_CODE_R] = 57,
- [Q_KEY_CODE_T] = 58,
- [Q_KEY_CODE_Y] = 59,
- [Q_KEY_CODE_U] = 60,
- [Q_KEY_CODE_I] = 61,
- [Q_KEY_CODE_O] = 62,
- [Q_KEY_CODE_P] = 63,
- [Q_KEY_CODE_BRACKET_LEFT] = 64,
- [Q_KEY_CODE_BRACKET_RIGHT] = 65,
- [Q_KEY_CODE_RET] = 89,
- [Q_KEY_CODE_A] = 77,
- [Q_KEY_CODE_S] = 78,
- [Q_KEY_CODE_D] = 79,
- [Q_KEY_CODE_F] = 80,
- [Q_KEY_CODE_G] = 81,
- [Q_KEY_CODE_H] = 82,
- [Q_KEY_CODE_J] = 83,
- [Q_KEY_CODE_K] = 84,
- [Q_KEY_CODE_L] = 85,
- [Q_KEY_CODE_SEMICOLON] = 86,
- [Q_KEY_CODE_APOSTROPHE] = 87,
- [Q_KEY_CODE_GRAVE_ACCENT] = 42,
- [Q_KEY_CODE_BACKSLASH] = 88,
- [Q_KEY_CODE_Z] = 100,
- [Q_KEY_CODE_X] = 101,
- [Q_KEY_CODE_C] = 102,
- [Q_KEY_CODE_V] = 103,
- [Q_KEY_CODE_B] = 104,
- [Q_KEY_CODE_N] = 105,
- [Q_KEY_CODE_M] = 106,
- [Q_KEY_CODE_COMMA] = 107,
- [Q_KEY_CODE_DOT] = 108,
- [Q_KEY_CODE_SLASH] = 109,
- [Q_KEY_CODE_ASTERISK] = 47,
- [Q_KEY_CODE_SPC] = 121,
- [Q_KEY_CODE_CAPS_LOCK] = 119,
- [Q_KEY_CODE_F1] = 5,
- [Q_KEY_CODE_F2] = 6,
- [Q_KEY_CODE_F3] = 8,
- [Q_KEY_CODE_F4] = 10,
- [Q_KEY_CODE_F5] = 12,
- [Q_KEY_CODE_F6] = 14,
- [Q_KEY_CODE_F7] = 16,
- [Q_KEY_CODE_F8] = 17,
- [Q_KEY_CODE_F9] = 18,
- [Q_KEY_CODE_F10] = 7,
- [Q_KEY_CODE_NUM_LOCK] = 98,
- [Q_KEY_CODE_SCROLL_LOCK] = 23,
- [Q_KEY_CODE_KP_DIVIDE] = 46,
- [Q_KEY_CODE_KP_MULTIPLY] = 47,
- [Q_KEY_CODE_KP_SUBTRACT] = 71,
- [Q_KEY_CODE_KP_ADD] = 125,
- [Q_KEY_CODE_KP_ENTER] = 90,
- [Q_KEY_CODE_KP_DECIMAL] = 50,
- [Q_KEY_CODE_KP_0] = 94,
- [Q_KEY_CODE_KP_1] = 112,
- [Q_KEY_CODE_KP_2] = 113,
- [Q_KEY_CODE_KP_3] = 114,
- [Q_KEY_CODE_KP_4] = 91,
- [Q_KEY_CODE_KP_5] = 92,
- [Q_KEY_CODE_KP_6] = 93,
- [Q_KEY_CODE_KP_7] = 68,
- [Q_KEY_CODE_KP_8] = 69,
- [Q_KEY_CODE_KP_9] = 70,
- [Q_KEY_CODE_LESS] = 124,
- [Q_KEY_CODE_F11] = 9,
- [Q_KEY_CODE_F12] = 11,
- [Q_KEY_CODE_HOME] = 52,
- [Q_KEY_CODE_PGUP] = 96,
- [Q_KEY_CODE_PGDN] = 123,
- [Q_KEY_CODE_END] = 74,
- [Q_KEY_CODE_LEFT] = 24,
- [Q_KEY_CODE_UP] = 20,
- [Q_KEY_CODE_DOWN] = 27,
- [Q_KEY_CODE_RIGHT] = 28,
- [Q_KEY_CODE_INSERT] = 44,
- [Q_KEY_CODE_DELETE] = 66,
- [Q_KEY_CODE_STOP] = 1,
- [Q_KEY_CODE_AGAIN] = 3,
- [Q_KEY_CODE_PROPS] = 25,
- [Q_KEY_CODE_UNDO] = 26,
- [Q_KEY_CODE_FRONT] = 49,
- [Q_KEY_CODE_COPY] = 51,
- [Q_KEY_CODE_OPEN] = 72,
- [Q_KEY_CODE_PASTE] = 73,
- [Q_KEY_CODE_FIND] = 95,
- [Q_KEY_CODE_CUT] = 97,
- [Q_KEY_CODE_LF] = 111,
- [Q_KEY_CODE_HELP] = 118,
- [Q_KEY_CODE_META_L] = 120,
- [Q_KEY_CODE_META_R] = 122,
- [Q_KEY_CODE_COMPOSE] = 67,
- [Q_KEY_CODE_PRINT] = 22,
- [Q_KEY_CODE_SYSRQ] = 21,
-};
-
-static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src,
- InputEvent *evt)
-{
- ChannelState *s = (ChannelState *)dev;
- int qcode, keycode;
- InputKeyEvent *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],
- key->down);
-
- if (qcode == Q_KEY_CODE_CAPS_LOCK) {
- if (key->down) {
- s->caps_lock_mode ^= 1;
- if (s->caps_lock_mode == 2) {
- return; /* Drop second press */
- }
- } else {
- s->caps_lock_mode ^= 2;
- if (s->caps_lock_mode == 3) {
- return; /* Drop first release */
- }
- }
- }
-
- if (qcode == Q_KEY_CODE_NUM_LOCK) {
- if (key->down) {
- s->num_lock_mode ^= 1;
- if (s->num_lock_mode == 2) {
- return; /* Drop second press */
- }
- } else {
- s->num_lock_mode ^= 2;
- if (s->num_lock_mode == 3) {
- return; /* Drop first release */
- }
- }
- }
-
- keycode = qcode_to_keycode[qcode];
- if (!key->down) {
- keycode |= 0x80;
- }
- trace_escc_sunkbd_event_out(keycode);
- put_queue(s, keycode);
-}
-
-static QemuInputHandler sunkbd_handler = {
- .name = "sun keyboard",
- .mask = INPUT_EVENT_MASK_KEY,
- .event = sunkbd_handle_event,
-};
-
-static void handle_kbd_command(ChannelState *s, int val)
-{
- trace_escc_kbd_command(val);
- if (s->led_mode) { // Ignore led byte
- s->led_mode = 0;
- return;
- }
- switch (val) {
- case 1: // Reset, return type code
- clear_queue(s);
- put_queue(s, 0xff);
- put_queue(s, 4); // Type 4
- put_queue(s, 0x7f);
- break;
- case 0xe: // Set leds
- s->led_mode = 1;
- break;
- case 7: // Query layout
- case 0xf:
- clear_queue(s);
- put_queue(s, 0xfe);
- put_queue(s, 0x21); /* en-us layout */
- break;
- default:
- break;
- }
-}
-
-static void sunmouse_event(void *opaque,
- int dx, int dy, int dz, int buttons_state)
-{
- ChannelState *s = opaque;
- int ch;
-
- trace_escc_sunmouse_event(dx, dy, buttons_state);
- ch = 0x80 | 0x7; /* protocol start byte, no buttons pressed */
-
- if (buttons_state & MOUSE_EVENT_LBUTTON)
- ch ^= 0x4;
- if (buttons_state & MOUSE_EVENT_MBUTTON)
- ch ^= 0x2;
- if (buttons_state & MOUSE_EVENT_RBUTTON)
- ch ^= 0x1;
-
- put_queue(s, ch);
-
- ch = dx;
-
- if (ch > 127)
- ch = 127;
- else if (ch < -127)
- ch = -127;
-
- put_queue(s, ch & 0xff);
-
- ch = -dy;
-
- if (ch > 127)
- ch = 127;
- else if (ch < -127)
- ch = -127;
-
- put_queue(s, ch & 0xff);
-
- // MSC protocol specify two extra motion bytes
-
- put_queue(s, 0);
- put_queue(s, 0);
-}
-
-void slavio_serial_ms_kbd_init(hwaddr base, qemu_irq irq,
- int disabled, int clock, int it_shift)
-{
- DeviceState *dev;
- SysBusDevice *s;
-
- dev = qdev_create(NULL, TYPE_ESCC);
- qdev_prop_set_uint32(dev, "disabled", disabled);
- qdev_prop_set_uint32(dev, "frequency", clock);
- qdev_prop_set_uint32(dev, "it_shift", it_shift);
- qdev_prop_set_chr(dev, "chrB", NULL);
- qdev_prop_set_chr(dev, "chrA", NULL);
- qdev_prop_set_uint32(dev, "chnBtype", mouse);
- qdev_prop_set_uint32(dev, "chnAtype", kbd);
- qdev_init_nofail(dev);
- s = SYS_BUS_DEVICE(dev);
- sysbus_connect_irq(s, 0, irq);
- sysbus_connect_irq(s, 1, irq);
- sysbus_mmio_map(s, 0, base);
-}
-
-static int escc_init1(SysBusDevice *dev)
-{
- ESCCState *s = ESCC(dev);
- unsigned int i;
-
- s->chn[0].disabled = s->disabled;
- s->chn[1].disabled = s->disabled;
- 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) {
- 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,
- "QEMU Sun Mouse");
- }
- if (s->chn[1].type == kbd) {
- s->chn[1].hs = qemu_input_handler_register((DeviceState *)(&s->chn[1]),
- &sunkbd_handler);
- }
-
- return 0;
-}
-
-static Property escc_properties[] = {
- DEFINE_PROP_UINT32("frequency", ESCCState, frequency, 0),
- DEFINE_PROP_UINT32("it_shift", ESCCState, it_shift, 0),
- DEFINE_PROP_UINT32("disabled", ESCCState, disabled, 0),
- DEFINE_PROP_UINT32("chnBtype", ESCCState, chn[0].type, 0),
- DEFINE_PROP_UINT32("chnAtype", ESCCState, chn[1].type, 0),
- DEFINE_PROP_CHR("chrB", ESCCState, chn[0].chr),
- DEFINE_PROP_CHR("chrA", ESCCState, chn[1].chr),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-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->vmsd = &vmstate_escc;
- dc->props = escc_properties;
- set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
-}
-
-static const TypeInfo escc_info = {
- .name = TYPE_ESCC,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(ESCCState),
- .class_init = escc_class_init,
-};
-
-static void escc_register_types(void)
-{
- type_register_static(&escc_info);
-}
-
-type_init(escc_register_types)
diff --git a/qemu/hw/char/etraxfs_ser.c b/qemu/hw/char/etraxfs_ser.c
deleted file mode 100644
index 146b387e7..000000000
--- a/qemu/hw/char/etraxfs_ser.c
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * QEMU ETRAX System Emulator
- *
- * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "qemu/osdep.h"
-#include "hw/sysbus.h"
-#include "sysemu/char.h"
-#include "qemu/log.h"
-
-#define D(x)
-
-#define RW_TR_CTRL (0x00 / 4)
-#define RW_TR_DMA_EN (0x04 / 4)
-#define RW_REC_CTRL (0x08 / 4)
-#define RW_DOUT (0x1c / 4)
-#define RS_STAT_DIN (0x20 / 4)
-#define R_STAT_DIN (0x24 / 4)
-#define RW_INTR_MASK (0x2c / 4)
-#define RW_ACK_INTR (0x30 / 4)
-#define R_INTR (0x34 / 4)
-#define R_MASKED_INTR (0x38 / 4)
-#define R_MAX (0x3c / 4)
-
-#define STAT_DAV 16
-#define STAT_TR_IDLE 22
-#define STAT_TR_RDY 24
-
-#define TYPE_ETRAX_FS_SERIAL "etraxfs,serial"
-#define ETRAX_SERIAL(obj) \
- OBJECT_CHECK(ETRAXSerial, (obj), TYPE_ETRAX_FS_SERIAL)
-
-typedef struct ETRAXSerial {
- SysBusDevice parent_obj;
-
- MemoryRegion mmio;
- CharDriverState *chr;
- qemu_irq irq;
-
- int pending_tx;
-
- uint8_t rx_fifo[16];
- unsigned int rx_fifo_pos;
- unsigned int rx_fifo_len;
-
- /* Control registers. */
- uint32_t regs[R_MAX];
-} ETRAXSerial;
-
-static void ser_update_irq(ETRAXSerial *s)
-{
-
- if (s->rx_fifo_len) {
- s->regs[R_INTR] |= 8;
- } else {
- s->regs[R_INTR] &= ~8;
- }
-
- s->regs[R_MASKED_INTR] = s->regs[R_INTR] & s->regs[RW_INTR_MASK];
- qemu_set_irq(s->irq, !!s->regs[R_MASKED_INTR]);
-}
-
-static uint64_t
-ser_read(void *opaque, hwaddr addr, unsigned int size)
-{
- ETRAXSerial *s = opaque;
- uint32_t r = 0;
-
- addr >>= 2;
- switch (addr)
- {
- case R_STAT_DIN:
- r = s->rx_fifo[(s->rx_fifo_pos - s->rx_fifo_len) & 15];
- if (s->rx_fifo_len) {
- r |= 1 << STAT_DAV;
- }
- r |= 1 << STAT_TR_RDY;
- r |= 1 << STAT_TR_IDLE;
- break;
- case RS_STAT_DIN:
- r = s->rx_fifo[(s->rx_fifo_pos - s->rx_fifo_len) & 15];
- if (s->rx_fifo_len) {
- r |= 1 << STAT_DAV;
- s->rx_fifo_len--;
- }
- r |= 1 << STAT_TR_RDY;
- r |= 1 << STAT_TR_IDLE;
- break;
- default:
- r = s->regs[addr];
- D(qemu_log("%s " TARGET_FMT_plx "=%x\n", __func__, addr, r));
- break;
- }
- return r;
-}
-
-static void
-ser_write(void *opaque, hwaddr addr,
- uint64_t val64, unsigned int size)
-{
- ETRAXSerial *s = opaque;
- uint32_t value = val64;
- unsigned char ch = val64;
-
- D(qemu_log("%s " TARGET_FMT_plx "=%x\n", __func__, addr, value));
- addr >>= 2;
- switch (addr)
- {
- case RW_DOUT:
- qemu_chr_fe_write(s->chr, &ch, 1);
- s->regs[R_INTR] |= 3;
- s->pending_tx = 1;
- s->regs[addr] = value;
- break;
- case RW_ACK_INTR:
- if (s->pending_tx) {
- value &= ~1;
- s->pending_tx = 0;
- D(qemu_log("fixedup value=%x r_intr=%x\n",
- value, s->regs[R_INTR]));
- }
- s->regs[addr] = value;
- s->regs[R_INTR] &= ~value;
- D(printf("r_intr=%x\n", s->regs[R_INTR]));
- break;
- default:
- s->regs[addr] = value;
- break;
- }
- ser_update_irq(s);
-}
-
-static const MemoryRegionOps ser_ops = {
- .read = ser_read,
- .write = ser_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
- .valid = {
- .min_access_size = 4,
- .max_access_size = 4
- }
-};
-
-static void serial_receive(void *opaque, const uint8_t *buf, int size)
-{
- ETRAXSerial *s = opaque;
- int i;
-
- /* Got a byte. */
- if (s->rx_fifo_len >= 16) {
- D(qemu_log("WARNING: UART dropped char.\n"));
- return;
- }
-
- for (i = 0; i < size; i++) {
- s->rx_fifo[s->rx_fifo_pos] = buf[i];
- s->rx_fifo_pos++;
- s->rx_fifo_pos &= 15;
- s->rx_fifo_len++;
- }
-
- ser_update_irq(s);
-}
-
-static int serial_can_receive(void *opaque)
-{
- ETRAXSerial *s = opaque;
-
- /* Is the receiver enabled? */
- if (!(s->regs[RW_REC_CTRL] & (1 << 3))) {
- return 0;
- }
-
- return sizeof(s->rx_fifo) - s->rx_fifo_len;
-}
-
-static void serial_event(void *opaque, int event)
-{
-
-}
-
-static void etraxfs_ser_reset(DeviceState *d)
-{
- ETRAXSerial *s = ETRAX_SERIAL(d);
-
- /* transmitter begins ready and idle. */
- s->regs[RS_STAT_DIN] |= (1 << STAT_TR_RDY);
- s->regs[RS_STAT_DIN] |= (1 << STAT_TR_IDLE);
-
- s->regs[RW_REC_CTRL] = 0x10000;
-
-}
-
-static int etraxfs_ser_init(SysBusDevice *dev)
-{
- ETRAXSerial *s = ETRAX_SERIAL(dev);
-
- sysbus_init_irq(dev, &s->irq);
- memory_region_init_io(&s->mmio, OBJECT(s), &ser_ops, s,
- "etraxfs-serial", R_MAX * 4);
- sysbus_init_mmio(dev, &s->mmio);
-
- /* 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;
-}
-
-static const TypeInfo etraxfs_ser_info = {
- .name = TYPE_ETRAX_FS_SERIAL,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(ETRAXSerial),
- .class_init = etraxfs_ser_class_init,
-};
-
-static void etraxfs_serial_register_types(void)
-{
- type_register_static(&etraxfs_ser_info);
-}
-
-type_init(etraxfs_serial_register_types)
diff --git a/qemu/hw/char/exynos4210_uart.c b/qemu/hw/char/exynos4210_uart.c
deleted file mode 100644
index 885ecc027..000000000
--- a/qemu/hw/char/exynos4210_uart.c
+++ /dev/null
@@ -1,678 +0,0 @@
-/*
- * Exynos4210 UART Emulation
- *
- * Copyright (C) 2011 Samsung Electronics Co Ltd.
- * Maksim Kozlov, <m.kozlov@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * 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 "hw/sysbus.h"
-#include "qemu/error-report.h"
-#include "sysemu/sysemu.h"
-#include "sysemu/char.h"
-
-#include "hw/arm/exynos4210.h"
-
-#undef DEBUG_UART
-#undef DEBUG_UART_EXTEND
-#undef DEBUG_IRQ
-#undef DEBUG_Rx_DATA
-#undef DEBUG_Tx_DATA
-
-#define DEBUG_UART 0
-#define DEBUG_UART_EXTEND 0
-#define DEBUG_IRQ 0
-#define DEBUG_Rx_DATA 0
-#define DEBUG_Tx_DATA 0
-
-#if DEBUG_UART
-#define PRINT_DEBUG(fmt, args...) \
- do { \
- fprintf(stderr, " [%s:%d] "fmt, __func__, __LINE__, ##args); \
- } while (0)
-
-#if DEBUG_UART_EXTEND
-#define PRINT_DEBUG_EXTEND(fmt, args...) \
- do { \
- fprintf(stderr, " [%s:%d] "fmt, __func__, __LINE__, ##args); \
- } while (0)
-#else
-#define PRINT_DEBUG_EXTEND(fmt, args...) \
- do {} while (0)
-#endif /* EXTEND */
-
-#else
-#define PRINT_DEBUG(fmt, args...) \
- do {} while (0)
-#define PRINT_DEBUG_EXTEND(fmt, args...) \
- do {} while (0)
-#endif
-
-#define PRINT_ERROR(fmt, args...) \
- do { \
- fprintf(stderr, " [%s:%d] "fmt, __func__, __LINE__, ##args); \
- } while (0)
-
-/*
- * Offsets for UART registers relative to SFR base address
- * for UARTn
- *
- */
-#define ULCON 0x0000 /* Line Control */
-#define UCON 0x0004 /* Control */
-#define UFCON 0x0008 /* FIFO Control */
-#define UMCON 0x000C /* Modem Control */
-#define UTRSTAT 0x0010 /* Tx/Rx Status */
-#define UERSTAT 0x0014 /* UART Error Status */
-#define UFSTAT 0x0018 /* FIFO Status */
-#define UMSTAT 0x001C /* Modem Status */
-#define UTXH 0x0020 /* Transmit Buffer */
-#define URXH 0x0024 /* Receive Buffer */
-#define UBRDIV 0x0028 /* Baud Rate Divisor */
-#define UFRACVAL 0x002C /* Divisor Fractional Value */
-#define UINTP 0x0030 /* Interrupt Pending */
-#define UINTSP 0x0034 /* Interrupt Source Pending */
-#define UINTM 0x0038 /* Interrupt Mask */
-
-/*
- * for indexing register in the uint32_t array
- *
- * 'reg' - register offset (see offsets definitions above)
- *
- */
-#define I_(reg) (reg / sizeof(uint32_t))
-
-typedef struct Exynos4210UartReg {
- const char *name; /* the only reason is the debug output */
- hwaddr offset;
- uint32_t reset_value;
-} Exynos4210UartReg;
-
-static Exynos4210UartReg exynos4210_uart_regs[] = {
- {"ULCON", ULCON, 0x00000000},
- {"UCON", UCON, 0x00003000},
- {"UFCON", UFCON, 0x00000000},
- {"UMCON", UMCON, 0x00000000},
- {"UTRSTAT", UTRSTAT, 0x00000006}, /* RO */
- {"UERSTAT", UERSTAT, 0x00000000}, /* RO */
- {"UFSTAT", UFSTAT, 0x00000000}, /* RO */
- {"UMSTAT", UMSTAT, 0x00000000}, /* RO */
- {"UTXH", UTXH, 0x5c5c5c5c}, /* WO, undefined reset value*/
- {"URXH", URXH, 0x00000000}, /* RO */
- {"UBRDIV", UBRDIV, 0x00000000},
- {"UFRACVAL", UFRACVAL, 0x00000000},
- {"UINTP", UINTP, 0x00000000},
- {"UINTSP", UINTSP, 0x00000000},
- {"UINTM", UINTM, 0x00000000},
-};
-
-#define EXYNOS4210_UART_REGS_MEM_SIZE 0x3C
-
-/* UART FIFO Control */
-#define UFCON_FIFO_ENABLE 0x1
-#define UFCON_Rx_FIFO_RESET 0x2
-#define UFCON_Tx_FIFO_RESET 0x4
-#define UFCON_Tx_FIFO_TRIGGER_LEVEL_SHIFT 8
-#define UFCON_Tx_FIFO_TRIGGER_LEVEL (7 << UFCON_Tx_FIFO_TRIGGER_LEVEL_SHIFT)
-#define UFCON_Rx_FIFO_TRIGGER_LEVEL_SHIFT 4
-#define UFCON_Rx_FIFO_TRIGGER_LEVEL (7 << UFCON_Rx_FIFO_TRIGGER_LEVEL_SHIFT)
-
-/* Uart FIFO Status */
-#define UFSTAT_Rx_FIFO_COUNT 0xff
-#define UFSTAT_Rx_FIFO_FULL 0x100
-#define UFSTAT_Rx_FIFO_ERROR 0x200
-#define UFSTAT_Tx_FIFO_COUNT_SHIFT 16
-#define UFSTAT_Tx_FIFO_COUNT (0xff << UFSTAT_Tx_FIFO_COUNT_SHIFT)
-#define UFSTAT_Tx_FIFO_FULL_SHIFT 24
-#define UFSTAT_Tx_FIFO_FULL (1 << UFSTAT_Tx_FIFO_FULL_SHIFT)
-
-/* UART Interrupt Source Pending */
-#define UINTSP_RXD 0x1 /* Receive interrupt */
-#define UINTSP_ERROR 0x2 /* Error interrupt */
-#define UINTSP_TXD 0x4 /* Transmit interrupt */
-#define UINTSP_MODEM 0x8 /* Modem interrupt */
-
-/* UART Line Control */
-#define ULCON_IR_MODE_SHIFT 6
-#define ULCON_PARITY_SHIFT 3
-#define ULCON_STOP_BIT_SHIFT 1
-
-/* UART Tx/Rx Status */
-#define UTRSTAT_TRANSMITTER_EMPTY 0x4
-#define UTRSTAT_Tx_BUFFER_EMPTY 0x2
-#define UTRSTAT_Rx_BUFFER_DATA_READY 0x1
-
-/* UART Error Status */
-#define UERSTAT_OVERRUN 0x1
-#define UERSTAT_PARITY 0x2
-#define UERSTAT_FRAME 0x4
-#define UERSTAT_BREAK 0x8
-
-typedef struct {
- uint8_t *data;
- uint32_t sp, rp; /* store and retrieve pointers */
- uint32_t size;
-} Exynos4210UartFIFO;
-
-#define TYPE_EXYNOS4210_UART "exynos4210.uart"
-#define EXYNOS4210_UART(obj) \
- OBJECT_CHECK(Exynos4210UartState, (obj), TYPE_EXYNOS4210_UART)
-
-typedef struct Exynos4210UartState {
- SysBusDevice parent_obj;
-
- MemoryRegion iomem;
-
- uint32_t reg[EXYNOS4210_UART_REGS_MEM_SIZE / sizeof(uint32_t)];
- Exynos4210UartFIFO rx;
- Exynos4210UartFIFO tx;
-
- CharDriverState *chr;
- qemu_irq irq;
-
- uint32_t channel;
-
-} Exynos4210UartState;
-
-
-#if DEBUG_UART
-/* Used only for debugging inside PRINT_DEBUG_... macros */
-static const char *exynos4210_uart_regname(hwaddr offset)
-{
-
- int i;
-
- for (i = 0; i < ARRAY_SIZE(exynos4210_uart_regs); i++) {
- if (offset == exynos4210_uart_regs[i].offset) {
- return exynos4210_uart_regs[i].name;
- }
- }
-
- return NULL;
-}
-#endif
-
-
-static void fifo_store(Exynos4210UartFIFO *q, uint8_t ch)
-{
- q->data[q->sp] = ch;
- q->sp = (q->sp + 1) % q->size;
-}
-
-static uint8_t fifo_retrieve(Exynos4210UartFIFO *q)
-{
- uint8_t ret = q->data[q->rp];
- q->rp = (q->rp + 1) % q->size;
- return ret;
-}
-
-static int fifo_elements_number(Exynos4210UartFIFO *q)
-{
- if (q->sp < q->rp) {
- return q->size - q->rp + q->sp;
- }
-
- return q->sp - q->rp;
-}
-
-static int fifo_empty_elements_number(Exynos4210UartFIFO *q)
-{
- return q->size - fifo_elements_number(q);
-}
-
-static void fifo_reset(Exynos4210UartFIFO *q)
-{
- g_free(q->data);
- q->data = NULL;
-
- q->data = (uint8_t *)g_malloc0(q->size);
-
- q->sp = 0;
- q->rp = 0;
-}
-
-static uint32_t exynos4210_uart_Tx_FIFO_trigger_level(Exynos4210UartState *s)
-{
- uint32_t level = 0;
- uint32_t reg;
-
- reg = (s->reg[I_(UFCON)] & UFCON_Tx_FIFO_TRIGGER_LEVEL) >>
- UFCON_Tx_FIFO_TRIGGER_LEVEL_SHIFT;
-
- switch (s->channel) {
- case 0:
- level = reg * 32;
- break;
- case 1:
- case 4:
- level = reg * 8;
- break;
- case 2:
- case 3:
- level = reg * 2;
- break;
- default:
- level = 0;
- PRINT_ERROR("Wrong UART channel number: %d\n", s->channel);
- }
-
- return level;
-}
-
-static void exynos4210_uart_update_irq(Exynos4210UartState *s)
-{
- /*
- * The Tx interrupt is always requested if the number of data in the
- * transmit FIFO is smaller than the trigger level.
- */
- if (s->reg[I_(UFCON)] & UFCON_FIFO_ENABLE) {
-
- uint32_t count = (s->reg[I_(UFSTAT)] & UFSTAT_Tx_FIFO_COUNT) >>
- UFSTAT_Tx_FIFO_COUNT_SHIFT;
-
- if (count <= exynos4210_uart_Tx_FIFO_trigger_level(s)) {
- s->reg[I_(UINTSP)] |= UINTSP_TXD;
- }
- }
-
- s->reg[I_(UINTP)] = s->reg[I_(UINTSP)] & ~s->reg[I_(UINTM)];
-
- if (s->reg[I_(UINTP)]) {
- qemu_irq_raise(s->irq);
-
-#if DEBUG_IRQ
- fprintf(stderr, "UART%d: IRQ has been raised: %08x\n",
- s->channel, s->reg[I_(UINTP)]);
-#endif
-
- } else {
- qemu_irq_lower(s->irq);
- }
-}
-
-static void exynos4210_uart_update_parameters(Exynos4210UartState *s)
-{
- int speed, parity, data_bits, stop_bits, frame_size;
- QEMUSerialSetParams ssp;
- uint64_t uclk_rate;
-
- if (s->reg[I_(UBRDIV)] == 0) {
- return;
- }
-
- frame_size = 1; /* start bit */
- if (s->reg[I_(ULCON)] & 0x20) {
- frame_size++; /* parity bit */
- if (s->reg[I_(ULCON)] & 0x28) {
- parity = 'E';
- } else {
- parity = 'O';
- }
- } else {
- parity = 'N';
- }
-
- if (s->reg[I_(ULCON)] & 0x4) {
- stop_bits = 2;
- } else {
- stop_bits = 1;
- }
-
- data_bits = (s->reg[I_(ULCON)] & 0x3) + 5;
-
- frame_size += data_bits + stop_bits;
-
- uclk_rate = 24000000;
-
- speed = uclk_rate / ((16 * (s->reg[I_(UBRDIV)]) & 0xffff) +
- (s->reg[I_(UFRACVAL)] & 0x7) + 16);
-
- ssp.speed = speed;
- ssp.parity = parity;
- ssp.data_bits = data_bits;
- ssp.stop_bits = stop_bits;
-
- qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
-
- PRINT_DEBUG("UART%d: speed: %d, parity: %c, data: %d, stop: %d\n",
- s->channel, speed, parity, data_bits, stop_bits);
-}
-
-static void exynos4210_uart_write(void *opaque, hwaddr offset,
- uint64_t val, unsigned size)
-{
- Exynos4210UartState *s = (Exynos4210UartState *)opaque;
- uint8_t ch;
-
- PRINT_DEBUG_EXTEND("UART%d: <0x%04x> %s <- 0x%08llx\n", s->channel,
- offset, exynos4210_uart_regname(offset), (long long unsigned int)val);
-
- switch (offset) {
- case ULCON:
- case UBRDIV:
- case UFRACVAL:
- s->reg[I_(offset)] = val;
- exynos4210_uart_update_parameters(s);
- break;
- case UFCON:
- s->reg[I_(UFCON)] = val;
- if (val & UFCON_Rx_FIFO_RESET) {
- fifo_reset(&s->rx);
- s->reg[I_(UFCON)] &= ~UFCON_Rx_FIFO_RESET;
- PRINT_DEBUG("UART%d: Rx FIFO Reset\n", s->channel);
- }
- if (val & UFCON_Tx_FIFO_RESET) {
- fifo_reset(&s->tx);
- s->reg[I_(UFCON)] &= ~UFCON_Tx_FIFO_RESET;
- PRINT_DEBUG("UART%d: Tx FIFO Reset\n", s->channel);
- }
- break;
-
- case UTXH:
- if (s->chr) {
- s->reg[I_(UTRSTAT)] &= ~(UTRSTAT_TRANSMITTER_EMPTY |
- UTRSTAT_Tx_BUFFER_EMPTY);
- ch = (uint8_t)val;
- qemu_chr_fe_write(s->chr, &ch, 1);
-#if DEBUG_Tx_DATA
- fprintf(stderr, "%c", ch);
-#endif
- s->reg[I_(UTRSTAT)] |= UTRSTAT_TRANSMITTER_EMPTY |
- UTRSTAT_Tx_BUFFER_EMPTY;
- s->reg[I_(UINTSP)] |= UINTSP_TXD;
- exynos4210_uart_update_irq(s);
- }
- break;
-
- case UINTP:
- s->reg[I_(UINTP)] &= ~val;
- s->reg[I_(UINTSP)] &= ~val;
- PRINT_DEBUG("UART%d: UINTP [%04x] have been cleared: %08x\n",
- s->channel, offset, s->reg[I_(UINTP)]);
- exynos4210_uart_update_irq(s);
- break;
- case UTRSTAT:
- case UERSTAT:
- case UFSTAT:
- case UMSTAT:
- case URXH:
- PRINT_DEBUG("UART%d: Trying to write into RO register: %s [%04x]\n",
- s->channel, exynos4210_uart_regname(offset), offset);
- break;
- case UINTSP:
- s->reg[I_(UINTSP)] &= ~val;
- break;
- case UINTM:
- s->reg[I_(UINTM)] = val;
- exynos4210_uart_update_irq(s);
- break;
- case UCON:
- case UMCON:
- default:
- s->reg[I_(offset)] = val;
- break;
- }
-}
-static uint64_t exynos4210_uart_read(void *opaque, hwaddr offset,
- unsigned size)
-{
- Exynos4210UartState *s = (Exynos4210UartState *)opaque;
- uint32_t res;
-
- switch (offset) {
- case UERSTAT: /* Read Only */
- res = s->reg[I_(UERSTAT)];
- s->reg[I_(UERSTAT)] = 0;
- return res;
- case UFSTAT: /* Read Only */
- s->reg[I_(UFSTAT)] = fifo_elements_number(&s->rx) & 0xff;
- if (fifo_empty_elements_number(&s->rx) == 0) {
- s->reg[I_(UFSTAT)] |= UFSTAT_Rx_FIFO_FULL;
- s->reg[I_(UFSTAT)] &= ~0xff;
- }
- return s->reg[I_(UFSTAT)];
- case URXH:
- if (s->reg[I_(UFCON)] & UFCON_FIFO_ENABLE) {
- if (fifo_elements_number(&s->rx)) {
- res = fifo_retrieve(&s->rx);
-#if DEBUG_Rx_DATA
- fprintf(stderr, "%c", res);
-#endif
- if (!fifo_elements_number(&s->rx)) {
- s->reg[I_(UTRSTAT)] &= ~UTRSTAT_Rx_BUFFER_DATA_READY;
- } else {
- s->reg[I_(UTRSTAT)] |= UTRSTAT_Rx_BUFFER_DATA_READY;
- }
- } else {
- s->reg[I_(UINTSP)] |= UINTSP_ERROR;
- exynos4210_uart_update_irq(s);
- res = 0;
- }
- } else {
- s->reg[I_(UTRSTAT)] &= ~UTRSTAT_Rx_BUFFER_DATA_READY;
- res = s->reg[I_(URXH)];
- }
- return res;
- case UTXH:
- PRINT_DEBUG("UART%d: Trying to read from WO register: %s [%04x]\n",
- s->channel, exynos4210_uart_regname(offset), offset);
- break;
- default:
- return s->reg[I_(offset)];
- }
-
- return 0;
-}
-
-static const MemoryRegionOps exynos4210_uart_ops = {
- .read = exynos4210_uart_read,
- .write = exynos4210_uart_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
- .valid = {
- .max_access_size = 4,
- .unaligned = false
- },
-};
-
-static int exynos4210_uart_can_receive(void *opaque)
-{
- Exynos4210UartState *s = (Exynos4210UartState *)opaque;
-
- return fifo_empty_elements_number(&s->rx);
-}
-
-
-static void exynos4210_uart_receive(void *opaque, const uint8_t *buf, int size)
-{
- Exynos4210UartState *s = (Exynos4210UartState *)opaque;
- int i;
-
- if (s->reg[I_(UFCON)] & UFCON_FIFO_ENABLE) {
- if (fifo_empty_elements_number(&s->rx) < size) {
- for (i = 0; i < fifo_empty_elements_number(&s->rx); i++) {
- fifo_store(&s->rx, buf[i]);
- }
- s->reg[I_(UINTSP)] |= UINTSP_ERROR;
- s->reg[I_(UTRSTAT)] |= UTRSTAT_Rx_BUFFER_DATA_READY;
- } else {
- for (i = 0; i < size; i++) {
- fifo_store(&s->rx, buf[i]);
- }
- s->reg[I_(UTRSTAT)] |= UTRSTAT_Rx_BUFFER_DATA_READY;
- }
- /* XXX: Around here we maybe should check Rx trigger level */
- s->reg[I_(UINTSP)] |= UINTSP_RXD;
- } else {
- s->reg[I_(URXH)] = buf[0];
- s->reg[I_(UINTSP)] |= UINTSP_RXD;
- s->reg[I_(UTRSTAT)] |= UTRSTAT_Rx_BUFFER_DATA_READY;
- }
-
- exynos4210_uart_update_irq(s);
-}
-
-
-static void exynos4210_uart_event(void *opaque, int event)
-{
- Exynos4210UartState *s = (Exynos4210UartState *)opaque;
-
- if (event == CHR_EVENT_BREAK) {
- /* When the RxDn is held in logic 0, then a null byte is pushed into the
- * fifo */
- fifo_store(&s->rx, '\0');
- s->reg[I_(UERSTAT)] |= UERSTAT_BREAK;
- exynos4210_uart_update_irq(s);
- }
-}
-
-
-static void exynos4210_uart_reset(DeviceState *dev)
-{
- Exynos4210UartState *s = EXYNOS4210_UART(dev);
- int i;
-
- for (i = 0; i < ARRAY_SIZE(exynos4210_uart_regs); i++) {
- s->reg[I_(exynos4210_uart_regs[i].offset)] =
- exynos4210_uart_regs[i].reset_value;
- }
-
- fifo_reset(&s->rx);
- fifo_reset(&s->tx);
-
- PRINT_DEBUG("UART%d: Rx FIFO size: %d\n", s->channel, s->rx.size);
-}
-
-static const VMStateDescription vmstate_exynos4210_uart_fifo = {
- .name = "exynos4210.uart.fifo",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(sp, Exynos4210UartFIFO),
- VMSTATE_UINT32(rp, Exynos4210UartFIFO),
- VMSTATE_VBUFFER_UINT32(data, Exynos4210UartFIFO, 1, NULL, 0, size),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_exynos4210_uart = {
- .name = "exynos4210.uart",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_STRUCT(rx, Exynos4210UartState, 1,
- vmstate_exynos4210_uart_fifo, Exynos4210UartFIFO),
- VMSTATE_UINT32_ARRAY(reg, Exynos4210UartState,
- EXYNOS4210_UART_REGS_MEM_SIZE / sizeof(uint32_t)),
- VMSTATE_END_OF_LIST()
- }
-};
-
-DeviceState *exynos4210_uart_create(hwaddr addr,
- int fifo_size,
- int channel,
- CharDriverState *chr,
- qemu_irq irq)
-{
- DeviceState *dev;
- SysBusDevice *bus;
-
- const char chr_name[] = "serial";
- char label[ARRAY_SIZE(chr_name) + 1];
-
- dev = qdev_create(NULL, TYPE_EXYNOS4210_UART);
-
- if (!chr) {
- if (channel >= 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)) {
- error_report("Can't assign serial port to UART%d", channel);
- exit(1);
- }
- }
- }
-
- qdev_prop_set_chr(dev, "chardev", chr);
- qdev_prop_set_uint32(dev, "channel", channel);
- qdev_prop_set_uint32(dev, "rx-size", fifo_size);
- qdev_prop_set_uint32(dev, "tx-size", fifo_size);
-
- 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);
-
- return dev;
-}
-
-static int exynos4210_uart_init(SysBusDevice *dev)
-{
- Exynos4210UartState *s = EXYNOS4210_UART(dev);
-
- /* memory mapping */
- memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_uart_ops, s,
- "exynos4210.uart", EXYNOS4210_UART_REGS_MEM_SIZE);
- sysbus_init_mmio(dev, &s->iomem);
-
- sysbus_init_irq(dev, &s->irq);
-
- qemu_chr_add_handlers(s->chr, exynos4210_uart_can_receive,
- exynos4210_uart_receive, exynos4210_uart_event, s);
-
- return 0;
-}
-
-static Property exynos4210_uart_properties[] = {
- DEFINE_PROP_CHR("chardev", Exynos4210UartState, chr),
- DEFINE_PROP_UINT32("channel", Exynos4210UartState, channel, 0),
- DEFINE_PROP_UINT32("rx-size", Exynos4210UartState, rx.size, 16),
- DEFINE_PROP_UINT32("tx-size", Exynos4210UartState, tx.size, 16),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void exynos4210_uart_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
- k->init = exynos4210_uart_init;
- dc->reset = exynos4210_uart_reset;
- dc->props = exynos4210_uart_properties;
- dc->vmsd = &vmstate_exynos4210_uart;
-}
-
-static const TypeInfo exynos4210_uart_info = {
- .name = TYPE_EXYNOS4210_UART,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(Exynos4210UartState),
- .class_init = exynos4210_uart_class_init,
-};
-
-static void exynos4210_uart_register(void)
-{
- type_register_static(&exynos4210_uart_info);
-}
-
-type_init(exynos4210_uart_register)
diff --git a/qemu/hw/char/grlib_apbuart.c b/qemu/hw/char/grlib_apbuart.c
deleted file mode 100644
index 871524c82..000000000
--- a/qemu/hw/char/grlib_apbuart.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * QEMU GRLIB APB UART Emulator
- *
- * Copyright (c) 2010-2011 AdaCore
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "qemu/osdep.h"
-#include "hw/sysbus.h"
-#include "sysemu/char.h"
-
-#include "trace.h"
-
-#define UART_REG_SIZE 20 /* Size of memory mapped registers */
-
-/* UART status register fields */
-#define UART_DATA_READY (1 << 0)
-#define UART_TRANSMIT_SHIFT_EMPTY (1 << 1)
-#define UART_TRANSMIT_FIFO_EMPTY (1 << 2)
-#define UART_BREAK_RECEIVED (1 << 3)
-#define UART_OVERRUN (1 << 4)
-#define UART_PARITY_ERROR (1 << 5)
-#define UART_FRAMING_ERROR (1 << 6)
-#define UART_TRANSMIT_FIFO_HALF (1 << 7)
-#define UART_RECEIVE_FIFO_HALF (1 << 8)
-#define UART_TRANSMIT_FIFO_FULL (1 << 9)
-#define UART_RECEIVE_FIFO_FULL (1 << 10)
-
-/* UART control register fields */
-#define UART_RECEIVE_ENABLE (1 << 0)
-#define UART_TRANSMIT_ENABLE (1 << 1)
-#define UART_RECEIVE_INTERRUPT (1 << 2)
-#define UART_TRANSMIT_INTERRUPT (1 << 3)
-#define UART_PARITY_SELECT (1 << 4)
-#define UART_PARITY_ENABLE (1 << 5)
-#define UART_FLOW_CONTROL (1 << 6)
-#define UART_LOOPBACK (1 << 7)
-#define UART_EXTERNAL_CLOCK (1 << 8)
-#define UART_RECEIVE_FIFO_INTERRUPT (1 << 9)
-#define UART_TRANSMIT_FIFO_INTERRUPT (1 << 10)
-#define UART_FIFO_DEBUG_MODE (1 << 11)
-#define UART_OUTPUT_ENABLE (1 << 12)
-#define UART_FIFO_AVAILABLE (1 << 31)
-
-/* Memory mapped register offsets */
-#define DATA_OFFSET 0x00
-#define STATUS_OFFSET 0x04
-#define CONTROL_OFFSET 0x08
-#define SCALER_OFFSET 0x0C /* not supported */
-#define FIFO_DEBUG_OFFSET 0x10 /* not supported */
-
-#define FIFO_LENGTH 1024
-
-#define TYPE_GRLIB_APB_UART "grlib,apbuart"
-#define GRLIB_APB_UART(obj) \
- OBJECT_CHECK(UART, (obj), TYPE_GRLIB_APB_UART)
-
-typedef struct UART {
- SysBusDevice parent_obj;
-
- MemoryRegion iomem;
- qemu_irq irq;
-
- CharDriverState *chr;
-
- /* registers */
- uint32_t status;
- uint32_t control;
-
- /* FIFO */
- char buffer[FIFO_LENGTH];
- int len;
- int current;
-} UART;
-
-static int uart_data_to_read(UART *uart)
-{
- return uart->current < uart->len;
-}
-
-static char uart_pop(UART *uart)
-{
- char ret;
-
- if (uart->len == 0) {
- uart->status &= ~UART_DATA_READY;
- return 0;
- }
-
- ret = uart->buffer[uart->current++];
-
- if (uart->current >= uart->len) {
- /* Flush */
- uart->len = 0;
- uart->current = 0;
- }
-
- if (!uart_data_to_read(uart)) {
- uart->status &= ~UART_DATA_READY;
- }
-
- return ret;
-}
-
-static void uart_add_to_fifo(UART *uart,
- const uint8_t *buffer,
- int length)
-{
- if (uart->len + length > FIFO_LENGTH) {
- abort();
- }
- memcpy(uart->buffer + uart->len, buffer, length);
- uart->len += length;
-}
-
-static int grlib_apbuart_can_receive(void *opaque)
-{
- UART *uart = opaque;
-
- return FIFO_LENGTH - uart->len;
-}
-
-static void grlib_apbuart_receive(void *opaque, const uint8_t *buf, int size)
-{
- UART *uart = opaque;
-
- if (uart->control & UART_RECEIVE_ENABLE) {
- uart_add_to_fifo(uart, buf, size);
-
- uart->status |= UART_DATA_READY;
-
- if (uart->control & UART_RECEIVE_INTERRUPT) {
- qemu_irq_pulse(uart->irq);
- }
- }
-}
-
-static void grlib_apbuart_event(void *opaque, int event)
-{
- trace_grlib_apbuart_event(event);
-}
-
-
-static uint64_t grlib_apbuart_read(void *opaque, hwaddr addr,
- unsigned size)
-{
- UART *uart = opaque;
-
- addr &= 0xff;
-
- /* Unit registers */
- switch (addr) {
- case DATA_OFFSET:
- case DATA_OFFSET + 3: /* when only one byte read */
- return uart_pop(uart);
-
- case STATUS_OFFSET:
- /* Read Only */
- return uart->status;
-
- case CONTROL_OFFSET:
- return uart->control;
-
- case SCALER_OFFSET:
- /* Not supported */
- return 0;
-
- default:
- trace_grlib_apbuart_readl_unknown(addr);
- return 0;
- }
-}
-
-static void grlib_apbuart_write(void *opaque, hwaddr addr,
- uint64_t value, unsigned size)
-{
- UART *uart = opaque;
- unsigned char c = 0;
-
- addr &= 0xff;
-
- /* Unit registers */
- switch (addr) {
- case DATA_OFFSET:
- case DATA_OFFSET + 3: /* When only one byte write */
- /* Transmit when character device available and transmitter enabled */
- if ((uart->chr) && (uart->control & UART_TRANSMIT_ENABLE)) {
- c = value & 0xFF;
- qemu_chr_fe_write(uart->chr, &c, 1);
- /* Generate interrupt */
- if (uart->control & UART_TRANSMIT_INTERRUPT) {
- qemu_irq_pulse(uart->irq);
- }
- }
- return;
-
- case STATUS_OFFSET:
- /* Read Only */
- return;
-
- case CONTROL_OFFSET:
- uart->control = value;
- return;
-
- case SCALER_OFFSET:
- /* Not supported */
- return;
-
- default:
- break;
- }
-
- trace_grlib_apbuart_writel_unknown(addr, value);
-}
-
-static const MemoryRegionOps grlib_apbuart_ops = {
- .write = grlib_apbuart_write,
- .read = grlib_apbuart_read,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int grlib_apbuart_init(SysBusDevice *dev)
-{
- UART *uart = GRLIB_APB_UART(dev);
-
- qemu_chr_add_handlers(uart->chr,
- grlib_apbuart_can_receive,
- grlib_apbuart_receive,
- grlib_apbuart_event,
- uart);
-
- sysbus_init_irq(dev, &uart->irq);
-
- memory_region_init_io(&uart->iomem, OBJECT(uart), &grlib_apbuart_ops, uart,
- "uart", UART_REG_SIZE);
-
- sysbus_init_mmio(dev, &uart->iomem);
-
- return 0;
-}
-
-static void grlib_apbuart_reset(DeviceState *d)
-{
- UART *uart = GRLIB_APB_UART(d);
-
- /* Transmitter FIFO and shift registers are always empty in QEMU */
- uart->status = UART_TRANSMIT_FIFO_EMPTY | UART_TRANSMIT_SHIFT_EMPTY;
- /* Everything is off */
- uart->control = 0;
- /* Flush receive FIFO */
- uart->len = 0;
- uart->current = 0;
-}
-
-static Property grlib_apbuart_properties[] = {
- DEFINE_PROP_CHR("chrdev", UART, chr),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void grlib_apbuart_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
- k->init = grlib_apbuart_init;
- dc->reset = grlib_apbuart_reset;
- dc->props = grlib_apbuart_properties;
-}
-
-static const TypeInfo grlib_apbuart_info = {
- .name = TYPE_GRLIB_APB_UART,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(UART),
- .class_init = grlib_apbuart_class_init,
-};
-
-static void grlib_apbuart_register_types(void)
-{
- type_register_static(&grlib_apbuart_info);
-}
-
-type_init(grlib_apbuart_register_types)
diff --git a/qemu/hw/char/imx_serial.c b/qemu/hw/char/imx_serial.c
deleted file mode 100644
index 6df74ac7c..000000000
--- a/qemu/hw/char/imx_serial.c
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * IMX31 UARTS
- *
- * 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.
- *
- * This is a `bare-bones' implementation of the IMX series serial ports.
- * TODO:
- * -- implement FIFOs. The real hardware has 32 word transmit
- * and receive FIFOs; we currently use a 1-char buffer
- * -- implement DMA
- * -- implement BAUD-rate and modem lines, for when the backend
- * is a real serial device.
- */
-
-#include "qemu/osdep.h"
-#include "hw/char/imx_serial.h"
-#include "sysemu/sysemu.h"
-#include "sysemu/char.h"
-
-#ifndef DEBUG_IMX_UART
-#define DEBUG_IMX_UART 0
-#endif
-
-#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 = TYPE_IMX_SERIAL,
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_INT32(readbuff, IMXSerialState),
- VMSTATE_UINT32(usr1, IMXSerialState),
- VMSTATE_UINT32(usr2, IMXSerialState),
- VMSTATE_UINT32(ucr1, IMXSerialState),
- VMSTATE_UINT32(uts1, IMXSerialState),
- VMSTATE_UINT32(onems, IMXSerialState),
- VMSTATE_UINT32(ufcr, IMXSerialState),
- VMSTATE_UINT32(ubmr, IMXSerialState),
- VMSTATE_UINT32(ubrc, IMXSerialState),
- VMSTATE_UINT32(ucr3, IMXSerialState),
- VMSTATE_END_OF_LIST()
- },
-};
-
-static void imx_update(IMXSerialState *s)
-{
- uint32_t flags;
-
- flags = (s->usr1 & s->ucr1) & (USR1_TRDY|USR1_RRDY);
- if (s->ucr1 & UCR1_TXMPTYEN) {
- flags |= (s->uts1 & UTS1_TXEMPTY);
- } else {
- flags &= ~USR1_TRDY;
- }
-
- qemu_set_irq(s->irq, !!flags);
-}
-
-static void imx_serial_reset(IMXSerialState *s)
-{
-
- s->usr1 = USR1_TRDY | USR1_RXDS;
- /*
- * Fake attachment of a terminal: assert RTS.
- */
- s->usr1 |= USR1_RTSS;
- s->usr2 = USR2_TXFE | USR2_TXDC | USR2_DCDIN;
- s->uts1 = UTS1_RXEMPTY | UTS1_TXEMPTY;
- s->ucr1 = 0;
- s->ucr2 = UCR2_SRST;
- s->ucr3 = 0x700;
- s->ubmr = 0;
- s->ubrc = 4;
- s->readbuff = URXD_ERR;
-}
-
-static void imx_serial_reset_at_boot(DeviceState *dev)
-{
- IMXSerialState *s = IMX_SERIAL(dev);
-
- imx_serial_reset(s);
-
- /*
- * enable the uart on boot, so messages from the linux decompresser
- * are visible. On real hardware this is done by the boot rom
- * before anything else is loaded.
- */
- s->ucr1 = UCR1_UARTEN;
- s->ucr2 = UCR2_TXEN;
-
-}
-
-static uint64_t imx_serial_read(void *opaque, hwaddr offset,
- unsigned size)
-{
- IMXSerialState *s = (IMXSerialState *)opaque;
- uint32_t c;
-
- DPRINTF("read(offset=0x%" HWADDR_PRIx ")\n", offset);
-
- switch (offset >> 2) {
- case 0x0: /* URXD */
- c = s->readbuff;
- if (!(s->uts1 & UTS1_RXEMPTY)) {
- /* Character is valid */
- c |= URXD_CHARRDY;
- s->usr1 &= ~USR1_RRDY;
- s->usr2 &= ~USR2_RDR;
- s->uts1 |= UTS1_RXEMPTY;
- imx_update(s);
- if (s->chr) {
- qemu_chr_accept_input(s->chr);
- }
- }
- return c;
-
- case 0x20: /* UCR1 */
- return s->ucr1;
-
- case 0x21: /* UCR2 */
- return s->ucr2;
-
- case 0x25: /* USR1 */
- return s->usr1;
-
- case 0x26: /* USR2 */
- return s->usr2;
-
- case 0x2A: /* BRM Modulator */
- return s->ubmr;
-
- case 0x2B: /* Baud Rate Count */
- return s->ubrc;
-
- case 0x2d: /* Test register */
- return s->uts1;
-
- case 0x24: /* UFCR */
- return s->ufcr;
-
- case 0x2c:
- return s->onems;
-
- case 0x22: /* UCR3 */
- return s->ucr3;
-
- case 0x23: /* UCR4 */
- case 0x29: /* BRM Incremental */
- return 0x0; /* TODO */
-
- default:
- 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)
-{
- IMXSerialState *s = (IMXSerialState *)opaque;
- unsigned char ch;
-
- 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 */
- ch = value;
- if (s->ucr2 & UCR2_TXEN) {
- if (s->chr) {
- qemu_chr_fe_write(s->chr, &ch, 1);
- }
- s->usr1 &= ~USR1_TRDY;
- imx_update(s);
- s->usr1 |= USR1_TRDY;
- imx_update(s);
- }
- break;
-
- case 0x20: /* UCR1 */
- s->ucr1 = value & 0xffff;
-
- DPRINTF("write(ucr1=%x)\n", (unsigned int)value);
-
- imx_update(s);
- break;
-
- case 0x21: /* UCR2 */
- /*
- * Only a few bits in control register 2 are implemented as yet.
- * If it's intended to use a real serial device as a back-end, this
- * register will have to be implemented more fully.
- */
- if (!(value & UCR2_SRST)) {
- imx_serial_reset(s);
- imx_update(s);
- value |= UCR2_SRST;
- }
- if (value & UCR2_RXEN) {
- if (!(s->ucr2 & UCR2_RXEN)) {
- if (s->chr) {
- qemu_chr_accept_input(s->chr);
- }
- }
- }
- s->ucr2 = value & 0xffff;
- break;
-
- case 0x25: /* USR1 */
- value &= USR1_AWAKE | USR1_AIRINT | USR1_DTRD | USR1_AGTIM |
- 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
- */
- value &= USR2_ADET | USR2_DTRF | USR2_IDLE | USR2_ACST |
- 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
- */
- case 0x29: /* UBIR */
- s->ubrc = value & 0xffff;
- break;
-
- case 0x2a: /* UBMR */
- s->ubmr = value & 0xffff;
- break;
-
- case 0x2c: /* One ms reg */
- s->onems = value & 0xffff;
- break;
-
- case 0x24: /* FIFO control register */
- s->ufcr = value & 0xffff;
- break;
-
- case 0x22: /* UCR3 */
- s->ucr3 = value & 0xffff;
- break;
-
- case 0x2d: /* UTS1 */
- case 0x23: /* UCR4 */
- qemu_log_mask(LOG_UNIMP, "[%s]%s: Unimplemented reg 0x%"
- HWADDR_PRIx "\n", TYPE_IMX_SERIAL, __func__, offset);
- /* TODO */
- break;
-
- default:
- qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
- HWADDR_PRIx "\n", TYPE_IMX_SERIAL, __func__, offset);
- }
-}
-
-static int imx_can_receive(void *opaque)
-{
- IMXSerialState *s = (IMXSerialState *)opaque;
- return !(s->usr1 & USR1_RRDY);
-}
-
-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;
- s->readbuff = value;
- imx_update(s);
-}
-
-static void imx_receive(void *opaque, const uint8_t *buf, int size)
-{
- imx_put_data(opaque, *buf);
-}
-
-static void imx_event(void *opaque, int event)
-{
- if (event == CHR_EVENT_BREAK) {
- imx_put_data(opaque, URXD_BRK);
- }
-}
-
-
-static const struct MemoryRegionOps imx_serial_ops = {
- .read = imx_serial_read,
- .write = imx_serial_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void imx_serial_realize(DeviceState *dev, Error **errp)
-{
- IMXSerialState *s = IMX_SERIAL(dev);
-
- if (s->chr) {
- qemu_chr_add_handlers(s->chr, imx_can_receive, imx_receive,
- imx_event, s);
- } else {
- DPRINTF("No char dev for uart\n");
- }
-}
-
-static void imx_serial_init(Object *obj)
-{
- 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 imx_serial_properties[] = {
- DEFINE_PROP_CHR("chardev", IMXSerialState, chr),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void imx_serial_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- 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 = imx_serial_properties;
-}
-
-static const TypeInfo imx_serial_info = {
- .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)
-{
- type_register_static(&imx_serial_info);
-}
-
-type_init(imx_serial_register_types)
diff --git a/qemu/hw/char/ipoctal232.c b/qemu/hw/char/ipoctal232.c
deleted file mode 100644
index bc0ae4980..000000000
--- a/qemu/hw/char/ipoctal232.c
+++ /dev/null
@@ -1,604 +0,0 @@
-/*
- * QEMU GE IP-Octal 232 IndustryPack emulation
- *
- * Copyright (C) 2012 Igalia, S.L.
- * Author: Alberto Garcia <agarcia@igalia.com>
- *
- * This code is licensed under the GNU GPL v2 or (at your option) any
- * later version.
- */
-
-#include "qemu/osdep.h"
-#include "hw/ipack/ipack.h"
-#include "qemu/bitops.h"
-#include "sysemu/char.h"
-
-/* #define DEBUG_IPOCTAL */
-
-#ifdef DEBUG_IPOCTAL
-#define DPRINTF2(fmt, ...) \
- do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF2(fmt, ...) do { } while (0)
-#endif
-
-#define DPRINTF(fmt, ...) DPRINTF2("IP-Octal: " fmt, ## __VA_ARGS__)
-
-#define RX_FIFO_SIZE 3
-
-/* The IP-Octal has 8 channels (a-h)
- divided into 4 blocks (A-D) */
-#define N_CHANNELS 8
-#define N_BLOCKS 4
-
-#define REG_MRa 0x01
-#define REG_MRb 0x11
-#define REG_SRa 0x03
-#define REG_SRb 0x13
-#define REG_CSRa 0x03
-#define REG_CSRb 0x13
-#define REG_CRa 0x05
-#define REG_CRb 0x15
-#define REG_RHRa 0x07
-#define REG_RHRb 0x17
-#define REG_THRa 0x07
-#define REG_THRb 0x17
-#define REG_ACR 0x09
-#define REG_ISR 0x0B
-#define REG_IMR 0x0B
-#define REG_OPCR 0x1B
-
-#define CR_ENABLE_RX BIT(0)
-#define CR_DISABLE_RX BIT(1)
-#define CR_ENABLE_TX BIT(2)
-#define CR_DISABLE_TX BIT(3)
-#define CR_CMD(cr) ((cr) >> 4)
-#define CR_NO_OP 0
-#define CR_RESET_MR 1
-#define CR_RESET_RX 2
-#define CR_RESET_TX 3
-#define CR_RESET_ERR 4
-#define CR_RESET_BRKINT 5
-#define CR_START_BRK 6
-#define CR_STOP_BRK 7
-#define CR_ASSERT_RTSN 8
-#define CR_NEGATE_RTSN 9
-#define CR_TIMEOUT_ON 10
-#define CR_TIMEOUT_OFF 12
-
-#define SR_RXRDY BIT(0)
-#define SR_FFULL BIT(1)
-#define SR_TXRDY BIT(2)
-#define SR_TXEMT BIT(3)
-#define SR_OVERRUN BIT(4)
-#define SR_PARITY BIT(5)
-#define SR_FRAMING BIT(6)
-#define SR_BREAK BIT(7)
-
-#define ISR_TXRDYA BIT(0)
-#define ISR_RXRDYA BIT(1)
-#define ISR_BREAKA BIT(2)
-#define ISR_CNTRDY BIT(3)
-#define ISR_TXRDYB BIT(4)
-#define ISR_RXRDYB BIT(5)
-#define ISR_BREAKB BIT(6)
-#define ISR_MPICHG BIT(7)
-#define ISR_TXRDY(CH) (((CH) & 1) ? BIT(4) : BIT(0))
-#define ISR_RXRDY(CH) (((CH) & 1) ? BIT(5) : BIT(1))
-#define ISR_BREAK(CH) (((CH) & 1) ? BIT(6) : BIT(2))
-
-typedef struct IPOctalState IPOctalState;
-typedef struct SCC2698Channel SCC2698Channel;
-typedef struct SCC2698Block SCC2698Block;
-
-struct SCC2698Channel {
- IPOctalState *ipoctal;
- CharDriverState *dev;
- bool rx_enabled;
- uint8_t mr[2];
- uint8_t mr_idx;
- uint8_t sr;
- uint8_t rhr[RX_FIFO_SIZE];
- uint8_t rhr_idx;
- uint8_t rx_pending;
-};
-
-struct SCC2698Block {
- uint8_t imr;
- uint8_t isr;
-};
-
-struct IPOctalState {
- IPackDevice parent_obj;
-
- SCC2698Channel ch[N_CHANNELS];
- SCC2698Block blk[N_BLOCKS];
- uint8_t irq_vector;
-};
-
-#define TYPE_IPOCTAL "ipoctal232"
-
-#define IPOCTAL(obj) \
- OBJECT_CHECK(IPOctalState, (obj), TYPE_IPOCTAL)
-
-static const VMStateDescription vmstate_scc2698_channel = {
- .name = "scc2698_channel",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_BOOL(rx_enabled, SCC2698Channel),
- VMSTATE_UINT8_ARRAY(mr, SCC2698Channel, 2),
- VMSTATE_UINT8(mr_idx, SCC2698Channel),
- VMSTATE_UINT8(sr, SCC2698Channel),
- VMSTATE_UINT8_ARRAY(rhr, SCC2698Channel, RX_FIFO_SIZE),
- VMSTATE_UINT8(rhr_idx, SCC2698Channel),
- VMSTATE_UINT8(rx_pending, SCC2698Channel),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_scc2698_block = {
- .name = "scc2698_block",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT8(imr, SCC2698Block),
- VMSTATE_UINT8(isr, SCC2698Block),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_ipoctal = {
- .name = "ipoctal232",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_IPACK_DEVICE(parent_obj, IPOctalState),
- VMSTATE_STRUCT_ARRAY(ch, IPOctalState, N_CHANNELS, 1,
- vmstate_scc2698_channel, SCC2698Channel),
- VMSTATE_STRUCT_ARRAY(blk, IPOctalState, N_BLOCKS, 1,
- vmstate_scc2698_block, SCC2698Block),
- VMSTATE_UINT8(irq_vector, IPOctalState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-/* data[10] is 0x0C, not 0x0B as the doc says */
-static const uint8_t id_prom_data[] = {
- 0x49, 0x50, 0x41, 0x43, 0xF0, 0x22,
- 0xA1, 0x00, 0x00, 0x00, 0x0C, 0xCC
-};
-
-static void update_irq(IPOctalState *dev, unsigned block)
-{
- IPackDevice *idev = IPACK_DEVICE(dev);
- /* Blocks A and B interrupt on INT0#, C and D on INT1#.
- Thus, to get the status we have to check two blocks. */
- SCC2698Block *blk0 = &dev->blk[block];
- SCC2698Block *blk1 = &dev->blk[block^1];
- unsigned intno = block / 2;
-
- if ((blk0->isr & blk0->imr) || (blk1->isr & blk1->imr)) {
- qemu_irq_raise(idev->irq[intno]);
- } else {
- qemu_irq_lower(idev->irq[intno]);
- }
-}
-
-static void write_cr(IPOctalState *dev, unsigned channel, uint8_t val)
-{
- SCC2698Channel *ch = &dev->ch[channel];
- SCC2698Block *blk = &dev->blk[channel / 2];
-
- DPRINTF("Write CR%c %u: ", channel + 'a', val);
-
- /* The lower 4 bits are used to enable and disable Tx and Rx */
- if (val & CR_ENABLE_RX) {
- DPRINTF2("Rx on, ");
- ch->rx_enabled = true;
- }
- if (val & CR_DISABLE_RX) {
- DPRINTF2("Rx off, ");
- ch->rx_enabled = false;
- }
- if (val & CR_ENABLE_TX) {
- DPRINTF2("Tx on, ");
- ch->sr |= SR_TXRDY | SR_TXEMT;
- blk->isr |= ISR_TXRDY(channel);
- }
- if (val & CR_DISABLE_TX) {
- DPRINTF2("Tx off, ");
- ch->sr &= ~(SR_TXRDY | SR_TXEMT);
- blk->isr &= ~ISR_TXRDY(channel);
- }
-
- DPRINTF2("cmd: ");
-
- /* The rest of the bits implement different commands */
- switch (CR_CMD(val)) {
- case CR_NO_OP:
- DPRINTF2("none");
- break;
- case CR_RESET_MR:
- DPRINTF2("reset MR");
- ch->mr_idx = 0;
- break;
- case CR_RESET_RX:
- DPRINTF2("reset Rx");
- ch->rx_enabled = false;
- ch->rx_pending = 0;
- ch->sr &= ~SR_RXRDY;
- blk->isr &= ~ISR_RXRDY(channel);
- break;
- case CR_RESET_TX:
- DPRINTF2("reset Tx");
- ch->sr &= ~(SR_TXRDY | SR_TXEMT);
- blk->isr &= ~ISR_TXRDY(channel);
- break;
- case CR_RESET_ERR:
- DPRINTF2("reset err");
- ch->sr &= ~(SR_OVERRUN | SR_PARITY | SR_FRAMING | SR_BREAK);
- break;
- case CR_RESET_BRKINT:
- DPRINTF2("reset brk ch int");
- blk->isr &= ~(ISR_BREAKA | ISR_BREAKB);
- break;
- default:
- DPRINTF2("unsupported 0x%x", CR_CMD(val));
- }
-
- DPRINTF2("\n");
-}
-
-static uint16_t io_read(IPackDevice *ip, uint8_t addr)
-{
- IPOctalState *dev = IPOCTAL(ip);
- uint16_t ret = 0;
- /* addr[7:6]: block (A-D)
- addr[7:5]: channel (a-h)
- addr[5:0]: register */
- unsigned block = addr >> 5;
- unsigned channel = addr >> 4;
- /* Big endian, accessed using 8-bit bytes at odd locations */
- unsigned offset = (addr & 0x1F) ^ 1;
- SCC2698Channel *ch = &dev->ch[channel];
- SCC2698Block *blk = &dev->blk[block];
- uint8_t old_isr = blk->isr;
-
- switch (offset) {
-
- case REG_MRa:
- case REG_MRb:
- ret = ch->mr[ch->mr_idx];
- DPRINTF("Read MR%u%c: 0x%x\n", ch->mr_idx + 1, channel + 'a', ret);
- ch->mr_idx = 1;
- break;
-
- case REG_SRa:
- case REG_SRb:
- ret = ch->sr;
- DPRINTF("Read SR%c: 0x%x\n", channel + 'a', ret);
- break;
-
- case REG_RHRa:
- case REG_RHRb:
- ret = ch->rhr[ch->rhr_idx];
- if (ch->rx_pending > 0) {
- ch->rx_pending--;
- if (ch->rx_pending == 0) {
- ch->sr &= ~SR_RXRDY;
- blk->isr &= ~ISR_RXRDY(channel);
- if (ch->dev) {
- qemu_chr_accept_input(ch->dev);
- }
- } else {
- ch->rhr_idx = (ch->rhr_idx + 1) % RX_FIFO_SIZE;
- }
- if (ch->sr & SR_BREAK) {
- ch->sr &= ~SR_BREAK;
- blk->isr |= ISR_BREAK(channel);
- }
- }
- DPRINTF("Read RHR%c (0x%x)\n", channel + 'a', ret);
- break;
-
- case REG_ISR:
- ret = blk->isr;
- DPRINTF("Read ISR%c: 0x%x\n", block + 'A', ret);
- break;
-
- default:
- DPRINTF("Read unknown/unsupported register 0x%02x\n", offset);
- }
-
- if (old_isr != blk->isr) {
- update_irq(dev, block);
- }
-
- return ret;
-}
-
-static void io_write(IPackDevice *ip, uint8_t addr, uint16_t val)
-{
- IPOctalState *dev = IPOCTAL(ip);
- unsigned reg = val & 0xFF;
- /* addr[7:6]: block (A-D)
- addr[7:5]: channel (a-h)
- addr[5:0]: register */
- unsigned block = addr >> 5;
- unsigned channel = addr >> 4;
- /* Big endian, accessed using 8-bit bytes at odd locations */
- unsigned offset = (addr & 0x1F) ^ 1;
- SCC2698Channel *ch = &dev->ch[channel];
- SCC2698Block *blk = &dev->blk[block];
- uint8_t old_isr = blk->isr;
- uint8_t old_imr = blk->imr;
-
- switch (offset) {
-
- case REG_MRa:
- case REG_MRb:
- ch->mr[ch->mr_idx] = reg;
- DPRINTF("Write MR%u%c 0x%x\n", ch->mr_idx + 1, channel + 'a', reg);
- ch->mr_idx = 1;
- break;
-
- /* Not implemented */
- case REG_CSRa:
- case REG_CSRb:
- DPRINTF("Write CSR%c: 0x%x\n", channel + 'a', reg);
- break;
-
- case REG_CRa:
- case REG_CRb:
- write_cr(dev, channel, reg);
- break;
-
- case REG_THRa:
- case REG_THRb:
- if (ch->sr & SR_TXRDY) {
- DPRINTF("Write THR%c (0x%x)\n", channel + 'a', reg);
- if (ch->dev) {
- uint8_t thr = reg;
- qemu_chr_fe_write(ch->dev, &thr, 1);
- }
- } else {
- DPRINTF("Write THR%c (0x%x), Tx disabled\n", channel + 'a', reg);
- }
- break;
-
- /* Not implemented */
- case REG_ACR:
- DPRINTF("Write ACR%c 0x%x\n", block + 'A', val);
- break;
-
- case REG_IMR:
- DPRINTF("Write IMR%c 0x%x\n", block + 'A', val);
- blk->imr = reg;
- break;
-
- /* Not implemented */
- case REG_OPCR:
- DPRINTF("Write OPCR%c 0x%x\n", block + 'A', val);
- break;
-
- default:
- DPRINTF("Write unknown/unsupported register 0x%02x %u\n", offset, val);
- }
-
- if (old_isr != blk->isr || old_imr != blk->imr) {
- update_irq(dev, block);
- }
-}
-
-static uint16_t id_read(IPackDevice *ip, uint8_t addr)
-{
- uint16_t ret = 0;
- unsigned pos = addr / 2; /* The ID PROM data is stored every other byte */
-
- if (pos < ARRAY_SIZE(id_prom_data)) {
- ret = id_prom_data[pos];
- } else {
- DPRINTF("Attempt to read unavailable PROM data at 0x%x\n", addr);
- }
-
- return ret;
-}
-
-static void id_write(IPackDevice *ip, uint8_t addr, uint16_t val)
-{
- IPOctalState *dev = IPOCTAL(ip);
- if (addr == 1) {
- DPRINTF("Write IRQ vector: %u\n", (unsigned) val);
- dev->irq_vector = val; /* Undocumented, but the hw works like that */
- } else {
- DPRINTF("Attempt to write 0x%x to 0x%x\n", val, addr);
- }
-}
-
-static uint16_t int_read(IPackDevice *ip, uint8_t addr)
-{
- IPOctalState *dev = IPOCTAL(ip);
- /* Read address 0 to ACK INT0# and address 2 to ACK INT1# */
- if (addr != 0 && addr != 2) {
- DPRINTF("Attempt to read from 0x%x\n", addr);
- return 0;
- } else {
- /* Update interrupts if necessary */
- update_irq(dev, addr);
- return dev->irq_vector;
- }
-}
-
-static void int_write(IPackDevice *ip, uint8_t addr, uint16_t val)
-{
- DPRINTF("Attempt to write 0x%x to 0x%x\n", val, addr);
-}
-
-static uint16_t mem_read16(IPackDevice *ip, uint32_t addr)
-{
- DPRINTF("Attempt to read from 0x%x\n", addr);
- return 0;
-}
-
-static void mem_write16(IPackDevice *ip, uint32_t addr, uint16_t val)
-{
- DPRINTF("Attempt to write 0x%x to 0x%x\n", val, addr);
-}
-
-static uint8_t mem_read8(IPackDevice *ip, uint32_t addr)
-{
- DPRINTF("Attempt to read from 0x%x\n", addr);
- return 0;
-}
-
-static void mem_write8(IPackDevice *ip, uint32_t addr, uint8_t val)
-{
- IPOctalState *dev = IPOCTAL(ip);
- if (addr == 1) {
- DPRINTF("Write IRQ vector: %u\n", (unsigned) val);
- dev->irq_vector = val;
- } else {
- DPRINTF("Attempt to write 0x%x to 0x%x\n", val, addr);
- }
-}
-
-static int hostdev_can_receive(void *opaque)
-{
- SCC2698Channel *ch = opaque;
- int available_bytes = RX_FIFO_SIZE - ch->rx_pending;
- return ch->rx_enabled ? available_bytes : 0;
-}
-
-static void hostdev_receive(void *opaque, const uint8_t *buf, int size)
-{
- SCC2698Channel *ch = opaque;
- IPOctalState *dev = ch->ipoctal;
- unsigned pos = ch->rhr_idx + ch->rx_pending;
- int i;
-
- assert(size + ch->rx_pending <= RX_FIFO_SIZE);
-
- /* Copy data to the RxFIFO */
- for (i = 0; i < size; i++) {
- pos %= RX_FIFO_SIZE;
- ch->rhr[pos++] = buf[i];
- }
-
- ch->rx_pending += size;
-
- /* If the RxFIFO was empty raise an interrupt */
- if (!(ch->sr & SR_RXRDY)) {
- unsigned block, channel = 0;
- /* Find channel number to update the ISR register */
- while (&dev->ch[channel] != ch) {
- channel++;
- }
- block = channel / 2;
- dev->blk[block].isr |= ISR_RXRDY(channel);
- ch->sr |= SR_RXRDY;
- update_irq(dev, block);
- }
-}
-
-static void hostdev_event(void *opaque, int event)
-{
- SCC2698Channel *ch = opaque;
- switch (event) {
- case CHR_EVENT_OPENED:
- DPRINTF("Device %s opened\n", ch->dev->label);
- break;
- case CHR_EVENT_BREAK: {
- uint8_t zero = 0;
- DPRINTF("Device %s received break\n", ch->dev->label);
-
- if (!(ch->sr & SR_BREAK)) {
- IPOctalState *dev = ch->ipoctal;
- unsigned block, channel = 0;
-
- while (&dev->ch[channel] != ch) {
- channel++;
- }
- block = channel / 2;
-
- ch->sr |= SR_BREAK;
- dev->blk[block].isr |= ISR_BREAK(channel);
- }
-
- /* Put a zero character in the buffer */
- hostdev_receive(ch, &zero, 1);
- }
- break;
- default:
- DPRINTF("Device %s received event %d\n", ch->dev->label, event);
- }
-}
-
-static void ipoctal_realize(DeviceState *dev, Error **errp)
-{
- IPOctalState *s = IPOCTAL(dev);
- unsigned i;
-
- for (i = 0; i < N_CHANNELS; i++) {
- SCC2698Channel *ch = &s->ch[i];
- ch->ipoctal = s;
-
- /* Redirect IP-Octal channels to host character devices */
- if (ch->dev) {
- qemu_chr_add_handlers(ch->dev, hostdev_can_receive,
- hostdev_receive, hostdev_event, ch);
- DPRINTF("Redirecting channel %u to %s\n", i, ch->dev->label);
- } else {
- DPRINTF("Could not redirect channel %u, no chardev set\n", i);
- }
- }
-}
-
-static Property ipoctal_properties[] = {
- DEFINE_PROP_CHR("chardev0", IPOctalState, ch[0].dev),
- DEFINE_PROP_CHR("chardev1", IPOctalState, ch[1].dev),
- DEFINE_PROP_CHR("chardev2", IPOctalState, ch[2].dev),
- DEFINE_PROP_CHR("chardev3", IPOctalState, ch[3].dev),
- DEFINE_PROP_CHR("chardev4", IPOctalState, ch[4].dev),
- DEFINE_PROP_CHR("chardev5", IPOctalState, ch[5].dev),
- DEFINE_PROP_CHR("chardev6", IPOctalState, ch[6].dev),
- DEFINE_PROP_CHR("chardev7", IPOctalState, ch[7].dev),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void ipoctal_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- IPackDeviceClass *ic = IPACK_DEVICE_CLASS(klass);
-
- ic->realize = ipoctal_realize;
- ic->io_read = io_read;
- ic->io_write = io_write;
- ic->id_read = id_read;
- ic->id_write = id_write;
- ic->int_read = int_read;
- ic->int_write = int_write;
- ic->mem_read16 = mem_read16;
- ic->mem_write16 = mem_write16;
- ic->mem_read8 = mem_read8;
- ic->mem_write8 = mem_write8;
-
- set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
- dc->desc = "GE IP-Octal 232 8-channel RS-232 IndustryPack";
- dc->props = ipoctal_properties;
- dc->vmsd = &vmstate_ipoctal;
-}
-
-static const TypeInfo ipoctal_info = {
- .name = TYPE_IPOCTAL,
- .parent = TYPE_IPACK_DEVICE,
- .instance_size = sizeof(IPOctalState),
- .class_init = ipoctal_class_init,
-};
-
-static void ipoctal_register_types(void)
-{
- type_register_static(&ipoctal_info);
-}
-
-type_init(ipoctal_register_types)
diff --git a/qemu/hw/char/lm32_juart.c b/qemu/hw/char/lm32_juart.c
deleted file mode 100644
index 5bf8acfe8..000000000
--- a/qemu/hw/char/lm32_juart.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * LatticeMico32 JTAG UART model.
- *
- * Copyright (c) 2010 Michael Walle <michael@walle.cc>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * 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"
-#include "sysemu/char.h"
-
-#include "hw/char/lm32_juart.h"
-
-enum {
- LM32_JUART_MIN_SAVE_VERSION = 0,
- LM32_JUART_CURRENT_SAVE_VERSION = 0,
- LM32_JUART_MAX_SAVE_VERSION = 0,
-};
-
-enum {
- JTX_FULL = (1<<8),
-};
-
-enum {
- JRX_FULL = (1<<8),
-};
-
-#define LM32_JUART(obj) OBJECT_CHECK(LM32JuartState, (obj), TYPE_LM32_JUART)
-
-struct LM32JuartState {
- SysBusDevice parent_obj;
-
- CharDriverState *chr;
-
- uint32_t jtx;
- uint32_t jrx;
-};
-typedef struct LM32JuartState LM32JuartState;
-
-uint32_t lm32_juart_get_jtx(DeviceState *d)
-{
- LM32JuartState *s = LM32_JUART(d);
-
- trace_lm32_juart_get_jtx(s->jtx);
- return s->jtx;
-}
-
-uint32_t lm32_juart_get_jrx(DeviceState *d)
-{
- LM32JuartState *s = LM32_JUART(d);
-
- trace_lm32_juart_get_jrx(s->jrx);
- return s->jrx;
-}
-
-void lm32_juart_set_jtx(DeviceState *d, uint32_t jtx)
-{
- LM32JuartState *s = LM32_JUART(d);
- unsigned char ch = jtx & 0xff;
-
- trace_lm32_juart_set_jtx(s->jtx);
-
- s->jtx = jtx;
- if (s->chr) {
- qemu_chr_fe_write_all(s->chr, &ch, 1);
- }
-}
-
-void lm32_juart_set_jrx(DeviceState *d, uint32_t jtx)
-{
- LM32JuartState *s = LM32_JUART(d);
-
- trace_lm32_juart_set_jrx(s->jrx);
- s->jrx &= ~JRX_FULL;
-}
-
-static void juart_rx(void *opaque, const uint8_t *buf, int size)
-{
- LM32JuartState *s = opaque;
-
- s->jrx = *buf | JRX_FULL;
-}
-
-static int juart_can_rx(void *opaque)
-{
- LM32JuartState *s = opaque;
-
- return !(s->jrx & JRX_FULL);
-}
-
-static void juart_event(void *opaque, int event)
-{
-}
-
-static void juart_reset(DeviceState *d)
-{
- LM32JuartState *s = LM32_JUART(d);
-
- s->jtx = 0;
- s->jrx = 0;
-}
-
-static int lm32_juart_init(SysBusDevice *dev)
-{
- 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 = {
- .name = "lm32-juart",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(jtx, LM32JuartState),
- VMSTATE_UINT32(jrx, LM32JuartState),
- VMSTATE_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;
-}
-
-static const TypeInfo lm32_juart_info = {
- .name = TYPE_LM32_JUART,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(LM32JuartState),
- .class_init = lm32_juart_class_init,
-};
-
-static void lm32_juart_register_types(void)
-{
- type_register_static(&lm32_juart_info);
-}
-
-type_init(lm32_juart_register_types)
diff --git a/qemu/hw/char/lm32_uart.c b/qemu/hw/char/lm32_uart.c
deleted file mode 100644
index 036813d0f..000000000
--- a/qemu/hw/char/lm32_uart.c
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * QEMU model of the LatticeMico32 UART block.
- *
- * Copyright (c) 2010 Michael Walle <michael@walle.cc>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- *
- *
- * Specification available at:
- * http://www.latticesemi.com/documents/mico32uart.pdf
- */
-
-
-#include "qemu/osdep.h"
-#include "hw/hw.h"
-#include "hw/sysbus.h"
-#include "trace.h"
-#include "sysemu/char.h"
-#include "qemu/error-report.h"
-
-enum {
- R_RXTX = 0,
- R_IER,
- R_IIR,
- R_LCR,
- R_MCR,
- R_LSR,
- R_MSR,
- R_DIV,
- R_MAX
-};
-
-enum {
- IER_RBRI = (1<<0),
- IER_THRI = (1<<1),
- IER_RLSI = (1<<2),
- IER_MSI = (1<<3),
-};
-
-enum {
- IIR_STAT = (1<<0),
- IIR_ID0 = (1<<1),
- IIR_ID1 = (1<<2),
-};
-
-enum {
- LCR_WLS0 = (1<<0),
- LCR_WLS1 = (1<<1),
- LCR_STB = (1<<2),
- LCR_PEN = (1<<3),
- LCR_EPS = (1<<4),
- LCR_SP = (1<<5),
- LCR_SB = (1<<6),
-};
-
-enum {
- MCR_DTR = (1<<0),
- MCR_RTS = (1<<1),
-};
-
-enum {
- LSR_DR = (1<<0),
- LSR_OE = (1<<1),
- LSR_PE = (1<<2),
- LSR_FE = (1<<3),
- LSR_BI = (1<<4),
- LSR_THRE = (1<<5),
- LSR_TEMT = (1<<6),
-};
-
-enum {
- MSR_DCTS = (1<<0),
- MSR_DDSR = (1<<1),
- MSR_TERI = (1<<2),
- MSR_DDCD = (1<<3),
- MSR_CTS = (1<<4),
- MSR_DSR = (1<<5),
- MSR_RI = (1<<6),
- MSR_DCD = (1<<7),
-};
-
-#define TYPE_LM32_UART "lm32-uart"
-#define LM32_UART(obj) OBJECT_CHECK(LM32UartState, (obj), TYPE_LM32_UART)
-
-struct LM32UartState {
- SysBusDevice parent_obj;
-
- MemoryRegion iomem;
- CharDriverState *chr;
- qemu_irq irq;
-
- uint32_t regs[R_MAX];
-};
-typedef struct LM32UartState LM32UartState;
-
-static void uart_update_irq(LM32UartState *s)
-{
- unsigned int irq;
-
- if ((s->regs[R_LSR] & (LSR_OE | LSR_PE | LSR_FE | LSR_BI))
- && (s->regs[R_IER] & IER_RLSI)) {
- irq = 1;
- s->regs[R_IIR] = IIR_ID1 | IIR_ID0;
- } else if ((s->regs[R_LSR] & LSR_DR) && (s->regs[R_IER] & IER_RBRI)) {
- irq = 1;
- s->regs[R_IIR] = IIR_ID1;
- } else if ((s->regs[R_LSR] & LSR_THRE) && (s->regs[R_IER] & IER_THRI)) {
- irq = 1;
- s->regs[R_IIR] = IIR_ID0;
- } else if ((s->regs[R_MSR] & 0x0f) && (s->regs[R_IER] & IER_MSI)) {
- irq = 1;
- s->regs[R_IIR] = 0;
- } else {
- irq = 0;
- s->regs[R_IIR] = IIR_STAT;
- }
-
- trace_lm32_uart_irq_state(irq);
- qemu_set_irq(s->irq, irq);
-}
-
-static uint64_t uart_read(void *opaque, hwaddr addr,
- unsigned size)
-{
- LM32UartState *s = opaque;
- uint32_t r = 0;
-
- addr >>= 2;
- switch (addr) {
- case R_RXTX:
- r = s->regs[R_RXTX];
- s->regs[R_LSR] &= ~LSR_DR;
- uart_update_irq(s);
- qemu_chr_accept_input(s->chr);
- break;
- case R_IIR:
- case R_LSR:
- case R_MSR:
- r = s->regs[addr];
- break;
- case R_IER:
- case R_LCR:
- case R_MCR:
- case R_DIV:
- error_report("lm32_uart: read access to write only register 0x"
- TARGET_FMT_plx, addr << 2);
- break;
- default:
- error_report("lm32_uart: read access to unknown register 0x"
- TARGET_FMT_plx, addr << 2);
- break;
- }
-
- trace_lm32_uart_memory_read(addr << 2, r);
- return r;
-}
-
-static void uart_write(void *opaque, hwaddr addr,
- uint64_t value, unsigned size)
-{
- LM32UartState *s = opaque;
- unsigned char ch = value;
-
- trace_lm32_uart_memory_write(addr, value);
-
- addr >>= 2;
- switch (addr) {
- case R_RXTX:
- if (s->chr) {
- qemu_chr_fe_write_all(s->chr, &ch, 1);
- }
- break;
- case R_IER:
- case R_LCR:
- case R_MCR:
- case R_DIV:
- s->regs[addr] = value;
- break;
- case R_IIR:
- case R_LSR:
- case R_MSR:
- error_report("lm32_uart: write access to read only register 0x"
- TARGET_FMT_plx, addr << 2);
- break;
- default:
- error_report("lm32_uart: write access to unknown register 0x"
- TARGET_FMT_plx, addr << 2);
- break;
- }
- uart_update_irq(s);
-}
-
-static const MemoryRegionOps uart_ops = {
- .read = uart_read,
- .write = uart_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
- .valid = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
-};
-
-static void uart_rx(void *opaque, const uint8_t *buf, int size)
-{
- LM32UartState *s = opaque;
-
- if (s->regs[R_LSR] & LSR_DR) {
- s->regs[R_LSR] |= LSR_OE;
- }
-
- s->regs[R_LSR] |= LSR_DR;
- s->regs[R_RXTX] = *buf;
-
- uart_update_irq(s);
-}
-
-static int uart_can_rx(void *opaque)
-{
- LM32UartState *s = opaque;
-
- return !(s->regs[R_LSR] & LSR_DR);
-}
-
-static void uart_event(void *opaque, int event)
-{
-}
-
-static void uart_reset(DeviceState *d)
-{
- LM32UartState *s = LM32_UART(d);
- int i;
-
- for (i = 0; i < R_MAX; i++) {
- s->regs[i] = 0;
- }
-
- /* defaults */
- s->regs[R_LSR] = LSR_THRE | LSR_TEMT;
-}
-
-static int lm32_uart_init(SysBusDevice *dev)
-{
- LM32UartState *s = LM32_UART(dev);
-
- sysbus_init_irq(dev, &s->irq);
-
- memory_region_init_io(&s->iomem, OBJECT(s), &uart_ops, s,
- "uart", R_MAX * 4);
- sysbus_init_mmio(dev, &s->iomem);
-
- /* 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 = {
- .name = "lm32-uart",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32_ARRAY(regs, LM32UartState, R_MAX),
- VMSTATE_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;
-}
-
-static const TypeInfo lm32_uart_info = {
- .name = TYPE_LM32_UART,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(LM32UartState),
- .class_init = lm32_uart_class_init,
-};
-
-static void lm32_uart_register_types(void)
-{
- type_register_static(&lm32_uart_info);
-}
-
-type_init(lm32_uart_register_types)
diff --git a/qemu/hw/char/mcf_uart.c b/qemu/hw/char/mcf_uart.c
deleted file mode 100644
index 3c0438fd7..000000000
--- a/qemu/hw/char/mcf_uart.c
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * ColdFire UART emulation.
- *
- * Copyright (c) 2007 CodeSourcery.
- *
- * This code is licensed under the GPL
- */
-#include "qemu/osdep.h"
-#include "hw/hw.h"
-#include "hw/m68k/mcf.h"
-#include "sysemu/char.h"
-#include "exec/address-spaces.h"
-
-typedef struct {
- MemoryRegion iomem;
- uint8_t mr[2];
- uint8_t sr;
- uint8_t isr;
- uint8_t imr;
- uint8_t bg1;
- uint8_t bg2;
- uint8_t fifo[4];
- uint8_t tb;
- int current_mr;
- int fifo_len;
- int tx_enabled;
- int rx_enabled;
- qemu_irq irq;
- CharDriverState *chr;
-} mcf_uart_state;
-
-/* UART Status Register bits. */
-#define MCF_UART_RxRDY 0x01
-#define MCF_UART_FFULL 0x02
-#define MCF_UART_TxRDY 0x04
-#define MCF_UART_TxEMP 0x08
-#define MCF_UART_OE 0x10
-#define MCF_UART_PE 0x20
-#define MCF_UART_FE 0x40
-#define MCF_UART_RB 0x80
-
-/* Interrupt flags. */
-#define MCF_UART_TxINT 0x01
-#define MCF_UART_RxINT 0x02
-#define MCF_UART_DBINT 0x04
-#define MCF_UART_COSINT 0x80
-
-/* UMR1 flags. */
-#define MCF_UART_BC0 0x01
-#define MCF_UART_BC1 0x02
-#define MCF_UART_PT 0x04
-#define MCF_UART_PM0 0x08
-#define MCF_UART_PM1 0x10
-#define MCF_UART_ERR 0x20
-#define MCF_UART_RxIRQ 0x40
-#define MCF_UART_RxRTS 0x80
-
-static void mcf_uart_update(mcf_uart_state *s)
-{
- s->isr &= ~(MCF_UART_TxINT | MCF_UART_RxINT);
- if (s->sr & MCF_UART_TxRDY)
- s->isr |= MCF_UART_TxINT;
- if ((s->sr & ((s->mr[0] & MCF_UART_RxIRQ)
- ? MCF_UART_FFULL : MCF_UART_RxRDY)) != 0)
- s->isr |= MCF_UART_RxINT;
-
- qemu_set_irq(s->irq, (s->isr & s->imr) != 0);
-}
-
-uint64_t mcf_uart_read(void *opaque, hwaddr addr,
- unsigned size)
-{
- mcf_uart_state *s = (mcf_uart_state *)opaque;
- switch (addr & 0x3f) {
- case 0x00:
- return s->mr[s->current_mr];
- case 0x04:
- return s->sr;
- case 0x0c:
- {
- uint8_t val;
- int i;
-
- if (s->fifo_len == 0)
- return 0;
-
- val = s->fifo[0];
- s->fifo_len--;
- for (i = 0; i < s->fifo_len; i++)
- s->fifo[i] = s->fifo[i + 1];
- s->sr &= ~MCF_UART_FFULL;
- if (s->fifo_len == 0)
- s->sr &= ~MCF_UART_RxRDY;
- mcf_uart_update(s);
- qemu_chr_accept_input(s->chr);
- return val;
- }
- case 0x10:
- /* TODO: Implement IPCR. */
- return 0;
- case 0x14:
- return s->isr;
- case 0x18:
- return s->bg1;
- case 0x1c:
- return s->bg2;
- default:
- return 0;
- }
-}
-
-/* Update TxRDY flag and set data if present and enabled. */
-static void mcf_uart_do_tx(mcf_uart_state *s)
-{
- if (s->tx_enabled && (s->sr & MCF_UART_TxEMP) == 0) {
- if (s->chr)
- qemu_chr_fe_write(s->chr, (unsigned char *)&s->tb, 1);
- s->sr |= MCF_UART_TxEMP;
- }
- if (s->tx_enabled) {
- s->sr |= MCF_UART_TxRDY;
- } else {
- s->sr &= ~MCF_UART_TxRDY;
- }
-}
-
-static void mcf_do_command(mcf_uart_state *s, uint8_t cmd)
-{
- /* Misc command. */
- switch ((cmd >> 4) & 7) {
- case 0: /* No-op. */
- break;
- case 1: /* Reset mode register pointer. */
- s->current_mr = 0;
- break;
- case 2: /* Reset receiver. */
- s->rx_enabled = 0;
- s->fifo_len = 0;
- s->sr &= ~(MCF_UART_RxRDY | MCF_UART_FFULL);
- break;
- case 3: /* Reset transmitter. */
- s->tx_enabled = 0;
- s->sr |= MCF_UART_TxEMP;
- s->sr &= ~MCF_UART_TxRDY;
- break;
- case 4: /* Reset error status. */
- break;
- case 5: /* Reset break-change interrupt. */
- s->isr &= ~MCF_UART_DBINT;
- break;
- case 6: /* Start break. */
- case 7: /* Stop break. */
- break;
- }
-
- /* Transmitter command. */
- switch ((cmd >> 2) & 3) {
- case 0: /* No-op. */
- break;
- case 1: /* Enable. */
- s->tx_enabled = 1;
- mcf_uart_do_tx(s);
- break;
- case 2: /* Disable. */
- s->tx_enabled = 0;
- mcf_uart_do_tx(s);
- break;
- case 3: /* Reserved. */
- fprintf(stderr, "mcf_uart: Bad TX command\n");
- break;
- }
-
- /* Receiver command. */
- switch (cmd & 3) {
- case 0: /* No-op. */
- break;
- case 1: /* Enable. */
- s->rx_enabled = 1;
- break;
- case 2:
- s->rx_enabled = 0;
- break;
- case 3: /* Reserved. */
- fprintf(stderr, "mcf_uart: Bad RX command\n");
- break;
- }
-}
-
-void mcf_uart_write(void *opaque, hwaddr addr,
- uint64_t val, unsigned size)
-{
- mcf_uart_state *s = (mcf_uart_state *)opaque;
- switch (addr & 0x3f) {
- case 0x00:
- s->mr[s->current_mr] = val;
- s->current_mr = 1;
- break;
- case 0x04:
- /* CSR is ignored. */
- break;
- case 0x08: /* Command Register. */
- mcf_do_command(s, val);
- break;
- case 0x0c: /* Transmit Buffer. */
- s->sr &= ~MCF_UART_TxEMP;
- s->tb = val;
- mcf_uart_do_tx(s);
- break;
- case 0x10:
- /* ACR is ignored. */
- break;
- case 0x14:
- s->imr = val;
- break;
- default:
- break;
- }
- mcf_uart_update(s);
-}
-
-static void mcf_uart_reset(mcf_uart_state *s)
-{
- s->fifo_len = 0;
- s->mr[0] = 0;
- s->mr[1] = 0;
- s->sr = MCF_UART_TxEMP;
- s->tx_enabled = 0;
- s->rx_enabled = 0;
- s->isr = 0;
- s->imr = 0;
-}
-
-static void mcf_uart_push_byte(mcf_uart_state *s, uint8_t data)
-{
- /* Break events overwrite the last byte if the fifo is full. */
- if (s->fifo_len == 4)
- s->fifo_len--;
-
- s->fifo[s->fifo_len] = data;
- s->fifo_len++;
- s->sr |= MCF_UART_RxRDY;
- if (s->fifo_len == 4)
- s->sr |= MCF_UART_FFULL;
-
- mcf_uart_update(s);
-}
-
-static void mcf_uart_event(void *opaque, int event)
-{
- mcf_uart_state *s = (mcf_uart_state *)opaque;
-
- switch (event) {
- case CHR_EVENT_BREAK:
- s->isr |= MCF_UART_DBINT;
- mcf_uart_push_byte(s, 0);
- break;
- default:
- break;
- }
-}
-
-static int mcf_uart_can_receive(void *opaque)
-{
- mcf_uart_state *s = (mcf_uart_state *)opaque;
-
- return s->rx_enabled && (s->sr & MCF_UART_FFULL) == 0;
-}
-
-static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size)
-{
- mcf_uart_state *s = (mcf_uart_state *)opaque;
-
- mcf_uart_push_byte(s, buf[0]);
-}
-
-void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
-{
- mcf_uart_state *s;
-
- s = g_malloc0(sizeof(mcf_uart_state));
- s->chr = chr;
- s->irq = irq;
- if (chr) {
- qemu_chr_fe_claim_no_fail(chr);
- qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive,
- mcf_uart_event, s);
- }
- mcf_uart_reset(s);
- return s;
-}
-
-static const MemoryRegionOps mcf_uart_ops = {
- .read = mcf_uart_read,
- .write = mcf_uart_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-void mcf_uart_mm_init(MemoryRegion *sysmem,
- hwaddr base,
- qemu_irq irq,
- CharDriverState *chr)
-{
- mcf_uart_state *s;
-
- s = mcf_uart_init(irq, chr);
- memory_region_init_io(&s->iomem, NULL, &mcf_uart_ops, s, "uart", 0x40);
- memory_region_add_subregion(sysmem, base, &s->iomem);
-}
diff --git a/qemu/hw/char/milkymist-uart.c b/qemu/hw/char/milkymist-uart.c
deleted file mode 100644
index 03b36b223..000000000
--- a/qemu/hw/char/milkymist-uart.c
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * QEMU model of the Milkymist UART block.
- *
- * Copyright (c) 2010 Michael Walle <michael@walle.cc>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- *
- *
- * Specification available at:
- * http://www.milkymist.org/socdoc/uart.pdf
- */
-
-#include "qemu/osdep.h"
-#include "hw/hw.h"
-#include "hw/sysbus.h"
-#include "trace.h"
-#include "sysemu/char.h"
-#include "qemu/error-report.h"
-
-enum {
- R_RXTX = 0,
- R_DIV,
- R_STAT,
- R_CTRL,
- R_DBG,
- R_MAX
-};
-
-enum {
- STAT_THRE = (1<<0),
- STAT_RX_EVT = (1<<1),
- STAT_TX_EVT = (1<<2),
-};
-
-enum {
- CTRL_RX_IRQ_EN = (1<<0),
- CTRL_TX_IRQ_EN = (1<<1),
- CTRL_THRU_EN = (1<<2),
-};
-
-enum {
- DBG_BREAK_EN = (1<<0),
-};
-
-#define TYPE_MILKYMIST_UART "milkymist-uart"
-#define MILKYMIST_UART(obj) \
- OBJECT_CHECK(MilkymistUartState, (obj), TYPE_MILKYMIST_UART)
-
-struct MilkymistUartState {
- SysBusDevice parent_obj;
-
- MemoryRegion regs_region;
- CharDriverState *chr;
- qemu_irq irq;
-
- uint32_t regs[R_MAX];
-};
-typedef struct MilkymistUartState MilkymistUartState;
-
-static void uart_update_irq(MilkymistUartState *s)
-{
- int rx_event = s->regs[R_STAT] & STAT_RX_EVT;
- int tx_event = s->regs[R_STAT] & STAT_TX_EVT;
- int rx_irq_en = s->regs[R_CTRL] & CTRL_RX_IRQ_EN;
- int tx_irq_en = s->regs[R_CTRL] & CTRL_TX_IRQ_EN;
-
- if ((rx_irq_en && rx_event) || (tx_irq_en && tx_event)) {
- trace_milkymist_uart_raise_irq();
- qemu_irq_raise(s->irq);
- } else {
- trace_milkymist_uart_lower_irq();
- qemu_irq_lower(s->irq);
- }
-}
-
-static uint64_t uart_read(void *opaque, hwaddr addr,
- unsigned size)
-{
- MilkymistUartState *s = opaque;
- uint32_t r = 0;
-
- addr >>= 2;
- switch (addr) {
- case R_RXTX:
- r = s->regs[addr];
- break;
- case R_DIV:
- case R_STAT:
- case R_CTRL:
- case R_DBG:
- r = s->regs[addr];
- break;
-
- default:
- error_report("milkymist_uart: read access to unknown register 0x"
- TARGET_FMT_plx, addr << 2);
- break;
- }
-
- trace_milkymist_uart_memory_read(addr << 2, r);
-
- return r;
-}
-
-static void uart_write(void *opaque, hwaddr addr, uint64_t value,
- unsigned size)
-{
- MilkymistUartState *s = opaque;
- unsigned char ch = value;
-
- trace_milkymist_uart_memory_write(addr, value);
-
- addr >>= 2;
- switch (addr) {
- case R_RXTX:
- if (s->chr) {
- qemu_chr_fe_write_all(s->chr, &ch, 1);
- }
- s->regs[R_STAT] |= STAT_TX_EVT;
- break;
- case R_DIV:
- case R_CTRL:
- case R_DBG:
- s->regs[addr] = value;
- break;
-
- case R_STAT:
- /* write one to clear bits */
- s->regs[addr] &= ~(value & (STAT_RX_EVT | STAT_TX_EVT));
- qemu_chr_accept_input(s->chr);
- break;
-
- default:
- error_report("milkymist_uart: write access to unknown register 0x"
- TARGET_FMT_plx, addr << 2);
- break;
- }
-
- uart_update_irq(s);
-}
-
-static const MemoryRegionOps uart_mmio_ops = {
- .read = uart_read,
- .write = uart_write,
- .valid = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void uart_rx(void *opaque, const uint8_t *buf, int size)
-{
- MilkymistUartState *s = opaque;
-
- assert(!(s->regs[R_STAT] & STAT_RX_EVT));
-
- s->regs[R_STAT] |= STAT_RX_EVT;
- s->regs[R_RXTX] = *buf;
-
- uart_update_irq(s);
-}
-
-static int uart_can_rx(void *opaque)
-{
- MilkymistUartState *s = opaque;
-
- return !(s->regs[R_STAT] & STAT_RX_EVT);
-}
-
-static void uart_event(void *opaque, int event)
-{
-}
-
-static void milkymist_uart_reset(DeviceState *d)
-{
- MilkymistUartState *s = MILKYMIST_UART(d);
- int i;
-
- for (i = 0; i < R_MAX; i++) {
- s->regs[i] = 0;
- }
-
- /* THRE is always set */
- s->regs[R_STAT] = STAT_THRE;
-}
-
-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);
- }
-}
-
-static void milkymist_uart_init(Object *obj)
-{
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
- MilkymistUartState *s = MILKYMIST_UART(obj);
-
- sysbus_init_irq(sbd, &s->irq);
-
- memory_region_init_io(&s->regs_region, OBJECT(s), &uart_mmio_ops, s,
- "milkymist-uart", R_MAX * 4);
- sysbus_init_mmio(sbd, &s->regs_region);
-}
-
-static const VMStateDescription vmstate_milkymist_uart = {
- .name = "milkymist-uart",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32_ARRAY(regs, MilkymistUartState, R_MAX),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void milkymist_uart_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- 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;
-}
-
-static const TypeInfo milkymist_uart_info = {
- .name = TYPE_MILKYMIST_UART,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(MilkymistUartState),
- .instance_init = milkymist_uart_init,
- .class_init = milkymist_uart_class_init,
-};
-
-static void milkymist_uart_register_types(void)
-{
- type_register_static(&milkymist_uart_info);
-}
-
-type_init(milkymist_uart_register_types)
diff --git a/qemu/hw/char/omap_uart.c b/qemu/hw/char/omap_uart.c
deleted file mode 100644
index 415bec5fa..000000000
--- a/qemu/hw/char/omap_uart.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * TI OMAP processors UART emulation.
- *
- * Copyright (C) 2006-2008 Andrzej Zaborowski <balrog@zabor.org>
- * Copyright (C) 2007-2009 Nokia Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * 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"
-#include "hw/char/serial.h"
-#include "exec/address-spaces.h"
-
-/* UARTs */
-struct omap_uart_s {
- MemoryRegion iomem;
- hwaddr base;
- SerialState *serial; /* TODO */
- struct omap_target_agent_s *ta;
- omap_clk fclk;
- qemu_irq irq;
-
- uint8_t eblr;
- uint8_t syscontrol;
- uint8_t wkup;
- uint8_t cfps;
- uint8_t mdr[2];
- uint8_t scr;
- uint8_t clksel;
-};
-
-void omap_uart_reset(struct omap_uart_s *s)
-{
- s->eblr = 0x00;
- s->syscontrol = 0;
- s->wkup = 0x3f;
- s->cfps = 0x69;
- s->clksel = 0;
-}
-
-struct omap_uart_s *omap_uart_init(hwaddr base,
- qemu_irq irq, omap_clk fclk, omap_clk iclk,
- qemu_irq txdma, qemu_irq rxdma,
- const char *label, CharDriverState *chr)
-{
- struct omap_uart_s *s = g_new0(struct omap_uart_s, 1);
-
- s->base = base;
- s->fclk = fclk;
- s->irq = irq;
- s->serial = serial_mm_init(get_system_memory(), base, 2, irq,
- omap_clk_getrate(fclk)/16,
- chr ?: qemu_chr_new(label, "null", NULL),
- DEVICE_NATIVE_ENDIAN);
- return s;
-}
-
-static uint64_t omap_uart_read(void *opaque, hwaddr addr,
- unsigned size)
-{
- struct omap_uart_s *s = (struct omap_uart_s *) opaque;
-
- if (size == 4) {
- return omap_badwidth_read8(opaque, addr);
- }
-
- switch (addr) {
- case 0x20: /* MDR1 */
- return s->mdr[0];
- case 0x24: /* MDR2 */
- return s->mdr[1];
- case 0x40: /* SCR */
- return s->scr;
- case 0x44: /* SSR */
- return 0x0;
- case 0x48: /* EBLR (OMAP2) */
- return s->eblr;
- case 0x4C: /* OSC_12M_SEL (OMAP1) */
- return s->clksel;
- case 0x50: /* MVR */
- return 0x30;
- case 0x54: /* SYSC (OMAP2) */
- return s->syscontrol;
- case 0x58: /* SYSS (OMAP2) */
- return 1;
- case 0x5c: /* WER (OMAP2) */
- return s->wkup;
- case 0x60: /* CFPS (OMAP2) */
- return s->cfps;
- }
-
- OMAP_BAD_REG(addr);
- return 0;
-}
-
-static void omap_uart_write(void *opaque, hwaddr addr,
- uint64_t value, unsigned size)
-{
- struct omap_uart_s *s = (struct omap_uart_s *) opaque;
-
- if (size == 4) {
- omap_badwidth_write8(opaque, addr, value);
- return;
- }
-
- switch (addr) {
- case 0x20: /* MDR1 */
- s->mdr[0] = value & 0x7f;
- break;
- case 0x24: /* MDR2 */
- s->mdr[1] = value & 0xff;
- break;
- case 0x40: /* SCR */
- s->scr = value & 0xff;
- break;
- case 0x48: /* EBLR (OMAP2) */
- s->eblr = value & 0xff;
- break;
- case 0x4C: /* OSC_12M_SEL (OMAP1) */
- s->clksel = value & 1;
- break;
- case 0x44: /* SSR */
- case 0x50: /* MVR */
- case 0x58: /* SYSS (OMAP2) */
- OMAP_RO_REG(addr);
- break;
- case 0x54: /* SYSC (OMAP2) */
- s->syscontrol = value & 0x1d;
- if (value & 2)
- omap_uart_reset(s);
- break;
- case 0x5c: /* WER (OMAP2) */
- s->wkup = value & 0x7f;
- break;
- case 0x60: /* CFPS (OMAP2) */
- s->cfps = value & 0xff;
- break;
- default:
- OMAP_BAD_REG(addr);
- }
-}
-
-static const MemoryRegionOps omap_uart_ops = {
- .read = omap_uart_read,
- .write = omap_uart_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-struct omap_uart_s *omap2_uart_init(MemoryRegion *sysmem,
- struct omap_target_agent_s *ta,
- qemu_irq irq, omap_clk fclk, omap_clk iclk,
- qemu_irq txdma, qemu_irq rxdma,
- const char *label, CharDriverState *chr)
-{
- hwaddr base = omap_l4_attach(ta, 0, NULL);
- struct omap_uart_s *s = omap_uart_init(base, irq,
- fclk, iclk, txdma, rxdma, label, chr);
-
- memory_region_init_io(&s->iomem, NULL, &omap_uart_ops, s, "omap.uart", 0x100);
-
- s->ta = ta;
-
- memory_region_add_subregion(sysmem, base + 0x20, &s->iomem);
-
- return s;
-}
-
-void omap_uart_attach(struct omap_uart_s *s, CharDriverState *chr)
-{
- /* TODO: Should reuse or destroy current s->serial */
- s->serial = serial_mm_init(get_system_memory(), s->base, 2, s->irq,
- omap_clk_getrate(s->fclk) / 16,
- chr ?: qemu_chr_new("null", "null", NULL),
- DEVICE_NATIVE_ENDIAN);
-}
diff --git a/qemu/hw/char/parallel.c b/qemu/hw/char/parallel.c
deleted file mode 100644
index 11c78fed8..000000000
--- a/qemu/hw/char/parallel.c
+++ /dev/null
@@ -1,645 +0,0 @@
-/*
- * QEMU Parallel PORT emulation
- *
- * Copyright (c) 2003-2005 Fabrice Bellard
- * Copyright (c) 2007 Marko Kohtala
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * 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"
-#include "hw/i386/pc.h"
-#include "sysemu/sysemu.h"
-
-//#define DEBUG_PARALLEL
-
-#ifdef DEBUG_PARALLEL
-#define pdebug(fmt, ...) printf("pp: " fmt, ## __VA_ARGS__)
-#else
-#define pdebug(fmt, ...) ((void)0)
-#endif
-
-#define PARA_REG_DATA 0
-#define PARA_REG_STS 1
-#define PARA_REG_CTR 2
-#define PARA_REG_EPP_ADDR 3
-#define PARA_REG_EPP_DATA 4
-
-/*
- * These are the definitions for the Printer Status Register
- */
-#define PARA_STS_BUSY 0x80 /* Busy complement */
-#define PARA_STS_ACK 0x40 /* Acknowledge */
-#define PARA_STS_PAPER 0x20 /* Out of paper */
-#define PARA_STS_ONLINE 0x10 /* Online */
-#define PARA_STS_ERROR 0x08 /* Error complement */
-#define PARA_STS_TMOUT 0x01 /* EPP timeout */
-
-/*
- * These are the definitions for the Printer Control Register
- */
-#define PARA_CTR_DIR 0x20 /* Direction (1=read, 0=write) */
-#define PARA_CTR_INTEN 0x10 /* IRQ Enable */
-#define PARA_CTR_SELECT 0x08 /* Select In complement */
-#define PARA_CTR_INIT 0x04 /* Initialize Printer complement */
-#define PARA_CTR_AUTOLF 0x02 /* Auto linefeed complement */
-#define PARA_CTR_STROBE 0x01 /* Strobe complement */
-
-#define PARA_CTR_SIGNAL (PARA_CTR_SELECT|PARA_CTR_INIT|PARA_CTR_AUTOLF|PARA_CTR_STROBE)
-
-typedef struct ParallelState {
- MemoryRegion iomem;
- uint8_t dataw;
- uint8_t datar;
- uint8_t status;
- uint8_t control;
- qemu_irq irq;
- int irq_pending;
- CharDriverState *chr;
- int hw_driver;
- int epp_timeout;
- uint32_t last_read_offset; /* For debugging */
- /* Memory-mapped interface */
- int it_shift;
-} ParallelState;
-
-#define TYPE_ISA_PARALLEL "isa-parallel"
-#define ISA_PARALLEL(obj) \
- OBJECT_CHECK(ISAParallelState, (obj), TYPE_ISA_PARALLEL)
-
-typedef struct ISAParallelState {
- ISADevice parent_obj;
-
- uint32_t index;
- uint32_t iobase;
- uint32_t isairq;
- ParallelState state;
-} ISAParallelState;
-
-static void parallel_update_irq(ParallelState *s)
-{
- if (s->irq_pending)
- qemu_irq_raise(s->irq);
- else
- qemu_irq_lower(s->irq);
-}
-
-static void
-parallel_ioport_write_sw(void *opaque, uint32_t addr, uint32_t val)
-{
- ParallelState *s = opaque;
-
- pdebug("write addr=0x%02x val=0x%02x\n", addr, val);
-
- addr &= 7;
- switch(addr) {
- case PARA_REG_DATA:
- s->dataw = val;
- parallel_update_irq(s);
- break;
- case PARA_REG_CTR:
- val |= 0xc0;
- if ((val & PARA_CTR_INIT) == 0 ) {
- s->status = PARA_STS_BUSY;
- s->status |= PARA_STS_ACK;
- s->status |= PARA_STS_ONLINE;
- s->status |= PARA_STS_ERROR;
- }
- else if (val & PARA_CTR_SELECT) {
- if (val & PARA_CTR_STROBE) {
- s->status &= ~PARA_STS_BUSY;
- if ((s->control & PARA_CTR_STROBE) == 0)
- qemu_chr_fe_write(s->chr, &s->dataw, 1);
- } else {
- if (s->control & PARA_CTR_INTEN) {
- s->irq_pending = 1;
- }
- }
- }
- parallel_update_irq(s);
- s->control = val;
- break;
- }
-}
-
-static void parallel_ioport_write_hw(void *opaque, uint32_t addr, uint32_t val)
-{
- ParallelState *s = opaque;
- uint8_t parm = val;
- int dir;
-
- /* Sometimes programs do several writes for timing purposes on old
- HW. Take care not to waste time on writes that do nothing. */
-
- s->last_read_offset = ~0U;
-
- addr &= 7;
- switch(addr) {
- case PARA_REG_DATA:
- if (s->dataw == val)
- return;
- pdebug("wd%02x\n", val);
- qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_WRITE_DATA, &parm);
- s->dataw = val;
- break;
- case PARA_REG_STS:
- pdebug("ws%02x\n", val);
- if (val & PARA_STS_TMOUT)
- s->epp_timeout = 0;
- break;
- case PARA_REG_CTR:
- val |= 0xc0;
- if (s->control == val)
- return;
- pdebug("wc%02x\n", val);
-
- if ((val & PARA_CTR_DIR) != (s->control & PARA_CTR_DIR)) {
- if (val & PARA_CTR_DIR) {
- dir = 1;
- } else {
- dir = 0;
- }
- qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_DATA_DIR, &dir);
- parm &= ~PARA_CTR_DIR;
- }
-
- qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_WRITE_CONTROL, &parm);
- s->control = val;
- break;
- case PARA_REG_EPP_ADDR:
- if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != PARA_CTR_INIT)
- /* Controls not correct for EPP address cycle, so do nothing */
- pdebug("wa%02x s\n", val);
- else {
- struct ParallelIOArg ioarg = { .buffer = &parm, .count = 1 };
- if (qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_EPP_WRITE_ADDR, &ioarg)) {
- s->epp_timeout = 1;
- pdebug("wa%02x t\n", val);
- }
- else
- pdebug("wa%02x\n", val);
- }
- break;
- case PARA_REG_EPP_DATA:
- if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != PARA_CTR_INIT)
- /* Controls not correct for EPP data cycle, so do nothing */
- pdebug("we%02x s\n", val);
- else {
- struct ParallelIOArg ioarg = { .buffer = &parm, .count = 1 };
- if (qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_EPP_WRITE, &ioarg)) {
- s->epp_timeout = 1;
- pdebug("we%02x t\n", val);
- }
- else
- pdebug("we%02x\n", val);
- }
- break;
- }
-}
-
-static void
-parallel_ioport_eppdata_write_hw2(void *opaque, uint32_t addr, uint32_t val)
-{
- ParallelState *s = opaque;
- uint16_t eppdata = cpu_to_le16(val);
- int err;
- struct ParallelIOArg ioarg = {
- .buffer = &eppdata, .count = sizeof(eppdata)
- };
- if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != PARA_CTR_INIT) {
- /* Controls not correct for EPP data cycle, so do nothing */
- pdebug("we%04x s\n", val);
- return;
- }
- err = qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_EPP_WRITE, &ioarg);
- if (err) {
- s->epp_timeout = 1;
- pdebug("we%04x t\n", val);
- }
- else
- pdebug("we%04x\n", val);
-}
-
-static void
-parallel_ioport_eppdata_write_hw4(void *opaque, uint32_t addr, uint32_t val)
-{
- ParallelState *s = opaque;
- uint32_t eppdata = cpu_to_le32(val);
- int err;
- struct ParallelIOArg ioarg = {
- .buffer = &eppdata, .count = sizeof(eppdata)
- };
- if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != PARA_CTR_INIT) {
- /* Controls not correct for EPP data cycle, so do nothing */
- pdebug("we%08x s\n", val);
- return;
- }
- err = qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_EPP_WRITE, &ioarg);
- if (err) {
- s->epp_timeout = 1;
- pdebug("we%08x t\n", val);
- }
- else
- pdebug("we%08x\n", val);
-}
-
-static uint32_t parallel_ioport_read_sw(void *opaque, uint32_t addr)
-{
- ParallelState *s = opaque;
- uint32_t ret = 0xff;
-
- addr &= 7;
- switch(addr) {
- case PARA_REG_DATA:
- if (s->control & PARA_CTR_DIR)
- ret = s->datar;
- else
- ret = s->dataw;
- break;
- case PARA_REG_STS:
- ret = s->status;
- s->irq_pending = 0;
- if ((s->status & PARA_STS_BUSY) == 0 && (s->control & PARA_CTR_STROBE) == 0) {
- /* XXX Fixme: wait 5 microseconds */
- if (s->status & PARA_STS_ACK)
- s->status &= ~PARA_STS_ACK;
- else {
- /* XXX Fixme: wait 5 microseconds */
- s->status |= PARA_STS_ACK;
- s->status |= PARA_STS_BUSY;
- }
- }
- parallel_update_irq(s);
- break;
- case PARA_REG_CTR:
- ret = s->control;
- break;
- }
- pdebug("read addr=0x%02x val=0x%02x\n", addr, ret);
- return ret;
-}
-
-static uint32_t parallel_ioport_read_hw(void *opaque, uint32_t addr)
-{
- ParallelState *s = opaque;
- uint8_t ret = 0xff;
- addr &= 7;
- switch(addr) {
- case PARA_REG_DATA:
- qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_READ_DATA, &ret);
- if (s->last_read_offset != addr || s->datar != ret)
- pdebug("rd%02x\n", ret);
- s->datar = ret;
- break;
- case PARA_REG_STS:
- qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_READ_STATUS, &ret);
- ret &= ~PARA_STS_TMOUT;
- if (s->epp_timeout)
- ret |= PARA_STS_TMOUT;
- if (s->last_read_offset != addr || s->status != ret)
- pdebug("rs%02x\n", ret);
- s->status = ret;
- break;
- case PARA_REG_CTR:
- /* s->control has some bits fixed to 1. It is zero only when
- it has not been yet written to. */
- if (s->control == 0) {
- qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_READ_CONTROL, &ret);
- if (s->last_read_offset != addr)
- pdebug("rc%02x\n", ret);
- s->control = ret;
- }
- else {
- ret = s->control;
- if (s->last_read_offset != addr)
- pdebug("rc%02x\n", ret);
- }
- break;
- case PARA_REG_EPP_ADDR:
- if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != (PARA_CTR_DIR|PARA_CTR_INIT))
- /* Controls not correct for EPP addr cycle, so do nothing */
- pdebug("ra%02x s\n", ret);
- else {
- struct ParallelIOArg ioarg = { .buffer = &ret, .count = 1 };
- if (qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_EPP_READ_ADDR, &ioarg)) {
- s->epp_timeout = 1;
- pdebug("ra%02x t\n", ret);
- }
- else
- pdebug("ra%02x\n", ret);
- }
- break;
- case PARA_REG_EPP_DATA:
- if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != (PARA_CTR_DIR|PARA_CTR_INIT))
- /* Controls not correct for EPP data cycle, so do nothing */
- pdebug("re%02x s\n", ret);
- else {
- struct ParallelIOArg ioarg = { .buffer = &ret, .count = 1 };
- if (qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_EPP_READ, &ioarg)) {
- s->epp_timeout = 1;
- pdebug("re%02x t\n", ret);
- }
- else
- pdebug("re%02x\n", ret);
- }
- break;
- }
- s->last_read_offset = addr;
- return ret;
-}
-
-static uint32_t
-parallel_ioport_eppdata_read_hw2(void *opaque, uint32_t addr)
-{
- ParallelState *s = opaque;
- uint32_t ret;
- uint16_t eppdata = ~0;
- int err;
- struct ParallelIOArg ioarg = {
- .buffer = &eppdata, .count = sizeof(eppdata)
- };
- if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != (PARA_CTR_DIR|PARA_CTR_INIT)) {
- /* Controls not correct for EPP data cycle, so do nothing */
- pdebug("re%04x s\n", eppdata);
- return eppdata;
- }
- err = qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_EPP_READ, &ioarg);
- ret = le16_to_cpu(eppdata);
-
- if (err) {
- s->epp_timeout = 1;
- pdebug("re%04x t\n", ret);
- }
- else
- pdebug("re%04x\n", ret);
- return ret;
-}
-
-static uint32_t
-parallel_ioport_eppdata_read_hw4(void *opaque, uint32_t addr)
-{
- ParallelState *s = opaque;
- uint32_t ret;
- uint32_t eppdata = ~0U;
- int err;
- struct ParallelIOArg ioarg = {
- .buffer = &eppdata, .count = sizeof(eppdata)
- };
- if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != (PARA_CTR_DIR|PARA_CTR_INIT)) {
- /* Controls not correct for EPP data cycle, so do nothing */
- pdebug("re%08x s\n", eppdata);
- return eppdata;
- }
- err = qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_EPP_READ, &ioarg);
- ret = le32_to_cpu(eppdata);
-
- if (err) {
- s->epp_timeout = 1;
- pdebug("re%08x t\n", ret);
- }
- else
- pdebug("re%08x\n", ret);
- return ret;
-}
-
-static void parallel_ioport_ecp_write(void *opaque, uint32_t addr, uint32_t val)
-{
- pdebug("wecp%d=%02x\n", addr & 7, val);
-}
-
-static uint32_t parallel_ioport_ecp_read(void *opaque, uint32_t addr)
-{
- uint8_t ret = 0xff;
-
- pdebug("recp%d:%02x\n", addr & 7, ret);
- return ret;
-}
-
-static void parallel_reset(void *opaque)
-{
- ParallelState *s = opaque;
-
- s->datar = ~0;
- s->dataw = ~0;
- s->status = PARA_STS_BUSY;
- s->status |= PARA_STS_ACK;
- s->status |= PARA_STS_ONLINE;
- s->status |= PARA_STS_ERROR;
- s->status |= PARA_STS_TMOUT;
- s->control = PARA_CTR_SELECT;
- s->control |= PARA_CTR_INIT;
- s->control |= 0xc0;
- s->irq_pending = 0;
- s->hw_driver = 0;
- s->epp_timeout = 0;
- s->last_read_offset = ~0U;
-}
-
-static const int isa_parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
-
-static const MemoryRegionPortio isa_parallel_portio_hw_list[] = {
- { 0, 8, 1,
- .read = parallel_ioport_read_hw,
- .write = parallel_ioport_write_hw },
- { 4, 1, 2,
- .read = parallel_ioport_eppdata_read_hw2,
- .write = parallel_ioport_eppdata_write_hw2 },
- { 4, 1, 4,
- .read = parallel_ioport_eppdata_read_hw4,
- .write = parallel_ioport_eppdata_write_hw4 },
- { 0x400, 8, 1,
- .read = parallel_ioport_ecp_read,
- .write = parallel_ioport_ecp_write },
- PORTIO_END_OF_LIST(),
-};
-
-static const MemoryRegionPortio isa_parallel_portio_sw_list[] = {
- { 0, 8, 1,
- .read = parallel_ioport_read_sw,
- .write = parallel_ioport_write_sw },
- PORTIO_END_OF_LIST(),
-};
-
-
-static const VMStateDescription vmstate_parallel_isa = {
- .name = "parallel_isa",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT8(state.dataw, ISAParallelState),
- VMSTATE_UINT8(state.datar, ISAParallelState),
- VMSTATE_UINT8(state.status, ISAParallelState),
- VMSTATE_UINT8(state.control, ISAParallelState),
- VMSTATE_INT32(state.irq_pending, ISAParallelState),
- VMSTATE_INT32(state.epp_timeout, ISAParallelState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-
-static void parallel_isa_realizefn(DeviceState *dev, Error **errp)
-{
- static int index;
- ISADevice *isadev = ISA_DEVICE(dev);
- ISAParallelState *isa = ISA_PARALLEL(dev);
- ParallelState *s = &isa->state;
- int base;
- uint8_t dummy;
-
- if (!s->chr) {
- error_setg(errp, "Can't create parallel device, empty char device");
- return;
- }
-
- if (isa->index == -1) {
- isa->index = index;
- }
- if (isa->index >= MAX_PARALLEL_PORTS) {
- error_setg(errp, "Max. supported number of parallel ports is %d.",
- MAX_PARALLEL_PORTS);
- return;
- }
- if (isa->iobase == -1) {
- isa->iobase = isa_parallel_io[isa->index];
- }
- index++;
-
- base = isa->iobase;
- isa_init_irq(isadev, &s->irq, isa->isairq);
- qemu_register_reset(parallel_reset, s);
-
- if (qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_READ_STATUS, &dummy) == 0) {
- s->hw_driver = 1;
- s->status = dummy;
- }
-
- isa_register_portio_list(isadev, base,
- (s->hw_driver
- ? &isa_parallel_portio_hw_list[0]
- : &isa_parallel_portio_sw_list[0]),
- s, "parallel");
-}
-
-/* Memory mapped interface */
-static uint32_t parallel_mm_readb (void *opaque, hwaddr addr)
-{
- ParallelState *s = opaque;
-
- return parallel_ioport_read_sw(s, addr >> s->it_shift) & 0xFF;
-}
-
-static void parallel_mm_writeb (void *opaque,
- hwaddr addr, uint32_t value)
-{
- ParallelState *s = opaque;
-
- parallel_ioport_write_sw(s, addr >> s->it_shift, value & 0xFF);
-}
-
-static uint32_t parallel_mm_readw (void *opaque, hwaddr addr)
-{
- ParallelState *s = opaque;
-
- return parallel_ioport_read_sw(s, addr >> s->it_shift) & 0xFFFF;
-}
-
-static void parallel_mm_writew (void *opaque,
- hwaddr addr, uint32_t value)
-{
- ParallelState *s = opaque;
-
- parallel_ioport_write_sw(s, addr >> s->it_shift, value & 0xFFFF);
-}
-
-static uint32_t parallel_mm_readl (void *opaque, hwaddr addr)
-{
- ParallelState *s = opaque;
-
- return parallel_ioport_read_sw(s, addr >> s->it_shift);
-}
-
-static void parallel_mm_writel (void *opaque,
- hwaddr addr, uint32_t value)
-{
- ParallelState *s = opaque;
-
- parallel_ioport_write_sw(s, addr >> s->it_shift, value);
-}
-
-static const MemoryRegionOps parallel_mm_ops = {
- .old_mmio = {
- .read = { parallel_mm_readb, parallel_mm_readw, parallel_mm_readl },
- .write = { parallel_mm_writeb, parallel_mm_writew, parallel_mm_writel },
- },
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-/* If fd is zero, it means that the parallel device uses the console */
-bool parallel_mm_init(MemoryRegion *address_space,
- hwaddr base, int it_shift, qemu_irq irq,
- CharDriverState *chr)
-{
- ParallelState *s;
-
- s = g_malloc0(sizeof(ParallelState));
- s->irq = irq;
- s->chr = chr;
- s->it_shift = it_shift;
- qemu_register_reset(parallel_reset, s);
-
- memory_region_init_io(&s->iomem, NULL, &parallel_mm_ops, s,
- "parallel", 8 << it_shift);
- memory_region_add_subregion(address_space, base, &s->iomem);
- return true;
-}
-
-static Property parallel_isa_properties[] = {
- DEFINE_PROP_UINT32("index", ISAParallelState, index, -1),
- DEFINE_PROP_UINT32("iobase", ISAParallelState, iobase, -1),
- DEFINE_PROP_UINT32("irq", ISAParallelState, isairq, 7),
- DEFINE_PROP_CHR("chardev", ISAParallelState, state.chr),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void parallel_isa_class_initfn(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->realize = parallel_isa_realizefn;
- dc->vmsd = &vmstate_parallel_isa;
- dc->props = parallel_isa_properties;
- set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
-}
-
-static const TypeInfo parallel_isa_info = {
- .name = TYPE_ISA_PARALLEL,
- .parent = TYPE_ISA_DEVICE,
- .instance_size = sizeof(ISAParallelState),
- .class_init = parallel_isa_class_initfn,
-};
-
-static void parallel_register_types(void)
-{
- type_register_static(&parallel_isa_info);
-}
-
-type_init(parallel_register_types)
diff --git a/qemu/hw/char/pl011.c b/qemu/hw/char/pl011.c
deleted file mode 100644
index 210c87b4c..000000000
--- a/qemu/hw/char/pl011.c
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * Arm PrimeCell PL011 UART
- *
- * Copyright (c) 2006 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licensed under the GPL.
- */
-
-#include "qemu/osdep.h"
-#include "hw/sysbus.h"
-#include "sysemu/char.h"
-
-#define TYPE_PL011 "pl011"
-#define PL011(obj) OBJECT_CHECK(PL011State, (obj), TYPE_PL011)
-
-typedef struct PL011State {
- SysBusDevice parent_obj;
-
- MemoryRegion iomem;
- uint32_t readbuff;
- uint32_t flags;
- uint32_t lcr;
- uint32_t rsr;
- uint32_t cr;
- uint32_t dmacr;
- uint32_t int_enabled;
- uint32_t int_level;
- uint32_t read_fifo[16];
- uint32_t ilpr;
- uint32_t ibrd;
- uint32_t fbrd;
- uint32_t ifl;
- int read_pos;
- int read_count;
- int read_trigger;
- CharDriverState *chr;
- qemu_irq irq;
- const unsigned char *id;
-} PL011State;
-
-#define PL011_INT_TX 0x20
-#define PL011_INT_RX 0x10
-
-#define PL011_FLAG_TXFE 0x80
-#define PL011_FLAG_RXFF 0x40
-#define PL011_FLAG_TXFF 0x20
-#define PL011_FLAG_RXFE 0x10
-
-static const unsigned char pl011_id_arm[8] =
- { 0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
-static const unsigned char pl011_id_luminary[8] =
- { 0x11, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 };
-
-static void pl011_update(PL011State *s)
-{
- uint32_t flags;
-
- flags = s->int_level & s->int_enabled;
- qemu_set_irq(s->irq, flags != 0);
-}
-
-static uint64_t pl011_read(void *opaque, hwaddr offset,
- unsigned size)
-{
- PL011State *s = (PL011State *)opaque;
- uint32_t c;
-
- if (offset >= 0xfe0 && offset < 0x1000) {
- return s->id[(offset - 0xfe0) >> 2];
- }
- switch (offset >> 2) {
- case 0: /* UARTDR */
- s->flags &= ~PL011_FLAG_RXFF;
- c = s->read_fifo[s->read_pos];
- if (s->read_count > 0) {
- s->read_count--;
- if (++s->read_pos == 16)
- s->read_pos = 0;
- }
- if (s->read_count == 0) {
- s->flags |= PL011_FLAG_RXFE;
- }
- if (s->read_count == s->read_trigger - 1)
- s->int_level &= ~ PL011_INT_RX;
- s->rsr = c >> 8;
- pl011_update(s);
- if (s->chr) {
- qemu_chr_accept_input(s->chr);
- }
- return c;
- case 1: /* UARTRSR */
- return s->rsr;
- case 6: /* UARTFR */
- return s->flags;
- case 8: /* UARTILPR */
- return s->ilpr;
- case 9: /* UARTIBRD */
- return s->ibrd;
- case 10: /* UARTFBRD */
- return s->fbrd;
- case 11: /* UARTLCR_H */
- return s->lcr;
- case 12: /* UARTCR */
- return s->cr;
- case 13: /* UARTIFLS */
- return s->ifl;
- case 14: /* UARTIMSC */
- return s->int_enabled;
- case 15: /* UARTRIS */
- return s->int_level;
- case 16: /* UARTMIS */
- return s->int_level & s->int_enabled;
- case 18: /* UARTDMACR */
- return s->dmacr;
- default:
- qemu_log_mask(LOG_GUEST_ERROR,
- "pl011_read: Bad offset %x\n", (int)offset);
- return 0;
- }
-}
-
-static void pl011_set_read_trigger(PL011State *s)
-{
-#if 0
- /* The docs say the RX interrupt is triggered when the FIFO exceeds
- the threshold. However linux only reads the FIFO in response to an
- interrupt. Triggering the interrupt when the FIFO is non-empty seems
- to make things work. */
- if (s->lcr & 0x10)
- s->read_trigger = (s->ifl >> 1) & 0x1c;
- else
-#endif
- s->read_trigger = 1;
-}
-
-static void pl011_write(void *opaque, hwaddr offset,
- uint64_t value, unsigned size)
-{
- PL011State *s = (PL011State *)opaque;
- unsigned char ch;
-
- switch (offset >> 2) {
- case 0: /* UARTDR */
- /* ??? Check if transmitter is enabled. */
- ch = value;
- if (s->chr)
- qemu_chr_fe_write(s->chr, &ch, 1);
- s->int_level |= PL011_INT_TX;
- pl011_update(s);
- break;
- case 1: /* UARTRSR/UARTECR */
- s->rsr = 0;
- break;
- case 6: /* UARTFR */
- /* Writes to Flag register are ignored. */
- break;
- case 8: /* UARTUARTILPR */
- s->ilpr = value;
- break;
- case 9: /* UARTIBRD */
- s->ibrd = value;
- break;
- case 10: /* UARTFBRD */
- s->fbrd = value;
- break;
- case 11: /* UARTLCR_H */
- /* Reset the FIFO state on FIFO enable or disable */
- if ((s->lcr ^ value) & 0x10) {
- s->read_count = 0;
- s->read_pos = 0;
- }
- s->lcr = value;
- pl011_set_read_trigger(s);
- break;
- case 12: /* UARTCR */
- /* ??? Need to implement the enable and loopback bits. */
- s->cr = value;
- break;
- case 13: /* UARTIFS */
- s->ifl = value;
- pl011_set_read_trigger(s);
- break;
- case 14: /* UARTIMSC */
- s->int_enabled = value;
- pl011_update(s);
- break;
- case 17: /* UARTICR */
- s->int_level &= ~value;
- pl011_update(s);
- break;
- case 18: /* UARTDMACR */
- s->dmacr = value;
- if (value & 3) {
- qemu_log_mask(LOG_UNIMP, "pl011: DMA not implemented\n");
- }
- break;
- default:
- qemu_log_mask(LOG_GUEST_ERROR,
- "pl011_write: Bad offset %x\n", (int)offset);
- }
-}
-
-static int pl011_can_receive(void *opaque)
-{
- PL011State *s = (PL011State *)opaque;
-
- if (s->lcr & 0x10)
- return s->read_count < 16;
- else
- return s->read_count < 1;
-}
-
-static void pl011_put_fifo(void *opaque, uint32_t value)
-{
- PL011State *s = (PL011State *)opaque;
- int slot;
-
- slot = s->read_pos + s->read_count;
- if (slot >= 16)
- slot -= 16;
- s->read_fifo[slot] = value;
- s->read_count++;
- s->flags &= ~PL011_FLAG_RXFE;
- if (!(s->lcr & 0x10) || s->read_count == 16) {
- s->flags |= PL011_FLAG_RXFF;
- }
- if (s->read_count == s->read_trigger) {
- s->int_level |= PL011_INT_RX;
- pl011_update(s);
- }
-}
-
-static void pl011_receive(void *opaque, const uint8_t *buf, int size)
-{
- pl011_put_fifo(opaque, *buf);
-}
-
-static void pl011_event(void *opaque, int event)
-{
- if (event == CHR_EVENT_BREAK)
- pl011_put_fifo(opaque, 0x400);
-}
-
-static const MemoryRegionOps pl011_ops = {
- .read = pl011_read,
- .write = pl011_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const VMStateDescription vmstate_pl011 = {
- .name = "pl011",
- .version_id = 2,
- .minimum_version_id = 2,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(readbuff, PL011State),
- VMSTATE_UINT32(flags, PL011State),
- VMSTATE_UINT32(lcr, PL011State),
- VMSTATE_UINT32(rsr, PL011State),
- VMSTATE_UINT32(cr, PL011State),
- VMSTATE_UINT32(dmacr, PL011State),
- VMSTATE_UINT32(int_enabled, PL011State),
- VMSTATE_UINT32(int_level, PL011State),
- VMSTATE_UINT32_ARRAY(read_fifo, PL011State, 16),
- VMSTATE_UINT32(ilpr, PL011State),
- VMSTATE_UINT32(ibrd, PL011State),
- VMSTATE_UINT32(fbrd, PL011State),
- VMSTATE_UINT32(ifl, PL011State),
- VMSTATE_INT32(read_pos, PL011State),
- VMSTATE_INT32(read_count, PL011State),
- VMSTATE_INT32(read_trigger, PL011State),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void pl011_init(Object *obj)
-{
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
- PL011State *s = PL011(obj);
-
- memory_region_init_io(&s->iomem, OBJECT(s), &pl011_ops, s, "pl011", 0x1000);
- sysbus_init_mmio(sbd, &s->iomem);
- sysbus_init_irq(sbd, &s->irq);
-
- s->read_trigger = 1;
- s->ifl = 0x12;
- s->cr = 0x300;
- s->flags = 0x90;
-
- s->id = pl011_id_arm;
-}
-
-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);
- }
-}
-
-static void pl011_class_init(ObjectClass *oc, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(oc);
-
- 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;
-}
-
-static const TypeInfo pl011_arm_info = {
- .name = TYPE_PL011,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(PL011State),
- .instance_init = pl011_init,
- .class_init = pl011_class_init,
-};
-
-static void pl011_luminary_init(Object *obj)
-{
- PL011State *s = PL011(obj);
-
- s->id = pl011_id_luminary;
-}
-
-static const TypeInfo pl011_luminary_info = {
- .name = "pl011_luminary",
- .parent = TYPE_PL011,
- .instance_init = pl011_luminary_init,
-};
-
-static void pl011_register_types(void)
-{
- type_register_static(&pl011_arm_info);
- type_register_static(&pl011_luminary_info);
-}
-
-type_init(pl011_register_types)
diff --git a/qemu/hw/char/sclpconsole-lm.c b/qemu/hw/char/sclpconsole-lm.c
deleted file mode 100644
index 7d4ff8120..000000000
--- a/qemu/hw/char/sclpconsole-lm.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * SCLP event types
- * Operations Command - Line Mode input
- * Message - Line Mode output
- *
- * Copyright IBM, Corp. 2013
- *
- * Authors:
- * Heinz Graalfs <graalfs@linux.vnet.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or (at your
- * option) any later version. See the COPYING file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "hw/qdev.h"
-#include "qemu/thread.h"
-#include "qemu/error-report.h"
-#include "sysemu/char.h"
-
-#include "hw/s390x/sclp.h"
-#include "hw/s390x/event-facility.h"
-#include "hw/s390x/ebcdic.h"
-
-#define SIZE_BUFFER 4096
-#define NEWLINE "\n"
-
-typedef struct OprtnsCommand {
- EventBufferHeader header;
- MDMSU message_unit;
- char data[0];
-} QEMU_PACKED OprtnsCommand;
-
-/* max size for line-mode data in 4K SCCB page */
-#define SIZE_CONSOLE_BUFFER (SCCB_DATA_LEN - sizeof(OprtnsCommand))
-
-typedef struct SCLPConsoleLM {
- SCLPEvent event;
- CharDriverState *chr;
- bool echo; /* immediate echo of input if true */
- uint32_t write_errors; /* errors writing to char layer */
- uint32_t length; /* length of byte stream in buffer */
- uint8_t buf[SIZE_CONSOLE_BUFFER];
-} SCLPConsoleLM;
-
-/*
-* Character layer call-back functions
- *
- * Allow 1 character at a time
- *
- * Accumulate bytes from character layer in console buffer,
- * event_pending is set when a newline character is encountered
- *
- * The maximum command line length is limited by the maximum
- * space available in an SCCB. Line mode console input is sent
- * truncated to the guest in case it doesn't fit into the SCCB.
- */
-
-static int chr_can_read(void *opaque)
-{
- SCLPConsoleLM *scon = opaque;
-
- if (scon->event.event_pending) {
- return 0;
- }
- return 1;
-}
-
-static void chr_read(void *opaque, const uint8_t *buf, int size)
-{
- SCLPConsoleLM *scon = opaque;
-
- assert(size == 1);
-
- if (*buf == '\r' || *buf == '\n') {
- scon->event.event_pending = true;
- sclp_service_interrupt(0);
- return;
- }
- if (scon->length == SIZE_CONSOLE_BUFFER) {
- /* Eat the character, but still process CR and LF. */
- return;
- }
- scon->buf[scon->length] = *buf;
- scon->length += 1;
- if (scon->echo) {
- qemu_chr_fe_write(scon->chr, buf, size);
- }
-}
-
-/* functions to be called by event facility */
-
-static bool can_handle_event(uint8_t type)
-{
- return type == SCLP_EVENT_MESSAGE || type == SCLP_EVENT_PMSGCMD;
-}
-
-static unsigned int send_mask(void)
-{
- return SCLP_EVENT_MASK_OP_CMD | SCLP_EVENT_MASK_PMSGCMD;
-}
-
-static unsigned int receive_mask(void)
-{
- return SCLP_EVENT_MASK_MSG | SCLP_EVENT_MASK_PMSGCMD;
-}
-
-/*
- * Triggered by SCLP's read_event_data
- * - convert ASCII byte stream to EBCDIC and
- * - copy converted data into provided (SCLP) buffer
- */
-static int get_console_data(SCLPEvent *event, uint8_t *buf, size_t *size,
- int avail)
-{
- int len;
-
- SCLPConsoleLM *cons = DO_UPCAST(SCLPConsoleLM, event, event);
-
- len = cons->length;
- /* data need to fit into provided SCLP buffer */
- if (len > avail) {
- return 1;
- }
-
- ebcdic_put(buf, (char *)&cons->buf, len);
- *size = len;
- cons->length = 0;
- /* data provided and no more data pending */
- event->event_pending = false;
- qemu_notify_event();
- return 0;
-}
-
-static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr,
- int *slen)
-{
- int avail, rc;
- size_t src_len;
- uint8_t *to;
- OprtnsCommand *oc = (OprtnsCommand *) evt_buf_hdr;
-
- if (!event->event_pending) {
- /* no data pending */
- return 0;
- }
-
- to = (uint8_t *)&oc->data;
- avail = *slen - sizeof(OprtnsCommand);
- rc = get_console_data(event, to, &src_len, avail);
- if (rc) {
- /* data didn't fit, try next SCCB */
- return 1;
- }
-
- oc->message_unit.mdmsu.gds_id = GDS_ID_MDSMU;
- oc->message_unit.mdmsu.length = cpu_to_be16(sizeof(struct MDMSU));
-
- oc->message_unit.cpmsu.gds_id = GDS_ID_CPMSU;
- oc->message_unit.cpmsu.length =
- cpu_to_be16(sizeof(struct MDMSU) - sizeof(GdsVector));
-
- oc->message_unit.text_command.gds_id = GDS_ID_TEXTCMD;
- oc->message_unit.text_command.length =
- cpu_to_be16(sizeof(struct MDMSU) - (2 * sizeof(GdsVector)));
-
- oc->message_unit.self_def_text_message.key = GDS_KEY_SELFDEFTEXTMSG;
- oc->message_unit.self_def_text_message.length =
- cpu_to_be16(sizeof(struct MDMSU) - (3 * sizeof(GdsVector)));
-
- oc->message_unit.text_message.key = GDS_KEY_TEXTMSG;
- oc->message_unit.text_message.length =
- cpu_to_be16(sizeof(GdsSubvector) + src_len);
-
- oc->header.length = cpu_to_be16(sizeof(OprtnsCommand) + src_len);
- oc->header.type = SCLP_EVENT_OPRTNS_COMMAND;
- *slen = avail - src_len;
-
- return 1;
-}
-
-/*
- * Triggered by SCLP's write_event_data
- * - write console data to character layer
- * returns < 0 if an error occurred
- */
-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);
-
- if (!scon->chr) {
- /* If there's no backend, we can just say we consumed all data. */
- return len;
- }
-
- buf_offset = buf;
- while (len > 0) {
- ret = qemu_chr_fe_write(scon->chr, buf, len);
- if (ret == 0) {
- /* a pty doesn't seem to be connected - no error */
- len = 0;
- } else if (ret == -EAGAIN || (ret > 0 && ret < len)) {
- len -= ret;
- buf_offset += ret;
- } else {
- len = 0;
- }
- }
-
- return ret;
-}
-
-static int process_mdb(SCLPEvent *event, MDBO *mdbo)
-{
- int rc;
- int len;
- uint8_t buffer[SIZE_BUFFER];
-
- len = be16_to_cpu(mdbo->length);
- len -= sizeof(mdbo->length) + sizeof(mdbo->type)
- + sizeof(mdbo->mto.line_type_flags)
- + sizeof(mdbo->mto.alarm_control)
- + sizeof(mdbo->mto._reserved);
-
- assert(len <= SIZE_BUFFER);
-
- /* convert EBCDIC SCLP contents to ASCII console message */
- ascii_put(buffer, mdbo->mto.message, len);
- rc = write_console_data(event, (uint8_t *)NEWLINE, 1);
- if (rc < 0) {
- return rc;
- }
- return write_console_data(event, buffer, len);
-}
-
-static int write_event_data(SCLPEvent *event, EventBufferHeader *ebh)
-{
- int len;
- int written;
- int errors = 0;
- MDBO *mdbo;
- SclpMsg *data = (SclpMsg *) ebh;
- SCLPConsoleLM *scon = DO_UPCAST(SCLPConsoleLM, event, event);
-
- len = be16_to_cpu(data->mdb.header.length);
- if (len < sizeof(data->mdb.header)) {
- return SCLP_RC_INCONSISTENT_LENGTHS;
- }
- len -= sizeof(data->mdb.header);
-
- /* first check message buffers */
- mdbo = data->mdb.mdbo;
- while (len > 0) {
- if (be16_to_cpu(mdbo->length) > len
- || be16_to_cpu(mdbo->length) == 0) {
- return SCLP_RC_INCONSISTENT_LENGTHS;
- }
- len -= be16_to_cpu(mdbo->length);
- mdbo = (void *) mdbo + be16_to_cpu(mdbo->length);
- }
-
- /* then execute */
- len = be16_to_cpu(data->mdb.header.length) - sizeof(data->mdb.header);
- mdbo = data->mdb.mdbo;
- while (len > 0) {
- switch (be16_to_cpu(mdbo->type)) {
- case MESSAGE_TEXT:
- /* message text object */
- written = process_mdb(event, mdbo);
- if (written < 0) {
- /* character layer error */
- errors++;
- }
- break;
- default: /* ignore */
- break;
- }
- len -= be16_to_cpu(mdbo->length);
- mdbo = (void *) mdbo + be16_to_cpu(mdbo->length);
- }
- if (errors) {
- scon->write_errors += errors;
- }
- data->header.flags = SCLP_EVENT_BUFFER_ACCEPTED;
-
- return SCLP_RC_NORMAL_COMPLETION;
-}
-
-/* functions for live migration */
-
-static const VMStateDescription vmstate_sclplmconsole = {
- .name = "sclplmconsole",
- .version_id = 0,
- .minimum_version_id = 0,
- .fields = (VMStateField[]) {
- VMSTATE_BOOL(event.event_pending, SCLPConsoleLM),
- VMSTATE_UINT32(write_errors, SCLPConsoleLM),
- VMSTATE_UINT32(length, SCLPConsoleLM),
- VMSTATE_UINT8_ARRAY(buf, SCLPConsoleLM, SIZE_CONSOLE_BUFFER),
- VMSTATE_END_OF_LIST()
- }
-};
-
-/* qemu object creation and initialization functions */
-
-/* tell character layer our call-back functions */
-
-static int console_init(SCLPEvent *event)
-{
- static bool console_available;
-
- SCLPConsoleLM *scon = DO_UPCAST(SCLPConsoleLM, event, event);
-
- if (console_available) {
- error_report("Multiple line-mode operator consoles are not supported");
- return -1;
- }
- console_available = true;
-
- if (scon->chr) {
- qemu_chr_add_handlers(scon->chr, chr_can_read, chr_read, NULL, scon);
- }
-
- return 0;
-}
-
-static int console_exit(SCLPEvent *event)
-{
- return 0;
-}
-
-static void console_reset(DeviceState *dev)
-{
- SCLPEvent *event = SCLP_EVENT(dev);
- SCLPConsoleLM *scon = DO_UPCAST(SCLPConsoleLM, event, event);
-
- event->event_pending = false;
- scon->length = 0;
- scon->write_errors = 0;
-}
-
-static Property console_properties[] = {
- DEFINE_PROP_CHR("chardev", SCLPConsoleLM, chr),
- DEFINE_PROP_UINT32("write_errors", SCLPConsoleLM, write_errors, 0),
- DEFINE_PROP_BOOL("echo", SCLPConsoleLM, echo, true),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void console_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- SCLPEventClass *ec = SCLP_EVENT_CLASS(klass);
-
- dc->props = console_properties;
- dc->reset = console_reset;
- dc->vmsd = &vmstate_sclplmconsole;
- ec->init = console_init;
- ec->exit = console_exit;
- ec->get_send_mask = send_mask;
- ec->get_receive_mask = receive_mask;
- ec->can_handle_event = can_handle_event;
- ec->read_event_data = read_event_data;
- ec->write_event_data = write_event_data;
- set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
-}
-
-static const TypeInfo sclp_console_info = {
- .name = "sclplmconsole",
- .parent = TYPE_SCLP_EVENT,
- .instance_size = sizeof(SCLPConsoleLM),
- .class_init = console_class_init,
- .class_size = sizeof(SCLPEventClass),
-};
-
-static void register_types(void)
-{
- type_register_static(&sclp_console_info);
-}
-
-type_init(register_types)
diff --git a/qemu/hw/char/sclpconsole.c b/qemu/hw/char/sclpconsole.c
deleted file mode 100644
index 45997ff4a..000000000
--- a/qemu/hw/char/sclpconsole.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * SCLP event type
- * Ascii Console Data (VT220 Console)
- *
- * Copyright IBM, Corp. 2012
- *
- * Authors:
- * Heinz Graalfs <graalfs@de.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or (at your
- * option) any later version. See the COPYING file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include <hw/qdev.h>
-#include "qemu/thread.h"
-#include "qemu/error-report.h"
-
-#include "hw/s390x/sclp.h"
-#include "hw/s390x/event-facility.h"
-#include "sysemu/char.h"
-
-typedef struct ASCIIConsoleData {
- EventBufferHeader ebh;
- char data[0];
-} QEMU_PACKED ASCIIConsoleData;
-
-/* max size for ASCII data in 4K SCCB page */
-#define SIZE_BUFFER_VT220 4080
-
-typedef struct SCLPConsole {
- SCLPEvent event;
- CharDriverState *chr;
- uint8_t iov[SIZE_BUFFER_VT220];
- uint32_t iov_sclp; /* offset in buf for SCLP read operation */
- uint32_t iov_bs; /* offset in buf for char layer read operation */
- uint32_t iov_data_len; /* length of byte stream in buffer */
- uint32_t iov_sclp_rest; /* length of byte stream not read via SCLP */
- bool notify; /* qemu_notify_event() req'd if true */
-} SCLPConsole;
-
-/* character layer call-back functions */
-
-/* Return number of bytes that fit into iov buffer */
-static int chr_can_read(void *opaque)
-{
- SCLPConsole *scon = opaque;
- int avail = SIZE_BUFFER_VT220 - scon->iov_data_len;
-
- if (avail == 0) {
- scon->notify = true;
- }
- return avail;
-}
-
-/* Send data from a char device over to the guest */
-static void chr_read(void *opaque, const uint8_t *buf, int size)
-{
- SCLPConsole *scon = opaque;
-
- assert(scon);
- /* read data must fit into current buffer */
- assert(size <= SIZE_BUFFER_VT220 - scon->iov_data_len);
-
- /* put byte-stream from character layer into buffer */
- memcpy(&scon->iov[scon->iov_bs], buf, size);
- scon->iov_data_len += size;
- scon->iov_sclp_rest += size;
- scon->iov_bs += size;
- scon->event.event_pending = true;
- sclp_service_interrupt(0);
-}
-
-/* functions to be called by event facility */
-
-static bool can_handle_event(uint8_t type)
-{
- return type == SCLP_EVENT_ASCII_CONSOLE_DATA;
-}
-
-static unsigned int send_mask(void)
-{
- return SCLP_EVENT_MASK_MSG_ASCII;
-}
-
-static unsigned int receive_mask(void)
-{
- return SCLP_EVENT_MASK_MSG_ASCII;
-}
-
-/* triggered by SCLP's read_event_data -
- * copy console data byte-stream into provided (SCLP) buffer
- */
-static void get_console_data(SCLPEvent *event, uint8_t *buf, size_t *size,
- int avail)
-{
- SCLPConsole *cons = DO_UPCAST(SCLPConsole, event, event);
-
- /* first byte is hex 0 saying an ascii string follows */
- *buf++ = '\0';
- avail--;
- /* if all data fit into provided SCLP buffer */
- if (avail >= cons->iov_sclp_rest) {
- /* copy character byte-stream to SCLP buffer */
- memcpy(buf, &cons->iov[cons->iov_sclp], cons->iov_sclp_rest);
- *size = cons->iov_sclp_rest + 1;
- cons->iov_sclp = 0;
- cons->iov_bs = 0;
- cons->iov_data_len = 0;
- cons->iov_sclp_rest = 0;
- event->event_pending = false;
- /* data provided and no more data pending */
- } else {
- /* if provided buffer is too small, just copy part */
- memcpy(buf, &cons->iov[cons->iov_sclp], avail);
- *size = avail + 1;
- cons->iov_sclp_rest -= avail;
- cons->iov_sclp += avail;
- /* more data pending */
- }
- if (cons->notify) {
- cons->notify = false;
- qemu_notify_event();
- }
-}
-
-static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr,
- int *slen)
-{
- int avail;
- size_t src_len;
- uint8_t *to;
- ASCIIConsoleData *acd = (ASCIIConsoleData *) evt_buf_hdr;
-
- if (!event->event_pending) {
- /* no data pending */
- return 0;
- }
-
- to = (uint8_t *)&acd->data;
- avail = *slen - sizeof(ASCIIConsoleData);
- get_console_data(event, to, &src_len, avail);
-
- acd->ebh.length = cpu_to_be16(sizeof(ASCIIConsoleData) + src_len);
- acd->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA;
- acd->ebh.flags |= SCLP_EVENT_BUFFER_ACCEPTED;
- *slen = avail - src_len;
-
- return 1;
-}
-
-/* triggered by SCLP's write_event_data
- * - write console data to character layer
- * returns < 0 if an error occurred
- */
-static ssize_t write_console_data(SCLPEvent *event, const uint8_t *buf,
- size_t len)
-{
- SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event);
-
- if (!scon->chr) {
- /* If there's no backend, we can just say we consumed all data. */
- return len;
- }
-
- return qemu_chr_fe_write_all(scon->chr, buf, len);
-}
-
-static int write_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr)
-{
- int rc;
- int length;
- ssize_t written;
- ASCIIConsoleData *acd = (ASCIIConsoleData *) evt_buf_hdr;
-
- length = be16_to_cpu(evt_buf_hdr->length) - sizeof(EventBufferHeader);
- written = write_console_data(event, (uint8_t *)acd->data, length);
-
- rc = SCLP_RC_NORMAL_COMPLETION;
- /* set event buffer accepted flag */
- evt_buf_hdr->flags |= SCLP_EVENT_BUFFER_ACCEPTED;
-
- /* written will be zero if a pty is not connected - don't treat as error */
- if (written < 0) {
- /* event buffer not accepted due to error in character layer */
- evt_buf_hdr->flags &= ~(SCLP_EVENT_BUFFER_ACCEPTED);
- rc = SCLP_RC_CONTAINED_EQUIPMENT_CHECK;
- }
-
- return rc;
-}
-
-static const VMStateDescription vmstate_sclpconsole = {
- .name = "sclpconsole",
- .version_id = 0,
- .minimum_version_id = 0,
- .fields = (VMStateField[]) {
- VMSTATE_BOOL(event.event_pending, SCLPConsole),
- VMSTATE_UINT8_ARRAY(iov, SCLPConsole, SIZE_BUFFER_VT220),
- VMSTATE_UINT32(iov_sclp, SCLPConsole),
- VMSTATE_UINT32(iov_bs, SCLPConsole),
- VMSTATE_UINT32(iov_data_len, SCLPConsole),
- VMSTATE_UINT32(iov_sclp_rest, SCLPConsole),
- VMSTATE_END_OF_LIST()
- }
-};
-
-/* qemu object creation and initialization functions */
-
-/* tell character layer our call-back functions */
-
-static int console_init(SCLPEvent *event)
-{
- static bool console_available;
-
- SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event);
-
- if (console_available) {
- error_report("Multiple VT220 operator consoles are not supported");
- return -1;
- }
- console_available = true;
- if (scon->chr) {
- qemu_chr_add_handlers(scon->chr, chr_can_read,
- chr_read, NULL, scon);
- }
-
- return 0;
-}
-
-static void console_reset(DeviceState *dev)
-{
- SCLPEvent *event = SCLP_EVENT(dev);
- SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event);
-
- event->event_pending = false;
- scon->iov_sclp = 0;
- scon->iov_bs = 0;
- scon->iov_data_len = 0;
- scon->iov_sclp_rest = 0;
- scon->notify = false;
-}
-
-static int console_exit(SCLPEvent *event)
-{
- return 0;
-}
-
-static Property console_properties[] = {
- DEFINE_PROP_CHR("chardev", SCLPConsole, chr),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void console_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- SCLPEventClass *ec = SCLP_EVENT_CLASS(klass);
-
- dc->props = console_properties;
- dc->reset = console_reset;
- dc->vmsd = &vmstate_sclpconsole;
- ec->init = console_init;
- ec->exit = console_exit;
- ec->get_send_mask = send_mask;
- ec->get_receive_mask = receive_mask;
- ec->can_handle_event = can_handle_event;
- ec->read_event_data = read_event_data;
- ec->write_event_data = write_event_data;
- set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
-}
-
-static const TypeInfo sclp_console_info = {
- .name = "sclpconsole",
- .parent = TYPE_SCLP_EVENT,
- .instance_size = sizeof(SCLPConsole),
- .class_init = console_class_init,
- .class_size = sizeof(SCLPEventClass),
-};
-
-static void register_types(void)
-{
- type_register_static(&sclp_console_info);
-}
-
-type_init(register_types)
diff --git a/qemu/hw/char/serial-isa.c b/qemu/hw/char/serial-isa.c
deleted file mode 100644
index 1594ec4db..000000000
--- a/qemu/hw/char/serial-isa.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * QEMU 16550A UART emulation
- *
- * Copyright (c) 2003-2004 Fabrice Bellard
- * Copyright (c) 2008 Citrix Systems, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * 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/char/serial.h"
-#include "hw/isa/isa.h"
-
-#define ISA_SERIAL(obj) OBJECT_CHECK(ISASerialState, (obj), TYPE_ISA_SERIAL)
-
-typedef struct ISASerialState {
- ISADevice parent_obj;
-
- uint32_t index;
- uint32_t iobase;
- uint32_t isairq;
- SerialState state;
-} ISASerialState;
-
-static const int isa_serial_io[MAX_SERIAL_PORTS] = {
- 0x3f8, 0x2f8, 0x3e8, 0x2e8
-};
-static const int isa_serial_irq[MAX_SERIAL_PORTS] = {
- 4, 3, 4, 3
-};
-
-static void serial_isa_realizefn(DeviceState *dev, Error **errp)
-{
- static int index;
- ISADevice *isadev = ISA_DEVICE(dev);
- ISASerialState *isa = ISA_SERIAL(dev);
- SerialState *s = &isa->state;
-
- if (isa->index == -1) {
- isa->index = index;
- }
- if (isa->index >= MAX_SERIAL_PORTS) {
- error_setg(errp, "Max. supported number of ISA serial ports is %d.",
- MAX_SERIAL_PORTS);
- return;
- }
- if (isa->iobase == -1) {
- isa->iobase = isa_serial_io[isa->index];
- }
- if (isa->isairq == -1) {
- isa->isairq = isa_serial_irq[isa->index];
- }
- index++;
-
- s->baudbase = 115200;
- isa_init_irq(isadev, &s->irq, isa->isairq);
- serial_realize_core(s, errp);
- qdev_set_legacy_instance_id(dev, isa->iobase, 3);
-
- memory_region_init_io(&s->io, OBJECT(isa), &serial_io_ops, s, "serial", 8);
- isa_register_ioport(isadev, &s->io, isa->iobase);
-}
-
-static const VMStateDescription vmstate_isa_serial = {
- .name = "serial",
- .version_id = 3,
- .minimum_version_id = 2,
- .fields = (VMStateField[]) {
- VMSTATE_STRUCT(state, ISASerialState, 0, vmstate_serial, SerialState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static Property serial_isa_properties[] = {
- DEFINE_PROP_UINT32("index", ISASerialState, index, -1),
- DEFINE_PROP_UINT32("iobase", ISASerialState, iobase, -1),
- DEFINE_PROP_UINT32("irq", ISASerialState, isairq, -1),
- DEFINE_PROP_CHR("chardev", ISASerialState, state.chr),
- DEFINE_PROP_UINT32("wakeup", ISASerialState, state.wakeup, 0),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void serial_isa_class_initfn(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->realize = serial_isa_realizefn;
- dc->vmsd = &vmstate_isa_serial;
- dc->props = serial_isa_properties;
- set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
-}
-
-static const TypeInfo serial_isa_info = {
- .name = TYPE_ISA_SERIAL,
- .parent = TYPE_ISA_DEVICE,
- .instance_size = sizeof(ISASerialState),
- .class_init = serial_isa_class_initfn,
-};
-
-static void serial_register_types(void)
-{
- type_register_static(&serial_isa_info);
-}
-
-type_init(serial_register_types)
-
-static void serial_isa_init(ISABus *bus, int index, CharDriverState *chr)
-{
- DeviceState *dev;
- ISADevice *isadev;
-
- isadev = isa_create(bus, TYPE_ISA_SERIAL);
- dev = DEVICE(isadev);
- qdev_prop_set_uint32(dev, "index", index);
- qdev_prop_set_chr(dev, "chardev", chr);
- qdev_init_nofail(dev);
-}
-
-void serial_hds_isa_init(ISABus *bus, int n)
-{
- int i;
-
- assert(n <= MAX_SERIAL_PORTS);
-
- for (i = 0; i < n; ++i) {
- if (serial_hds[i]) {
- serial_isa_init(bus, i, serial_hds[i]);
- }
- }
-}
diff --git a/qemu/hw/char/serial-pci.c b/qemu/hw/char/serial-pci.c
deleted file mode 100644
index 303104dd1..000000000
--- a/qemu/hw/char/serial-pci.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * QEMU 16550A UART emulation
- *
- * Copyright (c) 2003-2004 Fabrice Bellard
- * Copyright (c) 2008 Citrix Systems, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-/* see docs/specs/pci-serial.txt */
-
-#include "qemu/osdep.h"
-#include "qapi/error.h"
-#include "hw/char/serial.h"
-#include "hw/pci/pci.h"
-
-#define PCI_SERIAL_MAX_PORTS 4
-
-typedef struct PCISerialState {
- PCIDevice dev;
- SerialState state;
- uint8_t prog_if;
-} PCISerialState;
-
-typedef struct PCIMultiSerialState {
- PCIDevice dev;
- MemoryRegion iobar;
- uint32_t ports;
- char *name[PCI_SERIAL_MAX_PORTS];
- SerialState state[PCI_SERIAL_MAX_PORTS];
- uint32_t level[PCI_SERIAL_MAX_PORTS];
- qemu_irq *irqs;
- uint8_t prog_if;
-} PCIMultiSerialState;
-
-static void multi_serial_pci_exit(PCIDevice *dev);
-
-static void serial_pci_realize(PCIDevice *dev, Error **errp)
-{
- PCISerialState *pci = DO_UPCAST(PCISerialState, dev, dev);
- SerialState *s = &pci->state;
- Error *err = NULL;
-
- s->baudbase = 115200;
- serial_realize_core(s, &err);
- if (err != NULL) {
- error_propagate(errp, err);
- return;
- }
-
- pci->dev.config[PCI_CLASS_PROG] = pci->prog_if;
- pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
- s->irq = pci_allocate_irq(&pci->dev);
-
- memory_region_init_io(&s->io, OBJECT(pci), &serial_io_ops, s, "serial", 8);
- pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
-}
-
-static void multi_serial_irq_mux(void *opaque, int n, int level)
-{
- PCIMultiSerialState *pci = opaque;
- int i, pending = 0;
-
- pci->level[n] = level;
- for (i = 0; i < pci->ports; i++) {
- if (pci->level[i]) {
- pending = 1;
- }
- }
- pci_set_irq(&pci->dev, pending);
-}
-
-static void multi_serial_pci_realize(PCIDevice *dev, Error **errp)
-{
- PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
- PCIMultiSerialState *pci = DO_UPCAST(PCIMultiSerialState, dev, dev);
- SerialState *s;
- Error *err = NULL;
- int i, nr_ports = 0;
-
- switch (pc->device_id) {
- case 0x0003:
- nr_ports = 2;
- break;
- case 0x0004:
- nr_ports = 4;
- break;
- }
- assert(nr_ports > 0);
- assert(nr_ports <= PCI_SERIAL_MAX_PORTS);
-
- pci->dev.config[PCI_CLASS_PROG] = pci->prog_if;
- pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
- memory_region_init(&pci->iobar, OBJECT(pci), "multiserial", 8 * nr_ports);
- pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->iobar);
- pci->irqs = qemu_allocate_irqs(multi_serial_irq_mux, pci,
- nr_ports);
-
- for (i = 0; i < nr_ports; i++) {
- s = pci->state + i;
- s->baudbase = 115200;
- serial_realize_core(s, &err);
- if (err != NULL) {
- error_propagate(errp, err);
- multi_serial_pci_exit(dev);
- return;
- }
- s->irq = pci->irqs[i];
- pci->name[i] = g_strdup_printf("uart #%d", i+1);
- memory_region_init_io(&s->io, OBJECT(pci), &serial_io_ops, s,
- pci->name[i], 8);
- memory_region_add_subregion(&pci->iobar, 8 * i, &s->io);
- pci->ports++;
- }
-}
-
-static void serial_pci_exit(PCIDevice *dev)
-{
- PCISerialState *pci = DO_UPCAST(PCISerialState, dev, dev);
- SerialState *s = &pci->state;
-
- serial_exit_core(s);
- qemu_free_irq(s->irq);
-}
-
-static void multi_serial_pci_exit(PCIDevice *dev)
-{
- PCIMultiSerialState *pci = DO_UPCAST(PCIMultiSerialState, dev, dev);
- SerialState *s;
- int i;
-
- for (i = 0; i < pci->ports; i++) {
- s = pci->state + i;
- serial_exit_core(s);
- memory_region_del_subregion(&pci->iobar, &s->io);
- g_free(pci->name[i]);
- }
- qemu_free_irqs(pci->irqs, pci->ports);
-}
-
-static const VMStateDescription vmstate_pci_serial = {
- .name = "pci-serial",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_PCI_DEVICE(dev, PCISerialState),
- VMSTATE_STRUCT(state, PCISerialState, 0, vmstate_serial, SerialState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_pci_multi_serial = {
- .name = "pci-serial-multi",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_PCI_DEVICE(dev, PCIMultiSerialState),
- VMSTATE_STRUCT_ARRAY(state, PCIMultiSerialState, PCI_SERIAL_MAX_PORTS,
- 0, vmstate_serial, SerialState),
- VMSTATE_UINT32_ARRAY(level, PCIMultiSerialState, PCI_SERIAL_MAX_PORTS),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static Property serial_pci_properties[] = {
- DEFINE_PROP_CHR("chardev", PCISerialState, state.chr),
- DEFINE_PROP_UINT8("prog_if", PCISerialState, prog_if, 0x02),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static Property multi_2x_serial_pci_properties[] = {
- DEFINE_PROP_CHR("chardev1", PCIMultiSerialState, state[0].chr),
- DEFINE_PROP_CHR("chardev2", PCIMultiSerialState, state[1].chr),
- DEFINE_PROP_UINT8("prog_if", PCIMultiSerialState, prog_if, 0x02),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static Property multi_4x_serial_pci_properties[] = {
- DEFINE_PROP_CHR("chardev1", PCIMultiSerialState, state[0].chr),
- DEFINE_PROP_CHR("chardev2", PCIMultiSerialState, state[1].chr),
- DEFINE_PROP_CHR("chardev3", PCIMultiSerialState, state[2].chr),
- DEFINE_PROP_CHR("chardev4", PCIMultiSerialState, state[3].chr),
- DEFINE_PROP_UINT8("prog_if", PCIMultiSerialState, prog_if, 0x02),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void serial_pci_class_initfn(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass);
- pc->realize = serial_pci_realize;
- pc->exit = serial_pci_exit;
- pc->vendor_id = PCI_VENDOR_ID_REDHAT;
- pc->device_id = PCI_DEVICE_ID_REDHAT_SERIAL;
- pc->revision = 1;
- pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL;
- dc->vmsd = &vmstate_pci_serial;
- dc->props = serial_pci_properties;
- set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
-}
-
-static void multi_2x_serial_pci_class_initfn(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass);
- pc->realize = multi_serial_pci_realize;
- pc->exit = multi_serial_pci_exit;
- pc->vendor_id = PCI_VENDOR_ID_REDHAT;
- pc->device_id = PCI_DEVICE_ID_REDHAT_SERIAL2;
- pc->revision = 1;
- pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL;
- dc->vmsd = &vmstate_pci_multi_serial;
- dc->props = multi_2x_serial_pci_properties;
- set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
-}
-
-static void multi_4x_serial_pci_class_initfn(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass);
- pc->realize = multi_serial_pci_realize;
- pc->exit = multi_serial_pci_exit;
- pc->vendor_id = PCI_VENDOR_ID_REDHAT;
- pc->device_id = PCI_DEVICE_ID_REDHAT_SERIAL4;
- pc->revision = 1;
- pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL;
- dc->vmsd = &vmstate_pci_multi_serial;
- dc->props = multi_4x_serial_pci_properties;
- set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
-}
-
-static const TypeInfo serial_pci_info = {
- .name = "pci-serial",
- .parent = TYPE_PCI_DEVICE,
- .instance_size = sizeof(PCISerialState),
- .class_init = serial_pci_class_initfn,
-};
-
-static const TypeInfo multi_2x_serial_pci_info = {
- .name = "pci-serial-2x",
- .parent = TYPE_PCI_DEVICE,
- .instance_size = sizeof(PCIMultiSerialState),
- .class_init = multi_2x_serial_pci_class_initfn,
-};
-
-static const TypeInfo multi_4x_serial_pci_info = {
- .name = "pci-serial-4x",
- .parent = TYPE_PCI_DEVICE,
- .instance_size = sizeof(PCIMultiSerialState),
- .class_init = multi_4x_serial_pci_class_initfn,
-};
-
-static void serial_pci_register_types(void)
-{
- type_register_static(&serial_pci_info);
- type_register_static(&multi_2x_serial_pci_info);
- type_register_static(&multi_4x_serial_pci_info);
-}
-
-type_init(serial_pci_register_types)
diff --git a/qemu/hw/char/serial.c b/qemu/hw/char/serial.c
deleted file mode 100644
index 6d815b5c6..000000000
--- a/qemu/hw/char/serial.c
+++ /dev/null
@@ -1,966 +0,0 @@
-/*
- * QEMU 16550A UART emulation
- *
- * Copyright (c) 2003-2004 Fabrice Bellard
- * Copyright (c) 2008 Citrix Systems, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * 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"
-
-//#define DEBUG_SERIAL
-
-#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
-
-#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */
-#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */
-#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */
-#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */
-
-#define UART_IIR_NO_INT 0x01 /* No interrupts pending */
-#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */
-
-#define UART_IIR_MSI 0x00 /* Modem status interrupt */
-#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */
-#define UART_IIR_RDI 0x04 /* Receiver data interrupt */
-#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */
-#define UART_IIR_CTI 0x0C /* Character Timeout Indication */
-
-#define UART_IIR_FENF 0x80 /* Fifo enabled, but not functionning */
-#define UART_IIR_FE 0xC0 /* Fifo enabled */
-
-/*
- * These are the definitions for the Modem Control Register
- */
-#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
-#define UART_MCR_OUT2 0x08 /* Out2 complement */
-#define UART_MCR_OUT1 0x04 /* Out1 complement */
-#define UART_MCR_RTS 0x02 /* RTS complement */
-#define UART_MCR_DTR 0x01 /* DTR complement */
-
-/*
- * These are the definitions for the Modem Status Register
- */
-#define UART_MSR_DCD 0x80 /* Data Carrier Detect */
-#define UART_MSR_RI 0x40 /* Ring Indicator */
-#define UART_MSR_DSR 0x20 /* Data Set Ready */
-#define UART_MSR_CTS 0x10 /* Clear to Send */
-#define UART_MSR_DDCD 0x08 /* Delta DCD */
-#define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */
-#define UART_MSR_DDSR 0x02 /* Delta DSR */
-#define UART_MSR_DCTS 0x01 /* Delta CTS */
-#define UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */
-
-#define UART_LSR_TEMT 0x40 /* Transmitter empty */
-#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
-#define UART_LSR_BI 0x10 /* Break interrupt indicator */
-#define UART_LSR_FE 0x08 /* Frame error indicator */
-#define UART_LSR_PE 0x04 /* Parity error indicator */
-#define UART_LSR_OE 0x02 /* Overrun error indicator */
-#define UART_LSR_DR 0x01 /* Receiver data ready */
-#define UART_LSR_INT_ANY 0x1E /* Any of the lsr-interrupt-triggering status bits */
-
-/* Interrupt trigger levels. The byte-counts are for 16550A - in newer UARTs the byte-count for each ITL is higher. */
-
-#define UART_FCR_ITL_1 0x00 /* 1 byte ITL */
-#define UART_FCR_ITL_2 0x40 /* 4 bytes ITL */
-#define UART_FCR_ITL_3 0x80 /* 8 bytes ITL */
-#define UART_FCR_ITL_4 0xC0 /* 14 bytes ITL */
-
-#define UART_FCR_DMS 0x08 /* DMA Mode Select */
-#define UART_FCR_XFR 0x04 /* XMIT Fifo Reset */
-#define UART_FCR_RFR 0x02 /* RCVR Fifo Reset */
-#define UART_FCR_FE 0x01 /* FIFO Enable */
-
-#define MAX_XMIT_RETRY 4
-
-#ifdef DEBUG_SERIAL
-#define DPRINTF(fmt, ...) \
-do { fprintf(stderr, "serial: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) \
-do {} while (0)
-#endif
-
-static void serial_receive1(void *opaque, const uint8_t *buf, int size);
-
-static inline void recv_fifo_put(SerialState *s, uint8_t chr)
-{
- /* Receive overruns do not overwrite FIFO contents. */
- if (!fifo8_is_full(&s->recv_fifo)) {
- fifo8_push(&s->recv_fifo, chr);
- } else {
- s->lsr |= UART_LSR_OE;
- }
-}
-
-static void serial_update_irq(SerialState *s)
-{
- uint8_t tmp_iir = UART_IIR_NO_INT;
-
- if ((s->ier & UART_IER_RLSI) && (s->lsr & UART_LSR_INT_ANY)) {
- tmp_iir = UART_IIR_RLSI;
- } else if ((s->ier & UART_IER_RDI) && s->timeout_ipending) {
- /* Note that(s->ier & UART_IER_RDI) can mask this interrupt,
- * this is not in the specification but is observed on existing
- * hardware. */
- tmp_iir = UART_IIR_CTI;
- } else if ((s->ier & UART_IER_RDI) && (s->lsr & UART_LSR_DR) &&
- (!(s->fcr & UART_FCR_FE) ||
- s->recv_fifo.num >= s->recv_fifo_itl)) {
- tmp_iir = UART_IIR_RDI;
- } else if ((s->ier & UART_IER_THRI) && s->thr_ipending) {
- tmp_iir = UART_IIR_THRI;
- } else if ((s->ier & UART_IER_MSI) && (s->msr & UART_MSR_ANY_DELTA)) {
- tmp_iir = UART_IIR_MSI;
- }
-
- s->iir = tmp_iir | (s->iir & 0xF0);
-
- if (tmp_iir != UART_IIR_NO_INT) {
- qemu_irq_raise(s->irq);
- } else {
- qemu_irq_lower(s->irq);
- }
-}
-
-static void serial_update_parameters(SerialState *s)
-{
- int speed, parity, data_bits, stop_bits, frame_size;
- QEMUSerialSetParams ssp;
-
- if (s->divider == 0)
- return;
-
- /* Start bit. */
- frame_size = 1;
- if (s->lcr & 0x08) {
- /* Parity bit. */
- frame_size++;
- if (s->lcr & 0x10)
- parity = 'E';
- else
- parity = 'O';
- } else {
- parity = 'N';
- }
- if (s->lcr & 0x04)
- stop_bits = 2;
- else
- stop_bits = 1;
-
- data_bits = (s->lcr & 0x03) + 5;
- frame_size += data_bits + stop_bits;
- speed = s->baudbase / s->divider;
- ssp.speed = speed;
- ssp.parity = parity;
- ssp.data_bits = data_bits;
- ssp.stop_bits = stop_bits;
- 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",
- speed, parity, data_bits, stop_bits);
-}
-
-static void serial_update_msl(SerialState *s)
-{
- uint8_t omsr;
- int flags;
-
- timer_del(s->modem_status_poll);
-
- if (qemu_chr_fe_ioctl(s->chr,CHR_IOCTL_SERIAL_GET_TIOCM, &flags) == -ENOTSUP) {
- s->poll_msl = -1;
- return;
- }
-
- omsr = s->msr;
-
- s->msr = (flags & CHR_TIOCM_CTS) ? s->msr | UART_MSR_CTS : s->msr & ~UART_MSR_CTS;
- s->msr = (flags & CHR_TIOCM_DSR) ? s->msr | UART_MSR_DSR : s->msr & ~UART_MSR_DSR;
- s->msr = (flags & CHR_TIOCM_CAR) ? s->msr | UART_MSR_DCD : s->msr & ~UART_MSR_DCD;
- s->msr = (flags & CHR_TIOCM_RI) ? s->msr | UART_MSR_RI : s->msr & ~UART_MSR_RI;
-
- if (s->msr != omsr) {
- /* Set delta bits */
- s->msr = s->msr | ((s->msr >> 4) ^ (omsr >> 4));
- /* UART_MSR_TERI only if change was from 1 -> 0 */
- if ((s->msr & UART_MSR_TERI) && !(omsr & UART_MSR_RI))
- s->msr &= ~UART_MSR_TERI;
- serial_update_irq(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) +
- NANOSECONDS_PER_SECOND / 100);
- }
-}
-
-static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
-{
- SerialState *s = opaque;
-
- do {
- assert(!(s->lsr & UART_LSR_TEMT));
- if (s->tsr_retry <= 0) {
- assert(!(s->lsr & UART_LSR_THRE));
-
- if (s->fcr & UART_FCR_FE) {
- assert(!fifo8_is_empty(&s->xmit_fifo));
- s->tsr = fifo8_pop(&s->xmit_fifo);
- if (!s->xmit_fifo.num) {
- s->lsr |= UART_LSR_THRE;
- }
- } else {
- s->tsr = s->thr;
- s->lsr |= UART_LSR_THRE;
- }
- if ((s->lsr & UART_LSR_THRE) && !s->thr_ipending) {
- s->thr_ipending = 1;
- serial_update_irq(s);
- }
- }
-
- 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) {
- s->tsr_retry++;
- return FALSE;
- }
- s->tsr_retry = 0;
- } else {
- s->tsr_retry = 0;
- }
-
- /* Transmit another byte if it is already available. It is only
- possible when FIFO is enabled and not empty. */
- } while (!(s->lsr & UART_LSR_THRE));
-
- 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 */
-static void serial_write_fcr(SerialState *s, uint8_t val)
-{
- /* Set fcr - val only has the bits that are supposed to "stick" */
- s->fcr = val;
-
- if (val & UART_FCR_FE) {
- s->iir |= UART_IIR_FE;
- /* Set recv_fifo trigger Level */
- switch (val & 0xC0) {
- case UART_FCR_ITL_1:
- s->recv_fifo_itl = 1;
- break;
- case UART_FCR_ITL_2:
- s->recv_fifo_itl = 4;
- break;
- case UART_FCR_ITL_3:
- s->recv_fifo_itl = 8;
- break;
- case UART_FCR_ITL_4:
- s->recv_fifo_itl = 14;
- break;
- }
- } else {
- s->iir &= ~UART_IIR_FE;
- }
-}
-
-static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
- unsigned size)
-{
- SerialState *s = opaque;
-
- addr &= 7;
- DPRINTF("write addr=0x%" HWADDR_PRIx " val=0x%" PRIx64 "\n", addr, val);
- switch(addr) {
- default:
- case 0:
- if (s->lcr & UART_LCR_DLAB) {
- s->divider = (s->divider & 0xff00) | val;
- serial_update_parameters(s);
- } else {
- s->thr = (uint8_t) val;
- if(s->fcr & UART_FCR_FE) {
- /* xmit overruns overwrite data, so make space if needed */
- if (fifo8_is_full(&s->xmit_fifo)) {
- fifo8_pop(&s->xmit_fifo);
- }
- fifo8_push(&s->xmit_fifo, s->thr);
- }
- s->thr_ipending = 0;
- 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);
- }
- }
- break;
- case 1:
- if (s->lcr & UART_LCR_DLAB) {
- s->divider = (s->divider & 0x00ff) | (val << 8);
- serial_update_parameters(s);
- } else {
- uint8_t changed = (s->ier ^ val) & 0x0f;
- s->ier = val & 0x0f;
- /* If the backend device is a real serial port, turn polling of the modem
- * status lines on physical port on or off depending on UART_IER_MSI state.
- */
- if ((changed & UART_IER_MSI) && s->poll_msl >= 0) {
- if (s->ier & UART_IER_MSI) {
- s->poll_msl = 1;
- serial_update_msl(s);
- } else {
- timer_del(s->modem_status_poll);
- s->poll_msl = 0;
- }
- }
-
- /* Turning on the THRE interrupt on IER can trigger the interrupt
- * if LSR.THRE=1, even if it had been masked before by reading IIR.
- * This is not in the datasheet, but Windows relies on it. It is
- * unclear if THRE has to be resampled every time THRI becomes
- * 1, or only on the rising edge. Bochs does the latter, and Windows
- * always toggles IER to all zeroes and back to all ones, so do the
- * same.
- *
- * If IER.THRI is zero, thr_ipending is not used. Set it to zero
- * so that the thr_ipending subsection is not migrated.
- */
- if (changed & UART_IER_THRI) {
- if ((s->ier & UART_IER_THRI) && (s->lsr & UART_LSR_THRE)) {
- s->thr_ipending = 1;
- } else {
- s->thr_ipending = 0;
- }
- }
-
- if (changed) {
- serial_update_irq(s);
- }
- }
- break;
- case 2:
- /* Did the enable/disable flag change? If so, make sure FIFOs get flushed */
- if ((val ^ s->fcr) & UART_FCR_FE) {
- val |= UART_FCR_XFR | UART_FCR_RFR;
- }
-
- /* FIFO clear */
-
- if (val & UART_FCR_RFR) {
- s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
- timer_del(s->fifo_timeout_timer);
- s->timeout_ipending = 0;
- fifo8_reset(&s->recv_fifo);
- }
-
- if (val & UART_FCR_XFR) {
- s->lsr |= UART_LSR_THRE;
- s->thr_ipending = 1;
- fifo8_reset(&s->xmit_fifo);
- }
-
- serial_write_fcr(s, val & 0xC9);
- serial_update_irq(s);
- break;
- case 3:
- {
- int break_enable;
- s->lcr = val;
- serial_update_parameters(s);
- break_enable = (val >> 6) & 1;
- if (break_enable != s->last_break_enable) {
- s->last_break_enable = break_enable;
- qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
- &break_enable);
- }
- }
- break;
- case 4:
- {
- int flags;
- int old_mcr = s->mcr;
- s->mcr = val & 0x1f;
- if (val & UART_MCR_LOOP)
- break;
-
- if (s->poll_msl >= 0 && old_mcr != s->mcr) {
-
- qemu_chr_fe_ioctl(s->chr,CHR_IOCTL_SERIAL_GET_TIOCM, &flags);
-
- flags &= ~(CHR_TIOCM_RTS | CHR_TIOCM_DTR);
-
- if (val & UART_MCR_RTS)
- flags |= CHR_TIOCM_RTS;
- if (val & UART_MCR_DTR)
- flags |= CHR_TIOCM_DTR;
-
- qemu_chr_fe_ioctl(s->chr,CHR_IOCTL_SERIAL_SET_TIOCM, &flags);
- /* Update the modem status after a one-character-send wait-time, since there may be a response
- from the device/computer at the other end of the serial line */
- timer_mod(s->modem_status_poll, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->char_transmit_time);
- }
- }
- break;
- case 5:
- break;
- case 6:
- break;
- case 7:
- s->scr = val;
- break;
- }
-}
-
-static uint64_t serial_ioport_read(void *opaque, hwaddr addr, unsigned size)
-{
- SerialState *s = opaque;
- uint32_t ret;
-
- addr &= 7;
- switch(addr) {
- default:
- case 0:
- if (s->lcr & UART_LCR_DLAB) {
- ret = s->divider & 0xff;
- } else {
- if(s->fcr & UART_FCR_FE) {
- ret = fifo8_is_empty(&s->recv_fifo) ?
- 0 : fifo8_pop(&s->recv_fifo);
- if (s->recv_fifo.num == 0) {
- s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
- } else {
- timer_mod(s->fifo_timeout_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->char_transmit_time * 4);
- }
- s->timeout_ipending = 0;
- } else {
- ret = s->rbr;
- s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
- }
- serial_update_irq(s);
- if (!(s->mcr & UART_MCR_LOOP)) {
- /* in loopback mode, don't receive any data */
- qemu_chr_accept_input(s->chr);
- }
- }
- break;
- case 1:
- if (s->lcr & UART_LCR_DLAB) {
- ret = (s->divider >> 8) & 0xff;
- } else {
- ret = s->ier;
- }
- break;
- case 2:
- ret = s->iir;
- if ((ret & UART_IIR_ID) == UART_IIR_THRI) {
- s->thr_ipending = 0;
- serial_update_irq(s);
- }
- break;
- case 3:
- ret = s->lcr;
- break;
- case 4:
- ret = s->mcr;
- break;
- case 5:
- ret = s->lsr;
- /* Clear break and overrun interrupts */
- if (s->lsr & (UART_LSR_BI|UART_LSR_OE)) {
- s->lsr &= ~(UART_LSR_BI|UART_LSR_OE);
- serial_update_irq(s);
- }
- break;
- case 6:
- if (s->mcr & UART_MCR_LOOP) {
- /* in loopback, the modem output pins are connected to the
- inputs */
- ret = (s->mcr & 0x0c) << 4;
- ret |= (s->mcr & 0x02) << 3;
- ret |= (s->mcr & 0x01) << 5;
- } else {
- if (s->poll_msl >= 0)
- serial_update_msl(s);
- ret = s->msr;
- /* Clear delta bits & msr int after read, if they were set */
- if (s->msr & UART_MSR_ANY_DELTA) {
- s->msr &= 0xF0;
- serial_update_irq(s);
- }
- }
- break;
- case 7:
- ret = s->scr;
- break;
- }
- DPRINTF("read addr=0x%" HWADDR_PRIx " val=0x%02x\n", addr, ret);
- return ret;
-}
-
-static int serial_can_receive(SerialState *s)
-{
- if(s->fcr & UART_FCR_FE) {
- if (s->recv_fifo.num < UART_FIFO_LENGTH) {
- /*
- * Advertise (fifo.itl - fifo.count) bytes when count < ITL, and 1
- * if above. If UART_FIFO_LENGTH - fifo.count is advertised the
- * effect will be to almost always fill the fifo completely before
- * the guest has a chance to respond, effectively overriding the ITL
- * that the guest has set.
- */
- return (s->recv_fifo.num <= s->recv_fifo_itl) ?
- s->recv_fifo_itl - s->recv_fifo.num : 1;
- } else {
- return 0;
- }
- } else {
- return !(s->lsr & UART_LSR_DR);
- }
-}
-
-static void serial_receive_break(SerialState *s)
-{
- s->rbr = 0;
- /* When the LSR_DR is set a null byte is pushed into the fifo */
- recv_fifo_put(s, '\0');
- s->lsr |= UART_LSR_BI | UART_LSR_DR;
- serial_update_irq(s);
-}
-
-/* There's data in recv_fifo and s->rbr has not been read for 4 char transmit times */
-static void fifo_timeout_int (void *opaque) {
- SerialState *s = opaque;
- if (s->recv_fifo.num) {
- s->timeout_ipending = 1;
- serial_update_irq(s);
- }
-}
-
-static int serial_can_receive1(void *opaque)
-{
- SerialState *s = opaque;
- return serial_can_receive(s);
-}
-
-static void serial_receive1(void *opaque, const uint8_t *buf, int size)
-{
- SerialState *s = opaque;
-
- if (s->wakeup) {
- qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
- }
- if(s->fcr & UART_FCR_FE) {
- int i;
- for (i = 0; i < size; i++) {
- recv_fifo_put(s, buf[i]);
- }
- s->lsr |= UART_LSR_DR;
- /* call the timeout receive callback in 4 char transmit time */
- timer_mod(s->fifo_timeout_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->char_transmit_time * 4);
- } else {
- if (s->lsr & UART_LSR_DR)
- s->lsr |= UART_LSR_OE;
- s->rbr = buf[0];
- s->lsr |= UART_LSR_DR;
- }
- serial_update_irq(s);
-}
-
-static void serial_event(void *opaque, int event)
-{
- SerialState *s = opaque;
- DPRINTF("event %x\n", event);
- if (event == CHR_EVENT_BREAK)
- serial_receive_break(s);
-}
-
-static void serial_pre_save(void *opaque)
-{
- SerialState *s = opaque;
- s->fcr_vmstate = s->fcr;
-}
-
-static int serial_pre_load(void *opaque)
-{
- SerialState *s = opaque;
- s->thr_ipending = -1;
- s->poll_msl = -1;
- return 0;
-}
-
-static int serial_post_load(void *opaque, int version_id)
-{
- SerialState *s = opaque;
-
- if (version_id < 3) {
- s->fcr_vmstate = 0;
- }
- if (s->thr_ipending == -1) {
- s->thr_ipending = ((s->iir & UART_IIR_ID) == UART_IIR_THRI);
- }
- s->last_break_enable = (s->lcr >> 6) & 1;
- /* Initialize fcr via setter to perform essential side-effects */
- serial_write_fcr(s, s->fcr_vmstate);
- serial_update_parameters(s);
- return 0;
-}
-
-static bool serial_thr_ipending_needed(void *opaque)
-{
- SerialState *s = opaque;
-
- if (s->ier & UART_IER_THRI) {
- bool expected_value = ((s->iir & UART_IIR_ID) == UART_IIR_THRI);
- return s->thr_ipending != expected_value;
- } else {
- /* LSR.THRE will be sampled again when the interrupt is
- * enabled. thr_ipending is not used in this case, do
- * not migrate it.
- */
- return false;
- }
-}
-
-static const VMStateDescription vmstate_serial_thr_ipending = {
- .name = "serial/thr_ipending",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = serial_thr_ipending_needed,
- .fields = (VMStateField[]) {
- VMSTATE_INT32(thr_ipending, SerialState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static bool serial_tsr_needed(void *opaque)
-{
- SerialState *s = (SerialState *)opaque;
- return s->tsr_retry != 0;
-}
-
-static const VMStateDescription vmstate_serial_tsr = {
- .name = "serial/tsr",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = serial_tsr_needed,
- .fields = (VMStateField[]) {
- VMSTATE_INT32(tsr_retry, SerialState),
- VMSTATE_UINT8(thr, SerialState),
- VMSTATE_UINT8(tsr, SerialState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static bool serial_recv_fifo_needed(void *opaque)
-{
- SerialState *s = (SerialState *)opaque;
- return !fifo8_is_empty(&s->recv_fifo);
-
-}
-
-static const VMStateDescription vmstate_serial_recv_fifo = {
- .name = "serial/recv_fifo",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = serial_recv_fifo_needed,
- .fields = (VMStateField[]) {
- VMSTATE_STRUCT(recv_fifo, SerialState, 1, vmstate_fifo8, Fifo8),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static bool serial_xmit_fifo_needed(void *opaque)
-{
- SerialState *s = (SerialState *)opaque;
- return !fifo8_is_empty(&s->xmit_fifo);
-}
-
-static const VMStateDescription vmstate_serial_xmit_fifo = {
- .name = "serial/xmit_fifo",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = serial_xmit_fifo_needed,
- .fields = (VMStateField[]) {
- VMSTATE_STRUCT(xmit_fifo, SerialState, 1, vmstate_fifo8, Fifo8),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static bool serial_fifo_timeout_timer_needed(void *opaque)
-{
- SerialState *s = (SerialState *)opaque;
- return timer_pending(s->fifo_timeout_timer);
-}
-
-static const VMStateDescription vmstate_serial_fifo_timeout_timer = {
- .name = "serial/fifo_timeout_timer",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = serial_fifo_timeout_timer_needed,
- .fields = (VMStateField[]) {
- VMSTATE_TIMER_PTR(fifo_timeout_timer, SerialState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static bool serial_timeout_ipending_needed(void *opaque)
-{
- SerialState *s = (SerialState *)opaque;
- return s->timeout_ipending != 0;
-}
-
-static const VMStateDescription vmstate_serial_timeout_ipending = {
- .name = "serial/timeout_ipending",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = serial_timeout_ipending_needed,
- .fields = (VMStateField[]) {
- VMSTATE_INT32(timeout_ipending, SerialState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static bool serial_poll_needed(void *opaque)
-{
- SerialState *s = (SerialState *)opaque;
- return s->poll_msl >= 0;
-}
-
-static const VMStateDescription vmstate_serial_poll = {
- .name = "serial/poll",
- .version_id = 1,
- .needed = serial_poll_needed,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_INT32(poll_msl, SerialState),
- VMSTATE_TIMER_PTR(modem_status_poll, SerialState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-const VMStateDescription vmstate_serial = {
- .name = "serial",
- .version_id = 3,
- .minimum_version_id = 2,
- .pre_save = serial_pre_save,
- .pre_load = serial_pre_load,
- .post_load = serial_post_load,
- .fields = (VMStateField[]) {
- VMSTATE_UINT16_V(divider, SerialState, 2),
- VMSTATE_UINT8(rbr, SerialState),
- VMSTATE_UINT8(ier, SerialState),
- VMSTATE_UINT8(iir, SerialState),
- VMSTATE_UINT8(lcr, SerialState),
- VMSTATE_UINT8(mcr, SerialState),
- VMSTATE_UINT8(lsr, SerialState),
- VMSTATE_UINT8(msr, SerialState),
- VMSTATE_UINT8(scr, SerialState),
- VMSTATE_UINT8_V(fcr_vmstate, SerialState, 3),
- VMSTATE_END_OF_LIST()
- },
- .subsections = (const VMStateDescription*[]) {
- &vmstate_serial_thr_ipending,
- &vmstate_serial_tsr,
- &vmstate_serial_recv_fifo,
- &vmstate_serial_xmit_fifo,
- &vmstate_serial_fifo_timeout_timer,
- &vmstate_serial_timeout_ipending,
- &vmstate_serial_poll,
- NULL
- }
-};
-
-static void serial_reset(void *opaque)
-{
- SerialState *s = opaque;
-
- s->rbr = 0;
- s->ier = 0;
- s->iir = UART_IIR_NO_INT;
- s->lcr = 0;
- s->lsr = UART_LSR_TEMT | UART_LSR_THRE;
- s->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
- /* Default to 9600 baud, 1 start bit, 8 data bits, 1 stop bit, no parity. */
- s->divider = 0x0C;
- s->mcr = UART_MCR_OUT2;
- s->scr = 0;
- s->tsr_retry = 0;
- s->char_transmit_time = (NANOSECONDS_PER_SECOND / 9600) * 10;
- s->poll_msl = 0;
-
- s->timeout_ipending = 0;
- timer_del(s->fifo_timeout_timer);
- timer_del(s->modem_status_poll);
-
- fifo8_reset(&s->recv_fifo);
- fifo8_reset(&s->xmit_fifo);
-
- s->last_xmit_ts = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-
- s->thr_ipending = 0;
- s->last_break_enable = 0;
- qemu_irq_lower(s->irq);
-
- serial_update_msl(s);
- s->msr &= ~UART_MSR_ANY_DELTA;
-}
-
-void serial_realize_core(SerialState *s, Error **errp)
-{
- if (!s->chr) {
- error_setg(errp, "Can't create serial device, empty char device");
- return;
- }
-
- s->modem_status_poll = timer_new_ns(QEMU_CLOCK_VIRTUAL, (QEMUTimerCB *) serial_update_msl, s);
-
- s->fifo_timeout_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, (QEMUTimerCB *) fifo_timeout_int, s);
- qemu_register_reset(serial_reset, s);
-
- qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
- serial_event, s);
- fifo8_create(&s->recv_fifo, UART_FIFO_LENGTH);
- fifo8_create(&s->xmit_fifo, UART_FIFO_LENGTH);
- serial_reset(s);
-}
-
-void serial_exit_core(SerialState *s)
-{
- qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
- qemu_unregister_reset(serial_reset, s);
-}
-
-/* Change the main reference oscillator frequency. */
-void serial_set_frequency(SerialState *s, uint32_t frequency)
-{
- s->baudbase = frequency;
- serial_update_parameters(s);
-}
-
-const MemoryRegionOps serial_io_ops = {
- .read = serial_ioport_read,
- .write = serial_ioport_write,
- .impl = {
- .min_access_size = 1,
- .max_access_size = 1,
- },
- .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-SerialState *serial_init(int base, qemu_irq irq, int baudbase,
- CharDriverState *chr, MemoryRegion *system_io)
-{
- SerialState *s;
-
- s = g_malloc0(sizeof(SerialState));
-
- s->irq = irq;
- s->baudbase = baudbase;
- s->chr = chr;
- serial_realize_core(s, &error_fatal);
-
- vmstate_register(NULL, base, &vmstate_serial, s);
-
- memory_region_init_io(&s->io, NULL, &serial_io_ops, s, "serial", 8);
- memory_region_add_subregion(system_io, base, &s->io);
-
- return s;
-}
-
-/* Memory mapped interface */
-static uint64_t serial_mm_read(void *opaque, hwaddr addr,
- unsigned size)
-{
- SerialState *s = opaque;
- return serial_ioport_read(s, addr >> s->it_shift, 1);
-}
-
-static void serial_mm_write(void *opaque, hwaddr addr,
- uint64_t value, unsigned size)
-{
- SerialState *s = opaque;
- value &= ~0u >> (32 - (size * 8));
- serial_ioport_write(s, addr >> s->it_shift, value, 1);
-}
-
-static const MemoryRegionOps serial_mm_ops[3] = {
- [DEVICE_NATIVE_ENDIAN] = {
- .read = serial_mm_read,
- .write = serial_mm_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
- },
- [DEVICE_LITTLE_ENDIAN] = {
- .read = serial_mm_read,
- .write = serial_mm_write,
- .endianness = DEVICE_LITTLE_ENDIAN,
- },
- [DEVICE_BIG_ENDIAN] = {
- .read = serial_mm_read,
- .write = serial_mm_write,
- .endianness = DEVICE_BIG_ENDIAN,
- },
-};
-
-SerialState *serial_mm_init(MemoryRegion *address_space,
- hwaddr base, int it_shift,
- qemu_irq irq, int baudbase,
- CharDriverState *chr, enum device_endian end)
-{
- SerialState *s;
-
- s = g_malloc0(sizeof(SerialState));
-
- s->it_shift = it_shift;
- s->irq = irq;
- s->baudbase = baudbase;
- s->chr = chr;
-
- 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,
- "serial", 8 << it_shift);
- memory_region_add_subregion(address_space, base, &s->io);
- return s;
-}
diff --git a/qemu/hw/char/sh_serial.c b/qemu/hw/char/sh_serial.c
deleted file mode 100644
index 4c55dcb7d..000000000
--- a/qemu/hw/char/sh_serial.c
+++ /dev/null
@@ -1,409 +0,0 @@
-/*
- * QEMU SCI/SCIF serial port emulation
- *
- * Copyright (c) 2007 Magnus Damm
- *
- * Based on serial.c - QEMU 16450 UART emulation
- * Copyright (c) 2003-2004 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * 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"
-#include "exec/address-spaces.h"
-
-//#define DEBUG_SERIAL
-
-#define SH_SERIAL_FLAG_TEND (1 << 0)
-#define SH_SERIAL_FLAG_TDE (1 << 1)
-#define SH_SERIAL_FLAG_RDF (1 << 2)
-#define SH_SERIAL_FLAG_BRK (1 << 3)
-#define SH_SERIAL_FLAG_DR (1 << 4)
-
-#define SH_RX_FIFO_LENGTH (16)
-
-typedef struct {
- MemoryRegion iomem;
- MemoryRegion iomem_p4;
- MemoryRegion iomem_a7;
- uint8_t smr;
- uint8_t brr;
- uint8_t scr;
- uint8_t dr; /* ftdr / tdr */
- uint8_t sr; /* fsr / ssr */
- uint16_t fcr;
- uint8_t sptr;
-
- uint8_t rx_fifo[SH_RX_FIFO_LENGTH]; /* frdr / rdr */
- uint8_t rx_cnt;
- uint8_t rx_tail;
- uint8_t rx_head;
-
- int freq;
- int feat;
- int flags;
- int rtrg;
-
- CharDriverState *chr;
-
- qemu_irq eri;
- qemu_irq rxi;
- qemu_irq txi;
- qemu_irq tei;
- qemu_irq bri;
-} sh_serial_state;
-
-static void sh_serial_clear_fifo(sh_serial_state * s)
-{
- memset(s->rx_fifo, 0, SH_RX_FIFO_LENGTH);
- s->rx_cnt = 0;
- s->rx_head = 0;
- s->rx_tail = 0;
-}
-
-static void sh_serial_write(void *opaque, hwaddr offs,
- uint64_t val, unsigned size)
-{
- sh_serial_state *s = opaque;
- unsigned char ch;
-
-#ifdef DEBUG_SERIAL
- printf("sh_serial: write offs=0x%02x val=0x%02x\n",
- offs, val);
-#endif
- switch(offs) {
- case 0x00: /* SMR */
- s->smr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0x7b : 0xff);
- return;
- case 0x04: /* BRR */
- s->brr = val;
- return;
- case 0x08: /* SCR */
- /* TODO : For SH7751, SCIF mask should be 0xfb. */
- s->scr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0xfa : 0xff);
- if (!(val & (1 << 5)))
- s->flags |= SH_SERIAL_FLAG_TEND;
- if ((s->feat & SH_SERIAL_FEAT_SCIF) && s->txi) {
- qemu_set_irq(s->txi, val & (1 << 7));
- }
- if (!(val & (1 << 6))) {
- qemu_set_irq(s->rxi, 0);
- }
- return;
- case 0x0c: /* FTDR / TDR */
- if (s->chr) {
- ch = val;
- qemu_chr_fe_write(s->chr, &ch, 1);
- }
- s->dr = val;
- s->flags &= ~SH_SERIAL_FLAG_TDE;
- return;
-#if 0
- case 0x14: /* FRDR / RDR */
- ret = 0;
- break;
-#endif
- }
- if (s->feat & SH_SERIAL_FEAT_SCIF) {
- switch(offs) {
- case 0x10: /* FSR */
- if (!(val & (1 << 6)))
- s->flags &= ~SH_SERIAL_FLAG_TEND;
- if (!(val & (1 << 5)))
- s->flags &= ~SH_SERIAL_FLAG_TDE;
- if (!(val & (1 << 4)))
- s->flags &= ~SH_SERIAL_FLAG_BRK;
- if (!(val & (1 << 1)))
- s->flags &= ~SH_SERIAL_FLAG_RDF;
- if (!(val & (1 << 0)))
- s->flags &= ~SH_SERIAL_FLAG_DR;
-
- if (!(val & (1 << 1)) || !(val & (1 << 0))) {
- if (s->rxi) {
- qemu_set_irq(s->rxi, 0);
- }
- }
- return;
- case 0x18: /* FCR */
- s->fcr = val;
- switch ((val >> 6) & 3) {
- case 0:
- s->rtrg = 1;
- break;
- case 1:
- s->rtrg = 4;
- break;
- case 2:
- s->rtrg = 8;
- break;
- case 3:
- s->rtrg = 14;
- break;
- }
- if (val & (1 << 1)) {
- sh_serial_clear_fifo(s);
- s->sr &= ~(1 << 1);
- }
-
- return;
- case 0x20: /* SPTR */
- s->sptr = val & 0xf3;
- return;
- case 0x24: /* LSR */
- return;
- }
- }
- else {
- switch(offs) {
-#if 0
- case 0x0c:
- ret = s->dr;
- break;
- case 0x10:
- ret = 0;
- break;
-#endif
- case 0x1c:
- s->sptr = val & 0x8f;
- return;
- }
- }
-
- fprintf(stderr, "sh_serial: unsupported write to 0x%02"
- HWADDR_PRIx "\n", offs);
- abort();
-}
-
-static uint64_t sh_serial_read(void *opaque, hwaddr offs,
- unsigned size)
-{
- sh_serial_state *s = opaque;
- uint32_t ret = ~0;
-
-#if 0
- switch(offs) {
- case 0x00:
- ret = s->smr;
- break;
- case 0x04:
- ret = s->brr;
- break;
- case 0x08:
- ret = s->scr;
- break;
- case 0x14:
- ret = 0;
- break;
- }
-#endif
- if (s->feat & SH_SERIAL_FEAT_SCIF) {
- switch(offs) {
- case 0x00: /* SMR */
- ret = s->smr;
- break;
- case 0x08: /* SCR */
- ret = s->scr;
- break;
- case 0x10: /* FSR */
- ret = 0;
- if (s->flags & SH_SERIAL_FLAG_TEND)
- ret |= (1 << 6);
- if (s->flags & SH_SERIAL_FLAG_TDE)
- ret |= (1 << 5);
- if (s->flags & SH_SERIAL_FLAG_BRK)
- ret |= (1 << 4);
- if (s->flags & SH_SERIAL_FLAG_RDF)
- ret |= (1 << 1);
- if (s->flags & SH_SERIAL_FLAG_DR)
- ret |= (1 << 0);
-
- if (s->scr & (1 << 5))
- s->flags |= SH_SERIAL_FLAG_TDE | SH_SERIAL_FLAG_TEND;
-
- break;
- case 0x14:
- if (s->rx_cnt > 0) {
- ret = s->rx_fifo[s->rx_tail++];
- s->rx_cnt--;
- if (s->rx_tail == SH_RX_FIFO_LENGTH)
- s->rx_tail = 0;
- if (s->rx_cnt < s->rtrg)
- s->flags &= ~SH_SERIAL_FLAG_RDF;
- }
- break;
- case 0x18:
- ret = s->fcr;
- break;
- case 0x1c:
- ret = s->rx_cnt;
- break;
- case 0x20:
- ret = s->sptr;
- break;
- case 0x24:
- ret = 0;
- break;
- }
- }
- else {
- switch(offs) {
-#if 0
- case 0x0c:
- ret = s->dr;
- break;
- case 0x10:
- ret = 0;
- break;
- case 0x14:
- ret = s->rx_fifo[0];
- break;
-#endif
- case 0x1c:
- ret = s->sptr;
- break;
- }
- }
-#ifdef DEBUG_SERIAL
- printf("sh_serial: read offs=0x%02x val=0x%x\n",
- offs, ret);
-#endif
-
- if (ret & ~((1 << 16) - 1)) {
- fprintf(stderr, "sh_serial: unsupported read from 0x%02"
- HWADDR_PRIx "\n", offs);
- abort();
- }
-
- return ret;
-}
-
-static int sh_serial_can_receive(sh_serial_state *s)
-{
- return s->scr & (1 << 4);
-}
-
-static void sh_serial_receive_break(sh_serial_state *s)
-{
- if (s->feat & SH_SERIAL_FEAT_SCIF)
- s->sr |= (1 << 4);
-}
-
-static int sh_serial_can_receive1(void *opaque)
-{
- sh_serial_state *s = opaque;
- return sh_serial_can_receive(s);
-}
-
-static void sh_serial_receive1(void *opaque, const uint8_t *buf, int size)
-{
- sh_serial_state *s = opaque;
-
- if (s->feat & SH_SERIAL_FEAT_SCIF) {
- int i;
- for (i = 0; i < size; i++) {
- if (s->rx_cnt < SH_RX_FIFO_LENGTH) {
- s->rx_fifo[s->rx_head++] = buf[i];
- if (s->rx_head == SH_RX_FIFO_LENGTH) {
- s->rx_head = 0;
- }
- s->rx_cnt++;
- if (s->rx_cnt >= s->rtrg) {
- s->flags |= SH_SERIAL_FLAG_RDF;
- if (s->scr & (1 << 6) && s->rxi) {
- qemu_set_irq(s->rxi, 1);
- }
- }
- }
- }
- } else {
- s->rx_fifo[0] = buf[0];
- }
-}
-
-static void sh_serial_event(void *opaque, int event)
-{
- sh_serial_state *s = opaque;
- if (event == CHR_EVENT_BREAK)
- sh_serial_receive_break(s);
-}
-
-static const MemoryRegionOps sh_serial_ops = {
- .read = sh_serial_read,
- .write = sh_serial_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-void sh_serial_init(MemoryRegion *sysmem,
- hwaddr base, int feat,
- uint32_t freq, CharDriverState *chr,
- qemu_irq eri_source,
- qemu_irq rxi_source,
- qemu_irq txi_source,
- qemu_irq tei_source,
- qemu_irq bri_source)
-{
- sh_serial_state *s;
-
- s = g_malloc0(sizeof(sh_serial_state));
-
- s->feat = feat;
- s->flags = SH_SERIAL_FLAG_TEND | SH_SERIAL_FLAG_TDE;
- s->rtrg = 1;
-
- s->smr = 0;
- s->brr = 0xff;
- s->scr = 1 << 5; /* pretend that TX is enabled so early printk works */
- s->sptr = 0;
-
- if (feat & SH_SERIAL_FEAT_SCIF) {
- s->fcr = 0;
- }
- else {
- s->dr = 0xff;
- }
-
- sh_serial_clear_fifo(s);
-
- memory_region_init_io(&s->iomem, NULL, &sh_serial_ops, s,
- "serial", 0x100000000ULL);
-
- memory_region_init_alias(&s->iomem_p4, NULL, "serial-p4", &s->iomem,
- 0, 0x28);
- memory_region_add_subregion(sysmem, P4ADDR(base), &s->iomem_p4);
-
- memory_region_init_alias(&s->iomem_a7, NULL, "serial-a7", &s->iomem,
- 0, 0x28);
- memory_region_add_subregion(sysmem, A7ADDR(base), &s->iomem_a7);
-
- s->chr = chr;
-
- if (chr) {
- qemu_chr_fe_claim_no_fail(chr);
- qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
- sh_serial_event, s);
- }
-
- s->eri = eri_source;
- s->rxi = rxi_source;
- s->txi = txi_source;
- s->tei = tei_source;
- s->bri = bri_source;
-}
diff --git a/qemu/hw/char/spapr_vty.c b/qemu/hw/char/spapr_vty.c
deleted file mode 100644
index 3498d7b05..000000000
--- a/qemu/hw/char/spapr_vty.c
+++ /dev/null
@@ -1,249 +0,0 @@
-#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"
-#include "hw/ppc/spapr_vio.h"
-
-#define VTERM_BUFSIZE 16
-
-typedef struct VIOsPAPRVTYDevice {
- VIOsPAPRDevice sdev;
- CharDriverState *chardev;
- uint32_t in, out;
- uint8_t buf[VTERM_BUFSIZE];
-} VIOsPAPRVTYDevice;
-
-#define TYPE_VIO_SPAPR_VTY_DEVICE "spapr-vty"
-#define VIO_SPAPR_VTY_DEVICE(obj) \
- OBJECT_CHECK(VIOsPAPRVTYDevice, (obj), TYPE_VIO_SPAPR_VTY_DEVICE)
-
-static int vty_can_receive(void *opaque)
-{
- VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(opaque);
-
- return (dev->in - dev->out) < VTERM_BUFSIZE;
-}
-
-static void vty_receive(void *opaque, const uint8_t *buf, int size)
-{
- VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(opaque);
- int i;
-
- if ((dev->in == dev->out) && size) {
- /* toggle line to simulate edge interrupt */
- qemu_irq_pulse(spapr_vio_qirq(&dev->sdev));
- }
- for (i = 0; i < size; i++) {
- assert((dev->in - dev->out) < VTERM_BUFSIZE);
- dev->buf[dev->in++ % VTERM_BUFSIZE] = buf[i];
- }
-}
-
-static int vty_getchars(VIOsPAPRDevice *sdev, uint8_t *buf, int max)
-{
- VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(sdev);
- int n = 0;
-
- while ((n < max) && (dev->out != dev->in)) {
- buf[n++] = dev->buf[dev->out++ % VTERM_BUFSIZE];
- }
-
- qemu_chr_accept_input(dev->chardev);
-
- return n;
-}
-
-void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len)
-{
- VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(sdev);
-
- /* FIXME: should check the qemu_chr_fe_write() return value */
- qemu_chr_fe_write(dev->chardev, buf, len);
-}
-
-static void spapr_vty_realize(VIOsPAPRDevice *sdev, Error **errp)
-{
- VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(sdev);
-
- if (!dev->chardev) {
- error_setg(errp, "chardev property not set");
- return;
- }
-
- qemu_chr_add_handlers(dev->chardev, vty_can_receive,
- vty_receive, NULL, dev);
-}
-
-/* Forward declaration */
-static target_ulong h_put_term_char(PowerPCCPU *cpu, sPAPRMachineState *spapr,
- target_ulong opcode, target_ulong *args)
-{
- target_ulong reg = args[0];
- target_ulong len = args[1];
- target_ulong char0_7 = args[2];
- target_ulong char8_15 = args[3];
- VIOsPAPRDevice *sdev;
- uint8_t buf[16];
-
- sdev = vty_lookup(spapr, reg);
- if (!sdev) {
- return H_PARAMETER;
- }
-
- if (len > 16) {
- return H_PARAMETER;
- }
-
- *((uint64_t *)buf) = cpu_to_be64(char0_7);
- *((uint64_t *)buf + 1) = cpu_to_be64(char8_15);
-
- vty_putchars(sdev, buf, len);
-
- return H_SUCCESS;
-}
-
-static target_ulong h_get_term_char(PowerPCCPU *cpu, sPAPRMachineState *spapr,
- target_ulong opcode, target_ulong *args)
-{
- target_ulong reg = args[0];
- target_ulong *len = args + 0;
- target_ulong *char0_7 = args + 1;
- target_ulong *char8_15 = args + 2;
- VIOsPAPRDevice *sdev;
- uint8_t buf[16];
-
- sdev = vty_lookup(spapr, reg);
- if (!sdev) {
- return H_PARAMETER;
- }
-
- *len = vty_getchars(sdev, buf, sizeof(buf));
- if (*len < 16) {
- memset(buf + *len, 0, 16 - *len);
- }
-
- *char0_7 = be64_to_cpu(*((uint64_t *)buf));
- *char8_15 = be64_to_cpu(*((uint64_t *)buf + 1));
-
- return H_SUCCESS;
-}
-
-void spapr_vty_create(VIOsPAPRBus *bus, CharDriverState *chardev)
-{
- DeviceState *dev;
-
- dev = qdev_create(&bus->bus, "spapr-vty");
- qdev_prop_set_chr(dev, "chardev", chardev);
- qdev_init_nofail(dev);
-}
-
-static Property spapr_vty_properties[] = {
- DEFINE_SPAPR_PROPERTIES(VIOsPAPRVTYDevice, sdev),
- DEFINE_PROP_CHR("chardev", VIOsPAPRVTYDevice, chardev),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static const VMStateDescription vmstate_spapr_vty = {
- .name = "spapr_vty",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_SPAPR_VIO(sdev, VIOsPAPRVTYDevice),
-
- VMSTATE_UINT32(in, VIOsPAPRVTYDevice),
- VMSTATE_UINT32(out, VIOsPAPRVTYDevice),
- VMSTATE_BUFFER(buf, VIOsPAPRVTYDevice),
- VMSTATE_END_OF_LIST()
- },
-};
-
-static void spapr_vty_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- VIOsPAPRDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
-
- k->realize = spapr_vty_realize;
- k->dt_name = "vty";
- k->dt_type = "serial";
- k->dt_compatible = "hvterm1";
- set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
- dc->props = spapr_vty_properties;
- dc->vmsd = &vmstate_spapr_vty;
-}
-
-static const TypeInfo spapr_vty_info = {
- .name = TYPE_VIO_SPAPR_VTY_DEVICE,
- .parent = TYPE_VIO_SPAPR_DEVICE,
- .instance_size = sizeof(VIOsPAPRVTYDevice),
- .class_init = spapr_vty_class_init,
-};
-
-VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus)
-{
- VIOsPAPRDevice *sdev, *selected;
- BusChild *kid;
-
- /*
- * To avoid the console bouncing around we want one VTY to be
- * the "default". We haven't really got anything to go on, so
- * arbitrarily choose the one with the lowest reg value.
- */
-
- selected = NULL;
- QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
- DeviceState *iter = kid->child;
-
- /* Only look at VTY devices */
- if (!object_dynamic_cast(OBJECT(iter), TYPE_VIO_SPAPR_VTY_DEVICE)) {
- continue;
- }
-
- sdev = VIO_SPAPR_DEVICE(iter);
-
- /* First VTY we've found, so it is selected for now */
- if (!selected) {
- selected = sdev;
- continue;
- }
-
- /* Choose VTY with lowest reg value */
- if (sdev->reg < selected->reg) {
- selected = sdev;
- }
- }
-
- return selected;
-}
-
-VIOsPAPRDevice *vty_lookup(sPAPRMachineState *spapr, target_ulong reg)
-{
- VIOsPAPRDevice *sdev;
-
- sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
- if (!sdev && reg == 0) {
- /* Hack for kernel early debug, which always specifies reg==0.
- * We search all VIO devices, and grab the vty with the lowest
- * reg. This attempts to mimic existing PowerVM behaviour
- * (early debug does work there, despite having no vty with
- * reg==0. */
- return spapr_vty_get_default(spapr->vio_bus);
- }
-
- if (!object_dynamic_cast(OBJECT(sdev), TYPE_VIO_SPAPR_VTY_DEVICE)) {
- return NULL;
- }
-
- return sdev;
-}
-
-static void spapr_vty_register_types(void)
-{
- spapr_register_hypercall(H_PUT_TERM_CHAR, h_put_term_char);
- spapr_register_hypercall(H_GET_TERM_CHAR, h_get_term_char);
- type_register_static(&spapr_vty_info);
-}
-
-type_init(spapr_vty_register_types)
diff --git a/qemu/hw/char/stm32f2xx_usart.c b/qemu/hw/char/stm32f2xx_usart.c
deleted file mode 100644
index a94d61ceb..000000000
--- a/qemu/hw/char/stm32f2xx_usart.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * STM32F2XX USART
- *
- * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "qemu/osdep.h"
-#include "hw/char/stm32f2xx_usart.h"
-
-#ifndef STM_USART_ERR_DEBUG
-#define STM_USART_ERR_DEBUG 0
-#endif
-
-#define DB_PRINT_L(lvl, fmt, args...) do { \
- if (STM_USART_ERR_DEBUG >= lvl) { \
- qemu_log("%s: " fmt, __func__, ## args); \
- } \
-} while (0);
-
-#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
-
-static int stm32f2xx_usart_can_receive(void *opaque)
-{
- STM32F2XXUsartState *s = opaque;
-
- if (!(s->usart_sr & USART_SR_RXNE)) {
- return 1;
- }
-
- return 0;
-}
-
-static void stm32f2xx_usart_receive(void *opaque, const uint8_t *buf, int size)
-{
- STM32F2XXUsartState *s = opaque;
-
- s->usart_dr = *buf;
-
- if (!(s->usart_cr1 & USART_CR1_UE && s->usart_cr1 & USART_CR1_RE)) {
- /* USART not enabled - drop the chars */
- DB_PRINT("Dropping the chars\n");
- return;
- }
-
- s->usart_sr |= USART_SR_RXNE;
-
- if (s->usart_cr1 & USART_CR1_RXNEIE) {
- qemu_set_irq(s->irq, 1);
- }
-
- DB_PRINT("Receiving: %c\n", s->usart_dr);
-}
-
-static void stm32f2xx_usart_reset(DeviceState *dev)
-{
- STM32F2XXUsartState *s = STM32F2XX_USART(dev);
-
- s->usart_sr = USART_SR_RESET;
- s->usart_dr = 0x00000000;
- s->usart_brr = 0x00000000;
- s->usart_cr1 = 0x00000000;
- s->usart_cr2 = 0x00000000;
- s->usart_cr3 = 0x00000000;
- s->usart_gtpr = 0x00000000;
-
- qemu_set_irq(s->irq, 0);
-}
-
-static uint64_t stm32f2xx_usart_read(void *opaque, hwaddr addr,
- unsigned int size)
-{
- STM32F2XXUsartState *s = opaque;
- uint64_t retvalue;
-
- DB_PRINT("Read 0x%"HWADDR_PRIx"\n", addr);
-
- switch (addr) {
- case USART_SR:
- retvalue = s->usart_sr;
- s->usart_sr &= ~USART_SR_TC;
- if (s->chr) {
- qemu_chr_accept_input(s->chr);
- }
- return retvalue;
- case USART_DR:
- DB_PRINT("Value: 0x%" PRIx32 ", %c\n", s->usart_dr, (char) s->usart_dr);
- s->usart_sr |= USART_SR_TXE;
- s->usart_sr &= ~USART_SR_RXNE;
- if (s->chr) {
- qemu_chr_accept_input(s->chr);
- }
- qemu_set_irq(s->irq, 0);
- return s->usart_dr & 0x3FF;
- case USART_BRR:
- return s->usart_brr;
- case USART_CR1:
- return s->usart_cr1;
- case USART_CR2:
- return s->usart_cr2;
- case USART_CR3:
- return s->usart_cr3;
- case USART_GTPR:
- return s->usart_gtpr;
- default:
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
- return 0;
- }
-
- return 0;
-}
-
-static void stm32f2xx_usart_write(void *opaque, hwaddr addr,
- uint64_t val64, unsigned int size)
-{
- STM32F2XXUsartState *s = opaque;
- uint32_t value = val64;
- unsigned char ch;
-
- DB_PRINT("Write 0x%" PRIx32 ", 0x%"HWADDR_PRIx"\n", value, addr);
-
- switch (addr) {
- case USART_SR:
- if (value <= 0x3FF) {
- s->usart_sr = value;
- } else {
- s->usart_sr &= value;
- }
- if (!(s->usart_sr & USART_SR_RXNE)) {
- qemu_set_irq(s->irq, 0);
- }
- return;
- case USART_DR:
- if (value < 0xF000) {
- ch = value;
- if (s->chr) {
- qemu_chr_fe_write_all(s->chr, &ch, 1);
- }
- s->usart_sr |= USART_SR_TC;
- s->usart_sr &= ~USART_SR_TXE;
- }
- return;
- case USART_BRR:
- s->usart_brr = value;
- return;
- case USART_CR1:
- s->usart_cr1 = value;
- if (s->usart_cr1 & USART_CR1_RXNEIE &&
- s->usart_sr & USART_SR_RXNE) {
- qemu_set_irq(s->irq, 1);
- }
- return;
- case USART_CR2:
- s->usart_cr2 = value;
- return;
- case USART_CR3:
- s->usart_cr3 = value;
- return;
- case USART_GTPR:
- s->usart_gtpr = value;
- return;
- default:
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
- }
-}
-
-static const MemoryRegionOps stm32f2xx_usart_ops = {
- .read = stm32f2xx_usart_read,
- .write = stm32f2xx_usart_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void stm32f2xx_usart_init(Object *obj)
-{
- STM32F2XXUsartState *s = STM32F2XX_USART(obj);
-
- sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
-
- 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();
-
- if (s->chr) {
- qemu_chr_add_handlers(s->chr, stm32f2xx_usart_can_receive,
- stm32f2xx_usart_receive, NULL, s);
- }
-}
-
-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;
-}
-
-static const TypeInfo stm32f2xx_usart_info = {
- .name = TYPE_STM32F2XX_USART,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(STM32F2XXUsartState),
- .instance_init = stm32f2xx_usart_init,
- .class_init = stm32f2xx_usart_class_init,
-};
-
-static void stm32f2xx_usart_register_types(void)
-{
- type_register_static(&stm32f2xx_usart_info);
-}
-
-type_init(stm32f2xx_usart_register_types)
diff --git a/qemu/hw/char/virtio-console.c b/qemu/hw/char/virtio-console.c
deleted file mode 100644
index 2e36481a7..000000000
--- a/qemu/hw/char/virtio-console.c
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Virtio Console and Generic Serial Port Devices
- *
- * Copyright Red Hat, Inc. 2009, 2010
- *
- * Authors:
- * Amit Shah <amit.shah@redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- */
-
-#include "qemu/osdep.h"
-#include "sysemu/char.h"
-#include "qemu/error-report.h"
-#include "trace.h"
-#include "hw/virtio/virtio-serial.h"
-#include "qapi-event.h"
-
-#define TYPE_VIRTIO_CONSOLE_SERIAL_PORT "virtserialport"
-#define VIRTIO_CONSOLE(obj) \
- OBJECT_CHECK(VirtConsole, (obj), TYPE_VIRTIO_CONSOLE_SERIAL_PORT)
-
-typedef struct VirtConsole {
- VirtIOSerialPort parent_obj;
-
- CharDriverState *chr;
- guint watch;
-} VirtConsole;
-
-/*
- * Callback function that's called from chardevs when backend becomes
- * writable.
- */
-static gboolean chr_write_unblocked(GIOChannel *chan, GIOCondition cond,
- void *opaque)
-{
- VirtConsole *vcon = opaque;
-
- vcon->watch = 0;
- virtio_serial_throttle_port(VIRTIO_SERIAL_PORT(vcon), false);
- return FALSE;
-}
-
-/* Callback function that's called when the guest sends us data */
-static ssize_t flush_buf(VirtIOSerialPort *port,
- const uint8_t *buf, ssize_t len)
-{
- VirtConsole *vcon = VIRTIO_CONSOLE(port);
- ssize_t ret;
-
- if (!vcon->chr) {
- /* If there's no backend, we can just say we consumed all data. */
- return len;
- }
-
- ret = qemu_chr_fe_write(vcon->chr, buf, len);
- trace_virtio_console_flush_buf(port->id, len, ret);
-
- if (ret < len) {
- VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port);
-
- /*
- * Ideally we'd get a better error code than just -1, but
- * that's what the chardev interface gives us right now. If
- * we had a finer-grained message, like -EPIPE, we could close
- * this connection.
- */
- if (ret < 0)
- ret = 0;
- if (!k->is_console) {
- virtio_serial_throttle_port(port, true);
- if (!vcon->watch) {
- vcon->watch = qemu_chr_fe_add_watch(vcon->chr,
- G_IO_OUT|G_IO_HUP,
- chr_write_unblocked, vcon);
- }
- }
- }
- return ret;
-}
-
-/* Callback function that's called when the guest opens/closes the port */
-static void set_guest_connected(VirtIOSerialPort *port, int guest_connected)
-{
- VirtConsole *vcon = VIRTIO_CONSOLE(port);
- DeviceState *dev = DEVICE(port);
-
- if (vcon->chr) {
- qemu_chr_fe_set_open(vcon->chr, guest_connected);
- }
-
- if (dev->id) {
- qapi_event_send_vserport_change(dev->id, guest_connected,
- &error_abort);
- }
-}
-
-static void guest_writable(VirtIOSerialPort *port)
-{
- VirtConsole *vcon = VIRTIO_CONSOLE(port);
-
- if (vcon->chr) {
- qemu_chr_accept_input(vcon->chr);
- }
-}
-
-/* Readiness of the guest to accept data on a port */
-static int chr_can_read(void *opaque)
-{
- VirtConsole *vcon = opaque;
-
- return virtio_serial_guest_ready(VIRTIO_SERIAL_PORT(vcon));
-}
-
-/* Send data from a char device over to the guest */
-static void chr_read(void *opaque, const uint8_t *buf, int size)
-{
- VirtConsole *vcon = opaque;
- VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(vcon);
-
- trace_virtio_console_chr_read(port->id, size);
- virtio_serial_write(port, buf, size);
-}
-
-static void chr_event(void *opaque, int event)
-{
- VirtConsole *vcon = opaque;
- VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(vcon);
-
- trace_virtio_console_chr_event(port->id, event);
- switch (event) {
- case CHR_EVENT_OPENED:
- virtio_serial_open(port);
- break;
- case CHR_EVENT_CLOSED:
- if (vcon->watch) {
- g_source_remove(vcon->watch);
- vcon->watch = 0;
- }
- virtio_serial_close(port);
- break;
- }
-}
-
-static void virtconsole_realize(DeviceState *dev, Error **errp)
-{
- VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev);
- VirtConsole *vcon = VIRTIO_CONSOLE(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;
- }
-
- if (vcon->chr) {
- vcon->chr->explicit_fe_open = 1;
- qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
- vcon);
- }
-}
-
-static void virtconsole_unrealize(DeviceState *dev, Error **errp)
-{
- VirtConsole *vcon = VIRTIO_CONSOLE(dev);
-
- if (vcon->watch) {
- g_source_remove(vcon->watch);
- }
-}
-
-static void virtconsole_class_init(ObjectClass *klass, void *data)
-{
- VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass);
-
- k->is_console = true;
-}
-
-static const TypeInfo virtconsole_info = {
- .name = "virtconsole",
- .parent = TYPE_VIRTIO_CONSOLE_SERIAL_PORT,
- .class_init = virtconsole_class_init,
-};
-
-static Property virtserialport_properties[] = {
- DEFINE_PROP_CHR("chardev", VirtConsole, chr),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void virtserialport_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass);
-
- k->realize = virtconsole_realize;
- k->unrealize = virtconsole_unrealize;
- k->have_data = flush_buf;
- k->set_guest_connected = set_guest_connected;
- k->guest_writable = guest_writable;
- dc->props = virtserialport_properties;
-}
-
-static const TypeInfo virtserialport_info = {
- .name = TYPE_VIRTIO_CONSOLE_SERIAL_PORT,
- .parent = TYPE_VIRTIO_SERIAL_PORT,
- .instance_size = sizeof(VirtConsole),
- .class_init = virtserialport_class_init,
-};
-
-static void virtconsole_register_types(void)
-{
- type_register_static(&virtserialport_info);
- type_register_static(&virtconsole_info);
-}
-
-type_init(virtconsole_register_types)
diff --git a/qemu/hw/char/virtio-serial-bus.c b/qemu/hw/char/virtio-serial-bus.c
deleted file mode 100644
index 6e5de6dec..000000000
--- a/qemu/hw/char/virtio-serial-bus.c
+++ /dev/null
@@ -1,1149 +0,0 @@
-/*
- * A bus for connecting virtio serial and console ports
- *
- * Copyright (C) 2009, 2010 Red Hat, Inc.
- *
- * Author(s):
- * Amit Shah <amit.shah@redhat.com>
- *
- * Some earlier parts are:
- * Copyright IBM, Corp. 2008
- * authored by
- * Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * 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"
-#include "qemu/queue.h"
-#include "hw/sysbus.h"
-#include "trace.h"
-#include "hw/virtio/virtio-serial.h"
-#include "hw/virtio/virtio-access.h"
-
-static struct VirtIOSerialDevices {
- QLIST_HEAD(, VirtIOSerial) devices;
-} vserdevices;
-
-static VirtIOSerialPort *find_port_by_id(VirtIOSerial *vser, uint32_t id)
-{
- VirtIOSerialPort *port;
-
- if (id == VIRTIO_CONSOLE_BAD_ID) {
- return NULL;
- }
-
- QTAILQ_FOREACH(port, &vser->ports, next) {
- if (port->id == id)
- return port;
- }
- return NULL;
-}
-
-static VirtIOSerialPort *find_port_by_vq(VirtIOSerial *vser, VirtQueue *vq)
-{
- VirtIOSerialPort *port;
-
- QTAILQ_FOREACH(port, &vser->ports, next) {
- if (port->ivq == vq || port->ovq == vq)
- return port;
- }
- return NULL;
-}
-
-static VirtIOSerialPort *find_port_by_name(char *name)
-{
- VirtIOSerial *vser;
-
- QLIST_FOREACH(vser, &vserdevices.devices, next) {
- VirtIOSerialPort *port;
-
- QTAILQ_FOREACH(port, &vser->ports, next) {
- if (port->name && !strcmp(port->name, name)) {
- return port;
- }
- }
- }
- return NULL;
-}
-
-static bool use_multiport(VirtIOSerial *vser)
-{
- VirtIODevice *vdev = VIRTIO_DEVICE(vser);
- 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;
- VirtQueue *vq;
- size_t offset;
-
- vq = port->ivq;
- if (!virtio_queue_ready(vq)) {
- return 0;
- }
-
- offset = 0;
- while (offset < size) {
- size_t len;
-
- elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
- if (!elem) {
- break;
- }
-
- len = iov_from_buf(elem->in_sg, elem->in_num, 0,
- buf + offset, size - offset);
- offset += len;
-
- virtqueue_push(vq, elem, len);
- g_free(elem);
- }
-
- virtio_notify(VIRTIO_DEVICE(port->vser), vq);
- return offset;
-}
-
-static void discard_vq_data(VirtQueue *vq, VirtIODevice *vdev)
-{
- VirtQueueElement *elem;
-
- if (!virtio_queue_ready(vq)) {
- return;
- }
- for (;;) {
- elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
- if (!elem) {
- break;
- }
- virtqueue_push(vq, elem, 0);
- g_free(elem);
- }
- virtio_notify(vdev, vq);
-}
-
-static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
- VirtIODevice *vdev)
-{
- VirtIOSerialPortClass *vsc;
-
- assert(port);
- assert(virtio_queue_ready(vq));
-
- vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
-
- while (!port->throttled) {
- unsigned int i;
-
- /* Pop an elem only if we haven't left off a previous one mid-way */
- 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++) {
- size_t buf_size;
- ssize_t ret;
-
- 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->iov_offset,
- buf_size);
- if (port->throttled) {
- port->iov_idx = i;
- if (ret > 0) {
- port->iov_offset += ret;
- }
- break;
- }
- port->iov_offset = 0;
- }
- if (port->throttled) {
- break;
- }
- virtqueue_push(vq, port->elem, 0);
- g_free(port->elem);
- port->elem = NULL;
- }
- virtio_notify(vdev, vq);
-}
-
-static void flush_queued_data(VirtIOSerialPort *port)
-{
- assert(port);
-
- if (!virtio_queue_ready(port->ovq)) {
- return;
- }
- do_flush_queued_data(port, port->ovq, VIRTIO_DEVICE(port->vser));
-}
-
-static size_t send_control_msg(VirtIOSerial *vser, void *buf, size_t len)
-{
- VirtQueueElement *elem;
- VirtQueue *vq;
-
- vq = vser->c_ivq;
- if (!virtio_queue_ready(vq)) {
- return 0;
- }
-
- 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);
-
- virtqueue_push(vq, elem, len);
- virtio_notify(VIRTIO_DEVICE(vser), vq);
- g_free(elem);
-
- return len;
-}
-
-static size_t send_control_event(VirtIOSerial *vser, uint32_t port_id,
- uint16_t event, uint16_t value)
-{
- VirtIODevice *vdev = VIRTIO_DEVICE(vser);
- struct virtio_console_control cpkt;
-
- virtio_stl_p(vdev, &cpkt.id, port_id);
- virtio_stw_p(vdev, &cpkt.event, event);
- virtio_stw_p(vdev, &cpkt.value, value);
-
- trace_virtio_serial_send_control_event(port_id, event, value);
- return send_control_msg(vser, &cpkt, sizeof(cpkt));
-}
-
-/* Functions for use inside qemu to open and read from/write to ports */
-int virtio_serial_open(VirtIOSerialPort *port)
-{
- /* Don't allow opening an already-open port */
- if (port->host_connected) {
- return 0;
- }
- /* Send port open notification to the guest */
- port->host_connected = true;
- send_control_event(port->vser, port->id, VIRTIO_CONSOLE_PORT_OPEN, 1);
-
- return 0;
-}
-
-int virtio_serial_close(VirtIOSerialPort *port)
-{
- port->host_connected = false;
- /*
- * If there's any data the guest sent which the app didn't
- * consume, reset the throttling flag and discard the data.
- */
- port->throttled = false;
- discard_vq_data(port->ovq, VIRTIO_DEVICE(port->vser));
-
- send_control_event(port->vser, port->id, VIRTIO_CONSOLE_PORT_OPEN, 0);
-
- return 0;
-}
-
-/* Individual ports/apps call this function to write to the guest. */
-ssize_t virtio_serial_write(VirtIOSerialPort *port, const uint8_t *buf,
- size_t size)
-{
- if (!port || !port->host_connected || !port->guest_connected) {
- return 0;
- }
- return write_to_port(port, buf, size);
-}
-
-/*
- * Readiness of the guest to accept data on a port.
- * Returns max. data the guest can receive
- */
-size_t virtio_serial_guest_ready(VirtIOSerialPort *port)
-{
- VirtIODevice *vdev = VIRTIO_DEVICE(port->vser);
- VirtQueue *vq = port->ivq;
- unsigned int bytes;
-
- if (!virtio_queue_ready(vq) ||
- !(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) ||
- virtio_queue_empty(vq)) {
- return 0;
- }
- if (use_multiport(port->vser) && !port->guest_connected) {
- return 0;
- }
- virtqueue_get_avail_bytes(vq, &bytes, NULL, 4096, 0);
- return bytes;
-}
-
-static void flush_queued_data_bh(void *opaque)
-{
- VirtIOSerialPort *port = opaque;
-
- flush_queued_data(port);
-}
-
-void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle)
-{
- if (!port) {
- return;
- }
-
- trace_virtio_serial_throttle_port(port->id, throttle);
- port->throttled = throttle;
- if (throttle) {
- return;
- }
- qemu_bh_schedule(port->bh);
-}
-
-/* Guest wants to notify us of some event */
-static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
-{
- VirtIODevice *vdev = VIRTIO_DEVICE(vser);
- struct VirtIOSerialPort *port;
- VirtIOSerialPortClass *vsc;
- struct virtio_console_control cpkt, *gcpkt;
- uint8_t *buffer;
- size_t buffer_len;
-
- gcpkt = buf;
-
- if (len < sizeof(cpkt)) {
- /* The guest sent an invalid control packet */
- return;
- }
-
- cpkt.event = virtio_lduw_p(vdev, &gcpkt->event);
- cpkt.value = virtio_lduw_p(vdev, &gcpkt->value);
-
- trace_virtio_serial_handle_control_message(cpkt.event, cpkt.value);
-
- if (cpkt.event == VIRTIO_CONSOLE_DEVICE_READY) {
- if (!cpkt.value) {
- error_report("virtio-serial-bus: Guest failure in adding device %s",
- vser->bus.qbus.name);
- return;
- }
- /*
- * The device is up, we can now tell the device about all the
- * ports we have here.
- */
- QTAILQ_FOREACH(port, &vser->ports, next) {
- send_control_event(vser, port->id, VIRTIO_CONSOLE_PORT_ADD, 1);
- }
- return;
- }
-
- port = find_port_by_id(vser, virtio_ldl_p(vdev, &gcpkt->id));
- if (!port) {
- error_report("virtio-serial-bus: Unexpected port id %u for device %s",
- virtio_ldl_p(vdev, &gcpkt->id), vser->bus.qbus.name);
- return;
- }
-
- trace_virtio_serial_handle_control_message_port(port->id);
-
- vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
-
- switch(cpkt.event) {
- case VIRTIO_CONSOLE_PORT_READY:
- if (!cpkt.value) {
- error_report("virtio-serial-bus: Guest failure in adding port %u for device %s",
- port->id, vser->bus.qbus.name);
- break;
- }
- /*
- * Now that we know the guest asked for the port name, we're
- * sure the guest has initialised whatever state is necessary
- * for this port. Now's a good time to let the guest know if
- * this port is a console port so that the guest can hook it
- * up to hvc.
- */
- if (vsc->is_console) {
- send_control_event(vser, port->id, VIRTIO_CONSOLE_CONSOLE_PORT, 1);
- }
-
- if (port->name) {
- virtio_stl_p(vdev, &cpkt.id, port->id);
- virtio_stw_p(vdev, &cpkt.event, VIRTIO_CONSOLE_PORT_NAME);
- virtio_stw_p(vdev, &cpkt.value, 1);
-
- buffer_len = sizeof(cpkt) + strlen(port->name) + 1;
- buffer = g_malloc(buffer_len);
-
- memcpy(buffer, &cpkt, sizeof(cpkt));
- memcpy(buffer + sizeof(cpkt), port->name, strlen(port->name));
- buffer[buffer_len - 1] = 0;
-
- send_control_msg(vser, buffer, buffer_len);
- g_free(buffer);
- }
-
- if (port->host_connected) {
- send_control_event(vser, port->id, VIRTIO_CONSOLE_PORT_OPEN, 1);
- }
-
- /*
- * When the guest has asked us for this information it means
- * the guest is all setup and has its virtqueues
- * initialised. If some app is interested in knowing about
- * this event, let it know.
- */
- if (vsc->guest_ready) {
- vsc->guest_ready(port);
- }
- break;
-
- case VIRTIO_CONSOLE_PORT_OPEN:
- port->guest_connected = cpkt.value;
- if (vsc->set_guest_connected) {
- /* Send the guest opened notification if an app is interested */
- vsc->set_guest_connected(port, cpkt.value);
- }
- break;
- }
-}
-
-static void control_in(VirtIODevice *vdev, VirtQueue *vq)
-{
-}
-
-static void control_out(VirtIODevice *vdev, VirtQueue *vq)
-{
- VirtQueueElement *elem;
- VirtIOSerial *vser;
- uint8_t *buf;
- size_t len;
-
- vser = VIRTIO_SERIAL(vdev);
-
- len = 0;
- buf = NULL;
- for (;;) {
- size_t cur_len;
-
- 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
- */
- if (cur_len > len) {
- g_free(buf);
-
- buf = g_malloc(cur_len);
- len = 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);
- g_free(elem);
- }
- g_free(buf);
- virtio_notify(vdev, vq);
-}
-
-/* Guest wrote something to some port. */
-static void handle_output(VirtIODevice *vdev, VirtQueue *vq)
-{
- VirtIOSerial *vser;
- VirtIOSerialPort *port;
-
- vser = VIRTIO_SERIAL(vdev);
- port = find_port_by_vq(vser, vq);
-
- if (!port || !port->host_connected) {
- discard_vq_data(vq, vdev);
- return;
- }
-
- if (!port->throttled) {
- do_flush_queued_data(port, vq, vdev);
- return;
- }
-}
-
-static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
-{
- /*
- * Users of virtio-serial would like to know when guest becomes
- * writable again -- i.e. if a vq had stuff queued up and the
- * guest wasn't reading at all, the host would not be able to
- * write to the vq anymore. Once the guest reads off something,
- * we can start queueing things up again. However, this call is
- * made for each buffer addition by the guest -- even though free
- * buffers existed prior to the current buffer addition. This is
- * done so as not to maintain previous state, which will need
- * additional live-migration-related changes.
- */
- VirtIOSerial *vser;
- VirtIOSerialPort *port;
- VirtIOSerialPortClass *vsc;
-
- vser = VIRTIO_SERIAL(vdev);
- port = find_port_by_vq(vser, vq);
-
- if (!port) {
- return;
- }
- vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
-
- /*
- * If guest_connected is false, this call is being made by the
- * early-boot queueing up of descriptors, which is just noise for
- * the host apps -- don't disturb them in that case.
- */
- if (port->guest_connected && port->host_connected && vsc->guest_writable) {
- vsc->guest_writable(port);
- }
-}
-
-static uint64_t get_features(VirtIODevice *vdev, uint64_t features,
- Error **errp)
-{
- VirtIOSerial *vser;
-
- vser = VIRTIO_SERIAL(vdev);
-
- if (vser->bus.max_nr_ports > 1) {
- virtio_add_feature(&features, VIRTIO_CONSOLE_F_MULTIPORT);
- }
- return features;
-}
-
-/* Guest requested config info */
-static void get_config(VirtIODevice *vdev, uint8_t *config_data)
-{
- VirtIOSerial *vser = VIRTIO_SERIAL(vdev);
- struct virtio_console_config *config =
- (struct virtio_console_config *)config_data;
-
- config->cols = 0;
- config->rows = 0;
- config->max_nr_ports = virtio_tswap32(vdev,
- vser->serial.max_virtserial_ports);
-}
-
-static void guest_reset(VirtIOSerial *vser)
-{
- VirtIOSerialPort *port;
- VirtIOSerialPortClass *vsc;
-
- QTAILQ_FOREACH(port, &vser->ports, next) {
- vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
- if (port->guest_connected) {
- port->guest_connected = false;
- if (vsc->set_guest_connected) {
- vsc->set_guest_connected(port, false);
- }
- }
- }
-}
-
-static void set_status(VirtIODevice *vdev, uint8_t status)
-{
- VirtIOSerial *vser;
- VirtIOSerialPort *port;
-
- vser = VIRTIO_SERIAL(vdev);
- port = find_port_by_id(vser, 0);
-
- if (port && !use_multiport(port->vser)
- && (status & VIRTIO_CONFIG_S_DRIVER_OK)) {
- /*
- * Non-multiport guests won't be able to tell us guest
- * open/close status. Such guests can only have a port at id
- * 0, so set guest_connected for such ports as soon as guest
- * is up.
- */
- port->guest_connected = true;
- }
- if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
- guest_reset(vser);
- }
-}
-
-static void vser_reset(VirtIODevice *vdev)
-{
- VirtIOSerial *vser;
-
- vser = VIRTIO_SERIAL(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);
- VirtIOSerialPort *port;
- uint32_t nr_active_ports;
- unsigned int i, max_nr_ports;
- struct virtio_console_config config;
-
- /* 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);
-
- /* The ports map */
- max_nr_ports = s->serial.max_virtserial_ports;
- for (i = 0; i < (max_nr_ports + 31) / 32; i++) {
- qemu_put_be32s(f, &s->ports_map[i]);
- }
-
- /* Ports */
-
- nr_active_ports = 0;
- QTAILQ_FOREACH(port, &s->ports, next) {
- nr_active_ports++;
- }
-
- qemu_put_be32s(f, &nr_active_ports);
-
- /*
- * Items in struct VirtIOSerialPort.
- */
- QTAILQ_FOREACH(port, &s->ports, next) {
- uint32_t elem_popped;
-
- qemu_put_be32s(f, &port->id);
- qemu_put_byte(f, port->guest_connected);
- qemu_put_byte(f, port->host_connected);
-
- elem_popped = 0;
- 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_virtqueue_element(f, port->elem);
- }
- }
-}
-
-static void virtio_serial_post_load_timer_cb(void *opaque)
-{
- uint32_t i;
- VirtIOSerial *s = VIRTIO_SERIAL(opaque);
- VirtIOSerialPort *port;
- uint8_t host_connected;
- VirtIOSerialPortClass *vsc;
-
- if (!s->post_load) {
- return;
- }
- for (i = 0 ; i < s->post_load->nr_active_ports; ++i) {
- port = s->post_load->connected[i].port;
- host_connected = s->post_load->connected[i].host_connected;
- if (host_connected != port->host_connected) {
- /*
- * We have to let the guest know of the host connection
- * status change
- */
- send_control_event(s, port->id, VIRTIO_CONSOLE_PORT_OPEN,
- port->host_connected);
- }
- vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
- if (vsc->set_guest_connected) {
- vsc->set_guest_connected(port, port->guest_connected);
- }
- }
- g_free(s->post_load->connected);
- timer_free(s->post_load->timer);
- g_free(s->post_load);
- s->post_load = NULL;
-}
-
-static int fetch_active_ports_list(QEMUFile *f, int version_id,
- VirtIOSerial *s, uint32_t nr_active_ports)
-{
- uint32_t i;
-
- s->post_load = g_malloc0(sizeof(*s->post_load));
- s->post_load->nr_active_ports = nr_active_ports;
- s->post_load->connected =
- g_malloc0(sizeof(*s->post_load->connected) * nr_active_ports);
-
- s->post_load->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
- virtio_serial_post_load_timer_cb,
- s);
-
- /* Items in struct VirtIOSerialPort */
- for (i = 0; i < nr_active_ports; i++) {
- VirtIOSerialPort *port;
- uint32_t id;
-
- id = qemu_get_be32(f);
- port = find_port_by_id(s, id);
- if (!port) {
- return -EINVAL;
- }
-
- port->guest_connected = qemu_get_byte(f);
- 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);
-
- 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);
- }
- }
- }
- timer_mod(s->post_load->timer, 1);
- return 0;
-}
-
-static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
-{
- if (version_id > 3) {
- return -EINVAL;
- }
-
- /* The virtio device */
- return virtio_load(VIRTIO_DEVICE(opaque), f, version_id);
-}
-
-static int virtio_serial_load_device(VirtIODevice *vdev, QEMUFile *f,
- int version_id)
-{
- VirtIOSerial *s = VIRTIO_SERIAL(vdev);
- uint32_t max_nr_ports, nr_active_ports, ports_map;
- unsigned int i;
- 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);
- qemu_get_be32s(f, &tmp);
-
- max_nr_ports = s->serial.max_virtserial_ports;
- for (i = 0; i < (max_nr_ports + 31) / 32; i++) {
- qemu_get_be32s(f, &ports_map);
-
- if (ports_map != s->ports_map[i]) {
- /*
- * Ports active on source and destination don't
- * match. Fail migration.
- */
- return -EINVAL;
- }
- }
-
- qemu_get_be32s(f, &nr_active_ports);
-
- if (nr_active_ports) {
- ret = fetch_active_ports_list(f, version_id, s, nr_active_ports);
- if (ret) {
- return ret;
- }
- }
- return 0;
-}
-
-static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
-
-static Property virtser_props[] = {
- DEFINE_PROP_UINT32("nr", VirtIOSerialPort, id, VIRTIO_CONSOLE_BAD_ID),
- DEFINE_PROP_STRING("name", VirtIOSerialPort, name),
- 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);
- k->print_dev = virtser_bus_dev_print;
-}
-
-static const TypeInfo virtser_bus_info = {
- .name = TYPE_VIRTIO_SERIAL_BUS,
- .parent = TYPE_BUS,
- .instance_size = sizeof(VirtIOSerialBus),
- .class_init = virtser_bus_class_init,
-};
-
-static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
-{
- VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(qdev);
-
- monitor_printf(mon, "%*sport %d, guest %s, host %s, throttle %s\n",
- indent, "", port->id,
- port->guest_connected ? "on" : "off",
- port->host_connected ? "on" : "off",
- port->throttled ? "on" : "off");
-}
-
-/* This function is only used if a port id is not provided by the user */
-static uint32_t find_free_port_id(VirtIOSerial *vser)
-{
- unsigned int i, max_nr_ports;
-
- max_nr_ports = vser->serial.max_virtserial_ports;
- for (i = 0; i < (max_nr_ports + 31) / 32; i++) {
- uint32_t map, zeroes;
-
- map = vser->ports_map[i];
- zeroes = ctz32(~map);
- if (zeroes != 32) {
- return zeroes + i * 32;
- }
- }
- return VIRTIO_CONSOLE_BAD_ID;
-}
-
-static void mark_port_added(VirtIOSerial *vser, uint32_t port_id)
-{
- unsigned int i;
-
- i = port_id / 32;
- vser->ports_map[i] |= 1U << (port_id % 32);
-}
-
-static void add_port(VirtIOSerial *vser, uint32_t port_id)
-{
- mark_port_added(vser, port_id);
- send_control_event(vser, port_id, VIRTIO_CONSOLE_PORT_ADD, 1);
-}
-
-static void remove_port(VirtIOSerial *vser, uint32_t port_id)
-{
- VirtIOSerialPort *port;
-
- /*
- * Don't mark port 0 removed -- we explicitly reserve it for
- * backward compat with older guests, ensure a virtconsole device
- * unplug retains the reservation.
- */
- if (port_id) {
- unsigned int i;
-
- i = port_id / 32;
- vser->ports_map[i] &= ~(1U << (port_id % 32));
- }
-
- port = find_port_by_id(vser, port_id);
- /*
- * This function is only called from qdev's unplug callback; if we
- * get a NULL port here, we're in trouble.
- */
- assert(port);
-
- /* Flush out any unconsumed buffers first */
- discard_vq_data(port->ovq, VIRTIO_DEVICE(port->vser));
-
- send_control_event(vser, port->id, VIRTIO_CONSOLE_PORT_REMOVE, 1);
-}
-
-static void virtser_port_device_realize(DeviceState *dev, Error **errp)
-{
- VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev);
- VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
- VirtIOSerialBus *bus = VIRTIO_SERIAL_BUS(qdev_get_parent_bus(dev));
- int max_nr_ports;
- bool plugging_port0;
- Error *err = NULL;
-
- port->vser = bus->vser;
- port->bh = qemu_bh_new(flush_queued_data_bh, port);
-
- assert(vsc->have_data);
-
- /*
- * Is the first console port we're seeing? If so, put it up at
- * location 0. This is done for backward compatibility (old
- * kernel, new qemu).
- */
- plugging_port0 = vsc->is_console && !find_port_by_id(port->vser, 0);
-
- if (find_port_by_id(port->vser, port->id)) {
- error_setg(errp, "virtio-serial-bus: A port already exists at id %u",
- port->id);
- return;
- }
-
- if (port->name != NULL && find_port_by_name(port->name)) {
- error_setg(errp, "virtio-serial-bus: A port already exists by name %s",
- port->name);
- return;
- }
-
- if (port->id == VIRTIO_CONSOLE_BAD_ID) {
- if (plugging_port0) {
- port->id = 0;
- } else {
- port->id = find_free_port_id(port->vser);
- if (port->id == VIRTIO_CONSOLE_BAD_ID) {
- error_setg(errp, "virtio-serial-bus: Maximum port limit for "
- "this device reached");
- return;
- }
- }
- }
-
- max_nr_ports = port->vser->serial.max_virtserial_ports;
- if (port->id >= max_nr_ports) {
- error_setg(errp, "virtio-serial-bus: Out-of-range port id specified, "
- "max. allowed: %u", max_nr_ports - 1);
- return;
- }
-
- vsc->realize(dev, &err);
- if (err != NULL) {
- error_propagate(errp, err);
- return;
- }
-
- port->elem = NULL;
-}
-
-static void virtser_port_device_plug(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
-{
- VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev);
-
- QTAILQ_INSERT_TAIL(&port->vser->ports, port, next);
- port->ivq = port->vser->ivqs[port->id];
- port->ovq = port->vser->ovqs[port->id];
-
- add_port(port->vser, port->id);
-
- /* Send an update to the guest about this new port added */
- virtio_notify_config(VIRTIO_DEVICE(hotplug_dev));
-}
-
-static void virtser_port_device_unrealize(DeviceState *dev, Error **errp)
-{
- VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev);
- VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(dev);
- VirtIOSerial *vser = port->vser;
-
- qemu_bh_delete(port->bh);
- remove_port(port->vser, port->id);
-
- QTAILQ_REMOVE(&vser->ports, port, next);
-
- if (vsc->unrealize) {
- vsc->unrealize(dev, errp);
- }
-}
-
-static void virtio_serial_device_realize(DeviceState *dev, Error **errp)
-{
- VirtIODevice *vdev = VIRTIO_DEVICE(dev);
- VirtIOSerial *vser = VIRTIO_SERIAL(dev);
- uint32_t i, max_supported_ports;
-
- if (!vser->serial.max_virtserial_ports) {
- error_setg(errp, "Maximum number of serial ports not specified");
- return;
- }
-
- /* Each port takes 2 queues, and one pair is for the control queue */
- max_supported_ports = VIRTIO_QUEUE_MAX / 2 - 1;
-
- if (vser->serial.max_virtserial_ports > max_supported_ports) {
- error_setg(errp, "maximum ports supported: %u", max_supported_ports);
- return;
- }
-
- /* We don't support emergency write, skip it for now. */
- /* TODO: cleaner fix, depending on host features. */
- virtio_init(vdev, "virtio-serial", VIRTIO_ID_CONSOLE,
- offsetof(struct virtio_console_config, emerg_wr));
-
- /* 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);
- vser->bus.vser = vser;
- QTAILQ_INIT(&vser->ports);
-
- vser->bus.max_nr_ports = vser->serial.max_virtserial_ports;
- vser->ivqs = g_malloc(vser->serial.max_virtserial_ports
- * sizeof(VirtQueue *));
- vser->ovqs = g_malloc(vser->serial.max_virtserial_ports
- * sizeof(VirtQueue *));
-
- /* Add a queue for host to guest transfers for port 0 (backward compat) */
- vser->ivqs[0] = virtio_add_queue(vdev, 128, handle_input);
- /* Add a queue for guest to host transfers for port 0 (backward compat) */
- vser->ovqs[0] = virtio_add_queue(vdev, 128, handle_output);
-
- /* TODO: host to guest notifications can get dropped
- * if the queue fills up. Implement queueing in host,
- * this might also make it possible to reduce the control
- * queue size: as guest preposts buffers there,
- * this will save 4Kbyte of guest memory per entry. */
-
- /* control queue: host to guest */
- vser->c_ivq = virtio_add_queue(vdev, 32, control_in);
- /* control queue: guest to host */
- vser->c_ovq = virtio_add_queue(vdev, 32, control_out);
-
- for (i = 1; i < vser->bus.max_nr_ports; i++) {
- /* Add a per-port queue for host to guest transfers */
- vser->ivqs[i] = virtio_add_queue(vdev, 128, handle_input);
- /* Add a per-per queue for guest to host transfers */
- vser->ovqs[i] = virtio_add_queue(vdev, 128, handle_output);
- }
-
- vser->ports_map = g_malloc0(((vser->serial.max_virtserial_ports + 31) / 32)
- * sizeof(vser->ports_map[0]));
- /*
- * Reserve location 0 for a console port for backward compat
- * (old kernel, new qemu)
- */
- mark_port_added(vser, 0);
-
- 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);
-}
-
-static void virtio_serial_port_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *k = DEVICE_CLASS(klass);
-
- set_bit(DEVICE_CATEGORY_INPUT, k->categories);
- k->bus_type = TYPE_VIRTIO_SERIAL_BUS;
- k->realize = virtser_port_device_realize;
- k->unrealize = virtser_port_device_unrealize;
- k->props = virtser_props;
-}
-
-static const TypeInfo virtio_serial_port_type_info = {
- .name = TYPE_VIRTIO_SERIAL_PORT,
- .parent = TYPE_DEVICE,
- .instance_size = sizeof(VirtIOSerialPort),
- .abstract = true,
- .class_size = sizeof(VirtIOSerialPortClass),
- .class_init = virtio_serial_port_class_init,
-};
-
-static void virtio_serial_device_unrealize(DeviceState *dev, Error **errp)
-{
- VirtIODevice *vdev = VIRTIO_DEVICE(dev);
- VirtIOSerial *vser = VIRTIO_SERIAL(dev);
-
- QLIST_REMOVE(vser, next);
-
- 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);
- timer_del(vser->post_load->timer);
- timer_free(vser->post_load->timer);
- g_free(vser->post_load);
- }
- virtio_cleanup(vdev);
-}
-
-static Property virtio_serial_properties[] = {
- DEFINE_PROP_UINT32("max_ports", VirtIOSerial, serial.max_virtserial_ports,
- 31),
- 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);
- HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
-
- QLIST_INIT(&vserdevices.devices);
-
- dc->props = virtio_serial_properties;
- set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
- vdc->realize = virtio_serial_device_realize;
- vdc->unrealize = virtio_serial_device_unrealize;
- vdc->get_features = get_features;
- vdc->get_config = get_config;
- vdc->set_status = set_status;
- vdc->reset = vser_reset;
- vdc->save = virtio_serial_save_device;
- vdc->load = virtio_serial_load_device;
- hc->plug = virtser_port_device_plug;
- hc->unplug = qdev_simple_device_unplug_cb;
-}
-
-static const TypeInfo virtio_device_info = {
- .name = TYPE_VIRTIO_SERIAL,
- .parent = TYPE_VIRTIO_DEVICE,
- .instance_size = sizeof(VirtIOSerial),
- .class_init = virtio_serial_class_init,
- .interfaces = (InterfaceInfo[]) {
- { TYPE_HOTPLUG_HANDLER },
- { }
- }
-};
-
-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/qemu/hw/char/xen_console.c b/qemu/hw/char/xen_console.c
deleted file mode 100644
index cbf1dccbb..000000000
--- a/qemu/hw/char/xen_console.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Copyright (C) International Business Machines Corp., 2005
- * Author(s): Anthony Liguori <aliguori@us.ibm.com>
- *
- * Copyright (C) Red Hat 2007
- *
- * Xen Console
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; under version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * 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 <sys/select.h>
-#include <termios.h>
-#include <sys/mman.h>
-
-#include "hw/hw.h"
-#include "sysemu/char.h"
-#include "hw/xen/xen_backend.h"
-
-#include <xen/io/console.h>
-
-struct buffer {
- uint8_t *data;
- size_t consumed;
- size_t size;
- size_t capacity;
- size_t max_capacity;
-};
-
-struct XenConsole {
- struct XenDevice xendev; /* must be first */
- struct buffer buffer;
- char console[XEN_BUFSIZE];
- int ring_ref;
- void *sring;
- CharDriverState *chr;
- int backlog;
-};
-
-static void buffer_append(struct XenConsole *con)
-{
- struct buffer *buffer = &con->buffer;
- XENCONS_RING_IDX cons, prod, size;
- struct xencons_interface *intf = con->sring;
-
- cons = intf->out_cons;
- prod = intf->out_prod;
- xen_mb();
-
- size = prod - cons;
- if ((size == 0) || (size > sizeof(intf->out)))
- return;
-
- if ((buffer->capacity - buffer->size) < size) {
- buffer->capacity += (size + 1024);
- buffer->data = g_realloc(buffer->data, buffer->capacity);
- }
-
- while (cons != prod)
- buffer->data[buffer->size++] = intf->out[
- MASK_XENCONS_IDX(cons++, intf->out)];
-
- xen_mb();
- intf->out_cons = cons;
- xen_be_send_notify(&con->xendev);
-
- if (buffer->max_capacity &&
- buffer->size > buffer->max_capacity) {
- /* Discard the middle of the data. */
-
- size_t over = buffer->size - buffer->max_capacity;
- uint8_t *maxpos = buffer->data + buffer->max_capacity;
-
- memmove(maxpos - over, maxpos, over);
- buffer->data = g_realloc(buffer->data, buffer->max_capacity);
- buffer->size = buffer->capacity = buffer->max_capacity;
-
- if (buffer->consumed > buffer->max_capacity - over)
- buffer->consumed = buffer->max_capacity - over;
- }
-}
-
-static void buffer_advance(struct buffer *buffer, size_t len)
-{
- buffer->consumed += len;
- if (buffer->consumed == buffer->size) {
- buffer->consumed = 0;
- buffer->size = 0;
- }
-}
-
-static int ring_free_bytes(struct XenConsole *con)
-{
- struct xencons_interface *intf = con->sring;
- XENCONS_RING_IDX cons, prod, space;
-
- cons = intf->in_cons;
- prod = intf->in_prod;
- xen_mb();
-
- space = prod - cons;
- if (space > sizeof(intf->in))
- return 0; /* ring is screwed: ignore it */
-
- return (sizeof(intf->in) - space);
-}
-
-static int xencons_can_receive(void *opaque)
-{
- struct XenConsole *con = opaque;
- return ring_free_bytes(con);
-}
-
-static void xencons_receive(void *opaque, const uint8_t *buf, int len)
-{
- struct XenConsole *con = opaque;
- struct xencons_interface *intf = con->sring;
- XENCONS_RING_IDX prod;
- int i, max;
-
- max = ring_free_bytes(con);
- /* The can_receive() func limits this, but check again anyway */
- if (max < len)
- len = max;
-
- prod = intf->in_prod;
- for (i = 0; i < len; i++) {
- intf->in[MASK_XENCONS_IDX(prod++, intf->in)] =
- buf[i];
- }
- xen_wmb();
- intf->in_prod = prod;
- xen_be_send_notify(&con->xendev);
-}
-
-static void xencons_send(struct XenConsole *con)
-{
- ssize_t len, size;
-
- size = con->buffer.size - con->buffer.consumed;
- if (con->chr)
- len = qemu_chr_fe_write(con->chr, con->buffer.data + con->buffer.consumed,
- size);
- else
- len = size;
- if (len < 1) {
- if (!con->backlog) {
- con->backlog = 1;
- xen_be_printf(&con->xendev, 1, "backlog piling up, nobody listening?\n");
- }
- } else {
- buffer_advance(&con->buffer, len);
- if (con->backlog && len == size) {
- con->backlog = 0;
- xen_be_printf(&con->xendev, 1, "backlog is gone\n");
- }
- }
-}
-
-/* -------------------------------------------------------------------- */
-
-static int con_init(struct XenDevice *xendev)
-{
- struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
- char *type, *dom, label[32];
- int ret = 0;
- const char *output;
-
- /* setup */
- dom = xs_get_domain_path(xenstore, con->xendev.dom);
- if (!xendev->dev) {
- snprintf(con->console, sizeof(con->console), "%s/console", dom);
- } else {
- snprintf(con->console, sizeof(con->console), "%s/device/console/%d", dom, xendev->dev);
- }
- free(dom);
-
- type = xenstore_read_str(con->console, "type");
- if (!type || strcmp(type, "ioemu") != 0) {
- xen_be_printf(xendev, 1, "not for me (type=%s)\n", type);
- ret = -1;
- goto out;
- }
-
- output = xenstore_read_str(con->console, "output");
-
- /* no Xen override, use qemu output device */
- if (output == NULL) {
- con->chr = serial_hds[con->xendev.dev];
- } else {
- snprintf(label, sizeof(label), "xencons%d", con->xendev.dev);
- con->chr = qemu_chr_new(label, output, NULL);
- }
-
- xenstore_store_pv_console_info(con->xendev.dev, con->chr);
-
-out:
- g_free(type);
- return ret;
-}
-
-static int con_initialise(struct XenDevice *xendev)
-{
- struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
- int limit;
-
- if (xenstore_read_int(con->console, "ring-ref", &con->ring_ref) == -1)
- return -1;
- if (xenstore_read_int(con->console, "port", &con->xendev.remote_port) == -1)
- return -1;
- if (xenstore_read_int(con->console, "limit", &limit) == 0)
- con->buffer.max_capacity = limit;
-
- if (!xendev->dev) {
- xen_pfn_t mfn = con->ring_ref;
- con->sring = xenforeignmemory_map(xen_fmem, con->xendev.dom,
- PROT_READ|PROT_WRITE,
- 1, &mfn, NULL);
- } else {
- con->sring = xengnttab_map_grant_ref(xendev->gnttabdev, con->xendev.dom,
- con->ring_ref,
- PROT_READ|PROT_WRITE);
- }
- if (!con->sring)
- return -1;
-
- xen_be_bind_evtchn(&con->xendev);
- if (con->chr) {
- if (qemu_chr_fe_claim(con->chr) == 0) {
- qemu_chr_add_handlers(con->chr, xencons_can_receive,
- xencons_receive, NULL, con);
- } else {
- xen_be_printf(xendev, 0,
- "xen_console_init error chardev %s already used\n",
- con->chr->label);
- con->chr = NULL;
- }
- }
-
- xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n",
- con->ring_ref,
- con->xendev.remote_port,
- con->xendev.local_port,
- con->buffer.max_capacity);
- return 0;
-}
-
-static void con_disconnect(struct XenDevice *xendev)
-{
- struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
-
- if (con->chr) {
- qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL);
- qemu_chr_fe_release(con->chr);
- }
- xen_be_unbind_evtchn(&con->xendev);
-
- if (con->sring) {
- if (!xendev->dev) {
- xenforeignmemory_unmap(xen_fmem, con->sring, 1);
- } else {
- xengnttab_unmap(xendev->gnttabdev, con->sring, 1);
- }
- con->sring = NULL;
- }
-}
-
-static void con_event(struct XenDevice *xendev)
-{
- struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
-
- buffer_append(con);
- if (con->buffer.size - con->buffer.consumed)
- xencons_send(con);
-}
-
-/* -------------------------------------------------------------------- */
-
-struct XenDevOps xen_console_ops = {
- .size = sizeof(struct XenConsole),
- .flags = DEVOPS_FLAG_IGNORE_STATE|DEVOPS_FLAG_NEED_GNTDEV,
- .init = con_init,
- .initialise = con_initialise,
- .event = con_event,
- .disconnect = con_disconnect,
-};
diff --git a/qemu/hw/char/xilinx_uartlite.c b/qemu/hw/char/xilinx_uartlite.c
deleted file mode 100644
index 911af4a0d..000000000
--- a/qemu/hw/char/xilinx_uartlite.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * QEMU model of Xilinx uartlite.
- *
- * Copyright (c) 2009 Edgar E. Iglesias.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "qemu/osdep.h"
-#include "hw/sysbus.h"
-#include "sysemu/char.h"
-
-#define DUART(x)
-
-#define R_RX 0
-#define R_TX 1
-#define R_STATUS 2
-#define R_CTRL 3
-#define R_MAX 4
-
-#define STATUS_RXVALID 0x01
-#define STATUS_RXFULL 0x02
-#define STATUS_TXEMPTY 0x04
-#define STATUS_TXFULL 0x08
-#define STATUS_IE 0x10
-#define STATUS_OVERRUN 0x20
-#define STATUS_FRAME 0x40
-#define STATUS_PARITY 0x80
-
-#define CONTROL_RST_TX 0x01
-#define CONTROL_RST_RX 0x02
-#define CONTROL_IE 0x10
-
-#define TYPE_XILINX_UARTLITE "xlnx.xps-uartlite"
-#define XILINX_UARTLITE(obj) \
- OBJECT_CHECK(XilinxUARTLite, (obj), TYPE_XILINX_UARTLITE)
-
-typedef struct XilinxUARTLite {
- SysBusDevice parent_obj;
-
- MemoryRegion mmio;
- CharDriverState *chr;
- qemu_irq irq;
-
- uint8_t rx_fifo[8];
- unsigned int rx_fifo_pos;
- unsigned int rx_fifo_len;
-
- uint32_t regs[R_MAX];
-} XilinxUARTLite;
-
-static void uart_update_irq(XilinxUARTLite *s)
-{
- unsigned int irq;
-
- if (s->rx_fifo_len)
- s->regs[R_STATUS] |= STATUS_IE;
-
- irq = (s->regs[R_STATUS] & STATUS_IE) && (s->regs[R_CTRL] & CONTROL_IE);
- qemu_set_irq(s->irq, irq);
-}
-
-static void uart_update_status(XilinxUARTLite *s)
-{
- uint32_t r;
-
- r = s->regs[R_STATUS];
- r &= ~7;
- r |= 1 << 2; /* Tx fifo is always empty. We are fast :) */
- r |= (s->rx_fifo_len == sizeof (s->rx_fifo)) << 1;
- r |= (!!s->rx_fifo_len);
- s->regs[R_STATUS] = r;
-}
-
-static void xilinx_uartlite_reset(DeviceState *dev)
-{
- uart_update_status(XILINX_UARTLITE(dev));
-}
-
-static uint64_t
-uart_read(void *opaque, hwaddr addr, unsigned int size)
-{
- XilinxUARTLite *s = opaque;
- uint32_t r = 0;
- addr >>= 2;
- switch (addr)
- {
- case R_RX:
- r = s->rx_fifo[(s->rx_fifo_pos - s->rx_fifo_len) & 7];
- if (s->rx_fifo_len)
- s->rx_fifo_len--;
- uart_update_status(s);
- uart_update_irq(s);
- qemu_chr_accept_input(s->chr);
- break;
-
- default:
- if (addr < ARRAY_SIZE(s->regs))
- r = s->regs[addr];
- DUART(qemu_log("%s addr=%x v=%x\n", __func__, addr, r));
- break;
- }
- return r;
-}
-
-static void
-uart_write(void *opaque, hwaddr addr,
- uint64_t val64, unsigned int size)
-{
- XilinxUARTLite *s = opaque;
- uint32_t value = val64;
- unsigned char ch = value;
-
- addr >>= 2;
- switch (addr)
- {
- case R_STATUS:
- hw_error("write to UART STATUS?\n");
- break;
-
- case R_CTRL:
- if (value & CONTROL_RST_RX) {
- s->rx_fifo_pos = 0;
- s->rx_fifo_len = 0;
- }
- s->regs[addr] = value;
- break;
-
- case R_TX:
- if (s->chr)
- qemu_chr_fe_write(s->chr, &ch, 1);
-
- s->regs[addr] = value;
-
- /* hax. */
- s->regs[R_STATUS] |= STATUS_IE;
- break;
-
- default:
- DUART(printf("%s addr=%x v=%x\n", __func__, addr, value));
- if (addr < ARRAY_SIZE(s->regs))
- s->regs[addr] = value;
- break;
- }
- uart_update_status(s);
- uart_update_irq(s);
-}
-
-static const MemoryRegionOps uart_ops = {
- .read = uart_read,
- .write = uart_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
- .valid = {
- .min_access_size = 1,
- .max_access_size = 4
- }
-};
-
-static void uart_rx(void *opaque, const uint8_t *buf, int size)
-{
- XilinxUARTLite *s = opaque;
-
- /* Got a byte. */
- if (s->rx_fifo_len >= 8) {
- printf("WARNING: UART dropped char.\n");
- return;
- }
- s->rx_fifo[s->rx_fifo_pos] = *buf;
- s->rx_fifo_pos++;
- s->rx_fifo_pos &= 0x7;
- s->rx_fifo_len++;
-
- uart_update_status(s);
- uart_update_irq(s);
-}
-
-static int uart_can_rx(void *opaque)
-{
- XilinxUARTLite *s = opaque;
-
- return s->rx_fifo_len < sizeof(s->rx_fifo);
-}
-
-static void uart_event(void *opaque, int event)
-{
-
-}
-
-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);
-}
-
-static void xilinx_uartlite_init(Object *obj)
-{
- XilinxUARTLite *s = XILINX_UARTLITE(obj);
-
- sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
-
- memory_region_init_io(&s->mmio, obj, &uart_ops, s,
- "xlnx.xps-uartlite", R_MAX * 4);
- sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
-}
-
-static void xilinx_uartlite_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- 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;
-}
-
-static const TypeInfo xilinx_uartlite_info = {
- .name = TYPE_XILINX_UARTLITE,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(XilinxUARTLite),
- .instance_init = xilinx_uartlite_init,
- .class_init = xilinx_uartlite_class_init,
-};
-
-static void xilinx_uart_register_types(void)
-{
- type_register_static(&xilinx_uartlite_info);
-}
-
-type_init(xilinx_uart_register_types)