diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2008-12-17 19:35:40 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2008-12-17 19:35:40 +0000 |
commit | fa4b01bd5967e601a425d903264fb6d2342f3646 (patch) | |
tree | e3950df030c637f7a54e8503da5cb0d3472b94db | |
parent | 823b38eb3a28a96007ed6e273eb7d4bbafbf6154 (diff) |
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.c | 64 |
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); } |