hw: move char devices to hw/char/, configure via default-configs/
authorPaolo Bonzini <pbonzini@redhat.com>
Tue, 5 Feb 2013 12:35:34 +0000 (13:35 +0100)
committerPaolo Bonzini <pbonzini@redhat.com>
Mon, 8 Apr 2013 16:13:14 +0000 (18:13 +0200)
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
42 files changed:
default-configs/arm-softmmu.mak
default-configs/i386-softmmu.mak
default-configs/lm32-softmmu.mak
default-configs/s390x-softmmu.mak
default-configs/sparc-softmmu.mak
default-configs/x86_64-softmmu.mak
hw/arm/Makefile.objs
hw/char/Makefile.objs
hw/char/debugcon.c [new file with mode: 0644]
hw/char/etraxfs_ser.c [new file with mode: 0644]
hw/char/exynos4210_uart.c [new file with mode: 0644]
hw/char/grlib_apbuart.c [new file with mode: 0644]
hw/char/imx_serial.c [new file with mode: 0644]
hw/char/lm32_juart.c [new file with mode: 0644]
hw/char/lm32_uart.c [new file with mode: 0644]
hw/char/mcf_uart.c [new file with mode: 0644]
hw/char/milkymist-uart.c [new file with mode: 0644]
hw/char/omap_uart.c [new file with mode: 0644]
hw/char/sclpconsole.c [new file with mode: 0644]
hw/char/sh_serial.c [new file with mode: 0644]
hw/char/spapr_vty.c [new file with mode: 0644]
hw/cris/Makefile.objs
hw/debugcon.c [deleted file]
hw/etraxfs_ser.c [deleted file]
hw/exynos4210_uart.c [deleted file]
hw/grlib_apbuart.c [deleted file]
hw/i386/Makefile.objs
hw/imx_serial.c [deleted file]
hw/lm32/Makefile.objs
hw/lm32_juart.c [deleted file]
hw/lm32_uart.c [deleted file]
hw/m68k/Makefile.objs
hw/mcf_uart.c [deleted file]
hw/milkymist-uart.c [deleted file]
hw/omap_uart.c [deleted file]
hw/ppc/Makefile.objs
hw/s390x/Makefile.objs
hw/s390x/sclpconsole.c [deleted file]
hw/sh4/Makefile.objs
hw/sh_serial.c [deleted file]
hw/spapr_vty.c [deleted file]
hw/sparc/Makefile.objs

index 8eb04e20bf028f743637127159b90e9f007bd7bc..8da5ec857edb3a80b71a791db51bc9ee7c2e0b81 100644 (file)
@@ -57,6 +57,7 @@ CONFIG_MARVELL_88W8618=y
 CONFIG_OMAP=y
 CONFIG_BLIZZARD=y
 CONFIG_ONENAND=y
+CONFIG_IMX=y
 CONFIG_ZAURUS=y
 
 CONFIG_VERSATILE_PCI=y
index 89aaff5faaee89ccae3fae75e43cda20d135d69a..9d852ff2d82c13e0fc050f8d97977256d132ab67 100644 (file)
@@ -34,3 +34,4 @@ CONFIG_MC146818RTC=y
 CONFIG_WDT_IB700=y
 CONFIG_PC_SYSFW=y
 CONFIG_XEN_I386=$(CONFIG_XEN)
+CONFIG_ISA_DEBUG=y
index 6b2ee430e5620fe8d1e6450c3b519266f5a0aa90..ef0f4bae72d1776718ad7f522dbab5a37c448327 100644 (file)
@@ -1,5 +1,6 @@
 # Default configuration for lm32-softmmu
 
+CONFIG_LM32=y
 CONFIG_MILKYMIST=y
 CONFIG_FRAMEBUFFER=y
 CONFIG_PTIMER=y
index 30057292047c1a905095f0ba2172ea78362a26aa..81fbc6865491bda5494b697efd7c221f7d3c2a7f 100644 (file)
@@ -1 +1,2 @@
 CONFIG_VIRTIO=y
+CONFIG_SCLPCONSOLE=y
index 25bcbe38bc781b50485dfd6210f1f5ef321b600b..da5b02d40517412b1041702640f8c2fbf51dfc73 100644 (file)
@@ -11,3 +11,4 @@ CONFIG_PCNET_COMMON=y
 CONFIG_LANCE=y
 CONFIG_TCX=y
 CONFIG_CS4231=y
+CONFIG_GRLIB=y
index c34f8f87597e7f81ce327dc535efe4d89ac31ae2..760d51e663ef9db9cccdabc7ada005f1f95df176 100644 (file)
@@ -34,3 +34,4 @@ CONFIG_MC146818RTC=y
 CONFIG_WDT_IB700=y
 CONFIG_PC_SYSFW=y
 CONFIG_XEN_I386=$(CONFIG_XEN)
+CONFIG_ISA_DEBUG=y
index 6f764e62fee6c1c116a62b1d989bdb3ff077d2a9..26e107f93c411ba15482ba45a677b23feb0f5bf6 100644 (file)
@@ -3,7 +3,7 @@ obj-y += arm_gic.o arm_gic_common.o
 obj-y += a9scu.o
 obj-y += realview_gic.o arm_sysctl.o arm11mpcore.o a9mpcore.o
 obj-y += exynos4210_gic.o exynos4210_combiner.o
-obj-y += exynos4210_uart.o exynos4210_pwm.o
+obj-y += exynos4210_pwm.o
 obj-y += exynos4210_pmu.o exynos4210_mct.o
 obj-y += exynos4210_rtc.o
 obj-y += arm_mptimer.o a15mpcore.o
@@ -12,14 +12,14 @@ obj-y += pxa2xx_timer.o pxa2xx_dma.o
 obj-y += pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
 obj-y += zaurus.o
 obj-y += omap_dma.o omap_clk.o omap_mmc.o \
-                omap_gpio.o omap_intc.o omap_uart.o
+                omap_gpio.o omap_intc.o
 obj-y += soc_dma.o omap_gptimer.o omap_synctimer.o \
                 omap_gpmc.o omap_sdrc.o omap_tap.o omap_l4.o
 obj-y += tsc210x.o
 obj-y += cbus.o tusb6010.o
 obj-y += mst_fpga.o
 obj-y += strongarm.o
-obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
+obj-y += imx_ccm.o imx_timer.o imx_avic.o
 obj-$(CONFIG_KVM) += kvm/arm_gic.o
 
 obj-y := $(addprefix ../,$(obj-y))
index ddfd3ec9cb10e4aa4662d1b6c20932c6ec08c96b..f8f3dbca3e2a498d49076893ff4ad20f9e741eac 100644 (file)
@@ -9,4 +9,19 @@ 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
+
+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
+
 obj-$(CONFIG_VIRTIO) += virtio-serial-bus.o
diff --git a/hw/char/debugcon.c b/hw/char/debugcon.c
new file mode 100644 (file)
index 0000000..0588eeb
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * 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 "hw/hw.h"
+#include "char/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%04x val=0x%02x\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%04x\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_init_core(DebugconState *s)
+{
+    if (!s->chr) {
+        fprintf(stderr, "Can't create debugcon device, empty char device\n");
+        exit(1);
+    }
+
+    qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, s);
+}
+
+static int debugcon_isa_initfn(ISADevice *dev)
+{
+    ISADebugconState *isa = ISA_DEBUGCON_DEVICE(dev);
+    DebugconState *s = &isa->state;
+
+    debugcon_init_core(s);
+    memory_region_init_io(&s->io, &debugcon_ops, s,
+                          TYPE_ISA_DEBUGCON_DEVICE, 1);
+    memory_region_add_subregion(isa_address_space_io(dev),
+                                isa->iobase, &s->io);
+    return 0;
+}
+
+static Property debugcon_isa_properties[] = {
+    DEFINE_PROP_HEX32("iobase", ISADebugconState, iobase, 0xe9),
+    DEFINE_PROP_CHR("chardev",  ISADebugconState, state.chr),
+    DEFINE_PROP_HEX32("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);
+    ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+    ic->init = debugcon_isa_initfn;
+    dc->props = debugcon_isa_properties;
+}
+
+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/hw/char/etraxfs_ser.c b/hw/char/etraxfs_ser.c
new file mode 100644 (file)
index 0000000..b7499d7
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * 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 "hw/sysbus.h"
+#include "char/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
+
+struct etrax_serial
+{
+    SysBusDevice busdev;
+    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];
+};
+
+static void ser_update_irq(struct etrax_serial *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)
+{
+    struct etrax_serial *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)
+{
+    struct etrax_serial *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)
+{
+    struct etrax_serial *s = opaque;
+    int i;
+
+    /* Got a byte.  */
+    if (s->rx_fifo_len >= 16) {
+        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)
+{
+    struct etrax_serial *s = opaque;
+    int r;
+
+    /* Is the receiver enabled?  */
+    if (!(s->regs[RW_REC_CTRL] & (1 << 3))) {
+        return 0;
+    }
+
+    r = sizeof(s->rx_fifo) - s->rx_fifo_len;
+    return r;
+}
+
+static void serial_event(void *opaque, int event)
+{
+
+}
+
+static void etraxfs_ser_reset(DeviceState *d)
+{
+    struct etrax_serial *s = container_of(d, typeof(*s), busdev.qdev);
+
+    /* 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)
+{
+    struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev);
+
+    sysbus_init_irq(dev, &s->irq);
+    memory_region_init_io(&s->mmio, &ser_ops, s, "etraxfs-serial", R_MAX * 4);
+    sysbus_init_mmio(dev, &s->mmio);
+
+    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;
+}
+
+static const TypeInfo etraxfs_ser_info = {
+    .name          = "etraxfs,serial",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(struct etrax_serial),
+    .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/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c
new file mode 100644 (file)
index 0000000..8b4e72c
--- /dev/null
@@ -0,0 +1,676 @@
+/*
+ *  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 "hw/sysbus.h"
+#include "sysemu/sysemu.h"
+#include "char/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;
+
+typedef struct {
+    SysBusDevice busdev;
+    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 regs_number = sizeof(exynos4210_uart_regs) / sizeof(Exynos4210UartReg);
+    int i;
+
+    for (i = 0; i < regs_number; 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)
+{
+    if (q->data != NULL) {
+        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 =
+            container_of(dev, Exynos4210UartState, busdev.qdev);
+    int regs_number = sizeof(exynos4210_uart_regs)/sizeof(Exynos4210UartReg);
+    int i;
+
+    for (i = 0; i < regs_number; 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,
+    .minimum_version_id_old = 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,
+    .minimum_version_id_old = 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, "exynos4210.uart");
+
+    if (!chr) {
+        if (channel >= MAX_SERIAL_PORTS) {
+            hw_error("Only %d serial ports are supported by QEMU.\n",
+                     MAX_SERIAL_PORTS);
+        }
+        chr = serial_hds[channel];
+        if (!chr) {
+            snprintf(label, ARRAY_SIZE(label), "%s%d", chr_name, channel);
+            chr = qemu_chr_new(label, "null", NULL);
+            if (!(chr)) {
+                hw_error("Can't assign serial port to UART%d.\n", channel);
+            }
+        }
+    }
+
+    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 = FROM_SYSBUS(Exynos4210UartState, dev);
+
+    /* memory mapping */
+    memory_region_init_io(&s->iomem, &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          = "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/hw/char/grlib_apbuart.c b/hw/char/grlib_apbuart.c
new file mode 100644 (file)
index 0000000..62f7990
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * 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 "hw/sysbus.h"
+#include "char/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
+
+typedef struct UART {
+    SysBusDevice busdev;
+    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 = FROM_SYSBUS(typeof(*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, &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 = container_of(d, UART, busdev.qdev);
+
+    /* 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          = "grlib,apbuart",
+    .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/hw/char/imx_serial.c b/hw/char/imx_serial.c
new file mode 100644 (file)
index 0000000..d7ec209
--- /dev/null
@@ -0,0 +1,467 @@
+/*
+ * IMX31 UARTS
+ *
+ * Copyright (c) 2008 OKL
+ * Originally Written by Hans Jiang
+ * Copyright (c) 2011 NICTA Pty Ltd.
+ *
+ * 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 "hw/hw.h"
+#include "hw/sysbus.h"
+#include "sysemu/sysemu.h"
+#include "char/char.h"
+#include "hw/arm/imx.h"
+
+//#define DEBUG_SERIAL 1
+#ifdef DEBUG_SERIAL
+#define DPRINTF(fmt, args...) \
+do { printf("imx_serial: " fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...) do {} while (0)
+#endif
+
+/*
+ * Define to 1 for messages about attempts to
+ * access unimplemented registers or similar.
+ */
+//#define DEBUG_IMPLEMENTATION 1
+#ifdef DEBUG_IMPLEMENTATION
+#  define IPRINTF(fmt, args...) \
+    do  { fprintf(stderr, "imx_serial: " fmt, ##args); } while (0)
+#else
+#  define IPRINTF(fmt, args...) do {} while (0)
+#endif
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    int32_t readbuff;
+
+    uint32_t usr1;
+    uint32_t usr2;
+    uint32_t ucr1;
+    uint32_t ucr2;
+    uint32_t uts1;
+
+    /*
+     * The registers below are implemented just so that the
+     * guest OS sees what it has written
+     */
+    uint32_t onems;
+    uint32_t ufcr;
+    uint32_t ubmr;
+    uint32_t ubrc;
+    uint32_t ucr3;
+
+    qemu_irq irq;
+    CharDriverState *chr;
+} IMXSerialState;
+
+static const VMStateDescription vmstate_imx_serial = {
+    .name = "imx-serial",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 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()
+    },
+};
+
+
+#define URXD_CHARRDY    (1<<15)   /* character read is valid */
+#define URXD_ERR        (1<<14)   /* Character has error */
+#define URXD_BRK        (1<<11)   /* Break received */
+
+#define USR1_PARTYER    (1<<15)   /* Parity Error */
+#define USR1_RTSS       (1<<14)   /* RTS pin status */
+#define USR1_TRDY       (1<<13)   /* Tx ready */
+#define USR1_RTSD       (1<<12)   /* RTS delta: pin changed state */
+#define USR1_ESCF       (1<<11)   /* Escape sequence interrupt */
+#define USR1_FRAMERR    (1<<10)   /* Framing error  */
+#define USR1_RRDY       (1<<9)    /* receiver ready */
+#define USR1_AGTIM      (1<<8)    /* Aging timer interrupt */
+#define USR1_DTRD       (1<<7)    /* DTR changed */
+#define USR1_RXDS       (1<<6)    /* Receiver is idle */
+#define USR1_AIRINT     (1<<5)    /* Aysnch IR interrupt */
+#define USR1_AWAKE      (1<<4)    /* Falling edge detected on RXd pin */
+
+#define USR2_ADET       (1<<15)   /* Autobaud complete */
+#define USR2_TXFE       (1<<14)   /* Transmit FIFO empty */
+#define USR2_DTRF       (1<<13)   /* DTR/DSR transition */
+#define USR2_IDLE       (1<<12)   /* UART has been idle for too long */
+#define USR2_ACST       (1<<11)   /* Autobaud counter stopped */
+#define USR2_RIDELT     (1<<10)   /* Ring Indicator delta */
+#define USR2_RIIN       (1<<9)    /* Ring Indicator Input */
+#define USR2_IRINT      (1<<8)    /* Serial Infrared Interrupt */
+#define USR2_WAKE       (1<<7)    /* Start bit detected */
+#define USR2_DCDDELT    (1<<6)    /* Data Carrier Detect delta */
+#define USR2_DCDIN      (1<<5)    /* Data Carrier Detect Input */
+#define USR2_RTSF       (1<<4)    /* RTS transition */
+#define USR2_TXDC       (1<<3)    /* Transmission complete */
+#define USR2_BRCD       (1<<2)    /* Break condition detected */
+#define USR2_ORE        (1<<1)    /* Overrun error */
+#define USR2_RDR        (1<<0)    /* Receive data ready */
+
+#define UCR1_TRDYEN     (1<<13)   /* Tx Ready Interrupt Enable */
+#define UCR1_RRDYEN     (1<<9)    /* Rx Ready Interrupt Enable */
+#define UCR1_TXMPTYEN   (1<<6)    /* Tx Empty Interrupt Enable */
+#define UCR1_UARTEN     (1<<0)    /* UART Enable */
+
+#define UCR2_TXEN       (1<<2)    /* Transmitter enable */
+#define UCR2_RXEN       (1<<1)    /* Receiver enable */
+#define UCR2_SRST       (1<<0)    /* Reset complete */
+
+#define UTS1_TXEMPTY    (1<<6)
+#define UTS1_RXEMPTY    (1<<5)
+#define UTS1_TXFULL     (1<<4)
+#define UTS1_RXFULL     (1<<3)
+
+static void imx_update(IMXSerialState *s)
+{
+    uint32_t flags;
+
+    flags = (s->usr1 & s->ucr1) & (USR1_TRDY|USR1_RRDY);
+    if (!(s->ucr1 & UCR1_TXMPTYEN)) {
+        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 = container_of(dev, IMXSerialState, busdev.qdev);
+
+    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=%x)\n", offset >> 2);
+    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);
+            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:
+        IPRINTF("imx_serial_read: bad offset: 0x%x\n", (int)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=%x, value = %x) to %s\n",
+            offset >> 2,
+            (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)) {
+                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 */
+        IPRINTF("Unimplemented Register %x written to\n", offset >> 2);
+        /* TODO */
+        break;
+
+    default:
+        IPRINTF("imx_serial_write: Bad offset 0x%x\n", (int)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 int imx_serial_init(SysBusDevice *dev)
+{
+    IMXSerialState *s = FROM_SYSBUS(IMXSerialState, dev);
+
+
+    memory_region_init_io(&s->iomem, &imx_serial_ops, s, "imx-serial", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_irq(dev, &s->irq);
+
+    if (s->chr) {
+        qemu_chr_add_handlers(s->chr, imx_can_receive, imx_receive,
+                              imx_event, s);
+    } else {
+        DPRINTF("No char dev for uart at 0x%lx\n",
+                (unsigned long)s->iomem.ram_addr);
+    }
+
+    return 0;
+}
+
+void imx_serial_create(int uart, const hwaddr addr, qemu_irq irq)
+{
+    DeviceState *dev;
+    SysBusDevice *bus;
+    CharDriverState *chr;
+    const char chr_name[] = "serial";
+    char label[ARRAY_SIZE(chr_name) + 1];
+
+    dev = qdev_create(NULL, "imx-serial");
+
+    if (uart >= MAX_SERIAL_PORTS) {
+        hw_error("Cannot assign uart %d: QEMU supports only %d ports\n",
+                 uart, MAX_SERIAL_PORTS);
+    }
+    chr = serial_hds[uart];
+    if (!chr) {
+        snprintf(label, ARRAY_SIZE(label), "%s%d", chr_name, uart);
+        chr = qemu_chr_new(label, "null", NULL);
+        if (!(chr)) {
+            hw_error("Can't assign serial port to imx-uart%d.\n", uart);
+        }
+    }
+
+    qdev_prop_set_chr(dev, "chardev", chr);
+    bus = SYS_BUS_DEVICE(dev);
+    qdev_init_nofail(dev);
+    if (addr != (hwaddr)-1) {
+        sysbus_mmio_map(bus, 0, addr);
+    }
+    sysbus_connect_irq(bus, 0, irq);
+
+}
+
+
+static Property imx32_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);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = imx_serial_init;
+    dc->vmsd = &vmstate_imx_serial;
+    dc->reset = imx_serial_reset_at_boot;
+    dc->desc = "i.MX series UART";
+    dc->props = imx32_serial_properties;
+}
+
+static const TypeInfo imx_serial_info = {
+    .name = "imx-serial",
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(IMXSerialState),
+    .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/hw/char/lm32_juart.c b/hw/char/lm32_juart.c
new file mode 100644 (file)
index 0000000..93f0d15
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ *  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 "hw/hw.h"
+#include "hw/sysbus.h"
+#include "trace.h"
+#include "char/char.h"
+
+#include "hw/lm32/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),
+};
+
+struct LM32JuartState {
+    SysBusDevice busdev;
+    CharDriverState *chr;
+
+    uint32_t jtx;
+    uint32_t jrx;
+};
+typedef struct LM32JuartState LM32JuartState;
+
+uint32_t lm32_juart_get_jtx(DeviceState *d)
+{
+    LM32JuartState *s = container_of(d, LM32JuartState, busdev.qdev);
+
+    trace_lm32_juart_get_jtx(s->jtx);
+    return s->jtx;
+}
+
+uint32_t lm32_juart_get_jrx(DeviceState *d)
+{
+    LM32JuartState *s = container_of(d, LM32JuartState, busdev.qdev);
+
+    trace_lm32_juart_get_jrx(s->jrx);
+    return s->jrx;
+}
+
+void lm32_juart_set_jtx(DeviceState *d, uint32_t jtx)
+{
+    LM32JuartState *s = container_of(d, LM32JuartState, busdev.qdev);
+    unsigned char ch = jtx & 0xff;
+
+    trace_lm32_juart_set_jtx(s->jtx);
+
+    s->jtx = jtx;
+    if (s->chr) {
+        qemu_chr_fe_write(s->chr, &ch, 1);
+    }
+}
+
+void lm32_juart_set_jrx(DeviceState *d, uint32_t jtx)
+{
+    LM32JuartState *s = container_of(d, LM32JuartState, busdev.qdev);
+
+    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 = container_of(d, LM32JuartState, busdev.qdev);
+
+    s->jtx = 0;
+    s->jrx = 0;
+}
+
+static int lm32_juart_init(SysBusDevice *dev)
+{
+    LM32JuartState *s = FROM_SYSBUS(typeof(*s), dev);
+
+    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,
+    .minimum_version_id_old = 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;
+}
+
+static const TypeInfo lm32_juart_info = {
+    .name          = "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/hw/char/lm32_uart.c b/hw/char/lm32_uart.c
new file mode 100644 (file)
index 0000000..32bc37a
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ *  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 "hw/hw.h"
+#include "hw/sysbus.h"
+#include "trace.h"
+#include "char/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),
+};
+
+struct LM32UartState {
+    SysBusDevice busdev;
+    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(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 = container_of(d, LM32UartState, busdev.qdev);
+    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 = FROM_SYSBUS(typeof(*s), dev);
+
+    sysbus_init_irq(dev, &s->irq);
+
+    memory_region_init_io(&s->iomem, &uart_ops, s, "uart", R_MAX * 4);
+    sysbus_init_mmio(dev, &s->iomem);
+
+    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,
+    .minimum_version_id_old = 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;
+}
+
+static const TypeInfo lm32_uart_info = {
+    .name          = "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/hw/char/mcf_uart.c b/hw/char/mcf_uart.c
new file mode 100644 (file)
index 0000000..6724b1b
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * ColdFire UART emulation.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ *
+ * This code is licensed under the GPL
+ */
+#include "hw/hw.h"
+#include "hw/m68k/mcf.h"
+#include "char/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) & 3) {
+    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, &mcf_uart_ops, s, "uart", 0x40);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
+}
diff --git a/hw/char/milkymist-uart.c b/hw/char/milkymist-uart.c
new file mode 100644 (file)
index 0000000..f3bdf69
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ *  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 "hw/hw.h"
+#include "hw/sysbus.h"
+#include "trace.h"
+#include "char/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),
+};
+
+struct MilkymistUartState {
+    SysBusDevice busdev;
+    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(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 = container_of(d, MilkymistUartState, busdev.qdev);
+    int i;
+
+    for (i = 0; i < R_MAX; i++) {
+        s->regs[i] = 0;
+    }
+
+    /* THRE is always set */
+    s->regs[R_STAT] = STAT_THRE;
+}
+
+static int milkymist_uart_init(SysBusDevice *dev)
+{
+    MilkymistUartState *s = FROM_SYSBUS(typeof(*s), dev);
+
+    sysbus_init_irq(dev, &s->irq);
+
+    memory_region_init_io(&s->regs_region, &uart_mmio_ops, s,
+            "milkymist-uart", R_MAX * 4);
+    sysbus_init_mmio(dev, &s->regs_region);
+
+    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_milkymist_uart = {
+    .name = "milkymist-uart",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 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);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = milkymist_uart_init;
+    dc->reset = milkymist_uart_reset;
+    dc->vmsd = &vmstate_milkymist_uart;
+}
+
+static const TypeInfo milkymist_uart_info = {
+    .name          = "milkymist-uart",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(MilkymistUartState),
+    .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/hw/char/omap_uart.c b/hw/char/omap_uart.c
new file mode 100644 (file)
index 0000000..26c1426
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * 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 "char/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 = (struct omap_uart_s *)
+            g_malloc0(sizeof(struct omap_uart_s));
+
+    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) {
+        return omap_badwidth_write8(opaque, addr, value);
+    }
+
+    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, &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/hw/char/sclpconsole.c b/hw/char/sclpconsole.c
new file mode 100644 (file)
index 0000000..42ed54c
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * 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 <hw/qdev.h>
+#include "qemu/thread.h"
+#include "qemu/error-report.h"
+
+#include "hw/s390x/sclp.h"
+#include "hw/s390x/event-facility.h"
+#include "char/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;
+    /* io vector                                                       */
+    uint8_t *iov;           /* iov buffer pointer                      */
+    uint8_t *iov_sclp;      /* pointer to SCLP read offset             */
+    uint8_t *iov_bs;        /* pointer byte stream read offset         */
+    uint32_t iov_data_len;  /* length of byte stream in buffer         */
+    uint32_t iov_sclp_rest; /* length of byte stream not read via SCLP */
+    qemu_irq irq_read_vt220;
+} 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;
+
+    return scon->iov ? SIZE_BUFFER_VT220 - scon->iov_data_len : 0;
+}
+
+/* Receive n bytes from character layer, save in iov buffer,
+ * and set event pending */
+static void receive_from_chr_layer(SCLPConsole *scon, const uint8_t *buf,
+                                   int size)
+{
+    assert(scon->iov);
+
+    /* 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_bs, buf, size);
+    scon->iov_data_len += size;
+    scon->iov_sclp_rest += size;
+    scon->iov_bs += size;
+    scon->event.event_pending = true;
+}
+
+/* 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);
+
+    receive_from_chr_layer(scon, buf, size);
+    /* trigger SCLP read operation */
+    qemu_irq_raise(scon->irq_read_vt220);
+}
+
+static void chr_event(void *opaque, int event)
+{
+    SCLPConsole *scon = opaque;
+
+    switch (event) {
+    case CHR_EVENT_OPENED:
+        if (!scon->iov) {
+            scon->iov = g_malloc0(SIZE_BUFFER_VT220);
+            scon->iov_sclp = scon->iov;
+            scon->iov_bs = scon->iov;
+            scon->iov_data_len = 0;
+            scon->iov_sclp_rest = 0;
+        }
+        break;
+    case CHR_EVENT_CLOSED:
+        if (scon->iov) {
+            g_free(scon->iov);
+            scon->iov = NULL;
+        }
+        break;
+    }
+}
+
+/* functions to be called by event facility */
+
+static int event_type(void)
+{
+    return 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_sclp, cons->iov_sclp_rest);
+        *size = cons->iov_sclp_rest + 1;
+        cons->iov_sclp = cons->iov;
+        cons->iov_bs = cons->iov;
+        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_sclp, avail);
+        *size = avail + 1;
+        cons->iov_sclp_rest -= avail;
+        cons->iov_sclp += avail;
+        /* more data pending */
+    }
+}
+
+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)
+{
+    ssize_t ret = 0;
+    const uint8_t *iov_offset;
+    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;
+    }
+
+    iov_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;
+            iov_offset += ret;
+        } else {
+            len = 0;
+        }
+    }
+
+    return ret;
+}
+
+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 void trigger_ascii_console_data(void *opaque, int n, int level)
+{
+    sclp_service_interrupt(0);
+}
+
+/* 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;
+    event->event_type = SCLP_EVENT_ASCII_CONSOLE_DATA;
+    if (scon->chr) {
+        qemu_chr_add_handlers(scon->chr, chr_can_read,
+                              chr_read, chr_event, scon);
+    }
+    scon->irq_read_vt220 = *qemu_allocate_irqs(trigger_ascii_console_data,
+                                               NULL, 1);
+
+    return 0;
+}
+
+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;
+    ec->init = console_init;
+    ec->exit = console_exit;
+    ec->get_send_mask = send_mask;
+    ec->get_receive_mask = receive_mask;
+    ec->event_type = event_type;
+    ec->read_event_data = read_event_data;
+    ec->write_event_data = write_event_data;
+}
+
+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/hw/char/sh_serial.c b/hw/char/sh_serial.c
new file mode 100644 (file)
index 0000000..450c7d8
--- /dev/null
@@ -0,0 +1,410 @@
+/*
+ * 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 "hw/hw.h"
+#include "hw/sh4/sh.h"
+#include "char/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;
+#if 0
+        case 0x18:
+            ret = s->fcr;
+            break;
+#endif
+        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, &sh_serial_ops, s,
+                          "serial", 0x100000000ULL);
+
+    memory_region_init_alias(&s->iomem_p4, "serial-p4", &s->iomem,
+                             0, 0x28);
+    memory_region_add_subregion(sysmem, P4ADDR(base), &s->iomem_p4);
+
+    memory_region_init_alias(&s->iomem_a7, "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/hw/char/spapr_vty.c b/hw/char/spapr_vty.c
new file mode 100644 (file)
index 0000000..9df018a
--- /dev/null
@@ -0,0 +1,221 @@
+#include "hw/qdev.h"
+#include "char/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;
+
+static int vty_can_receive(void *opaque)
+{
+    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)opaque;
+
+    return (dev->in - dev->out) < VTERM_BUFSIZE;
+}
+
+static void vty_receive(void *opaque, const uint8_t *buf, int size)
+{
+    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)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 = (VIOsPAPRVTYDevice *)sdev;
+    int n = 0;
+
+    while ((n < max) && (dev->out != dev->in)) {
+        buf[n++] = dev->buf[dev->out++ % VTERM_BUFSIZE];
+    }
+
+    return n;
+}
+
+void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len)
+{
+    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
+
+    /* FIXME: should check the qemu_chr_fe_write() return value */
+    qemu_chr_fe_write(dev->chardev, buf, len);
+}
+
+static int spapr_vty_init(VIOsPAPRDevice *sdev)
+{
+    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
+
+    if (!dev->chardev) {
+        fprintf(stderr, "spapr-vty: Can't create vty without a chardev!\n");
+        exit(1);
+    }
+
+    qemu_chr_add_handlers(dev->chardev, vty_can_receive,
+                          vty_receive, NULL, dev);
+
+    return 0;
+}
+
+/* Forward declaration */
+static target_ulong h_put_term_char(PowerPCCPU *cpu, sPAPREnvironment *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, sPAPREnvironment *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 void spapr_vty_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VIOsPAPRDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
+
+    k->init = spapr_vty_init;
+    k->dt_name = "vty";
+    k->dt_type = "serial";
+    k->dt_compatible = "hvterm1";
+    dc->props = spapr_vty_properties;
+}
+
+static const TypeInfo spapr_vty_info = {
+    .name          = "spapr-vty",
+    .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), "spapr-vty")) {
+            continue;
+        }
+
+        sdev = DO_UPCAST(VIOsPAPRDevice, qdev, 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(sPAPREnvironment *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);
+    }
+
+    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)
index e02365d5cdc0b841672e23458e13d89edb4ac7ae..c4d5189fc05d2a9e9dae55134c4f1fae9ec285c8 100644 (file)
@@ -2,7 +2,6 @@
 obj-y += etraxfs_dma.o
 obj-y += etraxfs_pic.o
 obj-y += etraxfs_timer.o
-obj-y += etraxfs_ser.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
diff --git a/hw/debugcon.c b/hw/debugcon.c
deleted file mode 100644 (file)
index 0588eeb..0000000
+++ /dev/null
@@ -1,134 +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 "hw/hw.h"
-#include "char/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%04x val=0x%02x\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%04x\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_init_core(DebugconState *s)
-{
-    if (!s->chr) {
-        fprintf(stderr, "Can't create debugcon device, empty char device\n");
-        exit(1);
-    }
-
-    qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, s);
-}
-
-static int debugcon_isa_initfn(ISADevice *dev)
-{
-    ISADebugconState *isa = ISA_DEBUGCON_DEVICE(dev);
-    DebugconState *s = &isa->state;
-
-    debugcon_init_core(s);
-    memory_region_init_io(&s->io, &debugcon_ops, s,
-                          TYPE_ISA_DEBUGCON_DEVICE, 1);
-    memory_region_add_subregion(isa_address_space_io(dev),
-                                isa->iobase, &s->io);
-    return 0;
-}
-
-static Property debugcon_isa_properties[] = {
-    DEFINE_PROP_HEX32("iobase", ISADebugconState, iobase, 0xe9),
-    DEFINE_PROP_CHR("chardev",  ISADebugconState, state.chr),
-    DEFINE_PROP_HEX32("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);
-    ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
-    ic->init = debugcon_isa_initfn;
-    dc->props = debugcon_isa_properties;
-}
-
-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/hw/etraxfs_ser.c b/hw/etraxfs_ser.c
deleted file mode 100644 (file)
index 7e24d34..0000000
+++ /dev/null
@@ -1,248 +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 "hw/sysbus.h"
-#include "char/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
-
-struct etrax_serial
-{
-    SysBusDevice busdev;
-    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];
-};
-
-static void ser_update_irq(struct etrax_serial *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)
-{
-    struct etrax_serial *s = opaque;
-    D(CPUCRISState *env = s->env);
-    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)
-{
-    struct etrax_serial *s = opaque;
-    uint32_t value = val64;
-    unsigned char ch = val64;
-    D(CPUCRISState *env = s->env);
-
-    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)
-{
-    struct etrax_serial *s = opaque;
-    int i;
-
-    /* Got a byte.  */
-    if (s->rx_fifo_len >= 16) {
-        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)
-{
-    struct etrax_serial *s = opaque;
-    int r;
-
-    /* Is the receiver enabled?  */
-    if (!(s->regs[RW_REC_CTRL] & (1 << 3))) {
-        return 0;
-    }
-
-    r = sizeof(s->rx_fifo) - s->rx_fifo_len;
-    return r;
-}
-
-static void serial_event(void *opaque, int event)
-{
-
-}
-
-static void etraxfs_ser_reset(DeviceState *d)
-{
-    struct etrax_serial *s = container_of(d, typeof(*s), busdev.qdev);
-
-    /* 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)
-{
-    struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev);
-
-    sysbus_init_irq(dev, &s->irq);
-    memory_region_init_io(&s->mmio, &ser_ops, s, "etraxfs-serial", R_MAX * 4);
-    sysbus_init_mmio(dev, &s->mmio);
-
-    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;
-}
-
-static const TypeInfo etraxfs_ser_info = {
-    .name          = "etraxfs,serial",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(struct etrax_serial),
-    .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/hw/exynos4210_uart.c b/hw/exynos4210_uart.c
deleted file mode 100644 (file)
index 8b4e72c..0000000
+++ /dev/null
@@ -1,676 +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 "hw/sysbus.h"
-#include "sysemu/sysemu.h"
-#include "char/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;
-
-typedef struct {
-    SysBusDevice busdev;
-    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 regs_number = sizeof(exynos4210_uart_regs) / sizeof(Exynos4210UartReg);
-    int i;
-
-    for (i = 0; i < regs_number; 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)
-{
-    if (q->data != NULL) {
-        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 =
-            container_of(dev, Exynos4210UartState, busdev.qdev);
-    int regs_number = sizeof(exynos4210_uart_regs)/sizeof(Exynos4210UartReg);
-    int i;
-
-    for (i = 0; i < regs_number; 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,
-    .minimum_version_id_old = 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,
-    .minimum_version_id_old = 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, "exynos4210.uart");
-
-    if (!chr) {
-        if (channel >= MAX_SERIAL_PORTS) {
-            hw_error("Only %d serial ports are supported by QEMU.\n",
-                     MAX_SERIAL_PORTS);
-        }
-        chr = serial_hds[channel];
-        if (!chr) {
-            snprintf(label, ARRAY_SIZE(label), "%s%d", chr_name, channel);
-            chr = qemu_chr_new(label, "null", NULL);
-            if (!(chr)) {
-                hw_error("Can't assign serial port to UART%d.\n", channel);
-            }
-        }
-    }
-
-    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 = FROM_SYSBUS(Exynos4210UartState, dev);
-
-    /* memory mapping */
-    memory_region_init_io(&s->iomem, &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          = "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/hw/grlib_apbuart.c b/hw/grlib_apbuart.c
deleted file mode 100644 (file)
index 62f7990..0000000
+++ /dev/null
@@ -1,293 +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 "hw/sysbus.h"
-#include "char/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
-
-typedef struct UART {
-    SysBusDevice busdev;
-    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 = FROM_SYSBUS(typeof(*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, &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 = container_of(d, UART, busdev.qdev);
-
-    /* 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          = "grlib,apbuart",
-    .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)
index c85bb3df1bc00e001df340e70b3ee4be5febf996..5e91d1e669b7d58882057be2259c10a6d917a79d 100644 (file)
@@ -1,7 +1,7 @@
 obj-y += apic_common.o apic.o
 obj-y += sga.o ioapic_common.o ioapic.o piix_pci.o
 obj-y += vmport.o
-obj-y += debugcon.o debugexit.o
+obj-y += debugexit.o
 obj-y += lpc_ich9.o q35.o
 obj-y += kvm/
 obj-y += pc-testdev.o
diff --git a/hw/imx_serial.c b/hw/imx_serial.c
deleted file mode 100644 (file)
index d7ec209..0000000
+++ /dev/null
@@ -1,467 +0,0 @@
-/*
- * IMX31 UARTS
- *
- * Copyright (c) 2008 OKL
- * Originally Written by Hans Jiang
- * Copyright (c) 2011 NICTA Pty Ltd.
- *
- * 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 "hw/hw.h"
-#include "hw/sysbus.h"
-#include "sysemu/sysemu.h"
-#include "char/char.h"
-#include "hw/arm/imx.h"
-
-//#define DEBUG_SERIAL 1
-#ifdef DEBUG_SERIAL
-#define DPRINTF(fmt, args...) \
-do { printf("imx_serial: " fmt , ##args); } while (0)
-#else
-#define DPRINTF(fmt, args...) do {} while (0)
-#endif
-
-/*
- * Define to 1 for messages about attempts to
- * access unimplemented registers or similar.
- */
-//#define DEBUG_IMPLEMENTATION 1
-#ifdef DEBUG_IMPLEMENTATION
-#  define IPRINTF(fmt, args...) \
-    do  { fprintf(stderr, "imx_serial: " fmt, ##args); } while (0)
-#else
-#  define IPRINTF(fmt, args...) do {} while (0)
-#endif
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    int32_t readbuff;
-
-    uint32_t usr1;
-    uint32_t usr2;
-    uint32_t ucr1;
-    uint32_t ucr2;
-    uint32_t uts1;
-
-    /*
-     * The registers below are implemented just so that the
-     * guest OS sees what it has written
-     */
-    uint32_t onems;
-    uint32_t ufcr;
-    uint32_t ubmr;
-    uint32_t ubrc;
-    uint32_t ucr3;
-
-    qemu_irq irq;
-    CharDriverState *chr;
-} IMXSerialState;
-
-static const VMStateDescription vmstate_imx_serial = {
-    .name = "imx-serial",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 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()
-    },
-};
-
-
-#define URXD_CHARRDY    (1<<15)   /* character read is valid */
-#define URXD_ERR        (1<<14)   /* Character has error */
-#define URXD_BRK        (1<<11)   /* Break received */
-
-#define USR1_PARTYER    (1<<15)   /* Parity Error */
-#define USR1_RTSS       (1<<14)   /* RTS pin status */
-#define USR1_TRDY       (1<<13)   /* Tx ready */
-#define USR1_RTSD       (1<<12)   /* RTS delta: pin changed state */
-#define USR1_ESCF       (1<<11)   /* Escape sequence interrupt */
-#define USR1_FRAMERR    (1<<10)   /* Framing error  */
-#define USR1_RRDY       (1<<9)    /* receiver ready */
-#define USR1_AGTIM      (1<<8)    /* Aging timer interrupt */
-#define USR1_DTRD       (1<<7)    /* DTR changed */
-#define USR1_RXDS       (1<<6)    /* Receiver is idle */
-#define USR1_AIRINT     (1<<5)    /* Aysnch IR interrupt */
-#define USR1_AWAKE      (1<<4)    /* Falling edge detected on RXd pin */
-
-#define USR2_ADET       (1<<15)   /* Autobaud complete */
-#define USR2_TXFE       (1<<14)   /* Transmit FIFO empty */
-#define USR2_DTRF       (1<<13)   /* DTR/DSR transition */
-#define USR2_IDLE       (1<<12)   /* UART has been idle for too long */
-#define USR2_ACST       (1<<11)   /* Autobaud counter stopped */
-#define USR2_RIDELT     (1<<10)   /* Ring Indicator delta */
-#define USR2_RIIN       (1<<9)    /* Ring Indicator Input */
-#define USR2_IRINT      (1<<8)    /* Serial Infrared Interrupt */
-#define USR2_WAKE       (1<<7)    /* Start bit detected */
-#define USR2_DCDDELT    (1<<6)    /* Data Carrier Detect delta */
-#define USR2_DCDIN      (1<<5)    /* Data Carrier Detect Input */
-#define USR2_RTSF       (1<<4)    /* RTS transition */
-#define USR2_TXDC       (1<<3)    /* Transmission complete */
-#define USR2_BRCD       (1<<2)    /* Break condition detected */
-#define USR2_ORE        (1<<1)    /* Overrun error */
-#define USR2_RDR        (1<<0)    /* Receive data ready */
-
-#define UCR1_TRDYEN     (1<<13)   /* Tx Ready Interrupt Enable */
-#define UCR1_RRDYEN     (1<<9)    /* Rx Ready Interrupt Enable */
-#define UCR1_TXMPTYEN   (1<<6)    /* Tx Empty Interrupt Enable */
-#define UCR1_UARTEN     (1<<0)    /* UART Enable */
-
-#define UCR2_TXEN       (1<<2)    /* Transmitter enable */
-#define UCR2_RXEN       (1<<1)    /* Receiver enable */
-#define UCR2_SRST       (1<<0)    /* Reset complete */
-
-#define UTS1_TXEMPTY    (1<<6)
-#define UTS1_RXEMPTY    (1<<5)
-#define UTS1_TXFULL     (1<<4)
-#define UTS1_RXFULL     (1<<3)
-
-static void imx_update(IMXSerialState *s)
-{
-    uint32_t flags;
-
-    flags = (s->usr1 & s->ucr1) & (USR1_TRDY|USR1_RRDY);
-    if (!(s->ucr1 & UCR1_TXMPTYEN)) {
-        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 = container_of(dev, IMXSerialState, busdev.qdev);
-
-    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=%x)\n", offset >> 2);
-    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);
-            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:
-        IPRINTF("imx_serial_read: bad offset: 0x%x\n", (int)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=%x, value = %x) to %s\n",
-            offset >> 2,
-            (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)) {
-                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 */
-        IPRINTF("Unimplemented Register %x written to\n", offset >> 2);
-        /* TODO */
-        break;
-
-    default:
-        IPRINTF("imx_serial_write: Bad offset 0x%x\n", (int)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 int imx_serial_init(SysBusDevice *dev)
-{
-    IMXSerialState *s = FROM_SYSBUS(IMXSerialState, dev);
-
-
-    memory_region_init_io(&s->iomem, &imx_serial_ops, s, "imx-serial", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-    sysbus_init_irq(dev, &s->irq);
-
-    if (s->chr) {
-        qemu_chr_add_handlers(s->chr, imx_can_receive, imx_receive,
-                              imx_event, s);
-    } else {
-        DPRINTF("No char dev for uart at 0x%lx\n",
-                (unsigned long)s->iomem.ram_addr);
-    }
-
-    return 0;
-}
-
-void imx_serial_create(int uart, const hwaddr addr, qemu_irq irq)
-{
-    DeviceState *dev;
-    SysBusDevice *bus;
-    CharDriverState *chr;
-    const char chr_name[] = "serial";
-    char label[ARRAY_SIZE(chr_name) + 1];
-
-    dev = qdev_create(NULL, "imx-serial");
-
-    if (uart >= MAX_SERIAL_PORTS) {
-        hw_error("Cannot assign uart %d: QEMU supports only %d ports\n",
-                 uart, MAX_SERIAL_PORTS);
-    }
-    chr = serial_hds[uart];
-    if (!chr) {
-        snprintf(label, ARRAY_SIZE(label), "%s%d", chr_name, uart);
-        chr = qemu_chr_new(label, "null", NULL);
-        if (!(chr)) {
-            hw_error("Can't assign serial port to imx-uart%d.\n", uart);
-        }
-    }
-
-    qdev_prop_set_chr(dev, "chardev", chr);
-    bus = SYS_BUS_DEVICE(dev);
-    qdev_init_nofail(dev);
-    if (addr != (hwaddr)-1) {
-        sysbus_mmio_map(bus, 0, addr);
-    }
-    sysbus_connect_irq(bus, 0, irq);
-
-}
-
-
-static Property imx32_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);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = imx_serial_init;
-    dc->vmsd = &vmstate_imx_serial;
-    dc->reset = imx_serial_reset_at_boot;
-    dc->desc = "i.MX series UART";
-    dc->props = imx32_serial_properties;
-}
-
-static const TypeInfo imx_serial_info = {
-    .name = "imx-serial",
-    .parent = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(IMXSerialState),
-    .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)
index a894c466ca7f956d24cd14a7b7306c434dc72bc4..e1161566adf376f799acc7a9d610447c6b13ce50 100644 (file)
@@ -1,15 +1,12 @@
 # LM32 peripherals
 obj-y += lm32_pic.o
-obj-y += lm32_juart.o
 obj-y += lm32_timer.o
-obj-y += lm32_uart.o
 obj-y += lm32_sys.o
 obj-y += milkymist-hpdmc.o
 obj-y += milkymist-memcard.o
 obj-y += milkymist-pfpu.o
 obj-y += milkymist-softusb.o
 obj-y += milkymist-sysctl.o
-obj-y += milkymist-uart.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
diff --git a/hw/lm32_juart.c b/hw/lm32_juart.c
deleted file mode 100644 (file)
index 93f0d15..0000000
+++ /dev/null
@@ -1,159 +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 "hw/hw.h"
-#include "hw/sysbus.h"
-#include "trace.h"
-#include "char/char.h"
-
-#include "hw/lm32/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),
-};
-
-struct LM32JuartState {
-    SysBusDevice busdev;
-    CharDriverState *chr;
-
-    uint32_t jtx;
-    uint32_t jrx;
-};
-typedef struct LM32JuartState LM32JuartState;
-
-uint32_t lm32_juart_get_jtx(DeviceState *d)
-{
-    LM32JuartState *s = container_of(d, LM32JuartState, busdev.qdev);
-
-    trace_lm32_juart_get_jtx(s->jtx);
-    return s->jtx;
-}
-
-uint32_t lm32_juart_get_jrx(DeviceState *d)
-{
-    LM32JuartState *s = container_of(d, LM32JuartState, busdev.qdev);
-
-    trace_lm32_juart_get_jrx(s->jrx);
-    return s->jrx;
-}
-
-void lm32_juart_set_jtx(DeviceState *d, uint32_t jtx)
-{
-    LM32JuartState *s = container_of(d, LM32JuartState, busdev.qdev);
-    unsigned char ch = jtx & 0xff;
-
-    trace_lm32_juart_set_jtx(s->jtx);
-
-    s->jtx = jtx;
-    if (s->chr) {
-        qemu_chr_fe_write(s->chr, &ch, 1);
-    }
-}
-
-void lm32_juart_set_jrx(DeviceState *d, uint32_t jtx)
-{
-    LM32JuartState *s = container_of(d, LM32JuartState, busdev.qdev);
-
-    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 = container_of(d, LM32JuartState, busdev.qdev);
-
-    s->jtx = 0;
-    s->jrx = 0;
-}
-
-static int lm32_juart_init(SysBusDevice *dev)
-{
-    LM32JuartState *s = FROM_SYSBUS(typeof(*s), dev);
-
-    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,
-    .minimum_version_id_old = 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;
-}
-
-static const TypeInfo lm32_juart_info = {
-    .name          = "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/hw/lm32_uart.c b/hw/lm32_uart.c
deleted file mode 100644 (file)
index 32bc37a..0000000
+++ /dev/null
@@ -1,297 +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 "hw/hw.h"
-#include "hw/sysbus.h"
-#include "trace.h"
-#include "char/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),
-};
-
-struct LM32UartState {
-    SysBusDevice busdev;
-    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(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 = container_of(d, LM32UartState, busdev.qdev);
-    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 = FROM_SYSBUS(typeof(*s), dev);
-
-    sysbus_init_irq(dev, &s->irq);
-
-    memory_region_init_io(&s->iomem, &uart_ops, s, "uart", R_MAX * 4);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    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,
-    .minimum_version_id_old = 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;
-}
-
-static const TypeInfo lm32_uart_info = {
-    .name          = "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)
index ebbe0038042f5a3cd59d5fb855cf149922237f96..c4352e783ad5902d780b5dd06ff074cca7c9e85c 100644 (file)
@@ -1,7 +1,3 @@
-obj-y = mcf_uart.o
-
-obj-y := $(addprefix ../,$(obj-y))
-
 obj-y += an5206.o mcf5208.o
 obj-y += dummy_m68k.o
 
diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c
deleted file mode 100644 (file)
index 6724b1b..0000000
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * ColdFire UART emulation.
- *
- * Copyright (c) 2007 CodeSourcery.
- *
- * This code is licensed under the GPL
- */
-#include "hw/hw.h"
-#include "hw/m68k/mcf.h"
-#include "char/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) & 3) {
-    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, &mcf_uart_ops, s, "uart", 0x40);
-    memory_region_add_subregion(sysmem, base, &s->iomem);
-}
diff --git a/hw/milkymist-uart.c b/hw/milkymist-uart.c
deleted file mode 100644 (file)
index f3bdf69..0000000
+++ /dev/null
@@ -1,244 +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 "hw/hw.h"
-#include "hw/sysbus.h"
-#include "trace.h"
-#include "char/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),
-};
-
-struct MilkymistUartState {
-    SysBusDevice busdev;
-    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(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 = container_of(d, MilkymistUartState, busdev.qdev);
-    int i;
-
-    for (i = 0; i < R_MAX; i++) {
-        s->regs[i] = 0;
-    }
-
-    /* THRE is always set */
-    s->regs[R_STAT] = STAT_THRE;
-}
-
-static int milkymist_uart_init(SysBusDevice *dev)
-{
-    MilkymistUartState *s = FROM_SYSBUS(typeof(*s), dev);
-
-    sysbus_init_irq(dev, &s->irq);
-
-    memory_region_init_io(&s->regs_region, &uart_mmio_ops, s,
-            "milkymist-uart", R_MAX * 4);
-    sysbus_init_mmio(dev, &s->regs_region);
-
-    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_milkymist_uart = {
-    .name = "milkymist-uart",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 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);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = milkymist_uart_init;
-    dc->reset = milkymist_uart_reset;
-    dc->vmsd = &vmstate_milkymist_uart;
-}
-
-static const TypeInfo milkymist_uart_info = {
-    .name          = "milkymist-uart",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(MilkymistUartState),
-    .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/hw/omap_uart.c b/hw/omap_uart.c
deleted file mode 100644 (file)
index 26c1426..0000000
+++ /dev/null
@@ -1,187 +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 "char/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 = (struct omap_uart_s *)
-            g_malloc0(sizeof(struct omap_uart_s));
-
-    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) {
-        return omap_badwidth_write8(opaque, addr, value);
-    }
-
-    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, &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);
-}
index 2d51ae9b42f57c9dbb0c1c9c8fcbc12118c6fe8a..1e24b582826ae4363158859f1fcb32f0e728aa8e 100644 (file)
@@ -1,5 +1,4 @@
 # IBM pSeries (sPAPR)
-obj-$(CONFIG_PSERIES) += spapr_vty.o
 obj-$(CONFIG_PSERIES) += spapr_pci.o
 obj-$(CONFIG_PSERIES) += spapr_nvram.o
 # PowerPC 4xx boards
index 9f2f41989c50ef17775642dcd865645ee6f7b43f..77e1218447a641930263d20517a2948dc89fdba9 100644 (file)
@@ -2,7 +2,7 @@ obj-y = s390-virtio-bus.o s390-virtio.o
 obj-y += s390-virtio-hcall.o
 obj-y += sclp.o
 obj-y += event-facility.o
-obj-y += sclpquiesce.o sclpconsole.o
+obj-y += sclpquiesce.o
 obj-y += ipl.o
 obj-y += css.o
 obj-y += s390-virtio-ccw.o
diff --git a/hw/s390x/sclpconsole.c b/hw/s390x/sclpconsole.c
deleted file mode 100644 (file)
index 5c881e5..0000000
+++ /dev/null
@@ -1,305 +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 <hw/qdev.h>
-#include "qemu/thread.h"
-#include "qemu/error-report.h"
-
-#include "hw/s390x/sclp.h"
-#include "hw/s390x/event-facility.h"
-#include "char/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;
-    /* io vector                                                       */
-    uint8_t *iov;           /* iov buffer pointer                      */
-    uint8_t *iov_sclp;      /* pointer to SCLP read offset             */
-    uint8_t *iov_bs;        /* pointer byte stream read offset         */
-    uint32_t iov_data_len;  /* length of byte stream in buffer         */
-    uint32_t iov_sclp_rest; /* length of byte stream not read via SCLP */
-    qemu_irq irq_read_vt220;
-} 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;
-
-    return scon->iov ? SIZE_BUFFER_VT220 - scon->iov_data_len : 0;
-}
-
-/* Receive n bytes from character layer, save in iov buffer,
- * and set event pending */
-static void receive_from_chr_layer(SCLPConsole *scon, const uint8_t *buf,
-                                   int size)
-{
-    assert(scon->iov);
-
-    /* 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_bs, buf, size);
-    scon->iov_data_len += size;
-    scon->iov_sclp_rest += size;
-    scon->iov_bs += size;
-    scon->event.event_pending = true;
-}
-
-/* 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);
-
-    receive_from_chr_layer(scon, buf, size);
-    /* trigger SCLP read operation */
-    qemu_irq_raise(scon->irq_read_vt220);
-}
-
-static void chr_event(void *opaque, int event)
-{
-    SCLPConsole *scon = opaque;
-
-    switch (event) {
-    case CHR_EVENT_OPENED:
-        if (!scon->iov) {
-            scon->iov = g_malloc0(SIZE_BUFFER_VT220);
-            scon->iov_sclp = scon->iov;
-            scon->iov_bs = scon->iov;
-            scon->iov_data_len = 0;
-            scon->iov_sclp_rest = 0;
-        }
-        break;
-    case CHR_EVENT_CLOSED:
-        if (scon->iov) {
-            g_free(scon->iov);
-            scon->iov = NULL;
-        }
-        break;
-    }
-}
-
-/* functions to be called by event facility */
-
-static int event_type(void)
-{
-    return 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_sclp, cons->iov_sclp_rest);
-        *size = cons->iov_sclp_rest + 1;
-        cons->iov_sclp = cons->iov;
-        cons->iov_bs = cons->iov;
-        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_sclp, avail);
-        *size = avail + 1;
-        cons->iov_sclp_rest -= avail;
-        cons->iov_sclp += avail;
-        /* more data pending */
-    }
-}
-
-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)
-{
-    ssize_t ret = 0;
-    const uint8_t *iov_offset;
-    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;
-    }
-
-    iov_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;
-            iov_offset += ret;
-        } else {
-            len = 0;
-        }
-    }
-
-    return ret;
-}
-
-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 void trigger_ascii_console_data(void *env, int n, int level)
-{
-    sclp_service_interrupt(0);
-}
-
-/* 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;
-    event->event_type = SCLP_EVENT_ASCII_CONSOLE_DATA;
-    if (scon->chr) {
-        qemu_chr_add_handlers(scon->chr, chr_can_read,
-                              chr_read, chr_event, scon);
-    }
-    scon->irq_read_vt220 = *qemu_allocate_irqs(trigger_ascii_console_data,
-                                               NULL, 1);
-
-    return 0;
-}
-
-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;
-    ec->init = console_init;
-    ec->exit = console_exit;
-    ec->get_send_mask = send_mask;
-    ec->get_receive_mask = receive_mask;
-    ec->event_type = event_type;
-    ec->read_event_data = read_event_data;
-    ec->write_event_data = write_event_data;
-}
-
-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)
index c9b0416b077b58013ecd5362d475f7f90959f414..10c971a3006ebf4b280bf2ceb899c4d08943b46b 100644 (file)
@@ -1,4 +1,4 @@
-obj-y += sh_timer.o sh_serial.o sh_intc.o sh_pci.o
+obj-y += sh_timer.o sh_intc.o sh_pci.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
diff --git a/hw/sh_serial.c b/hw/sh_serial.c
deleted file mode 100644 (file)
index 450c7d8..0000000
+++ /dev/null
@@ -1,410 +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 "hw/hw.h"
-#include "hw/sh4/sh.h"
-#include "char/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;
-#if 0
-        case 0x18:
-            ret = s->fcr;
-            break;
-#endif
-        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, &sh_serial_ops, s,
-                          "serial", 0x100000000ULL);
-
-    memory_region_init_alias(&s->iomem_p4, "serial-p4", &s->iomem,
-                             0, 0x28);
-    memory_region_add_subregion(sysmem, P4ADDR(base), &s->iomem_p4);
-
-    memory_region_init_alias(&s->iomem_a7, "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/hw/spapr_vty.c b/hw/spapr_vty.c
deleted file mode 100644 (file)
index 9df018a..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-#include "hw/qdev.h"
-#include "char/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;
-
-static int vty_can_receive(void *opaque)
-{
-    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)opaque;
-
-    return (dev->in - dev->out) < VTERM_BUFSIZE;
-}
-
-static void vty_receive(void *opaque, const uint8_t *buf, int size)
-{
-    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)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 = (VIOsPAPRVTYDevice *)sdev;
-    int n = 0;
-
-    while ((n < max) && (dev->out != dev->in)) {
-        buf[n++] = dev->buf[dev->out++ % VTERM_BUFSIZE];
-    }
-
-    return n;
-}
-
-void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len)
-{
-    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
-
-    /* FIXME: should check the qemu_chr_fe_write() return value */
-    qemu_chr_fe_write(dev->chardev, buf, len);
-}
-
-static int spapr_vty_init(VIOsPAPRDevice *sdev)
-{
-    VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
-
-    if (!dev->chardev) {
-        fprintf(stderr, "spapr-vty: Can't create vty without a chardev!\n");
-        exit(1);
-    }
-
-    qemu_chr_add_handlers(dev->chardev, vty_can_receive,
-                          vty_receive, NULL, dev);
-
-    return 0;
-}
-
-/* Forward declaration */
-static target_ulong h_put_term_char(PowerPCCPU *cpu, sPAPREnvironment *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, sPAPREnvironment *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 void spapr_vty_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    VIOsPAPRDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
-
-    k->init = spapr_vty_init;
-    k->dt_name = "vty";
-    k->dt_type = "serial";
-    k->dt_compatible = "hvterm1";
-    dc->props = spapr_vty_properties;
-}
-
-static const TypeInfo spapr_vty_info = {
-    .name          = "spapr-vty",
-    .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), "spapr-vty")) {
-            continue;
-        }
-
-        sdev = DO_UPCAST(VIOsPAPRDevice, qdev, 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(sPAPREnvironment *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);
-    }
-
-    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)
index 235461696848be0590927edebf91bb41242c928c..e18bc67fc7ebdbefad0b4b38e7f1a49c900b0af6 100644 (file)
@@ -3,7 +3,7 @@ obj-y += slavio_timer.o slavio_misc.o sparc32_dma.o
 obj-y += eccmemctl.o sbi.o sun4c_intctl.o
 
 # GRLIB
-obj-y += grlib_gptimer.o grlib_irqmp.o grlib_apbuart.o
+obj-y += grlib_gptimer.o grlib_irqmp.o
 
 obj-y := $(addprefix ../,$(obj-y))