qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/8] hw/char/escc2: Add device


From: Jasper Lowell
Subject: [PATCH 1/8] hw/char/escc2: Add device
Date: Wed, 17 Jun 2020 18:23:55 +1000

The Ultra 5 (Darwin) machine that is emulated for the Sun4u architecture
ships with a SAB 82532 ESCC2 device that is used for providing the
default ttya/ttyb serial consoles. This device is introduced to
increment Sun4u emulation towards being hardware faithful. ISA support
is included so that the device can be attached to the Sun ebus.

Due to the complexity of the chip, the SAB 82532 ESCC2 is assumed to be
configured and used in the ASYNC serial mode. This is the case for
typical operating system drivers like those in Linux and OpenBSD.

While ASYNC serial mode is assumed, the implementation is designed with
the assumption that the full set of serial modes may be added at a later
date. Registers can not be represented as uint8_t when more than a
single serial mode is correctly implemented and so, the design avoids
assuming the data structure used for registers. Avoiding this assumption
leads to loops, rather than memset, along with a verbose switch case.
The verbose switch case also has the benefit of preemptively detangling
the jungle of features that the device supports.

Signed-off-by: Jasper Lowell <jasper.lowell@bt.com>
---
 hw/char/Kconfig         |   8 +
 hw/char/Makefile.objs   |   1 +
 hw/char/escc2.c         | 581 ++++++++++++++++++++++++++++++++++++++++
 hw/char/trace-events    |   4 +
 include/hw/char/escc2.h |  17 ++
 5 files changed, 611 insertions(+)
 create mode 100644 hw/char/escc2.c
 create mode 100644 include/hw/char/escc2.h

diff --git a/hw/char/Kconfig b/hw/char/Kconfig
index 40e7a8b8bb..87352a75d8 100644
--- a/hw/char/Kconfig
+++ b/hw/char/Kconfig
@@ -1,6 +1,14 @@
 config ESCC
     bool
 
+config ESCC2
+    bool
+
+config ESCC2_ISA
+    bool
+    depends on ISA_BUS
+    select ESCC2
+
 config PARALLEL
     bool
     default y
diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs
index 9e9a6c1aff..fd4766fd36 100644
--- a/hw/char/Makefile.objs
+++ b/hw/char/Makefile.objs
@@ -1,5 +1,6 @@
 common-obj-$(CONFIG_IPACK) += ipoctal232.o
 common-obj-$(CONFIG_ESCC) += escc.o
+common-obj-$(CONFIG_ESCC2) += escc2.o
 common-obj-$(CONFIG_NRF51_SOC) += nrf51_uart.o
 common-obj-$(CONFIG_PARALLEL) += parallel.o
 common-obj-$(CONFIG_ISA_BUS) += parallel-isa.o
diff --git a/hw/char/escc2.c b/hw/char/escc2.c
new file mode 100644
index 0000000000..94528b8a4c
--- /dev/null
+++ b/hw/char/escc2.c
@@ -0,0 +1,581 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU Enhanced Serial Communication Controller (ESCC2 v3.2).
+ * Modelled according to the user manual (version 07.96).
+ *
+ * Copyright (C) 2020 Jasper Lowell
+ */
+
+#include "qemu/osdep.h"
+#include "hw/char/escc2.h"
+#include "hw/isa/isa.h"
+#include "hw/qdev-properties.h"
+#include "qapi/error.h"
+#include "sysemu/reset.h"
+#include "trace.h"
+
+/* STAR. */
+#define REGISTER_STAR_OFFSET                    0x20
+
+/* CMDR. */
+#define REGISTER_CMDR_OFFSET                    0x20
+
+/* MODE. */
+#define REGISTER_MODE_OFFSET                    0x22
+
+/* TIMR. */
+#define REGISTER_TIMR_OFFSET                    0x23
+
+/* XON. */
+#define REGISTER_XON_OFFSET                     0x24
+
+/* XOFF. */
+#define REGISTER_XOFF_OFFSET                    0x25
+
+/* TCR. */
+#define REGISTER_TCR_OFFSET                     0x26
+
+/* DAFO. */
+#define REGISTER_DAFO_OFFSET                    0x27
+
+/* RFC. */
+#define REGISTER_RFC_OFFSET                     0x28
+
+/* RBCL. */
+#define REGISTER_RBCL_OFFSET                    0x2a
+
+/* XBCL. */
+#define REGISTER_XBCL_OFFSET                    0x2a
+
+/* RBCH. */
+#define REGISTER_RBCH_OFFSET                    0x2b
+
+/* XBCH. */
+#define REGISTER_XBCH_OFFSET                    0x2b
+
+/* CCR0. */
+#define REGISTER_CCR0_OFFSET                    0x2c
+
+/* CCR1. */
+#define REGISTER_CCR1_OFFSET                    0x2d
+
+/* CCR2. */
+#define REGISTER_CCR2_OFFSET                    0x2e
+
+/* CCR3. */
+#define REGISTER_CCR3_OFFSET                    0x2f
+
+/* TSAX. */
+#define REGISTER_TSAX_OFFSET                    0x30
+
+/* TSAR. */
+#define REGISTER_TSAR_OFFSET                    0x31
+
+/* XCCR. */
+#define REGISTER_XCCR_OFFSET                    0x32
+
+/* RCCR. */
+#define REGISTER_RCCR_OFFSET                    0x33
+
+/* VSTR. */
+#define REGISTER_VSTR_OFFSET                    0x34
+
+/* BGR. */
+#define REGISTER_BGR_OFFSET                     0x34
+
+/* TIC. */
+#define REGISTER_TIC_OFFSET                     0x35
+
+/* MXN. */
+#define REGISTER_MXN_OFFSET                     0x36
+
+/* MXF. */
+#define REGISTER_MXF_OFFSET                     0x37
+
+/* GIS. */
+#define REGISTER_GIS_OFFSET                     0x38
+
+/* IVA. */
+#define REGISTER_IVA_OFFSET                     0x38
+
+/* IPC. */
+#define REGISTER_IPC_OFFSET                     0x39
+
+/* ISR0. */
+#define REGISTER_ISR0_OFFSET                    0x3a
+
+/* IMR0. */
+#define REGISTER_IMR0_OFFSET                    0x3a
+
+/* ISR1. */
+#define REGISTER_ISR1_OFFSET                    0x3b
+
+/* IMR1. */
+#define REGISTER_IMR1_OFFSET                    0x3b
+
+/* PVR. */
+#define REGISTER_PVR_OFFSET                     0x3c
+
+/* PIS. */
+#define REGISTER_PIS_OFFSET                     0x3d
+
+/* PIM. */
+#define REGISTER_PIM_OFFSET                     0x3d
+
+/* PCR. */
+#define REGISTER_PCR_OFFSET                     0x3e
+
+/* CCR4. */
+#define REGISTER_CCR4_OFFSET                    0x3f
+
+enum {
+    REGISTER_STAR = 0,
+    REGISTER_CMDR,
+    REGISTER_MODE,
+    REGISTER_TIMR,
+    REGISTER_XON,
+    REGISTER_XOFF,
+    REGISTER_TCR,
+    REGISTER_DAFO,
+    REGISTER_RFC,
+    REGISTER_RBCL,
+    REGISTER_XBCL,
+    REGISTER_RBCH,
+    REGISTER_XBCH,
+    REGISTER_CCR0,
+    REGISTER_CCR1,
+    REGISTER_CCR2,
+    REGISTER_CCR3,
+    REGISTER_TSAX,
+    REGISTER_TSAR,
+    REGISTER_XCCR,
+    REGISTER_RCCR,
+    REGISTER_VSTR,
+    REGISTER_BGR,
+    REGISTER_TIC,
+    REGISTER_MXN,
+    REGISTER_MXF,
+    REGISTER_GIS,
+    REGISTER_IVA,
+    REGISTER_IPC,
+    REGISTER_ISR0,
+    REGISTER_IMR0,
+    REGISTER_ISR1,
+    REGISTER_IMR1,
+    REGISTER_PVR,
+    REGISTER_PIS,
+    REGISTER_PIM,
+    REGISTER_PCR,
+    REGISTER_CCR4,
+    /* End. */
+    REGISTER_COUNT
+};
+
+typedef struct ESCC2State ESCC2State;
+
+#define CHANNEL_FIFO_LENGTH                     0x20
+typedef struct ESCC2ChannelState {
+    ESCC2State *controller;
+
+    /*
+     * The SAB 82532 ships with 64 byte FIFO queues for transmitting and
+     * receiving but only 32 bytes are addressable.
+     */
+    uint8_t fifo_receive[CHANNEL_FIFO_LENGTH];
+    uint8_t fifo_transmit[CHANNEL_FIFO_LENGTH];
+
+    uint8_t register_set[REGISTER_COUNT];
+} ESCC2ChannelState;
+
+#define CHANNEL_A_OFFSET                        0x0
+#define CHANNEL_B_OFFSET                        0x40
+#define CHANNEL_LENGTH                          0x40
+
+#define REGISTER_READ(channel, idx) \
+    ((channel)->register_set[(idx)])
+#define REGISTER_WRITE(channel, idx, value) \
+    ((channel)->register_set[(idx)] = (value))
+
+enum {
+    CHANNEL_A = 0,
+    CHANNEL_B,
+    /* End. */
+    CHANNEL_COUNT
+};
+
+struct ESCC2State {
+    DeviceState parent;
+
+    MemoryRegion io;
+    ESCC2ChannelState channel[CHANNEL_COUNT];
+};
+
+#define CONTROLLER_CHANNEL_A(controller) (&(controller)->channel[CHANNEL_A])
+#define CONTROLLER_CHANNEL_B(controller) (&(controller)->channel[CHANNEL_B])
+#define CHANNEL_CHAR(channel) \
+    ((channel) == CONTROLLER_CHANNEL_A((channel)->controller) ? 'A' : 'B')
+
+typedef struct ESCC2ISAState {
+    ISADevice parent;
+    uint32_t iobase;
+    struct ESCC2State controller;
+} ESCC2ISAState;
+
+static void escc2_channel_reset(ESCC2ChannelState *channel)
+{
+    unsigned int i;
+
+    memset(channel->fifo_receive, 0, sizeof(channel->fifo_receive));
+    memset(channel->fifo_transmit, 0, sizeof(channel->fifo_transmit));
+    for (i = 0; i < REGISTER_COUNT; i++) {
+        channel->register_set[i] = 0;
+    }
+
+    channel->register_set[REGISTER_STAR] = 0x40;
+    channel->register_set[REGISTER_VSTR] = 0x2;
+}
+
+static void escc2_reset(void *opaque)
+{
+    unsigned int i;
+    ESCC2State *controller = opaque;
+
+    for (i = 0; i < CHANNEL_COUNT; i++) {
+        escc2_channel_reset(&controller->channel[i]);
+    }
+}
+
+static uint64_t escc2_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+    uint8_t value, offset;
+    ESCC2State *controller;
+    ESCC2ChannelState *channel;
+
+    assert(addr < (CHANNEL_COUNT * CHANNEL_LENGTH));
+    assert(size == sizeof(uint8_t));
+
+    controller = opaque;
+    if (addr < CHANNEL_LENGTH) {
+        channel = CONTROLLER_CHANNEL_A(controller);
+        offset = addr;
+    } else {
+        channel = CONTROLLER_CHANNEL_B(controller);
+        offset = addr - CHANNEL_LENGTH;
+    }
+
+    switch (offset) {
+    case 0 ... (CHANNEL_FIFO_LENGTH - 1):
+        value = channel->fifo_receive[offset];
+        break;
+    case REGISTER_STAR_OFFSET:
+        value = REGISTER_READ(channel, REGISTER_STAR);
+        break;
+    case REGISTER_MODE_OFFSET:
+        value = REGISTER_READ(channel, REGISTER_MODE);
+        break;
+    case REGISTER_TIMR_OFFSET:
+        value = REGISTER_READ(channel, REGISTER_TIMR);
+        break;
+    case REGISTER_XON_OFFSET:
+        value = REGISTER_READ(channel, REGISTER_XON);
+        break;
+    case REGISTER_XOFF_OFFSET:
+        value = REGISTER_READ(channel, REGISTER_XOFF);
+        break;
+    case REGISTER_TCR_OFFSET:
+        value = REGISTER_READ(channel, REGISTER_TCR);
+        break;
+    case REGISTER_DAFO_OFFSET:
+        value = REGISTER_READ(channel, REGISTER_DAFO);
+        break;
+    case REGISTER_RFC_OFFSET:
+        value = REGISTER_READ(channel, REGISTER_RFC);
+        break;
+    case REGISTER_RBCL_OFFSET:
+        value = REGISTER_READ(channel, REGISTER_RBCL);
+        break;
+    case REGISTER_RBCH_OFFSET:
+        value = REGISTER_READ(channel, REGISTER_RBCH);
+        break;
+    case REGISTER_CCR0_OFFSET:
+        value = REGISTER_READ(channel, REGISTER_CCR0);
+        break;
+    case REGISTER_CCR1_OFFSET:
+        value = REGISTER_READ(channel, REGISTER_CCR1);
+        break;
+    case REGISTER_CCR2_OFFSET:
+        value = REGISTER_READ(channel, REGISTER_CCR2);
+        break;
+    case REGISTER_CCR3_OFFSET:
+        value = REGISTER_READ(channel, REGISTER_CCR3);
+        break;
+    case REGISTER_VSTR_OFFSET:
+        value = REGISTER_READ(channel, REGISTER_VSTR);
+        break;
+    case REGISTER_GIS_OFFSET:
+        value = REGISTER_READ(channel, REGISTER_GIS);
+        break;
+    case REGISTER_IPC_OFFSET:
+        value = REGISTER_READ(channel, REGISTER_IPC);
+        break;
+    case REGISTER_ISR0_OFFSET:
+        value = REGISTER_READ(channel, REGISTER_ISR0);
+        break;
+    case REGISTER_ISR1_OFFSET:
+        value = REGISTER_READ(channel, REGISTER_ISR1);
+        break;
+    case REGISTER_PVR_OFFSET:
+        value = REGISTER_READ(channel, REGISTER_PVR);
+        break;
+    case REGISTER_PIS_OFFSET:
+        value = REGISTER_READ(channel, REGISTER_PIS);
+        break;
+    case REGISTER_PCR_OFFSET:
+        value = REGISTER_READ(channel, REGISTER_PCR);
+        break;
+    case REGISTER_CCR4_OFFSET:
+        value = REGISTER_READ(channel, REGISTER_CCR4);
+        break;
+    default:
+        value = 0;
+        break;
+    }
+
+    trace_escc2_mem_read(CHANNEL_CHAR(channel), offset, value);
+    return value;
+}
+
+static void escc2_mem_write(void *opaque, hwaddr addr, uint64_t value,
+        unsigned size)
+{
+    uint8_t offset;
+    ESCC2State *controller;
+    ESCC2ChannelState *channel;
+
+    assert(addr < (CHANNEL_COUNT * CHANNEL_LENGTH));
+    assert(size == sizeof(uint8_t));
+    assert(value <= 0xff);
+
+    controller = opaque;
+    if (addr < CHANNEL_LENGTH) {
+        channel = CONTROLLER_CHANNEL_A(controller);
+        offset = addr;
+    } else {
+        channel = CONTROLLER_CHANNEL_B(controller);
+        offset = addr - CHANNEL_LENGTH;
+    }
+
+    switch (offset) {
+    case 0 ... (CHANNEL_FIFO_LENGTH - 1):
+        channel->fifo_transmit[offset] = value;
+        break;
+    case REGISTER_CMDR_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_CMDR, value);
+        break;
+    case REGISTER_MODE_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_MODE, value);
+        break;
+    case REGISTER_TIMR_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_TIMR, value);
+        break;
+    case REGISTER_XON_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_XON, value);
+        break;
+    case REGISTER_XOFF_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_XOFF, value);
+        break;
+    case REGISTER_TCR_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_TCR, value);
+        break;
+    case REGISTER_DAFO_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_DAFO, value);
+        break;
+    case REGISTER_RFC_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_RFC, value);
+        break;
+    case REGISTER_XBCL_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_XBCL, value);
+        break;
+    case REGISTER_XBCH_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_XBCH, value);
+        break;
+    case REGISTER_CCR0_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_CCR0, value);
+        break;
+    case REGISTER_CCR1_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_CCR1, value);
+        break;
+    case REGISTER_CCR2_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_CCR2, value);
+        break;
+    case REGISTER_CCR3_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_CCR3, value);
+        break;
+    case REGISTER_TSAX_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_TSAX, value);
+        break;
+    case REGISTER_TSAR_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_TSAR, value);
+        break;
+    case REGISTER_XCCR_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_XCCR, value);
+        break;
+    case REGISTER_RCCR_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_RCCR, value);
+        break;
+    case REGISTER_BGR_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_BGR, value);
+        break;
+    case REGISTER_TIC_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_TIC, value);
+        break;
+    case REGISTER_MXN_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_MXN, value);
+        break;
+    case REGISTER_MXF_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_MXF, value);
+        break;
+    case REGISTER_IVA_OFFSET:
+        REGISTER_WRITE(CONTROLLER_CHANNEL_A(controller), REGISTER_IVA, value);
+        REGISTER_WRITE(CONTROLLER_CHANNEL_B(controller), REGISTER_IVA, value);
+        break;
+    case REGISTER_IPC_OFFSET:
+        REGISTER_WRITE(CONTROLLER_CHANNEL_A(controller), REGISTER_IPC, value);
+        REGISTER_WRITE(CONTROLLER_CHANNEL_B(controller), REGISTER_IPC, value);
+        break;
+    case REGISTER_IMR0_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_IMR0, value);
+        break;
+    case REGISTER_IMR1_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_IMR1, value);
+        break;
+    case REGISTER_PVR_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_PVR, value);
+        break;
+    case REGISTER_PIM_OFFSET:
+        REGISTER_WRITE(CONTROLLER_CHANNEL_A(controller), REGISTER_PIM, value);
+        REGISTER_WRITE(CONTROLLER_CHANNEL_B(controller), REGISTER_PIM, value);
+        break;
+    case REGISTER_PCR_OFFSET:
+        REGISTER_WRITE(CONTROLLER_CHANNEL_A(controller), REGISTER_PCR, value);
+        REGISTER_WRITE(CONTROLLER_CHANNEL_B(controller), REGISTER_PCR, value);
+        break;
+    case REGISTER_CCR4_OFFSET:
+        REGISTER_WRITE(channel, REGISTER_CCR4, value);
+        break;
+    default:
+        /* Registers do not exhaustively cover the addressable region. */
+        break;
+    }
+
+    trace_escc2_mem_write(CHANNEL_CHAR(channel), offset, value);
+}
+
+static void escc2_realize(DeviceState *dev, Error **errp)
+{
+    unsigned int i;
+    ESCC2ChannelState *channel;
+    ESCC2State *controller = ESCC2(dev);
+
+    for (i = 0; i < CHANNEL_COUNT; i++) {
+        channel = &controller->channel[i];
+        channel->controller = controller;
+    }
+
+    qemu_register_reset(escc2_reset, controller);
+    escc2_reset(controller);
+}
+
+const MemoryRegionOps escc2_mem_ops = {
+    .read = escc2_mem_read,
+    .write = escc2_mem_write,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1
+    },
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void escc2_isa_realize(DeviceState *dev, Error **errp)
+{
+    ESCC2ISAState *isa = ESCC2_ISA(dev);
+    ESCC2State *controller = &isa->controller;
+
+    if (isa->iobase == -1) {
+        error_setg(errp, "Base address must be provided.");
+        return;
+    }
+
+    object_property_set_bool(OBJECT(controller), true, "realized", errp);
+    if (*errp) {
+        return;
+    }
+
+    memory_region_init_io(&controller->io, OBJECT(dev), &escc2_mem_ops,
+            controller, "escc2", CHANNEL_COUNT * CHANNEL_LENGTH);
+    isa_register_ioport(ISA_DEVICE(dev), &controller->io, isa->iobase);
+}
+
+static void escc2_unrealize(DeviceState *dev)
+{
+    ESCC2State *controller = ESCC2(dev);
+    qemu_unregister_reset(escc2_reset, controller);
+}
+
+static void escc2_isa_instance_init(Object *o)
+{
+    ESCC2ISAState *self = ESCC2_ISA(o);
+    object_initialize_child(o, "escc2", &self->controller,
+            sizeof(self->controller), TYPE_ESCC2, &error_abort, NULL);
+    qdev_alias_all_properties(DEVICE(&self->controller), o);
+}
+
+static Property escc2_properties[] = {
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static Property escc2_isa_properties[] = {
+    DEFINE_PROP_UINT32("iobase", ESCC2ISAState, iobase, -1),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static void escc2_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->user_creatable = false;
+    dc->realize = escc2_realize;
+    dc->unrealize = escc2_unrealize;
+    device_class_set_props(dc, escc2_properties);
+}
+
+static void escc2_isa_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    device_class_set_props(dc, escc2_isa_properties);
+    dc->realize = escc2_isa_realize;
+}
+
+static const TypeInfo escc2_info = {
+    .name = TYPE_ESCC2,
+    .parent = TYPE_DEVICE,
+    .instance_size = sizeof(ESCC2State),
+    .class_init = escc2_class_init
+};
+
+static const TypeInfo escc2_isa_info = {
+    .name = TYPE_ESCC2_ISA,
+    .parent = TYPE_ISA_DEVICE,
+    .instance_size = sizeof(ESCC2ISAState),
+    .instance_init = escc2_isa_instance_init,
+    .class_init = escc2_isa_class_init
+};
+
+static void escc2_types(void)
+{
+    type_register_static(&escc2_info);
+    type_register_static(&escc2_isa_info);
+}
+
+type_init(escc2_types);
diff --git a/hw/char/trace-events b/hw/char/trace-events
index d20eafd56f..65c176f582 100644
--- a/hw/char/trace-events
+++ b/hw/char/trace-events
@@ -56,6 +56,10 @@ escc_sunkbd_event_out(int ch) "Translated keycode 0x%2.2x"
 escc_kbd_command(int val) "Command %d"
 escc_sunmouse_event(int dx, int dy, int buttons_state) "dx=%d dy=%d 
buttons=0x%01x"
 
+# escc2.c
+escc2_mem_read(char channel, uint32_t addr, uint8_t value) "channel %c addr 
0x%x value 0x%x"
+escc2_mem_write(char channel, uint32_t addr, uint8_t value) "channel %c addr 
0x%x value 0x%x"
+
 # pl011.c
 pl011_irq_state(int level) "irq state %d"
 pl011_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
diff --git a/include/hw/char/escc2.h b/include/hw/char/escc2.h
new file mode 100644
index 0000000000..ca2e34da3f
--- /dev/null
+++ b/include/hw/char/escc2.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU Enhanced Serial Communication Controller (ESCC2 v3.2).
+ * Modelled according to the user manual (version 07.96).
+ *
+ * Copyright (C) 2020 Jasper Lowell
+ */
+#ifndef HW_ESCC2_H
+#define HW_ESCC2_H
+
+#define TYPE_ESCC2      "ESCC2"
+#define ESCC2(obj)      OBJECT_CHECK(ESCC2State, (obj), TYPE_ESCC2)
+
+#define TYPE_ESCC2_ISA  "ESCC2_ISA"
+#define ESCC2_ISA(obj)  OBJECT_CHECK(ESCC2ISAState, (obj), TYPE_ESCC2_ISA)
+
+#endif /* HW_ESCC2_H */
-- 
2.26.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]