diff options
-rw-r--r-- | sys/ia64/ia64/interrupt.c | 119 | ||||
-rw-r--r-- | sys/ia64/ia64/nexus.c | 1 | ||||
-rw-r--r-- | sys/ia64/ia64/sapic.c | 154 | ||||
-rw-r--r-- | sys/ia64/include/intr.h | 20 | ||||
-rw-r--r-- | sys/ia64/include/sapicreg.h | 48 | ||||
-rw-r--r-- | sys/ia64/include/sapicvar.h | 65 |
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_ */ |