uint8_t rtwn_pci_read_1(struct rtwn_softc *sc, uint16_t addr) { struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); return (bus_space_read_1(pc->pc_st, pc->pc_sh, addr)); }
static void rtwn_pci_reset_tx_ring_stopped(struct rtwn_softc *sc, int qid) { struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); struct rtwn_tx_ring *ring = &pc->tx_ring[qid]; int i; for (i = 0; i < RTWN_PCI_TX_LIST_COUNT; i++) { struct rtwn_tx_data *data = &ring->tx_data[i]; void *desc = (uint8_t *)ring->desc + sc->txdesc_len * i; rtwn_pci_copy_tx_desc(pc, desc, NULL); if (data->m != NULL) { bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(ring->data_dmat, data->map); m_freem(data->m); data->m = NULL; } if (data->ni != NULL) { ieee80211_free_node(data->ni); data->ni = NULL; } } bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_POSTWRITE); sc->qfullmsk &= ~(1 << qid); ring->queued = 0; ring->last = ring->cur = 0; }
uint16_t rtwn_pci_read_2(struct rtwn_softc *sc, uint16_t addr) { struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); uint16_t val; val = bus_space_read_2(pc->pc_st, pc->pc_sh, addr); return le16toh(val); }
int rtwn_pci_write_1(struct rtwn_softc *sc, uint16_t addr, uint8_t val) { struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); bus_space_write_1(pc->pc_st, pc->pc_sh, addr, val); return (0); }
static uint16_t rtwn_pci_get_qmap(struct rtwn_softc *sc) { struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); KASSERT(pc->pc_qmap != 0, ("%s: qmap is not set!\n", __func__)); return (pc->pc_qmap); }
static void rtwn_pci_reset_rx_list(struct rtwn_softc *sc) { struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); struct rtwn_rx_ring *rx_ring = &pc->rx_ring; struct rtwn_rx_data *rx_data; int i; for (i = 0; i < RTWN_PCI_RX_LIST_COUNT; i++) { rx_data = &rx_ring->rx_data[i]; rtwn_pci_setup_rx_desc(pc, &rx_ring->desc[i], rx_data->paddr, MJUMPAGESIZE, i); } rx_ring->cur = 0; }
/* * Drop stale entries from Tx ring before the vap will be deleted. * In case if vap is NULL just free everything and reset cur / last pointers. */ static void rtwn_pci_reset_tx_list(struct rtwn_softc *sc, struct ieee80211vap *vap, int qid) { int i; if (vap == NULL) { if (qid != RTWN_PCI_BEACON_QUEUE) { /* * Device was stopped; just clear all entries. */ rtwn_pci_reset_tx_ring_stopped(sc, qid); } else { for (i = 0; i < RTWN_PORT_COUNT; i++) rtwn_pci_reset_beacon_ring(sc, i); } } else if (qid == RTWN_PCI_BEACON_QUEUE && (vap->iv_opmode == IEEE80211_M_HOSTAP || vap->iv_opmode == IEEE80211_M_IBSS)) { struct rtwn_vap *uvp = RTWN_VAP(vap); rtwn_pci_reset_beacon_ring(sc, uvp->id); } else { struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); struct rtwn_tx_ring *ring = &pc->tx_ring[qid]; for (i = 0; i < RTWN_PCI_TX_LIST_COUNT; i++) { struct rtwn_tx_data *data = &ring->tx_data[i]; if (data->ni != NULL && data->ni->ni_vap == vap) { /* * NB: if some vap is still running * rtwn_pci_tx_done() will free the mbuf; * otherwise, rtwn_stop() will reset all rings * after device shutdown. */ ieee80211_free_node(data->ni); data->ni = NULL; } } } }
static void rtwn_pci_free_rx_list(struct rtwn_softc *sc) { struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); struct rtwn_rx_ring *rx_ring = &pc->rx_ring; struct rtwn_rx_data *rx_data; int i; if (rx_ring->desc_dmat != NULL) { if (rx_ring->desc != NULL) { bus_dmamap_sync(rx_ring->desc_dmat, rx_ring->desc_map, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(rx_ring->desc_dmat, rx_ring->desc_map); bus_dmamem_free(rx_ring->desc_dmat, rx_ring->desc, rx_ring->desc_map); rx_ring->desc = NULL; } bus_dma_tag_destroy(rx_ring->desc_dmat); rx_ring->desc_dmat = NULL; } for (i = 0; i < RTWN_PCI_RX_LIST_COUNT; i++) { rx_data = &rx_ring->rx_data[i]; if (rx_data->m != NULL) { bus_dmamap_sync(rx_ring->data_dmat, rx_data->map, BUS_DMASYNC_POSTREAD); bus_dmamap_unload(rx_ring->data_dmat, rx_data->map); m_freem(rx_data->m); rx_data->m = NULL; } bus_dmamap_destroy(rx_ring->data_dmat, rx_data->map); rx_data->map = NULL; } if (rx_ring->data_dmat != NULL) { bus_dma_tag_destroy(rx_ring->data_dmat); rx_ring->data_dmat = NULL; } }
static void rtwn_pci_free_tx_list(struct rtwn_softc *sc, int qid) { struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); struct rtwn_tx_ring *tx_ring = &pc->tx_ring[qid]; struct rtwn_tx_data *tx_data; int i; if (tx_ring->desc_dmat != NULL) { if (tx_ring->desc != NULL) { bus_dmamap_sync(tx_ring->desc_dmat, tx_ring->desc_map, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(tx_ring->desc_dmat, tx_ring->desc_map); bus_dmamem_free(tx_ring->desc_dmat, tx_ring->desc, tx_ring->desc_map); } bus_dma_tag_destroy(tx_ring->desc_dmat); } for (i = 0; i < RTWN_PCI_TX_LIST_COUNT; i++) { tx_data = &tx_ring->tx_data[i]; if (tx_data->m != NULL) { bus_dmamap_sync(tx_ring->data_dmat, tx_data->map, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(tx_ring->data_dmat, tx_data->map); m_freem(tx_data->m); tx_data->m = NULL; } } if (tx_ring->data_dmat != NULL) { bus_dma_tag_destroy(tx_ring->data_dmat); tx_ring->data_dmat = NULL; } sc->qfullmsk &= ~(1 << qid); tx_ring->queued = 0; tx_ring->last = tx_ring->cur = 0; }
static void rtwn_pci_set_desc_addr(struct rtwn_softc *sc) { struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); RTWN_DPRINTF(sc, RTWN_DEBUG_RESET, "%s: addresses:\n" "bk: %08jX, be: %08jX, vi: %08jX, vo: %08jX\n" "bcn: %08jX, mgt: %08jX, high: %08jX, rx: %08jX\n", __func__, (uintmax_t)pc->tx_ring[RTWN_PCI_BK_QUEUE].paddr, (uintmax_t)pc->tx_ring[RTWN_PCI_BE_QUEUE].paddr, (uintmax_t)pc->tx_ring[RTWN_PCI_VI_QUEUE].paddr, (uintmax_t)pc->tx_ring[RTWN_PCI_VO_QUEUE].paddr, (uintmax_t)pc->tx_ring[RTWN_PCI_BEACON_QUEUE].paddr, (uintmax_t)pc->tx_ring[RTWN_PCI_MGNT_QUEUE].paddr, (uintmax_t)pc->tx_ring[RTWN_PCI_HIGH_QUEUE].paddr, (uintmax_t)pc->rx_ring.paddr); /* Set Tx Configuration Register. */ rtwn_pci_write_4(sc, R92C_TCR, pc->tcr); /* Configure Tx DMA. */ rtwn_pci_write_4(sc, R92C_BKQ_DESA, pc->tx_ring[RTWN_PCI_BK_QUEUE].paddr); rtwn_pci_write_4(sc, R92C_BEQ_DESA, pc->tx_ring[RTWN_PCI_BE_QUEUE].paddr); rtwn_pci_write_4(sc, R92C_VIQ_DESA, pc->tx_ring[RTWN_PCI_VI_QUEUE].paddr); rtwn_pci_write_4(sc, R92C_VOQ_DESA, pc->tx_ring[RTWN_PCI_VO_QUEUE].paddr); rtwn_pci_write_4(sc, R92C_BCNQ_DESA, pc->tx_ring[RTWN_PCI_BEACON_QUEUE].paddr); rtwn_pci_write_4(sc, R92C_MGQ_DESA, pc->tx_ring[RTWN_PCI_MGNT_QUEUE].paddr); rtwn_pci_write_4(sc, R92C_HQ_DESA, pc->tx_ring[RTWN_PCI_HIGH_QUEUE].paddr); /* Configure Rx DMA. */ rtwn_pci_write_4(sc, R92C_RX_DESA, pc->rx_ring.paddr); }
/* * Clear entry 0 (or 1) in the beacon queue (other are not used). */ static void rtwn_pci_reset_beacon_ring(struct rtwn_softc *sc, int id) { struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); struct rtwn_tx_ring *ring = &pc->tx_ring[RTWN_PCI_BEACON_QUEUE]; struct rtwn_tx_data *data = &ring->tx_data[id]; struct rtwn_tx_desc_common *txd = (struct rtwn_tx_desc_common *) ((uint8_t *)ring->desc + id * sc->txdesc_len); bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_POSTREAD); if (txd->flags0 & RTWN_FLAGS0_OWN) { /* Clear OWN bit. */ txd->flags0 &= ~RTWN_FLAGS0_OWN; bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_PREWRITE); /* Unload mbuf. */ bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(ring->data_dmat, data->map); } }
static int rtwn_pci_alloc_tx_list(struct rtwn_softc *sc, int qid) { struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); struct rtwn_tx_ring *tx_ring = &pc->tx_ring[qid]; bus_size_t size; int i, error; size = sc->txdesc_len * RTWN_PCI_TX_LIST_COUNT; error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), PAGE_SIZE, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, size, 1, size, 0, NULL, NULL, &tx_ring->desc_dmat); if (error != 0) { device_printf(sc->sc_dev, "could not create tx ring DMA tag\n"); goto fail; } error = bus_dmamem_alloc(tx_ring->desc_dmat, &tx_ring->desc, BUS_DMA_NOWAIT | BUS_DMA_ZERO, &tx_ring->desc_map); if (error != 0) { device_printf(sc->sc_dev, "can't map tx ring DMA memory\n"); goto fail; } error = bus_dmamap_load(tx_ring->desc_dmat, tx_ring->desc_map, tx_ring->desc, size, rtwn_pci_dma_map_addr, &tx_ring->paddr, BUS_DMA_NOWAIT); if (error != 0) { device_printf(sc->sc_dev, "could not load desc DMA map\n"); goto fail; } bus_dmamap_sync(tx_ring->desc_dmat, tx_ring->desc_map, BUS_DMASYNC_PREWRITE); error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MJUMPAGESIZE, 1, MJUMPAGESIZE, 0, NULL, NULL, &tx_ring->data_dmat); if (error != 0) { device_printf(sc->sc_dev, "could not create tx buf DMA tag\n"); goto fail; } for (i = 0; i < RTWN_PCI_TX_LIST_COUNT; i++) { struct rtwn_tx_data *tx_data = &tx_ring->tx_data[i]; void *tx_desc = (uint8_t *)tx_ring->desc + sc->txdesc_len * i; uint32_t next_desc_addr = tx_ring->paddr + sc->txdesc_len * ((i + 1) % RTWN_PCI_TX_LIST_COUNT); rtwn_pci_setup_tx_desc(pc, tx_desc, next_desc_addr); error = bus_dmamap_create(tx_ring->data_dmat, 0, &tx_data->map); if (error != 0) { device_printf(sc->sc_dev, "could not create tx buf DMA map\n"); return (error); } tx_data->m = NULL; tx_data->ni = NULL; } return (0); fail: rtwn_pci_free_tx_list(sc, qid); return (error); }
static int rtwn_pci_alloc_rx_list(struct rtwn_softc *sc) { struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); struct rtwn_rx_ring *rx_ring = &pc->rx_ring; struct rtwn_rx_data *rx_data; bus_size_t size; int i, error; /* Allocate Rx descriptors. */ size = sizeof(struct r92ce_rx_stat) * RTWN_PCI_RX_LIST_COUNT; error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, size, 1, size, 0, NULL, NULL, &rx_ring->desc_dmat); if (error != 0) { device_printf(sc->sc_dev, "could not create rx desc DMA tag\n"); goto fail; } error = bus_dmamem_alloc(rx_ring->desc_dmat, (void **)&rx_ring->desc, BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT, &rx_ring->desc_map); if (error != 0) { device_printf(sc->sc_dev, "could not allocate rx desc\n"); goto fail; } error = bus_dmamap_load(rx_ring->desc_dmat, rx_ring->desc_map, rx_ring->desc, size, rtwn_pci_dma_map_addr, &rx_ring->paddr, 0); if (error != 0) { device_printf(sc->sc_dev, "could not load rx desc DMA map\n"); goto fail; } bus_dmamap_sync(rx_ring->desc_dmat, rx_ring->desc_map, BUS_DMASYNC_PREWRITE); /* Create RX buffer DMA tag. */ error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MJUMPAGESIZE, 1, MJUMPAGESIZE, 0, NULL, NULL, &rx_ring->data_dmat); if (error != 0) { device_printf(sc->sc_dev, "could not create rx buf DMA tag\n"); goto fail; } /* Allocate Rx buffers. */ for (i = 0; i < RTWN_PCI_RX_LIST_COUNT; i++) { rx_data = &rx_ring->rx_data[i]; error = bus_dmamap_create(rx_ring->data_dmat, 0, &rx_data->map); if (error != 0) { device_printf(sc->sc_dev, "could not create rx buf DMA map\n"); goto fail; } rx_data->m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUMPAGESIZE); if (rx_data->m == NULL) { device_printf(sc->sc_dev, "could not allocate rx mbuf\n"); error = ENOMEM; goto fail; } error = bus_dmamap_load(rx_ring->data_dmat, rx_data->map, mtod(rx_data->m, void *), MJUMPAGESIZE, rtwn_pci_dma_map_addr, &rx_data->paddr, BUS_DMA_NOWAIT); if (error != 0) { device_printf(sc->sc_dev, "could not load rx buf DMA map"); goto fail; } rtwn_pci_setup_rx_desc(pc, &rx_ring->desc[i], rx_data->paddr, MJUMPAGESIZE, i); } rx_ring->cur = 0; return (0); fail: rtwn_pci_free_rx_list(sc); return (error); }