diff options
-rw-r--r-- | sys/dev/pci/if_msk.c | 102 | ||||
-rw-r--r-- | sys/dev/pci/if_mskvar.h | 11 |
2 files changed, 93 insertions, 20 deletions
diff --git a/sys/dev/pci/if_msk.c b/sys/dev/pci/if_msk.c index e5d914af5c2..4cb11b2499d 100644 --- a/sys/dev/pci/if_msk.c +++ b/sys/dev/pci/if_msk.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_msk.c,v 1.59 2007/11/14 10:00:47 brad Exp $ */ +/* $OpenBSD: if_msk.c,v 1.60 2007/11/25 00:27:44 kettenis Exp $ */ /* * Copyright (c) 1997, 1998, 1999, 2000 @@ -133,10 +133,12 @@ int mskc_probe(struct device *, void *, void *); void mskc_attach(struct device *, struct device *self, void *aux); +int mskc_detach(struct device *, int); void mskc_reset(struct sk_softc *); void mskc_shutdown(void *); int msk_probe(struct device *, void *, void *); void msk_attach(struct device *, struct device *self, void *aux); +int msk_detach(struct device *, int); void msk_reset(struct sk_if_softc *); int mskcprint(void *, const char *); int msk_intr(void *); @@ -977,7 +979,7 @@ msk_reset(struct sk_if_softc *sc_if) void msk_attach(struct device *parent, struct device *self, void *aux) { - struct sk_if_softc *sc_if = (struct sk_if_softc *) self; + struct sk_if_softc *sc_if = (struct sk_if_softc *)self; struct sk_softc *sc = (struct sk_softc *)parent; struct skc_attach_args *sa = aux; struct ifnet *ifp; @@ -1113,7 +1115,7 @@ msk_attach(struct device *parent, struct device *self, void *aux) if_attach(ifp); ether_ifattach(ifp); - shutdownhook_establish(mskc_shutdown, sc); + sc_if->sk_sdhook = shutdownhook_establish(mskc_shutdown, sc); DPRINTFN(2, ("msk_attach: end\n")); return; @@ -1129,6 +1131,41 @@ fail: } int +msk_detach(struct device *self, int flags) +{ + struct sk_if_softc *sc_if = (struct sk_if_softc *)self; + struct sk_softc *sc = sc_if->sk_softc; + struct ifnet *ifp= &sc_if->arpcom.ac_if; + + if (sc->sk_if[sc_if->sk_port] == NULL) + return (0); + + timeout_del(&sc_if->sk_tick_ch); + + /* Detach any PHYs we might have. */ + if (LIST_FIRST(&sc_if->sk_mii.mii_phys) != NULL) + mii_detach(&sc_if->sk_mii, MII_PHY_ANY, MII_OFFSET_ANY); + + /* Delete any remaining media. */ + ifmedia_delete_instance(&sc_if->sk_mii.mii_media, IFM_INST_ANY); + + if (sc_if->sk_sdhook != NULL) + shutdownhook_disestablish(sc_if->sk_sdhook); + + ether_ifdetach(ifp); + if_detach(ifp); + + bus_dmamap_destroy(sc->sc_dmatag, sc_if->sk_ring_map); + bus_dmamem_unmap(sc->sc_dmatag, (caddr_t)sc_if->sk_rdata, + sizeof(struct msk_ring_data)); + bus_dmamem_free(sc->sc_dmatag, + &sc_if->sk_ring_seg, sc_if->sk_ring_nseg); + sc->sk_if[sc_if->sk_port] = NULL; + + return (0); +} + +int mskcprint(void *aux, const char *pnp) { struct skc_attach_args *sa = aux; @@ -1155,12 +1192,9 @@ mskc_attach(struct device *parent, struct device *self, void *aux) pcireg_t command, memtype; pci_intr_handle_t ih; const char *intrstr = NULL; - bus_size_t size; u_int8_t hw, pmd; char *revstr = NULL; caddr_t kva; - bus_dma_segment_t seg; - int rseg; DPRINTFN(2, ("begin mskc_attach\n")); @@ -1202,9 +1236,8 @@ mskc_attach(struct device *parent, struct device *self, void *aux) switch (memtype) { case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT: case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT: - if (pci_mapreg_map(pa, SK_PCI_LOMEM, - memtype, 0, &sc->sk_btag, &sc->sk_bhandle, - NULL, &size, 0) == 0) + if (pci_mapreg_map(pa, SK_PCI_LOMEM, memtype, 0, &sc->sk_btag, + &sc->sk_bhandle, NULL, &sc->sk_bsize, 0) == 0) break; default: printf(": can't map mem space\n"); @@ -1239,15 +1272,17 @@ mskc_attach(struct device *parent, struct device *self, void *aux) printf("\n"); goto fail_1; } + sc->sk_pc = pc; if (bus_dmamem_alloc(sc->sc_dmatag, - MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc), - PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) { + MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc), PAGE_SIZE, + 0, &sc->sk_status_seg, 1, &sc->sk_status_nseg, BUS_DMA_NOWAIT)) { printf(": can't alloc status buffers\n"); goto fail_2; } - if (bus_dmamem_map(sc->sc_dmatag, &seg, rseg, + if (bus_dmamem_map(sc->sc_dmatag, + &sc->sk_status_seg, sc->sk_status_nseg, MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc), &kva, BUS_DMA_NOWAIT)) { printf(": can't map dma buffers (%lu bytes)\n", @@ -1387,14 +1422,45 @@ mskc_attach(struct device *parent, struct device *self, void *aux) fail_5: bus_dmamap_destroy(sc->sc_dmatag, sc->sk_status_map); fail_4: - bus_dmamem_unmap(sc->sc_dmatag, kva, + bus_dmamem_unmap(sc->sc_dmatag, (caddr_t)sc->sk_status_ring, MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc)); fail_3: - bus_dmamem_free(sc->sc_dmatag, &seg, rseg); + bus_dmamem_free(sc->sc_dmatag, + &sc->sk_status_seg, sc->sk_status_nseg); + sc->sk_status_nseg = 0; fail_2: - pci_intr_disestablish(pc, sc->sk_intrhand); + pci_intr_disestablish(sc->sk_pc, sc->sk_intrhand); + sc->sk_intrhand = NULL; fail_1: - bus_space_unmap(sc->sk_btag, sc->sk_bhandle, size); + bus_space_unmap(sc->sk_btag, sc->sk_bhandle, sc->sk_bsize); + sc->sk_bsize = 0; +} + +int +mskc_detach(struct device *self, int flags) +{ + struct sk_softc *sc = (struct sk_softc *)self; + int rv; + + rv = config_detach_children(self, flags); + if (rv != 0) + return (rv); + + if (sc->sk_status_nseg > 0) { + bus_dmamap_destroy(sc->sc_dmatag, sc->sk_status_map); + bus_dmamem_unmap(sc->sc_dmatag, (caddr_t)sc->sk_status_ring, + MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc)); + bus_dmamem_free(sc->sc_dmatag, + &sc->sk_status_seg, sc->sk_status_nseg); + } + + if (sc->sk_intrhand) + pci_intr_disestablish(sc->sk_pc, sc->sk_intrhand); + + if (sc->sk_bsize > 0) + bus_space_unmap(sc->sk_btag, sc->sk_bhandle, sc->sk_bsize); + + return(0); } int @@ -2142,7 +2208,7 @@ msk_stop(struct sk_if_softc *sc_if) } struct cfattach mskc_ca = { - sizeof(struct sk_softc), mskc_probe, mskc_attach, + sizeof(struct sk_softc), mskc_probe, mskc_attach, mskc_detach }; struct cfdriver mskc_cd = { @@ -2150,7 +2216,7 @@ struct cfdriver mskc_cd = { }; struct cfattach msk_ca = { - sizeof(struct sk_if_softc), msk_probe, msk_attach, + sizeof(struct sk_if_softc), msk_probe, msk_attach, msk_detach }; struct cfdriver msk_cd = { diff --git a/sys/dev/pci/if_mskvar.h b/sys/dev/pci/if_mskvar.h index 014be904785..f02ec3c89a9 100644 --- a/sys/dev/pci/if_mskvar.h +++ b/sys/dev/pci/if_mskvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_mskvar.h,v 1.5 2007/05/12 18:19:54 kettenis Exp $ */ +/* $OpenBSD: if_mskvar.h,v 1.6 2007/11/25 00:27:44 kettenis Exp $ */ /* $NetBSD: if_skvar.h,v 1.6 2005/05/30 04:35:22 christos Exp $ */ /*- @@ -33,7 +33,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -/* $OpenBSD: if_mskvar.h,v 1.5 2007/05/12 18:19:54 kettenis Exp $ */ +/* $OpenBSD: if_mskvar.h,v 1.6 2007/11/25 00:27:44 kettenis Exp $ */ /* * Copyright (c) 1997, 1998, 1999, 2000 @@ -192,7 +192,9 @@ struct sk_softc { struct device sk_dev; /* generic device */ bus_space_handle_t sk_bhandle; /* bus space handle */ bus_space_tag_t sk_btag; /* bus space tag */ + bus_size_t sk_bsize; /* bus space size */ void *sk_intrhand; /* irq handler handle */ + pci_chipset_tag_t sk_pc; u_int8_t sk_fibertype; u_int8_t sk_type; u_int8_t sk_rev; @@ -204,6 +206,8 @@ struct sk_softc { struct sk_if_softc *sk_if[2]; struct msk_status_desc *sk_status_ring; bus_dmamap_t sk_status_map; + bus_dma_segment_t sk_status_seg; + int sk_status_nseg; int sk_status_idx; }; @@ -224,6 +228,8 @@ struct sk_if_softc { struct msk_chain_data sk_cdata; struct msk_ring_data *sk_rdata; bus_dmamap_t sk_ring_map; + bus_dma_segment_t sk_ring_seg; + int sk_ring_nseg; int sk_status_idx; struct sk_softc *sk_softc; /* parent controller */ int sk_tx_bmu; /* TX BMU register */ @@ -231,6 +237,7 @@ struct sk_if_softc { LIST_HEAD(__sk_jfreehead, sk_jpool_entry) sk_jfree_listhead; LIST_HEAD(__sk_jinusehead, sk_jpool_entry) sk_jinuse_listhead; SIMPLEQ_HEAD(__sk_txmaphead, sk_txmap_entry) sk_txmap_head; + void *sk_sdhook; }; struct skc_attach_args { |