summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/ia64/ia64/interrupt.c119
-rw-r--r--sys/ia64/ia64/nexus.c1
-rw-r--r--sys/ia64/ia64/sapic.c154
-rw-r--r--sys/ia64/include/intr.h20
-rw-r--r--sys/ia64/include/sapicreg.h48
-rw-r--r--sys/ia64/include/sapicvar.h65
6 files changed, 180 insertions, 227 deletions
diff --git a/sys/ia64/ia64/interrupt.c b/sys/ia64/ia64/interrupt.c
index a90e8e8..a9bee27 100644
--- a/sys/ia64/ia64/interrupt.c
+++ b/sys/ia64/ia64/interrupt.c
@@ -60,7 +60,6 @@
#include <machine/md_var.h>
#include <machine/pcb.h>
#include <machine/reg.h>
-#include <machine/sapicvar.h>
#include <machine/smp.h>
#ifdef EVCNT_COUNTERS
@@ -74,16 +73,6 @@ struct evcnt clock_intr_evcnt; /* event counter for clock intrs. */
#include <ddb/ddb.h>
#endif
-static void ia64_dispatch_intr(void *, u_int);
-
-static void
-dummy_perf(unsigned long vector, struct trapframe *tf)
-{
- printf("performance interrupt!\n");
-}
-
-void (*perf_irq)(unsigned long, struct trapframe *) = dummy_perf;
-
SYSCTL_NODE(_debug, OID_AUTO, clock, CTLFLAG_RW, 0, "clock statistics");
static int adjust_edges = 0;
@@ -102,6 +91,19 @@ static int adjust_ticks = 0;
SYSCTL_INT(_debug_clock, OID_AUTO, adjust_ticks, CTLFLAG_RD,
&adjust_ticks, 0, "Total number of ITC interrupts with adjustment");
+
+struct ia64_intr {
+ struct intr_event *event; /* interrupt event */
+ volatile long *cntp; /* interrupt counter */
+ struct sapic *sapic;
+ u_int irq;
+};
+
+static struct ia64_intr *ia64_intrs[256];
+
+
+static void ia64_dispatch_intr(void *, u_int);
+
void
interrupt(struct trapframe *tf)
{
@@ -247,19 +249,6 @@ stray:
}
}
-/*
- * Hardware irqs have vectors starting at this offset.
- */
-#define IA64_HARDWARE_IRQ_BASE 0x20
-
-struct ia64_intr {
- struct intr_event *event; /* interrupt event */
- volatile long *cntp; /* interrupt counter */
- struct sapic *sapic;
- u_int irq;
-};
-
-static struct ia64_intr *ia64_intrs[256];
static void
ia64_intr_eoi(void *arg)
@@ -303,57 +292,75 @@ ia64_setup_intr(const char *name, int irq, driver_filter_t filter,
struct ia64_intr *i;
struct sapic *sa;
char *intrname;
- u_int vector;
+ u_int prio, vector;
int error;
- /* Get the I/O SAPIC that corresponds to the IRQ. */
- sa = sapic_lookup(irq);
- if (sa == NULL)
+ prio = intr_priority(flags);
+ if (prio > PRI_MAX_ITHD)
return (EINVAL);
+ /* XXX lock */
+
+ /* Get the I/O SAPIC and vector that corresponds to the IRQ. */
+ sa = sapic_lookup(irq, &vector);
+ if (sa == NULL) {
+ /* XXX unlock */
+ return (EINVAL);
+ }
+
+ if (vector == 0) {
+ /* XXX unlock */
+ i = malloc(sizeof(struct ia64_intr), M_DEVBUF,
+ M_ZERO | M_WAITOK);
+ /* XXX lock */
+ sa = sapic_lookup(irq, &vector);
+ KASSERT(sa != NULL, ("sapic_lookup"));
+ if (vector != 0)
+ free(i, M_DEVBUF);
+ }
+
/*
- * XXX - There's a priority implied by the choice of vector.
- * We should therefore relate the vector to the interrupt type.
+ * If the IRQ has no vector assigned to it yet, assign one based
+ * on the priority.
*/
- vector = irq + IA64_HARDWARE_IRQ_BASE;
-
- i = ia64_intrs[vector];
- if (i == NULL) {
- i = malloc(sizeof(struct ia64_intr), M_DEVBUF, M_NOWAIT);
- if (i == NULL)
- return (ENOMEM);
+ if (vector == 0) {
+ vector = (256 - 64) - (prio << 1);
+ while (vector < 256 && ia64_intrs[vector] != NULL)
+ vector++;
error = intr_event_create(&i->event, (void *)(uintptr_t)vector,
0, irq, ia64_intr_mask, ia64_intr_unmask, ia64_intr_eoi,
NULL, "irq%u:", irq);
if (error) {
+ /* XXX unlock */
free(i, M_DEVBUF);
return (error);
}
- if (!atomic_cmpset_ptr(&ia64_intrs[vector], NULL, i)) {
- intr_event_destroy(i->event);
- free(i, M_DEVBUF);
- i = ia64_intrs[vector];
- } else {
- i->sapic = sa;
- i->irq = irq;
-
- i->cntp = intrcnt + irq + INTRCNT_ISA_IRQ;
- if (name != NULL && *name != '\0') {
- /* XXX needs abstraction. Too error prone. */
- intrname = intrnames +
- (irq + INTRCNT_ISA_IRQ) * INTRNAME_LEN;
- memset(intrname, ' ', INTRNAME_LEN - 1);
- bcopy(name, intrname, strlen(name));
- }
-
- sapic_enable(i->sapic, irq, vector);
+ i->sapic = sa;
+ i->irq = irq;
+ i->cntp = intrcnt + irq + INTRCNT_ISA_IRQ;
+ ia64_intrs[vector] = i;
+ sapic_enable(sa, irq, vector);
+
+ /* XXX unlock */
+
+ if (name != NULL && *name != '\0') {
+ /* XXX needs abstraction. Too error prone. */
+ intrname = intrnames +
+ (irq + INTRCNT_ISA_IRQ) * INTRNAME_LEN;
+ memset(intrname, ' ', INTRNAME_LEN - 1);
+ bcopy(name, intrname, strlen(name));
}
+ } else {
+ i = ia64_intrs[vector];
+ /* XXX unlock */
}
+ KASSERT(i != NULL, ("vector mapping bug"));
+
error = intr_event_add_handler(i->event, name, filter, handler, arg,
- intr_priority(flags), flags, cookiep);
+ prio, flags, cookiep);
return (error);
}
diff --git a/sys/ia64/ia64/nexus.c b/sys/ia64/ia64/nexus.c
index 5ce4731..17c07d6 100644
--- a/sys/ia64/ia64/nexus.c
+++ b/sys/ia64/ia64/nexus.c
@@ -59,7 +59,6 @@
#include <machine/nexusvar.h>
#include <machine/pmap.h>
#include <machine/resource.h>
-#include <machine/sapicvar.h>
#include <machine/vmparam.h>
#include <contrib/dev/acpica/include/acpi.h>
diff --git a/sys/ia64/ia64/sapic.c b/sys/ia64/ia64/sapic.c
index 88bd013..cb8a1c3 100644
--- a/sys/ia64/ia64/sapic.c
+++ b/sys/ia64/ia64/sapic.c
@@ -39,77 +39,100 @@
#include <machine/intr.h>
#include <machine/pal.h>
-#include <machine/sapicreg.h>
-#include <machine/sapicvar.h>
#include <vm/vm.h>
#include <vm/pmap.h>
-static MALLOC_DEFINE(M_SAPIC, "sapic", "I/O SAPIC devices");
-
-static int sysctl_machdep_apic(SYSCTL_HANDLER_ARGS);
-
-SYSCTL_OID(_machdep, OID_AUTO, apic, CTLTYPE_STRING|CTLFLAG_RD,
- NULL, 0, sysctl_machdep_apic, "A", "(x)APIC redirection table entries");
+/*
+ * Offsets from the SAPIC base in memory. Most registers are accessed
+ * by indexing using the SAPIC_IO_SELECT register.
+ */
+#define SAPIC_IO_SELECT 0x00
+#define SAPIC_IO_WINDOW 0x10
+#define SAPIC_APIC_EOI 0x40
-struct sapic *ia64_sapics[16]; /* XXX make this resizable */
-int ia64_sapic_count;
+/*
+ * Indexed registers.
+ */
+#define SAPIC_ID 0x00
+#define SAPIC_VERSION 0x01
+#define SAPIC_ARBITRATION_ID 0x02
+#define SAPIC_RTE_BASE 0x10
+
+/* Interrupt polarity. */
+#define SAPIC_POLARITY_HIGH 0
+#define SAPIC_POLARITY_LOW 1
+
+/* Interrupt trigger. */
+#define SAPIC_TRIGGER_EDGE 0
+#define SAPIC_TRIGGER_LEVEL 1
+
+/* Interrupt delivery mode. */
+#define SAPIC_DELMODE_FIXED 0
+#define SAPIC_DELMODE_LOWPRI 1
+#define SAPIC_DELMODE_PMI 2
+#define SAPIC_DELMODE_NMI 4
+#define SAPIC_DELMODE_INIT 5
+#define SAPIC_DELMODE_EXTINT 7
+
+struct sapic {
+ struct mtx sa_mtx;
+ uint64_t sa_registers; /* virtual address of sapic */
+ u_int sa_id; /* I/O SAPIC Id */
+ u_int sa_base; /* ACPI vector base */
+ u_int sa_limit; /* last ACPI vector handled here */
+};
struct sapic_rte {
- u_int64_t rte_vector :8;
- u_int64_t rte_delivery_mode :3;
- u_int64_t rte_destination_mode :1;
- u_int64_t rte_delivery_status :1;
- u_int64_t rte_polarity :1;
- u_int64_t rte_rirr :1;
- u_int64_t rte_trigger_mode :1;
- u_int64_t rte_mask :1;
- u_int64_t rte_flushen :1;
- u_int64_t rte_reserved :30;
- u_int64_t rte_destination_eid :8;
- u_int64_t rte_destination_id :8;
+ uint64_t rte_vector :8;
+ uint64_t rte_delivery_mode :3;
+ uint64_t rte_destination_mode :1;
+ uint64_t rte_delivery_status :1;
+ uint64_t rte_polarity :1;
+ uint64_t rte_rirr :1;
+ uint64_t rte_trigger_mode :1;
+ uint64_t rte_mask :1;
+ uint64_t rte_flushen :1;
+ uint64_t rte_reserved :30;
+ uint64_t rte_destination_eid :8;
+ uint64_t rte_destination_id :8;
};
-struct sapic *
-sapic_lookup(u_int irq)
-{
- struct sapic *sa;
- int i;
+MALLOC_DEFINE(M_SAPIC, "sapic", "I/O SAPIC devices");
- for (i = 0; i < ia64_sapic_count; i++) {
- sa = ia64_sapics[i];
- if (irq >= sa->sa_base && irq <= sa->sa_limit)
- return (sa);
- }
+struct sapic *ia64_sapics[16]; /* XXX make this resizable */
+int ia64_sapic_count;
- return (NULL);
-}
+static int sysctl_machdep_apic(SYSCTL_HANDLER_ARGS);
-static __inline u_int32_t
+SYSCTL_OID(_machdep, OID_AUTO, apic, CTLTYPE_STRING|CTLFLAG_RD,
+ NULL, 0, sysctl_machdep_apic, "A", "(x)APIC redirection table entries");
+
+static __inline uint32_t
sapic_read(struct sapic *sa, int which)
{
- vm_offset_t reg = sa->sa_registers;
+ uint32_t value;
- *(volatile u_int32_t *) (reg + SAPIC_IO_SELECT) = which;
- ia64_mf();
- return *(volatile u_int32_t *) (reg + SAPIC_IO_WINDOW);
+ ia64_st4((void *)(sa->sa_registers + SAPIC_IO_SELECT), which);
+ ia64_mf_a();
+ value = ia64_ld4((void *)(sa->sa_registers + SAPIC_IO_WINDOW));
+ return (value);
}
static __inline void
-sapic_write(struct sapic *sa, int which, u_int32_t value)
+sapic_write(struct sapic *sa, int which, uint32_t value)
{
- vm_offset_t reg = sa->sa_registers;
- *(volatile u_int32_t *) (reg + SAPIC_IO_SELECT) = which;
- ia64_mf();
- *(volatile u_int32_t *) (reg + SAPIC_IO_WINDOW) = value;
- ia64_mf();
+ ia64_st4((void *)(sa->sa_registers + SAPIC_IO_SELECT), which);
+ ia64_mf_a();
+ ia64_st4((void *)(sa->sa_registers + SAPIC_IO_WINDOW), value);
+ ia64_mf_a();
}
static __inline void
sapic_read_rte(struct sapic *sa, int which, struct sapic_rte *rte)
{
- u_int32_t *p = (u_int32_t *) rte;
+ uint32_t *p = (uint32_t *) rte;
p[0] = sapic_read(sa, SAPIC_RTE_BASE + 2 * which);
p[1] = sapic_read(sa, SAPIC_RTE_BASE + 2 * which + 1);
@@ -118,19 +141,43 @@ sapic_read_rte(struct sapic *sa, int which, struct sapic_rte *rte)
static __inline void
sapic_write_rte(struct sapic *sa, int which, struct sapic_rte *rte)
{
- u_int32_t *p = (u_int32_t *) rte;
+ uint32_t *p = (uint32_t *) rte;
+
+ sapic_write(sa, SAPIC_RTE_BASE + 2 * which, p[0]);
+ sapic_write(sa, SAPIC_RTE_BASE + 2 * which + 1, p[1]);
+}
+
+struct sapic *
+sapic_lookup(u_int irq, u_int *vecp)
+{
+ struct sapic_rte rte;
+ struct sapic *sa;
+ int i;
+
+ for (i = 0; i < ia64_sapic_count; i++) {
+ sa = ia64_sapics[i];
+ if (irq >= sa->sa_base && irq <= sa->sa_limit) {
+ if (vecp != NULL) {
+ mtx_lock_spin(&sa->sa_mtx);
+ sapic_read_rte(sa, irq - sa->sa_base, &rte);
+ mtx_unlock_spin(&sa->sa_mtx);
+ *vecp = rte.rte_vector;
+ }
+ return (sa);
+ }
+ }
- sapic_write(sa, SAPIC_RTE_BASE + 2 *which, p[0]);
- sapic_write(sa, SAPIC_RTE_BASE + 2 *which + 1, p[1]);
+ return (NULL);
}
+
int
sapic_config_intr(u_int irq, enum intr_trigger trig, enum intr_polarity pol)
{
struct sapic_rte rte;
struct sapic *sa;
- sa = sapic_lookup(irq);
+ sa = sapic_lookup(irq, NULL);
if (sa == NULL)
return (EINVAL);
@@ -154,7 +201,7 @@ sapic_config_intr(u_int irq, enum intr_trigger trig, enum intr_polarity pol)
}
struct sapic *
-sapic_create(u_int id, u_int base, u_int64_t address)
+sapic_create(u_int id, u_int base, uint64_t address)
{
struct sapic_rte rte;
struct sapic *sa;
@@ -214,10 +261,9 @@ sapic_enable(struct sapic *sa, u_int irq, u_int vector)
void
sapic_eoi(struct sapic *sa, u_int vector)
{
- vm_offset_t reg = sa->sa_registers;
- *(volatile u_int32_t *)(reg + SAPIC_APIC_EOI) = vector;
- ia64_mf();
+ ia64_st4((void *)(sa->sa_registers + SAPIC_APIC_EOI), vector);
+ ia64_mf_a();
}
/* Expected to be called with interrupts disabled. */
diff --git a/sys/ia64/include/intr.h b/sys/ia64/include/intr.h
index 8651fda..0635e34 100644
--- a/sys/ia64/include/intr.h
+++ b/sys/ia64/include/intr.h
@@ -30,6 +30,8 @@
#ifndef _MACHINE_INTR_H_
#define _MACHINE_INTR_H_
+struct sapic;
+
/*
* Layout of the Processor Interrupt Block.
*/
@@ -46,8 +48,20 @@ struct ia64_pib
extern struct ia64_pib *ia64_pib;
-int ia64_setup_intr(const char *name, int irq, driver_filter_t filter,
- driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep);
-int ia64_teardown_intr(void *cookie);
+int ia64_setup_intr(const char *, int, driver_filter_t, driver_intr_t,
+ void *, enum intr_type, void **);
+int ia64_teardown_intr(void *);
+
+int sapic_config_intr(u_int, enum intr_trigger, enum intr_polarity);
+struct sapic *sapic_create(u_int, u_int, uint64_t);
+int sapic_enable(struct sapic *, u_int, u_int);
+void sapic_eoi(struct sapic *, u_int);
+struct sapic *sapic_lookup(u_int, u_int *);
+void sapic_mask(struct sapic *, u_int);
+void sapic_unmask(struct sapic *, u_int);
+
+#ifdef DDB
+void sapic_print(struct sapic *, u_int);
+#endif
#endif /* !_MACHINE_INTR_H_ */
diff --git a/sys/ia64/include/sapicreg.h b/sys/ia64/include/sapicreg.h
deleted file mode 100644
index 8f7dfbd..0000000
--- a/sys/ia64/include/sapicreg.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*-
- * Copyright (c) 2001 Doug Rabson
- * All rights reserved.
- *
- * 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 AUTHOR 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 AUTHOR 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.
- *
- * $FreeBSD$
- */
-
-#ifndef _MACHINE_SAPICREG_H_
-#define _MACHINE_SAPICREG_H_
-
-/*
- * Offsets from the SAPIC base in memory. Most registers are accessed
- * by indexing using the SAPIC_IO_SELECT register.
- */
-#define SAPIC_IO_SELECT 0x00
-#define SAPIC_IO_WINDOW 0x10
-#define SAPIC_APIC_EOI 0x40
-
-/*
- * Indexed registers.
- */
-#define SAPIC_ID 0x00
-#define SAPIC_VERSION 0x01
-#define SAPIC_ARBITRATION_ID 0x02
-#define SAPIC_RTE_BASE 0x10
-
-#endif /* ! _MACHINE_SAPICREG_H_ */
diff --git a/sys/ia64/include/sapicvar.h b/sys/ia64/include/sapicvar.h
deleted file mode 100644
index 30a353c..0000000
--- a/sys/ia64/include/sapicvar.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*-
- * Copyright (c) 2001 Doug Rabson
- * All rights reserved.
- *
- * 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 AUTHOR 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 AUTHOR 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.
- *
- * $FreeBSD$
- */
-
-#ifndef _MACHINE_SAPICVAR_H_
-#define _MACHINE_SAPICVAR_H_
-
-struct sapic {
- struct mtx sa_mtx;
- vm_offset_t sa_registers; /* virtual address of sapic */
- u_int sa_id; /* I/O SAPIC Id */
- u_int sa_base; /* ACPI vector base */
- u_int sa_limit; /* last ACPI vector handled here */
-};
-
-#define SAPIC_TRIGGER_EDGE 0
-#define SAPIC_TRIGGER_LEVEL 1
-
-#define SAPIC_POLARITY_HIGH 0
-#define SAPIC_POLARITY_LOW 1
-
-#define SAPIC_DELMODE_FIXED 0
-#define SAPIC_DELMODE_LOWPRI 1
-#define SAPIC_DELMODE_PMI 2
-#define SAPIC_DELMODE_NMI 4
-#define SAPIC_DELMODE_INIT 5
-#define SAPIC_DELMODE_EXTINT 7
-
-int sapic_config_intr(u_int irq, enum intr_trigger, enum intr_polarity);
-struct sapic *sapic_create(u_int id, u_int base, uint64_t address);
-int sapic_enable(struct sapic *sa, u_int irq, u_int vector);
-void sapic_eoi(struct sapic *sa, u_int vector);
-struct sapic *sapic_lookup(u_int irq);
-void sapic_mask(struct sapic *sa, u_int irq);
-void sapic_unmask(struct sapic *sa, u_int irq);
-
-#ifdef DDB
-void sapic_print(struct sapic *sa, u_int irq);
-#endif
-
-#endif /* ! _MACHINE_SAPICVAR_H_ */
OpenPOWER on IntegriCloud