intr.c revision 166901
1129198Scognet/* $NetBSD: intr.c,v 1.12 2003/07/15 00:24:41 lukem Exp $ */ 2129198Scognet 3139735Simp/*- 4129198Scognet * Copyright (c) 2004 Olivier Houchard. 5129198Scognet * Copyright (c) 1994-1998 Mark Brinicombe. 6129198Scognet * All rights reserved. 7129198Scognet * 8129198Scognet * Redistribution and use in source and binary forms, with or without 9129198Scognet * modification, are permitted provided that the following conditions 10129198Scognet * are met: 11129198Scognet * 1. Redistributions of source code must retain the above copyright 12129198Scognet * notice, this list of conditions and the following disclaimer. 13129198Scognet * 2. Redistributions in binary form must reproduce the above copyright 14129198Scognet * notice, this list of conditions and the following disclaimer in the 15129198Scognet * documentation and/or other materials provided with the distribution. 16129198Scognet * 3. All advertising materials mentioning features or use of this software 17129198Scognet * must display the following acknowledgement: 18129198Scognet * This product includes software developed by Mark Brinicombe 19129198Scognet * for the NetBSD Project. 20129198Scognet * 4. The name of the company nor the name of the author may be used to 21129198Scognet * endorse or promote products derived from this software without specific 22129198Scognet * prior written permission. 23129198Scognet * 24129198Scognet * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 25129198Scognet * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 26129198Scognet * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27129198Scognet * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 28129198Scognet * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29129198Scognet * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30129198Scognet * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31129198Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32129198Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33129198Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34129198Scognet * SUCH DAMAGE. 35129198Scognet * 36129198Scognet * Soft interrupt and other generic interrupt functions. 37129198Scognet */ 38129198Scognet 39129198Scognet#include <sys/cdefs.h> 40129198Scognet__FBSDID("$FreeBSD: head/sys/arm/arm/intr.c 166901 2007-02-23 12:19:07Z piso $"); 41129198Scognet#include <sys/param.h> 42129198Scognet#include <sys/systm.h> 43129198Scognet#include <sys/syslog.h> 44129198Scognet#include <sys/malloc.h> 45135650Scognet#include <sys/proc.h> 46129198Scognet#include <sys/bus.h> 47129198Scognet#include <sys/interrupt.h> 48129198Scognet#include <sys/conf.h> 49129198Scognet#include <machine/atomic.h> 50129198Scognet#include <machine/intr.h> 51129198Scognet#include <machine/cpu.h> 52129198Scognet 53151658Sjhbstatic struct intr_event *intr_events[NIRQ]; 54137629Scognetstatic int intrcnt_tab[NIRQ]; 55137629Scognetstatic int intrcnt_index = 0; 56137629Scognetstatic int last_printed = 0; 57129198Scognet 58153666Sjhbvoid arm_handler_execute(struct trapframe *, int); 59135650Scognet 60137629Scognetvoid 61166901Spisoarm_setup_irqhandler(const char *name, driver_filter_t *filt, 62166901Spiso void (*hand)(void*), void *arg, int irq, int flags, void **cookiep) 63129198Scognet{ 64151658Sjhb struct intr_event *event; 65129198Scognet int error; 66129198Scognet 67129198Scognet if (irq < 0 || irq >= NIRQ) 68129198Scognet return; 69151658Sjhb event = intr_events[irq]; 70151658Sjhb if (event == NULL) { 71151658Sjhb error = intr_event_create(&event, (void *)irq, 0, 72151658Sjhb (void (*)(void *))arm_unmask_irq, "intr%d:", irq); 73129198Scognet if (error) 74129198Scognet return; 75151658Sjhb intr_events[irq] = event; 76137629Scognet last_printed += 77137629Scognet snprintf(intrnames + last_printed, 78137629Scognet MAXCOMLEN + 1, 79137629Scognet "irq%d: %s", irq, name); 80137629Scognet last_printed++; 81137629Scognet intrcnt_tab[irq] = intrcnt_index; 82137629Scognet intrcnt_index++; 83137629Scognet 84129198Scognet } 85166901Spiso intr_event_add_handler(event, name, filt, hand, arg, 86151658Sjhb intr_priority(flags), flags, cookiep); 87129198Scognet} 88129198Scognet 89147166Scognetint 90147166Scognetarm_remove_irqhandler(void *cookie) 91147166Scognet{ 92151658Sjhb return (intr_event_remove_handler(cookie)); 93147166Scognet} 94147166Scognet 95129198Scognetvoid dosoftints(void); 96129198Scognetvoid 97129198Scognetdosoftints(void) 98129198Scognet{ 99129198Scognet} 100129198Scognet 101129198Scognetvoid 102153666Sjhbarm_handler_execute(struct trapframe *frame, int irqnb) 103129198Scognet{ 104151658Sjhb struct intr_event *event; 105151658Sjhb struct intr_handler *ih; 106135650Scognet struct thread *td = curthread; 107151658Sjhb int i, thread; 108129198Scognet 109164087Scognet PCPU_LAZY_INC(cnt.v_intr); 110135650Scognet td->td_intr_nesting_level++; 111147166Scognet while ((i = arm_get_next_irq()) != -1) { 112150869Scognet arm_mask_irq(i); 113137629Scognet intrcnt[intrcnt_tab[i]]++; 114151658Sjhb event = intr_events[i]; 115151658Sjhb if (!event || TAILQ_EMPTY(&event->ie_handlers)) 116135650Scognet continue; 117151658Sjhb 118151658Sjhb /* Execute fast handlers. */ 119151658Sjhb thread = 0; 120151658Sjhb TAILQ_FOREACH(ih, &event->ie_handlers, ih_next) { 121166901Spiso if (ih->ih_filter == NULL) 122151658Sjhb thread = 1; 123151658Sjhb else 124166901Spiso ih->ih_filter(ih->ih_argument ? 125135650Scognet ih->ih_argument : frame); 126151658Sjhb } 127151658Sjhb 128151658Sjhb /* Schedule thread if needed. */ 129151658Sjhb if (thread) 130151658Sjhb intr_event_schedule_thread(event); 131151658Sjhb else 132150869Scognet arm_unmask_irq(i); 133135650Scognet } 134135650Scognet td->td_intr_nesting_level--; 135129198Scognet} 136