aboutsummaryrefslogtreecommitdiff
path: root/sys/ia64/ia64/sapic.c
diff options
context:
space:
mode:
authorMarcel Moolenaar <marcel@FreeBSD.org>2003-09-10 22:49:38 +0000
committerMarcel Moolenaar <marcel@FreeBSD.org>2003-09-10 22:49:38 +0000
commit87ad0260ffe80975ac5d77744f605612eccc1499 (patch)
tree96f2cdeb14cca6a49dede20d7617de98bdcfd032 /sys/ia64/ia64/sapic.c
parent24752c4291823109c6b3d4758db8d69698ddf2db (diff)
downloadsrc-87ad0260ffe80975ac5d77744f605612eccc1499.tar.gz
src-87ad0260ffe80975ac5d77744f605612eccc1499.zip
Rewrite the SAPIC initialization to always program the RTEs with what
we think is the correct trigger mode and polarity. This allows us to implement BUS_CONFIG_INTR() as an update of the RTE in question. Consequently, we can trust the RTE when we enable an interrupt and avoids that we need to know about the trigger mode and polarity at that time.
Notes
Notes: svn path=/head/; revision=119970
Diffstat (limited to 'sys/ia64/ia64/sapic.c')
-rw-r--r--sys/ia64/ia64/sapic.c96
1 files changed, 76 insertions, 20 deletions
diff --git a/sys/ia64/ia64/sapic.c b/sys/ia64/ia64/sapic.c
index 6307f689bab6..0001f8c9f5c0 100644
--- a/sys/ia64/ia64/sapic.c
+++ b/sys/ia64/ia64/sapic.c
@@ -32,12 +32,13 @@
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/systm.h>
-#include <machine/sapicvar.h>
-#include <machine/sapicreg.h>
#include <sys/bus.h>
+#include <sys/sysctl.h>
+
#include <machine/intr.h>
#include <machine/pal.h>
-#include <sys/sysctl.h>
+#include <machine/sapicreg.h>
+#include <machine/sapicvar.h>
static MALLOC_DEFINE(M_SAPIC, "sapic", "I/O SAPIC devices");
@@ -100,8 +101,7 @@ sapic_read_rte(struct sapic *sa, int which, struct sapic_rte *rte)
}
static void
-sapic_write_rte(struct sapic *sa, int which,
- struct sapic_rte *rte)
+sapic_write_rte(struct sapic *sa, int which, struct sapic_rte *rte)
{
u_int32_t *p = (u_int32_t *) rte;
register_t c;
@@ -112,11 +112,44 @@ sapic_write_rte(struct sapic *sa, int which,
intr_restore(c);
}
+int
+sapic_config_intr(int irq, enum intr_trigger trig, enum intr_polarity pol)
+{
+ 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)
+ continue;
+
+ sapic_read_rte(sa, irq - sa->sa_base, &rte);
+ if (trig != INTR_TRIGGER_CONFORM)
+ rte.rte_trigger_mode = (trig == INTR_TRIGGER_EDGE) ?
+ SAPIC_TRIGGER_EDGE : SAPIC_TRIGGER_LEVEL;
+ else
+ rte.rte_trigger_mode = (irq < 16) ?
+ SAPIC_TRIGGER_EDGE : SAPIC_TRIGGER_LEVEL;
+ if (pol != INTR_POLARITY_CONFORM)
+ rte.rte_polarity = (pol == INTR_POLARITY_HIGH) ?
+ SAPIC_POLARITY_HIGH : SAPIC_POLARITY_LOW;
+ else
+ rte.rte_polarity = (irq < 16) ? SAPIC_POLARITY_HIGH :
+ SAPIC_POLARITY_LOW;
+ sapic_write_rte(sa, irq - sa->sa_base, &rte);
+ return (0);
+ }
+
+ return (ENOENT);
+}
+
struct sapic *
sapic_create(int id, int base, u_int64_t address)
{
+ struct sapic_rte rte;
struct sapic *sa;
- int max;
+ int i, max;
sa = malloc(sizeof(struct sapic), M_SAPIC, M_NOWAIT);
if (!sa)
@@ -131,24 +164,47 @@ sapic_create(int id, int base, u_int64_t address)
ia64_sapics[ia64_sapic_count++] = sa;
- return sa;
+ /*
+ * Initialize all RTEs with a default trigger mode and polarity.
+ * This may be changed later by calling sapic_config_intr(). We
+ * mask all interrupts by default.
+ */
+ bzero(&rte, sizeof(rte));
+ rte.rte_mask = 1;
+ for (i = base; i <= sa->sa_limit; i++) {
+ rte.rte_trigger_mode = (i < 16) ? SAPIC_TRIGGER_EDGE :
+ SAPIC_TRIGGER_LEVEL;
+ rte.rte_polarity = (i < 16) ? SAPIC_POLARITY_HIGH :
+ SAPIC_POLARITY_LOW;
+ sapic_write_rte(sa, i - base, &rte);
+ }
+
+ return (sa);
}
-void
-sapic_enable(struct sapic *sa, int input, int vector,
- int trigger_mode, int polarity)
+int
+sapic_enable(int irq, int vector)
{
struct sapic_rte rte;
- u_int64_t lid = ia64_get_lid();
-
- bzero(&rte, sizeof(rte));
- rte.rte_destination_id = (lid >> 24) & 255;
- rte.rte_destination_eid = (lid >> 16) & 255;
- rte.rte_trigger_mode = trigger_mode;
- rte.rte_polarity = polarity;
- rte.rte_delivery_mode = SAPIC_DELMODE_LOWPRI;
- rte.rte_vector = vector;
- sapic_write_rte(sa, input, &rte);
+ struct sapic *sa;
+ uint64_t lid = ia64_get_lid();
+ int i;
+
+ for (i = 0; i < ia64_sapic_count; i++) {
+ sa = ia64_sapics[i];
+ if (irq < sa->sa_base || irq > sa->sa_limit)
+ continue;
+
+ sapic_read_rte(sa, irq - sa->sa_base, &rte);
+ rte.rte_destination_id = (lid >> 24) & 255;
+ rte.rte_destination_eid = (lid >> 16) & 255;
+ rte.rte_delivery_mode = SAPIC_DELMODE_LOWPRI;
+ rte.rte_vector = vector;
+ rte.rte_mask = 0;
+ sapic_write_rte(sa, irq - sa->sa_base, &rte);
+ return (0);
+ }
+ return (ENOENT);
}
void