diff --git a/sys/arch/hp700/conf/GENERIC b/sys/arch/hp700/conf/GENERIC index e2fa9550a6ad..2a00841fae03 100644 --- a/sys/arch/hp700/conf/GENERIC +++ b/sys/arch/hp700/conf/GENERIC @@ -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 diff --git a/sys/arch/hp700/dev/apic.c b/sys/arch/hp700/dev/apic.c index aac2117fad5d..f460dd482921 100644 --- a/sys/arch/hp700/dev/apic.c +++ b/sys/arch/hp700/dev/apic.c @@ -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 #include -#include - #include #include #include @@ -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); diff --git a/sys/arch/hp700/dev/asp.c b/sys/arch/hp700/dev/asp.c index c9afbf53c5aa..a9ea678cc2bf 100644 --- a/sys/arch/hp700/dev/asp.c +++ b/sys/arch/hp700/dev/asp.c @@ -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 -__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 #include @@ -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) { diff --git a/sys/arch/hp700/dev/cpu.c b/sys/arch/hp700/dev/cpu.c index 09232a67a180..9cf5ff168b9f 100644 --- a/sys/arch/hp700/dev/cpu.c +++ b/sys/arch/hp700/dev/cpu.c @@ -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 -__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 #include -#include #include #include @@ -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) diff --git a/sys/arch/hp700/dev/dino.c b/sys/arch/hp700/dev/dino.c index 106e87761549..740298b595f8 100644 --- a/sys/arch/hp700/dev/dino.c +++ b/sys/arch/hp700/dev/dino.c @@ -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 -__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 #include #include -#include #include #include @@ -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 */ diff --git a/sys/arch/hp700/dev/lasi.c b/sys/arch/hp700/dev/lasi.c index 8419aa79c248..60b58e915bbb 100644 --- a/sys/arch/hp700/dev/lasi.c +++ b/sys/arch/hp700/dev/lasi.c @@ -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 -__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 */ diff --git a/sys/arch/hp700/dev/mongoose.c b/sys/arch/hp700/dev/mongoose.c index 25fe4386354a..59a949320ed8 100644 --- a/sys/arch/hp700/dev/mongoose.c +++ b/sys/arch/hp700/dev/mongoose.c @@ -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 -__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 #include -#include #include #include @@ -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); } diff --git a/sys/arch/hp700/dev/power.c b/sys/arch/hp700/dev/power.c index cb50fd74cfd1..56ed775017b8 100644 --- a/sys/arch/hp700/dev/power.c +++ b/sys/arch/hp700/dev/power.c @@ -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 #include -#include #include #include diff --git a/sys/arch/hp700/dev/siop_sgc.c b/sys/arch/hp700/dev/siop_sgc.c index 95c334fd1669..df9b2fb9a415 100644 --- a/sys/arch/hp700/dev/siop_sgc.c +++ b/sys/arch/hp700/dev/siop_sgc.c @@ -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 -__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 #include @@ -40,7 +40,6 @@ __KERNEL_RCSID(0, "$NetBSD: siop_sgc.c,v 1.9 2012/04/03 12:07:26 skrll Exp $"); #include #include -#include #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); } diff --git a/sys/arch/hp700/dev/wax.c b/sys/arch/hp700/dev/wax.c index cccbfe9afe20..fdbfb71cb700 100644 --- a/sys/arch/hp700/dev/wax.c +++ b/sys/arch/hp700/dev/wax.c @@ -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 -__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 #include @@ -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; diff --git a/sys/arch/hp700/gsc/gscbus.c b/sys/arch/hp700/gsc/gscbus.c index 75d5c08e1c2a..8a8964c65c82 100644 --- a/sys/arch/hp700/gsc/gscbus.c +++ b/sys/arch/hp700/gsc/gscbus.c @@ -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 -__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; diff --git a/sys/arch/hp700/gsc/gscbusvar.h b/sys/arch/hp700/gsc/gscbusvar.h index aaa8304168b8..888126e58d1c 100644 --- a/sys/arch/hp700/gsc/gscbusvar.h +++ b/sys/arch/hp700/gsc/gscbusvar.h @@ -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 +#include struct gsc_attach_args { struct confargs ga_ca; diff --git a/sys/arch/hp700/hp700/autoconf.c b/sys/arch/hp700/hp700/autoconf.c index 996bbcc18fdf..2b8a8b940012 100644 --- a/sys/arch/hp700/hp700/autoconf.c +++ b/sys/arch/hp700/hp700/autoconf.c @@ -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 -__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) diff --git a/sys/arch/hp700/hp700/genassym.cf b/sys/arch/hp700/hp700/genassym.cf index 738047cd4f26..883a4b883f9f 100644 --- a/sys/arch/hp700/hp700/genassym.cf +++ b/sys/arch/hp700/hp700/genassym.cf @@ -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 include include include - -include +include include @@ -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) diff --git a/sys/arch/hp700/hp700/intr.c b/sys/arch/hp700/hp700/intr.c index 79c4591de8a2..06f5a9be1977 100644 --- a/sys/arch/hp700/hp700/intr.c +++ b/sys/arch/hp700/hp700/intr.c @@ -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 -__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 #include -#include #include #include @@ -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 diff --git a/sys/arch/hp700/hp700/intr.h b/sys/arch/hp700/hp700/intr.h deleted file mode 100644 index 48d6ba3aec50..000000000000 --- a/sys/arch/hp700/hp700/intr.h +++ /dev/null @@ -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 *); diff --git a/sys/arch/hp700/hp700/locore.S b/sys/arch/hp700/hp700/locore.S index 0e7912dcb758..30feaeb1bc6b 100644 --- a/sys/arch/hp700/hp700/locore.S +++ b/sys/arch/hp700/hp700/locore.S @@ -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 #include -#include #include #include #include #include #include -#include -#include #include +#include #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); */ diff --git a/sys/arch/hp700/hp700/machdep.c b/sys/arch/hp700/hp700/machdep.c index 5f618f11169d..16876a14469d 100644 --- a/sys/arch/hp700/hp700/machdep.c +++ b/sys/arch/hp700/hp700/machdep.c @@ -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 -__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 #endif -#include #include #include #include @@ -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. diff --git a/sys/arch/hp700/hp700/mainbus.c b/sys/arch/hp700/hp700/mainbus.c index f819eb5bc338..5bd549992910 100644 --- a/sys/arch/hp700/hp700/mainbus.c +++ b/sys/arch/hp700/hp700/mainbus.c @@ -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 -__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 #include -#include #include #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()); } } diff --git a/sys/arch/hp700/include/cpu.h b/sys/arch/hp700/include/cpu.h index f486ffc3cb2d..a30cefa2dff3 100644 --- a/sys/arch/hp700/include/cpu.h +++ b/sys/arch/hp700/include/cpu.h @@ -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 #include #include +#include + +#ifndef __ASSEMBLER__ +#include +#endif #ifndef _LOCORE @@ -243,9 +248,11 @@ int clock_intr(void *); #endif /* _KERNEL */ +#ifndef __ASSEMBLER__ #if defined(_KERNEL) || defined(_KMEMUSER) #include +#include /* * 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) diff --git a/sys/arch/hp700/include/intr.h b/sys/arch/hp700/include/intr.h index 8c08706b4d3d..165670dbd05b 100644 --- a/sys/arch/hp700/include/intr.h +++ b/sys/arch/hp700/include/intr.h @@ -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 #include +#include + #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