diff options
Diffstat (limited to 'sys/arch/sgi/localbus/macebus.c')
-rw-r--r-- | sys/arch/sgi/localbus/macebus.c | 74 |
1 files changed, 48 insertions, 26 deletions
diff --git a/sys/arch/sgi/localbus/macebus.c b/sys/arch/sgi/localbus/macebus.c index b4686226f0e..2510a7eb819 100644 --- a/sys/arch/sgi/localbus/macebus.c +++ b/sys/arch/sgi/localbus/macebus.c @@ -1,4 +1,4 @@ -/* $OpenBSD: macebus.c,v 1.9 2004/09/24 14:22:49 deraadt Exp $ */ +/* $OpenBSD: macebus.c,v 1.10 2004/09/27 19:20:49 pefo Exp $ */ /* * Copyright (c) 2000-2004 Opsycon AB (www.opsycon.se) @@ -64,7 +64,7 @@ void *macebus_intr_establish(void *, u_long, int, int, int (*)(void *), void *, char *); void macebus_intr_disestablish(void *, void *); void macebus_intr_makemasks(void); -void macebus_do_pending_int(void); +void macebus_do_pending_int(int); intrmask_t macebus_iointr(intrmask_t, struct trap_frame *); intrmask_t macebus_aux(intrmask_t, struct trap_frame *); @@ -73,8 +73,6 @@ long crime_ext_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof (long)]; int maceticks; /* Time tracker for special events */ -u_int64_t crimestat; - struct cfattach macebus_ca = { sizeof(struct device), macebusmatch, macebusattach }; @@ -597,31 +595,40 @@ macebus_intr_makemasks(void) } void -macebus_do_pending_int(void) +macebus_do_pending_int(int newcpl) { +#ifdef _USE_SILLY_OVERWORKED_HW_INT_PENDING_HANDLER_ struct intrhand *ih; int vector; - intrmask_t pcpl; intrmask_t hwpend; struct trap_frame cf; static volatile int processing; - /* Don't recurse... */ - if (processing) + /* Don't recurse... but change the mask */ + if (processing) { + cpl = newcpl; return; + } processing = 1; - /* XXX interrupt vulnerable when changing ipending */ - pcpl = splhigh(); /* Turn off all */ /* XXX Fake a trapframe for clock pendings... */ cf.pc = (int)&macebus_do_pending_int; cf.sr = 0; - cf.cpl = pcpl; + cf.cpl = cpl; + + /* Hard mask current cpl so we don't get any new pendings */ + hw_setintrmask(cpl); + + /* Get what interrupt we should process */ + hwpend = ipending & ~newcpl; + hwpend &= ~SINT_ALLMASK; + clr_ipending(hwpend); + + /* Enable all non pending non masked hardware interrupts */ + cpl = (cpl & SINT_ALLMASK) | (newcpl & ~SINT_ALLMASK) | hwpend; + hw_setintrmask(cpl); - hwpend = ipending & ~pcpl; /* Do now unmasked pendings */ - hwpend &= ~(SINT_ALLMASK); - ipending &= ~hwpend; while (hwpend) { vector = ffs(hwpend) - 1; hwpend &= ~(1L << vector); @@ -634,30 +641,44 @@ macebus_do_pending_int(void) ih = ih->ih_next; } } - if ((ipending & SINT_CLOCKMASK) & ~pcpl) { - ipending &= ~SINT_CLOCKMASK; + + /* Enable all processed pending hardware interrupts */ + cpl &= ~hwpend; + hw_setintrmask(cpl); + + if ((ipending & SINT_CLOCKMASK) & ~newcpl) { + clr_ipending(SINT_CLOCKMASK); softclock(); } - if ((ipending & SINT_NETMASK) & ~pcpl) { + if ((ipending & SINT_NETMASK) & ~newcpl) { extern int netisr; int isr = netisr; netisr = 0; - ipending &= ~SINT_NETMASK; + clr_ipending(SINT_NETMASK); #define DONETISR(b,f) if (isr & (1 << (b))) f(); #include <net/netisr_dispatch.h> } #ifdef NOTYET - if ((ipending & SINT_TTYMASK) & ~pcpl) { - ipending &= ~SINT_TTYMASK; + if ((ipending & SINT_TTYMASK) & ~newcpl) { + clr_ipending(SINT_TTYMASK); compoll(NULL); } #endif - cpl = pcpl; /* Don't use splx... we are here already! */ - hw_setintrmask(pcpl); + /* Update masks to new cpl. Order highly important! */ + cpl = newcpl; + hw_setintrmask(newcpl); processing = 0; +#else + /* Update masks to new cpl. Order highly important! */ + cpl = newcpl; + hw_setintrmask(newcpl); + /* If we still have softints pending trigg processing */ + if (ipending & SINT_ALLMASK & ~cpl) + setsoftintr0(); +#endif } /* @@ -673,22 +694,23 @@ macebus_iointr(intrmask_t hwpend, struct trap_frame *cf) u_int64_t intstat, isastat, mask; intstat = bus_space_read_8(&crimebus_tag, crime_h, CRIME_INT_STAT); -crimestat=intstat; - intstat &= 0x0000ffff; + intstat &= 0xffff; + isastat = bus_space_read_8(&macebus_tag, mace_h, MACE_ISA_INT_STAT); catched = 0; /* Mask off masked interrupts and save them as pending */ if (intstat & cf->cpl) { - ipending |= intstat & cf->cpl; + set_ipending(intstat & cf->cpl); mask = bus_space_read_8(&crimebus_tag, crime_h, CRIME_INT_MASK); mask &= ~ipending; bus_space_write_8(&crimebus_tag, crime_h, CRIME_INT_MASK, mask); catched++; } - /* Scan the first 16 for now */ + /* Scan all unmasked. Scan the first 16 for now */ pending = intstat & ~cf->cpl; + clr_ipending(pending); for (v = 0, vm = 1; pending != 0 && v < 16 ; v++, vm <<= 1) { if (pending & vm) { |