1 /* $NetBSD: intr.h,v 1.9 2024/02/08 20:11:56 andvar Exp $ */ 2 3 /*- 4 * Copyright (c) 2023, 2024 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe. 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 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #ifndef _M68k_INTR_H_ 33 #define _M68k_INTR_H_ 34 35 #include <machine/psl.h> 36 37 #if (defined(_KERNEL) && !defined(_LOCORE)) || defined(_KMEMUSER) 38 typedef struct { 39 uint16_t _psl; /* physical manifestation of logical IPL_* */ 40 } ipl_cookie_t; 41 #endif 42 43 #ifdef _KERNEL 44 45 /* 46 * Logical interrupt priority levels -- these are distinct from 47 * the hardware interrupt priority levels of the m68k. 48 */ 49 #define IPL_NONE 0 50 #define IPL_SOFTCLOCK 1 /* clock software interrupts */ 51 #define IPL_SOFTBIO 2 /* block device software interrupts */ 52 #define IPL_SOFTNET 3 /* network software interrupts */ 53 #define IPL_SOFTSERIAL 4 /* serial device software interrupts */ 54 #define IPL_VM 5 /* all interrupts that can allocate memory */ 55 #define IPL_SCHED 6 /* scheduler / hard clock interrupts */ 56 #define IPL_HIGH 7 /* blocks all interrupts */ 57 #define NIPL 8 58 59 /* 60 * Abstract ISR priorities. These allow sorting of latency-sensitive 61 * devices earlier on the shared auto-vectored interrupt lists. 62 */ 63 #define ISRPRI_BIO 0 /* a block I/O device */ 64 #define ISRPRI_MISC 0 /* misc. devices */ 65 #define ISRPRI_NET 1 /* a network interface */ 66 #define ISRPRI_TTY 2 /* a serial port */ 67 #define ISRPRI_DISPLAY 2 /* display devices / framebuffers */ 68 #define ISRPRI_TTYNOBUF 3 /* a particularly bad serial port */ 69 #define ISRPRI_AUDIO 4 /* audio devices */ 70 71 #ifndef _LOCORE 72 73 extern volatile unsigned int intr_depth;/* interrupt depth */ 74 extern const uint16_t ipl2psl_table[NIPL]; 75 76 typedef int ipl_t; /* logical IPL_* value */ 77 78 static inline bool 79 cpu_intr_p(void) 80 { 81 return intr_depth != 0; 82 } 83 84 static inline ipl_cookie_t 85 makeiplcookie(ipl_t ipl) 86 { 87 return (ipl_cookie_t){._psl = ipl2psl_table[ipl]}; 88 } 89 90 static inline int 91 splraiseipl(ipl_cookie_t icookie) 92 { 93 return _splraise(icookie._psl); 94 } 95 96 /* 97 * These are essentially constant equivalents of what's in 98 * ipl2psl_table[] to avoid the memory reference. 99 */ 100 #define splsoftclock() _splraise(PSL_S | MACHINE_PSL_IPL_SOFTCLOCK) 101 #define splsoftbio() _splraise(PSL_S | MACHINE_PSL_IPL_SOFTBIO) 102 #define splsoftnet() _splraise(PSL_S | MACHINE_PSL_IPL_SOFTNET) 103 #define splsoftserial() _splraise(PSL_S | MACHINE_PSL_IPL_SOFTSERIAL) 104 #define splvm() _splraise(PSL_S | MACHINE_PSL_IPL_VM) 105 #define splsched() _splraise(PSL_S | MACHINE_PSL_IPL_SCHED) 106 #define splhigh() spl7() 107 108 /* 109 * XXX TODO: Support for hardware-assisted soft interrupts (sun68k) 110 * XXX and fast-soft-interrupts (others). 111 */ 112 #define spl0() _spl0() 113 #define splx(s) _splx(s) 114 115 #ifdef _M68K_INTR_PRIVATE 116 #include <sys/queue.h> 117 118 struct m68k_intrhand { 119 LIST_ENTRY(m68k_intrhand) ih_link; 120 int (*ih_func)(void *); 121 void *ih_arg; 122 struct evcnt *ih_evcnt; 123 int ih_ipl; /* m68k IPL, not IPL_* */ 124 int ih_vec; 125 int ih_isrpri; 126 }; 127 LIST_HEAD(m68k_intrhand_list, m68k_intrhand); 128 129 struct m68k_ih_allocfuncs { 130 struct m68k_intrhand * (*alloc)(int km_flag); 131 void (*free)(struct m68k_intrhand *); 132 }; 133 #else 134 struct m68k_ih_allocfuncs; 135 #endif /* _M68K_INTR_PRIVATE */ 136 137 #include <sys/evcnt.h> 138 139 #ifdef __HAVE_LEGACY_INTRCNT 140 #define m68k_count_intr(x) \ 141 do { \ 142 extern u_int intrcnt[]; \ 143 intrcnt[(x)]++; \ 144 curcpu()->ci_data.cpu_nintr++; \ 145 } while (/*CONSTCOND*/0) 146 #else 147 /* 148 * This is exposed here so that platform-specific interrupt handlers 149 * can access it. 150 */ 151 extern struct evcnt m68k_intr_evcnt[]; 152 153 #define m68k_count_intr(x) \ 154 do { \ 155 /* 32-bit counter should be sufficient for m68k. */ \ 156 m68k_intr_evcnt[(x)].ev_count32++; \ 157 curcpu()->ci_data.cpu_nintr++; \ 158 } while (/*CONSTCOND*/0) 159 #endif /* __HAVE_LEGACY_INTRCNT */ 160 161 /* 162 * Common m68k interrupt dispatch: 163 * 164 * ==> m68k_intr_init(const struct m68k_ih_allocfuncs *allocfuncs) 165 * 166 * Initialize the interrupt system. If the platform needs to store 167 * additional information in the interrupt handle, then it can provide 168 * its own alloc/free routines. Otherwise, pass NULL to get the default. 169 * If a platform doesn't want the special allocator behavior, calling 170 * this function is optional; it will be done for you on the first call 171 * to m68k_intr_establish(). 172 * 173 * ==> m68k_intr_establish(int (*func)(void *), void *arg, 174 * struct evcnt *ev, int vec, int ipl, int flags) 175 * 176 * Establish an interrupt handler. If vec is 0, then the handler is 177 * registered in the auto-vector list corresponding to the specified 178 * m68k interrupt priroity level (this is NOT an IPL_* value). Otherwise. 179 * the handler is registered at the specified vector. 180 * 181 * Vectored interrupts are not shareable. The interrupt vector must be 182 * within the platform's "user vector" region, which is generally defined 183 * as vectors 64-255, although some platforms may use vectors that start 184 * below 64 (in which case, that platform must define MACHINE_USERVEC_START 185 * to override the default). 186 * 187 * Vectored interrupt support is not included by default in order to reduce 188 * the memory footprint. If a platform wishes to enable vectored interrupts, 189 * then it should define __HAVE_M68K_INTR_VECTORED in its <machine/types.h> 190 * and genassym.cf. 191 * 192 * ==> m68k_intr_disestablish(void *ih) 193 * 194 * Removes a previously-established interrupt handler. Returns true 195 * if there are no more handlers on the list that handler was on. This 196 * information can be used to e.g. disable interrupts on a PIC. 197 */ 198 void m68k_intr_init(const struct m68k_ih_allocfuncs *); 199 void *m68k_intr_establish(int (*)(void *), void *, struct evcnt *, 200 int/*vec*/, int/*m68k ipl*/, int/*isrpri*/, int/*flags*/); 201 bool m68k_intr_disestablish(void *); 202 203 #ifdef __HAVE_M68K_INTR_VECTORED 204 void *m68k_intrvec_intrhand(int vec); /* XXX */ 205 #endif 206 207 #endif /* !_LOCORE */ 208 209 #endif /* _KERNEL */ 210 211 #endif /* _M68k_INTR_H_ */ 212