summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2008-12-17 19:35:39 +0000
committerkettenis <kettenis@openbsd.org>2008-12-17 19:35:39 +0000
commit01e588f2557fad46fca547605e1cc838d6e01014 (patch)
tree0572ca718a3793afdfdb12886f71cab61edee980
parentadd some newly created stats that are defined in ieee80211_ioctl.h (diff)
downloadwireguard-openbsd-01e588f2557fad46fca547605e1cc838d6e01014.tar.xz
wireguard-openbsd-01e588f2557fad46fca547605e1cc838d6e01014.zip
Make the code that picks an IRQ from the list of possible IRQs a bit smarter
by avoiding legacy IRQs if possible. Fixes problems (some, not all) with machines that advertise legacy IRQs as usable even if they have ISA devices onboard that need those IRQs. ok marco@
-rw-r--r--sys/dev/acpi/acpiprt.c64
1 files changed, 62 insertions, 2 deletions
diff --git a/sys/dev/acpi/acpiprt.c b/sys/dev/acpi/acpiprt.c
index 86cd08b217c..fe3ae073d2c 100644
--- a/sys/dev/acpi/acpiprt.c
+++ b/sys/dev/acpi/acpiprt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpiprt.c,v 1.28 2008/12/07 14:33:26 kettenis Exp $ */
+/* $OpenBSD: acpiprt.c,v 1.29 2008/12/17 19:35:39 kettenis Exp $ */
/*
* Copyright (c) 2006 Mark Kettenis <kettenis@openbsd.org>
*
@@ -58,6 +58,7 @@ void acpiprt_attach(struct device *, struct device *, void *);
int acpiprt_getirq(union acpi_resource *crs, void *arg);
int acpiprt_getminbus(union acpi_resource *, void *);
int acpiprt_checkprs(union acpi_resource *, void *);
+int acpiprt_chooseirq(union acpi_resource *, void *);
struct acpiprt_softc {
struct device sc_dev;
@@ -181,6 +182,65 @@ acpiprt_getirq(union acpi_resource *crs, void *arg)
return (0);
}
+int
+acpiprt_pri[16] = {
+ 0, /* 8254 Counter 0 */
+ 1, /* Keyboard */
+ 0, /* 8259 Slave */
+ 2, /* Serial Port A */
+ 2, /* Serial Port B */
+ 5, /* Parallel Port / Generic */
+ 2, /* Floppy Disk */
+ 4, /* Parallel Port / Generic */
+ 1, /* RTC */
+ 6, /* Generic */
+ 7, /* Generic */
+ 7, /* Generic */
+ 1, /* Mouse */
+ 0, /* FPU */
+ 2, /* Primary IDE */
+ 3 /* Secondary IDE */
+};
+
+int
+acpiprt_chooseirq(union acpi_resource *crs, void *arg)
+{
+ int *irq = (int *)arg;
+ int typ, i, pri = -1;
+
+ typ = AML_CRSTYPE(crs);
+ switch (typ) {
+ case SR_IRQ:
+ for (i = 0; i < sizeof(crs->sr_irq.irq_mask) * 8; i++) {
+ if (crs->sr_irq.irq_mask & (1 << i) &&
+ acpiprt_pri[i] > pri) {
+ *irq = i;
+ pri = acpiprt_pri[*irq];
+ }
+ }
+ break;
+ case LR_EXTIRQ:
+ /* First try non-8259 interrupts. */
+ for (i = 0; i < crs->lr_extirq.irq_count; i++) {
+ if (crs->lr_extirq.irq[i] > 15) {
+ *irq = crs->lr_extirq.irq[i];
+ return (0);
+ }
+ }
+
+ for (i = 0; i < crs->lr_extirq.irq_count; i++) {
+ if (acpiprt_pri[crs->lr_extirq.irq[i]] > pri) {
+ *irq = crs->lr_extirq.irq[i];
+ pri = acpiprt_pri[*irq];
+ }
+ }
+ break;
+ default:
+ printf("unknown interrupt: %x\n", typ);
+ }
+ return (0);
+}
+
void
acpiprt_prt_add(struct acpiprt_softc *sc, struct aml_value *v)
{
@@ -262,7 +322,7 @@ acpiprt_prt_add(struct acpiprt_softc *sc, struct aml_value *v)
aml_parse_resource(res.length, res.v_buffer,
acpiprt_checkprs, &irq);
aml_parse_resource(res.length, res.v_buffer,
- acpiprt_getirq, &newirq);
+ acpiprt_chooseirq, &newirq);
}
aml_freevalue(&res);
}