Pārlūkot izejas kodu

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>
Richard Henderson 3 gadi atpakaļ
vecāks
revīzija
c5fbdd60cf
1 mainītis faili ar 25 papildinājumiem un 0 dzēšanām
  1. 25 0
      hw/char/escc.c

+ 25 - 0
hw/char/escc.c

@@ -354,6 +354,17 @@ static void escc_reset(DeviceState *d)
             cs->rregs[j] = 0;
             cs->rregs[j] = 0;
             cs->wregs[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);
         escc_reset_chn(cs);
     }
     }
 }
 }
@@ -575,6 +586,20 @@ static void escc_mem_write(void *opaque, hwaddr addr,
             s->wregs[s->reg] = val;
             s->wregs[s->reg] = val;
             break;
             break;
         case W_TXCTRL1:
         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:
         case W_TXCTRL2:
             s->wregs[s->reg] = val;
             s->wregs[s->reg] = val;
             escc_update_parameters(s);
             escc_update_parameters(s);