summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2009-11-23 23:18:17 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2009-11-23 23:18:17 +0000
commit5fdc451887c832140fb81b64f4c5d7e40b34ccec (patch)
treef11e30023cc85c5d42be77c9041fc054b29001d4 /sys/dev/pci
parent78b3d0481abcba79662254f2549347ddaf8250e8 (diff)
Make vge(4) detachable.
ok jsg@, deraadt@
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/if_vge.c63
-rw-r--r--sys/dev/pci/if_vgevar.h4
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;