#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.37 2026/03/18 04:08:38 thorpej Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/vmmeter.h>
#include <sys/cpu.h>
#include <sys/intr.h>
#include <m68k/vectors.h>
#include <machine/psc.h>
#include <machine/viareg.h>
#define NISR 8
#define ISRLOC 0x18
static int intr_noint(void *);
static int ((*intr_func[NISR])(void *)) = {
intr_noint,
intr_noint,
intr_noint,
intr_noint,
intr_noint,
intr_noint,
intr_noint,
intr_noint
};
static void *intr_arg[NISR] = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};
#ifdef DEBUG
int intr_debug = 0;
#endif
uint16_t ipl2psl_table[NIPL];
volatile unsigned int intr_depth;
extern u_int intrcnt[];
void intr_computeipl(void);
#define MAX_INAME_LENGTH 53
#define STD_INAMES \
"spur\0via1\0via2\0unused1\0scc\0unused2\0unused3\0nmi\0clock\0"
#define AUX_INAMES \
"spur\0soft\0via2\0ethernet\0scc\0sound\0via1\0nmi\0clock\0 "
#define AV_INAMES \
"spur\0via1\0via2\0ethernet\0scc\0dsp\0unused1\0nmi\0clock\0 "
void
intr_init(void)
{
extern char intrnames[MAX_INAME_LENGTH];
extern char eintrnames[] __diagused;
const char *inames;
ipl2psl_table[IPL_NONE] = 0;
ipl2psl_table[IPL_SOFTCLOCK] = PSL_S|PSL_IPL1;
ipl2psl_table[IPL_SOFTNET] = PSL_S|PSL_IPL1;
ipl2psl_table[IPL_SOFTSERIAL] = PSL_S|PSL_IPL1;
ipl2psl_table[IPL_SOFTBIO] = PSL_S|PSL_IPL1;
ipl2psl_table[IPL_HIGH] = PSL_S|PSL_IPL7;
if (mac68k_machine.aux_interrupts) {
inames = AUX_INAMES;
ipl2psl_table[IPL_VM] = (PSL_S | PSL_IPL6);
ipl2psl_table[IPL_SCHED] = (PSL_S | PSL_IPL6);
} else {
inames = STD_INAMES;
ipl2psl_table[IPL_VM] = (PSL_S | PSL_IPL2);
ipl2psl_table[IPL_SCHED] = (PSL_S | PSL_IPL3);
if (current_mac_model->class == MACH_CLASSAV) {
inames = AV_INAMES;
ipl2psl_table[IPL_VM] = (PSL_S | PSL_IPL4);
ipl2psl_table[IPL_SCHED] = (PSL_S | PSL_IPL4);
}
}
KASSERT(MAX_INAME_LENGTH <=
((uintptr_t)eintrnames - (uintptr_t)intrnames));
memcpy(intrnames, inames, MAX_INAME_LENGTH);
intr_computeipl();
via_init();
psc_init();
}
void
intr_computeipl(void)
{
if (ipl2psl_table[IPL_VM] > ipl2psl_table[IPL_SCHED])
ipl2psl_table[IPL_SCHED] = ipl2psl_table[IPL_VM];
if (ipl2psl_table[IPL_SCHED] > ipl2psl_table[IPL_HIGH])
ipl2psl_table[IPL_HIGH] = ipl2psl_table[IPL_SCHED];
}
void
intr_establish(int (*func)(void *), void *arg, int ipl)
{
if ((ipl < 0) || (ipl >= NISR))
panic("intr_establish: bad ipl %d", ipl);
#ifdef DIAGNOSTIC
if (intr_func[ipl] != intr_noint)
printf("intr_establish: attempt to share ipl %d\n", ipl);
#endif
intr_func[ipl] = func;
intr_arg[ipl] = arg;
}
void
intr_disestablish(int ipl)
{
if ((ipl < 0) || (ipl >= NISR))
panic("intr_disestablish: bad ipl %d", ipl);
intr_func[ipl] = intr_noint;
intr_arg[ipl] = NULL;
}
void
intr_dispatch(struct clockframe frame)
{
const int ipl = VECO_TO_VECI(frame.cf_vo) - VECI_INTRAV0;
intr_depth++;
intrcnt[ipl]++;
curcpu()->ci_data.cpu_nintr++;
(void)(*intr_func[ipl])(intr_arg[ipl] ? intr_arg[ipl] : &frame);
intr_depth--;
}
static int
intr_noint(void *arg)
{
#ifdef DEBUG
intr_depth++;
if (intr_debug) {
const struct clockframe *frame = arg;
const int ipl = VECO_TO_VECI(frame->cf_vo) - VECI_INTRAV0;
printf("intr_noint: ipl %d\n", ipl);
}
intr_depth--;
#endif
return 0;
}
bool
cpu_intr_p(void)
{
return intr_depth != 0;
}