--- acpi_pcib.c Mon Nov 24 21:24:16 2003 +++ acpi_pcib.c.NEW Mon Nov 24 21:23:59 2003 @@ -324,6 +324,48 @@ printf(" %d", Interrupts[i]); printf("\n"); + /*************************************************************/ + /* This is the ugly hack to see if it will be working at all */ + /* We will look for environment variable 'hw.acpi.pci.preferred_irq' + * then check if IRQ in question is in the list of available ones + * and if it is available, we will use it. If it is not available + * we will fall back on "unscientific" first available interrupt + * (basically the way code worked before). + */ + int preferred_irq_idx = 0; + char *pPreferredIRQ = getenv("hw.acpi.pci.preferred_irq"); + if(pPreferredIRQ != NULL) + { + register char *pc; + /* I'm sure there is a better way ;) */ + /* strlen + isdigit */ + register int irq = 0; + for(pc = pPreferredIRQ; *pc != '\0'; pc++) + { + if((*pc < '0') || (*pc > '9')) + { + device_printf(pcib, "Invalid preferred IRQ: %s, " + "falling back on first available\n", + pPreferredIRQ); + goto fallBackOnZero; + } + irq = (irq << 3) + (irq << 1) + (*pc - '0'); + } + /* Looking for slot with the IRQ in question */ + for(register int i = 0; i < NumberOfInterrupts; i++) + { + if(Interrupts[i] == irq) + { + preferred_irq_idx = i; + break; + } + } + device_printf(pcib, "User suggested IRQ: %d (slot %d)\n", + irq, preferred_irq_idx); + } + fallBackOnZero: + /*************************************************************/ + if (crsbuf.Pointer != NULL) /* should never happen */ AcpiOsFree(crsbuf.Pointer); crsbuf.Pointer = NULL; @@ -332,29 +374,29 @@ resbuf.Length = ACPI_SIZEOF_RESOURCE(ACPI_RESOURCE_IRQ); resbuf.Data.Irq = prsres->Data.Irq; /* structure copy other fields */ resbuf.Data.Irq.NumberOfInterrupts = 1; - resbuf.Data.Irq.Interrupts[0] = Interrupts[0]; /* just take first... */ + resbuf.Data.Irq.Interrupts[0] = Interrupts[preferred_irq_idx]; /* just take first... */ } else { resbuf.Id = ACPI_RSTYPE_EXT_IRQ; resbuf.Length = ACPI_SIZEOF_RESOURCE(ACPI_RESOURCE_IRQ); resbuf.Data.ExtendedIrq = prsres->Data.ExtendedIrq; /* structure copy other fields */ resbuf.Data.ExtendedIrq.NumberOfInterrupts = 1; - resbuf.Data.ExtendedIrq.Interrupts[0] = Interrupts[0]; /* just take first... */ + resbuf.Data.ExtendedIrq.Interrupts[0] = Interrupts[preferred_irq_idx]; /* just take first... */ } if (ACPI_FAILURE(status = acpi_AppendBufferResource(&crsbuf, &resbuf))) { device_printf(pcib, "couldn't route interrupt %d via %s, interrupt resource build failed - %s\n", - Interrupts[0], acpi_name(lnkdev), AcpiFormatException(status)); + Interrupts[preferred_irq_idx], acpi_name(lnkdev), AcpiFormatException(status)); goto out; } if (ACPI_FAILURE(status = AcpiSetCurrentResources(lnkdev, &crsbuf))) { device_printf(pcib, "couldn't route interrupt %d via %s - %s\n", - Interrupts[0], acpi_name(lnkdev), AcpiFormatException(status)); + Interrupts[preferred_irq_idx], acpi_name(lnkdev), AcpiFormatException(status)); goto out; } /* successful, return the interrupt we just routed */ device_printf(pcib, "slot %d INT%c routed to irq %d via %s\n", - pci_get_slot(dev), 'A' + pin, Interrupts[0], acpi_name(lnkdev)); - interrupt = Interrupts[0]; + pci_get_slot(dev), 'A' + pin, Interrupts[preferred_irq_idx], acpi_name(lnkdev)); + interrupt = Interrupts[preferred_irq_idx]; out: if (crsbuf.Pointer != NULL)