diff options
author | Dale S. Rahn <rahnds@cvs.openbsd.org> | 2000-03-20 07:26:52 +0000 |
---|---|---|
committer | Dale S. Rahn <rahnds@cvs.openbsd.org> | 2000-03-20 07:26:52 +0000 |
commit | ef912cc6b6727d00d870e34cbb93dd81818ad5ee (patch) | |
tree | 08cc2cce860864839f83f7e566fe482a4323dc4e /sys/arch/powerpc | |
parent | 1f1dff1081e7f0bbf06664a62f35190afdc3a7a4 (diff) |
Interrupt code changed from called routines, to initialized driver.
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.
Diffstat (limited to 'sys/arch/powerpc')
-rw-r--r-- | sys/arch/powerpc/mac/if_bm.c | 11 | ||||
-rw-r--r-- | sys/arch/powerpc/mac/macintr.c | 128 | ||||
-rw-r--r-- | sys/arch/powerpc/mac/openpic.c | 670 | ||||
-rw-r--r-- | sys/arch/powerpc/mac/wdc_obio.c | 11 |
4 files changed, 792 insertions, 28 deletions
diff --git a/sys/arch/powerpc/mac/if_bm.c b/sys/arch/powerpc/mac/if_bm.c index 2e38fe74fe3..1cbcf4cff4d 100644 --- a/sys/arch/powerpc/mac/if_bm.c +++ b/sys/arch/powerpc/mac/if_bm.c @@ -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; diff --git a/sys/arch/powerpc/mac/macintr.c b/sys/arch/powerpc/mac/macintr.c index cbaec1a9fe7..c729d2b8b77 100644 --- a/sys/arch/powerpc/mac/macintr.c +++ b/sys/arch/powerpc/mac/macintr.c @@ -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 @@ -39,18 +39,15 @@ * * @(#)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 index 00000000000..0b768cc0523 --- /dev/null +++ b/sys/arch/powerpc/mac/openpic.c @@ -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); +} diff --git a/sys/arch/powerpc/mac/wdc_obio.c b/sys/arch/powerpc/mac/wdc_obio.c index 6d6b72c2185..fe3f09bb2dd 100644 --- a/sys/arch/powerpc/mac/wdc_obio.c +++ b/sys/arch/powerpc/mac/wdc_obio.c @@ -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); |