Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

machintr: Add intr_config interface

This interface is used to change pre-configured interrupt's trigger
mode and polarity.
  • Loading branch information...
commit d1ae7328fe6d956bb1f35aae7b169a0b95ebc5eb 1 parent ecec8dd
Sepherosa Ziehau authored
View
76 sys/platform/pc32/apic/ioapic_abi.c
@@ -457,6 +457,7 @@ static struct ioapic_irqmap {
enum intr_trigger im_trig;
enum intr_polarity im_pola;
int im_gsi;
+ uint32_t im_flags; /* IOAPIC_IMF_ */
} ioapic_irqmaps[MAX_HARDINTS]; /* XXX MAX_HARDINTS may not be correct */
#define IOAPIC_IMT_UNUSED 0
@@ -464,6 +465,8 @@ static struct ioapic_irqmap {
#define IOAPIC_IMT_LINE 2
#define IOAPIC_IMT_SYSCALL 3
+#define IOAPIC_IMF_CONF 0x1
+
extern void IOAPIC_INTREN(int);
extern void IOAPIC_INTRDIS(int);
@@ -475,6 +478,7 @@ static void ioapic_cleanup(void);
static void ioapic_setdefault(void);
static void ioapic_stabilize(void);
static void ioapic_initmap(void);
+static void ioapic_intr_config(int, enum intr_trigger, enum intr_polarity);
static int ioapic_imcr_present;
@@ -489,7 +493,8 @@ struct machintr_abi MachIntrABI_IOAPIC = {
.cleanup = ioapic_cleanup,
.setdefault = ioapic_setdefault,
.stabilize = ioapic_stabilize,
- .initmap = ioapic_initmap
+ .initmap = ioapic_initmap,
+ .intr_config = ioapic_intr_config
};
static int
@@ -755,11 +760,11 @@ ioapic_abi_set_irqmap(int irq, int gsi, enum intr_trigger trig,
if (bootverbose) {
kprintf("IOAPIC: irq %d -> gsi %d %c\n", irq, map->im_gsi,
- trig == INTR_TRIGGER_LEVEL ? 'L' : 'E');
+ map->im_trig == INTR_TRIGGER_LEVEL ? 'L' : 'E');
}
- pin = ioapic_gsi_pin(gsi);
- ioaddr = ioapic_gsi_ioaddr(gsi);
+ pin = ioapic_gsi_pin(map->im_gsi);
+ ioaddr = ioapic_gsi_ioaddr(map->im_gsi);
info = &int_to_apicintpin[irq];
@@ -768,7 +773,68 @@ ioapic_abi_set_irqmap(int irq, int gsi, enum intr_trigger trig,
info->apic_address = ioaddr;
info->redirindex = IOAPIC_REDTBL + (2 * pin);
info->flags = IOAPIC_IM_FLAG_MASKED;
- if (trig == INTR_TRIGGER_LEVEL)
+ if (map->im_trig == INTR_TRIGGER_LEVEL)
+ info->flags |= IOAPIC_IM_FLAG_LEVEL;
+
+ ioapic_pin_setup(ioaddr, pin, IDT_OFFSET + irq,
+ map->im_trig, map->im_pola);
+}
+
+static void
+ioapic_intr_config(int irq, enum intr_trigger trig, enum intr_polarity pola)
+{
+ struct apic_intmapinfo *info;
+ struct ioapic_irqmap *map;
+ void *ioaddr;
+ int pin;
+
+ if (ioapic_use_old)
+ return;
+
+ KKASSERT(trig == INTR_TRIGGER_EDGE || trig == INTR_TRIGGER_LEVEL);
+ KKASSERT(pola == INTR_POLARITY_HIGH || pola == INTR_POLARITY_LOW);
+ KKASSERT((trig == INTR_TRIGGER_EDGE && pola == INTR_POLARITY_HIGH) ||
+ (trig == INTR_TRIGGER_LEVEL && pola == INTR_POLARITY_LOW));
+
+ KKASSERT(irq >= 0 && irq < IOAPIC_HWI_VECTORS);
+ map = &ioapic_irqmaps[irq];
+
+ KKASSERT(map->im_type == IOAPIC_IMT_LINE);
+
+ if (map->im_flags & IOAPIC_IMF_CONF) {
+ if (trig != map->im_trig) {
+ panic("ioapic_intr_config: trig %c -> %c\n",
+ map->im_trig == INTR_TRIGGER_EDGE ? 'E' : 'L',
+ trig == INTR_TRIGGER_EDGE ? 'E' : 'L');
+ }
+ if (pola != map->im_pola) {
+ panic("ioapic_intr_config: pola %s -> %s\n",
+ map->im_pola == INTR_POLARITY_HIGH ? "hi" : "lo",
+ pola == INTR_POLARITY_HIGH ? "hi" : "lo");
+ }
+ return;
+ }
+ map->im_flags |= IOAPIC_IMF_CONF;
+
+ if (trig == map->im_trig && pola == map->im_pola)
+ return;
+
+ if (bootverbose) {
+ kprintf("IOAPIC: irq %d, gsi %d %c -> %c\n", irq, map->im_gsi,
+ map->im_trig == INTR_TRIGGER_LEVEL ? 'L' : 'E',
+ trig == INTR_TRIGGER_LEVEL ? 'L' : 'E');
+ }
+
+ map->im_trig = trig;
+ map->im_pola = pola;
+
+ pin = ioapic_gsi_pin(map->im_gsi);
+ ioaddr = ioapic_gsi_ioaddr(map->im_gsi);
+
+ info = &int_to_apicintpin[irq];
+
+ info->flags &= ~IOAPIC_IM_FLAG_LEVEL;
+ if (map->im_trig == INTR_TRIGGER_LEVEL)
info->flags |= IOAPIC_IM_FLAG_LEVEL;
ioapic_pin_setup(ioaddr, pin, IDT_OFFSET + irq,
View
10 sys/platform/pc32/icu/icu_abi.c
@@ -102,6 +102,7 @@ static void icu_cleanup(void);
static void icu_setdefault(void);
static void icu_stabilize(void);
static void icu_initmap(void);
+static void icu_intr_config(int, enum intr_trigger, enum intr_polarity);
struct machintr_abi MachIntrABI_ICU = {
MACHINTR_ICU,
@@ -114,7 +115,8 @@ struct machintr_abi MachIntrABI_ICU = {
.cleanup = icu_cleanup,
.setdefault = icu_setdefault,
.stabilize = icu_stabilize,
- .initmap = icu_initmap
+ .initmap = icu_initmap,
+ .intr_config = icu_intr_config
};
static int icu_imcr_present;
@@ -308,3 +310,9 @@ icu_initmap(void)
}
icu_irqmaps[IDT_OFFSET_SYSCALL - IDT_OFFSET].im_type = ICU_IMT_SYSCALL;
}
+
+static void
+icu_intr_config(int irq __unused, enum intr_trigger trig __unused,
+ enum intr_polarity pola __unused)
+{
+}
View
76 sys/platform/pc64/apic/ioapic_abi.c
@@ -457,6 +457,7 @@ static struct ioapic_irqmap {
enum intr_trigger im_trig;
enum intr_polarity im_pola;
int im_gsi;
+ uint32_t im_flags; /* IOAPIC_IMF_ */
} ioapic_irqmaps[MAX_HARDINTS]; /* XXX MAX_HARDINTS may not be correct */
#define IOAPIC_IMT_UNUSED 0
@@ -464,6 +465,8 @@ static struct ioapic_irqmap {
#define IOAPIC_IMT_LINE 2
#define IOAPIC_IMT_SYSCALL 3
+#define IOAPIC_IMF_CONF 0x1
+
extern void IOAPIC_INTREN(int);
extern void IOAPIC_INTRDIS(int);
@@ -475,6 +478,7 @@ static void ioapic_cleanup(void);
static void ioapic_setdefault(void);
static void ioapic_stabilize(void);
static void ioapic_initmap(void);
+static void ioapic_intr_config(int, enum intr_trigger, enum intr_polarity);
static int ioapic_imcr_present;
@@ -489,7 +493,8 @@ struct machintr_abi MachIntrABI_IOAPIC = {
.cleanup = ioapic_cleanup,
.setdefault = ioapic_setdefault,
.stabilize = ioapic_stabilize,
- .initmap = ioapic_initmap
+ .initmap = ioapic_initmap,
+ .intr_config = ioapic_intr_config
};
static int
@@ -748,11 +753,11 @@ ioapic_abi_set_irqmap(int irq, int gsi, enum intr_trigger trig,
if (bootverbose) {
kprintf("IOAPIC: irq %d -> gsi %d %c\n", irq, map->im_gsi,
- trig == INTR_TRIGGER_LEVEL ? 'L' : 'E');
+ map->im_trig == INTR_TRIGGER_LEVEL ? 'L' : 'E');
}
- pin = ioapic_gsi_pin(gsi);
- ioaddr = ioapic_gsi_ioaddr(gsi);
+ pin = ioapic_gsi_pin(map->im_gsi);
+ ioaddr = ioapic_gsi_ioaddr(map->im_gsi);
info = &int_to_apicintpin[irq];
@@ -761,7 +766,68 @@ ioapic_abi_set_irqmap(int irq, int gsi, enum intr_trigger trig,
info->apic_address = ioaddr;
info->redirindex = IOAPIC_REDTBL + (2 * pin);
info->flags = IOAPIC_IM_FLAG_MASKED;
- if (trig == INTR_TRIGGER_LEVEL)
+ if (map->im_trig == INTR_TRIGGER_LEVEL)
+ info->flags |= IOAPIC_IM_FLAG_LEVEL;
+
+ ioapic_pin_setup(ioaddr, pin, IDT_OFFSET + irq,
+ map->im_trig, map->im_pola);
+}
+
+static void
+ioapic_intr_config(int irq, enum intr_trigger trig, enum intr_polarity pola)
+{
+ struct apic_intmapinfo *info;
+ struct ioapic_irqmap *map;
+ void *ioaddr;
+ int pin;
+
+ if (ioapic_use_old)
+ return;
+
+ KKASSERT(trig == INTR_TRIGGER_EDGE || trig == INTR_TRIGGER_LEVEL);
+ KKASSERT(pola == INTR_POLARITY_HIGH || pola == INTR_POLARITY_LOW);
+ KKASSERT((trig == INTR_TRIGGER_EDGE && pola == INTR_POLARITY_HIGH) ||
+ (trig == INTR_TRIGGER_LEVEL && pola == INTR_POLARITY_LOW));
+
+ KKASSERT(irq >= 0 && irq < IOAPIC_HWI_VECTORS);
+ map = &ioapic_irqmaps[irq];
+
+ KKASSERT(map->im_type == IOAPIC_IMT_LINE);
+
+ if (map->im_flags & IOAPIC_IMF_CONF) {
+ if (trig != map->im_trig) {
+ panic("ioapic_intr_config: trig %c -> %c\n",
+ map->im_trig == INTR_TRIGGER_EDGE ? 'E' : 'L',
+ trig == INTR_TRIGGER_EDGE ? 'E' : 'L');
+ }
+ if (pola != map->im_pola) {
+ panic("ioapic_intr_config: pola %s -> %s\n",
+ map->im_pola == INTR_POLARITY_HIGH ? "hi" : "lo",
+ pola == INTR_POLARITY_HIGH ? "hi" : "lo");
+ }
+ return;
+ }
+ map->im_flags |= IOAPIC_IMF_CONF;
+
+ if (trig == map->im_trig && pola == map->im_pola)
+ return;
+
+ if (bootverbose) {
+ kprintf("IOAPIC: irq %d, gsi %d %c -> %c\n", irq, map->im_gsi,
+ map->im_trig == INTR_TRIGGER_LEVEL ? 'L' : 'E',
+ trig == INTR_TRIGGER_LEVEL ? 'L' : 'E');
+ }
+
+ map->im_trig = trig;
+ map->im_pola = pola;
+
+ pin = ioapic_gsi_pin(map->im_gsi);
+ ioaddr = ioapic_gsi_ioaddr(map->im_gsi);
+
+ info = &int_to_apicintpin[irq];
+
+ info->flags &= ~IOAPIC_IM_FLAG_LEVEL;
+ if (map->im_trig == INTR_TRIGGER_LEVEL)
info->flags |= IOAPIC_IM_FLAG_LEVEL;
ioapic_pin_setup(ioaddr, pin, IDT_OFFSET + irq,
View
10 sys/platform/pc64/icu/icu_abi.c
@@ -102,6 +102,7 @@ static void icu_cleanup(void);
static void icu_setdefault(void);
static void icu_stabilize(void);
static void icu_initmap(void);
+static void icu_intr_config(int, enum intr_trigger, enum intr_polarity);
struct machintr_abi MachIntrABI_ICU = {
MACHINTR_ICU,
@@ -114,7 +115,8 @@ struct machintr_abi MachIntrABI_ICU = {
.cleanup = icu_cleanup,
.setdefault = icu_setdefault,
.stabilize = icu_stabilize,
- .initmap = icu_initmap
+ .initmap = icu_initmap,
+ .intr_config = icu_intr_config
};
static int icu_imcr_present;
@@ -308,3 +310,9 @@ icu_initmap(void)
}
icu_irqmaps[i].im_type = ICU_IMT_SYSCALL;
}
+
+static void
+icu_intr_config(int irq __unused, enum intr_trigger trig __unused,
+ enum intr_polarity pola __unused)
+{
+}
View
8 sys/sys/machintr.h
@@ -38,6 +38,9 @@
* vector and masking layer.
*/
+#ifndef _SYS_BUS_H_
+#include <sys/bus.h>
+#endif
#ifndef _SYS_QUEUE_H_
#include <sys/queue.h>
#endif
@@ -66,6 +69,8 @@ struct machintr_abi {
void (*setdefault)(void); /* set default vectors */
void (*stabilize)(void); /* stable before ints enabled */
void (*initmap)(void); /* init irq mapping */
+ void (*intr_config) /* config intr */
+ (int, enum intr_trigger, enum intr_polarity);
};
#define machintr_intren(intr) MachIntrABI.intren(intr)
@@ -75,6 +80,9 @@ struct machintr_abi {
#define machintr_vector_teardown(intr) \
MachIntrABI.vectorctl(MACHINTR_VECTOR_TEARDOWN, intr, 0)
+#define machintr_intr_config(intr, trig, pola) \
+ MachIntrABI.intr_config((intr), (trig), (pola))
+
#ifdef _KERNEL
extern struct machintr_abi MachIntrABI;
Please sign in to comment.
Something went wrong with that request. Please try again.