From c15e7e493fa65cacaa987b450c0bd553c59c99c0 Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Sun, 27 May 2007 16:36:08 +0000 Subject: Dynamically allocate irq's for pci devices on elroy(4). ok martin@ --- sys/arch/hppa/dev/apic.c | 58 ++++++++++++++++++++++++++++------------ sys/arch/hppa/dev/elroyvar.h | 3 ++- sys/arch/hppa/hppa/intr.c | 14 +++++++++- sys/arch/hppa/include/autoconf.h | 3 ++- 4 files changed, 58 insertions(+), 20 deletions(-) (limited to 'sys') diff --git a/sys/arch/hppa/dev/apic.c b/sys/arch/hppa/dev/apic.c index 032afe8cbda..a52307c4033 100644 --- a/sys/arch/hppa/dev/apic.c +++ b/sys/arch/hppa/dev/apic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: apic.c,v 1.1 2007/05/21 22:43:38 kettenis Exp $ */ +/* $OpenBSD: apic.c,v 1.2 2007/05/27 16:36:07 kettenis Exp $ */ /* * Copyright (c) 2005 Michael Shalayeff @@ -32,6 +32,13 @@ #include #include +#define APIC_INT_LINE_MASK 0x0000ff00 +#define APIC_INT_LINE_SHIFT 8 +#define APIC_INT_IRQ_MASK 0x0000001f + +#define APIC_INT_LINE(x) (((x) & APIC_INT_LINE_MASK) >> APIC_INT_LINE_SHIFT) +#define APIC_INT_IRQ(x) ((x) & APIC_INT_IRQ_MASK) + struct apic_iv { struct elroy_softc *sc; pci_intr_handle_t ih; @@ -72,6 +79,11 @@ apic_attach(struct elroy_softc *sc) printf(" APIC ver %x, %d pins", data & APIC_VERSION_MASK, sc->sc_nints); + sc->sc_irq = malloc(sc->sc_nints * sizeof(int), M_DEVBUF, M_NOWAIT); + if (sc->sc_irq == NULL) + panic("apic_attach: cannot allocate irq table\n"); + memset(sc->sc_irq, 0, sc->sc_nints * sizeof(int)); + #ifdef DEBUG apic_dump(sc); #endif @@ -80,17 +92,22 @@ apic_attach(struct elroy_softc *sc) int apic_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) { + struct elroy_softc *sc = pa->pa_pc->_cookie; pci_chipset_tag_t pc = pa->pa_pc; pcitag_t tag = pa->pa_tag; pcireg_t reg; + int line; reg = pci_conf_read(pc, tag, PCI_INTERRUPT_REG); #ifdef DEBUG printf(" pin=%d line=%d ", PCI_INTERRUPT_PIN(reg), PCI_INTERRUPT_LINE(reg)); #endif - *ihp = PCI_INTERRUPT_LINE(reg) + 1; - return (*ihp == 0); + line = PCI_INTERRUPT_LINE(reg); + if (sc->sc_irq[line] == 0) + sc->sc_irq[line] = cpu_intr_findirq(); + *ihp = (line << APIC_INT_LINE_SHIFT) | sc->sc_irq[line]; + return (APIC_INT_IRQ(*ihp) == 0); } const char * @@ -98,7 +115,8 @@ apic_intr_string(void *v, pci_intr_handle_t ih) { static char buf[32]; - snprintf(buf, 32, "irq %ld", (ih + 8 - 1)); + snprintf(buf, 32, "line %ld irq %ld", + APIC_INT_LINE(ih), APIC_INT_IRQ(ih)); return (buf); } @@ -110,12 +128,14 @@ apic_intr_establish(void *v, pci_intr_handle_t ih, struct elroy_softc *sc = v; volatile struct elroy_regs *r = sc->sc_regs; hppa_hpa_t hpa = cpu_gethpa(0); - u_int32_t ent0; struct apic_iv *aiv, *biv; void *iv; + int irq = APIC_INT_IRQ(ih); + int line = APIC_INT_LINE(ih); + u_int32_t ent0; /* no mapping or bogus */ - if (ih <= 0 || ih > 31) + if (irq <= 0 || irq > 31) return (NULL); aiv = malloc(sizeof(struct apic_iv), M_DEVBUF, M_NOWAIT); @@ -127,32 +147,34 @@ apic_intr_establish(void *v, pci_intr_handle_t ih, aiv->handler = handler; aiv->arg = arg; aiv->next = NULL; - if (apic_intr_list[(ih + 8 - 1)]) { - biv = apic_intr_list[(ih + 8 - 1)]; + if (apic_intr_list[irq]) { + biv = apic_intr_list[irq]; while (biv->next) biv = biv->next; biv->next = aiv; return (arg); } - if ((iv = cpu_intr_establish(pri, (ih + 8 - 1), apic_intr, aiv, name))) { - ent0 = (31 - (ih + 8 - 1)) & APIC_ENT0_VEC; + if ((iv = cpu_intr_establish(pri, irq, apic_intr, aiv, name))) { + ent0 = (31 - irq) & APIC_ENT0_VEC; ent0 |= APIC_ENT0_LOW; ent0 |= APIC_ENT0_LEV; #if 0 if (cold) { - sc->sc_imr |= (1 << (ih + 8 - 1)); + sc->sc_imr |= (1 << irq); ent0 |= APIC_ENT0_MASK; } #endif - apic_write(sc->sc_regs, APIC_ENT0(ih - 1), APIC_ENT0_MASK); - apic_write(sc->sc_regs, APIC_ENT1(ih - 1), + apic_write(sc->sc_regs, APIC_ENT0(line), APIC_ENT0_MASK); + apic_write(sc->sc_regs, APIC_ENT1(line), ((hpa & 0x0ff00000) >> 4) | ((hpa & 0x000ff000) << 12)); - apic_write(sc->sc_regs, APIC_ENT0(ih - 1), ent0); + apic_write(sc->sc_regs, APIC_ENT0(line), ent0); - elroy_write32(&r->apic_eoi, htole32((31 - (ih + 8 - 1)) & APIC_ENT0_VEC)); + /* Signal EOI. */ + elroy_write32(&r->apic_eoi, + htole32((31 - irq) & APIC_ENT0_VEC)); - apic_intr_list[(ih + 8 - 1)] = aiv; + apic_intr_list[irq] = aiv; } return (arg); @@ -176,7 +198,9 @@ apic_intr(void *v) iv = iv->next; } - elroy_write32(&r->apic_eoi, htole32((31 - (iv->ih + 8 - 1)) & APIC_ENT0_VEC)); + /* Signal EOI. */ + elroy_write32(&r->apic_eoi, + htole32((31 - APIC_INT_IRQ(iv->ih)) & APIC_ENT0_VEC)); return (claimed); } diff --git a/sys/arch/hppa/dev/elroyvar.h b/sys/arch/hppa/dev/elroyvar.h index 48b2f74d7b1..20c2ed86d70 100644 --- a/sys/arch/hppa/dev/elroyvar.h +++ b/sys/arch/hppa/dev/elroyvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: elroyvar.h,v 1.1 2007/05/21 22:43:38 kettenis Exp $ */ +/* $OpenBSD: elroyvar.h,v 1.2 2007/05/27 16:36:07 kettenis Exp $ */ /* * Copyright (c) 2005 Michael Shalayeff @@ -29,6 +29,7 @@ struct elroy_softc { u_int32_t sc_imr; int sc_nints; + int *sc_irq; struct hppa_pci_chipset_tag sc_pc; struct hppa_bus_space_tag sc_iot; diff --git a/sys/arch/hppa/hppa/intr.c b/sys/arch/hppa/hppa/intr.c index e14d57e19f7..8a9dbbb7282 100644 --- a/sys/arch/hppa/hppa/intr.c +++ b/sys/arch/hppa/hppa/intr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: intr.c,v 1.22 2004/07/13 19:34:22 mickey Exp $ */ +/* $OpenBSD: intr.c,v 1.23 2007/05/27 16:36:07 kettenis Exp $ */ /* * Copyright (c) 2002-2004 Michael Shalayeff @@ -156,6 +156,18 @@ cpu_intr_init(void) ssm(PSL_I, mask); } +int +cpu_intr_findirq(void) +{ + int irq; + + for (irq = 0; irq < CPU_NINTS; irq++) + if (intr_table[irq].handler == NULL) + return irq; + + return -1; +} + void * cpu_intr_map(void *v, int pri, int irq, int (*handler)(void *), void *arg, const char *name) diff --git a/sys/arch/hppa/include/autoconf.h b/sys/arch/hppa/include/autoconf.h index 9c5acb6c2de..9e6d923a8cb 100644 --- a/sys/arch/hppa/include/autoconf.h +++ b/sys/arch/hppa/include/autoconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: autoconf.h,v 1.21 2004/09/15 20:11:29 mickey Exp $ */ +/* $OpenBSD: autoconf.h,v 1.22 2007/05/27 16:36:07 kettenis Exp $ */ /* * Copyright (c) 1998-2004 Michael Shalayeff @@ -72,6 +72,7 @@ const char *hppa_mod_info(int, int); void pdc_scanbus(struct device *, struct confargs *, int, hppa_hpa_t hpa); int mbprint(void *, const char *); int mbsubmatch(struct device *, void *, void *); +int cpu_intr_findirq(void); void *cpu_intr_map(void *v, int pri, int irq, int (*handler)(void *), void *arg, const char *name); void *cpu_intr_establish(int pri, int irq, int (*handler)(void *), -- cgit v1.2.3