1c533a883Shx147065 /*
2*0dc2366fSVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
3c533a883Shx147065 * Use is subject to license terms.
4c533a883Shx147065 */
5c533a883Shx147065
6c533a883Shx147065 /*
7c533a883Shx147065 * Copyright (c) 2007, Intel Corporation
8c533a883Shx147065 * All rights reserved.
9c533a883Shx147065 */
10c533a883Shx147065
11c533a883Shx147065 /*
12c533a883Shx147065 * Copyright (c) 2006
13c533a883Shx147065 * Copyright (c) 2007
14c533a883Shx147065 * Damien Bergamini <damien.bergamini@free.fr>
15c533a883Shx147065 *
16c533a883Shx147065 * Permission to use, copy, modify, and distribute this software for any
17c533a883Shx147065 * purpose with or without fee is hereby granted, provided that the above
18c533a883Shx147065 * copyright notice and this permission notice appear in all copies.
19c533a883Shx147065 *
20c533a883Shx147065 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
21c533a883Shx147065 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
22c533a883Shx147065 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
23c533a883Shx147065 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
24c533a883Shx147065 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
25c533a883Shx147065 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
26c533a883Shx147065 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
27c533a883Shx147065 */
28c533a883Shx147065
29c533a883Shx147065 /*
30c533a883Shx147065 * Driver for Intel PRO/Wireless 4965AGN(kedron) 802.11 network adapters.
31c533a883Shx147065 */
32c533a883Shx147065
33c533a883Shx147065 #include <sys/types.h>
34c533a883Shx147065 #include <sys/byteorder.h>
35c533a883Shx147065 #include <sys/conf.h>
36c533a883Shx147065 #include <sys/cmn_err.h>
37c533a883Shx147065 #include <sys/stat.h>
38c533a883Shx147065 #include <sys/ddi.h>
39c533a883Shx147065 #include <sys/sunddi.h>
40c533a883Shx147065 #include <sys/strsubr.h>
41c533a883Shx147065 #include <sys/ethernet.h>
42c533a883Shx147065 #include <inet/common.h>
43c533a883Shx147065 #include <inet/nd.h>
44c533a883Shx147065 #include <inet/mi.h>
45c533a883Shx147065 #include <sys/note.h>
46c533a883Shx147065 #include <sys/stream.h>
47c533a883Shx147065 #include <sys/strsun.h>
48c533a883Shx147065 #include <sys/modctl.h>
49c533a883Shx147065 #include <sys/devops.h>
50c533a883Shx147065 #include <sys/dlpi.h>
51da14cebeSEric Cheng #include <sys/mac_provider.h>
52c533a883Shx147065 #include <sys/mac_wifi.h>
53c533a883Shx147065 #include <sys/net80211.h>
54c533a883Shx147065 #include <sys/net80211_proto.h>
55c533a883Shx147065 #include <sys/varargs.h>
56c533a883Shx147065 #include <sys/policy.h>
57c533a883Shx147065 #include <sys/pci.h>
58c533a883Shx147065
59cdc64593Sxinghua wen - Sun Microsystems - Beijing China #include "iwk_calibration.h"
60c533a883Shx147065 #include "iwk_hw.h"
61c533a883Shx147065 #include "iwk_eeprom.h"
62c533a883Shx147065 #include "iwk2_var.h"
63c533a883Shx147065 #include <inet/wifi_ioctl.h>
64c533a883Shx147065
65c533a883Shx147065 #ifdef DEBUG
66c533a883Shx147065 #define IWK_DEBUG_80211 (1 << 0)
67c533a883Shx147065 #define IWK_DEBUG_CMD (1 << 1)
68c533a883Shx147065 #define IWK_DEBUG_DMA (1 << 2)
69c533a883Shx147065 #define IWK_DEBUG_EEPROM (1 << 3)
70c533a883Shx147065 #define IWK_DEBUG_FW (1 << 4)
71c533a883Shx147065 #define IWK_DEBUG_HW (1 << 5)
72c533a883Shx147065 #define IWK_DEBUG_INTR (1 << 6)
73c533a883Shx147065 #define IWK_DEBUG_MRR (1 << 7)
74c533a883Shx147065 #define IWK_DEBUG_PIO (1 << 8)
75c533a883Shx147065 #define IWK_DEBUG_RX (1 << 9)
76c533a883Shx147065 #define IWK_DEBUG_SCAN (1 << 10)
77c533a883Shx147065 #define IWK_DEBUG_TX (1 << 11)
78c533a883Shx147065 #define IWK_DEBUG_RATECTL (1 << 12)
79c533a883Shx147065 #define IWK_DEBUG_RADIO (1 << 13)
8043439c96Shx147065 #define IWK_DEBUG_RESUME (1 << 14)
81cdc64593Sxinghua wen - Sun Microsystems - Beijing China #define IWK_DEBUG_CALIBRATION (1 << 15)
82c533a883Shx147065 uint32_t iwk_dbg_flags = 0;
83c533a883Shx147065 #define IWK_DBG(x) \
84c533a883Shx147065 iwk_dbg x
85c533a883Shx147065 #else
86c533a883Shx147065 #define IWK_DBG(x)
87c533a883Shx147065 #endif
88c533a883Shx147065
89c533a883Shx147065 static void *iwk_soft_state_p = NULL;
90c533a883Shx147065 static uint8_t iwk_fw_bin [] = {
91c533a883Shx147065 #include "fw-iw/iw4965.ucode.hex"
92c533a883Shx147065 };
93c533a883Shx147065
94c533a883Shx147065 /* DMA attributes for a shared page */
95c533a883Shx147065 static ddi_dma_attr_t sh_dma_attr = {
96c533a883Shx147065 DMA_ATTR_V0, /* version of this structure */
97c533a883Shx147065 0, /* lowest usable address */
98c533a883Shx147065 0xffffffffU, /* highest usable address */
99c533a883Shx147065 0xffffffffU, /* maximum DMAable byte count */
100c533a883Shx147065 0x1000, /* alignment in bytes */
101c533a883Shx147065 0x1000, /* burst sizes (any?) */
102c533a883Shx147065 1, /* minimum transfer */
103c533a883Shx147065 0xffffffffU, /* maximum transfer */
104c533a883Shx147065 0xffffffffU, /* maximum segment length */
105c533a883Shx147065 1, /* maximum number of segments */
106c533a883Shx147065 1, /* granularity */
107c533a883Shx147065 0, /* flags (reserved) */
108c533a883Shx147065 };
109c533a883Shx147065
110c533a883Shx147065 /* DMA attributes for a keep warm DRAM descriptor */
111c533a883Shx147065 static ddi_dma_attr_t kw_dma_attr = {
112c533a883Shx147065 DMA_ATTR_V0, /* version of this structure */
113c533a883Shx147065 0, /* lowest usable address */
114c533a883Shx147065 0xffffffffU, /* highest usable address */
115c533a883Shx147065 0xffffffffU, /* maximum DMAable byte count */
116c533a883Shx147065 0x1000, /* alignment in bytes */
117c533a883Shx147065 0x1000, /* burst sizes (any?) */
118c533a883Shx147065 1, /* minimum transfer */
119c533a883Shx147065 0xffffffffU, /* maximum transfer */
120c533a883Shx147065 0xffffffffU, /* maximum segment length */
121c533a883Shx147065 1, /* maximum number of segments */
122c533a883Shx147065 1, /* granularity */
123c533a883Shx147065 0, /* flags (reserved) */
124c533a883Shx147065 };
125c533a883Shx147065
126c533a883Shx147065 /* DMA attributes for a ring descriptor */
127c533a883Shx147065 static ddi_dma_attr_t ring_desc_dma_attr = {
128c533a883Shx147065 DMA_ATTR_V0, /* version of this structure */
129c533a883Shx147065 0, /* lowest usable address */
130c533a883Shx147065 0xffffffffU, /* highest usable address */
131c533a883Shx147065 0xffffffffU, /* maximum DMAable byte count */
132c533a883Shx147065 0x100, /* alignment in bytes */
133c533a883Shx147065 0x100, /* burst sizes (any?) */
134c533a883Shx147065 1, /* minimum transfer */
135c533a883Shx147065 0xffffffffU, /* maximum transfer */
136c533a883Shx147065 0xffffffffU, /* maximum segment length */
137c533a883Shx147065 1, /* maximum number of segments */
138c533a883Shx147065 1, /* granularity */
139c533a883Shx147065 0, /* flags (reserved) */
140c533a883Shx147065 };
141c533a883Shx147065
142c533a883Shx147065 /* DMA attributes for a cmd */
143c533a883Shx147065 static ddi_dma_attr_t cmd_dma_attr = {
144c533a883Shx147065 DMA_ATTR_V0, /* version of this structure */
145c533a883Shx147065 0, /* lowest usable address */
146c533a883Shx147065 0xffffffffU, /* highest usable address */
147c533a883Shx147065 0xffffffffU, /* maximum DMAable byte count */
148c533a883Shx147065 4, /* alignment in bytes */
149c533a883Shx147065 0x100, /* burst sizes (any?) */
150c533a883Shx147065 1, /* minimum transfer */
151c533a883Shx147065 0xffffffffU, /* maximum transfer */
152c533a883Shx147065 0xffffffffU, /* maximum segment length */
153c533a883Shx147065 1, /* maximum number of segments */
154c533a883Shx147065 1, /* granularity */
155c533a883Shx147065 0, /* flags (reserved) */
156c533a883Shx147065 };
157c533a883Shx147065
158c533a883Shx147065 /* DMA attributes for a rx buffer */
159c533a883Shx147065 static ddi_dma_attr_t rx_buffer_dma_attr = {
160c533a883Shx147065 DMA_ATTR_V0, /* version of this structure */
161c533a883Shx147065 0, /* lowest usable address */
162c533a883Shx147065 0xffffffffU, /* highest usable address */
163c533a883Shx147065 0xffffffffU, /* maximum DMAable byte count */
164c533a883Shx147065 0x100, /* alignment in bytes */
165c533a883Shx147065 0x100, /* burst sizes (any?) */
166c533a883Shx147065 1, /* minimum transfer */
167c533a883Shx147065 0xffffffffU, /* maximum transfer */
168c533a883Shx147065 0xffffffffU, /* maximum segment length */
169c533a883Shx147065 1, /* maximum number of segments */
170c533a883Shx147065 1, /* granularity */
171c533a883Shx147065 0, /* flags (reserved) */
172c533a883Shx147065 };
173c533a883Shx147065
174c533a883Shx147065 /*
175c533a883Shx147065 * DMA attributes for a tx buffer.
176c533a883Shx147065 * the maximum number of segments is 4 for the hardware.
177c533a883Shx147065 * now all the wifi drivers put the whole frame in a single
178c533a883Shx147065 * descriptor, so we define the maximum number of segments 1,
179c533a883Shx147065 * just the same as the rx_buffer. we consider leverage the HW
180c533a883Shx147065 * ability in the future, that is why we don't define rx and tx
181c533a883Shx147065 * buffer_dma_attr as the same.
182c533a883Shx147065 */
183c533a883Shx147065 static ddi_dma_attr_t tx_buffer_dma_attr = {
184c533a883Shx147065 DMA_ATTR_V0, /* version of this structure */
185c533a883Shx147065 0, /* lowest usable address */
186c533a883Shx147065 0xffffffffU, /* highest usable address */
187c533a883Shx147065 0xffffffffU, /* maximum DMAable byte count */
188c533a883Shx147065 4, /* alignment in bytes */
189c533a883Shx147065 0x100, /* burst sizes (any?) */
190c533a883Shx147065 1, /* minimum transfer */
191c533a883Shx147065 0xffffffffU, /* maximum transfer */
192c533a883Shx147065 0xffffffffU, /* maximum segment length */
193c533a883Shx147065 1, /* maximum number of segments */
194c533a883Shx147065 1, /* granularity */
195c533a883Shx147065 0, /* flags (reserved) */
196c533a883Shx147065 };
197c533a883Shx147065
198c533a883Shx147065 /* DMA attributes for text and data part in the firmware */
199c533a883Shx147065 static ddi_dma_attr_t fw_dma_attr = {
200c533a883Shx147065 DMA_ATTR_V0, /* version of this structure */
201c533a883Shx147065 0, /* lowest usable address */
202c533a883Shx147065 0xffffffffU, /* highest usable address */
203c533a883Shx147065 0x7fffffff, /* maximum DMAable byte count */
204c533a883Shx147065 0x10, /* alignment in bytes */
205c533a883Shx147065 0x100, /* burst sizes (any?) */
206c533a883Shx147065 1, /* minimum transfer */
207c533a883Shx147065 0xffffffffU, /* maximum transfer */
208c533a883Shx147065 0xffffffffU, /* maximum segment length */
209c533a883Shx147065 1, /* maximum number of segments */
210c533a883Shx147065 1, /* granularity */
211c533a883Shx147065 0, /* flags (reserved) */
212c533a883Shx147065 };
213c533a883Shx147065
214c533a883Shx147065
215c533a883Shx147065 /* regs access attributes */
216c533a883Shx147065 static ddi_device_acc_attr_t iwk_reg_accattr = {
217c533a883Shx147065 DDI_DEVICE_ATTR_V0,
218c533a883Shx147065 DDI_STRUCTURE_LE_ACC,
219c533a883Shx147065 DDI_STRICTORDER_ACC,
220c533a883Shx147065 DDI_DEFAULT_ACC
221c533a883Shx147065 };
222c533a883Shx147065
223b510adaeSfei feng - Sun Microsystems - Beijing China /* DMA access attributes for Descriptor */
224b510adaeSfei feng - Sun Microsystems - Beijing China static ddi_device_acc_attr_t iwk_dma_descattr = {
225b510adaeSfei feng - Sun Microsystems - Beijing China DDI_DEVICE_ATTR_V0,
226b510adaeSfei feng - Sun Microsystems - Beijing China DDI_STRUCTURE_LE_ACC,
227b510adaeSfei feng - Sun Microsystems - Beijing China DDI_STRICTORDER_ACC,
228b510adaeSfei feng - Sun Microsystems - Beijing China DDI_DEFAULT_ACC
229b510adaeSfei feng - Sun Microsystems - Beijing China };
230b510adaeSfei feng - Sun Microsystems - Beijing China
231c533a883Shx147065 /* DMA access attributes */
232c533a883Shx147065 static ddi_device_acc_attr_t iwk_dma_accattr = {
233c533a883Shx147065 DDI_DEVICE_ATTR_V0,
234c533a883Shx147065 DDI_NEVERSWAP_ACC,
235c533a883Shx147065 DDI_STRICTORDER_ACC,
236c533a883Shx147065 DDI_DEFAULT_ACC
237c533a883Shx147065 };
238c533a883Shx147065
239c533a883Shx147065 static int iwk_ring_init(iwk_sc_t *);
240c533a883Shx147065 static void iwk_ring_free(iwk_sc_t *);
241c533a883Shx147065 static int iwk_alloc_shared(iwk_sc_t *);
242c533a883Shx147065 static void iwk_free_shared(iwk_sc_t *);
243c533a883Shx147065 static int iwk_alloc_kw(iwk_sc_t *);
244c533a883Shx147065 static void iwk_free_kw(iwk_sc_t *);
245c533a883Shx147065 static int iwk_alloc_fw_dma(iwk_sc_t *);
246c533a883Shx147065 static void iwk_free_fw_dma(iwk_sc_t *);
247c533a883Shx147065 static int iwk_alloc_rx_ring(iwk_sc_t *);
248c533a883Shx147065 static void iwk_reset_rx_ring(iwk_sc_t *);
249c533a883Shx147065 static void iwk_free_rx_ring(iwk_sc_t *);
250c533a883Shx147065 static int iwk_alloc_tx_ring(iwk_sc_t *, iwk_tx_ring_t *,
251c533a883Shx147065 int, int);
252c533a883Shx147065 static void iwk_reset_tx_ring(iwk_sc_t *, iwk_tx_ring_t *);
253c533a883Shx147065 static void iwk_free_tx_ring(iwk_sc_t *, iwk_tx_ring_t *);
254c533a883Shx147065
25543439c96Shx147065 static ieee80211_node_t *iwk_node_alloc(ieee80211com_t *);
25643439c96Shx147065 static void iwk_node_free(ieee80211_node_t *);
257c533a883Shx147065 static int iwk_newstate(ieee80211com_t *, enum ieee80211_state, int);
258c533a883Shx147065 static int iwk_key_set(ieee80211com_t *, const struct ieee80211_key *,
259c533a883Shx147065 const uint8_t mac[IEEE80211_ADDR_LEN]);
260c533a883Shx147065 static void iwk_mac_access_enter(iwk_sc_t *);
261c533a883Shx147065 static void iwk_mac_access_exit(iwk_sc_t *);
262c533a883Shx147065 static uint32_t iwk_reg_read(iwk_sc_t *, uint32_t);
263c533a883Shx147065 static void iwk_reg_write(iwk_sc_t *, uint32_t, uint32_t);
264c533a883Shx147065 static void iwk_reg_write_region_4(iwk_sc_t *, uint32_t,
265c533a883Shx147065 uint32_t *, int);
266c533a883Shx147065 static int iwk_load_firmware(iwk_sc_t *);
267c533a883Shx147065 static void iwk_rx_intr(iwk_sc_t *, iwk_rx_desc_t *,
268c533a883Shx147065 iwk_rx_data_t *);
269c533a883Shx147065 static void iwk_tx_intr(iwk_sc_t *, iwk_rx_desc_t *,
270c533a883Shx147065 iwk_rx_data_t *);
271c533a883Shx147065 static void iwk_cmd_intr(iwk_sc_t *, iwk_rx_desc_t *);
272cdc64593Sxinghua wen - Sun Microsystems - Beijing China static uint_t iwk_intr(caddr_t, caddr_t);
273c533a883Shx147065 static int iwk_eep_load(iwk_sc_t *sc);
274c533a883Shx147065 static void iwk_get_mac_from_eep(iwk_sc_t *sc);
275c533a883Shx147065 static int iwk_eep_sem_down(iwk_sc_t *sc);
276c533a883Shx147065 static void iwk_eep_sem_up(iwk_sc_t *sc);
277cdc64593Sxinghua wen - Sun Microsystems - Beijing China static uint_t iwk_rx_softintr(caddr_t, caddr_t);
278c533a883Shx147065 static uint8_t iwk_rate_to_plcp(int);
279c533a883Shx147065 static int iwk_cmd(iwk_sc_t *, int, const void *, int, int);
280c533a883Shx147065 static void iwk_set_led(iwk_sc_t *, uint8_t, uint8_t, uint8_t);
281c533a883Shx147065 static int iwk_hw_set_before_auth(iwk_sc_t *);
282c533a883Shx147065 static int iwk_scan(iwk_sc_t *);
283c533a883Shx147065 static int iwk_config(iwk_sc_t *);
284c533a883Shx147065 static void iwk_stop_master(iwk_sc_t *);
285c533a883Shx147065 static int iwk_power_up(iwk_sc_t *);
286c533a883Shx147065 static int iwk_preinit(iwk_sc_t *);
287c533a883Shx147065 static int iwk_init(iwk_sc_t *);
288c533a883Shx147065 static void iwk_stop(iwk_sc_t *);
28943439c96Shx147065 static void iwk_amrr_init(iwk_amrr_t *);
29043439c96Shx147065 static void iwk_amrr_timeout(iwk_sc_t *);
29143439c96Shx147065 static void iwk_amrr_ratectl(void *, ieee80211_node_t *);
292cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int32_t iwk_curr_tempera(iwk_sc_t *sc);
293cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_tx_power_calibration(iwk_sc_t *sc);
294cdc64593Sxinghua wen - Sun Microsystems - Beijing China static inline int iwk_is_24G_band(iwk_sc_t *sc);
295cdc64593Sxinghua wen - Sun Microsystems - Beijing China static inline int iwk_is_fat_channel(iwk_sc_t *sc);
296cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_txpower_grp(uint16_t channel);
297cdc64593Sxinghua wen - Sun Microsystems - Beijing China static struct iwk_eep_channel *iwk_get_eep_channel(iwk_sc_t *sc,
298cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint16_t channel,
299cdc64593Sxinghua wen - Sun Microsystems - Beijing China int is_24G, int is_fat, int is_hi_chan);
300cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int32_t iwk_band_number(iwk_sc_t *sc, uint16_t channel);
301cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_division(int32_t num, int32_t denom, int32_t *res);
302cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int32_t iwk_interpolate_value(int32_t x, int32_t x1, int32_t y1,
303cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t x2, int32_t y2);
304cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_channel_interpolate(iwk_sc_t *sc, uint16_t channel,
305cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_eep_calib_channel_info *chan_info);
306cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int32_t iwk_voltage_compensation(int32_t eep_voltage,
307cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t curr_voltage);
308cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int32_t iwk_min_power_index(int32_t rate_pow_idx, int32_t is_24G);
309cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_txpower_table_cmd_init(iwk_sc_t *sc,
310cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_tx_power_db *tp_db);
311cdc64593Sxinghua wen - Sun Microsystems - Beijing China static void iwk_statistics_notify(iwk_sc_t *sc, iwk_rx_desc_t *desc);
312cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_is_associated(iwk_sc_t *sc);
313cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_rxgain_diff_init(iwk_sc_t *sc);
314cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_rxgain_diff(iwk_sc_t *sc);
315cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_rx_sens_init(iwk_sc_t *sc);
316cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_rx_sens(iwk_sc_t *sc);
317cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_cck_sens(iwk_sc_t *sc, uint32_t actual_rx_time);
318cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_ofdm_sens(iwk_sc_t *sc, uint32_t actual_rx_time);
31919d332feSfei feng - Sun Microsystems - Beijing China static void iwk_recv_mgmt(struct ieee80211com *ic, mblk_t *mp,
32019d332feSfei feng - Sun Microsystems - Beijing China struct ieee80211_node *in, int subtype, int rssi, uint32_t rstamp);
321cdc64593Sxinghua wen - Sun Microsystems - Beijing China
322cdc64593Sxinghua wen - Sun Microsystems - Beijing China static void iwk_write_event_log(iwk_sc_t *);
323cdc64593Sxinghua wen - Sun Microsystems - Beijing China static void iwk_write_error_log(iwk_sc_t *);
324c533a883Shx147065
325c533a883Shx147065 static int iwk_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
326c533a883Shx147065 static int iwk_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
327d2a61391Spengcheng chen - Sun Microsystems - Beijing China static int iwk_quiesce(dev_info_t *dip);
328c533a883Shx147065
329c533a883Shx147065 /*
330c533a883Shx147065 * GLD specific operations
331c533a883Shx147065 */
332c533a883Shx147065 static int iwk_m_stat(void *arg, uint_t stat, uint64_t *val);
333c533a883Shx147065 static int iwk_m_start(void *arg);
334c533a883Shx147065 static void iwk_m_stop(void *arg);
335c533a883Shx147065 static int iwk_m_unicst(void *arg, const uint8_t *macaddr);
336c533a883Shx147065 static int iwk_m_multicst(void *arg, boolean_t add, const uint8_t *m);
337c533a883Shx147065 static int iwk_m_promisc(void *arg, boolean_t on);
338c533a883Shx147065 static mblk_t *iwk_m_tx(void *arg, mblk_t *mp);
339c533a883Shx147065 static void iwk_m_ioctl(void *arg, queue_t *wq, mblk_t *mp);
340bcb5c89dSSowmini Varadhan static int iwk_m_setprop(void *arg, const char *pr_name,
341bcb5c89dSSowmini Varadhan mac_prop_id_t wldp_pr_name, uint_t wldp_length, const void *wldp_buf);
342bcb5c89dSSowmini Varadhan static int iwk_m_getprop(void *arg, const char *pr_name,
343*0dc2366fSVenugopal Iyer mac_prop_id_t wldp_pr_name, uint_t wldp_length, void *wldp_buf);
344*0dc2366fSVenugopal Iyer static void iwk_m_propinfo(void *arg, const char *pr_name,
345*0dc2366fSVenugopal Iyer mac_prop_id_t wldp_pr_num, mac_prop_info_handle_t mph);
346c533a883Shx147065 static void iwk_destroy_locks(iwk_sc_t *sc);
347c533a883Shx147065 static int iwk_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type);
348c533a883Shx147065 static void iwk_thread(iwk_sc_t *sc);
349f3c4902cSpengcheng chen - Sun Microsystems - Beijing China static void iwk_watchdog(void *arg);
35019d332feSfei feng - Sun Microsystems - Beijing China static int iwk_run_state_config_ibss(ieee80211com_t *ic);
35119d332feSfei feng - Sun Microsystems - Beijing China static int iwk_run_state_config_sta(ieee80211com_t *ic);
3526f12def4Spengcheng chen - Sun Microsystems - Beijing China static int iwk_fast_recover(iwk_sc_t *sc);
35319d332feSfei feng - Sun Microsystems - Beijing China static int iwk_start_tx_beacon(ieee80211com_t *ic);
35419d332feSfei feng - Sun Microsystems - Beijing China static int iwk_clean_add_node_ibss(struct ieee80211com *ic,
35519d332feSfei feng - Sun Microsystems - Beijing China uint8_t addr[IEEE80211_ADDR_LEN], uint8_t *index2);
356c533a883Shx147065
357c533a883Shx147065 /*
358c533a883Shx147065 * Supported rates for 802.11b/g modes (in 500Kbps unit).
359c533a883Shx147065 * 11a and 11n support will be added later.
360c533a883Shx147065 */
361c533a883Shx147065 static const struct ieee80211_rateset iwk_rateset_11b =
362c533a883Shx147065 { 4, { 2, 4, 11, 22 } };
363c533a883Shx147065
364c533a883Shx147065 static const struct ieee80211_rateset iwk_rateset_11g =
365c533a883Shx147065 { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
366c533a883Shx147065
367c533a883Shx147065 /*
368c533a883Shx147065 * For mfthread only
369c533a883Shx147065 */
370c533a883Shx147065 extern pri_t minclsyspri;
371c533a883Shx147065
372c533a883Shx147065 #define DRV_NAME_4965 "iwk"
373c533a883Shx147065
374c533a883Shx147065 /*
375c533a883Shx147065 * Module Loading Data & Entry Points
376c533a883Shx147065 */
377c533a883Shx147065 DDI_DEFINE_STREAM_OPS(iwk_devops, nulldev, nulldev, iwk_attach,
378d2a61391Spengcheng chen - Sun Microsystems - Beijing China iwk_detach, nodev, NULL, D_MP, NULL, iwk_quiesce);
379c533a883Shx147065
380c533a883Shx147065 static struct modldrv iwk_modldrv = {
381c533a883Shx147065 &mod_driverops,
382c533a883Shx147065 "Intel(R) 4965AGN driver(N)",
383c533a883Shx147065 &iwk_devops
384c533a883Shx147065 };
385c533a883Shx147065
386c533a883Shx147065 static struct modlinkage iwk_modlinkage = {
387c533a883Shx147065 MODREV_1,
388c533a883Shx147065 &iwk_modldrv,
389c533a883Shx147065 NULL
390c533a883Shx147065 };
391c533a883Shx147065
392c533a883Shx147065 int
_init(void)393c533a883Shx147065 _init(void)
394c533a883Shx147065 {
395c533a883Shx147065 int status;
396c533a883Shx147065
397c533a883Shx147065 status = ddi_soft_state_init(&iwk_soft_state_p,
398c533a883Shx147065 sizeof (iwk_sc_t), 1);
399c533a883Shx147065 if (status != DDI_SUCCESS)
400c533a883Shx147065 return (status);
401c533a883Shx147065
402c533a883Shx147065 mac_init_ops(&iwk_devops, DRV_NAME_4965);
403c533a883Shx147065 status = mod_install(&iwk_modlinkage);
404c533a883Shx147065 if (status != DDI_SUCCESS) {
405c533a883Shx147065 mac_fini_ops(&iwk_devops);
406c533a883Shx147065 ddi_soft_state_fini(&iwk_soft_state_p);
407c533a883Shx147065 }
408c533a883Shx147065
409c533a883Shx147065 return (status);
410c533a883Shx147065 }
411c533a883Shx147065
412c533a883Shx147065 int
_fini(void)413c533a883Shx147065 _fini(void)
414c533a883Shx147065 {
415c533a883Shx147065 int status;
416c533a883Shx147065
417c533a883Shx147065 status = mod_remove(&iwk_modlinkage);
418c533a883Shx147065 if (status == DDI_SUCCESS) {
419c533a883Shx147065 mac_fini_ops(&iwk_devops);
420c533a883Shx147065 ddi_soft_state_fini(&iwk_soft_state_p);
421c533a883Shx147065 }
422c533a883Shx147065
423c533a883Shx147065 return (status);
424c533a883Shx147065 }
425c533a883Shx147065
426c533a883Shx147065 int
_info(struct modinfo * mip)427c533a883Shx147065 _info(struct modinfo *mip)
428c533a883Shx147065 {
429c533a883Shx147065 return (mod_info(&iwk_modlinkage, mip));
430c533a883Shx147065 }
431c533a883Shx147065
432c533a883Shx147065 /*
433c533a883Shx147065 * Mac Call Back entries
434c533a883Shx147065 */
435c533a883Shx147065 mac_callbacks_t iwk_m_callbacks = {
436*0dc2366fSVenugopal Iyer MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO,
437c533a883Shx147065 iwk_m_stat,
438c533a883Shx147065 iwk_m_start,
439c533a883Shx147065 iwk_m_stop,
440c533a883Shx147065 iwk_m_promisc,
441c533a883Shx147065 iwk_m_multicst,
442c533a883Shx147065 iwk_m_unicst,
443c533a883Shx147065 iwk_m_tx,
444*0dc2366fSVenugopal Iyer NULL,
445bcb5c89dSSowmini Varadhan iwk_m_ioctl,
446bcb5c89dSSowmini Varadhan NULL,
447bcb5c89dSSowmini Varadhan NULL,
448bcb5c89dSSowmini Varadhan NULL,
449bcb5c89dSSowmini Varadhan iwk_m_setprop,
450*0dc2366fSVenugopal Iyer iwk_m_getprop,
451*0dc2366fSVenugopal Iyer iwk_m_propinfo
452c533a883Shx147065 };
453c533a883Shx147065
454c533a883Shx147065 #ifdef DEBUG
455c533a883Shx147065 void
iwk_dbg(uint32_t flags,const char * fmt,...)456c533a883Shx147065 iwk_dbg(uint32_t flags, const char *fmt, ...)
457c533a883Shx147065 {
458c533a883Shx147065 va_list ap;
459c533a883Shx147065
460c533a883Shx147065 if (flags & iwk_dbg_flags) {
461c533a883Shx147065 va_start(ap, fmt);
462c533a883Shx147065 vcmn_err(CE_NOTE, fmt, ap);
463c533a883Shx147065 va_end(ap);
464c533a883Shx147065 }
465c533a883Shx147065 }
466c533a883Shx147065 #endif
467c533a883Shx147065
468c533a883Shx147065 /*
469c533a883Shx147065 * device operations
470c533a883Shx147065 */
471c533a883Shx147065 int
iwk_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)472c533a883Shx147065 iwk_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
473c533a883Shx147065 {
474c533a883Shx147065 iwk_sc_t *sc;
475c533a883Shx147065 ieee80211com_t *ic;
476c533a883Shx147065 int instance, err, i;
477c533a883Shx147065 char strbuf[32];
478c533a883Shx147065 wifi_data_t wd = { 0 };
479c533a883Shx147065 mac_register_t *macp;
480c533a883Shx147065
481cdc64593Sxinghua wen - Sun Microsystems - Beijing China int intr_type;
482cdc64593Sxinghua wen - Sun Microsystems - Beijing China int intr_count;
483cdc64593Sxinghua wen - Sun Microsystems - Beijing China int intr_actual;
484cdc64593Sxinghua wen - Sun Microsystems - Beijing China
485d62cb7ffShx147065 switch (cmd) {
486d62cb7ffShx147065 case DDI_ATTACH:
487d62cb7ffShx147065 break;
488d62cb7ffShx147065 case DDI_RESUME:
489d62cb7ffShx147065 sc = ddi_get_soft_state(iwk_soft_state_p,
490d62cb7ffShx147065 ddi_get_instance(dip));
491d62cb7ffShx147065 ASSERT(sc != NULL);
49209539a3cSpengcheng chen - Sun Microsystems - Beijing China
49309539a3cSpengcheng chen - Sun Microsystems - Beijing China mutex_enter(&sc->sc_glock);
49409539a3cSpengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~IWK_F_SUSPEND;
49509539a3cSpengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock);
49609539a3cSpengcheng chen - Sun Microsystems - Beijing China
497d40f4da4Spengcheng chen - Sun Microsystems - Beijing China if (sc->sc_flags & IWK_F_RUNNING)
498d40f4da4Spengcheng chen - Sun Microsystems - Beijing China (void) iwk_init(sc);
499d40f4da4Spengcheng chen - Sun Microsystems - Beijing China
500d62cb7ffShx147065 mutex_enter(&sc->sc_glock);
501d40f4da4Spengcheng chen - Sun Microsystems - Beijing China sc->sc_flags |= IWK_F_LAZY_RESUME;
502d62cb7ffShx147065 mutex_exit(&sc->sc_glock);
503d40f4da4Spengcheng chen - Sun Microsystems - Beijing China
504d62cb7ffShx147065 IWK_DBG((IWK_DEBUG_RESUME, "iwk: resume\n"));
505d62cb7ffShx147065 return (DDI_SUCCESS);
506d62cb7ffShx147065 default:
507c533a883Shx147065 err = DDI_FAILURE;
508c533a883Shx147065 goto attach_fail1;
509c533a883Shx147065 }
510c533a883Shx147065
511c533a883Shx147065 instance = ddi_get_instance(dip);
512c533a883Shx147065 err = ddi_soft_state_zalloc(iwk_soft_state_p, instance);
513c533a883Shx147065 if (err != DDI_SUCCESS) {
514c533a883Shx147065 cmn_err(CE_WARN,
515c533a883Shx147065 "iwk_attach(): failed to allocate soft state\n");
516c533a883Shx147065 goto attach_fail1;
517c533a883Shx147065 }
518c533a883Shx147065 sc = ddi_get_soft_state(iwk_soft_state_p, instance);
519c533a883Shx147065 sc->sc_dip = dip;
520c533a883Shx147065
521c533a883Shx147065 err = ddi_regs_map_setup(dip, 0, &sc->sc_cfg_base, 0, 0,
522c533a883Shx147065 &iwk_reg_accattr, &sc->sc_cfg_handle);
523c533a883Shx147065 if (err != DDI_SUCCESS) {
524c533a883Shx147065 cmn_err(CE_WARN,
525c533a883Shx147065 "iwk_attach(): failed to map config spaces regs\n");
526c533a883Shx147065 goto attach_fail2;
527c533a883Shx147065 }
528c533a883Shx147065 sc->sc_rev = ddi_get8(sc->sc_cfg_handle,
529c533a883Shx147065 (uint8_t *)(sc->sc_cfg_base + PCI_CONF_REVID));
530c533a883Shx147065 ddi_put8(sc->sc_cfg_handle, (uint8_t *)(sc->sc_cfg_base + 0x41), 0);
531c533a883Shx147065 sc->sc_clsz = ddi_get16(sc->sc_cfg_handle,
532c533a883Shx147065 (uint16_t *)(sc->sc_cfg_base + PCI_CONF_CACHE_LINESZ));
533c533a883Shx147065 if (!sc->sc_clsz)
534c533a883Shx147065 sc->sc_clsz = 16;
535c533a883Shx147065 sc->sc_clsz = (sc->sc_clsz << 2);
536c533a883Shx147065 sc->sc_dmabuf_sz = roundup(0x1000 + sizeof (struct ieee80211_frame) +
537c533a883Shx147065 IEEE80211_MTU + IEEE80211_CRC_LEN +
538c533a883Shx147065 (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
539c533a883Shx147065 IEEE80211_WEP_CRCLEN), sc->sc_clsz);
540c533a883Shx147065 /*
541c533a883Shx147065 * Map operating registers
542c533a883Shx147065 */
543c533a883Shx147065 err = ddi_regs_map_setup(dip, 1, &sc->sc_base,
544c533a883Shx147065 0, 0, &iwk_reg_accattr, &sc->sc_handle);
545c533a883Shx147065 if (err != DDI_SUCCESS) {
546c533a883Shx147065 cmn_err(CE_WARN,
547c533a883Shx147065 "iwk_attach(): failed to map device regs\n");
548c533a883Shx147065 goto attach_fail2a;
549c533a883Shx147065 }
550c533a883Shx147065
551cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = ddi_intr_get_supported_types(dip, &intr_type);
552cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((err != DDI_SUCCESS) || (!(intr_type & DDI_INTR_TYPE_FIXED))) {
553cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_attach(): "
554cdc64593Sxinghua wen - Sun Microsystems - Beijing China "Fixed type interrupt is not supported\n");
555cdc64593Sxinghua wen - Sun Microsystems - Beijing China goto attach_fail_intr_a;
556c533a883Shx147065 }
557cdc64593Sxinghua wen - Sun Microsystems - Beijing China
558cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = ddi_intr_get_nintrs(dip, DDI_INTR_TYPE_FIXED, &intr_count);
559cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((err != DDI_SUCCESS) || (intr_count != 1)) {
560cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_attach(): "
561cdc64593Sxinghua wen - Sun Microsystems - Beijing China "No fixed interrupts\n");
562cdc64593Sxinghua wen - Sun Microsystems - Beijing China goto attach_fail_intr_a;
563cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
564cdc64593Sxinghua wen - Sun Microsystems - Beijing China
565cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_intr_htable = kmem_zalloc(sizeof (ddi_intr_handle_t), KM_SLEEP);
566cdc64593Sxinghua wen - Sun Microsystems - Beijing China
567cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = ddi_intr_alloc(dip, sc->sc_intr_htable, DDI_INTR_TYPE_FIXED, 0,
568cdc64593Sxinghua wen - Sun Microsystems - Beijing China intr_count, &intr_actual, 0);
569cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((err != DDI_SUCCESS) || (intr_actual != 1)) {
570cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_attach(): "
571cdc64593Sxinghua wen - Sun Microsystems - Beijing China "ddi_intr_alloc() failed 0x%x\n", err);
572cdc64593Sxinghua wen - Sun Microsystems - Beijing China goto attach_fail_intr_b;
573cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
574cdc64593Sxinghua wen - Sun Microsystems - Beijing China
575cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = ddi_intr_get_pri(sc->sc_intr_htable[0], &sc->sc_intr_pri);
576cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) {
577cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_attach(): "
578cdc64593Sxinghua wen - Sun Microsystems - Beijing China "ddi_intr_get_pri() failed 0x%x\n", err);
579cdc64593Sxinghua wen - Sun Microsystems - Beijing China goto attach_fail_intr_c;
580cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
581cdc64593Sxinghua wen - Sun Microsystems - Beijing China
582cdc64593Sxinghua wen - Sun Microsystems - Beijing China mutex_init(&sc->sc_glock, NULL, MUTEX_DRIVER,
583cdc64593Sxinghua wen - Sun Microsystems - Beijing China DDI_INTR_PRI(sc->sc_intr_pri));
584cdc64593Sxinghua wen - Sun Microsystems - Beijing China mutex_init(&sc->sc_tx_lock, NULL, MUTEX_DRIVER,
585cdc64593Sxinghua wen - Sun Microsystems - Beijing China DDI_INTR_PRI(sc->sc_intr_pri));
586cdc64593Sxinghua wen - Sun Microsystems - Beijing China mutex_init(&sc->sc_mt_lock, NULL, MUTEX_DRIVER,
587cdc64593Sxinghua wen - Sun Microsystems - Beijing China DDI_INTR_PRI(sc->sc_intr_pri));
58819d332feSfei feng - Sun Microsystems - Beijing China mutex_init(&sc->sc_ibss.node_tb_lock, NULL, MUTEX_DRIVER,
58919d332feSfei feng - Sun Microsystems - Beijing China DDI_INTR_PRI(sc->sc_intr_pri));
590cdc64593Sxinghua wen - Sun Microsystems - Beijing China
591c533a883Shx147065 cv_init(&sc->sc_fw_cv, NULL, CV_DRIVER, NULL);
592c533a883Shx147065 cv_init(&sc->sc_cmd_cv, NULL, CV_DRIVER, NULL);
593c533a883Shx147065 cv_init(&sc->sc_tx_cv, "tx-ring", CV_DRIVER, NULL);
594c533a883Shx147065 /*
595c533a883Shx147065 * initialize the mfthread
596c533a883Shx147065 */
597c533a883Shx147065 cv_init(&sc->sc_mt_cv, NULL, CV_DRIVER, NULL);
598c533a883Shx147065 sc->sc_mf_thread = NULL;
599c533a883Shx147065 sc->sc_mf_thread_switch = 0;
600c533a883Shx147065
601c533a883Shx147065 /*
602c533a883Shx147065 * Allocate shared page.
603c533a883Shx147065 */
604c533a883Shx147065 err = iwk_alloc_shared(sc);
605c533a883Shx147065 if (err != DDI_SUCCESS) {
606cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_attach(): "
607cdc64593Sxinghua wen - Sun Microsystems - Beijing China "failed to allocate shared page\n");
608c533a883Shx147065 goto attach_fail3;
609c533a883Shx147065 }
610c533a883Shx147065
611c533a883Shx147065 /*
612c533a883Shx147065 * Allocate keep warm page.
613c533a883Shx147065 */
614c533a883Shx147065 err = iwk_alloc_kw(sc);
615c533a883Shx147065 if (err != DDI_SUCCESS) {
616cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_attach(): "
617cdc64593Sxinghua wen - Sun Microsystems - Beijing China "failed to allocate keep warm page\n");
618c533a883Shx147065 goto attach_fail3a;
619c533a883Shx147065 }
620c533a883Shx147065
621c533a883Shx147065 /*
622c533a883Shx147065 * Do some necessary hardware initializations.
623c533a883Shx147065 */
624c533a883Shx147065 err = iwk_preinit(sc);
625c533a883Shx147065 if (err != DDI_SUCCESS) {
626cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_attach(): "
627cdc64593Sxinghua wen - Sun Microsystems - Beijing China "failed to init hardware\n");
628c533a883Shx147065 goto attach_fail4;
629c533a883Shx147065 }
630c533a883Shx147065
631c533a883Shx147065 /* initialize EEPROM */
632c533a883Shx147065 err = iwk_eep_load(sc); /* get hardware configurations from eeprom */
633c533a883Shx147065 if (err != 0) {
634c533a883Shx147065 cmn_err(CE_WARN, "iwk_attach(): failed to load eeprom\n");
635c533a883Shx147065 goto attach_fail4;
636c533a883Shx147065 }
637c533a883Shx147065
638b510adaeSfei feng - Sun Microsystems - Beijing China if (LE_16(sc->sc_eep_map.calib_version) < EEP_TX_POWER_VERSION_NEW) {
639c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "older EEPROM detected\n");
640c533a883Shx147065 goto attach_fail4;
641c533a883Shx147065 }
642c533a883Shx147065
643c533a883Shx147065 iwk_get_mac_from_eep(sc);
644c533a883Shx147065
645c533a883Shx147065 err = iwk_ring_init(sc);
646c533a883Shx147065 if (err != DDI_SUCCESS) {
647c533a883Shx147065 cmn_err(CE_WARN, "iwk_attach(): "
648c533a883Shx147065 "failed to allocate and initialize ring\n");
649c533a883Shx147065 goto attach_fail4;
650c533a883Shx147065 }
651c533a883Shx147065
652c533a883Shx147065 sc->sc_hdr = (iwk_firmware_hdr_t *)iwk_fw_bin;
653c533a883Shx147065
654c533a883Shx147065 err = iwk_alloc_fw_dma(sc);
655c533a883Shx147065 if (err != DDI_SUCCESS) {
656c533a883Shx147065 cmn_err(CE_WARN, "iwk_attach(): "
657c533a883Shx147065 "failed to allocate firmware dma\n");
658c533a883Shx147065 goto attach_fail5;
659c533a883Shx147065 }
660c533a883Shx147065
661c533a883Shx147065 /*
662c533a883Shx147065 * Initialize the wifi part, which will be used by
663c533a883Shx147065 * generic layer
664c533a883Shx147065 */
665c533a883Shx147065 ic = &sc->sc_ic;
666c533a883Shx147065 ic->ic_phytype = IEEE80211_T_OFDM;
667c533a883Shx147065 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
668c533a883Shx147065 ic->ic_state = IEEE80211_S_INIT;
669c533a883Shx147065 ic->ic_maxrssi = 100; /* experimental number */
670c533a883Shx147065 ic->ic_caps = IEEE80211_C_SHPREAMBLE | IEEE80211_C_TXPMGT |
671c533a883Shx147065 IEEE80211_C_PMGT | IEEE80211_C_SHSLOT;
672c533a883Shx147065 /*
673c533a883Shx147065 * use software WEP and TKIP, hardware CCMP;
674c533a883Shx147065 */
675c533a883Shx147065 ic->ic_caps |= IEEE80211_C_AES_CCM;
676c533a883Shx147065 /*
677c533a883Shx147065 * Support WPA/WPA2
678c533a883Shx147065 */
679c533a883Shx147065 ic->ic_caps |= IEEE80211_C_WPA;
68019d332feSfei feng - Sun Microsystems - Beijing China /*
68119d332feSfei feng - Sun Microsystems - Beijing China * support Adhoc mode
68219d332feSfei feng - Sun Microsystems - Beijing China */
68319d332feSfei feng - Sun Microsystems - Beijing China ic->ic_caps |= IEEE80211_C_IBSS;
684cdc64593Sxinghua wen - Sun Microsystems - Beijing China
685c533a883Shx147065 /* set supported .11b and .11g rates */
686c533a883Shx147065 ic->ic_sup_rates[IEEE80211_MODE_11B] = iwk_rateset_11b;
687c533a883Shx147065 ic->ic_sup_rates[IEEE80211_MODE_11G] = iwk_rateset_11g;
688c533a883Shx147065
689c50ced99Spengcheng chen - Sun Microsystems - Beijing China /* set supported .11b and .11g channels (1 through 11) */
690c50ced99Spengcheng chen - Sun Microsystems - Beijing China for (i = 1; i <= 11; i++) {
691c533a883Shx147065 ic->ic_sup_channels[i].ich_freq =
692c533a883Shx147065 ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
693c533a883Shx147065 ic->ic_sup_channels[i].ich_flags =
694c533a883Shx147065 IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
695c50ced99Spengcheng chen - Sun Microsystems - Beijing China IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ |
696c50ced99Spengcheng chen - Sun Microsystems - Beijing China IEEE80211_CHAN_PASSIVE;
697c533a883Shx147065 }
69819d332feSfei feng - Sun Microsystems - Beijing China ic->ic_ibss_chan = &ic->ic_sup_channels[0];
699cdc64593Sxinghua wen - Sun Microsystems - Beijing China
700c533a883Shx147065 ic->ic_xmit = iwk_send;
701c533a883Shx147065 /*
702c533a883Shx147065 * init Wifi layer
703c533a883Shx147065 */
704c533a883Shx147065 ieee80211_attach(ic);
705c533a883Shx147065
706c533a883Shx147065 /*
707c533a883Shx147065 * different instance has different WPA door
708c533a883Shx147065 */
709c533a883Shx147065 (void) snprintf(ic->ic_wpadoor, MAX_IEEE80211STR, "%s_%s%d", WPA_DOOR,
710c533a883Shx147065 ddi_driver_name(dip),
711c533a883Shx147065 ddi_get_instance(dip));
712c533a883Shx147065
713c533a883Shx147065 /*
714c533a883Shx147065 * Override 80211 default routines
715c533a883Shx147065 */
716c533a883Shx147065 sc->sc_newstate = ic->ic_newstate;
717c533a883Shx147065 ic->ic_newstate = iwk_newstate;
718f3c4902cSpengcheng chen - Sun Microsystems - Beijing China ic->ic_watchdog = iwk_watchdog;
719cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_recv_mgmt = ic->ic_recv_mgmt;
72019d332feSfei feng - Sun Microsystems - Beijing China ic->ic_recv_mgmt = iwk_recv_mgmt;
72143439c96Shx147065 ic->ic_node_alloc = iwk_node_alloc;
72243439c96Shx147065 ic->ic_node_free = iwk_node_free;
723c533a883Shx147065 ic->ic_crypto.cs_key_set = iwk_key_set;
724c533a883Shx147065 ieee80211_media_init(ic);
725c533a883Shx147065 /*
726c533a883Shx147065 * initialize default tx key
727c533a883Shx147065 */
728c533a883Shx147065 ic->ic_def_txkey = 0;
729cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = ddi_intr_add_softint(dip, &sc->sc_soft_hdl, DDI_INTR_SOFTPRI_MAX,
730cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_rx_softintr, (caddr_t)sc);
731c533a883Shx147065 if (err != DDI_SUCCESS) {
732cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_attach(): "
733cdc64593Sxinghua wen - Sun Microsystems - Beijing China "add soft interrupt failed\n");
734c533a883Shx147065 goto attach_fail7;
735c533a883Shx147065 }
736c533a883Shx147065
737c533a883Shx147065 /*
738c533a883Shx147065 * Add the interrupt handler
739c533a883Shx147065 */
740cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = ddi_intr_add_handler(sc->sc_intr_htable[0], iwk_intr,
741cdc64593Sxinghua wen - Sun Microsystems - Beijing China (caddr_t)sc, NULL);
742c533a883Shx147065 if (err != DDI_SUCCESS) {
743cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_attach(): "
744cdc64593Sxinghua wen - Sun Microsystems - Beijing China "ddi_intr_add_handle() failed\n");
745c533a883Shx147065 goto attach_fail8;
746c533a883Shx147065 }
747c533a883Shx147065
748cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = ddi_intr_enable(sc->sc_intr_htable[0]);
749cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) {
750cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_attach(): "
751cdc64593Sxinghua wen - Sun Microsystems - Beijing China "ddi_intr_enable() failed\n");
752cdc64593Sxinghua wen - Sun Microsystems - Beijing China goto attach_fail_intr_d;
753cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
754cdc64593Sxinghua wen - Sun Microsystems - Beijing China
755c533a883Shx147065 /*
756c533a883Shx147065 * Initialize pointer to device specific functions
757c533a883Shx147065 */
758c533a883Shx147065 wd.wd_secalloc = WIFI_SEC_NONE;
759c533a883Shx147065 wd.wd_opmode = ic->ic_opmode;
760c533a883Shx147065 IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_macaddr);
761c533a883Shx147065
762c533a883Shx147065 macp = mac_alloc(MAC_VERSION);
76319d332feSfei feng - Sun Microsystems - Beijing China if (macp == NULL) {
764c533a883Shx147065 cmn_err(CE_WARN,
765c533a883Shx147065 "iwk_attach(): failed to do mac_alloc()\n");
766c533a883Shx147065 goto attach_fail9;
767c533a883Shx147065 }
768c533a883Shx147065
769c533a883Shx147065 macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI;
770c533a883Shx147065 macp->m_driver = sc;
771c533a883Shx147065 macp->m_dip = dip;
772c533a883Shx147065 macp->m_src_addr = ic->ic_macaddr;
773c533a883Shx147065 macp->m_callbacks = &iwk_m_callbacks;
774c533a883Shx147065 macp->m_min_sdu = 0;
775c533a883Shx147065 macp->m_max_sdu = IEEE80211_MTU;
776c533a883Shx147065 macp->m_pdata = &wd;
777c533a883Shx147065 macp->m_pdata_size = sizeof (wd);
778c533a883Shx147065
779c533a883Shx147065 /*
780c533a883Shx147065 * Register the macp to mac
781c533a883Shx147065 */
782c533a883Shx147065 err = mac_register(macp, &ic->ic_mach);
783c533a883Shx147065 mac_free(macp);
784c533a883Shx147065 if (err != DDI_SUCCESS) {
785c533a883Shx147065 cmn_err(CE_WARN,
786c533a883Shx147065 "iwk_attach(): failed to do mac_register()\n");
787c533a883Shx147065 goto attach_fail9;
788c533a883Shx147065 }
789c533a883Shx147065
790c533a883Shx147065 /*
791c533a883Shx147065 * Create minor node of type DDI_NT_NET_WIFI
792c533a883Shx147065 */
793c533a883Shx147065 (void) snprintf(strbuf, sizeof (strbuf), DRV_NAME_4965"%d", instance);
794c533a883Shx147065 err = ddi_create_minor_node(dip, strbuf, S_IFCHR,
795c533a883Shx147065 instance + 1, DDI_NT_NET_WIFI, 0);
796c533a883Shx147065 if (err != DDI_SUCCESS)
797c533a883Shx147065 cmn_err(CE_WARN,
798c533a883Shx147065 "iwk_attach(): failed to do ddi_create_minor_node()\n");
799c533a883Shx147065
800c533a883Shx147065 /*
801c533a883Shx147065 * Notify link is down now
802c533a883Shx147065 */
803c533a883Shx147065 mac_link_update(ic->ic_mach, LINK_STATE_DOWN);
804c533a883Shx147065
805c533a883Shx147065 /*
806c533a883Shx147065 * create the mf thread to handle the link status,
807c533a883Shx147065 * recovery fatal error, etc.
808c533a883Shx147065 */
809c533a883Shx147065 sc->sc_mf_thread_switch = 1;
810c533a883Shx147065 if (sc->sc_mf_thread == NULL)
811c533a883Shx147065 sc->sc_mf_thread = thread_create((caddr_t)NULL, 0,
812c533a883Shx147065 iwk_thread, sc, 0, &p0, TS_RUN, minclsyspri);
813c533a883Shx147065
814c533a883Shx147065 sc->sc_flags |= IWK_F_ATTACHED;
815c533a883Shx147065
816c533a883Shx147065 return (DDI_SUCCESS);
817c533a883Shx147065 attach_fail9:
818cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) ddi_intr_disable(sc->sc_intr_htable[0]);
819cdc64593Sxinghua wen - Sun Microsystems - Beijing China attach_fail_intr_d:
820cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) ddi_intr_remove_handler(sc->sc_intr_htable[0]);
821cdc64593Sxinghua wen - Sun Microsystems - Beijing China
822c533a883Shx147065 attach_fail8:
823cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) ddi_intr_remove_softint(sc->sc_soft_hdl);
824cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_soft_hdl = NULL;
825c533a883Shx147065 attach_fail7:
826c533a883Shx147065 ieee80211_detach(ic);
827c533a883Shx147065 attach_fail6:
828c533a883Shx147065 iwk_free_fw_dma(sc);
829c533a883Shx147065 attach_fail5:
830c533a883Shx147065 iwk_ring_free(sc);
831c533a883Shx147065 attach_fail4:
832c533a883Shx147065 iwk_free_kw(sc);
833c533a883Shx147065 attach_fail3a:
834c533a883Shx147065 iwk_free_shared(sc);
835c533a883Shx147065 attach_fail3:
836c533a883Shx147065 iwk_destroy_locks(sc);
837cdc64593Sxinghua wen - Sun Microsystems - Beijing China attach_fail_intr_c:
838cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) ddi_intr_free(sc->sc_intr_htable[0]);
839cdc64593Sxinghua wen - Sun Microsystems - Beijing China attach_fail_intr_b:
840cdc64593Sxinghua wen - Sun Microsystems - Beijing China kmem_free(sc->sc_intr_htable, sizeof (ddi_intr_handle_t));
841cdc64593Sxinghua wen - Sun Microsystems - Beijing China attach_fail_intr_a:
842c533a883Shx147065 ddi_regs_map_free(&sc->sc_handle);
843c533a883Shx147065 attach_fail2a:
844c533a883Shx147065 ddi_regs_map_free(&sc->sc_cfg_handle);
845c533a883Shx147065 attach_fail2:
846c533a883Shx147065 ddi_soft_state_free(iwk_soft_state_p, instance);
847c533a883Shx147065 attach_fail1:
848c533a883Shx147065 return (err);
849c533a883Shx147065 }
850c533a883Shx147065
851c533a883Shx147065 int
iwk_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)852c533a883Shx147065 iwk_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
853c533a883Shx147065 {
854c533a883Shx147065 iwk_sc_t *sc;
855c533a883Shx147065 int err;
856c533a883Shx147065
857c533a883Shx147065 sc = ddi_get_soft_state(iwk_soft_state_p, ddi_get_instance(dip));
858c533a883Shx147065 ASSERT(sc != NULL);
859c533a883Shx147065
860d62cb7ffShx147065 switch (cmd) {
861d62cb7ffShx147065 case DDI_DETACH:
862d62cb7ffShx147065 break;
863d62cb7ffShx147065 case DDI_SUSPEND:
864d62cb7ffShx147065 mutex_enter(&sc->sc_glock);
865d62cb7ffShx147065 sc->sc_flags |= IWK_F_SUSPEND;
866d62cb7ffShx147065 mutex_exit(&sc->sc_glock);
867d40f4da4Spengcheng chen - Sun Microsystems - Beijing China if (sc->sc_flags & IWK_F_RUNNING) {
868d40f4da4Spengcheng chen - Sun Microsystems - Beijing China iwk_stop(sc);
869d40f4da4Spengcheng chen - Sun Microsystems - Beijing China }
870d40f4da4Spengcheng chen - Sun Microsystems - Beijing China
871d62cb7ffShx147065 IWK_DBG((IWK_DEBUG_RESUME, "iwk: suspend\n"));
872d62cb7ffShx147065 return (DDI_SUCCESS);
873d62cb7ffShx147065 default:
874c533a883Shx147065 return (DDI_FAILURE);
875d62cb7ffShx147065 }
87643439c96Shx147065
877c533a883Shx147065 if (!(sc->sc_flags & IWK_F_ATTACHED))
878c533a883Shx147065 return (DDI_FAILURE);
879c533a883Shx147065
880cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = mac_disable(sc->sc_ic.ic_mach);
881cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (err != DDI_SUCCESS)
882cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (err);
883cdc64593Sxinghua wen - Sun Microsystems - Beijing China
884c533a883Shx147065 /*
885c533a883Shx147065 * Destroy the mf_thread
886c533a883Shx147065 */
887c533a883Shx147065 mutex_enter(&sc->sc_mt_lock);
888c533a883Shx147065 sc->sc_mf_thread_switch = 0;
889c533a883Shx147065 while (sc->sc_mf_thread != NULL) {
890c533a883Shx147065 if (cv_wait_sig(&sc->sc_mt_cv, &sc->sc_mt_lock) == 0)
891c533a883Shx147065 break;
892c533a883Shx147065 }
893c533a883Shx147065 mutex_exit(&sc->sc_mt_lock);
894c533a883Shx147065
895c533a883Shx147065 iwk_stop(sc);
896c533a883Shx147065 DELAY(500000);
897c533a883Shx147065
898c533a883Shx147065 /*
899c533a883Shx147065 * Unregiste from the MAC layer subsystem
900c533a883Shx147065 */
901cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) mac_unregister(sc->sc_ic.ic_mach);
902c533a883Shx147065
903c533a883Shx147065 mutex_enter(&sc->sc_glock);
904c533a883Shx147065 iwk_free_fw_dma(sc);
905c533a883Shx147065 iwk_ring_free(sc);
906c533a883Shx147065 iwk_free_kw(sc);
907c533a883Shx147065 iwk_free_shared(sc);
908c533a883Shx147065 mutex_exit(&sc->sc_glock);
909c533a883Shx147065
910cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) ddi_intr_disable(sc->sc_intr_htable[0]);
911cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) ddi_intr_remove_handler(sc->sc_intr_htable[0]);
912cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) ddi_intr_free(sc->sc_intr_htable[0]);
913cdc64593Sxinghua wen - Sun Microsystems - Beijing China kmem_free(sc->sc_intr_htable, sizeof (ddi_intr_handle_t));
914cdc64593Sxinghua wen - Sun Microsystems - Beijing China
915cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) ddi_intr_remove_softint(sc->sc_soft_hdl);
916cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_soft_hdl = NULL;
917c533a883Shx147065
918c533a883Shx147065 /*
919c533a883Shx147065 * detach ieee80211
920c533a883Shx147065 */
921c533a883Shx147065 ieee80211_detach(&sc->sc_ic);
922c533a883Shx147065
923c533a883Shx147065 iwk_destroy_locks(sc);
924c533a883Shx147065
925c533a883Shx147065 ddi_regs_map_free(&sc->sc_handle);
926c533a883Shx147065 ddi_regs_map_free(&sc->sc_cfg_handle);
927c533a883Shx147065 ddi_remove_minor_node(dip, NULL);
928c533a883Shx147065 ddi_soft_state_free(iwk_soft_state_p, ddi_get_instance(dip));
929c533a883Shx147065
930c533a883Shx147065 return (DDI_SUCCESS);
931c533a883Shx147065 }
932c533a883Shx147065
933d2a61391Spengcheng chen - Sun Microsystems - Beijing China /*
934d2a61391Spengcheng chen - Sun Microsystems - Beijing China * quiesce(9E) entry point.
935d2a61391Spengcheng chen - Sun Microsystems - Beijing China *
936d2a61391Spengcheng chen - Sun Microsystems - Beijing China * This function is called when the system is single-threaded at high
937d2a61391Spengcheng chen - Sun Microsystems - Beijing China * PIL with preemption disabled. Therefore, this function must not be
938d2a61391Spengcheng chen - Sun Microsystems - Beijing China * blocked.
939d2a61391Spengcheng chen - Sun Microsystems - Beijing China *
940d2a61391Spengcheng chen - Sun Microsystems - Beijing China * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
941d2a61391Spengcheng chen - Sun Microsystems - Beijing China * DDI_FAILURE indicates an error condition and should almost never happen.
942d2a61391Spengcheng chen - Sun Microsystems - Beijing China */
943d2a61391Spengcheng chen - Sun Microsystems - Beijing China int
iwk_quiesce(dev_info_t * dip)944d2a61391Spengcheng chen - Sun Microsystems - Beijing China iwk_quiesce(dev_info_t *dip)
945d2a61391Spengcheng chen - Sun Microsystems - Beijing China {
946d2a61391Spengcheng chen - Sun Microsystems - Beijing China iwk_sc_t *sc;
947d2a61391Spengcheng chen - Sun Microsystems - Beijing China
948d2a61391Spengcheng chen - Sun Microsystems - Beijing China sc = ddi_get_soft_state(iwk_soft_state_p, ddi_get_instance(dip));
949d2a61391Spengcheng chen - Sun Microsystems - Beijing China ASSERT(sc != NULL);
950d2a61391Spengcheng chen - Sun Microsystems - Beijing China
951d2a61391Spengcheng chen - Sun Microsystems - Beijing China /* no message prints and no lock accquisition */
952d2a61391Spengcheng chen - Sun Microsystems - Beijing China #ifdef DEBUG
953d2a61391Spengcheng chen - Sun Microsystems - Beijing China iwk_dbg_flags = 0;
954d2a61391Spengcheng chen - Sun Microsystems - Beijing China #endif
955d2a61391Spengcheng chen - Sun Microsystems - Beijing China sc->sc_flags |= IWK_F_QUIESCED;
956d2a61391Spengcheng chen - Sun Microsystems - Beijing China
957d2a61391Spengcheng chen - Sun Microsystems - Beijing China iwk_stop(sc);
958d2a61391Spengcheng chen - Sun Microsystems - Beijing China
959d2a61391Spengcheng chen - Sun Microsystems - Beijing China return (DDI_SUCCESS);
960d2a61391Spengcheng chen - Sun Microsystems - Beijing China }
961d2a61391Spengcheng chen - Sun Microsystems - Beijing China
962c533a883Shx147065 static void
iwk_destroy_locks(iwk_sc_t * sc)963c533a883Shx147065 iwk_destroy_locks(iwk_sc_t *sc)
964c533a883Shx147065 {
965c533a883Shx147065 cv_destroy(&sc->sc_mt_cv);
966c533a883Shx147065 mutex_destroy(&sc->sc_mt_lock);
967c533a883Shx147065 cv_destroy(&sc->sc_tx_cv);
968c533a883Shx147065 cv_destroy(&sc->sc_cmd_cv);
969c533a883Shx147065 cv_destroy(&sc->sc_fw_cv);
970c533a883Shx147065 mutex_destroy(&sc->sc_tx_lock);
971c533a883Shx147065 mutex_destroy(&sc->sc_glock);
972c533a883Shx147065 }
973c533a883Shx147065
974c533a883Shx147065 /*
975c533a883Shx147065 * Allocate an area of memory and a DMA handle for accessing it
976c533a883Shx147065 */
977c533a883Shx147065 static int
iwk_alloc_dma_mem(iwk_sc_t * sc,size_t memsize,ddi_dma_attr_t * dma_attr_p,ddi_device_acc_attr_t * acc_attr_p,uint_t dma_flags,iwk_dma_t * dma_p)978c533a883Shx147065 iwk_alloc_dma_mem(iwk_sc_t *sc, size_t memsize,
979c533a883Shx147065 ddi_dma_attr_t *dma_attr_p, ddi_device_acc_attr_t *acc_attr_p,
980c533a883Shx147065 uint_t dma_flags, iwk_dma_t *dma_p)
981c533a883Shx147065 {
982c533a883Shx147065 caddr_t vaddr;
983c533a883Shx147065 int err;
984c533a883Shx147065
985c533a883Shx147065 /*
986c533a883Shx147065 * Allocate handle
987c533a883Shx147065 */
988c533a883Shx147065 err = ddi_dma_alloc_handle(sc->sc_dip, dma_attr_p,
989c533a883Shx147065 DDI_DMA_SLEEP, NULL, &dma_p->dma_hdl);
990c533a883Shx147065 if (err != DDI_SUCCESS) {
991c533a883Shx147065 dma_p->dma_hdl = NULL;
992c533a883Shx147065 return (DDI_FAILURE);
993c533a883Shx147065 }
994c533a883Shx147065
995c533a883Shx147065 /*
996c533a883Shx147065 * Allocate memory
997c533a883Shx147065 */
998c533a883Shx147065 err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, acc_attr_p,
999c533a883Shx147065 dma_flags & (DDI_DMA_CONSISTENT | DDI_DMA_STREAMING),
1000c533a883Shx147065 DDI_DMA_SLEEP, NULL, &vaddr, &dma_p->alength, &dma_p->acc_hdl);
1001c533a883Shx147065 if (err != DDI_SUCCESS) {
1002c533a883Shx147065 ddi_dma_free_handle(&dma_p->dma_hdl);
1003c533a883Shx147065 dma_p->dma_hdl = NULL;
1004c533a883Shx147065 dma_p->acc_hdl = NULL;
1005c533a883Shx147065 return (DDI_FAILURE);
1006c533a883Shx147065 }
1007c533a883Shx147065
1008c533a883Shx147065 /*
1009c533a883Shx147065 * Bind the two together
1010c533a883Shx147065 */
1011c533a883Shx147065 dma_p->mem_va = vaddr;
1012c533a883Shx147065 err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL,
1013c533a883Shx147065 vaddr, dma_p->alength, dma_flags, DDI_DMA_SLEEP, NULL,
1014c533a883Shx147065 &dma_p->cookie, &dma_p->ncookies);
1015c533a883Shx147065 if (err != DDI_DMA_MAPPED) {
1016c533a883Shx147065 ddi_dma_mem_free(&dma_p->acc_hdl);
1017c533a883Shx147065 ddi_dma_free_handle(&dma_p->dma_hdl);
1018c533a883Shx147065 dma_p->acc_hdl = NULL;
1019c533a883Shx147065 dma_p->dma_hdl = NULL;
1020c533a883Shx147065 return (DDI_FAILURE);
1021c533a883Shx147065 }
1022c533a883Shx147065
1023c533a883Shx147065 dma_p->nslots = ~0U;
1024c533a883Shx147065 dma_p->size = ~0U;
1025c533a883Shx147065 dma_p->token = ~0U;
1026c533a883Shx147065 dma_p->offset = 0;
1027c533a883Shx147065 return (DDI_SUCCESS);
1028c533a883Shx147065 }
1029c533a883Shx147065
1030c533a883Shx147065 /*
1031c533a883Shx147065 * Free one allocated area of DMAable memory
1032c533a883Shx147065 */
1033c533a883Shx147065 static void
iwk_free_dma_mem(iwk_dma_t * dma_p)1034c533a883Shx147065 iwk_free_dma_mem(iwk_dma_t *dma_p)
1035c533a883Shx147065 {
1036c533a883Shx147065 if (dma_p->dma_hdl != NULL) {
1037c533a883Shx147065 if (dma_p->ncookies) {
1038c533a883Shx147065 (void) ddi_dma_unbind_handle(dma_p->dma_hdl);
1039c533a883Shx147065 dma_p->ncookies = 0;
1040c533a883Shx147065 }
1041c533a883Shx147065 ddi_dma_free_handle(&dma_p->dma_hdl);
1042c533a883Shx147065 dma_p->dma_hdl = NULL;
1043c533a883Shx147065 }
1044c533a883Shx147065
1045c533a883Shx147065 if (dma_p->acc_hdl != NULL) {
1046c533a883Shx147065 ddi_dma_mem_free(&dma_p->acc_hdl);
1047c533a883Shx147065 dma_p->acc_hdl = NULL;
1048c533a883Shx147065 }
1049c533a883Shx147065 }
1050c533a883Shx147065
1051c533a883Shx147065 /*
1052c533a883Shx147065 *
1053c533a883Shx147065 */
1054c533a883Shx147065 static int
iwk_alloc_fw_dma(iwk_sc_t * sc)1055c533a883Shx147065 iwk_alloc_fw_dma(iwk_sc_t *sc)
1056c533a883Shx147065 {
1057c533a883Shx147065 int err = DDI_SUCCESS;
1058c533a883Shx147065 iwk_dma_t *dma_p;
1059c533a883Shx147065 char *t;
1060c533a883Shx147065
1061c533a883Shx147065 /*
1062c533a883Shx147065 * firmware image layout:
1063c533a883Shx147065 * |HDR|<-TEXT->|<-DATA->|<-INIT_TEXT->|<-INIT_DATA->|<-BOOT->|
1064c533a883Shx147065 */
1065c533a883Shx147065 t = (char *)(sc->sc_hdr + 1);
1066c533a883Shx147065 err = iwk_alloc_dma_mem(sc, LE_32(sc->sc_hdr->textsz),
1067c533a883Shx147065 &fw_dma_attr, &iwk_dma_accattr,
1068c533a883Shx147065 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1069c533a883Shx147065 &sc->sc_dma_fw_text);
1070c533a883Shx147065 dma_p = &sc->sc_dma_fw_text;
1071c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "text[ncookies:%d addr:%lx size:%lx]\n",
1072c533a883Shx147065 dma_p->ncookies, dma_p->cookie.dmac_address,
1073c533a883Shx147065 dma_p->cookie.dmac_size));
1074c533a883Shx147065 if (err != DDI_SUCCESS) {
1075c533a883Shx147065 cmn_err(CE_WARN, "iwk_alloc_fw_dma(): failed to alloc"
1076c533a883Shx147065 " text dma memory");
1077c533a883Shx147065 goto fail;
1078c533a883Shx147065 }
1079c533a883Shx147065 (void) memcpy(dma_p->mem_va, t, LE_32(sc->sc_hdr->textsz));
1080c533a883Shx147065
1081c533a883Shx147065 t += LE_32(sc->sc_hdr->textsz);
1082c533a883Shx147065 err = iwk_alloc_dma_mem(sc, LE_32(sc->sc_hdr->datasz),
1083c533a883Shx147065 &fw_dma_attr, &iwk_dma_accattr,
1084c533a883Shx147065 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1085c533a883Shx147065 &sc->sc_dma_fw_data);
1086c533a883Shx147065 dma_p = &sc->sc_dma_fw_data;
1087c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "data[ncookies:%d addr:%lx size:%lx]\n",
1088c533a883Shx147065 dma_p->ncookies, dma_p->cookie.dmac_address,
1089c533a883Shx147065 dma_p->cookie.dmac_size));
1090c533a883Shx147065 if (err != DDI_SUCCESS) {
1091c533a883Shx147065 cmn_err(CE_WARN, "iwk_alloc_fw_dma(): failed to alloc"
1092c533a883Shx147065 " data dma memory");
1093c533a883Shx147065 goto fail;
1094c533a883Shx147065 }
1095c533a883Shx147065 (void) memcpy(dma_p->mem_va, t, LE_32(sc->sc_hdr->datasz));
1096c533a883Shx147065
1097c533a883Shx147065 err = iwk_alloc_dma_mem(sc, LE_32(sc->sc_hdr->datasz),
1098c533a883Shx147065 &fw_dma_attr, &iwk_dma_accattr,
1099c533a883Shx147065 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1100c533a883Shx147065 &sc->sc_dma_fw_data_bak);
1101c533a883Shx147065 dma_p = &sc->sc_dma_fw_data_bak;
1102c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "data_bak[ncookies:%d addr:%lx "
1103c533a883Shx147065 "size:%lx]\n",
1104c533a883Shx147065 dma_p->ncookies, dma_p->cookie.dmac_address,
1105c533a883Shx147065 dma_p->cookie.dmac_size));
1106c533a883Shx147065 if (err != DDI_SUCCESS) {
1107c533a883Shx147065 cmn_err(CE_WARN, "iwk_alloc_fw_dma(): failed to alloc"
1108c533a883Shx147065 " data bakeup dma memory");
1109c533a883Shx147065 goto fail;
1110c533a883Shx147065 }
1111c533a883Shx147065 (void) memcpy(dma_p->mem_va, t, LE_32(sc->sc_hdr->datasz));
1112c533a883Shx147065
1113c533a883Shx147065 t += LE_32(sc->sc_hdr->datasz);
1114c533a883Shx147065 err = iwk_alloc_dma_mem(sc, LE_32(sc->sc_hdr->init_textsz),
1115c533a883Shx147065 &fw_dma_attr, &iwk_dma_accattr,
1116c533a883Shx147065 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1117c533a883Shx147065 &sc->sc_dma_fw_init_text);
1118c533a883Shx147065 dma_p = &sc->sc_dma_fw_init_text;
1119c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "init_text[ncookies:%d addr:%lx "
1120c533a883Shx147065 "size:%lx]\n",
1121c533a883Shx147065 dma_p->ncookies, dma_p->cookie.dmac_address,
1122c533a883Shx147065 dma_p->cookie.dmac_size));
1123c533a883Shx147065 if (err != DDI_SUCCESS) {
1124c533a883Shx147065 cmn_err(CE_WARN, "iwk_alloc_fw_dma(): failed to alloc"
1125c533a883Shx147065 "init text dma memory");
1126c533a883Shx147065 goto fail;
1127c533a883Shx147065 }
1128c533a883Shx147065 (void) memcpy(dma_p->mem_va, t, LE_32(sc->sc_hdr->init_textsz));
1129c533a883Shx147065
1130c533a883Shx147065 t += LE_32(sc->sc_hdr->init_textsz);
1131c533a883Shx147065 err = iwk_alloc_dma_mem(sc, LE_32(sc->sc_hdr->init_datasz),
1132c533a883Shx147065 &fw_dma_attr, &iwk_dma_accattr,
1133c533a883Shx147065 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1134c533a883Shx147065 &sc->sc_dma_fw_init_data);
1135c533a883Shx147065 dma_p = &sc->sc_dma_fw_init_data;
1136c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "init_data[ncookies:%d addr:%lx "
1137c533a883Shx147065 "size:%lx]\n",
1138c533a883Shx147065 dma_p->ncookies, dma_p->cookie.dmac_address,
1139c533a883Shx147065 dma_p->cookie.dmac_size));
1140c533a883Shx147065 if (err != DDI_SUCCESS) {
1141c533a883Shx147065 cmn_err(CE_WARN, "iwk_alloc_fw_dma(): failed to alloc"
1142c533a883Shx147065 "init data dma memory");
1143c533a883Shx147065 goto fail;
1144c533a883Shx147065 }
1145c533a883Shx147065 (void) memcpy(dma_p->mem_va, t, LE_32(sc->sc_hdr->init_datasz));
1146c533a883Shx147065
1147c533a883Shx147065 sc->sc_boot = t + LE_32(sc->sc_hdr->init_datasz);
1148c533a883Shx147065 fail:
1149c533a883Shx147065 return (err);
1150c533a883Shx147065 }
1151c533a883Shx147065
1152c533a883Shx147065 static void
iwk_free_fw_dma(iwk_sc_t * sc)1153c533a883Shx147065 iwk_free_fw_dma(iwk_sc_t *sc)
1154c533a883Shx147065 {
1155c533a883Shx147065 iwk_free_dma_mem(&sc->sc_dma_fw_text);
1156c533a883Shx147065 iwk_free_dma_mem(&sc->sc_dma_fw_data);
1157c533a883Shx147065 iwk_free_dma_mem(&sc->sc_dma_fw_data_bak);
1158c533a883Shx147065 iwk_free_dma_mem(&sc->sc_dma_fw_init_text);
1159c533a883Shx147065 iwk_free_dma_mem(&sc->sc_dma_fw_init_data);
1160c533a883Shx147065 }
1161c533a883Shx147065
1162c533a883Shx147065 /*
1163c533a883Shx147065 * Allocate a shared page between host and NIC.
1164c533a883Shx147065 */
1165c533a883Shx147065 static int
iwk_alloc_shared(iwk_sc_t * sc)1166c533a883Shx147065 iwk_alloc_shared(iwk_sc_t *sc)
1167c533a883Shx147065 {
1168c533a883Shx147065 iwk_dma_t *dma_p;
1169c533a883Shx147065 int err = DDI_SUCCESS;
1170c533a883Shx147065
1171c533a883Shx147065 /* must be aligned on a 4K-page boundary */
1172c533a883Shx147065 err = iwk_alloc_dma_mem(sc, sizeof (iwk_shared_t),
1173b510adaeSfei feng - Sun Microsystems - Beijing China &sh_dma_attr, &iwk_dma_descattr,
1174c533a883Shx147065 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1175c533a883Shx147065 &sc->sc_dma_sh);
1176c533a883Shx147065 if (err != DDI_SUCCESS)
1177c533a883Shx147065 goto fail;
1178c533a883Shx147065 sc->sc_shared = (iwk_shared_t *)sc->sc_dma_sh.mem_va;
1179c533a883Shx147065
1180c533a883Shx147065 dma_p = &sc->sc_dma_sh;
1181c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "sh[ncookies:%d addr:%lx size:%lx]\n",
1182c533a883Shx147065 dma_p->ncookies, dma_p->cookie.dmac_address,
1183c533a883Shx147065 dma_p->cookie.dmac_size));
1184c533a883Shx147065
1185c533a883Shx147065 return (err);
1186c533a883Shx147065 fail:
1187c533a883Shx147065 iwk_free_shared(sc);
1188c533a883Shx147065 return (err);
1189c533a883Shx147065 }
1190c533a883Shx147065
1191c533a883Shx147065 static void
iwk_free_shared(iwk_sc_t * sc)1192c533a883Shx147065 iwk_free_shared(iwk_sc_t *sc)
1193c533a883Shx147065 {
1194c533a883Shx147065 iwk_free_dma_mem(&sc->sc_dma_sh);
1195c533a883Shx147065 }
1196c533a883Shx147065
1197c533a883Shx147065 /*
1198c533a883Shx147065 * Allocate a keep warm page.
1199c533a883Shx147065 */
1200c533a883Shx147065 static int
iwk_alloc_kw(iwk_sc_t * sc)1201c533a883Shx147065 iwk_alloc_kw(iwk_sc_t *sc)
1202c533a883Shx147065 {
1203c533a883Shx147065 iwk_dma_t *dma_p;
1204c533a883Shx147065 int err = DDI_SUCCESS;
1205c533a883Shx147065
1206c533a883Shx147065 /* must be aligned on a 4K-page boundary */
1207c533a883Shx147065 err = iwk_alloc_dma_mem(sc, IWK_KW_SIZE,
1208c533a883Shx147065 &kw_dma_attr, &iwk_dma_accattr,
1209c533a883Shx147065 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1210c533a883Shx147065 &sc->sc_dma_kw);
1211c533a883Shx147065 if (err != DDI_SUCCESS)
1212c533a883Shx147065 goto fail;
1213c533a883Shx147065
1214c533a883Shx147065 dma_p = &sc->sc_dma_kw;
1215c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "kw[ncookies:%d addr:%lx size:%lx]\n",
1216c533a883Shx147065 dma_p->ncookies, dma_p->cookie.dmac_address,
1217c533a883Shx147065 dma_p->cookie.dmac_size));
1218c533a883Shx147065
1219c533a883Shx147065 return (err);
1220c533a883Shx147065 fail:
1221c533a883Shx147065 iwk_free_kw(sc);
1222c533a883Shx147065 return (err);
1223c533a883Shx147065 }
1224c533a883Shx147065
1225c533a883Shx147065 static void
iwk_free_kw(iwk_sc_t * sc)1226c533a883Shx147065 iwk_free_kw(iwk_sc_t *sc)
1227c533a883Shx147065 {
1228c533a883Shx147065 iwk_free_dma_mem(&sc->sc_dma_kw);
1229c533a883Shx147065 }
1230c533a883Shx147065
1231c533a883Shx147065 static int
iwk_alloc_rx_ring(iwk_sc_t * sc)1232c533a883Shx147065 iwk_alloc_rx_ring(iwk_sc_t *sc)
1233c533a883Shx147065 {
1234c533a883Shx147065 iwk_rx_ring_t *ring;
1235c533a883Shx147065 iwk_rx_data_t *data;
1236c533a883Shx147065 iwk_dma_t *dma_p;
1237c533a883Shx147065 int i, err = DDI_SUCCESS;
1238c533a883Shx147065
1239c533a883Shx147065 ring = &sc->sc_rxq;
1240c533a883Shx147065 ring->cur = 0;
1241c533a883Shx147065
1242c533a883Shx147065 err = iwk_alloc_dma_mem(sc, RX_QUEUE_SIZE * sizeof (uint32_t),
1243b510adaeSfei feng - Sun Microsystems - Beijing China &ring_desc_dma_attr, &iwk_dma_descattr,
1244c533a883Shx147065 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1245c533a883Shx147065 &ring->dma_desc);
1246c533a883Shx147065 if (err != DDI_SUCCESS) {
1247c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "dma alloc rx ring desc failed\n");
1248c533a883Shx147065 goto fail;
1249c533a883Shx147065 }
1250c533a883Shx147065 ring->desc = (uint32_t *)ring->dma_desc.mem_va;
1251c533a883Shx147065 dma_p = &ring->dma_desc;
1252c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "rx bd[ncookies:%d addr:%lx size:%lx]\n",
1253c533a883Shx147065 dma_p->ncookies, dma_p->cookie.dmac_address,
1254c533a883Shx147065 dma_p->cookie.dmac_size));
1255c533a883Shx147065
1256c533a883Shx147065 /*
1257c533a883Shx147065 * Allocate Rx buffers.
1258c533a883Shx147065 */
1259c533a883Shx147065 for (i = 0; i < RX_QUEUE_SIZE; i++) {
1260c533a883Shx147065 data = &ring->data[i];
1261c533a883Shx147065 err = iwk_alloc_dma_mem(sc, sc->sc_dmabuf_sz,
1262c533a883Shx147065 &rx_buffer_dma_attr, &iwk_dma_accattr,
1263c533a883Shx147065 DDI_DMA_READ | DDI_DMA_STREAMING,
1264c533a883Shx147065 &data->dma_data);
1265c533a883Shx147065 if (err != DDI_SUCCESS) {
1266c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "dma alloc rx ring buf[%d] "
1267c50ced99Spengcheng chen - Sun Microsystems - Beijing China "failed\n", i);
1268c533a883Shx147065 goto fail;
1269c533a883Shx147065 }
1270c533a883Shx147065 /*
1271c533a883Shx147065 * the physical address bit [8-36] are used,
1272c533a883Shx147065 * instead of bit [0-31] in 3945.
1273c533a883Shx147065 */
1274b510adaeSfei feng - Sun Microsystems - Beijing China ring->desc[i] = (uint32_t)
1275b510adaeSfei feng - Sun Microsystems - Beijing China (data->dma_data.cookie.dmac_address >> 8);
1276c533a883Shx147065 }
1277c533a883Shx147065 dma_p = &ring->data[0].dma_data;
1278c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "rx buffer[0][ncookies:%d addr:%lx "
1279c533a883Shx147065 "size:%lx]\n",
1280c533a883Shx147065 dma_p->ncookies, dma_p->cookie.dmac_address,
1281c533a883Shx147065 dma_p->cookie.dmac_size));
1282c533a883Shx147065
1283c533a883Shx147065 IWK_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV);
1284c533a883Shx147065
1285c533a883Shx147065 return (err);
1286c533a883Shx147065
1287c533a883Shx147065 fail:
1288c533a883Shx147065 iwk_free_rx_ring(sc);
1289c533a883Shx147065 return (err);
1290c533a883Shx147065 }
1291c533a883Shx147065
1292c533a883Shx147065 static void
iwk_reset_rx_ring(iwk_sc_t * sc)1293c533a883Shx147065 iwk_reset_rx_ring(iwk_sc_t *sc)
1294c533a883Shx147065 {
1295c533a883Shx147065 int n;
1296c533a883Shx147065
1297c533a883Shx147065 iwk_mac_access_enter(sc);
1298c533a883Shx147065 IWK_WRITE(sc, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
1299c533a883Shx147065 for (n = 0; n < 2000; n++) {
1300c533a883Shx147065 if (IWK_READ(sc, FH_MEM_RSSR_RX_STATUS_REG) & (1 << 24))
1301c533a883Shx147065 break;
1302c533a883Shx147065 DELAY(1000);
1303c533a883Shx147065 }
1304d2a61391Spengcheng chen - Sun Microsystems - Beijing China
1305c533a883Shx147065 if (n == 2000)
1306c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "timeout resetting Rx ring\n"));
1307d2a61391Spengcheng chen - Sun Microsystems - Beijing China
1308c533a883Shx147065 iwk_mac_access_exit(sc);
1309c533a883Shx147065
1310c533a883Shx147065 sc->sc_rxq.cur = 0;
1311c533a883Shx147065 }
1312c533a883Shx147065
1313c533a883Shx147065 static void
iwk_free_rx_ring(iwk_sc_t * sc)1314c533a883Shx147065 iwk_free_rx_ring(iwk_sc_t *sc)
1315c533a883Shx147065 {
1316c533a883Shx147065 int i;
1317c533a883Shx147065
1318c533a883Shx147065 for (i = 0; i < RX_QUEUE_SIZE; i++) {
1319c533a883Shx147065 if (sc->sc_rxq.data[i].dma_data.dma_hdl)
1320c533a883Shx147065 IWK_DMA_SYNC(sc->sc_rxq.data[i].dma_data,
1321c533a883Shx147065 DDI_DMA_SYNC_FORCPU);
1322c533a883Shx147065 iwk_free_dma_mem(&sc->sc_rxq.data[i].dma_data);
1323c533a883Shx147065 }
1324c533a883Shx147065
1325c533a883Shx147065 if (sc->sc_rxq.dma_desc.dma_hdl)
1326c533a883Shx147065 IWK_DMA_SYNC(sc->sc_rxq.dma_desc, DDI_DMA_SYNC_FORDEV);
1327c533a883Shx147065 iwk_free_dma_mem(&sc->sc_rxq.dma_desc);
1328c533a883Shx147065 }
1329c533a883Shx147065
1330c533a883Shx147065 static int
iwk_alloc_tx_ring(iwk_sc_t * sc,iwk_tx_ring_t * ring,int slots,int qid)1331c533a883Shx147065 iwk_alloc_tx_ring(iwk_sc_t *sc, iwk_tx_ring_t *ring,
1332c533a883Shx147065 int slots, int qid)
1333c533a883Shx147065 {
1334c533a883Shx147065 iwk_tx_data_t *data;
1335c533a883Shx147065 iwk_tx_desc_t *desc_h;
1336c533a883Shx147065 uint32_t paddr_desc_h;
1337c533a883Shx147065 iwk_cmd_t *cmd_h;
1338c533a883Shx147065 uint32_t paddr_cmd_h;
1339c533a883Shx147065 iwk_dma_t *dma_p;
1340c533a883Shx147065 int i, err = DDI_SUCCESS;
1341c533a883Shx147065
1342c533a883Shx147065 ring->qid = qid;
1343c533a883Shx147065 ring->count = TFD_QUEUE_SIZE_MAX;
1344c533a883Shx147065 ring->window = slots;
1345c533a883Shx147065 ring->queued = 0;
1346c533a883Shx147065 ring->cur = 0;
1347c533a883Shx147065
1348c533a883Shx147065 err = iwk_alloc_dma_mem(sc,
1349c533a883Shx147065 TFD_QUEUE_SIZE_MAX * sizeof (iwk_tx_desc_t),
1350b510adaeSfei feng - Sun Microsystems - Beijing China &ring_desc_dma_attr, &iwk_dma_descattr,
1351c533a883Shx147065 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1352c533a883Shx147065 &ring->dma_desc);
1353c533a883Shx147065 if (err != DDI_SUCCESS) {
1354c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "dma alloc tx ring desc[%d] "
1355c50ced99Spengcheng chen - Sun Microsystems - Beijing China "failed\n", qid);
1356c533a883Shx147065 goto fail;
1357c533a883Shx147065 }
1358c533a883Shx147065 dma_p = &ring->dma_desc;
1359c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "tx bd[ncookies:%d addr:%lx size:%lx]\n",
1360c533a883Shx147065 dma_p->ncookies, dma_p->cookie.dmac_address,
1361c533a883Shx147065 dma_p->cookie.dmac_size));
1362c533a883Shx147065
1363c533a883Shx147065 desc_h = (iwk_tx_desc_t *)ring->dma_desc.mem_va;
1364c533a883Shx147065 paddr_desc_h = ring->dma_desc.cookie.dmac_address;
1365c533a883Shx147065
1366c533a883Shx147065 err = iwk_alloc_dma_mem(sc,
1367c533a883Shx147065 TFD_QUEUE_SIZE_MAX * sizeof (iwk_cmd_t),
1368c533a883Shx147065 &cmd_dma_attr, &iwk_dma_accattr,
1369c533a883Shx147065 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1370c533a883Shx147065 &ring->dma_cmd);
1371c533a883Shx147065 if (err != DDI_SUCCESS) {
1372c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "dma alloc tx ring cmd[%d] "
1373c50ced99Spengcheng chen - Sun Microsystems - Beijing China "failed\n", qid);
1374c533a883Shx147065 goto fail;
1375c533a883Shx147065 }
1376c533a883Shx147065 dma_p = &ring->dma_cmd;
1377c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "tx cmd[ncookies:%d addr:%lx size:%lx]\n",
1378c533a883Shx147065 dma_p->ncookies, dma_p->cookie.dmac_address,
1379c533a883Shx147065 dma_p->cookie.dmac_size));
1380c533a883Shx147065
1381c533a883Shx147065 cmd_h = (iwk_cmd_t *)ring->dma_cmd.mem_va;
1382c533a883Shx147065 paddr_cmd_h = ring->dma_cmd.cookie.dmac_address;
1383c533a883Shx147065
1384c533a883Shx147065 /*
1385c533a883Shx147065 * Allocate Tx buffers.
1386c533a883Shx147065 */
1387c533a883Shx147065 ring->data = kmem_zalloc(sizeof (iwk_tx_data_t) * TFD_QUEUE_SIZE_MAX,
1388c533a883Shx147065 KM_NOSLEEP);
1389c533a883Shx147065 if (ring->data == NULL) {
1390c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "could not allocate tx data slots\n");
1391c533a883Shx147065 goto fail;
1392c533a883Shx147065 }
1393c533a883Shx147065
1394c533a883Shx147065 for (i = 0; i < TFD_QUEUE_SIZE_MAX; i++) {
1395c533a883Shx147065 data = &ring->data[i];
1396c533a883Shx147065 err = iwk_alloc_dma_mem(sc, sc->sc_dmabuf_sz,
1397c533a883Shx147065 &tx_buffer_dma_attr, &iwk_dma_accattr,
1398c533a883Shx147065 DDI_DMA_WRITE | DDI_DMA_STREAMING,
1399c533a883Shx147065 &data->dma_data);
1400c533a883Shx147065 if (err != DDI_SUCCESS) {
1401c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "dma alloc tx ring "
1402c50ced99Spengcheng chen - Sun Microsystems - Beijing China "buf[%d] failed\n", i);
1403c533a883Shx147065 goto fail;
1404c533a883Shx147065 }
1405c533a883Shx147065
1406c533a883Shx147065 data->desc = desc_h + i;
1407c533a883Shx147065 data->paddr_desc = paddr_desc_h +
1408ff3124efSff224033 _PTRDIFF(data->desc, desc_h);
1409c533a883Shx147065 data->cmd = cmd_h + i; /* (i % slots); */
1410cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* ((i % slots) * sizeof (iwk_cmd_t)); */
1411c533a883Shx147065 data->paddr_cmd = paddr_cmd_h +
1412ff3124efSff224033 _PTRDIFF(data->cmd, cmd_h);
1413c533a883Shx147065 }
1414c533a883Shx147065 dma_p = &ring->data[0].dma_data;
1415c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "tx buffer[0][ncookies:%d addr:%lx "
1416c533a883Shx147065 "size:%lx]\n",
1417c533a883Shx147065 dma_p->ncookies, dma_p->cookie.dmac_address,
1418c533a883Shx147065 dma_p->cookie.dmac_size));
1419c533a883Shx147065
1420c533a883Shx147065 return (err);
1421c533a883Shx147065
1422c533a883Shx147065 fail:
1423c533a883Shx147065 if (ring->data)
1424c533a883Shx147065 kmem_free(ring->data,
1425c533a883Shx147065 sizeof (iwk_tx_data_t) * TFD_QUEUE_SIZE_MAX);
1426c533a883Shx147065 iwk_free_tx_ring(sc, ring);
1427c533a883Shx147065 return (err);
1428c533a883Shx147065 }
1429c533a883Shx147065
1430c533a883Shx147065 static void
iwk_reset_tx_ring(iwk_sc_t * sc,iwk_tx_ring_t * ring)1431c533a883Shx147065 iwk_reset_tx_ring(iwk_sc_t *sc, iwk_tx_ring_t *ring)
1432c533a883Shx147065 {
1433c533a883Shx147065 iwk_tx_data_t *data;
1434c533a883Shx147065 int i, n;
1435c533a883Shx147065
1436c533a883Shx147065 iwk_mac_access_enter(sc);
1437c533a883Shx147065
1438c533a883Shx147065 IWK_WRITE(sc, IWK_FH_TCSR_CHNL_TX_CONFIG_REG(ring->qid), 0);
1439c533a883Shx147065 for (n = 0; n < 200; n++) {
1440c533a883Shx147065 if (IWK_READ(sc, IWK_FH_TSSR_TX_STATUS_REG) &
1441c533a883Shx147065 IWK_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ring->qid))
1442c533a883Shx147065 break;
1443c533a883Shx147065 DELAY(10);
1444c533a883Shx147065 }
1445c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (n == 200) {
1446c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "timeout reset tx ring %d\n",
1447c533a883Shx147065 ring->qid));
1448c533a883Shx147065 }
1449c533a883Shx147065 iwk_mac_access_exit(sc);
1450c533a883Shx147065
1451c533a883Shx147065 for (i = 0; i < ring->count; i++) {
1452c533a883Shx147065 data = &ring->data[i];
1453c533a883Shx147065 IWK_DMA_SYNC(data->dma_data, DDI_DMA_SYNC_FORDEV);
1454c533a883Shx147065 }
1455c533a883Shx147065
1456c533a883Shx147065 ring->queued = 0;
1457c533a883Shx147065 ring->cur = 0;
1458c533a883Shx147065 }
1459c533a883Shx147065
1460c533a883Shx147065 /*ARGSUSED*/
1461c533a883Shx147065 static void
iwk_free_tx_ring(iwk_sc_t * sc,iwk_tx_ring_t * ring)1462c533a883Shx147065 iwk_free_tx_ring(iwk_sc_t *sc, iwk_tx_ring_t *ring)
1463c533a883Shx147065 {
1464c533a883Shx147065 int i;
1465c533a883Shx147065
1466c533a883Shx147065 if (ring->dma_desc.dma_hdl != NULL)
1467c533a883Shx147065 IWK_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV);
1468c533a883Shx147065 iwk_free_dma_mem(&ring->dma_desc);
1469c533a883Shx147065
1470c533a883Shx147065 if (ring->dma_cmd.dma_hdl != NULL)
1471c533a883Shx147065 IWK_DMA_SYNC(ring->dma_cmd, DDI_DMA_SYNC_FORDEV);
1472c533a883Shx147065 iwk_free_dma_mem(&ring->dma_cmd);
1473c533a883Shx147065
1474c533a883Shx147065 if (ring->data != NULL) {
1475c533a883Shx147065 for (i = 0; i < ring->count; i++) {
1476c533a883Shx147065 if (ring->data[i].dma_data.dma_hdl)
1477c533a883Shx147065 IWK_DMA_SYNC(ring->data[i].dma_data,
1478c533a883Shx147065 DDI_DMA_SYNC_FORDEV);
1479c533a883Shx147065 iwk_free_dma_mem(&ring->data[i].dma_data);
1480c533a883Shx147065 }
1481c533a883Shx147065 kmem_free(ring->data, ring->count * sizeof (iwk_tx_data_t));
1482c533a883Shx147065 }
1483c533a883Shx147065 }
1484c533a883Shx147065
1485c533a883Shx147065 static int
iwk_ring_init(iwk_sc_t * sc)1486c533a883Shx147065 iwk_ring_init(iwk_sc_t *sc)
1487c533a883Shx147065 {
1488c533a883Shx147065 int i, err = DDI_SUCCESS;
1489c533a883Shx147065
1490c533a883Shx147065 for (i = 0; i < IWK_NUM_QUEUES; i++) {
1491c533a883Shx147065 if (i == IWK_CMD_QUEUE_NUM)
1492c533a883Shx147065 continue;
1493c533a883Shx147065 err = iwk_alloc_tx_ring(sc, &sc->sc_txq[i], TFD_TX_CMD_SLOTS,
1494c533a883Shx147065 i);
1495c533a883Shx147065 if (err != DDI_SUCCESS)
1496c533a883Shx147065 goto fail;
1497c533a883Shx147065 }
1498c533a883Shx147065 err = iwk_alloc_tx_ring(sc, &sc->sc_txq[IWK_CMD_QUEUE_NUM],
1499c533a883Shx147065 TFD_CMD_SLOTS, IWK_CMD_QUEUE_NUM);
1500c533a883Shx147065 if (err != DDI_SUCCESS)
1501c533a883Shx147065 goto fail;
1502c533a883Shx147065 err = iwk_alloc_rx_ring(sc);
1503c533a883Shx147065 if (err != DDI_SUCCESS)
1504c533a883Shx147065 goto fail;
1505c533a883Shx147065 return (err);
1506c533a883Shx147065
1507c533a883Shx147065 fail:
1508c533a883Shx147065 return (err);
1509c533a883Shx147065 }
1510c533a883Shx147065
1511c533a883Shx147065 static void
iwk_ring_free(iwk_sc_t * sc)1512c533a883Shx147065 iwk_ring_free(iwk_sc_t *sc)
1513c533a883Shx147065 {
1514c533a883Shx147065 int i = IWK_NUM_QUEUES;
1515c533a883Shx147065
1516c533a883Shx147065 iwk_free_rx_ring(sc);
1517c533a883Shx147065 while (--i >= 0) {
1518c533a883Shx147065 iwk_free_tx_ring(sc, &sc->sc_txq[i]);
1519c533a883Shx147065 }
1520c533a883Shx147065 }
1521c533a883Shx147065
1522c533a883Shx147065 /* ARGSUSED */
152343439c96Shx147065 static ieee80211_node_t *
iwk_node_alloc(ieee80211com_t * ic)152443439c96Shx147065 iwk_node_alloc(ieee80211com_t *ic)
152543439c96Shx147065 {
152643439c96Shx147065 iwk_amrr_t *amrr;
152743439c96Shx147065
152843439c96Shx147065 amrr = kmem_zalloc(sizeof (iwk_amrr_t), KM_SLEEP);
152943439c96Shx147065 if (amrr != NULL)
153043439c96Shx147065 iwk_amrr_init(amrr);
153143439c96Shx147065 return (&amrr->in);
153243439c96Shx147065 }
153343439c96Shx147065
153443439c96Shx147065 static void
iwk_node_free(ieee80211_node_t * in)153543439c96Shx147065 iwk_node_free(ieee80211_node_t *in)
153643439c96Shx147065 {
153743439c96Shx147065 ieee80211com_t *ic = in->in_ic;
153843439c96Shx147065
153943439c96Shx147065 ic->ic_node_cleanup(in);
154043439c96Shx147065 if (in->in_wpa_ie != NULL)
154143439c96Shx147065 ieee80211_free(in->in_wpa_ie);
154243439c96Shx147065 kmem_free(in, sizeof (iwk_amrr_t));
154343439c96Shx147065 }
154443439c96Shx147065
154543439c96Shx147065 /*ARGSUSED*/
1546c533a883Shx147065 static int
iwk_newstate(ieee80211com_t * ic,enum ieee80211_state nstate,int arg)1547c533a883Shx147065 iwk_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg)
1548c533a883Shx147065 {
1549c533a883Shx147065 iwk_sc_t *sc = (iwk_sc_t *)ic;
155043439c96Shx147065 ieee80211_node_t *in = ic->ic_bss;
1551c533a883Shx147065 enum ieee80211_state ostate = ic->ic_state;
1552c533a883Shx147065 int i, err = IWK_SUCCESS;
1553c533a883Shx147065
1554c533a883Shx147065 mutex_enter(&sc->sc_glock);
1555c533a883Shx147065 switch (nstate) {
1556c533a883Shx147065 case IEEE80211_S_SCAN:
1557c50ced99Spengcheng chen - Sun Microsystems - Beijing China switch (ostate) {
1558c50ced99Spengcheng chen - Sun Microsystems - Beijing China case IEEE80211_S_INIT:
1559c50ced99Spengcheng chen - Sun Microsystems - Beijing China {
1560c50ced99Spengcheng chen - Sun Microsystems - Beijing China iwk_add_sta_t node;
1561c50ced99Spengcheng chen - Sun Microsystems - Beijing China
1562c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_flags |= IWK_F_SCANNING;
1563f3c4902cSpengcheng chen - Sun Microsystems - Beijing China sc->sc_scan_pending = 0;
1564c533a883Shx147065 iwk_set_led(sc, 2, 10, 2);
1565c533a883Shx147065
1566c50ced99Spengcheng chen - Sun Microsystems - Beijing China /*
1567c50ced99Spengcheng chen - Sun Microsystems - Beijing China * clear association to receive beacons from
1568c50ced99Spengcheng chen - Sun Microsystems - Beijing China * all BSS'es
1569c50ced99Spengcheng chen - Sun Microsystems - Beijing China */
1570c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_config.assoc_id = 0;
1571c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_config.filter_flags &=
1572c50ced99Spengcheng chen - Sun Microsystems - Beijing China ~LE_32(RXON_FILTER_ASSOC_MSK);
1573c50ced99Spengcheng chen - Sun Microsystems - Beijing China
1574c50ced99Spengcheng chen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_80211, "config chan %d "
1575c50ced99Spengcheng chen - Sun Microsystems - Beijing China "flags %x filter_flags %x\n", sc->sc_config.chan,
1576c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_config.flags, sc->sc_config.filter_flags));
1577c50ced99Spengcheng chen - Sun Microsystems - Beijing China
1578c50ced99Spengcheng chen - Sun Microsystems - Beijing China err = iwk_cmd(sc, REPLY_RXON, &sc->sc_config,
1579c50ced99Spengcheng chen - Sun Microsystems - Beijing China sizeof (iwk_rxon_cmd_t), 1);
1580c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) {
1581c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN,
1582c50ced99Spengcheng chen - Sun Microsystems - Beijing China "could not clear association\n");
1583c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~IWK_F_SCANNING;
1584c533a883Shx147065 mutex_exit(&sc->sc_glock);
1585c533a883Shx147065 return (err);
1586c533a883Shx147065 }
1587c50ced99Spengcheng chen - Sun Microsystems - Beijing China
1588c50ced99Spengcheng chen - Sun Microsystems - Beijing China /* add broadcast node to send probe request */
1589c50ced99Spengcheng chen - Sun Microsystems - Beijing China (void) memset(&node, 0, sizeof (node));
1590c50ced99Spengcheng chen - Sun Microsystems - Beijing China (void) memset(&node.bssid, 0xff, IEEE80211_ADDR_LEN);
1591c50ced99Spengcheng chen - Sun Microsystems - Beijing China node.id = IWK_BROADCAST_ID;
1592c50ced99Spengcheng chen - Sun Microsystems - Beijing China err = iwk_cmd(sc, REPLY_ADD_STA, &node,
1593c50ced99Spengcheng chen - Sun Microsystems - Beijing China sizeof (node), 1);
1594c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) {
1595c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "could not add "
1596c50ced99Spengcheng chen - Sun Microsystems - Beijing China "broadcast node\n");
1597c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~IWK_F_SCANNING;
1598c50ced99Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock);
1599c50ced99Spengcheng chen - Sun Microsystems - Beijing China return (err);
1600c50ced99Spengcheng chen - Sun Microsystems - Beijing China }
1601c50ced99Spengcheng chen - Sun Microsystems - Beijing China break;
1602c50ced99Spengcheng chen - Sun Microsystems - Beijing China }
1603f3c4902cSpengcheng chen - Sun Microsystems - Beijing China
1604f3c4902cSpengcheng chen - Sun Microsystems - Beijing China case IEEE80211_S_AUTH:
1605f3c4902cSpengcheng chen - Sun Microsystems - Beijing China case IEEE80211_S_ASSOC:
1606f3c4902cSpengcheng chen - Sun Microsystems - Beijing China case IEEE80211_S_RUN:
1607f3c4902cSpengcheng chen - Sun Microsystems - Beijing China sc->sc_flags |= IWK_F_SCANNING;
1608f3c4902cSpengcheng chen - Sun Microsystems - Beijing China sc->sc_scan_pending = 0;
1609f3c4902cSpengcheng chen - Sun Microsystems - Beijing China
1610f3c4902cSpengcheng chen - Sun Microsystems - Beijing China iwk_set_led(sc, 2, 10, 2);
1611f3c4902cSpengcheng chen - Sun Microsystems - Beijing China /* FALLTHRU */
1612c50ced99Spengcheng chen - Sun Microsystems - Beijing China case IEEE80211_S_SCAN:
1613c50ced99Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock);
1614c50ced99Spengcheng chen - Sun Microsystems - Beijing China /* step to next channel before actual FW scan */
1615c50ced99Spengcheng chen - Sun Microsystems - Beijing China err = sc->sc_newstate(ic, nstate, arg);
1616c50ced99Spengcheng chen - Sun Microsystems - Beijing China mutex_enter(&sc->sc_glock);
1617c50ced99Spengcheng chen - Sun Microsystems - Beijing China if ((err != 0) || ((err = iwk_scan(sc)) != 0)) {
1618c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN,
1619c50ced99Spengcheng chen - Sun Microsystems - Beijing China "could not initiate scan\n");
1620c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~IWK_F_SCANNING;
1621c50ced99Spengcheng chen - Sun Microsystems - Beijing China ieee80211_cancel_scan(ic);
1622c50ced99Spengcheng chen - Sun Microsystems - Beijing China }
1623c50ced99Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock);
1624c50ced99Spengcheng chen - Sun Microsystems - Beijing China return (err);
1625c50ced99Spengcheng chen - Sun Microsystems - Beijing China default:
1626c50ced99Spengcheng chen - Sun Microsystems - Beijing China break;
1627c50ced99Spengcheng chen - Sun Microsystems - Beijing China
1628c533a883Shx147065 }
162943439c96Shx147065 sc->sc_clk = 0;
1630c50ced99Spengcheng chen - Sun Microsystems - Beijing China break;
1631c533a883Shx147065
1632c533a883Shx147065 case IEEE80211_S_AUTH:
1633c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (ostate == IEEE80211_S_SCAN) {
1634c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~IWK_F_SCANNING;
1635c50ced99Spengcheng chen - Sun Microsystems - Beijing China }
1636c50ced99Spengcheng chen - Sun Microsystems - Beijing China
1637c533a883Shx147065 /* reset state to handle reassociations correctly */
1638c533a883Shx147065 sc->sc_config.assoc_id = 0;
1639c533a883Shx147065 sc->sc_config.filter_flags &= ~LE_32(RXON_FILTER_ASSOC_MSK);
1640c533a883Shx147065
1641c533a883Shx147065 /*
1642c533a883Shx147065 * before sending authentication and association request frame,
1643c533a883Shx147065 * we need do something in the hardware, such as setting the
1644c533a883Shx147065 * channel same to the target AP...
1645c533a883Shx147065 */
1646c533a883Shx147065 if ((err = iwk_hw_set_before_auth(sc)) != 0) {
1647c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "could not setup firmware for "
1648c50ced99Spengcheng chen - Sun Microsystems - Beijing China "authentication\n");
1649c533a883Shx147065 mutex_exit(&sc->sc_glock);
1650c533a883Shx147065 return (err);
1651c533a883Shx147065 }
1652c533a883Shx147065 break;
1653c533a883Shx147065
1654c533a883Shx147065 case IEEE80211_S_RUN:
1655c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (ostate == IEEE80211_S_SCAN) {
1656c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~IWK_F_SCANNING;
1657c50ced99Spengcheng chen - Sun Microsystems - Beijing China }
1658c50ced99Spengcheng chen - Sun Microsystems - Beijing China
1659c533a883Shx147065 if (ic->ic_opmode == IEEE80211_M_MONITOR) {
1660c533a883Shx147065 /* let LED blink when monitoring */
1661c533a883Shx147065 iwk_set_led(sc, 2, 10, 10);
1662c533a883Shx147065 break;
1663c533a883Shx147065 }
1664c533a883Shx147065 IWK_DBG((IWK_DEBUG_80211, "iwk: associated."));
1665c533a883Shx147065
166619d332feSfei feng - Sun Microsystems - Beijing China /* IBSS mode */
166719d332feSfei feng - Sun Microsystems - Beijing China if (ic->ic_opmode == IEEE80211_M_IBSS) {
166819d332feSfei feng - Sun Microsystems - Beijing China /*
166919d332feSfei feng - Sun Microsystems - Beijing China * clean all nodes in ibss node table
167019d332feSfei feng - Sun Microsystems - Beijing China * in order to be consistent with hardware
167119d332feSfei feng - Sun Microsystems - Beijing China */
167219d332feSfei feng - Sun Microsystems - Beijing China err = iwk_run_state_config_ibss(ic);
167319d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) {
167419d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_newstate(): "
167519d332feSfei feng - Sun Microsystems - Beijing China "failed to update configuration "
167619d332feSfei feng - Sun Microsystems - Beijing China "in IBSS mode\n");
167719d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock);
167819d332feSfei feng - Sun Microsystems - Beijing China return (err);
167919d332feSfei feng - Sun Microsystems - Beijing China }
168019d332feSfei feng - Sun Microsystems - Beijing China }
168119d332feSfei feng - Sun Microsystems - Beijing China
1682cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* none IBSS mode */
1683cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (ic->ic_opmode != IEEE80211_M_IBSS) {
1684c533a883Shx147065 /* update adapter's configuration */
168519d332feSfei feng - Sun Microsystems - Beijing China err = iwk_run_state_config_sta(ic);
1686c533a883Shx147065 if (err != IWK_SUCCESS) {
168719d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_newstate(): "
168819d332feSfei feng - Sun Microsystems - Beijing China "failed to update configuration "
168919d332feSfei feng - Sun Microsystems - Beijing China "in none IBSS mode\n");
1690c533a883Shx147065 mutex_exit(&sc->sc_glock);
1691c533a883Shx147065 return (err);
1692c533a883Shx147065 }
1693cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
1694cdc64593Sxinghua wen - Sun Microsystems - Beijing China
1695cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* obtain current temperature of chipset */
1696cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_tempera = iwk_curr_tempera(sc);
1697c533a883Shx147065
1698c533a883Shx147065 /*
1699cdc64593Sxinghua wen - Sun Microsystems - Beijing China * make Tx power calibration to determine
1700cdc64593Sxinghua wen - Sun Microsystems - Beijing China * the gains of DSP and radio
1701c533a883Shx147065 */
1702cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = iwk_tx_power_calibration(sc);
1703cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (err) {
1704cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_newstate(): "
1705cdc64593Sxinghua wen - Sun Microsystems - Beijing China "failed to set tx power table\n");
170619d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock);
1707c533a883Shx147065 return (err);
1708c533a883Shx147065 }
1709c533a883Shx147065
171019d332feSfei feng - Sun Microsystems - Beijing China if (ic->ic_opmode == IEEE80211_M_IBSS) {
171119d332feSfei feng - Sun Microsystems - Beijing China
171219d332feSfei feng - Sun Microsystems - Beijing China /*
171319d332feSfei feng - Sun Microsystems - Beijing China * allocate and transmit beacon frames
171419d332feSfei feng - Sun Microsystems - Beijing China */
171519d332feSfei feng - Sun Microsystems - Beijing China err = iwk_start_tx_beacon(ic);
171619d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) {
171719d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_newstate(): "
171819d332feSfei feng - Sun Microsystems - Beijing China "can't transmit beacon frames\n");
171919d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock);
172019d332feSfei feng - Sun Microsystems - Beijing China return (err);
172119d332feSfei feng - Sun Microsystems - Beijing China }
172219d332feSfei feng - Sun Microsystems - Beijing China }
172319d332feSfei feng - Sun Microsystems - Beijing China
172443439c96Shx147065 /* start automatic rate control */
172543439c96Shx147065 mutex_enter(&sc->sc_mt_lock);
172643439c96Shx147065 if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) {
172743439c96Shx147065 sc->sc_flags |= IWK_F_RATE_AUTO_CTL;
172843439c96Shx147065 /* set rate to some reasonable initial value */
172943439c96Shx147065 i = in->in_rates.ir_nrates - 1;
173043439c96Shx147065 while (i > 0 && IEEE80211_RATE(i) > 72)
173143439c96Shx147065 i--;
173243439c96Shx147065 in->in_txrate = i;
173343439c96Shx147065 } else {
173443439c96Shx147065 sc->sc_flags &= ~IWK_F_RATE_AUTO_CTL;
173543439c96Shx147065 }
173643439c96Shx147065 mutex_exit(&sc->sc_mt_lock);
173743439c96Shx147065
1738c533a883Shx147065 /* set LED on after associated */
1739c533a883Shx147065 iwk_set_led(sc, 2, 0, 1);
1740c533a883Shx147065 break;
1741c533a883Shx147065
1742c533a883Shx147065 case IEEE80211_S_INIT:
1743c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (ostate == IEEE80211_S_SCAN) {
1744c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~IWK_F_SCANNING;
1745c50ced99Spengcheng chen - Sun Microsystems - Beijing China }
1746c50ced99Spengcheng chen - Sun Microsystems - Beijing China
1747c533a883Shx147065 /* set LED off after init */
1748c533a883Shx147065 iwk_set_led(sc, 2, 1, 0);
1749c533a883Shx147065 break;
1750c533a883Shx147065 case IEEE80211_S_ASSOC:
1751c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (ostate == IEEE80211_S_SCAN) {
1752c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~IWK_F_SCANNING;
1753c50ced99Spengcheng chen - Sun Microsystems - Beijing China }
1754c50ced99Spengcheng chen - Sun Microsystems - Beijing China
1755c533a883Shx147065 break;
1756c533a883Shx147065 }
1757c533a883Shx147065
1758c533a883Shx147065 mutex_exit(&sc->sc_glock);
1759cdc64593Sxinghua wen - Sun Microsystems - Beijing China
1760cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = sc->sc_newstate(ic, nstate, arg);
1761cdc64593Sxinghua wen - Sun Microsystems - Beijing China
1762cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (nstate == IEEE80211_S_RUN) {
1763cdc64593Sxinghua wen - Sun Microsystems - Beijing China
1764cdc64593Sxinghua wen - Sun Microsystems - Beijing China mutex_enter(&sc->sc_glock);
1765cdc64593Sxinghua wen - Sun Microsystems - Beijing China
1766cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
1767cdc64593Sxinghua wen - Sun Microsystems - Beijing China * make initialization for Receiver
1768cdc64593Sxinghua wen - Sun Microsystems - Beijing China * sensitivity calibration
1769cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
1770cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = iwk_rx_sens_init(sc);
1771cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (err) {
1772cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_newstate(): "
1773cdc64593Sxinghua wen - Sun Microsystems - Beijing China "failed to init RX sensitivity\n");
1774c50ced99Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock);
1775cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (err);
1776cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
1777cdc64593Sxinghua wen - Sun Microsystems - Beijing China
1778cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* make initialization for Receiver gain balance */
1779cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = iwk_rxgain_diff_init(sc);
1780cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (err) {
1781cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_newstate(): "
1782cdc64593Sxinghua wen - Sun Microsystems - Beijing China "failed to init phy calibration\n");
1783c50ced99Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock);
1784cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (err);
1785cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
1786cdc64593Sxinghua wen - Sun Microsystems - Beijing China
1787cdc64593Sxinghua wen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock);
1788cdc64593Sxinghua wen - Sun Microsystems - Beijing China
1789cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
1790cdc64593Sxinghua wen - Sun Microsystems - Beijing China
1791cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (err);
1792c533a883Shx147065 }
1793c533a883Shx147065
1794f3c4902cSpengcheng chen - Sun Microsystems - Beijing China static void
iwk_watchdog(void * arg)1795f3c4902cSpengcheng chen - Sun Microsystems - Beijing China iwk_watchdog(void *arg)
1796f3c4902cSpengcheng chen - Sun Microsystems - Beijing China {
1797f3c4902cSpengcheng chen - Sun Microsystems - Beijing China iwk_sc_t *sc = arg;
1798f3c4902cSpengcheng chen - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic;
1799f3c4902cSpengcheng chen - Sun Microsystems - Beijing China #ifdef DEBUG
1800f3c4902cSpengcheng chen - Sun Microsystems - Beijing China timeout_id_t timeout_id = ic->ic_watchdog_timer;
1801f3c4902cSpengcheng chen - Sun Microsystems - Beijing China #endif
1802f3c4902cSpengcheng chen - Sun Microsystems - Beijing China
1803f3c4902cSpengcheng chen - Sun Microsystems - Beijing China ieee80211_stop_watchdog(ic);
1804f3c4902cSpengcheng chen - Sun Microsystems - Beijing China
1805f3c4902cSpengcheng chen - Sun Microsystems - Beijing China if ((ic->ic_state != IEEE80211_S_AUTH) &&
1806f3c4902cSpengcheng chen - Sun Microsystems - Beijing China (ic->ic_state != IEEE80211_S_ASSOC))
1807f3c4902cSpengcheng chen - Sun Microsystems - Beijing China return;
1808f3c4902cSpengcheng chen - Sun Microsystems - Beijing China
1809f3c4902cSpengcheng chen - Sun Microsystems - Beijing China if (ic->ic_bss->in_fails > 0) {
1810f3c4902cSpengcheng chen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_80211, "watchdog (0x%x) reset: "
1811f3c4902cSpengcheng chen - Sun Microsystems - Beijing China "node (0x%x)\n", timeout_id, &ic->ic_bss));
1812f3c4902cSpengcheng chen - Sun Microsystems - Beijing China ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
1813f3c4902cSpengcheng chen - Sun Microsystems - Beijing China } else {
1814f3c4902cSpengcheng chen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_80211, "watchdog (0x%x) timeout: "
1815f3c4902cSpengcheng chen - Sun Microsystems - Beijing China "node (0x%x), retry (%d)\n",
1816f3c4902cSpengcheng chen - Sun Microsystems - Beijing China timeout_id, &ic->ic_bss, ic->ic_bss->in_fails + 1));
1817f3c4902cSpengcheng chen - Sun Microsystems - Beijing China ieee80211_watchdog(ic);
1818f3c4902cSpengcheng chen - Sun Microsystems - Beijing China }
1819f3c4902cSpengcheng chen - Sun Microsystems - Beijing China }
1820f3c4902cSpengcheng chen - Sun Microsystems - Beijing China
1821c533a883Shx147065 /*ARGSUSED*/
iwk_key_set(ieee80211com_t * ic,const struct ieee80211_key * k,const uint8_t mac[IEEE80211_ADDR_LEN])1822c533a883Shx147065 static int iwk_key_set(ieee80211com_t *ic, const struct ieee80211_key *k,
1823c533a883Shx147065 const uint8_t mac[IEEE80211_ADDR_LEN])
1824c533a883Shx147065 {
1825c533a883Shx147065 iwk_sc_t *sc = (iwk_sc_t *)ic;
1826c533a883Shx147065 iwk_add_sta_t node;
1827c533a883Shx147065 int err;
182819d332feSfei feng - Sun Microsystems - Beijing China uint8_t index1;
1829c533a883Shx147065
1830c533a883Shx147065 switch (k->wk_cipher->ic_cipher) {
1831c533a883Shx147065 case IEEE80211_CIPHER_WEP:
1832c533a883Shx147065 case IEEE80211_CIPHER_TKIP:
1833c533a883Shx147065 return (1); /* sofeware do it. */
1834c533a883Shx147065 case IEEE80211_CIPHER_AES_CCM:
1835c533a883Shx147065 break;
1836c533a883Shx147065 default:
1837c533a883Shx147065 return (0);
1838c533a883Shx147065 }
1839b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.filter_flags &= ~LE_32(RXON_FILTER_DIS_DECRYPT_MSK |
1840cdc64593Sxinghua wen - Sun Microsystems - Beijing China RXON_FILTER_DIS_GRP_DECRYPT_MSK);
1841c533a883Shx147065
1842c533a883Shx147065 mutex_enter(&sc->sc_glock);
1843c533a883Shx147065
1844c533a883Shx147065 /* update ap/multicast node */
1845c533a883Shx147065 (void) memset(&node, 0, sizeof (node));
1846c533a883Shx147065 if (IEEE80211_IS_MULTICAST(mac)) {
1847c533a883Shx147065 (void) memset(node.bssid, 0xff, 6);
1848c533a883Shx147065 node.id = IWK_BROADCAST_ID;
184919d332feSfei feng - Sun Microsystems - Beijing China } else if (ic->ic_opmode == IEEE80211_M_IBSS) {
185019d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock);
185119d332feSfei feng - Sun Microsystems - Beijing China mutex_enter(&sc->sc_ibss.node_tb_lock);
185219d332feSfei feng - Sun Microsystems - Beijing China
185319d332feSfei feng - Sun Microsystems - Beijing China /*
185419d332feSfei feng - Sun Microsystems - Beijing China * search for node in ibss node table
185519d332feSfei feng - Sun Microsystems - Beijing China */
185619d332feSfei feng - Sun Microsystems - Beijing China for (index1 = IWK_STA_ID; index1 < IWK_STATION_COUNT;
185719d332feSfei feng - Sun Microsystems - Beijing China index1++) {
185819d332feSfei feng - Sun Microsystems - Beijing China if (sc->sc_ibss.ibss_node_tb[index1].used &&
185919d332feSfei feng - Sun Microsystems - Beijing China IEEE80211_ADDR_EQ(sc->sc_ibss.
186019d332feSfei feng - Sun Microsystems - Beijing China ibss_node_tb[index1].node.bssid,
186119d332feSfei feng - Sun Microsystems - Beijing China mac)) {
186219d332feSfei feng - Sun Microsystems - Beijing China break;
186319d332feSfei feng - Sun Microsystems - Beijing China }
186419d332feSfei feng - Sun Microsystems - Beijing China }
186519d332feSfei feng - Sun Microsystems - Beijing China if (index1 >= IWK_BROADCAST_ID) {
186619d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_key_set(): "
186719d332feSfei feng - Sun Microsystems - Beijing China "have no this node in hardware node table\n");
186819d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_ibss.node_tb_lock);
186919d332feSfei feng - Sun Microsystems - Beijing China return (0);
187019d332feSfei feng - Sun Microsystems - Beijing China } else {
187119d332feSfei feng - Sun Microsystems - Beijing China /*
187219d332feSfei feng - Sun Microsystems - Beijing China * configure key for given node in hardware
187319d332feSfei feng - Sun Microsystems - Beijing China */
187419d332feSfei feng - Sun Microsystems - Beijing China if (k->wk_flags & IEEE80211_KEY_XMIT) {
187519d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_node_tb[index1].
187619d332feSfei feng - Sun Microsystems - Beijing China node.key_flags = 0;
187719d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_node_tb[index1].
187819d332feSfei feng - Sun Microsystems - Beijing China node.keyp = k->wk_keyix;
187919d332feSfei feng - Sun Microsystems - Beijing China } else {
188019d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_node_tb[index1].
188119d332feSfei feng - Sun Microsystems - Beijing China node.key_flags = (1 << 14);
188219d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_node_tb[index1].
188319d332feSfei feng - Sun Microsystems - Beijing China node.keyp = k->wk_keyix + 4;
188419d332feSfei feng - Sun Microsystems - Beijing China }
188519d332feSfei feng - Sun Microsystems - Beijing China
188619d332feSfei feng - Sun Microsystems - Beijing China (void) memcpy(sc->sc_ibss.ibss_node_tb[index1].node.key,
188719d332feSfei feng - Sun Microsystems - Beijing China k->wk_key, k->wk_keylen);
188819d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_node_tb[index1].node.key_flags |=
188919d332feSfei feng - Sun Microsystems - Beijing China (STA_KEY_FLG_CCMP | (1 << 3) | (k->wk_keyix << 8));
1890b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_node_tb[index1].node.key_flags =
1891b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(sc->sc_ibss.ibss_node_tb[index1].
1892b510adaeSfei feng - Sun Microsystems - Beijing China node.key_flags);
189319d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_node_tb[index1].node.sta_mask =
189419d332feSfei feng - Sun Microsystems - Beijing China STA_MODIFY_KEY_MASK;
189519d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_node_tb[index1].node.control = 1;
189619d332feSfei feng - Sun Microsystems - Beijing China
189719d332feSfei feng - Sun Microsystems - Beijing China mutex_enter(&sc->sc_glock);
189819d332feSfei feng - Sun Microsystems - Beijing China err = iwk_cmd(sc, REPLY_ADD_STA,
189919d332feSfei feng - Sun Microsystems - Beijing China &sc->sc_ibss.ibss_node_tb[index1].node,
190019d332feSfei feng - Sun Microsystems - Beijing China sizeof (iwk_add_sta_t), 1);
190119d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) {
190219d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_key_set(): "
190319d332feSfei feng - Sun Microsystems - Beijing China "failed to update IBSS node in hardware\n");
190419d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock);
190519d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_ibss.node_tb_lock);
190619d332feSfei feng - Sun Microsystems - Beijing China return (0);
190719d332feSfei feng - Sun Microsystems - Beijing China }
190819d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock);
190919d332feSfei feng - Sun Microsystems - Beijing China }
191019d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_ibss.node_tb_lock);
191119d332feSfei feng - Sun Microsystems - Beijing China return (1);
1912c533a883Shx147065 } else {
1913c533a883Shx147065 IEEE80211_ADDR_COPY(node.bssid, ic->ic_bss->in_bssid);
1914c533a883Shx147065 node.id = IWK_AP_ID;
1915c533a883Shx147065 }
1916c533a883Shx147065 if (k->wk_flags & IEEE80211_KEY_XMIT) {
1917c533a883Shx147065 node.key_flags = 0;
1918c533a883Shx147065 node.keyp = k->wk_keyix;
1919c533a883Shx147065 } else {
1920c533a883Shx147065 node.key_flags = (1 << 14);
1921c533a883Shx147065 node.keyp = k->wk_keyix + 4;
1922c533a883Shx147065 }
1923c533a883Shx147065 (void) memcpy(node.key, k->wk_key, k->wk_keylen);
1924c533a883Shx147065 node.key_flags |= (STA_KEY_FLG_CCMP | (1 << 3) | (k->wk_keyix << 8));
1925b510adaeSfei feng - Sun Microsystems - Beijing China node.key_flags = LE_16(node.key_flags);
1926c533a883Shx147065 node.sta_mask = STA_MODIFY_KEY_MASK;
1927c533a883Shx147065 node.control = 1;
1928c533a883Shx147065 err = iwk_cmd(sc, REPLY_ADD_STA, &node, sizeof (node), 1);
1929c533a883Shx147065 if (err != IWK_SUCCESS) {
1930c533a883Shx147065 cmn_err(CE_WARN, "iwk_key_set():"
1931c533a883Shx147065 "failed to update ap node\n");
1932c533a883Shx147065 mutex_exit(&sc->sc_glock);
1933c533a883Shx147065 return (0);
1934c533a883Shx147065 }
1935c533a883Shx147065 mutex_exit(&sc->sc_glock);
1936c533a883Shx147065 return (1);
1937c533a883Shx147065 }
1938c533a883Shx147065
1939c533a883Shx147065 /*
1940c533a883Shx147065 * exclusive access to mac begin.
1941c533a883Shx147065 */
1942c533a883Shx147065 static void
iwk_mac_access_enter(iwk_sc_t * sc)1943c533a883Shx147065 iwk_mac_access_enter(iwk_sc_t *sc)
1944c533a883Shx147065 {
1945c533a883Shx147065 uint32_t tmp;
1946c533a883Shx147065 int n;
1947c533a883Shx147065
1948c533a883Shx147065 tmp = IWK_READ(sc, CSR_GP_CNTRL);
1949c533a883Shx147065 IWK_WRITE(sc, CSR_GP_CNTRL,
1950c533a883Shx147065 tmp | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
1951c533a883Shx147065
1952c533a883Shx147065 /* wait until we succeed */
1953c533a883Shx147065 for (n = 0; n < 1000; n++) {
1954c533a883Shx147065 if ((IWK_READ(sc, CSR_GP_CNTRL) &
1955c533a883Shx147065 (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
1956c533a883Shx147065 CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP)) ==
1957c533a883Shx147065 CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN)
1958c533a883Shx147065 break;
1959c533a883Shx147065 DELAY(10);
1960c533a883Shx147065 }
1961c533a883Shx147065 if (n == 1000)
1962c533a883Shx147065 IWK_DBG((IWK_DEBUG_PIO, "could not lock memory\n"));
1963c533a883Shx147065 }
1964c533a883Shx147065
1965c533a883Shx147065 /*
1966c533a883Shx147065 * exclusive access to mac end.
1967c533a883Shx147065 */
1968c533a883Shx147065 static void
iwk_mac_access_exit(iwk_sc_t * sc)1969c533a883Shx147065 iwk_mac_access_exit(iwk_sc_t *sc)
1970c533a883Shx147065 {
1971c533a883Shx147065 uint32_t tmp = IWK_READ(sc, CSR_GP_CNTRL);
1972c533a883Shx147065 IWK_WRITE(sc, CSR_GP_CNTRL,
1973c533a883Shx147065 tmp & ~CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
1974c533a883Shx147065 }
1975c533a883Shx147065
1976cdc64593Sxinghua wen - Sun Microsystems - Beijing China static uint32_t
iwk_mem_read(iwk_sc_t * sc,uint32_t addr)1977cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_mem_read(iwk_sc_t *sc, uint32_t addr)
1978cdc64593Sxinghua wen - Sun Microsystems - Beijing China {
1979cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_WRITE(sc, HBUS_TARG_MEM_RADDR, addr);
1980cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_READ(sc, HBUS_TARG_MEM_RDAT));
1981cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
1982c533a883Shx147065
1983c533a883Shx147065 static void
iwk_mem_write(iwk_sc_t * sc,uint32_t addr,uint32_t data)1984c533a883Shx147065 iwk_mem_write(iwk_sc_t *sc, uint32_t addr, uint32_t data)
1985c533a883Shx147065 {
1986c533a883Shx147065 IWK_WRITE(sc, HBUS_TARG_MEM_WADDR, addr);
1987c533a883Shx147065 IWK_WRITE(sc, HBUS_TARG_MEM_WDAT, data);
1988c533a883Shx147065 }
1989c533a883Shx147065
1990c533a883Shx147065 static uint32_t
iwk_reg_read(iwk_sc_t * sc,uint32_t addr)1991c533a883Shx147065 iwk_reg_read(iwk_sc_t *sc, uint32_t addr)
1992c533a883Shx147065 {
1993c533a883Shx147065 IWK_WRITE(sc, HBUS_TARG_PRPH_RADDR, addr | (3 << 24));
1994c533a883Shx147065 return (IWK_READ(sc, HBUS_TARG_PRPH_RDAT));
1995c533a883Shx147065 }
1996c533a883Shx147065
1997c533a883Shx147065 static void
iwk_reg_write(iwk_sc_t * sc,uint32_t addr,uint32_t data)1998c533a883Shx147065 iwk_reg_write(iwk_sc_t *sc, uint32_t addr, uint32_t data)
1999c533a883Shx147065 {
2000c533a883Shx147065 IWK_WRITE(sc, HBUS_TARG_PRPH_WADDR, addr | (3 << 24));
2001c533a883Shx147065 IWK_WRITE(sc, HBUS_TARG_PRPH_WDAT, data);
2002c533a883Shx147065 }
2003c533a883Shx147065
2004c533a883Shx147065 static void
iwk_reg_write_region_4(iwk_sc_t * sc,uint32_t addr,uint32_t * data,int wlen)2005c533a883Shx147065 iwk_reg_write_region_4(iwk_sc_t *sc, uint32_t addr,
2006c533a883Shx147065 uint32_t *data, int wlen)
2007c533a883Shx147065 {
2008c533a883Shx147065 for (; wlen > 0; wlen--, data++, addr += 4)
2009b510adaeSfei feng - Sun Microsystems - Beijing China iwk_reg_write(sc, addr, LE_32(*data));
2010c533a883Shx147065 }
2011c533a883Shx147065
2012c533a883Shx147065
2013c533a883Shx147065 /*
2014c533a883Shx147065 * ucode load/initialization steps:
2015c533a883Shx147065 * 1) load Bootstrap State Machine (BSM) with "bootstrap" uCode image.
2016c533a883Shx147065 * BSM contains a small memory that *always* stays powered up, so it can
2017c533a883Shx147065 * retain the bootstrap program even when the card is in a power-saving
2018c533a883Shx147065 * power-down state. The BSM loads the small program into ARC processor's
2019c533a883Shx147065 * instruction memory when triggered by power-up.
2020c533a883Shx147065 * 2) load Initialize image via bootstrap program.
2021c533a883Shx147065 * The Initialize image sets up regulatory and calibration data for the
2022c533a883Shx147065 * Runtime/Protocol uCode. This sends a REPLY_ALIVE notification when completed.
2023c533a883Shx147065 * The 4965 reply contains calibration data for temperature, voltage and tx gain
2024c533a883Shx147065 * correction.
2025c533a883Shx147065 */
2026c533a883Shx147065 static int
iwk_load_firmware(iwk_sc_t * sc)2027c533a883Shx147065 iwk_load_firmware(iwk_sc_t *sc)
2028c533a883Shx147065 {
2029c533a883Shx147065 uint32_t *boot_fw = (uint32_t *)sc->sc_boot;
2030b510adaeSfei feng - Sun Microsystems - Beijing China uint32_t size = LE_32(sc->sc_hdr->bootsz);
2031c533a883Shx147065 int n, err = IWK_SUCCESS;
2032c533a883Shx147065
2033c533a883Shx147065 /*
2034c533a883Shx147065 * The physical address bit [4-35] of the initialize uCode.
2035c533a883Shx147065 * In the initialize alive notify interrupt the physical address of
2036c533a883Shx147065 * the runtime ucode will be set for loading.
2037c533a883Shx147065 */
2038c533a883Shx147065 iwk_mac_access_enter(sc);
2039c533a883Shx147065
2040c533a883Shx147065 iwk_reg_write(sc, BSM_DRAM_INST_PTR_REG,
2041c533a883Shx147065 sc->sc_dma_fw_init_text.cookie.dmac_address >> 4);
2042c533a883Shx147065 iwk_reg_write(sc, BSM_DRAM_DATA_PTR_REG,
2043c533a883Shx147065 sc->sc_dma_fw_init_data.cookie.dmac_address >> 4);
2044c533a883Shx147065 iwk_reg_write(sc, BSM_DRAM_INST_BYTECOUNT_REG,
2045c533a883Shx147065 sc->sc_dma_fw_init_text.cookie.dmac_size);
2046c533a883Shx147065 iwk_reg_write(sc, BSM_DRAM_DATA_BYTECOUNT_REG,
2047c533a883Shx147065 sc->sc_dma_fw_init_data.cookie.dmac_size);
2048c533a883Shx147065
2049c533a883Shx147065 /* load bootstrap code into BSM memory */
2050c533a883Shx147065 iwk_reg_write_region_4(sc, BSM_SRAM_LOWER_BOUND, boot_fw,
2051c533a883Shx147065 size / sizeof (uint32_t));
2052c533a883Shx147065
2053c533a883Shx147065 iwk_reg_write(sc, BSM_WR_MEM_SRC_REG, 0);
2054c533a883Shx147065 iwk_reg_write(sc, BSM_WR_MEM_DST_REG, RTC_INST_LOWER_BOUND);
2055c533a883Shx147065 iwk_reg_write(sc, BSM_WR_DWCOUNT_REG, size / sizeof (uint32_t));
2056c533a883Shx147065
2057c533a883Shx147065 /*
2058c533a883Shx147065 * prepare to load initialize uCode
2059c533a883Shx147065 */
2060c533a883Shx147065 iwk_reg_write(sc, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START);
2061c533a883Shx147065
2062c533a883Shx147065 /* wait while the adapter is busy loading the firmware */
2063c533a883Shx147065 for (n = 0; n < 1000; n++) {
2064c533a883Shx147065 if (!(iwk_reg_read(sc, BSM_WR_CTRL_REG) &
2065c533a883Shx147065 BSM_WR_CTRL_REG_BIT_START))
2066c533a883Shx147065 break;
2067c533a883Shx147065 DELAY(10);
2068c533a883Shx147065 }
2069c533a883Shx147065 if (n == 1000) {
2070c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "timeout transferring firmware\n");
2071c533a883Shx147065 err = ETIMEDOUT;
2072c533a883Shx147065 return (err);
2073c533a883Shx147065 }
2074c533a883Shx147065
2075c533a883Shx147065 /* for future power-save mode use */
2076c533a883Shx147065 iwk_reg_write(sc, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN);
2077c533a883Shx147065
2078c533a883Shx147065 iwk_mac_access_exit(sc);
2079c533a883Shx147065
2080c533a883Shx147065 return (err);
2081c533a883Shx147065 }
2082c533a883Shx147065
2083c533a883Shx147065 /*ARGSUSED*/
2084c533a883Shx147065 static void
iwk_rx_intr(iwk_sc_t * sc,iwk_rx_desc_t * desc,iwk_rx_data_t * data)2085c533a883Shx147065 iwk_rx_intr(iwk_sc_t *sc, iwk_rx_desc_t *desc, iwk_rx_data_t *data)
2086c533a883Shx147065 {
2087c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic;
2088c533a883Shx147065 iwk_rx_ring_t *ring = &sc->sc_rxq;
2089c533a883Shx147065 iwk_rx_phy_res_t *stat;
2090c533a883Shx147065 ieee80211_node_t *in;
2091c533a883Shx147065 uint32_t *tail;
2092c533a883Shx147065 struct ieee80211_frame *wh;
2093c533a883Shx147065 mblk_t *mp;
2094c533a883Shx147065 uint16_t len, rssi, mrssi, agc;
2095c533a883Shx147065 int16_t t;
2096c533a883Shx147065 uint32_t ants, i;
2097c533a883Shx147065 struct iwk_rx_non_cfg_phy *phyinfo;
2098b510adaeSfei feng - Sun Microsystems - Beijing China uint32_t crc;
2099c533a883Shx147065
2100c533a883Shx147065 /* assuming not 11n here. cope with 11n in phase-II */
2101c533a883Shx147065 stat = (iwk_rx_phy_res_t *)(desc + 1);
2102c533a883Shx147065 if (stat->cfg_phy_cnt > 20) {
2103c533a883Shx147065 return;
2104c533a883Shx147065 }
2105c533a883Shx147065
2106b510adaeSfei feng - Sun Microsystems - Beijing China for (i = 0; i < RX_RES_PHY_CNT; i++)
2107b510adaeSfei feng - Sun Microsystems - Beijing China stat->non_cfg_phy[i] = LE_16(stat->non_cfg_phy[i]);
2108b510adaeSfei feng - Sun Microsystems - Beijing China
2109c533a883Shx147065 phyinfo = (struct iwk_rx_non_cfg_phy *)stat->non_cfg_phy;
2110c533a883Shx147065 agc = (phyinfo->agc_info & IWK_AGC_DB_MASK) >> IWK_AGC_DB_POS;
2111c533a883Shx147065 mrssi = 0;
2112b510adaeSfei feng - Sun Microsystems - Beijing China ants = (LE_16(stat->phy_flags) & RX_PHY_FLAGS_ANTENNAE_MASK) >>
2113cdc64593Sxinghua wen - Sun Microsystems - Beijing China RX_PHY_FLAGS_ANTENNAE_OFFSET;
2114c533a883Shx147065 for (i = 0; i < 3; i++) {
2115c533a883Shx147065 if (ants & (1 << i))
2116c533a883Shx147065 mrssi = MAX(mrssi, phyinfo->rssi_info[i << 1]);
2117c533a883Shx147065 }
2118c533a883Shx147065 t = mrssi - agc - 44; /* t is the dBM value */
2119c533a883Shx147065 /*
2120c533a883Shx147065 * convert dBm to percentage ???
2121c533a883Shx147065 */
2122cdc64593Sxinghua wen - Sun Microsystems - Beijing China rssi = (100 * 75 * 75 - (-20 - t) * (15 * 75 + 62 * (-20 - t))) /
2123cdc64593Sxinghua wen - Sun Microsystems - Beijing China (75 * 75);
2124c533a883Shx147065 if (rssi > 100)
2125c533a883Shx147065 rssi = 100;
2126c533a883Shx147065 if (rssi < 1)
2127c533a883Shx147065 rssi = 1;
2128b510adaeSfei feng - Sun Microsystems - Beijing China len = LE_16(stat->byte_count);
2129b510adaeSfei feng - Sun Microsystems - Beijing China tail = (uint32_t *)((caddr_t)(stat + 1) + stat->cfg_phy_cnt + len);
2130b510adaeSfei feng - Sun Microsystems - Beijing China bcopy(tail, &crc, 4);
2131c533a883Shx147065
2132c533a883Shx147065 IWK_DBG((IWK_DEBUG_RX, "rx intr: idx=%d phy_len=%x len=%d "
2133c533a883Shx147065 "rate=%x chan=%d tstamp=%x non_cfg_phy_count=%x "
2134c533a883Shx147065 "cfg_phy_count=%x tail=%x", ring->cur, sizeof (*stat),
2135b510adaeSfei feng - Sun Microsystems - Beijing China len, stat->rate.r.s.rate, LE_16(stat->channel),
2136c533a883Shx147065 LE_32(stat->timestampl), stat->non_cfg_phy_cnt,
2137b510adaeSfei feng - Sun Microsystems - Beijing China stat->cfg_phy_cnt, LE_32(crc)));
2138c533a883Shx147065
2139c533a883Shx147065 if ((len < 16) || (len > sc->sc_dmabuf_sz)) {
2140c533a883Shx147065 IWK_DBG((IWK_DEBUG_RX, "rx frame oversize\n"));
2141c533a883Shx147065 return;
2142c533a883Shx147065 }
2143c533a883Shx147065
2144c533a883Shx147065 /*
2145c533a883Shx147065 * discard Rx frames with bad CRC
2146c533a883Shx147065 */
2147b510adaeSfei feng - Sun Microsystems - Beijing China if ((LE_32(crc) &
2148c533a883Shx147065 (RX_RES_STATUS_NO_CRC32_ERROR | RX_RES_STATUS_NO_RXE_OVERFLOW)) !=
2149c533a883Shx147065 (RX_RES_STATUS_NO_CRC32_ERROR | RX_RES_STATUS_NO_RXE_OVERFLOW)) {
2150c533a883Shx147065 IWK_DBG((IWK_DEBUG_RX, "rx crc error tail: %x\n",
2151b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(crc)));
2152c533a883Shx147065 sc->sc_rx_err++;
2153c533a883Shx147065 return;
2154c533a883Shx147065 }
2155c533a883Shx147065
2156c533a883Shx147065 wh = (struct ieee80211_frame *)
2157c533a883Shx147065 ((uint8_t *)(stat + 1)+ stat->cfg_phy_cnt);
2158c533a883Shx147065 if (*(uint8_t *)wh == IEEE80211_FC0_SUBTYPE_ASSOC_RESP) {
2159c533a883Shx147065 sc->sc_assoc_id = *((uint16_t *)(wh + 1) + 2);
2160c533a883Shx147065 IWK_DBG((IWK_DEBUG_RX, "rx : association id = %x\n",
2161c533a883Shx147065 sc->sc_assoc_id));
2162c533a883Shx147065 }
2163c533a883Shx147065 #ifdef DEBUG
2164c533a883Shx147065 if (iwk_dbg_flags & IWK_DEBUG_RX)
2165c533a883Shx147065 ieee80211_dump_pkt((uint8_t *)wh, len, 0, 0);
2166c533a883Shx147065 #endif
2167c533a883Shx147065 in = ieee80211_find_rxnode(ic, wh);
2168c533a883Shx147065 mp = allocb(len, BPRI_MED);
2169c533a883Shx147065 if (mp) {
2170c533a883Shx147065 (void) memcpy(mp->b_wptr, wh, len);
2171c533a883Shx147065 mp->b_wptr += len;
2172c533a883Shx147065
2173c533a883Shx147065 /* send the frame to the 802.11 layer */
2174c533a883Shx147065 (void) ieee80211_input(ic, mp, in, rssi, 0);
2175c533a883Shx147065 } else {
2176c533a883Shx147065 sc->sc_rx_nobuf++;
2177c533a883Shx147065 IWK_DBG((IWK_DEBUG_RX,
2178c533a883Shx147065 "iwk_rx_intr(): alloc rx buf failed\n"));
2179c533a883Shx147065 }
2180c533a883Shx147065 /* release node reference */
2181c533a883Shx147065 ieee80211_free_node(in);
2182c533a883Shx147065 }
2183c533a883Shx147065
2184c533a883Shx147065 /*ARGSUSED*/
2185c533a883Shx147065 static void
iwk_tx_intr(iwk_sc_t * sc,iwk_rx_desc_t * desc,iwk_rx_data_t * data)2186c533a883Shx147065 iwk_tx_intr(iwk_sc_t *sc, iwk_rx_desc_t *desc, iwk_rx_data_t *data)
2187c533a883Shx147065 {
2188c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic;
2189c533a883Shx147065 iwk_tx_ring_t *ring = &sc->sc_txq[desc->hdr.qid & 0x3];
2190c533a883Shx147065 iwk_tx_stat_t *stat = (iwk_tx_stat_t *)(desc + 1);
219143439c96Shx147065 iwk_amrr_t *amrr = (iwk_amrr_t *)ic->ic_bss;
2192c533a883Shx147065
2193c533a883Shx147065 IWK_DBG((IWK_DEBUG_TX, "tx done: qid=%d idx=%d"
2194c533a883Shx147065 " retries=%d frame_count=%x nkill=%d "
2195c533a883Shx147065 "rate=%x duration=%d status=%x\n",
2196c533a883Shx147065 desc->hdr.qid, desc->hdr.idx, stat->ntries, stat->frame_count,
2197c533a883Shx147065 stat->bt_kill_count, stat->rate.r.s.rate,
2198b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(stat->duration), LE_32(stat->status)));
2199c533a883Shx147065
220043439c96Shx147065 amrr->txcnt++;
220143439c96Shx147065 IWK_DBG((IWK_DEBUG_RATECTL, "tx: %d cnt\n", amrr->txcnt));
2202c533a883Shx147065 if (stat->ntries > 0) {
220343439c96Shx147065 amrr->retrycnt++;
2204c533a883Shx147065 sc->sc_tx_retries++;
2205c533a883Shx147065 IWK_DBG((IWK_DEBUG_TX, "tx: %d retries\n",
2206c533a883Shx147065 sc->sc_tx_retries));
2207c533a883Shx147065 }
2208c533a883Shx147065
2209c533a883Shx147065 sc->sc_tx_timer = 0;
2210c533a883Shx147065
2211c533a883Shx147065 mutex_enter(&sc->sc_tx_lock);
2212c533a883Shx147065 ring->queued--;
2213c533a883Shx147065 if (ring->queued < 0)
2214c533a883Shx147065 ring->queued = 0;
2215c533a883Shx147065 if ((sc->sc_need_reschedule) && (ring->queued <= (ring->count << 3))) {
2216c533a883Shx147065 sc->sc_need_reschedule = 0;
2217c533a883Shx147065 mutex_exit(&sc->sc_tx_lock);
2218c533a883Shx147065 mac_tx_update(ic->ic_mach);
2219c533a883Shx147065 mutex_enter(&sc->sc_tx_lock);
2220c533a883Shx147065 }
2221c533a883Shx147065 mutex_exit(&sc->sc_tx_lock);
2222c533a883Shx147065 }
2223c533a883Shx147065
2224c533a883Shx147065 static void
iwk_cmd_intr(iwk_sc_t * sc,iwk_rx_desc_t * desc)2225c533a883Shx147065 iwk_cmd_intr(iwk_sc_t *sc, iwk_rx_desc_t *desc)
2226c533a883Shx147065 {
2227c533a883Shx147065 if ((desc->hdr.qid & 7) != 4) {
2228c533a883Shx147065 return;
2229c533a883Shx147065 }
2230c533a883Shx147065 mutex_enter(&sc->sc_glock);
2231c533a883Shx147065 sc->sc_flags |= IWK_F_CMD_DONE;
2232c533a883Shx147065 cv_signal(&sc->sc_cmd_cv);
2233c533a883Shx147065 mutex_exit(&sc->sc_glock);
2234c533a883Shx147065 IWK_DBG((IWK_DEBUG_CMD, "rx cmd: "
2235c533a883Shx147065 "qid=%x idx=%d flags=%x type=0x%x\n",
2236c533a883Shx147065 desc->hdr.qid, desc->hdr.idx, desc->hdr.flags,
2237c533a883Shx147065 desc->hdr.type));
2238c533a883Shx147065 }
2239c533a883Shx147065
2240c533a883Shx147065 static void
iwk_ucode_alive(iwk_sc_t * sc,iwk_rx_desc_t * desc)2241c533a883Shx147065 iwk_ucode_alive(iwk_sc_t *sc, iwk_rx_desc_t *desc)
2242c533a883Shx147065 {
2243c533a883Shx147065 uint32_t base, i;
2244c533a883Shx147065 struct iwk_alive_resp *ar =
2245c533a883Shx147065 (struct iwk_alive_resp *)(desc + 1);
2246c533a883Shx147065
2247c533a883Shx147065 /* the microcontroller is ready */
2248c533a883Shx147065 IWK_DBG((IWK_DEBUG_FW,
2249c533a883Shx147065 "microcode alive notification minor: %x major: %x type:"
2250c533a883Shx147065 " %x subtype: %x\n",
2251c533a883Shx147065 ar->ucode_minor, ar->ucode_minor, ar->ver_type, ar->ver_subtype));
2252c533a883Shx147065
2253c533a883Shx147065 if (LE_32(ar->is_valid) != UCODE_VALID_OK) {
2254c533a883Shx147065 IWK_DBG((IWK_DEBUG_FW,
2255c533a883Shx147065 "microcontroller initialization failed\n"));
2256c533a883Shx147065 }
2257c533a883Shx147065 if (ar->ver_subtype == INITIALIZE_SUBTYPE) {
2258c533a883Shx147065 IWK_DBG((IWK_DEBUG_FW,
2259c533a883Shx147065 "initialization alive received.\n"));
2260c533a883Shx147065 (void) memcpy(&sc->sc_card_alive_init, ar,
2261c533a883Shx147065 sizeof (struct iwk_init_alive_resp));
2262c533a883Shx147065 /* XXX get temperature */
2263c533a883Shx147065 iwk_mac_access_enter(sc);
2264c533a883Shx147065 iwk_reg_write(sc, BSM_DRAM_INST_PTR_REG,
2265c533a883Shx147065 sc->sc_dma_fw_text.cookie.dmac_address >> 4);
2266c533a883Shx147065 iwk_reg_write(sc, BSM_DRAM_DATA_PTR_REG,
2267c533a883Shx147065 sc->sc_dma_fw_data_bak.cookie.dmac_address >> 4);
2268c533a883Shx147065 iwk_reg_write(sc, BSM_DRAM_DATA_BYTECOUNT_REG,
2269c533a883Shx147065 sc->sc_dma_fw_data.cookie.dmac_size);
2270c533a883Shx147065 iwk_reg_write(sc, BSM_DRAM_INST_BYTECOUNT_REG,
2271c533a883Shx147065 sc->sc_dma_fw_text.cookie.dmac_size | 0x80000000);
2272c533a883Shx147065 iwk_mac_access_exit(sc);
2273c533a883Shx147065 } else {
2274c533a883Shx147065 IWK_DBG((IWK_DEBUG_FW, "runtime alive received.\n"));
2275c533a883Shx147065 (void) memcpy(&sc->sc_card_alive_run, ar,
2276c533a883Shx147065 sizeof (struct iwk_alive_resp));
2277c533a883Shx147065
2278c533a883Shx147065 /*
2279c533a883Shx147065 * Init SCD related registers to make Tx work. XXX
2280c533a883Shx147065 */
2281c533a883Shx147065 iwk_mac_access_enter(sc);
2282c533a883Shx147065
2283c533a883Shx147065 /* read sram address of data base */
2284c533a883Shx147065 sc->sc_scd_base = iwk_reg_read(sc, SCD_SRAM_BASE_ADDR);
2285c533a883Shx147065
2286c533a883Shx147065 /* clear and init SCD_CONTEXT_DATA_OFFSET area. 128 bytes */
2287c533a883Shx147065 for (base = sc->sc_scd_base + SCD_CONTEXT_DATA_OFFSET, i = 0;
2288c533a883Shx147065 i < 128; i += 4)
2289c533a883Shx147065 iwk_mem_write(sc, base + i, 0);
2290c533a883Shx147065
2291c533a883Shx147065 /* clear and init SCD_TX_STTS_BITMAP_OFFSET area. 256 bytes */
2292c533a883Shx147065 for (base = sc->sc_scd_base + SCD_TX_STTS_BITMAP_OFFSET;
2293c533a883Shx147065 i < 256; i += 4)
2294c533a883Shx147065 iwk_mem_write(sc, base + i, 0);
2295c533a883Shx147065
2296c533a883Shx147065 /* clear and init SCD_TRANSLATE_TBL_OFFSET area. 32 bytes */
2297c533a883Shx147065 for (base = sc->sc_scd_base + SCD_TRANSLATE_TBL_OFFSET;
2298c533a883Shx147065 i < sizeof (uint16_t) * IWK_NUM_QUEUES; i += 4)
2299c533a883Shx147065 iwk_mem_write(sc, base + i, 0);
2300c533a883Shx147065
2301c533a883Shx147065 iwk_reg_write(sc, SCD_DRAM_BASE_ADDR,
2302c533a883Shx147065 sc->sc_dma_sh.cookie.dmac_address >> 10);
2303c533a883Shx147065 iwk_reg_write(sc, SCD_QUEUECHAIN_SEL, 0);
2304c533a883Shx147065
2305c533a883Shx147065 /* initiate the tx queues */
2306c533a883Shx147065 for (i = 0; i < IWK_NUM_QUEUES; i++) {
2307c533a883Shx147065 iwk_reg_write(sc, SCD_QUEUE_RDPTR(i), 0);
2308c533a883Shx147065 IWK_WRITE(sc, HBUS_TARG_WRPTR, (i << 8));
2309c533a883Shx147065 iwk_mem_write(sc, sc->sc_scd_base +
2310c533a883Shx147065 SCD_CONTEXT_QUEUE_OFFSET(i),
2311c533a883Shx147065 (SCD_WIN_SIZE & 0x7f));
2312c533a883Shx147065 iwk_mem_write(sc, sc->sc_scd_base +
2313c533a883Shx147065 SCD_CONTEXT_QUEUE_OFFSET(i) + sizeof (uint32_t),
2314c533a883Shx147065 (SCD_FRAME_LIMIT & 0x7f) << 16);
2315c533a883Shx147065 }
2316c533a883Shx147065 /* interrupt enable on each queue0-7 */
2317c533a883Shx147065 iwk_reg_write(sc, SCD_INTERRUPT_MASK,
2318c533a883Shx147065 (1 << IWK_NUM_QUEUES) - 1);
2319c533a883Shx147065 /* enable each channel 0-7 */
2320c533a883Shx147065 iwk_reg_write(sc, SCD_TXFACT,
2321c533a883Shx147065 SCD_TXFACT_REG_TXFIFO_MASK(0, 7));
2322c533a883Shx147065 /*
2323c533a883Shx147065 * queue 0-7 maps to FIFO 0-7 and
2324c533a883Shx147065 * all queues work under FIFO mode (none-scheduler-ack)
2325c533a883Shx147065 */
2326c533a883Shx147065 for (i = 0; i < 7; i++) {
2327c533a883Shx147065 iwk_reg_write(sc,
2328c533a883Shx147065 SCD_QUEUE_STATUS_BITS(i),
2329c533a883Shx147065 (1 << SCD_QUEUE_STTS_REG_POS_ACTIVE)|
2330c533a883Shx147065 (i << SCD_QUEUE_STTS_REG_POS_TXF)|
2331c533a883Shx147065 SCD_QUEUE_STTS_REG_MSK);
2332c533a883Shx147065 }
2333c533a883Shx147065 iwk_mac_access_exit(sc);
2334c533a883Shx147065
2335c533a883Shx147065 sc->sc_flags |= IWK_F_FW_INIT;
2336c533a883Shx147065 cv_signal(&sc->sc_fw_cv);
2337c533a883Shx147065 }
2338c533a883Shx147065
2339c533a883Shx147065 }
2340c533a883Shx147065
2341c533a883Shx147065 static uint_t
2342cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* LINTED: argument unused in function: unused */
iwk_rx_softintr(caddr_t arg,caddr_t unused)2343cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_rx_softintr(caddr_t arg, caddr_t unused)
2344c533a883Shx147065 {
2345c533a883Shx147065 iwk_sc_t *sc = (iwk_sc_t *)arg;
2346c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic;
2347c533a883Shx147065 iwk_rx_desc_t *desc;
2348c533a883Shx147065 iwk_rx_data_t *data;
2349c533a883Shx147065 uint32_t index;
2350c533a883Shx147065
2351c533a883Shx147065 mutex_enter(&sc->sc_glock);
2352c533a883Shx147065 if (sc->sc_rx_softint_pending != 1) {
2353c533a883Shx147065 mutex_exit(&sc->sc_glock);
2354c533a883Shx147065 return (DDI_INTR_UNCLAIMED);
2355c533a883Shx147065 }
2356c533a883Shx147065 /* disable interrupts */
2357c533a883Shx147065 IWK_WRITE(sc, CSR_INT_MASK, 0);
2358c533a883Shx147065 mutex_exit(&sc->sc_glock);
2359c533a883Shx147065
2360c533a883Shx147065 /*
2361c533a883Shx147065 * firmware has moved the index of the rx queue, driver get it,
2362c533a883Shx147065 * and deal with it.
2363c533a883Shx147065 */
2364b510adaeSfei feng - Sun Microsystems - Beijing China index = sc->sc_shared->val0 & 0xfff;
2365c533a883Shx147065
2366c533a883Shx147065 while (sc->sc_rxq.cur != index) {
2367c533a883Shx147065 data = &sc->sc_rxq.data[sc->sc_rxq.cur];
2368c533a883Shx147065 desc = (iwk_rx_desc_t *)data->dma_data.mem_va;
2369c533a883Shx147065
2370c533a883Shx147065 IWK_DBG((IWK_DEBUG_INTR, "rx notification index = %d"
2371c533a883Shx147065 " cur = %d qid=%x idx=%d flags=%x type=%x len=%d\n",
2372c533a883Shx147065 index, sc->sc_rxq.cur, desc->hdr.qid, desc->hdr.idx,
2373c533a883Shx147065 desc->hdr.flags, desc->hdr.type, LE_32(desc->len)));
2374c533a883Shx147065
2375c533a883Shx147065 /* a command other than a tx need to be replied */
2376c533a883Shx147065 if (!(desc->hdr.qid & 0x80) &&
2377c533a883Shx147065 (desc->hdr.type != REPLY_RX_PHY_CMD) &&
2378cdc64593Sxinghua wen - Sun Microsystems - Beijing China (desc->hdr.type != REPLY_TX) &&
2379cdc64593Sxinghua wen - Sun Microsystems - Beijing China (desc->hdr.type != REPLY_TX_PWR_TABLE_CMD) &&
2380cdc64593Sxinghua wen - Sun Microsystems - Beijing China (desc->hdr.type != REPLY_PHY_CALIBRATION_CMD) &&
2381cdc64593Sxinghua wen - Sun Microsystems - Beijing China (desc->hdr.type != SENSITIVITY_CMD))
2382c533a883Shx147065 iwk_cmd_intr(sc, desc);
2383c533a883Shx147065
2384c533a883Shx147065 switch (desc->hdr.type) {
2385c533a883Shx147065 case REPLY_4965_RX:
2386c533a883Shx147065 iwk_rx_intr(sc, desc, data);
2387c533a883Shx147065 break;
2388c533a883Shx147065
2389c533a883Shx147065 case REPLY_TX:
2390c533a883Shx147065 iwk_tx_intr(sc, desc, data);
2391c533a883Shx147065 break;
2392c533a883Shx147065
2393c533a883Shx147065 case REPLY_ALIVE:
2394c533a883Shx147065 iwk_ucode_alive(sc, desc);
2395c533a883Shx147065 break;
2396c533a883Shx147065
2397c533a883Shx147065 case CARD_STATE_NOTIFICATION:
2398c533a883Shx147065 {
2399c533a883Shx147065 uint32_t *status = (uint32_t *)(desc + 1);
2400c533a883Shx147065
2401c533a883Shx147065 IWK_DBG((IWK_DEBUG_RADIO, "state changed to %x\n",
2402c533a883Shx147065 LE_32(*status)));
2403c533a883Shx147065
2404c533a883Shx147065 if (LE_32(*status) & 1) {
240543439c96Shx147065 /*
240643439c96Shx147065 * the radio button has to be pushed(OFF). It
240743439c96Shx147065 * is considered as a hw error, the
240843439c96Shx147065 * iwk_thread() tries to recover it after the
240943439c96Shx147065 * button is pushed again(ON)
241043439c96Shx147065 */
2411c533a883Shx147065 cmn_err(CE_NOTE,
2412cdc64593Sxinghua wen - Sun Microsystems - Beijing China "iwk_rx_softintr(): "
2413cdc64593Sxinghua wen - Sun Microsystems - Beijing China "Radio transmitter is off\n");
241443439c96Shx147065 sc->sc_ostate = sc->sc_ic.ic_state;
241543439c96Shx147065 ieee80211_new_state(&sc->sc_ic,
241643439c96Shx147065 IEEE80211_S_INIT, -1);
241743439c96Shx147065 sc->sc_flags |=
241843439c96Shx147065 (IWK_F_HW_ERR_RECOVER | IWK_F_RADIO_OFF);
2419c533a883Shx147065 }
2420c533a883Shx147065 break;
2421c533a883Shx147065 }
2422c533a883Shx147065 case SCAN_START_NOTIFICATION:
2423c533a883Shx147065 {
2424c533a883Shx147065 iwk_start_scan_t *scan =
2425c533a883Shx147065 (iwk_start_scan_t *)(desc + 1);
2426c533a883Shx147065
2427c533a883Shx147065 IWK_DBG((IWK_DEBUG_SCAN,
2428c533a883Shx147065 "scanning channel %d status %x\n",
2429c533a883Shx147065 scan->chan, LE_32(scan->status)));
2430c533a883Shx147065
2431c533a883Shx147065 ic->ic_curchan = &ic->ic_sup_channels[scan->chan];
2432c533a883Shx147065 break;
2433c533a883Shx147065 }
2434c533a883Shx147065 case SCAN_COMPLETE_NOTIFICATION:
2435cdc64593Sxinghua wen - Sun Microsystems - Beijing China {
2436c50ced99Spengcheng chen - Sun Microsystems - Beijing China iwk_stop_scan_t *scan =
2437c50ced99Spengcheng chen - Sun Microsystems - Beijing China (iwk_stop_scan_t *)(desc + 1);
2438c50ced99Spengcheng chen - Sun Microsystems - Beijing China
2439c50ced99Spengcheng chen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_SCAN,
2440c50ced99Spengcheng chen - Sun Microsystems - Beijing China "completed channel %d (burst of %d) status %02x\n",
2441c50ced99Spengcheng chen - Sun Microsystems - Beijing China scan->chan, scan->nchan, scan->status));
2442c50ced99Spengcheng chen - Sun Microsystems - Beijing China
2443c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_scan_pending++;
2444c50ced99Spengcheng chen - Sun Microsystems - Beijing China break;
2445c50ced99Spengcheng chen - Sun Microsystems - Beijing China }
2446c50ced99Spengcheng chen - Sun Microsystems - Beijing China case STATISTICS_NOTIFICATION:
2447cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* handle statistics notification */
2448cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_statistics_notify(sc, desc);
2449cdc64593Sxinghua wen - Sun Microsystems - Beijing China break;
2450cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
2451cdc64593Sxinghua wen - Sun Microsystems - Beijing China
2452c533a883Shx147065 sc->sc_rxq.cur = (sc->sc_rxq.cur + 1) % RX_QUEUE_SIZE;
2453c533a883Shx147065 }
2454c533a883Shx147065
2455c533a883Shx147065 /*
2456c533a883Shx147065 * driver dealt with what reveived in rx queue and tell the information
2457c533a883Shx147065 * to the firmware.
2458c533a883Shx147065 */
2459c533a883Shx147065 index = (index == 0) ? RX_QUEUE_SIZE - 1 : index - 1;
2460c533a883Shx147065 IWK_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, index & (~7));
2461c533a883Shx147065
2462c533a883Shx147065 mutex_enter(&sc->sc_glock);
2463c533a883Shx147065 /* re-enable interrupts */
2464c533a883Shx147065 IWK_WRITE(sc, CSR_INT_MASK, CSR_INI_SET_MASK);
2465c533a883Shx147065 sc->sc_rx_softint_pending = 0;
2466c533a883Shx147065 mutex_exit(&sc->sc_glock);
2467c533a883Shx147065
2468c533a883Shx147065 return (DDI_INTR_CLAIMED);
2469c533a883Shx147065 }
2470c533a883Shx147065
2471c533a883Shx147065 static uint_t
2472cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* LINTED: argument unused in function: unused */
iwk_intr(caddr_t arg,caddr_t unused)2473cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_intr(caddr_t arg, caddr_t unused)
2474c533a883Shx147065 {
2475c533a883Shx147065 iwk_sc_t *sc = (iwk_sc_t *)arg;
2476c533a883Shx147065 uint32_t r, rfh;
2477c533a883Shx147065
2478c533a883Shx147065 mutex_enter(&sc->sc_glock);
2479d62cb7ffShx147065
2480d62cb7ffShx147065 if (sc->sc_flags & IWK_F_SUSPEND) {
2481d62cb7ffShx147065 mutex_exit(&sc->sc_glock);
2482d62cb7ffShx147065 return (DDI_INTR_UNCLAIMED);
2483d62cb7ffShx147065 }
2484d62cb7ffShx147065
2485c533a883Shx147065 r = IWK_READ(sc, CSR_INT);
2486c533a883Shx147065 if (r == 0 || r == 0xffffffff) {
2487c533a883Shx147065 mutex_exit(&sc->sc_glock);
2488c533a883Shx147065 return (DDI_INTR_UNCLAIMED);
2489c533a883Shx147065 }
2490c533a883Shx147065
2491c533a883Shx147065 IWK_DBG((IWK_DEBUG_INTR, "interrupt reg %x\n", r));
2492c533a883Shx147065
2493c533a883Shx147065 rfh = IWK_READ(sc, CSR_FH_INT_STATUS);
2494c533a883Shx147065 IWK_DBG((IWK_DEBUG_INTR, "FH interrupt reg %x\n", rfh));
2495c533a883Shx147065 /* disable interrupts */
2496c533a883Shx147065 IWK_WRITE(sc, CSR_INT_MASK, 0);
2497c533a883Shx147065 /* ack interrupts */
2498c533a883Shx147065 IWK_WRITE(sc, CSR_INT, r);
2499c533a883Shx147065 IWK_WRITE(sc, CSR_FH_INT_STATUS, rfh);
2500c533a883Shx147065
2501cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (sc->sc_soft_hdl == NULL) {
2502c533a883Shx147065 mutex_exit(&sc->sc_glock);
2503c533a883Shx147065 return (DDI_INTR_CLAIMED);
2504c533a883Shx147065 }
2505c533a883Shx147065 if (r & (BIT_INT_SWERROR | BIT_INT_ERR)) {
2506c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "fatal firmware error\n");
2507c533a883Shx147065 mutex_exit(&sc->sc_glock);
2508cdc64593Sxinghua wen - Sun Microsystems - Beijing China #ifdef DEBUG
2509cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* dump event and error logs to dmesg */
2510cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_write_error_log(sc);
2511cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_write_event_log(sc);
2512cdc64593Sxinghua wen - Sun Microsystems - Beijing China #endif /* DEBUG */
2513c533a883Shx147065 iwk_stop(sc);
2514c533a883Shx147065 sc->sc_ostate = sc->sc_ic.ic_state;
25156f12def4Spengcheng chen - Sun Microsystems - Beijing China
25166f12def4Spengcheng chen - Sun Microsystems - Beijing China /* not capable of fast recovery */
25176f12def4Spengcheng chen - Sun Microsystems - Beijing China if (!IWK_CHK_FAST_RECOVER(sc))
2518c533a883Shx147065 ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
25196f12def4Spengcheng chen - Sun Microsystems - Beijing China
2520c533a883Shx147065 sc->sc_flags |= IWK_F_HW_ERR_RECOVER;
2521c533a883Shx147065 return (DDI_INTR_CLAIMED);
2522c533a883Shx147065 }
2523c533a883Shx147065
2524c533a883Shx147065 if (r & BIT_INT_RF_KILL) {
2525b510adaeSfei feng - Sun Microsystems - Beijing China uint32_t tmp = IWK_READ(sc, CSR_GP_CNTRL);
2526b510adaeSfei feng - Sun Microsystems - Beijing China if (tmp & (1 << 27))
2527b510adaeSfei feng - Sun Microsystems - Beijing China cmn_err(CE_NOTE, "RF switch: radio on\n");
2528c533a883Shx147065 }
2529c533a883Shx147065
2530c533a883Shx147065 if ((r & (BIT_INT_FH_RX | BIT_INT_SW_RX)) ||
2531c533a883Shx147065 (rfh & FH_INT_RX_MASK)) {
2532c533a883Shx147065 sc->sc_rx_softint_pending = 1;
2533cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) ddi_intr_trigger_softint(sc->sc_soft_hdl, NULL);
2534c533a883Shx147065 }
2535c533a883Shx147065
2536c533a883Shx147065 if (r & BIT_INT_ALIVE) {
2537c533a883Shx147065 IWK_DBG((IWK_DEBUG_FW, "firmware initialized.\n"));
2538c533a883Shx147065 }
2539c533a883Shx147065
2540c533a883Shx147065 /* re-enable interrupts */
2541c533a883Shx147065 IWK_WRITE(sc, CSR_INT_MASK, CSR_INI_SET_MASK);
2542c533a883Shx147065 mutex_exit(&sc->sc_glock);
2543c533a883Shx147065
2544c533a883Shx147065 return (DDI_INTR_CLAIMED);
2545c533a883Shx147065 }
2546c533a883Shx147065
2547c533a883Shx147065 static uint8_t
iwk_rate_to_plcp(int rate)2548c533a883Shx147065 iwk_rate_to_plcp(int rate)
2549c533a883Shx147065 {
2550c533a883Shx147065 uint8_t ret;
2551c533a883Shx147065
2552c533a883Shx147065 switch (rate) {
2553c533a883Shx147065 /* CCK rates */
2554c533a883Shx147065 case 2:
2555c533a883Shx147065 ret = 0xa;
2556c533a883Shx147065 break;
2557c533a883Shx147065 case 4:
2558c533a883Shx147065 ret = 0x14;
2559c533a883Shx147065 break;
2560c533a883Shx147065 case 11:
2561c533a883Shx147065 ret = 0x37;
2562c533a883Shx147065 break;
2563c533a883Shx147065 case 22:
2564c533a883Shx147065 ret = 0x6e;
2565c533a883Shx147065 break;
2566c533a883Shx147065 /* OFDM rates */
2567c533a883Shx147065 case 12:
2568c533a883Shx147065 ret = 0xd;
2569c533a883Shx147065 break;
2570c533a883Shx147065 case 18:
2571c533a883Shx147065 ret = 0xf;
2572c533a883Shx147065 break;
2573c533a883Shx147065 case 24:
2574c533a883Shx147065 ret = 0x5;
2575c533a883Shx147065 break;
2576c533a883Shx147065 case 36:
2577c533a883Shx147065 ret = 0x7;
2578c533a883Shx147065 break;
2579c533a883Shx147065 case 48:
2580c533a883Shx147065 ret = 0x9;
2581c533a883Shx147065 break;
2582c533a883Shx147065 case 72:
2583c533a883Shx147065 ret = 0xb;
2584c533a883Shx147065 break;
2585c533a883Shx147065 case 96:
2586c533a883Shx147065 ret = 0x1;
2587c533a883Shx147065 break;
2588c533a883Shx147065 case 108:
2589c533a883Shx147065 ret = 0x3;
2590c533a883Shx147065 break;
2591c533a883Shx147065 default:
2592c533a883Shx147065 ret = 0;
2593c533a883Shx147065 break;
2594c533a883Shx147065 }
2595c533a883Shx147065 return (ret);
2596c533a883Shx147065 }
2597c533a883Shx147065
2598c533a883Shx147065 static mblk_t *
iwk_m_tx(void * arg,mblk_t * mp)2599c533a883Shx147065 iwk_m_tx(void *arg, mblk_t *mp)
2600c533a883Shx147065 {
2601c533a883Shx147065 iwk_sc_t *sc = (iwk_sc_t *)arg;
2602c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic;
2603c533a883Shx147065 mblk_t *next;
2604c533a883Shx147065
2605d62cb7ffShx147065 if (sc->sc_flags & IWK_F_SUSPEND) {
2606d62cb7ffShx147065 freemsgchain(mp);
2607d62cb7ffShx147065 return (NULL);
2608d62cb7ffShx147065 }
2609d62cb7ffShx147065
2610c533a883Shx147065 if (ic->ic_state != IEEE80211_S_RUN) {
2611c533a883Shx147065 freemsgchain(mp);
2612c533a883Shx147065 return (NULL);
2613c533a883Shx147065 }
2614c533a883Shx147065
26156f12def4Spengcheng chen - Sun Microsystems - Beijing China if ((sc->sc_flags & IWK_F_HW_ERR_RECOVER) &&
26166f12def4Spengcheng chen - Sun Microsystems - Beijing China IWK_CHK_FAST_RECOVER(sc)) {
26176f12def4Spengcheng chen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_FW, "iwk_m_tx(): hold queue\n"));
26186f12def4Spengcheng chen - Sun Microsystems - Beijing China return (mp);
26196f12def4Spengcheng chen - Sun Microsystems - Beijing China }
26206f12def4Spengcheng chen - Sun Microsystems - Beijing China
2621c533a883Shx147065 while (mp != NULL) {
2622c533a883Shx147065 next = mp->b_next;
2623c533a883Shx147065 mp->b_next = NULL;
2624c533a883Shx147065 if (iwk_send(ic, mp, IEEE80211_FC0_TYPE_DATA) != 0) {
2625c533a883Shx147065 mp->b_next = next;
2626c533a883Shx147065 break;
2627c533a883Shx147065 }
2628c533a883Shx147065 mp = next;
2629c533a883Shx147065 }
2630c533a883Shx147065 return (mp);
2631c533a883Shx147065 }
2632c533a883Shx147065
2633c533a883Shx147065 /* ARGSUSED */
2634c533a883Shx147065 static int
iwk_send(ieee80211com_t * ic,mblk_t * mp,uint8_t type)2635c533a883Shx147065 iwk_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
2636c533a883Shx147065 {
2637c533a883Shx147065 iwk_sc_t *sc = (iwk_sc_t *)ic;
2638c533a883Shx147065 iwk_tx_ring_t *ring;
2639c533a883Shx147065 iwk_tx_desc_t *desc;
2640c533a883Shx147065 iwk_tx_data_t *data;
2641c533a883Shx147065 iwk_cmd_t *cmd;
2642c533a883Shx147065 iwk_tx_cmd_t *tx;
2643c533a883Shx147065 ieee80211_node_t *in;
2644c533a883Shx147065 struct ieee80211_frame *wh;
2645c533a883Shx147065 struct ieee80211_key *k = NULL;
2646c533a883Shx147065 mblk_t *m, *m0;
2647c533a883Shx147065 int rate, hdrlen, len, len0, mblen, off, err = IWK_SUCCESS;
2648c533a883Shx147065 uint16_t masks = 0;
264919d332feSfei feng - Sun Microsystems - Beijing China uint8_t index, index1, index2;
2650c533a883Shx147065
2651c533a883Shx147065 ring = &sc->sc_txq[0];
2652c533a883Shx147065 data = &ring->data[ring->cur];
2653c533a883Shx147065 desc = data->desc;
2654c533a883Shx147065 cmd = data->cmd;
2655c533a883Shx147065 bzero(desc, sizeof (*desc));
2656c533a883Shx147065 bzero(cmd, sizeof (*cmd));
2657c533a883Shx147065
2658c533a883Shx147065 mutex_enter(&sc->sc_tx_lock);
2659d62cb7ffShx147065 if (sc->sc_flags & IWK_F_SUSPEND) {
2660d62cb7ffShx147065 mutex_exit(&sc->sc_tx_lock);
2661d62cb7ffShx147065 if ((type & IEEE80211_FC0_TYPE_MASK) !=
2662d62cb7ffShx147065 IEEE80211_FC0_TYPE_DATA) {
2663d62cb7ffShx147065 freemsg(mp);
2664d62cb7ffShx147065 }
2665d62cb7ffShx147065 err = IWK_FAIL;
2666d62cb7ffShx147065 goto exit;
2667d62cb7ffShx147065 }
2668d62cb7ffShx147065
2669c533a883Shx147065 if (ring->queued > ring->count - 64) {
2670c533a883Shx147065 IWK_DBG((IWK_DEBUG_TX, "iwk_send(): no txbuf\n"));
2671c533a883Shx147065 sc->sc_need_reschedule = 1;
2672c533a883Shx147065 mutex_exit(&sc->sc_tx_lock);
2673c533a883Shx147065 if ((type & IEEE80211_FC0_TYPE_MASK) !=
2674c533a883Shx147065 IEEE80211_FC0_TYPE_DATA) {
2675c533a883Shx147065 freemsg(mp);
2676c533a883Shx147065 }
2677c533a883Shx147065 sc->sc_tx_nobuf++;
2678c533a883Shx147065 err = IWK_FAIL;
2679c533a883Shx147065 goto exit;
2680c533a883Shx147065 }
2681c533a883Shx147065 mutex_exit(&sc->sc_tx_lock);
2682c533a883Shx147065
2683c533a883Shx147065 hdrlen = sizeof (struct ieee80211_frame);
2684c533a883Shx147065
2685c533a883Shx147065 m = allocb(msgdsize(mp) + 32, BPRI_MED);
2686c533a883Shx147065 if (m == NULL) { /* can not alloc buf, drop this package */
2687c533a883Shx147065 cmn_err(CE_WARN,
2688c533a883Shx147065 "iwk_send(): failed to allocate msgbuf\n");
2689c533a883Shx147065 freemsg(mp);
2690c533a883Shx147065 err = IWK_SUCCESS;
2691c533a883Shx147065 goto exit;
2692c533a883Shx147065 }
2693c533a883Shx147065 for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) {
2694c533a883Shx147065 mblen = MBLKL(m0);
2695c533a883Shx147065 (void) memcpy(m->b_rptr + off, m0->b_rptr, mblen);
2696c533a883Shx147065 off += mblen;
2697c533a883Shx147065 }
2698c533a883Shx147065 m->b_wptr += off;
2699c533a883Shx147065 freemsg(mp);
2700c533a883Shx147065
2701c533a883Shx147065 wh = (struct ieee80211_frame *)m->b_rptr;
2702c533a883Shx147065
270319d332feSfei feng - Sun Microsystems - Beijing China if (ic->ic_opmode == IEEE80211_M_IBSS &&
270419d332feSfei feng - Sun Microsystems - Beijing China (!(IEEE80211_IS_MULTICAST(wh->i_addr1)))) {
270519d332feSfei feng - Sun Microsystems - Beijing China mutex_enter(&sc->sc_glock);
270619d332feSfei feng - Sun Microsystems - Beijing China mutex_enter(&sc->sc_ibss.node_tb_lock);
270719d332feSfei feng - Sun Microsystems - Beijing China
270819d332feSfei feng - Sun Microsystems - Beijing China /*
270919d332feSfei feng - Sun Microsystems - Beijing China * search for node in ibss node table
271019d332feSfei feng - Sun Microsystems - Beijing China */
271119d332feSfei feng - Sun Microsystems - Beijing China for (index1 = IWK_STA_ID;
271219d332feSfei feng - Sun Microsystems - Beijing China index1 < IWK_STATION_COUNT; index1++) {
271319d332feSfei feng - Sun Microsystems - Beijing China if (sc->sc_ibss.ibss_node_tb[index1].used &&
271419d332feSfei feng - Sun Microsystems - Beijing China IEEE80211_ADDR_EQ(sc->sc_ibss.
271519d332feSfei feng - Sun Microsystems - Beijing China ibss_node_tb[index1].node.bssid,
271619d332feSfei feng - Sun Microsystems - Beijing China wh->i_addr1)) {
271719d332feSfei feng - Sun Microsystems - Beijing China break;
271819d332feSfei feng - Sun Microsystems - Beijing China }
271919d332feSfei feng - Sun Microsystems - Beijing China }
272019d332feSfei feng - Sun Microsystems - Beijing China
272119d332feSfei feng - Sun Microsystems - Beijing China /*
272219d332feSfei feng - Sun Microsystems - Beijing China * if don't find in ibss node table
272319d332feSfei feng - Sun Microsystems - Beijing China */
272419d332feSfei feng - Sun Microsystems - Beijing China if (index1 >= IWK_BROADCAST_ID) {
272519d332feSfei feng - Sun Microsystems - Beijing China err = iwk_clean_add_node_ibss(ic,
272619d332feSfei feng - Sun Microsystems - Beijing China wh->i_addr1, &index2);
272719d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) {
272819d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_send(): "
272919d332feSfei feng - Sun Microsystems - Beijing China "failed to clean all nodes "
273019d332feSfei feng - Sun Microsystems - Beijing China "and add one node\n");
273119d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_ibss.node_tb_lock);
273219d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock);
273319d332feSfei feng - Sun Microsystems - Beijing China freemsg(m);
273419d332feSfei feng - Sun Microsystems - Beijing China sc->sc_tx_err++;
273519d332feSfei feng - Sun Microsystems - Beijing China err = IWK_SUCCESS;
273619d332feSfei feng - Sun Microsystems - Beijing China goto exit;
273719d332feSfei feng - Sun Microsystems - Beijing China }
273819d332feSfei feng - Sun Microsystems - Beijing China index = index2;
273919d332feSfei feng - Sun Microsystems - Beijing China } else {
274019d332feSfei feng - Sun Microsystems - Beijing China index = index1;
274119d332feSfei feng - Sun Microsystems - Beijing China }
274219d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_ibss.node_tb_lock);
274319d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock);
274419d332feSfei feng - Sun Microsystems - Beijing China }
274519d332feSfei feng - Sun Microsystems - Beijing China
2746c533a883Shx147065 in = ieee80211_find_txnode(ic, wh->i_addr1);
2747c533a883Shx147065 if (in == NULL) {
2748c533a883Shx147065 cmn_err(CE_WARN, "iwk_send(): failed to find tx node\n");
2749c533a883Shx147065 freemsg(m);
2750c533a883Shx147065 sc->sc_tx_err++;
2751c533a883Shx147065 err = IWK_SUCCESS;
2752c533a883Shx147065 goto exit;
2753c533a883Shx147065 }
2754c533a883Shx147065 (void) ieee80211_encap(ic, m, in);
2755c533a883Shx147065
2756c533a883Shx147065 cmd->hdr.type = REPLY_TX;
2757c533a883Shx147065 cmd->hdr.flags = 0;
2758c533a883Shx147065 cmd->hdr.qid = ring->qid;
2759c533a883Shx147065 cmd->hdr.idx = ring->cur;
2760c533a883Shx147065
2761c533a883Shx147065 tx = (iwk_tx_cmd_t *)cmd->data;
2762c533a883Shx147065 tx->tx_flags = 0;
2763c533a883Shx147065
2764c533a883Shx147065 if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
2765c533a883Shx147065 tx->tx_flags &= ~(LE_32(TX_CMD_FLG_ACK_MSK));
2766c533a883Shx147065 } else {
2767c533a883Shx147065 tx->tx_flags |= LE_32(TX_CMD_FLG_ACK_MSK);
2768c533a883Shx147065 }
2769c533a883Shx147065
2770c533a883Shx147065 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
2771c533a883Shx147065 k = ieee80211_crypto_encap(ic, m);
2772c533a883Shx147065 if (k == NULL) {
2773c533a883Shx147065 freemsg(m);
2774c533a883Shx147065 sc->sc_tx_err++;
2775c533a883Shx147065 err = IWK_SUCCESS;
2776c533a883Shx147065 goto exit;
2777c533a883Shx147065 }
2778c533a883Shx147065
2779c533a883Shx147065 if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_AES_CCM) {
2780c533a883Shx147065 tx->sec_ctl = 2; /* for CCMP */
2781c533a883Shx147065 tx->tx_flags |= LE_32(TX_CMD_FLG_ACK_MSK);
2782c533a883Shx147065 (void) memcpy(&tx->key, k->wk_key, k->wk_keylen);
2783c533a883Shx147065 }
2784c533a883Shx147065
2785c533a883Shx147065 /* packet header may have moved, reset our local pointer */
2786c533a883Shx147065 wh = (struct ieee80211_frame *)m->b_rptr;
2787c533a883Shx147065 }
2788c533a883Shx147065
2789c533a883Shx147065 len = msgdsize(m);
2790c533a883Shx147065
2791c533a883Shx147065 #ifdef DEBUG
2792c533a883Shx147065 if (iwk_dbg_flags & IWK_DEBUG_TX)
2793c533a883Shx147065 ieee80211_dump_pkt((uint8_t *)wh, hdrlen, 0, 0);
2794c533a883Shx147065 #endif
2795c533a883Shx147065
2796c533a883Shx147065 /* pickup a rate */
2797c533a883Shx147065 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
2798c533a883Shx147065 IEEE80211_FC0_TYPE_MGT) {
2799c533a883Shx147065 /* mgmt frames are sent at 1M */
2800c533a883Shx147065 rate = in->in_rates.ir_rates[0];
2801c533a883Shx147065 } else {
2802c533a883Shx147065 /*
280343439c96Shx147065 * do it here for the software way rate control.
280443439c96Shx147065 * later for rate scaling in hardware.
2805c533a883Shx147065 * maybe like the following, for management frame:
2806c533a883Shx147065 * tx->initial_rate_index = LINK_QUAL_MAX_RETRY_NUM - 1;
2807c533a883Shx147065 * for data frame:
2808c533a883Shx147065 * tx->tx_flags |= (LE_32(TX_CMD_FLG_STA_RATE_MSK));
2809c533a883Shx147065 * rate = in->in_rates.ir_rates[in->in_txrate];
2810c533a883Shx147065 * tx->initial_rate_index = 1;
2811c533a883Shx147065 *
2812c533a883Shx147065 * now the txrate is determined in tx cmd flags, set to the
2813c533a883Shx147065 * max value 54M for 11g and 11M for 11b.
2814c533a883Shx147065 */
2815c533a883Shx147065
2816c533a883Shx147065 if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
2817c533a883Shx147065 rate = ic->ic_fixed_rate;
2818c533a883Shx147065 } else {
2819c533a883Shx147065 rate = in->in_rates.ir_rates[in->in_txrate];
2820c533a883Shx147065 }
2821c533a883Shx147065 }
2822c533a883Shx147065 rate &= IEEE80211_RATE_VAL;
2823c533a883Shx147065 IWK_DBG((IWK_DEBUG_TX, "tx rate[%d of %d] = %x",
2824c533a883Shx147065 in->in_txrate, in->in_rates.ir_nrates, rate));
2825c533a883Shx147065
2826c533a883Shx147065 tx->tx_flags |= (LE_32(TX_CMD_FLG_SEQ_CTL_MSK));
2827c533a883Shx147065
2828c533a883Shx147065 len0 = roundup(4 + sizeof (iwk_tx_cmd_t) + hdrlen, 4);
2829c533a883Shx147065 if (len0 != (4 + sizeof (iwk_tx_cmd_t) + hdrlen))
2830b510adaeSfei feng - Sun Microsystems - Beijing China tx->tx_flags |= LE_32(TX_CMD_FLG_MH_PAD_MSK);
2831c533a883Shx147065
2832c533a883Shx147065 /* retrieve destination node's id */
2833c533a883Shx147065 if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
2834c533a883Shx147065 tx->sta_id = IWK_BROADCAST_ID;
2835c533a883Shx147065 } else {
283619d332feSfei feng - Sun Microsystems - Beijing China if (ic->ic_opmode == IEEE80211_M_IBSS)
283719d332feSfei feng - Sun Microsystems - Beijing China tx->sta_id = index;
283819d332feSfei feng - Sun Microsystems - Beijing China else
2839c533a883Shx147065 tx->sta_id = IWK_AP_ID;
2840c533a883Shx147065 }
2841c533a883Shx147065
2842c533a883Shx147065 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
2843c533a883Shx147065 IEEE80211_FC0_TYPE_MGT) {
2844c533a883Shx147065 /* tell h/w to set timestamp in probe responses */
2845c533a883Shx147065 if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
2846c533a883Shx147065 IEEE80211_FC0_SUBTYPE_PROBE_RESP)
2847c533a883Shx147065 tx->tx_flags |= LE_32(TX_CMD_FLG_TSF_MSK);
2848c533a883Shx147065
2849c533a883Shx147065 if (((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
2850c533a883Shx147065 IEEE80211_FC0_SUBTYPE_ASSOC_REQ) ||
2851c533a883Shx147065 ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
2852c533a883Shx147065 IEEE80211_FC0_SUBTYPE_REASSOC_REQ))
2853b510adaeSfei feng - Sun Microsystems - Beijing China tx->timeout.pm_frame_timeout = LE_16(3);
2854c533a883Shx147065 else
2855b510adaeSfei feng - Sun Microsystems - Beijing China tx->timeout.pm_frame_timeout = LE_16(2);
2856c533a883Shx147065 } else
2857c533a883Shx147065 tx->timeout.pm_frame_timeout = 0;
2858c533a883Shx147065 if (rate == 2 || rate == 4 || rate == 11 || rate == 22)
2859c533a883Shx147065 masks |= RATE_MCS_CCK_MSK;
2860c533a883Shx147065
2861c533a883Shx147065 masks |= RATE_MCS_ANT_B_MSK;
2862b510adaeSfei feng - Sun Microsystems - Beijing China tx->rate.r.rate_n_flags = LE_32(iwk_rate_to_plcp(rate) | masks);
2863c533a883Shx147065
2864c533a883Shx147065 IWK_DBG((IWK_DEBUG_TX, "tx flag = %x",
2865b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(tx->tx_flags)));
2866c533a883Shx147065
2867c533a883Shx147065 tx->rts_retry_limit = 60;
2868c533a883Shx147065 tx->data_retry_limit = 15;
2869c533a883Shx147065
2870c533a883Shx147065 tx->stop_time.life_time = LE_32(0xffffffff);
2871c533a883Shx147065
2872c533a883Shx147065 tx->len = LE_16(len);
2873c533a883Shx147065
2874c533a883Shx147065 tx->dram_lsb_ptr =
2875b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(data->paddr_cmd + 4 + offsetof(iwk_tx_cmd_t, scratch));
2876c533a883Shx147065 tx->dram_msb_ptr = 0;
2877c533a883Shx147065 tx->driver_txop = 0;
2878c533a883Shx147065 tx->next_frame_len = 0;
2879c533a883Shx147065
2880c533a883Shx147065 (void) memcpy(tx + 1, m->b_rptr, hdrlen);
2881c533a883Shx147065 m->b_rptr += hdrlen;
2882c533a883Shx147065 (void) memcpy(data->dma_data.mem_va, m->b_rptr, len - hdrlen);
2883c533a883Shx147065
2884c533a883Shx147065 IWK_DBG((IWK_DEBUG_TX, "sending data: qid=%d idx=%d len=%d",
2885c533a883Shx147065 ring->qid, ring->cur, len));
2886c533a883Shx147065
2887c533a883Shx147065 /*
2888c533a883Shx147065 * first segment includes the tx cmd plus the 802.11 header,
2889c533a883Shx147065 * the second includes the remaining of the 802.11 frame.
2890c533a883Shx147065 */
2891b510adaeSfei feng - Sun Microsystems - Beijing China desc->val0 = 2 << 24;
2892b510adaeSfei feng - Sun Microsystems - Beijing China desc->pa[0].tb1_addr = data->paddr_cmd;
2893c533a883Shx147065 desc->pa[0].val1 = ((len0 << 4) & 0xfff0) |
2894c533a883Shx147065 ((data->dma_data.cookie.dmac_address & 0xffff) << 16);
2895c533a883Shx147065 desc->pa[0].val2 =
2896c533a883Shx147065 ((data->dma_data.cookie.dmac_address & 0xffff0000) >> 16) |
2897c533a883Shx147065 ((len - hdrlen) << 20);
2898c533a883Shx147065 IWK_DBG((IWK_DEBUG_TX, "phy addr1 = 0x%x phy addr2 = 0x%x "
2899c533a883Shx147065 "len1 = 0x%x, len2 = 0x%x val1 = 0x%x val2 = 0x%x",
2900c533a883Shx147065 data->paddr_cmd, data->dma_data.cookie.dmac_address,
2901b510adaeSfei feng - Sun Microsystems - Beijing China len0, len - hdrlen, LE_32(desc->pa[0].val1),
2902b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(desc->pa[0].val2)));
2903c533a883Shx147065
2904c533a883Shx147065 mutex_enter(&sc->sc_tx_lock);
2905c533a883Shx147065 ring->queued++;
2906c533a883Shx147065 mutex_exit(&sc->sc_tx_lock);
2907c533a883Shx147065
2908c533a883Shx147065 /* kick ring */
2909cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_shared->queues_byte_cnt_tbls[ring->qid].
2910cdc64593Sxinghua wen - Sun Microsystems - Beijing China tfd_offset[ring->cur].val = 8 + len;
2911c533a883Shx147065 if (ring->cur < IWK_MAX_WIN_SIZE) {
2912c533a883Shx147065 sc->sc_shared->queues_byte_cnt_tbls[ring->qid].
2913c533a883Shx147065 tfd_offset[IWK_QUEUE_SIZE + ring->cur].val = 8 + len;
2914c533a883Shx147065 }
2915c533a883Shx147065
2916c533a883Shx147065 IWK_DMA_SYNC(data->dma_data, DDI_DMA_SYNC_FORDEV);
2917c533a883Shx147065 IWK_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV);
2918c533a883Shx147065
2919c533a883Shx147065 ring->cur = (ring->cur + 1) % ring->count;
2920c533a883Shx147065 IWK_WRITE(sc, HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur);
2921c533a883Shx147065 freemsg(m);
2922c533a883Shx147065 /* release node reference */
2923c533a883Shx147065 ieee80211_free_node(in);
2924c533a883Shx147065
2925c533a883Shx147065 ic->ic_stats.is_tx_bytes += len;
2926c533a883Shx147065 ic->ic_stats.is_tx_frags++;
2927c533a883Shx147065
2928c533a883Shx147065 if (sc->sc_tx_timer == 0)
29296f12def4Spengcheng chen - Sun Microsystems - Beijing China sc->sc_tx_timer = 4;
29306f12def4Spengcheng chen - Sun Microsystems - Beijing China
2931c533a883Shx147065 exit:
2932c533a883Shx147065 return (err);
2933c533a883Shx147065 }
2934c533a883Shx147065
2935c533a883Shx147065 static void
iwk_m_ioctl(void * arg,queue_t * wq,mblk_t * mp)2936c533a883Shx147065 iwk_m_ioctl(void* arg, queue_t *wq, mblk_t *mp)
2937c533a883Shx147065 {
2938c533a883Shx147065 iwk_sc_t *sc = (iwk_sc_t *)arg;
2939c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic;
294019d332feSfei feng - Sun Microsystems - Beijing China
294119d332feSfei feng - Sun Microsystems - Beijing China enum ieee80211_opmode oldmod;
294219d332feSfei feng - Sun Microsystems - Beijing China iwk_tx_power_table_cmd_t txpower;
294319d332feSfei feng - Sun Microsystems - Beijing China iwk_add_sta_t node;
294419d332feSfei feng - Sun Microsystems - Beijing China iwk_link_quality_cmd_t link_quality;
294519d332feSfei feng - Sun Microsystems - Beijing China uint16_t masks = 0;
294619d332feSfei feng - Sun Microsystems - Beijing China int i, err, err1;
294719d332feSfei feng - Sun Microsystems - Beijing China
294819d332feSfei feng - Sun Microsystems - Beijing China oldmod = ic->ic_opmode;
2949c533a883Shx147065
2950c533a883Shx147065 err = ieee80211_ioctl(ic, wq, mp);
2951cdc64593Sxinghua wen - Sun Microsystems - Beijing China
295219d332feSfei feng - Sun Microsystems - Beijing China /*
295319d332feSfei feng - Sun Microsystems - Beijing China * return to STA mode
295419d332feSfei feng - Sun Microsystems - Beijing China */
295519d332feSfei feng - Sun Microsystems - Beijing China if ((0 == err || ENETRESET == err) && (oldmod != ic->ic_opmode) &&
295619d332feSfei feng - Sun Microsystems - Beijing China (ic->ic_opmode == IEEE80211_M_STA)) {
295719d332feSfei feng - Sun Microsystems - Beijing China /* configure rxon */
295819d332feSfei feng - Sun Microsystems - Beijing China (void) memset(&sc->sc_config, 0, sizeof (iwk_rxon_cmd_t));
295919d332feSfei feng - Sun Microsystems - Beijing China IEEE80211_ADDR_COPY(sc->sc_config.node_addr, ic->ic_macaddr);
296019d332feSfei feng - Sun Microsystems - Beijing China IEEE80211_ADDR_COPY(sc->sc_config.wlap_bssid, ic->ic_macaddr);
2961b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.chan =
2962b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(ieee80211_chan2ieee(ic, ic->ic_curchan));
2963b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags = LE_32(RXON_FLG_TSF2HOST_MSK |
296419d332feSfei feng - Sun Microsystems - Beijing China RXON_FLG_AUTO_DETECT_MSK |
296519d332feSfei feng - Sun Microsystems - Beijing China RXON_FLG_BAND_24G_MSK);
2966b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags &= LE_32(~RXON_FLG_CCK_MSK);
296719d332feSfei feng - Sun Microsystems - Beijing China switch (ic->ic_opmode) {
296819d332feSfei feng - Sun Microsystems - Beijing China case IEEE80211_M_STA:
296919d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.dev_type = RXON_DEV_TYPE_ESS;
297019d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.filter_flags |=
297119d332feSfei feng - Sun Microsystems - Beijing China LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
297219d332feSfei feng - Sun Microsystems - Beijing China RXON_FILTER_DIS_DECRYPT_MSK |
297319d332feSfei feng - Sun Microsystems - Beijing China RXON_FILTER_DIS_GRP_DECRYPT_MSK);
297419d332feSfei feng - Sun Microsystems - Beijing China break;
297519d332feSfei feng - Sun Microsystems - Beijing China case IEEE80211_M_IBSS:
297619d332feSfei feng - Sun Microsystems - Beijing China case IEEE80211_M_AHDEMO:
297719d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.dev_type = RXON_DEV_TYPE_IBSS;
2978b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags |=
2979b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(RXON_FLG_SHORT_PREAMBLE_MSK);
298019d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.filter_flags =
298119d332feSfei feng - Sun Microsystems - Beijing China LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
298219d332feSfei feng - Sun Microsystems - Beijing China RXON_FILTER_DIS_DECRYPT_MSK |
298319d332feSfei feng - Sun Microsystems - Beijing China RXON_FILTER_DIS_GRP_DECRYPT_MSK);
298419d332feSfei feng - Sun Microsystems - Beijing China break;
298519d332feSfei feng - Sun Microsystems - Beijing China case IEEE80211_M_HOSTAP:
298619d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.dev_type = RXON_DEV_TYPE_AP;
298719d332feSfei feng - Sun Microsystems - Beijing China break;
298819d332feSfei feng - Sun Microsystems - Beijing China case IEEE80211_M_MONITOR:
298919d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.dev_type = RXON_DEV_TYPE_SNIFFER;
299019d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.filter_flags |=
299119d332feSfei feng - Sun Microsystems - Beijing China LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
299219d332feSfei feng - Sun Microsystems - Beijing China RXON_FILTER_CTL2HOST_MSK |
299319d332feSfei feng - Sun Microsystems - Beijing China RXON_FILTER_PROMISC_MSK);
299419d332feSfei feng - Sun Microsystems - Beijing China break;
299519d332feSfei feng - Sun Microsystems - Beijing China }
299619d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.cck_basic_rates = 0x0f;
299719d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.ofdm_basic_rates = 0xff;
299819d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.ofdm_ht_single_stream_basic_rates = 0xff;
299919d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.ofdm_ht_dual_stream_basic_rates = 0xff;
300019d332feSfei feng - Sun Microsystems - Beijing China /* set antenna */
300119d332feSfei feng - Sun Microsystems - Beijing China mutex_enter(&sc->sc_glock);
3002b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.rx_chain = LE_16(RXON_RX_CHAIN_DRIVER_FORCE_MSK |
3003b510adaeSfei feng - Sun Microsystems - Beijing China (0x7 << RXON_RX_CHAIN_VALID_POS) |
300419d332feSfei feng - Sun Microsystems - Beijing China (0x6 << RXON_RX_CHAIN_FORCE_SEL_POS) |
300519d332feSfei feng - Sun Microsystems - Beijing China (0x7 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS));
300619d332feSfei feng - Sun Microsystems - Beijing China err1 = iwk_cmd(sc, REPLY_RXON, &sc->sc_config,
300719d332feSfei feng - Sun Microsystems - Beijing China sizeof (iwk_rxon_cmd_t), 1);
300819d332feSfei feng - Sun Microsystems - Beijing China if (err1 != IWK_SUCCESS) {
300919d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_m_ioctl(): "
301019d332feSfei feng - Sun Microsystems - Beijing China "failed to set configure command"
301119d332feSfei feng - Sun Microsystems - Beijing China " please run (ifconfig unplumb and"
301219d332feSfei feng - Sun Microsystems - Beijing China " ifconfig plumb)\n");
301319d332feSfei feng - Sun Microsystems - Beijing China }
301419d332feSfei feng - Sun Microsystems - Beijing China /*
301519d332feSfei feng - Sun Microsystems - Beijing China * set Tx power for 2.4GHz channels
301619d332feSfei feng - Sun Microsystems - Beijing China * (need further investigation. fix tx power at present)
301719d332feSfei feng - Sun Microsystems - Beijing China */
301819d332feSfei feng - Sun Microsystems - Beijing China (void) memset(&txpower, 0, sizeof (txpower));
301919d332feSfei feng - Sun Microsystems - Beijing China txpower.band = 1; /* for 2.4G */
302019d332feSfei feng - Sun Microsystems - Beijing China txpower.channel = sc->sc_config.chan;
302119d332feSfei feng - Sun Microsystems - Beijing China txpower.channel_normal_width = 0;
302219d332feSfei feng - Sun Microsystems - Beijing China for (i = 0; i < POWER_TABLE_NUM_HT_OFDM_ENTRIES; i++) {
302319d332feSfei feng - Sun Microsystems - Beijing China txpower.tx_power.ht_ofdm_power[i].
3024b510adaeSfei feng - Sun Microsystems - Beijing China s.ramon_tx_gain = LE_16(0x3f3f);
302519d332feSfei feng - Sun Microsystems - Beijing China txpower.tx_power.ht_ofdm_power[i].
3026b510adaeSfei feng - Sun Microsystems - Beijing China s.dsp_predis_atten = LE_16(110 | (110 << 8));
302719d332feSfei feng - Sun Microsystems - Beijing China }
3028b510adaeSfei feng - Sun Microsystems - Beijing China txpower.tx_power.legacy_cck_power.s.
3029b510adaeSfei feng - Sun Microsystems - Beijing China ramon_tx_gain = LE_16(0x3f3f);
3030b510adaeSfei feng - Sun Microsystems - Beijing China txpower.tx_power.legacy_cck_power.s.
3031b510adaeSfei feng - Sun Microsystems - Beijing China dsp_predis_atten = LE_16(110 | (110 << 8));
303219d332feSfei feng - Sun Microsystems - Beijing China err1 = iwk_cmd(sc, REPLY_TX_PWR_TABLE_CMD, &txpower,
303319d332feSfei feng - Sun Microsystems - Beijing China sizeof (txpower), 1);
303419d332feSfei feng - Sun Microsystems - Beijing China if (err1 != IWK_SUCCESS) {
303519d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_m_ioctl(): failed to set txpower"
303619d332feSfei feng - Sun Microsystems - Beijing China " please run (ifconfig unplumb "
303719d332feSfei feng - Sun Microsystems - Beijing China "and ifconfig plumb)\n");
303819d332feSfei feng - Sun Microsystems - Beijing China }
303919d332feSfei feng - Sun Microsystems - Beijing China /* add broadcast node so that we can send broadcast frame */
304019d332feSfei feng - Sun Microsystems - Beijing China (void) memset(&node, 0, sizeof (node));
304119d332feSfei feng - Sun Microsystems - Beijing China (void) memset(node.bssid, 0xff, 6);
304219d332feSfei feng - Sun Microsystems - Beijing China node.id = IWK_BROADCAST_ID;
304319d332feSfei feng - Sun Microsystems - Beijing China err1 = iwk_cmd(sc, REPLY_ADD_STA, &node, sizeof (node), 1);
304419d332feSfei feng - Sun Microsystems - Beijing China if (err1 != IWK_SUCCESS) {
304519d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_m_ioctl(): "
304619d332feSfei feng - Sun Microsystems - Beijing China "failed to add broadcast node\n");
304719d332feSfei feng - Sun Microsystems - Beijing China }
304819d332feSfei feng - Sun Microsystems - Beijing China
304919d332feSfei feng - Sun Microsystems - Beijing China /* TX_LINK_QUALITY cmd */
305019d332feSfei feng - Sun Microsystems - Beijing China (void) memset(&link_quality, 0, sizeof (link_quality));
305119d332feSfei feng - Sun Microsystems - Beijing China for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
305219d332feSfei feng - Sun Microsystems - Beijing China masks |= RATE_MCS_CCK_MSK;
305319d332feSfei feng - Sun Microsystems - Beijing China masks |= RATE_MCS_ANT_B_MSK;
305419d332feSfei feng - Sun Microsystems - Beijing China masks &= ~RATE_MCS_ANT_A_MSK;
305519d332feSfei feng - Sun Microsystems - Beijing China link_quality.rate_n_flags[i] =
3056b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(iwk_rate_to_plcp(2) | masks);
305719d332feSfei feng - Sun Microsystems - Beijing China }
305819d332feSfei feng - Sun Microsystems - Beijing China link_quality.general_params.single_stream_ant_msk = 2;
305919d332feSfei feng - Sun Microsystems - Beijing China link_quality.general_params.dual_stream_ant_msk = 3;
306019d332feSfei feng - Sun Microsystems - Beijing China link_quality.agg_params.agg_dis_start_th = 3;
306119d332feSfei feng - Sun Microsystems - Beijing China link_quality.agg_params.agg_time_limit = LE_16(4000);
306219d332feSfei feng - Sun Microsystems - Beijing China link_quality.sta_id = IWK_BROADCAST_ID;
306319d332feSfei feng - Sun Microsystems - Beijing China err1 = iwk_cmd(sc, REPLY_TX_LINK_QUALITY_CMD, &link_quality,
306419d332feSfei feng - Sun Microsystems - Beijing China sizeof (link_quality), 1);
306519d332feSfei feng - Sun Microsystems - Beijing China if (err1 != IWK_SUCCESS) {
306619d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_m_ioctl(): "
306719d332feSfei feng - Sun Microsystems - Beijing China "failed to config link quality table\n");
306819d332feSfei feng - Sun Microsystems - Beijing China }
306919d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock);
307019d332feSfei feng - Sun Microsystems - Beijing China ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
307119d332feSfei feng - Sun Microsystems - Beijing China }
307219d332feSfei feng - Sun Microsystems - Beijing China
3073c533a883Shx147065 if (err == ENETRESET) {
307443439c96Shx147065 /*
307543439c96Shx147065 * This is special for the hidden AP connection.
307643439c96Shx147065 * In any case, we should make sure only one 'scan'
307743439c96Shx147065 * in the driver for a 'connect' CLI command. So
307843439c96Shx147065 * when connecting to a hidden AP, the scan is just
307943439c96Shx147065 * sent out to the air when we know the desired
308043439c96Shx147065 * essid of the AP we want to connect.
308143439c96Shx147065 */
308243439c96Shx147065 if (ic->ic_des_esslen) {
3083c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (sc->sc_flags & IWK_F_RUNNING) {
3084c50ced99Spengcheng chen - Sun Microsystems - Beijing China iwk_m_stop(sc);
3085c50ced99Spengcheng chen - Sun Microsystems - Beijing China (void) iwk_m_start(sc);
3086c533a883Shx147065 (void) ieee80211_new_state(ic,
3087c533a883Shx147065 IEEE80211_S_SCAN, -1);
3088c533a883Shx147065 }
3089c533a883Shx147065 }
309043439c96Shx147065 }
3091c50ced99Spengcheng chen - Sun Microsystems - Beijing China }
3092c533a883Shx147065
3093bcb5c89dSSowmini Varadhan /*
3094bcb5c89dSSowmini Varadhan * callback functions for set/get properties
3095bcb5c89dSSowmini Varadhan */
3096*0dc2366fSVenugopal Iyer
3097bcb5c89dSSowmini Varadhan static int
iwk_m_getprop(void * arg,const char * pr_name,mac_prop_id_t wldp_pr_num,uint_t wldp_length,void * wldp_buf)3098bcb5c89dSSowmini Varadhan iwk_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
3099*0dc2366fSVenugopal Iyer uint_t wldp_length, void *wldp_buf)
3100bcb5c89dSSowmini Varadhan {
3101bcb5c89dSSowmini Varadhan int err = 0;
3102bcb5c89dSSowmini Varadhan iwk_sc_t *sc = (iwk_sc_t *)arg;
3103bcb5c89dSSowmini Varadhan
3104bcb5c89dSSowmini Varadhan err = ieee80211_getprop(&sc->sc_ic, pr_name, wldp_pr_num,
3105*0dc2366fSVenugopal Iyer wldp_length, wldp_buf);
3106bcb5c89dSSowmini Varadhan
3107bcb5c89dSSowmini Varadhan return (err);
3108bcb5c89dSSowmini Varadhan }
3109*0dc2366fSVenugopal Iyer
3110bcb5c89dSSowmini Varadhan static int
iwk_m_setprop(void * arg,const char * pr_name,mac_prop_id_t wldp_pr_num,uint_t wldp_length,const void * wldp_buf)3111bcb5c89dSSowmini Varadhan iwk_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
3112bcb5c89dSSowmini Varadhan uint_t wldp_length, const void *wldp_buf)
3113bcb5c89dSSowmini Varadhan {
3114bcb5c89dSSowmini Varadhan int err;
3115bcb5c89dSSowmini Varadhan iwk_sc_t *sc = (iwk_sc_t *)arg;
3116bcb5c89dSSowmini Varadhan ieee80211com_t *ic = &sc->sc_ic;
3117bcb5c89dSSowmini Varadhan
3118bcb5c89dSSowmini Varadhan err = ieee80211_setprop(ic, pr_name, wldp_pr_num, wldp_length,
3119bcb5c89dSSowmini Varadhan wldp_buf);
3120bcb5c89dSSowmini Varadhan
3121bcb5c89dSSowmini Varadhan if (err == ENETRESET) {
3122bcb5c89dSSowmini Varadhan if (ic->ic_des_esslen) {
3123c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (sc->sc_flags & IWK_F_RUNNING) {
3124c50ced99Spengcheng chen - Sun Microsystems - Beijing China iwk_m_stop(sc);
3125c50ced99Spengcheng chen - Sun Microsystems - Beijing China (void) iwk_m_start(sc);
3126bcb5c89dSSowmini Varadhan (void) ieee80211_new_state(ic,
3127bcb5c89dSSowmini Varadhan IEEE80211_S_SCAN, -1);
3128bcb5c89dSSowmini Varadhan }
3129c50ced99Spengcheng chen - Sun Microsystems - Beijing China }
3130bcb5c89dSSowmini Varadhan err = 0;
3131bcb5c89dSSowmini Varadhan }
3132bcb5c89dSSowmini Varadhan
3133bcb5c89dSSowmini Varadhan return (err);
3134bcb5c89dSSowmini Varadhan }
3135bcb5c89dSSowmini Varadhan
3136*0dc2366fSVenugopal Iyer static void
iwk_m_propinfo(void * arg,const char * pr_name,mac_prop_id_t wldp_pr_num,mac_prop_info_handle_t mph)3137*0dc2366fSVenugopal Iyer iwk_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
3138*0dc2366fSVenugopal Iyer mac_prop_info_handle_t mph)
3139*0dc2366fSVenugopal Iyer {
3140*0dc2366fSVenugopal Iyer iwk_sc_t *sc = (iwk_sc_t *)arg;
3141*0dc2366fSVenugopal Iyer ieee80211com_t *ic = &sc->sc_ic;
3142*0dc2366fSVenugopal Iyer
3143*0dc2366fSVenugopal Iyer ieee80211_propinfo(ic, pr_name, wldp_pr_num, mph);
3144*0dc2366fSVenugopal Iyer }
3145*0dc2366fSVenugopal Iyer
3146c533a883Shx147065 /*ARGSUSED*/
3147c533a883Shx147065 static int
iwk_m_stat(void * arg,uint_t stat,uint64_t * val)3148c533a883Shx147065 iwk_m_stat(void *arg, uint_t stat, uint64_t *val)
3149c533a883Shx147065 {
3150c533a883Shx147065 iwk_sc_t *sc = (iwk_sc_t *)arg;
3151c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic;
3152503bf41cSpengcheng chen - Sun Microsystems - Beijing China ieee80211_node_t *in;
3153c533a883Shx147065
3154c533a883Shx147065 mutex_enter(&sc->sc_glock);
3155c533a883Shx147065 switch (stat) {
3156c533a883Shx147065 case MAC_STAT_IFSPEED:
3157503bf41cSpengcheng chen - Sun Microsystems - Beijing China in = ic->ic_bss;
3158c533a883Shx147065 *val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ?
3159503bf41cSpengcheng chen - Sun Microsystems - Beijing China IEEE80211_RATE(in->in_txrate) :
3160503bf41cSpengcheng chen - Sun Microsystems - Beijing China ic->ic_fixed_rate) / 2 * 1000000;
3161c533a883Shx147065 break;
3162c533a883Shx147065 case MAC_STAT_NOXMTBUF:
3163c533a883Shx147065 *val = sc->sc_tx_nobuf;
3164c533a883Shx147065 break;
3165c533a883Shx147065 case MAC_STAT_NORCVBUF:
3166c533a883Shx147065 *val = sc->sc_rx_nobuf;
3167c533a883Shx147065 break;
3168c533a883Shx147065 case MAC_STAT_IERRORS:
3169c533a883Shx147065 *val = sc->sc_rx_err;
3170c533a883Shx147065 break;
3171c533a883Shx147065 case MAC_STAT_RBYTES:
3172c533a883Shx147065 *val = ic->ic_stats.is_rx_bytes;
3173c533a883Shx147065 break;
3174c533a883Shx147065 case MAC_STAT_IPACKETS:
3175c533a883Shx147065 *val = ic->ic_stats.is_rx_frags;
3176c533a883Shx147065 break;
3177c533a883Shx147065 case MAC_STAT_OBYTES:
3178c533a883Shx147065 *val = ic->ic_stats.is_tx_bytes;
3179c533a883Shx147065 break;
3180c533a883Shx147065 case MAC_STAT_OPACKETS:
3181c533a883Shx147065 *val = ic->ic_stats.is_tx_frags;
3182c533a883Shx147065 break;
3183c533a883Shx147065 case MAC_STAT_OERRORS:
3184c533a883Shx147065 case WIFI_STAT_TX_FAILED:
3185c533a883Shx147065 *val = sc->sc_tx_err;
3186c533a883Shx147065 break;
3187c533a883Shx147065 case WIFI_STAT_TX_RETRANS:
3188c533a883Shx147065 *val = sc->sc_tx_retries;
3189c533a883Shx147065 break;
3190c533a883Shx147065 case WIFI_STAT_FCS_ERRORS:
3191c533a883Shx147065 case WIFI_STAT_WEP_ERRORS:
3192c533a883Shx147065 case WIFI_STAT_TX_FRAGS:
3193c533a883Shx147065 case WIFI_STAT_MCAST_TX:
3194c533a883Shx147065 case WIFI_STAT_RTS_SUCCESS:
3195c533a883Shx147065 case WIFI_STAT_RTS_FAILURE:
3196c533a883Shx147065 case WIFI_STAT_ACK_FAILURE:
3197c533a883Shx147065 case WIFI_STAT_RX_FRAGS:
3198c533a883Shx147065 case WIFI_STAT_MCAST_RX:
3199c533a883Shx147065 case WIFI_STAT_RX_DUPS:
3200c533a883Shx147065 mutex_exit(&sc->sc_glock);
3201c533a883Shx147065 return (ieee80211_stat(ic, stat, val));
3202c533a883Shx147065 default:
3203c533a883Shx147065 mutex_exit(&sc->sc_glock);
3204c533a883Shx147065 return (ENOTSUP);
3205c533a883Shx147065 }
3206c533a883Shx147065 mutex_exit(&sc->sc_glock);
3207c533a883Shx147065
3208c533a883Shx147065 return (IWK_SUCCESS);
3209c533a883Shx147065
3210c533a883Shx147065 }
3211c533a883Shx147065
3212c533a883Shx147065 static int
iwk_m_start(void * arg)3213c533a883Shx147065 iwk_m_start(void *arg)
3214c533a883Shx147065 {
3215c533a883Shx147065 iwk_sc_t *sc = (iwk_sc_t *)arg;
3216c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic;
3217c533a883Shx147065 int err;
3218c533a883Shx147065
3219c533a883Shx147065 err = iwk_init(sc);
3220c533a883Shx147065
3221c533a883Shx147065 if (err != IWK_SUCCESS) {
322243439c96Shx147065 /*
322343439c96Shx147065 * The hw init err(eg. RF is OFF). Return Success to make
322443439c96Shx147065 * the 'plumb' succeed. The iwk_thread() tries to re-init
322543439c96Shx147065 * background.
322643439c96Shx147065 */
322743439c96Shx147065 mutex_enter(&sc->sc_glock);
322843439c96Shx147065 sc->sc_flags |= IWK_F_HW_ERR_RECOVER;
322943439c96Shx147065 mutex_exit(&sc->sc_glock);
323043439c96Shx147065 return (IWK_SUCCESS);
3231c533a883Shx147065 }
323243439c96Shx147065
3233c533a883Shx147065 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
3234c533a883Shx147065
323543439c96Shx147065 mutex_enter(&sc->sc_glock);
323643439c96Shx147065 sc->sc_flags |= IWK_F_RUNNING;
323743439c96Shx147065 mutex_exit(&sc->sc_glock);
323843439c96Shx147065
323943439c96Shx147065 return (IWK_SUCCESS);
3240c533a883Shx147065 }
3241c533a883Shx147065
3242c533a883Shx147065 static void
iwk_m_stop(void * arg)3243c533a883Shx147065 iwk_m_stop(void *arg)
3244c533a883Shx147065 {
3245c533a883Shx147065 iwk_sc_t *sc = (iwk_sc_t *)arg;
3246c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic;
3247c533a883Shx147065
3248c533a883Shx147065 iwk_stop(sc);
3249c533a883Shx147065 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
3250f3c4902cSpengcheng chen - Sun Microsystems - Beijing China ieee80211_stop_watchdog(ic);
3251c533a883Shx147065 mutex_enter(&sc->sc_mt_lock);
3252c533a883Shx147065 sc->sc_flags &= ~IWK_F_HW_ERR_RECOVER;
325343439c96Shx147065 sc->sc_flags &= ~IWK_F_RATE_AUTO_CTL;
3254c533a883Shx147065 mutex_exit(&sc->sc_mt_lock);
325543439c96Shx147065 mutex_enter(&sc->sc_glock);
325643439c96Shx147065 sc->sc_flags &= ~IWK_F_RUNNING;
325743439c96Shx147065 mutex_exit(&sc->sc_glock);
3258c533a883Shx147065 }
3259c533a883Shx147065
3260c533a883Shx147065 /*ARGSUSED*/
3261c533a883Shx147065 static int
iwk_m_unicst(void * arg,const uint8_t * macaddr)3262c533a883Shx147065 iwk_m_unicst(void *arg, const uint8_t *macaddr)
3263c533a883Shx147065 {
3264c533a883Shx147065 iwk_sc_t *sc = (iwk_sc_t *)arg;
3265c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic;
3266c533a883Shx147065 int err;
3267c533a883Shx147065
3268c533a883Shx147065 if (!IEEE80211_ADDR_EQ(ic->ic_macaddr, macaddr)) {
3269c533a883Shx147065 IEEE80211_ADDR_COPY(ic->ic_macaddr, macaddr);
3270c533a883Shx147065 mutex_enter(&sc->sc_glock);
3271c533a883Shx147065 err = iwk_config(sc);
3272c533a883Shx147065 mutex_exit(&sc->sc_glock);
3273c533a883Shx147065 if (err != IWK_SUCCESS) {
3274c533a883Shx147065 cmn_err(CE_WARN,
3275c533a883Shx147065 "iwk_m_unicst(): "
3276c533a883Shx147065 "failed to configure device\n");
3277c533a883Shx147065 goto fail;
3278c533a883Shx147065 }
3279c533a883Shx147065 }
3280c533a883Shx147065 return (IWK_SUCCESS);
3281c533a883Shx147065 fail:
3282c533a883Shx147065 return (err);
3283c533a883Shx147065 }
3284c533a883Shx147065
3285c533a883Shx147065 /*ARGSUSED*/
3286c533a883Shx147065 static int
iwk_m_multicst(void * arg,boolean_t add,const uint8_t * m)3287c533a883Shx147065 iwk_m_multicst(void *arg, boolean_t add, const uint8_t *m)
3288c533a883Shx147065 {
3289c533a883Shx147065 return (IWK_SUCCESS);
3290c533a883Shx147065 }
3291c533a883Shx147065
3292c533a883Shx147065 /*ARGSUSED*/
3293c533a883Shx147065 static int
iwk_m_promisc(void * arg,boolean_t on)3294c533a883Shx147065 iwk_m_promisc(void *arg, boolean_t on)
3295c533a883Shx147065 {
3296c533a883Shx147065 return (IWK_SUCCESS);
3297c533a883Shx147065 }
3298c533a883Shx147065
3299c533a883Shx147065 static void
iwk_thread(iwk_sc_t * sc)3300c533a883Shx147065 iwk_thread(iwk_sc_t *sc)
3301c533a883Shx147065 {
3302c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic;
330343439c96Shx147065 clock_t clk;
3304c533a883Shx147065 int times = 0, err, n = 0, timeout = 0;
330543439c96Shx147065 uint32_t tmp;
3306c533a883Shx147065
3307c533a883Shx147065 mutex_enter(&sc->sc_mt_lock);
3308c533a883Shx147065 while (sc->sc_mf_thread_switch) {
330943439c96Shx147065 tmp = IWK_READ(sc, CSR_GP_CNTRL);
331043439c96Shx147065 if (tmp & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) {
331143439c96Shx147065 sc->sc_flags &= ~IWK_F_RADIO_OFF;
331243439c96Shx147065 } else {
331343439c96Shx147065 sc->sc_flags |= IWK_F_RADIO_OFF;
331443439c96Shx147065 }
331543439c96Shx147065 /*
3316d62cb7ffShx147065 * If in SUSPEND or the RF is OFF, do nothing
331743439c96Shx147065 */
3318d62cb7ffShx147065 if ((sc->sc_flags & IWK_F_SUSPEND) ||
3319d62cb7ffShx147065 (sc->sc_flags & IWK_F_RADIO_OFF)) {
332043439c96Shx147065 mutex_exit(&sc->sc_mt_lock);
332143439c96Shx147065 delay(drv_usectohz(100000));
332243439c96Shx147065 mutex_enter(&sc->sc_mt_lock);
332343439c96Shx147065 continue;
332443439c96Shx147065 }
332543439c96Shx147065
3326c533a883Shx147065 /*
3327c533a883Shx147065 * recovery fatal error
3328c533a883Shx147065 */
3329c533a883Shx147065 if (ic->ic_mach &&
3330c533a883Shx147065 (sc->sc_flags & IWK_F_HW_ERR_RECOVER)) {
3331c533a883Shx147065
3332c533a883Shx147065 IWK_DBG((IWK_DEBUG_FW,
3333c533a883Shx147065 "iwk_thread(): "
3334c533a883Shx147065 "try to recover fatal hw error: %d\n", times++));
3335c533a883Shx147065
3336c533a883Shx147065 iwk_stop(sc);
3337c533a883Shx147065
33386f12def4Spengcheng chen - Sun Microsystems - Beijing China if (IWK_CHK_FAST_RECOVER(sc)) {
33396f12def4Spengcheng chen - Sun Microsystems - Beijing China /* save runtime configuration */
33406f12def4Spengcheng chen - Sun Microsystems - Beijing China bcopy(&sc->sc_config, &sc->sc_config_save,
33416f12def4Spengcheng chen - Sun Microsystems - Beijing China sizeof (sc->sc_config));
33426f12def4Spengcheng chen - Sun Microsystems - Beijing China } else {
3343c533a883Shx147065 mutex_exit(&sc->sc_mt_lock);
3344c50ced99Spengcheng chen - Sun Microsystems - Beijing China ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
3345c533a883Shx147065 delay(drv_usectohz(2000000 + n*500000));
3346c533a883Shx147065 mutex_enter(&sc->sc_mt_lock);
33476f12def4Spengcheng chen - Sun Microsystems - Beijing China }
3348c50ced99Spengcheng chen - Sun Microsystems - Beijing China
3349c533a883Shx147065 err = iwk_init(sc);
3350c533a883Shx147065 if (err != IWK_SUCCESS) {
3351c533a883Shx147065 n++;
3352c533a883Shx147065 if (n < 20)
3353c533a883Shx147065 continue;
3354c533a883Shx147065 }
3355c533a883Shx147065 n = 0;
335643439c96Shx147065 if (!err)
335743439c96Shx147065 sc->sc_flags |= IWK_F_RUNNING;
33586f12def4Spengcheng chen - Sun Microsystems - Beijing China
33596f12def4Spengcheng chen - Sun Microsystems - Beijing China if (!IWK_CHK_FAST_RECOVER(sc) ||
33606f12def4Spengcheng chen - Sun Microsystems - Beijing China iwk_fast_recover(sc) != IWK_SUCCESS) {
3361c533a883Shx147065 sc->sc_flags &= ~IWK_F_HW_ERR_RECOVER;
33626f12def4Spengcheng chen - Sun Microsystems - Beijing China
3363c533a883Shx147065 mutex_exit(&sc->sc_mt_lock);
3364c533a883Shx147065 delay(drv_usectohz(2000000));
3365c533a883Shx147065 if (sc->sc_ostate != IEEE80211_S_INIT)
33666f12def4Spengcheng chen - Sun Microsystems - Beijing China ieee80211_new_state(ic,
33676f12def4Spengcheng chen - Sun Microsystems - Beijing China IEEE80211_S_SCAN, 0);
3368c533a883Shx147065 mutex_enter(&sc->sc_mt_lock);
3369c533a883Shx147065 }
33706f12def4Spengcheng chen - Sun Microsystems - Beijing China }
3371c533a883Shx147065
3372d40f4da4Spengcheng chen - Sun Microsystems - Beijing China if (ic->ic_mach && (sc->sc_flags & IWK_F_LAZY_RESUME)) {
3373d40f4da4Spengcheng chen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_RESUME,
33746f12def4Spengcheng chen - Sun Microsystems - Beijing China "iwk_thread(): lazy resume\n"));
33756f12def4Spengcheng chen - Sun Microsystems - Beijing China
3376d40f4da4Spengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~IWK_F_LAZY_RESUME;
3377d40f4da4Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_mt_lock);
3378d40f4da4Spengcheng chen - Sun Microsystems - Beijing China /*
3379d40f4da4Spengcheng chen - Sun Microsystems - Beijing China * NB: under WPA mode, this call hangs (door problem?)
3380d40f4da4Spengcheng chen - Sun Microsystems - Beijing China * when called in iwk_attach() and iwk_detach() while
3381d40f4da4Spengcheng chen - Sun Microsystems - Beijing China * system is in the procedure of CPR. To be safe, let
3382d40f4da4Spengcheng chen - Sun Microsystems - Beijing China * the thread do this.
3383d40f4da4Spengcheng chen - Sun Microsystems - Beijing China */
3384d40f4da4Spengcheng chen - Sun Microsystems - Beijing China ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
3385d40f4da4Spengcheng chen - Sun Microsystems - Beijing China mutex_enter(&sc->sc_mt_lock);
3386d40f4da4Spengcheng chen - Sun Microsystems - Beijing China }
3387d40f4da4Spengcheng chen - Sun Microsystems - Beijing China
3388c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (ic->ic_mach &&
3389c50ced99Spengcheng chen - Sun Microsystems - Beijing China (sc->sc_flags & IWK_F_SCANNING) && sc->sc_scan_pending) {
3390c50ced99Spengcheng chen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_SCAN,
3391c50ced99Spengcheng chen - Sun Microsystems - Beijing China "iwk_thread(): "
3392c50ced99Spengcheng chen - Sun Microsystems - Beijing China "wait for probe response\n"));
3393c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_scan_pending--;
3394c50ced99Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_mt_lock);
3395c50ced99Spengcheng chen - Sun Microsystems - Beijing China delay(drv_usectohz(200000));
3396d40f4da4Spengcheng chen - Sun Microsystems - Beijing China if (sc->sc_flags & IWK_F_SCANNING)
3397c50ced99Spengcheng chen - Sun Microsystems - Beijing China ieee80211_next_scan(ic);
3398c50ced99Spengcheng chen - Sun Microsystems - Beijing China mutex_enter(&sc->sc_mt_lock);
3399c50ced99Spengcheng chen - Sun Microsystems - Beijing China }
3400c50ced99Spengcheng chen - Sun Microsystems - Beijing China
340143439c96Shx147065 /*
340243439c96Shx147065 * rate ctl
340343439c96Shx147065 */
340443439c96Shx147065 if (ic->ic_mach &&
340543439c96Shx147065 (sc->sc_flags & IWK_F_RATE_AUTO_CTL)) {
340643439c96Shx147065 clk = ddi_get_lbolt();
340743439c96Shx147065 if (clk > sc->sc_clk + drv_usectohz(500000)) {
340843439c96Shx147065 iwk_amrr_timeout(sc);
340943439c96Shx147065 }
341043439c96Shx147065 }
341143439c96Shx147065
3412216e0daaSQuaker Fang if ((ic->ic_state == IEEE80211_S_RUN) &&
3413216e0daaSQuaker Fang (ic->ic_beaconmiss++ > 50)) { /* 5 seconds */
3414216e0daaSQuaker Fang cmn_err(CE_WARN, "iwk: beacon missed for 5 seconds\n");
3415216e0daaSQuaker Fang (void) ieee80211_new_state(ic,
3416216e0daaSQuaker Fang IEEE80211_S_INIT, -1);
3417216e0daaSQuaker Fang }
3418216e0daaSQuaker Fang
3419c533a883Shx147065 mutex_exit(&sc->sc_mt_lock);
3420c533a883Shx147065 delay(drv_usectohz(100000));
3421c533a883Shx147065 mutex_enter(&sc->sc_mt_lock);
3422c533a883Shx147065
3423c533a883Shx147065 if (sc->sc_tx_timer) {
3424c533a883Shx147065 timeout++;
3425c533a883Shx147065 if (timeout == 10) {
3426c533a883Shx147065 sc->sc_tx_timer--;
3427c533a883Shx147065 if (sc->sc_tx_timer == 0) {
3428c533a883Shx147065 sc->sc_flags |= IWK_F_HW_ERR_RECOVER;
3429c533a883Shx147065 sc->sc_ostate = IEEE80211_S_RUN;
3430c533a883Shx147065 IWK_DBG((IWK_DEBUG_FW,
3431c533a883Shx147065 "iwk_thread(): try to recover from"
3432c533a883Shx147065 " 'send fail\n"));
3433c533a883Shx147065 }
3434c533a883Shx147065 timeout = 0;
3435c533a883Shx147065 }
3436c533a883Shx147065 }
3437c533a883Shx147065
3438c533a883Shx147065 }
3439c533a883Shx147065 sc->sc_mf_thread = NULL;
3440c533a883Shx147065 cv_signal(&sc->sc_mt_cv);
3441c533a883Shx147065 mutex_exit(&sc->sc_mt_lock);
3442c533a883Shx147065 }
3443c533a883Shx147065
3444c533a883Shx147065
3445c533a883Shx147065 /*
3446c533a883Shx147065 * Send a command to the firmware.
3447c533a883Shx147065 */
3448c533a883Shx147065 static int
iwk_cmd(iwk_sc_t * sc,int code,const void * buf,int size,int async)3449c533a883Shx147065 iwk_cmd(iwk_sc_t *sc, int code, const void *buf, int size, int async)
3450c533a883Shx147065 {
3451c533a883Shx147065 iwk_tx_ring_t *ring = &sc->sc_txq[IWK_CMD_QUEUE_NUM];
3452c533a883Shx147065 iwk_tx_desc_t *desc;
3453c533a883Shx147065 iwk_cmd_t *cmd;
3454cdc64593Sxinghua wen - Sun Microsystems - Beijing China clock_t clk;
3455c533a883Shx147065
3456c533a883Shx147065 ASSERT(size <= sizeof (cmd->data));
3457c533a883Shx147065 ASSERT(mutex_owned(&sc->sc_glock));
3458c533a883Shx147065
3459c533a883Shx147065 IWK_DBG((IWK_DEBUG_CMD, "iwk_cmd() code[%d]", code));
3460c533a883Shx147065 desc = ring->data[ring->cur].desc;
3461c533a883Shx147065 cmd = ring->data[ring->cur].cmd;
3462c533a883Shx147065
3463c533a883Shx147065 cmd->hdr.type = (uint8_t)code;
3464c533a883Shx147065 cmd->hdr.flags = 0;
3465c533a883Shx147065 cmd->hdr.qid = ring->qid;
3466c533a883Shx147065 cmd->hdr.idx = ring->cur;
3467c533a883Shx147065 (void) memcpy(cmd->data, buf, size);
3468c533a883Shx147065 (void) memset(desc, 0, sizeof (*desc));
3469c533a883Shx147065
3470b510adaeSfei feng - Sun Microsystems - Beijing China desc->val0 = 1 << 24;
3471c533a883Shx147065 desc->pa[0].tb1_addr =
3472c533a883Shx147065 (uint32_t)(ring->data[ring->cur].paddr_cmd & 0xffffffff);
3473c533a883Shx147065 desc->pa[0].val1 = ((4 + size) << 4) & 0xfff0;
3474c533a883Shx147065
3475c533a883Shx147065 /* kick cmd ring XXX */
3476cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_shared->queues_byte_cnt_tbls[ring->qid].
3477cdc64593Sxinghua wen - Sun Microsystems - Beijing China tfd_offset[ring->cur].val = 8;
3478c533a883Shx147065 if (ring->cur < IWK_MAX_WIN_SIZE) {
3479cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_shared->queues_byte_cnt_tbls[ring->qid].
3480cdc64593Sxinghua wen - Sun Microsystems - Beijing China tfd_offset[IWK_QUEUE_SIZE + ring->cur].val = 8;
3481c533a883Shx147065 }
3482c533a883Shx147065 ring->cur = (ring->cur + 1) % ring->count;
3483c533a883Shx147065 IWK_WRITE(sc, HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur);
3484c533a883Shx147065
3485c533a883Shx147065 if (async)
3486c533a883Shx147065 return (IWK_SUCCESS);
3487c533a883Shx147065 else {
3488c533a883Shx147065 sc->sc_flags &= ~IWK_F_CMD_DONE;
3489c533a883Shx147065 clk = ddi_get_lbolt() + drv_usectohz(2000000);
3490c533a883Shx147065 while (!(sc->sc_flags & IWK_F_CMD_DONE)) {
3491cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (cv_timedwait(&sc->sc_cmd_cv, &sc->sc_glock, clk) <
3492cdc64593Sxinghua wen - Sun Microsystems - Beijing China 0)
3493c533a883Shx147065 break;
3494c533a883Shx147065 }
3495c533a883Shx147065 if (sc->sc_flags & IWK_F_CMD_DONE)
3496c533a883Shx147065 return (IWK_SUCCESS);
3497c533a883Shx147065 else
3498c533a883Shx147065 return (IWK_FAIL);
3499c533a883Shx147065 }
3500c533a883Shx147065 }
3501c533a883Shx147065
3502c533a883Shx147065 static void
iwk_set_led(iwk_sc_t * sc,uint8_t id,uint8_t off,uint8_t on)3503c533a883Shx147065 iwk_set_led(iwk_sc_t *sc, uint8_t id, uint8_t off, uint8_t on)
3504c533a883Shx147065 {
3505c533a883Shx147065 iwk_led_cmd_t led;
3506c533a883Shx147065
3507c533a883Shx147065 led.interval = LE_32(100000); /* unit: 100ms */
3508c533a883Shx147065 led.id = id;
3509c533a883Shx147065 led.off = off;
3510c533a883Shx147065 led.on = on;
3511c533a883Shx147065
3512c533a883Shx147065 (void) iwk_cmd(sc, REPLY_LEDS_CMD, &led, sizeof (led), 1);
3513c533a883Shx147065 }
3514c533a883Shx147065
3515c533a883Shx147065 static int
iwk_hw_set_before_auth(iwk_sc_t * sc)3516c533a883Shx147065 iwk_hw_set_before_auth(iwk_sc_t *sc)
3517c533a883Shx147065 {
3518c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic;
3519c533a883Shx147065 ieee80211_node_t *in = ic->ic_bss;
3520c533a883Shx147065 iwk_add_sta_t node;
3521c533a883Shx147065 iwk_link_quality_cmd_t link_quality;
3522c533a883Shx147065 struct ieee80211_rateset rs;
3523c533a883Shx147065 uint16_t masks = 0, rate;
3524c533a883Shx147065 int i, err;
3525c533a883Shx147065
3526f3c4902cSpengcheng chen - Sun Microsystems - Beijing China if (in->in_chan == IEEE80211_CHAN_ANYC) {
3527f3c4902cSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_hw_set_before_auth():"
3528f3c4902cSpengcheng chen - Sun Microsystems - Beijing China "channel (%d) isn't in proper range\n",
3529b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(ieee80211_chan2ieee(ic, in->in_chan)));
3530f3c4902cSpengcheng chen - Sun Microsystems - Beijing China return (IWK_FAIL);
3531f3c4902cSpengcheng chen - Sun Microsystems - Beijing China }
3532f3c4902cSpengcheng chen - Sun Microsystems - Beijing China
3533c533a883Shx147065 /* update adapter's configuration according the info of target AP */
3534c533a883Shx147065 IEEE80211_ADDR_COPY(sc->sc_config.bssid, in->in_bssid);
3535b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.chan = LE_16(ieee80211_chan2ieee(ic, in->in_chan));
3536c533a883Shx147065 if (ic->ic_curmode == IEEE80211_MODE_11B) {
3537c533a883Shx147065 sc->sc_config.cck_basic_rates = 0x03;
3538c533a883Shx147065 sc->sc_config.ofdm_basic_rates = 0;
3539c533a883Shx147065 } else if ((in->in_chan != IEEE80211_CHAN_ANYC) &&
3540c533a883Shx147065 (IEEE80211_IS_CHAN_5GHZ(in->in_chan))) {
3541c533a883Shx147065 sc->sc_config.cck_basic_rates = 0;
3542c533a883Shx147065 sc->sc_config.ofdm_basic_rates = 0x15;
3543c533a883Shx147065 } else { /* assume 802.11b/g */
3544c533a883Shx147065 sc->sc_config.cck_basic_rates = 0x0f;
3545c533a883Shx147065 sc->sc_config.ofdm_basic_rates = 0xff;
3546c533a883Shx147065 }
3547c533a883Shx147065
3548c533a883Shx147065 sc->sc_config.flags &= ~LE_32(RXON_FLG_SHORT_PREAMBLE_MSK |
3549c533a883Shx147065 RXON_FLG_SHORT_SLOT_MSK);
3550c533a883Shx147065
3551c533a883Shx147065 if (ic->ic_flags & IEEE80211_F_SHSLOT)
3552c533a883Shx147065 sc->sc_config.flags |= LE_32(RXON_FLG_SHORT_SLOT_MSK);
3553c533a883Shx147065 else
3554c533a883Shx147065 sc->sc_config.flags &= LE_32(~RXON_FLG_SHORT_SLOT_MSK);
3555c533a883Shx147065
3556c533a883Shx147065 if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
3557c533a883Shx147065 sc->sc_config.flags |= LE_32(RXON_FLG_SHORT_PREAMBLE_MSK);
3558c533a883Shx147065 else
3559c533a883Shx147065 sc->sc_config.flags &= LE_32(~RXON_FLG_SHORT_PREAMBLE_MSK);
3560c533a883Shx147065
3561c533a883Shx147065 IWK_DBG((IWK_DEBUG_80211, "config chan %d flags %x "
3562c533a883Shx147065 "filter_flags %x cck %x ofdm %x"
3563c533a883Shx147065 " bssid:%02x:%02x:%02x:%02x:%02x:%2x\n",
3564b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(sc->sc_config.chan), LE_32(sc->sc_config.flags),
3565b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(sc->sc_config.filter_flags),
3566c533a883Shx147065 sc->sc_config.cck_basic_rates, sc->sc_config.ofdm_basic_rates,
3567c533a883Shx147065 sc->sc_config.bssid[0], sc->sc_config.bssid[1],
3568c533a883Shx147065 sc->sc_config.bssid[2], sc->sc_config.bssid[3],
3569c533a883Shx147065 sc->sc_config.bssid[4], sc->sc_config.bssid[5]));
3570c533a883Shx147065 err = iwk_cmd(sc, REPLY_RXON, &sc->sc_config,
3571c533a883Shx147065 sizeof (iwk_rxon_cmd_t), 1);
3572c533a883Shx147065 if (err != IWK_SUCCESS) {
3573c533a883Shx147065 cmn_err(CE_WARN, "iwk_hw_set_before_auth():"
3574c533a883Shx147065 " failed to config chan%d\n",
3575c533a883Shx147065 sc->sc_config.chan);
3576c533a883Shx147065 return (err);
3577c533a883Shx147065 }
3578c533a883Shx147065
3579cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* obtain current temperature of chipset */
3580cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_tempera = iwk_curr_tempera(sc);
3581cdc64593Sxinghua wen - Sun Microsystems - Beijing China
3582cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* make Tx power calibration to determine the gains of DSP and radio */
3583cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = iwk_tx_power_calibration(sc);
3584cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (err) {
3585c533a883Shx147065 cmn_err(CE_WARN, "iwk_hw_set_before_auth():"
3586cdc64593Sxinghua wen - Sun Microsystems - Beijing China "failed to set tx power table\n");
3587c533a883Shx147065 return (err);
3588c533a883Shx147065 }
3589c533a883Shx147065
3590c533a883Shx147065 /* add default AP node */
3591c533a883Shx147065 (void) memset(&node, 0, sizeof (node));
3592c533a883Shx147065 IEEE80211_ADDR_COPY(node.bssid, in->in_bssid);
3593c533a883Shx147065 node.id = IWK_AP_ID;
3594c533a883Shx147065 err = iwk_cmd(sc, REPLY_ADD_STA, &node, sizeof (node), 1);
3595c533a883Shx147065 if (err != IWK_SUCCESS) {
3596c533a883Shx147065 cmn_err(CE_WARN, "iwk_hw_set_before_auth(): "
3597c533a883Shx147065 "failed to add BSS node\n");
3598c533a883Shx147065 return (err);
3599c533a883Shx147065 }
3600c533a883Shx147065
360119d332feSfei feng - Sun Microsystems - Beijing China /* TX_LINK_QUALITY cmd */
3602c533a883Shx147065 (void) memset(&link_quality, 0, sizeof (link_quality));
3603c533a883Shx147065 rs = ic->ic_sup_rates[ieee80211_chan2mode(ic, ic->ic_curchan)];
3604c533a883Shx147065 for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
3605c533a883Shx147065 if (i < rs.ir_nrates)
3606c533a883Shx147065 rate = rs.ir_rates[rs.ir_nrates - i];
3607c533a883Shx147065 else
3608c533a883Shx147065 rate = 2;
3609c533a883Shx147065 if (rate == 2 || rate == 4 || rate == 11 || rate == 22)
3610c533a883Shx147065 masks |= RATE_MCS_CCK_MSK;
3611c533a883Shx147065 masks |= RATE_MCS_ANT_B_MSK;
3612c533a883Shx147065 masks &= ~RATE_MCS_ANT_A_MSK;
3613c533a883Shx147065 link_quality.rate_n_flags[i] =
3614b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(iwk_rate_to_plcp(rate) | masks);
3615c533a883Shx147065 }
3616c533a883Shx147065
3617c533a883Shx147065 link_quality.general_params.single_stream_ant_msk = 2;
3618c533a883Shx147065 link_quality.general_params.dual_stream_ant_msk = 3;
3619c533a883Shx147065 link_quality.agg_params.agg_dis_start_th = 3;
3620c533a883Shx147065 link_quality.agg_params.agg_time_limit = LE_16(4000);
3621c533a883Shx147065 link_quality.sta_id = IWK_AP_ID;
3622c533a883Shx147065 err = iwk_cmd(sc, REPLY_TX_LINK_QUALITY_CMD, &link_quality,
3623c533a883Shx147065 sizeof (link_quality), 1);
3624c533a883Shx147065 if (err != IWK_SUCCESS) {
3625c533a883Shx147065 cmn_err(CE_WARN, "iwk_hw_set_before_auth(): "
3626c533a883Shx147065 "failed to config link quality table\n");
3627c533a883Shx147065 return (err);
3628c533a883Shx147065 }
3629c533a883Shx147065
3630c533a883Shx147065 return (IWK_SUCCESS);
3631c533a883Shx147065 }
3632c533a883Shx147065
3633c533a883Shx147065 /*
3634c533a883Shx147065 * Send a scan request(assembly scan cmd) to the firmware.
3635c533a883Shx147065 */
3636c533a883Shx147065 static int
iwk_scan(iwk_sc_t * sc)3637c533a883Shx147065 iwk_scan(iwk_sc_t *sc)
3638c533a883Shx147065 {
3639c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic;
3640c533a883Shx147065 iwk_tx_ring_t *ring = &sc->sc_txq[IWK_CMD_QUEUE_NUM];
3641c533a883Shx147065 iwk_tx_desc_t *desc;
3642c533a883Shx147065 iwk_tx_data_t *data;
3643c533a883Shx147065 iwk_cmd_t *cmd;
3644c533a883Shx147065 iwk_scan_hdr_t *hdr;
3645c533a883Shx147065 iwk_scan_chan_t *chan;
3646c533a883Shx147065 struct ieee80211_frame *wh;
3647c533a883Shx147065 ieee80211_node_t *in = ic->ic_bss;
3648c50ced99Spengcheng chen - Sun Microsystems - Beijing China uint8_t essid[IEEE80211_NWID_LEN+1];
3649c533a883Shx147065 struct ieee80211_rateset *rs;
3650c533a883Shx147065 enum ieee80211_phymode mode;
3651c533a883Shx147065 uint8_t *frm;
3652c533a883Shx147065 int i, pktlen, nrates;
3653c533a883Shx147065
3654c533a883Shx147065 data = &ring->data[ring->cur];
3655c533a883Shx147065 desc = data->desc;
3656c533a883Shx147065 cmd = (iwk_cmd_t *)data->dma_data.mem_va;
3657c533a883Shx147065
3658c533a883Shx147065 cmd->hdr.type = REPLY_SCAN_CMD;
3659c533a883Shx147065 cmd->hdr.flags = 0;
3660c533a883Shx147065 cmd->hdr.qid = ring->qid;
3661c533a883Shx147065 cmd->hdr.idx = ring->cur | 0x40;
3662c533a883Shx147065
3663c533a883Shx147065 hdr = (iwk_scan_hdr_t *)cmd->data;
3664c533a883Shx147065 (void) memset(hdr, 0, sizeof (iwk_scan_hdr_t));
3665c50ced99Spengcheng chen - Sun Microsystems - Beijing China hdr->nchan = 1;
3666c50ced99Spengcheng chen - Sun Microsystems - Beijing China hdr->quiet_time = LE_16(50);
3667c533a883Shx147065 hdr->quiet_plcp_th = LE_16(1);
3668c533a883Shx147065
3669b510adaeSfei feng - Sun Microsystems - Beijing China hdr->flags = LE_32(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK);
3670b510adaeSfei feng - Sun Microsystems - Beijing China hdr->rx_chain = LE_16(RXON_RX_CHAIN_DRIVER_FORCE_MSK |
3671b510adaeSfei feng - Sun Microsystems - Beijing China (0x7 << RXON_RX_CHAIN_VALID_POS) |
3672c533a883Shx147065 (0x6 << RXON_RX_CHAIN_FORCE_SEL_POS) |
3673c533a883Shx147065 (0x7 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS));
3674c533a883Shx147065
3675b510adaeSfei feng - Sun Microsystems - Beijing China hdr->tx_cmd.tx_flags = LE_32(TX_CMD_FLG_SEQ_CTL_MSK);
3676c533a883Shx147065 hdr->tx_cmd.sta_id = IWK_BROADCAST_ID;
3677b510adaeSfei feng - Sun Microsystems - Beijing China hdr->tx_cmd.stop_time.life_time = LE_32(0xffffffff);
3678b510adaeSfei feng - Sun Microsystems - Beijing China hdr->tx_cmd.tx_flags |= LE_32(0x200);
3679b510adaeSfei feng - Sun Microsystems - Beijing China hdr->tx_cmd.rate.r.rate_n_flags = LE_32(iwk_rate_to_plcp(2));
3680c533a883Shx147065 hdr->tx_cmd.rate.r.rate_n_flags |=
3681b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(RATE_MCS_ANT_B_MSK|RATE_MCS_CCK_MSK);
3682c533a883Shx147065 hdr->direct_scan[0].len = ic->ic_des_esslen;
3683c533a883Shx147065 hdr->direct_scan[0].id = IEEE80211_ELEMID_SSID;
3684c533a883Shx147065
3685c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (ic->ic_des_esslen) {
3686c50ced99Spengcheng chen - Sun Microsystems - Beijing China bcopy(ic->ic_des_essid, essid, ic->ic_des_esslen);
3687c50ced99Spengcheng chen - Sun Microsystems - Beijing China essid[ic->ic_des_esslen] = '\0';
3688c50ced99Spengcheng chen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_SCAN, "directed scan %s\n", essid));
3689c50ced99Spengcheng chen - Sun Microsystems - Beijing China
3690c533a883Shx147065 bcopy(ic->ic_des_essid, hdr->direct_scan[0].ssid,
3691c533a883Shx147065 ic->ic_des_esslen);
3692c50ced99Spengcheng chen - Sun Microsystems - Beijing China } else {
3693c533a883Shx147065 bzero(hdr->direct_scan[0].ssid,
3694c533a883Shx147065 sizeof (hdr->direct_scan[0].ssid));
3695c50ced99Spengcheng chen - Sun Microsystems - Beijing China }
3696c533a883Shx147065 /*
3697c533a883Shx147065 * a probe request frame is required after the REPLY_SCAN_CMD
3698c533a883Shx147065 */
3699c533a883Shx147065 wh = (struct ieee80211_frame *)(hdr + 1);
3700c533a883Shx147065 wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
3701c533a883Shx147065 IEEE80211_FC0_SUBTYPE_PROBE_REQ;
3702c533a883Shx147065 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
3703c533a883Shx147065 (void) memset(wh->i_addr1, 0xff, 6);
3704c533a883Shx147065 IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_macaddr);
3705c533a883Shx147065 (void) memset(wh->i_addr3, 0xff, 6);
3706c533a883Shx147065 *(uint16_t *)&wh->i_dur[0] = 0;
3707c533a883Shx147065 *(uint16_t *)&wh->i_seq[0] = 0;
3708c533a883Shx147065
3709c533a883Shx147065 frm = (uint8_t *)(wh + 1);
3710c533a883Shx147065
3711c533a883Shx147065 /* essid IE */
3712c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (in->in_esslen) {
3713c50ced99Spengcheng chen - Sun Microsystems - Beijing China bcopy(in->in_essid, essid, in->in_esslen);
3714c50ced99Spengcheng chen - Sun Microsystems - Beijing China essid[in->in_esslen] = '\0';
3715c50ced99Spengcheng chen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_SCAN, "probe with ESSID %s\n",
3716c50ced99Spengcheng chen - Sun Microsystems - Beijing China essid));
3717c50ced99Spengcheng chen - Sun Microsystems - Beijing China }
3718c533a883Shx147065 *frm++ = IEEE80211_ELEMID_SSID;
3719c533a883Shx147065 *frm++ = in->in_esslen;
3720c533a883Shx147065 (void) memcpy(frm, in->in_essid, in->in_esslen);
3721c533a883Shx147065 frm += in->in_esslen;
3722c533a883Shx147065
3723c533a883Shx147065 mode = ieee80211_chan2mode(ic, ic->ic_curchan);
3724c533a883Shx147065 rs = &ic->ic_sup_rates[mode];
3725c533a883Shx147065
3726c533a883Shx147065 /* supported rates IE */
3727c533a883Shx147065 *frm++ = IEEE80211_ELEMID_RATES;
3728c533a883Shx147065 nrates = rs->ir_nrates;
3729c533a883Shx147065 if (nrates > IEEE80211_RATE_SIZE)
3730c533a883Shx147065 nrates = IEEE80211_RATE_SIZE;
3731c533a883Shx147065 *frm++ = (uint8_t)nrates;
3732c533a883Shx147065 (void) memcpy(frm, rs->ir_rates, nrates);
3733c533a883Shx147065 frm += nrates;
3734c533a883Shx147065
3735c533a883Shx147065 /* supported xrates IE */
3736c533a883Shx147065 if (rs->ir_nrates > IEEE80211_RATE_SIZE) {
3737c533a883Shx147065 nrates = rs->ir_nrates - IEEE80211_RATE_SIZE;
3738c533a883Shx147065 *frm++ = IEEE80211_ELEMID_XRATES;
3739c533a883Shx147065 *frm++ = (uint8_t)nrates;
3740c533a883Shx147065 (void) memcpy(frm, rs->ir_rates + IEEE80211_RATE_SIZE, nrates);
3741c533a883Shx147065 frm += nrates;
3742c533a883Shx147065 }
3743c533a883Shx147065
3744c533a883Shx147065 /* optionnal IE (usually for wpa) */
3745c533a883Shx147065 if (ic->ic_opt_ie != NULL) {
3746c533a883Shx147065 (void) memcpy(frm, ic->ic_opt_ie, ic->ic_opt_ie_len);
3747c533a883Shx147065 frm += ic->ic_opt_ie_len;
3748c533a883Shx147065 }
3749c533a883Shx147065
3750c533a883Shx147065 /* setup length of probe request */
3751ff3124efSff224033 hdr->tx_cmd.len = LE_16(_PTRDIFF(frm, wh));
3752b510adaeSfei feng - Sun Microsystems - Beijing China hdr->len = LE_16(hdr->nchan * sizeof (iwk_scan_chan_t) +
3753b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(hdr->tx_cmd.len) + sizeof (iwk_scan_hdr_t));
3754c533a883Shx147065
3755c533a883Shx147065 /*
3756c533a883Shx147065 * the attribute of the scan channels are required after the probe
3757c533a883Shx147065 * request frame.
3758c533a883Shx147065 */
3759c533a883Shx147065 chan = (iwk_scan_chan_t *)frm;
3760c533a883Shx147065 for (i = 1; i <= hdr->nchan; i++, chan++) {
3761c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (ic->ic_des_esslen) {
3762c533a883Shx147065 chan->type = 3;
3763c50ced99Spengcheng chen - Sun Microsystems - Beijing China } else {
3764c50ced99Spengcheng chen - Sun Microsystems - Beijing China chan->type = 1;
3765c50ced99Spengcheng chen - Sun Microsystems - Beijing China }
3766c50ced99Spengcheng chen - Sun Microsystems - Beijing China
3767c50ced99Spengcheng chen - Sun Microsystems - Beijing China chan->chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
3768c533a883Shx147065 chan->tpc.tx_gain = 0x3f;
3769c533a883Shx147065 chan->tpc.dsp_atten = 110;
3770c50ced99Spengcheng chen - Sun Microsystems - Beijing China chan->active_dwell = LE_16(50);
3771c533a883Shx147065 chan->passive_dwell = LE_16(120);
3772c533a883Shx147065
3773c533a883Shx147065 frm += sizeof (iwk_scan_chan_t);
3774c533a883Shx147065 }
3775c533a883Shx147065
3776ff3124efSff224033 pktlen = _PTRDIFF(frm, cmd);
3777c533a883Shx147065
3778c533a883Shx147065 (void) memset(desc, 0, sizeof (*desc));
3779b510adaeSfei feng - Sun Microsystems - Beijing China desc->val0 = 1 << 24;
3780c533a883Shx147065 desc->pa[0].tb1_addr =
3781c533a883Shx147065 (uint32_t)(data->dma_data.cookie.dmac_address & 0xffffffff);
3782c533a883Shx147065 desc->pa[0].val1 = (pktlen << 4) & 0xfff0;
3783c533a883Shx147065
3784c533a883Shx147065 /*
3785c533a883Shx147065 * maybe for cmd, filling the byte cnt table is not necessary.
3786c533a883Shx147065 * anyway, we fill it here.
3787c533a883Shx147065 */
3788cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_shared->queues_byte_cnt_tbls[ring->qid].
3789cdc64593Sxinghua wen - Sun Microsystems - Beijing China tfd_offset[ring->cur].val = 8;
3790c533a883Shx147065 if (ring->cur < IWK_MAX_WIN_SIZE) {
3791cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_shared->queues_byte_cnt_tbls[ring->qid].
3792cdc64593Sxinghua wen - Sun Microsystems - Beijing China tfd_offset[IWK_QUEUE_SIZE + ring->cur].val = 8;
3793c533a883Shx147065 }
379443439c96Shx147065
3795c533a883Shx147065 /* kick cmd ring */
3796c533a883Shx147065 ring->cur = (ring->cur + 1) % ring->count;
3797c533a883Shx147065 IWK_WRITE(sc, HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur);
3798c533a883Shx147065
3799c533a883Shx147065 return (IWK_SUCCESS);
3800c533a883Shx147065 }
3801c533a883Shx147065
3802c533a883Shx147065 static int
iwk_config(iwk_sc_t * sc)3803c533a883Shx147065 iwk_config(iwk_sc_t *sc)
3804c533a883Shx147065 {
3805c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic;
3806c533a883Shx147065 iwk_powertable_cmd_t powertable;
3807c533a883Shx147065 iwk_bt_cmd_t bt;
3808c533a883Shx147065 iwk_add_sta_t node;
3809c533a883Shx147065 iwk_link_quality_cmd_t link_quality;
3810c533a883Shx147065 int i, err;
3811c533a883Shx147065 uint16_t masks = 0;
3812c533a883Shx147065
3813c533a883Shx147065 /*
3814c533a883Shx147065 * set power mode. Disable power management at present, do it later
3815c533a883Shx147065 */
3816c533a883Shx147065 (void) memset(&powertable, 0, sizeof (powertable));
3817c533a883Shx147065 powertable.flags = LE_16(0x8);
3818c533a883Shx147065 err = iwk_cmd(sc, POWER_TABLE_CMD, &powertable,
3819c533a883Shx147065 sizeof (powertable), 0);
3820c533a883Shx147065 if (err != IWK_SUCCESS) {
3821c533a883Shx147065 cmn_err(CE_WARN, "iwk_config(): failed to set power mode\n");
3822c533a883Shx147065 return (err);
3823c533a883Shx147065 }
3824c533a883Shx147065
3825c533a883Shx147065 /* configure bt coexistence */
3826c533a883Shx147065 (void) memset(&bt, 0, sizeof (bt));
3827c533a883Shx147065 bt.flags = 3;
3828c533a883Shx147065 bt.lead_time = 0xaa;
3829c533a883Shx147065 bt.max_kill = 1;
3830c533a883Shx147065 err = iwk_cmd(sc, REPLY_BT_CONFIG, &bt,
3831c533a883Shx147065 sizeof (bt), 0);
3832c533a883Shx147065 if (err != IWK_SUCCESS) {
3833c533a883Shx147065 cmn_err(CE_WARN,
3834c533a883Shx147065 "iwk_config(): "
3835c533a883Shx147065 "failed to configurate bt coexistence\n");
3836c533a883Shx147065 return (err);
3837c533a883Shx147065 }
3838c533a883Shx147065
3839c533a883Shx147065 /* configure rxon */
3840c533a883Shx147065 (void) memset(&sc->sc_config, 0, sizeof (iwk_rxon_cmd_t));
3841c533a883Shx147065 IEEE80211_ADDR_COPY(sc->sc_config.node_addr, ic->ic_macaddr);
3842c533a883Shx147065 IEEE80211_ADDR_COPY(sc->sc_config.wlap_bssid, ic->ic_macaddr);
3843b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.chan = LE_16(ieee80211_chan2ieee(ic, ic->ic_curchan));
3844b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags = LE_32(RXON_FLG_TSF2HOST_MSK |
3845cdc64593Sxinghua wen - Sun Microsystems - Beijing China RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_BAND_24G_MSK);
3846b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags &= LE_32(~RXON_FLG_CCK_MSK);
3847c533a883Shx147065 switch (ic->ic_opmode) {
3848c533a883Shx147065 case IEEE80211_M_STA:
3849c533a883Shx147065 sc->sc_config.dev_type = RXON_DEV_TYPE_ESS;
3850c533a883Shx147065 sc->sc_config.filter_flags |= LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
3851c533a883Shx147065 RXON_FILTER_DIS_DECRYPT_MSK |
3852c533a883Shx147065 RXON_FILTER_DIS_GRP_DECRYPT_MSK);
3853c533a883Shx147065 break;
385419d332feSfei feng - Sun Microsystems - Beijing China case IEEE80211_M_IBSS:
3855c533a883Shx147065 case IEEE80211_M_AHDEMO:
3856c533a883Shx147065 sc->sc_config.dev_type = RXON_DEV_TYPE_IBSS;
3857b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags |= LE_32(RXON_FLG_SHORT_PREAMBLE_MSK);
3858cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_config.filter_flags = LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
3859cdc64593Sxinghua wen - Sun Microsystems - Beijing China RXON_FILTER_DIS_DECRYPT_MSK |
3860cdc64593Sxinghua wen - Sun Microsystems - Beijing China RXON_FILTER_DIS_GRP_DECRYPT_MSK);
3861c533a883Shx147065 break;
3862c533a883Shx147065 case IEEE80211_M_HOSTAP:
3863c533a883Shx147065 sc->sc_config.dev_type = RXON_DEV_TYPE_AP;
3864c533a883Shx147065 break;
3865c533a883Shx147065 case IEEE80211_M_MONITOR:
3866c533a883Shx147065 sc->sc_config.dev_type = RXON_DEV_TYPE_SNIFFER;
3867c533a883Shx147065 sc->sc_config.filter_flags |= LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
3868c533a883Shx147065 RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_PROMISC_MSK);
3869c533a883Shx147065 break;
3870c533a883Shx147065 }
3871c533a883Shx147065 sc->sc_config.cck_basic_rates = 0x0f;
3872c533a883Shx147065 sc->sc_config.ofdm_basic_rates = 0xff;
3873c533a883Shx147065
3874c533a883Shx147065 sc->sc_config.ofdm_ht_single_stream_basic_rates = 0xff;
3875c533a883Shx147065 sc->sc_config.ofdm_ht_dual_stream_basic_rates = 0xff;
3876c533a883Shx147065
3877c533a883Shx147065 /* set antenna */
3878c533a883Shx147065
3879b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.rx_chain = LE_16(RXON_RX_CHAIN_DRIVER_FORCE_MSK |
3880b510adaeSfei feng - Sun Microsystems - Beijing China (0x7 << RXON_RX_CHAIN_VALID_POS) |
3881c533a883Shx147065 (0x6 << RXON_RX_CHAIN_FORCE_SEL_POS) |
3882c533a883Shx147065 (0x7 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS));
3883c533a883Shx147065
3884c533a883Shx147065 err = iwk_cmd(sc, REPLY_RXON, &sc->sc_config,
3885c533a883Shx147065 sizeof (iwk_rxon_cmd_t), 0);
3886c533a883Shx147065 if (err != IWK_SUCCESS) {
3887c533a883Shx147065 cmn_err(CE_WARN, "iwk_config(): "
3888c533a883Shx147065 "failed to set configure command\n");
3889c533a883Shx147065 return (err);
3890c533a883Shx147065 }
3891cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* obtain current temperature of chipset */
3892cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_tempera = iwk_curr_tempera(sc);
3893c533a883Shx147065
3894cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* make Tx power calibration to determine the gains of DSP and radio */
3895cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = iwk_tx_power_calibration(sc);
3896cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (err) {
3897cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_config(): "
3898cdc64593Sxinghua wen - Sun Microsystems - Beijing China "failed to set tx power table\n");
3899c533a883Shx147065 return (err);
3900c533a883Shx147065 }
3901c533a883Shx147065
3902c533a883Shx147065 /* add broadcast node so that we can send broadcast frame */
3903c533a883Shx147065 (void) memset(&node, 0, sizeof (node));
3904c533a883Shx147065 (void) memset(node.bssid, 0xff, 6);
3905c533a883Shx147065 node.id = IWK_BROADCAST_ID;
3906c533a883Shx147065 err = iwk_cmd(sc, REPLY_ADD_STA, &node, sizeof (node), 0);
3907c533a883Shx147065 if (err != IWK_SUCCESS) {
3908c533a883Shx147065 cmn_err(CE_WARN, "iwk_config(): "
3909c533a883Shx147065 "failed to add broadcast node\n");
3910c533a883Shx147065 return (err);
3911c533a883Shx147065 }
3912c533a883Shx147065
3913c533a883Shx147065 /* TX_LINK_QUALITY cmd ? */
3914c533a883Shx147065 (void) memset(&link_quality, 0, sizeof (link_quality));
3915c533a883Shx147065 for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
3916c533a883Shx147065 masks |= RATE_MCS_CCK_MSK;
3917c533a883Shx147065 masks |= RATE_MCS_ANT_B_MSK;
3918c533a883Shx147065 masks &= ~RATE_MCS_ANT_A_MSK;
3919b510adaeSfei feng - Sun Microsystems - Beijing China link_quality.rate_n_flags[i] =
3920b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(iwk_rate_to_plcp(2) | masks);
3921c533a883Shx147065 }
3922c533a883Shx147065
3923c533a883Shx147065 link_quality.general_params.single_stream_ant_msk = 2;
3924c533a883Shx147065 link_quality.general_params.dual_stream_ant_msk = 3;
3925c533a883Shx147065 link_quality.agg_params.agg_dis_start_th = 3;
3926c533a883Shx147065 link_quality.agg_params.agg_time_limit = LE_16(4000);
3927c533a883Shx147065 link_quality.sta_id = IWK_BROADCAST_ID;
3928c533a883Shx147065 err = iwk_cmd(sc, REPLY_TX_LINK_QUALITY_CMD, &link_quality,
3929c533a883Shx147065 sizeof (link_quality), 0);
3930c533a883Shx147065 if (err != IWK_SUCCESS) {
3931c533a883Shx147065 cmn_err(CE_WARN, "iwk_config(): "
3932c533a883Shx147065 "failed to config link quality table\n");
3933c533a883Shx147065 return (err);
3934c533a883Shx147065 }
3935c533a883Shx147065
3936c533a883Shx147065 return (IWK_SUCCESS);
3937c533a883Shx147065 }
3938c533a883Shx147065
3939c533a883Shx147065 static void
iwk_stop_master(iwk_sc_t * sc)3940c533a883Shx147065 iwk_stop_master(iwk_sc_t *sc)
3941c533a883Shx147065 {
3942c533a883Shx147065 uint32_t tmp;
3943c533a883Shx147065 int n;
3944c533a883Shx147065
3945c533a883Shx147065 tmp = IWK_READ(sc, CSR_RESET);
3946c533a883Shx147065 IWK_WRITE(sc, CSR_RESET, tmp | CSR_RESET_REG_FLAG_STOP_MASTER);
3947c533a883Shx147065
3948c533a883Shx147065 tmp = IWK_READ(sc, CSR_GP_CNTRL);
3949c533a883Shx147065 if ((tmp & CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE) ==
3950c533a883Shx147065 CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE)
3951c533a883Shx147065 return;
3952c533a883Shx147065
3953c533a883Shx147065 for (n = 0; n < 2000; n++) {
3954c533a883Shx147065 if (IWK_READ(sc, CSR_RESET) &
3955c533a883Shx147065 CSR_RESET_REG_FLAG_MASTER_DISABLED)
3956c533a883Shx147065 break;
3957c533a883Shx147065 DELAY(1000);
3958c533a883Shx147065 }
3959c533a883Shx147065 if (n == 2000)
3960c533a883Shx147065 IWK_DBG((IWK_DEBUG_HW,
3961c533a883Shx147065 "timeout waiting for master stop\n"));
3962c533a883Shx147065 }
3963c533a883Shx147065
3964c533a883Shx147065 static int
iwk_power_up(iwk_sc_t * sc)3965c533a883Shx147065 iwk_power_up(iwk_sc_t *sc)
3966c533a883Shx147065 {
3967c533a883Shx147065 uint32_t tmp;
3968c533a883Shx147065
3969c533a883Shx147065 iwk_mac_access_enter(sc);
3970c533a883Shx147065 tmp = iwk_reg_read(sc, ALM_APMG_PS_CTL);
3971c533a883Shx147065 tmp &= ~APMG_PS_CTRL_REG_MSK_POWER_SRC;
3972c533a883Shx147065 tmp |= APMG_PS_CTRL_REG_VAL_POWER_SRC_VMAIN;
3973c533a883Shx147065 iwk_reg_write(sc, ALM_APMG_PS_CTL, tmp);
3974c533a883Shx147065 iwk_mac_access_exit(sc);
3975c533a883Shx147065
3976c533a883Shx147065 DELAY(5000);
3977c533a883Shx147065 return (IWK_SUCCESS);
3978c533a883Shx147065 }
3979c533a883Shx147065
3980c533a883Shx147065 static int
iwk_preinit(iwk_sc_t * sc)3981c533a883Shx147065 iwk_preinit(iwk_sc_t *sc)
3982c533a883Shx147065 {
3983c533a883Shx147065 uint32_t tmp;
3984c533a883Shx147065 int n;
3985c533a883Shx147065 uint8_t vlink;
3986c533a883Shx147065
3987c533a883Shx147065 /* clear any pending interrupts */
3988c533a883Shx147065 IWK_WRITE(sc, CSR_INT, 0xffffffff);
3989c533a883Shx147065
3990c533a883Shx147065 tmp = IWK_READ(sc, CSR_GIO_CHICKEN_BITS);
3991c533a883Shx147065 IWK_WRITE(sc, CSR_GIO_CHICKEN_BITS,
3992c533a883Shx147065 tmp | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
3993c533a883Shx147065
3994c533a883Shx147065 tmp = IWK_READ(sc, CSR_GP_CNTRL);
3995c533a883Shx147065 IWK_WRITE(sc, CSR_GP_CNTRL, tmp | CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
3996c533a883Shx147065
3997c533a883Shx147065 /* wait for clock ready */
3998c533a883Shx147065 for (n = 0; n < 1000; n++) {
3999c533a883Shx147065 if (IWK_READ(sc, CSR_GP_CNTRL) &
4000c533a883Shx147065 CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY)
4001c533a883Shx147065 break;
4002c533a883Shx147065 DELAY(10);
4003c533a883Shx147065 }
4004c533a883Shx147065 if (n == 1000) {
4005c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN,
4006c50ced99Spengcheng chen - Sun Microsystems - Beijing China "iwk_preinit(): timeout waiting for clock ready\n");
4007c533a883Shx147065 return (ETIMEDOUT);
4008c533a883Shx147065 }
4009c533a883Shx147065 iwk_mac_access_enter(sc);
4010c533a883Shx147065 tmp = iwk_reg_read(sc, APMG_CLK_CTRL_REG);
4011c533a883Shx147065 iwk_reg_write(sc, APMG_CLK_CTRL_REG, tmp |
4012c533a883Shx147065 APMG_CLK_REG_VAL_DMA_CLK_RQT | APMG_CLK_REG_VAL_BSM_CLK_RQT);
4013c533a883Shx147065
4014c533a883Shx147065 DELAY(20);
4015c533a883Shx147065 tmp = iwk_reg_read(sc, ALM_APMG_PCIDEV_STT);
4016c533a883Shx147065 iwk_reg_write(sc, ALM_APMG_PCIDEV_STT, tmp |
4017c533a883Shx147065 APMG_DEV_STATE_REG_VAL_L1_ACTIVE_DISABLE);
4018c533a883Shx147065 iwk_mac_access_exit(sc);
4019c533a883Shx147065
4020c533a883Shx147065 IWK_WRITE(sc, CSR_INT_COALESCING, 512 / 32); /* ??? */
4021c533a883Shx147065
4022c533a883Shx147065 (void) iwk_power_up(sc);
4023c533a883Shx147065
4024c533a883Shx147065 if ((sc->sc_rev & 0x80) == 0x80 && (sc->sc_rev & 0x7f) < 8) {
4025c533a883Shx147065 tmp = ddi_get32(sc->sc_cfg_handle,
4026c533a883Shx147065 (uint32_t *)(sc->sc_cfg_base + 0xe8));
4027c533a883Shx147065 ddi_put32(sc->sc_cfg_handle,
4028c533a883Shx147065 (uint32_t *)(sc->sc_cfg_base + 0xe8),
4029c533a883Shx147065 tmp & ~(1 << 11));
4030c533a883Shx147065 }
4031c533a883Shx147065
4032c533a883Shx147065
4033c533a883Shx147065 vlink = ddi_get8(sc->sc_cfg_handle,
4034c533a883Shx147065 (uint8_t *)(sc->sc_cfg_base + 0xf0));
4035c533a883Shx147065 ddi_put8(sc->sc_cfg_handle, (uint8_t *)(sc->sc_cfg_base + 0xf0),
4036c533a883Shx147065 vlink & ~2);
4037c533a883Shx147065
4038c533a883Shx147065 tmp = IWK_READ(sc, CSR_SW_VER);
4039c533a883Shx147065 tmp |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
4040cdc64593Sxinghua wen - Sun Microsystems - Beijing China CSR_HW_IF_CONFIG_REG_BIT_MAC_SI |
4041cdc64593Sxinghua wen - Sun Microsystems - Beijing China CSR_HW_IF_CONFIG_REG_BIT_KEDRON_R;
4042c533a883Shx147065 IWK_WRITE(sc, CSR_SW_VER, tmp);
4043c533a883Shx147065
4044c533a883Shx147065 /* make sure power supply on each part of the hardware */
4045c533a883Shx147065 iwk_mac_access_enter(sc);
4046c533a883Shx147065 tmp = iwk_reg_read(sc, ALM_APMG_PS_CTL);
4047c533a883Shx147065 tmp |= APMG_PS_CTRL_REG_VAL_ALM_R_RESET_REQ;
4048c533a883Shx147065 iwk_reg_write(sc, ALM_APMG_PS_CTL, tmp);
4049c533a883Shx147065 DELAY(5);
4050c533a883Shx147065 tmp = iwk_reg_read(sc, ALM_APMG_PS_CTL);
4051c533a883Shx147065 tmp &= ~APMG_PS_CTRL_REG_VAL_ALM_R_RESET_REQ;
4052c533a883Shx147065 iwk_reg_write(sc, ALM_APMG_PS_CTL, tmp);
4053c533a883Shx147065 iwk_mac_access_exit(sc);
4054c533a883Shx147065 return (IWK_SUCCESS);
4055c533a883Shx147065 }
4056c533a883Shx147065
4057c533a883Shx147065 /*
4058c533a883Shx147065 * set up semphore flag to own EEPROM
4059c533a883Shx147065 */
iwk_eep_sem_down(iwk_sc_t * sc)4060c533a883Shx147065 static int iwk_eep_sem_down(iwk_sc_t *sc)
4061c533a883Shx147065 {
4062c533a883Shx147065 int count1, count2;
4063c533a883Shx147065 uint32_t tmp;
4064c533a883Shx147065
4065c533a883Shx147065 for (count1 = 0; count1 < 1000; count1++) {
4066c533a883Shx147065 tmp = IWK_READ(sc, CSR_HW_IF_CONFIG_REG);
4067c533a883Shx147065 IWK_WRITE(sc, CSR_HW_IF_CONFIG_REG,
4068c533a883Shx147065 tmp | CSR_HW_IF_CONFIG_REG_EEP_SEM);
4069c533a883Shx147065
4070c533a883Shx147065 for (count2 = 0; count2 < 2; count2++) {
4071c533a883Shx147065 if (IWK_READ(sc, CSR_HW_IF_CONFIG_REG) &
4072c533a883Shx147065 CSR_HW_IF_CONFIG_REG_EEP_SEM)
4073c533a883Shx147065 return (IWK_SUCCESS);
4074c533a883Shx147065 DELAY(10000);
4075c533a883Shx147065 }
4076c533a883Shx147065 }
4077c533a883Shx147065 return (IWK_FAIL);
4078c533a883Shx147065 }
4079c533a883Shx147065
4080c533a883Shx147065 /*
4081c533a883Shx147065 * reset semphore flag to release EEPROM
4082c533a883Shx147065 */
iwk_eep_sem_up(iwk_sc_t * sc)4083c533a883Shx147065 static void iwk_eep_sem_up(iwk_sc_t *sc)
4084c533a883Shx147065 {
4085c533a883Shx147065 uint32_t tmp;
4086c533a883Shx147065
4087c533a883Shx147065 tmp = IWK_READ(sc, CSR_HW_IF_CONFIG_REG);
4088c533a883Shx147065 IWK_WRITE(sc, CSR_HW_IF_CONFIG_REG,
4089c533a883Shx147065 tmp & (~CSR_HW_IF_CONFIG_REG_EEP_SEM));
4090c533a883Shx147065 }
4091c533a883Shx147065
4092c533a883Shx147065 /*
4093c533a883Shx147065 * This function load all infomation in eeprom into iwk_eep
4094c533a883Shx147065 * structure in iwk_sc_t structure
4095c533a883Shx147065 */
iwk_eep_load(iwk_sc_t * sc)4096c533a883Shx147065 static int iwk_eep_load(iwk_sc_t *sc)
4097c533a883Shx147065 {
4098c533a883Shx147065 int i, rr;
4099c533a883Shx147065 uint32_t rv, tmp, eep_gp;
4100c533a883Shx147065 uint16_t addr, eep_sz = sizeof (sc->sc_eep_map);
4101c533a883Shx147065 uint16_t *eep_p = (uint16_t *)&sc->sc_eep_map;
4102c533a883Shx147065
4103c533a883Shx147065 /* read eeprom gp register in CSR */
4104c533a883Shx147065 eep_gp = IWK_READ(sc, CSR_EEPROM_GP);
4105c533a883Shx147065 if ((eep_gp & CSR_EEPROM_GP_VALID_MSK) ==
4106c533a883Shx147065 CSR_EEPROM_GP_BAD_SIGNATURE) {
4107c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "EEPROM not found\n");
4108c533a883Shx147065 return (IWK_FAIL);
4109c533a883Shx147065 }
4110c533a883Shx147065
4111c533a883Shx147065 rr = iwk_eep_sem_down(sc);
4112c533a883Shx147065 if (rr != 0) {
4113c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "failed to own EEPROM\n");
4114c533a883Shx147065 return (IWK_FAIL);
4115c533a883Shx147065 }
4116c533a883Shx147065
4117c533a883Shx147065 for (addr = 0; addr < eep_sz; addr += 2) {
4118c533a883Shx147065 IWK_WRITE(sc, CSR_EEPROM_REG, addr<<1);
4119c533a883Shx147065 tmp = IWK_READ(sc, CSR_EEPROM_REG);
4120c533a883Shx147065 IWK_WRITE(sc, CSR_EEPROM_REG, tmp & ~(0x2));
4121c533a883Shx147065
4122c533a883Shx147065 for (i = 0; i < 10; i++) {
4123c533a883Shx147065 rv = IWK_READ(sc, CSR_EEPROM_REG);
4124c533a883Shx147065 if (rv & 1)
4125c533a883Shx147065 break;
4126c533a883Shx147065 DELAY(10);
4127c533a883Shx147065 }
4128c533a883Shx147065
4129c533a883Shx147065 if (!(rv & 1)) {
4130c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "time out when read EEPROM\n");
4131c533a883Shx147065 iwk_eep_sem_up(sc);
4132c533a883Shx147065 return (IWK_FAIL);
4133c533a883Shx147065 }
4134c533a883Shx147065
4135b510adaeSfei feng - Sun Microsystems - Beijing China eep_p[addr/2] = LE_16(rv >> 16);
4136c533a883Shx147065 }
4137c533a883Shx147065
4138c533a883Shx147065 iwk_eep_sem_up(sc);
4139c533a883Shx147065 return (IWK_SUCCESS);
4140c533a883Shx147065 }
4141c533a883Shx147065
4142c533a883Shx147065 /*
4143c533a883Shx147065 * init mac address in ieee80211com_t struct
4144c533a883Shx147065 */
iwk_get_mac_from_eep(iwk_sc_t * sc)4145c533a883Shx147065 static void iwk_get_mac_from_eep(iwk_sc_t *sc)
4146c533a883Shx147065 {
4147c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic;
4148c533a883Shx147065 struct iwk_eep *ep = &sc->sc_eep_map;
4149c533a883Shx147065
4150c533a883Shx147065 IEEE80211_ADDR_COPY(ic->ic_macaddr, ep->mac_address);
4151c533a883Shx147065
4152c533a883Shx147065 IWK_DBG((IWK_DEBUG_EEPROM, "mac:%2x:%2x:%2x:%2x:%2x:%2x\n",
4153c533a883Shx147065 ic->ic_macaddr[0], ic->ic_macaddr[1], ic->ic_macaddr[2],
4154c533a883Shx147065 ic->ic_macaddr[3], ic->ic_macaddr[4], ic->ic_macaddr[5]));
4155c533a883Shx147065 }
4156c533a883Shx147065
4157c533a883Shx147065 static int
iwk_init(iwk_sc_t * sc)4158c533a883Shx147065 iwk_init(iwk_sc_t *sc)
4159c533a883Shx147065 {
4160c533a883Shx147065 int qid, n, err;
4161c533a883Shx147065 clock_t clk;
416243439c96Shx147065 uint32_t tmp;
4163c533a883Shx147065
4164c533a883Shx147065 mutex_enter(&sc->sc_glock);
4165c533a883Shx147065 sc->sc_flags &= ~IWK_F_FW_INIT;
4166c533a883Shx147065
4167c533a883Shx147065 (void) iwk_preinit(sc);
4168c533a883Shx147065
416943439c96Shx147065 tmp = IWK_READ(sc, CSR_GP_CNTRL);
417043439c96Shx147065 if (!(tmp & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) {
4171b510adaeSfei feng - Sun Microsystems - Beijing China cmn_err(CE_NOTE, "iwk_init(): Radio transmitter is off\n");
417243439c96Shx147065 goto fail1;
417343439c96Shx147065 }
417443439c96Shx147065
4175c533a883Shx147065 /* init Rx ring */
4176c533a883Shx147065 iwk_mac_access_enter(sc);
4177c533a883Shx147065 IWK_WRITE(sc, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
4178c533a883Shx147065
4179c533a883Shx147065 IWK_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
4180c533a883Shx147065 IWK_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
4181c533a883Shx147065 sc->sc_rxq.dma_desc.cookie.dmac_address >> 8);
4182c533a883Shx147065
4183c533a883Shx147065 IWK_WRITE(sc, FH_RSCSR_CHNL0_STTS_WPTR_REG,
4184c533a883Shx147065 ((uint32_t)(sc->sc_dma_sh.cookie.dmac_address +
4185c533a883Shx147065 offsetof(struct iwk_shared, val0)) >> 4));
4186c533a883Shx147065
4187c533a883Shx147065 IWK_WRITE(sc, FH_MEM_RCSR_CHNL0_CONFIG_REG,
4188c533a883Shx147065 FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
4189c533a883Shx147065 FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
4190c533a883Shx147065 IWK_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K |
4191c533a883Shx147065 (RX_QUEUE_SIZE_LOG <<
4192c533a883Shx147065 FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT));
4193c533a883Shx147065 iwk_mac_access_exit(sc);
4194c533a883Shx147065 IWK_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_WPTR_REG,
4195c533a883Shx147065 (RX_QUEUE_SIZE - 1) & ~0x7);
4196c533a883Shx147065
4197c533a883Shx147065 /* init Tx rings */
4198c533a883Shx147065 iwk_mac_access_enter(sc);
4199c533a883Shx147065 iwk_reg_write(sc, SCD_TXFACT, 0);
4200c533a883Shx147065
4201d62cb7ffShx147065 /* keep warm page */
4202c533a883Shx147065 iwk_reg_write(sc, IWK_FH_KW_MEM_ADDR_REG,
4203c533a883Shx147065 sc->sc_dma_kw.cookie.dmac_address >> 4);
4204c533a883Shx147065
4205c533a883Shx147065 for (qid = 0; qid < IWK_NUM_QUEUES; qid++) {
4206c533a883Shx147065 IWK_WRITE(sc, FH_MEM_CBBC_QUEUE(qid),
4207c533a883Shx147065 sc->sc_txq[qid].dma_desc.cookie.dmac_address >> 8);
4208c533a883Shx147065 IWK_WRITE(sc, IWK_FH_TCSR_CHNL_TX_CONFIG_REG(qid),
4209c533a883Shx147065 IWK_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
4210c533a883Shx147065 IWK_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL);
4211c533a883Shx147065 }
4212c533a883Shx147065 iwk_mac_access_exit(sc);
4213c533a883Shx147065
4214c533a883Shx147065 /* clear "radio off" and "disable command" bits */
4215c533a883Shx147065 IWK_WRITE(sc, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
4216c533a883Shx147065 IWK_WRITE(sc, CSR_UCODE_DRV_GP1_CLR,
4217c533a883Shx147065 CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
4218c533a883Shx147065
4219c533a883Shx147065 /* clear any pending interrupts */
4220c533a883Shx147065 IWK_WRITE(sc, CSR_INT, 0xffffffff);
4221c533a883Shx147065
4222c533a883Shx147065 /* enable interrupts */
4223c533a883Shx147065 IWK_WRITE(sc, CSR_INT_MASK, CSR_INI_SET_MASK);
4224c533a883Shx147065
4225c533a883Shx147065 IWK_WRITE(sc, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
4226c533a883Shx147065 IWK_WRITE(sc, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
4227c533a883Shx147065
4228c533a883Shx147065 /*
4229c533a883Shx147065 * backup ucode data part for future use.
4230c533a883Shx147065 */
4231c533a883Shx147065 (void) memcpy(sc->sc_dma_fw_data_bak.mem_va,
4232c533a883Shx147065 sc->sc_dma_fw_data.mem_va,
4233c533a883Shx147065 sc->sc_dma_fw_data.alength);
4234c533a883Shx147065
4235c533a883Shx147065 for (n = 0; n < 2; n++) {
4236c533a883Shx147065 /* load firmware init segment into NIC */
4237c533a883Shx147065 err = iwk_load_firmware(sc);
4238c533a883Shx147065 if (err != IWK_SUCCESS) {
4239c533a883Shx147065 cmn_err(CE_WARN, "iwk_init(): "
4240c533a883Shx147065 "failed to setup boot firmware\n");
4241c533a883Shx147065 continue;
4242c533a883Shx147065 }
4243c533a883Shx147065
4244c533a883Shx147065 /* now press "execute" start running */
4245c533a883Shx147065 IWK_WRITE(sc, CSR_RESET, 0);
4246c533a883Shx147065 break;
4247c533a883Shx147065 }
4248c533a883Shx147065 if (n == 2) {
4249cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_init(): failed to load firmware\n");
4250c533a883Shx147065 goto fail1;
4251c533a883Shx147065 }
4252c533a883Shx147065 /* ..and wait at most one second for adapter to initialize */
4253c533a883Shx147065 clk = ddi_get_lbolt() + drv_usectohz(2000000);
4254c533a883Shx147065 while (!(sc->sc_flags & IWK_F_FW_INIT)) {
4255c533a883Shx147065 if (cv_timedwait(&sc->sc_fw_cv, &sc->sc_glock, clk) < 0)
4256c533a883Shx147065 break;
4257c533a883Shx147065 }
4258c533a883Shx147065 if (!(sc->sc_flags & IWK_F_FW_INIT)) {
4259c533a883Shx147065 cmn_err(CE_WARN,
4260c533a883Shx147065 "iwk_init(): timeout waiting for firmware init\n");
4261c533a883Shx147065 goto fail1;
4262c533a883Shx147065 }
4263c533a883Shx147065
4264c533a883Shx147065 /*
4265c533a883Shx147065 * at this point, the firmware is loaded OK, then config the hardware
4266c533a883Shx147065 * with the ucode API, including rxon, txpower, etc.
4267c533a883Shx147065 */
4268c533a883Shx147065 err = iwk_config(sc);
4269c533a883Shx147065 if (err) {
4270c533a883Shx147065 cmn_err(CE_WARN, "iwk_init(): failed to configure device\n");
4271c533a883Shx147065 goto fail1;
4272c533a883Shx147065 }
4273c533a883Shx147065
4274c533a883Shx147065 /* at this point, hardware may receive beacons :) */
4275c533a883Shx147065 mutex_exit(&sc->sc_glock);
4276c533a883Shx147065 return (IWK_SUCCESS);
4277c533a883Shx147065
4278c533a883Shx147065 fail1:
4279c533a883Shx147065 err = IWK_FAIL;
4280c533a883Shx147065 mutex_exit(&sc->sc_glock);
4281c533a883Shx147065 return (err);
4282c533a883Shx147065 }
4283c533a883Shx147065
4284c533a883Shx147065 static void
iwk_stop(iwk_sc_t * sc)4285c533a883Shx147065 iwk_stop(iwk_sc_t *sc)
4286c533a883Shx147065 {
4287c533a883Shx147065 uint32_t tmp;
4288c533a883Shx147065 int i;
4289c533a883Shx147065
4290d2a61391Spengcheng chen - Sun Microsystems - Beijing China if (!(sc->sc_flags & IWK_F_QUIESCED))
4291c533a883Shx147065 mutex_enter(&sc->sc_glock);
4292c533a883Shx147065
4293c533a883Shx147065 IWK_WRITE(sc, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
4294c533a883Shx147065 /* disable interrupts */
4295c533a883Shx147065 IWK_WRITE(sc, CSR_INT_MASK, 0);
4296c533a883Shx147065 IWK_WRITE(sc, CSR_INT, CSR_INI_SET_MASK);
4297c533a883Shx147065 IWK_WRITE(sc, CSR_FH_INT_STATUS, 0xffffffff);
4298c533a883Shx147065
4299c533a883Shx147065 /* reset all Tx rings */
4300c533a883Shx147065 for (i = 0; i < IWK_NUM_QUEUES; i++)
4301c533a883Shx147065 iwk_reset_tx_ring(sc, &sc->sc_txq[i]);
4302c533a883Shx147065
4303c533a883Shx147065 /* reset Rx ring */
4304c533a883Shx147065 iwk_reset_rx_ring(sc);
4305c533a883Shx147065
4306c533a883Shx147065 iwk_mac_access_enter(sc);
4307c533a883Shx147065 iwk_reg_write(sc, ALM_APMG_CLK_DIS, APMG_CLK_REG_VAL_DMA_CLK_RQT);
4308c533a883Shx147065 iwk_mac_access_exit(sc);
4309c533a883Shx147065
4310c533a883Shx147065 DELAY(5);
4311c533a883Shx147065
4312c533a883Shx147065 iwk_stop_master(sc);
4313c533a883Shx147065
4314c533a883Shx147065 sc->sc_tx_timer = 0;
4315f3c4902cSpengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~IWK_F_SCANNING;
4316f3c4902cSpengcheng chen - Sun Microsystems - Beijing China sc->sc_scan_pending = 0;
4317f3c4902cSpengcheng chen - Sun Microsystems - Beijing China
4318c533a883Shx147065 tmp = IWK_READ(sc, CSR_RESET);
4319c533a883Shx147065 IWK_WRITE(sc, CSR_RESET, tmp | CSR_RESET_REG_FLAG_SW_RESET);
4320d2a61391Spengcheng chen - Sun Microsystems - Beijing China
4321d2a61391Spengcheng chen - Sun Microsystems - Beijing China if (!(sc->sc_flags & IWK_F_QUIESCED))
4322c533a883Shx147065 mutex_exit(&sc->sc_glock);
4323c533a883Shx147065 }
432443439c96Shx147065
432543439c96Shx147065 /*
432643439c96Shx147065 * Naive implementation of the Adaptive Multi Rate Retry algorithm:
432743439c96Shx147065 * "IEEE 802.11 Rate Adaptation: A Practical Approach"
432843439c96Shx147065 * Mathieu Lacage, Hossein Manshaei, Thierry Turletti
432943439c96Shx147065 * INRIA Sophia - Projet Planete
433043439c96Shx147065 * http://www-sop.inria.fr/rapports/sophia/RR-5208.html
433143439c96Shx147065 */
433243439c96Shx147065 #define is_success(amrr) \
433343439c96Shx147065 ((amrr)->retrycnt < (amrr)->txcnt / 10)
433443439c96Shx147065 #define is_failure(amrr) \
433543439c96Shx147065 ((amrr)->retrycnt > (amrr)->txcnt / 3)
433643439c96Shx147065 #define is_enough(amrr) \
433743439c96Shx147065 ((amrr)->txcnt > 100)
433843439c96Shx147065 #define is_min_rate(in) \
433943439c96Shx147065 ((in)->in_txrate == 0)
434043439c96Shx147065 #define is_max_rate(in) \
434143439c96Shx147065 ((in)->in_txrate == (in)->in_rates.ir_nrates - 1)
434243439c96Shx147065 #define increase_rate(in) \
434343439c96Shx147065 ((in)->in_txrate++)
434443439c96Shx147065 #define decrease_rate(in) \
434543439c96Shx147065 ((in)->in_txrate--)
434643439c96Shx147065 #define reset_cnt(amrr) \
434743439c96Shx147065 { (amrr)->txcnt = (amrr)->retrycnt = 0; }
434843439c96Shx147065
434943439c96Shx147065 #define IWK_AMRR_MIN_SUCCESS_THRESHOLD 1
435043439c96Shx147065 #define IWK_AMRR_MAX_SUCCESS_THRESHOLD 15
435143439c96Shx147065
435243439c96Shx147065 static void
iwk_amrr_init(iwk_amrr_t * amrr)435343439c96Shx147065 iwk_amrr_init(iwk_amrr_t *amrr)
435443439c96Shx147065 {
435543439c96Shx147065 amrr->success = 0;
435643439c96Shx147065 amrr->recovery = 0;
435743439c96Shx147065 amrr->txcnt = amrr->retrycnt = 0;
435843439c96Shx147065 amrr->success_threshold = IWK_AMRR_MIN_SUCCESS_THRESHOLD;
435943439c96Shx147065 }
436043439c96Shx147065
436143439c96Shx147065 static void
iwk_amrr_timeout(iwk_sc_t * sc)436243439c96Shx147065 iwk_amrr_timeout(iwk_sc_t *sc)
436343439c96Shx147065 {
436443439c96Shx147065 ieee80211com_t *ic = &sc->sc_ic;
436543439c96Shx147065
436643439c96Shx147065 IWK_DBG((IWK_DEBUG_RATECTL, "iwk_amrr_timeout() enter\n"));
436743439c96Shx147065 if (ic->ic_opmode == IEEE80211_M_STA)
436843439c96Shx147065 iwk_amrr_ratectl(NULL, ic->ic_bss);
436943439c96Shx147065 else
437043439c96Shx147065 ieee80211_iterate_nodes(&ic->ic_sta, iwk_amrr_ratectl, NULL);
437143439c96Shx147065 sc->sc_clk = ddi_get_lbolt();
437243439c96Shx147065 }
437343439c96Shx147065
437443439c96Shx147065 /* ARGSUSED */
437543439c96Shx147065 static void
iwk_amrr_ratectl(void * arg,ieee80211_node_t * in)437643439c96Shx147065 iwk_amrr_ratectl(void *arg, ieee80211_node_t *in)
437743439c96Shx147065 {
437843439c96Shx147065 iwk_amrr_t *amrr = (iwk_amrr_t *)in;
437943439c96Shx147065 int need_change = 0;
438043439c96Shx147065
438143439c96Shx147065 if (is_success(amrr) && is_enough(amrr)) {
438243439c96Shx147065 amrr->success++;
438343439c96Shx147065 if (amrr->success >= amrr->success_threshold &&
438443439c96Shx147065 !is_max_rate(in)) {
438543439c96Shx147065 amrr->recovery = 1;
438643439c96Shx147065 amrr->success = 0;
438743439c96Shx147065 increase_rate(in);
438843439c96Shx147065 IWK_DBG((IWK_DEBUG_RATECTL,
438943439c96Shx147065 "AMRR increasing rate %d (txcnt=%d retrycnt=%d)\n",
439043439c96Shx147065 in->in_txrate, amrr->txcnt, amrr->retrycnt));
439143439c96Shx147065 need_change = 1;
439243439c96Shx147065 } else {
439343439c96Shx147065 amrr->recovery = 0;
439443439c96Shx147065 }
439543439c96Shx147065 } else if (is_failure(amrr)) {
439643439c96Shx147065 amrr->success = 0;
439743439c96Shx147065 if (!is_min_rate(in)) {
439843439c96Shx147065 if (amrr->recovery) {
439943439c96Shx147065 amrr->success_threshold++;
440043439c96Shx147065 if (amrr->success_threshold >
440143439c96Shx147065 IWK_AMRR_MAX_SUCCESS_THRESHOLD)
440243439c96Shx147065 amrr->success_threshold =
440343439c96Shx147065 IWK_AMRR_MAX_SUCCESS_THRESHOLD;
440443439c96Shx147065 } else {
440543439c96Shx147065 amrr->success_threshold =
440643439c96Shx147065 IWK_AMRR_MIN_SUCCESS_THRESHOLD;
440743439c96Shx147065 }
440843439c96Shx147065 decrease_rate(in);
440943439c96Shx147065 IWK_DBG((IWK_DEBUG_RATECTL,
441043439c96Shx147065 "AMRR decreasing rate %d (txcnt=%d retrycnt=%d)\n",
441143439c96Shx147065 in->in_txrate, amrr->txcnt, amrr->retrycnt));
441243439c96Shx147065 need_change = 1;
441343439c96Shx147065 }
441443439c96Shx147065 amrr->recovery = 0; /* paper is incorrect */
441543439c96Shx147065 }
441643439c96Shx147065
441743439c96Shx147065 if (is_enough(amrr) || need_change)
441843439c96Shx147065 reset_cnt(amrr);
441943439c96Shx147065 }
4420cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4421cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
4422cdc64593Sxinghua wen - Sun Microsystems - Beijing China * calculate 4965 chipset's kelvin temperature according to
4423cdc64593Sxinghua wen - Sun Microsystems - Beijing China * the data of init alive and satistics notification.
4424cdc64593Sxinghua wen - Sun Microsystems - Beijing China * The details is described in iwk_calibration.h file
4425cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
iwk_curr_tempera(iwk_sc_t * sc)4426cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int32_t iwk_curr_tempera(iwk_sc_t *sc)
4427cdc64593Sxinghua wen - Sun Microsystems - Beijing China {
4428cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t tempera;
4429cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t r1, r2, r3;
4430cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t r4_u;
4431cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t r4_s;
4432cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4433cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (iwk_is_fat_channel(sc)) {
4434b510adaeSfei feng - Sun Microsystems - Beijing China r1 = (int32_t)LE_32(sc->sc_card_alive_init.therm_r1[1]);
4435b510adaeSfei feng - Sun Microsystems - Beijing China r2 = (int32_t)LE_32(sc->sc_card_alive_init.therm_r2[1]);
4436b510adaeSfei feng - Sun Microsystems - Beijing China r3 = (int32_t)LE_32(sc->sc_card_alive_init.therm_r3[1]);
4437b510adaeSfei feng - Sun Microsystems - Beijing China r4_u = LE_32(sc->sc_card_alive_init.therm_r4[1]);
4438cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
4439b510adaeSfei feng - Sun Microsystems - Beijing China r1 = (int32_t)LE_32(sc->sc_card_alive_init.therm_r1[0]);
4440b510adaeSfei feng - Sun Microsystems - Beijing China r2 = (int32_t)LE_32(sc->sc_card_alive_init.therm_r2[0]);
4441b510adaeSfei feng - Sun Microsystems - Beijing China r3 = (int32_t)LE_32(sc->sc_card_alive_init.therm_r3[0]);
4442b510adaeSfei feng - Sun Microsystems - Beijing China r4_u = LE_32(sc->sc_card_alive_init.therm_r4[0]);
4443cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4444cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4445cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (sc->sc_flags & IWK_F_STATISTICS) {
4446b510adaeSfei feng - Sun Microsystems - Beijing China r4_s = (int32_t)(LE_32(sc->sc_statistics.general.temperature) <<
4447cdc64593Sxinghua wen - Sun Microsystems - Beijing China (31-23)) >> (31-23);
4448cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
4449cdc64593Sxinghua wen - Sun Microsystems - Beijing China r4_s = (int32_t)(r4_u << (31-23)) >> (31-23);
4450cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4451cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4452cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_CALIBRATION, "temperature R[1-4]: %d %d %d %d\n",
4453cdc64593Sxinghua wen - Sun Microsystems - Beijing China r1, r2, r3, r4_s));
4454cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4455cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (r3 == r1) {
4456cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_curr_tempera(): "
4457cdc64593Sxinghua wen - Sun Microsystems - Beijing China "failed to calculate temperature"
4458cdc64593Sxinghua wen - Sun Microsystems - Beijing China "because r3 = r1\n");
4459cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (DDI_FAILURE);
4460cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4461cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4462cdc64593Sxinghua wen - Sun Microsystems - Beijing China tempera = TEMPERATURE_CALIB_A_VAL * (r4_s - r2);
4463cdc64593Sxinghua wen - Sun Microsystems - Beijing China tempera /= (r3 - r1);
4464cdc64593Sxinghua wen - Sun Microsystems - Beijing China tempera = (tempera*97) / 100 + TEMPERATURE_CALIB_KELVIN_OFFSET;
4465cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4466cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_CALIBRATION, "calculated temperature: %dK, %dC\n",
4467cdc64593Sxinghua wen - Sun Microsystems - Beijing China tempera, KELVIN_TO_CELSIUS(tempera)));
4468cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4469cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (tempera);
4470cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4471cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4472cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* Determine whether 4965 is using 2.4 GHz band */
iwk_is_24G_band(iwk_sc_t * sc)4473cdc64593Sxinghua wen - Sun Microsystems - Beijing China static inline int iwk_is_24G_band(iwk_sc_t *sc)
4474cdc64593Sxinghua wen - Sun Microsystems - Beijing China {
4475b510adaeSfei feng - Sun Microsystems - Beijing China return (LE_32(sc->sc_config.flags) & RXON_FLG_BAND_24G_MSK);
4476cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4477cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4478cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* Determine whether 4965 is using fat channel */
iwk_is_fat_channel(iwk_sc_t * sc)4479cdc64593Sxinghua wen - Sun Microsystems - Beijing China static inline int iwk_is_fat_channel(iwk_sc_t *sc)
4480cdc64593Sxinghua wen - Sun Microsystems - Beijing China {
4481b510adaeSfei feng - Sun Microsystems - Beijing China return ((LE_32(sc->sc_config.flags) &
4482b510adaeSfei feng - Sun Microsystems - Beijing China RXON_FLG_CHANNEL_MODE_PURE_40_MSK) ||
4483b510adaeSfei feng - Sun Microsystems - Beijing China (LE_32(sc->sc_config.flags) & RXON_FLG_CHANNEL_MODE_MIXED_MSK));
4484cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4485cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4486cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
4487cdc64593Sxinghua wen - Sun Microsystems - Beijing China * In MIMO mode, determine which group 4965's current channel belong to.
4488cdc64593Sxinghua wen - Sun Microsystems - Beijing China * For more infomation about "channel group",
4489cdc64593Sxinghua wen - Sun Microsystems - Beijing China * please refer to iwk_calibration.h file
4490cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
iwk_txpower_grp(uint16_t channel)4491cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_txpower_grp(uint16_t channel)
4492cdc64593Sxinghua wen - Sun Microsystems - Beijing China {
4493cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (channel >= CALIB_IWK_TX_ATTEN_GR5_FCH &&
4494cdc64593Sxinghua wen - Sun Microsystems - Beijing China channel <= CALIB_IWK_TX_ATTEN_GR5_LCH) {
4495cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (CALIB_CH_GROUP_5);
4496cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4497cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4498cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (channel >= CALIB_IWK_TX_ATTEN_GR1_FCH &&
4499cdc64593Sxinghua wen - Sun Microsystems - Beijing China channel <= CALIB_IWK_TX_ATTEN_GR1_LCH) {
4500cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (CALIB_CH_GROUP_1);
4501cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4502cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4503cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (channel >= CALIB_IWK_TX_ATTEN_GR2_FCH &&
4504cdc64593Sxinghua wen - Sun Microsystems - Beijing China channel <= CALIB_IWK_TX_ATTEN_GR2_LCH) {
4505cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (CALIB_CH_GROUP_2);
4506cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4507cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4508cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (channel >= CALIB_IWK_TX_ATTEN_GR3_FCH &&
4509cdc64593Sxinghua wen - Sun Microsystems - Beijing China channel <= CALIB_IWK_TX_ATTEN_GR3_LCH) {
4510cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (CALIB_CH_GROUP_3);
4511cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4512cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4513cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (channel >= CALIB_IWK_TX_ATTEN_GR4_FCH &&
4514cdc64593Sxinghua wen - Sun Microsystems - Beijing China channel <= CALIB_IWK_TX_ATTEN_GR4_LCH) {
4515cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (CALIB_CH_GROUP_4);
4516cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4517cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4518cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_txpower_grp(): "
4519cdc64593Sxinghua wen - Sun Microsystems - Beijing China "can't find txpower group for channel %d.\n", channel);
4520cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4521cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (DDI_FAILURE);
4522cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4523cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4524cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 2.4 GHz */
4525cdc64593Sxinghua wen - Sun Microsystems - Beijing China static uint16_t iwk_eep_band_1[14] = {
4526cdc64593Sxinghua wen - Sun Microsystems - Beijing China 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
4527cdc64593Sxinghua wen - Sun Microsystems - Beijing China };
4528cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4529cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 5.2 GHz bands */
4530cdc64593Sxinghua wen - Sun Microsystems - Beijing China static uint16_t iwk_eep_band_2[13] = {
4531cdc64593Sxinghua wen - Sun Microsystems - Beijing China 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16
4532cdc64593Sxinghua wen - Sun Microsystems - Beijing China };
4533cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4534cdc64593Sxinghua wen - Sun Microsystems - Beijing China static uint16_t iwk_eep_band_3[12] = {
4535cdc64593Sxinghua wen - Sun Microsystems - Beijing China 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
4536cdc64593Sxinghua wen - Sun Microsystems - Beijing China };
4537cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4538cdc64593Sxinghua wen - Sun Microsystems - Beijing China static uint16_t iwk_eep_band_4[11] = {
4539cdc64593Sxinghua wen - Sun Microsystems - Beijing China 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
4540cdc64593Sxinghua wen - Sun Microsystems - Beijing China };
4541cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4542cdc64593Sxinghua wen - Sun Microsystems - Beijing China static uint16_t iwk_eep_band_5[6] = {
4543cdc64593Sxinghua wen - Sun Microsystems - Beijing China 145, 149, 153, 157, 161, 165
4544cdc64593Sxinghua wen - Sun Microsystems - Beijing China };
4545cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4546cdc64593Sxinghua wen - Sun Microsystems - Beijing China static uint16_t iwk_eep_band_6[7] = {
4547cdc64593Sxinghua wen - Sun Microsystems - Beijing China 1, 2, 3, 4, 5, 6, 7
4548cdc64593Sxinghua wen - Sun Microsystems - Beijing China };
4549cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4550cdc64593Sxinghua wen - Sun Microsystems - Beijing China static uint16_t iwk_eep_band_7[11] = {
4551cdc64593Sxinghua wen - Sun Microsystems - Beijing China 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
4552cdc64593Sxinghua wen - Sun Microsystems - Beijing China };
4553cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4554cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* Get regulatory data from eeprom for a given channel */
iwk_get_eep_channel(iwk_sc_t * sc,uint16_t channel,int is_24G,int is_fat,int is_hi_chan)4555cdc64593Sxinghua wen - Sun Microsystems - Beijing China static struct iwk_eep_channel *iwk_get_eep_channel(iwk_sc_t *sc,
4556cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint16_t channel,
4557cdc64593Sxinghua wen - Sun Microsystems - Beijing China int is_24G, int is_fat, int is_hi_chan)
4558cdc64593Sxinghua wen - Sun Microsystems - Beijing China {
4559cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t i;
4560cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint16_t chan;
4561cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4562cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (is_fat) { /* 11n mode */
4563cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4564cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (is_hi_chan) {
4565cdc64593Sxinghua wen - Sun Microsystems - Beijing China chan = channel - 4;
4566cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
4567cdc64593Sxinghua wen - Sun Microsystems - Beijing China chan = channel;
4568cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4569cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4570cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < 7; i++) {
4571cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (iwk_eep_band_6[i] == chan) {
4572cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (&sc->sc_eep_map.band_24_channels[i]);
4573cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4574cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4575cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < 11; i++) {
4576cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (iwk_eep_band_7[i] == chan) {
4577cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (&sc->sc_eep_map.band_52_channels[i]);
4578cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4579cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4580cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else if (is_24G) { /* 2.4 GHz band */
4581cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < 14; i++) {
4582cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (iwk_eep_band_1[i] == channel) {
4583cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (&sc->sc_eep_map.band_1_channels[i]);
4584cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4585cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4586cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { /* 5 GHz band */
4587cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < 13; i++) {
4588cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (iwk_eep_band_2[i] == channel) {
4589cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (&sc->sc_eep_map.band_2_channels[i]);
4590cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4591cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4592cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < 12; i++) {
4593cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (iwk_eep_band_3[i] == channel) {
4594cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (&sc->sc_eep_map.band_3_channels[i]);
4595cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4596cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4597cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < 11; i++) {
4598cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (iwk_eep_band_4[i] == channel) {
4599cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (&sc->sc_eep_map.band_4_channels[i]);
4600cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4601cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4602cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < 6; i++) {
4603cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (iwk_eep_band_5[i] == channel) {
4604cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (&sc->sc_eep_map.band_5_channels[i]);
4605cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4606cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4607cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4608cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4609cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (NULL);
4610cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4611cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4612cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
4613cdc64593Sxinghua wen - Sun Microsystems - Beijing China * Determine which subband a given channel belongs
4614cdc64593Sxinghua wen - Sun Microsystems - Beijing China * to in 2.4 GHz or 5 GHz band
4615cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
iwk_band_number(iwk_sc_t * sc,uint16_t channel)4616cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int32_t iwk_band_number(iwk_sc_t *sc, uint16_t channel)
4617cdc64593Sxinghua wen - Sun Microsystems - Beijing China {
4618cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t b_n = -1;
4619cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4620cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (b_n = 0; b_n < EEP_TX_POWER_BANDS; b_n++) {
4621cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (0 == sc->sc_eep_map.calib_info.band_info_tbl[b_n].ch_from) {
4622cdc64593Sxinghua wen - Sun Microsystems - Beijing China continue;
4623cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4624cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4625cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((channel >=
4626cdc64593Sxinghua wen - Sun Microsystems - Beijing China (uint16_t)sc->sc_eep_map.calib_info.
4627cdc64593Sxinghua wen - Sun Microsystems - Beijing China band_info_tbl[b_n].ch_from) &&
4628cdc64593Sxinghua wen - Sun Microsystems - Beijing China (channel <=
4629cdc64593Sxinghua wen - Sun Microsystems - Beijing China (uint16_t)sc->sc_eep_map.calib_info.
4630cdc64593Sxinghua wen - Sun Microsystems - Beijing China band_info_tbl[b_n].ch_to)) {
4631cdc64593Sxinghua wen - Sun Microsystems - Beijing China break;
4632cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4633cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4634cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4635cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (b_n);
4636cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4637cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4638cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* Make a special division for interpolation operation */
iwk_division(int32_t num,int32_t denom,int32_t * res)4639cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_division(int32_t num, int32_t denom, int32_t *res)
4640cdc64593Sxinghua wen - Sun Microsystems - Beijing China {
4641cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t sign = 1;
4642cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4643cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (num < 0) {
4644cdc64593Sxinghua wen - Sun Microsystems - Beijing China sign = -sign;
4645cdc64593Sxinghua wen - Sun Microsystems - Beijing China num = -num;
4646cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4647cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4648cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (denom < 0) {
4649cdc64593Sxinghua wen - Sun Microsystems - Beijing China sign = -sign;
4650cdc64593Sxinghua wen - Sun Microsystems - Beijing China denom = -denom;
4651cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4652cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4653cdc64593Sxinghua wen - Sun Microsystems - Beijing China *res = ((num*2 + denom) / (denom*2)) * sign;
4654cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4655cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS);
4656cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4657cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4658cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* Make interpolation operation */
iwk_interpolate_value(int32_t x,int32_t x1,int32_t y1,int32_t x2,int32_t y2)4659cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int32_t iwk_interpolate_value(int32_t x, int32_t x1, int32_t y1,
4660cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t x2, int32_t y2)
4661cdc64593Sxinghua wen - Sun Microsystems - Beijing China {
4662cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t val;
4663cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4664cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (x2 == x1) {
4665cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (y1);
4666cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
4667cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) iwk_division((x2-x)*(y1-y2), (x2-x1), &val);
4668cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (val + y2);
4669cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4670cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4671cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4672cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* Get interpolation measurement data of a given channel for all chains. */
iwk_channel_interpolate(iwk_sc_t * sc,uint16_t channel,struct iwk_eep_calib_channel_info * chan_info)4673cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_channel_interpolate(iwk_sc_t *sc, uint16_t channel,
4674cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_eep_calib_channel_info *chan_info)
4675cdc64593Sxinghua wen - Sun Microsystems - Beijing China {
4676cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t ban_n;
4677cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t ch1_n, ch2_n;
4678cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t c, m;
4679cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_eep_calib_measure *m1_p, *m2_p, *m_p;
4680cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4681cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine subband number */
4682cdc64593Sxinghua wen - Sun Microsystems - Beijing China ban_n = iwk_band_number(sc, channel);
4683cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (ban_n >= EEP_TX_POWER_BANDS) {
4684cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (DDI_FAILURE);
4685cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4686cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4687cdc64593Sxinghua wen - Sun Microsystems - Beijing China ch1_n =
4688cdc64593Sxinghua wen - Sun Microsystems - Beijing China (uint32_t)sc->sc_eep_map.calib_info.band_info_tbl[ban_n].ch1.ch_num;
4689cdc64593Sxinghua wen - Sun Microsystems - Beijing China ch2_n =
4690cdc64593Sxinghua wen - Sun Microsystems - Beijing China (uint32_t)sc->sc_eep_map.calib_info.band_info_tbl[ban_n].ch2.ch_num;
4691cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4692cdc64593Sxinghua wen - Sun Microsystems - Beijing China chan_info->ch_num = (uint8_t)channel; /* given channel number */
4693cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4694cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
4695cdc64593Sxinghua wen - Sun Microsystems - Beijing China * go through all chains on chipset
4696cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
4697cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (c = 0; c < EEP_TX_POWER_TX_CHAINS; c++) {
4698cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
4699cdc64593Sxinghua wen - Sun Microsystems - Beijing China * go through all factory measurements
4700cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
4701cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (m = 0; m < EEP_TX_POWER_MEASUREMENTS; m++) {
4702cdc64593Sxinghua wen - Sun Microsystems - Beijing China m1_p =
4703cdc64593Sxinghua wen - Sun Microsystems - Beijing China &(sc->sc_eep_map.calib_info.
4704cdc64593Sxinghua wen - Sun Microsystems - Beijing China band_info_tbl[ban_n].ch1.measure[c][m]);
4705cdc64593Sxinghua wen - Sun Microsystems - Beijing China m2_p =
4706cdc64593Sxinghua wen - Sun Microsystems - Beijing China &(sc->sc_eep_map.calib_info.band_info_tbl[ban_n].
4707cdc64593Sxinghua wen - Sun Microsystems - Beijing China ch2.measure[c][m]);
4708cdc64593Sxinghua wen - Sun Microsystems - Beijing China m_p = &(chan_info->measure[c][m]);
4709cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4710cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
4711cdc64593Sxinghua wen - Sun Microsystems - Beijing China * make interpolation to get actual
4712cdc64593Sxinghua wen - Sun Microsystems - Beijing China * Tx power for given channel
4713cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
4714cdc64593Sxinghua wen - Sun Microsystems - Beijing China m_p->actual_pow = iwk_interpolate_value(channel,
4715cdc64593Sxinghua wen - Sun Microsystems - Beijing China ch1_n, m1_p->actual_pow,
4716cdc64593Sxinghua wen - Sun Microsystems - Beijing China ch2_n, m2_p->actual_pow);
4717cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4718cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* make interpolation to get index into gain table */
4719cdc64593Sxinghua wen - Sun Microsystems - Beijing China m_p->gain_idx = iwk_interpolate_value(channel,
4720cdc64593Sxinghua wen - Sun Microsystems - Beijing China ch1_n, m1_p->gain_idx,
4721cdc64593Sxinghua wen - Sun Microsystems - Beijing China ch2_n, m2_p->gain_idx);
4722cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4723cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* make interpolation to get chipset temperature */
4724cdc64593Sxinghua wen - Sun Microsystems - Beijing China m_p->temperature = iwk_interpolate_value(channel,
4725cdc64593Sxinghua wen - Sun Microsystems - Beijing China ch1_n, m1_p->temperature,
4726cdc64593Sxinghua wen - Sun Microsystems - Beijing China ch2_n, m2_p->temperature);
4727cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4728cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
4729cdc64593Sxinghua wen - Sun Microsystems - Beijing China * make interpolation to get power
4730cdc64593Sxinghua wen - Sun Microsystems - Beijing China * amp detector level
4731cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
4732cdc64593Sxinghua wen - Sun Microsystems - Beijing China m_p->pa_det = iwk_interpolate_value(channel, ch1_n,
4733cdc64593Sxinghua wen - Sun Microsystems - Beijing China m1_p->pa_det,
4734cdc64593Sxinghua wen - Sun Microsystems - Beijing China ch2_n, m2_p->pa_det);
4735cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4736cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4737cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4738cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS);
4739cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4740cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4741cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
4742cdc64593Sxinghua wen - Sun Microsystems - Beijing China * Calculate voltage compensation for Tx power. For more infomation,
4743cdc64593Sxinghua wen - Sun Microsystems - Beijing China * please refer to iwk_calibration.h file
4744cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
iwk_voltage_compensation(int32_t eep_voltage,int32_t curr_voltage)4745cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int32_t iwk_voltage_compensation(int32_t eep_voltage,
4746cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t curr_voltage)
4747cdc64593Sxinghua wen - Sun Microsystems - Beijing China {
4748cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t vol_comp = 0;
4749cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4750cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((TX_POWER_IWK_ILLEGAL_VOLTAGE == eep_voltage) ||
4751cdc64593Sxinghua wen - Sun Microsystems - Beijing China (TX_POWER_IWK_ILLEGAL_VOLTAGE == curr_voltage)) {
4752cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (vol_comp);
4753cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4754cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4755cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) iwk_division(curr_voltage-eep_voltage,
4756cdc64593Sxinghua wen - Sun Microsystems - Beijing China TX_POWER_IWK_VOLTAGE_CODES_PER_03V, &vol_comp);
4757cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4758cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (curr_voltage > eep_voltage) {
4759cdc64593Sxinghua wen - Sun Microsystems - Beijing China vol_comp *= 2;
4760cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4761cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((vol_comp < -2) || (vol_comp > 2)) {
4762cdc64593Sxinghua wen - Sun Microsystems - Beijing China vol_comp = 0;
4763cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4764cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4765cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (vol_comp);
4766cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4767cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4768cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
4769cdc64593Sxinghua wen - Sun Microsystems - Beijing China * Thermal compensation values for txpower for various frequency ranges ...
4770cdc64593Sxinghua wen - Sun Microsystems - Beijing China * ratios from 3:1 to 4.5:1 of degrees (Celsius) per half-dB gain adjust
4771cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
4772cdc64593Sxinghua wen - Sun Microsystems - Beijing China static struct iwk_txpower_tempera_comp {
4773cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t degrees_per_05db_a;
4774cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t degrees_per_05db_a_denom;
4775cdc64593Sxinghua wen - Sun Microsystems - Beijing China } txpower_tempera_comp_table[CALIB_CH_GROUP_MAX] = {
4776cdc64593Sxinghua wen - Sun Microsystems - Beijing China {9, 2}, /* group 0 5.2, ch 34-43 */
4777cdc64593Sxinghua wen - Sun Microsystems - Beijing China {4, 1}, /* group 1 5.2, ch 44-70 */
4778cdc64593Sxinghua wen - Sun Microsystems - Beijing China {4, 1}, /* group 2 5.2, ch 71-124 */
4779cdc64593Sxinghua wen - Sun Microsystems - Beijing China {4, 1}, /* group 3 5.2, ch 125-200 */
4780cdc64593Sxinghua wen - Sun Microsystems - Beijing China {3, 1} /* group 4 2.4, ch all */
4781cdc64593Sxinghua wen - Sun Microsystems - Beijing China };
4782cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4783cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
4784cdc64593Sxinghua wen - Sun Microsystems - Beijing China * bit-rate-dependent table to prevent Tx distortion, in half-dB units,
4785cdc64593Sxinghua wen - Sun Microsystems - Beijing China * for OFDM 6, 12, 18, 24, 36, 48, 54, 60 MBit, and CCK all rates.
4786cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
4787cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int32_t back_off_table[] = {
4788cdc64593Sxinghua wen - Sun Microsystems - Beijing China 10, 10, 10, 10, 10, 15, 17, 20, /* OFDM SISO 20 MHz */
4789cdc64593Sxinghua wen - Sun Microsystems - Beijing China 10, 10, 10, 10, 10, 15, 17, 20, /* OFDM MIMO 20 MHz */
4790cdc64593Sxinghua wen - Sun Microsystems - Beijing China 10, 10, 10, 10, 10, 15, 17, 20, /* OFDM SISO 40 MHz */
4791cdc64593Sxinghua wen - Sun Microsystems - Beijing China 10, 10, 10, 10, 10, 15, 17, 20, /* OFDM MIMO 40 MHz */
4792cdc64593Sxinghua wen - Sun Microsystems - Beijing China 10 /* CCK */
4793cdc64593Sxinghua wen - Sun Microsystems - Beijing China };
4794cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4795cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine minimum Tx power index in gain table */
iwk_min_power_index(int32_t rate_pow_idx,int32_t is_24G)4796cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int32_t iwk_min_power_index(int32_t rate_pow_idx, int32_t is_24G)
4797cdc64593Sxinghua wen - Sun Microsystems - Beijing China {
4798cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((!is_24G) && ((rate_pow_idx & 7) <= 4)) {
4799cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (MIN_TX_GAIN_INDEX_52GHZ_EXT);
4800cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4801cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4802cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (MIN_TX_GAIN_INDEX);
4803cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4804cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4805cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
4806cdc64593Sxinghua wen - Sun Microsystems - Beijing China * Determine DSP and radio gain according to temperature and other factors.
4807cdc64593Sxinghua wen - Sun Microsystems - Beijing China * This function is the majority of Tx power calibration
4808cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
iwk_txpower_table_cmd_init(iwk_sc_t * sc,struct iwk_tx_power_db * tp_db)4809cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_txpower_table_cmd_init(iwk_sc_t *sc,
4810cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_tx_power_db *tp_db)
4811cdc64593Sxinghua wen - Sun Microsystems - Beijing China {
4812cdc64593Sxinghua wen - Sun Microsystems - Beijing China int is_24G, is_fat, is_high_chan, is_mimo;
4813cdc64593Sxinghua wen - Sun Microsystems - Beijing China int c, r;
4814cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t target_power;
4815cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t tx_grp = CALIB_CH_GROUP_MAX;
4816cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint16_t channel;
4817cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint8_t saturation_power;
4818cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t regu_power;
4819cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t curr_regu_power;
4820cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_eep_channel *eep_chan_p;
4821cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_eep_calib_channel_info eep_chan_calib;
4822cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t eep_voltage, init_voltage;
4823cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t voltage_compensation;
4824cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t temperature;
4825cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t degrees_per_05db_num;
4826cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t degrees_per_05db_denom;
4827cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_eep_calib_measure *measure_p;
4828cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t interpo_temp;
4829cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t power_limit;
4830cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t atten_value;
4831cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t tempera_comp[2];
4832cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t interpo_gain_idx[2];
4833cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t interpo_actual_pow[2];
4834cdc64593Sxinghua wen - Sun Microsystems - Beijing China union iwk_tx_power_dual_stream txpower_gains;
4835cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t txpower_gains_idx;
4836cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4837b510adaeSfei feng - Sun Microsystems - Beijing China channel = LE_16(sc->sc_config.chan);
4838cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4839cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 2.4 GHz or 5 GHz band */
4840cdc64593Sxinghua wen - Sun Microsystems - Beijing China is_24G = iwk_is_24G_band(sc);
4841cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4842cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* fat channel or not */
4843cdc64593Sxinghua wen - Sun Microsystems - Beijing China is_fat = iwk_is_fat_channel(sc);
4844cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4845cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
4846cdc64593Sxinghua wen - Sun Microsystems - Beijing China * using low half channel number or high half channel number
4847cdc64593Sxinghua wen - Sun Microsystems - Beijing China * identify fat channel
4848cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
4849b510adaeSfei feng - Sun Microsystems - Beijing China if (is_fat && (LE_32(sc->sc_config.flags) &
4850cdc64593Sxinghua wen - Sun Microsystems - Beijing China RXON_FLG_CONTROL_CHANNEL_LOC_HIGH_MSK)) {
4851cdc64593Sxinghua wen - Sun Microsystems - Beijing China is_high_chan = 1;
4852cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4853cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4854cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((channel > 0) && (channel < 200)) {
4855cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* get regulatory channel data from eeprom */
4856cdc64593Sxinghua wen - Sun Microsystems - Beijing China eep_chan_p = iwk_get_eep_channel(sc, channel, is_24G,
4857cdc64593Sxinghua wen - Sun Microsystems - Beijing China is_fat, is_high_chan);
4858cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (NULL == eep_chan_p) {
4859cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN,
4860cdc64593Sxinghua wen - Sun Microsystems - Beijing China "iwk_txpower_table_cmd_init(): "
4861cdc64593Sxinghua wen - Sun Microsystems - Beijing China "can't get channel infomation\n");
4862cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (DDI_FAILURE);
4863cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4864cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
4865cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_txpower_table_cmd_init(): "
4866cdc64593Sxinghua wen - Sun Microsystems - Beijing China "channel(%d) isn't in proper range\n",
4867cdc64593Sxinghua wen - Sun Microsystems - Beijing China channel);
4868cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (DDI_FAILURE);
4869cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4870cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4871cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* initial value of Tx power */
4872cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_user_txpower = (int32_t)eep_chan_p->max_power_avg;
4873cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (sc->sc_user_txpower < IWK_TX_POWER_TARGET_POWER_MIN) {
4874cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_txpower_table_cmd_init(): "
4875cdc64593Sxinghua wen - Sun Microsystems - Beijing China "user TX power is too weak\n");
4876cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (DDI_FAILURE);
4877cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else if (sc->sc_user_txpower > IWK_TX_POWER_TARGET_POWER_MAX) {
4878cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_txpower_table_cmd_init(): "
4879cdc64593Sxinghua wen - Sun Microsystems - Beijing China "user TX power is too strong\n");
4880cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (DDI_FAILURE);
4881cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4882cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4883cdc64593Sxinghua wen - Sun Microsystems - Beijing China target_power = 2 * sc->sc_user_txpower;
4884cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4885cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine which group current channel belongs to */
4886cdc64593Sxinghua wen - Sun Microsystems - Beijing China tx_grp = iwk_txpower_grp(channel);
4887cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (tx_grp < 0) {
4888cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (tx_grp);
4889cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4890cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4891cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4892cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (is_fat) {
4893cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (is_high_chan) {
4894cdc64593Sxinghua wen - Sun Microsystems - Beijing China channel -= 2;
4895cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
4896cdc64593Sxinghua wen - Sun Microsystems - Beijing China channel += 2;
4897cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4898cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4899cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4900cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine saturation power */
4901cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (is_24G) {
4902cdc64593Sxinghua wen - Sun Microsystems - Beijing China saturation_power =
4903cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_eep_map.calib_info.saturation_power24;
4904cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
4905cdc64593Sxinghua wen - Sun Microsystems - Beijing China saturation_power =
4906cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_eep_map.calib_info.saturation_power52;
4907cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4908cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4909cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (saturation_power < IWK_TX_POWER_SATURATION_MIN ||
4910cdc64593Sxinghua wen - Sun Microsystems - Beijing China saturation_power > IWK_TX_POWER_SATURATION_MAX) {
4911cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (is_24G) {
4912cdc64593Sxinghua wen - Sun Microsystems - Beijing China saturation_power = IWK_TX_POWER_DEFAULT_SATURATION_24;
4913cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
4914cdc64593Sxinghua wen - Sun Microsystems - Beijing China saturation_power = IWK_TX_POWER_DEFAULT_SATURATION_52;
4915cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4916cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4917cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4918cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine regulatory power */
4919cdc64593Sxinghua wen - Sun Microsystems - Beijing China regu_power = (int32_t)eep_chan_p->max_power_avg * 2;
4920cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((regu_power < IWK_TX_POWER_REGULATORY_MIN) ||
4921cdc64593Sxinghua wen - Sun Microsystems - Beijing China (regu_power > IWK_TX_POWER_REGULATORY_MAX)) {
4922cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (is_24G) {
4923cdc64593Sxinghua wen - Sun Microsystems - Beijing China regu_power = IWK_TX_POWER_DEFAULT_REGULATORY_24;
4924cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
4925cdc64593Sxinghua wen - Sun Microsystems - Beijing China regu_power = IWK_TX_POWER_DEFAULT_REGULATORY_52;
4926cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4927cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4928cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4929cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
4930cdc64593Sxinghua wen - Sun Microsystems - Beijing China * get measurement data for current channel
4931cdc64593Sxinghua wen - Sun Microsystems - Beijing China * suach as temperature,index to gain table,actual Tx power
4932cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
4933cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) iwk_channel_interpolate(sc, channel, &eep_chan_calib);
4934cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4935b510adaeSfei feng - Sun Microsystems - Beijing China eep_voltage = (int32_t)LE_16(sc->sc_eep_map.calib_info.voltage);
4936b510adaeSfei feng - Sun Microsystems - Beijing China init_voltage = (int32_t)LE_32(sc->sc_card_alive_init.voltage);
4937cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4938cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* calculate voltage compensation to Tx power */
4939cdc64593Sxinghua wen - Sun Microsystems - Beijing China voltage_compensation =
4940cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_voltage_compensation(eep_voltage, init_voltage);
4941cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4942cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (sc->sc_tempera >= IWK_TX_POWER_TEMPERATURE_MIN) {
4943cdc64593Sxinghua wen - Sun Microsystems - Beijing China temperature = sc->sc_tempera;
4944cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
4945cdc64593Sxinghua wen - Sun Microsystems - Beijing China temperature = IWK_TX_POWER_TEMPERATURE_MIN;
4946cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4947cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (sc->sc_tempera <= IWK_TX_POWER_TEMPERATURE_MAX) {
4948cdc64593Sxinghua wen - Sun Microsystems - Beijing China temperature = sc->sc_tempera;
4949cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
4950cdc64593Sxinghua wen - Sun Microsystems - Beijing China temperature = IWK_TX_POWER_TEMPERATURE_MAX;
4951cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4952cdc64593Sxinghua wen - Sun Microsystems - Beijing China temperature = KELVIN_TO_CELSIUS(temperature);
4953cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4954cdc64593Sxinghua wen - Sun Microsystems - Beijing China degrees_per_05db_num =
4955cdc64593Sxinghua wen - Sun Microsystems - Beijing China txpower_tempera_comp_table[tx_grp].degrees_per_05db_a;
4956cdc64593Sxinghua wen - Sun Microsystems - Beijing China degrees_per_05db_denom =
4957cdc64593Sxinghua wen - Sun Microsystems - Beijing China txpower_tempera_comp_table[tx_grp].degrees_per_05db_a_denom;
4958cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4959cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (c = 0; c < 2; c++) { /* go through all chains */
4960cdc64593Sxinghua wen - Sun Microsystems - Beijing China measure_p = &eep_chan_calib.measure[c][1];
4961cdc64593Sxinghua wen - Sun Microsystems - Beijing China interpo_temp = measure_p->temperature;
4962cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4963cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine temperature compensation to Tx power */
4964cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) iwk_division(
4965cdc64593Sxinghua wen - Sun Microsystems - Beijing China (temperature-interpo_temp)*degrees_per_05db_denom,
4966cdc64593Sxinghua wen - Sun Microsystems - Beijing China degrees_per_05db_num, &tempera_comp[c]);
4967cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4968cdc64593Sxinghua wen - Sun Microsystems - Beijing China interpo_gain_idx[c] = measure_p->gain_idx;
4969cdc64593Sxinghua wen - Sun Microsystems - Beijing China interpo_actual_pow[c] = measure_p->actual_pow;
4970cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4971cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4972cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
4973cdc64593Sxinghua wen - Sun Microsystems - Beijing China * go through all rate entries in Tx power table
4974cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
4975cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (r = 0; r < POWER_TABLE_NUM_ENTRIES; r++) {
4976cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (r & 0x8) {
4977cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* need to lower regulatory power for MIMO mode */
4978cdc64593Sxinghua wen - Sun Microsystems - Beijing China curr_regu_power = regu_power -
4979cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_TX_POWER_MIMO_REGULATORY_COMPENSATION;
4980cdc64593Sxinghua wen - Sun Microsystems - Beijing China is_mimo = 1;
4981cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
4982cdc64593Sxinghua wen - Sun Microsystems - Beijing China curr_regu_power = regu_power;
4983cdc64593Sxinghua wen - Sun Microsystems - Beijing China is_mimo = 0;
4984cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4985cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4986cdc64593Sxinghua wen - Sun Microsystems - Beijing China power_limit = saturation_power - back_off_table[r];
4987cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (power_limit > curr_regu_power) {
4988cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* final Tx power limit */
4989cdc64593Sxinghua wen - Sun Microsystems - Beijing China power_limit = curr_regu_power;
4990cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4991cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4992cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (target_power > power_limit) {
4993cdc64593Sxinghua wen - Sun Microsystems - Beijing China target_power = power_limit; /* final target Tx power */
4994cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
4995cdc64593Sxinghua wen - Sun Microsystems - Beijing China
4996cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (c = 0; c < 2; c++) { /* go through all Tx chains */
4997cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (is_mimo) {
4998cdc64593Sxinghua wen - Sun Microsystems - Beijing China atten_value =
4999b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(sc->sc_card_alive_init.
5000b510adaeSfei feng - Sun Microsystems - Beijing China tx_atten[tx_grp][c]);
5001cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
5002cdc64593Sxinghua wen - Sun Microsystems - Beijing China atten_value = 0;
5003cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5004cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5005cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
5006cdc64593Sxinghua wen - Sun Microsystems - Beijing China * calculate index in gain table
5007cdc64593Sxinghua wen - Sun Microsystems - Beijing China * this step is very important
5008cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
5009cdc64593Sxinghua wen - Sun Microsystems - Beijing China txpower_gains_idx = interpo_gain_idx[c] -
5010cdc64593Sxinghua wen - Sun Microsystems - Beijing China (target_power - interpo_actual_pow[c]) -
5011cdc64593Sxinghua wen - Sun Microsystems - Beijing China tempera_comp[c] - voltage_compensation +
5012cdc64593Sxinghua wen - Sun Microsystems - Beijing China atten_value;
5013cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5014cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (txpower_gains_idx <
5015cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_min_power_index(r, is_24G)) {
5016cdc64593Sxinghua wen - Sun Microsystems - Beijing China txpower_gains_idx =
5017cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_min_power_index(r, is_24G);
5018cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5019cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5020cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!is_24G) {
5021cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
5022cdc64593Sxinghua wen - Sun Microsystems - Beijing China * support negative index for 5 GHz
5023cdc64593Sxinghua wen - Sun Microsystems - Beijing China * band
5024cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
5025cdc64593Sxinghua wen - Sun Microsystems - Beijing China txpower_gains_idx += 9;
5026cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5027cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5028cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (POWER_TABLE_CCK_ENTRY == r) {
5029cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* for CCK mode, make necessary attenuaton */
5030cdc64593Sxinghua wen - Sun Microsystems - Beijing China txpower_gains_idx +=
5031cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_TX_POWER_CCK_COMPENSATION_C_STEP;
5032cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5033cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5034cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (txpower_gains_idx > 107) {
5035cdc64593Sxinghua wen - Sun Microsystems - Beijing China txpower_gains_idx = 107;
5036cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else if (txpower_gains_idx < 0) {
5037cdc64593Sxinghua wen - Sun Microsystems - Beijing China txpower_gains_idx = 0;
5038cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5039cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5040cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* search DSP and radio gains in gain table */
5041cdc64593Sxinghua wen - Sun Microsystems - Beijing China txpower_gains.s.radio_tx_gain[c] =
5042cdc64593Sxinghua wen - Sun Microsystems - Beijing China gains_table[is_24G][txpower_gains_idx].radio;
5043cdc64593Sxinghua wen - Sun Microsystems - Beijing China txpower_gains.s.dsp_predis_atten[c] =
5044cdc64593Sxinghua wen - Sun Microsystems - Beijing China gains_table[is_24G][txpower_gains_idx].dsp;
5045cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5046cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_CALIBRATION,
5047cdc64593Sxinghua wen - Sun Microsystems - Beijing China "rate_index: %d, "
5048cdc64593Sxinghua wen - Sun Microsystems - Beijing China "gain_index %d, c: %d,is_mimo: %d\n",
5049cdc64593Sxinghua wen - Sun Microsystems - Beijing China r, txpower_gains_idx, c, is_mimo));
5050cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5051cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5052cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* initialize Tx power table */
5053cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (r < POWER_TABLE_NUM_HT_OFDM_ENTRIES) {
5054b510adaeSfei feng - Sun Microsystems - Beijing China tp_db->ht_ofdm_power[r].dw = LE_32(txpower_gains.dw);
5055cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
5056b510adaeSfei feng - Sun Microsystems - Beijing China tp_db->legacy_cck_power.dw = LE_32(txpower_gains.dw);
5057cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5058cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5059cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5060cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS);
5061cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5062cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5063cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
5064cdc64593Sxinghua wen - Sun Microsystems - Beijing China * make Tx power calibration to adjust Tx power.
5065cdc64593Sxinghua wen - Sun Microsystems - Beijing China * This is completed by sending out Tx power table command.
5066cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
iwk_tx_power_calibration(iwk_sc_t * sc)5067cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_tx_power_calibration(iwk_sc_t *sc)
5068cdc64593Sxinghua wen - Sun Microsystems - Beijing China {
5069cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_tx_power_table_cmd_t cmd;
5070cdc64593Sxinghua wen - Sun Microsystems - Beijing China int rv;
5071cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5072cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (sc->sc_flags & IWK_F_SCANNING) {
5073cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS);
5074cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5075cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5076cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* necessary initialization to Tx power table command */
5077cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.band = (uint8_t)iwk_is_24G_band(sc);
5078cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.channel = sc->sc_config.chan;
5079cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.channel_normal_width = 0;
5080cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5081cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* initialize Tx power table */
5082cdc64593Sxinghua wen - Sun Microsystems - Beijing China rv = iwk_txpower_table_cmd_init(sc, &cmd.tx_power);
5083cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rv) {
5084cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_NOTE, "rv= %d\n", rv);
5085cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (rv);
5086cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5087cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5088cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* send out Tx power table command */
5089cdc64593Sxinghua wen - Sun Microsystems - Beijing China rv = iwk_cmd(sc, REPLY_TX_PWR_TABLE_CMD, &cmd, sizeof (cmd), 1);
5090cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rv) {
5091cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (rv);
5092cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5093cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5094cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* record current temperature */
5095cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_last_tempera = sc->sc_tempera;
5096cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5097cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS);
5098cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5099cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5100cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* This function is the handler of statistics notification from uCode */
iwk_statistics_notify(iwk_sc_t * sc,iwk_rx_desc_t * desc)5101cdc64593Sxinghua wen - Sun Microsystems - Beijing China static void iwk_statistics_notify(iwk_sc_t *sc, iwk_rx_desc_t *desc)
5102cdc64593Sxinghua wen - Sun Microsystems - Beijing China {
5103cdc64593Sxinghua wen - Sun Microsystems - Beijing China int is_diff;
5104cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_notif_statistics *statistics_p =
5105cdc64593Sxinghua wen - Sun Microsystems - Beijing China (struct iwk_notif_statistics *)(desc + 1);
5106cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5107cdc64593Sxinghua wen - Sun Microsystems - Beijing China mutex_enter(&sc->sc_glock);
5108cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5109cdc64593Sxinghua wen - Sun Microsystems - Beijing China is_diff = (sc->sc_statistics.general.temperature !=
5110cdc64593Sxinghua wen - Sun Microsystems - Beijing China statistics_p->general.temperature) ||
5111b510adaeSfei feng - Sun Microsystems - Beijing China (LE_32(sc->sc_statistics.flag) &
5112b510adaeSfei feng - Sun Microsystems - Beijing China STATISTICS_REPLY_FLG_FAT_MODE_MSK) !=
5113b510adaeSfei feng - Sun Microsystems - Beijing China (LE_32(statistics_p->flag) & STATISTICS_REPLY_FLG_FAT_MODE_MSK);
5114cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5115cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* update statistics data */
5116cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) memcpy(&sc->sc_statistics, statistics_p,
5117cdc64593Sxinghua wen - Sun Microsystems - Beijing China sizeof (struct iwk_notif_statistics));
5118cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5119cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_flags |= IWK_F_STATISTICS;
5120cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5121cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!(sc->sc_flags & IWK_F_SCANNING)) {
5122cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* make Receiver gain balance calibration */
5123cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) iwk_rxgain_diff(sc);
5124cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5125cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* make Receiver sensitivity calibration */
5126cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) iwk_rx_sens(sc);
5127cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5128cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5129cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5130cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!is_diff) {
5131cdc64593Sxinghua wen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock);
5132cdc64593Sxinghua wen - Sun Microsystems - Beijing China return;
5133cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5134cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5135cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* calibration current temperature of 4965 chipset */
5136cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_tempera = iwk_curr_tempera(sc);
5137cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5138cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* distinct temperature change will trigger Tx power calibration */
5139cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (((sc->sc_tempera - sc->sc_last_tempera) >= 3) ||
5140cdc64593Sxinghua wen - Sun Microsystems - Beijing China ((sc->sc_last_tempera - sc->sc_tempera) >= 3)) {
5141cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* make Tx power calibration */
5142cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) iwk_tx_power_calibration(sc);
5143cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5144cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5145cdc64593Sxinghua wen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock);
5146cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5147cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5148cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* Determine this station is in associated state or not */
iwk_is_associated(iwk_sc_t * sc)5149cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_is_associated(iwk_sc_t *sc)
5150cdc64593Sxinghua wen - Sun Microsystems - Beijing China {
5151b510adaeSfei feng - Sun Microsystems - Beijing China return (LE_32(sc->sc_config.filter_flags) & RXON_FILTER_ASSOC_MSK);
5152cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5153cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5154cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* Make necessary preparation for Receiver gain balance calibration */
iwk_rxgain_diff_init(iwk_sc_t * sc)5155cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_rxgain_diff_init(iwk_sc_t *sc)
5156cdc64593Sxinghua wen - Sun Microsystems - Beijing China {
5157cdc64593Sxinghua wen - Sun Microsystems - Beijing China int i, rv;
5158cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_calibration_cmd cmd;
5159cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_rx_gain_diff *gain_diff_p;
5160cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5161cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p = &sc->sc_rxgain_diff;
5162cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5163cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) memset(gain_diff_p, 0, sizeof (struct iwk_rx_gain_diff));
5164cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) memset(&cmd, 0, sizeof (struct iwk_calibration_cmd));
5165cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5166cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < RX_CHAINS_NUM; i++) {
5167cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->gain_diff_chain[i] = CHAIN_GAIN_DIFF_INIT_VAL;
5168cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5169cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5170cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (iwk_is_associated(sc)) {
5171cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.opCode = PHY_CALIBRATE_DIFF_GAIN_CMD;
5172cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.diff_gain_a = 0;
5173cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.diff_gain_b = 0;
5174cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.diff_gain_c = 0;
5175cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5176cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* assume the gains of every Rx chains is balanceable */
5177cdc64593Sxinghua wen - Sun Microsystems - Beijing China rv = iwk_cmd(sc, REPLY_PHY_CALIBRATION_CMD, &cmd,
5178cdc64593Sxinghua wen - Sun Microsystems - Beijing China sizeof (cmd), 1);
5179cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rv) {
5180cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (rv);
5181cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5182cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5183cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->state = IWK_GAIN_DIFF_ACCUMULATE;
5184cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5185cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5186cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS);
5187cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5188cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5189cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
5190cdc64593Sxinghua wen - Sun Microsystems - Beijing China * make Receiver gain balance to balance Rx gain between Rx chains
5191cdc64593Sxinghua wen - Sun Microsystems - Beijing China * and determine which chain is disconnected
5192cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
iwk_rxgain_diff(iwk_sc_t * sc)5193cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_rxgain_diff(iwk_sc_t *sc)
5194cdc64593Sxinghua wen - Sun Microsystems - Beijing China {
5195cdc64593Sxinghua wen - Sun Microsystems - Beijing China int i, is_24G, rv;
5196cdc64593Sxinghua wen - Sun Microsystems - Beijing China int max_beacon_chain_n;
5197cdc64593Sxinghua wen - Sun Microsystems - Beijing China int min_noise_chain_n;
5198cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint16_t channel_n;
5199cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t beacon_diff;
5200cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t noise_diff;
5201cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t noise_chain_a, noise_chain_b, noise_chain_c;
5202cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t beacon_chain_a, beacon_chain_b, beacon_chain_c;
5203cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_calibration_cmd cmd;
5204cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t beacon_aver[RX_CHAINS_NUM] = {0xFFFFFFFF};
5205cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t noise_aver[RX_CHAINS_NUM] = {0xFFFFFFFF};
5206cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct statistics_rx_non_phy *rx_general_p =
5207cdc64593Sxinghua wen - Sun Microsystems - Beijing China &sc->sc_statistics.rx.general;
5208cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_rx_gain_diff *gain_diff_p = &sc->sc_rxgain_diff;
5209cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5210cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (INTERFERENCE_DATA_AVAILABLE !=
5211b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(rx_general_p->interference_data_flag)) {
5212cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS);
5213cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5214cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5215cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (IWK_GAIN_DIFF_ACCUMULATE != gain_diff_p->state) {
5216cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS);
5217cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5218cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5219cdc64593Sxinghua wen - Sun Microsystems - Beijing China is_24G = iwk_is_24G_band(sc);
5220cdc64593Sxinghua wen - Sun Microsystems - Beijing China channel_n = sc->sc_config.chan; /* channel number */
5221cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5222b510adaeSfei feng - Sun Microsystems - Beijing China if ((channel_n != (LE_32(sc->sc_statistics.flag) >> 16)) ||
5223cdc64593Sxinghua wen - Sun Microsystems - Beijing China ((STATISTICS_REPLY_FLG_BAND_24G_MSK ==
5224b510adaeSfei feng - Sun Microsystems - Beijing China (LE_32(sc->sc_statistics.flag) &
5225b510adaeSfei feng - Sun Microsystems - Beijing China STATISTICS_REPLY_FLG_BAND_24G_MSK)) &&
5226cdc64593Sxinghua wen - Sun Microsystems - Beijing China !is_24G)) {
5227cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS);
5228cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5229cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5230cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* Rx chain's noise strength from statistics notification */
5231b510adaeSfei feng - Sun Microsystems - Beijing China noise_chain_a = LE_32(rx_general_p->beacon_silence_rssi_a) & 0xFF;
5232b510adaeSfei feng - Sun Microsystems - Beijing China noise_chain_b = LE_32(rx_general_p->beacon_silence_rssi_b) & 0xFF;
5233b510adaeSfei feng - Sun Microsystems - Beijing China noise_chain_c = LE_32(rx_general_p->beacon_silence_rssi_c) & 0xFF;
5234cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5235cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* Rx chain's beacon strength from statistics notification */
5236b510adaeSfei feng - Sun Microsystems - Beijing China beacon_chain_a = LE_32(rx_general_p->beacon_rssi_a) & 0xFF;
5237b510adaeSfei feng - Sun Microsystems - Beijing China beacon_chain_b = LE_32(rx_general_p->beacon_rssi_b) & 0xFF;
5238b510adaeSfei feng - Sun Microsystems - Beijing China beacon_chain_c = LE_32(rx_general_p->beacon_rssi_c) & 0xFF;
5239cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5240cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->beacon_count++;
5241cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5242cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* accumulate chain's noise strength */
5243cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->noise_stren_a += noise_chain_a;
5244cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->noise_stren_b += noise_chain_b;
5245cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->noise_stren_c += noise_chain_c;
5246cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5247cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* accumulate chain's beacon strength */
5248cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->beacon_stren_a += beacon_chain_a;
5249cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->beacon_stren_b += beacon_chain_b;
5250cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->beacon_stren_c += beacon_chain_c;
5251cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5252cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (BEACON_NUM_20 == gain_diff_p->beacon_count) {
5253cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* calculate average beacon strength */
5254cdc64593Sxinghua wen - Sun Microsystems - Beijing China beacon_aver[0] = (gain_diff_p->beacon_stren_a) / BEACON_NUM_20;
5255cdc64593Sxinghua wen - Sun Microsystems - Beijing China beacon_aver[1] = (gain_diff_p->beacon_stren_b) / BEACON_NUM_20;
5256cdc64593Sxinghua wen - Sun Microsystems - Beijing China beacon_aver[2] = (gain_diff_p->beacon_stren_c) / BEACON_NUM_20;
5257cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5258cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* calculate average noise strength */
5259cdc64593Sxinghua wen - Sun Microsystems - Beijing China noise_aver[0] = (gain_diff_p->noise_stren_a) / BEACON_NUM_20;
5260cdc64593Sxinghua wen - Sun Microsystems - Beijing China noise_aver[1] = (gain_diff_p->noise_stren_b) / BEACON_NUM_20;
5261cdc64593Sxinghua wen - Sun Microsystems - Beijing China noise_aver[2] = (gain_diff_p->noise_stren_b) / BEACON_NUM_20;
5262cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5263cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine maximum beacon strength among 3 chains */
5264cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((beacon_aver[0] >= beacon_aver[1]) &&
5265cdc64593Sxinghua wen - Sun Microsystems - Beijing China (beacon_aver[0] >= beacon_aver[2])) {
5266cdc64593Sxinghua wen - Sun Microsystems - Beijing China max_beacon_chain_n = 0;
5267cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->connected_chains = 1 << 0;
5268cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else if (beacon_aver[1] >= beacon_aver[2]) {
5269cdc64593Sxinghua wen - Sun Microsystems - Beijing China max_beacon_chain_n = 1;
5270cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->connected_chains = 1 << 1;
5271cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
5272cdc64593Sxinghua wen - Sun Microsystems - Beijing China max_beacon_chain_n = 2;
5273cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->connected_chains = 1 << 2;
5274cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5275cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5276cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine which chain is disconnected */
5277cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < RX_CHAINS_NUM; i++) {
5278cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (i != max_beacon_chain_n) {
5279cdc64593Sxinghua wen - Sun Microsystems - Beijing China beacon_diff = beacon_aver[max_beacon_chain_n] -
5280cdc64593Sxinghua wen - Sun Microsystems - Beijing China beacon_aver[i];
5281cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (beacon_diff > MAX_ALLOWED_DIFF) {
5282cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->disconnect_chain[i] = 1;
5283cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
5284cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->connected_chains |=
5285cdc64593Sxinghua wen - Sun Microsystems - Beijing China (1 << i);
5286cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5287cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5288cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5289cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5290cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
5291cdc64593Sxinghua wen - Sun Microsystems - Beijing China * if chain A and B are both disconnected,
5292cdc64593Sxinghua wen - Sun Microsystems - Beijing China * assume the stronger in beacon strength is connected
5293cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
5294cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (gain_diff_p->disconnect_chain[0] &&
5295cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->disconnect_chain[1]) {
5296cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (beacon_aver[0] >= beacon_aver[1]) {
5297cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->disconnect_chain[0] = 0;
5298cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->connected_chains |= (1 << 0);
5299cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
5300cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->disconnect_chain[1] = 0;
5301cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->connected_chains |= (1 << 1);
5302cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5303cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5304cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5305cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine minimum noise strength among 3 chains */
5306cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!gain_diff_p->disconnect_chain[0]) {
5307cdc64593Sxinghua wen - Sun Microsystems - Beijing China min_noise_chain_n = 0;
5308cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5309cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < RX_CHAINS_NUM; i++) {
5310cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!gain_diff_p->disconnect_chain[i] &&
5311cdc64593Sxinghua wen - Sun Microsystems - Beijing China (noise_aver[i] <=
5312cdc64593Sxinghua wen - Sun Microsystems - Beijing China noise_aver[min_noise_chain_n])) {
5313cdc64593Sxinghua wen - Sun Microsystems - Beijing China min_noise_chain_n = i;
5314cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5315cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5316cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5317cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
5318cdc64593Sxinghua wen - Sun Microsystems - Beijing China min_noise_chain_n = 1;
5319cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5320cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < RX_CHAINS_NUM; i++) {
5321cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!gain_diff_p->disconnect_chain[i] &&
5322cdc64593Sxinghua wen - Sun Microsystems - Beijing China (noise_aver[i] <=
5323cdc64593Sxinghua wen - Sun Microsystems - Beijing China noise_aver[min_noise_chain_n])) {
5324cdc64593Sxinghua wen - Sun Microsystems - Beijing China min_noise_chain_n = i;
5325cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5326cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5327cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5328cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5329cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->gain_diff_chain[min_noise_chain_n] = 0;
5330cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5331cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine gain difference between chains */
5332cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < RX_CHAINS_NUM; i++) {
5333cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!gain_diff_p->disconnect_chain[i] &&
5334cdc64593Sxinghua wen - Sun Microsystems - Beijing China (CHAIN_GAIN_DIFF_INIT_VAL ==
5335cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->gain_diff_chain[i])) {
5336cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5337cdc64593Sxinghua wen - Sun Microsystems - Beijing China noise_diff = noise_aver[i] -
5338cdc64593Sxinghua wen - Sun Microsystems - Beijing China noise_aver[min_noise_chain_n];
5339cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->gain_diff_chain[i] =
5340cdc64593Sxinghua wen - Sun Microsystems - Beijing China (uint8_t)((noise_diff * 10) / 15);
5341cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5342cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (gain_diff_p->gain_diff_chain[i] > 3) {
5343cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->gain_diff_chain[i] = 3;
5344cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5345cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5346cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->gain_diff_chain[i] |= (1 << 2);
5347cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
5348cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->gain_diff_chain[i] = 0;
5349cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5350cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5351cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5352cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!gain_diff_p->gain_diff_send) {
5353cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->gain_diff_send = 1;
5354cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5355cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) memset(&cmd, 0, sizeof (cmd));
5356cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5357cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.opCode = PHY_CALIBRATE_DIFF_GAIN_CMD;
5358cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.diff_gain_a = gain_diff_p->gain_diff_chain[0];
5359cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.diff_gain_b = gain_diff_p->gain_diff_chain[1];
5360cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.diff_gain_c = gain_diff_p->gain_diff_chain[2];
5361cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5362cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
5363cdc64593Sxinghua wen - Sun Microsystems - Beijing China * send out PHY calibration command to
5364cdc64593Sxinghua wen - Sun Microsystems - Beijing China * adjust every chain's Rx gain
5365cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
5366cdc64593Sxinghua wen - Sun Microsystems - Beijing China rv = iwk_cmd(sc, REPLY_PHY_CALIBRATION_CMD,
5367cdc64593Sxinghua wen - Sun Microsystems - Beijing China &cmd, sizeof (cmd), 1);
5368cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rv) {
5369cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (rv);
5370cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5371cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5372cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->state = IWK_GAIN_DIFF_CALIBRATED;
5373cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5374cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5375cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->beacon_stren_a = 0;
5376cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->beacon_stren_b = 0;
5377cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->beacon_stren_c = 0;
5378cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5379cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->noise_stren_a = 0;
5380cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->noise_stren_b = 0;
5381cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->noise_stren_c = 0;
5382cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5383cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5384cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS);
5385cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5386cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5387cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* Make necessary preparation for Receiver sensitivity calibration */
iwk_rx_sens_init(iwk_sc_t * sc)5388cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_rx_sens_init(iwk_sc_t *sc)
5389cdc64593Sxinghua wen - Sun Microsystems - Beijing China {
5390cdc64593Sxinghua wen - Sun Microsystems - Beijing China int i, rv;
5391cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_rx_sensitivity_cmd cmd;
5392cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_rx_sensitivity *rx_sens_p = &sc->sc_rx_sens;
5393cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5394cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) memset(&cmd, 0, sizeof (struct iwk_rx_sensitivity_cmd));
5395cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) memset(rx_sens_p, 0, sizeof (struct iwk_rx_sensitivity));
5396cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5397cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_ofdm_x4 = 90;
5398cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_ofdm_x4 = 170;
5399cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_ofdm_x1 = 105;
5400cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_ofdm_x1 = 220;
5401cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5402cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_cck_x4 = 125;
5403cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_cck_x4 = 200;
5404cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->min_energy_det_cck = 100;
5405cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5406cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->flags &= (~IWK_SENSITIVITY_CALIB_ALLOW_MSK);
5407cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->flags &= (~IWK_SENSITIVITY_OFDM_UPDATE_MSK);
5408cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->flags &= (~IWK_SENSITIVITY_CCK_UPDATE_MSK);
5409cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5410cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->last_bad_plcp_cnt_ofdm = 0;
5411cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->last_false_alarm_cnt_ofdm = 0;
5412cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->last_bad_plcp_cnt_cck = 0;
5413cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->last_false_alarm_cnt_cck = 0;
5414cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5415cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_curr_state = IWK_TOO_MANY_FALSE_ALARM;
5416cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_prev_state = IWK_TOO_MANY_FALSE_ALARM;
5417cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_no_false_alarm_num = 0;
5418cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_beacon_idx = 0;
5419cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5420cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < 10; i++) {
5421cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_beacon_min[i] = 0;
5422cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5423cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5424cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_noise_idx = 0;
5425cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_noise_ref = 0;
5426cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5427cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < 20; i++) {
5428cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_noise_max[i] = 0;
5429cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5430cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5431cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_noise_diff = 0;
5432cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_no_false_alarm_num = 0;
5433cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5434b510adaeSfei feng - Sun Microsystems - Beijing China cmd.control = LE_16(IWK_SENSITIVITY_CONTROL_WORK_TABLE);
5435cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5436cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[AUTO_CORR32_X4_TH_ADD_MIN_IDX] =
5437b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(rx_sens_p->auto_corr_ofdm_x4);
5438cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[AUTO_CORR32_X4_TH_ADD_MIN_MRC_IDX] =
5439b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(rx_sens_p->auto_corr_mrc_ofdm_x4);
5440cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[AUTO_CORR32_X1_TH_ADD_MIN_IDX] =
5441b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(rx_sens_p->auto_corr_ofdm_x1);
5442cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[AUTO_CORR32_X1_TH_ADD_MIN_MRC_IDX] =
5443b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(rx_sens_p->auto_corr_mrc_ofdm_x1);
5444cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5445cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[AUTO_CORR40_X4_TH_ADD_MIN_IDX] =
5446b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(rx_sens_p->auto_corr_cck_x4);
5447cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[AUTO_CORR40_X4_TH_ADD_MIN_MRC_IDX] =
5448b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(rx_sens_p->auto_corr_mrc_cck_x4);
5449b510adaeSfei feng - Sun Microsystems - Beijing China cmd.table[MIN_ENERGY_CCK_DET_IDX] =
5450b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(rx_sens_p->min_energy_det_cck);
5451cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5452b510adaeSfei feng - Sun Microsystems - Beijing China cmd.table[MIN_ENERGY_OFDM_DET_IDX] = LE_16(100);
5453b510adaeSfei feng - Sun Microsystems - Beijing China cmd.table[BARKER_CORR_TH_ADD_MIN_IDX] = LE_16(190);
5454b510adaeSfei feng - Sun Microsystems - Beijing China cmd.table[BARKER_CORR_TH_ADD_MIN_MRC_IDX] = LE_16(390);
5455b510adaeSfei feng - Sun Microsystems - Beijing China cmd.table[PTAM_ENERGY_TH_IDX] = LE_16(62);
5456cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5457cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* at first, set up Rx to maximum sensitivity */
5458cdc64593Sxinghua wen - Sun Microsystems - Beijing China rv = iwk_cmd(sc, SENSITIVITY_CMD, &cmd, sizeof (cmd), 1);
5459cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rv) {
5460cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_rx_sens_init(): "
5461cdc64593Sxinghua wen - Sun Microsystems - Beijing China "in the process of initialization, "
5462cdc64593Sxinghua wen - Sun Microsystems - Beijing China "failed to send rx sensitivity command\n");
5463cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (rv);
5464cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5465cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5466cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->flags |= IWK_SENSITIVITY_CALIB_ALLOW_MSK;
5467cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5468cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS);
5469cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5470cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5471cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
5472cdc64593Sxinghua wen - Sun Microsystems - Beijing China * make Receiver sensitivity calibration to adjust every chain's Rx sensitivity.
5473cdc64593Sxinghua wen - Sun Microsystems - Beijing China * for more infomation, please refer to iwk_calibration.h file
5474cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
iwk_rx_sens(iwk_sc_t * sc)5475cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_rx_sens(iwk_sc_t *sc)
5476cdc64593Sxinghua wen - Sun Microsystems - Beijing China {
5477cdc64593Sxinghua wen - Sun Microsystems - Beijing China int rv;
5478cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t actual_rx_time;
5479cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct statistics_rx_non_phy *rx_general_p =
5480cdc64593Sxinghua wen - Sun Microsystems - Beijing China &sc->sc_statistics.rx.general;
5481cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_rx_sensitivity *rx_sens_p = &sc->sc_rx_sens;
5482cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_rx_sensitivity_cmd cmd;
5483cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5484cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!(rx_sens_p->flags & IWK_SENSITIVITY_CALIB_ALLOW_MSK)) {
5485cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_rx_sens(): "
5486cdc64593Sxinghua wen - Sun Microsystems - Beijing China "sensitivity initialization has not finished.\n");
5487cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (DDI_FAILURE);
5488cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5489cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5490cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (INTERFERENCE_DATA_AVAILABLE !=
5491b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(rx_general_p->interference_data_flag)) {
5492cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_rx_sens(): "
5493cdc64593Sxinghua wen - Sun Microsystems - Beijing China "can't make rx sensitivity calibration,"
5494cdc64593Sxinghua wen - Sun Microsystems - Beijing China "because of invalid statistics\n");
5495cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (DDI_FAILURE);
5496cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5497cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5498b510adaeSfei feng - Sun Microsystems - Beijing China actual_rx_time = LE_32(rx_general_p->channel_load);
5499cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!actual_rx_time) {
5500d2a61391Spengcheng chen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_CALIBRATION, "iwk_rx_sens(): "
5501cdc64593Sxinghua wen - Sun Microsystems - Beijing China "can't make rx sensitivity calibration,"
5502d2a61391Spengcheng chen - Sun Microsystems - Beijing China "because has not enough rx time\n"));
5503cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (DDI_FAILURE);
5504cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5505cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5506cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* make Rx sensitivity calibration for OFDM mode */
5507cdc64593Sxinghua wen - Sun Microsystems - Beijing China rv = iwk_ofdm_sens(sc, actual_rx_time);
5508cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rv) {
5509cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (rv);
5510cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5511cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5512cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* make Rx sensitivity calibration for CCK mode */
5513cdc64593Sxinghua wen - Sun Microsystems - Beijing China rv = iwk_cck_sens(sc, actual_rx_time);
5514cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rv) {
5515cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (rv);
5516cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5517cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5518cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
5519cdc64593Sxinghua wen - Sun Microsystems - Beijing China * if the sum of false alarm had not changed, nothing will be done
5520cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
5521cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((!(rx_sens_p->flags & IWK_SENSITIVITY_OFDM_UPDATE_MSK)) &&
5522cdc64593Sxinghua wen - Sun Microsystems - Beijing China (!(rx_sens_p->flags & IWK_SENSITIVITY_CCK_UPDATE_MSK))) {
5523cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS);
5524cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5525cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5526cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.control = IWK_SENSITIVITY_CONTROL_WORK_TABLE;
5527cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5528cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[AUTO_CORR32_X4_TH_ADD_MIN_IDX] =
5529cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_ofdm_x4;
5530cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[AUTO_CORR32_X4_TH_ADD_MIN_MRC_IDX] =
5531cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_ofdm_x4;
5532cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[AUTO_CORR32_X1_TH_ADD_MIN_IDX] =
5533cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_ofdm_x1;
5534cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[AUTO_CORR32_X1_TH_ADD_MIN_MRC_IDX] =
5535cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_ofdm_x1;
5536cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5537cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[AUTO_CORR40_X4_TH_ADD_MIN_IDX] =
5538cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_cck_x4;
5539cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[AUTO_CORR40_X4_TH_ADD_MIN_MRC_IDX] =
5540cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_cck_x4;
5541cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[MIN_ENERGY_CCK_DET_IDX] =
5542cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->min_energy_det_cck;
5543cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5544cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[MIN_ENERGY_OFDM_DET_IDX] = 100;
5545cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[BARKER_CORR_TH_ADD_MIN_IDX] = 190;
5546cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[BARKER_CORR_TH_ADD_MIN_MRC_IDX] = 390;
5547cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[PTAM_ENERGY_TH_IDX] = 62;
5548cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5549cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
5550cdc64593Sxinghua wen - Sun Microsystems - Beijing China * send sensitivity command to complete actual sensitivity calibration
5551cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
5552cdc64593Sxinghua wen - Sun Microsystems - Beijing China rv = iwk_cmd(sc, SENSITIVITY_CMD, &cmd, sizeof (cmd), 1);
5553cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rv) {
5554cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_rx_sens(): "
5555cdc64593Sxinghua wen - Sun Microsystems - Beijing China "fail to send rx sensitivity command\n");
5556cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (rv);
5557cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5558cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5559cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS);
5560cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5561cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5562cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5563cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
5564cdc64593Sxinghua wen - Sun Microsystems - Beijing China * make Rx sensitivity calibration for CCK mode.
5565cdc64593Sxinghua wen - Sun Microsystems - Beijing China * This is preparing parameters for Sensitivity command
5566cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
iwk_cck_sens(iwk_sc_t * sc,uint32_t actual_rx_time)5567cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_cck_sens(iwk_sc_t *sc, uint32_t actual_rx_time)
5568cdc64593Sxinghua wen - Sun Microsystems - Beijing China {
5569cdc64593Sxinghua wen - Sun Microsystems - Beijing China int i;
5570cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint8_t noise_a, noise_b, noise_c;
5571cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint8_t max_noise_abc, max_noise_20;
5572cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t beacon_a, beacon_b, beacon_c;
5573cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t min_beacon_abc, max_beacon_10;
5574cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t cck_fa, cck_bp;
5575cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t cck_sum_fa_bp;
5576cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t temp;
5577cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct statistics_rx_non_phy *rx_general_p =
5578cdc64593Sxinghua wen - Sun Microsystems - Beijing China &sc->sc_statistics.rx.general;
5579cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_rx_sensitivity *rx_sens_p = &sc->sc_rx_sens;
5580cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5581b510adaeSfei feng - Sun Microsystems - Beijing China cck_fa = LE_32(sc->sc_statistics.rx.cck.false_alarm_cnt);
5582b510adaeSfei feng - Sun Microsystems - Beijing China cck_bp = LE_32(sc->sc_statistics.rx.cck.plcp_err);
5583cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5584cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* accumulate false alarm */
5585cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rx_sens_p->last_false_alarm_cnt_cck > cck_fa) {
5586cdc64593Sxinghua wen - Sun Microsystems - Beijing China temp = rx_sens_p->last_false_alarm_cnt_cck;
5587cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->last_false_alarm_cnt_cck = cck_fa;
5588cdc64593Sxinghua wen - Sun Microsystems - Beijing China cck_fa += (0xFFFFFFFF - temp);
5589cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
5590cdc64593Sxinghua wen - Sun Microsystems - Beijing China cck_fa -= rx_sens_p->last_false_alarm_cnt_cck;
5591cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->last_false_alarm_cnt_cck += cck_fa;
5592cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5593cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5594cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* accumulate bad plcp */
5595cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rx_sens_p->last_bad_plcp_cnt_cck > cck_bp) {
5596cdc64593Sxinghua wen - Sun Microsystems - Beijing China temp = rx_sens_p->last_bad_plcp_cnt_cck;
5597cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->last_bad_plcp_cnt_cck = cck_bp;
5598cdc64593Sxinghua wen - Sun Microsystems - Beijing China cck_bp += (0xFFFFFFFF - temp);
5599cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
5600cdc64593Sxinghua wen - Sun Microsystems - Beijing China cck_bp -= rx_sens_p->last_bad_plcp_cnt_cck;
5601cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->last_bad_plcp_cnt_cck += cck_bp;
5602cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5603cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5604cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
5605cdc64593Sxinghua wen - Sun Microsystems - Beijing China * calculate relative value
5606cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
5607cdc64593Sxinghua wen - Sun Microsystems - Beijing China cck_sum_fa_bp = (cck_fa + cck_bp) * 200 * 1024;
5608cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_noise_diff = 0;
5609cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5610cdc64593Sxinghua wen - Sun Microsystems - Beijing China noise_a =
5611b510adaeSfei feng - Sun Microsystems - Beijing China (uint8_t)((LE_32(rx_general_p->beacon_silence_rssi_a) & 0xFF00) >>
5612b510adaeSfei feng - Sun Microsystems - Beijing China 8);
5613cdc64593Sxinghua wen - Sun Microsystems - Beijing China noise_b =
5614b510adaeSfei feng - Sun Microsystems - Beijing China (uint8_t)((LE_32(rx_general_p->beacon_silence_rssi_b) & 0xFF00) >>
5615b510adaeSfei feng - Sun Microsystems - Beijing China 8);
5616cdc64593Sxinghua wen - Sun Microsystems - Beijing China noise_c =
5617b510adaeSfei feng - Sun Microsystems - Beijing China (uint8_t)((LE_32(rx_general_p->beacon_silence_rssi_c) & 0xFF00) >>
5618b510adaeSfei feng - Sun Microsystems - Beijing China 8);
5619cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5620b510adaeSfei feng - Sun Microsystems - Beijing China beacon_a = LE_32(rx_general_p->beacon_energy_a);
5621b510adaeSfei feng - Sun Microsystems - Beijing China beacon_b = LE_32(rx_general_p->beacon_energy_b);
5622b510adaeSfei feng - Sun Microsystems - Beijing China beacon_c = LE_32(rx_general_p->beacon_energy_c);
5623cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5624cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine maximum noise among 3 chains */
5625cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((noise_a >= noise_b) && (noise_a >= noise_c)) {
5626cdc64593Sxinghua wen - Sun Microsystems - Beijing China max_noise_abc = noise_a;
5627cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else if (noise_b >= noise_c) {
5628cdc64593Sxinghua wen - Sun Microsystems - Beijing China max_noise_abc = noise_b;
5629cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
5630cdc64593Sxinghua wen - Sun Microsystems - Beijing China max_noise_abc = noise_c;
5631cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5632cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5633cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* record maximum noise among 3 chains */
5634cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_noise_max[rx_sens_p->cck_noise_idx] = max_noise_abc;
5635cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_noise_idx++;
5636cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rx_sens_p->cck_noise_idx >= 20) {
5637cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_noise_idx = 0;
5638cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5639cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5640cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine maximum noise among 20 max noise */
5641cdc64593Sxinghua wen - Sun Microsystems - Beijing China max_noise_20 = rx_sens_p->cck_noise_max[0];
5642cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < 20; i++) {
5643cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rx_sens_p->cck_noise_max[i] >= max_noise_20) {
5644cdc64593Sxinghua wen - Sun Microsystems - Beijing China max_noise_20 = rx_sens_p->cck_noise_max[i];
5645cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5646cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5647cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5648cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine minimum beacon among 3 chains */
5649cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((beacon_a <= beacon_b) && (beacon_a <= beacon_c)) {
5650cdc64593Sxinghua wen - Sun Microsystems - Beijing China min_beacon_abc = beacon_a;
5651cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else if (beacon_b <= beacon_c) {
5652cdc64593Sxinghua wen - Sun Microsystems - Beijing China min_beacon_abc = beacon_b;
5653cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
5654cdc64593Sxinghua wen - Sun Microsystems - Beijing China min_beacon_abc = beacon_c;
5655cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5656cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5657cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* record miminum beacon among 3 chains */
5658cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_beacon_min[rx_sens_p->cck_beacon_idx] = min_beacon_abc;
5659cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_beacon_idx++;
5660cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rx_sens_p->cck_beacon_idx >= 10) {
5661cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_beacon_idx = 0;
5662cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5663cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5664cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine maximum beacon among 10 miminum beacon among 3 chains */
5665cdc64593Sxinghua wen - Sun Microsystems - Beijing China max_beacon_10 = rx_sens_p->cck_beacon_min[0];
5666cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < 10; i++) {
5667cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rx_sens_p->cck_beacon_min[i] >= max_beacon_10) {
5668cdc64593Sxinghua wen - Sun Microsystems - Beijing China max_beacon_10 = rx_sens_p->cck_beacon_min[i];
5669cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5670cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5671cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5672cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* add a little margin */
5673cdc64593Sxinghua wen - Sun Microsystems - Beijing China max_beacon_10 += 6;
5674cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5675cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* record the count of having no false alarms */
5676cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (cck_sum_fa_bp < (5 * actual_rx_time)) {
5677cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_no_false_alarm_num++;
5678cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
5679cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_no_false_alarm_num = 0;
5680cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5681cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5682cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
5683cdc64593Sxinghua wen - Sun Microsystems - Beijing China * adjust parameters in sensitivity command
5684cdc64593Sxinghua wen - Sun Microsystems - Beijing China * according to different status.
5685cdc64593Sxinghua wen - Sun Microsystems - Beijing China * for more infomation, please refer to iwk_calibration.h file
5686cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
5687cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (cck_sum_fa_bp > (50 * actual_rx_time)) {
5688cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_curr_state = IWK_TOO_MANY_FALSE_ALARM;
5689cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5690cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rx_sens_p->auto_corr_cck_x4 > 160) {
5691cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_noise_ref = max_noise_20;
5692cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5693cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rx_sens_p->min_energy_det_cck > 2) {
5694cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->min_energy_det_cck -= 2;
5695cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5696cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5697cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5698cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rx_sens_p->auto_corr_cck_x4 < 160) {
5699cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_cck_x4 = 160 + 1;
5700cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
5701cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((rx_sens_p->auto_corr_cck_x4 + 3) < 200) {
5702cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_cck_x4 += 3;
5703cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
5704cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_cck_x4 = 200;
5705cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5706cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5707cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5708cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((rx_sens_p->auto_corr_mrc_cck_x4 + 3) < 400) {
5709cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_cck_x4 += 3;
5710cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
5711cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_cck_x4 = 400;
5712cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5713cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5714cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->flags |= IWK_SENSITIVITY_CCK_UPDATE_MSK;
5715cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5716cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else if (cck_sum_fa_bp < (5 * actual_rx_time)) {
5717cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_curr_state = IWK_TOO_FEW_FALSE_ALARM;
5718cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5719cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_noise_diff = (int32_t)rx_sens_p->cck_noise_ref -
5720cdc64593Sxinghua wen - Sun Microsystems - Beijing China (int32_t)max_noise_20;
5721cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5722cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((rx_sens_p->cck_prev_state != IWK_TOO_MANY_FALSE_ALARM) &&
5723cdc64593Sxinghua wen - Sun Microsystems - Beijing China ((rx_sens_p->cck_noise_diff > 2) ||
5724cdc64593Sxinghua wen - Sun Microsystems - Beijing China (rx_sens_p->cck_no_false_alarm_num > 100))) {
5725cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((rx_sens_p->min_energy_det_cck + 2) < 97) {
5726cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->min_energy_det_cck += 2;
5727cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
5728cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->min_energy_det_cck = 97;
5729cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5730cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5731cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((rx_sens_p->auto_corr_cck_x4 - 3) > 125) {
5732cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_cck_x4 -= 3;
5733cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
5734cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_cck_x4 = 125;
5735cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5736cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5737cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((rx_sens_p->auto_corr_mrc_cck_x4 -3) > 200) {
5738cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_cck_x4 -= 3;
5739cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
5740cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_cck_x4 = 200;
5741cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5742cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5743cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->flags |= IWK_SENSITIVITY_CCK_UPDATE_MSK;
5744cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
5745cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->flags &= (~IWK_SENSITIVITY_CCK_UPDATE_MSK);
5746cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5747cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
5748cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_curr_state = IWK_GOOD_RANGE_FALSE_ALARM;
5749cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5750cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_noise_ref = max_noise_20;
5751cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5752cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (IWK_TOO_MANY_FALSE_ALARM == rx_sens_p->cck_prev_state) {
5753cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->min_energy_det_cck -= 8;
5754cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5755cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5756cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->flags &= (~IWK_SENSITIVITY_CCK_UPDATE_MSK);
5757cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5758cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5759cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rx_sens_p->min_energy_det_cck < max_beacon_10) {
5760cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->min_energy_det_cck = (uint16_t)max_beacon_10;
5761cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5762cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5763cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_prev_state = rx_sens_p->cck_curr_state;
5764cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5765cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS);
5766cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5767cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5768cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
5769cdc64593Sxinghua wen - Sun Microsystems - Beijing China * make Rx sensitivity calibration for OFDM mode.
5770cdc64593Sxinghua wen - Sun Microsystems - Beijing China * This is preparing parameters for Sensitivity command
5771cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
iwk_ofdm_sens(iwk_sc_t * sc,uint32_t actual_rx_time)5772cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_ofdm_sens(iwk_sc_t *sc, uint32_t actual_rx_time)
5773cdc64593Sxinghua wen - Sun Microsystems - Beijing China {
5774cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t temp;
5775cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint16_t temp1;
5776cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t ofdm_fa, ofdm_bp;
5777cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t ofdm_sum_fa_bp;
5778cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_rx_sensitivity *rx_sens_p = &sc->sc_rx_sens;
5779cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5780b510adaeSfei feng - Sun Microsystems - Beijing China ofdm_fa = LE_32(sc->sc_statistics.rx.ofdm.false_alarm_cnt);
5781b510adaeSfei feng - Sun Microsystems - Beijing China ofdm_bp = LE_32(sc->sc_statistics.rx.ofdm.plcp_err);
5782cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5783cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* accumulate false alarm */
5784cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rx_sens_p->last_false_alarm_cnt_ofdm > ofdm_fa) {
5785cdc64593Sxinghua wen - Sun Microsystems - Beijing China temp = rx_sens_p->last_false_alarm_cnt_ofdm;
5786cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->last_false_alarm_cnt_ofdm = ofdm_fa;
5787cdc64593Sxinghua wen - Sun Microsystems - Beijing China ofdm_fa += (0xFFFFFFFF - temp);
5788cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
5789cdc64593Sxinghua wen - Sun Microsystems - Beijing China ofdm_fa -= rx_sens_p->last_false_alarm_cnt_ofdm;
5790cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->last_false_alarm_cnt_ofdm += ofdm_fa;
5791cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5792cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5793cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* accumulate bad plcp */
5794cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rx_sens_p->last_bad_plcp_cnt_ofdm > ofdm_bp) {
5795cdc64593Sxinghua wen - Sun Microsystems - Beijing China temp = rx_sens_p->last_bad_plcp_cnt_ofdm;
5796cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->last_bad_plcp_cnt_ofdm = ofdm_bp;
5797cdc64593Sxinghua wen - Sun Microsystems - Beijing China ofdm_bp += (0xFFFFFFFF - temp);
5798cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
5799cdc64593Sxinghua wen - Sun Microsystems - Beijing China ofdm_bp -= rx_sens_p->last_bad_plcp_cnt_ofdm;
5800cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->last_bad_plcp_cnt_ofdm += ofdm_bp;
5801cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5802cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5803cdc64593Sxinghua wen - Sun Microsystems - Beijing China ofdm_sum_fa_bp = (ofdm_fa + ofdm_bp) * 200 * 1024; /* relative value */
5804cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5805cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
5806cdc64593Sxinghua wen - Sun Microsystems - Beijing China * adjust parameter in sensitivity command according to different status
5807cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
5808cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (ofdm_sum_fa_bp > (50 * actual_rx_time)) {
5809cdc64593Sxinghua wen - Sun Microsystems - Beijing China temp1 = rx_sens_p->auto_corr_ofdm_x4 + 1;
5810cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_ofdm_x4 = (temp1 <= 120) ? temp1 : 120;
5811cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5812cdc64593Sxinghua wen - Sun Microsystems - Beijing China temp1 = rx_sens_p->auto_corr_mrc_ofdm_x4 + 1;
5813cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_ofdm_x4 =
5814cdc64593Sxinghua wen - Sun Microsystems - Beijing China (temp1 <= 210) ? temp1 : 210;
5815cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5816cdc64593Sxinghua wen - Sun Microsystems - Beijing China temp1 = rx_sens_p->auto_corr_ofdm_x1 + 1;
5817cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_ofdm_x1 = (temp1 <= 140) ? temp1 : 140;
5818cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5819cdc64593Sxinghua wen - Sun Microsystems - Beijing China temp1 = rx_sens_p->auto_corr_mrc_ofdm_x1 + 1;
5820cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_ofdm_x1 =
5821cdc64593Sxinghua wen - Sun Microsystems - Beijing China (temp1 <= 270) ? temp1 : 270;
5822cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5823cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->flags |= IWK_SENSITIVITY_OFDM_UPDATE_MSK;
5824cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5825cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else if (ofdm_sum_fa_bp < (5 * actual_rx_time)) {
5826cdc64593Sxinghua wen - Sun Microsystems - Beijing China temp1 = rx_sens_p->auto_corr_ofdm_x4 - 1;
5827cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_ofdm_x4 = (temp1 >= 85) ? temp1 : 85;
5828cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5829cdc64593Sxinghua wen - Sun Microsystems - Beijing China temp1 = rx_sens_p->auto_corr_mrc_ofdm_x4 - 1;
5830cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_ofdm_x4 =
5831cdc64593Sxinghua wen - Sun Microsystems - Beijing China (temp1 >= 170) ? temp1 : 170;
5832cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5833cdc64593Sxinghua wen - Sun Microsystems - Beijing China temp1 = rx_sens_p->auto_corr_ofdm_x1 - 1;
5834cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_ofdm_x1 = (temp1 >= 105) ? temp1 : 105;
5835cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5836cdc64593Sxinghua wen - Sun Microsystems - Beijing China temp1 = rx_sens_p->auto_corr_mrc_ofdm_x1 - 1;
5837cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_ofdm_x1 =
5838cdc64593Sxinghua wen - Sun Microsystems - Beijing China (temp1 >= 220) ? temp1 : 220;
5839cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5840cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->flags |= IWK_SENSITIVITY_OFDM_UPDATE_MSK;
5841cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5842cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
5843cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->flags &= (~IWK_SENSITIVITY_OFDM_UPDATE_MSK);
5844cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5845cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5846cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS);
5847cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5848cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5849cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
585019d332feSfei feng - Sun Microsystems - Beijing China * additional process to management frames
585119d332feSfei feng - Sun Microsystems - Beijing China */
iwk_recv_mgmt(struct ieee80211com * ic,mblk_t * mp,struct ieee80211_node * in,int subtype,int rssi,uint32_t rstamp)585219d332feSfei feng - Sun Microsystems - Beijing China static void iwk_recv_mgmt(struct ieee80211com *ic, mblk_t *mp,
585319d332feSfei feng - Sun Microsystems - Beijing China struct ieee80211_node *in,
585419d332feSfei feng - Sun Microsystems - Beijing China int subtype, int rssi, uint32_t rstamp)
585519d332feSfei feng - Sun Microsystems - Beijing China {
585619d332feSfei feng - Sun Microsystems - Beijing China iwk_sc_t *sc = (iwk_sc_t *)ic;
585719d332feSfei feng - Sun Microsystems - Beijing China struct ieee80211_frame *wh;
585819d332feSfei feng - Sun Microsystems - Beijing China uint8_t index1, index2;
585919d332feSfei feng - Sun Microsystems - Beijing China int err;
586019d332feSfei feng - Sun Microsystems - Beijing China
586119d332feSfei feng - Sun Microsystems - Beijing China sc->sc_recv_mgmt(ic, mp, in, subtype, rssi, rstamp);
586219d332feSfei feng - Sun Microsystems - Beijing China
586319d332feSfei feng - Sun Microsystems - Beijing China mutex_enter(&sc->sc_glock);
586419d332feSfei feng - Sun Microsystems - Beijing China switch (subtype) {
586519d332feSfei feng - Sun Microsystems - Beijing China case IEEE80211_FC0_SUBTYPE_BEACON:
586619d332feSfei feng - Sun Microsystems - Beijing China if (sc->sc_ibss.ibss_beacon.syncbeacon && in == ic->ic_bss &&
586719d332feSfei feng - Sun Microsystems - Beijing China ic->ic_state == IEEE80211_S_RUN) {
586819d332feSfei feng - Sun Microsystems - Beijing China if (ieee80211_beacon_update(ic, in,
586919d332feSfei feng - Sun Microsystems - Beijing China &sc->sc_ibss.ibss_beacon.iwk_boff,
587019d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_beacon.mp, 0)) {
587119d332feSfei feng - Sun Microsystems - Beijing China bcopy(sc->sc_ibss.ibss_beacon.mp->b_rptr,
587219d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_beacon.beacon_cmd.
587319d332feSfei feng - Sun Microsystems - Beijing China bcon_frame,
587419d332feSfei feng - Sun Microsystems - Beijing China MBLKL(sc->sc_ibss.ibss_beacon.mp));
587519d332feSfei feng - Sun Microsystems - Beijing China }
587619d332feSfei feng - Sun Microsystems - Beijing China err = iwk_cmd(sc, REPLY_TX_BEACON,
587719d332feSfei feng - Sun Microsystems - Beijing China &sc->sc_ibss.ibss_beacon.beacon_cmd,
587819d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_beacon.beacon_cmd_len, 1);
587919d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) {
588019d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_recv_mgmt(): "
588119d332feSfei feng - Sun Microsystems - Beijing China "failed to TX beacon.\n");
588219d332feSfei feng - Sun Microsystems - Beijing China }
588319d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_beacon.syncbeacon = 0;
588419d332feSfei feng - Sun Microsystems - Beijing China }
588519d332feSfei feng - Sun Microsystems - Beijing China if (ic->ic_opmode == IEEE80211_M_IBSS &&
588619d332feSfei feng - Sun Microsystems - Beijing China ic->ic_state == IEEE80211_S_RUN) {
588719d332feSfei feng - Sun Microsystems - Beijing China wh = (struct ieee80211_frame *)mp->b_rptr;
588819d332feSfei feng - Sun Microsystems - Beijing China mutex_enter(&sc->sc_ibss.node_tb_lock);
588919d332feSfei feng - Sun Microsystems - Beijing China /*
589019d332feSfei feng - Sun Microsystems - Beijing China * search for node in ibss node table
589119d332feSfei feng - Sun Microsystems - Beijing China */
589219d332feSfei feng - Sun Microsystems - Beijing China for (index1 = IWK_STA_ID; index1 < IWK_STATION_COUNT;
589319d332feSfei feng - Sun Microsystems - Beijing China index1++) {
589419d332feSfei feng - Sun Microsystems - Beijing China if (sc->sc_ibss.ibss_node_tb[index1].used &&
589519d332feSfei feng - Sun Microsystems - Beijing China IEEE80211_ADDR_EQ(sc->sc_ibss.
589619d332feSfei feng - Sun Microsystems - Beijing China ibss_node_tb[index1].node.bssid,
589719d332feSfei feng - Sun Microsystems - Beijing China wh->i_addr2)) {
589819d332feSfei feng - Sun Microsystems - Beijing China break;
589919d332feSfei feng - Sun Microsystems - Beijing China }
590019d332feSfei feng - Sun Microsystems - Beijing China }
590119d332feSfei feng - Sun Microsystems - Beijing China /*
590219d332feSfei feng - Sun Microsystems - Beijing China * if don't find in ibss node table
590319d332feSfei feng - Sun Microsystems - Beijing China */
590419d332feSfei feng - Sun Microsystems - Beijing China if (index1 >= IWK_BROADCAST_ID) {
590519d332feSfei feng - Sun Microsystems - Beijing China err = iwk_clean_add_node_ibss(ic,
590619d332feSfei feng - Sun Microsystems - Beijing China wh->i_addr2, &index2);
590719d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) {
590819d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_recv_mgmt(): "
590919d332feSfei feng - Sun Microsystems - Beijing China "failed to clean all nodes "
591019d332feSfei feng - Sun Microsystems - Beijing China "and add one node\n");
591119d332feSfei feng - Sun Microsystems - Beijing China }
591219d332feSfei feng - Sun Microsystems - Beijing China }
591319d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_ibss.node_tb_lock);
591419d332feSfei feng - Sun Microsystems - Beijing China }
591519d332feSfei feng - Sun Microsystems - Beijing China break;
591619d332feSfei feng - Sun Microsystems - Beijing China case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
591719d332feSfei feng - Sun Microsystems - Beijing China break;
591819d332feSfei feng - Sun Microsystems - Beijing China }
591919d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock);
592019d332feSfei feng - Sun Microsystems - Beijing China }
592119d332feSfei feng - Sun Microsystems - Beijing China
592219d332feSfei feng - Sun Microsystems - Beijing China /*
5923cdc64593Sxinghua wen - Sun Microsystems - Beijing China * 1) log_event_table_ptr indicates base of the event log. This traces
5924cdc64593Sxinghua wen - Sun Microsystems - Beijing China * a 256-entry history of uCode execution within a circular buffer.
5925cdc64593Sxinghua wen - Sun Microsystems - Beijing China * Its header format is:
5926cdc64593Sxinghua wen - Sun Microsystems - Beijing China *
5927cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t log_size; log capacity (in number of entries)
5928cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t type; (1) timestamp with each entry, (0) no timestamp
5929cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t wraps; # times uCode has wrapped to top of circular buffer
5930cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t write_index; next circular buffer entry that uCode would fill
5931cdc64593Sxinghua wen - Sun Microsystems - Beijing China *
5932cdc64593Sxinghua wen - Sun Microsystems - Beijing China * The header is followed by the circular buffer of log entries. Entries
5933cdc64593Sxinghua wen - Sun Microsystems - Beijing China * with timestamps have the following format:
5934cdc64593Sxinghua wen - Sun Microsystems - Beijing China *
5935cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t event_id; range 0 - 1500
5936cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t timestamp; low 32 bits of TSF (of network, if associated)
5937cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t data; event_id-specific data value
5938cdc64593Sxinghua wen - Sun Microsystems - Beijing China *
5939cdc64593Sxinghua wen - Sun Microsystems - Beijing China * Entries without timestamps contain only event_id and data.
5940cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
5941cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5942cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
5943cdc64593Sxinghua wen - Sun Microsystems - Beijing China * iwk_write_event_log - Write event log to dmesg
5944cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
iwk_write_event_log(iwk_sc_t * sc)5945cdc64593Sxinghua wen - Sun Microsystems - Beijing China static void iwk_write_event_log(iwk_sc_t *sc)
5946cdc64593Sxinghua wen - Sun Microsystems - Beijing China {
5947cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t log_event_table_ptr; /* Start address of event table */
5948cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t startptr; /* Start address of log data */
5949cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t logptr; /* address of log data entry */
5950cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t i, n, num_events;
5951cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t event_id, data1, data2; /* log data */
5952cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5953cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t log_size; /* log capacity (in number of entries) */
5954cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t type; /* (1)timestamp with each entry,(0) no timestamp */
5955cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t wraps; /* # times uCode has wrapped to */
5956cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* the top of circular buffer */
5957cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t idx; /* index of entry to be filled in next */
5958cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5959b510adaeSfei feng - Sun Microsystems - Beijing China log_event_table_ptr = LE_32(sc->sc_card_alive_run.log_event_table_ptr);
5960cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!(log_event_table_ptr)) {
5961cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "NULL event table pointer\n"));
5962cdc64593Sxinghua wen - Sun Microsystems - Beijing China return;
5963cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5964cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5965cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_mac_access_enter(sc);
5966cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5967cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* Read log header */
5968cdc64593Sxinghua wen - Sun Microsystems - Beijing China log_size = iwk_mem_read(sc, log_event_table_ptr);
5969cdc64593Sxinghua wen - Sun Microsystems - Beijing China log_event_table_ptr += sizeof (uint32_t); /* addr of "type" */
5970cdc64593Sxinghua wen - Sun Microsystems - Beijing China type = iwk_mem_read(sc, log_event_table_ptr);
5971cdc64593Sxinghua wen - Sun Microsystems - Beijing China log_event_table_ptr += sizeof (uint32_t); /* addr of "wraps" */
5972cdc64593Sxinghua wen - Sun Microsystems - Beijing China wraps = iwk_mem_read(sc, log_event_table_ptr);
5973cdc64593Sxinghua wen - Sun Microsystems - Beijing China log_event_table_ptr += sizeof (uint32_t); /* addr of "idx" */
5974cdc64593Sxinghua wen - Sun Microsystems - Beijing China idx = iwk_mem_read(sc, log_event_table_ptr);
5975cdc64593Sxinghua wen - Sun Microsystems - Beijing China startptr = log_event_table_ptr +
5976cdc64593Sxinghua wen - Sun Microsystems - Beijing China sizeof (uint32_t); /* addr of start of log data */
5977cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!log_size & !wraps) {
5978cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "Empty log\n"));
5979cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_mac_access_exit(sc);
5980cdc64593Sxinghua wen - Sun Microsystems - Beijing China return;
5981cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5982cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5983cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!wraps) {
5984cdc64593Sxinghua wen - Sun Microsystems - Beijing China num_events = idx;
5985cdc64593Sxinghua wen - Sun Microsystems - Beijing China logptr = startptr;
5986cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else {
5987cdc64593Sxinghua wen - Sun Microsystems - Beijing China num_events = log_size - idx;
5988cdc64593Sxinghua wen - Sun Microsystems - Beijing China n = type ? 2 : 3;
5989cdc64593Sxinghua wen - Sun Microsystems - Beijing China logptr = startptr + (idx * n * sizeof (uint32_t));
5990cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
5991cdc64593Sxinghua wen - Sun Microsystems - Beijing China
5992cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < num_events; i++) {
5993cdc64593Sxinghua wen - Sun Microsystems - Beijing China event_id = iwk_mem_read(sc, logptr);
5994cdc64593Sxinghua wen - Sun Microsystems - Beijing China logptr += sizeof (uint32_t);
5995cdc64593Sxinghua wen - Sun Microsystems - Beijing China data1 = iwk_mem_read(sc, logptr);
5996cdc64593Sxinghua wen - Sun Microsystems - Beijing China logptr += sizeof (uint32_t);
5997cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (type == 0) { /* no timestamp */
5998cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "Event ID=%d, Data=%x0x",
5999cdc64593Sxinghua wen - Sun Microsystems - Beijing China event_id, data1));
6000cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { /* timestamp */
6001cdc64593Sxinghua wen - Sun Microsystems - Beijing China data2 = iwk_mem_read(sc, logptr);
6002cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM,
6003cdc64593Sxinghua wen - Sun Microsystems - Beijing China "Time=%d, Event ID=%d, Data=0x%x\n",
6004cdc64593Sxinghua wen - Sun Microsystems - Beijing China data1, event_id, data2));
6005cdc64593Sxinghua wen - Sun Microsystems - Beijing China logptr += sizeof (uint32_t);
6006cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
6007cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
6008cdc64593Sxinghua wen - Sun Microsystems - Beijing China
6009cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
6010cdc64593Sxinghua wen - Sun Microsystems - Beijing China * Print the wrapped around entries, if any
6011cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
6012cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (wraps) {
6013cdc64593Sxinghua wen - Sun Microsystems - Beijing China logptr = startptr;
6014cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < idx; i++) {
6015cdc64593Sxinghua wen - Sun Microsystems - Beijing China event_id = iwk_mem_read(sc, logptr);
6016cdc64593Sxinghua wen - Sun Microsystems - Beijing China logptr += sizeof (uint32_t);
6017cdc64593Sxinghua wen - Sun Microsystems - Beijing China data1 = iwk_mem_read(sc, logptr);
6018cdc64593Sxinghua wen - Sun Microsystems - Beijing China logptr += sizeof (uint32_t);
6019cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (type == 0) { /* no timestamp */
6020cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM,
6021cdc64593Sxinghua wen - Sun Microsystems - Beijing China "Event ID=%d, Data=%x0x", event_id, data1));
6022cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { /* timestamp */
6023cdc64593Sxinghua wen - Sun Microsystems - Beijing China data2 = iwk_mem_read(sc, logptr);
6024cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM,
6025cdc64593Sxinghua wen - Sun Microsystems - Beijing China "Time = %d, Event ID=%d, Data=0x%x\n",
6026cdc64593Sxinghua wen - Sun Microsystems - Beijing China data1, event_id, data2));
6027cdc64593Sxinghua wen - Sun Microsystems - Beijing China logptr += sizeof (uint32_t);
6028cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
6029cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
6030cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
6031cdc64593Sxinghua wen - Sun Microsystems - Beijing China
6032cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_mac_access_exit(sc);
6033cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
6034cdc64593Sxinghua wen - Sun Microsystems - Beijing China
6035cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
6036cdc64593Sxinghua wen - Sun Microsystems - Beijing China * error_event_table_ptr indicates base of the error log. This contains
6037cdc64593Sxinghua wen - Sun Microsystems - Beijing China * information about any uCode error that occurs. For 4965, the format is:
6038cdc64593Sxinghua wen - Sun Microsystems - Beijing China *
6039cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t valid; (nonzero) valid, (0) log is empty
6040cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t error_id; type of error
6041cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t pc; program counter
6042cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t blink1; branch link
6043cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t blink2; branch link
6044cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t ilink1; interrupt link
6045cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t ilink2; interrupt link
6046cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t data1; error-specific data
6047cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t data2; error-specific data
6048cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t line; source code line of error
6049cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t bcon_time; beacon timer
6050cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t tsf_low; network timestamp function timer
6051cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t tsf_hi; network timestamp function timer
6052cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
6053cdc64593Sxinghua wen - Sun Microsystems - Beijing China /*
6054cdc64593Sxinghua wen - Sun Microsystems - Beijing China * iwk_write_error_log - Write error log to dmesg
6055cdc64593Sxinghua wen - Sun Microsystems - Beijing China */
iwk_write_error_log(iwk_sc_t * sc)6056cdc64593Sxinghua wen - Sun Microsystems - Beijing China static void iwk_write_error_log(iwk_sc_t *sc)
6057cdc64593Sxinghua wen - Sun Microsystems - Beijing China {
6058cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t err_ptr; /* Start address of error log */
6059cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t valid; /* is error log valid */
6060cdc64593Sxinghua wen - Sun Microsystems - Beijing China
6061b510adaeSfei feng - Sun Microsystems - Beijing China err_ptr = LE_32(sc->sc_card_alive_run.error_event_table_ptr);
6062cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!(err_ptr)) {
6063cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "NULL error table pointer\n"));
6064cdc64593Sxinghua wen - Sun Microsystems - Beijing China return;
6065cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
6066cdc64593Sxinghua wen - Sun Microsystems - Beijing China
6067cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_mac_access_enter(sc);
6068cdc64593Sxinghua wen - Sun Microsystems - Beijing China
6069cdc64593Sxinghua wen - Sun Microsystems - Beijing China valid = iwk_mem_read(sc, err_ptr);
6070cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!(valid)) {
6071cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "Error data not valid\n"));
6072cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_mac_access_exit(sc);
6073cdc64593Sxinghua wen - Sun Microsystems - Beijing China return;
6074cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
6075cdc64593Sxinghua wen - Sun Microsystems - Beijing China err_ptr += sizeof (uint32_t);
6076cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "err=%d ", iwk_mem_read(sc, err_ptr)));
6077cdc64593Sxinghua wen - Sun Microsystems - Beijing China err_ptr += sizeof (uint32_t);
6078cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "pc=0x%X ", iwk_mem_read(sc, err_ptr)));
6079cdc64593Sxinghua wen - Sun Microsystems - Beijing China err_ptr += sizeof (uint32_t);
6080cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM,
6081cdc64593Sxinghua wen - Sun Microsystems - Beijing China "branch link1=0x%X ", iwk_mem_read(sc, err_ptr)));
6082cdc64593Sxinghua wen - Sun Microsystems - Beijing China err_ptr += sizeof (uint32_t);
6083cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM,
6084cdc64593Sxinghua wen - Sun Microsystems - Beijing China "branch link2=0x%X ", iwk_mem_read(sc, err_ptr)));
6085cdc64593Sxinghua wen - Sun Microsystems - Beijing China err_ptr += sizeof (uint32_t);
6086cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM,
6087cdc64593Sxinghua wen - Sun Microsystems - Beijing China "interrupt link1=0x%X ", iwk_mem_read(sc, err_ptr)));
6088cdc64593Sxinghua wen - Sun Microsystems - Beijing China err_ptr += sizeof (uint32_t);
6089cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM,
6090cdc64593Sxinghua wen - Sun Microsystems - Beijing China "interrupt link2=0x%X ", iwk_mem_read(sc, err_ptr)));
6091cdc64593Sxinghua wen - Sun Microsystems - Beijing China err_ptr += sizeof (uint32_t);
6092cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "data1=0x%X ", iwk_mem_read(sc, err_ptr)));
6093cdc64593Sxinghua wen - Sun Microsystems - Beijing China err_ptr += sizeof (uint32_t);
6094cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "data2=0x%X ", iwk_mem_read(sc, err_ptr)));
6095cdc64593Sxinghua wen - Sun Microsystems - Beijing China err_ptr += sizeof (uint32_t);
6096cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "line=%d ", iwk_mem_read(sc, err_ptr)));
6097cdc64593Sxinghua wen - Sun Microsystems - Beijing China err_ptr += sizeof (uint32_t);
6098cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "bcon_time=%d ", iwk_mem_read(sc, err_ptr)));
6099cdc64593Sxinghua wen - Sun Microsystems - Beijing China err_ptr += sizeof (uint32_t);
6100cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "tsf_low=%d ", iwk_mem_read(sc, err_ptr)));
6101cdc64593Sxinghua wen - Sun Microsystems - Beijing China err_ptr += sizeof (uint32_t);
6102cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "tsf_hi=%d\n", iwk_mem_read(sc, err_ptr)));
6103cdc64593Sxinghua wen - Sun Microsystems - Beijing China
6104cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_mac_access_exit(sc);
6105cdc64593Sxinghua wen - Sun Microsystems - Beijing China }
610619d332feSfei feng - Sun Microsystems - Beijing China
610719d332feSfei feng - Sun Microsystems - Beijing China static int
iwk_run_state_config_ibss(ieee80211com_t * ic)610819d332feSfei feng - Sun Microsystems - Beijing China iwk_run_state_config_ibss(ieee80211com_t *ic)
610919d332feSfei feng - Sun Microsystems - Beijing China {
611019d332feSfei feng - Sun Microsystems - Beijing China iwk_sc_t *sc = (iwk_sc_t *)ic;
611119d332feSfei feng - Sun Microsystems - Beijing China ieee80211_node_t *in = ic->ic_bss;
611219d332feSfei feng - Sun Microsystems - Beijing China int i, err = IWK_SUCCESS;
611319d332feSfei feng - Sun Microsystems - Beijing China
611419d332feSfei feng - Sun Microsystems - Beijing China mutex_enter(&sc->sc_ibss.node_tb_lock);
611519d332feSfei feng - Sun Microsystems - Beijing China
611619d332feSfei feng - Sun Microsystems - Beijing China /*
611719d332feSfei feng - Sun Microsystems - Beijing China * clean all nodes in ibss node table assure be
611819d332feSfei feng - Sun Microsystems - Beijing China * consistent with hardware
611919d332feSfei feng - Sun Microsystems - Beijing China */
612019d332feSfei feng - Sun Microsystems - Beijing China for (i = IWK_STA_ID; i < IWK_STATION_COUNT; i++) {
612119d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_node_tb[i].used = 0;
612219d332feSfei feng - Sun Microsystems - Beijing China (void) memset(&sc->sc_ibss.ibss_node_tb[i].node,
612319d332feSfei feng - Sun Microsystems - Beijing China 0,
612419d332feSfei feng - Sun Microsystems - Beijing China sizeof (iwk_add_sta_t));
612519d332feSfei feng - Sun Microsystems - Beijing China }
612619d332feSfei feng - Sun Microsystems - Beijing China
612719d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.node_number = 0;
612819d332feSfei feng - Sun Microsystems - Beijing China
612919d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_ibss.node_tb_lock);
613019d332feSfei feng - Sun Microsystems - Beijing China
613119d332feSfei feng - Sun Microsystems - Beijing China /*
613219d332feSfei feng - Sun Microsystems - Beijing China * configure RX and TX
613319d332feSfei feng - Sun Microsystems - Beijing China */
613419d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.dev_type = RXON_DEV_TYPE_IBSS;
613519d332feSfei feng - Sun Microsystems - Beijing China
6136b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags |= LE_32(RXON_FLG_SHORT_PREAMBLE_MSK);
613719d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.filter_flags =
613819d332feSfei feng - Sun Microsystems - Beijing China LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
613919d332feSfei feng - Sun Microsystems - Beijing China RXON_FILTER_DIS_DECRYPT_MSK |
614019d332feSfei feng - Sun Microsystems - Beijing China RXON_FILTER_DIS_GRP_DECRYPT_MSK);
614119d332feSfei feng - Sun Microsystems - Beijing China
614219d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.assoc_id = 0;
614319d332feSfei feng - Sun Microsystems - Beijing China
614419d332feSfei feng - Sun Microsystems - Beijing China IEEE80211_ADDR_COPY(sc->sc_config.bssid, in->in_bssid);
6145b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.chan = LE_16(ieee80211_chan2ieee(ic,
6146b510adaeSfei feng - Sun Microsystems - Beijing China in->in_chan));
614719d332feSfei feng - Sun Microsystems - Beijing China
614819d332feSfei feng - Sun Microsystems - Beijing China if (ic->ic_curmode == IEEE80211_MODE_11B) {
614919d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.cck_basic_rates = 0x03;
615019d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.ofdm_basic_rates = 0;
615119d332feSfei feng - Sun Microsystems - Beijing China } else if ((in->in_chan != IEEE80211_CHAN_ANYC) &&
615219d332feSfei feng - Sun Microsystems - Beijing China (IEEE80211_IS_CHAN_5GHZ(in->in_chan))) {
615319d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.cck_basic_rates = 0;
615419d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.ofdm_basic_rates = 0x15;
615519d332feSfei feng - Sun Microsystems - Beijing China
615619d332feSfei feng - Sun Microsystems - Beijing China } else {
615719d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.cck_basic_rates = 0x0f;
615819d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.ofdm_basic_rates = 0xff;
615919d332feSfei feng - Sun Microsystems - Beijing China }
616019d332feSfei feng - Sun Microsystems - Beijing China
616119d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags &=
616219d332feSfei feng - Sun Microsystems - Beijing China ~LE_32(RXON_FLG_SHORT_PREAMBLE_MSK |
616319d332feSfei feng - Sun Microsystems - Beijing China RXON_FLG_SHORT_SLOT_MSK);
616419d332feSfei feng - Sun Microsystems - Beijing China
616519d332feSfei feng - Sun Microsystems - Beijing China if (ic->ic_flags & IEEE80211_F_SHSLOT) {
616619d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags |=
616719d332feSfei feng - Sun Microsystems - Beijing China LE_32(RXON_FLG_SHORT_SLOT_MSK);
616819d332feSfei feng - Sun Microsystems - Beijing China }
616919d332feSfei feng - Sun Microsystems - Beijing China
617019d332feSfei feng - Sun Microsystems - Beijing China if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) {
617119d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags |=
617219d332feSfei feng - Sun Microsystems - Beijing China LE_32(RXON_FLG_SHORT_PREAMBLE_MSK);
617319d332feSfei feng - Sun Microsystems - Beijing China }
617419d332feSfei feng - Sun Microsystems - Beijing China
617519d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.filter_flags |=
617619d332feSfei feng - Sun Microsystems - Beijing China LE_32(RXON_FILTER_ASSOC_MSK);
617719d332feSfei feng - Sun Microsystems - Beijing China
617819d332feSfei feng - Sun Microsystems - Beijing China err = iwk_cmd(sc, REPLY_RXON, &sc->sc_config,
617919d332feSfei feng - Sun Microsystems - Beijing China sizeof (iwk_rxon_cmd_t), 1);
618019d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) {
618119d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_run_state_config_ibss(): "
618219d332feSfei feng - Sun Microsystems - Beijing China "failed to update configuration.\n");
618319d332feSfei feng - Sun Microsystems - Beijing China return (err);
618419d332feSfei feng - Sun Microsystems - Beijing China }
618519d332feSfei feng - Sun Microsystems - Beijing China
618619d332feSfei feng - Sun Microsystems - Beijing China return (err);
618719d332feSfei feng - Sun Microsystems - Beijing China
618819d332feSfei feng - Sun Microsystems - Beijing China }
618919d332feSfei feng - Sun Microsystems - Beijing China
619019d332feSfei feng - Sun Microsystems - Beijing China static int
iwk_run_state_config_sta(ieee80211com_t * ic)619119d332feSfei feng - Sun Microsystems - Beijing China iwk_run_state_config_sta(ieee80211com_t *ic)
619219d332feSfei feng - Sun Microsystems - Beijing China {
619319d332feSfei feng - Sun Microsystems - Beijing China iwk_sc_t *sc = (iwk_sc_t *)ic;
619419d332feSfei feng - Sun Microsystems - Beijing China ieee80211_node_t *in = ic->ic_bss;
619519d332feSfei feng - Sun Microsystems - Beijing China int err = IWK_SUCCESS;
619619d332feSfei feng - Sun Microsystems - Beijing China
619719d332feSfei feng - Sun Microsystems - Beijing China /* update adapter's configuration */
619819d332feSfei feng - Sun Microsystems - Beijing China if (sc->sc_assoc_id != in->in_associd) {
619919d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_run_state_config_sta(): "
620019d332feSfei feng - Sun Microsystems - Beijing China "associate ID mismatch: expected %d, "
620119d332feSfei feng - Sun Microsystems - Beijing China "got %d\n",
620219d332feSfei feng - Sun Microsystems - Beijing China in->in_associd, sc->sc_assoc_id);
620319d332feSfei feng - Sun Microsystems - Beijing China }
6204b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.assoc_id = LE_16(in->in_associd & 0x3fff);
620519d332feSfei feng - Sun Microsystems - Beijing China
620619d332feSfei feng - Sun Microsystems - Beijing China /*
620719d332feSfei feng - Sun Microsystems - Beijing China * short preamble/slot time are
620819d332feSfei feng - Sun Microsystems - Beijing China * negotiated when associating
620919d332feSfei feng - Sun Microsystems - Beijing China */
621019d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags &=
621119d332feSfei feng - Sun Microsystems - Beijing China ~LE_32(RXON_FLG_SHORT_PREAMBLE_MSK |
621219d332feSfei feng - Sun Microsystems - Beijing China RXON_FLG_SHORT_SLOT_MSK);
621319d332feSfei feng - Sun Microsystems - Beijing China
621419d332feSfei feng - Sun Microsystems - Beijing China if (ic->ic_flags & IEEE80211_F_SHSLOT)
621519d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags |=
621619d332feSfei feng - Sun Microsystems - Beijing China LE_32(RXON_FLG_SHORT_SLOT_MSK);
621719d332feSfei feng - Sun Microsystems - Beijing China
621819d332feSfei feng - Sun Microsystems - Beijing China if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
621919d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags |=
622019d332feSfei feng - Sun Microsystems - Beijing China LE_32(RXON_FLG_SHORT_PREAMBLE_MSK);
622119d332feSfei feng - Sun Microsystems - Beijing China
622219d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.filter_flags |=
622319d332feSfei feng - Sun Microsystems - Beijing China LE_32(RXON_FILTER_ASSOC_MSK);
622419d332feSfei feng - Sun Microsystems - Beijing China
622519d332feSfei feng - Sun Microsystems - Beijing China if (ic->ic_opmode != IEEE80211_M_STA)
622619d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.filter_flags |=
622719d332feSfei feng - Sun Microsystems - Beijing China LE_32(RXON_FILTER_BCON_AWARE_MSK);
622819d332feSfei feng - Sun Microsystems - Beijing China
622919d332feSfei feng - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_80211, "config chan %d flags %x"
623019d332feSfei feng - Sun Microsystems - Beijing China " filter_flags %x\n",
623119d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.chan, sc->sc_config.flags,
623219d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.filter_flags));
623319d332feSfei feng - Sun Microsystems - Beijing China
623419d332feSfei feng - Sun Microsystems - Beijing China err = iwk_cmd(sc, REPLY_RXON, &sc->sc_config,
623519d332feSfei feng - Sun Microsystems - Beijing China sizeof (iwk_rxon_cmd_t), 1);
623619d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) {
623719d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_run_state_config_sta(): "
623819d332feSfei feng - Sun Microsystems - Beijing China "failed to update configuration\n");
623919d332feSfei feng - Sun Microsystems - Beijing China return (err);
624019d332feSfei feng - Sun Microsystems - Beijing China }
624119d332feSfei feng - Sun Microsystems - Beijing China
624219d332feSfei feng - Sun Microsystems - Beijing China return (err);
624319d332feSfei feng - Sun Microsystems - Beijing China }
624419d332feSfei feng - Sun Microsystems - Beijing China
624519d332feSfei feng - Sun Microsystems - Beijing China static int
iwk_fast_recover(iwk_sc_t * sc)62466f12def4Spengcheng chen - Sun Microsystems - Beijing China iwk_fast_recover(iwk_sc_t *sc)
62476f12def4Spengcheng chen - Sun Microsystems - Beijing China {
62486f12def4Spengcheng chen - Sun Microsystems - Beijing China ieee80211com_t *ic = &sc->sc_ic;
62496f12def4Spengcheng chen - Sun Microsystems - Beijing China int err;
62506f12def4Spengcheng chen - Sun Microsystems - Beijing China
62516f12def4Spengcheng chen - Sun Microsystems - Beijing China mutex_enter(&sc->sc_glock);
62526f12def4Spengcheng chen - Sun Microsystems - Beijing China
62536f12def4Spengcheng chen - Sun Microsystems - Beijing China /* restore runtime configuration */
62546f12def4Spengcheng chen - Sun Microsystems - Beijing China bcopy(&sc->sc_config_save, &sc->sc_config,
62556f12def4Spengcheng chen - Sun Microsystems - Beijing China sizeof (sc->sc_config));
62566f12def4Spengcheng chen - Sun Microsystems - Beijing China
62576f12def4Spengcheng chen - Sun Microsystems - Beijing China /* reset state to handle reassociations correctly */
62586f12def4Spengcheng chen - Sun Microsystems - Beijing China sc->sc_config.assoc_id = 0;
62596f12def4Spengcheng chen - Sun Microsystems - Beijing China sc->sc_config.filter_flags &=
62606f12def4Spengcheng chen - Sun Microsystems - Beijing China ~LE_32(RXON_FILTER_ASSOC_MSK);
62616f12def4Spengcheng chen - Sun Microsystems - Beijing China
62626f12def4Spengcheng chen - Sun Microsystems - Beijing China if ((err = iwk_hw_set_before_auth(sc)) != 0) {
62636f12def4Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_fast_recover(): "
62646f12def4Spengcheng chen - Sun Microsystems - Beijing China "failed to setup authentication\n");
62656f12def4Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock);
62666f12def4Spengcheng chen - Sun Microsystems - Beijing China return (err);
62676f12def4Spengcheng chen - Sun Microsystems - Beijing China }
62686f12def4Spengcheng chen - Sun Microsystems - Beijing China
62696f12def4Spengcheng chen - Sun Microsystems - Beijing China bcopy(&sc->sc_config_save, &sc->sc_config,
62706f12def4Spengcheng chen - Sun Microsystems - Beijing China sizeof (sc->sc_config));
62716f12def4Spengcheng chen - Sun Microsystems - Beijing China
62726f12def4Spengcheng chen - Sun Microsystems - Beijing China /* update adapter's configuration */
62736f12def4Spengcheng chen - Sun Microsystems - Beijing China err = iwk_run_state_config_sta(ic);
62746f12def4Spengcheng chen - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) {
62756f12def4Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_fast_recover(): "
62766f12def4Spengcheng chen - Sun Microsystems - Beijing China "failed to setup association\n");
62776f12def4Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock);
62786f12def4Spengcheng chen - Sun Microsystems - Beijing China return (err);
62796f12def4Spengcheng chen - Sun Microsystems - Beijing China }
62806f12def4Spengcheng chen - Sun Microsystems - Beijing China
62816f12def4Spengcheng chen - Sun Microsystems - Beijing China /* obtain current temperature of chipset */
62826f12def4Spengcheng chen - Sun Microsystems - Beijing China sc->sc_tempera = iwk_curr_tempera(sc);
62836f12def4Spengcheng chen - Sun Microsystems - Beijing China
62846f12def4Spengcheng chen - Sun Microsystems - Beijing China /*
62856f12def4Spengcheng chen - Sun Microsystems - Beijing China * make Tx power calibration to determine
62866f12def4Spengcheng chen - Sun Microsystems - Beijing China * the gains of DSP and radio
62876f12def4Spengcheng chen - Sun Microsystems - Beijing China */
62886f12def4Spengcheng chen - Sun Microsystems - Beijing China err = iwk_tx_power_calibration(sc);
62896f12def4Spengcheng chen - Sun Microsystems - Beijing China if (err) {
62906f12def4Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_fast_recover(): "
62916f12def4Spengcheng chen - Sun Microsystems - Beijing China "failed to set tx power table\n");
62926f12def4Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock);
62936f12def4Spengcheng chen - Sun Microsystems - Beijing China return (err);
62946f12def4Spengcheng chen - Sun Microsystems - Beijing China }
62956f12def4Spengcheng chen - Sun Microsystems - Beijing China
62966f12def4Spengcheng chen - Sun Microsystems - Beijing China /*
62976f12def4Spengcheng chen - Sun Microsystems - Beijing China * make initialization for Receiver
62986f12def4Spengcheng chen - Sun Microsystems - Beijing China * sensitivity calibration
62996f12def4Spengcheng chen - Sun Microsystems - Beijing China */
63006f12def4Spengcheng chen - Sun Microsystems - Beijing China err = iwk_rx_sens_init(sc);
63016f12def4Spengcheng chen - Sun Microsystems - Beijing China if (err) {
63026f12def4Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_fast_recover(): "
63036f12def4Spengcheng chen - Sun Microsystems - Beijing China "failed to init RX sensitivity\n");
63046f12def4Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock);
63056f12def4Spengcheng chen - Sun Microsystems - Beijing China return (err);
63066f12def4Spengcheng chen - Sun Microsystems - Beijing China }
63076f12def4Spengcheng chen - Sun Microsystems - Beijing China
63086f12def4Spengcheng chen - Sun Microsystems - Beijing China /* make initialization for Receiver gain balance */
63096f12def4Spengcheng chen - Sun Microsystems - Beijing China err = iwk_rxgain_diff_init(sc);
63106f12def4Spengcheng chen - Sun Microsystems - Beijing China if (err) {
63116f12def4Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_fast_recover(): "
63126f12def4Spengcheng chen - Sun Microsystems - Beijing China "failed to init phy calibration\n");
63136f12def4Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock);
63146f12def4Spengcheng chen - Sun Microsystems - Beijing China return (err);
63156f12def4Spengcheng chen - Sun Microsystems - Beijing China
63166f12def4Spengcheng chen - Sun Microsystems - Beijing China }
63176f12def4Spengcheng chen - Sun Microsystems - Beijing China /* set LED on */
63186f12def4Spengcheng chen - Sun Microsystems - Beijing China iwk_set_led(sc, 2, 0, 1);
63196f12def4Spengcheng chen - Sun Microsystems - Beijing China
63206f12def4Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock);
63216f12def4Spengcheng chen - Sun Microsystems - Beijing China
63226f12def4Spengcheng chen - Sun Microsystems - Beijing China /* update keys */
63236f12def4Spengcheng chen - Sun Microsystems - Beijing China if (ic->ic_flags & IEEE80211_F_PRIVACY) {
63246f12def4Spengcheng chen - Sun Microsystems - Beijing China for (int i = 0; i < IEEE80211_KEY_MAX; i++) {
63256f12def4Spengcheng chen - Sun Microsystems - Beijing China if (ic->ic_nw_keys[i].wk_keyix == IEEE80211_KEYIX_NONE)
63266f12def4Spengcheng chen - Sun Microsystems - Beijing China continue;
63276f12def4Spengcheng chen - Sun Microsystems - Beijing China err = iwk_key_set(ic, &ic->ic_nw_keys[i],
63286f12def4Spengcheng chen - Sun Microsystems - Beijing China ic->ic_bss->in_macaddr);
63296f12def4Spengcheng chen - Sun Microsystems - Beijing China /* failure */
63306f12def4Spengcheng chen - Sun Microsystems - Beijing China if (err == 0) {
63316f12def4Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_fast_recover(): "
63326f12def4Spengcheng chen - Sun Microsystems - Beijing China "failed to setup hardware keys\n");
63336f12def4Spengcheng chen - Sun Microsystems - Beijing China return (IWK_FAIL);
63346f12def4Spengcheng chen - Sun Microsystems - Beijing China }
63356f12def4Spengcheng chen - Sun Microsystems - Beijing China }
63366f12def4Spengcheng chen - Sun Microsystems - Beijing China }
63376f12def4Spengcheng chen - Sun Microsystems - Beijing China
63386f12def4Spengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~IWK_F_HW_ERR_RECOVER;
63396f12def4Spengcheng chen - Sun Microsystems - Beijing China
63406f12def4Spengcheng chen - Sun Microsystems - Beijing China /* start queue */
63416f12def4Spengcheng chen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_FW, "iwk_fast_recover(): resume xmit\n"));
63426f12def4Spengcheng chen - Sun Microsystems - Beijing China mac_tx_update(ic->ic_mach);
63436f12def4Spengcheng chen - Sun Microsystems - Beijing China
63446f12def4Spengcheng chen - Sun Microsystems - Beijing China
63456f12def4Spengcheng chen - Sun Microsystems - Beijing China return (IWK_SUCCESS);
63466f12def4Spengcheng chen - Sun Microsystems - Beijing China }
63476f12def4Spengcheng chen - Sun Microsystems - Beijing China
63486f12def4Spengcheng chen - Sun Microsystems - Beijing China static int
iwk_start_tx_beacon(ieee80211com_t * ic)634919d332feSfei feng - Sun Microsystems - Beijing China iwk_start_tx_beacon(ieee80211com_t *ic)
635019d332feSfei feng - Sun Microsystems - Beijing China {
635119d332feSfei feng - Sun Microsystems - Beijing China iwk_sc_t *sc = (iwk_sc_t *)ic;
635219d332feSfei feng - Sun Microsystems - Beijing China ieee80211_node_t *in = ic->ic_bss;
635319d332feSfei feng - Sun Microsystems - Beijing China int err = IWK_SUCCESS;
635419d332feSfei feng - Sun Microsystems - Beijing China iwk_tx_beacon_cmd_t *tx_beacon_p;
635519d332feSfei feng - Sun Microsystems - Beijing China uint16_t masks = 0;
635619d332feSfei feng - Sun Microsystems - Beijing China mblk_t *mp;
635719d332feSfei feng - Sun Microsystems - Beijing China int rate;
635819d332feSfei feng - Sun Microsystems - Beijing China
635919d332feSfei feng - Sun Microsystems - Beijing China /*
636019d332feSfei feng - Sun Microsystems - Beijing China * allocate and transmit beacon frames
636119d332feSfei feng - Sun Microsystems - Beijing China */
636219d332feSfei feng - Sun Microsystems - Beijing China tx_beacon_p = &sc->sc_ibss.ibss_beacon.beacon_cmd;
636319d332feSfei feng - Sun Microsystems - Beijing China
636419d332feSfei feng - Sun Microsystems - Beijing China (void) memset(tx_beacon_p, 0,
636519d332feSfei feng - Sun Microsystems - Beijing China sizeof (iwk_tx_beacon_cmd_t));
636619d332feSfei feng - Sun Microsystems - Beijing China rate = 0;
636719d332feSfei feng - Sun Microsystems - Beijing China masks = 0;
636819d332feSfei feng - Sun Microsystems - Beijing China
636919d332feSfei feng - Sun Microsystems - Beijing China tx_beacon_p->config.sta_id = IWK_BROADCAST_ID;
637019d332feSfei feng - Sun Microsystems - Beijing China tx_beacon_p->config.stop_time.life_time =
637119d332feSfei feng - Sun Microsystems - Beijing China LE_32(0xffffffff);
637219d332feSfei feng - Sun Microsystems - Beijing China
637319d332feSfei feng - Sun Microsystems - Beijing China if (sc->sc_ibss.ibss_beacon.mp != NULL) {
637419d332feSfei feng - Sun Microsystems - Beijing China freemsg(sc->sc_ibss.ibss_beacon.mp);
637519d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_beacon.mp = NULL;
637619d332feSfei feng - Sun Microsystems - Beijing China }
637719d332feSfei feng - Sun Microsystems - Beijing China
637819d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_beacon.mp =
637919d332feSfei feng - Sun Microsystems - Beijing China ieee80211_beacon_alloc(ic, in,
638019d332feSfei feng - Sun Microsystems - Beijing China &sc->sc_ibss.ibss_beacon.iwk_boff);
638119d332feSfei feng - Sun Microsystems - Beijing China if (sc->sc_ibss.ibss_beacon.mp == NULL) {
638219d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_start_tx_beacon(): "
638319d332feSfei feng - Sun Microsystems - Beijing China "failed to get beacon frame.\n");
638419d332feSfei feng - Sun Microsystems - Beijing China return (IWK_FAIL);
638519d332feSfei feng - Sun Microsystems - Beijing China }
638619d332feSfei feng - Sun Microsystems - Beijing China
638719d332feSfei feng - Sun Microsystems - Beijing China mp = sc->sc_ibss.ibss_beacon.mp;
638819d332feSfei feng - Sun Microsystems - Beijing China
638919d332feSfei feng - Sun Microsystems - Beijing China ASSERT(mp->b_cont == NULL);
639019d332feSfei feng - Sun Microsystems - Beijing China
639119d332feSfei feng - Sun Microsystems - Beijing China bcopy(mp->b_rptr, tx_beacon_p->bcon_frame, MBLKL(mp));
639219d332feSfei feng - Sun Microsystems - Beijing China
6393b510adaeSfei feng - Sun Microsystems - Beijing China tx_beacon_p->config.len = LE_16((uint16_t)(MBLKL(mp)));
639419d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_beacon.beacon_cmd_len =
639519d332feSfei feng - Sun Microsystems - Beijing China sizeof (iwk_tx_cmd_t) +
6396b510adaeSfei feng - Sun Microsystems - Beijing China 4 + LE_16(tx_beacon_p->config.len);
639719d332feSfei feng - Sun Microsystems - Beijing China
639819d332feSfei feng - Sun Microsystems - Beijing China /*
639919d332feSfei feng - Sun Microsystems - Beijing China * beacons are sent at 1M
640019d332feSfei feng - Sun Microsystems - Beijing China */
640119d332feSfei feng - Sun Microsystems - Beijing China rate = in->in_rates.ir_rates[0];
640219d332feSfei feng - Sun Microsystems - Beijing China rate &= IEEE80211_RATE_VAL;
640319d332feSfei feng - Sun Microsystems - Beijing China
640419d332feSfei feng - Sun Microsystems - Beijing China if (2 == rate || 4 == rate || 11 == rate ||
640519d332feSfei feng - Sun Microsystems - Beijing China 22 == rate) {
640619d332feSfei feng - Sun Microsystems - Beijing China masks |= RATE_MCS_CCK_MSK;
640719d332feSfei feng - Sun Microsystems - Beijing China }
640819d332feSfei feng - Sun Microsystems - Beijing China
640919d332feSfei feng - Sun Microsystems - Beijing China masks |= RATE_MCS_ANT_B_MSK;
641019d332feSfei feng - Sun Microsystems - Beijing China
641119d332feSfei feng - Sun Microsystems - Beijing China tx_beacon_p->config.rate.r.rate_n_flags =
6412b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(iwk_rate_to_plcp(rate) | masks);
641319d332feSfei feng - Sun Microsystems - Beijing China
641419d332feSfei feng - Sun Microsystems - Beijing China
641519d332feSfei feng - Sun Microsystems - Beijing China tx_beacon_p->config.tx_flags =
6416b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(TX_CMD_FLG_SEQ_CTL_MSK | TX_CMD_FLG_TSF_MSK);
641719d332feSfei feng - Sun Microsystems - Beijing China
641819d332feSfei feng - Sun Microsystems - Beijing China if (ic->ic_bss->in_tstamp.tsf != 0) {
641919d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_beacon.syncbeacon = 1;
642019d332feSfei feng - Sun Microsystems - Beijing China } else {
642119d332feSfei feng - Sun Microsystems - Beijing China if (ieee80211_beacon_update(ic, in,
642219d332feSfei feng - Sun Microsystems - Beijing China &sc->sc_ibss.ibss_beacon.iwk_boff,
642319d332feSfei feng - Sun Microsystems - Beijing China mp, 0)) {
642419d332feSfei feng - Sun Microsystems - Beijing China bcopy(mp->b_rptr,
642519d332feSfei feng - Sun Microsystems - Beijing China tx_beacon_p->bcon_frame,
642619d332feSfei feng - Sun Microsystems - Beijing China MBLKL(mp));
642719d332feSfei feng - Sun Microsystems - Beijing China }
642819d332feSfei feng - Sun Microsystems - Beijing China
642919d332feSfei feng - Sun Microsystems - Beijing China err = iwk_cmd(sc, REPLY_TX_BEACON,
643019d332feSfei feng - Sun Microsystems - Beijing China tx_beacon_p,
643119d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_beacon.beacon_cmd_len,
643219d332feSfei feng - Sun Microsystems - Beijing China 1);
643319d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) {
643419d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_start_tx_beacon(): "
643519d332feSfei feng - Sun Microsystems - Beijing China "failed to TX beacon.\n");
643619d332feSfei feng - Sun Microsystems - Beijing China return (err);
643719d332feSfei feng - Sun Microsystems - Beijing China }
643819d332feSfei feng - Sun Microsystems - Beijing China
643919d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_beacon.syncbeacon = 0;
644019d332feSfei feng - Sun Microsystems - Beijing China }
644119d332feSfei feng - Sun Microsystems - Beijing China
644219d332feSfei feng - Sun Microsystems - Beijing China return (err);
644319d332feSfei feng - Sun Microsystems - Beijing China }
644419d332feSfei feng - Sun Microsystems - Beijing China
644519d332feSfei feng - Sun Microsystems - Beijing China static int
iwk_clean_add_node_ibss(struct ieee80211com * ic,uint8_t addr[IEEE80211_ADDR_LEN],uint8_t * index2)644619d332feSfei feng - Sun Microsystems - Beijing China iwk_clean_add_node_ibss(struct ieee80211com *ic,
644719d332feSfei feng - Sun Microsystems - Beijing China uint8_t addr[IEEE80211_ADDR_LEN], uint8_t *index2)
644819d332feSfei feng - Sun Microsystems - Beijing China {
644919d332feSfei feng - Sun Microsystems - Beijing China iwk_sc_t *sc = (iwk_sc_t *)ic;
645019d332feSfei feng - Sun Microsystems - Beijing China uint8_t index;
645119d332feSfei feng - Sun Microsystems - Beijing China iwk_add_sta_t bc_node;
645219d332feSfei feng - Sun Microsystems - Beijing China iwk_link_quality_cmd_t bc_link_quality;
645319d332feSfei feng - Sun Microsystems - Beijing China iwk_link_quality_cmd_t link_quality;
645419d332feSfei feng - Sun Microsystems - Beijing China uint16_t bc_masks = 0;
645519d332feSfei feng - Sun Microsystems - Beijing China uint16_t masks = 0;
645619d332feSfei feng - Sun Microsystems - Beijing China int i, rate;
645719d332feSfei feng - Sun Microsystems - Beijing China struct ieee80211_rateset rs;
645819d332feSfei feng - Sun Microsystems - Beijing China iwk_ibss_node_t *ibss_node_p;
645919d332feSfei feng - Sun Microsystems - Beijing China int err = IWK_SUCCESS;
646019d332feSfei feng - Sun Microsystems - Beijing China
646119d332feSfei feng - Sun Microsystems - Beijing China /*
646219d332feSfei feng - Sun Microsystems - Beijing China * find a location that is not
646319d332feSfei feng - Sun Microsystems - Beijing China * used in ibss node table
646419d332feSfei feng - Sun Microsystems - Beijing China */
646519d332feSfei feng - Sun Microsystems - Beijing China for (index = IWK_STA_ID;
646619d332feSfei feng - Sun Microsystems - Beijing China index < IWK_STATION_COUNT; index++) {
646719d332feSfei feng - Sun Microsystems - Beijing China if (!sc->sc_ibss.ibss_node_tb[index].used) {
646819d332feSfei feng - Sun Microsystems - Beijing China break;
646919d332feSfei feng - Sun Microsystems - Beijing China }
647019d332feSfei feng - Sun Microsystems - Beijing China }
647119d332feSfei feng - Sun Microsystems - Beijing China
647219d332feSfei feng - Sun Microsystems - Beijing China /*
647319d332feSfei feng - Sun Microsystems - Beijing China * if have too many nodes in hardware, clean up
647419d332feSfei feng - Sun Microsystems - Beijing China */
647519d332feSfei feng - Sun Microsystems - Beijing China if (index < IWK_BROADCAST_ID &&
647619d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.node_number >= 25) {
647719d332feSfei feng - Sun Microsystems - Beijing China if (iwk_cmd(sc, REPLY_REMOVE_ALL_STA,
647819d332feSfei feng - Sun Microsystems - Beijing China NULL, 0, 1) != IWK_SUCCESS) {
647919d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_clean_add_node_ibss(): "
648019d332feSfei feng - Sun Microsystems - Beijing China "failed to remove all nodes in hardware\n");
648119d332feSfei feng - Sun Microsystems - Beijing China return (IWK_FAIL);
648219d332feSfei feng - Sun Microsystems - Beijing China }
648319d332feSfei feng - Sun Microsystems - Beijing China
648419d332feSfei feng - Sun Microsystems - Beijing China for (i = IWK_STA_ID; i < IWK_STATION_COUNT; i++) {
648519d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_node_tb[i].used = 0;
648619d332feSfei feng - Sun Microsystems - Beijing China (void) memset(&sc->sc_ibss.ibss_node_tb[i].node,
648719d332feSfei feng - Sun Microsystems - Beijing China 0, sizeof (iwk_add_sta_t));
648819d332feSfei feng - Sun Microsystems - Beijing China }
648919d332feSfei feng - Sun Microsystems - Beijing China
649019d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.node_number = 0;
649119d332feSfei feng - Sun Microsystems - Beijing China
649219d332feSfei feng - Sun Microsystems - Beijing China /*
649319d332feSfei feng - Sun Microsystems - Beijing China * add broadcast node so that we
649419d332feSfei feng - Sun Microsystems - Beijing China * can send broadcast frame
649519d332feSfei feng - Sun Microsystems - Beijing China */
649619d332feSfei feng - Sun Microsystems - Beijing China (void) memset(&bc_node, 0, sizeof (bc_node));
649719d332feSfei feng - Sun Microsystems - Beijing China (void) memset(bc_node.bssid, 0xff, 6);
649819d332feSfei feng - Sun Microsystems - Beijing China bc_node.id = IWK_BROADCAST_ID;
649919d332feSfei feng - Sun Microsystems - Beijing China
650019d332feSfei feng - Sun Microsystems - Beijing China err = iwk_cmd(sc, REPLY_ADD_STA, &bc_node, sizeof (bc_node), 1);
650119d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) {
650219d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_clean_add_node_ibss(): "
650319d332feSfei feng - Sun Microsystems - Beijing China "failed to add broadcast node\n");
650419d332feSfei feng - Sun Microsystems - Beijing China return (err);
650519d332feSfei feng - Sun Microsystems - Beijing China }
650619d332feSfei feng - Sun Microsystems - Beijing China
650719d332feSfei feng - Sun Microsystems - Beijing China /* TX_LINK_QUALITY cmd */
650819d332feSfei feng - Sun Microsystems - Beijing China (void) memset(&bc_link_quality, 0, sizeof (bc_link_quality));
650919d332feSfei feng - Sun Microsystems - Beijing China for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
651019d332feSfei feng - Sun Microsystems - Beijing China bc_masks |= RATE_MCS_CCK_MSK;
651119d332feSfei feng - Sun Microsystems - Beijing China bc_masks |= RATE_MCS_ANT_B_MSK;
651219d332feSfei feng - Sun Microsystems - Beijing China bc_masks &= ~RATE_MCS_ANT_A_MSK;
651319d332feSfei feng - Sun Microsystems - Beijing China bc_link_quality.rate_n_flags[i] =
6514b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(iwk_rate_to_plcp(2) | bc_masks);
651519d332feSfei feng - Sun Microsystems - Beijing China }
651619d332feSfei feng - Sun Microsystems - Beijing China
651719d332feSfei feng - Sun Microsystems - Beijing China bc_link_quality.general_params.single_stream_ant_msk = 2;
651819d332feSfei feng - Sun Microsystems - Beijing China bc_link_quality.general_params.dual_stream_ant_msk = 3;
651919d332feSfei feng - Sun Microsystems - Beijing China bc_link_quality.agg_params.agg_dis_start_th = 3;
652019d332feSfei feng - Sun Microsystems - Beijing China bc_link_quality.agg_params.agg_time_limit = LE_16(4000);
652119d332feSfei feng - Sun Microsystems - Beijing China bc_link_quality.sta_id = IWK_BROADCAST_ID;
652219d332feSfei feng - Sun Microsystems - Beijing China
652319d332feSfei feng - Sun Microsystems - Beijing China err = iwk_cmd(sc, REPLY_TX_LINK_QUALITY_CMD,
652419d332feSfei feng - Sun Microsystems - Beijing China &bc_link_quality, sizeof (bc_link_quality), 1);
652519d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) {
652619d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_clean_add_node_ibss(): "
652719d332feSfei feng - Sun Microsystems - Beijing China "failed to config link quality table\n");
652819d332feSfei feng - Sun Microsystems - Beijing China return (err);
652919d332feSfei feng - Sun Microsystems - Beijing China }
653019d332feSfei feng - Sun Microsystems - Beijing China }
653119d332feSfei feng - Sun Microsystems - Beijing China
653219d332feSfei feng - Sun Microsystems - Beijing China if (index >= IWK_BROADCAST_ID) {
653319d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_clean_add_node_ibss(): "
653419d332feSfei feng - Sun Microsystems - Beijing China "the count of node in hardware is too much\n");
653519d332feSfei feng - Sun Microsystems - Beijing China return (IWK_FAIL);
653619d332feSfei feng - Sun Microsystems - Beijing China }
653719d332feSfei feng - Sun Microsystems - Beijing China
653819d332feSfei feng - Sun Microsystems - Beijing China /*
653919d332feSfei feng - Sun Microsystems - Beijing China * add a node into hardware
654019d332feSfei feng - Sun Microsystems - Beijing China */
654119d332feSfei feng - Sun Microsystems - Beijing China ibss_node_p = &sc->sc_ibss.ibss_node_tb[index];
654219d332feSfei feng - Sun Microsystems - Beijing China
654319d332feSfei feng - Sun Microsystems - Beijing China ibss_node_p->used = 1;
654419d332feSfei feng - Sun Microsystems - Beijing China
654519d332feSfei feng - Sun Microsystems - Beijing China (void) memset(&ibss_node_p->node, 0,
654619d332feSfei feng - Sun Microsystems - Beijing China sizeof (iwk_add_sta_t));
654719d332feSfei feng - Sun Microsystems - Beijing China
654819d332feSfei feng - Sun Microsystems - Beijing China IEEE80211_ADDR_COPY(ibss_node_p->node.bssid, addr);
654919d332feSfei feng - Sun Microsystems - Beijing China ibss_node_p->node.id = index;
655019d332feSfei feng - Sun Microsystems - Beijing China ibss_node_p->node.control = 0;
655119d332feSfei feng - Sun Microsystems - Beijing China ibss_node_p->node.flags = 0;
655219d332feSfei feng - Sun Microsystems - Beijing China
655319d332feSfei feng - Sun Microsystems - Beijing China err = iwk_cmd(sc, REPLY_ADD_STA, &ibss_node_p->node,
655419d332feSfei feng - Sun Microsystems - Beijing China sizeof (iwk_add_sta_t), 1);
655519d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) {
655619d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_clean_add_node_ibss(): "
655719d332feSfei feng - Sun Microsystems - Beijing China "failed to add IBSS node\n");
655819d332feSfei feng - Sun Microsystems - Beijing China ibss_node_p->used = 0;
655919d332feSfei feng - Sun Microsystems - Beijing China (void) memset(&ibss_node_p->node, 0,
656019d332feSfei feng - Sun Microsystems - Beijing China sizeof (iwk_add_sta_t));
656119d332feSfei feng - Sun Microsystems - Beijing China return (err);
656219d332feSfei feng - Sun Microsystems - Beijing China }
656319d332feSfei feng - Sun Microsystems - Beijing China
656419d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.node_number++;
656519d332feSfei feng - Sun Microsystems - Beijing China
656619d332feSfei feng - Sun Microsystems - Beijing China (void) memset(&link_quality, 0, sizeof (link_quality));
656719d332feSfei feng - Sun Microsystems - Beijing China
656819d332feSfei feng - Sun Microsystems - Beijing China rs = ic->ic_sup_rates[ieee80211_chan2mode(ic,
656919d332feSfei feng - Sun Microsystems - Beijing China ic->ic_curchan)];
657019d332feSfei feng - Sun Microsystems - Beijing China
657119d332feSfei feng - Sun Microsystems - Beijing China for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
657219d332feSfei feng - Sun Microsystems - Beijing China if (i < rs.ir_nrates) {
657319d332feSfei feng - Sun Microsystems - Beijing China rate = rs.
657419d332feSfei feng - Sun Microsystems - Beijing China ir_rates[rs.ir_nrates - i];
657519d332feSfei feng - Sun Microsystems - Beijing China } else {
657619d332feSfei feng - Sun Microsystems - Beijing China rate = 2;
657719d332feSfei feng - Sun Microsystems - Beijing China }
657819d332feSfei feng - Sun Microsystems - Beijing China
657919d332feSfei feng - Sun Microsystems - Beijing China if (2 == rate || 4 == rate ||
658019d332feSfei feng - Sun Microsystems - Beijing China 11 == rate || 22 == rate) {
658119d332feSfei feng - Sun Microsystems - Beijing China masks |= RATE_MCS_CCK_MSK;
658219d332feSfei feng - Sun Microsystems - Beijing China }
658319d332feSfei feng - Sun Microsystems - Beijing China
658419d332feSfei feng - Sun Microsystems - Beijing China masks |= RATE_MCS_ANT_B_MSK;
658519d332feSfei feng - Sun Microsystems - Beijing China masks &= ~RATE_MCS_ANT_A_MSK;
658619d332feSfei feng - Sun Microsystems - Beijing China
658719d332feSfei feng - Sun Microsystems - Beijing China link_quality.rate_n_flags[i] =
6588b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(iwk_rate_to_plcp(rate) | masks);
658919d332feSfei feng - Sun Microsystems - Beijing China }
659019d332feSfei feng - Sun Microsystems - Beijing China
659119d332feSfei feng - Sun Microsystems - Beijing China link_quality.general_params.single_stream_ant_msk = 2;
659219d332feSfei feng - Sun Microsystems - Beijing China link_quality.general_params.dual_stream_ant_msk = 3;
659319d332feSfei feng - Sun Microsystems - Beijing China link_quality.agg_params.agg_dis_start_th = 3;
659419d332feSfei feng - Sun Microsystems - Beijing China link_quality.agg_params.agg_time_limit = LE_16(4000);
659519d332feSfei feng - Sun Microsystems - Beijing China link_quality.sta_id = ibss_node_p->node.id;
659619d332feSfei feng - Sun Microsystems - Beijing China
659719d332feSfei feng - Sun Microsystems - Beijing China err = iwk_cmd(sc, REPLY_TX_LINK_QUALITY_CMD,
659819d332feSfei feng - Sun Microsystems - Beijing China &link_quality, sizeof (link_quality), 1);
659919d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) {
660019d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_clean_add_node_ibss(): "
660119d332feSfei feng - Sun Microsystems - Beijing China "failed to set up TX link quality\n");
660219d332feSfei feng - Sun Microsystems - Beijing China ibss_node_p->used = 0;
660319d332feSfei feng - Sun Microsystems - Beijing China (void) memset(ibss_node_p->node.bssid, 0, 6);
660419d332feSfei feng - Sun Microsystems - Beijing China return (err);
660519d332feSfei feng - Sun Microsystems - Beijing China }
660619d332feSfei feng - Sun Microsystems - Beijing China
660719d332feSfei feng - Sun Microsystems - Beijing China *index2 = index;
660819d332feSfei feng - Sun Microsystems - Beijing China
660919d332feSfei feng - Sun Microsystems - Beijing China return (err);
661019d332feSfei feng - Sun Microsystems - Beijing China }
6611