xref: /titanic_51/usr/src/uts/common/io/iwh/iwh.c (revision 0dc2366f7b9f9f36e10909b1e95edbf2a261c2ac)
1c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
27d483bc1Sfei feng - Sun Microsystems - Beijing China  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
3c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * Use is subject to license terms.
4c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
5c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
6c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
7e2cf88acSQuaker Fang  * Copyright (c) 2009, Intel Corporation
8c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * All rights reserved.
9c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
10c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
11c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
12c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * Copyright (c) 2006
13c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * Copyright (c) 2007
14c7ee0b5cSfei feng - Sun Microsystems - Beijing China  *	Damien Bergamini <damien.bergamini@free.fr>
15c7ee0b5cSfei feng - Sun Microsystems - Beijing China  *
16c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * Permission to use, copy, modify, and distribute this software for any
17c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * purpose with or without fee is hereby granted, provided that the above
18c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * copyright notice and this permission notice appear in all copies.
19c7ee0b5cSfei feng - Sun Microsystems - Beijing China  *
20c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
21c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
22c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
23c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
24c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
25c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
26c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
27c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
28c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
29c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
30c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * Intel(R) WiFi Link 5100/5300 Driver
31c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
32c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
33c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include <sys/types.h>
34c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include <sys/byteorder.h>
35c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include <sys/conf.h>
36c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include <sys/cmn_err.h>
37c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include <sys/stat.h>
38c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include <sys/ddi.h>
39c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include <sys/sunddi.h>
40c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include <sys/strsubr.h>
41c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include <sys/ethernet.h>
42c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include <inet/common.h>
43c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include <inet/nd.h>
44c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include <inet/mi.h>
45c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include <sys/note.h>
46c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include <sys/stream.h>
47c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include <sys/strsun.h>
48c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include <sys/modctl.h>
49c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include <sys/devops.h>
50c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include <sys/dlpi.h>
51da14cebeSEric Cheng #include <sys/mac_provider.h>
52c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include <sys/mac_wifi.h>
53c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include <sys/net80211.h>
54c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include <sys/net80211_proto.h>
55e2cf88acSQuaker Fang #include <sys/net80211_ht.h>
56c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include <sys/varargs.h>
57c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include <sys/policy.h>
58c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include <sys/pci.h>
59c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
60c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include "iwh_calibration.h"
61c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include "iwh_hw.h"
62c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include "iwh_eeprom.h"
63c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include "iwh_var.h"
64c7ee0b5cSfei feng - Sun Microsystems - Beijing China #include <inet/wifi_ioctl.h>
65c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
66c7ee0b5cSfei feng - Sun Microsystems - Beijing China #ifdef DEBUG
67c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	IWH_DEBUG_80211		(1 << 0)
68c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	IWH_DEBUG_CMD		(1 << 1)
69c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	IWH_DEBUG_DMA		(1 << 2)
70c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	IWH_DEBUG_EEPROM	(1 << 3)
71c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	IWH_DEBUG_FW		(1 << 4)
72c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	IWH_DEBUG_HW		(1 << 5)
73c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	IWH_DEBUG_INTR		(1 << 6)
74c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	IWH_DEBUG_MRR		(1 << 7)
75c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	IWH_DEBUG_PIO		(1 << 8)
76c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	IWH_DEBUG_RX		(1 << 9)
77c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	IWH_DEBUG_SCAN		(1 << 10)
78c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	IWH_DEBUG_TX		(1 << 11)
79c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	IWH_DEBUG_RATECTL	(1 << 12)
80c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	IWH_DEBUG_RADIO		(1 << 13)
81c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	IWH_DEBUG_RESUME	(1 << 14)
82c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	IWH_DEBUG_CALIBRATION	(1 << 15)
83e2cf88acSQuaker Fang #define	IWH_DEBUG_BA		(1 << 16)
84e2cf88acSQuaker Fang #define	IWH_DEBUG_RXON		(1 << 17)
85e2cf88acSQuaker Fang #define	IWH_DEBUG_HWRATE	(1 << 18)
86e2cf88acSQuaker Fang #define	IWH_DEBUG_HTRATE	(1 << 19)
87e2cf88acSQuaker Fang #define	IWH_DEBUG_QOS		(1 << 20)
88c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
89c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * if want to see debug message of a given section,
90c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * please set this flag to one of above values
91c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
92c7ee0b5cSfei feng - Sun Microsystems - Beijing China uint32_t iwh_dbg_flags = 0;
93c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	IWH_DBG(x) \
94c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_dbg x
95c7ee0b5cSfei feng - Sun Microsystems - Beijing China #else
96c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	IWH_DBG(x)
97c7ee0b5cSfei feng - Sun Microsystems - Beijing China #endif
98c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
99e2cf88acSQuaker Fang #define	MS(v, f)    (((v) & f) >> f##_S)
100e2cf88acSQuaker Fang 
101c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	*iwh_soft_state_p = NULL;
102c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
103c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
104c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * ucode will be compiled into driver image
105c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
10689b2a9fbSfei feng - Sun Microsystems - Beijing China static uint8_t iwh_fw_5000_bin[] = {
10789b2a9fbSfei feng - Sun Microsystems - Beijing China #include "fw-iw/fw_5000/iwh_5000.ucode"
10889b2a9fbSfei feng - Sun Microsystems - Beijing China };
10989b2a9fbSfei feng - Sun Microsystems - Beijing China 
11089b2a9fbSfei feng - Sun Microsystems - Beijing China static uint8_t iwh_fw_5150_bin[] = {
11189b2a9fbSfei feng - Sun Microsystems - Beijing China #include "fw-iw/fw_5150/iwh_5150.ucode"
112c7ee0b5cSfei feng - Sun Microsystems - Beijing China };
113c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
114c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
115c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * DMA attributes for a shared page
116c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
117c7ee0b5cSfei feng - Sun Microsystems - Beijing China static ddi_dma_attr_t sh_dma_attr = {
118c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	DMA_ATTR_V0,	/* version of this structure */
119c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0,		/* lowest usable address */
120c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* highest usable address */
121c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* maximum DMAable byte count */
122c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0x1000,		/* alignment in bytes */
123c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0x1000,		/* burst sizes (any?) */
124c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	1,		/* minimum transfer */
125c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* maximum transfer */
126c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* maximum segment length */
127c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	1,		/* maximum number of segments */
128c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	1,		/* granularity */
129c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0,		/* flags (reserved) */
130c7ee0b5cSfei feng - Sun Microsystems - Beijing China };
131c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
132c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
133c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * DMA attributes for a keep warm DRAM descriptor
134c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
135c7ee0b5cSfei feng - Sun Microsystems - Beijing China static ddi_dma_attr_t kw_dma_attr = {
136c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	DMA_ATTR_V0,	/* version of this structure */
137c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0,		/* lowest usable address */
138c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* highest usable address */
139c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* maximum DMAable byte count */
140c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0x1000,		/* alignment in bytes */
141c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0x1000,		/* burst sizes (any?) */
142c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	1,		/* minimum transfer */
143c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* maximum transfer */
144c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* maximum segment length */
145c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	1,		/* maximum number of segments */
146c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	1,		/* granularity */
147c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0,		/* flags (reserved) */
148c7ee0b5cSfei feng - Sun Microsystems - Beijing China };
149c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
150c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
151c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * DMA attributes for a ring descriptor
152c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
153c7ee0b5cSfei feng - Sun Microsystems - Beijing China static ddi_dma_attr_t ring_desc_dma_attr = {
154c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	DMA_ATTR_V0,	/* version of this structure */
155c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0,		/* lowest usable address */
156c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* highest usable address */
157c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* maximum DMAable byte count */
158c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0x100,		/* alignment in bytes */
159c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0x100,		/* burst sizes (any?) */
160c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	1,		/* minimum transfer */
161c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* maximum transfer */
162c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* maximum segment length */
163c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	1,		/* maximum number of segments */
164c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	1,		/* granularity */
165c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0,		/* flags (reserved) */
166c7ee0b5cSfei feng - Sun Microsystems - Beijing China };
167c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
168c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
169c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * DMA attributes for a cmd
170c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
171c7ee0b5cSfei feng - Sun Microsystems - Beijing China static ddi_dma_attr_t cmd_dma_attr = {
172c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	DMA_ATTR_V0,	/* version of this structure */
173c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0,		/* lowest usable address */
174c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* highest usable address */
175c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* maximum DMAable byte count */
176c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	4,		/* alignment in bytes */
177c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0x100,		/* burst sizes (any?) */
178c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	1,		/* minimum transfer */
179c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* maximum transfer */
180c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* maximum segment length */
181c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	1,		/* maximum number of segments */
182c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	1,		/* granularity */
183c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0,		/* flags (reserved) */
184c7ee0b5cSfei feng - Sun Microsystems - Beijing China };
185c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
186c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
187c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * DMA attributes for a rx buffer
188c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
189c7ee0b5cSfei feng - Sun Microsystems - Beijing China static ddi_dma_attr_t rx_buffer_dma_attr = {
190c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	DMA_ATTR_V0,	/* version of this structure */
191c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0,		/* lowest usable address */
192c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* highest usable address */
193c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* maximum DMAable byte count */
194c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0x100,		/* alignment in bytes */
195c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0x100,		/* burst sizes (any?) */
196c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	1,		/* minimum transfer */
197c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* maximum transfer */
198c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* maximum segment length */
199c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	1,		/* maximum number of segments */
200c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	1,		/* granularity */
201c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0,		/* flags (reserved) */
202c7ee0b5cSfei feng - Sun Microsystems - Beijing China };
203c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
204c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
205c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * DMA attributes for a tx buffer.
206c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * the maximum number of segments is 4 for the hardware.
207c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * now all the wifi drivers put the whole frame in a single
208c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * descriptor, so we define the maximum  number of segments 1,
209c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * just the same as the rx_buffer. we consider leverage the HW
210c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * ability in the future, that is why we don't define rx and tx
211c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * buffer_dma_attr as the same.
212c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
213c7ee0b5cSfei feng - Sun Microsystems - Beijing China static ddi_dma_attr_t tx_buffer_dma_attr = {
214c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	DMA_ATTR_V0,	/* version of this structure */
215c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0,		/* lowest usable address */
216c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* highest usable address */
217c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* maximum DMAable byte count */
218c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	4,		/* alignment in bytes */
219c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0x100,		/* burst sizes (any?) */
220c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	1,		/* minimum transfer */
221c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* maximum transfer */
222c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* maximum segment length */
223c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	1,		/* maximum number of segments */
224c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	1,		/* granularity */
225c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0,		/* flags (reserved) */
226c7ee0b5cSfei feng - Sun Microsystems - Beijing China };
227c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
228c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
229c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * DMA attributes for text and data part in the firmware
230c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
231c7ee0b5cSfei feng - Sun Microsystems - Beijing China static ddi_dma_attr_t fw_dma_attr = {
232c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	DMA_ATTR_V0,	/* version of this structure */
233c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0,		/* lowest usable address */
234c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* highest usable address */
235c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0x7fffffff,	/* maximum DMAable byte count */
236c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0x10,		/* alignment in bytes */
237c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0x100,		/* burst sizes (any?) */
238c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	1,		/* minimum transfer */
239c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* maximum transfer */
240c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0xffffffffU,	/* maximum segment length */
241c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	1,		/* maximum number of segments */
242c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	1,		/* granularity */
243c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	0,		/* flags (reserved) */
244c7ee0b5cSfei feng - Sun Microsystems - Beijing China };
245c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
246c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
247c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * regs access attributes
248c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
249c7ee0b5cSfei feng - Sun Microsystems - Beijing China static ddi_device_acc_attr_t iwh_reg_accattr = {
250c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	DDI_DEVICE_ATTR_V0,
251c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	DDI_STRUCTURE_LE_ACC,
252c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	DDI_STRICTORDER_ACC,
253c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	DDI_DEFAULT_ACC
254c7ee0b5cSfei feng - Sun Microsystems - Beijing China };
255c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
256c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
257b510adaeSfei feng - Sun Microsystems - Beijing China  * DMA access attributes for descriptor
258b510adaeSfei feng - Sun Microsystems - Beijing China  */
259b510adaeSfei feng - Sun Microsystems - Beijing China static ddi_device_acc_attr_t iwh_dma_descattr = {
260b510adaeSfei feng - Sun Microsystems - Beijing China 	DDI_DEVICE_ATTR_V0,
261b510adaeSfei feng - Sun Microsystems - Beijing China 	DDI_STRUCTURE_LE_ACC,
262b510adaeSfei feng - Sun Microsystems - Beijing China 	DDI_STRICTORDER_ACC,
263b510adaeSfei feng - Sun Microsystems - Beijing China 	DDI_DEFAULT_ACC
264b510adaeSfei feng - Sun Microsystems - Beijing China };
265b510adaeSfei feng - Sun Microsystems - Beijing China 
266b510adaeSfei feng - Sun Microsystems - Beijing China /*
267c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * DMA access attributes
268c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
269c7ee0b5cSfei feng - Sun Microsystems - Beijing China static ddi_device_acc_attr_t iwh_dma_accattr = {
270c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	DDI_DEVICE_ATTR_V0,
271c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	DDI_NEVERSWAP_ACC,
272c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	DDI_STRICTORDER_ACC,
273c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	DDI_DEFAULT_ACC
274c7ee0b5cSfei feng - Sun Microsystems - Beijing China };
275c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
276c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_ring_init(iwh_sc_t *);
277c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_ring_free(iwh_sc_t *);
278c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_alloc_shared(iwh_sc_t *);
279c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_free_shared(iwh_sc_t *);
280c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_alloc_kw(iwh_sc_t *);
281c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_free_kw(iwh_sc_t *);
282c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_alloc_fw_dma(iwh_sc_t *);
283c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_free_fw_dma(iwh_sc_t *);
284c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_alloc_rx_ring(iwh_sc_t *);
285c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_reset_rx_ring(iwh_sc_t *);
286c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_free_rx_ring(iwh_sc_t *);
287c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_alloc_tx_ring(iwh_sc_t *, iwh_tx_ring_t *,
288c7ee0b5cSfei feng - Sun Microsystems - Beijing China     int, int);
289c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_reset_tx_ring(iwh_sc_t *, iwh_tx_ring_t *);
290c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_free_tx_ring(iwh_tx_ring_t *);
291c7ee0b5cSfei feng - Sun Microsystems - Beijing China static ieee80211_node_t *iwh_node_alloc(ieee80211com_t *);
292c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_node_free(ieee80211_node_t *);
293c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_newstate(ieee80211com_t *, enum ieee80211_state, int);
294c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_mac_access_enter(iwh_sc_t *);
295c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_mac_access_exit(iwh_sc_t *);
296c7ee0b5cSfei feng - Sun Microsystems - Beijing China static uint32_t	iwh_reg_read(iwh_sc_t *, uint32_t);
297c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_reg_write(iwh_sc_t *, uint32_t, uint32_t);
298c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_load_init_firmware(iwh_sc_t *);
299c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_load_run_firmware(iwh_sc_t *);
300c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_tx_intr(iwh_sc_t *, iwh_rx_desc_t *);
301c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_cmd_intr(iwh_sc_t *, iwh_rx_desc_t *);
302c7ee0b5cSfei feng - Sun Microsystems - Beijing China static uint_t   iwh_intr(caddr_t, caddr_t);
303c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_eep_load(iwh_sc_t *);
304c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_get_mac_from_eep(iwh_sc_t *);
305c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_eep_sem_down(iwh_sc_t *);
306c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_eep_sem_up(iwh_sc_t *);
307c7ee0b5cSfei feng - Sun Microsystems - Beijing China static uint_t   iwh_rx_softintr(caddr_t, caddr_t);
308c7ee0b5cSfei feng - Sun Microsystems - Beijing China static uint8_t	iwh_rate_to_plcp(int);
309c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_cmd(iwh_sc_t *, int, const void *, int, int);
310c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_set_led(iwh_sc_t *, uint8_t, uint8_t, uint8_t);
311c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_hw_set_before_auth(iwh_sc_t *);
312c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_scan(iwh_sc_t *);
313c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_config(iwh_sc_t *);
314c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_stop_master(iwh_sc_t *);
315c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_power_up(iwh_sc_t *);
316c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_preinit(iwh_sc_t *);
317c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_init(iwh_sc_t *);
318c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_stop(iwh_sc_t *);
319faceed93Sfei feng - Sun Microsystems - Beijing China static int	iwh_quiesce(dev_info_t *t);
320c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_amrr_init(iwh_amrr_t *);
321c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_amrr_timeout(iwh_sc_t *);
322c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_amrr_ratectl(void *, ieee80211_node_t *);
323c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_ucode_alive(iwh_sc_t *, iwh_rx_desc_t *);
324c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_rx_phy_intr(iwh_sc_t *, iwh_rx_desc_t *);
325c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_rx_mpdu_intr(iwh_sc_t *, iwh_rx_desc_t *);
326c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_release_calib_buffer(iwh_sc_t *);
327c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_init_common(iwh_sc_t *);
328c7ee0b5cSfei feng - Sun Microsystems - Beijing China static uint8_t	*iwh_eep_addr_trans(iwh_sc_t *, uint32_t);
329c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_put_seg_fw(iwh_sc_t *, uint32_t, uint32_t, uint32_t);
330c7ee0b5cSfei feng - Sun Microsystems - Beijing China static	int	iwh_alive_common(iwh_sc_t *);
331c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_save_calib_result(iwh_sc_t *, iwh_rx_desc_t *);
332c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_tx_power_table(iwh_sc_t *, int);
333c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_attach(dev_info_t *, ddi_attach_cmd_t);
334c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_detach(dev_info_t *, ddi_detach_cmd_t);
335c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_destroy_locks(iwh_sc_t *);
336c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_send(ieee80211com_t *, mblk_t *, uint8_t);
337c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_thread(iwh_sc_t *);
338e2cf88acSQuaker Fang static int	iwh_run_state_config(iwh_sc_t *);
339e2cf88acSQuaker Fang static int	iwh_fast_recover(iwh_sc_t *);
340e2cf88acSQuaker Fang static int	iwh_wme_update(ieee80211com_t *);
341e2cf88acSQuaker Fang static int	iwh_qosparam_to_hw(iwh_sc_t *, int);
342e2cf88acSQuaker Fang static int	iwh_wme_to_qos_ac(int);
343e2cf88acSQuaker Fang static uint16_t	iwh_cw_e_to_cw(uint8_t);
344e2cf88acSQuaker Fang static int	iwh_wmeparam_check(struct wmeParams *);
345e2cf88acSQuaker Fang static inline int	iwh_wme_tid_qos_ac(int);
346e2cf88acSQuaker Fang static inline int	iwh_qos_ac_to_txq(int);
347e2cf88acSQuaker Fang static int	iwh_wme_tid_to_txq(int);
348e2cf88acSQuaker Fang static void	iwh_init_ht_conf(iwh_sc_t *);
349e2cf88acSQuaker Fang static void	iwh_overwrite_11n_rateset(iwh_sc_t *);
350e2cf88acSQuaker Fang static void	iwh_overwrite_ic_default(iwh_sc_t *);
351e2cf88acSQuaker Fang static void	iwh_config_rxon_chain(iwh_sc_t *);
352e2cf88acSQuaker Fang static int	iwh_add_ap_sta(iwh_sc_t *);
353e2cf88acSQuaker Fang static int	iwh_ap_lq(iwh_sc_t *);
354e2cf88acSQuaker Fang static void	iwh_recv_action(struct ieee80211_node *,
355e2cf88acSQuaker Fang     const uint8_t *, const uint8_t *);
356e2cf88acSQuaker Fang static int	iwh_send_action(struct ieee80211_node *,
357e2cf88acSQuaker Fang     int, int, uint16_t[4]);
358e2cf88acSQuaker Fang static int	iwh_is_max_rate(ieee80211_node_t *);
359e2cf88acSQuaker Fang static int	iwh_is_min_rate(ieee80211_node_t *);
360e2cf88acSQuaker Fang static void	iwh_increase_rate(ieee80211_node_t *);
361e2cf88acSQuaker Fang static void	iwh_decrease_rate(ieee80211_node_t *);
362e2cf88acSQuaker Fang static int	iwh_alloc_dma_mem(iwh_sc_t *, size_t,
363e2cf88acSQuaker Fang     ddi_dma_attr_t *, ddi_device_acc_attr_t *,
364e2cf88acSQuaker Fang     uint_t, iwh_dma_t *);
365e2cf88acSQuaker Fang static void	iwh_free_dma_mem(iwh_dma_t *);
3667d483bc1Sfei feng - Sun Microsystems - Beijing China static int	iwh_reset_hw(iwh_sc_t *);
3676f12def4Spengcheng chen - Sun Microsystems - Beijing China 
368c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
369c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * GLD specific operations
370c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
371c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_m_stat(void *, uint_t, uint64_t *);
372c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_m_start(void *);
373c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_m_stop(void *);
374c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_m_unicst(void *, const uint8_t *);
375c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_m_multicst(void *, boolean_t, const uint8_t *);
376c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int	iwh_m_promisc(void *, boolean_t);
377c7ee0b5cSfei feng - Sun Microsystems - Beijing China static mblk_t	*iwh_m_tx(void *, mblk_t *);
378c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void	iwh_m_ioctl(void *, queue_t *, mblk_t *);
3797efa17f5Sfei feng - Sun Microsystems - Beijing China static int	iwh_m_setprop(void *arg, const char *pr_name,
3807efa17f5Sfei feng - Sun Microsystems - Beijing China     mac_prop_id_t wldp_pr_num, uint_t wldp_length, const void *wldp_buf);
3817efa17f5Sfei feng - Sun Microsystems - Beijing China static int	iwh_m_getprop(void *arg, const char *pr_name,
382*0dc2366fSVenugopal Iyer     mac_prop_id_t wldp_pr_num, uint_t wldp_length,
383*0dc2366fSVenugopal Iyer     void *wldp_buf);
384*0dc2366fSVenugopal Iyer static void	iwh_m_propinfo(void *arg, const char *pr_name,
385*0dc2366fSVenugopal Iyer     mac_prop_id_t wldp_pr_num, mac_prop_info_handle_t mph);
386c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
387c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
388c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * Supported rates for 802.11b/g modes (in 500Kbps unit).
389c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
390c7ee0b5cSfei feng - Sun Microsystems - Beijing China static const struct ieee80211_rateset iwh_rateset_11b =
391c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	{ 4, { 2, 4, 11, 22 } };
392c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
393c7ee0b5cSfei feng - Sun Microsystems - Beijing China static const struct ieee80211_rateset iwh_rateset_11g =
394c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	{ 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
395c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
396c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
397e2cf88acSQuaker Fang  * Default 11n reates supported by this station.
398e2cf88acSQuaker Fang  */
399e2cf88acSQuaker Fang extern struct ieee80211_htrateset ieee80211_rateset_11n;
400e2cf88acSQuaker Fang 
401e2cf88acSQuaker Fang /*
402c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * For mfthread only
403c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
404c7ee0b5cSfei feng - Sun Microsystems - Beijing China extern pri_t minclsyspri;
405c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
406c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	DRV_NAME_SP	"iwh"
407c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
408c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
409c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * Module Loading Data & Entry Points
410c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
411c7ee0b5cSfei feng - Sun Microsystems - Beijing China DDI_DEFINE_STREAM_OPS(iwh_devops, nulldev, nulldev, iwh_attach,
412faceed93Sfei feng - Sun Microsystems - Beijing China     iwh_detach, nodev, NULL, D_MP, NULL, iwh_quiesce);
413c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
414c7ee0b5cSfei feng - Sun Microsystems - Beijing China static struct modldrv iwh_modldrv = {
415c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	&mod_driverops,
41689b2a9fbSfei feng - Sun Microsystems - Beijing China 	"Intel(R) ShirleyPeak/EchoPeak driver(N)",
417c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	&iwh_devops
418c7ee0b5cSfei feng - Sun Microsystems - Beijing China };
419c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
420c7ee0b5cSfei feng - Sun Microsystems - Beijing China static struct modlinkage iwh_modlinkage = {
421c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	MODREV_1,
422c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	&iwh_modldrv,
423c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	NULL
424c7ee0b5cSfei feng - Sun Microsystems - Beijing China };
425c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
426c7ee0b5cSfei feng - Sun Microsystems - Beijing China int
427c7ee0b5cSfei feng - Sun Microsystems - Beijing China _init(void)
428c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
429c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	int status;
430c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
431c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	status = ddi_soft_state_init(&iwh_soft_state_p,
432c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    sizeof (iwh_sc_t), 1);
433c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (status != DDI_SUCCESS) {
434c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (status);
435c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
436c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
437c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mac_init_ops(&iwh_devops, DRV_NAME_SP);
438c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	status = mod_install(&iwh_modlinkage);
439c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (status != DDI_SUCCESS) {
440c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		mac_fini_ops(&iwh_devops);
441c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ddi_soft_state_fini(&iwh_soft_state_p);
442c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
443c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
444c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (status);
445c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
446c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
447c7ee0b5cSfei feng - Sun Microsystems - Beijing China int
448c7ee0b5cSfei feng - Sun Microsystems - Beijing China _fini(void)
449c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
450c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	int status;
451c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
452c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	status = mod_remove(&iwh_modlinkage);
453c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (DDI_SUCCESS == status) {
454c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		mac_fini_ops(&iwh_devops);
455c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ddi_soft_state_fini(&iwh_soft_state_p);
456c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
457c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
458c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (status);
459c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
460c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
461c7ee0b5cSfei feng - Sun Microsystems - Beijing China int
462c7ee0b5cSfei feng - Sun Microsystems - Beijing China _info(struct modinfo *mip)
463c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
464c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (mod_info(&iwh_modlinkage, mip));
465c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
466c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
467c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
468c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * Mac Call Back entries
469c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
470c7ee0b5cSfei feng - Sun Microsystems - Beijing China mac_callbacks_t	iwh_m_callbacks = {
471*0dc2366fSVenugopal Iyer 	MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO,
472c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_m_stat,
473c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_m_start,
474c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_m_stop,
475c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_m_promisc,
476c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_m_multicst,
477c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_m_unicst,
478c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_m_tx,
479*0dc2366fSVenugopal Iyer 	NULL,
4807efa17f5Sfei feng - Sun Microsystems - Beijing China 	iwh_m_ioctl,
4817efa17f5Sfei feng - Sun Microsystems - Beijing China 	NULL,
4827efa17f5Sfei feng - Sun Microsystems - Beijing China 	NULL,
4837efa17f5Sfei feng - Sun Microsystems - Beijing China 	NULL,
4847efa17f5Sfei feng - Sun Microsystems - Beijing China 	iwh_m_setprop,
485*0dc2366fSVenugopal Iyer 	iwh_m_getprop,
486*0dc2366fSVenugopal Iyer 	iwh_m_propinfo
487c7ee0b5cSfei feng - Sun Microsystems - Beijing China };
488c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
489c7ee0b5cSfei feng - Sun Microsystems - Beijing China #ifdef DEBUG
490c7ee0b5cSfei feng - Sun Microsystems - Beijing China void
491c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_dbg(uint32_t flags, const char *fmt, ...)
492c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
493c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	va_list	ap;
494c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
495c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (flags & iwh_dbg_flags) {
496c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		va_start(ap, fmt);
497d40f4da4Spengcheng chen - Sun Microsystems - Beijing China 		vcmn_err(CE_NOTE, fmt, ap);
498c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		va_end(ap);
499c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
500c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
501e2cf88acSQuaker Fang #endif	/* DEBUG */
502c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
503c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
504c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * device operations
505c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
506c7ee0b5cSfei feng - Sun Microsystems - Beijing China int
507c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
508c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
509c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_sc_t *sc;
510c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ieee80211com_t *ic;
511e2cf88acSQuaker Fang 	int instance, i;
512c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	char strbuf[32];
513c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	wifi_data_t wd = { 0 };
514c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mac_register_t *macp;
515c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	int intr_type;
516c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	int intr_count;
517c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	int intr_actual;
518e2cf88acSQuaker Fang 	int err = DDI_FAILURE;
519c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
520c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	switch (cmd) {
521c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case DDI_ATTACH:
522c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
523e2cf88acSQuaker Fang 
524c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case DDI_RESUME:
525e2cf88acSQuaker Fang 		instance = ddi_get_instance(dip);
526c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc = ddi_get_soft_state(iwh_soft_state_p,
527e2cf88acSQuaker Fang 		    instance);
528c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ASSERT(sc != NULL);
52909539a3cSpengcheng chen - Sun Microsystems - Beijing China 
530e2cf88acSQuaker Fang 		if (sc->sc_flags & IWH_F_RUNNING) {
531d40f4da4Spengcheng chen - Sun Microsystems - Beijing China 			(void) iwh_init(sc);
532e2cf88acSQuaker Fang 		}
533d40f4da4Spengcheng chen - Sun Microsystems - Beijing China 
53489b2a9fbSfei feng - Sun Microsystems - Beijing China 		atomic_and_32(&sc->sc_flags, ~IWH_F_SUSPEND);
53589b2a9fbSfei feng - Sun Microsystems - Beijing China 
536e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_RESUME, "iwh_attach(): "
537e2cf88acSQuaker Fang 		    "resume\n"));
538c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (DDI_SUCCESS);
539e2cf88acSQuaker Fang 
540c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	default:
541c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto attach_fail1;
542c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
543c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
544c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	instance = ddi_get_instance(dip);
545c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = ddi_soft_state_zalloc(iwh_soft_state_p, instance);
546c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
547c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_attach(): "
548c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to allocate soft state\n");
549c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto attach_fail1;
550c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
551e2cf88acSQuaker Fang 
552c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc = ddi_get_soft_state(iwh_soft_state_p, instance);
553e2cf88acSQuaker Fang 	ASSERT(sc != NULL);
554e2cf88acSQuaker Fang 
555c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_dip = dip;
556c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
557c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
558c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * map configure space
559c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
560c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = ddi_regs_map_setup(dip, 0, &sc->sc_cfg_base, 0, 0,
561c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    &iwh_reg_accattr, &sc->sc_cfg_handle);
562c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
563c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_attach(): "
564c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to map config spaces regs\n");
565c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto attach_fail2;
566c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
567c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
568e2cf88acSQuaker Fang 	sc->sc_dev_id = ddi_get16(sc->sc_cfg_handle,
569e2cf88acSQuaker Fang 	    (uint16_t *)(sc->sc_cfg_base + PCI_CONF_DEVID));
570e2cf88acSQuaker Fang 	if ((sc->sc_dev_id != 0x4232) &&
571e2cf88acSQuaker Fang 	    (sc->sc_dev_id != 0x4235) &&
572e2cf88acSQuaker Fang 	    (sc->sc_dev_id != 0x4236) &&
573e2cf88acSQuaker Fang 	    (sc->sc_dev_id != 0x4237) &&
57489b2a9fbSfei feng - Sun Microsystems - Beijing China 	    (sc->sc_dev_id != 0x423a) &&
57589b2a9fbSfei feng - Sun Microsystems - Beijing China 	    (sc->sc_dev_id != 0x423b) &&
57689b2a9fbSfei feng - Sun Microsystems - Beijing China 	    (sc->sc_dev_id != 0x423c) &&
57789b2a9fbSfei feng - Sun Microsystems - Beijing China 	    (sc->sc_dev_id != 0x423d)) {
578e2cf88acSQuaker Fang 		cmn_err(CE_WARN, "iwh_attach(): "
579e2cf88acSQuaker Fang 		    "Do not support this device\n");
580e2cf88acSQuaker Fang 		goto attach_fail3;
581e2cf88acSQuaker Fang 	}
582e2cf88acSQuaker Fang 
583e2cf88acSQuaker Fang 	iwh_init_ht_conf(sc);
584e2cf88acSQuaker Fang 	iwh_overwrite_11n_rateset(sc);
585c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
586c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_rev = ddi_get8(sc->sc_cfg_handle,
587c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    (uint8_t *)(sc->sc_cfg_base + PCI_CONF_REVID));
588c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
589c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
590c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * keep from disturbing C3 state of CPU
591c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
59289b2a9fbSfei feng - Sun Microsystems - Beijing China 	ddi_put8(sc->sc_cfg_handle, (uint8_t *)(sc->sc_cfg_base +
59389b2a9fbSfei feng - Sun Microsystems - Beijing China 	    PCI_CFG_RETRY_TIMEOUT), 0);
594e2cf88acSQuaker Fang 
595e2cf88acSQuaker Fang 	/*
596e2cf88acSQuaker Fang 	 * determine the size of buffer for frame and command to ucode
597e2cf88acSQuaker Fang 	 */
598c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_clsz = ddi_get16(sc->sc_cfg_handle,
599c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    (uint16_t *)(sc->sc_cfg_base + PCI_CONF_CACHE_LINESZ));
600c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (!sc->sc_clsz) {
601c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_clsz = 16;
602c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
603c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_clsz = (sc->sc_clsz << 2);
604e2cf88acSQuaker Fang 
605e2cf88acSQuaker Fang 	sc->sc_dmabuf_sz = roundup(0x2000 + sizeof (struct ieee80211_frame) +
606c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    IEEE80211_MTU + IEEE80211_CRC_LEN +
607c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
608c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    IEEE80211_WEP_CRCLEN), sc->sc_clsz);
609c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
610c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
611c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * Map operating registers
612c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
613c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = ddi_regs_map_setup(dip, 1, &sc->sc_base,
614c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    0, 0, &iwh_reg_accattr, &sc->sc_handle);
615c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
616c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_attach(): "
617c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to map device regs\n");
618c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto attach_fail3;
619c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
620c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
621c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
622c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * this is used to differentiate type of hardware
623c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
624c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_hw_rev = IWH_READ(sc, CSR_HW_REV);
625c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
626c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = ddi_intr_get_supported_types(dip, &intr_type);
627c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if ((err != DDI_SUCCESS) || (!(intr_type & DDI_INTR_TYPE_FIXED))) {
628c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_attach(): "
629c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "fixed type interrupt is not supported\n");
630c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto attach_fail4;
631c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
632c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
633c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = ddi_intr_get_nintrs(dip, DDI_INTR_TYPE_FIXED, &intr_count);
634c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if ((err != DDI_SUCCESS) || (intr_count != 1)) {
635c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_attach(): "
636c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "no fixed interrupts\n");
637c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto attach_fail4;
638c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
639c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
640c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_intr_htable = kmem_zalloc(sizeof (ddi_intr_handle_t), KM_SLEEP);
641c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
642c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = ddi_intr_alloc(dip, sc->sc_intr_htable, DDI_INTR_TYPE_FIXED, 0,
643c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    intr_count, &intr_actual, 0);
644c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if ((err != DDI_SUCCESS) || (intr_actual != 1)) {
645c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_attach(): "
646c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "ddi_intr_alloc() failed 0x%x\n", err);
647c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto attach_fail5;
648c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
649c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
650c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = ddi_intr_get_pri(sc->sc_intr_htable[0], &sc->sc_intr_pri);
651c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
652c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_attach(): "
653c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "ddi_intr_get_pri() failed 0x%x\n", err);
654c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto attach_fail6;
655c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
656c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
657c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mutex_init(&sc->sc_glock, NULL, MUTEX_DRIVER,
658c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    DDI_INTR_PRI(sc->sc_intr_pri));
659c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mutex_init(&sc->sc_tx_lock, NULL, MUTEX_DRIVER,
660c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    DDI_INTR_PRI(sc->sc_intr_pri));
661c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mutex_init(&sc->sc_mt_lock, NULL, MUTEX_DRIVER,
662c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    DDI_INTR_PRI(sc->sc_intr_pri));
663c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
664c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	cv_init(&sc->sc_cmd_cv, NULL, CV_DRIVER, NULL);
665c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	cv_init(&sc->sc_put_seg_cv, NULL, CV_DRIVER, NULL);
666c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	cv_init(&sc->sc_ucode_cv, NULL, CV_DRIVER, NULL);
667c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
668c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
669c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * initialize the mfthread
670c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
671c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	cv_init(&sc->sc_mt_cv, NULL, CV_DRIVER, NULL);
672c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_mf_thread = NULL;
673c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_mf_thread_switch = 0;
674c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
675c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
676c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * Allocate shared buffer for communication between driver and ucode.
677c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
678c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_alloc_shared(sc);
679c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
680c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_attach(): "
681c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to allocate shared page\n");
682c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto attach_fail7;
683c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
684c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
685c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) memset(sc->sc_shared, 0, sizeof (iwh_shared_t));
686c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
687c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
688c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * Allocate keep warm page.
689c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
690c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_alloc_kw(sc);
691c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
692c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_attach(): "
693c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to allocate keep warm page\n");
694c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto attach_fail8;
695c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
696c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
6977d483bc1Sfei feng - Sun Microsystems - Beijing China 	err = iwh_reset_hw(sc);
6987d483bc1Sfei feng - Sun Microsystems - Beijing China 	if (err != IWH_SUCCESS) {
6997d483bc1Sfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_attach(): "
7007d483bc1Sfei feng - Sun Microsystems - Beijing China 		    "failed to reset hardware\n");
7017d483bc1Sfei feng - Sun Microsystems - Beijing China 		goto attach_fail9;
7027d483bc1Sfei feng - Sun Microsystems - Beijing China 	}
7037d483bc1Sfei feng - Sun Microsystems - Beijing China 
704c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
705c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * Do some necessary hardware initializations.
706c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
707c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_preinit(sc);
708c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != IWH_SUCCESS) {
709c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_attach(): "
710c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to initialize hardware\n");
711c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto attach_fail9;
712c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
713c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
714c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
715c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * get hardware configurations from eeprom
716c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
717c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_eep_load(sc);
718e2cf88acSQuaker Fang 	if (err != IWH_SUCCESS) {
719c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_attach(): "
720c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to load eeprom\n");
721c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto attach_fail9;
722c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
723c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
724c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (IWH_READ_EEP_SHORT(sc, EEP_VERSION) < 0x011a) {
725e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_EEPROM, "iwh_attach(): "
726e2cf88acSQuaker Fang 		    "unsupported eeprom detected\n"));
727c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto attach_fail9;
728c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
729c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
730c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
731c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * get MAC address of this chipset
732c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
733c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_get_mac_from_eep(sc);
734c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
735c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
736c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * calibration information from EEPROM
737c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
738c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_eep_calib = (struct iwh_eep_calibration *)
739c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    iwh_eep_addr_trans(sc, EEP_CALIBRATION);
740c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
741c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
742c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * initialize TX and RX ring buffers
743c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
744c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_ring_init(sc);
745c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
746c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_attach(): "
747c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to allocate and initialize ring\n");
748c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto attach_fail9;
749c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
750c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
75189b2a9fbSfei feng - Sun Microsystems - Beijing China 	if ((0x423c == sc->sc_dev_id) || (0x423d == sc->sc_dev_id)) {
75289b2a9fbSfei feng - Sun Microsystems - Beijing China 		sc->sc_hdr = (iwh_firmware_hdr_t *)iwh_fw_5150_bin;
75389b2a9fbSfei feng - Sun Microsystems - Beijing China 	} else {
75489b2a9fbSfei feng - Sun Microsystems - Beijing China 		sc->sc_hdr = (iwh_firmware_hdr_t *)iwh_fw_5000_bin;
75589b2a9fbSfei feng - Sun Microsystems - Beijing China 	}
756c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
757c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
758c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * copy ucode to dma buffer
759c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
760c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_alloc_fw_dma(sc);
761c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
762c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_attach(): "
763c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to allocate firmware dma\n");
764c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto attach_fail10;
765c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
766c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
767c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
768c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * Initialize the wifi part, which will be used by
769c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * 802.11 module
770c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
771c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ic = &sc->sc_ic;
772e2cf88acSQuaker Fang 	ic->ic_phytype  = IEEE80211_T_HT;
773c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ic->ic_opmode   = IEEE80211_M_STA; /* default to BSS mode */
774c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ic->ic_state    = IEEE80211_S_INIT;
775c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ic->ic_maxrssi  = 100; /* experimental number */
776c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ic->ic_caps = IEEE80211_C_SHPREAMBLE | IEEE80211_C_TXPMGT |
777c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    IEEE80211_C_PMGT | IEEE80211_C_SHSLOT;
778c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
779c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
780c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * Support WPA/WPA2
781c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
782c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ic->ic_caps |= IEEE80211_C_WPA;
783c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
784c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
785e2cf88acSQuaker Fang 	 * Support QoS/WME
786e2cf88acSQuaker Fang 	 */
787e2cf88acSQuaker Fang 	ic->ic_caps |= IEEE80211_C_WME;
788e2cf88acSQuaker Fang 	ic->ic_wme.wme_update = iwh_wme_update;
789e2cf88acSQuaker Fang 
790e2cf88acSQuaker Fang 	/*
791e2cf88acSQuaker Fang 	 * Support 802.11n/HT
792e2cf88acSQuaker Fang 	 */
793e2cf88acSQuaker Fang 	if (sc->sc_ht_conf.ht_support) {
794e2cf88acSQuaker Fang 		ic->ic_htcaps = IEEE80211_HTC_HT |
795e2cf88acSQuaker Fang 		    IEEE80211_HTC_AMSDU;
796e2cf88acSQuaker Fang 		ic->ic_htcaps |= IEEE80211_HTCAP_MAXAMSDU_7935;
797e2cf88acSQuaker Fang 	}
798e2cf88acSQuaker Fang 
799e2cf88acSQuaker Fang 	/*
800c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * set supported .11b and .11g rates
801c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
802c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ic->ic_sup_rates[IEEE80211_MODE_11B] = iwh_rateset_11b;
803c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ic->ic_sup_rates[IEEE80211_MODE_11G] = iwh_rateset_11g;
804c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
805c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
806d5bd65e4Sfei feng - Sun Microsystems - Beijing China 	 * set supported .11b and .11g channels (1 through 11)
807c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
808d5bd65e4Sfei feng - Sun Microsystems - Beijing China 	for (i = 1; i <= 11; i++) {
809c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ic->ic_sup_channels[i].ich_freq =
810c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
811c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ic->ic_sup_channels[i].ich_flags =
812c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
813d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		    IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ |
814d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		    IEEE80211_CHAN_PASSIVE;
815e2cf88acSQuaker Fang 
816e2cf88acSQuaker Fang 		if (sc->sc_ht_conf.cap & HT_CAP_SUP_WIDTH) {
817e2cf88acSQuaker Fang 			ic->ic_sup_channels[i].ich_flags |=
818e2cf88acSQuaker Fang 			    IEEE80211_CHAN_HT40;
819e2cf88acSQuaker Fang 		} else {
820e2cf88acSQuaker Fang 			ic->ic_sup_channels[i].ich_flags |=
821e2cf88acSQuaker Fang 			    IEEE80211_CHAN_HT20;
822e2cf88acSQuaker Fang 		}
823c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
824c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
825c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ic->ic_ibss_chan = &ic->ic_sup_channels[0];
826c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ic->ic_xmit = iwh_send;
827c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
828c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
829c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * attach to 802.11 module
830c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
831c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ieee80211_attach(ic);
832c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
833c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
834c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * different instance has different WPA door
835c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
836c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) snprintf(ic->ic_wpadoor, MAX_IEEE80211STR, "%s_%s%d", WPA_DOOR,
837c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    ddi_driver_name(dip),
838c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    ddi_get_instance(dip));
839c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
840c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
841e2cf88acSQuaker Fang 	 * Overwrite 80211 default configurations.
842c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
843e2cf88acSQuaker Fang 	iwh_overwrite_ic_default(sc);
844c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
845c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
846c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * initialize 802.11 module
847c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
848c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ieee80211_media_init(ic);
849c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
850c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
851c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * initialize default tx key
852c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
853c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ic->ic_def_txkey = 0;
854c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
855c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = ddi_intr_add_softint(dip, &sc->sc_soft_hdl, DDI_INTR_SOFTPRI_MAX,
856c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    iwh_rx_softintr, (caddr_t)sc);
857c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
858c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_attach(): "
859c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "add soft interrupt failed\n");
860c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto attach_fail12;
861c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
862c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
863c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = ddi_intr_add_handler(sc->sc_intr_htable[0], iwh_intr,
864c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    (caddr_t)sc, NULL);
865c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
866c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_attach(): "
867c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "ddi_intr_add_handle() failed\n");
868c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto attach_fail13;
869c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
870c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
871c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = ddi_intr_enable(sc->sc_intr_htable[0]);
872c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
873c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_attach(): "
874c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "ddi_intr_enable() failed\n");
875c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto attach_fail14;
876c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
877c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
878c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
879c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * Initialize pointer to device specific functions
880c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
881c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	wd.wd_secalloc = WIFI_SEC_NONE;
882c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	wd.wd_opmode = ic->ic_opmode;
883c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_macaddr);
884c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
885c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
886c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * create relation to GLD
887c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
888c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	macp = mac_alloc(MAC_VERSION);
889e2cf88acSQuaker Fang 	if (NULL == macp) {
890c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_attach(): "
891c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to do mac_alloc()\n");
892c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto attach_fail15;
893c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
894c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
895c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	macp->m_type_ident	= MAC_PLUGIN_IDENT_WIFI;
896c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	macp->m_driver		= sc;
897c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	macp->m_dip		= dip;
898c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	macp->m_src_addr	= ic->ic_macaddr;
899c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	macp->m_callbacks	= &iwh_m_callbacks;
900c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	macp->m_min_sdu		= 0;
901c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	macp->m_max_sdu		= IEEE80211_MTU;
902c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	macp->m_pdata		= &wd;
903c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	macp->m_pdata_size	= sizeof (wd);
904c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
905c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
906c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * Register the macp to mac
907c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
908c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = mac_register(macp, &ic->ic_mach);
909c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mac_free(macp);
910c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
911c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_attach(): "
912c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to do mac_register()\n");
913c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto attach_fail15;
914c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
915c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
916c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
917c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * Create minor node of type DDI_NT_NET_WIFI
918c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
919c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) snprintf(strbuf, sizeof (strbuf), DRV_NAME_SP"%d", instance);
920c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = ddi_create_minor_node(dip, strbuf, S_IFCHR,
921c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    instance + 1, DDI_NT_NET_WIFI, 0);
922e2cf88acSQuaker Fang 	if (err != DDI_SUCCESS) {
923c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_attach(): "
924c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to do ddi_create_minor_node()\n");
925e2cf88acSQuaker Fang 	}
926c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
927c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
928c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * Notify link is down now
929c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
930c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mac_link_update(ic->ic_mach, LINK_STATE_DOWN);
931c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
932c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
933c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * create the mf thread to handle the link status,
934c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * recovery fatal error, etc.
935c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
936c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_mf_thread_switch = 1;
937c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (NULL == sc->sc_mf_thread) {
938c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_mf_thread = thread_create((caddr_t)NULL, 0,
939c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    iwh_thread, sc, 0, &p0, TS_RUN, minclsyspri);
940c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
941c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
94289b2a9fbSfei feng - Sun Microsystems - Beijing China 	atomic_or_32(&sc->sc_flags, IWH_F_ATTACHED);
943c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
944c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
945c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
946c7ee0b5cSfei feng - Sun Microsystems - Beijing China attach_fail15:
947c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) ddi_intr_disable(sc->sc_intr_htable[0]);
948c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
949c7ee0b5cSfei feng - Sun Microsystems - Beijing China attach_fail14:
950c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) ddi_intr_remove_handler(sc->sc_intr_htable[0]);
951c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
952c7ee0b5cSfei feng - Sun Microsystems - Beijing China attach_fail13:
953c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) ddi_intr_remove_softint(sc->sc_soft_hdl);
954c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_soft_hdl = NULL;
955c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
956c7ee0b5cSfei feng - Sun Microsystems - Beijing China attach_fail12:
957c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ieee80211_detach(ic);
958c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
959c7ee0b5cSfei feng - Sun Microsystems - Beijing China attach_fail11:
960c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_free_fw_dma(sc);
961c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
962c7ee0b5cSfei feng - Sun Microsystems - Beijing China attach_fail10:
963c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_ring_free(sc);
964c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
965c7ee0b5cSfei feng - Sun Microsystems - Beijing China attach_fail9:
966c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_free_kw(sc);
967c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
968c7ee0b5cSfei feng - Sun Microsystems - Beijing China attach_fail8:
969c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_free_shared(sc);
970c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
971c7ee0b5cSfei feng - Sun Microsystems - Beijing China attach_fail7:
972c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_destroy_locks(sc);
973c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
974c7ee0b5cSfei feng - Sun Microsystems - Beijing China attach_fail6:
975c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) ddi_intr_free(sc->sc_intr_htable[0]);
976c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
977c7ee0b5cSfei feng - Sun Microsystems - Beijing China attach_fail5:
978c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	kmem_free(sc->sc_intr_htable, sizeof (ddi_intr_handle_t));
979c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
980c7ee0b5cSfei feng - Sun Microsystems - Beijing China attach_fail4:
981c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ddi_regs_map_free(&sc->sc_handle);
982c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
983c7ee0b5cSfei feng - Sun Microsystems - Beijing China attach_fail3:
984c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ddi_regs_map_free(&sc->sc_cfg_handle);
985c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
986c7ee0b5cSfei feng - Sun Microsystems - Beijing China attach_fail2:
987c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ddi_soft_state_free(iwh_soft_state_p, instance);
988c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
989c7ee0b5cSfei feng - Sun Microsystems - Beijing China attach_fail1:
990e2cf88acSQuaker Fang 	return (DDI_FAILURE);
991c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
992c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
993c7ee0b5cSfei feng - Sun Microsystems - Beijing China int
994c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
995c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
996c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_sc_t *sc;
997e2cf88acSQuaker Fang 	ieee80211com_t *ic;
998c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	int err;
999c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1000c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc = ddi_get_soft_state(iwh_soft_state_p, ddi_get_instance(dip));
1001c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ASSERT(sc != NULL);
1002e2cf88acSQuaker Fang 	ic = &sc->sc_ic;
1003c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1004c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	switch (cmd) {
1005c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case DDI_DETACH:
1006c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
1007e2cf88acSQuaker Fang 
1008c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case DDI_SUSPEND:
100989b2a9fbSfei feng - Sun Microsystems - Beijing China 		atomic_and_32(&sc->sc_flags, ~IWH_F_HW_ERR_RECOVER);
101089b2a9fbSfei feng - Sun Microsystems - Beijing China 		atomic_and_32(&sc->sc_flags, ~IWH_F_RATE_AUTO_CTL);
101189b2a9fbSfei feng - Sun Microsystems - Beijing China 
101289b2a9fbSfei feng - Sun Microsystems - Beijing China 		atomic_or_32(&sc->sc_flags, IWH_F_SUSPEND);
101389b2a9fbSfei feng - Sun Microsystems - Beijing China 
1014d40f4da4Spengcheng chen - Sun Microsystems - Beijing China 		if (sc->sc_flags & IWH_F_RUNNING) {
1015e2cf88acSQuaker Fang 			ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
1016c25d4638SQuaker Fang 			iwh_stop(sc);
1017e2cf88acSQuaker Fang 		}
1018e2cf88acSQuaker Fang 
1019e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_RESUME, "iwh_detach(): "
1020e2cf88acSQuaker Fang 		    "suspend\n"));
1021c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (DDI_SUCCESS);
1022e2cf88acSQuaker Fang 
1023c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	default:
1024c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
1025c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1026c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1027c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (!(sc->sc_flags & IWH_F_ATTACHED)) {
1028c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
1029c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1030c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1031c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
1032c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * Destroy the mf_thread
1033c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
1034c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_mf_thread_switch = 0;
1035e2cf88acSQuaker Fang 
1036e2cf88acSQuaker Fang 	mutex_enter(&sc->sc_mt_lock);
1037c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	while (sc->sc_mf_thread != NULL) {
1038c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (cv_wait_sig(&sc->sc_mt_cv, &sc->sc_mt_lock) == 0) {
1039c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			break;
1040c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
1041c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1042c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mutex_exit(&sc->sc_mt_lock);
1043c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1044e2cf88acSQuaker Fang 	err = mac_disable(sc->sc_ic.ic_mach);
1045e2cf88acSQuaker Fang 	if (err != DDI_SUCCESS) {
1046e2cf88acSQuaker Fang 		return (err);
1047e2cf88acSQuaker Fang 	}
1048e2cf88acSQuaker Fang 
1049c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
1050c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * stop chipset
1051c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
1052c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_stop(sc);
1053c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1054c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	DELAY(500000);
1055c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1056c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
1057c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * release buffer for calibration
1058c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
1059c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_release_calib_buffer(sc);
1060c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1061c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
1062c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * Unregiste from GLD
1063c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
1064c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) mac_unregister(sc->sc_ic.ic_mach);
1065c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1066c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mutex_enter(&sc->sc_glock);
1067c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_free_fw_dma(sc);
1068c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_ring_free(sc);
1069c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_free_kw(sc);
1070c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_free_shared(sc);
1071c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mutex_exit(&sc->sc_glock);
1072c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1073c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) ddi_intr_disable(sc->sc_intr_htable[0]);
1074c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) ddi_intr_remove_handler(sc->sc_intr_htable[0]);
1075c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) ddi_intr_free(sc->sc_intr_htable[0]);
1076c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	kmem_free(sc->sc_intr_htable, sizeof (ddi_intr_handle_t));
1077c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1078c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) ddi_intr_remove_softint(sc->sc_soft_hdl);
1079c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_soft_hdl = NULL;
1080c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1081c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
1082c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * detach from 80211 module
1083c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
1084c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ieee80211_detach(&sc->sc_ic);
1085c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1086c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_destroy_locks(sc);
1087c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1088c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ddi_regs_map_free(&sc->sc_handle);
1089c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ddi_regs_map_free(&sc->sc_cfg_handle);
1090c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ddi_remove_minor_node(dip, NULL);
1091c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ddi_soft_state_free(iwh_soft_state_p, ddi_get_instance(dip));
1092c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1093c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
1094c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
1095c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1096c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
1097c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * destroy all locks
1098c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
1099c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
1100c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_destroy_locks(iwh_sc_t *sc)
1101c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
1102c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	cv_destroy(&sc->sc_mt_cv);
1103c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	cv_destroy(&sc->sc_cmd_cv);
1104c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	cv_destroy(&sc->sc_put_seg_cv);
1105c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	cv_destroy(&sc->sc_ucode_cv);
1106c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mutex_destroy(&sc->sc_mt_lock);
1107c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mutex_destroy(&sc->sc_tx_lock);
1108c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mutex_destroy(&sc->sc_glock);
1109c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
1110c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1111c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
1112c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * Allocate an area of memory and a DMA handle for accessing it
1113c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
1114c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
1115c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_alloc_dma_mem(iwh_sc_t *sc, size_t memsize,
1116c7ee0b5cSfei feng - Sun Microsystems - Beijing China     ddi_dma_attr_t *dma_attr_p, ddi_device_acc_attr_t *acc_attr_p,
1117c7ee0b5cSfei feng - Sun Microsystems - Beijing China     uint_t dma_flags, iwh_dma_t *dma_p)
1118c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
1119c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	caddr_t vaddr;
1120e2cf88acSQuaker Fang 	int err = DDI_FAILURE;
1121c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1122c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
1123c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * Allocate handle
1124c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
1125c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = ddi_dma_alloc_handle(sc->sc_dip, dma_attr_p,
1126c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    DDI_DMA_SLEEP, NULL, &dma_p->dma_hdl);
1127c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
1128c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		dma_p->dma_hdl = NULL;
1129c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
1130c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1131c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1132c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
1133c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * Allocate memory
1134c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
1135c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, acc_attr_p,
1136c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    dma_flags & (DDI_DMA_CONSISTENT | DDI_DMA_STREAMING),
1137c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    DDI_DMA_SLEEP, NULL, &vaddr, &dma_p->alength, &dma_p->acc_hdl);
1138c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
1139c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ddi_dma_free_handle(&dma_p->dma_hdl);
1140c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		dma_p->dma_hdl = NULL;
1141c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		dma_p->acc_hdl = NULL;
1142c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
1143c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1144c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1145c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
1146c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * Bind the two together
1147c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
1148c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	dma_p->mem_va = vaddr;
1149c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL,
1150c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    vaddr, dma_p->alength, dma_flags, DDI_DMA_SLEEP, NULL,
1151c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    &dma_p->cookie, &dma_p->ncookies);
1152c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_DMA_MAPPED) {
1153c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ddi_dma_mem_free(&dma_p->acc_hdl);
1154c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ddi_dma_free_handle(&dma_p->dma_hdl);
1155c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		dma_p->acc_hdl = NULL;
1156c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		dma_p->dma_hdl = NULL;
1157c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
1158c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1159c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1160c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	dma_p->nslots = ~0U;
1161c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	dma_p->size = ~0U;
1162c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	dma_p->token = ~0U;
1163c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	dma_p->offset = 0;
1164c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
1165c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
1166c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1167c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
1168c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * Free one allocated area of DMAable memory
1169c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
1170c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
1171c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_free_dma_mem(iwh_dma_t *dma_p)
1172c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
1173c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (dma_p->dma_hdl != NULL) {
1174c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (dma_p->ncookies) {
1175c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			(void) ddi_dma_unbind_handle(dma_p->dma_hdl);
1176c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			dma_p->ncookies = 0;
1177c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
1178c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ddi_dma_free_handle(&dma_p->dma_hdl);
1179c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		dma_p->dma_hdl = NULL;
1180c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1181c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1182c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (dma_p->acc_hdl != NULL) {
1183c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ddi_dma_mem_free(&dma_p->acc_hdl);
1184c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		dma_p->acc_hdl = NULL;
1185c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1186c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
1187c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1188c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
1189c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * copy ucode into dma buffers
1190c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
1191c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
1192c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_alloc_fw_dma(iwh_sc_t *sc)
1193c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
1194e2cf88acSQuaker Fang 	int err = DDI_FAILURE;
1195c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_dma_t *dma_p;
1196c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	char *t;
1197c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1198c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
1199c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * firmware image layout:
1200c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * |HDR|<-TEXT->|<-DATA->|<-INIT_TEXT->|<-INIT_DATA->|<-BOOT->|
1201c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
1202c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1203c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
1204c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * copy text of runtime ucode
1205c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
1206c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	t = (char *)(sc->sc_hdr + 1);
1207c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_alloc_dma_mem(sc, LE_32(sc->sc_hdr->textsz),
1208c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    &fw_dma_attr, &iwh_dma_accattr,
1209c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1210c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    &sc->sc_dma_fw_text);
1211c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
1212c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_alloc_fw_dma(): "
1213c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to allocate text dma memory.\n");
1214c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto fail;
1215c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1216c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1217e2cf88acSQuaker Fang 	dma_p = &sc->sc_dma_fw_text;
1218e2cf88acSQuaker Fang 
1219e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_DMA, "iwh_alloc_fw_dma(): "
1220e2cf88acSQuaker Fang 	    "text[ncookies:%d addr:%lx size:%lx]\n",
1221e2cf88acSQuaker Fang 	    dma_p->ncookies, dma_p->cookie.dmac_address,
1222e2cf88acSQuaker Fang 	    dma_p->cookie.dmac_size));
1223e2cf88acSQuaker Fang 
122489b2a9fbSfei feng - Sun Microsystems - Beijing China 	bcopy(t, dma_p->mem_va, LE_32(sc->sc_hdr->textsz));
1225c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1226c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
1227c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * copy data and bak-data of runtime ucode
1228c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
1229c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	t += LE_32(sc->sc_hdr->textsz);
1230c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_alloc_dma_mem(sc, LE_32(sc->sc_hdr->datasz),
1231c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    &fw_dma_attr, &iwh_dma_accattr,
1232c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1233c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    &sc->sc_dma_fw_data);
1234c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
1235c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_alloc_fw_dma(): "
1236c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to allocate data dma memory\n");
1237c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto fail;
1238c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1239c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1240e2cf88acSQuaker Fang 	dma_p = &sc->sc_dma_fw_data;
1241e2cf88acSQuaker Fang 
1242e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_DMA, "iwh_alloc_fw_dma(): "
1243e2cf88acSQuaker Fang 	    "data[ncookies:%d addr:%lx size:%lx]\n",
1244e2cf88acSQuaker Fang 	    dma_p->ncookies, dma_p->cookie.dmac_address,
1245e2cf88acSQuaker Fang 	    dma_p->cookie.dmac_size));
1246e2cf88acSQuaker Fang 
124789b2a9fbSfei feng - Sun Microsystems - Beijing China 	bcopy(t, dma_p->mem_va, LE_32(sc->sc_hdr->datasz));
1248c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1249c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_alloc_dma_mem(sc, LE_32(sc->sc_hdr->datasz),
1250c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    &fw_dma_attr, &iwh_dma_accattr,
1251c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1252c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    &sc->sc_dma_fw_data_bak);
1253c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
1254c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_alloc_fw_dma(): "
1255c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to allocate data bakup dma memory\n");
1256c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto fail;
1257c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1258c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1259e2cf88acSQuaker Fang 	dma_p = &sc->sc_dma_fw_data_bak;
1260e2cf88acSQuaker Fang 
1261e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_DMA, "iwh_alloc_fw_dma(): "
1262e2cf88acSQuaker Fang 	    "data_bak[ncookies:%d addr:%lx "
1263e2cf88acSQuaker Fang 	    "size:%lx]\n",
1264e2cf88acSQuaker Fang 	    dma_p->ncookies, dma_p->cookie.dmac_address,
1265e2cf88acSQuaker Fang 	    dma_p->cookie.dmac_size));
1266e2cf88acSQuaker Fang 
126789b2a9fbSfei feng - Sun Microsystems - Beijing China 	bcopy(t, dma_p->mem_va, LE_32(sc->sc_hdr->datasz));
1268c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1269c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
1270c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * copy text of init ucode
1271c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
1272c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	t += LE_32(sc->sc_hdr->datasz);
1273c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_alloc_dma_mem(sc, LE_32(sc->sc_hdr->init_textsz),
1274c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    &fw_dma_attr, &iwh_dma_accattr,
1275c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1276c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    &sc->sc_dma_fw_init_text);
1277c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
1278c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_alloc_fw_dma(): "
1279c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to allocate init text dma memory\n");
1280c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto fail;
1281c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1282c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1283e2cf88acSQuaker Fang 	dma_p = &sc->sc_dma_fw_init_text;
1284e2cf88acSQuaker Fang 
1285e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_DMA, "iwh_alloc_fw_dma(): "
1286e2cf88acSQuaker Fang 	    "init_text[ncookies:%d addr:%lx "
1287e2cf88acSQuaker Fang 	    "size:%lx]\n",
1288e2cf88acSQuaker Fang 	    dma_p->ncookies, dma_p->cookie.dmac_address,
1289e2cf88acSQuaker Fang 	    dma_p->cookie.dmac_size));
1290e2cf88acSQuaker Fang 
129189b2a9fbSfei feng - Sun Microsystems - Beijing China 	bcopy(t, dma_p->mem_va, LE_32(sc->sc_hdr->init_textsz));
1292c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1293c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
1294c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * copy data of init ucode
1295c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
1296c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	t += LE_32(sc->sc_hdr->init_textsz);
1297c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_alloc_dma_mem(sc, LE_32(sc->sc_hdr->init_datasz),
1298c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    &fw_dma_attr, &iwh_dma_accattr,
1299c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1300c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    &sc->sc_dma_fw_init_data);
1301c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
1302c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_alloc_fw_dma(): "
1303c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to allocate init data dma memory\n");
1304c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto fail;
1305c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1306c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1307e2cf88acSQuaker Fang 	dma_p = &sc->sc_dma_fw_init_data;
1308e2cf88acSQuaker Fang 
1309e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_DMA, "iwh_alloc_fw_dma(): "
1310e2cf88acSQuaker Fang 	    "init_data[ncookies:%d addr:%lx "
1311e2cf88acSQuaker Fang 	    "size:%lx]\n",
1312e2cf88acSQuaker Fang 	    dma_p->ncookies, dma_p->cookie.dmac_address,
1313e2cf88acSQuaker Fang 	    dma_p->cookie.dmac_size));
1314e2cf88acSQuaker Fang 
131589b2a9fbSfei feng - Sun Microsystems - Beijing China 	bcopy(t, dma_p->mem_va, LE_32(sc->sc_hdr->init_datasz));
1316c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1317c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_boot = t + LE_32(sc->sc_hdr->init_datasz);
131889b2a9fbSfei feng - Sun Microsystems - Beijing China 
1319c7ee0b5cSfei feng - Sun Microsystems - Beijing China fail:
1320c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (err);
1321c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
1322c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1323c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
1324c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_free_fw_dma(iwh_sc_t *sc)
1325c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
1326c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_free_dma_mem(&sc->sc_dma_fw_text);
1327c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_free_dma_mem(&sc->sc_dma_fw_data);
1328c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_free_dma_mem(&sc->sc_dma_fw_data_bak);
1329c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_free_dma_mem(&sc->sc_dma_fw_init_text);
1330c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_free_dma_mem(&sc->sc_dma_fw_init_data);
1331c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
1332c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1333c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
1334c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * Allocate a shared buffer between host and NIC.
1335c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
1336c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
1337c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_alloc_shared(iwh_sc_t *sc)
1338c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
1339c7ee0b5cSfei feng - Sun Microsystems - Beijing China #ifdef	DEBUG
1340c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_dma_t *dma_p;
1341c7ee0b5cSfei feng - Sun Microsystems - Beijing China #endif
1342e2cf88acSQuaker Fang 	int err = DDI_FAILURE;
1343c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1344c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
1345c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * must be aligned on a 4K-page boundary
1346c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
1347c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_alloc_dma_mem(sc, sizeof (iwh_shared_t),
1348b510adaeSfei feng - Sun Microsystems - Beijing China 	    &sh_dma_attr, &iwh_dma_descattr,
1349c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1350c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    &sc->sc_dma_sh);
1351c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
1352c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto fail;
1353c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1354c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1355c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_shared = (iwh_shared_t *)sc->sc_dma_sh.mem_va;
1356c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1357c7ee0b5cSfei feng - Sun Microsystems - Beijing China #ifdef	DEBUG
1358c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	dma_p = &sc->sc_dma_sh;
1359c7ee0b5cSfei feng - Sun Microsystems - Beijing China #endif
1360e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_DMA, "iwh_alloc_shared(): "
1361e2cf88acSQuaker Fang 	    "sh[ncookies:%d addr:%lx size:%lx]\n",
1362c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    dma_p->ncookies, dma_p->cookie.dmac_address,
1363c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    dma_p->cookie.dmac_size));
1364c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1365c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (err);
136689b2a9fbSfei feng - Sun Microsystems - Beijing China 
1367c7ee0b5cSfei feng - Sun Microsystems - Beijing China fail:
1368c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_free_shared(sc);
1369c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (err);
1370c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
1371c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1372c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
1373c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_free_shared(iwh_sc_t *sc)
1374c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
1375c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_free_dma_mem(&sc->sc_dma_sh);
1376c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
1377c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1378c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
1379c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * Allocate a keep warm page.
1380c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
1381c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
1382c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_alloc_kw(iwh_sc_t *sc)
1383c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
1384c7ee0b5cSfei feng - Sun Microsystems - Beijing China #ifdef	DEBUG
1385c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_dma_t *dma_p;
1386c7ee0b5cSfei feng - Sun Microsystems - Beijing China #endif
1387e2cf88acSQuaker Fang 	int err = DDI_FAILURE;
1388c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1389c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
1390c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * must be aligned on a 4K-page boundary
1391c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
1392c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_alloc_dma_mem(sc, IWH_KW_SIZE,
1393b510adaeSfei feng - Sun Microsystems - Beijing China 	    &kw_dma_attr, &iwh_dma_descattr,
1394c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1395c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    &sc->sc_dma_kw);
1396c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
1397c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto fail;
1398c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1399c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1400c7ee0b5cSfei feng - Sun Microsystems - Beijing China #ifdef	DEBUG
1401c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	dma_p = &sc->sc_dma_kw;
1402c7ee0b5cSfei feng - Sun Microsystems - Beijing China #endif
1403e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_DMA, "iwh_alloc_kw(): "
1404e2cf88acSQuaker Fang 	    "kw[ncookies:%d addr:%lx size:%lx]\n",
1405c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    dma_p->ncookies, dma_p->cookie.dmac_address,
1406c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    dma_p->cookie.dmac_size));
1407c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1408c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (err);
140989b2a9fbSfei feng - Sun Microsystems - Beijing China 
1410c7ee0b5cSfei feng - Sun Microsystems - Beijing China fail:
1411c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_free_kw(sc);
1412c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (err);
1413c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
1414c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1415c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
1416c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_free_kw(iwh_sc_t *sc)
1417c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
1418c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_free_dma_mem(&sc->sc_dma_kw);
1419c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
1420c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1421c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
1422c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * initialize RX ring buffers
1423c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
1424c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
1425c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_alloc_rx_ring(iwh_sc_t *sc)
1426c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
1427c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_rx_ring_t *ring;
1428c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_rx_data_t *data;
1429c7ee0b5cSfei feng - Sun Microsystems - Beijing China #ifdef	DEBUG
1430c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_dma_t *dma_p;
1431c7ee0b5cSfei feng - Sun Microsystems - Beijing China #endif
1432e2cf88acSQuaker Fang 	int i, err = DDI_FAILURE;
1433c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1434c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ring = &sc->sc_rxq;
1435c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ring->cur = 0;
1436c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1437c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
1438c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * allocate RX description ring buffer
1439c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
1440c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_alloc_dma_mem(sc, RX_QUEUE_SIZE * sizeof (uint32_t),
1441b510adaeSfei feng - Sun Microsystems - Beijing China 	    &ring_desc_dma_attr, &iwh_dma_descattr,
1442c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1443c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    &ring->dma_desc);
1444c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
1445e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_DMA, "iwh_alloc_rx_ring(): "
1446e2cf88acSQuaker Fang 		    "dma alloc rx ring desc "
1447c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed\n"));
1448c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto fail;
1449c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1450c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1451c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ring->desc = (uint32_t *)ring->dma_desc.mem_va;
1452c7ee0b5cSfei feng - Sun Microsystems - Beijing China #ifdef	DEBUG
1453c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	dma_p = &ring->dma_desc;
1454c7ee0b5cSfei feng - Sun Microsystems - Beijing China #endif
1455e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_DMA, "iwh_alloc_rx_ring(): "
1456e2cf88acSQuaker Fang 	    "rx bd[ncookies:%d addr:%lx size:%lx]\n",
1457c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    dma_p->ncookies, dma_p->cookie.dmac_address,
1458c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    dma_p->cookie.dmac_size));
1459c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1460c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
1461c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * Allocate Rx frame buffers.
1462c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
1463c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < RX_QUEUE_SIZE; i++) {
1464c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		data = &ring->data[i];
1465c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		err = iwh_alloc_dma_mem(sc, sc->sc_dmabuf_sz,
1466c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    &rx_buffer_dma_attr, &iwh_dma_accattr,
1467c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    DDI_DMA_READ | DDI_DMA_STREAMING,
1468c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    &data->dma_data);
1469c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (err != DDI_SUCCESS) {
1470e2cf88acSQuaker Fang 			IWH_DBG((IWH_DEBUG_DMA, "iwh_alloc_rx_ring(): "
1471e2cf88acSQuaker Fang 			    "dma alloc rx ring "
1472c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			    "buf[%d] failed\n", i));
1473c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			goto fail;
1474c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
1475c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		/*
1476c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * the physical address bit [8-36] are used,
1477c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * instead of bit [0-31] in 3945.
1478c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 */
1479b510adaeSfei feng - Sun Microsystems - Beijing China 		ring->desc[i] = (uint32_t)
1480b510adaeSfei feng - Sun Microsystems - Beijing China 		    (data->dma_data.cookie.dmac_address >> 8);
1481c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1482c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1483c7ee0b5cSfei feng - Sun Microsystems - Beijing China #ifdef	DEBUG
1484c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	dma_p = &ring->data[0].dma_data;
1485c7ee0b5cSfei feng - Sun Microsystems - Beijing China #endif
1486e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_DMA, "iwh_alloc_rx_ring(): "
1487e2cf88acSQuaker Fang 	    "rx buffer[0][ncookies:%d addr:%lx "
1488c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    "size:%lx]\n",
1489c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    dma_p->ncookies, dma_p->cookie.dmac_address,
1490c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    dma_p->cookie.dmac_size));
1491c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1492c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV);
1493c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1494c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (err);
1495c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1496c7ee0b5cSfei feng - Sun Microsystems - Beijing China fail:
1497c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_free_rx_ring(sc);
1498c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (err);
1499c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
1500c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1501c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
1502c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * disable RX ring
1503c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
1504c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
1505c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_reset_rx_ring(iwh_sc_t *sc)
1506c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
1507c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	int n;
1508c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1509c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_mac_access_enter(sc);
1510c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
1511c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	for (n = 0; n < 2000; n++) {
1512c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (IWH_READ(sc, FH_MEM_RSSR_RX_STATUS_REG) & (1 << 24)) {
1513c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			break;
1514c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
1515c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		DELAY(1000);
1516c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1517c7ee0b5cSfei feng - Sun Microsystems - Beijing China #ifdef DEBUG
1518c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (2000 == n) {
1519e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_DMA, "iwh_reset_rx_ring(): "
1520e2cf88acSQuaker Fang 		    "timeout resetting Rx ring\n"));
1521c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1522c7ee0b5cSfei feng - Sun Microsystems - Beijing China #endif
1523c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_mac_access_exit(sc);
1524c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1525c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_rxq.cur = 0;
1526c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
1527c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1528c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
1529c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_free_rx_ring(iwh_sc_t *sc)
1530c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
1531c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	int i;
1532c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1533c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < RX_QUEUE_SIZE; i++) {
1534c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (sc->sc_rxq.data[i].dma_data.dma_hdl) {
1535c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			IWH_DMA_SYNC(sc->sc_rxq.data[i].dma_data,
1536c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			    DDI_DMA_SYNC_FORCPU);
1537c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
1538c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1539c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		iwh_free_dma_mem(&sc->sc_rxq.data[i].dma_data);
1540c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1541c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1542c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (sc->sc_rxq.dma_desc.dma_hdl) {
1543c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		IWH_DMA_SYNC(sc->sc_rxq.dma_desc, DDI_DMA_SYNC_FORDEV);
1544c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1545c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1546c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_free_dma_mem(&sc->sc_rxq.dma_desc);
1547c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
1548c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1549c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
1550c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * initialize TX ring buffers
1551c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
1552c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
1553c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_alloc_tx_ring(iwh_sc_t *sc, iwh_tx_ring_t *ring,
1554c7ee0b5cSfei feng - Sun Microsystems - Beijing China     int slots, int qid)
1555c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
1556c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_tx_data_t *data;
1557c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_tx_desc_t *desc_h;
1558c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint32_t paddr_desc_h;
1559c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_cmd_t *cmd_h;
1560c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint32_t paddr_cmd_h;
1561c7ee0b5cSfei feng - Sun Microsystems - Beijing China #ifdef	DEBUG
1562c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_dma_t *dma_p;
1563c7ee0b5cSfei feng - Sun Microsystems - Beijing China #endif
1564e2cf88acSQuaker Fang 	int i, err = DDI_FAILURE;
156589b2a9fbSfei feng - Sun Microsystems - Beijing China 
1566c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ring->qid = qid;
1567c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ring->count = TFD_QUEUE_SIZE_MAX;
1568c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ring->window = slots;
1569c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ring->queued = 0;
1570c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ring->cur = 0;
157189b2a9fbSfei feng - Sun Microsystems - Beijing China 	ring->desc_cur = 0;
1572c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1573c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
1574c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * allocate buffer for TX descriptor ring
1575c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
1576c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_alloc_dma_mem(sc,
1577c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    TFD_QUEUE_SIZE_MAX * sizeof (iwh_tx_desc_t),
1578b510adaeSfei feng - Sun Microsystems - Beijing China 	    &ring_desc_dma_attr, &iwh_dma_descattr,
1579c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1580c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    &ring->dma_desc);
1581c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
1582e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_DMA, "iwh_alloc_tx_ring(): "
1583e2cf88acSQuaker Fang 		    "dma alloc tx ring desc[%d] "
1584c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed\n", qid));
1585c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto fail;
1586c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1587c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1588c7ee0b5cSfei feng - Sun Microsystems - Beijing China #ifdef	DEBUG
1589c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	dma_p = &ring->dma_desc;
1590c7ee0b5cSfei feng - Sun Microsystems - Beijing China #endif
1591e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_DMA, "iwh_alloc_tx_ring(): "
1592e2cf88acSQuaker Fang 	    "tx bd[ncookies:%d addr:%lx size:%lx]\n",
1593c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    dma_p->ncookies, dma_p->cookie.dmac_address,
1594c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    dma_p->cookie.dmac_size));
1595c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1596c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	desc_h = (iwh_tx_desc_t *)ring->dma_desc.mem_va;
1597c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	paddr_desc_h = ring->dma_desc.cookie.dmac_address;
1598c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1599c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
1600c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * allocate buffer for ucode command
1601c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
1602c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_alloc_dma_mem(sc,
1603c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    TFD_QUEUE_SIZE_MAX * sizeof (iwh_cmd_t),
1604c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    &cmd_dma_attr, &iwh_dma_accattr,
1605c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1606c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    &ring->dma_cmd);
1607c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
1608e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_DMA, "iwh_alloc_tx_ring(): "
1609e2cf88acSQuaker Fang 		    "dma alloc tx ring cmd[%d]"
1610c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    " failed\n", qid));
1611c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto fail;
1612c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1613c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1614c7ee0b5cSfei feng - Sun Microsystems - Beijing China #ifdef	DEBUG
1615c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	dma_p = &ring->dma_cmd;
1616c7ee0b5cSfei feng - Sun Microsystems - Beijing China #endif
1617e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_DMA, "iwh_alloc_tx_ring(): "
1618e2cf88acSQuaker Fang 	    "tx cmd[ncookies:%d addr:%lx size:%lx]\n",
1619c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    dma_p->ncookies, dma_p->cookie.dmac_address,
1620c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    dma_p->cookie.dmac_size));
1621c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1622c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	cmd_h = (iwh_cmd_t *)ring->dma_cmd.mem_va;
1623c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	paddr_cmd_h = ring->dma_cmd.cookie.dmac_address;
1624c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1625c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
1626c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * Allocate Tx frame buffers.
1627c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
1628c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ring->data = kmem_zalloc(sizeof (iwh_tx_data_t) * TFD_QUEUE_SIZE_MAX,
1629c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    KM_NOSLEEP);
1630c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (NULL == ring->data) {
1631e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_DMA, "iwh_alloc_tx_ring(): "
1632e2cf88acSQuaker Fang 		    "could not allocate "
1633c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "tx data slots\n"));
1634c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto fail;
1635c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1636c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1637c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < TFD_QUEUE_SIZE_MAX; i++) {
1638c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		data = &ring->data[i];
1639c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		err = iwh_alloc_dma_mem(sc, sc->sc_dmabuf_sz,
1640c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    &tx_buffer_dma_attr, &iwh_dma_accattr,
1641c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    DDI_DMA_WRITE | DDI_DMA_STREAMING,
1642c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    &data->dma_data);
1643c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (err != DDI_SUCCESS) {
1644e2cf88acSQuaker Fang 			IWH_DBG((IWH_DEBUG_DMA, "iwh_alloc_tx_ring(): "
1645e2cf88acSQuaker Fang 			    "dma alloc tx "
1646c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			    "ring buf[%d] failed\n", i));
1647c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			goto fail;
1648c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
1649c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1650c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		data->desc = desc_h + i;
1651c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		data->paddr_desc = paddr_desc_h +
1652c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    _PTRDIFF(data->desc, desc_h);
1653e2cf88acSQuaker Fang 		data->cmd = cmd_h +  i;
1654c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		data->paddr_cmd = paddr_cmd_h +
1655c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    _PTRDIFF(data->cmd, cmd_h);
1656c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1657c7ee0b5cSfei feng - Sun Microsystems - Beijing China #ifdef	DEBUG
1658c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	dma_p = &ring->data[0].dma_data;
1659c7ee0b5cSfei feng - Sun Microsystems - Beijing China #endif
1660e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_DMA, "iwh_alloc_tx_ring(): "
1661e2cf88acSQuaker Fang 	    "tx buffer[0][ncookies:%d addr:%lx "
1662c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    "size:%lx]\n",
1663c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    dma_p->ncookies, dma_p->cookie.dmac_address,
1664c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    dma_p->cookie.dmac_size));
1665c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1666c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (err);
1667c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1668c7ee0b5cSfei feng - Sun Microsystems - Beijing China fail:
1669c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_free_tx_ring(ring);
1670c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1671c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (err);
1672c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
1673c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1674c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
1675c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * disable TX ring
1676c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
1677c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
1678c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_reset_tx_ring(iwh_sc_t *sc, iwh_tx_ring_t *ring)
1679c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
1680c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_tx_data_t *data;
1681c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	int i, n;
1682c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1683c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_mac_access_enter(sc);
1684c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1685c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, IWH_FH_TCSR_CHNL_TX_CONFIG_REG(ring->qid), 0);
1686c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	for (n = 0; n < 200; n++) {
1687c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (IWH_READ(sc, IWH_FH_TSSR_TX_STATUS_REG) &
1688c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    IWH_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ring->qid)) {
1689c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			break;
1690c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
1691c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		DELAY(10);
1692c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1693e2cf88acSQuaker Fang 
1694e2cf88acSQuaker Fang #ifdef	DEBUG
1695d5bd65e4Sfei feng - Sun Microsystems - Beijing China 	if (200 == n) {
1696e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_DMA, "iwh_reset_tx_ring(): "
1697e2cf88acSQuaker Fang 		    "timeout reset tx ring %d\n",
1698c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    ring->qid));
1699c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1700e2cf88acSQuaker Fang #endif
1701e2cf88acSQuaker Fang 
1702c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_mac_access_exit(sc);
1703c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
170489b2a9fbSfei feng - Sun Microsystems - Beijing China 	/*
170589b2a9fbSfei feng - Sun Microsystems - Beijing China 	 * by pass, if it's quiesce
170689b2a9fbSfei feng - Sun Microsystems - Beijing China 	 */
1707faceed93Sfei feng - Sun Microsystems - Beijing China 	if (!(sc->sc_flags & IWH_F_QUIESCED)) {
1708c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		for (i = 0; i < ring->count; i++) {
1709c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			data = &ring->data[i];
1710c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			IWH_DMA_SYNC(data->dma_data, DDI_DMA_SYNC_FORDEV);
1711c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
1712faceed93Sfei feng - Sun Microsystems - Beijing China 	}
1713c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1714c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ring->queued = 0;
1715c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ring->cur = 0;
171689b2a9fbSfei feng - Sun Microsystems - Beijing China 	ring->desc_cur = 0;
1717c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
1718c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1719c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
1720c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_free_tx_ring(iwh_tx_ring_t *ring)
1721c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
1722c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	int i;
1723c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1724c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (ring->dma_desc.dma_hdl != NULL) {
1725c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		IWH_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV);
1726c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1727c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_free_dma_mem(&ring->dma_desc);
1728c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1729c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (ring->dma_cmd.dma_hdl != NULL) {
1730c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		IWH_DMA_SYNC(ring->dma_cmd, DDI_DMA_SYNC_FORDEV);
1731c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1732c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_free_dma_mem(&ring->dma_cmd);
1733c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1734c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (ring->data != NULL) {
1735c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		for (i = 0; i < ring->count; i++) {
1736c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			if (ring->data[i].dma_data.dma_hdl) {
1737c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				IWH_DMA_SYNC(ring->data[i].dma_data,
1738c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				    DDI_DMA_SYNC_FORDEV);
1739c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			}
1740c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			iwh_free_dma_mem(&ring->data[i].dma_data);
1741c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
1742c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		kmem_free(ring->data, ring->count * sizeof (iwh_tx_data_t));
1743c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1744c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
1745c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1746c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
1747c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * initialize TX and RX ring
1748c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
1749c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
1750c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_ring_init(iwh_sc_t *sc)
1751c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
1752e2cf88acSQuaker Fang 	int i, err = DDI_FAILURE;
1753c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1754c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < IWH_NUM_QUEUES; i++) {
1755c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (IWH_CMD_QUEUE_NUM == i) {
1756c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			continue;
1757c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
1758c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1759c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		err = iwh_alloc_tx_ring(sc, &sc->sc_txq[i], TFD_TX_CMD_SLOTS,
1760c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    i);
1761c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (err != DDI_SUCCESS) {
1762c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			goto fail;
1763c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
1764c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1765c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1766c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
1767c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * initialize command queue
1768c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
1769c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_alloc_tx_ring(sc, &sc->sc_txq[IWH_CMD_QUEUE_NUM],
1770c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    TFD_CMD_SLOTS, IWH_CMD_QUEUE_NUM);
1771c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
1772c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto fail;
1773c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1774c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1775c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_alloc_rx_ring(sc);
1776c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
1777c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto fail;
1778c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1779c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1780c7ee0b5cSfei feng - Sun Microsystems - Beijing China fail:
1781c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (err);
1782c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
1783c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1784c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
1785c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_ring_free(iwh_sc_t *sc)
1786c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
1787c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	int i = IWH_NUM_QUEUES;
1788c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1789c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_free_rx_ring(sc);
1790c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	while (--i >= 0) {
1791c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		iwh_free_tx_ring(&sc->sc_txq[i]);
1792c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1793c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
1794c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1795c7ee0b5cSfei feng - Sun Microsystems - Beijing China /* ARGSUSED */
1796c7ee0b5cSfei feng - Sun Microsystems - Beijing China static ieee80211_node_t *
1797c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_node_alloc(ieee80211com_t *ic)
1798c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
1799c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_amrr_t *amrr;
1800c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1801c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	amrr = kmem_zalloc(sizeof (iwh_amrr_t), KM_SLEEP);
1802e2cf88acSQuaker Fang 	if (NULL == amrr) {
1803e2cf88acSQuaker Fang 		cmn_err(CE_WARN, "iwh_node_alloc(): "
1804e2cf88acSQuaker Fang 		    "failed to allocate memory for amrr structure\n");
1805e2cf88acSQuaker Fang 		return (NULL);
1806c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1807c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1808e2cf88acSQuaker Fang 	iwh_amrr_init(amrr);
1809e2cf88acSQuaker Fang 
1810c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (&amrr->in);
1811c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
1812c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1813c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
1814c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_node_free(ieee80211_node_t *in)
1815c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
1816e2cf88acSQuaker Fang 	ieee80211com_t *ic;
1817c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1818e2cf88acSQuaker Fang 	if ((NULL == in) ||
1819e2cf88acSQuaker Fang 	    (NULL == in->in_ic)) {
1820e2cf88acSQuaker Fang 		cmn_err(CE_WARN, "iwh_node_free() "
1821e2cf88acSQuaker Fang 		    "Got a NULL point from Net80211 module\n");
1822e2cf88acSQuaker Fang 		return;
1823e2cf88acSQuaker Fang 	}
1824e2cf88acSQuaker Fang 	ic = in->in_ic;
1825e2cf88acSQuaker Fang 
1826e2cf88acSQuaker Fang 	if (ic->ic_node_cleanup != NULL) {
1827c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ic->ic_node_cleanup(in);
1828e2cf88acSQuaker Fang 	}
1829e2cf88acSQuaker Fang 
1830c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (in->in_wpa_ie != NULL) {
1831c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ieee80211_free(in->in_wpa_ie);
1832c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
1833c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1834e2cf88acSQuaker Fang 	if (in->in_wme_ie != NULL) {
1835e2cf88acSQuaker Fang 		ieee80211_free(in->in_wme_ie);
1836e2cf88acSQuaker Fang 	}
1837e2cf88acSQuaker Fang 
1838e2cf88acSQuaker Fang 	if (in->in_htcap_ie != NULL) {
1839e2cf88acSQuaker Fang 		ieee80211_free(in->in_htcap_ie);
1840e2cf88acSQuaker Fang 	}
1841e2cf88acSQuaker Fang 
1842c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	kmem_free(in, sizeof (iwh_amrr_t));
1843c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
1844c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1845c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
1846c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * change station's state. this function will be invoked by 80211 module
1847c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * when need to change staton's state.
1848c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
1849c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
1850c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg)
1851c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
1852e2cf88acSQuaker Fang 	iwh_sc_t *sc;
1853e2cf88acSQuaker Fang 	ieee80211_node_t *in;
1854e2cf88acSQuaker Fang 	enum ieee80211_state ostate;
1855e2cf88acSQuaker Fang 	iwh_add_sta_t node;
1856e2cf88acSQuaker Fang 	iwh_amrr_t *amrr;
1857e2cf88acSQuaker Fang 	uint8_t r;
1858e2cf88acSQuaker Fang 	int i, err = IWH_FAIL;
1859e2cf88acSQuaker Fang 
1860e2cf88acSQuaker Fang 	if (NULL == ic) {
1861e2cf88acSQuaker Fang 		return (err);
1862e2cf88acSQuaker Fang 	}
1863e2cf88acSQuaker Fang 	sc = (iwh_sc_t *)ic;
1864e2cf88acSQuaker Fang 	in = ic->ic_bss;
1865e2cf88acSQuaker Fang 	ostate = ic->ic_state;
1866c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1867c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mutex_enter(&sc->sc_glock);
1868c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1869c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	switch (nstate) {
1870c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case IEEE80211_S_SCAN:
1871d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		switch (ostate) {
1872d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		case IEEE80211_S_INIT:
187389b2a9fbSfei feng - Sun Microsystems - Beijing China 			atomic_or_32(&sc->sc_flags, IWH_F_SCANNING);
1874c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			iwh_set_led(sc, 2, 10, 2);
1875c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1876d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			/*
1877d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			 * clear association to receive beacons from
1878d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			 * all BSS'es
1879d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			 */
1880d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			sc->sc_config.assoc_id = 0;
1881d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			sc->sc_config.filter_flags &=
1882d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			    ~LE_32(RXON_FILTER_ASSOC_MSK);
1883d5bd65e4Sfei feng - Sun Microsystems - Beijing China 
1884e2cf88acSQuaker Fang 			IWH_DBG((IWH_DEBUG_80211, "iwh_newstate(): "
1885e2cf88acSQuaker Fang 			    "config chan %d "
1886b510adaeSfei feng - Sun Microsystems - Beijing China 			    "flags %x filter_flags %x\n",
1887b510adaeSfei feng - Sun Microsystems - Beijing China 			    LE_16(sc->sc_config.chan),
1888b510adaeSfei feng - Sun Microsystems - Beijing China 			    LE_32(sc->sc_config.flags),
1889b510adaeSfei feng - Sun Microsystems - Beijing China 			    LE_32(sc->sc_config.filter_flags)));
1890d5bd65e4Sfei feng - Sun Microsystems - Beijing China 
1891d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			err = iwh_cmd(sc, REPLY_RXON, &sc->sc_config,
1892d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			    sizeof (iwh_rxon_cmd_t), 1);
1893d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			if (err != IWH_SUCCESS) {
1894e2cf88acSQuaker Fang 				cmn_err(CE_WARN, "iwh_newstate(): "
1895d5bd65e4Sfei feng - Sun Microsystems - Beijing China 				    "could not clear association\n");
189689b2a9fbSfei feng - Sun Microsystems - Beijing China 				atomic_and_32(&sc->sc_flags, ~IWH_F_SCANNING);
1897c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				mutex_exit(&sc->sc_glock);
1898c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				return (err);
1899c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			}
1900d5bd65e4Sfei feng - Sun Microsystems - Beijing China 
190189b2a9fbSfei feng - Sun Microsystems - Beijing China 			/*
190289b2a9fbSfei feng - Sun Microsystems - Beijing China 			 * add broadcast node to send probe request
190389b2a9fbSfei feng - Sun Microsystems - Beijing China 			 */
1904d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			(void) memset(&node, 0, sizeof (node));
1905d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			(void) memset(&node.sta.addr, 0xff, IEEE80211_ADDR_LEN);
1906d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			node.sta.sta_id = IWH_BROADCAST_ID;
1907d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			err = iwh_cmd(sc, REPLY_ADD_STA, &node,
1908d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			    sizeof (node), 1);
1909d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			if (err != IWH_SUCCESS) {
1910e2cf88acSQuaker Fang 				cmn_err(CE_WARN, "iwh_newstate(): "
1911e2cf88acSQuaker Fang 				    "could not add broadcast node\n");
191289b2a9fbSfei feng - Sun Microsystems - Beijing China 				atomic_and_32(&sc->sc_flags, ~IWH_F_SCANNING);
1913d5bd65e4Sfei feng - Sun Microsystems - Beijing China 				mutex_exit(&sc->sc_glock);
1914d5bd65e4Sfei feng - Sun Microsystems - Beijing China 				return (err);
1915d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			}
1916d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			break;
1917d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		case IEEE80211_S_SCAN:
1918d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			mutex_exit(&sc->sc_glock);
1919d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			/* step to next channel before actual FW scan */
1920d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			err = sc->sc_newstate(ic, nstate, arg);
1921d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			mutex_enter(&sc->sc_glock);
1922d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			if ((err != 0) || ((err = iwh_scan(sc)) != 0)) {
1923e2cf88acSQuaker Fang 				cmn_err(CE_WARN, "iwh_newstate(): "
1924d5bd65e4Sfei feng - Sun Microsystems - Beijing China 				    "could not initiate scan\n");
192589b2a9fbSfei feng - Sun Microsystems - Beijing China 				atomic_and_32(&sc->sc_flags, ~IWH_F_SCANNING);
1926d5bd65e4Sfei feng - Sun Microsystems - Beijing China 				ieee80211_cancel_scan(ic);
1927d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			}
1928d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			mutex_exit(&sc->sc_glock);
1929d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			return (err);
1930d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		default:
1931d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			break;
1932c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
1933c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_clk = 0;
1934d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		break;
1935c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1936c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case IEEE80211_S_AUTH:
1937d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		if (ostate == IEEE80211_S_SCAN) {
193889b2a9fbSfei feng - Sun Microsystems - Beijing China 			atomic_and_32(&sc->sc_flags, ~IWH_F_SCANNING);
1939d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		}
1940d5bd65e4Sfei feng - Sun Microsystems - Beijing China 
1941c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		/*
1942c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * reset state to handle reassociations correctly
1943c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 */
1944c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_config.assoc_id = 0;
1945c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_config.filter_flags &= ~LE_32(RXON_FILTER_ASSOC_MSK);
1946c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1947c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		/*
1948c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * before sending authentication and association request frame,
1949c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * we need do something in the hardware, such as setting the
1950c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * channel same to the target AP...
1951c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 */
1952c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if ((err = iwh_hw_set_before_auth(sc)) != 0) {
1953e2cf88acSQuaker Fang 			IWH_DBG((IWH_DEBUG_80211, "iwh_newstate(): "
1954c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			    "could not send authentication request\n"));
1955c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			mutex_exit(&sc->sc_glock);
1956c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			return (err);
1957c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
1958c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
1959c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1960c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case IEEE80211_S_RUN:
1961d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		if (ostate == IEEE80211_S_SCAN) {
196289b2a9fbSfei feng - Sun Microsystems - Beijing China 			atomic_and_32(&sc->sc_flags, ~IWH_F_SCANNING);
1963d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		}
1964d5bd65e4Sfei feng - Sun Microsystems - Beijing China 
1965c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (IEEE80211_M_MONITOR == ic->ic_opmode) {
196689b2a9fbSfei feng - Sun Microsystems - Beijing China 			/*
196789b2a9fbSfei feng - Sun Microsystems - Beijing China 			 * let LED blink when monitoring
196889b2a9fbSfei feng - Sun Microsystems - Beijing China 			 */
1969c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			iwh_set_led(sc, 2, 10, 10);
1970c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			break;
1971c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
1972c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1973e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_80211, "iwh_newstate(): "
1974e2cf88acSQuaker Fang 		    "associated.\n"));
1975c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
19766f12def4Spengcheng chen - Sun Microsystems - Beijing China 		err = iwh_run_state_config(sc);
1977c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (err != IWH_SUCCESS) {
19786f12def4Spengcheng chen - Sun Microsystems - Beijing China 			cmn_err(CE_WARN, "iwh_newstate(): "
19796f12def4Spengcheng chen - Sun Microsystems - Beijing China 			    "failed to set up association\n");
1980c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			mutex_exit(&sc->sc_glock);
1981c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			return (err);
1982c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
1983c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
1984c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		/*
1985c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * start automatic rate control
1986c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 */
1987e2cf88acSQuaker Fang 		if ((in->in_flags & IEEE80211_NODE_HT) &&
1988e2cf88acSQuaker Fang 		    (sc->sc_ht_conf.ht_support) &&
1989e2cf88acSQuaker Fang 		    (in->in_htrates.rs_nrates > 0) &&
1990e2cf88acSQuaker Fang 		    (in->in_htrates.rs_nrates <= IEEE80211_HTRATE_MAXSIZE)) {
1991e2cf88acSQuaker Fang 			amrr = (iwh_amrr_t *)in;
1992e2cf88acSQuaker Fang 
1993e2cf88acSQuaker Fang 			for (i = in->in_htrates.rs_nrates - 1; i > 0; i--) {
1994e2cf88acSQuaker Fang 
1995e2cf88acSQuaker Fang 				r = in->in_htrates.rs_rates[i] &
1996e2cf88acSQuaker Fang 				    IEEE80211_RATE_VAL;
1997e2cf88acSQuaker Fang 				if ((r != 0) && (r <= 0xd) &&
1998e2cf88acSQuaker Fang 				    (sc->sc_ht_conf.tx_support_mcs[r/8] &
1999e2cf88acSQuaker Fang 				    (1 << (r%8)))) {
2000e2cf88acSQuaker Fang 					amrr->ht_mcs_idx = r;
200189b2a9fbSfei feng - Sun Microsystems - Beijing China 					atomic_or_32(&sc->sc_flags,
200289b2a9fbSfei feng - Sun Microsystems - Beijing China 					    IWH_F_RATE_AUTO_CTL);
2003e2cf88acSQuaker Fang 					break;
2004e2cf88acSQuaker Fang 				}
2005e2cf88acSQuaker Fang 			}
2006e2cf88acSQuaker Fang 		} else {
2007c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			if (IEEE80211_FIXED_RATE_NONE == ic->ic_fixed_rate) {
200889b2a9fbSfei feng - Sun Microsystems - Beijing China 				atomic_or_32(&sc->sc_flags,
200989b2a9fbSfei feng - Sun Microsystems - Beijing China 				    IWH_F_RATE_AUTO_CTL);
2010e2cf88acSQuaker Fang 
2011c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				/*
2012c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				 * set rate to some reasonable initial value
2013c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				 */
2014c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				i = in->in_rates.ir_nrates - 1;
2015c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				while (i > 0 && IEEE80211_RATE(i) > 72) {
2016c7ee0b5cSfei feng - Sun Microsystems - Beijing China 					i--;
2017c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				}
2018c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				in->in_txrate = i;
2019e2cf88acSQuaker Fang 
2020c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			} else {
202189b2a9fbSfei feng - Sun Microsystems - Beijing China 				atomic_and_32(&sc->sc_flags,
202289b2a9fbSfei feng - Sun Microsystems - Beijing China 				    ~IWH_F_RATE_AUTO_CTL);
2023c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			}
2024e2cf88acSQuaker Fang 		}
2025c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2026c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		/*
2027c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * set LED on after associated
2028c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 */
2029c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		iwh_set_led(sc, 2, 0, 1);
2030c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
2031c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2032c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case IEEE80211_S_INIT:
2033d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		if (ostate == IEEE80211_S_SCAN) {
203489b2a9fbSfei feng - Sun Microsystems - Beijing China 			atomic_and_32(&sc->sc_flags, ~IWH_F_SCANNING);
2035d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		}
2036c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		/*
2037c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * set LED off after init
2038c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 */
2039c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		iwh_set_led(sc, 2, 1, 0);
2040c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
2041c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2042c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case IEEE80211_S_ASSOC:
2043d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		if (ostate == IEEE80211_S_SCAN) {
204489b2a9fbSfei feng - Sun Microsystems - Beijing China 			atomic_and_32(&sc->sc_flags, ~IWH_F_SCANNING);
2045d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		}
2046c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
2047c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2048c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2049c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mutex_exit(&sc->sc_glock);
2050c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2051c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (sc->sc_newstate(ic, nstate, arg));
2052c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
2053c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2054c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
2055c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * exclusive access to mac begin.
2056c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
2057c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
2058c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_mac_access_enter(iwh_sc_t *sc)
2059c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
2060c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint32_t tmp;
2061c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	int n;
2062c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2063c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tmp = IWH_READ(sc, CSR_GP_CNTRL);
2064c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_GP_CNTRL,
2065c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    tmp | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
2066c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
206789b2a9fbSfei feng - Sun Microsystems - Beijing China 	/*
206889b2a9fbSfei feng - Sun Microsystems - Beijing China 	 * wait until we succeed
206989b2a9fbSfei feng - Sun Microsystems - Beijing China 	 */
2070c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	for (n = 0; n < 1000; n++) {
2071c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if ((IWH_READ(sc, CSR_GP_CNTRL) &
2072c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
2073c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP)) ==
2074c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN) {
2075c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			break;
2076c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
2077c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		DELAY(10);
2078c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2079c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2080c7ee0b5cSfei feng - Sun Microsystems - Beijing China #ifdef	DEBUG
2081c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (1000 == n) {
2082e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_PIO, "iwh_mac_access_enter(): "
2083e2cf88acSQuaker Fang 		    "could not lock memory\n"));
2084c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2085c7ee0b5cSfei feng - Sun Microsystems - Beijing China #endif
2086c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
2087c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2088c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
2089c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * exclusive access to mac end.
2090c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
2091c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
2092c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_mac_access_exit(iwh_sc_t *sc)
2093c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
2094c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint32_t tmp = IWH_READ(sc, CSR_GP_CNTRL);
2095c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_GP_CNTRL,
2096c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    tmp & ~CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
2097c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
2098c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2099c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
2100c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * this function defined here for future use.
2101c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * static uint32_t
2102c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * iwh_mem_read(iwh_sc_t *sc, uint32_t addr)
2103c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * {
2104c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * 	IWH_WRITE(sc, HBUS_TARG_MEM_RADDR, addr);
2105c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * 	return (IWH_READ(sc, HBUS_TARG_MEM_RDAT));
2106c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * }
2107c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
2108c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2109c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
2110c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * write mac memory
2111c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
2112c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
2113c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_mem_write(iwh_sc_t *sc, uint32_t addr, uint32_t data)
2114c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
2115c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, HBUS_TARG_MEM_WADDR, addr);
2116c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, HBUS_TARG_MEM_WDAT, data);
2117c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
2118c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2119c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
2120c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * read mac register
2121c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
2122c7ee0b5cSfei feng - Sun Microsystems - Beijing China static uint32_t
2123c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_reg_read(iwh_sc_t *sc, uint32_t addr)
2124c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
2125c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, HBUS_TARG_PRPH_RADDR, addr | (3 << 24));
2126c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (IWH_READ(sc, HBUS_TARG_PRPH_RDAT));
2127c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
2128c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2129c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
2130c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * write mac register
2131c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
2132c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
2133c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_reg_write(iwh_sc_t *sc, uint32_t addr, uint32_t data)
2134c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
2135c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, HBUS_TARG_PRPH_WADDR, addr | (3 << 24));
2136c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, HBUS_TARG_PRPH_WDAT, data);
2137c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
2138c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2139c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2140c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
2141c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * steps of loading ucode:
2142c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * load init ucode=>init alive=>calibrate=>
2143c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * receive calibration result=>reinitialize NIC=>
2144c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * load runtime ucode=>runtime alive=>
2145c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * send calibration result=>running.
2146c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
2147c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
2148c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_load_init_firmware(iwh_sc_t *sc)
2149c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
2150e2cf88acSQuaker Fang 	int err = IWH_FAIL;
2151c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	clock_t	clk;
2152c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
215389b2a9fbSfei feng - Sun Microsystems - Beijing China 	atomic_and_32(&sc->sc_flags, ~IWH_F_PUT_SEG);
2154c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2155c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
2156c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * load init_text section of uCode to hardware
2157c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
2158c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_put_seg_fw(sc, sc->sc_dma_fw_init_text.cookie.dmac_address,
2159c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    RTC_INST_LOWER_BOUND, sc->sc_dma_fw_init_text.cookie.dmac_size);
2160c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != IWH_SUCCESS) {
2161c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_load_init_firmware(): "
2162c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to write init uCode.\n");
2163c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (err);
2164c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2165c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2166c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	clk = ddi_get_lbolt() + drv_usectohz(1000000);
2167c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
216889b2a9fbSfei feng - Sun Microsystems - Beijing China 	/*
216989b2a9fbSfei feng - Sun Microsystems - Beijing China 	 * wait loading init_text until completed or timeout
217089b2a9fbSfei feng - Sun Microsystems - Beijing China 	 */
2171c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	while (!(sc->sc_flags & IWH_F_PUT_SEG)) {
2172c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (cv_timedwait(&sc->sc_put_seg_cv, &sc->sc_glock, clk) < 0) {
2173c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			break;
2174c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
2175c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2176c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2177c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (!(sc->sc_flags & IWH_F_PUT_SEG)) {
2178c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_load_init_firmware(): "
2179c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "timeout waiting for init uCode load.\n");
2180c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (IWH_FAIL);
2181c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2182c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
218389b2a9fbSfei feng - Sun Microsystems - Beijing China 	atomic_and_32(&sc->sc_flags, ~IWH_F_PUT_SEG);
2184c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2185c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
2186c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * load init_data section of uCode to hardware
2187c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
2188c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_put_seg_fw(sc, sc->sc_dma_fw_init_data.cookie.dmac_address,
2189c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    RTC_DATA_LOWER_BOUND, sc->sc_dma_fw_init_data.cookie.dmac_size);
2190c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != IWH_SUCCESS) {
2191c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_load_init_firmware(): "
2192c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to write init_data uCode.\n");
2193c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (err);
2194c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2195c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2196c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	clk = ddi_get_lbolt() + drv_usectohz(1000000);
2197c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2198c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
2199c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * wait loading init_data until completed or timeout
2200c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
2201c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	while (!(sc->sc_flags & IWH_F_PUT_SEG)) {
2202c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (cv_timedwait(&sc->sc_put_seg_cv, &sc->sc_glock, clk) < 0) {
2203c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			break;
2204c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
2205c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2206c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2207c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (!(sc->sc_flags & IWH_F_PUT_SEG)) {
2208c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_load_init_firmware(): "
2209c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "timeout waiting for init_data uCode load.\n");
2210c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (IWH_FAIL);
2211c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2212c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
221389b2a9fbSfei feng - Sun Microsystems - Beijing China 	atomic_and_32(&sc->sc_flags, ~IWH_F_PUT_SEG);
2214c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2215c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (err);
2216c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
2217c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2218c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
2219c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_load_run_firmware(iwh_sc_t *sc)
2220c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
2221e2cf88acSQuaker Fang 	int err = IWH_FAIL;
2222c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	clock_t	clk;
2223c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
222489b2a9fbSfei feng - Sun Microsystems - Beijing China 	atomic_and_32(&sc->sc_flags, ~IWH_F_PUT_SEG);
2225c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2226c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
2227c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * load init_text section of uCode to hardware
2228c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
2229c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_put_seg_fw(sc, sc->sc_dma_fw_text.cookie.dmac_address,
2230c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    RTC_INST_LOWER_BOUND, sc->sc_dma_fw_text.cookie.dmac_size);
2231c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != IWH_SUCCESS) {
2232c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_load_run_firmware(): "
2233c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to write run uCode.\n");
2234c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (err);
2235c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2236c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2237c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	clk = ddi_get_lbolt() + drv_usectohz(1000000);
2238c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
223989b2a9fbSfei feng - Sun Microsystems - Beijing China 	/*
224089b2a9fbSfei feng - Sun Microsystems - Beijing China 	 * wait loading run_text until completed or timeout
224189b2a9fbSfei feng - Sun Microsystems - Beijing China 	 */
2242c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	while (!(sc->sc_flags & IWH_F_PUT_SEG)) {
2243c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (cv_timedwait(&sc->sc_put_seg_cv, &sc->sc_glock, clk) < 0) {
2244c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			break;
2245c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
2246c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2247c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2248c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (!(sc->sc_flags & IWH_F_PUT_SEG)) {
2249c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_load_run_firmware(): "
2250c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "timeout waiting for run uCode load.\n");
2251c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (IWH_FAIL);
2252c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2253c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
225489b2a9fbSfei feng - Sun Microsystems - Beijing China 	atomic_and_32(&sc->sc_flags, ~IWH_F_PUT_SEG);
2255c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2256c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
2257c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * load run_data section of uCode to hardware
2258c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
2259c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_put_seg_fw(sc, sc->sc_dma_fw_data_bak.cookie.dmac_address,
2260c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    RTC_DATA_LOWER_BOUND, sc->sc_dma_fw_data.cookie.dmac_size);
2261c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != IWH_SUCCESS) {
2262c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_load_run_firmware(): "
2263c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to write run_data uCode.\n");
2264c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (err);
2265c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2266c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2267c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	clk = ddi_get_lbolt() + drv_usectohz(1000000);
2268c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2269c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
2270c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * wait loading run_data until completed or timeout
2271c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
2272c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	while (!(sc->sc_flags & IWH_F_PUT_SEG)) {
2273c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (cv_timedwait(&sc->sc_put_seg_cv, &sc->sc_glock, clk) < 0) {
2274c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			break;
2275c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
2276c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2277c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2278c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (!(sc->sc_flags & IWH_F_PUT_SEG)) {
2279c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_load_run_firmware(): "
2280c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "timeout waiting for run_data uCode load.\n");
2281c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (IWH_FAIL);
2282c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2283c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
228489b2a9fbSfei feng - Sun Microsystems - Beijing China 	atomic_and_32(&sc->sc_flags, ~IWH_F_PUT_SEG);
2285c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2286c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (err);
2287c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
2288c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2289c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
2290c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * this function will be invoked to receive phy information
2291c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * when a frame is received.
2292c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
2293c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
2294c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_rx_phy_intr(iwh_sc_t *sc, iwh_rx_desc_t *desc)
2295c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
2296c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2297c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_rx_phy_res.flag = 1;
2298c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
229989b2a9fbSfei feng - Sun Microsystems - Beijing China 	bcopy((uint8_t *)(desc + 1), sc->sc_rx_phy_res.buf,
2300c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    sizeof (iwh_rx_phy_res_t));
2301c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
2302c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2303c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
2304c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * this function will be invoked to receive body of frame when
2305c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * a frame is received.
2306c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
2307c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
2308c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_rx_mpdu_intr(iwh_sc_t *sc, iwh_rx_desc_t *desc)
2309c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
2310c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ieee80211com_t *ic = &sc->sc_ic;
2311c7ee0b5cSfei feng - Sun Microsystems - Beijing China #ifdef	DEBUG
2312c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_rx_ring_t *ring = &sc->sc_rxq;
2313c7ee0b5cSfei feng - Sun Microsystems - Beijing China #endif
2314b510adaeSfei feng - Sun Microsystems - Beijing China 	struct ieee80211_frame *wh;
2315b510adaeSfei feng - Sun Microsystems - Beijing China 	struct iwh_rx_non_cfg_phy *phyinfo;
2316b510adaeSfei feng - Sun Microsystems - Beijing China 	struct iwh_rx_mpdu_body_size *mpdu_size;
2317b510adaeSfei feng - Sun Microsystems - Beijing China 	mblk_t *mp;
2318b510adaeSfei feng - Sun Microsystems - Beijing China 	int16_t t;
2319b510adaeSfei feng - Sun Microsystems - Beijing China 	uint16_t len, rssi, agc;
2320b510adaeSfei feng - Sun Microsystems - Beijing China 	uint32_t temp, crc, *tail;
2321b510adaeSfei feng - Sun Microsystems - Beijing China 	uint32_t arssi, brssi, crssi, mrssi;
2322c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_rx_phy_res_t *stat;
2323c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ieee80211_node_t *in;
2324c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2325c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
2326c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * assuming not 11n here. cope with 11n in phase-II
2327c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
2328c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mpdu_size = (struct iwh_rx_mpdu_body_size *)(desc + 1);
2329c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	stat = (iwh_rx_phy_res_t *)sc->sc_rx_phy_res.buf;
2330c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (stat->cfg_phy_cnt > 20) {
2331c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return;
2332c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2333c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2334c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	phyinfo = (struct iwh_rx_non_cfg_phy *)stat->non_cfg_phy;
2335b510adaeSfei feng - Sun Microsystems - Beijing China 	temp = LE_32(phyinfo->non_cfg_phy[IWH_RX_RES_AGC_IDX]);
2336c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	agc = (temp & IWH_OFDM_AGC_MSK) >> IWH_OFDM_AGC_BIT_POS;
2337c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2338b510adaeSfei feng - Sun Microsystems - Beijing China 	temp = LE_32(phyinfo->non_cfg_phy[IWH_RX_RES_RSSI_AB_IDX]);
2339c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	arssi = (temp & IWH_OFDM_RSSI_A_MSK) >> IWH_OFDM_RSSI_A_BIT_POS;
2340c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	brssi = (temp & IWH_OFDM_RSSI_B_MSK) >> IWH_OFDM_RSSI_B_BIT_POS;
2341c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2342b510adaeSfei feng - Sun Microsystems - Beijing China 	temp = LE_32(phyinfo->non_cfg_phy[IWH_RX_RES_RSSI_C_IDX]);
2343c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	crssi = (temp & IWH_OFDM_RSSI_C_MSK) >> IWH_OFDM_RSSI_C_BIT_POS;
2344c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2345c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mrssi = MAX(arssi, brssi);
2346c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mrssi = MAX(mrssi, crssi);
2347c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2348c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	t = mrssi - agc - IWH_RSSI_OFFSET;
2349c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
2350c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * convert dBm to percentage
2351c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
2352c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	rssi = (100 * 75 * 75 - (-20 - t) * (15 * 75 + 62 * (-20 - t)))
2353c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    / (75 * 75);
2354c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (rssi > 100) {
2355c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		rssi = 100;
2356c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2357c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (rssi < 1) {
2358c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		rssi = 1;
2359c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2360c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2361c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
2362c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * size of frame, not include FCS
2363c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
2364b510adaeSfei feng - Sun Microsystems - Beijing China 	len = LE_16(mpdu_size->byte_count);
2365c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tail = (uint32_t *)((uint8_t *)(desc + 1) +
2366c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    sizeof (struct iwh_rx_mpdu_body_size) + len);
2367b510adaeSfei feng - Sun Microsystems - Beijing China 	bcopy(tail, &crc, 4);
2368c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2369e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_RX, "iwh_rx_mpdu_intr(): "
2370e2cf88acSQuaker Fang 	    "rx intr: idx=%d phy_len=%x len=%d "
2371c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    "rate=%x chan=%d tstamp=%x non_cfg_phy_count=%x "
2372c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    "cfg_phy_count=%x tail=%x", ring->cur, sizeof (*stat),
2373c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    len, stat->rate.r.s.rate, stat->channel,
2374c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    LE_32(stat->timestampl), stat->non_cfg_phy_cnt,
2375b510adaeSfei feng - Sun Microsystems - Beijing China 	    stat->cfg_phy_cnt, LE_32(crc)));
2376c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2377c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if ((len < 16) || (len > sc->sc_dmabuf_sz)) {
2378e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_RX, "iwh_rx_mpdu_intr(): "
2379e2cf88acSQuaker Fang 		    "rx frame oversize\n"));
2380c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return;
2381c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2382c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2383c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
2384c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * discard Rx frames with bad CRC
2385c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
2386b510adaeSfei feng - Sun Microsystems - Beijing China 	if ((LE_32(crc) &
2387c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    (RX_RES_STATUS_NO_CRC32_ERROR | RX_RES_STATUS_NO_RXE_OVERFLOW)) !=
2388c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    (RX_RES_STATUS_NO_CRC32_ERROR | RX_RES_STATUS_NO_RXE_OVERFLOW)) {
2389e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_RX, "iwh_rx_mpdu_intr(): "
2390e2cf88acSQuaker Fang 		    "rx crc error tail: %x\n",
2391b510adaeSfei feng - Sun Microsystems - Beijing China 		    LE_32(crc)));
2392c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_rx_err++;
2393c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return;
2394c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2395c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2396c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	wh = (struct ieee80211_frame *)
2397c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    ((uint8_t *)(desc + 1)+ sizeof (struct iwh_rx_mpdu_body_size));
2398c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2399c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (IEEE80211_FC0_SUBTYPE_ASSOC_RESP == *(uint8_t *)wh) {
2400c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_assoc_id = *((uint16_t *)(wh + 1) + 2);
2401e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_RX, "iwh_rx_mpdu_intr(): "
2402e2cf88acSQuaker Fang 		    "rx : association id = %x\n",
2403c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    sc->sc_assoc_id));
2404c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2405c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2406c7ee0b5cSfei feng - Sun Microsystems - Beijing China #ifdef DEBUG
2407c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (iwh_dbg_flags & IWH_DEBUG_RX) {
2408c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ieee80211_dump_pkt((uint8_t *)wh, len, 0, 0);
2409c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2410c7ee0b5cSfei feng - Sun Microsystems - Beijing China #endif
2411c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2412c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	in = ieee80211_find_rxnode(ic, wh);
2413c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mp = allocb(len, BPRI_MED);
2414c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (mp) {
241589b2a9fbSfei feng - Sun Microsystems - Beijing China 		bcopy(wh, mp->b_wptr, len);
2416c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		mp->b_wptr += len;
2417c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2418c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		/*
2419c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * send the frame to the 802.11 layer
2420c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 */
2421c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		(void) ieee80211_input(ic, mp, in, rssi, 0);
2422c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	} else {
2423c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_rx_nobuf++;
2424e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_RX, "iwh_rx_mpdu_intr(): "
2425e2cf88acSQuaker Fang 		    "alloc rx buf failed\n"));
2426c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2427c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2428c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
2429c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * release node reference
2430c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
2431c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ieee80211_free_node(in);
2432c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
2433c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2434c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
2435c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * process correlative affairs after a frame is sent.
2436c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
2437c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
2438c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_tx_intr(iwh_sc_t *sc, iwh_rx_desc_t *desc)
2439c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
2440c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ieee80211com_t *ic = &sc->sc_ic;
2441c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_tx_ring_t *ring = &sc->sc_txq[desc->hdr.qid & 0x3];
2442c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_tx_stat_t *stat = (iwh_tx_stat_t *)(desc + 1);
2443e2cf88acSQuaker Fang 	iwh_amrr_t *amrr;
2444e2cf88acSQuaker Fang 
2445e2cf88acSQuaker Fang 	if (NULL == ic->ic_bss) {
2446e2cf88acSQuaker Fang 		return;
2447e2cf88acSQuaker Fang 	}
2448e2cf88acSQuaker Fang 
2449e2cf88acSQuaker Fang 	amrr = (iwh_amrr_t *)ic->ic_bss;
2450c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2451c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	amrr->txcnt++;
2452e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_RATECTL, "iwh_tx_intr(): "
2453e2cf88acSQuaker Fang 	    "tx: %d cnt\n", amrr->txcnt));
2454c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2455c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (stat->ntries > 0) {
2456c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		amrr->retrycnt++;
2457c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_tx_retries++;
2458e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_TX, "iwh_tx_intr(): "
2459e2cf88acSQuaker Fang 		    "tx: %d retries\n",
2460c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    sc->sc_tx_retries));
2461c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2462c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2463e2cf88acSQuaker Fang 	mutex_enter(&sc->sc_mt_lock);
2464c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_tx_timer = 0;
2465e2cf88acSQuaker Fang 	mutex_exit(&sc->sc_mt_lock);
2466c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2467c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mutex_enter(&sc->sc_tx_lock);
2468c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2469c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ring->queued--;
2470c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (ring->queued < 0) {
2471c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ring->queued = 0;
2472c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2473c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2474e2cf88acSQuaker Fang 	if ((sc->sc_need_reschedule) && (ring->queued <= (ring->count >> 3))) {
2475c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_need_reschedule = 0;
2476c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		mutex_exit(&sc->sc_tx_lock);
2477c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		mac_tx_update(ic->ic_mach);
2478c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		mutex_enter(&sc->sc_tx_lock);
2479c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2480c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2481c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mutex_exit(&sc->sc_tx_lock);
2482c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
2483c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2484c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
2485c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * inform a given command has been executed
2486c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
2487c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
2488c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_cmd_intr(iwh_sc_t *sc, iwh_rx_desc_t *desc)
2489c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
2490c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if ((desc->hdr.qid & 7) != 4) {
2491c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return;
2492c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2493c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2494e2cf88acSQuaker Fang 	if (sc->sc_cmd_accum > 0) {
2495e2cf88acSQuaker Fang 		sc->sc_cmd_accum--;
2496e2cf88acSQuaker Fang 		return;
2497e2cf88acSQuaker Fang 	}
2498e2cf88acSQuaker Fang 
2499c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mutex_enter(&sc->sc_glock);
2500c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2501e2cf88acSQuaker Fang 	sc->sc_cmd_flag = SC_CMD_FLG_DONE;
2502e2cf88acSQuaker Fang 
2503c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	cv_signal(&sc->sc_cmd_cv);
2504c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2505c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mutex_exit(&sc->sc_glock);
2506c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2507e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_CMD, "iwh_cmd_intr(): "
2508c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    "qid=%x idx=%d flags=%x type=0x%x\n",
2509c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    desc->hdr.qid, desc->hdr.idx, desc->hdr.flags,
2510c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    desc->hdr.type));
2511c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
2512c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2513c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
2514c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * this function will be invoked when alive notification occur.
2515c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
2516c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
2517c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_ucode_alive(iwh_sc_t *sc, iwh_rx_desc_t *desc)
2518c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
2519c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint32_t rv;
2520c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	struct iwh_calib_cfg_cmd cmd;
2521c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	struct iwh_alive_resp *ar =
2522c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    (struct iwh_alive_resp *)(desc + 1);
2523c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	struct iwh_calib_results *res_p = &sc->sc_calib_results;
2524c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2525c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
2526c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * the microcontroller is ready
2527c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
2528e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_FW, "iwh_ucode_alive(): "
2529c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    "microcode alive notification minor: %x major: %x type: "
2530c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    "%x subtype: %x\n",
2531c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    ar->ucode_minor, ar->ucode_minor, ar->ver_type, ar->ver_subtype));
2532c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2533c7ee0b5cSfei feng - Sun Microsystems - Beijing China #ifdef	DEBUG
2534c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (LE_32(ar->is_valid) != UCODE_VALID_OK) {
2535e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_FW, "iwh_ucode_alive(): "
2536c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "microcontroller initialization failed\n"));
2537c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2538c7ee0b5cSfei feng - Sun Microsystems - Beijing China #endif
2539c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2540c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
2541c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * determine if init alive or runtime alive.
2542c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
2543c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (INITIALIZE_SUBTYPE == ar->ver_subtype) {
2544e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_FW, "iwh_ucode_alive(): "
2545c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "initialization alive received.\n"));
2546c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
254789b2a9fbSfei feng - Sun Microsystems - Beijing China 		bcopy(ar, &sc->sc_card_alive_init,
2548c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    sizeof (struct iwh_init_alive_resp));
2549c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2550c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		/*
2551c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * necessary configuration to NIC
2552c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 */
2553c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		mutex_enter(&sc->sc_glock);
2554c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2555c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		rv = iwh_alive_common(sc);
2556c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (rv != IWH_SUCCESS) {
2557c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			cmn_err(CE_WARN, "iwh_ucode_alive(): "
2558c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			    "common alive process failed in init alive.\n");
2559c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			mutex_exit(&sc->sc_glock);
2560c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			return;
2561c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
2562c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2563c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		(void) memset(&cmd, 0, sizeof (cmd));
2564c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2565c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmd.ucd_calib_cfg.once.is_enable = IWH_CALIB_INIT_CFG_ALL;
2566c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmd.ucd_calib_cfg.once.start = IWH_CALIB_INIT_CFG_ALL;
2567c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmd.ucd_calib_cfg.once.send_res = IWH_CALIB_INIT_CFG_ALL;
2568c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmd.ucd_calib_cfg.flags = IWH_CALIB_INIT_CFG_ALL;
2569c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2570c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		/*
2571c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * require ucode execute calibration
2572c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 */
2573c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		rv = iwh_cmd(sc, CALIBRATION_CFG_CMD, &cmd, sizeof (cmd), 1);
2574c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (rv != IWH_SUCCESS) {
2575c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			cmn_err(CE_WARN, "iwh_ucode_alive(): "
2576c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			    "failed to send calibration configure command.\n");
2577c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			mutex_exit(&sc->sc_glock);
2578c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			return;
2579c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
2580c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2581c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		mutex_exit(&sc->sc_glock);
2582c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2583c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	} else {	/* runtime alive */
2584c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2585e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_FW, "iwh_ucode_alive(): "
2586e2cf88acSQuaker Fang 		    "runtime alive received.\n"));
2587c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
258889b2a9fbSfei feng - Sun Microsystems - Beijing China 		bcopy(ar, &sc->sc_card_alive_run,
2589c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    sizeof (struct iwh_alive_resp));
2590c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2591c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		mutex_enter(&sc->sc_glock);
2592c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2593c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		/*
2594c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * necessary configuration to NIC
2595c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 */
2596c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		rv = iwh_alive_common(sc);
2597c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (rv != IWH_SUCCESS) {
2598c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			cmn_err(CE_WARN, "iwh_ucode_alive(): "
2599c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			    "common alive process failed in run alive.\n");
2600c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			mutex_exit(&sc->sc_glock);
2601c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			return;
2602c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
2603c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2604c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		/*
2605c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * send the result of local oscilator calibration to uCode.
2606c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 */
2607c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (res_p->lo_res != NULL) {
2608c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			rv = iwh_cmd(sc, REPLY_PHY_CALIBRATION_CMD,
2609c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			    res_p->lo_res, res_p->lo_res_len, 1);
2610c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			if (rv != IWH_SUCCESS) {
2611c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				cmn_err(CE_WARN, "iwh_ucode_alive(): "
2612c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				    "failed to send local"
2613c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				    "oscilator calibration command.\n");
2614c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				mutex_exit(&sc->sc_glock);
2615c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				return;
2616c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			}
2617c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2618c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			DELAY(1000);
2619c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
2620c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2621c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		/*
2622c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * send the result of TX IQ calibration to uCode.
2623c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 */
2624c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (res_p->tx_iq_res != NULL) {
2625c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			rv = iwh_cmd(sc, REPLY_PHY_CALIBRATION_CMD,
2626c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			    res_p->tx_iq_res, res_p->tx_iq_res_len, 1);
2627c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			if (rv != IWH_SUCCESS) {
2628c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				cmn_err(CE_WARN, "iwh_ucode_alive(): "
2629c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				    "failed to send TX IQ"
2630c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				    "calibration command.\n");
2631c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				mutex_exit(&sc->sc_glock);
2632c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				return;
2633c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			}
2634c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2635c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			DELAY(1000);
2636c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
2637c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2638c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		/*
2639c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * sned the result of TX IQ perd calibration to uCode.
2640c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 */
2641c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (res_p->tx_iq_perd_res != NULL) {
2642c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			rv = iwh_cmd(sc, REPLY_PHY_CALIBRATION_CMD,
2643c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			    res_p->tx_iq_perd_res,
2644c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			    res_p->tx_iq_perd_res_len, 1);
2645c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			if (rv != IWH_SUCCESS) {
2646c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				cmn_err(CE_WARN, "iwh_ucode_alive(): "
2647c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				    "failed to send TX IQ perd"
2648c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				    "calibration command.\n");
2649c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				mutex_exit(&sc->sc_glock);
2650c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				return;
2651c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			}
2652c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2653c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			DELAY(1000);
2654c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
2655c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
265689b2a9fbSfei feng - Sun Microsystems - Beijing China 		/*
265789b2a9fbSfei feng - Sun Microsystems - Beijing China 		 * send the result of DC calibration to uCode.
265889b2a9fbSfei feng - Sun Microsystems - Beijing China 		 */
265989b2a9fbSfei feng - Sun Microsystems - Beijing China 		if (res_p->dc_res != NULL) {
266089b2a9fbSfei feng - Sun Microsystems - Beijing China 			rv = iwh_cmd(sc, REPLY_PHY_CALIBRATION_CMD,
266189b2a9fbSfei feng - Sun Microsystems - Beijing China 			    res_p->dc_res,
266289b2a9fbSfei feng - Sun Microsystems - Beijing China 			    res_p->dc_res_len, 1);
266389b2a9fbSfei feng - Sun Microsystems - Beijing China 			if (rv != IWH_SUCCESS) {
266489b2a9fbSfei feng - Sun Microsystems - Beijing China 				cmn_err(CE_WARN, "iwh_ucode_alive(): "
266589b2a9fbSfei feng - Sun Microsystems - Beijing China 				    "failed to send DC"
266689b2a9fbSfei feng - Sun Microsystems - Beijing China 				    "calibration command.\n");
266789b2a9fbSfei feng - Sun Microsystems - Beijing China 				mutex_exit(&sc->sc_glock);
266889b2a9fbSfei feng - Sun Microsystems - Beijing China 				return;
266989b2a9fbSfei feng - Sun Microsystems - Beijing China 			}
267089b2a9fbSfei feng - Sun Microsystems - Beijing China 
267189b2a9fbSfei feng - Sun Microsystems - Beijing China 			DELAY(1000);
267289b2a9fbSfei feng - Sun Microsystems - Beijing China 		}
267389b2a9fbSfei feng - Sun Microsystems - Beijing China 
267489b2a9fbSfei feng - Sun Microsystems - Beijing China 		/*
267589b2a9fbSfei feng - Sun Microsystems - Beijing China 		 * send the result of BASE BAND calibration to uCode.
267689b2a9fbSfei feng - Sun Microsystems - Beijing China 		 */
267789b2a9fbSfei feng - Sun Microsystems - Beijing China 		if (res_p->base_band_res != NULL) {
267889b2a9fbSfei feng - Sun Microsystems - Beijing China 			rv = iwh_cmd(sc, REPLY_PHY_CALIBRATION_CMD,
267989b2a9fbSfei feng - Sun Microsystems - Beijing China 			    res_p->base_band_res,
268089b2a9fbSfei feng - Sun Microsystems - Beijing China 			    res_p->base_band_res_len, 1);
268189b2a9fbSfei feng - Sun Microsystems - Beijing China 			if (rv != IWH_SUCCESS) {
268289b2a9fbSfei feng - Sun Microsystems - Beijing China 				cmn_err(CE_WARN, "iwh_ucode_alive(): "
268389b2a9fbSfei feng - Sun Microsystems - Beijing China 				    "failed to send BASE BAND"
268489b2a9fbSfei feng - Sun Microsystems - Beijing China 				    "calibration command.\n");
268589b2a9fbSfei feng - Sun Microsystems - Beijing China 				mutex_exit(&sc->sc_glock);
268689b2a9fbSfei feng - Sun Microsystems - Beijing China 				return;
268789b2a9fbSfei feng - Sun Microsystems - Beijing China 			}
268889b2a9fbSfei feng - Sun Microsystems - Beijing China 
268989b2a9fbSfei feng - Sun Microsystems - Beijing China 			DELAY(1000);
269089b2a9fbSfei feng - Sun Microsystems - Beijing China 		}
269189b2a9fbSfei feng - Sun Microsystems - Beijing China 
269289b2a9fbSfei feng - Sun Microsystems - Beijing China 		atomic_or_32(&sc->sc_flags, IWH_F_FW_INIT);
2693c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cv_signal(&sc->sc_ucode_cv);
2694e2cf88acSQuaker Fang 
2695e2cf88acSQuaker Fang 		mutex_exit(&sc->sc_glock);
2696c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2697c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2698c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
2699c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2700c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
2701c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * deal with receiving frames, command response
2702c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * and all notifications from ucode.
2703c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
2704e2cf88acSQuaker Fang /* ARGSUSED */
2705c7ee0b5cSfei feng - Sun Microsystems - Beijing China static uint_t
2706c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_rx_softintr(caddr_t arg, caddr_t unused)
2707c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
2708e2cf88acSQuaker Fang 	iwh_sc_t *sc;
2709e2cf88acSQuaker Fang 	ieee80211com_t *ic;
2710c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_rx_desc_t *desc;
2711c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_rx_data_t *data;
2712c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint32_t index;
2713c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2714e2cf88acSQuaker Fang 	if (NULL == arg) {
2715c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (DDI_INTR_UNCLAIMED);
2716c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2717e2cf88acSQuaker Fang 	sc = (iwh_sc_t *)arg;
2718e2cf88acSQuaker Fang 	ic = &sc->sc_ic;
2719c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2720c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
2721c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * firmware has moved the index of the rx queue, driver get it,
2722c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * and deal with it.
2723c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
2724b510adaeSfei feng - Sun Microsystems - Beijing China 	index = (sc->sc_shared->val0) & 0xfff;
2725c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2726c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	while (sc->sc_rxq.cur != index) {
2727c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		data = &sc->sc_rxq.data[sc->sc_rxq.cur];
2728c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		desc = (iwh_rx_desc_t *)data->dma_data.mem_va;
2729c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2730e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_INTR, "iwh_rx_softintr(): "
2731e2cf88acSQuaker Fang 		    "rx notification index = %d"
2732c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    " cur = %d qid=%x idx=%d flags=%x type=%x len=%d\n",
2733c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    index, sc->sc_rxq.cur, desc->hdr.qid, desc->hdr.idx,
2734c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    desc->hdr.flags, desc->hdr.type, LE_32(desc->len)));
2735c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2736c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		/*
2737c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * a command other than a tx need to be replied
2738c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 */
2739c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (!(desc->hdr.qid & 0x80) &&
2740e2cf88acSQuaker Fang 		    (desc->hdr.type != REPLY_SCAN_CMD) &&
2741e2cf88acSQuaker Fang 		    (desc->hdr.type != REPLY_TX)) {
2742c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			iwh_cmd_intr(sc, desc);
2743c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
2744c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2745c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		switch (desc->hdr.type) {
2746c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		case REPLY_RX_PHY_CMD:
2747c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			iwh_rx_phy_intr(sc, desc);
2748c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			break;
2749c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2750c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		case REPLY_RX_MPDU_CMD:
2751c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			iwh_rx_mpdu_intr(sc, desc);
2752c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			break;
2753c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2754c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		case REPLY_TX:
2755c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			iwh_tx_intr(sc, desc);
2756c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			break;
2757c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2758c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		case REPLY_ALIVE:
2759c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			iwh_ucode_alive(sc, desc);
2760c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			break;
2761c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2762c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		case CARD_STATE_NOTIFICATION:
2763c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		{
2764c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			uint32_t *status = (uint32_t *)(desc + 1);
2765c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2766e2cf88acSQuaker Fang 			IWH_DBG((IWH_DEBUG_RADIO, "iwh_rx_softintr(): "
2767e2cf88acSQuaker Fang 			    "state changed to %x\n",
2768c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			    LE_32(*status)));
2769c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2770c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			if (LE_32(*status) & 1) {
2771c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				/*
2772c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				 * the radio button has to be pushed(OFF). It
2773c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				 * is considered as a hw error, the
2774c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				 * iwh_thread() tries to recover it after the
2775c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				 * button is pushed again(ON)
2776c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				 */
2777b510adaeSfei feng - Sun Microsystems - Beijing China 				cmn_err(CE_NOTE, "iwh_rx_softintr(): "
2778c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				    "radio transmitter is off\n");
2779c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				sc->sc_ostate = sc->sc_ic.ic_state;
2780c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				ieee80211_new_state(&sc->sc_ic,
2781c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				    IEEE80211_S_INIT, -1);
278289b2a9fbSfei feng - Sun Microsystems - Beijing China 				atomic_or_32(&sc->sc_flags,
278389b2a9fbSfei feng - Sun Microsystems - Beijing China 				    (IWH_F_HW_ERR_RECOVER | IWH_F_RADIO_OFF));
2784c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			}
2785e2cf88acSQuaker Fang 
2786c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			break;
2787c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
2788c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2789c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		case SCAN_START_NOTIFICATION:
2790c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		{
2791c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			iwh_start_scan_t *scan =
2792c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			    (iwh_start_scan_t *)(desc + 1);
2793c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2794e2cf88acSQuaker Fang 			IWH_DBG((IWH_DEBUG_SCAN, "iwh_rx_softintr(): "
2795c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			    "scanning channel %d status %x\n",
2796c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			    scan->chan, LE_32(scan->status)));
2797c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2798c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			ic->ic_curchan = &ic->ic_sup_channels[scan->chan];
2799c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			break;
2800c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
2801c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2802c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		case SCAN_COMPLETE_NOTIFICATION:
2803d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		{
2804e2cf88acSQuaker Fang #ifdef	DEBUG
2805d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			iwh_stop_scan_t *scan =
2806d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			    (iwh_stop_scan_t *)(desc + 1);
2807d5bd65e4Sfei feng - Sun Microsystems - Beijing China 
2808e2cf88acSQuaker Fang 			IWH_DBG((IWH_DEBUG_SCAN, "iwh_rx_softintr(): "
2809d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			    "completed channel %d (burst of %d) status %02x\n",
2810d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			    scan->chan, scan->nchan, scan->status));
2811e2cf88acSQuaker Fang #endif
2812d5bd65e4Sfei feng - Sun Microsystems - Beijing China 
2813d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			sc->sc_scan_pending++;
2814c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			break;
2815d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		}
2816c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2817c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		case STATISTICS_NOTIFICATION:
2818c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		{
2819c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			/*
2820c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			 * handle statistics notification
2821c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			 */
2822c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			break;
2823c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
2824c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2825c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		case CALIBRATION_RES_NOTIFICATION:
2826c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			iwh_save_calib_result(sc, desc);
2827c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			break;
2828c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2829c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		case CALIBRATION_COMPLETE_NOTIFICATION:
2830e2cf88acSQuaker Fang 			mutex_enter(&sc->sc_glock);
283189b2a9fbSfei feng - Sun Microsystems - Beijing China 			atomic_or_32(&sc->sc_flags, IWH_F_FW_INIT);
2832c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			cv_signal(&sc->sc_ucode_cv);
2833e2cf88acSQuaker Fang 			mutex_exit(&sc->sc_glock);
2834c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			break;
2835d00ac735Sfei feng - Sun Microsystems - Beijing China 
2836d00ac735Sfei feng - Sun Microsystems - Beijing China 		case MISSED_BEACONS_NOTIFICATION:
2837216e0daaSQuaker Fang 			/* handle beacon miss by software mechanism */
2838d00ac735Sfei feng - Sun Microsystems - Beijing China 			break;
2839d00ac735Sfei feng - Sun Microsystems - Beijing China 		}
2840c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2841c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_rxq.cur = (sc->sc_rxq.cur + 1) % RX_QUEUE_SIZE;
2842c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2843c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2844c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
2845c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * driver dealt with what received in rx queue and tell the information
2846c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * to the firmware.
2847c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
2848c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	index = (0 == index) ? RX_QUEUE_SIZE - 1 : index - 1;
2849c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, index & (~7));
2850c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2851c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
2852c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * re-enable interrupts
2853c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
2854c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_INT_MASK, CSR_INI_SET_MASK);
2855c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2856c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (DDI_INTR_CLAIMED);
2857c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
2858c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2859c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
2860c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * the handle of interrupt
2861c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
2862e2cf88acSQuaker Fang /* ARGSUSED */
2863c7ee0b5cSfei feng - Sun Microsystems - Beijing China static uint_t
2864c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_intr(caddr_t arg, caddr_t unused)
2865c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
2866e2cf88acSQuaker Fang 	iwh_sc_t *sc;
2867c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint32_t r, rfh;
2868c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2869e2cf88acSQuaker Fang 	if (NULL == arg) {
2870e2cf88acSQuaker Fang 		return (DDI_INTR_UNCLAIMED);
2871e2cf88acSQuaker Fang 	}
2872e2cf88acSQuaker Fang 	sc = (iwh_sc_t *)arg;
2873e2cf88acSQuaker Fang 
2874e2cf88acSQuaker Fang 	r = IWH_READ(sc, CSR_INT);
2875e2cf88acSQuaker Fang 	if (0 == r || 0xffffffff == r) {
2876e2cf88acSQuaker Fang 		return (DDI_INTR_UNCLAIMED);
2877e2cf88acSQuaker Fang 	}
2878e2cf88acSQuaker Fang 
2879e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_INTR, "iwh_intr(): "
2880e2cf88acSQuaker Fang 	    "interrupt reg %x\n", r));
2881c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2882c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	rfh = IWH_READ(sc, CSR_FH_INT_STATUS);
2883c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2884e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_INTR, "iwh_intr(): "
2885e2cf88acSQuaker Fang 	    "FH interrupt reg %x\n", rfh));
2886c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2887c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
2888c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * disable interrupts
2889c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
2890c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_INT_MASK, 0);
2891c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2892c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
2893c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * ack interrupts
2894c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
2895c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_INT, r);
2896c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_FH_INT_STATUS, rfh);
2897c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2898c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (r & (BIT_INT_SWERROR | BIT_INT_ERR)) {
2899e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_FW, "iwh_intr(): "
2900e2cf88acSQuaker Fang 		    "fatal firmware error\n"));
2901c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		iwh_stop(sc);
2902c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_ostate = sc->sc_ic.ic_state;
29036f12def4Spengcheng chen - Sun Microsystems - Beijing China 
290489b2a9fbSfei feng - Sun Microsystems - Beijing China 		/*
290589b2a9fbSfei feng - Sun Microsystems - Beijing China 		 * notify upper layer
290689b2a9fbSfei feng - Sun Microsystems - Beijing China 		 */
2907e2cf88acSQuaker Fang 		if (!IWH_CHK_FAST_RECOVER(sc)) {
2908c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
2909e2cf88acSQuaker Fang 		}
29106f12def4Spengcheng chen - Sun Microsystems - Beijing China 
291189b2a9fbSfei feng - Sun Microsystems - Beijing China 		atomic_or_32(&sc->sc_flags, IWH_F_HW_ERR_RECOVER);
2912c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (DDI_INTR_CLAIMED);
2913c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2914c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2915c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (r & BIT_INT_RF_KILL) {
2916b510adaeSfei feng - Sun Microsystems - Beijing China 		uint32_t tmp = IWH_READ(sc, CSR_GP_CNTRL);
2917e2cf88acSQuaker Fang 		if (tmp & (1 << 27)) {
2918b510adaeSfei feng - Sun Microsystems - Beijing China 			cmn_err(CE_NOTE, "RF switch: radio on\n");
2919c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
2920e2cf88acSQuaker Fang 	}
2921c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2922c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if ((r & (BIT_INT_FH_RX | BIT_INT_SW_RX)) ||
2923c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    (rfh & FH_INT_RX_MASK)) {
2924c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		(void) ddi_intr_trigger_softint(sc->sc_soft_hdl, NULL);
2925e2cf88acSQuaker Fang 		return (DDI_INTR_CLAIMED);
2926c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2927c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2928c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (r & BIT_INT_FH_TX) {
2929e2cf88acSQuaker Fang 		mutex_enter(&sc->sc_glock);
293089b2a9fbSfei feng - Sun Microsystems - Beijing China 		atomic_or_32(&sc->sc_flags, IWH_F_PUT_SEG);
2931c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cv_signal(&sc->sc_put_seg_cv);
2932e2cf88acSQuaker Fang 		mutex_exit(&sc->sc_glock);
2933c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2934c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2935c7ee0b5cSfei feng - Sun Microsystems - Beijing China #ifdef	DEBUG
2936c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (r & BIT_INT_ALIVE)	{
2937e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_FW, "iwh_intr(): "
2938e2cf88acSQuaker Fang 		    "firmware initialized.\n"));
2939c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
2940c7ee0b5cSfei feng - Sun Microsystems - Beijing China #endif
2941c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2942c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
2943c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * re-enable interrupts
2944c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
2945c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_INT_MASK, CSR_INI_SET_MASK);
2946c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2947c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (DDI_INTR_CLAIMED);
2948c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
2949c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2950c7ee0b5cSfei feng - Sun Microsystems - Beijing China static uint8_t
2951c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_rate_to_plcp(int rate)
2952c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
2953c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint8_t ret;
2954c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2955c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	switch (rate) {
2956c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
2957c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * CCK rates
2958c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
2959c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case 2:
2960c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ret = 0xa;
2961c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
2962c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2963c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case 4:
2964c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ret = 0x14;
2965c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
2966c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2967c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case 11:
2968c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ret = 0x37;
2969c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
2970c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2971c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case 22:
2972c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ret = 0x6e;
2973c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
2974c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2975c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
2976c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * OFDM rates
2977c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
2978c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case 12:
2979c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ret = 0xd;
2980c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
2981c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2982c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case 18:
2983c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ret = 0xf;
2984c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
2985c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2986c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case 24:
2987c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ret = 0x5;
2988c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
2989c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2990c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case 36:
2991c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ret = 0x7;
2992c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
2993c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2994c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case 48:
2995c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ret = 0x9;
2996c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
2997c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
2998c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case 72:
2999c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ret = 0xb;
3000c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
3001c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3002c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case 96:
3003c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ret = 0x1;
3004c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
3005c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3006c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case 108:
3007c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ret = 0x3;
3008c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
3009c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3010c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	default:
3011c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ret = 0;
3012c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
3013c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
3014c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3015c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (ret);
3016c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
3017c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3018c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
3019c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * invoked by GLD send frames
3020c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
3021c7ee0b5cSfei feng - Sun Microsystems - Beijing China static mblk_t *
3022c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_m_tx(void *arg, mblk_t *mp)
3023c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
3024e2cf88acSQuaker Fang 	iwh_sc_t *sc;
3025e2cf88acSQuaker Fang 	ieee80211com_t *ic;
3026c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mblk_t *next;
3027c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3028e2cf88acSQuaker Fang 	if (NULL == arg) {
3029c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (NULL);
3030c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
3031e2cf88acSQuaker Fang 	sc = (iwh_sc_t *)arg;
3032e2cf88acSQuaker Fang 	ic = &sc->sc_ic;
3033c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
303489b2a9fbSfei feng - Sun Microsystems - Beijing China 	if (sc->sc_flags & IWH_F_SUSPEND) {
303589b2a9fbSfei feng - Sun Microsystems - Beijing China 		freemsgchain(mp);
303689b2a9fbSfei feng - Sun Microsystems - Beijing China 		return (NULL);
303789b2a9fbSfei feng - Sun Microsystems - Beijing China 	}
303889b2a9fbSfei feng - Sun Microsystems - Beijing China 
3039c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (ic->ic_state != IEEE80211_S_RUN) {
3040c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		freemsgchain(mp);
3041c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (NULL);
3042c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
3043c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
30446f12def4Spengcheng chen - Sun Microsystems - Beijing China 	if ((sc->sc_flags & IWH_F_HW_ERR_RECOVER) &&
30456f12def4Spengcheng chen - Sun Microsystems - Beijing China 	    IWH_CHK_FAST_RECOVER(sc)) {
3046e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_FW, "iwh_m_tx(): "
3047e2cf88acSQuaker Fang 		    "hold queue\n"));
30486f12def4Spengcheng chen - Sun Microsystems - Beijing China 		return (mp);
30496f12def4Spengcheng chen - Sun Microsystems - Beijing China 	}
30506f12def4Spengcheng chen - Sun Microsystems - Beijing China 
3051c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	while (mp != NULL) {
3052c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		next = mp->b_next;
3053c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		mp->b_next = NULL;
3054c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (iwh_send(ic, mp, IEEE80211_FC0_TYPE_DATA) != 0) {
3055c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			mp->b_next = next;
3056c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			break;
3057c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
3058c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		mp = next;
3059c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
3060c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3061c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (mp);
3062c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
3063c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3064c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
3065c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * send frames
3066c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
3067c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
3068c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
3069c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
3070e2cf88acSQuaker Fang 	iwh_sc_t *sc;
3071c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_tx_ring_t *ring;
3072c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_tx_desc_t *desc;
3073c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_tx_data_t *data;
307489b2a9fbSfei feng - Sun Microsystems - Beijing China 	iwh_tx_data_t *desc_data;
3075c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_cmd_t *cmd;
3076c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_tx_cmd_t *tx;
3077c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ieee80211_node_t *in;
307889b2a9fbSfei feng - Sun Microsystems - Beijing China 	struct ieee80211_frame *wh, *mp_wh;
3079c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	struct ieee80211_key *k = NULL;
3080c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mblk_t *m, *m0;
3081e2cf88acSQuaker Fang 	int hdrlen, len, len0, mblen, off, err = IWH_SUCCESS;
3082c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint16_t masks = 0;
3083e2cf88acSQuaker Fang 	uint32_t rate, s_id = 0;
3084e2cf88acSQuaker Fang 	int txq_id = NON_QOS_TXQ;
3085e2cf88acSQuaker Fang 	struct ieee80211_qosframe *qwh = NULL;
3086e2cf88acSQuaker Fang 	int tid = WME_TID_INVALID;
3087c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3088e2cf88acSQuaker Fang 	if (NULL == ic) {
3089e2cf88acSQuaker Fang 		return (IWH_FAIL);
3090e2cf88acSQuaker Fang 	}
3091e2cf88acSQuaker Fang 	sc = (iwh_sc_t *)ic;
3092c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3093c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (sc->sc_flags & IWH_F_SUSPEND) {
3094c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if ((type & IEEE80211_FC0_TYPE_MASK) !=
3095c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    IEEE80211_FC0_TYPE_DATA) {
3096c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			freemsg(mp);
3097c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
3098c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		err = IWH_FAIL;
3099c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto exit;
3100c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
3101c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
310289b2a9fbSfei feng - Sun Microsystems - Beijing China 	if ((NULL == mp) || (MBLKL(mp) <= 0)) {
310389b2a9fbSfei feng - Sun Microsystems - Beijing China 		return (IWH_FAIL);
3104c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
3105c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
310689b2a9fbSfei feng - Sun Microsystems - Beijing China 	mp_wh = (struct ieee80211_frame *)mp->b_rptr;
3107c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3108c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
310989b2a9fbSfei feng - Sun Microsystems - Beijing China 	 * Determine send which AP or station in IBSS
3110c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
311189b2a9fbSfei feng - Sun Microsystems - Beijing China 	in = ieee80211_find_txnode(ic, mp_wh->i_addr1);
3112c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (NULL == in) {
3113c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_send(): "
3114c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to find tx node\n");
3115e2cf88acSQuaker Fang 		freemsg(mp);
3116c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_tx_err++;
3117c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		err = IWH_SUCCESS;
3118c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		goto exit;
3119c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
3120c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3121e2cf88acSQuaker Fang 	/*
3122e2cf88acSQuaker Fang 	 * Determine TX queue according to traffic ID in frame
3123e2cf88acSQuaker Fang 	 * if working in QoS mode.
3124e2cf88acSQuaker Fang 	 */
3125e2cf88acSQuaker Fang 	if (in->in_flags & IEEE80211_NODE_QOS) {
3126e2cf88acSQuaker Fang 
3127e2cf88acSQuaker Fang 		if ((type & IEEE80211_FC0_TYPE_MASK) ==
3128e2cf88acSQuaker Fang 		    IEEE80211_FC0_TYPE_DATA) {
3129e2cf88acSQuaker Fang 
313089b2a9fbSfei feng - Sun Microsystems - Beijing China 			if (mp_wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS) {
313189b2a9fbSfei feng - Sun Microsystems - Beijing China 				qwh = (struct ieee80211_qosframe *)mp_wh;
3132e2cf88acSQuaker Fang 
3133e2cf88acSQuaker Fang 				tid = qwh->i_qos[0] & IEEE80211_QOS_TID;
3134e2cf88acSQuaker Fang 				txq_id = iwh_wme_tid_to_txq(tid);
3135e2cf88acSQuaker Fang 
3136e2cf88acSQuaker Fang 				if (txq_id < TXQ_FOR_AC_MIN ||
3137e2cf88acSQuaker Fang 				    (txq_id > TXQ_FOR_AC_MAX)) {
3138e2cf88acSQuaker Fang 					freemsg(mp);
3139e2cf88acSQuaker Fang 					sc->sc_tx_err++;
3140e2cf88acSQuaker Fang 					err = IWH_SUCCESS;
3141e2cf88acSQuaker Fang 					goto exit;
3142e2cf88acSQuaker Fang 				}
3143e2cf88acSQuaker Fang 
3144e2cf88acSQuaker Fang 			} else {
3145e2cf88acSQuaker Fang 				txq_id = NON_QOS_TXQ;
3146e2cf88acSQuaker Fang 			}
3147e2cf88acSQuaker Fang 
3148e2cf88acSQuaker Fang 		} else if ((type & IEEE80211_FC0_TYPE_MASK) ==
3149e2cf88acSQuaker Fang 		    IEEE80211_FC0_TYPE_MGT) {
3150e2cf88acSQuaker Fang 			txq_id = QOS_TXQ_FOR_MGT;
3151e2cf88acSQuaker Fang 		} else {
3152e2cf88acSQuaker Fang 			txq_id = NON_QOS_TXQ;
3153e2cf88acSQuaker Fang 		}
3154e2cf88acSQuaker Fang 
3155e2cf88acSQuaker Fang 	} else {
3156e2cf88acSQuaker Fang 		txq_id = NON_QOS_TXQ;
3157e2cf88acSQuaker Fang 	}
3158e2cf88acSQuaker Fang 
315989b2a9fbSfei feng - Sun Microsystems - Beijing China 	mutex_enter(&sc->sc_tx_lock);
3160e2cf88acSQuaker Fang 	ring = &sc->sc_txq[txq_id];
3161e2cf88acSQuaker Fang 	data = &ring->data[ring->cur];
3162e2cf88acSQuaker Fang 	cmd = data->cmd;
3163e2cf88acSQuaker Fang 	bzero(cmd, sizeof (*cmd));
3164e2cf88acSQuaker Fang 
316589b2a9fbSfei feng - Sun Microsystems - Beijing China 	ring->cur = (ring->cur + 1) % ring->count;
3166e2cf88acSQuaker Fang 
3167e2cf88acSQuaker Fang 	/*
3168e2cf88acSQuaker Fang 	 * Need reschedule TX if TX buffer is full.
3169e2cf88acSQuaker Fang 	 */
3170e2cf88acSQuaker Fang 	if (ring->queued > ring->count - IWH_MAX_WIN_SIZE) {
3171e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_TX, "iwh_send(): "
3172e2cf88acSQuaker Fang 		"no txbuf\n"));
3173e2cf88acSQuaker Fang 
3174e2cf88acSQuaker Fang 		sc->sc_need_reschedule = 1;
3175e2cf88acSQuaker Fang 		mutex_exit(&sc->sc_tx_lock);
3176e2cf88acSQuaker Fang 
3177e2cf88acSQuaker Fang 		if ((type & IEEE80211_FC0_TYPE_MASK) !=
3178e2cf88acSQuaker Fang 		    IEEE80211_FC0_TYPE_DATA) {
3179e2cf88acSQuaker Fang 			freemsg(mp);
3180e2cf88acSQuaker Fang 		}
3181e2cf88acSQuaker Fang 		sc->sc_tx_nobuf++;
3182e2cf88acSQuaker Fang 		err = IWH_FAIL;
3183e2cf88acSQuaker Fang 		goto exit;
3184e2cf88acSQuaker Fang 	}
318589b2a9fbSfei feng - Sun Microsystems - Beijing China 
318689b2a9fbSfei feng - Sun Microsystems - Beijing China 	ring->queued++;
318789b2a9fbSfei feng - Sun Microsystems - Beijing China 
3188e2cf88acSQuaker Fang 	mutex_exit(&sc->sc_tx_lock);
3189e2cf88acSQuaker Fang 
319089b2a9fbSfei feng - Sun Microsystems - Beijing China 	hdrlen = ieee80211_hdrspace(ic, mp->b_rptr);
319189b2a9fbSfei feng - Sun Microsystems - Beijing China 
319289b2a9fbSfei feng - Sun Microsystems - Beijing China 	m = allocb(msgdsize(mp) + 32, BPRI_MED);
319389b2a9fbSfei feng - Sun Microsystems - Beijing China 	if (NULL == m) { /* can not alloc buf, drop this package */
319489b2a9fbSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_send(): "
319589b2a9fbSfei feng - Sun Microsystems - Beijing China 		    "failed to allocate msgbuf\n");
319689b2a9fbSfei feng - Sun Microsystems - Beijing China 		freemsg(mp);
319789b2a9fbSfei feng - Sun Microsystems - Beijing China 
319889b2a9fbSfei feng - Sun Microsystems - Beijing China 		mutex_enter(&sc->sc_tx_lock);
319989b2a9fbSfei feng - Sun Microsystems - Beijing China 		ring->queued--;
320089b2a9fbSfei feng - Sun Microsystems - Beijing China 		if ((sc->sc_need_reschedule) && (ring->queued <= 0)) {
320189b2a9fbSfei feng - Sun Microsystems - Beijing China 			sc->sc_need_reschedule = 0;
320289b2a9fbSfei feng - Sun Microsystems - Beijing China 			mutex_exit(&sc->sc_tx_lock);
320389b2a9fbSfei feng - Sun Microsystems - Beijing China 			mac_tx_update(ic->ic_mach);
320489b2a9fbSfei feng - Sun Microsystems - Beijing China 			mutex_enter(&sc->sc_tx_lock);
320589b2a9fbSfei feng - Sun Microsystems - Beijing China 		}
320689b2a9fbSfei feng - Sun Microsystems - Beijing China 		mutex_exit(&sc->sc_tx_lock);
320789b2a9fbSfei feng - Sun Microsystems - Beijing China 
320889b2a9fbSfei feng - Sun Microsystems - Beijing China 		err = IWH_SUCCESS;
320989b2a9fbSfei feng - Sun Microsystems - Beijing China 		goto exit;
321089b2a9fbSfei feng - Sun Microsystems - Beijing China 	}
321189b2a9fbSfei feng - Sun Microsystems - Beijing China 
321289b2a9fbSfei feng - Sun Microsystems - Beijing China 	for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) {
321389b2a9fbSfei feng - Sun Microsystems - Beijing China 		mblen = MBLKL(m0);
321489b2a9fbSfei feng - Sun Microsystems - Beijing China 		bcopy(m0->b_rptr, m->b_rptr + off, mblen);
321589b2a9fbSfei feng - Sun Microsystems - Beijing China 		off += mblen;
321689b2a9fbSfei feng - Sun Microsystems - Beijing China 	}
321789b2a9fbSfei feng - Sun Microsystems - Beijing China 
321889b2a9fbSfei feng - Sun Microsystems - Beijing China 	m->b_wptr += off;
321989b2a9fbSfei feng - Sun Microsystems - Beijing China 
322089b2a9fbSfei feng - Sun Microsystems - Beijing China 	wh = (struct ieee80211_frame *)m->b_rptr;
322189b2a9fbSfei feng - Sun Microsystems - Beijing China 
322289b2a9fbSfei feng - Sun Microsystems - Beijing China 	/*
322389b2a9fbSfei feng - Sun Microsystems - Beijing China 	 * Net80211 module encapsulate outbound data frames.
322489b2a9fbSfei feng - Sun Microsystems - Beijing China 	 * Add some feilds of 80211 frame.
322589b2a9fbSfei feng - Sun Microsystems - Beijing China 	 */
322689b2a9fbSfei feng - Sun Microsystems - Beijing China 	if ((type & IEEE80211_FC0_TYPE_MASK) ==
322789b2a9fbSfei feng - Sun Microsystems - Beijing China 	    IEEE80211_FC0_TYPE_DATA) {
322889b2a9fbSfei feng - Sun Microsystems - Beijing China 		(void) ieee80211_encap(ic, m, in);
322989b2a9fbSfei feng - Sun Microsystems - Beijing China 	}
323089b2a9fbSfei feng - Sun Microsystems - Beijing China 
3231e2cf88acSQuaker Fang 	freemsg(mp);
3232c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3233c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	cmd->hdr.type = REPLY_TX;
3234c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	cmd->hdr.flags = 0;
3235c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	cmd->hdr.qid = ring->qid;
3236c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3237c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tx = (iwh_tx_cmd_t *)cmd->data;
3238c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tx->tx_flags = 0;
3239c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3240c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
3241c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		tx->tx_flags &= ~(LE_32(TX_CMD_FLG_ACK_MSK));
3242c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	} else {
3243c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		tx->tx_flags |= LE_32(TX_CMD_FLG_ACK_MSK);
3244c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
3245c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3246c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
3247c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		k = ieee80211_crypto_encap(ic, m);
3248c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (NULL == k) {
3249c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			freemsg(m);
3250c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			sc->sc_tx_err++;
325189b2a9fbSfei feng - Sun Microsystems - Beijing China 
325289b2a9fbSfei feng - Sun Microsystems - Beijing China 			mutex_enter(&sc->sc_tx_lock);
325389b2a9fbSfei feng - Sun Microsystems - Beijing China 			ring->queued--;
325489b2a9fbSfei feng - Sun Microsystems - Beijing China 			if ((sc->sc_need_reschedule) && (ring->queued <= 0)) {
325589b2a9fbSfei feng - Sun Microsystems - Beijing China 				sc->sc_need_reschedule = 0;
325689b2a9fbSfei feng - Sun Microsystems - Beijing China 				mutex_exit(&sc->sc_tx_lock);
325789b2a9fbSfei feng - Sun Microsystems - Beijing China 				mac_tx_update(ic->ic_mach);
325889b2a9fbSfei feng - Sun Microsystems - Beijing China 				mutex_enter(&sc->sc_tx_lock);
325989b2a9fbSfei feng - Sun Microsystems - Beijing China 			}
326089b2a9fbSfei feng - Sun Microsystems - Beijing China 			mutex_exit(&sc->sc_tx_lock);
326189b2a9fbSfei feng - Sun Microsystems - Beijing China 
3262c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			err = IWH_SUCCESS;
3263c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			goto exit;
3264c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
3265c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
326689b2a9fbSfei feng - Sun Microsystems - Beijing China 		/*
326789b2a9fbSfei feng - Sun Microsystems - Beijing China 		 * packet header may have moved, reset our local pointer
326889b2a9fbSfei feng - Sun Microsystems - Beijing China 		 */
3269c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		wh = (struct ieee80211_frame *)m->b_rptr;
3270c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
3271c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3272c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	len = msgdsize(m);
3273c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3274c7ee0b5cSfei feng - Sun Microsystems - Beijing China #ifdef DEBUG
3275c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (iwh_dbg_flags & IWH_DEBUG_TX) {
3276c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ieee80211_dump_pkt((uint8_t *)wh, hdrlen, 0, 0);
3277c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
3278c7ee0b5cSfei feng - Sun Microsystems - Beijing China #endif
3279c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3280e2cf88acSQuaker Fang 	tx->rts_retry_limit = IWH_TX_RTS_RETRY_LIMIT;
3281e2cf88acSQuaker Fang 	tx->data_retry_limit = IWH_TX_DATA_RETRY_LIMIT;
3282e2cf88acSQuaker Fang 
3283c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
3284e2cf88acSQuaker Fang 	 * specific TX parameters for management frames
3285c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
3286c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
3287c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    IEEE80211_FC0_TYPE_MGT) {
3288c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		/*
3289c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * mgmt frames are sent at 1M
3290c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 */
3291e2cf88acSQuaker Fang 		if ((in->in_rates.ir_rates[0] &
3292e2cf88acSQuaker Fang 		    IEEE80211_RATE_VAL) != 0) {
3293e2cf88acSQuaker Fang 			rate = in->in_rates.ir_rates[0] & IEEE80211_RATE_VAL;
3294e2cf88acSQuaker Fang 		} else {
3295e2cf88acSQuaker Fang 			rate = 2;
3296e2cf88acSQuaker Fang 		}
3297e2cf88acSQuaker Fang 
3298e2cf88acSQuaker Fang 		tx->tx_flags |= LE_32(TX_CMD_FLG_SEQ_CTL_MSK);
3299e2cf88acSQuaker Fang 
3300e2cf88acSQuaker Fang 		/*
3301e2cf88acSQuaker Fang 		 * tell h/w to set timestamp in probe responses
3302e2cf88acSQuaker Fang 		 */
3303e2cf88acSQuaker Fang 		if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
3304e2cf88acSQuaker Fang 		    IEEE80211_FC0_SUBTYPE_PROBE_RESP) {
3305e2cf88acSQuaker Fang 			tx->tx_flags |= LE_32(TX_CMD_FLG_TSF_MSK);
3306e2cf88acSQuaker Fang 
3307e2cf88acSQuaker Fang 			tx->data_retry_limit = 3;
3308e2cf88acSQuaker Fang 			if (tx->data_retry_limit < tx->rts_retry_limit) {
3309e2cf88acSQuaker Fang 				tx->rts_retry_limit = tx->data_retry_limit;
3310e2cf88acSQuaker Fang 			}
3311e2cf88acSQuaker Fang 		}
3312e2cf88acSQuaker Fang 
3313e2cf88acSQuaker Fang 		if (((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
3314e2cf88acSQuaker Fang 		    IEEE80211_FC0_SUBTYPE_ASSOC_REQ) ||
3315e2cf88acSQuaker Fang 		    ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
3316e2cf88acSQuaker Fang 		    IEEE80211_FC0_SUBTYPE_REASSOC_REQ)) {
3317e2cf88acSQuaker Fang 			tx->timeout.pm_frame_timeout = LE_16(3);
3318e2cf88acSQuaker Fang 		} else {
3319e2cf88acSQuaker Fang 			tx->timeout.pm_frame_timeout = LE_16(2);
3320e2cf88acSQuaker Fang 		}
3321e2cf88acSQuaker Fang 
3322c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	} else {
3323c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		/*
3324e2cf88acSQuaker Fang 		 * do it here for the software way rate scaling.
3325c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * later for rate scaling in hardware.
3326c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 *
3327c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * now the txrate is determined in tx cmd flags, set to the
3328e2cf88acSQuaker Fang 		 * max value 54M for 11g and 11M for 11b and 96M for 11n
3329e2cf88acSQuaker Fang 		 * originally.
3330c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 */
3331c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
3332c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			rate = ic->ic_fixed_rate;
3333c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		} else {
3334e2cf88acSQuaker Fang 			if ((in->in_flags & IEEE80211_NODE_HT) &&
3335e2cf88acSQuaker Fang 			    (sc->sc_ht_conf.ht_support)) {
3336e2cf88acSQuaker Fang 				iwh_amrr_t *amrr = (iwh_amrr_t *)in;
3337e2cf88acSQuaker Fang 				rate = amrr->ht_mcs_idx;
3338e2cf88acSQuaker Fang 			} else {
3339e2cf88acSQuaker Fang 				if ((in->in_rates.ir_rates[in->in_txrate] &
3340e2cf88acSQuaker Fang 				    IEEE80211_RATE_VAL) != 0) {
3341e2cf88acSQuaker Fang 					rate = in->in_rates.
3342e2cf88acSQuaker Fang 					    ir_rates[in->in_txrate] &
3343e2cf88acSQuaker Fang 					    IEEE80211_RATE_VAL;
3344e2cf88acSQuaker Fang 				}
3345c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			}
3346c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
3347c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3348e2cf88acSQuaker Fang 		if (tid != WME_TID_INVALID) {
3349e2cf88acSQuaker Fang 			tx->tid_tspec = (uint8_t)tid;
3350e2cf88acSQuaker Fang 			tx->tx_flags &= LE_32(~TX_CMD_FLG_SEQ_CTL_MSK);
3351e2cf88acSQuaker Fang 		} else {
3352e2cf88acSQuaker Fang 			tx->tx_flags |= LE_32(TX_CMD_FLG_SEQ_CTL_MSK);
3353e2cf88acSQuaker Fang 		}
3354c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3355e2cf88acSQuaker Fang 		tx->timeout.pm_frame_timeout = 0;
3356e2cf88acSQuaker Fang 	}
3357e2cf88acSQuaker Fang 
3358e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_TX, "iwh_send(): "
3359e2cf88acSQuaker Fang 	    "tx rate[%d of %d] = %x",
3360c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    in->in_txrate, in->in_rates.ir_nrates, rate));
3361c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3362c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	len0 = roundup(4 + sizeof (iwh_tx_cmd_t) + hdrlen, 4);
3363c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (len0 != (4 + sizeof (iwh_tx_cmd_t) + hdrlen)) {
3364b510adaeSfei feng - Sun Microsystems - Beijing China 		tx->tx_flags |= LE_32(TX_CMD_FLG_MH_PAD_MSK);
3365c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
3366c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3367c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
3368c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * retrieve destination node's id
3369c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
3370c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
3371c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		tx->sta_id = IWH_BROADCAST_ID;
3372c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	} else {
3373c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		tx->sta_id = IWH_AP_ID;
3374c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
3375c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3376e2cf88acSQuaker Fang 	if ((in->in_flags & IEEE80211_NODE_HT) &&
3377e2cf88acSQuaker Fang 	    (sc->sc_ht_conf.ht_support) &&
3378e2cf88acSQuaker Fang 	    ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
3379e2cf88acSQuaker Fang 	    IEEE80211_FC0_TYPE_DATA)) {
3380e2cf88acSQuaker Fang 		if (rate >= HT_2CHAIN_RATE_MIN_IDX) {
3381e2cf88acSQuaker Fang 			rate |= LE_32(RATE_MCS_ANT_AB_MSK);
3382e2cf88acSQuaker Fang 		} else {
3383e2cf88acSQuaker Fang 			rate |= LE_32(RATE_MCS_ANT_B_MSK);
3384c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
3385c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3386e2cf88acSQuaker Fang 		rate |= LE_32((1 << RATE_MCS_HT_POS));
3387c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3388e2cf88acSQuaker Fang 		tx->rate.r.rate_n_flags = rate;
3389e2cf88acSQuaker Fang 
3390e2cf88acSQuaker Fang 	} else {
3391c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (2 == rate || 4 == rate || 11 == rate || 22 == rate) {
3392c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			masks |= RATE_MCS_CCK_MSK;
3393c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
3394c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3395c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		masks |= RATE_MCS_ANT_B_MSK;
3396b510adaeSfei feng - Sun Microsystems - Beijing China 		tx->rate.r.rate_n_flags = LE_32(iwh_rate_to_plcp(rate) | masks);
3397e2cf88acSQuaker Fang 	}
3398c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3399e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_TX, "iwh_send(): "
3400e2cf88acSQuaker Fang 	    "tx flag = %x",
3401c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    tx->tx_flags));
3402c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3403c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tx->stop_time.life_time  = LE_32(0xffffffff);
3404c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3405c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tx->len = LE_16(len);
3406c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3407c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tx->dram_lsb_ptr =
3408b510adaeSfei feng - Sun Microsystems - Beijing China 	    LE_32(data->paddr_cmd + 4 + offsetof(iwh_tx_cmd_t, scratch));
3409c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tx->dram_msb_ptr = 0;
3410c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tx->driver_txop = 0;
3411c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tx->next_frame_len = 0;
3412c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
341389b2a9fbSfei feng - Sun Microsystems - Beijing China 	bcopy(m->b_rptr, tx + 1, hdrlen);
3414c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	m->b_rptr += hdrlen;
341589b2a9fbSfei feng - Sun Microsystems - Beijing China 	bcopy(m->b_rptr, data->dma_data.mem_va, (len - hdrlen));
3416c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3417e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_TX, "iwh_send(): "
3418e2cf88acSQuaker Fang 	    "sending data: qid=%d idx=%d len=%d",
3419c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    ring->qid, ring->cur, len));
3420c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3421c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
3422c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * first segment includes the tx cmd plus the 802.11 header,
3423c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * the second includes the remaining of the 802.11 frame.
3424c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
342589b2a9fbSfei feng - Sun Microsystems - Beijing China 
342689b2a9fbSfei feng - Sun Microsystems - Beijing China 	mutex_enter(&sc->sc_tx_lock);
342789b2a9fbSfei feng - Sun Microsystems - Beijing China 	cmd->hdr.idx = ring->desc_cur;
342889b2a9fbSfei feng - Sun Microsystems - Beijing China 	desc_data = &ring->data[ring->desc_cur];
342989b2a9fbSfei feng - Sun Microsystems - Beijing China 	desc = desc_data->desc;
343089b2a9fbSfei feng - Sun Microsystems - Beijing China 	bzero(desc, sizeof (*desc));
3431b510adaeSfei feng - Sun Microsystems - Beijing China 	desc->val0 = 2 << 24;
3432b510adaeSfei feng - Sun Microsystems - Beijing China 	desc->pa[0].tb1_addr = data->paddr_cmd;
3433c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	desc->pa[0].val1 = ((len0 << 4) & 0xfff0) |
3434c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    ((data->dma_data.cookie.dmac_address & 0xffff) << 16);
3435c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	desc->pa[0].val2 =
3436c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    ((data->dma_data.cookie.dmac_address & 0xffff0000) >> 16) |
3437c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    ((len - hdrlen) << 20);
3438e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_TX, "iwh_send(): "
3439e2cf88acSQuaker Fang 	    "phy addr1 = 0x%x phy addr2 = 0x%x "
3440c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    "len1 = 0x%x, len2 = 0x%x val1 = 0x%x val2 = 0x%x",
3441c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    data->paddr_cmd, data->dma_data.cookie.dmac_address,
3442c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    len0, len - hdrlen, desc->pa[0].val1, desc->pa[0].val2));
3443c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3444c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
3445c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * kick ring
3446c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
3447c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	s_id = tx->sta_id;
3448c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3449c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_shared->queues_byte_cnt_tbls[ring->qid].
345089b2a9fbSfei feng - Sun Microsystems - Beijing China 	    tfd_offset[ring->desc_cur].val =
3451c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    (8 + len) | (s_id << 12);
345289b2a9fbSfei feng - Sun Microsystems - Beijing China 	if (ring->desc_cur < IWH_MAX_WIN_SIZE) {
3453c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_shared->queues_byte_cnt_tbls[ring->qid].
345489b2a9fbSfei feng - Sun Microsystems - Beijing China 		    tfd_offset[IWH_QUEUE_SIZE + ring->desc_cur].val =
3455c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    (8 + len) | (s_id << 12);
3456c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
3457c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3458c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_DMA_SYNC(data->dma_data, DDI_DMA_SYNC_FORDEV);
3459c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV);
3460c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
346189b2a9fbSfei feng - Sun Microsystems - Beijing China 	ring->desc_cur = (ring->desc_cur + 1) % ring->count;
346289b2a9fbSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, HBUS_TARG_WRPTR, ring->qid << 8 | ring->desc_cur);
346389b2a9fbSfei feng - Sun Microsystems - Beijing China 
346489b2a9fbSfei feng - Sun Microsystems - Beijing China 	mutex_exit(&sc->sc_tx_lock);
3465c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	freemsg(m);
3466c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3467c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
3468c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * release node reference
3469c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
3470c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ieee80211_free_node(in);
3471c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3472c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ic->ic_stats.is_tx_bytes += len;
3473c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ic->ic_stats.is_tx_frags++;
3474c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3475e2cf88acSQuaker Fang 	mutex_enter(&sc->sc_mt_lock);
3476c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (0 == sc->sc_tx_timer) {
34776f12def4Spengcheng chen - Sun Microsystems - Beijing China 		sc->sc_tx_timer = 4;
3478c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
3479e2cf88acSQuaker Fang 	mutex_exit(&sc->sc_mt_lock);
3480c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3481c7ee0b5cSfei feng - Sun Microsystems - Beijing China exit:
3482c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (err);
3483c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
3484c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3485c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
3486c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * invoked by GLD to deal with IOCTL affaires
3487c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
3488c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
3489c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_m_ioctl(void* arg, queue_t *wq, mblk_t *mp)
3490c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
3491e2cf88acSQuaker Fang 	iwh_sc_t *sc;
3492e2cf88acSQuaker Fang 	ieee80211com_t *ic;
3493e2cf88acSQuaker Fang 	int err = EINVAL;
3494e2cf88acSQuaker Fang 
3495e2cf88acSQuaker Fang 	if (NULL == arg) {
3496e2cf88acSQuaker Fang 		return;
3497e2cf88acSQuaker Fang 	}
3498e2cf88acSQuaker Fang 	sc = (iwh_sc_t *)arg;
3499e2cf88acSQuaker Fang 	ic = &sc->sc_ic;
3500c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3501c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = ieee80211_ioctl(ic, wq, mp);
3502c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (ENETRESET == err) {
3503c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		/*
3504c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * This is special for the hidden AP connection.
3505c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * In any case, we should make sure only one 'scan'
3506c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * in the driver for a 'connect' CLI command. So
3507c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * when connecting to a hidden AP, the scan is just
3508c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * sent out to the air when we know the desired
3509c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * essid of the AP we want to connect.
3510c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 */
3511c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (ic->ic_des_esslen) {
3512d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			if (sc->sc_flags & IWH_F_RUNNING) {
3513d5bd65e4Sfei feng - Sun Microsystems - Beijing China 				iwh_m_stop(sc);
3514d5bd65e4Sfei feng - Sun Microsystems - Beijing China 				(void) iwh_m_start(sc);
3515c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				(void) ieee80211_new_state(ic,
3516c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				    IEEE80211_S_SCAN, -1);
3517c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			}
3518c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
3519c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
3520d5bd65e4Sfei feng - Sun Microsystems - Beijing China }
3521c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3522c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
35237efa17f5Sfei feng - Sun Microsystems - Beijing China  * Call back functions for get/set proporty
35247efa17f5Sfei feng - Sun Microsystems - Beijing China  */
35257efa17f5Sfei feng - Sun Microsystems - Beijing China static int
35267efa17f5Sfei feng - Sun Microsystems - Beijing China iwh_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
3527*0dc2366fSVenugopal Iyer     uint_t wldp_length, void *wldp_buf)
35287efa17f5Sfei feng - Sun Microsystems - Beijing China {
3529e2cf88acSQuaker Fang 	iwh_sc_t *sc;
3530e2cf88acSQuaker Fang 	int err = EINVAL;
3531e2cf88acSQuaker Fang 
3532e2cf88acSQuaker Fang 	if (NULL == arg) {
3533e2cf88acSQuaker Fang 		return (EINVAL);
3534e2cf88acSQuaker Fang 	}
3535e2cf88acSQuaker Fang 	sc = (iwh_sc_t *)arg;
35367efa17f5Sfei feng - Sun Microsystems - Beijing China 
35377efa17f5Sfei feng - Sun Microsystems - Beijing China 	err = ieee80211_getprop(&sc->sc_ic, pr_name, wldp_pr_num,
3538*0dc2366fSVenugopal Iyer 	    wldp_length, wldp_buf);
35397efa17f5Sfei feng - Sun Microsystems - Beijing China 
35407efa17f5Sfei feng - Sun Microsystems - Beijing China 	return (err);
35417efa17f5Sfei feng - Sun Microsystems - Beijing China }
35427efa17f5Sfei feng - Sun Microsystems - Beijing China 
3543*0dc2366fSVenugopal Iyer static void
3544*0dc2366fSVenugopal Iyer iwh_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
3545*0dc2366fSVenugopal Iyer     mac_prop_info_handle_t mph)
3546*0dc2366fSVenugopal Iyer {
3547*0dc2366fSVenugopal Iyer 	iwh_sc_t	*sc = (iwh_sc_t *)arg;
3548*0dc2366fSVenugopal Iyer 
3549*0dc2366fSVenugopal Iyer 	ieee80211_propinfo(&sc->sc_ic, pr_name, wldp_pr_num, mph);
3550*0dc2366fSVenugopal Iyer }
3551*0dc2366fSVenugopal Iyer 
35527efa17f5Sfei feng - Sun Microsystems - Beijing China static int
35537efa17f5Sfei feng - Sun Microsystems - Beijing China iwh_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
35547efa17f5Sfei feng - Sun Microsystems - Beijing China     uint_t wldp_length, const void *wldp_buf)
35557efa17f5Sfei feng - Sun Microsystems - Beijing China {
3556e2cf88acSQuaker Fang 	iwh_sc_t *sc;
3557e2cf88acSQuaker Fang 	ieee80211com_t *ic;
3558e2cf88acSQuaker Fang 	int err = EINVAL;
3559e2cf88acSQuaker Fang 
3560e2cf88acSQuaker Fang 	if (NULL == arg) {
3561e2cf88acSQuaker Fang 		return (EINVAL);
3562e2cf88acSQuaker Fang 	}
3563e2cf88acSQuaker Fang 	sc = (iwh_sc_t *)arg;
3564e2cf88acSQuaker Fang 	ic = &sc->sc_ic;
35657efa17f5Sfei feng - Sun Microsystems - Beijing China 
35667efa17f5Sfei feng - Sun Microsystems - Beijing China 	err = ieee80211_setprop(ic, pr_name, wldp_pr_num, wldp_length,
35677efa17f5Sfei feng - Sun Microsystems - Beijing China 	    wldp_buf);
35687efa17f5Sfei feng - Sun Microsystems - Beijing China 
35697efa17f5Sfei feng - Sun Microsystems - Beijing China 	if (err == ENETRESET) {
35707efa17f5Sfei feng - Sun Microsystems - Beijing China 		if (ic->ic_des_esslen) {
35717efa17f5Sfei feng - Sun Microsystems - Beijing China 			if (sc->sc_flags & IWH_F_RUNNING) {
35727efa17f5Sfei feng - Sun Microsystems - Beijing China 				iwh_m_stop(sc);
35737efa17f5Sfei feng - Sun Microsystems - Beijing China 				(void) iwh_m_start(sc);
35747efa17f5Sfei feng - Sun Microsystems - Beijing China 				(void) ieee80211_new_state(ic,
35757efa17f5Sfei feng - Sun Microsystems - Beijing China 				    IEEE80211_S_SCAN, -1);
35767efa17f5Sfei feng - Sun Microsystems - Beijing China 			}
35777efa17f5Sfei feng - Sun Microsystems - Beijing China 		}
35787efa17f5Sfei feng - Sun Microsystems - Beijing China 		err = 0;
35797efa17f5Sfei feng - Sun Microsystems - Beijing China 	}
35807efa17f5Sfei feng - Sun Microsystems - Beijing China 	return (err);
35817efa17f5Sfei feng - Sun Microsystems - Beijing China }
35827efa17f5Sfei feng - Sun Microsystems - Beijing China 
35837efa17f5Sfei feng - Sun Microsystems - Beijing China /*
3584c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * invoked by GLD supply statistics NIC and driver
3585c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
3586c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
3587c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_m_stat(void *arg, uint_t stat, uint64_t *val)
3588c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
3589e2cf88acSQuaker Fang 	iwh_sc_t *sc;
3590e2cf88acSQuaker Fang 	ieee80211com_t *ic;
35916cf34271Spengcheng chen - Sun Microsystems - Beijing China 	ieee80211_node_t *in;
3592c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3593e2cf88acSQuaker Fang 	if (NULL == arg) {
3594e2cf88acSQuaker Fang 		return (EINVAL);
3595e2cf88acSQuaker Fang 	}
3596e2cf88acSQuaker Fang 	sc = (iwh_sc_t *)arg;
3597e2cf88acSQuaker Fang 	ic = &sc->sc_ic;
3598e2cf88acSQuaker Fang 
3599c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mutex_enter(&sc->sc_glock);
3600c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3601c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	switch (stat) {
3602c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_IFSPEED:
36036cf34271Spengcheng chen - Sun Microsystems - Beijing China 		in = ic->ic_bss;
3604c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		*val = ((IEEE80211_FIXED_RATE_NONE == ic->ic_fixed_rate) ?
36056cf34271Spengcheng chen - Sun Microsystems - Beijing China 		    IEEE80211_RATE(in->in_txrate) :
3606c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    ic->ic_fixed_rate) / 2 * 1000000;
3607c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
3608c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3609c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_NOXMTBUF:
3610c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		*val = sc->sc_tx_nobuf;
3611c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
3612c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3613c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_NORCVBUF:
3614c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		*val = sc->sc_rx_nobuf;
3615c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
3616c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3617c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_IERRORS:
3618c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		*val = sc->sc_rx_err;
3619c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
3620c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3621c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_RBYTES:
3622c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		*val = ic->ic_stats.is_rx_bytes;
3623c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
3624c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3625c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_IPACKETS:
3626c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		*val = ic->ic_stats.is_rx_frags;
3627c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
3628c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3629c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_OBYTES:
3630c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		*val = ic->ic_stats.is_tx_bytes;
3631c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
3632c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3633c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_OPACKETS:
3634c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		*val = ic->ic_stats.is_tx_frags;
3635c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
3636c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3637c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_OERRORS:
3638c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_TX_FAILED:
3639c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		*val = sc->sc_tx_err;
3640c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
3641c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3642c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_TX_RETRANS:
3643c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		*val = sc->sc_tx_retries;
3644c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
3645c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3646c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_FCS_ERRORS:
3647c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_WEP_ERRORS:
3648c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_TX_FRAGS:
3649c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_MCAST_TX:
3650c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_RTS_SUCCESS:
3651c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_RTS_FAILURE:
3652c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_ACK_FAILURE:
3653c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_RX_FRAGS:
3654c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_MCAST_RX:
3655c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_RX_DUPS:
3656c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		mutex_exit(&sc->sc_glock);
3657c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (ieee80211_stat(ic, stat, val));
3658c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3659c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	default:
3660c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		mutex_exit(&sc->sc_glock);
3661c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (ENOTSUP);
3662c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
3663c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3664c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mutex_exit(&sc->sc_glock);
3665c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3666c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (IWH_SUCCESS);
3667c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
3668c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3669c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
3670c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * invoked by GLD to start or open NIC
3671c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
3672c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
3673c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_m_start(void *arg)
3674c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
3675e2cf88acSQuaker Fang 	iwh_sc_t *sc;
3676e2cf88acSQuaker Fang 	ieee80211com_t *ic;
3677e2cf88acSQuaker Fang 	int err = IWH_FAIL;
3678e2cf88acSQuaker Fang 
3679e2cf88acSQuaker Fang 	if (NULL == arg) {
3680e2cf88acSQuaker Fang 		return (EINVAL);
3681e2cf88acSQuaker Fang 	}
3682e2cf88acSQuaker Fang 	sc = (iwh_sc_t *)arg;
3683e2cf88acSQuaker Fang 	ic = &sc->sc_ic;
3684c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3685c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_init(sc);
3686c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != IWH_SUCCESS) {
3687c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		/*
3688c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * The hw init err(eg. RF is OFF). Return Success to make
3689c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * the 'plumb' succeed. The iwh_thread() tries to re-init
3690c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * background.
3691c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 */
369289b2a9fbSfei feng - Sun Microsystems - Beijing China 		atomic_or_32(&sc->sc_flags, IWH_F_HW_ERR_RECOVER);
3693c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (IWH_SUCCESS);
3694c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
3695c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3696c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
3697c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
369889b2a9fbSfei feng - Sun Microsystems - Beijing China 	atomic_or_32(&sc->sc_flags, IWH_F_RUNNING);
3699c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3700c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (IWH_SUCCESS);
3701c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
3702c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3703c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
3704c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * invoked by GLD to stop or down NIC
3705c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
3706c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
3707c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_m_stop(void *arg)
3708c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
3709e2cf88acSQuaker Fang 	iwh_sc_t *sc;
3710e2cf88acSQuaker Fang 	ieee80211com_t *ic;
3711e2cf88acSQuaker Fang 
3712e2cf88acSQuaker Fang 	if (NULL == arg) {
3713e2cf88acSQuaker Fang 		return;
3714e2cf88acSQuaker Fang 	}
3715e2cf88acSQuaker Fang 	sc = (iwh_sc_t *)arg;
3716e2cf88acSQuaker Fang 	ic = &sc->sc_ic;
3717c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3718c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_stop(sc);
3719c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3720c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
3721c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * release buffer for calibration
3722c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
3723c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_release_calib_buffer(sc);
3724c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3725c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
3726c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
372789b2a9fbSfei feng - Sun Microsystems - Beijing China 	atomic_and_32(&sc->sc_flags, ~IWH_F_HW_ERR_RECOVER);
372889b2a9fbSfei feng - Sun Microsystems - Beijing China 	atomic_and_32(&sc->sc_flags, ~IWH_F_RATE_AUTO_CTL);
3729e2cf88acSQuaker Fang 
373089b2a9fbSfei feng - Sun Microsystems - Beijing China 	atomic_and_32(&sc->sc_flags, ~IWH_F_RUNNING);
373189b2a9fbSfei feng - Sun Microsystems - Beijing China 	atomic_and_32(&sc->sc_flags, ~IWH_F_SCANNING);
3732c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
3733c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3734c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
3735c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * invoked by GLD to configure NIC
3736c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
3737c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
3738c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_m_unicst(void *arg, const uint8_t *macaddr)
3739c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
3740e2cf88acSQuaker Fang 	iwh_sc_t *sc;
3741e2cf88acSQuaker Fang 	ieee80211com_t *ic;
3742e2cf88acSQuaker Fang 	int err = IWH_SUCCESS;
3743e2cf88acSQuaker Fang 
3744e2cf88acSQuaker Fang 	if (NULL == arg) {
3745e2cf88acSQuaker Fang 		return (EINVAL);
3746e2cf88acSQuaker Fang 	}
3747e2cf88acSQuaker Fang 	sc = (iwh_sc_t *)arg;
3748e2cf88acSQuaker Fang 	ic = &sc->sc_ic;
3749c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3750c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (!IEEE80211_ADDR_EQ(ic->ic_macaddr, macaddr)) {
3751c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		IEEE80211_ADDR_COPY(ic->ic_macaddr, macaddr);
3752c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		mutex_enter(&sc->sc_glock);
3753c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		err = iwh_config(sc);
3754c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		mutex_exit(&sc->sc_glock);
3755c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (err != IWH_SUCCESS) {
3756c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			cmn_err(CE_WARN, "iwh_m_unicst(): "
3757c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			    "failed to configure device\n");
3758c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			goto fail;
3759c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
3760c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
3761c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3762c7ee0b5cSfei feng - Sun Microsystems - Beijing China fail:
3763c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (err);
3764c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
3765c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3766e2cf88acSQuaker Fang /* ARGSUSED */
3767c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
3768c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_m_multicst(void *arg, boolean_t add, const uint8_t *m)
3769c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
3770c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (IWH_SUCCESS);
3771c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
3772c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3773e2cf88acSQuaker Fang /* ARGSUSED */
3774c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
3775c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_m_promisc(void *arg, boolean_t on)
3776c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
3777c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (IWH_SUCCESS);
3778c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
3779c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3780c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
3781c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * kernel thread to deal with exceptional situation
3782c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
3783c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
3784c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_thread(iwh_sc_t *sc)
3785c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
3786c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ieee80211com_t *ic = &sc->sc_ic;
3787c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	clock_t clk;
3788c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	int err, n = 0, timeout = 0;
3789c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint32_t tmp;
3790c7ee0b5cSfei feng - Sun Microsystems - Beijing China #ifdef	DEBUG
3791c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	int times = 0;
3792c7ee0b5cSfei feng - Sun Microsystems - Beijing China #endif
3793c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3794c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	while (sc->sc_mf_thread_switch) {
3795c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		tmp = IWH_READ(sc, CSR_GP_CNTRL);
3796c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (tmp & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) {
379789b2a9fbSfei feng - Sun Microsystems - Beijing China 			atomic_and_32(&sc->sc_flags, ~IWH_F_RADIO_OFF);
3798c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		} else {
379989b2a9fbSfei feng - Sun Microsystems - Beijing China 			atomic_or_32(&sc->sc_flags, IWH_F_RADIO_OFF);
3800c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
3801c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3802c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		/*
3803c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * If  in SUSPEND or the RF is OFF, do nothing.
3804c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 */
3805e2cf88acSQuaker Fang 		if (sc->sc_flags & IWH_F_RADIO_OFF) {
3806c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			delay(drv_usectohz(100000));
3807c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			continue;
3808c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
3809c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3810c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		/*
3811c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * recovery fatal error
3812c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 */
3813c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (ic->ic_mach &&
3814c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    (sc->sc_flags & IWH_F_HW_ERR_RECOVER)) {
3815c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3816e2cf88acSQuaker Fang 			IWH_DBG((IWH_DEBUG_FW, "iwh_thread(): "
3817c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			    "try to recover fatal hw error: %d\n", times++));
3818c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3819c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			iwh_stop(sc);
3820c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
38216f12def4Spengcheng chen - Sun Microsystems - Beijing China 			if (IWH_CHK_FAST_RECOVER(sc)) {
382289b2a9fbSfei feng - Sun Microsystems - Beijing China 				/*
382389b2a9fbSfei feng - Sun Microsystems - Beijing China 				 * save runtime configuration
382489b2a9fbSfei feng - Sun Microsystems - Beijing China 				 */
38256f12def4Spengcheng chen - Sun Microsystems - Beijing China 				bcopy(&sc->sc_config, &sc->sc_config_save,
38266f12def4Spengcheng chen - Sun Microsystems - Beijing China 				    sizeof (sc->sc_config));
38276f12def4Spengcheng chen - Sun Microsystems - Beijing China 			} else {
3828d5bd65e4Sfei feng - Sun Microsystems - Beijing China 				ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
3829c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				delay(drv_usectohz(2000000 + n*500000));
38306f12def4Spengcheng chen - Sun Microsystems - Beijing China 			}
3831c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3832c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			err = iwh_init(sc);
3833c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			if (err != IWH_SUCCESS) {
3834c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				n++;
3835c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				if (n < 20) {
3836c7ee0b5cSfei feng - Sun Microsystems - Beijing China 					continue;
3837c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				}
3838c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			}
3839c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3840c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			n = 0;
3841c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			if (!err) {
384289b2a9fbSfei feng - Sun Microsystems - Beijing China 				atomic_or_32(&sc->sc_flags, IWH_F_RUNNING);
3843c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			}
3844c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
38456f12def4Spengcheng chen - Sun Microsystems - Beijing China 
38466f12def4Spengcheng chen - Sun Microsystems - Beijing China 			if (!IWH_CHK_FAST_RECOVER(sc) ||
38476f12def4Spengcheng chen - Sun Microsystems - Beijing China 			    iwh_fast_recover(sc) != IWH_SUCCESS) {
384889b2a9fbSfei feng - Sun Microsystems - Beijing China 				atomic_and_32(&sc->sc_flags,
384989b2a9fbSfei feng - Sun Microsystems - Beijing China 				    ~IWH_F_HW_ERR_RECOVER);
3850c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3851c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				delay(drv_usectohz(2000000));
3852e2cf88acSQuaker Fang 				if (sc->sc_ostate != IEEE80211_S_INIT) {
38536f12def4Spengcheng chen - Sun Microsystems - Beijing China 					ieee80211_new_state(ic,
38546f12def4Spengcheng chen - Sun Microsystems - Beijing China 					    IEEE80211_S_SCAN, 0);
3855c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				}
38566f12def4Spengcheng chen - Sun Microsystems - Beijing China 			}
3857d40f4da4Spengcheng chen - Sun Microsystems - Beijing China 		}
3858d40f4da4Spengcheng chen - Sun Microsystems - Beijing China 
3859d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		if (ic->ic_mach &&
3860d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		    (sc->sc_flags & IWH_F_SCANNING) && sc->sc_scan_pending) {
3861e2cf88acSQuaker Fang 			IWH_DBG((IWH_DEBUG_SCAN, "iwh_thread(): "
3862d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			    "wait for probe response\n"));
3863d5bd65e4Sfei feng - Sun Microsystems - Beijing China 
3864d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			sc->sc_scan_pending--;
3865d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			delay(drv_usectohz(200000));
3866d5bd65e4Sfei feng - Sun Microsystems - Beijing China 			ieee80211_next_scan(ic);
3867d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		}
3868d5bd65e4Sfei feng - Sun Microsystems - Beijing China 
3869c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		/*
3870c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * rate ctl
3871c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 */
3872c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (ic->ic_mach &&
3873c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    (sc->sc_flags & IWH_F_RATE_AUTO_CTL)) {
3874c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			clk = ddi_get_lbolt();
3875e2cf88acSQuaker Fang 			if (clk > sc->sc_clk + drv_usectohz(1000000)) {
3876c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				iwh_amrr_timeout(sc);
3877c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			}
3878c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
3879c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3880216e0daaSQuaker Fang 		if ((ic->ic_state == IEEE80211_S_RUN) &&
3881216e0daaSQuaker Fang 		    (ic->ic_beaconmiss++ > 100)) {	/* 10 seconds */
3882216e0daaSQuaker Fang 			cmn_err(CE_WARN, "iwh: beacon missed for 10 seconds\n");
3883216e0daaSQuaker Fang 			(void) ieee80211_new_state(ic,
3884216e0daaSQuaker Fang 			    IEEE80211_S_INIT, -1);
3885216e0daaSQuaker Fang 		}
3886216e0daaSQuaker Fang 
3887c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		delay(drv_usectohz(100000));
3888c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3889e2cf88acSQuaker Fang 		mutex_enter(&sc->sc_mt_lock);
3890c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (sc->sc_tx_timer) {
3891c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			timeout++;
3892c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			if (10 == timeout) {
3893c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				sc->sc_tx_timer--;
3894c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				if (0 == sc->sc_tx_timer) {
389589b2a9fbSfei feng - Sun Microsystems - Beijing China 					atomic_or_32(&sc->sc_flags,
389689b2a9fbSfei feng - Sun Microsystems - Beijing China 					    IWH_F_HW_ERR_RECOVER);
3897c7ee0b5cSfei feng - Sun Microsystems - Beijing China 					sc->sc_ostate = IEEE80211_S_RUN;
3898e2cf88acSQuaker Fang 					IWH_DBG((IWH_DEBUG_FW, "iwh_thread(): "
3899e2cf88acSQuaker Fang 					    "try to recover from "
3900e2cf88acSQuaker Fang 					    "send fail\n"));
3901c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				}
3902c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				timeout = 0;
3903c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			}
3904c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
3905e2cf88acSQuaker Fang 		mutex_exit(&sc->sc_mt_lock);
3906c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
3907c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3908e2cf88acSQuaker Fang 	mutex_enter(&sc->sc_mt_lock);
3909c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_mf_thread = NULL;
3910c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	cv_signal(&sc->sc_mt_cv);
3911c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mutex_exit(&sc->sc_mt_lock);
3912c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
3913c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3914c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
3915c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * Send a command to the ucode.
3916c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
3917c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
3918c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_cmd(iwh_sc_t *sc, int code, const void *buf, int size, int async)
3919c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
3920c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_tx_ring_t *ring = &sc->sc_txq[IWH_CMD_QUEUE_NUM];
3921c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_tx_desc_t *desc;
3922c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_cmd_t *cmd;
3923c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3924c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ASSERT(size <= sizeof (cmd->data));
3925c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ASSERT(mutex_owned(&sc->sc_glock));
3926c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3927e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_CMD, "iwh_cmd() "
3928e2cf88acSQuaker Fang 	    "code[%d]", code));
3929c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	desc = ring->data[ring->cur].desc;
3930c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	cmd = ring->data[ring->cur].cmd;
3931c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3932c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	cmd->hdr.type = (uint8_t)code;
3933c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	cmd->hdr.flags = 0;
3934c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	cmd->hdr.qid = ring->qid;
3935c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	cmd->hdr.idx = ring->cur;
393689b2a9fbSfei feng - Sun Microsystems - Beijing China 	bcopy(buf, cmd->data, size);
3937c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) memset(desc, 0, sizeof (*desc));
3938c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3939b510adaeSfei feng - Sun Microsystems - Beijing China 	desc->val0 = 1 << 24;
3940c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	desc->pa[0].tb1_addr =
3941c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    (uint32_t)(ring->data[ring->cur].paddr_cmd & 0xffffffff);
3942c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	desc->pa[0].val1 = ((4 + size) << 4) & 0xfff0;
3943c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3944e2cf88acSQuaker Fang 	if (async) {
3945e2cf88acSQuaker Fang 		sc->sc_cmd_accum++;
3946e2cf88acSQuaker Fang 	}
3947e2cf88acSQuaker Fang 
3948c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
3949c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * kick cmd ring XXX
3950c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
3951c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_shared->queues_byte_cnt_tbls[ring->qid].
3952c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    tfd_offset[ring->cur].val = 8;
3953c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (ring->cur < IWH_MAX_WIN_SIZE) {
3954c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_shared->queues_byte_cnt_tbls[ring->qid].
3955c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    tfd_offset[IWH_QUEUE_SIZE + ring->cur].val = 8;
3956c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
3957c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ring->cur = (ring->cur + 1) % ring->count;
3958c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur);
3959c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3960c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (async) {
3961c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (IWH_SUCCESS);
3962c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	} else {
3963c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		clock_t clk;
3964e2cf88acSQuaker Fang 
3965c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		clk = ddi_get_lbolt() + drv_usectohz(2000000);
3966e2cf88acSQuaker Fang 		while (sc->sc_cmd_flag != SC_CMD_FLG_DONE) {
3967c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			if (cv_timedwait(&sc->sc_cmd_cv,
3968c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			    &sc->sc_glock, clk) < 0) {
3969c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				break;
3970c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			}
3971c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
3972c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3973e2cf88acSQuaker Fang 		if (SC_CMD_FLG_DONE == sc->sc_cmd_flag) {
3974e2cf88acSQuaker Fang 			sc->sc_cmd_flag = SC_CMD_FLG_NONE;
3975c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			return (IWH_SUCCESS);
3976c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		} else {
3977e2cf88acSQuaker Fang 			sc->sc_cmd_flag = SC_CMD_FLG_NONE;
3978c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			return (IWH_FAIL);
3979c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
3980c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
3981c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
3982c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3983c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
3984c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * require ucode seting led of NIC
3985c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
3986c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
3987c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_set_led(iwh_sc_t *sc, uint8_t id, uint8_t off, uint8_t on)
3988c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
3989c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_led_cmd_t led;
3990c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3991c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	led.interval = LE_32(100000);	/* unit: 100ms */
3992c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	led.id = id;
3993c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	led.off = off;
3994c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	led.on = on;
3995c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3996c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) iwh_cmd(sc, REPLY_LEDS_CMD, &led, sizeof (led), 1);
3997c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
3998c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
3999c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
4000c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * necessary setting to NIC before authentication
4001c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
4002c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
4003c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_hw_set_before_auth(iwh_sc_t *sc)
4004c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
4005c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ieee80211com_t *ic = &sc->sc_ic;
4006c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ieee80211_node_t *in = ic->ic_bss;
4007e2cf88acSQuaker Fang 	int err = IWH_FAIL;
4008c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4009c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4010c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * update adapter's configuration according
4011c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * the info of target AP
4012c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4013c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IEEE80211_ADDR_COPY(sc->sc_config.bssid, in->in_bssid);
4014b510adaeSfei feng - Sun Microsystems - Beijing China 	sc->sc_config.chan = LE_16(ieee80211_chan2ieee(ic, in->in_chan));
4015e2cf88acSQuaker Fang 
4016e2cf88acSQuaker Fang 	if (ic->ic_curmode != IEEE80211_MODE_11NG) {
4017e2cf88acSQuaker Fang 
4018e2cf88acSQuaker Fang 		sc->sc_config.ofdm_ht_triple_stream_basic_rates = 0;
4019e2cf88acSQuaker Fang 		sc->sc_config.ofdm_ht_dual_stream_basic_rates = 0;
4020e2cf88acSQuaker Fang 		sc->sc_config.ofdm_ht_single_stream_basic_rates = 0;
4021e2cf88acSQuaker Fang 
4022c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (IEEE80211_MODE_11B == ic->ic_curmode) {
4023c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			sc->sc_config.cck_basic_rates  = 0x03;
4024c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			sc->sc_config.ofdm_basic_rates = 0;
4025c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		} else if ((in->in_chan != IEEE80211_CHAN_ANYC) &&
4026c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    (IEEE80211_IS_CHAN_5GHZ(in->in_chan))) {
4027c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			sc->sc_config.cck_basic_rates  = 0;
4028c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			sc->sc_config.ofdm_basic_rates = 0x15;
4029c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		} else { /* assume 802.11b/g */
4030c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			sc->sc_config.cck_basic_rates  = 0x0f;
4031c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			sc->sc_config.ofdm_basic_rates = 0xff;
4032c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
4033e2cf88acSQuaker Fang 	}
4034c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4035c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_config.flags &= ~LE_32(RXON_FLG_SHORT_PREAMBLE_MSK |
4036c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    RXON_FLG_SHORT_SLOT_MSK);
4037c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4038c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (ic->ic_flags & IEEE80211_F_SHSLOT) {
4039c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_config.flags |= LE_32(RXON_FLG_SHORT_SLOT_MSK);
4040c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	} else {
4041c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_config.flags &= LE_32(~RXON_FLG_SHORT_SLOT_MSK);
4042c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4043c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4044c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) {
4045c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_config.flags |= LE_32(RXON_FLG_SHORT_PREAMBLE_MSK);
4046c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	} else {
4047c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_config.flags &= LE_32(~RXON_FLG_SHORT_PREAMBLE_MSK);
4048c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4049c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4050e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_80211, "iwh_hw_set_before_auth(): "
4051e2cf88acSQuaker Fang 	    "config chan %d flags %x "
4052c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    "filter_flags %x  cck %x ofdm %x"
4053c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    " bssid:%02x:%02x:%02x:%02x:%02x:%2x\n",
4054b510adaeSfei feng - Sun Microsystems - Beijing China 	    LE_16(sc->sc_config.chan), LE_32(sc->sc_config.flags),
4055b510adaeSfei feng - Sun Microsystems - Beijing China 	    LE_32(sc->sc_config.filter_flags),
4056c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    sc->sc_config.cck_basic_rates, sc->sc_config.ofdm_basic_rates,
4057c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    sc->sc_config.bssid[0], sc->sc_config.bssid[1],
4058c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    sc->sc_config.bssid[2], sc->sc_config.bssid[3],
4059c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    sc->sc_config.bssid[4], sc->sc_config.bssid[5]));
4060c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4061c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_cmd(sc, REPLY_RXON, &sc->sc_config,
4062c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    sizeof (iwh_rxon_cmd_t), 1);
4063c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != IWH_SUCCESS) {
4064c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_hw_set_before_auth(): "
4065c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to config chan%d\n", sc->sc_config.chan);
4066c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (err);
4067c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4068c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
406989b2a9fbSfei feng - Sun Microsystems - Beijing China 	if ((sc->sc_dev_id != 0x423c) &&
407089b2a9fbSfei feng - Sun Microsystems - Beijing China 	    (sc->sc_dev_id != 0x423d)) {
4071c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		err = iwh_tx_power_table(sc, 1);
4072c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (err != IWH_SUCCESS) {
4073c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			return (err);
4074c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
407589b2a9fbSfei feng - Sun Microsystems - Beijing China 	}
4076c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4077c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4078c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * add default AP node
4079c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4080e2cf88acSQuaker Fang 	err = iwh_add_ap_sta(sc);
4081c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != IWH_SUCCESS) {
4082c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (err);
4083c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4084c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
408589b2a9fbSfei feng - Sun Microsystems - Beijing China 	if ((sc->sc_dev_id != 0x423c) &&
408689b2a9fbSfei feng - Sun Microsystems - Beijing China 	    (sc->sc_dev_id != 0x423d)) {
4087c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		/*
4088e2cf88acSQuaker Fang 		 * set up retry rate table for AP node
4089c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 */
4090e2cf88acSQuaker Fang 		err = iwh_ap_lq(sc);
4091c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (err != IWH_SUCCESS) {
4092c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			return (err);
4093c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
409489b2a9fbSfei feng - Sun Microsystems - Beijing China 	}
4095c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4096e2cf88acSQuaker Fang 	return (err);
4097c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
4098c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4099c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
4100c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * Send a scan request(assembly scan cmd) to the firmware.
4101c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
4102c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
4103c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_scan(iwh_sc_t *sc)
4104c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
4105c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ieee80211com_t *ic = &sc->sc_ic;
4106c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_tx_ring_t *ring = &sc->sc_txq[IWH_CMD_QUEUE_NUM];
4107c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_tx_desc_t *desc;
4108c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_tx_data_t *data;
4109c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_cmd_t *cmd;
4110c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_scan_hdr_t *hdr;
4111b510adaeSfei feng - Sun Microsystems - Beijing China 	iwh_scan_chan_t chan;
4112c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	struct ieee80211_frame *wh;
4113c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ieee80211_node_t *in = ic->ic_bss;
4114d5bd65e4Sfei feng - Sun Microsystems - Beijing China 	uint8_t essid[IEEE80211_NWID_LEN+1];
4115c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	struct ieee80211_rateset *rs;
4116c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	enum ieee80211_phymode mode;
4117c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint8_t *frm;
4118c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	int i, pktlen, nrates;
4119c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4120c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	data = &ring->data[ring->cur];
4121c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	desc = data->desc;
4122c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	cmd = (iwh_cmd_t *)data->dma_data.mem_va;
4123c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4124c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	cmd->hdr.type = REPLY_SCAN_CMD;
4125c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	cmd->hdr.flags = 0;
4126c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	cmd->hdr.qid = ring->qid;
4127c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	cmd->hdr.idx = ring->cur | 0x40;
4128c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4129c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	hdr = (iwh_scan_hdr_t *)cmd->data;
4130c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) memset(hdr, 0, sizeof (iwh_scan_hdr_t));
4131d5bd65e4Sfei feng - Sun Microsystems - Beijing China 	hdr->nchan = 1;
4132d5bd65e4Sfei feng - Sun Microsystems - Beijing China 	hdr->quiet_time = LE_16(50);
4133c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	hdr->quiet_plcp_th = LE_16(1);
4134c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4135b510adaeSfei feng - Sun Microsystems - Beijing China 	hdr->flags = LE_32(RXON_FLG_BAND_24G_MSK);
4136b510adaeSfei feng - Sun Microsystems - Beijing China 	hdr->rx_chain = LE_16(RXON_RX_CHAIN_DRIVER_FORCE_MSK |
4137b510adaeSfei feng - Sun Microsystems - Beijing China 	    (0x7 << RXON_RX_CHAIN_VALID_POS) |
4138c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    (0x2 << RXON_RX_CHAIN_FORCE_SEL_POS) |
4139c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    (0x2 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS));
4140c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4141c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	hdr->tx_cmd.tx_flags = LE_32(TX_CMD_FLG_SEQ_CTL_MSK);
4142c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	hdr->tx_cmd.sta_id = IWH_BROADCAST_ID;
4143b510adaeSfei feng - Sun Microsystems - Beijing China 	hdr->tx_cmd.stop_time.life_time = LE_32(0xffffffff);
4144b510adaeSfei feng - Sun Microsystems - Beijing China 	hdr->tx_cmd.rate.r.rate_n_flags = LE_32(iwh_rate_to_plcp(2));
4145c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	hdr->tx_cmd.rate.r.rate_n_flags |=
4146b510adaeSfei feng - Sun Microsystems - Beijing China 	    LE_32(RATE_MCS_ANT_B_MSK |RATE_MCS_CCK_MSK);
4147c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	hdr->direct_scan[0].len = ic->ic_des_esslen;
4148c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	hdr->direct_scan[0].id  = IEEE80211_ELEMID_SSID;
4149c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4150b510adaeSfei feng - Sun Microsystems - Beijing China 	hdr->filter_flags = LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
4151b510adaeSfei feng - Sun Microsystems - Beijing China 	    RXON_FILTER_BCON_AWARE_MSK);
4152c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4153c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (ic->ic_des_esslen) {
4154d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		bcopy(ic->ic_des_essid, essid, ic->ic_des_esslen);
4155d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		essid[ic->ic_des_esslen] = '\0';
4156e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_SCAN, "iwh_scan(): "
4157e2cf88acSQuaker Fang 		    "directed scan %s\n", essid));
4158d5bd65e4Sfei feng - Sun Microsystems - Beijing China 
4159c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		bcopy(ic->ic_des_essid, hdr->direct_scan[0].ssid,
4160c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    ic->ic_des_esslen);
4161c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	} else {
4162c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		bzero(hdr->direct_scan[0].ssid,
4163c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    sizeof (hdr->direct_scan[0].ssid));
4164c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4165c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4166c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4167c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * a probe request frame is required after the REPLY_SCAN_CMD
4168c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4169c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	wh = (struct ieee80211_frame *)(hdr + 1);
4170c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
4171c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    IEEE80211_FC0_SUBTYPE_PROBE_REQ;
4172c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
4173c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) memset(wh->i_addr1, 0xff, 6);
4174c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_macaddr);
4175c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) memset(wh->i_addr3, 0xff, 6);
4176c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	*(uint16_t *)&wh->i_dur[0] = 0;
4177c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	*(uint16_t *)&wh->i_seq[0] = 0;
4178c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4179c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	frm = (uint8_t *)(wh + 1);
4180c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4181c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4182c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * essid IE
4183c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4184d5bd65e4Sfei feng - Sun Microsystems - Beijing China 	if (in->in_esslen) {
4185d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		bcopy(in->in_essid, essid, in->in_esslen);
4186d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		essid[in->in_esslen] = '\0';
4187e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_SCAN, "iwh_scan(): "
4188e2cf88acSQuaker Fang 		    "probe with ESSID %s\n",
4189d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		    essid));
4190d5bd65e4Sfei feng - Sun Microsystems - Beijing China 	}
4191c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	*frm++ = IEEE80211_ELEMID_SSID;
4192c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	*frm++ = in->in_esslen;
419389b2a9fbSfei feng - Sun Microsystems - Beijing China 	bcopy(in->in_essid, frm, in->in_esslen);
4194c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	frm += in->in_esslen;
4195c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4196c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mode = ieee80211_chan2mode(ic, ic->ic_curchan);
4197c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	rs = &ic->ic_sup_rates[mode];
4198c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4199c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4200c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * supported rates IE
4201c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4202c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	*frm++ = IEEE80211_ELEMID_RATES;
4203c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	nrates = rs->ir_nrates;
4204c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (nrates > IEEE80211_RATE_SIZE) {
4205c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		nrates = IEEE80211_RATE_SIZE;
4206c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4207c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4208c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	*frm++ = (uint8_t)nrates;
420989b2a9fbSfei feng - Sun Microsystems - Beijing China 	bcopy(rs->ir_rates, frm, nrates);
4210c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	frm += nrates;
4211c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4212c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4213c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * supported xrates IE
4214c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4215c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (rs->ir_nrates > IEEE80211_RATE_SIZE) {
4216c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		nrates = rs->ir_nrates - IEEE80211_RATE_SIZE;
4217c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		*frm++ = IEEE80211_ELEMID_XRATES;
4218c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		*frm++ = (uint8_t)nrates;
421989b2a9fbSfei feng - Sun Microsystems - Beijing China 		bcopy(rs->ir_rates + IEEE80211_RATE_SIZE, frm, nrates);
4220c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		frm += nrates;
4221c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4222c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4223c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4224c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * optionnal IE (usually for wpa)
4225c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4226c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (ic->ic_opt_ie != NULL) {
422789b2a9fbSfei feng - Sun Microsystems - Beijing China 		bcopy(ic->ic_opt_ie, frm, ic->ic_opt_ie_len);
4228c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		frm += ic->ic_opt_ie_len;
4229c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4230c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4231c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/* setup length of probe request */
4232b510adaeSfei feng - Sun Microsystems - Beijing China 	hdr->tx_cmd.len = LE_16(_PTRDIFF(frm, wh));
4233b510adaeSfei feng - Sun Microsystems - Beijing China 	hdr->len = LE_16(hdr->nchan * sizeof (iwh_scan_chan_t) +
4234b510adaeSfei feng - Sun Microsystems - Beijing China 	    LE_16(hdr->tx_cmd.len) + sizeof (iwh_scan_hdr_t));
4235c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4236c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4237c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * the attribute of the scan channels are required after the probe
4238c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * request frame.
4239c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4240b510adaeSfei feng - Sun Microsystems - Beijing China 	for (i = 1; i <= hdr->nchan; i++) {
4241d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		if (ic->ic_des_esslen) {
4242b510adaeSfei feng - Sun Microsystems - Beijing China 			chan.type = LE_32(3);
4243d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		} else {
4244b510adaeSfei feng - Sun Microsystems - Beijing China 			chan.type = LE_32(1);
4245d5bd65e4Sfei feng - Sun Microsystems - Beijing China 		}
4246d5bd65e4Sfei feng - Sun Microsystems - Beijing China 
4247b510adaeSfei feng - Sun Microsystems - Beijing China 		chan.chan = LE_16(ieee80211_chan2ieee(ic, ic->ic_curchan));
4248b510adaeSfei feng - Sun Microsystems - Beijing China 		chan.tpc.tx_gain = 0x28;
4249b510adaeSfei feng - Sun Microsystems - Beijing China 		chan.tpc.dsp_atten = 110;
4250b510adaeSfei feng - Sun Microsystems - Beijing China 		chan.active_dwell = LE_16(50);
4251b510adaeSfei feng - Sun Microsystems - Beijing China 		chan.passive_dwell = LE_16(120);
4252c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4253b510adaeSfei feng - Sun Microsystems - Beijing China 		bcopy(&chan, frm, sizeof (iwh_scan_chan_t));
4254c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		frm += sizeof (iwh_scan_chan_t);
4255c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4256c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4257c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	pktlen = _PTRDIFF(frm, cmd);
4258c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4259c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) memset(desc, 0, sizeof (*desc));
4260b510adaeSfei feng - Sun Microsystems - Beijing China 	desc->val0 = 1 << 24;
4261c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	desc->pa[0].tb1_addr =
4262c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    (uint32_t)(data->dma_data.cookie.dmac_address & 0xffffffff);
4263c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	desc->pa[0].val1 = (pktlen << 4) & 0xfff0;
4264c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4265c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4266c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * maybe for cmd, filling the byte cnt table is not necessary.
4267c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * anyway, we fill it here.
4268c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4269c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_shared->queues_byte_cnt_tbls[ring->qid]
4270c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    .tfd_offset[ring->cur].val = 8;
4271c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (ring->cur < IWH_MAX_WIN_SIZE) {
4272c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_shared->queues_byte_cnt_tbls[ring->qid].
4273c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    tfd_offset[IWH_QUEUE_SIZE + ring->cur].val = 8;
4274c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4275c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4276c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4277c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * kick cmd ring
4278c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4279c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ring->cur = (ring->cur + 1) % ring->count;
4280c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur);
4281c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4282c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (IWH_SUCCESS);
4283c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
4284c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4285c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
4286c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * configure NIC by using ucode commands after loading ucode.
4287c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
4288c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
4289c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_config(iwh_sc_t *sc)
4290c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
4291c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ieee80211com_t *ic = &sc->sc_ic;
4292c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_powertable_cmd_t powertable;
4293c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_bt_cmd_t bt;
4294c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_add_sta_t node;
4295c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_rem_sta_t rm_sta;
4296c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	const uint8_t bcast[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
4297c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_link_quality_cmd_t link_quality;
4298e2cf88acSQuaker Fang 	int i, err = IWH_FAIL;
4299c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint16_t masks = 0;
4300c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4301c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4302c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * set power mode. Disable power management at present, do it later
4303c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4304c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) memset(&powertable, 0, sizeof (powertable));
4305c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	powertable.flags = LE_16(0x8);
4306c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_cmd(sc, POWER_TABLE_CMD, &powertable,
4307c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    sizeof (powertable), 0);
4308c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != IWH_SUCCESS) {
4309c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_config(): "
4310c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to set power mode\n");
4311c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (err);
4312c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4313c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4314c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4315c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * configure bt coexistence
4316c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4317c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) memset(&bt, 0, sizeof (bt));
4318c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	bt.flags = 3;
4319c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	bt.lead_time = 0xaa;
4320c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	bt.max_kill = 1;
4321c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_cmd(sc, REPLY_BT_CONFIG, &bt,
4322c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    sizeof (bt), 0);
4323c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != IWH_SUCCESS) {
4324c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_config(): "
4325c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to configurate bt coexistence\n");
4326c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (err);
4327c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4328c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4329c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4330c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * configure rxon
4331c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4332c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) memset(&sc->sc_config, 0, sizeof (iwh_rxon_cmd_t));
4333c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IEEE80211_ADDR_COPY(sc->sc_config.node_addr, ic->ic_macaddr);
4334c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IEEE80211_ADDR_COPY(sc->sc_config.wlap_bssid, ic->ic_macaddr);
4335b510adaeSfei feng - Sun Microsystems - Beijing China 	sc->sc_config.chan = LE_16(ieee80211_chan2ieee(ic, ic->ic_curchan));
4336b510adaeSfei feng - Sun Microsystems - Beijing China 	sc->sc_config.flags = LE_32(RXON_FLG_BAND_24G_MSK);
4337e2cf88acSQuaker Fang 	sc->sc_config.flags &= LE_32(~(RXON_FLG_CHANNEL_MODE_MIXED_MSK |
4338e2cf88acSQuaker Fang 	    RXON_FLG_CHANNEL_MODE_PURE_40_MSK));
4339c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4340c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	switch (ic->ic_opmode) {
4341c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case IEEE80211_M_STA:
4342c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_config.dev_type = RXON_DEV_TYPE_ESS;
4343e2cf88acSQuaker Fang 		sc->sc_config.filter_flags |= LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
4344e2cf88acSQuaker Fang 		    RXON_FILTER_DIS_DECRYPT_MSK |
4345c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    RXON_FILTER_DIS_GRP_DECRYPT_MSK);
4346c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
4347c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4348c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case IEEE80211_M_IBSS:
4349c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case IEEE80211_M_AHDEMO:
4350c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_config.dev_type = RXON_DEV_TYPE_IBSS;
4351c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4352b510adaeSfei feng - Sun Microsystems - Beijing China 		sc->sc_config.flags |= LE_32(RXON_FLG_SHORT_PREAMBLE_MSK);
4353c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_config.filter_flags = LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
4354c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    RXON_FILTER_DIS_DECRYPT_MSK |
4355c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    RXON_FILTER_DIS_GRP_DECRYPT_MSK);
4356c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
4357c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4358c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case IEEE80211_M_HOSTAP:
4359c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_config.dev_type = RXON_DEV_TYPE_AP;
4360c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
4361c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4362c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case IEEE80211_M_MONITOR:
4363c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_config.dev_type = RXON_DEV_TYPE_SNIFFER;
4364c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_config.filter_flags |= LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
4365c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_PROMISC_MSK);
4366c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
4367c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4368c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4369e2cf88acSQuaker Fang 	/*
4370e2cf88acSQuaker Fang 	 * Support all CCK rates.
4371e2cf88acSQuaker Fang 	 */
4372c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_config.cck_basic_rates  = 0x0f;
4373e2cf88acSQuaker Fang 
4374e2cf88acSQuaker Fang 	/*
4375e2cf88acSQuaker Fang 	 * Support all OFDM rates.
4376e2cf88acSQuaker Fang 	 */
4377c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_config.ofdm_basic_rates = 0xff;
4378c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4379c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4380e2cf88acSQuaker Fang 	 * Determine HT supported rates.
4381c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4382e2cf88acSQuaker Fang 	switch (sc->sc_ht_conf.rx_stream_count) {
4383e2cf88acSQuaker Fang 	case 3:
4384e2cf88acSQuaker Fang 		sc->sc_config.ofdm_ht_triple_stream_basic_rates = 0xff;
4385e2cf88acSQuaker Fang 		sc->sc_config.ofdm_ht_dual_stream_basic_rates = 0xff;
4386e2cf88acSQuaker Fang 		sc->sc_config.ofdm_ht_single_stream_basic_rates = 0xff;
4387e2cf88acSQuaker Fang 		break;
4388e2cf88acSQuaker Fang 	case 2:
4389e2cf88acSQuaker Fang 		sc->sc_config.ofdm_ht_dual_stream_basic_rates = 0xff;
4390e2cf88acSQuaker Fang 		sc->sc_config.ofdm_ht_single_stream_basic_rates = 0xff;
4391e2cf88acSQuaker Fang 		break;
4392e2cf88acSQuaker Fang 	case 1:
4393e2cf88acSQuaker Fang 		sc->sc_config.ofdm_ht_single_stream_basic_rates = 0xff;
4394e2cf88acSQuaker Fang 		break;
4395e2cf88acSQuaker Fang 	default:
4396e2cf88acSQuaker Fang 		cmn_err(CE_WARN, "iwh_config(): "
4397e2cf88acSQuaker Fang 		    "RX stream count %d is not in suitable range\n",
4398e2cf88acSQuaker Fang 		    sc->sc_ht_conf.rx_stream_count);
4399e2cf88acSQuaker Fang 		return (IWH_FAIL);
4400e2cf88acSQuaker Fang 	}
4401e2cf88acSQuaker Fang 
4402e2cf88acSQuaker Fang 	/*
4403e2cf88acSQuaker Fang 	 * set RX chains/antennas.
4404e2cf88acSQuaker Fang 	 */
4405e2cf88acSQuaker Fang 	iwh_config_rxon_chain(sc);
4406c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4407c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_cmd(sc, REPLY_RXON, &sc->sc_config,
4408c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    sizeof (iwh_rxon_cmd_t), 0);
4409c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != IWH_SUCCESS) {
4410c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_config(): "
4411c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to set configure command\n");
4412c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (err);
4413c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4414c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4415c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4416c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * remove all nodes in NIC
4417c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4418c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) memset(&rm_sta, 0, sizeof (rm_sta));
4419c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	rm_sta.num_sta = 1;
442089b2a9fbSfei feng - Sun Microsystems - Beijing China 	bcopy(bcast, rm_sta.addr, 6);
4421c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4422c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_cmd(sc, REPLY_REMOVE_STA, &rm_sta, sizeof (iwh_rem_sta_t), 0);
4423c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != IWH_SUCCESS) {
4424c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_config(): "
4425c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to remove broadcast node in hardware.\n");
4426c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (err);
4427c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4428c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
442989b2a9fbSfei feng - Sun Microsystems - Beijing China 	if ((sc->sc_dev_id != 0x423c) &&
443089b2a9fbSfei feng - Sun Microsystems - Beijing China 	    (sc->sc_dev_id != 0x423d)) {
4431c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		/*
4432e2cf88acSQuaker Fang 		 * configure TX power table
4433c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 */
4434c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		err = iwh_tx_power_table(sc, 0);
4435c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (err != IWH_SUCCESS) {
4436c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			return (err);
4437c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
443889b2a9fbSfei feng - Sun Microsystems - Beijing China 	}
4439c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4440c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4441c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * add broadcast node so that we can send broadcast frame
4442c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4443c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) memset(&node, 0, sizeof (node));
4444c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) memset(node.sta.addr, 0xff, 6);
4445c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	node.mode = 0;
4446c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	node.sta.sta_id = IWH_BROADCAST_ID;
4447c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	node.station_flags = 0;
4448c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4449c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_cmd(sc, REPLY_ADD_STA, &node, sizeof (node), 0);
4450c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != IWH_SUCCESS) {
4451c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_config(): "
4452c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to add broadcast node\n");
4453c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (err);
4454c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4455c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
445689b2a9fbSfei feng - Sun Microsystems - Beijing China 	if ((sc->sc_dev_id != 0x423c) &&
445789b2a9fbSfei feng - Sun Microsystems - Beijing China 	    (sc->sc_dev_id != 0x423d)) {
4458c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		/*
4459c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * TX_LINK_QUALITY cmd
4460c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 */
4461c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		(void) memset(&link_quality, 0, sizeof (link_quality));
4462c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
4463c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			masks |= RATE_MCS_CCK_MSK;
4464c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			masks |= RATE_MCS_ANT_B_MSK;
4465c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			masks &= ~RATE_MCS_ANT_A_MSK;
4466b510adaeSfei feng - Sun Microsystems - Beijing China 			link_quality.rate_n_flags[i] =
4467b510adaeSfei feng - Sun Microsystems - Beijing China 			    LE_32(iwh_rate_to_plcp(2) | masks);
4468c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
4469c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4470c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		link_quality.general_params.single_stream_ant_msk = 2;
4471c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		link_quality.general_params.dual_stream_ant_msk = 3;
4472c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		link_quality.agg_params.agg_dis_start_th = 3;
4473c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		link_quality.agg_params.agg_time_limit = LE_16(4000);
4474c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		link_quality.sta_id = IWH_BROADCAST_ID;
4475c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		err = iwh_cmd(sc, REPLY_TX_LINK_QUALITY_CMD, &link_quality,
4476c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    sizeof (link_quality), 0);
4477c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (err != IWH_SUCCESS) {
4478c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			cmn_err(CE_WARN, "iwh_config(): "
4479c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			    "failed to config link quality table\n");
4480c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			return (err);
4481c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
448289b2a9fbSfei feng - Sun Microsystems - Beijing China 	}
4483c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4484e2cf88acSQuaker Fang 	return (err);
4485c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
4486c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4487faceed93Sfei feng - Sun Microsystems - Beijing China /*
4488faceed93Sfei feng - Sun Microsystems - Beijing China  * quiesce(9E) entry point.
4489faceed93Sfei feng - Sun Microsystems - Beijing China  * This function is called when the system is single-threaded at high
4490faceed93Sfei feng - Sun Microsystems - Beijing China  * PIL with preemption disabled. Therefore, this function must not be
4491faceed93Sfei feng - Sun Microsystems - Beijing China  * blocked.
4492faceed93Sfei feng - Sun Microsystems - Beijing China  * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
4493faceed93Sfei feng - Sun Microsystems - Beijing China  * DDI_FAILURE indicates an error condition and should almost never happen.
4494faceed93Sfei feng - Sun Microsystems - Beijing China  */
4495faceed93Sfei feng - Sun Microsystems - Beijing China static int
4496faceed93Sfei feng - Sun Microsystems - Beijing China iwh_quiesce(dev_info_t *dip)
4497faceed93Sfei feng - Sun Microsystems - Beijing China {
4498faceed93Sfei feng - Sun Microsystems - Beijing China 	iwh_sc_t *sc;
4499faceed93Sfei feng - Sun Microsystems - Beijing China 
4500faceed93Sfei feng - Sun Microsystems - Beijing China 	sc = ddi_get_soft_state(iwh_soft_state_p, ddi_get_instance(dip));
4501e2cf88acSQuaker Fang 	if (sc == NULL) {
4502faceed93Sfei feng - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
4503e2cf88acSQuaker Fang 	}
4504faceed93Sfei feng - Sun Microsystems - Beijing China 
4505faceed93Sfei feng - Sun Microsystems - Beijing China #ifdef DEBUG
450689b2a9fbSfei feng - Sun Microsystems - Beijing China 	/*
450789b2a9fbSfei feng - Sun Microsystems - Beijing China 	 * by pass any messages, if it's quiesce
450889b2a9fbSfei feng - Sun Microsystems - Beijing China 	 */
4509faceed93Sfei feng - Sun Microsystems - Beijing China 	iwh_dbg_flags = 0;
4510faceed93Sfei feng - Sun Microsystems - Beijing China #endif
4511faceed93Sfei feng - Sun Microsystems - Beijing China 
4512faceed93Sfei feng - Sun Microsystems - Beijing China 	/*
4513faceed93Sfei feng - Sun Microsystems - Beijing China 	 * No more blocking is allowed while we are in the
4514faceed93Sfei feng - Sun Microsystems - Beijing China 	 * quiesce(9E) entry point.
4515faceed93Sfei feng - Sun Microsystems - Beijing China 	 */
451689b2a9fbSfei feng - Sun Microsystems - Beijing China 	atomic_or_32(&sc->sc_flags, IWH_F_QUIESCED);
4517faceed93Sfei feng - Sun Microsystems - Beijing China 
4518faceed93Sfei feng - Sun Microsystems - Beijing China 	/*
4519faceed93Sfei feng - Sun Microsystems - Beijing China 	 * Disable and mask all interrupts.
4520faceed93Sfei feng - Sun Microsystems - Beijing China 	 */
4521faceed93Sfei feng - Sun Microsystems - Beijing China 	iwh_stop(sc);
4522faceed93Sfei feng - Sun Microsystems - Beijing China 
4523faceed93Sfei feng - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
4524faceed93Sfei feng - Sun Microsystems - Beijing China }
4525faceed93Sfei feng - Sun Microsystems - Beijing China 
4526c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
4527c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_stop_master(iwh_sc_t *sc)
4528c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
4529c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint32_t tmp;
4530c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	int n;
4531c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4532c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tmp = IWH_READ(sc, CSR_RESET);
4533c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_RESET, tmp | CSR_RESET_REG_FLAG_STOP_MASTER);
4534c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4535c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tmp = IWH_READ(sc, CSR_GP_CNTRL);
4536c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if ((tmp & CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE) ==
4537c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE) {
4538c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return;
4539c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4540c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4541c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	for (n = 0; n < 2000; n++) {
4542c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (IWH_READ(sc, CSR_RESET) &
4543c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    CSR_RESET_REG_FLAG_MASTER_DISABLED) {
4544c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			break;
4545c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
4546c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		DELAY(1000);
4547c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4548c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4549c7ee0b5cSfei feng - Sun Microsystems - Beijing China #ifdef	DEBUG
4550c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (2000 == n) {
4551e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_HW, "iwh_stop_master(): "
4552c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "timeout waiting for master stop\n"));
4553c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4554c7ee0b5cSfei feng - Sun Microsystems - Beijing China #endif
4555c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
4556c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4557c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
4558c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_power_up(iwh_sc_t *sc)
4559c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
4560c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint32_t tmp;
4561c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4562c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_mac_access_enter(sc);
4563c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tmp = iwh_reg_read(sc, ALM_APMG_PS_CTL);
4564c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tmp &= ~APMG_PS_CTRL_REG_MSK_POWER_SRC;
4565c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tmp |= APMG_PS_CTRL_REG_VAL_POWER_SRC_VMAIN;
4566c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_reg_write(sc, ALM_APMG_PS_CTL, tmp);
4567c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_mac_access_exit(sc);
4568c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4569c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	DELAY(5000);
4570c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (IWH_SUCCESS);
4571c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
4572c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4573c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
4574c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * hardware initialization
4575c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
4576c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
4577c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_preinit(iwh_sc_t *sc)
4578c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
4579c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	int n;
4580c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint8_t vlink;
4581c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint16_t radio_cfg;
4582b510adaeSfei feng - Sun Microsystems - Beijing China 	uint32_t tmp;
4583c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4584c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4585c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * clear any pending interrupts
4586c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4587c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_INT, 0xffffffff);
4588c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4589c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tmp = IWH_READ(sc, CSR_GIO_CHICKEN_BITS);
4590c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_GIO_CHICKEN_BITS,
4591c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    tmp | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
4592c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4593c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tmp = IWH_READ(sc, CSR_ANA_PLL_CFG);
4594c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_ANA_PLL_CFG, tmp | IWH_CSR_ANA_PLL_CFG);
4595c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4596c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tmp = IWH_READ(sc, CSR_GP_CNTRL);
4597c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_GP_CNTRL, tmp | CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
4598c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4599c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4600c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * wait for clock ready
4601c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4602c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	for (n = 0; n < 1000; n++) {
4603c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (IWH_READ(sc, CSR_GP_CNTRL) &
4604c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY) {
4605c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			break;
4606c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
4607c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		DELAY(10);
4608c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4609c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4610c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (1000 == n) {
4611c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (ETIMEDOUT);
4612c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4613c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4614c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_mac_access_enter(sc);
4615c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4616c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_reg_write(sc, ALM_APMG_CLK_EN, APMG_CLK_REG_VAL_DMA_CLK_RQT);
4617c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4618c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	DELAY(20);
4619c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tmp = iwh_reg_read(sc, ALM_APMG_PCIDEV_STT);
4620c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_reg_write(sc, ALM_APMG_PCIDEV_STT, tmp |
4621c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    APMG_DEV_STATE_REG_VAL_L1_ACTIVE_DISABLE);
4622c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_mac_access_exit(sc);
4623c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4624c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	radio_cfg = IWH_READ_EEP_SHORT(sc, EEP_SP_RADIO_CONFIGURATION);
4625c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (SP_RADIO_TYPE_MSK(radio_cfg) < SP_RADIO_TYPE_MAX) {
4626c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		tmp = IWH_READ(sc, CSR_HW_IF_CONFIG_REG);
4627c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		IWH_WRITE(sc, CSR_HW_IF_CONFIG_REG,
4628c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    tmp | SP_RADIO_TYPE_MSK(radio_cfg) |
4629c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    SP_RADIO_STEP_MSK(radio_cfg) |
4630c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    SP_RADIO_DASH_MSK(radio_cfg));
4631c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	} else {
4632c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_preinit(): "
4633c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "radio configuration information in eeprom is wrong\n");
4634c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (IWH_FAIL);
4635c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4636c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4637c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4638c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_INT_COALESCING, 512 / 32);
4639c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4640c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) iwh_power_up(sc);
4641c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4642c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if ((sc->sc_rev & 0x80) == 0x80 && (sc->sc_rev & 0x7f) < 8) {
4643c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		tmp = ddi_get32(sc->sc_cfg_handle,
4644c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    (uint32_t *)(sc->sc_cfg_base + 0xe8));
4645c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ddi_put32(sc->sc_cfg_handle,
4646c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    (uint32_t *)(sc->sc_cfg_base + 0xe8),
4647c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    tmp & ~(1 << 11));
4648c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4649c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4650c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	vlink = ddi_get8(sc->sc_cfg_handle,
4651c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    (uint8_t *)(sc->sc_cfg_base + 0xf0));
4652c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ddi_put8(sc->sc_cfg_handle, (uint8_t *)(sc->sc_cfg_base + 0xf0),
4653c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    vlink & ~2);
4654c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
465589b2a9fbSfei feng - Sun Microsystems - Beijing China 	tmp = IWH_READ(sc, CSR_HW_IF_CONFIG_REG);
4656c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tmp |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
4657c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    CSR_HW_IF_CONFIG_REG_BIT_MAC_SI;
4658c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_SW_VER, tmp);
4659c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4660c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4661c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * make sure power supply on each part of the hardware
4662c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4663c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_mac_access_enter(sc);
4664c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tmp = iwh_reg_read(sc, ALM_APMG_PS_CTL);
4665c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tmp |= APMG_PS_CTRL_REG_VAL_ALM_R_RESET_REQ;
4666c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_reg_write(sc, ALM_APMG_PS_CTL, tmp);
4667c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	DELAY(5);
4668c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4669c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tmp = iwh_reg_read(sc, ALM_APMG_PS_CTL);
4670c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tmp &= ~APMG_PS_CTRL_REG_VAL_ALM_R_RESET_REQ;
4671c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_reg_write(sc, ALM_APMG_PS_CTL, tmp);
4672c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_mac_access_exit(sc);
4673c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4674c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (IWH_SUCCESS);
4675c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
4676c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4677c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
4678c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * set up semphore flag to own EEPROM
4679c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
4680c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
4681c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_eep_sem_down(iwh_sc_t *sc)
4682c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
4683c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	int count1, count2;
4684c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint32_t tmp;
4685c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4686c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	for (count1 = 0; count1 < 1000; count1++) {
4687c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		tmp = IWH_READ(sc, CSR_HW_IF_CONFIG_REG);
4688c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		IWH_WRITE(sc, CSR_HW_IF_CONFIG_REG,
4689c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    tmp | CSR_HW_IF_CONFIG_REG_EEP_SEM);
4690c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4691c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		for (count2 = 0; count2 < 2; count2++) {
4692c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			if (IWH_READ(sc, CSR_HW_IF_CONFIG_REG) &
4693c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			    CSR_HW_IF_CONFIG_REG_EEP_SEM) {
4694c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				return (IWH_SUCCESS);
4695c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			}
4696c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			DELAY(10000);
4697c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
4698c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
469989b2a9fbSfei feng - Sun Microsystems - Beijing China 
4700c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (IWH_FAIL);
4701c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
4702c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4703c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
4704c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * reset semphore flag to release EEPROM
4705c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
4706c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
4707c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_eep_sem_up(iwh_sc_t *sc)
4708c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
4709c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint32_t tmp;
4710c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4711c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tmp = IWH_READ(sc, CSR_HW_IF_CONFIG_REG);
4712c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_HW_IF_CONFIG_REG,
4713c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    tmp & (~CSR_HW_IF_CONFIG_REG_EEP_SEM));
4714c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
4715c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4716c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
4717c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * This function read all infomation from eeprom
4718c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
4719c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
4720c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_eep_load(iwh_sc_t *sc)
4721c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
4722c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	int i, rr;
4723c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint32_t rv, tmp, eep_gp;
4724c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint16_t addr, eep_sz = sizeof (sc->sc_eep_map);
4725c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint16_t *eep_p = (uint16_t *)&sc->sc_eep_map;
4726c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4727c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4728c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * read eeprom gp register in CSR
4729c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4730c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	eep_gp = IWH_READ(sc, CSR_EEPROM_GP);
4731c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if ((eep_gp & CSR_EEPROM_GP_VALID_MSK) ==
4732c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    CSR_EEPROM_GP_BAD_SIGNATURE) {
4733e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_EEPROM, "iwh_eep_load(): "
4734e2cf88acSQuaker Fang 		    "not find eeprom\n"));
4735c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (IWH_FAIL);
4736c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4737c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4738c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	rr = iwh_eep_sem_down(sc);
4739c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (rr != 0) {
4740e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_EEPROM, "iwh_eep_load(): "
4741e2cf88acSQuaker Fang 		    "driver failed to own EEPROM\n"));
4742c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (IWH_FAIL);
4743c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4744c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4745c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	for (addr = 0; addr < eep_sz; addr += 2) {
4746c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		IWH_WRITE(sc, CSR_EEPROM_REG, addr<<1);
4747c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		tmp = IWH_READ(sc, CSR_EEPROM_REG);
4748c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		IWH_WRITE(sc, CSR_EEPROM_REG, tmp & ~(0x2));
4749c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4750c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		for (i = 0; i < 10; i++) {
4751c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			rv = IWH_READ(sc, CSR_EEPROM_REG);
4752c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			if (rv & 1) {
4753c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				break;
4754c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			}
4755c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			DELAY(10);
4756c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
4757c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4758c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (!(rv & 1)) {
4759e2cf88acSQuaker Fang 			IWH_DBG((IWH_DEBUG_EEPROM, "iwh_eep_load(): "
4760c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			    "time out when read eeprome\n"));
4761c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			iwh_eep_sem_up(sc);
4762c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			return (IWH_FAIL);
4763c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
4764c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4765b510adaeSfei feng - Sun Microsystems - Beijing China 		eep_p[addr/2] = LE_16(rv >> 16);
4766c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4767c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4768c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_eep_sem_up(sc);
4769c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (IWH_SUCCESS);
4770c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
4771c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4772c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
4773c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * initialize mac address in ieee80211com_t struct
4774c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
4775c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
4776c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_get_mac_from_eep(iwh_sc_t *sc)
4777c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
4778c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ieee80211com_t *ic = &sc->sc_ic;
4779c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4780c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IEEE80211_ADDR_COPY(ic->ic_macaddr, &sc->sc_eep_map[EEP_MAC_ADDRESS]);
4781c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4782e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_EEPROM, "iwh_get_mac_from_eep(): "
4783e2cf88acSQuaker Fang 	    "mac:%2x:%2x:%2x:%2x:%2x:%2x\n",
4784c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    ic->ic_macaddr[0], ic->ic_macaddr[1], ic->ic_macaddr[2],
4785c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    ic->ic_macaddr[3], ic->ic_macaddr[4], ic->ic_macaddr[5]));
4786c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
4787c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4788c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
4789c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * main initialization function
4790c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
4791c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
4792c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_init(iwh_sc_t *sc)
4793c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
4794e2cf88acSQuaker Fang 	int err = IWH_FAIL;
4795c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	clock_t clk;
4796c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4797c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4798c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * release buffer for calibration
4799c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4800c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_release_calib_buffer(sc);
4801c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4802c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mutex_enter(&sc->sc_glock);
480389b2a9fbSfei feng - Sun Microsystems - Beijing China 	atomic_and_32(&sc->sc_flags, ~IWH_F_FW_INIT);
4804c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4805c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_init_common(sc);
4806c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != IWH_SUCCESS) {
4807c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		mutex_exit(&sc->sc_glock);
4808c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (IWH_FAIL);
4809c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4810c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4811c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4812c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * backup ucode data part for future use.
4813c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
481489b2a9fbSfei feng - Sun Microsystems - Beijing China 	bcopy(sc->sc_dma_fw_data.mem_va,
481589b2a9fbSfei feng - Sun Microsystems - Beijing China 	    sc->sc_dma_fw_data_bak.mem_va,
4816c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    sc->sc_dma_fw_data.alength);
4817c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4818c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/* load firmware init segment into NIC */
4819c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_load_init_firmware(sc);
4820c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != IWH_SUCCESS) {
4821c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_init(): "
4822c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to setup init firmware\n");
4823e2cf88acSQuaker Fang 		mutex_exit(&sc->sc_glock);
4824e2cf88acSQuaker Fang 		return (IWH_FAIL);
4825c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4826c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4827c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4828c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * now press "execute" start running
4829c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4830c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_RESET, 0);
4831c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4832c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	clk = ddi_get_lbolt() + drv_usectohz(1000000);
4833c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	while (!(sc->sc_flags & IWH_F_FW_INIT)) {
4834c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (cv_timedwait(&sc->sc_ucode_cv,
4835e2cf88acSQuaker Fang 		    &sc->sc_glock, clk) < 0) {
4836c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			break;
4837c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
4838c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4839c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4840c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (!(sc->sc_flags & IWH_F_FW_INIT)) {
4841c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_init(): "
4842c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to process init alive.\n");
4843e2cf88acSQuaker Fang 		mutex_exit(&sc->sc_glock);
4844c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (IWH_FAIL);
4845c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4846c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4847e2cf88acSQuaker Fang 	mutex_exit(&sc->sc_glock);
4848c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4849c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4850c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * stop chipset for initializing chipset again
4851c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4852c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_stop(sc);
4853c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4854c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mutex_enter(&sc->sc_glock);
485589b2a9fbSfei feng - Sun Microsystems - Beijing China 	atomic_and_32(&sc->sc_flags, ~IWH_F_FW_INIT);
4856c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4857c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_init_common(sc);
4858c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != IWH_SUCCESS) {
4859c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		mutex_exit(&sc->sc_glock);
4860c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (IWH_FAIL);
4861c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4862c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4863c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4864c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * load firmware run segment into NIC
4865c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4866c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_load_run_firmware(sc);
4867c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != IWH_SUCCESS) {
4868c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_init(): "
4869c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to setup run firmware\n");
4870e2cf88acSQuaker Fang 		mutex_exit(&sc->sc_glock);
4871e2cf88acSQuaker Fang 		return (IWH_FAIL);
4872c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4873c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4874c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4875c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * now press "execute" start running
4876c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4877c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_RESET, 0);
4878c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4879c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	clk = ddi_get_lbolt() + drv_usectohz(1000000);
4880c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	while (!(sc->sc_flags & IWH_F_FW_INIT)) {
4881c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (cv_timedwait(&sc->sc_ucode_cv,
4882e2cf88acSQuaker Fang 		    &sc->sc_glock, clk) < 0) {
4883c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			break;
4884c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
4885c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4886c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4887c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (!(sc->sc_flags & IWH_F_FW_INIT)) {
4888c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_init(): "
4889c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to process runtime alive.\n");
4890e2cf88acSQuaker Fang 		mutex_exit(&sc->sc_glock);
4891c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (IWH_FAIL);
4892c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4893c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4894e2cf88acSQuaker Fang 	mutex_exit(&sc->sc_glock);
4895e2cf88acSQuaker Fang 
4896e2cf88acSQuaker Fang 	DELAY(1000);
4897c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4898c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mutex_enter(&sc->sc_glock);
489989b2a9fbSfei feng - Sun Microsystems - Beijing China 	atomic_and_32(&sc->sc_flags, ~IWH_F_FW_INIT);
4900c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4901c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4902c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * at this point, the firmware is loaded OK, then config the hardware
4903c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * with the ucode API, including rxon, txpower, etc.
4904c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4905c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_config(sc);
4906c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err) {
4907c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_init(): "
4908c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to configure device\n");
4909c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		mutex_exit(&sc->sc_glock);
4910c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (IWH_FAIL);
4911c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4912c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4913c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4914c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * at this point, hardware may receive beacons :)
4915c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4916c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	mutex_exit(&sc->sc_glock);
4917c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (IWH_SUCCESS);
4918c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
4919c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4920c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
4921c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * stop or disable NIC
4922c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
4923c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
4924c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_stop(iwh_sc_t *sc)
4925c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
4926c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint32_t tmp;
4927c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	int i;
4928c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
492989b2a9fbSfei feng - Sun Microsystems - Beijing China 	/*
493089b2a9fbSfei feng - Sun Microsystems - Beijing China 	 * by pass if it's quiesced
493189b2a9fbSfei feng - Sun Microsystems - Beijing China 	 */
4932e2cf88acSQuaker Fang 	if (!(sc->sc_flags & IWH_F_QUIESCED)) {
4933c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		mutex_enter(&sc->sc_glock);
4934e2cf88acSQuaker Fang 	}
4935c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4936c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
4937c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4938c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * disable interrupts
4939c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4940c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_INT_MASK, 0);
4941c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_INT, CSR_INI_SET_MASK);
4942c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_FH_INT_STATUS, 0xffffffff);
4943c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4944c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4945c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * reset all Tx rings
4946c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4947c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < IWH_NUM_QUEUES; i++) {
4948c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		iwh_reset_tx_ring(sc, &sc->sc_txq[i]);
4949c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4950c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4951c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
4952c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * reset Rx ring
4953c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
4954c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_reset_rx_ring(sc);
4955c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4956c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_mac_access_enter(sc);
4957c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_reg_write(sc, ALM_APMG_CLK_DIS, APMG_CLK_REG_VAL_DMA_CLK_RQT);
4958c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_mac_access_exit(sc);
4959c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4960c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	DELAY(5);
4961c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4962c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_stop_master(sc);
4963c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4964e2cf88acSQuaker Fang 	mutex_enter(&sc->sc_mt_lock);
4965c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_tx_timer = 0;
4966e2cf88acSQuaker Fang 	mutex_exit(&sc->sc_mt_lock);
4967e2cf88acSQuaker Fang 
4968c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tmp = IWH_READ(sc, CSR_RESET);
4969c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_RESET, tmp | CSR_RESET_REG_FLAG_SW_RESET);
4970c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
497189b2a9fbSfei feng - Sun Microsystems - Beijing China 	/*
497289b2a9fbSfei feng - Sun Microsystems - Beijing China 	 * by pass if it's quiesced
497389b2a9fbSfei feng - Sun Microsystems - Beijing China 	 */
4974e2cf88acSQuaker Fang 	if (!(sc->sc_flags & IWH_F_QUIESCED)) {
4975c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		mutex_exit(&sc->sc_glock);
4976c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
4977e2cf88acSQuaker Fang }
4978c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
4979c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
4980c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * Naive implementation of the Adaptive Multi Rate Retry algorithm:
4981c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * "IEEE 802.11 Rate Adaptation: A Practical Approach"
4982c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * Mathieu Lacage, Hossein Manshaei, Thierry Turletti
4983c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * INRIA Sophia - Projet Planete
4984c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * http://www-sop.inria.fr/rapports/sophia/RR-5208.html
4985c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
4986c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	is_success(amrr)	\
4987c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	((amrr)->retrycnt < (amrr)->txcnt / 10)
4988c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	is_failure(amrr)	\
4989c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	((amrr)->retrycnt > (amrr)->txcnt / 3)
4990c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	is_enough(amrr)		\
4991e2cf88acSQuaker Fang 	((amrr)->txcnt > 200)
4992e2cf88acSQuaker Fang #define	not_very_few(amrr)	\
4993e2cf88acSQuaker Fang 	((amrr)->txcnt > 40)
4994c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	is_min_rate(in)		\
4995c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(0 == (in)->in_txrate)
4996c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	is_max_rate(in)		\
4997c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	((in)->in_rates.ir_nrates - 1 == (in)->in_txrate)
4998c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	increase_rate(in)	\
4999c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	((in)->in_txrate++)
5000c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	decrease_rate(in)	\
5001c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	((in)->in_txrate--)
5002c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	reset_cnt(amrr)		\
5003c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	{ (amrr)->txcnt = (amrr)->retrycnt = 0; }
5004c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5005c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	IWH_AMRR_MIN_SUCCESS_THRESHOLD	 1
5006c7ee0b5cSfei feng - Sun Microsystems - Beijing China #define	IWH_AMRR_MAX_SUCCESS_THRESHOLD	15
5007c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5008c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
5009c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_amrr_init(iwh_amrr_t *amrr)
5010c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
5011c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	amrr->success = 0;
5012c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	amrr->recovery = 0;
5013c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	amrr->txcnt = amrr->retrycnt = 0;
5014c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	amrr->success_threshold = IWH_AMRR_MIN_SUCCESS_THRESHOLD;
5015e2cf88acSQuaker Fang 	amrr->ht_mcs_idx = 0;	/* 6Mbps */
5016c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
5017c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5018c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
5019c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_amrr_timeout(iwh_sc_t *sc)
5020c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
5021c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	ieee80211com_t *ic = &sc->sc_ic;
5022c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5023e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_RATECTL, "iwh_amrr_timeout(): "
5024e2cf88acSQuaker Fang 	    "enter\n"));
5025c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5026c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (IEEE80211_M_STA == ic->ic_opmode) {
5027c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		iwh_amrr_ratectl(NULL, ic->ic_bss);
5028c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	} else {
5029c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		ieee80211_iterate_nodes(&ic->ic_sta, iwh_amrr_ratectl, NULL);
5030c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
5031c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5032c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_clk = ddi_get_lbolt();
5033c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
5034c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5035e2cf88acSQuaker Fang static int
5036e2cf88acSQuaker Fang iwh_is_max_rate(ieee80211_node_t *in)
5037e2cf88acSQuaker Fang {
5038e2cf88acSQuaker Fang 	int i;
5039e2cf88acSQuaker Fang 	iwh_amrr_t *amrr = (iwh_amrr_t *)in;
5040e2cf88acSQuaker Fang 	uint8_t r = (uint8_t)amrr->ht_mcs_idx;
5041e2cf88acSQuaker Fang 	ieee80211com_t *ic = in->in_ic;
5042e2cf88acSQuaker Fang 	iwh_sc_t *sc = (iwh_sc_t *)ic;
5043e2cf88acSQuaker Fang 
5044e2cf88acSQuaker Fang 	if (in->in_flags & IEEE80211_NODE_HT) {
5045e2cf88acSQuaker Fang 		for (i = in->in_htrates.rs_nrates - 1; i >= 0; i--) {
5046e2cf88acSQuaker Fang 			r = in->in_htrates.rs_rates[i] &
5047e2cf88acSQuaker Fang 			    IEEE80211_RATE_VAL;
5048e2cf88acSQuaker Fang 			if (sc->sc_ht_conf.tx_support_mcs[r/8] &
5049e2cf88acSQuaker Fang 			    (1 << (r%8))) {
5050e2cf88acSQuaker Fang 				break;
5051e2cf88acSQuaker Fang 			}
5052e2cf88acSQuaker Fang 		}
5053e2cf88acSQuaker Fang 
5054e2cf88acSQuaker Fang 		return (r == (uint8_t)amrr->ht_mcs_idx);
5055e2cf88acSQuaker Fang 	} else {
5056e2cf88acSQuaker Fang 		return (is_max_rate(in));
5057e2cf88acSQuaker Fang 	}
5058e2cf88acSQuaker Fang }
5059e2cf88acSQuaker Fang 
5060e2cf88acSQuaker Fang static int
5061e2cf88acSQuaker Fang iwh_is_min_rate(ieee80211_node_t *in)
5062e2cf88acSQuaker Fang {
5063e2cf88acSQuaker Fang 	int i;
5064e2cf88acSQuaker Fang 	uint8_t r = 0;
5065e2cf88acSQuaker Fang 	iwh_amrr_t *amrr = (iwh_amrr_t *)in;
5066e2cf88acSQuaker Fang 	ieee80211com_t *ic = in->in_ic;
5067e2cf88acSQuaker Fang 	iwh_sc_t *sc = (iwh_sc_t *)ic;
5068e2cf88acSQuaker Fang 
5069e2cf88acSQuaker Fang 	if (in->in_flags & IEEE80211_NODE_HT) {
5070e2cf88acSQuaker Fang 		for (i = 0; i < in->in_htrates.rs_nrates; i++) {
5071e2cf88acSQuaker Fang 			r = in->in_htrates.rs_rates[i] &
5072e2cf88acSQuaker Fang 			    IEEE80211_RATE_VAL;
5073e2cf88acSQuaker Fang 			if (sc->sc_ht_conf.tx_support_mcs[r/8] &
5074e2cf88acSQuaker Fang 			    (1 << (r%8))) {
5075e2cf88acSQuaker Fang 				break;
5076e2cf88acSQuaker Fang 			}
5077e2cf88acSQuaker Fang 		}
5078e2cf88acSQuaker Fang 
5079e2cf88acSQuaker Fang 		return (r == (uint8_t)amrr->ht_mcs_idx);
5080e2cf88acSQuaker Fang 	} else {
5081e2cf88acSQuaker Fang 		return (is_min_rate(in));
5082e2cf88acSQuaker Fang 	}
5083e2cf88acSQuaker Fang }
5084e2cf88acSQuaker Fang 
5085c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
5086e2cf88acSQuaker Fang iwh_increase_rate(ieee80211_node_t *in)
5087e2cf88acSQuaker Fang {
5088e2cf88acSQuaker Fang 	int i;
5089e2cf88acSQuaker Fang 	uint8_t r;
5090e2cf88acSQuaker Fang 	iwh_amrr_t *amrr = (iwh_amrr_t *)in;
5091e2cf88acSQuaker Fang 	ieee80211com_t *ic = in->in_ic;
5092e2cf88acSQuaker Fang 	iwh_sc_t *sc = (iwh_sc_t *)ic;
5093e2cf88acSQuaker Fang 
5094e2cf88acSQuaker Fang 	if (in->in_flags & IEEE80211_NODE_HT) {
5095e2cf88acSQuaker Fang again:
5096e2cf88acSQuaker Fang 		amrr->ht_mcs_idx++;
5097e2cf88acSQuaker Fang 
5098e2cf88acSQuaker Fang 		for (i = 0; i < in->in_htrates.rs_nrates; i++) {
5099e2cf88acSQuaker Fang 			r = in->in_htrates.rs_rates[i] &
5100e2cf88acSQuaker Fang 			    IEEE80211_RATE_VAL;
5101e2cf88acSQuaker Fang 			if ((r == (uint8_t)amrr->ht_mcs_idx) &&
5102e2cf88acSQuaker Fang 			    (sc->sc_ht_conf.tx_support_mcs[r/8] &
5103e2cf88acSQuaker Fang 			    (1 << (r%8)))) {
5104e2cf88acSQuaker Fang 				break;
5105e2cf88acSQuaker Fang 			}
5106e2cf88acSQuaker Fang 		}
5107e2cf88acSQuaker Fang 
5108e2cf88acSQuaker Fang 		if (i >= in->in_htrates.rs_nrates) {
5109e2cf88acSQuaker Fang 			goto again;
5110e2cf88acSQuaker Fang 		}
5111e2cf88acSQuaker Fang 	} else {
5112e2cf88acSQuaker Fang 		increase_rate(in);
5113e2cf88acSQuaker Fang 	}
5114e2cf88acSQuaker Fang }
5115e2cf88acSQuaker Fang 
5116e2cf88acSQuaker Fang static void
5117e2cf88acSQuaker Fang iwh_decrease_rate(ieee80211_node_t *in)
5118e2cf88acSQuaker Fang {
5119e2cf88acSQuaker Fang 	int i;
5120e2cf88acSQuaker Fang 	uint8_t r;
5121e2cf88acSQuaker Fang 	iwh_amrr_t *amrr = (iwh_amrr_t *)in;
5122e2cf88acSQuaker Fang 	ieee80211com_t *ic = in->in_ic;
5123e2cf88acSQuaker Fang 	iwh_sc_t *sc = (iwh_sc_t *)ic;
5124e2cf88acSQuaker Fang 
5125e2cf88acSQuaker Fang 	if (in->in_flags & IEEE80211_NODE_HT) {
5126e2cf88acSQuaker Fang again:
5127e2cf88acSQuaker Fang 		amrr->ht_mcs_idx--;
5128e2cf88acSQuaker Fang 
5129e2cf88acSQuaker Fang 		for (i = 0; i < in->in_htrates.rs_nrates; i++) {
5130e2cf88acSQuaker Fang 			r = in->in_htrates.rs_rates[i] &
5131e2cf88acSQuaker Fang 			    IEEE80211_RATE_VAL;
5132e2cf88acSQuaker Fang 			if ((r == (uint8_t)amrr->ht_mcs_idx) &&
5133e2cf88acSQuaker Fang 			    (sc->sc_ht_conf.tx_support_mcs[r/8] &
5134e2cf88acSQuaker Fang 			    (1 << (r%8)))) {
5135e2cf88acSQuaker Fang 				break;
5136e2cf88acSQuaker Fang 			}
5137e2cf88acSQuaker Fang 		}
5138e2cf88acSQuaker Fang 
5139e2cf88acSQuaker Fang 		if (i >= in->in_htrates.rs_nrates) {
5140e2cf88acSQuaker Fang 			goto again;
5141e2cf88acSQuaker Fang 		}
5142e2cf88acSQuaker Fang 	} else {
5143e2cf88acSQuaker Fang 		decrease_rate(in);
5144e2cf88acSQuaker Fang 	}
5145e2cf88acSQuaker Fang }
5146e2cf88acSQuaker Fang 
5147e2cf88acSQuaker Fang /* ARGSUSED */
5148e2cf88acSQuaker Fang static void
5149c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_amrr_ratectl(void *arg, ieee80211_node_t *in)
5150c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
5151c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_amrr_t *amrr = (iwh_amrr_t *)in;
5152c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	int need_change = 0;
5153c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5154c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (is_success(amrr) && is_enough(amrr)) {
5155c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		amrr->success++;
5156c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (amrr->success >= amrr->success_threshold &&
5157e2cf88acSQuaker Fang 		    !iwh_is_max_rate(in)) {
5158c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			amrr->recovery = 1;
5159c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			amrr->success = 0;
5160e2cf88acSQuaker Fang 			iwh_increase_rate(in);
5161e2cf88acSQuaker Fang 			IWH_DBG((IWH_DEBUG_RATECTL, "iwh_amrr_ratectl(): "
5162e2cf88acSQuaker Fang 			    "AMRR increasing rate %d "
5163e2cf88acSQuaker Fang 			    "(txcnt=%d retrycnt=%d), mcs_idx=%d\n",
5164e2cf88acSQuaker Fang 			    in->in_txrate, amrr->txcnt,
5165e2cf88acSQuaker Fang 			    amrr->retrycnt, amrr->ht_mcs_idx));
5166c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			need_change = 1;
5167c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		} else {
5168c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			amrr->recovery = 0;
5169c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
5170e2cf88acSQuaker Fang 	} else if (not_very_few(amrr) && is_failure(amrr)) {
5171c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		amrr->success = 0;
5172e2cf88acSQuaker Fang 		if (!iwh_is_min_rate(in)) {
5173c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			if (amrr->recovery) {
5174c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				amrr->success_threshold++;
5175c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				if (amrr->success_threshold >
5176c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				    IWH_AMRR_MAX_SUCCESS_THRESHOLD) {
5177c7ee0b5cSfei feng - Sun Microsystems - Beijing China 					amrr->success_threshold =
5178c7ee0b5cSfei feng - Sun Microsystems - Beijing China 					    IWH_AMRR_MAX_SUCCESS_THRESHOLD;
5179c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				}
5180c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			} else {
5181c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				amrr->success_threshold =
5182c7ee0b5cSfei feng - Sun Microsystems - Beijing China 				    IWH_AMRR_MIN_SUCCESS_THRESHOLD;
5183c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			}
5184e2cf88acSQuaker Fang 			iwh_decrease_rate(in);
5185e2cf88acSQuaker Fang 			IWH_DBG((IWH_DEBUG_RATECTL, "iwh_amrr_ratectl(): "
5186e2cf88acSQuaker Fang 			    "AMRR decreasing rate %d "
5187e2cf88acSQuaker Fang 			    "(txcnt=%d retrycnt=%d), mcs_idx=%d\n",
5188e2cf88acSQuaker Fang 			    in->in_txrate, amrr->txcnt,
5189e2cf88acSQuaker Fang 			    amrr->retrycnt, amrr->ht_mcs_idx));
5190c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			need_change = 1;
5191c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
5192c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		amrr->recovery = 0;	/* paper is incorrect */
5193c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
5194c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5195c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (is_enough(amrr) || need_change) {
5196c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		reset_cnt(amrr);
5197c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
5198c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
5199c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5200c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
5201c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * translate indirect address in eeprom to direct address
5202c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * in eeprom and return address of entry whos indirect address
5203c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * is indi_addr
5204c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
5205c7ee0b5cSfei feng - Sun Microsystems - Beijing China static uint8_t *
5206c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_eep_addr_trans(iwh_sc_t *sc, uint32_t indi_addr)
5207c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
5208c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint32_t di_addr;
5209c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint16_t temp;
5210c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5211c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (!(indi_addr & INDIRECT_ADDRESS)) {
5212c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		di_addr = indi_addr;
5213c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (&sc->sc_eep_map[di_addr]);
5214c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
5215c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5216c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	switch (indi_addr & INDIRECT_TYPE_MSK) {
5217c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case INDIRECT_GENERAL:
5218c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		temp = IWH_READ_EEP_SHORT(sc, EEP_LINK_GENERAL);
5219c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
5220c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5221c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case	INDIRECT_HOST:
5222c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		temp = IWH_READ_EEP_SHORT(sc, EEP_LINK_HOST);
5223c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
5224c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5225c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case	INDIRECT_REGULATORY:
5226c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		temp = IWH_READ_EEP_SHORT(sc, EEP_LINK_REGULATORY);
5227c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
5228c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5229c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case	INDIRECT_CALIBRATION:
5230c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		temp = IWH_READ_EEP_SHORT(sc, EEP_LINK_CALIBRATION);
5231c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
5232c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5233c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case	INDIRECT_PROCESS_ADJST:
5234c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		temp = IWH_READ_EEP_SHORT(sc, EEP_LINK_PROCESS_ADJST);
5235c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
5236c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5237c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case	INDIRECT_OTHERS:
5238c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		temp = IWH_READ_EEP_SHORT(sc, EEP_LINK_OTHERS);
5239c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
5240c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5241c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	default:
5242c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		temp = 0;
5243c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_eep_addr_trans(): "
5244c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "incorrect indirect eeprom address.\n");
5245c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
5246c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
5247c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5248c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	di_addr = (indi_addr & ADDRESS_MSK) + (temp << 1);
5249c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5250c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (&sc->sc_eep_map[di_addr]);
5251c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
5252c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5253c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
5254c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * loade a section of ucode into NIC
5255c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
5256c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
5257c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_put_seg_fw(iwh_sc_t *sc, uint32_t addr_s, uint32_t addr_d, uint32_t len)
5258c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
5259c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5260c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_mac_access_enter(sc);
5261c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5262c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, IWH_FH_TCSR_CHNL_TX_CONFIG_REG(IWH_FH_SRVC_CHNL),
5263c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    IWH_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE);
5264c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5265c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, IWH_FH_SRVC_CHNL_SRAM_ADDR_REG(IWH_FH_SRVC_CHNL), addr_d);
5266c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5267c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, IWH_FH_TFDIB_CTRL0_REG(IWH_FH_SRVC_CHNL),
5268c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    (addr_s & FH_MEM_TFDIB_DRAM_ADDR_LSB_MASK));
5269c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5270c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, IWH_FH_TFDIB_CTRL1_REG(IWH_FH_SRVC_CHNL), len);
5271c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5272c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, IWH_FH_TCSR_CHNL_TX_BUF_STS_REG(IWH_FH_SRVC_CHNL),
5273c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    (1 << IWH_FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM) |
5274c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    (1 << IWH_FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX) |
5275c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    IWH_FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID);
5276c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5277c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, IWH_FH_TCSR_CHNL_TX_CONFIG_REG(IWH_FH_SRVC_CHNL),
5278c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    IWH_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
5279c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    IWH_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL |
5280c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    IWH_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
5281c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5282c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_mac_access_exit(sc);
5283c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5284c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (IWH_SUCCESS);
5285c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
5286c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5287c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
5288c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * necessary setting during alive notification
5289c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
5290c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
5291c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_alive_common(iwh_sc_t *sc)
5292c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
5293c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint32_t base;
5294c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint32_t i;
5295c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_wimax_coex_cmd_t w_cmd;
5296c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_calibration_crystal_cmd_t c_cmd;
5297e2cf88acSQuaker Fang 	uint32_t rv = IWH_FAIL;
5298c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5299c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
5300c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * initialize SCD related registers to make TX work.
5301c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
5302c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_mac_access_enter(sc);
5303c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5304c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
5305c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * read sram address of data base.
5306c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
5307c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	sc->sc_scd_base = iwh_reg_read(sc, IWH_SCD_SRAM_BASE_ADDR);
5308c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5309c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	for (base = sc->sc_scd_base + IWH_SCD_CONTEXT_DATA_OFFSET;
5310c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    base < sc->sc_scd_base + IWH_SCD_TX_STTS_BITMAP_OFFSET;
5311c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    base += 4) {
5312c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		iwh_mem_write(sc, base, 0);
5313c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
5314c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5315c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	for (; base < sc->sc_scd_base + IWH_SCD_TRANSLATE_TBL_OFFSET;
5316c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    base += 4) {
5317c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		iwh_mem_write(sc, base, 0);
5318c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
5319c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5320c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < sizeof (uint16_t) * IWH_NUM_QUEUES; i += 4) {
5321c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		iwh_mem_write(sc, base + i, 0);
5322c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
5323c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5324c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_reg_write(sc, IWH_SCD_DRAM_BASE_ADDR,
5325c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    sc->sc_dma_sh.cookie.dmac_address >> 10);
5326c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5327c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_reg_write(sc, IWH_SCD_QUEUECHAIN_SEL,
5328c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    IWH_SCD_QUEUECHAIN_SEL_ALL(IWH_NUM_QUEUES));
5329c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5330c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_reg_write(sc, IWH_SCD_AGGR_SEL, 0);
5331c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5332c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < IWH_NUM_QUEUES; i++) {
5333c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		iwh_reg_write(sc, IWH_SCD_QUEUE_RDPTR(i), 0);
5334c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		IWH_WRITE(sc, HBUS_TARG_WRPTR, 0 | (i << 8));
5335c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		iwh_mem_write(sc, sc->sc_scd_base +
5336c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    IWH_SCD_CONTEXT_QUEUE_OFFSET(i), 0);
5337c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		iwh_mem_write(sc, sc->sc_scd_base +
5338c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    IWH_SCD_CONTEXT_QUEUE_OFFSET(i) +
5339c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    sizeof (uint32_t),
5340c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    ((SCD_WIN_SIZE << IWH_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
5341c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    IWH_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
5342c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    ((SCD_FRAME_LIMIT <<
5343c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    IWH_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
5344c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    IWH_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
5345c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
5346c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5347c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_reg_write(sc, IWH_SCD_INTERRUPT_MASK, (1 << IWH_NUM_QUEUES) - 1);
5348c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5349c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_reg_write(sc, (IWH_SCD_BASE + 0x10),
5350c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    SCD_TXFACT_REG_TXFIFO_MASK(0, 7));
5351c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5352c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, HBUS_TARG_WRPTR, (IWH_CMD_QUEUE_NUM << 8));
5353c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_reg_write(sc, IWH_SCD_QUEUE_RDPTR(IWH_CMD_QUEUE_NUM), 0);
5354c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5355c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
5356c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * queue 0-7 map to FIFO 0-7 and
5357c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * all queues work under FIFO mode(none-scheduler_ack)
5358c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
5359c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < 4; i++) {
5360c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		iwh_reg_write(sc, IWH_SCD_QUEUE_STATUS_BITS(i),
5361c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    (1 << IWH_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
5362c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    ((3-i) << IWH_SCD_QUEUE_STTS_REG_POS_TXF) |
5363c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    (1 << IWH_SCD_QUEUE_STTS_REG_POS_WSL) |
5364c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    IWH_SCD_QUEUE_STTS_REG_MSK);
5365c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
5366c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5367c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_reg_write(sc, IWH_SCD_QUEUE_STATUS_BITS(IWH_CMD_QUEUE_NUM),
5368c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    (1 << IWH_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
5369c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    (IWH_CMD_FIFO_NUM << IWH_SCD_QUEUE_STTS_REG_POS_TXF) |
5370c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    (1 << IWH_SCD_QUEUE_STTS_REG_POS_WSL) |
5371c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    IWH_SCD_QUEUE_STTS_REG_MSK);
5372c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5373c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	for (i = 5; i < 7; i++) {
5374c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		iwh_reg_write(sc, IWH_SCD_QUEUE_STATUS_BITS(i),
5375c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    (1 << IWH_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
5376c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    (i << IWH_SCD_QUEUE_STTS_REG_POS_TXF) |
5377c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    (1 << IWH_SCD_QUEUE_STTS_REG_POS_WSL) |
5378c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    IWH_SCD_QUEUE_STTS_REG_MSK);
5379c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
5380c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5381c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_mac_access_exit(sc);
5382c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5383c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) memset(&w_cmd, 0, sizeof (w_cmd));
5384c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5385c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	rv = iwh_cmd(sc, COEX_PRIORITY_TABLE_CMD, &w_cmd, sizeof (w_cmd), 1);
5386c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (rv != IWH_SUCCESS) {
5387c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_alive_common(): "
5388c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to send wimax coexist command.\n");
5389c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (rv);
5390c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
5391c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
539289b2a9fbSfei feng - Sun Microsystems - Beijing China 	if ((sc->sc_dev_id != 0x423c) &&
539389b2a9fbSfei feng - Sun Microsystems - Beijing China 	    (sc->sc_dev_id != 0x423d)) {
5394c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		(void) memset(&c_cmd, 0, sizeof (c_cmd));
5395c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5396c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		c_cmd.opCode = PHY_CALIBRATE_CRYSTAL_FRQ_CMD;
5397b510adaeSfei feng - Sun Microsystems - Beijing China 		c_cmd.data.cap_pin1 = LE_16(sc->sc_eep_calib->xtal_calib[0]);
5398b510adaeSfei feng - Sun Microsystems - Beijing China 		c_cmd.data.cap_pin2 = LE_16(sc->sc_eep_calib->xtal_calib[1]);
5399c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
540089b2a9fbSfei feng - Sun Microsystems - Beijing China 		rv = iwh_cmd(sc, REPLY_PHY_CALIBRATION_CMD,
540189b2a9fbSfei feng - Sun Microsystems - Beijing China 		    &c_cmd, sizeof (c_cmd), 1);
5402c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (rv != IWH_SUCCESS) {
5403c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			cmn_err(CE_WARN, "iwh_alive_common(): "
540489b2a9fbSfei feng - Sun Microsystems - Beijing China 			    "failed to send crystal"
540589b2a9fbSfei feng - Sun Microsystems - Beijing China 			    "frq calibration command.\n");
5406c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			return (rv);
5407c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
5408c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5409c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		/*
5410c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * make sure crystal frequency calibration ready
5411c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 * before next operations.
5412c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		 */
5413c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		DELAY(1000);
541489b2a9fbSfei feng - Sun Microsystems - Beijing China 	}
5415c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5416c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (IWH_SUCCESS);
5417c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
5418c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5419c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
5420c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * save results of calibration from ucode
5421c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
5422c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
5423c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_save_calib_result(iwh_sc_t *sc, iwh_rx_desc_t *desc)
5424c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
5425c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	struct iwh_calib_results *res_p = &sc->sc_calib_results;
5426c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	struct iwh_calib_hdr *calib_hdr = (struct iwh_calib_hdr *)(desc + 1);
5427b510adaeSfei feng - Sun Microsystems - Beijing China 	int len = LE_32(desc->len);
5428c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5429c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
5430c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * ensure the size of buffer is not too big
5431c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
5432c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	len = (len & FH_RSCSR_FRAME_SIZE_MASK) - 4;
5433c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5434c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	switch (calib_hdr->op_code) {
5435c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case PHY_CALIBRATE_LO_CMD:
5436c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (NULL == res_p->lo_res) {
5437c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			res_p->lo_res = kmem_alloc(len, KM_NOSLEEP);
5438c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
5439c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5440c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (NULL == res_p->lo_res) {
5441c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			cmn_err(CE_WARN, "iwh_save_calib_result(): "
5442c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			    "failed to allocate memory.\n");
5443c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			return;
5444c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
5445c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5446c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		res_p->lo_res_len = len;
544789b2a9fbSfei feng - Sun Microsystems - Beijing China 		bcopy(calib_hdr, res_p->lo_res, len);
5448c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
5449c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5450c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case PHY_CALIBRATE_TX_IQ_CMD:
5451c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (NULL == res_p->tx_iq_res) {
5452c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			res_p->tx_iq_res = kmem_alloc(len, KM_NOSLEEP);
5453c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
5454c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5455c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (NULL == res_p->tx_iq_res) {
5456c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			cmn_err(CE_WARN, "iwh_save_calib_result(): "
5457c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			    "failed to allocate memory.\n");
5458c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			return;
5459c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
5460c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5461c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		res_p->tx_iq_res_len = len;
546289b2a9fbSfei feng - Sun Microsystems - Beijing China 		bcopy(calib_hdr, res_p->tx_iq_res, len);
5463c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
5464c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5465c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	case PHY_CALIBRATE_TX_IQ_PERD_CMD:
5466c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (NULL == res_p->tx_iq_perd_res) {
5467c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			res_p->tx_iq_perd_res = kmem_alloc(len, KM_NOSLEEP);
5468c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
5469c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5470c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		if (NULL == res_p->tx_iq_perd_res) {
5471c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			cmn_err(CE_WARN, "iwh_save_calib_result(): "
5472c7ee0b5cSfei feng - Sun Microsystems - Beijing China 			    "failed to allocate memory.\n");
54737d483bc1Sfei feng - Sun Microsystems - Beijing China 			return;
5474c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		}
5475c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5476c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		res_p->tx_iq_perd_res_len = len;
547789b2a9fbSfei feng - Sun Microsystems - Beijing China 		bcopy(calib_hdr, res_p->tx_iq_perd_res, len);
547889b2a9fbSfei feng - Sun Microsystems - Beijing China 		break;
547989b2a9fbSfei feng - Sun Microsystems - Beijing China 
548089b2a9fbSfei feng - Sun Microsystems - Beijing China 	case PHY_CALIBRATE_DC_CMD:
548189b2a9fbSfei feng - Sun Microsystems - Beijing China 		if (NULL == res_p->dc_res) {
548289b2a9fbSfei feng - Sun Microsystems - Beijing China 			res_p->dc_res = kmem_alloc(len, KM_NOSLEEP);
548389b2a9fbSfei feng - Sun Microsystems - Beijing China 		}
548489b2a9fbSfei feng - Sun Microsystems - Beijing China 
548589b2a9fbSfei feng - Sun Microsystems - Beijing China 		if (NULL == res_p->dc_res) {
548689b2a9fbSfei feng - Sun Microsystems - Beijing China 			cmn_err(CE_WARN, "iwh_save_calib_result(): "
548789b2a9fbSfei feng - Sun Microsystems - Beijing China 			    "failed to allocate memory.\n");
54887d483bc1Sfei feng - Sun Microsystems - Beijing China 			return;
548989b2a9fbSfei feng - Sun Microsystems - Beijing China 		}
549089b2a9fbSfei feng - Sun Microsystems - Beijing China 
549189b2a9fbSfei feng - Sun Microsystems - Beijing China 		res_p->dc_res_len = len;
549289b2a9fbSfei feng - Sun Microsystems - Beijing China 		bcopy(calib_hdr, res_p->dc_res, len);
549389b2a9fbSfei feng - Sun Microsystems - Beijing China 		break;
549489b2a9fbSfei feng - Sun Microsystems - Beijing China 
549589b2a9fbSfei feng - Sun Microsystems - Beijing China 	case PHY_CALIBRATE_BASE_BAND_CMD:
549689b2a9fbSfei feng - Sun Microsystems - Beijing China 		if (NULL == res_p->base_band_res) {
549789b2a9fbSfei feng - Sun Microsystems - Beijing China 			res_p->base_band_res = kmem_alloc(len, KM_NOSLEEP);
549889b2a9fbSfei feng - Sun Microsystems - Beijing China 		}
549989b2a9fbSfei feng - Sun Microsystems - Beijing China 
550089b2a9fbSfei feng - Sun Microsystems - Beijing China 		if (NULL == res_p->base_band_res) {
550189b2a9fbSfei feng - Sun Microsystems - Beijing China 			cmn_err(CE_WARN, "iwh_save_calib_result(): "
550289b2a9fbSfei feng - Sun Microsystems - Beijing China 			    "failed to allocate memory.\n");
55037d483bc1Sfei feng - Sun Microsystems - Beijing China 			return;
550489b2a9fbSfei feng - Sun Microsystems - Beijing China 		}
550589b2a9fbSfei feng - Sun Microsystems - Beijing China 
550689b2a9fbSfei feng - Sun Microsystems - Beijing China 		res_p->base_band_res_len = len;
550789b2a9fbSfei feng - Sun Microsystems - Beijing China 		bcopy(calib_hdr, res_p->base_band_res, len);
5508c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
5509c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5510c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	default:
5511c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_save_calib_result(): "
551289b2a9fbSfei feng - Sun Microsystems - Beijing China 		    "incorrect calibration type(%d).\n", calib_hdr->op_code);
5513c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		break;
5514c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
5515c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5516c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
5517c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5518c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
5519c7ee0b5cSfei feng - Sun Microsystems - Beijing China  * configure TX pwoer table
5520c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
5521c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
5522c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_tx_power_table(iwh_sc_t *sc, int async)
5523c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
5524c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_tx_power_table_cmd_t txpower;
5525e2cf88acSQuaker Fang 	int i, err = IWH_FAIL;
5526c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5527c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) memset(&txpower, 0, sizeof (txpower));
5528c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5529c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	txpower.band = 1; /* for 2.4G */
5530b510adaeSfei feng - Sun Microsystems - Beijing China 	txpower.channel = (uint8_t)LE_16(sc->sc_config.chan);
5531c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	txpower.pa_measurements = 1;
5532c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	txpower.max_mcs = 23;
5533c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5534c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < 24; i++) {
5535c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		txpower.db.ht_ofdm_power[i].s.radio_tx_gain[0] = 0x16;
5536c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		txpower.db.ht_ofdm_power[i].s.radio_tx_gain[1] = 0x16;
5537c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		txpower.db.ht_ofdm_power[i].s.radio_tx_gain[2] = 0x16;
5538c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		txpower.db.ht_ofdm_power[i].s.dsp_predis_atten[0] = 0x6E;
5539c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		txpower.db.ht_ofdm_power[i].s.dsp_predis_atten[1] = 0x6E;
5540c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		txpower.db.ht_ofdm_power[i].s.dsp_predis_atten[2] = 0x6E;
5541c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
5542c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5543c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < 2; i++) {
5544c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		txpower.db.cck_power[i].s.radio_tx_gain[0] = 0x16;
5545c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		txpower.db.cck_power[i].s.radio_tx_gain[1] = 0x16;
5546c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		txpower.db.cck_power[i].s.radio_tx_gain[2] = 0x16;
5547c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		txpower.db.cck_power[i].s.dsp_predis_atten[0] = 0x6E;
5548c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		txpower.db.cck_power[i].s.dsp_predis_atten[1] = 0x6E;
5549c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		txpower.db.cck_power[i].s.dsp_predis_atten[2] = 0x6E;
5550c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
5551c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5552c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	err = iwh_cmd(sc, REPLY_TX_PWR_TABLE_CMD, &txpower,
5553c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    sizeof (txpower), async);
5554c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (err != IWH_SUCCESS) {
5555c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_tx_power_table(): "
5556c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "failed to set tx power table.\n");
5557c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (err);
5558c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
5559c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5560e2cf88acSQuaker Fang 	return (err);
5561c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
5562c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5563c7ee0b5cSfei feng - Sun Microsystems - Beijing China static void
5564c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_release_calib_buffer(iwh_sc_t *sc)
5565c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
5566c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (sc->sc_calib_results.lo_res != NULL) {
5567c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		kmem_free(sc->sc_calib_results.lo_res,
5568c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    sc->sc_calib_results.lo_res_len);
5569c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_calib_results.lo_res = NULL;
5570c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
5571c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5572c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (sc->sc_calib_results.tx_iq_res != NULL) {
5573c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		kmem_free(sc->sc_calib_results.tx_iq_res,
5574c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    sc->sc_calib_results.tx_iq_res_len);
5575c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_calib_results.tx_iq_res = NULL;
5576c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
5577c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5578c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (sc->sc_calib_results.tx_iq_perd_res != NULL) {
5579c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		kmem_free(sc->sc_calib_results.tx_iq_perd_res,
5580c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    sc->sc_calib_results.tx_iq_perd_res_len);
5581c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		sc->sc_calib_results.tx_iq_perd_res = NULL;
5582c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
5583c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
558489b2a9fbSfei feng - Sun Microsystems - Beijing China 	if (sc->sc_calib_results.dc_res != NULL) {
558589b2a9fbSfei feng - Sun Microsystems - Beijing China 		kmem_free(sc->sc_calib_results.dc_res,
558689b2a9fbSfei feng - Sun Microsystems - Beijing China 		    sc->sc_calib_results.dc_res_len);
558789b2a9fbSfei feng - Sun Microsystems - Beijing China 		sc->sc_calib_results.dc_res = NULL;
558889b2a9fbSfei feng - Sun Microsystems - Beijing China 	}
558989b2a9fbSfei feng - Sun Microsystems - Beijing China 
559089b2a9fbSfei feng - Sun Microsystems - Beijing China 	if (sc->sc_calib_results.base_band_res != NULL) {
559189b2a9fbSfei feng - Sun Microsystems - Beijing China 		kmem_free(sc->sc_calib_results.base_band_res,
559289b2a9fbSfei feng - Sun Microsystems - Beijing China 		    sc->sc_calib_results.base_band_res_len);
559389b2a9fbSfei feng - Sun Microsystems - Beijing China 		sc->sc_calib_results.base_band_res = NULL;
559489b2a9fbSfei feng - Sun Microsystems - Beijing China 	}
5595c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
5596c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5597c7ee0b5cSfei feng - Sun Microsystems - Beijing China /*
5598e2cf88acSQuaker Fang  * common section of intialization
5599c7ee0b5cSfei feng - Sun Microsystems - Beijing China  */
5600c7ee0b5cSfei feng - Sun Microsystems - Beijing China static int
5601c7ee0b5cSfei feng - Sun Microsystems - Beijing China iwh_init_common(iwh_sc_t *sc)
5602c7ee0b5cSfei feng - Sun Microsystems - Beijing China {
5603c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	int32_t	qid;
5604c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	uint32_t tmp;
5605c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
56067d483bc1Sfei feng - Sun Microsystems - Beijing China 	if (iwh_reset_hw(sc) != IWH_SUCCESS) {
56077d483bc1Sfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_init_common(): "
56087d483bc1Sfei feng - Sun Microsystems - Beijing China 		    "failed to reset hardware\n");
56097d483bc1Sfei feng - Sun Microsystems - Beijing China 		return (IWH_FAIL);
56107d483bc1Sfei feng - Sun Microsystems - Beijing China 	}
56117d483bc1Sfei feng - Sun Microsystems - Beijing China 
5612c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	(void) iwh_preinit(sc);
5613c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5614c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	tmp = IWH_READ(sc, CSR_GP_CNTRL);
5615c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	if (!(tmp & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) {
5616b510adaeSfei feng - Sun Microsystems - Beijing China 		cmn_err(CE_NOTE, "iwh_init_common(): "
5617c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    "radio transmitter is off\n");
5618c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		return (IWH_FAIL);
5619c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
5620c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5621c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
5622c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * init Rx ring
5623c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
5624c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_mac_access_enter(sc);
5625c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
5626c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5627c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
5628c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
5629c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    sc->sc_rxq.dma_desc.cookie.dmac_address >> 8);
5630c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5631c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, FH_RSCSR_CHNL0_STTS_WPTR_REG,
5632c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    ((uint32_t)(sc->sc_dma_sh.cookie.dmac_address +
5633c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    offsetof(struct iwh_shared, val0)) >> 4));
5634c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5635c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, FH_MEM_RCSR_CHNL0_CONFIG_REG,
5636c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
5637c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
5638e2cf88acSQuaker Fang 	    IWH_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K |
5639c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    (RX_QUEUE_SIZE_LOG <<
5640c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT));
5641c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_mac_access_exit(sc);
5642c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_WPTR_REG,
5643c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    (RX_QUEUE_SIZE - 1) & ~0x7);
5644c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5645c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
5646c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * init Tx rings
5647c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
5648c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_mac_access_enter(sc);
5649c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_reg_write(sc, IWH_SCD_TXFACT, 0);
5650c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5651c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
5652c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * keep warm page
5653c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
5654c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, IWH_FH_KW_MEM_ADDR_REG,
5655c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    sc->sc_dma_kw.cookie.dmac_address >> 4);
5656c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5657c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	for (qid = 0; qid < IWH_NUM_QUEUES; qid++) {
5658c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		IWH_WRITE(sc, FH_MEM_CBBC_QUEUE(qid),
5659c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    sc->sc_txq[qid].dma_desc.cookie.dmac_address >> 8);
5660c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		IWH_WRITE(sc, IWH_FH_TCSR_CHNL_TX_CONFIG_REG(qid),
5661c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    IWH_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
5662c7ee0b5cSfei feng - Sun Microsystems - Beijing China 		    IWH_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL);
5663c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	}
5664c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5665c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	iwh_mac_access_exit(sc);
5666c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5667c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
5668c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * clear "radio off" and "disable command" bits
5669c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
5670c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
5671c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_UCODE_DRV_GP1_CLR,
5672c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
5673c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5674c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
5675c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * clear any pending interrupts
5676c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
5677c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_INT, 0xffffffff);
5678c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5679c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	/*
5680c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 * enable interrupts
5681c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	 */
5682c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_INT_MASK, CSR_INI_SET_MASK);
5683c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5684c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
5685c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
5686c7ee0b5cSfei feng - Sun Microsystems - Beijing China 
5687c7ee0b5cSfei feng - Sun Microsystems - Beijing China 	return (IWH_SUCCESS);
5688c7ee0b5cSfei feng - Sun Microsystems - Beijing China }
56896f12def4Spengcheng chen - Sun Microsystems - Beijing China 
56906f12def4Spengcheng chen - Sun Microsystems - Beijing China static int
56916f12def4Spengcheng chen - Sun Microsystems - Beijing China iwh_fast_recover(iwh_sc_t *sc)
56926f12def4Spengcheng chen - Sun Microsystems - Beijing China {
56936f12def4Spengcheng chen - Sun Microsystems - Beijing China 	ieee80211com_t *ic = &sc->sc_ic;
5694e2cf88acSQuaker Fang 	int err = IWH_FAIL;
56956f12def4Spengcheng chen - Sun Microsystems - Beijing China 
56966f12def4Spengcheng chen - Sun Microsystems - Beijing China 	mutex_enter(&sc->sc_glock);
56976f12def4Spengcheng chen - Sun Microsystems - Beijing China 
569889b2a9fbSfei feng - Sun Microsystems - Beijing China 	/*
569989b2a9fbSfei feng - Sun Microsystems - Beijing China 	 * restore runtime configuration
570089b2a9fbSfei feng - Sun Microsystems - Beijing China 	 */
57016f12def4Spengcheng chen - Sun Microsystems - Beijing China 	bcopy(&sc->sc_config_save, &sc->sc_config,
57026f12def4Spengcheng chen - Sun Microsystems - Beijing China 	    sizeof (sc->sc_config));
57036f12def4Spengcheng chen - Sun Microsystems - Beijing China 
57046f12def4Spengcheng chen - Sun Microsystems - Beijing China 	sc->sc_config.assoc_id = 0;
57056f12def4Spengcheng chen - Sun Microsystems - Beijing China 	sc->sc_config.filter_flags &= ~LE_32(RXON_FILTER_ASSOC_MSK);
57066f12def4Spengcheng chen - Sun Microsystems - Beijing China 
5707e2cf88acSQuaker Fang 	if ((err = iwh_hw_set_before_auth(sc)) != IWH_SUCCESS) {
57086f12def4Spengcheng chen - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_fast_recover(): "
57096f12def4Spengcheng chen - Sun Microsystems - Beijing China 		    "could not setup authentication\n");
57106f12def4Spengcheng chen - Sun Microsystems - Beijing China 		mutex_exit(&sc->sc_glock);
57116f12def4Spengcheng chen - Sun Microsystems - Beijing China 		return (err);
57126f12def4Spengcheng chen - Sun Microsystems - Beijing China 	}
57136f12def4Spengcheng chen - Sun Microsystems - Beijing China 
57146f12def4Spengcheng chen - Sun Microsystems - Beijing China 	bcopy(&sc->sc_config_save, &sc->sc_config,
57156f12def4Spengcheng chen - Sun Microsystems - Beijing China 	    sizeof (sc->sc_config));
57166f12def4Spengcheng chen - Sun Microsystems - Beijing China 
571789b2a9fbSfei feng - Sun Microsystems - Beijing China 	/*
571889b2a9fbSfei feng - Sun Microsystems - Beijing China 	 * update adapter's configuration
571989b2a9fbSfei feng - Sun Microsystems - Beijing China 	 */
57206f12def4Spengcheng chen - Sun Microsystems - Beijing China 	err = iwh_run_state_config(sc);
57216f12def4Spengcheng chen - Sun Microsystems - Beijing China 	if (err != IWH_SUCCESS) {
57226f12def4Spengcheng chen - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_fast_recover(): "
57236f12def4Spengcheng chen - Sun Microsystems - Beijing China 		    "failed to setup association\n");
57246f12def4Spengcheng chen - Sun Microsystems - Beijing China 		mutex_exit(&sc->sc_glock);
57256f12def4Spengcheng chen - Sun Microsystems - Beijing China 		return (err);
57266f12def4Spengcheng chen - Sun Microsystems - Beijing China 	}
572789b2a9fbSfei feng - Sun Microsystems - Beijing China 
572889b2a9fbSfei feng - Sun Microsystems - Beijing China 	/*
572989b2a9fbSfei feng - Sun Microsystems - Beijing China 	 * set LED on
573089b2a9fbSfei feng - Sun Microsystems - Beijing China 	 */
57316f12def4Spengcheng chen - Sun Microsystems - Beijing China 	iwh_set_led(sc, 2, 0, 1);
57326f12def4Spengcheng chen - Sun Microsystems - Beijing China 
57336f12def4Spengcheng chen - Sun Microsystems - Beijing China 	mutex_exit(&sc->sc_glock);
57346f12def4Spengcheng chen - Sun Microsystems - Beijing China 
573589b2a9fbSfei feng - Sun Microsystems - Beijing China 	atomic_and_32(&sc->sc_flags, ~IWH_F_HW_ERR_RECOVER);
57366f12def4Spengcheng chen - Sun Microsystems - Beijing China 
573789b2a9fbSfei feng - Sun Microsystems - Beijing China 	/*
573889b2a9fbSfei feng - Sun Microsystems - Beijing China 	 * start queue
573989b2a9fbSfei feng - Sun Microsystems - Beijing China 	 */
5740e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_FW, "iwh_fast_recover(): "
5741e2cf88acSQuaker Fang 	    "resume xmit\n"));
57426f12def4Spengcheng chen - Sun Microsystems - Beijing China 	mac_tx_update(ic->ic_mach);
57436f12def4Spengcheng chen - Sun Microsystems - Beijing China 
57446f12def4Spengcheng chen - Sun Microsystems - Beijing China 	return (IWH_SUCCESS);
57456f12def4Spengcheng chen - Sun Microsystems - Beijing China }
57466f12def4Spengcheng chen - Sun Microsystems - Beijing China 
57476f12def4Spengcheng chen - Sun Microsystems - Beijing China static int
57486f12def4Spengcheng chen - Sun Microsystems - Beijing China iwh_run_state_config(iwh_sc_t *sc)
57496f12def4Spengcheng chen - Sun Microsystems - Beijing China {
57506f12def4Spengcheng chen - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
57516f12def4Spengcheng chen - Sun Microsystems - Beijing China 	ieee80211_node_t *in = ic->ic_bss;
5752e2cf88acSQuaker Fang 	uint32_t ht_protec = (uint32_t)(-1);
5753e2cf88acSQuaker Fang 	int err = IWH_FAIL;
57546f12def4Spengcheng chen - Sun Microsystems - Beijing China 
57556f12def4Spengcheng chen - Sun Microsystems - Beijing China 	/*
57566f12def4Spengcheng chen - Sun Microsystems - Beijing China 	 * update adapter's configuration
57576f12def4Spengcheng chen - Sun Microsystems - Beijing China 	 */
57586f12def4Spengcheng chen - Sun Microsystems - Beijing China 	sc->sc_config.assoc_id = in->in_associd & 0x3fff;
57596f12def4Spengcheng chen - Sun Microsystems - Beijing China 
57606f12def4Spengcheng chen - Sun Microsystems - Beijing China 	/*
57616f12def4Spengcheng chen - Sun Microsystems - Beijing China 	 * short preamble/slot time are
57626f12def4Spengcheng chen - Sun Microsystems - Beijing China 	 * negotiated when associating
57636f12def4Spengcheng chen - Sun Microsystems - Beijing China 	 */
57646f12def4Spengcheng chen - Sun Microsystems - Beijing China 	sc->sc_config.flags &=
57656f12def4Spengcheng chen - Sun Microsystems - Beijing China 	    ~LE_32(RXON_FLG_SHORT_PREAMBLE_MSK |
57666f12def4Spengcheng chen - Sun Microsystems - Beijing China 	    RXON_FLG_SHORT_SLOT_MSK);
57676f12def4Spengcheng chen - Sun Microsystems - Beijing China 
57686f12def4Spengcheng chen - Sun Microsystems - Beijing China 	if (ic->ic_flags & IEEE80211_F_SHSLOT) {
57696f12def4Spengcheng chen - Sun Microsystems - Beijing China 		sc->sc_config.flags |=
57706f12def4Spengcheng chen - Sun Microsystems - Beijing China 		    LE_32(RXON_FLG_SHORT_SLOT_MSK);
57716f12def4Spengcheng chen - Sun Microsystems - Beijing China 	}
57726f12def4Spengcheng chen - Sun Microsystems - Beijing China 
57736f12def4Spengcheng chen - Sun Microsystems - Beijing China 	if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) {
57746f12def4Spengcheng chen - Sun Microsystems - Beijing China 		sc->sc_config.flags |=
57756f12def4Spengcheng chen - Sun Microsystems - Beijing China 		    LE_32(RXON_FLG_SHORT_PREAMBLE_MSK);
57766f12def4Spengcheng chen - Sun Microsystems - Beijing China 	}
57776f12def4Spengcheng chen - Sun Microsystems - Beijing China 
5778e2cf88acSQuaker Fang 	if (in->in_flags & IEEE80211_NODE_HT) {
5779e2cf88acSQuaker Fang 		ht_protec = in->in_htopmode;
5780e2cf88acSQuaker Fang 		if (ht_protec > 3) {
5781e2cf88acSQuaker Fang 			cmn_err(CE_WARN, "iwh_run_state_config(): "
5782e2cf88acSQuaker Fang 			    "HT protection mode is not correct.\n");
5783e2cf88acSQuaker Fang 			return (IWH_FAIL);
5784e2cf88acSQuaker Fang 		} else if (NO_HT_PROT == ht_protec) {
5785e2cf88acSQuaker Fang 			ht_protec = sc->sc_ht_conf.ht_protection;
5786e2cf88acSQuaker Fang 		}
5787e2cf88acSQuaker Fang 
5788e2cf88acSQuaker Fang 		sc->sc_config.flags |=
5789e2cf88acSQuaker Fang 		    LE_32(ht_protec << RXON_FLG_HT_OPERATING_MODE_POS);
5790e2cf88acSQuaker Fang 	}
5791e2cf88acSQuaker Fang 
5792e2cf88acSQuaker Fang 	/*
5793e2cf88acSQuaker Fang 	 * set RX chains/antennas.
5794e2cf88acSQuaker Fang 	 */
5795e2cf88acSQuaker Fang 	iwh_config_rxon_chain(sc);
5796e2cf88acSQuaker Fang 
57976f12def4Spengcheng chen - Sun Microsystems - Beijing China 	sc->sc_config.filter_flags |=
57986f12def4Spengcheng chen - Sun Microsystems - Beijing China 	    LE_32(RXON_FILTER_ASSOC_MSK);
57996f12def4Spengcheng chen - Sun Microsystems - Beijing China 
58006f12def4Spengcheng chen - Sun Microsystems - Beijing China 	if (ic->ic_opmode != IEEE80211_M_STA) {
58016f12def4Spengcheng chen - Sun Microsystems - Beijing China 		sc->sc_config.filter_flags |=
58026f12def4Spengcheng chen - Sun Microsystems - Beijing China 		    LE_32(RXON_FILTER_BCON_AWARE_MSK);
58036f12def4Spengcheng chen - Sun Microsystems - Beijing China 	}
58046f12def4Spengcheng chen - Sun Microsystems - Beijing China 
5805e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_80211, "iwh_run_state_config(): "
5806e2cf88acSQuaker Fang 	    "config chan %d flags %x"
58076f12def4Spengcheng chen - Sun Microsystems - Beijing China 	    " filter_flags %x\n",
58086f12def4Spengcheng chen - Sun Microsystems - Beijing China 	    sc->sc_config.chan, sc->sc_config.flags,
58096f12def4Spengcheng chen - Sun Microsystems - Beijing China 	    sc->sc_config.filter_flags));
58106f12def4Spengcheng chen - Sun Microsystems - Beijing China 
58116f12def4Spengcheng chen - Sun Microsystems - Beijing China 	err = iwh_cmd(sc, REPLY_RXON, &sc->sc_config,
58126f12def4Spengcheng chen - Sun Microsystems - Beijing China 	    sizeof (iwh_rxon_cmd_t), 1);
58136f12def4Spengcheng chen - Sun Microsystems - Beijing China 	if (err != IWH_SUCCESS) {
58146f12def4Spengcheng chen - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "iwh_run_state_config(): "
58156f12def4Spengcheng chen - Sun Microsystems - Beijing China 		    "could not update configuration\n");
58166f12def4Spengcheng chen - Sun Microsystems - Beijing China 		return (err);
58176f12def4Spengcheng chen - Sun Microsystems - Beijing China 	}
58186f12def4Spengcheng chen - Sun Microsystems - Beijing China 
581989b2a9fbSfei feng - Sun Microsystems - Beijing China 	if ((sc->sc_dev_id != 0x423c) &&
582089b2a9fbSfei feng - Sun Microsystems - Beijing China 	    (sc->sc_dev_id != 0x423d)) {
58216f12def4Spengcheng chen - Sun Microsystems - Beijing China 		/*
58226f12def4Spengcheng chen - Sun Microsystems - Beijing China 		 * send tx power table command
58236f12def4Spengcheng chen - Sun Microsystems - Beijing China 		 */
58246f12def4Spengcheng chen - Sun Microsystems - Beijing China 		err = iwh_tx_power_table(sc, 1);
58256f12def4Spengcheng chen - Sun Microsystems - Beijing China 		if (err != IWH_SUCCESS) {
58266f12def4Spengcheng chen - Sun Microsystems - Beijing China 			return (err);
58276f12def4Spengcheng chen - Sun Microsystems - Beijing China 		}
582889b2a9fbSfei feng - Sun Microsystems - Beijing China 	}
58296f12def4Spengcheng chen - Sun Microsystems - Beijing China 
5830e2cf88acSQuaker Fang 	/*
5831e2cf88acSQuaker Fang 	 * Not need to update retry rate table for AP node
5832e2cf88acSQuaker Fang 	 */
5833e2cf88acSQuaker Fang 	err = iwh_qosparam_to_hw(sc, 1);
5834e2cf88acSQuaker Fang 	if (err != IWH_SUCCESS) {
5835e2cf88acSQuaker Fang 		return (err);
5836e2cf88acSQuaker Fang 	}
5837e2cf88acSQuaker Fang 
5838e2cf88acSQuaker Fang 	return (err);
5839e2cf88acSQuaker Fang }
5840e2cf88acSQuaker Fang 
5841e2cf88acSQuaker Fang /*
5842e2cf88acSQuaker Fang  * This function is only for compatibility with Net80211 module.
5843e2cf88acSQuaker Fang  * iwh_qosparam_to_hw() is the actual function updating EDCA
5844e2cf88acSQuaker Fang  * parameters to hardware.
5845e2cf88acSQuaker Fang  */
5846e2cf88acSQuaker Fang /* ARGSUSED */
5847e2cf88acSQuaker Fang static int
5848e2cf88acSQuaker Fang iwh_wme_update(ieee80211com_t *ic)
5849e2cf88acSQuaker Fang {
5850e2cf88acSQuaker Fang 	return (0);
5851e2cf88acSQuaker Fang }
5852e2cf88acSQuaker Fang 
5853e2cf88acSQuaker Fang static int
5854e2cf88acSQuaker Fang iwh_wme_to_qos_ac(int wme_ac)
5855e2cf88acSQuaker Fang {
5856e2cf88acSQuaker Fang 	int qos_ac = QOS_AC_INVALID;
5857e2cf88acSQuaker Fang 
5858e2cf88acSQuaker Fang 	if (wme_ac < WME_AC_BE || wme_ac > WME_AC_VO) {
5859e2cf88acSQuaker Fang 		cmn_err(CE_WARN, "iwh_wme_to_qos_ac(): "
5860e2cf88acSQuaker Fang 		    "WME AC index is not in suitable range.\n");
5861e2cf88acSQuaker Fang 		return (qos_ac);
5862e2cf88acSQuaker Fang 	}
5863e2cf88acSQuaker Fang 
5864e2cf88acSQuaker Fang 	switch (wme_ac) {
5865e2cf88acSQuaker Fang 	case WME_AC_BE:
5866e2cf88acSQuaker Fang 		qos_ac = QOS_AC_BK;
5867e2cf88acSQuaker Fang 		break;
5868e2cf88acSQuaker Fang 	case WME_AC_BK:
5869e2cf88acSQuaker Fang 		qos_ac = QOS_AC_BE;
5870e2cf88acSQuaker Fang 		break;
5871e2cf88acSQuaker Fang 	case WME_AC_VI:
5872e2cf88acSQuaker Fang 		qos_ac = QOS_AC_VI;
5873e2cf88acSQuaker Fang 		break;
5874e2cf88acSQuaker Fang 	case WME_AC_VO:
5875e2cf88acSQuaker Fang 		qos_ac = QOS_AC_VO;
5876e2cf88acSQuaker Fang 		break;
5877e2cf88acSQuaker Fang 	}
5878e2cf88acSQuaker Fang 
5879e2cf88acSQuaker Fang 	return (qos_ac);
5880e2cf88acSQuaker Fang }
5881e2cf88acSQuaker Fang 
5882e2cf88acSQuaker Fang static uint16_t
5883e2cf88acSQuaker Fang iwh_cw_e_to_cw(uint8_t cw_e)
5884e2cf88acSQuaker Fang {
5885e2cf88acSQuaker Fang 	uint16_t cw = 1;
5886e2cf88acSQuaker Fang 
5887e2cf88acSQuaker Fang 	while (cw_e > 0) {
5888e2cf88acSQuaker Fang 		cw <<= 1;
5889e2cf88acSQuaker Fang 		cw_e--;
5890e2cf88acSQuaker Fang 	}
5891e2cf88acSQuaker Fang 
5892e2cf88acSQuaker Fang 	cw -= 1;
5893e2cf88acSQuaker Fang 	return (cw);
5894e2cf88acSQuaker Fang }
5895e2cf88acSQuaker Fang 
5896e2cf88acSQuaker Fang static int
5897e2cf88acSQuaker Fang iwh_wmeparam_check(struct wmeParams *wmeparam)
5898e2cf88acSQuaker Fang {
5899e2cf88acSQuaker Fang 	int i;
5900e2cf88acSQuaker Fang 
5901e2cf88acSQuaker Fang 	for (i = 0; i < WME_NUM_AC; i++) {
5902e2cf88acSQuaker Fang 
5903e2cf88acSQuaker Fang 		if ((wmeparam[i].wmep_logcwmax > QOS_CW_RANGE_MAX) ||
5904e2cf88acSQuaker Fang 		    (wmeparam[i].wmep_logcwmin >= wmeparam[i].wmep_logcwmax)) {
5905e2cf88acSQuaker Fang 			cmn_err(CE_WARN, "iwh_wmeparam_check(): "
5906e2cf88acSQuaker Fang 			    "Contention window is not in suitable range.\n");
5907e2cf88acSQuaker Fang 			return (IWH_FAIL);
5908e2cf88acSQuaker Fang 		}
5909e2cf88acSQuaker Fang 
5910e2cf88acSQuaker Fang 		if ((wmeparam[i].wmep_aifsn < QOS_AIFSN_MIN) ||
5911e2cf88acSQuaker Fang 		    (wmeparam[i].wmep_aifsn > QOS_AIFSN_MAX)) {
5912e2cf88acSQuaker Fang 			cmn_err(CE_WARN, "iwh_wmeparam_check(): "
5913e2cf88acSQuaker Fang 			    "Arbitration interframe space number"
5914e2cf88acSQuaker Fang 			    "is not in suitable range.\n");
5915e2cf88acSQuaker Fang 			return (IWH_FAIL);
5916e2cf88acSQuaker Fang 		}
5917e2cf88acSQuaker Fang 	}
5918e2cf88acSQuaker Fang 
59196f12def4Spengcheng chen - Sun Microsystems - Beijing China 	return (IWH_SUCCESS);
59206f12def4Spengcheng chen - Sun Microsystems - Beijing China }
5921e2cf88acSQuaker Fang 
5922e2cf88acSQuaker Fang /*
5923e2cf88acSQuaker Fang  * This function updates EDCA parameters into hardware.
5924e2cf88acSQuaker Fang  * FIFO0-background, FIFO1-best effort, FIFO2-viedo, FIFO3-voice.
5925e2cf88acSQuaker Fang  */
5926e2cf88acSQuaker Fang static int
5927e2cf88acSQuaker Fang iwh_qosparam_to_hw(iwh_sc_t *sc, int async)
5928e2cf88acSQuaker Fang {
5929e2cf88acSQuaker Fang 	ieee80211com_t *ic = &sc->sc_ic;
5930e2cf88acSQuaker Fang 	ieee80211_node_t *in = ic->ic_bss;
5931e2cf88acSQuaker Fang 	struct wmeParams *wmeparam;
5932e2cf88acSQuaker Fang 	iwh_qos_param_cmd_t qosparam_cmd;
5933e2cf88acSQuaker Fang 	int i, j;
5934e2cf88acSQuaker Fang 	int err = IWH_FAIL;
5935e2cf88acSQuaker Fang 
5936e2cf88acSQuaker Fang 	if ((in->in_flags & IEEE80211_NODE_QOS) &&
5937e2cf88acSQuaker Fang 	    (IEEE80211_M_STA == ic->ic_opmode)) {
5938e2cf88acSQuaker Fang 		wmeparam = ic->ic_wme.wme_chanParams.cap_wmeParams;
5939e2cf88acSQuaker Fang 	} else {
5940e2cf88acSQuaker Fang 		return (IWH_SUCCESS);
5941e2cf88acSQuaker Fang 	}
5942e2cf88acSQuaker Fang 
5943e2cf88acSQuaker Fang 	(void) memset(&qosparam_cmd, 0, sizeof (qosparam_cmd));
5944e2cf88acSQuaker Fang 
5945e2cf88acSQuaker Fang 	err = iwh_wmeparam_check(wmeparam);
5946e2cf88acSQuaker Fang 	if (err != IWH_SUCCESS) {
5947e2cf88acSQuaker Fang 		return (err);
5948e2cf88acSQuaker Fang 	}
5949e2cf88acSQuaker Fang 
5950e2cf88acSQuaker Fang 	if (in->in_flags & IEEE80211_NODE_QOS) {
5951e2cf88acSQuaker Fang 		qosparam_cmd.flags |= QOS_PARAM_FLG_UPDATE_EDCA;
5952e2cf88acSQuaker Fang 	}
5953e2cf88acSQuaker Fang 
5954e2cf88acSQuaker Fang 	if (in->in_flags & (IEEE80211_NODE_QOS | IEEE80211_NODE_HT)) {
5955e2cf88acSQuaker Fang 		qosparam_cmd.flags |= QOS_PARAM_FLG_TGN;
5956e2cf88acSQuaker Fang 	}
5957e2cf88acSQuaker Fang 
5958e2cf88acSQuaker Fang 	for (i = 0; i < WME_NUM_AC; i++) {
5959e2cf88acSQuaker Fang 
5960e2cf88acSQuaker Fang 		j = iwh_wme_to_qos_ac(i);
5961e2cf88acSQuaker Fang 		if (j < QOS_AC_BK || j > QOS_AC_VO) {
5962e2cf88acSQuaker Fang 			return (IWH_FAIL);
5963e2cf88acSQuaker Fang 		}
5964e2cf88acSQuaker Fang 
5965e2cf88acSQuaker Fang 		qosparam_cmd.ac[j].cw_min =
5966e2cf88acSQuaker Fang 		    iwh_cw_e_to_cw(wmeparam[i].wmep_logcwmin);
5967e2cf88acSQuaker Fang 		qosparam_cmd.ac[j].cw_max =
5968e2cf88acSQuaker Fang 		    iwh_cw_e_to_cw(wmeparam[i].wmep_logcwmax);
5969e2cf88acSQuaker Fang 		qosparam_cmd.ac[j].aifsn =
5970e2cf88acSQuaker Fang 		    wmeparam[i].wmep_aifsn;
5971e2cf88acSQuaker Fang 		qosparam_cmd.ac[j].txop =
5972e2cf88acSQuaker Fang 		    (uint16_t)(wmeparam[i].wmep_txopLimit * 32);
5973e2cf88acSQuaker Fang 	}
5974e2cf88acSQuaker Fang 
5975e2cf88acSQuaker Fang 	err = iwh_cmd(sc, REPLY_QOS_PARAM, &qosparam_cmd,
5976e2cf88acSQuaker Fang 	    sizeof (qosparam_cmd), async);
5977e2cf88acSQuaker Fang 	if (err != IWH_SUCCESS) {
5978e2cf88acSQuaker Fang 		cmn_err(CE_WARN, "iwh_qosparam_to_hw(): "
5979e2cf88acSQuaker Fang 		    "failed to update QoS parameters into hardware.\n");
5980e2cf88acSQuaker Fang 		return (err);
5981e2cf88acSQuaker Fang 	}
5982e2cf88acSQuaker Fang 
5983e2cf88acSQuaker Fang #ifdef	DEBUG
5984e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_QOS, "iwh_qosparam_to_hw(): "
5985e2cf88acSQuaker Fang 	    "EDCA parameters are as follows:\n"));
5986e2cf88acSQuaker Fang 
5987e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_QOS, "BK parameters are: "
5988e2cf88acSQuaker Fang 	    "cw_min = %d, cw_max = %d, aifsn = %d, txop = %d\n",
5989e2cf88acSQuaker Fang 	    qosparam_cmd.ac[0].cw_min, qosparam_cmd.ac[0].cw_max,
5990e2cf88acSQuaker Fang 	    qosparam_cmd.ac[0].aifsn, qosparam_cmd.ac[0].txop));
5991e2cf88acSQuaker Fang 
5992e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_QOS, "BE parameters are: "
5993e2cf88acSQuaker Fang 	    "cw_min = %d, cw_max = %d, aifsn = %d, txop = %d\n",
5994e2cf88acSQuaker Fang 	    qosparam_cmd.ac[1].cw_min, qosparam_cmd.ac[1].cw_max,
5995e2cf88acSQuaker Fang 	    qosparam_cmd.ac[1].aifsn, qosparam_cmd.ac[1].txop));
5996e2cf88acSQuaker Fang 
5997e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_QOS, "VI parameters are: "
5998e2cf88acSQuaker Fang 	    "cw_min = %d, cw_max = %d, aifsn = %d, txop = %d\n",
5999e2cf88acSQuaker Fang 	    qosparam_cmd.ac[2].cw_min, qosparam_cmd.ac[2].cw_max,
6000e2cf88acSQuaker Fang 	    qosparam_cmd.ac[2].aifsn, qosparam_cmd.ac[2].txop));
6001e2cf88acSQuaker Fang 
6002e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_QOS, "VO parameters are: "
6003e2cf88acSQuaker Fang 	    "cw_min = %d, cw_max = %d, aifsn = %d, txop = %d\n",
6004e2cf88acSQuaker Fang 	    qosparam_cmd.ac[3].cw_min, qosparam_cmd.ac[3].cw_max,
6005e2cf88acSQuaker Fang 	    qosparam_cmd.ac[3].aifsn, qosparam_cmd.ac[3].txop));
6006e2cf88acSQuaker Fang #endif
6007e2cf88acSQuaker Fang 	return (err);
6008e2cf88acSQuaker Fang }
6009e2cf88acSQuaker Fang 
6010e2cf88acSQuaker Fang static inline int
6011e2cf88acSQuaker Fang iwh_wme_tid_qos_ac(int tid)
6012e2cf88acSQuaker Fang {
6013e2cf88acSQuaker Fang 	switch (tid) {
6014e2cf88acSQuaker Fang 	case 1:
6015e2cf88acSQuaker Fang 	case 2:
6016e2cf88acSQuaker Fang 		return (QOS_AC_BK);
6017e2cf88acSQuaker Fang 	case 0:
6018e2cf88acSQuaker Fang 	case 3:
6019e2cf88acSQuaker Fang 		return (QOS_AC_BE);
6020e2cf88acSQuaker Fang 	case 4:
6021e2cf88acSQuaker Fang 	case 5:
6022e2cf88acSQuaker Fang 		return (QOS_AC_VI);
6023e2cf88acSQuaker Fang 	case 6:
6024e2cf88acSQuaker Fang 	case 7:
6025e2cf88acSQuaker Fang 		return (QOS_AC_VO);
6026e2cf88acSQuaker Fang 	}
6027e2cf88acSQuaker Fang 
6028e2cf88acSQuaker Fang 	return (QOS_AC_BE);
6029e2cf88acSQuaker Fang }
6030e2cf88acSQuaker Fang 
6031e2cf88acSQuaker Fang static inline int
6032e2cf88acSQuaker Fang iwh_qos_ac_to_txq(int qos_ac)
6033e2cf88acSQuaker Fang {
6034e2cf88acSQuaker Fang 	switch (qos_ac) {
6035e2cf88acSQuaker Fang 	case QOS_AC_BK:
6036e2cf88acSQuaker Fang 		return (QOS_AC_BK_TO_TXQ);
6037e2cf88acSQuaker Fang 	case QOS_AC_BE:
6038e2cf88acSQuaker Fang 		return (QOS_AC_BE_TO_TXQ);
6039e2cf88acSQuaker Fang 	case QOS_AC_VI:
6040e2cf88acSQuaker Fang 		return (QOS_AC_VI_TO_TXQ);
6041e2cf88acSQuaker Fang 	case QOS_AC_VO:
6042e2cf88acSQuaker Fang 		return (QOS_AC_VO_TO_TXQ);
6043e2cf88acSQuaker Fang 	}
6044e2cf88acSQuaker Fang 
6045e2cf88acSQuaker Fang 	return (QOS_AC_BE_TO_TXQ);
6046e2cf88acSQuaker Fang }
6047e2cf88acSQuaker Fang 
6048e2cf88acSQuaker Fang static int
6049e2cf88acSQuaker Fang iwh_wme_tid_to_txq(int tid)
6050e2cf88acSQuaker Fang {
6051e2cf88acSQuaker Fang 	int queue_n = TXQ_FOR_AC_INVALID;
6052e2cf88acSQuaker Fang 	int qos_ac;
6053e2cf88acSQuaker Fang 
6054e2cf88acSQuaker Fang 	if (tid < WME_TID_MIN ||
6055e2cf88acSQuaker Fang 	    tid > WME_TID_MAX) {
6056e2cf88acSQuaker Fang 		cmn_err(CE_WARN, "wme_tid_to_txq(): "
6057e2cf88acSQuaker Fang 		    "TID is not in suitable range.\n");
6058e2cf88acSQuaker Fang 		return (queue_n);
6059e2cf88acSQuaker Fang 	}
6060e2cf88acSQuaker Fang 
6061e2cf88acSQuaker Fang 	qos_ac = iwh_wme_tid_qos_ac(tid);
6062e2cf88acSQuaker Fang 	queue_n = iwh_qos_ac_to_txq(qos_ac);
6063e2cf88acSQuaker Fang 
6064e2cf88acSQuaker Fang 	return (queue_n);
6065e2cf88acSQuaker Fang }
6066e2cf88acSQuaker Fang 
6067e2cf88acSQuaker Fang /*
6068e2cf88acSQuaker Fang  * This function is used for intializing HT relevant configurations.
6069e2cf88acSQuaker Fang  */
6070e2cf88acSQuaker Fang static void
6071e2cf88acSQuaker Fang iwh_init_ht_conf(iwh_sc_t *sc)
6072e2cf88acSQuaker Fang {
6073e2cf88acSQuaker Fang 	(void) memset(&sc->sc_ht_conf, 0, sizeof (iwh_ht_conf_t));
6074e2cf88acSQuaker Fang 
6075e2cf88acSQuaker Fang 	if ((0x4235 == sc->sc_dev_id) ||
6076e2cf88acSQuaker Fang 	    (0x4236 == sc->sc_dev_id) ||
6077e2cf88acSQuaker Fang 	    (0x423a == sc->sc_dev_id)) {
6078e2cf88acSQuaker Fang 		sc->sc_ht_conf.ht_support = 1;
6079e2cf88acSQuaker Fang 
6080e2cf88acSQuaker Fang 		sc->sc_ht_conf.valid_chains = 3;
6081e2cf88acSQuaker Fang 		sc->sc_ht_conf.tx_stream_count = 2;
6082e2cf88acSQuaker Fang 		sc->sc_ht_conf.rx_stream_count = 2;
6083e2cf88acSQuaker Fang 
6084e2cf88acSQuaker Fang 		sc->sc_ht_conf.tx_support_mcs[0] = 0xff;
6085e2cf88acSQuaker Fang 		sc->sc_ht_conf.tx_support_mcs[1] = 0xff;
6086e2cf88acSQuaker Fang 		sc->sc_ht_conf.rx_support_mcs[0] = 0xff;
6087e2cf88acSQuaker Fang 		sc->sc_ht_conf.rx_support_mcs[1] = 0xff;
6088e2cf88acSQuaker Fang 	} else {
6089e2cf88acSQuaker Fang 		sc->sc_ht_conf.ht_support = 1;
6090e2cf88acSQuaker Fang 
6091e2cf88acSQuaker Fang 		sc->sc_ht_conf.valid_chains = 2;
6092e2cf88acSQuaker Fang 		sc->sc_ht_conf.tx_stream_count = 1;
6093e2cf88acSQuaker Fang 		sc->sc_ht_conf.rx_stream_count = 2;
6094e2cf88acSQuaker Fang 
6095e2cf88acSQuaker Fang 		sc->sc_ht_conf.tx_support_mcs[0] = 0xff;
6096e2cf88acSQuaker Fang 		sc->sc_ht_conf.rx_support_mcs[0] = 0xff;
6097e2cf88acSQuaker Fang 		sc->sc_ht_conf.rx_support_mcs[1] = 0xff;
6098e2cf88acSQuaker Fang 	}
6099e2cf88acSQuaker Fang 
6100e2cf88acSQuaker Fang 	if (sc->sc_ht_conf.ht_support) {
6101e2cf88acSQuaker Fang 		sc->sc_ht_conf.cap |= HT_CAP_GRN_FLD;
6102e2cf88acSQuaker Fang 		sc->sc_ht_conf.cap |= HT_CAP_SGI_20;
6103e2cf88acSQuaker Fang 		sc->sc_ht_conf.cap |= HT_CAP_MAX_AMSDU;
6104e2cf88acSQuaker Fang 		/* should disable MIMO */
6105e2cf88acSQuaker Fang 		sc->sc_ht_conf.cap |= HT_CAP_MIMO_PS;
6106e2cf88acSQuaker Fang 
6107e2cf88acSQuaker Fang 		sc->sc_ht_conf.ampdu_p.factor = HT_RX_AMPDU_FACTOR;
6108e2cf88acSQuaker Fang 		sc->sc_ht_conf.ampdu_p.density = HT_MPDU_DENSITY;
6109e2cf88acSQuaker Fang 
6110e2cf88acSQuaker Fang 		sc->sc_ht_conf.ht_protection = HT_PROT_CHAN_NON_HT;
6111e2cf88acSQuaker Fang 	}
6112e2cf88acSQuaker Fang }
6113e2cf88acSQuaker Fang 
6114e2cf88acSQuaker Fang /*
6115e2cf88acSQuaker Fang  * This function overwrites default ieee80211_rateset_11n struc.
6116e2cf88acSQuaker Fang  */
6117e2cf88acSQuaker Fang static void
6118e2cf88acSQuaker Fang iwh_overwrite_11n_rateset(iwh_sc_t *sc)
6119e2cf88acSQuaker Fang {
6120e2cf88acSQuaker Fang 	uint8_t *ht_rs = sc->sc_ht_conf.rx_support_mcs;
6121e2cf88acSQuaker Fang 	int mcs_idx, mcs_count = 0;
6122e2cf88acSQuaker Fang 	int i, j;
6123e2cf88acSQuaker Fang 
6124e2cf88acSQuaker Fang 	for (i = 0; i < HT_RATESET_NUM; i++) {
6125e2cf88acSQuaker Fang 		for (j = 0; j < 8; j++) {
6126e2cf88acSQuaker Fang 			if (ht_rs[i] & (1 << j)) {
6127e2cf88acSQuaker Fang 				mcs_idx = i * 8 + j;
6128e2cf88acSQuaker Fang 				if (mcs_idx >= IEEE80211_HTRATE_MAXSIZE) {
6129e2cf88acSQuaker Fang 					break;
6130e2cf88acSQuaker Fang 				}
6131e2cf88acSQuaker Fang 
6132e2cf88acSQuaker Fang 				ieee80211_rateset_11n.rs_rates[mcs_idx] =
6133e2cf88acSQuaker Fang 				    (uint8_t)mcs_idx;
6134e2cf88acSQuaker Fang 				mcs_count++;
6135e2cf88acSQuaker Fang 			}
6136e2cf88acSQuaker Fang 		}
6137e2cf88acSQuaker Fang 	}
6138e2cf88acSQuaker Fang 
6139e2cf88acSQuaker Fang 	ieee80211_rateset_11n.rs_nrates = (uint8_t)mcs_count;
6140e2cf88acSQuaker Fang 
6141e2cf88acSQuaker Fang #ifdef	DEBUG
6142e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_HTRATE, "iwh_overwrite_11n_rateset(): "
6143e2cf88acSQuaker Fang 	    "HT rates supported by this station is as follows:\n"));
6144e2cf88acSQuaker Fang 
6145e2cf88acSQuaker Fang 	for (i = 0; i < ieee80211_rateset_11n.rs_nrates; i++) {
6146e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_HTRATE, "Rate %d is %d\n",
6147e2cf88acSQuaker Fang 		    i, ieee80211_rateset_11n.rs_rates[i]));
6148e2cf88acSQuaker Fang 	}
6149e2cf88acSQuaker Fang #endif
6150e2cf88acSQuaker Fang }
6151e2cf88acSQuaker Fang 
6152e2cf88acSQuaker Fang /*
6153e2cf88acSQuaker Fang  * This function overwrites default configurations of
6154e2cf88acSQuaker Fang  * ieee80211com structure in Net80211 module.
6155e2cf88acSQuaker Fang  */
6156e2cf88acSQuaker Fang static void
6157e2cf88acSQuaker Fang iwh_overwrite_ic_default(iwh_sc_t *sc)
6158e2cf88acSQuaker Fang {
6159e2cf88acSQuaker Fang 	ieee80211com_t *ic = &sc->sc_ic;
6160e2cf88acSQuaker Fang 
6161e2cf88acSQuaker Fang 	sc->sc_newstate = ic->ic_newstate;
6162e2cf88acSQuaker Fang 	ic->ic_newstate = iwh_newstate;
6163e2cf88acSQuaker Fang 	ic->ic_node_alloc = iwh_node_alloc;
6164e2cf88acSQuaker Fang 	ic->ic_node_free = iwh_node_free;
6165e2cf88acSQuaker Fang 
6166e2cf88acSQuaker Fang 	if (sc->sc_ht_conf.ht_support) {
6167e2cf88acSQuaker Fang 		sc->sc_recv_action = ic->ic_recv_action;
6168e2cf88acSQuaker Fang 		ic->ic_recv_action = iwh_recv_action;
6169e2cf88acSQuaker Fang 		sc->sc_send_action = ic->ic_send_action;
6170e2cf88acSQuaker Fang 		ic->ic_send_action = iwh_send_action;
6171e2cf88acSQuaker Fang 
6172e2cf88acSQuaker Fang 		ic->ic_ampdu_rxmax = sc->sc_ht_conf.ampdu_p.factor;
6173e2cf88acSQuaker Fang 		ic->ic_ampdu_density = sc->sc_ht_conf.ampdu_p.density;
6174e2cf88acSQuaker Fang 		ic->ic_ampdu_limit = ic->ic_ampdu_rxmax;
6175e2cf88acSQuaker Fang 	}
6176e2cf88acSQuaker Fang }
6177e2cf88acSQuaker Fang 
6178e2cf88acSQuaker Fang /*
6179e2cf88acSQuaker Fang  * This function sets "RX chain selection" feild
6180e2cf88acSQuaker Fang  * in RXON command during plumb driver.
6181e2cf88acSQuaker Fang  */
6182e2cf88acSQuaker Fang static void
6183e2cf88acSQuaker Fang iwh_config_rxon_chain(iwh_sc_t *sc)
6184e2cf88acSQuaker Fang {
6185e2cf88acSQuaker Fang 	ieee80211com_t *ic = &sc->sc_ic;
6186e2cf88acSQuaker Fang 	ieee80211_node_t *in = ic->ic_bss;
6187e2cf88acSQuaker Fang 
6188e2cf88acSQuaker Fang 	if (3 == sc->sc_ht_conf.valid_chains) {
6189e2cf88acSQuaker Fang 		sc->sc_config.rx_chain = LE_16((RXON_RX_CHAIN_A_MSK |
6190e2cf88acSQuaker Fang 		    RXON_RX_CHAIN_B_MSK | RXON_RX_CHAIN_C_MSK) <<
6191e2cf88acSQuaker Fang 		    RXON_RX_CHAIN_VALID_POS);
6192e2cf88acSQuaker Fang 
6193e2cf88acSQuaker Fang 		sc->sc_config.rx_chain |= LE_16((RXON_RX_CHAIN_A_MSK |
6194e2cf88acSQuaker Fang 		    RXON_RX_CHAIN_B_MSK | RXON_RX_CHAIN_C_MSK) <<
6195e2cf88acSQuaker Fang 		    RXON_RX_CHAIN_FORCE_SEL_POS);
6196e2cf88acSQuaker Fang 
6197e2cf88acSQuaker Fang 		sc->sc_config.rx_chain |= LE_16((RXON_RX_CHAIN_A_MSK |
6198e2cf88acSQuaker Fang 		    RXON_RX_CHAIN_B_MSK | RXON_RX_CHAIN_C_MSK) <<
6199e2cf88acSQuaker Fang 		    RXON_RX_CHAIN_FORCE_MIMO_SEL_POS);
6200e2cf88acSQuaker Fang 	} else {
6201e2cf88acSQuaker Fang 		sc->sc_config.rx_chain = LE_16((RXON_RX_CHAIN_A_MSK |
6202e2cf88acSQuaker Fang 		    RXON_RX_CHAIN_B_MSK) << RXON_RX_CHAIN_VALID_POS);
6203e2cf88acSQuaker Fang 
6204e2cf88acSQuaker Fang 		sc->sc_config.rx_chain |= LE_16((RXON_RX_CHAIN_A_MSK |
6205e2cf88acSQuaker Fang 		    RXON_RX_CHAIN_B_MSK) << RXON_RX_CHAIN_FORCE_SEL_POS);
6206e2cf88acSQuaker Fang 
6207e2cf88acSQuaker Fang 		sc->sc_config.rx_chain |= LE_16((RXON_RX_CHAIN_A_MSK |
6208e2cf88acSQuaker Fang 		    RXON_RX_CHAIN_B_MSK) <<
6209e2cf88acSQuaker Fang 		    RXON_RX_CHAIN_FORCE_MIMO_SEL_POS);
6210e2cf88acSQuaker Fang 	}
6211e2cf88acSQuaker Fang 
6212e2cf88acSQuaker Fang 	sc->sc_config.rx_chain |= LE_16(RXON_RX_CHAIN_DRIVER_FORCE_MSK);
6213e2cf88acSQuaker Fang 
6214e2cf88acSQuaker Fang 	if ((in != NULL) &&
6215e2cf88acSQuaker Fang 	    (in->in_flags & IEEE80211_NODE_HT) &&
6216e2cf88acSQuaker Fang 	    sc->sc_ht_conf.ht_support) {
6217e2cf88acSQuaker Fang 		if (3 == sc->sc_ht_conf.valid_chains) {
6218e2cf88acSQuaker Fang 			sc->sc_config.rx_chain |= LE_16(3 <<
6219e2cf88acSQuaker Fang 			    RXON_RX_CHAIN_CNT_POS);
6220e2cf88acSQuaker Fang 			sc->sc_config.rx_chain |= LE_16(3 <<
6221e2cf88acSQuaker Fang 			    RXON_RX_CHAIN_MIMO_CNT_POS);
6222e2cf88acSQuaker Fang 		} else {
6223e2cf88acSQuaker Fang 			sc->sc_config.rx_chain |= LE_16(2 <<
6224e2cf88acSQuaker Fang 			    RXON_RX_CHAIN_CNT_POS);
6225e2cf88acSQuaker Fang 			sc->sc_config.rx_chain |= LE_16(2 <<
6226e2cf88acSQuaker Fang 			    RXON_RX_CHAIN_MIMO_CNT_POS);
6227e2cf88acSQuaker Fang 		}
6228e2cf88acSQuaker Fang 
6229e2cf88acSQuaker Fang 		sc->sc_config.rx_chain |= LE_16(1 <<
6230e2cf88acSQuaker Fang 		    RXON_RX_CHAIN_MIMO_FORCE_POS);
6231e2cf88acSQuaker Fang 	}
6232e2cf88acSQuaker Fang 
6233e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_RXON, "iwh_config_rxon_chain(): "
6234e2cf88acSQuaker Fang 	    "rxon->rx_chain = %x\n", sc->sc_config.rx_chain));
6235e2cf88acSQuaker Fang }
6236e2cf88acSQuaker Fang 
6237e2cf88acSQuaker Fang /*
6238e2cf88acSQuaker Fang  * This function adds AP station into hardware.
6239e2cf88acSQuaker Fang  */
6240e2cf88acSQuaker Fang static int
6241e2cf88acSQuaker Fang iwh_add_ap_sta(iwh_sc_t *sc)
6242e2cf88acSQuaker Fang {
6243e2cf88acSQuaker Fang 	ieee80211com_t *ic = &sc->sc_ic;
6244e2cf88acSQuaker Fang 	ieee80211_node_t *in = ic->ic_bss;
6245e2cf88acSQuaker Fang 	iwh_add_sta_t node;
6246e2cf88acSQuaker Fang 	uint32_t ampdu_factor, ampdu_density;
6247e2cf88acSQuaker Fang 	int err = IWH_FAIL;
6248e2cf88acSQuaker Fang 
6249e2cf88acSQuaker Fang 	/*
6250e2cf88acSQuaker Fang 	 * Add AP node into hardware.
6251e2cf88acSQuaker Fang 	 */
6252e2cf88acSQuaker Fang 	(void) memset(&node, 0, sizeof (node));
6253e2cf88acSQuaker Fang 	IEEE80211_ADDR_COPY(node.sta.addr, in->in_bssid);
6254e2cf88acSQuaker Fang 	node.mode = STA_MODE_ADD_MSK;
6255e2cf88acSQuaker Fang 	node.sta.sta_id = IWH_AP_ID;
6256e2cf88acSQuaker Fang 
6257e2cf88acSQuaker Fang 	if (sc->sc_ht_conf.ht_support &&
6258e2cf88acSQuaker Fang 	    (in->in_htcap_ie != NULL) &&
6259e2cf88acSQuaker Fang 	    (in->in_htcap != 0) &&
6260e2cf88acSQuaker Fang 	    (in->in_htparam != 0)) {
6261e2cf88acSQuaker Fang 
6262e2cf88acSQuaker Fang 		if (((in->in_htcap & HT_CAP_MIMO_PS) >> 2)
6263e2cf88acSQuaker Fang 		    == HT_CAP_MIMO_PS_DYNAMIC) {
6264e2cf88acSQuaker Fang 			node.station_flags |= LE_32(STA_FLG_RTS_MIMO_PROT);
6265e2cf88acSQuaker Fang 		}
6266e2cf88acSQuaker Fang 
6267e2cf88acSQuaker Fang 		ampdu_factor = in->in_htparam & HT_RX_AMPDU_FACTOR_MSK;
6268e2cf88acSQuaker Fang 		node.station_flags |=
6269e2cf88acSQuaker Fang 		    LE_32(ampdu_factor << STA_FLG_MAX_AMPDU_POS);
6270e2cf88acSQuaker Fang 
6271e2cf88acSQuaker Fang 		ampdu_density = (in->in_htparam & HT_MPDU_DENSITY_MSK) >>
6272e2cf88acSQuaker Fang 		    HT_MPDU_DENSITY_POS;
6273e2cf88acSQuaker Fang 		node.station_flags |=
6274e2cf88acSQuaker Fang 		    LE_32(ampdu_density << STA_FLG_AMPDU_DENSITY_POS);
6275e2cf88acSQuaker Fang 
6276e2cf88acSQuaker Fang 		if (in->in_htcap & LE_16(HT_CAP_SUP_WIDTH)) {
6277e2cf88acSQuaker Fang 			node.station_flags |=
6278e2cf88acSQuaker Fang 			    LE_32(STA_FLG_FAT_EN);
6279e2cf88acSQuaker Fang 		}
6280e2cf88acSQuaker Fang 	}
6281e2cf88acSQuaker Fang 
6282e2cf88acSQuaker Fang 	err = iwh_cmd(sc, REPLY_ADD_STA, &node, sizeof (node), 1);
6283e2cf88acSQuaker Fang 	if (err != IWH_SUCCESS) {
6284e2cf88acSQuaker Fang 		cmn_err(CE_WARN, "iwh_add_ap_lq(): "
6285e2cf88acSQuaker Fang 		    "failed to add AP node\n");
6286e2cf88acSQuaker Fang 		return (err);
6287e2cf88acSQuaker Fang 	}
6288e2cf88acSQuaker Fang 
6289e2cf88acSQuaker Fang 	return (err);
6290e2cf88acSQuaker Fang }
6291e2cf88acSQuaker Fang 
6292e2cf88acSQuaker Fang /*
6293e2cf88acSQuaker Fang  * Each station in the Shirley Peak's internal station table has
6294e2cf88acSQuaker Fang  * its own table of 16 TX rates and modulation modes for retrying
6295e2cf88acSQuaker Fang  * TX when an ACK is not received. This function replaces the entire
6296e2cf88acSQuaker Fang  * table for one station.Station must already be in Shirley Peak's
6297e2cf88acSQuaker Fang  * station talbe.
6298e2cf88acSQuaker Fang  */
6299e2cf88acSQuaker Fang static int
6300e2cf88acSQuaker Fang iwh_ap_lq(iwh_sc_t *sc)
6301e2cf88acSQuaker Fang {
6302e2cf88acSQuaker Fang 	ieee80211com_t *ic = &sc->sc_ic;
6303e2cf88acSQuaker Fang 	ieee80211_node_t *in = ic->ic_bss;
6304e2cf88acSQuaker Fang 	iwh_link_quality_cmd_t link_quality;
6305e2cf88acSQuaker Fang 	const struct ieee80211_rateset *rs_sup = NULL;
6306e2cf88acSQuaker Fang 	uint32_t masks = 0, rate;
6307e2cf88acSQuaker Fang 	int i, err = IWH_FAIL;
6308e2cf88acSQuaker Fang 
6309e2cf88acSQuaker Fang 	/*
6310e2cf88acSQuaker Fang 	 * TX_LINK_QUALITY cmd
6311e2cf88acSQuaker Fang 	 */
6312e2cf88acSQuaker Fang 	(void) memset(&link_quality, 0, sizeof (link_quality));
6313e2cf88acSQuaker Fang 	if (in->in_chan == IEEE80211_CHAN_ANYC)	/* skip null node */
6314e2cf88acSQuaker Fang 		return (err);
6315e2cf88acSQuaker Fang 	rs_sup = ieee80211_get_suprates(ic, in->in_chan);
6316e2cf88acSQuaker Fang 
6317e2cf88acSQuaker Fang 	for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
6318e2cf88acSQuaker Fang 		if (i < rs_sup->ir_nrates) {
6319e2cf88acSQuaker Fang 			rate = rs_sup->ir_rates[rs_sup->ir_nrates - i] &
6320e2cf88acSQuaker Fang 			    IEEE80211_RATE_VAL;
6321e2cf88acSQuaker Fang 		} else {
6322e2cf88acSQuaker Fang 			rate = 2;
6323e2cf88acSQuaker Fang 		}
6324e2cf88acSQuaker Fang 
6325e2cf88acSQuaker Fang 		if (2 == rate || 4 == rate ||
6326e2cf88acSQuaker Fang 		    11 == rate || 22 == rate) {
6327e2cf88acSQuaker Fang 			masks |= LE_32(RATE_MCS_CCK_MSK);
6328e2cf88acSQuaker Fang 		}
6329e2cf88acSQuaker Fang 
6330e2cf88acSQuaker Fang 		masks |= LE_32(RATE_MCS_ANT_B_MSK);
6331e2cf88acSQuaker Fang 
6332e2cf88acSQuaker Fang 		link_quality.rate_n_flags[i] =
6333e2cf88acSQuaker Fang 		    LE_32(iwh_rate_to_plcp(rate) | masks);
6334e2cf88acSQuaker Fang 	}
6335e2cf88acSQuaker Fang 
6336e2cf88acSQuaker Fang 	link_quality.general_params.single_stream_ant_msk = LINK_QUAL_ANT_B_MSK;
6337e2cf88acSQuaker Fang 	link_quality.general_params.dual_stream_ant_msk = LINK_QUAL_ANT_MSK;
6338e2cf88acSQuaker Fang 	link_quality.agg_params.agg_dis_start_th = 3;
6339e2cf88acSQuaker Fang 	link_quality.agg_params.agg_time_limit = LE_16(4000);
6340e2cf88acSQuaker Fang 	link_quality.sta_id = IWH_AP_ID;
6341e2cf88acSQuaker Fang 	err = iwh_cmd(sc, REPLY_TX_LINK_QUALITY_CMD, &link_quality,
6342e2cf88acSQuaker Fang 	    sizeof (link_quality), 1);
6343e2cf88acSQuaker Fang 	if (err != IWH_SUCCESS) {
6344e2cf88acSQuaker Fang 		cmn_err(CE_WARN, "iwh_ap_lq(): "
6345e2cf88acSQuaker Fang 		    "failed to config link quality table\n");
6346e2cf88acSQuaker Fang 		return (err);
6347e2cf88acSQuaker Fang 	}
6348e2cf88acSQuaker Fang 
6349e2cf88acSQuaker Fang #ifdef	DEBUG
6350e2cf88acSQuaker Fang 	IWH_DBG((IWH_DEBUG_HWRATE, "iwh_ap_lq(): "
6351e2cf88acSQuaker Fang 	    "Rates in HW are as follows:\n"));
6352e2cf88acSQuaker Fang 
6353e2cf88acSQuaker Fang 	for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
6354e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_HWRATE,
6355e2cf88acSQuaker Fang 		    "Rate %d in HW is %x\n", i, link_quality.rate_n_flags[i]));
6356e2cf88acSQuaker Fang 	}
6357e2cf88acSQuaker Fang #endif
6358e2cf88acSQuaker Fang 
6359e2cf88acSQuaker Fang 	return (err);
6360e2cf88acSQuaker Fang }
6361e2cf88acSQuaker Fang 
6362e2cf88acSQuaker Fang /*
6363e2cf88acSQuaker Fang  * When block ACK agreement has been set up between station and AP,
6364e2cf88acSQuaker Fang  * Net80211 module will call this function to inform hardware about
6365e2cf88acSQuaker Fang  * informations of this BA agreement.
6366e2cf88acSQuaker Fang  * When AP wants to delete BA agreement that was originated by it,
6367e2cf88acSQuaker Fang  * Net80211 modele will call this function to clean up relevant
6368e2cf88acSQuaker Fang  * information in hardware.
6369e2cf88acSQuaker Fang  */
6370e2cf88acSQuaker Fang static void
6371e2cf88acSQuaker Fang iwh_recv_action(struct ieee80211_node *in,
6372e2cf88acSQuaker Fang     const uint8_t *frm, const uint8_t *efrm)
6373e2cf88acSQuaker Fang {
6374e2cf88acSQuaker Fang 	struct ieee80211com *ic;
6375e2cf88acSQuaker Fang 	iwh_sc_t *sc;
6376e2cf88acSQuaker Fang 	const struct ieee80211_action *ia;
6377e2cf88acSQuaker Fang 	uint16_t baparamset, baseqctl;
6378e2cf88acSQuaker Fang 	uint32_t tid, ssn;
6379e2cf88acSQuaker Fang 	iwh_add_sta_t node;
6380e2cf88acSQuaker Fang 	int err = IWH_FAIL;
6381e2cf88acSQuaker Fang 
6382e2cf88acSQuaker Fang 	if ((NULL == in) || (NULL == frm)) {
6383e2cf88acSQuaker Fang 		return;
6384e2cf88acSQuaker Fang 	}
6385e2cf88acSQuaker Fang 
6386e2cf88acSQuaker Fang 	ic = in->in_ic;
6387e2cf88acSQuaker Fang 	if (NULL == ic) {
6388e2cf88acSQuaker Fang 		return;
6389e2cf88acSQuaker Fang 	}
6390e2cf88acSQuaker Fang 
6391e2cf88acSQuaker Fang 	sc = (iwh_sc_t *)ic;
6392e2cf88acSQuaker Fang 
6393e2cf88acSQuaker Fang 	sc->sc_recv_action(in, frm, efrm);
6394e2cf88acSQuaker Fang 
6395e2cf88acSQuaker Fang 	ia = (const struct ieee80211_action *)frm;
6396e2cf88acSQuaker Fang 	if (ia->ia_category != IEEE80211_ACTION_CAT_BA) {
6397e2cf88acSQuaker Fang 		return;
6398e2cf88acSQuaker Fang 	}
6399e2cf88acSQuaker Fang 
6400e2cf88acSQuaker Fang 	switch (ia->ia_action) {
6401e2cf88acSQuaker Fang 	case IEEE80211_ACTION_BA_ADDBA_REQUEST:
6402e2cf88acSQuaker Fang 		baparamset = *(uint16_t *)(frm + 3);
6403e2cf88acSQuaker Fang 		baseqctl = *(uint16_t *)(frm + 7);
6404e2cf88acSQuaker Fang 
6405e2cf88acSQuaker Fang 		tid = MS(baparamset, IEEE80211_BAPS_TID);
6406e2cf88acSQuaker Fang 		ssn = MS(baseqctl, IEEE80211_BASEQ_START);
6407e2cf88acSQuaker Fang 
6408e2cf88acSQuaker Fang 		(void) memset(&node, 0, sizeof (node));
6409e2cf88acSQuaker Fang 		IEEE80211_ADDR_COPY(node.sta.addr, in->in_bssid);
6410e2cf88acSQuaker Fang 		node.mode = STA_MODE_MODIFY_MSK;
6411e2cf88acSQuaker Fang 		node.sta.sta_id = IWH_AP_ID;
6412e2cf88acSQuaker Fang 
6413e2cf88acSQuaker Fang 		node.station_flags_msk = 0;
6414e2cf88acSQuaker Fang 		node.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
6415e2cf88acSQuaker Fang 		node.add_immediate_ba_tid = (uint8_t)tid;
6416e2cf88acSQuaker Fang 		node.add_immediate_ba_ssn = LE_16(ssn);
6417e2cf88acSQuaker Fang 
6418e2cf88acSQuaker Fang 		mutex_enter(&sc->sc_glock);
6419e2cf88acSQuaker Fang 		err = iwh_cmd(sc, REPLY_ADD_STA, &node, sizeof (node), 1);
6420e2cf88acSQuaker Fang 		if (err != IWH_SUCCESS) {
6421e2cf88acSQuaker Fang 			cmn_err(CE_WARN, "iwh_recv_action(): "
6422e2cf88acSQuaker Fang 			    "failed to setup RX block ACK\n");
6423e2cf88acSQuaker Fang 			mutex_exit(&sc->sc_glock);
6424e2cf88acSQuaker Fang 			return;
6425e2cf88acSQuaker Fang 		}
6426e2cf88acSQuaker Fang 		mutex_exit(&sc->sc_glock);
6427e2cf88acSQuaker Fang 
6428e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_BA, "iwh_recv_action(): "
6429e2cf88acSQuaker Fang 		    "RX block ACK "
6430e2cf88acSQuaker Fang 		    "was setup on TID %d and SSN is %d.\n", tid, ssn));
6431e2cf88acSQuaker Fang 
6432e2cf88acSQuaker Fang 		return;
6433e2cf88acSQuaker Fang 
6434e2cf88acSQuaker Fang 	case IEEE80211_ACTION_BA_DELBA:
6435e2cf88acSQuaker Fang 		baparamset = *(uint16_t *)(frm + 2);
6436e2cf88acSQuaker Fang 
6437e2cf88acSQuaker Fang 		if ((baparamset & IEEE80211_DELBAPS_INIT) == 0) {
6438e2cf88acSQuaker Fang 			return;
6439e2cf88acSQuaker Fang 		}
6440e2cf88acSQuaker Fang 
6441e2cf88acSQuaker Fang 		tid = MS(baparamset, IEEE80211_DELBAPS_TID);
6442e2cf88acSQuaker Fang 
6443e2cf88acSQuaker Fang 		(void) memset(&node, 0, sizeof (node));
6444e2cf88acSQuaker Fang 		IEEE80211_ADDR_COPY(node.sta.addr, in->in_bssid);
6445e2cf88acSQuaker Fang 		node.mode = STA_MODE_MODIFY_MSK;
6446e2cf88acSQuaker Fang 		node.sta.sta_id = IWH_AP_ID;
6447e2cf88acSQuaker Fang 
6448e2cf88acSQuaker Fang 		node.station_flags_msk = 0;
6449e2cf88acSQuaker Fang 		node.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
6450e2cf88acSQuaker Fang 		node.add_immediate_ba_tid = (uint8_t)tid;
6451e2cf88acSQuaker Fang 
6452e2cf88acSQuaker Fang 		mutex_enter(&sc->sc_glock);
6453e2cf88acSQuaker Fang 		err = iwh_cmd(sc, REPLY_ADD_STA, &node, sizeof (node), 1);
6454e2cf88acSQuaker Fang 		if (err != IWH_SUCCESS) {
6455e2cf88acSQuaker Fang 			cmn_err(CE_WARN, "iwh_recv_action(): "
6456e2cf88acSQuaker Fang 			    "failed to delete RX block ACK\n");
6457e2cf88acSQuaker Fang 			mutex_exit(&sc->sc_glock);
6458e2cf88acSQuaker Fang 			return;
6459e2cf88acSQuaker Fang 		}
6460e2cf88acSQuaker Fang 		mutex_exit(&sc->sc_glock);
6461e2cf88acSQuaker Fang 
6462e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_BA, "iwh_recv_action(): "
6463e2cf88acSQuaker Fang 		    "RX block ACK "
6464e2cf88acSQuaker Fang 		    "was deleted on TID %d.\n", tid));
6465e2cf88acSQuaker Fang 
6466e2cf88acSQuaker Fang 		return;
6467e2cf88acSQuaker Fang 	}
6468e2cf88acSQuaker Fang }
6469e2cf88acSQuaker Fang 
6470e2cf88acSQuaker Fang /*
6471e2cf88acSQuaker Fang  * When local station wants to delete BA agreement that was originated by AP,
6472e2cf88acSQuaker Fang  * Net80211 module will call this function to clean up relevant information
6473e2cf88acSQuaker Fang  * in hardware.
6474e2cf88acSQuaker Fang  */
6475e2cf88acSQuaker Fang static int
6476e2cf88acSQuaker Fang iwh_send_action(struct ieee80211_node *in,
6477e2cf88acSQuaker Fang     int category, int action, uint16_t args[4])
6478e2cf88acSQuaker Fang {
6479e2cf88acSQuaker Fang 	struct ieee80211com *ic;
6480e2cf88acSQuaker Fang 	iwh_sc_t *sc;
6481e2cf88acSQuaker Fang 	uint32_t tid;
6482e2cf88acSQuaker Fang 	iwh_add_sta_t node;
6483e2cf88acSQuaker Fang 	int ret = EIO;
6484e2cf88acSQuaker Fang 	int err = IWH_FAIL;
6485e2cf88acSQuaker Fang 
6486e2cf88acSQuaker Fang 
6487e2cf88acSQuaker Fang 	if (NULL == in) {
6488e2cf88acSQuaker Fang 		return (ret);
6489e2cf88acSQuaker Fang 	}
6490e2cf88acSQuaker Fang 
6491e2cf88acSQuaker Fang 	ic = in->in_ic;
6492e2cf88acSQuaker Fang 	if (NULL == ic) {
6493e2cf88acSQuaker Fang 		return (ret);
6494e2cf88acSQuaker Fang 	}
6495e2cf88acSQuaker Fang 
6496e2cf88acSQuaker Fang 	sc = (iwh_sc_t *)ic;
6497e2cf88acSQuaker Fang 
6498e2cf88acSQuaker Fang 	ret = sc->sc_send_action(in, category, action, args);
6499e2cf88acSQuaker Fang 
6500e2cf88acSQuaker Fang 	if (category != IEEE80211_ACTION_CAT_BA) {
6501e2cf88acSQuaker Fang 		return (ret);
6502e2cf88acSQuaker Fang 	}
6503e2cf88acSQuaker Fang 
6504e2cf88acSQuaker Fang 	switch (action) {
6505e2cf88acSQuaker Fang 	case IEEE80211_ACTION_BA_DELBA:
6506e2cf88acSQuaker Fang 		if (IEEE80211_DELBAPS_INIT == args[1]) {
6507e2cf88acSQuaker Fang 			return (ret);
6508e2cf88acSQuaker Fang 		}
6509e2cf88acSQuaker Fang 
6510e2cf88acSQuaker Fang 		tid = args[0];
6511e2cf88acSQuaker Fang 
6512e2cf88acSQuaker Fang 		(void) memset(&node, 0, sizeof (node));
6513e2cf88acSQuaker Fang 		IEEE80211_ADDR_COPY(node.sta.addr, in->in_bssid);
6514e2cf88acSQuaker Fang 		node.mode = STA_MODE_MODIFY_MSK;
6515e2cf88acSQuaker Fang 		node.sta.sta_id = IWH_AP_ID;
6516e2cf88acSQuaker Fang 
6517e2cf88acSQuaker Fang 		node.station_flags_msk = 0;
6518e2cf88acSQuaker Fang 		node.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
6519e2cf88acSQuaker Fang 		node.add_immediate_ba_tid = (uint8_t)tid;
6520e2cf88acSQuaker Fang 
6521e2cf88acSQuaker Fang 		mutex_enter(&sc->sc_glock);
6522e2cf88acSQuaker Fang 		err = iwh_cmd(sc, REPLY_ADD_STA, &node, sizeof (node), 1);
6523e2cf88acSQuaker Fang 		if (err != IWH_SUCCESS) {
6524e2cf88acSQuaker Fang 			cmn_err(CE_WARN, "iwh_send_action(): "
6525e2cf88acSQuaker Fang 			    "failed to delete RX balock ACK\n");
6526e2cf88acSQuaker Fang 			mutex_exit(&sc->sc_glock);
6527e2cf88acSQuaker Fang 			return (EIO);
6528e2cf88acSQuaker Fang 		}
6529e2cf88acSQuaker Fang 		mutex_exit(&sc->sc_glock);
6530e2cf88acSQuaker Fang 
6531e2cf88acSQuaker Fang 		IWH_DBG((IWH_DEBUG_BA, "iwh_send_action(): "
6532e2cf88acSQuaker Fang 		    "RX block ACK "
6533e2cf88acSQuaker Fang 		    "was deleted on TID %d.\n", tid));
6534e2cf88acSQuaker Fang 
6535e2cf88acSQuaker Fang 		break;
6536e2cf88acSQuaker Fang 	}
6537e2cf88acSQuaker Fang 
6538e2cf88acSQuaker Fang 	return (ret);
6539e2cf88acSQuaker Fang }
65407d483bc1Sfei feng - Sun Microsystems - Beijing China 
65417d483bc1Sfei feng - Sun Microsystems - Beijing China static int
65427d483bc1Sfei feng - Sun Microsystems - Beijing China iwh_reset_hw(iwh_sc_t *sc)
65437d483bc1Sfei feng - Sun Microsystems - Beijing China {
65447d483bc1Sfei feng - Sun Microsystems - Beijing China 	uint32_t tmp;
65457d483bc1Sfei feng - Sun Microsystems - Beijing China 	int n;
65467d483bc1Sfei feng - Sun Microsystems - Beijing China 
65477d483bc1Sfei feng - Sun Microsystems - Beijing China 	tmp = IWH_READ(sc, CSR_HW_IF_CONFIG_REG);
65487d483bc1Sfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_HW_IF_CONFIG_REG,
65497d483bc1Sfei feng - Sun Microsystems - Beijing China 	    tmp | CSR_HW_IF_CONFIG_REG_BITS_NIC_READY);
65507d483bc1Sfei feng - Sun Microsystems - Beijing China 
65517d483bc1Sfei feng - Sun Microsystems - Beijing China 	/*
65527d483bc1Sfei feng - Sun Microsystems - Beijing China 	 * wait for HW ready
65537d483bc1Sfei feng - Sun Microsystems - Beijing China 	 */
65547d483bc1Sfei feng - Sun Microsystems - Beijing China 	for (n = 0; n < 5; n++) {
65557d483bc1Sfei feng - Sun Microsystems - Beijing China 		if (IWH_READ(sc, CSR_HW_IF_CONFIG_REG) &
65567d483bc1Sfei feng - Sun Microsystems - Beijing China 		    CSR_HW_IF_CONFIG_REG_BITS_NIC_READY) {
65577d483bc1Sfei feng - Sun Microsystems - Beijing China 			break;
65587d483bc1Sfei feng - Sun Microsystems - Beijing China 		}
65597d483bc1Sfei feng - Sun Microsystems - Beijing China 		DELAY(10);
65607d483bc1Sfei feng - Sun Microsystems - Beijing China 	}
65617d483bc1Sfei feng - Sun Microsystems - Beijing China 
65627d483bc1Sfei feng - Sun Microsystems - Beijing China 	if (n != 5) {
65637d483bc1Sfei feng - Sun Microsystems - Beijing China 		return (IWH_SUCCESS);
65647d483bc1Sfei feng - Sun Microsystems - Beijing China 	}
65657d483bc1Sfei feng - Sun Microsystems - Beijing China 
65667d483bc1Sfei feng - Sun Microsystems - Beijing China 	tmp = IWH_READ(sc, CSR_HW_IF_CONFIG_REG);
65677d483bc1Sfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_HW_IF_CONFIG_REG,
65687d483bc1Sfei feng - Sun Microsystems - Beijing China 	    tmp | CSR_HW_IF_CONFIG_REG_BITS_PREPARE);
65697d483bc1Sfei feng - Sun Microsystems - Beijing China 
65707d483bc1Sfei feng - Sun Microsystems - Beijing China 	for (n = 0; n < 15000; n++) {
65717d483bc1Sfei feng - Sun Microsystems - Beijing China 		if (0 == (IWH_READ(sc, CSR_HW_IF_CONFIG_REG) &
65727d483bc1Sfei feng - Sun Microsystems - Beijing China 		    CSR_HW_IF_CONFIG_REG_BITS_NIC_PREPARE_DONE)) {
65737d483bc1Sfei feng - Sun Microsystems - Beijing China 			break;
65747d483bc1Sfei feng - Sun Microsystems - Beijing China 		}
65757d483bc1Sfei feng - Sun Microsystems - Beijing China 		DELAY(10);
65767d483bc1Sfei feng - Sun Microsystems - Beijing China 	}
65777d483bc1Sfei feng - Sun Microsystems - Beijing China 
65787d483bc1Sfei feng - Sun Microsystems - Beijing China 	if (15000 == n) {
65797d483bc1Sfei feng - Sun Microsystems - Beijing China 		return (ETIMEDOUT);
65807d483bc1Sfei feng - Sun Microsystems - Beijing China 	}
65817d483bc1Sfei feng - Sun Microsystems - Beijing China 
65827d483bc1Sfei feng - Sun Microsystems - Beijing China 	tmp = IWH_READ(sc, CSR_HW_IF_CONFIG_REG);
65837d483bc1Sfei feng - Sun Microsystems - Beijing China 	IWH_WRITE(sc, CSR_HW_IF_CONFIG_REG,
65847d483bc1Sfei feng - Sun Microsystems - Beijing China 	    tmp | CSR_HW_IF_CONFIG_REG_BITS_NIC_READY);
65857d483bc1Sfei feng - Sun Microsystems - Beijing China 
65867d483bc1Sfei feng - Sun Microsystems - Beijing China 	/*
65877d483bc1Sfei feng - Sun Microsystems - Beijing China 	 * wait for HW ready
65887d483bc1Sfei feng - Sun Microsystems - Beijing China 	 */
65897d483bc1Sfei feng - Sun Microsystems - Beijing China 	for (n = 0; n < 5; n++) {
65907d483bc1Sfei feng - Sun Microsystems - Beijing China 		if (IWH_READ(sc, CSR_HW_IF_CONFIG_REG) &
65917d483bc1Sfei feng - Sun Microsystems - Beijing China 		    CSR_HW_IF_CONFIG_REG_BITS_NIC_READY) {
65927d483bc1Sfei feng - Sun Microsystems - Beijing China 			break;
65937d483bc1Sfei feng - Sun Microsystems - Beijing China 		}
65947d483bc1Sfei feng - Sun Microsystems - Beijing China 		DELAY(10);
65957d483bc1Sfei feng - Sun Microsystems - Beijing China 	}
65967d483bc1Sfei feng - Sun Microsystems - Beijing China 
65977d483bc1Sfei feng - Sun Microsystems - Beijing China 	if (n != 5) {
65987d483bc1Sfei feng - Sun Microsystems - Beijing China 		return (IWH_SUCCESS);
65997d483bc1Sfei feng - Sun Microsystems - Beijing China 	} else {
66007d483bc1Sfei feng - Sun Microsystems - Beijing China 		return (ETIMEDOUT);
66017d483bc1Sfei feng - Sun Microsystems - Beijing China 	}
66027d483bc1Sfei feng - Sun Microsystems - Beijing China }
6603