diff options
Diffstat (limited to 'sys/dev/pci/if_sk.c')
-rw-r--r-- | sys/dev/pci/if_sk.c | 77 |
1 files changed, 67 insertions, 10 deletions
diff --git a/sys/dev/pci/if_sk.c b/sys/dev/pci/if_sk.c index ed97182d994..4745cdc5336 100644 --- a/sys/dev/pci/if_sk.c +++ b/sys/dev/pci/if_sk.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_sk.c,v 1.153 2009/08/13 14:24:47 jasper Exp $ */ +/* $OpenBSD: if_sk.c,v 1.154 2009/10/04 18:32:40 deraadt Exp $ */ /* * Copyright (c) 1997, 1998, 1999, 2000 @@ -133,9 +133,11 @@ int skc_probe(struct device *, void *, void *); void skc_attach(struct device *, struct device *self, void *aux); +int skc_detach(struct device *, int); void skc_shutdown(void *); int sk_probe(struct device *, void *, void *); void sk_attach(struct device *, struct device *self, void *aux); +int sk_detach(struct device *, int); int skcprint(void *, const char *); int sk_intr(void *); void sk_intr_bcom(struct sk_if_softc *); @@ -1028,8 +1030,7 @@ sk_attach(struct device *parent, struct device *self, void *aux) struct skc_attach_args *sa = aux; struct ifnet *ifp; caddr_t kva; - bus_dma_segment_t seg; - int i, rseg; + int i; sc_if->sk_port = sa->skc_port; sc_if->sk_softc = sc; @@ -1132,11 +1133,12 @@ sk_attach(struct device *parent, struct device *self, void *aux) /* Allocate the descriptor queues. */ if (bus_dmamem_alloc(sc->sc_dmatag, sizeof(struct sk_ring_data), - PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) { + PAGE_SIZE, 0, &sc_if->sk_ring_seg, 1, &sc_if->sk_ring_nseg, + BUS_DMA_NOWAIT)) { printf(": can't alloc rx buffers\n"); goto fail; } - if (bus_dmamem_map(sc->sc_dmatag, &seg, rseg, + if (bus_dmamem_map(sc->sc_dmatag, &sc_if->sk_ring_seg, sc_if->sk_ring_nseg, sizeof(struct sk_ring_data), &kva, BUS_DMA_NOWAIT)) { printf(": can't map dma buffers (%lu bytes)\n", (ulong)sizeof(struct sk_ring_data)); @@ -1236,7 +1238,7 @@ sk_attach(struct device *parent, struct device *self, void *aux) if_attach(ifp); ether_ifattach(ifp); - shutdownhook_establish(skc_shutdown, sc); + sc_if->sk_sdhook = shutdownhook_establish(skc_shutdown, sc); DPRINTFN(2, ("sk_attach: end\n")); return; @@ -1246,12 +1248,47 @@ fail_3: fail_2: bus_dmamem_unmap(sc->sc_dmatag, kva, sizeof(struct sk_ring_data)); fail_1: - bus_dmamem_free(sc->sc_dmatag, &seg, rseg); + bus_dmamem_free(sc->sc_dmatag, &sc_if->sk_ring_seg, sc_if->sk_ring_nseg); fail: sc->sk_if[sa->skc_port] = NULL; } int +sk_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 sk_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 skcprint(void *aux, const char *pnp) { struct skc_attach_args *sa = aux; @@ -1319,7 +1356,7 @@ skc_attach(struct device *parent, struct device *self, void *aux) */ memtype = pci_mapreg_type(pc, pa->pa_tag, SK_PCI_LOMEM); if (pci_mapreg_map(pa, SK_PCI_LOMEM, memtype, 0, &sc->sk_btag, - &sc->sk_bhandle, NULL, &size, 0)) { + &sc->sk_bhandle, NULL, &sc->sk_bsize, 0)) { printf(": can't map mem space\n"); return; } @@ -1328,6 +1365,7 @@ skc_attach(struct device *parent, struct device *self, void *aux) sc->sk_type = sk_win_read_1(sc, SK_CHIPVER); sc->sk_rev = (sk_win_read_1(sc, SK_CONFIG) >> 4); + sc->sk_pc = pc; /* bail out here if chip is not recognized */ if (! SK_IS_GENESIS(sc) && ! SK_IS_YUKON(sc)) { @@ -1489,6 +1527,25 @@ fail_1: } int +skc_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_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 sk_encap(struct sk_if_softc *sc_if, struct mbuf *m_head, u_int32_t *txidx) { struct sk_softc *sc = sc_if->sk_softc; @@ -2770,7 +2827,7 @@ sk_stop(struct sk_if_softc *sc_if) } struct cfattach skc_ca = { - sizeof(struct sk_softc), skc_probe, skc_attach, + sizeof(struct sk_softc), skc_probe, skc_attach, skc_detach }; struct cfdriver skc_cd = { @@ -2778,7 +2835,7 @@ struct cfdriver skc_cd = { }; struct cfattach sk_ca = { - sizeof(struct sk_if_softc), sk_probe, sk_attach, + sizeof(struct sk_if_softc), sk_probe, sk_attach, sk_detach }; struct cfdriver sk_cd = { |