[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] Re: [PATCH] sparc escc IUS improvements (SunOS 4.1.4 fix)
From: |
Blue Swirl |
Subject: |
[Qemu-devel] Re: [PATCH] sparc escc IUS improvements (SunOS 4.1.4 fix) |
Date: |
Mon, 16 Aug 2010 20:02:05 +0000 |
Thanks, applied.
On Sun, Aug 15, 2010 at 2:04 PM, Artyom Tarasenko
<address@hidden> wrote:
> According to scc_escc_um.pdf:
> - Reset Highest IUS must update irq status to allow processing
> of the next priority interrupt.
> - rx interrupt has always higher priority than tx on same channel
>
> The documentation only explicitly says that Reset Highest IUS
> command (0x38) clears IUS bits, not that it clears the corresponding
> interrupt too, so don't clear interrupts on this command.
>
> The patch allows SunOS 4.1.4 to use the serial ports
>
> Signed-off-by: Artyom Tarasenko <address@hidden>
> ---
> hw/escc.c | 56 ++++++++++++++++++++++++++++++--------------------------
> 1 files changed, 30 insertions(+), 26 deletions(-)
>
> diff --git a/hw/escc.c b/hw/escc.c
> index 6d2fd36..8714239 100644
> --- a/hw/escc.c
> +++ b/hw/escc.c
> @@ -65,6 +65,8 @@
> * 2006-Aug-10 Igor Kovalenko : Renamed KBDQueue to SERIOQueue,
> implemented
> * serial mouse queue.
> * Implemented serial mouse protocol.
> + *
> + * 2010-May-23 Artyom Tarasenko: Reworked IUS logic
> */
>
> #ifdef DEBUG_SERIAL
> @@ -279,7 +281,7 @@ static uint32_t get_queue(void *opaque)
>
> static int escc_update_irq_chn(ChannelState *s)
> {
> - if ((((s->wregs[W_INTR] & INTR_TXINT) && s->txint == 1) ||
> + if ((((s->wregs[W_INTR] & INTR_TXINT) && (s->txint == 1)) ||
> // tx ints enabled, pending
> ((((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINT1ST) ||
> ((s->wregs[W_INTR] & INTR_RXMODEMSK) == INTR_RXINTALL)) &&
> @@ -342,24 +344,22 @@ static void escc_reset(DeviceState *d)
> static inline void set_rxint(ChannelState *s)
> {
> s->rxint = 1;
> - if (!s->txint_under_svc) {
> - s->rxint_under_svc = 1;
> - if (s->chn == chn_a) {
> - if (s->wregs[W_MINTR] & MINTR_STATUSHI)
> - s->otherchn->rregs[R_IVEC] = IVEC_HIRXINTA;
> - else
> - s->otherchn->rregs[R_IVEC] = IVEC_LORXINTA;
> - } else {
> - if (s->wregs[W_MINTR] & MINTR_STATUSHI)
> - s->rregs[R_IVEC] = IVEC_HIRXINTB;
> - else
> - s->rregs[R_IVEC] = IVEC_LORXINTB;
> - }
> - }
> - if (s->chn == chn_a)
> + /* XXX: missing daisy chainnig: chn_b rx should have a lower priority
> + than chn_a rx/tx/special_condition service*/
> + s->rxint_under_svc = 1;
> + if (s->chn == chn_a) {
> s->rregs[R_INTR] |= INTR_RXINTA;
> - else
> + if (s->wregs[W_MINTR] & MINTR_STATUSHI)
> + s->otherchn->rregs[R_IVEC] = IVEC_HIRXINTA;
> + else
> + s->otherchn->rregs[R_IVEC] = IVEC_LORXINTA;
> + } else {
> s->otherchn->rregs[R_INTR] |= INTR_RXINTB;
> + if (s->wregs[W_MINTR] & MINTR_STATUSHI)
> + s->rregs[R_IVEC] = IVEC_HIRXINTB;
> + else
> + s->rregs[R_IVEC] = IVEC_LORXINTB;
> + }
> escc_update_irq(s);
> }
>
> @@ -369,19 +369,17 @@ static inline void set_txint(ChannelState *s)
> if (!s->rxint_under_svc) {
> s->txint_under_svc = 1;
> if (s->chn == chn_a) {
> + s->rregs[R_INTR] |= INTR_TXINTA;
> if (s->wregs[W_MINTR] & MINTR_STATUSHI)
> s->otherchn->rregs[R_IVEC] = IVEC_HITXINTA;
> else
> s->otherchn->rregs[R_IVEC] = IVEC_LOTXINTA;
> } else {
> s->rregs[R_IVEC] = IVEC_TXINTB;
> + s->otherchn->rregs[R_INTR] |= INTR_TXINTB;
> }
> - }
> - if (s->chn == chn_a)
> - s->rregs[R_INTR] |= INTR_TXINTA;
> - else
> - s->otherchn->rregs[R_INTR] |= INTR_TXINTB;
> escc_update_irq(s);
> + }
> }
>
> static inline void clr_rxint(ChannelState *s)
> @@ -417,6 +415,7 @@ static inline void clr_txint(ChannelState *s)
> s->otherchn->rregs[R_IVEC] = IVEC_LONOINT;
> s->rregs[R_INTR] &= ~INTR_TXINTA;
> } else {
> + s->otherchn->rregs[R_INTR] &= ~INTR_TXINTB;
> if (s->wregs[W_MINTR] & MINTR_STATUSHI)
> s->rregs[R_IVEC] = IVEC_HINOINT;
> else
> @@ -515,10 +514,15 @@ static void escc_mem_writeb(void *opaque,
> target_phys_addr_t addr, uint32_t val)
> clr_txint(s);
> break;
> case CMD_CLR_IUS:
> - if (s->rxint_under_svc)
> - clr_rxint(s);
> - else if (s->txint_under_svc)
> - clr_txint(s);
> + if (s->rxint_under_svc) {
> + s->rxint_under_svc = 0;
> + if (s->txint) {
> + set_txint(s);
> + }
> + } else if (s->txint_under_svc) {
> + s->txint_under_svc = 0;
> + }
> + escc_update_irq(s);
> break;
> default:
> break;
> --
> 1.7.2.1
>
>