Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/hp700 First pass at changing how spl masks are buil...



details:   https://anonhg.NetBSD.org/src/rev/c08c3180fac5
branches:  trunk
changeset: 535309:c08c3180fac5
user:      fredette <fredette%NetBSD.org@localhost>
date:      Wed Aug 14 16:18:11 2002 +0000

description:
First pass at changing how spl masks are built.  Now there is no
longer a forced correspondence between bit numbers in an interrupt
register and bit numbers in an spl mask.  This will avoid conflicts
between various interrupt registers in the same system.

Instead, bits in the spl mask are allocated on a first come, first
served basis by devices which can interrupt.  The new hp700_intr_ipending_new
takes care of reading all interrupt request registers that need
servicing, and mapping the bits set in those registers to new bits
set in ipending.

This whole mechanism is in and works.  A later commit will see the
I/O subsystems fixing which bits in their interrupt registers are
connected to which devices, largely removing irq information from
kernel configuration files.  There will also be a cosmetic fix to
show which spl bit corresponds to a device.

diffstat:

 sys/arch/hp700/hp700/genassym.cf |   10 ++-
 sys/arch/hp700/hp700/intr.c      |  158 ++++++++++++++++++--------------------
 sys/arch/hp700/hp700/intr.h      |   37 ++++++--
 sys/arch/hp700/hp700/locore.S    |  106 +++++++++++++++++++++++++-
 sys/arch/hp700/hp700/softintr.c  |   27 ++----
 sys/arch/hp700/include/intr.h    |    4 +-
 6 files changed, 227 insertions(+), 115 deletions(-)

diffs (truncated from 580 to 300 lines):

diff -r f3e75d6ef0fc -r c08c3180fac5 sys/arch/hp700/hp700/genassym.cf
--- a/sys/arch/hp700/hp700/genassym.cf  Wed Aug 14 15:41:57 2002 +0000
+++ b/sys/arch/hp700/hp700/genassym.cf  Wed Aug 14 16:18:11 2002 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: genassym.cf,v 1.2 2002/08/11 22:29:07 fredette Exp $
+#      $NetBSD: genassym.cf,v 1.3 2002/08/14 16:18:11 fredette Exp $
 
 #      $OpenBSD: genassym.cf,v 1.18 2001/09/20 18:31:14 mickey Exp $
 
@@ -58,6 +58,8 @@
 include <machine/pmap.h>
 include <machine/iomod.h>
 
+include <hp700/hp700/intr.h>
+
 include <hppa/hppa/hpt.h>
 
 # general constants
@@ -73,6 +75,12 @@
 export HPPA_BREAK_GET_PSW
 export HPPA_BREAK_SET_PSW
 
+# hp700_int_reg fields
+struct hp700_int_reg
+member INT_REG_REQ     int_reg_req
+member INT_REG_BITS_MAP int_reg_bits_map
+export INT_REG_BIT_REG_POS
+
 # pte things
 export TLB_REF_POS
 export TLB_NO_RW_ALIAS_POS
diff -r f3e75d6ef0fc -r c08c3180fac5 sys/arch/hp700/hp700/intr.c
--- a/sys/arch/hp700/hp700/intr.c       Wed Aug 14 15:41:57 2002 +0000
+++ b/sys/arch/hp700/hp700/intr.c       Wed Aug 14 16:18:11 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: intr.c,v 1.1 2002/06/06 19:48:06 fredette Exp $        */
+/*     $NetBSD: intr.c,v 1.2 2002/08/14 16:18:11 fredette Exp $        */
 
 /*
  * Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.1 2002/06/06 19:48:06 fredette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.2 2002/08/14 16:18:11 fredette Exp $");
 
 #include <sys/param.h>
 #include <sys/malloc.h>
@@ -55,8 +55,6 @@
 
 #include <uvm/uvm_extern.h>
 
-#define        HP700_INT_BITS  (32)
-
 /* The priority level masks. */
 int imask[NIPL];
 
@@ -70,8 +68,7 @@
 u_int hppa_intr_depth;
 
 /* The list of all interrupt registers. */
-static SLIST_HEAD(hp700_int_reg_list, hp700_int_reg)
-       hp700_int_regs;
+struct hp700_int_reg *hp700_int_regs[HP700_INT_BITS];
 
 /*
  * The array of interrupt handler structures, one per bit.
@@ -102,11 +99,8 @@
 
        /*
         * The interrupt handler and argument for this
-        * bit.  If the handler is NULL, this interrupt
-        * bit is for a whole I/O subsystem, and the
-        * argument is the struct hp700_int_reg for
-        * that subsystem.  If the argument is NULL,
-        * the handler gets the trapframe.
+        * bit.  If the argument is NULL, the handler 
+        * gets the trapframe.
         */
        int (*int_bit_handler) __P((void *));
        void *int_bit_arg;
@@ -131,12 +125,19 @@
 void
 hp700_intr_reg_establish(struct hp700_int_reg *int_reg)
 {
+       int idx;
 
-       /* Zero the register structure. */
+       /* Initialize the register structure. */
        memset(int_reg, 0, sizeof(*int_reg));
+       memset(int_reg->int_reg_bits_map, INT_REG_BIT_UNUSED,
+               sizeof(int_reg->int_reg_bits_map));
 
        /* Add this structure to the list. */
-       SLIST_INSERT_HEAD(&hp700_int_regs, int_reg, next);
+       for (idx = 0; idx < HP700_INT_BITS; idx++)
+               if (hp700_int_regs[idx] == NULL) break;
+       if (idx == HP700_INT_BITS)
+               panic("hp700_intr_reg_establish: too many regs");
+       hp700_int_regs[idx] = int_reg;
 }
 
 /*
@@ -167,7 +168,7 @@
        memset(hp700_int_bits, 0, sizeof(hp700_int_bits));
 
        /* There are no interrupt registers. */
-       SLIST_INIT(&hp700_int_regs);
+       memset(hp700_int_regs, 0, sizeof(hp700_int_regs));
 
        /* Initialize the CPU interrupt register description. */
        hp700_intr_reg_establish(&int_reg_cpu);
@@ -186,17 +187,40 @@
                     struct hp700_int_reg *int_reg, int bit_pos)
 {
        struct hp700_int_bit *int_bit;
+       int idx;
        
        /* Panic if this int bit is already handled. */
-       int_bit = hp700_int_bits + bit_pos;
-       if (int_bit->int_bit_handler != NULL ||
-           int_bit->int_bit_arg != NULL)
+       if (int_reg->int_reg_bits_map[31 ^ bit_pos] != INT_REG_BIT_UNUSED)
                panic("hp700_intr_establish: int already handled\n");
 
+       /*
+        * If this interrupt bit leads us to another interrupt
+        * register, simply note that in the mapping for the bit.
+        */
+       if (handler == NULL) {
+               for (idx = 0; idx < HP700_INT_BITS; idx++)
+                       if (hp700_int_regs[idx] == arg) break;
+               if (idx == HP700_INT_BITS)
+                       panic("hp700_intr_establish: unknown int reg");
+               int_reg->int_reg_bits_map[31 ^ bit_pos] = 
+                       (INT_REG_BIT_REG | idx);
+               return (NULL);
+       }
+
+       /*
+        * Otherwise, allocate a new bit in the spl.
+        */
+       for (idx = 0; idx < HP700_INT_BITS; idx++)
+               if (hp700_int_bits[idx].int_bit_reg == NULL) break;
+       if (idx == HP700_INT_BITS)
+               panic("hp700_intr_establish: too many devices");
+       int_reg->int_reg_bits_map[31 ^ bit_pos] = (31 ^ idx);
+       int_bit = hp700_int_bits + idx;
+
        /* Fill this int bit. */
        int_bit->int_bit_reg = int_reg;
        int_bit->int_bit_ipl = ipl;
-       int_bit->int_bit_spl = (1 << bit_pos);
+       int_bit->int_bit_spl = (1 << idx);
        evcnt_attach_dynamic(&int_bit->int_bit_evcnt, EVCNT_TYPE_INTR, NULL,
            dv->dv_xname, "intr");
        int_bit->int_bit_handler = handler;
@@ -206,39 +230,40 @@
 }
 
 /*
+ * This return the single-bit spl mask for an interrupt.  This 
+ * can only be called immediately after hp700_intr_establish, and 
+ * is not intended for wide use.
+ */
+int
+_hp700_intr_spl_mask(void *_int_bit)
+{
+       return ((struct hp700_int_bit *) _int_bit)->int_bit_spl;
+}
+
+/*
  * This finally initializes interrupts.
  */
 void
 hp700_intr_init(void)
 {
-       int bit_pos;
+       int idx, bit_pos;
        struct hp700_int_bit *int_bit;
-       int spl_free, spl_mask;
+       int mask;
        struct hp700_int_reg *int_reg;
        int eiem;
 
-       /* Calculate the remaining free spl bits. */
-       spl_free = 0;
-       for (bit_pos = 0; bit_pos < HP700_INT_BITS; bit_pos++)
-               spl_free |= hp700_int_bits[bit_pos].int_bit_spl;
-       spl_free = ~spl_free;
-
        /* Initialize soft interrupts. */
-       spl_free = softintr_init(spl_free);
+       softintr_init();
 
        /*
-        * Put together the initial imask for each level and
-        * mark which bits in each interrupt register are
-        * frobbable.
+        * Put together the initial imask for each level.
         */
        memset(imask, 0, sizeof(imask));
        for (bit_pos = 0; bit_pos < HP700_INT_BITS; bit_pos++) {
                int_bit = hp700_int_bits + bit_pos;
                if (int_bit->int_bit_reg == NULL)
                        continue;
-               spl_mask = int_bit->int_bit_spl;
-               imask[int_bit->int_bit_ipl] |= spl_mask;
-               int_bit->int_bit_reg->int_reg_frobbable |= spl_mask;
+               imask[int_bit->int_bit_ipl] |= int_bit->int_bit_spl;
        }
        
        /* The following bits cribbed from i386/isa/isa_machdep.c: */
@@ -308,12 +333,20 @@
         */
        cpl = -1;
        ipending = 0;
-       SLIST_FOREACH(int_reg, &hp700_int_regs, next) {
-               spl_mask = int_reg->int_reg_frobbable;
+       for (idx = 0; idx < HP700_INT_BITS; idx++) {
+               int_reg = hp700_int_regs[idx];
+               if (int_reg == NULL)
+                       continue;
+               mask = 0;
+               for (bit_pos = 0; bit_pos < HP700_INT_BITS; bit_pos++) {
+                       if (int_reg->int_reg_bits_map[31 ^ bit_pos] !=
+                           INT_REG_BIT_UNUSED)
+                               mask |= (1 << bit_pos);
+               }
                if (int_reg == &int_reg_cpu)
-                       eiem = spl_mask;
+                       eiem = mask;
                else if (int_reg->int_reg_mask != NULL)
-                       *int_reg->int_reg_mask = spl_mask;
+                       *int_reg->int_reg_mask = mask;
        }
        mtctl(eiem, CR_EIEM);
 }
@@ -328,59 +361,16 @@
 {
        int eirr;
        int ipending_new;
-       int bit_pos, bit_mask;
-       struct hp700_int_bit *int_bit;
-       struct hp700_int_reg *int_reg;
+       int hp700_intr_ipending_new __P((struct hp700_int_reg *, int));
 
        /*
         * Read the CPU interrupt register and acknowledge
-        * all interrupts.  Take this value as our initial
-        * set of new pending interrupts.
+        * all interrupts.  Starting with this value, get
+        * our set of new pending interrupts.
         */
        mfctl(CR_EIRR, eirr);
        mtctl(eirr, CR_EIRR);
-       ipending_new = eirr;
-
-       /* Loop while there are CPU interrupt bits. */
-       while (eirr) {
-
-               /* Get the next bit. */
-               bit_pos = ffs(eirr) - 1;
-               bit_mask = ~(1 << bit_pos);
-               eirr &= bit_mask;
-               int_bit = hp700_int_bits + bit_pos;
-
-               /*
-                * If this bit has a real interrupt handler,
-                * it's not for an I/O subsystem.  Continue.
-                */
-               if (int_bit->int_bit_handler != NULL)
-                       continue;
-
-               /*
-                * Now this bit is either for an I/O subsystem 
-                * or it's a stray.
-                */
-
-               /* Clear the bit from our ipending_new value. */
-               ipending_new &= bit_mask;
-
-               /*
-                * If this is for an I/O subsystem, read its 
-                * request register, mask off any bits that 
-                * aren't frobbable, and or the result into 
-                * ipending_new.
-                *
-                * The read of the request register also serves 
-                * to acknowledge the interrupt to the I/O subsystem.
-                */
-               int_reg = int_bit->int_bit_arg;
-               if (int_reg != NULL)
-                       ipending_new |= (*int_reg->int_reg_req &
-                                        int_reg->int_reg_frobbable);
-               else
-                       printf("cpu0: stray int %d\n", bit_pos);
-       }
+       ipending_new = hp700_intr_ipending_new(&int_reg_cpu, eirr);



Home | Main Index | Thread Index | Old Index