/* * This routine picks an AMSDU buffer, calls the platform specific 802.11 layer for * WLAN encapsulation and then dispatches it to hardware for transmit. */ void ath_amsdu_stageq_flush(struct ath_softc_net80211 *scn, struct ath_amsdu_tx *amsdutx) { struct ieee80211_node *ni; struct ieee80211com *ic; wbuf_t wbuf; ATH_AMSDU_TXQ_LOCK(scn); wbuf = amsdutx->amsdu_tx_buf; if (!wbuf) { ATH_AMSDU_TXQ_UNLOCK(scn); return; } amsdutx->amsdu_tx_buf = NULL; ATH_AMSDU_TXQ_UNLOCK(scn); ni = wbuf_get_node(wbuf); ic = ni->ni_ic; /* * Encapsulate the packet for transmission */ wbuf = ieee80211_encap(ni, wbuf); if (wbuf == NULL) { printk("%s[%d] : ERROR: ieee80211_encap ret NULL\n", __func__, __LINE__); return; } /* There is only one wbuf to send */ if (wbuf != NULL) { int error = 0; ATH_DEFINE_TXCTL(txctl, wbuf); HTC_WBUF_TX_DELCARE /* prepare this frame */ if (ath_tx_prepare(scn, wbuf, 0, txctl) != 0) { goto bad; } HTC_WBUF_TX_DATA_PREPARE(ic, scn); if (error == 0) { /* send this frame to hardware */ txctl->an = (ATH_NODE_NET80211(ni))->an_sta; if (scn->sc_ops->tx(scn->sc_dev, wbuf, txctl) != 0) { goto bad; } else { HTC_WBUF_TX_DATA_COMPLETE_STATUS(ic); } } }
UInt32 VoodooIntel3945::outputPacket( mbuf_t m, void* param ) { struct wpi_softc* sc = &fSelfData; struct ieee80211com* ic = &sc->sc_ic; struct ieee80211_node *ni; DPRINTF(("TX: mbuf len=%u\n", mbuf_len(m))); if (m == 0) return kIOReturnOutputDropped; // ??? ExtraMbufParams* p = (ExtraMbufParams*)param; if (p->is80211ManagementFrame) { ni = (struct ieee80211_node *)mbuf_pkthdr_rcvif(m); } else { if (sc->qfullmsk != 0) { freePacket(m); return kIOReturnOutputDropped; } if (ic->ic_state != IEEE80211_S_RUN) { freePacket(m); return kIOReturnOutputDropped; } /* Encapsulate and send data frames. */ if ((m = ieee80211_encap(ic, m, &ni)) == NULL) return kIOReturnOutputDropped; } if (wpi_tx(sc, m, ni) != 0) { ieee80211_release_node(ic, ni); if (m) freePacket(m); return kIOReturnOutputDropped; } else { DPRINTF(("(prev tx success)\n")); sc->sc_tx_timer = 5; return kIOReturnOutputSuccess; } }
void an_start(struct ifnet *ifp) { struct an_softc *sc = (struct an_softc *)ifp->if_softc; struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_node *ni; struct ieee80211_frame *wh; struct an_txframe frmhdr; struct mbuf *m; u_int16_t len; int cur, fid; if (!sc->sc_enabled || sc->sc_invalid) { DPRINTF(("an_start: noop: enabled %d invalid %d\n", sc->sc_enabled, sc->sc_invalid)); return; } memset(&frmhdr, 0, sizeof(frmhdr)); cur = sc->sc_txnext; for (;;) { if (ic->ic_state != IEEE80211_S_RUN) { DPRINTF(("an_start: not running %d\n", ic->ic_state)); break; } m = ifq_deq_begin(&ifp->if_snd); if (m == NULL) { DPRINTF2(("an_start: no pending mbuf\n")); break; } if (sc->sc_txd[cur].d_inuse) { ifq_deq_rollback(&ifp->if_snd, m); DPRINTF2(("an_start: %x/%d busy\n", sc->sc_txd[cur].d_fid, cur)); ifq_set_oactive(&ifp->if_snd); break; } ifq_deq_commit(&ifp->if_snd, m); ifp->if_opackets++; #if NBPFILTER > 0 if (ifp->if_bpf) bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT); #endif if ((m = ieee80211_encap(ifp, m, &ni)) == NULL) { ifp->if_oerrors++; continue; } if (ni != NULL) ieee80211_release_node(ic, ni); #if NBPFILTER > 0 if (ic->ic_rawbpf) bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT); #endif wh = mtod(m, struct ieee80211_frame *); if (ic->ic_flags & IEEE80211_F_WEPON) wh->i_fc[1] |= IEEE80211_FC1_WEP; m_copydata(m, 0, sizeof(struct ieee80211_frame), (caddr_t)&frmhdr.an_whdr); an_swap16((u_int16_t *)&frmhdr.an_whdr, sizeof(struct ieee80211_frame)/2); /* insert payload length in front of llc/snap */ len = htons(m->m_pkthdr.len - sizeof(struct ieee80211_frame)); m_adj(m, sizeof(struct ieee80211_frame) - sizeof(len)); if (mtod(m, u_long) & 0x01) memcpy(mtod(m, caddr_t), &len, sizeof(len)); else *mtod(m, u_int16_t *) = len; /* * XXX Aironet firmware apparently convert the packet * with longer than 1500 bytes in length into LLC/SNAP. * If we have 1500 bytes in ethernet payload, it is * 1508 bytes including LLC/SNAP and will be inserted * additional LLC/SNAP header with 1501-1508 in its * ethertype !! * So we skip LLC/SNAP header and force firmware to * convert it to LLC/SNAP again. */ m_adj(m, sizeof(struct llc)); frmhdr.an_tx_ctl = AN_TXCTL_80211; frmhdr.an_tx_payload_len = m->m_pkthdr.len; frmhdr.an_gaplen = AN_TXGAP_802_11; if (ic->ic_fixed_rate != -1) frmhdr.an_tx_rate = ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates[ ic->ic_fixed_rate] & IEEE80211_RATE_VAL; else frmhdr.an_tx_rate = 0; if (sizeof(frmhdr) + AN_TXGAP_802_11 + sizeof(len) + m->m_pkthdr.len > AN_TX_MAX_LEN) { ifp->if_oerrors++; m_freem(m); continue; } #if NBPFILTER > 0 if (sc->sc_drvbpf) { struct mbuf mb; struct an_tx_radiotap_header *tap = &sc->sc_txtap; tap->at_rate = ic->ic_bss->ni_rates.rs_rates[ic->ic_bss->ni_txrate]; tap->at_chan_freq = ic->ic_bss->ni_chan->ic_freq; tap->at_chan_flags = ic->ic_bss->ni_chan->ic_flags; mb.m_data = (caddr_t)tap; mb.m_len = sizeof(sc->sc_txtapu); mb.m_next = m; mb.m_nextpkt = NULL; mb.m_type = 0; mb.m_flags = 0; bpf_mtap(sc->sc_drvbpf, m, BPF_DIRECTION_OUT); } #endif fid = sc->sc_txd[cur].d_fid; if (an_write_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) != 0) { ifp->if_oerrors++; m_freem(m); continue; } /* dummy write to avoid seek. */ an_write_bap(sc, fid, -1, &frmhdr, AN_TXGAP_802_11); an_mwrite_bap(sc, fid, -1, m, m->m_pkthdr.len); m_freem(m); DPRINTF2(("an_start: send %d byte via %x/%d\n", ntohs(len) + sizeof(struct ieee80211_frame), fid, cur)); sc->sc_txd[cur].d_inuse = 1; if (an_cmd(sc, AN_CMD_TX, fid)) { printf("%s: xmit failed\n", ifp->if_xname); sc->sc_txd[cur].d_inuse = 0; continue; } sc->sc_tx_timer = 5; ifp->if_timer = 1; AN_INC(cur, AN_TX_RING_CNT); sc->sc_txnext = cur; } }