7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Use is subject to license terms.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * All rights reserved.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc *
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Redistribution and use in source and binary forms, with or without
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * modification, are permitted provided that the following conditions
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * are met:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * 1. Redistributions of source code must retain the above copyright
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * notice, this list of conditions and the following disclaimer,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * without modification.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * 2. Redistributions in binary form must reproduce at minimum a disclaimer
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * redistribution must be conditioned upon including a substantially
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * similar Disclaimer requirement for further binary redistribution.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * 3. Neither the names of the above-listed copyright holders nor the names
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * of any contributors may be used to endorse or promote products derived
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * from this software without specific prior written permission.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc *
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * NO WARRANTY
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * THE POSSIBILITY OF SUCH DAMAGES.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/param.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/types.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/signal.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/stream.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/termio.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/errno.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/file.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/cmn_err.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/stropts.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/strsubr.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/strtty.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/kbio.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/cred.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/stat.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/consdev.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/kmem.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/modctl.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/ddi.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/sunddi.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/pci.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/errno.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/gld.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/dlpi.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/ethernet.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/list.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/byteorder.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/strsun.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <inet/common.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <inet/nd.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <inet/mi.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <inet/wifi_ioctl.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include "ath_hal.h"
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include "ath_impl.h"
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic const char *acnames[] = {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "WME_AC_BE",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "WME_AC_BK",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "WME_AC_VI",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "WME_AC_VO",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "WME_UPSD"
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc};
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcextern void ath_setup_desc(ath_t *asc, struct ath_buf *bf);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc
3caf11144eab1a56717f986d44ae7f40ee8b28fcxcconst char *
3caf11144eab1a56717f986d44ae7f40ee8b28fcxcath_get_hal_status_desc(HAL_STATUS status)
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc{
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc static const char *hal_status_desc[] = {
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc "No error",
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc "No hardware present or device not yet supported",
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc "Memory allocation failed",
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc "Hardware didn't respond as expected",
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc "EEPROM magic number invalid",
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc "EEPROM version invalid",
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc "EEPROM unreadable",
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc "EEPROM checksum invalid",
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc "EEPROM read problem",
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc "EEPROM mac address invalid",
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc "EEPROM size not supported",
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc "Attempt to change write-locked EEPROM",
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc "Invalid parameter to function",
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc "Hardware revision not supported",
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc "Hardware self-test failed",
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc "Operation incomplete"
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc };
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc if (status >= 0 && status < sizeof (hal_status_desc)/sizeof (char *))
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc return (hal_status_desc[status]);
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc else
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc return ("");
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc}
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcuint32_t
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_calcrxfilter(ath_t *asc)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211com_t *ic = (ieee80211com_t *)asc;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_hal *ah = asc->asc_ah;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc uint32_t rfilt;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rfilt = (ATH_HAL_GETRXFILTER(ah) & HAL_RX_FILTER_PHYERR)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc | HAL_RX_FILTER_UCAST | HAL_RX_FILTER_BCAST | HAL_RX_FILTER_MCAST;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_opmode != IEEE80211_M_STA)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rfilt |= HAL_RX_FILTER_PROBEREQ;
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc if (ic->ic_opmode != IEEE80211_M_HOSTAP && asc->asc_promisc)
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc rfilt |= HAL_RX_FILTER_PROM; /* promiscuous */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_opmode == IEEE80211_M_STA ||
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_opmode == IEEE80211_M_IBSS ||
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_state == IEEE80211_S_SCAN)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rfilt |= HAL_RX_FILTER_BEACON;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (rfilt);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic int
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_set_data_queue(ath_t *asc, int ac, int haltype)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc HAL_TXQ_INFO qi;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc int qnum;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_hal *ah = asc->asc_ah;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_txq *txq;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (ac >= ATH_N(asc->asc_ac2q)) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_AUX, "ath: ath_set_data_queue(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "ac %u out of range, max %u!\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ac, ATH_N(asc->asc_ac2q)));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (1);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc (void) memset(&qi, 0, sizeof (qi));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc qi.tqi_subtype = haltype;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Enable interrupts only for EOL and DESC conditions.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * We mark tx descriptors to receive a DESC interrupt
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * when a tx queue gets deep; otherwise waiting for the
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * EOL to reap descriptors. Note that this is done to
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * reduce interrupt load and this only defers reaping
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * descriptors, never transmitting frames. Aside from
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * reducing interrupts this also permits more concurrency.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * The only potential downside is if the tx queue backs
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * up in which case the top half of the kernel may backup
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * due to a lack of tx descriptors.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc qi.tqi_qflags = HAL_TXQ_TXEOLINT_ENABLE | HAL_TXQ_TXDESCINT_ENABLE;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc qnum = ATH_HAL_SETUPTXQUEUE(ah, HAL_TX_QUEUE_DATA, &qi);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (qnum == -1) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_AUX, "ath: ath_set_data_queue(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "Unable to setup hardware queue for %s traffic!\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc acnames[ac]));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (1);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (qnum >= ATH_N(asc->asc_txq)) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_AUX, "ath: ath_set_data_queue(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "hal qnum %u out of range, max %u!\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc qnum, ATH_N(asc->asc_txq)));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (1);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (!ATH_TXQ_SETUP(asc, qnum)) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc txq = &asc->asc_txq[qnum];
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc txq->axq_qnum = qnum;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc txq->axq_depth = 0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc txq->axq_intrcnt = 0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc txq->axq_link = NULL;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc list_create(&txq->axq_list, sizeof (struct ath_buf),
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc offsetof(struct ath_buf, bf_node));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_init(&txq->axq_lock, NULL, MUTEX_DRIVER, NULL);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_txqsetup |= 1<<qnum;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_ac2q[ac] = &asc->asc_txq[qnum];
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcint
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_txq_setup(ath_t *asc)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (ath_set_data_queue(asc, WME_AC_BE, HAL_WME_AC_BK) ||
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_set_data_queue(asc, WME_AC_BK, HAL_WME_AC_BE) ||
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_set_data_queue(asc, WME_AC_VI, HAL_WME_AC_VI) ||
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_set_data_queue(asc, WME_AC_VO, HAL_WME_AC_VO)) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (1);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcvoid
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_txq_cleanup(ath_t *asc)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc int i;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mutex_destroy(&asc->asc_txbuflock);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ATH_TXQ_SETUP(asc, i)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ath_txq *txq = &asc->asc_txq[i];
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_HAL_RELEASETXQUEUE(asc->asc_ah, txq->axq_qnum);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mutex_destroy(&txq->axq_lock);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_txqsetup &= ~(1 << txq->axq_qnum);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcvoid
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_setcurmode(ath_t *asc, enum ieee80211_phymode mode)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc const HAL_RATE_TABLE *rt;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc int i;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc for (i = 0; i < sizeof (asc->asc_rixmap); i++)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_rixmap[i] = 0xff;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rt = asc->asc_rates[mode];
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ASSERT(rt != NULL);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc for (i = 0; i < rt->rateCount; i++)
5d2225f6bb395dbd38b87e1f0af3ce4afbca42f3ff asc->asc_rixmap[rt->info[i].dot11Rate & IEEE80211_RATE_VAL] =
5d2225f6bb395dbd38b87e1f0af3ce4afbca42f3ff (uint8_t)i;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_currates = rt;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_curmode = mode;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China /*
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * All protection frames are transmitted at 2Mb/s for
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * 11g, otherwise at 1Mb/s.
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * select protection rate index from rate table.
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China */
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China asc->asc_protrix = (mode == IEEE80211_MODE_11G ? 1 : 0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/* Set correct parameters for a certain mode */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcvoid
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_mode_init(ath_t *asc)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211com_t *ic = (ieee80211com_t *)asc;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_hal *ah = asc->asc_ah;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc uint32_t rfilt;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* configure rx filter */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rfilt = ath_calcrxfilter(asc);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_SETRXFILTER(ah, rfilt);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_SETOPMODE(ah);
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc ATH_HAL_SETMCASTFILTER(ah, asc->asc_mcast_hash[0],
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc asc->asc_mcast_hash[1]);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_AUX, "ath: ath_mode_init(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "mode =%d RX filter 0x%x, MC filter %08x:%08x\n",
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_opmode, rfilt,
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc asc->asc_mcast_hash[0], asc->asc_mcast_hash[1]));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Disable the receive h/w in preparation for a reset.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcvoid
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_stoprecv(ath_t *asc)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_STOPPCURECV(asc->asc_ah); /* disable PCU */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_SETRXFILTER(asc->asc_ah, 0); /* clear recv filter */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_STOPDMARECV(asc->asc_ah); /* disable DMA engine */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc drv_usecwait(3000);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_AUX, "ath: ath_stoprecv(): rx queue %p, link %p\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_GETRXBUF(asc->asc_ah), asc->asc_rxlink));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_rxlink = NULL;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcuint32_t
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_chan2flags(ieee80211com_t *isc, struct ieee80211_channel *chan)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc static const uint32_t modeflags[] = {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc 0, /* IEEE80211_MODE_AUTO */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc CHANNEL_A, /* IEEE80211_MODE_11A */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc CHANNEL_B, /* IEEE80211_MODE_11B */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc CHANNEL_PUREG, /* IEEE80211_MODE_11G */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc 0, /* IEEE80211_MODE_FH */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc CHANNEL_108A, /* IEEE80211_MODE_TURBO_A */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc CHANNEL_108G /* IEEE80211_MODE_TURBO_G */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc };
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (modeflags[ieee80211_chan2mode(isc, chan)]);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcint
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_getchannels(ath_t *asc, uint32_t cc, HAL_BOOL outdoor, HAL_BOOL xchanmode)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211com_t *ic = (ieee80211com_t *)asc;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_hal *ah = asc->asc_ah;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc HAL_CHANNEL *chans;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc int i, ix;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc uint32_t nchan;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc chans = (HAL_CHANNEL *)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc kmem_zalloc(IEEE80211_CHAN_MAX * sizeof (HAL_CHANNEL), KM_SLEEP);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (!ath_hal_init_channels(ah, chans, IEEE80211_CHAN_MAX, &nchan,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc NULL, 0, NULL, cc, HAL_MODE_ALL, outdoor, xchanmode)) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_AUX, "ath: ath_getchannels(): "
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc "unable to get channel list\n"));
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc kmem_free(chans, IEEE80211_CHAN_MAX * sizeof (HAL_CHANNEL));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (EINVAL);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Convert HAL channels to ieee80211 ones and insert
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * them in the table according to their channel number.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc for (i = 0; i < nchan; i++) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc HAL_CHANNEL *c = &chans[i];
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint16_t flags;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ix = ath_hal_mhz2ieee(ah, c->channel, c->channelFlags);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (ix > IEEE80211_CHAN_MAX) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_AUX, "ath: ath_getchannels(): "
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc "bad hal channel %d (%u/%x) ignored\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ix, c->channel, c->channelFlags));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc continue;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* NB: flags are known to be compatible */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ix < 0) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * can't handle frequency <2400MHz (negative
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * channels) right now
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_DEBUG((ATH_DBG_AUX, "ath:ath_getchannels(): "
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc "hal channel %d (%u/%x) "
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc "cannot be handled, ignored\n",
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ix, c->channel, c->channelFlags));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc continue;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Calculate net80211 flags; most are compatible
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * but some need massaging. Note the static turbo
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * conversion can be removed once net80211 is updated
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * to understand static vs. dynamic turbo.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc flags = c->channelFlags & CHANNEL_COMPAT;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (c->channelFlags & CHANNEL_STURBO)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc flags |= IEEE80211_CHAN_TURBO;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_sup_channels[ix].ich_freq == 0) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_sup_channels[ix].ich_freq = c->channel;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_sup_channels[ix].ich_flags = flags;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc } else {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* channels overlap; e.g. 11g and 11b */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_sup_channels[ix].ich_flags |= flags;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if ((c->channelFlags & CHANNEL_G) == CHANNEL_G)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_have11g = 1;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc kmem_free(chans, IEEE80211_CHAN_MAX * sizeof (HAL_CHANNEL));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_drainq(ath_t *asc, struct ath_txq *txq)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_buf *bf;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * This assumes output has been stopped.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc for (;;) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_enter(&txq->axq_lock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bf = list_head(&txq->axq_list);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (bf == NULL) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc txq->axq_link = NULL;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_exit(&txq->axq_lock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc break;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc list_remove(&txq->axq_list, bf);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_exit(&txq->axq_lock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bf->bf_in = NULL;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_enter(&asc->asc_txbuflock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc list_insert_tail(&asc->asc_txbuf_list, bf);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_exit(&asc->asc_txbuflock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Drain the transmit queues and reclaim resources.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcvoid
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_draintxq(ath_t *asc)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_hal *ah = asc->asc_ah;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_txq *txq;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc int i;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (!asc->asc_invalid) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (ATH_TXQ_SETUP(asc, i)) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc txq = &asc->asc_txq[i];
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc (void) ATH_HAL_STOPTXDMA(ah, txq->axq_qnum);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (ATH_TXQ_SETUP(asc, i)) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_drainq(asc, &asc->asc_txq[i]);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/* Enable the receive h/w following a reset */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcint
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_startrecv(ath_t *asc)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_buf *bf;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_rxlink = NULL;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bf = list_head(&asc->asc_rxbuf_list);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc while (bf != NULL) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_setup_desc(asc, bf);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bf = list_next(&asc->asc_rxbuf_list, bf);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bf = list_head(&asc->asc_rxbuf_list);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_PUTRXBUF(asc->asc_ah, bf->bf_daddr);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_RXENA(asc->asc_ah); /* enable recv descriptors */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_mode_init(asc); /* set filters, etc. */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_STARTPCURECV(asc->asc_ah); /* re-enable PCU/DMA engine */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Update internal state after a channel change.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcvoid
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_chan_change(ath_t *asc, struct ieee80211_channel *chan)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211com *ic = &asc->asc_isc;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc enum ieee80211_phymode mode;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Change channels and update the h/w rate map
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * if we're switching; e.g. 11a to 11b/g.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mode = ieee80211_chan2mode(ic, chan);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (mode != asc->asc_curmode)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_setcurmode(asc, mode);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Set/change channels. If the channel is really being changed,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * it's done by resetting the chip. To accomplish this we must
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * first cleanup any pending DMA.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcint
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_chan_set(ath_t *asc, struct ieee80211_channel *chan)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_hal *ah = asc->asc_ah;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211com_t *ic = &asc->asc_isc;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (chan != ic->ic_ibss_chan) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc HAL_STATUS status;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc HAL_CHANNEL hchan;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * To switch channels clear any pending DMA operations;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * wait long enough for the RX fifo to drain, reset the
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * hardware at the new frequency, and then re-enable
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * the relevant bits of the h/w.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_INTRSET(ah, 0); /* disable interrupts */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_draintxq(asc); /* clear pending tx frames */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_stoprecv(asc); /* turn off frame recv */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Convert to a HAL channel description with
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * the flags constrained to reflect the current
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * operating mode.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc hchan.channel = chan->ich_freq;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc hchan.channelFlags = ath_chan2flags(ic, chan);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (!ATH_HAL_RESET(ah, (HAL_OPMODE)ic->ic_opmode,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc &hchan, AH_TRUE, &status)) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_AUX, "ath: ath_chan_set():"
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc "unable to reset channel %u (%uMhz)\n"
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc "flags 0x%x: '%s' (HAL status %u)\n",
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc ieee80211_chan2ieee(ic, chan), hchan.channel,
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc hchan.channelFlags,
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc ath_get_hal_status_desc(status), status));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (EIO);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_curchan = hchan;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Re-enable rx framework.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (ath_startrecv(asc) != 0) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_problem("ath: ath_chan_set(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "restarting receiving logic failed\n");
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (EIO);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Change channels and update the h/w rate map
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * if we're switching; e.g. 11a to 11b/g.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_ibss_chan = chan;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_chan_change(asc, chan);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Re-enable interrupts.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_INTRSET(ah, asc->asc_imask);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Configure the beacon and sleep timers.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc *
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * When operating as an AP this resets the TSF and sets
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * up the hardware to notify us when we need to issue beacons.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc *
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * When operating in station mode this sets up the beacon
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * timers according to the timestamp of the last received
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * beacon and the current TSF, configures PCF and DTIM
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * handling, programs the sleep registers so the hardware
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * will wakeup in time to receive beacons, and configures
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * the beacon miss handling so we'll receive a BMISS
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * interrupt when we stop seeing beacons from the AP
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * we've associated with.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcvoid
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_beacon_config(ath_t *asc)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_hal *ah = asc->asc_ah;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211com_t *ic = (ieee80211com_t *)asc;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_node *in = ic->ic_bss;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc uint32_t nexttbtt;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China /* extract tstamp from last beacon and convert to TU */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc nexttbtt = (ATH_LE_READ_4(in->in_tstamp.data + 4) << 22) |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (ATH_LE_READ_4(in->in_tstamp.data) >> 10);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc nexttbtt += in->in_intval;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_opmode != IEEE80211_M_HOSTAP) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc HAL_BEACON_STATE bs;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* NB: no PCF support right now */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bzero(&bs, sizeof (bs));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bs.bs_intval = in->in_intval;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bs.bs_nexttbtt = nexttbtt;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bs.bs_dtimperiod = bs.bs_intval;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bs.bs_nextdtim = nexttbtt;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Setup the number of consecutive beacons to miss
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * before taking a BMISS interrupt.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Note that we clamp the result to at most 10 beacons.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bs.bs_bmissthreshold = ic->ic_bmissthreshold;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (bs.bs_bmissthreshold > 10)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bs.bs_bmissthreshold = 10;
22eb7cb54d8a6bcf6fe2674cb4b1f0cf2d85cfb6gd else if (bs.bs_bmissthreshold < 1)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bs.bs_bmissthreshold = 1;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Calculate sleep duration. The configuration is
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * given in ms. We insure a multiple of the beacon
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * period is used. Also, if the sleep duration is
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * greater than the DTIM period then it makes senses
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * to make it a multiple of that.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bs.bs_sleepduration =
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc roundup((100 * 1000) / 1024, bs.bs_intval);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (bs.bs_sleepduration > bs.bs_dtimperiod)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bs.bs_sleepduration =
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc roundup(bs.bs_sleepduration, bs.bs_dtimperiod);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_AUX, "ath: ath_beacon_config(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "intval %u nexttbtt %u dtim %u"
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc " nextdtim %u bmiss %u sleep %u\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bs.bs_intval,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bs.bs_nexttbtt,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bs.bs_dtimperiod,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bs.bs_nextdtim,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bs.bs_bmissthreshold,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bs.bs_sleepduration));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_INTRSET(ah, 0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Reset our tsf so the hardware will update the
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * tsf register to reflect timestamps found in
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * received beacons.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_RESETTSF(ah);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_BEACONTIMERS(ah, &bs);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_imask |= HAL_INT_BMISS;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_INTRSET(ah, asc->asc_imask);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc } else {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_INTRSET(ah, 0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_BEACONINIT(ah, nexttbtt, in->in_intval);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_imask |= HAL_INT_SWBA; /* beacon prepare */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_INTRSET(ah, asc->asc_imask);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China/*
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * Allocate tx/rx key slots for TKIP. We allocate one slot for
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * each key. MIC is right after the decrypt/encrypt key.
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China */
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing Chinastatic uint16_t
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing Chinakey_alloc_pair(ath_t *asc, ieee80211_keyix *txkeyix,
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ieee80211_keyix *rxkeyix)
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China{
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China uint16_t i, keyix;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ASSERT(!asc->asc_splitmic);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China for (i = 0; i < ATH_N(asc->asc_keymap)/4; i++) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China uint8_t b = asc->asc_keymap[i];
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (b == 0xff)
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China continue;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China for (keyix = i * NBBY; keyix < (i + 1) * NBBY;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China keyix++, b >>= 1) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if ((b & 1) || isset(asc->asc_keymap, keyix+64)) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China /* full pair unavailable */
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China continue;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China }
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China setbit(asc->asc_keymap, keyix);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China setbit(asc->asc_keymap, keyix+64);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ATH_DEBUG((ATH_DBG_AUX,
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China "key_alloc_pair: key pair %u,%u\n",
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China keyix, keyix+64));
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China *txkeyix = *rxkeyix = keyix;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China return (1);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China }
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China }
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ATH_DEBUG((ATH_DBG_AUX, "key_alloc_pair:"
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China " out of pair space\n"));
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China return (0);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
a399b7655a1d835aa8606c2b29e4e777baac8635zf/*
a399b7655a1d835aa8606c2b29e4e777baac8635zf * Allocate tx/rx key slots for TKIP. We allocate two slots for
a399b7655a1d835aa8606c2b29e4e777baac8635zf * each key, one for decrypt/encrypt and the other for the MIC.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
a399b7655a1d835aa8606c2b29e4e777baac8635zfstatic int
a399b7655a1d835aa8606c2b29e4e777baac8635zfkey_alloc_2pair(ath_t *asc, ieee80211_keyix *txkeyix, ieee80211_keyix *rxkeyix)
a399b7655a1d835aa8606c2b29e4e777baac8635zf{
a399b7655a1d835aa8606c2b29e4e777baac8635zf uint16_t i, keyix;
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf ASSERT(asc->asc_splitmic);
a399b7655a1d835aa8606c2b29e4e777baac8635zf for (i = 0; i < ATH_N(asc->asc_keymap)/4; i++) {
a399b7655a1d835aa8606c2b29e4e777baac8635zf uint8_t b = asc->asc_keymap[i];
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (b != 0xff) {
a399b7655a1d835aa8606c2b29e4e777baac8635zf /*
a399b7655a1d835aa8606c2b29e4e777baac8635zf * One or more slots in this byte are free.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
a399b7655a1d835aa8606c2b29e4e777baac8635zf keyix = i*NBBY;
a399b7655a1d835aa8606c2b29e4e777baac8635zf while (b & 1) {
a399b7655a1d835aa8606c2b29e4e777baac8635zf again:
a399b7655a1d835aa8606c2b29e4e777baac8635zf keyix++;
a399b7655a1d835aa8606c2b29e4e777baac8635zf b >>= 1;
a399b7655a1d835aa8606c2b29e4e777baac8635zf }
a399b7655a1d835aa8606c2b29e4e777baac8635zf /* XXX IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV */
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (isset(asc->asc_keymap, keyix+32) ||
a399b7655a1d835aa8606c2b29e4e777baac8635zf isset(asc->asc_keymap, keyix+64) ||
a399b7655a1d835aa8606c2b29e4e777baac8635zf isset(asc->asc_keymap, keyix+32+64)) {
a399b7655a1d835aa8606c2b29e4e777baac8635zf /* full pair unavailable */
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (keyix == (i+1)*NBBY) {
a399b7655a1d835aa8606c2b29e4e777baac8635zf /* no slots were appropriate, advance */
a399b7655a1d835aa8606c2b29e4e777baac8635zf continue;
a399b7655a1d835aa8606c2b29e4e777baac8635zf }
a399b7655a1d835aa8606c2b29e4e777baac8635zf goto again;
a399b7655a1d835aa8606c2b29e4e777baac8635zf }
a399b7655a1d835aa8606c2b29e4e777baac8635zf setbit(asc->asc_keymap, keyix);
a399b7655a1d835aa8606c2b29e4e777baac8635zf setbit(asc->asc_keymap, keyix+64);
a399b7655a1d835aa8606c2b29e4e777baac8635zf setbit(asc->asc_keymap, keyix+32);
a399b7655a1d835aa8606c2b29e4e777baac8635zf setbit(asc->asc_keymap, keyix+32+64);
a399b7655a1d835aa8606c2b29e4e777baac8635zf ATH_DEBUG((ATH_DBG_AUX,
a399b7655a1d835aa8606c2b29e4e777baac8635zf "key_alloc_2pair: key pair %u,%u %u,%u\n",
a399b7655a1d835aa8606c2b29e4e777baac8635zf keyix, keyix+64,
a399b7655a1d835aa8606c2b29e4e777baac8635zf keyix+32, keyix+32+64));
a399b7655a1d835aa8606c2b29e4e777baac8635zf *txkeyix = *rxkeyix = keyix;
a399b7655a1d835aa8606c2b29e4e777baac8635zf return (1);
a399b7655a1d835aa8606c2b29e4e777baac8635zf }
a399b7655a1d835aa8606c2b29e4e777baac8635zf }
a399b7655a1d835aa8606c2b29e4e777baac8635zf ATH_DEBUG((ATH_DBG_AUX, "key_alloc_2pair:"
a399b7655a1d835aa8606c2b29e4e777baac8635zf " out of pair space\n"));
a399b7655a1d835aa8606c2b29e4e777baac8635zf return (0);
a399b7655a1d835aa8606c2b29e4e777baac8635zf}
a399b7655a1d835aa8606c2b29e4e777baac8635zf/*
a399b7655a1d835aa8606c2b29e4e777baac8635zf * Allocate a single key cache slot.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
a399b7655a1d835aa8606c2b29e4e777baac8635zfstatic int
a399b7655a1d835aa8606c2b29e4e777baac8635zfkey_alloc_single(ath_t *asc, ieee80211_keyix *txkeyix, ieee80211_keyix *rxkeyix)
a399b7655a1d835aa8606c2b29e4e777baac8635zf{
a399b7655a1d835aa8606c2b29e4e777baac8635zf uint16_t i, keyix;
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf /* try i,i+32,i+64,i+32+64 to minimize key pair conflicts */
a399b7655a1d835aa8606c2b29e4e777baac8635zf for (i = 0; i < ATH_N(asc->asc_keymap); i++) {
a399b7655a1d835aa8606c2b29e4e777baac8635zf uint8_t b = asc->asc_keymap[i];
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (b != 0xff) {
a399b7655a1d835aa8606c2b29e4e777baac8635zf /*
a399b7655a1d835aa8606c2b29e4e777baac8635zf * One or more slots are free.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
a399b7655a1d835aa8606c2b29e4e777baac8635zf keyix = i*NBBY;
a399b7655a1d835aa8606c2b29e4e777baac8635zf while (b & 1)
a399b7655a1d835aa8606c2b29e4e777baac8635zf keyix++, b >>= 1;
a399b7655a1d835aa8606c2b29e4e777baac8635zf setbit(asc->asc_keymap, keyix);
a399b7655a1d835aa8606c2b29e4e777baac8635zf ATH_DEBUG((ATH_DBG_AUX, "key_alloc_single:"
a399b7655a1d835aa8606c2b29e4e777baac8635zf " key %u\n", keyix));
a399b7655a1d835aa8606c2b29e4e777baac8635zf *txkeyix = *rxkeyix = keyix;
a399b7655a1d835aa8606c2b29e4e777baac8635zf return (1);
a399b7655a1d835aa8606c2b29e4e777baac8635zf }
a399b7655a1d835aa8606c2b29e4e777baac8635zf }
a399b7655a1d835aa8606c2b29e4e777baac8635zf return (0);
a399b7655a1d835aa8606c2b29e4e777baac8635zf}
a399b7655a1d835aa8606c2b29e4e777baac8635zf
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Allocate one or more key cache slots for a unicast key. The
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * key itself is needed only to identify the cipher. For hardware
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * TKIP with split cipher+MIC keys we allocate two key cache slot
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * pairs so that we can setup separate TX and RX MIC keys. Note
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * that the MIC key for a TKIP key at slot i is assumed by the
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * hardware to be at slot i+64. This limits TKIP keys to the first
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * 64 entries.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/* ARGSUSED */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcint
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_key_alloc(ieee80211com_t *ic, const struct ieee80211_key *k,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
a399b7655a1d835aa8606c2b29e4e777baac8635zf ath_t *asc = (ath_t *)ic;
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf /*
a399b7655a1d835aa8606c2b29e4e777baac8635zf * We allocate two pair for TKIP when using the h/w to do
a399b7655a1d835aa8606c2b29e4e777baac8635zf * the MIC. For everything else, including software crypto,
a399b7655a1d835aa8606c2b29e4e777baac8635zf * we allocate a single entry. Note that s/w crypto requires
a399b7655a1d835aa8606c2b29e4e777baac8635zf * a pass-through slot on the 5211 and 5212. The 5210 does
a399b7655a1d835aa8606c2b29e4e777baac8635zf * not support pass-through cache entries and we map all
a399b7655a1d835aa8606c2b29e4e777baac8635zf * those requests to slot 0.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (k->wk_flags & IEEE80211_KEY_SWCRYPT) {
a399b7655a1d835aa8606c2b29e4e777baac8635zf return (key_alloc_single(asc, keyix, rxkeyix));
a399b7655a1d835aa8606c2b29e4e777baac8635zf } else if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP &&
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China (k->wk_flags & IEEE80211_KEY_SWMIC) == 0) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (asc->asc_splitmic)
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China return (key_alloc_2pair(asc, keyix, rxkeyix));
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China else
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China return (key_alloc_pair(asc, keyix, rxkeyix));
a399b7655a1d835aa8606c2b29e4e777baac8635zf } else {
a399b7655a1d835aa8606c2b29e4e777baac8635zf return (key_alloc_single(asc, keyix, rxkeyix));
a399b7655a1d835aa8606c2b29e4e777baac8635zf }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
a399b7655a1d835aa8606c2b29e4e777baac8635zf/*
a399b7655a1d835aa8606c2b29e4e777baac8635zf * Delete an entry in the key cache allocated by ath_key_alloc.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcint
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_key_delete(ieee80211com_t *ic, const struct ieee80211_key *k)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
a399b7655a1d835aa8606c2b29e4e777baac8635zf ath_t *asc = (ath_t *)ic;
a399b7655a1d835aa8606c2b29e4e777baac8635zf struct ath_hal *ah = asc->asc_ah;
a399b7655a1d835aa8606c2b29e4e777baac8635zf const struct ieee80211_cipher *cip = k->wk_cipher;
a399b7655a1d835aa8606c2b29e4e777baac8635zf ieee80211_keyix keyix = k->wk_keyix;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
a399b7655a1d835aa8606c2b29e4e777baac8635zf ATH_DEBUG((ATH_DBG_AUX, "ath_key_delete:"
a399b7655a1d835aa8606c2b29e4e777baac8635zf " delete key %u ic_cipher=0x%x\n", keyix, cip->ic_cipher));
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf ATH_HAL_KEYRESET(ah, keyix);
a399b7655a1d835aa8606c2b29e4e777baac8635zf /*
a399b7655a1d835aa8606c2b29e4e777baac8635zf * Handle split tx/rx keying required for TKIP with h/w MIC.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (cip->ic_cipher == IEEE80211_CIPHER_TKIP &&
a399b7655a1d835aa8606c2b29e4e777baac8635zf (k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && asc->asc_splitmic)
a399b7655a1d835aa8606c2b29e4e777baac8635zf ATH_HAL_KEYRESET(ah, keyix+32); /* RX key */
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (keyix >= IEEE80211_WEP_NKID) {
a399b7655a1d835aa8606c2b29e4e777baac8635zf /*
a399b7655a1d835aa8606c2b29e4e777baac8635zf * Don't touch keymap entries for global keys so
a399b7655a1d835aa8606c2b29e4e777baac8635zf * they are never considered for dynamic allocation.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
a399b7655a1d835aa8606c2b29e4e777baac8635zf clrbit(asc->asc_keymap, keyix);
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (cip->ic_cipher == IEEE80211_CIPHER_TKIP &&
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China (k->wk_flags & IEEE80211_KEY_SWMIC) == 0) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China /*
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * If splitmic is true +64 is TX key MIC,
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * else +64 is RX key + RX key MIC.
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China */
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China clrbit(asc->asc_keymap, keyix+64);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (asc->asc_splitmic) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China /* Rx key */
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China clrbit(asc->asc_keymap, keyix+32);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China /* RX key MIC */
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China clrbit(asc->asc_keymap, keyix+32+64);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China }
a399b7655a1d835aa8606c2b29e4e777baac8635zf }
a399b7655a1d835aa8606c2b29e4e777baac8635zf }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (1);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
a399b7655a1d835aa8606c2b29e4e777baac8635zfstatic void
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing Chinaath_keyprint(ath_t *asc, const char *tag, uint_t ix,
a399b7655a1d835aa8606c2b29e4e777baac8635zf const HAL_KEYVAL *hk, const uint8_t mac[IEEE80211_ADDR_LEN])
a399b7655a1d835aa8606c2b29e4e777baac8635zf{
a399b7655a1d835aa8606c2b29e4e777baac8635zf static const char *ciphers[] = {
a399b7655a1d835aa8606c2b29e4e777baac8635zf "WEP",
a399b7655a1d835aa8606c2b29e4e777baac8635zf "AES-OCB",
a399b7655a1d835aa8606c2b29e4e777baac8635zf "AES-CCM",
a399b7655a1d835aa8606c2b29e4e777baac8635zf "CKIP",
a399b7655a1d835aa8606c2b29e4e777baac8635zf "TKIP",
a399b7655a1d835aa8606c2b29e4e777baac8635zf "CLR",
a399b7655a1d835aa8606c2b29e4e777baac8635zf };
a399b7655a1d835aa8606c2b29e4e777baac8635zf int i, n;
a399b7655a1d835aa8606c2b29e4e777baac8635zf char buf[MAX_IEEE80211STR], buft[32];
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf (void) snprintf(buf, sizeof (buf), "%s: [%02u] %s ",
a399b7655a1d835aa8606c2b29e4e777baac8635zf tag, ix, ciphers[hk->kv_type]);
a399b7655a1d835aa8606c2b29e4e777baac8635zf for (i = 0, n = hk->kv_len; i < n; i++) {
a399b7655a1d835aa8606c2b29e4e777baac8635zf (void) snprintf(buft, sizeof (buft), "%02x", hk->kv_val[i]);
a399b7655a1d835aa8606c2b29e4e777baac8635zf (void) strlcat(buf, buft, sizeof (buf));
a399b7655a1d835aa8606c2b29e4e777baac8635zf }
a399b7655a1d835aa8606c2b29e4e777baac8635zf (void) snprintf(buft, sizeof (buft), " mac %s",
a399b7655a1d835aa8606c2b29e4e777baac8635zf ieee80211_macaddr_sprintf(mac));
a399b7655a1d835aa8606c2b29e4e777baac8635zf (void) strlcat(buf, buft, sizeof (buf));
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (hk->kv_type == HAL_CIPHER_TKIP) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China (void) snprintf(buft, sizeof (buft), " %s ",
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China asc->asc_splitmic ? "mic" : "rxmic");
a399b7655a1d835aa8606c2b29e4e777baac8635zf (void) strlcat(buf, buft, sizeof (buf));
a399b7655a1d835aa8606c2b29e4e777baac8635zf for (i = 0; i < sizeof (hk->kv_mic); i++) {
a399b7655a1d835aa8606c2b29e4e777baac8635zf (void) snprintf(buft, sizeof (buft), "%02x",
a399b7655a1d835aa8606c2b29e4e777baac8635zf hk->kv_mic[i]);
a399b7655a1d835aa8606c2b29e4e777baac8635zf (void) strlcat(buf, buft, sizeof (buf));
a399b7655a1d835aa8606c2b29e4e777baac8635zf }
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (!asc->asc_splitmic) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China (void) snprintf(buft, sizeof (buft), " txmic ");
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China (void) strlcat(buf, buft, sizeof (buf));
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China for (i = 0; i < sizeof (hk->kv_txmic); i++) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China (void) snprintf(buft, sizeof (buft), "%02x",
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China hk->kv_txmic[i]);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China (void) strlcat(buf, buft, sizeof (buf));
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China }
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China }
a399b7655a1d835aa8606c2b29e4e777baac8635zf }
a399b7655a1d835aa8606c2b29e4e777baac8635zf ATH_DEBUG((ATH_DBG_AUX, "%s", buf));
a399b7655a1d835aa8606c2b29e4e777baac8635zf}
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf/*
a399b7655a1d835aa8606c2b29e4e777baac8635zf * Set a TKIP key into the hardware. This handles the
a399b7655a1d835aa8606c2b29e4e777baac8635zf * potential distribution of key state to multiple key
a399b7655a1d835aa8606c2b29e4e777baac8635zf * cache slots for TKIP.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
a399b7655a1d835aa8606c2b29e4e777baac8635zfstatic int
a399b7655a1d835aa8606c2b29e4e777baac8635zfath_keyset_tkip(ath_t *asc, const struct ieee80211_key *k,
a399b7655a1d835aa8606c2b29e4e777baac8635zf HAL_KEYVAL *hk, const uint8_t mac[IEEE80211_ADDR_LEN])
a399b7655a1d835aa8606c2b29e4e777baac8635zf{
a399b7655a1d835aa8606c2b29e4e777baac8635zf#define IEEE80211_KEY_XR (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV)
a399b7655a1d835aa8606c2b29e4e777baac8635zf static const uint8_t zerobssid[IEEE80211_ADDR_LEN] = {0, 0, 0, 0, 0, 0};
a399b7655a1d835aa8606c2b29e4e777baac8635zf struct ath_hal *ah = asc->asc_ah;
a399b7655a1d835aa8606c2b29e4e777baac8635zf
a399b7655a1d835aa8606c2b29e4e777baac8635zf ASSERT(k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP);
a399b7655a1d835aa8606c2b29e4e777baac8635zf if ((k->wk_flags & IEEE80211_KEY_XR) == IEEE80211_KEY_XR) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (asc->asc_splitmic) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China /*
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * TX key goes at first index, RX key at +32.
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * The hal handles the MIC keys at index+64.
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China */
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China (void) memcpy(hk->kv_mic, k->wk_txmic,
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China sizeof (hk->kv_mic));
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ath_keyprint(asc, "ath_keyset_tkip:", k->wk_keyix, hk,
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China zerobssid);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (!ATH_HAL_KEYSET(ah, k->wk_keyix, hk, zerobssid))
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China return (0);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China (void) memcpy(hk->kv_mic, k->wk_rxmic,
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China sizeof (hk->kv_mic));
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ath_keyprint(asc, "ath_keyset_tkip:", k->wk_keyix+32,
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China hk, mac);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China return (ATH_HAL_KEYSET(ah, k->wk_keyix+32, hk, mac));
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China } else {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China /*
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * Room for both TX+RX MIC keys in one key cache
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * slot, just set key at the first index; the hal
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * will handle the reset.
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China */
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China (void) memcpy(hk->kv_mic, k->wk_rxmic,
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China sizeof (hk->kv_mic));
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China (void) memcpy(hk->kv_txmic, k->wk_txmic,
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China sizeof (hk->kv_txmic));
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ath_keyprint(asc, "ath_keyset_tkip", k->wk_keyix, hk,
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China mac);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China return (ATH_HAL_KEYSET(ah, k->wk_keyix, hk, mac));
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China }
a399b7655a1d835aa8606c2b29e4e777baac8635zf } else if (k->wk_flags & IEEE80211_KEY_XR) {
a399b7655a1d835aa8606c2b29e4e777baac8635zf /*
a399b7655a1d835aa8606c2b29e4e777baac8635zf * TX/RX key goes at first index.
a399b7655a1d835aa8606c2b29e4e777baac8635zf * The hal handles the MIC keys are index+64.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
a399b7655a1d835aa8606c2b29e4e777baac8635zf (void) memcpy(hk->kv_mic, k->wk_flags & IEEE80211_KEY_XMIT ?
a399b7655a1d835aa8606c2b29e4e777baac8635zf k->wk_txmic : k->wk_rxmic, sizeof (hk->kv_mic));
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ath_keyprint(asc, "ath_keyset_tkip:", k->wk_keyix, hk,
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China zerobssid);
a399b7655a1d835aa8606c2b29e4e777baac8635zf return (ATH_HAL_KEYSET(ah, k->wk_keyix, hk, zerobssid));
a399b7655a1d835aa8606c2b29e4e777baac8635zf }
a399b7655a1d835aa8606c2b29e4e777baac8635zf return (0);
a399b7655a1d835aa8606c2b29e4e777baac8635zf#undef IEEE80211_KEY_XR
a399b7655a1d835aa8606c2b29e4e777baac8635zf}
a399b7655a1d835aa8606c2b29e4e777baac8635zf
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Set the key cache contents for the specified key. Key cache
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * slot(s) must already have been allocated by ath_key_alloc.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcint
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_key_set(ieee80211com_t *ic, const struct ieee80211_key *k,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc const uint8_t mac[IEEE80211_ADDR_LEN])
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc static const uint8_t ciphermap[] = {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc HAL_CIPHER_WEP, /* IEEE80211_CIPHER_WEP */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc HAL_CIPHER_TKIP, /* IEEE80211_CIPHER_TKIP */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc HAL_CIPHER_AES_OCB, /* IEEE80211_CIPHER_AES_OCB */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc HAL_CIPHER_AES_CCM, /* IEEE80211_CIPHER_AES_CCM */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc HAL_CIPHER_CKIP, /* IEEE80211_CIPHER_CKIP */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc HAL_CIPHER_CLR, /* IEEE80211_CIPHER_NONE */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc };
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_t *asc = (ath_t *)ic;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_hal *ah = asc->asc_ah;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc const struct ieee80211_cipher *cip = k->wk_cipher;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc HAL_KEYVAL hk;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bzero(&hk, sizeof (hk));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Software crypto uses a "clear key" so non-crypto
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * state kept in the key cache are maintainedd so that
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * rx frames have an entry to match.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) == 0) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ASSERT(cip->ic_cipher < ATH_N(ciphermap));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc hk.kv_type = ciphermap[cip->ic_cipher];
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc hk.kv_len = k->wk_keylen;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bcopy(k->wk_key, hk.kv_val, k->wk_keylen);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc } else {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc hk.kv_type = HAL_CIPHER_CLR;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (hk.kv_type == HAL_CIPHER_TKIP &&
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China (k->wk_flags & IEEE80211_KEY_SWMIC) == 0) {
a399b7655a1d835aa8606c2b29e4e777baac8635zf return (ath_keyset_tkip(asc, k, &hk, mac));
a399b7655a1d835aa8606c2b29e4e777baac8635zf } else {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ath_keyprint(asc, "ath_keyset:", k->wk_keyix, &hk, mac);
a399b7655a1d835aa8606c2b29e4e777baac8635zf return (ATH_HAL_KEYSET(ah, k->wk_keyix, &hk, mac));
a399b7655a1d835aa8606c2b29e4e777baac8635zf }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Enable/Disable short slot timing
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcvoid
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_set_shortslot(ieee80211com_t *ic, int onoff)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ath_hal *ah = ((ath_t *)ic)->asc_ah;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (onoff)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_HAL_SETSLOTTIME(ah, HAL_SLOT_TIME_9);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc else
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_HAL_SETSLOTTIME(ah, HAL_SLOT_TIME_20);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcint
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_reset(ieee80211com_t *ic)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_t *asc = (ath_t *)ic;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_hal *ah = asc->asc_ah;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_channel *ch;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc HAL_STATUS status;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Convert to a HAL channel description with the flags
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * constrained to reflect the current operating mode.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ch = ic->ic_curchan;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_curchan.channel = ch->ich_freq;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_curchan.channelFlags = ath_chan2flags(ic, ch);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_INTRSET(ah, 0); /* disable interrupts */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_draintxq(asc); /* stop xmit side */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ATH_IS_RUNNING(asc)) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_stoprecv(asc); /* stop recv side */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* indicate channel change so we do a full reset */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc if (!ATH_HAL_RESET(ah, (HAL_OPMODE)ic->ic_opmode,
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc &asc->asc_curchan, AH_TRUE, &status)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_problem("ath: ath_reset(): "
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc "resetting hardware failed, '%s' (HAL status %u)\n",
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc ath_get_hal_status_desc(status), status);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_chan_change(asc, ch);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ATH_IS_RUNNING(asc)) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (ath_startrecv(asc) != 0) /* restart recv */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_problem("ath: ath_reset(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "starting receiving logic failed\n");
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_state == IEEE80211_S_RUN) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_beacon_config(asc); /* restart beacons */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_INTRSET(ah, asc->asc_imask);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}