diff options
-rw-r--r-- | sys/dev/pci/if_iwn.c | 31 | ||||
-rw-r--r-- | sys/dev/pci/if_iwnreg.h | 34 |
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; |