Interrupt code changed from called routines, to initialized driver.
authorrahnds <rahnds@openbsd.org>
Mon, 20 Mar 2000 07:26:49 +0000 (07:26 +0000)
committerrahnds <rahnds@openbsd.org>
Mon, 20 Mar 2000 07:26:49 +0000 (07:26 +0000)
Added openpic support with this new driver scheme.

added support for keylargo-ata, G4 ide configures properly.
interrupt configuration changed to be more full featured, like isa had been.

sys/arch/powerpc/mac/if_bm.c
sys/arch/powerpc/mac/macintr.c
sys/arch/powerpc/mac/openpic.c [new file with mode: 0644]
sys/arch/powerpc/mac/wdc_obio.c

index 2e38fe7..1cbcf4c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_bm.c,v 1.2 2000/02/03 05:49:46 rahnds Exp $        */
+/*     $OpenBSD: if_bm.c,v 1.3 2000/03/20 07:26:49 rahnds Exp $        */
 /*     $NetBSD: if_bm.c,v 1.1 1999/01/01 01:27:52 tsubai Exp $ */
 
 /*-
@@ -225,11 +225,14 @@ bmac_attach(parent, self, aux)
        printf(" irq %d,%d: address %s\n", ca->ca_intr[0], ca->ca_intr[2],
                ether_sprintf(laddr));
 
-       mac_intr_establish(ca->ca_intr[0], IST_LEVEL, IPL_NET, bmac_intr, sc);
+       mac_intr_establish(parent, ca->ca_intr[0], IST_LEVEL, IPL_NET,
+               bmac_intr, sc, "bmac intr");
        /*
-       mac_intr_establish(ca->ca_intr[1], IST_LEVEL, IPL_NET, bmac_tx_intr, sc);
+       mac_intr_establish(parent, ca->ca_intr[1], IST_LEVEL, IPL_NET,
+               bmac_tx_intr, sc, "bmac_tx");
        */
-       mac_intr_establish(ca->ca_intr[2], IST_LEVEL, IPL_NET, bmac_rint, sc);
+       mac_intr_establish(parent, ca->ca_intr[2], IST_LEVEL, IPL_NET,
+               bmac_rint, sc, "bmac rint");
 
        bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
        ifp->if_softc = sc;
index cbaec1a..c729d2b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: macintr.c,v 1.1 1999/11/08 23:46:01 rahnds Exp $      */
+/*     $OpenBSD: macintr.c,v 1.2 2000/03/20 07:26:50 rahnds Exp $      */
 
 /*-
  * Copyright (c) 1995 Per Fogelstrom
  *
  *     @(#)isa.c       7.2 (Berkeley) 5/12/91
  */
+
 #include <sys/param.h>
-#include <sys/proc.h>
-#include <sys/user.h>
-#include <sys/systm.h>
-#include <sys/time.h>
-#include <sys/kernel.h>
 #include <sys/device.h>
-#include <sys/malloc.h>
-
-#include <vm/vm.h>
-#include <vm/vm_kern.h>
+#include <sys/ioctl.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
 
+#include <machine/autoconf.h>
 #include <machine/intr.h>
 #include <machine/psl.h>
 #include <machine/pio.h>
@@ -71,6 +68,9 @@ static char *intr_typename(int type);
 static void intr_calculatemasks();
 static void enable_irq(int x);
 static __inline int cntlzw(int x);
+static int mapirq(int irq);
+static int read_irq();
+static void mac_intr_do_pending_int();
 
 extern u_int32_t *heathrow_FCR;
 
@@ -86,10 +86,96 @@ extern u_int32_t *heathrow_FCR;
 #define INT_CLEAR_REG1  (INT_CLEAR_REG0  - 0x10)
 #define INT_LEVEL_REG1  (INT_LEVEL_REG0  - 0x10)
 
-int      macintrmatch __P((struct device *, void *, void *));
-void     macintrattach __P((struct device *, struct device *, void *));
+struct macintr_softc {
+       struct device sc_dev;
+};
+
+int    macintr_match __P((struct device *parent, void *cf, void *aux));
+void   macintr_attach __P((struct device *, struct device *, void *));
+void   mac_do_pending_int();
+void   mac_ext_intr();
+
+struct cfattach macintr_ca = { 
+       sizeof(struct macintr_softc),
+       macintr_match,
+       macintr_attach
+};
+
+struct cfdriver macintr_cd = {
+       NULL, "macintr", DV_DULL
+};
+
+int
+macintr_match(parent, cf, aux) 
+       struct device *parent;
+       void *cf;
+       void *aux;
+{
+       char type[40];
+       struct confargs *ca = aux;
+
+       bzero (type, sizeof(type));
+
+       if (strcmp(ca->ca_name, "interrupt-controller") == 0 ) {
+               OF_getprop(ca->ca_node, "device_type", type, sizeof(type));
+               if (strcmp(type,  "interrupt-controller") == 0) {
+                       return 1;
+               }
+       }
+       return 0;
+}
 
 u_int8_t *interrupt_reg;
+typedef void  (void_f) (void);
+extern void_f *pending_int_f;
+int prog_switch (void *arg);
+typedef int mac_intr_handle_t;
+
+typedef void     *(intr_establish_t) __P((void *, mac_intr_handle_t,
+            int, int, int (*func)(void *), void *, char *));
+typedef void     (intr_disestablish_t) __P((void *, void *));
+
+intr_establish_t macintr_establish;
+intr_disestablish_t macintr_disestablish;
+extern intr_establish_t *mac_intr_establish_func;
+extern intr_disestablish_t *mac_intr_disestablish_func;
+
+void
+macintr_attach(parent, self, aux)
+       struct device *parent, *self;
+       void *aux;
+{
+       struct confargs *ca = aux;
+       struct macintr_softc *sc = (void *)self;
+       extern intr_establish_t *intr_establish_func;
+       extern intr_disestablish_t *intr_disestablish_func;
+
+       interrupt_reg = (void *)ca->ca_baseaddr; /* XXX */
+
+       install_extint(mac_ext_intr);
+       pending_int_f = mac_intr_do_pending_int;
+       intr_establish_func  = macintr_establish;
+       intr_disestablish_func  = macintr_disestablish;
+       mac_intr_establish_func  = macintr_establish;
+       mac_intr_disestablish_func  = macintr_disestablish;
+
+
+       mac_intr_establish(parent, 0x14, IST_LEVEL, IPL_HIGH,
+               prog_switch, (void *)0x14, "prog button");
+
+       printf("\n");
+}
+
+int
+prog_switch (void *arg)
+{
+#ifdef DDB
+        Debugger();
+#else
+       printf("programmer button pressed, debugger not available\n");
+#endif
+       return 1;
+}
 
 static int
 fakeintr(arg)
@@ -103,21 +189,24 @@ fakeintr(arg)
  * Register an interrupt handler.
  */
 void *
-mac_intr_establish(irq, type, level, ih_fun, ih_arg)
+macintr_establish(lcv, irq, type, level, ih_fun, ih_arg, name)
+       void * lcv;
        int irq;
        int type;
        int level;
        int (*ih_fun) __P((void *));
        void *ih_arg;
+       char *name;
 {
        struct intrhand **p, *q, *ih;
        static struct intrhand fakehand;
        extern int cold;
+
        fakehand.ih_next = NULL;
        fakehand.ih_fun  = fakeintr;
 
 #if 0
-printf("mac_intr_establish, hI %d L %d ", irq, type);
+printf("macintr_establish, hI %d L %d ", irq, type);
 printf("addr reg0 %x\n", INT_STATE_REG0);
 #endif
 
@@ -160,7 +249,7 @@ printf("vI %d ", irq);
 
        /*
         * Actually install a fake handler momentarily, since we might be doing
-        * this with interrupts enabled and don't want the real routine called
+        * this with interrupts enabled and DON'T WANt the real routine called
         * until masking is set up.
         */
        fakehand.ih_level = level;
@@ -186,7 +275,8 @@ printf("vI %d ", irq);
  * Deregister an interrupt handler.
  */
 void
-mac_intr_disestablish(arg)
+macintr_disestablish(lcp, arg)
+       void *lcp;
        void *arg;
 {
        struct intrhand *ih = arg;
@@ -332,7 +422,7 @@ enable_irq(x)
 /*
  * Map 64 irqs into 32 (bits).
  */
-int
+static int
 mapirq(irq)
        int irq;
 {
@@ -424,7 +514,7 @@ out:
 }
 
 void
-mac_do_pending_int()
+mac_intr_do_pending_int()
 {
        struct intrhand *ih;
        int irq;
@@ -479,7 +569,7 @@ mac_do_pending_int()
        processing = 0;
 }
 
-int
+static int
 read_irq()
 {
        int rv = 0;
diff --git a/sys/arch/powerpc/mac/openpic.c b/sys/arch/powerpc/mac/openpic.c
new file mode 100644 (file)
index 0000000..0b768cc
--- /dev/null
@@ -0,0 +1,670 @@
+/*     $OpenBSD: openpic.c,v 1.1 2000/03/20 07:26:50 rahnds Exp $      */
+
+/*-
+ * Copyright (c) 1995 Per Fogelstrom
+ * Copyright (c) 1993, 1994 Charles M. Hannum.
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz and Don Ahn.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)isa.c       7.2 (Berkeley) 5/12/91
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/ioctl.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+
+#include <machine/autoconf.h>
+#include <machine/intr.h>
+#include <machine/psl.h>
+#include <machine/pio.h>
+#include <powerpc/mac/openpicreg.h>
+
+#define ICU_LEN 64
+#define LEGAL_IRQ(x) ((x >= 0) && (x < ICU_LEN))
+
+static int intrtype[ICU_LEN], intrmask[ICU_LEN], intrlevel[ICU_LEN];
+static struct intrhand *intrhand[ICU_LEN] = { 0 };
+static int hwirq[ICU_LEN], virq[64];
+unsigned int imen /* = 0xffffffff */; /* XXX */
+static int virq_max = 0;
+
+struct evcnt evirq[ICU_LEN*2];
+
+static int fakeintr __P((void *));
+static char *intr_typename(int type);
+static void intr_calculatemasks();
+static __inline int cntlzw(int x);
+static int mapirq(int irq);
+static int read_irq();
+void openpic_enable_irq_mask(int irq_mask);
+
+extern u_int32_t *heathrow_FCR;
+
+#define HWIRQ_MAX 27
+#define HWIRQ_MASK 0x0fffffff
+
+
+static __inline u_int openpic_read __P((int));
+static __inline void openpic_write __P((int, u_int));
+void openpic_enable_irq __P((int));
+void openpic_disable_irq __P((int));
+void openpic_init();
+void openpic_set_priority __P((int, int));
+static __inline int openpic_read_irq __P((int));
+static __inline void openpic_eoi __P((int));
+
+struct openpic_softc {
+       struct device sc_dev;
+};
+
+int    openpic_match __P((struct device *parent, void *cf, void *aux));
+void   openpic_attach __P((struct device *, struct device *, void *));
+void   openpic_do_pending_int();
+void ext_intr_openpic();
+
+struct cfattach openpic_ca = { 
+       sizeof(struct openpic_softc),
+       openpic_match,
+       openpic_attach
+};
+
+struct cfdriver openpic_cd = {
+       NULL, "openpic", DV_DULL
+};
+
+int
+openpic_match(parent, cf, aux) 
+       struct device *parent;
+       void *cf;
+       void *aux;
+{
+       char type[40];
+       struct confargs *ca = aux;
+
+       bzero (type, sizeof(type));
+
+       if (strcmp(ca->ca_name, "interrupt-controller") == 0 ) {
+               OF_getprop(ca->ca_node, "device_type", type, sizeof(type));
+               if (strcmp(type,  "open-pic") == 0) {
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+u_int8_t *interrupt_reg;
+typedef void  (void_f) (void);
+extern void_f *pending_int_f;
+static int prog_switch (void *arg);
+typedef int mac_intr_handle_t;
+
+typedef void     *(intr_establish_t) __P((void *, mac_intr_handle_t,
+            int, int, int (*func)(void *), void *, char *));
+typedef void     (intr_disestablish_t) __P((void *, void *));
+
+vaddr_t openpic_base;
+void * openpic_intr_establish( void * lcv, int irq, int type, int level,
+       int (*ih_fun) __P((void *)), void *ih_arg, char *name);
+void openpic_intr_disestablish( void *lcp, void *arg);
+
+void
+openpic_attach(parent, self, aux)
+       struct device *parent, *self;
+       void *aux;
+{
+       struct confargs *ca = aux;
+       struct openpic_softc *sc = (void *)self;
+       extern intr_establish_t *intr_establish_func;
+       extern intr_disestablish_t *intr_disestablish_func;
+       extern intr_establish_t *mac_intr_establish_func;
+       extern intr_disestablish_t *mac_intr_disestablish_func;
+
+       openpic_base = (vaddr_t) mapiodev (ca->ca_baseaddr +
+                       ca->ca_reg[0], 0x22000);
+
+       printf("version %x", openpic_read(OPENPIC_VENDOR_ID));
+
+       openpic_init();
+
+       pending_int_f = openpic_do_pending_int;
+       intr_establish_func  = openpic_intr_establish;
+       intr_disestablish_func  = openpic_intr_disestablish;
+       mac_intr_establish_func  = openpic_intr_establish;
+       mac_intr_disestablish_func  = openpic_intr_disestablish;
+       install_extint(ext_intr_openpic);
+
+#if 1
+       mac_intr_establish(parent, 0x37, IST_LEVEL,
+               IPL_HIGH, prog_switch, 0x37, "prog button");
+#endif
+
+       printf("\n");
+}
+
+static int
+prog_switch (void *arg)
+{
+#ifdef DDB
+        Debugger();
+#else
+       printf("programmer button pressed, debugger not available\n");
+#endif
+       return 1;
+}
+
+static int
+fakeintr(arg)
+       void *arg;
+{
+
+       return 0;
+}
+
+/*
+ * Register an interrupt handler.
+ */
+void *
+openpic_intr_establish(lcv, irq, type, level, ih_fun, ih_arg, name)
+       void * lcv;
+       int irq;
+       int type;
+       int level;
+       int (*ih_fun) __P((void *));
+       void *ih_arg;
+       char *name;
+{
+       struct intrhand **p, *q, *ih;
+       static struct intrhand fakehand;
+       extern int cold;
+
+       fakehand.ih_next = NULL;
+       fakehand.ih_fun  = fakeintr;
+
+#if 0
+printf("mac_intr_establish, hI %d L %d ", irq, type);
+#endif
+
+       irq = mapirq(irq);
+#if 0
+printf("vI %d ", irq);
+#endif
+
+       /* no point in sleeping unless someone can free memory. */
+       ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
+       if (ih == NULL)
+               panic("intr_establish: can't malloc handler info");
+
+       if (!LEGAL_IRQ(irq) || type == IST_NONE)
+               panic("intr_establish: bogus irq or type");
+
+       switch (intrtype[irq]) {
+       case IST_NONE:
+               intrtype[irq] = type;
+               break;
+       case IST_EDGE:
+       case IST_LEVEL:
+               if (type == intrtype[irq])
+                       break;
+       case IST_PULSE:
+               if (type != IST_NONE)
+                       panic("intr_establish: can't share %s with %s",
+                           intr_typename(intrtype[irq]),
+                           intr_typename(type));
+               break;
+       }
+
+       /*
+        * Figure out where to put the handler.
+        * This is O(N^2), but we want to preserve the order, and N is
+        * generally small.
+        */
+       for (p = &intrhand[irq]; (q = *p) != NULL; p = &q->ih_next)
+               ;
+
+       /*
+        * Actually install a fake handler momentarily, since we might be doing
+        * this with interrupts enabled and DON'T WANt the real routine called
+        * until masking is set up.
+        */
+       fakehand.ih_level = level;
+       *p = &fakehand;
+
+       intr_calculatemasks();
+
+       /*
+        * Poke the real handler in now.
+        */
+       ih->ih_fun = ih_fun;
+       ih->ih_arg = ih_arg;
+       ih->ih_count = 0;
+       ih->ih_next = NULL;
+       ih->ih_level = level;
+       ih->ih_irq = irq;
+       *p = ih;
+
+       return (ih);
+}
+
+/*
+ * Deregister an interrupt handler.
+ */
+void
+openpic_intr_disestablish(lcp, arg)
+       void *lcp;
+       void *arg;
+{
+       struct intrhand *ih = arg;
+       int irq = ih->ih_irq;
+       struct intrhand **p, *q;
+
+       if (!LEGAL_IRQ(irq))
+               panic("intr_disestablish: bogus irq");
+
+       /*
+        * Remove the handler from the chain.
+        * This is O(n^2), too.
+        */
+       for (p = &intrhand[irq]; (q = *p) != NULL && q != ih; p = &q->ih_next)
+               ;
+       if (q)
+               *p = q->ih_next;
+       else
+               panic("intr_disestablish: handler not registered");
+       free((void *)ih, M_DEVBUF);
+
+       intr_calculatemasks();
+
+       if (intrhand[irq] == NULL)
+               intrtype[irq] = IST_NONE;
+}
+
+
+static char *
+intr_typename(type)
+       int type;
+{
+
+       switch (type) {
+        case IST_NONE :
+               return ("none");
+        case IST_PULSE:
+               return ("pulsed");
+        case IST_EDGE:
+               return ("edge-triggered");
+        case IST_LEVEL:
+               return ("level-triggered");
+       default:
+               panic("intr_typename: invalid type %d", type);
+#if 1 /* XXX */
+               return ("unknown");
+#endif
+       }
+}
+
+/*
+ * Recalculate the interrupt masks from scratch.
+ * We could code special registry and deregistry versions of this function that
+ * would be faster, but the code would be nastier, and we don't expect this to
+ * happen very much anyway.
+ */
+static void
+intr_calculatemasks()
+{
+       int irq, level;
+       struct intrhand *q;
+
+       /* First, figure out which levels each IRQ uses. */
+       for (irq = 0; irq < ICU_LEN; irq++) {
+               register int levels = 0;
+               for (q = intrhand[irq]; q; q = q->ih_next)
+                       levels |= 1 << q->ih_level;
+               intrlevel[irq] = levels;
+       }
+
+       /* Then figure out which IRQs use each level. */
+       for (level = 0; level < 5; level++) {
+               register int irqs = 0;
+               for (irq = 0; irq < ICU_LEN; irq++)
+                       if (intrlevel[irq] & (1 << level))
+                               irqs |= 1 << irq;
+               imask[level] = irqs | SINT_MASK;
+       }
+
+       /*
+        * There are tty, network and disk drivers that use free() at interrupt
+        * time, so imp > (tty | net | bio).
+        */
+       imask[IPL_IMP] |= imask[IPL_TTY] | imask[IPL_NET] | imask[IPL_BIO];
+
+       /*
+        * Enforce a hierarchy that gives slow devices a better chance at not
+        * dropping data.
+        */
+       imask[IPL_TTY] |= imask[IPL_NET] | imask[IPL_BIO];
+       imask[IPL_NET] |= imask[IPL_BIO];
+
+       /*
+        * These are pseudo-levels.
+        */
+       imask[IPL_NONE] = 0x00000000;
+       imask[IPL_HIGH] = 0xffffffff;
+
+       /* And eventually calculate the complete masks. */
+       for (irq = 0; irq < ICU_LEN; irq++) {
+               register int irqs = 1 << irq;
+               for (q = intrhand[irq]; q; q = q->ih_next)
+                       irqs |= imask[q->ih_level];
+               intrmask[irq] = irqs | SINT_MASK;
+       }
+
+       /* Lastly, determine which IRQs are actually in use. */
+       {
+               register int irqs = 0;
+               for (irq = 0; irq < ICU_LEN; irq++) {
+                       if (intrhand[irq]) {
+                               irqs |= 1 << irq;
+                               openpic_enable_irq(hwirq[irq]);
+                       } else {
+                               openpic_disable_irq(hwirq[irq]);
+                       }
+               }
+               imen = ~irqs;
+       }
+}
+/*
+ * Map 64 irqs into 32 (bits).
+ */
+static int
+mapirq(irq)
+       int irq;
+{
+       int v;
+
+       if (irq < 0 || irq >= 64)
+               panic("invalid irq");
+       virq_max++;
+       v = virq_max;
+       if (v > HWIRQ_MAX)
+               panic("virq overflow");
+
+       hwirq[v] = irq;
+       virq[irq] = v;
+#if 0
+printf("\nmapirq %x to %x\n", irq, v);
+#endif
+
+       return v;
+}
+
+/*
+ * Count leading zeros.
+ */
+static __inline int
+cntlzw(x)
+       int x;
+{
+       int a;
+
+       __asm __volatile ("cntlzw %0,%1" : "=r"(a) : "r"(x));
+
+       return a;
+}
+
+
+void
+openpic_do_pending_int()
+{
+       struct intrhand *ih;
+       int irq;
+       int pcpl;
+       int hwpend;
+       int emsr, dmsr;
+       static int processing;
+
+       if (processing)
+               return;
+
+       processing = 1;
+       pcpl = splhigh();               /* Turn off all */
+       asm volatile("mfmsr %0" : "=r"(emsr));
+       dmsr = emsr & ~PSL_EE;
+       asm volatile("mtmsr %0" :: "r"(dmsr));
+
+       hwpend = ipending & ~pcpl;      /* Do now unmasked pendings */
+       imen &= ~hwpend;
+       openpic_enable_irq_mask(~imen);
+       hwpend &= HWIRQ_MASK;
+       while (hwpend) {
+               irq = 31 - cntlzw(hwpend);
+               hwpend &= ~(1L << irq);
+               ih = intrhand[irq];
+               while(ih) {
+                       (*ih->ih_fun)(ih->ih_arg);
+                       ih = ih->ih_next;
+               }
+
+               evirq[hwirq[irq]].ev_count++;
+       }
+
+       /*out32rb(INT_ENABLE_REG, ~imen);*/
+
+       do {
+               if((ipending & SINT_CLOCK) & ~pcpl) {
+                       ipending &= ~SINT_CLOCK;
+                       softclock();
+               }
+               if((ipending & SINT_NET) & ~pcpl) {
+                       extern int netisr;
+                       int pisr = netisr;
+                       netisr = 0;
+                       ipending &= ~SINT_NET;
+                       softnet(pisr);
+               }
+       } while (ipending & (SINT_NET|SINT_CLOCK) & ~cpl);
+       ipending &= pcpl;
+       cpl = pcpl;     /* Don't use splx... we are here already! */
+       asm volatile("mtmsr %0" :: "r"(emsr));
+       processing = 0;
+}
+
+u_int
+openpic_read(reg)
+       int reg;
+{
+       char *addr = (void *)(openpic_base + reg);
+
+       return in32rb(addr);
+}
+
+void
+openpic_write(reg, val)
+       int reg;
+       u_int val;
+{
+       char *addr = (void *)(openpic_base + reg);
+
+       out32rb(addr, val);
+}
+
+void
+openpic_enable_irq_mask(irq_mask)
+int irq_mask;
+{
+       int irq;
+       for ( irq = 0; irq <= virq_max; irq++) {
+               if (irq_mask & (1 << irq)) {
+                       openpic_enable_irq(hwirq[irq]);
+               } else {
+                       openpic_disable_irq(hwirq[irq]);
+               }
+       }
+}
+void
+openpic_enable_irq(irq)
+       int irq;
+{
+       u_int x;
+
+       x = openpic_read(OPENPIC_SRC_VECTOR(irq));
+       x &= ~OPENPIC_IMASK;
+       openpic_write(OPENPIC_SRC_VECTOR(irq), x);
+}
+
+void
+openpic_disable_irq(irq)
+       int irq;
+{
+       u_int x;
+
+       x = openpic_read(OPENPIC_SRC_VECTOR(irq));
+       x |= OPENPIC_IMASK;
+       openpic_write(OPENPIC_SRC_VECTOR(irq), x);
+}
+
+void
+openpic_set_priority(cpu, pri)
+        int cpu, pri;
+{
+       u_int x;
+
+       x = openpic_read(OPENPIC_CPU_PRIORITY(cpu));
+       x &= ~OPENPIC_CPU_PRIORITY_MASK;
+       x |= pri;
+       openpic_write(OPENPIC_CPU_PRIORITY(cpu), x);
+}
+
+int
+openpic_read_irq(cpu)
+       int cpu;
+{
+       return openpic_read(OPENPIC_IACK(cpu)) & OPENPIC_VECTOR_MASK;
+}
+
+void
+openpic_eoi(cpu)
+        int cpu;
+{
+        openpic_write(OPENPIC_EOI(cpu), 0);
+        openpic_read(OPENPIC_EOI(cpu));
+}
+
+void
+ext_intr_openpic()
+{
+       int irq, realirq;
+       int r_imen;
+       int pcpl;
+       struct intrhand *ih;
+
+       pcpl = splhigh();       /* Turn off all */
+
+       realirq = openpic_read_irq(0);
+
+       while (realirq != 255) {
+               irq = virq[realirq];
+
+               /* XXX check range */
+
+               r_imen = 1 << irq;
+
+               if ((pcpl & r_imen) != 0) {
+                       ipending |= r_imen;     /* Masked! Mark this as pending */
+                       openpic_disable_irq(realirq);
+               } else {
+                       ih = intrhand[irq];
+                       while (ih) {
+                               (*ih->ih_fun)(ih->ih_arg);
+                               ih = ih->ih_next;
+                       }
+
+#ifdef UVM
+                       uvmexp.intrs++;
+#else
+#endif
+                       evirq[realirq].ev_count++;
+               }
+
+               openpic_eoi(0);
+
+               realirq = openpic_read_irq(0);
+       }
+
+       splx(pcpl);     /* Process pendings. */
+}
+void
+openpic_init()
+{
+        int irq;
+        u_int x;
+
+        /* disable all interrupts */
+        for (irq = 0; irq < ICU_LEN; irq++)
+                openpic_write(OPENPIC_SRC_VECTOR(irq), OPENPIC_IMASK);
+        openpic_set_priority(0, 15);
+
+        /* we don't need 8259 pass through mode */
+        x = openpic_read(OPENPIC_CONFIG);
+        x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE;
+        openpic_write(OPENPIC_CONFIG, x);
+
+        /* send all interrupts to cpu 0 */
+        for (irq = 0; irq < ICU_LEN; irq++)
+                openpic_write(OPENPIC_IDEST(irq), 1 << 0);
+        for (irq = 0; irq < ICU_LEN; irq++) {
+                x = irq;
+                x |= OPENPIC_IMASK;
+                x |= OPENPIC_POLARITY_POSITIVE;
+                x |= OPENPIC_SENSE_LEVEL;
+                x |= 8 << OPENPIC_PRIORITY_SHIFT;
+                openpic_write(OPENPIC_SRC_VECTOR(irq), x);
+        }
+
+        /* XXX set spurious intr vector */
+
+        openpic_set_priority(0, 0);
+
+        /* clear all pending interrunts */
+        for (irq = 0; irq < ICU_LEN; irq++) {
+                openpic_read_irq(0);
+                openpic_eoi(0);
+        }
+
+        for (irq = 0; irq < ICU_LEN; irq++)
+                openpic_disable_irq(irq);
+
+        install_extint(ext_intr_openpic);
+}
index 6d6b72c..fe3f09b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: wdc_obio.c,v 1.2 1999/11/23 01:25:29 rahnds Exp $     */
+/*     $OpenBSD: wdc_obio.c,v 1.3 2000/03/20 07:26:51 rahnds Exp $     */
 /*     $NetBSD: wdc_obio.c,v 1.4 1999/06/14 08:53:06 tsubai Exp $      */
 
 /*-
@@ -119,14 +119,14 @@ wdc_obio_probe(parent, match, aux)
 
        /* XXX should not use name */
        if (strcmp(ca->ca_name, "ATA") == 0 ||
-           strcmp(ca->ca_name, "ata") == 0 ||
-           strcmp(ca->ca_name, "ata0") == 0 ||
+           strncmp(ca->ca_name, "ata", 3) == 0 ||
            strcmp(ca->ca_name, "ide") == 0)
                return 1;
 
        bzero(compat, sizeof(compat));
        OF_getprop(ca->ca_node, "compatible", compat, sizeof(compat));
-       if (strcmp(compat, "heathrow-ata") == 0)
+       if (strcmp(compat, "heathrow-ata") == 0 ||
+           strcmp(compat, "keylargo-ata") == 0)
                return 1;
 
        return 0;
@@ -186,7 +186,8 @@ printf ("wdc_obio cmd_ioh %x ctl_ioh %x\n", chp->cmd_ioh, chp->ctl_ioh);
        chp->data32iot = chp->cmd_iot;
        chp->data32ioh = chp->cmd_ioh;
 
-       mac_intr_establish(intr, IST_LEVEL, IPL_BIO, wdcintr, chp);
+       mac_intr_establish(parent, intr, IST_LEVEL, IPL_BIO, wdcintr, chp,
+               "wdc_obio");
 
        if (use_dma) {
                sc->sc_dmacmd = dbdma_alloc(sizeof(dbdma_command_t) * 20);