From cf784f4497d8e00001b9d174f1ae616c538c7057 Mon Sep 17 00:00:00 2001 From: dyoung Date: Sun, 16 Dec 2007 21:28:30 +0000 Subject: [PATCH] Improve pci, cbb, cardslot, cardbus, and pcmcia to support detachment of this entire device tree: pci0 at mainbus0 elansc0 at pci0 gpio0 at elansc0 cbb0 at pci0 cardslot0 at cbb0 cardbus0 at cardslot0 pcmcia0 at cardslot0 cbb1 at pci0 cardslot1 at cbb1 cardbus1 at cardslot1 rtw0 at cardbus1 pcmcia1 at cardslot1 sip0 at pci0 nsphyter0 at sip0 sip1 at pci0 nsphyter1 at sip1 Whew! --- sys/dev/cardbus/cardbus.c | 19 ++++++++++-- sys/dev/cardbus/cardslot.c | 26 ++++++++++++++-- sys/dev/pci/pccbb.c | 63 +++++++++++++++++++++++++++++++++++--- sys/dev/pci/pccbbvar.h | 4 ++- sys/dev/pci/pci.c | 8 +++-- sys/dev/pcmcia/pcmcia.c | 19 ++++++++++-- 6 files changed, 122 insertions(+), 17 deletions(-) diff --git a/sys/dev/cardbus/cardbus.c b/sys/dev/cardbus/cardbus.c index d52caf5f88aa..57f06b855779 100644 --- a/sys/dev/cardbus/cardbus.c +++ b/sys/dev/cardbus/cardbus.c @@ -1,4 +1,4 @@ -/* $NetBSD: cardbus.c,v 1.81 2007/12/09 20:27:55 jmcneill Exp $ */ +/* $NetBSD: cardbus.c,v 1.82 2007/12/16 21:28:30 dyoung Exp $ */ /* * Copyright (c) 1997, 1998, 1999 and 2000 @@ -33,7 +33,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: cardbus.c,v 1.81 2007/12/09 20:27:55 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cardbus.c,v 1.82 2007/12/16 21:28:30 dyoung Exp $"); #include "opt_cardbus.h" @@ -70,6 +70,7 @@ __KERNEL_RCSID(0, "$NetBSD: cardbus.c,v 1.81 2007/12/09 20:27:55 jmcneill Exp $" STATIC void cardbusattach(struct device *, struct device *, void *); +STATIC int cardbusdetach(device_t, int); STATIC int cardbusmatch(struct device *, struct cfdata *, void *); int cardbus_rescan(struct device *, const char *, const int *); void cardbus_childdetached(struct device *, struct device *); @@ -91,7 +92,7 @@ static void disable_function(struct cardbus_softc *, int); static bool cardbus_child_register(device_t); CFATTACH_DECL2(cardbus, sizeof(struct cardbus_softc), - cardbusmatch, cardbusattach, NULL, NULL, + cardbusmatch, cardbusattach, cardbusdetach, NULL, cardbus_rescan, cardbus_childdetached); #ifndef __NetBSD_Version__ @@ -148,6 +149,18 @@ cardbusattach(struct device *parent, struct device *self, void *aux) aprint_error_dev(self, "couldn't establish power handler\n"); } +STATIC int +cardbusdetach(device_t self, int flags) +{ + int rc; + + if ((rc = config_detach_children(self, flags)) != 0) + return rc; + + pmf_device_deregister(self); + return 0; +} + static int cardbus_read_tuples(struct cardbus_attach_args *ca, cardbusreg_t cis_ptr, u_int8_t *tuples, size_t len) diff --git a/sys/dev/cardbus/cardslot.c b/sys/dev/cardbus/cardslot.c index 053e0d19d8bd..10fce0ecc61b 100644 --- a/sys/dev/cardbus/cardslot.c +++ b/sys/dev/cardbus/cardslot.c @@ -1,4 +1,4 @@ -/* $NetBSD: cardslot.c,v 1.38 2007/12/09 20:27:55 jmcneill Exp $ */ +/* $NetBSD: cardslot.c,v 1.39 2007/12/16 21:28:31 dyoung Exp $ */ /* * Copyright (c) 1999 and 2000 @@ -33,7 +33,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: cardslot.c,v 1.38 2007/12/09 20:27:55 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cardslot.c,v 1.39 2007/12/16 21:28:31 dyoung Exp $"); #include "opt_cardslot.h" @@ -66,6 +66,7 @@ __KERNEL_RCSID(0, "$NetBSD: cardslot.c,v 1.38 2007/12/09 20:27:55 jmcneill Exp $ STATIC void cardslotattach(struct device *, struct device *, void *); +STATIC int cardslotdetach(device_t, int); STATIC int cardslotmatch(struct device *, struct cfdata *, void *); static void cardslot_event_thread(void *arg); @@ -76,7 +77,7 @@ static int cardslot_16_submatch(struct device *, struct cfdata *, const int *, void *); CFATTACH_DECL(cardslot, sizeof(struct cardslot_softc), - cardslotmatch, cardslotattach, NULL, NULL); + cardslotmatch, cardslotattach, cardslotdetach, NULL); STATIC int cardslotmatch(struct device *parent, struct cfdata *cf, @@ -171,7 +172,26 @@ cardslotattach(struct device *parent, struct device *self, aprint_error_dev(self, "couldn't establish power handler\n"); } +STATIC int +cardslotdetach(device_t self, int flags) +{ + int rc; + struct cardslot_softc *sc = device_private(self); + if ((rc = config_detach_children(self, flags)) != 0) + return rc; + + sc->sc_th_enable = 0; + wakeup(&sc->sc_events); + while (sc->sc_event_thread != NULL) + (void)tsleep(sc, PWAIT, "cardslotthd", 0); + + if (!SIMPLEQ_EMPTY(&sc->sc_events)) + aprint_error_dev(self, "events outstanding"); + + pmf_device_deregister(self); + return 0; +} STATIC int cardslot_cb_print(void *aux, const char *pnp) diff --git a/sys/dev/pci/pccbb.c b/sys/dev/pci/pccbb.c index 65be24c82e4c..27cb8d3153e7 100644 --- a/sys/dev/pci/pccbb.c +++ b/sys/dev/pci/pccbb.c @@ -1,4 +1,4 @@ -/* $NetBSD: pccbb.c,v 1.157 2007/12/11 11:11:22 martin Exp $ */ +/* $NetBSD: pccbb.c,v 1.158 2007/12/16 21:28:31 dyoung Exp $ */ /* * Copyright (c) 1998, 1999 and 2000 @@ -31,7 +31,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: pccbb.c,v 1.157 2007/12/11 11:11:22 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pccbb.c,v 1.158 2007/12/16 21:28:31 dyoung Exp $"); /* #define CBB_DEBUG @@ -110,6 +110,7 @@ delay_ms(int millis, void *param) int pcicbbmatch(struct device *, struct cfdata *, void *); void pccbbattach(struct device *, struct device *, void *); +int pccbbdetach(device_t, int); int pccbbintr(void *); static void pci113x_insert(void *); static int pccbbintr_function(struct pccbb_softc *); @@ -225,7 +226,7 @@ static void cb_show_regs(pci_chipset_tag_t pc, pcitag_t tag, #endif CFATTACH_DECL(cbb_pci, sizeof(struct pccbb_softc), - pcicbbmatch, pccbbattach, NULL, NULL); + pcicbbmatch, pccbbattach, pccbbdetach, NULL); static struct pcmcia_chip_functions pccbb_pcmcia_funcs = { pccbb_pcmcia_mem_alloc, @@ -434,7 +435,7 @@ pccbbattach(struct device *parent, struct device *self, void *aux) PCI_MAPREG_MEM_ADDR(sock_base) != 0xfffffff0) { /* The address must be valid. */ if (pci_mapreg_map(pa, PCI_SOCKBASE, PCI_MAPREG_TYPE_MEM, 0, - &sc->sc_base_memt, &sc->sc_base_memh, &sockbase, NULL)) { + &sc->sc_base_memt, &sc->sc_base_memh, &sockbase, &sc->sc_base_size)) { aprint_error("%s: can't map socket base address 0x%lx\n", sc->sc_dev.dv_xname, (unsigned long)sock_base); /* @@ -443,7 +444,7 @@ pccbbattach(struct device *parent, struct device *self, void *aux) */ if (pci_mapreg_map(pa, PCI_SOCKBASE, PCI_MAPREG_TYPE_IO, 0, &sc->sc_base_memt, &sc->sc_base_memh, &sockbase, - NULL)) { + &sc->sc_base_size)) { aprint_error("%s: can't map socket base address" " 0x%lx: io mode\n", sc->sc_dev.dv_xname, (unsigned long)sockbase); @@ -515,8 +516,60 @@ pccbbattach(struct device *parent, struct device *self, void *aux) config_defer(self, pccbb_pci_callback); } +int +pccbbdetach(device_t self, int flags) +{ + struct pccbb_softc *sc = device_private(self); + pci_chipset_tag_t pc = sc->sc_pa.pa_pc; + bus_space_tag_t bmt = sc->sc_base_memt; + bus_space_handle_t bmh = sc->sc_base_memh; + uint32_t sockmask; + int rc; + if ((rc = config_detach_children(self, flags)) != 0) + return rc; + if (sc->sc_ih != NULL) { + pci_intr_disestablish(pc, sc->sc_ih); + sc->sc_ih = NULL; + } + + /* CSC Interrupt: turn off card detect and power cycle interrupts */ + sockmask = bus_space_read_4(bmt, bmh, CB_SOCKET_MASK); + sockmask &= ~(CB_SOCKET_MASK_CD | CB_SOCKET_MASK_POWER); + bus_space_write_4(bmt, bmh, CB_SOCKET_MASK, sockmask); + /* reset interrupt */ + bus_space_write_4(bmt, bmh, CB_SOCKET_EVENT, + bus_space_read_4(bmt, bmh, CB_SOCKET_EVENT)); + + switch (sc->sc_flags & (CBB_MEMHMAPPED|CBB_SPECMAPPED)) { + case CBB_MEMHMAPPED: + bus_space_unmap(bmt, bmh, sc->sc_base_size); + break; + case CBB_MEMHMAPPED|CBB_SPECMAPPED: +#if rbus + { + pcireg_t sockbase; + + sockbase = pci_conf_read(pc, sc->sc_tag, PCI_SOCKBASE); + rbus_space_free(sc->sc_rbus_memt, bmh, 0x1000, + NULL); + } +#else + bus_space_free(bmt, bmh, 0x1000); +#endif + } + sc->sc_flags &= ~(CBB_MEMHMAPPED|CBB_SPECMAPPED); + + if (!TAILQ_EMPTY(&sc->sc_iowindow)) + aprint_error_dev(self, "i/o windows not empty"); + if (!TAILQ_EMPTY(&sc->sc_memwindow)) + aprint_error_dev(self, "memory windows not empty"); + + callout_stop(&sc->sc_insert_ch); + callout_destroy(&sc->sc_insert_ch); + return 0; +} /* * static void pccbb_pci_callback(struct device *self) diff --git a/sys/dev/pci/pccbbvar.h b/sys/dev/pci/pccbbvar.h index 2a26c932293b..eba7eeb1ec5c 100644 --- a/sys/dev/pci/pccbbvar.h +++ b/sys/dev/pci/pccbbvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: pccbbvar.h,v 1.30 2007/12/09 20:28:11 jmcneill Exp $ */ +/* $NetBSD: pccbbvar.h,v 1.31 2007/12/16 21:28:32 dyoung Exp $ */ /* * Copyright (c) 1999 HAYAKAWA Koichi. All rights reserved. * @@ -110,6 +110,7 @@ struct pccbb_softc { bus_space_tag_t sc_base_memt; bus_space_handle_t sc_base_memh; + bus_size_t sc_base_size; struct callout sc_insert_ch; @@ -122,6 +123,7 @@ struct pccbb_softc { #define CBB_16BITCARD 0x04 #define CBB_32BITCARD 0x08 #define CBB_MEMHMAPPED 0x02000000 +#define CBB_SPECMAPPED 0x04000000 /* "special" mapping */ pci_chipset_tag_t sc_pc; pcitag_t sc_tag; diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index 87211c3708df..bd86c65331ad 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: pci.c,v 1.107 2007/12/09 20:28:11 jmcneill Exp $ */ +/* $NetBSD: pci.c,v 1.108 2007/12/16 21:28:32 dyoung Exp $ */ /* * Copyright (c) 1995, 1996, 1997, 1998 @@ -36,7 +36,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.107 2007/12/09 20:28:11 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.108 2007/12/16 21:28:32 dyoung Exp $"); #include "opt_pci.h" @@ -209,6 +209,10 @@ fail: static int pcidetach(struct device *self, int flags) { + int rc; + + if ((rc = config_detach_children(self, flags)) != 0) + return rc; pmf_device_deregister(self); return 0; } diff --git a/sys/dev/pcmcia/pcmcia.c b/sys/dev/pcmcia/pcmcia.c index 059fe6f69d26..f29c1f1f4b36 100644 --- a/sys/dev/pcmcia/pcmcia.c +++ b/sys/dev/pcmcia/pcmcia.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcmcia.c,v 1.84 2007/12/09 20:28:14 jmcneill Exp $ */ +/* $NetBSD: pcmcia.c,v 1.85 2007/12/16 21:28:30 dyoung Exp $ */ /* * Copyright (c) 2004 Charles M. Hannum. All rights reserved. @@ -48,7 +48,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: pcmcia.c,v 1.84 2007/12/09 20:28:14 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pcmcia.c,v 1.85 2007/12/16 21:28:30 dyoung Exp $"); #include "opt_pcmciaverbose.h" @@ -82,12 +82,13 @@ int pcmcia_verbose = 0; int pcmcia_match(struct device *, struct cfdata *, void *); void pcmcia_attach(struct device *, struct device *, void *); +int pcmcia_detach(device_t, int); int pcmcia_rescan(struct device *, const char *, const int *); void pcmcia_childdetached(struct device *, struct device *); int pcmcia_print(void *, const char *); CFATTACH_DECL2(pcmcia, sizeof(struct pcmcia_softc), - pcmcia_match, pcmcia_attach, NULL, NULL, + pcmcia_match, pcmcia_attach, pcmcia_detach, NULL, pcmcia_rescan, pcmcia_childdetached); int @@ -145,6 +146,18 @@ pcmcia_attach(struct device *parent, struct device *self, void *aux) aprint_error_dev(self, "couldn't establish power handler\n"); } +int +pcmcia_detach(device_t self, int flags) +{ + int rc; + + if ((rc = config_detach_children(self, flags)) != 0) + return rc; + + pmf_device_deregister(self); + return 0; +} + int pcmcia_card_attach(dev) struct device *dev;