ath_aux.c revision 7a1306a70fee0e017a445bde1dcfd1997f691cf4
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2002-2004 Sam Leffler, Errno Consulting
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
* redistribution must be conditioned upon including a substantially
* similar Disclaimer requirement for further binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/ethernet.h>
#include <sys/byteorder.h>
#include <inet/wifi_ioctl.h>
#include "ath_hal.h"
#include "ath_impl.h"
#include "ath_ieee80211.h"
static const char *acnames[] = {
"WME_AC_BE",
"WME_AC_BK",
"WME_AC_VI",
"WME_AC_VO",
"WME_UPSD"
};
{
return (rfilt);
}
static int
{
int qnum;
"ac %u out of range, max %u!\n",
return (1);
}
/*
* Enable interrupts only for EOL and DESC conditions.
* We mark tx descriptors to receive a DESC interrupt
* when a tx queue gets deep; otherwise waiting for the
* EOL to reap descriptors. Note that this is done to
* reduce interrupt load and this only defers reaping
* descriptors, never transmitting frames. Aside from
* reducing interrupts this also permits more concurrency.
* The only potential downside is if the tx queue backs
* up in which case the top half of the kernel may backup
* due to a lack of tx descriptors.
*/
if (qnum == -1) {
"Unable to setup hardware queue for %s traffic!\n",
return (1);
}
"hal qnum %u out of range, max %u!\n",
return (1);
}
txq->axq_intrcnt = 0;
}
return (0);
}
int
{
return (1);
}
return (0);
}
void
{
const HAL_RATE_TABLE *rt;
int i;
for (i = 0; i < sizeof (asc->asc_rixmap); i++)
}
/* Set correct parameters for a certain mode */
void
{
/* configure rx filter */
"mode =%d RX filter 0x%x, MC filter %08x:%08x\n",
}
/*
* Disable the receive h/w in preparation for a reset.
*/
void
{
drv_usecwait(3000);
}
{
0, /* IEEE80211_MODE_AUTO */
CHANNEL_A, /* IEEE80211_MODE_11A */
CHANNEL_B, /* IEEE80211_MODE_11B */
CHANNEL_PUREG, /* IEEE80211_MODE_11G */
CHANNEL_T /* IEEE80211_MODE_TURBO */
};
}
int
{
int i, ix;
chans = (HAL_CHANNEL *)
"unable to get channel list\n");
return (EINVAL);
}
/*
* Convert HAL channels to ieee80211 ones and insert
* them in the table according to their channel number.
*/
for (i = 0; i < nchan; i++) {
HAL_CHANNEL *c = &chans[i];
if (ix > IEEE80211_CHAN_MAX) {
"bad hal channel %u (%u/%x) ignored\n",
continue;
}
/* NB: flags are known to be compatible */
} else {
/* channels overlap; e.g. 11g and 11b */
}
}
return (0);
}
static void
{
/*
* This assumes output has been stopped.
*/
for (;;) {
break;
}
}
}
/*
* Drain the transmit queues and reclaim resources.
*/
void
{
int i;
if (!asc->asc_invalid) {
for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
if (ATH_TXQ_SETUP(asc, i)) {
}
}
}
for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
if (ATH_TXQ_SETUP(asc, i)) {
}
}
}
/* Enable the receive h/w following a reset */
int
{
}
return (0);
}
/*
* it's done by resetting the chip. To accomplish this we must
* first cleanup any pending DMA.
*/
int
{
enum ieee80211_phymode mode;
/*
* To switch channels clear any pending DMA operations;
* wait long enough for the RX fifo to drain, reset the
* hardware at the new frequency, and then re-enable
* the relevant bits of the h/w.
*/
/*
* Convert to a HAL channel description with
* the flags constrained to reflect the current
* operating mode.
*/
"unable to reset channel %u (%uMhz)\n",
return (EIO);
}
/*
* Re-enable rx framework.
*/
if (ath_startrecv(asc) != 0) {
ath_problem("ath: ath_chan_set(): "
"restarting receiving logic failed\n");
return (EIO);
}
/*
* Change channels and update the h/w rate map
* if we're switching; e.g. 11a to 11b/g.
*/
/*
* Re-enable interrupts.
*/
}
return (0);
}
/*
* Configure the beacon and sleep timers.
*
* When operating as an AP this resets the TSF and sets
* up the hardware to notify us when we need to issue beacons.
*
* When operating in station mode this sets up the beacon
* timers according to the timestamp of the last received
* beacon and the current TSF, configures PCF and DTIM
* handling, programs the sleep registers so the hardware
* will wakeup in time to receive beacons, and configures
* the beacon miss handling so we'll receive a BMISS
* interrupt when we stop seeing beacons from the AP
* we've associated with.
*/
void
{
/* NB: no PCF support right now */
/*
* Calculate the number of consecutive beacons to miss
* before taking a BMISS interrupt. The configuration
* is specified in ms, so we need to convert that to
* TU's and then calculate based on the beacon interval.
* Note that we clamp the result to at most 10 beacons.
*/
else if (bs.bs_bmissthreshold <= 0)
/*
* Calculate sleep duration. The configuration is
* given in ms. We insure a multiple of the beacon
* period is used. Also, if the sleep duration is
* greater than the DTIM period then it makes senses
* to make it a multiple of that.
*/
"intval %u nexttbtt %u dtim %u"
" nextdtim %u bmiss %u sleep %u\n",
ATH_HAL_INTRSET(ah, 0);
/*
* Reset our tsf so the hardware will update the
* tsf register to reflect timestamps found in
* received beacons.
*/
} else {
ATH_HAL_INTRSET(ah, 0);
}
}
/*
* Fill the hardware key cache with key entries.
*/
void
{
int32_t i;
for (i = 0; i < IEEE80211_WEP_NKID; i++) {
if (k->iwk_len == 0)
ATH_HAL_KEYRESET(ah, i);
else {
#ifdef DEBUG
int j;
for (j = 0; j < k->iwk_len; j++) {
}
"key%d val=%s\n", i, tmp));
#endif /* DEBUG */
}
}
}
void
{
struct ieee80211channel *ch;
/*
* Convert to a HAL channel description with the flags
* constrained to reflect the current operating mode.
*/
if (asc->asc_invalid == 0)
/* indicate channel change so we do a full reset */
ath_problem("ath: ath_reset(): "
"reseting hardware failed, HAL status %u\n", status);
}
if (asc->asc_invalid == 0) {
ath_problem("ath: ath_reset(): "
"starting receiving logic failed\n");
}
}
}