/*- * Copyright (c) 2006 Fill this file and put your name here * Copyright (c) 2002-2004 Juli Mallett * All rights reserved. * * 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, * without modification, immediately at the beginning of the file. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct mips_intrhand mips_intr_handlers[XLR_MAX_INTR]; static void mips_mask_hard_irq(void *source) { uintptr_t irq = (uintptr_t)source; write_c0_eimr64(read_c0_eimr64() & ~(1ULL< XLR_MAX_INTR) panic("%s called for unknown hard intr %d", __func__, intr); /* FIXME locking - not needed now, because we do this only on startup from CPU0 */ mih = &mips_intr_handlers[irq]; mih->cntp = &intrcnt[irq]; ie = mih->mih_event; if (ie == NULL) { errcode = intr_event_create(&event, (void *)(uintptr_t)irq, 0, irq, mips_mask_hard_irq, mips_unmask_hard_irq, NULL, NULL, "hard intr%d:", irq); if (errcode) { printf("Could not create event for intr %d\n", irq); return; } } intr_event_add_handler(event, name, filt, handler, arg, intr_priority(flags), flags, cookiep); mih->mih_event = ie; mips_unmask_hard_irq((void*)(uintptr_t)irq); } void cpu_establish_softintr(const char *name, driver_filter_t *filt, void (*handler)(void*), void *arg, int irq, int flags, void **cookiep) { /* we don't separate them into soft/hard like other mips */ cpu_establish_hardintr(name, filt, handler, arg, intr, flags, cookiep); } void cpu_intr(struct trapframe *tf) { struct mips_intrhand *mih; struct intr_handler *ih; struct intr_event *ie; register_t eirr; int i, thread, error; critical_enter(); eirr = read_c0_eirr64(); if (eirr == 0) { critical_exit(); return; } /* No need to clear the EIRR here. the handler is gonna * write to compare which clears eirr also */ if (eirr & (1 << IRQ_TIMER)) { count_compare_clockhandler(tf); critical_exit(); return; } /* FIXME sched pin >? LOCK>? */ for(i = sizeof(eirr)*8 - 1; i>=0; i--) { if ((eirr & 1ULL<cntp, 1); ie = mih->mih_event; write_c0_eirr64(1ULL << i); if (!ie || TAILQ_EMPTY(&ie->ie_handlers)) { printf("stray interrupt %d\n", i); continue; } if (intr_event_handle(ie, tf) != 0) { printf("stray %s interrupt %d\n", hard ? "hard" : "soft", i); } } critical_exit(); }