qemu-devel
[Top][All Lists]
Advanced

[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
>
>

reply via email to

[Prev in Thread] Current Thread [Next in Thread]