intr.h revision 1.14
1/* $OpenBSD: intr.h,v 1.14 2002/04/29 07:35:18 miod Exp $ */ 2/* $NetBSD: intr.h,v 1.5 1996/05/13 06:11:28 mycroft Exp $ */ 3 4/* 5 * Copyright (c) 1996 Charles M. Hannum. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Charles M. Hannum. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#ifndef _I386_INTR_H_ 34#define _I386_INTR_H_ 35 36/* 37 * Intel APICs (advanced programmable interrupt controllers) have 38 * bytesized priority registers where the upper nibble is the actual 39 * interrupt priority level (a.k.a. IPL). Interrupt vectors are 40 * closely tied to these levels as interrupts whose vectors' upper 41 * nibble is lower than or equal to the current level are blocked. 42 * Not all 256 possible vectors are available for interrupts in 43 * APIC systems, only 44 * 45 * For systems where instead the older ICU (interrupt controlling 46 * unit, a.k.a. PIC or 82C59) is used, the IPL is not directly useful, 47 * since the interrupt blocking is handled via interrupt masks instead 48 * of levels. However the IPL is easily used as an offset into arrays 49 * of masks. 50 */ 51#define IPLSHIFT 4 /* The upper nibble of vectors is the IPL. */ 52#define NIPL 16 /* Four bits of information gives as much. */ 53#define IPL(level) ((level) >> IPLSHIFT) /* Extract the IPL. */ 54/* XXX Maybe this IDTVECOFF definition should be elsewhere? */ 55#define IDTVECOFF 0x20 /* The lower 32 IDT vectors are reserved. */ 56 57/* 58 * This macro is only defined for 0 <= x < 14, i.e. there are fourteen 59 * distinct priority levels available for interrupts. 60 */ 61#define MAKEIPL(priority) (IDTVECOFF + ((priority) << IPLSHIFT)) 62 63/* 64 * Interrupt priority levels. 65 * XXX We are somewhat sloppy about what we mean by IPLs, sometimes 66 * XXX we refer to the eight-bit value suitable for storing into APICs' 67 * XXX priority registers, other times about the four-bit entity found 68 * XXX in the former values' upper nibble, which can be used as offsets 69 * XXX in various arrays of our implementation. We are hoping that 70 * XXX the context will provide enough information to not make this 71 * XXX sloppy naming a real problem. 72 */ 73#define IPL_NONE 0 /* nothing */ 74#define IPL_SOFTCLOCK MAKEIPL(0) /* timeouts */ 75#define IPL_SOFTNET MAKEIPL(1) /* protocol stacks */ 76#define IPL_BIO MAKEIPL(2) /* block I/O */ 77#define IPL_NET MAKEIPL(3) /* network */ 78#define IPL_SOFTTTY MAKEIPL(4) /* delayed terminal handling */ 79#define IPL_TTY MAKEIPL(5) /* terminal */ 80#define IPL_IMP MAKEIPL(6) /* memory allocation */ 81#define IPL_AUDIO MAKEIPL(7) /* audio */ 82#define IPL_CLOCK MAKEIPL(8) /* clock */ 83#define IPL_HIGH MAKEIPL(9) /* everything */ 84 85/* Interrupt sharing types. */ 86#define IST_NONE 0 /* none */ 87#define IST_PULSE 1 /* pulsed */ 88#define IST_EDGE 2 /* edge-triggered */ 89#define IST_LEVEL 3 /* level-triggered */ 90 91/* Soft interrupt masks. */ 92#define SIR_CLOCK 31 93#define SIR_NET 30 94#define SIR_TTY 29 95 96#ifndef _LOCORE 97 98volatile int cpl; /* Current interrupt priority level. */ 99volatile int ipending; /* Interrupts pending. */ 100volatile int astpending;/* Asynchronous software traps (softints) pending. */ 101int imask[NIPL]; /* Bitmasks telling what interrupts are blocked. */ 102int iunmask[NIPL]; /* Bitmasks telling what interrupts are accepted. */ 103 104#define IMASK(level) imask[IPL(level)] 105#define IUNMASK(level) iunmask[IPL(level)] 106 107extern void Xspllower(void); 108 109static __inline int splraise(int); 110static __inline int spllower(int); 111#define SPLX_DECL void splx(int); 112static __inline void softintr(int); 113 114/* SPL asserts */ 115#define splassert(wantipl) /* nothing */ 116 117/* 118 * Raise current interrupt priority level, and return the old one. 119 */ 120static __inline int 121splraise(ncpl) 122 int ncpl; 123{ 124 int ocpl = cpl; 125 126 if (ncpl > ocpl) 127 cpl = ncpl; 128 __asm __volatile(""); 129 return (ocpl); 130} 131 132/* 133 * Restore an old interrupt priority level. If any thereby unmasked 134 * interrupts are pending, call Xspllower() to process them. 135 */ 136#define SPLX_BODY \ 137void \ 138splx(ncpl) \ 139 int ncpl; \ 140{ \ 141 __asm __volatile(""); \ 142 cpl = ncpl; \ 143 if (ipending & IUNMASK(ncpl)) \ 144 Xspllower(); \ 145} 146 147/* If SMALL_KERNEL make splx out of line, otherwise inline it. */ 148#ifdef SMALL_KERNEL 149#define SPLX_INLINED_BODY 150#define SPLX_OUTLINED_BODY SPLX_BODY 151SPLX_DECL 152#else 153#define SPLX_INLINED_BODY static __inline SPLX_BODY 154#define SPLX_OUTLINED_BODY 155static __inline SPLX_DECL 156#endif 157 158SPLX_INLINED_BODY 159 160/* 161 * Same as splx(), but we return the old value of spl, for the 162 * benefit of some splsoftclock() callers. 163 */ 164static __inline int 165spllower(ncpl) 166 int ncpl; 167{ 168 int ocpl = cpl; 169 170 splx(ncpl); 171 return (ocpl); 172} 173 174/* 175 * Hardware interrupt masks 176 */ 177#define splbio() splraise(IPL_BIO) 178#define splnet() splraise(IPL_NET) 179#define spltty() splraise(IPL_TTY) 180#define splaudio() splraise(IPL_AUDIO) 181#define splclock() splraise(IPL_CLOCK) 182#define splstatclock() splhigh() 183 184/* 185 * Software interrupt masks 186 * 187 * NOTE: spllowersoftclock() is used by hardclock() to lower the priority from 188 * clock to softclock before it calls softclock(). 189 */ 190#define spllowersoftclock() spllower(IPL_SOFTCLOCK) 191#define splsoftclock() splraise(IPL_SOFTCLOCK) 192#define splsoftnet() splraise(IPL_SOFTNET) 193#define splsofttty() splraise(IPL_SOFTTTY) 194 195/* 196 * Miscellaneous 197 */ 198#define splimp() splraise(IPL_IMP) 199#define splvm() splraise(IPL_IMP) 200#define splhigh() splraise(IPL_HIGH) 201#define spl0() spllower(IPL_NONE) 202 203/* 204 * Software interrupt registration 205 * 206 * We hand-code this to ensure that it's atomic. 207 */ 208static __inline void 209softintr(mask) 210 int mask; 211{ 212 __asm __volatile("orl %0,_ipending" : : "ir" (mask)); 213} 214 215#define setsoftast() (astpending = 1) 216#define setsoftclock() softintr(1 << SIR_CLOCK) 217#define setsoftnet() softintr(1 << SIR_NET) 218#define setsofttty() softintr(1 << SIR_TTY) 219 220#endif /* !_LOCORE */ 221 222#endif /* !_I386_INTR_H_ */ 223