summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2006-10-17 19:40:40 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2006-10-17 19:40:40 +0000
commit2a11b595da5be15d0b96062f21c6b158c2afa031 (patch)
tree88b42d7cb40792a46f2e09e87f66db537ff2f4fd
parentaa40fe66b973b6ed8d8c01c9f8e062722bed7cc9 (diff)
Allocate and free TX DMA rings additionally change some of the structures to
match more the actual reality. Still unsure about it as we don't have any documentation to verify against. OK mglocker@
-rw-r--r--sys/dev/ic/malo.c198
-rw-r--r--sys/dev/ic/malo.h22
2 files changed, 194 insertions, 26 deletions
diff --git a/sys/dev/ic/malo.c b/sys/dev/ic/malo.c
index 882b9e0c0f1..e03d3dda1f4 100644
--- a/sys/dev/ic/malo.c
+++ b/sys/dev/ic/malo.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: malo.c,v 1.5 2006/10/17 10:31:26 claudio Exp $ */
+/* $OpenBSD: malo.c,v 1.6 2006/10/17 19:40:39 claudio Exp $ */
/*
* Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org>
@@ -66,20 +66,45 @@ struct malo_rx_data {
struct mbuf *m;
};
+struct malo_tx_data {
+ bus_dmamap_t map;
+ struct mbuf *m;
+ /* additional info for rate adaption */
+// struct ieee80211_node *ni;
+// struct ieee80211_rssdesc id;
+};
+
/* Rx descriptor used by HW */
struct malo_rx_desc {
- uint8_t status;
+ uint8_t rxctrl;
uint8_t rssi;
- uint16_t reserved1; /* needs to be 1 */
+ uint8_t status;
+ uint8_t channel;
uint16_t len;
- uint8_t reserved2; /* actually unkown */
- uint8_t reserved3;
+ uint8_t reserved1; /* actually unused */
+ uint8_t datarate;
uint32_t physdata; /* DMA address of data */
uint32_t physnext; /* DMA address of next control block */
- uint32_t id; /* id for the host to id buffer ??? */
+ uint16_t qosctrl;
+ uint16_t reserved2;
} __packed;
-#define MALO_RX_RING_COUNT 48
+struct malo_tx_desc {
+ uint32_t status;
+ uint8_t datarate;
+ uint8_t txpriority;
+ uint16_t qosctrl;
+ uint32_t physdata; /* DMA address of data */
+ uint16_t len;
+ uint8_t destaddr[6];
+ uint32_t physnext; /* DMA address of next control block */
+ uint32_t reserved1; /* SAP packet info ??? */
+ uint32_t reserved2;
+} __packed;
+
+#define MALO_RX_RING_COUNT 256
+#define MALO_TX_RING_COUNT 256
+#define MALO_MAX_SCATTER 8 /* XXX unknown, wild guess */
/* firmware commands as found in a document describing the Libertas FW */
#define MALO_CMD_GET_HW_SPEC 0x0003
@@ -95,16 +120,19 @@ struct malo_cmdheader {
struct malo_hw_spec {
uint16_t HwVersion;
- uint16_t NumOfWCB; /* reserved */
+ uint16_t NumOfWCB;
uint16_t NumOfMCastAdr;
uint8_t PermanentAddress[6];
uint16_t RegionCode;
uint16_t NumberOfAntenna;
uint32_t FWReleaseNumber;
- uint32_t RxPdRd1Ptr;
- uint32_t RxPdRd2Ptr;
+ uint32_t WcbBase0;
uint32_t RxPdWrPtr;
+ uint32_t RxPdRdPtr;
uint32_t CookiePtr;
+ uint32_t WcbBase1;
+ uint32_t WcbBase2;
+ uint32_t WcbBase3;
} __packed;
@@ -136,6 +164,9 @@ void malo_free_cmd(struct malo_softc *sc);
int malo_alloc_rx_ring(struct malo_softc *sc, struct malo_rx_ring *ring,
int count);
void malo_free_rx_ring(struct malo_softc *sc, struct malo_rx_ring *ring);
+int malo_alloc_tx_ring(struct malo_softc *sc, struct malo_tx_ring *ring,
+ int count);
+void malo_free_tx_ring(struct malo_softc *sc, struct malo_tx_ring *ring);
int malo_load_bootimg(struct malo_softc *sc);
int malo_load_firmware(struct malo_softc *sc);
int malo_send_cmd(struct malo_softc *sc, bus_addr_t addr, uint32_t waitfor);
@@ -213,8 +244,8 @@ malo_attach(struct malo_softc *sc)
#endif
/* allocate DMA structures */
malo_alloc_cmd(sc);
- malo_alloc_rx_ring(sc, &sc->sc_rxring0, MALO_RX_RING_COUNT);
- malo_alloc_rx_ring(sc, &sc->sc_rxring1, MALO_RX_RING_COUNT);
+ malo_alloc_rx_ring(sc, &sc->sc_rxring, MALO_RX_RING_COUNT);
+ malo_alloc_tx_ring(sc, &sc->sc_txring, MALO_TX_RING_COUNT);
/* setup interface */
ifp->if_softc = sc;
@@ -279,8 +310,8 @@ malo_detach(void *arg)
ieee80211_ifdetach(ifp);
if_detach(ifp);
malo_free_cmd(sc);
- malo_free_rx_ring(sc, &sc->sc_rxring0);
- malo_free_rx_ring(sc, &sc->sc_rxring1);
+ malo_free_rx_ring(sc, &sc->sc_rxring);
+ malo_free_tx_ring(sc, &sc->sc_txring);
return (0);
}
@@ -441,7 +472,6 @@ malo_alloc_rx_ring(struct malo_softc *sc, struct malo_rx_ring *ring, int count)
desc->physdata = htole32(data->map->dm_segs->ds_addr);
desc->physnext = htole32(ring->physaddr +
(i + 1) % count * sizeof(struct malo_rx_desc));
- desc->id = i; /* ignored by the card ??? */
}
bus_dmamap_sync(sc->sc_dmat, ring->map, 0, ring->map->dm_mapsize,
@@ -488,6 +518,125 @@ malo_free_rx_ring(struct malo_softc *sc, struct malo_rx_ring *ring)
}
int
+malo_alloc_tx_ring(struct malo_softc *sc, struct malo_tx_ring *ring,
+ int count)
+{
+ int i, nsegs, error;
+
+ ring->count = count;
+ ring->queued = 0;
+ ring->cur = ring->next = ring->stat = 0;
+
+ error = bus_dmamap_create(sc->sc_dmat,
+ count * sizeof(struct malo_tx_desc), 1,
+ count * sizeof(struct malo_tx_desc), 0, BUS_DMA_NOWAIT, &ring->map);
+ if (error != 0) {
+ printf("%s: could not create desc DMA map\n",
+ sc->sc_dev.dv_xname);
+ goto fail;
+ }
+
+ error = bus_dmamem_alloc(sc->sc_dmat,
+ count * sizeof(struct malo_tx_desc),
+ PAGE_SIZE, 0, &ring->seg, 1, &nsegs, BUS_DMA_NOWAIT);
+ if (error != 0) {
+ printf("%s: could not allocate DMA memory\n",
+ sc->sc_dev.dv_xname);
+ goto fail;
+ }
+
+ error = bus_dmamem_map(sc->sc_dmat, &ring->seg, nsegs,
+ count * sizeof(struct malo_tx_desc), (caddr_t *)&ring->desc,
+ BUS_DMA_NOWAIT);
+ if (error != 0) {
+ printf("%s: could not map desc DMA memory\n",
+ sc->sc_dev.dv_xname);
+ goto fail;
+ }
+
+ error = bus_dmamap_load(sc->sc_dmat, ring->map, ring->desc,
+ count * sizeof(struct malo_tx_desc), NULL, BUS_DMA_NOWAIT);
+ if (error != 0) {
+ printf("%s: could not load desc DMA map\n",
+ sc->sc_dev.dv_xname);
+ goto fail;
+ }
+
+ memset(ring->desc, 0, count * sizeof(struct malo_tx_desc));
+ ring->physaddr = ring->map->dm_segs->ds_addr;
+
+ ring->data = malloc(count * sizeof (struct malo_tx_data), M_DEVBUF,
+ M_NOWAIT);
+ if (ring->data == NULL) {
+ printf("%s: could not allocate soft data\n",
+ sc->sc_dev.dv_xname);
+ error = ENOMEM;
+ goto fail;
+ }
+
+ memset(ring->data, 0, count * sizeof (struct malo_tx_data));
+ for (i = 0; i < count; i++) {
+ error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
+ MALO_MAX_SCATTER, MCLBYTES, 0, BUS_DMA_NOWAIT,
+ &ring->data[i].map);
+ if (error != 0) {
+ printf("%s: could not create DMA map\n",
+ sc->sc_dev.dv_xname);
+ goto fail;
+ }
+ ring->desc[i].physnext = htole32(ring->physaddr +
+ (i + 1) % count * sizeof(struct malo_tx_desc));
+ }
+
+ return 0;
+
+fail: malo_free_tx_ring(sc, ring);
+ return error;
+}
+
+void
+malo_free_tx_ring(struct malo_softc *sc, struct malo_tx_ring *ring)
+{
+ struct malo_tx_data *data;
+ int i;
+
+ if (ring->desc != NULL) {
+ bus_dmamap_sync(sc->sc_dmat, ring->map, 0,
+ ring->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->sc_dmat, ring->map);
+ bus_dmamem_unmap(sc->sc_dmat, (caddr_t)ring->desc,
+ ring->count * sizeof(struct malo_tx_desc));
+ bus_dmamem_free(sc->sc_dmat, &ring->seg, 1);
+ }
+
+ if (ring->data != NULL) {
+ for (i = 0; i < ring->count; i++) {
+ data = &ring->data[i];
+
+ if (data->m != NULL) {
+ bus_dmamap_sync(sc->sc_dmat, data->map, 0,
+ data->map->dm_mapsize,
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->sc_dmat, data->map);
+ m_freem(data->m);
+ }
+
+#if 0
+ /*
+ * The node has already been freed at that point so
+ * don't call ieee80211_release_node() here.
+ */
+ data->ni = NULL;
+#endif
+
+ if (data->map != NULL)
+ bus_dmamap_destroy(sc->sc_dmat, data->map);
+ }
+ free(ring->data, M_DEVBUF);
+ }
+}
+
+int
malo_load_bootimg(struct malo_softc *sc)
{
char *name = "mrv8k-b.fw";
@@ -689,16 +838,19 @@ malo_get_spec(struct malo_softc *sc)
return (ETIMEDOUT);
/* XXX get the data form the buffer and feed it to ieee80211 */
- DPRINTF(("%s: get_hw_spec: V%x R%x, #Mcast %d, Regcode %d, #Ant %d\n",
- sc->sc_dev.dv_xname, htole16(spec->HwVersion),
- htole32(spec->FWReleaseNumber), htole16(spec->NumOfMCastAdr),
- htole16(spec->RegionCode), htole16(spec->NumberOfAntenna)));
+ DPRINTF(("%s: get_hw_spec: V%x R%x, #WCB %d, #Mcast %d, Regcode %d, "
+ "#Ant %d\n", sc->sc_dev.dv_xname, htole16(spec->HwVersion),
+ htole32(spec->FWReleaseNumber), htole16(spec->NumOfWCB),
+ htole16(spec->NumOfMCastAdr), htole16(spec->RegionCode),
+ htole16(spec->NumberOfAntenna)));
/* tell the DMA engine where our rings are */
- malo_mem_write4(sc, letoh32(spec->RxPdRd1Ptr) & 0xffff,
- htole32(sc->sc_rxring0.physaddr));
- malo_mem_write4(sc, letoh32(spec->RxPdRd2Ptr) & 0xffff,
- htole32(sc->sc_rxring1.physaddr));
+ malo_mem_write4(sc, letoh32(spec->RxPdRdPtr) & 0xffff,
+ htole32(sc->sc_rxring.physaddr));
+ malo_mem_write4(sc, letoh32(spec->RxPdWrPtr) & 0xffff,
+ htole32(sc->sc_rxring.physaddr));
+ malo_mem_write4(sc, letoh32(spec->WcbBase0) & 0xffff,
+ htole32(sc->sc_txring.physaddr));
return (0);
}
diff --git a/sys/dev/ic/malo.h b/sys/dev/ic/malo.h
index aec76150c15..a6f36994ec9 100644
--- a/sys/dev/ic/malo.h
+++ b/sys/dev/ic/malo.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: malo.h,v 1.3 2006/10/17 10:31:26 claudio Exp $ */
+/* $OpenBSD: malo.h,v 1.4 2006/10/17 19:40:39 claudio Exp $ */
/*
* Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org>
@@ -30,11 +30,27 @@ struct malo_rx_ring {
int next;
};
+struct malo_tx_desc;
+struct malo_tx_data;
+
+struct malo_tx_ring {
+ bus_dmamap_t map;
+ bus_dma_segment_t seg;
+ bus_addr_t physaddr;
+ struct malo_tx_desc *desc;
+ struct malo_tx_data *data;
+ int count;
+ int queued;
+ int cur;
+ int next;
+ int stat;
+};
+
struct malo_softc {
struct device sc_dev;
struct ieee80211com sc_ic;
- struct malo_rx_ring sc_rxring0;
- struct malo_rx_ring sc_rxring1;
+ struct malo_rx_ring sc_rxring;
+ struct malo_tx_ring sc_txring;
bus_dma_tag_t sc_dmat;
bus_space_tag_t sc_mem1_bt;