arn_recv.c revision 3ae945c326c1fc078149f2c8b11fac0cc8f6d1d6
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2008 Atheros Communications Inc.
*
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/byteorder.h>
#include "arn_core.h"
void
{
/* XXX block beacon interrupts */
sc->sc_rxotherant = 0;
}
/*
* Extend 15-bit time stamp from rx descriptor to
* a full 64-bit TSF using the current h/w TSF.
*/
static uint64_t
{
tsf -= 0x8000;
}
static void
{
/* configure rx filter */
/* configure bssid mask */
/* configure operational mode */
/* Handle any link-level address change. */
/* calculate and install multicast filter */
"mode = %d RX filter 0x%x, MC filter %08x:%08x\n",
}
/*
* Calculate the receive filter according to the
* operating mode and state:
*
* o always accept unicast, broadcast, and multicast traffic
* o maintain current state of phy error reception (the hal
* may enable phy error frames for noise immunity work)
* o probe request frames are accepted only when operating in
* hostap, adhoc, or monitor modes
* o enable promiscuous mode according to the interface state
* o accept beacons:
* - when operating in adhoc mode so the 802.11 layer creates
* node table entries for peers,
* - when operating in station mode for collecting rssi data when
* the station is otherwise quiet, or
* - when operating as a repeater so we see repeater-sta beacons
* - when scanning
*/
{
#define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | \
/* If not a STA, enable processing of Probe Requests */
/* Can't set HOSTAP into promiscous mode */
(sc->sc_promisc)) ||
/* ??? To prevent from sending ACK */
}
/*
* If in HOSTAP mode, want to enable reception of PSPOLL
* frames & beacon frames
*/
return (rfilt);
}
int
{
/* clean up rx link firstly */
/* rx descriptor link set up */
}
return (0);
}
{
ath9k_hw_setrxfilter(ah, 0);
/* 3ms is long enough for 1 frame ??? */
drv_usecwait(3000);
return (stopped);
}
/*
* Intercept management frames to collect beacon rssi data
* and to do ibss merges.
*/
void
{
/*
* Call up first so subsequent work can use information
* potentially stored in the node (e.g. for ibss merge).
*/
switch (subtype) {
/* update rssi statistics */
/*
* Resync beacon timers using the tsf of the beacon
* frame we just received.
*/
}
/* FALLTHRU */
/*
* Handle ibss merge as needed; check the tsf on the
* frame before attempting the merge. The 802.11 spec
* says the station should change it's bssid to match
* the oldest station with the same ssid, where oldest
* is determined by the tsf. Note that hardware
* reconfiguration happens through callback to
* ath_newstate as the state machine will go from
* RUN -> RUN when this happens.
*/
"ibss merge, rstamp %u tsf %lu "
ARN_UNLOCK(sc);
"ibss_merge: rstamp=%d in_tstamp=%02x %02x"
" %02x %02x %02x %02x %02x %02x\n",
(void) ieee80211_ibss_merge(in);
return;
}
}
break;
}
ARN_UNLOCK(sc);
}
static void
{
"%08x %08x %08x %c\n",
}
static void
{
struct ath_rx_status *rs;
struct ieee80211_frame *wh;
int status;
struct ieee80211_node *in;
ngood = 0;
do {
"no buffer\n"));
break;
}
/*
* Never process the self-linked entry at the end,
* this may be met at heavy load.
*/
break;
}
/*
* Must provide the virtual address of the current
* descriptor, the physical address, and the virtual
* address of the next descriptor in the h/w chain.
* This allows the HAL to look ahead to see if the
* hardware is done with a descriptor by checking the
* done bit in the following descriptor and the address
* of the current descriptor the DMA engine is working
* on. All this is necessary because of our use of
* a self-linked list to avoid rx overruns.
*/
if (status == EINPROGRESS) {
break;
}
}
}
}
}
goto rx_next;
}
/* less than sizeof(struct ieee80211_frame) */
if (len < 20) {
goto rx_next;
}
arn_problem("arn: arn_rx_handler(): "
"allocing mblk buffer failed.\n");
return;
}
/*
* Ignore control frame received in promisc mode.
*/
goto rx_next;
}
/* Remove the CRC at the end of IEEE80211 frame */
/*
* Locate the node for sender, track state, and then
* pass the (referenced) node up to the 802.11 layer
* for its use.
*/
/* Update Beacon RSSI, this is used by ANI. */
if (subtype == IEEE80211_FC0_SUBTYPE_BEACON)
}
#ifdef DEBUG
#endif
/*
* signal 13-15 DLADM_WLAN_STRENGTH_EXCELLENT
* signal 10-12 DLADM_WLAN_STRENGTH_VERY_GOOD
* signal 6-9 DLADM_WLAN_STRENGTH_GOOD
* signal 3-5 DLADM_WLAN_STRENGTH_WEAK
* signal 0-2 DLADM_WLAN_STRENGTH_VERY_WEAK
*/
cur_signal = 0;
else
/*
* Send the frame to net80211 for processing
*/
else
/* release node */
/*
* Arrange to update the last rx timestamp only for
* frames from our ap when operating in station mode.
* This assumes the rx key is always setup when associated.
*/
ngood++;
}
/*
* change the default rx antenna if rx diversity chooses the
* other antenna 3 times in a row.
*/
sc->sc_rxotherant = 0;
}
} else {
sc->sc_rxotherant = 0;
}
} while (loop);
if (ngood)
}
{
if (sc->sc_rx_pend) {
/* Soft interrupt for this driver */
sc->sc_rx_pend = 0;
ARN_UNLOCK(sc);
return (DDI_INTR_CLAIMED);
}
ARN_UNLOCK(sc);
return (DDI_INTR_UNCLAIMED);
}