improve interrupt response.

This commit is contained in:
uch 2001-09-23 14:32:52 +00:00
parent b77ae95a9e
commit 6c1c0aff9c
6 changed files with 208 additions and 184 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: interrupt.c,v 1.3 2001/09/15 19:51:38 uch Exp $ */
/* $NetBSD: interrupt.c,v 1.4 2001/09/23 14:32:52 uch Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -44,97 +44,10 @@
#include <uvm/uvm_extern.h>
#include <machine/locore.h> /* mips3_cp0_*() */
#include <machine/sysconf.h>
#ifdef DEBUG
#define STATIC
#else
#define STATIC static
#endif
#if defined(VR41XX) && defined(TX39XX)
STATIC void (*__cpu_intr)(u_int32_t, u_int32_t, u_int32_t, u_int32_t);
#define VR_INTR vr_intr
#define TX_INTR tx_intr
#elif defined(VR41XX)
#define VR_INTR cpu_intr
#elif defined(TX39XX)
#define TX_INTR cpu_intr
#endif
/*
* This is a mask of bits to clear in the SR when we go to a
* given interrupt priority level.
*/
#ifdef VR41XX
const u_int32_t __ipl_sr_bits_vr[_IPL_N] = {
0, /* IPL_NONE */
MIPS_SOFT_INT_MASK_0, /* IPL_SOFT */
MIPS_SOFT_INT_MASK_0, /* IPL_SOFTCLOCK */
MIPS_SOFT_INT_MASK_0|
MIPS_SOFT_INT_MASK_1, /* IPL_SOFTNET */
MIPS_SOFT_INT_MASK_0|
MIPS_SOFT_INT_MASK_1, /* IPL_SOFTSERIAL */
MIPS_SOFT_INT_MASK_0|
MIPS_SOFT_INT_MASK_1|
MIPS_INT_MASK_0, /* IPL_BIO */
MIPS_SOFT_INT_MASK_0|
MIPS_SOFT_INT_MASK_1|
MIPS_INT_MASK_0, /* IPL_NET */
MIPS_SOFT_INT_MASK_0|
MIPS_SOFT_INT_MASK_1|
MIPS_INT_MASK_0, /* IPL_{TTY,SERIAL} */
MIPS_SOFT_INT_MASK_0|
MIPS_SOFT_INT_MASK_1|
MIPS_INT_MASK_0|
MIPS_INT_MASK_1, /* IPL_{CLOCK,HIGH} */
};
#endif /* VR41XX */
#ifdef TX39XX
const u_int32_t __ipl_sr_bits_tx[_IPL_N] = {
0, /* IPL_NONE */
MIPS_SOFT_INT_MASK_0, /* IPL_SOFT */
MIPS_SOFT_INT_MASK_0, /* IPL_SOFTCLOCK */
MIPS_SOFT_INT_MASK_0|
MIPS_SOFT_INT_MASK_1, /* IPL_SOFTNET */
MIPS_SOFT_INT_MASK_0|
MIPS_SOFT_INT_MASK_1, /* IPL_SOFTSERIAL */
MIPS_SOFT_INT_MASK_0|
MIPS_SOFT_INT_MASK_1|
MIPS_INT_MASK_2|
MIPS_INT_MASK_4, /* IPL_BIO */
MIPS_SOFT_INT_MASK_0|
MIPS_SOFT_INT_MASK_1|
MIPS_INT_MASK_2|
MIPS_INT_MASK_4, /* IPL_NET */
MIPS_SOFT_INT_MASK_0|
MIPS_SOFT_INT_MASK_1|
MIPS_INT_MASK_2|
MIPS_INT_MASK_4, /* IPL_{TTY,SERIAL} */
MIPS_SOFT_INT_MASK_0|
MIPS_SOFT_INT_MASK_1|
MIPS_INT_MASK_2|
MIPS_INT_MASK_4, /* IPL_{CLOCK,HIGH} */
};
#endif /* TX39XX */
extern const u_int32_t __ipl_sr_bits_vr[];
extern const u_int32_t __ipl_sr_bits_tx[];
const u_int32_t ipl_si_to_sr[_IPL_NSOFT] = {
MIPS_SOFT_INT_MASK_0, /* IPL_SOFT */
@ -146,7 +59,6 @@ const u_int32_t ipl_si_to_sr[_IPL_NSOFT] = {
const u_int32_t *ipl_sr_bits;
struct hpcmips_soft_intrhand *softnet_intrhand;
struct hpcmips_soft_intr hpcmips_soft_intrs[_IPL_NSOFT];
STATIC void softintr(u_int32_t);
void
intr_init()
@ -162,49 +74,22 @@ intr_init()
}
#if defined(VR41XX) && defined(TX39XX)
/*
* cpu_intr:
*
* handle MIPS CPU interrupt.
* if VR41XX only or TX39XX only kernel, directly jump to each handler
* (tx/tx39icu.c, vr/vr.c), don't use this dispather.
*
*/
void
cpu_intr(u_int32_t status, u_int32_t cause, u_int32_t pc, u_int32_t ipending)
{
(*__cpu_intr)(status, caust, pc, ipending);
(*platform.cpu_intr)(status, cause, pc, ipending);
}
#endif /* VR41XX && TX39XX */
#ifdef VR41XX
void
VR_INTR(u_int32_t status, u_int32_t cause, u_int32_t pc, u_int32_t ipending)
{
uvmexp.intrs++;
if (ipending & MIPS_INT_MASK_5) {
/*
* Writing a value to the Compare register,
* as a side effect, clears the timer
* interrupt request.
*/
mips3_cp0_compare_write(mips3_cp0_count_read());
}
if (ipending & MIPS3_HARD_INT_MASK)
_splset((*platform.iointr)(status, cause, pc, ipending));
softintr(ipending);
}
#endif /* VR41XX */
#ifdef TX39XX
void
TX_INTR(u_int32_t status, u_int32_t cause, u_int32_t pc, u_int32_t ipending)
{
uvmexp.intrs++;
if (ipending & MIPS_HARD_INT_MASK)
_splset((*platform.iointr)(status, cause, pc, ipending));
softintr(ipending);
}
#endif /* TX39XX */
/*
* softintr:
*

View File

@ -1,4 +1,4 @@
/* $NetBSD: intr.h,v 1.14 2001/09/16 15:45:44 uch Exp $ */
/* $NetBSD: intr.h,v 1.15 2001/09/23 14:32:52 uch Exp $ */
/*
* Copyright (c) 1998 Jonathan Stone. All rights reserved.
@ -148,6 +148,7 @@ struct hpcmips_soft_intr {
};
void softintr_init(void);
void softintr(u_int32_t);
void *softintr_establish(int, void (*)(void *), void *);
void softintr_disestablish(void *);
void softintr_dispatch(void);

View File

@ -1,4 +1,4 @@
/* $NetBSD: sysconf.h,v 1.10 2001/09/18 17:37:28 uch Exp $ */
/* $NetBSD: sysconf.h,v 1.11 2001/09/23 14:32:52 uch Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@ -54,17 +54,17 @@ struct clock_ymdhms;
extern struct platform {
/*
* cpu_intr - interrupt handler
* cpu_idle - CPU dependend idle routine.
* cons_init - console initialization
* iointr - I/O interrupt handler
* fb_init - frame buffer initialization
* mem_init - Count available memory
* reboot - reboot or powerdown
* clock -
*/
void (*cpu_intr)(u_int32_t, u_int32_t, u_int32_t, u_int32_t);
void (*cpu_idle)(void);
void (*cons_init)(void);
int (*iointr)(u_int32_t, u_int32_t, u_int32_t, u_int32_t);
void (*fb_init)(caddr_t*);
void (*mem_init)(paddr_t);
void (*reboot)(int, char *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: tx39.c,v 1.26 2001/09/17 17:03:45 uch Exp $ */
/* $NetBSD: tx39.c,v 1.27 2001/09/23 14:32:53 uch Exp $ */
/*-
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@ -36,6 +36,8 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "opt_vr41xx.h"
#include "opt_tx39xx.h"
#include "opt_tx39_debug.h"
#include "m38813c.h"
#include "tc5165buf.h"
@ -83,7 +85,14 @@ u_int32_t tx39debugflag;
#endif
void tx_init(void);
int tx39icu_intr(u_int32_t, u_int32_t, u_int32_t, u_int32_t);
#if defined(VR41XX) && defined(TX39XX)
#define TX_INTR tx_intr
#else
#define TX_INTR cpu_intr /* locore_mips3 directly call this */
#endif
extern void TX_INTR(u_int32_t, u_int32_t, u_int32_t, u_int32_t);
void tx39clock_cpuspeed(int *, int *);
/* TX39-specific initialization vector */
@ -92,7 +101,6 @@ void tx_fb_init(caddr_t *);
void tx_mem_init(paddr_t);
void tx_find_dram(paddr_t, paddr_t);
void tx_reboot(int, char *);
int tx_intr(u_int32_t, u_int32_t, u_int32_t, u_int32_t);
void
tx_init()
@ -105,12 +113,13 @@ tx_init()
/*
* Platform Specific Function Hooks
*/
platform.cpu_intr = TX_INTR;
platform.cpu_idle = NULL; /* not implemented yet */
platform.cons_init = tx_cons_init;
platform.fb_init = tx_fb_init;
platform.mem_init = tx_mem_init;
platform.reboot = tx_reboot;
platform.iointr = tx39icu_intr;
model = MIPS_PRID_REV(cpu_id);

View File

@ -1,7 +1,7 @@
/* $NetBSD: tx39icu.c,v 1.13 2001/09/18 17:37:28 uch Exp $ */
/* $NetBSD: tx39icu.c,v 1.14 2001/09/23 14:32:53 uch Exp $ */
/*-
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
* Copyright (c) 1999-2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -36,6 +36,9 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "opt_vr41xx.h"
#include "opt_tx39xx.h"
#include "opt_tx39_debug.h"
#include "opt_use_poll.h"
#include "opt_tx39icudebug.h"
@ -47,6 +50,8 @@
#include <sys/malloc.h>
#include <sys/queue.h>
#include <uvm/uvm_extern.h>
#include <mips/cpuregs.h>
#include <machine/bus.h>
@ -59,6 +64,12 @@
#undef TX39ICUDEBUG_PRINT_PENDING_INTERRUPT /* For explorer. good luck! */
#if defined(VR41XX) && defined(TX39XX)
#define TX_INTR tx_intr
#else
#define TX_INTR cpu_intr /* locore_mips3 directly call this */
#endif
#ifdef TX39ICUDEBUG
#define DPRINTF(arg) printf arg
#else
@ -66,6 +77,44 @@
#endif
u_int32_t tx39intrvec;
/*
* This is a mask of bits to clear in the SR when we go to a
* given interrupt priority level.
*/
const u_int32_t __ipl_sr_bits_tx[_IPL_N] = {
0, /* IPL_NONE */
MIPS_SOFT_INT_MASK_0, /* IPL_SOFT */
MIPS_SOFT_INT_MASK_0, /* IPL_SOFTCLOCK */
MIPS_SOFT_INT_MASK_0|
MIPS_SOFT_INT_MASK_1, /* IPL_SOFTNET */
MIPS_SOFT_INT_MASK_0|
MIPS_SOFT_INT_MASK_1, /* IPL_SOFTSERIAL */
MIPS_SOFT_INT_MASK_0|
MIPS_SOFT_INT_MASK_1|
MIPS_INT_MASK_2|
MIPS_INT_MASK_4, /* IPL_BIO */
MIPS_SOFT_INT_MASK_0|
MIPS_SOFT_INT_MASK_1|
MIPS_INT_MASK_2|
MIPS_INT_MASK_4, /* IPL_NET */
MIPS_SOFT_INT_MASK_0|
MIPS_SOFT_INT_MASK_1|
MIPS_INT_MASK_2|
MIPS_INT_MASK_4, /* IPL_{TTY,SERIAL} */
MIPS_SOFT_INT_MASK_0|
MIPS_SOFT_INT_MASK_1|
MIPS_INT_MASK_2|
MIPS_INT_MASK_4, /* IPL_{CLOCK,HIGH} */
};
/* IRQHIGH lines list */
static const struct irqhigh_list {
int qh_pri; /* IRQHIGH priority */
@ -179,13 +228,14 @@ void tx39_irqhigh_intr(u_int32_t, u_int32_t, u_int32_t, u_int32_t);
int tx39_irqhigh(int, int);
struct cfattach tx39icu_ca = {
sizeof(struct tx39icu_softc), tx39icu_match, tx39icu_attach
sizeof(struct tx39icu_softc), tx39icu_match, tx39icu_attach
};
int
tx39icu_match(struct device *parent, struct cfdata *cf, void *aux)
{
return (ATTACH_FIRST);
return (ATTACH_FIRST);
}
void
@ -196,7 +246,7 @@ tx39icu_attach(struct device *parent, struct device *self, void *aux)
tx_chipset_tag_t tc = ta->ta_tc;
txreg_t reg, *regs;
int i;
printf("\n");
sc->sc_tc = ta->ta_tc;
@ -272,15 +322,19 @@ tx39icu_attach(struct device *parent, struct device *self, void *aux)
tx_conf_register_intr(tc, self);
}
int
tx39icu_intr(u_int32_t status, u_int32_t cause, u_int32_t pc,
u_int32_t ipending)
void
TX_INTR(u_int32_t status, u_int32_t cause, u_int32_t pc, u_int32_t ipending)
{
struct tx39icu_softc *sc;
tx_chipset_tag_t tc;
txreg_t reg, pend, *regs;
int i, j;
uvmexp.intrs++;
if ((ipending & MIPS_HARD_INT_MASK) == 0)
goto softintr;
tc = tx_conf_get_tag();
sc = tc->tc_intrt;
/*
@ -314,7 +368,7 @@ tx39icu_intr(u_int32_t status, u_int32_t cause, u_int32_t pc,
if (ipending & MIPS_INT_MASK_4) {
tx39_irqhigh_intr(ipending, pc, status, cause);
return (0);
goto softintr;
}
/* IRQLOW */
@ -371,7 +425,11 @@ tx39icu_intr(u_int32_t status, u_int32_t cause, u_int32_t pc,
reg = TX39_INTRENABLE6_PRIORITYMASK_SET(reg, 0xffff);
tx_conf_write(tc, TX39_INTRENABLE6_REG, reg);
#endif
return (MIPS_SR_INT_IE | (status & ~cause & MIPS_HARD_INT_MASK));
softintr:
_splset((status & ~cause & MIPS_HARD_INT_MASK) | MIPS_SR_INT_IE);
softintr(ipending);
}
int

View File

@ -1,7 +1,7 @@
/* $NetBSD: vr.c,v 1.30 2001/09/17 17:03:46 uch Exp $ */
/* $NetBSD: vr.c,v 1.31 2001/09/23 14:32:53 uch Exp $ */
/*-
* Copyright (c) 1999
* Copyright (c) 1999-2001
* Shin Takemura and PocketBSD Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -35,12 +35,15 @@
*/
#include "opt_vr41xx.h"
#include "opt_tx39xx.h"
#include "opt_kgdb.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/reboot.h>
#include <uvm/uvm_extern.h>
#include <machine/sysconf.h>
#include <machine/bus.h>
#include <machine/bootinfo.h>
@ -99,27 +102,74 @@
#include <arch/hpcmips/vr/vrkiuvar.h>
#endif
void vr_init(void);
int vr_intr(u_int32_t, u_int32_t, u_int32_t, u_int32_t);
void vr_cons_init(void);
void vr_fb_init(caddr_t *);
void vr_mem_init(paddr_t);
void vr_find_dram(paddr_t, paddr_t);
void vr_reboot(int, char *);
void vr_idle(void);
#ifdef DEBUG
#define STATIC
#else
#define STATIC static
#endif
/*
* This is a mask of bits to clear in the SR when we go to a
* given interrupt priority level.
*/
const u_int32_t __ipl_sr_bits_vr[_IPL_N] = {
0, /* IPL_NONE */
MIPS_SOFT_INT_MASK_0, /* IPL_SOFT */
MIPS_SOFT_INT_MASK_0, /* IPL_SOFTCLOCK */
MIPS_SOFT_INT_MASK_0|
MIPS_SOFT_INT_MASK_1, /* IPL_SOFTNET */
MIPS_SOFT_INT_MASK_0|
MIPS_SOFT_INT_MASK_1, /* IPL_SOFTSERIAL */
MIPS_SOFT_INT_MASK_0|
MIPS_SOFT_INT_MASK_1|
MIPS_INT_MASK_0, /* IPL_BIO */
MIPS_SOFT_INT_MASK_0|
MIPS_SOFT_INT_MASK_1|
MIPS_INT_MASK_0, /* IPL_NET */
MIPS_SOFT_INT_MASK_0|
MIPS_SOFT_INT_MASK_1|
MIPS_INT_MASK_0, /* IPL_{TTY,SERIAL} */
MIPS_SOFT_INT_MASK_0|
MIPS_SOFT_INT_MASK_1|
MIPS_INT_MASK_0|
MIPS_INT_MASK_1, /* IPL_{CLOCK,HIGH} */
};
#if defined(VR41XX) && defined(TX39XX)
#define VR_INTR vr_intr
#else
#define VR_INTR cpu_intr /* locore_mips3 directly call this */
#endif
void vr_init(void);
void VR_INTR(u_int32_t, u_int32_t, u_int32_t, u_int32_t);
extern void vr_idle(void);
STATIC void vr_cons_init(void);
STATIC void vr_fb_init(caddr_t *);
STATIC void vr_mem_init(paddr_t);
STATIC void vr_find_dram(paddr_t, paddr_t);
STATIC void vr_reboot(int, char *);
/*
* CPU interrupt dispatch table (HwInt[0:3])
*/
int null_handler(void *, u_int32_t, u_int32_t);
static int (*intr_handler[4])(void*, u_int32_t, u_int32_t) =
STATIC int vr_null_handler(void *, u_int32_t, u_int32_t);
STATIC int (*vr_intr_handler[4])(void *, u_int32_t, u_int32_t) =
{
null_handler,
null_handler,
null_handler,
null_handler
vr_null_handler,
vr_null_handler,
vr_null_handler,
vr_null_handler
};
static void *intr_arg[4];
STATIC void *vr_intr_arg[4];
void
vr_init()
@ -128,7 +178,7 @@ vr_init()
* Platform Specific Function Hooks
*/
platform.cpu_idle = vr_idle;
platform.iointr = vr_intr;
platform.cpu_intr = VR_INTR;
platform.cons_init = vr_cons_init;
platform.fb_init = vr_fb_init;
platform.mem_init = vr_mem_init;
@ -175,7 +225,7 @@ vr_find_dram(paddr_t addr, paddr_t end)
#ifdef VR_FIND_DRAMLIM
if (VR_FIND_DRAMLIM < end)
end = VR_FIND_DRAMLIM;
#endif
#endif /* VR_FIND_DRAMLIM */
n = mem_cluster_cnt;
for (; addr < end; addr += NBPG) {
@ -215,7 +265,7 @@ vr_find_dram(paddr_t addr, paddr_t end)
for (i = 0; i < NBPG; i += 4)
if (*(volatile int *)(page+i) != (x ^ i))
goto bad;
#endif
#endif /* NARLY_MEMORY_PROBE */
if (!mem_clusters[n].size)
mem_clusters[n].start = addr;
@ -339,15 +389,38 @@ vr_reboot(int howto, char *bootstr)
/*
* Handle interrupts.
*/
int
vr_intr(u_int32_t status, u_int32_t cause, u_int32_t pc, u_int32_t ipending)
void
VR_INTR(u_int32_t status, u_int32_t cause, u_int32_t pc, u_int32_t ipending)
{
int hwintr;
uvmexp.intrs++;
hwintr = (ffs(ipending >> 10) -1) & 0x3;
(*intr_handler[hwintr])(intr_arg[hwintr], pc, status);
return (MIPS_SR_INT_IE | (status & ~cause & MIPS_HARD_INT_MASK));
if (ipending & MIPS_INT_MASK_5) {
/*
* spl* uses MIPS_INT_MASK not MIPS3_INT_MASK. it causes
* INT5 interrupt.
*/
mips3_cp0_compare_write(mips3_cp0_count_read());
}
/* for spllowersoftclock */
_splset(((status & ~cause) & MIPS_HARD_INT_MASK) | MIPS_SR_INT_IE);
if (ipending & MIPS_INT_MASK_1) {
(*vr_intr_handler[1])(vr_intr_arg[1], pc, status);
cause &= ~MIPS_INT_MASK_1;
_splset(((status & ~cause) & MIPS_HARD_INT_MASK)
| MIPS_SR_INT_IE);
}
if (ipending & MIPS_INT_MASK_0) {
(*vr_intr_handler[0])(vr_intr_arg[0], pc, status);
cause &= ~MIPS_INT_MASK_0;
}
_splset(((status & ~cause) & MIPS_HARD_INT_MASK) | MIPS_SR_INT_IE);
softintr(ipending);
}
void *
@ -355,30 +428,28 @@ vr_intr_establish(int line, int (*ih_fun)(void *, u_int32_t, u_int32_t),
void *ih_arg)
{
if (intr_handler[line] != null_handler) {
panic("vr_intr_establish:"
" can't establish duplicated intr handler.");
}
intr_handler[line] = ih_fun;
intr_arg[line] = ih_arg;
KDASSERT(vr_intr_handler[line] == vr_null_handler);
return ((void*)line);
vr_intr_handler[line] = ih_fun;
vr_intr_arg[line] = ih_arg;
return ((void *)line);
}
void
vr_intr_disestablish(void *ih)
{
int line = (int)ih;
intr_handler[line] = null_handler;
intr_arg[line] = NULL;
vr_intr_handler[line] = vr_null_handler;
vr_intr_arg[line] = NULL;
}
int
null_handler(void *arg, u_int32_t pc, u_int32_t statusReg)
vr_null_handler(void *arg, u_int32_t pc, u_int32_t status)
{
printf("null_handler\n");
printf("vr_null_handler\n");
return (0);
}