aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2021-11-21 14:12:25 +0100
committerRichard Henderson <richard.henderson@linaro.org>2021-11-21 14:12:25 +0100
commitc5fbdd60cf1fb52f01bdfe342b6fa65d5343e1b1 (patch)
treee86a96d22f3b5244d2d82a2c95fb90c94da891f0
parent8627edfb3f1fca24a96a0954148885c3241c10f8 (diff)
parent319e89cdc32096432b578152a47d0d156033b711 (diff)
Merge tag 'qemu-sparc-20211121' of git://github.com/mcayland/qemu into staging
qemu-sparc queue # gpg: Signature made Sun 21 Nov 2021 10:57:01 AM CET # gpg: using RSA key CC621AB98E82200D915CC9C45BC2C56FAE0F321F # gpg: issuer "mark.cave-ayland@ilande.co.uk" # gpg: Good signature from "Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>" [full] * tag 'qemu-sparc-20211121' of git://github.com/mcayland/qemu: escc: update the R_SPEC register SPEC_ALLSENT bit when writing to W_TXCTRL1 escc: always set STATUS_TXEMPTY in R_STATUS on device reset Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r--hw/char/escc.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/hw/char/escc.c b/hw/char/escc.c
index 0fce4f6324..8755d8d34f 100644
--- a/hw/char/escc.c
+++ b/hw/char/escc.c
@@ -354,6 +354,17 @@ static void escc_reset(DeviceState *d)
cs->rregs[j] = 0;
cs->wregs[j] = 0;
}
+
+ /*
+ * ...but there is an exception. The "Transmit Interrupts and Transmit
+ * Buffer Empty Bit" section on page 50 of the ESCC datasheet says of
+ * the STATUS_TXEMPTY bit in R_STATUS: "After a hardware reset
+ * (including a hardware reset by software), or a channel reset, this
+ * bit is set to 1". The Sun PROM checks this bit early on startup and
+ * gets stuck in an infinite loop if it is not set.
+ */
+ cs->rregs[R_STATUS] |= STATUS_TXEMPTY;
+
escc_reset_chn(cs);
}
}
@@ -575,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);