summaryrefslogtreecommitdiff
path: root/sys/arch/socppc
diff options
context:
space:
mode:
authorMats O Jansson <maja@cvs.openbsd.org>2008-12-04 16:02:21 +0000
committerMats O Jansson <maja@cvs.openbsd.org>2008-12-04 16:02:21 +0000
commita0673e9ab5e9bf66704b60b8c36a5e83a3e91624 (patch)
treeeef991686cfbead476106ba1cb3aa9dcec184585 /sys/arch/socppc
parent1820d03152ff2b43ec6a9c80ca7c1e168137b675 (diff)
Revert ppc intr stuff. Make socppc compile again. -moj
Diffstat (limited to 'sys/arch/socppc')
-rw-r--r--sys/arch/socppc/dev/ipic.c209
-rw-r--r--sys/arch/socppc/socppc/machdep.c60
2 files changed, 130 insertions, 139 deletions
diff --git a/sys/arch/socppc/dev/ipic.c b/sys/arch/socppc/dev/ipic.c
index a43ede41f04..f48770b9efb 100644
--- a/sys/arch/socppc/dev/ipic.c
+++ b/sys/arch/socppc/dev/ipic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipic.c,v 1.5 2008/10/12 11:50:18 kettenis Exp $ */
+/* $OpenBSD: ipic.c,v 1.6 2008/12/04 16:02:20 maja Exp $ */
/*
* Copyright (c) 2008 Mark Kettenis
@@ -63,7 +63,7 @@ struct ipic_softc {
};
uint32_t ipic_imask;
-struct intrq ipic_handler[IPIC_NVEC];
+struct intrhand *ipic_intrhand[IPIC_NVEC];
struct ipic_softc *ipic_sc;
int ipic_match(struct device *, void *, void *);
@@ -82,17 +82,9 @@ void ipic_write(struct ipic_softc *, bus_addr_t, uint32_t);
uint32_t ipic_simsr_h(int);
uint32_t ipic_simsr_l(int);
uint32_t ipic_semsr(int);
-void ipic_calc_masks(void);
void ext_intr(void);
-
-ppc_splraise_t ipic_splraise;
-ppc_spllower_t ipic_spllower;
-ppc_splx_t ipic_splx;
-
-void ipic_setipl(int);
-void ipic_do_pending(int);
-
+void ipic_do_pending_int(void);
int
ipic_match(struct device *parent, void *cfdata, void *aux)
@@ -105,8 +97,6 @@ ipic_attach(struct device *parent, struct device *self, void *aux)
{
struct ipic_softc *sc = (void *)self;
struct obio_attach_args *oa = aux;
- struct intrq *iq;
- int i;
sc->sc_iot = oa->oa_iot;
if (bus_space_map(sc->sc_iot, oa->oa_offset, 128, 0, &sc->sc_ioh)) {
@@ -115,17 +105,6 @@ ipic_attach(struct device *parent, struct device *self, void *aux)
}
ipic_sc = sc;
-
- for (i = 0; i < IPIC_NVEC; i++) {
- iq = &ipic_handler[i];
- TAILQ_INIT(&iq->iq_list);
- }
-
- ppc_smask_init();
- ppc_intr_func.raise = ipic_splraise;
- ppc_intr_func.lower = ipic_spllower;
- ppc_intr_func.x = ipic_splx;
-
printf("\n");
}
@@ -197,10 +176,32 @@ ipic_semsr(int ivec)
return 0;
}
-void
-ipic_calc_masks(void)
+static void
+intr_calculatemasks(void)
{
struct ipic_softc *sc = ipic_sc;
+ int level;
+
+ for (level = IPL_NONE; level < IPL_NUM; level++)
+ imask[level] = SINT_MASK | (1 << level);
+
+ /*
+ * There are tty, network and disk drivers that use free() at interrupt
+ * time, so vm > (tty | net | bio).
+ *
+ * Enforce a hierarchy that gives slow devices a better chance at not
+ * dropping data.
+ */
+ imask[IPL_NET] |= imask[IPL_BIO];
+ imask[IPL_TTY] |= imask[IPL_NET];
+ imask[IPL_VM] |= imask[IPL_TTY];
+ imask[IPL_CLOCK] |= imask[IPL_VM] | SPL_CLOCK;
+
+ /*
+ * These are pseudo-levels.
+ */
+ imask[IPL_NONE] = 0x00000000;
+ imask[IPL_HIGH] = 0xffffffff;
sc->sc_simsr_h[IPL_NET] |= sc->sc_simsr_h[IPL_BIO];
sc->sc_simsr_h[IPL_TTY] |= sc->sc_simsr_h[IPL_NET];
@@ -226,40 +227,31 @@ intr_establish(int ivec, int type, int level,
int (*ih_fun)(void *), void *ih_arg, const char *name)
{
struct ipic_softc *sc = ipic_sc;
- struct intrhand *ih;
- struct intrq *iq;
+ struct intrhand **p, *q, *ih;
uint32_t mask;
- int s;
ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
if (ih == NULL)
panic("%s: malloc failed", __func__);
- iq = &ipic_handler[ivec];
if (ivec < 0 || ivec >= IPIC_NVEC)
panic("%s: invalid vector %d", __func__, ivec);
+ for (p = &ipic_intrhand[ivec]; (q = *p) != NULL; p = &q->ih_next)
+ ;
+
sc->sc_simsr_h[level] |= ipic_simsr_h(ivec);
sc->sc_simsr_l[level] |= ipic_simsr_l(ivec);
sc->sc_semsr[level] |= ipic_semsr(ivec);
+ intr_calculatemasks();
ih->ih_fun = ih_fun;
ih->ih_arg = ih_arg;
+ ih->ih_next = NULL;
ih->ih_level = level;
ih->ih_irq = ivec;
-
- evcount_attach(&ih->ih_count, name, (void *)&ih->ih_irq,
- &evcount_intr);
-
- /*
- * Append handler to end of list
- */
- s = ppc_intr_disable();
-
- TAILQ_INSERT_TAIL(&iq->iq_list, ih, ih_list);
- ipic_calc_masks();
-
- ppc_intr_enable(s);
+ evcount_attach(&ih->ih_count, name, NULL, &evcount_intr);
+ *p = ih;
/* Unmask the interrupt. */
mask = ipic_read(sc, IPIC_SIMSR_H);
@@ -281,19 +273,31 @@ ext_intr(void)
struct cpu_info *ci = curcpu();
struct ipic_softc *sc = ipic_sc;
struct intrhand *ih;
- struct intrq *iq;
- int pcpl;
+ uint32_t simsr_h, simsr_l, semsr;
+ int pcpl, ocpl;
int ivec;
pcpl = ci->ci_cpl;
ivec = ipic_read(sc, IPIC_SIVCR) & 0x7f;
- iq = &ipic_handler[ivec];
- TAILQ_FOREACH(ih, &iq->iq_list, ih_list) {
- if (ih->ih_level < pcpl)
- continue;
+ simsr_h = ipic_read(sc, IPIC_SIMSR_H);
+ simsr_l = ipic_read(sc, IPIC_SIMSR_L);
+ semsr = ipic_read(sc, IPIC_SEMSR);
+ ipic_write(sc, IPIC_SIMSR_H, simsr_h & ~ipic_simsr_h(ivec));
+ ipic_write(sc, IPIC_SIMSR_L, simsr_l & ~ipic_simsr_l(ivec));
+ ipic_write(sc, IPIC_SEMSR, semsr & ~ipic_semsr(ivec));
+
+ ih = ipic_intrhand[ivec];
+ while (ih) {
+ if (ci->ci_cpl & (1 << ih->ih_level)) {
+ ci->ci_ipending |= (1 << ih->ih_level);
+ return;
+ }
- ipic_splraise(ih->ih_level);
+ ipic_write(sc, IPIC_SIMSR_H, sc->sc_simsr_h[ih->ih_level]);
+ ipic_write(sc, IPIC_SIMSR_L, sc->sc_simsr_l[ih->ih_level]);
+ ipic_write(sc, IPIC_SEMSR, sc->sc_semsr[ih->ih_level]);
+ ocpl = splraise(imask[ih->ih_level]);
ppc_intr_enable(1);
KERNEL_LOCK();
@@ -302,111 +306,40 @@ ext_intr(void)
KERNEL_UNLOCK();
ppc_intr_disable();
+ ci->ci_cpl = ocpl;
+ ih = ih->ih_next;
}
+ ipic_write(sc, IPIC_SIMSR_H, simsr_h);
+ ipic_write(sc, IPIC_SIMSR_L, simsr_l);
+ ipic_write(sc, IPIC_SEMSR, semsr);
splx(pcpl);
}
-int
-ipic_splraise(int newcpl)
-{
- struct cpu_info *ci = curcpu();
- int ocpl = ci->ci_cpl;
-
- if (ocpl > newcpl)
- newcpl = ocpl;
-
- ipic_setipl(newcpl);
-
- return (ocpl);
-}
-
-int
-ipic_spllower(int newcpl)
+static __inline int
+cntlzw(int x)
{
- struct cpu_info *ci = curcpu();
- int ocpl = ci->ci_cpl;
-
- ipic_splx(newcpl);
-
- return (ocpl);
-}
+ int a;
-void
-ipic_splx(int newcpl)
-{
- struct cpu_info *ci = curcpu();
+ __asm __volatile("cntlzw %0,%1" : "=r"(a) : "r"(x));
- ipic_setipl(newcpl);
- if (ci->ci_ipending & ppc_smask[newcpl])
- ipic_do_pending(newcpl);
+ return a;
}
void
-ipic_setipl(int ipl)
+ipic_do_pending_int(void)
{
struct cpu_info *ci = curcpu();
struct ipic_softc *sc = ipic_sc;
uint32_t mask;
- int s;
+ int level;
- s = ppc_intr_disable();
- ci->ci_cpl = ipl;
- mask = sc->sc_simsr_h[IPL_HIGH] & ~sc->sc_simsr_h[ipl];
+ ci->ci_ipending &= SINT_MASK;
+ level = cntlzw(31 - (ci->ci_cpl & ~(SPL_CLOCK|SINT_MASK)));
+ mask = sc->sc_simsr_h[IPL_HIGH] & ~sc->sc_simsr_h[level];
ipic_write(sc, IPIC_SIMSR_H, mask);
- mask = sc->sc_simsr_l[IPL_HIGH] & ~sc->sc_simsr_l[ipl];
+ mask = sc->sc_simsr_l[IPL_HIGH] & ~sc->sc_simsr_l[level];
ipic_write(sc, IPIC_SIMSR_L, mask);
- mask = sc->sc_semsr[IPL_HIGH] & ~sc->sc_semsr[ipl];
+ mask = sc->sc_semsr[IPL_HIGH] & ~sc->sc_semsr[level];
ipic_write(sc, IPIC_SEMSR, mask);
- ppc_intr_enable(s);
-}
-
-void
-ipic_do_pending(int pcpl)
-{
- struct cpu_info *ci = curcpu();
- int s;
-
- s = ppc_intr_disable();
- if (ci->ci_iactive & CI_IACTIVE_PROCESSING_SOFT) {
- ppc_intr_enable(s);
- return;
- }
-
- atomic_setbits_int(&ci->ci_iactive, CI_IACTIVE_PROCESSING_SOFT);
-
- do {
- if ((ci->ci_ipending & SI_TO_IRQBIT(SI_SOFTNET)) &&
- (pcpl < IPL_SOFTNET)) {
- extern int netisr;
- int pisr;
-
- ci->ci_ipending &= ~SI_TO_IRQBIT(SI_SOFTNET);
- ci->ci_cpl = IPL_SOFTNET;
- ppc_intr_enable(s);
- KERNEL_LOCK();
- while ((pisr = netisr) != 0) {
- atomic_clearbits_int(&netisr, pisr);
- softnet(pisr);
- }
- KERNEL_UNLOCK();
- ppc_intr_disable();
- continue;
- }
- if ((ci->ci_ipending & SI_TO_IRQBIT(SI_SOFTCLOCK)) &&
- (pcpl < IPL_SOFTCLOCK)) {
- ci->ci_ipending &= ~SI_TO_IRQBIT(SI_SOFTCLOCK);
- ci->ci_cpl = IPL_SOFTCLOCK;
- ppc_intr_enable(s);
- KERNEL_LOCK();
- softclock();
- KERNEL_UNLOCK();
- ppc_intr_disable();
- continue;
- }
- } while (ci->ci_ipending & ppc_smask[pcpl]);
- ipic_setipl(pcpl); /* Don't use splx... we are here already! */
-
- atomic_clearbits_int(&ci->ci_iactive, CI_IACTIVE_PROCESSING_SOFT);
- ppc_intr_enable(s);
}
diff --git a/sys/arch/socppc/socppc/machdep.c b/sys/arch/socppc/socppc/machdep.c
index 42291ee77ef..ca0a96c6f55 100644
--- a/sys/arch/socppc/socppc/machdep.c
+++ b/sys/arch/socppc/socppc/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.6 2008/10/12 11:50:19 kettenis Exp $ */
+/* $OpenBSD: machdep.c,v 1.7 2008/12/04 16:02:20 maja Exp $ */
/* $NetBSD: machdep.c,v 1.4 1996/10/16 19:33:11 ws Exp $ */
/*
@@ -1094,9 +1094,67 @@ boot(int howto)
while(1) /* forever */;
}
+extern void ipic_do_pending_int(void);
+
void
do_pending_int(void)
{
+ struct cpu_info *ci = curcpu();
+ int pcpl, s;
+
+ if (ci->ci_iactive)
+ return;
+
+ ci->ci_iactive = 1;
+ s = ppc_intr_disable();
+ pcpl = ci->ci_cpl;
+
+ ipic_do_pending_int();
+
+ do {
+ if((ci->ci_ipending & SINT_CLOCK) & ~pcpl) {
+ ci->ci_ipending &= ~SINT_CLOCK;
+ ci->ci_cpl = SINT_CLOCK|SINT_NET|SINT_TTY;
+ ppc_intr_enable(1);
+ KERNEL_LOCK();
+ softclock();
+ KERNEL_UNLOCK();
+ ppc_intr_disable();
+ continue;
+ }
+ if((ci->ci_ipending & SINT_NET) & ~pcpl) {
+ extern int netisr;
+ int pisr;
+
+ ci->ci_ipending &= ~SINT_NET;
+ ci->ci_cpl = SINT_NET|SINT_TTY;
+ while ((pisr = netisr) != 0) {
+ atomic_clearbits_int(&netisr, pisr);
+ ppc_intr_enable(1);
+ KERNEL_LOCK();
+ softnet(pisr);
+ KERNEL_UNLOCK();
+ ppc_intr_disable();
+ }
+ continue;
+ }
+#if 0
+ if((ci->ci_ipending & SINT_TTY) & ~pcpl) {
+ ci->ci_ipending &= ~SINT_TTY;
+ ci->ci_cpl = SINT_TTY;
+ ppc_intr_enable(1);
+ KERNEL_LOCK();
+ softtty();
+ KERNEL_UNLOCK();
+ ppc_intr_disable();
+ continue;
+ }
+#endif
+ } while ((ci->ci_ipending & SINT_MASK) & ~pcpl);
+ ci->ci_cpl = pcpl; /* Don't use splx... we are here already! */
+
+ ci->ci_iactive = 0;
+ ppc_intr_enable(s);
}
/*