[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH for-6.2 2/2] escc: update the R_SPEC register SPEC_ALLSENT bit wh
From: |
Mark Cave-Ayland |
Subject: |
[PATCH for-6.2 2/2] escc: update the R_SPEC register SPEC_ALLSENT bit when writing to W_TXCTRL1 |
Date: |
Thu, 18 Nov 2021 18:18:35 +0000 |
The ESCC datasheet states that SPEC_ALLSENT is always set in sync mode and set
in async mode once all characters have cleared the transmitter. Since writes to
SERIAL_DATA use a synchronous chardev API, the guest can never see the state
when
transmission is in progress so it is possible to set SPEC_ALLSENT in the
R_SPEC register unconditionally.
This fixes a hang when using the Sun PROM as it attempts to enumerate the
onboard serial devices, and a similar hang in OpenBSD SPARC32 where in both
cases
the boot process will not proceed until SPEC_ALLSENT has been set after writing
to W_TXCTRL1.
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
---
hw/char/escc.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/hw/char/escc.c b/hw/char/escc.c
index a7d9050c83..8755d8d34f 100644
--- a/hw/char/escc.c
+++ b/hw/char/escc.c
@@ -586,6 +586,20 @@ static void escc_mem_write(void *opaque, hwaddr addr,
s->wregs[s->reg] = val;
break;
case W_TXCTRL1:
+ s->wregs[s->reg] = val;
+ /*
+ * The ESCC datasheet states that SPEC_ALLSENT is always set in
+ * sync mode, and set in async mode when all characters have
+ * cleared the transmitter. Since writes to SERIAL_DATA use the
+ * blocking qemu_chr_fe_write_all() function to write each
+ * character, the guest can never see the state when async data
+ * is in the process of being transmitted so we can set this bit
+ * unconditionally regardless of the state of the W_TXCTRL1 mode
+ * bits.
+ */
+ s->rregs[R_SPEC] |= SPEC_ALLSENT;
+ escc_update_parameters(s);
+ break;
case W_TXCTRL2:
s->wregs[s->reg] = val;
escc_update_parameters(s);
--
2.20.1