1 /* $NetBSD: interrupt.c,v 1.1 2001/03/30 23:21:30 wdk Exp $ */ 2 3 /* 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Wayne Knowles 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/param.h> 40 #include <sys/malloc.h> 41 42 #include <uvm/uvm_extern.h> 43 44 #include <net/netisr.h> /* Legacy softnet support */ 45 46 #include <machine/intr.h> 47 #include <machine/sysconf.h> 48 49 struct mipsco_intr softintr_tab[IPL_NSOFT]; 50 51 /* XXX For legacy software interrupts. */ 52 struct mipsco_intrhand *softnet_intrhand; 53 54 u_int32_t ssir; 55 56 /* 57 * softintr_init: 58 * 59 * Initialize the software interrupt system. 60 */ 61 void 62 softintr_init() 63 { 64 static const char *softintr_names[] = IPL_SOFTNAMES; 65 struct mipsco_intr *sip; 66 int i; 67 68 for (i = 0; i < IPL_NSOFT; i++) { 69 sip = &softintr_tab[i]; 70 sip->intr_ipl = i; 71 LIST_INIT(&sip->intr_q); 72 evcnt_attach_dynamic(&sip->ih_evcnt, EVCNT_TYPE_INTR, 73 NULL, "soft", softintr_names[i]); 74 } 75 76 /* XXX Establish legacy software interrupt handlers. */ 77 softnet_intrhand = softintr_establish(IPL_SOFTNET, 78 (void (*)(void *))netintr, NULL); 79 80 KASSERT(softnet_intrhand != NULL); 81 } 82 83 /* 84 * softintr_dispatch: 85 * 86 * Process pending software interrupts. 87 * 88 * Called at splsoft() 89 */ 90 void 91 softintr_dispatch() 92 { 93 struct mipsco_intr *sip; 94 struct mipsco_intrhand *sih; 95 u_int32_t n, i, s; 96 97 s = splhigh(); 98 n = ssir; ssir = 0; 99 splx(s); 100 sip = softintr_tab; 101 for (i = 0; i < IPL_NSOFT; sip++, i++) { 102 if ((n & (1 << i)) == 0) 103 continue; 104 sip->ih_evcnt.ev_count++; 105 106 LIST_FOREACH(sih, &sip->intr_q, ih_q) { 107 if (sih->ih_pending) { 108 uvmexp.softs++; 109 sih->ih_pending = 0; 110 (*sih->ih_fun)(sih->ih_arg); 111 } 112 } 113 } 114 } 115 116 /* 117 * softintr_establish: [interface] 118 * 119 * Register a software interrupt handler. 120 */ 121 void * 122 softintr_establish(int ipl, void (*func)(void *), void *arg) 123 { 124 struct mipsco_intr *sip; 125 struct mipsco_intrhand *sih; 126 int s; 127 128 if (__predict_false(ipl >= IPL_NSOFT || ipl < 0)) 129 panic("softintr_establish"); 130 131 sip = &softintr_tab[ipl]; 132 133 sih = malloc(sizeof(*sih), M_DEVBUF, M_NOWAIT); 134 if (__predict_true(sih != NULL)) { 135 sih->ih_fun = (void *)func; 136 sih->ih_arg = arg; 137 sih->ih_intrhead = sip; 138 sih->ih_pending = 0; 139 140 s = splsoft(); 141 LIST_INSERT_HEAD(&sip->intr_q, sih, ih_q); 142 splx(s); 143 } 144 return (sih); 145 } 146 147 /* 148 * softintr_disestablish: [interface] 149 * 150 * Unregister a software interrupt handler. 151 */ 152 void 153 softintr_disestablish(void *arg) 154 { 155 struct mipsco_intrhand *ih = arg; 156 int s; 157 158 s = splsoft(); 159 LIST_REMOVE(ih, ih_q); 160 splx(s); 161 free(ih, M_DEVBUF); 162 } 163 164 void 165 cpu_intr(status, cause, pc, ipending) 166 u_int32_t status; 167 u_int32_t cause; 168 u_int32_t pc; 169 u_int32_t ipending; 170 { 171 uvmexp.intrs++; 172 173 /* device interrupts */ 174 (*platform.iointr)(status, cause, pc, ipending); 175 176 /* software simulated interrupt */ 177 if ((ipending & MIPS_SOFT_INT_MASK_1) 178 || (ssir && (status & MIPS_SOFT_INT_MASK_1))) { 179 _clrsoftintr(MIPS_SOFT_INT_MASK_1); 180 softintr_dispatch(); 181 } 182 } 183