[Madwifi-cvs] madwifi/ath if_ath.c,1.36.2.48,1.36.2.49 if_athvar.h,1.17.2.7,1.17.2.8
Status: Beta
Brought to you by:
otaku
From: John B. <jb...@us...> - 2005-04-13 02:47:49
|
Update of /cvsroot/madwifi/madwifi/ath In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21697 Modified Files: Tag: BSD if_ath.c if_athvar.h Log Message: Add an additional device, athXraw, for "live" monitor mode. This is disabled by default. There are two new sysctls to interact with athXraw: dev.athX.rawdev - a value of "1" registers the device, "0" unregisters it. It is 0 by default. dev.athX.rawdev_type - The dev->type for athXraw. (0 = 802.11, 1 = 802.11 + prism, 2 = 802.11 + radiotap). It is 0 by default. Also simplify skb headroom calculations, moving it all into ath_rxbuf_init. Additionally, packets that were sent by the card are handed to athXraw if it exists after the card gives us the tx result. The live monitor device is loosely based on a patch sent in by Yury Shevchuk. Index: if_ath.c =================================================================== RCS file: /cvsroot/madwifi/madwifi/ath/if_ath.c,v retrieving revision 1.36.2.48 retrieving revision 1.36.2.49 diff -C2 -d -r1.36.2.48 -r1.36.2.49 *** if_ath.c 12 Apr 2005 20:47:04 -0000 1.36.2.48 --- if_ath.c 13 Apr 2005 02:47:21 -0000 1.36.2.49 *************** *** 179,182 **** --- 179,184 ---- static void ath_setcurmode(struct ath_softc *, enum ieee80211_phymode); + static int ath_rawdev_attach(struct ath_softc *); + static void ath_rawdev_detach(struct ath_softc *); #ifdef CONFIG_SYSCTL static void ath_dynamic_sysctl_register(struct ath_softc *); *************** *** 618,621 **** --- 620,626 ---- */ sc->sc_hasveol = ath_hal_hasveol(ah); + + sc->sc_rawdev_enabled = 0; + sc->sc_rawdev.type = ARPHRD_IEEE80211; /* get mac address from hardware */ *************** *** 720,723 **** --- 725,729 ---- ath_dynamic_sysctl_unregister(sc); #endif /* CONFIG_SYSCTL */ + ath_rawdev_detach(sc); unregister_netdev(dev); *************** *** 941,961 **** /* - * Resize receive skb's if changing to or from monitor mode - */ - if ((dev->type == ARPHRD_ETHER && - ic->ic_opmode == IEEE80211_M_MONITOR) || - (dev->type == ARPHRD_IEEE80211_PRISM && - ic->ic_opmode != IEEE80211_M_MONITOR)) { - struct ath_buf *bf; - STAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) - if (bf->bf_skb != NULL) { - bus_unmap_single(sc->sc_bdev, - bf->bf_skbaddr, sc->sc_rxbufsize, - BUS_DMA_FROMDEVICE); - dev_kfree_skb(bf->bf_skb); - bf->bf_skb = NULL; - } - } - /* * Change our interface type if we are in monitor mode. */ --- 947,950 ---- *************** *** 1865,1883 **** } - static struct sk_buff * - ath_alloc_skb(u_int size, u_int align) - { - struct sk_buff *skb; - u_int off; - - skb = dev_alloc_skb(size + align-1); - if (skb != NULL) { - off = ((unsigned long) skb->data) % align; - if (off != 0) - skb_reserve(skb, align - off); - } - return skb; - } - /* * Set the slot time based on the current setting. --- 1854,1857 ---- *************** *** 2542,2546 **** }; enum { ! P80211ENUM_truth_false = 0x00 }; --- 2516,2521 ---- }; enum { ! P80211ENUM_truth_false = 0x00, ! P80211ENUM_truth_true = 0x01 }; *************** *** 2575,2625 **** struct sk_buff *skb; struct ath_desc *ds; skb = bf->bf_skb; if (skb == NULL) { ! if (sc->sc_ic.ic_opmode == IEEE80211_M_MONITOR) { ! u_int off; ! /* ! * Allocate buffer for monitor mode with space for the ! * wlan-ng style physical layer header at the start. ! */ ! skb = dev_alloc_skb(sc->sc_rxbufsize + ! sizeof(wlan_ng_prism2_header) + ! sc->sc_cachelsz - 1); ! if (skb == NULL) { ! DPRINTF(sc, ATH_DEBUG_ANY, ! "%s: skbuff alloc of size %d failed\n", ! __func__, ! (int)(sc->sc_rxbufsize ! + sizeof(wlan_ng_prism2_header) ! + sc->sc_cachelsz - 1)); ! sc->sc_stats.ast_rx_nobuf++; ! return ENOMEM; ! } ! /* ! * Reserve space for the Prism header. ! */ ! skb_reserve(skb, sizeof(wlan_ng_prism2_header)); ! /* ! * Align to cache line. ! */ ! off = ((unsigned long) skb->data) % sc->sc_cachelsz; ! if (off != 0) ! skb_reserve(skb, sc->sc_cachelsz - off); ! } else { ! /* ! * Cache-line-align. This is important (for the ! * 5210 at least) as not doing so causes bogus data ! * in rx'd frames. ! */ ! skb = ath_alloc_skb(sc->sc_rxbufsize, sc->sc_cachelsz); ! if (skb == NULL) { ! DPRINTF(sc, ATH_DEBUG_ANY, ! "%s: skbuff alloc of size %u failed\n", ! __func__, sc->sc_rxbufsize); ! sc->sc_stats.ast_rx_nobuf++; ! return ENOMEM; ! } } skb->dev = &sc->sc_dev; bf->bf_skb = skb; --- 2550,2610 ---- struct sk_buff *skb; struct ath_desc *ds; + int headroom_needed = 0; + + if (sc->sc_ic.ic_opmode == IEEE80211_M_MONITOR) { + headroom_needed = sizeof(wlan_ng_prism2_header); + } else if (sc->sc_rawdev.type == ARPHRD_IEEE80211_PRISM) { + headroom_needed = sizeof(wlan_ng_prism2_header); + } else if (sc->sc_rawdev.type == ARPHRD_IEEE80211_RADIOTAP) { + headroom_needed = sizeof(struct ath_rx_radiotap_header); + } + + /* + * Check if we have enough headroom. If not, just free the skb + * and we'll alloc another one below. + */ + if (bf->bf_skb && skb_headroom(bf->bf_skb) < headroom_needed) { + bus_unmap_single(sc->sc_bdev, + bf->bf_skbaddr, sc->sc_rxbufsize, + BUS_DMA_FROMDEVICE); + dev_kfree_skb(bf->bf_skb); + bf->bf_skb = NULL; + } skb = bf->bf_skb; + if (skb == NULL) { ! u_int off; ! ! /* ! * Allocate buffer with headroom_needed space for the ! * fake physical layer header at the start. ! */ ! skb = dev_alloc_skb(sc->sc_rxbufsize + ! headroom_needed + ! sc->sc_cachelsz - 1); ! if (skb == NULL) { ! DPRINTF(sc, ATH_DEBUG_ANY, ! "%s: skbuff alloc of size %d failed\n", ! __func__, ! (int)(sc->sc_rxbufsize ! + headroom_needed ! + sc->sc_cachelsz - 1)); ! sc->sc_stats.ast_rx_nobuf++; ! return ENOMEM; } + /* + * Reserve space for the fake physical layer header. + */ + skb_reserve(skb, headroom_needed); + /* + * Cache-line-align. This is important (for the + * 5210 at least) as not doing so causes bogus data + * in rx'd frames. + */ + off = ((unsigned long) skb->data) % sc->sc_cachelsz; + if (off != 0) + skb_reserve(skb, sc->sc_cachelsz - off); + skb->dev = &sc->sc_dev; bf->bf_skb = skb; *************** *** 2665,2671 **** /* ! * Add a prism2 header to a received frame and ! * dispatch it to capture tools like kismet. ! * TODO: can stay unchanged? */ static void --- 2650,2801 ---- /* ! * Add additional headers to a transmitted frame and netif_rx it on ! * a monitor or raw device ! */ ! static void ! ath_tx_capture(struct net_device *dev, struct ath_desc *ds, struct sk_buff *skb) ! { ! struct ath_softc *sc = dev->priv; ! struct ieee80211com *ic = &sc->sc_ic; ! u_int32_t tsf; ! ! /* ! * release the owner of this skb since we're basically ! * recycling it ! */ ! if (atomic_read(&skb->users) != 1) { ! struct sk_buff *skb2 = skb; ! skb = skb_clone(skb, GFP_ATOMIC); ! if (skb == NULL) { ! dev_kfree_skb(skb2); ! return; ! } ! kfree_skb(skb2); ! } else { ! skb_orphan(skb); ! } ! ! switch (dev->type) { ! case ARPHRD_IEEE80211: ! break; ! case ARPHRD_IEEE80211_PRISM: { ! wlan_ng_prism2_header *ph; ! if (skb_headroom(skb) < sizeof(wlan_ng_prism2_header) && ! pskb_expand_head(skb, ! sizeof(wlan_ng_prism2_header), ! 0, GFP_ATOMIC)) { ! DPRINTF(sc, ATH_DEBUG_RECV, ! "%s: couldn't pskb_expand_head\n", __func__); ! goto bad; ! } ! ! ph = (wlan_ng_prism2_header *) ! skb_push(skb, sizeof(wlan_ng_prism2_header)); ! memset(ph, 0, sizeof(wlan_ng_prism2_header)); ! ! ph->msgcode = DIDmsg_lnxind_wlansniffrm; ! ph->msglen = sizeof(wlan_ng_prism2_header); ! strcpy(ph->devname, sc->sc_dev.name); ! ! ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime; ! ph->hosttime.status = 0; ! ph->hosttime.len = 4; ! ph->hosttime.data = jiffies; ! ! /* Pass up tsf clock in mactime */ ! ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime; ! ph->mactime.status = 0; ! ph->mactime.len = 4; ! /* ! * Rx descriptor has the low 15 bits of the tsf at ! * the time the frame was received. Use the current ! * tsf to extend this to 32 bits. ! */ ! tsf = ath_hal_gettsf32(sc->sc_ah); ! if ((tsf & 0x7fff) < ds->ds_rxstat.rs_tstamp) ! tsf -= 0x8000; ! ph->mactime.data = ds->ds_rxstat.rs_tstamp | (tsf &~ 0x7fff); ! ! ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx; ! ph->istx.status = 0; ! ph->istx.len = 4; ! ph->istx.data = P80211ENUM_truth_true; ! ! ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen; ! ph->frmlen.status = 0; ! ph->frmlen.len = 4; ! ph->frmlen.data = ds->ds_rxstat.rs_datalen; ! ! ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel; ! ph->channel.status = 0; ! ph->channel.len = 4; ! ph->channel.data = ieee80211_mhz2ieee(ic->ic_ibss_chan->ic_freq,0); ! ! ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi; ! ph->rssi.status = 0; ! ph->rssi.len = 4; ! ph->rssi.data = ds->ds_rxstat.rs_rssi; ! ! ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise; ! ph->noise.status = 0; ! ph->noise.len = 4; ! ph->noise.data = -95; ! ! ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal; ! ph->signal.status = 0; ! ph->signal.len = 4; ! ph->signal.data = -95 + ds->ds_rxstat.rs_rssi; ! ! ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate; ! ph->rate.status = 0; ! ph->rate.len = 4; ! ph->rate.data = sc->sc_hwmap[ds->ds_rxstat.rs_rate].ieeerate; ! break; ! } ! case ARPHRD_IEEE80211_RADIOTAP: { ! struct ath_tx_radiotap_header *th; ! ! if (skb_headroom(skb) < sizeof(struct ath_tx_radiotap_header) && ! pskb_expand_head(skb, ! sizeof(struct ath_tx_radiotap_header), ! 0, GFP_ATOMIC)) { ! DPRINTF(sc, ATH_DEBUG_RECV, ! "%s: couldn't pskb_expand_head\n", __func__); ! goto bad; ! } ! ! th = (struct ath_tx_radiotap_header *) skb_push(skb, sizeof(struct ath_tx_radiotap_header)); ! memset(th, 0, sizeof(struct ath_rx_radiotap_header)); ! th->wt_ihdr.it_version = 0; ! th->wt_ihdr.it_len = sizeof(struct ath_rx_radiotap_header); ! th->wt_ihdr.it_present = ATH_TX_RADIOTAP_PRESENT; ! th->wt_flags = 0; ! th->wt_rate = sc->sc_hwmap[ds->ds_txstat.ts_rate].ieeerate; ! th->wt_chan_freq = ic->ic_ibss_chan->ic_freq; ! th->wt_chan_flags = ic->ic_ibss_chan->ic_flags; ! th->wt_txpower = 0; ! th->wt_antenna = ds->ds_txstat.ts_antenna; ! break; ! } ! default: ! break; ! } ! ! skb->dev = dev; ! skb->mac.raw = skb->data; ! skb->ip_summed = CHECKSUM_NONE; ! skb->pkt_type = PACKET_OTHERHOST; ! skb->protocol = __constant_htons(0x0019); /* ETH_P_80211_RAW */ ! netif_rx(skb); ! return; ! ! bad: ! dev_kfree_skb(skb); ! return; ! } ! ! /* ! * Add additional headers to a received frame and netif_rx it on ! * a monitor or raw device */ static void *************** *** 2679,2683 **** int len = ds->ds_rxstat.rs_datalen; struct ieee80211_frame *wh; - wlan_ng_prism2_header *ph; u_int32_t tsf; --- 2809,2812 ---- *************** *** 2704,2772 **** } ! /* ! * enough headroom ist assured by ath_rxbuf_init ! */ ! ph = (wlan_ng_prism2_header *) ! skb_push(skb, sizeof(wlan_ng_prism2_header)); ! memset(ph, 0, sizeof(wlan_ng_prism2_header)); ! ! ph->msgcode = DIDmsg_lnxind_wlansniffrm; ! ph->msglen = sizeof(wlan_ng_prism2_header); ! strcpy(ph->devname, dev->name); ! ! ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime; ! ph->hosttime.status = 0; ! ph->hosttime.len = 4; ! ph->hosttime.data = jiffies; ! ! /* Pass up tsf clock in mactime */ ! ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime; ! ph->mactime.status = 0; ! ph->mactime.len = 4; ! /* ! * Rx descriptor has the low 15 bits of the tsf at ! * the time the frame was received. Use the current ! * tsf to extend this to 32 bits. ! */ ! tsf = ath_hal_gettsf32(sc->sc_ah); ! if ((tsf & 0x7fff) < ds->ds_rxstat.rs_tstamp) ! tsf -= 0x8000; ! ph->mactime.data = ds->ds_rxstat.rs_tstamp | (tsf &~ 0x7fff); ! ! ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx; ! ph->istx.status = 0; ! ph->istx.len = 4; ! ph->istx.data = P80211ENUM_truth_false; ! ! ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen; ! ph->frmlen.status = 0; ! ph->frmlen.len = 4; ! ph->frmlen.data = len; ! ! ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel; ! ph->channel.status = 0; ! ph->channel.len = 4; ! ph->channel.data = ieee80211_mhz2ieee(ic->ic_ibss_chan->ic_freq,0); ! ! ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi; ! ph->rssi.status = 0; ! ph->rssi.len = 4; ! ph->rssi.data = ds->ds_rxstat.rs_rssi; ! ! ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise; ! ph->noise.status = 0; ! ph->noise.len = 4; ! ph->noise.data = -95; ! ! ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal; ! ph->signal.status = 0; ! ph->signal.len = 4; ! ph->signal.data = -95 + ds->ds_rxstat.rs_rssi; ! ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate; ! ph->rate.status = 0; ! ph->rate.len = 4; ! ph->rate.data = sc->sc_hwmap[ds->ds_rxstat.rs_rate].ieeerate; skb->dev = dev; skb->mac.raw = skb->data; --- 2833,2939 ---- } ! switch (dev->type) { ! case ARPHRD_IEEE80211: ! break; ! case ARPHRD_IEEE80211_PRISM: { ! wlan_ng_prism2_header *ph; ! if (skb_headroom(skb) < sizeof(wlan_ng_prism2_header)) { ! DPRINTF(sc, ATH_DEBUG_RECV, ! "%s: prism not enough headroom %d/%d\n", ! __func__, skb_headroom(skb), ! sizeof(wlan_ng_prism2_header)); ! goto bad; ! } ! ph = (wlan_ng_prism2_header *) ! skb_push(skb, sizeof(wlan_ng_prism2_header)); ! memset(ph, 0, sizeof(wlan_ng_prism2_header)); ! ! ph->msgcode = DIDmsg_lnxind_wlansniffrm; ! ph->msglen = sizeof(wlan_ng_prism2_header); ! strcpy(ph->devname, sc->sc_dev.name); ! ! ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime; ! ph->hosttime.status = 0; ! ph->hosttime.len = 4; ! ph->hosttime.data = jiffies; ! ! /* Pass up tsf clock in mactime */ ! ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime; ! ph->mactime.status = 0; ! ph->mactime.len = 4; ! /* ! * Rx descriptor has the low 15 bits of the tsf at ! * the time the frame was received. Use the current ! * tsf to extend this to 32 bits. ! */ ! tsf = ath_hal_gettsf32(sc->sc_ah); ! if ((tsf & 0x7fff) < ds->ds_rxstat.rs_tstamp) ! tsf -= 0x8000; ! ph->mactime.data = ds->ds_rxstat.rs_tstamp | (tsf &~ 0x7fff); ! ! ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx; ! ph->istx.status = 0; ! ph->istx.len = 4; ! ph->istx.data = P80211ENUM_truth_false; ! ! ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen; ! ph->frmlen.status = 0; ! ph->frmlen.len = 4; ! ph->frmlen.data = len; ! ! ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel; ! ph->channel.status = 0; ! ph->channel.len = 4; ! ph->channel.data = ieee80211_mhz2ieee(ic->ic_ibss_chan->ic_freq,0); ! ! ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi; ! ph->rssi.status = 0; ! ph->rssi.len = 4; ! ph->rssi.data = ds->ds_rxstat.rs_rssi; ! ! ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise; ! ph->noise.status = 0; ! ph->noise.len = 4; ! ph->noise.data = -95; ! ! ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal; ! ph->signal.status = 0; ! ph->signal.len = 4; ! ph->signal.data = -95 + ds->ds_rxstat.rs_rssi; ! ! ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate; ! ph->rate.status = 0; ! ph->rate.len = 4; ! ph->rate.data = sc->sc_hwmap[ds->ds_rxstat.rs_rate].ieeerate; ! break; ! } ! case ARPHRD_IEEE80211_RADIOTAP: { ! struct ath_rx_radiotap_header *th; ! if (skb_headroom(skb) < sizeof(struct ath_rx_radiotap_header)) { ! DPRINTF(sc, ATH_DEBUG_RECV, ! "%s: radiotap not enough headroom %d/%d\n", ! __func__, skb_headroom(skb), ! sizeof(struct ath_rx_radiotap_header)); ! goto bad; ! } ! th = (struct ath_rx_radiotap_header *) skb_push(skb, sizeof(struct ath_rx_radiotap_header)); ! memset(th, 0, sizeof(struct ath_rx_radiotap_header)); ! th->wr_ihdr.it_version = 0; ! th->wr_ihdr.it_len = sizeof(struct ath_rx_radiotap_header); ! th->wr_ihdr.it_present = ATH_RX_RADIOTAP_PRESENT; ! th->wr_flags = 0; ! th->wr_rate = sc->sc_hwmap[ds->ds_rxstat.rs_rate].ieeerate; ! th->wr_chan_freq = ic->ic_ibss_chan->ic_freq; ! th->wr_chan_flags = ic->ic_ibss_chan->ic_flags; ! th->wr_antenna = ds->ds_rxstat.rs_antenna; ! th->wr_antsignal = ds->ds_rxstat.rs_rssi; + break; + } + default: + break; + } + skb->dev = dev; skb->mac.raw = skb->data; *************** *** 2774,2779 **** skb->pkt_type = PACKET_OTHERHOST; skb->protocol = __constant_htons(0x0019); /* ETH_P_80211_RAW */ ! netif_rx(skb); #undef IS_QOS_DATA } --- 2941,2951 ---- skb->pkt_type = PACKET_OTHERHOST; skb->protocol = __constant_htons(0x0019); /* ETH_P_80211_RAW */ ! netif_rx(skb); + return; + + bad: + dev_kfree_skb(skb); + return; #undef IS_QOS_DATA } *************** *** 3011,3014 **** --- 3183,3194 ---- sc->sc_stats.ast_ant_rx[ds->ds_rxstat.rs_antenna]++; + + if (len < IEEE80211_ACK_LEN) { + DPRINTF(sc, ATH_DEBUG_RECV, + "%s: runt packet %d\n", __func__, len); + sc->sc_stats.ast_rx_tooshort++; + dev_kfree_skb(skb); + goto rx_next; + } if (ic->ic_opmode == IEEE80211_M_MONITOR) { *************** *** 3019,3029 **** * and dispatch. */ - if (len < IEEE80211_ACK_LEN) { - DPRINTF(sc, ATH_DEBUG_RECV, - "%s: runt packet %d\n", __func__, len); - sc->sc_stats.ast_rx_tooshort++; - dev_kfree_skb(skb); - goto rx_next; - } /* XXX TSF */ --- 3199,3202 ---- *************** *** 3032,3035 **** --- 3205,3216 ---- } + if (sc->sc_rawdev_enabled && (sc->sc_rawdev.flags & IFF_UP)) { + struct sk_buff *skb2; + skb2 = skb_clone(skb, GFP_ATOMIC); + if (skb2) { + ath_rx_capture(&sc->sc_rawdev, ds, skb2); + } + } + /* * From this point on we assume the frame is at least *************** *** 3610,3626 **** sc->sc_hwmap[txrate].ieeerate, -1); - // TODO: okay???? - if (ic->ic_opmode == IEEE80211_M_MONITOR) { - /* - sc->sc_tx_th.wt_flags = sc->sc_hwmap[txrate].txflags; - if (iswep) - sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP; - sc->sc_tx_th.wt_rate = sc->sc_hwmap[txrate].ieeerate; - sc->sc_tx_th.wt_txpower = ni->ni_txpower; - sc->sc_tx_th.wt_antenna = sc->sc_txantenna; - */ - ath_rx_capture(dev, ds, skb); - } - /* * Determine if a tx interrupt should be generated for --- 3791,3794 ---- *************** *** 3843,3847 **** bus_unmap_single(sc->sc_bdev, bf->bf_skbaddr, bf->bf_skb->len, BUS_DMA_TODEVICE); ! dev_kfree_skb(bf->bf_skb); bf->bf_skb = NULL; bf->bf_node = NULL; --- 4011,4020 ---- bus_unmap_single(sc->sc_bdev, bf->bf_skbaddr, bf->bf_skb->len, BUS_DMA_TODEVICE); ! ! if (sc->sc_rawdev_enabled) { ! ath_tx_capture(&sc->sc_rawdev, ds, bf->bf_skb); ! } else { ! dev_kfree_skb(bf->bf_skb); ! } bf->bf_skb = NULL; bf->bf_node = NULL; *************** *** 4676,4679 **** --- 4849,4893 ---- } + + static int + ath_rawdev_attach(struct ath_softc *sc) + { + struct net_device *rawdev; + unsigned t; + rawdev = &sc->sc_rawdev; + strcpy(rawdev->name, sc->sc_dev.name); + strcat(rawdev->name, "raw"); + rawdev->priv = sc; + + /* ether_setup clobbers type, so save it */ + t = rawdev->type; + ether_setup(rawdev); + rawdev->type = t; + + rawdev->stop = NULL; + rawdev->hard_start_xmit = NULL; + rawdev->set_multicast_list = NULL; + rawdev->get_stats = ath_getstats; + rawdev->tx_queue_len = 0; + rawdev->flags |= IFF_NOARP; + rawdev->flags &= ~IFF_MULTICAST; + + if (register_netdev(rawdev)) { + goto bad; + } + sc->sc_rawdev_enabled = 1; + return 0; + bad: + return -1; + } + + static void + ath_rawdev_detach(struct ath_softc *sc) + { + if (sc->sc_rawdev_enabled) { + sc->sc_rawdev_enabled = 0; + unregister_netdev(&sc->sc_rawdev); + } + } #if IEEE80211_VLAN_TAG_USED static void *************** *** 5209,5213 **** ATH_TXPOWLIMIT = 15, ATH_VEOL = 16, ! ATH_BINTVAL = 17 }; --- 5423,5429 ---- ATH_TXPOWLIMIT = 15, ATH_VEOL = 16, ! ATH_BINTVAL = 17, ! ATH_RAWDEV = 18, ! ATH_RAWDEV_TYPE = 19, }; *************** *** 5298,5301 **** --- 5514,5541 ---- ret = -EINVAL; break; + case ATH_RAWDEV: + if (val && !sc->sc_rawdev_enabled) { + ath_rawdev_attach(sc); + } else if (!val && sc->sc_rawdev_enabled) { + ath_rawdev_detach(sc); + } + ath_reset(&sc->sc_dev); + break; + case ATH_RAWDEV_TYPE: + switch (val) { + case 0: + sc->sc_rawdev.type = ARPHRD_IEEE80211; + break; + case 1: + sc->sc_rawdev.type = ARPHRD_IEEE80211_PRISM; + break; + case 2: + sc->sc_rawdev.type = ARPHRD_IEEE80211_RADIOTAP; + break; + default: + return -EINVAL; + } + ath_reset(&sc->sc_dev); + break; default: return -EINVAL; *************** *** 5355,5358 **** --- 5595,5610 ---- val = (sc->sc_ic).ic_lintval; break; + case ATH_RAWDEV: + val = sc->sc_rawdev_enabled; + break; + case ATH_RAWDEV_TYPE: + switch (sc->sc_rawdev.type) { + case ARPHRD_IEEE80211: val = 0; break; + case ARPHRD_IEEE80211_PRISM: val = 1; break; + case ARPHRD_IEEE80211_RADIOTAP: val = 2; break; + default: + val = 0; + } + break; default: return -EINVAL; *************** *** 5458,5461 **** --- 5710,5723 ---- .proc_handler = ath_sysctl_halparam }, + { .ctl_name = ATH_RAWDEV, + .procname = "rawdev", + .mode = 0644, + .proc_handler = ath_sysctl_halparam + }, + { .ctl_name = ATH_RAWDEV_TYPE, + .procname = "rawdev_type", + .mode = 0644, + .proc_handler = ath_sysctl_halparam + }, { 0 } }; Index: if_athvar.h =================================================================== RCS file: /cvsroot/madwifi/madwifi/ath/if_athvar.h,v retrieving revision 1.17.2.7 retrieving revision 1.17.2.8 diff -C2 -d -r1.17.2.7 -r1.17.2.8 *** if_athvar.h 12 Apr 2005 20:47:05 -0000 1.17.2.7 --- if_athvar.h 13 Apr 2005 02:47:22 -0000 1.17.2.8 *************** *** 52,55 **** --- 52,59 ---- #endif + #ifndef ARPHRD_IEEE80211_RADIOTAP + #define ARPHRD_IEEE80211_RADIOTAP 803 /* IEEE 802.11 + radiotap header */ + #endif /* ARPHRD_IEEE80211_RADIOTAP */ + /* * Deduce if tasklets are available. If not then *************** *** 215,218 **** --- 219,223 ---- struct ath_softc { struct net_device sc_dev; /* NB: must be first */ + struct net_device sc_rawdev; /* live monitor device */ struct semaphore sc_lock; /* dev-level lock */ struct net_device_stats sc_devstats; /* device statistics */ *************** *** 249,253 **** sc_blinking: 1, /* LED blink operation active */ sc_endblink: 1, /* finish LED blink operation */ ! sc_mcastkey: 1; /* mcast key cache search */ /* rate tables */ const HAL_RATE_TABLE *sc_rates[IEEE80211_MODE_MAX]; --- 254,259 ---- sc_blinking: 1, /* LED blink operation active */ sc_endblink: 1, /* finish LED blink operation */ ! sc_mcastkey: 1, /* mcast key cache search */ ! sc_rawdev_enabled : 1; /* enable sc_rawdev */ /* rate tables */ const HAL_RATE_TABLE *sc_rates[IEEE80211_MODE_MAX]; |