summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2006-11-02 04:33:00 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2006-11-02 04:33:00 +0000
commit53d02d99ea277f36159561296e35f149d219a2f7 (patch)
tree7f38222a521072511010a08c0e7275dd07f9e535 /sys/dev
parent8ba1c65fb52377cc51d08bc15a56bf85ea7fe3f2 (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.c173
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 *