Module Name: src Committed By: dyoung Date: Sun Sep 13 22:07:34 UTC 2009
Modified Files: src/sys/dev/ic: atw.c atwvar.h Log Message: Experimental support for fragmentation and RTS/CTS. Delete unused atw_voodoo and constants. Export Tx/Rx statistics with evcnt(9). Correct the Short Inter-Frame Space (SIFS) that we write to ADM8211's registers; I do not recall if that corrected the SIFS that I observed "on the air." Use the constant IEEE80211_DUR_DS_EIFS to configure the ADM8211's EIFS, instead of writing the same "magic" number, 0x64, that my reference driver wrote. Do not clear OACTIVE in atw_init(), because atw_stop() cleared it previously by calling atw_txdrain(). Use the net80211 short-preamble flag and instead of ATW_SHPREAMBLE. Add an ADM8211 workaround from the reference driver, atw_workaround1(), but don't compile it right now. In at_intr(), don't stop processing the interrupt status after restarting the receive ring, but process Tx interrupt status. If a packet's Tx lifetime is exceeded, reinitialize the device to get packets moving again. If the Tx FIFO underflows, restart the transmitter, not the receiver! Avoid losing synchronization with the Rx ring by replicating one of Charles Hannum's fixes to rtw(4) here: receiving a management packet may, as a side-effect, reset the Rx ring, so refer to the softc's Rx ring pointer, sc_rxptr, every time through the loop in atw_rxintr(), instead of refering to a pointer on the stack, i. Re-synchronize DMA after reading the OWN bit on an Rx/Tx descriptor. XXX This needs more work. Reset sc_tx_timer as Tx descriptors are reclaimed from the device. Shorten staircases in atw_watchdog(). Remove from softc an unused member, sc_intr_ack. To generate a diff of this commit: cvs rdiff -u -r1.144 -r1.145 src/sys/dev/ic/atw.c cvs rdiff -u -r1.31 -r1.32 src/sys/dev/ic/atwvar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/ic/atw.c diff -u src/sys/dev/ic/atw.c:1.144 src/sys/dev/ic/atw.c:1.145 --- src/sys/dev/ic/atw.c:1.144 Sat Sep 5 14:19:30 2009 +++ src/sys/dev/ic/atw.c Sun Sep 13 22:07:34 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: atw.c,v 1.144 2009/09/05 14:19:30 tsutsui Exp $ */ +/* $NetBSD: atw.c,v 1.145 2009/09/13 22:07:34 dyoung Exp $ */ /*- * Copyright (c) 1998, 1999, 2000, 2002, 2003, 2004 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: atw.c,v 1.144 2009/09/05 14:19:30 tsutsui Exp $"); +__KERNEL_RCSID(0, "$NetBSD: atw.c,v 1.145 2009/09/13 22:07:34 dyoung Exp $"); #include "bpfilter.h" @@ -48,6 +48,7 @@ #include <sys/ioctl.h> #include <sys/errno.h> #include <sys/device.h> +#include <sys/kauth.h> #include <sys/time.h> #include <lib/libkern/libkern.h> @@ -131,10 +132,6 @@ #define ATW_REFSLAVE /* slavishly do what the reference driver does */ -#define VOODOO_DUR_11_ROUNDING 0x01 /* necessary */ -#define VOODOO_DUR_2_4_SPECIALCASE 0x02 /* NOT necessary */ -int atw_voodoo = VOODOO_DUR_11_ROUNDING; - int atw_pseudo_milli = 1; int atw_magic_delay1 = 100 * 1000; int atw_magic_delay2 = 100 * 1000; @@ -211,7 +208,7 @@ /* Interrupt handlers */ void atw_linkintr(struct atw_softc *, u_int32_t); void atw_rxintr(struct atw_softc *); -void atw_txintr(struct atw_softc *); +void atw_txintr(struct atw_softc *, uint32_t); /* 802.11 state machine */ static int atw_newstate(struct ieee80211com *, enum ieee80211_state, int); @@ -718,7 +715,7 @@ * before this point releases all resources that may have been * allocated. */ - sc->sc_flags |= ATWF_ATTACHED /* | ATWF_RTSCTS */; + sc->sc_flags |= ATWF_ATTACHED; ATW_DPRINTF((" SROM MAC %04x%04x%04x", htole16(sc->sc_srom[ATW_SR_MAC00]), @@ -1158,10 +1155,10 @@ * Go figure. */ ifst = __SHIFTIN(IEEE80211_DUR_DS_SLOT, ATW_IFST_SLOT_MASK) | - __SHIFTIN(22 * 5 /* IEEE80211_DUR_DS_SIFS */ /* # of 22 MHz cycles */, + __SHIFTIN(22 * 10 /* IEEE80211_DUR_DS_SIFS */ /* # of 22 MHz cycles */, ATW_IFST_SIFS_MASK) | __SHIFTIN(IEEE80211_DUR_DS_DIFS, ATW_IFST_DIFS_MASK) | - __SHIFTIN(0x64 /* IEEE80211_DUR_DS_EIFS */, ATW_IFST_EIFS_MASK); + __SHIFTIN(IEEE80211_DUR_DS_EIFS, ATW_IFST_EIFS_MASK); ATW_WRITE(sc, ATW_IFST, ifst); } @@ -1436,7 +1433,6 @@ * Note that the interface is now running. */ ifp->if_flags |= IFF_RUNNING; - ifp->if_flags &= ~IFF_OACTIVE; /* send no beacons, yet. */ atw_start_beacon(sc, 0); @@ -1447,7 +1443,7 @@ error = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); out: if (error) { - ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); + ifp->if_flags &= ~IFF_RUNNING; sc->sc_tx_timer = 0; ifp->if_timer = 0; printf("%s: interface not running\n", device_xname(sc->sc_dev)); @@ -2368,7 +2364,7 @@ /* TBD use ni_capinfo */ capinfo = 0; - if (sc->sc_flags & ATWF_SHORT_PREAMBLE) + if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE; if (ic->ic_flags & IEEE80211_F_PRIVACY) capinfo |= IEEE80211_CAPINFO_PRIVACY; @@ -2677,8 +2673,7 @@ /* * Mark the interface down and cancel the watchdog timer. */ - ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); - sc->sc_tx_timer = 0; + ifp->if_flags &= ~IFF_RUNNING; ifp->if_timer = 0; if (disable) { @@ -2777,6 +2772,30 @@ return true; } +#if 0 +static void +atw_workaround1(struct atw_softc *sc) +{ + uint32_t test1; + + test1 = ATW_READ(sc, ATW_TEST1); + + sc->sc_misc_ev.ev_count++; + + if ((test1 & ATW_TEST1_RXPKT1IN) != 0) { + sc->sc_rxpkt1in_ev.ev_count++; + return; + } + if (__SHIFTOUT(test1, ATW_TEST1_RRA_MASK) == + __SHIFTOUT(test1, ATW_TEST1_RWA_MASK)) { + sc->sc_rxamatch_ev.ev_count++; + return; + } + sc->sc_workaround1_ev.ev_count++; + (void)atw_init(&sc->sc_if); +} +#endif + int atw_intr(void *arg) { @@ -2863,17 +2882,17 @@ device_xname(sc->sc_dev)); /* Get the receive process going again. */ ATW_WRITE(sc, ATW_RDR, 0x1); - break; } } if (txstatus) { /* Sweep up transmit descriptors. */ - atw_txintr(sc); + atw_txintr(sc, txstatus); if (txstatus & ATW_INTR_TLT) { DPRINTF(sc, ("%s: tx lifetime exceeded\n", device_xname(sc->sc_dev))); + (void)atw_init(&sc->sc_if); } if (txstatus & ATW_INTR_TRT) { @@ -2903,7 +2922,7 @@ */ ATW_WRITE(sc, ATW_NAR, sc->sc_opmode); DELAY(atw_nar_delay); - ATW_WRITE(sc, ATW_RDR, 0x1); + ATW_WRITE(sc, ATW_TDR, 0x1); /* XXX Log every Nth underrun from * XXX now on? */ @@ -3073,7 +3092,7 @@ int i, len, rate, rate0; u_int32_t rssi, ctlrssi; - for (i = sc->sc_rxptr;; i = ATW_NEXTRX(i)) { + for (i = sc->sc_rxptr;; i = sc->sc_rxptr) { rxs = &sc->sc_rxsoft[i]; ATW_CDRXSYNC(sc, i, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); @@ -3082,8 +3101,12 @@ ctlrssi = le32toh(sc->sc_rxdescs[i].ar_ctlrssi); rate0 = __SHIFTOUT(rxstat, ATW_RXSTAT_RXDR_MASK); - if (rxstat & ATW_RXSTAT_OWN) - break; /* We have processed all receive buffers. */ + if (rxstat & ATW_RXSTAT_OWN) { + ATW_CDRXSYNC(sc, i, BUS_DMASYNC_PREREAD); + break; + } + + sc->sc_rxptr = ATW_NEXTRX(i); DPRINTF3(sc, ("%s: rx stat %08x ctlrssi %08x buf1 %08x buf2 %08x\n", @@ -3224,9 +3247,6 @@ ieee80211_input(ic, m, ni, (int)rssi, 0); ieee80211_free_node(ni); } - - /* Update the receive pointer. */ - sc->sc_rxptr = i; } /* @@ -3235,7 +3255,7 @@ * Helper; handle transmit interrupts. */ void -atw_txintr(struct atw_softc *sc) +atw_txintr(struct atw_softc *sc, uint32_t status) { static char txstat_buf[sizeof("ffffffff<>" ATW_TXSTAT_FMT)]; struct ifnet *ifp = &sc->sc_if; @@ -3273,17 +3293,20 @@ if (i == txs->txs_lastdesc) break; } + ATW_CDTXSYNC(sc, txs->txs_firstdesc, + txs->txs_ndescs - 1, BUS_DMASYNC_PREREAD); } #endif txstat = le32toh(sc->sc_txdescs[txs->txs_lastdesc].at_stat); - if (txstat & ATW_TXSTAT_OWN) + if (txstat & ATW_TXSTAT_OWN) { + ATW_CDTXSYNC(sc, txs->txs_lastdesc, 1, + BUS_DMASYNC_PREREAD); break; + } SIMPLEQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); - sc->sc_txfree += txs->txs_ndescs; - bus_dmamap_sync(sc->sc_dmat, txs->txs_dmamap, 0, txs->txs_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE); @@ -3291,10 +3314,11 @@ m_freem(txs->txs_mbuf); txs->txs_mbuf = NULL; + sc->sc_txfree += txs->txs_ndescs; SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); - KASSERT(!(SIMPLEQ_EMPTY(&sc->sc_txfreeq) || - sc->sc_txfree == 0)); + KASSERT(!SIMPLEQ_EMPTY(&sc->sc_txfreeq) && sc->sc_txfree != 0); + sc->sc_tx_timer = 0; ifp->if_flags &= ~IFF_OACTIVE; if ((ifp->if_flags & IFF_DEBUG) != 0 && @@ -3306,20 +3330,21 @@ __SHIFTOUT(txstat, ATW_TXSTAT_ARC_MASK)); } + sc->sc_xmit_ev.ev_count++; + /* * Check for errors and collisions. */ if (txstat & ATW_TXSTAT_TUF) - sc->sc_stats.ts_tx_tuf++; + sc->sc_tuf_ev.ev_count++; if (txstat & ATW_TXSTAT_TLT) - sc->sc_stats.ts_tx_tlt++; + sc->sc_tlt_ev.ev_count++; if (txstat & ATW_TXSTAT_TRT) - sc->sc_stats.ts_tx_trt++; + sc->sc_trt_ev.ev_count++; if (txstat & ATW_TXSTAT_TRO) - sc->sc_stats.ts_tx_tro++; - if (txstat & ATW_TXSTAT_SOFBR) { - sc->sc_stats.ts_tx_sofbr++; - } + sc->sc_tro_ev.ev_count++; + if (txstat & ATW_TXSTAT_SOFBR) + sc->sc_sofbr_ev.ev_count++; if ((txstat & ATW_TXSTAT_ES) == 0) ifp->if_collisions += @@ -3330,14 +3355,7 @@ ifp->if_opackets++; } - /* - * If there are no more pending transmissions, cancel the watchdog - * timer. - */ - if (txs == NULL) { - KASSERT((ifp->if_flags & IFF_OACTIVE) == 0); - sc->sc_tx_timer = 0; - } + KASSERT(txs != NULL || (ifp->if_flags & IFF_OACTIVE) == 0); } /* @@ -3355,18 +3373,14 @@ if (ATW_IS_ENABLED(sc) == 0) return; - if (sc->sc_rescan_timer) { - if (--sc->sc_rescan_timer == 0) - (void)ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); - } - if (sc->sc_tx_timer) { - if (--sc->sc_tx_timer == 0 && - !SIMPLEQ_EMPTY(&sc->sc_txdirtyq)) { - printf("%s: transmit timeout\n", ifp->if_xname); - ifp->if_oerrors++; - (void)atw_init(ifp); - atw_start(ifp); - } + if (sc->sc_rescan_timer != 0 && --sc->sc_rescan_timer == 0) + (void)ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); + if (sc->sc_tx_timer != 0 && --sc->sc_tx_timer == 0 && + !SIMPLEQ_EMPTY(&sc->sc_txdirtyq)) { + printf("%s: transmit timeout\n", ifp->if_xname); + ifp->if_oerrors++; + (void)atw_init(ifp); + atw_start(ifp); } if (sc->sc_tx_timer != 0 || sc->sc_rescan_timer != 0) ifp->if_timer = 1; @@ -3382,6 +3396,18 @@ evcnt_detach(&sc->sc_crc32e_ev); evcnt_detach(&sc->sc_crc16e_ev); evcnt_detach(&sc->sc_recv_ev); + + evcnt_detach(&sc->sc_tuf_ev); + evcnt_detach(&sc->sc_tro_ev); + evcnt_detach(&sc->sc_trt_ev); + evcnt_detach(&sc->sc_tlt_ev); + evcnt_detach(&sc->sc_sofbr_ev); + evcnt_detach(&sc->sc_xmit_ev); + + evcnt_detach(&sc->sc_rxpkt1in_ev); + evcnt_detach(&sc->sc_rxamatch_ev); + evcnt_detach(&sc->sc_workaround1_ev); + evcnt_detach(&sc->sc_misc_ev); } static void @@ -3399,6 +3425,28 @@ &sc->sc_recv_ev, sc->sc_if.if_xname, "PLCP SFD error"); evcnt_attach_dynamic(&sc->sc_sige_ev, EVCNT_TYPE_MISC, &sc->sc_recv_ev, sc->sc_if.if_xname, "PLCP Signal Field error"); + + evcnt_attach_dynamic(&sc->sc_xmit_ev, EVCNT_TYPE_MISC, + NULL, sc->sc_if.if_xname, "xmit"); + evcnt_attach_dynamic(&sc->sc_tuf_ev, EVCNT_TYPE_MISC, + &sc->sc_xmit_ev, sc->sc_if.if_xname, "transmit underflow"); + evcnt_attach_dynamic(&sc->sc_tro_ev, EVCNT_TYPE_MISC, + &sc->sc_xmit_ev, sc->sc_if.if_xname, "transmit overrun"); + evcnt_attach_dynamic(&sc->sc_trt_ev, EVCNT_TYPE_MISC, + &sc->sc_xmit_ev, sc->sc_if.if_xname, "retry count exceeded"); + evcnt_attach_dynamic(&sc->sc_tlt_ev, EVCNT_TYPE_MISC, + &sc->sc_xmit_ev, sc->sc_if.if_xname, "lifetime exceeded"); + evcnt_attach_dynamic(&sc->sc_sofbr_ev, EVCNT_TYPE_MISC, + &sc->sc_xmit_ev, sc->sc_if.if_xname, "packet size mismatch"); + + evcnt_attach_dynamic(&sc->sc_misc_ev, EVCNT_TYPE_MISC, + NULL, sc->sc_if.if_xname, "misc"); + evcnt_attach_dynamic(&sc->sc_workaround1_ev, EVCNT_TYPE_MISC, + &sc->sc_misc_ev, sc->sc_if.if_xname, "workaround #1"); + evcnt_attach_dynamic(&sc->sc_rxamatch_ev, EVCNT_TYPE_MISC, + &sc->sc_misc_ev, sc->sc_if.if_xname, "rra equals rwa"); + evcnt_attach_dynamic(&sc->sc_rxpkt1in_ev, EVCNT_TYPE_MISC, + &sc->sc_misc_ev, sc->sc_if.if_xname, "rxpkt1in set"); } #ifdef ATW_DEBUG @@ -3441,6 +3489,7 @@ struct ieee80211_frame_min *whm; struct ieee80211_frame *wh; struct atw_frame *hh; + uint16_t hdrctl; struct mbuf *m0, *m; struct atw_txsoft *txs, *last_txs; struct atw_txdesc *txd; @@ -3472,6 +3521,8 @@ while ((txs = SIMPLEQ_FIRST(&sc->sc_txfreeq)) != NULL && sc->sc_txfree != 0) { + hdrctl = htole16(ATW_HDRCTL_UNKNOWN1); + /* * Grab a packet off the management queue, if it * is not empty. Otherwise, from the data queue. @@ -3515,6 +3566,14 @@ ifp->if_oerrors++; break; } +#if 0 + if (IEEE80211_IS_MULTICAST(wh->i_addr1) && + m0->m_pkthdr.len > ic->ic_fragthreshold) + hdrctl |= htole16(ATW_HDRCTL_MORE_FRAG); +#endif + + if (m0->m_pkthdr.len + IEEE80211_CRC_LEN >= ic->ic_rtsthreshold) + hdrctl |= htole16(ATW_HDRCTL_RTSCTS); if (ieee80211_compute_duration(whm, k, m0->m_pkthdr.len, ic->ic_flags, ic->ic_fragthreshold, rate, @@ -3593,12 +3652,20 @@ hh->atw_paylen = htole16(m0->m_pkthdr.len - sizeof(struct atw_frame)); - hh->atw_fragthr = htole16(ic->ic_fragthreshold); + /* never fragment multicast frames */ + if (IEEE80211_IS_MULTICAST(hh->atw_dst)) + hh->atw_fragthr = htole16(IEEE80211_FRAG_MAX); + else { + if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && + (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) + hdrctl |= htole16(ATW_HDRCTL_SHORT_PREAMBLE); + hh->atw_fragthr = htole16(ic->ic_fragthreshold); + } + hh->atw_rtylmt = 3; - hh->atw_hdrctl = htole16(ATW_HDRCTL_UNKNOWN1); #if 0 if (do_encrypt) { - hh->atw_hdrctl |= htole16(ATW_HDRCTL_WEP); + hdrctl |= htole16(ATW_HDRCTL_WEP); hh->atw_keyid = ic->ic_def_txkey; } #endif @@ -3612,15 +3679,9 @@ hh->atw_head_dur = htole16(txs->txs_d0.d_rts_dur); hh->atw_tail_dur = htole16(txs->txs_dn.d_rts_dur); - /* never fragment multicast frames */ - if (IEEE80211_IS_MULTICAST(hh->atw_dst)) { - hh->atw_fragthr = htole16(ic->ic_fragthreshold); - } else if (sc->sc_flags & ATWF_RTSCTS) { - hh->atw_hdrctl |= htole16(ATW_HDRCTL_RTSCTS); - } - + hh->atw_hdrctl = hdrctl; + hh->atw_fragnum = npkt << 4; #ifdef ATW_DEBUG - hh->atw_fragnum = 0; if ((ifp->if_flags & IFF_DEBUG) != 0 && atw_debug > 2) { printf("%s: dst = %s, rate = 0x%02x, " @@ -3833,6 +3894,7 @@ atw_ioctl(struct ifnet *ifp, u_long cmd, void *data) { struct atw_softc *sc = ifp->if_softc; + struct ieee80211req *ireq; int s, error = 0; /* XXX monkey see, monkey do. comes from wi_ioctl. */ @@ -3866,6 +3928,22 @@ error = 0; } break; + case SIOCS80211: + ireq = data; + if (ireq->i_type == IEEE80211_IOC_FRAGTHRESHOLD) { + if ((error = kauth_authorize_network(curlwp->l_cred, + KAUTH_NETWORK_INTERFACE, + KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, + (void *)cmd, NULL) != 0)) + break; + if (!(IEEE80211_FRAG_MIN <= ireq->i_val && + ireq->i_val <= IEEE80211_FRAG_MAX)) + error = EINVAL; + else + sc->sc_ic.ic_fragthreshold = ireq->i_val; + break; + } + /*FALLTHROUGH*/ default: error = ieee80211_ioctl(&sc->sc_ic, cmd, data); if (error == ENETRESET || error == ERESTART) { Index: src/sys/dev/ic/atwvar.h diff -u src/sys/dev/ic/atwvar.h:1.31 src/sys/dev/ic/atwvar.h:1.32 --- src/sys/dev/ic/atwvar.h:1.31 Tue May 12 14:25:17 2009 +++ src/sys/dev/ic/atwvar.h Sun Sep 13 22:07:34 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: atwvar.h,v 1.31 2009/05/12 14:25:17 cegger Exp $ */ +/* $NetBSD: atwvar.h,v 1.32 2009/09/13 22:07:34 dyoung Exp $ */ /* * Copyright (c) 2003, 2004 The NetBSD Foundation, Inc. All rights reserved. @@ -36,17 +36,6 @@ #include <sys/time.h> /* - * Some misc. statics, useful for debugging. - */ -struct atw_stats { - u_long ts_tx_tuf; /* transmit underflow errors */ - u_long ts_tx_tro; /* transmit jabber timeouts */ - u_long ts_tx_trt; /* retry count exceeded */ - u_long ts_tx_tlt; /* lifetime exceeded */ - u_long ts_tx_sofbr; /* packet size mismatch */ -}; - -/* * Transmit descriptor list size. This is arbitrary, but allocate * enough descriptors for 64 pending transmissions and 16 segments * per packet. Since a descriptor holds 2 buffer addresses, that's @@ -192,8 +181,6 @@ struct ieee80211_node *(*sc_node_alloc)(struct ieee80211_node_table*); void (*sc_node_free)(struct ieee80211_node *); - struct atw_stats sc_stats; /* debugging stats */ - int sc_tx_timer; int sc_rescan_timer; @@ -252,9 +239,6 @@ u_int32_t sc_txint_mask; /* mask of Tx interrupts we want */ u_int32_t sc_linkint_mask;/* link-state interrupts mask */ - /* interrupt acknowledge hook */ - void (*sc_intr_ack)(struct atw_softc *); - enum atw_rftype sc_rftype; enum atw_bbptype sc_bbptype; u_int32_t sc_synctl_rd; @@ -275,6 +259,18 @@ uint8_t sc_rf3000_options1; uint8_t sc_rf3000_options2; + struct evcnt sc_misc_ev; + struct evcnt sc_workaround1_ev; + struct evcnt sc_rxamatch_ev; + struct evcnt sc_rxpkt1in_ev; + + struct evcnt sc_xmit_ev; + struct evcnt sc_tuf_ev; /* transmit underflow errors */ + struct evcnt sc_tro_ev; /* transmit overrun */ + struct evcnt sc_trt_ev; /* retry count exceeded */ + struct evcnt sc_tlt_ev; /* lifetime exceeded */ + struct evcnt sc_sofbr_ev; /* packet size mismatch */ + struct evcnt sc_recv_ev; struct evcnt sc_crc16e_ev; struct evcnt sc_crc32e_ev; @@ -345,9 +341,13 @@ #define atw_ihdr u.s2.ihdr #define ATW_HDRCTL_SHORT_PREAMBLE __BIT(0) /* use short preamble */ +#define ATW_HDRCTL_MORE_FRAG __BIT(1) /* ??? from Linux */ +#define ATW_HDRCTL_MORE_DATA __BIT(2) /* ??? from Linux */ +#define ATW_HDRCTL_FRAG_NUM __BIT(3) /* ??? from Linux */ #define ATW_HDRCTL_RTSCTS __BIT(4) /* send RTS */ #define ATW_HDRCTL_WEP __BIT(5) -#define ATW_HDRCTL_UNKNOWN1 __BIT(15) /* MAC adds FCS? */ +/* MAC adds FCS? Linux calls this "enable extended header" */ +#define ATW_HDRCTL_UNKNOWN1 __BIT(15) #define ATW_HDRCTL_UNKNOWN2 __BIT(8) #define ATW_FRAGTHR_FRAGTHR_MASK __BITS(0, 11) @@ -358,10 +358,9 @@ #define ATWF_MRM 0x00000002 /* memory read multi okay */ #define ATWF_MWI 0x00000004 /* memory write inval okay */ #define ATWF_SHORT_PREAMBLE 0x00000008 /* short preamble enabled */ -#define ATWF_RTSCTS 0x00000010 /* RTS/CTS enabled */ -#define ATWF_ATTACHED 0x00000020 /* attach has succeeded */ -#define ATWF_ENABLED 0x00000040 /* chip is enabled */ -#define ATWF_WEP_SRAM_VALID 0x00000080 /* SRAM matches s/w state */ +#define ATWF_ATTACHED 0x00000010 /* attach has succeeded */ +#define ATWF_ENABLED 0x00000020 /* chip is enabled */ +#define ATWF_WEP_SRAM_VALID 0x00000040 /* SRAM matches s/w state */ #define ATW_IS_ENABLED(sc) ((sc)->sc_flags & ATWF_ENABLED)