diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2009-11-23 23:18:17 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2009-11-23 23:18:17 +0000 |
commit | 5fdc451887c832140fb81b64f4c5d7e40b34ccec (patch) | |
tree | f11e30023cc85c5d42be77c9041fc054b29001d4 /sys/dev/pci | |
parent | 78b3d0481abcba79662254f2549347ddaf8250e8 (diff) |
Make vge(4) detachable.
ok jsg@, deraadt@
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/if_vge.c | 63 | ||||
-rw-r--r-- | sys/dev/pci/if_vgevar.h | 4 |
2 files changed, 61 insertions, 6 deletions
diff --git a/sys/dev/pci/if_vge.c b/sys/dev/pci/if_vge.c index a03fb4e7efd..0f87d056054 100644 --- a/sys/dev/pci/if_vge.c +++ b/sys/dev/pci/if_vge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vge.c,v 1.45 2009/09/04 21:43:00 kettenis Exp $ */ +/* $OpenBSD: if_vge.c,v 1.46 2009/11/23 23:18:16 kettenis Exp $ */ /* $FreeBSD: if_vge.c,v 1.3 2004/09/11 22:13:25 wpaul Exp $ */ /* * Copyright (c) 2004 @@ -128,10 +128,12 @@ int vge_probe (struct device *, void *, void *); void vge_attach (struct device *, struct device *, void *); +int vge_detach (struct device *, int); int vge_encap (struct vge_softc *, struct mbuf *, int); int vge_allocmem (struct vge_softc *); +void vge_freemem (struct vge_softc *); int vge_newbuf (struct vge_softc *, int, struct mbuf *); int vge_rx_list_init (struct vge_softc *); int vge_tx_list_init (struct vge_softc *); @@ -164,7 +166,7 @@ void vge_setmulti (struct vge_softc *); void vge_reset (struct vge_softc *); struct cfattach vge_ca = { - sizeof(struct vge_softc), vge_probe, vge_attach + sizeof(struct vge_softc), vge_probe, vge_attach, vge_detach }; struct cfdriver vge_cd = { @@ -693,6 +695,32 @@ vge_allocmem(struct vge_softc *sc) return (0); } +void +vge_freemem(struct vge_softc *sc) +{ + int i; + + for (i = 0; i < VGE_RX_DESC_CNT; i++) + bus_dmamap_destroy(sc->sc_dmat, + sc->vge_ldata.vge_rx_dmamap[i]); + + bus_dmamap_unload(sc->sc_dmat, sc->vge_ldata.vge_rx_list_map); + bus_dmamap_destroy(sc->sc_dmat, sc->vge_ldata.vge_rx_list_map); + bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->vge_ldata.vge_rx_list, + VGE_RX_LIST_SZ); + bus_dmamem_free(sc->sc_dmat, &sc->vge_ldata.vge_rx_listseg, 1); + + for (i = 0; i < VGE_TX_DESC_CNT; i++) + bus_dmamap_destroy(sc->sc_dmat, + sc->vge_ldata.vge_tx_dmamap[i]); + + bus_dmamap_unload(sc->sc_dmat, sc->vge_ldata.vge_tx_list_map); + bus_dmamap_destroy(sc->sc_dmat, sc->vge_ldata.vge_tx_list_map); + bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->vge_ldata.vge_tx_list, + VGE_TX_LIST_SZ); + bus_dmamem_free(sc->sc_dmat, &sc->vge_ldata.vge_tx_listseg, 1); +} + /* * Attach the interface. Allocate softc structures, do ifmedia * setup and ethernet/BPF attach. @@ -708,15 +736,14 @@ vge_attach(struct device *parent, struct device *self, void *aux) const char *intrstr = NULL; struct ifnet *ifp; int error = 0; - bus_size_t iosize; /* * Map control/status registers. */ if (pci_mapreg_map(pa, VGE_PCI_LOMEM, PCI_MAPREG_TYPE_MEM, 0, - &sc->vge_btag, &sc->vge_bhandle, NULL, &iosize, 0)) { + &sc->vge_btag, &sc->vge_bhandle, NULL, &sc->vge_bsize, 0)) { if (pci_mapreg_map(pa, VGE_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0, - &sc->vge_btag, &sc->vge_bhandle, NULL, &iosize, 0)) { + &sc->vge_btag, &sc->vge_bhandle, NULL, &sc->vge_bsize, 0)) { printf(": can't map mem or i/o space\n"); return; } @@ -739,6 +766,7 @@ vge_attach(struct device *parent, struct device *self, void *aux) printf(": %s", intrstr); sc->sc_dmat = pa->pa_dmat; + sc->sc_pc = pa->pa_pc; /* Reset the adapter. */ vge_reset(sc); @@ -809,6 +837,31 @@ vge_attach(struct device *parent, struct device *self, void *aux) } int +vge_detach(struct device *self, int flags) +{ + struct vge_softc *sc = (void *)self; + struct ifnet *ifp = &sc->arpcom.ac_if; + + pci_intr_disestablish(sc->sc_pc, sc->vge_intrhand); + + vge_stop(sc); + + /* Detach all PHYs */ + mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY); + + /* Delete any remaining media. */ + ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY); + + ether_ifdetach(ifp); + if_detach(ifp); + + vge_freemem(sc); + + bus_space_unmap(sc->vge_btag, sc->vge_bhandle, sc->vge_bsize); + return (0); +} + +int vge_newbuf(struct vge_softc *sc, int idx, struct mbuf *m) { struct mbuf *m_new = NULL; diff --git a/sys/dev/pci/if_vgevar.h b/sys/dev/pci/if_vgevar.h index 9073695cbaf..d320409650f 100644 --- a/sys/dev/pci/if_vgevar.h +++ b/sys/dev/pci/if_vgevar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vgevar.h,v 1.3 2006/05/28 00:20:21 brad Exp $ */ +/* $OpenBSD: if_vgevar.h,v 1.4 2009/11/23 23:18:16 kettenis Exp $ */ /* $FreeBSD: if_vgevar.h,v 1.1 2004/09/10 20:57:45 wpaul Exp $ */ /* * Copyright (c) 2004 @@ -78,8 +78,10 @@ struct vge_softc { struct arpcom arpcom; /* interface info */ bus_space_handle_t vge_bhandle; /* bus space handle */ bus_space_tag_t vge_btag; /* bus space tag */ + bus_size_t vge_bsize; void *vge_intrhand; bus_dma_tag_t sc_dmat; + pci_chipset_tag_t sc_pc; struct mii_data sc_mii; int vge_if_flags; int vge_rx_consumed; |