if (sc->txfree < 1 + IPW_MAX_NSEG) ifp->if_flags |= IFF_OACTIVE;
ipw_tx_start(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni){	struct ipw_softc *sc = ifp->if_softc;	struct ieee80211com *ic = &sc->sc_ic;	struct ieee80211_frame *wh;	struct ipw_soft_bd *sbd;	struct ipw_soft_hdr *shdr;	struct ipw_soft_buf *sbuf;	struct mbuf *mnew;	int error, i;	if (ic->ic_flags & IEEE80211_F_WEPON) {		m = ieee80211_wep_crypt(ifp, m, 1);		if (m == NULL)			return ENOBUFS;	}#if NBPFILTER > 0	if (sc->sc_drvbpf != NULL) {		struct mbuf mb;		struct ipw_tx_radiotap_header *tap = &sc->sc_txtap;		tap->wt_flags = 0;		tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);		tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);		M_DUP_PKTHDR(&mb, m);		mb.m_data = (caddr_t)tap;		mb.m_len = sc->sc_txtap_len;		mb.m_next = m;		mb.m_pkthdr.len += mb.m_len;		bpf_mtap(sc->sc_drvbpf, &mb);	}#endif	wh = mtod(m, struct ieee80211_frame *);	shdr = SLIST_FIRST(&sc->free_shdr);	sbuf = SLIST_FIRST(&sc->free_sbuf);	shdr->hdr.type = htole32(IPW_HDR_TYPE_SEND);	shdr->hdr.subtype = htole32(0);	shdr->hdr.encrypted = (wh->i_fc[1] & IEEE80211_FC1_WEP) ? 1 : 0;	shdr->hdr.encrypt = 0;	shdr->hdr.keyidx = 0;	shdr->hdr.keysz = 0;	shdr->hdr.fragmentsz = htole16(0);	IEEE80211_ADDR_COPY(shdr->hdr.src_addr, wh->i_addr2);	if (ic->ic_opmode == IEEE80211_M_STA)		IEEE80211_ADDR_COPY(shdr->hdr.dst_addr, wh->i_addr3);	else		IEEE80211_ADDR_COPY(shdr->hdr.dst_addr, wh->i_addr1);	/* trim IEEE802.11 header */	m_adj(m, sizeof (struct ieee80211_frame));	error = bus_dmamap_load_mbuf(sc->sc_dmat, sbuf->map, m, BUS_DMA_NOWAIT);	if (error != 0 && error != EFBIG) {		printf("%s: could not map mbuf (error %d)\n",		    sc->sc_dev.dv_xname, error);		m_freem(m);		return error;	}	if (error != 0) {		/* too many fragments, linearize */		MGETHDR(mnew, M_DONTWAIT, MT_DATA);		if (mnew == NULL) {			m_freem(m);			return ENOMEM;		}		M_DUP_PKTHDR(mnew, m);		MCLGET(mnew, M_DONTWAIT);		if (!(mnew->m_flags & M_EXT)) {			m_freem(m);			m_freem(mnew);			return ENOMEM;		}		m_copydata(m, 0, m->m_pkthdr.len, mtod(mnew, caddr_t));		m_freem(m);		mnew->m_len = mnew->m_pkthdr.len;		m = mnew;		error = bus_dmamap_load_mbuf(sc->sc_dmat, sbuf->map, m,		    BUS_DMA_NOWAIT);		if (error != 0) {			printf("%s: could not map mbuf (error %d)\n",			    sc->sc_dev.dv_xname, error);			m_freem(m);			return error;		}	}	error = bus_dmamap_load(sc->sc_dmat, shdr->map, &shdr->hdr,	    sizeof (struct ipw_hdr), NULL, BUS_DMA_NOWAIT);	if (error != 0) {		printf("%s: could not map header DMA memory (error %d)\n",		    sc->sc_dev.dv_xname, error);		bus_dmamap_unload(sc->sc_dmat, sbuf->map);		m_freem(m);		return error;	}	SLIST_REMOVE_HEAD(&sc->free_sbuf, next);	SLIST_REMOVE_HEAD(&sc->free_shdr, next);	sbd = &sc->stbd_list[sc->txcur];	sbd->type = IPW_SBD_TYPE_HEADER;	sbd->priv = shdr;	sbd->bd->physaddr = htole32(shdr->map->dm_segs[0].ds_addr);	sbd->bd->len = htole32(sizeof (struct ipw_hdr));	sbd->bd->nfrag = 1 + sbuf->map->dm_nsegs;	sbd->bd->flags = IPW_BD_FLAG_TX_FRAME_802_3 |			 IPW_BD_FLAG_TX_NOT_LAST_FRAGMENT;	DPRINTFN(5, ("TX!HDR!%u!%u!%u!%u", shdr->hdr.type, shdr->hdr.subtype,	    shdr->hdr.encrypted, shdr->hdr.encrypt));	DPRINTFN(5, ("!%s", ether_sprintf(shdr->hdr.src_addr)));	DPRINTFN(5, ("!%s\n", ether_sprintf(shdr->hdr.dst_addr)));	bus_dmamap_sync(sc->sc_dmat, sc->tbd_map,	    sc->txcur * sizeof (struct ipw_bd),	    sizeof (struct ipw_bd), BUS_DMASYNC_PREWRITE);	sc->txcur = (sc->txcur + 1) % IPW_NTBD;	sc->txfree--;	sbuf->m = m;	sbuf->ni = ni;	for (i = 0; i < sbuf->map->dm_nsegs; i++) {		sbd = &sc->stbd_list[sc->txcur];		sbd->bd->physaddr = htole32(sbuf->map->dm_segs[i].ds_addr);		sbd->bd->len = htole32(sbuf->map->dm_segs[i].ds_len);		sbd->bd->nfrag = 0; /* used only in first bd */		sbd->bd->flags = IPW_BD_FLAG_TX_FRAME_802_3;		if (i == sbuf->map->dm_nsegs - 1) {			sbd->type = IPW_SBD_TYPE_DATA;			sbd->priv = sbuf;			sbd->bd->flags |= IPW_BD_FLAG_TX_LAST_FRAGMENT;		} else {			sbd->type = IPW_SBD_TYPE_NOASSOC;			sbd->bd->flags |= IPW_BD_FLAG_TX_NOT_LAST_FRAGMENT;		}		DPRINTFN(5, ("TX!FRAG!%d!%d\n", i,		    sbuf->map->dm_segs[i].ds_len));		bus_dmamap_sync(sc->sc_dmat, sc->tbd_map,		    sc->txcur * sizeof (struct ipw_bd),		    sizeof (struct ipw_bd), BUS_DMASYNC_PREWRITE);		sc->txcur = (sc->txcur + 1) % IPW_NTBD;		sc->txfree--;	}	bus_dmamap_sync(sc->sc_dmat, shdr->map, 0, sizeof (struct ipw_hdr),	    BUS_DMASYNC_PREWRITE);	bus_dmamap_sync(sc->sc_dmat, sbuf->map, 0, MCLBYTES,	    BUS_DMASYNC_PREWRITE);	/* Inform firmware about this new packet */	CSR_WRITE_4(sc, IPW_CSR_TX_WRITE_INDEX, sc->txcur);	if (sc->txfree < 1 + IPW_MAX_NSEG)		ifp->if_flags |= IFF_OACTIVE;	return 0;}