diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2006-11-02 04:33:00 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2006-11-02 04:33:00 +0000 |
commit | 53d02d99ea277f36159561296e35f149d219a2f7 (patch) | |
tree | 7f38222a521072511010a08c0e7275dd07f9e535 /sys/dev | |
parent | 8ba1c65fb52377cc51d08bc15a56bf85ea7fe3f2 (diff) |
split the initialisation of the dma area up between the attach path and the
interface init path. the init path now does the allocation of the dmamaps
for both tx and rx, and allocates the mbufs for the rx ring.
the interface stop is now uncommented. it waits for the hardware to stop
working, and cleans up the bits allocated in the init path.
ifconfig vic0 up and ifconfig vic0 down both work now.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/if_vic.c | 173 |
1 files changed, 112 insertions, 61 deletions
diff --git a/sys/dev/pci/if_vic.c b/sys/dev/pci/if_vic.c index 91bf199fde5..ddc0807e619 100644 --- a/sys/dev/pci/if_vic.c +++ b/sys/dev/pci/if_vic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vic.c,v 1.22 2006/11/02 02:17:22 brad Exp $ */ +/* $OpenBSD: if_vic.c,v 1.23 2006/11/02 04:32:59 dlg Exp $ */ /* * Copyright (c) 2006 Reyk Floeter <reyk@openbsd.org> @@ -141,6 +141,7 @@ int vic_map_pci(struct vic_softc *, struct pci_attach_args *); int vic_query(struct vic_softc *); int vic_alloc_data(struct vic_softc *); int vic_init_data(struct vic_softc *sc); +int vic_uninit_data(struct vic_softc *sc); u_int32_t vic_read(struct vic_softc *, bus_size_t); void vic_write(struct vic_softc *, bus_size_t, u_int32_t); @@ -209,11 +210,6 @@ vic_attach(struct device *parent, struct device *self, void *aux) return; } - if (vic_init_data(sc) != 0) { - /* error printed by vic_alloc */ - return; - } - bcopy(sc->sc_lladdr, sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN); ifp = &sc->sc_ac.ac_if; @@ -335,6 +331,11 @@ vic_query(struct vic_softc *sc) int vic_alloc_data(struct vic_softc *sc) { + u_int8_t *kva; + u_int offset; + struct vic_rxdesc *rxd; + int i; + sc->sc_rxbuf = malloc(sizeof(struct vic_rxbuf) * sc->sc_nrxbuf, M_NOWAIT, M_DEVBUF); if (sc->sc_rxbuf == NULL) { @@ -357,6 +358,46 @@ vic_alloc_data(struct vic_softc *sc) printf("%s: unable to allocate dma region\n", DEVNAME(sc)); goto freetx; } + kva = VIC_DMA_KVA(sc); + + /* set up basic vic data */ + sc->sc_data = VIC_DMA_KVA(sc); + + sc->sc_data->vd_magic = VIC_MAGIC; + sc->sc_data->vd_length = sc->sc_dma_size; + + offset = sizeof(struct vic_data); + + /* set up the rx ring */ + sc->sc_rxq = (struct vic_rxdesc *)&kva[offset]; + + sc->sc_data->vd_rx_offset = offset; + sc->sc_data->vd_rx_length = sc->sc_nrxbuf; + + offset += sizeof(struct vic_rxdesc) * sc->sc_nrxbuf; + + /* set up the dummy rx ring 2 with an unusable entry */ + sc->sc_rxq2 = (struct vic_rxdesc *)&kva[offset]; + + sc->sc_data->vd_rx_offset2 = offset; + sc->sc_data->vd_rx_length2 = VIC_QUEUE2_SIZE; + + for (i = 0; i < VIC_QUEUE2_SIZE; i++) { + rxd = &sc->sc_rxq2[i]; + + rxd->rx_physaddr = 0; + rxd->rx_buflength = 0; + rxd->rx_length = 0; + rxd->rx_owner = VIC_OWNER_DRIVER; + + offset += sizeof(struct vic_rxdesc); + } + + /* set up the tx ring */ + sc->sc_txq = (struct vic_txdesc *)&kva[offset]; + + sc->sc_data->vd_tx_offset = offset; + sc->sc_data->vd_tx_length = sc->sc_ntxbuf; return (0); freetx: @@ -370,29 +411,12 @@ err: int vic_init_data(struct vic_softc *sc) { - u_int8_t *kva = VIC_DMA_KVA(sc); - u_int offset; - struct vic_rxbuf *rxb; struct vic_rxdesc *rxd; struct vic_txbuf *txb; int i; - /* set up basic vic data */ - sc->sc_data = VIC_DMA_KVA(sc); - - sc->sc_data->vd_magic = VIC_MAGIC; - sc->sc_data->vd_length = sc->sc_dma_size; - - offset = sizeof(struct vic_data); - - /* set up the rx ring */ - sc->sc_rxq = (struct vic_rxdesc *)&kva[offset]; - - sc->sc_data->vd_rx_offset = offset; - sc->sc_data->vd_rx_length = sc->sc_nrxbuf; - for (i = 0; i < sc->sc_nrxbuf; i++) { rxb = &sc->sc_rxbuf[i]; rxd = &sc->sc_rxq[i]; @@ -418,33 +442,8 @@ vic_init_data(struct vic_softc *sc) rxd->rx_buflength = rxb->rxb_m->m_pkthdr.len; /* XXX? */ rxd->rx_length = 0; rxd->rx_owner = VIC_OWNER_NIC; - - offset += sizeof(struct vic_rxdesc); - } - - /* set up the dummy rx ring 2 with an unusable entry */ - sc->sc_rxq2 = (struct vic_rxdesc *)&kva[offset]; - - sc->sc_data->vd_rx_offset2 = offset; - sc->sc_data->vd_rx_length2 = VIC_QUEUE2_SIZE; - - for (i = 0; i < VIC_QUEUE2_SIZE; i++) { - rxd = &sc->sc_rxq2[i]; - - rxd->rx_physaddr = 0; - rxd->rx_buflength = 0; - rxd->rx_length = 0; - rxd->rx_owner = VIC_OWNER_DRIVER; - - offset += sizeof(struct vic_rxdesc); } - /* set up the tx ring */ - sc->sc_txq = (struct vic_txdesc *)&kva[offset]; - - sc->sc_data->vd_tx_offset = offset; - sc->sc_data->vd_tx_length = sc->sc_ntxbuf; - for (i = 0; i < sc->sc_ntxbuf; i++) { txb = &sc->sc_txbuf[i]; if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, VIC_SG_MAX, @@ -477,6 +476,35 @@ freerxbs: return (1); } +int +vic_uninit_data(struct vic_softc *sc) +{ + struct vic_rxbuf *rxb; + struct vic_rxdesc *rxd; + struct vic_txbuf *txb; + + int i; + + for (i = 0; i < sc->sc_nrxbuf; i++) { + rxb = &sc->sc_rxbuf[i]; + rxd = &sc->sc_rxq[i]; + + bus_dmamap_sync(sc->sc_dmat, rxb->rxb_dmamap, 0, + rxb->rxb_m->m_pkthdr.len, BUS_DMASYNC_POSTREAD); + bus_dmamap_unload(sc->sc_dmat, rxb->rxb_dmamap); + bus_dmamap_destroy(sc->sc_dmat, rxb->rxb_dmamap); + + m_freem(rxb->rxb_m); + rxb->rxb_m = NULL; + } + + for (i = 0; i < sc->sc_ntxbuf; i++) { + txb = &sc->sc_txbuf[i]; + bus_dmamap_destroy(sc->sc_dmat, txb->txb_dmamap); + } + + return (0); +} void vic_link_state(struct vic_softc *sc) { @@ -523,6 +551,9 @@ vic_rx_proc(struct vic_softc *sc) struct mbuf *m; int len, idx; + if ((ifp->if_flags & IFF_RUNNING) == 0) + return; + bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); @@ -719,6 +750,9 @@ vic_start(struct ifnet *ifp) int i, idx; int tx = 0; + if (!(ifp->if_flags & IFF_RUNNING)) + return; + if (ifp->if_flags & IFF_OACTIVE) return; @@ -954,21 +988,32 @@ vic_init(struct ifnet *ifp) struct vic_softc *sc = (struct vic_softc *)ifp->if_softc; int s; + if (vic_init_data(sc) != 0) + return; + + sc->sc_data->vd_tx_curidx = 0; + sc->sc_data->vd_tx_nextidx = 0; + sc->sc_data->vd_tx_stopped = sc->sc_data->vd_tx_queued = 0; + + sc->sc_data->vd_rx_nextidx = 0; + sc->sc_data->vd_rx_nextidx2 = 0; + + sc->sc_data->vd_rx_saved_nextidx = 0; + sc->sc_data->vd_rx_saved_nextidx2 = 0; + sc->sc_data->vd_tx_saved_nextidx = 0; + bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); s = splnet(); - vic_write(sc, VIC_DATA_ADDR, VIC_DMA_DVA(sc)); - vic_write(sc, VIC_DATA_LENGTH, sc->sc_dma_size); if (ifp->if_flags & IFF_PROMISC) vic_iff(sc, VIC_CMD_IFF_PROMISC); else vic_iff(sc, VIC_CMD_IFF_BROADCAST | VIC_CMD_IFF_MULTICAST); - sc->sc_data->vd_tx_curidx = 0; - sc->sc_data->vd_tx_nextidx = 0; - sc->sc_data->vd_tx_stopped = sc->sc_data->vd_tx_queued = 0; + vic_write(sc, VIC_DATA_ADDR, VIC_DMA_DVA(sc)); + vic_write(sc, VIC_DATA_LENGTH, sc->sc_dma_size); ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; @@ -981,27 +1026,33 @@ vic_init(struct ifnet *ifp) void vic_stop(struct ifnet *ifp) { -#if 0 struct vic_softc *sc = (struct vic_softc *)ifp->if_softc; int s; s = splnet(); - sc->sc_txtimeout = 0; ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); -#ifdef notyet + bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + + /* XXX wait for tx to complete */ + while (sc->sc_txpending > 0) { + splx(s); + delay(1000); + s = splnet(); + } + + sc->sc_data->vd_tx_stopped = 1; + vic_write(sc, VIC_CMD, VIC_CMD_INTR_DISABLE); -#endif - vic_write(sc, VIC_DATA_ADDR, 0); vic_iff(sc, 0); + vic_write(sc, VIC_DATA_ADDR, 0); - sc->sc_data->vd_tx_stopped = 1; - timeout_del(&sc->sc_timer); + vic_uninit_data(sc); splx(s); -#endif } struct mbuf * |