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