summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/pci/if_iwn.c31
-rw-r--r--sys/dev/pci/if_iwnreg.h34
2 files changed, 33 insertions, 32 deletions
diff --git a/sys/dev/pci/if_iwn.c b/sys/dev/pci/if_iwn.c
index 369b903d47f..15f69c1df23 100644
--- a/sys/dev/pci/if_iwn.c
+++ b/sys/dev/pci/if_iwn.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_iwn.c,v 1.42 2008/12/03 17:17:08 damien Exp $ */
+/* $OpenBSD: if_iwn.c,v 1.43 2008/12/12 17:15:40 damien Exp $ */
/*-
* Copyright (c) 2007, 2008
@@ -2367,6 +2367,7 @@ iwn_tx(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
uint32_t flags;
uint16_t qos;
u_int hdrlen;
+ bus_dma_segment_t *seg;
uint8_t *ivp, tid, ridx, txant, type;
int i, totlen, hasqos, error, pad;
@@ -2537,7 +2538,8 @@ iwn_tx(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
flags |= IWN_TX_LINKQ; /* enable MRR */
}
/* Set physical address of "scratch area". */
- tx->loaddr = htole32(data->scratch_paddr);
+ tx->loaddr = htole32(IWN_LOADDR(data->scratch_paddr));
+ tx->hiaddr = IWN_HIADDR(data->scratch_paddr);
/* Copy 802.11 header in TX command. */
memcpy((uint8_t *)(tx + 1), wh, hdrlen);
@@ -2601,14 +2603,18 @@ iwn_tx(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
ring->qid, ring->cur, m->m_pkthdr.len, data->map->dm_nsegs));
/* Fill TX descriptor. */
- IWN_SET_DESC_NSEGS(desc, 1 + data->map->dm_nsegs);
+ desc->nsegs = 1 + data->map->dm_nsegs;
/* First DMA segment is used by the TX command. */
- IWN_SET_DESC_SEG(desc, 0, data->cmd_paddr,
- 4 + sizeof (*tx) + hdrlen + pad);
+ desc->segs[0].addr = htole32(IWN_LOADDR(data->cmd_paddr));
+ desc->segs[0].len = htole16(IWN_HIADDR(data->cmd_paddr) |
+ (4 + sizeof (*tx) + hdrlen + pad) << 4);
/* Other DMA segments are for data payload. */
+ seg = data->map->dm_segs;
for (i = 1; i <= data->map->dm_nsegs; i++) {
- IWN_SET_DESC_SEG(desc, i, data->map->dm_segs[i - 1].ds_addr,
- data->map->dm_segs[i - 1].ds_len);
+ desc->segs[i].addr = htole32(IWN_LOADDR(seg->ds_addr));
+ desc->segs[i].len = htole16(IWN_HIADDR(seg->ds_addr) |
+ seg->ds_len << 4);
+ seg++;
}
bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
@@ -2832,8 +2838,9 @@ iwn_cmd(struct iwn_softc *sc, int code, const void *buf, int size, int async)
cmd->idx = ring->cur;
memcpy(cmd->data, buf, size);
- IWN_SET_DESC_NSEGS(desc, 1);
- IWN_SET_DESC_SEG(desc, 0, paddr, totlen);
+ desc->nsegs = 1;
+ desc->segs[0].addr = htole32(IWN_LOADDR(paddr));
+ desc->segs[0].len = htole16(IWN_HIADDR(paddr) | totlen << 4);
if (size > sizeof cmd->data) {
bus_dmamap_sync(sc->sc_dmat, data->map, 0, totlen,
@@ -4684,8 +4691,10 @@ iwn5000_load_firmware_section(struct iwn_softc *sc, uint32_t dst,
IWN_FH_TX_CONFIG_DMA_PAUSE);
IWN_WRITE(sc, IWN_FH_SRAM_ADDR(IWN_SRVC_CHNL), dst);
- IWN_WRITE(sc, IWN_FH_TFBD_CTRL0(IWN_SRVC_CHNL), dma->paddr);
- IWN_WRITE(sc, IWN_FH_TFBD_CTRL1(IWN_SRVC_CHNL), size);
+ IWN_WRITE(sc, IWN_FH_TFBD_CTRL0(IWN_SRVC_CHNL),
+ IWN_LOADDR(dma->paddr));
+ IWN_WRITE(sc, IWN_FH_TFBD_CTRL1(IWN_SRVC_CHNL),
+ IWN_HIADDR(dma->paddr) << 28 | size);
IWN_WRITE(sc, IWN_FH_TXBUF_STATUS(IWN_SRVC_CHNL),
IWN_FH_TXBUF_STATUS_TBNUM(1) |
IWN_FH_TXBUF_STATUS_TBIDX(1) |
diff --git a/sys/dev/pci/if_iwnreg.h b/sys/dev/pci/if_iwnreg.h
index 789610db84b..ea18655ba10 100644
--- a/sys/dev/pci/if_iwnreg.h
+++ b/sys/dev/pci/if_iwnreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_iwnreg.h,v 1.19 2008/12/02 17:17:50 damien Exp $ */
+/* $OpenBSD: if_iwnreg.h,v 1.20 2008/12/12 17:15:40 damien Exp $ */
/*-
* Copyright (c) 2007, 2008
@@ -33,6 +33,15 @@
/* RX buffers must be large enough to hold a full 4K A-MPDU. */
#define IWN_RBUF_SIZE (4 * 1024)
+#if defined(__LP64__)
+/* HW supports 36-bit DMA addresses. */
+#define IWN_LOADDR(paddr) ((uint32_t)(paddr))
+#define IWN_HIADDR(paddr) (((paddr) >> 32) & 0xf)
+#else
+#define IWN_LOADDR(paddr) (paddr)
+#define IWN_HIADDR(paddr) (0)
+#endif
+
/* Base Address Register. */
#define IWN_PCI_BAR0 PCI_MAPREG_START
@@ -296,30 +305,13 @@ struct iwn_tx_desc {
uint8_t reserved1[3];
uint8_t nsegs;
struct {
- uint32_t w1;
- uint32_t w2;
- uint32_t w3;
- } __packed segs[IWN_MAX_SCATTER / 2];
+ uint32_t addr;
+ uint16_t len;
+ } __packed segs[IWN_MAX_SCATTER];
/* Pad to 128 bytes. */
uint32_t reserved2;
} __packed;
-#define IWN_SET_DESC_NSEGS(d, x) \
- (d)->nsegs = (x)
-
-/* Set a segment physical address and length in a TX descriptor. */
-#define IWN_SET_DESC_SEG(d, n, addr, size) do { \
- if ((n) & 1) { \
- (d)->segs[(n) / 2].w2 |= \
- htole32(((addr) & 0xffff) << 16); \
- (d)->segs[(n) / 2].w3 = \
- htole32((((addr) >> 16) & 0xffff) | (size) << 20); \
- } else { \
- (d)->segs[(n) / 2].w1 = htole32(addr); \
- (d)->segs[(n) / 2].w2 = htole32((size) << 4); \
- } \
-} while (0)
-
struct iwn_rx_status {
uint16_t closed_count;
uint16_t closed_rx_count;