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;