struct ieee80211com *ic = &sc->sc_ic;
rtw_intr_rx(struct rtw_softc *sc, u_int16_t isr){#define	IS_BEACON(__fc0)						\    ((__fc0 & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==\     (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_BEACON))	static const int ratetbl[4] = {2, 4, 11, 22};	/* convert rates:							 * hardware -> net80211							 */	u_int next, nproc = 0;	int hwrate, len, rate, rssi, sq;	u_int32_t hrssi, hstat, htsfth, htsftl;	struct rtw_rxdesc *rd;	struct rtw_rxsoft *rs;	struct rtw_rxdesc_blk *rdb;	struct mbuf *m;	struct ieee80211com *ic = &sc->sc_ic;	struct ieee80211_node *ni;	struct ieee80211_frame *wh;	rdb = &sc->sc_rxdesc_blk;	KASSERT(rdb->rdb_next < rdb->rdb_ndesc);	for (next = rdb->rdb_next; ; next = (next + 1) % rdb->rdb_ndesc) {		rtw_rxdescs_sync(rdb, next, 1,		    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);		rd = &rdb->rdb_desc[next];		rs = &sc->sc_rxsoft[next];		hstat = letoh32(rd->rd_stat);		hrssi = letoh32(rd->rd_rssi);		htsfth = letoh32(rd->rd_tsfth);		htsftl = letoh32(rd->rd_tsftl);		RTW_DPRINTF(RTW_DEBUG_RECV_DESC,		    ("%s: rxdesc[%d] hstat %08x hrssi %08x htsft %08x%08x\n",		    __func__, next, hstat, hrssi, htsfth, htsftl));		++nproc;		/* still belongs to NIC */		if ((hstat & RTW_RXSTAT_OWN) != 0) {			if (nproc > 1)				break;			/* sometimes the NIC skips to the 0th descriptor */			rtw_rxdescs_sync(rdb, 0, 1,			    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);			rd = &rdb->rdb_desc[0];			if ((rd->rd_stat & htole32(RTW_RXSTAT_OWN)) != 0)				break;			RTW_DPRINTF(RTW_DEBUG_BUGS,			    ("%s: NIC skipped to rxdesc[0]\n",			     sc->sc_dev.dv_xname));			next = 0;			continue;		}		if ((hstat & RTW_RXSTAT_IOERROR) != 0) {			printf("%s: DMA error/FIFO overflow %08x, "			    "rx descriptor %d\n", sc->sc_dev.dv_xname,			    hstat & RTW_RXSTAT_IOERROR, next);			sc->sc_if.if_ierrors++;			goto next;		}		len = MASK_AND_RSHIFT(hstat, RTW_RXSTAT_LENGTH_MASK);		if (len < IEEE80211_MIN_LEN) {			sc->sc_ic.ic_stats.is_rx_tooshort++;			goto next;		}		hwrate = MASK_AND_RSHIFT(hstat, RTW_RXSTAT_RATE_MASK);		if (hwrate >= sizeof(ratetbl) / sizeof(ratetbl[0])) {			printf("%s: unknown rate #%d\n", sc->sc_dev.dv_xname,			    MASK_AND_RSHIFT(hstat, RTW_RXSTAT_RATE_MASK));			sc->sc_if.if_ierrors++;			goto next;		}		rate = ratetbl[hwrate];#ifdef RTW_DEBUG#define PRINTSTAT(flag) do { \	if ((hstat & flag) != 0) { \		printf("%s" #flag, delim); \		delim = ","; \	} \} while (0)		if ((rtw_debug & RTW_DEBUG_RECV_DESC) != 0) {			const char *delim = "<";			printf("%s: ", sc->sc_dev.dv_xname);			if ((hstat & RTW_RXSTAT_DEBUG) != 0) {				printf("status %08x", hstat);				PRINTSTAT(RTW_RXSTAT_SPLCP);				PRINTSTAT(RTW_RXSTAT_MAR);				PRINTSTAT(RTW_RXSTAT_PAR);				PRINTSTAT(RTW_RXSTAT_BAR);				PRINTSTAT(RTW_RXSTAT_PWRMGT);				PRINTSTAT(RTW_RXSTAT_CRC32);				PRINTSTAT(RTW_RXSTAT_ICV);				printf(">, ");			}			printf("rate %d.%d Mb/s, time %08x%08x\n",			    (rate * 5) / 10, (rate * 5) % 10, htsfth, htsftl);		}#endif /* RTW_DEBUG */		if ((hstat & RTW_RXSTAT_RES) != 0 &&		    sc->sc_ic.ic_opmode != IEEE80211_M_MONITOR)			goto next;		/* if bad flags, skip descriptor */		if ((hstat & RTW_RXSTAT_ONESEG) != RTW_RXSTAT_ONESEG) {			printf("%s: too many rx segments\n",			    sc->sc_dev.dv_xname);			goto next;		}		bus_dmamap_sync(sc->sc_dmat, rs->rs_dmamap, 0,		    rs->rs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);		m = rs->rs_mbuf;		/* if temporarily out of memory, re-use mbuf */		switch (rtw_rxsoft_alloc(sc->sc_dmat, rs)) {		case 0:			break;		case ENOBUFS:			printf("%s: rtw_rxsoft_alloc(, %d) failed, "			    "dropping this packet\n", sc->sc_dev.dv_xname,			    next);			goto next;		default:			/* XXX shorten rx ring, instead? */			panic("%s: could not load DMA map\n",			    sc->sc_dev.dv_xname);		}		if (sc->sc_rfchipid == RTW_RFCHIPID_PHILIPS)			rssi = MASK_AND_RSHIFT(hrssi, RTW_RXRSSI_RSSI);		else {			rssi = MASK_AND_RSHIFT(hrssi, RTW_RXRSSI_IMR_RSSI);			/* TBD find out each front-end's LNA gain in the			 * front-end's units			 */			if ((hrssi & RTW_RXRSSI_IMR_LNA) == 0)				rssi |= 0x80;		}		sq = MASK_AND_RSHIFT(hrssi, RTW_RXRSSI_SQ);		/*		 * Note well: now we cannot recycle the rs_mbuf unless		 * we restore its original length.		 */		m->m_pkthdr.rcvif = &sc->sc_if;		m->m_pkthdr.len = m->m_len = len;		m->m_flags |= M_HASFCS;		wh = mtod(m, struct ieee80211_frame *);		/* TBD use _MAR, _BAR, _PAR flags as hints to _find_rxnode? */		ni = ieee80211_find_rxnode(&sc->sc_ic, wh);		sc->sc_tsfth = htsfth;#ifdef RTW_DEBUG		if ((sc->sc_if.if_flags & (IFF_DEBUG|IFF_LINK2)) ==		    (IFF_DEBUG|IFF_LINK2)) {			ieee80211_dump_pkt(mtod(m, uint8_t *), m->m_pkthdr.len,			    rate, rssi);		}#endif /* RTW_DEBUG */		ieee80211_input(&sc->sc_if, m, ni, rssi, htsftl);		if (ni == ic->ic_bss)			ieee80211_unref_node(&ni);		else			ieee80211_free_node(&sc->sc_ic, ni);next:		rtw_rxdesc_init(rdb, rs, next, 0);	}	rdb->rdb_next = next;	KASSERT(rdb->rdb_next < rdb->rdb_ndesc);	return;#undef IS_BEACON}