* [PATCH 0/8] ESCC2
@ 2020-06-17 8:23 Jasper Lowell
2020-06-17 8:23 ` [PATCH 1/8] hw/char/escc2: Add device Jasper Lowell
` (10 more replies)
0 siblings, 11 replies; 12+ messages in thread
From: Jasper Lowell @ 2020-06-17 8:23 UTC (permalink / raw)
To: qemu-devel; +Cc: tony.nguyen, mark.cave-ayland, atar4qemu, Jasper Lowell
I've been working on improving Solaris 10 emulation for the SPARC64
Sun4u architecture with the goal of a working shell. Currently, Solaris
10 boots with a number of errors before displaying the prompt of an
otherwise unresponsive installer shell. It's been mentioned that this
problem may not be isolated to Solaris 10 but may affect derivatives of
OpenSolaris including illumos.
From what I can tell, Solaris 10 never attempts to use the 16550A UART
for the serial console. The kernel will probe registers to identify the
device but will not use it for receiving or transmitting. The kernel
only prints to the console using the prom interface that OpenBIOS
provides. It's difficult to ascertain what the problem is because there
is no visibility into the kernel. The 16550A UART on the Ultra 5
(Darwin), the machine that QEMU Sun4u is modelled against, is used for
the keyboard/mouse (SuperIO) and is not traditionally used for the
serial tty. Instead, the SAB 82532 ESCC2 is used to provide ttya and
ttyb on this system. This patch exists to increment QEMU Sun4u towards
being hardware faithful.
The SAB 82532 ESCC2 is complex because of the jungle of features that it
provides. Linux and OpenBSD only use a small subset of features
restricted to the ASYNC serial mode. The ASYNC serial mode is
relatively simple to implement in isolation. I have made progress on a
patch series that supports all serial modes, along with transitioning
between them, but I have decided against submitting it. The serial
controller appears to multiplex bit positions in registers across serial
modes while preserving the bits themselves. This means that some 8-bit
registers need to keep track of more than 8-bits of data and that the
interpretation of the value the register holds depends on the selected
serial mode. It's not ideal having a copy of each register for each
serial mode because some bits are shared across some of the register
modes. An added difficulty is that the manual doesn't document this
behaviour well and its unclear what exactly happens when there is a
transition in the selected serial mode. I've avoided depending on
registers being uint8_t and have made use of macros so that the backend
implementation of each register can be changed at a later date when
supporting other serial modes. If I have the opportunity to test real
hardware, or it becomes clear that HDLC/SDLC/BISYNC support is needed,
I'll look at upstreaming the other changes that I have.
I have written a bare-bones patch for OpenBIOS that adds this device to
the device tree. With that applied, Solaris identifies and attaches the
device successfully but does not interact with it further - similar to
the 16550A UART. I did notice, however, that Solaris 10 entered an
interrupt routine for this device when the network card was being
configured. I couldn't manage to provoke this behaviour for the 16550A
so this might be some small success. I strongly suspect that the
interrupt is a spurious interrupt caused by misconfiguration of the
devices in the firmware but I have not investigated this further.
Solaris 10, judging from the OpenSolaris source code, determines
stdin/stdout for the console by examining the stdin/stdout properties
under /chosen in the device tree. Naturally, this is done with the prom
interface. From what I can tell, to set these properties to the ESCC2
node it's necessary to change stdin/stdout for OpenBIOS completely. This
requires a device driver. I have made some progress on an OpenBIOS
device driver for the ESCC2 but it's taking longer than expected to
completely replace the 16550A and it's unlikely that I will have this
finished soon. It's possible that Solaris 10 emulation for this platform
will improve once that work is finished but it's unclear.
This is my first patch series for QEMU so it's possible that I've made
mistakes in the contribution process - sorry in advance.
Jasper Lowell (8):
hw/char/escc2: Add device
hw/char/escc2: Handle interrupt generation
hw/char/escc2: Add character device backend
hw/char/escc2: Add clock generation
hw/char/escc2: Add Receiver Reset (RRES) command
hw/char/escc2: Add RFRD command
hw/char/escc2: Add Transmit Frame (XF) command
hw/char/escc2: Add XRES command
hw/char/Kconfig | 8 +
hw/char/Makefile.objs | 1 +
hw/char/escc2.c | 1135 +++++++++++++++++++++++++++++++++++++++
hw/char/trace-events | 6 +
include/hw/char/escc2.h | 17 +
5 files changed, 1167 insertions(+)
create mode 100644 hw/char/escc2.c
create mode 100644 include/hw/char/escc2.h
--
2.26.2
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/8] hw/char/escc2: Add device
2020-06-17 8:23 [PATCH 0/8] ESCC2 Jasper Lowell
@ 2020-06-17 8:23 ` Jasper Lowell
2020-06-17 8:23 ` [PATCH 2/8] hw/char/escc2: Handle interrupt generation Jasper Lowell
` (9 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Jasper Lowell @ 2020-06-17 8:23 UTC (permalink / raw)
To: qemu-devel; +Cc: tony.nguyen, mark.cave-ayland, atar4qemu, Jasper Lowell
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
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/8] hw/char/escc2: Handle interrupt generation
2020-06-17 8:23 [PATCH 0/8] ESCC2 Jasper Lowell
2020-06-17 8:23 ` [PATCH 1/8] hw/char/escc2: Add device Jasper Lowell
@ 2020-06-17 8:23 ` Jasper Lowell
2020-06-17 8:23 ` [PATCH 3/8] hw/char/escc2: Add character device backend Jasper Lowell
` (8 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Jasper Lowell @ 2020-06-17 8:23 UTC (permalink / raw)
To: qemu-devel; +Cc: tony.nguyen, mark.cave-ayland, atar4qemu, Jasper Lowell
Signed-off-by: Jasper Lowell <jasper.lowell@bt.com>
---
hw/char/escc2.c | 88 ++++++++++++++++++++++++++++++++++++++++++++
hw/char/trace-events | 1 +
2 files changed, 89 insertions(+)
diff --git a/hw/char/escc2.c b/hw/char/escc2.c
index 94528b8a4c..926346482f 100644
--- a/hw/char/escc2.c
+++ b/hw/char/escc2.c
@@ -8,6 +8,7 @@
#include "qemu/osdep.h"
#include "hw/char/escc2.h"
+#include "hw/irq.h"
#include "hw/isa/isa.h"
#include "hw/qdev-properties.h"
#include "qapi/error.h"
@@ -55,6 +56,13 @@
/* CCR0. */
#define REGISTER_CCR0_OFFSET 0x2c
+#define REGISTER_CCR0_PU 0x80
+#define REGISTER_CCR0_MCE 0x40
+#define REGISTER_CCR0_SC2 0x10
+#define REGISTER_CCR0_SC1 0x8
+#define REGISTER_CCR0_SC0 0x4
+#define REGISTER_CCR0_SM1 0x2
+#define REGISTER_CCR0_SM0 0x1
/* CCR1. */
#define REGISTER_CCR1_OFFSET 0x2d
@@ -94,12 +102,23 @@
/* GIS. */
#define REGISTER_GIS_OFFSET 0x38
+#define REGISTER_GIS_PI 0x80
+#define REGISTER_GIS_ISA1 0x8
+#define REGISTER_GIS_ISA0 0x4
+#define REGISTER_GIS_ISB1 0x2
+#define REGISTER_GIS_ISB0 0x1
/* IVA. */
#define REGISTER_IVA_OFFSET 0x38
/* IPC. */
#define REGISTER_IPC_OFFSET 0x39
+#define REGISTER_IPC_VIS 0x80
+#define REGISTER_IPC_SLA1 0x10
+#define REGISTER_IPC_SLA0 0x8
+#define REGISTER_IPC_CASM 0x4
+#define REGISTER_IPC_IC1 0x2
+#define REGISTER_IPC_IC0 0x1
/* ISR0. */
#define REGISTER_ISR0_OFFSET 0x3a
@@ -207,6 +226,7 @@ struct ESCC2State {
DeviceState parent;
MemoryRegion io;
+ qemu_irq irq;
ESCC2ChannelState channel[CHANNEL_COUNT];
};
@@ -218,9 +238,62 @@ struct ESCC2State {
typedef struct ESCC2ISAState {
ISADevice parent;
uint32_t iobase;
+ uint32_t irq;
struct ESCC2State controller;
} ESCC2ISAState;
+static void escc2_irq_update(ESCC2State *controller)
+{
+ bool power;
+ uint8_t gis;
+ ESCC2ChannelState *a, *b;
+
+ gis = 0;
+ a = CONTROLLER_CHANNEL_A(controller);
+ b = CONTROLLER_CHANNEL_B(controller);
+
+ /*
+ * Interrupts are not propagated to the CPU when in power-down mode. There
+ * is an exception for interrupts from the universal port.
+ */
+ power = REGISTER_READ(a, REGISTER_CCR0) & REGISTER_CCR0_PU;
+
+ if (REGISTER_READ(a, REGISTER_ISR0) & ~(REGISTER_READ(a, REGISTER_IMR0))) {
+ gis |= REGISTER_GIS_ISA0;
+ }
+ if (REGISTER_READ(a, REGISTER_ISR1) & ~(REGISTER_READ(a, REGISTER_IMR1))) {
+ gis |= REGISTER_GIS_ISA1;
+ }
+
+ if (REGISTER_READ(b, REGISTER_ISR0) & ~(REGISTER_READ(b, REGISTER_IMR0))) {
+ gis |= REGISTER_GIS_ISB0;
+ }
+ if (REGISTER_READ(b, REGISTER_ISR1) & ~(REGISTER_READ(b, REGISTER_IMR1))) {
+ gis |= REGISTER_GIS_ISB1;
+ }
+
+ if (REGISTER_READ(a, REGISTER_PIS) & ~(REGISTER_READ(a, REGISTER_PIM))) {
+ gis |= REGISTER_GIS_PI;
+ /*
+ * Ensure that interrupts are propagated even if the controller is in
+ * power-down mode.
+ */
+ power = true;
+ }
+
+ /* GIS is accessible from either channel and must be synchronised. */
+ REGISTER_WRITE(a, REGISTER_GIS, gis);
+ REGISTER_WRITE(b, REGISTER_GIS, gis);
+
+ if (gis && power) {
+ qemu_irq_raise(controller->irq);
+ } else {
+ qemu_irq_lower(controller->irq);
+ }
+
+ trace_escc2_irq_update(gis);
+}
+
static void escc2_channel_reset(ESCC2ChannelState *channel)
{
unsigned int i;
@@ -320,15 +393,22 @@ static uint64_t escc2_mem_read(void *opaque, hwaddr addr, unsigned size)
break;
case REGISTER_ISR0_OFFSET:
value = REGISTER_READ(channel, REGISTER_ISR0);
+ REGISTER_WRITE(channel, REGISTER_ISR0, 0);
+ escc2_irq_update(controller);
break;
case REGISTER_ISR1_OFFSET:
value = REGISTER_READ(channel, REGISTER_ISR1);
+ REGISTER_WRITE(channel, REGISTER_ISR1, 0);
+ escc2_irq_update(controller);
break;
case REGISTER_PVR_OFFSET:
value = REGISTER_READ(channel, REGISTER_PVR);
break;
case REGISTER_PIS_OFFSET:
value = REGISTER_READ(channel, REGISTER_PIS);
+ REGISTER_WRITE(CONTROLLER_CHANNEL_A(controller), REGISTER_PIS, 0);
+ REGISTER_WRITE(CONTROLLER_CHANNEL_B(controller), REGISTER_PIS, 0);
+ escc2_irq_update(controller);
break;
case REGISTER_PCR_OFFSET:
value = REGISTER_READ(channel, REGISTER_PCR);
@@ -506,6 +586,13 @@ static void escc2_isa_realize(DeviceState *dev, Error **errp)
return;
}
+ if (isa->irq == -1) {
+ error_setg(errp, "IRQ must be provided.");
+ return;
+ }
+
+ isa_init_irq(ISA_DEVICE(dev), &controller->irq, isa->irq);
+
object_property_set_bool(OBJECT(controller), true, "realized", errp);
if (*errp) {
return;
@@ -536,6 +623,7 @@ static Property escc2_properties[] = {
static Property escc2_isa_properties[] = {
DEFINE_PROP_UINT32("iobase", ESCC2ISAState, iobase, -1),
+ DEFINE_PROP_UINT32("irq", ESCC2ISAState, irq, -1),
DEFINE_PROP_END_OF_LIST()
};
diff --git a/hw/char/trace-events b/hw/char/trace-events
index 65c176f582..b4f4f30815 100644
--- a/hw/char/trace-events
+++ b/hw/char/trace-events
@@ -57,6 +57,7 @@ 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_irq_update(uint8_t gis) "value 0x%x"
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"
--
2.26.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 3/8] hw/char/escc2: Add character device backend
2020-06-17 8:23 [PATCH 0/8] ESCC2 Jasper Lowell
2020-06-17 8:23 ` [PATCH 1/8] hw/char/escc2: Add device Jasper Lowell
2020-06-17 8:23 ` [PATCH 2/8] hw/char/escc2: Handle interrupt generation Jasper Lowell
@ 2020-06-17 8:23 ` Jasper Lowell
2020-06-17 8:23 ` [PATCH 4/8] hw/char/escc2: Add clock generation Jasper Lowell
` (7 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Jasper Lowell @ 2020-06-17 8:23 UTC (permalink / raw)
To: qemu-devel; +Cc: tony.nguyen, mark.cave-ayland, atar4qemu, Jasper Lowell
Signed-off-by: Jasper Lowell <jasper.lowell@bt.com>
---
hw/char/escc2.c | 234 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 234 insertions(+)
diff --git a/hw/char/escc2.c b/hw/char/escc2.c
index 926346482f..e16049ce4d 100644
--- a/hw/char/escc2.c
+++ b/hw/char/escc2.c
@@ -7,6 +7,8 @@
*/
#include "qemu/osdep.h"
+#include "chardev/char-fe.h"
+#include "chardev/char-serial.h"
#include "hw/char/escc2.h"
#include "hw/irq.h"
#include "hw/isa/isa.h"
@@ -17,6 +19,13 @@
/* STAR. */
#define REGISTER_STAR_OFFSET 0x20
+#define REGISTER_STAR_XDOV 0x80
+#define REGISTER_STAR_XFW 0x40
+#define REGISTER_STAR_RFNE 0x20
+#define REGISTER_STAR_FCS 0x10
+#define REGISTER_STAR_TEC 0x8
+#define REGISTER_STAR_CEC 0x4
+#define REGISTER_STAR_CTS 0x2
/* CMDR. */
#define REGISTER_CMDR_OFFSET 0x20
@@ -38,9 +47,40 @@
/* DAFO. */
#define REGISTER_DAFO_OFFSET 0x27
+#define REGISTER_DAFO_XBRK 0x40
+#define REGISTER_DAFO_STOP 0x20
+#define REGISTER_DAFO_PAR1 0x10
+#define REGISTER_DAFO_PAR0 0x8
+#define REGISTER_DAFO_PARE 0x4
+#define REGISTER_DAFO_CHL1 0x2
+#define REGISTER_DAFO_CHL0 0x1
+
+#define REGISTER_DAFO_PAR_MASK \
+ (REGISTER_DAFO_PAR1 | REGISTER_DAFO_PAR0)
+#define REGISTER_DAFO_PAR_SPACE 0x0
+#define REGISTER_DAFO_PAR_ODD (REGISTER_DAFO_PAR0)
+#define REGISTER_DAFO_PAR_EVEN (REGISTER_DAFO_PAR1)
+#define REGISTER_DAFO_PAR_MARK \
+ (REGISTER_DAFO_PAR1 | REGISTER_DAFO_PAR0)
+#define REGISTER_DAFO_CHL_MASK \
+ (REGISTER_DAFO_CHL1 | REGISTER_DAFO_CHL0)
+#define REGISTER_DAFO_CHL_CS8 0x0
+#define REGISTER_DAFO_CHL_CS7 (REGISTER_DAFO_CHL0)
+#define REGISTER_DAFO_CHL_CS6 (REGISTER_DAFO_CHL1)
+#define REGISTER_DAFO_CHL_CS5 \
+ (REGISTER_DAFO_CHL1 | REGISTER_DAFO_CHL0)
/* RFC. */
#define REGISTER_RFC_OFFSET 0x28
+#define REGISTER_RFC_DPS 0x40
+#define REGISTER_RFC_DXS 0x20
+#define REGISTER_RFC_RFDF 0x10
+#define REGISTER_RFC_RFTH1 0x8
+#define REGISTER_RFC_RFTH0 0x4
+#define REGISTER_RFC_TCDE 0x1
+
+#define REGISTER_RFC_RFTH_MASK \
+ (REGISTER_RFC_RFTH1 | REGISTER_RFC_RFTH0)
/* RBCL. */
#define REGISTER_RBCL_OFFSET 0x2a
@@ -122,6 +162,14 @@
/* ISR0. */
#define REGISTER_ISR0_OFFSET 0x3a
+#define REGISTER_ISR0_TCD 0x80
+#define REGISTER_ISR0_TIME 0x40
+#define REGISTER_ISR0_PERR 0x20
+#define REGISTER_ISR0_FERR 0x10
+#define REGISTER_ISR0_PLLA 0x8
+#define REGISTER_ISR0_CDSC 0x4
+#define REGISTER_ISR0_RFO 0x2
+#define REGISTER_ISR0_RPF 0x1
/* IMR0. */
#define REGISTER_IMR0_OFFSET 0x3a
@@ -196,6 +244,8 @@ typedef struct ESCC2State ESCC2State;
typedef struct ESCC2ChannelState {
ESCC2State *controller;
+ CharBackend chardev;
+
/*
* The SAB 82532 ships with 64 byte FIFO queues for transmitting and
* receiving but only 32 bytes are addressable.
@@ -294,6 +344,102 @@ static void escc2_irq_update(ESCC2State *controller)
trace_escc2_irq_update(gis);
}
+static void escc2_channel_irq_event(ESCC2ChannelState *channel,
+ uint8_t status_register, uint8_t event)
+{
+ /*
+ * Ensure that event does not have more than one bit set when calling this
+ * function.
+ */
+ uint8_t mask, tmp;
+
+ switch (status_register) {
+ case REGISTER_ISR0:
+ mask = REGISTER_READ(channel, REGISTER_IMR0);
+ break;
+ case REGISTER_ISR1:
+ mask = REGISTER_READ(channel, REGISTER_IMR1);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ if ((event & ~(mask))
+ || (REGISTER_READ(channel, REGISTER_IPC) & REGISTER_IPC_VIS)) {
+ tmp = REGISTER_READ(channel, status_register);
+ tmp |= event;
+ REGISTER_WRITE(channel, status_register, tmp);
+ }
+
+ if (event & ~(mask)) {
+ escc2_irq_update(channel->controller);
+ }
+}
+
+static void escc2_channel_parameters_update(ESCC2ChannelState *channel)
+{
+ uint8_t dafo;
+ QEMUSerialSetParams ssp;
+
+ if (!qemu_chr_fe_backend_connected(&channel->chardev)) {
+ return;
+ }
+
+ /* Check if parity is enabled. */
+ dafo = REGISTER_READ(channel, REGISTER_DAFO);
+ if (dafo & REGISTER_DAFO_PARE) {
+ /* Determine the parity. */
+ switch (dafo & REGISTER_DAFO_PAR_MASK) {
+ case REGISTER_DAFO_PAR_SPACE:
+ case REGISTER_DAFO_PAR_MARK:
+ /*
+ * XXX: QEMU doesn't support stick parity yet. Silently fail and
+ * fall to the next case.
+ */
+ case REGISTER_DAFO_PAR_ODD:
+ ssp.parity = 'O';
+ break;
+ case REGISTER_DAFO_PAR_EVEN:
+ ssp.parity = 'E';
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ } else {
+ ssp.parity = 'N';
+ }
+
+ /* Determine the number of data bits. */
+ switch (dafo & REGISTER_DAFO_CHL_MASK) {
+ case REGISTER_DAFO_CHL_CS8:
+ ssp.data_bits = 8;
+ break;
+ case REGISTER_DAFO_CHL_CS7:
+ ssp.data_bits = 7;
+ break;
+ case REGISTER_DAFO_CHL_CS6:
+ ssp.data_bits = 6;
+ break;
+ case REGISTER_DAFO_CHL_CS5:
+ ssp.data_bits = 5;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ /* Determine the number of stop bits. */
+ if (dafo & REGISTER_DAFO_STOP) {
+ ssp.stop_bits = 2;
+ } else {
+ ssp.stop_bits = 1;
+ }
+
+ /* XXX */
+ ssp.speed = 0;
+
+ qemu_chr_fe_ioctl(&channel->chardev, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
+}
+
static void escc2_channel_reset(ESCC2ChannelState *channel)
{
unsigned int i;
@@ -469,6 +615,7 @@ static void escc2_mem_write(void *opaque, hwaddr addr, uint64_t value,
break;
case REGISTER_DAFO_OFFSET:
REGISTER_WRITE(channel, REGISTER_DAFO, value);
+ escc2_channel_parameters_update(channel);
break;
case REGISTER_RFC_OFFSET:
REGISTER_WRITE(channel, REGISTER_RFC, value);
@@ -484,6 +631,7 @@ static void escc2_mem_write(void *opaque, hwaddr addr, uint64_t value,
break;
case REGISTER_CCR1_OFFSET:
REGISTER_WRITE(channel, REGISTER_CCR1, value);
+ escc2_channel_parameters_update(channel);
break;
case REGISTER_CCR2_OFFSET:
REGISTER_WRITE(channel, REGISTER_CCR2, value);
@@ -505,9 +653,11 @@ static void escc2_mem_write(void *opaque, hwaddr addr, uint64_t value,
break;
case REGISTER_BGR_OFFSET:
REGISTER_WRITE(channel, REGISTER_BGR, value);
+ escc2_channel_parameters_update(channel);
break;
case REGISTER_TIC_OFFSET:
REGISTER_WRITE(channel, REGISTER_TIC, value);
+ qemu_chr_fe_write_all(&channel->chardev, (uint8_t *)&value, 1);
break;
case REGISTER_MXN_OFFSET:
REGISTER_WRITE(channel, REGISTER_MXN, value);
@@ -542,6 +692,7 @@ static void escc2_mem_write(void *opaque, hwaddr addr, uint64_t value,
break;
case REGISTER_CCR4_OFFSET:
REGISTER_WRITE(channel, REGISTER_CCR4, value);
+ escc2_channel_parameters_update(channel);
break;
default:
/* Registers do not exhaustively cover the addressable region. */
@@ -551,6 +702,74 @@ static void escc2_mem_write(void *opaque, hwaddr addr, uint64_t value,
trace_escc2_mem_write(CHANNEL_CHAR(channel), offset, value);
}
+static unsigned int escc2_channel_rfifo_threshold(ESCC2ChannelState *channel)
+{
+ unsigned int threshold;
+
+ switch (REGISTER_READ(channel, REGISTER_RFC) & REGISTER_RFC_RFTH_MASK) {
+ case 0:
+ threshold = 1;
+ break;
+ case 1:
+ threshold = 4;
+ break;
+ case 2:
+ threshold = 16;
+ break;
+ case 3:
+ threshold = 32;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ return threshold;
+}
+
+static int escc2_channel_chardev_can_receive(void *opaque)
+{
+ uint8_t tmp;
+ ESCC2ChannelState *channel = opaque;
+ unsigned int threshold = escc2_channel_rfifo_threshold(channel);
+
+ tmp = REGISTER_READ(channel, REGISTER_RBCL);
+ if (threshold > tmp) {
+ return threshold - tmp;
+ } else {
+ return 0;
+ }
+}
+
+static void escc2_channel_chardev_receive(void *opaque, const uint8_t *buf,
+ int size)
+{
+ uint8_t tmp, rbcl;
+ unsigned int i, nbytes;
+ ESCC2ChannelState *channel = opaque;
+
+ /* Determine the number of characters that can be safely consumed. */
+ rbcl = REGISTER_READ(channel, REGISTER_RBCL);
+ if (rbcl + size > CHANNEL_FIFO_LENGTH) {
+ nbytes = CHANNEL_FIFO_LENGTH - rbcl;
+ } else {
+ nbytes = size;
+ }
+
+ /* Consume characters. */
+ for (i = 0; i < nbytes; i++) {
+ channel->fifo_receive[rbcl + i] = buf[i];
+ }
+ REGISTER_WRITE(channel, REGISTER_RBCL, rbcl + nbytes);
+
+ tmp = REGISTER_READ(channel, REGISTER_STAR);
+ tmp |= REGISTER_STAR_RFNE;
+ REGISTER_WRITE(channel, REGISTER_STAR, tmp);
+
+ if (escc2_channel_chardev_can_receive(channel) == 0) {
+ escc2_channel_irq_event(channel, REGISTER_ISR0, REGISTER_ISR0_RPF);
+ }
+}
+
static void escc2_realize(DeviceState *dev, Error **errp)
{
unsigned int i;
@@ -560,6 +779,13 @@ static void escc2_realize(DeviceState *dev, Error **errp)
for (i = 0; i < CHANNEL_COUNT; i++) {
channel = &controller->channel[i];
channel->controller = controller;
+
+ if (qemu_chr_fe_backend_connected(&channel->chardev)) {
+ qemu_chr_fe_set_handlers(&channel->chardev,
+ escc2_channel_chardev_can_receive,
+ escc2_channel_chardev_receive, NULL, NULL, channel, NULL,
+ true);
+ }
}
qemu_register_reset(escc2_reset, controller);
@@ -605,7 +831,13 @@ static void escc2_isa_realize(DeviceState *dev, Error **errp)
static void escc2_unrealize(DeviceState *dev)
{
+ unsigned int i;
ESCC2State *controller = ESCC2(dev);
+
+ for (i = 0; i < CHANNEL_COUNT; i++) {
+ qemu_chr_fe_deinit(&controller->channel[i].chardev, false);
+ }
+
qemu_unregister_reset(escc2_reset, controller);
}
@@ -618,6 +850,8 @@ static void escc2_isa_instance_init(Object *o)
}
static Property escc2_properties[] = {
+ DEFINE_PROP_CHR("chardevA", ESCC2State, channel[CHANNEL_A].chardev),
+ DEFINE_PROP_CHR("chardevB", ESCC2State, channel[CHANNEL_B].chardev),
DEFINE_PROP_END_OF_LIST()
};
--
2.26.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 4/8] hw/char/escc2: Add clock generation
2020-06-17 8:23 [PATCH 0/8] ESCC2 Jasper Lowell
` (2 preceding siblings ...)
2020-06-17 8:23 ` [PATCH 3/8] hw/char/escc2: Add character device backend Jasper Lowell
@ 2020-06-17 8:23 ` Jasper Lowell
2020-06-17 8:23 ` [PATCH 5/8] hw/char/escc2: Add Receiver Reset (RRES) command Jasper Lowell
` (6 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Jasper Lowell @ 2020-06-17 8:23 UTC (permalink / raw)
To: qemu-devel; +Cc: tony.nguyen, mark.cave-ayland, atar4qemu, Jasper Lowell
Each channel on the controller has dedicated pins for providing receive
and transmit clock sources, a baud rate generator, and a DPLL.
Additionally, the controller has two pins, XTAL1 and XTAL2, that can be
used with a crystal and oscillator for providing a clock source.
Alternatively, XTAL1 can simply be used as a clock source. These
components are used individually or together according to register
configurations for generating the final receive and transmit clocks.
Signed-off-by: Jasper Lowell <jasper.lowell@bt.com>
---
hw/char/escc2.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 177 insertions(+), 2 deletions(-)
diff --git a/hw/char/escc2.c b/hw/char/escc2.c
index e16049ce4d..059e033089 100644
--- a/hw/char/escc2.c
+++ b/hw/char/escc2.c
@@ -106,9 +106,31 @@
/* CCR1. */
#define REGISTER_CCR1_OFFSET 0x2d
+#define REGISTER_CCR1_ODS 0x10
+#define REGISTER_CCR1_BCR 0x8
+#define REGISTER_CCR1_CM2 0x4
+#define REGISTER_CCR1_CM1 0x2
+#define REGISTER_CCR1_CM0 0x1
+
+#define REGISTER_CCR1_CM_MASK \
+ (REGISTER_CCR1_CM2 | REGISTER_CCR1_CM1 | REGISTER_CCR1_CM0)
/* CCR2. */
#define REGISTER_CCR2_OFFSET 0x2e
+#define REGISTER_CCR2_SOC1 0x80
+#define REGISTER_CCR2_BR9 0x80
+#define REGISTER_CCR2_SOC0 0x40
+#define REGISTER_CCR2_BR8 0x40
+#define REGISTER_CCR2_BDF 0x20
+#define REGISTER_CCR2_XCS0 0x20
+#define REGISTER_CCR2_SSEL 0x10
+#define REGISTER_CCR2_RCS0 0x10
+#define REGISTER_CCR2_TOE 0x8
+#define REGISTER_CCR2_RWX 0x4
+#define REGISTER_CCR2_DIV 0x1
+
+#define REGISTER_CCR2_BR_MASK \
+ (REGISTER_CCR2_BR8 | REGISTER_CCR2_BR9)
/* CCR3. */
#define REGISTER_CCR3_OFFSET 0x2f
@@ -131,6 +153,9 @@
/* BGR. */
#define REGISTER_BGR_OFFSET 0x34
+#define REGISTER_BGR_EN_MASK 0x3f
+#define REGISTER_BGR_EM_MASK 0xc0
+
/* TIC. */
#define REGISTER_TIC_OFFSET 0x35
@@ -194,6 +219,10 @@
/* CCR4. */
#define REGISTER_CCR4_OFFSET 0x3f
+#define REGISTER_CCR4_MCK4 0x80
+#define REGISTER_CCR4_EBRG 0x40
+#define REGISTER_CCR4_TST1 0x20
+#define REGISTER_CCR4_ICD 0x10
enum {
REGISTER_STAR = 0,
@@ -244,6 +273,14 @@ typedef struct ESCC2State ESCC2State;
typedef struct ESCC2ChannelState {
ESCC2State *controller;
+ /*
+ * Each channel has dedicated pins for providing receive and transmit clock
+ * sources. These dedicated pins are a subset of a larger set of selectable
+ * clock sources.
+ */
+ unsigned int rxclock;
+ unsigned int txclock;
+
CharBackend chardev;
/*
@@ -275,6 +312,14 @@ enum {
struct ESCC2State {
DeviceState parent;
+ /*
+ * The controller has two pins: XTAL1 and XTAL2. These pins can be used
+ * together with a crystal and oscillator to provide a clock source.
+ * Alternatively, XTAL1 can provide an externally generated clock source.
+ * These configurations are mutually exclusive.
+ */
+ unsigned int xtal;
+
MemoryRegion io;
qemu_irq irq;
ESCC2ChannelState channel[CHANNEL_COUNT];
@@ -376,9 +421,130 @@ static void escc2_channel_irq_event(ESCC2ChannelState *channel,
}
}
+static float escc2_channel_baud_rate_generate(ESCC2ChannelState *channel,
+ unsigned int clock)
+{
+ /*
+ * Each channel has an independent baud rate generator. This baud rate
+ * generator can act as a clock source for receiving, transmitting, and/or
+ * for the DPLL.
+ */
+ int k, n, m;
+ uint8_t ccr2 = REGISTER_READ(channel, REGISTER_CCR2);
+ uint8_t bgr = REGISTER_READ(channel, REGISTER_BGR);
+
+ if (REGISTER_READ(channel, REGISTER_CCR2) & REGISTER_CCR2_BDF) {
+ /* The baud rate division factor k relies on BGR. */
+ if (REGISTER_READ(channel, REGISTER_CCR4) & REGISTER_CCR4_EBRG) {
+ /* Enhanced mode. */
+ n = bgr & REGISTER_BGR_EN_MASK;
+ m = ((ccr2 & REGISTER_CCR2_BR_MASK) >> 6)
+ | ((bgr & REGISTER_BGR_EM_MASK) >> 6);
+ k = (n + 1) * (2 * m);
+ } else {
+ /* Standard mode. */
+ n = ((ccr2 & REGISTER_CCR2_BR_MASK) << 2) | bgr;
+ k = (n + 1) * 2;
+ }
+ } else {
+ k = 1;
+ }
+
+ return (float) clock / (16 * k);
+}
+
+static void escc2_channel_io_speed(ESCC2ChannelState *channel, float *input,
+ float *output)
+{
+ /*
+ * The receive and transmit speed can be configured to leverage dedicated
+ * receive and transmit clock source pins, the channel independent baud rate
+ * generator, the DPLL for handling clock synchronisation, the onboard
+ * oscillator, and a designated master clock. Different combinations of
+ * these are selected by specifying the clock mode and submode.
+ *
+ * Note: The DPLL, to function correctly, requires a clock source with a
+ * frequency 16 times the nominal bit rate so that the DPLL can synchronise
+ * the clock with the input stream. When the DPLL is used, the frequency
+ * must be divided by 16.
+ */
+ unsigned int mode = REGISTER_READ(channel, REGISTER_CCR1)
+ & REGISTER_CCR1_CM_MASK;
+ unsigned int submode = REGISTER_READ(channel, REGISTER_CCR2)
+ & REGISTER_CCR2_SSEL;
+
+ /* Clock modes are numbered 0 through 7. */
+ switch (mode) {
+ case 0:
+ *input = channel->rxclock;
+ if (!submode) {
+ /* 0a. */
+ *output = channel->txclock;
+ } else {
+ /* 0b. */
+ *output = escc2_channel_baud_rate_generate(channel,
+ channel->controller->xtal);
+ }
+ break;
+ case 1:
+ *input = channel->rxclock;
+ *output = *input;
+ break;
+ case 2:
+ *input = escc2_channel_baud_rate_generate(channel, channel->rxclock)
+ / 16;
+ if (!(REGISTER_READ(channel, REGISTER_CCR2)
+ & REGISTER_CCR2_SSEL)) {
+ /* 2a. */
+ *output = channel->txclock;
+ } else {
+ /* 2b. */
+ *output = *input;
+ }
+ break;
+ case 3:
+ *input = escc2_channel_baud_rate_generate(channel, channel->rxclock);
+ if (!(REGISTER_READ(channel, REGISTER_CCR2) & REGISTER_CCR2_SSEL)) {
+ /* 3a. */
+ *input /= 16;
+ }
+ *output = *input;
+ break;
+ case 4:
+ *input = channel->controller->xtal;
+ *output = *input;
+ case 5:
+ *input = channel->rxclock;
+ *output = *input;
+ case 6:
+ *input = escc2_channel_baud_rate_generate(channel,
+ channel->controller->xtal) / 16;
+ if (!(REGISTER_READ(channel, REGISTER_CCR2) & REGISTER_CCR2_SSEL)) {
+ /* 6a. */
+ *output = channel->txclock;
+ } else {
+ /* 6b. */
+ *output = *input;
+ }
+ break;
+ case 7:
+ *input = escc2_channel_baud_rate_generate(channel,
+ channel->controller->xtal);
+ if (!(REGISTER_READ(channel, REGISTER_CCR2) & REGISTER_CCR2_SSEL)) {
+ /* 7a. */
+ *input /= 16;
+ }
+ *output = *input;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}
+
static void escc2_channel_parameters_update(ESCC2ChannelState *channel)
{
uint8_t dafo;
+ float ispeed, ospeed;
QEMUSerialSetParams ssp;
if (!qemu_chr_fe_backend_connected(&channel->chardev)) {
@@ -434,8 +600,12 @@ static void escc2_channel_parameters_update(ESCC2ChannelState *channel)
ssp.stop_bits = 1;
}
- /* XXX */
- ssp.speed = 0;
+ /*
+ * XXX: QEMU doesn't support configurations with different input/output
+ * speeds yet so the input speed is used for both.
+ */
+ escc2_channel_io_speed(channel, &ispeed, &ospeed);
+ ssp.speed = ispeed;
qemu_chr_fe_ioctl(&channel->chardev, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
}
@@ -852,6 +1022,11 @@ static void escc2_isa_instance_init(Object *o)
static Property escc2_properties[] = {
DEFINE_PROP_CHR("chardevA", ESCC2State, channel[CHANNEL_A].chardev),
DEFINE_PROP_CHR("chardevB", ESCC2State, channel[CHANNEL_B].chardev),
+ DEFINE_PROP_UINT32("xtal", ESCC2State, xtal, 0),
+ DEFINE_PROP_UINT32("rxclockA", ESCC2State, channel[CHANNEL_A].rxclock, 0),
+ DEFINE_PROP_UINT32("txclockA", ESCC2State, channel[CHANNEL_A].txclock, 0),
+ DEFINE_PROP_UINT32("rxclockB", ESCC2State, channel[CHANNEL_B].rxclock, 0),
+ DEFINE_PROP_UINT32("txclockB", ESCC2State, channel[CHANNEL_B].txclock, 0),
DEFINE_PROP_END_OF_LIST()
};
--
2.26.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 5/8] hw/char/escc2: Add Receiver Reset (RRES) command
2020-06-17 8:23 [PATCH 0/8] ESCC2 Jasper Lowell
` (3 preceding siblings ...)
2020-06-17 8:23 ` [PATCH 4/8] hw/char/escc2: Add clock generation Jasper Lowell
@ 2020-06-17 8:23 ` Jasper Lowell
2020-06-17 8:24 ` [PATCH 6/8] hw/char/escc2: Add RFRD command Jasper Lowell
` (5 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Jasper Lowell @ 2020-06-17 8:23 UTC (permalink / raw)
To: qemu-devel; +Cc: tony.nguyen, mark.cave-ayland, atar4qemu, Jasper Lowell
Commands are initiated by setting certain bits in the CMDR register. The
Receiver Reset (RRES) command clears the receiver FIFO (RFIFO).
Signed-off-by: Jasper Lowell <jasper.lowell@bt.com>
---
hw/char/escc2.c | 24 ++++++++++++++++++++++++
hw/char/trace-events | 1 +
2 files changed, 25 insertions(+)
diff --git a/hw/char/escc2.c b/hw/char/escc2.c
index 059e033089..5afb8aa6d9 100644
--- a/hw/char/escc2.c
+++ b/hw/char/escc2.c
@@ -29,6 +29,12 @@
/* CMDR. */
#define REGISTER_CMDR_OFFSET 0x20
+#define REGISTER_CMDR_RMC 0x80
+#define REGISTER_CMDR_RRES 0x40
+#define REGISTER_CMDR_RFRD 0x20
+#define REGISTER_CMDR_STI 0x10
+#define REGISTER_CMDR_XF 0x8
+#define REGISTER_CMDR_XRES 0x1
/* MODE. */
#define REGISTER_MODE_OFFSET 0x22
@@ -741,6 +747,23 @@ static uint64_t escc2_mem_read(void *opaque, hwaddr addr, unsigned size)
return value;
}
+static void escc2_channel_command(ESCC2ChannelState *channel)
+{
+ uint8_t tmp, command;
+
+ command = REGISTER_READ(channel, REGISTER_CMDR);
+ trace_escc2_channel_command(CHANNEL_CHAR(channel), command);
+
+ if (command & REGISTER_CMDR_RRES) {
+ memset(channel->fifo_receive, 0, sizeof(channel->fifo_receive));
+ REGISTER_WRITE(channel, REGISTER_RBCL, 0);
+
+ tmp = REGISTER_READ(channel, REGISTER_STAR);
+ tmp &= ~(REGISTER_STAR_RFNE);
+ REGISTER_WRITE(channel, REGISTER_STAR, tmp);
+ }
+}
+
static void escc2_mem_write(void *opaque, hwaddr addr, uint64_t value,
unsigned size)
{
@@ -767,6 +790,7 @@ static void escc2_mem_write(void *opaque, hwaddr addr, uint64_t value,
break;
case REGISTER_CMDR_OFFSET:
REGISTER_WRITE(channel, REGISTER_CMDR, value);
+ escc2_channel_command(channel);
break;
case REGISTER_MODE_OFFSET:
REGISTER_WRITE(channel, REGISTER_MODE, value);
diff --git a/hw/char/trace-events b/hw/char/trace-events
index b4f4f30815..47b46b92c9 100644
--- a/hw/char/trace-events
+++ b/hw/char/trace-events
@@ -59,6 +59,7 @@ escc_sunmouse_event(int dx, int dy, int buttons_state) "dx=%d dy=%d buttons=0x%0
# escc2.c
escc2_irq_update(uint8_t gis) "value 0x%x"
escc2_mem_read(char channel, uint32_t addr, uint8_t value) "channel %c addr 0x%x value 0x%x"
+escc2_channel_command(char channel, uint8_t command) "channel %c command 0x%x"
escc2_mem_write(char channel, uint32_t addr, uint8_t value) "channel %c addr 0x%x value 0x%x"
# pl011.c
--
2.26.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 6/8] hw/char/escc2: Add RFRD command
2020-06-17 8:23 [PATCH 0/8] ESCC2 Jasper Lowell
` (4 preceding siblings ...)
2020-06-17 8:23 ` [PATCH 5/8] hw/char/escc2: Add Receiver Reset (RRES) command Jasper Lowell
@ 2020-06-17 8:24 ` Jasper Lowell
2020-06-17 8:24 ` [PATCH 7/8] hw/char/escc2: Add Transmit Frame (XF) command Jasper Lowell
` (4 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Jasper Lowell @ 2020-06-17 8:24 UTC (permalink / raw)
To: qemu-devel; +Cc: tony.nguyen, mark.cave-ayland, atar4qemu, Jasper Lowell
The Receive FIFO Read Enable command is used to request access to the
receive FIFO. When the command is finished, the controller will issue a
TCD interrupt and the number of available bytes will be available in tthe
RBCL register. Given that the visible receive FIFO window is used to
store characters as they come in, the only action that needs to be taken
is to raise the TCD interrupt (if this interrupt is enabled).
Signed-off-by: Jasper Lowell <jasper.lowell@bt.com>
---
hw/char/escc2.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hw/char/escc2.c b/hw/char/escc2.c
index 5afb8aa6d9..8198b7fec3 100644
--- a/hw/char/escc2.c
+++ b/hw/char/escc2.c
@@ -762,6 +762,10 @@ static void escc2_channel_command(ESCC2ChannelState *channel)
tmp &= ~(REGISTER_STAR_RFNE);
REGISTER_WRITE(channel, REGISTER_STAR, tmp);
}
+
+ if (command & REGISTER_CMDR_RFRD) {
+ escc2_channel_irq_event(channel, REGISTER_ISR0, REGISTER_ISR0_TCD);
+ }
}
static void escc2_mem_write(void *opaque, hwaddr addr, uint64_t value,
--
2.26.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 7/8] hw/char/escc2: Add Transmit Frame (XF) command
2020-06-17 8:23 [PATCH 0/8] ESCC2 Jasper Lowell
` (5 preceding siblings ...)
2020-06-17 8:24 ` [PATCH 6/8] hw/char/escc2: Add RFRD command Jasper Lowell
@ 2020-06-17 8:24 ` Jasper Lowell
2020-06-17 8:24 ` [PATCH 8/8] hw/char/escc2: Add XRES command Jasper Lowell
` (3 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Jasper Lowell @ 2020-06-17 8:24 UTC (permalink / raw)
To: qemu-devel; +Cc: tony.nguyen, mark.cave-ayland, atar4qemu, Jasper Lowell
The Transmit Frame (XF) command is an alternative to using the TIC
register for transmitting. This command allows the guest to transmit the
contents of the transmit FIFO rather than a single character.
Signed-off-by: Jasper Lowell <jasper.lowell@bt.com>
---
hw/char/escc2.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/hw/char/escc2.c b/hw/char/escc2.c
index 8198b7fec3..3bacdfaa7c 100644
--- a/hw/char/escc2.c
+++ b/hw/char/escc2.c
@@ -207,6 +207,14 @@
/* ISR1. */
#define REGISTER_ISR1_OFFSET 0x3b
+#define REGISTER_ISR1_BRK 0x80
+#define REGISTER_ISR1_BRKT 0x40
+#define REGISTER_ISR1_ALLS 0x20
+#define REGISTER_ISR1_XOFF 0x10
+#define REGISTER_ISR1_TIN 0x8
+#define REGISTER_ISR1_CSC 0x4
+#define REGISTER_ISR1_XON 0x2
+#define REGISTER_ISR1_XPR 0x1
/* IMR1. */
#define REGISTER_IMR1_OFFSET 0x3b
@@ -749,6 +757,7 @@ static uint64_t escc2_mem_read(void *opaque, hwaddr addr, unsigned size)
static void escc2_channel_command(ESCC2ChannelState *channel)
{
+ unsigned int i;
uint8_t tmp, command;
command = REGISTER_READ(channel, REGISTER_CMDR);
@@ -766,6 +775,21 @@ static void escc2_channel_command(ESCC2ChannelState *channel)
if (command & REGISTER_CMDR_RFRD) {
escc2_channel_irq_event(channel, REGISTER_ISR0, REGISTER_ISR0_TCD);
}
+
+ if (command & REGISTER_CMDR_XF) {
+ i = 0;
+ while (i < CHANNEL_FIFO_LENGTH && channel->fifo_transmit[i] != 0) {
+ i++;
+ }
+ qemu_chr_fe_write_all(&channel->chardev, channel->fifo_transmit, i);
+ escc2_channel_irq_event(channel, REGISTER_ISR1, REGISTER_ISR1_ALLS);
+
+ /*
+ * XFIFO is ready and ISR1_XPR should be generated. Fake the XRES
+ * command.
+ */
+ command &= REGISTER_CMDR_XRES;
+ }
}
static void escc2_mem_write(void *opaque, hwaddr addr, uint64_t value,
--
2.26.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 8/8] hw/char/escc2: Add XRES command
2020-06-17 8:23 [PATCH 0/8] ESCC2 Jasper Lowell
` (6 preceding siblings ...)
2020-06-17 8:24 ` [PATCH 7/8] hw/char/escc2: Add Transmit Frame (XF) command Jasper Lowell
@ 2020-06-17 8:24 ` Jasper Lowell
2020-06-17 8:54 ` [PATCH 0/8] ESCC2 no-reply
` (2 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Jasper Lowell @ 2020-06-17 8:24 UTC (permalink / raw)
To: qemu-devel; +Cc: tony.nguyen, mark.cave-ayland, atar4qemu, Jasper Lowell
The Transmitter Reset (XRES) command is used for clearing the the
transmit FIFO of any data. When the controller has completed the
command, an XPR interrupt is generated (if this interrupt is enabled).
Signed-off-by: Jasper Lowell <jasper.lowell@bt.com>
---
hw/char/escc2.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/hw/char/escc2.c b/hw/char/escc2.c
index 3bacdfaa7c..a40731b836 100644
--- a/hw/char/escc2.c
+++ b/hw/char/escc2.c
@@ -790,6 +790,11 @@ static void escc2_channel_command(ESCC2ChannelState *channel)
*/
command &= REGISTER_CMDR_XRES;
}
+
+ if (command & REGISTER_CMDR_XRES) {
+ memset(channel->fifo_transmit, 0, sizeof(channel->fifo_transmit));
+ escc2_channel_irq_event(channel, REGISTER_ISR1, REGISTER_ISR1_XPR);
+ }
}
static void escc2_mem_write(void *opaque, hwaddr addr, uint64_t value,
--
2.26.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 0/8] ESCC2
2020-06-17 8:23 [PATCH 0/8] ESCC2 Jasper Lowell
` (7 preceding siblings ...)
2020-06-17 8:24 ` [PATCH 8/8] hw/char/escc2: Add XRES command Jasper Lowell
@ 2020-06-17 8:54 ` no-reply
2020-06-17 13:33 ` Philippe Mathieu-Daudé
2020-06-17 17:29 ` Artyom Tarasenko
10 siblings, 0 replies; 12+ messages in thread
From: no-reply @ 2020-06-17 8:54 UTC (permalink / raw)
To: jasper.lowell
Cc: tony.nguyen, mark.cave-ayland, qemu-devel, atar4qemu, jasper.lowell
Patchew URL: https://patchew.org/QEMU/20200617082402.242631-1-jasper.lowell@bt.com/
Hi,
This series failed the asan build test. Please find the testing commands and
their output below. If you have Docker installed, you can probably reproduce it
locally.
=== TEST SCRIPT BEGIN ===
#!/bin/bash
export ARCH=x86_64
make docker-image-fedora V=1 NETWORK=1
time make docker-test-debug@fedora TARGET_LIST=x86_64-softmmu J=14 NETWORK=1
=== TEST SCRIPT END ===
GEN docs/interop/qemu-qmp-ref.html
GEN docs/interop/qemu-qmp-ref.txt
GEN docs/interop/qemu-qmp-ref.7
/usr/bin/ld: /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors_vfork.S.o): warning: common of `__interception::real_vfork' overridden by definition from /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors.cpp.o)
CC qga/commands.o
CC qga/guest-agent-command-state.o
CC qga/main.o
---
AR libvhost-user.a
GEN docs/interop/qemu-ga-ref.html
GEN docs/interop/qemu-ga-ref.txt
/usr/bin/ld: /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors_vfork.S.o): warning: common of `__interception::real_vfork' overridden by definition from /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors.cpp.o)
GEN docs/interop/qemu-ga-ref.7
LINK qemu-ga
LINK qemu-keymap
/usr/bin/ld: /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors_vfork.S.o): warning: common of `__interception::real_vfork' overridden by definition from /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors.cpp.o)
LINK ivshmem-client
/usr/bin/ld: /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors_vfork.S.o): warning: common of `__interception::real_vfork' overridden by definition from /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors.cpp.o)
LINK ivshmem-server
/usr/bin/ld: /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors_vfork.S.o): warning: common of `__interception::real_vfork' overridden by definition from /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors.cpp.o)
LINK qemu-nbd
AS pc-bios/optionrom/multiboot.o
/usr/bin/ld: /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors_vfork.S.o): warning: common of `__interception::real_vfork' overridden by definition from /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors.cpp.o)
AS pc-bios/optionrom/linuxboot.o
CC pc-bios/optionrom/linuxboot_dma.o
/usr/bin/ld: /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors_vfork.S.o): warning: common of `__interception::real_vfork' overridden by definition from /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors.cpp.o)
AS pc-bios/optionrom/kvmvapic.o
AS pc-bios/optionrom/pvh.o
LINK qemu-storage-daemon
CC pc-bios/optionrom/pvh_main.o
LINK qemu-img
/usr/bin/ld: /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors_vfork.S.o): warning: common of `__interception::real_vfork' overridden by definition from /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors.cpp.o)
BUILD pc-bios/optionrom/multiboot.img
/usr/bin/ld: /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors_vfork.S.o): warning: common of `__interception::real_vfork' overridden by definition from /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors.cpp.o)
BUILD pc-bios/optionrom/linuxboot.img
BUILD pc-bios/optionrom/linuxboot_dma.img
LINK qemu-io
BUILD pc-bios/optionrom/kvmvapic.img
BUILD pc-bios/optionrom/multiboot.raw
BUILD pc-bios/optionrom/linuxboot.raw
/usr/bin/ld: /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors_vfork.S.o): warning: common of ` BUILD pc-bios/optionrom/linuxboot_dma.raw
__interception::real_vfork' overridden by definition from /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors.cpp.o)
LINK qemu-edid
BUILD pc-bios/optionrom/kvmvapic.raw
SIGN pc-bios/optionrom/multiboot.bin
SIGN pc-bios/optionrom/linuxboot.bin
/usr/bin/ld: /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors_vfork.S.o): warning: common of `__interception::real_vfork' overridden by definition from /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors.cpp.o)
SIGN pc-bios/optionrom/linuxboot_dma.bin
LINK fsdev/virtfs-proxy-helper
SIGN pc-bios/optionrom/kvmvapic.bin
LINK scsi/qemu-pr-helper
LINK qemu-bridge-helper
LINK virtiofsd
/usr/bin/ld: /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors_vfork.S.o): warning: common of `__interception::real_vfork' overridden by definition from /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors.cpp.o)
/usr/bin/ld: /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors_vfork.S.o): warning: common of `__interception::real_vfork' overridden by definition from /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors.cpp.o)
/usr/bin/ld: /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors_vfork.S.o): warning: common of `__interception::real_vfork' overridden by definition from /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors.cpp.o)
LINK vhost-user-input
BUILD pc-bios/optionrom/pvh.img
BUILD pc-bios/optionrom/pvh.raw
SIGN pc-bios/optionrom/pvh.bin
/usr/bin/ld: /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors_vfork.S.o): warning: common of `__interception::real_vfork' overridden by definition from /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors.cpp.o)
/usr/bin/ld: /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors_vfork.S.o): warning: common of `__interception::real_vfork' overridden by definition from /usr/lib64/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.a(asan_interceptors.cpp.o)
GEN x86_64-softmmu/hmp-commands.h
GEN x86_64-softmmu/hmp-commands-info.h
GEN x86_64-softmmu/config-devices.h
---
CC x86_64-softmmu/hw/scsi/virtio-scsi.o
CC x86_64-softmmu/hw/scsi/virtio-scsi-dataplane.o
CC x86_64-softmmu/hw/scsi/vhost-scsi-common.o
/tmp/qemu-test/src/migration/ram.c:919:45: error: implicit conversion from 'unsigned long' to 'double' changes value from 18446744073709551615 to 18446744073709551616 [-Werror,-Wimplicit-int-float-conversion]
xbzrle_counters.encoding_rate = UINT64_MAX;
~ ^~~~~~~~~~
/usr/include/stdint.h:130:23: note: expanded from macro 'UINT64_MAX'
---
18446744073709551615UL
^~~~~~~~~~~~~~~~~~~~~~
1 error generated.
make[1]: *** [/tmp/qemu-test/src/rules.mak:69: migration/ram.o] Error 1
make[1]: *** Waiting for unfinished jobs....
/tmp/qemu-test/src/fpu/softfloat.c:3365:13: error: bitwise negation of a boolean expression; did you mean logical negation? [-Werror,-Wbool-operation]
absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!
/tmp/qemu-test/src/fpu/softfloat.c:3423:18: error: bitwise negation of a boolean expression; did you mean logical negation? [-Werror,-Wbool-operation]
absZ0 &= ~ ( ( (uint64_t) ( absZ1<<1 ) == 0 ) & roundNearestEven );
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!
/tmp/qemu-test/src/fpu/softfloat.c:3483:18: error: bitwise negation of a boolean expression; did you mean logical negation? [-Werror,-Wbool-operation]
absZ0 &= ~(((uint64_t)(absZ1<<1) == 0) & roundNearestEven);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!
/tmp/qemu-test/src/fpu/softfloat.c:3606:13: error: bitwise negation of a boolean expression; did you mean logical negation? [-Werror,-Wbool-operation]
zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!
/tmp/qemu-test/src/fpu/softfloat.c:3760:13: error: bitwise negation of a boolean expression; did you mean logical negation? [-Werror,-Wbool-operation]
zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven );
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!
/tmp/qemu-test/src/fpu/softfloat.c:3987:21: error: bitwise negation of a boolean expression; did you mean logical negation? [-Werror,-Wbool-operation]
~ ( ( (uint64_t) ( zSig1<<1 ) == 0 ) & roundNearestEven );
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!
/tmp/qemu-test/src/fpu/softfloat.c:4003:22: error: bitwise negation of a boolean expression; did you mean logical negation? [-Werror,-Wbool-operation]
zSig0 &= ~ ( ( (uint64_t) ( zSig1<<1 ) == 0 ) & roundNearestEven );
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!
/tmp/qemu-test/src/fpu/softfloat.c:4273:18: error: bitwise negation of a boolean expression; did you mean logical negation? [-Werror,-Wbool-operation]
zSig1 &= ~ ( ( zSig2 + zSig2 == 0 ) & roundNearestEven );
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!
8 errors generated.
make[1]: *** [/tmp/qemu-test/src/rules.mak:69: fpu/softfloat.o] Error 1
make: *** [Makefile:527: x86_64-softmmu/all] Error 2
Traceback (most recent call last):
File "./tests/docker/docker.py", line 669, in <module>
sys.exit(main())
---
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['sudo', '-n', 'docker', 'run', '--label', 'com.qemu.instance.uuid=8d05dab6690f47fa9c4a223cb750d7b8', '-u', '1001', '--security-opt', 'seccomp=unconfined', '--rm', '-e', 'TARGET_LIST=x86_64-softmmu', '-e', 'EXTRA_CONFIGURE_OPTS=', '-e', 'V=', '-e', 'J=14', '-e', 'DEBUG=', '-e', 'SHOW_ENV=', '-e', 'CCACHE_DIR=/var/tmp/ccache', '-v', '/home/patchew/.cache/qemu-docker-ccache:/var/tmp/ccache:z', '-v', '/var/tmp/patchew-tester-tmp-ijl9vbi1/src/docker-src.2020-06-17-04.49.55.30222:/var/tmp/qemu:z,ro', 'qemu:fedora', '/var/tmp/qemu/run', 'test-debug']' returned non-zero exit status 2.
filter=--filter=label=com.qemu.instance.uuid=8d05dab6690f47fa9c4a223cb750d7b8
make[1]: *** [docker-run] Error 1
make[1]: Leaving directory `/var/tmp/patchew-tester-tmp-ijl9vbi1/src'
make: *** [docker-run-test-debug@fedora] Error 2
real 4m7.449s
user 0m8.702s
The full log is available at
http://patchew.org/logs/20200617082402.242631-1-jasper.lowell@bt.com/testing.asan/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 0/8] ESCC2
2020-06-17 8:23 [PATCH 0/8] ESCC2 Jasper Lowell
` (8 preceding siblings ...)
2020-06-17 8:54 ` [PATCH 0/8] ESCC2 no-reply
@ 2020-06-17 13:33 ` Philippe Mathieu-Daudé
2020-06-17 17:29 ` Artyom Tarasenko
10 siblings, 0 replies; 12+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-06-17 13:33 UTC (permalink / raw)
To: Jasper Lowell, qemu-devel
Cc: tony.nguyen, mark.cave-ayland, Laurent Vivier,
Marc-André Lureau, Paolo Bonzini, atar4qemu
Cc'ing chardev maintainers and Laurent.
On 6/17/20 10:23 AM, Jasper Lowell wrote:
> I've been working on improving Solaris 10 emulation for the SPARC64
> Sun4u architecture with the goal of a working shell. Currently, Solaris
> 10 boots with a number of errors before displaying the prompt of an
> otherwise unresponsive installer shell. It's been mentioned that this
> problem may not be isolated to Solaris 10 but may affect derivatives of
> OpenSolaris including illumos.
>
> From what I can tell, Solaris 10 never attempts to use the 16550A UART
> for the serial console. The kernel will probe registers to identify the
> device but will not use it for receiving or transmitting. The kernel
> only prints to the console using the prom interface that OpenBIOS
> provides. It's difficult to ascertain what the problem is because there
> is no visibility into the kernel. The 16550A UART on the Ultra 5
> (Darwin), the machine that QEMU Sun4u is modelled against, is used for
> the keyboard/mouse (SuperIO) and is not traditionally used for the
> serial tty. Instead, the SAB 82532 ESCC2 is used to provide ttya and
> ttyb on this system. This patch exists to increment QEMU Sun4u towards
> being hardware faithful.
>
> The SAB 82532 ESCC2 is complex because of the jungle of features that it
> provides. Linux and OpenBSD only use a small subset of features
> restricted to the ASYNC serial mode. The ASYNC serial mode is
> relatively simple to implement in isolation. I have made progress on a
> patch series that supports all serial modes, along with transitioning
> between them, but I have decided against submitting it. The serial
> controller appears to multiplex bit positions in registers across serial
> modes while preserving the bits themselves. This means that some 8-bit
> registers need to keep track of more than 8-bits of data and that the
> interpretation of the value the register holds depends on the selected
> serial mode. It's not ideal having a copy of each register for each
> serial mode because some bits are shared across some of the register
> modes. An added difficulty is that the manual doesn't document this
> behaviour well and its unclear what exactly happens when there is a
> transition in the selected serial mode. I've avoided depending on
> registers being uint8_t and have made use of macros so that the backend
> implementation of each register can be changed at a later date when
> supporting other serial modes. If I have the opportunity to test real
> hardware, or it becomes clear that HDLC/SDLC/BISYNC support is needed,
> I'll look at upstreaming the other changes that I have.
>
> I have written a bare-bones patch for OpenBIOS that adds this device to
> the device tree. With that applied, Solaris identifies and attaches the
> device successfully but does not interact with it further - similar to
> the 16550A UART. I did notice, however, that Solaris 10 entered an
> interrupt routine for this device when the network card was being
> configured. I couldn't manage to provoke this behaviour for the 16550A
> so this might be some small success. I strongly suspect that the
> interrupt is a spurious interrupt caused by misconfiguration of the
> devices in the firmware but I have not investigated this further.
>
> Solaris 10, judging from the OpenSolaris source code, determines
> stdin/stdout for the console by examining the stdin/stdout properties
> under /chosen in the device tree. Naturally, this is done with the prom
> interface. From what I can tell, to set these properties to the ESCC2
> node it's necessary to change stdin/stdout for OpenBIOS completely. This
> requires a device driver. I have made some progress on an OpenBIOS
> device driver for the ESCC2 but it's taking longer than expected to
> completely replace the 16550A and it's unlikely that I will have this
> finished soon. It's possible that Solaris 10 emulation for this platform
> will improve once that work is finished but it's unclear.
>
> This is my first patch series for QEMU so it's possible that I've made
> mistakes in the contribution process - sorry in advance.
>
> Jasper Lowell (8):
> hw/char/escc2: Add device
> hw/char/escc2: Handle interrupt generation
> hw/char/escc2: Add character device backend
> hw/char/escc2: Add clock generation
> hw/char/escc2: Add Receiver Reset (RRES) command
> hw/char/escc2: Add RFRD command
> hw/char/escc2: Add Transmit Frame (XF) command
> hw/char/escc2: Add XRES command
>
> hw/char/Kconfig | 8 +
> hw/char/Makefile.objs | 1 +
> hw/char/escc2.c | 1135 +++++++++++++++++++++++++++++++++++++++
> hw/char/trace-events | 6 +
> include/hw/char/escc2.h | 17 +
> 5 files changed, 1167 insertions(+)
> create mode 100644 hw/char/escc2.c
> create mode 100644 include/hw/char/escc2.h
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 0/8] ESCC2
2020-06-17 8:23 [PATCH 0/8] ESCC2 Jasper Lowell
` (9 preceding siblings ...)
2020-06-17 13:33 ` Philippe Mathieu-Daudé
@ 2020-06-17 17:29 ` Artyom Tarasenko
10 siblings, 0 replies; 12+ messages in thread
From: Artyom Tarasenko @ 2020-06-17 17:29 UTC (permalink / raw)
To: Jasper Lowell
Cc: tony.nguyen, Mark Cave-Ayland, Laurent Vivier, qemu-devel,
Marc-André Lureau, Paolo Bonzini,
Philippe Mathieu-Daudé
On Wed, Jun 17, 2020 at 10:24 AM Jasper Lowell <jasper.lowell@bt.com> wrote:
>
> I've been working on improving Solaris 10 emulation for the SPARC64
> Sun4u architecture with the goal of a working shell. Currently, Solaris
> 10 boots with a number of errors before displaying the prompt of an
> otherwise unresponsive installer shell. It's been mentioned that this
> problem may not be isolated to Solaris 10 but may affect derivatives of
> OpenSolaris including illumos.
>
> From what I can tell, Solaris 10 never attempts to use the 16550A UART
> for the serial console. The kernel will probe registers to identify the
> device but will not use it for receiving or transmitting. The kernel
> only prints to the console using the prom interface that OpenBIOS
> provides. It's difficult to ascertain what the problem is because there
> is no visibility into the kernel. The 16550A UART on the Ultra 5
> (Darwin), the machine that QEMU Sun4u is modelled against, is used for
> the keyboard/mouse (SuperIO) and is not traditionally used for the
> serial tty. Instead, the SAB 82532 ESCC2 is used to provide ttya and
> ttyb on this system. This patch exists to increment QEMU Sun4u towards
> being hardware faithful.
Nice, thanks for sharing!
> The SAB 82532 ESCC2 is complex because of the jungle of features that it
> provides. Linux and OpenBSD only use a small subset of features
> restricted to the ASYNC serial mode. The ASYNC serial mode is
> relatively simple to implement in isolation. I have made progress on a
> patch series that supports all serial modes, along with transitioning
> between them, but I have decided against submitting it. The serial
> controller appears to multiplex bit positions in registers across serial
> modes while preserving the bits themselves. This means that some 8-bit
> registers need to keep track of more than 8-bits of data and that the
> interpretation of the value the register holds depends on the selected
> serial mode. It's not ideal having a copy of each register for each
> serial mode because some bits are shared across some of the register
> modes. An added difficulty is that the manual doesn't document this
> behaviour well and its unclear what exactly happens when there is a
> transition in the selected serial mode. I've avoided depending on
> registers being uint8_t and have made use of macros so that the backend
> implementation of each register can be changed at a later date when
> supporting other serial modes. If I have the opportunity to test real
> hardware, or it becomes clear that HDLC/SDLC/BISYNC support is needed,
> I'll look at upstreaming the other changes that I have.
>
> I have written a bare-bones patch for OpenBIOS that adds this device to
> the device tree. With that applied, Solaris identifies and attaches the
> device successfully but does not interact with it further - similar to
> the 16550A UART. I did notice, however, that Solaris 10 entered an
> interrupt routine for this device when the network card was being
> configured. I couldn't manage to provoke this behaviour for the 16550A
> so this might be some small success. I strongly suspect that the
> interrupt is a spurious interrupt caused by misconfiguration of the
> devices in the firmware but I have not investigated this further.
>
> Solaris 10, judging from the OpenSolaris source code, determines
> stdin/stdout for the console by examining the stdin/stdout properties
> under /chosen in the device tree. Naturally, this is done with the prom
> interface. From what I can tell, to set these properties to the ESCC2
> node it's necessary to change stdin/stdout for OpenBIOS completely. This
> requires a device driver. I have made some progress on an OpenBIOS
> device driver for the ESCC2 but it's taking longer than expected to
> completely replace the 16550A and it's unlikely that I will have this
> finished soon. It's possible that Solaris 10 emulation for this platform
> will improve once that work is finished but it's unclear.
Actually we may consider adding another sparc64 machine: "ultra5", and
maybe deprecate "sun4u" machine once OpenBIOS supports escc2. (But
maybe keep it as it's as long as it's used by NetBSD regression tests)
> This is my first patch series for QEMU so it's possible that I've made
> mistakes in the contribution process - sorry in advance.
Congratulations on the first patch! It's a very good start.
> Jasper Lowell (8):
> hw/char/escc2: Add device
> hw/char/escc2: Handle interrupt generation
> hw/char/escc2: Add character device backend
> hw/char/escc2: Add clock generation
> hw/char/escc2: Add Receiver Reset (RRES) command
> hw/char/escc2: Add RFRD command
> hw/char/escc2: Add Transmit Frame (XF) command
> hw/char/escc2: Add XRES command
>
> hw/char/Kconfig | 8 +
> hw/char/Makefile.objs | 1 +
> hw/char/escc2.c | 1135 +++++++++++++++++++++++++++++++++++++++
> hw/char/trace-events | 6 +
> include/hw/char/escc2.h | 17 +
> 5 files changed, 1167 insertions(+)
> create mode 100644 hw/char/escc2.c
> create mode 100644 include/hw/char/escc2.h
>
> --
> 2.26.2
>
--
Regards,
Artyom Tarasenko
SPARC and PPC PReP under qemu blog: http://tyom.blogspot.com/search/label/qemu
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2020-06-17 17:30 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-17 8:23 [PATCH 0/8] ESCC2 Jasper Lowell
2020-06-17 8:23 ` [PATCH 1/8] hw/char/escc2: Add device Jasper Lowell
2020-06-17 8:23 ` [PATCH 2/8] hw/char/escc2: Handle interrupt generation Jasper Lowell
2020-06-17 8:23 ` [PATCH 3/8] hw/char/escc2: Add character device backend Jasper Lowell
2020-06-17 8:23 ` [PATCH 4/8] hw/char/escc2: Add clock generation Jasper Lowell
2020-06-17 8:23 ` [PATCH 5/8] hw/char/escc2: Add Receiver Reset (RRES) command Jasper Lowell
2020-06-17 8:24 ` [PATCH 6/8] hw/char/escc2: Add RFRD command Jasper Lowell
2020-06-17 8:24 ` [PATCH 7/8] hw/char/escc2: Add Transmit Frame (XF) command Jasper Lowell
2020-06-17 8:24 ` [PATCH 8/8] hw/char/escc2: Add XRES command Jasper Lowell
2020-06-17 8:54 ` [PATCH 0/8] ESCC2 no-reply
2020-06-17 13:33 ` Philippe Mathieu-Daudé
2020-06-17 17:29 ` Artyom Tarasenko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).