1dd1de374Slin wang - Sun Microsystems - Beijing China /* 2c0c93480Slin wang - Sun Microsystems - Beijing China * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 3dd1de374Slin wang - Sun Microsystems - Beijing China * Use is subject to license terms. 4dd1de374Slin wang - Sun Microsystems - Beijing China */ 5dd1de374Slin wang - Sun Microsystems - Beijing China 6dd1de374Slin wang - Sun Microsystems - Beijing China /* 7dd1de374Slin wang - Sun Microsystems - Beijing China * Copyright (c) 2008 Atheros Communications Inc. 8dd1de374Slin wang - Sun Microsystems - Beijing China * 9dd1de374Slin wang - Sun Microsystems - Beijing China * Permission to use, copy, modify, and/or distribute this software for any 10dd1de374Slin wang - Sun Microsystems - Beijing China * purpose with or without fee is hereby granted, provided that the above 11dd1de374Slin wang - Sun Microsystems - Beijing China * copyright notice and this permission notice appear in all copies. 12dd1de374Slin wang - Sun Microsystems - Beijing China * 13dd1de374Slin wang - Sun Microsystems - Beijing China * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14dd1de374Slin wang - Sun Microsystems - Beijing China * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15dd1de374Slin wang - Sun Microsystems - Beijing China * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16dd1de374Slin wang - Sun Microsystems - Beijing China * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17dd1de374Slin wang - Sun Microsystems - Beijing China * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18dd1de374Slin wang - Sun Microsystems - Beijing China * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19dd1de374Slin wang - Sun Microsystems - Beijing China * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20dd1de374Slin wang - Sun Microsystems - Beijing China */ 21dd1de374Slin wang - Sun Microsystems - Beijing China 22*de710d24SJosef 'Jeff' Sipek #include <sys/sysmacros.h> 23dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/param.h> 24dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/types.h> 25dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/signal.h> 26dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/stream.h> 27dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/termio.h> 28dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/errno.h> 29dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/file.h> 30dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/cmn_err.h> 31dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/stropts.h> 32dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/strsubr.h> 33dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/strtty.h> 34dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/kbio.h> 35dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/cred.h> 36dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/stat.h> 37dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/consdev.h> 38dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/kmem.h> 39dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/modctl.h> 40dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/ddi.h> 41dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/sunddi.h> 42dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/pci.h> 43dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/errno.h> 44dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/mac_provider.h> 45dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/dlpi.h> 46dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/ethernet.h> 47dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/list.h> 48dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/byteorder.h> 49dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/strsun.h> 50dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/policy.h> 51dd1de374Slin wang - Sun Microsystems - Beijing China #include <inet/common.h> 52dd1de374Slin wang - Sun Microsystems - Beijing China #include <inet/nd.h> 53dd1de374Slin wang - Sun Microsystems - Beijing China #include <inet/mi.h> 54dd1de374Slin wang - Sun Microsystems - Beijing China #include <inet/wifi_ioctl.h> 55dd1de374Slin wang - Sun Microsystems - Beijing China #include <sys/mac_wifi.h> 56c0c93480Slin wang - Sun Microsystems - Beijing China #include <sys/net80211.h> 57c0c93480Slin wang - Sun Microsystems - Beijing China #include <sys/net80211_proto.h> 58c0c93480Slin wang - Sun Microsystems - Beijing China #include <sys/net80211_ht.h> 59c0c93480Slin wang - Sun Microsystems - Beijing China 60dd1de374Slin wang - Sun Microsystems - Beijing China 61dd1de374Slin wang - Sun Microsystems - Beijing China #include "arn_ath9k.h" 62dd1de374Slin wang - Sun Microsystems - Beijing China #include "arn_core.h" 63dd1de374Slin wang - Sun Microsystems - Beijing China #include "arn_reg.h" 64dd1de374Slin wang - Sun Microsystems - Beijing China #include "arn_hw.h" 65dd1de374Slin wang - Sun Microsystems - Beijing China 663ae945c3Slin wang - Sun Microsystems - Beijing China #define ARN_MAX_RSSI 45 /* max rssi */ 67dd1de374Slin wang - Sun Microsystems - Beijing China 68dd1de374Slin wang - Sun Microsystems - Beijing China /* 69c0c93480Slin wang - Sun Microsystems - Beijing China * Default 11n reates supported by this station. 70c0c93480Slin wang - Sun Microsystems - Beijing China */ 71c0c93480Slin wang - Sun Microsystems - Beijing China extern struct ieee80211_htrateset ieee80211_rateset_11n; 72c0c93480Slin wang - Sun Microsystems - Beijing China 73c0c93480Slin wang - Sun Microsystems - Beijing China /* 74dd1de374Slin wang - Sun Microsystems - Beijing China * PIO access attributes for registers 75dd1de374Slin wang - Sun Microsystems - Beijing China */ 76dd1de374Slin wang - Sun Microsystems - Beijing China static ddi_device_acc_attr_t arn_reg_accattr = { 77dd1de374Slin wang - Sun Microsystems - Beijing China DDI_DEVICE_ATTR_V0, 78dd1de374Slin wang - Sun Microsystems - Beijing China DDI_STRUCTURE_LE_ACC, 79c0c93480Slin wang - Sun Microsystems - Beijing China DDI_STRICTORDER_ACC, 80c0c93480Slin wang - Sun Microsystems - Beijing China DDI_DEFAULT_ACC 81dd1de374Slin wang - Sun Microsystems - Beijing China }; 82dd1de374Slin wang - Sun Microsystems - Beijing China 83dd1de374Slin wang - Sun Microsystems - Beijing China /* 84dd1de374Slin wang - Sun Microsystems - Beijing China * DMA access attributes for descriptors: NOT to be byte swapped. 85dd1de374Slin wang - Sun Microsystems - Beijing China */ 86dd1de374Slin wang - Sun Microsystems - Beijing China static ddi_device_acc_attr_t arn_desc_accattr = { 87dd1de374Slin wang - Sun Microsystems - Beijing China DDI_DEVICE_ATTR_V0, 88dd1de374Slin wang - Sun Microsystems - Beijing China DDI_STRUCTURE_LE_ACC, 89c0c93480Slin wang - Sun Microsystems - Beijing China DDI_STRICTORDER_ACC, 90c0c93480Slin wang - Sun Microsystems - Beijing China DDI_DEFAULT_ACC 91dd1de374Slin wang - Sun Microsystems - Beijing China }; 92dd1de374Slin wang - Sun Microsystems - Beijing China 93dd1de374Slin wang - Sun Microsystems - Beijing China /* 94dd1de374Slin wang - Sun Microsystems - Beijing China * Describes the chip's DMA engine 95dd1de374Slin wang - Sun Microsystems - Beijing China */ 96dd1de374Slin wang - Sun Microsystems - Beijing China static ddi_dma_attr_t arn_dma_attr = { 97dd1de374Slin wang - Sun Microsystems - Beijing China DMA_ATTR_V0, /* version number */ 98dd1de374Slin wang - Sun Microsystems - Beijing China 0, /* low address */ 99dd1de374Slin wang - Sun Microsystems - Beijing China 0xffffffffU, /* high address */ 100dd1de374Slin wang - Sun Microsystems - Beijing China 0x3ffffU, /* counter register max */ 101dd1de374Slin wang - Sun Microsystems - Beijing China 1, /* alignment */ 102dd1de374Slin wang - Sun Microsystems - Beijing China 0xFFF, /* burst sizes */ 103dd1de374Slin wang - Sun Microsystems - Beijing China 1, /* minimum transfer size */ 104dd1de374Slin wang - Sun Microsystems - Beijing China 0x3ffffU, /* max transfer size */ 105dd1de374Slin wang - Sun Microsystems - Beijing China 0xffffffffU, /* address register max */ 106dd1de374Slin wang - Sun Microsystems - Beijing China 1, /* no scatter-gather */ 107dd1de374Slin wang - Sun Microsystems - Beijing China 1, /* granularity of device */ 108dd1de374Slin wang - Sun Microsystems - Beijing China 0, /* DMA flags */ 109dd1de374Slin wang - Sun Microsystems - Beijing China }; 110dd1de374Slin wang - Sun Microsystems - Beijing China 111dd1de374Slin wang - Sun Microsystems - Beijing China static ddi_dma_attr_t arn_desc_dma_attr = { 112dd1de374Slin wang - Sun Microsystems - Beijing China DMA_ATTR_V0, /* version number */ 113dd1de374Slin wang - Sun Microsystems - Beijing China 0, /* low address */ 114dd1de374Slin wang - Sun Microsystems - Beijing China 0xffffffffU, /* high address */ 115dd1de374Slin wang - Sun Microsystems - Beijing China 0xffffffffU, /* counter register max */ 116dd1de374Slin wang - Sun Microsystems - Beijing China 0x1000, /* alignment */ 117dd1de374Slin wang - Sun Microsystems - Beijing China 0xFFF, /* burst sizes */ 118dd1de374Slin wang - Sun Microsystems - Beijing China 1, /* minimum transfer size */ 119dd1de374Slin wang - Sun Microsystems - Beijing China 0xffffffffU, /* max transfer size */ 120dd1de374Slin wang - Sun Microsystems - Beijing China 0xffffffffU, /* address register max */ 121dd1de374Slin wang - Sun Microsystems - Beijing China 1, /* no scatter-gather */ 122dd1de374Slin wang - Sun Microsystems - Beijing China 1, /* granularity of device */ 123dd1de374Slin wang - Sun Microsystems - Beijing China 0, /* DMA flags */ 124dd1de374Slin wang - Sun Microsystems - Beijing China }; 125dd1de374Slin wang - Sun Microsystems - Beijing China 126dd1de374Slin wang - Sun Microsystems - Beijing China #define ATH_DEF_CACHE_BYTES 32 /* default cache line size */ 127dd1de374Slin wang - Sun Microsystems - Beijing China 128dd1de374Slin wang - Sun Microsystems - Beijing China static kmutex_t arn_loglock; 129dd1de374Slin wang - Sun Microsystems - Beijing China static void *arn_soft_state_p = NULL; 130c0c93480Slin wang - Sun Microsystems - Beijing China static int arn_dwelltime = 200; /* scan interval */ 131dd1de374Slin wang - Sun Microsystems - Beijing China 132dd1de374Slin wang - Sun Microsystems - Beijing China static int arn_m_stat(void *, uint_t, uint64_t *); 133dd1de374Slin wang - Sun Microsystems - Beijing China static int arn_m_start(void *); 134dd1de374Slin wang - Sun Microsystems - Beijing China static void arn_m_stop(void *); 135dd1de374Slin wang - Sun Microsystems - Beijing China static int arn_m_promisc(void *, boolean_t); 136dd1de374Slin wang - Sun Microsystems - Beijing China static int arn_m_multicst(void *, boolean_t, const uint8_t *); 137dd1de374Slin wang - Sun Microsystems - Beijing China static int arn_m_unicst(void *, const uint8_t *); 138dd1de374Slin wang - Sun Microsystems - Beijing China static mblk_t *arn_m_tx(void *, mblk_t *); 139dd1de374Slin wang - Sun Microsystems - Beijing China static void arn_m_ioctl(void *, queue_t *, mblk_t *); 140dd1de374Slin wang - Sun Microsystems - Beijing China static int arn_m_setprop(void *, const char *, mac_prop_id_t, 141dd1de374Slin wang - Sun Microsystems - Beijing China uint_t, const void *); 142dd1de374Slin wang - Sun Microsystems - Beijing China static int arn_m_getprop(void *, const char *, mac_prop_id_t, 1430dc2366fSVenugopal Iyer uint_t, void *); 1440dc2366fSVenugopal Iyer static void arn_m_propinfo(void *, const char *, mac_prop_id_t, 1450dc2366fSVenugopal Iyer mac_prop_info_handle_t); 146dd1de374Slin wang - Sun Microsystems - Beijing China 147dd1de374Slin wang - Sun Microsystems - Beijing China /* MAC Callcack Functions */ 148dd1de374Slin wang - Sun Microsystems - Beijing China static mac_callbacks_t arn_m_callbacks = { 1490dc2366fSVenugopal Iyer MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO, 150dd1de374Slin wang - Sun Microsystems - Beijing China arn_m_stat, 151dd1de374Slin wang - Sun Microsystems - Beijing China arn_m_start, 152dd1de374Slin wang - Sun Microsystems - Beijing China arn_m_stop, 153dd1de374Slin wang - Sun Microsystems - Beijing China arn_m_promisc, 154dd1de374Slin wang - Sun Microsystems - Beijing China arn_m_multicst, 155dd1de374Slin wang - Sun Microsystems - Beijing China arn_m_unicst, 156dd1de374Slin wang - Sun Microsystems - Beijing China arn_m_tx, 1570dc2366fSVenugopal Iyer NULL, 158dd1de374Slin wang - Sun Microsystems - Beijing China arn_m_ioctl, 159dd1de374Slin wang - Sun Microsystems - Beijing China NULL, 160dd1de374Slin wang - Sun Microsystems - Beijing China NULL, 161dd1de374Slin wang - Sun Microsystems - Beijing China NULL, 162dd1de374Slin wang - Sun Microsystems - Beijing China arn_m_setprop, 1630dc2366fSVenugopal Iyer arn_m_getprop, 1640dc2366fSVenugopal Iyer arn_m_propinfo 165dd1de374Slin wang - Sun Microsystems - Beijing China }; 166dd1de374Slin wang - Sun Microsystems - Beijing China 167dd1de374Slin wang - Sun Microsystems - Beijing China /* 168dd1de374Slin wang - Sun Microsystems - Beijing China * ARN_DBG_HW 169dd1de374Slin wang - Sun Microsystems - Beijing China * ARN_DBG_REG_IO 170dd1de374Slin wang - Sun Microsystems - Beijing China * ARN_DBG_QUEUE 171dd1de374Slin wang - Sun Microsystems - Beijing China * ARN_DBG_EEPROM 172dd1de374Slin wang - Sun Microsystems - Beijing China * ARN_DBG_XMIT 173dd1de374Slin wang - Sun Microsystems - Beijing China * ARN_DBG_RECV 174dd1de374Slin wang - Sun Microsystems - Beijing China * ARN_DBG_CALIBRATE 175dd1de374Slin wang - Sun Microsystems - Beijing China * ARN_DBG_CHANNEL 176dd1de374Slin wang - Sun Microsystems - Beijing China * ARN_DBG_INTERRUPT 177dd1de374Slin wang - Sun Microsystems - Beijing China * ARN_DBG_REGULATORY 178dd1de374Slin wang - Sun Microsystems - Beijing China * ARN_DBG_ANI 179dd1de374Slin wang - Sun Microsystems - Beijing China * ARN_DBG_POWER_MGMT 180dd1de374Slin wang - Sun Microsystems - Beijing China * ARN_DBG_KEYCACHE 181dd1de374Slin wang - Sun Microsystems - Beijing China * ARN_DBG_BEACON 182dd1de374Slin wang - Sun Microsystems - Beijing China * ARN_DBG_RATE 183dd1de374Slin wang - Sun Microsystems - Beijing China * ARN_DBG_INIT 184dd1de374Slin wang - Sun Microsystems - Beijing China * ARN_DBG_ATTACH 185dd1de374Slin wang - Sun Microsystems - Beijing China * ARN_DBG_DEATCH 186dd1de374Slin wang - Sun Microsystems - Beijing China * ARN_DBG_AGGR 187dd1de374Slin wang - Sun Microsystems - Beijing China * ARN_DBG_RESET 188dd1de374Slin wang - Sun Microsystems - Beijing China * ARN_DBG_FATAL 189dd1de374Slin wang - Sun Microsystems - Beijing China * ARN_DBG_ANY 190dd1de374Slin wang - Sun Microsystems - Beijing China * ARN_DBG_ALL 191dd1de374Slin wang - Sun Microsystems - Beijing China */ 192dd1de374Slin wang - Sun Microsystems - Beijing China uint32_t arn_dbg_mask = 0; 193dd1de374Slin wang - Sun Microsystems - Beijing China 194dd1de374Slin wang - Sun Microsystems - Beijing China /* 195dd1de374Slin wang - Sun Microsystems - Beijing China * Exception/warning cases not leading to panic. 196dd1de374Slin wang - Sun Microsystems - Beijing China */ 197dd1de374Slin wang - Sun Microsystems - Beijing China void 198dd1de374Slin wang - Sun Microsystems - Beijing China arn_problem(const int8_t *fmt, ...) 199dd1de374Slin wang - Sun Microsystems - Beijing China { 200dd1de374Slin wang - Sun Microsystems - Beijing China va_list args; 201dd1de374Slin wang - Sun Microsystems - Beijing China 202dd1de374Slin wang - Sun Microsystems - Beijing China mutex_enter(&arn_loglock); 203dd1de374Slin wang - Sun Microsystems - Beijing China 204dd1de374Slin wang - Sun Microsystems - Beijing China va_start(args, fmt); 205dd1de374Slin wang - Sun Microsystems - Beijing China vcmn_err(CE_WARN, fmt, args); 206dd1de374Slin wang - Sun Microsystems - Beijing China va_end(args); 207dd1de374Slin wang - Sun Microsystems - Beijing China 208dd1de374Slin wang - Sun Microsystems - Beijing China mutex_exit(&arn_loglock); 209dd1de374Slin wang - Sun Microsystems - Beijing China } 210dd1de374Slin wang - Sun Microsystems - Beijing China 211dd1de374Slin wang - Sun Microsystems - Beijing China /* 212dd1de374Slin wang - Sun Microsystems - Beijing China * Normal log information independent of debug. 213dd1de374Slin wang - Sun Microsystems - Beijing China */ 214dd1de374Slin wang - Sun Microsystems - Beijing China void 215dd1de374Slin wang - Sun Microsystems - Beijing China arn_log(const int8_t *fmt, ...) 216dd1de374Slin wang - Sun Microsystems - Beijing China { 217dd1de374Slin wang - Sun Microsystems - Beijing China va_list args; 218dd1de374Slin wang - Sun Microsystems - Beijing China 219dd1de374Slin wang - Sun Microsystems - Beijing China mutex_enter(&arn_loglock); 220dd1de374Slin wang - Sun Microsystems - Beijing China 221dd1de374Slin wang - Sun Microsystems - Beijing China va_start(args, fmt); 222dd1de374Slin wang - Sun Microsystems - Beijing China vcmn_err(CE_CONT, fmt, args); 223dd1de374Slin wang - Sun Microsystems - Beijing China va_end(args); 224dd1de374Slin wang - Sun Microsystems - Beijing China 225dd1de374Slin wang - Sun Microsystems - Beijing China mutex_exit(&arn_loglock); 226dd1de374Slin wang - Sun Microsystems - Beijing China } 227dd1de374Slin wang - Sun Microsystems - Beijing China 228dd1de374Slin wang - Sun Microsystems - Beijing China void 229dd1de374Slin wang - Sun Microsystems - Beijing China arn_dbg(uint32_t dbg_flags, const int8_t *fmt, ...) 230dd1de374Slin wang - Sun Microsystems - Beijing China { 231dd1de374Slin wang - Sun Microsystems - Beijing China va_list args; 232dd1de374Slin wang - Sun Microsystems - Beijing China 233dd1de374Slin wang - Sun Microsystems - Beijing China if (dbg_flags & arn_dbg_mask) { 234dd1de374Slin wang - Sun Microsystems - Beijing China mutex_enter(&arn_loglock); 235dd1de374Slin wang - Sun Microsystems - Beijing China va_start(args, fmt); 236dd1de374Slin wang - Sun Microsystems - Beijing China vcmn_err(CE_CONT, fmt, args); 237dd1de374Slin wang - Sun Microsystems - Beijing China va_end(args); 238dd1de374Slin wang - Sun Microsystems - Beijing China mutex_exit(&arn_loglock); 239dd1de374Slin wang - Sun Microsystems - Beijing China } 240dd1de374Slin wang - Sun Microsystems - Beijing China } 241dd1de374Slin wang - Sun Microsystems - Beijing China 242dd1de374Slin wang - Sun Microsystems - Beijing China /* 243dd1de374Slin wang - Sun Microsystems - Beijing China * Read and write, they both share the same lock. We do this to serialize 244dd1de374Slin wang - Sun Microsystems - Beijing China * reads and writes on Atheros 802.11n PCI devices only. This is required 245dd1de374Slin wang - Sun Microsystems - Beijing China * as the FIFO on these devices can only accept sanely 2 requests. After 246dd1de374Slin wang - Sun Microsystems - Beijing China * that the device goes bananas. Serializing the reads/writes prevents this 247dd1de374Slin wang - Sun Microsystems - Beijing China * from happening. 248dd1de374Slin wang - Sun Microsystems - Beijing China */ 249dd1de374Slin wang - Sun Microsystems - Beijing China void 250dd1de374Slin wang - Sun Microsystems - Beijing China arn_iowrite32(struct ath_hal *ah, uint32_t reg_offset, uint32_t val) 251dd1de374Slin wang - Sun Microsystems - Beijing China { 252dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = ah->ah_sc; 253dd1de374Slin wang - Sun Microsystems - Beijing China if (ah->ah_config.serialize_regmode == SER_REG_MODE_ON) { 254dd1de374Slin wang - Sun Microsystems - Beijing China mutex_enter(&sc->sc_serial_rw); 255dd1de374Slin wang - Sun Microsystems - Beijing China ddi_put32(sc->sc_io_handle, 256dd1de374Slin wang - Sun Microsystems - Beijing China (uint32_t *)((uintptr_t)(sc->mem) + (reg_offset)), val); 257dd1de374Slin wang - Sun Microsystems - Beijing China mutex_exit(&sc->sc_serial_rw); 258dd1de374Slin wang - Sun Microsystems - Beijing China } else { 259dd1de374Slin wang - Sun Microsystems - Beijing China ddi_put32(sc->sc_io_handle, 260dd1de374Slin wang - Sun Microsystems - Beijing China (uint32_t *)((uintptr_t)(sc->mem) + (reg_offset)), val); 261dd1de374Slin wang - Sun Microsystems - Beijing China } 262dd1de374Slin wang - Sun Microsystems - Beijing China } 263dd1de374Slin wang - Sun Microsystems - Beijing China 264dd1de374Slin wang - Sun Microsystems - Beijing China unsigned int 265dd1de374Slin wang - Sun Microsystems - Beijing China arn_ioread32(struct ath_hal *ah, uint32_t reg_offset) 266dd1de374Slin wang - Sun Microsystems - Beijing China { 267dd1de374Slin wang - Sun Microsystems - Beijing China uint32_t val; 268dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = ah->ah_sc; 269dd1de374Slin wang - Sun Microsystems - Beijing China if (ah->ah_config.serialize_regmode == SER_REG_MODE_ON) { 270dd1de374Slin wang - Sun Microsystems - Beijing China mutex_enter(&sc->sc_serial_rw); 271dd1de374Slin wang - Sun Microsystems - Beijing China val = ddi_get32(sc->sc_io_handle, 272dd1de374Slin wang - Sun Microsystems - Beijing China (uint32_t *)((uintptr_t)(sc->mem) + (reg_offset))); 273dd1de374Slin wang - Sun Microsystems - Beijing China mutex_exit(&sc->sc_serial_rw); 274dd1de374Slin wang - Sun Microsystems - Beijing China } else { 275dd1de374Slin wang - Sun Microsystems - Beijing China val = ddi_get32(sc->sc_io_handle, 276dd1de374Slin wang - Sun Microsystems - Beijing China (uint32_t *)((uintptr_t)(sc->mem) + (reg_offset))); 277dd1de374Slin wang - Sun Microsystems - Beijing China } 278dd1de374Slin wang - Sun Microsystems - Beijing China 279dd1de374Slin wang - Sun Microsystems - Beijing China return (val); 280dd1de374Slin wang - Sun Microsystems - Beijing China } 281dd1de374Slin wang - Sun Microsystems - Beijing China 282dd1de374Slin wang - Sun Microsystems - Beijing China /* 283dd1de374Slin wang - Sun Microsystems - Beijing China * Allocate an area of memory and a DMA handle for accessing it 284dd1de374Slin wang - Sun Microsystems - Beijing China */ 285dd1de374Slin wang - Sun Microsystems - Beijing China static int 286dd1de374Slin wang - Sun Microsystems - Beijing China arn_alloc_dma_mem(dev_info_t *devinfo, ddi_dma_attr_t *dma_attr, size_t memsize, 287dd1de374Slin wang - Sun Microsystems - Beijing China ddi_device_acc_attr_t *attr_p, uint_t alloc_flags, 288dd1de374Slin wang - Sun Microsystems - Beijing China uint_t bind_flags, dma_area_t *dma_p) 289dd1de374Slin wang - Sun Microsystems - Beijing China { 290dd1de374Slin wang - Sun Microsystems - Beijing China int err; 291dd1de374Slin wang - Sun Microsystems - Beijing China 292dd1de374Slin wang - Sun Microsystems - Beijing China /* 293dd1de374Slin wang - Sun Microsystems - Beijing China * Allocate handle 294dd1de374Slin wang - Sun Microsystems - Beijing China */ 295dd1de374Slin wang - Sun Microsystems - Beijing China err = ddi_dma_alloc_handle(devinfo, dma_attr, 296dd1de374Slin wang - Sun Microsystems - Beijing China DDI_DMA_SLEEP, NULL, &dma_p->dma_hdl); 297dd1de374Slin wang - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) 298dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 299dd1de374Slin wang - Sun Microsystems - Beijing China 300dd1de374Slin wang - Sun Microsystems - Beijing China /* 301dd1de374Slin wang - Sun Microsystems - Beijing China * Allocate memory 302dd1de374Slin wang - Sun Microsystems - Beijing China */ 303dd1de374Slin wang - Sun Microsystems - Beijing China err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, attr_p, 304dd1de374Slin wang - Sun Microsystems - Beijing China alloc_flags, DDI_DMA_SLEEP, NULL, &dma_p->mem_va, 305dd1de374Slin wang - Sun Microsystems - Beijing China &dma_p->alength, &dma_p->acc_hdl); 306dd1de374Slin wang - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) 307dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 308dd1de374Slin wang - Sun Microsystems - Beijing China 309dd1de374Slin wang - Sun Microsystems - Beijing China /* 310dd1de374Slin wang - Sun Microsystems - Beijing China * Bind the two together 311dd1de374Slin wang - Sun Microsystems - Beijing China */ 312dd1de374Slin wang - Sun Microsystems - Beijing China err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL, 313dd1de374Slin wang - Sun Microsystems - Beijing China dma_p->mem_va, dma_p->alength, bind_flags, 314dd1de374Slin wang - Sun Microsystems - Beijing China DDI_DMA_SLEEP, NULL, &dma_p->cookie, &dma_p->ncookies); 315dd1de374Slin wang - Sun Microsystems - Beijing China if (err != DDI_DMA_MAPPED) 316dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 317dd1de374Slin wang - Sun Microsystems - Beijing China 318dd1de374Slin wang - Sun Microsystems - Beijing China dma_p->nslots = ~0U; 319dd1de374Slin wang - Sun Microsystems - Beijing China dma_p->size = ~0U; 320dd1de374Slin wang - Sun Microsystems - Beijing China dma_p->token = ~0U; 321dd1de374Slin wang - Sun Microsystems - Beijing China dma_p->offset = 0; 322dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 323dd1de374Slin wang - Sun Microsystems - Beijing China } 324dd1de374Slin wang - Sun Microsystems - Beijing China 325dd1de374Slin wang - Sun Microsystems - Beijing China /* 326dd1de374Slin wang - Sun Microsystems - Beijing China * Free one allocated area of DMAable memory 327dd1de374Slin wang - Sun Microsystems - Beijing China */ 328dd1de374Slin wang - Sun Microsystems - Beijing China static void 329dd1de374Slin wang - Sun Microsystems - Beijing China arn_free_dma_mem(dma_area_t *dma_p) 330dd1de374Slin wang - Sun Microsystems - Beijing China { 331dd1de374Slin wang - Sun Microsystems - Beijing China if (dma_p->dma_hdl != NULL) { 332dd1de374Slin wang - Sun Microsystems - Beijing China (void) ddi_dma_unbind_handle(dma_p->dma_hdl); 333dd1de374Slin wang - Sun Microsystems - Beijing China if (dma_p->acc_hdl != NULL) { 334dd1de374Slin wang - Sun Microsystems - Beijing China ddi_dma_mem_free(&dma_p->acc_hdl); 335dd1de374Slin wang - Sun Microsystems - Beijing China dma_p->acc_hdl = NULL; 336dd1de374Slin wang - Sun Microsystems - Beijing China } 337dd1de374Slin wang - Sun Microsystems - Beijing China ddi_dma_free_handle(&dma_p->dma_hdl); 338dd1de374Slin wang - Sun Microsystems - Beijing China dma_p->ncookies = 0; 339dd1de374Slin wang - Sun Microsystems - Beijing China dma_p->dma_hdl = NULL; 340dd1de374Slin wang - Sun Microsystems - Beijing China } 341dd1de374Slin wang - Sun Microsystems - Beijing China } 342dd1de374Slin wang - Sun Microsystems - Beijing China 343dd1de374Slin wang - Sun Microsystems - Beijing China /* 344dd1de374Slin wang - Sun Microsystems - Beijing China * Initialize tx, rx. or beacon buffer list. Allocate DMA memory for 345dd1de374Slin wang - Sun Microsystems - Beijing China * each buffer. 346dd1de374Slin wang - Sun Microsystems - Beijing China */ 347dd1de374Slin wang - Sun Microsystems - Beijing China static int 348c0c93480Slin wang - Sun Microsystems - Beijing China arn_buflist_setup(dev_info_t *devinfo, 349c0c93480Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc, 350c0c93480Slin wang - Sun Microsystems - Beijing China list_t *bflist, 351c0c93480Slin wang - Sun Microsystems - Beijing China struct ath_buf **pbf, 352c0c93480Slin wang - Sun Microsystems - Beijing China struct ath_desc **pds, 353c0c93480Slin wang - Sun Microsystems - Beijing China int nbuf, 354c0c93480Slin wang - Sun Microsystems - Beijing China uint_t dmabflags, 355c0c93480Slin wang - Sun Microsystems - Beijing China uint32_t buflen) 356dd1de374Slin wang - Sun Microsystems - Beijing China { 357dd1de374Slin wang - Sun Microsystems - Beijing China int i, err; 358dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_buf *bf = *pbf; 359dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_desc *ds = *pds; 360dd1de374Slin wang - Sun Microsystems - Beijing China 361dd1de374Slin wang - Sun Microsystems - Beijing China list_create(bflist, sizeof (struct ath_buf), 362dd1de374Slin wang - Sun Microsystems - Beijing China offsetof(struct ath_buf, bf_node)); 363dd1de374Slin wang - Sun Microsystems - Beijing China for (i = 0; i < nbuf; i++, bf++, ds++) { 364dd1de374Slin wang - Sun Microsystems - Beijing China bf->bf_desc = ds; 365dd1de374Slin wang - Sun Microsystems - Beijing China bf->bf_daddr = sc->sc_desc_dma.cookie.dmac_address + 366dd1de374Slin wang - Sun Microsystems - Beijing China ((uintptr_t)ds - (uintptr_t)sc->sc_desc); 367dd1de374Slin wang - Sun Microsystems - Beijing China list_insert_tail(bflist, bf); 368dd1de374Slin wang - Sun Microsystems - Beijing China 369dd1de374Slin wang - Sun Microsystems - Beijing China /* alloc DMA memory */ 370dd1de374Slin wang - Sun Microsystems - Beijing China err = arn_alloc_dma_mem(devinfo, &arn_dma_attr, 371c0c93480Slin wang - Sun Microsystems - Beijing China buflen, &arn_desc_accattr, DDI_DMA_STREAMING, 372dd1de374Slin wang - Sun Microsystems - Beijing China dmabflags, &bf->bf_dma); 373dd1de374Slin wang - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) 374dd1de374Slin wang - Sun Microsystems - Beijing China return (err); 375dd1de374Slin wang - Sun Microsystems - Beijing China } 376dd1de374Slin wang - Sun Microsystems - Beijing China *pbf = bf; 377dd1de374Slin wang - Sun Microsystems - Beijing China *pds = ds; 378dd1de374Slin wang - Sun Microsystems - Beijing China 379dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 380dd1de374Slin wang - Sun Microsystems - Beijing China } 381dd1de374Slin wang - Sun Microsystems - Beijing China 382dd1de374Slin wang - Sun Microsystems - Beijing China /* 383dd1de374Slin wang - Sun Microsystems - Beijing China * Destroy tx, rx or beacon buffer list. Free DMA memory. 384dd1de374Slin wang - Sun Microsystems - Beijing China */ 385dd1de374Slin wang - Sun Microsystems - Beijing China static void 386dd1de374Slin wang - Sun Microsystems - Beijing China arn_buflist_cleanup(list_t *buflist) 387dd1de374Slin wang - Sun Microsystems - Beijing China { 388dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_buf *bf; 389dd1de374Slin wang - Sun Microsystems - Beijing China 390dd1de374Slin wang - Sun Microsystems - Beijing China if (!buflist) 391dd1de374Slin wang - Sun Microsystems - Beijing China return; 392dd1de374Slin wang - Sun Microsystems - Beijing China 393dd1de374Slin wang - Sun Microsystems - Beijing China bf = list_head(buflist); 394dd1de374Slin wang - Sun Microsystems - Beijing China while (bf != NULL) { 395dd1de374Slin wang - Sun Microsystems - Beijing China if (bf->bf_m != NULL) { 396dd1de374Slin wang - Sun Microsystems - Beijing China freemsg(bf->bf_m); 397dd1de374Slin wang - Sun Microsystems - Beijing China bf->bf_m = NULL; 398dd1de374Slin wang - Sun Microsystems - Beijing China } 399dd1de374Slin wang - Sun Microsystems - Beijing China /* Free DMA buffer */ 400dd1de374Slin wang - Sun Microsystems - Beijing China arn_free_dma_mem(&bf->bf_dma); 401dd1de374Slin wang - Sun Microsystems - Beijing China if (bf->bf_in != NULL) { 402dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211_free_node(bf->bf_in); 403dd1de374Slin wang - Sun Microsystems - Beijing China bf->bf_in = NULL; 404dd1de374Slin wang - Sun Microsystems - Beijing China } 405dd1de374Slin wang - Sun Microsystems - Beijing China list_remove(buflist, bf); 406dd1de374Slin wang - Sun Microsystems - Beijing China bf = list_head(buflist); 407dd1de374Slin wang - Sun Microsystems - Beijing China } 408dd1de374Slin wang - Sun Microsystems - Beijing China list_destroy(buflist); 409dd1de374Slin wang - Sun Microsystems - Beijing China } 410dd1de374Slin wang - Sun Microsystems - Beijing China 411dd1de374Slin wang - Sun Microsystems - Beijing China static void 412dd1de374Slin wang - Sun Microsystems - Beijing China arn_desc_free(struct arn_softc *sc) 413dd1de374Slin wang - Sun Microsystems - Beijing China { 414dd1de374Slin wang - Sun Microsystems - Beijing China arn_buflist_cleanup(&sc->sc_txbuf_list); 415dd1de374Slin wang - Sun Microsystems - Beijing China arn_buflist_cleanup(&sc->sc_rxbuf_list); 416dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_IBSS 417dd1de374Slin wang - Sun Microsystems - Beijing China arn_buflist_cleanup(&sc->sc_bcbuf_list); 418dd1de374Slin wang - Sun Microsystems - Beijing China #endif 419dd1de374Slin wang - Sun Microsystems - Beijing China 420dd1de374Slin wang - Sun Microsystems - Beijing China /* Free descriptor DMA buffer */ 421dd1de374Slin wang - Sun Microsystems - Beijing China arn_free_dma_mem(&sc->sc_desc_dma); 422dd1de374Slin wang - Sun Microsystems - Beijing China 423dd1de374Slin wang - Sun Microsystems - Beijing China kmem_free((void *)sc->sc_vbufptr, sc->sc_vbuflen); 424dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_vbufptr = NULL; 425dd1de374Slin wang - Sun Microsystems - Beijing China } 426dd1de374Slin wang - Sun Microsystems - Beijing China 427dd1de374Slin wang - Sun Microsystems - Beijing China static int 428dd1de374Slin wang - Sun Microsystems - Beijing China arn_desc_alloc(dev_info_t *devinfo, struct arn_softc *sc) 429dd1de374Slin wang - Sun Microsystems - Beijing China { 430dd1de374Slin wang - Sun Microsystems - Beijing China int err; 431dd1de374Slin wang - Sun Microsystems - Beijing China size_t size; 432dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_desc *ds; 433dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_buf *bf; 434dd1de374Slin wang - Sun Microsystems - Beijing China 435dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_IBSS 436dd1de374Slin wang - Sun Microsystems - Beijing China size = sizeof (struct ath_desc) * (ATH_TXBUF + ATH_RXBUF + ATH_BCBUF); 437dd1de374Slin wang - Sun Microsystems - Beijing China #else 438dd1de374Slin wang - Sun Microsystems - Beijing China size = sizeof (struct ath_desc) * (ATH_TXBUF + ATH_RXBUF); 439dd1de374Slin wang - Sun Microsystems - Beijing China #endif 440dd1de374Slin wang - Sun Microsystems - Beijing China 441dd1de374Slin wang - Sun Microsystems - Beijing China err = arn_alloc_dma_mem(devinfo, &arn_desc_dma_attr, size, 442dd1de374Slin wang - Sun Microsystems - Beijing China &arn_desc_accattr, DDI_DMA_CONSISTENT, 443dd1de374Slin wang - Sun Microsystems - Beijing China DDI_DMA_RDWR | DDI_DMA_CONSISTENT, &sc->sc_desc_dma); 444dd1de374Slin wang - Sun Microsystems - Beijing China 445dd1de374Slin wang - Sun Microsystems - Beijing China /* virtual address of the first descriptor */ 446dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_desc = (struct ath_desc *)sc->sc_desc_dma.mem_va; 447dd1de374Slin wang - Sun Microsystems - Beijing China 448dd1de374Slin wang - Sun Microsystems - Beijing China ds = sc->sc_desc; 449dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_INIT, "arn: arn_desc_alloc(): DMA map: " 450dd1de374Slin wang - Sun Microsystems - Beijing China "%p (%d) -> %p\n", 451dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_desc, sc->sc_desc_dma.alength, 452dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_desc_dma.cookie.dmac_address)); 453dd1de374Slin wang - Sun Microsystems - Beijing China 454dd1de374Slin wang - Sun Microsystems - Beijing China /* allocate data structures to describe TX/RX DMA buffers */ 455dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_IBSS 456dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_vbuflen = sizeof (struct ath_buf) * (ATH_TXBUF + ATH_RXBUF + 457dd1de374Slin wang - Sun Microsystems - Beijing China ATH_BCBUF); 458dd1de374Slin wang - Sun Microsystems - Beijing China #else 459dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_vbuflen = sizeof (struct ath_buf) * (ATH_TXBUF + ATH_RXBUF); 460dd1de374Slin wang - Sun Microsystems - Beijing China #endif 461dd1de374Slin wang - Sun Microsystems - Beijing China bf = (struct ath_buf *)kmem_zalloc(sc->sc_vbuflen, KM_SLEEP); 462dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_vbufptr = bf; 463dd1de374Slin wang - Sun Microsystems - Beijing China 464dd1de374Slin wang - Sun Microsystems - Beijing China /* DMA buffer size for each TX/RX packet */ 465c0c93480Slin wang - Sun Microsystems - Beijing China #ifdef ARN_TX_AGGREGRATION 466c0c93480Slin wang - Sun Microsystems - Beijing China sc->tx_dmabuf_size = 467c0c93480Slin wang - Sun Microsystems - Beijing China roundup((IEEE80211_MAX_MPDU_LEN + 3840 * 2), 468c0c93480Slin wang - Sun Microsystems - Beijing China min(sc->sc_cachelsz, (uint16_t)64)); 469c0c93480Slin wang - Sun Microsystems - Beijing China #else 470c0c93480Slin wang - Sun Microsystems - Beijing China sc->tx_dmabuf_size = 471c0c93480Slin wang - Sun Microsystems - Beijing China roundup(IEEE80211_MAX_MPDU_LEN, min(sc->sc_cachelsz, (uint16_t)64)); 472c0c93480Slin wang - Sun Microsystems - Beijing China #endif 473c0c93480Slin wang - Sun Microsystems - Beijing China sc->rx_dmabuf_size = 474c0c93480Slin wang - Sun Microsystems - Beijing China roundup(IEEE80211_MAX_MPDU_LEN, min(sc->sc_cachelsz, (uint16_t)64)); 475dd1de374Slin wang - Sun Microsystems - Beijing China 476dd1de374Slin wang - Sun Microsystems - Beijing China /* create RX buffer list */ 477dd1de374Slin wang - Sun Microsystems - Beijing China err = arn_buflist_setup(devinfo, sc, &sc->sc_rxbuf_list, &bf, &ds, 478c0c93480Slin wang - Sun Microsystems - Beijing China ATH_RXBUF, DDI_DMA_READ | DDI_DMA_STREAMING, sc->rx_dmabuf_size); 479dd1de374Slin wang - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 480dd1de374Slin wang - Sun Microsystems - Beijing China arn_desc_free(sc); 481dd1de374Slin wang - Sun Microsystems - Beijing China return (err); 482dd1de374Slin wang - Sun Microsystems - Beijing China } 483dd1de374Slin wang - Sun Microsystems - Beijing China 484dd1de374Slin wang - Sun Microsystems - Beijing China /* create TX buffer list */ 485dd1de374Slin wang - Sun Microsystems - Beijing China err = arn_buflist_setup(devinfo, sc, &sc->sc_txbuf_list, &bf, &ds, 486c0c93480Slin wang - Sun Microsystems - Beijing China ATH_TXBUF, DDI_DMA_STREAMING, sc->tx_dmabuf_size); 487dd1de374Slin wang - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 488dd1de374Slin wang - Sun Microsystems - Beijing China arn_desc_free(sc); 489dd1de374Slin wang - Sun Microsystems - Beijing China return (err); 490dd1de374Slin wang - Sun Microsystems - Beijing China } 491dd1de374Slin wang - Sun Microsystems - Beijing China 492dd1de374Slin wang - Sun Microsystems - Beijing China /* create beacon buffer list */ 493dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_IBSS 494dd1de374Slin wang - Sun Microsystems - Beijing China err = arn_buflist_setup(devinfo, sc, &sc->sc_bcbuf_list, &bf, &ds, 495dd1de374Slin wang - Sun Microsystems - Beijing China ATH_BCBUF, DDI_DMA_STREAMING); 496dd1de374Slin wang - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 497dd1de374Slin wang - Sun Microsystems - Beijing China arn_desc_free(sc); 498dd1de374Slin wang - Sun Microsystems - Beijing China return (err); 499dd1de374Slin wang - Sun Microsystems - Beijing China } 500dd1de374Slin wang - Sun Microsystems - Beijing China #endif 501dd1de374Slin wang - Sun Microsystems - Beijing China 502dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 503dd1de374Slin wang - Sun Microsystems - Beijing China } 504dd1de374Slin wang - Sun Microsystems - Beijing China 505dd1de374Slin wang - Sun Microsystems - Beijing China static struct ath_rate_table * 506dd1de374Slin wang - Sun Microsystems - Beijing China /* LINTED E_STATIC_UNUSED */ 507dd1de374Slin wang - Sun Microsystems - Beijing China arn_get_ratetable(struct arn_softc *sc, uint32_t mode) 508dd1de374Slin wang - Sun Microsystems - Beijing China { 509dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_rate_table *rate_table = NULL; 510dd1de374Slin wang - Sun Microsystems - Beijing China 511dd1de374Slin wang - Sun Microsystems - Beijing China switch (mode) { 512dd1de374Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11A: 513dd1de374Slin wang - Sun Microsystems - Beijing China rate_table = sc->hw_rate_table[ATH9K_MODE_11A]; 514dd1de374Slin wang - Sun Microsystems - Beijing China break; 515dd1de374Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11B: 516dd1de374Slin wang - Sun Microsystems - Beijing China rate_table = sc->hw_rate_table[ATH9K_MODE_11B]; 517dd1de374Slin wang - Sun Microsystems - Beijing China break; 518dd1de374Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11G: 519dd1de374Slin wang - Sun Microsystems - Beijing China rate_table = sc->hw_rate_table[ATH9K_MODE_11G]; 520dd1de374Slin wang - Sun Microsystems - Beijing China break; 521dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARB_11N 522dd1de374Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11NA_HT20: 523dd1de374Slin wang - Sun Microsystems - Beijing China rate_table = sc->hw_rate_table[ATH9K_MODE_11NA_HT20]; 524dd1de374Slin wang - Sun Microsystems - Beijing China break; 525dd1de374Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11NG_HT20: 526dd1de374Slin wang - Sun Microsystems - Beijing China rate_table = sc->hw_rate_table[ATH9K_MODE_11NG_HT20]; 527dd1de374Slin wang - Sun Microsystems - Beijing China break; 528dd1de374Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11NA_HT40PLUS: 529dd1de374Slin wang - Sun Microsystems - Beijing China rate_table = sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS]; 530dd1de374Slin wang - Sun Microsystems - Beijing China break; 531dd1de374Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11NA_HT40MINUS: 532dd1de374Slin wang - Sun Microsystems - Beijing China rate_table = sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS]; 533dd1de374Slin wang - Sun Microsystems - Beijing China break; 534dd1de374Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11NG_HT40PLUS: 535dd1de374Slin wang - Sun Microsystems - Beijing China rate_table = sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS]; 536dd1de374Slin wang - Sun Microsystems - Beijing China break; 537dd1de374Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11NG_HT40MINUS: 538dd1de374Slin wang - Sun Microsystems - Beijing China rate_table = sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS]; 539dd1de374Slin wang - Sun Microsystems - Beijing China break; 540dd1de374Slin wang - Sun Microsystems - Beijing China #endif 541dd1de374Slin wang - Sun Microsystems - Beijing China default: 542dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_FATAL, "arn: arn_get_ratetable(): " 543dd1de374Slin wang - Sun Microsystems - Beijing China "invalid mode %u\n", mode)); 544dd1de374Slin wang - Sun Microsystems - Beijing China return (NULL); 545dd1de374Slin wang - Sun Microsystems - Beijing China } 546dd1de374Slin wang - Sun Microsystems - Beijing China 547dd1de374Slin wang - Sun Microsystems - Beijing China return (rate_table); 548dd1de374Slin wang - Sun Microsystems - Beijing China 549dd1de374Slin wang - Sun Microsystems - Beijing China } 550dd1de374Slin wang - Sun Microsystems - Beijing China 551dd1de374Slin wang - Sun Microsystems - Beijing China static void 552dd1de374Slin wang - Sun Microsystems - Beijing China arn_setcurmode(struct arn_softc *sc, enum wireless_mode mode) 553dd1de374Slin wang - Sun Microsystems - Beijing China { 554dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_rate_table *rt; 555dd1de374Slin wang - Sun Microsystems - Beijing China int i; 556dd1de374Slin wang - Sun Microsystems - Beijing China 557dd1de374Slin wang - Sun Microsystems - Beijing China for (i = 0; i < sizeof (sc->asc_rixmap); i++) 558dd1de374Slin wang - Sun Microsystems - Beijing China sc->asc_rixmap[i] = 0xff; 559dd1de374Slin wang - Sun Microsystems - Beijing China 560dd1de374Slin wang - Sun Microsystems - Beijing China rt = sc->hw_rate_table[mode]; 561dd1de374Slin wang - Sun Microsystems - Beijing China ASSERT(rt != NULL); 562dd1de374Slin wang - Sun Microsystems - Beijing China 563dd1de374Slin wang - Sun Microsystems - Beijing China for (i = 0; i < rt->rate_cnt; i++) 564dd1de374Slin wang - Sun Microsystems - Beijing China sc->asc_rixmap[rt->info[i].dot11rate & 565dd1de374Slin wang - Sun Microsystems - Beijing China IEEE80211_RATE_VAL] = (uint8_t)i; /* LINT */ 566dd1de374Slin wang - Sun Microsystems - Beijing China 567dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_currates = rt; 568dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_curmode = mode; 569dd1de374Slin wang - Sun Microsystems - Beijing China 570dd1de374Slin wang - Sun Microsystems - Beijing China /* 571dd1de374Slin wang - Sun Microsystems - Beijing China * All protection frames are transmited at 2Mb/s for 572dd1de374Slin wang - Sun Microsystems - Beijing China * 11g, otherwise at 1Mb/s. 573dd1de374Slin wang - Sun Microsystems - Beijing China * XXX select protection rate index from rate table. 574dd1de374Slin wang - Sun Microsystems - Beijing China */ 575dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_protrix = (mode == ATH9K_MODE_11G ? 1 : 0); 576dd1de374Slin wang - Sun Microsystems - Beijing China } 577dd1de374Slin wang - Sun Microsystems - Beijing China 578dd1de374Slin wang - Sun Microsystems - Beijing China static enum wireless_mode 579dd1de374Slin wang - Sun Microsystems - Beijing China arn_chan2mode(struct ath9k_channel *chan) 580dd1de374Slin wang - Sun Microsystems - Beijing China { 581dd1de374Slin wang - Sun Microsystems - Beijing China if (chan->chanmode == CHANNEL_A) 582dd1de374Slin wang - Sun Microsystems - Beijing China return (ATH9K_MODE_11A); 583dd1de374Slin wang - Sun Microsystems - Beijing China else if (chan->chanmode == CHANNEL_G) 584dd1de374Slin wang - Sun Microsystems - Beijing China return (ATH9K_MODE_11G); 585dd1de374Slin wang - Sun Microsystems - Beijing China else if (chan->chanmode == CHANNEL_B) 586dd1de374Slin wang - Sun Microsystems - Beijing China return (ATH9K_MODE_11B); 587dd1de374Slin wang - Sun Microsystems - Beijing China else if (chan->chanmode == CHANNEL_A_HT20) 588dd1de374Slin wang - Sun Microsystems - Beijing China return (ATH9K_MODE_11NA_HT20); 589dd1de374Slin wang - Sun Microsystems - Beijing China else if (chan->chanmode == CHANNEL_G_HT20) 590dd1de374Slin wang - Sun Microsystems - Beijing China return (ATH9K_MODE_11NG_HT20); 591dd1de374Slin wang - Sun Microsystems - Beijing China else if (chan->chanmode == CHANNEL_A_HT40PLUS) 592dd1de374Slin wang - Sun Microsystems - Beijing China return (ATH9K_MODE_11NA_HT40PLUS); 593dd1de374Slin wang - Sun Microsystems - Beijing China else if (chan->chanmode == CHANNEL_A_HT40MINUS) 594dd1de374Slin wang - Sun Microsystems - Beijing China return (ATH9K_MODE_11NA_HT40MINUS); 595dd1de374Slin wang - Sun Microsystems - Beijing China else if (chan->chanmode == CHANNEL_G_HT40PLUS) 596dd1de374Slin wang - Sun Microsystems - Beijing China return (ATH9K_MODE_11NG_HT40PLUS); 597dd1de374Slin wang - Sun Microsystems - Beijing China else if (chan->chanmode == CHANNEL_G_HT40MINUS) 598dd1de374Slin wang - Sun Microsystems - Beijing China return (ATH9K_MODE_11NG_HT40MINUS); 599dd1de374Slin wang - Sun Microsystems - Beijing China 600dd1de374Slin wang - Sun Microsystems - Beijing China return (ATH9K_MODE_11B); 601dd1de374Slin wang - Sun Microsystems - Beijing China } 602dd1de374Slin wang - Sun Microsystems - Beijing China 603dd1de374Slin wang - Sun Microsystems - Beijing China static void 604dd1de374Slin wang - Sun Microsystems - Beijing China arn_update_txpow(struct arn_softc *sc) 605dd1de374Slin wang - Sun Microsystems - Beijing China { 606dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_hal *ah = sc->sc_ah; 607dd1de374Slin wang - Sun Microsystems - Beijing China uint32_t txpow; 608dd1de374Slin wang - Sun Microsystems - Beijing China 609dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_curtxpow != sc->sc_config.txpowlimit) { 610dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_set_txpowerlimit(ah, sc->sc_config.txpowlimit); 611dd1de374Slin wang - Sun Microsystems - Beijing China /* read back in case value is clamped */ 612dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow); 613dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_curtxpow = (uint32_t)txpow; 614dd1de374Slin wang - Sun Microsystems - Beijing China } 615dd1de374Slin wang - Sun Microsystems - Beijing China } 616dd1de374Slin wang - Sun Microsystems - Beijing China 617c0c93480Slin wang - Sun Microsystems - Beijing China uint8_t 618c0c93480Slin wang - Sun Microsystems - Beijing China parse_mpdudensity(uint8_t mpdudensity) 619c0c93480Slin wang - Sun Microsystems - Beijing China { 620c0c93480Slin wang - Sun Microsystems - Beijing China /* 621c0c93480Slin wang - Sun Microsystems - Beijing China * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing": 622c0c93480Slin wang - Sun Microsystems - Beijing China * 0 for no restriction 623c0c93480Slin wang - Sun Microsystems - Beijing China * 1 for 1/4 us 624c0c93480Slin wang - Sun Microsystems - Beijing China * 2 for 1/2 us 625c0c93480Slin wang - Sun Microsystems - Beijing China * 3 for 1 us 626c0c93480Slin wang - Sun Microsystems - Beijing China * 4 for 2 us 627c0c93480Slin wang - Sun Microsystems - Beijing China * 5 for 4 us 628c0c93480Slin wang - Sun Microsystems - Beijing China * 6 for 8 us 629c0c93480Slin wang - Sun Microsystems - Beijing China * 7 for 16 us 630c0c93480Slin wang - Sun Microsystems - Beijing China */ 631c0c93480Slin wang - Sun Microsystems - Beijing China switch (mpdudensity) { 632c0c93480Slin wang - Sun Microsystems - Beijing China case 0: 633c0c93480Slin wang - Sun Microsystems - Beijing China return (0); 634c0c93480Slin wang - Sun Microsystems - Beijing China case 1: 635c0c93480Slin wang - Sun Microsystems - Beijing China case 2: 636c0c93480Slin wang - Sun Microsystems - Beijing China case 3: 637c0c93480Slin wang - Sun Microsystems - Beijing China /* 638c0c93480Slin wang - Sun Microsystems - Beijing China * Our lower layer calculations limit our 639c0c93480Slin wang - Sun Microsystems - Beijing China * precision to 1 microsecond 640c0c93480Slin wang - Sun Microsystems - Beijing China */ 641c0c93480Slin wang - Sun Microsystems - Beijing China return (1); 642c0c93480Slin wang - Sun Microsystems - Beijing China case 4: 643c0c93480Slin wang - Sun Microsystems - Beijing China return (2); 644c0c93480Slin wang - Sun Microsystems - Beijing China case 5: 645c0c93480Slin wang - Sun Microsystems - Beijing China return (4); 646c0c93480Slin wang - Sun Microsystems - Beijing China case 6: 647c0c93480Slin wang - Sun Microsystems - Beijing China return (8); 648c0c93480Slin wang - Sun Microsystems - Beijing China case 7: 649c0c93480Slin wang - Sun Microsystems - Beijing China return (16); 650c0c93480Slin wang - Sun Microsystems - Beijing China default: 651c0c93480Slin wang - Sun Microsystems - Beijing China return (0); 652c0c93480Slin wang - Sun Microsystems - Beijing China } 653c0c93480Slin wang - Sun Microsystems - Beijing China } 654c0c93480Slin wang - Sun Microsystems - Beijing China 655dd1de374Slin wang - Sun Microsystems - Beijing China static void 656dd1de374Slin wang - Sun Microsystems - Beijing China arn_setup_rates(struct arn_softc *sc, uint32_t mode) 657dd1de374Slin wang - Sun Microsystems - Beijing China { 658dd1de374Slin wang - Sun Microsystems - Beijing China int i, maxrates; 659dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_rate_table *rate_table = NULL; 660dd1de374Slin wang - Sun Microsystems - Beijing China struct ieee80211_rateset *rateset; 661dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211com_t *ic = (ieee80211com_t *)sc; 662dd1de374Slin wang - Sun Microsystems - Beijing China 663dd1de374Slin wang - Sun Microsystems - Beijing China /* rate_table = arn_get_ratetable(sc, mode); */ 664dd1de374Slin wang - Sun Microsystems - Beijing China switch (mode) { 665dd1de374Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11A: 666dd1de374Slin wang - Sun Microsystems - Beijing China rate_table = sc->hw_rate_table[ATH9K_MODE_11A]; 667dd1de374Slin wang - Sun Microsystems - Beijing China break; 668dd1de374Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11B: 669dd1de374Slin wang - Sun Microsystems - Beijing China rate_table = sc->hw_rate_table[ATH9K_MODE_11B]; 670dd1de374Slin wang - Sun Microsystems - Beijing China break; 671dd1de374Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11G: 672dd1de374Slin wang - Sun Microsystems - Beijing China rate_table = sc->hw_rate_table[ATH9K_MODE_11G]; 673dd1de374Slin wang - Sun Microsystems - Beijing China break; 674dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_11N 675dd1de374Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11NA_HT20: 676dd1de374Slin wang - Sun Microsystems - Beijing China rate_table = sc->hw_rate_table[ATH9K_MODE_11NA_HT20]; 677dd1de374Slin wang - Sun Microsystems - Beijing China break; 678dd1de374Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11NG_HT20: 679dd1de374Slin wang - Sun Microsystems - Beijing China rate_table = sc->hw_rate_table[ATH9K_MODE_11NG_HT20]; 680dd1de374Slin wang - Sun Microsystems - Beijing China break; 681dd1de374Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11NA_HT40PLUS: 682dd1de374Slin wang - Sun Microsystems - Beijing China rate_table = sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS]; 683dd1de374Slin wang - Sun Microsystems - Beijing China break; 684dd1de374Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11NA_HT40MINUS: 685dd1de374Slin wang - Sun Microsystems - Beijing China rate_table = sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS]; 686dd1de374Slin wang - Sun Microsystems - Beijing China break; 687dd1de374Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11NG_HT40PLUS: 688dd1de374Slin wang - Sun Microsystems - Beijing China rate_table = sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS]; 689dd1de374Slin wang - Sun Microsystems - Beijing China break; 690dd1de374Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11NG_HT40MINUS: 691dd1de374Slin wang - Sun Microsystems - Beijing China rate_table = sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS]; 692dd1de374Slin wang - Sun Microsystems - Beijing China break; 693dd1de374Slin wang - Sun Microsystems - Beijing China #endif 694dd1de374Slin wang - Sun Microsystems - Beijing China default: 695dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_RATE, "arn: arn_get_ratetable(): " 696dd1de374Slin wang - Sun Microsystems - Beijing China "invalid mode %u\n", mode)); 697dd1de374Slin wang - Sun Microsystems - Beijing China break; 698dd1de374Slin wang - Sun Microsystems - Beijing China } 699dd1de374Slin wang - Sun Microsystems - Beijing China if (rate_table == NULL) 700dd1de374Slin wang - Sun Microsystems - Beijing China return; 701dd1de374Slin wang - Sun Microsystems - Beijing China if (rate_table->rate_cnt > ATH_RATE_MAX) { 702dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_RATE, "arn: arn_rate_setup(): " 703dd1de374Slin wang - Sun Microsystems - Beijing China "rate table too small (%u > %u)\n", 704dd1de374Slin wang - Sun Microsystems - Beijing China rate_table->rate_cnt, IEEE80211_RATE_MAXSIZE)); 705dd1de374Slin wang - Sun Microsystems - Beijing China maxrates = ATH_RATE_MAX; 706dd1de374Slin wang - Sun Microsystems - Beijing China } else 707dd1de374Slin wang - Sun Microsystems - Beijing China maxrates = rate_table->rate_cnt; 708dd1de374Slin wang - Sun Microsystems - Beijing China 709dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_RATE, "arn: arn_rate_setup(): " 710dd1de374Slin wang - Sun Microsystems - Beijing China "maxrates is %d\n", maxrates)); 711dd1de374Slin wang - Sun Microsystems - Beijing China 712dd1de374Slin wang - Sun Microsystems - Beijing China rateset = &ic->ic_sup_rates[mode]; 713dd1de374Slin wang - Sun Microsystems - Beijing China for (i = 0; i < maxrates; i++) { 714dd1de374Slin wang - Sun Microsystems - Beijing China rateset->ir_rates[i] = rate_table->info[i].dot11rate; 715dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_RATE, "arn: arn_rate_setup(): " 716dd1de374Slin wang - Sun Microsystems - Beijing China "%d\n", rate_table->info[i].dot11rate)); 717dd1de374Slin wang - Sun Microsystems - Beijing China } 718dd1de374Slin wang - Sun Microsystems - Beijing China rateset->ir_nrates = (uint8_t)maxrates; /* ??? */ 719dd1de374Slin wang - Sun Microsystems - Beijing China } 720dd1de374Slin wang - Sun Microsystems - Beijing China 721dd1de374Slin wang - Sun Microsystems - Beijing China static int 722dd1de374Slin wang - Sun Microsystems - Beijing China arn_setup_channels(struct arn_softc *sc) 723dd1de374Slin wang - Sun Microsystems - Beijing China { 724dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_hal *ah = sc->sc_ah; 725dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211com_t *ic = (ieee80211com_t *)sc; 726dd1de374Slin wang - Sun Microsystems - Beijing China int nchan, i, index; 727dd1de374Slin wang - Sun Microsystems - Beijing China uint8_t regclassids[ATH_REGCLASSIDS_MAX]; 728dd1de374Slin wang - Sun Microsystems - Beijing China uint32_t nregclass = 0; 729dd1de374Slin wang - Sun Microsystems - Beijing China struct ath9k_channel *c; 730dd1de374Slin wang - Sun Microsystems - Beijing China 731dd1de374Slin wang - Sun Microsystems - Beijing China /* Fill in ah->ah_channels */ 732dd1de374Slin wang - Sun Microsystems - Beijing China if (!ath9k_regd_init_channels(ah, ATH_CHAN_MAX, (uint32_t *)&nchan, 733dd1de374Slin wang - Sun Microsystems - Beijing China regclassids, ATH_REGCLASSIDS_MAX, &nregclass, CTRY_DEFAULT, 734dd1de374Slin wang - Sun Microsystems - Beijing China B_FALSE, 1)) { 735dd1de374Slin wang - Sun Microsystems - Beijing China uint32_t rd = ah->ah_currentRD; 736dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_CHANNEL, "arn: arn_setup_channels(): " 737dd1de374Slin wang - Sun Microsystems - Beijing China "unable to collect channel list; " 738dd1de374Slin wang - Sun Microsystems - Beijing China "regdomain likely %u country code %u\n", 739dd1de374Slin wang - Sun Microsystems - Beijing China rd, CTRY_DEFAULT)); 740dd1de374Slin wang - Sun Microsystems - Beijing China return (EINVAL); 741dd1de374Slin wang - Sun Microsystems - Beijing China } 742dd1de374Slin wang - Sun Microsystems - Beijing China 743dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_CHANNEL, "arn: arn_setup_channels(): " 744dd1de374Slin wang - Sun Microsystems - Beijing China "number of channel is %d\n", nchan)); 745dd1de374Slin wang - Sun Microsystems - Beijing China 746dd1de374Slin wang - Sun Microsystems - Beijing China for (i = 0; i < nchan; i++) { 747dd1de374Slin wang - Sun Microsystems - Beijing China c = &ah->ah_channels[i]; 748c0c93480Slin wang - Sun Microsystems - Beijing China uint32_t flags; 749dd1de374Slin wang - Sun Microsystems - Beijing China index = ath9k_hw_mhz2ieee(ah, c->channel, c->channelFlags); 750dd1de374Slin wang - Sun Microsystems - Beijing China 751dd1de374Slin wang - Sun Microsystems - Beijing China if (index > IEEE80211_CHAN_MAX) { 752dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_CHANNEL, 753dd1de374Slin wang - Sun Microsystems - Beijing China "arn: arn_setup_channels(): " 754dd1de374Slin wang - Sun Microsystems - Beijing China "bad hal channel %d (%u/%x) ignored\n", 755dd1de374Slin wang - Sun Microsystems - Beijing China index, c->channel, c->channelFlags)); 756dd1de374Slin wang - Sun Microsystems - Beijing China continue; 757dd1de374Slin wang - Sun Microsystems - Beijing China } 758dd1de374Slin wang - Sun Microsystems - Beijing China /* NB: flags are known to be compatible */ 759dd1de374Slin wang - Sun Microsystems - Beijing China if (index < 0) { 760dd1de374Slin wang - Sun Microsystems - Beijing China /* 761dd1de374Slin wang - Sun Microsystems - Beijing China * can't handle frequency <2400MHz (negative 762dd1de374Slin wang - Sun Microsystems - Beijing China * channels) right now 763dd1de374Slin wang - Sun Microsystems - Beijing China */ 764dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_CHANNEL, 765dd1de374Slin wang - Sun Microsystems - Beijing China "arn: arn_setup_channels(): " 766dd1de374Slin wang - Sun Microsystems - Beijing China "hal channel %d (%u/%x) " 767dd1de374Slin wang - Sun Microsystems - Beijing China "cannot be handled, ignored\n", 768dd1de374Slin wang - Sun Microsystems - Beijing China index, c->channel, c->channelFlags)); 769dd1de374Slin wang - Sun Microsystems - Beijing China continue; 770dd1de374Slin wang - Sun Microsystems - Beijing China } 771dd1de374Slin wang - Sun Microsystems - Beijing China 772dd1de374Slin wang - Sun Microsystems - Beijing China /* 773dd1de374Slin wang - Sun Microsystems - Beijing China * Calculate net80211 flags; most are compatible 774dd1de374Slin wang - Sun Microsystems - Beijing China * but some need massaging. Note the static turbo 775dd1de374Slin wang - Sun Microsystems - Beijing China * conversion can be removed once net80211 is updated 776dd1de374Slin wang - Sun Microsystems - Beijing China * to understand static vs. dynamic turbo. 777dd1de374Slin wang - Sun Microsystems - Beijing China */ 778dd1de374Slin wang - Sun Microsystems - Beijing China 779dd1de374Slin wang - Sun Microsystems - Beijing China flags = c->channelFlags & (CHANNEL_ALL | CHANNEL_PASSIVE); 780dd1de374Slin wang - Sun Microsystems - Beijing China 781dd1de374Slin wang - Sun Microsystems - Beijing China if (ic->ic_sup_channels[index].ich_freq == 0) { 782dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_sup_channels[index].ich_freq = c->channel; 783dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_sup_channels[index].ich_flags = flags; 784dd1de374Slin wang - Sun Microsystems - Beijing China } else { 785dd1de374Slin wang - Sun Microsystems - Beijing China /* channels overlap; e.g. 11g and 11b */ 786dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_sup_channels[index].ich_flags |= flags; 787dd1de374Slin wang - Sun Microsystems - Beijing China } 788dd1de374Slin wang - Sun Microsystems - Beijing China if ((c->channelFlags & CHANNEL_G) == CHANNEL_G) { 789dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_have11g = 1; 790dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_caps |= IEEE80211_C_SHPREAMBLE | 791dd1de374Slin wang - Sun Microsystems - Beijing China IEEE80211_C_SHSLOT; /* short slot time */ 792dd1de374Slin wang - Sun Microsystems - Beijing China } 793dd1de374Slin wang - Sun Microsystems - Beijing China } 794dd1de374Slin wang - Sun Microsystems - Beijing China 795dd1de374Slin wang - Sun Microsystems - Beijing China return (0); 796dd1de374Slin wang - Sun Microsystems - Beijing China } 797dd1de374Slin wang - Sun Microsystems - Beijing China 798dd1de374Slin wang - Sun Microsystems - Beijing China uint32_t 799dd1de374Slin wang - Sun Microsystems - Beijing China arn_chan2flags(ieee80211com_t *isc, struct ieee80211_channel *chan) 800dd1de374Slin wang - Sun Microsystems - Beijing China { 801c0c93480Slin wang - Sun Microsystems - Beijing China uint32_t channel_mode; 802c0c93480Slin wang - Sun Microsystems - Beijing China switch (ieee80211_chan2mode(isc, chan)) { 803c0c93480Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11NA: 804c0c93480Slin wang - Sun Microsystems - Beijing China if (chan->ich_flags & IEEE80211_CHAN_HT40U) 805c0c93480Slin wang - Sun Microsystems - Beijing China channel_mode = CHANNEL_A_HT40PLUS; 806c0c93480Slin wang - Sun Microsystems - Beijing China else if (chan->ich_flags & IEEE80211_CHAN_HT40D) 807c0c93480Slin wang - Sun Microsystems - Beijing China channel_mode = CHANNEL_A_HT40MINUS; 808c0c93480Slin wang - Sun Microsystems - Beijing China else 809c0c93480Slin wang - Sun Microsystems - Beijing China channel_mode = CHANNEL_A_HT20; 810c0c93480Slin wang - Sun Microsystems - Beijing China break; 811c0c93480Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11NG: 812c0c93480Slin wang - Sun Microsystems - Beijing China if (chan->ich_flags & IEEE80211_CHAN_HT40U) 813c0c93480Slin wang - Sun Microsystems - Beijing China channel_mode = CHANNEL_G_HT40PLUS; 814c0c93480Slin wang - Sun Microsystems - Beijing China else if (chan->ich_flags & IEEE80211_CHAN_HT40D) 815c0c93480Slin wang - Sun Microsystems - Beijing China channel_mode = CHANNEL_G_HT40MINUS; 816c0c93480Slin wang - Sun Microsystems - Beijing China else 817c0c93480Slin wang - Sun Microsystems - Beijing China channel_mode = CHANNEL_G_HT20; 818c0c93480Slin wang - Sun Microsystems - Beijing China break; 819c0c93480Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_TURBO_G: 820c0c93480Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_STURBO_A: 821c0c93480Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_TURBO_A: 822c0c93480Slin wang - Sun Microsystems - Beijing China channel_mode = 0; 823c0c93480Slin wang - Sun Microsystems - Beijing China break; 824c0c93480Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11A: 825c0c93480Slin wang - Sun Microsystems - Beijing China channel_mode = CHANNEL_A; 826c0c93480Slin wang - Sun Microsystems - Beijing China break; 827c0c93480Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11G: 828c0c93480Slin wang - Sun Microsystems - Beijing China channel_mode = CHANNEL_B; 829c0c93480Slin wang - Sun Microsystems - Beijing China break; 830c0c93480Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11B: 831c0c93480Slin wang - Sun Microsystems - Beijing China channel_mode = CHANNEL_G; 832c0c93480Slin wang - Sun Microsystems - Beijing China break; 833c0c93480Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_FH: 834c0c93480Slin wang - Sun Microsystems - Beijing China channel_mode = 0; 835c0c93480Slin wang - Sun Microsystems - Beijing China break; 836c0c93480Slin wang - Sun Microsystems - Beijing China default: 837c0c93480Slin wang - Sun Microsystems - Beijing China break; 838c0c93480Slin wang - Sun Microsystems - Beijing China } 839c0c93480Slin wang - Sun Microsystems - Beijing China 840c0c93480Slin wang - Sun Microsystems - Beijing China return (channel_mode); 841dd1de374Slin wang - Sun Microsystems - Beijing China } 842dd1de374Slin wang - Sun Microsystems - Beijing China 843dd1de374Slin wang - Sun Microsystems - Beijing China /* 844dd1de374Slin wang - Sun Microsystems - Beijing China * Update internal state after a channel change. 845dd1de374Slin wang - Sun Microsystems - Beijing China */ 846dd1de374Slin wang - Sun Microsystems - Beijing China void 847dd1de374Slin wang - Sun Microsystems - Beijing China arn_chan_change(struct arn_softc *sc, struct ieee80211_channel *chan) 848dd1de374Slin wang - Sun Microsystems - Beijing China { 849dd1de374Slin wang - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_isc; 850dd1de374Slin wang - Sun Microsystems - Beijing China enum ieee80211_phymode mode; 851dd1de374Slin wang - Sun Microsystems - Beijing China enum wireless_mode wlmode; 852dd1de374Slin wang - Sun Microsystems - Beijing China 853dd1de374Slin wang - Sun Microsystems - Beijing China /* 854dd1de374Slin wang - Sun Microsystems - Beijing China * Change channels and update the h/w rate map 855dd1de374Slin wang - Sun Microsystems - Beijing China * if we're switching; e.g. 11a to 11b/g. 856dd1de374Slin wang - Sun Microsystems - Beijing China */ 857dd1de374Slin wang - Sun Microsystems - Beijing China mode = ieee80211_chan2mode(ic, chan); 858dd1de374Slin wang - Sun Microsystems - Beijing China switch (mode) { 859dd1de374Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11A: 860dd1de374Slin wang - Sun Microsystems - Beijing China wlmode = ATH9K_MODE_11A; 861dd1de374Slin wang - Sun Microsystems - Beijing China break; 862dd1de374Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11B: 863dd1de374Slin wang - Sun Microsystems - Beijing China wlmode = ATH9K_MODE_11B; 864dd1de374Slin wang - Sun Microsystems - Beijing China break; 865dd1de374Slin wang - Sun Microsystems - Beijing China case IEEE80211_MODE_11G: 866dd1de374Slin wang - Sun Microsystems - Beijing China wlmode = ATH9K_MODE_11B; 867dd1de374Slin wang - Sun Microsystems - Beijing China break; 868dd1de374Slin wang - Sun Microsystems - Beijing China default: 869dd1de374Slin wang - Sun Microsystems - Beijing China break; 870dd1de374Slin wang - Sun Microsystems - Beijing China } 871dd1de374Slin wang - Sun Microsystems - Beijing China if (wlmode != sc->sc_curmode) 872dd1de374Slin wang - Sun Microsystems - Beijing China arn_setcurmode(sc, wlmode); 873dd1de374Slin wang - Sun Microsystems - Beijing China 874dd1de374Slin wang - Sun Microsystems - Beijing China } 875dd1de374Slin wang - Sun Microsystems - Beijing China 876dd1de374Slin wang - Sun Microsystems - Beijing China /* 877dd1de374Slin wang - Sun Microsystems - Beijing China * Set/change channels. If the channel is really being changed, it's done 878dd1de374Slin wang - Sun Microsystems - Beijing China * by reseting the chip. To accomplish this we must first cleanup any pending 879dd1de374Slin wang - Sun Microsystems - Beijing China * DMA, then restart stuff. 880dd1de374Slin wang - Sun Microsystems - Beijing China */ 881dd1de374Slin wang - Sun Microsystems - Beijing China static int 882dd1de374Slin wang - Sun Microsystems - Beijing China arn_set_channel(struct arn_softc *sc, struct ath9k_channel *hchan) 883dd1de374Slin wang - Sun Microsystems - Beijing China { 884dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_hal *ah = sc->sc_ah; 885dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211com_t *ic = &sc->sc_isc; 886dd1de374Slin wang - Sun Microsystems - Beijing China boolean_t fastcc = B_TRUE; 887dd1de374Slin wang - Sun Microsystems - Beijing China boolean_t stopped; 888dd1de374Slin wang - Sun Microsystems - Beijing China struct ieee80211_channel chan; 889dd1de374Slin wang - Sun Microsystems - Beijing China enum wireless_mode curmode; 890dd1de374Slin wang - Sun Microsystems - Beijing China 891dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_flags & SC_OP_INVALID) 892dd1de374Slin wang - Sun Microsystems - Beijing China return (EIO); 893dd1de374Slin wang - Sun Microsystems - Beijing China 894dd1de374Slin wang - Sun Microsystems - Beijing China if (hchan->channel != sc->sc_ah->ah_curchan->channel || 895dd1de374Slin wang - Sun Microsystems - Beijing China hchan->channelFlags != sc->sc_ah->ah_curchan->channelFlags || 896dd1de374Slin wang - Sun Microsystems - Beijing China (sc->sc_flags & SC_OP_CHAINMASK_UPDATE) || 897dd1de374Slin wang - Sun Microsystems - Beijing China (sc->sc_flags & SC_OP_FULL_RESET)) { 898dd1de374Slin wang - Sun Microsystems - Beijing China int status; 899dd1de374Slin wang - Sun Microsystems - Beijing China 900dd1de374Slin wang - Sun Microsystems - Beijing China /* 901dd1de374Slin wang - Sun Microsystems - Beijing China * This is only performed if the channel settings have 902dd1de374Slin wang - Sun Microsystems - Beijing China * actually changed. 903dd1de374Slin wang - Sun Microsystems - Beijing China * 904dd1de374Slin wang - Sun Microsystems - Beijing China * To switch channels clear any pending DMA operations; 905dd1de374Slin wang - Sun Microsystems - Beijing China * wait long enough for the RX fifo to drain, reset the 906dd1de374Slin wang - Sun Microsystems - Beijing China * hardware at the new frequency, and then re-enable 907dd1de374Slin wang - Sun Microsystems - Beijing China * the relevant bits of the h/w. 908dd1de374Slin wang - Sun Microsystems - Beijing China */ 909dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_set_interrupts(ah, 0); /* disable interrupts */ 910dd1de374Slin wang - Sun Microsystems - Beijing China arn_draintxq(sc, B_FALSE); /* clear pending tx frames */ 911dd1de374Slin wang - Sun Microsystems - Beijing China stopped = arn_stoprecv(sc); /* turn off frame recv */ 912dd1de374Slin wang - Sun Microsystems - Beijing China 913dd1de374Slin wang - Sun Microsystems - Beijing China /* 914dd1de374Slin wang - Sun Microsystems - Beijing China * XXX: do not flush receive queue here. We don't want 915dd1de374Slin wang - Sun Microsystems - Beijing China * to flush data frames already in queue because of 916dd1de374Slin wang - Sun Microsystems - Beijing China * changing channel. 917dd1de374Slin wang - Sun Microsystems - Beijing China */ 918dd1de374Slin wang - Sun Microsystems - Beijing China 919dd1de374Slin wang - Sun Microsystems - Beijing China if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET)) 920dd1de374Slin wang - Sun Microsystems - Beijing China fastcc = B_FALSE; 921dd1de374Slin wang - Sun Microsystems - Beijing China 922dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_CHANNEL, "arn: arn_set_channel(): " 923dd1de374Slin wang - Sun Microsystems - Beijing China "(%u MHz) -> (%u MHz), cflags:%x, chanwidth: %d\n", 924dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_ah->ah_curchan->channel, 925dd1de374Slin wang - Sun Microsystems - Beijing China hchan->channel, hchan->channelFlags, sc->tx_chan_width)); 926dd1de374Slin wang - Sun Microsystems - Beijing China 927dd1de374Slin wang - Sun Microsystems - Beijing China if (!ath9k_hw_reset(ah, hchan, sc->tx_chan_width, 928dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_tx_chainmask, sc->sc_rx_chainmask, 929dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_ht_extprotspacing, fastcc, &status)) { 930dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_FATAL, "arn: arn_set_channel(): " 931dd1de374Slin wang - Sun Microsystems - Beijing China "unable to reset channel %u (%uMhz) " 932dd1de374Slin wang - Sun Microsystems - Beijing China "flags 0x%x hal status %u\n", 933dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_mhz2ieee(ah, hchan->channel, 934dd1de374Slin wang - Sun Microsystems - Beijing China hchan->channelFlags), 935dd1de374Slin wang - Sun Microsystems - Beijing China hchan->channel, hchan->channelFlags, status)); 936dd1de374Slin wang - Sun Microsystems - Beijing China return (EIO); 937dd1de374Slin wang - Sun Microsystems - Beijing China } 938dd1de374Slin wang - Sun Microsystems - Beijing China 939dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_curchan = *hchan; 940dd1de374Slin wang - Sun Microsystems - Beijing China 941dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_flags &= ~SC_OP_CHAINMASK_UPDATE; 942dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_flags &= ~SC_OP_FULL_RESET; 943dd1de374Slin wang - Sun Microsystems - Beijing China 944dd1de374Slin wang - Sun Microsystems - Beijing China if (arn_startrecv(sc) != 0) { 945dd1de374Slin wang - Sun Microsystems - Beijing China arn_problem("arn: arn_set_channel(): " 946dd1de374Slin wang - Sun Microsystems - Beijing China "unable to restart recv logic\n"); 947dd1de374Slin wang - Sun Microsystems - Beijing China return (EIO); 948dd1de374Slin wang - Sun Microsystems - Beijing China } 949dd1de374Slin wang - Sun Microsystems - Beijing China 950dd1de374Slin wang - Sun Microsystems - Beijing China chan.ich_freq = hchan->channel; 951dd1de374Slin wang - Sun Microsystems - Beijing China chan.ich_flags = hchan->channelFlags; 952dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_ibss_chan = &chan; 953dd1de374Slin wang - Sun Microsystems - Beijing China 954dd1de374Slin wang - Sun Microsystems - Beijing China /* 955dd1de374Slin wang - Sun Microsystems - Beijing China * Change channels and update the h/w rate map 956dd1de374Slin wang - Sun Microsystems - Beijing China * if we're switching; e.g. 11a to 11b/g. 957dd1de374Slin wang - Sun Microsystems - Beijing China */ 958dd1de374Slin wang - Sun Microsystems - Beijing China curmode = arn_chan2mode(hchan); 959dd1de374Slin wang - Sun Microsystems - Beijing China if (curmode != sc->sc_curmode) 960dd1de374Slin wang - Sun Microsystems - Beijing China arn_setcurmode(sc, arn_chan2mode(hchan)); 961dd1de374Slin wang - Sun Microsystems - Beijing China 962dd1de374Slin wang - Sun Microsystems - Beijing China arn_update_txpow(sc); 963dd1de374Slin wang - Sun Microsystems - Beijing China 964dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_set_interrupts(ah, sc->sc_imask); 965dd1de374Slin wang - Sun Microsystems - Beijing China } 966dd1de374Slin wang - Sun Microsystems - Beijing China 967dd1de374Slin wang - Sun Microsystems - Beijing China return (0); 968dd1de374Slin wang - Sun Microsystems - Beijing China } 969dd1de374Slin wang - Sun Microsystems - Beijing China 970dd1de374Slin wang - Sun Microsystems - Beijing China /* 971dd1de374Slin wang - Sun Microsystems - Beijing China * This routine performs the periodic noise floor calibration function 972dd1de374Slin wang - Sun Microsystems - Beijing China * that is used to adjust and optimize the chip performance. This 973dd1de374Slin wang - Sun Microsystems - Beijing China * takes environmental changes (location, temperature) into account. 974dd1de374Slin wang - Sun Microsystems - Beijing China * When the task is complete, it reschedules itself depending on the 975dd1de374Slin wang - Sun Microsystems - Beijing China * appropriate interval that was calculated. 976dd1de374Slin wang - Sun Microsystems - Beijing China */ 977dd1de374Slin wang - Sun Microsystems - Beijing China static void 978dd1de374Slin wang - Sun Microsystems - Beijing China arn_ani_calibrate(void *arg) 979dd1de374Slin wang - Sun Microsystems - Beijing China 980dd1de374Slin wang - Sun Microsystems - Beijing China { 981dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211com_t *ic = (ieee80211com_t *)arg; 982dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = (struct arn_softc *)ic; 983dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_hal *ah = sc->sc_ah; 984dd1de374Slin wang - Sun Microsystems - Beijing China boolean_t longcal = B_FALSE; 985dd1de374Slin wang - Sun Microsystems - Beijing China boolean_t shortcal = B_FALSE; 986dd1de374Slin wang - Sun Microsystems - Beijing China boolean_t aniflag = B_FALSE; 987dd1de374Slin wang - Sun Microsystems - Beijing China unsigned int timestamp = drv_hztousec(ddi_get_lbolt())/1000; 988dd1de374Slin wang - Sun Microsystems - Beijing China uint32_t cal_interval; 989dd1de374Slin wang - Sun Microsystems - Beijing China 990dd1de374Slin wang - Sun Microsystems - Beijing China /* 991dd1de374Slin wang - Sun Microsystems - Beijing China * don't calibrate when we're scanning. 992dd1de374Slin wang - Sun Microsystems - Beijing China * we are most likely not on our home channel. 993dd1de374Slin wang - Sun Microsystems - Beijing China */ 994dd1de374Slin wang - Sun Microsystems - Beijing China if (ic->ic_state != IEEE80211_S_RUN) 995dd1de374Slin wang - Sun Microsystems - Beijing China goto settimer; 996dd1de374Slin wang - Sun Microsystems - Beijing China 997dd1de374Slin wang - Sun Microsystems - Beijing China /* Long calibration runs independently of short calibration. */ 998dd1de374Slin wang - Sun Microsystems - Beijing China if ((timestamp - sc->sc_ani.sc_longcal_timer) >= ATH_LONG_CALINTERVAL) { 999dd1de374Slin wang - Sun Microsystems - Beijing China longcal = B_TRUE; 1000dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_CALIBRATE, "arn: " 1001dd1de374Slin wang - Sun Microsystems - Beijing China "%s: longcal @%lu\n", __func__, drv_hztousec)); 1002dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_ani.sc_longcal_timer = timestamp; 1003dd1de374Slin wang - Sun Microsystems - Beijing China } 1004dd1de374Slin wang - Sun Microsystems - Beijing China 1005dd1de374Slin wang - Sun Microsystems - Beijing China /* Short calibration applies only while sc_caldone is FALSE */ 1006dd1de374Slin wang - Sun Microsystems - Beijing China if (!sc->sc_ani.sc_caldone) { 1007dd1de374Slin wang - Sun Microsystems - Beijing China if ((timestamp - sc->sc_ani.sc_shortcal_timer) >= 1008dd1de374Slin wang - Sun Microsystems - Beijing China ATH_SHORT_CALINTERVAL) { 1009dd1de374Slin wang - Sun Microsystems - Beijing China shortcal = B_TRUE; 1010dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_CALIBRATE, "arn: " 1011dd1de374Slin wang - Sun Microsystems - Beijing China "%s: shortcal @%lu\n", 1012dd1de374Slin wang - Sun Microsystems - Beijing China __func__, drv_hztousec)); 1013dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_ani.sc_shortcal_timer = timestamp; 1014dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_ani.sc_resetcal_timer = timestamp; 1015dd1de374Slin wang - Sun Microsystems - Beijing China } 1016dd1de374Slin wang - Sun Microsystems - Beijing China } else { 1017dd1de374Slin wang - Sun Microsystems - Beijing China if ((timestamp - sc->sc_ani.sc_resetcal_timer) >= 1018dd1de374Slin wang - Sun Microsystems - Beijing China ATH_RESTART_CALINTERVAL) { 1019dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_reset_calvalid(ah, ah->ah_curchan, 1020dd1de374Slin wang - Sun Microsystems - Beijing China &sc->sc_ani.sc_caldone); 1021dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_ani.sc_caldone) 1022dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_ani.sc_resetcal_timer = timestamp; 1023dd1de374Slin wang - Sun Microsystems - Beijing China } 1024dd1de374Slin wang - Sun Microsystems - Beijing China } 1025dd1de374Slin wang - Sun Microsystems - Beijing China 1026dd1de374Slin wang - Sun Microsystems - Beijing China /* Verify whether we must check ANI */ 1027dd1de374Slin wang - Sun Microsystems - Beijing China if ((timestamp - sc->sc_ani.sc_checkani_timer) >= 1028dd1de374Slin wang - Sun Microsystems - Beijing China ATH_ANI_POLLINTERVAL) { 1029dd1de374Slin wang - Sun Microsystems - Beijing China aniflag = B_TRUE; 1030dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_ani.sc_checkani_timer = timestamp; 1031dd1de374Slin wang - Sun Microsystems - Beijing China } 1032dd1de374Slin wang - Sun Microsystems - Beijing China 1033dd1de374Slin wang - Sun Microsystems - Beijing China /* Skip all processing if there's nothing to do. */ 1034dd1de374Slin wang - Sun Microsystems - Beijing China if (longcal || shortcal || aniflag) { 1035dd1de374Slin wang - Sun Microsystems - Beijing China /* Call ANI routine if necessary */ 1036dd1de374Slin wang - Sun Microsystems - Beijing China if (aniflag) 1037dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_ani_monitor(ah, &sc->sc_halstats, 1038dd1de374Slin wang - Sun Microsystems - Beijing China ah->ah_curchan); 1039dd1de374Slin wang - Sun Microsystems - Beijing China 1040dd1de374Slin wang - Sun Microsystems - Beijing China /* Perform calibration if necessary */ 1041dd1de374Slin wang - Sun Microsystems - Beijing China if (longcal || shortcal) { 1042dd1de374Slin wang - Sun Microsystems - Beijing China boolean_t iscaldone = B_FALSE; 1043dd1de374Slin wang - Sun Microsystems - Beijing China 1044dd1de374Slin wang - Sun Microsystems - Beijing China if (ath9k_hw_calibrate(ah, ah->ah_curchan, 1045dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_rx_chainmask, longcal, &iscaldone)) { 1046dd1de374Slin wang - Sun Microsystems - Beijing China if (longcal) 1047dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_ani.sc_noise_floor = 1048dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_getchan_noise(ah, 1049dd1de374Slin wang - Sun Microsystems - Beijing China ah->ah_curchan); 1050dd1de374Slin wang - Sun Microsystems - Beijing China 1051dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_CALIBRATE, "arn: " 1052dd1de374Slin wang - Sun Microsystems - Beijing China "%s: calibrate chan %u/%x nf: %d\n", 1053dd1de374Slin wang - Sun Microsystems - Beijing China __func__, 1054dd1de374Slin wang - Sun Microsystems - Beijing China ah->ah_curchan->channel, 1055dd1de374Slin wang - Sun Microsystems - Beijing China ah->ah_curchan->channelFlags, 1056dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_ani.sc_noise_floor)); 1057dd1de374Slin wang - Sun Microsystems - Beijing China } else { 1058dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_CALIBRATE, "arn: " 1059dd1de374Slin wang - Sun Microsystems - Beijing China "%s: calibrate chan %u/%x failed\n", 1060dd1de374Slin wang - Sun Microsystems - Beijing China __func__, 1061dd1de374Slin wang - Sun Microsystems - Beijing China ah->ah_curchan->channel, 1062dd1de374Slin wang - Sun Microsystems - Beijing China ah->ah_curchan->channelFlags)); 1063dd1de374Slin wang - Sun Microsystems - Beijing China } 1064dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_ani.sc_caldone = iscaldone; 1065dd1de374Slin wang - Sun Microsystems - Beijing China } 1066dd1de374Slin wang - Sun Microsystems - Beijing China } 1067dd1de374Slin wang - Sun Microsystems - Beijing China 1068dd1de374Slin wang - Sun Microsystems - Beijing China settimer: 1069dd1de374Slin wang - Sun Microsystems - Beijing China /* 1070dd1de374Slin wang - Sun Microsystems - Beijing China * Set timer interval based on previous results. 1071dd1de374Slin wang - Sun Microsystems - Beijing China * The interval must be the shortest necessary to satisfy ANI, 1072dd1de374Slin wang - Sun Microsystems - Beijing China * short calibration and long calibration. 1073dd1de374Slin wang - Sun Microsystems - Beijing China */ 1074dd1de374Slin wang - Sun Microsystems - Beijing China cal_interval = ATH_LONG_CALINTERVAL; 1075dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_ah->ah_config.enable_ani) 1076dd1de374Slin wang - Sun Microsystems - Beijing China cal_interval = 1077dd1de374Slin wang - Sun Microsystems - Beijing China min(cal_interval, (uint32_t)ATH_ANI_POLLINTERVAL); 1078dd1de374Slin wang - Sun Microsystems - Beijing China 1079dd1de374Slin wang - Sun Microsystems - Beijing China if (!sc->sc_ani.sc_caldone) 1080dd1de374Slin wang - Sun Microsystems - Beijing China cal_interval = min(cal_interval, 1081dd1de374Slin wang - Sun Microsystems - Beijing China (uint32_t)ATH_SHORT_CALINTERVAL); 1082dd1de374Slin wang - Sun Microsystems - Beijing China 1083dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_scan_timer = 0; 1084dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_scan_timer = timeout(arn_ani_calibrate, (void *)sc, 1085dd1de374Slin wang - Sun Microsystems - Beijing China drv_usectohz(cal_interval * 1000)); 1086dd1de374Slin wang - Sun Microsystems - Beijing China } 1087dd1de374Slin wang - Sun Microsystems - Beijing China 1088dd1de374Slin wang - Sun Microsystems - Beijing China static void 1089dd1de374Slin wang - Sun Microsystems - Beijing China arn_stop_caltimer(struct arn_softc *sc) 1090dd1de374Slin wang - Sun Microsystems - Beijing China { 1091dd1de374Slin wang - Sun Microsystems - Beijing China timeout_id_t tmp_id = 0; 1092dd1de374Slin wang - Sun Microsystems - Beijing China 1093dd1de374Slin wang - Sun Microsystems - Beijing China while ((sc->sc_cal_timer != 0) && (tmp_id != sc->sc_cal_timer)) { 1094dd1de374Slin wang - Sun Microsystems - Beijing China tmp_id = sc->sc_cal_timer; 1095dd1de374Slin wang - Sun Microsystems - Beijing China (void) untimeout(tmp_id); 1096dd1de374Slin wang - Sun Microsystems - Beijing China } 1097dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_cal_timer = 0; 1098dd1de374Slin wang - Sun Microsystems - Beijing China } 1099dd1de374Slin wang - Sun Microsystems - Beijing China 1100dd1de374Slin wang - Sun Microsystems - Beijing China static uint_t 1101dd1de374Slin wang - Sun Microsystems - Beijing China arn_isr(caddr_t arg) 1102dd1de374Slin wang - Sun Microsystems - Beijing China { 1103dd1de374Slin wang - Sun Microsystems - Beijing China /* LINTED E_BAD_PTR_CAST_ALIGN */ 1104dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = (struct arn_softc *)arg; 1105dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_hal *ah = sc->sc_ah; 1106dd1de374Slin wang - Sun Microsystems - Beijing China enum ath9k_int status; 1107dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211com_t *ic = (ieee80211com_t *)sc; 1108dd1de374Slin wang - Sun Microsystems - Beijing China 1109dd1de374Slin wang - Sun Microsystems - Beijing China ARN_LOCK(sc); 1110dd1de374Slin wang - Sun Microsystems - Beijing China 1111dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_flags & SC_OP_INVALID) { 1112dd1de374Slin wang - Sun Microsystems - Beijing China /* 1113dd1de374Slin wang - Sun Microsystems - Beijing China * The hardware is not ready/present, don't 1114dd1de374Slin wang - Sun Microsystems - Beijing China * touch anything. Note this can happen early 1115dd1de374Slin wang - Sun Microsystems - Beijing China * on if the IRQ is shared. 1116dd1de374Slin wang - Sun Microsystems - Beijing China */ 1117dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 1118dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_INTR_UNCLAIMED); 1119dd1de374Slin wang - Sun Microsystems - Beijing China } 1120dd1de374Slin wang - Sun Microsystems - Beijing China if (!ath9k_hw_intrpend(ah)) { /* shared irq, not for us */ 1121dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 1122dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_INTR_UNCLAIMED); 1123dd1de374Slin wang - Sun Microsystems - Beijing China } 1124dd1de374Slin wang - Sun Microsystems - Beijing China 1125dd1de374Slin wang - Sun Microsystems - Beijing China /* 1126dd1de374Slin wang - Sun Microsystems - Beijing China * Figure out the reason(s) for the interrupt. Note 1127dd1de374Slin wang - Sun Microsystems - Beijing China * that the hal returns a pseudo-ISR that may include 1128dd1de374Slin wang - Sun Microsystems - Beijing China * bits we haven't explicitly enabled so we mask the 1129dd1de374Slin wang - Sun Microsystems - Beijing China * value to insure we only process bits we requested. 1130dd1de374Slin wang - Sun Microsystems - Beijing China */ 1131dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */ 1132dd1de374Slin wang - Sun Microsystems - Beijing China 1133dd1de374Slin wang - Sun Microsystems - Beijing China status &= sc->sc_imask; /* discard unasked-for bits */ 1134dd1de374Slin wang - Sun Microsystems - Beijing China 1135dd1de374Slin wang - Sun Microsystems - Beijing China /* 1136dd1de374Slin wang - Sun Microsystems - Beijing China * If there are no status bits set, then this interrupt was not 1137dd1de374Slin wang - Sun Microsystems - Beijing China * for me (should have been caught above). 1138dd1de374Slin wang - Sun Microsystems - Beijing China */ 1139dd1de374Slin wang - Sun Microsystems - Beijing China if (!status) { 1140dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 1141dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_INTR_UNCLAIMED); 1142dd1de374Slin wang - Sun Microsystems - Beijing China } 1143dd1de374Slin wang - Sun Microsystems - Beijing China 1144dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_intrstatus = status; 1145dd1de374Slin wang - Sun Microsystems - Beijing China 1146dd1de374Slin wang - Sun Microsystems - Beijing China if (status & ATH9K_INT_FATAL) { 1147dd1de374Slin wang - Sun Microsystems - Beijing China /* need a chip reset */ 1148dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_INTERRUPT, "arn: arn_isr(): " 1149dd1de374Slin wang - Sun Microsystems - Beijing China "ATH9K_INT_FATAL\n")); 1150dd1de374Slin wang - Sun Microsystems - Beijing China goto reset; 1151dd1de374Slin wang - Sun Microsystems - Beijing China } else if (status & ATH9K_INT_RXORN) { 1152dd1de374Slin wang - Sun Microsystems - Beijing China /* need a chip reset */ 1153dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_INTERRUPT, "arn: arn_isr(): " 1154dd1de374Slin wang - Sun Microsystems - Beijing China "ATH9K_INT_RXORN\n")); 1155dd1de374Slin wang - Sun Microsystems - Beijing China goto reset; 1156dd1de374Slin wang - Sun Microsystems - Beijing China } else { 1157dd1de374Slin wang - Sun Microsystems - Beijing China if (status & ATH9K_INT_RXEOL) { 1158dd1de374Slin wang - Sun Microsystems - Beijing China /* 1159dd1de374Slin wang - Sun Microsystems - Beijing China * NB: the hardware should re-read the link when 1160dd1de374Slin wang - Sun Microsystems - Beijing China * RXE bit is written, but it doesn't work 1161dd1de374Slin wang - Sun Microsystems - Beijing China * at least on older hardware revs. 1162dd1de374Slin wang - Sun Microsystems - Beijing China */ 1163dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_INTERRUPT, "arn: arn_isr(): " 1164dd1de374Slin wang - Sun Microsystems - Beijing China "ATH9K_INT_RXEOL\n")); 1165dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_rxlink = NULL; 1166dd1de374Slin wang - Sun Microsystems - Beijing China } 1167dd1de374Slin wang - Sun Microsystems - Beijing China if (status & ATH9K_INT_TXURN) { 1168dd1de374Slin wang - Sun Microsystems - Beijing China /* bump tx trigger level */ 1169dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_INTERRUPT, "arn: arn_isr(): " 1170dd1de374Slin wang - Sun Microsystems - Beijing China "ATH9K_INT_TXURN\n")); 1171dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_updatetxtriglevel(ah, B_TRUE); 1172dd1de374Slin wang - Sun Microsystems - Beijing China } 1173dd1de374Slin wang - Sun Microsystems - Beijing China /* XXX: optimize this */ 1174dd1de374Slin wang - Sun Microsystems - Beijing China if (status & ATH9K_INT_RX) { 1175dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_INTERRUPT, "arn: arn_isr(): " 1176dd1de374Slin wang - Sun Microsystems - Beijing China "ATH9K_INT_RX\n")); 1177dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_rx_pend = 1; 1178dd1de374Slin wang - Sun Microsystems - Beijing China ddi_trigger_softintr(sc->sc_softint_id); 1179dd1de374Slin wang - Sun Microsystems - Beijing China } 1180dd1de374Slin wang - Sun Microsystems - Beijing China if (status & ATH9K_INT_TX) { 1181dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_INTERRUPT, "arn: arn_isr(): " 1182dd1de374Slin wang - Sun Microsystems - Beijing China "ATH9K_INT_TX\n")); 1183dd1de374Slin wang - Sun Microsystems - Beijing China if (ddi_taskq_dispatch(sc->sc_tq, 1184dd1de374Slin wang - Sun Microsystems - Beijing China arn_tx_int_proc, sc, DDI_NOSLEEP) != 1185dd1de374Slin wang - Sun Microsystems - Beijing China DDI_SUCCESS) { 1186dd1de374Slin wang - Sun Microsystems - Beijing China arn_problem("arn: arn_isr(): " 1187dd1de374Slin wang - Sun Microsystems - Beijing China "No memory for tx taskq\n"); 1188dd1de374Slin wang - Sun Microsystems - Beijing China } 1189dd1de374Slin wang - Sun Microsystems - Beijing China } 1190dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_ATH9K_INT_MIB 1191dd1de374Slin wang - Sun Microsystems - Beijing China if (status & ATH9K_INT_MIB) { 1192dd1de374Slin wang - Sun Microsystems - Beijing China /* 1193dd1de374Slin wang - Sun Microsystems - Beijing China * Disable interrupts until we service the MIB 1194dd1de374Slin wang - Sun Microsystems - Beijing China * interrupt; otherwise it will continue to 1195dd1de374Slin wang - Sun Microsystems - Beijing China * fire. 1196dd1de374Slin wang - Sun Microsystems - Beijing China */ 1197dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_set_interrupts(ah, 0); 1198dd1de374Slin wang - Sun Microsystems - Beijing China /* 1199dd1de374Slin wang - Sun Microsystems - Beijing China * Let the hal handle the event. We assume 1200dd1de374Slin wang - Sun Microsystems - Beijing China * it will clear whatever condition caused 1201dd1de374Slin wang - Sun Microsystems - Beijing China * the interrupt. 1202dd1de374Slin wang - Sun Microsystems - Beijing China */ 1203dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_procmibevent(ah, &sc->sc_halstats); 1204dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_set_interrupts(ah, sc->sc_imask); 1205dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_INTERRUPT, "arn: arn_isr(): " 1206dd1de374Slin wang - Sun Microsystems - Beijing China "ATH9K_INT_MIB\n")); 1207dd1de374Slin wang - Sun Microsystems - Beijing China } 1208dd1de374Slin wang - Sun Microsystems - Beijing China #endif 1209dd1de374Slin wang - Sun Microsystems - Beijing China 1210dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_ATH9K_INT_TIM_TIMER 1211dd1de374Slin wang - Sun Microsystems - Beijing China if (status & ATH9K_INT_TIM_TIMER) { 1212dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_INTERRUPT, "arn: arn_isr(): " 1213dd1de374Slin wang - Sun Microsystems - Beijing China "ATH9K_INT_TIM_TIMER\n")); 1214dd1de374Slin wang - Sun Microsystems - Beijing China if (!(ah->ah_caps.hw_caps & 1215dd1de374Slin wang - Sun Microsystems - Beijing China ATH9K_HW_CAP_AUTOSLEEP)) { 1216dd1de374Slin wang - Sun Microsystems - Beijing China /* 1217dd1de374Slin wang - Sun Microsystems - Beijing China * Clear RxAbort bit so that we can 1218dd1de374Slin wang - Sun Microsystems - Beijing China * receive frames 1219dd1de374Slin wang - Sun Microsystems - Beijing China */ 1220dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_setrxabort(ah, 0); 1221dd1de374Slin wang - Sun Microsystems - Beijing China goto reset; 1222dd1de374Slin wang - Sun Microsystems - Beijing China } 1223dd1de374Slin wang - Sun Microsystems - Beijing China } 1224dd1de374Slin wang - Sun Microsystems - Beijing China #endif 1225dd1de374Slin wang - Sun Microsystems - Beijing China 1226dd1de374Slin wang - Sun Microsystems - Beijing China if (status & ATH9K_INT_BMISS) { 1227dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_INTERRUPT, "arn: arn_isr(): " 1228dd1de374Slin wang - Sun Microsystems - Beijing China "ATH9K_INT_BMISS\n")); 1229c0c93480Slin wang - Sun Microsystems - Beijing China #ifdef ARN_HW_BEACON_MISS_HANDLE 12303ae945c3Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_INTERRUPT, "arn: arn_isr(): " 12313ae945c3Slin wang - Sun Microsystems - Beijing China "handle beacon mmiss by H/W mechanism\n")); 1232dd1de374Slin wang - Sun Microsystems - Beijing China if (ddi_taskq_dispatch(sc->sc_tq, arn_bmiss_proc, 1233dd1de374Slin wang - Sun Microsystems - Beijing China sc, DDI_NOSLEEP) != DDI_SUCCESS) { 1234dd1de374Slin wang - Sun Microsystems - Beijing China arn_problem("arn: arn_isr(): " 1235dd1de374Slin wang - Sun Microsystems - Beijing China "No memory available for bmiss taskq\n"); 1236dd1de374Slin wang - Sun Microsystems - Beijing China } 12373ae945c3Slin wang - Sun Microsystems - Beijing China #else 12383ae945c3Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_INTERRUPT, "arn: arn_isr(): " 12393ae945c3Slin wang - Sun Microsystems - Beijing China "handle beacon mmiss by S/W mechanism\n")); 1240c0c93480Slin wang - Sun Microsystems - Beijing China #endif /* ARN_HW_BEACON_MISS_HANDLE */ 1241dd1de374Slin wang - Sun Microsystems - Beijing China } 1242dd1de374Slin wang - Sun Microsystems - Beijing China 1243dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 1244dd1de374Slin wang - Sun Microsystems - Beijing China 1245dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_ATH9K_INT_CST 1246dd1de374Slin wang - Sun Microsystems - Beijing China /* carrier sense timeout */ 1247dd1de374Slin wang - Sun Microsystems - Beijing China if (status & ATH9K_INT_CST) { 1248dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_INTERRUPT, "arn: arn_isr(): " 1249dd1de374Slin wang - Sun Microsystems - Beijing China "ATH9K_INT_CST\n")); 1250dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_INTR_CLAIMED); 1251dd1de374Slin wang - Sun Microsystems - Beijing China } 1252dd1de374Slin wang - Sun Microsystems - Beijing China #endif 1253dd1de374Slin wang - Sun Microsystems - Beijing China 1254dd1de374Slin wang - Sun Microsystems - Beijing China if (status & ATH9K_INT_SWBA) { 1255dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_INTERRUPT, "arn: arn_isr(): " 1256dd1de374Slin wang - Sun Microsystems - Beijing China "ATH9K_INT_SWBA\n")); 1257dd1de374Slin wang - Sun Microsystems - Beijing China /* This will occur only in Host-AP or Ad-Hoc mode */ 1258dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_INTR_CLAIMED); 1259dd1de374Slin wang - Sun Microsystems - Beijing China } 1260dd1de374Slin wang - Sun Microsystems - Beijing China } 1261dd1de374Slin wang - Sun Microsystems - Beijing China 1262dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_INTR_CLAIMED); 1263dd1de374Slin wang - Sun Microsystems - Beijing China reset: 1264dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_INTERRUPT, "Rset for fatal err\n")); 1265dd1de374Slin wang - Sun Microsystems - Beijing China (void) arn_reset(ic); 1266dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 1267dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_INTR_CLAIMED); 1268dd1de374Slin wang - Sun Microsystems - Beijing China } 1269dd1de374Slin wang - Sun Microsystems - Beijing China 1270dd1de374Slin wang - Sun Microsystems - Beijing China static int 1271dd1de374Slin wang - Sun Microsystems - Beijing China arn_get_channel(struct arn_softc *sc, struct ieee80211_channel *chan) 1272dd1de374Slin wang - Sun Microsystems - Beijing China { 1273dd1de374Slin wang - Sun Microsystems - Beijing China int i; 1274dd1de374Slin wang - Sun Microsystems - Beijing China 1275dd1de374Slin wang - Sun Microsystems - Beijing China for (i = 0; i < sc->sc_ah->ah_nchan; i++) { 1276dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_ah->ah_channels[i].channel == chan->ich_freq) 1277dd1de374Slin wang - Sun Microsystems - Beijing China return (i); 1278dd1de374Slin wang - Sun Microsystems - Beijing China } 1279dd1de374Slin wang - Sun Microsystems - Beijing China 1280dd1de374Slin wang - Sun Microsystems - Beijing China return (-1); 1281dd1de374Slin wang - Sun Microsystems - Beijing China } 1282dd1de374Slin wang - Sun Microsystems - Beijing China 1283dd1de374Slin wang - Sun Microsystems - Beijing China int 1284dd1de374Slin wang - Sun Microsystems - Beijing China arn_reset(ieee80211com_t *ic) 1285dd1de374Slin wang - Sun Microsystems - Beijing China { 1286dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = (struct arn_softc *)ic; 1287dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_hal *ah = sc->sc_ah; 1288dd1de374Slin wang - Sun Microsystems - Beijing China int status; 1289dd1de374Slin wang - Sun Microsystems - Beijing China int error = 0; 1290dd1de374Slin wang - Sun Microsystems - Beijing China 1291dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_set_interrupts(ah, 0); 1292dd1de374Slin wang - Sun Microsystems - Beijing China arn_draintxq(sc, 0); 1293dd1de374Slin wang - Sun Microsystems - Beijing China (void) arn_stoprecv(sc); 1294dd1de374Slin wang - Sun Microsystems - Beijing China 1295dd1de374Slin wang - Sun Microsystems - Beijing China if (!ath9k_hw_reset(ah, sc->sc_ah->ah_curchan, sc->tx_chan_width, 1296dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_tx_chainmask, sc->sc_rx_chainmask, 1297dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_ht_extprotspacing, B_FALSE, &status)) { 1298dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_RESET, "arn: arn_reset(): " 1299dd1de374Slin wang - Sun Microsystems - Beijing China "unable to reset hardware; hal status %u\n", status)); 1300dd1de374Slin wang - Sun Microsystems - Beijing China error = EIO; 1301dd1de374Slin wang - Sun Microsystems - Beijing China } 1302dd1de374Slin wang - Sun Microsystems - Beijing China 1303dd1de374Slin wang - Sun Microsystems - Beijing China if (arn_startrecv(sc) != 0) 1304dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_RESET, "arn: arn_reset(): " 1305dd1de374Slin wang - Sun Microsystems - Beijing China "unable to start recv logic\n")); 1306dd1de374Slin wang - Sun Microsystems - Beijing China 1307dd1de374Slin wang - Sun Microsystems - Beijing China /* 1308dd1de374Slin wang - Sun Microsystems - Beijing China * We may be doing a reset in response to a request 1309dd1de374Slin wang - Sun Microsystems - Beijing China * that changes the channel so update any state that 1310dd1de374Slin wang - Sun Microsystems - Beijing China * might change as a result. 1311dd1de374Slin wang - Sun Microsystems - Beijing China */ 1312dd1de374Slin wang - Sun Microsystems - Beijing China arn_setcurmode(sc, arn_chan2mode(sc->sc_ah->ah_curchan)); 1313dd1de374Slin wang - Sun Microsystems - Beijing China 1314dd1de374Slin wang - Sun Microsystems - Beijing China arn_update_txpow(sc); 1315dd1de374Slin wang - Sun Microsystems - Beijing China 1316dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_flags & SC_OP_BEACONS) 1317dd1de374Slin wang - Sun Microsystems - Beijing China arn_beacon_config(sc); /* restart beacons */ 1318dd1de374Slin wang - Sun Microsystems - Beijing China 1319dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_set_interrupts(ah, sc->sc_imask); 1320dd1de374Slin wang - Sun Microsystems - Beijing China 1321dd1de374Slin wang - Sun Microsystems - Beijing China return (error); 1322dd1de374Slin wang - Sun Microsystems - Beijing China } 1323dd1de374Slin wang - Sun Microsystems - Beijing China 1324dd1de374Slin wang - Sun Microsystems - Beijing China int 1325dd1de374Slin wang - Sun Microsystems - Beijing China arn_get_hal_qnum(uint16_t queue, struct arn_softc *sc) 1326dd1de374Slin wang - Sun Microsystems - Beijing China { 1327dd1de374Slin wang - Sun Microsystems - Beijing China int qnum; 1328dd1de374Slin wang - Sun Microsystems - Beijing China 1329dd1de374Slin wang - Sun Microsystems - Beijing China switch (queue) { 1330dd1de374Slin wang - Sun Microsystems - Beijing China case WME_AC_VO: 1331dd1de374Slin wang - Sun Microsystems - Beijing China qnum = sc->sc_haltype2q[ATH9K_WME_AC_VO]; 1332dd1de374Slin wang - Sun Microsystems - Beijing China break; 1333dd1de374Slin wang - Sun Microsystems - Beijing China case WME_AC_VI: 1334dd1de374Slin wang - Sun Microsystems - Beijing China qnum = sc->sc_haltype2q[ATH9K_WME_AC_VI]; 1335dd1de374Slin wang - Sun Microsystems - Beijing China break; 1336dd1de374Slin wang - Sun Microsystems - Beijing China case WME_AC_BE: 1337dd1de374Slin wang - Sun Microsystems - Beijing China qnum = sc->sc_haltype2q[ATH9K_WME_AC_BE]; 1338dd1de374Slin wang - Sun Microsystems - Beijing China break; 1339dd1de374Slin wang - Sun Microsystems - Beijing China case WME_AC_BK: 1340dd1de374Slin wang - Sun Microsystems - Beijing China qnum = sc->sc_haltype2q[ATH9K_WME_AC_BK]; 1341dd1de374Slin wang - Sun Microsystems - Beijing China break; 1342dd1de374Slin wang - Sun Microsystems - Beijing China default: 1343dd1de374Slin wang - Sun Microsystems - Beijing China qnum = sc->sc_haltype2q[ATH9K_WME_AC_BE]; 1344dd1de374Slin wang - Sun Microsystems - Beijing China break; 1345dd1de374Slin wang - Sun Microsystems - Beijing China } 1346dd1de374Slin wang - Sun Microsystems - Beijing China 1347dd1de374Slin wang - Sun Microsystems - Beijing China return (qnum); 1348dd1de374Slin wang - Sun Microsystems - Beijing China } 1349dd1de374Slin wang - Sun Microsystems - Beijing China 1350dd1de374Slin wang - Sun Microsystems - Beijing China static struct { 1351dd1de374Slin wang - Sun Microsystems - Beijing China uint32_t version; 1352dd1de374Slin wang - Sun Microsystems - Beijing China const char *name; 1353dd1de374Slin wang - Sun Microsystems - Beijing China } ath_mac_bb_names[] = { 1354dd1de374Slin wang - Sun Microsystems - Beijing China { AR_SREV_VERSION_5416_PCI, "5416" }, 1355dd1de374Slin wang - Sun Microsystems - Beijing China { AR_SREV_VERSION_5416_PCIE, "5418" }, 1356dd1de374Slin wang - Sun Microsystems - Beijing China { AR_SREV_VERSION_9100, "9100" }, 1357dd1de374Slin wang - Sun Microsystems - Beijing China { AR_SREV_VERSION_9160, "9160" }, 1358dd1de374Slin wang - Sun Microsystems - Beijing China { AR_SREV_VERSION_9280, "9280" }, 1359dd1de374Slin wang - Sun Microsystems - Beijing China { AR_SREV_VERSION_9285, "9285" } 1360dd1de374Slin wang - Sun Microsystems - Beijing China }; 1361dd1de374Slin wang - Sun Microsystems - Beijing China 1362dd1de374Slin wang - Sun Microsystems - Beijing China static struct { 1363dd1de374Slin wang - Sun Microsystems - Beijing China uint16_t version; 1364dd1de374Slin wang - Sun Microsystems - Beijing China const char *name; 1365dd1de374Slin wang - Sun Microsystems - Beijing China } ath_rf_names[] = { 1366dd1de374Slin wang - Sun Microsystems - Beijing China { 0, "5133" }, 1367dd1de374Slin wang - Sun Microsystems - Beijing China { AR_RAD5133_SREV_MAJOR, "5133" }, 1368dd1de374Slin wang - Sun Microsystems - Beijing China { AR_RAD5122_SREV_MAJOR, "5122" }, 1369dd1de374Slin wang - Sun Microsystems - Beijing China { AR_RAD2133_SREV_MAJOR, "2133" }, 1370dd1de374Slin wang - Sun Microsystems - Beijing China { AR_RAD2122_SREV_MAJOR, "2122" } 1371dd1de374Slin wang - Sun Microsystems - Beijing China }; 1372dd1de374Slin wang - Sun Microsystems - Beijing China 1373dd1de374Slin wang - Sun Microsystems - Beijing China /* 1374dd1de374Slin wang - Sun Microsystems - Beijing China * Return the MAC/BB name. "????" is returned if the MAC/BB is unknown. 1375dd1de374Slin wang - Sun Microsystems - Beijing China */ 1376dd1de374Slin wang - Sun Microsystems - Beijing China 1377dd1de374Slin wang - Sun Microsystems - Beijing China static const char * 1378dd1de374Slin wang - Sun Microsystems - Beijing China arn_mac_bb_name(uint32_t mac_bb_version) 1379dd1de374Slin wang - Sun Microsystems - Beijing China { 1380dd1de374Slin wang - Sun Microsystems - Beijing China int i; 1381dd1de374Slin wang - Sun Microsystems - Beijing China 1382dd1de374Slin wang - Sun Microsystems - Beijing China for (i = 0; i < ARRAY_SIZE(ath_mac_bb_names); i++) { 1383dd1de374Slin wang - Sun Microsystems - Beijing China if (ath_mac_bb_names[i].version == mac_bb_version) { 1384dd1de374Slin wang - Sun Microsystems - Beijing China return (ath_mac_bb_names[i].name); 1385dd1de374Slin wang - Sun Microsystems - Beijing China } 1386dd1de374Slin wang - Sun Microsystems - Beijing China } 1387dd1de374Slin wang - Sun Microsystems - Beijing China 1388dd1de374Slin wang - Sun Microsystems - Beijing China return ("????"); 1389dd1de374Slin wang - Sun Microsystems - Beijing China } 1390dd1de374Slin wang - Sun Microsystems - Beijing China 1391dd1de374Slin wang - Sun Microsystems - Beijing China /* 1392dd1de374Slin wang - Sun Microsystems - Beijing China * Return the RF name. "????" is returned if the RF is unknown. 1393dd1de374Slin wang - Sun Microsystems - Beijing China */ 1394dd1de374Slin wang - Sun Microsystems - Beijing China 1395dd1de374Slin wang - Sun Microsystems - Beijing China static const char * 1396dd1de374Slin wang - Sun Microsystems - Beijing China arn_rf_name(uint16_t rf_version) 1397dd1de374Slin wang - Sun Microsystems - Beijing China { 1398dd1de374Slin wang - Sun Microsystems - Beijing China int i; 1399dd1de374Slin wang - Sun Microsystems - Beijing China 1400dd1de374Slin wang - Sun Microsystems - Beijing China for (i = 0; i < ARRAY_SIZE(ath_rf_names); i++) { 1401dd1de374Slin wang - Sun Microsystems - Beijing China if (ath_rf_names[i].version == rf_version) { 1402dd1de374Slin wang - Sun Microsystems - Beijing China return (ath_rf_names[i].name); 1403dd1de374Slin wang - Sun Microsystems - Beijing China } 1404dd1de374Slin wang - Sun Microsystems - Beijing China } 1405dd1de374Slin wang - Sun Microsystems - Beijing China 1406dd1de374Slin wang - Sun Microsystems - Beijing China return ("????"); 1407dd1de374Slin wang - Sun Microsystems - Beijing China } 1408dd1de374Slin wang - Sun Microsystems - Beijing China 1409dd1de374Slin wang - Sun Microsystems - Beijing China static void 1410dd1de374Slin wang - Sun Microsystems - Beijing China arn_next_scan(void *arg) 1411dd1de374Slin wang - Sun Microsystems - Beijing China { 1412dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211com_t *ic = arg; 1413dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = (struct arn_softc *)ic; 1414dd1de374Slin wang - Sun Microsystems - Beijing China 1415dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_scan_timer = 0; 1416dd1de374Slin wang - Sun Microsystems - Beijing China if (ic->ic_state == IEEE80211_S_SCAN) { 1417dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_scan_timer = timeout(arn_next_scan, (void *)sc, 1418dd1de374Slin wang - Sun Microsystems - Beijing China drv_usectohz(arn_dwelltime * 1000)); 1419dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211_next_scan(ic); 1420dd1de374Slin wang - Sun Microsystems - Beijing China } 1421dd1de374Slin wang - Sun Microsystems - Beijing China } 1422dd1de374Slin wang - Sun Microsystems - Beijing China 1423dd1de374Slin wang - Sun Microsystems - Beijing China static void 1424dd1de374Slin wang - Sun Microsystems - Beijing China arn_stop_scantimer(struct arn_softc *sc) 1425dd1de374Slin wang - Sun Microsystems - Beijing China { 1426dd1de374Slin wang - Sun Microsystems - Beijing China timeout_id_t tmp_id = 0; 1427dd1de374Slin wang - Sun Microsystems - Beijing China 1428dd1de374Slin wang - Sun Microsystems - Beijing China while ((sc->sc_scan_timer != 0) && (tmp_id != sc->sc_scan_timer)) { 1429dd1de374Slin wang - Sun Microsystems - Beijing China tmp_id = sc->sc_scan_timer; 1430dd1de374Slin wang - Sun Microsystems - Beijing China (void) untimeout(tmp_id); 1431dd1de374Slin wang - Sun Microsystems - Beijing China } 1432dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_scan_timer = 0; 1433dd1de374Slin wang - Sun Microsystems - Beijing China } 1434dd1de374Slin wang - Sun Microsystems - Beijing China 1435dd1de374Slin wang - Sun Microsystems - Beijing China static int32_t 1436dd1de374Slin wang - Sun Microsystems - Beijing China arn_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg) 1437dd1de374Slin wang - Sun Microsystems - Beijing China { 1438dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = (struct arn_softc *)ic; 1439dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_hal *ah = sc->sc_ah; 1440dd1de374Slin wang - Sun Microsystems - Beijing China struct ieee80211_node *in; 1441dd1de374Slin wang - Sun Microsystems - Beijing China int32_t i, error; 1442dd1de374Slin wang - Sun Microsystems - Beijing China uint8_t *bssid; 1443dd1de374Slin wang - Sun Microsystems - Beijing China uint32_t rfilt; 1444dd1de374Slin wang - Sun Microsystems - Beijing China enum ieee80211_state ostate; 1445dd1de374Slin wang - Sun Microsystems - Beijing China struct ath9k_channel *channel; 1446dd1de374Slin wang - Sun Microsystems - Beijing China int pos; 1447dd1de374Slin wang - Sun Microsystems - Beijing China 1448dd1de374Slin wang - Sun Microsystems - Beijing China /* Should set up & init LED here */ 1449dd1de374Slin wang - Sun Microsystems - Beijing China 1450dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_flags & SC_OP_INVALID) 1451dd1de374Slin wang - Sun Microsystems - Beijing China return (0); 1452dd1de374Slin wang - Sun Microsystems - Beijing China 1453dd1de374Slin wang - Sun Microsystems - Beijing China ostate = ic->ic_state; 1454dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_INIT, "arn: arn_newstate(): " 1455dd1de374Slin wang - Sun Microsystems - Beijing China "%x -> %x!\n", ostate, nstate)); 1456dd1de374Slin wang - Sun Microsystems - Beijing China 1457dd1de374Slin wang - Sun Microsystems - Beijing China ARN_LOCK(sc); 1458dd1de374Slin wang - Sun Microsystems - Beijing China 1459dd1de374Slin wang - Sun Microsystems - Beijing China if (nstate != IEEE80211_S_SCAN) 1460dd1de374Slin wang - Sun Microsystems - Beijing China arn_stop_scantimer(sc); 1461dd1de374Slin wang - Sun Microsystems - Beijing China if (nstate != IEEE80211_S_RUN) 1462dd1de374Slin wang - Sun Microsystems - Beijing China arn_stop_caltimer(sc); 1463dd1de374Slin wang - Sun Microsystems - Beijing China 1464dd1de374Slin wang - Sun Microsystems - Beijing China /* Should set LED here */ 1465dd1de374Slin wang - Sun Microsystems - Beijing China 1466dd1de374Slin wang - Sun Microsystems - Beijing China if (nstate == IEEE80211_S_INIT) { 1467dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); 1468dd1de374Slin wang - Sun Microsystems - Beijing China /* 1469dd1de374Slin wang - Sun Microsystems - Beijing China * Disable interrupts. 1470dd1de374Slin wang - Sun Microsystems - Beijing China */ 1471dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_set_interrupts 1472dd1de374Slin wang - Sun Microsystems - Beijing China (ah, sc->sc_imask &~ ATH9K_INT_GLOBAL); 1473dd1de374Slin wang - Sun Microsystems - Beijing China 1474dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_IBSS 1475dd1de374Slin wang - Sun Microsystems - Beijing China if (ic->ic_opmode == IEEE80211_M_IBSS) { 1476dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_stoptxdma(ah, sc->sc_beaconq); 1477dd1de374Slin wang - Sun Microsystems - Beijing China arn_beacon_return(sc); 1478dd1de374Slin wang - Sun Microsystems - Beijing China } 1479dd1de374Slin wang - Sun Microsystems - Beijing China #endif 1480dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 1481dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211_stop_watchdog(ic); 1482dd1de374Slin wang - Sun Microsystems - Beijing China goto done; 1483dd1de374Slin wang - Sun Microsystems - Beijing China } 1484dd1de374Slin wang - Sun Microsystems - Beijing China in = ic->ic_bss; 1485dd1de374Slin wang - Sun Microsystems - Beijing China 1486dd1de374Slin wang - Sun Microsystems - Beijing China pos = arn_get_channel(sc, ic->ic_curchan); 1487dd1de374Slin wang - Sun Microsystems - Beijing China 1488dd1de374Slin wang - Sun Microsystems - Beijing China if (pos == -1) { 1489dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_FATAL, "arn: " 1490dd1de374Slin wang - Sun Microsystems - Beijing China "%s: Invalid channel\n", __func__)); 1491dd1de374Slin wang - Sun Microsystems - Beijing China error = EINVAL; 1492dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 1493dd1de374Slin wang - Sun Microsystems - Beijing China goto bad; 1494dd1de374Slin wang - Sun Microsystems - Beijing China } 1495c0c93480Slin wang - Sun Microsystems - Beijing China 1496c0c93480Slin wang - Sun Microsystems - Beijing China if (in->in_htcap & IEEE80211_HTCAP_CHWIDTH40) { 1497c0c93480Slin wang - Sun Microsystems - Beijing China arn_update_chainmask(sc); 1498c0c93480Slin wang - Sun Microsystems - Beijing China sc->tx_chan_width = ATH9K_HT_MACMODE_2040; 1499c0c93480Slin wang - Sun Microsystems - Beijing China } else 1500dd1de374Slin wang - Sun Microsystems - Beijing China sc->tx_chan_width = ATH9K_HT_MACMODE_20; 1501c0c93480Slin wang - Sun Microsystems - Beijing China 1502dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_ah->ah_channels[pos].chanmode = 1503dd1de374Slin wang - Sun Microsystems - Beijing China arn_chan2flags(ic, ic->ic_curchan); 1504dd1de374Slin wang - Sun Microsystems - Beijing China channel = &sc->sc_ah->ah_channels[pos]; 1505dd1de374Slin wang - Sun Microsystems - Beijing China if (channel == NULL) { 1506dd1de374Slin wang - Sun Microsystems - Beijing China arn_problem("arn_newstate(): channel == NULL"); 1507dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 1508dd1de374Slin wang - Sun Microsystems - Beijing China goto bad; 1509dd1de374Slin wang - Sun Microsystems - Beijing China } 1510dd1de374Slin wang - Sun Microsystems - Beijing China error = arn_set_channel(sc, channel); 1511dd1de374Slin wang - Sun Microsystems - Beijing China if (error != 0) { 1512dd1de374Slin wang - Sun Microsystems - Beijing China if (nstate != IEEE80211_S_SCAN) { 1513dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 1514dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211_reset_chan(ic); 1515dd1de374Slin wang - Sun Microsystems - Beijing China goto bad; 1516dd1de374Slin wang - Sun Microsystems - Beijing China } 1517dd1de374Slin wang - Sun Microsystems - Beijing China } 1518dd1de374Slin wang - Sun Microsystems - Beijing China 1519dd1de374Slin wang - Sun Microsystems - Beijing China /* 1520dd1de374Slin wang - Sun Microsystems - Beijing China * Get the receive filter according to the 1521dd1de374Slin wang - Sun Microsystems - Beijing China * operating mode and state 1522dd1de374Slin wang - Sun Microsystems - Beijing China */ 1523dd1de374Slin wang - Sun Microsystems - Beijing China rfilt = arn_calcrxfilter(sc); 1524dd1de374Slin wang - Sun Microsystems - Beijing China 1525dd1de374Slin wang - Sun Microsystems - Beijing China if (nstate == IEEE80211_S_SCAN) 1526dd1de374Slin wang - Sun Microsystems - Beijing China bssid = ic->ic_macaddr; 1527dd1de374Slin wang - Sun Microsystems - Beijing China else 1528dd1de374Slin wang - Sun Microsystems - Beijing China bssid = in->in_bssid; 1529dd1de374Slin wang - Sun Microsystems - Beijing China 1530dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_setrxfilter(ah, rfilt); 1531dd1de374Slin wang - Sun Microsystems - Beijing China 1532dd1de374Slin wang - Sun Microsystems - Beijing China if (nstate == IEEE80211_S_RUN && ic->ic_opmode != IEEE80211_M_IBSS) 1533dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_write_associd(ah, bssid, in->in_associd); 1534dd1de374Slin wang - Sun Microsystems - Beijing China else 1535dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_write_associd(ah, bssid, 0); 1536dd1de374Slin wang - Sun Microsystems - Beijing China 1537dd1de374Slin wang - Sun Microsystems - Beijing China /* Check for WLAN_CAPABILITY_PRIVACY ? */ 1538dd1de374Slin wang - Sun Microsystems - Beijing China if (ic->ic_flags & IEEE80211_F_PRIVACY) { 1539dd1de374Slin wang - Sun Microsystems - Beijing China for (i = 0; i < IEEE80211_WEP_NKID; i++) { 1540dd1de374Slin wang - Sun Microsystems - Beijing China if (ath9k_hw_keyisvalid(ah, (uint16_t)i)) 1541dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_keysetmac(ah, (uint16_t)i, 1542dd1de374Slin wang - Sun Microsystems - Beijing China bssid); 1543dd1de374Slin wang - Sun Microsystems - Beijing China } 1544dd1de374Slin wang - Sun Microsystems - Beijing China } 1545dd1de374Slin wang - Sun Microsystems - Beijing China 1546dd1de374Slin wang - Sun Microsystems - Beijing China if (nstate == IEEE80211_S_RUN) { 1547dd1de374Slin wang - Sun Microsystems - Beijing China switch (ic->ic_opmode) { 1548dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_IBSS 1549dd1de374Slin wang - Sun Microsystems - Beijing China case IEEE80211_M_IBSS: 1550dd1de374Slin wang - Sun Microsystems - Beijing China /* 1551dd1de374Slin wang - Sun Microsystems - Beijing China * Allocate and setup the beacon frame. 1552dd1de374Slin wang - Sun Microsystems - Beijing China * Stop any previous beacon DMA. 1553dd1de374Slin wang - Sun Microsystems - Beijing China */ 1554dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_stoptxdma(ah, sc->sc_beaconq); 1555dd1de374Slin wang - Sun Microsystems - Beijing China arn_beacon_return(sc); 1556dd1de374Slin wang - Sun Microsystems - Beijing China error = arn_beacon_alloc(sc, in); 1557dd1de374Slin wang - Sun Microsystems - Beijing China if (error != 0) { 1558dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 1559dd1de374Slin wang - Sun Microsystems - Beijing China goto bad; 1560dd1de374Slin wang - Sun Microsystems - Beijing China } 1561dd1de374Slin wang - Sun Microsystems - Beijing China /* 1562dd1de374Slin wang - Sun Microsystems - Beijing China * If joining an adhoc network defer beacon timer 1563dd1de374Slin wang - Sun Microsystems - Beijing China * configuration to the next beacon frame so we 1564dd1de374Slin wang - Sun Microsystems - Beijing China * have a current TSF to use. Otherwise we're 1565dd1de374Slin wang - Sun Microsystems - Beijing China * starting an ibss/bss so there's no need to delay. 1566dd1de374Slin wang - Sun Microsystems - Beijing China */ 1567dd1de374Slin wang - Sun Microsystems - Beijing China if (ic->ic_opmode == IEEE80211_M_IBSS && 1568dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_bss->in_tstamp.tsf != 0) { 1569dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_bsync = 1; 1570dd1de374Slin wang - Sun Microsystems - Beijing China } else { 1571dd1de374Slin wang - Sun Microsystems - Beijing China arn_beacon_config(sc); 1572dd1de374Slin wang - Sun Microsystems - Beijing China } 1573dd1de374Slin wang - Sun Microsystems - Beijing China break; 1574dd1de374Slin wang - Sun Microsystems - Beijing China #endif /* ARN_IBSS */ 1575dd1de374Slin wang - Sun Microsystems - Beijing China case IEEE80211_M_STA: 1576dd1de374Slin wang - Sun Microsystems - Beijing China if (ostate != IEEE80211_S_RUN) { 1577dd1de374Slin wang - Sun Microsystems - Beijing China /* 1578dd1de374Slin wang - Sun Microsystems - Beijing China * Defer beacon timer configuration to the next 1579dd1de374Slin wang - Sun Microsystems - Beijing China * beacon frame so we have a current TSF to use. 1580dd1de374Slin wang - Sun Microsystems - Beijing China * Any TSF collected when scanning is likely old 1581dd1de374Slin wang - Sun Microsystems - Beijing China */ 1582dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_IBSS 1583dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_bsync = 1; 1584dd1de374Slin wang - Sun Microsystems - Beijing China #else 1585dd1de374Slin wang - Sun Microsystems - Beijing China /* Configure the beacon and sleep timers. */ 1586dd1de374Slin wang - Sun Microsystems - Beijing China arn_beacon_config(sc); 1587c0c93480Slin wang - Sun Microsystems - Beijing China /* Reset rssi stats */ 15883ae945c3Slin wang - Sun Microsystems - Beijing China sc->sc_halstats.ns_avgbrssi = 15893ae945c3Slin wang - Sun Microsystems - Beijing China ATH_RSSI_DUMMY_MARKER; 15903ae945c3Slin wang - Sun Microsystems - Beijing China sc->sc_halstats.ns_avgrssi = 15913ae945c3Slin wang - Sun Microsystems - Beijing China ATH_RSSI_DUMMY_MARKER; 15923ae945c3Slin wang - Sun Microsystems - Beijing China sc->sc_halstats.ns_avgtxrssi = 15933ae945c3Slin wang - Sun Microsystems - Beijing China ATH_RSSI_DUMMY_MARKER; 15943ae945c3Slin wang - Sun Microsystems - Beijing China sc->sc_halstats.ns_avgtxrate = 15953ae945c3Slin wang - Sun Microsystems - Beijing China ATH_RATE_DUMMY_MARKER; 1596c0c93480Slin wang - Sun Microsystems - Beijing China /* end */ 1597c0c93480Slin wang - Sun Microsystems - Beijing China 1598dd1de374Slin wang - Sun Microsystems - Beijing China #endif /* ARN_IBSS */ 1599dd1de374Slin wang - Sun Microsystems - Beijing China } 1600dd1de374Slin wang - Sun Microsystems - Beijing China break; 1601dd1de374Slin wang - Sun Microsystems - Beijing China default: 1602dd1de374Slin wang - Sun Microsystems - Beijing China break; 1603dd1de374Slin wang - Sun Microsystems - Beijing China } 1604dd1de374Slin wang - Sun Microsystems - Beijing China } else { 1605dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); 1606dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_set_interrupts(ah, sc->sc_imask); 1607dd1de374Slin wang - Sun Microsystems - Beijing China } 1608dd1de374Slin wang - Sun Microsystems - Beijing China 1609dd1de374Slin wang - Sun Microsystems - Beijing China /* 1610dd1de374Slin wang - Sun Microsystems - Beijing China * Reset the rate control state. 1611dd1de374Slin wang - Sun Microsystems - Beijing China */ 1612dd1de374Slin wang - Sun Microsystems - Beijing China arn_rate_ctl_reset(sc, nstate); 1613dd1de374Slin wang - Sun Microsystems - Beijing China 1614dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 1615dd1de374Slin wang - Sun Microsystems - Beijing China done: 1616dd1de374Slin wang - Sun Microsystems - Beijing China /* 1617dd1de374Slin wang - Sun Microsystems - Beijing China * Invoke the parent method to complete the work. 1618dd1de374Slin wang - Sun Microsystems - Beijing China */ 1619dd1de374Slin wang - Sun Microsystems - Beijing China error = sc->sc_newstate(ic, nstate, arg); 1620dd1de374Slin wang - Sun Microsystems - Beijing China 1621dd1de374Slin wang - Sun Microsystems - Beijing China /* 1622dd1de374Slin wang - Sun Microsystems - Beijing China * Finally, start any timers. 1623dd1de374Slin wang - Sun Microsystems - Beijing China */ 1624dd1de374Slin wang - Sun Microsystems - Beijing China if (nstate == IEEE80211_S_RUN) { 1625dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211_start_watchdog(ic, 1); 1626dd1de374Slin wang - Sun Microsystems - Beijing China ASSERT(sc->sc_cal_timer == 0); 1627dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_cal_timer = timeout(arn_ani_calibrate, (void *)sc, 1628dd1de374Slin wang - Sun Microsystems - Beijing China drv_usectohz(100 * 1000)); 1629dd1de374Slin wang - Sun Microsystems - Beijing China } else if ((nstate == IEEE80211_S_SCAN) && (ostate != nstate)) { 1630dd1de374Slin wang - Sun Microsystems - Beijing China /* start ap/neighbor scan timer */ 1631dd1de374Slin wang - Sun Microsystems - Beijing China /* ASSERT(sc->sc_scan_timer == 0); */ 1632dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_scan_timer != 0) { 1633dd1de374Slin wang - Sun Microsystems - Beijing China (void) untimeout(sc->sc_scan_timer); 1634dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_scan_timer = 0; 1635dd1de374Slin wang - Sun Microsystems - Beijing China } 1636dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_scan_timer = timeout(arn_next_scan, (void *)sc, 1637dd1de374Slin wang - Sun Microsystems - Beijing China drv_usectohz(arn_dwelltime * 1000)); 1638dd1de374Slin wang - Sun Microsystems - Beijing China } 1639dd1de374Slin wang - Sun Microsystems - Beijing China 1640dd1de374Slin wang - Sun Microsystems - Beijing China bad: 1641dd1de374Slin wang - Sun Microsystems - Beijing China return (error); 1642dd1de374Slin wang - Sun Microsystems - Beijing China } 1643dd1de374Slin wang - Sun Microsystems - Beijing China 1644dd1de374Slin wang - Sun Microsystems - Beijing China static void 1645dd1de374Slin wang - Sun Microsystems - Beijing China arn_watchdog(void *arg) 1646dd1de374Slin wang - Sun Microsystems - Beijing China { 1647dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = arg; 1648dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211com_t *ic = &sc->sc_isc; 1649dd1de374Slin wang - Sun Microsystems - Beijing China int ntimer = 0; 1650dd1de374Slin wang - Sun Microsystems - Beijing China 1651dd1de374Slin wang - Sun Microsystems - Beijing China ARN_LOCK(sc); 1652dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_watchdog_timer = 0; 1653dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_flags & SC_OP_INVALID) { 1654dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 1655dd1de374Slin wang - Sun Microsystems - Beijing China return; 1656dd1de374Slin wang - Sun Microsystems - Beijing China } 1657dd1de374Slin wang - Sun Microsystems - Beijing China 1658dd1de374Slin wang - Sun Microsystems - Beijing China if (ic->ic_state == IEEE80211_S_RUN) { 1659dd1de374Slin wang - Sun Microsystems - Beijing China /* 1660dd1de374Slin wang - Sun Microsystems - Beijing China * Start the background rate control thread if we 1661dd1de374Slin wang - Sun Microsystems - Beijing China * are not configured to use a fixed xmit rate. 1662dd1de374Slin wang - Sun Microsystems - Beijing China */ 1663c0c93480Slin wang - Sun Microsystems - Beijing China #ifdef ARN_LEGACY_RC 1664dd1de374Slin wang - Sun Microsystems - Beijing China if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) { 1665dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_stats.ast_rate_calls ++; 1666dd1de374Slin wang - Sun Microsystems - Beijing China if (ic->ic_opmode == IEEE80211_M_STA) 1667dd1de374Slin wang - Sun Microsystems - Beijing China arn_rate_ctl(ic, ic->ic_bss); 1668dd1de374Slin wang - Sun Microsystems - Beijing China else 1669dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211_iterate_nodes(&ic->ic_sta, 1670dd1de374Slin wang - Sun Microsystems - Beijing China arn_rate_ctl, sc); 1671dd1de374Slin wang - Sun Microsystems - Beijing China } 1672c0c93480Slin wang - Sun Microsystems - Beijing China #endif /* ARN_LEGACY_RC */ 1673dd1de374Slin wang - Sun Microsystems - Beijing China 1674c0c93480Slin wang - Sun Microsystems - Beijing China #ifdef ARN_HW_BEACON_MISS_HANDLE 16753ae945c3Slin wang - Sun Microsystems - Beijing China /* nothing to do here */ 16763ae945c3Slin wang - Sun Microsystems - Beijing China #else 16773ae945c3Slin wang - Sun Microsystems - Beijing China /* currently set 10 seconds as beacon miss threshold */ 16783ae945c3Slin wang - Sun Microsystems - Beijing China if (ic->ic_beaconmiss++ > 100) { 16793ae945c3Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_BEACON, "arn_watchdog():" 16803ae945c3Slin wang - Sun Microsystems - Beijing China "Beacon missed for 10 seconds, run" 16813ae945c3Slin wang - Sun Microsystems - Beijing China "ieee80211_new_state(ic, IEEE80211_S_INIT, -1)\n")); 16823ae945c3Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 16833ae945c3Slin wang - Sun Microsystems - Beijing China (void) ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 16843ae945c3Slin wang - Sun Microsystems - Beijing China return; 16853ae945c3Slin wang - Sun Microsystems - Beijing China } 1686c0c93480Slin wang - Sun Microsystems - Beijing China #endif /* ARN_HW_BEACON_MISS_HANDLE */ 16873ae945c3Slin wang - Sun Microsystems - Beijing China 1688dd1de374Slin wang - Sun Microsystems - Beijing China ntimer = 1; 1689dd1de374Slin wang - Sun Microsystems - Beijing China } 1690dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 1691dd1de374Slin wang - Sun Microsystems - Beijing China 1692dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211_watchdog(ic); 1693dd1de374Slin wang - Sun Microsystems - Beijing China if (ntimer != 0) 1694dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211_start_watchdog(ic, ntimer); 1695dd1de374Slin wang - Sun Microsystems - Beijing China } 1696dd1de374Slin wang - Sun Microsystems - Beijing China 1697c0c93480Slin wang - Sun Microsystems - Beijing China /* ARGSUSED */ 1698dd1de374Slin wang - Sun Microsystems - Beijing China static struct ieee80211_node * 1699dd1de374Slin wang - Sun Microsystems - Beijing China arn_node_alloc(ieee80211com_t *ic) 1700dd1de374Slin wang - Sun Microsystems - Beijing China { 1701dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_node *an; 1702c0c93480Slin wang - Sun Microsystems - Beijing China #ifdef ARN_TX_AGGREGATION 1703dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = (struct arn_softc *)ic; 1704c0c93480Slin wang - Sun Microsystems - Beijing China #endif 1705dd1de374Slin wang - Sun Microsystems - Beijing China 1706dd1de374Slin wang - Sun Microsystems - Beijing China an = kmem_zalloc(sizeof (struct ath_node), KM_SLEEP); 1707c0c93480Slin wang - Sun Microsystems - Beijing China 1708c0c93480Slin wang - Sun Microsystems - Beijing China /* legacy rate control */ 1709c0c93480Slin wang - Sun Microsystems - Beijing China #ifdef ARN_LEGACY_RC 1710dd1de374Slin wang - Sun Microsystems - Beijing China arn_rate_update(sc, &an->an_node, 0); 1711c0c93480Slin wang - Sun Microsystems - Beijing China #endif 1712c0c93480Slin wang - Sun Microsystems - Beijing China 1713c0c93480Slin wang - Sun Microsystems - Beijing China #ifdef ARN_TX_AGGREGATION 1714c0c93480Slin wang - Sun Microsystems - Beijing China if (sc->sc_flags & SC_OP_TXAGGR) { 1715c0c93480Slin wang - Sun Microsystems - Beijing China arn_tx_node_init(sc, an); 1716c0c93480Slin wang - Sun Microsystems - Beijing China } 1717c0c93480Slin wang - Sun Microsystems - Beijing China #endif /* ARN_TX_AGGREGATION */ 1718c0c93480Slin wang - Sun Microsystems - Beijing China 1719c0c93480Slin wang - Sun Microsystems - Beijing China an->last_rssi = ATH_RSSI_DUMMY_MARKER; 1720dd1de374Slin wang - Sun Microsystems - Beijing China 1721dd1de374Slin wang - Sun Microsystems - Beijing China return ((an != NULL) ? &an->an_node : NULL); 1722dd1de374Slin wang - Sun Microsystems - Beijing China } 1723dd1de374Slin wang - Sun Microsystems - Beijing China 1724dd1de374Slin wang - Sun Microsystems - Beijing China static void 1725dd1de374Slin wang - Sun Microsystems - Beijing China arn_node_free(struct ieee80211_node *in) 1726dd1de374Slin wang - Sun Microsystems - Beijing China { 1727dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211com_t *ic = in->in_ic; 1728dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = (struct arn_softc *)ic; 1729dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_buf *bf; 1730dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_txq *txq; 1731dd1de374Slin wang - Sun Microsystems - Beijing China int32_t i; 1732dd1de374Slin wang - Sun Microsystems - Beijing China 1733c0c93480Slin wang - Sun Microsystems - Beijing China #ifdef ARN_TX_AGGREGATION 1734c0c93480Slin wang - Sun Microsystems - Beijing China if (sc->sc_flags & SC_OP_TXAGGR) 1735c0c93480Slin wang - Sun Microsystems - Beijing China arn_tx_node_cleanup(sc, in); 1736c0c93480Slin wang - Sun Microsystems - Beijing China #endif /* TX_AGGREGATION */ 1737c0c93480Slin wang - Sun Microsystems - Beijing China 1738dd1de374Slin wang - Sun Microsystems - Beijing China for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { 1739dd1de374Slin wang - Sun Microsystems - Beijing China if (ARN_TXQ_SETUP(sc, i)) { 1740dd1de374Slin wang - Sun Microsystems - Beijing China txq = &sc->sc_txq[i]; 1741dd1de374Slin wang - Sun Microsystems - Beijing China mutex_enter(&txq->axq_lock); 1742dd1de374Slin wang - Sun Microsystems - Beijing China bf = list_head(&txq->axq_list); 1743dd1de374Slin wang - Sun Microsystems - Beijing China while (bf != NULL) { 1744dd1de374Slin wang - Sun Microsystems - Beijing China if (bf->bf_in == in) { 1745dd1de374Slin wang - Sun Microsystems - Beijing China bf->bf_in = NULL; 1746dd1de374Slin wang - Sun Microsystems - Beijing China } 1747dd1de374Slin wang - Sun Microsystems - Beijing China bf = list_next(&txq->axq_list, bf); 1748dd1de374Slin wang - Sun Microsystems - Beijing China } 1749dd1de374Slin wang - Sun Microsystems - Beijing China mutex_exit(&txq->axq_lock); 1750dd1de374Slin wang - Sun Microsystems - Beijing China } 1751dd1de374Slin wang - Sun Microsystems - Beijing China } 1752dd1de374Slin wang - Sun Microsystems - Beijing China 1753dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_node_cleanup(in); 17543ae945c3Slin wang - Sun Microsystems - Beijing China 1755dd1de374Slin wang - Sun Microsystems - Beijing China if (in->in_wpa_ie != NULL) 1756dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211_free(in->in_wpa_ie); 17573ae945c3Slin wang - Sun Microsystems - Beijing China 17583ae945c3Slin wang - Sun Microsystems - Beijing China if (in->in_wme_ie != NULL) 17593ae945c3Slin wang - Sun Microsystems - Beijing China ieee80211_free(in->in_wme_ie); 17603ae945c3Slin wang - Sun Microsystems - Beijing China 17613ae945c3Slin wang - Sun Microsystems - Beijing China if (in->in_htcap_ie != NULL) 17623ae945c3Slin wang - Sun Microsystems - Beijing China ieee80211_free(in->in_htcap_ie); 17633ae945c3Slin wang - Sun Microsystems - Beijing China 1764dd1de374Slin wang - Sun Microsystems - Beijing China kmem_free(in, sizeof (struct ath_node)); 1765dd1de374Slin wang - Sun Microsystems - Beijing China } 1766dd1de374Slin wang - Sun Microsystems - Beijing China 1767dd1de374Slin wang - Sun Microsystems - Beijing China /* 1768dd1de374Slin wang - Sun Microsystems - Beijing China * Allocate tx/rx key slots for TKIP. We allocate one slot for 1769dd1de374Slin wang - Sun Microsystems - Beijing China * each key. MIC is right after the decrypt/encrypt key. 1770dd1de374Slin wang - Sun Microsystems - Beijing China */ 1771dd1de374Slin wang - Sun Microsystems - Beijing China static uint16_t 1772dd1de374Slin wang - Sun Microsystems - Beijing China arn_key_alloc_pair(struct arn_softc *sc, ieee80211_keyix *txkeyix, 1773dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211_keyix *rxkeyix) 1774dd1de374Slin wang - Sun Microsystems - Beijing China { 1775dd1de374Slin wang - Sun Microsystems - Beijing China uint16_t i, keyix; 1776dd1de374Slin wang - Sun Microsystems - Beijing China 1777dd1de374Slin wang - Sun Microsystems - Beijing China ASSERT(!sc->sc_splitmic); 1778dd1de374Slin wang - Sun Microsystems - Beijing China for (i = 0; i < ARRAY_SIZE(sc->sc_keymap)/4; i++) { 1779dd1de374Slin wang - Sun Microsystems - Beijing China uint8_t b = sc->sc_keymap[i]; 1780dd1de374Slin wang - Sun Microsystems - Beijing China if (b == 0xff) 1781dd1de374Slin wang - Sun Microsystems - Beijing China continue; 1782dd1de374Slin wang - Sun Microsystems - Beijing China for (keyix = i * NBBY; keyix < (i + 1) * NBBY; 1783dd1de374Slin wang - Sun Microsystems - Beijing China keyix++, b >>= 1) { 1784dd1de374Slin wang - Sun Microsystems - Beijing China if ((b & 1) || is_set(keyix+64, sc->sc_keymap)) { 1785dd1de374Slin wang - Sun Microsystems - Beijing China /* full pair unavailable */ 1786dd1de374Slin wang - Sun Microsystems - Beijing China continue; 1787dd1de374Slin wang - Sun Microsystems - Beijing China } 1788dd1de374Slin wang - Sun Microsystems - Beijing China set_bit(keyix, sc->sc_keymap); 1789dd1de374Slin wang - Sun Microsystems - Beijing China set_bit(keyix+64, sc->sc_keymap); 1790dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_KEYCACHE, 1791dd1de374Slin wang - Sun Microsystems - Beijing China "arn_key_alloc_pair(): key pair %u,%u\n", 1792dd1de374Slin wang - Sun Microsystems - Beijing China keyix, keyix+64)); 1793dd1de374Slin wang - Sun Microsystems - Beijing China *txkeyix = *rxkeyix = keyix; 1794dd1de374Slin wang - Sun Microsystems - Beijing China return (1); 1795dd1de374Slin wang - Sun Microsystems - Beijing China } 1796dd1de374Slin wang - Sun Microsystems - Beijing China } 1797dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_KEYCACHE, "arn_key_alloc_pair():" 1798dd1de374Slin wang - Sun Microsystems - Beijing China " out of pair space\n")); 1799dd1de374Slin wang - Sun Microsystems - Beijing China 1800dd1de374Slin wang - Sun Microsystems - Beijing China return (0); 1801dd1de374Slin wang - Sun Microsystems - Beijing China } 1802dd1de374Slin wang - Sun Microsystems - Beijing China 1803dd1de374Slin wang - Sun Microsystems - Beijing China /* 1804dd1de374Slin wang - Sun Microsystems - Beijing China * Allocate tx/rx key slots for TKIP. We allocate two slots for 1805dd1de374Slin wang - Sun Microsystems - Beijing China * each key, one for decrypt/encrypt and the other for the MIC. 1806dd1de374Slin wang - Sun Microsystems - Beijing China */ 1807dd1de374Slin wang - Sun Microsystems - Beijing China static int 1808dd1de374Slin wang - Sun Microsystems - Beijing China arn_key_alloc_2pair(struct arn_softc *sc, ieee80211_keyix *txkeyix, 1809dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211_keyix *rxkeyix) 1810dd1de374Slin wang - Sun Microsystems - Beijing China { 1811dd1de374Slin wang - Sun Microsystems - Beijing China uint16_t i, keyix; 1812dd1de374Slin wang - Sun Microsystems - Beijing China 1813dd1de374Slin wang - Sun Microsystems - Beijing China ASSERT(sc->sc_splitmic); 1814dd1de374Slin wang - Sun Microsystems - Beijing China for (i = 0; i < ARRAY_SIZE(sc->sc_keymap)/4; i++) { 1815dd1de374Slin wang - Sun Microsystems - Beijing China uint8_t b = sc->sc_keymap[i]; 1816dd1de374Slin wang - Sun Microsystems - Beijing China if (b != 0xff) { 1817dd1de374Slin wang - Sun Microsystems - Beijing China /* 1818dd1de374Slin wang - Sun Microsystems - Beijing China * One or more slots in this byte are free. 1819dd1de374Slin wang - Sun Microsystems - Beijing China */ 1820dd1de374Slin wang - Sun Microsystems - Beijing China keyix = i*NBBY; 1821dd1de374Slin wang - Sun Microsystems - Beijing China while (b & 1) { 1822dd1de374Slin wang - Sun Microsystems - Beijing China again: 1823dd1de374Slin wang - Sun Microsystems - Beijing China keyix++; 1824dd1de374Slin wang - Sun Microsystems - Beijing China b >>= 1; 1825dd1de374Slin wang - Sun Microsystems - Beijing China } 1826dd1de374Slin wang - Sun Microsystems - Beijing China /* XXX IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV */ 1827dd1de374Slin wang - Sun Microsystems - Beijing China if (is_set(keyix+32, sc->sc_keymap) || 1828dd1de374Slin wang - Sun Microsystems - Beijing China is_set(keyix+64, sc->sc_keymap) || 1829dd1de374Slin wang - Sun Microsystems - Beijing China is_set(keyix+32+64, sc->sc_keymap)) { 1830dd1de374Slin wang - Sun Microsystems - Beijing China /* full pair unavailable */ 1831dd1de374Slin wang - Sun Microsystems - Beijing China if (keyix == (i+1)*NBBY) { 1832dd1de374Slin wang - Sun Microsystems - Beijing China /* no slots were appropriate, advance */ 1833dd1de374Slin wang - Sun Microsystems - Beijing China continue; 1834dd1de374Slin wang - Sun Microsystems - Beijing China } 1835dd1de374Slin wang - Sun Microsystems - Beijing China goto again; 1836dd1de374Slin wang - Sun Microsystems - Beijing China } 1837dd1de374Slin wang - Sun Microsystems - Beijing China set_bit(keyix, sc->sc_keymap); 1838dd1de374Slin wang - Sun Microsystems - Beijing China set_bit(keyix+64, sc->sc_keymap); 1839dd1de374Slin wang - Sun Microsystems - Beijing China set_bit(keyix+32, sc->sc_keymap); 1840dd1de374Slin wang - Sun Microsystems - Beijing China set_bit(keyix+32+64, sc->sc_keymap); 1841dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_KEYCACHE, 1842dd1de374Slin wang - Sun Microsystems - Beijing China "arn_key_alloc_2pair(): key pair %u,%u %u,%u\n", 1843dd1de374Slin wang - Sun Microsystems - Beijing China keyix, keyix+64, 1844dd1de374Slin wang - Sun Microsystems - Beijing China keyix+32, keyix+32+64)); 1845dd1de374Slin wang - Sun Microsystems - Beijing China *txkeyix = *rxkeyix = keyix; 1846dd1de374Slin wang - Sun Microsystems - Beijing China return (1); 1847dd1de374Slin wang - Sun Microsystems - Beijing China } 1848dd1de374Slin wang - Sun Microsystems - Beijing China } 1849dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_KEYCACHE, "arn_key_alloc_2pair(): " 1850dd1de374Slin wang - Sun Microsystems - Beijing China " out of pair space\n")); 1851dd1de374Slin wang - Sun Microsystems - Beijing China 1852dd1de374Slin wang - Sun Microsystems - Beijing China return (0); 1853dd1de374Slin wang - Sun Microsystems - Beijing China } 1854dd1de374Slin wang - Sun Microsystems - Beijing China /* 1855dd1de374Slin wang - Sun Microsystems - Beijing China * Allocate a single key cache slot. 1856dd1de374Slin wang - Sun Microsystems - Beijing China */ 1857dd1de374Slin wang - Sun Microsystems - Beijing China static int 1858dd1de374Slin wang - Sun Microsystems - Beijing China arn_key_alloc_single(struct arn_softc *sc, ieee80211_keyix *txkeyix, 1859dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211_keyix *rxkeyix) 1860dd1de374Slin wang - Sun Microsystems - Beijing China { 1861dd1de374Slin wang - Sun Microsystems - Beijing China uint16_t i, keyix; 1862dd1de374Slin wang - Sun Microsystems - Beijing China 1863dd1de374Slin wang - Sun Microsystems - Beijing China /* try i,i+32,i+64,i+32+64 to minimize key pair conflicts */ 1864dd1de374Slin wang - Sun Microsystems - Beijing China for (i = 0; i < ARRAY_SIZE(sc->sc_keymap); i++) { 1865dd1de374Slin wang - Sun Microsystems - Beijing China uint8_t b = sc->sc_keymap[i]; 1866dd1de374Slin wang - Sun Microsystems - Beijing China 1867dd1de374Slin wang - Sun Microsystems - Beijing China if (b != 0xff) { 1868dd1de374Slin wang - Sun Microsystems - Beijing China /* 1869dd1de374Slin wang - Sun Microsystems - Beijing China * One or more slots are free. 1870dd1de374Slin wang - Sun Microsystems - Beijing China */ 1871dd1de374Slin wang - Sun Microsystems - Beijing China keyix = i*NBBY; 1872dd1de374Slin wang - Sun Microsystems - Beijing China while (b & 1) 1873dd1de374Slin wang - Sun Microsystems - Beijing China keyix++, b >>= 1; 1874dd1de374Slin wang - Sun Microsystems - Beijing China set_bit(keyix, sc->sc_keymap); 1875dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_KEYCACHE, "arn_key_alloc_single(): " 1876dd1de374Slin wang - Sun Microsystems - Beijing China "key %u\n", keyix)); 1877dd1de374Slin wang - Sun Microsystems - Beijing China *txkeyix = *rxkeyix = keyix; 1878dd1de374Slin wang - Sun Microsystems - Beijing China return (1); 1879dd1de374Slin wang - Sun Microsystems - Beijing China } 1880dd1de374Slin wang - Sun Microsystems - Beijing China } 1881dd1de374Slin wang - Sun Microsystems - Beijing China return (0); 1882dd1de374Slin wang - Sun Microsystems - Beijing China } 1883dd1de374Slin wang - Sun Microsystems - Beijing China 1884dd1de374Slin wang - Sun Microsystems - Beijing China /* 1885dd1de374Slin wang - Sun Microsystems - Beijing China * Allocate one or more key cache slots for a unicast key. The 1886dd1de374Slin wang - Sun Microsystems - Beijing China * key itself is needed only to identify the cipher. For hardware 1887dd1de374Slin wang - Sun Microsystems - Beijing China * TKIP with split cipher+MIC keys we allocate two key cache slot 1888dd1de374Slin wang - Sun Microsystems - Beijing China * pairs so that we can setup separate TX and RX MIC keys. Note 1889dd1de374Slin wang - Sun Microsystems - Beijing China * that the MIC key for a TKIP key at slot i is assumed by the 1890dd1de374Slin wang - Sun Microsystems - Beijing China * hardware to be at slot i+64. This limits TKIP keys to the first 1891dd1de374Slin wang - Sun Microsystems - Beijing China * 64 entries. 1892dd1de374Slin wang - Sun Microsystems - Beijing China */ 1893dd1de374Slin wang - Sun Microsystems - Beijing China /* ARGSUSED */ 1894dd1de374Slin wang - Sun Microsystems - Beijing China int 1895dd1de374Slin wang - Sun Microsystems - Beijing China arn_key_alloc(ieee80211com_t *ic, const struct ieee80211_key *k, 1896dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix) 1897dd1de374Slin wang - Sun Microsystems - Beijing China { 1898dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = (struct arn_softc *)ic; 1899dd1de374Slin wang - Sun Microsystems - Beijing China 1900dd1de374Slin wang - Sun Microsystems - Beijing China /* 1901dd1de374Slin wang - Sun Microsystems - Beijing China * We allocate two pair for TKIP when using the h/w to do 1902dd1de374Slin wang - Sun Microsystems - Beijing China * the MIC. For everything else, including software crypto, 1903dd1de374Slin wang - Sun Microsystems - Beijing China * we allocate a single entry. Note that s/w crypto requires 1904dd1de374Slin wang - Sun Microsystems - Beijing China * a pass-through slot on the 5211 and 5212. The 5210 does 1905dd1de374Slin wang - Sun Microsystems - Beijing China * not support pass-through cache entries and we map all 1906dd1de374Slin wang - Sun Microsystems - Beijing China * those requests to slot 0. 1907dd1de374Slin wang - Sun Microsystems - Beijing China */ 1908dd1de374Slin wang - Sun Microsystems - Beijing China if (k->wk_flags & IEEE80211_KEY_SWCRYPT) { 1909dd1de374Slin wang - Sun Microsystems - Beijing China return (arn_key_alloc_single(sc, keyix, rxkeyix)); 1910dd1de374Slin wang - Sun Microsystems - Beijing China } else if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP && 1911dd1de374Slin wang - Sun Microsystems - Beijing China (k->wk_flags & IEEE80211_KEY_SWMIC) == 0) { 1912dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_splitmic) 1913dd1de374Slin wang - Sun Microsystems - Beijing China return (arn_key_alloc_2pair(sc, keyix, rxkeyix)); 1914dd1de374Slin wang - Sun Microsystems - Beijing China else 1915dd1de374Slin wang - Sun Microsystems - Beijing China return (arn_key_alloc_pair(sc, keyix, rxkeyix)); 1916dd1de374Slin wang - Sun Microsystems - Beijing China } else { 1917dd1de374Slin wang - Sun Microsystems - Beijing China return (arn_key_alloc_single(sc, keyix, rxkeyix)); 1918dd1de374Slin wang - Sun Microsystems - Beijing China } 1919dd1de374Slin wang - Sun Microsystems - Beijing China } 1920dd1de374Slin wang - Sun Microsystems - Beijing China 1921dd1de374Slin wang - Sun Microsystems - Beijing China /* 1922dd1de374Slin wang - Sun Microsystems - Beijing China * Delete an entry in the key cache allocated by ath_key_alloc. 1923dd1de374Slin wang - Sun Microsystems - Beijing China */ 1924dd1de374Slin wang - Sun Microsystems - Beijing China int 1925dd1de374Slin wang - Sun Microsystems - Beijing China arn_key_delete(ieee80211com_t *ic, const struct ieee80211_key *k) 1926dd1de374Slin wang - Sun Microsystems - Beijing China { 1927dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = (struct arn_softc *)ic; 1928dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_hal *ah = sc->sc_ah; 1929dd1de374Slin wang - Sun Microsystems - Beijing China const struct ieee80211_cipher *cip = k->wk_cipher; 1930dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211_keyix keyix = k->wk_keyix; 1931dd1de374Slin wang - Sun Microsystems - Beijing China 1932dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_KEYCACHE, "arn_key_delete():" 1933dd1de374Slin wang - Sun Microsystems - Beijing China " delete key %u ic_cipher=0x%x\n", keyix, cip->ic_cipher)); 1934dd1de374Slin wang - Sun Microsystems - Beijing China 1935dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_keyreset(ah, keyix); 1936dd1de374Slin wang - Sun Microsystems - Beijing China /* 1937dd1de374Slin wang - Sun Microsystems - Beijing China * Handle split tx/rx keying required for TKIP with h/w MIC. 1938dd1de374Slin wang - Sun Microsystems - Beijing China */ 1939dd1de374Slin wang - Sun Microsystems - Beijing China if (cip->ic_cipher == IEEE80211_CIPHER_TKIP && 1940dd1de374Slin wang - Sun Microsystems - Beijing China (k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && sc->sc_splitmic) 1941dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_keyreset(ah, keyix+32); /* RX key */ 1942dd1de374Slin wang - Sun Microsystems - Beijing China 1943dd1de374Slin wang - Sun Microsystems - Beijing China if (keyix >= IEEE80211_WEP_NKID) { 1944dd1de374Slin wang - Sun Microsystems - Beijing China /* 1945dd1de374Slin wang - Sun Microsystems - Beijing China * Don't touch keymap entries for global keys so 1946dd1de374Slin wang - Sun Microsystems - Beijing China * they are never considered for dynamic allocation. 1947dd1de374Slin wang - Sun Microsystems - Beijing China */ 1948dd1de374Slin wang - Sun Microsystems - Beijing China clr_bit(keyix, sc->sc_keymap); 1949dd1de374Slin wang - Sun Microsystems - Beijing China if (cip->ic_cipher == IEEE80211_CIPHER_TKIP && 1950dd1de374Slin wang - Sun Microsystems - Beijing China (k->wk_flags & IEEE80211_KEY_SWMIC) == 0) { 1951dd1de374Slin wang - Sun Microsystems - Beijing China /* 1952dd1de374Slin wang - Sun Microsystems - Beijing China * If splitmic is true +64 is TX key MIC, 1953dd1de374Slin wang - Sun Microsystems - Beijing China * else +64 is RX key + RX key MIC. 1954dd1de374Slin wang - Sun Microsystems - Beijing China */ 1955dd1de374Slin wang - Sun Microsystems - Beijing China clr_bit(keyix+64, sc->sc_keymap); 1956dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_splitmic) { 1957dd1de374Slin wang - Sun Microsystems - Beijing China /* Rx key */ 1958dd1de374Slin wang - Sun Microsystems - Beijing China clr_bit(keyix+32, sc->sc_keymap); 1959dd1de374Slin wang - Sun Microsystems - Beijing China /* RX key MIC */ 1960dd1de374Slin wang - Sun Microsystems - Beijing China clr_bit(keyix+32+64, sc->sc_keymap); 1961dd1de374Slin wang - Sun Microsystems - Beijing China } 1962dd1de374Slin wang - Sun Microsystems - Beijing China } 1963dd1de374Slin wang - Sun Microsystems - Beijing China } 1964dd1de374Slin wang - Sun Microsystems - Beijing China return (1); 1965dd1de374Slin wang - Sun Microsystems - Beijing China } 1966dd1de374Slin wang - Sun Microsystems - Beijing China 1967dd1de374Slin wang - Sun Microsystems - Beijing China /* 1968dd1de374Slin wang - Sun Microsystems - Beijing China * Set a TKIP key into the hardware. This handles the 1969dd1de374Slin wang - Sun Microsystems - Beijing China * potential distribution of key state to multiple key 1970dd1de374Slin wang - Sun Microsystems - Beijing China * cache slots for TKIP. 1971dd1de374Slin wang - Sun Microsystems - Beijing China */ 1972dd1de374Slin wang - Sun Microsystems - Beijing China static int 1973dd1de374Slin wang - Sun Microsystems - Beijing China arn_keyset_tkip(struct arn_softc *sc, const struct ieee80211_key *k, 1974dd1de374Slin wang - Sun Microsystems - Beijing China struct ath9k_keyval *hk, const uint8_t mac[IEEE80211_ADDR_LEN]) 1975dd1de374Slin wang - Sun Microsystems - Beijing China { 1976dd1de374Slin wang - Sun Microsystems - Beijing China uint8_t *key_rxmic = NULL; 1977dd1de374Slin wang - Sun Microsystems - Beijing China uint8_t *key_txmic = NULL; 1978dd1de374Slin wang - Sun Microsystems - Beijing China uint8_t *key = (uint8_t *)&(k->wk_key[0]); 1979dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_hal *ah = sc->sc_ah; 1980dd1de374Slin wang - Sun Microsystems - Beijing China 1981dd1de374Slin wang - Sun Microsystems - Beijing China key_txmic = key + 16; 1982dd1de374Slin wang - Sun Microsystems - Beijing China key_rxmic = key + 24; 1983dd1de374Slin wang - Sun Microsystems - Beijing China 1984dd1de374Slin wang - Sun Microsystems - Beijing China if (mac == NULL) { 1985dd1de374Slin wang - Sun Microsystems - Beijing China /* Group key installation */ 1986dd1de374Slin wang - Sun Microsystems - Beijing China (void) memcpy(hk->kv_mic, key_rxmic, sizeof (hk->kv_mic)); 1987dd1de374Slin wang - Sun Microsystems - Beijing China return (ath9k_hw_set_keycache_entry(ah, k->wk_keyix, hk, 1988dd1de374Slin wang - Sun Microsystems - Beijing China mac, B_FALSE)); 1989dd1de374Slin wang - Sun Microsystems - Beijing China } 1990dd1de374Slin wang - Sun Microsystems - Beijing China if (!sc->sc_splitmic) { 1991dd1de374Slin wang - Sun Microsystems - Beijing China /* 1992dd1de374Slin wang - Sun Microsystems - Beijing China * data key goes at first index, 1993dd1de374Slin wang - Sun Microsystems - Beijing China * the hal handles the MIC keys at index+64. 1994dd1de374Slin wang - Sun Microsystems - Beijing China */ 1995dd1de374Slin wang - Sun Microsystems - Beijing China (void) memcpy(hk->kv_mic, key_rxmic, sizeof (hk->kv_mic)); 1996dd1de374Slin wang - Sun Microsystems - Beijing China (void) memcpy(hk->kv_txmic, key_txmic, sizeof (hk->kv_txmic)); 1997dd1de374Slin wang - Sun Microsystems - Beijing China return (ath9k_hw_set_keycache_entry(ah, k->wk_keyix, hk, 1998dd1de374Slin wang - Sun Microsystems - Beijing China mac, B_FALSE)); 1999dd1de374Slin wang - Sun Microsystems - Beijing China } 2000dd1de374Slin wang - Sun Microsystems - Beijing China /* 2001dd1de374Slin wang - Sun Microsystems - Beijing China * TX key goes at first index, RX key at +32. 2002dd1de374Slin wang - Sun Microsystems - Beijing China * The hal handles the MIC keys at index+64. 2003dd1de374Slin wang - Sun Microsystems - Beijing China */ 2004dd1de374Slin wang - Sun Microsystems - Beijing China (void) memcpy(hk->kv_mic, key_txmic, sizeof (hk->kv_mic)); 2005dd1de374Slin wang - Sun Microsystems - Beijing China if (!(ath9k_hw_set_keycache_entry(ah, k->wk_keyix, hk, NULL, 2006dd1de374Slin wang - Sun Microsystems - Beijing China B_FALSE))) { 2007dd1de374Slin wang - Sun Microsystems - Beijing China /* Txmic entry failed. No need to proceed further */ 2008dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_KEYCACHE, 2009dd1de374Slin wang - Sun Microsystems - Beijing China "%s Setting TX MIC Key Failed\n", __func__)); 2010dd1de374Slin wang - Sun Microsystems - Beijing China return (0); 2011dd1de374Slin wang - Sun Microsystems - Beijing China } 2012dd1de374Slin wang - Sun Microsystems - Beijing China 2013dd1de374Slin wang - Sun Microsystems - Beijing China (void) memcpy(hk->kv_mic, key_rxmic, sizeof (hk->kv_mic)); 2014dd1de374Slin wang - Sun Microsystems - Beijing China 2015dd1de374Slin wang - Sun Microsystems - Beijing China /* XXX delete tx key on failure? */ 2016dd1de374Slin wang - Sun Microsystems - Beijing China return (ath9k_hw_set_keycache_entry(ah, k->wk_keyix, hk, mac, B_FALSE)); 2017dd1de374Slin wang - Sun Microsystems - Beijing China 2018dd1de374Slin wang - Sun Microsystems - Beijing China } 2019dd1de374Slin wang - Sun Microsystems - Beijing China 2020dd1de374Slin wang - Sun Microsystems - Beijing China int 2021dd1de374Slin wang - Sun Microsystems - Beijing China arn_key_set(ieee80211com_t *ic, const struct ieee80211_key *k, 2022dd1de374Slin wang - Sun Microsystems - Beijing China const uint8_t mac[IEEE80211_ADDR_LEN]) 2023dd1de374Slin wang - Sun Microsystems - Beijing China { 2024dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = (struct arn_softc *)ic; 2025dd1de374Slin wang - Sun Microsystems - Beijing China const struct ieee80211_cipher *cip = k->wk_cipher; 2026dd1de374Slin wang - Sun Microsystems - Beijing China struct ath9k_keyval hk; 2027dd1de374Slin wang - Sun Microsystems - Beijing China 2028dd1de374Slin wang - Sun Microsystems - Beijing China /* cipher table */ 2029dd1de374Slin wang - Sun Microsystems - Beijing China static const uint8_t ciphermap[] = { 2030dd1de374Slin wang - Sun Microsystems - Beijing China ATH9K_CIPHER_WEP, /* IEEE80211_CIPHER_WEP */ 2031dd1de374Slin wang - Sun Microsystems - Beijing China ATH9K_CIPHER_TKIP, /* IEEE80211_CIPHER_TKIP */ 2032dd1de374Slin wang - Sun Microsystems - Beijing China ATH9K_CIPHER_AES_OCB, /* IEEE80211_CIPHER_AES_OCB */ 2033dd1de374Slin wang - Sun Microsystems - Beijing China ATH9K_CIPHER_AES_CCM, /* IEEE80211_CIPHER_AES_CCM */ 2034dd1de374Slin wang - Sun Microsystems - Beijing China ATH9K_CIPHER_CKIP, /* IEEE80211_CIPHER_CKIP */ 2035dd1de374Slin wang - Sun Microsystems - Beijing China ATH9K_CIPHER_CLR, /* IEEE80211_CIPHER_NONE */ 2036dd1de374Slin wang - Sun Microsystems - Beijing China }; 2037dd1de374Slin wang - Sun Microsystems - Beijing China 2038dd1de374Slin wang - Sun Microsystems - Beijing China bzero(&hk, sizeof (hk)); 2039dd1de374Slin wang - Sun Microsystems - Beijing China 2040dd1de374Slin wang - Sun Microsystems - Beijing China /* 2041dd1de374Slin wang - Sun Microsystems - Beijing China * Software crypto uses a "clear key" so non-crypto 2042dd1de374Slin wang - Sun Microsystems - Beijing China * state kept in the key cache are maintainedd so that 2043dd1de374Slin wang - Sun Microsystems - Beijing China * rx frames have an entry to match. 2044dd1de374Slin wang - Sun Microsystems - Beijing China */ 2045dd1de374Slin wang - Sun Microsystems - Beijing China if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) == 0) { 2046dd1de374Slin wang - Sun Microsystems - Beijing China ASSERT(cip->ic_cipher < 6); 2047dd1de374Slin wang - Sun Microsystems - Beijing China hk.kv_type = ciphermap[cip->ic_cipher]; 2048dd1de374Slin wang - Sun Microsystems - Beijing China hk.kv_len = k->wk_keylen; 2049dd1de374Slin wang - Sun Microsystems - Beijing China bcopy(k->wk_key, hk.kv_val, k->wk_keylen); 2050dd1de374Slin wang - Sun Microsystems - Beijing China } else { 2051dd1de374Slin wang - Sun Microsystems - Beijing China hk.kv_type = ATH9K_CIPHER_CLR; 2052dd1de374Slin wang - Sun Microsystems - Beijing China } 2053dd1de374Slin wang - Sun Microsystems - Beijing China 2054dd1de374Slin wang - Sun Microsystems - Beijing China if (hk.kv_type == ATH9K_CIPHER_TKIP && 2055dd1de374Slin wang - Sun Microsystems - Beijing China (k->wk_flags & IEEE80211_KEY_SWMIC) == 0) { 2056dd1de374Slin wang - Sun Microsystems - Beijing China return (arn_keyset_tkip(sc, k, &hk, mac)); 2057dd1de374Slin wang - Sun Microsystems - Beijing China } else { 2058dd1de374Slin wang - Sun Microsystems - Beijing China return (ath9k_hw_set_keycache_entry(sc->sc_ah, 2059dd1de374Slin wang - Sun Microsystems - Beijing China k->wk_keyix, &hk, mac, B_FALSE)); 2060dd1de374Slin wang - Sun Microsystems - Beijing China } 2061dd1de374Slin wang - Sun Microsystems - Beijing China } 2062dd1de374Slin wang - Sun Microsystems - Beijing China 2063dd1de374Slin wang - Sun Microsystems - Beijing China /* 2064dd1de374Slin wang - Sun Microsystems - Beijing China * Enable/Disable short slot timing 2065dd1de374Slin wang - Sun Microsystems - Beijing China */ 2066dd1de374Slin wang - Sun Microsystems - Beijing China void 2067dd1de374Slin wang - Sun Microsystems - Beijing China arn_set_shortslot(ieee80211com_t *ic, int onoff) 2068dd1de374Slin wang - Sun Microsystems - Beijing China { 2069dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_hal *ah = ((struct arn_softc *)ic)->sc_ah; 2070dd1de374Slin wang - Sun Microsystems - Beijing China 2071dd1de374Slin wang - Sun Microsystems - Beijing China if (onoff) 2072dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_setslottime(ah, ATH9K_SLOT_TIME_9); 2073dd1de374Slin wang - Sun Microsystems - Beijing China else 2074dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_setslottime(ah, ATH9K_SLOT_TIME_20); 2075dd1de374Slin wang - Sun Microsystems - Beijing China } 2076dd1de374Slin wang - Sun Microsystems - Beijing China 2077dd1de374Slin wang - Sun Microsystems - Beijing China static int 2078dd1de374Slin wang - Sun Microsystems - Beijing China arn_open(struct arn_softc *sc) 2079dd1de374Slin wang - Sun Microsystems - Beijing China { 2080dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211com_t *ic = (ieee80211com_t *)sc; 2081dd1de374Slin wang - Sun Microsystems - Beijing China struct ieee80211_channel *curchan = ic->ic_curchan; 2082dd1de374Slin wang - Sun Microsystems - Beijing China struct ath9k_channel *init_channel; 2083dd1de374Slin wang - Sun Microsystems - Beijing China int error = 0, pos, status; 2084dd1de374Slin wang - Sun Microsystems - Beijing China 2085dd1de374Slin wang - Sun Microsystems - Beijing China ARN_LOCK_ASSERT(sc); 2086dd1de374Slin wang - Sun Microsystems - Beijing China 2087dd1de374Slin wang - Sun Microsystems - Beijing China pos = arn_get_channel(sc, curchan); 2088dd1de374Slin wang - Sun Microsystems - Beijing China if (pos == -1) { 2089dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_FATAL, "arn: " 2090dd1de374Slin wang - Sun Microsystems - Beijing China "%s: Invalid channel\n", __func__)); 2091dd1de374Slin wang - Sun Microsystems - Beijing China error = EINVAL; 2092dd1de374Slin wang - Sun Microsystems - Beijing China goto error; 2093dd1de374Slin wang - Sun Microsystems - Beijing China } 2094dd1de374Slin wang - Sun Microsystems - Beijing China 2095dd1de374Slin wang - Sun Microsystems - Beijing China sc->tx_chan_width = ATH9K_HT_MACMODE_20; 2096dd1de374Slin wang - Sun Microsystems - Beijing China 2097dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_curmode == ATH9K_MODE_11A) { 2098dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_ah->ah_channels[pos].chanmode = CHANNEL_A; 2099dd1de374Slin wang - Sun Microsystems - Beijing China } else { 2100dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_ah->ah_channels[pos].chanmode = CHANNEL_G; 2101dd1de374Slin wang - Sun Microsystems - Beijing China } 2102dd1de374Slin wang - Sun Microsystems - Beijing China 2103dd1de374Slin wang - Sun Microsystems - Beijing China init_channel = &sc->sc_ah->ah_channels[pos]; 2104dd1de374Slin wang - Sun Microsystems - Beijing China 2105dd1de374Slin wang - Sun Microsystems - Beijing China /* Reset SERDES registers */ 2106dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_configpcipowersave(sc->sc_ah, 0); 2107dd1de374Slin wang - Sun Microsystems - Beijing China 2108dd1de374Slin wang - Sun Microsystems - Beijing China /* 2109dd1de374Slin wang - Sun Microsystems - Beijing China * The basic interface to setting the hardware in a good 2110dd1de374Slin wang - Sun Microsystems - Beijing China * state is ``reset''. On return the hardware is known to 2111dd1de374Slin wang - Sun Microsystems - Beijing China * be powered up and with interrupts disabled. This must 2112dd1de374Slin wang - Sun Microsystems - Beijing China * be followed by initialization of the appropriate bits 2113dd1de374Slin wang - Sun Microsystems - Beijing China * and then setup of the interrupt mask. 2114dd1de374Slin wang - Sun Microsystems - Beijing China */ 2115dd1de374Slin wang - Sun Microsystems - Beijing China if (!ath9k_hw_reset(sc->sc_ah, init_channel, 2116dd1de374Slin wang - Sun Microsystems - Beijing China sc->tx_chan_width, sc->sc_tx_chainmask, 2117dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_rx_chainmask, sc->sc_ht_extprotspacing, 2118dd1de374Slin wang - Sun Microsystems - Beijing China B_FALSE, &status)) { 2119dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_FATAL, "arn: " 2120dd1de374Slin wang - Sun Microsystems - Beijing China "%s: unable to reset hardware; hal status %u " 2121dd1de374Slin wang - Sun Microsystems - Beijing China "(freq %u flags 0x%x)\n", __func__, status, 2122dd1de374Slin wang - Sun Microsystems - Beijing China init_channel->channel, init_channel->channelFlags)); 2123dd1de374Slin wang - Sun Microsystems - Beijing China 2124dd1de374Slin wang - Sun Microsystems - Beijing China error = EIO; 2125dd1de374Slin wang - Sun Microsystems - Beijing China goto error; 2126dd1de374Slin wang - Sun Microsystems - Beijing China } 2127dd1de374Slin wang - Sun Microsystems - Beijing China 2128dd1de374Slin wang - Sun Microsystems - Beijing China /* 2129dd1de374Slin wang - Sun Microsystems - Beijing China * This is needed only to setup initial state 2130dd1de374Slin wang - Sun Microsystems - Beijing China * but it's best done after a reset. 2131dd1de374Slin wang - Sun Microsystems - Beijing China */ 2132dd1de374Slin wang - Sun Microsystems - Beijing China arn_update_txpow(sc); 2133dd1de374Slin wang - Sun Microsystems - Beijing China 2134dd1de374Slin wang - Sun Microsystems - Beijing China /* 2135dd1de374Slin wang - Sun Microsystems - Beijing China * Setup the hardware after reset: 2136dd1de374Slin wang - Sun Microsystems - Beijing China * The receive engine is set going. 2137dd1de374Slin wang - Sun Microsystems - Beijing China * Frame transmit is handled entirely 2138dd1de374Slin wang - Sun Microsystems - Beijing China * in the frame output path; there's nothing to do 2139dd1de374Slin wang - Sun Microsystems - Beijing China * here except setup the interrupt mask. 2140dd1de374Slin wang - Sun Microsystems - Beijing China */ 2141dd1de374Slin wang - Sun Microsystems - Beijing China if (arn_startrecv(sc) != 0) { 2142dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_INIT, "arn: " 2143dd1de374Slin wang - Sun Microsystems - Beijing China "%s: unable to start recv logic\n", __func__)); 2144dd1de374Slin wang - Sun Microsystems - Beijing China error = EIO; 2145dd1de374Slin wang - Sun Microsystems - Beijing China goto error; 2146dd1de374Slin wang - Sun Microsystems - Beijing China } 2147dd1de374Slin wang - Sun Microsystems - Beijing China 2148dd1de374Slin wang - Sun Microsystems - Beijing China /* Setup our intr mask. */ 2149dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_imask = ATH9K_INT_RX | ATH9K_INT_TX | 2150dd1de374Slin wang - Sun Microsystems - Beijing China ATH9K_INT_RXEOL | ATH9K_INT_RXORN | 2151dd1de374Slin wang - Sun Microsystems - Beijing China ATH9K_INT_FATAL | ATH9K_INT_GLOBAL; 2152dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_ATH9K_HW_CAP_GTT 2153dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_GTT) 2154dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_imask |= ATH9K_INT_GTT; 2155dd1de374Slin wang - Sun Microsystems - Beijing China #endif 2156dd1de374Slin wang - Sun Microsystems - Beijing China 2157dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_ATH9K_HW_CAP_GTT 2158dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) 2159dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_imask |= ATH9K_INT_CST; 2160dd1de374Slin wang - Sun Microsystems - Beijing China #endif 2161dd1de374Slin wang - Sun Microsystems - Beijing China 2162dd1de374Slin wang - Sun Microsystems - Beijing China /* 2163dd1de374Slin wang - Sun Microsystems - Beijing China * Enable MIB interrupts when there are hardware phy counters. 2164dd1de374Slin wang - Sun Microsystems - Beijing China * Note we only do this (at the moment) for station mode. 2165dd1de374Slin wang - Sun Microsystems - Beijing China */ 2166dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_ATH9K_INT_MIB 2167dd1de374Slin wang - Sun Microsystems - Beijing China if (ath9k_hw_phycounters(sc->sc_ah) && 2168dd1de374Slin wang - Sun Microsystems - Beijing China ((sc->sc_ah->ah_opmode == ATH9K_M_STA) || 2169dd1de374Slin wang - Sun Microsystems - Beijing China (sc->sc_ah->ah_opmode == ATH9K_M_IBSS))) 2170dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_imask |= ATH9K_INT_MIB; 2171dd1de374Slin wang - Sun Microsystems - Beijing China #endif 2172dd1de374Slin wang - Sun Microsystems - Beijing China /* 2173dd1de374Slin wang - Sun Microsystems - Beijing China * Some hardware processes the TIM IE and fires an 2174dd1de374Slin wang - Sun Microsystems - Beijing China * interrupt when the TIM bit is set. For hardware 2175dd1de374Slin wang - Sun Microsystems - Beijing China * that does, if not overridden by configuration, 2176dd1de374Slin wang - Sun Microsystems - Beijing China * enable the TIM interrupt when operating as station. 2177dd1de374Slin wang - Sun Microsystems - Beijing China */ 2178dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_ATH9K_INT_TIM 2179dd1de374Slin wang - Sun Microsystems - Beijing China if ((sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_ENHANCEDPM) && 2180dd1de374Slin wang - Sun Microsystems - Beijing China (sc->sc_ah->ah_opmode == ATH9K_M_STA) && 2181dd1de374Slin wang - Sun Microsystems - Beijing China !sc->sc_config.swBeaconProcess) 2182dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_imask |= ATH9K_INT_TIM; 2183dd1de374Slin wang - Sun Microsystems - Beijing China #endif 2184dd1de374Slin wang - Sun Microsystems - Beijing China if (arn_chan2mode(init_channel) != sc->sc_curmode) 2185dd1de374Slin wang - Sun Microsystems - Beijing China arn_setcurmode(sc, arn_chan2mode(init_channel)); 2186dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_INIT, "arn: " 2187dd1de374Slin wang - Sun Microsystems - Beijing China "%s: current mode after arn_setcurmode is %d\n", 2188dd1de374Slin wang - Sun Microsystems - Beijing China __func__, sc->sc_curmode)); 2189dd1de374Slin wang - Sun Microsystems - Beijing China 2190dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_isrunning = 1; 2191dd1de374Slin wang - Sun Microsystems - Beijing China 2192dd1de374Slin wang - Sun Microsystems - Beijing China /* Disable BMISS interrupt when we're not associated */ 2193dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); 2194dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask); 2195dd1de374Slin wang - Sun Microsystems - Beijing China 2196dd1de374Slin wang - Sun Microsystems - Beijing China return (0); 2197dd1de374Slin wang - Sun Microsystems - Beijing China 2198dd1de374Slin wang - Sun Microsystems - Beijing China error: 2199dd1de374Slin wang - Sun Microsystems - Beijing China return (error); 2200dd1de374Slin wang - Sun Microsystems - Beijing China } 2201dd1de374Slin wang - Sun Microsystems - Beijing China 2202dd1de374Slin wang - Sun Microsystems - Beijing China static void 2203dd1de374Slin wang - Sun Microsystems - Beijing China arn_close(struct arn_softc *sc) 2204dd1de374Slin wang - Sun Microsystems - Beijing China { 2205dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211com_t *ic = (ieee80211com_t *)sc; 2206dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_hal *ah = sc->sc_ah; 2207dd1de374Slin wang - Sun Microsystems - Beijing China 2208dd1de374Slin wang - Sun Microsystems - Beijing China ARN_LOCK_ASSERT(sc); 2209dd1de374Slin wang - Sun Microsystems - Beijing China 2210dd1de374Slin wang - Sun Microsystems - Beijing China if (!sc->sc_isrunning) 2211dd1de374Slin wang - Sun Microsystems - Beijing China return; 2212dd1de374Slin wang - Sun Microsystems - Beijing China 2213dd1de374Slin wang - Sun Microsystems - Beijing China /* 2214dd1de374Slin wang - Sun Microsystems - Beijing China * Shutdown the hardware and driver 2215dd1de374Slin wang - Sun Microsystems - Beijing China * Note that some of this work is not possible if the 2216dd1de374Slin wang - Sun Microsystems - Beijing China * hardware is gone (invalid). 2217dd1de374Slin wang - Sun Microsystems - Beijing China */ 2218dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 2219dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 2220dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211_stop_watchdog(ic); 2221dd1de374Slin wang - Sun Microsystems - Beijing China ARN_LOCK(sc); 2222dd1de374Slin wang - Sun Microsystems - Beijing China 2223dd1de374Slin wang - Sun Microsystems - Beijing China /* 2224dd1de374Slin wang - Sun Microsystems - Beijing China * make sure h/w will not generate any interrupt 2225dd1de374Slin wang - Sun Microsystems - Beijing China * before setting the invalid flag. 2226dd1de374Slin wang - Sun Microsystems - Beijing China */ 2227dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_set_interrupts(ah, 0); 2228dd1de374Slin wang - Sun Microsystems - Beijing China 2229dd1de374Slin wang - Sun Microsystems - Beijing China if (!(sc->sc_flags & SC_OP_INVALID)) { 2230dd1de374Slin wang - Sun Microsystems - Beijing China arn_draintxq(sc, 0); 2231dd1de374Slin wang - Sun Microsystems - Beijing China (void) arn_stoprecv(sc); 2232dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_phy_disable(ah); 2233dd1de374Slin wang - Sun Microsystems - Beijing China } else { 2234dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_rxlink = NULL; 2235dd1de374Slin wang - Sun Microsystems - Beijing China } 2236dd1de374Slin wang - Sun Microsystems - Beijing China 2237dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_isrunning = 0; 2238dd1de374Slin wang - Sun Microsystems - Beijing China } 2239dd1de374Slin wang - Sun Microsystems - Beijing China 2240dd1de374Slin wang - Sun Microsystems - Beijing China /* 2241dd1de374Slin wang - Sun Microsystems - Beijing China * MAC callback functions 2242dd1de374Slin wang - Sun Microsystems - Beijing China */ 2243dd1de374Slin wang - Sun Microsystems - Beijing China static int 2244dd1de374Slin wang - Sun Microsystems - Beijing China arn_m_stat(void *arg, uint_t stat, uint64_t *val) 2245dd1de374Slin wang - Sun Microsystems - Beijing China { 2246dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = arg; 2247dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211com_t *ic = (ieee80211com_t *)sc; 2248dd1de374Slin wang - Sun Microsystems - Beijing China struct ieee80211_node *in; 2249dd1de374Slin wang - Sun Microsystems - Beijing China struct ieee80211_rateset *rs; 2250dd1de374Slin wang - Sun Microsystems - Beijing China 2251dd1de374Slin wang - Sun Microsystems - Beijing China ARN_LOCK(sc); 2252dd1de374Slin wang - Sun Microsystems - Beijing China switch (stat) { 2253dd1de374Slin wang - Sun Microsystems - Beijing China case MAC_STAT_IFSPEED: 2254dd1de374Slin wang - Sun Microsystems - Beijing China in = ic->ic_bss; 2255dd1de374Slin wang - Sun Microsystems - Beijing China rs = &in->in_rates; 2256dd1de374Slin wang - Sun Microsystems - Beijing China *val = (rs->ir_rates[in->in_txrate] & IEEE80211_RATE_VAL) / 2 * 2257dd1de374Slin wang - Sun Microsystems - Beijing China 1000000ull; 2258dd1de374Slin wang - Sun Microsystems - Beijing China break; 2259dd1de374Slin wang - Sun Microsystems - Beijing China case MAC_STAT_NOXMTBUF: 2260dd1de374Slin wang - Sun Microsystems - Beijing China *val = sc->sc_stats.ast_tx_nobuf + 2261dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_stats.ast_tx_nobufmgt; 2262dd1de374Slin wang - Sun Microsystems - Beijing China break; 2263dd1de374Slin wang - Sun Microsystems - Beijing China case MAC_STAT_IERRORS: 2264dd1de374Slin wang - Sun Microsystems - Beijing China *val = sc->sc_stats.ast_rx_tooshort; 2265dd1de374Slin wang - Sun Microsystems - Beijing China break; 2266dd1de374Slin wang - Sun Microsystems - Beijing China case MAC_STAT_RBYTES: 2267dd1de374Slin wang - Sun Microsystems - Beijing China *val = ic->ic_stats.is_rx_bytes; 2268dd1de374Slin wang - Sun Microsystems - Beijing China break; 2269dd1de374Slin wang - Sun Microsystems - Beijing China case MAC_STAT_IPACKETS: 2270dd1de374Slin wang - Sun Microsystems - Beijing China *val = ic->ic_stats.is_rx_frags; 2271dd1de374Slin wang - Sun Microsystems - Beijing China break; 2272dd1de374Slin wang - Sun Microsystems - Beijing China case MAC_STAT_OBYTES: 2273dd1de374Slin wang - Sun Microsystems - Beijing China *val = ic->ic_stats.is_tx_bytes; 2274dd1de374Slin wang - Sun Microsystems - Beijing China break; 2275dd1de374Slin wang - Sun Microsystems - Beijing China case MAC_STAT_OPACKETS: 2276dd1de374Slin wang - Sun Microsystems - Beijing China *val = ic->ic_stats.is_tx_frags; 2277dd1de374Slin wang - Sun Microsystems - Beijing China break; 2278dd1de374Slin wang - Sun Microsystems - Beijing China case MAC_STAT_OERRORS: 2279dd1de374Slin wang - Sun Microsystems - Beijing China case WIFI_STAT_TX_FAILED: 2280dd1de374Slin wang - Sun Microsystems - Beijing China *val = sc->sc_stats.ast_tx_fifoerr + 2281dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_stats.ast_tx_xretries + 2282dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_stats.ast_tx_discard; 2283dd1de374Slin wang - Sun Microsystems - Beijing China break; 2284dd1de374Slin wang - Sun Microsystems - Beijing China case WIFI_STAT_TX_RETRANS: 2285dd1de374Slin wang - Sun Microsystems - Beijing China *val = sc->sc_stats.ast_tx_xretries; 2286dd1de374Slin wang - Sun Microsystems - Beijing China break; 2287dd1de374Slin wang - Sun Microsystems - Beijing China case WIFI_STAT_FCS_ERRORS: 2288dd1de374Slin wang - Sun Microsystems - Beijing China *val = sc->sc_stats.ast_rx_crcerr; 2289dd1de374Slin wang - Sun Microsystems - Beijing China break; 2290dd1de374Slin wang - Sun Microsystems - Beijing China case WIFI_STAT_WEP_ERRORS: 2291dd1de374Slin wang - Sun Microsystems - Beijing China *val = sc->sc_stats.ast_rx_badcrypt; 2292dd1de374Slin wang - Sun Microsystems - Beijing China break; 2293dd1de374Slin wang - Sun Microsystems - Beijing China case WIFI_STAT_TX_FRAGS: 2294dd1de374Slin wang - Sun Microsystems - Beijing China case WIFI_STAT_MCAST_TX: 2295dd1de374Slin wang - Sun Microsystems - Beijing China case WIFI_STAT_RTS_SUCCESS: 2296dd1de374Slin wang - Sun Microsystems - Beijing China case WIFI_STAT_RTS_FAILURE: 2297dd1de374Slin wang - Sun Microsystems - Beijing China case WIFI_STAT_ACK_FAILURE: 2298dd1de374Slin wang - Sun Microsystems - Beijing China case WIFI_STAT_RX_FRAGS: 2299dd1de374Slin wang - Sun Microsystems - Beijing China case WIFI_STAT_MCAST_RX: 2300dd1de374Slin wang - Sun Microsystems - Beijing China case WIFI_STAT_RX_DUPS: 2301dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 2302dd1de374Slin wang - Sun Microsystems - Beijing China return (ieee80211_stat(ic, stat, val)); 2303dd1de374Slin wang - Sun Microsystems - Beijing China default: 2304dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 2305dd1de374Slin wang - Sun Microsystems - Beijing China return (ENOTSUP); 2306dd1de374Slin wang - Sun Microsystems - Beijing China } 2307dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 2308dd1de374Slin wang - Sun Microsystems - Beijing China 2309dd1de374Slin wang - Sun Microsystems - Beijing China return (0); 2310dd1de374Slin wang - Sun Microsystems - Beijing China } 2311dd1de374Slin wang - Sun Microsystems - Beijing China 2312dd1de374Slin wang - Sun Microsystems - Beijing China int 2313dd1de374Slin wang - Sun Microsystems - Beijing China arn_m_start(void *arg) 2314dd1de374Slin wang - Sun Microsystems - Beijing China { 2315dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = arg; 2316dd1de374Slin wang - Sun Microsystems - Beijing China int err = 0; 2317dd1de374Slin wang - Sun Microsystems - Beijing China 2318dd1de374Slin wang - Sun Microsystems - Beijing China ARN_LOCK(sc); 2319dd1de374Slin wang - Sun Microsystems - Beijing China 2320dd1de374Slin wang - Sun Microsystems - Beijing China /* 2321dd1de374Slin wang - Sun Microsystems - Beijing China * Stop anything previously setup. This is safe 2322dd1de374Slin wang - Sun Microsystems - Beijing China * whether this is the first time through or not. 2323dd1de374Slin wang - Sun Microsystems - Beijing China */ 2324dd1de374Slin wang - Sun Microsystems - Beijing China 2325dd1de374Slin wang - Sun Microsystems - Beijing China arn_close(sc); 2326dd1de374Slin wang - Sun Microsystems - Beijing China 2327dd1de374Slin wang - Sun Microsystems - Beijing China if ((err = arn_open(sc)) != 0) { 2328dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 2329dd1de374Slin wang - Sun Microsystems - Beijing China return (err); 2330dd1de374Slin wang - Sun Microsystems - Beijing China } 2331dd1de374Slin wang - Sun Microsystems - Beijing China 2332dd1de374Slin wang - Sun Microsystems - Beijing China /* H/W is reday now */ 2333dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_flags &= ~SC_OP_INVALID; 2334dd1de374Slin wang - Sun Microsystems - Beijing China 2335dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 2336dd1de374Slin wang - Sun Microsystems - Beijing China 2337dd1de374Slin wang - Sun Microsystems - Beijing China return (0); 2338dd1de374Slin wang - Sun Microsystems - Beijing China } 2339dd1de374Slin wang - Sun Microsystems - Beijing China 2340dd1de374Slin wang - Sun Microsystems - Beijing China static void 2341dd1de374Slin wang - Sun Microsystems - Beijing China arn_m_stop(void *arg) 2342dd1de374Slin wang - Sun Microsystems - Beijing China { 2343dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = arg; 2344dd1de374Slin wang - Sun Microsystems - Beijing China 2345dd1de374Slin wang - Sun Microsystems - Beijing China ARN_LOCK(sc); 2346dd1de374Slin wang - Sun Microsystems - Beijing China arn_close(sc); 2347dd1de374Slin wang - Sun Microsystems - Beijing China 2348dd1de374Slin wang - Sun Microsystems - Beijing China /* disable HAL and put h/w to sleep */ 2349dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_disable(sc->sc_ah); 2350dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_configpcipowersave(sc->sc_ah, 1); 2351dd1de374Slin wang - Sun Microsystems - Beijing China 2352dd1de374Slin wang - Sun Microsystems - Beijing China /* XXX: hardware will not be ready in suspend state */ 2353dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_flags |= SC_OP_INVALID; 2354dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 2355dd1de374Slin wang - Sun Microsystems - Beijing China } 2356dd1de374Slin wang - Sun Microsystems - Beijing China 2357dd1de374Slin wang - Sun Microsystems - Beijing China static int 2358dd1de374Slin wang - Sun Microsystems - Beijing China arn_m_promisc(void *arg, boolean_t on) 2359dd1de374Slin wang - Sun Microsystems - Beijing China { 2360dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = arg; 2361dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_hal *ah = sc->sc_ah; 2362dd1de374Slin wang - Sun Microsystems - Beijing China uint32_t rfilt; 2363dd1de374Slin wang - Sun Microsystems - Beijing China 2364dd1de374Slin wang - Sun Microsystems - Beijing China ARN_LOCK(sc); 2365dd1de374Slin wang - Sun Microsystems - Beijing China 2366dd1de374Slin wang - Sun Microsystems - Beijing China rfilt = ath9k_hw_getrxfilter(ah); 2367dd1de374Slin wang - Sun Microsystems - Beijing China if (on) 2368dd1de374Slin wang - Sun Microsystems - Beijing China rfilt |= ATH9K_RX_FILTER_PROM; 2369dd1de374Slin wang - Sun Microsystems - Beijing China else 2370dd1de374Slin wang - Sun Microsystems - Beijing China rfilt &= ~ATH9K_RX_FILTER_PROM; 2371dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_promisc = on; 2372dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_setrxfilter(ah, rfilt); 2373dd1de374Slin wang - Sun Microsystems - Beijing China 2374dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 2375dd1de374Slin wang - Sun Microsystems - Beijing China 2376dd1de374Slin wang - Sun Microsystems - Beijing China return (0); 2377dd1de374Slin wang - Sun Microsystems - Beijing China } 2378dd1de374Slin wang - Sun Microsystems - Beijing China 2379dd1de374Slin wang - Sun Microsystems - Beijing China static int 2380dd1de374Slin wang - Sun Microsystems - Beijing China arn_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 2381dd1de374Slin wang - Sun Microsystems - Beijing China { 2382dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = arg; 2383dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_hal *ah = sc->sc_ah; 2384dd1de374Slin wang - Sun Microsystems - Beijing China uint32_t val, index, bit; 2385dd1de374Slin wang - Sun Microsystems - Beijing China uint8_t pos; 2386dd1de374Slin wang - Sun Microsystems - Beijing China uint32_t *mfilt = sc->sc_mcast_hash; 2387dd1de374Slin wang - Sun Microsystems - Beijing China 2388dd1de374Slin wang - Sun Microsystems - Beijing China ARN_LOCK(sc); 2389dd1de374Slin wang - Sun Microsystems - Beijing China 2390dd1de374Slin wang - Sun Microsystems - Beijing China /* calculate XOR of eight 6bit values */ 2391dd1de374Slin wang - Sun Microsystems - Beijing China val = ARN_LE_READ_32(mca + 0); 2392dd1de374Slin wang - Sun Microsystems - Beijing China pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; 2393dd1de374Slin wang - Sun Microsystems - Beijing China val = ARN_LE_READ_32(mca + 3); 2394dd1de374Slin wang - Sun Microsystems - Beijing China pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; 2395dd1de374Slin wang - Sun Microsystems - Beijing China pos &= 0x3f; 2396dd1de374Slin wang - Sun Microsystems - Beijing China index = pos / 32; 2397dd1de374Slin wang - Sun Microsystems - Beijing China bit = 1 << (pos % 32); 2398dd1de374Slin wang - Sun Microsystems - Beijing China 2399dd1de374Slin wang - Sun Microsystems - Beijing China if (add) { /* enable multicast */ 2400dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_mcast_refs[pos]++; 2401dd1de374Slin wang - Sun Microsystems - Beijing China mfilt[index] |= bit; 2402dd1de374Slin wang - Sun Microsystems - Beijing China } else { /* disable multicast */ 2403dd1de374Slin wang - Sun Microsystems - Beijing China if (--sc->sc_mcast_refs[pos] == 0) 2404dd1de374Slin wang - Sun Microsystems - Beijing China mfilt[index] &= ~bit; 2405dd1de374Slin wang - Sun Microsystems - Beijing China } 2406dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); 2407dd1de374Slin wang - Sun Microsystems - Beijing China 2408dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 2409dd1de374Slin wang - Sun Microsystems - Beijing China return (0); 2410dd1de374Slin wang - Sun Microsystems - Beijing China } 2411dd1de374Slin wang - Sun Microsystems - Beijing China 2412dd1de374Slin wang - Sun Microsystems - Beijing China static int 2413dd1de374Slin wang - Sun Microsystems - Beijing China arn_m_unicst(void *arg, const uint8_t *macaddr) 2414dd1de374Slin wang - Sun Microsystems - Beijing China { 2415dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = arg; 2416dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_hal *ah = sc->sc_ah; 2417dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211com_t *ic = (ieee80211com_t *)sc; 2418dd1de374Slin wang - Sun Microsystems - Beijing China 2419dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_XMIT, "ath: ath_gld_saddr(): " 2420dd1de374Slin wang - Sun Microsystems - Beijing China "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", 2421dd1de374Slin wang - Sun Microsystems - Beijing China macaddr[0], macaddr[1], macaddr[2], 2422dd1de374Slin wang - Sun Microsystems - Beijing China macaddr[3], macaddr[4], macaddr[5])); 2423dd1de374Slin wang - Sun Microsystems - Beijing China 2424dd1de374Slin wang - Sun Microsystems - Beijing China ARN_LOCK(sc); 2425dd1de374Slin wang - Sun Microsystems - Beijing China IEEE80211_ADDR_COPY(sc->sc_isc.ic_macaddr, macaddr); 2426dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_setmac(ah, sc->sc_isc.ic_macaddr); 2427dd1de374Slin wang - Sun Microsystems - Beijing China (void) arn_reset(ic); 2428dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 2429dd1de374Slin wang - Sun Microsystems - Beijing China return (0); 2430dd1de374Slin wang - Sun Microsystems - Beijing China } 2431dd1de374Slin wang - Sun Microsystems - Beijing China 2432dd1de374Slin wang - Sun Microsystems - Beijing China static mblk_t * 2433dd1de374Slin wang - Sun Microsystems - Beijing China arn_m_tx(void *arg, mblk_t *mp) 2434dd1de374Slin wang - Sun Microsystems - Beijing China { 2435dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = arg; 2436dd1de374Slin wang - Sun Microsystems - Beijing China int error = 0; 2437dd1de374Slin wang - Sun Microsystems - Beijing China mblk_t *next; 2438dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211com_t *ic = (ieee80211com_t *)sc; 2439dd1de374Slin wang - Sun Microsystems - Beijing China 2440dd1de374Slin wang - Sun Microsystems - Beijing China /* 2441dd1de374Slin wang - Sun Microsystems - Beijing China * No data frames go out unless we're associated; this 2442dd1de374Slin wang - Sun Microsystems - Beijing China * should not happen as the 802.11 layer does not enable 2443dd1de374Slin wang - Sun Microsystems - Beijing China * the xmit queue until we enter the RUN state. 2444dd1de374Slin wang - Sun Microsystems - Beijing China */ 2445dd1de374Slin wang - Sun Microsystems - Beijing China if (ic->ic_state != IEEE80211_S_RUN) { 2446dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_XMIT, "arn: arn_m_tx(): " 2447dd1de374Slin wang - Sun Microsystems - Beijing China "discard, state %u\n", ic->ic_state)); 2448dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_stats.ast_tx_discard++; 2449dd1de374Slin wang - Sun Microsystems - Beijing China freemsgchain(mp); 2450dd1de374Slin wang - Sun Microsystems - Beijing China return (NULL); 2451dd1de374Slin wang - Sun Microsystems - Beijing China } 2452dd1de374Slin wang - Sun Microsystems - Beijing China 2453dd1de374Slin wang - Sun Microsystems - Beijing China while (mp != NULL) { 2454dd1de374Slin wang - Sun Microsystems - Beijing China next = mp->b_next; 2455dd1de374Slin wang - Sun Microsystems - Beijing China mp->b_next = NULL; 2456dd1de374Slin wang - Sun Microsystems - Beijing China error = arn_tx(ic, mp, IEEE80211_FC0_TYPE_DATA); 2457dd1de374Slin wang - Sun Microsystems - Beijing China if (error != 0) { 2458dd1de374Slin wang - Sun Microsystems - Beijing China mp->b_next = next; 2459dd1de374Slin wang - Sun Microsystems - Beijing China if (error == ENOMEM) { 2460dd1de374Slin wang - Sun Microsystems - Beijing China break; 2461dd1de374Slin wang - Sun Microsystems - Beijing China } else { 2462dd1de374Slin wang - Sun Microsystems - Beijing China freemsgchain(mp); 2463dd1de374Slin wang - Sun Microsystems - Beijing China return (NULL); 2464dd1de374Slin wang - Sun Microsystems - Beijing China } 2465dd1de374Slin wang - Sun Microsystems - Beijing China } 2466dd1de374Slin wang - Sun Microsystems - Beijing China mp = next; 2467dd1de374Slin wang - Sun Microsystems - Beijing China } 2468dd1de374Slin wang - Sun Microsystems - Beijing China 2469dd1de374Slin wang - Sun Microsystems - Beijing China return (mp); 2470dd1de374Slin wang - Sun Microsystems - Beijing China } 2471dd1de374Slin wang - Sun Microsystems - Beijing China 2472dd1de374Slin wang - Sun Microsystems - Beijing China static void 2473dd1de374Slin wang - Sun Microsystems - Beijing China arn_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 2474dd1de374Slin wang - Sun Microsystems - Beijing China { 2475dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = arg; 2476dd1de374Slin wang - Sun Microsystems - Beijing China int32_t err; 2477dd1de374Slin wang - Sun Microsystems - Beijing China 2478dd1de374Slin wang - Sun Microsystems - Beijing China err = ieee80211_ioctl(&sc->sc_isc, wq, mp); 2479dd1de374Slin wang - Sun Microsystems - Beijing China 2480dd1de374Slin wang - Sun Microsystems - Beijing China ARN_LOCK(sc); 2481dd1de374Slin wang - Sun Microsystems - Beijing China if (err == ENETRESET) { 2482dd1de374Slin wang - Sun Microsystems - Beijing China if (!(sc->sc_flags & SC_OP_INVALID)) { 2483dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 2484dd1de374Slin wang - Sun Microsystems - Beijing China 2485dd1de374Slin wang - Sun Microsystems - Beijing China (void) arn_m_start(sc); 2486dd1de374Slin wang - Sun Microsystems - Beijing China 2487dd1de374Slin wang - Sun Microsystems - Beijing China (void) ieee80211_new_state(&sc->sc_isc, 2488dd1de374Slin wang - Sun Microsystems - Beijing China IEEE80211_S_SCAN, -1); 2489dd1de374Slin wang - Sun Microsystems - Beijing China ARN_LOCK(sc); 2490dd1de374Slin wang - Sun Microsystems - Beijing China } 2491dd1de374Slin wang - Sun Microsystems - Beijing China } 2492dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 2493dd1de374Slin wang - Sun Microsystems - Beijing China } 2494dd1de374Slin wang - Sun Microsystems - Beijing China 2495dd1de374Slin wang - Sun Microsystems - Beijing China static int 2496dd1de374Slin wang - Sun Microsystems - Beijing China arn_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 2497dd1de374Slin wang - Sun Microsystems - Beijing China uint_t wldp_length, const void *wldp_buf) 2498dd1de374Slin wang - Sun Microsystems - Beijing China { 2499dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = arg; 2500dd1de374Slin wang - Sun Microsystems - Beijing China int err; 2501dd1de374Slin wang - Sun Microsystems - Beijing China 2502dd1de374Slin wang - Sun Microsystems - Beijing China err = ieee80211_setprop(&sc->sc_isc, pr_name, wldp_pr_num, 2503dd1de374Slin wang - Sun Microsystems - Beijing China wldp_length, wldp_buf); 2504dd1de374Slin wang - Sun Microsystems - Beijing China 2505dd1de374Slin wang - Sun Microsystems - Beijing China ARN_LOCK(sc); 2506dd1de374Slin wang - Sun Microsystems - Beijing China 2507dd1de374Slin wang - Sun Microsystems - Beijing China if (err == ENETRESET) { 2508dd1de374Slin wang - Sun Microsystems - Beijing China if (!(sc->sc_flags & SC_OP_INVALID)) { 2509dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 2510dd1de374Slin wang - Sun Microsystems - Beijing China (void) arn_m_start(sc); 2511dd1de374Slin wang - Sun Microsystems - Beijing China (void) ieee80211_new_state(&sc->sc_isc, 2512dd1de374Slin wang - Sun Microsystems - Beijing China IEEE80211_S_SCAN, -1); 2513dd1de374Slin wang - Sun Microsystems - Beijing China ARN_LOCK(sc); 2514dd1de374Slin wang - Sun Microsystems - Beijing China } 2515dd1de374Slin wang - Sun Microsystems - Beijing China err = 0; 2516dd1de374Slin wang - Sun Microsystems - Beijing China } 2517dd1de374Slin wang - Sun Microsystems - Beijing China 2518dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 2519dd1de374Slin wang - Sun Microsystems - Beijing China 2520dd1de374Slin wang - Sun Microsystems - Beijing China return (err); 2521dd1de374Slin wang - Sun Microsystems - Beijing China } 2522dd1de374Slin wang - Sun Microsystems - Beijing China 2523dd1de374Slin wang - Sun Microsystems - Beijing China /* ARGSUSED */ 2524dd1de374Slin wang - Sun Microsystems - Beijing China static int 2525dd1de374Slin wang - Sun Microsystems - Beijing China arn_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 25260dc2366fSVenugopal Iyer uint_t wldp_length, void *wldp_buf) 2527dd1de374Slin wang - Sun Microsystems - Beijing China { 2528dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = arg; 2529dd1de374Slin wang - Sun Microsystems - Beijing China int err = 0; 2530dd1de374Slin wang - Sun Microsystems - Beijing China 2531dd1de374Slin wang - Sun Microsystems - Beijing China err = ieee80211_getprop(&sc->sc_isc, pr_name, wldp_pr_num, 25320dc2366fSVenugopal Iyer wldp_length, wldp_buf); 2533dd1de374Slin wang - Sun Microsystems - Beijing China 2534dd1de374Slin wang - Sun Microsystems - Beijing China return (err); 2535dd1de374Slin wang - Sun Microsystems - Beijing China } 2536dd1de374Slin wang - Sun Microsystems - Beijing China 25370dc2366fSVenugopal Iyer static void 25380dc2366fSVenugopal Iyer arn_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 25390dc2366fSVenugopal Iyer mac_prop_info_handle_t prh) 25400dc2366fSVenugopal Iyer { 25410dc2366fSVenugopal Iyer struct arn_softc *sc = arg; 25420dc2366fSVenugopal Iyer 25430dc2366fSVenugopal Iyer ieee80211_propinfo(&sc->sc_isc, pr_name, wldp_pr_num, prh); 25440dc2366fSVenugopal Iyer } 25450dc2366fSVenugopal Iyer 2546dd1de374Slin wang - Sun Microsystems - Beijing China /* return bus cachesize in 4B word units */ 2547dd1de374Slin wang - Sun Microsystems - Beijing China static void 2548dd1de374Slin wang - Sun Microsystems - Beijing China arn_pci_config_cachesize(struct arn_softc *sc) 2549dd1de374Slin wang - Sun Microsystems - Beijing China { 2550dd1de374Slin wang - Sun Microsystems - Beijing China uint8_t csz; 2551dd1de374Slin wang - Sun Microsystems - Beijing China 2552dd1de374Slin wang - Sun Microsystems - Beijing China /* 2553dd1de374Slin wang - Sun Microsystems - Beijing China * Cache line size is used to size and align various 2554dd1de374Slin wang - Sun Microsystems - Beijing China * structures used to communicate with the hardware. 2555dd1de374Slin wang - Sun Microsystems - Beijing China */ 2556dd1de374Slin wang - Sun Microsystems - Beijing China csz = pci_config_get8(sc->sc_cfg_handle, PCI_CONF_CACHE_LINESZ); 2557dd1de374Slin wang - Sun Microsystems - Beijing China if (csz == 0) { 2558dd1de374Slin wang - Sun Microsystems - Beijing China /* 2559dd1de374Slin wang - Sun Microsystems - Beijing China * We must have this setup properly for rx buffer 2560dd1de374Slin wang - Sun Microsystems - Beijing China * DMA to work so force a reasonable value here if it 2561dd1de374Slin wang - Sun Microsystems - Beijing China * comes up zero. 2562dd1de374Slin wang - Sun Microsystems - Beijing China */ 2563dd1de374Slin wang - Sun Microsystems - Beijing China csz = ATH_DEF_CACHE_BYTES / sizeof (uint32_t); 2564dd1de374Slin wang - Sun Microsystems - Beijing China pci_config_put8(sc->sc_cfg_handle, PCI_CONF_CACHE_LINESZ, 2565dd1de374Slin wang - Sun Microsystems - Beijing China csz); 2566dd1de374Slin wang - Sun Microsystems - Beijing China } 2567dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_cachelsz = csz << 2; 2568dd1de374Slin wang - Sun Microsystems - Beijing China } 2569dd1de374Slin wang - Sun Microsystems - Beijing China 2570dd1de374Slin wang - Sun Microsystems - Beijing China static int 2571dd1de374Slin wang - Sun Microsystems - Beijing China arn_pci_setup(struct arn_softc *sc) 2572dd1de374Slin wang - Sun Microsystems - Beijing China { 2573dd1de374Slin wang - Sun Microsystems - Beijing China uint16_t command; 2574dd1de374Slin wang - Sun Microsystems - Beijing China 2575dd1de374Slin wang - Sun Microsystems - Beijing China /* 2576dd1de374Slin wang - Sun Microsystems - Beijing China * Enable memory mapping and bus mastering 2577dd1de374Slin wang - Sun Microsystems - Beijing China */ 2578dd1de374Slin wang - Sun Microsystems - Beijing China ASSERT(sc != NULL); 2579dd1de374Slin wang - Sun Microsystems - Beijing China command = pci_config_get16(sc->sc_cfg_handle, PCI_CONF_COMM); 2580dd1de374Slin wang - Sun Microsystems - Beijing China command |= PCI_COMM_MAE | PCI_COMM_ME; 2581dd1de374Slin wang - Sun Microsystems - Beijing China pci_config_put16(sc->sc_cfg_handle, PCI_CONF_COMM, command); 2582dd1de374Slin wang - Sun Microsystems - Beijing China command = pci_config_get16(sc->sc_cfg_handle, PCI_CONF_COMM); 2583dd1de374Slin wang - Sun Microsystems - Beijing China if ((command & PCI_COMM_MAE) == 0) { 2584dd1de374Slin wang - Sun Microsystems - Beijing China arn_problem("arn: arn_pci_setup(): " 2585dd1de374Slin wang - Sun Microsystems - Beijing China "failed to enable memory mapping\n"); 2586dd1de374Slin wang - Sun Microsystems - Beijing China return (EIO); 2587dd1de374Slin wang - Sun Microsystems - Beijing China } 2588dd1de374Slin wang - Sun Microsystems - Beijing China if ((command & PCI_COMM_ME) == 0) { 2589dd1de374Slin wang - Sun Microsystems - Beijing China arn_problem("arn: arn_pci_setup(): " 2590dd1de374Slin wang - Sun Microsystems - Beijing China "failed to enable bus mastering\n"); 2591dd1de374Slin wang - Sun Microsystems - Beijing China return (EIO); 2592dd1de374Slin wang - Sun Microsystems - Beijing China } 2593dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_INIT, "arn: arn_pci_setup(): " 2594dd1de374Slin wang - Sun Microsystems - Beijing China "set command reg to 0x%x \n", command)); 2595dd1de374Slin wang - Sun Microsystems - Beijing China 2596dd1de374Slin wang - Sun Microsystems - Beijing China return (0); 2597dd1de374Slin wang - Sun Microsystems - Beijing China } 2598dd1de374Slin wang - Sun Microsystems - Beijing China 2599dd1de374Slin wang - Sun Microsystems - Beijing China static void 2600dd1de374Slin wang - Sun Microsystems - Beijing China arn_get_hw_encap(struct arn_softc *sc) 2601dd1de374Slin wang - Sun Microsystems - Beijing China { 2602dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211com_t *ic; 2603dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_hal *ah; 2604dd1de374Slin wang - Sun Microsystems - Beijing China 2605dd1de374Slin wang - Sun Microsystems - Beijing China ic = (ieee80211com_t *)sc; 2606dd1de374Slin wang - Sun Microsystems - Beijing China ah = sc->sc_ah; 2607dd1de374Slin wang - Sun Microsystems - Beijing China 2608dd1de374Slin wang - Sun Microsystems - Beijing China if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, 2609dd1de374Slin wang - Sun Microsystems - Beijing China ATH9K_CIPHER_AES_CCM, NULL)) 2610dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_caps |= IEEE80211_C_AES_CCM; 2611dd1de374Slin wang - Sun Microsystems - Beijing China if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, 2612dd1de374Slin wang - Sun Microsystems - Beijing China ATH9K_CIPHER_AES_OCB, NULL)) 2613dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_caps |= IEEE80211_C_AES; 2614dd1de374Slin wang - Sun Microsystems - Beijing China if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, 2615dd1de374Slin wang - Sun Microsystems - Beijing China ATH9K_CIPHER_TKIP, NULL)) 2616dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_caps |= IEEE80211_C_TKIP; 2617dd1de374Slin wang - Sun Microsystems - Beijing China if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, 2618dd1de374Slin wang - Sun Microsystems - Beijing China ATH9K_CIPHER_WEP, NULL)) 2619dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_caps |= IEEE80211_C_WEP; 2620dd1de374Slin wang - Sun Microsystems - Beijing China if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, 2621dd1de374Slin wang - Sun Microsystems - Beijing China ATH9K_CIPHER_MIC, NULL)) 2622dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_caps |= IEEE80211_C_TKIPMIC; 2623dd1de374Slin wang - Sun Microsystems - Beijing China } 2624dd1de374Slin wang - Sun Microsystems - Beijing China 2625c0c93480Slin wang - Sun Microsystems - Beijing China static void 2626c0c93480Slin wang - Sun Microsystems - Beijing China arn_setup_ht_cap(struct arn_softc *sc) 2627c0c93480Slin wang - Sun Microsystems - Beijing China { 2628c0c93480Slin wang - Sun Microsystems - Beijing China #define ATH9K_HT_CAP_MAXRXAMPDU_65536 0x3 /* 2 ^ 16 */ 2629c0c93480Slin wang - Sun Microsystems - Beijing China #define ATH9K_HT_CAP_MPDUDENSITY_8 0x6 /* 8 usec */ 2630c0c93480Slin wang - Sun Microsystems - Beijing China 2631c0c93480Slin wang - Sun Microsystems - Beijing China /* LINTED E_FUNC_SET_NOT_USED */ 2632c0c93480Slin wang - Sun Microsystems - Beijing China uint8_t tx_streams; 2633c0c93480Slin wang - Sun Microsystems - Beijing China uint8_t rx_streams; 2634c0c93480Slin wang - Sun Microsystems - Beijing China 2635c0c93480Slin wang - Sun Microsystems - Beijing China arn_ht_conf *ht_info = &sc->sc_ht_conf; 2636c0c93480Slin wang - Sun Microsystems - Beijing China 2637c0c93480Slin wang - Sun Microsystems - Beijing China ht_info->ht_supported = B_TRUE; 2638c0c93480Slin wang - Sun Microsystems - Beijing China 2639c0c93480Slin wang - Sun Microsystems - Beijing China /* Todo: IEEE80211_HTCAP_SMPS */ 2640c0c93480Slin wang - Sun Microsystems - Beijing China ht_info->cap = IEEE80211_HTCAP_CHWIDTH40| 2641c0c93480Slin wang - Sun Microsystems - Beijing China IEEE80211_HTCAP_SHORTGI40 | 2642c0c93480Slin wang - Sun Microsystems - Beijing China IEEE80211_HTCAP_DSSSCCK40; 2643c0c93480Slin wang - Sun Microsystems - Beijing China 2644c0c93480Slin wang - Sun Microsystems - Beijing China ht_info->ampdu_factor = ATH9K_HT_CAP_MAXRXAMPDU_65536; 2645c0c93480Slin wang - Sun Microsystems - Beijing China ht_info->ampdu_density = ATH9K_HT_CAP_MPDUDENSITY_8; 2646c0c93480Slin wang - Sun Microsystems - Beijing China 2647c0c93480Slin wang - Sun Microsystems - Beijing China /* set up supported mcs set */ 2648c0c93480Slin wang - Sun Microsystems - Beijing China (void) memset(&ht_info->rx_mcs_mask, 0, sizeof (ht_info->rx_mcs_mask)); 2649*de710d24SJosef 'Jeff' Sipek tx_streams = ISP2(sc->sc_ah->ah_caps.tx_chainmask) ? 1 : 2; 2650*de710d24SJosef 'Jeff' Sipek rx_streams = ISP2(sc->sc_ah->ah_caps.rx_chainmask) ? 1 : 2; 2651c0c93480Slin wang - Sun Microsystems - Beijing China 2652c0c93480Slin wang - Sun Microsystems - Beijing China ht_info->rx_mcs_mask[0] = 0xff; 2653c0c93480Slin wang - Sun Microsystems - Beijing China if (rx_streams >= 2) 2654c0c93480Slin wang - Sun Microsystems - Beijing China ht_info->rx_mcs_mask[1] = 0xff; 2655c0c93480Slin wang - Sun Microsystems - Beijing China } 2656c0c93480Slin wang - Sun Microsystems - Beijing China 2657c0c93480Slin wang - Sun Microsystems - Beijing China /* xxx should be used for ht rate set negotiating ? */ 2658c0c93480Slin wang - Sun Microsystems - Beijing China static void 2659c0c93480Slin wang - Sun Microsystems - Beijing China arn_overwrite_11n_rateset(struct arn_softc *sc) 2660c0c93480Slin wang - Sun Microsystems - Beijing China { 2661c0c93480Slin wang - Sun Microsystems - Beijing China uint8_t *ht_rs = sc->sc_ht_conf.rx_mcs_mask; 2662c0c93480Slin wang - Sun Microsystems - Beijing China int mcs_idx, mcs_count = 0; 2663c0c93480Slin wang - Sun Microsystems - Beijing China int i, j; 2664c0c93480Slin wang - Sun Microsystems - Beijing China 2665c0c93480Slin wang - Sun Microsystems - Beijing China (void) memset(&ieee80211_rateset_11n, 0, 2666c0c93480Slin wang - Sun Microsystems - Beijing China sizeof (ieee80211_rateset_11n)); 2667c0c93480Slin wang - Sun Microsystems - Beijing China for (i = 0; i < 10; i++) { 2668c0c93480Slin wang - Sun Microsystems - Beijing China for (j = 0; j < 8; j++) { 2669c0c93480Slin wang - Sun Microsystems - Beijing China if (ht_rs[i] & (1 << j)) { 2670c0c93480Slin wang - Sun Microsystems - Beijing China mcs_idx = i * 8 + j; 2671c0c93480Slin wang - Sun Microsystems - Beijing China if (mcs_idx >= IEEE80211_HTRATE_MAXSIZE) { 2672c0c93480Slin wang - Sun Microsystems - Beijing China break; 2673c0c93480Slin wang - Sun Microsystems - Beijing China } 2674c0c93480Slin wang - Sun Microsystems - Beijing China 2675c0c93480Slin wang - Sun Microsystems - Beijing China ieee80211_rateset_11n.rs_rates[mcs_idx] = 2676c0c93480Slin wang - Sun Microsystems - Beijing China (uint8_t)mcs_idx; 2677c0c93480Slin wang - Sun Microsystems - Beijing China mcs_count++; 2678c0c93480Slin wang - Sun Microsystems - Beijing China } 2679c0c93480Slin wang - Sun Microsystems - Beijing China } 2680c0c93480Slin wang - Sun Microsystems - Beijing China } 2681c0c93480Slin wang - Sun Microsystems - Beijing China 2682c0c93480Slin wang - Sun Microsystems - Beijing China ieee80211_rateset_11n.rs_nrates = (uint8_t)mcs_count; 2683c0c93480Slin wang - Sun Microsystems - Beijing China 2684c0c93480Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_RATE, "arn_overwrite_11n_rateset(): " 2685c0c93480Slin wang - Sun Microsystems - Beijing China "MCS rate set supported by this station is as follows:\n")); 2686c0c93480Slin wang - Sun Microsystems - Beijing China 2687c0c93480Slin wang - Sun Microsystems - Beijing China for (i = 0; i < ieee80211_rateset_11n.rs_nrates; i++) { 2688c0c93480Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_RATE, "MCS rate %d is %d\n", 2689c0c93480Slin wang - Sun Microsystems - Beijing China i, ieee80211_rateset_11n.rs_rates[i])); 2690c0c93480Slin wang - Sun Microsystems - Beijing China } 2691c0c93480Slin wang - Sun Microsystems - Beijing China 2692c0c93480Slin wang - Sun Microsystems - Beijing China } 2693c0c93480Slin wang - Sun Microsystems - Beijing China 2694c0c93480Slin wang - Sun Microsystems - Beijing China /* 2695c0c93480Slin wang - Sun Microsystems - Beijing China * Update WME parameters for a transmit queue. 2696c0c93480Slin wang - Sun Microsystems - Beijing China */ 2697c0c93480Slin wang - Sun Microsystems - Beijing China static int 2698c0c93480Slin wang - Sun Microsystems - Beijing China arn_tx_queue_update(struct arn_softc *sc, int ac) 2699c0c93480Slin wang - Sun Microsystems - Beijing China { 2700c0c93480Slin wang - Sun Microsystems - Beijing China #define ATH_EXPONENT_TO_VALUE(v) ((1<<v)-1) 2701c0c93480Slin wang - Sun Microsystems - Beijing China #define ATH_TXOP_TO_US(v) (v<<5) 2702c0c93480Slin wang - Sun Microsystems - Beijing China ieee80211com_t *ic = (ieee80211com_t *)sc; 2703c0c93480Slin wang - Sun Microsystems - Beijing China struct ath_txq *txq; 2704c0c93480Slin wang - Sun Microsystems - Beijing China struct wmeParams *wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[ac]; 2705c0c93480Slin wang - Sun Microsystems - Beijing China struct ath_hal *ah = sc->sc_ah; 2706c0c93480Slin wang - Sun Microsystems - Beijing China struct ath9k_tx_queue_info qi; 2707c0c93480Slin wang - Sun Microsystems - Beijing China 2708c0c93480Slin wang - Sun Microsystems - Beijing China txq = &sc->sc_txq[arn_get_hal_qnum(ac, sc)]; 2709c0c93480Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi); 2710c0c93480Slin wang - Sun Microsystems - Beijing China 2711c0c93480Slin wang - Sun Microsystems - Beijing China /* 2712c0c93480Slin wang - Sun Microsystems - Beijing China * TXQ_FLAG_TXOKINT_ENABLE = 0x0001 2713c0c93480Slin wang - Sun Microsystems - Beijing China * TXQ_FLAG_TXERRINT_ENABLE = 0x0001 2714c0c93480Slin wang - Sun Microsystems - Beijing China * TXQ_FLAG_TXDESCINT_ENABLE = 0x0002 2715c0c93480Slin wang - Sun Microsystems - Beijing China * TXQ_FLAG_TXEOLINT_ENABLE = 0x0004 2716c0c93480Slin wang - Sun Microsystems - Beijing China * TXQ_FLAG_TXURNINT_ENABLE = 0x0008 2717c0c93480Slin wang - Sun Microsystems - Beijing China * TXQ_FLAG_BACKOFF_DISABLE = 0x0010 2718c0c93480Slin wang - Sun Microsystems - Beijing China * TXQ_FLAG_COMPRESSION_ENABLE = 0x0020 2719c0c93480Slin wang - Sun Microsystems - Beijing China * TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE = 0x0040 2720c0c93480Slin wang - Sun Microsystems - Beijing China * TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE = 0x0080 2721c0c93480Slin wang - Sun Microsystems - Beijing China */ 2722c0c93480Slin wang - Sun Microsystems - Beijing China 2723c0c93480Slin wang - Sun Microsystems - Beijing China /* xxx should update these flags here? */ 2724c0c93480Slin wang - Sun Microsystems - Beijing China #if 0 2725c0c93480Slin wang - Sun Microsystems - Beijing China qi.tqi_qflags = TXQ_FLAG_TXOKINT_ENABLE | 2726c0c93480Slin wang - Sun Microsystems - Beijing China TXQ_FLAG_TXERRINT_ENABLE | 2727c0c93480Slin wang - Sun Microsystems - Beijing China TXQ_FLAG_TXDESCINT_ENABLE | 2728c0c93480Slin wang - Sun Microsystems - Beijing China TXQ_FLAG_TXURNINT_ENABLE; 2729c0c93480Slin wang - Sun Microsystems - Beijing China #endif 2730c0c93480Slin wang - Sun Microsystems - Beijing China 2731c0c93480Slin wang - Sun Microsystems - Beijing China qi.tqi_aifs = wmep->wmep_aifsn; 2732c0c93480Slin wang - Sun Microsystems - Beijing China qi.tqi_cwmin = ATH_EXPONENT_TO_VALUE(wmep->wmep_logcwmin); 2733c0c93480Slin wang - Sun Microsystems - Beijing China qi.tqi_cwmax = ATH_EXPONENT_TO_VALUE(wmep->wmep_logcwmax); 2734c0c93480Slin wang - Sun Microsystems - Beijing China qi.tqi_readyTime = 0; 2735c0c93480Slin wang - Sun Microsystems - Beijing China qi.tqi_burstTime = ATH_TXOP_TO_US(wmep->wmep_txopLimit); 2736c0c93480Slin wang - Sun Microsystems - Beijing China 2737c0c93480Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_INIT, 2738c0c93480Slin wang - Sun Microsystems - Beijing China "%s:" 2739c0c93480Slin wang - Sun Microsystems - Beijing China "Q%u" 2740c0c93480Slin wang - Sun Microsystems - Beijing China "qflags 0x%x" 2741c0c93480Slin wang - Sun Microsystems - Beijing China "aifs %u" 2742c0c93480Slin wang - Sun Microsystems - Beijing China "cwmin %u" 2743c0c93480Slin wang - Sun Microsystems - Beijing China "cwmax %u" 2744c0c93480Slin wang - Sun Microsystems - Beijing China "burstTime %u\n", 2745c0c93480Slin wang - Sun Microsystems - Beijing China __func__, 2746c0c93480Slin wang - Sun Microsystems - Beijing China txq->axq_qnum, 2747c0c93480Slin wang - Sun Microsystems - Beijing China qi.tqi_qflags, 2748c0c93480Slin wang - Sun Microsystems - Beijing China qi.tqi_aifs, 2749c0c93480Slin wang - Sun Microsystems - Beijing China qi.tqi_cwmin, 2750c0c93480Slin wang - Sun Microsystems - Beijing China qi.tqi_cwmax, 2751c0c93480Slin wang - Sun Microsystems - Beijing China qi.tqi_burstTime)); 2752c0c93480Slin wang - Sun Microsystems - Beijing China 2753c0c93480Slin wang - Sun Microsystems - Beijing China if (!ath9k_hw_set_txq_props(ah, txq->axq_qnum, &qi)) { 2754c0c93480Slin wang - Sun Microsystems - Beijing China arn_problem("unable to update hardware queue " 2755c0c93480Slin wang - Sun Microsystems - Beijing China "parameters for %s traffic!\n", 2756c0c93480Slin wang - Sun Microsystems - Beijing China ieee80211_wme_acnames[ac]); 2757c0c93480Slin wang - Sun Microsystems - Beijing China return (0); 2758c0c93480Slin wang - Sun Microsystems - Beijing China } else { 2759c0c93480Slin wang - Sun Microsystems - Beijing China /* push to H/W */ 2760c0c93480Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_resettxqueue(ah, txq->axq_qnum); 2761c0c93480Slin wang - Sun Microsystems - Beijing China return (1); 2762c0c93480Slin wang - Sun Microsystems - Beijing China } 2763c0c93480Slin wang - Sun Microsystems - Beijing China 2764c0c93480Slin wang - Sun Microsystems - Beijing China #undef ATH_TXOP_TO_US 2765c0c93480Slin wang - Sun Microsystems - Beijing China #undef ATH_EXPONENT_TO_VALUE 2766c0c93480Slin wang - Sun Microsystems - Beijing China } 2767c0c93480Slin wang - Sun Microsystems - Beijing China 2768c0c93480Slin wang - Sun Microsystems - Beijing China /* Update WME parameters */ 2769c0c93480Slin wang - Sun Microsystems - Beijing China static int 2770c0c93480Slin wang - Sun Microsystems - Beijing China arn_wme_update(ieee80211com_t *ic) 2771c0c93480Slin wang - Sun Microsystems - Beijing China { 2772c0c93480Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc = (struct arn_softc *)ic; 2773c0c93480Slin wang - Sun Microsystems - Beijing China 2774c0c93480Slin wang - Sun Microsystems - Beijing China /* updateing */ 2775c0c93480Slin wang - Sun Microsystems - Beijing China return (!arn_tx_queue_update(sc, WME_AC_BE) || 2776c0c93480Slin wang - Sun Microsystems - Beijing China !arn_tx_queue_update(sc, WME_AC_BK) || 2777c0c93480Slin wang - Sun Microsystems - Beijing China !arn_tx_queue_update(sc, WME_AC_VI) || 2778c0c93480Slin wang - Sun Microsystems - Beijing China !arn_tx_queue_update(sc, WME_AC_VO) ? EIO : 0); 2779c0c93480Slin wang - Sun Microsystems - Beijing China } 2780c0c93480Slin wang - Sun Microsystems - Beijing China 2781c0c93480Slin wang - Sun Microsystems - Beijing China /* 2782c0c93480Slin wang - Sun Microsystems - Beijing China * Update tx/rx chainmask. For legacy association, 2783c0c93480Slin wang - Sun Microsystems - Beijing China * hard code chainmask to 1x1, for 11n association, use 2784c0c93480Slin wang - Sun Microsystems - Beijing China * the chainmask configuration. 2785c0c93480Slin wang - Sun Microsystems - Beijing China */ 2786c0c93480Slin wang - Sun Microsystems - Beijing China void 2787c0c93480Slin wang - Sun Microsystems - Beijing China arn_update_chainmask(struct arn_softc *sc) 2788c0c93480Slin wang - Sun Microsystems - Beijing China { 2789c0c93480Slin wang - Sun Microsystems - Beijing China boolean_t is_ht = B_FALSE; 2790c0c93480Slin wang - Sun Microsystems - Beijing China sc->sc_flags |= SC_OP_CHAINMASK_UPDATE; 2791c0c93480Slin wang - Sun Microsystems - Beijing China 2792c0c93480Slin wang - Sun Microsystems - Beijing China is_ht = sc->sc_ht_conf.ht_supported; 2793c0c93480Slin wang - Sun Microsystems - Beijing China if (is_ht) { 2794c0c93480Slin wang - Sun Microsystems - Beijing China sc->sc_tx_chainmask = sc->sc_ah->ah_caps.tx_chainmask; 2795c0c93480Slin wang - Sun Microsystems - Beijing China sc->sc_rx_chainmask = sc->sc_ah->ah_caps.rx_chainmask; 2796c0c93480Slin wang - Sun Microsystems - Beijing China } else { 2797c0c93480Slin wang - Sun Microsystems - Beijing China sc->sc_tx_chainmask = 1; 2798c0c93480Slin wang - Sun Microsystems - Beijing China sc->sc_rx_chainmask = 1; 2799c0c93480Slin wang - Sun Microsystems - Beijing China } 2800c0c93480Slin wang - Sun Microsystems - Beijing China 2801c0c93480Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): " 2802c0c93480Slin wang - Sun Microsystems - Beijing China "tx_chainmask = %d, rx_chainmask = %d\n", 2803c0c93480Slin wang - Sun Microsystems - Beijing China sc->sc_tx_chainmask, sc->sc_rx_chainmask)); 2804c0c93480Slin wang - Sun Microsystems - Beijing China } 2805c0c93480Slin wang - Sun Microsystems - Beijing China 2806dd1de374Slin wang - Sun Microsystems - Beijing China static int 2807dd1de374Slin wang - Sun Microsystems - Beijing China arn_resume(dev_info_t *devinfo) 2808dd1de374Slin wang - Sun Microsystems - Beijing China { 2809dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc; 2810dd1de374Slin wang - Sun Microsystems - Beijing China int ret = DDI_SUCCESS; 2811dd1de374Slin wang - Sun Microsystems - Beijing China 2812dd1de374Slin wang - Sun Microsystems - Beijing China sc = ddi_get_soft_state(arn_soft_state_p, ddi_get_instance(devinfo)); 2813dd1de374Slin wang - Sun Microsystems - Beijing China if (sc == NULL) { 2814dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_INIT, "ath: ath_resume(): " 2815dd1de374Slin wang - Sun Microsystems - Beijing China "failed to get soft state\n")); 2816dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 2817dd1de374Slin wang - Sun Microsystems - Beijing China } 2818dd1de374Slin wang - Sun Microsystems - Beijing China 2819dd1de374Slin wang - Sun Microsystems - Beijing China ARN_LOCK(sc); 2820dd1de374Slin wang - Sun Microsystems - Beijing China /* 2821dd1de374Slin wang - Sun Microsystems - Beijing China * Set up config space command register(s). Refuse 2822dd1de374Slin wang - Sun Microsystems - Beijing China * to resume on failure. 2823dd1de374Slin wang - Sun Microsystems - Beijing China */ 2824dd1de374Slin wang - Sun Microsystems - Beijing China if (arn_pci_setup(sc) != 0) { 2825dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_INIT, "ath: ath_resume(): " 2826dd1de374Slin wang - Sun Microsystems - Beijing China "ath_pci_setup() failed\n")); 2827dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 2828dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 2829dd1de374Slin wang - Sun Microsystems - Beijing China } 2830dd1de374Slin wang - Sun Microsystems - Beijing China 2831dd1de374Slin wang - Sun Microsystems - Beijing China if (!(sc->sc_flags & SC_OP_INVALID)) 2832dd1de374Slin wang - Sun Microsystems - Beijing China ret = arn_open(sc); 2833dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 2834dd1de374Slin wang - Sun Microsystems - Beijing China 2835dd1de374Slin wang - Sun Microsystems - Beijing China return (ret); 2836dd1de374Slin wang - Sun Microsystems - Beijing China } 2837dd1de374Slin wang - Sun Microsystems - Beijing China 2838dd1de374Slin wang - Sun Microsystems - Beijing China static int 2839dd1de374Slin wang - Sun Microsystems - Beijing China arn_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) 2840dd1de374Slin wang - Sun Microsystems - Beijing China { 2841dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc; 2842dd1de374Slin wang - Sun Microsystems - Beijing China int instance; 2843dd1de374Slin wang - Sun Microsystems - Beijing China int status; 2844dd1de374Slin wang - Sun Microsystems - Beijing China int32_t err; 2845dd1de374Slin wang - Sun Microsystems - Beijing China uint16_t vendor_id; 2846dd1de374Slin wang - Sun Microsystems - Beijing China uint16_t device_id; 2847dd1de374Slin wang - Sun Microsystems - Beijing China uint32_t i; 2848dd1de374Slin wang - Sun Microsystems - Beijing China uint32_t val; 2849dd1de374Slin wang - Sun Microsystems - Beijing China char strbuf[32]; 2850dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211com_t *ic; 2851dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_hal *ah; 2852dd1de374Slin wang - Sun Microsystems - Beijing China wifi_data_t wd = { 0 }; 2853dd1de374Slin wang - Sun Microsystems - Beijing China mac_register_t *macp; 2854dd1de374Slin wang - Sun Microsystems - Beijing China 2855dd1de374Slin wang - Sun Microsystems - Beijing China switch (cmd) { 2856dd1de374Slin wang - Sun Microsystems - Beijing China case DDI_ATTACH: 2857dd1de374Slin wang - Sun Microsystems - Beijing China break; 2858dd1de374Slin wang - Sun Microsystems - Beijing China case DDI_RESUME: 2859dd1de374Slin wang - Sun Microsystems - Beijing China return (arn_resume(devinfo)); 2860dd1de374Slin wang - Sun Microsystems - Beijing China default: 2861dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 2862dd1de374Slin wang - Sun Microsystems - Beijing China } 2863dd1de374Slin wang - Sun Microsystems - Beijing China 2864dd1de374Slin wang - Sun Microsystems - Beijing China instance = ddi_get_instance(devinfo); 2865dd1de374Slin wang - Sun Microsystems - Beijing China if (ddi_soft_state_zalloc(arn_soft_state_p, instance) != DDI_SUCCESS) { 2866dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: " 2867dd1de374Slin wang - Sun Microsystems - Beijing China "%s: Unable to alloc softstate\n", __func__)); 2868dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 2869dd1de374Slin wang - Sun Microsystems - Beijing China } 2870dd1de374Slin wang - Sun Microsystems - Beijing China 2871dd1de374Slin wang - Sun Microsystems - Beijing China sc = ddi_get_soft_state(arn_soft_state_p, ddi_get_instance(devinfo)); 2872dd1de374Slin wang - Sun Microsystems - Beijing China ic = (ieee80211com_t *)sc; 2873dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_dev = devinfo; 2874dd1de374Slin wang - Sun Microsystems - Beijing China 2875dd1de374Slin wang - Sun Microsystems - Beijing China mutex_init(&sc->sc_genlock, NULL, MUTEX_DRIVER, NULL); 2876dd1de374Slin wang - Sun Microsystems - Beijing China mutex_init(&sc->sc_serial_rw, NULL, MUTEX_DRIVER, NULL); 2877dd1de374Slin wang - Sun Microsystems - Beijing China mutex_init(&sc->sc_txbuflock, NULL, MUTEX_DRIVER, NULL); 2878dd1de374Slin wang - Sun Microsystems - Beijing China mutex_init(&sc->sc_rxbuflock, NULL, MUTEX_DRIVER, NULL); 2879dd1de374Slin wang - Sun Microsystems - Beijing China mutex_init(&sc->sc_resched_lock, NULL, MUTEX_DRIVER, NULL); 2880dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_IBSS 2881dd1de374Slin wang - Sun Microsystems - Beijing China mutex_init(&sc->sc_bcbuflock, NULL, MUTEX_DRIVER, NULL); 2882dd1de374Slin wang - Sun Microsystems - Beijing China #endif 2883dd1de374Slin wang - Sun Microsystems - Beijing China 2884dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_flags |= SC_OP_INVALID; 2885dd1de374Slin wang - Sun Microsystems - Beijing China 2886dd1de374Slin wang - Sun Microsystems - Beijing China err = pci_config_setup(devinfo, &sc->sc_cfg_handle); 2887dd1de374Slin wang - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 2888dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): " 2889dd1de374Slin wang - Sun Microsystems - Beijing China "pci_config_setup() failed")); 2890dd1de374Slin wang - Sun Microsystems - Beijing China goto attach_fail0; 2891dd1de374Slin wang - Sun Microsystems - Beijing China } 2892dd1de374Slin wang - Sun Microsystems - Beijing China 2893dd1de374Slin wang - Sun Microsystems - Beijing China if (arn_pci_setup(sc) != 0) 2894dd1de374Slin wang - Sun Microsystems - Beijing China goto attach_fail1; 2895dd1de374Slin wang - Sun Microsystems - Beijing China 2896dd1de374Slin wang - Sun Microsystems - Beijing China /* Cache line size set up */ 2897dd1de374Slin wang - Sun Microsystems - Beijing China arn_pci_config_cachesize(sc); 2898dd1de374Slin wang - Sun Microsystems - Beijing China 2899dd1de374Slin wang - Sun Microsystems - Beijing China vendor_id = pci_config_get16(sc->sc_cfg_handle, PCI_CONF_VENID); 2900dd1de374Slin wang - Sun Microsystems - Beijing China device_id = pci_config_get16(sc->sc_cfg_handle, PCI_CONF_DEVID); 2901dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): vendor 0x%x, " 2902dd1de374Slin wang - Sun Microsystems - Beijing China "device id 0x%x, cache size %d\n", 2903dd1de374Slin wang - Sun Microsystems - Beijing China vendor_id, device_id, 2904dd1de374Slin wang - Sun Microsystems - Beijing China pci_config_get8(sc->sc_cfg_handle, PCI_CONF_CACHE_LINESZ))); 2905dd1de374Slin wang - Sun Microsystems - Beijing China 2906dd1de374Slin wang - Sun Microsystems - Beijing China pci_config_put8(sc->sc_cfg_handle, PCI_CONF_LATENCY_TIMER, 0xa8); 2907dd1de374Slin wang - Sun Microsystems - Beijing China val = pci_config_get32(sc->sc_cfg_handle, 0x40); 2908dd1de374Slin wang - Sun Microsystems - Beijing China if ((val & 0x0000ff00) != 0) 2909dd1de374Slin wang - Sun Microsystems - Beijing China pci_config_put32(sc->sc_cfg_handle, 0x40, val & 0xffff00ff); 2910dd1de374Slin wang - Sun Microsystems - Beijing China 2911dd1de374Slin wang - Sun Microsystems - Beijing China err = ddi_regs_map_setup(devinfo, 1, 2912dd1de374Slin wang - Sun Microsystems - Beijing China &sc->mem, 0, 0, &arn_reg_accattr, &sc->sc_io_handle); 2913dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): " 2914dd1de374Slin wang - Sun Microsystems - Beijing China "regs map1 = %x err=%d\n", sc->mem, err)); 2915dd1de374Slin wang - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 2916dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): " 2917dd1de374Slin wang - Sun Microsystems - Beijing China "ddi_regs_map_setup() failed")); 2918dd1de374Slin wang - Sun Microsystems - Beijing China goto attach_fail1; 2919dd1de374Slin wang - Sun Microsystems - Beijing China } 2920dd1de374Slin wang - Sun Microsystems - Beijing China 2921dd1de374Slin wang - Sun Microsystems - Beijing China ah = ath9k_hw_attach(device_id, sc, sc->mem, &status); 2922dd1de374Slin wang - Sun Microsystems - Beijing China if (ah == NULL) { 2923dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): " 2924dd1de374Slin wang - Sun Microsystems - Beijing China "unable to attach hw: H/W status %u\n", 2925dd1de374Slin wang - Sun Microsystems - Beijing China status)); 2926dd1de374Slin wang - Sun Microsystems - Beijing China goto attach_fail2; 2927dd1de374Slin wang - Sun Microsystems - Beijing China } 2928dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_ah = ah; 2929dd1de374Slin wang - Sun Microsystems - Beijing China 2930dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_getmac(ah, ic->ic_macaddr); 2931dd1de374Slin wang - Sun Microsystems - Beijing China 2932dd1de374Slin wang - Sun Microsystems - Beijing China /* Get the hardware key cache size. */ 2933dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_keymax = ah->ah_caps.keycache_size; 2934dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_keymax > ATH_KEYMAX) { 2935dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): " 2936dd1de374Slin wang - Sun Microsystems - Beijing China "Warning, using only %u entries in %u key cache\n", 2937dd1de374Slin wang - Sun Microsystems - Beijing China ATH_KEYMAX, sc->sc_keymax)); 2938dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_keymax = ATH_KEYMAX; 2939dd1de374Slin wang - Sun Microsystems - Beijing China } 2940dd1de374Slin wang - Sun Microsystems - Beijing China 2941dd1de374Slin wang - Sun Microsystems - Beijing China /* 2942dd1de374Slin wang - Sun Microsystems - Beijing China * Reset the key cache since some parts do not 2943dd1de374Slin wang - Sun Microsystems - Beijing China * reset the contents on initial power up. 2944dd1de374Slin wang - Sun Microsystems - Beijing China */ 2945dd1de374Slin wang - Sun Microsystems - Beijing China for (i = 0; i < sc->sc_keymax; i++) 2946dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_keyreset(ah, (uint16_t)i); 2947dd1de374Slin wang - Sun Microsystems - Beijing China /* 2948dd1de374Slin wang - Sun Microsystems - Beijing China * Mark key cache slots associated with global keys 2949dd1de374Slin wang - Sun Microsystems - Beijing China * as in use. If we knew TKIP was not to be used we 2950dd1de374Slin wang - Sun Microsystems - Beijing China * could leave the +32, +64, and +32+64 slots free. 2951dd1de374Slin wang - Sun Microsystems - Beijing China * XXX only for splitmic. 2952dd1de374Slin wang - Sun Microsystems - Beijing China */ 2953dd1de374Slin wang - Sun Microsystems - Beijing China for (i = 0; i < IEEE80211_WEP_NKID; i++) { 2954dd1de374Slin wang - Sun Microsystems - Beijing China set_bit(i, sc->sc_keymap); 2955dd1de374Slin wang - Sun Microsystems - Beijing China set_bit(i + 32, sc->sc_keymap); 2956dd1de374Slin wang - Sun Microsystems - Beijing China set_bit(i + 64, sc->sc_keymap); 2957dd1de374Slin wang - Sun Microsystems - Beijing China set_bit(i + 32 + 64, sc->sc_keymap); 2958dd1de374Slin wang - Sun Microsystems - Beijing China } 2959dd1de374Slin wang - Sun Microsystems - Beijing China 2960dd1de374Slin wang - Sun Microsystems - Beijing China /* Collect the channel list using the default country code */ 2961dd1de374Slin wang - Sun Microsystems - Beijing China err = arn_setup_channels(sc); 2962dd1de374Slin wang - Sun Microsystems - Beijing China if (err == EINVAL) { 2963dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): " 2964dd1de374Slin wang - Sun Microsystems - Beijing China "ERR:arn_setup_channels\n")); 2965dd1de374Slin wang - Sun Microsystems - Beijing China goto attach_fail3; 2966dd1de374Slin wang - Sun Microsystems - Beijing China } 2967dd1de374Slin wang - Sun Microsystems - Beijing China 2968dd1de374Slin wang - Sun Microsystems - Beijing China /* default to STA mode */ 2969dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_ah->ah_opmode = ATH9K_M_STA; 2970dd1de374Slin wang - Sun Microsystems - Beijing China 2971dd1de374Slin wang - Sun Microsystems - Beijing China /* Setup rate tables */ 2972dd1de374Slin wang - Sun Microsystems - Beijing China arn_rate_attach(sc); 2973dd1de374Slin wang - Sun Microsystems - Beijing China arn_setup_rates(sc, IEEE80211_MODE_11A); 2974dd1de374Slin wang - Sun Microsystems - Beijing China arn_setup_rates(sc, IEEE80211_MODE_11B); 2975dd1de374Slin wang - Sun Microsystems - Beijing China arn_setup_rates(sc, IEEE80211_MODE_11G); 2976dd1de374Slin wang - Sun Microsystems - Beijing China 2977dd1de374Slin wang - Sun Microsystems - Beijing China /* Setup current mode here */ 2978dd1de374Slin wang - Sun Microsystems - Beijing China arn_setcurmode(sc, ATH9K_MODE_11G); 2979dd1de374Slin wang - Sun Microsystems - Beijing China 2980dd1de374Slin wang - Sun Microsystems - Beijing China /* 802.11g features */ 2981dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_have11g) 2982dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_caps |= IEEE80211_C_SHPREAMBLE | 2983dd1de374Slin wang - Sun Microsystems - Beijing China IEEE80211_C_SHSLOT; /* short slot time */ 2984dd1de374Slin wang - Sun Microsystems - Beijing China 2985c0c93480Slin wang - Sun Microsystems - Beijing China /* Temp workaround */ 2986dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_mrretry = 1; 2987c0c93480Slin wang - Sun Microsystems - Beijing China sc->sc_config.ath_aggr_prot = 0; 2988dd1de374Slin wang - Sun Microsystems - Beijing China 2989dd1de374Slin wang - Sun Microsystems - Beijing China /* Setup tx/rx descriptors */ 2990dd1de374Slin wang - Sun Microsystems - Beijing China err = arn_desc_alloc(devinfo, sc); 2991dd1de374Slin wang - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 2992dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): " 2993dd1de374Slin wang - Sun Microsystems - Beijing China "failed to allocate descriptors: %d\n", err)); 2994dd1de374Slin wang - Sun Microsystems - Beijing China goto attach_fail3; 2995dd1de374Slin wang - Sun Microsystems - Beijing China } 2996dd1de374Slin wang - Sun Microsystems - Beijing China 2997dd1de374Slin wang - Sun Microsystems - Beijing China if ((sc->sc_tq = ddi_taskq_create(devinfo, "ath_taskq", 1, 2998dd1de374Slin wang - Sun Microsystems - Beijing China TASKQ_DEFAULTPRI, 0)) == NULL) { 2999dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): " 3000dd1de374Slin wang - Sun Microsystems - Beijing China "ERR:ddi_taskq_create\n")); 3001dd1de374Slin wang - Sun Microsystems - Beijing China goto attach_fail4; 3002dd1de374Slin wang - Sun Microsystems - Beijing China } 3003dd1de374Slin wang - Sun Microsystems - Beijing China 3004dd1de374Slin wang - Sun Microsystems - Beijing China /* 3005dd1de374Slin wang - Sun Microsystems - Beijing China * Allocate hardware transmit queues: one queue for 3006dd1de374Slin wang - Sun Microsystems - Beijing China * beacon frames and one data queue for each QoS 3007dd1de374Slin wang - Sun Microsystems - Beijing China * priority. Note that the hal handles reseting 3008dd1de374Slin wang - Sun Microsystems - Beijing China * these queues at the needed time. 3009dd1de374Slin wang - Sun Microsystems - Beijing China */ 3010dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_IBSS 3011dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_beaconq = arn_beaconq_setup(ah); 3012dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_beaconq == (-1)) { 3013dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): " 3014dd1de374Slin wang - Sun Microsystems - Beijing China "unable to setup a beacon xmit queue\n")); 3015dd1de374Slin wang - Sun Microsystems - Beijing China goto attach_fail4; 3016dd1de374Slin wang - Sun Microsystems - Beijing China } 3017dd1de374Slin wang - Sun Microsystems - Beijing China #endif 3018dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_HOSTAP 3019dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_cabq = arn_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); 3020dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_cabq == NULL) { 3021dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): " 3022dd1de374Slin wang - Sun Microsystems - Beijing China "unable to setup CAB xmit queue\n")); 3023dd1de374Slin wang - Sun Microsystems - Beijing China goto attach_fail4; 3024dd1de374Slin wang - Sun Microsystems - Beijing China } 3025dd1de374Slin wang - Sun Microsystems - Beijing China 3026dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_config.cabqReadytime = ATH_CABQ_READY_TIME; 3027dd1de374Slin wang - Sun Microsystems - Beijing China ath_cabq_update(sc); 3028dd1de374Slin wang - Sun Microsystems - Beijing China #endif 3029dd1de374Slin wang - Sun Microsystems - Beijing China 3030dd1de374Slin wang - Sun Microsystems - Beijing China for (i = 0; i < ARRAY_SIZE(sc->sc_haltype2q); i++) 3031dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_haltype2q[i] = -1; 3032dd1de374Slin wang - Sun Microsystems - Beijing China 3033dd1de374Slin wang - Sun Microsystems - Beijing China /* Setup data queues */ 3034dd1de374Slin wang - Sun Microsystems - Beijing China /* NB: ensure BK queue is the lowest priority h/w queue */ 3035dd1de374Slin wang - Sun Microsystems - Beijing China if (!arn_tx_setup(sc, ATH9K_WME_AC_BK)) { 3036dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): " 3037dd1de374Slin wang - Sun Microsystems - Beijing China "unable to setup xmit queue for BK traffic\n")); 3038dd1de374Slin wang - Sun Microsystems - Beijing China goto attach_fail4; 3039dd1de374Slin wang - Sun Microsystems - Beijing China } 3040dd1de374Slin wang - Sun Microsystems - Beijing China if (!arn_tx_setup(sc, ATH9K_WME_AC_BE)) { 3041dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): " 3042dd1de374Slin wang - Sun Microsystems - Beijing China "unable to setup xmit queue for BE traffic\n")); 3043dd1de374Slin wang - Sun Microsystems - Beijing China goto attach_fail4; 3044dd1de374Slin wang - Sun Microsystems - Beijing China } 3045dd1de374Slin wang - Sun Microsystems - Beijing China if (!arn_tx_setup(sc, ATH9K_WME_AC_VI)) { 3046dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): " 3047dd1de374Slin wang - Sun Microsystems - Beijing China "unable to setup xmit queue for VI traffic\n")); 3048dd1de374Slin wang - Sun Microsystems - Beijing China goto attach_fail4; 3049dd1de374Slin wang - Sun Microsystems - Beijing China } 3050dd1de374Slin wang - Sun Microsystems - Beijing China if (!arn_tx_setup(sc, ATH9K_WME_AC_VO)) { 3051dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): " 3052dd1de374Slin wang - Sun Microsystems - Beijing China "unable to setup xmit queue for VO traffic\n")); 3053dd1de374Slin wang - Sun Microsystems - Beijing China goto attach_fail4; 3054dd1de374Slin wang - Sun Microsystems - Beijing China } 3055dd1de374Slin wang - Sun Microsystems - Beijing China 3056dd1de374Slin wang - Sun Microsystems - Beijing China /* 3057dd1de374Slin wang - Sun Microsystems - Beijing China * Initializes the noise floor to a reasonable default value. 3058dd1de374Slin wang - Sun Microsystems - Beijing China * Later on this will be updated during ANI processing. 3059dd1de374Slin wang - Sun Microsystems - Beijing China */ 3060dd1de374Slin wang - Sun Microsystems - Beijing China 3061dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_ani.sc_noise_floor = ATH_DEFAULT_NOISE_FLOOR; 3062dd1de374Slin wang - Sun Microsystems - Beijing China 3063dd1de374Slin wang - Sun Microsystems - Beijing China 3064dd1de374Slin wang - Sun Microsystems - Beijing China if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, 3065dd1de374Slin wang - Sun Microsystems - Beijing China ATH9K_CIPHER_TKIP, NULL)) { 3066dd1de374Slin wang - Sun Microsystems - Beijing China /* 3067dd1de374Slin wang - Sun Microsystems - Beijing China * Whether we should enable h/w TKIP MIC. 3068dd1de374Slin wang - Sun Microsystems - Beijing China * XXX: if we don't support WME TKIP MIC, then we wouldn't 3069dd1de374Slin wang - Sun Microsystems - Beijing China * report WMM capable, so it's always safe to turn on 3070dd1de374Slin wang - Sun Microsystems - Beijing China * TKIP MIC in this case. 3071dd1de374Slin wang - Sun Microsystems - Beijing China */ 3072dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC, 3073dd1de374Slin wang - Sun Microsystems - Beijing China 0, 1, NULL); 3074dd1de374Slin wang - Sun Microsystems - Beijing China } 3075dd1de374Slin wang - Sun Microsystems - Beijing China 3076dd1de374Slin wang - Sun Microsystems - Beijing China /* Get cipher releated capability information */ 3077dd1de374Slin wang - Sun Microsystems - Beijing China arn_get_hw_encap(sc); 3078dd1de374Slin wang - Sun Microsystems - Beijing China 3079dd1de374Slin wang - Sun Microsystems - Beijing China /* 3080dd1de374Slin wang - Sun Microsystems - Beijing China * Check whether the separate key cache entries 3081dd1de374Slin wang - Sun Microsystems - Beijing China * are required to handle both tx+rx MIC keys. 3082dd1de374Slin wang - Sun Microsystems - Beijing China * With split mic keys the number of stations is limited 3083dd1de374Slin wang - Sun Microsystems - Beijing China * to 27 otherwise 59. 3084dd1de374Slin wang - Sun Microsystems - Beijing China */ 3085dd1de374Slin wang - Sun Microsystems - Beijing China if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, 3086dd1de374Slin wang - Sun Microsystems - Beijing China ATH9K_CIPHER_TKIP, NULL) && 3087dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, 3088dd1de374Slin wang - Sun Microsystems - Beijing China ATH9K_CIPHER_MIC, NULL) && 3089dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_getcapability(ah, ATH9K_CAP_TKIP_SPLIT, 3090dd1de374Slin wang - Sun Microsystems - Beijing China 0, NULL)) 3091dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_splitmic = 1; 3092dd1de374Slin wang - Sun Microsystems - Beijing China 3093dd1de374Slin wang - Sun Microsystems - Beijing China /* turn on mcast key search if possible */ 3094dd1de374Slin wang - Sun Microsystems - Beijing China if (!ath9k_hw_getcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL)) 3095dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_setcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 1, 3096dd1de374Slin wang - Sun Microsystems - Beijing China 1, NULL); 3097dd1de374Slin wang - Sun Microsystems - Beijing China 3098dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_config.txpowlimit = ATH_TXPOWER_MAX; 3099dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_config.txpowlimit_override = 0; 3100dd1de374Slin wang - Sun Microsystems - Beijing China 3101dd1de374Slin wang - Sun Microsystems - Beijing China /* 11n Capabilities */ 3102dd1de374Slin wang - Sun Microsystems - Beijing China if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) { 3103dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_flags |= SC_OP_TXAGGR; 3104dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_flags |= SC_OP_RXAGGR; 3105c0c93480Slin wang - Sun Microsystems - Beijing China arn_setup_ht_cap(sc); 3106c0c93480Slin wang - Sun Microsystems - Beijing China arn_overwrite_11n_rateset(sc); 3107dd1de374Slin wang - Sun Microsystems - Beijing China } 3108dd1de374Slin wang - Sun Microsystems - Beijing China 3109dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_tx_chainmask = 1; 3110dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_rx_chainmask = 1; 3111dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): " 3112dd1de374Slin wang - Sun Microsystems - Beijing China "tx_chainmask = %d, rx_chainmask = %d\n", 3113dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_tx_chainmask, sc->sc_rx_chainmask)); 3114dd1de374Slin wang - Sun Microsystems - Beijing China 3115c0c93480Slin wang - Sun Microsystems - Beijing China /* arn_update_chainmask(sc); */ 3116c0c93480Slin wang - Sun Microsystems - Beijing China 3117dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, B_TRUE, NULL); 3118dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_defant = ath9k_hw_getdefantenna(ah); 3119dd1de374Slin wang - Sun Microsystems - Beijing China 3120dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_getmac(ah, sc->sc_myaddr); 3121dd1de374Slin wang - Sun Microsystems - Beijing China if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) { 3122dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_getbssidmask(ah, sc->sc_bssidmask); 3123dd1de374Slin wang - Sun Microsystems - Beijing China ATH_SET_VAP_BSSID_MASK(sc->sc_bssidmask); 3124dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_setbssidmask(ah, sc->sc_bssidmask); 3125dd1de374Slin wang - Sun Microsystems - Beijing China } 3126dd1de374Slin wang - Sun Microsystems - Beijing China 3127dd1de374Slin wang - Sun Microsystems - Beijing China /* set default value to short slot time */ 3128dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_slottime = ATH9K_SLOT_TIME_9; 3129dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_setslottime(ah, ATH9K_SLOT_TIME_9); 3130dd1de374Slin wang - Sun Microsystems - Beijing China 3131dd1de374Slin wang - Sun Microsystems - Beijing China /* initialize beacon slots */ 3132dd1de374Slin wang - Sun Microsystems - Beijing China for (i = 0; i < ARRAY_SIZE(sc->sc_bslot); i++) 3133dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_bslot[i] = ATH_IF_ID_ANY; 3134dd1de374Slin wang - Sun Microsystems - Beijing China 3135c0c93480Slin wang - Sun Microsystems - Beijing China /* Save MISC configurations */ 3136dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_config.swBeaconProcess = 1; 3137dd1de374Slin wang - Sun Microsystems - Beijing China 3138c0c93480Slin wang - Sun Microsystems - Beijing China /* Support QoS/WME */ 3139c0c93480Slin wang - Sun Microsystems - Beijing China ic->ic_caps |= IEEE80211_C_WME; 3140c0c93480Slin wang - Sun Microsystems - Beijing China ic->ic_wme.wme_update = arn_wme_update; 3141dd1de374Slin wang - Sun Microsystems - Beijing China 3142c0c93480Slin wang - Sun Microsystems - Beijing China /* Support 802.11n/HT */ 3143c0c93480Slin wang - Sun Microsystems - Beijing China if (sc->sc_ht_conf.ht_supported) { 3144c0c93480Slin wang - Sun Microsystems - Beijing China ic->ic_htcaps = 3145c0c93480Slin wang - Sun Microsystems - Beijing China IEEE80211_HTCAP_CHWIDTH40 | 3146c0c93480Slin wang - Sun Microsystems - Beijing China IEEE80211_HTCAP_SHORTGI40 | 3147c0c93480Slin wang - Sun Microsystems - Beijing China IEEE80211_HTCAP_DSSSCCK40 | 3148c0c93480Slin wang - Sun Microsystems - Beijing China IEEE80211_HTCAP_MAXAMSDU_7935 | 3149c0c93480Slin wang - Sun Microsystems - Beijing China IEEE80211_HTC_HT | 3150c0c93480Slin wang - Sun Microsystems - Beijing China IEEE80211_HTC_AMSDU | 3151c0c93480Slin wang - Sun Microsystems - Beijing China IEEE80211_HTCAP_RXSTBC_2STREAM; 3152c0c93480Slin wang - Sun Microsystems - Beijing China 3153c0c93480Slin wang - Sun Microsystems - Beijing China #ifdef ARN_TX_AGGREGATION 3154c0c93480Slin wang - Sun Microsystems - Beijing China ic->ic_htcaps |= IEEE80211_HTC_AMPDU; 3155c0c93480Slin wang - Sun Microsystems - Beijing China #endif 3156c0c93480Slin wang - Sun Microsystems - Beijing China } 3157c0c93480Slin wang - Sun Microsystems - Beijing China 3158c0c93480Slin wang - Sun Microsystems - Beijing China /* Header padding requested by driver */ 3159c0c93480Slin wang - Sun Microsystems - Beijing China ic->ic_flags |= IEEE80211_F_DATAPAD; 3160c0c93480Slin wang - Sun Microsystems - Beijing China /* Support WPA/WPA2 */ 3161c0c93480Slin wang - Sun Microsystems - Beijing China ic->ic_caps |= IEEE80211_C_WPA; 3162c0c93480Slin wang - Sun Microsystems - Beijing China #if 0 3163c0c93480Slin wang - Sun Microsystems - Beijing China ic->ic_caps |= IEEE80211_C_TXFRAG; /* handle tx frags */ 3164c0c93480Slin wang - Sun Microsystems - Beijing China ic->ic_caps |= IEEE80211_C_BGSCAN; /* capable of bg scanning */ 3165c0c93480Slin wang - Sun Microsystems - Beijing China #endif 3166c0c93480Slin wang - Sun Microsystems - Beijing China ic->ic_phytype = IEEE80211_T_HT; 3167dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_opmode = IEEE80211_M_STA; 3168dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_state = IEEE80211_S_INIT; 3169dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_maxrssi = ARN_MAX_RSSI; 3170dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_set_shortslot = arn_set_shortslot; 3171dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_xmit = arn_tx; 3172dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211_attach(ic); 3173dd1de374Slin wang - Sun Microsystems - Beijing China 3174dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): " 3175dd1de374Slin wang - Sun Microsystems - Beijing China "ic->ic_curchan->ich_freq: %d\n", ic->ic_curchan->ich_freq)); 3176dd1de374Slin wang - Sun Microsystems - Beijing China 3177dd1de374Slin wang - Sun Microsystems - Beijing China /* different instance has different WPA door */ 3178dd1de374Slin wang - Sun Microsystems - Beijing China (void) snprintf(ic->ic_wpadoor, MAX_IEEE80211STR, "%s_%s%d", WPA_DOOR, 3179dd1de374Slin wang - Sun Microsystems - Beijing China ddi_driver_name(devinfo), 3180dd1de374Slin wang - Sun Microsystems - Beijing China ddi_get_instance(devinfo)); 3181dd1de374Slin wang - Sun Microsystems - Beijing China 3182c0c93480Slin wang - Sun Microsystems - Beijing China if (sc->sc_ht_conf.ht_supported) { 3183c0c93480Slin wang - Sun Microsystems - Beijing China sc->sc_recv_action = ic->ic_recv_action; 3184c0c93480Slin wang - Sun Microsystems - Beijing China ic->ic_recv_action = arn_ampdu_recv_action; 3185c0c93480Slin wang - Sun Microsystems - Beijing China // sc->sc_send_action = ic->ic_send_action; 3186c0c93480Slin wang - Sun Microsystems - Beijing China // ic->ic_send_action = arn_ampdu_send_action; 3187c0c93480Slin wang - Sun Microsystems - Beijing China 3188c0c93480Slin wang - Sun Microsystems - Beijing China ic->ic_ampdu_rxmax = sc->sc_ht_conf.ampdu_factor; 3189c0c93480Slin wang - Sun Microsystems - Beijing China ic->ic_ampdu_density = sc->sc_ht_conf.ampdu_density; 3190c0c93480Slin wang - Sun Microsystems - Beijing China ic->ic_ampdu_limit = ic->ic_ampdu_rxmax; 3191c0c93480Slin wang - Sun Microsystems - Beijing China } 3192c0c93480Slin wang - Sun Microsystems - Beijing China 3193dd1de374Slin wang - Sun Microsystems - Beijing China /* Override 80211 default routines */ 3194dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_newstate = ic->ic_newstate; 3195dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_newstate = arn_newstate; 3196dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_IBSS 3197dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_recv_mgmt = ic->ic_recv_mgmt; 3198dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_recv_mgmt = arn_recv_mgmt; 3199dd1de374Slin wang - Sun Microsystems - Beijing China #endif 3200dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_watchdog = arn_watchdog; 3201dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_node_alloc = arn_node_alloc; 3202dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_node_free = arn_node_free; 3203dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_crypto.cs_key_alloc = arn_key_alloc; 3204dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_crypto.cs_key_delete = arn_key_delete; 3205dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_crypto.cs_key_set = arn_key_set; 3206dd1de374Slin wang - Sun Microsystems - Beijing China 3207dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211_media_init(ic); 3208dd1de374Slin wang - Sun Microsystems - Beijing China 3209dd1de374Slin wang - Sun Microsystems - Beijing China /* 3210dd1de374Slin wang - Sun Microsystems - Beijing China * initialize default tx key 3211dd1de374Slin wang - Sun Microsystems - Beijing China */ 3212dd1de374Slin wang - Sun Microsystems - Beijing China ic->ic_def_txkey = 0; 3213dd1de374Slin wang - Sun Microsystems - Beijing China 3214dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_rx_pend = 0; 3215dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_set_interrupts(sc->sc_ah, 0); 3216dd1de374Slin wang - Sun Microsystems - Beijing China err = ddi_add_softintr(devinfo, DDI_SOFTINT_LOW, 3217dd1de374Slin wang - Sun Microsystems - Beijing China &sc->sc_softint_id, NULL, 0, arn_softint_handler, (caddr_t)sc); 3218dd1de374Slin wang - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 3219dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): " 3220dd1de374Slin wang - Sun Microsystems - Beijing China "ddi_add_softintr() failed....\n")); 3221dd1de374Slin wang - Sun Microsystems - Beijing China goto attach_fail5; 3222dd1de374Slin wang - Sun Microsystems - Beijing China } 3223dd1de374Slin wang - Sun Microsystems - Beijing China 3224dd1de374Slin wang - Sun Microsystems - Beijing China if (ddi_get_iblock_cookie(devinfo, 0, &sc->sc_iblock) 3225dd1de374Slin wang - Sun Microsystems - Beijing China != DDI_SUCCESS) { 3226dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): " 3227dd1de374Slin wang - Sun Microsystems - Beijing China "Can not get iblock cookie for INT\n")); 3228dd1de374Slin wang - Sun Microsystems - Beijing China goto attach_fail6; 3229dd1de374Slin wang - Sun Microsystems - Beijing China } 3230dd1de374Slin wang - Sun Microsystems - Beijing China 3231dd1de374Slin wang - Sun Microsystems - Beijing China if (ddi_add_intr(devinfo, 0, NULL, NULL, arn_isr, 3232dd1de374Slin wang - Sun Microsystems - Beijing China (caddr_t)sc) != DDI_SUCCESS) { 3233dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): " 3234dd1de374Slin wang - Sun Microsystems - Beijing China "Can not set intr for ARN driver\n")); 3235dd1de374Slin wang - Sun Microsystems - Beijing China goto attach_fail6; 3236dd1de374Slin wang - Sun Microsystems - Beijing China } 3237dd1de374Slin wang - Sun Microsystems - Beijing China 3238dd1de374Slin wang - Sun Microsystems - Beijing China /* 3239dd1de374Slin wang - Sun Microsystems - Beijing China * Provide initial settings for the WiFi plugin; whenever this 3240dd1de374Slin wang - Sun Microsystems - Beijing China * information changes, we need to call mac_plugindata_update() 3241dd1de374Slin wang - Sun Microsystems - Beijing China */ 3242dd1de374Slin wang - Sun Microsystems - Beijing China wd.wd_opmode = ic->ic_opmode; 3243dd1de374Slin wang - Sun Microsystems - Beijing China wd.wd_secalloc = WIFI_SEC_NONE; 3244dd1de374Slin wang - Sun Microsystems - Beijing China IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid); 3245dd1de374Slin wang - Sun Microsystems - Beijing China 3246dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): " 3247dd1de374Slin wang - Sun Microsystems - Beijing China "IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid)" 3248dd1de374Slin wang - Sun Microsystems - Beijing China "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", 3249dd1de374Slin wang - Sun Microsystems - Beijing China wd.wd_bssid[0], wd.wd_bssid[1], wd.wd_bssid[2], 3250dd1de374Slin wang - Sun Microsystems - Beijing China wd.wd_bssid[3], wd.wd_bssid[4], wd.wd_bssid[5])); 3251dd1de374Slin wang - Sun Microsystems - Beijing China 3252dd1de374Slin wang - Sun Microsystems - Beijing China if ((macp = mac_alloc(MAC_VERSION)) == NULL) { 3253dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): " 3254dd1de374Slin wang - Sun Microsystems - Beijing China "MAC version mismatch\n")); 3255dd1de374Slin wang - Sun Microsystems - Beijing China goto attach_fail7; 3256dd1de374Slin wang - Sun Microsystems - Beijing China } 3257dd1de374Slin wang - Sun Microsystems - Beijing China 3258dd1de374Slin wang - Sun Microsystems - Beijing China macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI; 3259dd1de374Slin wang - Sun Microsystems - Beijing China macp->m_driver = sc; 3260dd1de374Slin wang - Sun Microsystems - Beijing China macp->m_dip = devinfo; 3261dd1de374Slin wang - Sun Microsystems - Beijing China macp->m_src_addr = ic->ic_macaddr; 3262dd1de374Slin wang - Sun Microsystems - Beijing China macp->m_callbacks = &arn_m_callbacks; 3263dd1de374Slin wang - Sun Microsystems - Beijing China macp->m_min_sdu = 0; 3264dd1de374Slin wang - Sun Microsystems - Beijing China macp->m_max_sdu = IEEE80211_MTU; 3265dd1de374Slin wang - Sun Microsystems - Beijing China macp->m_pdata = &wd; 3266dd1de374Slin wang - Sun Microsystems - Beijing China macp->m_pdata_size = sizeof (wd); 3267dd1de374Slin wang - Sun Microsystems - Beijing China 3268dd1de374Slin wang - Sun Microsystems - Beijing China err = mac_register(macp, &ic->ic_mach); 3269dd1de374Slin wang - Sun Microsystems - Beijing China mac_free(macp); 3270dd1de374Slin wang - Sun Microsystems - Beijing China if (err != 0) { 3271dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): " 3272dd1de374Slin wang - Sun Microsystems - Beijing China "mac_register err %x\n", err)); 3273dd1de374Slin wang - Sun Microsystems - Beijing China goto attach_fail7; 3274dd1de374Slin wang - Sun Microsystems - Beijing China } 3275dd1de374Slin wang - Sun Microsystems - Beijing China 3276dd1de374Slin wang - Sun Microsystems - Beijing China /* Create minor node of type DDI_NT_NET_WIFI */ 3277dd1de374Slin wang - Sun Microsystems - Beijing China (void) snprintf(strbuf, sizeof (strbuf), "%s%d", 3278dd1de374Slin wang - Sun Microsystems - Beijing China ARN_NODENAME, instance); 3279dd1de374Slin wang - Sun Microsystems - Beijing China err = ddi_create_minor_node(devinfo, strbuf, S_IFCHR, 3280dd1de374Slin wang - Sun Microsystems - Beijing China instance + 1, DDI_NT_NET_WIFI, 0); 3281dd1de374Slin wang - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) 3282dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "WARN: arn: arn_attach(): " 3283dd1de374Slin wang - Sun Microsystems - Beijing China "Create minor node failed - %d\n", err)); 3284dd1de374Slin wang - Sun Microsystems - Beijing China 3285c0c93480Slin wang - Sun Microsystems - Beijing China /* Notify link is down now */ 3286dd1de374Slin wang - Sun Microsystems - Beijing China mac_link_update(ic->ic_mach, LINK_STATE_DOWN); 3287dd1de374Slin wang - Sun Microsystems - Beijing China 3288dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_promisc = B_FALSE; 3289dd1de374Slin wang - Sun Microsystems - Beijing China bzero(sc->sc_mcast_refs, sizeof (sc->sc_mcast_refs)); 3290dd1de374Slin wang - Sun Microsystems - Beijing China bzero(sc->sc_mcast_hash, sizeof (sc->sc_mcast_hash)); 3291dd1de374Slin wang - Sun Microsystems - Beijing China 3292dd1de374Slin wang - Sun Microsystems - Beijing China ARN_DBG((ARN_DBG_ATTACH, "arn: arn_attach(): " 3293dd1de374Slin wang - Sun Microsystems - Beijing China "Atheros AR%s MAC/BB Rev:%x " 3294dd1de374Slin wang - Sun Microsystems - Beijing China "AR%s RF Rev:%x: mem=0x%lx\n", 3295dd1de374Slin wang - Sun Microsystems - Beijing China arn_mac_bb_name(ah->ah_macVersion), 3296dd1de374Slin wang - Sun Microsystems - Beijing China ah->ah_macRev, 3297dd1de374Slin wang - Sun Microsystems - Beijing China arn_rf_name((ah->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR)), 3298dd1de374Slin wang - Sun Microsystems - Beijing China ah->ah_phyRev, 3299dd1de374Slin wang - Sun Microsystems - Beijing China (unsigned long)sc->mem)); 3300dd1de374Slin wang - Sun Microsystems - Beijing China 3301dd1de374Slin wang - Sun Microsystems - Beijing China /* XXX: hardware will not be ready until arn_open() being called */ 3302dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_flags |= SC_OP_INVALID; 3303dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_isrunning = 0; 3304dd1de374Slin wang - Sun Microsystems - Beijing China 3305dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 3306dd1de374Slin wang - Sun Microsystems - Beijing China 3307dd1de374Slin wang - Sun Microsystems - Beijing China attach_fail7: 3308dd1de374Slin wang - Sun Microsystems - Beijing China ddi_remove_intr(devinfo, 0, sc->sc_iblock); 3309dd1de374Slin wang - Sun Microsystems - Beijing China attach_fail6: 3310dd1de374Slin wang - Sun Microsystems - Beijing China ddi_remove_softintr(sc->sc_softint_id); 3311dd1de374Slin wang - Sun Microsystems - Beijing China attach_fail5: 3312dd1de374Slin wang - Sun Microsystems - Beijing China (void) ieee80211_detach(ic); 3313dd1de374Slin wang - Sun Microsystems - Beijing China attach_fail4: 3314dd1de374Slin wang - Sun Microsystems - Beijing China arn_desc_free(sc); 3315dd1de374Slin wang - Sun Microsystems - Beijing China if (sc->sc_tq) 3316dd1de374Slin wang - Sun Microsystems - Beijing China ddi_taskq_destroy(sc->sc_tq); 3317dd1de374Slin wang - Sun Microsystems - Beijing China attach_fail3: 3318dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_detach(ah); 3319dd1de374Slin wang - Sun Microsystems - Beijing China attach_fail2: 3320dd1de374Slin wang - Sun Microsystems - Beijing China ddi_regs_map_free(&sc->sc_io_handle); 3321dd1de374Slin wang - Sun Microsystems - Beijing China attach_fail1: 3322dd1de374Slin wang - Sun Microsystems - Beijing China pci_config_teardown(&sc->sc_cfg_handle); 3323dd1de374Slin wang - Sun Microsystems - Beijing China attach_fail0: 3324dd1de374Slin wang - Sun Microsystems - Beijing China sc->sc_flags |= SC_OP_INVALID; 3325dd1de374Slin wang - Sun Microsystems - Beijing China /* cleanup tx queues */ 3326dd1de374Slin wang - Sun Microsystems - Beijing China mutex_destroy(&sc->sc_txbuflock); 3327dd1de374Slin wang - Sun Microsystems - Beijing China for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { 3328dd1de374Slin wang - Sun Microsystems - Beijing China if (ARN_TXQ_SETUP(sc, i)) { 3329dd1de374Slin wang - Sun Microsystems - Beijing China /* arn_tx_cleanupq(asc, &asc->sc_txq[i]); */ 3330dd1de374Slin wang - Sun Microsystems - Beijing China mutex_destroy(&((&sc->sc_txq[i])->axq_lock)); 3331dd1de374Slin wang - Sun Microsystems - Beijing China } 3332dd1de374Slin wang - Sun Microsystems - Beijing China } 3333dd1de374Slin wang - Sun Microsystems - Beijing China mutex_destroy(&sc->sc_rxbuflock); 3334dd1de374Slin wang - Sun Microsystems - Beijing China mutex_destroy(&sc->sc_serial_rw); 3335dd1de374Slin wang - Sun Microsystems - Beijing China mutex_destroy(&sc->sc_genlock); 3336dd1de374Slin wang - Sun Microsystems - Beijing China mutex_destroy(&sc->sc_resched_lock); 3337dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_IBSS 3338dd1de374Slin wang - Sun Microsystems - Beijing China mutex_destroy(&sc->sc_bcbuflock); 3339dd1de374Slin wang - Sun Microsystems - Beijing China #endif 3340dd1de374Slin wang - Sun Microsystems - Beijing China 3341dd1de374Slin wang - Sun Microsystems - Beijing China ddi_soft_state_free(arn_soft_state_p, instance); 3342dd1de374Slin wang - Sun Microsystems - Beijing China 3343dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 3344dd1de374Slin wang - Sun Microsystems - Beijing China 3345dd1de374Slin wang - Sun Microsystems - Beijing China } 3346dd1de374Slin wang - Sun Microsystems - Beijing China 3347dd1de374Slin wang - Sun Microsystems - Beijing China /* 3348dd1de374Slin wang - Sun Microsystems - Beijing China * Suspend transmit/receive for powerdown 3349dd1de374Slin wang - Sun Microsystems - Beijing China */ 3350dd1de374Slin wang - Sun Microsystems - Beijing China static int 3351dd1de374Slin wang - Sun Microsystems - Beijing China arn_suspend(struct arn_softc *sc) 3352dd1de374Slin wang - Sun Microsystems - Beijing China { 3353dd1de374Slin wang - Sun Microsystems - Beijing China ARN_LOCK(sc); 3354dd1de374Slin wang - Sun Microsystems - Beijing China arn_close(sc); 3355dd1de374Slin wang - Sun Microsystems - Beijing China ARN_UNLOCK(sc); 3356dd1de374Slin wang - Sun Microsystems - Beijing China 3357dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 3358dd1de374Slin wang - Sun Microsystems - Beijing China } 3359dd1de374Slin wang - Sun Microsystems - Beijing China 3360dd1de374Slin wang - Sun Microsystems - Beijing China static int32_t 3361dd1de374Slin wang - Sun Microsystems - Beijing China arn_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) 3362dd1de374Slin wang - Sun Microsystems - Beijing China { 3363dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc; 3364dd1de374Slin wang - Sun Microsystems - Beijing China int i; 3365dd1de374Slin wang - Sun Microsystems - Beijing China 3366dd1de374Slin wang - Sun Microsystems - Beijing China sc = ddi_get_soft_state(arn_soft_state_p, ddi_get_instance(devinfo)); 3367dd1de374Slin wang - Sun Microsystems - Beijing China ASSERT(sc != NULL); 3368dd1de374Slin wang - Sun Microsystems - Beijing China 3369dd1de374Slin wang - Sun Microsystems - Beijing China switch (cmd) { 3370dd1de374Slin wang - Sun Microsystems - Beijing China case DDI_DETACH: 3371dd1de374Slin wang - Sun Microsystems - Beijing China break; 3372dd1de374Slin wang - Sun Microsystems - Beijing China 3373dd1de374Slin wang - Sun Microsystems - Beijing China case DDI_SUSPEND: 3374dd1de374Slin wang - Sun Microsystems - Beijing China return (arn_suspend(sc)); 3375dd1de374Slin wang - Sun Microsystems - Beijing China 3376dd1de374Slin wang - Sun Microsystems - Beijing China default: 3377dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 3378dd1de374Slin wang - Sun Microsystems - Beijing China } 3379dd1de374Slin wang - Sun Microsystems - Beijing China 3380dd1de374Slin wang - Sun Microsystems - Beijing China if (mac_disable(sc->sc_isc.ic_mach) != 0) 3381dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 3382dd1de374Slin wang - Sun Microsystems - Beijing China 3383dd1de374Slin wang - Sun Microsystems - Beijing China arn_stop_scantimer(sc); 3384dd1de374Slin wang - Sun Microsystems - Beijing China arn_stop_caltimer(sc); 3385dd1de374Slin wang - Sun Microsystems - Beijing China 3386dd1de374Slin wang - Sun Microsystems - Beijing China /* disable interrupts */ 3387dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_set_interrupts(sc->sc_ah, 0); 3388dd1de374Slin wang - Sun Microsystems - Beijing China 3389dd1de374Slin wang - Sun Microsystems - Beijing China /* 3390dd1de374Slin wang - Sun Microsystems - Beijing China * Unregister from the MAC layer subsystem 3391dd1de374Slin wang - Sun Microsystems - Beijing China */ 3392dd1de374Slin wang - Sun Microsystems - Beijing China (void) mac_unregister(sc->sc_isc.ic_mach); 3393dd1de374Slin wang - Sun Microsystems - Beijing China 3394dd1de374Slin wang - Sun Microsystems - Beijing China /* free intterrupt resources */ 3395dd1de374Slin wang - Sun Microsystems - Beijing China ddi_remove_intr(devinfo, 0, sc->sc_iblock); 3396dd1de374Slin wang - Sun Microsystems - Beijing China ddi_remove_softintr(sc->sc_softint_id); 3397dd1de374Slin wang - Sun Microsystems - Beijing China 3398dd1de374Slin wang - Sun Microsystems - Beijing China /* 3399dd1de374Slin wang - Sun Microsystems - Beijing China * NB: the order of these is important: 3400dd1de374Slin wang - Sun Microsystems - Beijing China * o call the 802.11 layer before detaching the hal to 3401dd1de374Slin wang - Sun Microsystems - Beijing China * insure callbacks into the driver to delete global 3402dd1de374Slin wang - Sun Microsystems - Beijing China * key cache entries can be handled 3403dd1de374Slin wang - Sun Microsystems - Beijing China * o reclaim the tx queue data structures after calling 3404dd1de374Slin wang - Sun Microsystems - Beijing China * the 802.11 layer as we'll get called back to reclaim 3405dd1de374Slin wang - Sun Microsystems - Beijing China * node state and potentially want to use them 3406dd1de374Slin wang - Sun Microsystems - Beijing China * o to cleanup the tx queues the hal is called, so detach 3407dd1de374Slin wang - Sun Microsystems - Beijing China * it last 3408dd1de374Slin wang - Sun Microsystems - Beijing China */ 3409dd1de374Slin wang - Sun Microsystems - Beijing China ieee80211_detach(&sc->sc_isc); 3410dd1de374Slin wang - Sun Microsystems - Beijing China 3411dd1de374Slin wang - Sun Microsystems - Beijing China arn_desc_free(sc); 3412dd1de374Slin wang - Sun Microsystems - Beijing China 3413dd1de374Slin wang - Sun Microsystems - Beijing China ddi_taskq_destroy(sc->sc_tq); 3414dd1de374Slin wang - Sun Microsystems - Beijing China 3415dd1de374Slin wang - Sun Microsystems - Beijing China if (!(sc->sc_flags & SC_OP_INVALID)) 3416dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); 3417dd1de374Slin wang - Sun Microsystems - Beijing China 3418dd1de374Slin wang - Sun Microsystems - Beijing China /* cleanup tx queues */ 3419dd1de374Slin wang - Sun Microsystems - Beijing China mutex_destroy(&sc->sc_txbuflock); 3420dd1de374Slin wang - Sun Microsystems - Beijing China for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { 3421dd1de374Slin wang - Sun Microsystems - Beijing China if (ARN_TXQ_SETUP(sc, i)) { 3422dd1de374Slin wang - Sun Microsystems - Beijing China arn_tx_cleanupq(sc, &sc->sc_txq[i]); 3423dd1de374Slin wang - Sun Microsystems - Beijing China mutex_destroy(&((&sc->sc_txq[i])->axq_lock)); 3424dd1de374Slin wang - Sun Microsystems - Beijing China } 3425dd1de374Slin wang - Sun Microsystems - Beijing China } 3426dd1de374Slin wang - Sun Microsystems - Beijing China 3427dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_detach(sc->sc_ah); 3428dd1de374Slin wang - Sun Microsystems - Beijing China 3429dd1de374Slin wang - Sun Microsystems - Beijing China /* free io handle */ 3430dd1de374Slin wang - Sun Microsystems - Beijing China ddi_regs_map_free(&sc->sc_io_handle); 3431dd1de374Slin wang - Sun Microsystems - Beijing China pci_config_teardown(&sc->sc_cfg_handle); 3432dd1de374Slin wang - Sun Microsystems - Beijing China 3433dd1de374Slin wang - Sun Microsystems - Beijing China /* destroy locks */ 3434dd1de374Slin wang - Sun Microsystems - Beijing China mutex_destroy(&sc->sc_genlock); 3435dd1de374Slin wang - Sun Microsystems - Beijing China mutex_destroy(&sc->sc_serial_rw); 3436dd1de374Slin wang - Sun Microsystems - Beijing China mutex_destroy(&sc->sc_rxbuflock); 3437dd1de374Slin wang - Sun Microsystems - Beijing China mutex_destroy(&sc->sc_resched_lock); 3438dd1de374Slin wang - Sun Microsystems - Beijing China #ifdef ARN_IBSS 3439dd1de374Slin wang - Sun Microsystems - Beijing China mutex_destroy(&sc->sc_bcbuflock); 3440dd1de374Slin wang - Sun Microsystems - Beijing China #endif 3441dd1de374Slin wang - Sun Microsystems - Beijing China 3442dd1de374Slin wang - Sun Microsystems - Beijing China ddi_remove_minor_node(devinfo, NULL); 3443dd1de374Slin wang - Sun Microsystems - Beijing China ddi_soft_state_free(arn_soft_state_p, ddi_get_instance(devinfo)); 3444dd1de374Slin wang - Sun Microsystems - Beijing China 3445dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 3446dd1de374Slin wang - Sun Microsystems - Beijing China } 3447dd1de374Slin wang - Sun Microsystems - Beijing China 3448dd1de374Slin wang - Sun Microsystems - Beijing China /* 3449dd1de374Slin wang - Sun Microsystems - Beijing China * quiesce(9E) entry point. 3450dd1de374Slin wang - Sun Microsystems - Beijing China * 3451dd1de374Slin wang - Sun Microsystems - Beijing China * This function is called when the system is single-threaded at high 3452dd1de374Slin wang - Sun Microsystems - Beijing China * PIL with preemption disabled. Therefore, this function must not be 3453dd1de374Slin wang - Sun Microsystems - Beijing China * blocked. 3454dd1de374Slin wang - Sun Microsystems - Beijing China * 3455dd1de374Slin wang - Sun Microsystems - Beijing China * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure. 3456dd1de374Slin wang - Sun Microsystems - Beijing China * DDI_FAILURE indicates an error condition and should almost never happen. 3457dd1de374Slin wang - Sun Microsystems - Beijing China */ 3458dd1de374Slin wang - Sun Microsystems - Beijing China static int32_t 3459dd1de374Slin wang - Sun Microsystems - Beijing China arn_quiesce(dev_info_t *devinfo) 3460dd1de374Slin wang - Sun Microsystems - Beijing China { 3461dd1de374Slin wang - Sun Microsystems - Beijing China struct arn_softc *sc; 3462dd1de374Slin wang - Sun Microsystems - Beijing China int i; 3463dd1de374Slin wang - Sun Microsystems - Beijing China struct ath_hal *ah; 3464dd1de374Slin wang - Sun Microsystems - Beijing China 3465dd1de374Slin wang - Sun Microsystems - Beijing China sc = ddi_get_soft_state(arn_soft_state_p, ddi_get_instance(devinfo)); 3466dd1de374Slin wang - Sun Microsystems - Beijing China 3467dd1de374Slin wang - Sun Microsystems - Beijing China if (sc == NULL || (ah = sc->sc_ah) == NULL) 3468dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_FAILURE); 3469dd1de374Slin wang - Sun Microsystems - Beijing China 3470dd1de374Slin wang - Sun Microsystems - Beijing China /* 3471dd1de374Slin wang - Sun Microsystems - Beijing China * Disable interrupts 3472dd1de374Slin wang - Sun Microsystems - Beijing China */ 3473dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_set_interrupts(ah, 0); 3474dd1de374Slin wang - Sun Microsystems - Beijing China 3475dd1de374Slin wang - Sun Microsystems - Beijing China /* 3476dd1de374Slin wang - Sun Microsystems - Beijing China * Disable TX HW 3477dd1de374Slin wang - Sun Microsystems - Beijing China */ 3478dd1de374Slin wang - Sun Microsystems - Beijing China for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { 3479dd1de374Slin wang - Sun Microsystems - Beijing China if (ARN_TXQ_SETUP(sc, i)) 3480dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_stoptxdma(ah, sc->sc_txq[i].axq_qnum); 3481dd1de374Slin wang - Sun Microsystems - Beijing China } 3482dd1de374Slin wang - Sun Microsystems - Beijing China 3483dd1de374Slin wang - Sun Microsystems - Beijing China /* 3484dd1de374Slin wang - Sun Microsystems - Beijing China * Disable RX HW 3485dd1de374Slin wang - Sun Microsystems - Beijing China */ 3486dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_stoppcurecv(ah); 3487dd1de374Slin wang - Sun Microsystems - Beijing China ath9k_hw_setrxfilter(ah, 0); 3488dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_stopdmarecv(ah); 3489dd1de374Slin wang - Sun Microsystems - Beijing China drv_usecwait(3000); 3490dd1de374Slin wang - Sun Microsystems - Beijing China 3491dd1de374Slin wang - Sun Microsystems - Beijing China /* 3492dd1de374Slin wang - Sun Microsystems - Beijing China * Power down HW 3493dd1de374Slin wang - Sun Microsystems - Beijing China */ 3494dd1de374Slin wang - Sun Microsystems - Beijing China (void) ath9k_hw_phy_disable(ah); 3495dd1de374Slin wang - Sun Microsystems - Beijing China 3496dd1de374Slin wang - Sun Microsystems - Beijing China return (DDI_SUCCESS); 3497dd1de374Slin wang - Sun Microsystems - Beijing China } 3498dd1de374Slin wang - Sun Microsystems - Beijing China 3499dd1de374Slin wang - Sun Microsystems - Beijing China DDI_DEFINE_STREAM_OPS(arn_dev_ops, nulldev, nulldev, arn_attach, arn_detach, 3500dd1de374Slin wang - Sun Microsystems - Beijing China nodev, NULL, D_MP, NULL, arn_quiesce); 3501dd1de374Slin wang - Sun Microsystems - Beijing China 3502dd1de374Slin wang - Sun Microsystems - Beijing China static struct modldrv arn_modldrv = { 3503dd1de374Slin wang - Sun Microsystems - Beijing China &mod_driverops, /* Type of module. This one is a driver */ 3504c0c93480Slin wang - Sun Microsystems - Beijing China "arn-Atheros 9000 series driver:2.0", /* short description */ 3505dd1de374Slin wang - Sun Microsystems - Beijing China &arn_dev_ops /* driver specific ops */ 3506dd1de374Slin wang - Sun Microsystems - Beijing China }; 3507dd1de374Slin wang - Sun Microsystems - Beijing China 3508dd1de374Slin wang - Sun Microsystems - Beijing China static struct modlinkage modlinkage = { 3509dd1de374Slin wang - Sun Microsystems - Beijing China MODREV_1, (void *)&arn_modldrv, NULL 3510dd1de374Slin wang - Sun Microsystems - Beijing China }; 3511dd1de374Slin wang - Sun Microsystems - Beijing China 3512dd1de374Slin wang - Sun Microsystems - Beijing China int 3513dd1de374Slin wang - Sun Microsystems - Beijing China _info(struct modinfo *modinfop) 3514dd1de374Slin wang - Sun Microsystems - Beijing China { 3515dd1de374Slin wang - Sun Microsystems - Beijing China return (mod_info(&modlinkage, modinfop)); 3516dd1de374Slin wang - Sun Microsystems - Beijing China } 3517dd1de374Slin wang - Sun Microsystems - Beijing China 3518dd1de374Slin wang - Sun Microsystems - Beijing China int 3519dd1de374Slin wang - Sun Microsystems - Beijing China _init(void) 3520dd1de374Slin wang - Sun Microsystems - Beijing China { 3521dd1de374Slin wang - Sun Microsystems - Beijing China int status; 3522dd1de374Slin wang - Sun Microsystems - Beijing China 3523dd1de374Slin wang - Sun Microsystems - Beijing China status = ddi_soft_state_init 3524dd1de374Slin wang - Sun Microsystems - Beijing China (&arn_soft_state_p, sizeof (struct arn_softc), 1); 3525dd1de374Slin wang - Sun Microsystems - Beijing China if (status != 0) 3526dd1de374Slin wang - Sun Microsystems - Beijing China return (status); 3527dd1de374Slin wang - Sun Microsystems - Beijing China 3528dd1de374Slin wang - Sun Microsystems - Beijing China mutex_init(&arn_loglock, NULL, MUTEX_DRIVER, NULL); 3529dd1de374Slin wang - Sun Microsystems - Beijing China mac_init_ops(&arn_dev_ops, "arn"); 3530dd1de374Slin wang - Sun Microsystems - Beijing China status = mod_install(&modlinkage); 3531dd1de374Slin wang - Sun Microsystems - Beijing China if (status != 0) { 3532dd1de374Slin wang - Sun Microsystems - Beijing China mac_fini_ops(&arn_dev_ops); 3533dd1de374Slin wang - Sun Microsystems - Beijing China mutex_destroy(&arn_loglock); 3534dd1de374Slin wang - Sun Microsystems - Beijing China ddi_soft_state_fini(&arn_soft_state_p); 3535dd1de374Slin wang - Sun Microsystems - Beijing China } 3536dd1de374Slin wang - Sun Microsystems - Beijing China 3537dd1de374Slin wang - Sun Microsystems - Beijing China return (status); 3538dd1de374Slin wang - Sun Microsystems - Beijing China } 3539dd1de374Slin wang - Sun Microsystems - Beijing China 3540dd1de374Slin wang - Sun Microsystems - Beijing China int 3541dd1de374Slin wang - Sun Microsystems - Beijing China _fini(void) 3542dd1de374Slin wang - Sun Microsystems - Beijing China { 3543dd1de374Slin wang - Sun Microsystems - Beijing China int status; 3544dd1de374Slin wang - Sun Microsystems - Beijing China 3545dd1de374Slin wang - Sun Microsystems - Beijing China status = mod_remove(&modlinkage); 3546dd1de374Slin wang - Sun Microsystems - Beijing China if (status == 0) { 3547dd1de374Slin wang - Sun Microsystems - Beijing China mac_fini_ops(&arn_dev_ops); 3548dd1de374Slin wang - Sun Microsystems - Beijing China mutex_destroy(&arn_loglock); 3549dd1de374Slin wang - Sun Microsystems - Beijing China ddi_soft_state_fini(&arn_soft_state_p); 3550dd1de374Slin wang - Sun Microsystems - Beijing China } 3551dd1de374Slin wang - Sun Microsystems - Beijing China return (status); 3552dd1de374Slin wang - Sun Microsystems - Beijing China } 3553