All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] sparc escc IUS improvements (SunOS 4.1.4 fix)
@ 2010-08-15 14:04 Artyom Tarasenko
  2010-08-16 20:02 ` [Qemu-devel] " Blue Swirl
  0 siblings, 1 reply; 2+ messages in thread
From: Artyom Tarasenko @ 2010-08-15 14:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: blauwirbel, Artyom Tarasenko

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 <atar4qemu@gmail.com>
---
 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

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [Qemu-devel] Re: [PATCH] sparc escc IUS improvements (SunOS 4.1.4 fix)
  2010-08-15 14:04 [Qemu-devel] [PATCH] sparc escc IUS improvements (SunOS 4.1.4 fix) Artyom Tarasenko
@ 2010-08-16 20:02 ` Blue Swirl
  0 siblings, 0 replies; 2+ messages in thread
From: Blue Swirl @ 2010-08-16 20:02 UTC (permalink / raw)
  To: Artyom Tarasenko; +Cc: qemu-devel, Artyom Tarasenko

Thanks, applied.

On Sun, Aug 15, 2010 at 2:04 PM, Artyom Tarasenko
<atar4qemu@googlemail.com> 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 <atar4qemu@gmail.com>
> ---
>  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
>
>

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2010-08-16 20:02 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-08-15 14:04 [Qemu-devel] [PATCH] sparc escc IUS improvements (SunOS 4.1.4 fix) Artyom Tarasenko
2010-08-16 20:02 ` [Qemu-devel] " Blue Swirl

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.