Exemplo n.º 1
0
/*
 * 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);
            }
        }
    }
Exemplo n.º 2
0
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;
	}
}
Exemplo n.º 3
0
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;
	}
}