if (ni != ic->ic_bss) ieee80211_free_node(&sc->sc_ic, ni);
ieee80211_release_node(&sc->sc_ic, ni);
rtw_start(struct ifnet *ifp){	uint8_t tppoll;	int desc, i, lastdesc, npkt, rate;	uint32_t proto_ctl0, ctl0, ctl1;	bus_dmamap_t		dmamap;	struct ieee80211com	*ic;	struct ieee80211_duration *d0;	struct ieee80211_frame	*wh;	struct ieee80211_node	*ni;	struct mbuf		*m0;	struct rtw_softc	*sc;	struct rtw_txsoft_blk	*tsb;	struct rtw_txdesc_blk	*tdb;	struct rtw_txsoft	*ts;	struct rtw_txdesc	*td;	sc = (struct rtw_softc *)ifp->if_softc;	ic = &sc->sc_ic;	DPRINTF(sc, RTW_DEBUG_XMIT,	    ("%s: enter %s\n", sc->sc_dev.dv_xname, __func__));	if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)		goto out;	/* XXX do real rate control */	proto_ctl0 = RTW_TXCTL0_RTSRATE_1MBPS;	rate = MAX(2, ieee80211_get_rate(ic));	if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0)		proto_ctl0 |= RTW_TXCTL0_SPLCP;	for (;;) {		if (rtw_dequeue(ifp, &tsb, &tdb, &m0, &ni) == -1)			continue;		if (m0 == NULL)			break;		ts = SIMPLEQ_FIRST(&tsb->tsb_freeq);		dmamap = ts->ts_dmamap;		m0 = rtw_dmamap_load_txbuf(sc->sc_dmat, dmamap, m0,		    tdb->tdb_nfree, &ifp->if_flags, sc->sc_dev.dv_xname);		if (m0 == NULL || dmamap->dm_nsegs == 0) {			DPRINTF(sc, RTW_DEBUG_XMIT,			    ("%s: fail dmamap load\n", __func__));			goto post_dequeue_err;		}#ifdef RTW_DEBUG		if ((sc->sc_if.if_flags & (IFF_DEBUG|IFF_LINK2)) ==		    (IFF_DEBUG|IFF_LINK2)) {			ieee80211_dump_pkt(mtod(m0, uint8_t *),			    (dmamap->dm_nsegs == 1) ? m0->m_pkthdr.len			                            : sizeof(wh),			    rate, 0);		}#endif /* RTW_DEBUG */		ctl0 = proto_ctl0 |		    LSHIFT(m0->m_pkthdr.len, RTW_TXCTL0_TPKTSIZE_MASK);		wh = mtod(m0, struct ieee80211_frame *);		if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==		    IEEE80211_FC0_TYPE_MGT) {			ctl0 |= RTW_TXCTL0_RATE_1MBPS;		} else switch (rate) {		default:		case 2:			ctl0 |= RTW_TXCTL0_RATE_1MBPS;			break;		case 4:			ctl0 |= RTW_TXCTL0_RATE_2MBPS;			break;		case 11:			ctl0 |= RTW_TXCTL0_RATE_5MBPS;			break;		case 22:			ctl0 |= RTW_TXCTL0_RATE_11MBPS;			break;		}		if ((wh->i_fc[1] & IEEE80211_FC1_WEP) != 0)			ctl0 |= LSHIFT(sc->sc_txkey, RTW_TXCTL0_KEYID_MASK);		if (ieee80211_compute_duration(wh, m0->m_pkthdr.len,		    ic->ic_flags, ic->ic_fragthreshold,		    rate, &ts->ts_d0, &ts->ts_dn, &npkt,		    (sc->sc_if.if_flags & (IFF_DEBUG|IFF_LINK2)) ==		    (IFF_DEBUG|IFF_LINK2)) == -1) {			DPRINTF(sc, RTW_DEBUG_XMIT,			    ("%s: fail compute duration\n", __func__));			goto post_load_err;		}		/* XXX >= ? */		if (m0->m_pkthdr.len > ic->ic_rtsthreshold)			ctl0 |= RTW_TXCTL0_RTSEN;		d0 = &ts->ts_d0;		*(uint16_t*)wh->i_dur = htole16(d0->d_data_dur);		ctl1 = LSHIFT(d0->d_plcp_len, RTW_TXCTL1_LENGTH_MASK) |		    LSHIFT(d0->d_rts_dur, RTW_TXCTL1_RTSDUR_MASK);		if (d0->d_residue)			ctl1 |= RTW_TXCTL1_LENGEXT;		/* TBD fragmentation */		ts->ts_first = tdb->tdb_next;		rtw_txdescs_sync(tdb, ts->ts_first, dmamap->dm_nsegs,		    BUS_DMASYNC_PREWRITE);		KASSERT(ts->ts_first < tdb->tdb_ndesc);		for (i = 0, lastdesc = desc = ts->ts_first;		     i < dmamap->dm_nsegs;		     i++, desc = RTW_NEXT_IDX(tdb, desc)) {			if (dmamap->dm_segs[i].ds_len > RTW_TXLEN_LENGTH_MASK) {				DPRINTF(sc, RTW_DEBUG_XMIT_DESC,				    ("%s: seg too long\n", __func__));				goto post_load_err;			}			td = &tdb->tdb_desc[desc];			td->td_ctl0 = htole32(ctl0);			if (i != 0)				td->td_ctl0 |= htole32(RTW_TXCTL0_OWN);			td->td_ctl1 = htole32(ctl1);			td->td_buf = htole32(dmamap->dm_segs[i].ds_addr);			td->td_len = htole32(dmamap->dm_segs[i].ds_len);			lastdesc = desc;#ifdef RTW_DEBUG			rtw_print_txdesc(sc, "load", ts, tdb, desc);#endif /* RTW_DEBUG */		}		KASSERT(desc < tdb->tdb_ndesc);		ts->ts_ni = ni;		ts->ts_mbuf = m0;		ts->ts_last = lastdesc;		tdb->tdb_desc[ts->ts_last].td_ctl0 |= htole32(RTW_TXCTL0_LS);		tdb->tdb_desc[ts->ts_first].td_ctl0 |=		   htole32(RTW_TXCTL0_FS);#ifdef RTW_DEBUG		rtw_print_txdesc(sc, "FS on", ts, tdb, ts->ts_first);		rtw_print_txdesc(sc, "LS on", ts, tdb, ts->ts_last);#endif /* RTW_DEBUG */		tdb->tdb_nfree -= dmamap->dm_nsegs;		tdb->tdb_next = desc;		rtw_txdescs_sync(tdb, ts->ts_first, dmamap->dm_nsegs,		    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);		tdb->tdb_desc[ts->ts_first].td_ctl0 |=		    htole32(RTW_TXCTL0_OWN);#ifdef RTW_DEBUG		rtw_print_txdesc(sc, "OWN on", ts, tdb, ts->ts_first);#endif /* RTW_DEBUG */		rtw_txdescs_sync(tdb, ts->ts_first, 1,		    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);		SIMPLEQ_REMOVE_HEAD(&tsb->tsb_freeq, ts_q);		SIMPLEQ_INSERT_TAIL(&tsb->tsb_dirtyq, ts, ts_q);		if (tsb != &sc->sc_txsoft_blk[RTW_TXPRIBCN]) {			tsb->tsb_tx_timer = 5;			ifp->if_timer = 1;		}		tppoll = RTW_READ8(&sc->sc_regs, RTW_TPPOLL);		RTW_WRITE8(&sc->sc_regs, RTW_TPPOLL,		    tppoll | (tsb->tsb_poll & RTW_TPPOLL_ALL));		RTW_SYNC(&sc->sc_regs, RTW_TPPOLL, RTW_TPPOLL);	}out:	DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: leave\n", __func__));	return;post_load_err:	bus_dmamap_unload(sc->sc_dmat, dmamap);	m_freem(m0);post_dequeue_err:	if (ni != ic->ic_bss)		ieee80211_free_node(&sc->sc_ic, ni);	return;}