summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/pci/if_nx.c73
-rw-r--r--sys/dev/pci/if_nxreg.h35
2 files changed, 106 insertions, 2 deletions
diff --git a/sys/dev/pci/if_nx.c b/sys/dev/pci/if_nx.c
index 4c5cf03988f..0208f740981 100644
--- a/sys/dev/pci/if_nx.c
+++ b/sys/dev/pci/if_nx.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_nx.c,v 1.38 2007/05/03 20:50:56 reyk Exp $ */
+/* $OpenBSD: if_nx.c,v 1.39 2007/05/03 21:05:41 reyk Exp $ */
/*
* Copyright (c) 2007 Reyk Floeter <reyk@openbsd.org>
@@ -167,6 +167,13 @@ struct nx_softc {
bus_space_tag_t nx_memt; /* pointer to sc_memt */
bus_space_handle_t nx_memh; /* port phy subregion */
+ bus_dmamap_t nx_dma_map;
+ bus_dma_segment_t nx_dma_seg;
+ size_t nx_dma_size;
+ caddr_t nx_dma_kva;
+
+ struct nx_ringcontext *nx_rc; /* Rx, Tx, Status */
+
struct nxb_softc *nx_sc; /* The nxb board */
struct nxb_port *nx_port; /* Port information */
void *nx_ih;
@@ -219,6 +226,9 @@ void nx_writephy(struct nx_softc *, bus_size_t, u_int32_t);
u_int32_t nx_readcrb(struct nx_softc *, enum nxsw_portreg);
void nx_writecrb(struct nx_softc *, enum nxsw_portreg, u_int32_t);
+int nx_dma_alloc(struct nx_softc *);
+void nx_dma_free(struct nx_softc *);
+
struct cfdriver nxb_cd = {
0, "nxb", DV_DULL
};
@@ -1251,6 +1261,12 @@ nx_attach(struct device *parent, struct device *self, void *aux)
return;
}
+ if (nx_dma_alloc(nx) != 0) {
+ printf(": unable to allocate dma memory\n");
+ pci_intr_disestablish(sc->sc_pc, nx->nx_ih);
+ return;
+ }
+
bcopy(nxp->nxp_lladdr, nx->nx_ac.ac_enaddr, ETHER_ADDR_LEN);
printf(", address %s\n", ether_sprintf(nx->nx_ac.ac_enaddr));
@@ -1571,3 +1587,58 @@ nx_writecrb(struct nx_softc *nx, enum nxsw_portreg n, u_int32_t val)
bus_space_barrier(nx->nx_memt, nx->nx_memh, reg, 4,
BUS_SPACE_BARRIER_WRITE);
}
+
+int
+nx_dma_alloc(struct nx_softc *nx)
+{
+ struct nxb_softc *sc = nx->nx_sc;
+ int nsegs;
+
+ /*
+ * One DMA'ed ring context per virtual port
+ */
+
+ nx->nx_dma_size = sizeof(struct nx_ringcontext);
+
+ if (bus_dmamap_create(sc->sc_dmat, nx->nx_dma_size, 1,
+ nx->nx_dma_size, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
+ &nx->nx_dma_map) != 0)
+ goto err;
+
+ if (bus_dmamem_alloc(sc->sc_dmat, nx->nx_dma_size,
+ NX_DMA_ALIGN, 0, &nx->nx_dma_seg, 1, &nsegs, BUS_DMA_NOWAIT) != 0)
+ goto destroy;
+
+ if (bus_dmamem_map(sc->sc_dmat, &nx->nx_dma_seg, nsegs,
+ nx->nx_dma_size, &nx->nx_dma_kva, BUS_DMA_NOWAIT) != 0)
+ goto free;
+
+ if (bus_dmamap_load(sc->sc_dmat, nx->nx_dma_map, nx->nx_dma_kva,
+ nx->nx_dma_size, NULL, BUS_DMA_NOWAIT) != 0)
+ goto unmap;
+
+ bzero(nx->nx_dma_kva, nx->nx_dma_size);
+ nx->nx_rc = (struct nx_ringcontext *)nx->nx_dma_kva;
+
+ return (0);
+
+ unmap:
+ bus_dmamem_unmap(sc->sc_dmat, nx->nx_dma_kva, nx->nx_dma_size);
+ free:
+ bus_dmamem_free(sc->sc_dmat, &nx->nx_dma_seg, 1);
+ destroy:
+ bus_dmamap_destroy(sc->sc_dmat, nx->nx_dma_map);
+ err:
+ return (1);
+}
+
+void
+nx_dma_free(struct nx_softc *nx)
+{
+ struct nxb_softc *sc = nx->nx_sc;
+
+ bus_dmamap_unload(sc->sc_dmat, nx->nx_dma_map);
+ bus_dmamem_unmap(sc->sc_dmat, nx->nx_dma_kva, nx->nx_dma_size);
+ bus_dmamem_free(sc->sc_dmat, &nx->nx_dma_seg, 1);
+ bus_dmamap_destroy(sc->sc_dmat, nx->nx_dma_map);
+}
diff --git a/sys/dev/pci/if_nxreg.h b/sys/dev/pci/if_nxreg.h
index 82cee19e4a0..e10b9dde8b6 100644
--- a/sys/dev/pci/if_nxreg.h
+++ b/sys/dev/pci/if_nxreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_nxreg.h,v 1.21 2007/05/03 20:50:56 reyk Exp $ */
+/* $OpenBSD: if_nxreg.h,v 1.22 2007/05/03 21:05:41 reyk Exp $ */
/*
* Copyright (c) 2007 Reyk Floeter <reyk@openbsd.org>
@@ -34,6 +34,8 @@
#define NX_MAX_MTU ETHER_MTU
#define NX_JUMBO_MTU 8000 /* less than 9k */
+#define NX_DMA_ALIGN 8 /* 64bit alignment */
+
#define NX_POLL_SENSOR 10 /* read temp sensor every 10s */
/* This driver supported the 3.4.31 (3.4.xx) NIC firmware */
@@ -137,6 +139,37 @@ struct nx_statusdesc {
#define NX_STSDESC_PROTO_M 0x003c
} __packed;
+struct nx_rxcontext {
+ u_int32_t rc_ringaddr_low;
+ u_int32_t rc_ringaddr_high;
+ u_int32_t rc_ringsize;
+ u_int32_t rc_reserved;
+} __packed;
+
+#define NX_NRXCONTEXT 3
+
+/* DMA-mapped ring context for the Rx, Tx, and Status rings */
+struct nx_ringcontext {
+ u_int64_t rc_txconsumer_off;
+ u_int32_t rc_txringaddr_low;
+ u_int32_t rc_txringaddr_high;
+
+ u_int32_t rc_txring_size;
+
+ struct nx_rxcontext rc_rxcontext[NX_NRXCONTEXT];
+
+ u_int32_t rc_statusringaddr_low;
+ u_int32_t rc_statusringaddr_high;
+ u_int32_t rc_statusring_size;
+
+ u_int32_t rc_id; /* context identifier */
+
+ /* d3 state register, dummy dma address */
+ u_int64_t rc_reserved[2];
+
+ u_int32_t rc_align; /* 64bit aligned */
+} __packed;
+
/*
* Memory layout
*/