From fa4b01bd5967e601a425d903264fb6d2342f3646 Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Wed, 17 Dec 2008 19:35:40 +0000 Subject: 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@ --- sys/dev/acpi/acpiprt.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 2 deletions(-) (limited to 'sys/dev/acpi') 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 * @@ -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); } -- cgit v1.2.3