Rework the hp700 interrupt code to

- note chip restictions on interrupt in the kernel config
	- allocate interrupts at attach time
	- track per CPU interrupts
	- remove a funciton written in assembly
This commit is contained in:
skrll 2012-05-23 16:11:37 +00:00
parent 3a550d746a
commit 8e6e666e7a
21 changed files with 405 additions and 497 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: GENERIC,v 1.113 2012/04/06 12:21:58 skrll Exp $
# $NetBSD: GENERIC,v 1.114 2012/05/23 16:11:37 skrll Exp $
#
# GENERIC machine description file
#
@ -23,7 +23,7 @@ include "arch/hp700/conf/std.hp700"
options INCLUDE_CONFIG_FILE # embed config file in kernel binary
options SYSCTL_INCLUDE_DESCR # Include sysctl descriptions in kernel
#ident "GENERIC-$Revision: 1.113 $"
#ident "GENERIC-$Revision: 1.114 $"
maxusers 32 # estimated number of users
@ -229,10 +229,13 @@ power0 at mainbus0 # power/fail manager
lcd0 at mainbus0 # LCD
# Basic Bus Support
lasi* at mainbus0 # LASI host adapter ( LSI PN??? )
asp* at mainbus0 # this one comes w/ Viper and leds
lasi0 at mainbus0 irq 28 # LASI host adapter
lasi0 at phantomas0 irq 28 # LASI on [AB]*
lasi0 at uturn? irq 28 # LASI on [CJ]*
lasi1 at mainbus0 irq 27 # 712 GIO card
asp* at mainbus0 irq 28 # this one comes w/ Viper and LEDs
wax* at mainbus0 # Wax GSC to GSC Bus Adapter
mongoose* at mainbus0 irq 17 # EISA Bus Adapter ( i82350 or TI??? )
mongoose* at mainbus0 # EISA Bus Adapter ( i82350 or TI??? )
#vmeb* at mainbus0 irq ? # VME bus adapter
phantomas* at mainbus0 # Phantom PseudoBC GSC+ Port
@ -341,10 +344,10 @@ lpt* at puc? port ? # || ports on "universal" comm boards
# GSC SCSI controllers
oosiop* at gsc? # NCR 53c700
osiop* at gsc? flags 0x00000 # NCR 53c710
siop* at gsc? irq 3 # NCR 53c720 (Fast/Wide)
siop* at mainbus0 irq 3 # NCR 53c720 (Fast/Wide)
siop* at phantomas? irq 3 # NCR 53c720 (Fast/Wide)
siop* at uturn? irq 3 # NCR 53c720 (Fast/Wide)
siop* at gsc? # NCR 53c720 (Fast/Wide)
siop* at mainbus0 # NCR 53c720 (Fast/Wide)
siop* at phantomas? # NCR 53c720 (Fast/Wide)
siop* at uturn? # NCR 53c720 (Fast/Wide)
# PCI SCSI controllers
adv* at pci? dev ? function ? # AdvanSys 1200[A,B], 9xx[U,UA] SCSI

View File

@ -1,4 +1,4 @@
/* $NetBSD: apic.c,v 1.15 2012/05/21 20:58:39 skrll Exp $ */
/* $NetBSD: apic.c,v 1.16 2012/05/23 16:11:37 skrll Exp $ */
/* $OpenBSD: apic.c,v 1.14 2011/05/01 21:59:39 kettenis Exp $ */
@ -28,8 +28,6 @@
#include <machine/pdc.h>
#include <machine/intr.h>
#include <hp700/hp700/intr.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
@ -127,6 +125,7 @@ int
apic_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp)
{
struct elroy_softc *sc = pa->pa_pc->_cookie;
struct cpu_info *ci = &cpus[0];
pci_chipset_tag_t pc = pa->pa_pc;
pcitag_t tag = pa->pa_tag;
pcireg_t reg;
@ -139,7 +138,8 @@ apic_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp)
#endif
line = PCI_INTERRUPT_LINE(reg);
if (sc->sc_irq[line] == 0)
sc->sc_irq[line] = hp700_intr_allocate_bit(&ir_cpu);
sc->sc_irq[line] = hp700_intr_allocate_bit(&ci->ci_ir, -1);
KASSERT(sc->sc_irq[line] != -1);
*ihp = (line << APIC_INT_LINE_SHIFT) | sc->sc_irq[line];
return APIC_INT_IRQ(*ihp) == 0;
@ -194,7 +194,7 @@ apic_intr_establish(void *v, pci_intr_handle_t ih,
biv = apic_intr_list[irq];
if (biv == NULL) {
iv = hp700_intr_establish(pri, apic_intr, aiv, &ir_cpu, irq);
iv = hp700_intr_establish(pri, apic_intr, aiv, &ci->ci_ir, irq);
if (iv == NULL) {
free(aiv, M_DEVBUF);
free(cnt, M_DEVBUF);

View File

@ -1,4 +1,4 @@
/* $NetBSD: asp.c,v 1.20 2012/05/23 10:37:01 skrll Exp $ */
/* $NetBSD: asp.c,v 1.21 2012/05/23 16:11:37 skrll Exp $ */
/* $OpenBSD: asp.c,v 1.5 2000/02/09 05:04:22 mickey Exp $ */
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: asp.c,v 1.20 2012/05/23 10:37:01 skrll Exp $");
__KERNEL_RCSID(0, "$NetBSD: asp.c,v 1.21 2012/05/23 16:11:37 skrll Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -172,10 +172,6 @@ aspmatch(device_t parent, cfdata_t cf, void *aux)
ca->ca_type.iodc_sv_model != HPPA_BHA_ASP)
return 0;
/* Make sure we have an IRQ. */
if (ca->ca_irq == HP700CF_IRQ_UNDEF)
ca->ca_irq = hp700_intr_allocate_bit(&ir_cpu);
/*
* Forcibly mask the HPA down to the start of the ASP
* chip address space.
@ -191,12 +187,19 @@ aspattach(device_t parent, device_t self, void *aux)
struct confargs *ca = aux;
struct asp_softc *sc = device_private(self);
struct gsc_attach_args ga;
struct cpu_info *ci = &cpus[0];
bus_space_handle_t ioh;
uint32_t irr;
int s;
sc->sc_dev = self;
ca->ca_irq = hp700_intr_allocate_bit(&ci->ci_ir, ca->ca_irq);
if (ca->ca_irq == HP700CF_IRQ_UNDEF) {
aprint_error_dev(self, ": can't allocate interrupt");
return;
}
/*
* Map the ASP interrupt registers.
*/
@ -244,18 +247,19 @@ aspattach(device_t parent, device_t self, void *aux)
sc->sc_trs->asp_imr = ~0;
irr = sc->sc_trs->asp_irr;
sc->sc_trs->asp_imr = 0;
/* Establish the interrupt register. */
hp700_interrupt_register_establish(ci, &sc->sc_ir);
sc->sc_ir.ir_name = device_xname(self);
sc->sc_ir.ir_mask = &sc->sc_trs->asp_imr;
sc->sc_ir.ir_req = &sc->sc_trs->asp_irr;
splx(s);
aprint_normal(": %s rev %d, lan %d scsi %d\n",
asp_spus[sc->sc_trs->asp_spu].name, sc->sc_hw->asp_version,
sc->sc_trs->asp_lan, sc->sc_trs->asp_scsi);
/* Establish the interrupt register. */
hp700_interrupt_register_establish(&sc->sc_ir);
sc->sc_ir.ir_name = device_xname(self);
sc->sc_ir.ir_mask = &sc->sc_trs->asp_imr;
sc->sc_ir.ir_req = &sc->sc_trs->asp_irr;
/* Attach the GSC bus. */
ga.ga_ca = *ca; /* clone from us */
if (strcmp(parent->dv_xname, "mainbus0") == 0) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.c,v 1.26 2012/05/23 09:49:56 skrll Exp $ */
/* $NetBSD: cpu.c,v 1.27 2012/05/23 16:11:37 skrll Exp $ */
/* $OpenBSD: cpu.c,v 1.29 2009/02/08 18:33:28 miod Exp $ */
@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.26 2012/05/23 09:49:56 skrll Exp $");
__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.27 2012/05/23 16:11:37 skrll Exp $");
#include "opt_multiprocessor.h"
@ -47,7 +47,6 @@ __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.26 2012/05/23 09:49:56 skrll Exp $");
#include <machine/autoconf.h>
#include <hppa/hppa/cpuvar.h>
#include <hp700/hp700/intr.h>
#include <hp700/hp700/machdep.h>
#include <hp700/dev/cpudevs.h>
@ -92,8 +91,9 @@ cpuattach(device_t parent, device_t self, void *aux)
struct cpu_softc *sc = device_private(self);
struct confargs *ca = aux;
struct cpu_info *ci;
static const char lvls[4][4] = { "0", "1", "1.5", "2" };
struct hp700_interrupt_register *ir;
struct cpu_info *ci;
u_int mhz = 100 * cpu_ticksnum / cpu_ticksdenom;
int cpuno = device_unit(self);
@ -115,6 +115,12 @@ cpuattach(device_t parent, device_t self, void *aux)
aprint_normal(" (%s)", hppa_cpu_info->hci_chip_nickname);
aprint_normal(" rev %d", cpu_revision);
/* sanity against luser amongst config editors */
if (ca->ca_irq != 31) {
aprint_error_dev(self, "bad irq number %d\n", ca->ca_irq);
return;
}
/* Print the CPU type, spec, level, category, and speed. */
aprint_normal("\n%s: %s, PA-RISC %s", self->dv_xname,
hppa_cpu_info->hci_chip_type,
@ -156,17 +162,25 @@ cpuattach(device_t parent, device_t self, void *aux)
hppa_mod_info(HPPA_TYPE_FPU, (fpu_version >> 16) & 0x1f),
(fpu_version >> 11) & 0x1f);
/* sanity against luser amongst config editors */
if (ca->ca_irq != 31) {
aprint_error_dev(self, "bad irq number %d\n", ca->ca_irq);
return;
}
hp700_intr_initialise(ci);
ir = &ci->ci_ir;
hp700_interrupt_register_establish(ci, ir);
ir->ir_iscpu = true;
ir->ir_ci = ci;
ir->ir_name = device_xname(self);
sc->sc_ihclk = hp700_intr_establish(IPL_CLOCK, clock_intr,
NULL /*clockframe*/, &ir_cpu, 31);
NULL /*clockframe*/, &ci->ci_ir, 31);
/*
* Reserve some bits for chips that don't like to be moved
* around, e.g. lasi and asp.
*/
ir->ir_rbits = ((1 << 28) | (1 << 27));
ir->ir_bits &= ~ir->ir_rbits;
#ifdef MULTIPROCESSOR
/* Allocate stack for spin up and FPU emulation. */
TAILQ_INIT(&mlist);
error = uvm_pglistalloc(PAGE_SIZE, 0, -1L, PAGE_SIZE, 0, &mlist, 1, 0);
@ -191,21 +205,10 @@ cpuattach(device_t parent, device_t self, void *aux)
}
}
hppa_ncpu++;
#endif
/*
* Set the allocatable bits in the CPU interrupt registers.
* These should only be used by major chipsets, like ASP and
* LASI, and the bits used appear to be important - the
* ASP doesn't seem to like to use interrupt bits above 28
* or below 27.
*/
ir_cpu.ir_bits =
(1 << 28) | (1 << 27) | (1 << 26);
KASSERT(ci->ci_cpl == -1);
}
#ifdef MULTIPROCESSOR
void
cpu_boot_secondary_processors(void)

View File

@ -1,4 +1,4 @@
/* $NetBSD: dino.c,v 1.35 2012/05/23 10:31:59 skrll Exp $ */
/* $NetBSD: dino.c,v 1.36 2012/05/23 16:11:37 skrll Exp $ */
/* $OpenBSD: dino.c,v 1.5 2004/02/13 20:39:31 mickey Exp $ */
@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: dino.c,v 1.35 2012/05/23 10:31:59 skrll Exp $");
__KERNEL_RCSID(0, "$NetBSD: dino.c,v 1.36 2012/05/23 16:11:37 skrll Exp $");
/* #include "cardbus.h" */
@ -43,7 +43,6 @@ __KERNEL_RCSID(0, "$NetBSD: dino.c,v 1.35 2012/05/23 10:31:59 skrll Exp $");
#include <machine/iomod.h>
#include <machine/autoconf.h>
#include <machine/intr.h>
#include <hp700/hp700/intr.h>
#include <hppa/include/vmparam.h>
#include <hp700/dev/cpudevs.h>
@ -1594,10 +1593,6 @@ dinomatch(device_t parent, cfdata_t cfdata, void *aux)
if (ca->ca_type.iodc_model == 0x78)
return 0;
/* Make sure we have an IRQ. */
if (ca->ca_irq == HP700CF_IRQ_UNDEF)
ca->ca_irq = hp700_intr_allocate_bit(&ir_cpu);
return 1;
}
@ -1617,6 +1612,7 @@ dinoattach(device_t parent, device_t self, void *aux)
sc->sc_bt = ca->ca_iot;
sc->sc_dmat = ca->ca_dmatag;
ca->ca_irq = hp700_intr_allocate_bit(&ci->ci_ir, ca->ca_irq);
if (ca->ca_irq == HP700CF_IRQ_UNDEF) {
aprint_error_dev(self, ": can't allocate interrupt");
return;
@ -1659,7 +1655,7 @@ dinoattach(device_t parent, device_t self, void *aux)
r->iar0 = ci->ci_hpa | (31 - ca->ca_irq);
splx(s);
/* Establish the interrupt register. */
hp700_interrupt_register_establish(&sc->sc_ir);
hp700_interrupt_register_establish(ci, &sc->sc_ir);
sc->sc_ir.ir_name = device_xname(self);
sc->sc_ir.ir_mask = &r->imr;
sc->sc_ir.ir_req = &r->irr0;
@ -1667,7 +1663,7 @@ dinoattach(device_t parent, device_t self, void *aux)
/* Add the I/O interrupt register. */
sc->sc_ih = hp700_intr_establish(IPL_NONE, NULL, &sc->sc_ir,
&ir_cpu, ca->ca_irq);
&ci->ci_ir, ca->ca_irq);
/* TODO establish the bus error interrupt */

View File

@ -1,4 +1,4 @@
/* $NetBSD: lasi.c,v 1.22 2012/04/03 12:07:26 skrll Exp $ */
/* $NetBSD: lasi.c,v 1.23 2012/05/23 16:11:37 skrll Exp $ */
/* $OpenBSD: lasi.c,v 1.4 2001/06/09 03:57:19 mickey Exp $ */
@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: lasi.c,v 1.22 2012/04/03 12:07:26 skrll Exp $");
__KERNEL_RCSID(0, "$NetBSD: lasi.c,v 1.23 2012/05/23 16:11:37 skrll Exp $");
#undef LASIDEBUG
@ -132,10 +132,6 @@ lasimatch(device_t parent, cfdata_t cf, void *aux)
ca->ca_type.iodc_sv_model != HPPA_BHA_LASI)
return 0;
/* Make sure we have an IRQ. */
if (ca->ca_irq == HP700CF_IRQ_UNDEF)
ca->ca_irq = hp700_intr_allocate_bit(&ir_cpu);
/*
* Forcibly mask the HPA down to the start of the LASI
* chip address space.
@ -181,6 +177,12 @@ lasiattach(device_t parent, device_t self, void *aux)
aprint_normal(": rev %d.%d\n", (sc->sc_hw->lasi_version & 0xf0) >> 4,
sc->sc_hw->lasi_version & 0xf);
ca->ca_irq = hp700_intr_allocate_bit(&ci->ci_ir, ca->ca_irq);
if (ca->ca_irq == HP700CF_IRQ_UNDEF) {
aprint_error(": can't allocate interrupt\n");
return;
}
/* interrupts guts */
s = splhigh();
sc->sc_trs->lasi_iar = ci->ci_hpa | (31 - ca->ca_irq);
@ -188,13 +190,13 @@ lasiattach(device_t parent, device_t self, void *aux)
sc->sc_trs->lasi_imr = ~0U;
in = sc->sc_trs->lasi_irr;
sc->sc_trs->lasi_imr = 0;
splx(s);
/* Establish the interrupt register. */
hp700_interrupt_register_establish(&sc->sc_ir);
hp700_interrupt_register_establish(ci, &sc->sc_ir);
sc->sc_ir.ir_name = device_xname(self);
sc->sc_ir.ir_mask = &sc->sc_trs->lasi_imr;
sc->sc_ir.ir_req = &sc->sc_trs->lasi_irr;
splx(s);
/* Attach the GSC bus. */
ga.ga_ca = *ca; /* clone from us */

View File

@ -1,4 +1,4 @@
/* $NetBSD: mongoose.c,v 1.22 2011/07/01 18:33:09 dyoung Exp $ */
/* $NetBSD: mongoose.c,v 1.23 2012/05/23 16:11:37 skrll Exp $ */
/* $OpenBSD: mongoose.c,v 1.19 2010/01/01 20:28:42 kettenis Exp $ */
@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mongoose.c,v 1.22 2011/07/01 18:33:09 dyoung Exp $");
__KERNEL_RCSID(0, "$NetBSD: mongoose.c,v 1.23 2012/05/23 16:11:37 skrll Exp $");
#define MONGOOSE_DEBUG 9
@ -42,7 +42,6 @@ __KERNEL_RCSID(0, "$NetBSD: mongoose.c,v 1.22 2011/07/01 18:33:09 dyoung Exp $")
#include <machine/iomod.h>
#include <machine/autoconf.h>
#include <hp700/hp700/intr.h>
#include <hp700/dev/cpudevs.h>
#include <hp700/dev/viper.h>
@ -358,7 +357,7 @@ mg_intr(void *v)
int s, irq = 0;
iv = &sc->sc_iv[irq];
s = splraise(imask[iv->iv_pri]);
s = splraise(iv->iv_pri);
(iv->iv_handler)(iv->iv_arg);
splx(s);
@ -594,6 +593,7 @@ mgattach(device_t parent, device_t self, void *aux)
{
struct confargs *ca = aux;
struct mongoose_softc *sc = device_private(self);
struct cpu_info *ci = &cpus[0];
struct hppa_bus_space_tag *bt;
union mongoose_attach_args ea;
char brid[EISA_IDSTRINGLEN];
@ -616,6 +616,13 @@ mgattach(device_t parent, device_t self, void *aux)
sizeof(struct mongoose_regs));
return;
}
ca->ca_irq = hp700_intr_allocate_bit(&ci->ci_ir, ca->ca_irq);
if (ca->ca_irq == HP700CF_IRQ_UNDEF) {
aprint_error(": can't allocate interrupt\n");
return;
}
sc->sc_ctrl = (struct mongoose_ctrl *)ioh;
viper_eisa_en();
@ -709,6 +716,6 @@ mgattach(device_t parent, device_t self, void *aux)
#undef R
/* attach interrupt */
sc->sc_ih = hp700_intr_establish(IPL_NONE, mg_intr, sc, &ir_cpu,
sc->sc_ih = hp700_intr_establish(IPL_NONE, mg_intr, sc, &ci->ci_ir,
ca->ca_irq);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: power.c,v 1.6 2011/01/04 10:42:33 skrll Exp $ */
/* $NetBSD: power.c,v 1.7 2012/05/23 16:11:37 skrll Exp $ */
/*
* Copyright (c) 2004 Jochen Kunz.
@ -70,7 +70,6 @@
#include <machine/autoconf.h>
#include <hp700/dev/cpudevs.h>
#include <hp700/hp700/intr.h>
#include <dev/sysmon/sysmon_taskq.h>
#include <dev/sysmon/sysmonvar.h>

View File

@ -1,4 +1,4 @@
/* $NetBSD: siop_sgc.c,v 1.9 2012/04/03 12:07:26 skrll Exp $ */
/* $NetBSD: siop_sgc.c,v 1.10 2012/05/23 16:11:37 skrll Exp $ */
/* $OpenBSD: siop_sgc.c,v 1.1 2007/08/05 19:09:52 kettenis Exp $ */
@ -19,7 +19,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: siop_sgc.c,v 1.9 2012/04/03 12:07:26 skrll Exp $");
__KERNEL_RCSID(0, "$NetBSD: siop_sgc.c,v 1.10 2012/05/23 16:11:37 skrll Exp $");
#include <sys/param.h>
#include <sys/device.h>
@ -40,7 +40,6 @@ __KERNEL_RCSID(0, "$NetBSD: siop_sgc.c,v 1.9 2012/04/03 12:07:26 skrll Exp $");
#include <dev/ic/siopvar.h>
#include <hp700/dev/cpudevs.h>
#include <hp700/hp700/intr.h>
#define IO_II_INTEN 0x20000000
#define IO_II_PACKEN 0x10000000
@ -75,10 +74,6 @@ siop_sgc_match(device_t parent, cfdata_t match, void *aux)
ca->ca_type.iodc_sv_model != HPPA_ADMA_FWSCSI)
return 0;
/* Make sure we have an IRQ. */
if (ca->ca_irq == HP700CF_IRQ_UNDEF)
ca->ca_irq = hp700_intr_allocate_bit(&ir_cpu);
return 1;
}
@ -99,6 +94,12 @@ siop_sgc_attach(device_t parent, device_t self, void *aux)
return;
}
ca->ca_irq = hp700_intr_allocate_bit(&ci->ci_ir, ca->ca_irq);
if (ca->ca_irq == HP700CF_IRQ_UNDEF) {
aprint_error(": can't allocate interrupt\n");
return;
}
sgc->sc_bustag = *sgc->sc_iot;
sgc->sc_bustag.hbt_r1 = siop_sgc_r1;
sgc->sc_bustag.hbt_r2 = siop_sgc_r2;
@ -135,7 +136,7 @@ siop_sgc_attach(device_t parent, device_t self, void *aux)
siop_attach(&sgc->sc_siop);
(void)hp700_intr_establish(IPL_BIO, siop_intr, sc, &ir_cpu,
(void)hp700_intr_establish(IPL_BIO, siop_intr, sc, &ci->ci_ir,
ca->ca_irq);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: wax.c,v 1.19 2012/05/23 10:31:59 skrll Exp $ */
/* $NetBSD: wax.c,v 1.20 2012/05/23 16:11:37 skrll Exp $ */
/* $OpenBSD: wax.c,v 1.1 1998/11/23 03:04:10 mickey Exp $ */
@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: wax.c,v 1.19 2012/05/23 10:31:59 skrll Exp $");
__KERNEL_RCSID(0, "$NetBSD: wax.c,v 1.20 2012/05/23 16:11:37 skrll Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -101,11 +101,6 @@ waxmatch(device_t parent, cfdata_t cf, void *aux)
ca->ca_type.iodc_sv_model != HPPA_BHA_WAX)
return 0;
/* Make sure we have an IRQ. */
if (ca->ca_irq == HP700CF_IRQ_UNDEF) {
ca->ca_irq = hp700_intr_allocate_bit(&ir_cpu);
}
return 1;
}
@ -119,6 +114,7 @@ waxattach(device_t parent, device_t self, void *aux)
bus_space_handle_t ioh;
int s, in;
ca->ca_irq = hp700_intr_allocate_bit(&ci->ci_ir, ca->ca_irq);
if (ca->ca_irq == HP700CF_IRQ_UNDEF) {
aprint_error(": can't allocate interrupt\n");
return;
@ -149,7 +145,7 @@ waxattach(device_t parent, device_t self, void *aux)
splx(s);
/* Establish the interrupt register. */
hp700_interrupt_register_establish(&sc->sc_ir);
hp700_interrupt_register_establish(ci, &sc->sc_ir);
sc->sc_ir.ir_name = device_xname(self);
sc->sc_ir.ir_mask = &sc->sc_regs->wax_imr;
sc->sc_ir.ir_req = &sc->sc_regs->wax_irr;

View File

@ -1,4 +1,4 @@
/* $NetBSD: gscbus.c,v 1.22 2011/02/01 18:33:24 skrll Exp $ */
/* $NetBSD: gscbus.c,v 1.23 2012/05/23 16:11:37 skrll Exp $ */
/* $OpenBSD: gscbus.c,v 1.13 2001/08/01 20:32:04 miod Exp $ */
@ -68,7 +68,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: gscbus.c,v 1.22 2011/02/01 18:33:24 skrll Exp $");
__KERNEL_RCSID(0, "$NetBSD: gscbus.c,v 1.23 2012/05/23 16:11:37 skrll Exp $");
#define GSCDEBUG
@ -136,6 +136,7 @@ gscattach(device_t parent, device_t self, void *aux)
{
struct gsc_softc *sc = device_private(self);
struct gsc_attach_args *ga = aux;
struct cpu_info *ci = &cpus[0];
sc->sc_dev = self;
sc->sc_ga = *ga;
@ -150,7 +151,7 @@ gscattach(device_t parent, device_t self, void *aux)
/* Add the I/O subsystem's interrupt register. */
ga->ga_ir->ir_name = device_xname(self);
sc->sc_ih = hp700_intr_establish(IPL_NONE, NULL, ga->ga_ir,
&ir_cpu, ga->ga_irq);
&ci->ci_ir, ga->ga_irq);
ga->ga_ca.ca_nmodules = MAXMODBUS;
ga->ga_ca.ca_hpabase = 0;

View File

@ -1,4 +1,4 @@
/* $NetBSD: gscbusvar.h,v 1.10 2011/02/01 18:33:24 skrll Exp $ */
/* $NetBSD: gscbusvar.h,v 1.11 2012/05/23 16:11:37 skrll Exp $ */
/* $OpenBSD: gscbusvar.h,v 1.3 1999/08/16 02:48:39 mickey Exp $ */
@ -28,7 +28,7 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <hp700/hp700/intr.h>
#include <machine/intr.h>
struct gsc_attach_args {
struct confargs ga_ca;

View File

@ -1,4 +1,4 @@
/* $NetBSD: autoconf.c,v 1.46 2012/05/23 11:08:33 skrll Exp $ */
/* $NetBSD: autoconf.c,v 1.47 2012/05/23 16:11:37 skrll Exp $ */
/* $OpenBSD: autoconf.c,v 1.15 2001/06/25 00:43:10 mickey Exp $ */
@ -86,7 +86,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.46 2012/05/23 11:08:33 skrll Exp $");
__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.47 2012/05/23 16:11:37 skrll Exp $");
#include "opt_kgdb.h"
#include "opt_useleds.h"
@ -164,8 +164,6 @@ static void hppa_pdc_system_map_scan(void);
void
cpu_configure(void)
{
struct cpu_info *ci = curcpu();
/*
* Consider stopping for a debugger before
* autoconfiguration.
@ -184,10 +182,8 @@ cpu_configure(void)
if (config_rootfound("mainbus", NULL) == NULL)
panic("no mainbus found");
/* in spl*() we trust */
hp700_intr_init();
hppa_enable_irq();
ci->ci_psw |= PSW_I;
/* Allow interrupts - we're trusting spl* here */
hp700_intr_enable();
spl0();
if (cold_hook)

View File

@ -1,4 +1,4 @@
# $NetBSD: genassym.cf,v 1.33 2012/05/23 11:18:46 skrll Exp $
# $NetBSD: genassym.cf,v 1.34 2012/05/23 16:11:37 skrll Exp $
# $OpenBSD: genassym.cf,v 1.18 2001/09/20 18:31:14 mickey Exp $
@ -64,8 +64,7 @@ include <machine/frame.h>
include <machine/pmap.h>
include <machine/iomod.h>
include <machine/lock.h>
include <hp700/hp700/intr.h>
include <machine/intr.h>
include <hppa/hppa/hpt.h>
@ -88,7 +87,6 @@ export HPPA_BREAK_SET_PSW
struct hp700_interrupt_register
member IR_REQ ir_req
member IR_BITS_MAP ir_bits_map
export IR_BIT_REG
# struct cpu_info fields
define CI_TRAPSAVE offsetof(struct cpu_info, ci_trapsave)
@ -96,6 +94,7 @@ define CI_MTX_COUNT offsetof(struct cpu_info, ci_mtx_count)
define CI_CPL offsetof(struct cpu_info, ci_cpl)
define CI_IPENDING offsetof(struct cpu_info, ci_ipending)
#define CI_INTR_DEPTH offsetof(struct cpu_info, ci_intr_depth)
define CI_IMASK offsetof(struct cpu_info, ci_imask)
#define CI_SOFTLWPS offsetof(struct cpu_info, ci_softlwps)
define CI_PSW offsetof(struct cpu_info, ci_psw)
define CI_FPU_STATE offsetof(struct cpu_info, ci_fpu_state)

View File

@ -1,4 +1,4 @@
/* $NetBSD: intr.c,v 1.40 2012/05/23 11:04:54 skrll Exp $ */
/* $NetBSD: intr.c,v 1.41 2012/05/23 16:11:37 skrll Exp $ */
/* $OpenBSD: intr.c,v 1.27 2009/12/31 12:52:35 jsing Exp $ */
/*
@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.40 2012/05/23 11:04:54 skrll Exp $");
__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.41 2012/05/23 16:11:37 skrll Exp $");
#define __MUTEX_PRIVATE
@ -50,7 +50,6 @@ __KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.40 2012/05/23 11:04:54 skrll Exp $");
#include <machine/intr.h>
#include <machine/reg.h>
#include <hp700/hp700/intr.h>
#include <hp700/hp700/machdep.h>
#include <machine/mutex.h>
@ -59,68 +58,32 @@ __KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.40 2012/05/23 11:04:54 skrll Exp $");
#include "opt_lockdebug.h"
#endif
/* The priority level masks. */
int imask[NIPL];
/* Shared interrupts */
int ishared;
static int hp700_intr_ipl_next(struct cpu_info *);
void hp700_intr_calculatemasks(struct cpu_info *);
int hp700_intr_ipending(struct hp700_interrupt_register *, int);
void hp700_intr_dispatch(int , int , struct trapframe *);
/* The list of all interrupt registers. */
struct hp700_interrupt_register *hp700_interrupt_registers[HP700_INTERRUPT_BITS];
/*
* The array of interrupt handler structures, one per bit.
*/
static struct hp700_interrupt_bit {
/* The interrupt register this bit is in. */
struct hp700_interrupt_register *ib_reg;
/*
* The priority level associated with this bit, e.g, IPL_BIO, IPL_NET,
* etc.
*/
int ib_ipl;
/*
* The spl mask for this bit. This starts out as the spl bit assigned
* to this particular interrupt, and later gets fleshed out by the mask
* calculator to be the full mask that we need to raise spl to when we
* get this interrupt.
*/
int ib_spl;
/* The interrupt name. */
char ib_name[16];
/* The interrupt event count. */
struct evcnt ib_evcnt;
/*
* The interrupt handler and argument for this bit. If the argument is
* NULL, the handler gets the trapframe.
*/
int (*ib_handler)(void *);
void *ib_arg;
} hp700_interrupt_bits[HP700_INTERRUPT_BITS];
/* The CPU interrupt register. */
struct hp700_interrupt_register ir_cpu;
/*
* This establishes a new interrupt register.
*/
void
hp700_interrupt_register_establish(struct hp700_interrupt_register *ir)
hp700_interrupt_register_establish(struct cpu_info *ci,
struct hp700_interrupt_register *ir)
{
int idx;
/* Initialize the register structure. */
memset(ir, 0, sizeof(*ir));
ir->ir_ci = ci;
for (idx = 0; idx < HP700_INTERRUPT_BITS; idx++)
ir->ir_bits_map[idx] = IR_BIT_UNUSED;
ir->ir_bits = ~0;
/* Add this structure to the list. */
for (idx = 0; idx < HP700_INTERRUPT_BITS; idx++)
if (hp700_interrupt_registers[idx] == NULL)
@ -131,17 +94,16 @@ hp700_interrupt_register_establish(struct hp700_interrupt_register *ir)
}
/*
* This bootstraps interrupts.
* This initialise interrupts for a CPU.
*/
void
hp700_intr_bootstrap(void)
hp700_intr_initialise(struct cpu_info *ci)
{
struct cpu_info *ci = curcpu();
int i;
/* Initialize all prority level masks to mask everything. */
for (i = 0; i < NIPL; i++)
imask[i] = -1;
ci->ci_imask[i] = -1;
/* We are now at the highest priority level. */
ci->ci_cpl = -1;
@ -149,18 +111,14 @@ hp700_intr_bootstrap(void)
/* There are no pending interrupts. */
ci->ci_ipending = 0;
/* We are not running an interrupt. */
/* We are not running an interrupt handler. */
ci->ci_intr_depth = 0;
/* There are no interrupt handlers. */
memset(hp700_interrupt_bits, 0, sizeof(hp700_interrupt_bits));
memset(ci->ci_ib, 0, sizeof(ci->ci_ib));
/* There are no interrupt registers. */
memset(hp700_interrupt_registers, 0, sizeof(hp700_interrupt_registers));
/* Initialize the CPU interrupt register description. */
hp700_interrupt_register_establish(&ir_cpu);
ir_cpu.ir_name = "cpu0";
}
/*
@ -171,6 +129,7 @@ hp700_intr_establish(int ipl, int (*handler)(void *), void *arg,
struct hp700_interrupt_register *ir, int bit_pos)
{
struct hp700_interrupt_bit *ib;
struct cpu_info *ci = ir->ir_ci;
int idx;
/* Panic on a bad interrupt bit. */
@ -182,38 +141,44 @@ hp700_intr_establish(int ipl, int (*handler)(void *), void *arg,
* shared interrupts for cascaded registers, e.g. dino and gsc
* XXX This could be improved.
*/
if (ir->ir_bits_map[31 ^ bit_pos] != IR_BIT_UNUSED &&
!IR_BIT_NESTED_P(ir->ir_bits_map[31 ^ bit_pos]) &&
handler == NULL)
panic("%s: int already handled", __func__);
if (handler != NULL) {
if (IR_BIT_USED_P(ir->ir_bits_map[31 ^ bit_pos]))
panic("%s: interrupt already handled", __func__);
}
/*
* If this interrupt bit leads us to another interrupt register,
* simply note that in the mapping for the bit.
*/
if (handler == NULL) {
for (idx = 0; idx < HP700_INTERRUPT_BITS; idx++)
for (idx = 1; idx < HP700_INTERRUPT_BITS; idx++)
if (hp700_interrupt_registers[idx] == arg)
break;
if (idx == HP700_INTERRUPT_BITS)
panic("%s: unknown int reg", __func__);
ir->ir_bits_map[31 ^ bit_pos] = IR_BIT_REG | idx;
ir->ir_bits_map[31 ^ bit_pos] = IR_BIT_REG(idx);
return NULL;
}
/*
* Otherwise, allocate a new bit in the spl.
*/
idx = _hp700_intr_ipl_next();
idx = hp700_intr_ipl_next(ir->ir_ci);
ir->ir_bits &= ~(1 << bit_pos);
if (ir->ir_bits_map[31 ^ bit_pos] == IR_BIT_UNUSED)
ir->ir_rbits &= ~(1 << bit_pos);
if (!IR_BIT_USED_P(ir->ir_bits_map[31 ^ bit_pos])) {
ir->ir_bits_map[31 ^ bit_pos] = 1 << idx;
else {
} else {
int j;
ir->ir_bits_map[31 ^ bit_pos] |= 1 << idx;
ishared |= ir->ir_bits_map[31 ^ bit_pos];
j = (ir - hp700_interrupt_registers[0]);
ci->ci_ishared |= (1 << j);
}
ib = &hp700_interrupt_bits[idx];
ib = &ci->ci_ib[idx];
/* Fill this interrupt bit. */
ib->ib_reg = ir;
@ -226,6 +191,8 @@ hp700_intr_establish(int ipl, int (*handler)(void *), void *arg,
ib->ib_handler = handler;
ib->ib_arg = arg;
hp700_intr_calculatemasks(ci);
return ib;
}
@ -234,32 +201,45 @@ hp700_intr_establish(int ipl, int (*handler)(void *), void *arg,
* It returns the bit position, or -1 if no bits were available.
*/
int
hp700_intr_allocate_bit(struct hp700_interrupt_register *ir)
hp700_intr_allocate_bit(struct hp700_interrupt_register *ir, int irq)
{
int bit_pos;
int last_bit;
u_int mask;
int *bits;
for (bit_pos = 31, mask = (1 << bit_pos);
bit_pos >= 0;
bit_pos--, mask >>= 1)
if (ir->ir_bits & mask)
if (irq == -1) {
bit_pos = 31;
last_bit = 0;
bits = &ir->ir_bits;
} else {
bit_pos = irq;
last_bit = irq;
bits = &ir->ir_rbits;
}
for (mask = (1 << bit_pos); bit_pos >= last_bit; bit_pos--) {
if (*bits & mask)
break;
if (bit_pos >= 0)
ir->ir_bits &= ~mask;
mask >>= 1;
}
if (bit_pos >= last_bit) {
*bits &= ~mask;
return bit_pos;
}
return bit_pos;
return -1;
}
/*
* This returns the next available spl bit. This is not intended for wide use.
* This returns the next available spl bit.
*/
int
_hp700_intr_ipl_next(void)
static int
hp700_intr_ipl_next(struct cpu_info *ci)
{
int idx;
for (idx = 0; idx < HP700_INTERRUPT_BITS; idx++)
if (hp700_interrupt_bits[idx].ib_reg == NULL)
if (ci->ci_ib[idx].ib_reg == NULL)
break;
if (idx == HP700_INTERRUPT_BITS)
panic("%s: too many devices", __func__);
@ -270,92 +250,74 @@ _hp700_intr_ipl_next(void)
* This finally initializes interrupts.
*/
void
hp700_intr_init(void)
hp700_intr_calculatemasks(struct cpu_info *ci)
{
struct hp700_interrupt_bit *ib;
struct hp700_interrupt_register *ir;
struct cpu_info *ci = curcpu();
int idx, bit_pos;
int mask;
int eiem;
int ipl;
/*
* Put together the initial imask for each level.
*/
memset(imask, 0, sizeof(imask));
memset(ci->ci_imask, 0, sizeof(ci->ci_imask));
for (bit_pos = 0; bit_pos < HP700_INTERRUPT_BITS; bit_pos++) {
ib = hp700_interrupt_bits + bit_pos;
ib = &ci->ci_ib[bit_pos];
if (ib->ib_reg == NULL)
continue;
imask[ib->ib_ipl] |= ib->ib_spl;
ci->ci_imask[ib->ib_ipl] |= ib->ib_spl;
}
/* The following bits cribbed from i386/isa/isa_machdep.c: */
/*
* IPL_NONE is used for hardware interrupts that are never blocked,
* and do not block anything else.
*/
imask[IPL_NONE] = 0;
ci->ci_imask[IPL_NONE] = 0;
/*
* Enforce a hierarchy that gives slow devices a better chance at not
* dropping data.
*/
imask[IPL_SOFTCLOCK] |= imask[IPL_NONE];
imask[IPL_SOFTBIO] |= imask[IPL_SOFTCLOCK];
imask[IPL_SOFTNET] |= imask[IPL_SOFTBIO];
imask[IPL_SOFTSERIAL] |= imask[IPL_SOFTNET];
imask[IPL_VM] |= imask[IPL_SOFTSERIAL];
imask[IPL_SCHED] |= imask[IPL_VM];
imask[IPL_HIGH] |= imask[IPL_SCHED];
/* Now go back and flesh out the spl levels on each bit. */
for (bit_pos = 0; bit_pos < HP700_INTERRUPT_BITS; bit_pos++) {
ib = hp700_interrupt_bits + bit_pos;
if (ib->ib_reg == NULL)
continue;
ib->ib_spl = imask[ib->ib_ipl];
}
/* Print out the levels. */
printf("vmmask %08x schedmask %08x highmask %08x\n",
imask[IPL_VM], imask[IPL_SCHED], imask[IPL_HIGH]);
#if 0
for (bit_pos = 0; bit_pos < NIPL; bit_pos++)
printf("imask[%d] == %08x\n", bit_pos, imask[bit_pos]);
#endif
for (ipl = NIPL - 1; ipl > 0; ipl--)
ci->ci_imask[ipl - 1] |= ci->ci_imask[ipl];
/*
* Load all mask registers, loading %eiem last. This will finally
* enable interrupts, but since cpl and ipending should be -1 and 0,
* respectively, no interrupts will get dispatched until the priority
* level is lowered.
*
* Because we're paranoid, we force these values for cpl and ipending,
* even though they should be unchanged since hp700_intr_bootstrap().
*/
ci->ci_cpl = -1;
ci->ci_ipending = 0;
eiem = 0;
KASSERT(ci->ci_cpl == -1);
KASSERT(ci->ci_ipending == 0);
for (idx = 0; idx < HP700_INTERRUPT_BITS; idx++) {
ir = hp700_interrupt_registers[idx];
if (ir == NULL)
if (ir == NULL || ir->ir_ci != ci)
continue;
mask = 0;
for (bit_pos = 0; bit_pos < HP700_INTERRUPT_BITS; bit_pos++) {
if (ir->ir_bits_map[31 ^ bit_pos] !=
IR_BIT_UNUSED)
if (IR_BIT_USED_P(ir->ir_bits_map[31 ^ bit_pos]))
mask |= (1 << bit_pos);
}
if (ir == &ir_cpu)
eiem = mask;
if (ir->ir_iscpu)
ir->ir_ci->ci_eiem = mask;
else if (ir->ir_mask != NULL)
*ir->ir_mask = mask;
}
mtctl(eiem, CR_EIEM);
}
void
hp700_intr_enable(void)
{
struct cpu_info *ci = curcpu();
mtctl(ci->ci_eiem, CR_EIEM);
ci->ci_psw |= PSW_I;
hppa_enable_irq();
}
/*
* Service interrupts. This doesn't necessarily dispatch them. This is called
* with %eiem loaded with zero. It's named hppa_intr instead of hp700_intr
@ -364,13 +326,9 @@ hp700_intr_init(void)
void
hppa_intr(struct trapframe *frame)
{
int eirr;
int ipending_new;
int pending;
int i;
struct hp700_interrupt_register *ir;
int hp700_intr_ipending_new(struct hp700_interrupt_register *, int);
struct cpu_info *ci = curcpu();
int eirr;
int i;
#ifndef LOCKDEBUG
extern char mutex_enter_crit_start[];
@ -409,36 +367,32 @@ hppa_intr(struct trapframe *frame)
mfctl(CR_EIRR, eirr);
mtctl(eirr, CR_EIRR);
ci->ci_ipending |= hp700_intr_ipending_new(&ir_cpu, eirr);
ci->ci_ipending |= hp700_intr_ipending(&ci->ci_ir, eirr);
i = 0;
/* If we have interrupts to dispatch, do so. */
if (ci->ci_ipending & ~ci->ci_cpl)
while (ci->ci_ipending & ~ci->ci_cpl) {
int shared;
hp700_intr_dispatch(ci->ci_cpl, frame->tf_eiem, frame);
/* We are done if there are no shared interrupts. */
if (ishared == 0)
return;
shared = ci->ci_ishared;
while (shared) {
struct hp700_interrupt_register *sir;
int sbit, lvl;
for (i = 0; i < HP700_INTERRUPT_BITS; i++) {
ir = hp700_interrupt_registers[i];
if (ir == NULL || ir->ir_level == NULL)
continue;
/*
* For shared interrupts look if the interrupt line is still
* asserted. If it is, reschedule the corresponding interrupt.
*/
ipending_new = *ir->ir_level;
while (ipending_new != 0) {
pending = ffs(ipending_new) - 1;
ci->ci_ipending |=
ir->ir_bits_map[31 ^ pending] & ishared;
ipending_new &= ~(1 << pending);
sbit = ffs(shared) - 1;
sir = hp700_interrupt_registers[sbit];
lvl = *sir->ir_level;
ci->ci_ipending |= hp700_intr_ipending(sir, lvl);
shared &= ~(1 << sbit);
}
i++;
KASSERTMSG(i <= 2,
"%s: ci->ipending %08x ci->ci_cpl %08x shared %08x\n",
__func__, ci->ci_ipending, ci->ci_cpl, shared);
}
/* If we still have interrupts to dispatch, do so. */
if (ci->ci_ipending & ~ci->ci_cpl)
hp700_intr_dispatch(ci->ci_cpl, frame->tf_eiem, frame);
}
/*
@ -449,16 +403,18 @@ void
hp700_intr_dispatch(int ncpl, int eiem, struct trapframe *frame)
{
struct cpu_info *ci = curcpu();
int ipending_run;
u_int old_hppa_intr_depth;
int bit_pos;
struct hp700_interrupt_bit *ib;
void *arg;
struct clockframe clkframe;
int ipending_run;
int bit_pos;
void *arg;
int handled;
bool locked = false;
/* Increment our depth, grabbing the previous value. */
old_hppa_intr_depth = ci->ci_intr_depth++;
/*
* Increment our depth
*/
ci->ci_intr_depth++;
/* Loop while we have interrupts to dispatch. */
for (;;) {
@ -475,12 +431,12 @@ hp700_intr_dispatch(int ncpl, int eiem, struct trapframe *frame)
* If this interrupt handler takes the clockframe
* as an argument, conjure one up.
*/
ib = &hp700_interrupt_bits[bit_pos];
ib = &ci->ci_ib[bit_pos];
ib->ib_evcnt.ev_count++;
arg = ib->ib_arg;
if (arg == NULL) {
clkframe.cf_flags = (old_hppa_intr_depth ?
TFF_INTR : 0);
clkframe.cf_flags = (ci->ci_intr_depth ?
TFF_INTR : 0);
clkframe.cf_spl = ncpl;
if (frame != NULL) {
clkframe.cf_flags |= frame->tf_flags;
@ -495,9 +451,14 @@ hp700_intr_dispatch(int ncpl, int eiem, struct trapframe *frame)
* and reenable interrupts.
*/
ci->ci_ipending &= ~(1 << bit_pos);
ci->ci_cpl = ncpl | ib->ib_spl;
ci->ci_cpl = ncpl | ci->ci_imask[ib->ib_ipl];
mtctl(eiem, CR_EIEM);
if (ib->ib_ipl == IPL_VM) {
KERNEL_LOCK(1, NULL);
locked = true;
}
/* Count and dispatch the interrupt. */
ci->ci_data.cpu_nintr++;
handled = (*ib->ib_handler)(arg);
@ -506,14 +467,43 @@ hp700_intr_dispatch(int ncpl, int eiem, struct trapframe *frame)
printf("%s: can't handle interrupt\n",
ib->ib_evcnt.ev_name);
#endif
if (locked) {
KERNEL_UNLOCK_ONE(NULL);
locked = false;
}
/* Disable interrupts and loop. */
mtctl(0, CR_EIEM);
}
/* Interrupts are disabled again, restore cpl and the depth. */
ci->ci_cpl = ncpl;
ci->ci_intr_depth = old_hppa_intr_depth;
ci->ci_intr_depth--;
}
int
hp700_intr_ipending(struct hp700_interrupt_register *ir, int eirr)
{
int pending = 0;
int idx;
for (idx = 31; idx >= 0; idx--) {
if ((eirr & (1 << idx)) == 0)
continue;
if (IR_BIT_NESTED_P(ir->ir_bits_map[31 ^ idx])) {
struct hp700_interrupt_register *nir;
int reg = ir->ir_bits_map[31 ^ idx] & ~IR_BIT_MASK;
nir = hp700_interrupt_registers[reg];
pending |= hp700_intr_ipending(nir, *(nir->ir_req));
} else {
pending |= ir->ir_bits_map[31 ^ idx];
}
}
return pending;
}
bool

View File

@ -1,96 +0,0 @@
/* $NetBSD: intr.h,v 1.15 2011/02/01 18:33:25 skrll Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Matthew Fredette.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* The maximum number of bits in a cpl value/spl mask, the maximum number of
* bits in an interrupt request register, and the maximum number of interrupt
* registers.
*/
#define HP700_INTERRUPT_BITS (32)
#define CPU_NINTS HP700_INTERRUPT_BITS /* Use this one */
/*
* This describes one HP700 interrupt register.
*/
struct hp700_interrupt_register {
/*
* The device name for this interrupt register.
*/
const char *ir_name;
/*
* The virtual address of the mask, request and level
* registers.
*/
volatile int *ir_mask;
volatile int *ir_req;
volatile int *ir_level;
/*
* This array has one entry for each bit in the interrupt request
* register.
*
* If the 24 most significant bits are set, the low 8 bits are the
* index of the hp700_interrupt_register that this interrupt bit leads
* to, with zero meaning that the interrupt bit is unused.
*
* Otherwise these bits correspond to hp700_int_bits. That is, these
* bits are ORed to ipending_new in hp700_intr_ipending_new() when an
* interrupt happens.
*
* Note that this array is indexed by HP bit number, *not* by "normal"
* bit number. In other words, the least significant bit in the inter-
* rupt register corresponds to array index 31.
*/
unsigned int ir_bits_map[HP700_INTERRUPT_BITS];
#define IR_BIT_REG 0xffffff00
#define IR_BIT_UNUSED IR_BIT_REG
#define IR_BIT_NESTED_P(x) (((x) & ~IR_BIT_UNUSED) != 0)
/*
* The mask of allocatable bit numbers.
*/
int ir_bits;
};
extern struct hp700_interrupt_register ir_cpu;
void hp700_intr_bootstrap(void);
void hp700_interrupt_register_establish(struct hp700_interrupt_register *);
void * hp700_intr_establish(int, int (*)(void *), void *,
struct hp700_interrupt_register *, int);
int hp700_intr_allocate_bit(struct hp700_interrupt_register *);
int _hp700_intr_ipl_next(void);
void hp700_intr_init(void);
void hp700_intr_dispatch(int, int, struct trapframe *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: locore.S,v 1.60 2012/04/06 12:21:59 skrll Exp $ */
/* $NetBSD: locore.S,v 1.61 2012/05/23 16:11:37 skrll Exp $ */
/* $OpenBSD: locore.S,v 1.158 2008/07/28 19:08:46 miod Exp $ */
/*
@ -64,15 +64,13 @@
#include <sys/errno.h>
#include <machine/param.h>
#include <machine/cpu.h>
#include <machine/asm.h>
#include <machine/psl.h>
#include <machine/trap.h>
#include <machine/iomod.h>
#include <machine/pdc.h>
#include <machine/intr.h>
#include <machine/frame.h>
#include <machine/reg.h>
#include <machine/cpu.h>
#include "assym.h"
@ -657,6 +655,8 @@ EXIT(pdc_call)
*/
LEAF_ENTRY(splraise)
GET_CURCPU(%t1)
sh2addl %arg0, %t1, %arg0
ldw CI_IMASK(%arg0), %arg0
ldw CI_CPL(%t1), %ret0
or %ret0, %arg0, %arg0
bv %r0(%rp)
@ -745,110 +745,6 @@ ENTRY(hp700_intr_schedule,0)
mtctl %arg1, %eiem
EXIT(hp700_intr_schedule)
/*
*
* int hp700_intr_ipending_new(struct hp700_int_reg *int_reg, int int_req);
*
* This assembles the mask of new pending interrupts.
*
*/
ENTRY(hp700_intr_ipending_new,HPPA_FRAME_SIZE)
/* Start stack calling convention. */
stw %rp, HPPA_FRAME_CRP(%sp)
copy %r3, %r1
copy %sp, %r3
stw,ma %r1, HPPA_FRAME_SIZE(%sp)
/*
* Get this interrupt register's interrupt bits map
* and start with the least significant bit and with
* a zero ipending_new value.
*/
ldo IR_BITS_MAP(%arg0), %arg0
ldi 31, %arg2
copy %r0, %ret0
/*
* The top of this loop finds the next set bit in
* the request register. Note that if the bvb does
* not branch, the addib is nullified, and control
* falls out of the loop. If the bvb does branch,
* the addib runs with the mtsar in its delay slot.
* If the addib branches, the mtsar is nullified.
*/
L$hp700_inew_loop:
mtsar %arg2
bvb,>=,n %arg1, L$hp700_inew_loop
addib,<,n -1, %arg2, L$hp700_inew_done
/*
* If the map entry for this bit has IR_BIT_REG
* set, branch to descend into the next interrupt
* register. Otherwise, set the bits in our ipending_new
* value and loop.
*/
ldwx,s %arg2(%arg0), %t1
ldil L%IR_BIT_REG, %t2
ldo R%IR_BIT_REG(%t2), %t2
and %t1, %t2, %t3
combt,=,n %t2, %t3, L$hp700_inew_descend
addib,>= -1, %arg2, L$hp700_inew_loop
or %t1, %ret0, %ret0
L$hp700_inew_done:
/* End stack calling convention. */
ldw HPPA_FRAME_CRP(%r3), %rp
ldo HPPA_FRAME_SIZE(%r3), %sp
bv %r0(%rp)
ldw,mb -HPPA_FRAME_SIZE(%sp), %r3
L$hp700_inew_descend:
/*
* If the next interrupt register index is zero,
* this interrupt bit is unused. (Index zero
* is the CPU interrupt register, which you can
* never descend into since it's the root.)
*/
andcm,<> %t1, %t2, %t1
b,n L$hp700_inew_unused
/* Save our state. */
stw %arg0, HPPA_FRAME_ARG(0)(%r3)
stw %arg1, HPPA_FRAME_ARG(1)(%r3)
stw %arg2, HPPA_FRAME_ARG(2)(%r3)
stw %ret0, HPPA_FRAME_ARG(3)(%r3)
/* Get our new interrupt register. */
ldil L%hp700_interrupt_registers, %arg0
ldo R%hp700_interrupt_registers(%arg0), %arg0
sh2add %t1, %arg0, %arg0
ldw 0(%arg0), %arg0
/*
* Read the interrupt request register and make
* our recursive call. The read also serves to
* acknowledge the interrupt to the I/O subsystem.
*/
ldw IR_REQ(%arg0), %arg1
bl hp700_intr_ipending_new, %rp
ldw 0(%arg1), %arg1
/* Restore our state. */
ldw HPPA_FRAME_ARG(0)(%r3), %arg0
ldw HPPA_FRAME_ARG(1)(%r3), %arg1
ldw HPPA_FRAME_ARG(2)(%r3), %arg2
ldw HPPA_FRAME_ARG(3)(%r3), %ret1
or %ret1, %ret0, %ret0
L$hp700_inew_unused:
addib,>= -1, %arg2, L$hp700_inew_loop
nop
b,n L$hp700_inew_done
EXIT(hp700_intr_ipending_new)
/*
* void cpu_die(void);
*/

View File

@ -1,4 +1,4 @@
/* $NetBSD: machdep.c,v 1.112 2012/05/23 08:59:36 skrll Exp $ */
/* $NetBSD: machdep.c,v 1.113 2012/05/23 16:11:37 skrll Exp $ */
/*-
* Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
@ -58,7 +58,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.112 2012/05/23 08:59:36 skrll Exp $");
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.113 2012/05/23 16:11:37 skrll Exp $");
#include "opt_cputype.h"
#include "opt_ddb.h"
@ -121,7 +121,6 @@ __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.112 2012/05/23 08:59:36 skrll Exp $");
#include <ddb/db_extern.h>
#endif
#include <hp700/hp700/intr.h>
#include <hp700/hp700/machdep.h>
#include <hp700/hp700/pim.h>
#include <hp700/dev/cpudevs.h>
@ -588,7 +587,7 @@ do { \
DPRINTF(("%s: intr bootstrap\n", __func__));
/* Bootstrap interrupt masking and dispatching. */
hp700_intr_bootstrap();
hp700_intr_initialise(ci);
/*
* Initialize any debugger.

View File

@ -1,4 +1,4 @@
/* $NetBSD: mainbus.c,v 1.82 2012/04/03 12:07:26 skrll Exp $ */
/* $NetBSD: mainbus.c,v 1.83 2012/05/23 16:11:37 skrll Exp $ */
/*-
* Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
@ -58,7 +58,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.82 2012/04/03 12:07:26 skrll Exp $");
__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.83 2012/05/23 16:11:37 skrll Exp $");
#include "locators.h"
#include "power.h"
@ -80,7 +80,6 @@ __KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.82 2012/04/03 12:07:26 skrll Exp $");
#include <machine/autoconf.h>
#include <hp700/hp700/machdep.h>
#include <hp700/hp700/intr.h>
#include <hp700/dev/cpudevs.h>
#if NLCD > 0
@ -1474,9 +1473,6 @@ mbprint(void *aux, const char *pnp)
}
if (!pnp && ca->ca_irq >= 0) {
aprint_normal(" irq %d", ca->ca_irq);
if (ca->ca_type.iodc_type != HPPA_TYPE_BHA)
aprint_normal(" ipl %d",
_hp700_intr_ipl_next());
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.h,v 1.69 2012/04/05 21:00:29 skrll Exp $ */
/* $NetBSD: cpu.h,v 1.70 2012/05/23 16:11:37 skrll Exp $ */
/* $OpenBSD: cpu.h,v 1.55 2008/07/23 17:39:35 kettenis Exp $ */
@ -60,6 +60,11 @@
#include <machine/trap.h>
#include <machine/frame.h>
#include <machine/reg.h>
#include <machine/intrdefs.h>
#ifndef __ASSEMBLER__
#include <machine/intr.h>
#endif
#ifndef _LOCORE
@ -243,9 +248,11 @@ int clock_intr(void *);
#endif /* _KERNEL */
#ifndef __ASSEMBLER__
#if defined(_KERNEL) || defined(_KMEMUSER)
#include <sys/cpu_data.h>
#include <sys/evcnt.h>
/*
* Note that the alignment of ci_trap_save is important since we want to keep
@ -259,6 +266,11 @@ struct cpu_info {
struct cpu_data ci_data; /* MI per-cpu data */
#ifndef _KMEMUSER
hppa_hpa_t ci_hpa;
register_t ci_psw; /* Processor Status Word. */
paddr_t ci_fpu_state; /* LWP FPU state address, or zero. */
u_long ci_itmr;
int ci_cpuid; /* CPU index (see cpus[] array) */
int ci_mtx_count;
int ci_mtx_oldspl;
@ -267,12 +279,14 @@ struct cpu_info {
volatile int ci_cpl;
volatile int ci_ipending; /* The pending interrupts. */
u_int ci_intr_depth; /* Nonzero iff running an interrupt. */
u_int ci_ishared;
u_int ci_eiem;
hppa_hpa_t ci_hpa;
register_t ci_psw; /* Processor Status Word. */
paddr_t ci_fpu_state; /* LWP FPU state address, or zero. */
u_long ci_itmr;
u_int ci_imask[NIPL];
struct hp700_interrupt_register ci_ir;
struct hp700_interrupt_bit ci_ib[HP700_INTERRUPT_BITS];
#if defined(MULTIPROCESSOR)
struct lwp *ci_curlwp; /* CPU owner */
paddr_t ci_stack; /* stack for spin up */
@ -289,6 +303,7 @@ struct cpu_info {
} __aligned(64);
#endif /* _KERNEL || _KMEMUSER */
#endif /* __ASSEMBLER__ */
#if defined(_KERNEL)

View File

@ -1,4 +1,4 @@
/* $NetBSD: intr.h,v 1.21 2012/04/05 21:00:29 skrll Exp $ */
/* $NetBSD: intr.h,v 1.22 2012/05/23 16:11:37 skrll Exp $ */
/* $OpenBSD: intr.h,v 1.26 2009/12/29 13:11:40 jsing Exp $ */
/*-
@ -36,12 +36,113 @@
#include <machine/psl.h>
#include <machine/intrdefs.h>
#include <sys/evcnt.h>
#ifndef _LOCORE
#ifdef _KERNEL
/* The priority level masks. */
extern int imask[NIPL];
struct cpu_info;
/*
* The maximum number of bits in a cpl value/spl mask, the maximum number of
* bits in an interrupt request register, and the maximum number of interrupt
* registers.
*/
#define HP700_INTERRUPT_BITS (32)
#define CPU_NINTS HP700_INTERRUPT_BITS /* Use this one */
/*
* This describes one HP700 interrupt register.
*/
struct hp700_interrupt_register {
bool ir_iscpu;
const char *ir_name; /* name for this intr reg */
struct cpu_info *ir_ci; /* cpu this intr reg */
/*
* The virtual address of the mask, request and level
* registers.
*/
volatile int *ir_mask;
volatile int *ir_req;
volatile int *ir_level;
/*
* This array has one entry for each bit in the interrupt request
* register.
*
* If the 24 most significant bits are set, the low 8 bits are the
* index of the hp700_interrupt_register that this interrupt bit leads
* to, with zero meaning that the interrupt bit is unused.
*
* Otherwise these bits correspond to hp700_interrupt_bits. That is,
* these bits are ORed to ipending_new in hp700_intr_ipending() when
* an interrupt happens.
*
* Note that this array is indexed by HP bit number, *not* by "normal"
* bit number. In other words, the least significant bit in the inter-
* rupt register corresponds to array index 31.
*/
unsigned int ir_bits_map[HP700_INTERRUPT_BITS];
#define IR_BIT_MASK 0xffffff00
#define IR_BIT_REG(x) (IR_BIT_MASK | (x))
#define IR_BIT_UNUSED IR_BIT_REG(0)
#define IR_BIT_USED_P(x) (((x) & IR_BIT_MASK) != IR_BIT_MASK)
#define IR_BIT_NESTED_P(x) (((x) & IR_BIT_MASK) == IR_BIT_MASK)
int ir_bits; /* mask of allocatable bit numbers */
int ir_rbits; /* mask of reserved (for lasi/asp) bit numbers */
};
struct hp700_interrupt_bit {
/*
* The interrupt register this bit is in. Some handlers, e.g
* apic_intr, don't make use of an hp700_interrupt_register, but are
* nested.
*/
struct hp700_interrupt_register *ib_reg;
/*
* The priority level associated with this bit, e.g, IPL_BIO, IPL_NET,
* etc.
*/
int ib_ipl;
/*
* The spl mask for this bit. This starts out as the spl bit assigned
* to this particular interrupt, and later gets fleshed out by the mask
* calculator to be the full mask that we need to raise spl to when we
* get this interrupt.
*/
int ib_spl;
/* The interrupt name. */
char ib_name[16];
/* The interrupt event count. */
struct evcnt ib_evcnt;
/*
* The interrupt handler and argument for this bit. If the argument is
* NULL, the handler gets the trapframe.
*/
int (*ib_handler)(void *);
void *ib_arg;
};
void hp700_intr_bootstrap(void);
void hp700_intr_initialise(struct cpu_info *);
void hp700_interrupt_register_establish(struct cpu_info *,
struct hp700_interrupt_register *);
void * hp700_intr_establish(int, int (*)(void *), void *,
struct hp700_interrupt_register *, int);
int hp700_intr_allocate_bit(struct hp700_interrupt_register *, int);
void hp700_intr_enable(void);
/* splraise()/spllower() are in locore.S */
int splraise(int);
@ -69,7 +170,7 @@ static inline int
splraiseipl(ipl_cookie_t icookie)
{
return splraise(imask[icookie._ipl]);
return splraise(icookie._ipl);
}
#include <sys/spl.h>