diff --git a/sys/dev/pci/pccbb.c b/sys/dev/pci/pccbb.c index 9a75492b61a3..5119a6bf8685 100644 --- a/sys/dev/pci/pccbb.c +++ b/sys/dev/pci/pccbb.c @@ -1,4 +1,4 @@ -/* $NetBSD: pccbb.c,v 1.79 2002/09/30 20:37:56 thorpej Exp $ */ +/* $NetBSD: pccbb.c,v 1.80 2002/10/01 09:09:16 haya Exp $ */ /* * Copyright (c) 1998, 1999 and 2000 @@ -31,7 +31,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: pccbb.c,v 1.79 2002/09/30 20:37:56 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pccbb.c,v 1.80 2002/10/01 09:09:16 haya Exp $"); /* #define CBB_DEBUG @@ -641,7 +641,7 @@ pccbb_pci_callback(self) pccbb_chipinit(sc); /* clear data structure for child device interrupt handlers */ - sc->sc_pil = NULL; + LIST_INIT(&sc->sc_pil); sc->sc_pil_intr_enable = 1; /* Map and establish the interrupt. */ @@ -1072,7 +1072,8 @@ pccbbintr_function(sc) struct pccbb_intrhand_list *pil; int s, splchanged; - for (pil = sc->sc_pil; pil != NULL; pil = pil->pil_next) { + for (pil = LIST_FIRST(&sc->sc_pil); pil != NULL; + pil = LIST_NEXT(pil, pil_next)) { /* * XXX priority change. gross. I use if-else * sentense instead of switch-case sentense because of @@ -1790,9 +1791,8 @@ pccbb_intr_establish(sc, irq, level, func, arg) DPRINTF(("pccbb_intr_establish start. %p\n", sc->sc_pil)); - if (sc->sc_pil == NULL) { - pccbb_intr_route(sc); - + if (LIST_EMPTY(&sc->sc_pil)) { + pccbb_intr_route(sc); } /* @@ -1807,14 +1807,14 @@ pccbb_intr_establish(sc, irq, level, func, arg) newpil->pil_func = func; newpil->pil_arg = arg; newpil->pil_level = level; - newpil->pil_next = NULL; - if (sc->sc_pil == NULL) { - sc->sc_pil = newpil; + if (LIST_EMPTY(&sc->sc_pil)) { + LIST_INSERT_HEAD(&sc->sc_pil, newpil, pil_next); } else { - for (pil = sc->sc_pil; pil->pil_next != NULL; - pil = pil->pil_next); - pil->pil_next = newpil; + for (pil = LIST_FIRST(&sc->sc_pil); + LIST_NEXT(pil, pil_next) != NULL; + pil = LIST_NEXT(pil, pil_next)); + LIST_INSERT_AFTER(pil, newpil, pil_next); } DPRINTF(("pccbb_intr_establish add pil. %p\n", sc->sc_pil)); @@ -1826,31 +1826,49 @@ pccbb_intr_establish(sc, irq, level, func, arg) * static void *pccbb_intr_disestablish(struct pccbb_softc *sc, * void *ih) * - * This function removes an interrupt handler pointed by ih. + * This function removes an interrupt handler pointed by ih. ih + * should be the value returned by cardbus_intr_establish() or + * NULL. + * + * When ih is NULL, this function will do nothing. */ static void pccbb_intr_disestablish(sc, ih) struct pccbb_softc *sc; void *ih; { - struct pccbb_intrhand_list *pil, **pil_prev; + struct pccbb_intrhand_list *pil; pcireg_t reg; DPRINTF(("pccbb_intr_disestablish start. %p\n", sc->sc_pil)); - pil_prev = &sc->sc_pil; + if (ih == NULL) { + /* intr handler is not set */ + DPRINTF(("pccbb_intr_disestablish: no ih\n")); + return; + } - for (pil = sc->sc_pil; pil != NULL; pil = pil->pil_next) { +#ifdef DIAGNOSTIC + for (pil = LIST_FIRST(&sc->sc_pil); pil != NULL; + pil = LIST_NEXT(pil, pil_next)) { + printf("pccbb_intr_disestablish: pil %p\n", pil); if (pil == ih) { - *pil_prev = pil->pil_next; - free(pil, M_DEVBUF); DPRINTF(("pccbb_intr_disestablish frees one pil\n")); break; } - pil_prev = &pil->pil_next; } + if (pil == NULL) { + panic("pccbb_intr_disestablish: %s cannot find pil %p", + sc->sc_dev.dv_xname, ih); + } +#endif - if (sc->sc_pil == NULL) { + pil = (struct pccbb_intrhand_list *)ih; + LIST_REMOVE(pil, pil_next); + free(pil, M_DEVBUF); + DPRINTF(("pccbb_intr_disestablish frees one pil\n")); + + if (LIST_EMPTY(&sc->sc_pil)) { /* No interrupt handlers */ DPRINTF(("pccbb_intr_disestablish: no interrupt handler\n")); diff --git a/sys/dev/pci/pccbbvar.h b/sys/dev/pci/pccbbvar.h index 29daab567ac2..81f8a6fb71cd 100644 --- a/sys/dev/pci/pccbbvar.h +++ b/sys/dev/pci/pccbbvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: pccbbvar.h,v 1.17 2001/11/02 03:32:34 haya Exp $ */ +/* $NetBSD: pccbbvar.h,v 1.18 2002/10/01 09:09:16 haya Exp $ */ /* * Copyright (c) 1999 HAYAKAWA Koichi. All rights reserved. * @@ -158,7 +158,7 @@ struct pccbb_softc { SIMPLEQ_HEAD(, pcic_event) sc_events; /* interrupt handler list on the bridge */ - struct pccbb_intrhand_list *sc_pil; + LIST_HEAD(, pccbb_intrhand_list) sc_pil; int sc_pil_intr_enable; /* can i call intr handler for child device? */ int sc_pwrmgt_offs; /* Offset for power management capability */ @@ -173,7 +173,7 @@ struct pccbb_intrhand_list { int (*pil_func) __P((void *)); void *pil_arg; int pil_level; - struct pccbb_intrhand_list *pil_next; + LIST_ENTRY(pccbb_intrhand_list) pil_next; }; void pccbb_intr_route __P((struct pccbb_softc *sc));